Skip to content

fix: preserve request cost history and recover quota pricing surfaces - #40

Merged
Mars-Sea merged 3 commits into
feat/pr36-panel-and-session-costfrom
codex/pr38-review-fixes
Sep 14, 2026
Merged

Mars-Sea merged 3 commits into
feat/pr36-panel-and-session-costfrom
codex/pr38-review-fixes

Conversation

@Mars-Sea

@Mars-Sea Mars-Sea commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Fixes the six review findings in #38. This PR targets feat/pr36-panel-and-session-cost, so its diff contains only the repairs; merge it into #38 before merging that feature into main.

Session costs previously applied the latest model and the viewing time to all cumulative tokens. A durable Host projection now retains each request's model, attempt timestamp and prompt context band, replaying both v1 usage samples and v2 message/attempt settlements. Samples replace within an attempt, retries add, and equivalent billing groups remain compact. The client verifies that cost facts and token totals describe the same history before displaying an estimate.

  • Preserve earlier spending across paid/free model switches and peak/off-peak viewing times.
  • Carry all eight models' complete context tiers through the generator and Remote; select bands per request, including cached input.
  • Let Host-resolved credentials drive quota availability, including composition literals and CLI-auth fallback, in both the sidebar and settings usage card.
  • Distinguish missing purchased/free balances from reported zero throughout the dashboard, settings and command output. Omit balance ratios with missing inputs or zero denominators, and print a single percent sign.
  • Retry transient price-table failures three times with 1/2/4-second backoff, retain manual refresh, and discard stale results when the Host namespace rebinds.
  • Label published-rate estimates and partial subtotals explicitly; hide costs on older Hosts without durable facts and suppress zero subtotals when free usage is mixed with unpriced usage. Update documentation and generated bundles.

Validation: 486 tests passed, npm run typecheck, npm run build, npm pack --dry-run, git diff --check, and live node scripts/sync-model-prices.mjs --check (68 rows match). Regression coverage includes real projection-registry history restoration/checkpoint views, v1/v2 retry semantics, model/time changes, context boundaries, credit presence, unknown/zero subtotal suppression, settings-card Host availability, bilingual command ratios and bounded price retries.

The estimate uses the installed published-rate snapshot; it is not a provider invoice. Live browser/Host interaction and invoice reconciliation were not performed. No dependency metadata changes or release publication.

Follow-up to the review of the previous two commits: no behaviour changes, so
the 486-test suite and the generated bundle are unchanged in substance.

- Record the ONE real gap in the durable cost facts: the fold implements the
  0.1.5 token-meter replacement rule (`llm/retry-started` closes the slot, so a
  retried attempt adds), while the 0.1.2/0.1.3-era fold replaced on
  `(turn, step)` alone and never handled that event. On those engines the two
  folds disagree by the retried attempt's tokens, and the client's per-bucket
  equality gate against `tokenUsage` then hides the readout instead of showing
  a wrong figure. Retries are routine on this route and both versions are
  declared compatible, so it is a live gap rather than a theoretical one. The
  note also says why the equality gate must NOT be loosened to work around it.

- Record why the settings usage card reads availability from the Host report:
  a composition literal is a stripped secret and the CLI auth file is not in
  the credentials store, so both are invisible to the browser while the Host
  serves requests with them. `state.anyAccountConfigured` must not gate that
  card or the post-save refresh, and `shouldRefresh` stays `idle`-only so a
  failed fetch cannot become an automatic request loop.

- `requestRates()`: document that a tiered row returns its band and does not
  then apply `peak` (the page publishes the two dimensions independently and no
  row carries both today), and that the band `find` is order-dependent on
  purpose because both the generator and the wire parser reject non-ascending
  bounds or a bounded last band.

- Fix two stale claims this work left behind: the controller JSDoc was attached
  to `PriceRetryTimer` and still called the cache "one-shot" (it now has a
  bounded 1/2/4 s retry budget and a rebind reload), and `ensure()` claimed the
  composer mounting was a trigger when its only callers are the namespace
  landing and a manual refresh. Same for the two AGENTS.md one-liners, plus
  the module/test entries the layout block was missing.

- Note that `isPeakHour()` in `src/client/session-cost.ts` is a dead third copy
  of the weekday rule (only its own test calls it; it is DCE'd out of the
  bundle) so the next reader deletes it rather than re-wiring it.
@Mars-Sea
Mars-Sea merged commit 1e2f7be into feat/pr36-panel-and-session-cost Sep 14, 2026
4 checks passed
Mars-Sea added a commit that referenced this pull request Sep 14, 2026
Ported from #36 by @xer-on, with the review fixes from #40 folded in: correct published rates and a sync script, per-request cost history instead of repricing cumulative tokens, Host-resolved credential availability, unreported-vs-zero balances, and the compatibility gate for the sidebar card.
@Mars-Sea
Mars-Sea deleted the codex/pr38-review-fixes branch September 14, 2026 15:01
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