@open-agent-toolkit/cli 0.3.6 → 0.3.7

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.
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "oatVersion": "0.3.6"
3
+ "oatVersion": "0.3.7"
4
4
  }
@@ -387,14 +387,14 @@ preference. For the full model, see
387
387
 
388
388
  ### Config keys
389
389
 
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 |
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 | Bundle version last written by adoption; does not prove the effective ladder matches |
397
+ | `workflow.dispatchCeiling.preset` | `balanced`, `maximum`, `cost-conscious` | Legacy policy setup alias |
398
398
 
399
399
  ### Adopt a complete ladder
400
400
 
@@ -406,14 +406,20 @@ oat config adopt dispatch-matrix --local
406
406
  oat config adopt dispatch-matrix --user
407
407
  ```
408
408
 
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.
409
+ Adoption replaces populated cells from the bundled recommendation in the
410
+ chosen scope, fills missing cells, and keeps extra custom tier cells when
411
+ the bundled provider remains a tier map. A bundled provider-level scalar
412
+ replaces the whole provider, including its custom tiers. It warns about
413
+ replaced and removed cells and reports their paths in human and JSON output. Preview with
414
+ `oat config adopt dispatch-matrix --user --dry-run` before writing user defaults.
415
+ Add `--keep-existing` when you want only missing cells filled; a fill-only run
416
+ with no missing cells leaves the config and version unchanged. If it fills
417
+ missing cells while preserving differences, it leaves the version unchanged. Planning uses
418
+ `--keep-existing` after showing the complete bundle and asking for the owning
419
+ scope. If the resulting effective ladder remains incomplete, readiness blocks.
420
+ The version records the bundle last written by adoption, not whether the
421
+ effective ladder matches it. Dispatch targets, structured notices, and runtime
422
+ disclosure come from the effective ladder.
417
423
 
418
424
  A recommended Fable target may require model access from the executing
419
425
  provider. The adopting organization is responsible for confirming its
@@ -700,7 +706,7 @@ Workflow preference keys live under the `workflow.*` namespace:
700
706
  - `workflow.dispatchCeiling.preset` — legacy compatibility alias (`balanced`, `maximum`, or `cost-conscious`) for capped managed policy setup.
701
707
  - `workflow.dispatchCeiling.providers.<provider>` — dispatch matrix provider column or legacy bare provider target.
702
708
  - `workflow.dispatchCeiling.providers.<provider>.<tier>` — one matrix cell for `economy`, `balanced`, `high`, or `frontier`.
703
- - `workflow.dispatchCeiling.recommendationVersion` — version of the adopted recommended matrix.
709
+ - `workflow.dispatchCeiling.recommendationVersion` — bundle version last written by adoption; not an effective-ladder parity indicator.
704
710
  - `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
711
  - `workflow.gateTimeouts.code` / `workflow.gateTimeouts.artifact` — validated default gate-review budgets in milliseconds. Both resolve through `local > shared > user`.
706
712
 
@@ -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.
@@ -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
@@ -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
@@ -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.7",
3
+ "docs-config": "0.3.7",
4
+ "docs-theme": "0.3.7",
5
+ "docs-transforms": "0.3.7"
6
6
  }
@@ -6,7 +6,7 @@ disable-model-invocation: true
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Bash, Glob, Grep, AskUserQuestion
8
8
  metadata:
9
- version: 2.0.0
9
+ version: 2.0.1
10
10
  ---
11
11
 
12
12
  # OAT Doctor
@@ -111,7 +111,7 @@ Each finding is one line with an **area**, a **severity**, a one-line **summary*
111
111
  - `activeProject` or `lastPausedProject` set to a path that does not exist → `error`; fix `oat config set activeProject ''` / `oat config set lastPausedProject ''` (the CLI refuses `unset` for these two lifecycle keys). `activeIdea` set to a missing path → `error`; fix `oat config unset activeIdea --local` (or `--user` for a user-level value).
112
112
  - A set key whose `describe` entry carries `deprecated` → `warning`; summary names the key and its `deprecated.supersededBy`; when `deprecated.legacyValues` is present the finding fires only when the set value is one of those values; fix = the entry's `owningCommand` for the successor.
113
113
  - A key set on a surface that is not one of the surfaces its `describe` entry's `file` names → `warning`; fix `oat config unset <key> --<surface>` then `oat config set <key> <value> --<right surface>`.
114
- - The `dispatch-matrix` recommendation is reported only through the `project:dispatch_matrix` check (command 1, config area); there is no separate rule for it, so one gap is one finding. Its fix is `oat config adopt dispatch-matrix --shared`, and the config dive explains it from `workflow.dispatchCeiling.recommendationVersion` in the dump.
114
+ - The `project:dispatch_matrix` check (command 1, config area) reports target availability, not parity with the bundled recommendation. Do not infer parity from `workflow.dispatchCeiling.recommendationVersion`: it identifies the bundle last written by adoption. In the config dive, `oat config adopt dispatch-matrix --shared --keep-existing` fills missing cells and reports preserved differences; a direct adoption without `--keep-existing` replaces bundled cells in the chosen scope, so preview it with `--dry-run`.
115
115
  - A documented key group with nothing set on any surface → one `info` per group, expanded only in the dive.
116
116
  - Synced project health: `project:synced_tracked_artifacts`, `project:synced_gitignore`, `project:synced_projects`, `project:synced_editor_hint`, and per-project `project:synced_<slug>_<kind>` checks from command 1 → severity from status, summary from the message; report them without treating an absent checkout as proof that no synced project exists (an absent checkout is materialized by `oat project pull`, which the check's message names).
117
117
 
@@ -6,7 +6,7 @@ disable-model-invocation: true
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion, Task
8
8
  metadata:
9
- version: 1.0.16
9
+ version: 1.0.17
10
10
  ---
11
11
 
12
12
  # Autonomous OAT Project
@@ -375,7 +375,7 @@ provider scalar or is shadowed by one at higher precedence, and block without
375
375
  mutation only when no authorized adoption-compatible scope remains. Existing
376
376
  explicit matrix cells are preserved by adoption; their provenance does not
377
377
  choose the persistence scope. Run exactly one matching
378
- `oat config adopt dispatch-matrix` command and re-run the reviewer preflight.
378
+ `oat config adopt dispatch-matrix --keep-existing` command and re-run the reviewer preflight.
379
379
  Block when the ladder remains incomplete after adoption.
380
380
 
381
381
  At every required artifact or code review:
@@ -7,7 +7,7 @@ disable-model-invocation: true
7
7
  user-invocable: true
8
8
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
9
9
  metadata:
10
- version: 1.4.17
10
+ version: 1.4.18
11
11
  ---
12
12
 
13
13
  # Import External Plan
@@ -291,9 +291,9 @@ show the complete bundled recommendation and ask for its owning scope before
291
291
  running exactly one of:
292
292
 
293
293
  ```bash
294
- oat config adopt dispatch-matrix --shared
295
- oat config adopt dispatch-matrix --local
296
- oat config adopt dispatch-matrix --user
294
+ oat config adopt dispatch-matrix --shared --keep-existing
295
+ oat config adopt dispatch-matrix --local --keep-existing
296
+ oat config adopt dispatch-matrix --user --keep-existing
297
297
  ```
298
298
 
299
299
  Adoption preserves explicit cells. Re-run the resolver and completeness check.
@@ -6,7 +6,7 @@ disable-model-invocation: true
6
6
  user-invocable: true
7
7
  allowed-tools: Read, Write, Bash(git:*), Glob, Grep, AskUserQuestion
8
8
  metadata:
9
- version: 1.4.14
9
+ version: 1.4.15
10
10
  ---
11
11
 
12
12
  # Planning Phase
@@ -408,9 +408,9 @@ recommendation and ask the user to choose the owning scope before running
408
408
  exactly one of:
409
409
 
410
410
  ```bash
411
- oat config adopt dispatch-matrix --shared
412
- oat config adopt dispatch-matrix --local
413
- oat config adopt dispatch-matrix --user
411
+ oat config adopt dispatch-matrix --shared --keep-existing
412
+ oat config adopt dispatch-matrix --local --keep-existing
413
+ oat config adopt dispatch-matrix --user --keep-existing
414
414
  ```
415
415
 
416
416
  Adoption fills missing cells but preserves explicit values. Re-run the resolver
@@ -5,7 +5,7 @@ disable-model-invocation: true
5
5
  user-invocable: false
6
6
  allowed-tools: Read, Write, Glob, Grep
7
7
  metadata:
8
- version: 1.2.32
8
+ version: 1.2.33
9
9
  ---
10
10
 
11
11
  # Plan Writing Contract
@@ -129,11 +129,11 @@ In an interactive run, ask the user to select the owning scope explicitly
129
129
  before any adoption write:
130
130
 
131
131
  1. **Shared repository** - team-owned `.oat/config.json`; run
132
- `oat config adopt dispatch-matrix --shared`.
132
+ `oat config adopt dispatch-matrix --shared --keep-existing`.
133
133
  2. **Repo-local checkout** - personal `.oat/config.local.json`; run
134
- `oat config adopt dispatch-matrix --local`.
134
+ `oat config adopt dispatch-matrix --local --keep-existing`.
135
135
  3. **User** - cross-repository `~/.oat/config.json`; run
136
- `oat config adopt dispatch-matrix --user`.
136
+ `oat config adopt dispatch-matrix --user --keep-existing`.
137
137
  4. **Do not adopt** - leave setup unresolved and block implementation
138
138
  readiness.
139
139
 
@@ -7,7 +7,7 @@ disable-model-invocation: true
7
7
  user-invocable: true
8
8
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
9
9
  metadata:
10
- version: 2.3.15
10
+ version: 2.3.16
11
11
  ---
12
12
 
13
13
  # Quick Start Project
@@ -659,9 +659,9 @@ show the full bundled recommendation and ask the user to select its owning
659
659
  scope before running exactly one command:
660
660
 
661
661
  ```bash
662
- oat config adopt dispatch-matrix --shared
663
- oat config adopt dispatch-matrix --local
664
- oat config adopt dispatch-matrix --user
662
+ oat config adopt dispatch-matrix --shared --keep-existing
663
+ oat config adopt dispatch-matrix --local --keep-existing
664
+ oat config adopt dispatch-matrix --user --keep-existing
665
665
  ```
666
666
 
667
667
  The selected scope owns only the reusable ladders. A project-specific active
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAIhF,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAoBzC,OAAO,EAML,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EAQnB,KAAK,UAAU,EAoBhB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAGL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAGL,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,mCAAmC,EACnC,0BAA0B,EAC3B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqKpC,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,kCAAkC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7E,2CAA2C,EAAE,CAC3C,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,SAAS,CAAC,CAAC;IACxB,gDAAgD,EAAE,CAChD,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,SAAS,CAAC,CAAC;IACxB,yBAAyB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACxE,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,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,KAC/B,OAAO,CAAC,8BAA8B,CAAC,CAAC;IAC7C,mCAAmC,EAAE,OAAO,mCAAmC,CAAC;IAChF,0BAA0B,EAAE,OAAO,0BAA0B,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA63GD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAqLT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/config/index.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { readFile as readFileDefault } from 'node:fs/promises';
2
2
  import { isAbsolute, join } from 'node:path';
3
+ import { isDeepStrictEqual } from 'node:util';
3
4
  import { buildCommandContext } from '../../app/command-context.js';
4
5
  import { normalizeExcludedPaths } from '../instructions/instructions.utils.js';
5
6
  import { resolveProjectsRoot } from '../shared/oat-paths.js';
@@ -2353,6 +2354,14 @@ async function removeConfigPathOnDisk(configPath, path) {
2353
2354
  const { next, removed } = removeConfigPath(parsed, path);
2354
2355
  return removed ? next : null;
2355
2356
  }
2357
+ function warnBeforeReplacingCells(application, options, context) {
2358
+ if (options.dryRun ||
2359
+ context.json ||
2360
+ application.replacedCells.length === 0) {
2361
+ return;
2362
+ }
2363
+ context.logger.warn(`Replacing ${application.replacedCells.length} populated dispatch matrix cells from the bundled recommendation: ${application.replacedCells.join(', ')}.${application.droppedCells.length > 0 ? ` Whole-provider replacements remove: ${application.droppedCells.join(', ')}.` : ''} Use --keep-existing to preserve them or --dry-run to preview.`);
2364
+ }
2356
2365
  async function loadDispatchMatrixRecommendation(dependencies) {
2357
2366
  const assetsRoot = await dependencies.resolveAssetsRoot();
2358
2367
  const assetPath = join(assetsRoot, DISPATCH_MATRIX_RECOMMENDATION_ASSET);
@@ -2392,18 +2401,90 @@ async function validateRecommendationCells(repoRoot, recommendation, dependencie
2392
2401
  }
2393
2402
  }
2394
2403
  }
2395
- function applyDispatchMatrixRecommendation(workflow, recommendation) {
2404
+ function applyDispatchMatrixRecommendation(workflow, recommendation, replace) {
2396
2405
  const existingProviders = workflow?.dispatchCeiling?.providers ?? {};
2397
2406
  const providers = {
2398
2407
  ...recommendation.providers,
2399
2408
  };
2409
+ const filledCells = [];
2410
+ const preservedCells = [];
2411
+ const differingCells = [];
2412
+ const replacedCells = [];
2413
+ const droppedCells = [];
2414
+ for (const [provider, recommendedValue] of Object.entries(recommendation.providers)) {
2415
+ const path = `${DISPATCH_CEILING_PROVIDER_KEY_PREFIX}${provider}`;
2416
+ const existingValue = getOwnKey(existingProviders, provider);
2417
+ if (existingValue === undefined) {
2418
+ if (typeof recommendedValue === 'string') {
2419
+ filledCells.push(path);
2420
+ }
2421
+ else {
2422
+ filledCells.push(...Object.keys(recommendedValue).map((tier) => `${path}.${tier}`));
2423
+ }
2424
+ continue;
2425
+ }
2426
+ if (typeof recommendedValue === 'string' ||
2427
+ typeof existingValue === 'string') {
2428
+ if (!isDeepStrictEqual(existingValue, recommendedValue)) {
2429
+ differingCells.push(path);
2430
+ if (replace) {
2431
+ replacedCells.push(path);
2432
+ if (typeof recommendedValue === 'string' &&
2433
+ typeof existingValue !== 'string') {
2434
+ droppedCells.push(...Object.keys(existingValue).map((tier) => `${path}.${tier}`));
2435
+ }
2436
+ }
2437
+ else {
2438
+ preservedCells.push(path);
2439
+ }
2440
+ }
2441
+ else {
2442
+ preservedCells.push(path);
2443
+ }
2444
+ continue;
2445
+ }
2446
+ for (const [tier, recommendedCell] of Object.entries(recommendedValue)) {
2447
+ const cellPath = `${path}.${tier}`;
2448
+ const existingCell = getOwnKey(existingValue, tier);
2449
+ if (existingCell === undefined) {
2450
+ filledCells.push(cellPath);
2451
+ }
2452
+ else {
2453
+ if (!isDeepStrictEqual(existingCell, recommendedCell)) {
2454
+ differingCells.push(cellPath);
2455
+ if (replace) {
2456
+ replacedCells.push(cellPath);
2457
+ }
2458
+ else {
2459
+ preservedCells.push(cellPath);
2460
+ }
2461
+ }
2462
+ else {
2463
+ preservedCells.push(cellPath);
2464
+ }
2465
+ }
2466
+ }
2467
+ }
2400
2468
  // `existingProviders` is a `normalizeDispatchMatrix` product, which now
2401
2469
  // keeps a provider literally named `__proto__` as an own key, so
2402
2470
  // `Object.entries` yields it here and every access is own-key guarded. The
2403
2471
  // `{ ...recommendation.providers }` spread above is already safe.
2404
2472
  for (const [provider, existingValue] of Object.entries(existingProviders)) {
2405
2473
  const recommendedValue = getOwnKey(recommendation.providers, provider);
2406
- if (recommendedValue &&
2474
+ if (replace &&
2475
+ recommendedValue &&
2476
+ typeof recommendedValue !== 'string' &&
2477
+ typeof existingValue !== 'string') {
2478
+ setOwnKey(providers, provider, {
2479
+ ...existingValue,
2480
+ ...recommendedValue,
2481
+ });
2482
+ }
2483
+ else if (replace && recommendedValue !== undefined) {
2484
+ // A bare provider override is replaced as one configured cell.
2485
+ setOwnKey(providers, provider, recommendedValue);
2486
+ }
2487
+ else if (recommendedValue &&
2407
2488
  typeof recommendedValue !== 'string' &&
2408
2489
  typeof existingValue !== 'string') {
2409
2490
  setOwnKey(providers, provider, {
@@ -2415,13 +2496,31 @@ function applyDispatchMatrixRecommendation(workflow, recommendation) {
2415
2496
  setOwnKey(providers, provider, existingValue);
2416
2497
  }
2417
2498
  }
2499
+ const versionWritten = replace
2500
+ ? filledCells.length > 0 ||
2501
+ replacedCells.length > 0 ||
2502
+ workflow?.dispatchCeiling?.recommendationVersion !==
2503
+ recommendation.version
2504
+ : filledCells.length > 0 && differingCells.length === 0;
2505
+ const writeRequired = filledCells.length > 0 || replacedCells.length > 0 || versionWritten;
2418
2506
  return {
2419
- ...(workflow ?? {}),
2420
- dispatchCeiling: {
2421
- ...workflow?.dispatchCeiling,
2422
- recommendationVersion: recommendation.version,
2423
- providers,
2507
+ workflow: {
2508
+ ...(workflow ?? {}),
2509
+ dispatchCeiling: {
2510
+ ...workflow?.dispatchCeiling,
2511
+ ...(versionWritten
2512
+ ? { recommendationVersion: recommendation.version }
2513
+ : {}),
2514
+ providers,
2515
+ },
2424
2516
  },
2517
+ filledCells,
2518
+ preservedCells,
2519
+ differingCells,
2520
+ replacedCells,
2521
+ droppedCells,
2522
+ versionWritten,
2523
+ writeRequired,
2425
2524
  };
2426
2525
  }
2427
2526
  async function effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies) {
@@ -2443,45 +2542,92 @@ async function adoptDispatchMatrixRecommendation(repoRoot, userConfigDir, option
2443
2542
  if (source === 'user') {
2444
2543
  const userConfig = await dependencies.readUserConfig(userConfigDir);
2445
2544
  await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
2446
- const workflow = applyDispatchMatrixRecommendation(userConfig.workflow, recommendation);
2447
- await dependencies.writeUserConfig(userConfigDir, {
2448
- ...userConfig,
2449
- workflow,
2450
- });
2545
+ const application = applyDispatchMatrixRecommendation(userConfig.workflow, recommendation, options.replace);
2546
+ warnBeforeReplacingCells(application, options, context);
2547
+ if (application.writeRequired && !options.dryRun) {
2548
+ await dependencies.writeUserConfig(userConfigDir, {
2549
+ ...userConfig,
2550
+ workflow: application.workflow,
2551
+ });
2552
+ }
2451
2553
  return {
2452
2554
  key: 'workflow.dispatchCeiling.providers',
2453
2555
  value: recommendation.version,
2454
2556
  source,
2455
- notices: await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2557
+ versionWritten: application.versionWritten && !options.dryRun,
2558
+ dryRun: options.dryRun,
2559
+ currentVersion: (options.dryRun
2560
+ ? userConfig.workflow?.dispatchCeiling?.recommendationVersion
2561
+ : application.workflow.dispatchCeiling?.recommendationVersion) ??
2562
+ null,
2563
+ filledCells: application.filledCells,
2564
+ preservedCells: application.preservedCells,
2565
+ differingCells: application.differingCells,
2566
+ replacedCells: application.replacedCells,
2567
+ droppedCells: application.droppedCells,
2568
+ notices: options.dryRun
2569
+ ? []
2570
+ : await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2456
2571
  };
2457
2572
  }
2458
2573
  if (source === 'local') {
2459
2574
  const localConfig = await dependencies.readOatLocalConfig(repoRoot);
2460
2575
  await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
2461
- const workflow = applyDispatchMatrixRecommendation(localConfig.workflow, recommendation);
2462
- await dependencies.writeOatLocalConfig(repoRoot, {
2463
- ...localConfig,
2464
- workflow,
2465
- });
2576
+ const application = applyDispatchMatrixRecommendation(localConfig.workflow, recommendation, options.replace);
2577
+ warnBeforeReplacingCells(application, options, context);
2578
+ if (application.writeRequired && !options.dryRun) {
2579
+ await dependencies.writeOatLocalConfig(repoRoot, {
2580
+ ...localConfig,
2581
+ workflow: application.workflow,
2582
+ });
2583
+ }
2466
2584
  return {
2467
2585
  key: 'workflow.dispatchCeiling.providers',
2468
2586
  value: recommendation.version,
2469
2587
  source,
2470
- notices: await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2588
+ versionWritten: application.versionWritten && !options.dryRun,
2589
+ dryRun: options.dryRun,
2590
+ currentVersion: (options.dryRun
2591
+ ? localConfig.workflow?.dispatchCeiling?.recommendationVersion
2592
+ : application.workflow.dispatchCeiling?.recommendationVersion) ??
2593
+ null,
2594
+ filledCells: application.filledCells,
2595
+ preservedCells: application.preservedCells,
2596
+ differingCells: application.differingCells,
2597
+ replacedCells: application.replacedCells,
2598
+ droppedCells: application.droppedCells,
2599
+ notices: options.dryRun
2600
+ ? []
2601
+ : await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2471
2602
  };
2472
2603
  }
2473
2604
  const sharedConfig = await dependencies.readOatConfig(repoRoot);
2474
2605
  await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
2475
- const workflow = applyDispatchMatrixRecommendation(sharedConfig.workflow, recommendation);
2476
- await dependencies.writeOatConfig(repoRoot, {
2477
- ...sharedConfig,
2478
- workflow,
2479
- });
2606
+ const application = applyDispatchMatrixRecommendation(sharedConfig.workflow, recommendation, options.replace);
2607
+ warnBeforeReplacingCells(application, options, context);
2608
+ if (application.writeRequired && !options.dryRun) {
2609
+ await dependencies.writeOatConfig(repoRoot, {
2610
+ ...sharedConfig,
2611
+ workflow: application.workflow,
2612
+ });
2613
+ }
2480
2614
  return {
2481
2615
  key: 'workflow.dispatchCeiling.providers',
2482
2616
  value: recommendation.version,
2483
2617
  source,
2484
- notices: await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2618
+ versionWritten: application.versionWritten && !options.dryRun,
2619
+ dryRun: options.dryRun,
2620
+ currentVersion: (options.dryRun
2621
+ ? sharedConfig.workflow?.dispatchCeiling?.recommendationVersion
2622
+ : application.workflow.dispatchCeiling?.recommendationVersion) ?? null,
2623
+ filledCells: application.filledCells,
2624
+ preservedCells: application.preservedCells,
2625
+ differingCells: application.differingCells,
2626
+ replacedCells: application.replacedCells,
2627
+ droppedCells: application.droppedCells,
2628
+ notices: options.dryRun
2629
+ ? []
2630
+ : await effectiveTerminalReviewerNotices(repoRoot, userConfigDir, dependencies),
2485
2631
  };
2486
2632
  }
2487
2633
  function formatList(values) {
@@ -2686,10 +2832,40 @@ async function runAdopt(templateArg, options, context, dependencies) {
2686
2832
  context.logger.json({
2687
2833
  status: 'ok',
2688
2834
  ...result,
2835
+ ...jsonWarnings(result.replacedCells.length > 0 && !result.dryRun
2836
+ ? [
2837
+ `Replaced ${result.replacedCells.length} populated dispatch matrix cells from the bundled recommendation.${result.droppedCells.length > 0 ? ` Removed whole-provider tier cells: ${result.droppedCells.join(', ')}.` : ''} Use --keep-existing to preserve them.`,
2838
+ ]
2839
+ : []),
2689
2840
  });
2690
2841
  }
2691
2842
  else {
2692
- context.logger.info(`Adopted dispatch matrix recommendation ${result.value} to ${result.source} config.`);
2843
+ if (result.dryRun) {
2844
+ context.logger.info(`Dry run for ${result.source} config using recommendation ${result.value}: would fill ${result.filledCells.length} cells and replace ${result.replacedCells.length} cells; no config changed.`);
2845
+ }
2846
+ else if (result.versionWritten ||
2847
+ result.filledCells.length > 0 ||
2848
+ result.replacedCells.length > 0) {
2849
+ context.logger.info(`Applied dispatch matrix recommendation ${result.value} to ${result.source} config: filled ${result.filledCells.length} cells and replaced ${result.replacedCells.length} cells.`);
2850
+ }
2851
+ else {
2852
+ context.logger.info(`No missing dispatch matrix cells in ${result.source} config; recommendation version remains ${result.currentVersion ?? 'unset'}.`);
2853
+ }
2854
+ if (result.replacedCells.length > 0) {
2855
+ context.logger.info(`${result.dryRun ? 'Would replace' : 'Replaced'}: ${result.replacedCells.join(', ')}.`);
2856
+ if (result.droppedCells.length > 0) {
2857
+ context.logger.warn(`${result.dryRun ? 'Would remove' : 'Removed'} whole-provider tier cells: ${result.droppedCells.join(', ')}.`);
2858
+ }
2859
+ }
2860
+ else if (result.differingCells.length > 0) {
2861
+ context.logger.warn(`Preserved cells differ from recommendation ${result.value}: ${result.differingCells.join(', ')}. Review and update those cells explicitly if you want the new ladder.`);
2862
+ }
2863
+ if (!result.dryRun &&
2864
+ !result.versionWritten &&
2865
+ result.filledCells.length > 0 &&
2866
+ result.differingCells.length > 0) {
2867
+ context.logger.warn(`Recommendation version remains ${result.currentVersion ?? 'unset'} because preserved cells differ from ${result.value}.`);
2868
+ }
2693
2869
  if (result.notices.length > 0) {
2694
2870
  context.logger.info(formatDispatchNotices(result.notices));
2695
2871
  }
@@ -2843,12 +3019,18 @@ export function createConfigCommand(overrides = {}) {
2843
3019
  .option('--shared', 'Write to the shared repo config (.oat/config.json)')
2844
3020
  .option('--local', 'Write to the repo-local config (.oat/config.local.json)')
2845
3021
  .option('--user', 'Write to the user-level config (~/.oat/config.json)')
2846
- .option('--yes', 'Compatibility flag; adoption always preserves explicit existing cells')
3022
+ .option('--yes', 'Compatibility flag; adoption does not require confirmation')
3023
+ .option('--keep-existing', 'Fill missing cells without replacing populated cells')
3024
+ .option('--dry-run', 'Preview cell changes without writing config')
2847
3025
  .action(async (template, options, command) => {
2848
3026
  const context = dependencies.buildCommandContext(readGlobalOptions(command));
2849
3027
  try {
2850
3028
  const surface = resolveSurfaceFlags(options);
2851
- await runAdopt(template, { surface }, context, dependencies);
3029
+ await runAdopt(template, {
3030
+ surface,
3031
+ replace: !(options.keepExisting ?? false),
3032
+ dryRun: options.dryRun ?? false,
3033
+ }, context, dependencies);
2852
3034
  }
2853
3035
  catch (error) {
2854
3036
  const message = error instanceof Error ? error.message : String(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "private": false,
5
5
  "description": "Open Agent Toolkit CLI",
6
6
  "homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
@@ -34,7 +34,7 @@
34
34
  "ora": "^9.0.0",
35
35
  "yaml": "2.8.2",
36
36
  "zod": "^3.25.76",
37
- "@open-agent-toolkit/control-plane": "0.3.6"
37
+ "@open-agent-toolkit/control-plane": "0.3.7"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",