Repository navigation
Goal context is discarded during compaction, breaking objective continuation #32922
Description
Codex version
Current main at 7f3eb8a2233aceba3e7962123da84379ee305bb2 (verified 2026-07-14).
What happens
When a task has an active goal and history compaction runs, the goal continuation context can disappear from the compacted history. Subsequent turns may lose the objective even when the user gives a directional continuation such as "continue" or "go".
This is a precise compaction bug. It may contribute to some apparent stalls or non-progressing continuations, but this report does not claim that it explains every indefinite Thinking state.
Root cause
Goal continuation is injected as a hidden user-context fragment:
<codex_internal_context source="goal">
...
</codex_internal_context>That content intentionally does not parse as a visible TurnItem. Both compaction paths currently use visible-turn parsing as their retention boundary:
- local compaction:
collect_user_messages - remote compaction:
should_keep_compacted_history_item
As a result, goal-owned context is dropped together with unrelated hidden context.
Expected behavior
A well-formed goal fragment should survive local and remote compaction. Other internal fragments should remain filtered. Resumed older threads using the legacy <goal_context> wrapper should remain compatible.
Reproduction proof
Focused regression tests were added for:
- current
source="goal"context through local compaction; - legacy
<goal_context>through local compaction; - current goal context through remote compaction;
- negative control:
source="extension"remains filtered.
Before the retention rule:
just test -p codex-core goal_context: 3 failed, 1 passed
After the narrow retention rule:
just test -p codex-core goal_context: 4 passedjust test -p codex-core compact::tests contextual_user_message::tests: 31 passedjust fix -p codex-core: passedjust fmt: passed
ProofTether patch
- Commit: prooftether@1dc5156
- Upstream comparison: main...prooftether:codex:codex/preserve-goal-context-compaction
The upstream compare page reports the branches as mergeable, but currently also reports that opening PRs is limited to repository collaborators. The patch is therefore attached as reproducible evidence here rather than presented as an unverified hypothesis.
Related context: #27894, #29811, #31099. This also revisits the intent of #22174 against the current internal-context architecture.
Activity
github-actions commentedon Jul 14, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Kiborgik commentedon Sep 5, 2026
Additional observed case on Windows, 2026-09-05: after a paused goal was resumed, mid-turn compaction left an earlier pause request as the last retained ordinary user message. The agent treated it as current, stopped the resumed work, and eventually marked the unfinished goal blocked.
Environment and evidence boundary
cli_version: 0.153.0,originator: codex-tui,source: cli. That session was created on September 3; the exact executable/app build at the September 5 incident was not separately verified.gpt-6-astra, reasoning effortxhigh.Observed timeline (UTC)
09:08:46: ordinary user message asks to pause and continue later.18:28:14: a later<codex_internal_context source="goal">continuation instructs work toward the active goal. The agent resumes and performs useful work.19:04:25: acompactedevent is recorded. Itsreplacement_historycontains 94 items. The old pause is the last retained ordinary user message; there are zero explicit goal-continuation user messages in that retained list.get_goalcall returnsstatus: active, but at19:04:52the agent announces another pause. It also writes a new pause checkpoint into project documentation.update_goalwithstatus: blockeditself.Important distinction
The missing explicit goal fragment matches the retention problem described here. This does not prove that the objective was absent from the compacted summary: the supplied carryover summary identified the goal as active/resumed. The agent also had fresh active-state evidence and failed to reconcile it with the older pause. The later blocked transition was an agent action, not proof that the goal scheduler independently paused or blocked the goal.
The additional failure mode is that retaining an obsolete pause as the last ordinary user message can lead to stale instructions being re-applied, then persisted into project documentation and amplified across subsequent continuations.
A useful regression scenario would be: pause -> resume persisted goal -> useful work -> mid-turn compaction. Verify that the current goal/continuation state remains explicit after compaction and that an older pause is not presented or interpreted as a new stopping instruction. The old pause must remain effective if no later resumption occurred.
Daniel-ChenJH commentedon Sep 7, 2026
Preserving Goal context without changing visible user-message parsing looks like a straightforward approach.
I ran into this during a long-running Goal task and put together a fix against the more recent upstream commit
694b6319. I found this issue and your patch after implementing mine; both take the same core approach.Implementation and coverage
My version preserves internal annotations and handles retention-budget boundaries: Goal fragments are retained whole or omitted, so text truncation cannot break their internal markers.
The regression tests cover:
Most of the diff is tests. The production changes are +46/-9 across four files.
Patch
Validation
Maintainer feedback
Could someone on the Codex team with repository access take a look and assess whether this implementation would be useful for an upstream fix?
If any of the code is adopted, I’d appreciate preserving the corresponding author attribution. I understand the current contribution policy; if only the analysis and reproduction details can be considered, please let me know.
Daniel-ChenJH commentedon Sep 7, 2026
Environment
I observed this while running a long-running Goal task in the desktop app. Across continuations, the agent repeatedly returned to earlier requests and produced similar progress summaries.
The patch and regression tests above are based on upstream commit
694b6319.Daniel-ChenJH commentedon Sep 9, 2026
@etraut-openai Could you please help get this looked at? Goal mode keeps revisiting earlier requests during long tasks, and compaction is dropping the Goal instructions.
I’ve added a patch and regression tests above. Since you’ve worked on Goal-related session handling, I figured I’d flag it to you:
#32922 (comment).
Daniel-ChenJH commentedon Sep 14, 2026
@jif-oai Could you take a look at this? I noticed you introduced the internal Goal context in #24918 and recently worked on preserving prompts across compaction failures in #44487.
This report concerns Goal context being filtered out during compaction. I’ve added a patch and regression tests above, based on the September 7 upstream code:
#32922 (comment)
Would be good to get your take on how this should be handled upstream.
Krigsexe commentedon Sep 30, 2026
I have a bounded user-side workaround for this symptom on Codex Desktop with codex-cli 0.155.0-alpha.16. It does not fix the core Goal-context retention bug.
SessionStartcommand hook forstartup|resume|clear|compact. It has a 2-second timeout, boundedadditionalContext, no model or network dependency, and no Stop/deny/automatic-continuation behavior. It only injects the latest checkpoint or explicitly reports stale/missing state.Evidence boundary: 29 targeted tests and five real-binary transport scenarios passed (the latter used synthetic model responses). After a controlled app reload, six already-open tasks received the expected native developer-context checkpoint. In one observed long-running Goal continuation after compaction, the agent resumed the recorded open step rather than replaying an older message. This is a local mitigation, not proof of universal model compliance, all compaction paths, or reduced token usage. The upstream retention fix and its regression tests are still needed.
I3eka commentedon Oct 7, 2026
What version of Codex CLI is running?
Recorded session
cli_version: 0.160.1; installed CLI and running app-server also report0.160.1when checked on October 7, 2026. GitHub's latest stable release at this check is rust-v0.160.1, published October 5. The session was created October 6; the affected turn ran October 7.What subscription do you have?
ChatGPT-authenticated account, plan type
prolite. The affected turn recordsrate_limits.plan_type: prolite. An independent reporting-time check through the running Codex app-server (account/read,refreshToken: false, October 7, 2026) returnedaccount.type: chatgptandaccount.planType: prolite. The plan identifier is reported exactly as returned by Codex; no billing price or commercial plan variant is inferred.Which model were you using?
gpt-6-astra, reasoning effortxhigh, provideropenai, collaboration modedefault. The model and effort are unchanged across the affected compaction.What platform is your computer?
Execution host checked when preparing this report: Ubuntu 22.04.5 LTS.
uname -mprsreturned:These are reporting-time workspace-host details. The operating system of any separate frontend/client was not captured in the incident record.
What terminal emulator and version are you using (if applicable)?
The thread originated from
codex-tuiversion0.160.1, with recordedsource: vscode. The current read-onlythread/readresponse confirms these values. A still-running Codex TUI process in the affected workspace started within one second of thread creation; it runs in aherdr-managed PTY and inheritedTERM_PROGRAM=vscode,TERM_PROGRAM_VERSION=1.134.0. This is supporting process evidence, not proof of which frontend was used to set the later goal.Reporting-time
codex doctorinstead seesVS Code 1.138.0in its environment. These terminal environment values do not establish a Codex extension/App build. The exact interface and build used when goal B was set were not captured, so this is not presented as a controlled CLI-only reproduction or a confirmed Windows App occurrence.Codex doctor report
Collected using
codex doctor --jsonin the affected workspace on 2026-10-07 10:15:30 UTC. Overall status:ok. This is a current diagnostic snapshot, not a snapshot taken during the incident, and does not demonstrate that the compaction bug is fixed. Local paths, project identifiers, endpoint URLs, and the active-overrides detail were redacted; all checks and their statuses are preserved.Full diagnostic JSON with private values redacted
{ "schemaVersion": 1, "generatedAt": "1791368130s since unix epoch", "overallStatus": "ok", "codexVersion": "0.160.1", "checks": { "app_server.status": { "id": "app_server.status", "category": "app-server", "status": "ok", "summary": "background server is running", "details": { "app-server version": "0.160.1", "control socket": "<HOME>/.codex/app-server-control/app-server-control.sock", "daemon state dir": "<HOME>/.codex/app-server-daemon", "dedicated pid file": "<HOME>/.codex/app-server-daemon/daemon.pid (file)", "dedicated update-loop pid file": "<HOME>/.codex/app-server-daemon/daemon-updater.pid (file)", "mode": "ephemeral", "pid file": "<HOME>/.codex/app-server-daemon/app-server.pid (missing)", "settings": "<HOME>/.codex/app-server-daemon/settings.json (missing)", "status": "running", "update-loop pid file": "<HOME>/.codex/app-server-daemon/app-server-updater.pid (missing)" }, "remediation": null, "durationMs": 85 }, "auth.credentials": { "id": "auth.credentials", "category": "auth", "status": "ok", "summary": "auth is configured", "details": { "auth file": "<HOME>/.codex/auth.json", "auth storage mode": "File", "stored API key": "false", "stored ChatGPT tokens": "true", "stored agent identity": "false", "stored auth mode": "chatgpt" }, "remediation": null, "durationMs": 0 }, "config.load": { "id": "config.load", "category": "config", "status": "ok", "summary": "config loaded", "details": { "CODEX_HOME": "<HOME>/.codex", "active thread overrides": "[REDACTED]", "config.toml": "<HOME>/.codex/config.toml", "config.toml parse": "ok", "configuration load ms": "76", "configuration scope": "invocation config, including cloud-managed policy", "cwd": "<WORKSPACE>", "enabled feature flags": "daemon_auto_start, shell_tool, view_image, sleep_tool, unified_exec, unified_exec_tty, unified_exec_zsh_fork, shell_snapshot, content_item_kinds, code_mode_host, terminal_resize_reflow, sqlite, memories, write_stdin_approval, hooks, enable_request_compression, unbounded_connection_retries, worktrees, system_proxy_fallback, multi_agent, apps, tool_search_always_defer_mcp_tools, tool_suggest, plugins, in_app_browser, in_app_chat, in_app_dictation, in_app_local_automation, in_app_updates, browser_use, browser_use_full_cdp_access, browser_use_external, computer_use, remote_plugin, plugin_sharing, image_generation, resize_all_images, item_ids, skill_mcp_dependency_install, skill_search, mentions_v2, steer, guardian_approval, guardian_reuse_parent_compaction, goals, collaboration_modes, tool_call_mcp_elicitation, auth_elicitation, fast_mode, realtime_conversation, tui_app_server, compaction_image_budget, workspace_dependencies", "feature flag overrides": "memories=true", "feature flags enabled": "53", "log dir": "<HOME>/.codex/log", "mcp servers": "4", "model": "gpt-6-astra", "model provider": "openai", "sqlite home": "<HOME>/.codex" }, "remediation": null, "durationMs": 0 }, "git.environment": { "id": "git.environment", "category": "git", "status": "ok", "summary": "git executable found; execution not verified", "details": { "PATH git #1": "/usr/bin/git", "PATH git #2": "/bin/git", "PATH git entries": "2", "git execution": "not inspected (PATH helpers are not executed)", "repo detected": "false", "selected git": "/usr/bin/git" }, "remediation": null, "durationMs": 0 }, "installation": { "id": "installation", "category": "install", "status": "ok", "summary": "installation looks consistent", "details": { "PATH codex #1": "<HOME>/.local/bin/codex", "current executable": "<HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/bin/codex", "install context": "standalone (unix, package <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl, bin <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/bin, resources <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/codex-resources, path <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/codex-path)", "managed by Vite+": "false", "managed by bun": "false", "managed by npm": "false", "managed by pnpm": "false", "managed package root": "not set" }, "remediation": null, "durationMs": 2 }, "mcp.config": { "id": "mcp.config", "category": "mcp", "status": "ok", "summary": "MCP configuration is locally consistent", "details": { "configured servers": "4", "disabled servers": "0", "stdio servers": "3", "streamable_http servers": "1" }, "remediation": null, "durationMs": 764 }, "network.env": { "id": "network.env", "category": "network", "status": "ok", "summary": "network-related environment looks readable", "details": { "managed proxy": "not configured", "proxy env vars": "none", "respect system proxy": "disabled" }, "remediation": null, "durationMs": 0 }, "network.provider_reachability": { "id": "network.provider_reachability", "category": "reachability", "status": "ok", "summary": "active provider endpoints are reachable over HTTP", "details": { "ChatGPT inference URL": "[REDACTED]", "reachability mode": "ChatGPT auth" }, "remediation": null, "durationMs": 448 }, "network.websocket_reachability": { "id": "network.websocket_reachability", "category": "websocket", "status": "ok", "summary": "Responses WebSocket handshake succeeded", "details": { "DNS": "2 IPv4, 2 IPv6, first IPv4", "auth mode": "chatgpt", "connect timeout": "15000 ms", "endpoint": "[REDACTED]", "handshake result": "HTTP 101 Switching Protocols", "model provider": "openai", "provider name": "OpenAI", "proxy env vars": "none", "reasoning header": "false", "server model present": "false", "supports websockets": "true", "wire API": "responses" }, "remediation": null, "durationMs": 1145 }, "runtime.provenance": { "id": "runtime.provenance", "category": "runtime", "status": "ok", "summary": "running standalone on linux-x86_64", "details": { "commit": "unknown", "current executable": "<HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/bin/codex", "install method": "standalone (unix, package <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl, bin <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/bin, resources <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/codex-resources, path <HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/codex-path)", "platform": "linux-x86_64", "version": "0.160.1" }, "remediation": null, "durationMs": 0 }, "runtime.search": { "id": "runtime.search", "category": "search", "status": "ok", "summary": "search command found (bundled); execution not verified", "details": { "search command": "<HOME>/.codex/packages/standalone/releases/0.160.1-x86_64-unknown-linux-musl/codex-path/rg", "search command readiness": "file exists", "search provider": "bundled" }, "remediation": null, "durationMs": 0 }, "sandbox.filesystem_paths": { "id": "sandbox.filesystem_paths", "category": "sandbox", "status": "ok", "summary": "no explicit filesystem paths to probe", "details": {}, "remediation": null, "durationMs": 0 }, "sandbox.helpers": { "id": "sandbox.helpers", "category": "sandbox", "status": "ok", "summary": "sandbox configuration is readable", "details": { "approval policy": "OnRequest", "codex-linux-sandbox helper": "<HOME>/.codex/tmp/arg0/codex-arg0MPOrbV/codex-linux-sandbox", "denied-read glob rules": "0", "denied-read rules": "0", "execve wrapper helper": "<HOME>/.codex/tmp/arg0/codex-arg0MPOrbV/codex-execve-wrapper", "filesystem sandbox": "restricted", "glob scan max depth": "unbounded", "managed filesystem source": "none", "network sandbox": "restricted" }, "remediation": null, "durationMs": 0 }, "security.endpoint": { "id": "security.endpoint", "category": "security", "status": "ok", "summary": "endpoint protection is not inspected on this platform", "details": { "endpoint products": "not inspected on this platform" }, "remediation": null, "durationMs": 0 }, "state.paths": { "id": "state.paths", "category": "state", "status": "ok", "summary": "state paths and databases are inspectable", "details": { "CODEX_HOME": "<HOME>/.codex (dir)", "active rollout files": "316 files, 2063313403 total bytes, 6529472 average bytes", "archived rollout files": "0 files, 0 total bytes, 0 average bytes", "goals DB": "<HOME>/.codex/goals_1.sqlite (file)", "goals DB integrity": "ok", "log DB": "<HOME>/.codex/logs_2.sqlite (file)", "log DB integrity": "ok", "log dir": "<HOME>/.codex/log (missing)", "memories DB": "<HOME>/.codex/memories_1.sqlite (file)", "memories DB integrity": "ok", "memories v2 DB": "<HOME>/.codex/memories_v2_1.sqlite (missing)", "memories v2 DB integrity": "skipped (missing)", "queue DB": "<HOME>/.codex/queue_1.sqlite (file)", "queue DB integrity": "ok", "sqlite home": "<HOME>/.codex (dir)", "standalone release cache": "3 entries in <HOME>/.codex/packages/standalone/releases", "state DB": "<HOME>/.codex/state_5.sqlite (file)", "state DB integrity": "ok", "thread history DB": "<HOME>/.codex/thread_history_1.sqlite (file)", "thread history DB integrity": "ok" }, "remediation": null, "durationMs": 29109 }, "state.rollout_db_parity": { "id": "state.rollout_db_parity", "category": "threads", "status": "ok", "summary": "rollout files and state DB thread inventory agree", "details": { "default model provider": "openai", "rollout DB active files": "316", "rollout DB active rows": "316", "rollout DB archive mismatches": "0", "rollout DB archived files": "0", "rollout DB archived rows": "0", "rollout DB duplicate DB paths": "0", "rollout DB duplicate rollout thread ids": "0", "rollout DB malformed file names": "0", "rollout DB missing active rows": "0", "rollout DB missing archived rows": "0", "rollout DB model providers": "openai=315, openrouter=1", "rollout DB rows": "316", "rollout DB scan cap reached": "false", "rollout DB scan errors": "0", "rollout DB sources": "cli=201, vscode=80, subagent:thread_spawn=23, subagent:review=12", "rollout DB stale rows": "0" }, "remediation": null, "durationMs": 203 }, "system.disk": { "id": "system.disk", "category": "disk", "status": "ok", "summary": "sufficient free disk space (56.1 GiB)", "details": { "CODEX_HOME available": "56.1 GiB", "failure threshold": "1.0 GiB", "warning threshold": "5.0 GiB", "worktree available": "56.1 GiB" }, "remediation": null, "durationMs": 0 }, "system.environment": { "id": "system.environment", "category": "system", "status": "ok", "summary": "OS language C", "details": { "EDITOR": "not set", "GH_PAGER": "set", "GIT_PAGER": "set", "LANG": "C.UTF-8", "LC_ALL": "C.UTF-8", "LC_CTYPE": "C.UTF-8", "PAGER": "set", "VISUAL": "not set", "os": "Ubuntu 22.4.0 (jammy) [64-bit]", "os language": "C", "os type": "Ubuntu", "os version": "22.4.0" }, "remediation": null, "durationMs": 43 }, "terminal.env": { "id": "terminal.env", "category": "terminal", "status": "ok", "summary": "terminal metadata was detected", "details": { "COLORTERM": "present", "NO_COLOR": "1", "SSH_CLIENT": "present", "SSH_CONNECTION": "present", "TERM_PROGRAM": "vscode", "VSCODE_IPC_HOOK_CLI": "present", "color output": "disabled (NO_COLOR)", "effective locale": "C.UTF-8", "stderr is terminal": "false", "stdin is terminal": "false", "stdout is terminal": "false", "terminal": "VS Code", "terminal size": "80x24", "terminal version": "1.138.0" }, "remediation": null, "durationMs": 11 }, "terminal.title": { "id": "terminal.title", "category": "title", "status": "ok", "summary": "terminal title default", "details": { "terminal title activity": "true", "terminal title items": "activity, project-name", "terminal title project source": "project config", "terminal title project value": "<WORKSPACE_NAME>", "terminal title source": "default" }, "remediation": null, "durationMs": 0 }, "updates.status": { "id": "updates.status", "category": "updates", "status": "ok", "summary": "update configuration is locally consistent", "details": { "cached latest version": "0.160.1", "check for update on startup": "true", "last checked at": "2026-10-07T09:27:59.066498501Z", "latest version": "0.160.1", "latest version status": "current version is not older", "update action": "standalone installer", "version cache": "<HOME>/.codex/version.json" }, "remediation": null, "durationMs": 750 } } }What issue are you seeing?
Additional occurrence on October 7, 2026; full event timeline. The explicit goal-continuation message disappeared from the recorded replacement history, and the last retained user message was an already answered question A. After compaction the agent started answering A again, although a new goal B was active.
At
09:23:13 UTC,get_goalsuccessfully returned the correct active B objective. Some B work continued andupdate_goalmarked B complete at09:27:42. The09:28:08final answer still led with A and then included B. This supports investigating retention and task precedence together; it is not evidence that the persisted goal was deleted or that the patches above have been evaluated.What steps can reproduce the bug?
Observed workflow; no independent deterministic minimal reproducer has been established:
get_goal.No new ordinary user message arrived between setting B and its final answer. Correlation identifiers and token/context counts are included below.
What is the expected behavior?
After compaction, the active goal should remain the current task. A completed earlier question should remain historical. If goal state needs refreshing, retrieve and reconcile it before choosing the next action or framing a response. Retrieving the correct active goal should not leave an unrelated completed question as the lead task in the final answer.
Additional information
Recorded context window:
258400tokens; no token budget was recorded for the goal. Recorded approval policy:on-request; sandbox:workspace-write,network_access: false. These historical values are distinguished from the current doctor snapshot.This was the ninth recorded compaction in the thread; this report analyzes one specific transition. The resumed turn ID, model, and reasoning effort match the pre-compaction goal turn. The identifiers above are included for correlation; private account and attachment identifiers remain omitted.
<codex_internal_context source="goal">message remained; the objective's opening sentence and attachment ID were absent from its readable messages.Related reports: #31659, #32922, and #46953. Matching symptoms do not by themselves establish an identical code-level cause. Raw private transcripts, internal addresses, account names, phone numbers, credentials, attachment IDs, and absolute local paths are omitted.