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
6 changes: 6 additions & 0 deletions bin/fm-brief.sh
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ The report is the only thing that survives, so anything worth keeping must be in
5. If you hit the same obstacle twice, append \`blocked: {why}\` and stop; firstmate will help.
6. If a decision belongs to a human (product choices, destructive actions),
append \`needs-decision: {summary of options}\` and stop. Firstmate will reply with the decision.
7. Never stop, restart, or update the shared \`no-mistakes\` daemon - it is one instance serving
every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
daemon error, append \`blocked: {the daemon error}\` and stop; only firstmate manages the daemon.

# Definition of done
Write your findings to \`$DATA/$ID/report.md\`.
Expand Down Expand Up @@ -251,6 +254,9 @@ $RULE1
5. If you hit the same obstacle twice, append \`blocked: {why}\` and stop; firstmate will help.
6. If a decision belongs to a human (product choices, destructive actions, ask-user findings),
append \`needs-decision: {summary of options}\` and stop. Firstmate will reply with the decision.
7. Never stop, restart, or update the shared \`no-mistakes\` daemon - it is one instance serving
every lane/home, so restarting it kills other lanes' in-flight pipeline runs. On ANY no-mistakes
daemon error, append \`blocked: {the daemon error}\` and stop; only firstmate manages the daemon.

# Project memory
If \`AGENTS.md\` or \`CLAUDE.md\` already exists, or if this task produced durable project-intrinsic knowledge, run \`$FM_ROOT/bin/fm-ensure-agents-md.sh .\` in the worktree.
Expand Down
10 changes: 6 additions & 4 deletions tests/fm-gotmp.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,10 @@ test_teardown_removes_tasktmp_dir() {
fake=$(make_fake_root "$id" "$task_tmp")
# Sanity: dir + contents exist before teardown.
[ -d "$task_tmp/gotmp" ] || fail "precondition: gotmp missing before teardown"
# Run the REAL teardown against the fake root.
bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
# Run the REAL teardown against the fake root. FM_HOME is pinned to the fake
# root so an ambient FM_HOME in the caller's environment cannot redirect
# teardown at a real home instead of this fixture.
FM_HOME="$fake" bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
|| fail "teardown exited non-zero with a valid tasktmp"
[ ! -e "$task_tmp" ] \
|| fail "teardown did not remove the tasktmp dir ($task_tmp still exists)"
Expand Down Expand Up @@ -169,7 +171,7 @@ kind=ship
mode=no-mistakes
yolo=off
META
bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
FM_HOME="$fake" bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
|| fail "teardown exited non-zero when tasktmp= was absent"
pass "fm-teardown skips gracefully when tasktmp= is absent (backward compat)"
}
Expand All @@ -182,7 +184,7 @@ test_teardown_skips_gracefully_when_dir_missing() {
[ ! -e "$task_tmp" ] || fail "precondition: task_tmp should not exist yet"
local fake
fake=$(make_fake_root "$id" "$task_tmp")
bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
FM_HOME="$fake" bash "$fake/bin/fm-teardown.sh" "$id" >/dev/null 2>&1 \
|| fail "teardown exited non-zero when tasktmp dir was missing"
[ ! -e "$task_tmp" ] || fail "teardown created/left the tasktmp dir unexpectedly"
pass "fm-teardown skips gracefully when tasktmp= points to a nonexistent dir"
Expand Down
14 changes: 11 additions & 3 deletions tests/fm-turnend-guard.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,26 @@ install_guard_scripts() {

# A primary-shaped checkout: plain (non-worktree) git repo, AGENTS.md, bin/,
# state/ - everything the hook's scoping check requires to treat it as primary.
# Returns the CANONICALIZED path (cd && pwd): TMPDIR on macOS ends in a trailing
# slash, so a path built by string concatenation off it carries a double slash
# that string-compares unequal to the same path normalized elsewhere (e.g.
# record_watcher_lock's `cd "$dir" && pwd`), which would falsely fail the
# fm-home identity match the watcher-lock tests depend on.
make_primary_dir() {
local dir=$1
mkdir -p "$dir/state"
git init -q "$dir"
git -C "$dir" commit -q --allow-empty -m init
: > "$dir/AGENTS.md"
install_guard_scripts "$dir"
printf '%s\n' "$dir"
(cd "$dir" && pwd)
}

# Same shape as primary, plus the .fm-secondmate-home marker bin/fm-home-seed.sh
# writes at seed time (regardless of treehouse-lease or git-clone acquisition).
make_secondmate_dir() {
local dir=$1
make_primary_dir "$dir" >/dev/null
dir=$(make_primary_dir "$dir")
printf 'sm-test-1\n' > "$dir/.fm-secondmate-home"
printf '%s\n' "$dir"
}
Expand All @@ -127,7 +132,10 @@ make_crewmate_worktree_dir() {

run_hook() {
local dir=$1 stop_active=$2
printf '{"stop_hook_active":%s}' "$stop_active" | bash "$dir/bin/fm-turnend-guard.sh" 2>&1
# Pin FM_HOME to the scenario dir so an ambient FM_HOME in the caller's
# environment cannot redirect the hook at a real home's state instead of
# this fixture.
printf '{"stop_hook_active":%s}' "$stop_active" | FM_HOME="$dir" bash "$dir/bin/fm-turnend-guard.sh" 2>&1
}

nonexistent_pid() {
Expand Down