Skip to content

[5283] fix(agent): Preserve Pi history after cold resume#5284

Closed
mmabrouk wants to merge 4 commits into
big-agentsfrom
docs/pi-session-continuity-design
Closed

[5283] fix(agent): Preserve Pi history after cold resume#5284
mmabrouk wants to merge 4 commits into
big-agentsfrom
docs/pi-session-continuity-design

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Jul 13, 2026

Copy link
Copy Markdown
Member

Problem

A cold local Pi continuation could report a successful native resume after its transcript had disappeared. The runner then sent only the newest user message, so Pi silently lost the earlier conversation. The same investigation found that Pi skill paths currently point into a throwaway per-run agent directory.

The immediate correctness bug is caused by identity-free loading: pinned pi-acp@0.0.29 does not return the loaded native session ID, while the compatibility wrapper substitutes the requested ID. That makes an unverified load look successful.

Refs #5283.

What changes

  • Cold Pi continuations no longer call native session/load while loaded identity cannot be verified.
  • A stale Pi continuity pointer is invalidated, a clean native session is created, and canonical Agenta history is replayed.
  • The new native ID is recorded only after the replayed turn succeeds.
  • Warm live Pi continuation is unchanged, and Claude native resume remains newest-message-only.
  • Structured logs record outcome=unverified replay=canonical without transcript content.
  • A production-shaped regression seeds a stale Pi pointer and proves the earlier marker reaches the clean session; a companion test protects Claude behavior.
  • The design workspace records the later, separate work for verified loads, durable transcripts, and append-only cwd skill snapshots.

Before and after

Before: cold Pi load appeared successful, the runner sent only the latest message, and missing native history became user-visible conversation loss.

After: every cold Pi load is conservative until identity evidence exists. Pi receives the full canonical transcript, so correctness does not depend on the temporary native transcript surviving.

Verification

  • pnpm exec vitest run tests/unit/sandbox-agent-qa-transcript-replay.test.ts -t "cold Pi native-history fallback": 2 passed.
  • pnpm exec vitest run tests/unit/continuation.test.ts: 7 passed.
  • pnpm run typecheck: passed.
  • Complete shared-workspace runner run: 1,045 passed; two older green-capture tests fail on an unrelated concurrently applied harness-ID contract change. Both new tests pass, and that contract change is not in this PR.
  • Pre-commit hooks passed for the implementation and documentation commits.

Local QA

Tested against the live local deployment on port 8280 with pi_core, local sandboxing, and the self-managed Codex subscription:

  1. After the 60-second keepalive TTL fully evicted the environment, turn 1 returned BETA-9 from turn 0.
  2. After a full sidecar restart and ownership-lease expiry, turn 1 returned ALPHA-7 from turn 0.
  3. Both runs logged a cold keepalive miss, canonical replay, outcome=unverified replay=canonical, a fresh native session create, and successful continuity sync.

What to review

  1. Confirm cold Pi bypasses the unverified resume branch and always sends plan.turnText.
  2. Confirm the stale pointer is invalidated before the clean session and replaced only after success.
  3. Confirm Claude resume behavior is unchanged.
  4. Treat Phase 0b identity verification, durable transcript storage, and skill snapshot migration as follow-up PRs rather than requirements for this launch gate.

@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 13, 2026 9:05pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

No new commits to review since the last review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d734ef27-5a83-4bda-8a78-3d16d0bc0a3f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

The PR adds design documentation for Pi session workspace materialization, including native-history verification, canonical replay, durable transcripts, and append-only skill snapshots. It also changes Pi continuity seeding to bypass unverified native session loads and adds tests covering Pi fallback and unchanged non-Pi resume behavior.

Changes

Session workspace materialization

Layer / File(s) Summary
Problem and current behavior
docs/design/agent-workflows/projects/session-workspace-materialization/README.md, context.md, research.md
Documents Pi transcript loss, session-load ambiguity, trust-gated resources, workspace lifecycle behavior, and current Claude skill materialization.
Verification and materialization design
docs/design/agent-workflows/projects/session-workspace-materialization/design.md, plan.md
Defines explicit native-history outcomes, canonical replay, durable transcript storage, single-writer rules, append-only skill snapshots, rollout phases, and delivery boundaries.
QA coverage and implementation status
docs/design/agent-workflows/projects/session-workspace-materialization/qa.md, status.md
Adds validation requirements for replay, durability, skills, lifecycle, security, and observability, and records Phase 0 status and next steps.
Pi continuity fallback
services/runner/src/engines/sandbox_agent.ts, services/runner/tests/unit/sandbox-agent-qa-transcript-replay.test.ts
Skips identity-unverified native continuation for Pi, invalidates continuity state, records canonical replay outcomes, and tests unchanged non-Pi resume behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the main Pi cold-resume history fix.
Description check ✅ Passed The description matches the changes and explains the Pi cold-resume fix, tests, and follow-up work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/pi-session-continuity-design

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mmabrouk mmabrouk added Custom Workflows Design documentation Improvements or additions to documentation needs-review Agent updated; awaiting Mahmoud's review labels Jul 13, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Please review two decisions before implementation: (1) only verified native history may use newest-message-only prompting; all uncertain loads replay canonical history, and (2) launch delivery stays split into the verified-load gate, durable transcripts, then append-only skills with no Claude reconciler.

naming. It uses the agent directory for credentials, private settings, global resources, custom
models, and native sessions.

Project `.pi/skills` and `.agents/skills` are trust-gated. RPC mode cannot display a trust prompt,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

explain this more what are trusted gated you did not define that

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Defined now in both places (commit 5eac8cb). Trust gating is Pi's project consent mechanism: the first time Pi runs in a cwd it asks whether to trust that project, and stores the decision in <agent-dir>/trust.json keyed by the canonical cwd path. Trust authorizes loading the project's own in-cwd configuration: .pi/settings.json, executable .pi/extensions, .pi/skills, .agents/skills, prompts, themes, and SYSTEM.md. RPC mode cannot show the prompt, so the default ask policy resolves to untrusted and none of these load. Added as a term in context.md and expanded in research.md, including the nuance that an installed extension can answer the trust request programmatically, so the Agenta extension must never do that.


Project `.pi/skills` and `.agents/skills` are trust-gated. RPC mode cannot display a trust prompt,
and the default `ask` policy leaves them unloaded. Trusting the whole cwd would also authorize
project settings and executable extensions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

arent the project settings and extensions outside of the cwd

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, these specific ones are inside the cwd: project settings are <cwd>/.pi/settings.json and project extensions are <cwd>/.pi/extensions (verified in Pi 0.80.6 source: package-manager.js:710,1924). What lives outside the cwd is the agent directory (PI_CODING_AGENT_DIR): auth.json, the global settings.json, models.json, and sessions. Pi has both a global and a project settings file, and only the project one is trust-gated. research.md now spells out the split (commit 5eac8cb).

@mmabrouk mmabrouk left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

lgtm

@mmabrouk mmabrouk added lgtm This PR has been approved by a maintainer and removed needs-review Agent updated; awaiting Mahmoud's review labels Jul 13, 2026
Launch gate ships without any pi-acp change: every cold Pi load starts
unverified and replays; verified loads return via Phase 0b (pi-acp
preferred, local runner header check as interim). Durable transcripts
lead with Pi's settings.json sessionDir override, which pi-acp's scan
paths also honor. Snapshots are immutable by convention. Defines
trust gating and pins the upstream behaviors the gate defends against.

Claude-Session: https://claude.ai/code/session_01XhENr63WL9npkKrJGnzDc1
@mmabrouk

Copy link
Copy Markdown
Member Author

Review updates (commit 5eac8cb)

Fact-checked every claim in research.md against the runner source, pinned Pi 0.80.6, and pi-acp@0.0.29. All confirmed. The review changed four things:

1. The launch gate no longer depends on changing pi-acp. pi-acp is an external prebuilt dependency and its load response carries no identity evidence, so at launch every cold Pi load is unverified and replays the canonical transcript. That is the intended behavior, not a regression. The pi-acp fix moved to a new Phase 0b as the preferred way to restore verified loads, with a runner-side header check as an acceptable interim: on local runs the runner shares the filesystem and HOME with Pi, knows the agent dir it created, holds the expected native ID, and already parses transcript headers in pi-error.ts — a pure file read, no new access path.

2. Durable transcripts now lead with Pi's supported session-directory override. Traced end to end: Pi resolves --session-dir / PI_CODING_AGENT_SESSION_DIR / settings.json sessionDir, and pi-acp reads the same settings key for its scan paths but ignores the env var. Writing sessionDir into the per-run agent directory's settings.json aligns both programs: Pi writes to durable storage, and pi-acp's session listing and its header-validating map-miss fallback scan the same directory. Mount extension and sessions-child link stay as fallbacks pending the Phase 1 fault-injection probe.

3. Snapshot immutability is stated as convention, not enforcement. The cwd is agent-writable and the completion record does not hash contents; accepted threat model, documented in design.md.

4. QA pins the upstream behaviors the gate defends against: Pi --session <path> silently creates a blank session at a missing path (the exact incident mechanism — the <id> form errors instead), and the 0.0.29 load response omits a session ID. A Pi or pi-acp upgrade that changes these fails a test instead of silently shifting the safety argument.

Also defined trust gating in context.md/research.md and clarified that project settings/extensions live inside the cwd (see inline replies).

https://claude.ai/code/session_01XhENr63WL9npkKrJGnzDc1

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Implementation has started on the approved launch gate. I agree with the conservative replay decision. I am treating the sandbox-agent ID substitution as Phase 0b cleanup because the launch fix will bypass cold Pi native loading entirely, create a clean Pi session, and replay canonical history. The final handoff will include focused tests and a live port 8280 cold-resume reproduction.

@mmabrouk mmabrouk added the implementing Design approved; implementation queued/in progress (not awaiting review) label Jul 13, 2026 — with ChatGPT Codex Connector
@mmabrouk mmabrouk changed the title [5283] docs(agent): Plan safe Pi session continuity [5283] fix(agent): Preserve Pi history after cold resume Jul 13, 2026
@mmabrouk mmabrouk added needs-review Agent updated; awaiting Mahmoud's review and removed implementing Design approved; implementation queued/in progress (not awaiting review) labels Jul 13, 2026
@mmabrouk
mmabrouk marked this pull request as ready for review July 13, 2026 21:06
@dosubot dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. Bug Report Something isn't working labels Jul 13, 2026
@mmabrouk

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Phase 0 is implemented, pushed, and ready for review.

  • ecb08f6: cold Pi bypasses identity-free native loading, invalidates the stale pointer, creates a clean native session, and sends canonical replay. The regression test proves Pi does not call resumeSession, retains the earlier marker, records the replacement native ID after success, and leaves Claude resume unchanged.
  • db88540: records the implementation and live QA, and moves wrapper ID substitution into Phase 0b. That is my only correction to the revised design: the cleanup is necessary before restoring verified loads, but it is not necessary for the launch gate because Phase 0 never attempts a cold Pi load.
  • Focused tests: 2 new replay tests passed; 7 continuity tests passed; typecheck passed.
  • Live local QA: BETA-9 survived full 60-second environment eviction, and ALPHA-7 survived a sidecar restart. Both runs logged canonical replay and outcome=unverified replay=canonical before creating a fresh native session.
  • GitButler scope was repaired and verified: this PR owns the two Pi runner files plus seven design files; the concurrent MCP PR owns only its separate policy hunk.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

@mmabrouk Got it — I'll review the latest changes now, focusing on:

  1. Confirming cold Pi bypasses the unverified resume branch and always sends plan.turnText.
  2. Verifying the stale continuity pointer is invalidated before the clean session is created, and only replaced after the replay succeeds.
  3. Confirming Claude's native resume (newest-message-only) path is untouched.
  4. Checking that the regression test in sandbox-agent-qa-transcript-replay.test.ts and the continuation.test.ts suite actually exercise these paths as described.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mmabrouk

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Final-head CI is green: manually dispatched workflow run 29285246373 passed runner unit tests and typecheck, runner acceptance tests, runner integration tests, services tests, and SDK tests on commit db88540241.

The automatic unit-test event had skipped because the push occurred while the PR was draft. The separate preview and Railway workflow entries that show red are workflow-file startup failures with zero jobs, not branch test failures; they are pre-existing repository workflow configuration and are not required checks.

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e8ec0a8c-7fb1-492d-adf5-6d49aa39e018

📥 Commits

Reviewing files that changed from the base of the PR and between 51dabc1 and db88540.

📒 Files selected for processing (9)
  • docs/design/agent-workflows/projects/session-workspace-materialization/README.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/context.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/design.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/plan.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/qa.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/research.md
  • docs/design/agent-workflows/projects/session-workspace-materialization/status.md
  • services/runner/src/engines/sandbox_agent.ts
  • services/runner/tests/unit/sandbox-agent-qa-transcript-replay.test.ts

Comment on lines +146 to +151
cold start, cold resume, or changed fingerprint
-> mount/create cwd and private transcript storage
-> materialize or validate the current skill snapshot
-> attempt verified native load
-> verified: send newest message only
-> anything else: create clean native session and send canonical replay

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the documentation consistent with the shipped cold-Pi gate.

Phase 0 does not verify or resume cold Pi sessions; it treats them as unverified, invalidates stale continuity, creates a clean native session, and replays canonical history. Verified native loads belong to Phase 0b.

  • docs/design/agent-workflows/projects/session-workspace-materialization/design.md#L146-L151: replace “attempt verified native load” in the cold-path sequence with the implemented clean-session replay flow.
  • docs/design/agent-workflows/projects/session-workspace-materialization/README.md#L3-L7: describe the immediate gate as conservative bypass/replay rather than native-load verification.
📍 Affects 2 files
  • docs/design/agent-workflows/projects/session-workspace-materialization/design.md#L146-L151 (this comment)
  • docs/design/agent-workflows/projects/session-workspace-materialization/README.md#L3-L7

@mmabrouk

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Closing this PR because its Phase 0 fallback changed every cold Pi continuation to canonical replay. That is not the approved launch behavior. The replacement work will persist Pi transcripts first, then stack the skill-folder fix, while preserving healthy native resume behavior.

@mmabrouk mmabrouk closed this Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Report Something isn't working Custom Workflows Design documentation Improvements or additions to documentation lgtm This PR has been approved by a maintainer needs-review Agent updated; awaiting Mahmoud's review size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant