Skip to content

fix(server): stop querying Claude context usage after turns - #8610

Merged
t3dotgg merged 1 commit into
mainfrom
t3code/investigate-claude-usage-limits
Aug 29, 2026
Merged

fix(server): stop querying Claude context usage after turns#8610
t3dotgg merged 1 commit into
mainfrom
t3code/investigate-claude-usage-limits

Conversation

@t3dotgg

@t3dotgg t3dotgg commented Aug 29, 2026

Copy link
Copy Markdown
Member

Claude queried detailed context usage after every completed turn. If native token counting failed, that query could trigger extra model requests.

This change stops the automatic detailed query. Completion now uses the final main assistant usage when available, keeps cumulative result usage as processed tokens, and falls back to the existing result, iteration, and stream snapshots.

Focused Claude adapter tests verify usage, cumulative totals, turn completion, and zero detailed context queries.

Tradeoff: the context meter omits its automatic compaction note because normal SDK messages do not expose the effective policy. Claude Code's automatic compaction behavior is unchanged.

Refs #7338

Built by GPT-5.6 Sol in the Codex harness.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 812f85ad-1a5a-4378-b552-dbc6ff570ddb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Aug 29, 2026
Comment thread apps/server/src/provider/Layers/ClaudeAdapter.ts
@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.3 KiB 13.3 KiB −9 B (−0.1%) 15.1 KiB
Codex Thread snapshot wire 6.9 KiB 6.9 KiB −6 B (−0.1%) 7.3 KiB
Codex Live turn WebSocket wire 6.4 KiB 6.4 KiB −3 B (−0.0%) 7.8 KiB
Codex Live turn WebSocket decoded 55.6 KiB 55.6 KiB 0 B (0.0%) 66.4 KiB
Codex Live turn messages 11 11 0 (0.0%) 21
Claude Total thread wire 13.3 KiB 13.3 KiB +24 B (+0.2%) 15.1 KiB
Claude Thread snapshot wire 6.9 KiB 6.9 KiB −4 B (−0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.4 KiB 6.5 KiB +28 B (+0.4%) 7.8 KiB
Claude Live turn WebSocket decoded 56.4 KiB 56.4 KiB +44 B (+0.1%) 66.4 KiB
Claude Live turn messages 10 11 +1 (+10.0%) 21

Baseline: 702a6ad · PR result: 73916c2 · Source CI: success

Scenario 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: 109.4 KiB
  • Claude decoded thread snapshot: 110.1 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a localized Claude adapter bug fix that removes unintended context-usage queries and adds targeted usage/compaction coverage without changing schemas, defaults, deployment, or sensitive paths. A separate unresolved Medium finding flags lost automatic-compaction metadata, leaving a correctness risk recorded for follow-up.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@t3dotgg
t3dotgg merged commit c131f28 into main Aug 29, 2026
22 checks passed
@t3dotgg
t3dotgg deleted the t3code/investigate-claude-usage-limits branch August 29, 2026 03:27
juliusmarminge added a commit that referenced this pull request Aug 29, 2026
Main's #8610 (stop querying Claude context usage after turns) only touches
the v1 ClaudeAdapter layers this branch replaces with orchestration-v2; the
v2 Claude adapter never issued the post-turn getContextUsage control query,
so the fix has no v2 counterpart to port. Keep the deletions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aorwall added a commit to aorwall/t3code that referenced this pull request Aug 29, 2026
Merges 58 upstream commits (`badae6a5c` → `6a9d9f988`, upstream v0.0.34
→ v0.0.36) through the `fork-upstream-merge` skill.

`merge-stats.mjs` reconciles exactly: **431 files landed** against **431
in the upstream range**, no gap to explain. Fork delta is 611 files.

## Conflicts

Three, plus one git resolved silently and wrongly.

- **`Sidebar.tsx`** — upstream replaced the project picker's
`Menu`/`MenuRadioGroup` with a searchable `Combobox` (pingdotgg#5931). Took
upstream's structure and re-applied only the
`FEATURES.projectManagement` gate on "New project", now carrying the `//
Fork:` marker it had been missing. Upstream has since grown the mobile
touch-target span itself, so the Mobile Touch Delta has nothing left to
re-apply here — one convergence, unprompted.
- **`ProviderSettingsPanel.tsx`** — upstream split provider settings
into list and editor (pingdotgg#8380, pingdotgg#8472), moving `ProviderLastChecked` and
the refresh button out of `headerAction` into the list footer. Took
upstream's and re-applied the gate as `!readOnly &&
FEATURES.serverAdministration`.
- **`pnpm-lock.yaml`** — took upstream's and re-ran `vp i`, which
restored the fork's `@t3tools/moatless-api` workspace edge.
- **`packages/contracts/src/orchestration.test.ts`** — auto-merged, no
marker, broken. Both sides appended `OrchestrationMessage` to the same
import list and the same `decodeOrchestrationMessage` const at different
offsets, so git took both. Surfaced as a parse error in lint, typecheck
and test at once. This is the case `merge-stats.mjs`'s
conflict-candidate list exists to catch.

`HostedBrowserFrame.tsx` (fork-only) also needed the `renderingActive`
prop pingdotgg#8567 made required. Upstream suspends a parked webview unless
background audio, PiP or a recording still needs it painted; a frame has
none of those to read and is the app's only copy of the preview page, so
it passes `true` and keeps today's behavior.

## Sweep

Five keyword hits, all false positives:

- `apps/web/src/connection/clientMetadata.ts` + test — reports the
client's OS/browser/device on connect (pingdotgg#8481). Auth-adjacent, but it
rides `ClientPresentation` on the relay and remote-bearer bootstraps;
the fork's primary environment sends none of it.
- `packages/client-runtime/src/relay/errorPresentation.ts` + test,
`connection/errors.test.ts` — explain DPoP failures (pingdotgg#8351). Relay only,
and T3 Connect is decided out.

## Feature classification

**Usable as-is**

- Searchable project-filter combobox in the sidebar (pingdotgg#5931).
- Long task drawers stay usable on small screens (pingdotgg#8313) — directly
relevant, the fork's phone story is `apps/web` in mobile Safari/Chrome.
- Toggleable confirmation before unpinning a thread (pingdotgg#7313); toggle
thread pin from the keyboard.
- Back button in project settings (pingdotgg#8168); the configured stash shortcut
is shown (pingdotgg#8437).
- No more red-x summaries for ordinary tool failures (pingdotgg#8395); PRs open
in the browser when loading fails (pingdotgg#8507).
- Project default models are honored in new threads (pingdotgg#6011).
- Provider settings split into list and editor (pingdotgg#8380, pingdotgg#8472) — landed,
though `/settings/providers` is itself gated behind
`serverAdministration`.

**Unsupported in Moatless / needs implementation**

- **Non-image file attachments** (pingdotgg#8235) — a turn may now carry any file
up to 50MB, advertised as `capabilities.fileAttachments.maxUploadBytes`
and sized by `PROVIDER_SEND_TURN_MAX_FILE_BYTES`. Moatless advertises
neither this nor `attachmentUploads`, so the composer's attach
affordance stays off. Costs nothing today (upstream's own web composer
offers images only; `ChatAttachment` widened just far enough to
typecheck), but it is the second capability key to report when uploads
land. Extends the existing **Attachment uploads** entry in
`docs/fork/gaps.md`.
- **Connected-client platform analytics** (pingdotgg#8481) and **DPoP failure
explanations** (pingdotgg#8351) — relay and T3 Connect surfaces, already decided
out of the fork.

No new WS methods entered the contract in this range, so no new
`UnsupportedMethodError` union entries. `unsupported-methods.mjs`
reports `ADD 0`, `DROP 1` (`scripts.run`), `KEEP 2`. The `scripts.run`
DROP is **not** actioned — it is the documented exception in the gaps
register: that union entry answers for `apps/server`, which still stubs
the method (verified surviving in `ws.ts`), not for Moatless.

**Backend behavior to consider reproducing in Moatless**

- **Replay all un-applied events during projection bootstrap** (pingdotgg#7538) —
a one-line pipeline fix upstream; Moatless runs its own projection and
the same class of bug applies.
- **A draft can retry its first send after a failed bootstrap** (pingdotgg#8226)
— Moatless owns turn start, and a draft wedged by a failed bootstrap is
the same dead end here.
- **Recover stale Codex approval callbacks** (pingdotgg#5195) — Moatless owns the
agent runtime in the sandbox.
- **Stop querying Claude context usage after turns** (pingdotgg#8610) — a cheap
correctness/cost fix in the same place Moatless polls.
- **Server-side accept and size-limit non-image uploads** (pingdotgg#8235), the
other half of the gap above.
- Auto-settling churn (pingdotgg#8321 made it opt-in, pingdotgg#8596 reverted) nets to no
change — noted so the next merge does not re-derive it.

## Verification

`verify.mjs`: `tripwires`, `fmt:check`, `lint`, `typecheck` pass. `test`
reports `@t3tools/web` **flaky, passed alone** — in the full run
`MessagesTimeline.test.tsx` skipped all 34 tests on a 30s module-import
timeout under `ChatMarkdown.tsx`; alone the package is 297 files / 3117
tests green. Load, not the merge. `inventory-check.mjs` clean.

Model: Claude Opus 5, via Claude Code in a Moatless sandbox.

---
Moatless task:
https://moatless.soaplabstest.com/tasks/a0c041bb-1426-4591-9296-6a4b0cfa2eff
sandscooling pushed a commit to sandscooling/t3code that referenced this pull request Aug 29, 2026
Brings in 192 upstream commits through v0.0.36 (053affb).

Most of the 52 conflict hunks were additive: the fork's thread `group`
landing on the same lines as upstream's new `linkedPullRequest`. Both sides
kept.

Real tie-breaks, all resolved for upstream:
- Projector bootstrap paging dropped for upstream pingdotgg#7538, which drains the
  whole stream in one read. BOOTSTRAP_PAGE_SIZE went with it.
- Claude `getContextUsage` dropped for upstream pingdotgg#8610. The fork's plan usage
  meter sat next to it and stays; only the context-usage pull is gone.
- The Windows logs-directory assertion in server.test.ts dropped for
  upstream's path.basename form, which handles both separators anyway.

The fork's thread group migration moves from 042 to 044, above upstream's new
042 and 043. The migration runner skips any id at or below the highest one
already recorded, so a fork migration parked on an id upstream later reuses
masks upstream's silently. Existing databases that recorded 42 as
ProjectionThreadsGroupKey need that row dropped once so upstream's 042 and 043
can run; all three migrations are idempotent.

Upstream also stopped passing the raw activity list into the composer, so the
plan usage meter now takes a derived snapshot prop like the context window
does, computed in ChatView.
vitalyiegorov added a commit to vitalyiegorov/t3code that referenced this pull request Aug 29, 2026
Resolves an import conflict in ClaudeAdapter.ts: pingdotgg#8610 dropped the detailed
context-usage query, so SDKControlGetContextUsageResponse no longer has a
consumer and is gone; SDKRateLimitInfo stays, since the usage-limit surfacing
this branch adds still uses it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SamGu-NRX added a commit to SamGu-NRX/t3code that referenced this pull request Aug 29, 2026
…gg#8610

Turn completion now prefers the last assistant usage over the cumulative
result total, so the parent's used count here is its real 12,000 rather
than the clamped window. The subagent total this guards is unchanged.
AspireOne pushed a commit to AspireOne/t3code that referenced this pull request Aug 29, 2026
sheehanmunim added a commit to munimtechnologies/mtcode that referenced this pull request Aug 29, 2026
Upstream pingdotgg#8610 (`stop querying Claude context usage after turns`) brought
six `Option.isNone`/`isSome` call sites into ClaudeAdapter, but the
merge dropped the accompanying `effect/Option` import. That is a
ReferenceError at runtime in the context-usage and stop-acknowledge
paths, not just a type error — the package had nine TS2552 errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
longtngo added a commit to longtngo/t3code that referenced this pull request Aug 29, 2026
Range f6f2be3..053affb, v0.0.36. 411 upstream files, 632 fork files,
81 touched by both, 19 conflicted.

Competing implementations resolved toward the fork's superset:

- Claude context usage (pingdotgg#8610). Upstream deleted `queryCurrentContextUsage` and
  `normalizeClaudeContextUsageApiSnapshot` outright. `getContextUsage` is the ONLY
  source of the compaction facts (`autocompactSource`, `autoCompactThreshold`,
  `isAutoCompactEnabled`) the Vitals gauge's compaction note and marker render from,
  and they travel on the wire contract, so the call is kept. Upstream's
  `latestAssistantUsage` tracking and its post-compaction guard are adopted BELOW it
  as the next-best fallback: `contextUsageSnapshot ?? latestAssistantSnapshot ?? ...`.
  Upstream removed `getContextUsage` from `ClaudeQueryRuntime`, the
  `SDKControlGetContextUsageResponse` import and the `Option` import outside every
  conflict marker; all three restored.
- Provider settings editor (pingdotgg#8472). Upstream's `useEffect` + `lastPublishedEnvironmentRef`
  re-seed is the superset of the fork's render-phase `seededRef` (8fe3190, one of four
  silent-data-loss fixes). The merge had kept BOTH mechanisms; collapsed to upstream's,
  with the fork's half-typed-row null guard on the publish path. `environmentKey` deleted
  with the code it served.
- Sidebar project combobox (pingdotgg#5931). Upstream replaced the menu-based project filter,
  whose `MenuRadioItem` carried the fork's project-actions button. Rebuilt on upstream's
  `ComboboxItem` with the ellipsis button grafted back (invariant 6). The dead `Menu*`
  import is gone.
- Composer attachments (pingdotgg#8236). Upstream's `addComposerAttachments` pipeline adopted; the
  fork's drop split (image -> attach, other -> absolute path with upload fallback) kept
  and repointed at the new handler.
- Mid-turn steer. Upstream's `steeringTurnState` branch rejected again (invariant 5); its
  side of that hunk also opened an `if` whose brace lives below the hunk.
- Thread deletion drain (pingdotgg#8226). Upstream replaced `drain` with `drainThrough(sequence)`;
  the fork's test retargeted. Its new drain test observed `ProviderService.stopSession`,
  which this reactor never calls (it dispatches `thread.session.stop`), so it now counts
  engine dispatches and provides the two services the fork's reactor needs.

Three defects the resolutions introduced, each caught by a check that is not the suite:

- `shouldShowBranchMismatchBanner` was resurrected into two import lists by resolving
  them toward upstream. Fork commit cfdf255 replaced that function; the import had no
  definition. Found by the RESURRECTED sweep.
- `scriptPath` ended up declared twice in CodexCollabRuntime.integration.test.ts: `both`
  reintroduced upstream's fixture-dir copy that the fork deliberately moved to a temp dir.
  Found by the RESURRECTED sweep.
- `setProjectScopeMenuOpen` survived in the fork's `handleProjectActions` after upstream
  replaced that state with a reducer, outside every marker. Found by typecheck.

Upstream regressions of fork fixes, kept fixed:

- Raw NUL bytes returned to ChatComposer.tsx. A raw NUL renders as nothing in grep and
  aborts BSD sed mid-file; the fork had converted all six to `\0` escapes and carries a
  guard test for it. The guard failed, and the offending line reads as space-separated in
  any normal diff. Converted back to escapes.
- `defaultTheme` / `defaultThemeSetAt` (pingdotgg#8569) are absent from `ServerSettingsPatch`; the
  fork's patch-parity guard caught it. They are owned by `t3 theme set`, which rewrites
  settings.json directly and which clients only read, so they are recorded as deliberately
  unpatchable rather than mirrored.
- The fork's mobile held-messages strip used `dark:` variants that upstream's new Uniwind
  theme rule (pingdotgg#7327) forbids; moved to the `text-foreground-muted` semantic token rather
  than added to the rule's allowlist.

Invariants: all re-probed against the merged tree. 1 (49 migrations, ids unique and
monotonic, max 50, 34 burned), 2 (the fork-only @effect/platform-node patch survived the
Expo 57 rewrite of patchedDependencies, is pinned, resolved and applied on disk; effect
stays at beta.103 so no re-pin), 3, 4, 4b (4 `isSendBlocked=`), 5, 5b, 5c, 6, 7, 8, 9, 10,
11 all hold.

Sweeps: resurrected 3, dropped 21, fork-loss 45, both-kept 0. Every entry named: the 3
resurrected and the fork-loss in ProviderInstanceCard / ChatComposer / Sidebar are the
decisions above; the OpenCode fork-loss is 11 comment lines whose guard upstream extracted
into `deleteContextIfCurrent` (the rationale is restored on the helper); pnpm-lock churn is
the install. Test declarations 18,691 -> 19,081; one file lost one, upstream's own pingdotgg#8484.

Gate: pnpm run verify green, exit 0 read from the captured log line. 14 blocks,
10,744 passed, 20 skipped, 0 failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
longtngo added a commit to longtngo/t3code that referenced this pull request Aug 29, 2026
Four new invariants and one correction, each from something this merge got
wrong once before a check caught it.

12. The Claude adapter still calls getContextUsage. Upstream pingdotgg#8610 deleted it;
    it is the only source of the compaction facts the Vitals gauge renders, and
    upstream's replacement is adopted underneath rather than instead. Names the
    three symbols upstream removed outside every conflict marker, and why two of
    its tests are retargeted.
13. The provider-settings re-seed is upstream's on purpose. The merge kept both
    it and the fork's older one; restoring the fork's is adding a second, not
    restoring a fix.
14. Upstream keeps reintroducing raw NUL bytes into ChatComposer.tsx. The line
    reads as ordinary spaces in every diff and grep; only the guard test and
    cat -v see it.
15. defaultTheme / defaultThemeSetAt are deliberately unpatchable, so the
    patch-parity guard needs to know rather than be relaxed.

Also: invariant 6's two project buttons now live in a ComboboxItem, and the
Surface counts are redated instead of quoting stale figures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant