Skip to content

One Launch directory module opens the Launch directory for every command - #361

Merged
JacobStephens2 merged 3 commits into
mainfrom
issue-359
Oct 4, 2026
Merged

JacobStephens2 merged 3 commits into
mainfrom
issue-359

Conversation

@JacobStephens2

Copy link
Copy Markdown
Owner

Summary

Every command now opens its Launch directory through src/launch.rs. The pre-flight checks module is gone.

 src/
-├── preflight.rs   # Origin match, open issue, identity, Base branch on origin
 ├── launch.rs      # LaunchDirectory: opening for a Run or a pass, Base branch, launch.pull, lock
 ├── branch.rs      # Issue branch selection: only the open PR's base names the Base branch
 └── run.rs         # no longer reads the checked-out branch or exports the pull
 run (a Run)
-  Git::new(current_dir)
-  preflight::check            # Origin match, open issue, identity
+  LaunchDirectory::open_for_run   # same checks, same order; reads checked-out branch
   ...
-  symbolic-ref HEAD
   branch::select
-  selection.base_branch(given, checked_out)    # incl. detached-HEAD fallback
-  preflight::check_base_branch
-  run::pull_base_branch
+  named = selection.pr_base(given, checked_out).or(given)
+  directory.base_branch(named)   # named, else checked out; detached fails; checks on origin
+  directory.pull(base)

 launch::start (an Architect run or a Pickup run)
   open → repo of origin → identity → base_branch(named) → repository lock
 architect::run
-  run::pull_base_branch(...)
+  directory.pull(base)          # still only after the skip checks

There is one detached-HEAD rule. It keeps two wordings, and the module picks one by which opening was used. Only the pass's wording adds , or name it with base <branch>.

Evidence

  • Before: no unit tests for the Base branch rules. They were only covered end to end.
    After: cargo test --bin thirdshift launch:: passes 11 new tests. They run against a temporary repository whose origin is a bare repository beside it, named https://github.com/acme/widgets.git through url.<bare>.insteadOf:
    detached HEAD, no named branch → Run message / pass message (with base hint)
    detached HEAD + named branch → named branch
    named branch wins over checked-out
    Base branch missing on origin → "base branch unpushed does not exist on origin; push it first"
    local main ahead → "local main is 1 commit(s) ahead of origin/main; push them first"
    pull fast-forwards the checked-out Base branch only
    pull that can't fast-forward → checkout and uncommitted file untouched
    
  • The full cargo test passes, and no file under tests/ changed (preflight, launch_pull, continuation, numbered_branches, architect_run, pickup_run, command_logs and the rest). cargo clippy --all-targets is clean.

Merge Danger

Door: two-way

This is a behaviour-preserving refactor with no data or config changes. A revert undoes it.

Blast Radius: startup

If a check was reordered or a message changed, every Run, Architect run and Pickup run would see it before any work starts. The unchanged end-to-end tests pin those messages and their order.

Unaddressed findings

Standards

  • git(), origin() and checked_out() expose every field. Skipped. The spec makes these facts read-only to callers. Worktree creation and the Ready-issue search still need the git handle.
  • Opening enum stored only to pick a message is speculative. Skipped. The spec decides the wording is chosen inside the module by which opening was used, not by callers.
  • Return a BaseBranch type so pull can only follow base_branch. Skipped. It is a new type the spec didn't ask for. The ordering is documented, and both callers follow it.
  • Isolated-git test helper is a third copy (git.rs, worktree.rs). Skipped. Each module's test setup is private to that module, as the existing two already are. Sharing it would need a new test-support module, which is outside this change. The duplication inside launch.rs was fixed.
  • launch::repo() opens as a pass and reads the checked-out branch for nothing. Skipped. It costs one cheap local git call and keeps one opening path.
  • The Base branch fallback is now spread over branch.rs, run.rs and launch.rs. Skipped. The spec settles a Run's Base branch in exactly these two steps: Issue branch selection says what names it, then the Launch directory module settles it.
  • pr_base writes a progress line from a query. Skipped. This predates the change, and the spec keeps the progress line with Issue branch selection.
  • No unit test for a missing git identity or for the order of open_for_run's checks. Skipped. Both need either gh or the global git config, and both are covered end to end in tests/preflight.rs.

Spec

  • The pull-failure unit test doesn't assert that a warning is given. Skipped. progress::warn writes to the process's stderr, which a unit test doesn't capture. tests/launch_pull.rs asserts the warning end to end.
  • Unit tests use the private open(dir, …) rather than open_for_run. Skipped. The spec says the open-issue check needs gh and stays covered end to end.
  • Doc comments still say "preflight checks". Skipped. The phrase still names the checks themselves, which still exist. Only the module is gone.

Closes #359

🤖 Generated with Claude Code

JacobStephens2 and others added 3 commits October 4, 2026 13:39
…and (#359)

A Run now opens its Launch directory through the Launch directory module,
which makes the Origin match, the open-issue check and the identity check,
reads the checked-out branch, settles and checks the Base branch, and does
the launch.pull fast-forward. The pre-flight checks module is absorbed and
deleted; Issue branch selection only says what names the Base branch.

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

One Launch directory module opens the Launch directory for every command

1 participant