@open-agent-toolkit/cli 0.1.41 → 0.1.43

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 (47) hide show
  1. package/assets/agents/oat-phase-implementer.md +13 -9
  2. package/assets/agents/oat-reviewer.md +16 -12
  3. package/assets/docs/cli-utilities/configuration.md +51 -35
  4. package/assets/docs/cli-utilities/workflow-gates.md +55 -0
  5. package/assets/docs/reference/cli-reference.md +1 -1
  6. package/assets/docs/reference/oat-directory-structure.md +26 -24
  7. package/assets/docs/workflows/projects/artifacts.md +22 -0
  8. package/assets/docs/workflows/projects/dispatch-ceiling.md +128 -85
  9. package/assets/docs/workflows/projects/hill-checkpoints.md +2 -0
  10. package/assets/docs/workflows/projects/implementation-execution.md +70 -46
  11. package/assets/docs/workflows/projects/index.md +2 -2
  12. package/assets/docs/workflows/projects/lifecycle.md +17 -2
  13. package/assets/docs/workflows/projects/reviews.md +17 -0
  14. package/assets/public-package-versions.json +4 -4
  15. package/assets/skills/oat-project-implement/SKILL.md +256 -95
  16. package/assets/skills/oat-project-plan/SKILL.md +60 -29
  17. package/assets/skills/oat-project-plan-writing/SKILL.md +10 -10
  18. package/assets/skills/oat-project-quick-start/SKILL.md +60 -29
  19. package/assets/skills/oat-project-review-provide/SKILL.md +25 -13
  20. package/assets/skills/oat-project-review-receive/SKILL.md +20 -10
  21. package/assets/skills/oat-review-provide/SKILL.md +14 -12
  22. package/assets/skills/oat-review-provide/references/review-artifact-template.md +1 -1
  23. package/assets/templates/plan.md +4 -4
  24. package/assets/templates/state.md +7 -3
  25. package/dist/commands/config/index.d.ts.map +1 -1
  26. package/dist/commands/config/index.js +66 -3
  27. package/dist/commands/gate/index.d.ts.map +1 -1
  28. package/dist/commands/gate/index.js +15 -3
  29. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  30. package/dist/commands/project/dispatch-ceiling/index.js +296 -49
  31. package/dist/commands/review/latest.d.ts.map +1 -1
  32. package/dist/commands/review/latest.js +5 -2
  33. package/dist/commands/shared/frontmatter.d.ts +11 -0
  34. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  35. package/dist/commands/shared/frontmatter.js +15 -0
  36. package/dist/config/dispatch-ceiling-preset.d.ts +37 -1
  37. package/dist/config/dispatch-ceiling-preset.d.ts.map +1 -1
  38. package/dist/config/dispatch-ceiling-preset.js +20 -0
  39. package/dist/config/oat-config.d.ts +10 -1
  40. package/dist/config/oat-config.d.ts.map +1 -1
  41. package/dist/config/oat-config.js +20 -1
  42. package/dist/config/resolve.d.ts.map +1 -1
  43. package/dist/config/resolve.js +4 -0
  44. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  45. package/dist/providers/ceiling/registry.js +6 -1
  46. package/dist/providers/codex/codec/sync-extension.js +1 -1
  47. package/package.json +2 -2
@@ -1,134 +1,177 @@
1
1
  ---
2
- title: Dispatch Ceiling
3
- description: "How OAT's provider-neutral dispatch ceiling works presets, the compile/resolve flow, and how enforcement differs for Codex, Claude, and unsupported providers."
2
+ title: Dispatch Policy
3
+ description: 'How OAT dispatch policy works: managed capped tiers, managed Uncapped, Inherit Host Defaults, legacy dispatch-ceiling compatibility, and provider-specific enforcement.'
4
4
  ---
5
5
 
6
- # Dispatch Ceiling
6
+ # Dispatch Policy
7
7
 
8
- The **dispatch ceiling** is the most capable tier OAT is allowed to use when it dispatches subagents (phase implementers and reviewers) during `oat-project-implement`. It is a **provider-neutral OAT intent** — your declaration of "don't go above this," decoupled from which provider you happen to be running. OAT then applies that intent through whatever mechanism each provider actually exposes.
8
+ OAT dispatch policy controls how `oat-project-implement` selects model or
9
+ effort controls for phase implementers, fix loops, and reviewers. The current
10
+ contract separates two ideas that used to be conflated:
9
11
 
10
- This page explains the model, the why, and — most importantly — how enforcement differs across providers. For the raw config keys see [Configuration](../../cli-utilities/configuration.md); for how dispatch runs at execution time see [Implementation Execution](implementation-execution.md).
12
+ - **Managed policies** keep OAT responsible for selecting model/effort controls.
13
+ - **Inherit Host Defaults** tells OAT not to select model/effort controls and to
14
+ let the executing host/provider decide.
11
15
 
12
- ## Two principles
16
+ The CLI command is still named `oat project dispatch-ceiling resolve` for
17
+ compatibility, and legacy `workflow.dispatchCeiling.*` / `oat_dispatch_ceiling`
18
+ state is still readable as capped managed input. New configuration should use
19
+ dispatch policy terminology.
13
20
 
14
- 1. **Presets are convenience only — they compile to concrete values at _write_ time.** A fuzzy label like `balanced` is never read at dispatch; it is expanded into concrete per-provider values the moment you set it.
15
- 2. **Enforcement capability is computed at dispatch, never stored.** Whether a ceiling is _enforced_, _advisory_, or _unsupported_ is a property of the provider × runtime, so OAT recomputes it on every run rather than persisting a value that would go stale.
21
+ For raw config keys see [Configuration](../../cli-utilities/configuration.md);
22
+ for execution-time behavior see [Implementation Execution](implementation-execution.md).
16
23
 
17
- ## Setting a ceiling
24
+ ## Policy Choices
18
25
 
19
- Set it via `oat config set` (repo / user / local) or answer the planning/implementation preflight prompt. Three shapes:
26
+ | Policy | Mode | Codex target | Claude target | Meaning |
27
+ | ----------------------- | ------- | ------------ | ------------- | -------------------------------------------- |
28
+ | `Economy` | managed | `medium` | `sonnet` | Lower-cost managed cap |
29
+ | `Balanced` | managed | `high` | `sonnet` | Default managed cap |
30
+ | `High` | managed | `xhigh` | `opus` | High-capability managed cap |
31
+ | `Frontier` | managed | `xhigh` | `fable` | Top managed tier currently exposed by OAT |
32
+ | `Uncapped` | managed | none | none | OAT selects preferred controls without a cap |
33
+ | `Inherit Host Defaults` | inherit | none | none | OAT does not select model/effort controls |
20
34
 
21
- | Choice | What gets written |
22
- | ------------------------------------------------------ | ---------------------------------------------------------------------- |
23
- | **Preset** `balanced` / `maximum` / `cost-conscious` | The preset label (provenance) **and** the compiled per-provider values |
24
- | **Advanced** — set providers directly | `providers.*` only (no `preset` key) |
25
- | **No ceiling** | Nothing — each provider runs at its normal/inherited behavior |
35
+ `Uncapped` is explicit managed state. It is not represented by omitting policy
36
+ state. Existing projects with absent legacy ceiling state remain unresolved or
37
+ legacy-compatible; they do not silently become managed `Uncapped`.
26
38
 
27
- The fixed preset table:
39
+ ## Config Shapes
28
40
 
29
- | Preset | Codex | Claude |
30
- | -------------- | -------- | -------- |
31
- | Balanced | `high` | `sonnet` |
32
- | Maximum | `xhigh` | `opus` |
33
- | Cost-conscious | `medium` | `sonnet` |
41
+ Preferred managed policy config:
34
42
 
35
- `cost-conscious` deliberately keeps Claude at `sonnet` (no `haiku` reviewers by default) so review quality stays trustworthy.
43
+ ```bash
44
+ oat config set workflow.dispatchPolicy.policy balanced --shared
45
+ oat config set workflow.dispatchPolicy.policy frontier --shared
46
+ oat config set workflow.dispatchPolicy.policy uncapped --shared
47
+ ```
36
48
 
37
- Config keys:
38
-
39
- - `workflow.dispatchCeiling.preset`
40
- - `workflow.dispatchCeiling.providers.codex` (`low` \| `medium` \| `high` \| `xhigh`)
41
- - `workflow.dispatchCeiling.providers.claude` (`haiku` \| `sonnet` \| `opus`)
49
+ `workflow.dispatchPolicy.policy` writes `workflow.dispatchPolicy.mode=managed`.
50
+ To request host defaults:
42
51
 
43
52
  ```bash
44
- # A preset compiles immediately to concrete per-provider values:
45
- oat config set workflow.dispatchCeiling.preset balanced --shared
46
- # → stores preset: balanced AND providers: { codex: high, claude: sonnet }
53
+ oat config set workflow.dispatchPolicy.mode inherit --shared
54
+ ```
47
55
 
48
- # Or set providers directly (advanced — no preset key stored):
49
- oat config set workflow.dispatchCeiling.providers.codex high --shared
56
+ Project state uses the same shape:
57
+
58
+ ```yaml
59
+ oat_dispatch_policy:
60
+ mode: managed
61
+ policy: balanced
62
+ providers:
63
+ codex: high
64
+ claude: sonnet
65
+ source: project-state
50
66
  ```
51
67
 
52
- Project state can persist the compiled answer as `oat_dispatch_ceiling` (`preset?` + `providers` + `source`) so a planning/preflight choice carries into implementation.
68
+ For `Uncapped`, omit provider caps:
69
+
70
+ ```yaml
71
+ oat_dispatch_policy:
72
+ mode: managed
73
+ policy: uncapped
74
+ source: project-state
75
+ ```
53
76
 
54
- > The earlier flat `workflow.dispatchCeiling.codex` / `.claude` keys were removed. This was a clean break with no migration — set the new keys above.
77
+ For host defaults:
78
+
79
+ ```yaml
80
+ oat_dispatch_policy:
81
+ mode: inherit
82
+ source: project-state
83
+ ```
55
84
 
56
- ## How it resolves at dispatch
85
+ Legacy compatibility keys remain readable:
86
+
87
+ - `workflow.dispatchCeiling.preset`
88
+ - `workflow.dispatchCeiling.providers.codex`
89
+ - `workflow.dispatchCeiling.providers.claude`
90
+ - `oat_dispatch_ceiling`
91
+
92
+ Legacy preset names map into the managed ladder: `cost-conscious` maps to
93
+ `Economy`, `balanced` maps to `Balanced`, and `maximum` maps to `High`.
94
+
95
+ ## How Resolution Works
57
96
 
58
97
  Before dispatching a subagent, the orchestrator calls:
59
98
 
60
99
  ```bash
61
- oat project dispatch-ceiling resolve --provider <provider> --role <implementer|reviewer> --preflight --json
100
+ oat project dispatch-ceiling resolve --provider <provider> --role <implementer|reviewer> --json
62
101
  ```
63
102
 
64
- For implementer or fix dispatch, pass the runtime classification too. In Codex
65
- this is the preferred effort; in Claude it is the preferred model tier:
103
+ For implementer or fix dispatch, pass the preferred runtime control:
66
104
 
67
105
  ```bash
68
- oat project dispatch-ceiling resolve --provider codex --role implementer --preferred medium --json
69
- oat project dispatch-ceiling resolve --provider claude --role implementer --preferred sonnet --json
106
+ oat project dispatch-ceiling resolve --provider codex --role implementer --preferred high --json
107
+ oat project dispatch-ceiling resolve --provider claude --role implementer --preferred opus --json
70
108
  ```
71
109
 
72
- The resolver:
73
-
74
- 1. reads the concrete `providers.<provider>` value (config precedence, then project state) — **never the preset label**;
75
- 2. looks up that provider's **adapter** in the provider ceiling registry;
76
- 3. applies `--preferred` for implementer/fix dispatch, capping it against the ceiling;
77
- 4. returns a per-provider result: `{ value, mode, mechanism, dispatchArgs, selection }`.
110
+ The resolver returns the resolved policy, optional cap, source, provider default
111
+ effort where applicable, and provider-specific `dispatchArgs`.
78
112
 
79
- `mode` is the honest enforcement status, computed right there and never persisted:
113
+ Selection modes:
80
114
 
81
- - **enforced** the provider has a real mechanism and OAT dispatched the requested control.
82
- - **advisory** the ceiling is recorded as intent, but the provider can't deterministically enforce it (or an above-orchestrator request couldn't be honored).
83
- - **unsupported** no adapter mechanism exists for that provider.
115
+ - `capped` - implementer/fix dispatch selects `min(preferred, cap)`.
116
+ - `uncapped` - implementer/fix dispatch selects the preferred value.
117
+ - `review-target` - reviewer dispatch targets a configured cap when one exists.
118
+ - `no-review-target` - managed uncapped reviewer dispatch has no configured
119
+ target and falls back to the base/unpinned reviewer.
120
+ - `inherit-default` - OAT returns no dispatch args and leaves controls to the host.
121
+ - `unresolved` - non-interactive implementation blocks before work starts.
84
122
 
85
- ## Per-provider behavior
123
+ ## Provider Behavior
86
124
 
87
- The same ceiling intent produces different — but honest — behavior per provider, because each adapter declares its own mechanism.
125
+ | | Codex | Claude Code | Unsupported provider |
126
+ | ----------------- | ------------------------------------------- | --------------------------------------- | -------------------- |
127
+ | Managed mechanism | Pinned role variants | Task `model` argument | None |
128
+ | Axis | effort (`low < medium < high < xhigh`) | model (`haiku < sonnet < opus < fable`) | None |
129
+ | Capped policy | selected pinned variant up to cap | selected Task model up to cap | advisory/unsupported |
130
+ | Uncapped | preferred pinned variant, no cap | preferred Task model, no cap | advisory/unsupported |
131
+ | Inherit/default | base/unpinned role follows provider default | omit `model` | normal behavior |
88
132
 
89
- | | **Codex** | **Claude** | **Unsupported provider** |
90
- | ----------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------- | -------------------------- |
91
- | Can OAT enforce? | Yes | Yes | No (no adapter yet) |
92
- | Mechanism | Pinned variant files | Per-call Task `model` argument | None |
93
- | Where it lives | Sync-time committed `.codex` role variants (`oat-phase-implementer-high`, `oat-reviewer-high`, …) | Passed at dispatch time — **no files** | — |
94
- | Axis | effort (`low < medium < high < xhigh`) | model tier (`haiku < sonnet < opus`) | — |
95
- | `dispatchArgs` | `{ variant: "oat-reviewer-high" }` | `{ model: "sonnet" }` | `null` |
96
- | `mode` | `enforced` | `enforced` | `advisory` / `unsupported` |
97
- | If no ceiling set | base/unpinned role (provider default) | inherits the orchestrator's model | normal behavior |
133
+ Codex uses pinned variants because per-call effort controls were unreliable in
134
+ dogfooding. For managed `Uncapped`, OAT still selects the preferred pinned
135
+ variant; the dispatching host should verify whether upward effort selection is
136
+ actually honored in the current session.
98
137
 
99
- ### Why the mechanisms differ
138
+ Claude Code uses the per-call Task `model` argument. It has no OAT-managed
139
+ per-dispatch effort axis, so dispatch logs use `effort_axis=not-applicable`.
140
+ `Frontier` maps to Claude `fable`.
100
141
 
101
- - **Codex** dispatches through **pinned, sync-time role variants**. Per-call reasoning-effort proved unreliable in practice, so OAT generates committed `oat-phase-implementer-{low..xhigh}` / `oat-reviewer-{low..xhigh}` role files. Implementer/fix dispatch passes `--preferred` so `dispatchArgs.variant` matches the selected capped effort; reviewer dispatch uses the variant matching the resolved ceiling.
102
- - **Claude** uses the **per-call Task `model` parameter**, which is reliable and bidirectional (a Sonnet orchestrator can dispatch an Opus subagent and vice-versa) and overrides agent frontmatter. Implementer/fix dispatch passes `--preferred` as the preferred model tier and receives the capped selected `model`; reviewer dispatch uses the ceiling model. OAT needs no variant files.
103
- - **Unsupported providers** (any without a registered adapter) resolve to `unsupported` with `dispatchArgs: null`. The resolve command **returns cleanly and never blocks** — the ceiling is recorded as intent and applied if/when an adapter ships, while the provider runs at its own capabilities.
142
+ ## Implementer, Fix, and Reviewer Behavior
104
143
 
105
- A **provider adapter registry** is what lets these genuinely different mechanisms sit behind one resolver, so the lifecycle skills consume `dispatchArgs` without ever branching on provider.
144
+ For implementer and fix dispatches:
106
145
 
107
- ## Cap vs target: implementer vs reviewer
146
+ - Capped managed policies select `min(preferred, cap)`.
147
+ - Managed `Uncapped` selects the preferred value without a cap.
148
+ - Inherit/default mode returns no model/effort dispatch args.
108
149
 
109
- The ceiling means slightly different things for the two dispatch roles:
150
+ For reviewer dispatches:
110
151
 
111
- - **Implementer** runs at `min(preferred, ceiling)` — the ceiling is a **cap**. A simple phase may run below it.
112
- - **Reviewer** runs **at** the ceiling — a **target** — so quality gates are deterministic.
152
+ - Capped managed policies target the configured cap for deterministic review
153
+ quality gates.
154
+ - Managed `Uncapped` has no reviewer cap, so OAT uses the base/unpinned reviewer
155
+ fallback and logs provider-default behavior.
156
+ - Inherit/default mode also uses the base/unpinned reviewer fallback.
113
157
 
114
- Both providers honor this distinction (Codex selects the matching variant; Claude passes the matching model).
158
+ Generic sidecars such as `explorer` are outside the implementer/reviewer/fix
159
+ contract. If their payload does not pin a reliable provider control, logs should
160
+ say `provider-default`.
115
161
 
116
- Generic sidecars such as built-in `explorer` are outside this implementer/reviewer/fix contract. They may run at provider default when they are read-only advisory helpers. In that case, dispatch logs should say `Preferred effort: provider-default`, `Selected effort: provider-default`, and `Effort axis: provider-default`; only log a concrete selected effort when the actual sidecar payload pins a reliable provider control.
162
+ ## Dispatch Logs
117
163
 
118
- ## Verify-on-upgrade
119
-
120
- Only a request for a tier **above** the orchestrator's current tier risks a silent plan/entitlement fallback. So the adapter verifies the actually-dispatched model **only** on that upgrade path; capping down or staying lateral needs no check. OAT never logs `enforced` unless the requested control was actually honored.
121
-
122
- ## Dispatch logs
123
-
124
- OAT logs the honest enforcement state per dispatch, for example:
164
+ Examples:
125
165
 
126
166
  ```text
127
- Dispatch ceiling: high (codex, enforced — variant oat-reviewer-high)
128
- Dispatch ceiling: sonnet (claude, enforced — Task model arg)
129
- Dispatch ceiling: balanced (cursor, unsupportedno adapter; informational)
167
+ Dispatch policy: balanced; selected=high; cap=high (codex, enforced — variant oat-phase-implementer-high)
168
+ Dispatch policy: high; selected=xhigh; cap=xhigh (codex, enforced — variant oat-reviewer-xhigh)
169
+ Dispatch policy: uncapped; selected=xhigh; cap=none (codex, enforcedvariant oat-phase-implementer-xhigh)
170
+ Dispatch policy: inherit host defaults; selected=none; cap=none (codex, advisory — base role follows provider default)
171
+ Dispatch policy: frontier; selected=fable; cap=fable (claude, enforced — Task model arg)
130
172
  ```
131
173
 
132
- ## Summary
133
-
134
- You declare intent once (a preset, explicit per-provider values, or nothing). Under Codex it becomes deterministic pinned variants; under Claude it becomes a per-call Task `model` argument; under any other provider it is recorded as advisory and that provider runs normally. The logs tell you honestly whether the ceiling was `enforced`, `advisory`, or `unsupported` — one provider-neutral knob that enforces where it can and degrades gracefully where it can't.
174
+ OAT logs `enforced` only when the provider accepted the requested control.
175
+ Above-orchestrator Claude upgrade requests may require post-dispatch
176
+ verification. Unsupported providers do not block; OAT records the policy as
177
+ advisory/unsupported and dispatch follows provider behavior.
@@ -10,6 +10,8 @@ OAT supports two checkpoint classes:
10
10
  - Workflow phase checkpoints
11
11
  - Plan phase checkpoints
12
12
 
13
+ The [phase review gate](reviews.md#phase-review-gate) (`oat_phase_review_gate`) is a separate, non-pausing mechanism — it does not pause on a passing gate and never modifies the HiLL keys below (`oat_hill_completed`, `oat_plan_hill_phases`).
14
+
13
15
  ## Workflow checkpoints (`state.md`)
14
16
 
15
17
  Frontmatter keys:
@@ -12,8 +12,8 @@ This page covers how `oat-project-implement` actually runs a plan: tier selectio
12
12
  - **When to use:** you have a plan ready and want to understand what happens during `oat-project-implement`.
13
13
  - **Unit of dispatch:** one phase at a time (not one task). A phase implementer executes all tasks in the phase, commits per task, and returns a single summary.
14
14
  - **Two tiers, one lock:** capability detection picks Tier 1 (native subagents) or Tier 2 (inline) at start. The tier is locked for the whole run — no mid-run downgrades.
15
- - **Dispatch ceiling:** implementation resolves an OAT-owned, provider-neutral ceiling before work starts. A ceiling is set as a preset (`balanced`, `maximum`, `cost-conscious`) or per-provider advanced values; runtime dispatch reads only the compiled concrete values. Codex uses effort values (`low`, `medium`, `high`, `xhigh`); Claude uses model tiers (`haiku`, `sonnet`, `opus`).
16
- - **Runtime dispatch:** each phase uses the lowest available model/effort/control that can confidently complete the work, capped by the resolved dispatch ceiling, unless `plan.md` includes an explicit Dispatch Profile override.
15
+ - **Dispatch policy:** implementation resolves an OAT-owned dispatch policy before work starts. Managed policies are `Economy`, `Balanced`, `High`, `Frontier`, and `Uncapped`; `Inherit Host Defaults` explicitly leaves model/effort controls to the host.
16
+ - **Runtime dispatch:** each phase uses the lowest available model/effort/control that can confidently complete the work. Capped managed policies cap preferred selections, managed `Uncapped` uses preferred selections directly, and inherit/default mode uses no OAT-selected control.
17
17
 
18
18
  ## Execution model
19
19
 
@@ -35,11 +35,11 @@ The selected tier is reported to the user and locked for the remainder of the ru
35
35
  → Selected: Tier 1 — Subagents
36
36
  ```
37
37
 
38
- ### Dispatch ceiling preflight
38
+ ### Dispatch policy preflight
39
39
 
40
- Before phase work starts, `oat-project-implement` resolves and prints the dispatch ceiling for the current provider. For the conceptual model and per-provider enforcement (Codex vs Claude vs unsupported), see [Dispatch Ceiling](dispatch-ceiling.md).
40
+ Before phase work starts, `oat-project-implement` resolves and prints the dispatch policy for the current provider. For the conceptual model and per-provider enforcement (Codex vs Claude vs unsupported), see [Dispatch Policy](dispatch-ceiling.md).
41
41
 
42
- The compiled resolver is the source of truth:
42
+ The resolver is the source of truth. The command name remains `dispatch-ceiling` for compatibility:
43
43
 
44
44
  ```bash
45
45
  oat project dispatch-ceiling resolve --provider codex --preflight --json
@@ -47,46 +47,50 @@ oat project dispatch-ceiling resolve --provider codex --preflight --json
47
47
 
48
48
  Resolution order:
49
49
 
50
- 1. `workflow.dispatchCeiling.providers.<provider>` from effective config
51
- 2. `oat_dispatch_ceiling` in project `state.md` frontmatter
52
- 3. Interactive implementation preflight prompt
53
- 4. Non-interactive unresolved state blocks before work starts
50
+ 1. `workflow.dispatchPolicy.mode` / `workflow.dispatchPolicy.policy` from effective config
51
+ 2. Compatibility `workflow.dispatchCeiling.providers.<provider>` from effective config
52
+ 3. `oat_dispatch_policy` in project `state.md` frontmatter
53
+ 4. Legacy `oat_dispatch_ceiling` in project `state.md` frontmatter
54
+ 5. Interactive implementation preflight prompt
55
+ 6. Non-interactive unresolved state blocks before work starts
54
56
 
55
- The ceiling is set via a preset or Advanced per-provider values. Runtime dispatch reads the compiled concrete provider values only — never the preset label. If no ceiling is configured, the interactive preflight prompt offers the preset choices; non-interactive mode blocks.
57
+ Runtime dispatch reads the resolved policy and provider-specific selection only. If no policy is configured, the interactive preflight prompt offers the policy choices; non-interactive mode blocks.
56
58
 
57
- **Preset options (interactive prompt):**
59
+ **Policy options (interactive prompt):**
58
60
 
59
- | Option | Codex | Claude |
60
- | -------------- | ---------------- | ---------------- |
61
- | Balanced | `high` | `sonnet` |
62
- | Maximum | `xhigh` | `opus` |
63
- | Cost-conscious | `medium` | `sonnet` |
64
- | Advanced | per-provider | per-provider |
65
- | No ceiling | provider default | provider default |
61
+ | Option | Mode | Codex | Claude |
62
+ | --------------------- | ------- | -------- | -------- |
63
+ | Economy | managed | `medium` | `sonnet` |
64
+ | Balanced | managed | `high` | `sonnet` |
65
+ | High | managed | `xhigh` | `opus` |
66
+ | Frontier | managed | `xhigh` | `fable` |
67
+ | Uncapped | managed | none | none |
68
+ | Inherit Host Defaults | inherit | none | none |
66
69
 
67
- For Codex, provider default effort is displayed when available but is not treated as the OAT ceiling. Provider default only explains base/unpinned role behavior.
70
+ For Codex, provider default effort is displayed when available but is not treated as managed `Uncapped` or as a cap. Provider defaults apply only to explicit inherit/default behavior or base/unpinned fallback paths.
68
71
 
69
72
  ```text
70
- Dispatch ceiling: high (codex, enforced — variant oat-phase-implementer-high)
71
- Source: project state | Preset: balanced
73
+ Dispatch policy: balanced (codex, managed capped pinned-variant)
74
+ Resolved cap: high
75
+ Source: project state
72
76
  Provider default effort: medium
73
- Note: OAT will use pinned subagent variants up to high. Base/unpinned roles resolve through the provider default.
77
+ Note: OAT will use pinned subagent variants up to high. Base/unpinned roles resolve through the provider default only on fallback paths.
74
78
  ```
75
79
 
76
80
  **Enforcement modes** (from resolver):
77
81
 
78
82
  - `enforced` — the adapter compiled concrete dispatch args and the provider accepted them (Codex: pinned variants; Claude: Task `model` parameter).
79
83
  - `advisory` — the provider is supported but no value resolved, or an upgrade request was not honored by the provider.
80
- - `unsupported` — the provider has no registered adapter; the ceiling is informational only. Dispatch follows provider defaults.
84
+ - `unsupported` — the provider has no registered adapter; the policy is informational only. Dispatch follows provider behavior.
81
85
 
82
- In non-interactive mode, an unresolved ceiling blocks before any implementation work:
86
+ In non-interactive mode, an unresolved policy blocks before any implementation work:
83
87
 
84
88
  ```text
85
- BLOCKED: Codex dispatch ceiling is unresolved in non-interactive mode.
86
- Set workflow.dispatchCeiling.providers.codex in .oat/config.json or oat_dispatch_ceiling in project state.
89
+ BLOCKED: Codex dispatch policy is unresolved in non-interactive mode.
90
+ Set workflow.dispatchPolicy.mode/workflow.dispatchPolicy.policy, workflow.dispatchCeiling.providers.codex, oat_dispatch_policy, or legacy oat_dispatch_ceiling.
87
91
  ```
88
92
 
89
- Dry-run reports unresolved ceiling and planned behavior without writing project state.
93
+ Dry-run reports unresolved policy and planned behavior without writing project state.
90
94
 
91
95
  ### Runtime dispatch selection
92
96
 
@@ -103,14 +107,14 @@ The orchestrator considers, in order:
103
107
  Model and effort are separate axes. Each axis logs one of these states:
104
108
 
105
109
  - `selected:<value>` — the host exposes the axis and the orchestrator chose a value.
106
- - `provider-default` — Codex base/unpinned role follows configured/provider default effort.
110
+ - `provider-default` — Codex base/unpinned role follows configured/provider default effort for explicit inherit/default behavior or fallback paths.
107
111
  - `inherited` — the host exposes the axis and the orchestrator deliberately defers to the parent session.
108
112
  - `not-applicable` — this host/API has no meaningful per-dispatch concept for that axis.
109
113
  - `host-auto` — exceptional; the host uses that axis internally but the orchestrator cannot read or pin it.
110
114
 
111
- In Codex, implementation and fix dispatch classify a preferred effort (`low`, `medium`, `high`, or `xhigh`) and pass it to `oat project dispatch-ceiling resolve --provider codex --role implementer --preferred <effort>`. The resolver selects `min(preferred, resolved_ceiling)` and returns the matching pinned role: `oat-phase-implementer-low`, `oat-phase-implementer-medium`, `oat-phase-implementer-high`, or `oat-phase-implementer-xhigh`. Reviewer dispatch uses the reviewer variant matching the resolved ceiling (`oat-reviewer-low|medium|high|xhigh`) for deterministic quality gates. Base/unpinned Codex roles are provider-default fallbacks; they should be logged as `provider-default`, not as inherited parent-session ceiling.
115
+ In Codex, implementation and fix dispatch classify a preferred effort (`low`, `medium`, `high`, or `xhigh`) and pass it to `oat project dispatch-ceiling resolve --provider codex --role implementer --preferred <effort>`. For capped managed policies, the resolver selects `min(preferred, resolved_cap)` and returns the matching pinned role. For managed `Uncapped`, the resolver selects the preferred pinned role with no cap. For inherit/default mode, it returns no pinned role and OAT uses the base/unpinned role. Reviewer dispatch targets the configured cap only when a capped managed policy exists; managed `Uncapped` and inherit/default use base `oat-reviewer` fallback.
112
116
 
113
- In Claude Code, implementation and fix dispatch classify a preferred model tier (`haiku`, `sonnet`, or `opus`) and pass it to `oat project dispatch-ceiling resolve --provider claude --role implementer --preferred <model> --orchestrator-tier <current-orchestrator-tier>`. The resolver selects `min(preferred, resolved_ceiling)` and returns the `model` argument to pass at dispatch. Reviewer dispatch targets the resolved Claude ceiling directly. The separate effort axis is `not-applicable`.
117
+ In Claude Code, implementation and fix dispatch classify a preferred model tier (`haiku`, `sonnet`, `opus`, or `fable`) and pass it to `oat project dispatch-ceiling resolve --provider claude --role implementer --preferred <model> --orchestrator-tier <current-orchestrator-tier>`. Capped policies select `min(preferred, resolved_cap)`, managed `Uncapped` selects the preferred model, and inherit/default omits `model`. Reviewer dispatch passes a `model` only when the resolver returns one. The separate effort axis is `not-applicable`.
114
118
 
115
119
  Dispatch logs use a consistent structured block so provider behavior is comparable without flattening the model and effort axes:
116
120
 
@@ -125,25 +129,43 @@ Rationale: multi-file integration with mock wiring; sonnet is the lowest suffici
125
129
  OAT Dispatch: Phase p02 implementation
126
130
  Host: Codex
127
131
  Preferred effort: high
128
- Dispatch ceiling: medium
132
+ Dispatch policy: economy
133
+ Resolved cap: medium
129
134
  Selected effort: medium
130
- Ceiling source: repo config
135
+ Policy source: repo config
131
136
  Provider default effort: high
137
+ Selection mode: capped
132
138
  Model axis: inherited
133
139
  Effort axis: selected:medium
134
140
  Dispatch target: oat-phase-implementer-medium
135
- Rationale: shared TypeScript/config substrate; high preferred due to integration risk, capped by configured ceiling.
141
+ Rationale: shared TypeScript/config substrate; high preferred due to integration risk, capped by configured policy.
136
142
 
137
143
  OAT Dispatch: Phase p03 review
138
144
  Host: Codex
139
- Dispatch ceiling: high
140
- Selected effort: high
141
- Ceiling source: project state
145
+ Dispatch policy: high
146
+ Resolved cap: xhigh
147
+ Selected effort: xhigh
148
+ Policy source: project state
142
149
  Provider default effort: medium
150
+ Selection mode: review-target
143
151
  Model axis: inherited
144
- Effort axis: selected:high
145
- Dispatch target: oat-reviewer-high
146
- Rationale: reviewer runs at the configured ceiling for deterministic quality gate behavior.
152
+ Effort axis: selected:xhigh
153
+ Dispatch target: oat-reviewer-xhigh
154
+ Rationale: reviewer runs at the configured policy cap for deterministic quality gate behavior.
155
+
156
+ OAT Dispatch: Phase p03 implementation
157
+ Host: Codex
158
+ Preferred effort: xhigh
159
+ Dispatch policy: uncapped
160
+ Resolved cap: none
161
+ Selected effort: xhigh
162
+ Policy source: project state
163
+ Provider default effort: medium
164
+ Selection mode: uncapped
165
+ Model axis: inherited
166
+ Effort axis: selected:xhigh
167
+ Dispatch target: oat-phase-implementer-xhigh
168
+ Rationale: high-risk phase; managed uncapped policy allows the preferred pinned variant.
147
169
 
148
170
  OAT Dispatch: Phase p04 implementation
149
171
  Host: Other
@@ -155,9 +177,10 @@ Rationale: host does not expose readable or pinnable dispatch controls; rational
155
177
  OAT Dispatch: p02-t10 sidecar exploration
156
178
  Host: Codex
157
179
  Preferred effort: provider-default
158
- Dispatch ceiling: xhigh
180
+ Dispatch policy: high
181
+ Resolved cap: xhigh
159
182
  Selected effort: provider-default
160
- Ceiling source: project state
183
+ Policy source: project state
161
184
  Provider default effort: xhigh
162
185
  Model axis: inherited
163
186
  Effort axis: provider-default
@@ -165,7 +188,7 @@ Dispatch target: explorer
165
188
  Rationale: read-only sidecar exploration; generic explorer payload does not pin an OAT-managed effort variant.
166
189
  ```
167
190
 
168
- Phase and review scope packets include dispatch context when the orchestrator has resolved it: `model_axis`, `effort_axis`, `dispatch_ceiling`, `ceiling_source`, `provider_default_effort`, and `dispatch_rationale`.
191
+ Phase and review scope packets include dispatch context when the orchestrator has resolved it: `model_axis`, `effort_axis`, `dispatch_policy`, `dispatch_ceiling`, `policy_source`, `ceiling_source` as a compatibility alias, `provider_default_effort`, and `dispatch_rationale`.
169
192
 
170
193
  Generic sidecars such as built-in `explorer` are not OAT-managed implementer, reviewer, or fix roles. If a sidecar payload does not pin a reliable effort/model control, log it as provider-default rather than classifying the task complexity as a selected effort. Sidecar results are advisory context; implementation and review/fix gates still follow the OAT-managed dispatch rules above.
171
194
 
@@ -183,11 +206,12 @@ For each phase in the plan (whether sequential or inside a parallel group):
183
206
  2. **Dispatch the selected implementer role** with a Phase Scope block (project path, phase id, artifact paths, commit convention, workflow mode, and dispatch context when known). In Codex, `effort_axis=selected:low|medium|high|xhigh` uses `oat-phase-implementer-low|medium|high|xhigh`. Base `oat-phase-implementer` means provider-default/unpinned fallback.
184
207
  3. **Receive the summary:** `DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED`.
185
208
  - `BLOCKED` stops the run and surfaces the blocker to the user.
186
- 4. **Dispatch the selected reviewer role** with a Review Scope block (phase id, commit range, optional files-changed hint, and dispatch context). The commit range is authoritative; the file list is only orientation metadata. In Codex, pass this as a self-contained packet with `fork_context: false` and use the `oat-reviewer-<ceiling>` variant. In Claude Code, cap any selected model by the Claude ceiling and record `effort_axis=not-applicable`. If the reviewer does not conclude on the first wait, poll once more, then send a concise "return now with current findings" nudge before falling back inline for that phase.
209
+ 4. **Dispatch the selected reviewer role** with a Review Scope block (phase id, commit range, optional files-changed hint, and dispatch context). The commit range is authoritative; the file list is only orientation metadata. In Codex, pass this as a self-contained packet with `fork_context: false`; use an `oat-reviewer-<value>` variant only for capped managed policies, and use base `oat-reviewer` for managed `Uncapped` or inherit/default. In Claude Code, pass a review `model` only when the resolver returns one and always record `effort_axis=not-applicable`. If the reviewer does not conclude on the first wait, poll once more, then send a concise "return now with current findings" nudge before falling back inline for that phase.
187
210
  5. **Parse the verdict:** zero Critical + zero Important findings → `pass`; otherwise `fail`.
188
211
  6. **On fail, run the bounded fix loop** (see below).
189
212
  7. **Update artifacts** (`implementation.md`, `plan.md` review row, `state.md`) and make the mandatory bookkeeping commit.
190
- 8. **HiLL checkpoint** if the phase id is listed in `oat_plan_hill_phases`.
213
+ 8. **Phase review gate** when `oat_phase_review_gate` selects the phase, run the optional non-pausing external gate (`oat gate review`) after the step 7 bookkeeping commit and before the HiLL check. A passing gate continues automatically; a blocking gate is received and fixed, reusing the bounded fix loop's `oat_orchestration_retry_limit`. See [Reviews → Phase review gate](reviews.md#phase-review-gate).
214
+ 9. **HiLL checkpoint** if the phase id is listed in `oat_plan_hill_phases`.
191
215
 
192
216
  ### Bounded fix loop
193
217
 
@@ -206,8 +230,8 @@ Tier is never silently downgraded. If a Tier 1 dispatch has a transient failure,
206
230
 
207
231
  When escalation re-dispatches at a stronger control, the ladder is provider-specific:
208
232
 
209
- - **Codex:** `selected:low -> selected:medium -> selected:high -> selected:xhigh`, capped by the resolved Codex dispatch ceiling.
210
- - **Claude Code:** `selected:haiku -> selected:sonnet -> selected:opus`, capped by the resolved Claude dispatch ceiling (compiled from preset or `workflow.dispatchCeiling.providers.claude`).
233
+ - **Codex:** `selected:low -> selected:medium -> selected:high -> selected:xhigh`, capped by the resolved managed cap when one exists. Managed `Uncapped` can select the preferred value; inherit/default mode has no OAT escalation control.
234
+ - **Claude Code:** `selected:haiku -> selected:sonnet -> selected:opus -> selected:fable`, capped by the resolved managed cap when one exists. Managed `Uncapped` can select the preferred model; inherit/default mode has no OAT escalation control.
211
235
 
212
236
  Escalation re-dispatches still count against the bounded retry budget; escalation changes the dispatch control, it does not grant extra retry attempts.
213
237
 
@@ -14,7 +14,7 @@ Projects are where the workflow layer becomes concrete: lifecycle phases, `state
14
14
  - [Lifecycle](lifecycle.md) - End-to-end flow from discovery through completion.
15
15
  - [Design Modes](design-modes.md) - How full design balances collaborative, selective collaborative, and draft-and-review interaction.
16
16
  - [HiLL Checkpoints](hill-checkpoints.md) - Human-in-the-Loop Lifecycle configuration and approval behavior.
17
- - [Dispatch Ceiling](dispatch-ceiling.md) - Provider-neutral ceiling model and provider-specific enforcement.
17
+ - [Dispatch Policy](dispatch-ceiling.md) - Managed capped tiers, managed Uncapped, Inherit Host Defaults, and provider-specific enforcement.
18
18
  - [Project Artifacts](artifacts.md) - What lives in `state.md`, `discovery.md`, `plan.md`, `implementation.md`, and related files.
19
19
  - [Implementation Execution](implementation-execution.md) - Phase dispatch, runtime selection, review/fix loop, and dry-run behavior.
20
20
  - [Project Splitting](splitting.md) - How broad discoveries or brainstorms become coordination parents and child projects.
@@ -47,7 +47,7 @@ This sub-section is the deep technical surface for how tracked OAT projects exec
47
47
  - [Lifecycle](lifecycle.md) - End-to-end flow from discovery through completion.
48
48
  - [Design Modes](design-modes.md) - How full design balances collaborative, selective collaborative, and draft-and-review interaction.
49
49
  - [HiLL Checkpoints](hill-checkpoints.md) - Human-in-the-Loop Lifecycle configuration and approval behavior.
50
- - [Dispatch Ceiling](dispatch-ceiling.md) - Provider-neutral ceiling model: presets, the compile/resolve flow, and how enforcement differs for Codex, Claude, and unsupported providers.
50
+ - [Dispatch Policy](dispatch-ceiling.md) - Managed capped tiers, managed Uncapped, Inherit Host Defaults, legacy dispatch-ceiling compatibility, and provider-specific enforcement.
51
51
  - [Artifacts](artifacts.md) - What lives in `state.md`, `discovery.md`, `plan.md`, `implementation.md`, and related files.
52
52
  - [Project Splitting](splitting.md) - How broad discoveries or brainstorms become coordination parents and child projects.
53
53
  - [State Machine](state-machine.md) - Lifecycle and review status transitions across a project.
@@ -136,7 +136,17 @@ flowchart LR
136
136
 
137
137
  During the Design step, `oat-project-design` asks how to work through the document unless a mode was selected by argument, environment, or `workflow.designMode`. The three full-design choices are collaborative, selective collaborative, and draft-and-review.
138
138
 
139
- Before a plan is marked ready for implementation, planning resolves the current provider's dispatch ceiling from `workflow.dispatchCeiling.providers.<provider>` (compiled from a preset or set directly) or project `state.md` frontmatter. If no ceiling is configured and the session is interactive, planning asks once and stores the answer as `oat_dispatch_ceiling`; non-interactive planning leaves it unresolved so implementation preflight can fail before work starts with setup instructions.
139
+ Before a plan is marked ready for implementation, planning resolves the current
140
+ provider's dispatch policy from `workflow.dispatchPolicy.mode` and
141
+ `workflow.dispatchPolicy.policy`, or from project `state.md` frontmatter. The
142
+ legacy `workflow.dispatchCeiling.providers.<provider>` config and
143
+ `oat_dispatch_ceiling` frontmatter remain compatibility inputs for capped
144
+ managed policies. If no policy is configured and the session is interactive,
145
+ planning asks once and stores the answer as `oat_dispatch_policy`;
146
+ non-interactive planning leaves it unresolved so implementation preflight can
147
+ fail before work starts with setup instructions. `Uncapped` is explicit managed
148
+ selection with no maximum cap; `Inherit Host Defaults` is separate and means OAT
149
+ does not select model or effort controls.
140
150
 
141
151
  ### Quick lane
142
152
 
@@ -152,7 +162,12 @@ flowchart LR
152
162
 
153
163
  Quick lane lightweight design intentionally keeps a smaller collaborative/draft choice. Selective collaborative becomes available only after promotion into the full spec-driven design lane.
154
164
 
155
- Quick-start follows the same dispatch ceiling rule at the plan boundary: capture it when interactive, persist it to project state, and avoid any mid-implementation ceiling prompt.
165
+ Quick-start follows the same dispatch policy rule at the plan boundary: capture
166
+ the policy when interactive, persist `oat_dispatch_policy` to project state, and
167
+ avoid any mid-implementation policy prompt. Legacy dispatch-ceiling state is
168
+ still read as compatibility capped-policy input, but new quick-start selections
169
+ should use the dispatch-policy names, including explicit `Uncapped` and
170
+ `Inherit Host Defaults`.
156
171
 
157
172
  ### Import lane
158
173
 
@@ -107,6 +107,23 @@ Auto-triggered reviews use `oat_review_invocation: auto` in the review artifact
107
107
 
108
108
  This feature is opt-in and disabled by default. When disabled, the manual `oat-project-review-provide` workflow applies.
109
109
 
110
+ ## Phase review gate
111
+
112
+ The phase review gate is an optional, **non-pausing** external review gate that runs after a phase's standard per-phase reviewer passes and the phase bookkeeping is committed. Where the Tier 1 reviewer is an in-session self-review, the gate calls `oat gate review` against the configured cross-provider target, adding an independent perspective before implementation moves to the next phase. It is enabled per-project through `plan.md` frontmatter (`oat_phase_review_gate`; see [Project Artifacts](artifacts.md#oat_phase_review_gate) for the field shape and validation).
113
+
114
+ It is independent of [HiLL checkpoints](hill-checkpoints.md): a passing gate does not pause, and the gate never touches `oat_hill_completed`, `oat_plan_hill_phases`, or `oat_auto_review_at_hill_checkpoints`.
115
+
116
+ Gate-produced review artifacts use `oat_review_invocation: gate` in frontmatter (the third invocation marker alongside `manual` and `auto`). The gate verdict — controlled by `exit_nonzero_on` (default `important`) — decides whether the **phase stops**; it does not decide whether sub-threshold findings are ignored. Either way the produced artifact is consumed by `oat-project-review-receive`, autonomously and without user prompts, so findings never evaporate:
117
+
118
+ - **Passing gate** (no findings at or above the threshold): receive runs a non-pausing **judgment sweep**. It makes a per-finding decision for each Medium/Minor — defer to final review (the default, recorded so [final review](#phase-and-final-review) resurfaces it), address now (only for small, contained, low-risk fixes, which do **not** re-trigger the standard reviewer or re-gate the phase), or reject with rationale — then archives the artifact. Address-now is an exception, not the norm; if such a fix reveals a Critical/Important concern it escalates to the blocking path.
119
+ - **Blocking gate** (one or more findings at or above the threshold): receive converts findings to fix tasks and implementation re-runs the standard reviewer and the gate for the phase. These block → fix → re-gate rounds are bounded by `oat_orchestration_retry_limit` (default `2`); exhausting the bound stops a sequential run or excludes the phase in a parallel group, matching the standard fix loop's terminal handling.
120
+
121
+ Gate-originated artifacts (`oat_review_invocation: gate`) are excluded from the same-scope review-cycle cap in `oat-project-review-receive`. The cap measures failed fix cycles of the standard review loop, so counting gate artifacts would trip it on artifact volume rather than real fix rounds.
122
+
123
+ When a phase is re-gated multiple times, each round produces a distinct review artifact — filenames and `oat_generated_at` are seconds-precision, so rounds never collide and `oat review latest` resolves the newest. An orchestrator should know a gate finished from the `oat --json gate review` result envelope on process exit (`status`, `runId`, `generatedAt`), not by watching the `reviews/` directory or the provider's log; see [Gate completion signal](../../cli-utilities/workflow-gates.md#gate-completion-signal).
124
+
125
+ This feature is opt-in and disabled by default (missing or `enabled: false`). For a parallel phase group, selected gates run after fan-in and bookkeeping, one per merged phase in plan order.
126
+
110
127
  ## Auto artifact-review loops
111
128
 
112
129
  Generated planning and analysis artifacts have a separate review loop from code/phase reviews.
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.1.41",
3
- "docs-config": "0.1.41",
4
- "docs-theme": "0.1.41",
5
- "docs-transforms": "0.1.41"
2
+ "cli": "0.1.43",
3
+ "docs-config": "0.1.43",
4
+ "docs-theme": "0.1.43",
5
+ "docs-transforms": "0.1.43"
6
6
  }