Repository navigation
fix(composer): compact context without clearing the draft - #363
Merged
Merged
Conversation
Compact worked by overwriting the composer draft with "/compact" and submitting it, so the button was disabled whenever the composer had content. Send "/compact" as its own turn from ChatView instead: it never reads or clears the draft and omits composerDraftRevision so the server keeps its autosaved copy. The context meter and the resume-compaction banner both use the new path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Upstream fixes the same bug in `pingdotgg#11103`, which depends on its server-side compaction command in `pingdotgg#9293`. Record that in the comment so the intake of that chain replaces this function. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 19, 2026
incognitojam
added a commit
that referenced
this pull request
Sep 25, 2026
Some intake commits carry `Intake-Note:` trailers, but no script, report, or runbook reads them. I reviewed all 50. Most record how a merge conflict was resolved and need no follow-up. Two are waiting on upstream, and several show fork behavior that the fork ledger doesn't cover. This adds both to the places intake already reports on. **Tracked upstream PRs** (`.github/upstream-tracked-prs.json`) - `11103` (merged upstream, not yet taken) replaces the fork's draft-preserving compact action from fork #363. The intake note on the `9293` import kept the fork version "until upstream `11103` lands". - `10411` (still open upstream) was imported early from its unmerged commits and renamed for styal in fork #425. When upstream merges it, the queue takes it and has to reconcile it with that import. **Fork ledger** (`data-import-from-t3-code`) Fork #306 derives `thread.turn-prompt-linked` events so imported user prompts stay attached to their turns. Four intake commits (`8368`, `8600`, `9715`, `9726`) preserved that behavior while resolving conflicts in the live coalescing, replay, and snapshot paths, but the ledger didn't mention it. The entry now lists #306, states the invariant, and adds the projection pipeline, snapshot query, and live event coalescer to `upstream_paths`, so upstream changes to those files point reviewers to this feature. The other behavior those notes preserved, excluding imported messages from a thread's latest user message time, is now in upstream too (`NOT GLOB 'import:*'`), so it stays out of the ledger. **Validation** - `node scripts/upstream-tracked-prs-report.ts` lists `11103` as pending (merged 3.1 days ahead of the fork's last reconciled upstream integration) and `10411` as open, with each reason shown. - `vp run --filter @t3tools/scripts ledger:check` validates all 64 ledger entries, and the three new `upstream_paths` exist on upstream main. - `vp test run scripts/upstream-tracked-prs.test.ts scripts/fork-feature-ledger.test.ts` passes (12 tests). --- Written by an agent (Claude Code, claude-opus-5-5).
incognitojam
pushed a commit
that referenced
this pull request
Sep 29, 2026
Fork adaptation: Upstream's onCompactContext replaces the fork's draft-preserving version from fork #363. It stays a memoized callback declared before the fork's resume-compaction banner, which also calls it, and a successful compaction still records the thread visit baseline and acknowledges a woken thread, as the fork's send path does. (cherry picked from commit ef6fa11) Upstream-PR: 11103
incognitojam
pushed a commit
that referenced
this pull request
Oct 2, 2026
…pingdotgg#11673) (cherry picked from commit cc839c4) Fork adaptation: Queued messages carry the fork's GitHub issue contexts: queuing takes them from the composer, sending a queued message appends them like a direct send, and Stop or cancel returns them to the composer; the queued row counts them as context items. Queuing and sending clear the composer with the fork's composer draft sync mark, so retained model and mode preferences do not resurrect the cleared draft. The send button keeps the fork's disabled-reason tooltip while it queues beside Stop, and the fork's compact action, which no longer lives in ChatView (fork #363), is not reintroduced. The timeline keeps the fork's review findings and standalone activity rows beside the queued message row. The ledger records the issue context feature from fork #31. Upstream-PR: 11673 Fork-Feature: github-issue-thread-context, composer-draft-sync
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
TL;DR: Compact context and the resume banner's Compact now work while a draft is in the composer, and the draft is left untouched.
/compactis sent as its own turn instead of being typed into the draft. Upstream has an equivalent fix that depends on a larger compaction chain; this function gets replaced when that chain is taken in.Problem
Compact context in the context meter, and Compact on the resume-compaction banner, were disabled whenever the composer held a draft, with the tooltip "Send or clear your draft before compacting". That was deliberate: compacting worked by overwriting the draft with
/compactand submitting it through the normal send path, so any half-written message would have been destroyed.Fix
ChatViewnow has a dedicatedonCompactContextthat sends/compactas its own turn. It never reads or clears the composer draft, and it omitscomposerDraftRevision, so the server does not clear its autosaved copy of the draft either. The draft check is removed fromcompactDisabled, and both entry points (context meter and resume banner) call the new function.ChatComposerno longer injects/compactinto the draft, which also removes thecompactContexthandle method and the pasted-image-compression guard that only existed because compacting used to snapshot the draft.docs/user/providers-claude.mdgains one sentence saying compacting leaves a draft in place.Surfaces: web and desktop share this code. Mobile has no Compact button. Only the Claude provider offers compaction. The server and wire contracts are unchanged.
Relationship to upstream
Upstream fixes the same bug with the same design in
pingdotgg/t3code#11103. That change cannot be taken on its own: it edits code introduced bypingdotgg/t3code#9293, which moves compaction into a server-side command and adds it for Codex, OpenCode and mobile, and is followed bypingdotgg/t3code#9623,pingdotgg/t3code#10112andpingdotgg/t3code#11107. This PR is a fork-written fix for the current client-side/compactpath and is not a port of any of them, so it does not mark them as taken in. When that chain is taken in, replaceonCompactContextinChatView.tsxwith the upstream version; the code comment says the same. For that reason there is no fork feature ledger entry.Before / after
Same thread, same draft in the composer, context meter open.
After clicking Compact context with the draft present:
/compactis sent as its own message and the draft is still in the composer. (Claude answered "Not enough messages to compact" here because this small thread had already been compacted a moment earlier.)Verification
Exercised in a headless Chromium against an isolated dev server (worktree-local state seeded from a snapshot), in a fresh Claude Sonnet 5 thread in a scratch project:
/compactuser message and the compaction turn ran to completion ("Worked for 31s").Focused checks:
tsgo --noEmitforapps/web,vp linton the changed files, andContextWindowMeter.test.tsx/ComposerBannerStack.test.tsxpass.Not verified: the desktop Electron shell was not run separately (it wraps the same web code), and the resume-compaction banner's Compact button was not clicked in the browser because the scratch thread was too small to trigger the banner; it calls the same function as the meter button.
Written by an agent (Claude Code, claude-fable-5-1).