@open-agent-toolkit/cli 0.1.46 → 0.1.48

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 (82) hide show
  1. package/assets/agents/oat-phase-implementer.md +202 -191
  2. package/assets/agents/oat-reviewer.md +11 -1
  3. package/assets/config/dispatch-matrix-recommendation.json +120 -13
  4. package/assets/docs/cli-utilities/configuration.md +172 -113
  5. package/assets/docs/cli-utilities/workflow-gates.md +161 -27
  6. package/assets/docs/contributing/skills.md +14 -8
  7. package/assets/docs/provider-sync/providers.md +41 -7
  8. package/assets/docs/provider-sync/scope-and-surface.md +2 -2
  9. package/assets/docs/reference/cli-reference.md +3 -1
  10. package/assets/docs/reference/oat-directory-structure.md +27 -26
  11. package/assets/docs/workflows/projects/artifacts.md +31 -1
  12. package/assets/docs/workflows/projects/dispatch-ceiling.md +235 -187
  13. package/assets/docs/workflows/projects/implementation-execution.md +283 -260
  14. package/assets/docs/workflows/projects/lifecycle.md +26 -5
  15. package/assets/docs/workflows/projects/reviews.md +27 -2
  16. package/assets/migration/pjm-restructure.md +1 -1
  17. package/assets/public-package-versions.json +4 -4
  18. package/assets/skills/oat-project-implement/SKILL.md +247 -133
  19. package/assets/skills/oat-project-import-plan/SKILL.md +173 -16
  20. package/assets/skills/oat-project-next/SKILL.md +2 -2
  21. package/assets/skills/oat-project-plan/SKILL.md +122 -92
  22. package/assets/skills/oat-project-plan-writing/SKILL.md +246 -15
  23. package/assets/skills/oat-project-quick-start/SKILL.md +157 -107
  24. package/assets/skills/oat-project-review-provide/SKILL.md +94 -22
  25. package/dist/commands/config/index.d.ts.map +1 -1
  26. package/dist/commands/config/index.js +64 -39
  27. package/dist/commands/doctor/index.d.ts.map +1 -1
  28. package/dist/commands/doctor/index.js +21 -6
  29. package/dist/commands/gate/index.d.ts +7 -1
  30. package/dist/commands/gate/index.d.ts.map +1 -1
  31. package/dist/commands/gate/index.js +544 -67
  32. package/dist/commands/gate/review-verdict.d.ts +16 -0
  33. package/dist/commands/gate/review-verdict.d.ts.map +1 -1
  34. package/dist/commands/gate/review-verdict.js +72 -9
  35. package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
  36. package/dist/commands/project/dispatch-ceiling/index.js +452 -16
  37. package/dist/commands/providers/codex/materialize.d.ts.map +1 -1
  38. package/dist/commands/providers/codex/materialize.js +6 -1
  39. package/dist/commands/shared/frontmatter.d.ts +4 -0
  40. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  41. package/dist/commands/shared/frontmatter.js +23 -0
  42. package/dist/commands/status/index.d.ts +1 -0
  43. package/dist/commands/status/index.d.ts.map +1 -1
  44. package/dist/commands/status/index.js +10 -4
  45. package/dist/commands/sync/index.d.ts.map +1 -1
  46. package/dist/commands/sync/index.js +10 -3
  47. package/dist/commands/sync/sync.types.d.ts +1 -0
  48. package/dist/commands/sync/sync.types.d.ts.map +1 -1
  49. package/dist/config/oat-config.d.ts +19 -2
  50. package/dist/config/oat-config.d.ts.map +1 -1
  51. package/dist/config/oat-config.js +139 -24
  52. package/dist/config/resolve.d.ts +8 -0
  53. package/dist/config/resolve.d.ts.map +1 -1
  54. package/dist/config/resolve.js +66 -2
  55. package/dist/engine/index.d.ts +1 -1
  56. package/dist/engine/index.d.ts.map +1 -1
  57. package/dist/engine/index.js +1 -1
  58. package/dist/engine/scanner.d.ts +1 -0
  59. package/dist/engine/scanner.d.ts.map +1 -1
  60. package/dist/engine/scanner.js +17 -1
  61. package/dist/fs/paths.d.ts +4 -0
  62. package/dist/fs/paths.d.ts.map +1 -1
  63. package/dist/fs/paths.js +18 -1
  64. package/dist/providers/ceiling/registry.d.ts +1 -0
  65. package/dist/providers/ceiling/registry.d.ts.map +1 -1
  66. package/dist/providers/ceiling/registry.js +12 -5
  67. package/dist/providers/codex/codec/catalog.d.ts +14 -0
  68. package/dist/providers/codex/codec/catalog.d.ts.map +1 -0
  69. package/dist/providers/codex/codec/catalog.js +21 -0
  70. package/dist/providers/codex/codec/materialize.d.ts.map +1 -1
  71. package/dist/providers/codex/codec/materialize.js +6 -5
  72. package/dist/providers/codex/codec/shared.d.ts +19 -0
  73. package/dist/providers/codex/codec/shared.d.ts.map +1 -1
  74. package/dist/providers/codex/codec/shared.js +98 -5
  75. package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
  76. package/dist/providers/codex/codec/sync-extension.js +142 -32
  77. package/dist/providers/identity/stamp.d.ts.map +1 -1
  78. package/dist/providers/identity/stamp.js +4 -0
  79. package/dist/shared/types.d.ts +1 -0
  80. package/dist/shared/types.d.ts.map +1 -1
  81. package/dist/shared/types.js +4 -0
  82. package/package.json +2 -2
@@ -33,7 +33,7 @@ Gate config lives under `workflow.gates.skills` and is keyed by skill name.
33
33
  "gates": {
34
34
  "skills": {
35
35
  "oat-project-implement": {
36
- "command": "oat gate review \"Use oat-project-review-provide code final to review the current project\"",
36
+ "command": "oat gate review --project \"$PROJECT_PATH\" --review-type code --review-scope final \"Use oat-project-review-provide code final for the declared project\"",
37
37
  "description": "Run a fresh-runtime final review before implementation is considered done.",
38
38
  "onFailure": "block",
39
39
  "maxAttempts": 2
@@ -69,9 +69,48 @@ review side effects are expected:
69
69
  tracked state
70
70
 
71
71
  Gate-produced review artifacts use `oat_review_invocation: gate` in
72
- frontmatter. After a gate review reports a produced artifact, the host must run
73
- or hand off to `oat-project-review-receive` before treating the review as
74
- dispositioned. Until receive runs, the artifact is only produced, not consumed.
72
+ frontmatter. After a gate returns a corroborated `ok` or `blocked` result with a
73
+ non-null `handoff`, the host must run or hand off to
74
+ `oat-project-review-receive` before treating the review as dispositioned. An
75
+ artifact path by itself is not receive eligibility. Until receive runs for a
76
+ receive-eligible result, the artifact is only produced, not consumed.
77
+
78
+ Gate-originated artifacts also copy the configured invocation record that the
79
+ CLI places in the review prompt:
80
+
81
+ ```yaml
82
+ oat_review_invocation: gate
83
+ oat_project: .oat/projects/shared/example
84
+ oat_gate_run_id: 00000000-0000-0000-0000-000000000000
85
+ oat_gate_target: codex-sol-max
86
+ oat_gate_runtime: codex
87
+ oat_invocation_model: gpt-5.6-sol # or provider-default | unknown
88
+ oat_invocation_reasoning_effort: max # or provider-default | unknown
89
+ oat_invocation_source: exec-target-config # or unknown
90
+ ```
91
+
92
+ These fields describe configured invocation controls. They do not confirm the
93
+ model that ran, and the reviewer must not replace them with self-identification.
94
+ The CLI compares the copied values with its gate-owned record before it applies
95
+ the severity threshold.
96
+
97
+ ### Review project resolution and corroboration
98
+
99
+ `--project <path-or-name>` is a declaration. OAT normalizes the declared path
100
+ and reports `projectResolutionSource: declared`. When the option is omitted,
101
+ the compatibility resolver may use the configured active project
102
+ (`active-project`) or the only project candidate (`single-candidate`); those
103
+ ambient paths report `corroboration.project: ambient` rather than pretending a
104
+ declaration was made.
105
+
106
+ After dispatch, OAT searches direct, non-archived review files across project
107
+ review directories for the unique `oat_gate_run_id`. An explicitly resolved
108
+ project is included even when it is outside the configured shared projects
109
+ root. For a declaration to corroborate, both the artifact's containing project
110
+ and its parsed, normalized `oat_project` must equal the declaration. Sibling
111
+ project writes, missing or wrong `oat_project`, missing or wrong run IDs,
112
+ outside-repository artifact project values, and duplicate run-ID matches all
113
+ fail closed before invocation-field remediation or severity evaluation.
75
114
 
76
115
  `oat gate review` parses the produced artifact and returns a blocking exit
77
116
  status when the configured threshold is met. `cross-provider-exec` does not do
@@ -101,24 +140,54 @@ once an artifact exists, its `generatedAt` (the artifact's seconds-precision
101
140
  `oat_generated_at`), so a caller can correlate the result to the exact artifact
102
141
  and disambiguate re-gate rounds:
103
142
 
104
- | `status` | Exit | Meaning |
105
- | ---------------------------- | ---- | --------------------------------------------------------- |
106
- | `ok` | 0 | Review completed; gate passed at the threshold. |
107
- | `blocked` | 1 | Review completed; findings at/above the threshold. |
108
- | `review_failed` | ≠0 | The provider target exited non-zero; no verdict. |
109
- | `artifact_validation_failed` | 1 | Provider ran but the review artifact could not be parsed. |
110
-
111
- `ok` and `blocked` also include `outcome`, `artifactPath`, `counts`, `scope`,
112
- and `handoff`. Treat any status other than `ok`/`blocked` as an operational
113
- failure, not a passing gate.
143
+ | `status` | Exit | Meaning |
144
+ | ------------------------------ | ---- | ------------------------------------------------------------ |
145
+ | `ok` | 0 | Review completed; gate passed at the threshold. |
146
+ | `blocked` | 1 | Review completed; findings at/above the threshold. |
147
+ | `review_failed` | ≠0 | The provider target exited non-zero; no verdict. |
148
+ | `artifact_validation_failed` | 1 | Artifact format or configured invocation fields are invalid. |
149
+ | `targeting_correlation_failed` | 1 | Identity did not correlate; do not run review-receive. |
150
+
151
+ Only `ok` and `blocked` are positive, receive-eligible review outcomes: both
152
+ follow successful identity corroboration and carry a non-null `handoff`.
153
+ `blocked` exits nonzero because of findings, while `ok` exits zero; callers must
154
+ therefore route receive from the structured status and handoff rather than from
155
+ the exit code. `review_failed` has no validated verdict and is not eligible.
156
+ For `artifact_validation_failed`, correct the artifact and rerun the gate; do
157
+ not invoke review-receive until the gate successfully revalidates it as `ok` or
158
+ `blocked`.
159
+
160
+ `ok` and `blocked` also include `receiveEligible: true`, `outcome`,
161
+ `artifactPath`, `counts`, `scope`, `handoff`, `gateInvocation`, and
162
+ `corroboration`. Invoke review-receive only when all three conditions hold:
163
+ the status is `ok` or `blocked`, `receiveEligible` is `true`, and `handoff` is
164
+ non-null. `gateInvocation` contains the
165
+ configured `runId`, `targetId`, `runtime`, `model`, `reasoningEffort`, and
166
+ `source`. `corroboration.run` and `corroboration.invocation` are each
167
+ `matched`, `missing`, or `mismatched`. `corroboration.project` is `matched` for
168
+ an explicitly declared, corroborated project and `ambient` when the command
169
+ relied on active-project or single-candidate compatibility. Expected and actual
170
+ diagnostics include the declared project, containing project, artifact
171
+ `oat_project`, normalized artifact project, matching run-ID paths, and configured
172
+ invocation. Treat any status other than `ok`/`blocked` as an operational failure,
173
+ not a passing gate.
174
+
175
+ `targeting_correlation_failed` is non-remediable by review-fix retries. Its JSON
176
+ sets `receiveEligible: false`, `remediable: false`, and `handoff: null`; do not
177
+ run review-receive for that artifact even when `artifactPath` is present.
178
+ Correct the stored project declaration or reviewer output routing and run a new
179
+ gate instead. Invocation-only mismatch continues to use
180
+ `artifact_validation_failed`; correct the exact configured invocation fields
181
+ and rerun the gate for successful revalidation before receive.
114
182
 
115
183
  **Drive gates through `oat gate review`, not raw provider invocation.** An
116
184
  orchestrator that hand-rolls the review (for example, calling
117
185
  `codex exec … oat-project-review-provide <scope>` directly) and then watches
118
186
  `reviews/` for a file is reimplementing — less reliably — what the CLI already
119
- does: `oat gate review` snapshots the reviews directory, dispatches the
120
- provider, and attributes the produced artifact by content hash, so it is immune
121
- to a stale file lingering from a prior round. It works standalone, not only
187
+ does: `oat gate review` dispatches the provider, locates direct active project
188
+ review artifacts by the unique gate run ID, and uses before/after signatures
189
+ only for compatibility diagnostics. Archived and ad-hoc reviews remain
190
+ ineligible. It works standalone, not only
122
191
  inside the `oat-project-implement` auto-loop — a one-off final review is just:
123
192
 
124
193
  ```bash
@@ -127,7 +196,7 @@ oat --json gate review \
127
196
  --review-type code \
128
197
  --review-scope final \
129
198
  --exit-nonzero-on important \
130
- 'Use oat-project-review-provide code final to review the current project'
199
+ 'Use oat-project-review-provide code final for the declared project'
131
200
  ```
132
201
 
133
202
  Read the resulting envelope and exit code; that is the whole completion
@@ -183,6 +252,10 @@ that candidate's model and is not double-pinned.
183
252
  "cursor-family-gate": {
184
253
  "runtime": "cursor",
185
254
  "baseCommand": ["cursor-agent", "-p", "--force"],
255
+ "invocation": {
256
+ "model": "composer-2.5",
257
+ "reasoningEffort": "provider-default"
258
+ },
186
259
  "models": ["composer-2.5", "gpt-5.5-xhigh", "claude-opus-4-8"],
187
260
  "availabilityCommand": [
188
261
  "sh",
@@ -221,6 +294,8 @@ for the same behavior.
221
294
  oat gate target set codex-5.5-xhigh \
222
295
  --runtime codex \
223
296
  --base-command-json '["codex","exec","--model","gpt-5.5","-c","model_reasoning_effort=\"xhigh\"","--dangerously-bypass-approvals-and-sandbox"]' \
297
+ --invocation-model gpt-5.5 \
298
+ --invocation-reasoning-effort xhigh \
224
299
  --availability-json '["codex","--version"]' \
225
300
  --priority 120 \
226
301
  --layer user
@@ -228,6 +303,8 @@ oat gate target set codex-5.5-xhigh \
228
303
  oat gate target set claude-opus-skip-permissions \
229
304
  --runtime claude \
230
305
  --base-command-json '["claude","-p","--model","opus","--dangerously-skip-permissions"]' \
306
+ --invocation-model opus \
307
+ --invocation-reasoning-effort provider-default \
231
308
  --availability-json '["claude","--version"]' \
232
309
  --priority 115 \
233
310
  --layer user
@@ -235,6 +312,8 @@ oat gate target set claude-opus-skip-permissions \
235
312
  oat gate target set cursor-force \
236
313
  --runtime cursor \
237
314
  --base-command-json '["cursor-agent","-p","--force"]' \
315
+ --invocation-model provider-default \
316
+ --invocation-reasoning-effort provider-default \
238
317
  --availability-json '["cursor-agent","--version"]' \
239
318
  --priority 90 \
240
319
  --layer user
@@ -252,7 +331,7 @@ Set or clear a skill gate:
252
331
 
253
332
  ```bash
254
333
  oat gate set oat-project-implement \
255
- --command 'oat gate review --review-type code --review-scope final "Use oat-project-review-provide code final to review the current project"' \
334
+ --command 'oat gate review --project "$PROJECT_PATH" --review-type code --review-scope final "Use oat-project-review-provide code final for the declared project"' \
256
335
  --description "Run final review in another runtime" \
257
336
  --on-failure block \
258
337
  --max-attempts 2 \
@@ -261,31 +340,67 @@ oat gate set oat-project-implement \
261
340
  oat gate unset oat-project-implement --layer user
262
341
  ```
263
342
 
264
- Lifecycle gate commands should normally omit `--target <id>`. Leaving the
265
- target unset lets the dispatcher avoid the current runtime and choose the
343
+ Lifecycle review gate commands must declare `--project "$PROJECT_PATH"` and
344
+ omit `--target <id>`. The lifecycle skill exports `PROJECT_PATH` into the gate
345
+ command shell, validates the resolved review command, and then executes it
346
+ exactly as configured. It does not inject missing arguments. Leaving the target
347
+ unset lets the dispatcher avoid the current runtime and choose the
266
348
  highest-priority available non-host target. Pin a target only for manual
267
349
  dispatch, debugging, or a deliberate local/user-specific override.
268
350
 
351
+ ### Migrate ambient lifecycle commands
352
+
353
+ Older user-level lifecycle commands often asked a reviewer to inspect the
354
+ "current project" but omitted a machine-readable declaration. Migrate each
355
+ stored `oat gate review` command by inserting `--project "$PROJECT_PATH"` and
356
+ retaining provider-neutral target selection. For example:
357
+
358
+ ```bash
359
+ export PROJECT_PATH
360
+ oat gate set oat-project-implement \
361
+ --command 'oat gate review --project "$PROJECT_PATH" --review-type code --review-scope final "Use oat-project-review-provide code final for the declared project"' \
362
+ --description "Run final review in another runtime" \
363
+ --on-failure block \
364
+ --max-attempts 2 \
365
+ --layer user
366
+ ```
367
+
368
+ Apply the same command shape to `oat-project-plan`,
369
+ `oat-project-quick-start`, and `oat-project-import-plan` when those lifecycle
370
+ skills have configured review gates. Do not add `--target`; explicit targets
371
+ remain manual/debug or deliberate local/user-specific overrides.
372
+
269
373
  Set or clear an exec target:
270
374
 
271
375
  ```bash
272
376
  oat gate target set codex-high \
273
377
  --runtime codex \
274
378
  --base-command-json '["codex","exec","--model","gpt-5.5"]' \
379
+ --invocation-model gpt-5.5 \
380
+ --invocation-reasoning-effort provider-default \
275
381
  --availability-json '["codex","--version"]' \
276
382
  --priority 90 \
277
383
  --layer user
278
384
 
279
385
  oat gate target unset codex-high --layer user
386
+
387
+ oat --json gate target list
280
388
  ```
281
389
 
390
+ `gate target list` is read-only. It reports each resolved target's origin,
391
+ explicit configuration, enabled state, current availability, and normalized
392
+ invocation values without selecting or executing a reviewer. Omitted invocation
393
+ values are reported as `unknown`; `provider-default` is an explicit configured
394
+ value, not an inference from the provider command.
395
+
282
396
  Dispatch a review through the target registry:
283
397
 
284
398
  ```bash
285
399
  oat gate review \
400
+ --project "$PROJECT_PATH" \
286
401
  --review-type code \
287
402
  --review-scope final \
288
- "Use oat-project-review-provide code final to review the current project"
403
+ "Use oat-project-review-provide code final for the declared project"
289
404
  ```
290
405
 
291
406
  Leaving `--target` unset lets target priority choose the highest-priority
@@ -295,10 +410,10 @@ For manual or debug dispatch, use `--target <id>` to pin one target and skip
295
410
  detection/avoidance:
296
411
 
297
412
  ```bash
298
- oat gate review --target codex-5.5-xhigh \
413
+ oat gate review --project "$PROJECT_PATH" --target codex-5.5-xhigh \
299
414
  --review-type code \
300
415
  --review-scope final \
301
- "Use oat-project-review-provide code final to review the current project"
416
+ "Use oat-project-review-provide code final for the declared project"
302
417
  ```
303
418
 
304
419
  Dispatch a generic prompt through the target registry:
@@ -313,7 +428,9 @@ By default the dispatcher:
313
428
  2. Expands target `models` into candidate `(target, model)` pairs.
314
429
  3. Detects the current runtime with host detection commands.
315
430
  4. Resolves producer identity from `--producer-identity` or dispatch stamps when
316
- available.
431
+ available. Exact phase/task scopes use the matching stamp. `final` and
432
+ contiguous ranges such as `p02-p03` aggregate every in-range implementer/fix
433
+ stamp.
317
434
  5. Applies `--avoid same-family`.
318
435
  6. Checks candidate availability in descending priority order, with target id as
319
436
  the tie-breaker.
@@ -338,15 +455,32 @@ producer when no project dispatch stamp exists:
338
455
 
339
456
  ```bash
340
457
  oat gate review \
458
+ --project "$PROJECT_PATH" \
341
459
  --producer-identity gpt-5.5-xhigh:declared \
342
460
  --review-type code \
343
461
  --review-scope final \
344
- "Use oat-project-review-provide code final to review the current project"
462
+ "Use oat-project-review-provide code final for the declared project"
345
463
  ```
346
464
 
347
465
  Gate JSON output includes `diversity` metadata with the requested avoid mode,
348
466
  producer identity/provenance/confidence, reviewer target/model/family, and the
349
- achieved level:
467
+ achieved level. Claimable exact phase/task matches with a known family report
468
+ producer source `stamp` without contributor fields; legacy or otherwise
469
+ non-claimable exact matches remain fully `unknown`. An explicit flag reports
470
+ `flag` and remains authoritative. Final and contiguous range scopes report
471
+ `aggregated-stamps` whenever at least one relevant stamp exists, even for a
472
+ single stamp or when no stamp has a claimable family. Their producer record uses
473
+ an unknown representative instead of presenting the latest stamp as aggregate
474
+ truth:
475
+
476
+ - `avoidFamilies` is the stable deduplicated union of claimable known families.
477
+ - `contributingScopes` is the stable document-order list of distinct scopes from
478
+ every relevant stamp.
479
+ - `contributingStampCount` counts every relevant stamp, including unknown or
480
+ otherwise non-claimable identities.
481
+
482
+ When no relevant aggregate stamp exists, producer source is `unknown` and the
483
+ contributor fields are absent. The achieved level is one of:
350
484
 
351
485
  - `different-family`
352
486
  - `degraded-to-different-slug`
@@ -88,18 +88,24 @@ The Gate Execution step should:
88
88
 
89
89
  1. Run `oat gate resolve <this-skill> --json`.
90
90
  2. Treat `null` as "no gate configured."
91
- 3. Run the resolved `command` as the skill's last step when a gate is present.
92
- 4. Use the command exit code as the pass/fail signal.
93
- 5. Follow the gate's `onFailure` policy:
91
+ 3. Export the resolved path with `export PROJECT_PATH` before launching the
92
+ command shell.
93
+ 4. For `oat gate review`, require the configured command to include
94
+ `--project "$PROJECT_PATH"`; do not append it at runtime, because the resolved
95
+ command must execute exactly as configured.
96
+ 5. Run the resolved `command` as the skill's last step and use its exit code as
97
+ the pass/fail signal.
98
+ 6. Follow the gate's `onFailure` policy:
94
99
  - `block` - remediate and rerun up to `maxAttempts`, then escalate.
95
100
  - `prompt` - surface the failure and ask the user.
96
101
  - `warn` - record the failure and continue.
97
102
 
98
- For OAT review gates, prefer putting `oat gate review "<prompt>"` in the
99
- configured gate command rather than hard-coding a provider CLI directly in the
100
- skill. Use `oat gate cross-provider-exec "<prompt>"` for generic cross-runtime
101
- commands that should report only the child process status, not review findings.
102
- Reusable lifecycle gate commands should normally omit `--target <id>` so the
103
+ For OAT review gates, prefer putting
104
+ `oat gate review --project "$PROJECT_PATH" "<prompt>"` in the configured gate
105
+ command rather than hard-coding a provider CLI directly in the skill. Use
106
+ `oat gate cross-provider-exec "<prompt>"` for generic cross-runtime commands
107
+ that should report only the child process status, not review findings.
108
+ Reusable lifecycle gate commands must omit `--target <id>` so the
103
109
  dispatcher can avoid the current runtime; reserve explicit targets for
104
110
  manual/debug commands or deliberate local/user-specific overrides. See
105
111
  [Workflow Gates](../cli-utilities/workflow-gates.md) for the config and command
@@ -12,13 +12,15 @@ description: 'Provider-specific path mappings for Claude, Cursor, Copilot, Gemin
12
12
  - Project: `.agents/skills` -> `.claude/skills`, `.agents/agents` -> `.claude/agents`, `.agents/rules` -> `.claude/rules`
13
13
  - User: `~/.agents/skills` -> `~/.claude/skills`, `~/.agents/agents` -> `~/.claude/agents`
14
14
  - Rule files stay `.md` and are rendered with Claude-compatible frontmatter when needed
15
+ - Managed task workers use the exact configured candidate returned as `providers.claude.dispatchArgs.model`; OAT passes that value as the actual Task `model`
15
16
 
16
17
  === "Cursor"
17
18
 
18
19
  - Project: `.agents/skills` -> `.cursor/skills`, `.agents/agents` -> `.cursor/agents`, `.agents/rules` -> `.cursor/rules`
19
20
  - User: `~/.agents/skills` -> `~/.cursor/skills`, `~/.agents/agents` -> `~/.cursor/agents`
20
21
  - Subagent invocation in Cursor is prompt-driven (`/name` or natural mention), not `subagent_type`
21
- - OAT-controlled Cursor dispatch uses the generic `.cursor/agents/<name>.md` file plus the Task-level `model` argument selected from the dispatch matrix. A `model` frontmatter value is only a default/fallback mechanism.
22
+ - OAT-controlled Cursor dispatch uses the generic `.cursor/agents/<name>.md` file plus the exact `providers.cursor.dispatchArgs.model` value selected from the candidate ladder. OAT passes it byte-for-byte as the actual Task-level `model`; a `model` frontmatter value is only a default/fallback mechanism.
23
+ - Cursor model strings are opaque. OAT does not infer family, effort, cost, or capability from their spelling; the configured candidate position owns the named tier meaning.
22
24
  - Cursor model validation checks whether the selected model is eligible for subagent Task dispatch; the broad `cursor-agent models` catalog alone is not enough proof.
23
25
  - Rule files render as `.cursor/rules/*.mdc`
24
26
 
@@ -43,20 +45,52 @@ description: 'Provider-specific path mappings for Claude, Cursor, Copilot, Gemin
43
45
  - Canonical markdown agents in `.agents/agents/*.md` are exported to Codex runtime roles:
44
46
  - `.codex/agents/<role>.toml`
45
47
  - `.codex/config.toml` (`[features] multi_agent = true`, `[agents.<role>]` upserts)
46
- - Codex role files include OAT managed provenance headers and are regenerated by `oat sync --scope project`
47
- - The Codex sync extension also generates materialized roles from explicit model+effort targets, such as `oat-phase-implementer-gpt-5-6-terra-xhigh` or `oat-reviewer-gpt-5-6-terra-xhigh`, alongside canonical-derived base roles. These generated variants are managed by `oat sync` and are not treated as strays (see Manifest and Drift -> Generated provider roles)
48
- - A single role can be materialized directly with `oat providers codex materialize <agent-name> --model <model-id> --effort <reasoning-effort>`; `--agent-path` selects a specific canonical markdown agent, `--role-name` overrides the generated role name, and `--scope user` writes a one-off user-scope role.
48
+ - Codex role files include OAT managed provenance headers and are regenerated by `oat sync --scope project|user|all`
49
+ - Project sync writes and maintains the version-controlled supported catalogue: Luna and Terra at `low`, `medium`, `high`, and `xhigh`, plus Sol at those efforts and `max`, for both `oat-phase-implementer` and `oat-reviewer` (26 pinned variants). Sync writes files; it does not create a Git commit.
50
+ - Custom targets follow configuration provenance: user-config targets write only under `~/.codex`; shared, repo-local, and active-project targets write under the project's tracked `.codex` view.
51
+ - User sync loads only the bundled canonical `oat-phase-implementer` and `oat-reviewer` definitions needed to expand user-config targets. It does not enable general user-agent mirroring, and it refuses stale user-role cleanup if either managed definition is unavailable.
52
+ - Generated variants carry `supported-catalogue`, `user-config`, or `project-config` ownership. Cleanup removes stale entries only for the owner being reconciled and preserves other scopes plus unrelated Codex entries.
53
+ - All project-generated Codex variants and config registrations are repository-owned, version-controlled output and are never auto-ignored by OAT. User-config output remains under `~/.codex`.
54
+ - A single role can be materialized directly with `oat providers codex materialize <agent-name> --model <model-id> --effort <reasoning-effort>`; `--agent-path` selects a specific canonical markdown agent, `--role-name` overrides the generated role name, and `--scope user` writes a user-config-owned role.
49
55
  - Aggregate Codex config drift metadata (`aggregateConfigHash`) is emitted in sync/status codex extension output and intentionally not stored as a separate manifest row
50
- - User-scope Codex role generation via provider sync (`~/.codex`) remains deferred
56
+ - Sync-time materialization is best effort; managed workflow correctness uses exact registered roles or a fresh child pinned to the resolved model plus reasoning effort with canonical role instructions, and does not require provider restart/hot reload
57
+ - Codex `max` is a first-class dispatch effort. It is present only for the Sol family in the committed supported catalogue, for both implementer and reviewer roles.
51
58
  - Codex multi-agent dispatch uses config-defined roles (`[agents.<name>]`) and `agent_type`
52
59
  - Codex subagent workflows require `[features] multi_agent = true` in active Codex config layers
60
+ - `oat-phase-implementer` is dual-mode: Phase Scope makes it a phase coordinator, while Task Scope makes the exact materialized variant a one-task worker. The coordinator does not implement ordinary tasks itself.
61
+
62
+ ## Managed dispatch views
63
+
64
+ Reusable ordered candidate ladders live in `workflow.dispatchCeiling.providers`.
65
+ The project or phase named ceiling is only a maximum over those candidates; it
66
+ does not select one permanent model family for the project.
67
+
68
+ Adopt the complete ladder into an explicit owning config scope before sync:
69
+
70
+ ```bash
71
+ oat config adopt dispatch-matrix --shared
72
+ oat config adopt dispatch-matrix --local
73
+ oat config adopt dispatch-matrix --user
74
+ ```
75
+
76
+ Project-config candidates materialize into the tracked, version-controlled
77
+ project `.codex` view. User-config candidates materialize under `~/.codex`.
78
+ OAT does not auto-ignore project output or create its Git commit; the team owns
79
+ that repository change.
80
+
81
+ At implementation time, the phase coordinator passes the recorded named
82
+ maximum through invocation-only `--ceiling-tier`, resolves one exact candidate
83
+ per bounded task, and dispatches one task worker at a time. Codex uses the
84
+ resolver-returned materialized role. Claude and Cursor bind the exact model
85
+ arguments described above. A missing or unselectable managed target blocks
86
+ rather than falling back to the coordinator or a base role.
53
87
 
54
88
  ## Scope rules
55
89
 
56
90
  - Project scope: skills + agents + rules
57
- - User scope: skills + agents (provider mappings vary by adapter)
91
+ - User scope: skills, plus the two bundled managed Codex role definitions used only for user-owned target expansion (provider mappings vary by adapter)
58
92
  - Rules are project-scoped only in this release
59
- - Codex user-scope role generation under `~/.codex` via provider sync remains deferred in this release; direct one-off materialization can use `--scope user`
93
+ - Codex user-scope sync materializes user-config custom roles under `~/.codex`; project-config and supported-catalogue output remains project-scoped and version controlled
60
94
 
61
95
  ## Adoption model
62
96
 
@@ -47,9 +47,9 @@ Rules are currently project-scoped canonical content. Unlike skills and agents,
47
47
  - Project provider enablement is stored in `.oat/sync/config.json` (`providers.<name>.enabled`).
48
48
  - `oat init --scope project` (interactive) prompts for supported providers and persists explicit true/false values.
49
49
  - `oat sync --scope project` uses config-aware provider activation and can prompt to remediate detected mismatches.
50
- - Codex project-scope subagent sync is generated output (`.codex/agents/*.toml` + `.codex/config.toml`) computed at command layer after path-mapping sync. Generated Codex roles - including materialized model+effort implementer and reviewer variants - are tracked as managed by `oat status` and `oat init`, not as strays.
50
+ - Codex project-scope subagent sync writes `.codex/config.toml` and `.codex/agents/*.toml` at command layer after path-mapping sync. Every generated project Codex variant and registration is repository-owned, version-controlled provider output. OAT provides no automatic ignore mechanism for this project output; collaborators review and commit it like other project configuration.
51
51
  - Codex aggregate config drift is reported via sync/status extension metadata (`aggregateConfigHash`); it is not persisted as a separate manifest schema entry.
52
- - Codex user-scope role generation remains intentionally deferred in this release.
52
+ - Codex user-config materialization writes user-owned implementer and reviewer roles under the user provider directory, `~/.codex`; it does not write those roles into the repository.
53
53
 
54
54
  ## Non-interop namespaces in the same CLI
55
55
 
@@ -68,7 +68,9 @@ Notable commands introduced in the current CLI surface:
68
68
  - `oat repo archive sync [project-name]` - hydrate archived project snapshots from the configured repo-scoped S3 archive into `.oat/projects/archived/`. The old `oat project archive sync` path remains as a deprecated shim.
69
69
  - `oat project validate-plan --project-path <path>` - validates `oat_plan_parallel_groups` metadata in `plan.md`; exits non-zero on invalid. See [Implementation Execution](../workflows/projects/implementation-execution.md#validating-plan-metadata).
70
70
  - `oat project set-mode` — deprecated no-op. Execution mode is no longer user-selectable; emits a deprecation warning and preserves the `--json` contract.
71
- - `oat gate review <prompt...>` - run a stateful OAT review through the target registry, parse the produced review artifact, and exit nonzero for configured blocking findings; produced gate reviews use `oat_review_invocation: gate` and still require `oat-project-review-receive` handoff before they are dispositioned. With `--json`, the result envelope on exit is the canonical completion signal `status` (`ok` | `blocked` | `review_failed` | `artifact_validation_failed`), `runId`, `generatedAt`, `artifactPath` so orchestrators should read it rather than poll the filesystem. Runs standalone (e.g. `--review-scope final`), not only inside `oat-project-implement`. See [Workflow Gates → Gate completion signal](../cli-utilities/workflow-gates.md#gate-completion-signal).
71
+ - `oat gate review <prompt...>` - run a stateful OAT review through the target registry, parse the produced review artifact, and exit nonzero for configured blocking findings. With `--json`, the result envelope on exit is the canonical completion signal: `status` is `ok` | `blocked` | `review_failed` | `artifact_validation_failed` | `targeting_correlation_failed`, alongside `runId`, `generatedAt`, and `artifactPath` when available. Invoke `oat-project-review-receive` only when all three conditions hold: `status` is `ok` or `blocked`, `receiveEligible` is `true`, and `handoff` is non-null. For `artifact_validation_failed`, correct the artifact and rerun the gate for successful revalidation before receive. `targeting_correlation_failed` sets `receiveEligible: false`; do not run review-receive even if it reports an artifact path. Orchestrators should read the structured result rather than poll the filesystem. The command runs standalone (for example, `--review-scope final`), not only inside `oat-project-implement`. See [Workflow Gates → Gate completion signal](../cli-utilities/workflow-gates.md#gate-completion-signal).
72
+ - `oat gate target set <id> --invocation-model <model|provider-default> --invocation-reasoning-effort <effort|provider-default>` - persist optional configured invocation metadata alongside an exec target without inferring it from the target command.
73
+ - `oat gate target list --json` - inspect resolved gate targets without selecting or executing a reviewer. Each entry reports its config origin, whether it is explicitly configured and enabled, current availability, and normalized configured invocation values (`unknown` when omitted).
72
74
  - `oat gate cross-provider-exec <prompt...>` - choose an available exec target while avoiding the current runtime by default, then run the prompt with the chosen target's configured base command and exit with the child status.
73
75
 
74
76
  ## `oat config` surface flags
@@ -93,32 +93,33 @@ Legacy `.oat/active-project` / `.oat/projects-root` / `.oat/active-idea` files m
93
93
 
94
94
  Current schema keys:
95
95
 
96
- | Key | Type | Default | Description |
97
- | ------------------------------------------- | ---------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
- | `version` | `number` | `1` | Schema version |
99
- | `worktrees.root` | `string` | `".worktrees"` | Root directory for git worktrees (repo-relative or absolute) |
100
- | `projects.root` | `string` | `".oat/projects/shared"` | Default root directory for OAT projects |
101
- | `localPaths` | `string[]` | - | Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via `oat local add/remove`. |
102
- | `documentation.root` | `string` | - | Root directory containing documentation source files (e.g., `apps/docs/docs`) |
103
- | `documentation.tooling` | `string` | - | Documentation framework identifier (`mkdocs` or `fumadocs`) |
104
- | `documentation.config` | `string` | - | Path to the documentation framework config file (e.g., `mkdocs.yml`, `next.config.js`) |
105
- | `documentation.index` | `string` | - | Path to the docs surface entry point (e.g., `index.md` for Fumadocs, `mkdocs.yml` for MkDocs). Set by `oat docs init` and updated by `oat docs generate-index`. |
106
- | `documentation.requireForProjectCompletion` | `boolean` | `false` | When `true`, OAT project completion gates require documentation to be updated |
107
- | `git.defaultBranch` | `string` | `"main"` | Default branch for PR creation. Auto-detected during `oat init` via `gh repo view` or `origin/HEAD`. Used by `oat-project-pr-final` and `oat-project-pr-progress`. |
108
- | `workflow.autoReviewAtHillCheckpoints` | `boolean` | unset | When `true`, completing a HiLL checkpoint automatically runs the extra lifecycle review. Does not control Tier 1 per-phase `oat-reviewer` gates. Can be overridden per-project via `oat_auto_review_at_hill_checkpoints` in `plan.md` frontmatter. Legacy `autoReviewAtCheckpoints` remains a fallback. |
109
- | `workflow.dispatchPolicy.mode` | `string` | unset | Dispatch policy mode: `managed` lets OAT select model/effort controls; `inherit` leaves controls to the host/provider defaults. |
110
- | `workflow.dispatchPolicy.policy` | `string` | unset | Managed dispatch policy: `economy`, `balanced`, `high`, `frontier`, or `uncapped`. Capped policies compile to provider targets; `uncapped` keeps OAT-managed preferred selection without provider caps. `inherit` mode is separate and leaves controls to the host/provider. |
111
- | `workflow.dispatchCeiling.preset` | `string` | unset | Legacy compatibility preset for capped managed policy setup (`balanced`, `maximum`, `cost-conscious`). `maximum` maps to `high`; `cost-conscious` maps to `economy`. |
112
- | `workflow.dispatchCeiling.providers.codex` | `string` | unset | Legacy concrete Codex capped target (`low`, `medium`, `high`, or `xhigh`). New managed Codex dispatch resolves explicit model+effort targets to materialized role names; provider default effort is informational only for explicit inherit/default behavior or base/unpinned fallback paths. |
113
- | `workflow.dispatchCeiling.providers.claude` | `string` | unset | Legacy concrete Claude capped target (`haiku`, `sonnet`, `opus`, or `fable`). Claude has no separate per-dispatch effort axis. The flat keys `workflow.dispatchCeiling.codex` and `workflow.dispatchCeiling.claude` were removed (no migration). |
114
- | `workflow.gates.skills` | `object` | unset | Per-skill final gate config keyed by skill name. Managed with `oat gate set/unset`; gate-aware skills declare `oat_gateable: true`. |
115
- | `workflow.gates.execTargets` | `object` | built-ins | Cross-runtime exec target registry keyed by opaque target id. Managed with `oat gate target set/unset`; built-ins cover Codex, Claude, and Cursor defaults. |
116
- | `archive.s3Uri` | `string` | - | Base S3 URI for repo-scoped archived project sync, for example `s3://bucket/oat-archive` |
117
- | `archive.s3SyncOnComplete` | `boolean` | `false` | When `true`, `oat-project-complete` uploads the archived project to the configured S3 archive after local archive succeeds |
118
- | `archive.summaryExportPath` | `string` | - | Repo-relative directory where completion exports `summary.md` as a dated snapshot like `20260401-<project-name>.md` for durable tracked reference |
119
- | `archive.wrapUpExportPath` | `string` | - | Repo-relative directory where `oat-wrap-up` writes dated reports like `20260413-wrap-up-past-week.md`; when unset, the skill falls back to `.oat/repo/reference/wrap-ups/` |
120
- | `archive.awsProfile` | `string` | - | Optional AWS named profile forwarded as `AWS_PROFILE` to every `aws` invocation in archive flows (`oat-project-complete` S3 sync, `oat repo archive sync`). Overrides ambient shell `AWS_PROFILE` / `AWS_DEFAULT_PROFILE` when set. |
121
- | `archive.awsRegion` | `string` | - | Optional AWS region forwarded as `AWS_REGION` to every `aws` invocation in archive flows. Overrides ambient shell `AWS_REGION` / `AWS_DEFAULT_REGION` when set. |
96
+ | Key | Type | Default | Description |
97
+ | ---------------------------------------------------------- | -------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
+ | `version` | `number` | `1` | Schema version |
99
+ | `worktrees.root` | `string` | `".worktrees"` | Root directory for git worktrees (repo-relative or absolute) |
100
+ | `projects.root` | `string` | `".oat/projects/shared"` | Default root directory for OAT projects |
101
+ | `localPaths` | `string[]` | - | Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via `oat local add/remove`. |
102
+ | `documentation.root` | `string` | - | Root directory containing documentation source files (e.g., `apps/docs/docs`) |
103
+ | `documentation.tooling` | `string` | - | Documentation framework identifier (`mkdocs` or `fumadocs`) |
104
+ | `documentation.config` | `string` | - | Path to the documentation framework config file (e.g., `mkdocs.yml`, `next.config.js`) |
105
+ | `documentation.index` | `string` | - | Path to the docs surface entry point (e.g., `index.md` for Fumadocs, `mkdocs.yml` for MkDocs). Set by `oat docs init` and updated by `oat docs generate-index`. |
106
+ | `documentation.requireForProjectCompletion` | `boolean` | `false` | When `true`, OAT project completion gates require documentation to be updated |
107
+ | `git.defaultBranch` | `string` | `"main"` | Default branch for PR creation. Auto-detected during `oat init` via `gh repo view` or `origin/HEAD`. Used by `oat-project-pr-final` and `oat-project-pr-progress`. |
108
+ | `workflow.autoReviewAtHillCheckpoints` | `boolean` | unset | When `true`, completing a HiLL checkpoint automatically runs the extra lifecycle review. Does not control Tier 1 per-phase `oat-reviewer` gates. Can be overridden per-project via `oat_auto_review_at_hill_checkpoints` in `plan.md` frontmatter. Legacy `autoReviewAtCheckpoints` remains a fallback. |
109
+ | `workflow.dispatchPolicy.mode` | `string` | unset | Dispatch policy mode: `managed` lets OAT select model/effort controls; `inherit` leaves controls to the host/provider defaults. |
110
+ | `workflow.dispatchPolicy.policy` | `string` | unset | Managed dispatch policy: `economy`, `balanced`, `high`, `frontier`, or `uncapped`. Capped policies compile to provider targets; `uncapped` keeps OAT-managed preferred selection without provider caps. `inherit` mode is separate and leaves controls to the host/provider. |
111
+ | `workflow.dispatchCeiling.preset` | `string` | unset | Legacy compatibility preset for capped managed policy setup (`balanced`, `maximum`, `cost-conscious`). `maximum` maps to `high`; `cost-conscious` maps to `economy`. |
112
+ | `workflow.dispatchCeiling.providers.<provider>` | `object` or legacy scalar | unset | Reusable provider candidate ladder. The canonical shape maps `economy`, `balanced`, `high`, and `frontier` to ordered candidate cells; project and phase state record only a named maximum over that ladder. |
113
+ | `workflow.dispatchCeiling.providers.<provider>.<tier>` | `{ candidates: [...] }` | unset | One ordered candidate cell. Codex entries carry exact `model` plus `effort` and resolve to materialized roles; Claude entries carry a model; Cursor strings remain opaque and pass to Cursor byte-for-byte. The final candidate defines that tier's reviewer ceiling. |
114
+ | `workflow.dispatchCeiling.providers.{codex,claude,cursor}` | `string`, route, or target | unset | Legacy compatibility input normalized to a one-candidate ladder. New configuration should use tiered candidate cells. The flat keys `workflow.dispatchCeiling.codex` and `workflow.dispatchCeiling.claude` were removed without migration. |
115
+ | `workflow.gates.skills` | `object` | unset | Per-skill final gate config keyed by skill name. Managed with `oat gate set/unset`; gate-aware skills declare `oat_gateable: true`. |
116
+ | `workflow.gates.execTargets` | `object` | built-ins | Cross-runtime exec target registry keyed by opaque target id. Managed with `oat gate target set/unset`; built-ins cover Codex, Claude, and Cursor defaults. |
117
+ | `archive.s3Uri` | `string` | - | Base S3 URI for repo-scoped archived project sync, for example `s3://bucket/oat-archive` |
118
+ | `archive.s3SyncOnComplete` | `boolean` | `false` | When `true`, `oat-project-complete` uploads the archived project to the configured S3 archive after local archive succeeds |
119
+ | `archive.summaryExportPath` | `string` | - | Repo-relative directory where completion exports `summary.md` as a dated snapshot like `20260401-<project-name>.md` for durable tracked reference |
120
+ | `archive.wrapUpExportPath` | `string` | - | Repo-relative directory where `oat-wrap-up` writes dated reports like `20260413-wrap-up-past-week.md`; when unset, the skill falls back to `.oat/repo/reference/wrap-ups/` |
121
+ | `archive.awsProfile` | `string` | - | Optional AWS named profile forwarded as `AWS_PROFILE` to every `aws` invocation in archive flows (`oat-project-complete` S3 sync, `oat repo archive sync`). Overrides ambient shell `AWS_PROFILE` / `AWS_DEFAULT_PROFILE` when set. |
122
+ | `archive.awsRegion` | `string` | - | Optional AWS region forwarded as `AWS_REGION` to every `aws` invocation in archive flows. Overrides ambient shell `AWS_REGION` / `AWS_DEFAULT_REGION` when set. |
122
123
 
123
124
  All `documentation.*` keys are managed via `oat config get/set` and are set automatically by `oat docs init`.
124
125
  The `git.defaultBranch` key is auto-detected during `oat init` and can be overridden via `oat config set git.defaultBranch <branch>`.
@@ -31,6 +31,28 @@ Mode-sensitive notes:
31
31
  - `references/imported-plan.md`: preserved source plan for import mode
32
32
  - `references/split-plan.json`: persisted split plan for a coordination parent, used as the durable resume source when `oat-project-split` is interrupted
33
33
 
34
+ ### Gate review frontmatter
35
+
36
+ Review artifacts produced by `oat gate review` use the normal review fields plus
37
+ an exact copy of the gate-owned configured invocation:
38
+
39
+ ```yaml
40
+ oat_review_invocation: gate
41
+ oat_project: .oat/projects/shared/example
42
+ oat_gate_run_id: 00000000-0000-0000-0000-000000000000
43
+ oat_gate_target: codex-sol-max
44
+ oat_gate_runtime: codex
45
+ oat_invocation_model: gpt-5.6-sol
46
+ oat_invocation_reasoning_effort: max
47
+ oat_invocation_source: exec-target-config
48
+ ```
49
+
50
+ `oat_invocation_model` and `oat_invocation_reasoning_effort` may be
51
+ `provider-default` when OAT deliberately leaves a control to the provider, or
52
+ `unknown` when the target does not declare it. These fields are configured
53
+ invocation metadata, not runtime-confirmed or self-reported model identity.
54
+ Manual and auto review artifacts do not require the gate-only fields.
55
+
34
56
  ## Contract
35
57
 
36
58
  Artifacts are the project system of record; automation and routing should derive from these files, not memory.
@@ -75,7 +97,7 @@ Each inner array is a group of phases that execute concurrently in their own wor
75
97
  - Each group must contain **2 or more** phases — singleton groups are rejected.
76
98
  - Every phase ID must exist in the plan body.
77
99
  - No phase may appear in more than one group.
78
- - Parallelism is only honored at Tier 1 (native subagents). Tier 2 degrades parallel groups to sequential inline execution.
100
+ - Parallelism is only honored at Tier 1 (native subagents). Tier 2 degrades parallel groups to sequential target-preserving execution, not unconditional inline review. Concrete managed Claude and Cursor reviewers retain the exact resolver-returned `dispatchArgs.model` in the actual invocation and every retry; Codex retains its exact role or pinned child. Inline review requires verified equivalent host controls or an explicit inherit/default or managed-uncapped base-role exception, and otherwise blocks.
79
101
 
80
102
  **Authoring responsibility:**
81
103
 
@@ -90,6 +112,14 @@ Before dispatching, `oat-project-implement` invokes `oat project validate-plan -
90
112
 
91
113
  Enable an optional, non-pausing external review gate that runs after each selected phase's standard reviewer passes and its bookkeeping is committed:
92
114
 
115
+ Planning offers this setting after stable phase IDs exist and before the plan
116
+ artifact review. The read-only target probe qualifies only an explicitly
117
+ configured, enabled, and available target, then offers all phases, selected
118
+ phases, or disabled. An explicit `oat_phase_review_gate` value from a resumed or
119
+ imported plan is preserved unchanged without re-prompting. If the probe fails,
120
+ no target qualifies, the run is non-interactive, or the user declines, planning
121
+ leaves phase review disabled.
122
+
93
123
  ```yaml
94
124
  oat_phase_review_gate:
95
125
  enabled: true