Skip to content

feat(daemon): fence lifecycle operations by durable identity - #1123

Open
sethkarten wants to merge 16 commits into
perf/b00b-production-gatefrom
perf/c01-identity-fencing
Open

feat(daemon): fence lifecycle operations by durable identity#1123
sethkarten wants to merge 16 commits into
perf/b00b-production-gatefrom
perf/c01-identity-fencing

Conversation

@sethkarten

@sethkarten sethkarten commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Stack

What this delivers

  • Fences daemon worker state by canonical process identity plus generation.
  • Fences RLM child callbacks by immutable assignment identity across selector reuse, hydration, deletion, and terminal races.
  • Resolves durable reused-child selectors to the newest exact assignment while stale A callbacks cannot mutate or tombstone B.
  • Preserves immutable recovery-operation tokens through each operation's real terminal/cancel edge; concurrent entries survive restart independently and restored actions remain busy until their own durable action ID settles.
  • Uses bounded, fsync-backed, atomic recovery-journal replacement with partial-write handling. Terminal append evidence cannot be resurrected as busy after a compact failure, and malformed raw evidence remains fail-closed across restarts.
  • Rejects duplicate restored action IDs before any durable token allocation.
  • Preserves close recovery across admission awaits, releases exact deferred/recovery join promises, reacquires same-object passivated wake generations, and safely retries a failed newly-published launch generation only after verified cleanup. Unverified cleanup preserves the exact process-bearing failed descriptor.
  • Classifies worker process identity as exact/dead/recycled/unreadable: transient unreadability retains the stop tombstone and cannot signal or finalize; verified recycled/dead identities finalize without signaling an unrelated PID.
  • Quarantines unreadable legacy descriptor evidence without authorizing wake, rewrite, adoption, or signal.
  • Keeps passivated as the only processless durable descriptor shape and preserves the legacy host ABI, public daemon schema, C00 metadata-only reads, and default recursion-depth policy.

No client-side concurrency limiter, admission queue, hidden batching, synthetic 429, credentialed provider request, or public protocol/schema revision is introduced.

Automated-review remediation

All prior Cursor and Macroscope findings, including the follow-up journal/restore/launch findings and the later signal-finalization finding, are fixed at this exact head. Independent component reviews approve the registry, supervisor, journal, duplicate-restore, and failed-launch repairs; integrated audits approve both review waves.

Exact validation

Isolated Linux lane c01-821a180763e2 on the reserved CPU runner, pinned image sha256:0f66…4c4d70d:

  • Biome: changed files clean
  • root tsgo --noEmit: pass
  • full workspace build: pass
  • C01 focused matrix: 463/463
  • process-stress: 6/6 runnable, 8 tag-skipped
  • parent B00B regression: 70/70
  • RSS regression: 20/20, max gap 28 ms, positive empty final process group 20/20
  • direct descriptor-derived signal check: absent
  • post-validation worktree: clean at exact head
  • disk headroom after validation: ~679 GB

Evidence

  • Bundle SHA-256: 4bbc562ba0704c3b08fbbdd32c46391176bd1ea6d7f7da7afaac8db91c85ec5f
  • Evidence archive SHA-256: 690225cae1c955794834edb651251ec8768ba406836145a565f1ab4ca795ab47
  • Full report: coordination/REMOTE_C01_FINAL_VALIDATION.md (program workspace)
  • Raw full/install logs, all 24 RSS warmup/measured cells, per-cell hashes, pattern result, exact bundle, component/integrated reviews, commit history, and cleanup proof are retained.
  • Superseded passing and non-passing attempts remain retained rather than being relabeled as final evidence.

Human review is intentionally deferred until the full dependency-ordered stack is visible. Automated review/CI findings on this PR will still be monitored and resolved now.


Note

High Risk
Touches daemon supervisor process signaling, crash recovery journaling, and RLM subagent lifecycle across restarts and selector reuse—errors could strand workers, mis-route recovery, or let stale callbacks affect the wrong incarnation.

Overview
Fences daemon and RLM lifecycle work with durable identities so a late callback from incarnation A cannot mutate, signal, or recover state owned by B.

Worker descriptors move from flat pid fields to a nested process pair plus a per-launch generation. The supervisor quarantines ambiguous legacy on-disk records (no wake, signal, or rewrite), migrates promotable legacy PIDs only after a verified start ID, and persists processless rows only for passivated lifecycle. Worker connect, frames, forwards, and shutdown signals are gated on generation and exact process identity; failed launches are retried only after verified cleanup.

RLM children get an immutable assignmentId per run. Parent session, runtime host, and daemon registry paths key tombstones, deletions, hydration, passivation, and event forwarding on (childId, assignmentId), with an opt-in assignmentIdentityFenced host ABI for embedded compatibility.

Worker recovery switches to journal v2 records keyed by operationId + generation`, with per-operation begin/end tokens for prompts, steer, follow-up, restored actions (validated before token allocation), session close, and turn/tool checkpoints—so crash recovery stays busy until the real terminal edge for that exact operation.

Session action restore is split into validate vs restore, returns admitted action IDs, and exposes unfinishedActionIds for recovery settlement. daemon-ps skips descriptors without a nested process when force-stopping workers.

Reviewed by Cursor Bugbot for commit 821a180. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fence daemon worker lifecycle operations by durable assignment and generation identity

  • Introduces a generation UUID per daemon worker incarnation, minted at launch and threaded through the startup gate, descriptors, passivation, and recovery journal so that stale callbacks from a previous worker process cannot mutate current state.
  • Adds assignmentId to subagent runtime lifecycle operations across AgentSession, AgentSessionRuntime, and AgentDaemon, keying all child session maps, tombstones, and deletion records by (childId, assignmentId) to prevent cross-incarnation interference.
  • Rewrites the WorkerRecoveryJournal to a v2 record format that includes operationId and generation for fencing, with atomic file replacement and platform-aware parent-directory fsync for durability.
  • Quarantines malformed or unclassifiable legacy worker descriptors on load rather than rewriting them, and enforces strict canonical descriptor shapes (nested process identity, canonical generation UUID) on every persist.
  • Risk: existing flat pid/processStartId descriptor fields are deprecated and stripped on write; legacy journal v1 records are preserved read-only but no new v1 records are written.

Macroscope summarized 821a180.

Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/worker-recovery-journal.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d6ec958. Configure here.

Comment thread packages/coding-agent/src/modes/daemon/worker-recovery-journal.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts
Comment thread packages/coding-agent/src/modes/daemon/worker-recovery-journal.ts Outdated
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts Outdated
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.

1 participant