Repository navigation
Fix open Collie issues: stops hold, gone agents restart, unsettled launches park, and more - #218
Open
madskronborg wants to merge 18 commits into
Open
madskronborg wants to merge 18 commits into
madskronborg wants to merge 18 commits into
Conversation
added 18 commits
October 26, 2026 13:33
…th the Run A stopped Run carried on after a host restart and filed an issue (#176), and a check it was running outlived the stop, dropped off the board and lost its worktree to cleanup (#211). STOP was honoured only at agent launch and collection and in the memory and CI waits. Step entry now suspends on a stop as it does on a hold. The host refuses to file or comment on an issue for a stopped Run. The host's own check and an agent's collie verify race STOP and end their process group: the host's check parks the Run so a resume runs it again, and the agent is refused with a reason naming the stop. A live running-check record keeps the card working and the worktree out of cleanup.
…gain herdr keeps listing an agent whose process died with its Machine and refuses it as not active. Collie counted an agent gone only when herdr stopped listing it, so the step failed undelivered, a revive waited on a dead agent, and resume said the Run was already running (#160). One predicate now decides gone for delivery, relaunch, revive and steering; the dead agent's pane is closed first, because herdr keeps a name while it lists it. A startup block is no longer read from every agent_not_ready, only from herdr's own wording.
…and take its files as evidence A start given <state>/runs/<id>/plan by hand was put on a branch named plan, cut from the default branch, and its gate refused the plan Run's handoffs as outside every root (#159, #174). One shared predicate now recognises a Run's own plan directory: branch naming never slugs it, placement continues the branch that Run's lineage was placed on unless its merge request has merged or closed, and the gate counts that Run's directory as evidence.
…nly where a reviewer can move a gap A typed, Linear or follow-up source's build writes plan/SPEC.md, yet reviewers were told there was none. Evidence outside every root, or a check that has not passed, is no reviewer's to change, so a fresh gate review over it bought nothing.
… gate and merge request to the current one A Run admitted with the wrong kind looped on gaps it could never close: its gate kept asking a misclassified migration for migrate-up/down, and its reviewers a misclassified refactor for behavior_preserved (#172). set-outcome is an Intent change every door can make, and the implement workflow now reads the kind in an Activity at each review round, gate pass and the merge request instead of once at admission. The plan prompt says what each kind obliges.
… the cap once at the finish, and take a plan's goal from its Solution A Run whose work is only its Outputs could never be judged aligned, a branch past the evidence cap paid for the same truncated judgement at every boundary, and every Run started from a Collie plan had no goal because the planner never wrote an Objective.
…typechecks against the declarations it is held to
…run judge when no Run has work to show
…agent its Run's directory, so notes and MCP output land where the prompts ask
…ep a plan's design artifact as a local copy, and have Desktop's chat ask in its reply when nobody can click
… once, so the test holds whichever order the server takes its drain in A loaded server can take its SIGTERM after a second interrupt, start a further continuation, and have the stop interrupt that too; that is correct under ADR-0059, so the stand-in's lateDrain now holds the drain back by a count to make that order on demand.
…ent gates stop running the whole suite again on a head CI already proves The check came only from the checks remembered for the remote, with no ci field, so nothing told the gate or a Release that CI's test job runs the same bun run check. The committed .collie/verify.json says so and wins over the remembered checks; a test ties it to ci.yml so renaming either side breaks it.
…rk, and hold a steer until a new agent's step has gone out A timed-out start, an unanswered agent listing or a step prompt that did not go out failed the Run, which resume refuses, though a resume lists herdr's agents again and can take up or start the agent. A steer that reached a just-launched agent first held its ledger, and the step's submission failed on that contention with an empty reason. Ledger contention is now waited out like a busy pane, and a refusal with no message says the error's tag and fields.
…rce and outcome sections spliced into them Splitting the build prompt's source and outcome instructions into sections of their own left fragments that mention collie verify without the line, which the build step they are spliced into already carries.
…Runs still runs, not only its leader's
… so two edits made on the same version cannot both apply
…when it failed, and have the never-admitted tests wait for that park
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 branch fixes a batch of open Collie issues, one ticket each. These are its effects:
testjob.It addresses #159, #160, #161, #162, #163, #164, #166, #167, #172, #174, #176, #196, #199, #203, #204, #205, #206, #207, #210, #211 and #212. None is closed automatically, because several have checks that can only run after the merge (listed below).
The outcome this Run was held to: bug.
Verifications
Passed on the branch as it stands (3469260), run by an agent through Collie's collector:
regression,typecheck,lint,format-checkandgate-fix-1-suites.check, which Collie ran itself, failed: 4637 tests passed and 1 failed. The failure is "a host that finds its Herd while a Run finishes offers that Run's blocking drift" (test/oversight.test.ts), which also fails at 56d3c96, where this branch leaves the default branch.This Run is held to one verification:
After the last review
Two gate fixes came after the last review. Each was checked by its own tests and not by a reviewer:
src/agents.ts).regressionin the worktree itself: it failed with ticket 03's sources set back to 6d3d421, then passed on HEAD, so one command now shows both.Open findings, all non-blocking:
Not settled by the run
refusedoutcome, so a resume does not retry that finding. Step entry stops a new filing step, and the next self-improve Run sees the finding again. Making that loop suspend instead was left out as beyond the ticket.agent getonly about an agent herdr still lists, so an agent it no longer lists costs no extra herdr call. The same predicate also decidesgonein steering.plan, not that Run's branch #159 case, where the failedImplement nowchild built the branch.taskInput, not before it. A fan-out's repository Runs, and Implement now, carrytaskand keep their shared branch name. Only a start with notask, as a by-hand start has none, takes the Task's branch, so no Run is handed a branch from another repository.outcomefield. Unset means the admitted kind stands, and null means cleared.host.place, a Run's view and its offer facts all lay it over the launch options, so every reader ofoptions.outcomesees the current kind.unspecifiedis the CLI and chat spelling, since it is the name Collie already gives a Run with no kind.invalid_input. It also refuses a Run whose workflow fixes its own kind, as admission already does. Unlike admission, it does not check a workflow'sselectablelist.outcome.NActivity before each review round, which also refreshes the round's fix prompt, and before the mr step. Inside the gate's gap Activities and the proof's fresh review it is read directly. Build and criteria prompts for later tickets still show the admitted kind, since the ticket names only the rally, the gate and the merge request.hostedtakes an optional module list, so the intent test can save a fixed-outcome fixture beside the defaults.## Objective, else the first## Solution, whichever order they appear in. I replaced the Objective state machine with one firstParagraphUnder helper used for both, so a spec whose first Objective is empty no longer falls through to a later Objective.git rev-parse --git-dirfailing with "not a git repository". The diff's own message cannot be used, because git diff says "Not a git repository" with a capital N in a usage warning.judgetakesagentsDirandboundaryas optional fields. No agentsDir means no Outputs, and no boundary means the finish. This keeps the existing callers and the unchanged guard test compiling. Oversight passes both.skippeddrift line and writes no new judged.jsonat. This matches how a mid-Integration boundary is already skipped, so the card does not list a reason the finish will answer.## Objective, which each Run takes as its goal. The after-merge check of a real plan Run's intent.json is left to the human, as the ticket says.cwdOf(id): Effect<string>besidedirOf. It is an Effect because a sibling's checkout comes from its store row, and owed Runs outside the family need one too. The engine resolves it with the same worktree-else-placed-cwd-else-directory rule, now shared ascheckoutOf.cross-run judgement not asked at <when>: no related Run's work can be shownand returns, with no pending, no evaluated line and nothing owed, even for a Run leaving with nobody to pay.evidenceRootsfrom src/sdk.ts without declaring it in SDK_DECLARATIONS, so the shipped implement workflow failed engine's toolchain test. I fixed it here in a separate commit rather than leave a known gate failure on the branch.<run dir>/handoffsrecursively, in place of the Run's directory, under the same condition: only for a Run with a store row. Asking about a Run that was never started still leaves nothing behind.dirArgs(dir); only Claude declares it, as--add-dir <dir>. The launch passes it the Run's directory as${host.dir}/runs/<run>, the same form agents.ts already uses for attachments, so agents.ts does not import the engine.--add-dirgoes after startArgs and before the settings and MCP arguments, so the existingargs.slice(0, 2)model checks and startArgs tests stand unchanged.unspecified), gets## outcome.unspecified: "No outcome kind is given, so only the checks have to pass." The sentence is a section in implement.md, beside the others, so a user layer can override it like them.{{inputs.plan}}and{{run.dir}}. The workflow's sectionOf fills them when it selects a section, as plan.workflow.ts does for attendance, because the template renders in one pass.input.inputs.outcome), as before this ticket. Re-reading it live for the build (ticket 06's kindNow) is out of this ticket's scope.test.each([1, 2])of the one scenario rather than two hand-written tests, so the assertion is the same code in both orders.{ threadId, turnId }before they are compared, because lint refuses a sort over unparsedunknownvalues.cifield, so the tie holds in both directions.ci, so its gate still runsbun run checklocally. I did not amend the Run's verification, which the ticket did not ask for. The merge request'stestjob proves the check for later Runs.ciexample, workflows.md in the Release section's Checks paragraph.agent_blocked, ten minutes from the first contention. It then returnsexhausted, which parks like a pane that stayed busy. That bound has no test of its own.TransactionOpenerror, notDispatcherDefect, because it is now an expected, transient condition.DispatcherDefectkeeps only the channel-used-after-close case.undeliverable, the delivery refusal the ticket names, rather than in the sharedreason()every caller uses.collie verifyis running: its processes are gone within the stop's grace period.checkis running. Itsbunprocesses are gone within the stop's grace period, and its worktree survives a cleanup. Resume finishes the check (Stopped merged Run leaves background recheck running; cleanup deletes its live worktree #211).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: Collie's gate runscheckon the final tree after review; per the step I did not run the whole suite. Its parts I could run passed through collie verify:typecheck,lint(0 errors; the 112 warnings were there before this branch),format-check, andtouched-suites.run stopandrun resumethe Run. The agent is started again and the Run carries on (A Run whose agent died with its Machine stays running, and resume does not start the agent again #160).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: Collie's gate runscheckon the final tree after review. Per the step, I did not run the whole suite. These parts of it passed through collie verify on 293f6a7:typecheck,format-check,touched-suites(350 pass, 0 fail across 12 files), andlint(0 errors; its 112 warnings predate this branch).lintran on the working tree before the commit.plan/directory opens its merge request from that plan Run's Task branch, not fromplan(An implement Run started from another Run's plan directory gets a fresh branch namedplan, not that Run's branch #159).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: Collie's gate runscheckon the final tree; per the step I did not run the whole suite. It will hit one baseline scenario that already fails on the release base 56d3c96 (see findings).touched-suitesran 601 tests across 8 files: 600 passed, and that pre-existing scenario failed. typecheck, lint (0 errors, the 112 warnings predate the branch) and format-check passed.checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step I did not run the whole suite; the gate runscheck, and with ticket 12 on the branch it is left to CI's test job. Locally, touched-suites (outcome, outcome-records, sdk, implement-content, baseline, baseline-unrelated) had 747 pass and 2 fail. Both failures are the pre-existing, machine-local no-evidence timeout in findings.checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step I did not run the whole suite, and with ticket 12 on the branch the gate leavescheckto CI's test job. Locally, touched-suites covered intent, tools, chat-parity, proposals, evaluator, steer, collie-cli, remote-cli, credentials, outcome, sdk, implement-content, lifecycle, baseline and baseline-unrelated. 943 passed and 1 failed. The failure is the pre-existing, machine-local no-evidence scenario in findings.plan/directory, has the spec's Objective as the goal in itsintent.json, and its card's record shows it (A Run reportsaligned: true — every constraint was checkedwhen nothing was judged #164).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step I did not run the whole suite. The gate runscheck, and with ticket 12 on the branch it leaves it to CI's test job. Locally, on cf6a5cb's tree:touched-suitespassed: 314 tests across intent, drift, oversight, correction, live, plan-repos, implement-content and agents.baselinepassed 694 of 696. The 2 failures are the pre-existing, machine-local scenario in findings.checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step, I did not run the whole suite; the gate runscheck. Locally, on the final tree:touched-suitespassed 160 of 160 (oversight, engine, cards, correction, placement, drift).evidenceRoots, which ticket 04 exported from the SDK but did not declare for authors. That fix is its own commit.cross-run-neighbourshad one failure, a timeout that predates the branch (see findings).<run dir>/handoffs/(Prompts send agents to a handoffs/ directory Collie never creates #203).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step, I did not run the whole suite; the gate runscheck. Locally:touched-suites(agents, harness, handoffs, run-detail) passed 219 of 219.run-dir-neighbours(the cleanup, host, lifecycle, only-writer, run-detail and worktree suites) passed 230 of 231. The one failure is the timeout that predates the branch, in findings.plan/design/, and its tickets name that copy (Implementers re-read a design artifact at the 50k cap when the plan already saved a local copy #206).NO_HUMANdenial in its transcript (Desktop calls AskUserQuestion in turns it started itself and gets bounced every session #207).checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: per the step, I did not run the whole suite; the gate runscheck.baseline(test/baseline.test.ts) at d557148 passed 346 of 347. The one failure is the no-evidence scenario that predates the branch, in findings. touched-suites, typecheck, lint and format-check pass.checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: the gate runscheckon the final tree; per the step, I did not run the whole suite. This ticket changes only test/codex-stop.test.ts and its stand-in.codex-stop,typecheck,lint(0 errors) andformat-checkpass on 6cd1ed3's tree.testjob is green on the merge request's head, and the gate recorded that as thecheck's proof.testjob is green at the head, with no localbun run checkin its record.testjob after opening its merge request instead of running the suite locally.bun run checkpasses on the branch's final tree. It passed on origin/master e53cd71 throughcollie verify(seehandoffs/base-check-e53cd719.log), and in CI run 40305594214. — after merge: the gate runscheckon the final tree, and I do not run the whole suite.checkwas frozen at start, withoutci, so this Run's gate still runsbun run checklocally. The merge request'stestjob proves it for the Runs that start after the merge.checkCheck (bun run check) on the final tree, and it passes. It passed on origin/master e53cd71 throughcollie verify: seehandoffs/base-check-e53cd719.log. — after merge: the gate runscheckon the final tree, and I do not run the whole suite. On this tree the following pass:touched-suites(agents, resume, dispatcher, step-ahead): 224 pass;regression;typecheck,lint(0 errors) andformat-check;verify-told.steer-neighboursran 12 files that steer or deliver (attachments, agent-origin, chat-parity, evaluator, steering-caps, report, finished-steer, host-issues, verify-memory, only-writer, verify-told, live). It had 98 pass and 1 fail: verify-told, which also failed at HEAD and is fixed in 8f69c72 (see findings).