Skip to content

FE-1123: Structured-exchange rendering: fix, unify, and lock the transcript renderer family#287

Merged
lunelson merged 30 commits into
nextfrom
ln/fe-1123-exchange-rendering
Jul 3, 2026
Merged

FE-1123: Structured-exchange rendering: fix, unify, and lock the transcript renderer family#287
lunelson merged 30 commits into
nextfrom
ln/fe-1123-exchange-rendering

Conversation

@lunelson

@lunelson lunelson commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Stack Context

This branch is the exchange-presentation transcript-rendering frontier. It stacks on the walkthrough fixes and feeds the later live answering/chrome work.

What changed

  • Moved structured-exchange validation to the session/tool parameter boundaries where bad answers can return friendly exchange errors.
  • Centralized comment-requirement rules and typed exchange detail construction.
  • Reworked transcript content grammar for present/request/review exchanges, including answer echo and tuple goldens.
  • Settled renderResult as Markdown pass-through of the formatter content for now, with the richer details-backed render path named as a ceiling.
  • Locked review-set tuple rendering and reconciled exchange validation/rendering topology.

Why

The walkthrough showed uneven, scaffold-like transcript renders. This branch makes the exchange family consistent and testable while keeping model-facing content and TUI rendering on the simplest current path.

@cursor

cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Markdown and planning traceability only; no application code in this diff.

Overview
Documentation-only closeout for FE-1123 / the exchange-rendering frontier: memory/PLAN.md marks the frontier done (2026-07-03), moves it to Recently Completed, drops it from Next, and rewrites the frontier block to match what shipped—D104-L Markdown pass-through for renderResult, D108-L consolidation under src/exchanges/, updated aggregate DoD/oracles/traceability (D105–D108-L), and removal of the draft sweep inventory table in favor of the built ledger. docs/design/STRUCTURED_EXCHANGE_COLLAPSE.md points schema topology at src/exchanges/schemas/TOPOLOGY.md (post-D108-L) and reformats comparison tables.

.agents/skills/ln-review/references/contract-lenses.md adds a graduated contract-integrity lens for parallel provider-payload system-prompt carrier lists (append vs debug extract drift), with repair guidance to unify carriers and parity-test them—cited from PR #286, not changed by this PR’s runtime code in this diff.

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens structured-exchange validation and rendering by moving key invariants (comment requirements, non-empty multi-select, trimmed non-empty headings) to earlier trust boundaries, and by standardizing transcript content formatting through shared, details-backed formatters (with render-honesty checks and updated goldens).

Changes:

  • Enforce exchange invariants at session/tool boundaries (comment required for Other/None and request_changes; multi-select must be non-empty; headings must be trimmed + non-empty).
  • Route accepted responses and tool results through centralized projections + markdown formatters (option-echo payload added; updated snapshot/golden strategy).
  • Add/propagate proposed graph codes in review sets and enforce “stale proposed code” detection during acceptance.

Reviewed changes

Copilot reviewed 85 out of 85 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/session/structured-exchange-loop/accepted-response.ts Moves comment + empty-selection validation into acceptance; emits formatted content via request formatters.
src/session/tests/structured-exchange-loop.test.ts Updates expectations for new content grammar and adds tests for new acceptance validations.
src/session/tests/exchange-projection.test.ts Updates fixtures to include proposed codes and answered option echoes.
src/rpc/methods/session.ts Threads proposed codes into RPC payload derived from details.
src/rpc/tests/handlers.test.ts Updates RPC handler expectations for proposed codes in review-set payloads.
src/projections/TOPOLOGY.md Records D104-L and updates projection-layer migration notes for typed constructors vs recognizers.
src/projections/exchanges/request-review.ts Converts to typed branch construction (removes Zod parse).
src/projections/exchanges/request-choices.ts Adds answered options echo + typed constructors; removes Zod parse.
src/projections/exchanges/request-choice.ts Adds answered options echo + typed constructors; removes Zod parse.
src/projections/exchanges/request-answer.ts Converts to typed branch construction; trims answered text.
src/projections/exchanges/present-review-set.ts Adds proposed_code to persisted review-set node details; typed details construction.
src/projections/exchanges/present-question.ts Splits answer vs option forms explicitly; typed details construction.
src/projections/exchanges/present-candidates.ts Typed details construction (removes Zod parse).
src/projections/exchanges/tests/request-choice.test.ts Updates tests for required answered options echo.
src/probes/structured-exchange-rpc-proof.ts Updates proof fixture to include answered options echo.
src/probes/tests/structured-exchange-rpc-proof.test.ts Updates probe expectations for answered options echo.
src/probes/tests/project-graph-review-cycle-proof.test.ts Updates proof fixtures to include proposed codes.
src/graph/review-set.ts Introduces proposed-code assignment + stale-code diagnostics; validates entity draft proposedCode presence/shape.
src/graph/command-executor/tests/accept-review-set.test.ts Adds coverage for honoring proposed codes and failing on divergence.
src/graph/command-executor.ts Adds proposed-code validation before mutation planning and exposes assignment helper.
src/graph/tests/review-set.test.ts Adds tests for deterministic proposed-code assignment across consecutive drafts.
src/dev/component-preview/registry.ts Adds preview entries rendering exchange markdown results.
src/dev/component-preview/exchange-fixtures.ts New fixtures for present_question and present_review_set projections + formatted results.
src/dev/tests/support/tier-2-test-support.ts Updates helper messages for request_choices to supply answered options echo.
src/agents/shared/tree.ts Switches code-block rendering to md-pen primitives.
src/agents/shared/toon.ts Switches code-block rendering to md-pen primitives.
src/agents/shared/markdown.ts Narrows shared markdown util to house block-composition (joinMarkdownBlocks).
src/agents/shared/tests/markdown.test.ts Updates tests to focus on block-composition semantics.
src/agents/contexts/seeds/graph-fact-seed.ts Uses md-pen list primitive directly instead of wrapper.
src/agents/contexts/exchanges/TOPOLOGY.md Updates exchange formatter ownership notes and records D104-L/D106-L grammar decisions.
src/agents/contexts/exchanges/request-review.ts Updates request_review content formatting to new “Review:” grammar.
src/agents/contexts/exchanges/request-response.ts Updates diagnostic header level to match new grammar.
src/agents/contexts/exchanges/request-choices.ts Implements ★ answer echo grammar for multi-select responses.
src/agents/contexts/exchanges/request-choice.ts Implements ★ answer echo grammar for single-choice responses.
src/agents/contexts/exchanges/request-answer.ts Implements ★ answer grammar for free-text responses.
src/agents/contexts/exchanges/render-honesty.ts New helper to verify details-leaf visibility vs declared elisions.
src/agents/contexts/exchanges/present-review-set.ts Reworks review-set content formatting to proposed-code neighborhood grammar + elision list.
src/agents/contexts/exchanges/present-question.ts Reworks question content formatting + provides elision list for honesty checks.
src/agents/contexts/exchanges/option-echo.ts New shared option-echo formatter and terminal-state formatter.
src/agents/contexts/exchanges/design-permutations.md Adds design exploration doc for transcript/content grammar.
src/agents/contexts/exchanges/design-permutations-neighborhood.md Adds neighborhood-grammar doc for review-set content.
src/agents/contexts/exchanges/tests/present-review-set.test.ts Adds tuple goldens + render-honesty invariant coverage for present_review_set.
src/agents/contexts/exchanges/tests/present-question-honesty.test.ts Adds render-honesty invariant coverage for present_question.
src/agents/contexts/exchanges/tests/exchange-renderer-inventory.test.ts Updates inventory to tuple goldens and adds present_question content golden.
src/agents/contexts/exchanges/snapshots/present-review-set.md Removes old snapshot (superseded by tuple snapshots).
src/agents/contexts/exchanges/snapshots/present-review-set-trailing-group-changes-tuple.md New tuple snapshot for trailing existing-edge group + changes-requested review.
src/agents/contexts/exchanges/snapshots/present-review-set-rejected-tuple.md New tuple snapshot for rejected review tuple.
src/agents/contexts/exchanges/snapshots/present-review-set-accepted-tuple.md New tuple snapshot for accepted review tuple.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-unavailable-choices.md Updates unavailable formatting to new header conventions.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-unavailable-choice.md Updates unavailable formatting to new header conventions.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-review.md Updates review formatting to new “Review:” grammar.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-question-choices-tuple.md New tuple snapshot for question→choices.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-question-choice-tuple.md New tuple snapshot for question→choice.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-question-answer-tuple.md New tuple snapshot for question→answer.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-present.md Removes old snapshot (superseded by tuple inventory).
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-present-question-content.md New snapshot for present_question model-facing content.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-diagnostic.md Updates diagnostic formatting to new header conventions.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-choices.md Updates request_choices rendering to option-echo grammar.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-choice.md Updates request_choice rendering to option-echo grammar.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-cancelled-review.md Updates cancelled review formatting to new conventions.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-cancelled-answer.md Updates cancelled answer formatting to new conventions.
src/agents/contexts/exchanges/snapshots/exchange-renderer-inventory-answer.md Removes old snapshot (superseded by tuple inventory).
src/agents/contexts/data-model/workspace/workspace-context.ts Switches to md-pen primitives; keeps house composition via joinMarkdownBlocks.
src/agents/contexts/data-model/spec/spec-output.ts Switches to md-pen primitives for headings and bullets.
src/agents/contexts/data-model/spec/spec-context.ts Switches to md-pen primitives for lists/tables.
src/agents/contexts/data-model/plan/plan-output.ts Switches to md-pen primitives for headings and bullets.
src/agents/contexts/data-model/graph/graph-slice.ts Switches to md-pen table primitive.
src/.pi/extensions/exchanges/TOPOLOGY.md Updates tool family ownership + D104-L renderResult rule + D106/D107 notes.
src/.pi/extensions/exchanges/shared/markdown.ts Removes unused local markdown escaping helper.
src/.pi/extensions/exchanges/shared/choices-editor.ts Centralizes comment requirement predicate use; threads answered options echo.
src/.pi/extensions/exchanges/shared/choice-source.ts Enforces comment requirement for Other/None; threads answered options echo.
src/.pi/extensions/exchanges/schemas/TOPOLOGY.md Updates boundary chain notes for typed constructors and read-side recognizers.
src/.pi/extensions/exchanges/schemas/request.ts Adds answered.options echo + shared comment predicate; updates invariants.
src/.pi/extensions/exchanges/schemas/present.ts Requires proposed_code on review-set node drafts.
src/.pi/extensions/exchanges/schemas/params.ts Trims and rejects blank present headings at params boundary.
src/.pi/extensions/exchanges/request-response.ts Threads options echo through UI collectors (question/candidates).
src/.pi/extensions/exchanges/present-review-set.ts Assigns proposed codes before persistence and dry-run validation.
src/.pi/extensions/exchanges/present-question.ts Documents ceiling: renderResult is markdown pass-through of content.
src/.pi/extensions/tests/exchanges-schemas.test.ts Adds tests for new predicate, proposed_code, options echo, and heading trimming.
src/.pi/extensions/tests/exchanges-present-request.test.ts Updates end-to-end present/request expectations for new grammar and payloads.
src/.pi/extensions/tests/exchanges-extension.test.ts Updates renderResult expectations per D104-L revision.
src/.pi/extensions/tests/exchanges-editor-envelope.test.ts Updates editor envelope reconstruction to supply answered options echo.
memory/PLAN.md Updates exchange-rendering frontier metadata (Linear/branch pointer) and notes.
memory/cards/exchange-rendering--sweep.md Adds sweep ledger capturing row inventory, DoD, and verification plan.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +34
if (input.status === 'answered' && input.review === 'request_changes') {
return {
...base,
unavailable: { message: input.message ?? 'request_review requires interactive UI' },
});
tool_meta: { ...base.tool_meta, next: 'capture_review' },
answered: { decision: input.review, comment: input.comment ?? '' },
Comment on lines +29 to +48
return collectPrimitiveLeaves(details)
.filter(({ path }) => !matchesAny(path, elisionPatterns))
.filter(
({ path, value }) =>
!renderedText.includes(value) && !hasRenderedRepresentation(path, renderedText, options),
)
.map(({ path, value }) => ({ path, value }));
}

function hasRenderedRepresentation(
path: string,
renderedText: string,
options: RenderHonestyOptions,
): boolean {
const representations = options.representations ?? {};
for (const [pattern, tokens] of Object.entries(representations)) {
if (matchesPath(path, pattern) && tokens.some((token) => renderedText.includes(token))) return true;
}
return false;
}
@lunelson lunelson changed the title FE-1123: Validate single-select none comments at acceptance FE-1123: Structured-exchange rendering: fix, unify, and lock the transcript renderer family Jul 3, 2026
@lunelson lunelson marked this pull request as ready for review July 3, 2026 12:18
Copilot AI review requested due to automatic review settings July 3, 2026 12:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 128 out of 134 changed files in this pull request and generated no new comments.

@graphite-app graphite-app Bot changed the base branch from ln/fe-1122-walkthrough-fixes to graphite-base/287 July 3, 2026 12:46
lunelson and others added 12 commits July 3, 2026 14:03
Reject Other/None single-select responses without a comment at the session acceptance boundary so bad answers return the friendly exchange error instead of relying on projection parsing.
Move the non-empty multi-select answer invariant to session acceptance so empty choices return the exchange boundary error shape instead of a projection parse failure.
Centralize the Other/None/request_changes comment rule beside the request schemas and route schema refinements, UI collection, and session acceptance through the same predicate.
Move non-empty trimmed heading enforcement into the present tool parameter schemas so invalid headings fail before projection construction.
Convert present exchange projections to typed branch construction so write-side detail creation no longer revalidates objects it just built.
Convert request exchange projections to typed status branches so answered details require their payloads statically instead of relying on constructor-time schema parses.
Record the structured-exchange validation boundary decision and update topology docs so projections are typed detail constructors while schemas remain boundary/read-back recognizers.
…(D104-L)

Head slice of the exchange-rendering sweep: renderResult consumes
result.details via a pure rounded-box projection instead of re-rendering
the model-facing markdown string. Adds the render-honesty helper +
elision-list convention, live/persisted metamorphic test, dual-family
snapshots (content vs renderResult), shared fixtures, and a
dev:components static preview entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Design session outcomes: SPEC oracle design revised to tuple-form goldens
(present + request results together); design-permutations.md captures the
content-register grammar exploration (★ pattern: h2 Question/Answer frames,
em-dash rationale, numbered answer echo with struck rejected options) and
the review-set evaluation. Sweep ledger restructured around two new proving
rows; content-grammar scope card covers the ★ formatters, answered-payload
option echo, and tuple goldens. Consumed head-slice card deleted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restating original option numbers inside checkbox items resolves the
numbering-vs-checkbox tension and handles Other write-ins naturally.
Strike variant stays the single-choice alternate; final pick at build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…k rejected

The composed stack settles the echo grammar: selection state, original
numbering, and item-level rejection legibility in one line; one grammar
for choice and choices; Other write-ins unnumbered and unstruck.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…trings

Route through the existing src/agents/shared/markdown.ts wrapper; use
md-pen escape for untrusted option/answer text embedded in the grammar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lunelson and others added 18 commits July 3, 2026 14:03
…ntent

Simplest current solution: TUI renderResult feeds the formatter's content
markdown to pi-tui's Markdown component (wraps + renders inline styles for
free); details-built TUI enhancement stays a named ceiling. renderResult
golden family + metamorphic leg suspended; render-honesty retargets the
details→content pipeline. Ledger row rewritten; revert rides the
content-grammar slice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pass-through

Builder slice: D106-L answered-payload option echo (schema recognizer +
projection constructors), ★ grammar formatters, tuple content goldens.

Snapshot-review batch: terminal states to h2 ## Response; comments as bare
blockquotes (no ## Comment heading); free-text answers plain, not quoted;
review renders as "## Review: accepted|changes requested|rejected"; option
content bolded in questions; Other/None/comment affordances elided from
content (collection-UI concerns, named in the elision list); write-ins join
the checkbox echo as "- [x] *Other:* …"; shared option-echo/terminal
formatters extracted.

renderResult pass-through row built per revised D104-L: box renderer, its
golden, and metamorphic test retired; render-honesty helper moved beside
the content formatters and retargeted at details → content; preview entry
shows the Markdown render.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Lu Nelson <ln@hash.ai>
Signed-off-by: Lu Nelson <ln@hash.ai>
Signed-off-by: Lu Nelson <ln@hash.ai>
Signed-off-by: Lu Nelson <ln@hash.ai>
Centralize provider system-prompt carrier handling so prompt injection and debug mirroring cannot silently disagree across provider payload shapes.
…n sweep rows

- SPEC: add D108-L (src/exchanges consolidation), repoint D37/D41/D96/D104-107-L and I26/I53-L paths; prune framing_as quadruple record (D7-L/I7-L rows), retired A27-L row, duplicate Subagent lexicon entry, and the 13-row lexicon graveyard (Strategy/Lens kept as suspended)
- PLAN + sweep ledger: fix stale boundary-test and schema paths; execution pointer now names the three open-row scope cards
- TOPOLOGY files (exchanges, .pi/extensions, agents/contexts, schemas, projections): reconcile to consolidated layout
- New cards: present_candidates, STRUCTURAL_ILLEGAL/recovery, renderCall coverage (independent earned closures; renderCall builds last)
Signed-off-by: Lu Nelson <ln@hash.ai>
Signed-off-by: Lu Nelson <ln@hash.ai>
@lunelson lunelson force-pushed the graphite-base/287 branch from 6e26378 to 6fbf523 Compare July 3, 2026 14:03
@lunelson lunelson force-pushed the ln/fe-1123-exchange-rendering branch from d692512 to d18062e Compare July 3, 2026 14:03
@graphite-app graphite-app Bot changed the base branch from graphite-base/287 to next July 3, 2026 14:04
@graphite-app

graphite-app Bot commented Jul 3, 2026

Copy link
Copy Markdown

Merge activity

  • Jul 3, 2:04 PM UTC: Graphite rebased this pull request, because this pull request is set to merge when ready.

@lunelson lunelson merged commit 5a46e9c into next Jul 3, 2026
12 checks passed
@lunelson lunelson deleted the ln/fe-1123-exchange-rendering branch July 3, 2026 14:16
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