Port fresh-agent canonical recovery subset#351
Conversation
Ported from ca8c188.
Ported the fresh-agent portions of bf59a03. Excluded Codex durability hunks that require the later durability subset.
Ported from ce6bb53. Excluded adjacent Codex durability dependencies from the stale dev stack.
Ported the canonical fresh-agent recovery portions of 9290e5f. Excluded sidebar live-terminal and Codex durability adjacent hunks for the later durability subset.
Port the fresh-agent canonical recovery portion of bf4f948. Exclude OpenCode lab-note churn and unrelated tabs range behavior from the stale dev-stack carrier.
Port the fresh-agent production runtime and replay-cache cleanup portions of 0dea351. Exclude Codex durability cleanup, sidecar deletion, launch-retry tests, and plan/doc residue from the stale carrier.
Remote legacy agent-chat snapshots now reopen as fresh-agent tabs while preserving the Claude mode from the source record.
Carry the canonical recovery prerequisite from e333d1a so copied legacy agent-chat panes can recover from UUID resumeSessionId values. This is limited to Claude canonical identity promotion and does not include Codex durability or OpenCode behavior.
Align shared session-contract coverage with canonical agent-chat resumeSessionId promotion carried for the fresh-agent recovery subset.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1fa8664fde
ℹ️ 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".
| const inputTokens = input.liveSession?.totalInputTokens ?? 0 | ||
| const outputTokens = input.liveSession?.totalOutputTokens ?? 0 | ||
| return FreshAgentSnapshotSchema.parse({ | ||
| sessionType: 'freshclaude', |
There was a problem hiding this comment.
Preserve session type when normalizing Claude snapshots
The Claude adapter is wired for both freshclaude and kilroy sessions (server/index.ts registers both to the same adapter), but the normalization layer hard-codes sessionType: 'freshclaude'. For kilroy threads this returns a mismatched contract payload from /api/fresh-agent/threads/:sessionType/..., so any client logic keyed by {sessionType, provider, sessionId} can mis-associate state and treat Kilroy sessions as Freshclaude. Thread/page/body normalization should carry through the caller’s actual session type instead of forcing freshclaude.
Useful? React with 👍 / 👎.
…replacement/fresh-agent-canonical-recovery-main-20260518
Summary
replacement/fresh-agent-foundation-main-20260518) and port the fresh-agent/canonical recovery subset from stale PR Stabilize dev green and canonical agent recovery #342.Depends on #350. This PR is intentionally main-targeted so GitHub can stack it over #350 until #350 lands.
Source content preserved
0dea351a: fresh-agent production runtime wiring, shutdown ownership, WebSocket create replay cache cleanup, focused production/ws tests.bf4f948d: canonical fresh-agent lost-session recovery and explicit restore-unavailable errors.9290e5f4: FreshAgentView recovery stabilization and canonical recovery tests.e02e695a: canonical restore/resume history fixture alignment.ce6bb53b: freshAgent WebSocket create/attach/send/interrupt/approval/question/kill/fork routing and subscription failure surfacing.bf59a03e: fresh-agent registry/persistence migration pieces, excluding Codex durability-only hunks.ca8c1882: valid canonical UUID fixture updates; OpenCode ownership expectation intentionally omitted.e333d1a9canonical ClauderesumeSessionIdpromotion, limited to shared session-contract recovery behavior needed by the selected subset.Verification
npm run test:vitest -- --run test/unit/client/components/fresh-agent/FreshAgentView.test.tsx test/unit/client/components/agent-chat/AgentChatView.session-lost.test.tsx test/e2e/agent-chat-resume-history-flow.test.tsx test/e2e/agent-chat-restore-flow.test.tsx test/unit/client/store/persisted-state.fresh-agent.test.ts test/unit/client/store/persistedState.test.ts test/unit/client/store/panesPersistence.test.tsnpm run test:vitest -- --run test/unit/shared/session-contract.test.ts test/unit/client/lib/session-contract.test.ts test/unit/client/components/TabsView.fresh-agent.test.tsx test/e2e/tabs-view-flow.test.tsx test/unit/client/components/TabsView.test.tsx -t "rehydrates remote agent-chat panes|session-contract|TabsView fresh-agent reopen|tabs view flow"npm run test:vitest -- --config vitest.server.config.ts --run test/unit/server/ws-handler-fresh-agent.test.ts test/unit/server/fresh-agent/production-wiring.test.ts test/server/session-association.test.ts -t "WsHandler fresh-agent routing|fresh-agent production wiring|Session-Terminal Association via onUpdate"npm run buildNote: an exploratory full
test/unit/client/components/TabsView.test.tsxrun still has the pre-existing/out-of-scope same-device other-window fixture failure. The subset-specific TabsView assertion added here passes.