Skip to content

A Base fix, when the base-fix flag is given - #236

Merged
JacobStephens2 merged 2 commits into
issue-221from
issue-222
Oct 1, 2026
Merged

JacobStephens2 merged 2 commits into
issue-221from
issue-222

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

With base-fix (or --base-fix), a Run whose only red checks are Inherited failures starts a Base fix instead of failing (ADR-0008).

 RepairLoop::run, CI red, every failed check an Inherited failure
   if the Base branch moved since the merge
     count a Base move, go round
-  fail: CI red on <check>, which also fails on <base> at <sha>; fix <base> first
+  BaseFix::fix
+    already had its one Base fix
+      fail: ..., even after Base fix <issue URL> merged; fix <base> first
+    not given base-fix (or is itself a Base fix, which sees no Inherited failures)
+      fail: ...; fix <base> first                      # exactly as in #103
+    gh label create (only labels the repository lacks), gh issue create
+      title  CI red on <base>: <check>[, <check>…]
+      body   the checks and their URLs on <base>, <base> and its short sha, the Run's PR
+      labels base-fix, ready-for-agent
+    child thirdshift --base-fix-into <base> <issue URL>   # Merge run, no Run notification
+    wait, relaying its lines as "#<n>: …"
+      merged  -> go round: merge <base> in, watch CI again
+      failed  -> fail: Base fix <issue URL> failed: <its cause>
 src/
+├── base_fix.rs    # BaseFix: a Run's one Base fix, its issue template, its report
+├── child_run.rs   # a Run in a child thirdshift (Ticket or Base fix): start, relay, how it ended
 ├── spec_run.rs    # Ticket Runs now start and wait through child_run; pass base-fix on
 ├── run.rs         # the Repair loop asks BaseFix instead of failing
 ├── ci.rs          # watch() compares with no Base branch commit in a Base fix
 ├── github.rs      # create_issue, adding missing labels first
 └── notification.rs  # "Base fix:     <issue URL> merged | not merged"
 tests/
+├── base_fix.rs
 └── fakes/gh.rs    # gh issue create --label, gh label list / create

On a Spec, base-fix goes to each Ticket's Run (its Base fix goes into the Spec branch) and to the Spec PR (into the Base branch).

Seam under test: the binary, with the fake gh and claude (tests/support::Scenario), as #221 agreed.

Evidence

  • Before: cargo test --test base_fix, first test: thirdshift <Issue URL> base-fix exits 2, not a GitHub issue URL: base-fix.
    After:
tests/base_fix.rs: 9 passed
  with_base_fix_an_inherited_failure_gets_an_issue_a_merged_fix_and_the_run_finishes_green
  the_base_fix_repairs_the_check_as_its_own_and_only_the_run_sends_a_notification
  a_merge_run_self_merges_once_its_base_fix_has_merged
  the_base_fix_merges_into_the_runs_base_branch_whatever_the_launch_directory_has_checked_out
  a_failing_base_fix_fails_the_run_naming_its_issue
  checks_still_inherited_failures_after_the_base_fix_merged_fail_the_run_with_no_second_base_fix
  without_base_fix_an_inherited_failure_fails_the_run_and_writes_no_issue
  a_label_the_repository_lacks_is_added_and_one_it_has_is_left_alone
  help_names_base_fix_and_not_the_base_fixs_hidden_argument
tests/spec_run.rs: 65 passed, including
  with_base_fix_a_tickets_inherited_failure_gets_a_base_fix_into_the_spec_branch
  with_base_fix_the_spec_prs_inherited_failure_gets_a_base_fix_into_the_base_branch

Full cargo test, cargo clippy --all-targets -- -D warnings and cargo fmt --check pass locally. The #103 tests in tests/ci.rs pass unchanged.

Merge Danger

Door: two-way

Nothing changes without base-fix: no gh label or gh issue call is made, and the cause text is #103's.

Blast Radius: opt-in

With base-fix, thirdshift writes to the repository beyond the Run's own pull request: it may add the base-fix and ready-for-agent labels, opens an issue, and merges a pull request into the Base branch with no human review. Until #224, Tickets of a Spec run that meet the same Inherited failure at once each start a Base fix of their own.

Unaddressed findings

Standards

  • &mut BaseFix threaded through run → implement / spec_run::run → open_and_review → review_and_deliver → deliver, with three new #[allow(clippy::too_many_arguments)] (issue, worktree, base, goal, logs are a Data Clump). Bundling them is a refactor of run.rs and spec_run.rs beyond this Ticket; spec_run.rs already allowed the lint twice.
  • run::run still takes given_base and BaseFix apart, so a Base fix with no given Base branch is representable there. Partly addressed: main now derives both from one child_run::Kind, and giving both hidden arguments is rejected.
  • BaseFix::fix mostly fails for a Run not given base-fix, and a BaseFix exists for Runs that never start one. Kept: it puts every Inherited failure cause in one place, and the Repair loop makes one call.
  • BaseFix::report words merged / not merged outside notification.rs. Kept: the notification only adds its label, as it does for a cause.
  • tests/spec_run.rs re-inlines the Base fix agent's script from tests/base_fix.rs. Kept: the two differ in branch and issue numbers, and the test files share only tests/support.

Spec

  • thirdshift adds a label the repository lacks (gh label list, gh label create), which A Base fix, when the base-fix flag is given #222 does not ask for. Kept: gh issue create --label refuses a label the repository doesn't have, so without it a Base fix would fail in any repository that has no base-fix label yet. A label the repository has is left alone.

Closes #222

🤖 Generated with Claude Code

JacobStephens2 and others added 2 commits October 1, 2026 01:55
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ks, name the child Run's kind

Co-Authored-By: Claude Opus 5.5 <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