Skip to content

fix(bin): sync upstream wake-queue, stat, and spawn fixes - #51

Merged
zeeshaanahmad merged 6 commits into
mainfrom
fm/upstream-batch-17-to-tip
Sep 8, 2026
Merged

zeeshaanahmad merged 6 commits into
mainfrom
fm/upstream-batch-17-to-tip

Conversation

@zeeshaanahmad

Copy link
Copy Markdown
Owner

Intent

Captain's standing policy for this fork (2026-09-05, verbatim): "the main goal for firstmate is to become sync with upstream. once we reach that state, we avoid introducing more changes and stay aligned with the upstream. until then you can keep adding work that helps aligning with the upstream easier and reaches the intended state quickly."

Captain's conflict rule (2026-09-05, verbatim): "if there is something upstream and our code both worked on and fixed but approaches differ, take the upstream change, however, if our change is better than upstream, file a PR. for other items, take the upstream changes."

Captain's decision on 2026-09-07 (verbatim): "park whatever diverges from upstream. our goal was to sync with upstream for firstmate. if thats achieved and new updates can easily be pulled from upstream, thats it. no further work on firstmate." Sync batches are the only firstmate work; no fork-side improvements, no new upstream PR candidates unless a measured defect forces one.

The ask this task serves: upstream sync batch 17 - bring the fork's origin/main (now c442cd0: batch 16 landed as #50, waypoint 0b9f518) up to upstream's current tip, waypoint 72bfdd0 ("fix(spawn): carry attribution-off policy in every claude launch (kunchenguid#3945)"). Five upstream commits in range 0b9f518..72bfdd0, 43 files:

What Changed

  • Wake-queue stall detection is refactored to gate alerts on real no-progress conditions (progress tracking plus active-turn gating), and every counted wake-queue row is now made presentable or retired instead of silently dropped; touches fm-watch.sh, fm-wake-lib.sh, fm-wake-drain.sh, fm-guard.sh, and fm-wake-grant.sh, with fm-wake-queue.test.sh gaining substantial new coverage.
  • Darwin BSD-format stat invocations across 24 bin/ scripts now call /usr/bin/stat explicitly so a GNU coreutils stat earlier on PATH can no longer shadow them; adds tests/fm-stat-shadowing.test.sh and small related hardening in the backlog-atomicity, pr-check-security, and teardown tests.
  • fm-spawn.sh now carries the attribution-off policy into every claude launch path, with matching updates to fm-spawn-dispatch-profile, fm-control-relaunch, fm-secondmate-harness, and fm-backend-orca tests; the calm-mode Pi export-DOM render test is hardened with recorded Pi 0.85.1 evidence.

Risk Assessment

✅ Low: placeholder_pending_agents

Testing

Targeted validation covered 2 of the batch's 5 upstream commits with confirmed-passing evidence (Darwin stat fix via fm-stat-shadowing.test.sh on real hardware; wake-queue stall/presentability logic via fm-wake-queue.test.sh after clearing a one-off real-time-budget flake with 3 clean reruns); the remaining commits (Pi-calm DOM-render hardening and fm-spawn attribution-off propagation) were queued for their targeted test files but that background run had not finished when this phase had to conclude, so no artifacts or pass/fail signal exist for those yet. No reviewer-visible UI artifacts were produced or applicable — this batch is backend shell-script and CLI/test-infrastructure behavior (queue processing, stat syscalls, spawn flag propagation, and a test-only DOM-render harness), not an end-user rendered surface.

  • Outcome: ⚠️ 2 issues (1 warning, 1 info) across 1 run (13m12s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

⏭️ **Rebase** - skipped

Step was skipped.

✅ **Review** - passed

✅ No issues found.

⚠️ **Test** - 2 issues (1 warning, 1 info)
  • ℹ️ tests/fm-wake-queue.test.sh:294 - tests/fm-wake-queue.test.sh::test_secondmate_foreign_queue_stall_tracks_progress_and_alerts_once (new in this batch, from ffd2c89) failed once with "a foreign queue with no progress did not alert: checkpoint: no actionable wake within 1s", then passed cleanly on 3 immediate reruns (exit=0 each, ~135-144s). Root cause: the test invokes bin/fm-watch-checkpoint.sh --seconds 1, which enforces a real 1-second wall-clock timeout (via timeout/perl-alarm) around one fm-watch.sh poll cycle; on this heavily-loaded dev host (many concurrent agents/hooks) that single cycle can occasionally miss the 1s budget before the process is killed. This is upstream's own merged test executed unmodified, not a fork-authored change, and per the standing captain policy (take upstream as-is / no fork-side changes) it should not be altered here. Flagging as an informational/known-flaky note rather than a merge defect.
  • ⚠️ Could not finish confirming the remaining batch-17 targeted tests before this phase's turn budget ran out. I launched bash bin/fm-test-run.sh tests/fm-calm-pi-extension.test.sh tests/fm-spawn-dispatch-profile.test.sh tests/fm-control-relaunch.test.sh tests/fm-secondmate-harness.test.sh tests/fm-backend-orca.test.sh tests/fm-backlog-atomicity.test.sh tests/fm-pr-check-security.test.sh tests/fm-teardown.test.sh in the background; it was still running after several minutes (confirmed via ps: real tmux session, a live pi --approve agent process, and multiple headless Chrome renderer/GPU processes doing an actual DOM export/render for the calm-mode extension). That one E2E test (fm-calm-pi-extension.test.sh, from 36fd955) is inherently slow on this host since Pi 0.85.1 and Chrome are both actually installed here, so it exercises the real render path rather than skipping. As a result I have no pass/fail confirmation yet for: the Pi-calm export-DOM render hardening (36fd955), or the fm-spawn attribution-off propagation tests (72bfdd0: fm-spawn-dispatch-profile, fm-control-relaunch, fm-secondmate-harness, fm-backend-orca), or the small Darwin-stat-adjacent additions in fm-backlog-atomicity/fm-pr-check-security/fm-teardown. These are fast, non-E2E scripts apart from the calm test, so a rerun of just this command set should resolve quickly once given more wall-clock time; recommend rerunning it to completion before merging.
  • bash bin/fm-test-run.sh tests/fm-stat-shadowing.test.sh (Darwin-only, ran on real Darwin host — passed, confirming 98b37d40's /usr/bin/stat fix)
  • bash bin/fm-test-run.sh tests/fm-wake-queue.test.sh (first run: 1 failure in a new real-time-budget test; reran 3x consecutively, all exit=0, confirming flakiness rather than a merge defect)
  • bash bin/fm-test-run.sh tests/fm-calm-pi-extension.test.sh tests/fm-spawn-dispatch-profile.test.sh tests/fm-control-relaunch.test.sh tests/fm-secondmate-harness.test.sh tests/fm-backend-orca.test.sh tests/fm-backlog-atomicity.test.sh tests/fm-pr-check-security.test.sh tests/fm-teardown.test.sh (launched in background; did not complete before this phase concluded — the calm-pi-extension E2E spawns real tmux/pi/Chrome and is slow on this host)
⚠️ **Document** - 1 info
  • ℹ️ docs/fm-test-portable-shards.md:70 - This maintainer-verification doc's script counts/timings (152-script lane, 10 unhinted, 5x13.69min shards) were refreshed by upstream commit 98b37d4 to match upstream's own test suite, but the fork's actual current tests/*.test.sh set is larger (verified: bin/fm-test-run.sh --list --lane portable-serial returns 165 scripts today, per-shard 32/34/32/34/33, vs the doc's 29/30/31/31/31=152). This drift predates batch 17 (confirmed the same gap already existed at base commit c442cd0, where the doc said 147 but the actual count was 164), so it is not something this change made stale, and I left it untouched per scope discipline. A faithful refresh needs real dated CI timing artifacts (per the doc's own generation method), which are not available locally, so fixing it here would mean hand-computing numbers this maintainer-verification doc is supposed to source from actual CI runs. Flagging as a pre-existing fork/upstream test-suite-size divergence worth a dedicated follow-up refresh (with real CI artifacts) rather than a local approximation.
✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

cisrd and others added 6 commits September 7, 2026 12:41
…gress (kunchenguid#3943)

* fix(watch): detect stalled secondmate queue progress

* no-mistakes(review): gate secondmate stall on active turns and progress episodes

* no-mistakes(document): align secondmate wake-stall docs with progress-episode detector

* no-mistakes(document): clarify active-turn gate in wake-stall config docs

* no-mistakes(ci): Fixed the one real defect behind the failing checks. ROOT CAUSE (Greptile P1, real code defect in this PR): `secondmate_wake_stall_tick` in bin/fm-watch.sh reset the no-progress timer only when the oldest actionable queue sequence INCREASED (`[ "$seq" -gt "$observed_seq" ]`). When a secondmate is retired and reprovisioned under the same task ID, its fresh home's queue sequence restarts BELOW the recorded position, so the comparison is false, no reset happens, and the new queue inherits the retired generation's already-expired idle interval — emitting a false `secondmate wake-loop stalled` on its very first observation. That is precisely the false-alarm class the user intent requires this PR to remove. FIX (smallest, removal-first): bin/fm-watch.sh:749 now resets when the drain position MOVES AT ALL (`-ne` instead of `-gt`). Draining moves it up, reprovisioning moves it down; neither is a continued no-progress episode. The asymmetric `-gt` branch is removed rather than special-cased or hardened. Updated the function header comment plus the two doc sentences in docs/architecture.md and docs/configuration.md that stated the old advance-only semantics. REGRESSION TEST: added `test_secondmate_reprovisioned_queue_starts_a_fresh_interval` to tests/fm-wake-queue.test.sh (registered in the invocation list). It drives the real watcher through retired generation (seq 9) -> reprovision (seq 3, later clock) -> freeze, asserting observable wake-queue output, no source-text inspection. VERIFICATION: - Fails before / passes after: with the fix reverted the suite aborts on `not ok - a reprovisioned queue generation inherited the retired generation's idle interval and alerted`; with the fix it passes, and its third leg confirms the restarted generation still escalates on a genuine freeze (row=3 idle=2s), so the fix does not merely mute the alarm. - `bash tests/fm-wake-queue.test.sh`: exit 0, 38/38 pass, all five secondmate cases green. - `bin/fm-lint.sh`: clean (ShellCheck 0.11.0, actionlint 1.7.12). CHECKS NOT CAUSED BY THE CODE: the CI and "Require no-mistakes" runs (34152740610, 34152740604) both ended with conclusion `action_required` — workflow approval pending, not a test/build failure. Separately, `bin/fm-test-run.sh --check-coverage` exits 1 in this environment, but I confirmed by stashing my changes that it fails identically on the unmodified base tree (locale-related `comm: input is not in sorted order`); it is pre-existing and this change adds no new test file for the partition to account for. Changes are left uncommitted in the worktree

* no-mistakes(ci): Fixed the one real code defect behind the failing checks. ROOT CAUSE (Greptile P1, second round, on the head commit e1304e6): `secondmate_wake_stall_tick` in bin/fm-watch.sh identified the queue's drain position by the sequence number ALONE. The previous round changed the comparison from `-gt` to `-ne`, which handles a reprovisioned queue that restarts BELOW the recorded position, but not one that restarts ON it. A mate retired and reprovisioned under the same task id gets a fresh home whose wake-queue sequence counter restarts at 1 — and the retained parent progress marker very plausibly holds a low sequence too (a queue frozen on its first row records seq 1). Equal sequence ⇒ no reset ⇒ the brand-new queue inherits the retired generation's long-expired idle interval and emits a false `secondmate wake-loop stalled` on its very first observation. That is exactly the false-alarm class this PR exists to remove. FIX (smallest, removal-first): the file already defines the identity of a queue row once, as `row_key="$epoch-$seq"` (used for stall receipts, the stall marker, and the notify key). The progress marker's separate, weaker seq-only identity is removed: `row_key` is now computed once right after the row is parsed, stored in the progress marker, and compared with `!=`. Across generations the epoch differs (the new generation's rows are appended later), so no sequence collision can carry a stale interval; within a generation the key is stable exactly while the position does not move. bin/fm-wake-lib.sh's `fm_wake_secondmate_progress_marker_write` now takes `<oldest-row-key>` and validates it the same way the two neighbouring row-key writers do. Updated the function header comment and the two doc sentences (docs/architecture.md, docs/configuration.md) that described the old sequence-only semantics. REGRESSION TEST: `test_secondmate_reprovisioned_queue_starts_a_fresh_interval` in tests/fm-wake-queue.test.sh now drives the reported case — the reprovisioned generation restarts on the SAME sequence 9 (epoch 200) that the retired generation recorded (epoch 100), at a later clock — and asserts observable watcher output only. Its third leg still confirms the restarted generation escalates on a genuine freeze (row=9 idle=2s), so the fix does not merely mute the alarm. Three seeded progress markers in the symlink, crash-window and prefix-receipt tests were updated to the epoch-sequence form. VERIFICATION: - Fails before / passes after: with bin/fm-watch.sh and bin/fm-wake-lib.sh reverted to HEAD and the new test in place, the suite aborts on `not ok - a reprovisioned queue generation inherited the retired generation's idle interval and alerted` (exit 1); with the fix, `bash tests/fm-wake-queue.test.sh` exits 0 with 38/38 pass, all six secondmate cases green. - `bin/fm-lint.sh`: clean (ShellCheck 0.11.0, actionlint 1.7.12). - I also started `bin/fm-test-run.sh tests/fm-watch-checkpoint.test.sh tests/fm-watch-triage.test.sh tests/fm-watch-recovery-loop.test.sh` as a blast-radius check; it was still running when this phase had to return, so its result is not included. No other suite references the stall detector or the progress marker (grep over tests/ for `wake-loop stall|SECONDMATE_WAKE_STALL|secondmate-wake-progress` matches only fm-wake-queue.test.sh), and the changed lib function has exactly one caller. CHECKS NOT CAUSED BY THE CODE: the CI and "Require no-mistakes" runs on the head commit (34154091191, 34154091236, 34154091945) all ended with conclusion `action_required` — pending workflow approval, not a test/build failure. `bin/fm-test-run.sh --check-coverage` still exits 1 in this environment for the pre-existing locale reason recorded in the previous phase (`comm: input is not in sorted order` on the unmodified base tree); this change adds no new test file. Changes are left uncommitted in the worktree: bin/fm-watch.sh, bin/fm-wake-lib.sh, docs/architecture.md, docs/configuration.md, tests/fm-wake-queue.test.sh

---------

Co-authored-by: Alex William <awilliam@v2202608403614505120.powersrv.de>
…idence (kunchenguid#3952)

* fix(tests): make the Calm export-DOM render step retry and report

The Calm suite's rendered-export-DOM assertion started breaking CI with a
bare "could not render calm-mode HTML export DOM", which read like a Pi
0.85 rendering change. It is not one. Calm's rendered rows are identical
across Pi 0.84.4, 0.85.0, and 0.85.1, and the CI break appeared in exactly
one of the thirteen most recent runs, all on the same Pi 0.85.1, with the
main runs immediately before and after it passing.

What actually failed is headless Chrome's start-up. The render step made a
single unattended attempt and discarded both Chrome's stderr and its exit
status, so the log held nothing to tell a Chrome crash apart from a real
change in Pi's export shape.

Rendering is a vendor-tool step; the DOM assertions that follow it are what
protect the Calm conversation boundary. So the step now retries a bounded
number of Chrome start-ups on a fresh profile, drops Chrome's background
network and /dev/shm dependencies without changing what a local file renders
to, and, when every attempt fails, reports the Chrome binary, its version,
the installed Pi version, each attempt's exit status, and Chrome's own
stderr. test_export_dom_render_guard pins that with real processes and no
browser: one clean render, one that only succeeds after a start-up failure,
and one that never renders and must report enough to diagnose itself.

The verification record adds the 0.85.1 evidence this contract is now
pinned to, the cross-version comparison run through isolated installs, and
the Pi 0.85.0 packaging gap - its dist/experimental/server.js statically
imports @earendil-works/pi-server, which 0.85.0 does not declare - that
made the contract look version-sensitive in the first place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7rr2DHf51MjMvy7sMRauo

* no-mistakes(review): docs: attribute Pi 0.85 calm contract adaptation to renderer change

* no-mistakes(review): tests: drop inert chrome flags, report render timeouts

* no-mistakes(document): docs: fix stale Pi version facts and doc-lint link

---------

Co-authored-by: Alex William <awilliam@v2202608403614505120.powersrv.de>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…unchenguid#3950)

* fix(bin): make every counted wake queue row presentable or retired

A wake row could be counted as queued while no drain would ever present
it, leaving the operator told to "drain them before anything else" by a
command that printed nothing and offered no acknowledgement.

Two independent paths produced that state.
A row reserved by a live supervision-branch grant is excluded from a main
drain by design, but fm-guard.sh counted the whole queue, so main was
warned about rows only the branch could present, on every guarded command
for as long as the grant was held.
A row that lost its five appended fields or its numeric sequence can never
be claimed, presented, or named by an --ack-through cutoff, yet it still
counted as queued, wedging the queue permanently.

The guard now counts only the rows the calling actor can itself present or
retire, and a main drain retires unusable rows under the queue lock,
reporting them in bounded escaped form before removal so the evidence
survives for the separate row-generating defects. A retirement failure is
reported loudly and never suppresses unrelated consumable work. A main
drain whose remaining rows are all branch-held says so in one bounded line
instead of exiting silently. Grant row-list and owner-record reads move
into fm-wake-lib.sh so the drain, the grant publisher, and the guard share
one implementation.

Ownership is unchanged: a branch drain still touches nothing outside its
grant and never retires a row, and main still cannot present or acknowledge
an active grant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GghGvsa4JDB1E5FuznX2i1

* no-mistakes(test): keep SIGTERM-safe arithmetic in wake queue retirement pass

* no-mistakes(review): add guard advisory for branch-held wake rows

* no-mistakes(document): document per-actor wake counting and unusable-row retirement

* no-mistakes(ci): Addressed the Greptile P1 on bin/fm-wake-lib.sh:1840 ("Unreadable queue suppresses alarms"). Root cause: fm_wake_actor_pending_count inferred "the queue could not be counted" only from awk's printed output (`case "$count" in ''|*[!0-9]*) count=1`). That relies on awk aborting before its END rule when the input cannot be opened. An awk that reaches END after a failed open prints `0`, which the fallback accepts as a genuine count; both actor counts then read zero and bin/fm-guard.sh emits neither the queued-wake warning nor the branch-held advisory for a queue nobody proved empty. Fix (bin/fm-wake-lib.sh:1828,1835): both counting awk invocations now set `count=''` on a non-zero awk exit status, so the existing "cannot be counted => report a pending row" fallback is driven by awk's exit status instead of an implementation-defined detail of what it printed. No new code path or behavior; the pre-existing fallback just becomes unconditional. Comment updated to state why. Regression test (tests/fm-wake-queue.test.sh: test_uncountable_queue_still_raises_the_pending_alarm, registered in the run list): runs the real bin/fm-guard.sh against a non-empty, unreadable queue with a PATH-injected awk emulating an END-running implementation (prints 0, exits 2; execs the real awk otherwise) and asserts "queued wakes pending" is still emitted; disconfirming half asserts the same fake awk over a readable, provably empty queue stays silent. Fails on the pre-fix library ("not ok - a queue that could not be counted silenced the queued-wake alarm"), passes after. Verified locally: bin/fm-test-run.sh tests/fm-wake-queue.test.sh -> 0 failed; tests/fm-guard-stale-banner.test.sh + tests/fm-watcher-lock.test.sh -> 0 failed; bin/fm-lint.sh (ShellCheck 0.11.0 + actionlint 1.7.12) clean. Caveat reported honestly: on the awks available/known here (mawk locally, plus gawk and BWK/macOS awk, all of which treat an unopenable input as fatal and skip END) the alarm was not actually suppressed - I reproduced the unreadable-queue case and the warning fired. The change removes the code's dependence on that awk detail rather than repairing an outage observed on this platform. Both intent constraints still hold: every counted row remains presentable or retirable, and no alarm-suppressing path was added

---------

Co-authored-by: Alex William <awilliam@v2202608403614505120.powersrv.de>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* fix(bin): use /usr/bin/stat on Darwin to survive GNU stat shadowing

* fix(bin): extend /usr/bin/stat prefix to Darwin stat -f sites added on main

* test(bin): make fm-stat-shadowing skip visible on non-Darwin and isolate fm-watch state

* ci: re-trigger after Chrome headless timeout in calm HTML export test

* ci: re-trigger serial-5 after second Chrome headless timeout in calm HTML export test

* test(bin): skip PATH-based stat fault injection on Darwin where stat is /usr/bin/stat

* no-mistakes(document): Refresh stat and shard docs
…henguid#3945)

The captain's attribution policy (no Co-Authored-By trailer, no
Claude-Session link, no generated-with line) lives in Claude Code's `user`
settings scope. A spawned worker's settings sources are not guaranteed to
load that scope, so a launched worker could write attribution trailers into
its commits and PR bodies regardless of the captain's own configuration.

launch_template()'s claude case now carries the same policy
("attribution": {"commit": "", "pr": "", "sessionUrl": false}) directly in
its inline --settings JSON, so every claude launch keeps attribution off
independent of which settings scopes end up loaded. Tests assert the policy
on the rendered launch command for both a crewmate and a secondmate spawn.

Co-authored-by: NewAiCoder <170579485+NewAiCoder@users.noreply.github.com>
…system stat, claude attribution policy

Brings the fork's main up to upstream tip 72bfdd0
("fix(spawn): carry attribution-off policy in every claude launch (kunchenguid#3945)"),
five upstream commits over 0b9f518..72bfdd0, 43 files:

  ffd2c89  gate secondmate wake-loop stall alerts on real queue no-progress (kunchenguid#3943)
  36fd955  harden the calm export-DOM render step, record Pi 0.85.1 evidence (kunchenguid#3952)
  3af74fe  make every counted wake queue row presentable or retired (kunchenguid#3950)
  98b37d4  use system stat for Darwin BSD formats (kunchenguid#3305)
  72bfdd0  carry attribution-off policy in every claude launch (kunchenguid#3945)

Merged as one merge commit so 72bfdd0 stays in ancestry; never rebased,
squashed, or cherry-picked.

Conflicts (five files, all one overlap) resolved to upstream per the captain's
conflict rule (both sides fixed the same thing, approaches differ -> take
upstream):

  bin/fm-spawn.sh - the fork's PR 35 (a9980f4) and upstream kunchenguid#3945 both put the
  attribution-off policy into the per-launch --settings JSON. The two lines were
  semantically identical (same keys, same values, including sessionUrl:false);
  they differed only in JSON key order and in the explaining comment. Resolved
  to upstream's launch line and its comment verbatim. PR 35's own comment block
  above the line was also dropped: upstream's comment now owns that explanation,
  and keeping both would restate one contract twice. bin/fm-spawn.sh's claude
  launch line is now byte-identical to upstream.

  tests/fm-backend-orca.test.sh (1 hunk), tests/fm-secondmate-harness.test.sh
  (2), tests/fm-spawn-dispatch-profile.test.sh (3) - expected launch strings
  updated to upstream's key order. Every fork-only case in those files survives.

  tests/fm-control-relaunch.test.sh (3 hunks) - NOT an attribution conflict.
  Both sides fixed the same fixture flake differently: upstream raised the three
  publication-race wait ceilings from 200 to 500 ticks, while the fork's 9373abe
  replaced the literal with a named CONTROL_RACE_WAIT_TICKS=1000 tripwire.
  Resolved to upstream's literal 500 per the same rule. Upstream never touched
  the fourth site (the cwd race, still 200 upstream), so the fork's constant
  survives there; its comment is corrected because it no longer governs three
  fixtures. NOTE: this lowers those three ceilings from 1000 to 500 on this
  fork. Upstream's 500 is ~3.4x the 139-146 ticks the fork measured unloaded,
  so it is not obviously too tight, but it is untested under load here; the
  validation lane exercises it.

Surviving fork hunks in bin/fm-spawn.sh (git diff upstream/main, 13 hunks) all
belong to fork features upstream never touched, and none belong to PR 35's
approach: the --model/--effort "default" axis with the crew-dispatch
consultation backstop (header text, EFFORT validation, batch and single-spawn
checks, RELAUNCH_PRIOR_MODEL/EFFORT), and tmux_socket endpoint pinning
(RELAUNCH_TMUX_SOCKET, SPAWN_TMUX_SOCKET, the preserve_relaunch_meta key list,
and the meta write).

98b37d4 (system stat) splice check: for each of the 24 bin scripts upstream
rewrote, every line upstream added is present in the merged file (0 missing).
The same check over all 43 files in the range is also 0 missing.

Fork-only stat sites changed: NONE. The six fork-only scripts named as
candidates (bin/fm-liveness-lib.sh, bin/fm-static-guard-lib.sh,
bin/fm-test-env-lib.sh, bin/fm-ci-probe.sh, bin/fm-liveness-register.sh,
bin/fm-main-guard.sh) invoke stat nowhere - every apparent hit is a substring of
"state", "static", or "status". A sweep of every stat invocation in bin/ finds
no bare BSD-format `stat -f` call left anywhere; the two fallback-form sites
(bin/fm-test-run.sh, bin/fm-x-lib.sh:413) are byte-identical to upstream. So
upstream's rule needed no extension to fork-only code.

Fork fixes confirmed intact after the merge:
  bin/fm-wake-lib.sh "the guard is progress, not depth" (PR 47) = 1
  tests/fm-calm-pi-extension.test.sh "FIRSTMATE_OP_END: v1 watcher" = 1
    (survived upstream kunchenguid#3952's export-DOM rewrite; no re-apply needed)
  the watcher liveness deferral (PR 1, PR 15) and the bounded cleanup lock wait
  (PR 7) are both still present in bin/fm-watch.sh

tests/fm-claude-attribution.test.sh (fork-only, PR 35) needed no change: it
parses the --settings JSON and asserts the policy (attribution.commit == "",
attribution.pr == "", sessionUrl is False) rather than pinning bytes, so
upstream's key order satisfies it unmodified.

.github/workflows/ is identical to upstream (git diff 72bfdd0 is empty).
@zeeshaanahmad
zeeshaanahmad merged commit 1c741b9 into main Sep 8, 2026
14 checks passed
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.

4 participants