Skip to content

Cipher Voice — Post-v0.1 Integration Plan

  • docs/architecture/adr/ADR-0015-cipher-line-auxiliary-display.md — authoritative hardware + FFI decision.
  • docs/architecture/KN-86-CIPHER-LINE-Grammar-Framework.md — authoritative engine spec (event stream, memory store, five modes, mode selector, grammar s-exp, coherence stack, NoshAPI primitives).
  • docs/architecture/KN-86-Capability-Model-Spec.md — Cipher Voice section + Universal Deck State schema.
  • CLAUDE.md Canonical Hardware Specification — CIPHER-LINE hardware values; Spec Hygiene Rule 6 (OLED-exclusive with one sanctioned Null exception).
  • docs/plans/post-v0.1/2026-04-21-mission-board.md — companion plan this doc wires into.
  • docs/plans/post-v0.1/2026-04-21-dev-repl.md, 2026-04-21-nemacs.md — companion plans for REPL and editor wiring.
  • Predecessor: docs/_archive/plans/post-v0.1/2026-04-21-cipher-voice.md — archived v1 (pre-ADR-0015 grammar engine design, superseded 2026-04-24). Retained as design history only.

Hardware spec: See CLAUDE.md Canonical Hardware Specification. This plan does not restate CIPHER-LINE row geometry, panel size, or font values — consult the Grammar Framework §2 and CLAUDE.md for those.


This is a post-v0.1 planning document for the cross-capability integration work that follows once ADR-0015 lands its firmware bring-up (F1–F7 in the ADR) and the CIPHER-LINE Grammar Framework’s engine ships.

It is NOT:

  • A grammar engine spec. That’s docs/architecture/KN-86-CIPHER-LINE-Grammar-Framework.md.
  • A hardware or FFI spec. That’s ADR-0015.
  • An architectural decision. The architecture is decided.

This plan answers a narrower question: once the Cipher voice is rendering on CIPHER-LINE per the Grammar Framework, what integration work is queued across Mission Board, the dev REPL, nEmacs, and companion subsystems? Each section below is a PR-sized slice of work with acceptance criteria, scoped to agents who own those surfaces.

The archived v1 of this doc (now at docs/_archive/plans/post-v0.1/2026-04-21-cipher-voice.md) spent most of its pages designing the grammar engine on the assumption Cipher rendered on the 80×25 main grid across five zones. That engine design is superseded; the Grammar Framework is the authoritative replacement. The genuinely still-useful content in v1 was the cross-capability integration thinking — that is what this v2 preserves and cleans up.


1. Scope boundary — firmware, cartridges, and this plan

Section titled “1. Scope boundary — firmware, cartridges, and this plan”

Before delegating integration work to other subsystems, we restate the boundary ADR-0015 and the Grammar Framework already enforce. This plan NEVER revisits these — it only wires them to companion subsystems.

Firmware (nOSh) owns — already specified, do not re-design:

  • The Cipher engine (event stream, memory store, five modes, mode selector, grammar expansion, coherence stack). See Grammar Framework §§3–9.
  • CIPHER-LINE rendering (the 4-row OLED surface — Row 1 status strip, Rows 2–3 Cipher scrollback, Row 4 contextual). See ADR-0015 §2 and Grammar Framework §2.
  • The NoshAPI FFI (cipher-emit, cipher-push-event, cipher-extend-grammar, cipher-set-mode-weights, aux-* family). See Grammar Framework §11 (authoritative signatures) and ADR-0015 §4 (eight new primitives, NoshAPI 54 → 62).
  • The cart-capabilities allowlist that gates Null’s cipher-main-grid-escape. See ADR-0015 §3a.
  • Universal Deck State fields for Cipher: coherence_stack (50 B), event_ring (1280 B), cipher_mode_weights (4 B), plus the existing cipher_seed[4] LFSR. See ADR-0015 §6 and Grammar Framework §9.

Cartridges own — already specified:

  • Their cipher-grammar block in the .kn86 container (vocabulary pools, production fragments, new non-terminals, mode biases, style deltas, event-type registrations, cart-scoped affect tags). See Grammar Framework §10.
  • Pushing events via cipher-push-event. See Grammar Framework §11.
  • Null uniquely: main-grid Cipher passages via cipher-emit-main-grid, authorized by the cipher-main-grid-escape capability. See ADR-0015 §3a and Grammar Framework §2 (sanctioned exception).

This plan owns — the integration surface:

  • Wiring Mission Board events into the Cipher event stream (Section 2).
  • Wiring the dev REPL’s read-only introspection + tutorial hooks (Section 3).
  • Wiring nEmacs’s predictive palette and editing-session ambient behavior (Section 4).
  • Tracking cross-cutting follow-ups that don’t belong to any single agent (Section 5).
  • Open questions that need Josh’s disposition before work begins (Section 6).

No new Cipher engine design decisions live here. If you find yourself proposing one, stop — it belongs in an ADR or in the Grammar Framework, not in a post-v0.1 plan.


Companion plan: docs/plans/post-v0.1/2026-04-21-mission-board.md §Cross-capability hooks → Cipher voice.

The Mission Board is the highest-traffic Cipher consumer. Per ADR-0015, Cipher no longer renders on the MISSIONS tab — there is no Row 20–22 commentary strip, no per-contract annotation block on the main grid. Instead, mission board events push into the Cipher event stream; the nOSh runtime generator decides when and how to speak on CIPHER-LINE Rows 2–3.

The mission-board plan already emits these events on the nOSh topic bus. This plan commits them into the Cipher engine’s event stream via cipher-push-event from the nOSh runtime side (Cipher’s events are firmware-pushed, tagged :firmware; the Grammar Framework §3 baseline event types accommodate all of these without extension).

Mission-board eventCipher event typeDefault affectBeat transition
mission_board_refreshed:observation:routine— (beat stays)
mission_highlight_changed:observation:routine
mission_bid:action:routine
mission_accepted:mission-start:routinenOSh runtime sets beat to :mission-brief
mission_required_cartridge_missing:anomaly:anomalous
mission_suspended_resume_available:phase-advance:significantnOSh runtime sets beat to :phase-transition
Mission Board entry (first tab switch per power cycle):observation:routinenOSh runtime sets beat to :bare-deck:mission-brief

Cipher will often be silent in response (silent mode is first-class per Grammar Framework §5.5). That is correct; it matches the cockpit-voice-recorder aesthetic §1 of the Grammar Framework codifies. The operator does not need Cipher to narrate every board-refresh tick.

  • GWP-TBD (Firmware, post-ADR-0015 bring-up) — Wire Mission Board event bus into cipher-push-event with the mapping above. Acceptance: Mission Board events show up in the Cipher event stream debug overlay (F12) with correct :type / :affect / :tag=:firmware. Cipher engine consumes them; CIPHER-LINE Rows 2–3 respond according to the Grammar Framework’s mode selector. No main-grid Cipher rendering anywhere.
  • GWP-TBD (Gameplay Design) — Author a small nOSh-baseline cipher-grammar extension for mission-flavored vocabulary (:subject, :object, :verb-present entries for contracts, threats, payouts) so that Mission Board events produce readable fragments even without a domain cartridge loaded. Lives in the nOSh baseline grammar, not in any cartridge. Acceptance: with no cart inserted, a mission_highlight_changed tick renders a comprehensible fragment like contract. waiting. rather than a bare slot fallback.
  • GWP-TBD (QA) — Golden-file regression. Given a fixed Mission Board event sequence and a fixed cipher_seed, the CIPHER-LINE output must be deterministic per Grammar Framework §6 Determinism. Test matrix: at least one sequence covering board refresh, highlight change, bid, accept, and the resume path.
  • Cipher commentary on specific contracts (threat-bracket flavor, payout-tier flavor, domain-tag flavor). That flavor is captured in the Grammar Framework’s mode selector biases and in each cartridge’s cipher-grammar block, not in the integration plan.
  • Any notion of a Mission Board “Cipher annotation rail” on the main grid. That is retired per ADR-0015.

Companion plan: docs/plans/post-v0.1/2026-04-21-dev-repl.md.

The dev REPL (ADR-0002) gives the operator a player-facing Lisp shell with read-only NoshAPI access. For Cipher, the REPL is an inspection and teaching surface — never a mutation surface without explicit operator consent.

The Grammar Framework’s NoshAPI primitives (§11) already exist. The REPL exposes a small read-only subset for introspection.

REPL primitiveDelegates toMutation?Purpose
(cipher-stack-head N)Grammar Framework §9 Stack OperationsNoRead last N coherence-stack entries. Null uses the same primitive for its Cipher Analysis subpanel.
(cipher-memory-peek)Read-only snapshot of memory-store stateNoReturns a list of current memory-store entries (event-type, tag, approximate age, current weight). For tutorial and debug only.
(cipher-beat)Read-only access to current firmware beatNoReturns the current beat keyword (:bare-deck, :active-hack, etc.) so operators can see what mode-selector distribution is active.
(cipher-sample passage-hint)Scratch LFSR variantNoPreview what Cipher might say next tick without consuming the real seed. Uses a scratch LFSR derived from cipher_seed. Tutorial-friendly.

Explicitly NOT exposed to the REPL:

  • cipher-emit (writes CIPHER-LINE; mutation).
  • cipher-push-event (mutates event stream; writeable only from the active cart or nOSh runtime subsystems, not from the REPL, to prevent tutorial programs from rewriting Cipher’s memory).
  • cipher-extend-grammar, cipher-set-mode-weights (mutate live grammar / bias tables).
  • Any aux-* primitive that takes a row. The REPL doesn’t get to paint CIPHER-LINE.

The first-boot REPL tutorial (ADR-0002) gains a three-step Cipher lesson:

  1. (cipher-beat) — observe that the engine has a context.
  2. (cipher-stack-head 3) — observe the last three things Cipher said (or silence markers).
  3. (cipher-sample :observe) — preview an observation without consuming the seed.

The lesson teaches read-vs-mutate as a concept; Cipher is a natural teaching case because cipher-sample and cipher-emit are visibly different verbs on the same voice.

  • GWP-TBD (Firmware) — Implement the four REPL-scoped read primitives above. Acceptance: calling any of them from the REPL returns a well-formed value and does NOT advance cipher_seed, push into the event stream, or push into the coherence stack.
  • GWP-TBD (Gameplay Design) — Author the three-step tutorial lesson. Acceptance: first-boot operators see the lesson, complete it without any Cipher state mutation, and the post-lesson cipher_seed equals the pre-lesson cipher_seed.
  • GWP-TBD (QA) — Tutorial regression. The lesson must be idempotent against cipher_seed, coherence_stack, memory_store — run it, run it again, the state is bit-identical.

Companion plan: docs/plans/post-v0.1/2026-04-21-nemacs.md.

nEmacs (ADR-0008) is the structural editor. Its predictive palette uses cartridge vocabulary the same way Cipher does — this is a shared-data opportunity, not a duplication.

ADR-0008 boosts predictive palette ranking for tokens in the currently-loaded cartridge’s vocabulary. The Grammar Framework §10 already defines vocabulary as part of the cipher-grammar block. nEmacs and the Cipher engine consume the same vocabulary frame — the cart’s cipher-grammar :vocabulary pools.

Concretely, the nOSh runtime publishes a vocab_frame_updated event on cart-load and cart-eject. Both Cipher and nEmacs subscribe. This keeps them in lockstep — whatever words a cartridge teaches the editor are the same words Cipher might speak.

This is not a new design decision (the Grammar Framework already makes vocabulary data, not code). It is a statement that the integration is free if we wire it correctly, and a reminder not to create a second vocabulary table for nEmacs.

There is no ambient Cipher whisper on the main grid inside nEmacs. Per Spec Hygiene Rule 6, Cipher does not render glyphs on the 80×25 main grid (the one sanctioned exception is Null’s escape — nEmacs is not Null). Any ambient Cipher behavior during editing sessions happens on CIPHER-LINE, using the normal mode selector and the normal beat (editing sessions run against :bare-deck or :mission-brief, not a bespoke :editor-open beat).

If the experience with shipping v0.1 reveals that CIPHER-LINE goes too quiet during long editing sessions, the fix is a bias adjustment (push a per-cartridge :mode-biases entry for the active beat that raises drift slightly), not a new rendering zone.

  • GWP-TBD (Firmware) — Publish vocab_frame_updated on cart-load and cart-eject. Acceptance: nEmacs’s palette invalidates its cache on each event; Cipher’s active grammar refreshes on each event. Both consume the same vocab_frame_hash.
  • GWP-TBD (nEmacs agent) — Subscribe to vocab_frame_updated; use the emitted frame as the sole vocabulary source for palette ranking. Acceptance: when a cart swaps, nEmacs’s top-ranked palette entries change within one frame.
  • GWP-TBD (Playtest / QA) — Post-v0.1 telemetry or playtest observation: is CIPHER-LINE too quiet during extended editor sessions? If yes, file a small bias-tuning task; if no, do nothing. Do not preemptively add editor-specific beats.

5. Cross-cutting follow-ups (not owned by a single companion plan)

Section titled “5. Cross-cutting follow-ups (not owned by a single companion plan)”

These are items that don’t fit cleanly into Mission Board, REPL, or nEmacs plans but are in-scope for the Cipher voice area.

5.1 Legacy field names vs. Grammar Framework schema

Section titled “5.1 Legacy field names vs. Grammar Framework schema”

The predecessor v1 of this doc referenced a cipher_seed[4] LFSR as the single randomness source. The Grammar Framework §6 Computation and ADR-0015 §6 confirm this is still correct — cipher_seed[4] is the one LFSR, advanced per mode selection and per slot fill. The new event_ring (1280 B) and coherence_stack (~272 B reserved, 265 B used) and cipher_mode_weights (4 B) are additive fields, not a replacement. No work item — just a note so a future reader doesn’t think the LFSR model was displaced.

5.2 Null’s main-grid escape — tooling parity

Section titled “5.2 Null’s main-grid escape — tooling parity”

Null is the one cartridge authorized to render Cipher on the main grid (ADR-0015 §3a, Grammar Framework §2). The voice heuristic still applies: Null’s main-grid passages are chains of clipped fragments joined by punctuation and line breaks, not conversational sentences. This is an authoring discipline, not a runtime constraint — firmware will render whatever cipher-emit-main-grid is given.

  • GWP-TBD (QA) — Add a Null-specific voice-heuristic check to the gameplay-spec review pass. Any proposed Null main-grid passage must pass §1 of the Grammar Framework (under eight words per clause, drops articles/connectives, etc.) before it ships.

5.3 Debrief / phase-completion Cipher on CIPHER-LINE

Section titled “5.3 Debrief / phase-completion Cipher on CIPHER-LINE”

The phase-completion moment used to trigger a full-screen debrief modal with main-grid Cipher text. Per ADR-0015 it now fires as a standard event (:result-success or :result-failure) that produces a CIPHER-LINE utterance at whatever mode the selector picks — typically annotate or reflect under :debrief beat (Grammar Framework §6 beat table). There is no main-grid debrief modal for Cipher; whatever cartridge-side outcome UI a module wants post-phase is cartridge content on the main grid, Cipher commentary on CIPHER-LINE.

No work item — this is a restatement for the post-v0.1 reader who remembers the old debrief-modal design.

ADR-0015 follow-on F1 creates kn86-emulator/src/oled.c for the CIPHER-LINE SDL2 render surface. This plan depends on that landing before any of the above work items can be QA’d end-to-end on the emulator. Tracked in the ADR; not duplicated here.


Each of these blocks some sub-item above and needs Josh’s disposition (as PM) before the agent picks it up. None require re-opening ADR-0015 or the Grammar Framework.

  1. Should cipher-sample from the REPL be unrestricted, or gated by operator consent on first use? The primitive is read-only and doesn’t touch cipher_seed, so there’s no memory-rewrite risk. The concern is narrative spoilers — cipher-sample :reflect could surface a memory a first-time operator isn’t ready to see. Proposal: unrestricted; Cipher fragments are terse enough that spoilers are not a real risk. PM to confirm.

  2. Per-cartridge :mode-biases and :style-deltas authoring quality bar. Grammar Framework §10 caps biases at ±0.20 and deltas at ±64. But a cart that maxes out both on every beat will drown out the nOSh runtime-default voice. Do we need a QA checklist that flags a cart’s grammar block for review if it approaches the caps? Proposal: yes — QA agent adds “Cipher grammar balance” to the gameplay-spec Round 2 review pass. PM to confirm QA scope change.

  3. Cipher commentary on mission_required_cartridge_missing. Should the nOSh-baseline grammar include an “insert the module” fragment, or stay silent and let the main-grid error message carry the load? Proposal: baseline silent; modules that want a voice line on this event can register it via their own cipher-grammar. PM to confirm.

  4. Tutorial lesson order. The three-step REPL Cipher lesson §3.2 assumes it comes AFTER the operator has loaded at least one cartridge (so the coherence stack and memory store have content to introspect). Is that a hard sequencing constraint, or do we ship a “demo state” the tutorial injects into the memory store and coherence stack? Proposal: hard constraint — the tutorial is gated on “at least one cart has been loaded this session.” Gameplay Design agent to confirm with first-boot flow.

  5. Null-specific QA pass (§5.2). Does the Null gameplay spec’s current voice-heuristic compliance ship as-is, or does it need a revision pass against the Grammar Framework §1 heuristic before v0.1 closes? Proposal: a short Null-specific compliance review, same template as the other Round 2 reviews. PM to schedule with QA.


End of plan.