fix(clients): answer history no longer shows provider context from review comments #35897
main fromrefs/pull/35897/head·merged by juliusmarminge View on GitHubReview item 1 was correct: the earlier helper removed every <t3_context version="1">…</t3_context> span, so XML a user typed into an answer was lost, and an answer that was only that XML displayed as empty. The helper now proves an envelope came from provider projection before removing it. projectPendingUserInputAnswer projects each chip separately with projectComposerContextForProvider, which writes [Kind: label; ref=<id>] + \n\n<t3_context version="1">\n<context kind="…" id="<id>"… … </t3_context>. composerContextProviderTextForDisplay walks the provider markers, and for each it checks that the envelope prefix starts right after the marker and that the entry's id attribute equals the marker's ref (escaped as escapeAttribute escapes it). Only then does it replace marker plus envelope with [Kind: label], cut at the first </t3_context>; payload text is escaped so that tag cannot appear inside an entry. Everything else, including typed XML and markers with no envelope, is returned unchanged, as on main. The reviewer's two examples now display in full, so hasQuestionAnswer stays true and the preview shows the answer. The existing repro test case gained an assertion that typed envelope XML stays unchanged. A throwaway test (not committed) ran real projectPendingUserInputAnswer output with two review-comment chips, one comment containing </t3_context>, through getQuestionAnswerText and got 'See [Review comment: notes.md L2] and [Review comment: notes.md L5] please'. Worst case on adversarial input: the marker regex /[([A-Z][^[]:;\n]): ([^[];\n]); ref=([^[]\s]+)]/g has character classes that cannot cross '[' or ']', so its scan is close to linear. Each marker then gets one fixed-prefix startsWith, one indexOf for the closing quote and one for the closing tag. Consumed spans advance the cursor and matches before it are skipped, so total work stays about linear in the answer's length.
Fixes pingdotgg/t3code#35843
Reproduction on main#
Commit 95cb068c10 (origin/main). Ran T3CODE_DEV_SEED=0 vp run dev with a fresh database and added a scratch git project with one uncommitted line in notes.md. Started a thread on the Replay (dev) provider's question scenario. That scenario's question is choice-only, so as a temporary, uncommitted test fixture I pointed it at a copy of its transcript with the enum removed, making the question free-text. Answer submission, storage and display ran as they are on main. In the web client (headless Chromium via Playwright), I typed 'See my note: ' into the answer, added a file comment 'Rename this to something clearer' on notes.md line 2 (the chip 'notes.md L2' appeared in the answer), and pressed Submit. The answered-question work-log row read 'See my note: [Review comment: notes.md L2; ref=review-comment_file-comment-…] <context kind="review-comment" …> file: notes.md range: L2 (1-1) section: File comment comment: Rename this to something clearer md: line changed '. Expanding the row showed the same block as multi-line raw text under the question. A plain answer is unaffected because it contains no envelope. The failing unit test on factory/repro-35843 shows the same thing at the shared helpers.
Evidence#
Real web client, Chromium, 1280×800, light theme, fresh synthetic databases. Start a free-text Replay question, type “See my note: ”, add a file comment “Rename this to something clearer” on notes.md L2, submit the answer with its chip, then expand answer history.
Proven: the scenario fails on base and passes on head. Base displays the internal context XML, comment text, and code; head retains the user's words and readable comment mention without the envelope.
| Before — 95cb068c10 | After — bb43f3bb61 | |
|---|---|---|
| Result | Failed: context envelope found in answer history | Passed: no envelope; readable answer retained |
| Submitted chip | ![]() | ![]() |
| Summary | ![]() | ![]() |
| Expanded history | ![]() | ![]() |
| Recording | Before interaction | After interaction |
Scenario source · Temporary startup fixture patch. Apply the patch before running the scenario; it removes the replay question's enum identically on both sides. Neither artifact was committed.
Not shown:
- Desktop and mobile were not run; this proof covers the real web client using the shared answer-history helper.
- Literal user-authored XML preservation and other context kinds were not exercised; this scenario targets the reported review-comment answer.
Tests#
vp test run packages/client-runtime/src/work-log/userInput.test.ts packages/shared/src/composerContextReferences.test.ts: 2 files, 40 tests passed. A throwaway test (deleted, not committed) ran real projectPendingUserInputAnswer output with two review-comment chips through getQuestionAnswerText: passed, output shown in summary. vp run check:changed: format, lint, knip, typecheck (35 packages) and tests (3 files) all pass.
Not in this change#
- Answers are still stored in provider form on the server. Storing the composer form plus records, as normal chat messages do, would let clients render real chips, but that is a contract and server change.
- An answer chip whose record is missing still shows its raw markdown t3-context link, which is unchanged from main.
- The user's own text is not escaped when an answer is projected for the provider, so a user who types an exact marker followed by a matching envelope is indistinguishable from projected output. That behaviour was already on main and is out of scope here.
Who did the work#
- Written by Claude Opus 5.5, in Claude Code
- Reviewed by GPT-6.1 Sol, in Codex, and by Claude Opus 5.5, each on its own
- Proof captured by GPT-6.1 Sol and checked by Claude Opus 5.5
Run by the t3code factory in T3 Code.
- 1
github-actions[bot](GitHub profile, opens in a new tab) added labelsvouch:trusted
tanstack-source added labelsbug
github-actions[bot](GitHub profile, opens in a new tab) added labelssize:M
Approvability#
Verdict: Approved at
bb43f3bMacroscope's review found this PR approvable — Answer histories and previews now show readable context labels instead of provider-context envelopes. The change is limited to display formatting and leaves stored answers and provider inputs unchanged.
You can add or adjust custom eligibility rules. [Learn more](https://docs.macroscope.com/approvability#example-custom-eligibility-rules).Thread transfer impact#
✅ Thread transfer remains within every enforced ceiling.
ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful
mainmeasurement shown below.Provider Metric Main baseline This PR Impact PR ceiling Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅ Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅ Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅ Codex Live turn WebSocket decoded 21.5 KiB 21.5 KiB 0 B (0.0%) 24.4 KiB ✅ Codex Live turn messages 1 1 0 (0.0%) 8 ✅ Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅ Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅ Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅ Claude Live turn WebSocket decoded 21.9 KiB 21.9 KiB 0 B (0.0%) 24.4 KiB ✅ Claude Live turn messages 1 1 0 (0.0%) 8 ✅ Other scenarios#
All 64 scenario measurements match
main.All 64 scenario measurements
Provider Scenario Metric Main baseline This PR Impact PR ceiling Codex short turn resumeWebSocket decoded10.5 KiB 10.5 KiB 0 B (0.0%) 12.7 KiB ✅ Codex short turn resumeWebSocket messages2 2 0 (0.0%) 2 ✅ Codex long turn running, cold openHTTP decoded281.7 KiB 281.7 KiB 0 B (0.0%) 302.7 KiB ✅ Codex long turn running, cold openrows75 75 0 (0.0%) 75 ✅ Codex long turn running, history pageHTTP decoded92.4 KiB 92.4 KiB 0 B (0.0%) 107.4 KiB ✅ Codex long turn running, history pagerows75 75 0 (0.0%) 75 ✅ Codex long turn finished, cold openHTTP decoded381.5 KiB 381.5 KiB 0 B (0.0%) 410.2 KiB ✅ Codex long turn finished, cold openrows151 151 0 (0.0%) 151 ✅ Codex long turn finished, socket cold openWebSocket decoded381.6 KiB 381.6 KiB 0 B (0.0%) 410.2 KiB ✅ Codex long turn finished, socket cold openWebSocket messages2 2 0 (0.0%) 2 ✅ Codex long turn finished, socket cold openrows151 151 0 (0.0%) 151 ✅ Codex long turn finished, work pageHTTP decoded186.2 KiB 186.2 KiB 0 B (0.0%) 200.2 KiB ✅ Codex long turn finished, work pagerows150 150 0 (0.0%) 150 ✅ Codex idle thread resumeWebSocket decoded65 B 65 B 0 B (0.0%) 200 B ✅ Codex idle thread resumeWebSocket messages1 1 0 (0.0%) 1 ✅ Codex fleet shell snapshotHTTP decoded42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅ Codex fleet shell snapshotrows27 27 0 (0.0%) 27 ✅ Codex fleet shell subscribeWebSocket decoded65 B 65 B 0 B (0.0%) 200 B ✅ Codex fleet shell subscribeWebSocket messages1 1 0 (0.0%) 1 ✅ Codex fleet shell resume checkHTTP decoded18 B 18 B 0 B (0.0%) 100 B ✅ Codex fleet shell resume checkrows0 0 0 0 ✅ Codex stale shell reloadHTTP decoded42.4 KiB 42.4 KiB 0 B (0.0%) 53.7 KiB ✅ Codex stale shell reloadrows27 27 0 (0.0%) 27 ✅ Codex stale shell resumeWebSocket decoded140 B 140 B 0 B (0.0%) 400 B ✅ Codex stale shell resumeWebSocket messages2 2 0 (0.0%) 2 ✅ Codex stale todo list cold openHTTP decoded72.4 KiB 72.4 KiB 0 B (0.0%) 83.0 KiB ✅ Codex stale todo list cold openrows75 75 0 (0.0%) 75 ✅ Codex stale todo list cold opennodes2 2 0 (0.0%) 4 ✅ Codex stale todo list cold opensubagents2 2 0 (0.0%) 4 ✅ Codex stale todo list cold openplans1 1 0 (0.0%) 2 ✅ Codex stale todo list cold openproviderTurns1 1 0 (0.0%) 2 ✅ Codex stale todo list cold opencheckpoints1 1 0 (0.0%) 2 ✅ Claude short turn resumeWebSocket decoded10.6 KiB 10.6 KiB 0 B (0.0%) 12.7 KiB ✅ Claude short turn resumeWebSocket messages2 2 0 (0.0%) 2 ✅ Claude long turn running, cold openHTTP decoded283.3 KiB 283.3 KiB 0 B (0.0%) 302.7 KiB ✅ Claude long turn running, cold openrows75 75 0 (0.0%) 75 ✅ Claude long turn running, history pageHTTP decoded93.4 KiB 93.4 KiB 0 B (0.0%) 107.4 KiB ✅ Claude long turn running, history pagerows75 75 0 (0.0%) 75 ✅ Claude long turn finished, cold openHTTP decoded384.2 KiB 384.2 KiB 0 B (0.0%) 410.2 KiB ✅ Claude long turn finished, cold openrows151 151 0 (0.0%) 151 ✅ Claude long turn finished, socket cold openWebSocket decoded384.3 KiB 384.3 KiB 0 B (0.0%) 410.2 KiB ✅ Claude long turn finished, socket cold openWebSocket messages2 2 0 (0.0%) 2 ✅ Claude long turn finished, socket cold openrows151 151 0 (0.0%) 151 ✅ Claude long turn finished, work pageHTTP decoded188.1 KiB 188.1 KiB 0 B (0.0%) 200.2 KiB ✅ Claude long turn finished, work pagerows150 150 0 (0.0%) 150 ✅ Claude idle thread resumeWebSocket decoded66 B 66 B 0 B (0.0%) 200 B ✅ Claude idle thread resumeWebSocket messages1 1 0 (0.0%) 1 ✅ Claude fleet shell snapshotHTTP decoded43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅ Claude fleet shell snapshotrows27 27 0 (0.0%) 27 ✅ Claude fleet shell subscribeWebSocket decoded66 B 66 B 0 B (0.0%) 200 B ✅ Claude fleet shell subscribeWebSocket messages1 1 0 (0.0%) 1 ✅ Claude fleet shell resume checkHTTP decoded18 B 18 B 0 B (0.0%) 100 B ✅ Claude fleet shell resume checkrows0 0 0 0 ✅ Claude stale shell reloadHTTP decoded43.0 KiB 43.0 KiB 0 B (0.0%) 53.7 KiB ✅ Claude stale shell reloadrows27 27 0 (0.0%) 27 ✅ Claude stale shell resumeWebSocket decoded140 B 140 B 0 B (0.0%) 400 B ✅ Claude stale shell resumeWebSocket messages2 2 0 (0.0%) 2 ✅ Claude stale todo list cold openHTTP decoded73.4 KiB 73.4 KiB 0 B (0.0%) 83.0 KiB ✅ Claude stale todo list cold openrows75 75 0 (0.0%) 75 ✅ Claude stale todo list cold opennodes2 2 0 (0.0%) 4 ✅ Claude stale todo list cold opensubagents2 2 0 (0.0%) 4 ✅ Claude stale todo list cold openplans1 1 0 (0.0%) 2 ✅ Claude stale todo list cold openproviderTurns1 1 0 (0.0%) 2 ✅ Claude stale todo list cold opencheckpoints1 1 0 (0.0%) 2 ✅ Baseline:
ed2a319· PR result:bb43f3b· Source CI: successScenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review.
Walkthrough
-
String answers in the work log now use a shared formatter to remove matching provider context envelopes and render review-comment markers without reference IDs. Tests cover history text, previews, and unmatched XML.
Changes: Answer display
Layer / File(s) Summary Format provider context for display
packages/shared/src/composerContextReferences.tsA shared function removes a closed context envelope when it follows a marker with a matching reference ID. It renders the marker without the reference ID and preserves unmatched text. Use display text in work-log answers
packages/client-runtime/src/work-log/userInput.ts,packages/client-runtime/src/work-log/userInput.test.tsString answers use the shared formatter. Tests check history and preview output, preservation of the chip label, and unchanged standalone XML. Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Low
Suggested reviewers:
maria-rcks,t3dotgg
Merge Risk:
Minimal · up tobb43f-
This change hides generated context blocks in answer history while keeping the review-comment label. Stored answers are not changed, so merge risk is minimal.
Pre-merge checks:
4-
Check name Status Explanation Title check The title names the fix: answer history no longer shows provider context from review comments. It matches the main change in userInput.ts and composerContextReferences.ts, which hide the generated t3_… Linked Issues check Issue #35843requires hiding the generated provider block from answer history and row previews for review-comment answers, keeping the answer readable, and preserving plain-text answers. …Out of Scope Changes check The whole-PR diff against the merge base 95cb068c10 touches the shared helper composerContextReferences.ts (new function only), the client-runtime userInput.ts (one-line routing change in getQuestionA… Description check The description follows the template sections (Problem, Change, Scope, Verification) and is detailed. It states the problem and reproduction on main, links issue #35843, and documents the change: a pr…Full details: Title check
-
Explanation
The title names the fix: answer history no longer shows provider context from review comments. It matches the main change in userInput.ts and composerContextReferences.ts, which hide the generated t3_context envelope and keep the review-comment label. The title follows the conventional commit form the template asks for.
Full details: Linked Issues check
-
Explanation
Issue
#35843requires hiding the generated <t3_context> provider block from answer history and row previews for review-comment answers, keeping the answer readable, and preserving plain-text answers. At head, composerContextProviderTextForDisplay (packages/shared/src/composerContextReferences.ts) replaces a provider marker plus its envelope with '[Kind: label]' only when the envelope starts right after the marker and its id attribute equals the marker ref. Everything else is returned unchanged. getQuestionAnswerText (packages/client-runtime/src/work-log/userInput.ts) now routes string answers through this helper, so the shared answer-display path covers history and previews. Plain strings with no envelope pass through unchanged. The reported test runs cover the helper and the question-answer display. Not independently verified: that every web, desktop, and mobile consumer calls getQuestionAnswerText, and the pending evidence section in the PR description. These do not change the coding verdict.
Full details: Out of Scope Changes check
-
Explanation
The whole-PR diff against the merge base 95cb068c10 touches the shared helper composerContextReferences.ts (new function only), the client-runtime userInput.ts (one-line routing change in getQuestionAnswerText), and userInput.test.ts (regression and preservation tests). Each change supports the
#35843objective. No unrelated files or behavior changes were identified in the reviewed evidence. Server-side storage is explicitly unchanged, which matches the issue scope.
Full details: Description check
-
Explanation
The description follows the template sections (Problem, Change, Scope, Verification) and is detailed. It states the problem and reproduction on main, links issue
#35843, and documents the change: a provider-envelope check tied to the marker ref, with typed XML and envelope-less markers left unchanged. Verification includes focused test runs (40 tests passed across 2 files), a throwaway test with two review-comment chips, and a check:changed run. Before/after screenshots and a recording are embedded, and the author lists model and harness. Remaining gaps: the Scope section does not say why this is a bug fix rather than a feature, and the Verification section lists desktop and mobile as not run. The description states these gaps openly. Both are minor, so the description is mostly complete.
-
Finishing Touches
-
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Recent review info-
Run configuration-
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: factory/issue-35843
- File: .coderabbit.config.ts
- Commit: bb43f3b
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
07cdb90f-de0f-431c-8908-1737f5104988
Commits-
Reviewing files that changed from the base of the PR and between 8b23382191ba7c7db69978d6a310a4244c566741 and bb43f3bb6160d39394b553e94b09b93656097d5c.
Files selected for processing: 3-
packages/client-runtime/src/work-log/userInput.test.tspackages/client-runtime/src/work-log/userInput.tspackages/shared/src/composerContextReferences.ts
Limit details: You’ve used all 10 included reviews currently available. Your 17 included PR review attempts over the past 7 days set your current allowance at 10 reviews per hour.
-
-
juliusmarminge merged this
afff0d3juliusmarminge closed this
Sign in to join this conversation.






macroscopeapp[bot](GitHub profile, opens in a new tab) approved these changes