# Final merged-head review round 3

HEAD f21775904c4e1c647a0b4279f752013208694bb2; BASE4812dcad02.

FRICTION

- Final-head integrated evidence and CI remain pending. Earlier recordings do not prove this head; this is an evidence gate, not a code defect.
- No files changed, and no push, comment, watch, or merge performed.

VERDICT: **MERGE**

Independently reviewed [f2177590](https://github.com/pingdotgg/t3code/commit/f21775904c4e1c647a0b4279f752013208694bb2) against [4812dcad02](https://github.com/pingdotgg/t3code/commit/4812dcad02) for [#24008](https://github.com/pingdotgg/t3code/pull/24008). No concrete blocking bugs found.

- Current composer trims the input before planning; current Claude effort formatting preserves slash commands, and the adapter forwards their instructions.
- Command boundaries correctly distinguish `/compact instructions` from `/compactfoo`. Full-history and existing queue behavior remain intact.
- Fixed, anchored regex examines a bounded prefix: constant work, no backtracking risk. With 3,000 whitespace-delimited tokens, one million calls took 19–35 ms across ordinary, instructed, and near-match inputs.
- Regression tests meaningfully assert compaction and dispatch decisions. All **45 tests passed**; scoped lint and diff whitespace checks passed.
- Sensitive paths reviewed: automatic compaction, queue dispatch, prompt transformation, and Claude message construction. No wire-contract, persistence, permission, or dependency changes. Web and desktop share the fix; mobile has no caller of this planner.

Merge recommendation remains subject to final-head evidence and CI completion.

FRICTION: none blocked me. The budget was tight, so I checked only callers and providers that relate to `/compact`. I did not do a full trace of the composer.

**VERDICT: MERGE.** Reviewed head [f217759](https://github.com/pingdotgg/t3code/commit/f21775904c4e1c647a0b4279f752013208694bb2) against base `4812dcad02` (origin/main). The base is the actual merge-base. [#24008](https://github.com/pingdotgg/t3code/pull/24008) replaces [#20236](https://github.com/pingdotgg/t3code/pull/20236).

**Diff:** 2 files, +20/−9, the same fix as before. In `apps/web/src/components/ChatView.logic.ts:936`, `COMPACT_COMMAND_PATTERN = /^\/compact(?:\s|$)/i` replaces the exact match on `"/compact"` in `planComposerTurn` (line 1548). When the session is stale, a typed `/compact` with instructions no longer gets an automatic bare compaction queued in front of it. That had meant two compactions and two charges.

**Bugs:** none found.
- **Failing sequence before the fix:** stale session → user types `/compact keep the API notes` → the old exact match fails → a bare compaction runs first, then the instructed one. After the fix it is sent once with `auto` dispatch.
- **The boundary is correct:** `/compactfoo` still gets the automatic compaction. This matches the existing parser `parsePiCompactCommand` (`packages/provider-pi/src/server/commands.ts:16-24`): `/compact` followed by whitespace or the end of the text counts, anything else does not.
- **New upstream code doesn't affect this:** the new composer and Claude adapter code in main don't touch this decision. `ChatComposer.tsx:1318` and `:3655` only gate the mobile "open composer" label and button on `resumeCompactionTokens`, which is unrelated. The server's exact-`/compact` checks (Orchestrator, ProviderTurnStartService, ProjectionStore) are about how commands are recognised. This change is client-side and doesn't change them.

**Sensitive paths:** none. The change is client-only planning logic, with no contract, server, auth or persistence changes.

**Regex cost:** the pattern is anchored with a fixed prefix and one alternation, so there is no backtracking and the cost is constant. Benchmark with node on a 12k-character input (about 3000 tokens):
- matching input: ~61 ns per call
- non-matching input: ~31 ns per call

That's negligible.

**Tests:** `vp test run apps/web/src/components/ChatView.logic.test.ts -t planComposerTurn` passed 4 tests (41 skipped by the filter). The table-driven cases are meaningful: `hello` and `/compactfoo` still compact first, while `/COMPACT`, `/compact <args>` and `/compact\n  tests` don't. The `shouldQueueBehindActiveRun: false` assertion was added on purpose.

**Compatibility (not blocking):**
- A `/compact` with instructions now relies on the provider to run the compaction itself. Pi parses the arguments and Claude's slash command handles them. For Codex I found no adapter-side parsing of `/compact <args>`. It may reach Codex as plain text and skip compaction, but that is about how each provider handles `/compact` and was already true before this change.
- One small mismatch: this regex ignores case, while Pi's parser is case-sensitive, so `/COMPACT foo` on Pi would skip compaction. It's very unlikely and not a blocker.

**Evidence still pending:** CI and bot reviews for this exact head were not checked here; the parent needs to confirm them. I didn't push, comment, watch or merge anything.


