Skip to content

🤖 feat: add actor-critic mode loop and source-aware rendering#2471

Open
ammar-agent wants to merge 13 commits intomainfrom
critic-mode-pgfx
Open

🤖 feat: add actor-critic mode loop and source-aware rendering#2471
ammar-agent wants to merge 13 commits intomainfrom
critic-mode-pgfx

Conversation

@ammar-agent
Copy link
Collaborator

@ammar-agent ammar-agent commented Feb 17, 2026

Summary

Adds an actor-critic mode loop where a critic LLM automatically reviews each actor turn and provides feedback until it signals /done. The main text input becomes the critic prompt in critic mode — no separate inline input field.

Background

Actor-critic is a workflow pattern where a "critic" LLM evaluates the "actor" LLM's output after each turn, providing iterative feedback. This enables autonomous self-improvement loops where the actor refines its work based on critic feedback until the critic is satisfied.

Implementation

Critic mode UX

  • /critic slash command toggles critic mode per workspace (persisted in localStorage)
  • When critic mode is on, the main textarea becomes the critic prompt input (placeholder changes to "Critic instructions...")
  • Sending a message in critic mode uses the message text as both the user message to the actor AND the critic's evaluation criteria
  • Simple badge indicator ("Critic mode active") in the footer — no separate inline input field

Actor-critic loop orchestration (agentSession.ts)

  • After each actor turn completes, if criticEnabled, a critic turn auto-fires
  • Critic turn uses role-flipped history (buildCriticRequestHistory), disables all tools, and injects critic-specific system instructions
  • Critic responds with feedback (injected back into actor context) or exactly /done to stop the loop
  • Loop guards: edit-pending check, queued user messages check, compaction handling

Critic message building (criticMessageBuilder.ts)

  • buildCriticRequestHistory — role-flips actor ↔ user messages for critic perspective
  • buildActorRequestHistoryWithCriticFeedback — transforms critic feedback into user-role messages for actor context, filtering out partial and /done messages
  • isCriticDoneResponse — detects /done sentinel, allowing reasoning parts but checking only visible text
  • buildCriticAdditionalInstructions — assembles critic system prompt from base instructions + user critic prompt

Source-aware rendering

  • Messages tagged with metadata.messageSource = "actor" | "critic"
  • data-message-source attribute on assistant/reasoning message DOM elements
  • messageSource threaded through stream events (stream-start, reasoning-delta, stream-end)

Resilience

  • Critic loop state preserved across stream interrupts for clean resume
  • shouldResumeAsCriticTurn inspects latest partial message metadata
  • Context-exceeded auto-compaction preserves critic settings

Validation

  • 11 UI integration tests covering: toggle, auto-loop, prompt forwarding, /done semantics, role-flip, reasoning persistence, context-exceeded recovery, model parity, queue priority, interrupt, disabled baseline
  • IPC integration test for critic resume across interrupt
  • 7 unit tests for isCriticDoneResponse and buildActorRequestHistoryWithCriticFeedback
  • make static-check passes

Generated with mux • Model: anthropic:claude-opus-4-6 • Thinking: xhigh • Cost: $20.56

@ammar-agent
Copy link
Collaborator Author

@codex review

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed the failing integration check by switching the new critic UI test from a bun:test import to Jest globals.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: f91158db9a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed queue-priority feedback:

  • queued user input now short-circuits actor-critic auto-continuation at stream end
  • added integration coverage for queued follow-up during critic streaming

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 70929b8143

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Aligned tests/ui/critic/criticMode.test.ts with the tests skill:

  • added shouldRunIntegrationTests() guard
  • removed direct updatePersistedState prompt mutation in favor of UI input interaction
  • replaced backend interruptStream API calls with UI "Stop streaming" interaction
  • replaced fixed sleeps with explicit stream-complete synchronization

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed the edit-precedence thread:

  • actor-critic auto-continuation now exits early when deferQueuedFlushUntilAfterEdit is armed
  • added IPC regression test (queuedMessages.completing) that reproduces edit-vs-continuation timing and asserts no critic auto-turn runs before the edit

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 78e85797d2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed the critic-resume thread:

  • useResumeManager now infers critic-turn resume intent from the latest partial assistant/reasoning message source and sends isCriticTurn: true
  • AgentSession.streamWithHistory now keeps an effectiveOptions view and infers critic-turn resume from persisted partial critic history as backend fallback
  • added tests/ipc/streaming/criticResume.test.ts covering interrupted critic turn resume semantics

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 84fd2e8d31

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed both new threads:

  • isCriticDoneResponse now permits reasoning parts while enforcing visible text equals /done exactly, with a new unit test suite in criticMessageBuilder.test.ts
  • useResumeManager critic-resume inference now inspects only the latest partial assistant/reasoning message to avoid stale older partial critic entries forcing critic-turn resumes

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 03461a1949

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed the /done parity thread:

  • extracted shared visible-text sentinel logic for critic done detection
  • buildActorRequestHistoryWithCriticFeedback now skips critic /done using the same reasoning-tolerant visible-text semantics as isCriticDoneResponse
  • expanded criticMessageBuilder.test.ts to cover reasoning+/done skip behavior and non-done critique retention

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: edb08de807

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed both latest threads:

  • stream-abort now preserves criticLoopState for critic-enabled turns so resumed loops retain original actor options (tool policy/additional instructions)
  • actor request history builder now drops partial critic assistant messages before converting feedback
  • extended critic builder unit tests + critic resume IPC test coverage for these cases

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Implement actor-critic mode across command parsing, send options, backend stream orchestration, and UI rendering.

- Add /critic toggle command and workspace-scoped critic prompt persistence.
- Add backend actor↔critic automatic turn loop with strict /done termination and critic-only tool disable policy.
- Persist actor/critic message source metadata and transform request history for critic role-flip + actor feedback.
- Render critic reasoning/assistant output with dedicated source badges and styling.
- Expand mock router/player plumbing and add comprehensive UI coverage for looping, /done semantics, context recovery, and interrupt behavior.

Validation:
- make static-check
- bun test ./tests/ui/critic/criticMode.test.ts
- bun test ./src/browser/utils/slashCommands/parser.test.ts ./src/browser/utils/slashCommands/suggestions.test.ts ./src/browser/utils/messages/sendOptions.test.ts

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$19.73`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=19.73 -->
The integration CI suite runs tests with Jest, not bun:test. Replace the bun:test import in the new critic-mode UI suite so the file uses the same Jest global pattern as other `tests/ui/*.test.ts` files.

Validation:
- env TEST_INTEGRATION=1 bun x jest --maxWorkers=100% --silent tests/ui/critic/criticMode.test.ts
- make static-check

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$19.73`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=19.73 -->
When a user sends a follow-up during a critic-streaming turn, the queued message should be processed before the actor-critic loop starts another automatic continuation turn.

- Stop actor-critic auto-continuation when queued user input exists at stream end.
- Clear critic loop state in that branch so the queued user turn can own continuation semantics.
- Add a UI integration test that queues user input during critic streaming and asserts the queued turn executes before auto-continuation.

Validation:
- bun test ./tests/ui/critic/criticMode.test.ts
- env TEST_INTEGRATION=1 bun x jest --maxWorkers=100% --silent tests/ui/critic/criticMode.test.ts
- make static-check

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$19.73`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=19.73 -->
Reduce the mocked critic stream length in the new queue-priority scenario so CI workers can still queue input during streaming without timing out waiting for the critic turn to finish.

Validation:
- bun test ./tests/ui/critic/criticMode.test.ts
- env TEST_INTEGRATION=1 bun x jest --maxWorkers=100% --silent tests/ui/critic/criticMode.test.ts
- make static-check

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$19.73`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=19.73 -->
In critic mode, the main text input now serves as the critic prompt input.
Removes the separate inline critic prompt field and its wrapper row.

- Textarea placeholder changes to "Critic instructions..." when critic mode is on
- Sending in critic mode uses the message text as the critic prompt (persisted
  for resumability and override in send options)
- Badge kept as a simple standalone indicator
- Removed unused setCriticPromptFromUi/findCriticPromptInput test helpers
- Updated 3 tests to reflect new UX model (TDD approach)

Generated with `mux` · anthropic:claude-opus-4-6 · xhigh · $20.56
@ammar-agent
Copy link
Collaborator Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 5c87e16b99

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Command prefixes (e.g. /haiku) were included in the critic prompt
because we used messageText (raw input) instead of actualMessageText
(parsed send payload). Now the critic evaluates against the same text
the actor sees.
@ammar-agent
Copy link
Collaborator Author

@codex review

Fixed: critic prompt now uses actualMessageText (parsed send payload) instead of messageText (raw input), so command prefixes like /haiku are stripped.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

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: 3b9d36c3e2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

When a critic turn is interrupted and resumed, the frontend only sets
isCriticTurn/criticEnabled. The tool-disable policy and critic system
instructions (including /done contract and user critic prompt) were
missing, allowing unintended tool execution on resumed critic turns.

Now streamWithHistory ensures critic guardrails are applied whenever
isCriticTurn is true, using criticLoopState (preserved across aborts)
to recover the original actor instructions and critic prompt.
@ammar-agent
Copy link
Collaborator Author

@codex review

Addressed: critic guardrails (tool-disable policy, critic system instructions, /done contract) are now reapplied when resuming critic turns via streamWithHistory. Uses criticLoopState (preserved across aborts) to recover the original actor instructions and critic prompt on resume.

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

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

Comments