Name the failure when task setup dies before the worker spawns#37
Conversation
Failed tasks keep their worktrees (by design, for post-mortems), so a follow-up run with the same run_name collides with the stale taskdir. In the field that surfaced as verdict ERROR at 0.0s with an empty log, empty check output, and no message anywhere — a full diagnosis cycle to discover what one sentence could have said. Three surfaces now carry the reason: - the collision message names the exact unblocking command (git worktree remove --force <taskdir>) instead of a bare "already exists" - _record_prepare_error stores the reason on the task record as setup_error (included in the run-state payload for the HUD and post-mortems) and appends it to the worker log, which is where log_tail, activity, and humans look first - the run summary prints a "setup failures (no worker was spawned)" section listing each affected task with its reason Test: end-to-end worktrees run against a temp git repo with a pre-existing stale taskdir — asserts the ERROR verdict now travels with the collision message in the summary, the worker log, and the run-state record's setup_error field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A linked worktree has a .git file; only then is `git worktree remove` the right recovery, now printed repo-qualified and shell-quoted so it is paste-safe from anywhere. A plain directory in the way gets named as exactly that. Tests cover both branches with a real registered stale worktree and a bare directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Merging this one — thank you. The instant-fail-with-empty-everything signature has personally cost us a diagnosis cycle (it's been folklore in our MODEL-NOTES since), and routing the reason to all three surfaces an operator actually checks — worker log, run state, summary — is the right shape. It also cleanly separates never-spawned failures from model evidence, which matters to how we read the scoreboard. One maintainer-side adjustment before merge (your authorship stays on the commit): the recovery command is now printed only when the stale path is a registered worktree ( Full suite green at 215 tests. Also: the joint-design invitation on #33/#36 is genuine — this PR's |
Every merged community contributor must appear in README Contributors — tests/test_contributors.py audits git history (squash authors + merged-PR handles) against the section and fails on any omission; CI checks out full history for it. README refresh: all four merged contributors credited (#24 #30 #4 #37 #38), --baseline documented, canonical-route enforcement mentioned in the taxonomy section, CI badge added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Jones-Projects#37) * Name the failure when task setup dies before the worker spawns Failed tasks keep their worktrees (by design, for post-mortems), so a follow-up run with the same run_name collides with the stale taskdir. In the field that surfaced as verdict ERROR at 0.0s with an empty log, empty check output, and no message anywhere — a full diagnosis cycle to discover what one sentence could have said. Three surfaces now carry the reason: - the collision message names the exact unblocking command (git worktree remove --force <taskdir>) instead of a bare "already exists" - _record_prepare_error stores the reason on the task record as setup_error (included in the run-state payload for the HUD and post-mortems) and appends it to the worker log, which is where log_tail, activity, and humans look first - the run summary prints a "setup failures (no worker was spawned)" section listing each affected task with its reason Test: end-to-end worktrees run against a temp git repo with a pre-existing stale taskdir — asserts the ERROR verdict now travels with the collision message in the summary, the worker log, and the run-state record's setup_error field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Only print the worktree-remove command when it will actually work A linked worktree has a .git file; only then is `git worktree remove` the right recovery, now printed repo-qualified and shell-quoted so it is paste-safe from anywhere. A plain directory in the way gets named as exactly that. Tests cover both branches with a real registered stale worktree and a bare directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Jonathan Edwards <justfinethanku@gmail.com> (cherry picked from commit e686947)
Independent of #35/#36 (different code region); trivially mergeable in any order — the only shared file is
ringer.pyin non-overlapping functions, plus a one-line adjacency inprint_summary.Problem
Failed tasks keep their worktrees (by design, for post-mortems). A follow-up run with the same run_name then collides with the stale taskdir and dies pre-spawn: verdict
ERROR,elapsed_s: 0.0, emptylog_tail, empty check output — and no message anywhere. In the field (2026-07-14,protocol-spec-fixes-20260714T131326Z) it took a full diagnosis cycle (git worktree list) to find what one sentence could have said. The prepare-error string existed internally, but only landed in a model-log row'snotes— not the worker log, not the task record, not the summary.Fix — three surfaces
git worktree remove --force <taskdir>(instead of a bare "already exists")._record_prepare_errorstores the reason as a newsetup_errorfield on the task record (included in the run-state payload, so the HUD and post-mortems see it) and appends it to the worker log — wherelog_tail,activity, and humans look first.setup failures (no worker was spawned)section listing each affected task with its reason.Test
End-to-end worktrees run against a temp git repo with a pre-created stale taskdir (
tests/test_setup_error_diagnostics.py): asserts the ERROR verdict now travels with the collision message in the summary, the worker log, and the run-state record'ssetup_error. Full suite: no new failures (the pre-existingtest_design_reference/test_scoreboard_pagefailures reproduce on clean main).Related follow-up not in this PR: an explicit
--reclaimflag to auto-remove stale worktrees from prior runs of the same manifest.🤖 Generated with Claude Code