@bicorne/task-flow 0.1.0

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 (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/SKILL.md +250 -0
  4. package/assets/.harnessrc +10 -0
  5. package/assets/PHASE-task.json.example +50 -0
  6. package/assets/design.md +69 -0
  7. package/assets/hooks.json +15 -0
  8. package/assets/product-requirement.md +82 -0
  9. package/assets/schema.json +127 -0
  10. package/assets/tasks.md +26 -0
  11. package/dist/commands/analyze.d.ts +32 -0
  12. package/dist/commands/analyze.js +338 -0
  13. package/dist/commands/archive.d.ts +11 -0
  14. package/dist/commands/archive.js +53 -0
  15. package/dist/commands/design.d.ts +38 -0
  16. package/dist/commands/design.js +492 -0
  17. package/dist/commands/extract.d.ts +31 -0
  18. package/dist/commands/extract.js +477 -0
  19. package/dist/commands/init.d.ts +24 -0
  20. package/dist/commands/init.js +165 -0
  21. package/dist/commands/merge/index.d.ts +17 -0
  22. package/dist/commands/merge/index.js +322 -0
  23. package/dist/commands/merge/merger.d.ts +18 -0
  24. package/dist/commands/merge/merger.js +151 -0
  25. package/dist/commands/merge/types.d.ts +67 -0
  26. package/dist/commands/merge/types.js +6 -0
  27. package/dist/commands/merge/validators.d.ts +14 -0
  28. package/dist/commands/merge/validators.js +147 -0
  29. package/dist/commands/merge.d.ts +7 -0
  30. package/dist/commands/merge.js +15 -0
  31. package/dist/commands/start.d.ts +32 -0
  32. package/dist/commands/start.js +265 -0
  33. package/dist/commands/status.d.ts +15 -0
  34. package/dist/commands/status.js +143 -0
  35. package/dist/commands/sync.d.ts +11 -0
  36. package/dist/commands/sync.js +58 -0
  37. package/dist/commands/tasks-gen/doc-parser.d.ts +7 -0
  38. package/dist/commands/tasks-gen/doc-parser.js +259 -0
  39. package/dist/commands/tasks-gen/generators.d.ts +33 -0
  40. package/dist/commands/tasks-gen/generators.js +141 -0
  41. package/dist/commands/tasks-gen/index.d.ts +30 -0
  42. package/dist/commands/tasks-gen/index.js +345 -0
  43. package/dist/commands/tasks-gen/parsers.d.ts +29 -0
  44. package/dist/commands/tasks-gen/parsers.js +272 -0
  45. package/dist/commands/tasks-gen/templates.d.ts +8 -0
  46. package/dist/commands/tasks-gen/templates.js +37 -0
  47. package/dist/commands/tasks-gen/types.d.ts +71 -0
  48. package/dist/commands/tasks-gen/types.js +17 -0
  49. package/dist/commands/tasks-gen/validators.d.ts +14 -0
  50. package/dist/commands/tasks-gen/validators.js +54 -0
  51. package/dist/commands/tasks.d.ts +9 -0
  52. package/dist/commands/tasks.js +22 -0
  53. package/dist/commands/worktree.d.ts +28 -0
  54. package/dist/commands/worktree.js +275 -0
  55. package/dist/hooks/check-prd-exists.d.ts +20 -0
  56. package/dist/hooks/check-prd-exists.js +61 -0
  57. package/dist/hooks/check-worktree-conflict.d.ts +34 -0
  58. package/dist/hooks/check-worktree-conflict.js +107 -0
  59. package/dist/hooks/hook-runner/executor.d.ts +18 -0
  60. package/dist/hooks/hook-runner/executor.js +143 -0
  61. package/dist/hooks/hook-runner/index.d.ts +64 -0
  62. package/dist/hooks/hook-runner/index.js +220 -0
  63. package/dist/hooks/hook-runner/loader.d.ts +23 -0
  64. package/dist/hooks/hook-runner/loader.js +126 -0
  65. package/dist/hooks/hook-runner/types.d.ts +59 -0
  66. package/dist/hooks/hook-runner/types.js +6 -0
  67. package/dist/hooks/hook-runner.d.ts +9 -0
  68. package/dist/hooks/hook-runner.js +30 -0
  69. package/dist/hooks/phase-complete-detector.d.ts +35 -0
  70. package/dist/hooks/phase-complete-detector.js +203 -0
  71. package/dist/hooks/phase-gate-validator.d.ts +76 -0
  72. package/dist/hooks/phase-gate-validator.js +407 -0
  73. package/dist/hooks/save-checkpoint.d.ts +43 -0
  74. package/dist/hooks/save-checkpoint.js +144 -0
  75. package/dist/hooks/start-mcp-servers.d.ts +50 -0
  76. package/dist/hooks/start-mcp-servers.js +75 -0
  77. package/dist/hooks/stop-mcp-servers.d.ts +40 -0
  78. package/dist/hooks/stop-mcp-servers.js +58 -0
  79. package/dist/index.d.ts +29 -0
  80. package/dist/index.js +238 -0
  81. package/dist/lib/archive.d.ts +31 -0
  82. package/dist/lib/archive.js +226 -0
  83. package/dist/lib/config.d.ts +93 -0
  84. package/dist/lib/config.js +251 -0
  85. package/dist/lib/constants.d.ts +222 -0
  86. package/dist/lib/constants.js +247 -0
  87. package/dist/lib/interactive.d.ts +31 -0
  88. package/dist/lib/interactive.js +166 -0
  89. package/dist/lib/mcp-client.d.ts +156 -0
  90. package/dist/lib/mcp-client.js +370 -0
  91. package/dist/lib/state.d.ts +119 -0
  92. package/dist/lib/state.js +293 -0
  93. package/dist/slash/executor.d.ts +22 -0
  94. package/dist/slash/executor.js +259 -0
  95. package/dist/slash/index.d.ts +11 -0
  96. package/dist/slash/index.js +45 -0
  97. package/dist/slash/parser.d.ts +24 -0
  98. package/dist/slash/parser.js +101 -0
  99. package/dist/slash/registry.d.ts +22 -0
  100. package/dist/slash/registry.js +155 -0
  101. package/dist/spec/openspec-to-task/builders.d.ts +107 -0
  102. package/dist/spec/openspec-to-task/builders.js +138 -0
  103. package/dist/spec/openspec-to-task/index.d.ts +20 -0
  104. package/dist/spec/openspec-to-task/index.js +182 -0
  105. package/dist/spec/openspec-to-task/parsers.d.ts +65 -0
  106. package/dist/spec/openspec-to-task/parsers.js +232 -0
  107. package/dist/spec/openspec-to-task/types.d.ts +49 -0
  108. package/dist/spec/openspec-to-task/types.js +6 -0
  109. package/dist/spec/sync-openspec-to-task.d.ts +7 -0
  110. package/dist/spec/sync-openspec-to-task.js +21 -0
  111. package/dist/spec/sync-task-to-openspec.d.ts +27 -0
  112. package/dist/spec/sync-task-to-openspec.js +288 -0
  113. package/dist/types/ai-context.d.ts +108 -0
  114. package/dist/types/ai-context.js +9 -0
  115. package/package.json +66 -0
  116. package/references/AI-CONVERSATION-TUTORIAL.md +270 -0
  117. package/references/CLI-TUTORIAL.md +447 -0
  118. package/references/GIT-WORKTREE-SOP.md +109 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * commands/tasks-gen/doc-parser.ts
3
+ * Parse PRD and design documents to extract tasks
4
+ */
5
+ import { Task } from './types';
6
+ export declare function parseDocumentsToTasks(prdContent: string, designContent: string | null, _changeName: string): Task[];
7
+ export declare function extractProjectName(prdContent: string): string;
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ /**
3
+ * commands/tasks-gen/doc-parser.ts
4
+ * Parse PRD and design documents to extract tasks
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseDocumentsToTasks = parseDocumentsToTasks;
8
+ exports.extractProjectName = extractProjectName;
9
+ const PRIORITY_MAP = {
10
+ P0: 'high',
11
+ P1: 'medium',
12
+ P2: 'low',
13
+ p0: 'high',
14
+ p1: 'medium',
15
+ p2: 'low',
16
+ };
17
+ function extractSection(content, sectionTitle) {
18
+ const lines = content.split(/\r?\n/);
19
+ const sectionStartRegex = new RegExp(`^(#{2,})\\s+${sectionTitle}`, 'i');
20
+ let startIndex = -1;
21
+ let endIndex = lines.length;
22
+ let sectionLevel = 0;
23
+ for (let i = 0; i < lines.length; i += 1) {
24
+ const line = lines[i] || '';
25
+ const match = line.match(sectionStartRegex);
26
+ if (match) {
27
+ startIndex = i;
28
+ sectionLevel = match[1]?.length || 2;
29
+ continue;
30
+ }
31
+ if (startIndex !== -1) {
32
+ const nextSectionMatch = line.match(/^(#{1,})\s+/);
33
+ if (nextSectionMatch) {
34
+ const nextLevel = nextSectionMatch[1]?.length || 0;
35
+ if (nextLevel <= sectionLevel) {
36
+ endIndex = i;
37
+ break;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ if (startIndex === -1) {
43
+ return '';
44
+ }
45
+ return lines.slice(startIndex, endIndex).join('\n');
46
+ }
47
+ function sanitizeCell(cell) {
48
+ return cell
49
+ .replace(/<br\s*\/?>/gi, '\n')
50
+ .replace(/<[^>]+>/g, '')
51
+ .trim();
52
+ }
53
+ function parseFeatureTable(section) {
54
+ const features = [];
55
+ const lines = section.split(/\r?\n/);
56
+ let featureCounter = 0;
57
+ let headerIndices = {};
58
+ for (const line of lines) {
59
+ const trimmed = line.trim();
60
+ if (!trimmed.startsWith('|') || !trimmed.endsWith('|')) {
61
+ continue;
62
+ }
63
+ if (trimmed.includes('---')) {
64
+ continue;
65
+ }
66
+ const cells = trimmed
67
+ .split('|')
68
+ .map((cell) => sanitizeCell(cell.trim()))
69
+ .filter((cell) => cell.length > 0);
70
+ if (cells.some((cell) => cell.includes('功能名称') || cell.includes('优先级'))) {
71
+ headerIndices = {};
72
+ cells.forEach((cell, idx) => {
73
+ const lower = cell.toLowerCase();
74
+ if (lower.includes('功能名称') || lower.includes('feature') || lower.includes('名称')) {
75
+ headerIndices.name = idx;
76
+ }
77
+ if (lower.includes('优先级') || lower.includes('priority')) {
78
+ headerIndices.priority = idx;
79
+ }
80
+ if (lower.includes('描述') || lower.includes('description')) {
81
+ headerIndices.description = idx;
82
+ }
83
+ if (lower.includes('验收') || lower.includes('acceptance') || lower.includes('标准')) {
84
+ headerIndices.acceptanceCriteria = idx;
85
+ }
86
+ if (lower.includes('编号') || lower.includes('id') || lower.includes('#')) {
87
+ headerIndices.id = idx;
88
+ }
89
+ });
90
+ continue;
91
+ }
92
+ if (cells.length >= 2) {
93
+ featureCounter += 1;
94
+ const nameIdx = headerIndices.name ?? 0;
95
+ const priorityIdx = headerIndices.priority ?? (nameIdx + 1);
96
+ const descIdx = headerIndices.description ?? (priorityIdx + 1);
97
+ const acIdx = headerIndices.acceptanceCriteria ?? (descIdx + 1);
98
+ const feature = {
99
+ id: headerIndices.id !== undefined ? (cells[headerIndices.id] ?? `F-${featureCounter}`) : `F-${featureCounter}`,
100
+ name: cells[nameIdx] ?? `Feature ${featureCounter}`,
101
+ priority: cells[priorityIdx] ?? 'medium',
102
+ description: cells[descIdx] ?? '',
103
+ acceptanceCriteria: cells[acIdx] ?? '',
104
+ };
105
+ features.push(feature);
106
+ }
107
+ }
108
+ return features;
109
+ }
110
+ function parseDesignDocument(designContent) {
111
+ const design = {
112
+ modules: [],
113
+ apis: [],
114
+ dataModels: [],
115
+ };
116
+ const archSection = extractSection(designContent, '架构设计');
117
+ const moduleMatches = archSection.match(/[-*]\s+(.+)/g);
118
+ if (moduleMatches) {
119
+ design.modules = moduleMatches.map((m) => m.replace(/^[-*]\s+/, '').trim());
120
+ }
121
+ const apiSection = extractSection(designContent, '接口设计');
122
+ const apiMatches = apiSection.match(/[-*]\s+(.+)/g);
123
+ if (apiMatches) {
124
+ design.apis = apiMatches.map((m) => m.replace(/^[-*]\s+/, '').trim());
125
+ }
126
+ const dataSection = extractSection(designContent, '数据模型');
127
+ const dataMatches = dataSection.match(/[-*]\s+(.+)/g);
128
+ if (dataMatches) {
129
+ design.dataModels = dataMatches.map((m) => m.replace(/^[-*]\s+/, '').trim());
130
+ }
131
+ return design;
132
+ }
133
+ function inferPhase(priority) {
134
+ const normalizedPriority = PRIORITY_MAP[priority] || priority;
135
+ switch (normalizedPriority) {
136
+ case 'high':
137
+ return 2;
138
+ case 'medium':
139
+ return 3;
140
+ case 'low':
141
+ return 4;
142
+ default:
143
+ return 3;
144
+ }
145
+ }
146
+ function inferFiles(feature, _design) {
147
+ const files = [];
148
+ const featureLower = (feature.name + ' ' + feature.description).toLowerCase();
149
+ if (featureLower.includes('api') || featureLower.includes('接口')) {
150
+ files.push('src/api/');
151
+ }
152
+ if (featureLower.includes('数据') || featureLower.includes('database') || featureLower.includes('model')) {
153
+ files.push('src/models/');
154
+ }
155
+ if (featureLower.includes('页面') || featureLower.includes('page') || featureLower.includes('ui')) {
156
+ files.push('src/pages/');
157
+ }
158
+ if (featureLower.includes('组件') || featureLower.includes('component')) {
159
+ files.push('src/components/');
160
+ }
161
+ if (featureLower.includes('工具') || featureLower.includes('util') || featureLower.includes('helper')) {
162
+ files.push('src/utils/');
163
+ }
164
+ if (files.length === 0) {
165
+ files.push('src/');
166
+ }
167
+ return files;
168
+ }
169
+ function parseDocumentsToTasks(prdContent, designContent, _changeName) {
170
+ const tasks = [];
171
+ const design = designContent ? parseDesignDocument(designContent) : { modules: [], apis: [], dataModels: [] };
172
+ const hasArchitectureTask = design.modules.length > 0 || designContent;
173
+ if (hasArchitectureTask) {
174
+ tasks.push({
175
+ id: 'PHASE-1-1-1',
176
+ phase: 1,
177
+ subphase: 1,
178
+ sequence: 1,
179
+ title: '搭建基础架构',
180
+ type: 'feat',
181
+ priority: 'high',
182
+ status: 'pending',
183
+ dependencies: [],
184
+ spec: {
185
+ description: '根据技术规格搭建项目基础架构',
186
+ files: ['src/'],
187
+ context: design.modules,
188
+ },
189
+ acceptance_criteria: ['架构符合设计文档', '模块划分清晰'],
190
+ });
191
+ }
192
+ const featureSection = extractSection(prdContent, '(详细功能需求|功能需求)');
193
+ const features = parseFeatureTable(featureSection);
194
+ const phaseTaskCount = {};
195
+ for (const feature of features) {
196
+ const phase = inferPhase(feature.priority);
197
+ if (!phaseTaskCount[phase]) {
198
+ phaseTaskCount[phase] = 1;
199
+ }
200
+ else {
201
+ phaseTaskCount[phase] += 1;
202
+ }
203
+ const taskId = `PHASE-${phase}-${phase}-${phaseTaskCount[phase]}`;
204
+ const files = inferFiles(feature, design);
205
+ const priority = PRIORITY_MAP[feature.priority] || 'medium';
206
+ const task = {
207
+ id: taskId,
208
+ phase,
209
+ subphase: phase,
210
+ sequence: phaseTaskCount[phase],
211
+ title: feature.name,
212
+ type: 'feat',
213
+ priority: priority,
214
+ status: 'pending',
215
+ dependencies: hasArchitectureTask ? ['PHASE-1-1-1'] : [],
216
+ spec: {
217
+ description: feature.description || feature.name,
218
+ files,
219
+ context: [],
220
+ },
221
+ acceptance_criteria: feature.acceptanceCriteria
222
+ ? feature.acceptanceCriteria.split(/\n/).filter((s) => s.length > 0)
223
+ : ['功能正常工作', '测试通过'],
224
+ };
225
+ tasks.push(task);
226
+ }
227
+ const nonFuncSection = extractSection(prdContent, '非功能性需求');
228
+ if (nonFuncSection && nonFuncSection.length > 50) {
229
+ const lastTaskId = tasks.length > 0 ? tasks[tasks.length - 1]?.id : undefined;
230
+ tasks.push({
231
+ id: `PHASE-5-5-1`,
232
+ phase: 5,
233
+ subphase: 5,
234
+ sequence: 1,
235
+ title: '非功能性需求实现',
236
+ type: 'feat',
237
+ priority: 'medium',
238
+ status: 'pending',
239
+ dependencies: lastTaskId ? [lastTaskId] : [],
240
+ spec: {
241
+ description: '实现性能、安全、可用性等非功能性需求',
242
+ files: ['src/'],
243
+ context: [],
244
+ },
245
+ acceptance_criteria: ['性能达标', '安全检查通过', '可用性要求满足'],
246
+ });
247
+ }
248
+ return tasks;
249
+ }
250
+ function extractProjectName(prdContent) {
251
+ const lines = prdContent.split(/\r?\n/);
252
+ for (const line of lines) {
253
+ const headingMatch = line.match(/^#\s+(.+)$/);
254
+ if (headingMatch) {
255
+ return headingMatch[1] || 'Unknown Project';
256
+ }
257
+ }
258
+ return 'Unknown Project';
259
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * commands/tasks-gen/generators.ts
3
+ * Task file generation utilities
4
+ */
5
+ import { Task } from './types';
6
+ /**
7
+ * Generate a single phase JSON object
8
+ */
9
+ export declare function generatePhaseJson(task: Task, changeName: string, allTaskIds?: string[]): Record<string, unknown>;
10
+ /**
11
+ * Generate manifest JSON
12
+ */
13
+ export declare function generateManifestJson(changeName: string, tasks: Task[], options?: {
14
+ type?: string;
15
+ priority?: string;
16
+ }): Record<string, unknown>;
17
+ /**
18
+ * Generate phase JSON files for all tasks
19
+ */
20
+ export declare function generatePhaseFiles(tasksDir: string, tasks: Task[], changeName: string): {
21
+ generatedFiles: string[];
22
+ allTaskIds: string[];
23
+ error?: string;
24
+ };
25
+ /**
26
+ * Generate manifest JSON file
27
+ */
28
+ export declare function generateManifestFile(manifestPath: string, changeName: string, tasks: Task[], options?: {
29
+ type?: string;
30
+ priority?: string;
31
+ }): {
32
+ error?: string;
33
+ };
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ /**
3
+ * commands/tasks-gen/generators.ts
4
+ * Task file generation utilities
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.generatePhaseJson = generatePhaseJson;
41
+ exports.generateManifestJson = generateManifestJson;
42
+ exports.generatePhaseFiles = generatePhaseFiles;
43
+ exports.generateManifestFile = generateManifestFile;
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ /**
47
+ * Generate a single phase JSON object
48
+ */
49
+ function generatePhaseJson(task, changeName, allTaskIds = []) {
50
+ const dependencies = task.dependencies || [];
51
+ const invalidDependencies = dependencies.filter((depId) => !allTaskIds.includes(depId));
52
+ if (invalidDependencies.length > 0) {
53
+ console.warn(`[TASKS] Warning: Invalid dependencies found: ${invalidDependencies.join(', ')}`);
54
+ console.warn(`[TASKS] Available task IDs: ${allTaskIds.join(', ')}`);
55
+ }
56
+ return {
57
+ id: task.id,
58
+ type: task.type,
59
+ title: task.title,
60
+ priority: task.priority,
61
+ phase: task.phase,
62
+ dependencies: dependencies.filter((depId) => allTaskIds.includes(depId)),
63
+ docs_to_read: task.docs_to_read || [
64
+ `spec/changes/${changeName}/product-requirement.md`,
65
+ `spec/changes/${changeName}/design.md`,
66
+ ],
67
+ spec: {
68
+ description: task.spec.description || task.title,
69
+ files: task.spec.files.length > 0 ? task.spec.files : ['src/README.md'],
70
+ context: task.spec.context || [],
71
+ },
72
+ acceptance_criteria: task.acceptance_criteria && task.acceptance_criteria.length > 0
73
+ ? task.acceptance_criteria
74
+ : ['功能正常工作'],
75
+ implementation: task.implementation || {
76
+ steps: [],
77
+ notes: '',
78
+ },
79
+ validation: task.validation || {
80
+ commands: [],
81
+ manual_checks: [],
82
+ },
83
+ status: task.status,
84
+ };
85
+ }
86
+ /**
87
+ * Generate manifest JSON
88
+ */
89
+ function generateManifestJson(changeName, tasks, options = {}) {
90
+ return {
91
+ version: '1.0',
92
+ taskId: changeName,
93
+ type: options.type || 'feat',
94
+ priority: options.priority || 'medium',
95
+ title: changeName,
96
+ changeName,
97
+ totalTasks: tasks.length,
98
+ phases: [...new Set(tasks.map((t) => t.phase))].sort((a, b) => a - b),
99
+ mergeStrategy: {
100
+ type: 'squash',
101
+ deleteBranch: true,
102
+ deleteWorktree: true,
103
+ },
104
+ createdAt: new Date().toISOString(),
105
+ };
106
+ }
107
+ /**
108
+ * Generate phase JSON files for all tasks
109
+ */
110
+ function generatePhaseFiles(tasksDir, tasks, changeName) {
111
+ try {
112
+ fs.mkdirSync(tasksDir, { recursive: true });
113
+ const allTaskIds = tasks.map((t) => t.id);
114
+ const generatedFiles = [];
115
+ for (const task of tasks) {
116
+ const taskJsonPath = path.resolve(tasksDir, `${task.id}.json`);
117
+ const taskJson = generatePhaseJson(task, changeName, allTaskIds);
118
+ fs.writeFileSync(taskJsonPath, JSON.stringify(taskJson, null, 2), 'utf8');
119
+ generatedFiles.push(taskJsonPath);
120
+ }
121
+ return { generatedFiles, allTaskIds };
122
+ }
123
+ catch (error) {
124
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
125
+ return { generatedFiles: [], allTaskIds: [], error: errorMessage };
126
+ }
127
+ }
128
+ /**
129
+ * Generate manifest JSON file
130
+ */
131
+ function generateManifestFile(manifestPath, changeName, tasks, options = {}) {
132
+ try {
133
+ const manifestJson = generateManifestJson(changeName, tasks, options);
134
+ fs.writeFileSync(manifestPath, JSON.stringify(manifestJson, null, 2), 'utf8');
135
+ return {};
136
+ }
137
+ catch (error) {
138
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
139
+ return { error: errorMessage };
140
+ }
141
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * commands/tasks-gen/index.ts
3
+ * Generate PHASE-*.json files from product-requirement.md and design.md
4
+ * Supports AI input via stdin or --input parameter
5
+ */
6
+ import { TasksGenOptions, TasksGenResult } from './types';
7
+ import { parseTasksMd } from './parsers';
8
+ import { generatePhaseJson, generateManifestJson } from './generators';
9
+ /**
10
+ * Generate task files from AI input or tasks.md
11
+ */
12
+ export declare function generateTasks(options?: TasksGenOptions): Promise<TasksGenResult>;
13
+ /**
14
+ * Main entry point
15
+ */
16
+ export declare function main(): void;
17
+ declare const _default: {
18
+ generateTasks: typeof generateTasks;
19
+ parseTasksMd: typeof parseTasksMd;
20
+ generatePhaseJson: typeof generatePhaseJson;
21
+ generateManifestJson: typeof generateManifestJson;
22
+ TASK_SCHEMA: {
23
+ required: string[];
24
+ idPattern: RegExp;
25
+ types: string[];
26
+ priorities: string[];
27
+ statuses: string[];
28
+ };
29
+ };
30
+ export default _default;