feat(kernel): dispatch host requests as capabilities - #1243
Conversation
c2f3e01 to
94e98f7
Compare
0f051bb to
cce55b6
Compare
|
Core checkpoint update (local, not yet pushed): the replacement-race remediation is validated through strict typecheck/formatting and focused recursion coverage. A late review found one directly related daemon-mode case where an old finalizer after same-ID republish threw instead of reporting a stale incarnation. The narrow correction and regression are being finalized now. Pre-existing or environment-only failures outside this lifecycle change are deferred rather than expanded into this PR. Publication will be append-only after the focused gate and exact-tip review pass. |
| if (!existingJob || !this.isPublicCronJob(existingJob)) { | ||
| throw new Error(`No cron job found: ${command.jobId}`); | ||
| } |
There was a problem hiding this comment.
🟠 High daemon/daemon-mode.ts:4604
cron_cancel can cancel a public cron job owned by session B when the client supplies session A as activeSessionId. The handler validates that A is public but never compares existingJob.activeSessionId with it before calling cronStore.cancel(command.jobId), allowing cross-session cancellation of scheduled work. Reject jobs whose activeSessionId differs from the requested session.
- if (!existingJob || !this.isPublicCronJob(existingJob)) {
+ if (
+ !existingJob ||
+ !this.isPublicCronJob(existingJob) ||
+ (command.activeSessionId !== undefined && existingJob.activeSessionId !== command.activeSessionId)
+ ) {🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @packages/coding-agent/src/modes/daemon/daemon-mode.ts around lines 4604-4606:
`cron_cancel` can cancel a public cron job owned by session B when the client supplies session A as `activeSessionId`. The handler validates that A is public but never compares `existingJob.activeSessionId` with it before calling `cronStore.cancel(command.jobId)`, allowing cross-session cancellation of scheduled work. Reject jobs whose `activeSessionId` differs from the requested session.
Evidence trail:
f7d36520bba57692bf11662c0b1601348496f11c: packages/coding-agent/src/modes/daemon/daemon-mode.ts:4563-4577, 4601-4616; packages/coding-agent/src/modes/daemon/daemon-supervisor.ts:1758-1762; packages/coding-agent/src/modes/agent-connection/daemon-agent-connection.ts:623-628
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f7d3652. Configure here.
| throw cascadeError; | ||
| } | ||
| if (daemonOwnsSessionLeaseRelease) state.runtime.releaseSessionLease(); | ||
| if (closeError) throw closeError; |
There was a problem hiding this comment.
Shutdown aborts on child close
High Severity
closeSessionOnce now throws every captured closeError, including child-cascade failures during shutdown and update. shutdown() awaits closeSession with no catch, so one descendant teardown failure can abort the remaining session closes and skip process.exit.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f7d3652. Configure here.
| this._disposeAsyncPromise = undefined; | ||
| } | ||
| throw error; | ||
| } |
There was a problem hiding this comment.
Dispose retry skips failed teardown
Medium Severity
Clearing _disposeAsyncPromise after failure does not re-run kernel dispose or drain. The failed attempt still calls dispose() in finally, so a retry sees _disposed and returns success. AgentSessionRuntime.dispose() can also release the session lease in finally before a retry continues teardown.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f7d3652. Configure here.


Summary
Validation
biome checkon all changed pathstsgo --noEmitNote
Dispatch host requests as capability-branded handlers with abortable, provenance-checked contexts
KernelManagernow mints a per-commHostRequestContext(viamintHostRequestContext) with anAbortController-backed signal that is revoked oncomm_close, during shutdown, and after settlement, preventing stale or replayed handler invocations.createHostRequestHandlernow requires an explicitcontextAwareHostRequestHandlermarker; unary or unmarked handlers are rejected at registration time rather than viaFunction.lengthheuristics.assertGenuineHostRequestContextvalidates context objects by WeakSet provenance instead of structural checks, blocking payload-injected or fabricated contexts.KernelManagergains a terminal state: once entered,start()rejects, host-request admission is closed, and restart waits for non-terminal shutdown to complete before reopening admission.agent-messages,agent-observe,agent-session,rlm-runtime,mcp-manager) are wrapped withcreateHostRequestHandlerandcontextAwareHostRequestHandler.invokeHostRequestHandlerForTest/invokeHostRequestThroughKernelForTestfor exercising dispatch semantics without a real kernel.createHostRequestHandler+contextAwareHostRequestHandlerwill be rejected at dispatch time.Changes since #1243 opened
AgentDaemon.persistedTopologyClaimsandAgentDaemon.residentAgentFamilyCandidateutilities to gate parent session derivation based on depth values [2694177]AgentDaemon.closeSessionOnce()to support tombstoned retry context and resilient error handling [f7d3652]PrivateSessionUnavailableErrorand modified session state retrieval to enforce quarantine checks [f7d3652]AgentDaemon.findExactRlmState()helper for precise subagent state lookup [f7d3652]AgentSessionRuntime[f7d3652]AgentSessionRuntime.dispose()andAgentSession.disposeAsync()to reset disposal promises on failure for retry support [f7d3652]AgentSessionto prevent direct prompts during update-restart preparation [f7d3652]AgentSession[f7d3652]AgentSessionRuntimeRLM subagent deletion to reportdeletionDurability='absent'for old incarnations [f7d3652]sessionIdto RLM subagent records in daemon supervisor tests [f7d3652]Macroscope summarized cce55b6.
Note
High Risk
Touches kernel request authority, multi-phase RLM subagent deletion with durable host boundaries, and security-sensitive catalog traversal; regressions could revoke live work, delete wrong child incarnations, or mis-resolve agent families.
Overview
This PR turns IPython host requests into factory-minted handlers that only run with dispatcher-minted
HostRequestContext(WeakSet-provenAbortSignal). Authority is revoked on comm close, settlement, shutdown, and dispose; the kernel has a one-way terminal state that blocks new admission. Production handlers (rlm.*, goals, compact, MCP, agent messaging/observe) are migrated tocreateHostRequestHandler, andrlm.run/rlm.delete_subagentpropagate the signal into spawn and delete paths.RLM subagent lifecycle gets a per-child deletion coordinator (generation + exact lease/incarnation) so explicit deletes, compaction reapers, spawn finalizers, and cancelled never-admitted children share one transaction. Deletes can return
preserved_neweror land in private quarantine when durability is unknown; runtime/host APIs gainRlmSubagentDeletionAuthority, typed host deletion errors, and stricterdeleteRlmSubagentRuntimematching onsessionFile/sessionId. Spawn admission can abort before publication; session disposal adds synchronous closing (beginClosing/isClosing), blocks reload/runtime rebuild during async teardown, and defers session lease release when the daemon owns retirement.Agent family naming and reach now resolve siblings via catalog-filtered parents (with a direct parent-id/path fallback for passive children) and stricter
isAgentFamilyParentwhen both id and path are present. The daemon catalog adds afamilycommand and replaces sibling listing with a bounded walk: O_NOFOLLOW roots, a persistent Python openat helper for header/metadata/registry reads, registry layout validation, and fail-closed limits on nodes/edges/depth. Session listing gains buffer-based header parsing helpers for that path.Reviewed by Cursor Bugbot for commit f7d3652. Bugbot is set up for automated code reviews on this repo. Configure here.