loop: a claim, because two sessions took the same three tasks - #3332
Merged
Conversation
Two sessions of this loop ran concurrently and picked the same three tasks from the same list of recommendations, opening PRs for all of them (#3314, #3317). Nothing in the flow says who is working on what. `tri loop claim <name>` uses the one atomic operation git gives over a shared remote: creating a ref that does not exist. Exit 0 it is yours, 1 someone has it and the line names them, 2 the attempt could not be made -- which is not the same as being refused. THE OBVIOUS VERSION DOES NOT LOCK, and I measured it before writing this one. Pushing `origin/master` to the claim tag succeeds for the SECOND claimant too: git treats re-pushing the same value to an existing tag as a no-op and exits 0, so both sessions believe they hold it. Two sessions of this loop sit on the same `origin/master` almost by definition, so that lock would have been worse than none -- it reports success. The claim is therefore a commit no other claimant can produce: an empty tree with a message naming host, pid and HEAD. Measured: ALPHA exit 0, BETA exit 1 with the holder named. A refused push with NO holder exits 2, not 1. That is a broken push rather than a lost race, and reporting it as HELD would send the next session away from work nobody is doing. Two mutants killed -- borrowing the claim value from an existing ref, and reporting a broken push as held. The second test could not kill anything until it was fixed: it sliced from the first `match holder` to end of file and asserted `contains("exit(2)")`, which four unrelated exit-2 sites satisfy. CENSUS. Three moved and they are not all mine: fetches files read 43 -> 44 MINE: cli/tri/src/loopclaim.rs quiet named a path but not quiet 128 -> 127 already moved on master shell run: steps 235 -> 234 already moved on master A clean `origin/master` worktree fails `census pin --gate` with the last two before any change of mine, so the pre-commit hook has been failing for every author since a workflow edit landed unblessed. This commit carries the bless it inherited and says so rather than passing it on. Getting there took four wrong turns worth recording: `census pin` WITHOUT `--gate` exits 0 whatever moved, and I read that non-verdict as "nothing moved" twice -- once as the control that supposedly cleared master. Refs #3331 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag
enabled auto-merge (squash)
September 5, 2026 19:15
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
This was referenced Sep 5, 2026
The branch was green with auto-merge armed and BEHIND by nine commits, and `allow_update_branch` is false, so nothing but a session could move it. The claim mechanism it carries is the one both concurrent sessions need: this pass alone duplicated an issue already open (#3323 against #3333) and nearly retook a task a neighbour had finished. Two censuses moved and are re-blessed in this same commit, as the gate demands: `quiet` 127 -> 128 (one more path named but not quiet) and `shell` `run: steps` 234 -> 235, both from the nine commits being merged in, not from this branch's own work.
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
PR DashboardGenerated at: 2026-09-06 03:42:30 UTC
Summary
Seal Status
|
This was referenced Sep 6, 2026
Closed
gHashTag
added a commit
that referenced
this pull request
Sep 6, 2026
…3357) (#3358) Two sessions ran concurrently on 2026-09-06 sharing one checkout and one `target/`, and neither had a way to find out. Every symptom was attributed to the tool being measured: a commit that "did not form" while `git push` reported success (it pushed an unchanged HEAD), a built binary that lost a subcommand it had a minute earlier, census readings that flip-flopped between runs, and a HEAD sitting on a branch this session never created. That is the broken-ruler error with a second session as the ruler. R17 writes down what `tri loop claim` (#3332) made possible: own the tree, take the claim first, and do not diagnose a shared tree through the tree. It also records the trap found while following it. A private `CARGO_TARGET_DIR` -- the thing that makes the tree private -- hides the binary from `.githooks/pre-commit:52` and `.githooks/commit-msg:14`, which probe `$ROOT/target/{debug,release}/tri`. They report "not built", refuse with exit 2, and the commit silently does not form while the next push reports success. The fix is a symlink where the hooks look, and checking that `git rev-parse HEAD` moved rather than trusting what `git commit` printed. Resealed: the rule file changed, so `LOOP-RULES.sha256` moved with it in this commit. R6 -- the seal certifies identity, not correctness. Co-authored-by: lab <lab@example.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
gHashTag
added a commit
that referenced
this pull request
Sep 6, 2026
* skill: spool five lessons from pass 119 (Refs #3236) Written with `tri skill add` and left UNNUMBERED, deliberately. A branch that also runs `fold` picks its number against its own base and collides exactly like a direct append; folding belongs after the merge. The five: - A refusal recorded only in prose is invisible to the tool that advises against it. `gates unmeasured` printed `dispatch: NO` beside "add `workflow_dispatch:` first" for the workflow #3325 had just deliberately removed one from -- that is, it advised putting a dispatch back in front of `cargo publish` on a live registry. A two-state predicate over a three-state domain is the shape. - Two date fields render in two timezones. `%ad` and `%cd` each print in their OWN recorded offset, which made one commit read as a seven-hour clock skew. Compared as epochs: 0 of 20. The tell was that the date order ran against topology. - Assert that the edit moved, not that the anchor exists. Two scripted edits reported success and changed nothing; the second because `find()` returned -1, `s[-1:j]` is the empty string, and `replace("", new)` inserts at position 0. - A private target dir hides the binary from the hooks. `.githooks/pre-commit:52` probes `$ROOT/target/{debug,release}/tri`; with `CARGO_TARGET_DIR` elsewhere the commit silently does not form while the next push reports success. - A gate whose workflow is not a required context cannot block a merge. This one refutes a claim I had already published in #3332: replayed over twelve first-parent commits with the tool unchanged, exactly one fails, blessed nineteen minutes later. `tri skill check`: 556 sections, no number used twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * skill: a quoted diagnostic is not a command invocation (Refs #3236) `Documented t27c subcommands exist` went red on this branch alone: dead `tri` mentions rose 141 -> 142. The offender was mine, and it was a QUOTATION. The lesson about stale binaries quoted the hook's own warning inside one code span -- `target/debug/tri is older than cli/tri/src`. The gate extracts `tri <word>` from code spans, so it read a subcommand `is`, which resolves on none of the four surfaces. Correctly: the gate is right, the text was wrong. Split into two spans, so the prose reads the same and the code spans name only paths: `target/debug/tri` is older than `cli/tri/src`. Measured rather than assumed, with both controls run first because the obvious probe was itself broken -- `$B $sub --help` does not word-split in zsh, so both mentions reported DEAD until the probe used `${=sub}`. With a must-resolve and a must-not-resolve control behaving correctly, the two `tri` mentions my files introduce (`tri census pin`, `tri gates unmeasured`) both resolve, and `tri is` is gone. The ratchet returns to 141. Not amended: the branch is pushed, and this repository never force-pushes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: lab <lab@example.com> Co-authored-by: Claude Opus 5 <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.
Two sessions of this loop ran concurrently and picked the same three tasks
from the same list of recommendations, opening PRs for all of them (#3314,
#3317). Nothing in the flow says who is working on what.
tri loop claim <name>Git gives exactly one atomic operation over a shared remote: creating a ref that
does not exist.
Exit codes follow the repo's vocabulary: 0 taken · 1 refused, and the
line names the holder · 2 the attempt could not be made — which is not the
same as being refused.
The obvious version does not lock
Pushing
origin/masterto the claim tag succeeds for the second claimanttoo — git treats re-pushing the same value to an existing tag as a no-op:
Only a different value is rejected, and two sessions of this loop sit on the
same
origin/masteralmost by definition. That lock would have been worse thannone, because it reports success.
So the claim is a commit no other claimant can produce — an empty tree with a
message naming host, pid and HEAD:
A structural test pins that the claim is built, not borrowed; mutating it
back to
rev-parse origin/masterfails the suite. A second pins that a refusedpush with no holder exits 2 — a broken push is not a lost race, and
reporting it as HELD sends the next session away from work nobody is doing.
That second test could not kill anything until it was fixed: it sliced from the
first
match holderto end of file and assertedcontains("exit(2)"), whichfour unrelated exit-2 sites satisfy.
Census: three moved, and two are not mine
fetchesfiles readloopclaim.rsquietnamed a path but not quietshellrun: stepsA clean
origin/masterworktree failscensus pin --gatewith the last twobefore any change of mine. This carries that bless and says so rather than
passing it on.
Correction, measured after this merged. The clause that stood here — "the
pre-commit hook has been failing for every author since a workflow edit landed
unblessed" — is false. I generalised it from a single observation and published
it without measuring. Replaying
census pin --gateover the last twelvefirst-parent commits of
master, with the tool itself unchanged across thewindow (
cli/tri/src/census.rs: 0 commits), exactly one commit fails:3429f9c6. The next commit blesses it nineteen minutes later. The red windowwas one commit, not an era.
The replay showed two things worth more than the claim they replace.
cli-tri.yml, wherecensus pin --gateruns, is not one of the fourrequired contexts (
check,check-linked-issue,check-now-freshness,validate), so a red census cannot block a merge; and a GitHub squash-mergenever runs a local hook, so the pre-commit census guard binds local commits
only.
3429f9c6merged red for both reasons at once — which is also why thepin oscillated
235 → 234 → 235in under an hour, one commit blessing areduction that the next reverted.
Worth recording how long that took:
census pinwithout--gateexits 0whatever moved. I read that non-verdict as "nothing moved" twice, once as the
control that supposedly cleared master, and spent several commands chasing a
phantom the hook's own preamble had already explained.
791 tests pass. Claimed
pass-118with the tool while writing this.Refs #3331