@open-agent-toolkit/cli 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/assets/agents/oat-phase-implementer.md +14 -3
  2. package/assets/agents/oat-reviewer.md +9 -2
  3. package/assets/docs/cli-utilities/configuration.md +33 -1
  4. package/assets/docs/contributing/hooks-and-safety.md +2 -0
  5. package/assets/docs/provider-sync/config.md +1 -0
  6. package/assets/docs/provider-sync/manifest-and-drift.md +2 -0
  7. package/assets/docs/reference/oat-directory-structure.md +2 -0
  8. package/assets/docs/workflows/projects/implementation-execution.md +60 -12
  9. package/assets/docs/workflows/projects/lifecycle.md +4 -0
  10. package/assets/public-package-versions.json +4 -4
  11. package/assets/skills/oat-project-implement/SKILL.md +173 -94
  12. package/assets/skills/oat-project-plan/SKILL.md +57 -1
  13. package/assets/skills/oat-project-plan-writing/SKILL.md +6 -2
  14. package/assets/skills/oat-project-quick-start/SKILL.md +57 -1
  15. package/assets/templates/plan.md +1 -1
  16. package/assets/templates/state.md +4 -0
  17. package/dist/commands/config/index.d.ts.map +1 -1
  18. package/dist/commands/config/index.js +36 -0
  19. package/dist/commands/project/dispatch-ceiling/index.d.ts +16 -0
  20. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -0
  21. package/dist/commands/project/dispatch-ceiling/index.js +288 -0
  22. package/dist/commands/project/index.d.ts.map +1 -1
  23. package/dist/commands/project/index.js +2 -0
  24. package/dist/config/oat-config.d.ts +7 -0
  25. package/dist/config/oat-config.d.ts.map +1 -1
  26. package/dist/config/oat-config.js +23 -0
  27. package/dist/config/resolve.d.ts.map +1 -1
  28. package/dist/config/resolve.js +4 -0
  29. package/dist/drift/strays.d.ts.map +1 -1
  30. package/dist/drift/strays.js +26 -0
  31. package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
  32. package/dist/providers/codex/codec/sync-extension.js +16 -8
  33. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-implement
3
- version: 2.0.17
3
+ version: 2.0.18
4
4
  description: Use when plan.md is ready for execution. Dispatches phase-level subagents with bounded fix loops; supports plan-declared parallel phase groups with worktree-isolated execution and ordered fan-in.
5
5
  argument-hint: '[--retry-limit <N>] [--dry-run]'
6
6
  disable-model-invocation: true
@@ -162,132 +162,204 @@ Forbidden: Selected: Tier 2 — Inline because the user did not separately menti
162
162
 
163
163
  **Legacy state migration:** If `state.md` contains `oat_execution_mode: subagent-driven`, silently ignore it. On the next bookkeeping write, remove that key. Do not redirect to `oat-project-subagent-implement` — that skill is deprecated.
164
164
 
165
- ### Runtime dispatch selection
165
+ ### Dispatch Ceiling Preflight
166
166
 
167
- Before each phase implementation dispatch, choose and log the phase's runtime dispatch controls. This is separate from the Tier 1/Tier 2 execution mode above: Tier 1/Tier 2 decides whether OAT uses subagents or inline fallback; runtime dispatch selection decides the model and effort controls to use for the specific phase when the host exposes them.
167
+ Before any phase work, resolve and print the OAT dispatch ceiling for the
168
+ current provider. This is a preflight gate, not a mid-run question.
168
169
 
169
- Use these inputs:
170
+ Use the CLI helper as the source of truth for resolution:
170
171
 
171
- - phase ID
172
- - phase scope, including task count, file boundaries, verification commands, and integration risk
173
- - optional `## Dispatch Profile` row in `plan.md`
174
- - host-exposed provider controls, by axis
175
- - prior outcomes for the phase, including review results and failed retries
172
+ ```bash
173
+ oat project dispatch-ceiling resolve --provider <codex|claude> --preflight --json
174
+ ```
176
175
 
177
- Selection rule:
176
+ If `oat` is not in PATH, use:
178
177
 
179
- 1. If a valid Dispatch Profile override row applies and the host can honor it, use the requested provider control and log that the choice came from the override.
180
- 2. If no override applies, choose the lowest available model and/or effort that can confidently complete the phase.
181
- 3. Treat model and effort as separate axes. Each axis logs exactly one state:
182
- - `selected:<value>` — host exposes the axis and the orchestrator chose a value.
183
- - `inherited` — host exposes the axis and the orchestrator deliberately defers to the parent session.
184
- - `not-applicable` — this host/API has no meaningful per-dispatch concept for that axis.
185
- - `host-auto` — exceptional; the host uses that axis internally but the orchestrator cannot read or pin it.
186
- 4. In Codex implementation/fix dispatch, the model axis normally logs `inherited`; choose `effort_axis=selected:low|medium|high` from phase complexity and dispatch the matching effort-specific implementer role. Treat `effort_axis=inherited` as the parent-session ceiling path, not a neutral default.
187
- 5. In Claude Code, when subagent model selection is available, choose the lowest sufficient model on the model axis; the effort axis is `not-applicable` because Claude Code does not expose a separate `reasoning_effort` control for subagent dispatch.
188
- 6. If a host uses model/effort internally but exposes neither axis to the orchestrator, log `model_axis=host-auto, effort_axis=host-auto` and include the rationale that would have informed selection.
189
- 7. If confidence is low, choose a stronger available control before dispatch rather than knowingly underpowering the phase.
178
+ ```bash
179
+ pnpm run cli -- project dispatch-ceiling resolve --provider <codex|claude> --preflight --json
180
+ ```
190
181
 
191
- **Payload-first dispatch invariant.** Select dispatch controls, construct the actual host dispatch argument map, then print the dispatch log from that argument map. Do not emit an `OAT Dispatch:` block with a `Model axis: selected:<value>` or `Effort axis: selected:<value>` field until the corresponding host-tool selection is present in the argument map you are about to call. A selected axis that exists only in the Phase Scope text is invalid; if you cannot or will not pass the host-tool selection, log that axis as `inherited`, `not-applicable`, or `host-auto` instead of `selected:<value>`.
182
+ Resolution order:
192
183
 
193
- **Passing axis values to the host dispatch API.** The log shape and the actual dispatch call must agree: never log a `selected:<value>` axis without passing the corresponding parameter on the dispatch invocation, and never pass an explicit parameter that the log does not reflect.
184
+ 1. Effective config key `workflow.dispatchCeiling.<provider>` via the resolver CLI
185
+ 2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
186
+ 3. Interactive implementation preflight prompt
187
+ 4. Non-interactive unresolved: block before work starts
194
188
 
195
- - **Claude Code implementer/fix dispatch:** when `model_axis=selected:<value>`, pass `model: "<value>"` on the Task tool call. When `model_axis=inherited`, omit the `model` parameter so Claude Code uses its own default. `effort_axis=not-applicable` for both cases because the Task tool exposes no per-dispatch `reasoning_effort` control.
196
- - **Codex implementer/fix dispatch:** default to a selected effort. Classify phase complexity, choose the lowest sufficient `effort_axis=selected:low|medium|high`, and dispatch the matching configured role: `agent_type: "oat-phase-implementer-low"`, `agent_type: "oat-phase-implementer-medium"`, or `agent_type: "oat-phase-implementer-high"`. Those roles set `model_reasoning_effort` in `.codex/agents/*.toml`. Use the base `agent_type: "oat-phase-implementer"` only when `effort_axis=inherited` is intentionally selected for an allowed reason below. Do not use top-level per-call `reasoning_effort` as the standard OAT selected-effort path; dogfooding showed that path can be inconsistent in some Codex runs.
197
- - **Codex inherited effort is the ceiling path:** because inherited effort follows the parent/orchestrator session and may be `xhigh`, do not use `effort_axis=inherited` merely because it is valid, convenient, or avoids choosing a selected effort. Use inherited effort for Codex implementer/fix dispatch only when the user explicitly requested inherited/default parent controls; a valid Dispatch Profile row explicitly requests inherited/default controls; the phase requires the parent-session ceiling and `selected:high` is insufficient; or the selected-effort roles are unavailable or fail to resolve. The dispatch rationale must cite the allowed reason. For ceiling-needed dispatch, explain why `selected:high` is insufficient.
198
- - **Codex xhigh:** do not create or select an `xhigh` implementer variant. Use `xhigh` only when the parent/orchestrator session is already xhigh and therefore `effort_axis=inherited` on the base role is the correct representation. If a phase appears to require xhigh while the parent is not xhigh, choose `selected:high` only if high is sufficient; otherwise split/revise the phase or stop for user re-invocation at xhigh.
199
- - **Claude Code `opus`:** unlike Codex `xhigh`, `opus` is directly selectable. Claude Code exposes `opus` through the Task tool's `model` parameter, so OAT may select it when available (`model_axis=selected:opus`) — including as a terminal escalation step. There is no `opus` inherited-only restriction; the `xhigh` rule above is specific to Codex's effort-variant mechanism, not a general "never select the maximum tier" rule.
200
- - **Reviewer dispatch on either host:** use `model_axis=inherited` by default. For `effort_axis`: use `inherited` on hosts that expose an effort axis (such as Codex); use `not-applicable` on hosts that do not expose a meaningful effort axis (such as Claude Code). Omit `model` and, on Codex, `reasoning_effort` overrides entirely.
189
+ Provider values:
201
190
 
202
- Codex selected-effort implementer/fix dispatch shape:
191
+ - Codex: `low`, `medium`, `high`, `xhigh`
192
+ - Claude: `haiku`, `sonnet`, `opus`
203
193
 
204
- ```yaml
205
- agent_type: oat-phase-implementer-low # or oat-phase-implementer-medium/high
206
- message: |
207
- Phase Scope:
208
- model_axis: inherited
209
- effort_axis: selected:low
210
- ...
194
+ For Codex, also resolve the provider default effort when possible by reading
195
+ Codex configuration (for example `.codex/config.toml`). If it cannot be found,
196
+ display `unknown`. Do not treat provider default as the OAT ceiling.
197
+ The resolver prints this as `providerDefaultEffort` in JSON and includes it in
198
+ human-readable output.
199
+
200
+ Print this before phase work:
201
+
202
+ ```text
203
+ Codex dispatch ceiling: high
204
+ Source: project state
205
+ Codex provider default effort: medium
206
+ Note: OAT will use pinned subagent variants up to high. Base/unpinned roles resolve through the provider default.
211
207
  ```
212
208
 
213
- Invalid Codex selected-effort dispatch shape:
209
+ If no ceiling resolves and the session is interactive, ask before starting
210
+ implementation and persist the answer in project `state.md` frontmatter:
214
211
 
215
212
  ```yaml
216
- agent_type: oat-phase-implementer
217
- reasoning_effort: low
218
- message: |
219
- Phase Scope:
220
- effort_axis: selected:low
213
+ oat_dispatch_ceiling:
214
+ provider: codex
215
+ value: high
216
+ source: project-state
221
217
  ```
222
218
 
223
- The invalid shape relies on per-call override behavior that has proven inconsistent during dogfooding. It also risks creating a log/dispatch mismatch if the override is ignored.
219
+ If no ceiling resolves and `OAT_NON_INTERACTIVE=1` or no user-response channel
220
+ exists, rerun the resolver with non-interactive behavior and stop before work
221
+ starts if it blocks:
224
222
 
225
- **Post-spawn verification gate.** After any Codex implementer/fix `spawn_agent` call with `effort_axis=selected:<value>`, immediately inspect the returned spawn status before waiting for work or updating the plan. If the status shows a different effort, such as `effort_axis=selected:low` followed by `(gpt-5.5 high)`, this is an orchestration deviation. Stop using that agent, record the mismatch in `implementation.md`, and redispatch with the correct effort-specific `agent_type`. Do not continue to `wait_agent`, phase bookkeeping, or the next phase with a mismatched selected-effort dispatch.
223
+ ```bash
224
+ oat project dispatch-ceiling resolve --provider <codex|claude> --preflight --non-interactive
225
+ ```
226
+
227
+ ```text
228
+ BLOCKED: Codex dispatch ceiling is unresolved in non-interactive mode.
229
+ Set workflow.dispatchCeiling.codex in .oat/config.json or oat_dispatch_ceiling in project state.
230
+ ```
231
+
232
+ Dry-run mode must report the unresolved ceiling and planned behavior without
233
+ modifying project state.
226
234
 
227
- After the payload-first check, log the choice before dispatch in this structured shape:
235
+ ### Runtime dispatch selection
236
+
237
+ Before each phase implementation, fix, or review dispatch, choose and log the
238
+ runtime dispatch controls. This is separate from Tier 1/Tier 2 execution mode:
239
+ Tier 1/Tier 2 decides whether OAT uses subagents or inline fallback; runtime
240
+ dispatch selection decides model/effort controls for the specific work.
241
+
242
+ Use these inputs:
243
+
244
+ - resolved dispatch ceiling and source
245
+ - phase ID and phase scope
246
+ - optional `## Dispatch Profile` row in `plan.md`
247
+ - host-exposed provider controls, by axis
248
+ - prior outcomes for the phase, including review results and failed retries
249
+
250
+ Axis states:
251
+
252
+ - `selected:<value>` - host exposes the axis and the orchestrator chose a value.
253
+ - `provider-default` - Codex base/unpinned role follows configured/provider default effort.
254
+ - `inherited` - host/API explicitly inherits the parent setting and OAT can trust that behavior.
255
+ - `not-applicable` - this host/API has no meaningful per-dispatch concept for that axis.
256
+ - `host-auto` - exceptional; the host uses that axis internally but OAT cannot read or pin it.
257
+
258
+ Codex rules:
259
+
260
+ 1. Codex effort order is `low < medium < high < xhigh`.
261
+ 2. Classify preferred effort from scope:
262
+ - `low`: trivial docs-only, narrow single-file, or mechanical changes
263
+ - `medium`: normal multi-file implementation and moderate integration risk
264
+ - `high`: broad architecture, security/auth/redaction boundaries, subtle state behavior, or repeated substantive review failures
265
+ - `xhigh`: highest-risk work that requires the configured ceiling to allow xhigh
266
+ 3. Selected effort is `min(preferred, resolved_ceiling)`.
267
+ 4. Dispatch implementer/fix work through `oat-phase-implementer-<selected>`.
268
+ 5. Dispatch review work through `oat-reviewer-<resolved_ceiling>` for deterministic quality gate behavior.
269
+ 6. Use base/unpinned Codex roles only as a fallback or explicit provider-default choice. Log `Selected effort: provider-default`, display provider default effort when known, and do not describe this as parent-ceiling inheritance.
270
+ 7. Do not use top-level per-call `reasoning_effort` as the standard OAT selected-effort path; dogfooding showed that path can be inconsistent.
271
+
272
+ Claude rules:
273
+
274
+ - Claude ceiling is model-based: `haiku < sonnet < opus`.
275
+ - Select the lowest sufficient model capped by `workflow.dispatchCeiling.claude` or project `oat_dispatch_ceiling`.
276
+ - Pass `model: "<value>"` when `model_axis=selected:<value>` on the Task tool call.
277
+ - Keep `effort_axis=not-applicable`; Claude Code has no separate per-dispatch effort axis.
278
+
279
+ Payload-first invariant:
280
+
281
+ - Build the actual host dispatch argument map before logging.
282
+ - Do not emit `selected:<value>` unless the host invocation contains the corresponding role/model selection.
283
+ - Derive `Dispatch target` and `Effort axis` / `Model axis` from the payload.
284
+
285
+ Structured dispatch log:
228
286
 
229
287
  ```text
230
288
  OAT Dispatch: Phase {phase_id} {implementation | fix | review}
231
289
  Host: {Claude Code | Codex | Cursor | other host}
290
+ Preferred effort: {low | medium | high | xhigh | not-applicable}
291
+ Dispatch ceiling: {resolved ceiling value}
292
+ Selected effort: {low | medium | high | xhigh | provider-default | not-applicable}
293
+ Ceiling source: {repo config | project state | preflight prompt}
294
+ Provider default effort: {value | unknown | not-applicable}
232
295
  Model axis: { selected:<value> | inherited | not-applicable | host-auto }
233
- Effort axis: { selected:<value> | inherited | not-applicable | host-auto }
296
+ Effort axis: { selected:<value> | provider-default | inherited | not-applicable | host-auto }
234
297
  Dispatch target: {host-specific subagent/role/tool target}
235
- Rationale: {short rationale grounded in phase scope}
298
+ Rationale: {short rationale grounded in phase scope and any ceiling cap}
236
299
  ```
237
300
 
238
- For Codex implementation/fix dispatches, the rationale must include the phase complexity class that drove the selected effort (for example, mechanical, normal multi-file, or broad/high-risk). If `Effort axis: inherited`, the rationale must also cite the allowed reason for using the parent-session ceiling instead of `selected:low|medium|high`.
239
-
240
- Examples:
301
+ Codex capped example:
241
302
 
242
303
  ```text
243
- OAT Dispatch: Phase p01 implementation
244
- Host: Claude Code
245
- Model axis: selected:haiku
246
- Effort axis: not-applicable
247
- Dispatch target: oat-phase-implementer
248
- Rationale: mechanical template edits; haiku is the lowest sufficient Claude model.
249
-
250
304
  OAT Dispatch: Phase p02 implementation
251
- Host: Claude Code
252
- Model axis: selected:sonnet
253
- Effort axis: not-applicable
254
- Dispatch target: oat-phase-implementer
255
- Rationale: multi-file integration with mock wiring; sonnet is the lowest sufficient Claude model.
256
-
257
- OAT Dispatch: Phase p03 implementation
258
305
  Host: Codex
306
+ Preferred effort: high
307
+ Dispatch ceiling: medium
308
+ Selected effort: medium
309
+ Ceiling source: repo config
310
+ Provider default effort: high
259
311
  Model axis: inherited
260
312
  Effort axis: selected:medium
261
313
  Dispatch target: oat-phase-implementer-medium
262
- Rationale: shared TypeScript/config substrate with cross-file contracts; medium is the lowest sufficient Codex effort.
314
+ Rationale: normal multi-file implementation; high preferred due to integration risk, capped by configured ceiling.
315
+ ```
263
316
 
264
- OAT Dispatch: Phase p04 implementation
265
- Host: Other
266
- Model axis: host-auto
267
- Effort axis: host-auto
268
- Dispatch target: host default
269
- Rationale: host does not expose readable or pinnable dispatch controls; rationale maps to standard effort.
317
+ Codex reviewer example:
270
318
 
271
- OAT Dispatch: Phase p05 review
319
+ ```text
320
+ OAT Dispatch: Phase p02 review
272
321
  Host: Codex
322
+ Preferred effort: high
323
+ Dispatch ceiling: high
324
+ Selected effort: high
325
+ Ceiling source: project state
326
+ Provider default effort: medium
273
327
  Model axis: inherited
274
- Effort axis: inherited
275
- Dispatch target: oat-reviewer
276
- Rationale: reviewer dispatches inherit parent controls by default.
328
+ Effort axis: selected:high
329
+ Dispatch target: oat-reviewer-high
330
+ Rationale: reviewer runs at the configured ceiling for deterministic quality gate behavior.
277
331
  ```
278
332
 
279
- Use `low` for trivial docs-only, narrow single-file, or mechanical changes; `medium` for normal multi-file implementation and moderate integration risk; `high` for broad architecture, security/auth/redaction boundaries, subtle state behavior, or repeated substantive review failures. Use inherited `xhigh` only when the parent/orchestrator session is already xhigh.
333
+ Codex base/unpinned fallback example:
334
+
335
+ ```text
336
+ OAT Dispatch: Phase p02 review
337
+ Host: Codex
338
+ Preferred effort: provider-default
339
+ Dispatch ceiling: high
340
+ Selected effort: provider-default
341
+ Ceiling source: project state
342
+ Provider default effort: medium
343
+ Model axis: inherited
344
+ Effort axis: provider-default
345
+ Dispatch target: oat-reviewer
346
+ Rationale: base unpinned role fallback; effective effort follows Codex provider default.
347
+ ```
280
348
 
281
- Include the resolved implementation dispatch axes and rationale in the Phase Scope packet when known. Reserve `host-auto` for an axis the host uses internally but the orchestrator cannot read or pin; use `inherited` for deliberate inheritance and `not-applicable` when an axis is not meaningful for that host/API.
349
+ Include resolved dispatch context in scope packets when known:
282
350
 
283
351
  ```yaml
284
352
  model_axis: { selected:<value> | inherited | not-applicable | host-auto }
285
- effort_axis: { selected:<value> | inherited | not-applicable | host-auto }
353
+ effort_axis:
354
+ {
355
+ selected:<value> | provider-default | inherited | not-applicable | host-auto,
356
+ }
357
+ dispatch_ceiling: { resolved ceiling value }
358
+ ceiling_source: { repo config | project state | preflight prompt }
359
+ provider_default_effort: { value | unknown | not-applicable }
286
360
  dispatch_rationale: { short rationale }
287
361
  ```
288
362
 
289
- Review dispatch is intentionally different. A reviewer should inherit the parent session's model and effort axes unless the user explicitly requests a review override. In Codex, omit `model` and `reasoning_effort` overrides when spawning `oat-reviewer`; in Claude Code, do not pass a per-review model override. Log review scope as `model_axis=inherited` and `effort_axis=inherited` on hosts that expose an effort axis (such as Codex), or `effort_axis=not-applicable` on hosts that do not (such as Claude Code).
290
-
291
363
  ### Dry-Run Mode
292
364
 
293
365
  When the skill is invoked with `--dry-run`:
@@ -564,22 +636,25 @@ For each phase `pNN` in the plan (or each phase in the current parallel group),
564
636
  commit_convention: {from plan.md header}
565
637
  workflow_mode: {from state.md or plan.md frontmatter}
566
638
  model_axis: {selected:<value> | inherited | not-applicable | host-auto; omit if unknown}
567
- effort_axis: {selected:<value> | inherited | not-applicable | host-auto; omit if unknown}
639
+ effort_axis: {selected:<value> | provider-default | inherited | not-applicable | host-auto; omit if unknown}
640
+ dispatch_ceiling: {resolved ceiling value; omit if unknown}
641
+ ceiling_source: {repo config | project state | preflight prompt; omit if unknown}
642
+ provider_default_effort: {value | unknown | not-applicable; omit if unknown}
568
643
  dispatch_rationale: {short rationale; omit if unknown}
569
644
  ```
570
645
 
571
646
  2. Perform a pre-dispatch assertion against the host invocation parameters. The Phase Scope fields are audit/context fields; selected axes must also be represented in the actual host dispatch call.
572
647
  - Codex implementer/fix dispatch:
573
- - Before building the `spawn_agent` argument map, classify the phase complexity and choose the lowest sufficient selected effort (`low`, `medium`, or `high`) when the matching effort-specific role is available.
574
- - Build the `spawn_agent` argument map before logging the dispatch. If `effort_axis=selected:low|medium|high`, the argument map MUST use the matching `agent_type`: `"oat-phase-implementer-low"`, `"oat-phase-implementer-medium"`, or `"oat-phase-implementer-high"`. Then derive the `OAT Dispatch:` block `Effort axis:` field from that same argument map.
648
+ - Before building the `spawn_agent` argument map, classify the phase complexity and choose preferred effort (`low`, `medium`, `high`, or `xhigh`), then cap it to the resolved Codex dispatch ceiling.
649
+ - Build the `spawn_agent` argument map before logging the dispatch. If `effort_axis=selected:low|medium|high|xhigh`, the argument map MUST use the matching `agent_type`: `"oat-phase-implementer-low"`, `"oat-phase-implementer-medium"`, `"oat-phase-implementer-high"`, or `"oat-phase-implementer-xhigh"`. Then derive the `OAT Dispatch:` block `Effort axis:` field from that same argument map.
575
650
  - Example selected low payload shape: `agent_type: "oat-phase-implementer-low"` and a Phase Scope message containing `effort_axis: selected:low`.
576
651
  - Immediately after spawning, compare the returned Codex status line with the selected effort before waiting on the agent. If the spawned status reports a different effort than the selected value (for example, the log says `effort_axis=selected:medium` but the spawn result reports `gpt-5.5 high`), treat this as an orchestration deviation. Stop, record the deviation in `implementation.md`, and redispatch with corrected parameters before continuing. Do not use work from the mismatched dispatch.
577
- - If `effort_axis=inherited`, use base `agent_type: "oat-phase-implementer"` and omit `reasoning_effort`. This is the parent-session ceiling path, so the dispatch rationale MUST cite the explicit user/Dispatch Profile override, explain why `selected:high` is insufficient, or record that the selected-effort roles are unavailable or failed to resolve.
652
+ - If `effort_axis=provider-default`, use base `agent_type: "oat-phase-implementer"` and omit `reasoning_effort`. The dispatch rationale MUST say this is a base/unpinned fallback and include provider default effort when known.
578
653
  - Claude Code implementer/fix dispatch:
579
654
  - If `model_axis=selected:<value>`, the Task tool call MUST include `model: "<value>"`.
580
655
  - If `model_axis=inherited`, omit `model`.
581
656
 
582
- 3. Dispatch the selected implementer role (Tier 1 via provider-native subagent mechanism) — the role asserted in the pre-dispatch step above (e.g., `oat-phase-implementer-low`, `oat-phase-implementer-medium`, `oat-phase-implementer-high`, or base `oat-phase-implementer` for inherited effort) — with the Phase Scope block as input and with the asserted host invocation parameters.
657
+ 3. Dispatch the selected implementer role (Tier 1 via provider-native subagent mechanism) — the role asserted in the pre-dispatch step above (e.g., `oat-phase-implementer-low`, `oat-phase-implementer-medium`, `oat-phase-implementer-high`, `oat-phase-implementer-xhigh`, or base `oat-phase-implementer` only for provider-default fallback) — with the Phase Scope block as input and with the asserted host invocation parameters.
583
658
 
584
659
  4. Receive the structured summary (DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED).
585
660
 
@@ -614,8 +689,8 @@ Escalate the runtime dispatch control when there is evidence that the current co
614
689
  When escalation is needed:
615
690
 
616
691
  1. If a stronger available control exists, re-dispatch at the next stronger control and include the reason in the scope packet. The escalation ladder is provider-specific:
617
- - **Codex:** `selected:low selected:medium selected:high exhausted`. `high` is the strongest control OAT can select. Beyond `high`: if the parent/orchestrator session is already `xhigh`, dispatch uses `effort_axis=inherited`; otherwise escalation is exhausted — stop, split the phase, or ask the user to re-invoke at `xhigh` (see step 4).
618
- - **Claude Code:** `selected:haiku selected:sonnet selected:opus`. `opus` is a selectable terminal step when available (and not capped by a future Claude-specific ceiling).
692
+ - **Codex:** `selected:low -> selected:medium -> selected:high -> selected:xhigh`, capped by the resolved Codex dispatch ceiling.
693
+ - **Claude Code:** `selected:haiku -> selected:sonnet -> selected:opus`, capped by the resolved Claude dispatch ceiling.
619
694
  2. Count the escalation redispatch against the existing bounded retry budget. Escalation changes the control; it does not create extra retry attempts.
620
695
  3. Record a compact note in `implementation.md` when practical:
621
696
  - `Dispatch: p03 escalated to model_axis=selected:opus, effort_axis=not-applicable after repeated review failures.` (Claude Code)
@@ -634,8 +709,9 @@ After the implementer returns DONE (or DONE_WITH_CONCERNS without correctness co
634
709
  **Dispatch:**
635
710
 
636
711
  - Use the same tier that was selected at start.
637
- - Inherit the parent session's model/effort/control for review. Do not choose a separate reviewer model or reasoning effort unless the user explicitly requests an override.
638
- - Tier 1: dispatch `oat-reviewer` via provider-native subagent mechanism with Review Scope:
712
+ - For Codex, dispatch the reviewer variant matching the resolved ceiling (`oat-reviewer-low|medium|high|xhigh`) for deterministic quality gates.
713
+ - For Claude Code, cap any selected review model by the resolved Claude ceiling and keep `effort_axis=not-applicable`.
714
+ - Tier 1: dispatch the selected reviewer target via provider-native subagent mechanism with Review Scope:
639
715
 
640
716
  ```
641
717
  project: {PROJECT_PATH}
@@ -646,13 +722,16 @@ After the implementer returns DONE (or DONE_WITH_CONCERNS without correctness co
646
722
  workflow_mode: {from state.md}
647
723
  artifact_paths: {same as Phase Scope}
648
724
  tasks_in_scope: {list of pNN-tNN IDs in the phase}
725
+ dispatch_ceiling: {resolved ceiling value}
726
+ ceiling_source: {repo config | project state | preflight prompt}
727
+ provider_default_effort: {value | unknown | not-applicable}
649
728
  model_axis: inherited
650
- effort_axis: inherited # on Codex; use not-applicable on Claude Code
651
- dispatch_rationale: review dispatch inherits parent session controls
729
+ effort_axis: selected:{resolved Codex ceiling} # on Codex; use not-applicable on Claude Code
730
+ dispatch_rationale: reviewer runs at the configured ceiling for deterministic quality gate behavior
652
731
  ```
653
732
 
654
733
  - For Codex Tier 1 dispatches, send the Review Scope block as a self-contained packet and keep fresh context (`fork_context: false`). The reviewer is expected to reconstruct context from git state and the OAT artifacts listed above.
655
- - For Codex Tier 1 review dispatches, omit `model` and `reasoning_effort` overrides in the `spawn_agent` call. For Claude Code review dispatches, do not pass a per-review model override. `host-auto` is not the right label when the review is intentionally inheriting parent controls.
734
+ - For Codex Tier 1 review dispatches, use `agent_type: "oat-reviewer-low|medium|high|xhigh"` matching the resolved ceiling. Use base `oat-reviewer` only as a provider-default fallback and log `effort_axis=provider-default`. For Claude Code review dispatches, do not pass a per-review effort override because the effort axis is not applicable; if selecting a model, cap it by the resolved Claude ceiling.
656
735
  - Treat the commit range as authoritative for review scope. `files_changed` is optional orientation metadata only.
657
736
  - If a Codex reviewer does not return a terminal result on the first wait, poll once more. If it still has not concluded, send one concise nudge to return immediately with current findings. If the reviewer still does not conclude, treat the Tier 1 review dispatch as failed for this phase and perform the review inline instead of waiting indefinitely.
658
737
 
@@ -673,7 +752,7 @@ On reviewer verdict `fail`, run a bounded fix loop.
673
752
 
674
753
  1. Read `oat_orchestration_retry_limit` from `state.md` frontmatter (default: `2`, range 0–5).
675
754
  2. For each retry (up to the limit):
676
- a. Select/log fix dispatch axes from the fix scope, then perform the same pre-dispatch assertion used for implementation dispatch. A Codex fix dispatch with `effort_axis=selected:low|medium|high` MUST use matching `agent_type: "oat-phase-implementer-low|medium|high"`; a Claude Code fix dispatch with `model_axis=selected:<value>` MUST pass `model: "<value>"` on the Task call.
755
+ a. Select/log fix dispatch axes from the fix scope, then perform the same pre-dispatch assertion used for implementation dispatch. A Codex fix dispatch with `effort_axis=selected:low|medium|high|xhigh` MUST use matching `agent_type: "oat-phase-implementer-low|medium|high|xhigh"`; a Claude Code fix dispatch with `model_axis=selected:<value>` MUST pass `model: "<value>"` on the Task call.
677
756
  b. Dispatch the selected phase implementer role in `fix` mode (Tier 1) OR read the agent and apply fixes inline (Tier 2), with: - `review_artifact`: the path written by the reviewer - `findings`: the Critical + Important findings list - `prior_summary`: the last implementer summary
678
757
  c. Receive the fix summary.
679
758
  d. Re-dispatch the reviewer with the updated commit range.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-plan
3
- version: 1.3.2
3
+ version: 1.3.3
4
4
  description: Use when design.md is complete and executable implementation tasks are needed. Breaks design into bite-sized TDD tasks in canonical plan.md format.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -312,6 +312,62 @@ Unless the source artifact or user already supplied a confirmed `oat_plan_hill_p
312
312
 
313
313
  If `## Planning Checklist` is missing (older plans), add it before finalizing with the items above.
314
314
 
315
+ ### Step 11.5: Resolve Dispatch Ceiling Before Implementation Readiness
316
+
317
+ Before marking the plan ready for implementation, resolve the dispatch ceiling
318
+ for the current provider.
319
+
320
+ Resolution order:
321
+
322
+ 1. Repo/user/local config key `workflow.dispatchCeiling.<provider>` via `oat config get`
323
+ 2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
324
+ 3. Interactive planning prompt
325
+ 4. Leave unresolved for implementation preflight when non-interactive
326
+
327
+ Provider values:
328
+
329
+ - Codex: `low`, `medium`, `high`, `xhigh`
330
+ - Claude: `haiku`, `sonnet`, `opus`
331
+
332
+ If no ceiling resolves for the current provider and the session is interactive,
333
+ ask once before final plan review:
334
+
335
+ ```text
336
+ No Codex dispatch ceiling is configured for this project.
337
+
338
+ Choose the maximum Codex reasoning effort OAT may dispatch during implementation:
339
+ low | medium | high | xhigh
340
+
341
+ This controls implementer/reviewer subagent variants. It does not change your Codex config.
342
+ ```
343
+
344
+ Adapt the wording for Claude:
345
+
346
+ ```text
347
+ No Claude dispatch ceiling is configured for this project.
348
+
349
+ Choose the maximum Claude model tier OAT may dispatch during implementation:
350
+ haiku | sonnet | opus
351
+
352
+ This controls provider-native subagent model selection. It does not change your Claude config.
353
+ ```
354
+
355
+ Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter:
356
+
357
+ ```yaml
358
+ oat_dispatch_ceiling:
359
+ provider: codex
360
+ value: high
361
+ source: project-state
362
+ ```
363
+
364
+ Do not prompt when `OAT_NON_INTERACTIVE=1` or when no user-response channel
365
+ exists. In that case, leave the value unresolved. `oat-project-implement`
366
+ must block before work starts if it still cannot resolve a ceiling.
367
+
368
+ Do not treat Codex provider default effort as the OAT dispatch ceiling. Provider
369
+ default is informational for base/unpinned roles only.
370
+
315
371
  ### Step 12: Review Plan with User
316
372
 
317
373
  Present plan summary:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-plan-writing
3
- version: 1.2.3
3
+ version: 1.2.4
4
4
  description: Use when authoring or mutating plan.md in any OAT workflow. Defines canonical format invariants — stable task IDs, required sections, review table rules, and resume guardrails.
5
5
  disable-model-invocation: true
6
6
  user-invocable: false
@@ -48,6 +48,10 @@ Runtime routing note:
48
48
 
49
49
  - Keep `oat_ready_for` canonical as `oat-project-implement`.
50
50
  - Declare parallelism via `oat_plan_parallel_groups` in plan.md frontmatter (empty = sequential; nested arrays of phase IDs = parallel groups). `oat-project-implement` reads this field to choose sequential vs worktree-isolated parallel execution.
51
+ - Dispatch ceilings are not stored in `plan.md`. Plan-producing skills resolve
52
+ them from `workflow.dispatchCeiling.<provider>` or project `state.md`
53
+ frontmatter, then persist interactive answers back to `state.md` as
54
+ `oat_dispatch_ceiling`.
51
55
 
52
56
  Additional frontmatter keys (`oat_phase`, `oat_phase_status`, `oat_blockers`, `oat_last_updated`, `oat_generated`, `oat_template`, `oat_import_reference`, `oat_import_source_path`, `oat_import_provider`) are set by calling skills as needed.
53
57
 
@@ -71,7 +75,7 @@ Validation rules for explicit rows:
71
75
 
72
76
  - `Phase` must match a real `pNN` phase in the plan.
73
77
  - `Claude model` must be `haiku`, `sonnet`, `opus`, `auto`, or blank.
74
- - `Codex effort` must be `low`, `medium`, `high`, `xhigh`, `auto`, or blank. In Codex, `low`, `medium`, and `high` map to effort-specific implementer roles. Codex xhigh is inherited-only; `xhigh` can be honored only by inheriting an already-xhigh parent/orchestrator session, not by selecting an `xhigh` implementer variant.
78
+ - `Codex effort` must be `low`, `medium`, `high`, `xhigh`, `auto`, or blank. In Codex, explicit effort values are preferred controls that `oat-project-implement` caps against the resolved OAT dispatch ceiling and maps to pinned implementer variants when selected. Provider default effort is informational for base/unpinned roles and is not an OAT ceiling.
75
79
  - Blank or `auto` means no explicit constraint for that provider.
76
80
  - `Rationale` is recommended and should explain why runtime selection should not decide on its own.
77
81
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-quick-start
3
- version: 2.1.1
3
+ version: 2.1.2
4
4
  description: Use when a task is small enough for quick mode or rapid iteration is preferred. Scaffolds a lightweight OAT project from discovery directly to a runnable plan, with optional brainstorming and lightweight design.
5
5
  argument-hint: '<project-name> ["project description"]'
6
6
  disable-model-invocation: true
@@ -456,6 +456,62 @@ Required parallelism pass before finalizing the plan:
456
456
  - Quick mode is not "sequential by default." A quick-start plan is sequential only when the dependency and write-set analysis says it should be.
457
457
  - When a task claims scoped verification, prefer the exact runner invocation that truly scopes to the intended file, test, or target instead of package-level shortcuts that may execute the full suite.
458
458
 
459
+ ### Step 3.5: Resolve Dispatch Ceiling Before Implementation Readiness
460
+
461
+ Before moving the quick project to ready-for-implementation, resolve the
462
+ dispatch ceiling for the current provider.
463
+
464
+ Resolution order:
465
+
466
+ 1. Repo/user/local config key `workflow.dispatchCeiling.<provider>` via `oat config get`
467
+ 2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
468
+ 3. Interactive quick-planning prompt
469
+ 4. Leave unresolved for implementation preflight when non-interactive
470
+
471
+ Provider values:
472
+
473
+ - Codex: `low`, `medium`, `high`, `xhigh`
474
+ - Claude: `haiku`, `sonnet`, `opus`
475
+
476
+ If no ceiling resolves for the current provider and the session is interactive,
477
+ ask once before finalizing `plan.md`:
478
+
479
+ ```text
480
+ No Codex dispatch ceiling is configured for this project.
481
+
482
+ Choose the maximum Codex reasoning effort OAT may dispatch during implementation:
483
+ low | medium | high | xhigh
484
+
485
+ This controls implementer/reviewer subagent variants. It does not change your Codex config.
486
+ ```
487
+
488
+ Adapt the wording for Claude:
489
+
490
+ ```text
491
+ No Claude dispatch ceiling is configured for this project.
492
+
493
+ Choose the maximum Claude model tier OAT may dispatch during implementation:
494
+ haiku | sonnet | opus
495
+
496
+ This controls provider-native subagent model selection. It does not change your Claude config.
497
+ ```
498
+
499
+ Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter:
500
+
501
+ ```yaml
502
+ oat_dispatch_ceiling:
503
+ provider: codex
504
+ value: high
505
+ source: project-state
506
+ ```
507
+
508
+ Do not prompt when `OAT_NON_INTERACTIVE=1` or when no user-response channel
509
+ exists. In that case, leave the value unresolved. `oat-project-implement`
510
+ must block before work starts if it still cannot resolve a ceiling.
511
+
512
+ Do not treat Codex provider default effort as the OAT dispatch ceiling. Provider
513
+ default is informational for base/unpinned roles only.
514
+
459
515
  ### Step 4: Sync Project State
460
516
 
461
517
  Update `"$PROJECT_PATH/state.md"`:
@@ -61,7 +61,7 @@ Blank or `auto` means there is no explicit constraint for that provider. Do not
61
61
  | ----- | ------------------------- | ------------------------------ | ----------------------------- |
62
62
  | pNN | haiku\|sonnet\|opus\|auto | low\|medium\|high\|xhigh\|auto | why this constraint is needed |
63
63
 
64
- Codex `low`, `medium`, and `high` effort values map to effort-specific implementer roles. `xhigh` is inherited-only: it can be honored only when the parent/orchestrator session is already xhigh, not by selecting an `xhigh` implementer variant.
64
+ Codex effort values are preferred controls. `oat-project-implement` caps them against the resolved OAT dispatch ceiling and maps selected efforts to pinned implementer variants. Codex provider default effort is informational for base/unpinned roles and is not an OAT ceiling.
65
65
 
66
66
  ---
67
67
 
@@ -14,6 +14,10 @@ oat_parallel_execution: false
14
14
  oat_phase: { OAT_PHASE } # Current phase: discovery | spec | design | plan | implement | decomposition
15
15
  oat_phase_status: in_progress # Status: in_progress | complete | pr_open
16
16
  # oat_orchestration_retry_limit: 2 # optional; override fix-loop retry limit (range 0-5)
17
+ # oat_dispatch_ceiling: # optional project override for provider-aware dispatch ceilings
18
+ # provider: codex # codex | claude
19
+ # value: high # codex: low|medium|high|xhigh; claude: haiku|sonnet|opus
20
+ # source: project-state
17
21
  oat_workflow_mode: { OAT_WORKFLOW_MODE } # spec-driven | quick | import
18
22
  oat_workflow_origin: native # native | imported
19
23
  oat_docs_updated: null # null | skipped | complete — documentation sync status
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAOhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyDpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAonCD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CA0GT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAOhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2DpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA2pCD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CA0GT"}