fix: harden review resolution and merged poll retirement - #13
Merged
Merged
Conversation
added 5 commits
July 28, 2026 10:25
Recorded review heads can lag fixes pushed after initial registration, causing reviewers to assess stale code. Fetch the trusted GitHub or GitLab review ref into private storage before using the recorded head as an offline fallback.
Merged review polls otherwise keep producing duplicate notifications after their terminal result. Retire exact GitHub and GitLab poll artifacts only after the notification is durable, with identity-bound receipts that make interrupted cleanup safe to recover without touching task lifecycle state.
eyevanovich
added a commit
that referenced
this pull request
Jul 28, 2026
## Intent Port the approved upstream B3/B4/B5 authority, primary native-delegation guard, and typed operational-input safeguards onto the current Firstmate fork as one coherent, tested change. Bound autonomous decisions to the captain's accepted contract; require captain authority for expansions into new guarantees, subsystems, threat models, compatibility surfaces, or repeated questionable abstractions. Prevent genuine primary and secondmate sessions from starting untracked native subagents while preserving observation and stop operations, the explicit launch-time FM_ALLOW_SUBAGENT=1 exception, and legitimate delegation in linked worker copies. Replace prose and ad hoc markers with the canonical U+2063 FIRSTMATE_OP v1 typed envelope, opaque bodies, exact kinds, narrow classifier-only compatibility for locally emitted legacy transcripts, strict malformed and near-miss rejection, safe JS/TypeScript adapters, and atomic migration of session-start, watcher, turn-end, away-supervisor, secondmate-send, and all five harness launch-brief producers. Keep full procedures in skills, wire formats and mechanisms in scripts/docs, and concise trigger/safety stubs in AGENTS.md. Preserve this fork's GitLab, commit-signing, no-mistakes observer, X/AFK, secondmate, five-runtime, multi-backend, local-only, review-lifecycle, PR #13 reviewed-head, and merged-poll retirement behavior. Treat upstream commits as evidence rather than authority; reimplement against the fork. Preserve current behavior where live integration cannot be verified, explicitly leaving OpenCode/Grok native delegation wiring pending rather than claiming unsupported enforcement. Do not merge the resulting PR. ## What Changed - Bound autonomous ask-user decisions to the captain-approved contract and added an escalation procedure for material contract expansions. - Introduced the canonical typed operational-input envelope and migrated session, watcher, turn-end, away, messaging, and launch-brief producers across supported runtimes. - Added primary and secondmate native-delegation guards while preserving observation, stop operations, the explicit launch-time exception, and delegation from linked worker copies. ## Risk Assessment ✅ Low: Captain, the change coherently implements the required authority, scoped delegation, typed operational-input, compatibility, and five-harness producer boundaries without a substantiated defect or intent contradiction. ## Testing The supplied baseline had passed; focused authority, typed-input, producer-migration, native-delegation, session-start, secondmate-send, and turn-end tests also passed, while a captured CLI transcript demonstrates the user-visible protocol and guard behavior end to end. This change has no rendered UI surface, so text CLI evidence is the appropriate reviewer-visible artifact. <details> <summary>Evidence: End-to-end typed-envelope and delegation-guard transcript</summary> ```text $ printf body | bin/fm-operational-input.sh encode watcher | bin/fm-operational-input.sh kind watcher $ encoded envelope (hex prefix and visible payload) e2 81 a3 46 49 52 53 54 4d 41 54 45 5f 4f 50 3a FIRSTMATE_OP: v1 watcher: signal: task-42 complete $ malformed ASCII near-miss classification (expected: empty) classifier output: <> $ genuine primary attempts collaboration.spawn_agent (expected: denied) exit: 2 {"decision":"deny","reason":"[subagent-dispatch] the Firstmate primary dispatches through its durable supervised lifecycle, not native delegation tools: work started natively has no durable fleet record and dies with this session. Instead, first classify the work under the AGENTS.md intake contract, then write its instructions with bin/fm-brief.sh and dispatch it with bin/fm-spawn.sh (blocked tool: collaboration.spawn_agent, launch-shaped on \"agent\"). Launch the primary session with FM_ALLOW_SUBAGENT=1 for a deliberate exception."} $ genuine primary observes with collaboration.list_agents (expected: allowed) exit: 0 $ explicit launch-time exception FM_ALLOW_SUBAGENT=1 (expected: allowed) exit: 0 ``` </details> ## Pipeline Updates from [git push no-mistakes](https://github.com/kunchenguid/no-mistakes) <details> <summary>✅ **intent** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Rebase** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Review** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Test** - passed</summary> ✅ 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 full test command previously completed successfully as supplied by the outer executor.` - `bash tests/fm-ask-user-authority.test.sh` - `bash tests/fm-operational-input.test.sh` - `bash tests/fm-subagent-pretool-check.test.sh` - `bash tests/fm-send-secondmate-marker.test.sh` - `bash tests/fm-sessionstart-nudge.test.sh` - `bash tests/fm-turnend-guard.test.sh` - <code>Manual CLI verification of U+2063 envelope encoding/classification, malformed ASCII near-miss rejection, primary native-spawn denial, observation allowance, and exact `FM_ALLOW_SUBAGENT=1` exception.</code> </details> <details> <summary>✅ **Document** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Lint** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Push** - passed</summary> ✅ No issues found. </details> --------- Co-authored-by: Ivan Miles Piesh <ivan@ivanpiesh.info>
eyevanovich
added a commit
that referenced
this pull request
Jul 29, 2026
## Intent Port the approved upstream supervision-continuity and AFK/current-run-attribution end state onto the current Firstmate fork. Add bounded one-owner successor cycles for Pi and OpenCode, Claude Stop-owned auto-arm with shared session-lock identity and bounded block cooperation, structured AFK terminal classification with independent wedge aging, and exact code/head-bound no-mistakes run attribution. Preserve PR #13/#14 security, authority, observer, delegation, signing, GitLab, and canonical FIRSTMATE_OP behavior; keep Codex and Grok continuity unchanged; include genuine secondmate primaries while excluding child task copies and observer/daemon/diagnostic/unrelated windows. Use the pre-calm Pi implementation and do not introduce unavailable calm dependencies or the rejected upstream command-gate change. Update ownership docs and add hermetic plus current-version live verification, reporting Claude authentication as a blocker rather than claiming success. ## What Changed - Add bounded, single-owner watcher successor cycles for Pi and OpenCode, plus Claude Stop-owned auto-arm coordinated through verified session-lock identity and bounded turn-end recovery. - Make AFK terminal classification and wedge aging independent, and bind no-mistakes run attribution to both branch and commit ancestry. - Extend primary-session scoping, lifecycle diagnostics, documentation, and hermetic/live coverage while preserving Codex and Grok continuity. ## Risk Assessment ✅ Low: The follow-up binds auto-arm ownership to process identity and scopes successor-cycle behavior to Pi, OpenCode, and Claude while preserving Grok’s default one-cycle semantics, with no remaining material source issue identified. ## Testing Completed 1 recorded test check. - Outcome:⚠️ 1 error across 2 runs (1h2m47s) ## Pipeline Updates from [git push no-mistakes](https://github.com/kunchenguid/no-mistakes) <details> <summary>✅ **intent** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Rebase** - passed</summary> ✅ No issues found. </details> <details> <summary>🔧 **Review** - 2 issues found → auto-fixed ✅</summary> - 🚨 `bin/fm-turnend-guard.sh:180` - The Claude guard treats any live process with the PID recorded in `.claude-autoarm.lock` as proof that recovery is underway. If an auto-arm process dies without releasing the lock and its PID is reused, `fm_lock_try_acquire` also refuses the stale lock, while this guard indefinitely allows stops with no watcher. Bind generic lock ownership to process identity, as watcher locks already do, and verify that identity at this shared lock boundary. - 🚨 `bin/fm-watch-arm.sh:261` - The required criterion says to “keep Codex and Grok continuity unchanged,” but the shared arm wrapper used by Grok now follows successor watchers and converts an attached cycle ending without a successor from a clean completion into a nonzero failure. This changes Grok’s documented re-arm/notification behavior; scope the new successor semantics to Pi/OpenCode (and Claude where intended), or obtain explicit approval to change Grok continuity. 🔧 Fix: Bind auto-arm identity and preserve Grok continuity ✅ Re-checked - no issues remain. </details> <details> <summary>⚠️ **Test** - 1 error</summary> - 🚨 tests failed with exit code 1 - `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"` 🔧 Fix: Bound recursive lock stealing and stabilize identity mocks 1 error still open: - 🚨 tests failed with exit code 1 - `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"` </details> <details> <summary>✅ **Document** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Lint** - passed</summary> ✅ No issues found. </details> <details> <summary>✅ **Push** - passed</summary> ✅ No issues found. </details> --------- Co-authored-by: Ivan Miles Piesh <ivan@ivanpiesh.info>
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
Port the two captain-approved upstream review-lifecycle correctness fixes onto the Firstmate fork at PR #12's landed head. Review diffs must prefer freshly fetched GitHub or GitLab review heads stored under private refs, use reachable recorded pr_head only as an offline fallback, refuse forge-origin identity mismatches, and warn before final local-branch fallback. Merged-review polling must retire exactly once only after its notification is durable, use provider-neutral identity-bound crash-recovery receipts, preserve GitLab's hash-registered custom-check route including trusted self-hosted forges, retain task and persistent-secondmate lifecycle state, preserve X-mode and non-executing migration security, and safely recover through watcher, migration, rearm, replacement, tamper, and teardown races. Preserve all fork-specific GitLab, direct signing, no-mistakes observer, local-only, secondmate, away/X-mode, and five-backend behavior; add comprehensive counterfactual tests; do not merge.
What Changed
Risk Assessment
🚨 High: Captain, the change should not merge until the crash window that can duplicate a merged-review notification is explicitly resolved or approved.
Testing
The full baseline was already green; focused end-to-end CLI tests then exercised review-head selection, identity and fallback handling, exactly-once durable retirement and recovery races, migration/X-mode security, and GitLab lifecycle behavior, all successfully. A reviewer-visible CLI transcript was captured; no screenshot was applicable because this change has no rendered UI surface.
Evidence: Review lifecycle end-to-end transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-watch.sh:827- The required criterion says, “Merged-review polling must retire exactly once only after its notification is durable” and must recover safely through watcher races. The wake is durably appended here before the retirement receipt is published. A crash between lines 827 and 829 leaves the poll armed with no recovery receipt, so the next watcher can append a duplicate merged notification. Couple the durable notification to an identity-bound retirement intent that recovery can correlate before permitting another poll execution.🔧 **Test** - 1 issue found → auto-fixed (2) ✅
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"🔧 Fix: Supply teardown fixtures’ new check-library dependency
1 error still open:
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"🔧 Fix: Supply legacy teardown fixture’s check-library dependency
✅ Re-checked - no issues remain.
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 previously completed: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"bash tests/fm-review-diff.test.shbash tests/fm-pr-check-security.test.shbash tests/fm-gitlab-review-lifecycle.test.shCaptured combined behavioral output withtee /var/folders/j_/g4b3__rs5j95fq6xf9fb17sc0000gn/T/no-mistakes-evidence/01KYMW7NF1APVGVDT8G2J1RRVJ/review-lifecycle-e2e-transcript.txtVerifiedgit status --shortremained empty after testing✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.