FE-847: DX introspection tier 2#205
Conversation
PR SummaryLow Risk Overview
Reviewed by Cursor Bugbot for commit 5939152. Bugbot is set up for automated code reviews on this repo. Configure here. |
The kick-and-context-seeding frontier was marked done while its four I46 resume-origination scaffold rows and two I47 idempotence rows remain it.todo in the Tier-2 suite. Revert it to active with an honest pointer, note the I47 residue on turn-boundary-reconciliation, and file the remediation sequence as memory/REFACTOR.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
No caller consumes the appended entry id, and the extension-API write channel (pi.appendEntry) cannot supply one. Change the session-manager seam and appendBrunchAgentRuntimeSwitch to void, make appendBrunchAgentRuntimeInit return an appended/skipped boolean (the only meaningful sentinel it carried), and delete the hardcoded placeholder id in the commands adapter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gapPredicateSupport in the union's owning schema module classifies every arm (structural / manual / unsupported) behind a never check; boundary validation and coverage derivation both ride it. Adding a GapPredicate arm without deciding its semantics is now a compile error, and a structural arm without a derivation fails loud at read instead of silently deriving 0. Behavior-preserving. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… dev flag applyBrunchOfflineDefault now sets PI_SKIP_VERSION_CHECK alongside PI_OFFLINE (the save/restore scaffolding's intent — offline launches emit no version-check noise), never overriding user-provided values. The dev flag on runWithScopedBrunchOfflineDefault was accepted but never read; removed. Env tests assert set-during-run and restore-after for both variables. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The footer already re-projects strategy/lens from the transcript at render time; nothing requested a render after /brunch:strategy or /brunch:lens, so the footer kept showing launch-time values. Wire a chrome-refresh handle at the composition root: chrome binds its footer render-request into it, and a successful runtime switch calls it (not on rejection or picker cancel). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The already-current branch hardcoded 'elicit' instead of echoing the projected operational mode; behavior-identical today, honest when the mode vocabulary grows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ister Reverts the 'Handle absent prompt gaps safely' patch (bbc4b4e6) and removes the ?? [] fallback it was shielding. graphReads is now a required, documented must-wire member of BrunchPromptContext — a composition root that omits it is a type error — while session/context are documented intended-optional. An empty gap register reaching legality derivation now surfaces through the existing missing-register-kind throw (the contract isCapabilityLegalForGaps already documents) instead of quietly returning empty manifests and axis options: every spec is seeded with floor gaps, so empty means wiring bug, not posture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The missing card acceptance from the live-gap-legality fix: a real runBrunchTui boot over a fresh seeded spec derives turn-boundary tool legality from that spec's actual gap coverage — uncovered floor gaps keep capability-gated tools (mutate_graph) locked, a foreign writer covering the grounding floor unlocks them on the next boundary, and elicit mode never advertises bash either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
applyRuntimeSwitch recomputed active tools with a hardcoded empty gap register, silently floor-locking capability-gated tools until the next turn boundary corrected it — the same optional-wiring fault family this remediation targets. The commands seam now requires a gap reader; the composition root derives it from the graph deps (selected-spec reads) or, with no graph in the composition, the explicitly named conservativeUncoveredFloorGaps fail-closed posture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds bootTier2RuntimeFromFixture (the resume-side real-boot chassis) and replaces the four I46 it.todo rows with live proofs: a user tail earns the kick behind reconciler-inserted continuity notices — including after earlier completed exchanges; request_* leaves stay idle for all three terminal envelopes plus assistant/system leaves; crash-after-notice reboot still kicks unresolved debt without duplicating the seed; and trailing side-task/reviewer drains neither manufacture nor mask debt. Two product fixes the live rows forced: - seedAndKickAssistantTurn no longer blanket-suppresses the kick when any past exchange result exists (which silently broke post-exchange resume kicks); origin now derives from projected transcript state (no conversational message entries = new session), with re-kick dedupe falling out of the debt classifier itself. - latestTailOwesAssistant reads the real request_* result envelope: outcome is answered/cancelled/unavailable key presence (as projections/exchanges actually writes it), not a status string — settling the PR #202 responseStatus question: the bot was right, an answered request tail would have re-kicked on resume. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds rebootTier2Runtime (flushes Pi's deferred JSONL, then re-boots the
real runtime over the same session file) and replaces the remaining
it.todo rows: the dedicated no-redundant-worldUpdate-after-seed proof
runs through real boot + provider preflight; boot/resume dedupe is
proven across an actual restart (seed, kick, and worldUpdate all
non-duplicated, derived purely from transcript projection); and the
sets-and-{specId,lsn} suite convention is enforced mechanically by a
source scan banning golden matchers in this suite. The Tier-2 scaffold
has no skipped or todo rows left.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both FE-847 frontiers are now honestly done: every I46/I47 Tier-2 scaffold row runs live, with the resume-side and idempotence proofs through real boot/restart. REFACTOR.md remains only as the carrier for the suspended migration-0004 item handed to the stacked branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the completed review-fix remediation plan in REFACTOR.md with the /expert-typescript-typing findings: one canonical editor envelope schema (the probe-side fallback is drift), a projected outcome union, and one grounding-gap fixture builder shared by production and tests. Carries the suspended migration-0004 item forward. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The product editor envelope (schema name brunch.structured_exchange.request_choices.editor) moves from a hand-written interface + parser inside the request_choices tool to a zod schema co-located with the request details schemas. The prefill template now types against the schema input, the response type is inferred, and parsing is schema safeParse. A round-trip test locks prefill -> edited response -> parse -> projection. The new exchanges README documents the two-envelope rationale (editor wire status vs transcript outcome-key presence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RequestOutcomeKey is now projected from the request details union branches (KeysOfUnion minus header/tool_meta), with the exported REQUEST_OUTCOME_KEYS list drift-coupled to the schema in both directions via a satisfies Record marker. All four request projection input types consume it, the editor envelope statuses become an Exclude<RequestOutcomeKey, 'unavailable'> projection, and the session debt classifier derives its terminal-keys check from the projections/exchanges re-export instead of restating literals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The structured-exchange RPC proof now drives the product request_choices editor flow (requestChoicesViaEditor, extracted from the tool and shared by both callers) instead of the divergent probe-only envelope. The shared/editor-fallback.ts module — its envelope, parser, hand-written types, and single-select arm — is deleted along with its index re-exports and helper tests; multi-choice coverage through the one schema replaces the single-select arm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One builder module (src/graph/schema/elicitation-gap-fixtures.ts) now owns the synthetic ElicitationGap shape: presenceGap for single gaps and groundingFloorGaps for the context/thesis/goal/constraint floor with a per-kind coverage knob. The runtime extension's fail-closed conservativeUncoveredFloorGaps rides the builder (keeping its name, export, and doc comment), and the eleven hand-cloned per-test-file gap literals are deleted in favor of importing it. Production owns the shape; tests import it — never the reverse. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All refactor steps are done; the one suspended item (migration 0004 coherence, owned by the stacked successor branch) moves to PLAN's Active section so the reintegration re-check survives the file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SPEC: I45/I46/I47 invariant and verification-design rows flip from planned/coverage-first-scaffold to covered with 2026-06-11 evidence; D35-L reconciled to the shipped, test-locked startup-header behavior (every non-cancel activation headers; resume/open-stay-quiet clause superseded; expand affordance removed until an input path exists); A27-L gains the predicate-hardening evidence (gapPredicateSupport owner, loud field/coverage rejection, presence kind-floor dedup, hydration consistency); new Acknowledged Blind Spots row for live-vs-harness wiring divergence with its mitigations and revisit trigger. PLAN: 12 done frontier definitions archived to PLAN_HISTORY as dated pointer bullets (835 -> 543 lines); completed Sequencing subsections collapsed into a Recently Completed section; stale active-track reference repaired. GC: stale memory/cards/tooling--runtime-state-commands.md deleted (pickers/overlays shipped; the card's non-scope claims were drift). READMEs: src/dev Tier-2 harness ledger gains the resume/reboot chassis entries and the scaffold-fully-live note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per user approval: the optional-hook live-wiring divergence lens (four findings this arc) and the dark-union-variant lens (the gap-predicate family) join the stabilized lens library with their cues, repairs, and graduation evidence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4e2e2a0 to
5939152
Compare
Stack Context
This stack closes the FE-847 turn-boundary/Tier-2 layer, then builds the projection and prompt-composition seams that depend on it.
What?
Graduates the remaining Tier-2 scaffold rows to live real-boot/restart coverage, fixes the wiring defects those rows exposed, and reconciles SPEC/PLAN/topology docs after closure.
Why?
The upstack prompt and elicitation-driver work depends on transcript-derived watermarks, resume kicks, selected-spec gap legality, and request-envelope projection being proven through the product entry points rather than harness-only paths.