Skip to content

Show Plan usage across the Fleet in the CLI and Console - #2204

Merged
JacobStephens2 merged 4 commits into
issue-583from
issue-2182
Nov 14, 2026
Merged

JacobStephens2 merged 4 commits into
issue-583from
issue-2182

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Nov 14, 2026 •

Copy link
Copy Markdown
Owner

Summary

thirdshift plan-usage and the Console's new Plan usage page show the Fleet by default once a machine is paired, saved or reported. The view groups shared subscription logins, and the Console header warns while a configured route is used up.

plan-usage [--fleet | --machine <name> | --local] [--json]      GET /api/v1/plan-usage   (read)
plan-usage --clear [<harness>] [--json]                         POST /api/v1/plan-usage/clear (act)
plan-usage --push [<destination>], and after every Command  →  POST /api/v1/plan-usage/report (report)

show(selection, Capture)            # pairing + saved views taken once per operation
  Local            → this machine's view (non-billed reads ≤ 1/min)
  Fleet / default  → this machine
                     + each peer's /api/v1/plan-usage?local=true   (no relaying)
                       ok → save per person   unreachable → cached   link-only → reported slot
                     + retired / reported machines
                     → group(): one row per login
                         claude: organization + email · codex: account id · muse: label
                         agy, grok, unknown identity → one row per machine
                         freshest observation shown, every machine named
 header
   host admission
+  Plan usage · N routes limited  → /plan-usage   (saved state only, no reads)
 nav
   … Metrics
+  Plan usage (g p)
   9 Resources        # unchanged: RAM, CPU, disk
  • Parity: the two interim parity exclusions for plan-usage are gone. Each machine choice and --clear has an API twin, and ADR 0026 records why this one read answers for the Fleet.
  • Peer views: a peer's or pushed view is refused whole if any of its text is longer than 256 characters or holds a control character.
  • Routing: unchanged and machine-local (ADR 0031).
  • Shared code: Slot, Held and the Fleet Status move to src/console/fleet/snapshot.rs, which Fleet metrics now uses too.

Evidence

Execution evidence

The same fixture (grok in cooldown on its routes) was run against both builds with /tmp/ts2182-capture/evidence.sh <binary>.

  • Before (origin/issue-583 build):

    $ thirdshift plan-usage --fleet --json
    thirdshift: usage: thirdshift plan-usage [--json] [--clear [<harness>]]   (exit 2)
    $ curl /api/v1/plan-usage
    HTTP 404
    $ curl / | grep plan-usage-warning
    (no warning in the header)
    

    After (this branch):

    $ thirdshift plan-usage --fleet --json
    {"harnesses": [{"harness": "grok", "identity": null, "installed": true, "machines": [...] ... (exit 0)
    $ curl /api/v1/plan-usage
    HTTP 200
    $ curl / | grep plan-usage-warning
    <p id="plan-usage-warning" role="status"><a href="/plan-usage" title="grok harness.def…
    
  • New tests:

    • cargo test --test console plan_usage::: 6 passed. It covers CLI/API parity, the header pill, clearing under act and read, Fleet grouping, offline fallback, a pushed NATted report, and the after-Command push.
    • cargo test --bin thirdshift plan_usage::fleet console::plan_usage: 6 passed.
    • node --test console/tests/plan-usage.test.cjs: 2 passed, at desktop and phone widths.
  • Full Console browser suite: npm test --prefix console passed 207/207.

  • Site: npm test --prefix site passed 69/69, and npm run docs:check --prefix site is clean.

  • Format and lint: cargo fmt --check and cargo clippy --all-targets are clean.

  • Full Rust suite: cargo test --no-fail-fast passed 4559 and failed 6. This host has no C linker, so the suite ran in a node:22 container with the host toolchain, and all 6 failures are container artifacts:

    • Four Commands warned could not fully sweep session …: could not read process …'s environment: Permission denied and failed their no-warning assertions: architect_run (run 1), launch_pull, opencode_sessions and run_notification. architect_run passed once ptrace was allowed.
    • trial_scope needs systemd.
    • session::execution_tests::partial_stdout… and activity_log::an_activity_log_that_cannot_be_written… failed under load and pass alone.

    CI runs the suite natively.

Visual evidence

Console header, desktop 1440×900, with a route in cooldown and one at its ceiling:

Before
After

Console header, mobile 390×844, same state:

Before
After

Unaddressed findings

Standards

  • 1. after_command builds reports without report destinations. Declined; I ran the reviewer's test as written and it passes:
    • cargo test --test console plan_usage::a_finished_command_without_report_destinations_builds_and_warns_nothing → ... ok.
    • src/console/report.rs after_command still returns at if config.console.report.is_empty() { return; } before building any report.
    • The test is kept as a guard.
  • 3. Duplicated fallback state machine with Fleet metrics. Declined:
    • Metrics' fallback keeps per-view saved windows and re-buckets a stand-in window (cached in src/logs/metrics/fleet.rs). Plan usage keeps one view per machine.
    • The parts with the same shape (Slot, Held, Status) were extracted to src/console/fleet/snapshot.rs. A generic fallback over both payloads would mean reworking the Metrics model in this ticket.

Spec

  • 1. plan-usage --push [<destination>] is scope creep. Declined:
    • Every Console route must name a CLI twin that parses (src/console.rs assert_cli_parity: "{} has no paired CLI command"), and ADR 0026 makes every endpoint the twin of a CLI command.
    • The issue requires the receiving endpoint /api/v1/plan-usage/report, and plan-usage --push is its twin, as metrics --push is for /api/v1/metrics/report.

Security

None unaddressed. The Security review found one introduced finding and fixed it in a2988d8:

  • thirdshift plan-usage --fleet printed a paired peer's refusal reason to the terminal with its control characters intact. A peer could use this to set the terminal title, clear the screen or rewrite lines.
  • The text now goes through cronjobs::report_line, the same treatment the cronjobs Fleet view uses. JSON keeps the text as the peer sent it.
  • The regression test cargo test --test console plan_usage::a_fleet_peers_refusal_reaches_the_terminal_without_control_characters failed before the fix and passes after it.

All other findings were fixed in bde9559:

  • one Fleet Capture per operation;
  • Reach instead of two coupled Options;
  • Outgoing as a route and body;
  • identity and peer_view renames;
  • the shared empty-view text;
  • shared test helpers.

Both reviewers read every changed file. site/docs/index.html was excluded as generated output from docs/guide.md; docs:check passes. No changed file was left unread.

Security review outcome

No unaddressed introduced findings.

Merge Danger

Door: two-way

New read, action and report endpoints, a header line and a nav entry. Nothing is migrated. Saved peer views live in a new logs/fleet-plan-usage/ directory.

Blast Radius: moderate

  • plan-usage --json now answers with the Fleet shape once a Fleet machine is paired or reported. --local keeps the old one.
  • A machine that reports to an older hub gets a 404 on the new report route. That costs only an after-Command warning, now worded metrics and Plan usage not reported.
  • /api/v1/plan-usage reads paired peers with this Console's saved Fleet tokens, for a read-scope view only. ADR 0026 records this.

Closes #2182

Built with claude 2.1.322 · claude-opus-5-5 · high

thirdshift plan-usage and the Console's /plan-usage (with
/api/v1/plan-usage) default to the Fleet once a machine is paired or
saved, and take --fleet, --machine <name> and --local. Each Fleet
machine is asked for its own view alone, saved for when it goes
offline, and grouped into one row per subscription login by the
identity its Harness reports (Claude organization and email, Codex
account id, Muse label); agy and grok stay per machine.

Clearing cooldowns becomes an act-scoped Console action, so the two
interim parity exclusions go. The push after each Command, and
plan-usage --push, send this machine's saved view under the report
scope. Every Console header warns while a configured route is in
cooldown or at its ceiling, linking to Plan usage.

Closes #2182
…pers

Plan usage takes the Fleet's saved views and pairing once per operation,
so the default view, machine choices and the view shown agree; load takes
a Reach instead of two Options that had to agree. Outgoing reports are a
route and a body, Login.login is identity, the page reuses the CLI's
empty-view text, and the tests reuse the Metrics report helpers.
A paired peer's refusal reason reached `thirdshift plan-usage` text output
with its control characters intact, so a peer could set the terminal
title, clear the screen or rewrite lines. Print it through the same
report_line the cronjobs Fleet view uses; JSON keeps the text as sent.
@JacobStephens2
JacobStephens2 merged commit e3544e4 into issue-583 Nov 14, 2026
24 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-2182 branch November 14, 2026 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant