Skip to content

[Bug]: Codex PreCompact hook stop reason is hidden behind "Stopped by the provider" #27219

Closed

Description

@michal-jarczewski-deel

Before submitting

  • I searched existing issues and did not find a duplicate for the hidden PreCompact hook stop reason.
  • I included enough detail to investigate the problem.

Area

apps/server

What happened

In T3 Code desktop 0.1.5, a Codex project PreCompact hook intentionally stopped a turn and supplied an actionable stop reason. The provider protocol log contains that reason in hook/completed, but the thread timeline shows only Run interrupted · Stopped by the provider. The user cannot discover from that interruption item which hook stopped the turn or what recovery action it requested.

The local guard's policy also creates a recovery trap: it requires a current checkpoint before compaction, so a turn needing compaction stops before the assistant can save that checkpoint. That policy is custom local code. This report concerns T3 hiding the reason, not a request to bypass the hook or a claim that T3 caused the missing checkpoint.

Steps to reproduce

Observed scenario, not a fresh synthetic host reproduction:

  1. Configure a trusted synchronous Codex PreCompact command hook. A proposed reduction of the observed custom guard prints {"continue":false,"stopReason":"Save a current task checkpoint before compaction."}; this reduced hook has not been tested in a fresh T3 thread.
  2. Continue a sufficiently long thread until Codex triggers compaction on the next turn.
  3. Send a normal user message. The hook stops the turn.
  4. Compare the provider protocol log's hook/completed event with the interruption item in the thread.

The custom hook was separately replayed against its real ledger and returned the expected denial. No fresh disposable T3 thread or forced compaction was used during diagnosis.

Expected behavior

Show the hook identity/event and supplied stop reason in the thread when a hook stops a turn. Preserve the intentional stop. A user should be able to distinguish a local policy stop from a provider outage and know the required recovery action.

Actual behavior

The provider log has an actionable kind: stop entry. Codex then emits turn/completed with status: interrupted and error: null. The visible interruption item contains only Stopped by the provider.

T3 would need to associate the earlier hook/completed event with the stopped turn to expose the reason. Codex omitting that reason from its terminal event may also be part of the upstream fix; ownership across the integration is for maintainers to determine.

Inspection of the installed app bundle confirms the interruption-result builder falls back to input.reason ?? "Stopped by the provider".

Impact

Major degradation in the affected existing thread. This report traces one turn end to end; local hook audit records also show earlier CHECKPOINT denials. The UI did not expose the recovery instruction. A separate browser-access blocker remained in the task, so this report does not claim the hook was the sole obstacle to completing it or establish prevalence across installations.

Version or commit

T3 Code desktop 0.1.5 (installed app version and last-started version both checked). The local codex --version reports codex-cli 0.166.0; exact running provider-binary identity has not been independently established. No T3 source patches were made during diagnosis.

Environment

macOS 26.2, T3 Code desktop, Codex provider, an existing long thread, trusted project command hooks.

Logs or stack traces

Minimized protocol fields from one observed turn on 2026-10-29 (UTC); IDs, project paths and task contents omitted:

{"time":"22:56:38.818Z","method":"hook/completed","run":{"eventName":"preCompact","source":"project","status":"stopped","entries":[{"kind":"stop","text":"Agent harness [CHECKPOINT]: Save a current harness checkpoint with decisions, verified state and next action before compaction."}]}}
{"time":"22:56:39.421Z","method":"turn/completed","turn":{"status":"interrupted","error":null,"durationMs":1017}}
{"time":"22:56:39.423Z","type":"run_interrupt_result","status":"interrupted","text":"Stopped by the provider"}

Workaround

Save a truthful current checkpoint for the affected local task outside the stopped turn, then retry the original thread. Do not disable hooks, mark acceptance checks passed, or mark the task complete. The recovery must be verified against the actual hook and ledger. This handles the custom checkpoint policy; unrelated task blockers still need resolution.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions