@tmddev/tmd 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.
- package/LICENSE +201 -0
- package/README.md +424 -0
- package/bin/tmd.js +3 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +92 -0
- package/dist/commands/act.d.ts +3 -0
- package/dist/commands/act.js +210 -0
- package/dist/commands/check.d.ts +3 -0
- package/dist/commands/check.js +183 -0
- package/dist/commands/do.d.ts +3 -0
- package/dist/commands/do.js +310 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.js +56 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +89 -0
- package/dist/commands/show.d.ts +2 -0
- package/dist/commands/show.js +69 -0
- package/dist/commands/skills.d.ts +3 -0
- package/dist/commands/skills.js +243 -0
- package/dist/types.d.ts +79 -0
- package/dist/types.js +5 -0
- package/dist/utils/act-processing.d.ts +64 -0
- package/dist/utils/act-processing.js +222 -0
- package/dist/utils/analysis.d.ts +34 -0
- package/dist/utils/analysis.js +159 -0
- package/dist/utils/comparison.d.ts +34 -0
- package/dist/utils/comparison.js +217 -0
- package/dist/utils/language-validator.d.ts +11 -0
- package/dist/utils/language-validator.js +39 -0
- package/dist/utils/openspec.d.ts +5 -0
- package/dist/utils/openspec.js +91 -0
- package/dist/utils/paths.d.ts +10 -0
- package/dist/utils/paths.js +33 -0
- package/dist/utils/skills.d.ts +3 -0
- package/dist/utils/skills.js +248 -0
- package/dist/utils/skillssh.d.ts +12 -0
- package/dist/utils/skillssh.js +135 -0
- package/dist/utils/standardization.d.ts +26 -0
- package/dist/utils/standardization.js +106 -0
- package/dist/utils/task-chain.d.ts +35 -0
- package/dist/utils/task-chain.js +146 -0
- package/dist/utils/task-id.d.ts +5 -0
- package/dist/utils/task-id.js +15 -0
- package/dist/utils/task-status.d.ts +6 -0
- package/dist/utils/task-status.js +61 -0
- package/dist/utils/task-validator.d.ts +42 -0
- package/dist/utils/task-validator.js +178 -0
- package/dist/utils/tasks.d.ts +27 -0
- package/dist/utils/tasks.js +125 -0
- package/dist/utils/templates.d.ts +12 -0
- package/dist/utils/templates.js +143 -0
- package/package.json +84 -0
- package/scripts/postinstall.js +92 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { getSkillsDir, getSkillDir } from './paths.js';
|
|
4
|
+
import { generateTaskId } from './task-id.js';
|
|
5
|
+
import yaml from 'js-yaml';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
export function createSkill(description, taskId) {
|
|
8
|
+
const skillsDir = getSkillsDir();
|
|
9
|
+
ensureDir(skillsDir);
|
|
10
|
+
// Generate skill name from description
|
|
11
|
+
const skillName = generateTaskId(description).replace(/^\d+-/, '');
|
|
12
|
+
const skillDir = getSkillDir(skillName);
|
|
13
|
+
if (existsSync(skillDir)) {
|
|
14
|
+
console.log(chalk.yellow(` Skill already exists: ${skillName}`));
|
|
15
|
+
return skillName;
|
|
16
|
+
}
|
|
17
|
+
mkdirSync(skillDir, { recursive: true });
|
|
18
|
+
// Create skill.md with user story template
|
|
19
|
+
const skillContent = `# Skill: ${description}
|
|
20
|
+
|
|
21
|
+
## User Story
|
|
22
|
+
As a [role], I want to [action], so as to [benefit]
|
|
23
|
+
|
|
24
|
+
## Description
|
|
25
|
+
${description}
|
|
26
|
+
|
|
27
|
+
## Prerequisites
|
|
28
|
+
<!-- List prerequisites -->
|
|
29
|
+
|
|
30
|
+
## Skill Steps
|
|
31
|
+
<!-- Define executable steps -->
|
|
32
|
+
1.
|
|
33
|
+
2.
|
|
34
|
+
3.
|
|
35
|
+
|
|
36
|
+
## Expected Outcomes
|
|
37
|
+
<!-- Define expected results -->
|
|
38
|
+
|
|
39
|
+
## Validation Criteria
|
|
40
|
+
<!-- Define how to validate success -->
|
|
41
|
+
`;
|
|
42
|
+
writeFileSync(join(skillDir, 'skill.md'), skillContent);
|
|
43
|
+
// Create steps.yaml
|
|
44
|
+
const stepsContent = {
|
|
45
|
+
steps: [
|
|
46
|
+
{
|
|
47
|
+
type: 'example',
|
|
48
|
+
description: 'Example step',
|
|
49
|
+
// Add step configuration
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
};
|
|
53
|
+
writeFileSync(join(skillDir, 'steps.yaml'), yaml.dump(stepsContent));
|
|
54
|
+
// Create config.yaml
|
|
55
|
+
const configContent = {
|
|
56
|
+
// Configuration for skill execution
|
|
57
|
+
};
|
|
58
|
+
writeFileSync(join(skillDir, 'config.yaml'), yaml.dump(configContent));
|
|
59
|
+
// Create metadata.yaml
|
|
60
|
+
const metadataContent = {
|
|
61
|
+
name: skillName,
|
|
62
|
+
version: '1.0.0',
|
|
63
|
+
description: description,
|
|
64
|
+
tags: [],
|
|
65
|
+
createdFrom: taskId,
|
|
66
|
+
interface: {
|
|
67
|
+
input: [],
|
|
68
|
+
output: {}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
writeFileSync(join(skillDir, 'metadata.yaml'), yaml.dump(metadataContent));
|
|
72
|
+
return skillName;
|
|
73
|
+
}
|
|
74
|
+
function executeStep(step, stepIndex) {
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const startTime = Date.now();
|
|
77
|
+
try {
|
|
78
|
+
// Basic step execution based on type
|
|
79
|
+
switch (step.type) {
|
|
80
|
+
case 'database':
|
|
81
|
+
console.log(chalk.yellow(` Database operation: ${step.operation ?? 'query'}`));
|
|
82
|
+
// TODO: Implement database operations
|
|
83
|
+
break;
|
|
84
|
+
case 'file':
|
|
85
|
+
console.log(chalk.yellow(` File operation: ${step.operation ?? 'read'}`));
|
|
86
|
+
// TODO: Implement file operations
|
|
87
|
+
break;
|
|
88
|
+
case 'script':
|
|
89
|
+
console.log(chalk.yellow(` Script execution: ${step.script ?? 'unknown'}`));
|
|
90
|
+
// TODO: Implement script execution
|
|
91
|
+
break;
|
|
92
|
+
case 'api':
|
|
93
|
+
console.log(chalk.yellow(` API call: ${step.endpoint ?? 'unknown'}`));
|
|
94
|
+
// TODO: Implement API calls
|
|
95
|
+
break;
|
|
96
|
+
case 'image':
|
|
97
|
+
console.log(chalk.yellow(` Image processing: ${step.operation ?? 'process'}`));
|
|
98
|
+
// TODO: Implement image processing
|
|
99
|
+
break;
|
|
100
|
+
default:
|
|
101
|
+
console.log(chalk.yellow(` Unknown step type: ${step.type ?? 'undefined'}`));
|
|
102
|
+
}
|
|
103
|
+
const duration = Date.now() - startTime;
|
|
104
|
+
resolve({
|
|
105
|
+
stepIndex,
|
|
106
|
+
success: true,
|
|
107
|
+
duration
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const duration = Date.now() - startTime;
|
|
112
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
113
|
+
resolve({
|
|
114
|
+
stepIndex,
|
|
115
|
+
success: false,
|
|
116
|
+
error: errorMessage,
|
|
117
|
+
duration
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async function executeStepsConcurrently(steps, maxConcurrency = Infinity) {
|
|
123
|
+
const results = [];
|
|
124
|
+
const executing = [];
|
|
125
|
+
for (let i = 0; i < steps.length; i++) {
|
|
126
|
+
const step = steps[i];
|
|
127
|
+
if (!step)
|
|
128
|
+
continue;
|
|
129
|
+
const stepDeps = step.depends ?? [];
|
|
130
|
+
// Check if dependencies are satisfied (simplified - assumes sequential if dependencies exist)
|
|
131
|
+
const hasDependencies = Array.isArray(stepDeps) && stepDeps.length > 0;
|
|
132
|
+
if (hasDependencies) {
|
|
133
|
+
// Wait for dependencies to complete before executing
|
|
134
|
+
// For now, execute sequentially if dependencies exist
|
|
135
|
+
// TODO: Implement proper dependency resolution
|
|
136
|
+
await Promise.all(executing);
|
|
137
|
+
executing.length = 0;
|
|
138
|
+
}
|
|
139
|
+
const promise = executeStep(step, i);
|
|
140
|
+
executing.push(promise);
|
|
141
|
+
if (executing.length >= maxConcurrency) {
|
|
142
|
+
const completed = await Promise.race(executing);
|
|
143
|
+
results.push(completed);
|
|
144
|
+
// Remove one promise from executing (the one that completed)
|
|
145
|
+
// We can't reliably identify which one, so remove the first
|
|
146
|
+
// The promise is already resolved by Promise.race, so we can safely remove it
|
|
147
|
+
const removedPromise = executing.shift();
|
|
148
|
+
// Explicitly mark as handled to satisfy ESLint
|
|
149
|
+
void removedPromise;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Wait for remaining steps
|
|
153
|
+
if (executing.length > 0) {
|
|
154
|
+
const remainingResults = await Promise.allSettled(executing);
|
|
155
|
+
for (const result of remainingResults) {
|
|
156
|
+
if (result.status === 'fulfilled') {
|
|
157
|
+
results.push(result.value);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// Handle rejected promise - reason can be any type
|
|
161
|
+
const reason = result.reason;
|
|
162
|
+
let errorMessage;
|
|
163
|
+
if (reason instanceof Error) {
|
|
164
|
+
errorMessage = reason.message;
|
|
165
|
+
}
|
|
166
|
+
else if (typeof reason === 'string') {
|
|
167
|
+
errorMessage = reason;
|
|
168
|
+
}
|
|
169
|
+
else if (reason === null || reason === undefined) {
|
|
170
|
+
errorMessage = 'Unknown error';
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// For other types, use JSON.stringify if possible, otherwise fallback
|
|
174
|
+
try {
|
|
175
|
+
errorMessage = JSON.stringify(reason);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
errorMessage = 'Unknown error';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
results.push({
|
|
182
|
+
stepIndex: -1,
|
|
183
|
+
success: false,
|
|
184
|
+
error: errorMessage,
|
|
185
|
+
duration: 0
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return results.sort((a, b) => a.stepIndex - b.stepIndex);
|
|
191
|
+
}
|
|
192
|
+
export async function executeSkill(skillName, _taskId, parallel = false, maxConcurrency = Infinity) {
|
|
193
|
+
const skillDir = getSkillDir(skillName);
|
|
194
|
+
if (!existsSync(skillDir)) {
|
|
195
|
+
console.error(chalk.red(`✗ Skill not found: ${skillName}`));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const stepsPath = join(skillDir, 'steps.yaml');
|
|
199
|
+
if (!existsSync(stepsPath)) {
|
|
200
|
+
console.error(chalk.red(`✗ Skill steps not found: ${skillName}`));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const steps = yaml.load(readFileSync(stepsPath, 'utf-8'));
|
|
205
|
+
console.log(chalk.blue(` Executing skill: ${skillName}`));
|
|
206
|
+
console.log(chalk.gray(` Steps: ${String(steps.steps?.length ?? 0)}`));
|
|
207
|
+
console.log(chalk.gray(` Mode: ${parallel ? 'concurrent' : 'sequential'}`));
|
|
208
|
+
if (steps.steps && Array.isArray(steps.steps)) {
|
|
209
|
+
if (parallel) {
|
|
210
|
+
// Execute steps concurrently
|
|
211
|
+
const results = await executeStepsConcurrently(steps.steps, maxConcurrency);
|
|
212
|
+
const successCount = results.filter(r => r.success).length;
|
|
213
|
+
const failCount = results.length - successCount;
|
|
214
|
+
console.log(chalk.blue(` Execution Summary: ${String(successCount)} successful, ${String(failCount)} failed`));
|
|
215
|
+
if (failCount > 0) {
|
|
216
|
+
const failedSteps = results.filter(r => !r.success);
|
|
217
|
+
throw new Error(`Skill execution failed: ${String(failedSteps.length)} step(s) failed`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// Execute steps sequentially (original behavior)
|
|
222
|
+
for (let i = 0; i < steps.steps.length; i++) {
|
|
223
|
+
const step = steps.steps[i];
|
|
224
|
+
if (!step)
|
|
225
|
+
continue;
|
|
226
|
+
console.log(chalk.gray(` Step ${String(i + 1)}/${String(steps.steps.length)}: ${step.type ?? 'unknown'}`));
|
|
227
|
+
const result = await executeStep(step, i);
|
|
228
|
+
if (!result.success) {
|
|
229
|
+
const errorMsg = result.error ?? 'Unknown error';
|
|
230
|
+
throw new Error(`Step ${String(i + 1)} failed: ${errorMsg}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
console.log(chalk.green(` ✓ Skill execution completed: ${skillName}`));
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
239
|
+
console.error(chalk.red(`✗ Error executing skill: ${errorMessage}`));
|
|
240
|
+
throw e;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function ensureDir(path) {
|
|
244
|
+
if (!existsSync(path)) {
|
|
245
|
+
mkdirSync(path, { recursive: true });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface SkillsshResult {
|
|
2
|
+
success: boolean;
|
|
3
|
+
skillName?: string;
|
|
4
|
+
skillDir?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Fetches and converts a skill from skills.sh to TMD format
|
|
9
|
+
*/
|
|
10
|
+
export declare function addSkillFromSkillssh(ownerRepo: string): Promise<SkillsshResult>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=skillssh.d.ts.map
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { getSkillsDir, getSkillDir } from './paths.js';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
5
|
+
/**
|
|
6
|
+
* Fetches and converts a skill from skills.sh to TMD format
|
|
7
|
+
*/
|
|
8
|
+
export async function addSkillFromSkillssh(ownerRepo) {
|
|
9
|
+
// Validate owner/repo format
|
|
10
|
+
const parts = ownerRepo.split('/');
|
|
11
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
12
|
+
return {
|
|
13
|
+
success: false,
|
|
14
|
+
error: `Invalid format: "${ownerRepo}". Expected: <owner>/<repo>`
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const [owner, repo] = parts;
|
|
18
|
+
const skillName = repo;
|
|
19
|
+
// Check if skill already exists
|
|
20
|
+
const skillDir = getSkillDir(skillName);
|
|
21
|
+
if (existsSync(skillDir)) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
error: `Skill already exists: ${skillName}`
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Fetch skill content from GitHub
|
|
28
|
+
const skillContent = await fetchSkillContent(owner, repo);
|
|
29
|
+
if (!skillContent.success) {
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
error: skillContent.error ?? 'Unknown error'
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Create skill directory
|
|
36
|
+
const skillsDir = getSkillsDir();
|
|
37
|
+
if (!existsSync(skillsDir)) {
|
|
38
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
mkdirSync(skillDir, { recursive: true });
|
|
41
|
+
// Convert and save skill files
|
|
42
|
+
saveSkillFiles(skillDir, skillName, ownerRepo, skillContent.content ?? '');
|
|
43
|
+
return {
|
|
44
|
+
success: true,
|
|
45
|
+
skillName,
|
|
46
|
+
skillDir
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async function fetchSkillContent(owner, repo) {
|
|
50
|
+
// Try common skill file locations
|
|
51
|
+
const possiblePaths = [
|
|
52
|
+
`https://raw.githubusercontent.com/${owner}/${repo}/main/README.md`,
|
|
53
|
+
`https://raw.githubusercontent.com/${owner}/${repo}/master/README.md`,
|
|
54
|
+
`https://raw.githubusercontent.com/${owner}/${repo}/main/skill.md`,
|
|
55
|
+
`https://raw.githubusercontent.com/${owner}/${repo}/master/skill.md`,
|
|
56
|
+
];
|
|
57
|
+
for (const url of possiblePaths) {
|
|
58
|
+
try {
|
|
59
|
+
const response = await fetch(url);
|
|
60
|
+
if (response.ok) {
|
|
61
|
+
const content = await response.text();
|
|
62
|
+
return { success: true, content };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Continue to next URL
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: `Could not fetch skill from ${owner}/${repo}. Check that the repository exists and is public.`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function saveSkillFiles(skillDir, skillName, ownerRepo, content) {
|
|
75
|
+
// Parse frontmatter if present
|
|
76
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
77
|
+
// Create skill.md
|
|
78
|
+
const skillMd = `# Skill: ${skillName}
|
|
79
|
+
|
|
80
|
+
## Source
|
|
81
|
+
Imported from [skills.sh](https://skills.sh): \`${ownerRepo}\`
|
|
82
|
+
|
|
83
|
+
## Description
|
|
84
|
+
${body || 'No description available.'}
|
|
85
|
+
`;
|
|
86
|
+
writeFileSync(join(skillDir, 'skill.md'), skillMd);
|
|
87
|
+
// Create metadata.yaml with source attribution
|
|
88
|
+
const version = typeof frontmatter['version'] === 'string' ? frontmatter['version'] : '1.0.0';
|
|
89
|
+
const description = typeof frontmatter['description'] === 'string' ? frontmatter['description'] : `Skill imported from skills.sh: ${ownerRepo}`;
|
|
90
|
+
const tags = Array.isArray(frontmatter['tags']) ? frontmatter['tags'] : [];
|
|
91
|
+
const metadata = {
|
|
92
|
+
name: skillName,
|
|
93
|
+
version,
|
|
94
|
+
description,
|
|
95
|
+
tags,
|
|
96
|
+
source: 'skillssh',
|
|
97
|
+
repo: ownerRepo,
|
|
98
|
+
importedAt: new Date().toISOString(),
|
|
99
|
+
interface: {
|
|
100
|
+
input: [],
|
|
101
|
+
output: {}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
writeFileSync(join(skillDir, 'metadata.yaml'), yaml.dump(metadata));
|
|
105
|
+
// Create config.yaml
|
|
106
|
+
const config = {
|
|
107
|
+
// Default configuration
|
|
108
|
+
};
|
|
109
|
+
writeFileSync(join(skillDir, 'config.yaml'), yaml.dump(config));
|
|
110
|
+
// Create steps.yaml placeholder
|
|
111
|
+
const steps = {
|
|
112
|
+
steps: [
|
|
113
|
+
{
|
|
114
|
+
type: 'procedural',
|
|
115
|
+
description: 'This skill contains procedural knowledge. See skill.md for details.'
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
};
|
|
119
|
+
writeFileSync(join(skillDir, 'steps.yaml'), yaml.dump(steps));
|
|
120
|
+
}
|
|
121
|
+
function parseFrontmatter(content) {
|
|
122
|
+
const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
|
|
123
|
+
const match = content.match(frontmatterRegex);
|
|
124
|
+
if (match?.[1] && match[2]) {
|
|
125
|
+
try {
|
|
126
|
+
const frontmatter = yaml.load(match[1]);
|
|
127
|
+
return { frontmatter: frontmatter ?? {}, body: match[2].trim() };
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return { frontmatter: {}, body: content };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { frontmatter: {}, body: content };
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=skillssh.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Success } from './act-processing.js';
|
|
2
|
+
export interface SuccessfulPractice {
|
|
3
|
+
description: string;
|
|
4
|
+
context: string;
|
|
5
|
+
category: 'process' | 'tool' | 'approach' | 'pattern';
|
|
6
|
+
applicability: string;
|
|
7
|
+
steps: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface StandardizationRecommendation {
|
|
10
|
+
practice: SuccessfulPractice;
|
|
11
|
+
recommendation: string;
|
|
12
|
+
priority: 'high' | 'medium' | 'low';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extract successful practices from successes
|
|
16
|
+
*/
|
|
17
|
+
export declare function extractSuccessfulPractices(successes: Success[]): SuccessfulPractice[];
|
|
18
|
+
/**
|
|
19
|
+
* Generate standardization recommendations
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateStandardizationRecommendations(practices: SuccessfulPractice[]): StandardizationRecommendation[];
|
|
22
|
+
/**
|
|
23
|
+
* Format standardization document content
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatStandardizationDocument(practices: SuccessfulPractice[], recommendations: StandardizationRecommendation[]): string;
|
|
26
|
+
//# sourceMappingURL=standardization.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract successful practices from successes
|
|
3
|
+
*/
|
|
4
|
+
export function extractSuccessfulPractices(successes) {
|
|
5
|
+
const practices = [];
|
|
6
|
+
for (const success of successes) {
|
|
7
|
+
// Determine category based on goal description
|
|
8
|
+
const goalLower = success.goal.toLowerCase();
|
|
9
|
+
let category = 'process';
|
|
10
|
+
if (goalLower.includes('tool') || goalLower.includes('system') || goalLower.includes('platform')) {
|
|
11
|
+
category = 'tool';
|
|
12
|
+
}
|
|
13
|
+
else if (goalLower.includes('approach') || goalLower.includes('method') || goalLower.includes('strategy')) {
|
|
14
|
+
category = 'approach';
|
|
15
|
+
}
|
|
16
|
+
else if (goalLower.includes('pattern') || goalLower.includes('template') || goalLower.includes('standard')) {
|
|
17
|
+
category = 'pattern';
|
|
18
|
+
}
|
|
19
|
+
practices.push({
|
|
20
|
+
description: success.goal,
|
|
21
|
+
context: `Successfully achieved in current PDCA cycle`,
|
|
22
|
+
category,
|
|
23
|
+
applicability: `Applicable when similar goals or contexts are encountered`,
|
|
24
|
+
steps: [
|
|
25
|
+
`Review the approach used to achieve: ${success.goal}`,
|
|
26
|
+
`Document the key factors that contributed to success`,
|
|
27
|
+
`Identify conditions where this practice can be applied`,
|
|
28
|
+
`Create reusable template or checklist if applicable`
|
|
29
|
+
]
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return practices;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate standardization recommendations
|
|
36
|
+
*/
|
|
37
|
+
export function generateStandardizationRecommendations(practices) {
|
|
38
|
+
const recommendations = [];
|
|
39
|
+
for (const practice of practices) {
|
|
40
|
+
let priority = 'medium';
|
|
41
|
+
// Higher priority for over-achieved goals
|
|
42
|
+
if (practice.description.toLowerCase().includes('exceed') ||
|
|
43
|
+
practice.description.toLowerCase().includes('over-achieved')) {
|
|
44
|
+
priority = 'high';
|
|
45
|
+
}
|
|
46
|
+
// Higher priority for process and pattern practices
|
|
47
|
+
if (practice.category === 'process' || practice.category === 'pattern') {
|
|
48
|
+
priority = 'high';
|
|
49
|
+
}
|
|
50
|
+
recommendations.push({
|
|
51
|
+
practice,
|
|
52
|
+
recommendation: `Standardize the practice: ${practice.description}. This practice was successful and can be reused in similar contexts.`,
|
|
53
|
+
priority
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return recommendations;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Format standardization document content
|
|
60
|
+
*/
|
|
61
|
+
export function formatStandardizationDocument(practices, recommendations) {
|
|
62
|
+
let content = '# Standardization: Successful Practices\n\n';
|
|
63
|
+
content += 'This document identifies successful practices from the current PDCA cycle that should be standardized for future use.\n\n';
|
|
64
|
+
if (practices.length === 0) {
|
|
65
|
+
content += 'No successful practices identified for standardization.\n';
|
|
66
|
+
return content;
|
|
67
|
+
}
|
|
68
|
+
content += '## Successful Practices Identified\n\n';
|
|
69
|
+
content += `Total practices: ${String(practices.length)}\n\n`;
|
|
70
|
+
// Group by category
|
|
71
|
+
const byCategory = {};
|
|
72
|
+
for (const practice of practices) {
|
|
73
|
+
const category = practice.category;
|
|
74
|
+
byCategory[category] ??= [];
|
|
75
|
+
byCategory[category].push(practice);
|
|
76
|
+
}
|
|
77
|
+
for (const [category, categoryPractices] of Object.entries(byCategory)) {
|
|
78
|
+
content += `### ${category.charAt(0).toUpperCase() + category.slice(1)} Practices\n\n`;
|
|
79
|
+
for (const practice of categoryPractices) {
|
|
80
|
+
content += `#### ${practice.description}\n\n`;
|
|
81
|
+
content += `**Context**: ${practice.context}\n\n`;
|
|
82
|
+
content += `**Applicability**: ${practice.applicability}\n\n`;
|
|
83
|
+
content += `**Steps to Implement**:\n`;
|
|
84
|
+
for (const step of practice.steps) {
|
|
85
|
+
content += `- ${step}\n`;
|
|
86
|
+
}
|
|
87
|
+
content += '\n';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
content += '## Standardization Recommendations\n\n';
|
|
91
|
+
for (const rec of recommendations) {
|
|
92
|
+
const priorityEmoji = rec.priority === 'high' ? '🔴' : rec.priority === 'medium' ? '🟡' : '🟢';
|
|
93
|
+
content += `### ${priorityEmoji} ${rec.priority.toUpperCase()} Priority: ${rec.practice.description}\n\n`;
|
|
94
|
+
content += `${rec.recommendation}\n\n`;
|
|
95
|
+
}
|
|
96
|
+
const patternPractices = practices.filter(p => p.category === 'pattern');
|
|
97
|
+
if (patternPractices.length > 0) {
|
|
98
|
+
content += '## Reusable Patterns\n\n';
|
|
99
|
+
content += 'The following patterns can be reused in future PDCA cycles:\n\n';
|
|
100
|
+
for (const practice of patternPractices) {
|
|
101
|
+
content += `- **${practice.description}**: ${practice.applicability}\n`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return content;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=standardization.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Task } from './tasks.js';
|
|
2
|
+
export interface TaskExecutionResult {
|
|
3
|
+
taskIndex: number;
|
|
4
|
+
success: boolean;
|
|
5
|
+
error?: string;
|
|
6
|
+
duration: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TaskChain {
|
|
9
|
+
tasks: Task[];
|
|
10
|
+
dependencyGraph: Map<number, number[]>;
|
|
11
|
+
executionOrder: number[][];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build dependency graph from tasks
|
|
15
|
+
* Returns a map of task index to array of dependency indices
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildDependencyGraph(tasks: Task[]): Map<number, number[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Detect cycles in dependency graph using DFS
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectCycles(graph: Map<number, number[]>): number[] | null;
|
|
22
|
+
/**
|
|
23
|
+
* Topological sort to determine execution order
|
|
24
|
+
* Returns array of arrays, where each inner array contains tasks that can run concurrently
|
|
25
|
+
*/
|
|
26
|
+
export declare function topologicalSort(tasks: Task[], graph: Map<number, number[]>): number[][];
|
|
27
|
+
/**
|
|
28
|
+
* Execute tasks concurrently with dependency management
|
|
29
|
+
* @param tasks Array of tasks to execute
|
|
30
|
+
* @param executeTask Function to execute a single task
|
|
31
|
+
* @param maxConcurrency Maximum number of concurrent executions
|
|
32
|
+
* @returns Array of execution results
|
|
33
|
+
*/
|
|
34
|
+
export declare function executeConcurrently(tasks: Task[], executeTask: (task: Task) => Promise<TaskExecutionResult>, maxConcurrency?: number): Promise<TaskExecutionResult[]>;
|
|
35
|
+
//# sourceMappingURL=task-chain.d.ts.map
|