Skip to content

fix(pi-plugin): support pi-web multi-session and RPC hosts - #350

Open
elrond298 wants to merge 5 commits into
cortexkit:masterfrom
elrond298:fix/pi-web-compat
Open

fix(pi-plugin): support pi-web multi-session and RPC hosts#350
elrond298 wants to merge 5 commits into
cortexkit:masterfrom
elrond298:fix/pi-web-compat

Conversation

@elrond298

@elrond298 elrond298 commented Aug 21, 2026

Copy link
Copy Markdown

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-dream failures before the first model turn.

Changes

Session isolation

  • Replace the process-global child-session flag with an AsyncLocalStorage<boolean> marker.
  • Update the marker through the public subagents:child:session-created and subagents:child:disposed events.
  • Suppress initialization only for in-process child subagents.
  • Allow independent sessions in the same pi-web process to initialize normally.
  • Remove child lifecycle listeners during session_shutdown to prevent stale handlers after reloads.

Process-wide startup maintenance

  • Claim deferred startup maintenance once per process.
  • Schedule the legacy-memory identity rekey introduced by database migration v22 only once per process.
  • Schedule the session-to-project mapping backfill only once per process.
  • Load session history only after acquiring the durable backfill lease, avoiding redundant JSONL scans.

Safer subagent CLI detection

  • Reuse process.argv[1] only when it identifies a supported Pi CLI; otherwise use the packaged executable, bundled CLI, or PATH fallback as appropriate.
  • This prevents embedded hosts such as Next.js from accidentally launching another web server when creating a subagent.

RPC command presentation

  • Preserve model-invisible command entries while presenting them through the RPC UI.
  • Show short progress updates through ctx.ui.notify.
  • Show formatted results in modal dialogs through ctx.ui.custom.
  • Apply this behavior to /ctx-status, /ctx-embed, /ctx-recomp, /ctx-session-upgrade, and /ctx-dream.

Dreamer registration

  • Track Dreamer registration ownership per Pi extension instance.
  • Prevent one session’s shutdown from deregistering a same-project sibling.
  • Transfer the active registration to a remaining worktree owner when necessary.
  • Synchronize the current project’s Dreamer registration immediately before a manual /ctx-dream run.
  • This allows /ctx-dream to work before the first before_agent_start event.

Verification

  • bun run --cwd packages/pi-plugin build
  • bun run --cwd packages/pi-plugin test804 passed, 0 failed
  • bun test packages/plugin/src/features/magic-context/session-project-backfill.test.ts9 passed, 0 failed
  • git diff --check

Regression coverage includes:

  • independent same-process sessions versus child-session suppression
  • lifecycle listener cleanup during shutdown
  • process-wide startup maintenance claimed through full runtime initialization
  • lazy backfill lease gating without session-history reads
  • owner-aware Dreamer registration, shutdown isolation, and ownership transfer
  • single-timer Dreamer handoff when remaining owners repeat a worktree directory
  • embedded-host Pi CLI discrimination
  • RPC notification and modal-dialog routing
  • pre-execution /ctx-dream registration synchronization

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Supports pi-web multi-session and RPC hosts in packages/pi-plugin and isolates 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, and presents command output through the live RPC context.

  • Scope child-session detection to lifecycle AsyncLocalStorage; remove lifecycle listeners on session_shutdown; keep agent_end synchronous.
  • Claim process‑wide startup tasks once and defer session‑history reads until the backfill lease is acquired.
  • Dreamer registration is shared per project and owner-aware: require an active registration owner for manual runs, ensure registration before /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.
  • Route command output through the live RPC context: short progress via ctx.ui.notify; detailed results or rpcDisplay: "dialog" via ctx.ui.custom. Applied to /ctx-status, /ctx-embed, /ctx-recomp, /ctx-session-upgrade, /ctx-wrapup, /ctx-flush, and /ctx-dream.
  • Await only the matching session’s historian and recomp during session_shutdown; drain only the active owner’s in‑flight Dreamer work with timeouts.
  • Resolve subagent CLI safely: reuse process.argv[1] only when the host is the Pi CLI; otherwise prefer the packaged binary, bundled CLI, or pi on PATH. Never spawn with a shell.

Written for commit abc835f. Summary will update on new commits.

Review in cubic

Greptile Summary

This PR adapts the Pi plugin to persistent, multi-session RPC hosts while isolating session lifecycle state and process-wide maintenance.

  • Uses async-context child-session detection instead of a process-global active-session latch.
  • Coordinates Dreamer registration and shutdown through per-instance ownership.
  • Scopes historian and recomp draining by session.
  • Routes command progress and detailed results through each live RPC context.
  • Hardens subagent CLI selection for embedded hosts.
  • Defers session-history scans until the durable backfill lease is acquired.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the eligible follow-up-review scope.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/pi-plugin/src/index.ts Reworks persistent-process initialization, child-session suppression, startup maintenance, project registration, and session-scoped shutdown.
packages/pi-plugin/src/dreamer/index.ts Adds process-shared owner-aware Dreamer registration, handoff, manual-run validation, and owner-scoped draining.
packages/pi-plugin/src/commands/pi-command-utils.ts Introduces command-context-bound RPC notifications and dialogs while retaining model-invisible status entries.
packages/pi-plugin/src/subagent-runner.ts Selects supported Pi launch targets without accidentally reusing an embedded host executable.
packages/pi-plugin/src/context-handler.ts Defers session-history loading until the durable project-backfill lease permits the scan.
packages/pi-plugin/src/pi-recomp-runner.ts Keys in-flight recomp work by session so one session does not drain another session’s tasks.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  H[Persistent pi-web process] --> S1[Pi session A]
  H --> S2[Pi session B]
  S1 --> C1[Session-scoped context and background work]
  S2 --> C2[Session-scoped context and background work]
  S1 --> D[Process-shared Dreamer registry]
  S2 --> D
  D --> O[Active project owner]
  O --> T[Scheduled and manual Dreamer runs]
  H --> M[Once-per-process startup maintenance]
  S1 --> R1[Live RPC command context A]
  S2 --> R2[Live RPC command context B]
  R1 --> U1[Session A notifications and dialogs]
  R2 --> U2[Session B notifications and dialogs]
Loading

Reviews (6): Last reviewed commit: "fix(pi-plugin): require owners for manua..." | Re-trigger Greptile

Context used:

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 17 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/pi-plugin/src/dreamer/index.ts Outdated
ualtinok added a commit that referenced this pull request Aug 21, 2026
…amer registry, session-scoped drains, presenter ctx capture; NOT a security blocker — rpc-server untouched)

Co-Authored-By: Alfonso <alfonso@cortexkit.io>

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 17 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/pi-plugin/src/dreamer/index.ts

@alfonso-magic-context alfonso-magic-context left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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:

  1. "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 on 127.0.0.1 with a bearer token. We checked; this PR does not touch that.
  2. 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 registeredProjects on globalThis (same jiti moduleCache:false reason as the child marker), so two sessions in one repo don't start two timers.
  • session_shutdown draining only that session's in-flight work — in pi-web, shutdown is not process exit.
  • RPC presentation using the command's live ctx, not a session_start closure.
  • The #177 "never spawn bare pi" test kept alongside the new embedded-host test.
  • packages/pi-plugin/PARITY.md updated 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.

@cubic-dev-ai cubic-dev-ai 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.

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

Comment thread packages/pi-plugin/src/dreamer/index.ts Outdated

@cubic-dev-ai cubic-dev-ai 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.

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

Comment thread packages/pi-plugin/src/dreamer/index.ts Outdated
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
@elrond298

Copy link
Copy Markdown
Author

Rebased onto the latest master (52e650c6) and force-pushed the updated branch. No functional changes were made as part of the rebase.

LZHcode1986 pushed a commit to LZHcode1986/magic-context-pi-web that referenced this pull request Aug 21, 2026
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.
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.

2 participants