Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Critical workflow bug] Auto-compaction silently abandons active delegated tasks; Responses repair destroys handover semantics

Closed
#6,764 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
18/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript

Research direction

Start with the repro fixture: it imports externalTaskInputContent from src/responses/task-input.ts and repairUnidentifiedToolOutputItems from src/adapters/openai-responses/tool-output-recovery.ts, and the two disagree on the same function_call_output seed. Then check src/adapters/openai-responses/passthrough.ts, where the repair runs after the routed-compaction request is built. Done means external task input survives repair with its provenance intact, and a regression fixture (completed A, authorized B, compaction, continuation) keeps B active and does not repeat A.

Written by the indexing model from the issue text.

Description

bug
Client or integration

Codex App; independently investigated with isolated HTTP protocol tests.

Area

Proxy and routing / Responses adapter / automatic compaction.

Summary

Critical autonomous-workflow failure: after automatic compaction, an agent can silently abandon its active, human-authorized delegated task, answer an already-completed initial request again, and end the turn with unfinished work outstanding. There is no transport failure or explicit failed-task signal: the requests succeed. The failure occurs in task ownership and continuation semantics.

The observed Codex App conversation first completed a small browser check, then accepted an explicitly authorized task handover from another chat and worked on it for roughly 32 minutes. Immediately after auto-compaction, it repeated the original browser check and ended its answer, leaving the active task and a pending review unfinished.

This breaks a central promise of long-running agent workflows: compaction must preserve what the agent is currently supposed to finish. A clean API completion can conceal abandonment of the real job. Please prioritize this as a serious workflow-integrity bug, rather than a cosmetic repeated answer.

Confirmed OpenCodex defect

Two code paths interpret the same valid Codex external-task input differently:

{
  "type": "function_call_output",
  "id": "fco_synthetic",
  "name": "send_message_to_thread",
  "namespace": "codex_app",
  "output": "<codex_delegation>Human-authorized task B</codex_delegation>"
}

There is deliberately no call_id: this is externally submitted task input, not the result of a call made by the destination agent.

  • externalTaskInputContent() recognizes it as external task input; the common parser converts it to a user-role message.
  • repairUnidentifiedToolOutputItems() instead converts it to a user message prefixed [tool output for unknown call], discarding the protocol fields that distinguish an authorized handover from an ordinary orphaned result.
  • The Responses passthrough runs that repair after constructing the routed-compaction request. Thus the summarizer sees the external task misclassified as unidentified tool output.

I reproduced this inconsistency by executing the installed 2.80.0 functions directly. The repair function still has this behavior on current main (250f17afd8ff44c93c620d87c1f346ef56f64fb4).

Relevant sources:

Related earlier contract fixes: #3732, #3735, #3807. This report concerns semantic degradation and silent abandonment, rather than their explicit missing-call_id rejection.

Reproduction

Run this TypeScript fixture against the repository, or adapt the import paths to the installed package:

import { externalTaskInputContent } from './src/responses/task-input';
import { repairUnidentifiedToolOutputItems } from './src/adapters/openai-responses/tool-output-recovery';

const seed = {
  type: 'function_call_output',
  id: 'fco_synthetic',
  name: 'send_message_to_thread',
  namespace: 'codex_app',
  output: '<codex_delegation>Human-authorized task B</codex_delegation>',
};

console.log(externalTaskInputContent(seed));
// Correctly recognized as external task input.

console.log(JSON.stringify(repairUnidentifiedToolOutputItems({ input: [seed] })));
// Incorrectly labelled "[tool output for unknown call]".
Behavioral reproduction and controls

The isolated fixture contains:

  1. User task A: inspect example.txt.
  2. Recorded successful tool result and assistant confirmation: A is completed.
  3. A valid external-task envelope: human-authorized task B, synthetic ticket 1731, with reviewer pass 2 pending.
  4. Assistant acknowledgement that B is active.
  5. A real remote-compaction request through /v1/responses using compaction_trigger.
  6. Continuation with the retained original user message and returned compaction item, mirroring the observed replacement-history shape.

The fixture explicitly tells the model what Codex's external-task protocol means. Both native GPT and routed Claude choose B with the full history, establishing a valid pre-compaction baseline. Tool calls only record the selected next action; no real files, tickets, browser actions, or reviews are changed by these tests.

Route / condition Observed continuation
Native OpenAI/GPT compaction, no proxy B continued in both tested runs
OpenAI/GPT through OpenCodex B continued
Claude through OpenCodex → Meridian Both tested runs abandoned B and answered completed A
Handover normalized to user input before Claude summarization, but only original A retained afterward Both tested runs selected A again, despite a correct summary identifying B as active
Direct user message naming B retained after compaction Claude continued B
Explicit new user instruction: A is done; do not repeat A; continue B Claude continued only B in both tested runs

These are small controlled tests, not statistical reliability estimates. Preliminary fixtures that lacked valid handover semantics were excluded from this comparison.

Switching the compaction model to GPT does not suffice

I tested a portable GPT-generated prose checkpoint followed by Claude continuation, using OpenCodex's COMPACT_PROMPT and an ocx1: envelope. This emulates the cross-provider portable-summary path; I did not change the live compactionRouting setting.

Two results:

  1. With the unchanged external-task item, GPT sees [tool output for unknown call] and questions whether B was authorized. Changing the summarizer cannot restore protocol information already removed upstream.
  2. With the handover normalized before GPT summarization, GPT correctly identifies B as active and A as completed. Claude nevertheless selects A again after replay. So there is also a continuation/task-selection issue beyond summary accuracy.
Limits of attribution

The inconsistent external-task handling above is a concrete OpenCodex defect. The additional failure after replay of a correct summary is reproduced in the Claude/Meridian route, but is not fully isolated between message framing, Meridian and Claude behavior.

In the original App failure, the complete summary was preserved word-for-word in the actual Claude input and correctly named the active task. Codex continued the same turn. This rules out simple summary truncation or a new user turn as the explanation for that incident. The retained old request and decoded summary arrived as one user message after Meridian translation.

Native OpenAI's successful controlled compaction is a useful control, not proof that native Codex can never have a similar failure.

Expected behavior / suggested investigation
  • Reuse external-task recognition in the Responses passthrough before generic orphan-output repair; preserve authorized-task provenance. Do not promote arbitrary tool output based only on delegation text or XML.
  • Preserve the active authorized task through both summarization and replay, including a clear distinction between completed requests and the current job.
  • Add a regression fixture with completed A → authorized external B → compaction → continuation. Assert that B remains active and A is not repeated. Cover both correct-summary replay and cross-provider compaction.
Version

2.80.0

Operating system

macOS 27.0.1, build 26A434

Provider and model

meridian/claude-opus-5-5 through OpenCodex → Meridian 1.79.0. Native/control model: gpt-6.1-sol.

Logs or error output
externalTaskInputContent(seed): external user task recognized
repairUnidentifiedToolOutputItems({input:[seed]}): [tool output for unknown call]
Before compaction: continue_review({ticket:1731})
After routed compaction: answers already-completed task A; B remains unfinished
Transport: successful completion, no explicit failure signal
Screenshots and supporting files

The deterministic TypeScript reproduction, source permalinks, behavioral controls and test matrix are included above. No private conversation logs are attached.

Additional environment details
  • OpenCodex: 2.80.0.
  • Codex App bundled CLI reported by the affected rollout: 0.160.1.
  • Meridian: 1.79.0.
  • OS: macOS 27.0.1, build 26A434.
  • Routed selector: meridian/claude-opus-5-5; Meridian telemetry reports opus[1m].
  • Native/control selector: gpt-6.1-sol.
  • Auto-compaction token limit in the observed App configuration: 350000.
  • No compaction-routing override configured during the original incident.
Redacted configuration shape
{
  "providers": {
    "meridian": {
      "adapter": "openai-responses",
      "baseUrl": "http://127.0.0.1:3456/v1"
    }
  }
}

Codex's OpenAI base URL points to the OpenCodex loopback listener. All reproduction content above is synthetic or anonymized; no account identifiers, credentials, customer data, private repository URLs, or private chat logs are included.

Checks
  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.
Dominant language
TypeScript
Stars
16.9k
Forks
1.3k
Avg merge
7h 34m
Merged PRs (30d)
667

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from lidge-jun/opencodex

All issues in lidge-jun/opencodex

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.