Default goal continuation can preserve stale Plan Mode instructions when developer_instructions is null

Open 💬 2 comments Opened Jun 1, 2026 by BWAAEEEK

Summary

I hit a /goal-adjacent variant of the stale Plan Mode issue where the recorded/logical collaboration mode was Default, but the assistant continued to behave as if Plan Mode was still active.

This looks related to #18954 / #10185, but this report adds a narrower root-cause hypothesis and a minimal core-level characterization test.

Observed behavior

In a local Codex session:

  • A goal was active.
  • Several turns were recorded as Default mode:
  • collaboration_mode_kind = "default"
  • collaboration_mode.mode = "default"
  • However, those same turns had:
  • collaboration_mode.settings.developer_instructions = null
  • During those Default/null turns, the assistant repeatedly emitted <proposed_plan> and said it could not edit/create files because it was still in Plan Mode.
  • A later Default turn included the Default collaboration developer instructions again:
  • # Collaboration Mode: Default
  • “Any previous instructions for other modes ... are no longer active.”
  • Immediately after that reset instruction reappeared, the assistant resumed implementation behavior.

So the symptom was not simply “the user is still in Plan Mode.” The recorded mode was Default, but the model-visible instruction state still appeared to contain stale Plan Mode constraints.

Current main checked

I checked current main at:

cf0911076f234e0219bd8d61dd3bc2f80a2df287

Current app-server turn/start appears to mitigate this for normal v2 turn requests:

  • codex-rs/app-server/src/request_processors/turn_processor.rs
  • TurnProcessor::normalize_collaboration_mode(...)
  • If developer_instructions is missing, it fills from builtin_collaboration_mode_presets().

That means the normal app-server request path may already be safer now.

However, the core context update path still has the failure mode if a Default collaboration mode with missing instructions reaches core.

Suspected root cause

In codex-rs/core/src/context_manager/updates.rs, build_collaboration_mode_update_item(previous, next) detects a collaboration mode change, but then does:

CollaborationModeInstructions::from_collaboration_mode(&next.collaboration_mode)?

In codex-rs/core/src/context/collaboration_mode_instructions.rs, from_collaboration_mode returns None when settings.developer_instructions is None or empty.

The consequence is already described by the source comment in updates.rs:

// If the next mode has empty developer instructions, this returns None and we emit no
// update, so prior collaboration instructions remain in the prompt history.

That matches the observed rollout shape: logical Default mode, but no Default reset developer message, so earlier Plan Mode instructions can remain model-visible.

Goal-mode relevance

This may be triggered or made visible by goal continuation:

  • codex-rs/core/src/goals.rs
  • maybe_start_goal_continuation_turn starts a continuation with new_default_turn_with_sub_id(...).
  • should_ignore_goal_for_mode returns true only for ModeKind::Plan, so Default-mode goal continuation is allowed.

This supports the hypothesis that /goal itself is not forcing Plan Mode. Instead, a goal continuation/resume/internal turn can be logically Default while still missing the Default collaboration reset instructions.

Minimal characterization test

I added this local characterization test against codex-core:

#[tokio::test]
async fn build_settings_update_items_omits_collaboration_reset_for_default_without_instructions() {
    // previous: Plan mode with developer instructions
    // next: Default mode with developer_instructions: None
    // observed: no developer collaboration reset/update is emitted
}

Command:

cargo test -p codex-core build_settings_update_items_omits_collaboration_reset_for_default_without_instructions

Result:

running 1 test
test session::tests::build_settings_update_items_omits_collaboration_reset_for_default_without_instructions ... ok

test result: ok. 1 passed

The characterization confirms current core behavior: Plan -> Default plus missing Default developer_instructions emits no <collaboration_mode> reset/update.

Expected behavior

When the collaboration mode changes from Plan to Default, the model should receive an authoritative Default-mode reset instruction, even if the next CollaborationMode object has developer_instructions = None.

Otherwise, a turn can be logically Default while the prompt history still contains effective Plan Mode constraints.

Possible fix directions

Some possible approaches:

  • Normalize Default collaboration mode earlier/centrally so built-in Default developer instructions are always present before core context diffing.
  • Or make build_collaboration_mode_update_item emit an explicit Default reset message when mode changes to Default and next instructions are missing.
  • Avoid duplicate emission when the normal Default instructions are already present.

Related issues

  • #18954: Intermittent mismatch between displayed collaboration mode and actual model mode
  • #10185: Mode switch Plan -> Code still behaves like Plan
  • #21512: /goal command will edit files directly with plan mode on
  • #20656: Plan mode makes active /goal look stuck because continuation is suppressed silently

cc @etraut-openai because this may be a narrower root-cause variant of the /goal + Plan Mode behavior discussed in #21512 / #20656.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗