Replace the footer's placeholder usage with a real observation ledger

The footer showed invented percentages. It now shows what two harnesses
actually report, or says it does not know.

lumbridge-core gains an append-only per-profile UsageLedger and a projection
that labels every derived value estimated, withholds a burn rate from a single
sample, withholds a window fraction with no reported ceiling, withholds an
exhaustion estimate that lands after the reset, and reports an expired window
as rolled over rather than freezing its last percentage. A missing fact renders
as missing, never as zero. (0012)

lumbridge-harness is the impure side: processes, clocks, and untrusted wire
text in, observations out. Three adapters:

- Codex's account/rateLimits/read over the app-server's JSON-RPC stdio. The
  client cannot express a request outside a two-variant enum and answers every
  server-to-client request with -32601, so a harness asking Lumbridge for a
  credential is refused by construction. (0013)
- Claude Code's session transcripts, as a byte-offset tail follower that
  reports nothing until the backlog is read to EOF — a partially-read backlog
  is indistinguishable from a burst of spend, and the first run against 20 MB
  reported forty-six billion tokens an hour. The parser models four counters,
  so the conversations in those files are not representable. (0014)
- Claude Code's five-hour and seven-day subscription windows, via a bridge
  installed as its statusLine command. 0014 had claimed no such surface
  existed; it does, and the record is corrected in place rather than quietly
  edited. Lumbridge does not read the OAuth credential to call the account
  usage endpoint, which is what comparable tools do — AGENTS.md forbids it,
  and 0015 says so rather than leaving the gap unexplained.

Also in here: a capability-check ordering fix in the workspace reducer, where
the applied-request replay table was consulted before the capability check and
so answered questions the caller had no right to ask; the GPUI spike wired to
the live probes with per-harness gauges and provenance chips; and a launcher
that matches its own window by PID, because GPUI sets WM_NAME but not
_NET_WM_NAME and a title match never succeeded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Metal Agent
2026-08-31 21:47:11 -07:00
co-authored by Claude Opus 5
parent 7fe84f71e2
commit ef52aa7ce2
34 changed files with 7319 additions and 137 deletions
+52 -5
View File
@@ -28,7 +28,8 @@ messages should be real from the beginning.
- `lumbridge-pty`: portable PTY and process-tree adapters.
- `lumbridge-terminal`: VT parsing, scrollback, selection, search, render model.
- `lumbridge-acp`: ACP client, capability negotiation, transcript normalization.
- `lumbridge-harness`: manifests, launch profiles, hooks, PTY fallback adapters.
- `lumbridge-harness`: manifests, launch profiles, hooks, PTY fallback adapters,
and documented status/usage probes.
- `lumbridge-provider`: BYOK providers and provider-neutral usage records.
- `lumbridge-storage`: SQLite migrations, event log, snapshots, retention.
- `lumbridge-remote`: OpenSSH/Tailscale command construction, framed stdio,
@@ -41,10 +42,10 @@ messages should be real from the beginning.
- `lumbridge`: installable application entry point.
The scaffold currently contains `lumbridge-core`, `lumbridge-storage`,
`lumbridge-buzz`, `lumbridge-pty`, `lumbridge-runtime`, `lumbridge-terminal`, and
the entry point. `lumbridge-core` also contains the first typed workspace
command reducer. Larger runtime crates are added after their architecture spikes
pass.
`lumbridge-buzz`, `lumbridge-pty`, `lumbridge-runtime`, `lumbridge-terminal`,
`lumbridge-harness`, and the entry point. `lumbridge-core` also contains the
first typed workspace command reducer and the usage ledger. Larger runtime
crates are added after their architecture spikes pass.
## Terminal path
@@ -200,6 +201,52 @@ Observations include account profile, provider, harness, model, units, time
window, reset time, provenance, confidence, and source timestamp. Projections are
derived views that can be recomputed as forecasting improves.
`lumbridge-core` now implements that stream. A bounded per-profile `UsageLedger`
accepts observations in time order, and `project` derives the footer view:
window fraction, reset, burn rate, and exhaustion. Facts keep their reported
provenance; every derived value is labelled estimated. The projection withholds
a burn rate from a single sample, withholds a window fraction without a reported
ceiling, withholds an exhaustion estimate that falls after the reset, treats an
unavailable observation as invalidating older facts, and reports an expired
window as rolled over rather than freezing its last percentage. `FooterUsage`
renders the five product-spec questions and returns explicit unavailable phrases
instead of placeholder numbers. See decision 0012.
`lumbridge-harness` is the other side of that boundary: it runs processes,
reads a clock, and parses untrusted wire text, then hands back observations.
Its first adapter probes Codex's documented `account/rateLimits/read` surface
over the app-server's JSON-RPC stdio protocol. The client cannot express a
request outside a two-variant enum and answers every server-to-client request
with `-32601`, so a harness asking Lumbridge for a credential is refused by
construction. All protocol decisions live in a pure state machine driven by
`&str` lines and an explicit timestamp, with a `replay_transcript` entry point
that verifies the whole path against a fixture without a process, a clock, or a
network. See decision 0013.
Its second adapter reads Claude Code's session transcripts, the only local
surface that reports what that harness spent. It is a tail follower with a
per-file byte offset, so its total is monotonic, and it reports nothing until
it has read the existing backlog to the end — a partially-read backlog is
indistinguishable from a burst of spend, and the ledger would derive a rate
from it. The transcript carries no window or ceiling, so that profile reports
consumption against none. The parser models four token counters and nothing
else, so the conversations in those files are not representable in a Lumbridge
value. See decision 0014.
Claude Code's subscription windows come from a different surface: the CLI pipes
a `rate_limits` object carrying the five-hour and seven-day windows to whatever
`statusLine` command the user has configured, on every turn. A small installed
bridge writes those fields — and only those — to a local feed the probe tails,
so the windows are `ProviderReported` and no credential is ever read. Reading
Claude Code's OAuth token would be more capable and is what comparable tools
do; Lumbridge does not, because AGENTS.md forbids it. See decision 0015.
The GPUI shell now runs both probes; a probe contributes its own profiles on
top of the declared ones, so the Claude windows appear once they report. Its
footer strip
shows every declared harness at once, and a harness with no adapter renders
the honest gap.
Subscription balance is provider-specific and sometimes unavailable. BYOK calls
usually expose token counts but cost still depends on cached tokens, reasoning,
tool calls, and current pricing. Adapters normalize facts without erasing their