First-Party Programs — Implementation Roadmap
- ADR-0042 — the program roster + the cart/baseline/program taxonomy (Decision-4: screen-router registers program ids; Decision-5: programs live in
runtime/programs/<name>/). - ADR-0046 — knEmacs is the application engine; programs are modes; build-then-extract (rule of three).
- ADR-0049 / ADR-0005 — the
launch-app/dossier-commit/dossier-has?FFI surface + the opaque:worldhandle. ../software/programs/enrichment-contract.md— lens / simulated-world / sanctioned-write contract.../software/programs/dossier-data-model.md— fact-node / edge schema a linkage commits as.../software/gameplay-framework.md— the connective gameplay map; the central World Engine.- The six v1 program specs:
conduit.md·kommander.md·ripsaw.md·keyring.md·kn9.md·bzbx.md(all merged via PR #53, GWP-623). - The two foundation tasks this roadmap depends on: GWP-626 (World Engine spec) · GWP-625 (ADR-0049 amendment — opaque live
:worldhandle + tick/event delivery).
0. Ground state (what is actually built today)
Section titled “0. Ground state (what is actually built today)”The roadmap is anchored on a real, working exemplar, not a green field. Before sequencing anything, here is the verified state of the tree on main:
- AmberCalc (#7) is fully built and wired.
runtime/programs/ambercalc/ambercalc.lspis a complete pure-Lisp system screen (grid, SES formula model, sort, GoTo, type-routing,:worldingestion via*launch-world*,dossier-commitexport). It ships a ctest (test_ambercalc) and a cross-context render test (test_blackledger_ambercalc_render). - The FFI seam exists and is bound.
nosh_lisp_bridge.cbindslaunch-app(Tier 1) +dossier-commit/dossier-has?(Tier 2);dossier.cimplements the store;recorder_drive.ccarries the world-carryinglaunch-apphook (--cart-dispatch). The ADR-0049 signatures are real C, not aspirational. - The screen router already reserves all 13 program ids.
screen_router.ck_programs[]maps every ADR-0042 id (conduit … knsalk) to a screen name, with aNULLactivation sexp for the not-yet-built ones; AmberCalc’s row carries"(ambercalc/load-world!)". Registering a new program is: author the screen module, add it to the router’sk_libsload list, and (if it needs a launch hook) fill in its activation sexp. This is not greenfield router work — it is filling reserved slots. - The knEmacs engine substrate is vendored and pulled.
runtime/vendor/kec-lisp/editor/carries52-mode.lsp(major-modes) and85-minibuffer.lsp(command-by-name) from kec-lisp ADR-0004 (KEC_REV 29af766) — but see the Phase-0 footgun in §6: they are NOT yet in the CMake embed manifest, so they are non-callable on-device today. - The demo recorder exists.
kn86rec(runtime/tools/kn86rec/) records both a cell-API--screenand a--cart-dispatchflow into a real-screen GIF (GWP-605/610). This is the QA-demo tool every slice’s exit criterion uses.
The build/test matrix is green in-tree (runtime 120+ ctests). The build pattern, the FFI, the router, and the recorder are all proven by AmberCalc — this wave is “do it five more times, on the engine, and extract the shared library when the consumers line up.”
1. The phased roadmap
Section titled “1. The phased roadmap”Phase 0 · Foundation — gates LIVE behavior
Section titled “Phase 0 · Foundation — gates LIVE behavior”Goal. Stand up the substrate that live-world programs need: the central World Engine, the opaque live :world handle + tick delivery, the screen-router activation wiring, and the kec-lisp editor-module embed manifest. Phase 0 does not gate static/cold-case programs (see the cleavage in §2) — a cold-case RIPSAW reads a frozen world region and needs none of the live machinery.
Work items.
- World Engine implementation [spec = GWP-626]. The central generator:
seed + cart-archetype → the single shared mission world-region(one coherent generated world per mission instance, perenrichment-contract.md§4 — one region, not one per program). The world is the union of the per-program slices (bzbx’s WIRE layer, RIPSAW’s RELATIONSHIP layer, AmberCalc’s table, etc.), coherent across them (the host bzbx finds is owned by the entity RIPSAW maps). Includes:- the World Clock — hybrid: move-driven by default (a tick is a move/budget unit on cold cases), cart wall-clock heat where a cart opts in (per the move-driven vs heat note in MEMORY / the program specs’ “tick-aware” sections);
- the typed-event bus — clock events (
node-online,new-filing,stream-appears) the live programs subscribe to and render live.
- The opaque live
:worldhandle + tick delivery [spec = GWP-625, ADR-0049 amendment]. Promote the AmberCalc-era*launch-world*snapshot-binding into the opaque, GC-rooted, mission-instance-scopedFE_TPTRhandle ADR-0049 §2 already specifies as the contract, plus the live read path: program-side accessors that see mission-state changes (a node revealed stays revealed) and the tick/event delivery onto a live handle.:invalid-worldon a stale handle. This is the hard gate for every live-reveal behavior (bzbx → CONDUIT live reveal; RIPSAW live-case filings). - Screen-router activation wiring. For each program in this wave, fill its
k_programs[]slot: add the screen module to the router’sk_libsload list and supply its activation sexp (the(<prog>/load-world!)analogue of AmberCalc’s row). The ids are already reserved — this is completion, not new registration. (Per-program; lands incrementally with each program, but the wiring mechanism is validated once here against a first non-AmberCalc program.) - kec-lisp editor-module embed-manifest wiring (the footgun — see §6). Add
52-mode.lsp(major-modes) and85-minibuffer.lsp(command-by-name) — and any other editor modules the modes call — to theKEC_EDITOR_SRCSlist inruntime/CMakeLists.txt, and confirm theKN86_NEMACS_LIBintegration is on the build path the programs link. Without this,define-major-modeandcompleting-readare silently unbound on-device even though the files are vendored.
Exit criteria.
- A World Engine ctest:
seed + archetype → a world regionis deterministic and coherent across at least two program slices (e.g. a host in the WIRE layer is owned by an entity in the RELATIONSHIP layer). - A live-handle ctest: a handle survives a mission-state mutation (revealed-stays-revealed), delivers a tick event, and raises
:invalid-worldafter a mission-instance reset. - A router ctest: a non-AmberCalc program id activates its registered screen through the live router path (the
test_screen_routersurface). define-major-modeandcompleting-readresolve in the System-tier context a program loads into (an embed-manifest smoke test), proving the editor tier is callable.
Phase 0 is partly parallelizable with Phase 1. Items 1–2 (World Engine + live handle) are the long pole and gate Phase 2, not Phase 1. Item 4 (embed manifest) gates every mode-based program including cold-case RIPSAW, so it is the true critical-path Phase-0 item and must land first. See §2/§3.
Phase 1 · First vertical slice — RIPSAW (cold-case / static world)
Section titled “Phase 1 · First vertical slice — RIPSAW (cold-case / static world)”Goal. Build the first non-AmberCalc program end-to-end as a knEmacs major-mode, on a static world it does not need the live handle for — proving the program-as-mode construction model and the slice checklist (§5), and producing the first consumer-side half of the shared tabulated-list library.
Why RIPSAW, why static. RIPSAW’s own spec is explicit: “the cold-case (v1 Black Ledger) path is static and works today”; only live-case org events (a filing appearing mid-mission) depend on the opaque live handle. So RIPSAW can read a frozen world region (materialized once at launch, no ticks) and proceed in parallel with Phase-0 items 1–2. It only needs the embed manifest (Phase-0 item 4) and the static slice of the World Engine’s RELATIONSHIP layer (a generated org graph with no clock).
Work items.
ripsaw-modeskeleton —runtime/programs/ripsaw/, adefine-major-modeon the engine, dual-panel (foldable org/directory tree via the engine tree-cursor CAR/CDR/BACK + an entity-detail/linkage panel). Registered viadeck/register-screen+ the router slot (Phase-0 item 3 mechanism).- The org/entity-graph world-schema — the
entity/edge/directory-nodenode types from the RIPSAW spec, materialized lazily over the static RELATIONSHIP slice.:hidden?edges are the clues; the visible skeleton is the haystack. - The generic verb floor — QUERY (minibuffer
completing-readover entity names/attrs — the EUDC narrowing), EXPAND/COLLAPSE, descend/ascend, INSPECT, FOLLOW (mgr→report, owner→account), COMMIT-to-DOSSIER. Ships bare-launchable. - DOSSIER wiring —
dossier-commitlinkage facts (org:<id>:employs:<person>,acct:<id>:owns,corp:<id>:controls:<shell>,org:<id>:shell-links) with confidence-by-recon-depth;dossier-has?gates (a previously-mapped org pre-seeds the tree). Uses the bound bridge primitives from §0 — no new FFI. - Extract the shared
tabulated-listlibrary — RIPSAW’s entity-attribute/linkage detail panel is atabulated-list. Build it inside RIPSAW first (design-for-extraction: keep the generic half behind a seam), do not pre-extract. (See §2 for the consumer-order correction — RIPSAW is not the first consumer; bzbx is. The rule-of-three extraction triggers in Phase 2, not here. RIPSAW builds its own table behind a seam so Phase 2 can harvest it.) - ctest — headless tests for the tree-cursor navigation, QUERY narrowing, FOLLOW-the-hidden-edge, and
dossier-commit/dossier-has?round-trip, on thetest_ambercalc/test_screen_routerlink surface (no new C — pure-Lisp program). - QA demo GIF — a real-screen
kn86recrecording (the cold-case Black Ledger RIPSAW recon: PROFILE filings → shell links → name a beneficiary → commit).
Exit criteria.
- RIPSAW loads bare (deck’s own DOSSIER directory as the “org of one”), and enriched (a static generated org graph via
:world). - The full verb floor is exercised by ctest; a hidden ownership edge is FOLLOWed and committed; a
dossier-has?pre-seed de-risks a second launch. - A
kn86recGIF of the cold-case recon flow is attached to the story. - RIPSAW’s
tabulated-listlives behind a seam, ready to be the harvest target in Phase 2.
Phase 2 · Remaining programs (bzbx, CONDUIT, Kommander, kn9, Keyring)
Section titled “Phase 2 · Remaining programs (bzbx, CONDUIT, Kommander, kn9, Keyring)”Goal. Build the remaining five, each a mode + world-schema + verb floor + DOSSIER + tests + demo GIF (§5). Extract the shared tabulated-list / feed library when the consumer count justifies it. bzbx requires the live handle (Phase-0 items 1–2 complete) for its live reveal; the others can use static or live worlds per their specs.
Work items (per program — each is a full §5 vertical slice).
- bzbx (
bzbx-mode, SPLIT: engine primary + optional deferred cell-API capture waterfall). World = the WIRE layer (host/port/service/link/dns/stream). Verb floor: PING/PROBE, TRACEROUTE, RESOLVE, FETCH, CONNECT, CAPTURE-VIEW. The capture viewer is thetop-styletabulated-list— bzbx is consumer #1 of that table. Live-handle dependent: the bzbx → CONDUIT live reveal (a host revealed in the run-region mid-mission, before it’s a DOSSIER fact) needs the opaque live handle. The durable-key path (commit:reachable, CONDUIT gates on it) works without it, but the live reveal is the headline interaction — so bzbx is gated on Phase-0 items 1–2. - CONDUIT (
conduit-mode, clean knEmacs mode, comint/shell-mode lineage). A session is a buffer (scrollback + input line). Gates on bzbx’s revealed/:reachablehost. Contributes the comint / session-buffer generic half (extract when the second comint consumer arrives — bzbx’s applet output is that consumer). - Kinoshita Kommander (
kommander-mode, clean knEmacs mode, Dired×2 / Sunrise lineage). Twotabulated-listpanels (name/size/mtime/tags), MARK + verb (COPY/MOVE/DELETE), clone-to-passive-pane, AVFS-into-archives, open-terminal-into-dir =(launch-app :conduit …). Anothertabulated-listconsumer. - kn9 (
kn9-mode, clean knEmacs mode, Gnus/Mutt lineage). Group buffer (tabulated-list) + thread tree (tree-cursor) + message buffer. The group buffer is identical in shape to the Mission Board feed — kn9 + Mission Board are the feed-engine pair. - Keyring (
keyring-mode, SPLIT: engine primary + thin cell-API crack output animation). Key MANAGEMENT is atabulated-list(id/kind/owner/state) + INSPECT detail; CRACK input is grammar (select lock + method + EVAL), only the crack OUTPUT is animated. Anothertabulated-listconsumer. CIPHER narration → OLED only.
Shared-library extraction (the rule-of-three trigger).
tabulated-listhas five consumers across this wave (bzbx #1, RIPSAW #2, kn9 #3, Kommander #4, Keyring #5). Per ADR-0046 build-then-extract: each program builds its own table behind a seam first; extract the sharedtabulated-listlibrary when the 2nd/3rd consumer lands (i.e. after bzbx + RIPSAW, confirmed by kn9). Do not pre-build the generic table.- The feed engine (Mission Board + kn9, same
tabulated-listshape) is the feed-reader specialization of that table — extract it once the table library exists and kn9’s group buffer + the Mission Board feed are the two confirmed consumers. - comint (CONDUIT + bzbx applet output) is a separate extraction on the same discipline.
Exit criteria.
- Each of the five programs: loads bare + enriched, full verb floor under ctest, DOSSIER round-trip, a
kn86recGIF. - The bzbx → CONDUIT live reveal is demonstrated (a host revealed mid-run in bzbx is openable in CONDUIT before it is a durable DOSSIER fact) — proving the live handle end-to-end.
- The shared
tabulated-listlibrary is extracted and ≥3 programs consume it (the rule of three is satisfied, not speculatively pre-built). - The feed engine backs both kn9 and the Mission Board.
Phase 3 · Cross-program threading
Section titled “Phase 3 · Cross-program threading”Goal. Wire the campaign threads that span programs, and prove one worked multi-program mission end-to-end.
Work items.
- Campaign threads.
- bzbx → Keyring → CONDUIT → Kommander — bzbx sniffs a credential fragment that de-risks a Keyring crack; the cracked key pre-auths a CONDUIT session on a bzbx-revealed host; Kommander stages exfil off that session (
open-terminal-into-dirhandoff in reverse). - RIPSAW → AmberCalc → DOSSIER — RIPSAW follows a hidden ownership edge to an account; the account hands off to AmberCalc (the spreadsheet lens); the audit finding commits to DOSSIER. (AmberCalc is already built — this thread is wiring, not a new program.)
- bzbx → Keyring → CONDUIT → Kommander — bzbx sniffs a credential fragment that de-risks a Keyring crack; the cracked key pre-auths a CONDUIT session on a bzbx-revealed host; Kommander stages exfil off that session (
- Cross-mission
dossier-has?gating — a key committed in one mission de-risks or hard-gates an objective in a later mission (the recon → knowledge bridge made load-bearing across mission instances). - One worked multi-program mission — a single contract that requires ≥3 programs in sequence, with the World Engine’s coherence (one host, owned by one entity, holding one account) visible across the bzbx/RIPSAW/AmberCalc slices, demonstrated as a
kn86recwalkthrough.
Exit criteria.
- Both campaign threads run end-to-end on a generated world.
- A cross-mission
dossier-has?gate is shown to block, then unblock after the prerequisite recon. - A multi-program mission GIF demonstrates the coherent shared world across program handoffs.
2. Dependency graph
Section titled “2. Dependency graph”The load-bearing cleavages:
- Static-world vs live-world. Programs that read a frozen world region (materialized once at launch, no ticks) need only the embed manifest + a static World Engine slice — they can start before the live handle. Programs whose headline interaction is a live reveal (a node revealed mid-run, a tick event rendered) are gated on the opaque live handle (Phase-0 items 1–2). Cold-case RIPSAW = static → Phase 1, parallel with Phase 0. bzbx’s live reveal = live → Phase 2, after the handle.
tabulated-list/ feed extraction timing (rule of three). Build the table inside the first consumer, extract at the 2nd/3rd. bzbx is consumer #1, RIPSAW #2, kn9 #3. Extraction triggers in Phase 2 — RIPSAW (Phase 1) builds its table behind a seam but does not extract.
graph TD
subgraph P0["Phase 0 · Foundation"]
EM["embed-manifest wiring<br/>(52-mode + 85-minibuffer → KEC_EDITOR_SRCS)"]
WE["World Engine<br/>(GWP-626): generator + World Clock + event bus"]
LH["opaque live :world handle + tick delivery<br/>(GWP-625, ADR-0049 amendment)"]
RW["router activation wiring<br/>(fill reserved k_programs slots)"]
end
subgraph EX["Built exemplar (on main)"]
AC["AmberCalc #7<br/>+ launch-app/dossier-commit/dossier-has? bound<br/>+ kn86rec recorder"]
end
subgraph P1["Phase 1 · RIPSAW (STATIC / cold-case)"]
RIP["ripsaw-mode + org-graph schema + verb floor<br/>+ DOSSIER wiring + table-behind-a-seam"]
end
subgraph P2["Phase 2 · remaining five"]
BZ["bzbx (LIVE reveal) — table consumer #1"]
CO["CONDUIT (static-ok) — comint core"]
KM["Kommander (static-ok) — table consumer #4"]
K9["kn9 (static-ok) — table #3 + feed pair"]
KR["Keyring (split) — table consumer #5"]
TL["EXTRACT shared tabulated-list lib<br/>(rule of three: bzbx + RIPSAW + kn9)"]
FE["EXTRACT feed engine<br/>(kn9 + Mission Board)"]
end
subgraph P3["Phase 3 · cross-program threading"]
TH["campaign threads + cross-mission gating<br/>+ one worked multi-program mission"]
end
AC -. proves build pattern / FFI / router / recorder .-> P1
AC -. proves build pattern .-> P2
EM --> RIP
WE -->|static slice| RIP
RW --> RIP
EM --> BZ
EM --> CO
EM --> KM
EM --> K9
EM --> KR
WE --> BZ
LH -->|live reveal HARD-GATES| BZ
WE -. static slice ok .-> CO
WE -. static slice ok .-> KM
WE -. static slice ok .-> K9
BZ -->|revealed host| CO
RIP -. table behind seam .-> TL
BZ --> TL
K9 --> TL
TL --> FE
K9 --> FE
RIP --> TH
BZ --> TH
CO --> TH
KM --> TH
K9 --> TH
KR --> TH
AC --> TH
LH --> TH
3. Recommended build order + parallelization
Section titled “3. Recommended build order + parallelization”Critical path: embed manifest → RIPSAW slice → (World Engine + live handle) → bzbx → CONDUIT → cross-program threading.
| Order | Work | Can run concurrently with | Gated by |
|---|---|---|---|
| 1 | Phase-0 item 4 (embed manifest) | nothing — do first | — |
| 2a | Phase 1 RIPSAW (static) | 2b (World Engine + live handle) | embed manifest only |
| 2b | Phase-0 items 1–2 (World Engine + live handle) | 2a (RIPSAW) | embed manifest (for any mode smoke test) |
| 3a | bzbx | 3b (CONDUIT/Kommander/kn9 static portions) | live handle (2b) |
| 3b | CONDUIT, Kommander, kn9, Keyring (static slices) | 3a (bzbx), each other | embed manifest + World Engine static slices |
| 4 | Extract tabulated-list + feed + comint libs | — | bzbx + RIPSAW + kn9 (rule of three) |
| 5 | Phase 3 threading | — | all programs in the thread + live handle |
The key parallelization win: RIPSAW (cold-case, static) and the World Engine + live-handle foundation run concurrently. RIPSAW proves the program-as-mode model and the slice checklist on a static world while the long-pole live machinery is built beside it; bzbx (the first live-reveal program) then lands on a proven slice pattern and a finished live handle. Phase 0’s only hard pre-req for RIPSAW is the embed manifest.
Validation of the RIPSAW-first call — CONFIRMED
Section titled “Validation of the RIPSAW-first call — CONFIRMED”RIPSAW-first is the right call. Reasoning:
- It is the cleanest static program with a real cart behind it. Cold-case Black Ledger gives RIPSAW a concrete, already-designed world (the shell-company org graph) and a concrete demo (PROFILE → shell links → name the beneficiary). It needs zero live machinery — its spec says the cold-case path “works today.” That lets the first non-AmberCalc slice prove the construction model (mode skeleton, verb floor, DOSSIER wiring, slice checklist) without waiting on the World Engine + live handle long pole.
- It exercises the most engine surface of any single program. RIPSAW uses the tree-cursor (CAR/CDR/BACK + fold),
completing-read(EUDC QUERY), ANDtabulated-list(the detail panel). Proving all three on one program de-risks the engine substrate for the entire wave — if the embed manifest or the engine tier is wrong, RIPSAW surfaces it first and loudly. - It is the natural design-for-extraction seed for the shared table. RIPSAW is
tabulated-listconsumer #2; building its table behind a seam (without extracting) sets up the rule-of-three harvest in Phase 2 cleanly. - It pairs with an already-built neighbor. The RIPSAW → AmberCalc → DOSSIER thread reuses the one program already shipped. Building RIPSAW first means the first cross-program thread (Phase 3) is RIPSAW + AmberCalc — two done programs — not two new ones.
One refinement (not a counter): the prompt skeleton calls RIPSAW “the first consumer” of tabulated-list. Per the merged specs, bzbx is consumer #1; RIPSAW is #2. This does not change the RIPSAW-first build order (bzbx is gated on the live handle and must come later), but the roadmap should — and does — say RIPSAW builds its table behind a seam without extracting, and the extraction triggers in Phase 2 once bzbx + RIPSAW + kn9 are the confirmed three. Treating RIPSAW as “the program that designs the table for extraction” rather than “the first consumer” keeps the rule-of-three honest.
4. Risks & open questions
Section titled “4. Risks & open questions”- The embed-manifest footgun (highest-confidence, do-first).
52-mode.lspand85-minibuffer.lspare vendored underruntime/vendor/kec-lisp/editor/but are not in theKEC_EDITOR_SRCSCMake list today, andKN86_NEMACS_LIBdefaultsOFF. A program callingdefine-major-modeorcompleting-readwill fail with “unbound symbol” on-device even though the file is present and CI may stay green if no test exercises it. Mitigation: Phase-0 item 4 lands first, with an embed-manifest smoke test that callsdefine-major-mode+completing-readin the program’s System-tier context. Re-check on every kec-lisp sync (per MEMORY: KEC_CORE_SRCS / editor manifest is duplicated across CMakeLists and is curated for the arena). - The live-handle ADR-0049 amendment (GWP-625) is a hard gate for Phase-2 bzbx. bzbx’s headline interaction — the live bzbx → CONDUIT reveal — cannot ship until the opaque live handle + tick delivery exist. The AmberCalc-era
*launch-world*is a snapshot binding, not the live, mission-scoped, mutation-visible handle ADR-0049 §2 describes. If GWP-625 slips, bzbx’s live reveal slips with it (the durable-key fallback still works, but it is not the designed experience). Mitigation: start GWP-625 + GWP-626 concurrently with RIPSAW so the handle is ready when bzbx starts; keep bzbx’s durable-key path as the de-risked floor. - Per-cart save vs. run-state confusion. The world region is run-state (resets at the mission-instance boundary; a stale handle raises
:invalid-world); DOSSIER facts are durable (sanctioned-write, cross-mission). The danger is a program treating a:worldread as durable or trying to raw-write DOSSIER. Mitigation: the slice checklist (§5) makes “durable consequence only viadossier-commit, never a raw write;:worldreads are never persisted” an explicit gate; the live-handle ctest asserts:invalid-worldafter reset. - World Engine coherence is unspecified detail (GWP-626 owns it). The per-program world schemas (the exact node shapes for WIRE / RELATIONSHIP / table / filesystem) are per-program design; the World Engine must generate them coherently (one host owned by one entity holding one account). If the generator produces incoherent slices, the cross-program threads (Phase 3) break. Mitigation: the Phase-0 exit criterion requires a coherence ctest across ≥2 slices before any Phase-2 program reads a generated world.
tabulated-listpremature extraction. The temptation is to build a generic table first (speculative generality — exactly Option C that ADR-0046 rejected). Mitigation: the roadmap forces build-behind-a-seam in RIPSAW + bzbx, extract only at the confirmed third consumer (kn9). No generic table before two real consumers exist.- Host CMake duplication (per MEMORY). Pure-Lisp programs (the common case here, like AmberCalc) need no host CMakeLists touch. But any program that adds a
runtime/src/*.cTU referenced by a host-linked target must add it to bothhosts/emulatorandhosts/deviceNOSH_SRCSor the hosts fail to link while runtime CI stays green. Mitigation: prefer pure-Lisp programs (the engine-mode model makes this the default); flag any C-seam addition for the dual-host-CMake check.
5. Definition of a program vertical slice (the repeatable checklist)
Section titled “5. Definition of a program vertical slice (the repeatable checklist)”Every program in this wave follows the same slice, generalized from the built AmberCalc exemplar. A slice is “done” when all six gates pass:
- Mode skeleton —
runtime/programs/<name>/<name>.lsp, adefine-major-mode(<name>-mode) on the knEmacs engine, registered viadeck/register-screen+ itsk_programs[]router slot (anddeck/register-charif it is a composer screen). Bare-launchable. Side of the ADR-0046 scope line declared (clean engine mode, or SPLIT with a thin/optional cell-API passenger). - World-schema — the program’s slice of the World Engine’s world region (its node/edge types), read through
:world— lazily materialized, static or live per the program’s spec. Bare-launch (no:world) degrades to the program’s honest default world (never raises — enrich-never-gate). - Verb floor — the generic, bare-launchable verb set from the program’s spec, wired to the engine substrate: tree-cursor navigation,
completing-readfor command-/query-by-name, and the program’s domain verbs. Carts overlay domain verbs on top; the floor ships without a cart. - DOSSIER wiring — durable findings emitted only through
(dossier-commit <key>)(sanctioned; never a raw write), with confidence-by-recon-depth; gates read via(dossier-has? <key> &key min-conf).:worldreads are never persisted; the only durable consequence is the committed fact. - Tests — headless ctest on the
test_ambercalc/test_screen_routerlink surface (pure-Lisp programs need no new C): verb-floor exercise, navigation, DOSSIER round-trip, bare-vs-enriched launch, and (for live programs) the live-handle reveal +:invalid-world-after-reset assertion. - Demo GIF — a real-screen
kn86recrecording of the program’s headline flow (the QA-demo gate every KN-86 code story ends on — GWP-605), attached to the story; the task goes to Review, not Done.
6. The embed-manifest call-out (Phase-0, restated for emphasis)
Section titled “6. The embed-manifest call-out (Phase-0, restated for emphasis)”Because this is the single most likely silent failure in the whole wave, it is restated as its own section. The kec-lisp editor tier is vendored but not fully embedded:
- Present in
runtime/vendor/kec-lisp/editor/:52-mode.lsp,85-minibuffer.lsp(the major-mode + command-by-name substrate ADR-0046 designates as the engine). - Missing from
KEC_EDITOR_SRCSinruntime/CMakeLists.txt— sokec_mkembednever bakes them into the embed header, and the symbols are non-callable on-device despite the files existing on disk. KN86_NEMACS_LIBdefaultsOFF.
Phase-0 item 4 is: add the mode + minibuffer modules (and any editor modules they transitively require) to the embed manifest, confirm the build path the programs link has them, and add a smoke test that calls define-major-mode and completing-read so the gap can never reappear silently. Per MEMORY, the embed manifest is duplicated across multiple CMakeLists and curated for the 32 KB arena — re-verify on every kec-lisp sync. No program in this wave is buildable until this lands.