feat: add campaign task dispatch#266
Open
mielyemitchell wants to merge 9 commits into
Open
Conversation
…document campaign filing
…ME/architecture/config/scripts
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Add campaign task support to firstmate: a third dispatch shape alongside ship and scout for one long-lived crewmate driving a committed roadmap/spec. Include --campaign brief scaffolding, kind=campaign spawn metadata, ship-like teardown protection, campaign-aware validation state, docs, and tests without changing existing ship/scout behavior. Campaign crewmates must never merge: PR-based campaigns stop at PR ready/checks green so firstmate can merge through bin/fm-pr-merge.sh, including yolo repos; local-only campaigns are supported and use the fixed fm/ task branch, stopping at ready in branch for firstmate's local merge path. Existing no-mistakes review/test fixes through 3c92fe1 are intentional and should be validated; the prior run reached document before a captain-approved daemon restart cancelled it, then a retry hit a Claude session limit.
What Changed
campaignas a third dispatch shape alongsideshipandscout:bin/fm-brief.sh --campaignscaffolds a long-lived roadmap-driven crewmate brief, andbin/fm-spawn.sh --campaignrecordskind=campaignmetadata, including model/effort/harness dispatch-profile support consistent with ship/scout launches.bin/fm-teardown.sh: everyfm/<id>-prefixed local branch (the fixed branch for local-only projects, per-batch branches for PR-based projects) must be verified as landed and is pruned at teardown, with each campaign batch branch checked against its own PR rather than the task's last-recorded PR.bin/fm-pr-merge.sh(including yolo repos), and local-only campaigns stop at "ready in branch" on the fixedfm/<id>branch for firstmate's local merge path;bin/fm-crew-state.shandbin/fm-send.shgain campaign-aware state handling.AGENTS.md,README.md,CONTRIBUTING.md, anddocs/(architecture, configuration, scripts, herdr/orca/zellij backends, turnend-guard) to document the campaign lifecycle end to end, alongsideharness-adaptersandsecondmate-provisioningskill updates.FM_HOMEin the turnend-guard test, isolated gotmp env) uncovered while validating this branch.Risk Assessment
✅ Low: The campaign feature is additive (new --campaign kind alongside ship/scout), the multi-branch teardown protection and per-branch PR verification logic is subtle but thoroughly covered by new targeted tests (unpushed refusal, unlanded batch branch refusal even with HEAD parked elsewhere, all-batches-landed pruning, per-branch PR lookup, local-only detached-HEAD refusal), and existing ship/scout/secondmate code paths are left behavior-unchanged (kind defaults and gating conditions were extended, not altered). No security, data-loss, or breaking-change risks found.
Testing
The configured baseline test command passed, and I independently reran the full 44-file suite (0 failures) plus the four campaign-specific suites in isolation; I additionally exercised bin/fm-brief.sh --campaign directly to produce a real generated brief showing the roadmap contract, fm/<id>/<batch> branch naming, "never merge" rule, and mode-specific stop conditions (PR ready/checks green vs. ready in branch) — end-to-end evidence that campaign scaffolding, spawn metadata, and teardown protection work as intended without regressing ship/scout behavior. Working tree is clean; no stray artifacts left behind.
Evidence: Campaign-specific test suite transcript (fm-brief, fm-spawn-dispatch-profile, fm-teardown, fm-crew-state)
Evidence: Real generated campaign crewmate brief (bin/fm-brief.sh --campaign output)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:829- The worktree-discovery poll now latches a non-isolated cwd as final after only 2 consecutive identical polls (~2s), rather than the full 60s budget, to detect a genuinely stuck/tangled spawn quickly. If treehouse's intermediate staging cwd (e.g. ~/.treehouse) happens to stay put for 2+ seconds before moving to the final leaf worktree on a slower machine, this could produce a premature 'did not yield an isolated worktree' refusal instead of waiting it out. This is a judgment call the author already made deliberately (per the inline comment) to fix a real race; flagging only as a possible flakiness source under system load, not a functional bug.✅ **Test** - passed
✅ No issues found.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"command -v tmux && tmux -V (baseline env check)bash tests/fm-brief.test.shbash tests/fm-spawn-dispatch-profile.test.shbash tests/fm-teardown.test.shbash tests/fm-crew-state.test.shFull suite: for t in tests/*.test.sh; do bash "$t"; done (44 files, all pass, FULL_SUITE_RC=0)Manual: bin/fm-brief.sh demo-campaign-x1 demo-repo --campaign in an isolated temp FM_HOME to render the actual generated campaign brief contract✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.