CIPHER-LINE Grammar — S-Expression Format
The wire grammar that produces CIPHER-LINE utterances. Cartridges contribute production fragments and vocabulary pools through a cipher-grammar block in the .kn86 container; the runtime ships a baseline grammar covering all five modes and the standard event types.
Related:
software/runtime/cipher-voice.md— the engine that executes this grammar (event stream, memory store, mode selector, coherence stack, style controls). The full Grammar Framework lives there; this doc is the contract-surface extract for implementers.adr/ADR-0015— the auxiliary OLED hardware + render budget the grammar produces text for.adr/ADR-0006— the.kn86container that shipscipher-grammarblocks.
1. Non-Terminals
Section titled “1. Non-Terminals”Non-terminals are symbols with a leading colon or written as bare symbols inside grammar blocks. By convention:
- Slot-filling non-terminals (pulled from the current event) use the event-key names:
:actor,:target,:location,:from,:to. - Memory-drawn non-terminals use
:memory-*prefixes. - Cart-namespaced non-terminals use the cart tag as a prefix (e.g.,
:ice-breaker/ice-class), which become callable from cart-supplied productions.
2. Productions
Section titled “2. Productions”A production maps a non-terminal to a list of weighted alternatives:
(<non-terminal> -> (<weight> <expansion>) (<weight> <expansion>) ...)<expansion> is a list of literals and non-terminals. Literals are strings. Non-terminals are symbols starting with :. Weights are positive integers; the engine normalizes per production at load time.
3. Baseline Grammar (abbreviated)
Section titled “3. Baseline Grammar (abbreviated)”(utterance -> (1 (:mode-observe)) (1 (:mode-annotate)) (1 (:mode-reflect)) (1 (:mode-drift))); note: mode selection itself is done by the mode selector (see; cipher-voice.md §6); the grammar's (utterance) rule is only used; when a rare path skips the selector (e.g., test harness).
(:mode-observe -> (3 (:subject) " " (:verb-present) " " (:object) (:coda?)) (2 (:subject) ". " (:verb-present) ".") (3 (:location) ". " (:heading?)) (2 (:actor) ". " (:verb-past-participle) "."))
(:mode-annotate -> (3 (:deictic) " " (:affect-word) ".") (2 (:affect-word) ".") (2 "that " (:event-kind) ". " (:affect-word) "."))
(:mode-reflect -> (3 (:deictic) ". " (:memory-fragment) (:coda?)) (2 "same " (:memory-keyword) ". " (:memory-fragment)) (2 (:memory-fragment) ". then. " (:memory-fragment)))
(:mode-drift -> (3 (:memory-fragment) ".") (2 (:memory-deictic) ". " (:memory-fragment)) (1 "the " (:memory-keyword) ". " (:memory-when)))
(:deictic -> (2 "this place") (2 "here") (2 "here again") (1 "same light") (1 "this hour") (1 "this corridor") (1 "this silence") (1 "same pressure"))
(:coda? -> (5 "") (2 ".") (1 " —") (1 " " (:affect-word)))
(:affect-word -> (2 "quiet") (2 "wrong") (2 "familiar") (1 "colder now") (1 "loud") (1 "clean") (1 "dry") (1 "thin"))
(:heading? -> (3 "") (1 "north.") (1 "back.") (1 "still."))
(:event-kind -> ; filled at runtime from event.:type (1 :event-type-slot))Cartridges extend :subject, :object, :location, :verb-present, :verb-past-participle, :memory-keyword, and :event-kind with domain-appropriate vocabulary. Cartridges may also add new non-terminals prefixed with their cart tag (e.g., :ice-breaker/ice-class), which become callable from cart-supplied productions.
4. Slot Filling
Section titled “4. Slot Filling”When the engine expands :subject, :object, :location, :from, :to, it pulls from the triggering event’s corresponding field. If the field is missing, it falls back to the cartridge’s default vocabulary for that slot; if the cart has no default, it falls back to the runtime’s generic vocabulary ("it", "here", "the place", etc.). Slot filling never fails loudly.
:memory-fragment expansion samples a past event and runs it through a reduced grammar — an abbreviated version of :mode-observe — producing a clipped past-tense fragment. This is how reflect and drift speak memory.
5. Production Weights and Sampling
Section titled “5. Production Weights and Sampling”Production alternatives are sampled with lfsr_next(cipher_seed) and weight-proportional selection, same mechanism as mode selection (see cipher-voice.md §6). Deterministic. Cart-supplied productions compose into the runtime’s productions at load time per the merge rules below.
6. Cart-Supplied Grammar Block
Section titled “6. Cart-Supplied Grammar Block”Cartridges ship grammar contributions in a cipher-grammar block in the .kn86 container. Full block-form syntax + merge rules are documented in cipher-voice.md §10. Quick summary:
- Vocabulary pools merge additively. Cart’s
:subjectwords are appended to the runtime’s base pool with default weight 1. - Productions merge by weight. A cart-supplied production for an existing non-terminal is appended with its declared weight. The engine normalizes across the combined set at merge time. Runtime-shipped productions carry weight 10 by default — a cart adding a weight-2 production is a minority voice, not a dominant one.
- Cart-namespaced non-terminals (prefixed with the cart tag) are isolated to that cart’s productions.
On cart unload, the cart’s overlay is rolled back from the active grammar tables. See cartridge-lifecycle.md for the lifecycle event ordering.