Repository navigation
Description
Priority / target
P2 · correctness-driven state consolidation · medium accounting/reset risk. Preserve local token savings, costs, resettable counters, history and terminal-monitor behavior. Remove independently authoritative in-memory totals and per-call captured-total rewrites of the same cumulative fact.
Evidence
At 1bf9f0819465b2720241b20057510ff01dfa633a, McpServer::spawn_token_accounting_persist increments an AtomicU64, captures new_total, and spawns an observed async write. That task sets project tokens_saved, increments a separate local counter, and upserts a project total through the ledger sink. The first two errors are discarded.
store_meta.rs::set_tokens_saved stores the supplied absolute value through metadata; it is not an atomic increment or a compare-with-newer-total operation. Shutdown in server/connection.rs writes the in-memory absolute total again. requests.rs separately emits the underlying savings/analytics observation.
Two accounted completions can capture totals A then B while their independently scheduled persistence tasks execute in the reverse order. The setter itself has no monotonic/version condition, so stale captured state is not rejected there. This is a source-derived ordering risk, not a reproduced end-to-end counter regression; implementation must test the actual recorder scheduling and shutdown ordering.
Exact implementation
- Choose the existing registered accounting/store owner for the durable cumulative total. Submit the actual per-response accounting delta/identity there once, and update lifetime/resettable projections with their documented semantics. Reuse existing savings observations where they already establish the needed identity; do not add another event-sourcing subsystem.
- Replace per-call absolute snapshots with an atomic durable increment or an existing authoritative projection operation. Keep overflow typed. Make any in-memory display total a derived/read-through view, not a competing source that overwrites the database on shutdown.
- Delete stale absolute setters and duplicate final-total reconciliation once all production callers use the canonical owner. Where a profile summary remains a necessary projection, update it from committed authority with ordering/replay guarantees rather than independently captured values.
- Preserve reset-counter as a distinct operation: lifetime savings and a resettable session/user counter are not interchangeable. Serialize reset versus new deltas at the actual owner so older queued work cannot undo a reset or be counted in the wrong epoch.
- Keep nonblocking tool responses and existing observed-write shutdown settlement. Surface persistence failure through existing diagnostics instead of dropping it or crediting a durable total that never committed. Retrying a write must not double-credit the same completed response.
- Preserve separate analytics/cost and monitor semantics; their different output purposes do not require duplicating authority for the total. Keep per-project/profile attribution and existing opt-out behavior.
Acceptance
Controlled reverse-order completions cannot decrease or duplicate the durable lifetime total. Concurrent calls, reset interleaving, disconnect, restart and shutdown-with-pending-writes produce consistent committed results. Inject failure in each existing persistence stage; the system reports degraded accounting without fabricated durable success. Historical local totals and monitor output remain readable. Run actual MCP accounting/registered-store integration tests through Bazel, and report eliminated writes/state owners rather than assuming fewer methods means less I/O.
Distinct from #3619's worldwide-counter retirement, which explicitly preserves this local capability, and #2392's observability batching. Exact setter issue search found no matching task. Static source review only; no Rust concurrency test, production accounting incident or performance measurement is claimed.
Activity
fix(accounting): refuse oversized savings ledger token counts
fix(accounting): stop uncommitted monitor token credits
style(accounting): apply hosted Rustfmt corrections
fix(accounting): gate savings history and analytics credit on project…
ScriptedAlchemy commentedon Nov 9, 2026
Coverage checkpoint, 2026-11-09: #4852 is now the single active accounting PR, replacing #4811 (closed unmerged; old branch/history retained). Current head
0ebb86a6a717c80833150093c5548aeadf210901, prerequisite #4831 at0bdd2a376dea87086bf6ea9c8e4e57ff5d4b88ce, complete tree042b48cab2d5fe17d3d5f97866f551b3938bd40didentical to repaired #4811d0f314b. Five existing source/test files retained unchanged. The original strict-Clippy unused-import error is removed; the new conforming single-commit title repairs the immutable historical commitlint blocker without force-rewriting history or changing gates.Exact-head CI 42702961402 is queued, not passed. Maintenance should use #4852 and preserve its prerequisite/review/CI holds; do not merge into the feature prerequisite branch. This is Refs #4447 only: durable per-response idempotency, reset/retry/restart/disconnect and all failure-stage acceptance are still outstanding. No issue closure or owner-slot recycling is justified. Existing schedules and protected model/release PRs are unchanged.
style(accounting): apply exact hosted rustfmt corrections
fix(accounting): preserve durable credit and monitor failures (#4852)