Skip to content

feat: add Zero exec resume and fork sessions#32

Merged
Vasanthdev2004 merged 2 commits into
mainfrom
feat/m3-resume-fork
Jun 3, 2026
Merged

feat: add Zero exec resume and fork sessions#32
Vasanthdev2004 merged 2 commits into
mainfrom
feat/m3-resume-fork

Conversation

@gnanam1990

Copy link
Copy Markdown
Collaborator

Summary

  • add a Zero exec session resolver for new, resumed, and forked runs
  • extend the session event store with latest-session lookup, fork lineage metadata, and append-only event copying
  • wire zero exec --resume [id] and zero exec --fork <id> into headless runs with persisted user, assistant, tool, usage, and crash events
  • include sessionId in stream-json run_start events and update the protocol example

Why

This gives headless Zero runs a durable session lifecycle so later CLI and TUI flows can continue prior context or branch from an existing run without losing lineage.

Validation

  • npx --yes bun test ./tests --timeout 15000
  • npx --yes bun run typecheck
  • npx --yes bun run build
  • npx --yes bun run smoke:build
  • ./zero exec --help
  • OPENAI_API_KEY= ./zero exec hi --resume abc --fork def --output-format stream-json
  • git diff --check origin/main..HEAD

Reviewers

Please review: @Vasanthdev2004 @anandh8x

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

Blockers

None found.

Non-Blocking

  • None.

Looks Good

  • Session store changes validate session IDs, preserve fork lineage, copy append-only parent events, and keep deterministic latest-session ordering.
  • Headless exec now records user/assistant/tool/usage/crash events, exposes sessionId in stream-json run_start, and rejects ambiguous resume/fork options before provider setup.
  • Validation passed: 212/212 tests, typecheck, build, smoke:build, git diff checks, and CI smoke checks on Ubuntu/macOS/Windows/Performance are green.
  • Manual smoke on the built zero.exe covered exec --help plus new/resume/fork runs against a local OpenAI-compatible probe; 668 additions, 5 deletions is focused for durable exec-session support.

Verdict: Approve — Clean exec session resume/fork foundation.

@Vasanthdev2004 Vasanthdev2004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved after local validation and behavior review.

@gnanam1990
gnanam1990 force-pushed the feat/m3-resume-fork branch from 6ac0b5c to a422f18 Compare June 3, 2026 10:28
@gnanam1990

Copy link
Copy Markdown
Collaborator Author

Rebased PR #32 onto latest main after PR #30 landed and resolved the exec runtime/session conflicts.

Kept the new runtime context/list-tools flow and restored session resume/fork preparation, contextual prompt wrapping, session event persistence, and regression coverage.

Validation after the rebase:

  • npx --yes bun test ./tests --timeout 15000 -> 227 pass, 0 fail
  • npx --yes bun run typecheck -> pass
  • npx --yes bun run build -> pass
  • npx --yes bun run smoke:build -> pass
  • built ./zero exec --help -> includes runtime flags plus --resume/--fork
  • built resume/fork conflict probe -> usage error exit 2
  • built --list-tools --enabled-tools read_file,grep probe -> exit 0
  • git diff --check origin/main..HEAD -> clean

Please re-review when CI finishes: @Vasanthdev2004 @anandh8x

@gnanam1990
gnanam1990 requested a review from Vasanthdev2004 June 3, 2026 10:28

@anandh8x anandh8x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review: Zero exec resume and fork sessions

No blockers. Clean session lifecycle extension with lineage tracking.

What's good

  • prepareZeroExecSession — Clean tri-mode (new/resume/fork) with mutual exclusion enforced at both CLI and domain layer
  • Promise queueappendSessionEvent chains on a serialized promise for non-blocking ordered writes without locks
  • Prompt contextformatZeroExecSessionPrompt truncates at 20 events, 500 chars per event, with redactZeroString — no unbounded context or secret leaks
  • Fork lineageparentSessionId, forkedFromEventId, forkedFromSequence in metadata plus session_fork event marker provide full fork tree auditability
  • cloneJsonValue — JSON round-trip for deep-copying event payloads to forks (handles undefined gracefully)
  • getLatestSession — Simple delegation to listSessions which sorts by updatedAt desc; correct for current scale
  • --resume omits id — Auto-selects latest session; convenient for sequential continuation
  • createSessionTitle — First 80 chars of prompt, handles empty/whitespace
  • Stream-json integrationsessionId added to run_start event, protocol doc updated
  • Event coverage — User message, tool calls/results, provider usage, assistant message, and crash errors all recorded
  • Crash resiliencesession_fork appended last, so partial forks (mid-copy crash) are detectable by its absence
  • Test coverage — 335 lines of tests covering: new session, resume latest, resume by id, fork with override, conflict errors, missing targets, session id in stream-json, event recording, fork lineage metadata

Minor issue

  • formatZeroExecSessionPrompt label for resume-of-fork — Line 359: prepared.session.parentSessionId ?? prepared.session.sessionId. For fork mode this correctly shows the parent. But for resume mode on a forked session, it shows the parent's ID ("Continuing Zero session parentId") instead of the fork's own sessionId. Should use session.sessionId for resume mode and session.parentSessionId for fork mode:
    const displayId = prepared.mode === 'fork'
      ? prepared.session.parentSessionId
      : prepared.session.sessionId;
    
    Non-blocking — cosmetic label only, doesn't affect correctness.

Observations (non-blocking)

  • Promise queue cascading rejectionappendSessionEvent chains onto sessionEventQueue. If one write fails, the queue becomes rejected and the final await in both success and crash paths throws. The secondary throw in the catch block is unhandled. Could use sessionEventQueue.catch(() => {}) to isolate, but acceptable since session writes are secondary to stdout/stderr output
  • forkSession copies events serially via appendEvent — Each event triggers a metadata rewrite (writeMetadata with incremented eventCount). Could be optimized with batch append, but correct and simple for M3
  • No --context-events option — Full history truncated to 20 events in prompt. Longer sessions silently lose context. Future enhancement candidate

@Vasanthdev2004
Vasanthdev2004 merged commit 5b01fbb into main Jun 3, 2026
4 checks passed
@Vasanthdev2004
Vasanthdev2004 deleted the feat/m3-resume-fork branch June 28, 2026 08:27
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.

3 participants