feat: merge the completed 30-commit upstream sync with local main - #11
Merged
Merged
Conversation
* Add instruction owners foundation * no-mistakes(document): Refresh project-management owner pointers
…kunchenguid#626) * docs: compress firstmate operating contract * docs: make delivery rigor single-owner PR B already removed personal and stacked review requirements, but it did not explicitly assign rigor to the selected delivery path or forbid risk-based manual clean gates. That gap still permitted the Hi Bit inversion. * no-mistakes(review): Honor configured merge authority across faster delivery paths * no-mistakes(document): Align docs with compressed operating contract
* Add durable captain decision holds * no-mistakes(review): Validate decision hold retries and origin paths * no-mistakes(review): Enforce durable decision lifecycle boundaries * no-mistakes(review): Harden decision display and partial retry recovery * no-mistakes(test): Update scout teardown fixtures for decision inventory * no-mistakes(document): Align decision lifecycle and scout teardown documentation * no-mistakes: apply CI fixes * no-mistakes(review): Reconcile terminal decision holds * no-mistakes(document): Align captain decision-hold documentation
* fix: harden PR check artifacts * fix: close PR check migration gaps * fix: close PR check retry gaps * fix: clarify migration outcomes and ESM boundary * fix: keep failed migrations authoritative * test: use inert PR validation fixtures * no-mistakes(review): Reserve noncanonical PR quarantine namespace * no-mistakes(review): Prevalidate final PR-check teardown artifacts * no-mistakes(review): Preserve X metadata and validate teardown IDs * no-mistakes(review): Initialize migration state before watcher exclusion * no-mistakes(review): Isolate failed poll migrations from bootstrap recovery * no-mistakes(review): Allow safe polling during incomplete private repairs * no-mistakes(review): Authenticate watcher checks at execution time * no-mistakes(review): Preserve custom checks with hash-bound registration * no-mistakes(review): Clean custom check snapshots on watcher signals * no-mistakes(review): Stop watcher checks promptly on signals * no-mistakes(review): Terminate watcher check groups before cleanup * no-mistakes(document): Correct stale X-mode watcher documentation * fix: drain returned watcher check groups * no-mistakes(review): Harden quarantine links and recover validated replacement polls * no-mistakes(review): Preserve X mode across shim version transitions * no-mistakes(review): Refresh legacy X shims before marker short-circuits * no-mistakes(document): Correct persisted PR-check artifact documentation * no-mistakes(document): Correct stale PR-check documentation * fix: bind PR poll repair provenance * no-mistakes(review): Enforce single-link ownership for custom check artifacts * no-mistakes(review): Preserve private checks, X polling, and lifecycle IDs * no-mistakes(review): Separate task creation and legacy teardown validation * no-mistakes(review): Restore safe legacy operations and teardown validation * no-mistakes(review): Disambiguate migration obligations and preserve legacy retries * no-mistakes(review): Preserve fail-closed diagnostics and legacy quarantine evidence * no-mistakes(review): Reconcile legacy migration retries and teardown collisions * no-mistakes(review): Force legacy namespace reconciliation before marker short-circuits * no-mistakes(document): Document private poll artifact safety contracts * no-mistakes(lint): Suppress intentional literal-dollar lint finding * fix: migrate historical X poll identity * fix: harden PR check artifacts * no-mistakes(review): Preserve fail-closed diagnostics and legacy quarantine evidence * no-mistakes(review): Reconcile legacy migration retries and teardown collisions * fix: migrate historical X poll identity * no-mistakes(review): Harden X-mode artifact publication against symlink corruption * no-mistakes(review): Guard X artifact publication * no-mistakes(review): Enforce private X artifact reads * no-mistakes(test): Fix backend compatibility fixture dependencies * no-mistakes(document): Refresh PR-check documentation * no-mistakes(lint): Remove unused x-mode test locals * no-mistakes: apply CI fixes
* fix: compact session-start backlog digest * no-mistakes(test): Fix legacy backend fixture helper * no-mistakes(test): Fix watcher exit wait helper * no-mistakes(document): Document compact backlog digest
* fix: dedupe stale watcher guard banner * no-mistakes(review): Keep read-only guard state nonmutating * no-mistakes(document): Clarify stale watcher docs
* fix: balance bearings landed defaults * no-mistakes(document): Document balanced landed baseline * no-mistakes: apply CI fixes
* docs: clarify captain-facing translation contract * no-mistakes(review): Restore runtime fallback mandate * no-mistakes(document): Align Bearings translation wording
…#646) * fix: make bootstrap nudges deterministic * no-mistakes(review): Honor state override for bootstrap nudges * no-mistakes(review): Update benign bootstrap documentation labels * no-mistakes(review): Validate bootstrap nudge retry markers * no-mistakes(document): Align bootstrap nudge documentation * no-mistakes: apply CI fixes
…nchenguid#649) * Clarify concise secondmate registry contract * no-mistakes(review): Expand secondmate registry boilerplate coverage * no-mistakes(document): Point route docs to owner
…kunchenguid#654) * fix(bin): strip quotes on blocked_by in decision-hold resolve tasks-axi quotes multi-entry blocked_by as "a,b,c", so the comma-boundary membership test only matched middle elements. Strip surrounding quotes before matching so first and last hold ids resolve correctly. * no-mistakes(document): Refresh decision-hold regression evidence
* feat(secondmate): inherit shared captain preferences * no-mistakes(review): Honor shared captain data overrides * no-mistakes(review): Honor bootstrap data override registry * no-mistakes(document): Refresh shared inheritance docs * no-mistakes(document): Clarify inherited local-material docs
* feat(spawn): gate local agent secret injection * fix(spawn): align final Keychain slot * no-mistakes: apply CI fixes
* test: isolate herdr autodetect smoke session * no-mistakes(review): Restored autodetect smoke gate bypass * no-mistakes(test): Harden Herdr lab provisioning * no-mistakes(document): Refresh Herdr lab docs
…unchenguid#668) This reverts commit c27135c.
* fix(pi): distinguish stale locks when arming watcher * no-mistakes(test): Stabilize watcher extension async waits * no-mistakes(document): Document Pi lock recovery
* fix: accept secondmate as house vocabulary * no-mistakes(test): Update captain vocabulary contract test * no-mistakes(document): Align secondmate documentation vocabulary
…uid#686) * fix: parse secondmate home after pre-field parentheses Registry summaries often include parentheticals before the structured (home: ...) field. Match that field with a greedy prefix so handoff no longer reports "has no home" for those entries. * no-mistakes(document): Refresh handoff test comments
* feat: add native session-start nudges * no-mistakes(document): Document nudge script inventory
…nguid#688) Relabel absent-captain and related domain defaults wording so it names the firstmate repo rather than treating "template" as this domain's identity label. Keep the design-tenet "shared template" statements and unrelated launch/PR-poll template uses unchanged.
…nsion (kunchenguid#205) * fix(bin): use set -u-safe empty-array expansion in pr-merge and spawn Expanding "${arr[@]}" on an empty array under set -u fails on bash < 4.4 (notably macOS bash 3.2). Quote the portable "${arr[@]+"${arr[@]}"}" idiom in fm-pr-merge and fm-spawn batch dispatch so empty arrays expand to nothing. Co-authored-by: Cursor <cursoragent@cursor.com> * test(brief): harden fm-brief regression coverage for parse and scaffolds Tighten bash -n checking, pin literal backtick rendering in the no-mistakes DOD wording assertion, and keep a scout/secondmate scaffold smoke test so the Co-authored-by: Cursor <cursoragent@cursor.com> kunchenguid#166 apostrophe regression cannot return unnoticed. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…nchenguid#693) * fix: make watcher supervision continuous * no-mistakes(review): Bound watcher retries and log attached signals * no-mistakes(review): Add bounded successor-recovery wake fallbacks * no-mistakes(review): Prevent overlapping successor-arm retries * no-mistakes(review): Resume supervision after late arm closes * no-mistakes(review): Bind OpenCode recovery to attempted arm * no-mistakes(test): Synchronize peer beacon regression fixture * no-mistakes(test): Synchronize Pi and OpenCode late-close lifecycle fixtures * no-mistakes(document): Captain: document watcher successor protocol behavior * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes * no-mistakes: apply CI fixes
* fix: always fetch PR head for review diffs Prefer a freshly fetched refs/pull/<n>/head over a reachable recorded pr_head= so reviewers never hold a merge over a "missing" fix that already landed on the remote PR. Recorded SHA is offline fallback only; local branch is last resort with a warning. Store the tip under refs/fm-review/ so a later base-branch fetch cannot clobber the compare tip via FETCH_HEAD. * no-mistakes(test): Isolate session-start nudge tests from gate state * no-mistakes(document): Correct review-diff documentation
…and skills (kunchenguid#736) * docs: resolve five contract contradictions * no-mistakes(test): align owner-pointer assertions with reworded docs; skip absent shellcheck
* docs(harness): reverify grok exit command * no-mistakes(test): Correct Grok exit resume attribution
* fix(watcher): bound stale wakes for exited paused crew * no-mistakes(review): Gate pause suppression on confirmed agent death * no-mistakes(test): Fixed stale pause cadence * no-mistakes(document): Document dead-agent hold cadence
…id#744) * fix(supervision): distinguish ordinary wakes from repair * no-mistakes(review): Make passive guard follow-ups recovery-only * no-mistakes(document): Clarify recovery-only turn-end guard documentation
* fix(x-mode): dedupe pending mention wakes * no-mistakes(review): fix x-poll claim error deduplication * no-mistakes(review): separate claim diagnostics from relay recovery * no-mistakes(document): Document X-mode once-only mention wakes
…enguid#747) * feat(wake): enrich drained signal context * no-mistakes(review): Bound wake enrichment reads * no-mistakes(document): Document wake-drain annotations * docs(wake): explain at-least-once drain boundary * no-mistakes(review): Prevent symlink races in wake annotations * no-mistakes(review): Exercise wake symlink race regression * test: document intentional AFK marker subprocesses * fix(wake): isolate annotation marker state
Brings the fork up to date with upstream (b2bf95f..4ab61fa reached upstream between dispatch and fetch, so 30 commits landed rather than the 24 counted at dispatch). All 6 local commits survive; verification below. What upstream brings, grouped: - Instruction ownership restructure (kunchenguid#619, kunchenguid#626, kunchenguid#644, kunchenguid#649, kunchenguid#666, kunchenguid#685, kunchenguid#688, kunchenguid#736): AGENTS.md compressed 958 -> 479 lines, contracts moved to single owners in docs/ and new skills (project-management, decision-hold-lifecycle, diagnostic-reasoning), enforced by the new tests/fm-instruction-owners.test.sh. - PR-check security hardening (kunchenguid#556): new fm-pr-lib.sh canonical task-ID and PR-URL validation, byte-static fm-pr-poll.sh sidecars, fm-check-register.sh and fm-check-lib.sh for custom checks, fm-pr-check-migrate.sh quarantine, plus the large tests/fm-pr-check-security.test.sh matrix. - Watcher and supervision fixes: continuous supervision across child cycles (kunchenguid#693), bounded stale wakes for parked crew (kunchenguid#743), recovery vs ordinary wake distinction (kunchenguid#744), enriched drained signals (kunchenguid#747), deduped stale guard banners (kunchenguid#637), pi stale-lock arming (kunchenguid#681). - Secondmate: shared captain preferences via data/captain-shared.md (kunchenguid#656), handoff-home parsing after registry parentheticals (kunchenguid#686), durable captain decision holds (kunchenguid#593) and their quoted blocked_by fix (kunchenguid#654). - Session start: native session-start nudges (kunchenguid#687), compact backlog digest (kunchenguid#636), deterministic bootstrap output (kunchenguid#646), balanced bearings baseline (kunchenguid#640). - Review diffs fetch the current PR head (kunchenguid#722); fm-brief.sh parse and set -u hardening (kunchenguid#205); X-mode pending-mention wake dedupe (kunchenguid#745); Herdr smoke test isolation (kunchenguid#662); Grok exit-guidance docs (kunchenguid#742); secret-injection gate added (kunchenguid#658) and reverted (kunchenguid#668). Conflicts and resolutions (3 files): - AGENTS.md: upstream compressed the delivery/yolo section that local commit a6d71e7 had extended. Took upstream's compact block and re-added the local test-keep-gate stub in the same style: the fm-assert-tests-kept.sh hard refusal and the captain-approved data/supersessions/<project>.md routing. The local data/supersessions layout line auto-merged. The dropped verbose HEAD-side text (Supervise, review-diff, evidence commits) was verified relocated by upstream into docs/ and skills, not lost. - bin/fm-pr-merge.sh: upstream rewrote entry validation around fm-pr-lib.sh (canonical ID/URL parsing, symlink-refusing META check); local commits had added the test-keep gate and supersession honor logic. Kept upstream's validation and structure, reinserted the local gate between pr= recording and the gh-axi merge call, and merged both header docs. The gate execution block itself auto-merged. - docs/scripts.md: combined upstream's new script table rows (fm-pr-lib, fm-pr-poll, fm-check-register, fm-check-lib, fm-pr-check-migrate) with the local fm-assert-tests-kept.sh row; the fm-pr-merge.sh row now names both the gate and the canonical-URL contract. Local work survival, commit by commit: - 40fa488 (treehouse pool config + reset-accounts skill): treehouse.toml and .agents/skills/reset-accounts/SKILL.md present and byte-identical (git diff 40fa488..HEAD on both paths is empty). - eec0f70 (assert a rebase never reduces main's test assertions): bin/fm-assert-tests-kept.sh present and untouched by upstream; bin/fm-pr-merge.sh still invokes it; docs/architecture.md and docs/scripts.md references intact; tests/fm-assert-tests-kept.test.sh all green post-merge. - a6d71e7 (check 2 + captain-approved supersessions): check-2 baseline-run logic present in fm-assert-tests-kept.sh; supersession_approved and its refusal guidance present in fm-pr-merge.sh; AGENTS.md keeps the data/supersessions layout line and the yolo-section gate stub; all 15 tests/fm-pr-merge.test.sh cases green post-merge, including the gate and supersession cases. - cb6a599, 3b060d5, c55b29a (PR merge commits): reachable unchanged from HEAD; a merge was used precisely so no local history was rewritten. Validation: bin/fm-lint.sh passes; fm-pr-merge, fm-assert-tests-kept, fm-review-diff, fm-instruction-owners, and fm-pr-check-security suites pass (the security suite needed a follow-up fixture commit teaching its merge-success cases to satisfy the local test-keep gate).
fm-pr-merge.sh gates merges on fm-assert-tests-kept.sh, which resolves a real project repo and task worktree from the task meta. The upstream security fixtures predate the gate and used bare or missing paths, so every expected-successful merge was refused with 'could not verify'. Add write_gate_project and scope the legacy-loop gate worktree to the merge step so both teardown invocations still exercise the missing-worktree path.
test_output_ordering_diagnostics_lead and test_composition_invokes_real_scripts forced a MISSING: node diagnostic only by deleting the fakebin node stub, which silently assumed node is absent from the fallback BASE_PATH (/usr/bin:/bin:/usr/sbin:/sbin). That holds on GitHub runners but breaks on any host where apt/nodesource installed /usr/bin/node: command -v node succeeds, bootstrap correctly reports nothing missing, and both assertions fail. Reuse the existing tmux masking idiom from test_herdr_backend_diagnostics_follow_real_session_start: a shared write_node_mask helper emits a BASH_ENV file overriding command -v node to fail regardless of PATH, and both tests pass it on their run_session_start call while keeping the fakebin removal. The assertions themselves are unchanged; only how node is made to look absent is.
Conflicts resolved by keeping the upstream restructure and folding in main's semantic additions: the /handoff trigger and exec-gate sentences in AGENTS.md, both SessionStart hooks (nudge + handoff pickup) in .claude/settings.json, and both sides' new script rows in docs/scripts.md. Test seams repaired: the pr-merge stub dir now mirrors bin/*.sh so SCRIPT_DIR-relative sourcing of fm-pr-lib.sh resolves, and the nudge test asserts its own SessionStart entry instead of sole registration. bin/fm-wake-lib.sh merged with zero deletions vs main, preserving the kernel-start-ticks process identity from PR #5.
tests/fm-pr-check-security.test.sh's write_gate_project and tests/fm-continuity-pretool-check.test.sh's primary-checkout fixture both ran bare git commit without fm_git_identity or an inline -c identity, so they passed on any machine with a global git config and failed exit 128 (empty ident) on a clean CI runner. Call fm_git_identity after sourcing lib.sh, matching the convention the other nineteen callers use. Audited all 86 test files for the same latent defect; these two were the only instances. Full suite passes under a neutralized-identity environment (GIT_CONFIG_GLOBAL=/dev/null, identity vars unset) and normally.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Bring the fork's parked upstream-sync branch up to date with local main so the completed upstream sync (30 upstream commits merged at a3b15b4 by a previous worker) can ship without losing any local work. This merge commit (db46bda) merges main (4bf2e94, PRs #5-#10) into the sync branch, deliberately a merge rather than a rebase to avoid rewriting shared history. Key constraint honored: PR #5's kernel-start-ticks process identity in bin/fm-wake-lib.sh (Linux /proc//stat field 22 parsed after the final paren in comm, proc-starttime: prefix, ps lstart kept only as macOS fallback and legacy-lock compatibility) had to survive against the upstream side's older lstart-based code; the merged file has zero deletions vs main, only the branch's ~157 added watcher-health lines. Conflict resolutions: AGENTS.md keeps the upstream restructure (section bodies moved into skills) and folds in main's only semantic additions - the /handoff skill load trigger and PR #9's exec-gate sentence; .claude/settings.json keeps BOTH SessionStart hooks (upstream's matcher-scoped fm-sessionstart-nudge.sh plus main's fm-handoff.sh pickup) and the branch's third PreToolUse hook; docs/scripts.md keeps both sides' new script rows, with main's richer fm-assert-tests-kept.sh description (matches the #6/#9-enhanced script the branch did not touch). Two deliberate test edits are part of the merge, not drive-by changes: tests/fm-pr-merge.test.sh's stub helper now mirrors all bin/.sh into its shim dir because the branch's fm-pr-merge.sh sources SCRIPT_DIR/fm-pr-lib.sh (with transitive deps) which the old two-symlink shim lacked, and tests/fm-sessionstart-nudge.test.sh now asserts the nudge SessionStart entry is registered exactly once with matcher startup|resume|clear instead of asserting SessionStart has exactly one entry total, because main's handoff pickup hook is a legitimate second entry (its registration is asserted by tests/fm-handoff.test.sh). The .github/workflows/ci.yml diff vs main (test-count assertions 12->13 and 30->36) is inherited byte-identical from upstream and required: the merged tree really has 13 fleet-snapshot/view and 36 bearings tests, verified by running them. Note: the branch was pushed to origin over SSH out-of-band because the pipeline's HTTPS OAuth token lacks workflow scope and cannot push the ci.yml change; the remote branch already matches HEAD, so the push step should be a no-op. Validation before commit: bin/fm-lint.sh clean and all 86 tests/.test.sh files pass.
What Changed
bin/fm-pr-lib.sh,bin/fm-pr-check-migrate.sh), and the AGENTS.md restructure that moves section bodies into skills.bin/fm-wake-lib.shsurvives with zero deletions vs main (only the branch's watcher-health additions),.claude/settings.jsonkeeps both SessionStart hooks (upstream's matcher-scoped nudge plus main's handoff pickup) and the branch's third PreToolUse hook, and the restructured AGENTS.md and docs/scripts.md fold in main's semantic additions (the /handoff load trigger, PR feat(bin): execute Python base tests at the kept-tests merge gate #9's exec-gate sentence, the richer fm-assert-tests-kept.sh description).tests/fm-pr-merge.test.sh's stub helper now mirrors allbin/*.shinto its shim dir (fm-pr-merge.sh now sources fm-pr-lib.sh with transitive deps), andtests/fm-sessionstart-nudge.test.shasserts the nudge SessionStart entry is registered exactly once with matcherstartup|resume|clearinstead of asserting a single entry total. The ci.yml test-count bumps (12→13, 30→36) are inherited byte-identical from upstream and match the merged tree; all 86 test files pass.Risk Assessment
✅ Low: Every intent constraint verified against both parents (wake-lib zero deletions with kernel-ticks identity intact, ci.yml byte-identical to upstream with statically confirmed test counts of 13 and 36, both SessionStart hooks plus the third PreToolUse hook, both AGENTS.md semantic additions, both scripts.md row sets), the only hand-edits beyond mechanical resolution are the two declared test-seam repairs which are demonstrably necessary, and no duplicate definitions, dropped test invocations, or syntax issues exist in any both-sides-merged file.</risk_rationale>
["git diff --numstat 4bf2e94..db46bda -- bin/fm-wake-lib.sh (165 insertions, 0 deletions) and grep for proc-starttime/lstart identity helpers", "git diff 9ae91ac..db46bda -- .github/workflows/ci.yml (empty: byte-identical to sync parent)", "static pass-assertion counts: 13 in fm-fleet-snapshot-view.test.sh, 36 in fm-bearings-snapshot.test.sh, matching ci.yml", "jq parse of .claude/settings.json and presence of both SessionStart hooks plus third PreToolUse hook", "isolation of merge-resolution edits: every test hunk vs main traced to the sync parent except the two declared edits", "duplicate-function and defined-but-uninvoked test-function sweeps over all both-sides-merged bash files", "bash -n on fm-pr-merge.sh, fm-wake-lib.sh, and merged test files", "SCRIPT_DIR transitive-dependency check confirming the bin/.sh shim mirror is required (fm-pr-check-migrate.sh sources five sibling scripts)", "git ls-remote: origin fm/fm-upstream-sync-b3 already at db46bda; 86 tests/.test.sh files present"]
Testing
Baseline run of all 86 shell test files passed; I then re-ran the merge-critical tests (fm-pr-merge, fm-sessionstart-nudge, fm-handoff, fm-watcher-lock, fm-wake-queue, fm-fleet-snapshot-view, fm-bearings-snapshot) and verified each intent constraint directly: zero deletions in fm-wake-lib.sh vs main with proc-starttime identity intact, ci.yml diff limited to the inherited count bumps whose values (13, 36) match live test output, both SessionStart hooks plus the three-command PreToolUse hook registered, both deliberate test edits present as described, and the remote branch already at HEAD. No linter was run per task rules. No visual artifacts because this is a shell/CLI project with no rendered UI surface; CLI transcripts serve as the product-level evidence.
Evidence: Merge intent verification transcript (diffs, live counts, hooks, remote check)
Evidence: fm-fleet-snapshot-view test output (13 ok lines)
Evidence: fm-bearings-snapshot test output (36 ok lines)
Evidence: Merge-critical test runs (pr-merge, sessionstart-nudge, handoff)
Evidence: Watcher process-identity test runs (watcher-lock, wake-queue)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
tests/fm-handoff.test.sh:243- tests/fm-handoff.test.sh's no-matcher assertion (jq '.hooks.SessionStart[] | has("matcher")' output contains 'false') became imprecise once the merge added a second, matcher-scoped SessionStart entry: it passes if any entry lacks a matcher, rather than asserting the pickup entry specifically is unmatchered. The nudge test was tightened to entry-scoped jq selects during this merge; the handoff test was not given the symmetric treatment. It still guards correctly today since pickup is the only unmatchered entry, but a future third unmatchered SessionStart entry would let a narrowed pickup slip past this assertion.✅ **Test** - passed
✅ No issues found.
command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"Baseline (pre-run):for t in tests/*.test.sh; do bash "$t"; done- all 86 test files passedbash tests/fm-fleet-snapshot-view.test.sh- exit 0 with exactly 13ok -lines, matching the new ci.yml assertionbash tests/fm-bearings-snapshot.test.sh- exit 0 with exactly 36ok -lines, matching the new ci.yml assertionbash tests/fm-pr-merge.test.sh,bash tests/fm-sessionstart-nudge.test.sh,bash tests/fm-handoff.test.sh- all pass, covering the two deliberate test edits and the dual SessionStart hook registrationbash tests/fm-watcher-lock.test.sh,bash tests/fm-wake-queue.test.sh- pass, exercising the preserved proc-starttime process identity from PR #5git diff --stat 4bf2e94 HEAD -- bin/fm-wake-lib.sh- 165 insertions, 0 deletions; grep confirms proc-starttime prefix and lstart-fallback code intactgit diff 4bf2e94 HEAD -- .github/workflows/ci.yml- diff vs main is exactly the 12->13 and 30->36 count changesInspected.claude/settings.jsonhooks: nudge SessionStart entry with matcher startup|resume|clear, handoff pickup SessionStart entry, and the three-command PreToolUse Bash hookInspected AGENTS.md (handoff skill load trigger, exec-gate sentence) and docs/scripts.md (both sides' script rows, main's richer fm-assert-tests-kept.sh description)git ls-remote origin fm/fm-upstream-sync-b3- remote tip db46bda equals local HEAD, so the pipeline push is a no-opdocs/scripts.md- Pre-existing docs/scripts.md coverage gap, not caused by this merge: bin/fm-cd-pretool-check.sh and bin/fm-cd-command-policy.mjs are unlisted while their sibling PreToolUse hooks (fm-arm-* and fm-continuity-*) have rows, and fm-lint.sh, fm-lint-plan.awk, fm-install-shellcheck.sh, and fm-transition-lib.sh are also unlisted. All were equally absent at base 4bf2e94, so this is a follow-up candidate for a session that owns scripts.md coverage, not part of this change.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.