Skip to content

fix(daemon): drop deleted rlm children's kernel state and dedupe artifact paths - #1450

Open
snimu wants to merge 10 commits into
mainfrom
feat/rlm-child-artifact-cleanup
Open

fix(daemon): drop deleted rlm children's kernel state and dedupe artifact paths#1450
snimu wants to merge 10 commits into
mainfrom
feat/rlm-child-artifact-cleanup

Conversation

@snimu

@snimu snimu commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

What this fixes

A subagent child's state is split across two stores: its transcript dir (session-artifacts/<parentId>/sub-XXXX/ — transcript plus the rlm-subagent.json display file) and a nested artifact tree (session-artifacts/<parentId>/session-artifacts/<child-uuid>/) where the child's own session puts kernel snapshots (kernel-state.dill) and harness state. Deleting a child never touched the nested tree, so every deleted child leaked its kernel snapshots forever — unreachable state, since a deleted child has no revival path.

Policy, stated explicitly

Deleted subagents are deleted. On child deletion, kernel snapshots and harness state go. Only the transcript .jsonl and the display-file tombstone remain, preserving the documented "deletion keeps the transcript readable" contract. The boundary: transcript + display file = durable record, retained; nested artifact dir = runtime cache, dropped.

What it does

  • Deletion drops the cache through the existing single code path. deleteSessionArtifacts (which full-session delete already used) is now also invoked by rlm child deletion, after the display tombstone and the ledger delete are durable, best-effort — cache cleanup can never fail a deletion. A retried deletion re-sweeps (crash-window heal). Because a resident child's kernel dispose flushes a final snapshot during teardown (which would resurrect the dir), the teardown paths re-sweep in finally blocks, so even a throwing teardown cannot skip the sweep; scheduled-job cancellation during deletion is likewise best-effort — a jobs-store error is logged rather than failing a deletion whose tombstones are already durable (deliberate semantic change).
  • Path dedup. The artifact-path formula (join(dirname(dirname(sessionFile)), "session-artifacts", id)) was hand-duplicated in 7 places across session-manager, session-file-actions, catalog process, supervisor, daemon-mode, and the spawn ledger. There is now one exported canonical helper family in session-manager (getSessionArtifactsRoot / getSessionArtifactPath / getSessionArtifactPathForFile) and every site uses it — zero copies of the formula remain outside the helpers.
  • Degenerate-name guard. deleteSessionArtifacts refuses a session file whose basename yields an empty id (e.g. literally .jsonl) — unguarded, the path join would resolve to the artifacts root itself. All four daemon sweep call sites route through this single guarded rm.

Scope note

Artifact dirs already leaked by pre-fix builds are deliberately NOT cleaned up by this PR (an earlier draft carried an opportunistic reaper; it was cut — a permanently-running mechanism is the wrong trade for a one-time mess). New children stop leaking by construction. Existing garbage can be removed manually (for each tombstoned child, remove session-artifacts/<parentId>/session-artifacts/<child-uuid>/) or by a future doctor --fix.

Numbers

Net src +49 (7 files, +90/−41): the helper family and the deletion hook, minus the deduplicated formulas.

Testing

Deletion removes the artifact dir while transcript, display tombstone, and a grandchild's transcript survive; teardown-throw still sweeps (regression, fails pre-fix); throwing jobs-cancel doesn't fail deletion (regression); rm failure is best-effort; degenerate-basename guard (proven to fail unguarded); helper path-equivalence. Targeted daemon suites green, npm run check clean.

Note

Drop deleted RLM children's kernel state and deduplicate artifact path resolution

  • When an RLM subagent is deleted, the daemon now sweeps its nested artifact directory via a new deleteRlmSubagentArtifacts method; cleanup is best-effort and never fails the parent deletion flow.
  • Artifact directory removal is wrapped in try/finally so it runs even when child teardown or scheduled-job cancellation throws.
  • Tombstoned-edge retry paths now also sweep leftover artifact dirs for each tombstoned child.
  • Centralizes artifact path computation into three new helpers (getSessionArtifactsRoot, getSessionArtifactPath, getSessionArtifactPathForFile) in session-manager.ts, replacing scattered manual dirname/join calls across daemon, supervisor, ledger, and cron-job modules.
  • deleteSessionArtifacts gains a safety guard that no-ops for degenerate .jsonl-only basenames to prevent accidental removal of the artifacts root.

Macroscope summarized 8fcb0bc.

Comment thread packages/coding-agent/src/modes/daemon/daemon-mode.ts
snimu added 3 commits August 16, 2026 17:02
Pre-round-2 a cancel throw on the healthy path propagated as a deletion
failure. Swallowing it is deliberate: both tombstones are durable by this
point, the reaper and retry-heal converge on leftover state, and a deletion
should not fail over jobs-store bookkeeping.
New children never orphan artifact dirs once the deletion hook exists; the pre-fix garbage is a one-time mess not worth a permanent mechanism in the deletion path. The degenerate-basename guard keeps direct coverage via deleteSessionArtifacts.
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