@open-agent-toolkit/cli 0.2.59 → 0.2.62

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.
Files changed (78) hide show
  1. package/assets/agents/oat-phase-implementer.md +27 -4
  2. package/assets/agents/oat-reviewer.md +25 -14
  3. package/assets/bundle-metadata.json +1 -1
  4. package/assets/docs/cli-utilities/workflow-gates.md +3 -3
  5. package/assets/docs/reference/cli-reference.md +10 -3
  6. package/assets/docs/reference/oat-directory-structure.md +1 -0
  7. package/assets/docs/workflows/ideas/index.md +1 -1
  8. package/assets/docs/workflows/index.md +1 -0
  9. package/assets/docs/workflows/projects/artifacts.md +24 -3
  10. package/assets/docs/workflows/projects/hill-checkpoints.md +21 -0
  11. package/assets/docs/workflows/projects/implementation-execution.md +5 -0
  12. package/assets/docs/workflows/projects/lifecycle.md +124 -7
  13. package/assets/docs/workflows/projects/pr-flow.md +2 -0
  14. package/assets/docs/workflows/projects/reviews.md +1 -1
  15. package/assets/docs/workflows/projects/state-machine.md +20 -0
  16. package/assets/docs/workflows/skills/index.md +2 -1
  17. package/assets/public-package-versions.json +4 -4
  18. package/assets/skills/oat-brainstorm/SKILL.md +61 -12
  19. package/assets/skills/oat-docs/SKILL.md +13 -8
  20. package/assets/skills/oat-doctor/SKILL.md +3 -3
  21. package/assets/skills/oat-pjm-review-backlog/SKILL.md +2 -2
  22. package/assets/skills/oat-project-autonomous/SKILL.md +14 -9
  23. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +56 -42
  24. package/assets/skills/oat-project-capture/SKILL.md +2 -2
  25. package/assets/skills/oat-project-discover/SKILL.md +6 -5
  26. package/assets/skills/oat-project-document/SKILL.md +11 -1
  27. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +56 -42
  28. package/assets/skills/oat-project-implement/SKILL.md +3 -3
  29. package/assets/skills/oat-project-implement/references/completion-and-closeout.md +106 -15
  30. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +56 -42
  31. package/assets/skills/oat-project-implement/references/phase-execution.md +16 -1
  32. package/assets/skills/oat-project-implement/references/plan-and-resume.md +19 -1
  33. package/assets/skills/oat-project-import-plan/SKILL.md +47 -3
  34. package/assets/skills/oat-project-lite/SKILL.md +467 -0
  35. package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +331 -0
  36. package/assets/skills/oat-project-next/SKILL.md +26 -10
  37. package/assets/skills/oat-project-plan/SKILL.md +14 -2
  38. package/assets/skills/oat-project-plan-writing/SKILL.md +6 -3
  39. package/assets/skills/oat-project-pr-final/SKILL.md +33 -7
  40. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +56 -42
  41. package/assets/skills/oat-project-pr-progress/SKILL.md +3 -3
  42. package/assets/skills/oat-project-progress/SKILL.md +16 -3
  43. package/assets/skills/oat-project-promote-spec-driven/SKILL.md +3 -1
  44. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +56 -42
  45. package/assets/skills/oat-project-review-provide/SKILL.md +25 -6
  46. package/assets/skills/oat-project-summary/SKILL.md +27 -3
  47. package/assets/templates/plan-lite.md +165 -0
  48. package/assets/templates/plan.md +1 -1
  49. package/assets/templates/state.md +1 -1
  50. package/dist/commands/project/index.d.ts.map +1 -1
  51. package/dist/commands/project/index.js +2 -0
  52. package/dist/commands/project/new/index.d.ts +3 -2
  53. package/dist/commands/project/new/index.d.ts.map +1 -1
  54. package/dist/commands/project/new/index.js +2 -1
  55. package/dist/commands/project/new/scaffold.d.ts +5 -3
  56. package/dist/commands/project/new/scaffold.d.ts.map +1 -1
  57. package/dist/commands/project/new/scaffold.js +38 -10
  58. package/dist/commands/project/promote/index.d.ts +2 -0
  59. package/dist/commands/project/promote/index.d.ts.map +1 -0
  60. package/dist/commands/project/promote/index.js +1 -0
  61. package/dist/commands/project/promote/promote.d.ts +47 -0
  62. package/dist/commands/project/promote/promote.d.ts.map +1 -0
  63. package/dist/commands/project/promote/promote.js +322 -0
  64. package/dist/commands/project/split/run.d.ts.map +1 -1
  65. package/dist/commands/project/split/run.js +8 -1
  66. package/dist/commands/project/validate-plan/index.d.ts.map +1 -1
  67. package/dist/commands/project/validate-plan/index.js +25 -1
  68. package/dist/commands/project/validate-plan/validate-plan.d.ts +8 -0
  69. package/dist/commands/project/validate-plan/validate-plan.d.ts.map +1 -1
  70. package/dist/commands/project/validate-plan/validate-plan.js +49 -0
  71. package/dist/commands/shared/frontmatter.d.ts +1 -1
  72. package/dist/commands/shared/frontmatter.d.ts.map +1 -1
  73. package/dist/commands/shared/frontmatter.js +1 -0
  74. package/dist/commands/state/generate.d.ts.map +1 -1
  75. package/dist/commands/state/generate.js +23 -0
  76. package/dist/commands/tools/shared/pack-manifest.d.ts.map +1 -1
  77. package/dist/commands/tools/shared/pack-manifest.js +2 -0
  78. package/package.json +2 -2
@@ -0,0 +1,322 @@
1
+ import { mkdir as defaultMkdir, readFile as defaultReadFile, rename as defaultRename, writeFile as defaultWriteFile, } from 'node:fs/promises';
2
+ import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
3
+ import { buildCommandContext, } from '../../../app/command-context.js';
4
+ import { applyTemplateReplacements, resolveTemplateSource as defaultResolveTemplateSource, } from '../../project/new/scaffold.js';
5
+ import { defaultGitRunner } from '../../project/sync/git.js';
6
+ import { buildSyncTarget, pushSynced as defaultPushSynced, } from '../../project/sync/ref-sync.js';
7
+ import { getFrontmatterBlock } from '../../shared/frontmatter.js';
8
+ import { replaceFrontmatter } from '../../shared/frontmatter-write.js';
9
+ import { resolveProjectsRoot as defaultResolveProjectsRoot } from '../../shared/oat-paths.js';
10
+ import { resolveProjectScope } from '../../shared/project-scope.js';
11
+ import { readGlobalOptions } from '../../shared/shared.utils.js';
12
+ import { fileExists as defaultFileExists } from '../../../fs/io.js';
13
+ import { resolveProjectRoot } from '../../../fs/paths.js';
14
+ import { Command } from 'commander';
15
+ import YAML from 'yaml';
16
+ const PROMOTED_FILES = [
17
+ 'discovery.md',
18
+ 'references/lite-plan.md',
19
+ 'plan.md',
20
+ 'state.md',
21
+ ];
22
+ const LITE_SECTION_HEADINGS = [
23
+ ['Summary', 'summary'],
24
+ ['Decisions', 'decisions'],
25
+ ['Assumptions', 'assumptions'],
26
+ ['Out of Scope', 'outOfScope'],
27
+ ['Validation Criteria', 'validationCriteria'],
28
+ ];
29
+ const DEFAULT_DEPENDENCIES = {
30
+ buildCommandContext,
31
+ resolveProjectRoot,
32
+ resolveProjectsRoot: defaultResolveProjectsRoot,
33
+ resolveTemplateSource: defaultResolveTemplateSource,
34
+ readFile: defaultReadFile,
35
+ writeFile: defaultWriteFile,
36
+ mkdir: defaultMkdir,
37
+ rename: defaultRename,
38
+ fileExists: defaultFileExists,
39
+ gitRunner: defaultGitRunner,
40
+ pushSynced: defaultPushSynced,
41
+ processEnv: process.env,
42
+ now: () => new Date(),
43
+ };
44
+ function extractSection(content, heading) {
45
+ const escapedHeading = heading.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
46
+ const headingMatch = new RegExp(`^## ${escapedHeading}[ \\t]*$`, 'm').exec(content);
47
+ if (!headingMatch)
48
+ return null;
49
+ const bodyStart = headingMatch.index + headingMatch[0].length;
50
+ const remaining = content.slice(bodyStart);
51
+ const nextHeading = /^##\s+/m.exec(remaining);
52
+ const bodyEnd = nextHeading ? bodyStart + nextHeading.index : content.length;
53
+ const body = content.slice(bodyStart, bodyEnd).trim();
54
+ return body.length > 0 ? body : null;
55
+ }
56
+ function extractLitePlanSections(planContent) {
57
+ const sections = {};
58
+ for (const [heading, key] of LITE_SECTION_HEADINGS) {
59
+ const body = extractSection(planContent, heading);
60
+ if (!body)
61
+ return null;
62
+ sections[key] = body;
63
+ }
64
+ const productBehavior = extractSection(planContent, 'Product Behavior');
65
+ const technicalDesign = extractSection(planContent, 'Technical Design');
66
+ if (productBehavior)
67
+ sections.productBehavior = productBehavior;
68
+ if (technicalDesign)
69
+ sections.technicalDesign = technicalDesign;
70
+ return sections;
71
+ }
72
+ function containsUnresolvedTemplateContent(sections, templateSections) {
73
+ const containsTemplateMarkers = (key) => {
74
+ const content = sections[key];
75
+ const templateContent = templateSections[key];
76
+ if (!content || !templateContent)
77
+ return false;
78
+ if (content === templateContent)
79
+ return true;
80
+ const markers = templateContent
81
+ .match(/\[[^\]\n]+\]|\{[^{}\n]+\}/g)
82
+ ?.filter((marker) => !/^\[\s*\]$/.test(marker)) ?? [];
83
+ const instructionalComments = templateContent.match(/<!--[\s\S]*?-->/g) ?? [];
84
+ return [...markers, ...instructionalComments].some((marker) => content.includes(marker));
85
+ };
86
+ return (LITE_SECTION_HEADINGS.some(([, key]) => containsTemplateMarkers(key)) ||
87
+ ['productBehavior', 'technicalDesign'].some((key) => containsTemplateMarkers(key)));
88
+ }
89
+ export function parseLitePlanSections(planContent, liteTemplateContent) {
90
+ const sections = extractLitePlanSections(planContent);
91
+ if (!sections || !liteTemplateContent)
92
+ return sections;
93
+ const templateSections = extractLitePlanSections(liteTemplateContent);
94
+ if (!templateSections ||
95
+ containsUnresolvedTemplateContent(sections, templateSections)) {
96
+ return null;
97
+ }
98
+ return sections;
99
+ }
100
+ function readObjectFrontmatter(content, filePath) {
101
+ const block = getFrontmatterBlock(content);
102
+ if (!block) {
103
+ throw new Error(`${filePath} is missing frontmatter`);
104
+ }
105
+ const parsed = YAML.parse(block);
106
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
107
+ throw new Error(`${filePath} frontmatter must be a YAML object`);
108
+ }
109
+ return parsed;
110
+ }
111
+ function replaceSection(content, heading, body) {
112
+ const escapedHeading = heading.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
113
+ const headingMatch = new RegExp(`^## ${escapedHeading}[ \\t]*$`, 'm').exec(content);
114
+ if (!headingMatch) {
115
+ throw new Error(`discovery template is missing ## ${heading}`);
116
+ }
117
+ const bodyStart = headingMatch.index + headingMatch[0].length;
118
+ const remaining = content.slice(bodyStart);
119
+ const nextHeading = /^##\s+/m.exec(remaining);
120
+ const bodyEnd = nextHeading ? bodyStart + nextHeading.index : content.length;
121
+ const suffix = content.slice(bodyEnd).replace(/^\s*/, '');
122
+ return `${content.slice(0, bodyStart)}\n\n${body.trim()}\n\n${suffix}`;
123
+ }
124
+ function renderDiscovery(template, projectName, today, nowUtc, sections) {
125
+ let rendered = applyTemplateReplacements(template, projectName, today, nowUtc, 'quick');
126
+ const frontmatter = readObjectFrontmatter(rendered, 'rendered discovery.md');
127
+ frontmatter['oat_ready_for'] = 'oat-project-quick-start';
128
+ rendered = replaceFrontmatter(rendered, YAML.stringify(frontmatter).trimEnd());
129
+ const successCriteria = sections.productBehavior
130
+ ? `### Product Behavior (from Lite plan)\n\n${sections.productBehavior}\n\n### Validation Criteria (from Lite plan)\n\n${sections.validationCriteria}`
131
+ : sections.validationCriteria;
132
+ for (const [heading, body] of [
133
+ ['Initial Request', sections.summary],
134
+ ['Key Decisions', sections.decisions],
135
+ ['Assumptions', sections.assumptions],
136
+ ['Out of Scope', sections.outOfScope],
137
+ ['Success Criteria', successCriteria],
138
+ ]) {
139
+ rendered = replaceSection(rendered, heading, body);
140
+ }
141
+ if (sections.technicalDesign) {
142
+ const nextSteps = /^## Next Steps[ \t]*$/m.exec(rendered);
143
+ if (!nextSteps) {
144
+ throw new Error('discovery template is missing ## Next Steps');
145
+ }
146
+ const carriedForward = [
147
+ '## Carried-Forward Technical Design',
148
+ '',
149
+ '> Prior implementation context carried forward from the Lite plan; this is not a new discovery deliverable.',
150
+ '',
151
+ sections.technicalDesign,
152
+ '',
153
+ ].join('\n');
154
+ rendered = `${rendered.slice(0, nextSteps.index)}${carriedForward}${rendered.slice(nextSteps.index)}`;
155
+ }
156
+ return rendered;
157
+ }
158
+ function renderQuickState(stateContent, statePath, nowUtc) {
159
+ const frontmatter = readObjectFrontmatter(stateContent, statePath);
160
+ frontmatter['oat_workflow_mode'] = 'quick';
161
+ frontmatter['oat_phase'] = 'discovery';
162
+ frontmatter['oat_phase_status'] = 'complete';
163
+ frontmatter['oat_ready_for'] = 'oat-project-quick-start';
164
+ frontmatter['oat_project_state_updated'] = nowUtc;
165
+ return replaceFrontmatter(stateContent, YAML.stringify(frontmatter).trimEnd());
166
+ }
167
+ function repoRelativePath(repoRoot, path) {
168
+ return relative(repoRoot, path).split(sep).join('/');
169
+ }
170
+ async function persistPromotion(repoRoot, projectsRoot, projectRoot, projectName, scope, dependencies) {
171
+ const message = `chore(oat): promote ${projectName} to quick`;
172
+ if (scope === 'synced') {
173
+ const target = buildSyncTarget(repoRoot, projectsRoot, projectName);
174
+ const result = await dependencies.pushSynced(target, dependencies.gitRunner, { message });
175
+ if (result.status !== 'pushed' && result.status !== 'up-to-date') {
176
+ throw new Error(`synced promotion push ${result.status}`);
177
+ }
178
+ return;
179
+ }
180
+ if (scope === 'local') {
181
+ return;
182
+ }
183
+ const pathspecs = PROMOTED_FILES.map((file) => repoRelativePath(repoRoot, join(projectRoot, file)));
184
+ await dependencies.gitRunner.run(['add', '--', ...pathspecs], {
185
+ cwd: repoRoot,
186
+ });
187
+ await dependencies.gitRunner.run(['commit', '-m', message, '--', ...pathspecs], { cwd: repoRoot });
188
+ }
189
+ async function promoteProject(projectPath, options, context, dependencies) {
190
+ if (options.to !== 'quick') {
191
+ return { status: 'refused', reason: 'unsupported-target', files: [] };
192
+ }
193
+ const repoRoot = await dependencies.resolveProjectRoot(context.cwd);
194
+ const projectRoot = isAbsolute(projectPath)
195
+ ? resolve(projectPath)
196
+ : resolve(repoRoot, projectPath);
197
+ const projectName = basename(projectRoot);
198
+ const statePath = join(projectRoot, 'state.md');
199
+ const planPath = join(projectRoot, 'plan.md');
200
+ const referencePath = join(projectRoot, 'references', 'lite-plan.md');
201
+ let stateContent;
202
+ let planContent;
203
+ try {
204
+ [stateContent, planContent] = await Promise.all([
205
+ dependencies.readFile(statePath, 'utf8'),
206
+ dependencies.readFile(planPath, 'utf8'),
207
+ ]);
208
+ }
209
+ catch {
210
+ return { status: 'refused', reason: 'project-unreadable', files: [] };
211
+ }
212
+ let stateFrontmatter;
213
+ try {
214
+ stateFrontmatter = readObjectFrontmatter(stateContent, statePath);
215
+ }
216
+ catch {
217
+ return { status: 'refused', reason: 'project-unreadable', files: [] };
218
+ }
219
+ if (stateFrontmatter['oat_workflow_mode'] !== 'lite') {
220
+ return { status: 'refused', reason: 'not-lite', files: [] };
221
+ }
222
+ if (await dependencies.fileExists(referencePath)) {
223
+ return {
224
+ status: 'refused',
225
+ reason: 'lite-plan-reference-exists',
226
+ files: [],
227
+ };
228
+ }
229
+ const userOatRoot = join(context.home, '.oat');
230
+ let liteTemplateContent;
231
+ try {
232
+ const liteTemplatePath = await dependencies.resolveTemplateSource(userOatRoot, repoRoot, 'plan-lite.md');
233
+ liteTemplateContent = await dependencies.readFile(liteTemplatePath, 'utf8');
234
+ }
235
+ catch {
236
+ return { status: 'refused', reason: 'template-unreadable', files: [] };
237
+ }
238
+ const sections = parseLitePlanSections(planContent, liteTemplateContent);
239
+ if (!sections) {
240
+ return { status: 'refused', reason: 'invalid-lite-plan', files: [] };
241
+ }
242
+ const projectsRoot = await dependencies.resolveProjectsRoot(repoRoot, dependencies.processEnv);
243
+ const scope = resolveProjectScope(projectRoot, projectsRoot, repoRoot);
244
+ if (!scope) {
245
+ return { status: 'refused', reason: 'scope-unresolved', files: [] };
246
+ }
247
+ const now = dependencies.now();
248
+ const nowUtc = now.toISOString();
249
+ const today = nowUtc.slice(0, 10);
250
+ let discoveryContent;
251
+ let quickPlanContent;
252
+ let quickStateContent;
253
+ try {
254
+ const [discoveryTemplatePath, quickPlanTemplatePath] = await Promise.all([
255
+ dependencies.resolveTemplateSource(userOatRoot, repoRoot, 'discovery.md'),
256
+ dependencies.resolveTemplateSource(userOatRoot, repoRoot, 'plan.md'),
257
+ ]);
258
+ const [discoveryTemplate, quickPlanTemplate] = await Promise.all([
259
+ dependencies.readFile(discoveryTemplatePath, 'utf8'),
260
+ dependencies.readFile(quickPlanTemplatePath, 'utf8'),
261
+ ]);
262
+ discoveryContent = renderDiscovery(discoveryTemplate, projectName, today, nowUtc, sections);
263
+ quickPlanContent = applyTemplateReplacements(quickPlanTemplate, projectName, today, nowUtc, 'quick');
264
+ quickStateContent = renderQuickState(stateContent, statePath, nowUtc);
265
+ }
266
+ catch {
267
+ return { status: 'refused', reason: 'template-unreadable', files: [] };
268
+ }
269
+ const writtenFiles = [];
270
+ try {
271
+ await dependencies.mkdir(join(projectRoot, 'references'), {
272
+ recursive: true,
273
+ });
274
+ await dependencies.writeFile(join(projectRoot, 'discovery.md'), discoveryContent, 'utf8');
275
+ writtenFiles.push('discovery.md');
276
+ await dependencies.rename(planPath, referencePath);
277
+ writtenFiles.push('references/lite-plan.md');
278
+ await dependencies.writeFile(planPath, quickPlanContent, 'utf8');
279
+ writtenFiles.push('plan.md');
280
+ await dependencies.writeFile(statePath, quickStateContent, 'utf8');
281
+ writtenFiles.push('state.md');
282
+ }
283
+ catch {
284
+ return { status: 'refused', reason: 'write-failed', files: writtenFiles };
285
+ }
286
+ try {
287
+ await persistPromotion(repoRoot, projectsRoot, projectRoot, projectName, scope, dependencies);
288
+ }
289
+ catch {
290
+ return {
291
+ status: 'refused',
292
+ reason: 'persistence-failed',
293
+ files: writtenFiles,
294
+ };
295
+ }
296
+ return {
297
+ status: 'promoted',
298
+ reason: 'promoted',
299
+ files: [...PROMOTED_FILES],
300
+ };
301
+ }
302
+ export function createProjectPromoteCommand(overrides = {}) {
303
+ const dependencies = { ...DEFAULT_DEPENDENCIES, ...overrides };
304
+ return new Command('promote')
305
+ .description('Promote an authored lite project to the quick workflow')
306
+ .argument('<project-path>', 'Lite project path to promote')
307
+ .requiredOption('--to <mode>', 'Target workflow mode')
308
+ .action(async (projectPath, options, command) => {
309
+ const context = dependencies.buildCommandContext(readGlobalOptions(command));
310
+ const result = await promoteProject(projectPath, options, context, dependencies);
311
+ if (context.json) {
312
+ context.logger.json(result);
313
+ }
314
+ else if (result.status === 'promoted') {
315
+ context.logger.info(`Promoted ${projectPath} to quick.`);
316
+ }
317
+ else {
318
+ context.logger.error(`Promotion refused: ${result.reason}.`);
319
+ }
320
+ process.exitCode = result.status === 'promoted' ? 0 : 1;
321
+ });
322
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/split/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOlF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAMhE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,gBAAgB,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,iBAAiB,CAAC;CACtC;AAiND,wBAAgB,4BAA4B,CAC1C,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CAkLT"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/split/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGvE,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOlF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAMhE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,UAAU,oBAAoB;IAC5B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,mBAAmB,EAAE,CACnB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,IAAI,EAAE,OAAO,IAAI,CAAC;IAClB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,gBAAgB,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,OAAO,iBAAiB,CAAC;CACtC;AAqND,wBAAgB,4BAA4B,CAC1C,SAAS,GAAE,OAAO,CAAC,oBAAoB,CAAM,GAC5C,OAAO,CA2LT"}
@@ -63,6 +63,9 @@ async function recordDetectedRecommendation(repoRoot, document, dependencies) {
63
63
  throw new Error('Cannot record detected split recommendation without an active project');
64
64
  }
65
65
  const discoveryPath = join(repoRoot, localConfig.activeProject, 'discovery.md');
66
+ if (!(await exists(discoveryPath, dependencies))) {
67
+ return false;
68
+ }
66
69
  await dependencies.appendFile(discoveryPath, [
67
70
  '',
68
71
  '## Detected Split Recommendation',
@@ -74,6 +77,7 @@ async function recordDetectedRecommendation(repoRoot, document, dependencies) {
74
77
  .join(', ')}`,
75
78
  '',
76
79
  ].join('\n'), 'utf8');
80
+ return true;
77
81
  }
78
82
  function isEffectivelyNonInteractive(options, context, processEnv) {
79
83
  return (options.nonInteractive === true ||
@@ -180,7 +184,10 @@ export function createProjectSplitRunCommand(overrides = {}) {
180
184
  if (isEffectivelyNonInteractive(options, context, dependencies.processEnv) &&
181
185
  (document.origin === 'detected-mid-stream' ||
182
186
  document.origin === 'detected-convergence')) {
183
- await recordDetectedRecommendation(repoRoot, document, dependencies);
187
+ const recorded = await recordDetectedRecommendation(repoRoot, document, dependencies);
188
+ if (!recorded) {
189
+ context.logger.info('skipped split recommendation: no discovery.md for this project');
190
+ }
184
191
  context.logger.error('Detected split requires interactive confirmation; recommendation recorded.');
185
192
  process.exitCode = 1;
186
193
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/validate-plan/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,+BAA+B;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;CACjE;AAMD,wBAAgB,gCAAgC,CAC9C,SAAS,GAAE,OAAO,CAAC,+BAA+B,CAAM,GACvD,OAAO,CA0ET"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/validate-plan/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,UAAU,+BAA+B;IACvC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;CACjE;AAMD,wBAAgB,gCAAgC,CAC9C,SAAS,GAAE,OAAO,CAAC,+BAA+B,CAAM,GACvD,OAAO,CAsGT"}
@@ -3,7 +3,7 @@ import { join } from 'node:path';
3
3
  import { buildCommandContext, } from '../../../app/command-context.js';
4
4
  import { readGlobalOptions } from '../../shared/shared.utils.js';
5
5
  import { Command } from 'commander';
6
- import { extractPhaseIdsFromPlan, parseFrontmatterFromContent, validateParallelGroups, } from './validate-plan.js';
6
+ import { extractPhaseIdsFromPlan, parseFrontmatterFromContent, validateLitePlan, validateParallelGroups, } from './validate-plan.js';
7
7
  const DEFAULT_DEPENDENCIES = {
8
8
  buildCommandContext,
9
9
  };
@@ -47,6 +47,30 @@ export function createProjectValidatePlanCommand(overrides = {}) {
47
47
  }
48
48
  const groups = frontmatterResult.data['oat_plan_parallel_groups'];
49
49
  const phaseIds = extractPhaseIdsFromPlan(content);
50
+ let workflowMode = null;
51
+ try {
52
+ const stateContent = readFileSync(join(options.projectPath, 'state.md'), 'utf-8');
53
+ const stateFrontmatter = parseFrontmatterFromContent(stateContent);
54
+ const mode = stateFrontmatter.kind === 'invalid'
55
+ ? null
56
+ : stateFrontmatter.data['oat_workflow_mode'];
57
+ workflowMode = typeof mode === 'string' ? mode : null;
58
+ }
59
+ catch {
60
+ workflowMode = null;
61
+ }
62
+ const liteResult = validateLitePlan(content, workflowMode);
63
+ if (!liteResult.ok) {
64
+ if (context.json) {
65
+ context.logger.json({ valid: false, errors: [liteResult.message] });
66
+ }
67
+ else {
68
+ context.logger.error('Plan validation failed:');
69
+ context.logger.error(` - ${liteResult.message}`);
70
+ }
71
+ process.exitCode = 1;
72
+ return;
73
+ }
50
74
  const result = validateParallelGroups(groups, phaseIds);
51
75
  if (result.valid) {
52
76
  if (context.json) {
@@ -15,6 +15,14 @@ export type ValidationResult = {
15
15
  valid: false;
16
16
  errors: string[];
17
17
  };
18
+ export type LitePlanValidationResult = {
19
+ ok: true;
20
+ } | {
21
+ ok: false;
22
+ code: 'lite-multi-phase' | 'lite-parallel-groups' | 'lite-criterion-without-command';
23
+ message: string;
24
+ };
25
+ export declare function validateLitePlan(planContent: string, workflowMode: string | null | undefined): LitePlanValidationResult;
18
26
  export declare function validateParallelGroups(groups: unknown, phaseIds: readonly string[]): ValidationResult;
19
27
  export declare function extractPhaseIdsFromPlan(planContent: string): string[];
20
28
  //# sourceMappingURL=validate-plan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-plan.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/validate-plan/validate-plan.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GACd,iBAAiB,CAyBnB;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEvC,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,gBAAgB,CAgDlB;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAOrE"}
1
+ {"version":3,"file":"validate-plan.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/validate-plan/validate-plan.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,GACd,iBAAiB,CAyBnB;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEvC,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACE,EAAE,EAAE,KAAK,CAAC;IACV,IAAI,EACA,kBAAkB,GAClB,sBAAsB,GACtB,gCAAgC,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAeN,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACtC,wBAAwB,CA8C1B;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,gBAAgB,CAgDlB;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAOrE"}
@@ -25,6 +25,55 @@ export function parseFrontmatterFromContent(content) {
25
25
  };
26
26
  }
27
27
  }
28
+ function validationCriteria(planContent) {
29
+ const heading = /^## Validation Criteria[ \t]*$/m.exec(planContent);
30
+ if (!heading)
31
+ return null;
32
+ const bodyStart = heading.index + heading[0].length;
33
+ const remaining = planContent.slice(bodyStart);
34
+ const nextHeading = /^##\s+/m.exec(remaining);
35
+ const body = remaining.slice(0, nextHeading?.index ?? remaining.length);
36
+ return body
37
+ .split('\n')
38
+ .filter((line) => /^\s*-\s+/.test(line))
39
+ .map((line) => line.replace(/^\s*-\s+(?:\[[ xX]\]\s*)?/, '').trim());
40
+ }
41
+ export function validateLitePlan(planContent, workflowMode) {
42
+ if (workflowMode !== 'lite') {
43
+ return { ok: true };
44
+ }
45
+ const phaseCount = planContent.match(/^## Phase\b.*$/gm)?.length ?? 0;
46
+ if (phaseCount !== 1) {
47
+ return {
48
+ ok: false,
49
+ code: 'lite-multi-phase',
50
+ message: `Lite plans must contain exactly one phase; found ${phaseCount}.`,
51
+ };
52
+ }
53
+ const frontmatter = parseFrontmatterFromContent(planContent);
54
+ const groups = frontmatter.kind === 'invalid'
55
+ ? undefined
56
+ : frontmatter.data['oat_plan_parallel_groups'];
57
+ if (groups !== undefined &&
58
+ groups !== null &&
59
+ !(Array.isArray(groups) && groups.length === 0)) {
60
+ return {
61
+ ok: false,
62
+ code: 'lite-parallel-groups',
63
+ message: 'Lite plans must declare no parallel groups.',
64
+ };
65
+ }
66
+ const criteria = validationCriteria(planContent);
67
+ const invalidCriterion = criteria?.find((criterion) => !criterion.startsWith('manual:') && !/`[^`\n]+`/.test(criterion));
68
+ if (!criteria || criteria.length === 0 || invalidCriterion !== undefined) {
69
+ return {
70
+ ok: false,
71
+ code: 'lite-criterion-without-command',
72
+ message: 'Every lite Validation Criteria bullet must name a command in backticks or start with manual: after the bullet marker.',
73
+ };
74
+ }
75
+ return { ok: true };
76
+ }
28
77
  export function validateParallelGroups(groups, phaseIds) {
29
78
  // Missing or empty → valid (sequential execution, no parallelism declared)
30
79
  if (groups === undefined || groups === null) {
@@ -24,7 +24,7 @@ export declare const SKILL_GATE_OVERRIDE_SOURCE = "state.md:oat_skill_gate_overr
24
24
  * `skills.test.ts` pins this constant against the live `oat_gateable: true`
25
25
  * declarations so the two cannot drift apart.
26
26
  */
27
- export declare const GATE_AWARE_SKILLS: readonly ['oat-project-implement', 'oat-project-import-plan', 'oat-project-plan', 'oat-project-quick-start'];
27
+ export declare const GATE_AWARE_SKILLS: readonly ['oat-project-implement', 'oat-project-import-plan', 'oat-project-lite', 'oat-project-plan', 'oat-project-quick-start'];
28
28
  export type SkillGateOverrideValue = typeof SKILL_GATE_OVERRIDE_DISABLED;
29
29
  export interface ProjectSkillGateOverrides {
30
30
  /** False when the key is absent entirely: absence means follow configuration. */
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"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"}
@@ -70,6 +70,7 @@ export const SKILL_GATE_OVERRIDE_SOURCE = `state.md:${SKILL_GATE_OVERRIDE_FIELD}
70
70
  export const GATE_AWARE_SKILLS = [
71
71
  'oat-project-implement',
72
72
  'oat-project-import-plan',
73
+ 'oat-project-lite',
73
74
  'oat-project-plan',
74
75
  'oat-project-quick-start',
75
76
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/commands/state/generate.ts"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAU9E,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAiHD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvE;AAsgBD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAkF9B"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/commands/state/generate.ts"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAU9E,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAkHD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvE;AAgiBD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAkF9B"}
@@ -88,6 +88,8 @@ async function readProjectState(repoRoot, projectPath) {
88
88
  const stateFile = join(repoRoot, projectPath, 'state.md');
89
89
  const phase = (await parseFrontmatterField(stateFile, 'oat_phase')) || 'unknown';
90
90
  const phaseStatus = (await parseFrontmatterField(stateFile, 'oat_phase_status')) || 'unknown';
91
+ const readyForRaw = await parseFrontmatterField(stateFile, 'oat_ready_for');
92
+ const readyFor = readyForRaw && readyForRaw !== 'null' ? readyForRaw : '';
91
93
  let currentTask = await parseFrontmatterField(stateFile, 'oat_current_task');
92
94
  if (!currentTask || currentTask === 'null')
93
95
  currentTask = '-';
@@ -115,6 +117,7 @@ async function readProjectState(repoRoot, projectPath) {
115
117
  return {
116
118
  phase,
117
119
  phaseStatus,
120
+ readyFor,
118
121
  currentTask,
119
122
  lifecycle,
120
123
  pauseTimestamp,
@@ -230,6 +233,15 @@ function computeNextStep(project, hasProjects, state) {
230
233
  reason: `Complete ${state.phase} HiLL approval before advancing`,
231
234
  };
232
235
  }
236
+ if (state.workflowMode === 'quick' &&
237
+ state.phase === 'discovery' &&
238
+ state.phaseStatus === 'complete' &&
239
+ state.readyFor === 'oat-project-quick-start') {
240
+ return {
241
+ step: 'oat-project-quick-start',
242
+ reason: 'Continue the promoted quick workflow',
243
+ };
244
+ }
233
245
  // Workflow mode routing
234
246
  const key = `${state.workflowMode}:${state.phase}:${state.phaseStatus}`;
235
247
  const routeMap = {
@@ -271,6 +283,10 @@ function computeNextStep(project, hasProjects, state) {
271
283
  step: 'oat-project-import-plan',
272
284
  reason: 'Continue import-plan normalization',
273
285
  },
286
+ 'lite:plan:in_progress': {
287
+ step: 'oat-project-lite',
288
+ reason: 'Continue lite planning',
289
+ },
274
290
  };
275
291
  if (routeMap[key])
276
292
  return routeMap[key];
@@ -298,6 +314,12 @@ function computeNextStep(project, hasProjects, state) {
298
314
  return sharedMap[sharedKey];
299
315
  // Implementation complete — recommend docs sync if not yet done, then PR
300
316
  if (state.phase === 'implement' && state.phaseStatus === 'complete') {
317
+ if (state.workflowMode === 'lite') {
318
+ return {
319
+ step: 'oat-project-pr-final',
320
+ reason: 'Generate final PR description from plan and implementation',
321
+ };
322
+ }
301
323
  if (!state.docsUpdated || state.docsUpdated === '') {
302
324
  return {
303
325
  step: 'oat-project-document',
@@ -469,6 +491,7 @@ function buildDashboardMarkdown(project, state, knowledge, staleness, nextStep,
469
491
  lines.push('- `oat-project-new` - Create a spec-driven project');
470
492
  lines.push('- `oat-project-quick-start` - Create a quick workflow project');
471
493
  lines.push('- `oat-project-import-plan` - Import an external provider plan');
494
+ lines.push('- `oat-project-lite` - Create a lite workflow project');
472
495
  lines.push('- `oat project open <name>` - Open or resume a project');
473
496
  lines.push('- `oat project pause [name]` - Pause active or named project');
474
497
  lines.push('- `oat-project-complete` - Mark project complete');
@@ -1 +1 @@
1
- {"version":3,"file":"pack-manifest.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACf,CAAC;AAEF,eAAO,MAAM,UAAU,4GASiB,CAAC;AAEzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAkID,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAwLlD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAMhE;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,aAAa,GACnB,SAAS,mBAAmB,EAAE,CAGhC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAC9C,MAAM,EAAE,CAQV;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAIlE;AAoJD,wBAAgB,oBAAoB,CAClC,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,IAAI,CAiEN"}
1
+ {"version":3,"file":"pack-manifest.d.ts","sourceRoot":"","sources":["../../../../src/commands/tools/shared/pack-manifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,QAAQ,EACT,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACf,CAAC;AAEF,eAAO,MAAM,UAAU,4GASiB,CAAC;AAEzC,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAmID,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAyLlD,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAMhE;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,aAAa,GACnB,SAAS,mBAAmB,EAAE,CAGhC;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAC9C,MAAM,EAAE,CAQV;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAIlE;AAoJD,wBAAgB,oBAAoB,CAClC,QAAQ,GAAE,SAAS,cAAc,EAAkB,GAClD,IAAI,CAiEN"}
@@ -86,6 +86,7 @@ const WORKFLOW_SKILL_NAMES = [
86
86
  'oat-project-document',
87
87
  'oat-project-implement',
88
88
  'oat-project-import-plan',
89
+ 'oat-project-lite',
89
90
  'oat-project-new',
90
91
  'oat-project-next',
91
92
  'oat-project-open',
@@ -189,6 +190,7 @@ export const PACK_MANIFEST = [
189
190
  'spec.md',
190
191
  'design.md',
191
192
  'plan.md',
193
+ 'plan-lite.md',
192
194
  'implementation.md',
193
195
  'summary.md',
194
196
  'project-log.md',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-agent-toolkit/cli",
3
- "version": "0.2.59",
3
+ "version": "0.2.62",
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.2.59"
37
+ "@open-agent-toolkit/control-plane": "0.2.62"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.10.0",