Skip to content

A waiting Spec run puts ready-for-agent back on its Spec, not agent-failed - #1936

Merged
JacobStephens2 merged 3 commits into
issue-1901from
issue-1903
Nov 10, 2026
Merged

JacobStephens2 merged 3 commits into
issue-1901from
issue-1903

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

A Spec run that is only waiting no longer ends agent-failed. Its Claim hands the Spec back.

 claim_ending(outcome)
   Err(held)                        -> Held
+  Err(Tickets not done, only waiting, not interrupted) -> Waiting
   Err(_)                           -> Failed      # agent-failed

+Claimed::hand_back                 # Ending::Waiting
+  if the Claim took no ready-for-agent off
+    take in-progress off, put nothing back
+  elif an untrusted account edited the Spec since its last Trusted ready-for-agent labelling
+    in-progress, ready-for-agent off; needs-triage on
+  else
+    in-progress off; ready-for-agent on   # a hand-back Pickup's Ready-issue rule already counts

A Spec run is only waiting (TicketBoard::only_waiting) when two things hold:

  • No Ticket failed, was interrupted, or is still running.
  • Every open Ticket is an Unready Ticket (including one with sub-issues), is outside the Spec's repository, or is blocked only by issues outside the Spec and by Tickets that wait themselves.

A Ticket in a blocking cycle never waits. The run still exits 1 and still reports Tickets not done: …, because #585 owns the outcome name, exit code and notification wording.

Other changes:

  • trust::untrusted_edit_since_ready reuses the Trusted-account check from the last Trusted ready-for-agent labelling.
  • Security review fix (5d9c221): handing a waiting Spec back re-dated its Trusted ready-for-agent labelling, which the Ticket trust check counts edits from, so an untrusted edit to a waiting Ticket made earlier in the run was excused and the next Spec run started that Ticket. A waiting Spec run now runs the Ticket trust check on each open Ticket in the Spec's repository first, and ends agent-failed if one fails it or cannot be checked. Regression test a_waiting_spec_runs_handback_does_not_let_an_earlier_untrusted_ticket_edit_start failed on c5499fd (Ticket Numbered Issue branches after a merged or closed PR #21 started), passed at the merge base, and passes after the fix; GLOSSARY.md and docs/guide.md say so.
  • Docs updated: docs/guide.md (regenerated into site/docs/index.html), site/index.html, site/how-it-works/ and site/architecture/.

Evidence

Execution evidence

  • Before: CARGO_INCREMENTAL=0 cargo test -j2 --test spec_run a_spec_run_waiting_only_on_unready_tickets_hands_its_spec_back, run against origin/issue-1901's src/ with this PR's test:
    thread 'a_spec_run_waiting_only_on_unready_tickets_hands_its_spec_back' panicked at tests/spec_run.rs:2330:5:
    assertion `left == right` failed
      left: ["enhancement", "agent-failed"]
     right: ["enhancement", "ready-for-agent"]
    test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 98 filtered out
    
    After: the same test on this head: test a_spec_run_waiting_only_on_unready_tickets_hands_its_spec_back ... ok.
  • Before: the Spec reviewer's test a_waiting_spec_run_on_a_spec_never_labelled_ready_for_agent_does_not_label_it, on a9a70d1:
    panicked at tests/spec_run.rs:2389:5:
    labels: ["ready-for-agent"]
    test result: FAILED. 0 passed; 1 failed
    
    After: on c5499fd: ... ok.
  • Full integration files on this head:
    • cargo test --test spec_run: 98 passed, 1 ignored.
    • cargo test --test pickup_run: 147 passed, 1 ignored.
    • This covers a_waiting_spec_is_passed_over_until_its_ticket_can_start_then_continued, which replays the timeline thirdshift's own label edits recorded.
  • cargo clippy --all-targets is clean.
  • npm run docs:check --prefix site exits 0.
  • Not run locally: the unit-test binary (cargo test --bin thirdshift). The machine had about 2 GB free and no swap, and rustc was killed (SIGKILL) linking it, three times. These unit tests rely on CI:
    • claim::tests (hand-back, needs-triage, never-ready, trust-read failure, Stop)
    • spec_run::tests (waiting/failed classification through Scripted)
    • trust::tests

Visual evidence

There are three prose-only changes to hand-written site pages. Each was captured at 1440×900 with Playwright Chromium, Before from origin/issue-1901's site/ and After from this head:

  • /how-it-works/ Spec runs paragraph
  • / Pickup run paragraph
  • /architecture/ Claim bullet

Publishing them to a secret Gist was refused by this session's permission settings, so they are not embedded. They remain on the host:

  • /tmp/before-desktop-how.STGO2B.png / /tmp/after-desktop-how.0KLxMX.png
  • /tmp/before-desktop-index.DYb8OE.png / /tmp/after-desktop-index.43LHms.png
  • /tmp/before-desktop-arch.Tl5i6p.png / /tmp/after-desktop-arch.GnwA9l.png

Layout is unchanged; each page only gains a sentence.

Review coverage

The Standards and Spec reviewers reviewed a9a70d1, and between them read every changed file. One generated file was excluded:

  • site/docs/index.html, generated from docs/guide.md by site/generate-docs.mjs.
  • npm run docs:check --prefix site exited 0, and both reviewers confirmed the exclusion.

The review-fix commit c5499fd was not reviewed again. It changed:

  • src/claim.rs, src/spec_run.rs, src/spec_run/ticket_board.rs, src/failed_run.rs
  • tests/spec_run.rs, tests/pickup_run.rs
  • docs/guide.md, site/index.html, site/docs/index.html

Unaddressed findings

Standards

  • 7. Possible Primitive Obsession: TicketsNotDone { not_done: Vec<String> }. Declined, as the reviewer suggested. It carries the strings TicketBoard::not_done (src/spec_run/ticket_board.rs) already returns for every Tickets-not-done cause. A type for them is a wider change than this issue.

Spec

  • 3. A Ticket that landed but is still open makes the run fail. Declined; the reviewer marked it "not a defect". The issue says a run is only waiting when "every undone Ticket is an Unready Ticket, blocked by Unready Tickets or by work elsewhere, or outside the Spec's repository". A landed-but-open Ticket is none of these. TicketBoard::waits returns false for any Ticket that ended in this run other than a not-reproduced bug.

Security review outcome

No unaddressed introduced findings.

Merge Danger

Door: two-way

Reverting restores the old behaviour, where a waiting Spec run is labelled agent-failed. Specs already handed back keep ready-for-agent. That is the normal hand-back state, and they need no cleanup.

Blast Radius: labels

The change affects Spec Claim endings, and through them Pickup:

  • A waiting Spec no longer counts toward the Failure limit.
  • Pickup now continues a waiting Spec once one of its Tickets becomes startable.

Ticket runs and Custom processes without land-tickets are unaffected.

Closes #1903

🤖 Generated with Claude Code

Built with claude 2.1.314 · claude-opus-5-5 · medium

JacobStephens2 and others added 3 commits November 10, 2026 00:57
…ailed

A Spec run that failed no Ticket and whose undone Tickets all wait on a
person or on other work takes in-progress off its Spec and puts
ready-for-agent back, or needs-triage after an untrusted edit of the Spec
since its last Trusted ready-for-agent labelling. A blocking cycle, or any
failed or interrupted Ticket, still ends agent-failed.

Closes #1903
A waiting Spec run on a Spec with no ready-for-agent only takes in-progress
off, so thirdshift never makes a Spec Ready that the Day shift did not.
Keep one Tickets not done error with an only_waiting flag, check cycles
where the walk through blockers starts, and correct the guide and site
index wording. The Pickup test now reads the timeline thirdshift's edits
recorded.
Handing a waiting Spec back labels it ready-for-agent again, by thirdshift's
own Trusted account. The Trusted-account check for Tickets counts edits only
since the later of the Ticket's and its Spec's last Trusted labelling, so
that hand-back excused an untrusted edit of a waiting Ticket made before it,
and the next Spec run started that Ticket. A waiting Spec run now checks
each open Ticket in the Spec's repository first, and fails as before when
one fails the check or cannot be checked.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

1 participant