Skip to content

feat(bin): track exact work identities end to end - #3510

Open
Charliekirk-creator wants to merge 98 commits into
kunchenguid:mainfrom
Charliekirk-creator:fm/firstmate-exact-work-unit-identity
Open

feat(bin): track exact work identities end to end#3510
Charliekirk-creator wants to merge 98 commits into
kunchenguid:mainfrom
Charliekirk-creator:fm/firstmate-exact-work-unit-identity

Conversation

@Charliekirk-creator

Copy link
Copy Markdown

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

  • Added the fm-work-identity.v1 public 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.
  • Bound validated identities into briefs, metadata, and dispatch, and preserve them through local and remote secondmate handoffs using revision-checked moves and recoverable ownership receipts.
  • Exposed exact identities through fleet snapshots, fleet views, Bearings, and bounded delegated-child summaries while hardening endpoint recovery and teardown across supported runtime backends.

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

$ fm-work-identity.sh record linked-evidence-worker --file manifest.json
recorded fm-work-identity.v1 task=linked-evidence-worker sha256=8c0516da1ce377d99437482592dbd9097970b25ee8e80b32847edef706df32db

$ fm-backlog-handoff.sh planning linked-evidence-worker
handed off 1 item(s) to planning: linked-evidence-worker
  into /private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/planning/data/backlog.md
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no watcher has a fresh beacon (last beat: never, grace 300s).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the requested message WILL still be sent.
●  repair a missing or failed watcher cycle with the Pi tool fm_watch_arm_pi, or restart Pi with -e /Users/gigachad/.no-mistakes/worktrees/9fe8f75cf8ab/01M1DA7VXNBCBKYDA1ZT4ZFD8X/.pi/extensions/fm-primary-turnend-guard.ts -e /Users/gigachad/.no-mistakes/worktrees/9fe8f75cf8ab/01M1DA7VXNBCBKYDA1ZT4ZFD8X/.pi/extensions/fm-primary-pi-watch.ts if the extensions are not loaded.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

$ destination: fm-work-identity.sh verify linked-evidence-worker | jq <exact relation>
{
  "schema": "fm-work-identity.v1",
  "status": "linked",
  "binding": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/planning",
    "home_id": "secondmate:planning",
    "task_id": "linked-evidence-worker"
  },
  "initiative": {
    "id": "wa-project-42",
    "kind": "project",
    "label": "Roadmap Accuracy",
    "namespace": "work-aligner"
  },
  "plan_id": {
    "id": "wa-plan-2026-q3",
    "kind": "plan",
    "label": "Identity Plan",
    "namespace": "work-aligner"
  },
  "stage": {
    "id": "implementation",
    "kind": "stage",
    "label": "Implementation",
    "namespace": "work-aligner"
  },
  "work_units": [
    {
      "id": "wu-exact-intake",
      "kind": "work-unit",
      "label": "Exact Intake",
      "namespace": "work-aligner"
    },
    {
      "id": "local-fleet-projection",
      "kind": "work-unit",
      "label": "Fleet Projection",
      "namespace": "firstmate"
    }
  ],
  "sources": [
    {
      "id": "dtm-project-17",
      "kind": "project",
      "label": "Delivery Tracking",
      "namespace": "dtm"
    },
    {
      "id": "DTM-431",
      "kind": "issue",
      "label": "Worker Relation Gap",
      "namespace": "dtm"
    },
    {
      "id": "DTT-88",
      "kind": "ticket",
      "label": "Dashboard Tracking",
      "namespace": "data-team-ticket"
    }
  ],
  "sha256": "e67de9eb32247dfe4f05b6dfecb8ee5fdb93aba25380e79876af4a26da3a05ee"
}

$ source ownership tombstone
{
  "role": "source",
  "state": "completed",
  "source": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/main",
    "home_id": "main",
    "task_id": "linked-evidence-worker"
  },
  "target": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/planning",
    "home_id": "secondmate:planning",
    "task_id": "linked-evidence-worker"
  },
  "identity_status": "linked"
}

$ destination ownership receipt
{
  "role": "target",
  "state": "completed",
  "source": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/main",
    "home_id": "main",
    "task_id": "linked-evidence-worker"
  },
  "target": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-handoff-evidence.jzr4Jq/planning",
    "home_id": "secondmate:planning",
    "task_id": "linked-evidence-worker"
  },
  "identity_status": "linked"
}

$ exact backlog ownership after handoff
source_count=0
destination_count=1
Evidence: tasks-axi commit and handoff capability evidence

Source: tasks-axi commit and handoff capability evidence

tasks-axi source commit: e2860a7f5d277e3ac61eccb3567c839e3d689192
test-private executable: /Users/gigachad/.no-mistakes/worktrees/9fe8f75cf8ab/01M1DA7VXNBCBKYDA1ZT4ZFD8X/.no-mistakes-task-bin/tasks-axi

$ tasks-axi capabilities --json
{
  "ok": true,
  "action": "capabilities",
  "schema_version": 1,
  "capabilities": {
    "backend": "markdown",
    "deps": true,
    "prune": true,
    "comments": false,
    "full_text_search": false,
    "realtime_sync": false,
    "custom_states": true,
    "server_mints_ids": false,
    "public_followups": true,
    "owner_revisions": true,
    "cas_move": true,
    "handoff_revision_cas": {
      "version": 1,
      "digest": "sha256",
      "move": true,
      "peer_checked_remove": true
    }
  }
}
Evidence: Focused local exact-handoff test

Source: Focused local exact-handoff test

ok - linked handoff rebinds identity for delegated decision summaries and Bearings
Evidence: Remote handoff integration test

Source: Remote handoff integration test

ok - confined put rejects incomplete and superseded payload generations
ok - confined put rejects directory replacement without external writes
ok - ambiguous receipt leaves one durable outbox and no duplicate dispatchable source
ok - new remote handoff preserves identities for every pending outbox row
ok - dropped transfer recovery removes exact interrupted source duplicates
ok - pending handoff recovery refuses symlinked and hardlinked records
ok - concurrent handoffs serialize staging through confirmed cleanup
ok - remote handoff reserves target identity before moving source backlog rows
ok - remote handoff commits an exact destination identity and source tombstone
ok - receiver validates every target commitment before batch move
ok - receiver validates the complete identity batch before reservation
ok - mixed remote recovery completes source ownership from the target receipt
ok - receiver removes one proven dead stale lock and retries once
ok - offline target reservation preserves recovery without source backlog mutation
ok - remote handoff wakes its supported endpoint or remains loudly recoverable
ok - fresh remote work gets a new wake after confirmed cleanup recovery
ok - route classification serializes with retirement before staging
ok - remote same-ID outbox rows require exact source content
ok - unconfigured bootstrap has no remote handoff behavior
ALL TESTS PASSED
Evidence: Baseline exact work-identity CLI transcript

Source: Baseline exact work-identity CLI transcript

$ fm-work-identity.sh record exact-worker --file exact-worker.json
recorded fm-work-identity.v1 task=exact-worker sha256=330adf14232462422321fba191885b2f2162a57bbbf975c59769240293af9db8

$ fm-work-identity.sh record exact-worker --file exact-worker.json  # idempotent retry
recorded fm-work-identity.v1 task=exact-worker sha256=330adf14232462422321fba191885b2f2162a57bbbf975c59769240293af9db8 (unchanged)

$ fm-work-identity.sh verify exact-worker | jq <identity projection>
{
  "schema": "fm-work-identity.v1",
  "status": "linked",
  "binding": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-identity-evidence.r8r4DW",
    "home_id": "main",
    "task_id": "exact-worker"
  },
  "initiative": {
    "id": "wa-project-42",
    "kind": "project",
    "label": "Roadmap Accuracy",
    "namespace": "work-aligner"
  },
  "plan_id": {
    "id": "wa-plan-2026-q3",
    "kind": "plan",
    "label": "Identity Plan",
    "namespace": "work-aligner"
  },
  "stage": {
    "id": "implementation",
    "kind": "stage",
    "label": "Implementation",
    "namespace": "work-aligner"
  },
  "work_units": [
    {
      "id": "wu-exact-intake",
      "kind": "work-unit",
      "label": "Exact Intake",
      "namespace": "work-aligner"
    },
    {
      "id": "local-fleet-projection",
      "kind": "work-unit",
      "label": "Fleet Projection",
      "namespace": "firstmate"
    }
  ],
  "sources": [
    {
      "id": "dtm-project-17",
      "kind": "project",
      "label": "Delivery Tracking",
      "namespace": "dtm"
    },
    {
      "id": "DTM-431",
      "kind": "issue",
      "label": "Worker Relation Gap",
      "namespace": "dtm"
    },
    {
      "id": "DTT-88",
      "kind": "ticket",
      "label": "Dashboard Tracking",
      "namespace": "data-team-ticket"
    }
  ],
  "sha256": "330adf14232462422321fba191885b2f2162a57bbbf975c59769240293af9db8"
}

$ fm-work-identity.sh verify legacy-task-with-no-record | jq <link status>
{
  "status": "unlinked",
  "reason": "legacy-no-record",
  "binding": {
    "home": "/private/var/folders/l9/13blqg851n3bj8p1b_3lxxk00000gn/T/fm-identity-evidence.r8r4DW",
    "home_id": "main",
    "task_id": "legacy-task-with-no-record"
  },
  "work_units": [],
  "sources": []
}

$ malformed v2 manifest is refused without publication
exit=1
error: manifest does not satisfy fm-work-identity.v1
published_sidecar=no

$ runtime state remains untouched by intake and reads
state_entries=0
- Outcome: 🔧 1 issue found → auto-fixed ✅ across 2 runs (1h44m41s)

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/main
  • ⚠️ bin/fm-fleet-snapshot.sh - merge conflict rebasing onto origin/main
  • ⚠️ bin/fm-test-run.sh - merge conflict rebasing onto origin/main
  • ⚠️ docs/configuration.md - merge conflict rebasing onto origin/main
  • ⚠️ docs/documentation-audiences.json - merge conflict rebasing onto origin/main
  • ⚠️ docs/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_lines and every subsequent secondmate summary/page share SECONDMATE_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 to page_tmp without 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 and fm_backend_herdr_prompt_version_check has 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, while check_herdr now 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 calls resume_remote_outbox with two arguments, but the function requires $3 as the handoff-directory inode. Under set -u this exits immediately, so the documented recovery path cannot finish the old handoff. Pass $handoff_inode here.
  • ⚠️ .agents/skills/secondmate-provisioning/SKILL.md:198 - The guide says handoff needs no tasks-axi capability beyond atomic mv, but fm_tasks_axi_handoff_compatible now additionally requires source/target revision CAS and peer-checked rm, 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=1 may 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_label accepts path-shaped labels such as ../secret and /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's state/&lt;id&gt;.meta, then re-enters cleanup paths that enumerate only state/*.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 and FM_HERDR_CI_MIN_PROTOCOL enforce 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_raw probes every remote metadata row sequentially with a fresh full timeout before FM_SNAPSHOT_SECONDMATES sampling 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_lock has no callers and references STATE and 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 emits paths.home.present:null at line 693, but fm-fleet-view.sh:45-46 renders every non-true value as &lt;path&gt; (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, both spawn_send_literal and spawn_send_key have their failures ignored. A backend failure therefore still transitions the backlog and reports spawned without 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 before launch-submitted is published: spawn_launch_request_state reports launch-exited, and recovery deletes its execution evidence, restores worktree-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 a launch-submitted receipt. 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. Its exited:&lt;status&gt; outcome becomes launch-exited, which now returns success here and allows metadata/backlog commit plus a spawned report 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 retryable launch-abandoned path. After spawn_launch_guard_state observes a dead owner with no child file, the already-started child can publish child before cleanup enumerates it; cleanup then deletes that evidence while the child advances to exec, restores worktree-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 --resume receipt and dispatch-prepare refuses 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_transition is defined only inside the SPAWN_METADATA_RECOVERY=0 branch, 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 becomes launch-exited, which this wait treats as successful delivery. Spawn then commits identity and reports spawned although 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 compensates launch-failed, deletes its journal, restores worktree-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 after dispatch-retire-run removes metadata, launch instructions, and dispatch state but before the endpoint receipt is removed at line 2970. The next --resume creates 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_wiring removes the token sidecar, but metadata retains harness_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 calls spawn_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_load exits 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 ordinary mv: a concurrent writer can place a file, symlink, or hardlink after line 2990 and it will be replaced here. The mktemp -u authorization 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 after ln publishes 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 .meta causes 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 after cmp validates it but before rm, 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 before describe-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 previous cmp stopped 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 to describe-digest. After that command returns, the authorization inode can grow after remove_entry checks actual_state; its uncapped entry_digest then reads through EOF, restoring the unbounded-I/O failure during cleanup. Derive the committed size from expected_state and 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 any state_change_seq increase is treated as acceptance, although the token is installed separately before agent prompt. An unrelated agent transition after baseline S can advance the sequence; if this prompt then fails before acceptance, recovery still returns accepted and 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 because tasks-axi mv publishes 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 with mv -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 from prepared to backlog-prepared before 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, allowing handoff-abort to 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 because replace_entry copies 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 by rm -f, and spawn reports success. Retire against SPAWN_ENDPOINT_ENTRY_STATE and SPAWN_ENDPOINT_ENTRY_DIGEST through 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. remove can durably rename the receipt behind its removal journal before cleanup completes; after interruption, line 2990 sees no live receipt, omits --resume, and dispatch-prepare refuses 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.sh detects the payload-digest mismatch only after authoritative publication. The no-clobber path also ignores copy_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 unconditionally rm -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-clobber now requires exact source state and digest arguments, but seed_backlog_scaffold still uses the old invocation. Any handoff needing a new target/outbox scaffold fails before backlog transfer. Capture the temporary scaffold with describe-source and 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 valid instructions_sha256 and 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.sh
  • FM_TEST_ONLY=contract-validation tests/fm-work-identity.test.sh
  • FM_TEST_ONLY=no-clobber-recovery tests/fm-work-identity.test.sh
  • FM_TEST_ONLY=owned-replace-source tests/fm-work-identity.test.sh
  • FM_TEST_ONLY=delegated-projections tests/fm-work-identity.test.sh
  • FM_TEST_ONLY=scaffold-publication-recovery tests/fm-backlog-handoff.test.sh
  • FM_TEST_ONLY=scaffold-parent-swap tests/fm-backlog-handoff.test.sh
  • Manual templaterecord → idempotent recordverify CLI 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 HEAD verified commit e2860a7f5d277e3ac61eccb3567c839e3d689192.
  • PATH=&lt;private-bin&gt; tasks-axi capabilities --json with jq validation of handoff_revision_cas version 1, move: true, and peer_checked_remove: true.
  • PATH=&lt;private-bin&gt; FM_TEST_ONLY=delegated-projections bash tests/fm-work-identity.test.sh initially exceeded the broad selector timeout after its exact linked-handoff assertion succeeded.
  • PATH=&lt;private-bin&gt; FM_TEST_ONLY=handoff-rebinding bash tests/fm-work-identity.test.sh.
  • PATH=&lt;private-bin&gt; bash tests/fm-remote-backlog-handoff.test.sh; after repairing stale cleanup-failure injection, the rerun completed successfully.
  • Manual CLI flow using fm-work-identity.sh record, fm-backlog-handoff.sh planning linked-evidence-worker, destination verify, receipt inspection, and source/destination backlog counts.
✅ **Document** - passed

✅ No issues found.

🔧 **Lint** - 1 issue found → auto-fixed ✅
  • ⚠️ linter found issues (exit code 1)

🔧 Fix: Fix ShellCheck lint violations
✅ Re-checked - no issues remain.

✅ **Push** - passed

✅ No issues found.

@greptile-apps

greptile-apps Bot commented Sep 2, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

The 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

Comment thread bin/fm-spawn.sh Outdated
while [ "$i" -lt "$max" ]; do
state=$(spawn_launch_request_state) || return 1
case "$state" in
accepted|executed|launch-exited) return 0 ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Suggested change
accepted|executed|launch-exited) return 0 ;;
accepted|executed) return 0 ;;
launch-exited) return 2 ;;

@Charliekirk-creator
Charliekirk-creator force-pushed the fm/firstmate-exact-work-unit-identity branch from 065b1c8 to 632a867 Compare September 2, 2026 08:53
@Charliekirk-creator
Charliekirk-creator force-pushed the fm/firstmate-exact-work-unit-identity branch from 632a867 to e318f5b Compare September 2, 2026 09:45
@kunchenguid

Copy link
Copy Markdown
Owner

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 <!-- no-mistakes-pipeline-attestation:v1 {"head_sha":"065b1c84a5b3a2395a2f03c90e7598b9a0e6e58b",...} --> while HEAD is e318f5b2528f398328c1fd9cac0d6cc3085dfa64 (ci commit “Reject exited worker launches”). NM run 33615883939 FAILED on that exact mismatch. Re-run git push no-mistakes so the PR body attestation binds to the current head. Do not merge until MATCH.

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 8988af2a (ahead 98 / behind 0). workflow surface: .github/workflows/ci.yml Herdr pin only (0.7.4→0.7.5, protocol 16→17); asset SHA-256s match official herdrdev/herdr v0.7.5 digests — not fake pins. No pull_request_target, credential, or hidden-gate risk found.

Contract-class: new-default. Recording via fm-work-identity.sh template|record|verify is an explicit intake step, but unconfigured behavior still changes always-on: fleet/Bearings/delegated projections always surface linked vs explicitly-unlinked; spawn/dispatch journals and acceptance reconciliation land for every ship/scout; bootstrap now requires python3 and fm_tasks_axi_handoff_compatible (revision-CAS) as universal readiness; Herdr CI/install floor moves to 0.7.5/protocol 17. That is a new unconfigured path/reorder, not a restore of an already-promised default, and not an off-by-default opt-in. No auto-merge. Firstmate escalate only when otherwise ready (attestation MATCH + green CI/NM) — not this pass.

VISION.md per-rule

  • One captain, one interface — aligns. Exact IDs through fleet/Bearings without reconstructing child trees; captain sees outcomes, not label inference.
  • Authority is explicit and never inferred — tension / partial. Intake itself refuses fuzzy inference (good), but new always-on spawn/handoff/bootstrap floors assume consent rather than shipping behind an enable flag (“new capability ships as an option to enable”).
  • Scripts own the mechanics, agents own the judgment — aligns. Contract owner is bin/fm-work-identity.sh + fm-work-identity-fs.py; agents do not adjudicate identity tuples.
  • A restart is a non-event — aligns. Sidecars, launch journals, handoff receipts, and ownership tombstones are durable disk records.
  • Delegation with a spine — aligns. Explicit contract before dispatch; unlinked remains explicit; no double-counting one worker across multiple work units.
  • The fleet outlives any vendor — aligns. Namespaces separate Work Aligner / DTM / Data Team Ticket / Firstmate; backend applicability covered; Herdr pin is versioned+hashed.
  • Scope — aligns. Command-layer identity + projections; no workshop merge authority change; field failures folded into public-interface tests.

Security: no. CI workflow delta is pin-only; install SHAs verify; dangerous eval hits in handoff are bash nameref array copies, not remote code.

Waiting on author for attestation rebind (and green CI after that). Not escalating; not merging.

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.

2 participants