@open-agent-toolkit/cli 0.1.45 → 0.1.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agents/oat-phase-implementer.md +202 -191
- package/assets/agents/oat-reviewer.md +12 -2
- package/assets/config/dispatch-matrix-recommendation.json +120 -13
- package/assets/docs/cli-utilities/config-and-local-state.md +7 -0
- package/assets/docs/cli-utilities/configuration.md +183 -84
- package/assets/docs/cli-utilities/workflow-gates.md +161 -27
- package/assets/docs/contributing/skills.md +14 -8
- package/assets/docs/provider-sync/config.md +5 -1
- package/assets/docs/provider-sync/manifest-and-drift.md +6 -1
- package/assets/docs/provider-sync/providers.md +42 -5
- package/assets/docs/provider-sync/scope-and-surface.md +3 -2
- package/assets/docs/reference/cli-reference.md +3 -1
- package/assets/docs/reference/oat-directory-structure.md +27 -26
- package/assets/docs/workflows/projects/artifacts.md +31 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +235 -174
- package/assets/docs/workflows/projects/implementation-execution.md +283 -253
- package/assets/docs/workflows/projects/lifecycle.md +26 -5
- package/assets/docs/workflows/projects/reviews.md +27 -2
- package/assets/migration/pjm-restructure.md +1 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +347 -178
- package/assets/skills/oat-project-import-plan/SKILL.md +173 -16
- package/assets/skills/oat-project-next/SKILL.md +2 -2
- package/assets/skills/oat-project-plan/SKILL.md +122 -92
- package/assets/skills/oat-project-plan-writing/SKILL.md +246 -15
- package/assets/skills/oat-project-quick-start/SKILL.md +156 -94
- package/assets/skills/oat-project-review-provide/SKILL.md +94 -22
- package/dist/commands/config/index.d.ts +2 -2
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +129 -53
- package/dist/commands/doctor/index.d.ts +2 -2
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +102 -31
- package/dist/commands/gate/index.d.ts +7 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +544 -67
- package/dist/commands/gate/review-verdict.d.ts +16 -0
- package/dist/commands/gate/review-verdict.d.ts.map +1 -1
- package/dist/commands/gate/review-verdict.js +72 -9
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +586 -23
- package/dist/commands/providers/codex/index.d.ts +4 -0
- package/dist/commands/providers/codex/index.d.ts.map +1 -0
- package/dist/commands/providers/codex/index.js +7 -0
- package/dist/commands/providers/codex/materialize.d.ts +5 -0
- package/dist/commands/providers/codex/materialize.d.ts.map +1 -0
- package/dist/commands/providers/codex/materialize.js +157 -0
- package/dist/commands/providers/index.d.ts +2 -2
- package/dist/commands/providers/index.d.ts.map +1 -1
- package/dist/commands/providers/index.js +4 -2
- package/dist/commands/providers/providers.types.d.ts +23 -0
- package/dist/commands/providers/providers.types.d.ts.map +1 -1
- package/dist/commands/shared/codex-strays.d.ts.map +1 -1
- package/dist/commands/shared/codex-strays.js +11 -1
- package/dist/commands/shared/frontmatter.d.ts +4 -0
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +23 -0
- package/dist/commands/status/index.d.ts +5 -1
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +10 -4
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +10 -3
- package/dist/commands/sync/sync.types.d.ts +5 -1
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/config/dispatch-ceiling-preset.d.ts +4 -0
- package/dist/config/dispatch-ceiling-preset.d.ts.map +1 -1
- package/dist/config/dispatch-ceiling-preset.js +3 -0
- package/dist/config/dispatch-policy-options.d.ts +20 -0
- package/dist/config/dispatch-policy-options.d.ts.map +1 -0
- package/dist/config/dispatch-policy-options.js +96 -0
- package/dist/config/oat-config.d.ts +25 -2
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +154 -24
- package/dist/config/resolve.d.ts +8 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +66 -2
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/engine/scanner.d.ts +1 -0
- package/dist/engine/scanner.d.ts.map +1 -1
- package/dist/engine/scanner.js +17 -1
- package/dist/fs/paths.d.ts +4 -0
- package/dist/fs/paths.d.ts.map +1 -1
- package/dist/fs/paths.js +18 -1
- package/dist/providers/ceiling/registry.d.ts +8 -5
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +25 -7
- package/dist/providers/codex/codec/catalog.d.ts +14 -0
- package/dist/providers/codex/codec/catalog.d.ts.map +1 -0
- package/dist/providers/codex/codec/catalog.js +21 -0
- package/dist/providers/codex/codec/config-merge.d.ts +6 -0
- package/dist/providers/codex/codec/config-merge.d.ts.map +1 -1
- package/dist/providers/codex/codec/config-merge.js +7 -0
- package/dist/providers/codex/codec/materialize.d.ts +16 -0
- package/dist/providers/codex/codec/materialize.d.ts.map +1 -0
- package/dist/providers/codex/codec/materialize.js +58 -0
- package/dist/providers/codex/codec/shared.d.ts +20 -0
- package/dist/providers/codex/codec/shared.d.ts.map +1 -1
- package/dist/providers/codex/codec/shared.js +107 -6
- package/dist/providers/codex/codec/sync-extension.d.ts +7 -1
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +299 -52
- package/dist/providers/identity/availability.d.ts +24 -1
- package/dist/providers/identity/availability.d.ts.map +1 -1
- package/dist/providers/identity/availability.js +253 -19
- package/dist/providers/identity/stamp.d.ts.map +1 -1
- package/dist/providers/identity/stamp.js +4 -0
- package/dist/shared/types.d.ts +1 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +4 -0
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-project-review-provide
|
|
3
|
-
version: 1.3.
|
|
3
|
+
version: 1.3.12
|
|
4
4
|
description: Use when the user explicitly asks to review an OAT project — e.g. "review project", "review the project", "run project review", or confirms a previously offered review. Do NOT auto-invoke on completed work alone. Resolves a project review scope and offers before running.
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
user-invocable: true
|
|
@@ -31,7 +31,7 @@ Before acting, verify that there is an active OAT project or a user-provided rev
|
|
|
31
31
|
|
|
32
32
|
When the invocation is manual, summarize the inferred review type and scope, then ask before running the review.
|
|
33
33
|
|
|
34
|
-
**Gate-originated mode:** If the request context says the review is gate-originated, set `REVIEW_INVOCATION=gate`, honor any provided review type/scope arguments, and run without interactive confirmation prompts. The gate session is already the explicit authorization boundary
|
|
34
|
+
**Gate-originated mode:** If the request context says the review is gate-originated, set `REVIEW_INVOCATION=gate`, honor any provided review type/scope arguments, and run without interactive confirmation prompts. The gate session is already the explicit authorization boundary, but it does not waive dispatch controls. Resolve the reviewer target and use the exact registered role or explicitly pinned fresh child. Inline gate review is allowed only with verified equivalent current-host model and effort controls or a documented base-role exception; otherwise fail closed.
|
|
35
35
|
|
|
36
36
|
## Mode Assertion
|
|
37
37
|
|
|
@@ -428,23 +428,30 @@ Proceed with review?
|
|
|
428
428
|
|
|
429
429
|
If `REVIEW_INVOCATION=gate`, print the same scope summary but do not ask `Proceed with review?`; continue directly.
|
|
430
430
|
|
|
431
|
-
### Step 4.1: Dispatch Profile
|
|
431
|
+
### Step 4.1: Dispatch Profile Ceiling Advisory (Artifact Plan Only)
|
|
432
432
|
|
|
433
|
-
When reviewing `artifact plan`, apply this Dispatch Profile
|
|
433
|
+
When reviewing `artifact plan`, apply this Dispatch Profile named-ceiling
|
|
434
|
+
advisory:
|
|
434
435
|
|
|
435
436
|
- A missing `## Dispatch Profile` section is normal and must not be flagged.
|
|
436
437
|
- Important findings:
|
|
437
438
|
- invalid phase ID that does not match a real plan phase
|
|
438
|
-
- unknown
|
|
439
|
-
-
|
|
440
|
-
|
|
439
|
+
- unknown named ceiling or a phase ceiling above the project ceiling
|
|
440
|
+
- wording that pins an exact provider model, family, effort, or role instead
|
|
441
|
+
of a named maximum
|
|
442
|
+
- low named ceiling for multi-file integration, architecture, or review-heavy
|
|
443
|
+
work
|
|
444
|
+
- low named ceiling with missing or generic rationale
|
|
441
445
|
- Medium findings:
|
|
442
446
|
- malformed but recoverable Dispatch Profile table structure
|
|
443
|
-
- mid-tier
|
|
447
|
+
- mid-tier ceiling for architecture-heavy work without convincing rationale
|
|
444
448
|
- Minor findings:
|
|
445
449
|
- rationale is present but weakly tied to phase scope
|
|
446
450
|
|
|
447
|
-
Include this advisory in the Review Scope metadata for artifact plan reviews so
|
|
451
|
+
Include this advisory in the Review Scope metadata for artifact plan reviews so
|
|
452
|
+
the reviewer evaluates explicit ceiling rows without treating omitted rows as a
|
|
453
|
+
gap. A named ceiling is a maximum; lower configured candidates remain eligible
|
|
454
|
+
for later task selection.
|
|
448
455
|
|
|
449
456
|
### Step 4.5: Gather Deferred Findings Ledger (Final Scope Only)
|
|
450
457
|
|
|
@@ -510,6 +517,56 @@ Build the "Review Scope" metadata for the reviewer:
|
|
|
510
517
|
|
|
511
518
|
### Step 6: Execute Review (3-Tier Capability Model)
|
|
512
519
|
|
|
520
|
+
**Step 6.0: Resolve the managed reviewer target**
|
|
521
|
+
|
|
522
|
+
Before capability-tier selection, resolve the same reviewer contract used by
|
|
523
|
+
plan artifact review and implementation phase/final review:
|
|
524
|
+
|
|
525
|
+
```bash
|
|
526
|
+
oat project dispatch-ceiling resolve --provider "$ACTIVE_PROVIDER" --role reviewer --preflight --json
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
The reviewer resolver selects the final candidate of the configured review
|
|
530
|
+
ceiling. Do not supply ephemeral implementer candidate requests for artifact,
|
|
531
|
+
phase, project, or final review. A lower candidate is allowed only when a
|
|
532
|
+
separate reviewed contract explicitly authorizes reviewer lowering and defines
|
|
533
|
+
its bounds; a Dispatch Profile row does not authorize it.
|
|
534
|
+
|
|
535
|
+
Resolve every concrete managed reviewer target before probing generic subagent
|
|
536
|
+
availability or selecting Tier 1/Tier 2/Tier 3. The concrete target takes
|
|
537
|
+
precedence over all availability, preference, timeout, fresh-session, and gate
|
|
538
|
+
fallbacks.
|
|
539
|
+
A concrete managed Codex target takes precedence over tier availability.
|
|
540
|
+
Build the actual provider invocation before reporting the target as enforced:
|
|
541
|
+
|
|
542
|
+
- Codex uses the exact registered reviewer role or variant from
|
|
543
|
+
`providers.codex.dispatchArgs.variant` when selectable. If the current host
|
|
544
|
+
cannot select it, launch a fresh Codex child with the resolver target's
|
|
545
|
+
explicit model, reasoning effort, canonical role instructions from
|
|
546
|
+
`.agents/agents/oat-reviewer.md`, and the same Review Scope payload.
|
|
547
|
+
If that fresh child is unavailable, use only a verified-equivalent inline
|
|
548
|
+
route or block the review.
|
|
549
|
+
- Claude requires a non-empty `providers.claude.dispatchArgs.model`; the actual
|
|
550
|
+
provider invocation must include that exact value as its `model` argument.
|
|
551
|
+
- Cursor requires a non-empty `providers.cursor.dispatchArgs.model`; the actual
|
|
552
|
+
provider invocation must include that exact opaque string as its `model`
|
|
553
|
+
argument without normalization.
|
|
554
|
+
|
|
555
|
+
Managed incomplete resolver results, including a missing or incomplete
|
|
556
|
+
candidate ladder, fail closed before review. Route interactive repair through
|
|
557
|
+
the planning workflow's `Complete Dispatch Ladder Adoption Contract`; do not
|
|
558
|
+
invent a reviewer target.
|
|
559
|
+
|
|
560
|
+
On timeout or retry, reuse the same exact role or complete invocation payload,
|
|
561
|
+
including the Claude or Cursor model argument. If the host cannot apply a
|
|
562
|
+
required role or model argument, fail closed or block unless inline execution
|
|
563
|
+
has verified equivalent current-host controls.
|
|
564
|
+
Workflow correctness must not require provider restart or hot reload.
|
|
565
|
+
Never use a managed base role because a target is missing or unavailable; a
|
|
566
|
+
managed base role is forbidden except for
|
|
567
|
+
explicit inherit/default behavior or the documented managed-uncapped reviewer
|
|
568
|
+
fallback.
|
|
569
|
+
|
|
513
570
|
**Step 6a: Probe Subagent Availability**
|
|
514
571
|
|
|
515
572
|
Before selecting a tier, announce the probe and its result so the user can see what's happening:
|
|
@@ -526,8 +583,7 @@ Detection logic:
|
|
|
526
583
|
- If the host is Cursor, invoke `oat-reviewer` using Cursor-native explicit invocation (`/oat-reviewer`) or natural mention, and resolve from `.cursor/agents/oat-reviewer.md` (or `.claude/agents/oat-reviewer.md` compatibility path).
|
|
527
584
|
- If the host is Codex multi-agent, verify Codex requirements first:
|
|
528
585
|
- `[features] multi_agent = true` is enabled in active Codex config.
|
|
529
|
-
-
|
|
530
|
-
- Codex may also auto-select and spawn agents without explicit role pinning.
|
|
586
|
+
- For a concrete managed target, `agent_type` must be the exact custom role declared under `[agents.<name>]`; built-in roles and auto-selection are not equivalent fallbacks.
|
|
531
587
|
- If the current Codex host requires explicit user authorization before calling `spawn_agent`, do not mark `oat-reviewer` as unresolved. Announce `authorization required` and ask one concise confirmation question before selecting Tier 2 or Tier 3:
|
|
532
588
|
|
|
533
589
|
```
|
|
@@ -535,12 +591,12 @@ Detection logic:
|
|
|
535
591
|
```
|
|
536
592
|
|
|
537
593
|
- If the user authorizes delegation and Codex role prerequisites are satisfied, use **Tier 1**.
|
|
538
|
-
- If the user declines delegation, continue
|
|
594
|
+
- If the user declines delegation, continue only through a target-preserving pinned-child or guarded inline route. Otherwise block.
|
|
539
595
|
|
|
540
596
|
- If the runtime can dispatch reviewer work (`subagent_type` in Claude Code, Cursor invocation via `/name` or natural mention, or Codex multi-agent spawn/auto-spawn) → **Tier 1**.
|
|
541
|
-
- If the Task tool is not available or subagent dispatch is not supported
|
|
542
|
-
- If user explicitly requests inline or confirms they are already in a fresh session
|
|
543
|
-
-
|
|
597
|
+
- If the Task tool is not available or subagent dispatch is not supported, use **Tier 2** only after applying the target-first contract.
|
|
598
|
+
- If the user explicitly requests inline or confirms they are already in a fresh session, use **Tier 3** only when the guarded inline route is valid.
|
|
599
|
+
- Gate-originated review skips fresh-session handoff instructions and immediately uses the first target-preserving route available from Step 6.0. If none exists, fail closed.
|
|
544
600
|
|
|
545
601
|
**Step 6b: Tier 1 — Subagent (if available)**
|
|
546
602
|
|
|
@@ -549,9 +605,9 @@ First, pre-compute the review artifact path using Step 7 naming conventions so i
|
|
|
549
605
|
Then spawn the reviewer:
|
|
550
606
|
|
|
551
607
|
- Use provider-appropriate dispatch:
|
|
552
|
-
- Claude Code: Task tool with `subagent_type: "oat-reviewer"` (resolves from `.claude/agents/oat-reviewer.md`).
|
|
553
|
-
- Cursor: explicit invocation `/oat-reviewer` (or natural mention) with agent resolved from `.cursor/agents/oat-reviewer.md` or `.claude/agents/oat-reviewer.md` compatibility path.
|
|
554
|
-
- Codex style:
|
|
608
|
+
- Claude Code: Task tool with `subagent_type: "oat-reviewer"` (resolves from `.claude/agents/oat-reviewer.md`). For a concrete managed target, the payload must also contain `model: providers.claude.dispatchArgs.model` with the resolver-returned value.
|
|
609
|
+
- Cursor: explicit invocation `/oat-reviewer` (or natural mention) with agent resolved from `.cursor/agents/oat-reviewer.md` or `.claude/agents/oat-reviewer.md` compatibility path. For a concrete managed target, the invocation must also contain `model: providers.cursor.dispatchArgs.model` with the exact opaque resolver-returned string.
|
|
610
|
+
- Codex style: for a concrete managed target, spawn the exact resolver-returned `agent_type`; if it cannot be selected, use the explicitly pinned fresh-child route from Step 6.0. Generic auto-selection is permitted only for the documented base-role exceptions.
|
|
555
611
|
- Pass the Review Scope metadata block from Step 5 as the prompt
|
|
556
612
|
- Include the pre-computed artifact path for the subagent to write to
|
|
557
613
|
- **If a worktree was resolved in Step 1.5:** include the worktree path in the prompt so the subagent writes the artifact to the worktree directory, not the current session's working directory
|
|
@@ -566,12 +622,12 @@ After the subagent completes:
|
|
|
566
622
|
|
|
567
623
|
**Step 6c: Tier 2 — Fresh Session (recommended fallback)**
|
|
568
624
|
|
|
569
|
-
If subagent not available:
|
|
625
|
+
If target-preserving subagent dispatch is not available:
|
|
570
626
|
|
|
571
627
|
- If user is already in a fresh session (confirmed), proceed to Tier 3.
|
|
572
628
|
- If Codex reported `authorization required` and the user approved delegation, do **not** use Tier 2. Return to Tier 1 and delegate to `oat-reviewer`.
|
|
573
629
|
- If user prefers fresh session: provide instructions and exit.
|
|
574
|
-
-
|
|
630
|
+
- Gate-originated review does not return fresh-session instructions; it uses the guarded route selected in Step 6.0 or fails closed.
|
|
575
631
|
|
|
576
632
|
Instructions for fresh session:
|
|
577
633
|
|
|
@@ -585,7 +641,13 @@ To run review in a fresh session:
|
|
|
585
641
|
|
|
586
642
|
**Step 6d: Tier 3 — Inline Reset (fallback)**
|
|
587
643
|
|
|
588
|
-
If user
|
|
644
|
+
If the user requests inline review, first verify equivalent current-host model
|
|
645
|
+
and effort controls. Inline is also allowed for explicit inherit/default or the
|
|
646
|
+
documented managed-uncapped reviewer behavior. User preference alone does not
|
|
647
|
+
override a concrete managed target; if the guard fails, use the exact/pinned
|
|
648
|
+
route or block.
|
|
649
|
+
|
|
650
|
+
When inline is allowed:
|
|
589
651
|
|
|
590
652
|
- Run "reset protocol":
|
|
591
653
|
1. Re-read required artifacts for current workflow mode from scratch
|
|
@@ -649,6 +711,13 @@ oat_review_scope: { scope }
|
|
|
649
711
|
oat_review_type: { code|artifact }
|
|
650
712
|
oat_review_invocation: { manual|auto|gate }
|
|
651
713
|
oat_project: { PROJECT_PATH }
|
|
714
|
+
# Gate-only: copy the exact prompt-provided fields below.
|
|
715
|
+
oat_gate_run_id: { gate run id }
|
|
716
|
+
oat_gate_target: { configured target id }
|
|
717
|
+
oat_gate_runtime: { configured runtime }
|
|
718
|
+
oat_invocation_model: { configured model|provider-default|unknown }
|
|
719
|
+
oat_invocation_reasoning_effort: { configured effort|provider-default|unknown }
|
|
720
|
+
oat_invocation_source: { exec-target-config|unknown }
|
|
652
721
|
---
|
|
653
722
|
|
|
654
723
|
# {Code|Artifact} Review: {scope}
|
|
@@ -669,6 +738,8 @@ When `oat-project-implement` spawns this skill for auto-review at checkpoints, i
|
|
|
669
738
|
|
|
670
739
|
When `oat gate review` invokes this skill, it includes gate-originated context instructing the reviewer to write `oat_review_invocation: gate`. Honor that instruction in the artifact frontmatter.
|
|
671
740
|
|
|
741
|
+
The gate prompt also supplies exact values for `oat_gate_run_id`, `oat_gate_target`, `oat_gate_runtime`, `oat_invocation_model`, `oat_invocation_reasoning_effort`, and `oat_invocation_source`. Copy all six values verbatim for gate-originated artifacts. These fields record OAT's configured invocation; do not derive them from `baseCommand`, the target id, model self-identification, or surrounding dispatch prose. Optional observed/self-reported identity is separate and non-authoritative.
|
|
742
|
+
|
|
672
743
|
For all other invocations (user-triggered, fresh session), use `manual`.
|
|
673
744
|
|
|
674
745
|
Gate parsing contract:
|
|
@@ -784,7 +855,8 @@ For best review quality, run in a fresh session:
|
|
|
784
855
|
2. Run the oat-project-review-provide skill with: code {scope}
|
|
785
856
|
3. Return here and run the oat-project-review-receive skill
|
|
786
857
|
|
|
787
|
-
Or say "inline" to
|
|
858
|
+
Or say "inline" to request review in the current session; the managed-target
|
|
859
|
+
guard still applies.
|
|
788
860
|
|
|
789
861
|
```
|
|
790
862
|
|
|
@@ -2,7 +2,7 @@ import { buildCommandContext, type CommandContext } from '../../app/command-cont
|
|
|
2
2
|
import { type PromptContext } from '../shared/shared.prompts.js';
|
|
3
3
|
import { type OatConfig, type OatLocalConfig, type UserConfig } from '../../config/oat-config.js';
|
|
4
4
|
import { type ResolvedConfig } from '../../config/resolve.js';
|
|
5
|
-
import { type
|
|
5
|
+
import { type MatrixCellAvailabilityResponse, type ValidateMatrixCellOptions } from '../../providers/identity/availability.js';
|
|
6
6
|
import { Command } from 'commander';
|
|
7
7
|
interface ConfigCommandDependencies {
|
|
8
8
|
buildCommandContext: (options: Parameters<typeof buildCommandContext>[0]) => CommandContext;
|
|
@@ -18,7 +18,7 @@ interface ConfigCommandDependencies {
|
|
|
18
18
|
resolveAssetsRoot: () => Promise<string>;
|
|
19
19
|
readFile: (path: string) => Promise<string>;
|
|
20
20
|
confirmAction: (message: string, ctx: PromptContext) => Promise<boolean>;
|
|
21
|
-
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<
|
|
21
|
+
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
|
|
22
22
|
processEnv: NodeJS.ProcessEnv;
|
|
23
23
|
}
|
|
24
24
|
export declare function createConfigCommand(overrides?: Partial<ConfigCommandDependencies>): Command;
|
|
@@ -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;AAEhF,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;
|
|
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;AAEhF,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AAQzC,OAAO,EAML,KAAK,SAAS,EACd,KAAK,cAAc,EAGnB,KAAK,UAAU,EAgBhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAGL,KAAK,8BAA8B,EACnC,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkFpC,UAAU,yBAAyB;IACjC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAC/C,cAAc,CAAC;IACpB,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/D,eAAe,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,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,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AA45DD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,yBAAyB,CAAM,GACjD,OAAO,CAsKT"}
|
|
@@ -5,11 +5,12 @@ import { resolveProjectsRoot } from '../shared/oat-paths.js';
|
|
|
5
5
|
import { confirmAction, } from '../shared/shared.prompts.js';
|
|
6
6
|
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
7
7
|
import { compileDispatchCeilingPreset } from '../../config/dispatch-ceiling-preset.js';
|
|
8
|
-
import {
|
|
8
|
+
import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
|
|
9
|
+
import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, isCodexMaterializedRouteTarget, isWorkflowDispatchCandidateLadder, isWorkflowDispatchFallbackRoute, readOatConfig, readOatLocalConfig, readUserConfig, validateDispatchRouteTarget, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
|
|
9
10
|
import { resolveEffectiveConfig, } from '../../config/resolve.js';
|
|
10
11
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
11
12
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
12
|
-
import { validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
13
|
+
import { normalizeMatrixCellAvailability, validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
13
14
|
import { Command } from 'commander';
|
|
14
15
|
import { createConfigDumpCommand } from './dump.js';
|
|
15
16
|
const DISPATCH_CEILING_PROVIDER_KEY_PREFIX = 'workflow.dispatchCeiling.providers.';
|
|
@@ -478,7 +479,7 @@ const CONFIG_CATALOG = [
|
|
|
478
479
|
defaultValue: 'unset',
|
|
479
480
|
mutability: 'read/write',
|
|
480
481
|
owningCommand: 'oat config set workflow.dispatchPolicy.mode <value>',
|
|
481
|
-
description:
|
|
482
|
+
description: dispatchPolicyModeDescription(),
|
|
482
483
|
},
|
|
483
484
|
{
|
|
484
485
|
key: 'workflow.dispatchPolicy.policy',
|
|
@@ -489,14 +490,14 @@ const CONFIG_CATALOG = [
|
|
|
489
490
|
defaultValue: 'unset',
|
|
490
491
|
mutability: 'read/write',
|
|
491
492
|
owningCommand: 'oat config set workflow.dispatchPolicy.policy <value>',
|
|
492
|
-
description:
|
|
493
|
+
description: dispatchPolicyPolicyDescription(),
|
|
493
494
|
},
|
|
494
495
|
{
|
|
495
496
|
key: 'workflow.dispatchCeiling.providers.codex',
|
|
496
497
|
group: 'Workflow Preferences (3-layer: local > shared > user)',
|
|
497
498
|
file: '.oat/config.local.json | .oat/config.json | ~/.oat/config.json',
|
|
498
499
|
scope: 'workflow',
|
|
499
|
-
type: 'low | medium | high | xhigh',
|
|
500
|
+
type: 'low | medium | high | xhigh | max',
|
|
500
501
|
defaultValue: 'unset',
|
|
501
502
|
mutability: 'read/write',
|
|
502
503
|
owningCommand: 'oat config set workflow.dispatchCeiling.providers.codex <value>',
|
|
@@ -614,20 +615,15 @@ const WORKFLOW_ENUM_VALUES = {
|
|
|
614
615
|
'workflow.postImplementSequence': ['wait', 'summary', 'pr', 'docs-pr'],
|
|
615
616
|
'workflow.reviewExecutionModel': ['subagent', 'inline', 'fresh-session'],
|
|
616
617
|
'workflow.designMode': ['collaborative', 'selective', 'draft'],
|
|
617
|
-
'workflow.dispatchPolicy.mode': [
|
|
618
|
-
'workflow.dispatchPolicy.policy': [
|
|
619
|
-
'economy',
|
|
620
|
-
'balanced',
|
|
621
|
-
'high',
|
|
622
|
-
'frontier',
|
|
623
|
-
'uncapped',
|
|
624
|
-
],
|
|
618
|
+
'workflow.dispatchPolicy.mode': [...VALID_DISPATCH_POLICY_MODES],
|
|
619
|
+
'workflow.dispatchPolicy.policy': [...VALID_MANAGED_DISPATCH_POLICIES],
|
|
625
620
|
'workflow.dispatchCeiling.preset': ['balanced', 'maximum', 'cost-conscious'],
|
|
626
621
|
'workflow.dispatchCeiling.providers.codex': [
|
|
627
622
|
'low',
|
|
628
623
|
'medium',
|
|
629
624
|
'high',
|
|
630
625
|
'xhigh',
|
|
626
|
+
'max',
|
|
631
627
|
],
|
|
632
628
|
'workflow.dispatchCeiling.providers.claude': [
|
|
633
629
|
'haiku',
|
|
@@ -747,13 +743,15 @@ function isRecord(value) {
|
|
|
747
743
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
748
744
|
}
|
|
749
745
|
function matrixCellAvailabilityWarning(path, value, availability) {
|
|
750
|
-
|
|
746
|
+
const result = normalizeMatrixCellAvailability(availability);
|
|
747
|
+
if (result.availability === 'valid') {
|
|
751
748
|
return null;
|
|
752
749
|
}
|
|
753
|
-
|
|
754
|
-
|
|
750
|
+
const details = result.message ? ` ${result.message}` : '';
|
|
751
|
+
if (result.availability === 'unknown-value') {
|
|
752
|
+
return `${path} value '${value}' was not recognized by the provider availability oracle; saving anyway.${details}`;
|
|
755
753
|
}
|
|
756
|
-
return `${path} value '${value}' could not be validated because the provider availability oracle is unavailable; saving anyway
|
|
754
|
+
return `${path} value '${value}' could not be validated because the provider availability oracle is unavailable; saving anyway.${details}`;
|
|
757
755
|
}
|
|
758
756
|
function parseDispatchMatrixRecommendation(raw) {
|
|
759
757
|
const parsed = JSON.parse(raw);
|
|
@@ -775,26 +773,64 @@ function parseDispatchMatrixRecommendation(raw) {
|
|
|
775
773
|
function isRouteTarget(entry) {
|
|
776
774
|
return isRecord(entry);
|
|
777
775
|
}
|
|
776
|
+
function formatRouteTargetValue(entry) {
|
|
777
|
+
return [entry.model, entry.effort].filter(Boolean).join('/');
|
|
778
|
+
}
|
|
778
779
|
function addDispatchMatrixCellRefs(refs, provider, path, cell) {
|
|
779
780
|
if (typeof cell === 'string') {
|
|
780
781
|
refs.push({ provider, value: cell, path });
|
|
781
782
|
return;
|
|
782
783
|
}
|
|
783
|
-
|
|
784
|
-
const entryPath = `${path}[${index}]`;
|
|
784
|
+
const addEntry = (entry, entryPath) => {
|
|
785
785
|
if (typeof entry === 'string') {
|
|
786
786
|
refs.push({ provider, value: entry, path: entryPath });
|
|
787
|
-
|
|
787
|
+
return;
|
|
788
788
|
}
|
|
789
789
|
if (!isRouteTarget(entry)) {
|
|
790
|
-
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const targetProvider = entry.harness ?? provider;
|
|
793
|
+
if (isCodexMaterializedRouteTarget(provider, entry)) {
|
|
794
|
+
if (entry.model && entry.effort) {
|
|
795
|
+
refs.push({
|
|
796
|
+
provider: targetProvider,
|
|
797
|
+
value: formatRouteTargetValue(entry),
|
|
798
|
+
path: entryPath,
|
|
799
|
+
target: entry,
|
|
800
|
+
});
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
791
803
|
}
|
|
792
804
|
if (entry.model) {
|
|
793
|
-
refs.push({
|
|
805
|
+
refs.push({
|
|
806
|
+
provider: targetProvider,
|
|
807
|
+
value: entry.model,
|
|
808
|
+
path: `${entryPath}.model`,
|
|
809
|
+
});
|
|
794
810
|
}
|
|
795
811
|
if (entry.effort) {
|
|
796
|
-
refs.push({
|
|
812
|
+
refs.push({
|
|
813
|
+
provider: targetProvider,
|
|
814
|
+
value: entry.effort,
|
|
815
|
+
path: `${entryPath}.effort`,
|
|
816
|
+
});
|
|
797
817
|
}
|
|
818
|
+
};
|
|
819
|
+
if (isWorkflowDispatchCandidateLadder(cell)) {
|
|
820
|
+
for (const [candidateIndex, candidate] of cell.candidates.entries()) {
|
|
821
|
+
const candidatePath = `${path}.candidates[${candidateIndex}]`;
|
|
822
|
+
if (isWorkflowDispatchFallbackRoute(candidate)) {
|
|
823
|
+
for (const [routeIndex, entry] of candidate.route.entries()) {
|
|
824
|
+
addEntry(entry, `${candidatePath}.route[${routeIndex}]`);
|
|
825
|
+
}
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
addEntry(candidate, candidatePath);
|
|
829
|
+
}
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
for (const [index, entry] of cell.entries()) {
|
|
833
|
+
addEntry(entry, `${path}[${index}]`);
|
|
798
834
|
}
|
|
799
835
|
}
|
|
800
836
|
function collectDispatchMatrixCellRefs(providers) {
|
|
@@ -814,6 +850,46 @@ function collectDispatchMatrixCellRefs(providers) {
|
|
|
814
850
|
}
|
|
815
851
|
return refs;
|
|
816
852
|
}
|
|
853
|
+
function collectDispatchMatrixTargetValidationErrors(providers) {
|
|
854
|
+
const errors = [];
|
|
855
|
+
for (const [provider, providerValue] of Object.entries(providers)) {
|
|
856
|
+
if (typeof providerValue === 'string') {
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
const providerPath = `workflow.dispatchCeiling.providers.${provider}`;
|
|
860
|
+
for (const [tier, cell] of Object.entries(providerValue)) {
|
|
861
|
+
if (cell === undefined || typeof cell === 'string') {
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
const validateEntry = (entry, entryPath) => {
|
|
865
|
+
if (!isRouteTarget(entry)) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
const validation = validateDispatchRouteTarget(provider, entry);
|
|
869
|
+
if (!validation.valid) {
|
|
870
|
+
errors.push(`${entryPath}: ${validation.reason}`);
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
if (isWorkflowDispatchCandidateLadder(cell)) {
|
|
874
|
+
for (const [candidateIndex, candidate] of cell.candidates.entries()) {
|
|
875
|
+
const candidatePath = `${providerPath}.${tier}.candidates[${candidateIndex}]`;
|
|
876
|
+
if (isWorkflowDispatchFallbackRoute(candidate)) {
|
|
877
|
+
for (const [routeIndex, entry] of candidate.route.entries()) {
|
|
878
|
+
validateEntry(entry, `${candidatePath}.route[${routeIndex}]`);
|
|
879
|
+
}
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
validateEntry(candidate, candidatePath);
|
|
883
|
+
}
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
for (const [index, entry] of cell.entries()) {
|
|
887
|
+
validateEntry(entry, `${providerPath}.${tier}[${index}]`);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
return errors;
|
|
892
|
+
}
|
|
817
893
|
function applyWorkflowValue(workflow, key, value) {
|
|
818
894
|
const subKey = key.slice('workflow.'.length);
|
|
819
895
|
if (subKey === 'dispatchPolicy.mode') {
|
|
@@ -826,7 +902,7 @@ function applyWorkflowValue(workflow, key, value) {
|
|
|
826
902
|
}
|
|
827
903
|
const policy = workflow.dispatchPolicy?.policy;
|
|
828
904
|
if (!policy) {
|
|
829
|
-
throw new Error(
|
|
905
|
+
throw new Error(`Cannot set workflow.dispatchPolicy.mode to managed without an existing workflow.dispatchPolicy.policy. Set workflow.dispatchPolicy.policy <${managedDispatchPolicyValueList('|')}> instead.`);
|
|
830
906
|
}
|
|
831
907
|
return {
|
|
832
908
|
...workflow,
|
|
@@ -923,6 +999,9 @@ function formatResolvedValue(value) {
|
|
|
923
999
|
if (Array.isArray(value)) {
|
|
924
1000
|
return value.join(',');
|
|
925
1001
|
}
|
|
1002
|
+
if (typeof value === 'object') {
|
|
1003
|
+
return JSON.stringify(value);
|
|
1004
|
+
}
|
|
926
1005
|
return String(value);
|
|
927
1006
|
}
|
|
928
1007
|
async function getConfigValue(repoRoot, userConfigDir, key, dependencies) {
|
|
@@ -956,6 +1035,7 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
956
1035
|
const availability = await dependencies.validateMatrixCell(providerNameFromConfigKey(key), parsedValue, {
|
|
957
1036
|
cwd: repoRoot,
|
|
958
1037
|
env: dependencies.processEnv,
|
|
1038
|
+
detailed: true,
|
|
959
1039
|
});
|
|
960
1040
|
const warning = dispatchProviderAvailabilityWarning(key, parsedValue, availability);
|
|
961
1041
|
if (warning) {
|
|
@@ -1139,19 +1219,19 @@ async function setConfigValue(repoRoot, userConfigDir, key, rawValue, surface, d
|
|
|
1139
1219
|
source: 'shared',
|
|
1140
1220
|
};
|
|
1141
1221
|
}
|
|
1142
|
-
function hasExistingDispatchMatrix(config) {
|
|
1143
|
-
const providers = config.workflow?.dispatchCeiling?.providers;
|
|
1144
|
-
return providers !== undefined && Object.keys(providers).length > 0;
|
|
1145
|
-
}
|
|
1146
1222
|
async function loadDispatchMatrixRecommendation(dependencies) {
|
|
1147
1223
|
const assetsRoot = await dependencies.resolveAssetsRoot();
|
|
1148
1224
|
const assetPath = join(assetsRoot, DISPATCH_MATRIX_RECOMMENDATION_ASSET);
|
|
1149
1225
|
return parseDispatchMatrixRecommendation(await dependencies.readFile(assetPath));
|
|
1150
1226
|
}
|
|
1151
1227
|
async function validateRecommendationCells(repoRoot, recommendation, dependencies, warn) {
|
|
1228
|
+
const targetErrors = collectDispatchMatrixTargetValidationErrors(recommendation.providers);
|
|
1229
|
+
if (targetErrors.length > 0) {
|
|
1230
|
+
throw new Error(targetErrors.join('\n'));
|
|
1231
|
+
}
|
|
1152
1232
|
for (const ref of collectDispatchMatrixCellRefs(recommendation.providers)) {
|
|
1153
1233
|
const closedValues = closedDispatchProviderValues(ref.provider);
|
|
1154
|
-
if (closedValues && !closedValues.includes(ref.value)) {
|
|
1234
|
+
if (!ref.target && closedValues && !closedValues.includes(ref.value)) {
|
|
1155
1235
|
throw new Error(`Invalid value for ${ref.path}: expected one of ${closedValues.join(' | ')}, got '${ref.value}'`);
|
|
1156
1236
|
}
|
|
1157
1237
|
let availability;
|
|
@@ -1159,6 +1239,8 @@ async function validateRecommendationCells(repoRoot, recommendation, dependencie
|
|
|
1159
1239
|
availability = await dependencies.validateMatrixCell(ref.provider, ref.value, {
|
|
1160
1240
|
cwd: repoRoot,
|
|
1161
1241
|
env: dependencies.processEnv,
|
|
1242
|
+
detailed: true,
|
|
1243
|
+
...(ref.target ? { target: ref.target } : {}),
|
|
1162
1244
|
});
|
|
1163
1245
|
}
|
|
1164
1246
|
catch {
|
|
@@ -1171,35 +1253,35 @@ async function validateRecommendationCells(repoRoot, recommendation, dependencie
|
|
|
1171
1253
|
}
|
|
1172
1254
|
}
|
|
1173
1255
|
function applyDispatchMatrixRecommendation(workflow, recommendation) {
|
|
1256
|
+
const existingProviders = workflow?.dispatchCeiling?.providers ?? {};
|
|
1257
|
+
const providers = {
|
|
1258
|
+
...recommendation.providers,
|
|
1259
|
+
};
|
|
1260
|
+
for (const [provider, existingValue] of Object.entries(existingProviders)) {
|
|
1261
|
+
const recommendedValue = recommendation.providers[provider];
|
|
1262
|
+
if (recommendedValue &&
|
|
1263
|
+
typeof recommendedValue !== 'string' &&
|
|
1264
|
+
typeof existingValue !== 'string') {
|
|
1265
|
+
providers[provider] = { ...recommendedValue, ...existingValue };
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
providers[provider] = existingValue;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1174
1271
|
return {
|
|
1175
1272
|
...(workflow ?? {}),
|
|
1176
1273
|
dispatchCeiling: {
|
|
1177
1274
|
...workflow?.dispatchCeiling,
|
|
1178
1275
|
recommendationVersion: recommendation.version,
|
|
1179
|
-
providers
|
|
1276
|
+
providers,
|
|
1180
1277
|
},
|
|
1181
1278
|
};
|
|
1182
1279
|
}
|
|
1183
|
-
async function confirmDispatchMatrixOverwrite(context, dependencies, source, yes) {
|
|
1184
|
-
if (yes) {
|
|
1185
|
-
return;
|
|
1186
|
-
}
|
|
1187
|
-
if (!context.interactive) {
|
|
1188
|
-
throw new Error('Dispatch matrix already exists; rerun interactively or pass --yes to replace it.');
|
|
1189
|
-
}
|
|
1190
|
-
const shouldReplace = await dependencies.confirmAction(`Replace existing dispatch matrix in ${source} config?`, { interactive: context.interactive });
|
|
1191
|
-
if (!shouldReplace) {
|
|
1192
|
-
throw new Error('Dispatch matrix adoption cancelled; existing matrix unchanged.');
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
1280
|
async function adoptDispatchMatrixRecommendation(repoRoot, userConfigDir, options, context, dependencies) {
|
|
1196
1281
|
const source = options.surface === 'auto' ? 'local' : options.surface;
|
|
1197
1282
|
const recommendation = await loadDispatchMatrixRecommendation(dependencies);
|
|
1198
1283
|
if (source === 'user') {
|
|
1199
1284
|
const userConfig = await dependencies.readUserConfig(userConfigDir);
|
|
1200
|
-
if (hasExistingDispatchMatrix(userConfig)) {
|
|
1201
|
-
await confirmDispatchMatrixOverwrite(context, dependencies, source, options.yes);
|
|
1202
|
-
}
|
|
1203
1285
|
await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
|
|
1204
1286
|
await dependencies.writeUserConfig(userConfigDir, {
|
|
1205
1287
|
...userConfig,
|
|
@@ -1213,9 +1295,6 @@ async function adoptDispatchMatrixRecommendation(repoRoot, userConfigDir, option
|
|
|
1213
1295
|
}
|
|
1214
1296
|
if (source === 'local') {
|
|
1215
1297
|
const localConfig = await dependencies.readOatLocalConfig(repoRoot);
|
|
1216
|
-
if (hasExistingDispatchMatrix(localConfig)) {
|
|
1217
|
-
await confirmDispatchMatrixOverwrite(context, dependencies, source, options.yes);
|
|
1218
|
-
}
|
|
1219
1298
|
await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
|
|
1220
1299
|
await dependencies.writeOatLocalConfig(repoRoot, {
|
|
1221
1300
|
...localConfig,
|
|
@@ -1228,9 +1307,6 @@ async function adoptDispatchMatrixRecommendation(repoRoot, userConfigDir, option
|
|
|
1228
1307
|
};
|
|
1229
1308
|
}
|
|
1230
1309
|
const sharedConfig = await dependencies.readOatConfig(repoRoot);
|
|
1231
|
-
if (hasExistingDispatchMatrix(sharedConfig)) {
|
|
1232
|
-
await confirmDispatchMatrixOverwrite(context, dependencies, source, options.yes);
|
|
1233
|
-
}
|
|
1234
1310
|
await validateRecommendationCells(repoRoot, recommendation, dependencies, context.logger.warn);
|
|
1235
1311
|
await dependencies.writeOatConfig(repoRoot, {
|
|
1236
1312
|
...sharedConfig,
|
|
@@ -1509,7 +1585,7 @@ export function createConfigCommand(overrides = {}) {
|
|
|
1509
1585
|
.option('--shared', 'Write to the shared repo config (.oat/config.json)')
|
|
1510
1586
|
.option('--local', 'Write to the repo-local config (.oat/config.local.json)')
|
|
1511
1587
|
.option('--user', 'Write to the user-level config (~/.oat/config.json)')
|
|
1512
|
-
.option('--yes', '
|
|
1588
|
+
.option('--yes', 'Compatibility flag; adoption always preserves explicit existing cells')
|
|
1513
1589
|
.action(async (template, options, command) => {
|
|
1514
1590
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
1515
1591
|
try {
|
|
@@ -1528,7 +1604,7 @@ export function createConfigCommand(overrides = {}) {
|
|
|
1528
1604
|
surface = 'local';
|
|
1529
1605
|
else if (options.user)
|
|
1530
1606
|
surface = 'user';
|
|
1531
|
-
await runAdopt(template, { surface
|
|
1607
|
+
await runAdopt(template, { surface }, context, dependencies);
|
|
1532
1608
|
}
|
|
1533
1609
|
catch (error) {
|
|
1534
1610
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -2,7 +2,7 @@ import { type CommandContext, type GlobalOptions } from '../../app/command-conte
|
|
|
2
2
|
import { type PjmDoctorOptions } from '../pjm/doctor.js';
|
|
3
3
|
import { type OatConfig, type OatLocalConfig, type UserConfig } from '../../config/oat-config.js';
|
|
4
4
|
import { type Manifest } from '../../manifest/index.js';
|
|
5
|
-
import { type
|
|
5
|
+
import { type MatrixCellAvailabilityResponse, type ValidateMatrixCellOptions } from '../../providers/identity/availability.js';
|
|
6
6
|
import type { ConcreteScope } from '../../shared/types.js';
|
|
7
7
|
import { type DoctorCheck } from '../../ui/output.js';
|
|
8
8
|
import { Command } from 'commander';
|
|
@@ -22,7 +22,7 @@ interface DoctorDependencies {
|
|
|
22
22
|
readOatConfig: (repoRoot: string) => Promise<OatConfig>;
|
|
23
23
|
readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
|
|
24
24
|
readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
|
|
25
|
-
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<
|
|
25
|
+
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
|
|
26
26
|
processEnv: NodeJS.ProcessEnv;
|
|
27
27
|
runPjmDoctorChecks: (repoRoot: string, options?: PjmDoctorOptions) => Promise<DoctorCheck[]>;
|
|
28
28
|
checkSkillVersions: (scopeRoot: string, assetsRoot: string, pathExists: (path: string) => Promise<boolean>) => Promise<SkillVersionReport>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
|