@open-agent-toolkit/cli 0.1.33 → 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.
@@ -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 };
@@ -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,EAIL,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"}
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"}
@@ -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,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;CACjB;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;CAClB;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;AAmPD,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,CA6HlC"}
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.33",
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.33"
37
+ "@open-agent-toolkit/control-plane": "0.1.34"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",