Conversation
…is built from The /v1 task projection (the Tasks list, every receipt, attention and the task timeline) was cached on the events fingerprint alone, with a 30 s expiry. It is built from more than events: - the continuation store, whose user-confirmed groupings decide which sessions form one Task. A link, unlink or rename records no ledger event, and nothing invalidated the cache, so the app kept showing the old grouping for up to 30 s; - the cost, run and Evidence stores, through the shared ledger. The ledger itself rebuilds for those at once (its key folds in their signature); the projection assembled over it did not. Key the projection on everything it is built from: the shared ledger's own change key plus the continuation store's signature. The 30 s bound stays, now only for the one input that is the wall clock: the weekly-plan shares are calibrated over a window ending "now". The background warmer builds this projection too (without counting as a reader), and its change token covers the continuation store. On a copy of a 12,000-event store, a receipt opened three seconds after a write went from 279 ms median to 20 ms. tests/test_task_projection_cache.py: four of its six tests fail on main, including "a continuation link is visible to the very next reader" (main answers 2 Tasks where the store says 1). The other two guard what is preserved: an unchanged store is reused across routes, and the wall-clock bound still recomputes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
/v1task projection backs the Tasks list, every receipt, attention and the task timeline. It was cached on the events fingerprint alone, with a 30-second expiry. It is built from more than events, so the app could show an answer older than the store:_ledger_secondary_signature); the projection assembled over it did not. The old comment accepted this as "can lag up to ~60s".Reproduced on
mainby the new testtest_a_continuation_link_is_visible_to_the_very_next_reader: after a link,/v1/tasksanswerstotal == 2where the store says 1.Fix
src/agentacct/api.py(size, mtime)signature (actions.jsonlis its only persisted state, append-only). The same ledger key is passed down, so the projection and the ledger it is assembled over stay in lockstep within a request.for_reader=Falseso its own build cannot keep it awake, and its change token now covers the continuation store.I audited the projection's inputs before changing the key: events, the ledger (and its stashed mechanical checks), cost events and the continuation projection. It does not read ingestion health; the task-identity codec and CSRF token are constant for the process;
task_projection,task_outcomeandreceiptdo not read the clock.Measured
Copy of a live 12,000-event store, real warmer thread, a receipt opened three seconds after a write:
main(with #305)Tests
tests/test_task_projection_cache.py, 6 tests. Four fail onmain:mainassert 2 == 1Validation
pytest tests/ -n 4 --dist loadfile -p no:randomly: 4,502 passed, 1 failed. The one failure,test_display_alignment.py::test_real_titles_are_worth_showing_in_full, also fails on unmodifiedmainon this machine: it measures this Mac's real recorded task titles (19.6% exceed the card budget against a 15% limit) and does not touch this code.Not addressed
🤖 Generated with Claude Code