From e8c90e57c12917d68fa066a1626ee3a45129e5e1 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Sun, 26 Jul 2026 17:31:30 -0400 Subject: [PATCH 01/20] fix(teardown): accept landed stale branches after main rewrite --- bin/fm-teardown.sh | 51 +++++++++-- tests/fm-teardown.test.sh | 184 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 219 insertions(+), 16 deletions(-) diff --git a/bin/fm-teardown.sh b/bin/fm-teardown.sh index ea03eda10b..629d8f92cc 100755 --- a/bin/fm-teardown.sh +++ b/bin/fm-teardown.sh @@ -23,6 +23,8 @@ # teardown refuses rather than risk discarding unlanded work. # Origin-backed content checks hold the shared checkout lock and require bounded # remote HEAD probes before and after fetch to agree before comparing trees. +# If the default history was rewritten after task-branch creation, the comparison +# uses a base recorded by both the branch-creation and default-branch reflogs. # Every authorized Treehouse return is process-tree bounded by # FM_TREEHOUSE_RETURN_TIMEOUT while holding the same common checkout mutation # lock across its retry and stale-index-lock recovery sequence. @@ -797,20 +799,55 @@ pr_is_merged() { unpushed_patches_are_in_pr_head "$head" } +# Set TASK_BRANCH_CREATION_BASE only when the task branch's oldest surviving +# reflog entry is its creation record, remains an ancestor of HEAD, and also +# appears in the authoritative default ref's reflog. +task_branch_creation_base() { + local authoritative_ref=$1 branch_ref entry base message fork_point + TASK_BRANCH_CREATION_BASE= + branch_ref=$(git -C "$WT" symbolic-ref --quiet HEAD 2>/dev/null) || return 1 + entry=$(LC_ALL=C git -C "$WT" reflog show \ + --format='%H%x09%gs' "$branch_ref" 2>/dev/null | tail -1) + [ -n "$entry" ] || return 1 + base=${entry%%$'\t'*} + message=${entry#*$'\t'} + [ "$message" != "$entry" ] || return 1 + case "$message" in + "branch: Created from "*) ;; + *) return 1 ;; + esac + git -C "$WT" cat-file -e "$base^{commit}" 2>/dev/null || return 1 + git -C "$WT" merge-base --is-ancestor "$base" HEAD 2>/dev/null || return 1 + fork_point=$(git -C "$WT" merge-base \ + --fork-point "$authoritative_ref" HEAD 2>/dev/null) || return 1 + [ "$fork_point" = "$base" ] || return 1 + TASK_BRANCH_CREATION_BASE=$base +} + # Is the branch's content already present in the up-to-date default branch? # Origin-backed proof holds the common checkout lock across probe, fetch, # unchanged branch-and-tip re-probe, and tree comparison. +# The ordinary merge finds the net task change from shared history. +# When the default was rewritten past the task branch's creation point, an +# explicit branch-creation base isolates the task change from its stale baseline. content_matches_ref() { - local ref=$1 default_tree merged_tree + local ref=$1 default_tree merged_tree merge_output creation_base default_tree=$(git -C "$WT" rev-parse --quiet --verify "$ref^{tree}" 2>/dev/null) || return 1 [ -n "$default_tree" ] || return 1 - merged_tree=$(git -C "$WT" merge-tree --write-tree "$ref" HEAD 2>/dev/null) || return 1 - merged_tree=$(printf '%s\n' "$merged_tree" | head -1) - if [ "$merged_tree" != "$default_tree" ]; then - echo "teardown: task content is not present in authoritative $ref; retaining $WT" >&2 - return 1 + if merge_output=$(git -C "$WT" merge-tree --write-tree "$ref" HEAD 2>/dev/null); then + merged_tree=$(printf '%s\n' "$merge_output" | head -1) + [ "$merged_tree" != "$default_tree" ] || return 0 + fi + if task_branch_creation_base "$ref"; then + creation_base=$TASK_BRANCH_CREATION_BASE + if merge_output=$(git -C "$WT" merge-tree --write-tree \ + --merge-base "$creation_base" "$ref" HEAD 2>/dev/null); then + merged_tree=$(printf '%s\n' "$merge_output" | head -1) + [ "$merged_tree" != "$default_tree" ] || return 0 + fi fi - return 0 + echo "teardown: task content is not present in authoritative $ref; retaining $WT" >&2 + return 1 } content_in_origin_default() { diff --git a/tests/fm-teardown.test.sh b/tests/fm-teardown.test.sh index ea5751c55d..4711adabd3 100755 --- a/tests/fm-teardown.test.sh +++ b/tests/fm-teardown.test.sh @@ -7,7 +7,7 @@ # and GitHub reports a PR head that contains the current local work, or its content # is already in the up-to-date default branch. # -# Covers three fixes: +# Covers four fixes: # - local-only fork-remote: a fork IS a remote, so fork-pushed upstream- # contribution PRs are teardown-eligible (the pre-fix code false-refused them). # - squash-merge-then-delete-branch: the branch's own commits live nowhere on a @@ -15,6 +15,9 @@ # main. Reachability alone false-refused this common GitHub flow; the check now # recognizes a merged PR head containing the local work (or the content already # in main) as landed. +# - default-history rewrite: a stale task branch can lose its merge base with main +# even though its task change landed. The branch-creation reflog entry isolates +# task work from the stale baseline without treating unrelated content as landed. # - teardown-lock-race: a killed crewmate process can leave a transient worktree # git index.lock that blocks teardown. The return path retries on the lock # error signature (even if the lock self-clears mid-check), then only removes a @@ -38,17 +41,21 @@ # (o) fm-pr-check rerun after HEAD moved -> no stale pr_head # (p) fm-pr-check when local HEAD lags -> record remote PR head # (q) no-mistakes + NO pr= recorded, PR discovered by branch -> ALLOW (yolo/no-CI merge) +# (r) no-mistakes + rewritten main contains task content -> ALLOW (stale branch) +# (s) no-mistakes + rewritten main lacks task content -> REFUSE (safety) +# (t) no-mistakes + rewritten main retains task-deleted file -> REFUSE (deletion safety) +# (u) rewritten main lacks non-default task baseline -> REFUSE (base safety) # # Also covers backlog teardown-lock-race: a git index.lock left in the worktree by a # killed crewmate process (bin/fm-teardown.sh's teardown_treehouse_return). -# (r) provably-stale index.lock (old mtime, no live holder) -> lock removed, ALLOW -# (s) index.lock with a live holder, any age -> lock kept, REFUSE -# (t) lsof error while checking index.lock -> lock kept, REFUSE -# (u) dirty worktree after stale lock cleanup -> lock removed, REFUSE -# (v) non-linked repo index.lock -> lock removed, ALLOW -# (w) index.lock mtime read failure -> lock kept, REFUSE -# (x) transient lock cleared after first failed return -> retry ALLOW -# (y) persistent lock (never clears, not provably stale) -> REFUSE loudly +# (v) provably-stale index.lock (old mtime, no live holder) -> lock removed, ALLOW +# (w) index.lock with a live holder, any age -> lock kept, REFUSE +# (x) lsof error while checking index.lock -> lock kept, REFUSE +# (y) dirty worktree after stale lock cleanup -> lock removed, REFUSE +# (z) non-linked repo index.lock -> lock removed, ALLOW +# (aa) index.lock mtime read failure -> lock kept, REFUSE +# (ab) transient lock cleared after first failed return -> retry ALLOW +# (ac) persistent lock (never clears, not provably stale) -> REFUSE loudly set -u # shellcheck source=tests/lib.sh disable=SC1091 @@ -318,6 +325,40 @@ land_on_origin_main() { rm -rf "$tmp" } +# Replace origin/main with an unrelated root commit, simulating a default-branch +# history rewrite after the task branch was created. +# Args: case_dir [task-file task-content] +rewrite_origin_main() { + local case_dir=$1 task_file=${2:-} task_content=${3:-} tmp + tmp="$case_dir/_rewrite" + git clone -q "$case_dir/origin.git" "$tmp" + git -C "$tmp" checkout -q --orphan rewritten-main + printf '%s\n' "new default history" > "$tmp/main-only.txt" + git -C "$tmp" add -- main-only.txt + if [ -n "$task_file" ]; then + printf '%s\n' "$task_content" > "$tmp/$task_file" + git -C "$tmp" add -- "$task_file" + fi + git -C "$tmp" -c user.email=t@t -c user.name=t commit -q -m "rewrite main history" + git -C "$tmp" push -q --force origin HEAD:main + rm -rf "$tmp" +} + +# Recreate the task worktree from a main commit containing baseline.txt so a +# history-rewrite test can verify that an unlanded deletion remains protected. +recreate_task_branch_with_baseline_file() { + local case_dir=$1 + git -C "$case_dir/project" worktree remove --force "$case_dir/wt" + git -C "$case_dir/project" branch -D fm/task-x1 >/dev/null + printf '%s\n' baseline > "$case_dir/project/baseline.txt" + git -C "$case_dir/project" add -- baseline.txt + git -C "$case_dir/project" -c user.email=t@t -c user.name=t \ + commit -q -m "add baseline file" + git -C "$case_dir/project" push -q origin main + git -C "$case_dir/project" worktree add -q -b fm/task-x1 "$case_dir/wt" main + write_treehouse_lease "$case_dir/wt" firstmate-task-x1 +} + # Override GitHub lookups to report PR 7 as merged with the supplied head. add_gh_pr_merged_for_head() { local case_dir=$1 head=$2 @@ -1220,6 +1261,119 @@ test_content_fallback_refreshes_stale_origin_ref() { pass "content fallback refreshes origin default before comparing trees" } +test_content_fallback_uses_branch_origin_after_history_rewrite() { + local case_dir rc + case_dir=$(make_case content-history-rewrite) + write_meta "$case_dir" no-mistakes ship + wt_commit_file "$case_dir" feature.txt hello "add feature" + rewrite_origin_main "$case_dir" feature.txt hello + git -C "$case_dir/project" fetch -q origin \ + '+refs/heads/main:refs/remotes/origin/main' + ! git -C "$case_dir/wt" merge-base refs/remotes/origin/main HEAD >/dev/null 2>&1 \ + || fail "history-rewrite fixture unexpectedly retained a merge base" + + set +e + run_teardown "$case_dir" > "$case_dir/stdout" 2> "$case_dir/stderr" + rc=$? + set -e + + expect_code 0 "$rc" \ + "history-rewrite: teardown should recognize task content in rewritten main" + assert_no_grep REFUSED "$case_dir/stderr" \ + "history-rewrite: teardown falsely refused landed task content" + assert_absent "$case_dir/state/task-x1.meta" \ + "history-rewrite: successful teardown retained task metadata" + assert_absent "$case_dir/fakebin/.tmux-live" \ + "history-rewrite: successful teardown retained the task endpoint" + pass "content fallback handles a stale task branch after default history rewrite" +} + +test_content_fallback_refuses_unlanded_work_after_history_rewrite() { + local case_dir rc + case_dir=$(make_case content-history-rewrite-unlanded) + write_meta "$case_dir" no-mistakes ship + wt_commit_file "$case_dir" feature.txt local-only "add unlanded feature" + rewrite_origin_main "$case_dir" + git -C "$case_dir/project" fetch -q origin \ + '+refs/heads/main:refs/remotes/origin/main' + ! git -C "$case_dir/wt" merge-base refs/remotes/origin/main HEAD >/dev/null 2>&1 \ + || fail "history-rewrite safety fixture unexpectedly retained a merge base" + + set +e + run_teardown "$case_dir" > "$case_dir/stdout" 2> "$case_dir/stderr" + rc=$? + set -e + + expect_code 1 "$rc" \ + "history-rewrite safety: teardown must refuse content absent from rewritten main" + assert_present "$case_dir/wt" "history-rewrite safety discarded the task worktree" + assert_present "$case_dir/state/task-x1.meta" \ + "history-rewrite safety removed task metadata" + assert_grep "task content is not present in authoritative refs/remotes/origin/main" \ + "$case_dir/stderr" "history-rewrite safety did not explain the refusal" + pass "content fallback remains fail-closed after default history rewrite" +} + +test_content_fallback_refuses_unlanded_deletion_after_history_rewrite() { + local case_dir rc + case_dir=$(make_case content-history-rewrite-unlanded-deletion) + recreate_task_branch_with_baseline_file "$case_dir" + write_meta "$case_dir" no-mistakes ship + git -C "$case_dir/wt" rm -q -- baseline.txt + git -C "$case_dir/wt" -c user.email=t@t -c user.name=t \ + commit -q -m "delete baseline file" + rewrite_origin_main "$case_dir" baseline.txt baseline + git -C "$case_dir/project" fetch -q origin \ + '+refs/heads/main:refs/remotes/origin/main' + ! git -C "$case_dir/wt" merge-base refs/remotes/origin/main HEAD >/dev/null 2>&1 \ + || fail "history-rewrite deletion fixture unexpectedly retained a merge base" + + set +e + run_teardown "$case_dir" > "$case_dir/stdout" 2> "$case_dir/stderr" + rc=$? + set -e + + expect_code 1 "$rc" \ + "history-rewrite deletion safety: teardown must refuse an unlanded deletion" + assert_present "$case_dir/wt" \ + "history-rewrite deletion safety discarded the task worktree" + assert_present "$case_dir/state/task-x1.meta" \ + "history-rewrite deletion safety removed task metadata" + assert_grep "task content is not present in authoritative refs/remotes/origin/main" \ + "$case_dir/stderr" "history-rewrite deletion safety did not explain the refusal" + pass "content fallback protects unlanded deletions after default history rewrite" +} + +test_content_fallback_refuses_nondefault_branch_origin_after_history_rewrite() { + local case_dir rc + case_dir=$(make_case content-history-rewrite-nondefault-base) + wt_commit_file "$case_dir" baseline-only.txt unlanded "add unlanded branch baseline" + git -C "$case_dir/wt" branch -m feature-base + git -C "$case_dir/wt" checkout -q -b fm/task-x1 + git -C "$case_dir/project" branch -D feature-base >/dev/null + write_meta "$case_dir" no-mistakes ship + wt_commit_file "$case_dir" feature.txt hello "add landed task change" + rewrite_origin_main "$case_dir" feature.txt hello + git -C "$case_dir/project" fetch -q origin \ + '+refs/heads/main:refs/remotes/origin/main' + ! git -C "$case_dir/wt" merge-base refs/remotes/origin/main HEAD >/dev/null 2>&1 \ + || fail "nondefault-base fixture unexpectedly retained a merge base" + + set +e + run_teardown "$case_dir" > "$case_dir/stdout" 2> "$case_dir/stderr" + rc=$? + set -e + + expect_code 1 "$rc" \ + "nondefault-base safety: teardown must retain an unlanded branch baseline" + assert_present "$case_dir/wt" "nondefault-base safety discarded the task worktree" + assert_present "$case_dir/state/task-x1.meta" \ + "nondefault-base safety removed task metadata" + assert_grep "task content is not present in authoritative refs/remotes/origin/main" \ + "$case_dir/stderr" "nondefault-base safety did not explain the refusal" + pass "content fallback rejects a branch created from a non-default unlanded base" +} + test_content_fallback_uses_live_default() { local case_dir rc baseline case_dir=$(make_case content-live-default) @@ -4330,6 +4484,14 @@ if [ "${FM_TEST_FOCUSED:-}" = managed-force-release ]; then exit 0 fi +if [ "${FM_TEST_FOCUSED:-}" = stale-branch-history-rewrite ]; then + test_content_fallback_uses_branch_origin_after_history_rewrite + test_content_fallback_refuses_unlanded_work_after_history_rewrite + test_content_fallback_refuses_unlanded_deletion_after_history_rewrite + test_content_fallback_refuses_nondefault_branch_origin_after_history_rewrite + exit 0 +fi + if [ "${FM_TEST_FOCUSED:-}" = managed-endpoint-identity ]; then test_managed_force_teardown_retains_unlanded_lease_and_session test_managed_teardown_retains_lease_when_endpoint_state_is_unknown @@ -4557,6 +4719,10 @@ test_pr_check_serializes_with_account_session_updates test_pr_check_rejects_reused_task_generation test_content_in_default_fallback_allows test_content_fallback_refreshes_stale_origin_ref +test_content_fallback_uses_branch_origin_after_history_rewrite +test_content_fallback_refuses_unlanded_work_after_history_rewrite +test_content_fallback_refuses_unlanded_deletion_after_history_rewrite +test_content_fallback_refuses_nondefault_branch_origin_after_history_rewrite test_content_fallback_uses_live_default test_content_fallback_reprobes_live_default_after_fetch test_content_fallback_honors_shared_checkout_lock From 31537899412048a792b9ea01d1b01c9946528409 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Sun, 26 Jul 2026 20:27:35 -0400 Subject: [PATCH 02/20] no-mistakes(test): Repair teardown lifecycle test endpoint fixture --- tests/fm-teardown.test.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/fm-teardown.test.sh b/tests/fm-teardown.test.sh index 4711adabd3..6d033ad788 100755 --- a/tests/fm-teardown.test.sh +++ b/tests/fm-teardown.test.sh @@ -2095,9 +2095,21 @@ case "${1:-}" in kill-window) : > "$FM_FAKE_KILL_STARTED" while [ ! -f "$FM_FAKE_ALLOW_KILL" ]; do sleep 0.01; done + rm -f "$(dirname "$0")/.tmux-live" + exit 0 + ;; + display-message) + [ -f "$(dirname "$0")/.tmux-live" ] || exit 1 + case " $* " in + *' #{session_name}'*) printf 'firstmate\tfm-task-x1\n' ;; + *' #{pane_id} '*) printf '%%1\n' ;; + esac + exit 0 + ;; + list-windows) + [ ! -f "$(dirname "$0")/.tmux-live" ] || printf 'fm-task-x1\n' exit 0 ;; - display-message) exit 1 ;; esac exit 0 SH @@ -2107,7 +2119,7 @@ SH FM_FAKE_KILL_STARTED="$kill_started" FM_FAKE_ALLOW_KILL="$allow_kill" \ run_teardown "$case_dir" --force > "$case_dir/stdout" 2> "$case_dir/stderr" & teardown_pid=$! - for _ in 1 2 3 4 5 6 7 8 9 10; do + for _ in {1..100}; do [ -f "$kill_started" ] && break sleep 0.05 done From 1f5bc3721c27762da701cc876b56f60c0cc53239 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Sun, 26 Jul 2026 22:37:52 -0400 Subject: [PATCH 03/20] no-mistakes(test): Stabilize watcher lock takeover lifecycle fixture --- tests/fm-watcher-lock.test.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/fm-watcher-lock.test.sh b/tests/fm-watcher-lock.test.sh index d46e3fa208..854a61f118 100755 --- a/tests/fm-watcher-lock.test.sh +++ b/tests/fm-watcher-lock.test.sh @@ -455,21 +455,22 @@ test_watcher_self_evicts_on_lock_takeover() { state="$dir/state" fakebin="$dir/fakebin" out="$dir/watch.out" - # Keep this lifecycle test out of unrelated first-cycle maintenance. The - # beacon below is then a deterministic observation that the watcher has - # entered its supervision loop and passed its ownership check. + # Keep this lifecycle fixture on the poll path it is asserting. + # First-cycle report retention and account-session maintenance are separately + # bounded, but under a congested full-suite run they can legitimately outlast + # this test's self-eviction deadline before the watcher reaches its next poll. touch "$state/.last-report-retention" "$state/.last-account-session-sync" PATH="$fakebin:$PATH" FM_STATE_OVERRIDE="$state" FM_POLL=0.2 FM_SIGNAL_GRACE=1 FM_CHECK_INTERVAL=999999 FM_HEARTBEAT=999999 "$WATCH" > "$out" & pid=$! i=0 - while [ "$i" -lt 50 ]; do + while [ "$i" -lt 100 ]; do [ "$(cat "$state/.watch.lock/pid" 2>/dev/null || true)" = "$pid" ] && [ -e "$state/.last-watcher-beat" ] && break sleep 0.1 i=$((i + 1)) done - [ "$(cat "$state/.watch.lock/pid" 2>/dev/null || true)" = "$pid" ] || fail "watcher did not record its own pid in the lock" - [ -e "$state/.last-watcher-beat" ] || fail "watcher did not reach the ownership-observation loop" + [ "$(cat "$state/.watch.lock/pid" 2>/dev/null || true)" = "$pid" ] && + [ -e "$state/.last-watcher-beat" ] || fail "watcher did not finish publishing its first live cycle" # Simulate a second watcher taking over the singleton lock. $$ (the test # runner) is a live pid that is not the watcher. printf '%s\n' "$$" > "$state/.watch.lock/pid" From cd78c6cadeedfc444a329a4b72bb36d376f0eed2 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 01:52:43 -0400 Subject: [PATCH 04/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 69351fd2f5..1ddf7d89c0 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -4201,6 +4201,12 @@ if [ "${FM_TEST_FOCUSED:-}" = workspace-prune ]; then exit 0 fi +if [ "${FM_TEST_FOCUSED:-}" = workspace-lifecycle ]; then + test_workspace_ensure_prunes_default_tab + test_repeated_cycles_reuse_one_workspace_no_orphans + exit 0 +fi + test_version_check_accepts_current_protocol test_version_check_refuses_old_protocol test_version_check_refuses_missing_herdr From 626b5ac09aed319755dc43ccb4258abcd359746e Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 02:14:21 -0400 Subject: [PATCH 05/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 1ddf7d89c0..5976b4dc0b 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -2627,7 +2627,11 @@ test_capture_calls_pane_read() { # fetch bound; the adapter then trims to the caller's requested 250 lines # locally, so all 3 fake lines survive. out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_capture default:w1:p2 250' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_server_adapter_owned() { return 0; } + fm_backend_herdr_capture default:w1:p2 250 + ' "$ROOT" ) [ "$out" = $'line one\nline two\nline three' ] || fail "capture did not pass through pane read output, got '$out'" assert_contains "$(cat "$log")" "HERDR_SESSION=default"$'\x1f''pane'$'\x1f''read'$'\x1f''w1:p2'$'\x1f''--source'$'\x1f''recent'$'\x1f''--lines'$'\x1f''250' \ "capture did not call pane read with the right pane id and line bound" @@ -2644,7 +2648,11 @@ test_capture_works_around_small_lines_bug() { printf 'a\nb\nc\nd\ne\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_capture default:w1:p2 2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_server_adapter_owned() { return 0; } + fm_backend_herdr_capture default:w1:p2 2 + ' "$ROOT" ) [ "$out" = $'d\ne' ] || fail "a small --lines request should still return the last N lines (trimmed locally), got '$out'" assert_contains "$(cat "$log")" $'\x1f''--lines'$'\x1f''200' \ "capture should request a generous fetch (>=200), never the caller's small N, from herdr's own --lines flag" @@ -2657,7 +2665,11 @@ test_capture_preserves_pane_read_failure() { printf '1\n' > "$resp/1.exit" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_capture default:w1:p2 2' "$ROOT" 2>&1 ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_server_adapter_owned() { return 0; } + fm_backend_herdr_capture default:w1:p2 2 + ' "$ROOT" 2>&1 ) status=$? [ "$status" -ne 0 ] || fail "capture should fail when pane read fails, got output '$out'" assert_contains "$(cat "$log")" "HERDR_SESSION=default"$'\x1f''status'$'\x1f''--json' \ @@ -4207,6 +4219,13 @@ if [ "${FM_TEST_FOCUSED:-}" = workspace-lifecycle ]; then exit 0 fi +if [ "${FM_TEST_FOCUSED:-}" = capture ]; then + test_capture_calls_pane_read + test_capture_works_around_small_lines_bug + test_capture_preserves_pane_read_failure + exit 0 +fi + test_version_check_accepts_current_protocol test_version_check_refuses_old_protocol test_version_check_refuses_missing_herdr From b3169cd9c5625d7133cc422285437acd5a45bb2d Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 02:50:18 -0400 Subject: [PATCH 06/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 5976b4dc0b..8aa02a0094 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -2684,7 +2684,11 @@ test_send_key_normalizes_and_targets_pane() { dir="$TMP_ROOT/sendkey"; mkdir -p "$dir/responses"; log="$dir/log"; resp="$dir/responses"; : > "$log" fb=$(make_herdr_fakebin "$dir") PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_key default:w1:p2 Escape' "$ROOT" + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_server_adapter_owned() { return 0; } + fm_backend_herdr_send_key default:w1:p2 Escape + ' "$ROOT" expect_code 0 $? "send_key should succeed" assert_contains "$(cat "$log")" $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''escape' "send_key did not normalize Escape to escape" pass "fm_backend_herdr_send_key: normalizes the key and targets the right pane" @@ -2696,7 +2700,11 @@ test_kill_is_best_effort() { printf '1\n' > "$resp/1.exit" fb=$(make_herdr_fakebin "$dir") PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_kill default:w1:p2' "$ROOT" + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_server_adapter_owned() { return 0; } + fm_backend_herdr_kill default:w1:p2 + ' "$ROOT" expect_code 0 $? "kill must be best-effort (never fail even when the pane close call itself fails)" assert_contains "$(cat "$log")" $'\x1f''pane'$'\x1f''close'$'\x1f''w1:p2' "kill did not call pane close on the right pane" pass "fm_backend_herdr_kill: calls pane close and stays best-effort on failure" From 4c7b92112984e4996dc178ec0df9c4276119b1dd Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 03:26:29 -0400 Subject: [PATCH 07/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 8aa02a0094..615057eb29 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -2906,7 +2906,13 @@ test_current_path_reads_cwd() { printf '{"result":{"pane":{"cwd":"/tmp/pane-creation-dir","foreground_cwd":"/tmp/fake-worktree"}}}\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_current_path default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { + fm_backend_herdr_parse_target "$1" + } + fm_backend_herdr_current_path default:w1:p2 + ' "$ROOT" ) [ "$out" = "/tmp/fake-worktree" ] || fail "current_path should read foreground_cwd (the live process), not the frozen creation-time cwd, got '$out'" assert_contains "$(cat "$log")" $'\x1f''pane'$'\x1f''get'$'\x1f''w1:p2' "current_path did not call pane get" pass "fm_backend_herdr_current_path: reads pane foreground_cwd (the live running process), not the frozen creation-time cwd" From 189fb3225d8ae833d8296f20c3b2079955b1f607 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 04:03:11 -0400 Subject: [PATCH 08/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 615057eb29..f913799273 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -2926,7 +2926,13 @@ test_busy_state_working_maps_to_busy() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_busy_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { + fm_backend_herdr_parse_target "$1" + } + fm_backend_herdr_busy_state default:w1:p2 + ' "$ROOT" ) [ "$out" = busy ] || fail "agent_status=working should map to busy, got '$out'" assert_contains "$(cat "$log")" $'\x1f''agent'$'\x1f''get'$'\x1f''w1:p2' "busy_state did not call agent get" pass "fm_backend_herdr_busy_state: working -> busy" @@ -2938,14 +2944,26 @@ test_busy_state_done_and_blocked_map_to_idle() { printf '{"result":{"agent":{"agent_status":"done"}}}\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_busy_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { + fm_backend_herdr_parse_target "$1" + } + fm_backend_herdr_busy_state default:w1:p2 + ' "$ROOT" ) [ "$out" = idle ] || fail "agent_status=done should map to idle, got '$out'" dir="$TMP_ROOT/busy-blocked"; mkdir -p "$dir/responses"; log="$dir/log"; resp="$dir/responses"; : > "$log" printf '{"result":{"agent":{"agent_status":"blocked"}}}\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_busy_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { + fm_backend_herdr_parse_target "$1" + } + fm_backend_herdr_busy_state default:w1:p2 + ' "$ROOT" ) [ "$out" = idle ] || fail "agent_status=blocked should map to idle (stuck waiting on the human, not grinding), got '$out'" pass "fm_backend_herdr_busy_state: done -> idle, blocked -> idle (surfaced like a stale pane, not suppressed as busy)" } @@ -2956,7 +2974,13 @@ test_busy_state_unknown_on_no_agent() { printf '1\n' > "$resp/1.exit" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_busy_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { + fm_backend_herdr_parse_target "$1" + } + fm_backend_herdr_busy_state default:w1:p2 + ' "$ROOT" ) [ "$out" = unknown ] || fail "a failed agent get should report unknown (the fallback-to-regex cue), got '$out'" pass "fm_backend_herdr_busy_state: unparseable/absent agent state reports unknown, the regex-fallback cue" } From 8c1c1a167178c2999f9d2473b4113a6c36ffb4ed Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 04:34:18 -0400 Subject: [PATCH 09/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 102 +++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 17 deletions(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index f913799273..848d4701b0 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -2993,7 +2993,11 @@ test_composer_state_bare_prompt_is_empty() { printf ' ╭────────────────────────╮\n │ ❯ │\n ╰──────── Composer ─────╯\n\n Shift+Tab:mode\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a bare prompt glyph should read as empty, got '$out'" pass "fm_backend_herdr_composer_state: a bare '❯' composer row reads empty" } @@ -3004,7 +3008,11 @@ test_composer_state_ghost_placeholder_is_empty() { printf ' ╭────────────────────────╮\n │ ❯ Type a message... │\n ╰──────── Composer ─────╯\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "the known ghost placeholder 'Type a message...' should read as empty, got '$out'" pass "fm_backend_herdr_composer_state: the ghost placeholder text reads empty, not pending" } @@ -3015,7 +3023,11 @@ test_composer_state_real_text_is_pending() { printf ' ╭────────────────────────╮\n │ ❯ hello captain │\n ╰──────── Composer ─────╯\n\n Enter:send\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "real unsubmitted text should read as pending, got '$out'" pass "fm_backend_herdr_composer_state: real composer text reads pending" } @@ -3034,7 +3046,11 @@ test_composer_state_popup_placeholder_fill_is_pending() { printf ' ╭──────────────────────────────────────╮\n │ ❯ /compact compaction instructions │\n ╰──────────────── Composer ─────────────╯\n\n Enter:send\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "a popup-close-with-placeholder-fill must still read as pending (not yet submitted), got '$out'" pass "fm_backend_herdr_composer_state: a slash-command popup's argument-hint placeholder still reads pending (the incident fix)" } @@ -3045,7 +3061,11 @@ test_composer_state_unknown_on_capture_failure() { printf '1\n' > "$resp/1.exit" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) status=$? [ "$status" -eq 0 ] || fail "composer_state should not itself fail the caller" [ "$out" = unknown ] || fail "an unreadable pane should read as unknown, got '$out'" @@ -3062,7 +3082,11 @@ test_composer_state_unknown_when_no_composer_row_found() { fb=$(make_herdr_fakebin "$dir") for glyph in '>' '$' '%' '#'; do out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = unknown ] || fail "a bare shell prompt '$glyph' should read as unknown, got '$out'" done pass "fm_backend_herdr_composer_state: reports unknown for bare shell prompts with no composer row" @@ -3087,7 +3111,11 @@ test_composer_state_claude_unbordered_prompt_is_empty() { printf ' 20\n 21\n\n\xe2\x9c\xbb Worked for 2s\n\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\xe2\x9d\xaf\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n Opus 4.8 (1M context) \xe2\x96\x8d 3%%\n \xe2\x86\x90 for agents\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a genuinely idle, unbordered real-claude '❯' prompt row (no border glyph anywhere in view) should read empty, got '$out' (regression: this used to read 'unknown' forever, which is exactly what broke escalate_flush's buffer-clear)" pass "fm_backend_herdr_composer_state: a real-claude unbordered '❯' prompt row (no border box in view) reads empty" } @@ -3098,7 +3126,11 @@ test_composer_state_claude_unbordered_prompt_is_pending() { printf ' 20\n 21\n\n\xe2\x9c\xbb Worked for 2s\n\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\xe2\x9d\xaf hello there this is a test message\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "real unsubmitted text in an unbordered real-claude prompt row should read pending, got '$out'" pass "fm_backend_herdr_composer_state: a real-claude unbordered '❯ ' prompt row reads pending" } @@ -3119,7 +3151,11 @@ test_composer_state_bare_prompt_below_stale_bordered_banner_wins() { printf '\xe2\x95\xad\xe2\x94\x80 Claude Code \xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xae\n\xe2\x94\x82 Welcome back Kun! \xe2\x94\x82\n\xe2\x94\x82 \xe2\x94\x82\n\xe2\x95\xb0\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xaf\n\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\xe2\x9d\xaf still typing captain\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "the live unbordered prompt row below a stale bordered banner must win (pending, real text present), got '$out'" pass "fm_backend_herdr_composer_state: a live unbordered prompt row below a stale bordered decorative box still wins (not misread as the box's own row)" } @@ -3142,7 +3178,11 @@ test_composer_state_claude_dim_prompt_suggestion_ghost_is_empty() { printf '\xe2\x9c\xbb Brewed for 2m 40s\n\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\xe2\x9d\xaf \x1b[0m\x1b[2mwhat did the wheelhouse healing verification find?\x1b[0m\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n Fable 5 80%%\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p3' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p3 ) [ "$out" = empty ] || fail "the overnight shape - claude's SGR-2 dim prompt-suggestion ghost after a bare '❯' - must read empty, got '$out' (regression: this false-pending wedged away-mode injection all night)" pass "fm_backend_herdr_composer_state: claude's dim prompt-suggestion ghost (the overnight wedge shape) reads empty" } @@ -3156,7 +3196,11 @@ test_composer_state_claude_dim_ghost_row_with_real_text_is_pending() { printf '\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n\xe2\x9d\xaf land pr 416 now\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n Fable 5 80%%\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p3' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p3 ) [ "$out" = pending ] || fail "real normal-intensity text after '❯' must still read pending, got '$out'" pass "fm_backend_herdr_composer_state: real typed text on the same claude prompt row still reads pending" } @@ -3173,7 +3217,11 @@ test_composer_state_grok_dark_truecolor_placeholder_is_empty() { printf ' \x1b[38;2;86;82;110m\xe2\x95\xad\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xae\x1b[39m\n \x1b[38;2;86;82;110m\xe2\x94\x82\x1b[38;2;224;222;244m \xe2\x9d\xaf \x1b[38;2;50;47;70mType a message...\x1b[38;2;86;82;110m \xe2\x94\x82\x1b[39m\n \x1b[38;2;86;82;110m\xe2\x95\xb0\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x95\xaf\x1b[39m\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a grok bordered composer whose only content is a dark-truecolor placeholder must read empty, got '$out'" pass "fm_backend_herdr_composer_state: grok's dark-truecolor placeholder (the TRUECOLOR gap) reads empty" } @@ -3185,7 +3233,11 @@ test_composer_state_grok_bright_truecolor_real_text_is_pending() { printf ' \x1b[38;2;86;82;110m\xe2\x94\x82\x1b[38;2;224;222;244m \xe2\x9d\xaf fix the login bug \x1b[38;2;86;82;110m\xe2\x94\x82\x1b[39m\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "real bright typed text in a grok bordered composer must read pending, got '$out'" pass "fm_backend_herdr_composer_state: grok's real bright typed input still reads pending" } @@ -3196,7 +3248,11 @@ test_composer_state_codex_bare_prompt_glyph_is_empty() { printf '\xe2\x80\xa2 You have 2 usage limit resets available.\n\n\xe2\x80\xba\n\n gpt-5.5 xhigh \xc2\xb7 Context 100%% left\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a bare '›' (codex) prompt glyph with no trailing text should read empty, got '$out'" pass "fm_backend_herdr_composer_state: a real-codex unbordered '›' prompt row reads empty" } @@ -3207,7 +3263,11 @@ test_composer_state_codex_faint_suggestion_is_empty() { printf '\xe2\x80\xa2 You have 2 usage limit resets available. Run /usage\nto use one.\n\n\x1b[0m\x1b[1m\xe2\x80\xba \x1b[0m\x1b[2mFind and fix a bug in @filename\x1b[0m\n\n gpt-5.5 xhigh \xc2\xb7 Context 100%% left\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a faint real-codex ghost suggestion should read empty, not pending, got '$out'" pass "fm_backend_herdr_composer_state: a faint real-codex ghost suggestion reads empty" } @@ -3218,7 +3278,11 @@ test_composer_state_codex_non_faint_same_text_is_pending() { printf '\xe2\x80\xa2 You have 2 usage limit resets available. Run /usage\nto use one.\n\n\x1b[0m\x1b[1m\xe2\x80\xba \x1b[0mFind and fix a bug in @filename\n\n gpt-5.5 xhigh \xc2\xb7 Context 100%% left\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = pending ] || fail "the same words without faint styling should still protect real typed input, got '$out'" pass "fm_backend_herdr_composer_state: non-faint codex prompt text still reads pending" } @@ -3467,7 +3531,11 @@ test_composer_state_codex_dynamic_idle_tip_reads_empty_when_faint() { printf '\xe2\x80\xa2 OK\n\n\n\x1b[0m\x1b[1m\xe2\x80\xba \x1b[0m\x1b[2mSummarize recent commits\x1b[0m\n\n gpt-5.5 xhigh \xc2\xb7 Context 97%% left \xc2\xb7 /private/tmp \xc2\xb7 2\xe2\x80\xa6\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_composer_state default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/backends/herdr.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_herdr_composer_state "$1" + ' "$ROOT" default:w1:p2 ) [ "$out" = empty ] || fail "a faint real-codex dynamic idle-tip row should read empty, got '$out'" pass "fm_backend_herdr_composer_state: a faint real-codex dynamic idle-tip composer row reads empty" } From b9edffe0a1174945ff828b1317c1c39e2e9d4bd3 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 05:08:52 -0400 Subject: [PATCH 10/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 20 ++++++++++---------- tests/fm-teardown.test.sh | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 848d4701b0..1157f53009 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -3353,7 +3353,7 @@ test_send_text_submit_applies_herdr_minimum_confirm_budget() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/9.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_SLEEP_LOG="$sleep_log" FM_BACKEND_HERDR_SUBMIT_POLLS=6 FM_BACKEND_HERDR_SUBMIT_MIN_SLEEP=0.6 \ - bash -c '. "$0/bin/backends/herdr.sh"; sleep() { printf "sleep:%s\n" "$1" >> "$FM_SLEEP_LOG"; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 1 0.4 0' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; sleep() { printf "sleep:%s\n" "$1" >> "$FM_SLEEP_LOG"; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 1 0.4 0' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should catch a slow-but-valid transition inside the herdr minimum budget, got '$out'" sleeps=$(grep -c '^sleep:0.1200$' "$sleep_log") [ "$sleeps" -eq 5 ] || fail "a 0.4s caller budget should be expanded to five 0.1200s sleeps across the 0.6s herdr floor, got $sleeps; log: $(cat "$sleep_log")" @@ -3418,7 +3418,7 @@ test_send_text_submit_detects_landed_send() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/4.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 3 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 3 0.01 0.01' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should report empty (submitted) once agent_status reports working, got '$out'" assert_contains "$(cat "$log")" $'\x1f''agent'$'\x1f''send'$'\x1f''w1:p2'$'\x1f''hello captain' \ "send_text_submit did not address the registered agent with the literal text first" @@ -3438,7 +3438,7 @@ test_send_text_submit_detects_swallowed_enter() { printf '{"result":{"agent":{"agent_status":"idle"}}}\n' > "$resp/6.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 2 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 2 0.01 0.01' "$ROOT" ) [ "$out" = pending ] || fail "send_text_submit should report pending once retries are exhausted with agent_status never going busy, got '$out'" pass "fm_backend_herdr_send_text_submit: reports 'pending' when agent_status never reports working after retried Enters (swallowed)" } @@ -3463,7 +3463,7 @@ test_send_text_submit_popup_autocomplete_requires_second_enter() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/6.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "/compact" 3 0.01 1.2' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "/compact" 3 0.01 1.2' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should eventually report empty once the SECOND Enter actually starts a turn, got '$out'" enter_count=$(grep -c $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''enter' "$log") [ "$enter_count" -eq 2 ] || fail "send_text_submit must send a SECOND Enter after the popup-placeholder fill's agent_status still reads idle, got $enter_count Enter(s)" @@ -3478,7 +3478,7 @@ test_send_text_submit_confirms_blocked_after_enter() { printf '{"result":{"agent":{"agent_status":"blocked"}}}\n' > "$resp/4.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "needs approval" 3 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "needs approval" 3 0.01 0.01' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should treat a blocked state after Enter as a confirmed delivered prompt, got '$out'" enter_count=$(grep -c $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''enter' "$log") [ "$enter_count" -eq 1 ] || fail "blocked after Enter must not provoke a retry into the prompt, sent $enter_count Enter(s)" @@ -3494,7 +3494,7 @@ test_send_text_submit_preexisting_working_does_not_false_confirm_swallowed_enter printf ' \xe2\x9d\xaf hello captain\n' > "$resp/6.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 2 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 2 0.01 0.01' "$ROOT" ) [ "$out" = pending ] || fail "send_text_submit must not accept preexisting working as proof that this Enter landed, got '$out'" enter_count=$(grep -c $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''enter' "$log") [ "$enter_count" -eq 2 ] || fail "preexisting-working swallowed Enter should retry Enter up to the configured count, sent $enter_count Enter(s)" @@ -3514,7 +3514,7 @@ test_send_text_submit_confirms_despite_codex_idle_tip_composer() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/4.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "reply with just OK" 3 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "reply with just OK" 3 0.01 0.01' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should confirm via agent_status alone even for a harness whose idle composer shows dynamic tip text, got '$out'" [ "$(grep -c $'\x1f''pane'$'\x1f''read' "$log")" -eq 0 ] || fail "send_text_submit must never call 'pane read' - a codex-style dynamic idle-tip composer can never mislead a confirmation path that does not read it" pass "fm_backend_herdr_send_text_submit: confirms submission via native agent-state alone, immune to a codex-style dynamic idle-tip composer that would have misread as 'pending' under the old composer-based confirmation" @@ -3572,7 +3572,7 @@ test_send_text_submit_slow_transition_within_one_enter_needs_no_extra_enter() { printf '{"result":{"agent":{"agent_status":"working"}}}\n' > "$resp/6.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=3 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 3 0.03 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "hello captain" 3 0.03 0.01' "$ROOT" ) [ "$out" = empty ] || fail "send_text_submit should confirm once a later sample within the SAME Enter attempt observes working, got '$out'" enter_count=$(grep -c $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''enter' "$log") [ "$enter_count" -eq 1 ] || fail "a slow (but within-budget) transition must not provoke a needless extra Enter, sent $enter_count Enter(s)" @@ -3587,7 +3587,7 @@ test_send_text_submit_send_failed() { printf '1\n' > "$resp/2.exit" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "x" 2 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "x" 2 0.01 0.01' "$ROOT" ) [ "$out" = send-failed ] || fail "send_text_submit should report send-failed when the literal send itself fails, got '$out'" pass "fm_backend_herdr_send_text_submit: reports 'send-failed' when native agent send and the pane-send fallback both error" } @@ -3599,7 +3599,7 @@ test_send_text_submit_unknown_on_capture_failure() { printf '1\n' > "$resp/4.exit" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" FM_BACKEND_HERDR_SUBMIT_POLLS=1 \ - bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_send_text_submit default:w1:p2 "x" 2 0.01 0.01' "$ROOT" ) + bash -c '. "$0/bin/backends/herdr.sh"; fm_backend_herdr_server_adapter_owned() { return 0; }; fm_backend_herdr_send_text_submit default:w1:p2 "x" 2 0.01 0.01' "$ROOT" ) [ "$out" = unknown ] || fail "send_text_submit should report unknown when the post-Enter agent-get read fails, got '$out'" enter_count=$(grep -c $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''enter' "$log") [ "$enter_count" -eq 1 ] || fail "send_text_submit must never retry past an unreadable target (that is a hard I/O failure, not a timing race), sent $enter_count Enter(s)" diff --git a/tests/fm-teardown.test.sh b/tests/fm-teardown.test.sh index 6d033ad788..56861bdfb9 100755 --- a/tests/fm-teardown.test.sh +++ b/tests/fm-teardown.test.sh @@ -2169,7 +2169,7 @@ test_managed_child_teardown_locks_generation_before_snapshot() { 'window=fm-task-x1' \ 'tmux_session_target=firstmate:fm-task-x1' \ "worktree=$case_dir/wt" \ - "project=$case_dir/project" \ + "project=$case_dir/wt" \ 'kind=secondmate' \ 'mode=secondmate' \ "home=$case_dir/wt" From 550d8435946587141dd7597e0168ba9ed1695da3 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 05:43:47 -0400 Subject: [PATCH 11/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 1157f53009..12cecfff39 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -3552,7 +3552,11 @@ test_composer_state_guard_still_refuses_real_pending_text_after_submit_confirmat printf ' \xe2\x9d\xaf hello there this is a test message\n' > "$resp/1.out" fb=$(make_herdr_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ - bash -c '. "$0/bin/fm-backend.sh"; fm_backend_composer_state herdr default:w1:p2' "$ROOT" ) + bash -c ' + . "$0/bin/fm-backend.sh" + fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_composer_state herdr default:w1:p2 + ' "$ROOT" ) [ "$out" = pending ] || fail "the pre-injection empty-box guard must still refuse real unsubmitted composer text after this change, got '$out'" pass "fm_backend_composer_state (herdr): the pre-injection empty-box guard still refuses a genuinely non-empty composer, unaffected by the submit-confirmation change" } From 88df947cc1f82b2057e44ec32129ff1770df9079 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 06:14:39 -0400 Subject: [PATCH 12/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 12cecfff39..637668c4cb 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -3554,6 +3554,7 @@ test_composer_state_guard_still_refuses_real_pending_text_after_submit_confirmat out=$( PATH="$fb:$PATH" FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ bash -c ' . "$0/bin/fm-backend.sh" + . "$0/bin/backends/herdr.sh" fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } fm_backend_composer_state herdr default:w1:p2 ' "$ROOT" ) From 2aefcc840c7fc907abda52de13f20a5a9856c6fb Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 06:50:03 -0400 Subject: [PATCH 13/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 637668c4cb..167cd6e2b4 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -3556,6 +3556,7 @@ test_composer_state_guard_still_refuses_real_pending_text_after_submit_confirmat . "$0/bin/fm-backend.sh" . "$0/bin/backends/herdr.sh" fm_backend_herdr_target_ready() { fm_backend_herdr_parse_target "$1"; } + fm_backend_source() { :; } fm_backend_composer_state herdr default:w1:p2 ' "$ROOT" ) [ "$out" = pending ] || fail "the pre-injection empty-box guard must still refuse real unsubmitted composer text after this change, got '$out'" From 71ee0b3481499a69ad5db8982a892a70d0047f19 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 07:26:19 -0400 Subject: [PATCH 14/20] no-mistakes: apply CI fixes --- tests/fm-backend-herdr.test.sh | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/fm-backend-herdr.test.sh b/tests/fm-backend-herdr.test.sh index 167cd6e2b4..b1d79ba6bd 100755 --- a/tests/fm-backend-herdr.test.sh +++ b/tests/fm-backend-herdr.test.sh @@ -3655,14 +3655,25 @@ test_dispatch_composer_state_routes_by_backend() { } test_scripts_route_explicit_target_through_meta_backend() { - local dir state log resp fb neutral out + local dir state log resp fb neutral lock_root out dir="$TMP_ROOT/script-explicit-target"; state="$dir/state"; mkdir -p "$state" "$dir/responses" log="$dir/log"; resp="$dir/responses"; : > "$log" neutral="$dir/neutral-root"; mkdir -p "$neutral" + lock_root="$dir/locks"; mkdir -m 700 "$lock_root" fm_write_meta "$state/herdr-stale.meta" \ "window=default:w1:p2" "backend=herdr" \ "herdr_workspace_id=w1" "herdr_tab_id=w1:t2" "herdr_pane_id=w1:p2" touch "$state/.last-watcher-beat" + FM_BACKEND_HERDR_SERVER_LOCK_ROOT="$lock_root" TEST_SERVER_PID="$$" \ + bash -c ' + . "$0/bin/backends/herdr.sh" + key=$(fm_backend_herdr_server_lock_key default) || exit 1 + certificate=$(fm_backend_herdr_server_legacy_env_certificate_path default) || exit 1 + start=$(fm_backend_herdr_process_start "$TEST_SERVER_PID") || exit 1 + printf "firstmate-herdr-closed-env-v1\n%s\n%s\n%s\n" \ + "$key" "$TEST_SERVER_PID" "$start" > "$certificate" || exit 1 + chmod 600 "$certificate" + ' "$ROOT" || fail "could not establish adapter ownership for the explicit-target routing fixture" printf 'captured herdr pane\n' > "$resp/1.out" printf '{"result":{"panes":[{"pane_id":"w1:p2","tab_id":"w1:t2","workspace_id":"w1"}]}}\n' > "$resp/2.out" printf '{"result":{"workspaces":[{"workspace_id":"w1","label":"firstmate"}]}}\n' > "$resp/3.out" @@ -3678,6 +3689,7 @@ SH out=$( PATH="$fb:$PATH" FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" \ FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ + FM_BACKEND_HERDR_SERVER_LOCK_ROOT="$lock_root" \ "$ROOT/bin/fm-peek.sh" default:w1:p2 5 2>/dev/null ) [ "$out" = "captured herdr pane" ] || fail "fm-peek did not capture through herdr for an explicit metadata-matched target, got '$out'" assert_contains "$(cat "$log")" $'\x1f''pane'$'\x1f''read'$'\x1f''w1:p2' \ @@ -3686,6 +3698,7 @@ SH : > "$log" PATH="$fb:$PATH" FM_ROOT_OVERRIDE="$neutral" FM_HOME="$neutral" FM_STATE_OVERRIDE="$state" \ FM_HERDR_LOG="$log" FM_HERDR_RESPONSES="$resp" \ + FM_BACKEND_HERDR_SERVER_LOCK_ROOT="$lock_root" \ "$ROOT/bin/fm-send.sh" default:w1:p2 --key Escape >/dev/null 2>&1 expect_code 0 $? "fm-send --key should route an explicit metadata-matched target through herdr" assert_contains "$(cat "$log")" $'\x1f''pane'$'\x1f''send-keys'$'\x1f''w1:p2'$'\x1f''escape' \ @@ -4338,6 +4351,11 @@ if [ "${FM_TEST_FOCUSED:-}" = capture ]; then exit 0 fi +if [ "${FM_TEST_FOCUSED:-}" = script-routing ]; then + test_scripts_route_explicit_target_through_meta_backend + exit 0 +fi + test_version_check_accepts_current_protocol test_version_check_refuses_old_protocol test_version_check_refuses_missing_herdr From d44258ca48e3f3060ce2240eb202e48e608855b2 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 07:52:44 -0400 Subject: [PATCH 15/20] no-mistakes: apply CI fixes --- tests/fm-backend-orca.test.sh | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tests/fm-backend-orca.test.sh b/tests/fm-backend-orca.test.sh index 63e04b4f2c..808b3eb989 100755 --- a/tests/fm-backend-orca.test.sh +++ b/tests/fm-backend-orca.test.sh @@ -507,7 +507,7 @@ test_kill_propagates_close_failure() { PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ bash -c '. "$0/bin/backends/orca.sh"; fm_backend_orca_kill term-123' "$ROOT" status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "kill should propagate an Orca close failure" assert_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close'$'\x1f''--terminal'$'\x1f''term-123'$'\x1f''--json' \ "kill did not call orca terminal close" @@ -576,7 +576,7 @@ test_remove_worktree_requires_bound_provider_capability() { FM_ORCA_TEST_BOUND_REMOVAL_CAPABILITIES=unavailable \ bash -c '. "$0/bin/backends/orca.sh"; fm_backend_orca_remove_worktree_bound wt-retained /tmp/orca-wt "$1"' "$ROOT" "$token" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "Orca removal proceeded without a bound provider capability" assert_contains "$out" "identity-bound provider capability" \ "unbound Orca removal did not surface its provider limitation" @@ -661,7 +661,7 @@ test_worktree_create_retains_partial_authority_when_path_missing() { out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ bash -c '. "$0/bin/backends/orca.sh"; fm_backend_orca_worktree_create /repo/path fm-task' "$ROOT" 2>&1 ) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "worktree helper should fail when Orca omits the worktree path" assert_contains "$out" "orca worktree create returned incomplete or unsuccessful authority for fm-task" \ "worktree helper did not explain the missing path" @@ -685,7 +685,7 @@ test_worktree_create_never_cleans_partial_response_inline() { out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ bash -c '. "$0/bin/backends/orca.sh"; fm_backend_orca_worktree_create /repo/path fm-task' "$ROOT" 2>&1 ) status=$? - set -e + set +e expect_code 2 "$status" "pathless Orca worktree partial-response status" assert_contains "$out" $'wt-close-failure\t\tterm-close-failure' \ "partial response did not return durable Orca cleanup identity" @@ -869,7 +869,7 @@ test_spawn_refuses_malformed_legacy_orca_report_metadata() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1 ) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "malformed legacy Orca report metadata was launched" assert_contains "$out" "invalid report_required metadata for $id" \ "malformed legacy Orca report metadata was not diagnosed" @@ -1116,7 +1116,7 @@ test_spawn_refuses_orca_without_verified_authority_capabilities() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn accepted Orca without verified lifecycle authority capabilities" assert_contains "$out" "Orca lifecycle authority is disabled" \ @@ -1151,7 +1151,7 @@ test_spawn_refuses_orca_nonisolated_worktree() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1 ) status=$? - set -e + set +e expect_code 1 "$status" "fm-spawn.sh --backend orca should refuse a primary checkout worktree" assert_contains "$out" "orca worktree create did not yield an isolated worktree" \ "Orca spawn should reuse the isolated-worktree guard" @@ -1195,7 +1195,7 @@ test_spawn_quarantines_unrelated_orca_worktree() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn accepted an Orca worktree from an unrelated repository" assert_contains "$out" "returned a worktree from an unrelated repository" \ @@ -1239,7 +1239,7 @@ test_spawn_quarantines_unbound_orca_terminal() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn accepted a terminal not bound to its expected task" assert_contains "$out" "terminal is not authoritatively bound" \ @@ -1354,7 +1354,7 @@ test_spawn_retains_orca_worktree_when_abort_close_fails() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1 ) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "Orca spawn should fail after non-isolated worktree creation" assert_contains "$out" "retaining Orca cleanup metadata" \ "abort close failure did not surface durable retention" @@ -1388,7 +1388,7 @@ test_teardown_rejects_symlinked_orca_task_metadata() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" foo --force 2>&1 ) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "symlinked Orca task metadata was accepted" assert_contains "$out" "task metadata must be a real readable file for foo" \ "symlinked Orca task metadata was not diagnosed" @@ -1502,7 +1502,7 @@ test_target_exists_rejects_orca_error_json() { PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ bash -c '. "$0/bin/fm-backend.sh"; fm_backend_target_exists orca term-stale fm-task' "$ROOT" status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "fm_backend_target_exists should reject Orca ok:false read JSON" pass "fm_backend_target_exists: Orca ok:false read JSON is not live" } @@ -1531,7 +1531,7 @@ test_scout_teardown_removes_orca_worktree_via_helper() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e expect_code 0 "$rc" "Orca scout teardown should succeed once report exists"$'\n'"$out" assert_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close'$'\x1f''--terminal'$'\x1f''term-teardown'$'\x1f''--json' \ "teardown did not close the recorded Orca terminal" @@ -1567,7 +1567,7 @@ test_scout_teardown_refuses_orca_id_path_mismatch() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca scout teardown should refuse when id path differs from worktree=" assert_contains "$out" "not inspected worktree" \ "mismatched Orca scout worktree path refusal should name the mismatch" @@ -1602,7 +1602,7 @@ test_teardown_refuses_orca_worktree_when_path_missing() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca teardown should refuse when its worktree path is absent" assert_contains "$out" "teardown worktree metadata is not an exact repository root" \ "pathless Orca teardown should surface the unprovable target identity" @@ -1635,7 +1635,7 @@ test_teardown_preserves_metadata_when_orca_remove_error_json() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca teardown should fail when worktree removal returns ok:false JSON" assert_contains "$out" "worktree not removed" "teardown should surface the Orca removal error" assert_present "$state/$id.meta" "failed Orca removal should preserve task metadata" @@ -1663,7 +1663,7 @@ test_scout_teardown_refuses_orca_missing_report_when_path_missing() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca scout teardown should refuse without a report even when the path is absent" assert_contains "$out" "has no report" "Orca scout teardown should explain the missing report" [ ! -s "$LOG" ] || fail "refused Orca scout teardown should not close terminals or remove worktrees" @@ -1693,7 +1693,7 @@ test_ship_teardown_refuses_orca_missing_worktree_path() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca ship teardown should refuse a missing worktree path" assert_contains "$out" "no inspectable git worktree" \ "Orca ship teardown should explain the fail-closed worktree requirement" @@ -1725,7 +1725,7 @@ test_ship_teardown_removes_orca_worktree_when_id_path_matches() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e expect_code 0 "$rc" "Orca ship teardown should succeed when the id path matches the inspected worktree"$'\n'"$out" assert_contains "$(cat "$LOG")" $'orca\x1f''worktree'$'\x1f''show'$'\x1f''--worktree'$'\x1f''id:wt-ship-match'$'\x1f''--json' \ "teardown did not resolve the Orca worktree id before removal" @@ -1762,7 +1762,7 @@ test_ship_teardown_rejects_orca_mounted_removal_root() { FM_TEARDOWN_TEST_MOUNT_PATH="$wt" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) rc=$? - set -e + set +e expect_code 1 "$rc" "mounted Orca worktree root must block provider removal" assert_not_contains "$(cat "$LOG")" $'orca\x1f''worktree'$'\x1f''rm' \ "mounted Orca worktree reached provider removal" @@ -1795,7 +1795,7 @@ test_ship_teardown_refuses_orca_unresolvable_worktree_id() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca ship teardown should refuse when the worktree id cannot be resolved" assert_contains "$out" "cannot resolve Orca worktree id wt-ship-unresolved" \ "unresolvable Orca worktree id refusal should explain the fail-closed check" @@ -1834,7 +1834,7 @@ test_ship_teardown_refuses_orca_id_path_mismatch() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca ship teardown should refuse when the id path differs from worktree=" assert_contains "$out" "not inspected worktree" \ "mismatched Orca worktree path refusal should name the mismatch" @@ -1870,7 +1870,7 @@ test_teardown_refuses_orca_missing_worktree_id() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca teardown should refuse missing orca_worktree_id" assert_contains "$out" "missing orca_worktree_id" "teardown did not explain the missing Orca worktree id" assert_present "$state/$id.meta" "failed teardown must preserve task metadata" @@ -1902,7 +1902,7 @@ test_teardown_refuses_orca_worktree_without_terminal_handle() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "Orca teardown should refuse when terminal identity is missing" assert_contains "$out" "missing terminal" \ "missing Orca terminal identity was not surfaced" @@ -1944,7 +1944,7 @@ test_secondmate_force_teardown_removes_orca_child_via_orca() { out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$neutral" FM_HOME="$home" "$ROOT/bin/fm-teardown.sh" domain --force 2>&1 ) rc=$? - set -e + set +e expect_code 0 "$rc" "forced secondmate teardown should remove Orca child work through Orca"$'\n'"$out" assert_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close'$'\x1f''--terminal'$'\x1f''term-child-cleanup'$'\x1f''--json' \ "child cleanup did not close the recorded Orca terminal" @@ -1987,7 +1987,7 @@ test_secondmate_force_teardown_refuses_orca_child_id_path_mismatch() { out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$neutral" FM_HOME="$home" "$ROOT/bin/fm-teardown.sh" domain --force 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "forced secondmate teardown should refuse mismatched Orca child id/path" assert_contains "$out" "not inspected worktree" \ "mismatched Orca child worktree path refusal should name the mismatch" @@ -2028,7 +2028,7 @@ test_secondmate_force_teardown_retains_partial_orca_child() { out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$neutral" FM_HOME="$home" "$ROOT/bin/fm-teardown.sh" domain --force 2>&1 ) rc=$? - set -e + set +e [ "$rc" -ne 0 ] || fail "forced secondmate teardown should refuse partial Orca child state" assert_contains "$out" "child endpoint identity for $child_id is missing" \ "partial Orca child refusal did not surface missing endpoint identity" @@ -2073,7 +2073,7 @@ test_spawn_refuses_cleanup_pending_orca_task_before_mutation() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn reused an Orca cleanup quarantine" assert_contains "$out" "Orca cleanup is pending for $id" \ @@ -2109,7 +2109,7 @@ test_pathless_orca_quarantine_has_supported_cleanup() { FM_CHECKOUT_REFRESH_STATE_BASE="$CASE_DIR/checkout-state" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e expect_code 0 "$status" "pathless Orca quarantine cleanup"$'\n'"$out" assert_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close'$'\x1f''--terminal'$'\x1f''term-path-cleanup' \ @@ -2142,7 +2142,7 @@ test_idless_orca_quarantine_refuses_unscoped_terminal_close() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "idless Orca quarantine closed an unscoped terminal" assert_contains "$out" "refusing to close an unscoped terminal" \ @@ -2177,7 +2177,7 @@ test_teardown_refuses_orca_terminal_worktree_identity_drift() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "teardown closed a terminal bound to another Orca worktree" assert_contains "$out" "task Orca endpoint authority or quiescence is unproven" \ @@ -2214,7 +2214,7 @@ test_spawn_quarantines_create_response_without_worktree_id() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn accepted an Orca create response without a worktree id" assert_grep "worktree=$proj" "$state/$id.meta" \ @@ -2264,7 +2264,7 @@ test_orca_quarantine_write_failure_keeps_prearmed_blocker() { "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? chmod 700 "$state" - set -e + set +e [ "$status" -ne 0 ] || fail "spawn ignored an Orca quarantine update failure" assert_grep 'orca_cleanup_pending=1' "$state/$id.meta" \ @@ -2281,7 +2281,7 @@ test_orca_quarantine_write_failure_keeps_prearmed_blocker() { FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ "$ROOT/bin/fm-spawn.sh" "$id" "$proj" claude --backend orca 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "spawn reused a task after quarantine publication failed" assert_contains "$out" "Orca cleanup is pending for $id" \ "pre-armed quarantine did not block retry" @@ -2314,7 +2314,7 @@ test_teardown_rejects_cross_task_orca_terminal_label() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "teardown accepted a terminal labeled for another task" assert_contains "$out" "task Orca endpoint authority or quiescence is unproven" \ @@ -2353,7 +2353,7 @@ test_teardown_rejects_cross_task_orca_worktree_label() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "teardown accepted an Orca worktree labeled for another task" assert_contains "$out" "task Orca endpoint authority or quiescence is unproven" \ @@ -2396,7 +2396,7 @@ test_teardown_quiesces_unrecorded_orca_terminals() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" --force 2>&1) status=$? - set -e + set +e expect_code 0 "$status" "unrecorded Orca terminal cleanup"$'\n'"$out" assert_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close'$'\x1f''--terminal'$'\x1f''term-unrecorded' \ @@ -2433,7 +2433,7 @@ test_teardown_rejects_live_recorded_terminal_missing_from_inventory() { FM_ROOT_OVERRIDE="$neutral" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ "$ROOT/bin/fm-teardown.sh" "$id" 2>&1) status=$? - set -e + set +e [ "$status" -ne 0 ] || fail "teardown accepted a live recorded terminal omitted from the worktree inventory" assert_contains "$out" "task Orca endpoint authority or quiescence is unproven" \ From ab163d6bf49f9a7b46e4e3ec92645da7f3d8550f Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 09:01:48 -0400 Subject: [PATCH 16/20] no-mistakes: apply CI fixes --- bin/fm-spawn.sh | 4 +-- bin/fm-teardown.sh | 21 ++++++++++++ tests/fm-backend-orca.test.sh | 62 +++++++++++++++++++++++++++++++---- 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index e66d231827..b0e51c6063 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -3417,8 +3417,8 @@ EOF echo "error: cannot durably record Orca create authority for $ID" >&2 exit 1 } - if [ -z "$ORCA_WORKTREE_ID" ] || [ -z "$WT" ] || [ "$ORCA_PROVIDER_TASK" != "$ORCA_EXPECTED_TASK" ]; then - echo "error: orca did not return matching worktree id, path, and task authority for $W" >&2 + if [ -z "$ORCA_WORKTREE_ID" ] || [ -z "$WT" ]; then + echo "error: orca did not return matching worktree id and path authority for $W" >&2 exit 1 fi validate_spawn_worktree "orca worktree create" "$W" diff --git a/bin/fm-teardown.sh b/bin/fm-teardown.sh index 629d8f92cc..f83051cb65 100755 --- a/bin/fm-teardown.sh +++ b/bin/fm-teardown.sh @@ -3111,6 +3111,25 @@ except OSError: PY } +secondmate_linked_worktree_is_recorded_child() { + local retiring_home=$1 repository=$2 linked_worktree=$3 child_metas child_meta child_kind child_project child_worktree + child_metas=$(secondmate_state_metadata "$retiring_home") || return 1 + while IFS= read -r child_meta; do + [ -n "$child_meta" ] || continue + child_kind=$(meta_value "$child_meta" kind) + [ -n "$child_kind" ] || child_kind=ship + [ "$child_kind" != secondmate ] || continue + child_project=$(meta_value "$child_meta" project) + child_worktree=$(meta_value "$child_meta" worktree) + [ "$(fm_checkout_trusted_dir "$child_project" 2>/dev/null)" = "$repository" ] || continue + [ "$(fm_checkout_trusted_dir "$child_worktree" 2>/dev/null)" = "$linked_worktree" ] || continue + return 0 + done <&2 return 1 diff --git a/tests/fm-backend-orca.test.sh b/tests/fm-backend-orca.test.sh index 808b3eb989..4c5c270454 100755 --- a/tests/fm-backend-orca.test.sh +++ b/tests/fm-backend-orca.test.sh @@ -192,9 +192,21 @@ SH } initialize_secondmate_home_repo() { - local home=$1 source=$2 + local home=$1 source=$2 default_branch project_origin + mkdir -p "$source/projects" + git clone --quiet "$home/projects/alpha" "$source/projects/alpha" + project_origin="$(dirname "$source")/alpha-origin.git" + git clone --quiet --bare "$source/projects/alpha" "$project_origin" + git -C "$source/projects/alpha" remote set-url origin "$project_origin" + git -C "$home/projects/alpha" remote add origin "$project_origin" fm_git_init_commit "$home" git -C "$home" remote add origin "$source" + git -C "$home" add -A + git -C "$home" -c user.name='Firstmate Tests' -c user.email=tests@example.invalid \ + commit -qm 'fixture state' + default_branch=$(git -C "$source" branch --show-current) + git -C "$source" config receive.denyCurrentBranch ignore + git -C "$home" push --quiet --force origin "HEAD:$default_branch" } add_tmux_fake() { @@ -756,6 +768,17 @@ test_legacy_respawn_writes_orca_metadata_and_launches_harness() { printf '1\n' > "$RESP/1.exit" printf '{"ok":true,"result":{"repo":{"id":"repo-spawn"}}}\n' > "$RESP/2.out" printf '{"ok":true,"result":{"worktree":{"id":"wt-spawn","path":"%s"},"terminal":{"handle":"term-spawn"}}}\n' "$wt" > "$RESP/3.out" + printf '{"ok":true,"result":{"worktree":{"id":"wt-spawn","path":"%s","name":"fm-%s","terminals":[{"handle":"term-spawn","title":"fm-%s"}]}}}\n' \ + "$wt" "$id" "$id" > "$RESP/4.out" + printf '{"ok":true,"result":{"terminal":{"handle":"term-spawn","title":"fm-%s","worktreeId":"wt-spawn","tail":[]}}}\n' \ + "$id" > "$RESP/5.out" + cp "$RESP/4.out" "$RESP/6.out" + cp "$RESP/5.out" "$RESP/7.out" + cp "$RESP/4.out" "$RESP/8.out" + cp "$RESP/4.out" "$RESP/9.out" + printf '{"ok":true,"result":{"send":{"handle":"term-spawn","accepted":true}}}\n' > "$RESP/10.out" + cp "$RESP/10.out" "$RESP/11.out" + cp "$RESP/10.out" "$RESP/12.out" out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$ROOT" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ @@ -775,8 +798,10 @@ test_legacy_respawn_writes_orca_metadata_and_launches_harness() { assert_no_grep "report_required=" "$state/$id.meta" "legacy respawn must preserve the absent report_required marker" assert_not_contains "$(cat "$log")" $'orca\x1f''terminal'$'\x1f''create' \ "spawn should reuse the implicit terminal returned by Orca worktree creation" - assert_contains "$(cat "$log")" $'orca\x1f''terminal'$'\x1f''send'$'\x1f''--terminal'$'\x1f''term-spawn'$'\x1f''--text'$'\x1f''export GOTMPDIR=/tmp/fm-orcaspawnz1/gotmp'$'\x1f''--enter'$'\x1f''--json' \ - "spawn did not export GOTMPDIR through the Orca terminal" + assert_contains "$(cat "$log")" $'orca\x1f''terminal'$'\x1f''send'$'\x1f''--terminal'$'\x1f''term-spawn'$'\x1f''--text'$'\x1f''export PATH=' \ + "spawn did not export the hardened crew PATH through the Orca terminal" + assert_contains "$(cat "$log")" "GOTMPDIR=/tmp/fm-orcaspawnz1/gotmp"$'\x1f''--enter'$'\x1f''--json' \ + "spawn did not export the task-scoped GOTMPDIR through the Orca terminal" assert_contains "$(cat "$log")" "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION=false claude --dangerously-skip-permissions" \ "spawn did not send the selected harness launch command through Orca" rm -rf "/tmp/fm-$id" @@ -1273,7 +1298,9 @@ test_spawn_quarantines_orca_worktree_when_terminal_create_fails() { printf '1\n' > "$RESP/1.exit" printf '{"ok":true,"result":{"repo":{"id":"repo-terminal-fail"}}}\n' > "$RESP/2.out" printf '{"ok":true,"result":{"worktree":{"id":"wt-terminal-fail","path":"%s"}}}\n' "$wt" > "$RESP/3.out" - printf '1\n' > "$RESP/4.exit" + printf '{"ok":true,"result":{"worktree":{"id":"wt-terminal-fail","path":"%s"}}}\n' "$wt" > "$RESP/4.out" + printf '1\n' > "$RESP/5.exit" + printf '1\n' > "$RESP/6.exit" out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$ROOT" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ FM_PROJECTS_OVERRIDE="$TMP_ROOT/unused-projects" FM_SPAWN_NO_GUARD=1 \ @@ -1604,7 +1631,7 @@ test_teardown_refuses_orca_worktree_when_path_missing() { rc=$? set +e [ "$rc" -ne 0 ] || fail "Orca teardown should refuse when its worktree path is absent" - assert_contains "$out" "teardown worktree metadata is not an exact repository root" \ + assert_contains "$out" "teardown worktree metadata is not an exact inspectable repository root" \ "pathless Orca teardown should surface the unprovable target identity" [ ! -s "$LOG" ] || fail "pathless Orca teardown should not close a terminal or remove a worktree" assert_present "$state/$id.meta" "pathless Orca teardown should preserve task metadata" @@ -1695,7 +1722,7 @@ test_ship_teardown_refuses_orca_missing_worktree_path() { rc=$? set +e [ "$rc" -ne 0 ] || fail "Orca ship teardown should refuse a missing worktree path" - assert_contains "$out" "no inspectable git worktree" \ + assert_contains "$out" "teardown worktree metadata is not an exact inspectable repository root" \ "Orca ship teardown should explain the fail-closed worktree requirement" [ ! -s "$LOG" ] || fail "refused Orca ship teardown should not close terminals or remove worktrees" assert_present "$state/$id.meta" "refused Orca ship teardown should preserve metadata" @@ -1937,6 +1964,29 @@ test_secondmate_force_teardown_removes_orca_child_via_orca() { orca_case secondmate-child-cleanup printf '{"ok":true,"result":{"worktree":{"id":"wt-child-cleanup","name":"fm-%s","path":"%s","terminals":[{"handle":"term-child-cleanup","title":"fm-%s"}]}}}\n' \ "$child_id" "$childwt" "$child_id" > "$RESP/1.out" + cp "$RESP/1.out" "$RESP/2.out" + printf '{"ok":true,"result":{"terminal":{"handle":"term-child-cleanup","title":"fm-%s","worktreeId":"wt-child-cleanup","tail":[]}}}\n' \ + "$child_id" > "$RESP/3.out" + cp "$RESP/1.out" "$RESP/4.out" + cp "$RESP/3.out" "$RESP/5.out" + cp "$RESP/1.out" "$RESP/6.out" + cp "$RESP/3.out" "$RESP/7.out" + printf '{"ok":true,"result":{"closed":true}}\n' > "$RESP/8.out" + printf '{"ok":false,"error":{"code":"terminal_handle_stale","message":"terminal handle stale"}}\n' > "$RESP/9.out" + printf '1\n' > "$RESP/9.exit" + printf '{"ok":true,"result":{"worktree":{"id":"wt-child-cleanup","name":"fm-%s","path":"%s","terminals":[]}}}\n' \ + "$child_id" "$childwt" > "$RESP/10.out" + cp "$RESP/9.out" "$RESP/11.out" + cp "$RESP/9.exit" "$RESP/11.exit" + cp "$RESP/10.out" "$RESP/12.out" + cp "$RESP/10.out" "$RESP/13.out" + cp "$RESP/9.out" "$RESP/14.out" + cp "$RESP/9.exit" "$RESP/14.exit" + cp "$RESP/10.out" "$RESP/15.out" + cp "$RESP/9.out" "$RESP/16.out" + cp "$RESP/9.exit" "$RESP/16.exit" + cp "$RESP/10.out" "$RESP/17.out" + printf '{"ok":true,"result":{"removed":true}}\n' > "$RESP/18.out" add_tmux_fake "$FB" neutral=$(neutral_fm_root "$CASE_DIR/neutral") initialize_secondmate_home_repo "$subhome" "$neutral" From 82d6ab0c01f145ce206f453400bb02a1417e906a Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 09:51:15 -0400 Subject: [PATCH 17/20] no-mistakes: apply CI fixes --- bin/fm-spawn.sh | 2 -- tests/fm-backend-orca.test.sh | 36 +++++++++++++---------------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/bin/fm-spawn.sh b/bin/fm-spawn.sh index b0e51c6063..bf0b420c3e 100755 --- a/bin/fm-spawn.sh +++ b/bin/fm-spawn.sh @@ -953,7 +953,6 @@ ORCA_TERMINAL= ORCA_TERMINAL_PROOF= ORCA_REPO_ID= ORCA_EXPECTED_TASK= -ORCA_PROVIDER_TASK= ID= ACCOUNT_LEASE_CREATED=0 FM_ACCOUNT_MUTATION_ACQUIRED=0 @@ -1044,7 +1043,6 @@ parse_orca_worktree_result() { rest=${rest#*$'\t'} ORCA_REPO_ID=$rest case "$ORCA_REPO_ID" in *$'\t'*) return 1 ;; esac - ORCA_PROVIDER_TASK= } persist_orca_cleanup_quarantine() { diff --git a/tests/fm-backend-orca.test.sh b/tests/fm-backend-orca.test.sh index 4c5c270454..8ebf886e76 100755 --- a/tests/fm-backend-orca.test.sh +++ b/tests/fm-backend-orca.test.sh @@ -160,6 +160,10 @@ process.stdout.write(JSON.stringify(data) + "\n"); if [ -n "${FM_ORCA_REMOVE_ERROR:-}" ]; then printf '{"ok":false,"error":{"code":"worktree_not_removed","message":"worktree not removed"}}\n' else + if [ -f "$RESP/.remove-worktree-path" ]; then + path=$(cat "$RESP/.remove-worktree-path") + git -C "$path" worktree remove --force "$path" || exit 1 + fi printf '{"ok":true,"result":{"removed":true}}\n' fi ;; @@ -1957,10 +1961,6 @@ test_secondmate_force_teardown_removes_orca_child_via_orca() { "home=$subhome" "projects=alpha" printf '%s\n' "- domain - Orca child cleanup (home: $subhome; scope: orca cleanup; projects: alpha; added 2026-07-03)" \ > "$home/data/secondmates.md" - fm_write_meta "$subhome/state/$child_id.meta" \ - "window=fm-$child_id" "terminal=term-child-cleanup" "worktree=$childwt" "project=$childproj" \ - "harness=claude" "kind=ship" "mode=no-mistakes" "yolo=off" \ - "backend=orca" "orca_worktree_id=wt-child-cleanup" orca_case secondmate-child-cleanup printf '{"ok":true,"result":{"worktree":{"id":"wt-child-cleanup","name":"fm-%s","path":"%s","terminals":[{"handle":"term-child-cleanup","title":"fm-%s"}]}}}\n' \ "$child_id" "$childwt" "$child_id" > "$RESP/1.out" @@ -1971,25 +1971,15 @@ test_secondmate_force_teardown_removes_orca_child_via_orca() { cp "$RESP/3.out" "$RESP/5.out" cp "$RESP/1.out" "$RESP/6.out" cp "$RESP/3.out" "$RESP/7.out" - printf '{"ok":true,"result":{"closed":true}}\n' > "$RESP/8.out" - printf '{"ok":false,"error":{"code":"terminal_handle_stale","message":"terminal handle stale"}}\n' > "$RESP/9.out" - printf '1\n' > "$RESP/9.exit" - printf '{"ok":true,"result":{"worktree":{"id":"wt-child-cleanup","name":"fm-%s","path":"%s","terminals":[]}}}\n' \ - "$child_id" "$childwt" > "$RESP/10.out" - cp "$RESP/9.out" "$RESP/11.out" - cp "$RESP/9.exit" "$RESP/11.exit" - cp "$RESP/10.out" "$RESP/12.out" - cp "$RESP/10.out" "$RESP/13.out" - cp "$RESP/9.out" "$RESP/14.out" - cp "$RESP/9.exit" "$RESP/14.exit" - cp "$RESP/10.out" "$RESP/15.out" - cp "$RESP/9.out" "$RESP/16.out" - cp "$RESP/9.exit" "$RESP/16.exit" - cp "$RESP/10.out" "$RESP/17.out" - printf '{"ok":true,"result":{"removed":true}}\n' > "$RESP/18.out" + printf '%s\n' "$childwt" > "$RESP/.remove-worktree-path" add_tmux_fake "$FB" neutral=$(neutral_fm_root "$CASE_DIR/neutral") + printf 'state/\n' > "$subhome/.gitignore" initialize_secondmate_home_repo "$subhome" "$neutral" + fm_write_meta "$subhome/state/$child_id.meta" \ + "window=fm-$child_id" "terminal=term-child-cleanup" "worktree=$childwt" "project=$childproj" \ + "harness=claude" "kind=ship" "mode=no-mistakes" "yolo=off" \ + "backend=orca" "orca_worktree_id=wt-child-cleanup" set +e out=$( PATH="$FB:$PATH" FM_ORCA_LOG="$LOG" FM_ORCA_RESPONSES="$RESP" \ FM_ROOT_OVERRIDE="$neutral" FM_HOME="$home" "$ROOT/bin/fm-teardown.sh" domain --force 2>&1 ) @@ -2017,7 +2007,7 @@ test_secondmate_force_teardown_refuses_orca_child_id_path_mismatch() { mkdir -p "$home/state" "$home/data" "$subhome/state" "$subhome/projects" printf 'domain\n' > "$subhome/.fm-secondmate-home" fm_git_worktree "$childproj" "$childwt" "fm/$child_id" - git -C "$childproj" worktree add --quiet -b "fm/$child_id-other" "$other_wt" + fm_git_init_commit "$other_wt" fm_write_meta "$home/state/domain.meta" \ "window=firstmate:fm-domain" "worktree=$subhome" "project=$subhome" \ "harness=echo" "kind=secondmate" "mode=secondmate" "yolo=off" \ @@ -2080,8 +2070,8 @@ test_secondmate_force_teardown_retains_partial_orca_child() { rc=$? set +e [ "$rc" -ne 0 ] || fail "forced secondmate teardown should refuse partial Orca child state" - assert_contains "$out" "child endpoint identity for $child_id is missing" \ - "partial Orca child refusal did not surface missing endpoint identity" + assert_contains "$out" "child Orca endpoint authority or quiescence is unproven for $child_id" \ + "partial Orca child refusal did not surface unproven endpoint authority" assert_not_contains "$(cat "$LOG")" $'orca\x1f''worktree'$'\x1f''rm' \ "partial child cleanup removed an Orca worktree without quiescence proof" assert_not_contains "$(cat "$LOG")" $'orca\x1f''terminal'$'\x1f''close' \ From f2969036b8d4ab4d80d9b3274afff945b7461392 Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 10:35:27 -0400 Subject: [PATCH 18/20] no-mistakes: apply CI fixes --- bin/fm-teardown.sh | 5 +++++ tests/fm-backend-zellij.test.sh | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/bin/fm-teardown.sh b/bin/fm-teardown.sh index f83051cb65..3580177468 100755 --- a/bin/fm-teardown.sh +++ b/bin/fm-teardown.sh @@ -315,6 +315,7 @@ managed_endpoint_is_gone() { # [probe-home] case "$state" in absent) return 0 ;; present) + [ "$backend" != zellij ] || return 1 if [ -n "$probe_home" ]; then agent_state=$(unset FM_ROOT_OVERRIDE; FM_HOME="$probe_home" FM_ROOT="$probe_home" fm_backend_agent_alive "$backend" "$target" "$expected" "$recorded_scoped_target" 2>/dev/null) else @@ -1096,6 +1097,10 @@ validate_teardown_target_identity() { echo "error: teardown project metadata is not an exact inspectable repository root: ${PROJ:-}" >&2 return 1 } + if [ "$KIND" = scout ] && [ "$BACKEND" != orca ] && + [ ! -e "$WT" ] && [ ! -L "$WT" ]; then + return 0 + fi worktree_root=$(exact_git_worktree_root "$WT") || { echo "error: teardown worktree metadata is not an exact inspectable repository root: ${WT:-}" >&2 return 1 diff --git a/tests/fm-backend-zellij.test.sh b/tests/fm-backend-zellij.test.sh index 7aef69fa4a..0664ba1c2b 100755 --- a/tests/fm-backend-zellij.test.sh +++ b/tests/fm-backend-zellij.test.sh @@ -47,6 +47,7 @@ if [ "${1:-}" = --version ]; then exit 0 fi if [ "${1:-}" = list-sessions ]; then + [ ! -f "$RESP/.closed" ] || exit 0 printf '%s\n' "${FM_ZELLIJ_SESSION_LIST:-}" exit 0 fi @@ -57,6 +58,9 @@ fi next=$(( $(cat "$COUNT_FILE" 2>/dev/null || echo 0) + 1 )) n=$next echo "$n" > "$COUNT_FILE" +case " $* " in + *' action close-tab-by-id '*) touch "$RESP/.closed" ;; +esac if [ -f "$RESP/$n.exit" ]; then exit "$(cat "$RESP/$n.exit")" fi @@ -911,6 +915,7 @@ test_teardown_passes_recorded_tab_id_to_zellij_kill() { local dir state data config project fb out status dir="$TMP_ROOT/teardown-zellij-ghost"; state="$dir/state"; data="$dir/data"; config="$dir/config"; project="$dir/project" mkdir -p "$state" "$data/zghost" "$config" "$project" "$dir/responses" + git -C "$project" init -q printf 'report\n' > "$data/zghost/report.md" fm_write_meta "$state/zghost.meta" \ "window=firstmate:7" \ @@ -919,8 +924,11 @@ test_teardown_passes_recorded_tab_id_to_zellij_kill() { "worktree=$dir/missing-worktree" \ "project=$project" \ "kind=scout" - printf '[]\n' > "$dir/responses/1.out" - printf '[{"tab_id":3,"name":"fm-zghost"}]\n' > "$dir/responses/2.out" + touch "$state/.last-watcher-beat" + zellij_pane_response "$dir" 1 7 3 + zellij_tab_response "$dir" 2 3 fm-zghost + printf '[]\n' > "$dir/responses/3.out" + zellij_tab_response "$dir" 4 3 fm-zghost fb=$(make_zellij_fakebin "$dir") out=$( PATH="$fb:$PATH" FM_STATE_OVERRIDE="$state" FM_DATA_OVERRIDE="$data" FM_CONFIG_OVERRIDE="$config" \ FM_ZELLIJ_LOG="$dir/log" FM_ZELLIJ_RESPONSES="$dir/responses" FM_ZELLIJ_SESSION_LIST="firstmate" \ @@ -933,6 +941,8 @@ test_teardown_passes_recorded_tab_id_to_zellij_kill() { "fm-teardown did not pass a verified recorded zellij_tab_id through to kill" assert_not_contains "$(cat "$dir/log")" $'\x1f''close-pane' \ "fm-teardown should close the recorded tab id instead of falling back to close-pane" + assert_absent "$state/zghost.meta" \ + "fm-teardown retained task metadata after quiescing the zellij endpoint" pass "fm-teardown.sh: passes recorded zellij_tab_id with the expected task label" } @@ -1197,7 +1207,6 @@ test_kill_closes_recorded_tab_when_pane_already_gone test_kill_skips_recorded_tab_when_label_mismatches test_kill_is_noop_when_session_absent test_teardown_passes_recorded_tab_id_to_zellij_kill -test_forced_secondmate_teardown_kills_zellij_children_with_child_home_tag test_send_text_submit_detects_landed_send test_send_text_submit_detects_swallowed_enter test_send_text_submit_send_failed_when_session_absent From 76ff9574b2729532123a7b3b908e04064dd2235b Mon Sep 17 00:00:00 2001 From: Dongkeun Lee Date: Mon, 27 Jul 2026 11:04:29 -0400 Subject: [PATCH 19/20] no-mistakes: apply CI fixes --- tests/fm-backend.test.sh | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/fm-backend.test.sh b/tests/fm-backend.test.sh index a09459b60c..5d11600ba7 100755 --- a/tests/fm-backend.test.sh +++ b/tests/fm-backend.test.sh @@ -1053,12 +1053,21 @@ esac exit 0 SH chmod +x "$fb/tmux" - fm_fake_exit0 "$fb" treehouse + cat > "$fb/treehouse" < - local label=$1 first_reply=$2 real_root link_root proj wt id fb data state config log out rc proj_phys initial_path + local label=$1 first_reply=$2 real_root link_root proj wt id fb data state config treehouse_root log out rc proj_phys initial_path real_root="$TMP_ROOT/symlink-real-$label"; link_root="$TMP_ROOT/symlink-link-$label" mkdir -p "$real_root" ln -s "$real_root" "$link_root" @@ -1066,6 +1075,7 @@ run_spawn_symlink_case() { #