@open-agent-toolkit/cli 0.1.42 → 0.1.45

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 (60) hide show
  1. package/assets/agents/oat-phase-implementer.md +11 -7
  2. package/assets/agents/oat-reviewer.md +6 -4
  3. package/assets/config/dispatch-matrix-recommendation.json +23 -0
  4. package/assets/docs/cli-utilities/configuration.md +95 -40
  5. package/assets/docs/cli-utilities/workflow-gates.md +79 -16
  6. package/assets/docs/contributing/code.md +10 -4
  7. package/assets/docs/contributing/hooks-and-safety.md +23 -0
  8. package/assets/docs/reference/oat-directory-structure.md +26 -24
  9. package/assets/docs/workflows/projects/dispatch-ceiling.md +193 -80
  10. package/assets/docs/workflows/projects/implementation-execution.md +68 -45
  11. package/assets/docs/workflows/projects/index.md +2 -2
  12. package/assets/docs/workflows/projects/lifecycle.md +17 -2
  13. package/assets/public-package-versions.json +4 -4
  14. package/assets/skills/oat-project-implement/SKILL.md +232 -100
  15. package/assets/skills/oat-project-plan/SKILL.md +80 -30
  16. package/assets/skills/oat-project-plan-writing/SKILL.md +10 -10
  17. package/assets/skills/oat-project-quick-start/SKILL.md +80 -30
  18. package/assets/templates/plan.md +4 -4
  19. package/assets/templates/state.md +12 -3
  20. package/dist/commands/config/index.d.ts +6 -0
  21. package/dist/commands/config/index.d.ts.map +1 -1
  22. package/dist/commands/config/index.js +432 -11
  23. package/dist/commands/doctor/index.d.ts +6 -1
  24. package/dist/commands/doctor/index.d.ts.map +1 -1
  25. package/dist/commands/doctor/index.js +138 -4
  26. package/dist/commands/gate/index.d.ts +39 -2
  27. package/dist/commands/gate/index.d.ts.map +1 -1
  28. package/dist/commands/gate/index.js +343 -30
  29. package/dist/commands/internal/cursor-current-target.d.ts +37 -0
  30. package/dist/commands/internal/cursor-current-target.d.ts.map +1 -0
  31. package/dist/commands/internal/cursor-current-target.js +228 -0
  32. package/dist/commands/internal/index.d.ts.map +1 -1
  33. package/dist/commands/internal/index.js +2 -0
  34. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  35. package/dist/commands/project/dispatch-ceiling/index.js +646 -56
  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 +25 -6
  40. package/dist/config/oat-config.d.ts.map +1 -1
  41. package/dist/config/oat-config.js +123 -11
  42. package/dist/config/resolve.d.ts.map +1 -1
  43. package/dist/config/resolve.js +16 -0
  44. package/dist/manifest/manifest.types.d.ts +12 -12
  45. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  46. package/dist/providers/ceiling/registry.js +22 -1
  47. package/dist/providers/codex/codec/sync-extension.js +1 -1
  48. package/dist/providers/identity/availability.d.ts +22 -0
  49. package/dist/providers/identity/availability.d.ts.map +1 -0
  50. package/dist/providers/identity/availability.js +119 -0
  51. package/dist/providers/identity/family.d.ts +13 -0
  52. package/dist/providers/identity/family.d.ts.map +1 -0
  53. package/dist/providers/identity/family.js +32 -0
  54. package/dist/providers/identity/provenance.d.ts +21 -0
  55. package/dist/providers/identity/provenance.d.ts.map +1 -0
  56. package/dist/providers/identity/provenance.js +65 -0
  57. package/dist/providers/identity/stamp.d.ts +35 -0
  58. package/dist/providers/identity/stamp.d.ts.map +1 -0
  59. package/dist/providers/identity/stamp.js +171 -0
  60. package/package.json +2 -2
@@ -1,134 +1,247 @@
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 tiers, dispatch matrix cells, ordered routes, producer provenance, legacy 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
+ Multi-family providers such as Cursor use the same abstract policy names, but
25
+ their concrete model values come from a dispatch matrix under
26
+ `workflow.dispatchCeiling.providers.*`. A matrix cell can be a single value, a
27
+ per-tier value, or an ordered route for escalation.
18
28
 
19
- Set it via `oat config set` (repo / user / local) or answer the planning/implementation preflight prompt. Three shapes:
29
+ ## Policy Choices
20
30
 
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 |
31
+ | Policy | Mode | Codex target | Claude target | Meaning |
32
+ | ----------------------- | ------- | ------------ | ------------- | -------------------------------------------- |
33
+ | `Economy` | managed | `medium` | `sonnet` | Lower-cost managed cap |
34
+ | `Balanced` | managed | `high` | `sonnet` | Default managed cap |
35
+ | `High` | managed | `xhigh` | `opus` | High-capability managed cap |
36
+ | `Frontier` | managed | `xhigh` | `fable` | Top managed tier currently exposed by OAT |
37
+ | `Uncapped` | managed | none | none | OAT selects preferred controls without a cap |
38
+ | `Inherit Host Defaults` | inherit | none | none | OAT does not select model/effort controls |
26
39
 
27
- The fixed preset table:
40
+ `Uncapped` is explicit managed state. It is not represented by omitting policy
41
+ state. Existing projects with absent legacy ceiling state remain unresolved or
42
+ legacy-compatible; they do not silently become managed `Uncapped`.
28
43
 
29
- | Preset | Codex | Claude |
30
- | -------------- | -------- | -------- |
31
- | Balanced | `high` | `sonnet` |
32
- | Maximum | `xhigh` | `opus` |
33
- | Cost-conscious | `medium` | `sonnet` |
44
+ ## Config Shapes
34
45
 
35
- `cost-conscious` deliberately keeps Claude at `sonnet` (no `haiku` reviewers by default) so review quality stays trustworthy.
46
+ Preferred managed policy config:
36
47
 
37
- Config keys:
48
+ ```bash
49
+ oat config set workflow.dispatchPolicy.policy balanced --shared
50
+ oat config set workflow.dispatchPolicy.policy frontier --shared
51
+ oat config set workflow.dispatchPolicy.policy uncapped --shared
52
+ ```
38
53
 
39
- - `workflow.dispatchCeiling.preset`
40
- - `workflow.dispatchCeiling.providers.codex` (`low` \| `medium` \| `high` \| `xhigh`)
41
- - `workflow.dispatchCeiling.providers.claude` (`haiku` \| `sonnet` \| `opus`)
54
+ `workflow.dispatchPolicy.policy` writes `workflow.dispatchPolicy.mode=managed`.
55
+ To request host defaults:
42
56
 
43
57
  ```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 }
58
+ oat config set workflow.dispatchPolicy.mode inherit --shared
59
+ ```
47
60
 
48
- # Or set providers directly (advanced — no preset key stored):
49
- oat config set workflow.dispatchCeiling.providers.codex high --shared
61
+ Project state uses the same shape:
62
+
63
+ ```yaml
64
+ oat_dispatch_policy:
65
+ mode: managed
66
+ policy: balanced
67
+ providers:
68
+ codex: high
69
+ claude: sonnet
70
+ source: project-state
50
71
  ```
51
72
 
52
- Project state can persist the compiled answer as `oat_dispatch_ceiling` (`preset?` + `providers` + `source`) so a planning/preflight choice carries into implementation.
73
+ For `Uncapped`, omit provider caps:
74
+
75
+ ```yaml
76
+ oat_dispatch_policy:
77
+ mode: managed
78
+ policy: uncapped
79
+ source: project-state
80
+ ```
81
+
82
+ For host defaults:
83
+
84
+ ```yaml
85
+ oat_dispatch_policy:
86
+ mode: inherit
87
+ source: project-state
88
+ ```
89
+
90
+ Legacy compatibility keys remain readable:
91
+
92
+ - `workflow.dispatchCeiling.preset`
93
+ - `workflow.dispatchCeiling.providers.<provider>`
94
+ - `workflow.dispatchCeiling.providers.<provider>.<tier>`
95
+ - `oat_dispatch_ceiling`
53
96
 
54
- > The earlier flat `workflow.dispatchCeiling.codex` / `.claude` keys were removed. This was a clean break with no migration — set the new keys above.
97
+ Legacy preset names map into the managed ladder: `cost-conscious` maps to
98
+ `Economy`, `balanced` maps to `Balanced`, and `maximum` maps to `High`.
55
99
 
56
- ## How it resolves at dispatch
100
+ ## Dispatch Matrix
101
+
102
+ The dispatch matrix maps the abstract policy rung (`economy`, `balanced`,
103
+ `high`, `frontier`) to concrete provider controls. Existing bare Codex and
104
+ Claude values remain valid, and multi-family providers can use tier cells:
105
+
106
+ ```bash
107
+ oat config adopt dispatch-matrix --shared
108
+ oat config set workflow.dispatchCeiling.providers.cursor.balanced composer-2.5 --shared
109
+ oat config set workflow.dispatchCeiling.providers.cursor.high gpt-5.5-xhigh --shared
110
+ ```
111
+
112
+ For ordered escalation, write a route in config JSON. The resolver selects the
113
+ floor entry at escalation level `0` and advances by route entry when the
114
+ implementation/fix loop escalates:
115
+
116
+ ```json
117
+ {
118
+ "workflow": {
119
+ "dispatchCeiling": {
120
+ "providers": {
121
+ "cursor": {
122
+ "high": [
123
+ "composer-2.5",
124
+ { "harness": "cursor", "model": "gpt-5.5-xhigh" }
125
+ ],
126
+ "frontier": [
127
+ { "harness": "cursor", "model": "gpt-5.5-xhigh" },
128
+ { "harness": "cursor", "model": "fable-5" }
129
+ ]
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ Project `state.md` may carry only sparse project-specific matrix overrides
138
+ under `oat_dispatch_policy.matrix`. The full reusable matrix belongs in user,
139
+ shared, or local config so switching harnesses mid-project re-resolves the same
140
+ abstract policy through the active provider column.
141
+
142
+ ## How Resolution Works
57
143
 
58
144
  Before dispatching a subagent, the orchestrator calls:
59
145
 
60
146
  ```bash
61
- oat project dispatch-ceiling resolve --provider <provider> --role <implementer|reviewer> --preflight --json
147
+ oat project dispatch-ceiling resolve --provider <provider> --role <implementer|reviewer> --json
62
148
  ```
63
149
 
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:
150
+ For implementer or fix dispatch, pass the preferred runtime control:
66
151
 
67
152
  ```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
153
+ oat project dispatch-ceiling resolve --provider codex --role implementer --preferred high --json
154
+ oat project dispatch-ceiling resolve --provider claude --role implementer --preferred opus --json
155
+ oat project dispatch-ceiling resolve --provider cursor --role implementer --preferred high --escalation-level 0 --json
70
156
  ```
71
157
 
72
- The resolver:
158
+ The resolver returns the resolved policy, optional cap, source, provider default
159
+ effort where applicable, and provider-specific `dispatchArgs`.
160
+
161
+ Selection modes:
73
162
 
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 }`.
163
+ - `capped` - implementer/fix dispatch selects `min(preferred, cap)`.
164
+ - `uncapped` - implementer/fix dispatch selects the preferred value.
165
+ - `matrix-pinned` - a matrix cell supplied the selected provider value.
166
+ - `prompt-persisted` - an interactive prompt filled a missing cell and persisted it.
167
+ - `escalation-target` - an ordered route entry supplied the selected target.
168
+ - `review-target` - reviewer dispatch targets a configured cap when one exists.
169
+ - `no-review-target` - managed uncapped reviewer dispatch has no configured
170
+ target and falls back to the base/unpinned reviewer.
171
+ - `inherit-default` - OAT returns no dispatch args and leaves controls to the host.
172
+ - `unresolved` - non-interactive implementation blocks before work starts.
78
173
 
79
- `mode` is the honest enforcement status, computed right there and never persisted:
174
+ ## Provider Behavior
80
175
 
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.
176
+ | | Codex | Claude Code | Cursor / model-arg providers | Unsupported provider |
177
+ | ----------------- | ------------------------------------------- | --------------------------------------- | ---------------------------- | -------------------- |
178
+ | Managed mechanism | Pinned role variants | Task `model` argument | `--model` argument | None |
179
+ | Axis | effort (`low < medium < high < xhigh`) | model (`haiku < sonnet < opus < fable`) | opaque model slug | None |
180
+ | Capped policy | selected pinned variant up to cap | selected Task model up to cap | selected matrix cell | advisory/unsupported |
181
+ | Uncapped | preferred pinned variant, no cap | preferred Task model, no cap | preferred matrix cell | advisory/unsupported |
182
+ | Inherit/default | base/unpinned role follows provider default | omit `model` | omit `--model` | normal behavior |
84
183
 
85
- ## Per-provider behavior
184
+ Codex uses pinned variants because per-call effort controls were unreliable in
185
+ dogfooding. For managed `Uncapped`, OAT still selects the preferred pinned
186
+ variant; the dispatching host should verify whether upward effort selection is
187
+ actually honored in the current session.
86
188
 
87
- The same ceiling intent produces different — but honest — behavior per provider, because each adapter declares its own mechanism.
189
+ Claude Code uses the per-call Task `model` argument. It has no OAT-managed
190
+ per-dispatch effort axis, so dispatch logs use `effort_axis=not-applicable`.
191
+ `Frontier` maps to Claude `fable`.
88
192
 
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 |
193
+ Cursor and other model-arg providers use matrix values as opaque slugs. OAT
194
+ validates availability with provider oracles when possible, but tier semantics
195
+ come from the configured matrix, not from a built-in model catalog.
98
196
 
99
- ### Why the mechanisms differ
197
+ ## Producer Provenance
100
198
 
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.
199
+ Dispatch notes use a parseable single-line stamp so later gates can identify
200
+ the producer family:
104
201
 
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.
202
+ ```text
203
+ Dispatch: scope=p06 action=implementation role=implementer producer=gpt-5.5-xhigh provenance=declared model_axis=selected:gpt-5.5-xhigh effort_axis=not-applicable dispatch_policy=high dispatch_ceiling=xhigh target=cursor
204
+ ```
106
205
 
107
- ## Cap vs target: implementer vs reviewer
206
+ `producer` is the resolved model slug when OAT knows it, otherwise `unknown`.
207
+ `provenance` is one of `declared`, `observed`, `inferred`, or `unknown`.
208
+ Concrete same-harness model arguments can be declared. Codex pinned effort
209
+ variants declare effort, not concrete producer identity, unless an observed or
210
+ inferred model is available.
108
211
 
109
- The ceiling means slightly different things for the two dispatch roles:
212
+ ## Implementer, Fix, and Reviewer Behavior
110
213
 
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.
214
+ For implementer and fix dispatches:
113
215
 
114
- Both providers honor this distinction (Codex selects the matching variant; Claude passes the matching model).
216
+ - Capped managed policies select `min(preferred, cap)`.
217
+ - Managed `Uncapped` selects the preferred value without a cap.
218
+ - Inherit/default mode returns no model/effort dispatch args.
115
219
 
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.
220
+ For reviewer dispatches:
117
221
 
118
- ## Verify-on-upgrade
222
+ - Capped managed policies target the configured cap for deterministic review
223
+ quality gates.
224
+ - Managed `Uncapped` has no reviewer cap, so OAT uses the base/unpinned reviewer
225
+ fallback and logs provider-default behavior.
226
+ - Inherit/default mode also uses the base/unpinned reviewer fallback.
119
227
 
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.
228
+ Generic sidecars such as `explorer` are outside the implementer/reviewer/fix
229
+ contract. If their payload does not pin a reliable provider control, logs should
230
+ say `provider-default`.
121
231
 
122
- ## Dispatch logs
232
+ ## Dispatch Logs
123
233
 
124
- OAT logs the honest enforcement state per dispatch, for example:
234
+ Examples:
125
235
 
126
236
  ```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)
237
+ Dispatch policy: balanced; selected=high; cap=high (codex, enforced — variant oat-phase-implementer-high)
238
+ Dispatch policy: high; selected=xhigh; cap=xhigh (codex, enforced — variant oat-reviewer-xhigh)
239
+ Dispatch policy: uncapped; selected=xhigh; cap=none (codex, enforcedvariant oat-phase-implementer-xhigh)
240
+ Dispatch policy: inherit host defaults; selected=none; cap=none (codex, advisory — base role follows provider default)
241
+ Dispatch policy: frontier; selected=fable; cap=fable (claude, enforced — Task model arg)
130
242
  ```
131
243
 
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.
244
+ OAT logs `enforced` only when the provider accepted the requested control.
245
+ Above-orchestrator Claude upgrade requests may require post-dispatch
246
+ verification. Unsupported providers do not block; OAT records the policy as
247
+ advisory/unsupported and dispatch follows provider behavior.
@@ -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,7 +206,7 @@ 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.
@@ -207,8 +230,8 @@ Tier is never silently downgraded. If a Tier 1 dispatch has a transient failure,
207
230
 
208
231
  When escalation re-dispatches at a stronger control, the ladder is provider-specific:
209
232
 
210
- - **Codex:** `selected:low -> selected:medium -> selected:high -> selected:xhigh`, capped by the resolved Codex dispatch ceiling.
211
- - **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.
212
235
 
213
236
  Escalation re-dispatches still count against the bounded retry budget; escalation changes the dispatch control, it does not grant extra retry attempts.
214
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