Skip to content

sync: merge upstream through d43e610b (round 2) - #270

Merged
HelloWorldSungin merged 27 commits into
mainfrom
fm/fm-upstream-sync-2026-09-08-round-2
Sep 11, 2026
Merged

HelloWorldSungin merged 27 commits into
mainfrom
fm/fm-upstream-sync-2026-09-08-round-2

Conversation

@HelloWorldSungin

@HelloWorldSungin HelloWorldSungin commented Sep 11, 2026 •

Copy link
Copy Markdown
Owner

Merge the first of four remaining contiguous upstream prefixes, through kunchenguid/firstmate@d43e610b0a6b1c6eb79bcf37e6c41074d89a4c6d.
This imports 26 first-parent changes while preserving the fork's agy adapter, Pi away supervision, durable outcomes, remote process safety, GBrain, dashboard behavior, and test bounds.

Topology and scope

  • Exact fork parent: 83f4a40bff0ee86960bd7f4774a92068da56880b.
  • Measured merge base: 88fb3c0ae9ddca1cfd58acf87308f0d1d4b73ccb.
  • One git merge --no-ff d43e610b0a6b1c6eb79bcf37e6c41074d89a4c6d; the merge commit has exactly the fork and endpoint parents above.
  • Exact pushed head: 38e6e9f0374d5d8dbfc99e9e328b2f6854d932e8. Pushed successfully to the explicitly verified fork origin.
  • Review ceiling: 4768e98d469b7216569acf6e7a5cc696ecd15c2e; later endpoints 2e65d2e2482247c22db2ba7aeeb055eb7876fef1, b84e0e362face25f3dd8945297a3df1320d7668c, and the ceiling remain excluded.
  • No rebase, cherry-pick, squash, force, default-branch write, or third-party upstream write.
  • None of the five ledger-parked branch tips is an ancestor of either parent, and their commits beyond the fork parent have zero intersection with the endpoint's additions.
  • The self-decided-findings detector remains unlanded and was inspected read-only; no detector commit entered this merge.

Validation

Revision Complete scripts Failed Gate skips Full lint
Exact fork parent 223 14 30 exit 0
Exact upstream parent 178 19 24 exit 0
Final committed merge 225 0 30 exit 0

The unchanged-parent failures are preserved separately.
Both parents expose private-directory fixture refusals under ambient umask 0002 and a Calm stock-renderer oracle mismatch on Pi 0.85.1.
Upstream additionally exposes host-sensitive node/PATH/wrapper fixtures and an unavailable Ruby parser dependency that the fork already handles.
Final validation uses umask 022 with the production private-state guard unchanged; unchanged-parent directory-mode counterexamples establish that distinction.
Calm's production code is unchanged; its test now supplies the stock SDK tool definitions and recognizes the installed stock working indicator.
The initial integrated sweep's two additional failures were outdated fork-only agy brief and Claude launch-template expectations, corrected without weakening production gates; both affected suites passed their reruns.

Strict Pi typechecking passed against installed Pi 0.85.1 with the existing cached TypeScript 7.0.2 compiler.
Credential-free real-SDK guard tests passed on both parents and the candidate; all final Pi TypeScript files are byte-identical to that candidate.
No real model-provider or opt-in live-harness coverage is implied by those checks or by gate skips.
The snapshot suite passes 52 checks against the CI minimum of 49.
Documentation audience, cross-system pointer, whitespace, and full lint checks passed.

All lifecycle tests use repository-owned unique guarded nondefault Herdr labs, under Firstmate's explicit fixture authorization.
An initial isolated-HOME discovery attempt hit the unchanged fleet tripwire and was stopped; read-only A/B established the stopped shadow socket versus the actual running default under baseline HOME.
The final invocation restores real-HOME discovery, clears inherited fleet identity, and isolates Claude-writing fixtures with scratch stores, including a regression observing the actual write destination.
No server update, global stop, default-session lifecycle change, tool installation, or fleet dispatch-default change was performed.
Private trust-fixture incident reconciliation: the captain-approved four-entry cleanup completed with exact-key verification and unchanged unrelated settings/permissions; a possible fifth remains unconfirmed and was neither searched for nor removed.

Review conclusions and ledger changes

Gemini CLI and Antigravity/agy are separate executables with different authentication, trust, and supervision mechanisms.
Gemini arrives in the next prefix, not this merge; agy remains crew-only and Herdr-only with native identity and atomic inbox delivery.
The ceiling's Gemini configured-profile validator omits Gemini despite its runtime registration; the report records an executable reproduction for the later round.
This prefix preserves existing Pi supervision and adds fresh per-main-session branch conversations, accepted-follow-up handling, requested-result classification, and wake-task-scoped reporting.
Later async delivery, extension-provider, Windows, native Codex, and AFK-posture changes remain excluded.
Prompt-cache and interruption-percentage announcements are not treated as measured guarantees.

The ledger records the explicitly approved terminal exact-HEAD anchor for unresolved active no-mistakes heads, retaining strict teardown attribution and the fork's relation/custody/degraded-state guarantees.
It retires the pre-move crash-fixture divergence because upstream's shared injector now supplies that behavior.
Compatible snapshot, wait-cadence, authored-brief, and preserving-refusal adaptations are recorded; the parked list is unchanged.
Firstmate approved narrowing two inconsistent skill statements to their existing owners: preserving-refusal recovery follows teardown, and rollout restart eligibility requires confirmed exact-target convergence and excludes skipped homes.

This is direct-PR because no-mistakes would rebase away the required merge topology.
No no-mistakes run was invoked.
The sole expected red check is PR must be raised via no-mistakes; all 16 other checks passed, including lint, every portable lane, real-Herdr behavior, stock macOS Bash snapshot compatibility, repository invariants, coverage and timing aggregation.
Explicit GitHub API readback: mergeable=true, merged=false, exact head 38e6e9f0374d5d8dbfc99e9e328b2f6854d932e8, base HelloWorldSungin/firstmate:main at 83f4a40bff0ee86960bd7f4774a92068da56880b.
mergeable_state=unstable reflects the deliberately red compliance gate, not a merge conflict.
Landing remains reserved for Firstmate through bin/fm-pr-merge.sh fm-upstream-sync-2026-09-08-round-2 https://github.com/HelloWorldSungin/firstmate/pull/270 -- --merge with an explicitly composed commit body.

Private comparison report: /home/sungin/firstmate/data/fm-upstream-sync-2026-09-08-round-2/report.md.
Its evidence index preserves the measured inventory and all 166 overlap patches, parent/final artifacts, Kun fetched commit/hashes and attributed advisory influence, and the full-ceiling comparison.

Current-round first-parent applicability

Upstream change Disposition Fork integration reasoning
8988af2aec35 fix(bearings): keep active children underway during captain holds Adopted with adaptation Render active and abandoned children individually; retain fork child identity and state fields.
77ee3c82f86e fix(pi): settle watcher delivery on Pi accepting the follow-up Adopted Settle Pi follow-up on acceptance; retain consumption tracking, generation replay and away standby.
d22318ea1e61 fix(bin): bound repeat stale wakes for parked workers Adopted with adaptation Keep fork declaration-scoped widening for paused workers; add upstream live captain-held throttle without duplicate enqueue.
5fb0ce7628f2 fix(bin): accept the away-mode daemon as the turn-end supervision owner Adopted Recognize verified live away daemon as turn-end owner; retain freshness and pending-wake requirements.
353a8f0ff25d fix(backlog): omit --file from row probes for non-markdown backends Adopted Select tasks-axi row-probe arguments by configured backend instead of imposing markdown --file.
1c00e86cf3a1 fix(bin): classify progress updates on requested work as routine Adopted Classify start/progress as routine while completed requested results remain important.
b2e3e9ef69b2 fix(bin): preserve captain calls during teardown Adopted with adaptation Retain captain calls through teardown; preserve fork design gate, manifest ordering and preserving-refusal withdrawal.
d3fcdfa548f5 fix(bin): deliver secondmate outcomes to the parent channel Adopted Publish secondmate outcomes and retained calls to parent channel with durable delivery handling.
e1d1d692674b fix(bin): sync remote second mates to primary commit Adopted Sync remote code/home to primary commit; preserve fork inheritance and remote process guarantees.
28fb5acaf32c fix(bin): separate captain intent from firstmate specs Adopted with adaptation Separate intent from spec through shared DOD owner; retain design and continuation flows and parse structural identity from authored brief.
3d2a08b2097d fix: start a fresh supervision branch for every main session Adopted Create a fresh branch conversation per main session and reanchor mirror; retain current-session pins and fork away behavior.
1c5c9c18d580 feat: restart second mates after instruction updates Adopted Persist-gated secondmate restart and runtime capabilities; retain read-only upstream and scoped home updates.
7dcf07218c76 perf: accelerate local validation with bounded concurrency Adopted with adaptation Bounded named-list/changed concurrency; retain default 480-second deadline, fork lane coverage and shared crash-injector correction.
75b2de262ab0 fix: copy PR URLs from durable records Adopted Copy full recorded PR URLs, preserving explicit fork-only publishing instructions.
3034912cd57d fix(bin): disable Claude feedback drafts for fleet launches Adopted with adaptation Disable Claude feedback drafts in fork canonical launch owner while retaining prompt-suggestion setting.
7adb358fd507 feat(tests): run three more validation families concurrently Adopted with adaptation Add proven family scheduling while retaining fork tests, eight serial shards and test bounds.
ed44d1507a91 feat: structure no-mistakes ask-user escalations Adopted with adaptation Carry structured ask-user escalation format through ship and design DOD and brief rules.
3b82ebdd79cf fix(bin): require self-sufficient no-mistakes intent Adopted Require self-sufficient intent content without importing Firstmate spec as captain words.
5a7ba57caf2c fix: accelerate local Bearings snapshot composition Adopted with adaptation Capture task metadata once and reject replacement-generation observations; reuse fork bounded parallel row owner and additive fields.
f4d7875824ec fix: prevent stale supervision wake loops Adopted with adaptation Constrain branch outcome task scope and repair watcher successor handling; retain fork default stop-signal disposition.
31cba0db93f0 fix(bin): avoid fleet snapshot argument limits Adopted with adaptation Use file-backed JSON transport without argument-size limits; retain read-only dashboard cache path.
b82d09f0f090 fix(bin): attribute active runs with unfetched pipeline heads Adopted with approved narrowing Allow unresolved running head only with terminal exact-HEAD same-branch anchor; retain custody, relation table, strict teardown and degraded/abandoned state.
1b0fbb9b8693 fix(bin): pre-register claude workspace trust at spawn time Adopted with adaptation Pre-register Claude trust for linked worktrees; normalize explicit relative config path and isolate all writing fixtures.
efbeb4fe700e fix: restart every live second mate after updates Adopted with corrected instruction Restart all eligible live updated/current mates; exclude skipped homes and require exact-target convergence for one-time rollout.
3c1e86d7687b fix(bin): close pending-reply decisions via resolve-key Adopted Close pending-reply decisions via keyed resolution and refold status after append; retain scout gate reopening.
d43e610b0a6b fix(bin): prevent false missed-reply escalations Adopted Suppress false missed-reply escalation with durable reply observation and delivery/reply distinction.

Per-file contract reasoning

File Reasoning
AGENTS.md Retain fork hard rules, design scope, agy restrictions, GBrain/dashboard pointers and upstream-only read boundary; adopt current intent, outcome and restart contracts.
.agents/skills/bearings/SKILL.md Adopt per-child Underway presentation while retaining fork fields and read-only observations.
.agents/skills/bootstrap-diagnostics/SKILL.md Adopt retained captain-call recovery; Firstmate-approved wording distinguishes interrupted cleanup from preserving-refusal withdrawal.
.agents/skills/updatefirstmate/SKILL.md Adopt persist-gated restart; Firstmate-approved rollout wording requires live homes at the exact target and excludes skipped homes.
.agents/skills/ask-user-authority/SKILL.md Adopt structured finding snapshot intake without shifting decision authority to the worker.
.agents/skills/captain-hold-lifecycle/SKILL.md Adopt retained-call and parent-delivery mechanics while preserving design completion requirements.
.agents/skills/secondmate-provisioning/SKILL.md Adopt primary-commit remote update and parent-channel/restart owners without dropping fork inheritance.
.agents/skills/harness-adapters/references/common/control-and-recovery.md Adopt restart capability routing while preserving harness-specific supported roles.
.agents/skills/harness-adapters/references/harness/claude.md Document trust preregistration and feedback settings without extending them to agy.
bin/fm-bearings-snapshot.sh Project each active/abandoned child under its own identity instead of a parent aggregate.
bin/fm-fleet-snapshot.sh Capture metadata once, discard replacement-generation results, transport JSON by file and retain fork bounded parallel collection, timeouts, additive fields and read-only cache mode.
bin/fm-bootstrap.sh Use backend-aware backlog probes and current remote sync logic while retaining fork host-sensitive fixture handling and dispatch validation.
bin/fm-brief.sh Emit intent/spec and structured ask-user rules; preserve design, work-item, GBrain, role and continuation sections.
bin/fm-dod-lib.sh Keep one DOD owner for ship/design/handoff fragments; adopt self-sufficient provenance-marked intent and structured escalation overlay.
bin/fm-crew-state.sh Use shared three-verdict attribution; require active matching full detail before promoting anchored coarse state; preserve abandoned/degraded and recorded-branch behavior.
bin/fm-nm-run-lib.sh Implement approved terminal exact-HEAD anchor narrowing while keeping explicit custody, relation table and strict teardown predicate.
bin/fm-guard.sh Adopt current ownership guidance while keeping queued wakes a supervision requirement.
bin/fm-launch-lib.sh Remain canonical launch template owner; add Claude feedback flags beside existing prompt settings and retain agy template.
bin/fm-spawn.sh Add trust preregistration and intent overlay; parse structural markers from authored source; preserve design pinning, agy gates, raw restrictions and watermark failure records.
bin/fm-claude-trust.sh Adopt linked-worktree-only trust registration with atomic store update; all test calls must target disposable stores.
bin/fm-pr-check.sh Keep fork current-body refresh and compliance event scope while adopting parent outcome delivery wiring.
bin/fm-task-inbox-lib.sh Adopt optimistic lock claim/retry without losing competing-lock behavior or fork harness-aware atomic doorbell dispatch.
bin/fm-teardown.sh Retain calls and notify parent before destructive cleanup; preserve manifest/GBrain/usage ordering, strict run identity and marker withdrawal on preserving refusal.
bin/fm-test-run.sh Adopt bounded automatic/family concurrency; preserve 480-second default with explicit-zero opt-out, fork family membership, locale handling and eight serial shards.
bin/fm-watch.sh Adopt scope-aware branch recovery and captain-held repeat throttle; preserve fork signal disposition, fd4 warnings, caller-owned eventwait cleanup and widening paused cadence.
bin/fm-backlog-transition-lib.sh Adopt retention transition through existing durable pending-close identity and replay owner.
bin/fm-parent-channel-lib.sh New parent-channel owner for durable secondmate outcomes and captain-call notification, separate from answer authorship.
bin/fm-secondmate-report.sh Route correlated and uncorrelated results through the new parent-channel owner.
bin/fm-pending-reply-lib.sh Adopt actual-reply observation and keyed closure to prevent false missed replies.
bin/fm-send.sh Adopt reserved pending-reply resolution/refolding while retaining fork scout-gate reopening on both delivery planes.
bin/fm-secondmate-restart-lib.sh New persist-before-restart capability and correlation owner; no claim that capability proves version convergence.
bin/fm-secondmate-restart.sh New guarded restart entry point; consume capability/persistence evidence before stopping the target.
bin/fm-update.sh Adopt primary-target sync and eligible live-mate restart while retaining guarded fast-forward-only behavior.
bin/fm-remote-secondmate-control.sh Adopt parent-channel/restart integration while preserving fork inherited material, target identity and harness-aware inbox.
bin/fm-tasks-axi-lib.sh Select backend-specific row-probe flags through the shared backend resolver.
bin/fm-turnend-guard.sh Recognize identity-matched away daemon ownership with fresh beacon; retain pending-queue and strict failure cases.
.pi/extensions/fm-primary-pi-watch.ts Separate accepted delivery from consumed follow-up and recover generation-bound successor chains; preserve fork away standby.
.pi/extensions/fm-branch-supervision.ts Fresh branch per main session; deterministic wake task scope; retain model pins, durable outcome replay, leases and away behavior.
.pi/extensions/lib/fm-branch-dispatch.ts Carry current wake scope and dispatcher generation semantics without importing later async/provider/native changes.
bin/fm-branch-outcome.sh Adopt current durable result scope and preserve sequence-based storage/processed acknowledgement.
bin/fm-branch-prompt.sh Treat requested completion as important, progress as routine, and copy recorded full PR URLs.
.github/workflows/ci.yml Preserve Node22 and eight shards; raise snapshot minimum to49 with52 actual checks, retain refresh and fork compliance event scope.
.no-mistakes.yaml Retain private validation evidence; take this prefix changed-test command and disclose its later upstream reversal rather than importing that future change.
docs/fork-divergence.md Record approved anchor narrowing, upstream crash-fixture retirement and compatible adaptations; parked branch list unchanged.
docs/fm-test-portable-shards.md Recompute current membership/weights from retained timing hints:161 scripts, seven defaults, eight shards; projections are not new measurements.
CONTRIBUTING.md Retain fork development/validation entry points and adopt current bounded concurrency instructions.
README.md Adopt current public capability descriptions without dropping fork integrations.
docs/configuration.md Keep single-owner schema pointers and all fork-local knobs while adding parent-channel/restart/intent references.
docs/watcher-continuity.md Document accepted follow-up/consumption distinction and retain fork signal/away continuity.
docs/captain-hold-lifecycle.md Retained call and outcome semantics coexist with fork design completion and preserving-refusal safety.
docs/supervision-protocols/pi.md Adopt current branch prompt/PR URL discipline and retain fork away ownership.
docs/verification/runtime-backends.md Preserve dated fork evidence alongside upstream verification; no universal live certification claim.
docs/verification/supervision.md Preserve fork signal disposition evidence and add upstream continuity evidence with current validation limitations.
docs/architecture.md Keep fork architecture links while adopting parent-channel and Pi lifetime ownership.
docs/scripts.md Catalog new upstream owners without removing fork launch, GBrain or dashboard entry points.

Additional changed contract files

File Reasoning
bin/fm-backend.sh Replace the metadata grep/tail/cut pipeline with a shell scan preserving last-key-wins values, reducing snapshot subprocess cost.
bin/fm-control.sh Accept explicit default effort as a reset for replacement launches; preserve harness/role validation before stopping anything.
bin/fm-ff-lib.sh Expose a settled-home hook only for updated/current live homes, never skipped ones; remote sync uses the same ancestry guards.
bin/fm-inactive-reconcile.sh Publish complete terminal child ledger lines promptly through the parent owner, share receipts with inactive detection and refuse teardown when delivery remains owed.
bin/fm-merge-outcome-lib.sh Use the shared parent-channel identity and append owner without changing locked PR-identity duplicate suppression.
bin/fm-promote.sh Carry original provenance-marked scout intent into ship instructions and distinguish new ship spec from old investigation context.
bin/fm-supervise-daemon.sh Report inability to publish daemon process identity instead of silently leaving the turn-end guard unable to prove ownership.
bin/fm-wake-lib.sh Prove away-daemon ownership using live PID plus process identity and away flag; keep freshness a separate caller obligation.
bin/fm-wake-drain.sh Diagnose stale acknowledgement cutoffs against already presented rows without acknowledging newer unseen arrivals.
docs/secondmate-parent-channel.md Document the canonical durable upward outcome and retained-call transport introduced in this prefix.
docs/verification/secondmate-parent-channel.md Keep upstream dated verification separate from this task current test evidence.
docs/agent-control.md Describe explicit model/effort reset and guarded restart paths through their executable owners.
docs/remote-secondmates.md Document primary-commit sync and parent-channel/restart routing without replacing remote cleanup ownership.
docs/turnend-guard.md Explain verified daemon ownership between one-shot watcher cycles while retaining freshness checks.
docs/orca-backend.md Carry updated validation evidence and runtime-owner pointers without granting agy Orca support.
docs/documentation-audiences.json Register new parent-channel owners and retain fork-only contract pointers; audience/pointer checks pass.
docs/fm-test-isolation-proof.md Record adopted family concurrency evidence without claiming unproven serial fixtures are safe to overlap.

Remaining contract rows

File Reasoning
bin/fm-captain-hold.sh Preserve retained-call transitions and design completion checks; publish hold occurrences and answers through the shared parent-channel owner without importing the unlanded authorship detector.
docs/pi-supervision-branch.md Document fresh conversations per main session, accepted follow-up delivery, scoped reports and recorded PR URLs while retaining fork away standby and durable outcome semantics.

Changed fixture contract reasoning

File Reasoning
tests/fixtures.sh Own shared valid intent/spec fixture content and scratch HOME/config isolation for spawn tests.
tests/fm-agy-adapter.test.sh Give intended launch paths valid synthetic intent/spec; preserve guard-specific raw, role and backend refusals.
tests/fm-design-skills.test.sh Use synthetic structured briefs; isolate helper and direct ship calls and observe the actual scratch trust entry.
tests/fm-issue-linkage.test.sh Keep issue-marker validation reachable with valid synthetic task content and isolate Claude trust writes.
tests/fm-dashboard-events.test.sh Keep additive event-wiring comparisons executable under the new task contract and isolate launch config.
tests/fm-spawn-worktree-settle.test.sh Preserve the valid task body while testing malformed/duplicate markers and issue prose; require the intended diagnostic.
tests/fm-cmux-claude-composer-live-e2e.test.sh Use disposable HOME/config and complete both scaffold subsections; remain explicitly opt-in with environment authentication.
tests/fm-launch-lib.test.sh Update the full expected Claude template for adopted feedback flags while retaining prompt and lifecycle assertions.
tests/fm-brief.test.sh Keep complete design/ship/continuation contract assertions and the negative old-rule pointer check.
tests/fixtures/fm-brief-no-issue.sha256 Regenerate eight fingerprints from actual canonical brief rendering after the accepted template changes.
tests/fm-calm-pi-extension.test.sh Correct the stock SDK oracle and working indicator expectation; keep production Calm unchanged and retain actual UI checks.
tests/fm-crew-state.test.sh Add terminal-anchor and full-detail identity counterexamples; separate the two missing-head fixture directories.
tests/fm-test-run.test.sh Supply the real timeout dependency in executing fixture constructors while preserving intentional absent-helper and arm-failure cases.
tests/fm-backlog-handoff.test.sh Use the upstream shared crash injector without allowing a pre-move orphan to continue the move.
tests/fm-bearings-snapshot.test.sh Retain fork timeouts, abandoned children and read-only cache assertions alongside new metadata-generation and large-document cases.
tests/fm-watch-triage.test.sh Exercise fork paused cadence separately from upstream live captain-held throttling and retain run-progress/write-deferral witnesses.
tests/fm-spawn-dispatch-profile.test.sh Keep model/config/continuation cases valid, with disposable stores and source-brief structural metadata assertions.

Active-divergence survival evidence

Each row names the executable regression witness; pending entries are not claimed passed.
The opt-in live dashboard/browser and real agy probes remain explicitly gated and are not implied by portable passes.

Active divergence Behavioral evidence
Agy crew adapter tests/fm-agy-adapter.test.sh: passed
Pinned ShellCheck download retry budget tests/fm-lint.test.sh: passed
LLM quota sidecar tests/fm-quota-sidecar.test.sh: passed
Scout completion gate reopened by a firstmate steer tests/fm-send-strict.test.sh: passed
Watcher restart hand-over tests/fm-watcher-lock.test.sh: passed
Watcher stop-signal disposition tests/fm-backend-herdr.test.sh: passed; tests/fm-watcher-lock.test.sh: passed
Run-progress wedge hold tests/fm-daemon.test.sh: passed; tests/fm-watch-triage.test.sh: passed
Watcher live declared-wait routing and self-widening recheck cadence tests/fm-daemon.test.sh: passed; tests/fm-watch-triage.test.sh: passed
Herdr pre-Enter footer read on a native working baseline tests/fm-backend-herdr.test.sh: passed
Remote job worker descendant reaping tests/fm-remote-job-orphan-reap.test.sh: passed; tests/fm-remote-job.test.sh: passed
Bounded remote job stdin capture tests/fm-remote-job.test.sh: passed
Default per-script bound on every test sweep tests/fm-on.test.sh: passed; tests/fm-test-run.test.sh: passed
Locale-independent test coverage comparisons tests/fm-test-run.test.sh: passed
Queued wakes remain a supervision requirement tests/fm-guard-stale-banner.test.sh: passed; tests/fm-turnend-guard.test.sh: passed; tests/fm-wake-queue.test.sh: passed
No-mistakes run attribution tests/fm-crew-state.test.sh: passed
Definition-of-done owner carries this fork's ready-to-validate handoff tests/fm-trigger-validation.test.sh: passed
A preserving refusal withdraws the pending backlog close tests/fm-backlog-atomicity.test.sh: passed
A watermark-capture failure keeps the published task record tests/fm-spawn-dispatch-profile.test.sh: passed
Fleet snapshot per-task timeout and abandoned child work tests/fm-bearings-snapshot.test.sh: passed; tests/fm-fleet-snapshot-view.test.sh: passed; tests/fm-home-summary-refresh.test.sh: passed
Pi away-mode supervision standby tests/fm-pi-watch-extension.test.sh: passed
Fork-local no-mistakes compliance-gate event scope tests/fm-no-mistakes-required-gate.test.sh: passed
Live pull-request body refresh before the compliance gate tests/fm-no-mistakes-required-gate.test.sh: passed
Merge-proof contract: one divergence accepted, one retired tests/fm-pr-merge.test.sh: passed
Upstream tracking mechanism tests/fm-upstream-status.test.sh: passed
Repository-local validation evidence Parsed config assertion: test.evidence.store_in_repo=false; pipeline intentionally not invoked.
Upstream-read-only posture in shared tracked docs tests/fm-agents-hard-rules.test.sh: passed
GBrain per-home knowledge memory tests/fm-bootstrap.test.sh: passed; tests/fm-brief.test.sh: passed; tests/fm-gbrain-capture.test.sh: passed; tests/fm-gbrain-health.test.sh: passed; tests/fm-gbrain-pin-check.test.sh: passed; tests/fm-gbrain-readonly-e2e.test.sh: gate skipped; tests/fm-recall.test.sh: passed; tests/fm-remote-secondmate-lifecycle-e2e.test.sh: passed
Fleet dashboard and agent-event instrumentation tests/fm-bearings-snapshot.test.sh: passed; tests/fm-dashboard-browser.test.sh: gate skipped; tests/fm-dashboard-events.test.sh: passed; tests/fm-dashboard-gbrain-ui.test.sh: passed; tests/fm-dashboard-gbrain.test.sh: passed; tests/fm-dashboard-history.test.sh: passed; tests/fm-dashboard-usage.test.sh: passed; tests/fm-dashboard.test.sh: passed

kunchenguid and others added 27 commits September 2, 2026 01:46
…nchenguid#3505)

* fix(bearings): keep active children underway beside a captain hold

Project each readable home's active children into Underway independently of the home-level captain-decision classification so a hold no longer hides live work.

* no-mistakes(review): Preserve Underway repos and disclose child truncation

* no-mistakes(review): Fall back to task project for Underway repos

* no-mistakes(ci): Updated the stock macOS Bash CI assertion from 44 to 45 Bearings tests, matching the newly added behavioral regression. Verified all 45 tests pass under /bin/bash, Bash syntax checks pass, and git diff validation is clean
…enguid#3513)

* fix(pi): settle watcher delivery on Pi accepting the follow-up

A follow-up queued while main is streaming joins the running run without
ever raising before_agent_start, so waiting on that event before clearing
the successor pipeline (kunchenguid#3498) stalled every later actionable close: no
successor started, no wake was delivered or offered to the branch, and the
turn-end guard woke main to re-arm by hand after every close.

The pipeline now settles once Pi accepts the follow-up. Consumption is
observed at before_agent_start for an idle main and at the user
message_start for a streaming main, and decides only what a replacement
session (/new, /resume, /fork, reload) replays. An exhausted restoration
delivers its typed failure without launching an arm past the retry bound,
which the stall had hidden. The replacement-coordinator map is typed so the
strict no-emit typecheck passes again.

Tests: the doubles no longer raise before_agent_start for a streaming send,
a portable regression drives two actionable closes while main streams and
proves the successor chain plus consumption-scoped replay, and a
credential-free real-SDK probe pins Pi's event contract for both the
streaming and the idle follow-up.

Claude-Session: https://claude.ai/code/session_01QJjTsUvKkWAwLGNoncaZ3a

* fix(pi): retry a verified successor that fails during wake delivery

A verified successor can exit while the wake it was started for is still
being delivered, most plausibly during a branch turn that holds the
settlement for minutes. Its failure close arrived while the pipeline's
single-flight guard was set, so the close handler skipped the retry, and
the pipeline's end no longer launched an arm, which left the live
generation with no watcher and no retry timer.

The close handler now records that failure when the child had reported
readiness and was not retired by the restoration itself, and the pipeline
runs the ordinary bounded, lock-checked retry for it once the delivery
settles. A restoration started for a later pending supersedes it, and an
exhausted restoration still hands repair to main without a further arm.

The regression holds a branch settlement open while the verified
successor exits with a failure and proves one retry watcher starts after
the settlement releases, none while it is held.

Claude-Session: https://claude.ai/code/session_01QJjTsUvKkWAwLGNoncaZ3a
* fix(bin): bound repeat stale wakes for a parked but live worker

A worker parked on a declared wait - `paused:` for an external or pipeline
wait, or a verified `captain-held` transfer - kept waking firstmate far inside
FM_PAUSE_RESURFACE_SECS. Observed as five consecutive alarms on one
captain-held worker and dozens across a day on a pipeline wait, and reported
upstream as four wakes in 75 minutes against a 3600s window.

pause_state_class deliberately answers `none` for a still-live agent even under
a declared wait, so a worker genuinely waiting on a decision is never silenced.
That classification is correct and is left alone; it routes every parked but
live worker through surface_nonterminal_stale on first sight of each distinct
stale hash, and an idle parked pane still churns its hash on a clock or a token
counter without changing what is being waited on.

Two places let that churn re-alarm:

- surface_nonterminal_stale queued the wake BEFORE consulting whether a wait was
  declared, then wrote `.paused-resurfaced-<key>` - the very throttle that should
  have suppressed it. The throttle was never read on this path and was advanced
  by the wake it should have prevented.
- The hash-change path cleared that throttle through clear_pause_tracking
  whenever the classification came back `none`, so each tick also bought the same
  declared wait a fresh window. Fixing only the first site changes nothing.

Read the throttle before anything is queued and advance it only on a wake that
really fires, and on the hash-change path reset only the per-hash bookkeeping
while the declaration still stands, via a clear_stale_hash_tracking split so
neither half of clear_pause_tracking is duplicated. The throttle is keyed to the
declaration, not to the pane.

First sight still wakes, so an inconclusive state is still inspected, and the
window's end still re-surfaces once, so a forgotten wait cannot rot invisibly -
noise traded for a bounded cadence, never for silence. The wake identity stays
the plain `stale: <win>` the away-mode handoff depends on.

Tests cover both observed forms and were confirmed to fail against three
deliberate breaks: each site reverted on its own, and a re-surface that never
fires again.

* fix(document): Clarify declared-wait wake cadence documentation

* fix(ci): Captain, fixed the stale-throttle inheritance: cadence markers now bind to the current wait declaration, so replacement paused and captain-held waits each emit their first plain `stale:` wake. Added behavioral coverage for both forms. Bite proof failed as expected when identity matching was removed, then passed after restoration. Full watcher triage suite, `bin/fm-lint.sh`, syntax checks, and diff checks pass. Changes remain uncommitted for the outer executor

* fix(ci): Captain, fixed the confirmed Greptile finding. `resurface_absorbed` now applies a throttle only when its stored declaration scope matches the current wait, so replacement `paused:` and `captain-held` waits surface immediately without changing classification. Added executable coverage for both absorbed forms. Bite proof failed before the fix at the intended assertion; afterward the full watcher triage suite, `bin/fm-lint.sh`, shell syntax checks, and `git diff --check` passed
…er (kunchenguid#3567)

* fix(turnend): accept the away-mode daemon as the supervision owner

While state/.afk exists the away-mode daemon owns supervision and runs
bin/fm-watch.sh one-shot: the watcher exits on every wake and the daemon
starts its replacement. The turn-end guard tested for a live watcher
process holding the watch lock at that instant, so a turn boundary that
landed in the hand-off blocked with "TURN WOULD END BLIND" while
supervision was completely healthy, costing a full handling turn each
time.

Reproduced with the real daemon wrapping the real watcher and the real
guard sampling the same home: 6 of 40 samples blocked, every one of them
with the daemon alive and the beacon 2-3 seconds old, and a new watcher
pid on each cycle. After the fix the same reproduction blocks 0 of 40,
and killing the daemon and its watcher (away mode still on, beacon still
fresh) blocks again.

The guard now accepts a live, identity-matched daemon holding this home
as proof of supervision while away mode is active. The identity match is
the same discipline the watcher lock uses, so a recycled pid or a lock
left by a killed daemon proves nothing. The fresh-beacon half of the
predicate is unchanged: a daemon that stops restarting its watcher still
blocks once the beacon passes grace, a home with no supervisor blocks
exactly as before, and with away mode off the strict watcher predicate is
untouched.

The predicate reads only durable state, so it behaves identically for
every primary harness and runtime backend.

* no-mistakes(document): clarify away-mode daemon supervision proof and test coverage

* no-mistakes(document): generalize stale turn-end predicate summary in architecture.md
…unchenguid#3582)

* fix(backlog): omit markdown file for beads probes

* no-mistakes(document): Narrow backlog addressing doc to mutations for backend-aware probes

* no-mistakes(ci): Fixed the Greptile P2 review comment (the only failing check) on tests/fm-backlog-atomicity.test.sh. The comment correctly noted that an exported TASKS_AXI_BACKEND environment variable would inherit into the spawned scripts and, because fm_tasks_axi_backend gives it top precedence, override each test case's .tasks.toml backend fixture — making the backend-specific argv assertions fail for environmental reasons. Fix: unset TASKS_AXI_BACKEND in the test harness right after sourcing tests/lib.sh, with a comment explaining why, so every case deterministically exercises its declared backend (4 lines added; no production code touched). Verified: reproduced the leak before the fix (TASKS_AXI_BACKEND=beads made the markdown dispatch case fail with 'beads show failed', exactly the reported failure mode); after the fix the full suite passes (0 failures, exit 0) both with and without TASKS_AXI_BACKEND=beads exported. The added lines are shellcheck-clean (the only shellcheck note, SC1091 on the lib.sh source line, pre-exists this change)
…chenguid#3589)

The supervision branch's verdict rule escalated every outcome that
answered a captain request, so "the work started" and "still working"
notes reached the captain with nothing to look at. The rule now keeps a
finished result of requested work captain-facing, even when healthy, and
treats start or still-working updates that bring no new artifact,
finding, or decision as routine. The captain list for review-ready PRs,
ask-user findings, exhausted blockers, credentials, and destructive or
security-sensitive cases is unchanged, as are the unsolicited-routine,
silent-fleet-review, and doubt-chooses-captain rules.

The fm_branch_report tool description and the two docs that restated the
old unconditional rule now point at the prompt's "Verdict: routine or
captain" section as the one owner instead of carrying a second copy.
* fix(bin): never close a captain call during cleanup

A scout that held its own work item for the captain, which is what
captain-hold-lifecycle prefers ("hold the work item the question gates"),
was closed by bin/fm-teardown.sh's automatic backlog transition. The
completion gate passed, cleanup ran, and the captain's question moved to
Done with no recorded answer: the one thing the policy says must never
happen. `tasks-axi done` closes a held row silently, and nothing in
teardown asked whether the row was the captain's own call.

bin/fm-captain-hold.sh gains the read-only `open` predicate: exit 0 when
the task is still an open captain call, 1 when it is not, 2 when that
cannot be established. It reads the row through the transition library's
backend-aware probe, so it addresses the same backlog teardown does; the
script's other commands now address the configured data directory the
same way instead of FM_HOME, which also fixes captain holds in a home
with a relocated data directory.

Teardown asks `open` before any destructive step and refuses on 2. On 0
only the close changes: after cleanup and still under the task's own
lock, the row gets one "Deliverable of the finished work" line at the end
of its body and returns to Queued through `tasks-axi reopen`, keeping its
hold, so it lands in Captain's Call instead of reading as work under way.
--force does not lift this: it authorizes discarding unlanded work, never
the captain's question. The deliverable goes into the body because
`tasks-axi update --report` rewrites the title of a row that is not Done.

The crash window reuses the pending-close record teardown already stages:
a `mode=retain` line makes the existing replay record the deliverable and
reopen instead of closing, with the same validator, stale-generation
check, cleanup-incomplete marking, and non-blocking bootstrap lock as an
ordinary close. A retained row the captain answered first simply retires
the record. No parallel record type, recovery command, or second bootstrap
loop is introduced.

Regressions run the real executables: the captain-held scout survives
cleanup queued, held, with its deliverable and on the board, only
`answer` closes it, --force keeps it open, and an ordinary scout still
closes with its report; an interrupted cleanup leaves the row untouched
and the next session start retains it; a relocated backlog keeps the
retention in its one configured file; and a ship row whose hold cannot be
read refuses cleanup before anything destructive.

Claude-Session: https://claude.ai/code/session_01FqdTiHCwTqrAQrz8K2y4Np

* no-mistakes(review): Serialize captain holds and fix backend-aware listing

* no-mistakes(document): Update captain-call retention documentation

* no-mistakes(document): Fix relocated captain-hold backlog diagnostics
…uid#3592)

* fix(bin): deliver every secondmate outcome on the parent channel from the recording scripts

A secondmate's captain-facing outcomes could miss: the mate model addressed
the captain in its own unread chat instead of appending to the parent
channel, and a PR-ready report, a finding, a decision, a blocker, and a
failure all depended on that one remembered append. Make delivery
structural, so the parent channel never depends on the model:

- bin/fm-parent-channel-lib.sh is the one owner of channel resolution and
  exact-line append-once; the merge outcome path and the inactive-outcome
  scan now publish through it instead of two private copies.
- bin/fm-inactive-reconcile.sh gains a ledger-first path that runs on every
  watcher poll in a secondmate home: a direct child's whole terminal done or
  failed line is delivered at once with its note, recorded PR, mode, merge
  posture, and scout report pointer, keyed and receipted so it is delivered
  once, and the inactive path yields to it. `report <task-id>` runs the same
  delivery for a caller holding the child's meta lock.
- bin/fm-pr-check.sh publishes the PR-ready line with the canonical URL at
  registration.
- bin/fm-captain-hold.sh publishes a hold and its answer, keyed by task id
  and resolution-record count, with no new persisted state.
- bin/fm-teardown.sh delivers the child's final line before removing its
  record and refuses, retaining every record, while the channel cannot be
  written.
- The charter opens with the parent-channel rule and confines the mate's own
  appends to judgement; AGENTS.md carries the carve-out at the persona
  address rule and the escalation list.

docs/secondmate-parent-channel.md records the design and its coverage, and
docs/verification/secondmate-parent-channel.md records the live run with real
tmux panes and both real watchers delivering every line with no model.
Supersedes kunchenguid#3569.

* no-mistakes(review): Fix parent outcome retries and reconciliation locking

* no-mistakes(review): Prevent busy children from starving ledger delivery

* no-mistakes(review): Correct ledger metadata and hold occurrence handling

* no-mistakes(review): Disambiguate ledger outcomes and normalize hold reasons

* no-mistakes(review): Close ledger races and preserve teardown records

* no-mistakes(document): Correct parent-channel receipt and scanner documentation

* no-mistakes(lint): Quote done arguments for ShellCheck compliance

* no-mistakes(ci): Fixed both CI failures. Updated GOTMP teardown fixtures for the new final-outcome reporter and isolated them from host tmux state. Updated the PR security assertion to distinguish the accepted PR-ready line from duplicate merge outcomes. Verified with both failing test suites, bash syntax checks, and git diff checks

* no-mistakes(ci): Fixed Greptile’s duplicate-delivery race in bin/fm-inactive-reconcile.sh. Ledger events now claim matching already-delivered inactive receipts using the prior status fingerprint, preventing duplicate parent reports while preserving later same-state completions. Added behavioral regression coverage. Verified inactive-reconcile tests, project lint, documentation audience checks, syntax, and diff checks. Teardown tests passed relevant cases before the documented pre-existing herdr-preflight-missing-adapter failure
* fix(bin): sync remote second-mate homes to the parent primary commit

Session start and remote launch pointed a remote second-mate home at whatever
Firstmate copy its own host kept, so a home that had already advanced past that
copy refused as a non-fast-forward and every other home stopped at the host's
older commit while the primary ran ahead.

The parent now resolves ITS primary default-branch commit with the existing
helper and hands that commit to the host on both paths. Because a remote home
is a standalone clone, the host imports that one commit before advancing -
already present, else from that host's Firstmate copy without moving it, else
from the home's own origin - and then runs the SAME ff_target guards a local
home gets, so dirty, diverged, feature-branch, and unresolvable targets skip
untouched and the ancestry rules keep one owner. An unimportable target now
names /updatefirstmate instead of failing opaquely, and a host still running an
older Firstmate copy is reported the same way rather than echoing a bare
refusal.

The host-local launch leg no longer re-runs its own secondmate sync, so the
spawn it drives cannot re-target that host's copy after the parent has already
converged the home.

/updatefirstmate is unchanged: it still refreshes the remote code root from that
host's origin and then syncs the home to that refreshed copy, which is what the
sync call with no target commit means.

* no-mistakes(document): Document primary-targeted remote secondmate synchronization
)

* fix(bin): split brief task into captain intent and firstmate spec

Keep no-mistakes --intent as the captain's ask plus later captain words, not the build spec or worker tradeoffs.

* fix(bin): stop task-subsection copies at the next heading

Promotion was swallowing the scout Setup contract into Firstmate spec, and pre-subsection briefs lost their # Task body.

* no-mistakes(review): Validate brief content and preserve nested specifications

* no-mistakes(review): Scope placeholder validation to scaffold-only subsection bodies

* no-mistakes(review): Ignore fenced subsection headings during brief validation

* no-mistakes(review): Preserve captain intent across scout promotion

* no-mistakes(review): Enforce safe intent boundaries for legacy promotions

* no-mistakes(review): Allow marked legacy intent and reject empty promotions

* no-mistakes(review): Scope task parsing and overlay legacy intent contracts

* no-mistakes(review): Overlay current intent contract for all no-mistakes spawns

* no-mistakes(review): Preserve later captain clarifications in intent overlays

* no-mistakes(document): Document brief intent enforcement and ownership

* no-mistakes(ci): Updated spawn-related test fixtures to use valid Captain intent and Firstmate spec subsections, corrected launch-path expectations to launch-brief.md, and resolved ShellCheck quoting findings. Verified with fm-lint.sh and 15 affected behavior tests, including real Herdr tests; all passed

* no-mistakes(ci): Updated stale spawn/promotion fixtures in the Muse, Orca, secondmate-harness, and public-followup suites to provide valid Captain's intent and Firstmate spec subsections. Verified full Orca and secondmate-harness suites, targeted public-followup promotion behavior, Bash syntax, diff checks, and fm-lint
…guid#3600)

* fix(pi): start a new supervision branch conversation per main session

The supervision branch reopened one recorded conversation forever, so
every main session start reloaded the current generated prompt and then
weeks of accumulated thread, where a superseded rule could still outweigh
today's.

The branch conversation is now scoped to one main session: the session
generation owns the recorded conversation, so a cold start, /new,
/resume, /fork, or a reload always builds a new one, while a rebuild
inside one session (a model or effort change) still continues that
session's own conversation.

The dialog mirror re-anchors with it. Its durable cursor records what the
previous branch conversation received, so a /resume or reload - which
keeps main's own session file - would otherwise leave the new branch
blind to dialog main itself still has. The reset is bounded by the
current main session, and the cursor keeps advancing incrementally within
it. The durable outcome store and its processed marker are untouched, so
unacknowledged captain-facing outcomes still re-present on the new main
session.

* no-mistakes(document): Document fresh Pi supervision conversations

* no-mistakes(ci): Fixed the flaky concurrent inbox failure. Lock acquisition now retries when a competing lock disappears between a failed claim and inspection. Added a behavioral regression covering that race. Verified the full inbox test four times, project lint, and git diff checks
* feat(update): restart second mates whose instructions changed

/updatefirstmate pulled new bytes onto disk and then asked each advanced
second mate to re-read them. A running agent holds AGENTS.md and every
loaded skill frozen from launch and no verified harness offers a reload,
so that steer could not reach a loaded skill at all and left the mate
holding two contradictory copies of its own job description.

An eligible mate is now restarted instead, in the same home and endpoint,
through the existing transactional relaunch. The restart is gated on the
mate first writing down the open work it holds only in conversation - the
open-record half of /stow, never its memory sweeps - so an unregistered
captain call is flushed before the conversation is spent. Anything that
leaves the reload unprovable falls back to the old re-read message and is
reported as exactly that, never as a clean reload.

Remote mates take the same path: fm-remote-secondmate-control.sh gains a
relaunch verb whose host-local leg runs that same control plane, since the
mate is an ordinary local secondmate from its host's point of view. The
primary resolves the profile and passes it explicitly, because
config/secondmate-harness is not inherited and the file on that host
belongs to a different home.

fm-update.sh now splits its advanced live mates into a restart set and a
nudge residual, and both sets require a changed instruction surface, which
also closes the over-nudge against the session-start sweep. Restart is
stricter still: a bin/-only advance reloads itself on the next call, so it
never costs a conversation.

Colocated tests cover the gating, the persist-then-restart order, the
task-subset persist request, each unsafe fallback, the remote hop, and the
remote sync's new instruction-surface report.

* no-mistakes(review): Fix restart correlation, concurrent waits, and lifecycle reporting

* no-mistakes(review): Parallelize relaunches and classify replacement incarnations

* no-mistakes(review): Gate restart actions on live agent state

* no-mistakes(review): Handle failed restart workers without hanging

* no-mistakes(review): Nudge legacy remotes and preserve persist recovery

* no-mistakes(review): Document one-time secondmate restart rollout

* no-mistakes(review): Honor arrived replies and refresh remote profiles

* no-mistakes(review): Revert remote parent profile reconciliation

* no-mistakes(review): Reset remote profile defaults and honor published results

* no-mistakes(review): Preserve fallback nudges for unverifiable secondmates

* no-mistakes(document): Document second-mate restart update flow

* no-mistakes(lint): Fix ShellCheck warnings in restart scripts
…id#3644)

* perf(tests): route gate verification through the bounded concurrent runner

Local validation was the pipeline's dominant cost: across 67 recorded
no-mistakes agent sessions on this repo, 99.3% of command execution was
`bash tests/*.test.sh`, run strictly one script at a time, and 2% of those
calls were killed by an agent-guessed timeout and paid for twice.

Three changes, each measured:

- `.no-mistakes.yaml` pins `commands.test` to
  `bin/fm-test-run.sh --changed --exclude-family real-herdr-gated`. The runner
  already owns changed-file selection, bounded concurrency, the refusal of
  unproven scripts, and a generous automatic per-script bound, so the gate's
  baseline is neither a serial chain nor a guessed timeout. It stays
  intent-targeted - the Test step still runs its evidence agent on top - and
  excludes the live-Herdr family the required Herdr lane owns.

- `bin/fm-test-run.sh` gives a plain list of script paths the same bounded
  automatic scheduler and automatic bound that `--changed` gets. Naming several
  subjects is how a verification round asks for exactly those scripts. The
  curated selections are untouched: `--lane` still composes CI shards whose
  serial lane must stay serial, `--family` is what the required Herdr lane runs,
  and `--all` stays a deliberate complete regression.

- `pr-forge` is admitted to the concurrent-safe family registry on two
  consecutive clean proofs. `docs/fm-test-isolation-proof.md` records those,
  and records `secondmate` and `session-bootstrap` as refused with the exact
  script and reason each failed on, so the refusals are actionable rather than
  silent.

Measured on this host, 0 failures on both sides:

  verification round, 4 scripts   448s chained -> 231s through the runner (-48%)
  pr-forge family                 409.2s at 1 worker -> 237.9s at 4 (1.72x)
  watcher-wake-lock family        1311.1s at 1 worker -> 539.3s at 4 (2.43x)

A fourth lever was implemented and then removed because the measurement
refused it: raising the bounded-wait sample interval from 0.1s to 0.5s made
`fm-watch-triage.test.sh` slower, 435s and 440s against 390s and 393s
unchanged, back to back. Those sleeps are not overhead added to the clock -
they are how a test waits for a subject moving on fm-watch.sh's own one-second
cadence - so sampling less often only delays detection. It also broke
`fm-watcher-lock.test.sh`, which catches a transient rather than waiting for a
settled condition. CONTRIBUTING.md records that result so the experiment is not
repeated.

* no-mistakes(review): Separate concurrent runs by isolation proof family

* no-mistakes(review): Limit automatic timeouts to changed-file validation

* no-mistakes(document): Clarify validation concurrency documentation
* fix: copy PR URLs from records or abstain, never assemble them

Supervision reported a plausible but dead PR link three times because its
prompt demanded a full https:// URL at a moment when only a PR number was
observable, so the model assembled an owner/repository from memory, and the PR
check then accepted that URL and wrote it into the task record, after which the
model kept defending its own tool-endorsed guess over the worker's real link.

Three changes close that chain without any live forge lookup, so private
forges are treated exactly like public ones:

- bin/fm-branch-prompt.sh no longer mandates a URL. Its new "PR identity: copy
  or abstain" section requires a URL to be copied verbatim from a durable
  record (the done: PR <url> status line, pr= metadata, or the backlog note),
  forbids assembling owner, repository, host, or number from memory, and has
  the branch report only the identifier it actually holds when no record names
  the URL yet, leaving the PR check unarmed until the worker's ready line
  arrives. AGENTS.md section 7 and 9 carry the same copy-or-abstain rule for
  main in place of the bare full-URL mandate.

- Worker briefs (bin/fm-brief.sh, ship and scout rules) require the full
  https:// URL wherever a PR is mentioned - status line, terminal, or summary -
  never a bare "PR 108", so the link is in view as early as the number is.

- bin/fm-pr-check.sh refuses, offline and before any side effect, a URL that
  the task's own done lines contradict, printing both spellings; a log naming
  no URL still records the argument as before. fm_pr_status_ready_urls in
  bin/fm-pr-lib.sh owns reading those lines. The refusal also reaches
  bin/fm-pr-merge.sh, so nothing merges under a contradicted URL.

Tests cover the offline refusal with zero side effects, the recorded spelling
being accepted, markdown-wrapped and punctuated URLs, working lines not
counting, the merge wrapper propagation, a self-hosted merge request with no
forge call, the prompt carrying the rule, and the brief carrying the worker
rule.

* no-mistakes(review): Remove stale PR URL enforcement

* no-mistakes(ci): Removed backlog notes as an accepted PR identity source. PR URLs may now be copied only from the task’s `done: PR <url>` status or canonical `pr=` metadata; otherwise supervision reports only the known identifier and leaves PR checking unarmed. Updated related guidance/docs and verified with branch-supervision tests, brief tests, ShellCheck, and `git diff --check`
…uid#3661)

* fix(bin): disable Claude's feedback-draft flow for fleet-launched agents

Scope --settings '{"feedbackDrafts":"off"}' to every Firstmate-launched
Claude crewmate and secondmate, so /bug and /feedback never queue or
submit a bug report on the captain's behalf. feedbackDrafts is the
documented settings key (Claude Code changelog 2.1.247); the
per-launch CLI flag never touches the captain's global settings.json.

Claude-Session: https://claude.ai/code/session_01XYAXXzr4oZx9NjZb1veeE3

* no-mistakes(review): Prevent managed settings from re-enabling Claude feedback drafts

* no-mistakes(document): Fix Claude feedback documentation formatting

* fix(bin): layer both feedback-draft controls for defense in depth

The prior --settings-only fix can be overridden by a managed Claude
settings policy (feedbackDrafts precedence). Keep CLAUDE_CODE_SEND_FEEDBACK=0
alongside --settings '{"feedbackDrafts":"off"}': either control alone
disables the SendFeedback tool, so a managed override of one still
leaves the other in force.

Claude-Session: https://claude.ai/code/session_01XYAXXzr4oZx9NjZb1veeE3

* no-mistakes(document): Document Claude feedback-draft suppression ownership
…guid#3662)

* perf(tests): admit three more families to concurrent validation

The three families that `docs/fm-test-isolation-proof.md` recorded as refused
were not refused for concurrency. Each blocker was a test that decided a
property by wall clock, or a script filed where it cannot run. Fixing those
three things admits all three families and recovers 28.6 minutes of local
validation with no assertion removed or weakened.

- `tests/fm-backlog-handoff.test.sh` injected its pre-move crash by killing the
  handoff, sleeping a fixed second, then delegating the move to the real
  binary. Nothing ever killed the fake, so on a host slow enough for the case's
  next assertions to take longer than a second, the orphan woke and completed
  the very move the case requires left undone, and recovery then failed with
  `Task "pre-move-crash" not found in this backlog`. Watching the two backlogs
  during the injected crash showed exactly that, the item moving one second
  after the crash. All four crash injections in the file now go through a new
  `fm_fake_crash_injector` shim that signals the target and returns only once
  it is observably gone, and the pre-move fake never delegates the move at all.

- `tests/fm-session-start.test.sh` proved the startup digest does not block on
  a slow current-state read by timing the whole digest against a fixed
  eight-second sleep, which a loaded host exceeds without the property being
  violated. It now holds that read open until the case releases it and asserts,
  the moment the digest returns, that the read has not finished. A digest that
  waited would wait indefinitely rather than for an interval a slow host can
  out-run, so the assertion is stronger than the bound it replaces. Its scan
  budget moves to the maximum, because the old value left two seconds of margin
  over the fixed sleep and measured the host rather than the deadline that
  `tests/fm-inactive-reconcile.test.sh` owns.

- `fm-backend-herdr-focus-flash-e2e` was filed in the family map's catch-all,
  which put it in the portable serial lane, where Linux CI gate-skips it: that
  real-Herdr regression was running nowhere. It moves to `real-herdr-gated` and
  the required Herdr lane. `fm-claude-stop-autoarm-live-e2e` gate-skips on its
  opt-in variable and moves to `live-harness-optin`.

The 28 remaining ungrouped scripts become an enumerated `standalone` family
instead of admitting `unclassified` itself. `unclassified` is the family map's
`*)` arm, so admitting it would silently grant concurrency to every test added
afterwards, which is exactly the population with no proof. A new test still
lands in `unclassified` and stays serial, and `tests/fm-test-run.test.sh`
covers that split behaviorally.

Each family passes two consecutive four-worker proofs with zero failures. On
the production runner, `secondmate` goes 1233.1s to 453.4s, `session-bootstrap`
756.4s to 286.4s, and `standalone` 724.6s to 261.1s: 2.71x overall and 1713.2s
recovered. The whole suite runs 177 scripts in 52.6 minutes of wall clock
against 121 minutes of summed script time.

* no-mistakes(document): Refresh concurrent validation and shard documentation

* no-mistakes(ci): Fixed the real-Herdr focus-flash E2E race exposed by reclassification. Part C now starts its persistent child atomically via `pane run` and verifies stable child identity through Herdr’s public `process-info` interface, avoiding the racy send-text/send-keys sequence and platform-specific `ps` matching. Verified with bash syntax checking, ShellCheck, git diff checks, and the complete E2E test on Herdr 0.8.2
* feat(brief): structure no-mistakes ask-user escalation as event + snapshot file

Crewmates escalating a no-mistakes ask-user gate now report one status
event naming every finding id plus a snapshot file holding the gate's
axi finding records verbatim (id, severity, file, line, description,
authority), using the same shape even for a single finding. The status
line never paraphrases. The format is defined once in fm-dod-lib.sh and
rendered into both the scout and ship rule 6 in fm-brief.sh, so a
promoted scout - whose rule 6 fm-promote.sh preserves unchanged - gets
the identical contract as a freshly-spawned no-mistakes ship worker.

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

* no-mistakes(review): Preserve ask-user escalation output contract

* no-mistakes(review): Align escalation format test expectation

* no-mistakes(review): Scope ask-user escalation instructions correctly

* no-mistakes(review): Remove ask-user from generic decision rules

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* fix(bin): require a self-sufficient no-mistakes intent

A no-mistakes worker's --intent is only as useful as the string it
passes. PR kunchenguid#3604 shipped with an intent that was only "do 1, 2, 3, 7
from the report": the real contract lived in a private scout report and
never reached --intent, so nobody holding that string plus the codebase
could have derived the specification.

This is pure instruction at the contract's one owner; no spawn-side or
promotion-side check is added.

- bin/fm-dod-lib.sh: the generated no-mistakes Definition of done now
  states that the --intent string must be self-sufficient (the string
  plus the codebase reconstructs roughly the same specification) and
  tells the worker to write the substance of any report, decision, or
  PR the captain's intent refers to into --intent rather than the
  pointer, while Firstmate build instructions and the worker's own
  decisions still stay out. The spawn-time overlay points back at that
  rule so its "supersedes" wording cannot cancel it, and the header's
  owner statement carries the rule.
- AGENTS.md section 11 and bin/fm-brief.sh's header ask Firstmate to
  include the substance of referenced material when filling
  ## Captain's intent, and section 11 points at the owner of the rule.
- tests/fm-brief.test.sh and tests/fm-task-delivery.test.sh assert the
  rendered brief and launch contract carry the rule.

Claude-Session: https://claude.ai/code/session_01YMhEe42q7BAAoN6RxNuzim

* no-mistakes(document): Replace incident-specific intent test commentary
* Speed local fleet snapshot composition

* no-mistakes(review): Stabilize task inventory during concurrent snapshot composition

* no-mistakes(document): Document local snapshot observation concurrency

* no-mistakes(ci): Fixed CI failures by making empty task manifests compatible with stock macOS Bash 3.2, snapshotting task metadata before concurrent observations to prevent generation drift, strengthening the behavioral race regression, and updating the stock-Bash Bearings test count to 45. Verified fleet snapshot tests (15), Bearings tests (45), workflow lint tests, project lint, Bash 3.2 parsing, and diff checks

* no-mistakes(ci): Fixed the Linux CI failure caused by passing large backlog/task JSON through jq command-line arguments, which exceeded the per-argument size limit. Both inventory projections now stream large JSON inputs through stdin. Verified with fm-bearings-snapshot.test.sh (45 tests), fm-fleet-snapshot-view.test.sh (15 tests), Bash syntax, and git diff checks

* no-mistakes(ci): Fixed concurrent task teardown during metadata capture: vanished metadata is now omitted while genuine copy failures remain fatal. Added a deterministic public Bearings regression test and updated CI’s expected test count. Verified with the full Bearings suite, workflow-lint suite, Bash syntax checks, and git diff checks

* no-mistakes(ci): Fixed PR-caused CI and review issues: streamed large fleet JSON through jq stdin to avoid Linux argument limits, kept crew-state reads bound to captured metadata generations, and strengthened the behavioral race test. Bearings (46 tests), fleet snapshot (15 tests), crew-state, backend, lint, Bash syntax, and diff checks pass locally. Serial shard 5’s unrelated task-inbox segmentation fault appears infrastructural/flaky

* no-mistakes(ci): Fixed endpoint-state generation crossing by validating captured spawn_gen before and after local endpoint probes, falling back to exact metadata identity for legacy tasks. Stale probe results now become unknown instead of false unhealthy state. Added a behavioral relaunch-race regression test. Verified the full Bearings snapshot suite, shellcheck, bash syntax, and git diff checks

* fix(snapshot): keep live observations generation-coherent

* no-mistakes(review): Keep secondmate observations generation-bound without copying reports

* no-mistakes(document): Document generation-coherent snapshot observations

* test(bearings): measure local read overlap instead of wall-clock budget

The large-local-snapshot regression asserted that a whole snapshot
composed in under five seconds. That bound measures how loaded the host
is, not whether the per-task reads actually overlap, so it failed
intermittently on a contended machine: one run in six on a box at load
16-20, landing exactly on the five second boundary.

Time a serialized run and a concurrent run of the same workload instead
and require the concurrent one to save at least two seconds. Both runs
pay the same composition overhead, so the difference isolates the
overlap this change delivers. Five one-second reads serialize into five
seconds and overlap into about one, and re-serializing the reads
collapses the saving to roughly zero, so the assertion still fails
loudly if the concurrency regresses.

Also bump the pinned Bearings test count to 48, since rebasing onto the
current default branch picked up its captain-hold test.

* no-mistakes(review): Restore JSON-derived decision flags

* no-mistakes(review): Unify status-derived snapshot observations

* no-mistakes(ci): Updated the stock macOS Bash CI check’s Bearings test count from 48 to 49. Verified the full Bearings suite passes and emits exactly 49 TAP successes; git diff checks pass
* fix(bin): stop the supervision branch's stale-ack and ghost-report loops

Clean-slate implementation of the four authorized recommendations from the
supervision-ghost-retrigger analysis (items 1, 2, 3, and 7), in their minimal
form, superseding PR kunchenguid#3604:

- fm_branch_report refuses a task the wake being handled never named. The
  extension fixes the reportable task set from the eligible rows before each
  prompt (signal and stale rows resolve to their tasks, a heartbeat allows any
  task with a live record, fleet is always allowed), so a report typed from
  memory about a task whose records teardown already removed is never stored
  or delivered.
- An acknowledgement that consumes nothing says "nothing was acknowledged
  through N" and prints the exact --ack-through / --recovery-generation
  command for the current presented wake, instead of "re-run the drain",
  which re-fed the same stale acknowledgement in a loop.
- bin/fm-guard.sh no longer tells the branch actor to drain queued wakes
  while it is handling them; it names the granted rows instead.
- Teardown removes state/.<task>.branch-outcome-index for ordinary tasks and
  descendants; the index rebuild and the append-side index write both skip a
  task with neither a live record nor a status log, so the branch's report of
  a teardown it just performed is stored without recreating the index.

No new locking, no spawn-generation binding, and no retired-task refusal: the
branch can still report the outcome of a task it just tore down, and the
teardown test now proves that path end to end.

* fix(bin): narrow the branch report scope and guard silence to the minimal form

Apply the four review decisions on the clean-slate branch:

- A signal or stale prompt may report only the tasks its own rows resolve
  to; fleet is refused there too. A heartbeat review is not scoped by task
  at all, so the extension no longer tracks live task records and refuses
  nothing by task id during a fleet review.
- The outcome-index rebuild no longer skips retired tasks; the append-side
  skip alone keeps a torn-down task's index from being recreated.
- bin/fm-guard.sh keeps the queued-wakes warning silent for the branch actor
  instead of printing a replacement note.

* no-mistakes(document): Align supervision docs with scoped wake handling
* Fix fleet snapshot large JSON transport

* no-mistakes(review): Captain: file-back fleet snapshot transport safely

* no-mistakes(review): Captain: file-back parent summary aggregation

* no-mistakes(ci): Rebased the PR's three commits onto f4d7875 and resolved the fleet snapshot conflict while preserving the base's task-observation lifecycle. Fixed Greptile's valid finding by recursively removing the private mktemp transport directory, so future transport files cannot cause cleanup to fail. Verified with tests/fm-home-summary-refresh.test.sh, bin/fm-lint.sh, git diff --check, and ancestry checks. All passed; the fix remains as an uncommitted worktree change for the outer executor
…nguid#3681)

* fix(bin): recognize active pipeline fix rounds with unfetched run heads

A no-mistakes fix round advances the run head beyond the submitted head,
and the pipeline commits in its own checkout, so the task copy never
receives the new commit object. fm-crew-state's strict head rule rejected
the active row, the coarse runs-list scan skipped it and matched the
older failed row at the submitted head, and an active validation read as
failed (observed on model-routing-benchmark-hardening: active head
ac61c64 vs task copy at fb47636d).

fm_nm_runs_status_for_worktree in bin/fm-nm-run-lib.sh now owns
runs-ledger attribution: the branch's newest row alone decides, and a
newest row whose head cannot resolve locally is recognized only as a
provable pipeline-owned continuation - active (running) and anchored by
the immediately older row for the same branch having ended at exactly
this worktree's HEAD. The reader keeps the axi TOON as full detail for
that proven same-branch run. Unanchored, ancestor-anchored, and terminal
unresolvable rows stay unattributed, so branch-name coincidence and other
tasks' runs never match, and fm_nm_head_matches_worktree keeps its exact
prior semantics for teardown (verified by the full teardown suite).

Tests: reproduction regression for the unfetched active fix head (reads
working via full run-step detail), coarse-path continuation when axi
answers another branch, and negative controls for the unanchored active
row and the unresolvable terminal row with the historical fallback
preserved.

Ported onto upstream/main f4d7875, where kunchenguid#3194 independently added the
branch_sync custody exemption on the full axi-status path: both mechanisms
now coexist, each owning one surface (TOON custody on the full path, the
runs ledger on the coarse path). The port deletes the superseded coarse
scan-and-skip (nm_runs_status_for_branch) and its now caller-less helpers
(fm_nm_head_resolvable, nm_coarse_head_matches_worktree), renames the
exemption comment's "the one exemption" phrasing now that a second
complementary exemption exists, and points the stale
FM_CREW_STATE_RUNS_LIMIT comment at fm_nm_runs_status_for_worktree
(judge follow-up #1). The parent coarse-guard test's fixture is the
ledger-anchored continuation shape, so its expectation flips to the fixed
behavior (working via run-step, never the older failed row); a new
mismatched-anchor coarse negative control preserves that guard's original
no-anchor protection (pane answers, never the older row).

* no-mistakes(document): Clarify pipeline attribution documentation
…uid#3663)

* fix(bin): pre-register claude workspace trust for task worktrees

A claude crewmate launched into a fresh task worktree met Claude Code's
interactive workspace-trust dialog before it ever read its brief, and firstmate
could not answer it: the key plane carries only Enter, Escape, and C-c with no
arrow navigation, and the dialog's selection starts on "No, exit", so the
documented Enter recipe ended the session instead of accepting it. Two workers
wedged this way and were unblocked only by hand-seeding the trust store per
path.

--dangerously-skip-permissions does not cover that gate. `claude --help`
records the dialog as skipped only in non-interactive mode, through -p or a
non-TTY stdout, and a crewmate pane is interactive, so there is no launch flag
to reach for.

fm-spawn now pre-registers the worktree through bin/fm-claude-trust.sh in the
existing claude branch, before the project settings that the same gate would
otherwise block, and refuses the spawn when that write fails rather than
launching a worker that would wedge.

The scope test is the safety property and is structural rather than a path
policy: the path must be a linked git worktree, sharing the spawning project's
common dir, whose top level is exactly the resolved argument. Git is the ground
truth, so the argument is never trusted on its own word, and a primary
checkout, an unrelated repo, a worktree subdirectory, a plain directory, and a
home directory are each refused rather than warned about or skipped. A
treehouse or orca path prefix was deliberately avoided because treehouse's root
is configurable, which would make a prefix both wrong and a new policy surface.
One structural test covers both worktree providers.

tests/fm-claude-trust.test.sh pins both halves, including a case where HOME is
itself a valid linked worktree so the home guard is proven load-bearing rather
than passing vacuously, plus the spawn-level proof that a claude spawn trusts
its worktree and launches with the brief pointed at the same store.

The adapter reference no longer tells a firstmate to press Enter on that
dialog, and the shared trust reference now names every harness surface: which
harnesses gate, which suppress at launch, which dodge the gate, which now
pre-registers, and that a claude secondmate is excluded by design.

The spawn fixture runs each spawn against a throwaway HOME so the suite cannot
write the developer's real store, isolating through HOME rather than
CLAUDE_CONFIG_DIR because the spawn forwards a set CLAUDE_CONFIG_DIR onto the
launch command that launch-shape assertions read.

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

* fix(bin): create the staged trust store exclusively

The staged store was written to a predictable pid-based path with a plain
write, which follows a symlink. Where the Claude config directory is writable
by another local account, that account could pre-create the path as a symlink
and redirect the write into another file the launching user owns.

The staged name now carries random bytes and is created with an exclusive
"wx" open, so an existing path is refused outright instead of followed. The
happy-path test also asserts no staged store survives the rename.

The durability comment now states the residual window plainly: the readback
proves the entry landed, not that it survives, because a vendor session that
rewrites the whole store afterwards can still drop it and no lock closes that
window when the writer is Claude itself. The worker then meets the dialog and
stalls, which reaches firstmate as the ordinary stale wake rather than as
silent success.

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

* no-mistakes(review): neutralise CDPATH in claude trust scope guard

* no-mistakes(review): sandbox HOME in spawn tests, drop out-of-scope artifacts

* no-mistakes(review): refuse unresolvable git dir, compact store, fix secondmate doc

* no-mistakes(review): clear git env overrides, resolve symlinked store target

* no-mistakes(review): degrade without node, fix Pi gate claim, record trust proof

* no-mistakes(review): refuse without node, pin CLAUDE_CONFIG_DIR in spawn tests

* no-mistakes(review): refuse relative config dir and concurrent store modification

* no-mistakes(review): correct orca worktree claim, clean staged store on failure

* no-mistakes(review): restore pretty-printed store, correct trust dialog docs

* no-mistakes(review): arm trust gate before busy state to avoid orphans

* no-mistakes(document): record claude trust pre-registration in its owner docs

* no-mistakes(document): note orca limit for claude trust pre-registration

* no-mistakes(ci): Fixed the Greptile P1 on bin/fm-spawn.sh by moving the Claude trust gate earlier rather than adding cleanup machinery. Diagnosis: Greptile reported that when Claude trust registration fails on tmux/Zellij/cmux/non-projected Herdr, the exit runs after the backend endpoint and /tmp/fm-<id> were created, and the abort trap cleans neither. The endpoint half is pre-existing, deliberate architecture — the two refusals immediately above the gate (the 60s `treehouse get` timeout at fm-spawn.sh:2550 and `validate_spawn_worktree` at :2487) also exit with the endpoint live and direct the operator with "inspect window $T"; spawn_abort_cleanup only reclaims orca endpoints (already covered via ORCA_ABORT_CLEANUP) and herdr projections. The temp-root half was genuinely introduced by this PR: the gate was placed beside the busy-state arm, ~30 lines after `mkdir -p "$TASK_TMP/gotmp"`, and fm-teardown can only find that root through `tasktmp=` in a meta record a refused spawn never publishes. Root-cause fix (smallest correct change, no new subsystem): - bin/fm-spawn.sh — moved the `claude*` trust gate from inside the busy-arm block up to the first point $WT is known, immediately after the `freshen_spawn_worktree_base` block and before TASK_TMP creation, the STATE setup, and the relaunch `clear_relaunch_harness_wiring` retirement. A refusal now leaves no temp root, no retired relaunch wiring, and no busy record; only the endpoint remains, in the same class as the two refusals just above it. - bin/fm-spawn.sh — the refusal message now ends with "inspect window $T", matching the existing convention so control/teardown can identify the endpoint. $T is set for every backend on the non-secondmate path. - bin/fm-spawn.sh:196 — header note corrected from "before any state is armed" to "before any per-task state exists". - tests/fm-claude-trust.test.sh — the existing refused-spawn test's own comment claimed "before any task state exists" but only asserted busy state. Renamed to test_refused_spawn_leaves_no_task_state and added an assertion that /tmp/fm-<id> is absent, with the task id suffixed by the test process pid so the assertion reads only this run's path (a stale /tmp/fm-refusedspawn from the fixed-id version was in fact present on this box). No assertions on implementation source bytes. Verification run locally: - The new assertion fails against the pre-fix bin/fm-spawn.sh ("not ok - a refused spawn stranded a temp root no teardown can find") and passes after — a real before/after regression proof. - tests/fm-claude-trust.test.sh: 20/20 ok. - tests/fm-backend.test.sh, fm-backend-orca, fm-control-relaunch, fm-spawn-dispatch-profile, fm-trace-context-spawn, fm-gotmp: all pass. - tests/fm-backlog-atomicity.test.sh: rc=0, 79 assertions ok. - bin/fm-lint.sh (repo's single lint owner, pinned ShellCheck 0.11.0 + actionlint 1.7.12): clean. - No /tmp/fm-refusedspawn* leftovers after the runs. Scope respected: no trust subsystem, no policy layer, no config surface, no endpoint-cleanup mechanism added; the change is an ordering move plus one error-message clause and the test that pins it. Adapter references and docs made no ordering claim, so none needed updating. Changes are left uncommitted in the worktree for the outer executor

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* feat(update): restart every live second mate after a successful update

/updatefirstmate only restarted a second mate when that pass advanced its
AGENTS.md or .agents/skills. An already-current home was skipped entirely, a
bin/-only advance was steered instead, and a remote host that could not report
its instruction diff was downgraded to a re-read. A running agent also freezes
its launch-time wiring - turn-end hooks, harness flags, per-harness feature
switches - and none of that is derivable from a file diff, so an unchanged
tracked surface is not evidence the agent is already on the current behavior.

Restart is now unconditional on a successful update of that home. Every live
second mate the pass leaves on the target commit is restarted, whether it
advanced or was already there.

The safety contract is unchanged: open records are persisted before the agent is
replaced, nothing is forced, stashed, or discarded, a home the pass had to skip
is not restarted at all, and a mate whose runtime cannot prove a restart keeps
the honest re-read path and is never reported as reloaded.

bin/fm-ff-lib.sh gains a settled-state hook that fires for a home left at the
base whether it advanced or was already there, and never for a skipped one; the
instruction-gated hook the session-start convergence sweep uses is untouched.

Regressions: fm-update pins the already-current mate into the restart set and
the unprovable one into the nudge set, and fm-secondmate-restart drives both
real commands end to end - an already-current home is named, persisted, and
genuinely replaced with its checkout untouched, while the unprovable one keeps
its running agent.

* no-mistakes(document): Document unconditional secondmate restarts
…3696)

* fix(bin): close reserved pending-reply keys via fm-send --resolve-key

fm-send wrote answered: notes that the reserved-key fold ignores, so
operator closes exited 0 while OPEN DECISIONS kept the decision open.
Speak the owning library's close vocabulary on that path, and refuse
when a reserved close cannot take effect.

* no-mistakes(review): Safely quote manual decision-close recovery commands

* no-mistakes(review): Reject unclosable overlong decision keys before sending

* no-mistakes(review): Remove contract suffix from open decisions hint

* no-mistakes(document): Document resolve-key line-cap refusal
* fix(bin): stop false missed-reply escalations for same-basename self-home answers

A healthy secondmate that wrote corr= to its own state/<id>.status never matched the parent channel, so recovery confirmed and the record escalated as pending-reply-missed. Make the report helper resolve the parent channel itself, skip parent-replies.status as wrong-home, put a readable sighting path on the missed line, and restatement-copy only that same-basename self-home file onto the parent channel.

* no-mistakes(review): Resolve late replies before recovery escalation

* no-mistakes(review): Tighten reply routing and regression coverage

* no-mistakes(review): Preserve reply paths and require explicit home

* no-mistakes(review): Encode wrong-home paths before persistence

* no-mistakes(document): Document corrected secondmate reply routing

* no-mistakes(lint): Fix pending-reply ShellCheck warnings
Adopt the first 26 remaining first-parent changes through a full merge.
Preserve agy, Pi away supervision, durable fork outcomes, remote process
safety, bounded validation, GBrain, and dashboard contracts.

Apply the reviewed terminal-anchor attribution requirement and the
Firstmate-approved recovery/restart instruction corrections.
Isolate Claude trust-writing fixtures and retain their negative guards.

Later sync endpoints and ledger-parked branches remain excluded.
@HelloWorldSungin
HelloWorldSungin merged commit f49a50d into main Sep 11, 2026
16 of 17 checks passed
@HelloWorldSungin
HelloWorldSungin deleted the fm/fm-upstream-sync-2026-09-08-round-2 branch September 11, 2026 08:10
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.

7 participants