Uh oh!
There was an error while loading. Please reload this page.
fix(pi-plugin): support pi-web multi-session and RPC hosts - #350
fix(pi-plugin): support pi-web multi-session and RPC hosts#350elrond298 wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
All reported issues were addressed across 17 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Uh oh!
There was an error while loading. Please reload this page.
…amer registry, session-scoped drains, presenter ctx capture; NOT a security blocker — rpc-server untouched) Co-Authored-By: Alfonso <alfonso@cortexkit.io>
There was a problem hiding this comment.
All reported issues were addressed across 17 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Uh oh!
There was an error while loading. Please reload this page.
alfonso-magic-context
left a comment
There was a problem hiding this comment.
Thanks for this — especially as a first contribution. The diagnosis is right: the #247 process-global latch is what makes the second pi-web session skip Magic Context entirely, and routing child suppression through subagents:child:session-created/disposed plus AsyncLocalStorage is the correct seam. Once-per-process startup maintenance, not reusing a non-Pi argv[1], Dreamer sibling ownership, and keeping ctx-status entries model-invisible while presenting them in RPC are all the right instincts. And noted that you already pushed the Dreamer owner-handoff stabilization mid-review — that resolves one of the items we had flagged, and that kind of responsiveness makes this easy to shepherd.
Two clarifications so we don't talk past each other:
- "RPC hosts" here is Pi RPC mode (
ctx.ui.notify/ctx.ui.custom). It does not change Magic Context's RPC server, which must stay on127.0.0.1with a bearer token. We checked; this PR does not touch that. - The old "second init in the process is a no-op" test should change — that contract is the bug for pi-web. Please keep the child-only skip test (you did).
Before we can merge:
- Dreamer
registeredProjectsonglobalThis(same jitimoduleCache:falsereason as the child marker), so two sessions in one repo don't start two timers. session_shutdowndraining only that session's in-flight work — in pi-web, shutdown is not process exit.- RPC presentation using the command's live
ctx, not asession_startclosure. - The #177 "never spawn bare
pi" test kept alongside the new embedded-host test. packages/pi-plugin/PARITY.mdupdated for RPC dialogs, the multi-session process model, and the latch → ALS change.
We've approved CI for this PR so your next push gets the full check suite. Really solid work — happy to re-review quickly.
There was a problem hiding this comment.
All reported issues were addressed across 21 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Uh oh!
There was an error while loading. Please reload this page.
870ff86 to
abc835fCompareelrond298
commented
Aug 21, 2026
Rebased onto the latest master ( |
Self-review against the upstream six-axis standard (calibrated on the PR cortexkit#350 review) found and fixes: - dreamer project registry moves to a globalThis Symbol.for holder so jiti moduleCache:false re-imports share one timer per project (duplicate-timer class, cortexkit#350-review must-fix 1); runtimeKeys ref-counting now actually spans module instances (+ test) - session_shutdown drains historian/recomp scoped to the shutting-down sessionId (awaitInFlightHistoriansFor/awaitInFlightRecompsFor), keeping process-wide variants as fallback; comments no longer assume shutdown == process exit; dream drain stays process-wide (project- scoped work, bounded wait) - PARITY.md §7a documents the embedded host model, adapter trust tier, init-gating split, and the known in-process-child limitation (F1); §13 points at scoped drains Known limitations documented rather than fixed: embedded-mode third- party in-process children still fully initialize (needs lifecycle-event marking, coordinate with upstream PR cortexkit#350). Test-depth gaps G1/G2 recorded in the self-review report (.cortexkit/alfonso/task-outputs/, untracked). Verification: pi-plugin typecheck clean, 809/809 tests passing.
alfonso-magic-context
left a comment
There was a problem hiding this comment.
Thanks for the rework — the quality jump since the last round is real, and most of it verified clean under a full re-review (all five prior items confirmed addressed at source; ALS suppression held up under a four-concurrent-child probe with an async hop; both suites green on the PR merged onto current master; no public adapter surface rides in, which matters because the API question is deliberately deferred to #353).
Four items block the merge, two of them reproduced by probe rather than read off the diff:
Stale sibling-worktree dreamer timer.
registerPiDreamerProjectkeeps the old owner in the shared owners map when a different owner re-registers the same project identity from another directory (src/dreamer/index.ts:157-185), and the retired timer's predicate checks only that old owner's entry and directory (:190-194) — not the current registration generation/activeOwner. A probe with owner A/worktree A then owner B/worktree B showed the old A client still prompts. The committed test (dreamer/index.test.ts:428-470) covers one owner changing directories and misses this. Bind scheduled clients to the current registration generation (or activeOwner+projectDir) and add the sibling-owner regression.Shutdown timeout abandons rather than cancels.
src/index.ts:2337-2373stops waiting after 5s whiletimeout.ts:1-14leaves the underlying promise alive; detached recomp/upgrade retainsctx(commands/ctx-recomp.ts:177-278) andpi-recomp-runner.ts:69-84callsonStatusChangefromfinallywithout a stale-context guard. Pi 0.83 invalidates command contexts after disposal, so long recomp work can outlive shutdown and throw on dead ctx/UI. Capture immutable session data up front, fence or cancel on shutdown, and guard post-await presentation.Native Pi 0.83 RPC dialogs are silently vacuous.
pi-command-utils.ts:180-190assumesctx.ui.customrenders or rejects, but Pi 0.83 rpc-mode implements it asPromise.resolve(undefined)— the catch fallback never runs, so native/external RPC hosts lose the detailed results entirely. It works in your host because pi-web supplies its own custom UI. Add a capability check with a portable notification fallback (and a test against the real 0.83 shape, not a functional fake), or scope the PARITY.md claim explicitly to hosts that provideui.custom.Missing #247 storm regression. The process-global latch you removed originally existed for the four-child in-process init storm. Our probe of your ALS scoping passed it — the implementation looks right — but no committed test reproduces the storm. Please add the parallel multi-child regression asserting every child registers no tools/events/background scans.
Nothing else stands between this and merge — the internals-first direction is settled on our side, and #353 tracks the public API question separately.
Scope in-process child detection to lifecycle AsyncLocalStorage so independent sessions initialize normally, and release lifecycle subscriptions on shutdown. Run startup maintenance once per process and defer session-history reads until the backfill lease is acquired. Resolve the child Pi CLI independently from embedded host argv, present command output through RPC notifications and dialogs, and ensure Dreamer registration before manual runs.
Handle multiple Pi sessions running in the same embedded host. - share Dreamer registration across plugin instances and hand its timer to the most recently registered remaining session - wait only for each session's historian, recomp, and Dreamer jobs during session_shutdown - keep agent_end synchronous so it does not delay turn completion - use the current command context to display status in Pi RPC mode - keep standalone Pi and embedded-host subagent launch regression tests - document the behavior in PARITY.md Tests: - NODE_ENV=test bun test src (813 passed) - NODE_ENV=test bun test session-project-backfill.test.ts (9 passed) - bun run build - bun run typecheck - bun run format:check
- reject Dreamer prompts after their registration owner is removed or switches worktrees - track complete manual runs, including domain lease waits, during shutdown - unregister the session owner before draining its Dreamer work - notify every registered owner after successful adjunct updates - add regression coverage for shutdown and multi-worktree races
- resolve manual runs through the active registration owner's options - reject ownerless and deregistered-owner requests - preserve process-shared argument order across extension reloads - cover refreshed owners, stale owners, and lease-wait draining
- fence Dreamer timers and late results across reloads and worktree handoffs - wait up to five seconds for recomp and upgrade tasks before canceling them - capture session state at command start and block late UI updates - fall back to notifications when RPC dialogs are unavailable - add regression coverage for concurrent child initialization
abc835f to
329dddfCompareelrond298
commented
Aug 22, 2026
Thanks for the detailed review. I addressed the four remaining items, rebased the branch onto
Additional points from the earlier review remain covered:
After rebasing onto The new CI and Smoke runs are currently waiting for workflow approval. Cubic reports that it skipped automatic review because the force-push rewrote the branch history, so it will need to be triggered manually. |
Summary
This PR adapts the Pi plugin for
pi-web, where multiple Pi sessions share one persistent Node.js process and commands run through Pi’s RPC mode.It addresses shared-process session isolation, duplicate startup work, unsafe subagent CLI detection, RPC command feedback, and
/ctx-dreamfailures before the first model turn.Changes
Session isolation
AsyncLocalStorage<boolean>marker.subagents:child:session-createdandsubagents:child:disposedevents.pi-webprocess to initialize normally.session_shutdownto prevent stale handlers after reloads.Process-wide startup maintenance
Safer subagent CLI detection
process.argv[1]only when it identifies a supported Pi CLI; otherwise use the packaged executable, bundled CLI, orPATHfallback as appropriate.RPC command presentation
ctx.ui.notify.ctx.ui.custom./ctx-status,/ctx-embed,/ctx-recomp,/ctx-session-upgrade, and/ctx-dream.Dreamer registration
/ctx-dreamrun./ctx-dreamto work before the firstbefore_agent_startevent.Verification
bun run --cwd packages/pi-plugin buildbun run --cwd packages/pi-plugin test— 804 passed, 0 failedbun test packages/plugin/src/features/magic-context/session-project-backfill.test.ts— 9 passed, 0 failedgit diff --checkRegression coverage includes:
/ctx-dreamregistration synchronizationNeed help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Supports
pi-webmulti-session and RPC hosts inpackages/pi-plugin, isolating work by session and owner. Old behavior suppressed all same‑process inits and drained all jobs on shutdown; new behavior suppresses only in‑process child subagents, drains only the shutting‑down session’s historian/recomp and the active owner’s Dreamer jobs (cancel after ~5s), and presents command output through the live RPC context.session_shutdown; keepagent_endsynchronous./ctx-dream, resolve manual runs through the active owner’s options, reject ownerless/deregistered requests, transfer/handoff ownership on exit, notify all owners after adjunct updates, preserve process‑shared argument order across extension reloads, prevent stale runs across worktrees, and track complete manual runs (including lease waits) during shutdown.ctx.ui.notify; detailed results orrpcDisplay: "dialog"viactx.ui.custom, with a fallback to notifications when dialogs are unavailable. Applied to/ctx-status,/ctx-embed,/ctx-recomp,/ctx-session-upgrade,/ctx-wrapup,/ctx-flush, and/ctx-dream. Capture session snapshots at command start and block late UI updates.session_shutdown; propagate cancellation to recomp and memory migration and abort remaining work after a short grace period.process.argv[1]only when the host is the Pi CLI; otherwise prefer the packaged binary, bundled CLI, orpion PATH. Never spawn with a shell.Written for commit 329dddf. Summary will update on new commits.
Greptile Summary
This PR adapts the Pi plugin to persistent multi-session and RPC hosts while isolating session-owned lifecycle and background work.
Confidence Score: 5/5
The PR appears safe to merge because no blocking failure remains.
No blocking failure remains.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD H[Persistent Pi host] --> S1[Session A extension] H --> S2[Session B extension] S1 --> C1[Session-scoped commands and jobs] S2 --> C2[Session-scoped commands and jobs] S1 --> D[Process-shared Dreamer registry] S2 --> D D --> O[Active project owner] O --> T[Scheduled and manual Dreamer work] S1 --> M[Process-wide startup maintenance] S2 --> M C1 --> U1[Live RPC UI context A] C2 --> U2[Live RPC UI context B]Reviews (7): Last reviewed commit: "fix(pi-plugin): harden embedded host lif..." | Re-trigger Greptile
Context used (3)