Skip to content

Add Happy Codex resume workflow and replay-safe restore#838

Open
KevinCJM wants to merge 9 commits intoslopus:mainfrom
KevinCJM:codex/happy-codex-resume
Open

Add Happy Codex resume workflow and replay-safe restore#838
KevinCJM wants to merge 9 commits intoslopus:mainfrom
KevinCJM:codex/happy-codex-resume

Conversation

@KevinCJM
Copy link

Summary

This PR adds a complete happy codex resume workflow for restoring a previously closed Happy Codex session with its prior conversation context and memory, while preventing restore-time replay bugs that could resend historical prompts to the model.

The changes are focused on happy-cli and include a usage guide for this branch.

Problems addressed

Before this change:

  • Restoring a closed Happy Codex session required manual environment variables and log inspection.
  • A restored Happy session could come back online but fail to decrypt app messages because a new session key was generated instead of reusing the original key.
  • Happy stored Codex identifiers, but restore did not use a native Codex resume path, so prior context and memory were not reliably restored.
  • resume launched a detached process only, which made it difficult to observe the restored session directly in the terminal.
  • Reconnected sessions could fetch messages from the wrong sequence cursor and replay already-processed messages.
  • Restore could enqueue and resend historical prompts that had already been answered, causing the model to answer old questions again.

What changed

1. Added a first-class happy codex resume command

File:

  • packages/happy-cli/src/index.ts

New command:

  • happy codex resume <session-id>

Capabilities:

  • Accepts restore inputs from session metadata or explicit flags.
  • Resolves restore inputs from:
    • --metadata-file
    • --path
    • --pid
    • --session-tag
    • --home-dir
    • --happy-home-dir
  • Supports --dry-run to validate a restore before launching.
  • Supports --detach for background restore mode.
  • Defaults to attached/foreground launch so the restored Happy UI is visible immediately in the terminal.

This removes the need to manually assemble restore environment variables and makes session restoration a supported CLI workflow.

2. Reused the original Happy session encryption key on restore

File:

  • packages/happy-cli/src/api/api.ts

Changes:

  • Restore mode now loads the saved session snapshot from ~/.happy-session-crypto.
  • If a saved dataKey exists for the session, the restore path reuses it instead of generating a new key.

Effect:

  • Restored Happy sessions can continue decrypting messages from the same app session.
  • Fixes the restore failure mode where the session appears online but messages do not produce responses because payloads cannot be decrypted.

3. Added a native Codex app-server restore client

File:

  • packages/happy-cli/src/codex/codexAppServerClient.ts

New functionality:

  • Added a dedicated restore client that talks to Codex app-server over stdio.
  • Supports:
    • initialization
    • thread/resume
    • turn/start
    • turn/interrupt
    • seeding saved session/conversation identifiers
  • Reuses the existing permission flow so restore remains compatible with normal Happy approval behavior.

Effect:

  • Restore no longer depends only on the older MCP compatibility path.
  • Happy can resume a previously saved Codex thread using a native resume flow when that thread is still available.

4. Added Codex identifier seeding to the MCP client

File:

  • packages/happy-cli/src/codex/codexMcpClient.ts

Changes:

  • Added seedSessionIdentifiers() support so previously saved Codex identifiers can be injected back into the client.

Effect:

  • Keeps restore-related identifier handling consistent across client implementations.
  • Supports first-turn continuation logic when identifiers already exist.

5. Implemented a full restore pipeline in runCodex

File:

  • packages/happy-cli/src/codex/runCodex.ts

Changes:

  • Loads saved Codex identifiers from the Happy session snapshot during startup.
  • Persists updated session snapshots so later restores have the latest:
    • Happy session crypto state
    • Codex session id
    • Codex conversation id
  • Uses the new app-server restore client when a saved Codex session is present.
  • Seeds the saved identifiers into the client before first use.
  • Falls back to local rollout transcript recovery when native thread resume is unavailable.
  • Extracts recent transcript context from local Codex rollout files when fallback is required.

Effect:

  • Restored Happy Codex sessions recover prior context more reliably.
  • Restore now prefers native thread continuation, while still retaining a local-context fallback path.

6. Fixed message cursor replay on reconnect

Files:

  • packages/happy-cli/src/api/apiSession.ts
  • packages/happy-cli/src/api/apiSession.test.ts

Changes:

  • ApiSessionClient no longer restarts its message cursor from an implicit zero-equivalent position.
  • Reconnect logic now initializes from session.seq so already-seen messages are not re-fetched.
  • Added regression coverage for reconnecting from an existing sequence cursor.

Effect:

  • Prevents reconnect-time replay of already-processed messages.
  • Removes one restore path that could cause duplicate message delivery.

7. Prevented restore from replaying historical prompts into the model

Files:

  • packages/happy-cli/src/codex/runCodex.ts
  • packages/happy-cli/src/codex/__tests__/resumeReplayFilter.test.ts

Changes:

  • During restore bootstrap, incoming user messages are buffered before entering MessageQueue2.
  • Happy explicitly performs thread/resume before normal queue processing resumes.
  • Buffered messages are compared against recent user content extracted from the saved transcript.
  • Messages that are already present in the previous transcript are filtered out instead of being re-enqueued.
  • Added regression tests for replay filtering helpers.

Effect:

  • Restoring a session no longer causes already-answered historical prompts to be merged into a fresh turn and sent back to the model.
  • Fixes the user-visible behavior where old prompts reappear in the terminal and get answered again after resume.

8. Added branch usage documentation

File:

  • docs/happy-codex-resume-fork.md

Contents:

  • Purpose of the branch
  • Setup and remotes
  • Build and validation steps
  • Restore usage examples
  • How to use the branch and prepare an upstream PR

Effect:

  • Documents the branch for reuse, validation, and review.

User-facing improvements

After this PR:

  • happy codex resume is a supported CLI command instead of a manual recovery procedure.
  • Restore can attach directly to the terminal UI by default, with an explicit detached mode when desired.
  • Restored sessions can preserve prior conversation memory and context.
  • Restore reuses the original Happy session encryption context, allowing message decryption to continue.
  • Restore no longer replays previously answered prompts back into the model.

Validation

Targeted tests executed:

cd packages/happy-cli
npx --yes yarn@1.22.22 test \
  src/api/apiSession.test.ts \
  src/codex/__tests__/emitReadyIfIdle.test.ts \
  src/codex/__tests__/resumeReplayFilter.test.ts
npx --yes yarn@1.22.22 build

Manual end-to-end validation performed:

  • Created a new Happy Codex session.
  • Stored explicit memory in the conversation.
  • Closed the session.
  • Restored the session using happy codex resume.
  • Verified the restored session retained memory/context.
  • Verified that previously answered prompts were not replayed after restore.

Scope

Included in this PR:

  • happy-cli restore workflow improvements
  • replay prevention fixes
  • reconnect cursor fix
  • branch usage guide

Not included:

  • app/server deployment changes
  • client compatibility changes for older mobile app bundles

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