prefer harness-native goal execution #953

Closed
opened 2026-07-10 05:58:46 +00:00 by coilysiren · 2 comments
Owner

The problem

//

Proposed change

Problem

Ward’s managed-director flow provides long-horizon execution across multiple agent harnesses. It should remain the generic implementation for harnesses that do not expose equivalent native lifecycle primitives.

Codex now exposes native Goal Mode through codex app-server, including persisted objectives, automatic continuation, status transitions, token accounting, and lifecycle notifications. Codex-backed director runs should use this native capability instead of recreating the same loop through prompts.

Decision

Add a Codex-specific native-goal execution path and enable it by default for Codex-backed director runs.

The existing Ward-managed director remains available:

  • as the implementation for Goose, Claude, and other harnesses
  • as a compatibility fallback for Codex versions without Goal Mode
  • as an explicit override for debugging or behavioral comparison

This changes the Codex backend, not the public director feature or its cross-harness contract.

Backend selection

Support three Codex director modes:

auto       default; use native Goal Mode when supported, otherwise managed
native     require native Goal Mode and fail if unavailable
managed    force Ward’s existing managed-director loop

The exact configuration surface can follow existing Ward conventions, but should be available through both configuration and a one-run CLI override.

Example conceptual interface:

ward director --harness codex --director-mode auto
ward director --harness codex --director-mode native
ward director --harness codex --director-mode managed

For non-Codex harnesses, the existing managed-director behavior remains unchanged.

Native Codex flow

When the resolved harness is Codex and the mode resolves to native:

  1. Start codex app-server over stdio.

  2. Complete the JSON-RPC initialization handshake.

  3. Create or resume a persisted Codex thread.

  4. Translate the Ward director objective into one bounded native goal containing:

    • objective
    • constraints
    • validation requirements
    • verifiable stopping condition
    • optional token budget
  5. Invoke thread/goal/set with status: "active".

  6. Allow Codex to own continuation across turns.

  7. Observe app-server turn, item, and goal notifications.

  8. Translate the terminal native goal state into Ward’s existing director result contract.

Ward must not send /goal ... as ordinary prompt text or inject synthetic continuation prompts while the native goal is active.

Fallback behavior

In auto mode:

  • Detect support before starting substantive work.
  • If app-server or native goals are unavailable, log that Ward is using the managed director and continue normally.
  • Do not silently fall back after a native goal has begun executing; that could duplicate work. A mid-run native failure should surface as interrupted or blocked and retain the thread/goal identifiers for recovery.

In native mode, missing support is a hard error with remediation instructions.

Status mapping

Preserve native Codex details in the run record while mapping them onto Ward’s existing result model.

At minimum, retain:

  • Codex thread ID
  • objective
  • native goal status
  • token budget and tokens used
  • elapsed time
  • terminal reason
  • last completed turn
  • whether execution used native or managed mode

Avoid creating a second Ward-owned continuation state machine around an active native goal.

Scope

  • Add a Codex app-server client sufficient for thread and goal lifecycle operations.
  • Add native-goal capability detection.
  • Add Codex director-mode selection with auto as the default.
  • Route eligible Codex director runs through native Goal Mode.
  • Adapt native events and terminal states to Ward’s existing director result/output surface.
  • Retain the generic managed-director implementation for other harnesses and forced Codex compatibility mode.
  • Document which director implementation was selected and why.

Out of scope

  • Replacing the managed-director implementation for other harnesses.
  • Defining a universal native-goal protocol across all harnesses.
  • Sending slash commands through codex exec.
  • PTY automation of the Codex TUI.
  • Reworking Ward’s public director UX beyond exposing backend selection and status.

Acceptance

  • Codex director runs default to native Goal Mode when the installed Codex supports it.
  • Native execution sends a real thread/goal/set request.
  • Codex continues across multiple turns without Ward injecting continuation prompts.
  • Native progress and terminal status appear through Ward’s existing director output.
  • auto falls back to the managed director when native support is unavailable.
  • native fails clearly when native support is unavailable.
  • managed forces the existing Codex behavior.
  • Goose and other harness director runs are behaviorally unchanged.
  • Ward records whether each run used the native or managed implementation.
  • A mid-run app-server failure does not start a second managed-director run.
  • Tests cover capability detection, mode selection, native execution, pre-run fallback, forced modes, event translation, and failure after goal activation.
  • An end-to-end test demonstrates a Codex-backed Ward director completing a multi-turn issue through native Goal Mode.

References

Alternatives considered

//

Before filing

  • I searched existing issues and this is not a duplicate.
  • This stays within ward's scope (the dev-verb gate / agent driver), not a personal-infra or downstream-repo verb.
### The problem // ### Proposed change ## Problem Ward’s managed-director flow provides long-horizon execution across multiple agent harnesses. It should remain the generic implementation for harnesses that do not expose equivalent native lifecycle primitives. Codex now exposes native Goal Mode through `codex app-server`, including persisted objectives, automatic continuation, status transitions, token accounting, and lifecycle notifications. Codex-backed director runs should use this native capability instead of recreating the same loop through prompts. ## Decision Add a Codex-specific native-goal execution path and enable it by default for Codex-backed director runs. The existing Ward-managed director remains available: * as the implementation for Goose, Claude, and other harnesses * as a compatibility fallback for Codex versions without Goal Mode * as an explicit override for debugging or behavioral comparison This changes the Codex backend, not the public director feature or its cross-harness contract. ## Backend selection Support three Codex director modes: ```text auto default; use native Goal Mode when supported, otherwise managed native require native Goal Mode and fail if unavailable managed force Ward’s existing managed-director loop ``` The exact configuration surface can follow existing Ward conventions, but should be available through both configuration and a one-run CLI override. Example conceptual interface: ```text ward director --harness codex --director-mode auto ward director --harness codex --director-mode native ward director --harness codex --director-mode managed ``` For non-Codex harnesses, the existing managed-director behavior remains unchanged. ## Native Codex flow When the resolved harness is Codex and the mode resolves to `native`: 1. Start `codex app-server` over stdio. 2. Complete the JSON-RPC initialization handshake. 3. Create or resume a persisted Codex thread. 4. Translate the Ward director objective into one bounded native goal containing: * objective * constraints * validation requirements * verifiable stopping condition * optional token budget 5. Invoke `thread/goal/set` with `status: "active"`. 6. Allow Codex to own continuation across turns. 7. Observe app-server turn, item, and goal notifications. 8. Translate the terminal native goal state into Ward’s existing director result contract. Ward must not send `/goal ...` as ordinary prompt text or inject synthetic continuation prompts while the native goal is active. ## Fallback behavior In `auto` mode: * Detect support before starting substantive work. * If app-server or native goals are unavailable, log that Ward is using the managed director and continue normally. * Do not silently fall back after a native goal has begun executing; that could duplicate work. A mid-run native failure should surface as interrupted or blocked and retain the thread/goal identifiers for recovery. In `native` mode, missing support is a hard error with remediation instructions. ## Status mapping Preserve native Codex details in the run record while mapping them onto Ward’s existing result model. At minimum, retain: * Codex thread ID * objective * native goal status * token budget and tokens used * elapsed time * terminal reason * last completed turn * whether execution used `native` or `managed` mode Avoid creating a second Ward-owned continuation state machine around an active native goal. ## Scope * Add a Codex app-server client sufficient for thread and goal lifecycle operations. * Add native-goal capability detection. * Add Codex director-mode selection with `auto` as the default. * Route eligible Codex director runs through native Goal Mode. * Adapt native events and terminal states to Ward’s existing director result/output surface. * Retain the generic managed-director implementation for other harnesses and forced Codex compatibility mode. * Document which director implementation was selected and why. ## Out of scope * Replacing the managed-director implementation for other harnesses. * Defining a universal native-goal protocol across all harnesses. * Sending slash commands through `codex exec`. * PTY automation of the Codex TUI. * Reworking Ward’s public director UX beyond exposing backend selection and status. ## Acceptance * Codex director runs default to native Goal Mode when the installed Codex supports it. * Native execution sends a real `thread/goal/set` request. * Codex continues across multiple turns without Ward injecting continuation prompts. * Native progress and terminal status appear through Ward’s existing director output. * `auto` falls back to the managed director when native support is unavailable. * `native` fails clearly when native support is unavailable. * `managed` forces the existing Codex behavior. * Goose and other harness director runs are behaviorally unchanged. * Ward records whether each run used the native or managed implementation. * A mid-run app-server failure does not start a second managed-director run. * Tests cover capability detection, mode selection, native execution, pre-run fallback, forced modes, event translation, and failure after goal activation. * An end-to-end test demonstrates a Codex-backed Ward director completing a multi-turn issue through native Goal Mode. ## References * [Codex app-server protocol](https://learn.chatgpt.com/docs/app-server) * [Codex Goal Mode](https://learn.chatgpt.com/use-cases/follow-goals) ### Alternatives considered // ### Before filing - [x] I searched existing issues and this is not a duplicate. - [x] This stays within ward's scope (the dev-verb gate / agent driver), not a personal-infra or downstream-repo verb.
coilysiren changed title from Use native Codex Goal Mode by default for Codex-backed director runs to prefer harness-native goal execution 2026-07-10 06:03:31 +00:00
Author
Owner

Scope update: prefer harness-native goals

This issue should cover harness-native goal execution, not only Codex.

The public ward director flow and Ward-managed implementation remain. Ward should select the best available execution engine for the configured harness:

Codex  → native Goal Mode through `codex app-server`
Claude → native `/goal` through headless Claude Code
Other  → existing Ward-managed director

Native execution should be default-on when supported. The generic Ward-managed director remains the compatibility implementation and the path for harnesses without native goals.

Claude implementation

Claude Code supports hard-dispatching /goal in non-interactive mode:

claude -p \
  --output-format stream-json \
  --verbose \
  --permission-mode auto \
  --max-turns "$MAX_TURNS" \
  --max-budget-usd "$MAX_BUDGET_USD" \
  "/goal $CONDITION"

This is a real built-in command, not ordinary model-visible prompt text. The invocation runs the goal loop to completion in one process: after each turn, Claude uses a separate evaluator model to decide whether the condition is satisfied and automatically begins another turn when it is not.

Ward should:

  • Require Claude Code v2.1.139 or later.
  • Capability-detect goal, including checking the Agent SDK system/init.slash_commands list where applicable.
  • Translate the director objective into a measurable completion condition with validation evidence and an explicit turn/time bound.
  • Stream and retain Claude’s JSON events, session ID, token/cost information, evaluator reasons, and terminal outcome.
  • Preserve the Claude session so an interrupted active goal can be resumed.
  • Detect unavailable goals caused by an untrusted workspace, disableAllHooks, or allowManagedHooksOnly.
  • Fall back to Ward-managed execution only before substantive native work begins.
  • Never start a managed-director run automatically after a native goal has already begun.

Selection behavior

Use the same conceptual modes for supported harnesses:

auto       default; prefer the harness-native goal, otherwise use managed
native     require native goal support and fail clearly when unavailable
managed    force Ward’s existing director implementation

Native capability detection and invocation remain adapter-specific. We do not need to pretend Codex and Claude expose the same protocol:

  • Codex uses persisted thread/goal/* app-server RPCs.
  • Claude dispatches a session-scoped /goal command through -p or the Agent SDK.
  • Ward normalizes only the result needed by its existing director contract.

Additional acceptance

  • Claude-backed director runs use native /goal by default when supported.
  • The command is dispatched through claude -p or the Agent SDK, not included inside a general-purpose prompt.
  • Claude continues for multiple turns without Ward injecting continuation prompts.
  • Turn limits and budget limits remain enforceable.
  • Claude evaluator reasons and terminal state are observable in Ward’s run record.
  • Unsupported Claude versions and hook-policy restrictions fall back in auto mode and fail in native mode.
  • Codex and Claude can each use their native mechanisms while other harnesses remain on the managed director.
  • Existing non-native harness behavior remains unchanged.

References:

## Scope update: prefer harness-native goals This issue should cover **harness-native goal execution**, not only Codex. The public `ward director` flow and Ward-managed implementation remain. Ward should select the best available execution engine for the configured harness: ```text Codex → native Goal Mode through `codex app-server` Claude → native `/goal` through headless Claude Code Other → existing Ward-managed director ``` Native execution should be default-on when supported. The generic Ward-managed director remains the compatibility implementation and the path for harnesses without native goals. ### Claude implementation Claude Code supports hard-dispatching `/goal` in non-interactive mode: ```bash claude -p \ --output-format stream-json \ --verbose \ --permission-mode auto \ --max-turns "$MAX_TURNS" \ --max-budget-usd "$MAX_BUDGET_USD" \ "/goal $CONDITION" ``` This is a real built-in command, not ordinary model-visible prompt text. The invocation runs the goal loop to completion in one process: after each turn, Claude uses a separate evaluator model to decide whether the condition is satisfied and automatically begins another turn when it is not. Ward should: * Require Claude Code v2.1.139 or later. * Capability-detect `goal`, including checking the Agent SDK `system/init.slash_commands` list where applicable. * Translate the director objective into a measurable completion condition with validation evidence and an explicit turn/time bound. * Stream and retain Claude’s JSON events, session ID, token/cost information, evaluator reasons, and terminal outcome. * Preserve the Claude session so an interrupted active goal can be resumed. * Detect unavailable goals caused by an untrusted workspace, `disableAllHooks`, or `allowManagedHooksOnly`. * Fall back to Ward-managed execution only before substantive native work begins. * Never start a managed-director run automatically after a native goal has already begun. ### Selection behavior Use the same conceptual modes for supported harnesses: ```text auto default; prefer the harness-native goal, otherwise use managed native require native goal support and fail clearly when unavailable managed force Ward’s existing director implementation ``` Native capability detection and invocation remain adapter-specific. We do not need to pretend Codex and Claude expose the same protocol: * Codex uses persisted `thread/goal/*` app-server RPCs. * Claude dispatches a session-scoped `/goal` command through `-p` or the Agent SDK. * Ward normalizes only the result needed by its existing director contract. ### Additional acceptance * Claude-backed director runs use native `/goal` by default when supported. * The command is dispatched through `claude -p` or the Agent SDK, not included inside a general-purpose prompt. * Claude continues for multiple turns without Ward injecting continuation prompts. * Turn limits and budget limits remain enforceable. * Claude evaluator reasons and terminal state are observable in Ward’s run record. * Unsupported Claude versions and hook-policy restrictions fall back in `auto` mode and fail in `native` mode. * Codex and Claude can each use their native mechanisms while other harnesses remain on the managed director. * Existing non-native harness behavior remains unchanged. References: * [Claude Code goals](https://code.claude.com/docs/en/goal) * [Claude Agent SDK slash commands](https://code.claude.com/docs/en/agent-sdk/slash-commands) * [Codex app-server protocol](https://learn.chatgpt.com/docs/app-server)
Member

Closing as superseded by #1620. Ward will retain governed queue, dispatch, status, and recovery primitives while harness-native goals own long-horizon orchestration. The generic managed-director fallback proposed here is no longer part of the product direction.

Closing as superseded by #1620. Ward will retain governed queue, dispatch, status, and recovery primitives while harness-native goals own long-horizon orchestration. The generic managed-director fallback proposed here is no longer part of the product direction.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/ward#953
No description provided.