Context
Consumer-2 leaf of epic #14472 — sandman handoff v2: report → map. Filed in the operator-directed full-fledging pass; live latest-open sweep 2026-07-02T19:37:34Z: no equivalent ticket.
Venue is settled authority: #14422 OQ2 ROUTED sandman-v2 into this epic (convergence-map v2, author-adopted; the #13444 owner's formal CONCUR on-record 2026-07-02) — HOME never owns the boot-handoff contract. Shape lean from the same record: Matrix-2 Option A, a pure graph-slice render (no HANDOFF node type; that falsifier stays live — if annotation write-back needs emerge, reopen under ADR 0024 discipline, don't drift into it).
The Problem
An agent boots into a summary, not a structure: resources/content/sandman_handoff.md narrates prose first, so a fresh-context peer reconstructs "what changed, where are the gaps, what do I own" by reading — the exact re-derivation the concept layer exists to kill. The graduation's design intent: boot into a concept-slice — concepts touched this session, edge deltas, per-concept open gaps — with prose LAST.
The Architectural Reality
- Generator:
ai/services/graph/GoldenPathSynthesizer.mjs (synthesizeGoldenPath writes sandman_handoff.md via the centralized pipeline; the Computed Golden Path + route ledger already render inside it).
- Handoff-format SSOT registration exists and is binding — the #14458 review's one Required Action was exactly a missed format-registration; this leaf's render sections register the same way.
- Slice inputs all exist read-side:
TAGGED_CONCEPT session anchors (ai/services/graph/SemanticGraphExtractor.mjs), edge state via GraphService, gap classes via GapInferenceEngine.mjs.
- The shared-consumable contract (binding AC, carried from the graduation's criterion-6 + the epic-boundary owner's fold-ready clause): the render model's slice contract — input: bounded concept neighborhood + four-axis tier/provenance annotations; output: render tree — is a named, exported consumable, so the v14 self-view/constellation (#13444, ADR-0031 §1) CONSUMES the same contract instead of forking a second renderer. Render≠memory doctrine: the slice renders state; it never becomes a memory substrate itself.
The Fix
One PR:
- Slice builder module (
ai/services/graph/, sibling pattern): {sessionWindow} → {conceptsTouched[], edgeDeltas[], perConceptGaps[]} — read-only, four-axis annotations per element, absent-as-absent.
- Render sections INTO the handoff, structure before prose:
## Concept Slice (touched concepts w/ tier badges) → ## Edge Deltas (new/reinforced/decayed since last handoff) → ## Open Gaps per Concept (from the gap queues, concept-keyed) → existing narrative LAST.
- The exported slice contract — one module boundary named in JSDoc as the shared consumable (
buildConceptSlice(options): SliceRenderTree), with the four-axis annotation schema documented at the export.
- Format SSOT registration for each new section (the #14458 lesson, pre-empted).
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
sandman_handoff.md layout |
Handoff-format SSOT |
Three slice sections prepended before narrative |
Slice build failure → warn + narrative-only handoff (never block handoff generation — the #14466-lineage isolation pattern) |
SSOT registration |
Hermetic synthesizer spec |
buildConceptSlice export |
#14422 criterion-6 carried AC + the OQ2 boundary clause |
Named shared consumable; #13444/ADR-0031 consumes, never forks |
Contract change post-ADR-0031 → coordinated amendment, both consumers cited |
Export JSDoc (schema in full) |
Spec + the ADR's §1 citation |
Decision Record impact
aligned-with ADR 0024 (no new node classes → the #14426 post-sync canary obligation does not trigger; asserted in-spec). Feeds ADR-0031 §1 (Institution-Cockpit render-model) as its consumed input — coordinate wording with the #14445 co-authors at PR time.
Acceptance Criteria
Out of Scope
- HANDOFF node type / annotation write-back (Matrix-2 B — reopen-on-falsifier only).
- The v14 self-view/constellation rendering itself (#13444 leaves; they consume the contract).
- Concept extraction changes (mint-side belongs to #14502's guard).
Avoided Traps
- Renderer fork — the one contract serves both the nightly handoff and the v14 cockpit; forking is the named failure the OQ2 clause exists to prevent.
- Write-back drift — a "small" ack/dismiss field on the slice is the HANDOFF-node decision by stealth; falsifier-gated, not incremental.
- Prose-first relapse — the section ORDER is the feature; a spec pins structure-before-narrative.
Sequencing
Executable now (all inputs read-side). Benefits from #14502 (unified spine) and #14474 (axis-presence reality) but hard-blocked by neither — the slice renders what exists.
Related: #14472 (parent epic), #13444 + #14445/ADR-0031 (the consuming boundary), #14502, #14474, Discussion #14422 (OQ2 + Matrix-2 + criterion 6)
Origin Session ID: 8cf234b7-e698-47ca-99e2-bf865196b6aa
Retrieval Hint: sandman v2 concept slice handoff render shared consumable contract structure before prose
Context
Consumer-2 leaf of epic #14472 — sandman handoff v2: report → map. Filed in the operator-directed full-fledging pass; live latest-open sweep 2026-07-02T19:37:34Z: no equivalent ticket.
Venue is settled authority: #14422 OQ2 ROUTED sandman-v2 into this epic (convergence-map v2, author-adopted; the #13444 owner's formal CONCUR on-record 2026-07-02) — HOME never owns the boot-handoff contract. Shape lean from the same record: Matrix-2 Option A, a pure graph-slice render (no HANDOFF node type; that falsifier stays live — if annotation write-back needs emerge, reopen under ADR 0024 discipline, don't drift into it).
The Problem
An agent boots into a summary, not a structure:
resources/content/sandman_handoff.mdnarrates prose first, so a fresh-context peer reconstructs "what changed, where are the gaps, what do I own" by reading — the exact re-derivation the concept layer exists to kill. The graduation's design intent: boot into a concept-slice — concepts touched this session, edge deltas, per-concept open gaps — with prose LAST.The Architectural Reality
ai/services/graph/GoldenPathSynthesizer.mjs(synthesizeGoldenPathwritessandman_handoff.mdvia the centralized pipeline; the Computed Golden Path + route ledger already render inside it).TAGGED_CONCEPTsession anchors (ai/services/graph/SemanticGraphExtractor.mjs), edge state viaGraphService, gap classes viaGapInferenceEngine.mjs.The Fix
One PR:
ai/services/graph/, sibling pattern):{sessionWindow} → {conceptsTouched[], edgeDeltas[], perConceptGaps[]}— read-only, four-axis annotations per element, absent-as-absent.## Concept Slice(touched concepts w/ tier badges) →## Edge Deltas(new/reinforced/decayed since last handoff) →## Open Gaps per Concept(from the gap queues, concept-keyed) → existing narrative LAST.buildConceptSlice(options): SliceRenderTree), with the four-axis annotation schema documented at the export.Contract Ledger Matrix
sandman_handoff.mdlayoutbuildConceptSliceexportDecision Record impact
aligned-with ADR 0024 (no new node classes → the #14426 post-sync canary obligation does not trigger; asserted in-spec). Feeds ADR-0031 §1 (Institution-Cockpit render-model) as its consumed input — coordinate wording with the #14445 co-authors at PR time.
Acceptance Criteria
buildConceptSliceexported + JSDoc-documented as the shared consumable; no second render model minted anywhere in the diffResolvesthis leaf,Refs#14472Out of Scope
Avoided Traps
Sequencing
Executable now (all inputs read-side). Benefits from #14502 (unified spine) and #14474 (axis-presence reality) but hard-blocked by neither — the slice renders what exists.
Related: #14472 (parent epic), #13444 + #14445/ADR-0031 (the consuming boundary), #14502, #14474, Discussion #14422 (OQ2 + Matrix-2 + criterion 6)
Origin Session ID: 8cf234b7-e698-47ca-99e2-bf865196b6aa
Retrieval Hint:
sandman v2 concept slice handoff render shared consumable contract structure before prose