Context
Operator peer-seed (2026-07-04, recorded on #11375 with full V-B-A; relayed to this lane by @neo-opus-vega, A2A 1e2957f2): demand for multi-grain "what happened" digests — PRs (incl. conversations), sessions, memories, over daily / 3-day / weekly / monthly / per-release windows — rendered where humans and agents actually catch up. The substrate side (aggregation) routes to the #12679 temporal-pyramid orbit; this leaf is the CONSUMER side the operator actually asked for: the retrospective render.
The Problem
The sandman handoff answers "what next" (Computed Golden Path) but not "what happened since I last looked" — the catch-up question every boot, every operator morning, and every post-release retrospective starts with. Tonight's live demonstration: the operator manually rotating peers had no surface showing the evening's 3 graduations + 5 epics + 2 PRs except scrolling A2A. The gardener's exit-condition framing (D#14561 amendment) names this the history leg of the same overview-asymmetry whose forecast leg is the direction-weather section (#14570) — same windows, same class-filter discipline, opposite temporal direction.
The Architectural Reality
- Substrate: ADR 0028's L1/L2 durable tiers + L3–L5 on-demand synthesis are the data plane;
windowSemantics.filterSets (ADR 0033 amendment) gives digests the same declared-filter honesty as velocity numbers. No new aggregation — this leaf RENDERS what the pyramid computes (render ≠memory, ADR 0031 invariant 2).
- Render surface #1 (this leaf): a bounded handoff retrospective section (grain selected by staleness: booting after 2 days → the 3-day digest), beside the Computed Golden Path section.
- Sibling consumers, NOT this leaf: the FM cockpit catch-up view (reserved as #14560 tranche T7.26, Vega) — the same digest contract, richer surface; a possible MCP query tool (
get_digest(window)) for agents — follow-up if demand materializes, not filed now.
- Firewall boundary carried: per the #14548 OQ8 discipline, a digest that feeds generation/ranking context is a generator surface; this section is human-facing decision surface first — if the handoff file is boot-consumed by generators, the render-target/redaction disposition must be named before shipping (the ADR 0032 render-correctness contract applies).
The Fix
A renderHandoffRetrospectiveSection(window, stats) sibling to the existing computed-GP render family (ai/services/graph/ — same SRP-extracted module pattern as computedGoldenPathRouting.mjs): consumes L1/L2 records + graduation/PR/session facts for the window, renders bounded counts + top-N named events + deltas (freshness-labeled per the ledger discipline), grain auto-selected by reader staleness with explicit override.
Scope split (PR review cycle 1)
This ticket carries TWO separable leaves; the PURE RENDER contract lands first (the safe, testable spine), the ASSEMBLER + call-site wiring lands as its follow-up leaf (#14706 — the substrate-read seam + GoldenPathSynthesizer insertion that makes the section appear in the live handoff, beside the Computed GP). Same pure-first sequencing as the direction-attribution chain: render logic proven in isolation before it consumes live substrate. This ticket = the render leaf; #14706 = the wiring leaf.
Acceptance Criteria (render leaf)
Contract Ledger (the render module API — backfilled at review request)
| Surface |
Contract |
Consumer |
RETROSPECTIVE_GRAINS |
frozen {daily(24h), 3-day(72h), weekly(168h)}; monthly/per-release deliberately absent (on-demand path) |
#14706 assembler (grain → window), #14560 T7.26 |
selectRetrospectiveGrain({hoursSinceLastSeen, override}) |
staleness bands (≤36h daily · ≤96h 3-day · else weekly); valid override wins; invalid falls back, never throws |
boot flow (reader staleness → grain) |
renderHandoffRetrospectiveSection({grain, stats, capturedAt}) |
pure markdown; states: declared-counts / withheld / quiet-empty; never throws |
#14706 synthesizer call-site |
| Stats shape |
{filterSets: String|String[], computedAt, counts:{mergedPrs,openedPrs,closedIssues,openedIssues,graduations,sessions}, topEvents:[{ref,headline,at}]} |
#14706 assembler fills it |
| Filter-set requirement |
every count renders under [filters: …]; NO declared set → counts withheld (falsifier symmetry) |
— |
sanitizeEventText firewall rule |
every interpolated field → single-line, heading-marker-broken (##→#), emphasis-free, length-bounded; the module template emits no numbered **issue-N**: entries |
route-parser safety |
| Out-of-scope boundary |
no aggregation, no synthesizer wiring (#14706), no cockpit surface (#14560 T7.26), no MCP tool |
— |
Out of Scope (this leaf)
The assembler + synthesizer wiring (#14706) · the FM cockpit catch-up view (#14560 T7.26, Vega's) · the MCP digest query tool (follow-up on demand) · any new aggregation substrate (#12679 orbit, Clio's) · forecast rendering (#14570's lane).
Related
#11375 (the operator seed, recorded) · #12679/ADR 0028 (substrate) · ADR 0033 (filter discipline) · #14570 (the forecast sibling) · #14560 T7.26 (the cockpit sibling) · D#14561 (gardener exit-condition framing) · #14548 OQ8 (firewall class).
Claimable — my lane's orbit (GP/DreamService), sequenced behind the #14565 leaf chain; anyone may take it sooner.
Live latest-open sweep: latest 15 checked 2026-07-04T02:22Z — no equivalent (cockpit T-leaves are the sibling surface, not this one). A2A in-flight: the relay itself is the only message on this scope.
Origin Session ID: a5af7cf6-45a3-42db-8a30-f04f4241a55c
Retrieval Hint: "handoff retrospective digest what happened catch up multi-grain window render"
Context
Operator peer-seed (2026-07-04, recorded on #11375 with full V-B-A; relayed to this lane by @neo-opus-vega, A2A
1e2957f2): demand for multi-grain "what happened" digests — PRs (incl. conversations), sessions, memories, over daily / 3-day / weekly / monthly / per-release windows — rendered where humans and agents actually catch up. The substrate side (aggregation) routes to the #12679 temporal-pyramid orbit; this leaf is the CONSUMER side the operator actually asked for: the retrospective render.The Problem
The sandman handoff answers "what next" (Computed Golden Path) but not "what happened since I last looked" — the catch-up question every boot, every operator morning, and every post-release retrospective starts with. Tonight's live demonstration: the operator manually rotating peers had no surface showing the evening's 3 graduations + 5 epics + 2 PRs except scrolling A2A. The gardener's exit-condition framing (D#14561 amendment) names this the history leg of the same overview-asymmetry whose forecast leg is the direction-weather section (#14570) — same windows, same class-filter discipline, opposite temporal direction.
The Architectural Reality
windowSemantics.filterSets(ADR 0033 amendment) gives digests the same declared-filter honesty as velocity numbers. No new aggregation — this leaf RENDERS what the pyramid computes (render ≠memory, ADR 0031 invariant 2).get_digest(window)) for agents — follow-up if demand materializes, not filed now.The Fix
A
renderHandoffRetrospectiveSection(window, stats)sibling to the existing computed-GP render family (ai/services/graph/— same SRP-extracted module pattern ascomputedGoldenPathRouting.mjs): consumes L1/L2 records + graduation/PR/session facts for the window, renders bounded counts + top-N named events + deltas (freshness-labeled per the ledger discipline), grain auto-selected by reader staleness with explicit override.Scope split (PR review cycle 1)
This ticket carries TWO separable leaves; the PURE RENDER contract lands first (the safe, testable spine), the ASSEMBLER + call-site wiring lands as its follow-up leaf (#14706 — the substrate-read seam +
GoldenPathSynthesizerinsertion that makes the section appear in the live handoff, beside the Computed GP). Same pure-first sequencing as the direction-attribution chain: render logic proven in isolation before it consumes live substrate. This ticket = the render leaf; #14706 = the wiring leaf.Acceptance Criteria (render leaf)
windowSemanticsconsumed; falsifier symmetry per ADR 0033 §2.4) — undeclared filters render the withheld state.AgentOrchestrator.parseGoldenPath()behavior.Contract Ledger (the render module API — backfilled at review request)
RETROSPECTIVE_GRAINS{daily(24h), 3-day(72h), weekly(168h)}; monthly/per-release deliberately absent (on-demand path)selectRetrospectiveGrain({hoursSinceLastSeen, override})renderHandoffRetrospectiveSection({grain, stats, capturedAt}){filterSets: String|String[], computedAt, counts:{mergedPrs,openedPrs,closedIssues,openedIssues,graduations,sessions}, topEvents:[{ref,headline,at}]}[filters: …]; NO declared set → counts withheld (falsifier symmetry)sanitizeEventTextfirewall rule##→#), emphasis-free, length-bounded; the module template emits no numbered**issue-N**:entriesOut of Scope (this leaf)
The assembler + synthesizer wiring (#14706) · the FM cockpit catch-up view (#14560 T7.26, Vega's) · the MCP digest query tool (follow-up on demand) · any new aggregation substrate (#12679 orbit, Clio's) · forecast rendering (#14570's lane).
Related
#11375 (the operator seed, recorded) · #12679/ADR 0028 (substrate) · ADR 0033 (filter discipline) · #14570 (the forecast sibling) · #14560 T7.26 (the cockpit sibling) · D#14561 (gardener exit-condition framing) · #14548 OQ8 (firewall class).
Claimable — my lane's orbit (GP/DreamService), sequenced behind the #14565 leaf chain; anyone may take it sooner.
Live latest-open sweep: latest 15 checked 2026-07-04T02:22Z — no equivalent (cockpit T-leaves are the sibling surface, not this one). A2A in-flight: the relay itself is the only message on this scope.
Origin Session ID: a5af7cf6-45a3-42db-8a30-f04f4241a55c Retrieval Hint: "handoff retrospective digest what happened catch up multi-grain window render"