Skip to content

Emit completed Codex plan artifacts via negotiated plan_update - #333

Open
s-cork wants to merge 3 commits into
agentclientprotocol:mainfrom
anvil-works:stu-dev/plan-updates-main
Open

Emit completed Codex plan artifacts via negotiated plan_update#333
s-cork wants to merge 3 commits into
agentclientprotocol:mainfrom
anvil-works:stu-dev/plan-updates-main

Conversation

@s-cork

@s-cork s-cork commented Jul 24, 2026

Copy link
Copy Markdown

Summary

  • emit completed live Codex plan artifacts as ACP plan_update events when the client advertises the unstable clientCapabilities.plan capability
  • replay saved plan artifacts through the same capability-dependent representation
  • preserve the fix: Emit plan contents in plan mode #326 agent_message_chunk fallback for clients without that capability
  • leave standard ACP v1 sessionUpdate: "plan" execution-plan updates unchanged
  • keep completed item text authoritative, with buffered deltas as a fallback

Rationale

#326 fixed plan visibility by emitting completed Codex plan items as ordinary final-answer messages. That preserves broad client compatibility, but loses the plan semantic: a client cannot reliably distinguish a proposed plan from an ordinary final answer.

ACP currently exposes two related representations:

  • standard v1 sessionUpdate: "plan", a complete execution-plan snapshot containing entries, priorities, and progress statuses
  • unstable plan_update, a richer plan artifact that can preserve Markdown content and a stable planId

A completed Codex ThreadItem of type plan contains authoritative Markdown and a stable item ID. It therefore maps losslessly to a Markdown plan_update. Mapping it to the standard entry-based notification would require parsing the Markdown or inventing entry boundaries, priorities, and statuses, and would not preserve equivalent artifact identity.

This PR does not replace or change the standard execution-plan notifications Codex already emits. It only changes the representation of the completed plan artifact when the client explicitly advertises support for the unstable richer update.

Compatibility

Clients without the unstable Plan capability retain the #326 representation:

  • agent_message_chunk
  • the Codex plan item ID as messageId
  • _meta.codex.phase: "final_answer"

The same choice is applied to live events and replayed session history.

Open design question

Should a completed Codex plan item be represented by the negotiated richer plan_update, as implemented here, or should it be mapped into the standard entry-based plan notification? The current implementation chooses the lossless richer representation when negotiated and preserves #326 as the fallback. Feedback on the intended protocol model is welcome.

Testing

  • npm run typecheck
  • npx vitest run src/__tests__/CodexACPAgent/load-session.test.ts — includes legacy replay without Plan capability
  • npm test — 329 passed, 28 skipped
  • npm run bundle:all with Bun 1.3.11
  • git diff --check main...HEAD

Related work

AI assisted with implementation, test verification, and PR text.

@s-cork
s-cork marked this pull request as draft July 24, 2026 08:44
@s-cork s-cork changed the title Emit proposed plans for plan-capable clients Emit completed Codex plan artifacts via negotiated plan_update Jul 27, 2026
@s-cork
s-cork marked this pull request as ready for review July 27, 2026 01:31
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