Skip to content

Name the failure when task setup dies before the worker spawns#37

Merged
justfinethanku merged 3 commits into
NateBJones-Projects:mainfrom
mlava:fix/worktree-collision-diagnostics
Jul 16, 2026
Merged

Name the failure when task setup dies before the worker spawns#37
justfinethanku merged 3 commits into
NateBJones-Projects:mainfrom
mlava:fix/worktree-collision-diagnostics

Conversation

@mlava

@mlava mlava commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Independent of #35/#36 (different code region); trivially mergeable in any order — the only shared file is ringer.py in non-overlapping functions, plus a one-line adjacency in print_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, empty log_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's notes — not the worker log, not the task record, not the summary.

Fix — three surfaces

  1. The collision message names the exact unblocking command: git worktree remove --force <taskdir> (instead of a bare "already exists").
  2. _record_prepare_error stores the reason as a new setup_error field 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 — where log_tail, activity, and humans look first.
  3. 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-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's setup_error. Full suite: no new failures (the pre-existing test_design_reference/test_scoreboard_page failures reproduce on clean main).

Related follow-up not in this PR: an explicit --reclaim flag to auto-remove stale worktrees from prior runs of the same manifest.

🤖 Generated with Claude Code

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>
justfinethanku and others added 2 commits July 16, 2026 11:55
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>
@justfinethanku

Copy link
Copy Markdown
Contributor

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 (.git file present), repo-qualified (git -C <repo> ...) and shell-quoted, so it's paste-safe from any directory. A plain directory in the way — where git worktree remove would itself fail — now gets named as exactly that with no command we haven't verified. Your test was restructured to cover both branches, with the worktree case using a real registered stale worktree.

Full suite green at 215 tests. Also: the joint-design invitation on #33/#36 is genuine — this PR's _record_prepare_error surface is adjacent to that work, so whoever lands the unified breaker will rebase over this small diff easily. Thanks for the steady quality.

@justfinethanku
justfinethanku merged commit e686947 into NateBJones-Projects:main Jul 16, 2026
justfinethanku added a commit that referenced this pull request Jul 16, 2026
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>
adamreading pushed a commit to adamreading/AJO-ringer that referenced this pull request Jul 19, 2026
…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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants