Skip to content

feat(codex): map plan_delta to canonical turn.proposed.delta#11

Merged
ranvier2d2 merged 1 commit intomainfrom
feat/codex-plan-delta-mapping
Mar 25, 2026
Merged

feat(codex): map plan_delta to canonical turn.proposed.delta#11
ranvier2d2 merged 1 commit intomainfrom
feat/codex-plan-delta-mapping

Conversation

@ranvier2d2
Copy link
Collaborator

@ranvier2d2 ranvier2d2 commented Mar 25, 2026

Summary

  • Maps codex/event/plan_deltaturn.proposed.delta in codexEventMapping.ts — ~200 events per Codex turn were silently dropped, making the UI appear frozen while Codex streamed its plan
  • Follows the same extraction pattern as item/plan/delta (delta → text → content.text fallback chain)
  • Adds 5 direct unit tests against mapToRuntimeEvents + 1 integration test in CodexAdapter.test.ts
  • Verified ProviderRuntimeIngestion.ts already accumulates turn.proposed.delta via appendBufferedProposedPlan() — no consumer-side changes needed

Test plan

  • bun test codexEventMapping.test.ts — 5/5 pass (happy path, 2 fallbacks, 2 edge cases)
  • Type-check passes (tsc --noEmit)
  • Pre-existing adapter test timeouts confirmed unchanged (12 on main → 12 with change)
  • Manual: run Codex session and verify plan text streams in UI

🤖 Generated with Claude Code


Open with Devin

Summary by CodeRabbit

  • New Features
    • Handle Codex "plan_delta" events to emit incremental turn-proposal updates (streamed deltas).
  • Tests
    • Added unit and integration tests verifying delta extraction priority, correct emission of "turn.proposed.delta" events, and no events when delta is missing or empty.

@coderabbitai
Copy link

coderabbitai bot commented Mar 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f4feb0e1-1051-46b3-9350-b5824cd22b91

📥 Commits

Reviewing files that changed from the base of the PR and between bbfa758 and 90a04d3.

📒 Files selected for processing (3)
  • apps/server/src/provider/Layers/CodexAdapter.test.ts
  • apps/server/src/provider/Layers/codexEventMapping.test.ts
  • apps/server/src/provider/Layers/codexEventMapping.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/server/src/provider/Layers/codexEventMapping.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/server/src/provider/Layers/CodexAdapter.test.ts
  • apps/server/src/provider/Layers/codexEventMapping.test.ts

📝 Walkthrough

Walkthrough

Adds mapping for Codex provider events with method codex/event/plan_delta to emit canonical runtime events turn.proposed.delta, with delta extraction from multiple payload locations and tests covering integration and unit scenarios.

Changes

Cohort / File(s) Summary
Event Mapping Implementation
apps/server/src/provider/Layers/codexEventMapping.ts
Added mapping branch for codex/event/plan_delta that extracts delta from msg.delta, then msg.text, then msg.content.text; ignores empty results and emits a runtime event type: "turn.proposed.delta" when present.
Test Coverage
apps/server/src/provider/Layers/CodexAdapter.test.ts, apps/server/src/provider/Layers/codexEventMapping.test.ts
Added a live adapter lifecycle test and unit tests verifying delta extraction priority, empty-delta filtering, and that the adapter/mapper emits a canonical turn.proposed.delta event with the exact delta string.

Sequence Diagram

sequenceDiagram
    participant CodexProvider as Codex Provider
    participant EventMapper as codexEventMapping
    participant Runtime as Runtime Events

    CodexProvider->>EventMapper: emit raw event (method: codex/event/plan_delta)
    activate EventMapper
    EventMapper->>EventMapper: extract delta from payload\n(msg.delta → msg.text → msg.content.text)
    alt delta missing or empty
        EventMapper-->>Runtime: return empty array / drop event
    else delta present
        EventMapper-->>Runtime: emit canonical event\n(type: turn.proposed.delta, payload.delta)
    end
    deactivate EventMapper
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble at payloads, sniff for the trace,
msg.delta, then text, then content in place,
When a delta appears I hop with delight,
Emit a proposal into the light,
A small coded hop, and the plan takes flight. 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: mapping codex plan_delta events to the canonical turn.proposed.delta event type for UI streaming.
Description check ✅ Passed The description covers the required template sections: it explains what changed (event mapping), why (200 dropped events causing frozen UI), includes test evidence (5/5 passing tests), and references type-checking validation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/codex-plan-delta-mapping

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 25, 2026
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

* Unit tests for codexEventMapping — calls mapToRuntimeEvents directly
* without the full adapter/stream infrastructure.
*/
import { describe, it, expect } from "bun:test";

Choose a reason for hiding this comment

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

🔴 New test file imports from bun:test instead of @effect/vitest, violating AGENTS.md and project conventions

The new test file codexEventMapping.test.ts imports describe, it, and expect from bun:test, while every other test file in apps/server/src/ uses @effect/vitest (see e.g. apps/server/src/provider/Layers/CodexAdapter.test.ts:15, apps/server/src/provider/Layers/ProviderHealth.test.ts:2, and all ~18 other test files in the server). AGENTS.md explicitly states: "NEVER run bun test. Always use bun run test (runs Vitest)." The server's test script is "test": "vitest run" (apps/server/package.json). When vitest run processes this file, tests registered via bun:test's describe/it won't integrate with Vitest's runner — they'll either fail to import or silently not execute, meaning these tests provide no verification.

Prompt for agents
In apps/server/src/provider/Layers/codexEventMapping.test.ts, replace the import on line 5 from bun:test with @effect/vitest, matching the convention used by every other test file in the server app. Change:

import { describe, it, expect } from "bun:test";

to:

import { describe, it, assert } from "@effect/vitest";

Then update all expect() calls to use Node's assert module (assert.equal, assert.deepStrictEqual, etc.) or vitest's assert, matching the patterns in CodexAdapter.test.ts and other sibling test files. For example, expect(events).toHaveLength(1) should become assert.equal(events.length, 1), and expect(events[0]!.type).toBe("turn.proposed.delta") should become assert.equal(events[0]?.type, "turn.proposed.delta").
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/server/src/provider/Layers/codexEventMapping.test.ts`:
- Around line 64-67: The test currently uses a conditional guard that lets the
test pass if the mapped event type is wrong; replace the guards with explicit
assertions on the event type before asserting payload contents. Specifically, in
codexEventMapping.test.ts ensure you assert
expect(events[0]!.type).toBe("turn.proposed.delta") before accessing
events[0]!.payload.delta (and likewise assert the expected type at the second
occurrence around lines 84-86) so the test fails if the mapper returns the wrong
event type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f163cb7-6d48-43de-9455-7eb8acbfadd1

📥 Commits

Reviewing files that changed from the base of the PR and between 6610011 and bbfa758.

📒 Files selected for processing (3)
  • apps/server/src/provider/Layers/CodexAdapter.test.ts
  • apps/server/src/provider/Layers/codexEventMapping.test.ts
  • apps/server/src/provider/Layers/codexEventMapping.ts

Codex emits ~200 plan_delta events per turn that were silently dropped,
making the UI appear frozen while Codex streams its plan. Wire them
through codexEventMapping to the canonical turn.proposed.delta event,
matching the streaming fidelity of Claude/Cursor/OpenCode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ranvier2d2 ranvier2d2 force-pushed the feat/codex-plan-delta-mapping branch from bbfa758 to 90a04d3 Compare March 25, 2026 23:10
@ranvier2d2 ranvier2d2 merged commit c452e73 into main Mar 25, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant