@open-agent-toolkit/cli 0.1.32 → 0.1.34
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/config-and-local-state.md +21 -1
- package/assets/docs/cli-utilities/configuration.md +17 -6
- package/assets/docs/cli-utilities/index.md +5 -0
- package/assets/docs/cli-utilities/tool-packs.md +1 -1
- package/assets/docs/cli-utilities/workflow-gates.md +163 -0
- package/assets/docs/contributing/skills.md +25 -0
- package/assets/docs/reference/cli-reference.md +17 -14
- package/assets/docs/reference/file-locations.md +1 -0
- package/assets/docs/reference/oat-directory-structure.md +3 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/scripts/resolve-tracking.sh +52 -0
- package/assets/skills/oat-project-implement/SKILL.md +23 -1
- package/assets/skills/oat-project-plan/SKILL.md +23 -1
- package/dist/commands/doctor/index.d.ts +4 -1
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +12 -3
- package/dist/commands/gate/index.d.ts +35 -0
- package/dist/commands/gate/index.d.ts.map +1 -0
- package/dist/commands/gate/index.js +500 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/internal/validate-oat-skills.d.ts +3 -0
- package/dist/commands/internal/validate-oat-skills.d.ts.map +1 -1
- package/dist/commands/internal/validate-oat-skills.js +44 -2
- package/dist/commands/pjm/doctor.d.ts +5 -1
- package/dist/commands/pjm/doctor.d.ts.map +1 -1
- package/dist/commands/pjm/doctor.js +13 -1
- package/dist/commands/pjm/index.d.ts.map +1 -1
- package/dist/commands/pjm/index.js +5 -2
- package/dist/commands/sync/apply.d.ts.map +1 -1
- package/dist/commands/sync/apply.js +6 -2
- package/dist/config/oat-config.d.ts +22 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +136 -0
- package/dist/config/resolve.d.ts +3 -1
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +103 -1
- package/dist/manifest/manager.d.ts.map +1 -1
- package/dist/manifest/manager.js +4 -1
- package/dist/validation/skills.d.ts +2 -0
- package/dist/validation/skills.d.ts.map +1 -1
- package/dist/validation/skills.js +39 -0
- package/package.json +2 -2
|
@@ -1,11 +1,30 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
1
2
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
2
3
|
import { readGlobalOptions } from '../shared/shared.utils.js';
|
|
4
|
+
import { resolveEffectiveConfig as defaultResolveEffectiveConfig, } from '../../config/resolve.js';
|
|
3
5
|
import { validateOatSkills as defaultValidateOatSkills, } from '../../validation/index.js';
|
|
4
6
|
import { Command } from 'commander';
|
|
5
7
|
const DEFAULT_DEPENDENCIES = {
|
|
6
8
|
buildCommandContext,
|
|
7
9
|
validateOatSkills: defaultValidateOatSkills,
|
|
10
|
+
resolveEffectiveConfig: defaultResolveEffectiveConfig,
|
|
8
11
|
};
|
|
12
|
+
function collectConfiguredGateSkillNames(effective) {
|
|
13
|
+
const names = new Set();
|
|
14
|
+
for (const layer of [effective.shared, effective.local, effective.user]) {
|
|
15
|
+
const skills = layer.workflow?.gates?.skills;
|
|
16
|
+
if (!skills) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
for (const skillName of Object.keys(skills)) {
|
|
20
|
+
names.add(skillName);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [...names].sort();
|
|
24
|
+
}
|
|
25
|
+
function isBlockingFinding(finding) {
|
|
26
|
+
return finding.severity !== 'warning';
|
|
27
|
+
}
|
|
9
28
|
function reportFindings(context, result) {
|
|
10
29
|
if (context.json) {
|
|
11
30
|
context.logger.json({
|
|
@@ -21,14 +40,37 @@ function reportFindings(context, result) {
|
|
|
21
40
|
}
|
|
22
41
|
context.logger.error('\nFix the issues above, then re-run: pnpm oat:validate-skills');
|
|
23
42
|
}
|
|
43
|
+
function reportWarnings(context, result) {
|
|
44
|
+
if (context.json) {
|
|
45
|
+
context.logger.json({
|
|
46
|
+
status: 'ok',
|
|
47
|
+
validatedSkillCount: result.validatedSkillCount,
|
|
48
|
+
findings: result.findings,
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
context.logger.warn('OAT skill validation warnings:\n');
|
|
53
|
+
for (const finding of result.findings) {
|
|
54
|
+
context.logger.warn(`- ${finding.file}: ${finding.message}`);
|
|
55
|
+
}
|
|
56
|
+
context.logger.info(`OK: validated ${result.validatedSkillCount} oat-* skills`);
|
|
57
|
+
}
|
|
24
58
|
async function runValidateOatSkills(context, options, dependencies) {
|
|
25
59
|
try {
|
|
26
|
-
const
|
|
27
|
-
|
|
60
|
+
const effectiveConfig = await dependencies.resolveEffectiveConfig(context.cwd, join(context.home, '.oat'), dependencies.env ?? process.env);
|
|
61
|
+
const gateSkillNames = collectConfiguredGateSkillNames(effectiveConfig);
|
|
62
|
+
const validationOptions = gateSkillNames.length > 0 ? { ...options, gateSkillNames } : options;
|
|
63
|
+
const result = await dependencies.validateOatSkills(context.cwd, validationOptions);
|
|
64
|
+
if (result.findings.some(isBlockingFinding)) {
|
|
28
65
|
reportFindings(context, result);
|
|
29
66
|
process.exitCode = 1;
|
|
30
67
|
return;
|
|
31
68
|
}
|
|
69
|
+
if (result.findings.length > 0) {
|
|
70
|
+
reportWarnings(context, result);
|
|
71
|
+
process.exitCode = 0;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
32
74
|
if (context.json) {
|
|
33
75
|
context.logger.json({
|
|
34
76
|
status: 'ok',
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { DoctorCheck } from '../../ui/output.js';
|
|
2
|
-
export
|
|
2
|
+
export interface PjmDoctorOptions {
|
|
3
|
+
projectManagementEnabled?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function createPjmDisabledCheck(): DoctorCheck;
|
|
6
|
+
export declare function runPjmDoctorChecks(repoRoot: string, options?: PjmDoctorOptions): Promise<DoctorCheck[]>;
|
|
3
7
|
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0I9C,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/doctor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0I9C,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,wBAAgB,sBAAsB,IAAI,WAAW,CAQpD;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CAyJxB"}
|
|
@@ -114,7 +114,19 @@ function checkStatus(missing) {
|
|
|
114
114
|
function warnStatus(items) {
|
|
115
115
|
return items.length === 0 ? 'pass' : 'warn';
|
|
116
116
|
}
|
|
117
|
-
export
|
|
117
|
+
export function createPjmDisabledCheck() {
|
|
118
|
+
return {
|
|
119
|
+
name: 'pjm:disabled',
|
|
120
|
+
description: 'Project-management pack enablement',
|
|
121
|
+
status: 'pass',
|
|
122
|
+
message: 'Project-management pack is disabled; PJM checks skipped.',
|
|
123
|
+
fix: 'Run `oat init tools project-management` to install and enable PJM checks.',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export async function runPjmDoctorChecks(repoRoot, options = {}) {
|
|
127
|
+
if (options.projectManagementEnabled === false) {
|
|
128
|
+
return [createPjmDisabledCheck()];
|
|
129
|
+
}
|
|
118
130
|
const checks = [];
|
|
119
131
|
const missingCanonical = [];
|
|
120
132
|
for (const relativePath of CANONICAL_REPO_REFERENCE_PATHS) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAiBnE,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA6FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/pjm/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,uBAAuB,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAiBnE,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,sBAAsB,EAAE,OAAO,sBAAsB,CAAC;CACvD;AA6FD,wBAAgB,gBAAgB,CAC9B,SAAS,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC9C,OAAO,CAsJT"}
|
|
@@ -120,14 +120,17 @@ export function createPjmCommand(overrides = {}) {
|
|
|
120
120
|
});
|
|
121
121
|
cmd
|
|
122
122
|
.command('doctor')
|
|
123
|
-
.description('Run PJM repo reference diagnostics')
|
|
123
|
+
.description('Run PJM repo reference diagnostics when enabled')
|
|
124
124
|
.option('--repo-root <path>', 'PJM repo reference root directory (defaults to .oat/repo)')
|
|
125
125
|
.action(async (options, command) => {
|
|
126
126
|
const context = dependencies.buildCommandContext(readGlobalOptions(command));
|
|
127
127
|
try {
|
|
128
128
|
const projectRoot = await dependencies.resolveProjectRoot(context.cwd);
|
|
129
129
|
const repoRoot = await resolveRepoRoot(context, projectRoot, options.repoRoot);
|
|
130
|
-
const
|
|
130
|
+
const config = await dependencies.readOatConfig(projectRoot);
|
|
131
|
+
const checks = await dependencies.runPjmDoctorChecks(repoRoot, {
|
|
132
|
+
projectManagementEnabled: config.tools?.['project-management'] === true,
|
|
133
|
+
});
|
|
131
134
|
const status = doctorStatus(checks);
|
|
132
135
|
if (context.json) {
|
|
133
136
|
context.logger.json({ status, repoRoot, checks });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EACV,aAAa,EACb,uBAAuB,EAExB,MAAM,cAAc,CAAC;AAgEtB,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,aAAa,EAAE,EAC3B,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,IAAI,CAAC,CA8Ef"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OAT_VERSION } from '../../shared/oat-version.js';
|
|
1
2
|
import { countPlannedOperations } from './sync.utils.js';
|
|
2
3
|
function countSkippedEntries(scopePlans) {
|
|
3
4
|
return scopePlans.reduce((total, scopePlan) => {
|
|
@@ -45,10 +46,13 @@ export async function runSyncApply(context, scopePlans, dependencies) {
|
|
|
45
46
|
for (const scopePlan of scopePlans) {
|
|
46
47
|
const hasSyncEntries = scopePlan.plan.entries.length > 0 || scopePlan.plan.removals.length > 0;
|
|
47
48
|
const hasCodexPlannedOperations = scopePlan.codexExtensionPlan?.operations.some((operation) => operation.action !== 'skip') ?? false;
|
|
48
|
-
|
|
49
|
+
const shouldRefreshManifestVersion = scopePlan.manifest.oatVersion !== OAT_VERSION;
|
|
50
|
+
if (!hasSyncEntries &&
|
|
51
|
+
!hasCodexPlannedOperations &&
|
|
52
|
+
!shouldRefreshManifestVersion) {
|
|
49
53
|
continue;
|
|
50
54
|
}
|
|
51
|
-
if (hasSyncEntries) {
|
|
55
|
+
if (hasSyncEntries || shouldRefreshManifestVersion) {
|
|
52
56
|
const result = await dependencies.executeSyncPlan(scopePlan.plan, scopePlan.manifest, scopePlan.manifestPath);
|
|
53
57
|
applied += result.applied;
|
|
54
58
|
failed += result.failed;
|
|
@@ -23,6 +23,8 @@ export type WorkflowDesignMode = 'collaborative' | 'selective' | 'draft';
|
|
|
23
23
|
export type WorkflowCodexDispatchCeiling = 'low' | 'medium' | 'high' | 'xhigh';
|
|
24
24
|
export type WorkflowClaudeDispatchCeiling = 'haiku' | 'sonnet' | 'opus';
|
|
25
25
|
export type WorkflowDispatchCeilingPreset = 'balanced' | 'maximum' | 'cost-conscious';
|
|
26
|
+
export type GateOnFailure = 'block' | 'prompt' | 'warn';
|
|
27
|
+
export type GateAvoid = 'same-runtime' | 'none';
|
|
26
28
|
export interface WorkflowDispatchCeiling {
|
|
27
29
|
preset?: WorkflowDispatchCeilingPreset;
|
|
28
30
|
providers?: {
|
|
@@ -34,6 +36,24 @@ export interface WorkflowAutoArtifactReview {
|
|
|
34
36
|
plan?: boolean;
|
|
35
37
|
analysis?: boolean;
|
|
36
38
|
}
|
|
39
|
+
export interface GateConfig {
|
|
40
|
+
command: string;
|
|
41
|
+
onFailure: GateOnFailure;
|
|
42
|
+
description?: string;
|
|
43
|
+
maxAttempts?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface ExecTarget {
|
|
46
|
+
runtime: string;
|
|
47
|
+
baseCommand: string[];
|
|
48
|
+
hostDetectionCommand?: string[];
|
|
49
|
+
availabilityCommand?: string[];
|
|
50
|
+
priority: number;
|
|
51
|
+
}
|
|
52
|
+
export type ExecTargetConfig = Partial<ExecTarget>;
|
|
53
|
+
export interface WorkflowGatesConfig {
|
|
54
|
+
execTargets?: Record<string, ExecTargetConfig | null>;
|
|
55
|
+
skills?: Record<string, GateConfig | null>;
|
|
56
|
+
}
|
|
37
57
|
export interface OatWorkflowConfig {
|
|
38
58
|
hillCheckpointDefault?: WorkflowHillCheckpointDefault;
|
|
39
59
|
archiveOnComplete?: boolean;
|
|
@@ -45,10 +65,12 @@ export interface OatWorkflowConfig {
|
|
|
45
65
|
autoArtifactReview?: WorkflowAutoArtifactReview;
|
|
46
66
|
designMode?: WorkflowDesignMode;
|
|
47
67
|
dispatchCeiling?: WorkflowDispatchCeiling;
|
|
68
|
+
gates?: WorkflowGatesConfig;
|
|
48
69
|
}
|
|
49
70
|
export declare const VALID_CODEX_DISPATCH_CEILINGS: readonly WorkflowCodexDispatchCeiling[];
|
|
50
71
|
export declare const VALID_CLAUDE_DISPATCH_CEILINGS: readonly WorkflowClaudeDispatchCeiling[];
|
|
51
72
|
export declare const VALID_DISPATCH_CEILING_PRESETS: readonly WorkflowDispatchCeilingPreset[];
|
|
73
|
+
export declare const BUILTIN_EXEC_TARGETS: Readonly<Record<string, ExecTarget>>;
|
|
52
74
|
export type OatToolsConfig = Partial<Record<'core' | 'ideas' | 'docs' | 'workflows' | 'utility' | 'project-management' | 'research' | 'brainstorm', boolean>>;
|
|
53
75
|
export interface OatConfig {
|
|
54
76
|
version: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,6BAA6B,GACrC,MAAM,GACN,SAAS,GACT,IAAI,GACJ,SAAS,CAAC;AACd,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,QAAQ,GACR,eAAe,CAAC;AACpB,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,WAAW,GAAG,OAAO,CAAC;AACzE,MAAM,MAAM,4BAA4B,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAC/E,MAAM,MAAM,6BAA6B,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,6BAA6B,GACrC,UAAU,GACV,SAAS,GACT,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"oat-config.d.ts","sourceRoot":"","sources":["../../src/config/oat-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,128 @@ const VALID_DESIGN_MODES = [
|
|
|
19
19
|
export const VALID_CODEX_DISPATCH_CEILINGS = ['low', 'medium', 'high', 'xhigh'];
|
|
20
20
|
export const VALID_CLAUDE_DISPATCH_CEILINGS = ['haiku', 'sonnet', 'opus'];
|
|
21
21
|
export const VALID_DISPATCH_CEILING_PRESETS = ['balanced', 'maximum', 'cost-conscious'];
|
|
22
|
+
const VALID_GATE_ON_FAILURES = [
|
|
23
|
+
'block',
|
|
24
|
+
'prompt',
|
|
25
|
+
'warn',
|
|
26
|
+
];
|
|
27
|
+
export const BUILTIN_EXEC_TARGETS = {
|
|
28
|
+
'codex-default': {
|
|
29
|
+
runtime: 'codex',
|
|
30
|
+
baseCommand: ['codex', 'exec'],
|
|
31
|
+
hostDetectionCommand: [
|
|
32
|
+
'sh',
|
|
33
|
+
'-c',
|
|
34
|
+
'[ -n "$CODEX_THREAD_ID" ] || [ -n "$CODEX_SESSION_ID" ]',
|
|
35
|
+
],
|
|
36
|
+
availabilityCommand: ['codex', '--version'],
|
|
37
|
+
priority: 100,
|
|
38
|
+
},
|
|
39
|
+
'claude-default': {
|
|
40
|
+
runtime: 'claude',
|
|
41
|
+
baseCommand: ['claude', '-p'],
|
|
42
|
+
hostDetectionCommand: ['sh', '-c', 'test -n "$CLAUDECODE"'],
|
|
43
|
+
availabilityCommand: ['claude', '--version'],
|
|
44
|
+
priority: 100,
|
|
45
|
+
},
|
|
46
|
+
'cursor-default': {
|
|
47
|
+
runtime: 'cursor',
|
|
48
|
+
baseCommand: ['cursor-agent', '-p', '--force'],
|
|
49
|
+
hostDetectionCommand: ['sh', '-c', 'test -n "$CURSOR_AGENT"'],
|
|
50
|
+
availabilityCommand: ['cursor-agent', '--version'],
|
|
51
|
+
priority: 70,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
function normalizeMaxAttempts(value) {
|
|
55
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
56
|
+
return 2;
|
|
57
|
+
}
|
|
58
|
+
const attempts = Math.trunc(value);
|
|
59
|
+
return attempts >= 1 ? attempts : 2;
|
|
60
|
+
}
|
|
61
|
+
function normalizeArgv(value) {
|
|
62
|
+
if (!Array.isArray(value) ||
|
|
63
|
+
value.length === 0 ||
|
|
64
|
+
!value.every((item) => typeof item === 'string')) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const [executable] = value;
|
|
68
|
+
if (executable === undefined || !executable.trim()) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
return [...value];
|
|
72
|
+
}
|
|
73
|
+
function normalizeGateConfig(value) {
|
|
74
|
+
if (value === null) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
if (!isRecord(value)) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
const command = trimNonEmptyString(value.command);
|
|
81
|
+
if (command === undefined ||
|
|
82
|
+
typeof value.onFailure !== 'string' ||
|
|
83
|
+
!VALID_GATE_ON_FAILURES.includes(value.onFailure)) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const gate = {
|
|
87
|
+
command,
|
|
88
|
+
onFailure: value.onFailure,
|
|
89
|
+
maxAttempts: normalizeMaxAttempts(value.maxAttempts),
|
|
90
|
+
};
|
|
91
|
+
const description = trimNonEmptyString(value.description);
|
|
92
|
+
if (description !== undefined) {
|
|
93
|
+
gate.description = description;
|
|
94
|
+
}
|
|
95
|
+
return gate;
|
|
96
|
+
}
|
|
97
|
+
function normalizeExecTarget(value) {
|
|
98
|
+
if (value === null) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
if (!isRecord(value)) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const target = {};
|
|
105
|
+
const runtime = trimNonEmptyString(value.runtime);
|
|
106
|
+
if (runtime !== undefined) {
|
|
107
|
+
target.runtime = runtime;
|
|
108
|
+
}
|
|
109
|
+
const baseCommand = normalizeArgv(value.baseCommand);
|
|
110
|
+
if (baseCommand !== undefined) {
|
|
111
|
+
target.baseCommand = baseCommand;
|
|
112
|
+
}
|
|
113
|
+
if ('priority' in value) {
|
|
114
|
+
if (typeof value.priority === 'number' && Number.isFinite(value.priority)) {
|
|
115
|
+
target.priority = value.priority;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const hostDetectionCommand = normalizeArgv(value.hostDetectionCommand);
|
|
119
|
+
if (hostDetectionCommand !== undefined) {
|
|
120
|
+
target.hostDetectionCommand = hostDetectionCommand;
|
|
121
|
+
}
|
|
122
|
+
const availabilityCommand = normalizeArgv(value.availabilityCommand);
|
|
123
|
+
if (availabilityCommand !== undefined) {
|
|
124
|
+
target.availabilityCommand = availabilityCommand;
|
|
125
|
+
}
|
|
126
|
+
return Object.keys(target).length > 0 ? target : undefined;
|
|
127
|
+
}
|
|
128
|
+
function normalizeRecordMap(value, normalizeValue) {
|
|
129
|
+
if (!isRecord(value)) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
const next = {};
|
|
133
|
+
for (const [key, rawEntry] of Object.entries(value)) {
|
|
134
|
+
if (!key.trim()) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const normalized = normalizeValue(rawEntry);
|
|
138
|
+
if (normalized !== undefined) {
|
|
139
|
+
next[key] = normalized;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return Object.keys(next).length > 0 ? next : undefined;
|
|
143
|
+
}
|
|
22
144
|
function normalizeWorkflowConfig(parsed) {
|
|
23
145
|
if (!isRecord(parsed)) {
|
|
24
146
|
return undefined;
|
|
@@ -94,6 +216,20 @@ function normalizeWorkflowConfig(parsed) {
|
|
|
94
216
|
next.dispatchCeiling = dispatchCeiling;
|
|
95
217
|
}
|
|
96
218
|
}
|
|
219
|
+
if (isRecord(parsed.gates)) {
|
|
220
|
+
const gates = {};
|
|
221
|
+
const execTargets = normalizeRecordMap(parsed.gates.execTargets, normalizeExecTarget);
|
|
222
|
+
if (execTargets !== undefined) {
|
|
223
|
+
gates.execTargets = execTargets;
|
|
224
|
+
}
|
|
225
|
+
const skills = normalizeRecordMap(parsed.gates.skills, normalizeGateConfig);
|
|
226
|
+
if (skills !== undefined) {
|
|
227
|
+
gates.skills = skills;
|
|
228
|
+
}
|
|
229
|
+
if (Object.keys(gates).length > 0) {
|
|
230
|
+
next.gates = gates;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
97
233
|
return Object.keys(next).length > 0 ? next : undefined;
|
|
98
234
|
}
|
|
99
235
|
const DEFAULT_OAT_CONFIG = { version: 1 };
|
package/dist/config/resolve.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OatConfig, type OatLocalConfig, type UserConfig } from './oat-config.js';
|
|
1
|
+
import { type ExecTarget, type GateConfig, type OatConfig, type OatLocalConfig, type UserConfig } from './oat-config.js';
|
|
2
2
|
export type ResolvedConfigSource = 'shared' | 'local' | 'user' | 'env' | 'default';
|
|
3
3
|
export interface ResolvedKeyEntry {
|
|
4
4
|
value: unknown;
|
|
@@ -16,4 +16,6 @@ export interface ResolveEffectiveConfigDependencies {
|
|
|
16
16
|
readUserConfig: (userConfigDir: string) => Promise<UserConfig>;
|
|
17
17
|
}
|
|
18
18
|
export declare function resolveEffectiveConfig(repoRoot: string, userConfigDir: string, env?: NodeJS.ProcessEnv, overrides?: Partial<ResolveEffectiveConfigDependencies>): Promise<ResolvedConfig>;
|
|
19
|
+
export declare function resolveGate(effective: ResolvedConfig, skillName: string): GateConfig | null;
|
|
20
|
+
export declare function resolveExecTargets(effective: ResolvedConfig): Record<string, ExecTarget>;
|
|
19
21
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,OAAO,GACP,MAAM,GACN,KAAK,GACL,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,cAAc,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,kCAAkC;IACjD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,cAAc,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAChE;AA+ED,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,GAAE,OAAO,CAAC,kCAAkC,CAAM,GAC1D,OAAO,CAAC,cAAc,CAAC,CAgFzB;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,MAAM,GAChB,UAAU,GAAG,IAAI,CAcnB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,cAAc,GACxB,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAY5B"}
|
package/dist/config/resolve.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readOatConfig, readOatLocalConfig, readUserConfig, } from './oat-config.js';
|
|
1
|
+
import { BUILTIN_EXEC_TARGETS, readOatConfig, readOatLocalConfig, readUserConfig, } from './oat-config.js';
|
|
2
2
|
const DEFAULT_DEPENDENCIES = {
|
|
3
3
|
readOatConfig,
|
|
4
4
|
readOatLocalConfig,
|
|
@@ -139,6 +139,105 @@ export async function resolveEffectiveConfig(repoRoot, userConfigDir, env = proc
|
|
|
139
139
|
resolved,
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
|
+
export function resolveGate(effective, skillName) {
|
|
143
|
+
for (const skills of [
|
|
144
|
+
effective.local.workflow?.gates?.skills,
|
|
145
|
+
effective.shared.workflow?.gates?.skills,
|
|
146
|
+
effective.user.workflow?.gates?.skills,
|
|
147
|
+
]) {
|
|
148
|
+
if (!skills || !hasOwn(skills, skillName)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
return skills[skillName] ?? null;
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
export function resolveExecTargets(effective) {
|
|
156
|
+
const targets = cloneExecTargetRegistry(BUILTIN_EXEC_TARGETS);
|
|
157
|
+
for (const execTargets of [
|
|
158
|
+
effective.user.workflow?.gates?.execTargets,
|
|
159
|
+
effective.shared.workflow?.gates?.execTargets,
|
|
160
|
+
effective.local.workflow?.gates?.execTargets,
|
|
161
|
+
]) {
|
|
162
|
+
mergeExecTargetLayer(targets, execTargets);
|
|
163
|
+
}
|
|
164
|
+
return targets;
|
|
165
|
+
}
|
|
166
|
+
function mergeExecTargetLayer(targets, layer) {
|
|
167
|
+
if (!layer) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
for (const [id, override] of Object.entries(layer)) {
|
|
171
|
+
if (override === null) {
|
|
172
|
+
delete targets[id];
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const existing = targets[id];
|
|
176
|
+
if (existing) {
|
|
177
|
+
targets[id] = cloneExecTarget({
|
|
178
|
+
runtime: override.runtime ?? existing.runtime,
|
|
179
|
+
baseCommand: override.baseCommand ?? existing.baseCommand,
|
|
180
|
+
hostDetectionCommand: override.hostDetectionCommand ?? existing.hostDetectionCommand,
|
|
181
|
+
availabilityCommand: override.availabilityCommand ?? existing.availabilityCommand,
|
|
182
|
+
priority: override.priority ?? existing.priority,
|
|
183
|
+
});
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const completeTarget = toCompleteExecTarget(override);
|
|
187
|
+
if (completeTarget) {
|
|
188
|
+
targets[id] = completeTarget;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function cloneExecTargetRegistry(registry) {
|
|
193
|
+
return Object.fromEntries(Object.entries(registry).map(([id, target]) => [
|
|
194
|
+
id,
|
|
195
|
+
cloneExecTarget(target),
|
|
196
|
+
]));
|
|
197
|
+
}
|
|
198
|
+
function cloneExecTarget(target) {
|
|
199
|
+
const next = {
|
|
200
|
+
runtime: target.runtime,
|
|
201
|
+
baseCommand: [...target.baseCommand],
|
|
202
|
+
priority: target.priority,
|
|
203
|
+
};
|
|
204
|
+
if (target.hostDetectionCommand) {
|
|
205
|
+
next.hostDetectionCommand = [...target.hostDetectionCommand];
|
|
206
|
+
}
|
|
207
|
+
if (target.availabilityCommand) {
|
|
208
|
+
next.availabilityCommand = [...target.availabilityCommand];
|
|
209
|
+
}
|
|
210
|
+
return next;
|
|
211
|
+
}
|
|
212
|
+
function toCompleteExecTarget(target) {
|
|
213
|
+
const runtime = typeof target.runtime === 'string' ? target.runtime.trim() : '';
|
|
214
|
+
if (!runtime || !isValidArgv(target.baseCommand)) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const completeTarget = {
|
|
218
|
+
runtime,
|
|
219
|
+
baseCommand: [...target.baseCommand],
|
|
220
|
+
priority: typeof target.priority === 'number' && Number.isFinite(target.priority)
|
|
221
|
+
? target.priority
|
|
222
|
+
: 0,
|
|
223
|
+
};
|
|
224
|
+
if (isValidArgv(target.hostDetectionCommand)) {
|
|
225
|
+
completeTarget.hostDetectionCommand = [...target.hostDetectionCommand];
|
|
226
|
+
}
|
|
227
|
+
if (isValidArgv(target.availabilityCommand)) {
|
|
228
|
+
completeTarget.availabilityCommand = [...target.availabilityCommand];
|
|
229
|
+
}
|
|
230
|
+
return completeTarget;
|
|
231
|
+
}
|
|
232
|
+
function isValidArgv(value) {
|
|
233
|
+
if (!Array.isArray(value) ||
|
|
234
|
+
value.length === 0 ||
|
|
235
|
+
!value.every((part) => typeof part === 'string')) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const [executable] = value;
|
|
239
|
+
return executable !== undefined && executable.trim().length > 0;
|
|
240
|
+
}
|
|
142
241
|
function flattenConfig(value, prefix = '') {
|
|
143
242
|
if (!isRecord(value)) {
|
|
144
243
|
return {};
|
|
@@ -168,6 +267,9 @@ function resolveEnvOverride(key, env) {
|
|
|
168
267
|
function isRecord(value) {
|
|
169
268
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
170
269
|
}
|
|
270
|
+
function hasOwn(value, key) {
|
|
271
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
272
|
+
}
|
|
171
273
|
function isResolvedValue(value) {
|
|
172
274
|
return value !== undefined && value !== null;
|
|
173
275
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manifest/manager.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAa1B,wBAAgB,mBAAmB,IAAI,QAAQ,CAO9C;AAED,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6C1E;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/manifest/manager.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAa1B,wBAAgB,mBAAmB,IAAI,QAAQ,CAO9C;AAED,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6C1E;AAED,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAgB,SAAS,CACvB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,aAAa,GAAG,SAAS,CAK3B;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,QAAQ,CAc3E;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,QAAQ,CAeV"}
|
package/dist/manifest/manager.js
CHANGED
|
@@ -54,7 +54,10 @@ export async function loadManifest(manifestPath) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
export async function saveManifest(manifestPath, manifest) {
|
|
57
|
-
const validated = ManifestSchema.parse(
|
|
57
|
+
const validated = ManifestSchema.parse({
|
|
58
|
+
...manifest,
|
|
59
|
+
oatVersion: OAT_VERSION,
|
|
60
|
+
});
|
|
58
61
|
const dir = dirname(manifestPath);
|
|
59
62
|
const tempPath = `${manifestPath}.${randomUUID()}.tmp`;
|
|
60
63
|
await mkdir(dir, { recursive: true });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface ValidationFinding {
|
|
2
2
|
file: string;
|
|
3
3
|
message: string;
|
|
4
|
+
severity?: 'error' | 'warning';
|
|
4
5
|
}
|
|
5
6
|
export interface ValidateOatSkillsResult {
|
|
6
7
|
validatedSkillCount: number;
|
|
@@ -15,6 +16,7 @@ export interface ValidateChangedSkillVersionBumpsResult {
|
|
|
15
16
|
}
|
|
16
17
|
export interface ValidateOatSkillsOptions {
|
|
17
18
|
baseRef?: string;
|
|
19
|
+
gateSkillNames?: readonly string[];
|
|
18
20
|
}
|
|
19
21
|
export type ExecFileResult = {
|
|
20
22
|
stdout: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/validation/skills.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,uCAAuC;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sCAAsC;IACrD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChD,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,UAAU,6BAA6B;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAuSD,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uCAAuC,EAChD,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,sCAAsC,CAAC,CAoBjD;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,wBAA6B,EACtC,YAAY,GAAE,6BAAkC,GAC/C,OAAO,CAAC,uBAAuB,CAAC,CAmIlC"}
|
|
@@ -22,6 +22,10 @@ function getFrontmatterScalar(frontmatter, key) {
|
|
|
22
22
|
const match = frontmatter.match(re);
|
|
23
23
|
return match?.[1]?.trim() ?? null;
|
|
24
24
|
}
|
|
25
|
+
function hasTrueFrontmatterValue(frontmatter, key) {
|
|
26
|
+
return (frontmatterHasKey(frontmatter, key) &&
|
|
27
|
+
getFrontmatterScalar(frontmatter, key) === 'true');
|
|
28
|
+
}
|
|
25
29
|
function isValidSemver(value) {
|
|
26
30
|
return /^\d+\.\d+\.\d+$/.test(value);
|
|
27
31
|
}
|
|
@@ -87,6 +91,40 @@ function validateQuickStartSemantics(skillPath, content, findings) {
|
|
|
87
91
|
});
|
|
88
92
|
}
|
|
89
93
|
}
|
|
94
|
+
function normalizeGateSkillNames(gateSkillNames) {
|
|
95
|
+
if (!gateSkillNames) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
return [
|
|
99
|
+
...new Set(gateSkillNames.map((name) => name.trim()).filter(Boolean)),
|
|
100
|
+
].sort();
|
|
101
|
+
}
|
|
102
|
+
async function collectGateabilityFindings(skillsRoot, gateSkillNames, findings) {
|
|
103
|
+
for (const skillName of normalizeGateSkillNames(gateSkillNames)) {
|
|
104
|
+
const skillPath = join(skillsRoot, skillName, 'SKILL.md');
|
|
105
|
+
let content;
|
|
106
|
+
try {
|
|
107
|
+
content = await readFile(skillPath, 'utf8');
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
findings.push({
|
|
111
|
+
file: skillPath,
|
|
112
|
+
message: `Configured gate targets unknown skill: ${skillName}`,
|
|
113
|
+
severity: 'warning',
|
|
114
|
+
});
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const frontmatter = getFrontmatterBlock(content);
|
|
118
|
+
if (frontmatter === null ||
|
|
119
|
+
!hasTrueFrontmatterValue(frontmatter, 'oat_gateable')) {
|
|
120
|
+
findings.push({
|
|
121
|
+
file: skillPath,
|
|
122
|
+
message: 'Configured gate targets skill without oat_gateable: true',
|
|
123
|
+
severity: 'warning',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
90
128
|
async function listChangedSkillFiles(repoRoot, baseRef, dependencies) {
|
|
91
129
|
const execFile = dependencies.gitExecFile ?? execFileAsync;
|
|
92
130
|
const { stdout } = await execFile('git', [
|
|
@@ -261,6 +299,7 @@ export async function validateOatSkills(repoRoot, options = {}, dependencies = {
|
|
|
261
299
|
validateQuickStartSemantics(skillPath, content, findings);
|
|
262
300
|
}
|
|
263
301
|
}
|
|
302
|
+
await collectGateabilityFindings(skillsRoot, options.gateSkillNames, findings);
|
|
264
303
|
if (options.baseRef) {
|
|
265
304
|
const changedSkillFiles = await listChangedSkillFiles(repoRoot, options.baseRef, dependencies);
|
|
266
305
|
await collectChangedSkillVersionBumpFindings(repoRoot, options.baseRef, changedSkillFiles, findings, dependencies);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
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.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.1.34"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|