Skip to content

feat: unify CLI and web run lifecycle#232

Merged
roackb2 merged 2 commits into
mainfrom
codex/run-service-client-parity
Jul 11, 2026
Merged

feat: unify CLI and web run lifecycle#232
roackb2 merged 2 commits into
mainfrom
codex/run-service-client-parity

Conversation

@roackb2

@roackb2 roackb2 commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What changed

  • add a run-addressed control-plane subscription over ConversationRunService, including active-run recovery and stable public result projection
  • add shared client cursor, duplicate, sequence-gap, terminal, and bounded reconnect behavior used by both cli-v2 and web-v2
  • migrate CLI and browser activity delivery off the duplicate session EventEmitter path
  • announce queued run identities, refresh from terminal items, and bind cancellation/approval resolution to the observed run when available
  • deduplicate completion/approval notifications across detailed run activity, workspace lifecycle, and polling fallback
  • update service boundaries, architecture docs, and regression coverage

Why

Heddle already executed prompts, continuation, direct shell, and compaction through the public run service, but its own CLI and web clients still consumed a separate non-replayable session event path. That meant the experience inside Heddle differed from the lifecycle SDK users build against and could lose or duplicate activity across reconnects.

This change makes Heddle dogfood the same accepted identity, ordered replay, terminal, cancellation, and approval semantics exposed by the SDK while keeping the daemon/control-plane boundary intact.

Contract impact

  • controlPlane.sessionEvents now carries lifecycle/discovery, queue, approval, and durable-session signals rather than conversation activities.
  • detailed activity and result/cancel/error terminals move to controlPlane.sessionRunEvents({ sessionId, runId, afterSequence }).
  • controlPlane.sessionRunState now includes activeRun.
  • the compatibility REST session-events endpoint mirrors lifecycle signals; CLI and web use the replayable tRPC run stream.

Validation

  • yarn test — 109 unit files / 626 tests; 29 integration files / 285 tests
  • yarn typecheck
  • yarn lint
  • yarn build
  • yarn verify:tui-behavior
  • yarn test:browser-integration — 7 Playwright tests, including active-run recovery/replay after browser reload
  • public-repo search for private integration names returned no matches

@roackb2 roackb2 marked this pull request as ready for review July 11, 2026 06:35
@roackb2 roackb2 merged commit 1cd1b79 into main Jul 11, 2026
5 checks passed

@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: 151a52f329

ℹ️ 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 on lines 231 to +235
useEffect(() => {
setStreamConnected(subscription.status === 'pending');
}, [subscription.status]);
if (activeRun) {
ensureRunSubscription(activeRun);
}
}, [activeRun, ensureRunSubscription]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate active run address before subscribing

When the user switches from a session that still has an active run to another session, runControl.activeRun still contains the previous session's run for the render before its reset effect applies. This effect then calls ensureRunSubscription with the new workspaceId/sessionId but the old runId, so the new session subscribes to a non-existent run and starts the reconnect/error path on the wrong session. Include the run address in the tracked value or clear/validate the active run against the selected session before subscribing.

Useful? React with 👍 / 👎.

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