@open-agent-toolkit/cli 0.1.11 → 0.1.13

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 (31) hide show
  1. package/assets/docs/cli-utilities/configuration.md +66 -11
  2. package/assets/docs/reference/oat-directory-structure.md +22 -21
  3. package/assets/docs/workflows/projects/dispatch-ceiling.md +123 -0
  4. package/assets/docs/workflows/projects/implementation-execution.md +27 -9
  5. package/assets/docs/workflows/projects/index.md +1 -0
  6. package/assets/docs/workflows/projects/lifecycle.md +1 -1
  7. package/assets/public-package-versions.json +4 -4
  8. package/assets/skills/oat-project-implement/SKILL.md +125 -31
  9. package/assets/skills/oat-project-plan/SKILL.md +28 -28
  10. package/assets/skills/oat-project-quick-start/SKILL.md +28 -27
  11. package/dist/commands/config/index.d.ts.map +1 -1
  12. package/dist/commands/config/index.js +53 -13
  13. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  14. package/dist/commands/project/dispatch-ceiling/index.js +126 -28
  15. package/dist/config/dispatch-ceiling-preset.d.ts +54 -0
  16. package/dist/config/dispatch-ceiling-preset.d.ts.map +1 -0
  17. package/dist/config/dispatch-ceiling-preset.js +32 -0
  18. package/dist/config/json.d.ts +2 -0
  19. package/dist/config/json.d.ts.map +1 -0
  20. package/dist/config/json.js +29 -0
  21. package/dist/config/oat-config.d.ts +9 -2
  22. package/dist/config/oat-config.d.ts.map +1 -1
  23. package/dist/config/oat-config.js +26 -18
  24. package/dist/config/resolve.d.ts.map +1 -1
  25. package/dist/config/resolve.js +5 -2
  26. package/dist/config/sync-config.d.ts.map +1 -1
  27. package/dist/config/sync-config.js +2 -1
  28. package/dist/providers/ceiling/registry.d.ts +53 -0
  29. package/dist/providers/ceiling/registry.d.ts.map +1 -0
  30. package/dist/providers/ceiling/registry.js +77 -0
  31. package/package.json +3 -2
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-implement
3
- version: 2.0.19
3
+ version: 2.0.20
4
4
  description: Use when plan.md is ready for execution. Dispatches phase-level subagents with bounded fix loops; supports plan-declared parallel phase groups with worktree-isolated execution and ordered fan-in.
5
5
  argument-hint: '[--retry-limit <N>] [--dry-run]'
6
6
  disable-model-invocation: true
@@ -164,55 +164,101 @@ Forbidden: Selected: Tier 2 — Inline because the user did not separately menti
164
164
 
165
165
  ### Dispatch Ceiling Preflight
166
166
 
167
- Before any phase work, resolve and print the OAT dispatch ceiling for the
168
- current provider. This is a preflight gate, not a mid-run question.
167
+ Before any phase work, resolve and print the OAT dispatch ceiling. This is a
168
+ preflight gate, not a mid-run question.
169
169
 
170
- Use the CLI helper as the source of truth for resolution:
170
+ Use the CLI resolver as the source of truth:
171
171
 
172
172
  ```bash
173
- oat project dispatch-ceiling resolve --provider <codex|claude> --preflight --json
173
+ oat project dispatch-ceiling resolve --provider <active-provider> --preflight --json
174
174
  ```
175
175
 
176
176
  If `oat` is not in PATH, use:
177
177
 
178
178
  ```bash
179
- pnpm run cli -- project dispatch-ceiling resolve --provider <codex|claude> --preflight --json
179
+ pnpm run cli -- project dispatch-ceiling resolve --provider <active-provider> --preflight --json
180
180
  ```
181
181
 
182
182
  Resolution order:
183
183
 
184
- 1. Effective config key `workflow.dispatchCeiling.<provider>` via the resolver CLI
184
+ 1. Config keys `workflow.dispatchCeiling.providers.<provider>` (local > shared > user)
185
185
  2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
186
- 3. Interactive implementation preflight prompt
186
+ 3. Interactive implementation preflight prompt (below)
187
187
  4. Non-interactive unresolved: block before work starts
188
188
 
189
- Provider values:
190
-
191
- - Codex: `low`, `medium`, `high`, `xhigh`
192
- - Claude: `haiku`, `sonnet`, `opus`
189
+ **JSON response shape** (from `--json`):
190
+
191
+ ```json
192
+ {
193
+ "status": "resolved",
194
+ "provider": "codex",
195
+ "value": "high",
196
+ "source": "project-state",
197
+ "preset": "balanced",
198
+ "unresolved": false,
199
+ "providerDefaultEffort": "medium",
200
+ "providers": {
201
+ "codex": {
202
+ "value": "high",
203
+ "mode": "enforced",
204
+ "mechanism": "pinned-variant",
205
+ "dispatchArgs": { "variant": "oat-phase-implementer-high" },
206
+ "verifyOnDispatch": false
207
+ }
208
+ }
209
+ }
210
+ ```
193
211
 
194
- For Codex, also resolve the provider default effort when possible by reading
195
- Codex configuration (for example `.codex/config.toml`). If it cannot be found,
196
- display `unknown`. Do not treat provider default as the OAT ceiling.
197
- The resolver prints this as `providerDefaultEffort` in JSON and includes it in
198
- human-readable output.
212
+ Read `providers.<active-provider>` for the concrete dispatch controls. The
213
+ `dispatchArgs` field carries the provider-specific argument to pass through
214
+ (Codex: `variant` name; Claude: `model` string). Never re-derive these from the
215
+ preset label the resolver is the single compilation/join point.
199
216
 
200
- Print this before phase work:
217
+ Print before phase work:
201
218
 
202
219
  ```text
203
- Codex dispatch ceiling: high
204
- Source: project state
205
- Codex provider default effort: medium
220
+ Dispatch ceiling: high (codex, enforced — pinned-variant)
221
+ Source: project state | Preset: balanced
222
+ Provider default effort: medium
206
223
  Note: OAT will use pinned subagent variants up to high. Base/unpinned roles resolve through the provider default.
207
224
  ```
208
225
 
209
- If no ceiling resolves and the session is interactive, ask before starting
210
- implementation and persist the answer in project `state.md` frontmatter:
226
+ If no ceiling resolves and the session is interactive, present the preset
227
+ prompt once before starting work:
228
+
229
+ ```text
230
+ No dispatch ceiling is configured for this project.
231
+
232
+ Set the dispatch ceiling — the maximum subagent tier OAT may use.
233
+
234
+ 1. Balanced (recommended) — Codex: high · Claude: sonnet
235
+ 2. Maximum — Codex: xhigh · Claude: opus (reviews always run at this tier)
236
+ 3. Cost-conscious — Codex: medium · Claude: sonnet
237
+ 4. Advanced — set per provider
238
+ 5. No ceiling
239
+
240
+ OAT applies this where the provider exposes a reliable mechanism (Codex: pinned
241
+ variants; Claude: Task model parameter). Other providers may treat it as advisory.
242
+ ```
243
+
244
+ **Preset selection** persists `preset` + compiled per-provider values. On
245
+ selection, print the exact compiled result (e.g., "Ceiling set: balanced →
246
+ Codex: high · Claude: sonnet") before proceeding.
247
+
248
+ **Advanced (option 4)** prompts for each provider's value individually, then
249
+ persists `providers` + `source` only — no `preset` key.
250
+
251
+ **No ceiling (option 5)** leaves `oat_dispatch_ceiling` unset; implementer
252
+ subagents run at provider defaults.
253
+
254
+ Persist in project `state.md` frontmatter using the normalized shape:
211
255
 
212
256
  ```yaml
213
257
  oat_dispatch_ceiling:
214
- provider: codex
215
- value: high
258
+ preset: balanced # omit when Advanced was chosen
259
+ providers:
260
+ codex: high
261
+ claude: sonnet
216
262
  source: project-state
217
263
  ```
218
264
 
@@ -221,12 +267,12 @@ exists, rerun the resolver with non-interactive behavior and stop before work
221
267
  starts if it blocks:
222
268
 
223
269
  ```bash
224
- oat project dispatch-ceiling resolve --provider <codex|claude> --preflight --non-interactive
270
+ oat project dispatch-ceiling resolve --provider <active-provider> --preflight --non-interactive
225
271
  ```
226
272
 
227
273
  ```text
228
274
  BLOCKED: Codex dispatch ceiling is unresolved in non-interactive mode.
229
- Set workflow.dispatchCeiling.codex in .oat/config.json or oat_dispatch_ceiling in project state.
275
+ Set workflow.dispatchCeiling.providers.codex in .oat/config.json or oat_dispatch_ceiling in project state.
230
276
  ```
231
277
 
232
278
  Dry-run mode must report the unresolved ceiling and planned behavior without
@@ -263,16 +309,18 @@ Codex rules:
263
309
  - `medium`: normal multi-file implementation and moderate integration risk
264
310
  - `high`: broad architecture, security/auth/redaction boundaries, subtle state behavior, or repeated substantive review failures
265
311
  - `xhigh`: highest-risk work that requires the configured ceiling to allow xhigh
266
- 3. Selected effort is `min(preferred, resolved_ceiling)`.
267
- 4. Dispatch implementer/fix work through `oat-phase-implementer-<selected>`.
268
- 5. Dispatch review work through `oat-reviewer-<resolved_ceiling>` for deterministic quality gate behavior.
312
+ 3. Selected effort is `min(preferred, resolved_ceiling)` for implementer/fix work.
313
+ 4. For implementer/fix dispatch: call `oat project dispatch-ceiling resolve --provider codex --role implementer`; read `providers.codex.dispatchArgs.variant` for the role name (e.g., `oat-phase-implementer-high`). Pass that variant name directly — do not re-derive it from the ceiling value.
314
+ 5. For review dispatch: call `oat project dispatch-ceiling resolve --provider codex --role reviewer`; read `providers.codex.dispatchArgs.variant` for the reviewer role name (e.g., `oat-reviewer-high`). Reviewer always targets the ceiling for deterministic quality gate behavior.
269
315
  6. Use base/unpinned Codex roles only as a fallback or explicit provider-default choice. Log `Selected effort: provider-default`, display provider default effort when known, and do not describe this as parent-ceiling inheritance.
270
316
  7. Do not use top-level per-call `reasoning_effort` as the standard OAT selected-effort path; dogfooding showed that path can be inconsistent.
271
317
 
272
318
  Claude rules:
273
319
 
274
320
  - Claude ceiling is model-based: `haiku < sonnet < opus`.
275
- - Select the lowest sufficient model capped by `workflow.dispatchCeiling.claude` or project `oat_dispatch_ceiling`.
321
+ - Implementer dispatch: select the lowest sufficient model capped by the resolved Claude ceiling (`min(preferred, ceiling)`).
322
+ - Review dispatch: target the resolved Claude ceiling directly.
323
+ - Call `oat project dispatch-ceiling resolve --provider claude --role implementer --orchestrator-tier <current-orchestrator-tier>` (or `--role reviewer`); read `providers.claude.dispatchArgs.model` for the model string to pass. Pass `--orchestrator-tier` so the resolver can flag above-orchestrator upgrade requests and set `verifyOnDispatch` correctly.
276
324
  - Pass `model: "<value>"` when `model_axis=selected:<value>` on the Task tool call.
277
325
  - Keep `effort_axis=not-applicable`; Claude Code has no separate per-dispatch effort axis.
278
326
 
@@ -360,6 +408,52 @@ provider_default_effort: { value | unknown | not-applicable }
360
408
  dispatch_rationale: { short rationale }
361
409
  ```
362
410
 
411
+ ### Dispatch Ceiling Enforcement Log
412
+
413
+ After each phase dispatch (implementation, fix, or review), append one enforcement
414
+ log line. The log reflects the `mode` and `mechanism` returned by
415
+ `oat project dispatch-ceiling resolve` — do not compute these yourself.
416
+
417
+ **Three-state log format:**
418
+
419
+ ```text
420
+ Dispatch ceiling: {value} ({provider}, {mode} — {mechanism detail})
421
+ ```
422
+
423
+ **Log examples (matching resolver output):**
424
+
425
+ ```text
426
+ Dispatch ceiling: high (codex, enforced — variant oat-phase-implementer-high)
427
+ Dispatch ceiling: high (codex, enforced — variant oat-reviewer-high)
428
+ Dispatch ceiling: sonnet (claude, enforced — Task model arg)
429
+ Dispatch ceiling: opus (claude, enforced — Task model arg)
430
+ Dispatch ceiling: high (cursor, unsupported — no adapter; informational)
431
+ Dispatch ceiling: unresolved (codex, advisory — ceiling set but no value resolved)
432
+ ```
433
+
434
+ **Verify-on-upgrade (`verifyOnDispatch: true`):**
435
+
436
+ When the resolver returns `providers.<provider>.verifyOnDispatch: true`, the
437
+ requested tier is above the orchestrator tier (an upgrade request). Before
438
+ logging `enforced`, confirm the actual model/tier used by the dispatched agent.
439
+ If the provider honored the request, log `enforced`. If it did not:
440
+
441
+ ```text
442
+ Dispatch ceiling: opus (claude, advisory — provider did not honor upgrade; ran sonnet)
443
+ ```
444
+
445
+ **`enforced`** — the adapter compiled concrete dispatch args and the provider
446
+ accepted them. Log value + provider + mechanism detail (variant name or "Task
447
+ model arg").
448
+
449
+ **`advisory`** — the adapter supports the ceiling but no concrete value resolved,
450
+ or the provider is known but could not be verified. Log with note "ceiling set
451
+ but no value resolved" or "provider did not honor upgrade; ran \<tier\>".
452
+
453
+ **`unsupported`** — the provider has no registered adapter. Log with note "no
454
+ adapter; informational". Never block on unsupported — dispatch follows provider
455
+ defaults.
456
+
363
457
  ### Dry-Run Mode
364
458
 
365
459
  When the skill is invoked with `--dry-run`:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-plan
3
- version: 1.3.3
3
+ version: 1.3.4
4
4
  description: Use when design.md is complete and executable implementation tasks are needed. Breaks design into bite-sized TDD tasks in canonical plan.md format.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -314,50 +314,50 @@ If `## Planning Checklist` is missing (older plans), add it before finalizing wi
314
314
 
315
315
  ### Step 11.5: Resolve Dispatch Ceiling Before Implementation Readiness
316
316
 
317
- Before marking the plan ready for implementation, resolve the dispatch ceiling
318
- for the current provider.
317
+ Before marking the plan ready for implementation, resolve the dispatch ceiling.
319
318
 
320
319
  Resolution order:
321
320
 
322
- 1. Repo/user/local config key `workflow.dispatchCeiling.<provider>` via `oat config get`
321
+ 1. Config keys `workflow.dispatchCeiling.providers.<provider>` via the resolver CLI
323
322
  2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
324
- 3. Interactive planning prompt
323
+ 3. Interactive planning prompt (below)
325
324
  4. Leave unresolved for implementation preflight when non-interactive
326
325
 
327
- Provider values:
328
-
329
- - Codex: `low`, `medium`, `high`, `xhigh`
330
- - Claude: `haiku`, `sonnet`, `opus`
331
-
332
- If no ceiling resolves for the current provider and the session is interactive,
333
- ask once before final plan review:
326
+ If no ceiling resolves and the session is interactive, present the preset
327
+ prompt once before final plan review:
334
328
 
335
329
  ```text
336
- No Codex dispatch ceiling is configured for this project.
330
+ Set the dispatch ceiling the maximum subagent tier OAT may use.
337
331
 
338
- Choose the maximum Codex reasoning effort OAT may dispatch during implementation:
339
- low | medium | high | xhigh
332
+ 1. Balanced (recommended) Codex: high · Claude: sonnet
333
+ 2. Maximum — Codex: xhigh · Claude: opus (reviews always run at this tier)
334
+ 3. Cost-conscious — Codex: medium · Claude: sonnet
335
+ 4. Advanced — set per provider
336
+ 5. No ceiling
340
337
 
341
- This controls implementer/reviewer subagent variants. It does not change your Codex config.
338
+ OAT applies this where the provider exposes a reliable mechanism (Codex: pinned
339
+ variants; Claude: Task model parameter). Other providers may treat it as advisory.
342
340
  ```
343
341
 
344
- Adapt the wording for Claude:
342
+ **Preset selection** persists `preset` + compiled per-provider values. On
343
+ selection, print the exact compiled result (e.g., "Ceiling set: balanced →
344
+ Codex: high · Claude: sonnet") before proceeding.
345
345
 
346
- ```text
347
- No Claude dispatch ceiling is configured for this project.
346
+ **Advanced (option 4)** prompts for each provider's value individually, then
347
+ persists `providers` + `source` only no `preset` key.
348
348
 
349
- Choose the maximum Claude model tier OAT may dispatch during implementation:
350
- haiku | sonnet | opus
351
-
352
- This controls provider-native subagent model selection. It does not change your Claude config.
353
- ```
349
+ **No ceiling (option 5)** leaves `oat_dispatch_ceiling` unset; implementer
350
+ subagents run at provider defaults.
354
351
 
355
- Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter:
352
+ Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter using the
353
+ normalized shape:
356
354
 
357
355
  ```yaml
358
356
  oat_dispatch_ceiling:
359
- provider: codex
360
- value: high
357
+ preset: balanced # omit when Advanced was chosen
358
+ providers:
359
+ codex: high
360
+ claude: sonnet
361
361
  source: project-state
362
362
  ```
363
363
 
@@ -365,7 +365,7 @@ Do not prompt when `OAT_NON_INTERACTIVE=1` or when no user-response channel
365
365
  exists. In that case, leave the value unresolved. `oat-project-implement`
366
366
  must block before work starts if it still cannot resolve a ceiling.
367
367
 
368
- Do not treat Codex provider default effort as the OAT dispatch ceiling. Provider
368
+ Do not treat provider default effort as the OAT dispatch ceiling. Provider
369
369
  default is informational for base/unpinned roles only.
370
370
 
371
371
  ### Step 12: Review Plan with User
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-quick-start
3
- version: 2.1.3
3
+ version: 2.1.4
4
4
  description: Use when a task is small enough for quick mode or rapid iteration is preferred. Scaffolds a lightweight OAT project from discovery directly to a runnable plan, with optional brainstorming and lightweight design.
5
5
  argument-hint: '<project-name> ["project description"]'
6
6
  disable-model-invocation: true
@@ -459,49 +459,50 @@ Required parallelism pass before finalizing the plan:
459
459
  ### Step 3.5: Resolve Dispatch Ceiling Before Implementation Readiness
460
460
 
461
461
  Before moving the quick project to ready-for-implementation, resolve the
462
- dispatch ceiling for the current provider.
462
+ dispatch ceiling.
463
463
 
464
464
  Resolution order:
465
465
 
466
- 1. Repo/user/local config key `workflow.dispatchCeiling.<provider>` via `oat config get`
466
+ 1. Config keys `workflow.dispatchCeiling.providers.<provider>` via the resolver CLI
467
467
  2. Project `state.md` frontmatter key `oat_dispatch_ceiling`
468
- 3. Interactive quick-planning prompt
468
+ 3. Interactive quick-planning prompt (below)
469
469
  4. Leave unresolved for implementation preflight when non-interactive
470
470
 
471
- Provider values:
472
-
473
- - Codex: `low`, `medium`, `high`, `xhigh`
474
- - Claude: `haiku`, `sonnet`, `opus`
475
-
476
- If no ceiling resolves for the current provider and the session is interactive,
477
- ask once before finalizing `plan.md`:
471
+ If no ceiling resolves and the session is interactive, present the preset
472
+ prompt once before finalizing `plan.md`:
478
473
 
479
474
  ```text
480
- No Codex dispatch ceiling is configured for this project.
475
+ Set the dispatch ceiling the maximum subagent tier OAT may use.
481
476
 
482
- Choose the maximum Codex reasoning effort OAT may dispatch during implementation:
483
- low | medium | high | xhigh
477
+ 1. Balanced (recommended) Codex: high · Claude: sonnet
478
+ 2. Maximum — Codex: xhigh · Claude: opus (reviews always run at this tier)
479
+ 3. Cost-conscious — Codex: medium · Claude: sonnet
480
+ 4. Advanced — set per provider
481
+ 5. No ceiling
484
482
 
485
- This controls implementer/reviewer subagent variants. It does not change your Codex config.
483
+ OAT applies this where the provider exposes a reliable mechanism (Codex: pinned
484
+ variants; Claude: Task model parameter). Other providers may treat it as advisory.
486
485
  ```
487
486
 
488
- Adapt the wording for Claude:
487
+ **Preset selection** persists `preset` + compiled per-provider values. On
488
+ selection, print the exact compiled result (e.g., "Ceiling set: balanced →
489
+ Codex: high · Claude: sonnet") before proceeding.
489
490
 
490
- ```text
491
- No Claude dispatch ceiling is configured for this project.
491
+ **Advanced (option 4)** prompts for each provider's value individually, then
492
+ persists `providers` + `source` only no `preset` key.
492
493
 
493
- Choose the maximum Claude model tier OAT may dispatch during implementation:
494
- haiku | sonnet | opus
495
-
496
- This controls provider-native subagent model selection. It does not change your Claude config.
497
- ```
494
+ **No ceiling (option 5)** leaves `oat_dispatch_ceiling` unset; implementer
495
+ subagents run at provider defaults.
498
496
 
499
- Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter:
497
+ Persist the answer in `"$PROJECT_PATH/state.md"` frontmatter using the
498
+ normalized shape:
500
499
 
501
500
  ```yaml
502
501
  oat_dispatch_ceiling:
503
- provider: codex
504
- value: high
502
+ preset: balanced # omit when Advanced was chosen
503
+ providers:
504
+ codex: high
505
+ claude: sonnet
505
506
  source: project-state
506
507
  ```
507
508
 
@@ -509,7 +510,7 @@ Do not prompt when `OAT_NON_INTERACTIVE=1` or when no user-response channel
509
510
  exists. In that case, leave the value unresolved. `oat-project-implement`
510
511
  must block before work starts if it still cannot resolve a ceiling.
511
512
 
512
- Do not treat Codex provider default effort as the OAT dispatch ceiling. Provider
513
+ Do not treat provider default effort as the OAT dispatch ceiling. Provider
513
514
  default is informational for base/unpinned roles only.
514
515
 
515
516
  ### Step 4: Sync Project State
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAOhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2DpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA2pCD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CA0GT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAIhF,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAQhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAysCD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CA0GT"}
@@ -2,6 +2,7 @@ import { join } from 'node:path';
2
2
  import { buildCommandContext } from '../../app/command-context.js';
3
3
  import { resolveProjectsRoot } from '../shared/oat-paths.js';
4
4
  import { readGlobalOptions } from '../shared/shared.utils.js';
5
+ import { compileDispatchCeilingPreset } from '../../config/dispatch-ceiling-preset.js';
5
6
  import { readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
6
7
  import { resolveEffectiveConfig, } from '../../config/resolve.js';
7
8
  import { resolveProjectRoot } from '../../fs/paths.js';
@@ -40,8 +41,9 @@ const KEY_ORDER = [
40
41
  'workflow.autoReviewAtHillCheckpoints',
41
42
  'workflow.autoNarrowReReviewScope',
42
43
  'workflow.designMode',
43
- 'workflow.dispatchCeiling.codex',
44
- 'workflow.dispatchCeiling.claude',
44
+ 'workflow.dispatchCeiling.preset',
45
+ 'workflow.dispatchCeiling.providers.codex',
46
+ 'workflow.dispatchCeiling.providers.claude',
45
47
  'worktrees.root',
46
48
  ];
47
49
  const CONFIG_CATALOG = [
@@ -420,26 +422,37 @@ const CONFIG_CATALOG = [
420
422
  description: 'Persisted preference for oat-project-design: "collaborative" runs every section section-by-section, "selective" drafts routine sections silently and live-reviews high-risk sections, and "draft" drafts the full design up front for holistic review. Quick-start lightweight design supports collaborative/draft only and treats selective as collaborative when encountered. When unset, the skill prompts. Runtime signals (OAT_NON_INTERACTIVE=1, no TTY) always outrank this preference. Resolution: arg > env > non-interactive context > local > shared > user > default.',
421
423
  },
422
424
  {
423
- key: 'workflow.dispatchCeiling.codex',
425
+ key: 'workflow.dispatchCeiling.preset',
426
+ group: 'Workflow Preferences (3-layer: local > shared > user)',
427
+ file: '.oat/config.local.json | .oat/config.json | ~/.oat/config.json',
428
+ scope: 'workflow',
429
+ type: 'balanced | maximum | cost-conscious',
430
+ defaultValue: 'unset',
431
+ mutability: 'read/write',
432
+ owningCommand: 'oat config set workflow.dispatchCeiling.preset <value>',
433
+ description: 'Provider-neutral ceiling preset that compiles to concrete per-provider values at write time. balanced → Codex: high, Claude: sonnet; maximum → Codex: xhigh, Claude: opus; cost-conscious → Codex: medium, Claude: sonnet. Preset provenance only; runtime dispatch reads concrete providers values. Resolution: local > shared > user > default.',
434
+ },
435
+ {
436
+ key: 'workflow.dispatchCeiling.providers.codex',
424
437
  group: 'Workflow Preferences (3-layer: local > shared > user)',
425
438
  file: '.oat/config.local.json | .oat/config.json | ~/.oat/config.json',
426
439
  scope: 'workflow',
427
440
  type: 'low | medium | high | xhigh',
428
441
  defaultValue: 'unset',
429
442
  mutability: 'read/write',
430
- owningCommand: 'oat config set workflow.dispatchCeiling.codex <value>',
431
- description: 'Maximum Codex reasoning effort OAT may select for deterministic implementation and review subagent variants. Provider defaults remain informational for base/unpinned roles and are not treated as this ceiling. Resolution: local > shared > user > default.',
443
+ owningCommand: 'oat config set workflow.dispatchCeiling.providers.codex <value>',
444
+ description: 'Explicit Codex ceiling value (advanced/manual). Wins over any preset. Maximum Codex reasoning effort OAT may select for deterministic implementation and review subagent variants. Resolution: local > shared > user > default.',
432
445
  },
433
446
  {
434
- key: 'workflow.dispatchCeiling.claude',
447
+ key: 'workflow.dispatchCeiling.providers.claude',
435
448
  group: 'Workflow Preferences (3-layer: local > shared > user)',
436
449
  file: '.oat/config.local.json | .oat/config.json | ~/.oat/config.json',
437
450
  scope: 'workflow',
438
451
  type: 'haiku | sonnet | opus',
439
452
  defaultValue: 'unset',
440
453
  mutability: 'read/write',
441
- owningCommand: 'oat config set workflow.dispatchCeiling.claude <value>',
442
- description: 'Maximum Claude model tier OAT may select for provider-native subagent dispatch. Claude has no separate per-dispatch effort axis, so the effort axis remains not-applicable. Resolution: local > shared > user > default.',
454
+ owningCommand: 'oat config set workflow.dispatchCeiling.providers.claude <value>',
455
+ description: 'Explicit Claude ceiling value (advanced/manual). Wins over any preset. Maximum Claude model tier OAT may select for provider-native subagent dispatch. Resolution: local > shared > user > default.',
443
456
  },
444
457
  {
445
458
  key: 'sync.defaultStrategy',
@@ -503,8 +516,14 @@ const WORKFLOW_ENUM_VALUES = {
503
516
  'workflow.postImplementSequence': ['wait', 'summary', 'pr', 'docs-pr'],
504
517
  'workflow.reviewExecutionModel': ['subagent', 'inline', 'fresh-session'],
505
518
  'workflow.designMode': ['collaborative', 'selective', 'draft'],
506
- 'workflow.dispatchCeiling.codex': ['low', 'medium', 'high', 'xhigh'],
507
- 'workflow.dispatchCeiling.claude': ['haiku', 'sonnet', 'opus'],
519
+ 'workflow.dispatchCeiling.preset': ['balanced', 'maximum', 'cost-conscious'],
520
+ 'workflow.dispatchCeiling.providers.codex': [
521
+ 'low',
522
+ 'medium',
523
+ 'high',
524
+ 'xhigh',
525
+ ],
526
+ 'workflow.dispatchCeiling.providers.claude': ['haiku', 'sonnet', 'opus'],
508
527
  };
509
528
  const WORKFLOW_BOOLEAN_KEYS = new Set([
510
529
  'workflow.archiveOnComplete',
@@ -588,13 +607,34 @@ function parseWorkflowValue(key, rawValue) {
588
607
  }
589
608
  function applyWorkflowValue(workflow, key, value) {
590
609
  const subKey = key.slice('workflow.'.length);
591
- if (subKey.startsWith('dispatchCeiling.')) {
592
- const providerKey = subKey.slice('dispatchCeiling.'.length);
610
+ if (subKey === 'dispatchCeiling.preset') {
611
+ // Presets compile to concrete per-provider values at write time so the
612
+ // resolver (which reads only providers.*) gets a usable ceiling. The preset
613
+ // label is persisted as provenance alongside the compiled providers.
614
+ const compiled = compileDispatchCeilingPreset(value);
615
+ return {
616
+ ...workflow,
617
+ dispatchCeiling: {
618
+ ...workflow.dispatchCeiling,
619
+ preset: compiled.preset,
620
+ providers: {
621
+ ...workflow.dispatchCeiling?.providers,
622
+ codex: compiled.providers.codex,
623
+ claude: compiled.providers.claude,
624
+ },
625
+ },
626
+ };
627
+ }
628
+ if (subKey.startsWith('dispatchCeiling.providers.')) {
629
+ const providerKey = subKey.slice('dispatchCeiling.providers.'.length);
593
630
  return {
594
631
  ...workflow,
595
632
  dispatchCeiling: {
596
633
  ...workflow.dispatchCeiling,
597
- [providerKey]: value,
634
+ providers: {
635
+ ...workflow.dispatchCeiling?.providers,
636
+ [providerKey]: value,
637
+ },
598
638
  },
599
639
  };
600
640
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,uBAAuB,EAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAiXD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAsCT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,uBAAuB,EAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAggBD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAiDT"}