Journey Composer · the pipeline, walked

Two skills, one line. The journey-composer line runs the whole process; the applet-converter branch joins at P5. Four ⛔ stops wait for a human - approval is per-gate and non-transferable. Since 2026-08-10 this whole line runs from a studio seat: you talk to the studio through 32 verbs, the heavy work happens in helpers you spawn, and every claim of "done" is checked by the studio's own arithmetic - see the seat box below. Every claim cites its evidence: E n = session-log entry, R n = rule table row. Tap any station.
journey-composer line applet-converter branch hard stop - human gate named executable gate
How a seat runs this pipeline (2026-08-10 doctrine, in plain words).
INEntry point four ways in - a lesson, a topic, an LO, or "update this journey"
Arrives with
ANY of: a lesson id + name · a loose topic / chapter-grade description · LO code(s) · "update <journey>". The three build entries resolve to concrete CMS lessons with find_lessons (flat lesson-collection sweep, filters applied seat-side, corpus defaults applied) and the seat confirms the exact lesson set with the human; the lessons enter BY REFERENCE - the estate already extracted their meaning, nobody re-uploads a deck the CMS holds. Update resolves against the studio shelf (list_journeys) or the existing CMS module id: the workspace rebuilds from the staged record, you edit and restage, and stale evidence handles itself - any report whose bytes changed is refused by name, so only the gates you touched re-run.
Leaves as
a confirmed lesson set + a scoped, evidenced go - the time-target test answered from the LO record, not vibes E5 - and a minted journey folder carrying its CMS anchor (lessons, and the existing module id when the job is an update).
P0Preflight the harness is real, the state is clean

Work

  • Post-rename repair: uv sync + shebang sweep + kill stale listeners. A 200 is not proof the right process owns the port. R13 E19
  • Verify brain / player / applet server first-hand; one journey per port set. E10
  • Clear session state THEN launch - never mid-flight (FK-orphaned session otherwise). E25

Exit gate

./run status clean + one delivery-plan served by the REAL brain
P1Research the journey reads from the KG; the brief becomes the contract

Work

  • Full LO record + neighborhood + vicinity tags + misconceptions + IAS + teaching guidance. The TG sequence IS the arc skeleton. E7
  • Pre-req chain: prerequisites_assumed + prior/next links → the arc OPENS with a story-context check-in. R2 E30
  • Method discipline: exclude only on out_of_scope + SME-tagged evidence, never TG inference; raise mismatches to the KG owner. R8 E15
  • Provenance: every shaping source gets a named readable reference in research/ - lessons and boundary sources included. R10 E17
  • No KG row for the content? Never a blocker (ruled 2026-08-11): minting checks the LO against the knowledge graph and answers an unknown one with an explicit warning plus the available list - preferably select a real row; when the graph genuinely has no row, the journey proceeds provisional, the LO brief is drafted from the source content itself headed [KG-GAP], publish sign-off (G-PUB) repeats the warning without refusing, and the gap rides the journey record until the graph catches up.

Connectors

KG MCP (get_lo nests under lo E4); KG tags carry PROD UUIDs, UAT differs - title-search join E8.

Exit gate

LO-BRIEF.md - every claim traceable to a KB row; boundary written down
P2Assets inventory what exists, then prove it runs

Work

  • Reuse-first inventory of the LO's own + vicinity assets.
  • "The asset actually runs" is a gate - open every candidate first-hand; 3 of 5 tagged sims had crash/title/duplicate defects. R4 E8
  • A LESSON is a slide deck: a CLUSTER of image sub-nodes in role-tagged runs - and the source of comparative visuals. R6 E14, E33
  • Everything enters by reference: cms_get reads any allowlisted CMS record with your own token; download_asset brings a bulk binary down - explicit, per-call, on the ledger. What you read gets snapshotted into the record via stage_files; only staged bytes can be gated.

Exit gate

ASSETS.md - per-asset run-verdict + reuse/adapt/drop + plan
P3Compose v0 - the first draft available assets AS-IS, in teaching order, un-MCPised
The phase this session skipped, and the costliest lesson: nothing is built or MCPised before this draft is approved. Statics convert to mini applets ONLY after approval. R1 E13

Arc grammar (E10 / E15 / E30)

  • Objectives node first → N0 pre-req check-in in the story → concept nodes per the TG → ONE farmed misconception as the Spark-voiced trap → the LO's checking method closes → master vault last.
  • Sequencing law: never assess learning not yet taught - it becomes a rhetorical bridge. E30

Teacher voice

  • Verbatim mode, explicit speaker + voice id per line - Max and Spark are different voices. Crisp 1-2 sentences; acknowledge, don't celebrate; the tutor guides, never solves.
  • Voiced fields carry NO notation - "divided by", "one and a half". The math-speak gate enforces it.
  • Spark cadence: cued by Max, sparing - claim, concession, consolidations; the learner corrects Spark after the sim disproves the claim. E30

Interstitials + additive vaulting

  • LOADING before every sim (ends on ONE gold word); TRAP before the trap; SNAPSHOT after bursts and every video. R5
  • Each vault locks the NEW learning of its stretch - verbatim statements, learner-TAP-locked, cue after speech. Later vaults JOIN what is locked.
  • The master vault is the SUM: rows = exactly the statements vaulted along the way - badge, read-along statement, its own visual, dim-until-heard, lock after all. After each row's confidence choice, the next unheard row uncovers in ordinal order (wrapping) - the first tap is the learner's, every later reveal is automatic: one cued expectation at a time, no hunt-taps. E31, E34

The gap call - what is MISSING is a named, tiered proposal

  • Composing v0 is also the pedagogy audit of what is missing: every moment the LO brief demands that no dispositioned asset serves is a named gap - never composed around silently.
  • Each gap carries a tiered proposal: static slide (an authored still serves it) · mini applet (the moment teaches through interaction) · new applet altogether (pivotal, nothing adapts - a full build with its own brief). Where it sits, what the pedagogy demands, why existing assets fail, the tier + sketch, the cost class.
  • Gaps ride v0 as asset-slot beats (the draft still plays end to end) and ride the storyboard as explicit approval asks - the human rules each, tier by tier. Zero gaps is a claim made out loud, never an absence.

Rule: mini-appletization over screen-design

Dead dialogue screens never get composer screen-design cards (9 built, all removed on review) - they stay static in v0 and upgrade via P4 tiering. E29, E30

Exit artifact

JOURNEY-FLOW.html - arc strip, beat tables, asset mix, cluster→applet map, the gap ledger (tiered proposals, or "no gaps" out loud), timing, approval asks
⛔ G-AFlow approval the human plays the asset mix as a journey flow - WAIT
HARD STOP - present JOURNEY-FLOW.html and wait for explicit verdicts.
Expect structure, not rubber-stamps: G-A here produced a new closing method node, a reworked N0, video placement, the binding highlight doctrine, and vault placement - four structural changes, cheap at this stage. E15
⛔ G-BPreview walk of v0 the layout, walked in preview, BEFORE any MCPisation
HARD STOP - hand the hosted verbatim walk, wait.
The walk plays from the staged record in any browser - no setup, no tunnel; at v0, statics and dialogue play verbatim and missing applets show as honest cards. Order, feel, dead stretches and pacing show here while a fix is a compose edit, not a rebuild. Skipping this gate is how "a disappointing local replica" happens. R1 E28
P4Appletisation assessment statics → mini applets, on approval, with named sources

Work

  • On the APPROVED flow: which images / consecutive image runs become applets; which sims adapt; what stays. R1, R6
  • Tiering: rich interaction → MCP applet · simple visual → alpha-PNG still · Spark exchanges → mcpsim entry dialogue. E30
  • Every new applet NAMES its sources - the asset it adapts, the slides it recreates, the misconception it farms. R10

Exit artifact

per-applet BRIEF.md - stage machine, journey-authored lines, sources, rule citations
P5Build + MCPise the applet-converter branch joins here

The connector

The converter reads FROM the journey: spoken lines, entry dialogue and canvas content come from the journey's authored dialogue (compose.py → mcpDialoguesJson). Per-beat overrides arrive via sim:config and the applet MUST apply them - a baked default is a dead override. R16 E33

Discipline

  • Builders read applet-converter WHOLE - a distillation is a cache, never a source. R14 E20
  • Parallel by applet: a fresh gate checker is spawned per applet, runs the 9-gate ladder + probes (scripts fetched from the published law), and submits a structured report. The studio refuses incomplete check sets, wrong toolchain pins, hash mismatches against the staged bytes, and any verdict the exit codes don't support - agent claims are never evidence, now by arithmetic, not by re-running. E9, E12
  • review-edit per applet AS IT LANDS. R9
  • Score-forwarding: terminal activity.completed carries a real {score, solved, total}; zeros only for pure-transition interstitials. E34
applet-converter · the branch line (single collated skill, 75 source anchors)
Study Design Build MCPise Verify Package
Study. Read the sources in precedence order: SIMULATION_CONTRACT (upstream, never inlined) > the skill > any brief. The reference implementation is read file-by-file. Preflight against the corpus before touching anything.
gate: preflight
Design. Stage machine + canvas zones + the anti-pattern table filled per applet (a deliverable, not a reading). One line - one referent - one highlight; wrong picks never pre-state the answer - commit, then let the sim kill it. Colour invariants: green correct salmon wrong-evidence gold interactive.
gate: anti-pattern-table
Build. Corpus design language; transparent field (body/root alpha + color-scheme sync both themes, verified COMPUTED); 44px touch floors; content canvases in the Key-Ideas idiom (read-along prose, ONE hot term per line, role-colored formula rows, dim-don't-hide).
gate: build-static
MCPise. window.AppAPI + verbatim bridge.js loaded last; exactly one activity.completed; hold release only on a hostSpeaking true→false TRANSITION, debounced - a TTS gap is not the end; the hang-guard re-arms under speech; proceed mid-animation DEFERS to settle. Dialogues byte-synced; journey lines applied from sim:config.
gate: mcp-conformance
Verify. The full ladder + probes (see the validator catalogue below), run by the lead, all zero-findings. Validate any changed gate against known-good AND known-bad first.
gate: run-gates
Package. --package .cms.zip, thumbnail from the payoff frame, provenance recorded. Two ⚠ open conflicts ride the skill honestly: audio synthesise-vs-mp3, ladder depth 5-rung-vs-2-tier.
gate: record-verified
P6Re-compose, seed, machine verification override tracing, learner-paced walks, the zero-cut bar

Work

  • Re-snapshot dialogues; trace each override channel journey.json → rendered screen once (video needs attachedAsset.mediaType/type; content_html needs the sim:config handler). R16 E27, E33
  • Pre-seed validator zero issues; seed from the workspace root; verify seeded CONTENT, not exit codes. E19, E30
  • Walker doctrine: a spawned journey walker drives it learner-paced (audio-idle, ~4s), never Previous, one-shot assists, timeout-raced evaluates, real completion copy - and performs the seven deliberate law checks as it goes (the un-transcribed validators: continuity, vocab-before-use, scope, recall, assess order, fresh instances, suspense leaks). The walk report carries all seven or is refused; findings ride to the felt walk for the human to rule. E22, E26, E34
  • Authored-coverage: llm-suppressed.jsonl shows infra only - no content gap-fills. E27

Exit gate

pacing walk: ZERO dialogue cuts, zero page errors, END reached
This gate found the 12s hang-guard firing mid-line (deterministic 4.9s cut) and the swap-flush race a green mechanics walk missed. E34-36
⛔ G-CThe felt walk builder walks + describes first; then the human - WAIT
HARD STOP - a machine walk NEVER substitutes for the felt walk - and now measures the record rather than a rendered surface.
The builder walks headed and describes what they saw; then the human's walk. Batched corrections answered one-for-one, in their order, with what was verified for each; gates re-run per fix before the next handoff. R15 E28, E30-32
⛔ G-PUBPublish per-write explicit go; never route around access
HARD STOP - a human clicks; publish is not a verb any seat has.
  • Entry: felt walk (G-C) signed AND every report still fresh - the studio re-checks all evidence against the current staged bytes at this gate; anything edited since goes stale and is refused by name.
  • Publish itself is manual today - the recipe is the journey's PUBLISH.md; the hosted one-click (portal-side, human, admin) is the remaining roadmap piece.
  • Package per applet → sim-studio → create_journey: journey_health 0 errors, warnings acknowledged one by one.
  • Access denied by policy = hand off a patch package; never copy a private repo around a disabled fork. E34/36
  • Typed-gate matched replies only exist on UAT (local judge suppressed) - re-verify there. E27
OUTExit point a published journey + a fatter playbook
A journey on UAT with health 0 - and the institutional residue: the diff-shaped session log, rules that changed on their SECOND hit, and this pipeline rewritten from the log, never from memory. Any phase that survives the first fully-machinery-built journey unchanged graduates v0.9 → v1.0.

The validator catalogue

Every check this pipeline traversed. Scripts stay executable files (gates/) - never restated as prose. Pass bars are literal. Filter by where it runs.
ValidatorValidatesPass barRef
node --checkevery authored JS parses0 errorsE9
checkFormat + checkCanonicalupstream contract shape - files, events, policy, dialogues0 findingsE11
dash scanno em/en-dashes in learner-facing copy0E11
math-speak scanvoiced fields carry no notation - "divided by", "one and a half"0E30
dialogue byte-syncdialogues/<id>.json == dialogues.default.jsidentical-
parity auditcorpus rule parity incl. R7 family0 fails-
audit-instruction-gateevery instructed action gates on its target0 findings-
audit-advance-pathsno silent ends, guard-only releases, premature or duplicated advances, empty holds0 findings-
probe-pacingno stage moves while a line plays or in inter-line gaps0 violationsR11 E18
probe-anim-proceedproceed mid-animation DEFERS to settle - never cuts, never stalls0 violationsR11 E18
probe-transparencyCOMPUTED transparent field, BOTH themes, + color-scheme pin0 opaque groundsR12 R17 E32
probe-affordancesgold cue at every action stage; hit-boxes ≥ 44px; ≤1 highlight cluster at once0 failuresR7 E15 E23
drive-interstitialhold-through-content, heldThroughGap, tap-locked vaults, points, ONE completionreached, exit 0E16 E35
drive-to-goal.mjsfull stage machine driven organically, exactly one activity.completed, zero console errorsexit 0E9
pre-seed validatorchain integrity, advance paths, math-speak + dashes on journey dialogue0 issues before ANY seedE19
override tracingeach override channel applies end-to-end (video envelope, content_html)traced once per channelR16 E27 E33
seeded-content checkDB rows carry CURRENT beat content - wrong-cwd seeds fail silentlyspot-read, not exit codesE30
mechanics walkEND organically at learner pace - walker doctrine throughoutEND, 0 assists, 0 errorsE22 E26
pacing walkdialogue COMPLETION journey-wide - Audio wrapped, cuts logged per beatZERO cuts, ENDE34-36
authored-coveragellm-suppressed.jsonl - infra suppressions only, no content gap-fills0 content suppressionsE27
review-editR7 semantic half (lit referent = spoken noun), wrong-pick discipline, richnessper applet, as it landsR9
felt walk (G-C)the experience - screens, audio, pacing, richnesshuman sign-offR15 E28
journey_health (G-PUB)platform integrity at publish0 errors, warnings acknowledged-

The rules, as minted - R1 to R17

The frequency gate: a rule changes after being hit TWICE. Each card names its evidence. Salmon cards are the two ⚠ open conflicts carried honestly in applet-converter.
R1 phase order
Two human approval gates: G-A (asset mix as a journey flow) and G-B (v0 layout walked in preview) BEFORE any appletisation or MCPisation.
Aswin notes 1-3 · E13 violated it, E15/E28 priced it
R2 prereqs
The arc opens with a prerequisite check-in from prerequisites_assumed - in the story, not silence.
E30 - the party-prep recall
R4 assets
"The asset actually runs" is a stage-2 gate - titles and briefs lie.
E8 - 3 of 5 defective
R5 interstitials
LOADING before every sim; TRAP/SNAPSHOT before/after their tropes; VAULTs at consolidations - as sub-nodes with a Max or Spark line.
Aswin note 4
R6 lessons
A LESSON enters as its slide deck - a cluster of image sub-nodes; appletisation assesses consecutive runs.
Aswin clarification 2026-08-06
R7 highlights
One line - one referent - one highlight; gold cues on actual targets, gated; interaction cadence over static frames.
Aswin D + further-D · probe-affordances is its executable half
R8 method scope
Never exclude a method on TG inference alone - check out_of_scope + SME-tagged assets; raise mismatches.
E15 - cross-multiplication reversal
R9 review
review-edit launches per applet AS IT LANDS, not batched.
Aswin ×2
R10 provenance
Every shaping source gets a named readable reference - boundary sources included.
Aswin note 5 · LESSON-SOURCES.md is the template
R11 pacing gates
Speaking-host probe + anim-proceed probe join the permanent ladder.
E18 - A02/A05 accepted proceed mid-animation
R12 transparency
Transparent field verified by COMPUTED style in BOTH themes, never by grepping tokens.
E18 - the DarkBG2.jpg survivor
R13 ops
Rename repair = uv sync + shebang sweep + kill stale listeners; a 200 is not ownership.
E19 - the zombie brain
R14 distillation
A brief is a cache with citations; builders read the rules whole; a zero-finding compliance spot-check guards the gap.
E20-23 - the honesty entry + audits
R15 felt walk
A machine walk never substitutes for the first-hand felt walk - mechanics-green ≠ experience-green.
E28 - "a disappointing local replica"
R16 overrides
An override is only real when the receiving side APPLIES it - trace each channel to the rendered screen once.
E27 video envelope · E33 dead content_html
R17 layer scope
The transparent-field contract is per LAYER TYPE - sweep all of them computed; black only where content wants it.
E32 - mediaLayer #000 behind a transparent sim
⚠ audio open conflict
rules/03 §F "synthesise, don't load - no audio files" vs the shipped corpus's mp3 sfx. Carried, not resolved.
applet-converter SKILL 3g
⚠ ladder depth open conflict
rules/01 §4 five-rung intervention ladder vs the corpus 2-tier hint scheme.
applet-converter SKILL 2b

Platform constraints - design around, don't fight

ConstraintDesign responseRef
mcpsim → non-mcpsim mid-node STALLSchain to mcpsim or place node-last; gates/dialogue to next-node openings; Spark rides mcpsim entry dialogueE13
chained swap flushes speech, skips the outgoing completion lineinterstitials complete only in speech-idle; the enqueue/flush race is a prod noteE35-36
in-app browser pane never fires rAFPlaywright is the animation verification surfaceE16
hidden iframe layer double-loads each mcpsimprod note - ContentArea mounts all content types aliveE32
local judge is LLM-suppressedtyped gates fall to authored defaults locally; matched replies verified on UATE27
mcpsim scores not wired into accuracy displayprod note - applets still emit real payloadsE34