@open-agent-toolkit/cli 0.0.32 → 0.0.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/README.md CHANGED
@@ -34,6 +34,7 @@ Additional useful entry points:
34
34
  - `oat config dump --json`
35
35
  - `oat project status --json`
36
36
  - `oat project list --json`
37
+ - `oat project complete-state /path/to/project`
37
38
  - `oat project archive sync`
38
39
  - `oat doctor`
39
40
 
@@ -44,6 +45,7 @@ Use these commands when you want structured runtime/project state out of the CLI
44
45
  - `oat config dump --json` - emit merged OAT config with per-key source attribution
45
46
  - `oat project status --json` - emit the active project's full parsed control-plane state
46
47
  - `oat project list --json` - emit summary state for tracked projects under the configured projects root
48
+ - `oat project complete-state <project-path>` - emit the canonical completed lifecycle shape into a tracked project's `state.md`
47
49
 
48
50
  ## Requirements
49
51
 
@@ -39,6 +39,7 @@ Notable inspection commands introduced in the current CLI surface:
39
39
  - `oat config dump --json` - merged config with source attribution
40
40
  - `oat project status --json` - full parsed state for the active tracked project
41
41
  - `oat project list --json` - summary state for tracked projects under the configured projects root
42
+ - `oat project complete-state <project-path>` - apply the canonical completed-state mutation to a project's `state.md`; used by `oat-project-complete` during lifecycle closeout
42
43
 
43
44
  ## `oat config` surface flags
44
45
 
@@ -104,7 +104,7 @@ When `autoReviewAtCheckpoints` is enabled (via `.oat/config.json` or `plan.md` f
104
104
 
105
105
  ### Quick lane diagram
106
106
 
107
- 1. `oat-project-quick-start` (adaptive discovery — well-understood requests synthesize quickly, exploratory requests invest in solution space exploration)
107
+ 1. `oat-project-quick-start` (adaptive discovery — provide a project name and optional description; if only the name is provided, quick-start asks for the missing description before discovery. Well-understood requests synthesize quickly, exploratory requests invest in solution space exploration)
108
108
  2. Decision point: straight to plan, optional lightweight `design.md`, or promote to spec-driven
109
109
  3. Implement:
110
110
  - `oat-project-implement` (sequential)
@@ -14,7 +14,7 @@ Use this section when you want to choose the right OAT skill for a task. If you
14
14
 
15
15
  ## Key Skills by Use Case
16
16
 
17
- - Start a new tracked project: `oat-project-new` or `oat-project-quick-start`
17
+ - Start a new tracked project: `oat-project-new` or `oat-project-quick-start` (quick start accepts a project name plus optional description; if you omit the description it should ask before discovery begins)
18
18
  - Resume an existing project: `oat-project-open` and `oat-project-progress`
19
19
  - Execute a ready plan: `oat-project-implement`
20
20
  - Import an existing plan: `oat-project-import-plan`
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.0.32",
3
- "docs-config": "0.0.32",
4
- "docs-theme": "0.0.32",
5
- "docs-transforms": "0.0.32"
2
+ "cli": "0.0.34",
3
+ "docs-config": "0.0.34",
4
+ "docs-theme": "0.0.34",
5
+ "docs-transforms": "0.0.34"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-docs
3
- version: 1.0.0
3
+ version: 1.0.1
4
4
  description: Use when a user asks questions about OAT workflows, CLI commands, skill authoring, configuration, or project lifecycle. Answers questions by reading locally-bundled OAT documentation.
5
5
  argument-hint: '[question]'
6
6
  disable-model-invocation: false
@@ -161,13 +161,15 @@ Would you like me to:
161
161
  To create a new OAT project, you have two main approaches:
162
162
 
163
163
  1. **Quick mode** (recommended for most tasks):
164
- oat-project-quick-start <project-name>
164
+ oat-project-quick-start <project-name> "project description"
165
165
 
166
166
  2. **Spec-driven mode** (for complex features):
167
167
  oat-project-new <project-name>
168
168
 
169
169
  Quick mode goes straight from discovery to plan. Spec-driven mode adds
170
- formal spec and design phases.
170
+ formal spec and design phases. If you invoke quick mode with only a
171
+ project name, it should ask you for the missing project description
172
+ before discovery starts.
171
173
 
172
174
  Both create a project directory under your projects root
173
175
  (default: .oat/projects/shared/<project-name>/) with standard artifacts:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-complete
3
- version: 1.4.0
3
+ version: 1.4.1
4
4
  description: Use when all implementation work is finished and the project is ready to close. Marks the OAT project lifecycle as complete.
5
5
  disable-model-invocation: true
6
6
  user-invocable: true
@@ -254,41 +254,19 @@ Rules:
254
254
 
255
255
  ### Step 5: Set Lifecycle Complete
256
256
 
257
- Update `state.md` frontmatter to add/update `oat_lifecycle: complete` and set completion timestamps:
257
+ Delegate the canonical `state.md` completion mutation to the CLI:
258
258
 
259
259
  ```bash
260
- STATE_FILE="${PROJECT_PATH}/state.md"
261
- NOW_UTC=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
262
-
263
- # Check if oat_lifecycle already exists
264
- if grep -q "^oat_lifecycle:" "$STATE_FILE"; then
265
- # Update existing (portable approach using temp file)
266
- sed 's/^oat_lifecycle:.*/oat_lifecycle: complete/' "$STATE_FILE" > "$STATE_FILE.tmp"
267
- mv "$STATE_FILE.tmp" "$STATE_FILE"
268
- else
269
- # Add after oat_phase_status line using awk (more portable for multi-line inserts)
270
- awk '/^oat_phase_status:/ {print; print "oat_lifecycle: complete"; next} 1' "$STATE_FILE" > "$STATE_FILE.tmp"
271
- mv "$STATE_FILE.tmp" "$STATE_FILE"
260
+ COMPLETE_STATE_ARGS=("$PROJECT_PATH")
261
+ if [[ "$SHOULD_ARCHIVE" == "true" && "$IS_SHARED_PROJECT" == "true" ]]; then
262
+ COMPLETE_STATE_ARGS+=("--archived")
272
263
  fi
273
264
 
274
- # Set completion and state-updated timestamps
275
- sed -E "s/^oat_project_completed:.*/oat_project_completed: \"$NOW_UTC\"/" "$STATE_FILE" > "$STATE_FILE.tmp"
276
- mv "$STATE_FILE.tmp" "$STATE_FILE"
277
- sed -E "s/^oat_project_state_updated:.*/oat_project_state_updated: \"$NOW_UTC\"/" "$STATE_FILE" > "$STATE_FILE.tmp"
278
- mv "$STATE_FILE.tmp" "$STATE_FILE"
265
+ oat project complete-state "${COMPLETE_STATE_ARGS[@]}"
279
266
  ```
280
267
 
281
- Then update the markdown body in `state.md` so the completion state is explicit and does not rely on reference lookups:
282
-
283
- - Set `**Status:** Complete`
284
- - Set `**Last Updated:**` to the completion date in `YYYY-MM-DD`
285
- - In `## Current Phase`, replace the body with:
286
- - `Lifecycle complete; archived locally` when the project is archived in Step 8
287
- - `Lifecycle complete` when the project is completed without archive
288
- - In `## Progress`, preserve the existing completed workflow/review bullets and add `- ✓ Project lifecycle complete` if it is not already present
289
- - In `## Next Milestone`, replace the body with `None. Project complete.`
290
-
291
- Do not infer these body mutations from other archived projects. Apply them directly as part of this skill.
268
+ The CLI command owns both the frontmatter completion fields and the canonical markdown body updates for `state.md`.
269
+ It must set `oat_lifecycle: complete`, completion timestamps, `**Status:** Complete`, `**Last Updated:**`, the canonical `## Current Phase` body, normalized `## Progress`, and `## Next Milestone`.
292
270
 
293
271
  ### Step 6: Clear Active Project Pointer
294
272
 
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: oat-project-quick-start
3
- version: 1.3.1
3
+ version: 1.3.3
4
4
  description: Use when a task is small enough for quick mode or rapid iteration is preferred. Scaffolds a lightweight OAT project from discovery directly to a runnable plan, with optional brainstorming and lightweight design.
5
- argument-hint: '<project-name>'
5
+ argument-hint: '<project-name> ["project description"]'
6
6
  disable-model-invocation: true
7
7
  user-invocable: true
8
8
  allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
@@ -83,7 +83,11 @@ PROJECTS_ROOT="${PROJECTS_ROOT%/}"
83
83
 
84
84
  If no valid active project exists:
85
85
 
86
- - Read `{project-name}` from `$ARGUMENTS`, or ask user.
86
+ - Resolve startup input from `$ARGUMENTS` before doing any discovery work:
87
+ - Accept `{project-name}` plus an optional `{project-description}`.
88
+ - If `$ARGUMENTS` contains only a bare `{project-name}` (for example a slug or short title) without a substantive description, ask the user for a short project description before scanning the repo or drafting discovery.
89
+ - Do not infer requirements from the project name alone or go exploring the codebase to guess what the project means.
90
+ - If neither field is available, ask for both the project name and a short project description. One or two sentences is enough for the description.
87
91
  - Create project via the same scaffolding path used by `oat-project-new`:
88
92
 
89
93
  ```bash
@@ -116,6 +120,8 @@ If `"$PROJECT_PATH/discovery.md"` is missing, create it from `.oat/templates/dis
116
120
 
117
121
  Before asking questions, classify the request:
118
122
 
123
+ - Base this classification on the user's project description plus session context. A bare project name by itself is not enough context to start discovery.
124
+
119
125
  - **Well-understood** — the user has a clear mental model, requirements are specific, approach is obvious. Examples: "add a CLI flag for verbose output", "rename X to Y across the codebase."
120
126
  → Synthesize `discovery.md` from available session context quickly when enough detail is already available. Ask only the minimum additional questions needed to remove blockers for a quality plan.
121
127
 
@@ -0,0 +1,16 @@
1
+ import { readFile as defaultReadFile, writeFile as defaultWriteFile } from 'node:fs/promises';
2
+ import { buildCommandContext, type CommandContext } from '../../../app/command-context.js';
3
+ import { dirExists, fileExists } from '../../../fs/io.js';
4
+ import { Command } from 'commander';
5
+ interface ProjectCompleteStateDependencies {
6
+ buildCommandContext: (options: Parameters<typeof buildCommandContext>[0]) => CommandContext;
7
+ resolveProjectRoot: (cwd: string) => Promise<string>;
8
+ readFile: typeof defaultReadFile;
9
+ writeFile: typeof defaultWriteFile;
10
+ dirExists: typeof dirExists;
11
+ fileExists: typeof fileExists;
12
+ now: () => Date;
13
+ }
14
+ export declare function createProjectCompleteStateCommand(overrides?: Partial<ProjectCompleteStateDependencies>): Command;
15
+ export {};
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,IAAI,eAAe,EAC3B,SAAS,IAAI,gBAAgB,EAC9B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,gCAAgC;IACxC,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,QAAQ,EAAE,OAAO,eAAe,CAAC;IACjC,SAAS,EAAE,OAAO,gBAAgB,CAAC;IACnC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAsED,wBAAgB,iCAAiC,CAC/C,SAAS,GAAE,OAAO,CAAC,gCAAgC,CAAM,GACxD,OAAO,CA2BT"}
@@ -0,0 +1,78 @@
1
+ import { readFile as defaultReadFile, writeFile as defaultWriteFile, } from 'node:fs/promises';
2
+ import { isAbsolute, join } from 'node:path';
3
+ import { buildCommandContext } from '../../../app/command-context.js';
4
+ import { readGlobalOptions } from '../../shared/shared.utils.js';
5
+ import { CliError } from '../../../errors/cli-error.js';
6
+ import { dirExists, fileExists } from '../../../fs/io.js';
7
+ import { resolveProjectRoot } from '../../../fs/paths.js';
8
+ import { Command } from 'commander';
9
+ import { renderCompletedProjectState } from './state-utils.js';
10
+ const DEFAULT_DEPENDENCIES = {
11
+ buildCommandContext,
12
+ resolveProjectRoot,
13
+ readFile: defaultReadFile,
14
+ writeFile: defaultWriteFile,
15
+ dirExists,
16
+ fileExists,
17
+ now: () => new Date(),
18
+ };
19
+ function resolveTargetProjectPath(repoRoot, projectPath) {
20
+ return isAbsolute(projectPath) ? projectPath : join(repoRoot, projectPath);
21
+ }
22
+ async function runProjectCompleteState(projectPath, options, context, dependencies) {
23
+ try {
24
+ const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
25
+ const targetProjectPath = resolveTargetProjectPath(repoRoot, projectPath);
26
+ if (!(await dependencies.dirExists(targetProjectPath))) {
27
+ throw new CliError(`Project not found: ${projectPath}`, 1);
28
+ }
29
+ const statePath = join(targetProjectPath, 'state.md');
30
+ if (!(await dependencies.fileExists(statePath))) {
31
+ throw new CliError(`Project state.md not found: ${statePath}`, 1);
32
+ }
33
+ const now = dependencies.now();
34
+ const content = await dependencies.readFile(statePath, 'utf8');
35
+ const updatedContent = renderCompletedProjectState(content, {
36
+ archived: options.archived ?? false,
37
+ nowUtc: now.toISOString(),
38
+ today: now.toISOString().slice(0, 10),
39
+ });
40
+ await dependencies.writeFile(statePath, updatedContent, 'utf8');
41
+ if (context.json) {
42
+ context.logger.json({
43
+ status: 'ok',
44
+ projectPath,
45
+ statePath,
46
+ archived: options.archived ?? false,
47
+ });
48
+ }
49
+ else {
50
+ context.logger.info(`Updated completed project state: ${projectPath}`);
51
+ }
52
+ process.exitCode = 0;
53
+ }
54
+ catch (error) {
55
+ const message = error instanceof Error ? error.message : String(error);
56
+ if (context.json) {
57
+ context.logger.json({ status: 'error', message });
58
+ }
59
+ else {
60
+ context.logger.error(message);
61
+ }
62
+ process.exitCode = error instanceof CliError ? error.exitCode : 1;
63
+ }
64
+ }
65
+ export function createProjectCompleteStateCommand(overrides = {}) {
66
+ const dependencies = {
67
+ ...DEFAULT_DEPENDENCIES,
68
+ ...overrides,
69
+ };
70
+ return new Command('complete-state')
71
+ .description('Update a project state.md to the completed lifecycle shape')
72
+ .argument('<project-path>', 'Project path to update')
73
+ .option('--archived', 'Mark the completed project as archived locally')
74
+ .action(async (projectPath, options, command) => {
75
+ const context = dependencies.buildCommandContext(readGlobalOptions(command));
76
+ await runProjectCompleteState(projectPath, options, context, dependencies);
77
+ });
78
+ }
@@ -0,0 +1,7 @@
1
+ export interface CompleteProjectStateOptions {
2
+ archived: boolean;
3
+ nowUtc: string;
4
+ today: string;
5
+ }
6
+ export declare function renderCompletedProjectState(content: string, options: CompleteProjectStateOptions): string;
7
+ //# sourceMappingURL=state-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-utils.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/complete-state/state-utils.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAoED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,2BAA2B,GACnC,MAAM,CA8DR"}
@@ -0,0 +1,72 @@
1
+ import { getFrontmatterBlock, getFrontmatterField, } from '../../shared/frontmatter.js';
2
+ import { replaceFrontmatter, upsertFrontmatterField, } from '../../shared/frontmatter-write.js';
3
+ function replaceLine(content, pattern, nextLine) {
4
+ return pattern.test(content) ? content.replace(pattern, nextLine) : content;
5
+ }
6
+ function findSectionBounds(content, heading) {
7
+ const marker = `## ${heading}\n\n`;
8
+ const start = content.indexOf(marker);
9
+ if (start === -1) {
10
+ return null;
11
+ }
12
+ const bodyStart = start + marker.length;
13
+ const nextHeading = content.indexOf('\n## ', bodyStart);
14
+ return {
15
+ start,
16
+ bodyStart,
17
+ end: nextHeading === -1 ? content.length : nextHeading,
18
+ };
19
+ }
20
+ function readSectionBody(content, heading) {
21
+ const bounds = findSectionBounds(content, heading);
22
+ if (!bounds) {
23
+ return '';
24
+ }
25
+ return content.slice(bounds.bodyStart, bounds.end).trim();
26
+ }
27
+ function replaceSection(content, heading, body) {
28
+ const bounds = findSectionBounds(content, heading);
29
+ if (!bounds) {
30
+ return content;
31
+ }
32
+ return [
33
+ content.slice(0, bounds.start),
34
+ `## ${heading}\n\n${body.trim()}\n`,
35
+ content.slice(bounds.end),
36
+ ].join('');
37
+ }
38
+ function renderCompletedProgress(content) {
39
+ const existingLines = readSectionBody(content, 'Progress')
40
+ .split('\n')
41
+ .map((line) => line.trim())
42
+ .filter((line) => line.length > 0 && line.startsWith('- ✓'));
43
+ if (!existingLines.includes('- ✓ Project lifecycle complete')) {
44
+ existingLines.push('- ✓ Project lifecycle complete');
45
+ }
46
+ return existingLines.join('\n');
47
+ }
48
+ export function renderCompletedProjectState(content, options) {
49
+ const frontmatter = getFrontmatterBlock(content);
50
+ if (!frontmatter) {
51
+ throw new Error('state.md is missing frontmatter');
52
+ }
53
+ let nextBlock = upsertFrontmatterField(frontmatter, 'oat_lifecycle', 'complete', true).nextBlock;
54
+ nextBlock = upsertFrontmatterField(nextBlock, 'oat_project_completed', `"${options.nowUtc}"`, true).nextBlock;
55
+ nextBlock = upsertFrontmatterField(nextBlock, 'oat_project_state_updated', `"${options.nowUtc}"`, true).nextBlock;
56
+ let nextContent = nextBlock === frontmatter
57
+ ? content
58
+ : replaceFrontmatter(content, nextBlock);
59
+ nextContent = replaceLine(nextContent, /^\*\*Status:\*\*.*$/m, '**Status:** Complete');
60
+ nextContent = replaceLine(nextContent, /^\*\*Last Updated:\*\*.*$/m, `**Last Updated:** ${options.today}`);
61
+ const currentPhase = options.archived
62
+ ? 'Lifecycle complete; archived locally'
63
+ : 'Lifecycle complete';
64
+ nextContent = replaceSection(nextContent, 'Current Phase', currentPhase);
65
+ nextContent = replaceSection(nextContent, 'Progress', renderCompletedProgress(nextContent));
66
+ nextContent = replaceSection(nextContent, 'Next Milestone', 'None. Project complete.');
67
+ const currentLifecycle = getFrontmatterField(nextBlock, 'oat_lifecycle');
68
+ if (currentLifecycle !== 'complete') {
69
+ throw new Error('Failed to set oat_lifecycle: complete');
70
+ }
71
+ return nextContent;
72
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,oBAAoB,IAAI,OAAO,CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/project/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,oBAAoB,IAAI,OAAO,CAW9C"}
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import { createProjectArchiveCommand } from './archive/index.js';
3
+ import { createProjectCompleteStateCommand } from './complete-state/index.js';
3
4
  import { createProjectListCommand } from './list.js';
4
5
  import { createProjectNewCommand } from './new/index.js';
5
6
  import { createProjectOpenCommand } from './open/index.js';
@@ -10,6 +11,7 @@ export function createProjectCommand() {
10
11
  return new Command('project')
11
12
  .description('Manage OAT project workflows')
12
13
  .addCommand(createProjectArchiveCommand())
14
+ .addCommand(createProjectCompleteStateCommand())
13
15
  .addCommand(createProjectListCommand())
14
16
  .addCommand(createProjectNewCommand())
15
17
  .addCommand(createProjectOpenCommand())
@@ -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;AAgOD,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;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"}
@@ -77,6 +77,15 @@ function validateQuickStartSemantics(skillPath, content, findings) {
77
77
  message: 'Quick-start must limit follow-up questions to the minimum needed to remove blockers',
78
78
  });
79
79
  }
80
+ if (!(/(project description|project brief)/i.test(content) &&
81
+ /(project name alone|bare .*project-name|only a bare .*project-name)/i.test(content) &&
82
+ /(ask the user|ask for)/i.test(content) &&
83
+ /(do not infer requirements from the project name alone|not enough context to start discovery)/i.test(content))) {
84
+ findings.push({
85
+ file: skillPath,
86
+ message: 'Quick-start must treat a bare project name as insufficient input, ask for a project description, and avoid inferring scope from the repo',
87
+ });
88
+ }
80
89
  }
81
90
  async function listChangedSkillFiles(repoRoot, baseRef, dependencies) {
82
91
  const execFile = dependencies.gitExecFile ?? execFileAsync;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.0.32",
3
+ "version": "0.0.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",
@@ -33,7 +33,7 @@
33
33
  "ora": "^9.0.0",
34
34
  "yaml": "2.8.2",
35
35
  "zod": "^3.25.76",
36
- "@open-agent-toolkit/control-plane": "0.0.32"
36
+ "@open-agent-toolkit/control-plane": "0.0.34"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/node": "^22.10.0",