@tmddev/tmd 0.1.0 → 0.2.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.
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Pipeline orchestration engine for automated PDCA execution
3
+ */
4
+ import { type PipelineConfig } from './pipeline-config.js';
5
+ export type PipelinePhase = 'do' | 'check' | 'act';
6
+ export interface PhaseResult {
7
+ phase: PipelinePhase;
8
+ success: boolean;
9
+ startTime: Date;
10
+ endTime: Date;
11
+ error?: string;
12
+ details?: Record<string, unknown>;
13
+ }
14
+ export interface PipelineResult {
15
+ taskId: string;
16
+ success: boolean;
17
+ startTime: Date;
18
+ endTime: Date;
19
+ phases: PhaseResult[];
20
+ error?: string;
21
+ }
22
+ export interface PipelineState {
23
+ taskId: string;
24
+ currentPhase?: PipelinePhase;
25
+ completedPhases: PipelinePhase[];
26
+ lastRun?: Date;
27
+ lastError?: string;
28
+ phaseResults: PhaseResult[];
29
+ }
30
+ export declare class PipelineRunner {
31
+ private taskId;
32
+ private config;
33
+ private dryRun;
34
+ private state;
35
+ constructor(taskId: string, config: PipelineConfig, dryRun?: boolean);
36
+ /**
37
+ * Run the full pipeline from the specified phase
38
+ */
39
+ run(fromPhase?: PipelinePhase): Promise<PipelineResult>;
40
+ /**
41
+ * Validate that prerequisites for starting from a phase are met
42
+ */
43
+ private validatePrerequisites;
44
+ /**
45
+ * Execute a single phase
46
+ */
47
+ private executePhase;
48
+ /**
49
+ * Execute the Do phase
50
+ */
51
+ private executeDoPhase;
52
+ /**
53
+ * Execute skill steps
54
+ */
55
+ private executeSkillSteps;
56
+ /**
57
+ * Write execution results to execution.md and data.md
58
+ */
59
+ private writeExecutionResults;
60
+ /**
61
+ * Execute the Check phase
62
+ */
63
+ private executeCheckPhase;
64
+ /**
65
+ * Write check phase results
66
+ */
67
+ private writeCheckResults;
68
+ /**
69
+ * Execute the Act phase
70
+ */
71
+ private executeActPhase;
72
+ /**
73
+ * Get current pipeline state
74
+ */
75
+ getState(): PipelineState;
76
+ }
77
+ /**
78
+ * Get the current pipeline state for a task
79
+ */
80
+ export declare function getPipelineState(taskId: string): PipelineState;
81
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1,580 @@
1
+ /**
2
+ * Pipeline orchestration engine for automated PDCA execution
3
+ */
4
+ import { existsSync, readFileSync, writeFileSync } from 'fs';
5
+ import { join } from 'path';
6
+ import yaml from 'js-yaml';
7
+ import chalk from 'chalk';
8
+ import { getPlanDir, getDoDir, getCheckDir, getActDir, ensureDir } from './paths.js';
9
+ import { getTaskStatus, updateTaskStatus } from './task-status.js';
10
+ import { parseSuccessCriteria } from './pipeline-config.js';
11
+ import { executeStep } from './step-executor.js';
12
+ import { extractTasks, updateTaskStatus as updatePlanTaskStatus, detectSkillReference } from './tasks.js';
13
+ import { extractGoals, extractResults, compareGoalsAndResults } from './comparison.js';
14
+ import { identifyDeviations, analyzeRootCauses, recommendAdjustments } from './analysis.js';
15
+ import { parseEvaluationResults, parseDeviationAnalysis, identifySuccesses, identifyFailures, identifyUnresolvedIssues } from './act-processing.js';
16
+ import { extractSuccessfulPractices, generateStandardizationRecommendations, formatStandardizationDocument } from './standardization.js';
17
+ import { executionTemplate, evaluationTemplate, improvementTemplate, renderTemplate } from './templates.js';
18
+ import { getSkillDir } from './paths.js';
19
+ export class PipelineRunner {
20
+ taskId;
21
+ config;
22
+ dryRun;
23
+ state;
24
+ constructor(taskId, config, dryRun = false) {
25
+ this.taskId = taskId;
26
+ this.config = config;
27
+ this.dryRun = dryRun;
28
+ this.state = {
29
+ taskId,
30
+ completedPhases: [],
31
+ phaseResults: []
32
+ };
33
+ }
34
+ /**
35
+ * Run the full pipeline from the specified phase
36
+ */
37
+ async run(fromPhase) {
38
+ const startTime = new Date();
39
+ const phases = ['do', 'check', 'act'];
40
+ const startIndex = fromPhase ? phases.indexOf(fromPhase) : 0;
41
+ if (startIndex === -1) {
42
+ return {
43
+ taskId: this.taskId,
44
+ success: false,
45
+ startTime,
46
+ endTime: new Date(),
47
+ phases: [],
48
+ error: `Invalid phase: ${fromPhase ?? ''}`
49
+ };
50
+ }
51
+ // Validate prerequisites
52
+ const prereqError = this.validatePrerequisites(fromPhase);
53
+ if (prereqError) {
54
+ return {
55
+ taskId: this.taskId,
56
+ success: false,
57
+ startTime,
58
+ endTime: new Date(),
59
+ phases: [],
60
+ error: prereqError
61
+ };
62
+ }
63
+ const phaseResults = [];
64
+ let success = true;
65
+ let lastError;
66
+ const phasesToRun = phases.slice(startIndex);
67
+ for (const phase of phasesToRun) {
68
+ const phaseConfig = this.config.phases[phase];
69
+ if (!phaseConfig.auto) {
70
+ console.log(chalk.yellow(` Skipping ${phase} phase (auto: false)`));
71
+ continue;
72
+ }
73
+ console.log(chalk.blue(`\n Phase: ${phase.toUpperCase()}`));
74
+ this.state.currentPhase = phase;
75
+ const phaseResult = await this.executePhase(phase);
76
+ phaseResults.push(phaseResult);
77
+ if (!phaseResult.success) {
78
+ success = false;
79
+ lastError = phaseResult.error;
80
+ console.log(chalk.red(` Phase ${phase} failed: ${phaseResult.error ?? ''}`));
81
+ break;
82
+ }
83
+ this.state.completedPhases.push(phase);
84
+ console.log(chalk.green(` Phase ${phase} completed`));
85
+ }
86
+ this.state.lastRun = new Date();
87
+ this.state.phaseResults = phaseResults;
88
+ if (!success && lastError != null) {
89
+ this.state.lastError = lastError;
90
+ }
91
+ return {
92
+ taskId: this.taskId,
93
+ success,
94
+ startTime,
95
+ endTime: new Date(),
96
+ phases: phaseResults,
97
+ ...(lastError != null ? { error: lastError } : {})
98
+ };
99
+ }
100
+ /**
101
+ * Validate that prerequisites for starting from a phase are met
102
+ */
103
+ validatePrerequisites(fromPhase) {
104
+ const planPath = join(getPlanDir(this.taskId), 'plan.md');
105
+ if (!existsSync(planPath)) {
106
+ return `Plan not found for task: ${this.taskId}`;
107
+ }
108
+ if (fromPhase === 'check') {
109
+ const executionPath = join(getDoDir(this.taskId), 'execution.md');
110
+ if (!existsSync(executionPath)) {
111
+ return `Execution not found for task: ${this.taskId}. Run Do phase first.`;
112
+ }
113
+ }
114
+ if (fromPhase === 'act') {
115
+ const evaluationPath = join(getCheckDir(this.taskId), 'evaluation.md');
116
+ if (!existsSync(evaluationPath)) {
117
+ return `Evaluation not found for task: ${this.taskId}. Run Check phase first.`;
118
+ }
119
+ }
120
+ return null;
121
+ }
122
+ /**
123
+ * Execute a single phase
124
+ */
125
+ async executePhase(phase) {
126
+ const startTime = new Date();
127
+ try {
128
+ switch (phase) {
129
+ case 'do':
130
+ return await this.executeDoPhase(startTime);
131
+ case 'check':
132
+ return await this.executeCheckPhase(startTime);
133
+ case 'act':
134
+ return await this.executeActPhase(startTime);
135
+ default:
136
+ return {
137
+ phase,
138
+ success: false,
139
+ startTime,
140
+ endTime: new Date(),
141
+ error: `Unknown phase: ${String(phase)}`
142
+ };
143
+ }
144
+ }
145
+ catch (error) {
146
+ return {
147
+ phase,
148
+ success: false,
149
+ startTime,
150
+ endTime: new Date(),
151
+ error: error instanceof Error ? error.message : String(error)
152
+ };
153
+ }
154
+ }
155
+ /**
156
+ * Execute the Do phase
157
+ */
158
+ async executeDoPhase(startTime) {
159
+ const planPath = join(getPlanDir(this.taskId), 'plan.md');
160
+ const doDir = getDoDir(this.taskId);
161
+ const phaseConfig = this.config.phases.do;
162
+ if (!this.dryRun) {
163
+ ensureDir(doDir);
164
+ }
165
+ // Extract tasks
166
+ const tasks = extractTasks(planPath);
167
+ const incompleteTasks = tasks.filter(t => !t.completed);
168
+ if (incompleteTasks.length === 0) {
169
+ console.log(chalk.yellow(' All tasks already completed'));
170
+ return {
171
+ phase: 'do',
172
+ success: true,
173
+ startTime,
174
+ endTime: new Date(),
175
+ details: { tasksCompleted: tasks.length, totalTasks: tasks.length }
176
+ };
177
+ }
178
+ console.log(chalk.gray(` Tasks to execute: ${String(incompleteTasks.length)}/${String(tasks.length)}`));
179
+ // Initialize execution.md
180
+ const executionPath = join(doDir, 'execution.md');
181
+ const dataPath = join(doDir, 'data.md');
182
+ if (!this.dryRun) {
183
+ if (!existsSync(executionPath)) {
184
+ writeFileSync(executionPath, renderTemplate(executionTemplate, { taskId: this.taskId }));
185
+ }
186
+ if (!existsSync(dataPath)) {
187
+ writeFileSync(dataPath, '# Data Collection\n\n');
188
+ }
189
+ }
190
+ // Execute tasks
191
+ const stepResults = [];
192
+ const actionsTaken = [];
193
+ const dataCollected = [];
194
+ const observations = [];
195
+ const issues = [];
196
+ const context = {
197
+ taskId: this.taskId,
198
+ workingDir: process.cwd(),
199
+ dryRun: this.dryRun
200
+ };
201
+ for (const task of incompleteTasks) {
202
+ console.log(chalk.gray(` [${String(task.index)}] ${task.content.substring(0, 50)}${task.content.length > 50 ? '...' : ''}`));
203
+ // Check for skill reference
204
+ const skillRef = detectSkillReference(task.content);
205
+ if (skillRef) {
206
+ const skillResult = await this.executeSkillSteps(skillRef, context);
207
+ stepResults.push(...skillResult.results);
208
+ if (skillResult.output) {
209
+ dataCollected.push(`Skill ${skillRef}: ${skillResult.output}`);
210
+ }
211
+ if (!skillResult.success) {
212
+ issues.push(`Task ${String(task.index)} skill execution failed: ${skillResult.error ?? ''}`);
213
+ continue;
214
+ }
215
+ }
216
+ // Mark task as complete
217
+ if (!this.dryRun) {
218
+ updatePlanTaskStatus(planPath, task.index, true);
219
+ }
220
+ actionsTaken.push(`Completed task ${String(task.index)}: ${task.content}`);
221
+ }
222
+ // Check success criteria
223
+ const updatedTasks = this.dryRun ? tasks : extractTasks(planPath);
224
+ const completedCount = updatedTasks.filter(t => t.completed).length;
225
+ const criteriaResult = parseSuccessCriteria(phaseConfig.successCriteria, updatedTasks.length, completedCount);
226
+ if (!criteriaResult.passed) {
227
+ return {
228
+ phase: 'do',
229
+ success: false,
230
+ startTime,
231
+ endTime: new Date(),
232
+ ...(criteriaResult.reason != null ? { error: criteriaResult.reason } : {}),
233
+ details: { tasksCompleted: completedCount, totalTasks: updatedTasks.length }
234
+ };
235
+ }
236
+ // Write execution results
237
+ if (!this.dryRun) {
238
+ this.writeExecutionResults(executionPath, dataPath, {
239
+ actionsTaken,
240
+ dataCollected,
241
+ observations,
242
+ issues,
243
+ stepResults
244
+ });
245
+ updateTaskStatus(this.taskId, 'doing');
246
+ }
247
+ return {
248
+ phase: 'do',
249
+ success: true,
250
+ startTime,
251
+ endTime: new Date(),
252
+ details: {
253
+ tasksCompleted: completedCount,
254
+ totalTasks: updatedTasks.length,
255
+ stepsExecuted: stepResults.length
256
+ }
257
+ };
258
+ }
259
+ /**
260
+ * Execute skill steps
261
+ */
262
+ async executeSkillSteps(skillName, context) {
263
+ const skillDir = getSkillDir(skillName);
264
+ const stepsPath = join(skillDir, 'steps.yaml');
265
+ if (!existsSync(stepsPath)) {
266
+ return {
267
+ success: false,
268
+ results: [],
269
+ error: `Skill steps not found: ${skillName}`
270
+ };
271
+ }
272
+ try {
273
+ const stepsData = yaml.load(readFileSync(stepsPath, 'utf-8'));
274
+ const steps = (stepsData != null && typeof stepsData === 'object' && 'steps' in stepsData ? (stepsData.steps ?? []) : []);
275
+ const results = [];
276
+ const outputs = [];
277
+ for (const step of steps) {
278
+ const result = await executeStep(step, context);
279
+ results.push(result);
280
+ if (result.output) {
281
+ outputs.push(result.output);
282
+ }
283
+ if (!result.success) {
284
+ return {
285
+ success: false,
286
+ results,
287
+ output: outputs.join('\n'),
288
+ ...(result.error != null ? { error: result.error } : {})
289
+ };
290
+ }
291
+ }
292
+ return {
293
+ success: true,
294
+ results,
295
+ output: outputs.join('\n')
296
+ };
297
+ }
298
+ catch (error) {
299
+ return {
300
+ success: false,
301
+ results: [],
302
+ error: error instanceof Error ? error.message : String(error)
303
+ };
304
+ }
305
+ }
306
+ /**
307
+ * Write execution results to execution.md and data.md
308
+ */
309
+ writeExecutionResults(executionPath, dataPath, results) {
310
+ let content = readFileSync(executionPath, 'utf-8');
311
+ const timestamp = new Date().toISOString();
312
+ // Add actions taken
313
+ if (results.actionsTaken.length > 0) {
314
+ const actionsSection = `\n## Actions Taken\n\n${results.actionsTaken.map(a => `- [${timestamp}] ${a}`).join('\n')}\n`;
315
+ content = content.replace(/(## Actions Taken\n<!-- Document actions performed -->\n)/, actionsSection);
316
+ }
317
+ // Add data collected
318
+ if (results.dataCollected.length > 0) {
319
+ const dataSection = `\n## Data Collected\n\n${results.dataCollected.map(d => `- ${d}`).join('\n')}\n`;
320
+ content = content.replace(/(## Data Collected\n<!-- Record data collected during execution -->\n)/, dataSection);
321
+ }
322
+ // Add observations
323
+ if (results.observations.length > 0) {
324
+ const obsSection = `\n## Observations\n\n${results.observations.map(o => `- ${o}`).join('\n')}\n`;
325
+ content = content.replace(/(## Observations\n<!-- Note any observations or insights -->\n)/, obsSection);
326
+ }
327
+ // Add issues
328
+ if (results.issues.length > 0) {
329
+ const issuesSection = `\n## Issues Encountered\n\n${results.issues.map(i => `- ${i}`).join('\n')}\n`;
330
+ content = content.replace(/(## Issues Encountered\n<!-- Document any problems or blockers -->\n)/, issuesSection);
331
+ }
332
+ writeFileSync(executionPath, content);
333
+ // Write step results to data.md
334
+ if (results.stepResults.length > 0) {
335
+ const stepData = results.stepResults.map((r, i) => ({
336
+ step: i + 1,
337
+ success: r.success,
338
+ duration: r.duration,
339
+ output: r.output?.substring(0, 200)
340
+ }));
341
+ const dataContent = readFileSync(dataPath, 'utf-8');
342
+ writeFileSync(dataPath, dataContent + '\n## Step Execution Results\n\n```yaml\n' + yaml.dump(stepData) + '```\n');
343
+ }
344
+ }
345
+ /**
346
+ * Execute the Check phase
347
+ */
348
+ async executeCheckPhase(startTime) {
349
+ await Promise.resolve();
350
+ const planPath = join(getPlanDir(this.taskId), 'plan.md');
351
+ const executionPath = join(getDoDir(this.taskId), 'execution.md');
352
+ const dataPath = join(getDoDir(this.taskId), 'data.md');
353
+ const checkDir = getCheckDir(this.taskId);
354
+ const phaseConfig = this.config.phases.check;
355
+ if (!this.dryRun) {
356
+ ensureDir(checkDir);
357
+ }
358
+ // Extract goals and results
359
+ const goals = extractGoals(planPath);
360
+ const results = extractResults(executionPath, dataPath);
361
+ console.log(chalk.gray(` Goals found: ${String(goals.length)}`));
362
+ console.log(chalk.gray(` Results found: ${String(results.length)}`));
363
+ // Perform comparison
364
+ const comparisons = compareGoalsAndResults(goals, results);
365
+ // Calculate statistics
366
+ const totalGoals = comparisons.length;
367
+ const metGoals = comparisons.filter(c => c.status === 'met').length;
368
+ const unmetGoals = comparisons.filter(c => c.status === 'unmet').length;
369
+ const partialGoals = comparisons.filter(c => c.status === 'partial').length;
370
+ console.log(chalk.gray(` Goals met: ${String(metGoals)}/${String(totalGoals)}`));
371
+ if (unmetGoals > 0) {
372
+ console.log(chalk.yellow(` Goals unmet: ${String(unmetGoals)}`));
373
+ }
374
+ // Identify deviations
375
+ const deviations = identifyDeviations(comparisons);
376
+ let rootCauses = [];
377
+ let recommendations = [];
378
+ if (phaseConfig.analyze && deviations.length > 0) {
379
+ rootCauses = analyzeRootCauses(deviations);
380
+ }
381
+ if (phaseConfig.recommend && deviations.length > 0) {
382
+ recommendations = recommendAdjustments(deviations, rootCauses);
383
+ }
384
+ // Check success criteria
385
+ const criteria = phaseConfig.successCriteria;
386
+ if (criteria) {
387
+ if (!criteria.allowUnmetGoals && unmetGoals > 0) {
388
+ return {
389
+ phase: 'check',
390
+ success: false,
391
+ startTime,
392
+ endTime: new Date(),
393
+ error: `${String(unmetGoals)} goal(s) not met`,
394
+ details: { totalGoals, metGoals, unmetGoals, partialGoals }
395
+ };
396
+ }
397
+ }
398
+ // Write evaluation and deviation documents
399
+ if (!this.dryRun) {
400
+ this.writeCheckResults(checkDir, {
401
+ comparisons,
402
+ deviations,
403
+ rootCauses,
404
+ recommendations,
405
+ totalGoals,
406
+ metGoals,
407
+ unmetGoals
408
+ });
409
+ updateTaskStatus(this.taskId, 'checking');
410
+ }
411
+ return {
412
+ phase: 'check',
413
+ success: true,
414
+ startTime,
415
+ endTime: new Date(),
416
+ details: { totalGoals, metGoals, unmetGoals, partialGoals, deviations: deviations.length }
417
+ };
418
+ }
419
+ /**
420
+ * Write check phase results
421
+ */
422
+ writeCheckResults(checkDir, data) {
423
+ // Generate evaluation.md
424
+ let evaluationContent = renderTemplate(evaluationTemplate, { taskId: this.taskId });
425
+ // Add comparison table
426
+ evaluationContent += '\n## Comparison with Plan\n\n';
427
+ evaluationContent += '| Goal | Planned | Actual | Status | Deviation |\n';
428
+ evaluationContent += '|------|---------|--------|--------|-----------|\n';
429
+ for (const comp of data.comparisons) {
430
+ const goal = comp.goal.description.substring(0, 50) + (comp.goal.description.length > 50 ? '...' : '');
431
+ const planned = comp.goal.targetValue !== undefined ? String(comp.goal.targetValue) : 'N/A';
432
+ const actual = comp.result?.value !== undefined ? String(comp.result.value) : 'No data';
433
+ const status = comp.status === 'met' ? 'Met' : comp.status === 'unmet' ? 'Unmet' : comp.status;
434
+ const deviation = comp.deviation !== undefined ? comp.deviation.toFixed(2) : 'N/A';
435
+ evaluationContent += `| ${goal} | ${planned} | ${actual} | ${status} | ${deviation} |\n`;
436
+ }
437
+ evaluationContent += '\n## Results Summary\n\n';
438
+ evaluationContent += `- Total goals: ${String(data.totalGoals)}\n`;
439
+ evaluationContent += `- Goals met: ${String(data.metGoals)}\n`;
440
+ evaluationContent += `- Goals unmet: ${String(data.unmetGoals)}\n`;
441
+ if (data.recommendations.length > 0) {
442
+ evaluationContent += '\n## Recommendations\n\n';
443
+ for (const rec of data.recommendations) {
444
+ evaluationContent += `- **${rec.action}** (${rec.priority}): ${rec.description}\n`;
445
+ }
446
+ }
447
+ writeFileSync(join(checkDir, 'evaluation.md'), evaluationContent);
448
+ // Generate deviation.md
449
+ let deviationContent = '# Deviation Analysis\n\n';
450
+ if (data.deviations.length === 0) {
451
+ deviationContent += 'No deviations found. All goals were met.\n';
452
+ }
453
+ else {
454
+ deviationContent += '## Deviations Identified\n\n';
455
+ for (const dev of data.deviations) {
456
+ deviationContent += `### ${dev.description}\n`;
457
+ deviationContent += `- Type: ${dev.type}\n`;
458
+ deviationContent += `- Severity: ${dev.severity}\n\n`;
459
+ }
460
+ if (data.rootCauses.length > 0) {
461
+ deviationContent += '## Root Cause Analysis\n\n';
462
+ for (const cause of data.rootCauses) {
463
+ deviationContent += `### ${cause.category}\n`;
464
+ deviationContent += `${cause.description}\n\n`;
465
+ }
466
+ }
467
+ }
468
+ writeFileSync(join(checkDir, 'deviation.md'), deviationContent);
469
+ }
470
+ /**
471
+ * Execute the Act phase
472
+ */
473
+ async executeActPhase(startTime) {
474
+ await Promise.resolve();
475
+ const evaluationPath = join(getCheckDir(this.taskId), 'evaluation.md');
476
+ const deviationPath = join(getCheckDir(this.taskId), 'deviation.md');
477
+ const actDir = getActDir(this.taskId);
478
+ const phaseConfig = this.config.phases.act;
479
+ if (!this.dryRun) {
480
+ ensureDir(actDir);
481
+ }
482
+ // Parse check results
483
+ const evaluationResults = parseEvaluationResults(evaluationPath);
484
+ const deviationAnalysis = existsSync(deviationPath)
485
+ ? parseDeviationAnalysis(deviationPath)
486
+ : { deviations: [], rootCauses: [] };
487
+ // Identify successes and failures
488
+ const successes = identifySuccesses(evaluationResults);
489
+ const failures = identifyFailures(deviationAnalysis, evaluationResults);
490
+ const unresolvedIssues = identifyUnresolvedIssues(evaluationResults, deviationAnalysis);
491
+ console.log(chalk.gray(` Successes: ${String(successes.length)}`));
492
+ console.log(chalk.gray(` Failures: ${String(failures.length)}`));
493
+ console.log(chalk.gray(` Unresolved: ${String(unresolvedIssues.length)}`));
494
+ if (!this.dryRun) {
495
+ // Generate improvement.md
496
+ let improvementContent = renderTemplate(improvementTemplate, { taskId: this.taskId });
497
+ if (failures.length > 0) {
498
+ improvementContent += '\n## Corrective Actions\n\n';
499
+ for (const failure of failures) {
500
+ improvementContent += `- **${failure.goal}**: ${failure.lesson ?? failure.deviation}\n`;
501
+ }
502
+ improvementContent += '\n## Lessons Learned\n\n';
503
+ for (const failure of failures) {
504
+ if (failure.lesson) {
505
+ improvementContent += `- ${failure.lesson}\n`;
506
+ }
507
+ }
508
+ }
509
+ writeFileSync(join(actDir, 'improvement.md'), improvementContent);
510
+ // Generate standardization.md if enabled
511
+ if (phaseConfig.standardize && successes.length > 0) {
512
+ const practices = extractSuccessfulPractices(successes);
513
+ const recommendations = generateStandardizationRecommendations(practices);
514
+ const standardizationContent = formatStandardizationDocument(practices, recommendations);
515
+ writeFileSync(join(actDir, 'standardization.md'), standardizationContent);
516
+ }
517
+ // Generate next-cycle-items.md if enabled
518
+ if (phaseConfig.carryForward && unresolvedIssues.length > 0) {
519
+ let nextCycleContent = `# Next Cycle Planning Items\n\n`;
520
+ nextCycleContent += `Items from task ${this.taskId}:\n\n`;
521
+ for (const issue of unresolvedIssues) {
522
+ nextCycleContent += `- [ ] ${issue.description} (Priority: ${issue.priority})\n`;
523
+ }
524
+ writeFileSync(join(actDir, 'next-cycle-items.md'), nextCycleContent);
525
+ }
526
+ // Update status
527
+ if (phaseConfig.completeOnSuccess) {
528
+ updateTaskStatus(this.taskId, 'completed');
529
+ console.log(chalk.green(' Task marked as completed'));
530
+ }
531
+ else {
532
+ updateTaskStatus(this.taskId, 'acting');
533
+ }
534
+ }
535
+ return {
536
+ phase: 'act',
537
+ success: true,
538
+ startTime,
539
+ endTime: new Date(),
540
+ details: {
541
+ successes: successes.length,
542
+ failures: failures.length,
543
+ unresolvedIssues: unresolvedIssues.length
544
+ }
545
+ };
546
+ }
547
+ /**
548
+ * Get current pipeline state
549
+ */
550
+ getState() {
551
+ return { ...this.state };
552
+ }
553
+ }
554
+ /**
555
+ * Get the current pipeline state for a task
556
+ */
557
+ export function getPipelineState(taskId) {
558
+ const status = getTaskStatus(taskId);
559
+ const completedPhases = [];
560
+ if (existsSync(join(getDoDir(taskId), 'execution.md'))) {
561
+ completedPhases.push('do');
562
+ }
563
+ if (existsSync(join(getCheckDir(taskId), 'evaluation.md'))) {
564
+ completedPhases.push('check');
565
+ }
566
+ if (existsSync(join(getActDir(taskId), 'improvement.md'))) {
567
+ completedPhases.push('act');
568
+ }
569
+ const currentPhase = status === 'doing' ? 'do'
570
+ : status === 'checking' ? 'check'
571
+ : status === 'acting' ? 'act'
572
+ : undefined;
573
+ return {
574
+ taskId,
575
+ ...(currentPhase != null ? { currentPhase } : {}),
576
+ completedPhases,
577
+ phaseResults: []
578
+ };
579
+ }
580
+ //# sourceMappingURL=pipeline.js.map
@@ -1,3 +1,11 @@
1
- export declare function createSkill(description: string, taskId: string): string | null;
2
- export declare function executeSkill(skillName: string, _taskId: string, parallel?: boolean, maxConcurrency?: number): Promise<void>;
1
+ export interface CreateSkillOptions {
2
+ taskId?: string;
3
+ tags?: string[];
4
+ }
5
+ /**
6
+ * Create a skill from a plan (tmd plan --skill). Generates name from description.
7
+ * Options.tags is applied when provided; options.taskId is used as createdFrom when provided.
8
+ */
9
+ export declare function createSkill(description: string, taskId: string, options?: CreateSkillOptions): string | null;
10
+ export declare function executeSkill(skillName: string, taskId: string, parallel?: boolean, maxConcurrency?: number, params?: Record<string, string>): Promise<void>;
3
11
  //# sourceMappingURL=skills.d.ts.map