Skip to content

fix(bin): never report done for a run whose pr or ci step was skipped - #1896

Open
ivannovak wants to merge 3 commits into
kunchenguid:mainfrom
ivannovak:fm/nm-pr-ci-steps-skip-silently
Open

fix(bin): never report done for a run whose pr or ci step was skipped#1896
ivannovak wants to merge 3 commits into
kunchenguid:mainfrom
ivannovak:fm/nm-pr-ci-steps-skip-silently

Conversation

@ivannovak

Copy link
Copy Markdown

Intent

Fix: the no-mistakes pipeline reaches outcome=passed with its pr and ci steps silently skipped, so a run can report the pipeline's strongest terminal verdict having never opened a PR or observed a single CI check. Found 2026-08-05 across five consecutive auctic-core runs (dev-5190, dev-5441, dev-5490, auctic-dompdf2-lane-stranded, auctic-phpstan-never-loaded), each showing push,completed then pr,skipped and ci,skipped; the step logs name the cause: 'skipping PR creation: gh CLI is not authenticated'. Task scope had two parts. Part 1, establish why the daemon's gh has no credential when interactive gh works: established empirically that the daemon runs as a launchd LaunchAgent (installed 2026-07-31 by the v1.41.2 update) with only HOME and PATH env; gh's token lives only in the macOS login keychain (hosts.yml has no token); env alone does not reproduce the failure (gh auth status succeeds under env -i with the daemon's exact env); the same daemon created PRs Aug 1-4 then failed consistently from Aug 5 18:55 with no reboot, no gh upgrade, and no keychain item change - so the daemon's detached security session lost login-keychain access at runtime. The daemon itself is a closed-source third-party binary, so it cannot be patched here. Part 2, make a skipped pr or ci step fail the run or at minimum forbid the passed outcome: implemented on firstmate's side in bin/fm-crew-state.sh, the single owner of run-state interpretation (verified no other bin script parses outcome). A new nm_skipped_delivery_steps helper scans the axi status steps[] table; when a run reads passed, checks-passed, or bare completed status with a skipped pr or ci row, the crew state now reports failed naming the skipped steps, never done, so the fleet view cannot claim 'run passed: PR merged/closed' for a PR that never existed. The companion rendering bug (fm-crew-state-false-merged-claim, the 'PR merged/closed' wording on genuine passes at bin/fm-crew-state.sh) is filed separately and deliberately NOT changed here; genuine passes keep their existing wording, enforced by a negative-control test. Tests: new fixtures in tests/fm-crew-state.test.sh mirror the real skipped-delivery axi output verified against real run 01KZBCA6DEHQC1404F34QJE0CC; the guard was watched fail red against the unguarded code and again with its match pattern sabotaged; a negative control keeps a genuinely delivered pass reporting done. Constraints honored: never restart or modify the shared no-mistakes daemon; no launchd state mutation (the definitive launchd-context gh test was deliberately not run because it would mutate state outside the task worktree); repo style one-sentence-per-line comments, shellcheck-clean via bin/fm-lint.sh, colocated tests extending the existing fm-crew-state.test.sh runner.

What Changed

  • bin/fm-crew-state.sh gains nm_skipped_delivery_steps, which scans the axi status steps table, and nm_missing_delivery_evidence, which derives the wording from what was actually skipped. A run reading passed, checks-passed, or bare completed with a skipped pr or ci row now reports failed naming the skipped steps and only the evidence that does not exist (no pull request opened, no CI check observed, or both) instead of done.
  • The coarse no-mistakes runs list fallback no longer maps a terminal completed row to done; that source carries no steps table, so it reports unknown and points at axi status for the branch's own run. The failed/cancelled coarse arms are unchanged.
  • tests/fm-crew-state.test.sh adds four fixtures mirroring the real skipped-delivery axi output plus six cases, including a negative control that keeps a genuinely delivered pass reporting done and a case covering the coarse terminal row. AGENTS.md and docs/architecture.md record the new rule for both paths.

Risk Assessment

✅ Low: Both captain-directed fixes are implemented precisely to their stated scope with regression tests and scope guards, no existing test or consumer depended on the changed coarse mapping, and no path in the script can now certify done without delivery-step evidence.

Testing

I ran the targeted colocated suite (tests/fm-crew-state.test.sh, all green) plus the three neighbouring suites that consume fm-crew-state, then went past unit tests to a product-level end-to-end run: a throwaway firstmate home with four ship crews whose fake no-mistakes axi status output mirrors the real 2026-08-05 incident, driven through the actual operator commands (fm-crew-state.sh, fm-fleet-snapshot.sh --json, fm-fleet-view.sh) once against the base commit and once against the fix. The captured transcripts show the fleet view's Current column moving from done / run-step - run passed: PR merged/closed to failed / run-step - no pull request was opened and no CI check was observed for the two runs that never opened a PR, the ci-only skip naming only the missing CI evidence, and the genuinely delivered pass staying done with its wording unchanged. I then watched each new check fail: four mutations (guard removed, ci dropped from the match pattern, coarse completed arm restored to done, guard widened to fire on completed rows) each drove a different new assertion red, so none of them - including the negative control - is inert. No screenshots or rendered HTML apply here: the changed surface is a terminal CLI/markdown fleet table with no browser or GUI rendering path, so the CLI transcripts are the end-user surface. One failure in tests/fm-teardown.test.sh turned out to be pre-existing (identical failure with base-commit fm-crew-state.sh) and unrelated to run-outcome interpretation. Working tree left clean and all scratch dirs removed.

Evidence: Fleet view before/after, side by side (the operator-visible verdict flip)

Fleet view "Current" column, same four crews, same fake axi output. dev-5190 / dev-5441 : outcome=passed, pr,skipped ci,skipped, pr: "" (the real incident) auctic-dompdf2-lane-... : outcome=checks-passed, pr,completed ci,skipped, real PR URL auctic-genuine-pass : outcome=passed, pr,completed ci,completed (negative control) CREW BEFORE (2cf0283) AFTER (49a9f8f) ------------------------------ ---------------------- ---------------------- dev-5190 done / run-step failed / run-step dev-5441 done / run-step failed / run-step auctic-dompdf2-lane-stranded done / run-step failed / run-step auctic-genuine-pass done / run-step done / run-step Detail line for dev-5190 (the run with no PR at all): BEFORE: state: done · source: run-step · run passed: PR merged/closed AFTER : state: failed · source: run-step · run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?) Detail line for the ci-only skip (pr step completed, PR URL exists): BEFORE: state: done · source: run-step · checks green: PR ready for review AFTER : state: failed · source: run-step · run reported checks-passed but skipped delivery step(s) ci: no CI check was observed, do not trust the pass (daemon gh auth?)

Fleet view "Current" column, same four crews, same fake axi output.
dev-5190 / dev-5441      : outcome=passed, pr,skipped ci,skipped, pr: ""  (the real incident)
auctic-dompdf2-lane-...  : outcome=checks-passed, pr,completed ci,skipped, real PR URL
auctic-genuine-pass      : outcome=passed, pr,completed ci,completed     (negative control)

CREW                           BEFORE (2cf0283)       AFTER (49a9f8f)
------------------------------ ---------------------- ----------------------
dev-5190                       done / run-step        failed / run-step
dev-5441                       done / run-step        failed / run-step
auctic-dompdf2-lane-stranded   done / run-step        failed / run-step
auctic-genuine-pass            done / run-step        done / run-step

Detail line for dev-5190 (the run with no PR at all):
  BEFORE: state: done · source: run-step · run passed: PR merged/closed
  AFTER : state: failed · source: run-step · run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)

Detail line for the ci-only skip (pr step completed, PR URL exists):
  BEFORE: state: done · source: run-step · checks green: PR ready for review
  AFTER : state: failed · source: run-step · run reported checks-passed but skipped delivery step(s) ci: no CI check was observed, do not trust the pass (daemon gh auth?)
Evidence: BEFORE - full CLI transcript at base commit 2cf0283 (bug reproduced)
===============================================================
 BEFORE - base commit 2cf0283 (bin/fm-crew-state.sh unguarded)
 bin under test: /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-base-JBC43B/bin
===============================================================

--- what the pipeline reported for crew dev-5190 -------------
run:
  id: "01KZBCA6DEHQC1404F34QJE0CC"
  branch: fm/dev-5190
  status: completed
  head: "a99f22a1adb71601d140c7ca2cd87213afb6d18a"
  pr: ""
  findings: none
  steps[9]{step,status,findings,duration_ms}:
    intent,completed,0,0
    rebase,completed,0,1820
    review,completed,1,199827
    test,completed,0,605653
    document,completed,0,265219
    lint,completed,1,12
    push,completed,0,4551
    pr,skipped,0,26
    ci,skipped,0,28
outcome: passed

--- $ fm-crew-state.sh <id>  (per-crew operator read) --------

$ fm-crew-state.sh dev-5190
state: done · source: run-step · run passed: PR merged/closed

$ fm-crew-state.sh dev-5441
state: done · source: run-step · run passed: PR merged/closed

$ fm-crew-state.sh auctic-dompdf2-lane-stranded
state: done · source: run-step · checks green: PR ready for review

$ fm-crew-state.sh auctic-genuine-pass
state: done · source: run-step · run passed: PR merged/closed

--- $ fm-fleet-view.sh  (the human fleet table) --------------

## Under Way
| ID | Current | Kind | Repo/Project | Backend | Endpoint | Artifact | Path | Watch / return channel |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| auctic-dompdf2-lane-stranded | done / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-1SanSw/home/projects/auctic-dompdf2-lane-stranded-worktree | bin/fm-peek.sh fm-auctic-dompdf2-lane-stranded |
| auctic-genuine-pass | done / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-1SanSw/home/projects/auctic-genuine-pass-worktree | bin/fm-peek.sh fm-auctic-genuine-pass |
| dev-5190 | done / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-1SanSw/home/projects/dev-5190-worktree | bin/fm-peek.sh fm-dev-5190 |
| dev-5441 | done / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-1SanSw/home/projects/dev-5441-worktree | bin/fm-peek.sh fm-dev-5441 |


--- snapshot JSON current_state (what the view renders from) -

auctic-dompdf2-lane-stranded: done / run-step
    detail: checks green: PR ready for review
auctic-genuine-pass: done / run-step
    detail: run passed: PR merged/closed
dev-5190: done / run-step
    detail: run passed: PR merged/closed
dev-5441: done / run-step
    detail: run passed: PR merged/closed
Evidence: AFTER - full CLI transcript with the fix (fm-crew-state, fleet view, snapshot JSON)
===============================================================
 AFTER - fix 49a9f8f (skipped-delivery guard active)
 bin under test: /Users/ivannovak/.no-mistakes/worktrees/e7be5960b363/01KZBGX63YWTPZPY3KQHRMQRTW/bin
===============================================================

--- what the pipeline reported for crew dev-5190 -------------
run:
  id: "01KZBCA6DEHQC1404F34QJE0CC"
  branch: fm/dev-5190
  status: completed
  head: "230bbcc2ee7c4e7e966354c8f8279dae4322bb25"
  pr: ""
  findings: none
  steps[9]{step,status,findings,duration_ms}:
    intent,completed,0,0
    rebase,completed,0,1820
    review,completed,1,199827
    test,completed,0,605653
    document,completed,0,265219
    lint,completed,1,12
    push,completed,0,4551
    pr,skipped,0,26
    ci,skipped,0,28
outcome: passed

--- $ fm-crew-state.sh <id>  (per-crew operator read) --------

$ fm-crew-state.sh dev-5190
state: failed · source: run-step · run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)

$ fm-crew-state.sh dev-5441
state: failed · source: run-step · run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)

$ fm-crew-state.sh auctic-dompdf2-lane-stranded
state: failed · source: run-step · run reported checks-passed but skipped delivery step(s) ci: no CI check was observed, do not trust the pass (daemon gh auth?)

$ fm-crew-state.sh auctic-genuine-pass
state: done · source: run-step · run passed: PR merged/closed

--- $ fm-fleet-view.sh  (the human fleet table) --------------

## Under Way
| ID | Current | Kind | Repo/Project | Backend | Endpoint | Artifact | Path | Watch / return channel |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| auctic-dompdf2-lane-stranded | failed / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-OwEnBI/home/projects/auctic-dompdf2-lane-stranded-worktree | bin/fm-peek.sh fm-auctic-dompdf2-lane-stranded |
| auctic-genuine-pass | done / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-OwEnBI/home/projects/auctic-genuine-pass-worktree | bin/fm-peek.sh fm-auctic-genuine-pass |
| dev-5190 | failed / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-OwEnBI/home/projects/dev-5190-worktree | bin/fm-peek.sh fm-dev-5190 |
| dev-5441 | failed / run-step | ship | auctic-core | tmux | present | - | /var/folders/pq/43bb80gj31x7009tmpvfjcy40000gn/T//fm-e2e-OwEnBI/home/projects/dev-5441-worktree | bin/fm-peek.sh fm-dev-5441 |


--- snapshot JSON current_state (what the view renders from) -

auctic-dompdf2-lane-stranded: failed / run-step
    detail: run reported checks-passed but skipped delivery step(s) ci: no CI check was observed, do not trust the pass (daemon gh auth?)
auctic-genuine-pass: done / run-step
    detail: run passed: PR merged/closed
dev-5190: failed / run-step
    detail: run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)
dev-5441: failed / run-step
    detail: run reported passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)
Evidence: Instrument verification - each new guard and control watched fail red under mutation

===== MUTATION 1 - guard removed entirely (bin/fm-crew-state.sh reverted to base 2cf0283) ===== not ok - passed with skipped pr/ci -> failed (missing: 'state: failed') --- output --- state: done · source: run-step · run passed: PR merged/closed ===== MUTATION 2 - match pattern sabotaged: 'ci' dropped from the (pr|ci) alternation ===== not ok - both steps skipped -> detail names both missing pieces of evidence --- output --- state: failed · source: run-step · run reported passed but skipped delivery step(s) pr: no pull request was opened, do not trust the pass (daemon gh auth?) ===== MUTATION 3 - coarse runs-list 'completed' arm restored to done ===== not ok - coarse completed row -> unknown, not a certified pass (missing: 'state: unknown') --- output --- state: done · source: run-step · run completed ===== MUTATION 4 - guard widened to fire on completed rows too (negative controls must catch it) ===== not ok - must not deny a PR whose step completed and whose URL exists (unexpected: 'no pull request was opened') --- output --- state: failed · source: run-step · run reported checks-passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)

Instrument verification: each new guard/control was watched fail red.
Test file: tests/fm-crew-state.test.sh, run against a mutated copy of bin/.
The suite passes unmutated (see targeted-suite run); below each mutation
shows the first assertion that goes red and the wrong output it caught.

===== MUTATION 1 - guard removed entirely (bin/fm-crew-state.sh reverted to base 2cf0283) =====
not ok - passed with skipped pr/ci -> failed (missing: 'state: failed')
--- output ---
state: done · source: run-step · run passed: PR merged/closed

===== MUTATION 2 - match pattern sabotaged: 'ci' dropped from the (pr|ci) alternation =====
not ok - both steps skipped -> detail names both missing pieces of evidence (missing: 'no pull request was opened and no CI check was observed')
--- output ---
state: failed · source: run-step · run reported passed but skipped delivery step(s) pr: no pull request was opened, do not trust the pass (daemon gh auth?)

===== MUTATION 3 - coarse runs-list 'completed' arm restored to done =====
not ok - coarse completed row -> unknown, not a certified pass (missing: 'state: unknown')
--- output ---
state: done · source: run-step · run completed

===== MUTATION 4 - guard widened to fire on completed rows too (negative controls must catch it) =====
not ok - must not deny a PR whose step completed and whose URL exists (unexpected: 'no pull request was opened')
--- output ---
state: failed · source: run-step · run reported checks-passed but skipped delivery step(s) pr/ci: no pull request was opened and no CI check was observed, do not trust the pass (daemon gh auth?)
Evidence: e2e harness used to produce the before/after transcripts (reproducible)
#!/usr/bin/env bash
# End-to-end evidence harness for fm/nm-pr-ci-steps-skip-silently.
#
# Stands up a throwaway firstmate home holding four ship crews whose fake
# `no-mistakes axi status` output mirrors the real 2026-08-05 incident, then
# runs the REAL operator-facing commands (bin/fm-crew-state.sh and
# bin/fm-fleet-view.sh) against it, once with the BASE bin/ and once with the
# fixed bin/, so the two transcripts sit side by side.
set -u

REPO=${1:?usage: e2e-harness.sh <repo-root> <out-dir> <bin-dir> <label>}
OUT=${2:?}
BIN=${3:?}
LABEL=${4:?}

WORK=$(mktemp -d "${TMPDIR:-/tmp}/fm-e2e-XXXXXX")
trap 'rm -rf "$WORK"' EXIT

HOME_DIR="$WORK/home"
mkdir -p "$HOME_DIR/state" "$HOME_DIR/data" "$HOME_DIR/projects" "$HOME_DIR/config"
FIXTURES="$WORK/fixtures"
mkdir -p "$FIXTURES"

export GIT_AUTHOR_NAME=fmtest GIT_AUTHOR_EMAIL=fmtest@example.invalid
export GIT_COMMITTER_NAME=fmtest GIT_COMMITTER_EMAIL=fmtest@example.invalid

make_crew() {  # <id> <branch>
  local id=$1 branch=$2 wt="$HOME_DIR/projects/$1-worktree"
  mkdir -p "$wt"
  git -C "$wt" init -q
  git -C "$wt" commit -q --allow-empty -m init
  git -C "$wt" checkout -q -b "$branch"
  {
    printf 'window=fm:fm-%s\n' "$id"
    printf 'worktree=%s\n' "$wt"
    printf 'project=auctic-core\n'
    printf 'kind=ship\n'
    printf 'harness=claude\n'
  } > "$HOME_DIR/state/$id.meta"
  git -C "$wt" rev-parse HEAD
}

# --- crew 1+2: the real incident shape - push completed, pr+ci SKIPPED, yet
# the pipeline still reports outcome=passed.
for id in dev-5190 dev-5441; do
  head=$(make_crew "$id" "fm/$id")
  cat > "$FIXTURES/$id.axi" <<EOF
run:
  id: "01KZBCA6DEHQC1404F34QJE0CC"
  branch: fm/$id
  status: completed
  head: "$head"
  pr: ""
  findings: none
  steps[9]{step,status,findings,duration_ms}:
    intent,completed,0,0
    rebase,completed,0,1820
    review,completed,1,199827
    test,completed,0,605653
    document,completed,0,265219
    lint,completed,1,12
    push,completed,0,4551
    pr,skipped,0,26
    ci,skipped,0,28
outcome: passed
EOF
done

# --- crew 3: only the ci step skipped; the pr step really completed and a real
# PR URL exists.
head=$(make_crew auctic-dompdf2-lane-stranded fm/auctic-dompdf2-lane-stranded)
cat > "$FIXTURES/auctic-dompdf2-lane-stranded.axi" <<EOF
run:
  id: "01KZBCA6DEHQC1404F34QJE0CD"
  branch: fm/auctic-dompdf2-lane-stranded
  status: completed
  head: "$head"
  pr: "https://github.com/auctic-software/auctic-core/pull/812"
  findings: none
  steps[9]{step,status,findings,duration_ms}:
    intent,completed,0,0
    rebase,completed,0,1500
    review,completed,0,120000
    test,completed,0,400000
    document,completed,0,90000
    lint,completed,0,900
    push,completed,0,3300
    pr,completed,0,4100
    ci,skipped,0,31
outcome: checks-passed
EOF

# --- crew 4 (negative control): a genuinely delivered pass - pr and ci both
# completed. This one must keep reading done, with its existing wording.
head=$(make_crew auctic-genuine-pass fm/auctic-genuine-pass)
cat > "$FIXTURES/auctic-genuine-pass.axi" <<EOF
run:
  id: "01KZBCA6DEHQC1404F34QJE0CE"
  branch: fm/auctic-genuine-pass
  status: completed
  head: "$head"
  pr: "https://github.com/auctic-software/auctic-core/pull/813"
  findings: none
  steps[9]{step,status,findings,duration_ms}:
    intent,completed,0,0
    rebase,completed,0,1500
    review,completed,0,120000
    test,completed,0,400000
    document,completed,0,90000
    lint,completed,0,900
    push,completed,0,3300
    pr,completed,0,4100
    ci,completed,0,220000
outcome: passed
EOF

# --- fake CLI surface: a `no-mistakes` that answers with the fixture for
# whatever branch the caller cd'd into, plus an idle tmux/herdr endpoint.
FB="$WORK/fakebin"
mkdir -p "$FB"
cat > "$FB/no-mistakes" <<'SH'
#!/usr/bin/env bash
set -u
branch=$(git symbolic-ref --short HEAD 2>/dev/null || printf '')
fixture="$FM_E2E_FIXTURES/${branch#fm/}.axi"
case "${1:-}" in
  axi)
    shift
    case "${1:-}" in
      status) [ -f "$fixture" ] && cat "$fixture" ;;
      logs)   : ;;
    esac ;;
  runs) : ;;
esac
exit 0
SH
cat > "$FB/tmux" <<'SH'
#!/usr/bin/env bash
set -u
case "${1:-}" in
  list-windows)    sed -n 's/^window=[^:]*://p' "${FM_HOME:?}"/state/*.meta ;;
  display-message) printf '%%1\n' ;;
  capture-pane)    printf 'all quiet\n> \n' ;;
esac
exit 0
SH
chmod +x "$FB/no-mistakes" "$FB/tmux"

export FM_E2E_FIXTURES="$FIXTURES"
export FM_HOME="$HOME_DIR"
export FM_ROOT_OVERRIDE="$REPO"
export FM_STATE_OVERRIDE="$HOME_DIR/state"
export FM_DATA_OVERRIDE="$HOME_DIR/data"
export FM_CONFIG_OVERRIDE="$HOME_DIR/config"
export FM_PROJECTS_OVERRIDE="$HOME_DIR/projects"
export FM_GATE_REFUSE_BYPASS=1
export PATH="$FB:$PATH"

{
  printf '===============================================================\n'
  printf ' %s\n' "$LABEL"
  printf ' bin under test: %s\n' "$BIN"
  printf '===============================================================\n\n'
  printf '%s\n' '--- what the pipeline reported for crew dev-5190 -------------'
  cat "$FIXTURES/dev-5190.axi"
  printf '\n%s\n' '--- $ fm-crew-state.sh <id>  (per-crew operator read) --------'
  for id in dev-5190 dev-5441 auctic-dompdf2-lane-stranded auctic-genuine-pass; do
    printf '\n$ fm-crew-state.sh %s\n' "$id"
    "$BIN/fm-crew-state.sh" "$id" 2>&1
  done
  printf '\n%s\n\n' '--- $ fm-fleet-view.sh  (the human fleet table) --------------'
  "$BIN/fm-fleet-view.sh" 2>&1 | sed -n '/## Under Way/,/^$/p'
  printf '\n%s\n\n' '--- snapshot JSON current_state (what the view renders from) -'
  "$BIN/fm-fleet-snapshot.sh" --json 2>/dev/null \
    | jq -r '.tasks[] | "\(.id): \(.current_state.state) / \(.current_state.source)\n    detail: \(.current_state.detail)"'
} > "$OUT" 2>&1

printf 'wrote %s\n' "$OUT"
- Outcome: ⚠️ 1 info across 1 run (15m0s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • ⚠️ bin/fm-crew-state.sh:452 - The intent claims a delivery-skipped run 'never' reads done, but the guard only covers the full axi-status TOON path. The coarse runs-list fallback still maps completed -> done ('run completed') with no delivery-step evidence: when bare axi status answers another crew's branch (the exact scenario exercised by test_cross_branch_attribution_via_runs_list and ..._picks_most_recent_row, which includes a completed row), a delivery-skipped run is attributed from the no-mistakes runs list as a plain completed row with matching short-sha and reports state: done · run completed, bypassing nm_skipped_delivery_steps entirely. The coarse row for such a run has no pr-url column (no PR ever existed), which is available evidence: nm_runs_status_for_branch already parses each row and could surface pr-url presence so the coarse completed mapping refuses done (or reports unknown pending full attribution) for a completed row without a PR URL. This is pre-existing sibling behavior, not introduced by the diff, and changing it alters coarse-path reporting semantics, so it needs the author's call rather than an auto-fix.
  • ℹ️ bin/fm-crew-state.sh:472 - The failure detail 'no PR/CI evidence exists, do not trust the pass' overstates the situation when only the ci step was skipped: in the run_checks_passed_ci_skipped fixture the pr step completed and a real PR URL exists (pr: https://github.com/o/r/pull/3), so only CI evidence is missing. The wording could steer an operator away from inspecting a PR that does exist. Consider naming only the actually-missing evidence (e.g. derive the message from which steps were skipped).

🔧 Fix: close coarse runs-list done bypass, derive missing-evidence wording
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 info
  • ℹ️ tests/fm-teardown.test.sh:1568 - tests/fm-teardown.test.sh fails at herdr-preflight-missing-adapter: the retryable pre-return refusal was not explained visibly. This is NOT a regression from this change: I re-ran the same suite against a copy of the tree with bin/fm-crew-state.sh reverted to base 2cf0283 and it fails with the identical assertion. The test exercises herdr backend preflight refusal (a missing bin/backends/herdr.sh adapter), which is unrelated to run-outcome interpretation. Noted so it is not mistaken for fallout from the skipped-delivery guard; remote CI owns whether it needs attention.
  • bash tests/fm-crew-state.test.sh - full colocated suite including the four new skipped-delivery fixtures and the two new coarse runs-list cases (all green)
  • End-to-end product run: stood up a throwaway FM_HOME with four ship crews (dev-5190, dev-5441, auctic-dompdf2-lane-stranded, auctic-genuine-pass) and a fake no-mistakes serving the real incident's axi output, then ran bin/fm-crew-state.sh &lt;id&gt;, bin/fm-fleet-snapshot.sh --json, and bin/fm-fleet-view.sh against BOTH the base-commit bin/ and the fixed bin/ (harness: e2e-harness.sh in the evidence dir)
  • Instrument verification / mutation 1: git show 2cf0283:bin/fm-crew-state.sh over a copied tree, then bash tests/fm-crew-state.test.sh - passed with skipped pr/ci -&gt; failed goes red, printing the exact bug output state: done ... run passed: PR merged/closed
  • Instrument verification / mutation 2: sabotaged the match pattern by dropping ci from (pr|ci) - the derived-wording assertion both steps skipped -&gt; detail names both missing pieces of evidence goes red
  • Instrument verification / mutation 3: restored the coarse runs-list arm to completed) RUN_STATE=&#34;done&#34; - coarse completed row -&gt; unknown, not a certified pass goes red
  • Instrument verification / mutation 4: widened the guard to &#34;?(skipped|completed)&#34;? so it fires on completed rows - the negative control must not deny a PR whose step completed and whose URL exists goes red, proving the controls are not inert
  • bash tests/fm-fleet-snapshot-view.test.sh - the renderer that consumes fm-crew-state (green)
  • bash tests/fm-watch-triage.test.sh (green)
  • bash tests/fm-wake-queue.test.sh - exercises crew_is_provably_working over the real helper (green)
  • bash tests/fm-teardown.test.sh - one failure, re-run against base-commit fm-crew-state.sh to confirm it pre-exists this change
  • Spot-check of the intent's single-owner claim: grep -rn outcome bin/ - only bin/fm-teardown.sh also reads outcome, and only to tell terminal from non-terminal after an abort (task_status_is_terminal_run, bin/fm-teardown.sh:1180), deriving no pass verdict, so no second bypass path exists
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

no-mistakes v1.41.2 reaches outcome=passed with its pr and ci steps
silently skipped when the pipeline daemon's gh is unauthenticated
("skipping PR creation: gh CLI is not authenticated" in the step log),
so a run could report the pipeline's strongest verdict having never
opened a PR or observed a single CI check, and fm-crew-state.sh then
rendered it as "run passed: PR merged/closed".

Root cause of the missing credential, established empirically: the
daemon runs as a launchd LaunchAgent (installed 2026-07-31 by the
v1.41.2 update) and gh's token lives only in the macOS login keychain
(hosts.yml carries no token). The environment is not the boundary -
gh auth status succeeds under env -i HOME PATH with the daemon's exact
environment - and the same daemon process created PRs Aug 1-4 before
failing consistently from Aug 5 18:55 with no reboot, no gh upgrade,
and no keychain item change, so the daemon's detached security session
lost access to the login keychain at runtime. Fixing the daemon itself
is upstream (closed-source binary); this change makes firstmate stop
believing the false verdict.

fm-crew-state.sh now checks the axi status steps[] table whenever a
run reads passed, checks-passed, or bare completed: any skipped pr or
ci row reports state failed with the skipped steps named, never done,
so the fleet view cannot claim a merged PR that never existed
(companion of the separately filed fm-crew-state-false-merged-claim).

Tests: new fixtures mirror the real skipped-delivery output verified
against run 01KZBCA6DEHQC1404F34QJE0CC; watched red against the
unguarded code, green after, and red again with the guard's match
pattern sabotaged; a negative control keeps a genuinely delivered
pass reporting done.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant