codex - 💡(How to fix) Fix Proposal: add task and plan lifecycle hooks with external harness-driven plan updates

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

I would like to propose adding task and plan lifecycle hooks to Codex, together with a small external plan update API for harness-driven workflows.

I already have a working prototype in my fork, but I read docs/contributing.md and saw that external code contributions are by invitation only. So I am opening this issue first to check whether this direction fits the project before asking for PR review.

Fork PR:

https://github.com/ashione/codex/pull/1

Upstream compare:

https://github.com/openai/codex/compare/main...ashione:feat/task-plan-lifecycle-hooks

Root Cause

I would like to propose adding task and plan lifecycle hooks to Codex, together with a small external plan update API for harness-driven workflows.

I already have a working prototype in my fork, but I read docs/contributing.md and saw that external code contributions are by invitation only. So I am opening this issue first to check whether this direction fits the project before asking for PR review.

Fork PR:

https://github.com/ashione/codex/pull/1

Upstream compare:

https://github.com/openai/codex/compare/main...ashione:feat/task-plan-lifecycle-hooks

Fix Action

Fix / Workaround

The API lets an external client patch the active turn checklist in a restricted way. It requires the active turn id to match expectedTurnId, and supports two operations:

  • lifecycle hooks are command hooks only

  • hook failures are reported but do not block task completion or plan updates

  • external plan updates only affect the current active turn

  • external updates are patch-based, not full snapshot replacement

  • Plan Mode proposals remain text proposals and do not become checklist state

  • event naming

  • payload shape

  • matcher semantics

  • whether turn/plan_update should stay app-server v2 only

  • whether the external patch constraints are strict enough

  • whether non-blocking lifecycle hooks are the right v1 behavior

Code Example

turn/plan_update

---

{ type: "append", step: string, status?: "pending" | "in_progress" | "completed" }
{ type: "update", index: number, step?: string, status?: "pending" | "in_progress" | "completed" }
RAW_BUFFERClick to expand / collapse

Summary

I would like to propose adding task and plan lifecycle hooks to Codex, together with a small external plan update API for harness-driven workflows.

I already have a working prototype in my fork, but I read docs/contributing.md and saw that external code contributions are by invitation only. So I am opening this issue first to check whether this direction fits the project before asking for PR review.

Fork PR:

https://github.com/ashione/codex/pull/1

Upstream compare:

https://github.com/openai/codex/compare/main...ashione:feat/task-plan-lifecycle-hooks

Motivation

Codex has hooks for tools and session events, but there is not currently a hook surface for the higher-level lifecycle that external harnesses usually care about:

  • a task/turn has started
  • a task/turn has completed
  • a checklist plan was created
  • a checklist plan changed
  • a checklist plan reached completion

For human users, the checklist is visible progress. For an external harness, it can also be a machine-readable progress contract. Without lifecycle hooks or a bounded plan update API, a harness has to keep a separate out-of-band plan, inject synthetic text, or ask the model to rewrite plan state even when the change came from deterministic external state.

The use case I am trying to support is an orchestrator around Codex that can:

  • observe when a real task starts and finishes
  • capture task completion metadata
  • observe checklist creation/update/completion
  • append or update active checklist items from outside the model loop
  • avoid rewriting completed checklist history

Proposed Events

The prototype adds these command-hook events:

  • TaskCreated
  • TaskCompleted
  • PlanCreated
  • PlanUpdated
  • PlanCompleted

Task hook matchers use task_kind:

  • regular
  • review
  • compact

Plan hook matchers use plan_source:

  • update_plan
  • external
  • proposed_plan

TaskCompleted includes metadata such as the last agent message, completion timestamp, duration, and time to first token.

Plan hook payloads include the current plan, previous plan, explanation, and status counts. For Plan Mode proposed plans, the proposal text is exposed as plan_text, and it is intentionally not written into the checklist snapshot.

External Harness-Driven Plan Updates

The prototype adds an app-server JSON-RPC method:

turn/plan_update

The API lets an external client patch the active turn checklist in a restricted way. It requires the active turn id to match expectedTurnId, and supports two operations:

{ type: "append", step: string, status?: "pending" | "in_progress" | "completed" }
{ type: "update", index: number, step?: string, status?: "pending" | "in_progress" | "completed" }

The important constraint is that completed checklist items cannot be modified. My intent is to treat completed steps as historical facts, while still letting an external harness add new work or adjust open items.

A successful external update reuses the normal plan update notification path and emits plan lifecycle hooks with plan_source = "external".

Behavior Boundaries

The prototype keeps this intentionally narrow:

  • lifecycle hooks are command hooks only
  • hook failures are reported but do not block task completion or plan updates
  • external plan updates only affect the current active turn
  • external updates are patch-based, not full snapshot replacement
  • Plan Mode proposals remain text proposals and do not become checklist state

If blocking policy is needed later, I think it should probably be a separate pre-update hook such as PrePlanUpdate, rather than overloading these lifecycle notifications.

Prototype Status

The fork branch wires this through hook config, hook discovery/listing, app-server schema generation, task/plan lifecycle emission, turn-scoped plan state, and TUI hook labels.

I also did local validation, including hook tests, core plan-update tests, schema fixture checks, a release codex-cli build, and CLI smoke tests confirming that the new command hooks fire with the expected payloads.

I did hit some local environment limitations: just was not installed on my machine, and a full core lib run hit an unrelated existing stack overflow test. The release CLI build succeeded and was used for the hook verification.

Questions

Would the Codex team be open to this lifecycle hook surface and external harness-driven plan update API?

If the direction seems reasonable, I would appreciate guidance on:

  • event naming
  • payload shape
  • matcher semantics
  • whether turn/plan_update should stay app-server v2 only
  • whether the external patch constraints are strict enough
  • whether non-blocking lifecycle hooks are the right v1 behavior

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Proposal: add task and plan lifecycle hooks with external harness-driven plan updates