Skip to content

fix(teardown): uniformly apply worktree safety to scout and secondmate kinds - #1138

Closed
ICGNU3 wants to merge 1 commit into
kunchenguid:mainfrom
ICGNU3:lane/teardown-uniform-safety
Closed

ICGNU3 wants to merge 1 commit into
kunchenguid:mainfrom
ICGNU3:lane/teardown-uniform-safety

Conversation

@ICGNU3

@ICGNU3 ICGNU3 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

fm-teardown.sh refused the landed-work test for scout and secondmate kinds. This branch makes the safety contract uniform across all kinds: scout worktrees return scratch state, secondmate homes gate teardown by their own backlog/state, ship kinds keep the standard landed-work check.

Verified: bin/fm-teardown.sh -h unchanged; 40 ok / 0 not-ok on the test matrix, including 8 new unit tests covering scout/secondmate paths.

…e kinds

Removes the inner 'case secondmate|scout) return 0' early-exit from
validate_worktree_teardown_safety. The function is now kind-agnostic.

The previous exemption was redundant at the only intentional call site
(fm-teardown.sh:1132, which only assigns the function for non-scout,
non-secondmate kinds), but the unconditional call site at line 1087 ran
the function regardless of kind. After this change, scout and secondmate
worktrees are uniformly checked for dirty, unpushed, and unmerged state,
in line with AGENTS.md's never-tear-down-unlanded-work contract.

CAPTAIN NOTE
- The function is now trustworthy regardless of which call site invokes
  it. This is a data-loss-sensitive change because the unconditional
  call site (1087) used to skip scout/secondmate worktree safety entirely.
  Eight new unit tests pin the new behavior at the function level, with
  stubbed external dependencies (worktree_safety_blocked_by_lock,
  default_branch, work_is_landed) so only the kind-uniqueness property is
  under test. Reverting the inner exemption causes four tests to fail
  with 'unexpectedly refused' messages.

VERIFICATION
- tests/fm-teardown.test.sh: 40 ok / 0 not-ok, including the 8 new
  tests covering scout and secondmate kinds under dirty / unpushed /
  clean-pushed / --force states.
- The pre-existing parse error in bin/fm-brief.sh is a separate upstream
  issue not touched by this lane.

Refs: firstmate-cleanup 2026-07-26 lane B

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9a84306ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread bin/fm-teardown.sh
@@ -668,9 +668,6 @@ validate_worktree_teardown_safety() {
local dirty_raw dirty unpushed_raw unpushed DEFAULT unmerged_raw unmerged branch
[ -d "$WT" ] || return 0
[ "$FORCE" != "--force" ] || return 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the scout scratch-worktree exemption

Captain, when a completed scout leaves uncommitted debug edits or unpushed diagnostic commits, this removal makes validate_worktree_teardown_safety refuse cleanup even after the required report and unresolved-decision verification have succeeded. Scout copies are explicitly disposable at that point, so requiring them to satisfy ship-style landing rules forces an unnecessary captain-approved --force; retain the exemption for KIND=scout while continuing to enforce the report and decision checks.

AGENTS.md reference: AGENTS.md:L29-L32

Useful? React with 👍 / 👎.

@ICGNU3

ICGNU3 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Closing this in favor of #1160, which fixes the same data-loss bug but keeps the secondmate half of the exemption.

This change breaks every secondmate teardown. Verified end-to-end on this branch:

fm-teardown.test.sh          40 ok, 0 fail   <- this PR's own suite, green
fm-secondmate-safety.test.sh 40 ok, 1 fail
  not ok - teardown failed for empty secondmate home

Why the new tests pass anyway. They call the safety function directly against a make_case fixture, which is a real git worktree. A secondmate home is not: it is a plain directory carrying a .fm-secondmate-home marker. Every check in validate_worktree_teardown_safety shells out to git -C "$WT", which fails on a non-repo and correctly fail-safes to REFUSED. The unit fixture never reaches that condition, so the uniform-behavior assertions hold while the real path is broken.

Only tests/fm-secondmate-safety.test.sh exercises it, through fm-teardown.sh end to end.

Worth noting: that suite cannot run at all on macOS right now, because bin/fm-brief.sh has not parsed under bash 3.2 since #945. That likely masked this. #1163 fixes the parse; with it applied, the failure above reproduces reliably.

The asymmetry is real, not an oversight. scout should lose the exemption: a scout's worktree is a git worktree, so every check applies, and a scout lane authored an ADR and a guard script in our fleet, so "scouts are read-only" is false in practice. secondmate should keep it: there is no uncommitted git state there for these checks to protect, and removing it makes teardown impossible rather than safe.

#1160 also drops the same exemption from post_lock_cleanup_check, which this PR leaves in place. That recheck is what catches work written between the first safety check and the treehouse return that resets the worktree.

@ICGNU3 ICGNU3 closed this Jul 28, 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.

1 participant