diff --git a/TODO.md b/TODO.md index b206f8f6..febc9440 100644 --- a/TODO.md +++ b/TODO.md @@ -447,27 +447,21 @@ outside the example's new README: ## Waiting on the owner to run it -- [ ] **The AI usage panel has never run.** Landed 2026-08-18. Click the harness pill in the chat composer - and it shows Claude Code's own usage display — limits with countdowns, tokens by day and by model — - with one tab per Anthropic account, so a login you have switched away from still answers. +- [ ] **The AI usage panel works for one account; the multi-account half is unproven.** Landed and verified + live 2026-08-18 — click the harness pill in the chat composer and it shows Claude Code's own usage + display, limits with countdowns, tokens by day and by model. - **Two things must happen before it does anything**: `bun db:push` (it adds `ai_provider_usage`) and - `pm2 restart officer officer-claude-code`. Neither has been run. Without the push the panel opens and - shows the signed-in account with no tabs, which is the designed degradation rather than a failure. + What is NOT proven is the reason it was built: a second Anthropic login, the account tabs, and a + stored row surviving a switch. **Group C of `docs/ai-usage-panel.md`** is that, and test 10 is the one + most likely to be wrong — a refresh must not overwrite an account it could not measure, and that + failure is silent. - **`docs/ai-usage-panel.md` is the checklist** — sixteen ordered tests in five groups. Group C is the - feature: sign in as the second account and confirm the first one keeps its numbers and its countdown. - Test 10 is the one most likely to be wrong — a refresh must not overwrite an account it could not - measure, and that failure is silent. + Deliberately deferred rather than forgotten: the owner switches accounts when the work needs it, and + the worst case is one wrong tab. Run Group C the first time a second login lands on this machine. - Safe to leave untested. Everything is read-only except one fire-and-forget upsert at turn end, and the - pill was already an inert label before this. The one thing worth watching is `pm2 logs officer` during - a turn: the snapshot is `void`ed and swallows its own errors, so a persistent failure shows up only - there and as a row that never updates. - - Shipped alongside it and also unexercised: the model dropdown no longer renders the literal string - `claude-code` for a chat that named no tier. That half needs `officer-claude-code` restarted, not just - `officer` — the parser in the sidecar is what emits it. + Also unexercised: the model dropdown no longer renders the literal string `claude-code` for a chat + that named no tier. Needs `officer-claude-code` restarted, not just `officer` — the parser in the + sidecar is what emits it. - [ ] **Plan mode is live and has never been exercised.** Landed `1b811dfa` on 2026-08-17; all three processes were restarted the same evening, so the code IS running. Not one part of it has been used: diff --git a/docs/ai-usage-panel.md b/docs/ai-usage-panel.md index d7ef72db..a23721f1 100644 --- a/docs/ai-usage-panel.md +++ b/docs/ai-usage-panel.md @@ -1,8 +1,12 @@ # The AI usage panel -**Built 2026-08-18. Never run against a live server.** The parts with unit tests are noted below; nothing -here has been exercised through HTTP, through a real turn, or with two accounts. The test plan at the end is -what "tested" would mean. +**Built and running 2026-08-18. Verified for ONE account, never for two.** The owner confirmed the panel +live the same day: limits, countdowns, tokens by day and by model all render against the signed-in account. + +What that leaves untested is the half the cache exists for — a second Anthropic login, the account tabs, and +a stored row surviving a switch. Group C of the test plan below is that, and it is the only part still worth +running. It will be run when it is needed rather than pre-emptively, since the failure it would catch costs +nothing but a wrong tab. Click the harness pill in the chat composer — the label reading **Claude Code**, left of the background-job button — and it opens what Claude Code's own usage display shows: limits with reset countdowns, tokens by @@ -18,6 +22,11 @@ pm2 restart officer officer-claude-code `db:push` first. Without the table the panel still opens and still shows the signed-in account — the stored read catches and returns an empty list — but there are no tabs and nothing survives an account switch. +That degradation was not free: it was broken on the first deploy and fixed the same day. `snapshotClaudeUsage` +had the read and the write in ONE `try`, so a missing table threw on the upsert and discarded a perfectly good +reading — the panel said "Not signed in" over an account that was signed in fine. The write has its own `try` +now, and `usage-store-degradation.test.ts` holds the line. + Both processes are needed for the _other_ change that shipped alongside this (`model:resolved`, see "Related" below). The usage panel itself only needs `officer`.