@open-agent-toolkit/cli 0.3.6 → 0.3.8

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/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/configuration.md +38 -18
  3. package/assets/docs/cli-utilities/workflow-gates.md +37 -0
  4. package/assets/docs/contributing/updating-model-guidance.md +6 -6
  5. package/assets/docs/provider-sync/commands.md +6 -0
  6. package/assets/docs/provider-sync/providers.md +24 -0
  7. package/assets/docs/provider-sync/scope-and-surface.md +2 -0
  8. package/assets/docs/reference/cli-reference.md +2 -1
  9. package/assets/docs/workflows/projects/autonomy.md +1 -1
  10. package/assets/docs/workflows/projects/dispatch-ceiling.md +26 -20
  11. package/assets/docs/workflows/projects/evidence-layers.md +5 -1
  12. package/assets/docs/workflows/projects/retro.md +7 -0
  13. package/assets/public-package-versions.json +4 -4
  14. package/assets/skills/oat-agent-instructions-analyze/SKILL.md +1 -1
  15. package/assets/skills/oat-agent-instructions-analyze/scripts/resolve-providers.sh +17 -6
  16. package/assets/skills/oat-dispatch-subagents/SKILL.md +1 -1
  17. package/assets/skills/oat-dispatch-subagents/references/managed-claude-example.json +387 -0
  18. package/assets/skills/oat-dispatch-subagents/references/record-schema.md +75 -0
  19. package/assets/skills/oat-doctor/SKILL.md +2 -2
  20. package/assets/skills/oat-project-autonomous/SKILL.md +2 -2
  21. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  22. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  23. package/assets/skills/oat-project-implement/SKILL.md +1 -1
  24. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +24 -22
  25. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  26. package/assets/skills/oat-project-import-plan/SKILL.md +4 -4
  27. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +1 -1
  28. package/assets/skills/oat-project-plan/SKILL.md +4 -4
  29. package/assets/skills/oat-project-plan-writing/SKILL.md +4 -4
  30. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  31. package/assets/skills/oat-project-quick-start/SKILL.md +4 -4
  32. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  33. package/assets/skills/oat-project-retro/SKILL.md +70 -6
  34. package/assets/skills/oat-project-review-provide/SKILL.md +3 -1
  35. package/assets/skills/oat-project-review-provide-remote/SKILL.md +3 -1
  36. package/dist/agents/canonical/resolve.d.ts +6 -4
  37. package/dist/agents/canonical/resolve.d.ts.map +1 -1
  38. package/dist/agents/canonical/resolve.js +6 -4
  39. package/dist/commands/config/index.d.ts.map +1 -1
  40. package/dist/commands/config/index.js +210 -28
  41. package/dist/commands/gate/index.d.ts.map +1 -1
  42. package/dist/commands/gate/index.js +51 -2
  43. package/dist/commands/gate/review-verdict.d.ts +22 -0
  44. package/dist/commands/gate/review-verdict.d.ts.map +1 -1
  45. package/dist/commands/gate/review-verdict.js +111 -0
  46. package/dist/commands/project/dispatch/canonical-role.d.ts +33 -0
  47. package/dist/commands/project/dispatch/canonical-role.d.ts.map +1 -0
  48. package/dist/commands/project/dispatch/canonical-role.js +114 -0
  49. package/dist/commands/project/dispatch/index.d.ts.map +1 -1
  50. package/dist/commands/project/dispatch/index.js +3 -1
  51. package/dist/commands/project/dispatch/record.d.ts.map +1 -1
  52. package/dist/commands/project/dispatch/record.js +146 -4
  53. package/dist/commands/sync/apply.d.ts.map +1 -1
  54. package/dist/commands/sync/apply.js +28 -21
  55. package/dist/commands/tools/shared/sync-evidence.d.ts.map +1 -1
  56. package/dist/commands/tools/shared/sync-evidence.js +32 -5
  57. package/dist/config/oat-config.d.ts +8 -0
  58. package/dist/config/oat-config.d.ts.map +1 -1
  59. package/dist/config/oat-config.js +116 -1
  60. package/dist/engine/compute-plan.d.ts.map +1 -1
  61. package/dist/engine/compute-plan.js +31 -3
  62. package/dist/providers/claude/dispatch-envelope.d.ts +53 -0
  63. package/dist/providers/claude/dispatch-envelope.d.ts.map +1 -1
  64. package/dist/providers/claude/dispatch-envelope.js +324 -48
  65. package/dist/providers/claude/rule-transform.js +1 -1
  66. package/dist/providers/copilot/rule-transform.js +1 -1
  67. package/dist/providers/cursor/rule-transform.js +1 -1
  68. package/dist/providers/identity/absolute-paths.d.ts +13 -0
  69. package/dist/providers/identity/absolute-paths.d.ts.map +1 -1
  70. package/dist/providers/identity/absolute-paths.js +27 -14
  71. package/dist/providers/identity/generic-dispatch-record.d.ts +212 -0
  72. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -1
  73. package/dist/providers/identity/generic-dispatch-record.js +78 -19
  74. package/dist/providers/identity/oat-dispatch-record.d.ts +5 -0
  75. package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -1
  76. package/dist/providers/identity/oat-dispatch-record.js +11 -2
  77. package/dist/providers/shared/registry.d.ts +6 -0
  78. package/dist/providers/shared/registry.d.ts.map +1 -1
  79. package/dist/providers/shared/registry.js +30 -0
  80. package/dist/rules/canonical/parse.d.ts.map +1 -1
  81. package/dist/rules/canonical/parse.js +38 -3
  82. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "oatVersion": "0.3.6"
3
+ "oatVersion": "0.3.8"
4
4
  }
@@ -51,7 +51,7 @@ What each command is for:
51
51
 
52
52
  - `oat config list` shows the currently resolved command-surface values for shared and repo-local keys.
53
53
  - `oat config get <key>` reads one supported key value.
54
- - `oat config set <key> <value>` updates supported shared or repo-local keys.
54
+ - `oat config set <key> <value>` updates supported shared or repo-local keys. Writes to the shared `.oat/config.json` keep the file's existing key order, and a write that would not change any value leaves the file byte-identical.
55
55
  - `oat config unset <key>` removes a supported key from one surface, using the same `--shared`/`--local`/`--user` flags and per-key restrictions as `set`. The resolved value then falls back to the next surface down, or to the built-in default. A key the surface does not hold exits 0 as already-unset (`--json` adds a `removed` boolean to tell the two apart). Unknown keys, lifecycle state, `tools.*` pack intent, aggregate read views, read-only remote-policy structure, and environment-shadowed keys with nothing stored are refused with exit 1 — see [CLI Reference](../reference/cli-reference.md#oat-config-surface-flags).
56
56
  - `oat config describe` shows the supported config catalog across shared repo, repo-local, user, and sync/provider surfaces.
57
57
  - `oat config describe <key>` shows file, scope, default, mutability, owning command, and description for one key. A deprecated key also prints `Deprecated: prefer <successor>`, and `--json` carries the same fact as a `deprecated` object (`supersededBy`, plus `note` and `legacyValues` where they apply).
@@ -125,6 +125,20 @@ and purpose field grants intersect to narrow outbound fields. No configured
125
125
  layer bypasses hard approval floors or current caller-owned authority evidence;
126
126
  missing, stale, or mismatched evidence fails closed.
127
127
 
128
+ The shared `pjm.remote` tree is closed. An unknown key, a non-object where an
129
+ object is expected, or a wrong-typed leaf (for example `authority.default: 5`,
130
+ a string `schemaVersion`, or a number, boolean, array, object, or `null` where a
131
+ string is expected) makes every shared config read fail closed with an
132
+ `Invalid PJM remote policy structure` error. The error names each offending
133
+ field path: unknown keys by path alone, and wrong-typed values by path and
134
+ structure type, never by value. This includes ordinary reads such as
135
+ `oat config get` and `oat config unset` of an unrelated `pjm.remote` child: the
136
+ `oat config` subcommands report the error and exit with code `1`, and `unset`
137
+ leaves the file byte-identical. Repair the named fields by editing
138
+ `.oat/config.json` by hand. A well-typed but unrecognized string is not
139
+ rejected: it keeps its documented coercion to `none` for descriptions and
140
+ `read-only` for authority.
141
+
128
142
  Tool-pack intent example:
129
143
 
130
144
  ```bash
@@ -387,14 +401,14 @@ preference. For the full model, see
387
401
 
388
402
  ### Config keys
389
403
 
390
- | Key | Values | Purpose |
391
- | ------------------------------------------------------ | ----------------------------------------------------- | --------------------------------------------------------------------------------------- |
392
- | `workflow.dispatchPolicy.mode` | `managed`, `inherit` | `managed` lets OAT select exact candidates; `inherit` leaves controls to the host |
393
- | `workflow.dispatchPolicy.policy` | `economy`, `balanced`, `high`, `frontier`, `uncapped` | Default named maximum or explicit managed uncapped state |
394
- | `workflow.dispatchCeiling.providers.<provider>` | tier map or legacy bare value | Reusable provider candidate column |
395
- | `workflow.dispatchCeiling.providers.<provider>.<tier>` | `candidates` cell, route, or legacy bare value | One named tier in the provider ladder |
396
- | `workflow.dispatchCeiling.recommendationVersion` | string | Version written by `oat config adopt dispatch-matrix` for recommendation drift tracking |
397
- | `workflow.dispatchCeiling.preset` | `balanced`, `maximum`, `cost-conscious` | Legacy policy setup alias |
404
+ | Key | Values | Purpose |
405
+ | ------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------------------------------ |
406
+ | `workflow.dispatchPolicy.mode` | `managed`, `inherit` | `managed` lets OAT select exact candidates; `inherit` leaves controls to the host |
407
+ | `workflow.dispatchPolicy.policy` | `economy`, `balanced`, `high`, `frontier`, `uncapped` | Default named maximum or explicit managed uncapped state |
408
+ | `workflow.dispatchCeiling.providers.<provider>` | tier map or legacy bare value | Reusable provider candidate column |
409
+ | `workflow.dispatchCeiling.providers.<provider>.<tier>` | `candidates` cell, route, or legacy bare value | One named tier in the provider ladder |
410
+ | `workflow.dispatchCeiling.recommendationVersion` | string | Bundle version last written by adoption; does not prove the effective ladder matches |
411
+ | `workflow.dispatchCeiling.preset` | `balanced`, `maximum`, `cost-conscious` | Legacy policy setup alias |
398
412
 
399
413
  ### Adopt a complete ladder
400
414
 
@@ -406,14 +420,20 @@ oat config adopt dispatch-matrix --local
406
420
  oat config adopt dispatch-matrix --user
407
421
  ```
408
422
 
409
- Adoption fills missing provider/tier cells and preserves explicit existing
410
- values. Planning shows the complete bundled recommendation before asking for
411
- this scope, then rechecks the effective ladder. If explicit cells still leave
412
- the ladder incomplete, readiness blocks; OAT does not overwrite them.
413
- `workflow.dispatchCeiling.recommendationVersion` describes only the bundled
414
- recommendation that was adopted. Dispatch targets, structured notices, and
415
- runtime disclosure come from the effective ladder after explicit cells have
416
- been preserved.
423
+ Adoption replaces populated cells from the bundled recommendation in the
424
+ chosen scope, fills missing cells, and keeps extra custom tier cells when
425
+ the bundled provider remains a tier map. A bundled provider-level scalar
426
+ replaces the whole provider, including its custom tiers. It warns about
427
+ replaced and removed cells and reports their paths in human and JSON output. Preview with
428
+ `oat config adopt dispatch-matrix --user --dry-run` before writing user defaults.
429
+ Add `--keep-existing` when you want only missing cells filled; a fill-only run
430
+ with no missing cells leaves the config and version unchanged. If it fills
431
+ missing cells while preserving differences, it leaves the version unchanged. Planning uses
432
+ `--keep-existing` after showing the complete bundle and asking for the owning
433
+ scope. If the resulting effective ladder remains incomplete, readiness blocks.
434
+ The version records the bundle last written by adoption, not whether the
435
+ effective ladder matches it. Dispatch targets, structured notices, and runtime
436
+ disclosure come from the effective ladder.
417
437
 
418
438
  A recommended Fable target may require model access from the executing
419
439
  provider. The adopting organization is responsible for confirming its
@@ -700,7 +720,7 @@ Workflow preference keys live under the `workflow.*` namespace:
700
720
  - `workflow.dispatchCeiling.preset` — legacy compatibility alias (`balanced`, `maximum`, or `cost-conscious`) for capped managed policy setup.
701
721
  - `workflow.dispatchCeiling.providers.<provider>` — dispatch matrix provider column or legacy bare provider target.
702
722
  - `workflow.dispatchCeiling.providers.<provider>.<tier>` — one matrix cell for `economy`, `balanced`, `high`, or `frontier`.
703
- - `workflow.dispatchCeiling.recommendationVersion` — version of the adopted recommended matrix.
723
+ - `workflow.dispatchCeiling.recommendationVersion` — bundle version last written by adoption; not an effective-ladder parity indicator.
704
724
  - `workflow.gates.skills` / `workflow.gates.execTargets` — structured per-skill final gate commands and exec-target registry. Use `oat gate set`, `oat gate target set`, `oat gate review`, and `oat gate cross-provider-exec`; do not use `oat config set` for these objects.
705
725
  - `workflow.gateTimeouts.code` / `workflow.gateTimeouts.artifact` — validated default gate-review budgets in milliseconds. Both resolve through `local > shared > user`.
706
726
 
@@ -236,6 +236,35 @@ model that ran, and the reviewer must not replace them with self-identification.
236
236
  The CLI compares the copied values with its gate-owned record before it applies
237
237
  the severity threshold.
238
238
 
239
+ The gate frontmatter is also the authority for the artifact's dispatch audit
240
+ line. The reviewer's resolver stamp describes the project reviewer policy, so
241
+ gate-originated artifacts label it as the policy view:
242
+
243
+ ```markdown
244
+ **Dispatch audit (policy view):** `Dispatch: scope=p01 action=review role=reviewer ... target=oat-reviewer-gpt-6-sol-high`
245
+ ```
246
+
247
+ The gate reads reviewer stamps (`action=review role=reviewer`) from audit lines
248
+ anywhere in the artifact body except finding sections: `## Findings` with its
249
+ subsections, and any `### Critical`, `### High`, `### Medium`, or `### Low`
250
+ section. Reviewers place these lines in the metadata block before the first
251
+ level-two (`##`) heading and in sections such as `## Dispatch Audit`,
252
+ `## Dispatch Metadata`, `## Review Dispatch Audit`, `## Review Scope`, and
253
+ `## Dispatch Evidence`. An audit line is an optional list marker, an optional
254
+ label ending in `:`, and a `Dispatch:` stamp that is either bare or wrapped in
255
+ one backtick pair, which may be followed only by punctuation or one
256
+ parenthetical such as `(resolver)`. Fenced code blocks, table rows, and prose
257
+ that quotes a stamp are ignored, including a labeled line where other prose
258
+ follows the closing backtick. To cite a stamp as evidence, put it in a fenced
259
+ block, a table, or a finding. A stamp whose label contains
260
+ `policy view` is not checked. Every other audit stamp must agree with the
261
+ frontmatter: its `target` equals `oat_gate_target`, and, when
262
+ `oat_invocation_reasoning_effort` is a concrete effort (not `unknown`,
263
+ `provider-default`, or `not-applicable`), its `effort_axis` equals
264
+ `selected:<effort>`. A disagreeing stamp fails with
265
+ `status: artifact_validation_failed` and cause `gate_dispatch_audit_mismatched`.
266
+ Artifacts without an audit stamp are unaffected.
267
+
239
268
  ### Review producer identity
240
269
 
241
270
  Dynamic planning workflows can declare their current parent model to a review
@@ -329,6 +358,14 @@ self-report are not interchangeable. The human report is rendered from the
329
358
  versioned object, and any parseable `Dispatch:` compatibility line is derived
330
359
  from that same report rather than rebuilt from target IDs or model names.
331
360
 
361
+ Because the resolver stamp and the gate invocation can name different targets
362
+ and efforts, a gate artifact writes the resolver stamp under the
363
+ `**Dispatch audit (policy view):**` label (see
364
+ [Review gates](#review-gates) above for the agreement rule). An unlabeled stamp that disagrees with the frontmatter fails with
365
+ `gate_dispatch_audit_mismatched`. When an older installed
366
+ `oat-project-review-provide` wrote the unlabeled line, refresh installed skills
367
+ with `oat tools update` and rerun the gate instead of editing findings.
368
+
332
369
  ### Review project resolution and corroboration
333
370
 
334
371
  `--project <path-or-name>` is a declaration. OAT normalizes the declared path
@@ -108,11 +108,11 @@ Follow [Contributing Code](code.md) for the current validation and PR workflow.
108
108
 
109
109
  ## Adoption Is Separate
110
110
 
111
- The bundled ladder is a default for missing provider/tier cells. `oat config
112
- adopt dispatch-matrix --shared`, `--local`, or `--user` fills missing cells but
113
- does not replace populated explicit cells, even when its recommendation version
114
- changes. A user who wants the new model ordering must edit those cells or
115
- clear and re-adopt them deliberately. The active project's named ceiling is a
116
- separate policy in its `state.md`; a model update must not silently change it.
111
+ A bundled ladder update does not mutate adopted user or repository config.
112
+ `oat config adopt dispatch-matrix --shared`, `--local`, or `--user` replaces
113
+ bundled cells in the chosen scope, with a warning and a `--dry-run` preview;
114
+ extra custom cells remain. Add `--keep-existing` to fill only missing cells.
115
+ The active project's named ceiling is a separate policy in its `state.md`;
116
+ a model update must not silently change it.
117
117
  See [Dispatch Policy](../workflows/projects/dispatch-ceiling.md#ownership-and-adoption)
118
118
  for config precedence and examples.
@@ -71,6 +71,12 @@ Key behavior:
71
71
  symlinks retain their existing behavior. Explicit `symlink` and `copy` remain
72
72
  per-entry modes; `oat sync` does not add a `--strategy` option.
73
73
  - Provider enable/disable honored via sync config
74
+ - Invalid canonical rules stop the run before anything is applied. Sync
75
+ checks every rule first and fails once with a message that names each
76
+ invalid rule file exactly once, even though several provider transforms
77
+ read the same rule, so one run surfaces every file to fix. See
78
+ [Canonical rule frontmatter](providers.md#canonical-rule-frontmatter) for
79
+ the accepted `alwaysApply: true` alias.
74
80
  - Cursor skills are native-read from canonical `.agents/skills`; sync does not
75
81
  create `.cursor/skills` mirrors
76
82
  - Copilot skills are native-read from canonical `.agents/skills`; sync does not
@@ -89,6 +89,10 @@ oat config adopt dispatch-matrix --local
89
89
  oat config adopt dispatch-matrix --user
90
90
  ```
91
91
 
92
+ These commands replace bundled cells in the chosen scope and warn about
93
+ replacements. Add `--dry-run` to preview or `--keep-existing` to fill only
94
+ missing cells.
95
+
92
96
  Project-config candidates materialize into the tracked, version-controlled
93
97
  project `.codex` and `.cursor` views. User-config candidates materialize under
94
98
  `~/.codex` and `~/.cursor`. OAT does not auto-ignore project output or create
@@ -182,6 +186,26 @@ current-session catalog probe is still not proof of provider visibility.
182
186
  - Codex user-scope sync materializes user-config custom roles under `~/.codex`; project-config and supported-catalogue output remains project-scoped and version controlled
183
187
  - Cursor user-scope sync materializes user-config variants under `~/.cursor/agents`; project-config and supported-catalogue output remains project-scoped and version controlled
184
188
 
189
+ ## Canonical rule frontmatter
190
+
191
+ Canonical rules in `.agents/rules/*.md` declare `activation` as one of
192
+ `always`, `glob`, `agent-requested`, or `manual`; `globs` is valid only with
193
+ `activation: glob`.
194
+
195
+ Third-party installers sometimes write Cursor-style rules straight into
196
+ `.agents/rules/` (for example `argent init`, reported in GitHub issue #316).
197
+ OAT accepts that shape through one narrow alias:
198
+
199
+ - `alwaysApply: true` with no `activation` is read as `activation: always`.
200
+ - Under that alias a null or empty `globs` value is ignored, and a non-empty
201
+ `globs` value is an error naming the file, because canonical rules keep globs
202
+ only for `activation: glob`.
203
+ - An explicit `activation` always wins over `alwaysApply`.
204
+ - `alwaysApply: false`, or any value other than `true`, without `activation`
205
+ stays an activation error that names the file.
206
+
207
+ Every canonical rule parse error names the repository-relative rule file.
208
+
185
209
  ## Adoption model
186
210
 
187
211
  - Stray adoption is available in `oat init` and `oat status`.
@@ -45,6 +45,8 @@ Rules are currently project-scoped canonical content. Unlike skills and agents,
45
45
  - `oat providers codex materialize`
46
46
  - `oat project dispatch record` (project-aware dispatch evidence only; never a
47
47
  provider launcher)
48
+ - `oat project dispatch canonical-role` (read-only; prints the
49
+ canonical-role-resolution event that `oat project dispatch record` accepts)
48
50
 
49
51
  ## Adjacent CLI commands (commonly used with provider interop)
50
52
 
@@ -153,7 +153,8 @@ Notable commands introduced in the current CLI surface:
153
153
  - `oat project complete-state <project-path>` - apply the canonical completed-state mutation to a project's `state.md`; used by `oat-project-complete` during lifecycle closeout
154
154
  - `oat project archive [project-path] [--project-recap-run <project-relative-path>] [--no-commit]` - archive a tracked project through the same local move, summary export, and configured S3 upload path used by completion. When omitted, the project path falls back to the active project. The optional recap path must identify a `project-recap` run inside the project's `explainers/` directory. Archive stages the selected complete package into `.oat/repo/reference/project-recaps/<YYYYMMDD-project-slug>/`, verifies every manifest-declared file byte, then atomically installs the export before deleting the active project. Existing destinations, incomplete inventory coverage, stale bytes, path escapes, and recipe mismatches fail without removing the active project. For synced projects, a configured S3 upload must succeed before terminal cleanup. Successful closeout makes `refs/oat/completed/<project>` authoritative, deletes the tracked JSON record and nested checkout, and leaves archive metadata sufficient for an idempotent recordless retry. With `--json`, the terminal receipt reports `completedRef`, `verifiedSourceSha`, whether `activeAliasDisposition` was `retained` or `removed`, whether `recordRetired` completed, and the parent `lifecycleCommit`. `--no-commit` is a manual/library-only option: for a synced project it still removes the checkout but deliberately leaves `lifecycleCommit` null. Never pass it through `oat-project-complete`, which requires that receipt.
155
155
  - `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.
156
- - `oat project dispatch record --event-file <json-file-or-dash> [--project <project-path>]` - validate one generic dispatch record plus its namespaced OAT evidence event, and persist it into the project's append-only `dispatch/` journal (optional; no lifecycle skill requires persistence). Omit `--project` to validate without persisting. Managed, effort-pinned Claude launches use the validation-only form before launch: the input carries `claudeLaunch` with the real resolver result, generated definition, and proposed payload, plus `recordBase` and `event`. The command validates their agreement and derives the configured invocation fields; callers cannot copy those fields into `recordBase`. Revision 1 is `dispatch/<request-id>.json` and every later revision is `dispatch/<request-id>@<NNNN>.json`; superseded revisions are never replaced or removed. The command validates and records evidence only — it never launches a provider. A `runtime-observation` event may carry either a finished `observation` or the provider `metadata` envelope (`provider`, `observedAt`, `entries`) to normalize, but not both. `entries` may be raw provider output: they are projected through the owning parser's allowlist, are never persisted, and both forms have their `match` derived from the record's configured invocation rather than trusted from the caller, with the observation's `provider` bound to the record's. With `--json`, the result adds `runtimeIdentity` with separate `configured` and `observed` objects plus a `match` of `matching`, `mismatching`, `not-comparable`, or `null`; observation is corroboration only and never overrides configured invocation. Error output is redacted on a best-effort basis; absolute paths in identity fields are rejected outright, while some prose forms (colon-prefixed, URL routes) can survive. See [Evidence Layers](../workflows/projects/evidence-layers.md).
156
+ - `oat project dispatch record --event-file <json-file-or-dash> [--project <project-path>]` - validate one generic dispatch record plus its namespaced OAT evidence event, and persist it into the project's append-only `dispatch/` journal (optional; no lifecycle skill requires persistence). Omit `--project` to validate without persisting. Managed, effort-pinned Claude launches use the validation-only form before launch: the input carries `claudeLaunch` with the real resolver result, generated definition, and proposed payload, plus `recordBase` and `event`. The command validates their agreement and derives the configured invocation fields; callers cannot copy those fields into `recordBase`. One validation run reports every violation across `claudeLaunch`, `recordBase`, and `event` in a single error message, one `stage path: message` line each; the `recordBase` cross-field rules run even when a required field is missing, checks that need a value that failed to parse are skipped and named on a final line, secret-shaped values and absolute paths are scrubbed from the message, and the exit code stays 1. A validated input per role is published at `.agents/skills/oat-dispatch-subagents/references/managed-claude-example.json`. Revision 1 is `dispatch/<request-id>.json` and every later revision is `dispatch/<request-id>@<NNNN>.json`; superseded revisions are never replaced or removed. The command validates and records evidence only — it never launches a provider. A `runtime-observation` event may carry either a finished `observation` or the provider `metadata` envelope (`provider`, `observedAt`, `entries`) to normalize, but not both. `entries` may be raw provider output: they are projected through the owning parser's allowlist, are never persisted, and both forms have their `match` derived from the record's configured invocation rather than trusted from the caller, with the observation's `provider` bound to the record's. With `--json`, the result adds `runtimeIdentity` with separate `configured` and `observed` objects plus a `match` of `matching`, `mismatching`, `not-comparable`, or `null`; observation is corroboration only and never overrides configured invocation. Error output is redacted on a best-effort basis; absolute paths in identity fields are rejected outright, while some prose forms (colon-prefixed, URL routes) can survive. See [Evidence Layers](../workflows/projects/evidence-layers.md).
157
+ - `oat project dispatch canonical-role --role <name> --request-id <id> --skill-dir <dir> [--json]` - resolve a canonical role through the loaded, user (`$HOME/.agents`), and project (`<repo>/.agents`) tiers and print the `canonical-role-resolution` event that `oat project dispatch record` accepts unchanged: redacted `canonicalPath` and `selectedPath` in the form `<loaded|user|project>/agents/<name>.md`, the role's `contentDigest`, and `candidateMisses`. `--skill-dir` is required because the loaded tier is derived from the loaded skill's directory; a missing or invalid directory exits 1 with a redacted error. An unknown role prints `missing` evidence with its recovery commands. Read-only; the dependency is the `workflows` pack.
157
158
  - `oat project validate-plan --project-path <path>` - validates `oat_plan_parallel_groups` metadata in `plan.md`; exits non-zero on invalid. Lite plans must contain exactly one phase, declare no parallel groups, and give every Validation Criteria bullet either a backticked command or a `manual:` instruction. See [Implementation Execution](../workflows/projects/implementation-execution.md#parallel-phase-groups).
158
159
  - `oat project log append|check|synthesize|rollup` - manage the optional append-only project observation log: append validated judgment or structural entries, inspect grammar and synthesis status, complete end-of-run synthesis, and roll observations into `summary.md` plus the configured repository ledger. See [Project Log](../cli-utilities/project-log.md).
159
160
  - `oat project set-mode` — deprecated no-op. Execution mode is no longer user-selectable; emits a deprecation warning and preserves the `--json` contract.
@@ -83,7 +83,7 @@ provider-level scalar in that scope or remain shadowed by one at higher
83
83
  precedence. It always tries the next authorized compatible candidate and stops
84
84
  without mutation only when none remains.
85
85
 
86
- The planner runs exactly one matching `oat config adopt dispatch-matrix`
86
+ The planner runs exactly one matching `oat config adopt dispatch-matrix --keep-existing`
87
87
  command, records file-existence and compatibility evidence plus the selected
88
88
  scope, and re-runs dispatch preflight. Existing explicit cells remain unchanged;
89
89
  their provenance does not select the persistence scope. No authorized
@@ -58,27 +58,32 @@ oat config adopt dispatch-matrix --local
58
58
  oat config adopt dispatch-matrix --user
59
59
  ```
60
60
 
61
- Adoption fills missing provider/tier cells and records
62
- `workflow.dispatchCeiling.recommendationVersion`; it does not replace explicit
63
- existing cells. Planning shows the complete recommendation before asking which
64
- scope should own it. If the resulting ladder is still missing or incomplete,
65
- planning remains blocked rather than replacing the user's explicit values.
66
- The recommendation version describes only the bundled recommendation. After
67
- preserving existing cells, OAT resolves the effective ladder and uses that
68
- effective result—not the recommendation version—for dispatch targets and
69
- runtime disclosure.
61
+ Adoption replaces populated cells from the bundled recommendation in the
62
+ chosen scope, fills missing cells, and retains extra custom tiers when the
63
+ bundled provider remains a tier map. A bundled provider-level scalar replaces
64
+ the whole provider, including custom tiers. It warns about replaced or
65
+ removed cells and reports their paths. Use `--dry-run` to preview. For
66
+ fill-only setup, `--keep-existing` preserves populated cells; if it fills
67
+ nothing, both config and version remain unchanged. When it fills missing
68
+ cells but preserves divergent cells, the version also stays unchanged. Planning always uses
69
+ `--keep-existing` after showing the complete recommendation and asking which
70
+ scope should own it. If the resulting effective ladder remains incomplete,
71
+ planning blocks. The version identifies the bundle last written by adoption;
72
+ it does not prove the effective ladder matches it. OAT resolves the effective
73
+ ladder for dispatch targets and runtime disclosure.
70
74
 
71
75
  ### Upgrading to a newer recommendation version
72
76
 
73
- Preservation applies to whole cells, which has a consequence worth stating
74
- plainly: when a new recommendation version adds candidates to a tier you have
75
- already populated, re-running adoption will not give them to you. The existing
76
- cell is kept intact rather than merged candidate by candidate. Removals are not
77
- propagated either.
77
+ A new bundled recommendation does not change an adopted config by itself.
78
+ To update the chosen scope, first preview its affected cells:
78
79
 
79
- To pick up a new version, compare your
80
- `workflow.dispatchCeiling.recommendationVersion` against the bundled version,
81
- then either edit the affected cells by hand or clear them and re-adopt.
80
+ ```bash
81
+ oat config adopt dispatch-matrix --user --dry-run
82
+ ```
83
+
84
+ Run the same command without `--dry-run` to replace bundled cells. Use
85
+ `--shared` or `--local` instead when that scope owns the ladder. Add
86
+ `--keep-existing` to fill only missing cells and preserve existing choices.
82
87
 
83
88
  Version `2026-09-25.1` is the current bundled recommendation. It prefers
84
89
  GPT-6 Luna and Sol in Codex, then Sol xhigh, Astra high, and Astra xhigh in
@@ -96,9 +101,10 @@ Balanced, and Fable 5.1 thinking high replaces Fable 5 as Frontier's terminal
96
101
  target. The ordering is an explicit user-directed preference informed by
97
102
  vendor benchmarks and the model-selection matrix, not a local workload
98
103
  comparison. Grok 4.5 and Fable 5 stay supported for explicit configurations.
99
- Rerunning adoption preserves any
100
- explicit older cell unchanged. For the complete maintenance
101
- procedure, see [Updating Model Guidance](../../contributing/updating-model-guidance.md).
104
+ Rerunning adoption replaces the bundled cells in the chosen scope; use
105
+ `--keep-existing` to preserve explicit older cells. For the complete
106
+ maintenance procedure, see
107
+ [Updating Model Guidance](../../contributing/updating-model-guidance.md).
102
108
 
103
109
  The terminal Fable target may require model access from the executing provider.
104
110
  The adopting organization is responsible for confirming its applicable
@@ -86,7 +86,11 @@ before launch. That validation-only call derives the configured invocation and
86
86
  does not persist a journal file. When a host opts in, the generic snake-case
87
87
  fields remain authoritative. A namespaced `oat` block adds
88
88
  only canonical-role identity, proven pre-start rejection, fallback linkage,
89
- and optional runtime observation. `DispatchReportV1` and the parseable
89
+ and optional runtime observation. `oat project dispatch canonical-role`
90
+ prints the canonical-role-resolution event read-only, so callers do not
91
+ hand-author it; a validated managed Claude input per role is published at
92
+ `.agents/skills/oat-dispatch-subagents/references/managed-claude-example.json`.
93
+ `DispatchReportV1` and the parseable
90
94
  `Dispatch:` compatibility stamp keep their existing byte shape.
91
95
 
92
96
  The launcher constructs and redacts the complete payload before calling the
@@ -84,6 +84,13 @@ Per-item statuses and frontmatter rollups make interrupted and repeated runs
84
84
  resumable. The promotions rollup covers RP apply-items; the filing rollup covers
85
85
  UP items plus RP file-items.
86
86
 
87
+ Every run ends with a final report walkthrough that links the artifact and
88
+ explains each `RP-*` and `UP-*` item (ID, title, summary, why it matters,
89
+ current disposition and destination, and next action), grouped into apply,
90
+ repository filing, and upstream filing items, or states that no items were
91
+ proposed. It appears in interactive and non-interactive runs, whatever happened
92
+ to apply and filing.
93
+
87
94
  ### Project-log receipt
88
95
 
89
96
  When a project log exists, generate mode appends this one-line structural
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.3.6",
3
- "docs-config": "0.3.6",
4
- "docs-theme": "0.3.6",
5
- "docs-transforms": "0.3.6"
2
+ "cli": "0.3.8",
3
+ "docs-config": "0.3.8",
4
+ "docs-theme": "0.3.8",
5
+ "docs-transforms": "0.3.8"
6
6
  }
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  user-invocable: true
6
6
  allowed-tools: Read, Write, Bash(git:*), Glob, Grep, AskUserQuestion, Task
7
7
  metadata:
8
- version: 1.12.2
8
+ version: 1.12.3
9
9
  ---
10
10
 
11
11
  # Agent Instructions Analysis
@@ -78,11 +78,21 @@ resolve_from_sync_config() {
78
78
  }
79
79
 
80
80
  resolve_from_auto_detect() {
81
- # Scan for provider directories
82
- [[ -d "${REPO_ROOT}/.claude" || -f "${REPO_ROOT}/CLAUDE.md" ]] && providers+=("claude")
83
- [[ -d "${REPO_ROOT}/.cursor" ]] && providers+=("cursor")
84
- [[ -d "${REPO_ROOT}/.github/instructions" || -f "${REPO_ROOT}/.github/copilot-instructions.md" ]] && providers+=("copilot")
85
- [[ -d "${REPO_ROOT}/.cline" ]] && providers+=("cline")
81
+ # Scan for provider directories. Each test is an `if` block so a false test
82
+ # never becomes the function's exit status under `set -e`.
83
+ if [[ -d "${REPO_ROOT}/.claude" || -f "${REPO_ROOT}/CLAUDE.md" ]]; then
84
+ providers+=("claude")
85
+ fi
86
+ if [[ -d "${REPO_ROOT}/.cursor" ]]; then
87
+ providers+=("cursor")
88
+ fi
89
+ if [[ -d "${REPO_ROOT}/.github/instructions" || -f "${REPO_ROOT}/.github/copilot-instructions.md" ]]; then
90
+ providers+=("copilot")
91
+ fi
92
+ if [[ -d "${REPO_ROOT}/.cline" ]]; then
93
+ providers+=("cline")
94
+ fi
95
+ return 0
86
96
  }
87
97
 
88
98
  interactive_confirm() {
@@ -103,7 +113,8 @@ interactive_confirm() {
103
113
  echo "" >&2
104
114
  echo "Available providers: claude, cursor, copilot, cline, codex" >&2
105
115
  echo -n "Add any additional providers? (comma-separated, or Enter to skip): " >&2
106
- read -r additional
116
+ # EOF (for example Ctrl-D) means no additional providers, not failure.
117
+ read -r additional || additional=""
107
118
 
108
119
  if [[ -n "$additional" ]]; then
109
120
  IFS=',' read -ra items <<< "$additional"
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  user-invocable: false
6
6
  allowed-tools: Read
7
7
  metadata:
8
- version: 1.2.9
8
+ version: 1.2.10
9
9
  ---
10
10
 
11
11
  # Dispatching OAT Subagents