@open-agent-toolkit/cli 0.1.38 → 0.1.40

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.
@@ -22,14 +22,14 @@ For the deep file-by-file reference, see:
22
22
  | -------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
23
23
  | Shared repo config | `.oat/config.json` | Repo-wide non-sync settings such as `projects.root`, `git.defaultBranch`, `documentation.*`, `archive.*`, `tools.*`, and shared `workflow.*` defaults | `oat config get/set/list/describe`, `oat gate` |
24
24
  | Repo-local config | `.oat/config.local.json` | Per-developer state for this checkout, such as `activeProject`, `lastPausedProject`, repo-local `activeIdea`, and local `workflow.*` overrides | `oat config get/set/list/describe`, `oat gate` |
25
- | User config | `~/.oat/config.json` | User-level state such as global `activeIdea` fallback and personal `workflow.*` defaults | `oat config describe`, `oat gate` |
26
- | Provider sync config | `.oat/sync/config.json` | Provider enablement and sync strategy settings | `oat providers set`, `oat config describe` |
25
+ | User config | `~/.oat/config.json` | User-level state such as global `activeIdea` fallback, personal `workflow.*` defaults, and personal known provider strays | `oat config describe`, `oat gate` |
26
+ | Provider sync config | `.oat/sync/config.json` | Provider enablement, sync strategy, and repo-level known stray settings | `oat providers set`, `oat config describe` |
27
27
 
28
28
  The main split is:
29
29
 
30
30
  - `.oat/config.json` for shared repo behavior
31
31
  - `.oat/config.local.json` for local developer state
32
- - `~/.oat/config.json` for user-scope fallback state
32
+ - `~/.oat/config.json` for user-scope fallback state and personal provider-sync exceptions
33
33
  - `.oat/sync/config.json` for provider sync only
34
34
 
35
35
  ## The fastest way to inspect config
@@ -232,6 +232,8 @@ reading config keys directly:
232
232
 
233
233
  ```bash
234
234
  oat project dispatch-ceiling resolve --provider codex --json
235
+ oat project dispatch-ceiling resolve --provider codex --role implementer --preferred medium --json
236
+ oat project dispatch-ceiling resolve --provider claude --role implementer --preferred sonnet --orchestrator-tier sonnet --json
235
237
  oat project dispatch-ceiling resolve --provider claude --orchestrator-tier sonnet --json
236
238
  ```
237
239
 
@@ -398,6 +400,10 @@ Use:
398
400
  - `oat config describe ...` to understand sync keys
399
401
  - `oat providers set ...` to mutate sync/provider settings
400
402
 
403
+ Known provider strays are the narrow cross-surface exception: repo-wide
404
+ `knownStrays` entries live in `.oat/sync/config.json`, while personal
405
+ `knownStrays` entries can live in `~/.oat/config.json`.
406
+
401
407
  For the provider-sync schema details, use [Sync Config (`.oat/sync/config.json`)](../provider-sync/config.md).
402
408
 
403
409
  ## Recommended workflow
@@ -23,6 +23,7 @@ Discovery note:
23
23
  It is read by:
24
24
 
25
25
  - `oat init` (provider selection and defaults)
26
+ - `oat status` (known-stray suppression in drift reports and remediation)
26
27
  - `oat sync` (active provider resolution and mismatch handling)
27
28
  - `oat providers set` (explicit provider enable/disable updates)
28
29
 
@@ -32,6 +33,7 @@ It is read by:
32
33
  {
33
34
  "version": 1,
34
35
  "defaultStrategy": "auto",
36
+ "knownStrays": [".cursor/skills/cloud-environment-setup"],
35
37
  "providers": {
36
38
  "claude": {
37
39
  "enabled": true,
@@ -50,10 +52,41 @@ It is read by:
50
52
  | --------------------------- | ------------------------------------- | ---------------------------------------------------------- |
51
53
  | `version` | yes | Config schema version (currently `1`) |
52
54
  | `defaultStrategy` | yes | Global default sync strategy: `auto`, `symlink`, or `copy` |
55
+ | `knownStrays` | no | Exact provider paths to suppress from stray reporting |
53
56
  | `providers` | no (persisted), normalized at runtime | Provider-specific overrides keyed by adapter name |
54
57
  | `providers.<name>.enabled` | no | Explicit provider activation (`true` / `false`) |
55
58
  | `providers.<name>.strategy` | no | Per-provider strategy override (`auto`, `symlink`, `copy`) |
56
59
 
60
+ ### Known strays
61
+
62
+ Use `knownStrays` for provider-local files that should remain unmanaged by OAT.
63
+ Entries are exact provider-path matches after path normalization; they are not
64
+ globs and do not suppress sibling paths.
65
+
66
+ Project-level config in `.oat/sync/config.json` applies to everyone using the
67
+ repository:
68
+
69
+ ```json
70
+ {
71
+ "version": 1,
72
+ "defaultStrategy": "auto",
73
+ "knownStrays": [".cursor/skills/cloud-environment-setup"]
74
+ }
75
+ ```
76
+
77
+ User-level config in `~/.oat/config.json` is useful for personal provider-local
78
+ files that should not be committed to the repository:
79
+
80
+ ```json
81
+ {
82
+ "knownStrays": [".cursor/skills/cloud-environment-setup"]
83
+ }
84
+ ```
85
+
86
+ The common Cursor-only skill case is a good fit: the skill may intentionally
87
+ exist in `.cursor/skills/cloud-environment-setup` while remaining outside the
88
+ canonical `.agents/skills` inventory.
89
+
57
90
  ## Behavior notes
58
91
 
59
92
  - If `providers.<name>.enabled` is:
@@ -53,6 +53,12 @@ Rendered rule files participate in the same drift states as other managed copies
53
53
 
54
54
  Provider files ignored by Git are treated as intentionally local runtime files and are not reported as strays. This includes files covered by tracked `.gitignore`, repo-local `.git/info/exclude`, or other standard Git exclude mechanisms.
55
55
 
56
+ Provider files listed in sync config `knownStrays` are also omitted from stray
57
+ summaries and adoption prompts. Known strays can be configured at project scope
58
+ in `.oat/sync/config.json` or user scope in `~/.oat/config.json`; entries use
59
+ exact provider-path matching, so `.cursor/skills/cloud-environment-setup` does
60
+ not suppress `.cursor/skills/cloud-environment-setup-extra`.
61
+
56
62
  For rules, adoption maps provider-native files back into `.agents/rules/*.md`:
57
63
 
58
64
  - Claude: `.claude/rules/*.md`
@@ -61,11 +61,20 @@ Before dispatching a subagent, the orchestrator calls:
61
61
  oat project dispatch-ceiling resolve --provider <provider> --role <implementer|reviewer> --preflight --json
62
62
  ```
63
63
 
64
+ For implementer or fix dispatch, pass the runtime classification too. In Codex
65
+ this is the preferred effort; in Claude it is the preferred model tier:
66
+
67
+ ```bash
68
+ oat project dispatch-ceiling resolve --provider codex --role implementer --preferred medium --json
69
+ oat project dispatch-ceiling resolve --provider claude --role implementer --preferred sonnet --json
70
+ ```
71
+
64
72
  The resolver:
65
73
 
66
74
  1. reads the concrete `providers.<provider>` value (config precedence, then project state) — **never the preset label**;
67
75
  2. looks up that provider's **adapter** in the provider ceiling registry;
68
- 3. returns a per-provider result: `{ value, mode, mechanism, dispatchArgs }`.
76
+ 3. applies `--preferred` for implementer/fix dispatch, capping it against the ceiling;
77
+ 4. returns a per-provider result: `{ value, mode, mechanism, dispatchArgs, selection }`.
69
78
 
70
79
  `mode` is the honest enforcement status, computed right there and never persisted:
71
80
 
@@ -89,8 +98,8 @@ The same ceiling intent produces different — but honest — behavior per provi
89
98
 
90
99
  ### Why the mechanisms differ
91
100
 
92
- - **Codex** dispatches through **pinned, sync-time role variants**. Per-call reasoning-effort proved unreliable in practice, so OAT generates committed `oat-phase-implementer-{low..xhigh}` / `oat-reviewer-{low..xhigh}` role files and dispatches the variant matching the resolved effort.
93
- - **Claude** uses the **per-call Task `model` parameter**, which is reliable and bidirectional (a Sonnet orchestrator can dispatch an Opus subagent and vice-versa) and overrides agent frontmatter so OAT simply passes `model` at dispatch and needs no variant files.
101
+ - **Codex** dispatches through **pinned, sync-time role variants**. Per-call reasoning-effort proved unreliable in practice, so OAT generates committed `oat-phase-implementer-{low..xhigh}` / `oat-reviewer-{low..xhigh}` role files. Implementer/fix dispatch passes `--preferred` so `dispatchArgs.variant` matches the selected capped effort; reviewer dispatch uses the variant matching the resolved ceiling.
102
+ - **Claude** uses the **per-call Task `model` parameter**, which is reliable and bidirectional (a Sonnet orchestrator can dispatch an Opus subagent and vice-versa) and overrides agent frontmatter. Implementer/fix dispatch passes `--preferred` as the preferred model tier and receives the capped selected `model`; reviewer dispatch uses the ceiling model. OAT needs no variant files.
94
103
  - **Unsupported providers** (any without a registered adapter) resolve to `unsupported` with `dispatchArgs: null`. The resolve command **returns cleanly and never blocks** — the ceiling is recorded as intent and applied if/when an adapter ships, while the provider runs at its own capabilities.
95
104
 
96
105
  A **provider adapter registry** is what lets these genuinely different mechanisms sit behind one resolver, so the lifecycle skills consume `dispatchArgs` without ever branching on provider.
@@ -104,6 +113,8 @@ The ceiling means slightly different things for the two dispatch roles:
104
113
 
105
114
  Both providers honor this distinction (Codex selects the matching variant; Claude passes the matching model).
106
115
 
116
+ Generic sidecars such as built-in `explorer` are outside this implementer/reviewer/fix contract. They may run at provider default when they are read-only advisory helpers. In that case, dispatch logs should say `Preferred effort: provider-default`, `Selected effort: provider-default`, and `Effort axis: provider-default`; only log a concrete selected effort when the actual sidecar payload pins a reliable provider control.
117
+
107
118
  ## Verify-on-upgrade
108
119
 
109
120
  Only a request for a tier **above** the orchestrator's current tier risks a silent plan/entitlement fallback. So the adapter verifies the actually-dispatched model **only** on that upgrade path; capping down or staying lateral needs no check. OAT never logs `enforced` unless the requested control was actually honored.
@@ -108,9 +108,9 @@ Model and effort are separate axes. Each axis logs one of these states:
108
108
  - `not-applicable` — this host/API has no meaningful per-dispatch concept for that axis.
109
109
  - `host-auto` — exceptional; the host uses that axis internally but the orchestrator cannot read or pin it.
110
110
 
111
- In Codex, implementation and fix dispatch classify a preferred effort (`low`, `medium`, `high`, or `xhigh`) and select `min(preferred, resolved_ceiling)`. The selected effort maps to the matching pinned role: `oat-phase-implementer-low`, `oat-phase-implementer-medium`, `oat-phase-implementer-high`, or `oat-phase-implementer-xhigh`. Reviewer dispatch uses the reviewer variant matching the resolved ceiling (`oat-reviewer-low|medium|high|xhigh`) for deterministic quality gates. Base/unpinned Codex roles are provider-default fallbacks; they should be logged as `provider-default`, not as inherited parent-session ceiling.
111
+ In Codex, implementation and fix dispatch classify a preferred effort (`low`, `medium`, `high`, or `xhigh`) and pass it to `oat project dispatch-ceiling resolve --provider codex --role implementer --preferred <effort>`. The resolver selects `min(preferred, resolved_ceiling)` and returns the matching pinned role: `oat-phase-implementer-low`, `oat-phase-implementer-medium`, `oat-phase-implementer-high`, or `oat-phase-implementer-xhigh`. Reviewer dispatch uses the reviewer variant matching the resolved ceiling (`oat-reviewer-low|medium|high|xhigh`) for deterministic quality gates. Base/unpinned Codex roles are provider-default fallbacks; they should be logged as `provider-default`, not as inherited parent-session ceiling.
112
112
 
113
- In Claude Code, subagent model selection is a model axis when available and is capped by `workflow.dispatchCeiling.providers.claude` (or the compiled concrete value from a preset) or project `oat_dispatch_ceiling`. The separate effort axis is `not-applicable`.
113
+ In Claude Code, implementation and fix dispatch classify a preferred model tier (`haiku`, `sonnet`, or `opus`) and pass it to `oat project dispatch-ceiling resolve --provider claude --role implementer --preferred <model> --orchestrator-tier <current-orchestrator-tier>`. The resolver selects `min(preferred, resolved_ceiling)` and returns the `model` argument to pass at dispatch. Reviewer dispatch targets the resolved Claude ceiling directly. The separate effort axis is `not-applicable`.
114
114
 
115
115
  Dispatch logs use a consistent structured block so provider behavior is comparable without flattening the model and effort axes:
116
116
 
@@ -151,10 +151,24 @@ Model axis: host-auto
151
151
  Effort axis: host-auto
152
152
  Dispatch target: host default
153
153
  Rationale: host does not expose readable or pinnable dispatch controls; rationale maps to standard effort.
154
+
155
+ OAT Dispatch: p02-t10 sidecar exploration
156
+ Host: Codex
157
+ Preferred effort: provider-default
158
+ Dispatch ceiling: xhigh
159
+ Selected effort: provider-default
160
+ Ceiling source: project state
161
+ Provider default effort: xhigh
162
+ Model axis: inherited
163
+ Effort axis: provider-default
164
+ Dispatch target: explorer
165
+ Rationale: read-only sidecar exploration; generic explorer payload does not pin an OAT-managed effort variant.
154
166
  ```
155
167
 
156
168
  Phase and review scope packets include dispatch context when the orchestrator has resolved it: `model_axis`, `effort_axis`, `dispatch_ceiling`, `ceiling_source`, `provider_default_effort`, and `dispatch_rationale`.
157
169
 
170
+ Generic sidecars such as built-in `explorer` are not OAT-managed implementer, reviewer, or fix roles. If a sidecar payload does not pin a reliable effort/model control, log it as provider-default rather than classifying the task complexity as a selected effort. Sidecar results are advisory context; implementation and review/fix gates still follow the OAT-managed dispatch rules above.
171
+
158
172
  ### Dispatch Profile overrides
159
173
 
160
174
  `plan.md` should omit `## Dispatch Profile` by default. Missing dispatch rows are normal, because runtime selection has fresher phase context and host capability information at execution time.
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.1.38",
3
- "docs-config": "0.1.38",
4
- "docs-theme": "0.1.38",
5
- "docs-transforms": "0.1.38"
2
+ "cli": "0.1.40",
3
+ "docs-config": "0.1.40",
4
+ "docs-theme": "0.1.40",
5
+ "docs-transforms": "0.1.40"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-implement
3
- version: 2.0.23
3
+ version: 2.0.24
4
4
  description: Use when plan.md is ready for execution. Dispatches phase-level subagents with bounded fix loops; supports plan-declared parallel phase groups with worktree-isolated execution and ordered fan-in.
5
5
  oat_gateable: true
6
6
  argument-hint: '[--retry-limit <N>] [--dry-run]'
@@ -204,7 +204,13 @@ Resolution order:
204
204
  "mode": "enforced",
205
205
  "mechanism": "pinned-variant",
206
206
  "dispatchArgs": { "variant": "oat-phase-implementer-high" },
207
- "verifyOnDispatch": false
207
+ "verifyOnDispatch": false,
208
+ "selection": {
209
+ "role": "implementer",
210
+ "preferredValue": null,
211
+ "selectedValue": "high",
212
+ "capped": false
213
+ }
208
214
  }
209
215
  }
210
216
  }
@@ -212,8 +218,10 @@ Resolution order:
212
218
 
213
219
  Read `providers.<active-provider>` for the concrete dispatch controls. The
214
220
  `dispatchArgs` field carries the provider-specific argument to pass through
215
- (Codex: `variant` name; Claude: `model` string). Never re-derive these from the
216
- preset label the resolver is the single compilation/join point.
221
+ (Codex: `variant` name; Claude: `model` string). For implementer/fix dispatch,
222
+ pass `--preferred <preferred-effort>` and use `selection.selectedValue` as the
223
+ selected axis value. Never re-derive these from the preset label or a ceiling-only
224
+ variant — the resolver is the single compilation/join point.
217
225
 
218
226
  Print before phase work:
219
227
 
@@ -311,7 +319,7 @@ Codex rules:
311
319
  - `high`: broad architecture, security/auth/redaction boundaries, subtle state behavior, or repeated substantive review failures
312
320
  - `xhigh`: highest-risk work that requires the configured ceiling to allow xhigh
313
321
  3. Selected effort is `min(preferred, resolved_ceiling)` for implementer/fix work.
314
- 4. For implementer/fix dispatch: call `oat project dispatch-ceiling resolve --provider codex --role implementer`; read `providers.codex.dispatchArgs.variant` for the role name (e.g., `oat-phase-implementer-high`). Pass that variant name directly do not re-derive it from the ceiling value.
322
+ 4. For implementer/fix dispatch: call `oat project dispatch-ceiling resolve --provider codex --role implementer --preferred <preferred-effort>`; read `providers.codex.selection.selectedValue` and `providers.codex.dispatchArgs.variant` for the selected role name (e.g., `oat-phase-implementer-medium`). The resolver caps the preferred effort against the ceiling; never pass a ceiling-only implementer variant when `selection.selectedValue` is lower.
315
323
  5. For review dispatch: call `oat project dispatch-ceiling resolve --provider codex --role reviewer`; read `providers.codex.dispatchArgs.variant` for the reviewer role name (e.g., `oat-reviewer-high`). Reviewer always targets the ceiling for deterministic quality gate behavior.
316
324
  6. Use base/unpinned Codex roles only as a fallback or explicit provider-default choice. Log `Selected effort: provider-default`, display provider default effort when known, and do not describe this as parent-ceiling inheritance.
317
325
  7. Do not use top-level per-call `reasoning_effort` as the standard OAT selected-effort path; dogfooding showed that path can be inconsistent.
@@ -319,9 +327,9 @@ Codex rules:
319
327
  Claude rules:
320
328
 
321
329
  - Claude ceiling is model-based: `haiku < sonnet < opus`.
322
- - Implementer dispatch: select the lowest sufficient model capped by the resolved Claude ceiling (`min(preferred, ceiling)`).
330
+ - Implementer/fix dispatch: classify the preferred model (`haiku`, `sonnet`, or `opus`) and pass it to the resolver as `--preferred <preferred-model>`. The resolver selects the lowest sufficient model capped by the resolved Claude ceiling (`min(preferred, ceiling)`).
323
331
  - Review dispatch: target the resolved Claude ceiling directly.
324
- - Call `oat project dispatch-ceiling resolve --provider claude --role implementer --orchestrator-tier <current-orchestrator-tier>` (or `--role reviewer`); read `providers.claude.dispatchArgs.model` for the model string to pass. Pass `--orchestrator-tier` so the resolver can flag above-orchestrator upgrade requests and set `verifyOnDispatch` correctly.
332
+ - For implementer/fix dispatch, call `oat project dispatch-ceiling resolve --provider claude --role implementer --preferred <preferred-model> --orchestrator-tier <current-orchestrator-tier>`; for review dispatch, call the same resolver with `--role reviewer` and no `--preferred`. Read `providers.claude.selection.selectedValue` and `providers.claude.dispatchArgs.model` for the selected model string to pass. Pass `--orchestrator-tier` so the resolver can flag above-orchestrator upgrade requests and set `verifyOnDispatch` correctly.
325
333
  - Pass `model: "<value>"` when `model_axis=selected:<value>` on the Task tool call.
326
334
  - Keep `effort_axis=not-applicable`; Claude Code has no separate per-dispatch effort axis.
327
335
 
@@ -336,7 +344,7 @@ Structured dispatch log:
336
344
  ```text
337
345
  OAT Dispatch: Phase {phase_id} {implementation | fix | review}
338
346
  Host: {Claude Code | Codex | Cursor | other host}
339
- Preferred effort: {low | medium | high | xhigh | not-applicable}
347
+ Preferred effort: {low | medium | high | xhigh | provider-default | not-applicable}
340
348
  Dispatch ceiling: {resolved ceiling value}
341
349
  Selected effort: {low | medium | high | xhigh | provider-default | not-applicable}
342
350
  Ceiling source: {repo config | project state | preflight prompt}
@@ -395,6 +403,29 @@ Dispatch target: oat-reviewer
395
403
  Rationale: base unpinned role fallback; effective effort follows Codex provider default.
396
404
  ```
397
405
 
406
+ Generic sidecar/explorer dispatch:
407
+
408
+ - Built-in or generic sidecars such as `explorer` are not OAT-managed implementer, reviewer, or fix roles.
409
+ - If a sidecar spawn payload does not explicitly pin a reliable effort/model control, log `Preferred effort: provider-default`, `Selected effort: provider-default`, and `Effort axis: provider-default`.
410
+ - Do not classify a generic sidecar as `Preferred effort: low|medium|high|xhigh` unless the actual host invocation contains the corresponding reliable selection. If the host has no reliable effort control for that sidecar, use provider-default wording instead.
411
+ - Sidecar outputs are advisory context only. Implementation work and review/fix gates still follow the OAT-managed dispatch rules above.
412
+
413
+ Codex generic explorer example:
414
+
415
+ ```text
416
+ OAT Dispatch: p02-t10 sidecar exploration
417
+ Host: Codex
418
+ Preferred effort: provider-default
419
+ Dispatch ceiling: xhigh
420
+ Selected effort: provider-default
421
+ Ceiling source: project state
422
+ Provider default effort: xhigh
423
+ Model axis: inherited
424
+ Effort axis: provider-default
425
+ Dispatch target: explorer
426
+ Rationale: read-only sidecar exploration; generic explorer payload does not pin an OAT-managed effort variant.
427
+ ```
428
+
398
429
  Include resolved dispatch context in scope packets when known:
399
430
 
400
431
  ```yaml
@@ -740,8 +771,8 @@ For each phase `pNN` in the plan (or each phase in the current parallel group),
740
771
 
741
772
  2. Perform a pre-dispatch assertion against the host invocation parameters. The Phase Scope fields are audit/context fields; selected axes must also be represented in the actual host dispatch call.
742
773
  - Codex implementer/fix dispatch:
743
- - Before building the `spawn_agent` argument map, classify the phase complexity and choose preferred effort (`low`, `medium`, `high`, or `xhigh`), then cap it to the resolved Codex dispatch ceiling.
744
- - Build the `spawn_agent` argument map before logging the dispatch. If `effort_axis=selected:low|medium|high|xhigh`, the argument map MUST use the matching `agent_type`: `"oat-phase-implementer-low"`, `"oat-phase-implementer-medium"`, `"oat-phase-implementer-high"`, or `"oat-phase-implementer-xhigh"`. Then derive the `OAT Dispatch:` block `Effort axis:` field from that same argument map.
774
+ - Before building the `spawn_agent` argument map, classify the phase complexity and choose preferred effort (`low`, `medium`, `high`, or `xhigh`), then call `oat project dispatch-ceiling resolve --provider codex --role implementer --preferred <preferred-effort>`.
775
+ - Build the `spawn_agent` argument map from `providers.codex.selection.selectedValue` and `providers.codex.dispatchArgs.variant` before logging the dispatch. If `effort_axis=selected:low|medium|high|xhigh`, the argument map MUST use the matching `agent_type`: `"oat-phase-implementer-low"`, `"oat-phase-implementer-medium"`, `"oat-phase-implementer-high"`, or `"oat-phase-implementer-xhigh"`. Then derive the `OAT Dispatch:` block `Effort axis:` field from that same argument map.
745
776
  - Example selected low payload shape: `agent_type: "oat-phase-implementer-low"` and a Phase Scope message containing `effort_axis: selected:low`.
746
777
  - Immediately after spawning, compare the returned Codex status line with the selected effort before waiting on the agent. If the spawned status reports a different effort than the selected value (for example, the log says `effort_axis=selected:medium` but the spawn result reports `gpt-5.5 high`), treat this as an orchestration deviation. Stop, record the deviation in `implementation.md`, and redispatch with corrected parameters before continuing. Do not use work from the mismatched dispatch.
747
778
  - If `effort_axis=provider-default`, use base `agent_type: "oat-phase-implementer"` and omit `reasoning_effort`. The dispatch rationale MUST say this is a base/unpinned fallback and include provider default effort when known.
@@ -2,7 +2,7 @@ import { type CommandContext, type GlobalOptions } from '../../app/command-conte
2
2
  import { type ApplyOatCoreResult } from '../init/gitignore.js';
3
3
  import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
4
4
  import { type SyncConfig } from '../../config/index.js';
5
- import { type OatConfig } from '../../config/oat-config.js';
5
+ import { type OatConfig, type UserConfig } from '../../config/oat-config.js';
6
6
  import { type DriftReport } from '../../drift/index.js';
7
7
  import { type CanonicalEntry, type HookInstallInfo } from '../../engine/index.js';
8
8
  import type { Manifest } from '../../manifest/manifest.types.js';
@@ -42,6 +42,7 @@ interface InitDependencies {
42
42
  uninstallHook: (projectRoot: string) => Promise<void>;
43
43
  getAdapters: () => ProviderAdapter[];
44
44
  loadSyncConfig: (configPath: string) => Promise<SyncConfig>;
45
+ readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
45
46
  saveSyncConfig: (configPath: string, config: SyncConfig) => Promise<SyncConfig>;
46
47
  getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<ConfigAwareAdaptersResult>;
47
48
  applyOatCoreGitignore: (repoRoot: string) => Promise<ApplyOatCoreResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,8 @@ import { withScopeOption } from '../shared/scope-option.js';
12
12
  import { confirmAction, inputWithDefault, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
13
13
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
14
14
  import { DEFAULT_SYNC_CONFIG, loadSyncConfig, saveSyncConfig, } from '../../config/index.js';
15
- import { detectDefaultBranch, readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../config/oat-config.js';
16
- import { detectStrays } from '../../drift/index.js';
15
+ import { detectDefaultBranch, readUserConfig, readOatConfig, resolveLocalPaths, writeOatConfig, } from '../../config/oat-config.js';
16
+ import { detectStrays, filterKnownStrays, } from '../../drift/index.js';
17
17
  import { configureLocalHooksPath, getHookInstallInfo, installHook, isHookInstalled, scanCanonical, uninstallHook, } from '../../engine/index.js';
18
18
  import { dirExists, fileExists } from '../../fs/io.js';
19
19
  import { resolveProjectRoot, resolveScopeRoot } from '../../fs/paths.js';
@@ -131,6 +131,7 @@ function createDependencies() {
131
131
  async loadSyncConfig(configPath) {
132
132
  return loadSyncConfig(configPath, DEFAULT_SYNC_CONFIG);
133
133
  },
134
+ readUserConfig,
134
135
  saveSyncConfig,
135
136
  getConfigAwareAdapters,
136
137
  applyOatCoreGitignore,
@@ -428,13 +429,16 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
428
429
  const scopeSummaries = [];
429
430
  for (const scope of scopes) {
430
431
  const scopeRoot = await dependencies.resolveScopeRoot(scope, context);
432
+ const syncConfigPath = join(scopeRoot, '.oat', 'sync', 'config.json');
433
+ const userConfigDir = join(context.home, '.oat');
434
+ let syncConfig = await dependencies.loadSyncConfig(syncConfigPath);
435
+ const userConfig = await dependencies.readUserConfig(userConfigDir);
431
436
  let activeAdaptersForStrays;
432
437
  if (scope === 'project') {
433
438
  projectRoot = scopeRoot;
434
439
  oatDirExistedBefore = await dependencies.dirExists(join(scopeRoot, '.oat'));
435
- const configPath = join(scopeRoot, '.oat', 'sync', 'config.json');
436
440
  const adapters = dependencies.getAdapters();
437
- let config = await dependencies.loadSyncConfig(configPath);
441
+ let config = syncConfig;
438
442
  let resolution = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
439
443
  if (!context.interactive && !context.json) {
440
444
  context.logger.info(PROVIDER_CONFIG_REMEDIATION);
@@ -457,10 +461,11 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
457
461
  enabled: selectedProviderNames.has(adapter.name),
458
462
  };
459
463
  }
460
- config = await dependencies.saveSyncConfig(configPath, {
464
+ config = await dependencies.saveSyncConfig(syncConfigPath, {
461
465
  ...config,
462
466
  providers,
463
467
  });
468
+ syncConfig = config;
464
469
  }
465
470
  resolution = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
466
471
  }
@@ -476,7 +481,15 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
476
481
  manifest = createEmptyManifest();
477
482
  }
478
483
  const canonicalEntries = await dependencies.scanCanonical(scopeRoot, scope);
479
- const strays = await dependencies.collectStrays(scopeRoot, scope, manifest, canonicalEntries, activeAdaptersForStrays);
484
+ const collectedStrays = await dependencies.collectStrays(scopeRoot, scope, manifest, canonicalEntries, activeAdaptersForStrays);
485
+ const { candidates: strays } = filterKnownStrays({
486
+ reports: collectedStrays.map((stray) => stray.report),
487
+ candidates: collectedStrays,
488
+ knownStrays: {
489
+ project: syncConfig.knownStrays,
490
+ user: userConfig.knownStrays,
491
+ },
492
+ });
480
493
  let straysAdopted = 0;
481
494
  if (!context.interactive && strays.length > 0) {
482
495
  context.logger.warn(ADOPT_REMEDIATION);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,uBAAuB,EAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAggBD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAiDT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAEL,KAAK,uBAAuB,EAG7B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BpC,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAknBD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CAqDT"}
@@ -173,12 +173,67 @@ function readResolvedConfigCeiling(provider, resolvedConfig) {
173
173
  function normalizeRole(value) {
174
174
  return value === 'reviewer' ? 'reviewer' : 'implementer';
175
175
  }
176
+ function providerValueOrder(provider) {
177
+ if (provider === 'codex') {
178
+ return CODEX_VALUES;
179
+ }
180
+ if (provider === 'claude') {
181
+ return CLAUDE_VALUES;
182
+ }
183
+ return null;
184
+ }
185
+ function normalizePreferredValue(provider, value) {
186
+ if (!value) {
187
+ return null;
188
+ }
189
+ const normalized = value.trim();
190
+ if (!normalized) {
191
+ return null;
192
+ }
193
+ const order = providerValueOrder(provider);
194
+ if (!order) {
195
+ return null;
196
+ }
197
+ if (!isValidProviderValue(provider, normalized)) {
198
+ const validValues = order.join(', ');
199
+ throw new Error(`Invalid preferred dispatch value "${normalized}" for ${provider}. Valid values: ${validValues}.`);
200
+ }
201
+ return normalized;
202
+ }
203
+ function selectDispatchValue(provider, role, ceilingValue, preferredValue) {
204
+ if (role === 'reviewer' || preferredValue === null) {
205
+ return {
206
+ role,
207
+ preferredValue,
208
+ selectedValue: ceilingValue,
209
+ capped: false,
210
+ };
211
+ }
212
+ const order = providerValueOrder(provider);
213
+ const preferredIndex = order?.indexOf(preferredValue) ?? -1;
214
+ const ceilingIndex = order?.indexOf(ceilingValue) ?? -1;
215
+ if (!order || preferredIndex < 0 || ceilingIndex < 0) {
216
+ return {
217
+ role,
218
+ preferredValue,
219
+ selectedValue: ceilingValue,
220
+ capped: false,
221
+ };
222
+ }
223
+ const selectedIndex = Math.min(preferredIndex, ceilingIndex);
224
+ return {
225
+ role,
226
+ preferredValue,
227
+ selectedValue: order[selectedIndex],
228
+ capped: preferredIndex > ceilingIndex,
229
+ };
230
+ }
176
231
  /**
177
232
  * Join a resolved ceiling value with the active provider's adapter to compute
178
233
  * the enforcement mode, mechanism, dispatch args, and verify-on-upgrade flag.
179
234
  * Mode is computed here at call time — it is never read from persisted state.
180
235
  */
181
- function buildProviderResolution(provider, value, role, orchestratorTier) {
236
+ function buildProviderResolution(provider, value, role, orchestratorTier, preferredValue) {
182
237
  const adapter = getCeilingAdapter(provider);
183
238
  if (value === null) {
184
239
  return {
@@ -187,9 +242,17 @@ function buildProviderResolution(provider, value, role, orchestratorTier) {
187
242
  mechanism: adapter.mechanism,
188
243
  dispatchArgs: null,
189
244
  verifyOnDispatch: false,
245
+ selection: {
246
+ role,
247
+ preferredValue,
248
+ selectedValue: null,
249
+ capped: false,
250
+ },
190
251
  };
191
252
  }
192
- const dispatchArgs = adapter.compileToDispatchArgs(value, role, {
253
+ const selection = selectDispatchValue(provider, role, value, preferredValue);
254
+ const dispatchValue = selection.selectedValue ?? value;
255
+ const dispatchArgs = adapter.compileToDispatchArgs(dispatchValue, role, {
193
256
  orchestratorTier,
194
257
  });
195
258
  let mode;
@@ -207,7 +270,10 @@ function buildProviderResolution(provider, value, role, orchestratorTier) {
207
270
  mode,
208
271
  mechanism: adapter.mechanism,
209
272
  dispatchArgs,
210
- verifyOnDispatch: adapter.verifyOnDispatch(value, { orchestratorTier }),
273
+ verifyOnDispatch: adapter.verifyOnDispatch(dispatchValue, {
274
+ orchestratorTier,
275
+ }),
276
+ selection,
211
277
  };
212
278
  }
213
279
  function readCodexDefaultFromToml(content) {
@@ -257,8 +323,9 @@ async function resolveDispatchCeiling(context, dependencies, options) {
257
323
  const providerDefaultEffort = provider === 'codex'
258
324
  ? await resolveCodexProviderDefaultEffort(repoRoot, context, dependencies)
259
325
  : 'not-applicable';
326
+ const preferredValue = normalizePreferredValue(provider, options.preferred);
260
327
  const resolvedValue = await resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies);
261
- const providerResolution = buildProviderResolution(provider, resolvedValue?.value ?? null, role, orchestratorTier);
328
+ const providerResolution = buildProviderResolution(provider, resolvedValue?.value ?? null, role, orchestratorTier, preferredValue);
262
329
  const providers = {
263
330
  [provider]: providerResolution,
264
331
  };
@@ -332,9 +399,17 @@ function writeHumanResolution(context, resolution) {
332
399
  if (resolution.provider === 'codex') {
333
400
  context.logger.info(`Codex provider default effort: ${resolution.providerDefaultEffort}`);
334
401
  context.logger.info(`Note: OAT will use pinned subagent variants up to ${resolution.value ?? 'the resolved ceiling'}. Base/unpinned roles resolve through the provider default.`);
402
+ if (providerResolution?.selection.selectedValue &&
403
+ providerResolution.selection.preferredValue) {
404
+ context.logger.info(`Selected Codex effort: ${providerResolution.selection.selectedValue}`);
405
+ }
335
406
  }
336
407
  else {
337
408
  context.logger.info('Effort axis: not-applicable');
409
+ if (providerResolution?.selection.selectedValue &&
410
+ providerResolution.selection.preferredValue) {
411
+ context.logger.info(`Selected dispatch value: ${providerResolution.selection.selectedValue}`);
412
+ }
338
413
  }
339
414
  }
340
415
  async function runDispatchCeilingResolve(context, dependencies, options) {
@@ -370,6 +445,7 @@ export function createProjectDispatchCeilingCommand(overrides = {}) {
370
445
  .requiredOption('--provider <provider>', 'Provider name: codex or claude are enforced; any other provider resolves as advisory (unsupported)')
371
446
  .option('--role <role>', 'Dispatch role for variant compilation: implementer (default) or reviewer')
372
447
  .option('--orchestrator-tier <tier>', 'Orchestrator tier, used to flag verify-on-upgrade for above-orchestrator requests')
448
+ .option('--preferred <value>', 'Preferred implementer/fix dispatch value before capping by the resolved ceiling')
373
449
  .option('--project-path <path>', 'Read project-state ceiling from an explicit project path')
374
450
  .option('--preflight', 'Treat unresolved non-interactive resolution as an implementation block')
375
451
  .option('--non-interactive', 'Force non-interactive block behavior when the ceiling is unresolved')
@@ -1,6 +1,8 @@
1
1
  import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
2
2
  import { type CodexRoleStray } from '../shared/codex-strays.js';
3
3
  import { type MultiSelectChoice, type PromptContext } from '../shared/shared.prompts.js';
4
+ import { type SyncConfig } from '../../config/index.js';
5
+ import { type UserConfig } from '../../config/oat-config.js';
4
6
  import { type CopyTransform, type DriftReport } from '../../drift/index.js';
5
7
  import { type CanonicalEntry } from '../../engine/index.js';
6
8
  import type { Manifest } from '../../manifest/index.js';
@@ -12,6 +14,8 @@ interface StatusDependencies {
12
14
  buildCommandContext: (options: GlobalOptions) => CommandContext;
13
15
  resolveScopeRoot: (scope: ConcreteScope, context: CommandContext) => Promise<string>;
14
16
  loadManifest: (manifestPath: string) => Promise<Manifest>;
17
+ loadSyncConfig: (configPath: string) => Promise<SyncConfig>;
18
+ readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
15
19
  saveManifest: (manifestPath: string, manifest: Manifest) => Promise<void>;
16
20
  scanCanonical: (scopeRoot: string, scope: ConcreteScope) => Promise<CanonicalEntry[]>;
17
21
  getAdapters: () => ProviderAdapter[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,9 @@ import { detectCodexRoleStrays, regenerateCodexAfterAdoption, } from '../shared/
5
5
  import { withScopeOption } from '../shared/scope-option.js';
6
6
  import { confirmAction, selectManyWithAbort, } from '../shared/shared.prompts.js';
7
7
  import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
8
- import { detectDrift, detectStrays, } from '../../drift/index.js';
8
+ import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../config/index.js';
9
+ import { readUserConfig } from '../../config/oat-config.js';
10
+ import { detectDrift, detectStrays, filterKnownStrays, } from '../../drift/index.js';
9
11
  import { HOOK_DRIFT_WARNING, HOOK_STRAY_INFO, scanCanonical, } from '../../engine/index.js';
10
12
  import { normalizeToPosixPath, resolveProjectRoot, resolveScopeRoot, } from '../../fs/paths.js';
11
13
  import { loadManifest, saveManifest } from '../../manifest/manager.js';
@@ -29,6 +31,10 @@ const DEFAULT_DEPENDENCIES = {
29
31
  return resolveScopeRoot(scope, context.cwd, context.home);
30
32
  },
31
33
  loadManifest,
34
+ async loadSyncConfig(configPath) {
35
+ return loadSyncConfig(configPath, DEFAULT_SYNC_CONFIG);
36
+ },
37
+ readUserConfig,
32
38
  saveManifest,
33
39
  scanCanonical,
34
40
  getAdapters() {
@@ -113,8 +119,14 @@ function formatStrayChoiceLabel(scope, providerPath, provider) {
113
119
  async function collectScopeReports(scope, context, dependencies) {
114
120
  const scopeRoot = await dependencies.resolveScopeRoot(scope, context);
115
121
  const manifestPath = join(scopeRoot, '.oat', 'sync', 'manifest.json');
116
- const manifest = await dependencies.loadManifest(manifestPath);
117
- const canonicalEntries = await dependencies.scanCanonical(scopeRoot, scope);
122
+ const syncConfigPath = join(scopeRoot, '.oat', 'sync', 'config.json');
123
+ const userConfigDir = join(context.home, '.oat');
124
+ const [manifest, canonicalEntries, syncConfig, userConfig] = await Promise.all([
125
+ dependencies.loadManifest(manifestPath),
126
+ dependencies.scanCanonical(scopeRoot, scope),
127
+ dependencies.loadSyncConfig(syncConfigPath),
128
+ dependencies.readUserConfig(userConfigDir),
129
+ ]);
118
130
  const adapters = dependencies.getAdapters();
119
131
  const activeAdapters = await dependencies.getActiveAdapters(adapters, scopeRoot);
120
132
  const reports = [];
@@ -234,13 +246,21 @@ async function collectScopeReports(scope, context, dependencies) {
234
246
  });
235
247
  }
236
248
  }
249
+ const filtered = filterKnownStrays({
250
+ reports,
251
+ candidates: strayCandidates,
252
+ knownStrays: {
253
+ project: syncConfig.knownStrays,
254
+ user: userConfig.knownStrays,
255
+ },
256
+ });
237
257
  return {
238
258
  scope,
239
259
  scopeRoot,
240
260
  manifestPath,
241
261
  manifest,
242
- reports,
243
- strayCandidates,
262
+ reports: filtered.reports,
263
+ strayCandidates: filtered.candidates,
244
264
  };
245
265
  }
246
266
  async function runStatusCommand(context, dependencies, options = {}) {
@@ -98,6 +98,7 @@ export interface OatLocalConfig {
98
98
  export interface UserConfig {
99
99
  version: number;
100
100
  activeIdea?: string | null;
101
+ knownStrays?: string[];
101
102
  workflow?: OatWorkflowConfig;
102
103
  }
103
104
  export interface ActiveProjectResolution {
@@ -1 +1 @@
1
- {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
@@ -260,6 +260,24 @@ function trimNonEmptyString(value) {
260
260
  const trimmed = value.trim();
261
261
  return trimmed.length > 0 ? trimmed : undefined;
262
262
  }
263
+ function normalizeKnownStrayPath(pathValue) {
264
+ const trimmed = pathValue.trim();
265
+ if (!trimmed) {
266
+ return undefined;
267
+ }
268
+ const normalized = trimPathValue(normalizeToPosixPath(trimmed));
269
+ return normalized && normalized !== '.' ? normalized : undefined;
270
+ }
271
+ function normalizeKnownStrays(value) {
272
+ if (!Array.isArray(value)) {
273
+ return undefined;
274
+ }
275
+ const normalized = value
276
+ .filter((pathValue) => typeof pathValue === 'string')
277
+ .map((pathValue) => normalizeKnownStrayPath(pathValue))
278
+ .filter((pathValue) => pathValue !== undefined);
279
+ return normalized.length > 0 ? [...new Set(normalized)].sort() : undefined;
280
+ }
263
281
  function normalizeProjectPath(repoRoot, pathValue) {
264
282
  if (pathValue == null) {
265
283
  return null;
@@ -523,6 +541,10 @@ function normalizeUserConfig(parsed) {
523
541
  ? parsed.activeIdea.trim()
524
542
  : null;
525
543
  }
544
+ const knownStrays = normalizeKnownStrays(parsed.knownStrays);
545
+ if (knownStrays) {
546
+ next.knownStrays = knownStrays;
547
+ }
526
548
  const workflow = normalizeWorkflowConfig(parsed.workflow);
527
549
  if (workflow) {
528
550
  next.workflow = workflow;
@@ -12,6 +12,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
12
12
  export declare const SyncConfigSchema: z.ZodObject<{
13
13
  version: z.ZodLiteral<1>;
14
14
  defaultStrategy: z.ZodEnum<["symlink", "copy", "auto"]>;
15
+ knownStrays: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
15
16
  providers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
16
17
  strategy: z.ZodOptional<z.ZodEnum<["symlink", "copy", "auto"]>>;
17
18
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -29,6 +30,7 @@ export declare const SyncConfigSchema: z.ZodObject<{
29
30
  strategy?: "symlink" | "copy" | "auto" | undefined;
30
31
  enabled?: boolean | undefined;
31
32
  }> | undefined;
33
+ knownStrays?: string[] | undefined;
32
34
  }, {
33
35
  version: 1;
34
36
  defaultStrategy: "symlink" | "copy" | "auto";
@@ -36,9 +38,11 @@ export declare const SyncConfigSchema: z.ZodObject<{
36
38
  strategy?: "symlink" | "copy" | "auto" | undefined;
37
39
  enabled?: boolean | undefined;
38
40
  }> | undefined;
41
+ knownStrays?: string[] | undefined;
39
42
  }>;
40
43
  export type ProviderSyncConfig = z.infer<typeof ProviderConfigSchema>;
41
44
  export type SyncConfig = z.infer<typeof SyncConfigSchema> & {
45
+ knownStrays: string[];
42
46
  providers: Record<string, ProviderSyncConfig>;
43
47
  };
44
48
  export declare const DEFAULT_SYNC_CONFIG: SyncConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAIjC,CAAC;AAoDF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA4BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
1
+ {"version":3,"file":"sync-config.d.ts","sourceRoot":"","sources":["../../src/config/sync-config.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,QAAA,MAAM,oBAAoB;;;;;;;;;EAGxB,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK3B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,GAAG;IAC1D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,UAKjC,CAAC;AA6EF,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,UAAgC,GACzC,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,UAAU,CAAC,CAcrB"}
@@ -1,6 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { CliError } from '../errors/index.js';
3
3
  import { atomicWriteJson } from '../fs/io.js';
4
+ import { normalizeToPosixPath } from '../fs/paths.js';
4
5
  import { SyncStrategySchema } from '../shared/types.js';
5
6
  import { z } from 'zod';
6
7
  import { parseJsonConfig } from './json.js';
@@ -11,11 +12,13 @@ const ProviderConfigSchema = z.object({
11
12
  export const SyncConfigSchema = z.object({
12
13
  version: z.literal(1),
13
14
  defaultStrategy: SyncStrategySchema,
15
+ knownStrays: z.array(z.string()).optional(),
14
16
  providers: z.record(ProviderConfigSchema).optional(),
15
17
  });
16
18
  export const DEFAULT_SYNC_CONFIG = {
17
19
  version: 1,
18
20
  defaultStrategy: 'auto',
21
+ knownStrays: [],
19
22
  providers: {},
20
23
  };
21
24
  function mergeProviderConfigs(base, override) {
@@ -28,10 +31,30 @@ function mergeProviderConfigs(base, override) {
28
31
  }
29
32
  return merged;
30
33
  }
34
+ function normalizeKnownStrayPath(pathValue) {
35
+ const trimmed = pathValue.trim();
36
+ if (!trimmed) {
37
+ return undefined;
38
+ }
39
+ const normalized = normalizeToPosixPath(trimmed)
40
+ .replace(/\/+$/, '')
41
+ .replace(/^\.\//, '');
42
+ return normalized && normalized !== '.' ? normalized : undefined;
43
+ }
44
+ function normalizeKnownStrays(paths) {
45
+ const normalized = paths
46
+ ?.map((pathValue) => normalizeKnownStrayPath(pathValue))
47
+ .filter((pathValue) => pathValue !== undefined);
48
+ return [...new Set(normalized ?? [])].sort();
49
+ }
31
50
  function normalizeConfig(config, defaults) {
32
51
  return {
33
52
  version: 1,
34
53
  defaultStrategy: config.defaultStrategy ?? defaults.defaultStrategy,
54
+ knownStrays: normalizeKnownStrays([
55
+ ...defaults.knownStrays,
56
+ ...(config.knownStrays ?? []),
57
+ ]),
35
58
  providers: mergeProviderConfigs(defaults.providers, config.providers ?? {}),
36
59
  };
37
60
  }
@@ -61,6 +84,7 @@ export async function loadSyncConfig(configPath, defaults = DEFAULT_SYNC_CONFIG)
61
84
  error.code === 'ENOENT') {
62
85
  return {
63
86
  ...defaults,
87
+ knownStrays: [...defaults.knownStrays],
64
88
  providers: { ...defaults.providers },
65
89
  };
66
90
  }
@@ -1,5 +1,7 @@
1
1
  export { detectDrift } from './detector.js';
2
2
  export type { CopyTransform } from './detector.js';
3
3
  export type { DriftReport, DriftState } from './drift.types.js';
4
+ export { filterKnownStrays } from './known-strays.js';
5
+ export type { FilterKnownStraysOptions, FilterKnownStraysResult, KnownStrayCandidate, KnownStraySources, } from './known-strays.js';
4
6
  export { detectStrays } from './strays.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drift/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/drift/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { detectDrift } from './detector.js';
2
+ export { filterKnownStrays } from './known-strays.js';
2
3
  export { detectStrays } from './strays.js';
@@ -0,0 +1,19 @@
1
+ import type { DriftReport } from './drift.types.js';
2
+ export interface KnownStraySources {
3
+ project?: readonly string[];
4
+ user?: readonly string[];
5
+ }
6
+ export interface KnownStrayCandidate {
7
+ report: DriftReport;
8
+ }
9
+ export interface FilterKnownStraysOptions<Candidate extends KnownStrayCandidate> {
10
+ reports: readonly DriftReport[];
11
+ candidates: readonly Candidate[];
12
+ knownStrays?: KnownStraySources;
13
+ }
14
+ export interface FilterKnownStraysResult<Candidate extends KnownStrayCandidate> {
15
+ reports: DriftReport[];
16
+ candidates: Candidate[];
17
+ }
18
+ export declare function filterKnownStrays<Candidate extends KnownStrayCandidate>(options: FilterKnownStraysOptions<Candidate>): FilterKnownStraysResult<Candidate>;
19
+ //# sourceMappingURL=known-strays.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"known-strays.d.ts","sourceRoot":"","sources":["../../src/drift/known-strays.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB,CACvC,SAAS,SAAS,mBAAmB;IAErC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB,CACtC,SAAS,SAAS,mBAAmB;IAErC,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAuCD,wBAAgB,iBAAiB,CAAC,SAAS,SAAS,mBAAmB,EACrE,OAAO,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAC3C,uBAAuB,CAAC,SAAS,CAAC,CAiBpC"}
@@ -0,0 +1,37 @@
1
+ import { normalizeToPosixPath } from '../fs/paths.js';
2
+ function normalizeProviderPath(pathValue) {
3
+ const trimmed = pathValue.trim();
4
+ if (!trimmed) {
5
+ return undefined;
6
+ }
7
+ const normalized = normalizeToPosixPath(trimmed)
8
+ .replace(/\/+$/, '')
9
+ .replace(/^\.\//, '');
10
+ return normalized && normalized !== '.' ? normalized : undefined;
11
+ }
12
+ function resolveKnownStrayPaths(knownStrays) {
13
+ const paths = [...(knownStrays?.project ?? []), ...(knownStrays?.user ?? [])];
14
+ return new Set(paths
15
+ .map((pathValue) => normalizeProviderPath(pathValue))
16
+ .filter((pathValue) => pathValue !== undefined));
17
+ }
18
+ function isKnownStrayReport(report, knownStrayPaths) {
19
+ if (report.state.status !== 'stray') {
20
+ return false;
21
+ }
22
+ const providerPath = normalizeProviderPath(report.providerPath);
23
+ return providerPath !== undefined && knownStrayPaths.has(providerPath);
24
+ }
25
+ export function filterKnownStrays(options) {
26
+ const knownStrayPaths = resolveKnownStrayPaths(options.knownStrays);
27
+ if (knownStrayPaths.size === 0) {
28
+ return {
29
+ reports: [...options.reports],
30
+ candidates: [...options.candidates],
31
+ };
32
+ }
33
+ return {
34
+ reports: options.reports.filter((report) => !isKnownStrayReport(report, knownStrayPaths)),
35
+ candidates: options.candidates.filter((candidate) => !isKnownStrayReport(candidate.report, knownStrayPaths)),
36
+ };
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
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.1.38"
37
+ "@open-agent-toolkit/control-plane": "0.1.40"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",