Skip to content

FE-847: DX introspection tier 2#205

Merged
lunelson merged 32 commits into
nextfrom
ln/fe-847-turn-boundary-closure
Jun 11, 2026
Merged

FE-847: DX introspection tier 2#205
lunelson merged 32 commits into
nextfrom
ln/fe-847-turn-boundary-closure

Conversation

@lunelson

@lunelson lunelson commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

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.

@lunelson lunelson marked this pull request as ready for review June 11, 2026 14:31
Copilot AI review requested due to automatic review settings June 11, 2026 14:31
@cursor

cursor Bot commented Jun 11, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Documentation and agent-skill updates only; no runtime, auth, or data-path changes in the PR diff.

Overview
Documents FE-847 Tier-2 / turn-boundary closure and tightens how future reviews catch wiring and schema gaps—no product runtime changes in this diff.

memory/PLAN.md is reconciled after 2026-06-11 completion: turn-boundary-reconciliation and kick-and-context-seeding are done on ln/fe-847-turn-boundary-closure; dx-tier-2-harness and capability-readiness / dx-introspection-live are recorded as done with remediation notes (live getElicitationGaps, I46/I47 scaffold live, request-envelope projection). The active frontier list is empty with one handed-off migration residue note; a large block of completed frontier definitions moves out of the live plan. Sequencing text now reflects the two-branch FE-847 stack (harness vs turn-boundary closure) instead of a single-branch S0–S5 story.

docs/archive/PLAN_HISTORY.md gains a 2026-06-11 sync archive summarizing retired frontiers (DX tiers, gaps remodel, graph mutations, etc.). memory/CROSS_CUT_PLAN.md rewrites deferred Q-state / elicitation copy from stored grade to gap-driven readiness and elicitation_gaps / D75-L. HANDOFF.md is removed as volatile transfer state superseded by SPEC/PLAN.

.agents/skills/ln-review/SKILL.md adds two graduated contract lenses: optional capability hooks on context interfaces (live vs harness divergence) and representable but semantically empty tagged-union arms (“dark variants”), with repairs aligned to SPEC §Acknowledged Blind Spots.

Reviewed by Cursor Bugbot for commit 5939152. Bugbot is set up for automated code reviews on this repo. Configure here.

lunelson and others added 26 commits June 11, 2026 16:44
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>
@lunelson lunelson changed the title Sync planning docs after FE-847 restack FE-847: DX introspection tier 2 Jun 11, 2026
@lunelson lunelson force-pushed the ln/fe-847-turn-boundary-closure branch from 4e2e2a0 to 5939152 Compare June 11, 2026 14:51
@lunelson lunelson merged commit 30fa4df into next Jun 11, 2026
5 of 6 checks passed
@lunelson lunelson deleted the ln/fe-847-turn-boundary-closure branch June 11, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants