fix(pi): isolate explicit cross-project memory saves - #1592
Conversation
Route project and cwd targets through project-owned satellites without rebinding the runtime session. Require isolation capability on each dispatch and validate roots and continuations before lease mutations.
Keep success and negative socket scenarios inside a trusted 0700 parent without weakening production hierarchy checks.
Keep disabled phase and pause reason until explicit resume while retaining outcome persistence and lease ownership. Use a private trusted parent in the CLI socket fixture so its shutdown assertion is exercised.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Repository UI Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (17)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Raw explicit project names can incorrectly route canonically equivalent same-project writes through satellite sessions.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Adds isolated Pi satellite sessions for explicit cross-project memory writes while preserving principal session ownership.
Changes:
- Routes explicit
project/cwdwrites through isolated satellite sessions. - Adds atomic server/store isolation enforcement and capability negotiation.
- Improves socket fixtures and autosync pause-state handling.
| File | Description |
|---|---|
plugin/pi/index.ts |
Implements explicit target resolution and satellites. |
plugin/pi/test/cross-project-saves.test.mjs |
Tests cross-project routing. |
plugin/pi/test/startup-lifecycle.test.mjs |
Tests guarded retries and recovery. |
plugin/pi/test/native-tool-contract.test.mjs |
Extends integration coverage. |
plugin/pi/test/index-source.test.mjs |
Updates source extraction assertions. |
plugin/pi/README.md |
Documents satellite routing. |
internal/store/store.go |
Adds atomic isolated registration. |
internal/store/isolated_session_test.go |
Tests isolation invariants. |
internal/server/server.go |
Exposes capability and isolated API. |
internal/server/server_test.go |
Expands directory behavior coverage. |
internal/server/isolated_session_test.go |
Tests isolated HTTP registration. |
internal/server/unix_socket_test.go |
Uses trusted private socket fixtures. |
cmd/engram/serve_socket_test.go |
Hardens CLI socket fixture. |
internal/cloud/autosync/manager.go |
Preserves upgrade-pause status. |
internal/cloud/autosync/manager_test.go |
Adds deterministic pause regressions. |
DOCS.md |
Documents the API contract. |
odd/tasks/pi-cross-project-saves.md |
Records implementation evidence. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const writeEpoch = writeState?.epoch; | ||
| const registeredSessionForWrite = async (sessionProject: string) => registerEffectiveSession(ctx, sessionProject, appendEntry, fetch); | ||
| const writeTarget = WRITE_TARGET_TOOLS.has(toolName) ? await resolveExplicitWriteTarget(params, fetch) : undefined; | ||
| const requestedProject = writeTarget?.project || (typeof params.project === "string" && params.project ? params.project : undefined); |

🔗 Linked Issue
Closes #1591
🏷️ PR Type
type:bug— Bug fixtype:featuretype:questiontype:docstype:refactortype:choretype:breaking-change📝 Summary
project/cwdwrites through isolated project-owned satellite sessions without changing principal ownership or inferring targets from edited files.📂 Changes
plugin/pi/index.tsinternal/server/server.go,internal/store/store.gointernal/server/unix_socket_test.go,cmd/engram/serve_socket_test.gointernal/cloud/autosync/manager.go,manager_test.goDOCS.md,plugin/pi/README.mdodd/tasks/pi-cross-project-saves.md🧪 Test Plan
cd plugin/pi && npm test— 272/272 PASS, real Go-server attribution included.go test -count=1 -v ./internal/server -run '^TestUnixSocket'— 6 top-level tests and 6 policy subcases PASS.go test -race -count=20 ./internal/cloud/autosync -run '^TestManager(StopForUpgrade|Resume)'— PASS independently.go vet ./cmd/engram/... ./internal/cloud/autosync/...and server/store vet — PASS.git diff --check— PASS.go test -count=1 ./...passed; independent full run had 28 passing packages, 1 plugin failure, 3 without tests.TestSubagentStopExplicitEmptyMessageSelection/primary_winsreported empty JSON body; subsequent focused, plugin-package and diagnostic-overlay runs each passed once. Cause unresolved, no Claude fix claimed.🤖 Automated Checks
Required checks remain pending until executed by GitHub: Check Issue Reference; Check Issue Has status:approved; Check PR Has type:* Label; Unit Tests; E2E Tests; Plugin Tests. Lint, transient-artifact, platform and other applicable checks also remain pending. No admin bypass or force merge is authorized.
✅ Contributor Checklist
type:*label requested:type:bug.Co-Authored-Bytrailers..codegraph/excluded.💬 Notes for Reviewers
Single-PR exception explicitly approved by maintainer: 1568 additions+deletions across 17 files, mainly regression evidence.
size:exceptionrequested; no code compression or artificial test splitting.Work units:
0f5fdf2explicit routing/isolation,5aa207eserver socket fixtures,66ed312CLI fixture/autosync pause,f2f78f2progress disposition.Native exact-candidate reviews approved/acknowledged:
review-bb33ea57146a0faf,review-38aa747720e5f3c1,review-fbee4168a9483776. Independent scoped gates passed. Nonblocking satellite-key collision advisory remains follow-up, not a correction reopened on the approved candidate.Deferred: unexplained intermittent Claude-hook test. Pause precedence is NOT cancellation, draining or rollback quiescence. Existing nonblank satellites fail closed rather than being silently repaired; older servers require upgrade for foreign-project writes. Merge must wait for fresh mandatory CI and repository policy.
Summary by CodeRabbit