Skip to content

Test the Spec run's Ticket loop in-process behind a seam (#380) - #381

Merged
JacobStephens2 merged 2 commits into
mainfrom
issue-380
Oct 5, 2026
Merged

JacobStephens2 merged 2 commits into
mainfrom
issue-380

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

The Spec run's Ticket loop now reaches the outside world only through a private Outside seam. It has two adapters: ChildRunsAndGitHub in production, and a scripted fake in the module's tests. The fake drives a real Ticket board. Behaviour is unchanged.

 spec_run::run
   SpecPr::resume
-  land_tickets(spec, tickets, &worktree, parallel, &base_fix, &mut spec_pr)
-    worktree.push · child_run::start + channel · github::tickets
-    spec_pr.show/landed · interrupt::requested · progress::step
+  ChildRunsAndGitHub::new(spec, &worktree, &base_fix, &mut spec_pr)
+  land_tickets(&mut outside, tickets, parallel)
+    outside.push · start_ticket · next_ending · tickets
+    outside.show · landed · interrupted · step("starting #n")
   review_and_deliver           # unchanged

The #n landed, #n failed and #n interrupted lines stay in the adapter's waiting thread, so their timing on stderr is unchanged.

Evidence

  • Before: the loop's rules were checked only end to end, by spawning child Runs against the fake gh and claude.
    After: 18 unit tests at the seam, one per rule in the acceptance criteria, run in about 0.01s together. The 10 end-to-end tests listed in the issue are deleted. The kept ones pass: cargo test --test spec_run gives 65 passed.
  • The full cargo test passes. cargo clippy --all-targets is clean.

Merge Danger

Door: two-way

It refactors one module and its tests. A revert restores the old code and the deleted tests.

Blast Radius: Spec runs

A mistake in the production adapter would change how a Spec run starts, waits for or reports its Tickets. The kept end-to-end tests cover the real child Runs, concurrency, the Spec PR's writes and interrupts.

Unaddressed findings

Standards

  • The Ticket ending lines are written outside the seam. #n landed, #n failed and #n interrupted still go straight to progress::step in finish_ticket. Skipped: the issue's Decisions keep them in the adapter's waiting thread, so their timing on stderr relative to the relayed lines does not change.
  • The reached() and failed() test helpers duplicate others. Similar helpers exist in ticket_board.rs and run_ending.rs. Skipped: each test module keeps its own small builders, as the repo already does.
  • "Ticket loop" is not a CONTEXT.md term. Skipped: the issue uses "Ticket loop" throughout and states that no CONTEXT.md change is needed. The term names a private function's job, not a domain concept.

Spec

None. Both findings were addressed: the first-error test now makes a Spec PR opening fail after the first error, and the start-error test checks that the Tickets not done lines are not printed.

Closes #380

🤖 Generated with Claude Code

JacobStephens2 and others added 2 commits October 4, 2026 19:50
…ide effects (#380)

The Ticket loop now reaches the Spec branch push, the Tickets' child Runs
and their channel, the graph re-read, the Spec PR, the interrupt and its
progress lines only through a private Outside seam, with a production
adapter over child Runs, GitHub and the Spec PR and a scripted fake for
unit tests driving a real Ticket board. End-to-end tests that only checked
a loop rule or a board line through the loop are replaced by unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit 4dd6f1e into main Oct 5, 2026
13 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-380 branch October 5, 2026 00:00
@JacobStephens2 JacobStephens2 mentioned this pull request Oct 5, 2026
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.

Test the Spec run's Ticket loop in-process behind a seam for its child Runs, re-reads and Spec PR

1 participant