Skip to content

[v0.8 Core 3] reconstruct managed session catalog - #1333

Merged
sethkarten merged 2 commits into
core02-host-request-dispatcherfrom
v080/core-split-c3-managed-catalog
Aug 13, 2026
Merged

[v0.8 Core 3] reconstruct managed session catalog#1333
sethkarten merged 2 commits into
core02-host-request-dispatcherfrom
v080/core-split-c3-managed-catalog

Conversation

@sethkarten

@sethkarten sethkarten commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Replacement scope

This PR reconstructs and supersedes the unique implementation delta reviewed in #1261 without rewriting that historical branch. The original PR remains the immutable discussion record: #1261

  • Base: core02-host-request-dispatcher
  • Replacement branch: v080/core-split-c3-managed-catalog
  • Replacement commit: b37fc9895f105341355e680a81097e674bd159f8
  • Propagation/reconciliation merge commits are intentionally excluded.
  • fix(mcp): make cleanup failures observable #1264 is intentionally omitted from the replacement stacks because its declared-base-to-head tree delta is empty.
  • Frozen feat(kernel): dispatch host requests as capabilities #1243 (77b188b92dc91365cb2bc41bdb46a50669d104a8) is the shared foundation. For reconstructed deltas it is a proven tree-compatible base, not an ancestry claim about the historical PR stack.

Validation

  • Biome 2.5.5 on the exact changed paths: pass
  • root tsgo --noEmit: pass
  • Core focused suite on the final Core tip with live daemon/RLM environment removed and single-worker execution: 11 files, 388 tests passed
  • MCP focused suite on the final MCP tip: 9 files, 106 tests passed
  • Independent Terra tree/delta review: pass

No original PR was retargeted, closed, merged, or otherwise mutated.


Note

High Risk
Changes agent-to-agent authorization, session catalog trust boundaries, and fail-closed behavior across daemon/supervisor paths; mis-merged topology or stricter family walks could deny legitimate messaging or rename flows.

Overview
Replaces ad-hoc sibling listing with listCatalogFamilySessions, which walks RLM registries from managed O_NOFOLLOW directory roots using descriptor-relative reads (Python openat helper), validates header/registry topology, and fails closed on symlinks, cycles, and hostile artifacts. Siblings and a new catalog family RPC are derived from that graph; readSessionInfoFromBuffer avoids reopening paths after authorized reads.

Daemon worker and supervisor now build frozen agentFamilyCatalogEntries / familyCatalogEntries from persisted scans, artifact-resident passive children, and live workers, merging only compatible topology claims. Agent-origin messaging, observation, rosters, and cross-worker send_message authorize against that snapshot (including post-wake session-id checks); CLI sends stay deliverable but relationship labels are advisory when the catalog is ambiguous or unavailable.

agent-messages tightens nuclear-family rules: siblings/parent edges require a catalog-resolved unique parent; contradictory id/path parent claims are rejected; name reservation gains a weaker direct-parent fallback that does not broaden reach.

Daemon schema revision 17 adds optional sessionDir on detached rename_saved_session so inactive renames use the correct catalog authority root.

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

Note

Reconstruct managed session catalog with secure family traversal and sessionDir-scoped authorization

  • Introduces listCatalogFamilySessions in daemon-catalog-process.ts, which enumerates the full session family graph using descriptor-relative, O_NOFOLLOW file reads via an embedded Python helper to mitigate path traversal and TOCTOU races.
  • Replaces mutable live-topology derivation in daemon-mode.ts with agentFamilyCatalogEntries, an immutable merged cross-source catalog snapshot used for all authorization decisions (observe, getAgent, sendMessage).
  • Scopes all session catalog operations (family enumeration, sibling resolution, name availability checks, rename) to an explicit sessionDir, propagated through the daemon supervisor and protocol commands.
  • Tightens sibling/parent determination in agent-messages.ts: sameAgentFamilyParent now requires catalog-resolved unique parents; malformed remote peer topology is rejected early with AGENT_FAMILY_REACH_ERROR.
  • Bumps daemon schema revision to 17 and extends rename_saved_session with an optional sessionDir field; commands without it remain legacy-compatible.
  • Risk: listSavedSessionSiblings now throws if the target session is not found in the authoritative family, and cross-worker delivery is denied if the woken target's identity does not match the pre-authorized snapshot.

Macroscope summarized 8b21a40.

Reconstruct the unique net delta from PR #1261, excluding propagation merges.
Comment thread packages/coding-agent/src/modes/daemon/daemon-protocol.ts
Comment thread packages/coding-agent/src/modes/daemon/daemon-supervisor.ts

@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 b37fc98. Configure here.

Comment thread packages/coding-agent/src/core/agent-messages.ts
Scope live family catalogs, anchor relative parent paths, and retain legacy rename compatibility without weakening authority-aware requests.

@jonaowen jonaowen 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.

This cannot be an authority boundary yet.

  1. The catalog path is unusable on Windows: Node exposes neither O_DIRECTORY nor O_NOFOLLOW; Python exposes neither constant and no dir_fd support. The helper necessarily fails, and python3 is not a reliable Windows launcher. Add a supported root-bound Windows implementation with real reparse/fd-handle tests.
  2. Worker ACL construction still independently scans through SessionManager.listAll / passive registries / pathname reads that follow links and accept registry-controlled paths. Messaging/observe/roster authority must consume the same verified snapshot or an equivalent root-bound traversal; hostile external/../symlink/replacement/forged-sessionDir tests are required.
  3. The walk has no aggregate work budget: up to 10,000 synchronous Python launches, each allowing 128 MiB and 5 s, can block the supervisor for hours. Bound aggregate bytes, reads/processes, and elapsed time (prefer one bounded traversal), with deterministic exhaustion tests.
  4. The peer-summary semantic change is not versioned. One legacy/malformed peer lacking depth/topology makes the entire catalog throw and disables unrelated valid local families, while schema 17 gates only saved rename. Capability/version the peer shape or quarantine unverifiable peers; test old/new worker-supervisor combinations.
  5. Direct parent/child reach does not uniquely resolve a path claim through the catalog. Two rows with different IDs but one canonical path can both become a path-only child's parent; merge logic rejects duplicate IDs, not duplicate paths. Reject duplicate canonical authority paths globally or require unique parent resolution, including Windows case variants.

The new test suite has no Windows path and protocol tests do not exercise mixed peers.

@snimu

snimu commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Opened #1370 against this branch. Running this PR's family walk against a real ~/.prime/agent profile surfaced two independent real-data blockers, both now fixed there with regression tests that fail on the current head:

  1. Fork lineage rejected as topology corruption: /fork and lineage-carrying /new write parentSession into flat-dir headers (two shapes: with and without rlmDepth). One forked session anywhere makes family() throw, and the daemon-supervisor.ts call sites have no fallback — so agent-origin send_message, create-with-name, and rename all hard-fail for the whole profile. The real profile tested has 5 such sessions.
  2. Registry-child identity check contradicts every registry the daemon has ever written: registries store childId as the rlm node id (sub-*), never the session UUID, so child.id !== entry.childId rejects 100% of real edges (597/597 live on the tested profile). Also: nested registries live at the writer's session-artifacts/<id> layout, not where the walk looked (silent depth-1 truncation), 429/597 legacy edges have no persisted rlmDepth, and real registries exceed the 1MB cap (largest: 3.3MB).

#1370 also fixes the perf profile: header-only reads instead of whole-file base64 round-trips, and one looped openat helper per walk instead of one python3 spawn per file (~330 spawns / ~645MB piped per walk on the benchmark profile → 1 spawn / a few hundred KB). Walk time 7.4–7.9s → 28–29ms warm; against the real profile the walk now returns 775 members incl. depth-2 families the current head silently drops. Security properties (descriptor-relative O_NOFOLLOW traversal, fstat identity, fail-closed on protocol violations) are unchanged.

The PR description also sketches a supervisor-owned spawn-ledger alternative that would make this class of bug structurally impossible — worth a read before more validation is layered onto re-derived writer-owned files.

@sethkarten
sethkarten merged commit 8d72bfe into core02-host-request-dispatcher Aug 13, 2026
2 checks passed
@sethkarten
sethkarten deleted the v080/core-split-c3-managed-catalog branch August 13, 2026 21:00
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.

3 participants