# Usage-limit evidence capture

Scope: [#22775](https://git.cafe/pingdotgg/t3code/pulls/22775), [GitHub mirror #22775](https://github.com/pingdotgg/t3code/pull/22775). No other issue or PR was touched. No push, PR edit, comment, or forge mutation was made. T3's app-owned PR registration was verified.

**Delivery status: paired actual-server captures for the core R1–R5 transitions are complete. R4's active-wake rejection is supplemental OFFLINE EVENT HARNESS evidence, not a live-server observation. Public uploads are blocked by DNS. Real Claude quota exhaustion remains UNVERIFIED.**

## Revisions and attribution

- BEFORE: [21da3061aa](https://git.cafe/pingdotgg/t3code/commit/21da3061aa006fc852ea4bd84c31ec084a3afa26), full `21da3061aa006fc852ea4bd84c31ec084a3afa26`.
- Original AFTER production/test code: [80d27e96db](https://git.cafe/pingdotgg/t3code/commit/80d27e96db888d3ab0dbf12314f136f4e8b3e9b4), full `80d27e96db888d3ab0dbf12314f136f4e8b3e9b4`.
- Captured AFTER and runner commit: [9fd419a6e9](https://git.cafe/pingdotgg/t3code/commit/9fd419a6e9b455f17958325ad3ed696f08f00722), full `9fd419a6e9b455f17958325ad3ed696f08f00722`. **Local, not pushed; its forge commit link will resolve only after a later authorized push.**

The AFTER checkout was clean. BEFORE retained the exact merge-base HEAD and no tracked changes; its only untracked additions were byte-identical copies of the three runner/fixture files. Capture headers record this status and each file's SHA-256. `runnerCommitSha` was supplied as the abbreviation `9fd419a6e9` in the command lines; its full resolution is recorded above and in [capture-manifest.json](/tmp/issue-16815-evidence/capture-manifest.json). `runnerBlobSha` separately identifies the executable script blob.

All ten captures have matching runner file hashes. BEFORE dependencies resolved workspace source under `/tmp/t3-limit-evidence-before`, AFTER under `/home/ubuntu/wt/issue-16815`; each header records `shared`, `contracts`, and `provider-core` real paths. Only the unchanged external dependency store was shared. No dependency install was needed. The single authorized throwaway checkout and its dependency links were removed after the BEFORE runs.

## Environment and method

Environment: `freestyle`, Linux x86_64, Node `v24.21.0`, UTC, SQLite-backed server development source entrypoint. Captures ran 2026-10-21 approximately 10:14–10:20 UTC; exact timestamps, bound ports, captured server PIDs, homes, commands, events, and readiness milestones are in every scenario block.

Each scenario used a fresh, explicitly marked `/tmp/t3-limit-evidence-{before|after}-R*` home, a separate workspace, loopback port, disposable OS HOME and CODEX_HOME, and an environment allowlist. No live T3 database or real provider credentials were read or written. The existing Codex mock peer held any real server-started continuation open; usage-limit failures and wake completions were **synthetic provider events**, not real quota behavior. The mock's unsupported rate-limit/config probes can log decode diagnostics; these do not represent Claude quota or a real provider failure.

The committed runner staged thread history offline through existing Orchestrator/EventSink services, closed that database, then spawned the existing `apps/server/src/bin.ts start --bootstrap-fd 3 --log-level debug` server. It used the existing desktop bootstrap exchange, WebSocket ticket, `orchestration.dispatchCommand`, thread projections, shell HTTP snapshot, and subscriptions. No production RPC/HTTP/MCP endpoint or auth/permission/mode/trust/sandbox behavior was added or changed. No browser, screenshots, Vite origins, or real provider were used.

Only records prefixed `LIVE-` and server process/readiness records are actual dev-server evidence. `OFFLINE EVENT HARNESS (server stopped)` records document fixture staging and SQL service observations. A completed `UsageLimitRecoveryWorker.sweep` trace span is the milestone for the automatic-arm observation, not an arbitrary sleep. Real reset deadlines were waited on using wall-clock timestamps. Continuation success is the committed response sequence plus the persisted new run in the live projection; no provider work completion is claimed. Final offline event dumps include shutdown events and must not be confused with the last live state.

## Raw evidence

Public URLs: **unavailable**. Two configured ghdrop attempts failed; curl could not resolve the upload host, and a bounded read-only public DNS query returned SERVFAIL. See [publishing status](/tmp/issue-16815-evidence/capture-upload-status.md). No DNS or credential configuration was changed. The earlier published matrix is not a URL for these new captures.

- [BEFORE raw transcript, R1–R5](/tmp/issue-16815-evidence/before-transcript.log)
- [AFTER raw transcript, R1–R5](/tmp/issue-16815-evidence/after-transcript.log)
- [BEFORE actual server stdout/stderr](/tmp/issue-16815-evidence/before-server.log), [AFTER actual server stdout/stderr](/tmp/issue-16815-evidence/after-server.log)
- [Structured per-row observables, commands, receipts and identities](/tmp/issue-16815-evidence/capture-summary.json)
- [Exact revision/file hashes](/tmp/issue-16815-evidence/capture-manifest.json)
- [Capture assertions](/tmp/issue-16815-evidence/capture-validation.log)

Per-row raw files also remain as `before-R1.ndjson` through `before-R5.ndjson` and `after-R1.ndjson` through `after-R5.ndjson`. These are mixed raw host stdout/stderr (including `df` output), not strict NDJSON. Combined `.log` transcripts preserve them byte-for-byte with scenario boundary labels.

## Row results

- **R1 prearm:** synthetic L failed, completed notification-first W before reset, no stored recovery initially. BEFORE: SQL candidate absent, live shell `completed / null`, no blocked source, automatic sweep cannot arm, no due command and two runs. AFTER: offline SQL candidate and live blocked selector identify L, live shell `failed / usage_limit`, completed real scheduler sweep arms L, due command sent twice through the server returns the same committed sequence and creates exactly one continuation (three runs). Source, reset time, root input type, full arm metadata, and command identities are recorded.
- **R2 already armed:** A is explicitly labeled offline service staging before W. BEFORE: stored arm remains, but live shell becomes completed and no due command is selected; two runs remain. AFTER: live blocked selector/shell still identify L, armed requestId remains unchanged, and duplicate live due dispatch returns one receipt sequence and one continuation. **The offline candidate query is intentionally at pre-reset `now`: armed windows are not yet due, so it returns null on BOTH revisions. That scheduling-filter result is not labeled a lost source.** Due SQL boundary behavior retains its supplied regression-test coverage; the runtime capture proves live shell identity, due-command source identity and the server continuation guard.
- **R3 Stop before arm:** W completed before Stop. BEFORE: live Stop does not mark L, no disarmed L metadata is created, explicit rearm is rejected with `The provider limit changed before recovery could be configured.`, and no continuation is added. AFTER: live Stop persists L's `run_interrupt_request`, `{autoResume:false, requestId:"proof:stop:R3"}`, a completed real automatic sweep preserves that identity, explicit live rearm replaces it with `proof:rearm:R3`, and duplicate due delivery adds one continuation. Source marker, metadata, sweep span and committed event order are captured.
- **R4 manual + held queue:** initial Q is queued with `queueHeld:true`; completed notification-first W is before reset, auto-resume remains off; manual dispatch is after R+2s. BEFORE: the recorded client selector expression chooses completed W, selected Resume and forced M(L) are rejected; queue.resume then starts Q. AFTER: the expression chooses L, live M(L) succeeds, Q remains queued with `queueHeld:false`, a new-identity duplicate M(L) is rejected, queue.resume succeeds and leaves Q behind the active continuation. This is selector/service evidence, not proof of a rendered button. The active-wake M(L) rejection is separately recorded during offline EventSink staging and covered by the existing regression suite; **it was not captured on the live server**. The existing WebSocket transport rewrites client provenance and rejects client-created provider notifications; no bypass or protected change was made.
- **R5 post-reset success:** A and saved D are staged offline, W completes after R+2s with assistant output. Both revisions: live shell completed, no usage-limit error or blocked source; stale D returns a no-op receipt and forced M(L) is rejected; both retain exactly two runs. Recovery metadata may remain but is inert. This is the non-regression boundary, so BEFORE and AFTER intentionally agree.

## R6–R10 and validation

The task supplied an already passing **99/99** regression result at exact `80d27e96db888d3ab0dbf12314f136f4e8b3e9b4`. No tests were changed and that suite was not rerun, as instructed. R6 active supersession, R7 ordinary/user-first input ordering, R8 inclusive reset/invalid-date boundaries, R9 failure/root identity and R10 status/guard cases retain that test attribution. The earlier 28-case parity diagnostic is supplemental uncommitted evidence, not a newly committed fixture.

- [Original supplied 99-test output](/tmp/issue-16815-evidence/followup-tests.log)
- [Regression provenance and limits](/tmp/issue-16815-evidence/regression-provenance.md)
- [Fresh server-scoped typecheck (exit 0, suggestions only)](/tmp/issue-16815-evidence/runner-typecheck.log)
- [Fresh targeted script lint](/tmp/issue-16815-evidence/runner-lint.log)
- [Fresh complexity/timing results at full runner commit](/tmp/issue-16815-evidence/capture-complexity.log)

No new regex was introduced. Shared selection is O(runs + items). JSON/date parsing scales with input length; trace observation reads appended bytes, scans complete lines, and bounds its 20-second observation to 4 MiB. Fresh 1000-iteration diagnostic medians: 3000-wake selector 0.252 ms; 3000-token malformed reset 0.117 ms; 3000-token nominal JSON 0.114 ms; malformed final delimiter after 3000 tokens 0.133 ms. These are measurements, not timeout-based assertions. Original SQL malformed-date timing remains in `followup-sql-malformed.log` with its original attribution.

## What else changed

This evidence commit adds only:

- [usage-limit-evidence.ts](/home/ubuntu/wt/issue-16815/apps/server/scripts/usage-limit-evidence.ts): host capture runner.
- [usage-limit-evidence.fixture.ts](/home/ubuntu/wt/issue-16815/apps/server/scripts/usage-limit-evidence.fixture.ts): offline service-layer staging and raw event output.
- [usage-limit-evidence.fixture.json](/home/ubuntu/wt/issue-16815/apps/server/scripts/usage-limit-evidence.fixture.json): versioned input recipe/data.

No production or regression-test file was changed in this evidence step. Existing fix differences between merge-base and original AFTER remain the six files named in the supplied audit: Orchestrator, ProjectionStore, shared thread-error selection, web ChatView, server runtime tests, and client execution tests. Web UI rendering was not verified here. Capture logs/assets were not committed. No remote push or forge write was made.

## Cleanup and remaining limits

All ten final captured server PIDs and all smoke server PIDs checked have exited. Sixteen explicitly enumerated disposable homes were removed after saving raw evidence and fixture manifests. The one throwaway worktree/dependency links were removed; the external dependency store was retained. The main issue checkout remains clean at the full runner commit. Root disk remained above 11 GiB available throughout, approximately 12 GiB after cleanup. See [cleanup record](/tmp/issue-16815-evidence/capture-cleanup.json).

Remaining unverified: real Claude quota exhaustion/adapter classification (no credentials or real limit), live R4 active-wake rejection (offline harness and existing tests only), rendered Resume UI (server scope), and public delivery of evidence (DNS blocked). No attempt was made to turn a client notification into a provider event through a new endpoint or authorization change.
