Skip to content

regression: lock durable Session reconnect semantics#953

Merged
dennisonbertram merged 5 commits into
developfrom
test/950-session-durability
Jul 11, 2026
Merged

regression: lock durable Session reconnect semantics#953
dennisonbertram merged 5 commits into
developfrom
test/950-session-durability

Conversation

@dennisonbertram

Copy link
Copy Markdown
Owner

Why

Fixes #950. Parent epic: #931.

Durable interactive coding depends on two independent persisted identities: the chat workflow referenced by chats.activeStreamId, and the Session workspace referenced by sessions.sandboxState.sandboxName. This PR protects the path where a user starts long-running work, disconnects or refreshes, and returns to the same workflow and persistent workspace without duplicate work or a replacement sandbox.

The audit found the core durability behavior already correct. One real violation remained: sandbox pause/reconnect/resume failures could echo raw provider messages to logs or API clients, and recovery responses lacked stable typed evidence.

What changed

Characterization and regression coverage

  • Proves repeated stream GETs reattach to the same active workflow without mutating activeStreamId.
  • Retains existing coverage that POST chat reconnects to a running workflow without invoking start() again.
  • Retains terminal-state coverage for completed, cancelled, failed, and absent workflows, including compare-and-set protection for a newer stream owner.
  • Proves sandbox reconnect and resume stop before provider access across ownership boundaries.
  • Proves persistent pause/resume reuses session_<sessionId>.
  • Proves repeated resume is idempotent: one provider reconnect, followed by alreadyRunning without a second reconnect or write.
  • Proves persistent provider state and legacy snapshot migration remain distinct; createIfMissing is still limited to the explicit legacy migration path.
  • Proves typed failure/warning responses and logs do not expose injected provider-token text.

Small behavior fix

  • Adds safe requestId correlation to reconnect and lifecycle responses.
  • Adds sandboxName and restoredFrom evidence to successful resume responses.
  • Adds stable recovery kinds:
    • sandbox_reconnect_transient
    • sandbox_unavailable
    • sandbox_pause_failed
    • sandbox_resume_state_missing
    • sandbox_resume_unavailable
    • sandbox_resume_failed
  • Replaces raw provider-error logging and response text with structured, redacted lifecycle evidence.
  • Preserves the existing status semantics: transient reconnect errors retain persisted state, hard-unavailable runtimes transition to hibernated recovery, and missing persistent sandboxes require explicit new-sandbox recovery.

Documentation

  • Adds docs/process/session-durability-proof.md with sources of truth, ownership/idempotency rules, safe evidence vocabulary, Level 1 proof, and exact live-provider proof limits.
  • Links that proof from apps/web/SANDBOX-LIFECYCLE.md.
  • Records the redaction lesson in docs/agents/lessons-learned.md.

TDD audit trail

  • RED commit: 83e38522 test: characterize durable session reconnect semantics
    • 21 assertions were already green characterization.
    • 6 assertions were intentionally RED for the confirmed identity/typing/redaction gaps.
  • GREEN commit: b47186ac fix: make session recovery evidence safe and typed

This does not manufacture a durability behavior change: stream ownership, workflow starts, sandbox naming, resume policy, and provider connection policy are unchanged.

Out of scope

  • New sandbox providers or managed-runtime profile authoring.
  • Session UI redesign.
  • Automation/Run execution or schema consolidation.
  • Changing persistent Session sandboxes to disposable workspaces.
  • Changing fresh-per-run/fresh-per-step policies used by background agents or loops.
  • Production deployment or live-provider durability claims.

How it was verified

Focused GREEN suite

bun test --isolate \
  'apps/web/app/api/chat/[chatId]/stream/route.test.ts' \
  apps/web/app/api/sandbox/reconnect/route.test.ts \
  apps/web/app/api/sandbox/snapshot/route.test.ts

Result: 27 passed, 0 failed.

Adjacent durability suite

bun test --isolate \
  'apps/web/app/api/chat/[chatId]/stream/route.test.ts' \
  apps/web/app/api/chat/route.test.ts \
  apps/web/app/workflows/chat.test.ts \
  apps/web/app/api/sandbox/reconnect/route.test.ts \
  apps/web/app/api/sandbox/snapshot/route.test.ts \
  apps/web/app/api/sandbox/route.test.ts \
  apps/web/app/api/sandbox/status/route.test.ts \
  apps/web/app/api/sessions/_lib/session-context.test.ts \
  apps/web/lib/sandbox/utils.test.ts \
  apps/web/lib/sandbox/lifecycle.test.ts \
  apps/web/lib/sandbox/lifecycle-kick.test.ts \
  packages/sandbox/vercel/sandbox.test.ts

Result: 200 passed, 0 failed.

Repository gates

  • bun run --cwd apps/web typecheck — passed.
  • bun --bun run check — passed.
  • git diff --check — passed.
  • bun --bun run ci — all 793 isolated test files passed; all package typechecks passed; migrations are in sync.

Browser and live proof

Authenticated Agent Browser reconnect smoke is blocked by configuration in this isolated worktree:

  • apps/web/.env.local is absent.
  • POSTGRES_URL is absent.
  • BETTER_AUTH_SECRET is absent.
  • The prescribed ./init.sh --force-env-pull --verify attempt stopped with: Vercel project is not linked. Rerun with --link-vercel --vercel-project <name>, or use --offline.

The task did not authorize selecting/linking an external Vercel project, so no link was guessed and no authenticated browser claim is made.

Evidence quality and exact proof limits

This PR provides Level 1 deterministic route/workflow/adapter proof. Workflow and Vercel Sandbox calls are doubles. It does not prove:

  • a deployed Workflow run replayed real chunks after browser disconnect,
  • Vercel retained a real MicroVM across hibernation,
  • repository files and branch state survived a provider-level resume,
  • local, preview, or production UI states during a real reconnect.

Level 2 requires configured auth/database state, a disposable repository, a real sandbox name captured before and after resume, workflow/stream evidence across refresh, repository/branch checks inside the resumed sandbox, and redacted browser/server/provider evidence.

Risk and rollback

There is no migration or environment change. Existing clients continue to receive the existing status, error, success, and alreadyRunning fields; typed metadata is additive. The only copy change replaces raw provider details with safe actionable messages. Rollback is a focused revert of the GREEN commit; existing Session rows, workflow ids, and sandbox names are untouched.

The first push hook scanned unrelated files under .worktrees/create-repo-897 and failed on their pre-existing formatting. This branch itself passed full CI, so the documented SKIP_HOOKS=1 bypass was used. No unrelated worktree files were changed.

Reviewer guide

  1. Start with docs/process/session-durability-proof.md for the contract and proof boundary.
  2. Review apps/web/app/api/chat/[chatId]/stream/route.test.ts for stream reuse and compare-and-set behavior; production stream routing is intentionally unchanged.
  3. Review apps/web/app/api/sandbox/reconnect/route.ts for additive correlation/typed warning evidence and redacted structured logs.
  4. Review apps/web/app/api/sandbox/snapshot/route.ts for persistent-name evidence, typed pause/resume recovery, and provider-message redaction.
  5. Review the two route tests for ownership, idempotency, policy preservation, and secret-canary assertions.

Please pay particular attention to the fact that transient reconnect failures still preserve runtime state, while hard unavailable errors still clear only the runtime/resume state dictated by existing utility policy.

Open PR overlap audit

@vercel

vercel Bot commented Jul 11, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
open-agents Ready Ready Preview, Comment Jul 11, 2026 5:50pm

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b47186ac02

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/web/app/api/sandbox/snapshot/route.ts
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.

1 participant