Conversation
Done means merged, never green-open. Reconciliation previously transitioned a terminal producer row from In flight to Done as soon as the worker reported complete with a clean tree, which released dependents against work that had not landed. Record the terminal-retention evidence (exact head, clean tree) on the row instead and leave it In flight. Teardown, which separately refuses unlanded work, stays the only path that retires it. The write is idempotent so repeated terminal wakes do not churn the row body. Also restores the reconcile-binary and current-state seams the two lanes' tests depend on, so the resumed-worker refusal is still exercised through the drain path.
coreldh
force-pushed
the
fm/c0803-o2-fold
branch
from
August 5, 2026 05:51
503e90d to
0fddbae
Compare
Owner
|
Speaking as Kun's firstmate: closing this as stale. It has been waiting on a contributor update for 14+ days with no author push or comment. Reopen if you want to pick it back up. |
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
Fold two previously-split branches back into one self-contained PR, per an explicit ruling from the repository owner, and remove a contract change he rejected.
BACKGROUND: An earlier PR (#1493) bundled a large supervision/record-integrity change with a hardening of the watcher arm guard. A prior lane rebased it onto current main (8 conflicts) and split it into two branches: PR1 (the bulk plus five gate fixes) and PR2 (the arm-guard hardening). The owner then ruled on both.
RULING 1 - SECURITY, fold the hardening IN. His words: 'the watcher-arm bypass must never exist in a merged state. Not the split-and-bet-on-order path.' The bulk commit INTRODUCES the bypass: it added an inferred 'noexec' flag so that legitimate 'bash -n bin/fm-watch.sh' syntax checks could be allowed, but the inference is unsafe because bash options like --rcfile and --init-file consume a value. I verified on main that no such inference exists, and verified on the bulk-only branch that all of these reach the ALLOW path: 'bash --rcfile -n bin/fm-watch.sh' and 'bash --init-file -n bin/fm-watch.sh' (which EXECUTE the watcher, since -n is swallowed as the rcfile argument), and 'bash -n bin/fm-watch.sh > bin/fm-watch.sh' (which TRUNCATES it). So shipping the bulk without the hardening would land a real regression. The hardening replaces the inference with an exact positive allowlist for the only two sole-syntax-check forms, and rejects protected output redirection independently and before every allow path. I re-verified against the folded tree that all attack forms now deny and both legitimate syntax-check forms still allow. This is deliberate and is the whole point of the PR being self-contained.
RULING 2 - CONTRACT, the 'Done' redefinition is REJECTED. His words: 'Done = MERGED, never green-open. Unlanded work does not release dependents.' The bulk added bin/fm-record-reconcile.sh, which transitioned a backlog row from In flight to Done as soon as a worker reported complete with a clean tree - i.e. on a green-but-unmerged PR - which released dependents against work that had not landed. I removed that transition. The smallest compliant alternative the gate itself named, and what I implemented, is to keep the row In flight and record terminal-retention evidence (exact head, clean tree) on it, leaving teardown - which separately refuses unlanded work - as the only path that retires it. The write is idempotent so repeated terminal wakes do not churn the row body. A reviewer seeing a 'tasks-axi done' call deleted should read it as this deliberate rejection, not an oversight.
DELIBERATE MERGE DECISIONS worth knowing: (a) The two lanes both touched the terminal-wake reconcile path. PR1 had built a helper that detected terminal wakes by PARSING ANNOTATION PROSE, then patched it again to survive truncated annotations; PR2 replaced that approach entirely with structural status-key mapping. I resolved in favor of the structural approach and dropped the prose parser, because it supersedes both gate fixes rather than competing with them. (b) That resolution silently broke two test seams which I deliberately restored: the drain now calls the reconcile script through FM_RECORD_RECONCILE_BIN again so the existing 'terminal signals reconcile records even when annotations truncate' test can still stub it, and the test file re-defines RECONCILE (which PR2 had removed while PR1 still used it, an unbound-variable failure under set -u). (c) Reconciliation refuses any row whose worker has resumed - a real safety property PR1 added - so the drain-driven test needs a current-state source; I export FM_CREW_STATE_BIN so it survives into the reconcile child.
VERIFICATION: full suite is 1034 passing with 3 failures, and I confirmed all 3 reproduce unmodified on main (Orca spawn metadata, fm-send --key exit code, teardown tasktmp) - none are from this change. Lint and the doc-audience gate are clean. Do not fix those 3 pre-existing failures here.
Final shape: 44 files, +2909/-104.
What Changed
awaiting-captainsupervision, identity-bound process-progress sampling, serialized model-capacity holds, receipt-bound decision resolution, and strict spec-forging brief preflights.Risk Assessment
Testing
The supplied broad-suite baseline and its three main-reproducing failures were not rerun; focused security, reconciliation, and truncated-notification suites passed, while manual CLI evidence demonstrated real guard decisions, unchanged branch HEAD, retained metadata, no Done transition, and idempotent repeated reconciliation. No standalone lint phase ran, although the watcher test script includes its own final shellcheck assertion.
Evidence: Watcher guard allow/deny transcript
Evidence: Terminal retention and idempotency transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
🔧 **Review** - 3 issues found → auto-fixed (2) ✅
bin/fm-crew-state.sh:632- The repository contract says running, fixing, and CI states remain working, and this function's comment says an absent worker identity leaves that mapping unchanged. The catch-all instead changes every PID-unbound full-source working run tounknown. Thus a legitimate CI step without a native model PID—or a transiently unreadable step log—is first mapped to working and then overwritten; the test fake masks this by injectingcodex started pid=4242into every log response. Confirm whether all PID-unbound runs should now be indeterminate; otherwise preserve the authoritative run-step state unless a bound worker is positively contradicted.bin/fm-crew-state.sh:373- The worker check does not actually detect PID reuse by another allowed-family process. If the recorded worker dies without an exit marker and its PID is reused by an unrelated Codex, Claude, or other matching agent process, the broad command regex reports the stale run as live. Bind the PID to a process-birth identity at the launcher/logging boundary and compare that exact tuple here.bin/fm-model-capacity-hold.sh:97- Registration publishes an exclusive per-ID receipt but overwrites the shared active marker without serialization. Two different hold IDs can both observe no marker, both create receipts, both return success, and the lastmvsilently discards the first active reservation; releasing the winner then opens capacity despite the first successful registration. An interruption after receipt publication also makes retry fail permanently. Serialize the home-wide lifecycle and make a matching orphan receipt repairable before reporting success.🔧 Fix: Fix worker identity and capacity hold races
3 errors still open:
bin/fm-crew-state.sh:357- The required fix was to “bind the recorded worker PID to a process-birth identity at the launcher/logging boundary and compare that exact tuple,” but this patch only consumes a newpid-identity-hextoken. No production source emits that token; it appears only in this parser and its test helper. The installed no-mistakes v1.41.2 logs confirm the gap: 261 step logs contain plainstarted pid=...records and zero contain the new identity token, including this review round. Consequently every real worker remains unbound and a dead or reused PID still inheritsworking. The durable fix requires the no-mistakes launcher to emit the exact identity and a compatible version floor; otherwise retain the authoritative run-step behavior as explicitly documented containment rather than claiming PID-reuse closure.bin/fm-wake-lib.sh:13- Extractingfm_pid_identitymakesfm-wake-lib.shdepend on a new sibling, but several supported isolated-copy paths still copy onlyfm-wake-lib.sh—for example the Claude auto-arm, turn-end guard, session-lock, AFK-return, and historical-backend fixtures. Those copies now source a missing file and lose the shared identity functions, introducing failures beyond the three explicitly allowed pre-existing failures. Update every bundle/copy manifest to carry the new helper, or keep this dependency self-contained.bin/fm-model-capacity-hold.sh:119- The serialized registration path still treats an active marker with the same ID as a successful retry without comparingreasonordispatch_ref. A second caller reusing the slug with different reservation metadata receives success and can later release that ID, retiring the first caller's reservation. Apply the existingregistration_matchescheck to the active marker and its receipt before returningalready active.🔧 Fix: Document PID containment and secure hold retries
✅ Re-checked - no issues remain.
✅ **Test** - passed
✅ No issues found.
bash tests/fm-arm-pretool-check.test.shbash tests/fm-record-reconcile.test.shbash tests/fm-wake-queue.test.sh/var/folders/cq/xf4qcb9j0qzc2dbh173mflbm0000gn/T/no-mistakes-evidence/01KZ53QC8FMRR1QTJWKEWVSA7R/reproduce-intent-evidence.sh "$PWD"Comparedterminal-retention-after-first-wake.mdwithterminal-retention-after-second-pass.mdand verified identical content.Verifiedgit status --shortremained empty after testing.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.
Rebuild update - 2026-08-04
BLOCKER-1 is closed in the rebuilt head. Composer preflight capability is static and adapter-owned: tmux, herdr, Orca, and cmux are classified and accept only
classified:empty; zellij alone is statically unclassified and falls back to its existing submit-verification policy; unknown classifier capability and every non-empty or unknown classified verdict refuse before mutation.The independently gated production repair is unchanged by the rebase. Commit
966e211eand its rebased twinaa4103ahave the same subject (fix: preserve zellij composer fallback) and the same stable patch ID,3eea69560f217c8baa543f4aff36a4c24f27bda6.The three authorized non-blocking follow-ups are closed:
tests/fm-send-strict.test.shnow exercises thefm-send.shcapability-unknown refusal arm through the executable path and kills mutant C.docs/architecture.mdnow documents the statically unclassified fallback and fail-closed unknown states.docs/scripts.mdnow describesfm-composer-lib.shas the classifier used by statically classified backends.fm-watch-triagestatus: this BLOCKER-1 repair and its follow-ups do not modifybin/fm-watch-triage.shortests/fm-watch-triage.test.sh. Any changes to that area visible elsewhere in this PR are inherited from earlier branch commits; their disposition is a separate decision, and this repair takes no position on them.Validation evidence:
966e211e, including 28 crafted classifier outputs, fail-closed classified and unclassified unknown cases, and zellij red-before-green.01KZ81N8QN97X17NBBEVM2B6QDpassed intent, rebase, review, focused behavioral tests, documentation, and full repository lint with no findings. Its testing independently passedtests/fm-send-strict.test.shandtests/fm-backend-zellij.test.shand killed mutant C.total=125,failed=7, andskipped_gate=25; six failures reproduced on main and the seventh reproduced on the pre-repair feature-branch control.bea3d23for upstream PR fix(bin): resolve remote entrypoint path through symlinks #1709 infm-remote-entrypoint.sh; no gate-bound BLOCKER-1 production byte moved.Published head:
0fddbae64cb4fbd8b0a0b3dbe276e4ff5a3a9c87.