Repository navigation
feat: let a claim and a completion carry an attempt key - #77
Merged
Merged
Conversation
The paper gives each task operation an attempt key from the caller, so a retry cannot claim two tasks or complete a task two times (Appendix A, Appendix C). The ledger had no such key. A caller that did not get the answer to `claim_next` and asked again got a second task. - `claim_next_once` takes a key. The same key asked again gives the same claim, while that claim is in force for that holder. When the claim is over, the ledger refuses the key with `Error::AttemptSpent`. - `complete_once` takes a key. The same key asked again gives the done task, and the ledger appends no second event. A key that was used for a different task or a different operation is refused. - The key is in the event of the claim or the completion. The ledger finds it in the events, so a rebuild keeps it. The event of a claim now also has its generation. - The memory tools `claim_next` and `complete` take `attempt`. `amem task claim-next` and `amem task complete` take `--attempt`. - A completion asked again reaches the ledger after the session forgot the claim. A test of the tools found that the session refused it first. Not in this change: an attempt key for the other operations. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… claim This commit merges `main` and changes the attempt keys of 98646df. The adversarial pass ran on 98646df and confirmed nine findings. - A key was the same for each session of an author, and on SQLite for each domain. A second session with the same key got the claim of the first. A session with low handling got a restricted task. The memory server now keeps a key under its session and its operation. The ledger looks for a key in the domain of the claim. It gives the claim back only to a caller whose name, handling and manifest fit the task. - The refusal for a used key gave the id of the task. It now gives only the key. - The ledger looked for the key before the transaction of the claim. Two callers with one key claimed two tasks. Each backend now looks in that transaction. PostgreSQL takes the lock of the domain first. - A completion asked again ran the close of the continuation chain again, with the handoff of the second call. It now changes nothing. With a different handoff, the ledger refuses the key. - One key for a claim and for a completion of one task was refused. A key now belongs to one operation. - A key had no limit. A key is now 1 to 64 letters, digits, dots, hyphens or underscores. - `amem task claim-next` and `complete` no longer take `--attempt`. A command has no session, so its key could not be found again. - Tests now hold the generation check of a key, the domain of a key, the handling of the caller, a second session, a bad key, and a completion asked again with a different handoff. A test of this branch claimed the first of two tasks that were filed at one time. The queue order of `main` is now by time and then by id, so the test gives the two tasks different times. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The second adversarial pass found no defect in behaviour. It found rules that no test held. Each new assertion failed against a mutation of the code before this commit kept it. - Two connections with one key make one claim. Without the domain lock in the PostgreSQL lookup, the new test fails. - A lapsed lease ends the claim of a key. A caller without the requirements of the task does not get the claim back. - A completion asked again closes no task up its chain. Changes in behaviour: - The kept key is the session and the caller's key. The operation prefix is gone, because the ledger looks among claims or among completions. - A refusal names the key as the caller gave it. - `complete` reads the task with the ledger locked, so a second call with the same key reads what the first call left. - The message and the README say that a key is ASCII, and that a key belongs to one domain. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
sstriker
marked this pull request as ready for review
November 12, 2026 12:30
sstriker
added a commit
that referenced
this pull request
Nov 12, 2026
Main has the attempt keys of #77. The plan keeps the rows of both, and the MCP tests of both stand. Co-Authored-By: Claude Fable 5.2 <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.
This is one more part of package 2 of
PLAN.md.The paper gives each task operation an attempt key from the caller, so a retry cannot claim two tasks or complete a task two times (Appendix A, Appendix C). The ledger had no such key. A caller that did not get the answer to
claim_nextand asked again got a second task.What changes
claim_nextandcompletetakeattempt. A key is 1 to 64 ASCII letters, digits, dots, hyphens or underscores.claim_nextwith the same key gives the same claim, while that claim is in force. It does not give a second task. When the claim is over, the ledger refuses the key.completewith the same key and the same handoff gives the done task. The ledger completes the task one time, and nothing else occurs for the second call. With a different handoff, the ledger refuses the key.<session>:<key>. A different session with the same key makes its own claim. The ledger looks among claims for a claim and among completions for a completion, so one key can be used for each. A refusal names the key as the caller gave it.local/README.md,README.md,PLAN.mdanddocs/terms.mdhave the attempt key.Not in this change
An attempt key for the other operations.
amem taskhas no attempt key, because a command has no session.Checks
make checkpassed with 985 tests on 09bfe14. The ledger tests ran on SQLite and on the embedded PostgreSQL.Adversarial pass
The pass ran on 98646df, the first form. It confirmed nine findings, and 295b01a corrects them:
A second pass ran on 295b01a. It ran its own tests and mutations on SQLite and on the embedded PostgreSQL. It confirmed no defect in behaviour. It confirmed six findings about tests and text, and 09bfe14 answers them:
two_connections_under_one_key_make_one_claimfails on PostgreSQL when the lookup does not take the domain lock.same_claim. Each new assertion fails when its term is removed.a_completion_asked_again_closes_no_task_up_its_chainfails when the second call runs the chain.The pass also named these points as plausible, without a test that shows them:
completecould read the task before the first call ended, and then getNotHolder.completenow reads the task with the ledger locked. No test holds this.local/README.mdnow says so.completestops after the ledger completed the task and before the chain closed, the second call gives the done task and the parent stays open. Before this branch, the second call gotWrongState, and the parent also stayed open.I stop at two passes.
Posted by Claude on behalf of @sstriker
🤖 Generated with Claude Code