@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.
- package/README.md +195 -3
- package/dist/cli.js +70 -10
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +60 -0
- package/dist/commands/pipeline.d.ts +26 -0
- package/dist/commands/pipeline.js +168 -0
- package/dist/commands/schemas.d.ts +4 -0
- package/dist/commands/schemas.js +57 -0
- package/dist/commands/skills.d.ts +1 -1
- package/dist/commands/skills.js +247 -162
- package/dist/commands/validate.d.ts +9 -0
- package/dist/commands/validate.js +179 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +65 -0
- package/dist/tmd-skills +0 -0
- package/dist/types.d.ts +21 -1
- package/dist/utils/github.d.ts +18 -0
- package/dist/utils/github.js +165 -0
- package/dist/utils/paths.d.ts +1 -0
- package/dist/utils/paths.js +4 -0
- package/dist/utils/pipeline-config.d.ts +37 -0
- package/dist/utils/pipeline-config.js +117 -0
- package/dist/utils/pipeline.d.ts +81 -0
- package/dist/utils/pipeline.js +580 -0
- package/dist/utils/skills.d.ts +10 -2
- package/dist/utils/skills.js +152 -150
- package/dist/utils/skillssh.d.ts +1 -1
- package/dist/utils/skillssh.js +39 -27
- package/dist/utils/step-executor.d.ts +58 -0
- package/dist/utils/step-executor.js +374 -0
- package/dist/utils/templates.d.ts +1 -0
- package/dist/utils/templates.js +30 -0
- package/package.json +22 -21
- package/scripts/postinstall.js +11 -8
package/README.md
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://tmdd.dev"><img alt="Website" src="https://img.shields.io/badge/Website-tmdd.dev-blue?style=flat-square" /></a>
|
|
11
11
|
<a href="https://github.com/sdd330/tmd/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/sdd330/tmd/actions/workflows/ci.yml/badge.svg" /></a>
|
|
12
|
-
<a href="
|
|
12
|
+
<a href="https://www.npmjs.com/package/@tmddev/tmd"><img alt="npm version" src="https://img.shields.io/npm/v/@tmddev/tmd?style=flat-square" /></a>
|
|
13
|
+
<a href="https://nodejs.org/"><img alt="node version" src="https://img.shields.io/node/v/@tmddev/tmd?style=flat-square" /></a>
|
|
14
|
+
<a href="./LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square" /></a>
|
|
13
15
|
<a href="https://conventionalcommits.org"><img alt="Conventional Commits" src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square" /></a>
|
|
14
16
|
</p>
|
|
15
17
|
|
|
@@ -34,9 +36,11 @@ At the core of TMD is the principle that tasks should be **pee-break (10 seconds
|
|
|
34
36
|
## Features
|
|
35
37
|
|
|
36
38
|
- **PDCA Cycle Management**: Four-phase commands for Plan, Do, Check, and Act
|
|
39
|
+
- **Pipe Execution**: Automated PDCA cycles without human input for CI/CD and AI agent workflows
|
|
37
40
|
- **Ten sec to Ten min Task!**: Tasks are designed to be pee-break (10 seconds to 10 minutes) sized for quick completion
|
|
38
41
|
- **OpenSpec Integration**: Automatic creation and linking of OpenSpec change proposals
|
|
39
42
|
- **Skills System**: Reusable capabilities for AI agents with cross-agent invocation support
|
|
43
|
+
- **Step Executors**: Built-in executors for bash commands, file operations, and API calls
|
|
40
44
|
- **English Language Standard**: All documents and specifications use English
|
|
41
45
|
- **Markdown-Based**: All documentation stored in Markdown format
|
|
42
46
|
- **CLI Interface**: Simple command-line interface with aliases
|
|
@@ -44,7 +48,7 @@ At the core of TMD is the principle that tasks should be **pee-break (10 seconds
|
|
|
44
48
|
## Installation
|
|
45
49
|
|
|
46
50
|
### Prerequisites
|
|
47
|
-
- **Node.js >= 20.19.0**
|
|
51
|
+
- **Node.js >= 20.19.0** or **Bun >= 1.0** — Check with `node --version` or `bun --version`
|
|
48
52
|
|
|
49
53
|
### Install the CLI globally
|
|
50
54
|
|
|
@@ -72,6 +76,38 @@ pnpm run build
|
|
|
72
76
|
pnpm link --global # Optional: link for local development
|
|
73
77
|
```
|
|
74
78
|
|
|
79
|
+
**Option D: Using Bun**
|
|
80
|
+
```bash
|
|
81
|
+
bun install -g @tmddev/tmd@latest
|
|
82
|
+
# or run without global install:
|
|
83
|
+
bun x @tmddev/tmd --version
|
|
84
|
+
bun run tmd --help # when in a project with @tmddev/tmd as a dependency
|
|
85
|
+
```
|
|
86
|
+
In the TMD repo: `bun install`, `bun run build`, `bun run test`, and `bun ./bin/tmd.js --version` are all supported.
|
|
87
|
+
|
|
88
|
+
### Install from source
|
|
89
|
+
|
|
90
|
+
**Prerequisites:** Node.js >=20.19.0 or Bun >=1.0, pnpm, [Rust](https://rustup.rs/) (for the `tmd-skills` binary), git.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/sdd330/tmd.git
|
|
94
|
+
cd tmd
|
|
95
|
+
pnpm install
|
|
96
|
+
pnpm build # includes the tmd-skills native binary
|
|
97
|
+
pnpm link --global # optional: use `tmd` from this build
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Optional:
|
|
101
|
+
|
|
102
|
+
- **`pnpm build:native`** — Rebuild only the `tmd-skills` Rust binary (faster when only Rust code changed).
|
|
103
|
+
- **`./bin/agent-browser install`** — When using the agent-browser skill, install the agent-browser CLI if this script is provided (e.g. by the agent-browser project; skip if not present).
|
|
104
|
+
|
|
105
|
+
Example: add the `pdf` skill from [anthropics/skills](https://github.com/anthropics/skills) and symlink to all detected agents:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
tmd skills add anthropics/skills --github --skill pdf --all
|
|
109
|
+
```
|
|
110
|
+
|
|
75
111
|
## Quick Start
|
|
76
112
|
|
|
77
113
|
### 1. Create a Plan
|
|
@@ -162,6 +198,18 @@ This principle ensures tasks are:
|
|
|
162
198
|
|
|
163
199
|
## Commands
|
|
164
200
|
|
|
201
|
+
### Setup and Dashboard
|
|
202
|
+
|
|
203
|
+
- `tmd init [path]` - Initialize TMD in your project (creates `tmd/` and `schemas/pdca/` when missing; default path `.`)
|
|
204
|
+
- `tmd view` - Display a dashboard of tasks by phase and status
|
|
205
|
+
- `tmd validate [task-id]` - Validate task documents or PDCA schemas
|
|
206
|
+
- `--schemas [name]` - Validate schemas only (name optional)
|
|
207
|
+
- `--all` - Validate all tasks and schemas
|
|
208
|
+
- `--strict` - Stricter checks (e.g. task size)
|
|
209
|
+
- `--json` - Output as JSON
|
|
210
|
+
- `tmd schemas` - List available workflow schemas
|
|
211
|
+
- `--json` - Output as JSON
|
|
212
|
+
|
|
165
213
|
### PDCA Commands
|
|
166
214
|
|
|
167
215
|
- `tmd plan <description>` / `tmdp` - Create a new plan
|
|
@@ -190,12 +238,28 @@ This principle ensures tasks are:
|
|
|
190
238
|
|
|
191
239
|
- `tmd show <task-id>` - Show task details
|
|
192
240
|
|
|
241
|
+
### Pipe (Automated PDCA)
|
|
242
|
+
|
|
243
|
+
- `tmd pipe init <task-id>` - Initialize pipe configuration
|
|
244
|
+
- `--force` - Overwrite existing configuration
|
|
245
|
+
|
|
246
|
+
- `tmd pipe run <task-id>` - Run full PDCA cycle automatically
|
|
247
|
+
- `--from <phase>` - Start from specific phase (do, check, act)
|
|
248
|
+
- `--dry-run` - Preview execution without making changes
|
|
249
|
+
|
|
250
|
+
- `tmd pipe status <task-id>` - Show pipe execution state
|
|
251
|
+
- `--json` - Output in JSON format
|
|
252
|
+
|
|
193
253
|
### Skills Management
|
|
194
254
|
|
|
195
255
|
- `tmd skills list` - List all available skills
|
|
256
|
+
- `--tag <tag>` - Filter by tag (repeatable, OR semantics)
|
|
196
257
|
- `tmd skills search <query>` - Search skills
|
|
197
258
|
- `tmd skills show <skill-name>` - Show skill details
|
|
198
259
|
- `tmd skills invoke <skill-name> --input <params>` - Invoke a skill
|
|
260
|
+
- `tmd skills create <name>` - Create a skill (optionally `--description <desc>`, `--tags <t1,t2>`)
|
|
261
|
+
- `tmd skills update <name>` - Update metadata (`--description <desc>`, `--tags <t1,t2>`; at least one required)
|
|
262
|
+
- `tmd skills remove <name>` - Remove a skill (`--force` to skip confirmation)
|
|
199
263
|
|
|
200
264
|
## Skills System
|
|
201
265
|
|
|
@@ -244,6 +308,94 @@ Skills can be invoked by any AI agent:
|
|
|
244
308
|
tmd skill invoke generate-readme-multilang --input "template_path=README.md target_languages=[zh,es,fr]"
|
|
245
309
|
```
|
|
246
310
|
|
|
311
|
+
## Pipe Execution
|
|
312
|
+
|
|
313
|
+
Pipe execution enables fully automated PDCA cycles without human intervention - ideal for CI/CD integration and AI agent workflows.
|
|
314
|
+
|
|
315
|
+
### Initialize Pipe
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
tmd pipe init <task-id>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
This creates a `pipeline.yaml` configuration file in the task's plan directory with customizable settings for each phase.
|
|
322
|
+
|
|
323
|
+
### Run Full Pipe
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
tmd pipe run <task-id>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
This automatically executes:
|
|
330
|
+
1. **Do phase**: Executes all tasks, runs skill steps, captures output
|
|
331
|
+
2. **Check phase**: Compares results against goals, analyzes deviations
|
|
332
|
+
3. **Act phase**: Processes results, generates improvements, marks task complete
|
|
333
|
+
|
|
334
|
+
### Pipeline Configuration
|
|
335
|
+
|
|
336
|
+
```yaml
|
|
337
|
+
# pipeline.yaml
|
|
338
|
+
version: "1.0"
|
|
339
|
+
phases:
|
|
340
|
+
do:
|
|
341
|
+
auto: true
|
|
342
|
+
parallel: false
|
|
343
|
+
maxConcurrency: 4
|
|
344
|
+
successCriteria:
|
|
345
|
+
minTasksCompleted: "100%"
|
|
346
|
+
check:
|
|
347
|
+
auto: true
|
|
348
|
+
analyze: true
|
|
349
|
+
recommend: true
|
|
350
|
+
act:
|
|
351
|
+
auto: true
|
|
352
|
+
standardize: true
|
|
353
|
+
carryForward: true
|
|
354
|
+
completeOnSuccess: true
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Step Executors
|
|
358
|
+
|
|
359
|
+
Pipeline supports three step types for automated task execution:
|
|
360
|
+
|
|
361
|
+
- **bash**: Execute shell commands
|
|
362
|
+
```yaml
|
|
363
|
+
- type: bash
|
|
364
|
+
command: "npm run build"
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
- **file**: File operations (read, write, copy, delete)
|
|
368
|
+
```yaml
|
|
369
|
+
- type: file
|
|
370
|
+
operation: write
|
|
371
|
+
path: output.txt
|
|
372
|
+
content: "Hello World"
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
- **api**: HTTP requests
|
|
376
|
+
```yaml
|
|
377
|
+
- type: api
|
|
378
|
+
url: "https://api.example.com/data"
|
|
379
|
+
method: POST
|
|
380
|
+
body: { "key": "value" }
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Dry Run Mode
|
|
384
|
+
|
|
385
|
+
Preview pipe execution without making changes:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
tmd pipe run <task-id> --dry-run
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Resume from Phase
|
|
392
|
+
|
|
393
|
+
Start from a specific phase (useful for recovering from failures):
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
tmd pipe run <task-id> --from check
|
|
397
|
+
```
|
|
398
|
+
|
|
247
399
|
## OpenSpec Integration
|
|
248
400
|
|
|
249
401
|
TMD automatically integrates with OpenSpec projects:
|
|
@@ -328,6 +480,46 @@ tmd plan "Generate README for new project" --use-skill generate-readme-multilang
|
|
|
328
480
|
tmd do <task-id> --skill generate-readme-multilang
|
|
329
481
|
```
|
|
330
482
|
|
|
483
|
+
### Example 3: Automated Pipe
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
# Create a plan with tasks
|
|
487
|
+
tmd plan "Build and deploy application"
|
|
488
|
+
|
|
489
|
+
# Initialize pipe configuration
|
|
490
|
+
tmd pipe init 20260123-build-and-deploy-application
|
|
491
|
+
|
|
492
|
+
# Preview what will happen (dry run)
|
|
493
|
+
tmd pipe run 20260123-build-and-deploy-application --dry-run
|
|
494
|
+
|
|
495
|
+
# Run the full automated PDCA cycle
|
|
496
|
+
tmd pipe run 20260123-build-and-deploy-application
|
|
497
|
+
|
|
498
|
+
# Check pipe status
|
|
499
|
+
tmd pipe status 20260123-build-and-deploy-application
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Output:
|
|
503
|
+
```
|
|
504
|
+
Pipe: 20260123-build-and-deploy-application
|
|
505
|
+
──────────────────────────────────────────────────
|
|
506
|
+
|
|
507
|
+
Phase: DO
|
|
508
|
+
Tasks to execute: 5/5
|
|
509
|
+
Phase do completed
|
|
510
|
+
|
|
511
|
+
Phase: CHECK
|
|
512
|
+
Goals met: 3/3
|
|
513
|
+
Phase check completed
|
|
514
|
+
|
|
515
|
+
Phase: ACT
|
|
516
|
+
Task marked as completed
|
|
517
|
+
Phase act completed
|
|
518
|
+
──────────────────────────────────────────────────
|
|
519
|
+
|
|
520
|
+
Pipe completed successfully
|
|
521
|
+
```
|
|
522
|
+
|
|
331
523
|
## Language Standard
|
|
332
524
|
|
|
333
525
|
All documents and specifications use English. The system:
|
|
@@ -421,4 +613,4 @@ See [MAINTAINERS.md](MAINTAINERS.md) for maintainer information.
|
|
|
421
613
|
|
|
422
614
|
## License
|
|
423
615
|
|
|
424
|
-
|
|
616
|
+
Apache-2.0
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import {
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import { planCommand } from './commands/plan.js';
|
|
@@ -10,20 +10,46 @@ import { actCommand } from './commands/act.js';
|
|
|
10
10
|
import { listCommand } from './commands/list.js';
|
|
11
11
|
import { showCommand } from './commands/show.js';
|
|
12
12
|
import { skillsCommand } from './commands/skills.js';
|
|
13
|
+
import { pipelineInitCommand, pipelineRunCommand, pipelineStatusCommand } from './commands/pipeline.js';
|
|
14
|
+
import { initCommand } from './commands/init.js';
|
|
15
|
+
import { viewCommand } from './commands/view.js';
|
|
16
|
+
import { validateCommand } from './commands/validate.js';
|
|
17
|
+
import { schemasCommand } from './commands/schemas.js';
|
|
13
18
|
const program = new Command();
|
|
14
|
-
//
|
|
15
|
-
// When running from bin/tmd.js -> dist/cli.js, we need to go up from dist/ to project root
|
|
16
|
-
const require = createRequire(import.meta.url);
|
|
19
|
+
// Resolve project root: bin/tmd.js -> dist/cli.js -> dist/ -> project root
|
|
17
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
// dist/cli.js -> dist/ -> project root
|
|
19
21
|
const projectRoot = dirname(dirname(__filename));
|
|
20
22
|
const packageJsonPath = join(projectRoot, 'package.json');
|
|
21
|
-
const pkg =
|
|
23
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
22
24
|
const { version } = pkg;
|
|
23
25
|
program
|
|
24
26
|
.name('tmd')
|
|
25
27
|
.description('Task Markdown Driven - PDCA cycle management framework')
|
|
26
28
|
.version(version);
|
|
29
|
+
// Init
|
|
30
|
+
program
|
|
31
|
+
.command('init')
|
|
32
|
+
.description('Initialize TMD in your project')
|
|
33
|
+
.argument('[path]', 'Target path', '.')
|
|
34
|
+
.action((pathArg) => { initCommand(pathArg); });
|
|
35
|
+
program
|
|
36
|
+
.command('view')
|
|
37
|
+
.description('Display a dashboard of tasks by phase and status')
|
|
38
|
+
.action(viewCommand);
|
|
39
|
+
program
|
|
40
|
+
.command('validate')
|
|
41
|
+
.description('Validate task documents or PDCA schemas')
|
|
42
|
+
.argument('[task-id]', 'Task ID to validate')
|
|
43
|
+
.option('--schemas [name]', 'Validate schemas only (name optional)')
|
|
44
|
+
.option('--all', 'Validate all tasks and schemas')
|
|
45
|
+
.option('--strict', 'Stricter checks (e.g. task size)')
|
|
46
|
+
.option('--json', 'Output as JSON')
|
|
47
|
+
.action((taskId, opts) => { validateCommand(taskId, opts); });
|
|
48
|
+
program
|
|
49
|
+
.command('schemas')
|
|
50
|
+
.description('List available workflow schemas')
|
|
51
|
+
.option('--json', 'Output as JSON')
|
|
52
|
+
.action((opts) => { schemasCommand(opts); });
|
|
27
53
|
// PDCA commands
|
|
28
54
|
program
|
|
29
55
|
.command('plan')
|
|
@@ -83,10 +109,44 @@ program
|
|
|
83
109
|
// Skills commands
|
|
84
110
|
program
|
|
85
111
|
.command('skills')
|
|
86
|
-
.description('Manage skills')
|
|
87
|
-
.argument('[action]', 'Action: list, search, show, invoke')
|
|
88
|
-
.argument('[name]', 'Skill name or
|
|
112
|
+
.description('Manage skills (list, search, show, invoke, add, create, update, remove)')
|
|
113
|
+
.argument('[action]', 'Action: list, search, show, invoke, add, create, update, remove')
|
|
114
|
+
.argument('[name]', 'Skill name, search query, or repository (owner/repo)')
|
|
89
115
|
.option('--input <params>', 'Input parameters for invoke')
|
|
90
|
-
.
|
|
116
|
+
.option('--skill <skill-name>', 'Skill name when adding from repository')
|
|
117
|
+
.option('--description <desc>', 'Description for create/update')
|
|
118
|
+
.option('--tags <t1,t2>', 'Comma-separated tags for create/update')
|
|
119
|
+
.option('--tag <tag>', 'Filter list by tag (repeatable)', (v, prev) => (prev ?? []).concat([v]))
|
|
120
|
+
.option('--force', 'Remove without confirmation, or overwrite existing skill on add')
|
|
121
|
+
.option('--all', 'With remove: also delete agent/IDE links. With create/add/update: also create symlinks under .cursor, .agents, .codex, .opencode, etc. so the skill is available to those IDEs')
|
|
122
|
+
.option('--github', 'Import skill from GitHub repository (not skills.sh)')
|
|
123
|
+
.option('--branch <branch>', 'GitHub branch to fetch from (default: main/master)')
|
|
124
|
+
.option('--path <path>', 'Custom path to skill file in repository')
|
|
125
|
+
.action(function (action, name) {
|
|
126
|
+
void skillsCommand(action, name, this.opts());
|
|
127
|
+
});
|
|
128
|
+
// Pipeline commands
|
|
129
|
+
const pipe = program
|
|
130
|
+
.command('pipe')
|
|
131
|
+
.description('Automated PDCA pipeline execution');
|
|
132
|
+
pipe
|
|
133
|
+
.command('init')
|
|
134
|
+
.description('Initialize pipe configuration for a task')
|
|
135
|
+
.argument('<task-id>', 'Task ID')
|
|
136
|
+
.option('--force', 'Overwrite existing configuration')
|
|
137
|
+
.action(pipelineInitCommand);
|
|
138
|
+
pipe
|
|
139
|
+
.command('run')
|
|
140
|
+
.description('Run the PDCA pipe for a task')
|
|
141
|
+
.argument('<task-id>', 'Task ID')
|
|
142
|
+
.option('--from <phase>', 'Start from specific phase (do, check, act)')
|
|
143
|
+
.option('--dry-run', 'Preview execution without making changes')
|
|
144
|
+
.action(pipelineRunCommand);
|
|
145
|
+
pipe
|
|
146
|
+
.command('status')
|
|
147
|
+
.description('Show pipe status for a task')
|
|
148
|
+
.argument('<task-id>', 'Task ID')
|
|
149
|
+
.option('--json', 'Output in JSON format')
|
|
150
|
+
.action(pipelineStatusCommand);
|
|
91
151
|
program.parse();
|
|
92
152
|
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { ensureDir, getSchemasDir, getTmdDir } from '../utils/paths.js';
|
|
6
|
+
const MINIMAL_PDCA_SCHEMA = `name: pdca
|
|
7
|
+
version: 1
|
|
8
|
+
description: PDCA (Plan-Do-Check-Act) cycle workflow for task management
|
|
9
|
+
artifacts:
|
|
10
|
+
- id: plan
|
|
11
|
+
generates: plan.md
|
|
12
|
+
description: Planning document
|
|
13
|
+
template: plan.md
|
|
14
|
+
requires: []
|
|
15
|
+
- id: do
|
|
16
|
+
generates: execution.md
|
|
17
|
+
description: Execution log
|
|
18
|
+
template: execution.md
|
|
19
|
+
requires: [plan]
|
|
20
|
+
- id: check
|
|
21
|
+
generates: evaluation.md
|
|
22
|
+
description: Evaluation and deviation analysis
|
|
23
|
+
template: evaluation.md
|
|
24
|
+
requires: [do]
|
|
25
|
+
- id: act
|
|
26
|
+
generates: improvement.md
|
|
27
|
+
description: Improvement and standardization
|
|
28
|
+
template: improvement.md
|
|
29
|
+
requires: [check]
|
|
30
|
+
apply:
|
|
31
|
+
requires: [plan]
|
|
32
|
+
tracks: plan.md
|
|
33
|
+
`;
|
|
34
|
+
export function initCommand(pathArg) {
|
|
35
|
+
const targetPath = join(process.cwd(), pathArg ?? '.');
|
|
36
|
+
if (!existsSync(targetPath)) {
|
|
37
|
+
mkdirSync(targetPath, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
const tmdDir = join(targetPath, getTmdDir());
|
|
40
|
+
const schemasPdcaDir = join(targetPath, getSchemasDir(), 'pdca');
|
|
41
|
+
const schemaPath = join(schemasPdcaDir, 'schema.yaml');
|
|
42
|
+
ensureDir(tmdDir);
|
|
43
|
+
ensureDir(schemasPdcaDir);
|
|
44
|
+
if (!existsSync(schemaPath)) {
|
|
45
|
+
// Bun: import.meta.dirname; Node: derive from import.meta.url
|
|
46
|
+
const __dirname = typeof import.meta.dirname === 'string'
|
|
47
|
+
? import.meta.dirname
|
|
48
|
+
: dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const packageRoot = join(__dirname, '..', '..');
|
|
50
|
+
const builtin = join(packageRoot, 'schemas', 'pdca', 'schema.yaml');
|
|
51
|
+
if (existsSync(builtin)) {
|
|
52
|
+
writeFileSync(schemaPath, readFileSync(builtin, 'utf-8'));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
writeFileSync(schemaPath, MINIMAL_PDCA_SCHEMA);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
console.log(chalk.green('TMD initialized'));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline command handlers for automated PDCA execution
|
|
3
|
+
*/
|
|
4
|
+
export interface PipelineInitOptions {
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface PipelineRunOptions {
|
|
8
|
+
from?: string;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface PipelineStatusOptions {
|
|
12
|
+
json?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Initialize pipeline configuration for a task
|
|
16
|
+
*/
|
|
17
|
+
export declare function pipelineInitCommand(taskId: string, options: PipelineInitOptions): void;
|
|
18
|
+
/**
|
|
19
|
+
* Run the pipeline for a task
|
|
20
|
+
*/
|
|
21
|
+
export declare function pipelineRunCommand(taskId: string, options: PipelineRunOptions): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Show pipeline status for a task
|
|
24
|
+
*/
|
|
25
|
+
export declare function pipelineStatusCommand(taskId: string, options: PipelineStatusOptions): void;
|
|
26
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline command handlers for automated PDCA execution
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { getPlanDir, ensureDir } from '../utils/paths.js';
|
|
8
|
+
import { loadPipelineConfig, generatePipelineConfigTemplate, getPipelineConfigPath, DEFAULT_PIPELINE_CONFIG } from '../utils/pipeline-config.js';
|
|
9
|
+
import { PipelineRunner, getPipelineState } from '../utils/pipeline.js';
|
|
10
|
+
import { writeFileSync } from 'fs';
|
|
11
|
+
/**
|
|
12
|
+
* Initialize pipeline configuration for a task
|
|
13
|
+
*/
|
|
14
|
+
export function pipelineInitCommand(taskId, options) {
|
|
15
|
+
const planPath = join(getPlanDir(taskId), 'plan.md');
|
|
16
|
+
if (!existsSync(planPath)) {
|
|
17
|
+
console.error(chalk.red(`Error: Plan not found for task: ${taskId}`));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
const configPath = getPipelineConfigPath(taskId);
|
|
21
|
+
if (existsSync(configPath) && !options.force) {
|
|
22
|
+
console.log(chalk.yellow(`Pipe config already exists: ${configPath}`));
|
|
23
|
+
console.log(chalk.gray('Use --force to overwrite'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const configContent = generatePipelineConfigTemplate();
|
|
27
|
+
ensureDir(getPlanDir(taskId));
|
|
28
|
+
writeFileSync(configPath, configContent);
|
|
29
|
+
console.log(chalk.green(`Created pipeline configuration: ${configPath}`));
|
|
30
|
+
console.log(chalk.gray('\nDefault settings:'));
|
|
31
|
+
console.log(chalk.gray(' - Do phase: auto execution enabled'));
|
|
32
|
+
console.log(chalk.gray(' - Check phase: auto comparison with analysis'));
|
|
33
|
+
console.log(chalk.gray(' - Act phase: auto processing with standardization'));
|
|
34
|
+
console.log(chalk.gray('\nEdit pipeline.yaml to customize behavior.'));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Run the pipeline for a task
|
|
38
|
+
*/
|
|
39
|
+
export async function pipelineRunCommand(taskId, options) {
|
|
40
|
+
const planPath = join(getPlanDir(taskId), 'plan.md');
|
|
41
|
+
if (!existsSync(planPath)) {
|
|
42
|
+
console.error(chalk.red(`Error: Plan not found for task: ${taskId}`));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
// Load config or use defaults
|
|
46
|
+
let config = loadPipelineConfig(taskId);
|
|
47
|
+
if (!config) {
|
|
48
|
+
console.log(chalk.yellow('No pipeline.yaml found, using default configuration'));
|
|
49
|
+
config = DEFAULT_PIPELINE_CONFIG;
|
|
50
|
+
}
|
|
51
|
+
// Validate --from option
|
|
52
|
+
const validPhases = ['do', 'check', 'act'];
|
|
53
|
+
let fromPhase;
|
|
54
|
+
if (options.from) {
|
|
55
|
+
if (!validPhases.includes(options.from)) {
|
|
56
|
+
console.error(chalk.red(`Error: Invalid phase: ${options.from}`));
|
|
57
|
+
console.error(chalk.gray(`Valid phases: ${validPhases.join(', ')}`));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
fromPhase = options.from;
|
|
61
|
+
}
|
|
62
|
+
// Create and run pipeline
|
|
63
|
+
const runner = new PipelineRunner(taskId, config, options.dryRun);
|
|
64
|
+
console.log(chalk.blue(`\nPipe: ${taskId}`));
|
|
65
|
+
if (options.dryRun) {
|
|
66
|
+
console.log(chalk.yellow('Mode: DRY RUN (no changes will be made)'));
|
|
67
|
+
}
|
|
68
|
+
if (fromPhase) {
|
|
69
|
+
console.log(chalk.gray(`Starting from: ${fromPhase}`));
|
|
70
|
+
}
|
|
71
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
72
|
+
const result = await runner.run(fromPhase);
|
|
73
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
74
|
+
if (result.success) {
|
|
75
|
+
console.log(chalk.green('\nPipe completed successfully'));
|
|
76
|
+
displayPipelineSummary(result);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.log(chalk.red(`\nPipe failed: ${result.error ?? ''}`));
|
|
80
|
+
displayPipelineSummary(result);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Show pipeline status for a task
|
|
86
|
+
*/
|
|
87
|
+
export function pipelineStatusCommand(taskId, options) {
|
|
88
|
+
const planPath = join(getPlanDir(taskId), 'plan.md');
|
|
89
|
+
if (!existsSync(planPath)) {
|
|
90
|
+
console.error(chalk.red(`Error: Plan not found for task: ${taskId}`));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
const state = getPipelineState(taskId);
|
|
94
|
+
const config = loadPipelineConfig(taskId);
|
|
95
|
+
if (options.json) {
|
|
96
|
+
console.log(JSON.stringify({
|
|
97
|
+
taskId,
|
|
98
|
+
state,
|
|
99
|
+
hasConfig: !!config
|
|
100
|
+
}, null, 2));
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
console.log(chalk.blue(`\nPipe Status: ${taskId}`));
|
|
104
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
105
|
+
// Config status
|
|
106
|
+
console.log(chalk.gray('\nConfiguration:'));
|
|
107
|
+
if (config) {
|
|
108
|
+
console.log(chalk.green(' pipeline.yaml: found'));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(chalk.yellow(' pipeline.yaml: not found (will use defaults)'));
|
|
112
|
+
}
|
|
113
|
+
// Phase status
|
|
114
|
+
console.log(chalk.gray('\nPhases:'));
|
|
115
|
+
const phases = ['do', 'check', 'act'];
|
|
116
|
+
for (const phase of phases) {
|
|
117
|
+
const completed = state.completedPhases.includes(phase);
|
|
118
|
+
const current = state.currentPhase === phase;
|
|
119
|
+
let status;
|
|
120
|
+
let color;
|
|
121
|
+
if (completed) {
|
|
122
|
+
status = 'completed';
|
|
123
|
+
color = chalk.green;
|
|
124
|
+
}
|
|
125
|
+
else if (current) {
|
|
126
|
+
status = 'in progress';
|
|
127
|
+
color = chalk.yellow;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
status = 'pending';
|
|
131
|
+
color = chalk.gray;
|
|
132
|
+
}
|
|
133
|
+
const indicator = completed ? '✓' : current ? '→' : '○';
|
|
134
|
+
console.log(color(` ${indicator} ${phase.toUpperCase()}: ${status}`));
|
|
135
|
+
}
|
|
136
|
+
// Last run info
|
|
137
|
+
if (state.lastRun) {
|
|
138
|
+
console.log(chalk.gray(`\nLast run: ${state.lastRun.toISOString()}`));
|
|
139
|
+
}
|
|
140
|
+
if (state.lastError) {
|
|
141
|
+
console.log(chalk.red(`\nLast error: ${state.lastError}`));
|
|
142
|
+
}
|
|
143
|
+
console.log('');
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Display pipeline execution summary
|
|
147
|
+
*/
|
|
148
|
+
function displayPipelineSummary(result) {
|
|
149
|
+
if (result.phases.length === 0) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(chalk.gray('\nPhase Summary:'));
|
|
153
|
+
for (const phase of result.phases) {
|
|
154
|
+
const duration = phase.endTime.getTime() - phase.startTime.getTime();
|
|
155
|
+
const status = phase.success ? chalk.green('✓') : chalk.red('✗');
|
|
156
|
+
const durationStr = duration < 1000 ? `${String(duration)}ms` : `${(duration / 1000).toFixed(1)}s`;
|
|
157
|
+
console.log(` ${status} ${phase.phase.toUpperCase()} (${durationStr})`);
|
|
158
|
+
if (phase.details) {
|
|
159
|
+
for (const [key, value] of Object.entries(phase.details)) {
|
|
160
|
+
console.log(chalk.gray(` ${key}: ${String(value)}`));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (phase.error) {
|
|
164
|
+
console.log(chalk.red(` Error: ${phase.error}`));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=pipeline.js.map
|