Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ README.md public overview and development notes
.agents/skills/ shared skills, committed
.claude/skills symlink to .agents/skills for claude compatibility
bin/ helper scripts, committed; read each script's header before first use
fm-completeness-check.sh formal completeness gate: proves a task's done/teardown/merge claim consistent with the directives (Z3-backed via fm-completeness.py + fm-completeness.rules.json). Wired into fm-teardown.sh and fm-merge-local.sh; FAILS OPEN when the solver tooling is absent, so it never wedges the lifecycle and the existing bash checks remain the hard guarantee. Off-switch: FM_COMPLETENESS_GATE=0; enforce-when-broken: FM_COMPLETENESS_STRICT=1
config/crew-harness crewmate harness override; LOCAL, gitignored; absent or "default" = same as firstmate
data/ personal fleet records; LOCAL, gitignored as a whole
backlog.md task queue, dependencies, history
Expand Down Expand Up @@ -113,6 +114,10 @@ Otherwise it prints one line per problem or capability fact; handle each:
- `FLEET_SYNC: <repo>: skipped: <reason>` - bootstrap continued; investigate only if the dirty, diverged, or offline clone blocks work.
- `TASKS_AXI: available` - an optional capability fact, not a problem; record it silently and use section 10 for backlog mutations.
It prints only after the `tasks-axi` compatibility probe passes for version 0.1.1 or newer; absence or incompatibility only falls back to hand-editing and never blocks work.
- `COMPLETENESS_GATE: available` - an optional capability fact, not a problem; record it silently and never surface it to the captain.
Bootstrap prints this only when `python3` can import `z3`.
When present, the formal completeness gate (`bin/fm-completeness-check.sh`, wired into teardown and the local merge) actively proves each done/teardown/merge claim against the directives; when `z3` is absent the gate fails open and firstmate relies on the existing bash safety checks exactly as before.
It is never a missing tool to install: `fm-bootstrap.sh install z3` opts in, and its absence never blocks work.

Bootstrap's fleet refresh is bounded by `FM_FLEET_SYNC_BOOTSTRAP_TIMEOUT` seconds, default 20; a timeout is reported as a `FLEET_SYNC` skip and does not block startup.

Expand Down Expand Up @@ -339,12 +344,12 @@ A ship task's path from `done` to landed on `main` is set by the project's `mode

- **no-mistakes** - the stages below as written: no-mistakes validation pipeline -> PR -> captain merge.
- **direct-PR** - no pipeline. The crewmate pushes and opens the PR itself (its brief says so) and reports `done: PR <url>`. Skip the Validate step and go straight to PR ready (run `fm-pr-check`, relay the PR). Teardown uses the normal pushed-branch check.
- **local-only** - no remote, no PR. The crewmate stops at `done: ready in branch fm/<id>`. Review the diff with `bin/fm-review-diff.sh <id>`, relay a one-paragraph summary to the captain, and on approval run `bin/fm-merge-local.sh <id>` to fast-forward local `main` (it refuses anything but a clean fast-forward - if it does, have the crewmate rebase). No `fm-pr-check`. Then teardown, whose safety check requires the branch already merged into local `main`, OR the work pushed to any remote (a fork counts - relevant for upstream-contribution PRs on a local-only-registered project).
- **local-only** - no remote, no PR. The crewmate stops at `done: ready in branch fm/<id>`. Review the diff with `bin/fm-review-diff.sh <id>`, relay a one-paragraph summary to the captain, and on approval run `FM_CAPTAIN_APPROVED=granted bin/fm-merge-local.sh <id>` to fast-forward local `main` (it refuses anything but a clean fast-forward - if it does, have the crewmate rebase). The `FM_CAPTAIN_APPROVED` assertion is the completeness gate's directive-#2 check: the merge is firstmate exercising the captain's merge authority, so the approval must be asserted explicitly (`granted`, or `not_required` under yolo); without it the gate blocks the merge when the solver tooling is present, and fails open (proceeds) when it is absent. No `fm-pr-check`. Then teardown, whose safety check requires the branch already merged into local `main`, OR the work pushed to any remote (a fork counts - relevant for upstream-contribution PRs on a local-only-registered project).

When reviewing any crewmate branch diff, use `bin/fm-review-diff.sh <id>` rather than `git diff <default>...branch` directly.
Pooled clones keep their local default refs frozen at clone time and can lag `origin`; the helper always compares against the authoritative base.

**yolo (orthogonal).** With `yolo=off` (default) every approval is the captain's: ask-user findings, PR merges, the local-only merge. With `yolo=on`, firstmate makes those calls itself without asking - resolve ask-user findings on your judgment, and run `gh-axi pr merge` / `bin/fm-merge-local.sh` once the work is green/approved - EXCEPT anything destructive, irreversible, or security-sensitive, which still escalates to the captain. Never merge a red PR even under yolo. After any merge you perform without asking the captain, post a one-line "merged <full PR URL or local main> after checks passed" FYI so the captain keeps a trail.
**yolo (orthogonal).** With `yolo=off` (default) every approval is the captain's: ask-user findings, PR merges, the local-only merge. With `yolo=on`, firstmate makes those calls itself without asking - resolve ask-user findings on your judgment, and run `gh-axi pr merge` / `FM_CAPTAIN_APPROVED=not_required bin/fm-merge-local.sh` once the work is green/approved - EXCEPT anything destructive, irreversible, or security-sensitive, which still escalates to the captain. Never merge a red PR even under yolo. After any merge you perform without asking the captain, post a one-line "merged <full PR URL or local main> after checks passed" FYI so the captain keeps a trail.

### Validate

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ See the [no-mistakes quick start](https://kunchenguid.github.io/no-mistakes/star
Everything personal to one captain's fleet (`data/`, `state/`, `config/`, `projects/`, `.no-mistakes/`) is gitignored; never commit it.
The root `.tasks.toml` is tracked `tasks-axi` config for `data/backlog.md`; compatible `tasks-axi` uses it for routine backlog mutations.
It does not make `data/` tracked.
- Helper scripts in `bin/` are plain bash.
- Helper scripts in `bin/` are plain bash, with one exception: `fm-completeness.py` is the optional Z3-backed completeness engine driven by `fm-completeness-check.sh`.
Each starts with a usage header comment; keep it accurate when you change behavior.
Test scripts and helpers in `tests/` are plain bash too.
`shellcheck bin/*.sh tests/*.sh` must pass, and CI enforces it.
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ firstmate works from any terminal - outside tmux, crewmates land in a detached `
- **Local clones stay fresh** - bootstrap and PR-based teardown refresh remote-backed project clones with clean default-branch fast-forwards when the clone is on the default branch and has no local work, and prune local branches whose remote is gone and that no worktree still needs.
- **Self-updates stay safe** - `/updatefirstmate` fast-forwards the running firstmate repo and registered secondmate homes from `origin`, then re-reads updated instructions and nudges updated secondmates without touching project clones.
The update is fast-forward only: dirty, diverged, offline, and off-default targets are reported and left untouched.
- **Lifecycle claims are provable** - an optional formal completeness gate (`bin/fm-completeness-check.sh`, Z3-backed) wires into teardown and the local merge to prove each done/teardown/merge claim consistent with the directives before the irreversible step.
Bootstrap reports it as available only when `python3` can import `z3`; when the solver is absent the gate fails open and the existing bash safety checks remain the hard guarantee.
- **Restart-proof** - all state lives in tmux, status files, local markdown under `data/`, `data/secondmates.md`, and persistent secondmate homes.
Kill the first mate session anytime; the next one reconciles and carries on.

Expand All @@ -161,7 +163,7 @@ The first mate drives these; you rarely need to, but they work by hand too.
| `fm-home-seed.sh` | Lease/provision a secondmate home transactionally, clone projects, initialize gates, and maintain `data/secondmates.md` |
| `fm-spawn.sh` | Spawn one task, several `id=repo` pairs, or a persistent secondmate with `--secondmate` |
| `fm-project-mode.sh` | Resolve a project's delivery mode and `+yolo` flag from `data/projects.md` |
| `fm-merge-local.sh` | Fast-forward a `local-only` project's local default branch after approval |
| `fm-merge-local.sh` | Fast-forward a `local-only` project's local default branch after the captain's approval is asserted via `FM_CAPTAIN_APPROVED` |
| `fm-review-diff.sh` | Review a crewmate branch against the authoritative base, with optional `--stat` output |
| `fm-watch-arm.sh` | Verified per-home watcher re-arm; reports `started`, `healthy`, or `FAILED`; `--restart` relaunches only this home's watcher |
| `fm-watch.sh` | Singleton-safe one-shot watcher; blocks until supervision work is due, queues it durably, then exits with one reason line |
Expand All @@ -173,6 +175,7 @@ The first mate drives these; you rarely need to, but they work by hand too.
| `fm-pr-check.sh` | Record a PR-ready task and arm the watcher's merge poll |
| `fm-promote.sh` | Promote a scout task in place so it becomes a protected ship task |
| `fm-teardown.sh` | Return the worktree or retire/release a secondmate home; protects ship work, requires scout reports, checks child work, and prints the backlog reminder |
| `fm-completeness-check.sh` | Formal completeness gate wired into teardown and the local merge: proves a done/teardown/merge claim consistent with the directives (Z3-backed via `fm-completeness.py` + `fm-completeness.rules.json`); fails open when the solver is absent |
| `fm-harness.sh` | Detect the running harness; resolve the effective crewmate harness |
| `fm-lock.sh` | Per-home firstmate session lock |

Expand Down Expand Up @@ -227,6 +230,11 @@ FM_WATCHER_STALE_GRACE=300 # defaults to FM_GUARD_GRACE; seconds a live watche
FM_SIGNAL_GRACE=30 # seconds to coalesce nearby status and turn-end signals into one wake
FM_FLEET_SYNC_BOOTSTRAP_TIMEOUT=20 # seconds allowed for bootstrap's best-effort clone refresh
FM_FLEET_PRUNE=1 # set to 0 to skip pruning local branches whose upstream is gone
# formal completeness gate (bin/fm-completeness-check.sh); optional, fails open without z3
FM_COMPLETENESS_GATE=1 # set to 0 to skip the gate entirely (always exits 0)
FM_COMPLETENESS_STRICT=0 # set to 1 to refuse instead of fail open when the solver tooling is absent/broken
FM_COMPLETENESS_RULES= # optional override for the rules file (default bin/fm-completeness.rules.json)
FM_CAPTAIN_APPROVED= # assert the captain's merge approval at the merge gate: granted|yes|1|true, or not_required under yolo
FM_BUSY_REGEX='esc (to )?interrupt|Working\.\.\.' # busy-pane signatures, shared by watcher and tmux helper
FM_COMPOSER_IDLE_RE= # optional empty-composer regex, applied after dim-ghost and border stripping
FM_SEND_RETRIES=3 # fm-send Enter-retry attempts after typing the line once
Expand Down Expand Up @@ -271,6 +279,7 @@ tests/fm-spawn-batch.test.sh # fm-spawn.sh batch (id=repo) argument
tests/fm-bootstrap.test.sh # bootstrap dependency and feature-probe tests
tests/fm-update.test.sh # fast-forward-only self-update, reread, nudge, dedup, and skip-safety tests
tests/fm-teardown.test.sh # fm-teardown.sh safety and reminder checks: local-only fork-remote allow, truly-unpushed refuse, merged-to-main allow, no-mistakes regression, tasks-axi reminder, --force override
tests/fm-completeness.test.sh # completeness gate: off-switch, fail-open, strict enforcement, argument parsing, and (when z3 imports) the SAT/UNSAT invariant matrix plus --id derivation
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ]
[ "$(readlink .claude/skills)" = "../.agents/skills" ]
FM_HEARTBEAT=2 FM_POLL=1 bin/fm-watch-arm.sh # watcher re-arm smoke test (prints arm status, then "heartbeat")
Expand Down
Binary file not shown.
11 changes: 10 additions & 1 deletion bin/fm-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
# Silent = all good.
# Lines: "MISSING: <tool> (install: <command>)", "NEEDS_GH_AUTH",
# "CREW_HARNESS_OVERRIDE: <name>", "FLEET_SYNC: <repo>: skipped: <reason>",
# "TASKS_AXI: available".
# "TASKS_AXI: available", "COMPLETENESS_GATE: available".
# z3 (z3-solver) is an OPTIONAL capability that powers the formal
# completeness gate (bin/fm-completeness-check.sh); reported only when
# python3 can import z3. It is never a MISSING line and never prompts an
# install - the gate fails open without it. Opt in with
# "fm-bootstrap.sh install z3".
# treehouse is also MISSING when its installed version lacks
# "treehouse get --lease" support.
# tasks-axi is an OPTIONAL backlog-management capability reported only
Expand Down Expand Up @@ -69,6 +74,7 @@ install_cmd() {
tmux|node|gh) echo "brew install $1 # or the platform's package manager" ;;
treehouse) echo "curl -fsSL https://kunchenguid.github.io/treehouse/install.sh | sh" ;;
no-mistakes) echo "curl -fsSL https://raw.githubusercontent.com/kunchenguid/no-mistakes/main/docs/install.sh | sh" ;;
z3) echo "python3 -m pip install z3-solver" ;;
gh-axi|chrome-devtools-axi|lavish-axi) echo "npm install -g $1 && $1 setup hooks" ;;
*) return 1 ;;
esac
Expand Down Expand Up @@ -103,5 +109,8 @@ crew=
[ -f "$CONFIG/crew-harness" ] && crew=$(tr -d '[:space:]' < "$CONFIG/crew-harness" || true)
[ -n "$crew" ] && [ "$crew" != "default" ] && echo "CREW_HARNESS_OVERRIDE: $crew"
fm_tasks_axi_compatible && echo "TASKS_AXI: available"
if command -v python3 >/dev/null 2>&1 && python3 -c 'import z3' >/dev/null 2>&1; then
echo "COMPLETENESS_GATE: available"
fi
fleet_sync
exit 0
Loading