Repository navigation
Record and inspect local Plan usage across subscription Harnesses and User config routes - #2198
Merged
Merged
Conversation
Running sessions save Plan windows and limits from structured wire frames (Claude rate_limit_event at every status and utilization and API-error rate-limit facts, Codex token_count, and terminal usage-limit errors on claude, codex, muse, agy and grok) in ~/.thirdshift/plan-usage.json. thirdshift plan-usage [--json] [--clear [<harness>]] adds non-billed codex app-server, muse serve and claude auth status reads at most once a minute, shows the User config's routes in order with the active one, and forgets recorded cooldowns. The User config gains harness.routes, harness.max_utilization and security.routes, and headless agy keeps to included usage unless its route allows credits. Closes #2181
…route Terminal usage-limit facts now come only from each Harness's own top-level failed-turn frame (never a tool task's failure or an interrupted turn's final message), Claude API errors keep their window, reset and spend cap without a status, the snapshot skips unchanged writes, an installed API-key route ahead of a subscription route leaves none marked active, Muse's account state can say signed out, and plan-usage gets interim ADR 0026 exclusions until #2182 serves its Console API.
The every-setting fixtures and default-key inventory name harness.routes, harness.max_utilization and security.routes, the agy session argv expects the included-usage guard, and plan-usage shares the resources help line so help stays a compact reference.
This was referenced Nov 14, 2026
Closed
Merged
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.
Summary
Ticket 1 of #583: this machine now records Plan usage for the five subscription Harnesses, refreshes it on demand, and shows it. The User config gains ordered routes and utilization ceilings, and headless
agykeeps to included usage unless its route allows credits.Rows list every Harness the User config names:
harness.default,harness.routes,security.harnessandsecurity.routes, in route order. Any other subscription Harness appears only when it has a saved observation or a signed-in CLI.opencodeandkiminever appear.Evidence
Execution evidence
Tests and builds ran inside the local
node:22container with the host Rust toolchain, because this host has no C toolchain.cargo test --bin thirdshift console::parity::every_cli_command_has_an_api_twin_or_reasoned_exclusionpanicked at src/console/parity.rs:320:5: CLI inventory for Command needs updating … left: {…, "PlanUsage", …}After: same command →
test result: ok. The command addsPlanUsageto the inventory with interim exclusions.an_unchanged_snapshot_is_not_rewritten,a_failed_tool_task_mentioning_quota_is_not_plan_usage,agent_text_in_an_interrupted_claude_result_records_no_plan_usage,claude_api_error_limits_without_a_status_keep_their_window_reset_and_spend_cap,an_api_key_route_ahead_leaves_no_subscription_route_active,muse_account_state_alone_says_signed_out):test result: FAILED. 15 passed; 6 failedAfter:
cargo test --bin thirdshift -- plan_usage console::parity harness::→test result: ok. 235 passed; 0 failedcargo test --test plan_usage→test result: ok. 7 passed; 0 failed. The tests use scripted fake Harness CLIs to cover passive capture at several utilization levels on claude and codex, terminal limits on claude, codex, grok, muse and agy, the reads and their 60 s cache, row filtering, JSON output,--clear, User config validation and the agy credit guard.cargo test --no-fail-faston the final head): 107 targets passed and 4 failed.trial_sessions_keep_their_cap_and_clean_detached_workneeds asystemctl --usersession, which the container lacks.warning: could not fully sweep session …: could not read process …'s environment: Permission deniedin their stderr (architect_run,opencode_sessions,run_notification). That sweep code is untouched here. All three passed when rerun alone, one of them 3/3, and all passed in the first full run.docker run --init.npm test --prefix console). Playwright and Chromium are not installed here. The only Console change is onematcharm insrc/console/start_controls.rs.Visual evidence
None: the change is CLI-only, with no rendered UI.
Merge Danger
Door: two-way
The new User config keys default to today's behaviour (
routes = [],max_utilization = 100). The snapshot is a new file. Nothing routes on it yet; routing comes in #2183.Blast Radius: sessions
Every session's stream now also writes
~/.thirdshift/plan-usage.json, best-effort and skipped when unchanged. Headlessagysessions, release summaries included, now pass--settings {"useG1Credits":false}. ADR 0026 gains two interim CLI-only entries forplan-usage, which #2182 removes when it serves/api/v1/plan-usage.Unaddressed findings
Standards
2. User manual, site pages and README not updated. Declined: Document Plan usage viewing and routing across the user manual, site pages, and code index #2185 is open and owns "Document Plan usage viewing and routing across the user manual, site pages, and code index". This follows the plan's split in
docs/grill-with-docs/583-available-usage-routing.mdQ3.4, item 5. That includesdocs/guide.md's copy of the default User config.3.
cfg!(test)and a User config read inside agy's argument builder. Declined.Choiceis built as a struct literal at about 87 sites. Carrying the credit decision on it belongs with the route choice that Route factory session Steps proactively and reactively across configured Plan usage routes #2183 introduces.credits_allowed(src/plan_usage.rs) fails closed, keeping the guard on whenever the config can't be read.cfg!(test)keeps unit tests off the developer's real$HOME. The decision itself is the pure, unit-testedRouting::allows_credits.4. Shared locked-JSON helper with the GitHub Quota store. The bug is fixed: the write guard now compares like with like, and
an_unchanged_snapshot_is_not_rewrittenpasses. The extraction is declined. The two stores already sharelock_exclusive, and their record types and update semantics differ.7. No Plan usage row in
docs/code-navigation.md. Declined: Document Plan usage viewing and routing across the user manual, site pages, and code index #2185 owns the code index.8. Smells. Fixed:
availabilityis nowState::availability.Viewcarries itsnow.harness_name: one function inroute.rs.Declined:
token_countand the camelCase app-server answer.read.rs: they need different things. One needs only an exit status, one needs stdout to EOF, and one is a JSON-RPC line stream.BTreeMap<String, State>: the key is the saved file's JSON key, andHarnesshas no serde impl.Spec
account/readstatevalues are unconfirmed.muse_state_signed_inmaps only clearly signed-in or signed-out spellings, and leaves anything else unknown.Security
plan-usageview and--clear, User config route parsing, and theagycredit guard. Saved strings are kept only as short operator tokens or control-free text, the snapshot is written owner-only under its lock, the reads read no private tokens, and the credit guard stays on unless a User config route allows credits. A cooldown forged from a session's text could only change whatplan-usagedisplays, because nothing routes on it until Route factory session Steps proactively and reactively across configured Plan usage routes #2183.Security review outcome
No unaddressed introduced findings.
Review coverage
Both reviewers read every changed file at review time; nothing was excluded as generated. These files changed after review, while addressing findings, and were not reviewed as changes:
docs/adr/0026-each-console-serves-an-api-that-can-do-what-the-cli-can.mdsrc/console/parity.rssrc/harness/agy/stream.rssrc/harness/muse/stream.rssrc/harness/interpretation_tests.rssrc/setup.rstests/agy_sessions.rsCloses #2181
Built with claude 2.1.322 · claude-opus-5-5 · high