feat(bin): track exact work identities end to end - #3510
feat(bin): track exact work identities end to end#3510Charliekirk-creator wants to merge 98 commits into
Conversation
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; current launch handling compensates an exited worker instead of accepting it and moving its task to active work. Reviews (3): Last reviewed commit: "no-mistakes(ci): Reject exited worker la..." | Re-trigger Greptile |
| while [ "$i" -lt "$max" ]; do | ||
| state=$(spawn_launch_request_state) || return 1 | ||
| case "$state" in | ||
| accepted|executed|launch-exited) return 0 ;; |
There was a problem hiding this comment.
Exited launches count as accepted
When a ship or scout process exits successfully before acceptance is observed, launch-exited is treated as accepted delivery, so spawn publishes launch-submitted and moves the task to In flight even though no worker remains.
| accepted|executed|launch-exited) return 0 ;; | |
| accepted|executed) return 0 ;; | |
| launch-exited) return 2 ;; |
065b1c8 to
632a867
Compare
…fs and projections
…ctions and retries
…ble brief delivery
… omission disclosure
… snapshot deadlines
632a867 to
e318f5b
Compare
|
Speaking as Kun's firstmate: full-thread + full-diff review of #3510 (Charliekirk-creator). Author is not on the blocked list. Attestation: MISMATCH. Body carries First-time fork CI this pass: after safe diff review, approved workflow runs 33615883962 (CI) and 33615883939 (Require no-mistakes). CI attempt 2 is in_progress; already-failed job: Stock macOS Bash snapshot compatibility. Greptile SUCCESS 5/5 on this HEAD (prior P1 “exited launches count as accepted” addressed by the tip commit). MERGEABLE / BLOCKED vs main Contract-class: new-default. Recording via VISION.md per-rule
Security: no. CI workflow delta is pin-only; install SHAs verify; dangerous Waiting on author for attestation rebind (and green CI after that). Not escalating; not merging. |
Intent
Implement one exact, versioned Firstmate project, plan, and work-unit identity contract from intake through fleet projections. Accurate project-roadmap and worker-to-work-unit tracking is a highest-priority requirement. Provide one small public intake interface that records and validates exact project or initiative, plan, stage, work-unit, and source-system identities before dispatch. Preserve identities unchanged through generated instructions and task metadata or one purpose-built private sidecar. Expose them through the authoritative fleet snapshot, Bearings, delegated-child, and second-mate projections without reconstructing remote child trees. Support Work Aligner plan_id and work_units, exact DTM project or issue identities, Data Team Ticket identities, and local Firstmate plans as distinct namespaces. Support one task related to several exact work units without double-counting its worker identity. Pair human labels with stable exact IDs, with labels never establishing identity. Keep old or intentionally unlinked tasks compatible and explicitly unlinked. Make the interface deterministic and idempotent, and validate version, syntax, namespace, duplicate or contradictory IDs, unsafe paths or labels, and exact task/home binding. Refuse malformed, symlinked, hardlinked, cross-home, stale, or task-mismatched records without partial publication. Never infer a relation from title, repository, branch, pane, worker name, time, or status prose. Reading or recording a relation must not change task state, assignment, DTM, GitHub, or a Work Aligner plan. Add executable public-interface tests for single and multiple relations, namespace separation, exact DTM and Work Aligner IDs, absent legacy records, idempotence, task mismatch, unsafe files and labels, cross-home isolation, delegated projections, stable snapshot output, and rejection of every fuzzy fallback. Review every supported runtime backend and worker tool for applicability. Keep the full data contract in one authoritative script or schema owner with concise pointers elsewhere. Do not add conditional detail to AGENTS.md beyond a genuinely necessary trigger or invariant. Follow firstmate-coding-guidelines including one-owner, public-interface testing, documentation audience, shellcheck, lint, and maintainer-verification requirements. Preserve strict truthfulness and every accepted pipeline correction from the prior failed validation. Do not modify the private Workstack Compass artifact, add fuzzy fallback, merge, deploy, publish outside the selected path, or mutate external task, DTM, GitHub, or Work Aligner state when reading or recording identity relations.
What Changed
fm-work-identity.v1public intake flow for immutable, task-bound initiative, plan, stage, multi-work-unit, and source identities across Work Aligner, DTM, Data Team Ticket, and Firstmate namespaces; legacy tasks remain explicitly unlinked.Risk Assessment
✅ Low: The final correction is narrowly scoped, pins the scaffold source before no-clobber publication, and introduces no new substantiated source risk.
Testing
Building on the prior intake and validation baseline, I verified the requested tasks-axi commit and revision-CAS capabilities, exercised exact linked local and remote handoffs, fixed two test-harness targeting issues, and captured CLI/JSON evidence showing unchanged IDs, completed ownership receipts, and one destination backlog owner; no screenshot was applicable because this is a CLI and persisted-data change.
Evidence: Exact local handoff CLI and persisted identity transcript
Source: Exact local handoff CLI and persisted identity transcript
Evidence: tasks-axi commit and handoff capability evidence
Source: tasks-axi commit and handoff capability evidence
Evidence: Focused local exact-handoff test
Source: Focused local exact-handoff test
Evidence: Remote handoff integration test
Source: Remote handoff integration test
Evidence: Baseline exact work-identity CLI transcript
Source: Baseline exact work-identity CLI transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
🔧 **Rebase** - 6 issues found → auto-fixed ✅
bin/fm-bearings-snapshot.sh- merge conflict rebasing onto origin/mainbin/fm-fleet-snapshot.sh- merge conflict rebasing onto origin/mainbin/fm-test-run.sh- merge conflict rebasing onto origin/maindocs/configuration.md- merge conflict rebasing onto origin/maindocs/documentation-audiences.json- merge conflict rebasing onto origin/maindocs/scripts.md- merge conflict rebasing onto origin/main🔧 Fix applied.
✅ Re-checked - no issues remain.
🔧 **Review** - 3 issues found → auto-fixed (24) ✅
bin/fm-fleet-snapshot.sh:1844- The required criterion “Expose them through ... delegated-child, and second-mate projections” remains unreachable for later homes when an earlier remote read consumes this single fleet-wide deadline.task_json_linesand every subsequent secondmate summary/page shareSECONDMATE_DEADLINE_EPOCH, so one slow route makes otherwise healthy later routes appear unavailable. Establish a fresh bounded deadline per secondmate home and reuse it only across that home's summary and identity pages.bin/fm-fleet-snapshot.sh:1102- Remote identity output is written topage_tmpwithout a byte limit and checked only after the command exits. A broken or hostile remote can therefore write unbounded temporary data until timeout, contradicting the claimed transport-bounded paging. Bound stdout during transport and terminate/report overflow; apply the same boundary to remote summary capture at line 1631.bin/fm-remote-doctor.sh:61- Remote doctor now rejects Herdr protocol 16 for durable agent-prompt support, but persistent Herdr Kimi is explicitly refused andfm_backend_herdr_prompt_version_checkhas no caller. This unnecessarily makes existing 0.7.4 routes fail readiness for every still-supported harness. Restore the prior floor or identify the remaining supported protocol-17 consumer.🔧 Fix: Isolate secondmate deadlines and restore Herdr compatibility
1 warning still open:
docs/remote-secondmates.md:110- The operator guide still says remote routes require Herdr 0.7.5/protocol 17, whilecheck_herdrnow accepts the general protocol-14 backend floor and the updated test explicitly accepts protocol 16. Update the documented requirement so supported protocol-14/16 hosts are not incorrectly told to upgrade.🔧 Fix: Align Herdr requirements and isolate missing-Python test
2 issues (1 error, 1 warning) still open:
bin/fm-backlog-handoff.sh:1516- When an earlier remote handoff has both an outbox and wake-pending marker, adding new work callsresume_remote_outboxwith two arguments, but the function requires$3as the handoff-directory inode. Underset -uthis exits immediately, so the documented recovery path cannot finish the old handoff. Pass$handoff_inodehere..agents/skills/secondmate-provisioning/SKILL.md:198- The guide says handoff needs no tasks-axi capability beyond atomicmv, butfm_tasks_axi_handoff_compatiblenow additionally requires source/target revision CAS and peer-checkedrm, and bootstrap rejects tools lacking them. Document those requirements so operators are not told an incompatible build is sufficient.🔧 Fix: Pass handoff inode during remote outbox recovery
2 errors still open:
bin/fm-backlog-receive.sh:85-dd bs=73729 count=1may treat the first short pipe/SSH read as its single input block and silently truncate a valid handoff envelope. Larger valid identity transfers can therefore fail remote prepare/complete. Read through EOF with a 73,729-byte cap, then retain the existing size check.bin/fm-work-identity.sh:660- The required criterion to “validate ... unsafe paths or labels” is not met:safe_labelaccepts path-shaped labels such as../secretand/tmp/record, despite the contract stating labels are never paths. Reject absolute, traversal-segment, and empty-segment path forms in this authoritative predicate and add public-interface coverage.🔧 Fix: Read chunked handoff transfers through EOF
2 issues (1 error, 1 warning) still open:
bin/fm-teardown.sh:2504- Forced secondmate teardown authorizes completed child dispatches by quarantining each child'sstate/<id>.meta, then re-enters cleanup paths that enumerate onlystate/*.meta(for example line 2699). Consequently ordinary authorized children are skipped during endpoint/worktree cleanup and nested-home traversal before the secondmate home is removed, leaving external worktrees and runtime endpoints orphaned. Enumerate authorization-backed quarantine metadata alongside live metadata at the shared child-inventory boundary used by recursion, preflight, and cleanup.bin/fm-install-herdr.sh:15- The installer header still identifies protocol 16 as the required real-Herdr floor, while the updated pin andFM_HERDR_CI_MIN_PROTOCOLenforce protocol 17. Update the single-owner header to state protocol 17.🔧 Fix: Clean authorized children during forced secondmate teardown
2 issues (1 error, 1 info) still open:
bin/fm-fleet-snapshot.sh:664-task_json_lines_rawprobes every remote metadata row sequentially with a fresh full timeout beforeFM_SNAPSHOT_SECONDMATESsampling occurs. Thus N unreachable remote rows can delay the authoritative snapshot by N×timeout, despite the documented cross-home count bound. Apply sampling before this network boundary or leave unsampled endpoint state unknown; retain per-home deadlines for each sampled home's summary and identity pages.bin/fm-decision-hold.sh:219-with_backlog_mutation_lockhas no callers and referencesSTATEand lock functions that this script never initializes. It provides no serialization and should be removed to avoid implying a safety boundary that does not exist.🔧 Fix: Bound remote probes and remove unused lock wrapper
1 error still open:
bin/fm-fleet-snapshot.sh:627- The required criterion “Preserve strict truthfulness” is contradicted by the new unsampled-remote path. It deliberately avoids contacting the route and emitspaths.home.present:nullat line 693, butfm-fleet-view.sh:45-46renders every non-true value as<path> (absent). Remote secondmates therefore falsely appear to have absent homes. Keep probing bounded, but render null as unknown and reserve “absent” for false.🔧 Fix: Render unknown remote homes truthfully
1 error still open:
bin/fm-spawn.sh:5258- The required criterion “Make the interface deterministic and idempotent” is not met for ship/scout launches: after metadata is committed and the endpoint receipt is deleted at line 5095, bothspawn_send_literalandspawn_send_keyhave their failures ignored. A backend failure therefore still transitions the backlog and reportsspawnedwithout starting a worker; interruption in this gap also leaves no evidence for an exact retry. Retain a launch-intent/endpoint receipt and require backend acceptance before committing delivery, using the earliest shared launch boundary rather than backend-specific symptom handling.🔧 Fix: Journal worker launch acceptance for exact retries
2 errors still open:
bin/fm-spawn.sh:2890- The required criterion “Make the interface deterministic and idempotent” is violated when an accepted command exits beforelaunch-submittedis published:spawn_launch_request_statereportslaunch-exited, and recovery deletes its execution evidence, restoresworktree-ready, and submits the same transaction again. Treat any outcome proving child execution as non-retryable and reconcile it at the shared launch-journal boundary instead of replaying it.bin/fm-spawn.sh:2914- After backend acceptance, a backlog-transition failure rolls back the published metadata and exits while retaining alaunch-submittedreceipt. The next exact retry then requires that deleted metadata here and fails permanently, leaving a running worker with queued backlog state and no supported reconciliation path. This contradicts “deterministic and idempotent” and “without partial publication”; preserve metadata for commit retry or atomically compensate the accepted endpoint and transaction at the shared commit boundary.🔧 Fix: Reconcile accepted launches without replay or metadata loss
3 errors still open:
bin/fm-spawn.sh:1079- The required criterion “Make the interface deterministic and idempotent” is violated when the guarded worker command exits nonzero before acceptance is observed. Itsexited:<status>outcome becomeslaunch-exited, which now returns success here and allows metadata/backlog commit plus aspawnedreport despite no worker remaining; this is especially false for a persistent secondmate. Preserve this as non-replayable terminal evidence, but fail/reconcile rather than declaring successful acceptance.bin/fm-spawn.sh:2895- The prior duplicate-launch failure remains reachable through the new retryablelaunch-abandonedpath. Afterspawn_launch_guard_stateobserves a dead owner with no child file, the already-started child can publishchildbefore cleanup enumerates it; cleanup then deletes that evidence while the child advances toexec, restoresworktree-ready, and submits another worker. Atomically retire/claim the guard directory before classifying it retryable, then verify the retired guard has no live/executed child.bin/fm-spawn.sh:2870- After an accepted launch is preserved because backlog commit failed, the endpoint may disappear before retry. That retry deletes the sole endpoint receipt here, while completed dispatch metadata remains; the next invocation has no--resumereceipt anddispatch-preparerefuses the existing dispatch/metadata, so the advertised replacement rerun is impossible. Keep launch-prepared/submitted receipts and reconcile or explicitly compensate the accepted transaction at the shared receipt boundary instead of deleting it.🔧 Fix: Harden exact launch failure and endpoint reconciliation
1 error still open:
bin/fm-spawn.sh:5143- The required criterion “Make the interface deterministic and idempotent” remains broken for every metadata-recovery path.spawn_commit_backlog_transitionis defined only inside theSPAWN_METADATA_RECOVERY=0branch, but recovered accepted launches later call it unconditionally at line 5379. After an accepted launch and failed/interrupted backlog commit, the exact retry therefore reaches an undefined command and cannot complete the queued-to-in-flight transition. Define this shared commit function before the recovery/fresh-publication branch.🔧 Fix: Enable backlog commit during launch recovery
4 errors still open:
bin/fm-spawn.sh:1108- A persistent secondmate command that exits successfully before observation becomeslaunch-exited, which this wait treats as successful delivery. Spawn then commits identity and reportsspawnedalthough no secondmate remains, contradicting “Preserve strict truthfulness.” Treat every exited persistent launch as terminal failure requiring reconciliation, regardless of exit status.bin/fm-spawn.sh:2922- After an accepted launch and failed backlog commit, exact retry sets metadata recovery here but still repeats one-time preparation: line 4674 fetches and hard-resets the running worker's worktree, and line 4733 mints a new busy generation while preserved metadata retains the old generation. This violates “deterministic and idempotent” recovery and can invalidate lifecycle wiring. Skip pre-launch initialization during accepted-launch recovery and rehydrate preserved incarnation state instead.bin/fm-spawn.sh:2930- A nonzero worker exit preserves published metadata and a launch-prepared receipt, but every exact retry returns through this same branch forever. The queued task therefore retains worker metadata with no supported convergence path, contradicting “without partial publication” and idempotence. Reconcile terminal execution at the shared launch journal by compensating exact resources and retiring the failed transaction before allowing a fresh launch.bin/fm-spawn.sh:5403- When an accepted launch was preserved after backlog commit failure and its endpoint later disappears, recovery skips delivery verification, moves the queued row to In flight at line 5381, and only then errors here while preserving the receipt. Repeated retries cannot converge and project a nonexistent worker as in flight, contradicting “deterministic and idempotent” and “without partial publication.” Reconcile or compensate the missing endpoint before the backlog commit boundary.🔧 Fix: Harden launch failure and accepted-recovery reconciliation
3 issues (2 errors, 1 warning) still open:
bin/fm-spawn.sh:3028- The required “deterministic and idempotent” behavior is contradicted by converting terminal execution evidence into a fresh retry. A worker can perform side effects and then exit nonzero; the next invocation compensateslaunch-failed, deletes its journal, restoresworktree-ready, and a subsequent invocation executes the task again. The missing-endpoint path at line 3099 similarly discards a successfully exited ship’s evidence. Keep proven execution non-retryable and reconcile it at the launch-journal boundary rather than authorizing replay.bin/fm-spawn.sh:2961- The required “deterministic and idempotent” and “without partial publication” guarantees fail if the process stops afterdispatch-retire-runremoves metadata, launch instructions, and dispatch state but before the endpoint receipt is removed at line 2970. The next--resumecreates a new transaction, after which the surviving receipt is permanently transaction-mismatched. Journal a recoverable compensation phase at the shared dispatch/endpoint boundary before retiring either side.bin/fm-spawn.sh:2935- Terminal compensation removes metadata and busy state without retiring the provisional harness wiring. For Grok and Kimi, a fresh retry creates a new global authorization file and overwrites the only state token, permanently orphaning the prior authorization; other harness sidecars also survive incorrectly. Retire the exact current harness wiring as part of the shared compensation transaction before making the endpoint retryable.🔧 Fix: Retire harness wiring during launch compensation
1 warning still open:
bin/fm-spawn.sh:2941- Compensation retires Grok/Kimi authorization using the retry process's ambient GROK_HOME/HOME rather than the root used when wiring was created. A failed launch created with GROK_HOME=A and retried with it unset or changed removes local pointers but leaves A's global authorization orphaned. Persist and validate the exact authorization path/root when arming wiring, then consume that recorded value during shared cleanup.🔧 Fix: Persist exact harness authorization cleanup paths
2 errors still open:
bin/fm-spawn.sh:1869- The required “deterministic and idempotent” behavior fails if cleanup is interrupted.clear_relaunch_harness_wiringremoves the token sidecar, but metadata retainsharness_turnend_auth_path; if execution stops before the following rollback at line 2961, retry supplies an empty token and this validation rejects forever. Teardown has the same gap after deleting token sidecars but before metadata retirement. At the shared cleanup boundary, validate the recorded path using its basename when the sidecar is absent, and require equality when the sidecar remains.bin/fm-spawn.sh:1805- The required “deterministic and idempotent” and “without partial publication” guarantees remain violated for fresh-launch aborts. Grok/Kimi wiring is armed before metadata publication, but fresh abort cleanup only rolls back metadata/backlog state here; it never callsspawn_provisional_harness_wiring_retire. A failure after publication but before launch preparation therefore removes metadata while leaving global authorization and local pointers, and the next spawn overwrites the pointers while orphaning the old authorization. Arm exact provisional-wiring cleanup when wiring creation begins and retire it at the shared fresh-abort boundary.🔧 Fix: Harden harness cleanup across interrupted spawns
1 error still open:
bin/fm-spawn.sh:4900- The required “deterministic and idempotent” and “without partial publication” behavior still relies on an in-memory pending flag and EXIT trap. If the process or host stops after Grok/Kimi creates its global authorization (for example line 5079) but before metadata publication, no durable record identifies that authorization. The next exact retry creates a new authorization and overwrites the token sidecar, permanently orphaning the prior file. Persist a provisional-wiring receipt before creating harness artifacts and recover it at the shared harness-arming boundary.🔧 Fix: Journal provisional harness wiring before authorization creation
2 errors still open:
bin/fm-spawn.sh:4978- The required “deterministic and idempotent” behavior remains unreachable after a valid crash sequence: if Grok/Kimi wiring is journaled and created, the process dies, and the worktree-ready endpoint disappears,spawn_endpoint_receipt_loadexits at line 3156 before this recovery call. Every retry preserves the provisional receipt and global authorization without a convergence path. Recover or conditionally retire provisional wiring at the shared endpoint-recovery boundary before endpoint-liveness refusal.bin/fm-spawn.sh:3003- The criterion “Refuse malformed, symlinked, hardlinked ... records without partial publication” is contradicted by checking receipt absence and then using ordinarymv: a concurrent writer can place a file, symlink, or hardlink after line 2990 and it will be replaced here. Themktemp -uauthorization reservation has a related gap whose abort cleanup can remove the competing path. Publish the receipt atomically with no-replace semantics and remove authorization paths only after exact ownership/type/content validation.🔧 Fix: Harden provisional wiring recovery and receipt publication
4 errors still open:
bin/fm-spawn.sh:1288- The required criterion “Refuse malformed, symlinked, hardlinked ... records without partial publication” is violated because provisional cleanup runs before backend details and the recorded worktree are semantically validated. A canonical receipt with invalid backend fields or a non-worktree path can delete valid authorization/wiring before later validation fails. Fully validate endpoint details and exact worktree binding, then recover wiring before the liveness probe.bin/fm-spawn.sh:3007- The required deterministic and idempotent behavior is not durable: interruption afterlnpublishes the receipt but before the staging link is removed leaves both names with link count 2, while the loader rejects that receipt at line 2964 forever. Use the existing journaled no-clobber publication boundary so this intermediate state can be recovered.bin/fm-spawn.sh:3047- The required refusal of malformed, hardlinked, or task-mismatched records without partial publication is contradicted by collapsing every metadata validation failure into the unpublished branch. A hardlinked, malformed, or mismatched existing.metacauses valid harness authorization and the provisional receipt to be deleted instead of preserving state and refusing. Distinguish proven metadata absence from unsafe or mismatched metadata, and clean up only in the former case.bin/fm-control-lib.sh:292- The requested exact ownership/type/content removal remains racy: another process can replace the authorization aftercmpvalidates it but beforerm, causing cleanup to delete an unvalidated competing file. Perform conditional removal against a pinned inode/content commitment at the shared filesystem-owner boundary rather than check-then-unlink by pathname.🔧 Fix: Harden provisional wiring recovery and conditional cleanup
3 issues (2 errors, 1 warning) still open:
bin/fm-spawn.sh:1348- The required criterion “Refuse malformed, symlinked, hardlinked ... records without partial publication” remains race-reachable. After the endpoint receipt’s link count and contents are checked, another process can hardlink it before this call; recovery then removes valid authorization/receipt state despite the now-hardlinked endpoint. Metadata has the same gap between line 3070’s link check and line 3121’s receipt removal. Condition the shared recovery transition on pinned endpoint, metadata, and provisional-receipt commitments.bin/fm-control-lib.sh:298- The accepted exact-ownership correction is incomplete: ownership is checked by pathname beforedescribe-digest, but the Python entry commitment omits UID. A shared writable authorization root allows the checked file to be replaced with an exact-content file owned by another UID; the subsequent conditional removal then deletes that unvalidated owner’s file. Include UID in the pinned filesystem commitment and enforce ownership inside the same conditional retirement boundary.bin/fm-control-lib.sh:298- Cleanup now hashes the entire authorization file before comparing it with the known one-line payload. A malformed or sparse authorization of arbitrary size can make spawn/teardown perform unbounded I/O, whereas the previouscmpstopped immediately after detecting extra content. Enforce the exact expected byte length or a small cap through the pinned filesystem helper before hashing.🔧 Fix: Bound authorization digests by exact payload size
1 warning still open:
bin/fm-work-identity-fs.py:378- The new size cap applies only todescribe-digest. After that command returns, the authorization inode can grow afterremove_entrychecksactual_state; its uncappedentry_digestthen reads through EOF, restoring the unbounded-I/O failure during cleanup. Derive the committed size fromexpected_stateand enforce it throughout the shared removal and recovery digest boundary, with a regression that grows the file between describe and remove.🔧 Fix: Bound removal digests to committed file size
3 errors still open:
bin/backends/herdr.sh:2623- The required criterion “Make the interface deterministic and idempotent” is contradicted because anystate_change_seqincrease is treated as acceptance, although the token is installed separately beforeagent prompt. An unrelated agent transition after baseline S can advance the sequence; if this prompt then fails before acceptance, recovery still returnsacceptedand Kimi commits without receiving the brief. Require a server receipt binding the transaction token to this exact prompt, or preserve the result as ambiguous/unsupported.bin/fm-backlog-receive.sh:274- The required criterion “Refuse malformed, symlinked, hardlinked ... records without partial publication” is violated becausetasks-axi mvpublishes destination backlog rows before target identity receipts are checked at lines 290-296. If a prepared receipt or destination backlog changes between remote preflight and receipt, rows move first and validation then fails, leaving partial backlog publication and incomplete identity state. Validate every exact target receipt and backlog commitment under the receiver lock before the batch move, then retain the post-move completion check.bin/fm-spawn.sh:1216- The required criterion “Refuse malformed, symlinked, hardlinked ... records without partial publication” is contradicted by publishing every endpoint phase withmv -f. A competing malformed, symlinked, hardlinked, or transaction-mismatched receipt appearing after load is silently replaced and spawn continues. Use no-clobber publication for the initial receipt and exact expected-state/digest CAS for phase transitions at this shared publication boundary.🔧 Fix: Harden prompt, handoff, and endpoint receipts
3 errors still open:
bin/fm-backlog-receive.sh:286- The required “Refuse malformed ... records without partial publication” invariant is still violated for multi-key deliveries: key A is changed frompreparedtobacklog-preparedbefore key B is validated, so a malformed B leaves A partially mutated without moving any backlog rows. Additionally, the child identity lock is released after each transition, allowinghandoff-abortto remove A before the batch move despite the receiver lock. Validate and reserve the complete batch at one shared identity/backlog boundary before moving rows.bin/fm-work-identity-fs.py:1014- The required “Refuse malformed ... records without partial publication” behavior is not guaranteed becausereplace_entrycopies an unpinned source and then accepts whatever digest the resulting candidate has. If the spawn temporary source changes during copying, malformed content replaces the valid endpoint receipt; spawn detects the digest mismatch only after publication and exact retries remain blocked by that malformed receipt. Pin and verify the source inode/state/digest through copying at the filesystem-owner boundary before journaling the candidate.bin/fm-spawn.sh:5865- The required refusal of malformed, symlinked, hardlinked, or task-mismatched records is bypassed during retirement. After launch and backlog commit, a concurrent replacement of the validated endpoint receipt is deleted unconditionally byrm -f, and spawn reports success. Retire againstSPAWN_ENDPOINT_ENTRY_STATEandSPAWN_ENDPOINT_ENTRY_DIGESTthrough one conditional shared helper, including the sibling compensation and secondmate retirement paths.🔧 Fix: Harden handoff batches and endpoint lifecycle ownership
3 errors still open:
bin/fm-spawn.sh:1200- The required “deterministic and idempotent” behavior remains broken during conditional receipt retirement.removecan durably rename the receipt behind its removal journal before cleanup completes; after interruption, line 2990 sees no live receipt, omits--resume, anddispatch-preparerefuses the already-completed dispatch/metadata. Recover the removal journal before testing receipt presence and reconcile committed launches at the shared endpoint/dispatch boundary.bin/fm-work-identity-fs.py:118- The required “Refuse malformed ... records without partial publication” invariant is not met because the source commitment is captured only after the helper opens the source. A source changed before that open is copied and published as stable;fm-spawn.shdetects the payload-digest mismatch only after authoritative publication. The no-clobber path also ignorescopy_to_new's returned digest at line 1728. Require the caller's expected source state/digest and verify it through copying before journaling either replacement path.bin/fm-teardown.sh:3207- The required criterion to “Refuse malformed, symlinked, hardlinked ... records without partial publication” is bypassed by teardown: after destructive endpoint/worktree cleanup, it unconditionallyrm -fs the spawn endpoint receipt without validating or conditionally retiring its exact state and digest. A malformed or concurrently replaced receipt is silently deleted. Capture or prove absence during teardown preflight and retire through the shared conditional endpoint-receipt owner before destructive cleanup.🔧 Fix: Harden endpoint recovery, publication, and teardown ownership
3 errors still open:
bin/fm-backlog-handoff.sh:377-no-clobbernow requires exact source state and digest arguments, butseed_backlog_scaffoldstill uses the old invocation. Any handoff needing a new target/outbox scaffold fails before backlog transfer. Capture the temporary scaffold withdescribe-sourceand pass its state and digest.bin/fm-spawn.sh:3734- The required criterion “Make the interface deterministic and idempotent” remains false for successful secondmates. Normal success removes the endpoint receipt and its journal, while secondmates have no in-flight backlog row; an exact rerun therefore has neither condition accepted here, skips reconciliation, and reaches backend creation where the existing endpoint causes failure. Preserve a durable committed-launch result for backlogless kinds and reconcile it at the shared endpoint/dispatch boundary.bin/fm-teardown.sh:948- The required criterion “Refuse malformed, symlinked, hardlinked, cross-home, stale, or task-mismatched records without partial publication” is contradicted by teardown accepting any syntactically validinstructions_sha256and merely string-shaped backend details. A receipt with the correct transaction but an altered launch hash, Herdr workspace/tab, Zellij tab, or Orca worktree ID is conditionally deleted and destructive teardown proceeds. Bind these fields to the exact launch hash and backend identities in validated metadata before retirement.🔧 Fix: Pin backlog scaffold source before no-clobber publication
✅ Re-checked - no issues remain.
🔧 **Test** - 1 issue found → auto-fixed ✅
tests/fm-work-identity.test.sh:2475- The installed tasks-axi 0.2.5 lacks the required revision-CAS flags, so exact linked local and remote handoff rebinding could not be exercised. Rerun those tests with a handoff-compatible tasks-axi to complete the required evidence.tests/fm-work-identity.test.sh(initial monolithic attempts exposed and prompted fixes to stale test fixtures; focused selectors were then used to stay within the targeted phase boundary)FM_TEST_ONLY=intake-through-fleet tests/fm-work-identity.test.shFM_TEST_ONLY=contract-validation tests/fm-work-identity.test.shFM_TEST_ONLY=no-clobber-recovery tests/fm-work-identity.test.shFM_TEST_ONLY=owned-replace-source tests/fm-work-identity.test.shFM_TEST_ONLY=delegated-projections tests/fm-work-identity.test.shFM_TEST_ONLY=scaffold-publication-recovery tests/fm-backlog-handoff.test.shFM_TEST_ONLY=scaffold-parent-swap tests/fm-backlog-handoff.test.shManualtemplate→record→ idempotentrecord→verifyCLI workflow, plus legacy-unlinked verification, malformed-version rejection, publication absence, and runtime-state inspection🔧 Fix: Forward exact handoff payloads to remote receivers
✅ Re-checked - no issues remain.
Baseline public-interface transcript: exact intake, idempotent retry, linked/unlinked verification, malformed-record refusal without publication, and state nonmutation.git -C /Users/gigachad/.treehouse/tasks-axi-2925e9/1/tasks-axi rev-parse HEADverified commite2860a7f5d277e3ac61eccb3567c839e3d689192.PATH=<private-bin> tasks-axi capabilities --jsonwithjqvalidation ofhandoff_revision_casversion 1,move: true, andpeer_checked_remove: true.PATH=<private-bin> FM_TEST_ONLY=delegated-projections bash tests/fm-work-identity.test.shinitially exceeded the broad selector timeout after its exact linked-handoff assertion succeeded.PATH=<private-bin> FM_TEST_ONLY=handoff-rebinding bash tests/fm-work-identity.test.sh.PATH=<private-bin> bash tests/fm-remote-backlog-handoff.test.sh; after repairing stale cleanup-failure injection, the rerun completed successfully.Manual CLI flow usingfm-work-identity.sh record,fm-backlog-handoff.sh planning linked-evidence-worker, destinationverify, receipt inspection, and source/destination backlog counts.✅ **Document** - passed
✅ No issues found.
🔧 **Lint** - 1 issue found → auto-fixed ✅
🔧 Fix: Fix ShellCheck lint violations
✅ Re-checked - no issues remain.
✅ **Push** - passed
✅ No issues found.