@open-agent-toolkit/cli 0.1.48 → 0.1.50
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/docs/cli-utilities/configuration.md +41 -0
- package/assets/docs/cli-utilities/workflow-gates.md +17 -0
- package/assets/docs/provider-sync/providers.md +5 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +59 -7
- package/assets/docs/workflows/projects/implementation-execution.md +34 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +49 -22
- package/assets/skills/oat-project-review-provide/SKILL.md +18 -2
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +28 -1
- package/dist/commands/config/index.d.ts +3 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +70 -128
- package/dist/commands/doctor/index.d.ts +3 -0
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +57 -110
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +71 -0
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +144 -112
- package/dist/config/dispatch-matrix.d.ts +59 -0
- package/dist/config/dispatch-matrix.d.ts.map +1 -0
- package/dist/config/dispatch-matrix.js +264 -0
- package/dist/config/oat-config.d.ts +2 -28
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +8 -144
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +2 -1
- package/dist/providers/identity/availability.d.ts +12 -0
- package/dist/providers/identity/availability.d.ts.map +1 -1
- package/dist/providers/identity/availability.js +72 -29
- package/dist/providers/identity/dispatch-report.d.ts +124 -0
- package/dist/providers/identity/dispatch-report.d.ts.map +1 -0
- package/dist/providers/identity/dispatch-report.js +285 -0
- package/dist/providers/identity/dispatch-validation.d.ts +28 -0
- package/dist/providers/identity/dispatch-validation.d.ts.map +1 -0
- package/dist/providers/identity/dispatch-validation.js +149 -0
- package/dist/providers/identity/stamp.d.ts +2 -0
- package/dist/providers/identity/stamp.d.ts.map +1 -1
- package/dist/providers/identity/stamp.js +3 -1
- package/package.json +2 -2
|
@@ -5,12 +5,14 @@ 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 { normalizeDispatchMatrix, validateDispatchRouteTarget, walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
|
|
8
9
|
import { dispatchPolicyModeDescription, dispatchPolicyPolicyDescription, managedDispatchPolicyValueList, } from '../../config/dispatch-policy-options.js';
|
|
9
|
-
import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES,
|
|
10
|
+
import { VALID_DISPATCH_POLICY_MODES, VALID_MANAGED_DISPATCH_POLICIES, readOatConfig, readOatLocalConfig, readUserConfig, writeOatConfig, writeOatLocalConfig, writeUserConfig, } from '../../config/oat-config.js';
|
|
10
11
|
import { resolveEffectiveConfig, } from '../../config/resolve.js';
|
|
11
12
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
12
13
|
import { resolveProjectRoot } from '../../fs/paths.js';
|
|
13
14
|
import { normalizeMatrixCellAvailability, validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
15
|
+
import { createDispatchValidationPassContext, validateDispatchMatrixRefs, } from '../../providers/identity/dispatch-validation.js';
|
|
14
16
|
import { Command } from 'commander';
|
|
15
17
|
import { createConfigDumpCommand } from './dump.js';
|
|
16
18
|
const DISPATCH_CEILING_PROVIDER_KEY_PREFIX = 'workflow.dispatchCeiling.providers.';
|
|
@@ -563,6 +565,8 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
563
565
|
readFile: (path) => readFileDefault(path, 'utf8'),
|
|
564
566
|
confirmAction,
|
|
565
567
|
validateMatrixCell,
|
|
568
|
+
createDispatchValidationPassContext,
|
|
569
|
+
validateDispatchMatrixRefs,
|
|
566
570
|
processEnv: process.env,
|
|
567
571
|
};
|
|
568
572
|
function isConfigKey(value) {
|
|
@@ -765,130 +769,62 @@ function parseDispatchMatrixRecommendation(raw) {
|
|
|
765
769
|
if (!isRecord(parsed.providers)) {
|
|
766
770
|
throw new Error('Dispatch matrix recommendation asset is missing providers.');
|
|
767
771
|
}
|
|
772
|
+
const normalized = normalizeDispatchMatrix(parsed.providers, {
|
|
773
|
+
pathPrefix: 'workflow.dispatchCeiling.providers',
|
|
774
|
+
compatibilityMode: 'layered-config',
|
|
775
|
+
});
|
|
768
776
|
return {
|
|
769
777
|
version,
|
|
770
|
-
providers:
|
|
778
|
+
providers: normalized.providers,
|
|
779
|
+
issues: normalized.issues,
|
|
771
780
|
};
|
|
772
781
|
}
|
|
773
|
-
function
|
|
774
|
-
return
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
782
|
+
function collectDispatchMatrixCellRefs(providers) {
|
|
783
|
+
return walkDispatchMatrix(providers, {
|
|
784
|
+
source: 'repo-config',
|
|
785
|
+
pathPrefix: 'workflow.dispatchCeiling.providers',
|
|
786
|
+
});
|
|
778
787
|
}
|
|
779
|
-
function
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
return
|
|
788
|
-
}
|
|
789
|
-
if (!isRouteTarget(entry)) {
|
|
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
|
-
}
|
|
803
|
-
}
|
|
804
|
-
if (entry.model) {
|
|
805
|
-
refs.push({
|
|
806
|
-
provider: targetProvider,
|
|
807
|
-
value: entry.model,
|
|
808
|
-
path: `${entryPath}.model`,
|
|
809
|
-
});
|
|
810
|
-
}
|
|
811
|
-
if (entry.effort) {
|
|
812
|
-
refs.push({
|
|
813
|
-
provider: targetProvider,
|
|
814
|
-
value: entry.effort,
|
|
815
|
-
path: `${entryPath}.effort`,
|
|
816
|
-
});
|
|
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);
|
|
788
|
+
function collectDispatchMatrixTargetValidationErrors(refs, issues) {
|
|
789
|
+
const errors = issues.map((issue) => {
|
|
790
|
+
const relativePath = issue.path.startsWith(DISPATCH_CEILING_PROVIDER_KEY_PREFIX)
|
|
791
|
+
? issue.path.slice(DISPATCH_CEILING_PROVIDER_KEY_PREFIX.length)
|
|
792
|
+
: '';
|
|
793
|
+
const provider = relativePath.split(/[.[]/, 1)[0] ?? '';
|
|
794
|
+
const closedValues = closedDispatchProviderValues(provider);
|
|
795
|
+
if (typeof issue.value === 'string' && closedValues) {
|
|
796
|
+
return `Invalid value for ${issue.path}: expected one of ${closedValues.join(' | ')}, got '${issue.value}'`;
|
|
829
797
|
}
|
|
830
|
-
return
|
|
831
|
-
}
|
|
832
|
-
for (const
|
|
833
|
-
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
function collectDispatchMatrixCellRefs(providers) {
|
|
837
|
-
const refs = [];
|
|
838
|
-
for (const [provider, providerValue] of Object.entries(providers)) {
|
|
839
|
-
const providerPath = `workflow.dispatchCeiling.providers.${provider}`;
|
|
840
|
-
if (typeof providerValue === 'string') {
|
|
841
|
-
refs.push({ provider, value: providerValue, path: providerPath });
|
|
798
|
+
return `${issue.path}: malformed dispatch matrix entry (${issue.kind}).`;
|
|
799
|
+
});
|
|
800
|
+
for (const ref of refs) {
|
|
801
|
+
if (ref.target === null) {
|
|
842
802
|
continue;
|
|
843
803
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}
|
|
848
|
-
addDispatchMatrixCellRefs(refs, provider, `${providerPath}.${tier}`, cell);
|
|
804
|
+
const validation = validateDispatchRouteTarget(ref.provider, ref.target);
|
|
805
|
+
if (!validation.valid) {
|
|
806
|
+
errors.push(`${ref.path}: ${validation.reason}`);
|
|
849
807
|
}
|
|
850
808
|
}
|
|
851
|
-
return
|
|
809
|
+
return errors;
|
|
852
810
|
}
|
|
853
|
-
function
|
|
854
|
-
|
|
855
|
-
|
|
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
|
-
}
|
|
811
|
+
function toAvailabilityRef(ref) {
|
|
812
|
+
if (ref.value !== null) {
|
|
813
|
+
return { provider: ref.provider, value: ref.value, path: ref.path };
|
|
890
814
|
}
|
|
891
|
-
|
|
815
|
+
if (ref.target === null) {
|
|
816
|
+
return null;
|
|
817
|
+
}
|
|
818
|
+
const value = ref.target.model ?? ref.target.effort;
|
|
819
|
+
if (!value) {
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
return {
|
|
823
|
+
provider: ref.target.harness ?? ref.provider,
|
|
824
|
+
value,
|
|
825
|
+
path: ref.path,
|
|
826
|
+
target: ref.target,
|
|
827
|
+
};
|
|
892
828
|
}
|
|
893
829
|
function applyWorkflowValue(workflow, key, value) {
|
|
894
830
|
const subKey = key.slice('workflow.'.length);
|
|
@@ -1225,28 +1161,34 @@ async function loadDispatchMatrixRecommendation(dependencies) {
|
|
|
1225
1161
|
return parseDispatchMatrixRecommendation(await dependencies.readFile(assetPath));
|
|
1226
1162
|
}
|
|
1227
1163
|
async function validateRecommendationCells(repoRoot, recommendation, dependencies, warn) {
|
|
1228
|
-
const
|
|
1164
|
+
const refs = collectDispatchMatrixCellRefs(recommendation.providers);
|
|
1165
|
+
const targetErrors = collectDispatchMatrixTargetValidationErrors(refs, recommendation.issues);
|
|
1229
1166
|
if (targetErrors.length > 0) {
|
|
1230
1167
|
throw new Error(targetErrors.join('\n'));
|
|
1231
1168
|
}
|
|
1232
|
-
|
|
1169
|
+
const availabilityRefs = refs.filter((matrixRef) => {
|
|
1170
|
+
const ref = toAvailabilityRef(matrixRef);
|
|
1171
|
+
if (ref === null) {
|
|
1172
|
+
return false;
|
|
1173
|
+
}
|
|
1233
1174
|
const closedValues = closedDispatchProviderValues(ref.provider);
|
|
1234
1175
|
if (!ref.target && closedValues && !closedValues.includes(ref.value)) {
|
|
1235
1176
|
throw new Error(`Invalid value for ${ref.path}: expected one of ${closedValues.join(' | ')}, got '${ref.value}'`);
|
|
1236
1177
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1178
|
+
return true;
|
|
1179
|
+
});
|
|
1180
|
+
const pass = dependencies.createDispatchValidationPassContext({
|
|
1181
|
+
cwd: repoRoot,
|
|
1182
|
+
env: dependencies.processEnv,
|
|
1183
|
+
validateMatrixCell: dependencies.validateMatrixCell,
|
|
1184
|
+
});
|
|
1185
|
+
const results = await dependencies.validateDispatchMatrixRefs(availabilityRefs, pass);
|
|
1186
|
+
for (const result of results) {
|
|
1187
|
+
const ref = toAvailabilityRef(result.ref);
|
|
1188
|
+
const warning = matrixCellAvailabilityWarning(ref.path, ref.value, {
|
|
1189
|
+
availability: result.status,
|
|
1190
|
+
...(result.diagnostic ? { message: result.diagnostic } : {}),
|
|
1191
|
+
});
|
|
1250
1192
|
if (warning) {
|
|
1251
1193
|
warn(warning);
|
|
1252
1194
|
}
|
|
@@ -3,6 +3,7 @@ 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
5
|
import { type MatrixCellAvailabilityResponse, type ValidateMatrixCellOptions } from '../../providers/identity/availability.js';
|
|
6
|
+
import { createDispatchValidationPassContext, validateDispatchMatrixRefs } from '../../providers/identity/dispatch-validation.js';
|
|
6
7
|
import type { ConcreteScope } from '../../shared/types.js';
|
|
7
8
|
import { type DoctorCheck } from '../../ui/output.js';
|
|
8
9
|
import { Command } from 'commander';
|
|
@@ -23,6 +24,8 @@ interface DoctorDependencies {
|
|
|
23
24
|
readOatLocalConfig: (repoRoot: string) => Promise<OatLocalConfig>;
|
|
24
25
|
readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
|
|
25
26
|
validateMatrixCell: (provider: string, value: string, options: ValidateMatrixCellOptions) => Promise<MatrixCellAvailabilityResponse>;
|
|
27
|
+
createDispatchValidationPassContext: typeof createDispatchValidationPassContext;
|
|
28
|
+
validateDispatchMatrixRefs: typeof validateDispatchMatrixRefs;
|
|
26
29
|
processEnv: NodeJS.ProcessEnv;
|
|
27
30
|
runPjmDoctorChecks: (repoRoot: string, options?: PjmDoctorOptions) => Promise<DoctorCheck[]>;
|
|
28
31
|
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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,8 @@ import { createPjmDisabledCheck, runPjmDoctorChecks, } from '../pjm/doctor.js';
|
|
|
7
7
|
import { getSkillVersion } from '../shared/frontmatter.js';
|
|
8
8
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
9
9
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
10
|
-
import {
|
|
10
|
+
import { walkDispatchMatrix, } from '../../config/dispatch-matrix.js';
|
|
11
|
+
import { readOatConfig, readOatLocalConfig, readUserConfig, } from '../../config/oat-config.js';
|
|
11
12
|
import { resolveAssetsRoot } from '../../fs/assets.js';
|
|
12
13
|
import { resolveProjectRoot, resolveScopeRoot } from '../../fs/paths.js';
|
|
13
14
|
import TOML from '@iarna/toml';
|
|
@@ -18,7 +19,8 @@ import { isOatManagedCodexRoleFile } from '../../providers/codex/codec/shared.js
|
|
|
18
19
|
import { copilotAdapter } from '../../providers/copilot/index.js';
|
|
19
20
|
import { cursorAdapter } from '../../providers/cursor/index.js';
|
|
20
21
|
import { geminiAdapter } from '../../providers/gemini/index.js';
|
|
21
|
-
import {
|
|
22
|
+
import { validateMatrixCell, } from '../../providers/identity/availability.js';
|
|
23
|
+
import { createDispatchValidationPassContext, validateDispatchMatrixRefs, } from '../../providers/identity/dispatch-validation.js';
|
|
22
24
|
import { formatDoctorResults } from '../../ui/output.js';
|
|
23
25
|
import { Command } from 'commander';
|
|
24
26
|
async function pathExistsDefault(path) {
|
|
@@ -134,6 +136,8 @@ function createDependencies() {
|
|
|
134
136
|
readOatLocalConfig,
|
|
135
137
|
readUserConfig,
|
|
136
138
|
validateMatrixCell,
|
|
139
|
+
createDispatchValidationPassContext,
|
|
140
|
+
validateDispatchMatrixRefs,
|
|
137
141
|
processEnv: process.env,
|
|
138
142
|
runPjmDoctorChecks,
|
|
139
143
|
// Default binding remains self-contained, but still honors the caller-
|
|
@@ -141,97 +145,46 @@ function createDependencies() {
|
|
|
141
145
|
checkSkillVersions: (scopeRoot, assetsRoot, pathExists = pathExistsDefault) => checkSkillVersionsDefault(scopeRoot, assetsRoot, pathExists),
|
|
142
146
|
};
|
|
143
147
|
}
|
|
144
|
-
function
|
|
145
|
-
return
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
function collectDispatchMatrixCellRefs(layers) {
|
|
149
|
+
return layers.flatMap(({ source, config }) => {
|
|
150
|
+
const providers = config.workflow?.dispatchCeiling?.providers ?? {};
|
|
151
|
+
return walkDispatchMatrix(providers, {
|
|
152
|
+
source,
|
|
153
|
+
pathPrefix: 'workflow.dispatchCeiling.providers',
|
|
154
|
+
});
|
|
155
|
+
});
|
|
149
156
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
function dispatchMatrixSourceLabel(source) {
|
|
158
|
+
switch (source) {
|
|
159
|
+
case 'user-config':
|
|
160
|
+
return 'user';
|
|
161
|
+
case 'repo-config':
|
|
162
|
+
return 'shared';
|
|
163
|
+
case 'local-config':
|
|
164
|
+
return 'local';
|
|
165
|
+
case 'project-state':
|
|
166
|
+
return 'project-state';
|
|
154
167
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
const targetProvider = entry.harness ?? provider;
|
|
164
|
-
if (isCodexMaterializedRouteTarget(provider, entry)) {
|
|
165
|
-
if (entry.model && entry.effort) {
|
|
166
|
-
refs.push({
|
|
167
|
-
layer,
|
|
168
|
-
provider: targetProvider,
|
|
169
|
-
value: formatRouteTargetValue(entry),
|
|
170
|
-
path: entryPath,
|
|
171
|
-
target: entry,
|
|
172
|
-
});
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
if (entry.model) {
|
|
177
|
-
refs.push({
|
|
178
|
-
layer,
|
|
179
|
-
provider: targetProvider,
|
|
180
|
-
value: entry.model,
|
|
181
|
-
path: `${entryPath}.model`,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
if (entry.effort) {
|
|
185
|
-
refs.push({
|
|
186
|
-
layer,
|
|
187
|
-
provider: targetProvider,
|
|
188
|
-
value: entry.effort,
|
|
189
|
-
path: `${entryPath}.effort`,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
if (isWorkflowDispatchCandidateLadder(cell)) {
|
|
194
|
-
for (const [candidateIndex, candidate] of cell.candidates.entries()) {
|
|
195
|
-
const candidatePath = `${path}.candidates[${candidateIndex}]`;
|
|
196
|
-
if (isWorkflowDispatchFallbackRoute(candidate)) {
|
|
197
|
-
for (const [routeIndex, entry] of candidate.route.entries()) {
|
|
198
|
-
addEntry(entry, `${candidatePath}.route[${routeIndex}]`);
|
|
199
|
-
}
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
addEntry(candidate, candidatePath);
|
|
203
|
-
}
|
|
204
|
-
return;
|
|
168
|
+
}
|
|
169
|
+
function dispatchMatrixRefValue(ref) {
|
|
170
|
+
return ref.value ?? ref.target?.model ?? ref.target?.effort ?? 'unknown';
|
|
171
|
+
}
|
|
172
|
+
function dispatchMatrixAvailabilityRef(ref) {
|
|
173
|
+
if (ref.value !== null) {
|
|
174
|
+
return { provider: ref.provider, value: ref.value, target: null };
|
|
205
175
|
}
|
|
206
|
-
|
|
207
|
-
|
|
176
|
+
if (ref.target === null) {
|
|
177
|
+
return null;
|
|
208
178
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
for (const { layer, config } of layers) {
|
|
213
|
-
const providers = config.workflow?.dispatchCeiling?.providers ?? {};
|
|
214
|
-
for (const [provider, providerValue] of Object.entries(providers)) {
|
|
215
|
-
const providerPath = `workflow.dispatchCeiling.providers.${provider}`;
|
|
216
|
-
if (typeof providerValue === 'string') {
|
|
217
|
-
refs.push({
|
|
218
|
-
layer,
|
|
219
|
-
provider,
|
|
220
|
-
value: providerValue,
|
|
221
|
-
path: providerPath,
|
|
222
|
-
});
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
const tierMap = providerValue;
|
|
226
|
-
for (const [tier, cell] of Object.entries(tierMap)) {
|
|
227
|
-
if (cell === undefined) {
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
addDispatchMatrixCellRefs(refs, layer, provider, `${providerPath}.${tier}`, cell);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
179
|
+
const value = ref.target.model ?? ref.target.effort;
|
|
180
|
+
if (!value) {
|
|
181
|
+
return null;
|
|
233
182
|
}
|
|
234
|
-
return
|
|
183
|
+
return {
|
|
184
|
+
provider: ref.target.harness ?? ref.provider,
|
|
185
|
+
value,
|
|
186
|
+
target: ref.target,
|
|
187
|
+
};
|
|
235
188
|
}
|
|
236
189
|
function formatDispatchMatrixIssueList(issues) {
|
|
237
190
|
return issues
|
|
@@ -239,12 +192,12 @@ function formatDispatchMatrixIssueList(issues) {
|
|
|
239
192
|
const suffix = 'message' in issue && typeof issue.message === 'string'
|
|
240
193
|
? `; ${issue.message}`
|
|
241
194
|
: '';
|
|
242
|
-
return `${issue.path}=${issue
|
|
195
|
+
return `${issue.path}=${dispatchMatrixRefValue(issue)} (${dispatchMatrixSourceLabel(issue.source)} config)${suffix}`;
|
|
243
196
|
})
|
|
244
197
|
.join(', ');
|
|
245
198
|
}
|
|
246
199
|
async function createDispatchMatrixDoctorCheck(scopeRoot, layers, dependencies) {
|
|
247
|
-
const refs = collectDispatchMatrixCellRefs(layers);
|
|
200
|
+
const refs = collectDispatchMatrixCellRefs(layers).filter((ref) => dispatchMatrixAvailabilityRef(ref) !== null);
|
|
248
201
|
if (refs.length === 0) {
|
|
249
202
|
return {
|
|
250
203
|
name: 'project:dispatch_matrix',
|
|
@@ -253,25 +206,19 @@ async function createDispatchMatrixDoctorCheck(scopeRoot, layers, dependencies)
|
|
|
253
206
|
message: 'No configured dispatch matrix cells found in user, shared, or local config layers.',
|
|
254
207
|
};
|
|
255
208
|
}
|
|
209
|
+
const pass = dependencies.createDispatchValidationPassContext({
|
|
210
|
+
cwd: scopeRoot,
|
|
211
|
+
env: dependencies.processEnv,
|
|
212
|
+
validateMatrixCell: dependencies.validateMatrixCell,
|
|
213
|
+
});
|
|
214
|
+
const results = await dependencies.validateDispatchMatrixRefs(refs, pass);
|
|
256
215
|
const issues = [];
|
|
257
|
-
for (const
|
|
258
|
-
|
|
259
|
-
try {
|
|
260
|
-
result = normalizeMatrixCellAvailability(await dependencies.validateMatrixCell(ref.provider, ref.value, {
|
|
261
|
-
cwd: scopeRoot,
|
|
262
|
-
env: dependencies.processEnv,
|
|
263
|
-
detailed: true,
|
|
264
|
-
...(ref.target ? { target: ref.target } : {}),
|
|
265
|
-
}));
|
|
266
|
-
}
|
|
267
|
-
catch {
|
|
268
|
-
result = { availability: 'unvalidated' };
|
|
269
|
-
}
|
|
270
|
-
if (result.availability !== 'valid') {
|
|
216
|
+
for (const result of results) {
|
|
217
|
+
if (result.status !== 'valid') {
|
|
271
218
|
issues.push({
|
|
272
|
-
...ref,
|
|
273
|
-
availability: result.
|
|
274
|
-
...(result.
|
|
219
|
+
...result.ref,
|
|
220
|
+
availability: result.status,
|
|
221
|
+
...(result.diagnostic ? { message: result.diagnostic } : {}),
|
|
275
222
|
});
|
|
276
223
|
}
|
|
277
224
|
}
|
|
@@ -547,9 +494,9 @@ async function runChecksForScope(scope, scopeRoot, userConfigDir, dependencies)
|
|
|
547
494
|
dependencies.readOatLocalConfig(scopeRoot),
|
|
548
495
|
]);
|
|
549
496
|
checks.push(await createDispatchMatrixDoctorCheck(scopeRoot, [
|
|
550
|
-
{
|
|
551
|
-
{
|
|
552
|
-
{
|
|
497
|
+
{ source: 'user-config', config: userConfig },
|
|
498
|
+
{ source: 'repo-config', config },
|
|
499
|
+
{ source: 'local-config', config: localConfig },
|
|
553
500
|
], dependencies));
|
|
554
501
|
const projectManagementEnabled = config.tools?.['project-management'] === true;
|
|
555
502
|
if (projectManagementEnabled) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAQ9B,OAAO,EAQL,KAAK,UAAU,EAIf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/index.ts"],"names":[],"mappings":"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"}
|