One run per batch: simultaneous hand-offs join one run, a failed run road says so - #1417
Merged
Merged
Conversation
The tests, and only the seams they need (a slow or failing copy cut, a waiting hook, the run's root handed to a belt worker, the name of the run binding). No behaviour changes in this commit; every new test is expected to fail on it.
… store Starting a run is now one critical section, from the look for a live run until the run is registered, and every other hand-off waits at its door and then joins the run as a child. A batch approved at one moment is one run with every hand-off in it. A run road that fails says "task N did not start: <reason>" on both the proposal door and the typed /task, reads as a failure, and starts nothing on the older engine. Only a missing run engine or plan place still takes the older road. A worker is bound to its run's root as well as its store path (PLANDB_RUN), and the plandb CLI refuses a store at that path whose root is another run's. A run row's room takes a message as a note on its task's page. A run row nothing drives answers that it can be stopped instead of "no task N in this session", and a stop settles it.
…ading stops competing with how to stop a task
…ell formed again
…son's folder The pr line was left unstaged by the rename. The test spelled a real checkout under /home, which exists on the machine it was measured on, so it failed there.
…er-batch # Conflicts: # docs/changes/unreleased/1418-ground-lint-remote-path.md # docs/changes/unreleased/1421-ground-lint-remote-path.md # docs/changes/unreleased/ground-lint-remote-path.md # internal/manual/chat/worker-harness.md # internal/session/task.go
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.
What was wrong
One message proposed eight tasks, and all eight were approved at once. Their hand-offs raced to open the conversation's one plan store. A run is registered only after its store is open and its copy is cut, so every hand-off saw "no live run" and opened or set aside the same
plandb.db. Two runs started over one path. The other six failed ("plan store belongs to a different run", or a disk I/O error) and quietly became nodes of the older task graph. The second run's worker was bound to the store by path alone, so it filed its children and itsdones into the other run's plan. That run's row never settled, and its room answeredno task 1 in this session.What changed
beltStartMu/lockBeltStart). It runs from the look for a live run until the run is registered. Other hand-offs wait at the door, then join the run as children, the same way a later hand-off does.ContinueRuntakes the same lock, andopenBeltRunStorerefuses to open while a run is live.NewBeltWorkertakes the run's root from the run's open handle. A worker's command prefix exportsPLANDB_RUN=<root>besidePLANDB_DB. TheplandbCLI refuses a store at that path whose root is another run's, and neither reads nor writes it./taskboth answertask N did not start: <reason>. Nothing is running for it and nothing was started in its place; .... The proposal receipt is marked failed, and nothing is admitted to the older graph. A store seeded for a run that never started is removed. Only a missing run engine or a missing plan place still takes the older road. This replaces do, run, session: codeaf do edits in place, commits nothing, and stops at a price #1416'sIt runs on the older task engine, because the run engine could not start it:receipt. That receipt was honest, but the work still became an old-graph node, which contradicts the "an approved hand-off under the bash belt is a run, never a session-tree node" law. do, run, session: codeaf do edits in place, commits nothing, and stops at a price #1416's test now asserts the refusal shape.left on the task's page — its worker reads it between steps). A row nothing drives says so and that it can be stopped. It never saysno task N in this session. A stop settles such a row asstopped.worker-harness.md. Change entry:1417-one-run-per-batch.md(fixed).TestAPathOnAnotherMachineDoesNotRefuseTheTaskspelled a real checkout under/homeas its "remote" path. That directory exists on the machine it was measured on, so the test failed there. It now names a folder that exists nowhere.This PR does not touch
internal/tui3. The◑ $guard and the running glyph moved to #1420.Tests: each shown red on the unfixed code first (Spark, commit 199bd9d, tests plus seams, no behaviour change)
TestEightHandoffsApprovedAtOnceAreOneRun: 8 approved proposals committed at once throughstageTask/ResolveTask/Commit, with the first copy cut held slow and a fixed clockTestAHandoffWhoseRunRoadFailsIsNotASilentNode(both doors)task 1 started, a node admitted, typed/taskerr=nilTestARunRowNothingDrivesAnswersAMessageAndStopsno task 1 in this session; the stop said "has already finished"TestALiveRunsRowsTakeAMessageAndAMissingOneStopsTestABeltWorkerIsBoundToItsOwnRunTestPlandbCliRefusesAnotherRunsStore(internal/plandb)TestBashWorkerCannotWriteIntoAnotherRunsStore(internal/run, a real worker and the real CLI)All seven pass on the final head, f0bc033.
Gate: Spark, fresh clone, final head f0bc033 (includes a real merge of santos/dev2 at 147382a)
go build ./...: EXIT 0go vet ./...: EXIT 0make test PKGS="./internal/session ./internal/plandb ./internal/run ./internal/manual" TEST_FLAGS=-count=1(box lock): EXIT 0make check TEST_FLAGS=-count=1: EXIT 0 (bin/codeaf 53412105 bytes, under budget; cross builds pass)One touched run before that went red on
TestARecallThatLandsBeforeTheFirstWordIsAskedAgainWithIt(turn did not finish; events so far: []). This red is not caused by this change. The same test fails the same way on a clean santos/dev2 at 147382a when starved (GOMAXPROCS=1 -cpu 1 -count=60: one failure on each tree). It is a load-sensitive defect in the recall path and is worth its own issue.