fix(server): usage-limit auto-resume no longer arms children of settled parents#27951
Problem
Turning on Resume after usage limits made the usage-limit recovery sweep arm and resume delegated child threads that had stopped on a usage limit while the setting was off, even when their parent thread was settled. When a resumed child finished, its delegated-completion wake could pull the settled parent back to active and start a new run. The candidate query only checked the child's own archivedAt and settledOverride and never looked at its lineage.
Reproduced on main (2b15ba077d) with a projection-level test. It builds two parent/subagent pairs whose children failed on a usage limit and have nothing armed; one parent is settled. With autoResume on (and separately with snooze on), both children get a limit-arm: command, including the child of the settled parent.
Change
getLimitRecoveryCandidates gets one extra condition in the branch that freshly arms a recovery (both the auto-resume arm and the snooze arm). A thread whose lineage.relationshipToParent is subagent and whose direct parent has settledOverride = 'settled' is not offered for a new arm. The parent lookup goes through the threads table's primary key and only runs for rows that already passed the usage-limit pre-filter.
The resume branch is unchanged: a recovery that was already armed for the child's latest failed run still resumes at its reset. Unsettling the parent emits a thread.* event, which already makes the sweep due, so the child becomes eligible again on the next tick.
Scope and approval
Fixes pingdotgg/t3code#27944
Verification
- New test
ProjectionStoreV2 > does not freshly arm limit recovery for a subagent of a settled parentinapps/server/src/orchestration-v2/ProjectionStore.test.ts. It checks that a child of a settled parent is not armed underautoResumeor snooze, that a child of an unsettled parent still is, and that a child armed before its parent settled still produces itslimit-resume:dispatch. - Red with
main'sProjectionStore.ts(2b15ba077d):1 × does not freshly arm limit recovery for a subagent of a settled parent 2 AssertionError: only the child of the unsettled parent is armed ({"now":"1970-01-01T00:00:00.000Z","autoResume":true,"snooze":false}): expected [ …(2) ] to deeply equal [ Array(1) ] 3 actual: [ 'thread:settled-parent-limit:active:child', 'thread:settled-parent-limit:settled:child' ], 4 expected: [ 'thread:settled-parent-limit:active:child' ] 5 Tests 1 failed | 44 skipped (45) - Green with the fix (003df33f85):
Tests 1 passed | 44 skipped (45). ProjectionStore.test.tsandUsageLimitRecoveryWorker.test.ts: 46/46 pass.runtimeLayer.test.ts -t "limit": 20 pass.vp run check:changedpasses (format, lint, knip, typecheck, tests).- Server-only change with no visible surface, so there are no captures. Not checked: a live provider hitting a real usage limit, which a VM cannot trigger. The proof is the projection test above.
Claude Opus 5.5 (Claude Code in T3 Code; reviews by GPT-6.1 Sol on Codex and Claude Opus 5.5).
🤖 Generated with Claude Code
Checks
Added 3 commits
Approvability
Verdict: Approved at 5abe8a0
Macroscope's review found this PR approvable — Fresh usage-limit recovery will no longer arm subagents of explicitly settled parents, preventing abandoned work from waking those parents. Already-armed recoveries and product preference defaults remain unchanged.
No code changes detected at 8f9e45d. Prior analysis still applies.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
✅ Thread transfer remains within every enforced ceiling.
| 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.6 KiB | 21.6 KiB | 0 B (0.0%) | 24.4 KiB | ✅ |
| Codex | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | −18 B (−0.3%) | 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 | −18 B (−1.4%) | 2.0 KiB | ✅ |
| Claude | Live turn WebSocket decoded | 21.9 KiB | 21.9 KiB | −41 B (−0.2%) | 24.4 KiB | ✅ |
| Claude | Live turn messages | 2 | 1 | −1 (−50.0%) | 8 | ✅ |
Baseline: f6503f0 · PR result: 8f9e45d · 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: 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
The limit-recovery candidate query now excludes subagent threads whose parent has
settledOverrideset to"settled". Tests check fresh recovery selection under two option sets and verify that an already-armed recovery can still produce a resume command after its reset time.Changes: Usage-limit recovery
Layer / File(s) Summary Filter fresh recovery candidates
apps/server/src/orchestration-v2/ProjectionStore.ts,apps/server/src/orchestration-v2/ProjectionStore.test.tsThe query excludes subagent threads when their parent has settledOverrideset to"settled". Tests cover both option sets and confirm that an already-armed recovery can still yield a resume command after the reset time.Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related issues
Suggested labels:
size:MSuggested reviewers:
t3dotgg,macroscopeapp
Merge Risk: External image Minimal · up to 8f9e4
Fresh recovery selection excludes children of settled parents while preserving already-armed recoveries. No merge-blocking issue was identified.
Pre-merge checks: Passed 3 · Failed 1
Failed Failed checks: 1 warning
Check name Status Explanation Resolution Linked Issues check Warning Issue #27944requires that a child whose direct parent is settled is not resumed by the usage-limit sweep.ProjectionStore.tsexcludes the child only when the sweep would create a fresh recovery arm…Also exclude subagents of settled parents from the already-armed resume path, or cancel their recovery before dispatch. Keep a regression test that settles the parent after arming and verifies that no resume dispatch occurs. Passed Passed checks: 3 passed
Check name Status Explanation Title check Passed The title clearly and concisely describes the main server fix: preventing usage-limit auto-resume from freshly arming children of settled parents. Description check Passed The description includes all required sections: Problem, Change, Scope and approval, and Verification. It explains the bug, implementation, linked issue, focused tests, observed results, and untested … Out of Scope Changes check Passed The changes stay within issue #27944. The production change updates usage-limit candidate selection, and the test covers settled and unsettled parents, auto-resume, snooze, and existing recovery behav…Full details: Description check
Explanation
The description includes all required sections: Problem, Change, Scope and approval, and Verification. It explains the bug, implementation, linked issue, focused tests, observed results, and untested live-provider scenario.
Full details: Out of Scope Changes check
Explanation
The changes stay within issue
#27944. The production change updates usage-limit candidate selection, and the test covers settled and unsettled parents, auto-resume, snooze, and existing recovery behavior.
Full details: Linked Issues check
Explanation
Issue
#27944requires that a child whose direct parent is settled is not resumed by the usage-limit sweep.ProjectionStore.tsexcludes the child only when the sweep would create a fresh recovery arm.UsageLimitRecoveryWorker.tsstill dispatcheslimit-resume:when an existing recovery matches the latest failed run, without checking the parent's settlement. The added test confirms this behavior for an already-armed child.Resolution
Also exclude subagents of settled parents from the already-armed resume path, or cancel their recovery before dispatch. Keep a regression test that settles the parent after arming and verifies that no resume dispatch occurs.
Finishing Touches
Generate docstrings
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
Some tools did not complete. Review the errors below.
External image ast-grep (0.51.1)
ast-grep could not parse rule config: /ast-grep-rules/ast-grep-essentials/rules/ruby/security/insufficient-rsa-key-size-ruby.yml
Usage-based review receipt
- Mode: Continue automatically
- Reviewed files: 2
- Charged: $0.50
- View usage details
Note
This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.
CodeRabbit Verify
- Run CodeRabbit Verify to test the changes in this pull request.
External image Recent review info
-
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: fix/issue-27944
- File: .coderabbit.config.ts
- Commit: 8f9e45d
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
22161180-013d-447a-a139-ba9923d758f6
External image Commits
Reviewing files that changed from the base of the PR and between 5abe8a0c4b9641116dbb6dd8aaba09e6c263157d and 8f9e45d918d61b9a26206e55500c1de6ddf558cb.
External image Files selected for processing: 2
apps/server/src/orchestration-v2/ProjectionStore.test.tsapps/server/src/orchestration-v2/ProjectionStore.ts
Limit details: You’ve used all 10 included reviews currently available.
External image Recent review info
-
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: fix/issue-27944
- File: .coderabbit.config.ts
- Commit: 8f9e45d
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
22161180-013d-447a-a139-ba9923d758f6
External image Commits
Reviewing files that changed from the base of the PR and between 5abe8a0c4b9641116dbb6dd8aaba09e6c263157d and 8f9e45d918d61b9a26206e55500c1de6ddf558cb.
External image Files selected for processing: 2
apps/server/src/orchestration-v2/ProjectionStore.test.tsapps/server/src/orchestration-v2/ProjectionStore.ts
Limit details: You’ve used all 10 included reviews currently available.
Added 1 commit
- Merge branch 'main' into fix/issue-279448f9e45d