Atomic write-then-rename for the landing handoff #15
Loading…
Reference in a new issue
No description provided.
Delete branch "fm/fm-quota-landing-procedure"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Replaces the size-stability handoff check with an atomic write-then-rename, so a partially written file can never be mistaken for a completed handoff.
Validated through the full no-mistakes pipeline: run 01M0FX639JSVPJ3JTVY0E0EWMX, outcome passed, one auto-fix and one informational finding, nothing awaiting a decision.
Firstmate verified the mechanism by reading the code rather than trusting the report. All three required proofs exist as named tests, including
test_fast_atomic_handoff_is_accepted_without_observing_the_temp- the false-negative case firstmate own design got wrong and the reviewer caught. The worker also added an edge case firstmate had not considered:test_marker_quoted_in_the_body_is_not_a_completion_signal, so a handoff that merely DISCUSSES the completion marker cannot falsely signal completion.Two follow-ups the captain judged inside the accepted contract. 1. Sentinel no-live-firstmate audit (the harder defect). Dropping ensure_watcher fixed one instance, but the real defect was broader: the sentinel made a synchronous call into a component whose completion depends on a live firstmate. Audit EVERY external call and answer "does this terminate without a live firstmate?": - quota-axi --json: NO (network). Now runs under a hard QUOTA_TIMEOUT (fm_run_bounded: timeout -> gtimeout -> perl-alarm; refuses unbounded if no tool). A timeout is logged loudly and treated as an unreadable meter (skip the cycle, never fire a reset wake). - tmux/herdr calls (target_exists, composer_state, send_text_submit, pane_is_busy): cannot be PROVEN to terminate (wedged tmux). Now all run inside inject_tmux under fm_fn_bounded INJECT_TIMEOUT (background+kill bound, since shell functions cannot be exec'd by timeout). Fail loud. - python3, fm_wake_append (file I/O + bounded lock), env reads, fm_operational_input_encode, sleep, date: terminate unaided. Unchanged. - re-arming the watcher: already removed (blocks on a watcher wake, and a re-armed watcher has no delivery channel under Claude with no live firstmate). Proof: a new test runs the sentinel with a quota-axi that hangs 60s; with QUOTA_TIMEOUT=2 the sentinel hard-timeout-kills it, logs, and COMPLETES instead of hanging - the exact defect the 21-minute hang exposed. 2. Missing worktree check. fm-land.sh now verifies the recorded worktree resolves to its own git toplevel (git -C <worktree> rev-parse --show-toplevel vs the recorded path, realpath-compared) and refuses on mismatch, naming the actual mismatch (recorded=X actual=Y). A refused worker is not handed off, not pushed, not /cleared; its status records a refused: line and the marker lists it under REFUSALS; fm-land.sh exits non-zero. Proven RED against a deliberately drifted worker (recorded subdir != real toplevel) and GREEN against a correct worktree. Honest limit recorded in notes: this catches a mis-recorded/mis-resolved worktree (subdir, symlink, deleted, moved) but NOT the pure cd-drift the author committed (worker cd'd to a different checkout while the recorded worktree stayed intact) - fm-land.sh operates on the recorded path and cannot see the worker's shell. That cd-drift remains an open gap. tests/fm-land.test.sh: +2 cases (drifted-worktree RED, correct-worktree GREEN). tests/fm-quota-reset-sentinel.test.sh: +1 case (hanging quota-axi hard-timeout). fm-lint.sh clean; fm-test-run.sh --check-coverage ok (total=144).