spec-agent 1.0.4 → 2.0.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 CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  如果你是通过 npm 公网安装并希望从零开始跑通,建议先阅读:
8
8
 
9
- - [`USAGE_FROM_NPM.md`](./USAGE_FROM_NPM.md)
9
+ - `USAGE_FROM_NPM.md`(npm 网页不支持该相对链接,安装后在本地包目录查看)
10
10
 
11
11
  ## 在 Cursor 中使用
12
12
 
@@ -148,6 +148,20 @@ Options:
148
148
  --dry-run 预览交接包生成计划
149
149
  ```
150
150
 
151
+ #### execute - v2 beta 执行状态机
152
+ ```bash
153
+ spec-agent execute --workspace <dir> [options]
154
+
155
+ Options:
156
+ --max-parallel <count> 最大并行运行任务数 (默认: 4)
157
+ --retry <count> 单任务失败后重试次数 (默认: 1)
158
+ --complete <ids> 标记任务完成,如: T001,T002
159
+ --fail <ids> 标记任务失败,如: T003
160
+ --error <message> 配合 --fail 写入失败原因
161
+ --reset 重置 run_state 后重新初始化
162
+ --dry-run 仅预览状态迁移,不写文件
163
+ ```
164
+
151
165
  ### 退出码约定(用于脚本/CI)
152
166
 
153
167
  - `scan`:
@@ -178,7 +192,7 @@ spec-agent clean --workspace <dir> [--all]
178
192
 
179
193
  ### 4. 环境变量配置
180
194
 
181
- | 变量 | 说明 | 默认值 |
195
+ ![1775094639360](image/README/1775094639360.png)| 变量 | 说明 | 默认值 |
182
196
  |------|------|--------|
183
197
  | `OPENAI_API_KEY` | OpenAI API Key | - |
184
198
  | `LLM_API_KEY` | 通用 LLM API Key | - |
package/USAGE_FROM_NPM.md CHANGED
@@ -155,6 +155,19 @@ spec-agent clean --workspace ./output
155
155
  spec-agent handoff --workspace ./output --target cursor --include-summaries
156
156
  ```
157
157
 
158
+ 执行状态机(v2 beta,先做实验):
159
+
160
+ ```bash
161
+ # 第一次执行:初始化 run_state 并调度首批任务
162
+ spec-agent execute --workspace ./output --max-parallel 4
163
+
164
+ # 回填执行结果:将已完成任务标记为 succeeded
165
+ spec-agent execute --workspace ./output --complete T001,T002
166
+
167
+ # 回填失败并触发重试/最终失败
168
+ spec-agent execute --workspace ./output --fail T003 --error "compile failed"
169
+ ```
170
+
158
171
  ---
159
172
 
160
173
  ## 9. `--help` 使用方式
@@ -0,0 +1,15 @@
1
+ import { Command } from 'commander';
2
+ interface ExecuteOptions {
3
+ workspace: string;
4
+ bundle?: string;
5
+ maxParallel: string;
6
+ retry: string;
7
+ complete?: string;
8
+ fail?: string;
9
+ error?: string;
10
+ reset?: boolean;
11
+ dryRun?: boolean;
12
+ }
13
+ export declare function executeCommand(options: ExecuteOptions, command: Command): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/commands/execute.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmDD,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAsF7F"}
@@ -0,0 +1,298 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.executeCommand = executeCommand;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs-extra"));
39
+ const logger_1 = require("../utils/logger");
40
+ const file_1 = require("../utils/file");
41
+ async function executeCommand(options, command) {
42
+ const logger = new logger_1.Logger();
43
+ try {
44
+ const workspacePath = path.resolve(options.workspace);
45
+ const bundlePath = options.bundle
46
+ ? path.resolve(options.bundle)
47
+ : path.join(workspacePath, 'handoff', 'handoff_bundle.json');
48
+ const executionDir = path.join(workspacePath, 'execution');
49
+ const statePath = path.join(executionDir, 'run_state.json');
50
+ const reportPath = path.join(executionDir, 'execution_report.json');
51
+ const inboxDir = path.join(executionDir, 'inbox');
52
+ const handoffTasksDir = path.join(workspacePath, 'handoff', 'tasks');
53
+ const maxParallel = Math.max(1, parseInt(options.maxParallel || '4', 10) || 4);
54
+ const maxRetries = Math.max(0, parseInt(options.retry || '1', 10) || 1);
55
+ if (!(await (0, file_1.fileExists)(bundlePath))) {
56
+ logger.error(`handoff bundle not found: ${bundlePath}`);
57
+ logger.info('Run spec-agent handoff first.');
58
+ process.exit(1);
59
+ }
60
+ const bundle = await (0, file_1.readJson)(bundlePath);
61
+ await (0, file_1.ensureDir)(executionDir);
62
+ await (0, file_1.ensureDir)(inboxDir);
63
+ if (options.reset && await (0, file_1.fileExists)(statePath)) {
64
+ await fs.remove(statePath);
65
+ logger.warn('Existing run_state.json removed due to --reset');
66
+ }
67
+ const state = await loadOrInitState(statePath, bundlePath, workspacePath, maxParallel, maxRetries, bundle, logger);
68
+ applyManualTransitions(state, options, logger);
69
+ applyBlockedStatus(state);
70
+ const scheduled = scheduleRunningTasks(state, maxParallel);
71
+ for (const taskId of scheduled) {
72
+ await createInboxFile(taskId, handoffTasksDir, inboxDir);
73
+ state.history.push({
74
+ at: new Date().toISOString(),
75
+ action: 'scheduled',
76
+ taskId,
77
+ detail: 'Moved to running and generated inbox task file',
78
+ });
79
+ }
80
+ state.maxParallel = maxParallel;
81
+ state.updatedAt = new Date().toISOString();
82
+ if (!options.dryRun) {
83
+ await (0, file_1.writeJson)(statePath, state);
84
+ await (0, file_1.writeJson)(reportPath, buildExecutionReport(state));
85
+ }
86
+ const summary = summarizeState(state);
87
+ logger.info(`Execution workspace: ${workspacePath}`);
88
+ logger.info(`Bundle: ${bundlePath}`);
89
+ logger.info(`State: ${statePath}`);
90
+ logger.info(`Report: ${reportPath}`);
91
+ logger.info(`Status => pending:${summary.pending} running:${summary.running} succeeded:${summary.succeeded} failed:${summary.failed} blocked:${summary.blocked}`);
92
+ if (scheduled.length > 0) {
93
+ logger.success(`Scheduled ${scheduled.length} tasks: ${scheduled.join(', ')}`);
94
+ }
95
+ else {
96
+ logger.info('No new tasks scheduled in this round.');
97
+ }
98
+ if (options.dryRun) {
99
+ logger.warn('Dry run mode - state/report files were not written.');
100
+ }
101
+ logger.json({
102
+ status: 'success',
103
+ scheduled,
104
+ summary,
105
+ statePath,
106
+ reportPath,
107
+ inboxDir,
108
+ });
109
+ }
110
+ catch (error) {
111
+ const logger = new logger_1.Logger();
112
+ logger.error(`Execute failed: ${error instanceof Error ? error.message : String(error)}`);
113
+ process.exit(1);
114
+ }
115
+ }
116
+ async function loadOrInitState(statePath, bundlePath, workspacePath, maxParallel, maxRetries, bundle, logger) {
117
+ if (await (0, file_1.fileExists)(statePath)) {
118
+ const state = await (0, file_1.readJson)(statePath);
119
+ reconcileStateWithBundle(state, bundle, maxRetries, logger);
120
+ return state;
121
+ }
122
+ const now = new Date().toISOString();
123
+ const tasks = {};
124
+ for (const task of bundle.tasks || []) {
125
+ tasks[task.id] = {
126
+ taskId: task.id,
127
+ name: task.name,
128
+ assignedAgent: task.assignedAgent || 'UNKNOWN',
129
+ dependencies: task.dependencies || [],
130
+ status: 'pending',
131
+ attempts: 0,
132
+ maxAttempts: maxRetries + 1,
133
+ updatedAt: now,
134
+ };
135
+ }
136
+ return {
137
+ version: '2.0.0-beta',
138
+ createdAt: now,
139
+ updatedAt: now,
140
+ workspace: workspacePath,
141
+ bundlePath,
142
+ maxParallel,
143
+ tasks,
144
+ history: [{ at: now, action: 'init', detail: `Initialized from ${bundlePath}` }],
145
+ };
146
+ }
147
+ function reconcileStateWithBundle(state, bundle, maxRetries, logger) {
148
+ const now = new Date().toISOString();
149
+ const existingIds = new Set(Object.keys(state.tasks));
150
+ let added = 0;
151
+ for (const task of bundle.tasks || []) {
152
+ if (existingIds.has(task.id)) {
153
+ continue;
154
+ }
155
+ state.tasks[task.id] = {
156
+ taskId: task.id,
157
+ name: task.name,
158
+ assignedAgent: task.assignedAgent || 'UNKNOWN',
159
+ dependencies: task.dependencies || [],
160
+ status: 'pending',
161
+ attempts: 0,
162
+ maxAttempts: maxRetries + 1,
163
+ updatedAt: now,
164
+ };
165
+ added++;
166
+ }
167
+ if (added > 0) {
168
+ logger.warn(`Detected ${added} new tasks from bundle, appended to run state`);
169
+ state.history.push({ at: now, action: 'reconcile', detail: `Added ${added} new tasks from bundle` });
170
+ }
171
+ }
172
+ function parseTaskIds(raw) {
173
+ if (!raw)
174
+ return [];
175
+ return raw
176
+ .split(',')
177
+ .map(item => item.trim())
178
+ .filter(Boolean);
179
+ }
180
+ function applyManualTransitions(state, options, logger) {
181
+ const now = new Date().toISOString();
182
+ const completeIds = parseTaskIds(options.complete);
183
+ const failIds = parseTaskIds(options.fail);
184
+ for (const taskId of completeIds) {
185
+ const task = state.tasks[taskId];
186
+ if (!task) {
187
+ logger.warn(`Complete ignored (task not found): ${taskId}`);
188
+ continue;
189
+ }
190
+ task.status = 'succeeded';
191
+ task.lastError = undefined;
192
+ task.updatedAt = now;
193
+ state.history.push({ at: now, action: 'complete', taskId });
194
+ }
195
+ for (const taskId of failIds) {
196
+ const task = state.tasks[taskId];
197
+ if (!task) {
198
+ logger.warn(`Fail ignored (task not found): ${taskId}`);
199
+ continue;
200
+ }
201
+ task.attempts += 1;
202
+ task.updatedAt = now;
203
+ task.lastError = options.error || 'manual failure';
204
+ if (task.attempts < task.maxAttempts) {
205
+ task.status = 'pending';
206
+ state.history.push({
207
+ at: now,
208
+ action: 'retry',
209
+ taskId,
210
+ detail: `attempt ${task.attempts}/${task.maxAttempts - 1}`,
211
+ });
212
+ }
213
+ else {
214
+ task.status = 'failed';
215
+ state.history.push({
216
+ at: now,
217
+ action: 'failed',
218
+ taskId,
219
+ detail: `attempt ${task.attempts}/${task.maxAttempts - 1}`,
220
+ });
221
+ }
222
+ }
223
+ }
224
+ function applyBlockedStatus(state) {
225
+ const now = new Date().toISOString();
226
+ for (const task of Object.values(state.tasks)) {
227
+ if (task.status !== 'pending')
228
+ continue;
229
+ const hasHardFailedDependency = task.dependencies.some(depId => state.tasks[depId]?.status === 'failed');
230
+ if (hasHardFailedDependency) {
231
+ task.status = 'blocked';
232
+ task.updatedAt = now;
233
+ task.lastError = 'blocked by failed dependency';
234
+ state.history.push({ at: now, action: 'blocked', taskId: task.taskId, detail: task.lastError });
235
+ }
236
+ }
237
+ }
238
+ function scheduleRunningTasks(state, maxParallel) {
239
+ const now = new Date().toISOString();
240
+ const currentRunning = Object.values(state.tasks).filter(task => task.status === 'running').length;
241
+ const availableSlots = Math.max(0, maxParallel - currentRunning);
242
+ if (availableSlots <= 0)
243
+ return [];
244
+ const ready = Object.values(state.tasks).filter(task => {
245
+ if (task.status !== 'pending')
246
+ return false;
247
+ if (task.dependencies.length === 0)
248
+ return true;
249
+ return task.dependencies.every(depId => state.tasks[depId]?.status === 'succeeded');
250
+ });
251
+ ready.sort((a, b) => a.taskId.localeCompare(b.taskId));
252
+ const picked = ready.slice(0, availableSlots);
253
+ for (const task of picked) {
254
+ task.status = 'running';
255
+ task.updatedAt = now;
256
+ }
257
+ return picked.map(task => task.taskId);
258
+ }
259
+ async function createInboxFile(taskId, handoffTasksDir, inboxDir) {
260
+ const source = path.join(handoffTasksDir, `${taskId}.md`);
261
+ const target = path.join(inboxDir, `${taskId}.md`);
262
+ if (await (0, file_1.fileExists)(source)) {
263
+ await fs.copyFile(source, target);
264
+ return;
265
+ }
266
+ await fs.writeFile(target, `# ${taskId}\n\nTask prompt file not found in handoff/tasks.\n`, 'utf-8');
267
+ }
268
+ function summarizeState(state) {
269
+ const summary = {
270
+ pending: 0,
271
+ running: 0,
272
+ succeeded: 0,
273
+ failed: 0,
274
+ blocked: 0,
275
+ };
276
+ for (const task of Object.values(state.tasks)) {
277
+ summary[task.status] += 1;
278
+ }
279
+ return summary;
280
+ }
281
+ function buildExecutionReport(state) {
282
+ const summary = summarizeState(state);
283
+ const done = summary.succeeded + summary.failed + summary.blocked;
284
+ const total = Object.keys(state.tasks).length;
285
+ const completionRate = total === 0 ? 0 : Number(((done / total) * 100).toFixed(2));
286
+ return {
287
+ version: '2.0.0-beta',
288
+ generatedAt: new Date().toISOString(),
289
+ workspace: state.workspace,
290
+ bundlePath: state.bundlePath,
291
+ maxParallel: state.maxParallel,
292
+ totalTasks: total,
293
+ summary,
294
+ completionRate,
295
+ lastEvents: state.history.slice(-30),
296
+ };
297
+ }
298
+ //# sourceMappingURL=execute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.js","sourceRoot":"","sources":["../../src/commands/execute.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ const status_1 = require("./commands/status");
47
47
  const clean_1 = require("./commands/clean");
48
48
  const doctor_1 = require("./commands/doctor");
49
49
  const handoff_1 = require("./commands/handoff");
50
+ const execute_1 = require("./commands/execute");
50
51
  const program = new commander_1.Command();
51
52
  const pkgVersion = (() => {
52
53
  try {
@@ -179,5 +180,18 @@ program
179
180
  .option('--include-summaries', 'Include summary directory as required evidence')
180
181
  .option('--dry-run', 'Preview handoff generation plan')
181
182
  .action(handoff_1.handoffCommand);
183
+ program
184
+ .command('execute')
185
+ .description('Run v2 beta execution state machine from handoff bundle')
186
+ .option('-w, --workspace <dir>', 'Workspace directory', '.')
187
+ .option('-b, --bundle <path>', 'Path to handoff_bundle.json (optional)')
188
+ .option('-p, --max-parallel <count>', 'Max parallel running tasks', '4')
189
+ .option('-r, --retry <count>', 'Retry times per task after failure', '1')
190
+ .option('--complete <ids>', 'Mark task IDs as completed, comma-separated')
191
+ .option('--fail <ids>', 'Mark task IDs as failed, comma-separated')
192
+ .option('--error <message>', 'Failure reason when using --fail')
193
+ .option('--reset', 'Reset existing run state and reinitialize from bundle')
194
+ .option('--dry-run', 'Preview execution transitions without writing state')
195
+ .action(execute_1.executeCommand);
182
196
  program.parse();
183
197
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-agent",
3
- "version": "1.0.4",
3
+ "version": "2.0.0",
4
4
  "description": "CLI for requirement decomposition and agent-ready planning",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -50,6 +50,7 @@ spec-agent/
50
50
  │ │ ├── dispatch.ts # Phase 5: 任务分配
51
51
  │ │ ├── learn.ts # 学习积累模式
52
52
  │ │ ├── handoff.ts # 生成多 Agent 执行交接包(v2 beta)
53
+ │ │ ├── execute.ts # v2 beta 执行状态机(run_state/report)
53
54
  │ │ ├── pipeline.ts # 一键执行全流程
54
55
  │ │ ├── status.ts # 查看工作状态
55
56
  │ │ └── clean.ts # 清理中间文件
@@ -449,6 +450,28 @@ spec-agent handoff --workspace ./workspace --target cursor --include-summaries
449
450
 
450
451
  ---
451
452
 
453
+ ### 3.13 execute — 执行状态机(v2 beta)
454
+
455
+ ```bash
456
+ # 初始化并调度首批任务
457
+ spec-agent execute --workspace ./workspace --max-parallel 4
458
+
459
+ # 回填成功
460
+ spec-agent execute --workspace ./workspace --complete T001,T002
461
+
462
+ # 回填失败(按 retry 策略进入 pending 或 failed)
463
+ spec-agent execute --workspace ./workspace --fail T003 --error "build failed"
464
+ ```
465
+
466
+ **功能**:
467
+
468
+ - 从 `handoff_bundle.json` 初始化 `execution/run_state.json`
469
+ - 按依赖与并行度调度任务进入 `running`
470
+ - 支持手动回填任务 `succeeded/failed`
471
+ - 产出 `execution/execution_report.json` 供实验评估
472
+
473
+ ---
474
+
452
475
  ## 四、核心类型定义
453
476
 
454
477
  ```typescript
@@ -0,0 +1,358 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs-extra';
3
+ import { Command } from 'commander';
4
+ import { Logger } from '../utils/logger';
5
+ import { ensureDir, fileExists, readJson, writeJson } from '../utils/file';
6
+
7
+ interface ExecuteOptions {
8
+ workspace: string;
9
+ bundle?: string;
10
+ maxParallel: string;
11
+ retry: string;
12
+ complete?: string;
13
+ fail?: string;
14
+ error?: string;
15
+ reset?: boolean;
16
+ dryRun?: boolean;
17
+ }
18
+
19
+ type ExecutionStatus =
20
+ | 'pending'
21
+ | 'running'
22
+ | 'succeeded'
23
+ | 'failed'
24
+ | 'blocked';
25
+
26
+ interface BundleTask {
27
+ id: string;
28
+ name: string;
29
+ dependencies?: string[];
30
+ assignedAgent?: string;
31
+ }
32
+
33
+ interface HandoffBundle {
34
+ version: string;
35
+ createdAt: string;
36
+ workspace: string;
37
+ tasks: BundleTask[];
38
+ }
39
+
40
+ interface RunTaskState {
41
+ taskId: string;
42
+ name: string;
43
+ assignedAgent: string;
44
+ dependencies: string[];
45
+ status: ExecutionStatus;
46
+ attempts: number;
47
+ maxAttempts: number;
48
+ lastError?: string;
49
+ updatedAt: string;
50
+ }
51
+
52
+ interface RunState {
53
+ version: string;
54
+ createdAt: string;
55
+ updatedAt: string;
56
+ workspace: string;
57
+ bundlePath: string;
58
+ maxParallel: number;
59
+ tasks: Record<string, RunTaskState>;
60
+ history: Array<{
61
+ at: string;
62
+ action: string;
63
+ taskId?: string;
64
+ detail?: string;
65
+ }>;
66
+ }
67
+
68
+ export async function executeCommand(options: ExecuteOptions, command: Command): Promise<void> {
69
+ const logger = new Logger();
70
+
71
+ try {
72
+ const workspacePath = path.resolve(options.workspace);
73
+ const bundlePath = options.bundle
74
+ ? path.resolve(options.bundle)
75
+ : path.join(workspacePath, 'handoff', 'handoff_bundle.json');
76
+ const executionDir = path.join(workspacePath, 'execution');
77
+ const statePath = path.join(executionDir, 'run_state.json');
78
+ const reportPath = path.join(executionDir, 'execution_report.json');
79
+ const inboxDir = path.join(executionDir, 'inbox');
80
+ const handoffTasksDir = path.join(workspacePath, 'handoff', 'tasks');
81
+ const maxParallel = Math.max(1, parseInt(options.maxParallel || '4', 10) || 4);
82
+ const maxRetries = Math.max(0, parseInt(options.retry || '1', 10) || 1);
83
+
84
+ if (!(await fileExists(bundlePath))) {
85
+ logger.error(`handoff bundle not found: ${bundlePath}`);
86
+ logger.info('Run spec-agent handoff first.');
87
+ process.exit(1);
88
+ }
89
+
90
+ const bundle = await readJson<HandoffBundle>(bundlePath);
91
+ await ensureDir(executionDir);
92
+ await ensureDir(inboxDir);
93
+
94
+ if (options.reset && await fileExists(statePath)) {
95
+ await fs.remove(statePath);
96
+ logger.warn('Existing run_state.json removed due to --reset');
97
+ }
98
+
99
+ const state = await loadOrInitState(statePath, bundlePath, workspacePath, maxParallel, maxRetries, bundle, logger);
100
+
101
+ applyManualTransitions(state, options, logger);
102
+ applyBlockedStatus(state);
103
+
104
+ const scheduled = scheduleRunningTasks(state, maxParallel);
105
+ for (const taskId of scheduled) {
106
+ await createInboxFile(taskId, handoffTasksDir, inboxDir);
107
+ state.history.push({
108
+ at: new Date().toISOString(),
109
+ action: 'scheduled',
110
+ taskId,
111
+ detail: 'Moved to running and generated inbox task file',
112
+ });
113
+ }
114
+
115
+ state.maxParallel = maxParallel;
116
+ state.updatedAt = new Date().toISOString();
117
+
118
+ if (!options.dryRun) {
119
+ await writeJson(statePath, state);
120
+ await writeJson(reportPath, buildExecutionReport(state));
121
+ }
122
+
123
+ const summary = summarizeState(state);
124
+ logger.info(`Execution workspace: ${workspacePath}`);
125
+ logger.info(`Bundle: ${bundlePath}`);
126
+ logger.info(`State: ${statePath}`);
127
+ logger.info(`Report: ${reportPath}`);
128
+ logger.info(
129
+ `Status => pending:${summary.pending} running:${summary.running} succeeded:${summary.succeeded} failed:${summary.failed} blocked:${summary.blocked}`
130
+ );
131
+ if (scheduled.length > 0) {
132
+ logger.success(`Scheduled ${scheduled.length} tasks: ${scheduled.join(', ')}`);
133
+ } else {
134
+ logger.info('No new tasks scheduled in this round.');
135
+ }
136
+
137
+ if (options.dryRun) {
138
+ logger.warn('Dry run mode - state/report files were not written.');
139
+ }
140
+
141
+ logger.json({
142
+ status: 'success',
143
+ scheduled,
144
+ summary,
145
+ statePath,
146
+ reportPath,
147
+ inboxDir,
148
+ });
149
+ } catch (error) {
150
+ const logger = new Logger();
151
+ logger.error(`Execute failed: ${error instanceof Error ? error.message : String(error)}`);
152
+ process.exit(1);
153
+ }
154
+ }
155
+
156
+ async function loadOrInitState(
157
+ statePath: string,
158
+ bundlePath: string,
159
+ workspacePath: string,
160
+ maxParallel: number,
161
+ maxRetries: number,
162
+ bundle: HandoffBundle,
163
+ logger: Logger
164
+ ): Promise<RunState> {
165
+ if (await fileExists(statePath)) {
166
+ const state = await readJson<RunState>(statePath);
167
+ reconcileStateWithBundle(state, bundle, maxRetries, logger);
168
+ return state;
169
+ }
170
+
171
+ const now = new Date().toISOString();
172
+ const tasks: Record<string, RunTaskState> = {};
173
+ for (const task of bundle.tasks || []) {
174
+ tasks[task.id] = {
175
+ taskId: task.id,
176
+ name: task.name,
177
+ assignedAgent: task.assignedAgent || 'UNKNOWN',
178
+ dependencies: task.dependencies || [],
179
+ status: 'pending',
180
+ attempts: 0,
181
+ maxAttempts: maxRetries + 1,
182
+ updatedAt: now,
183
+ };
184
+ }
185
+
186
+ return {
187
+ version: '2.0.0-beta',
188
+ createdAt: now,
189
+ updatedAt: now,
190
+ workspace: workspacePath,
191
+ bundlePath,
192
+ maxParallel,
193
+ tasks,
194
+ history: [{ at: now, action: 'init', detail: `Initialized from ${bundlePath}` }],
195
+ };
196
+ }
197
+
198
+ function reconcileStateWithBundle(
199
+ state: RunState,
200
+ bundle: HandoffBundle,
201
+ maxRetries: number,
202
+ logger: Logger
203
+ ): void {
204
+ const now = new Date().toISOString();
205
+ const existingIds = new Set(Object.keys(state.tasks));
206
+ let added = 0;
207
+ for (const task of bundle.tasks || []) {
208
+ if (existingIds.has(task.id)) {
209
+ continue;
210
+ }
211
+ state.tasks[task.id] = {
212
+ taskId: task.id,
213
+ name: task.name,
214
+ assignedAgent: task.assignedAgent || 'UNKNOWN',
215
+ dependencies: task.dependencies || [],
216
+ status: 'pending',
217
+ attempts: 0,
218
+ maxAttempts: maxRetries + 1,
219
+ updatedAt: now,
220
+ };
221
+ added++;
222
+ }
223
+ if (added > 0) {
224
+ logger.warn(`Detected ${added} new tasks from bundle, appended to run state`);
225
+ state.history.push({ at: now, action: 'reconcile', detail: `Added ${added} new tasks from bundle` });
226
+ }
227
+ }
228
+
229
+ function parseTaskIds(raw?: string): string[] {
230
+ if (!raw) return [];
231
+ return raw
232
+ .split(',')
233
+ .map(item => item.trim())
234
+ .filter(Boolean);
235
+ }
236
+
237
+ function applyManualTransitions(state: RunState, options: ExecuteOptions, logger: Logger): void {
238
+ const now = new Date().toISOString();
239
+ const completeIds = parseTaskIds(options.complete);
240
+ const failIds = parseTaskIds(options.fail);
241
+
242
+ for (const taskId of completeIds) {
243
+ const task = state.tasks[taskId];
244
+ if (!task) {
245
+ logger.warn(`Complete ignored (task not found): ${taskId}`);
246
+ continue;
247
+ }
248
+ task.status = 'succeeded';
249
+ task.lastError = undefined;
250
+ task.updatedAt = now;
251
+ state.history.push({ at: now, action: 'complete', taskId });
252
+ }
253
+
254
+ for (const taskId of failIds) {
255
+ const task = state.tasks[taskId];
256
+ if (!task) {
257
+ logger.warn(`Fail ignored (task not found): ${taskId}`);
258
+ continue;
259
+ }
260
+ task.attempts += 1;
261
+ task.updatedAt = now;
262
+ task.lastError = options.error || 'manual failure';
263
+ if (task.attempts < task.maxAttempts) {
264
+ task.status = 'pending';
265
+ state.history.push({
266
+ at: now,
267
+ action: 'retry',
268
+ taskId,
269
+ detail: `attempt ${task.attempts}/${task.maxAttempts - 1}`,
270
+ });
271
+ } else {
272
+ task.status = 'failed';
273
+ state.history.push({
274
+ at: now,
275
+ action: 'failed',
276
+ taskId,
277
+ detail: `attempt ${task.attempts}/${task.maxAttempts - 1}`,
278
+ });
279
+ }
280
+ }
281
+ }
282
+
283
+ function applyBlockedStatus(state: RunState): void {
284
+ const now = new Date().toISOString();
285
+ for (const task of Object.values(state.tasks)) {
286
+ if (task.status !== 'pending') continue;
287
+ const hasHardFailedDependency = task.dependencies.some(depId => state.tasks[depId]?.status === 'failed');
288
+ if (hasHardFailedDependency) {
289
+ task.status = 'blocked';
290
+ task.updatedAt = now;
291
+ task.lastError = 'blocked by failed dependency';
292
+ state.history.push({ at: now, action: 'blocked', taskId: task.taskId, detail: task.lastError });
293
+ }
294
+ }
295
+ }
296
+
297
+ function scheduleRunningTasks(state: RunState, maxParallel: number): string[] {
298
+ const now = new Date().toISOString();
299
+ const currentRunning = Object.values(state.tasks).filter(task => task.status === 'running').length;
300
+ const availableSlots = Math.max(0, maxParallel - currentRunning);
301
+ if (availableSlots <= 0) return [];
302
+
303
+ const ready = Object.values(state.tasks).filter(task => {
304
+ if (task.status !== 'pending') return false;
305
+ if (task.dependencies.length === 0) return true;
306
+ return task.dependencies.every(depId => state.tasks[depId]?.status === 'succeeded');
307
+ });
308
+
309
+ ready.sort((a, b) => a.taskId.localeCompare(b.taskId));
310
+ const picked = ready.slice(0, availableSlots);
311
+ for (const task of picked) {
312
+ task.status = 'running';
313
+ task.updatedAt = now;
314
+ }
315
+ return picked.map(task => task.taskId);
316
+ }
317
+
318
+ async function createInboxFile(taskId: string, handoffTasksDir: string, inboxDir: string): Promise<void> {
319
+ const source = path.join(handoffTasksDir, `${taskId}.md`);
320
+ const target = path.join(inboxDir, `${taskId}.md`);
321
+ if (await fileExists(source)) {
322
+ await fs.copyFile(source, target);
323
+ return;
324
+ }
325
+ await fs.writeFile(target, `# ${taskId}\n\nTask prompt file not found in handoff/tasks.\n`, 'utf-8');
326
+ }
327
+
328
+ function summarizeState(state: RunState): Record<ExecutionStatus, number> {
329
+ const summary: Record<ExecutionStatus, number> = {
330
+ pending: 0,
331
+ running: 0,
332
+ succeeded: 0,
333
+ failed: 0,
334
+ blocked: 0,
335
+ };
336
+ for (const task of Object.values(state.tasks)) {
337
+ summary[task.status] += 1;
338
+ }
339
+ return summary;
340
+ }
341
+
342
+ function buildExecutionReport(state: RunState): Record<string, unknown> {
343
+ const summary = summarizeState(state);
344
+ const done = summary.succeeded + summary.failed + summary.blocked;
345
+ const total = Object.keys(state.tasks).length;
346
+ const completionRate = total === 0 ? 0 : Number(((done / total) * 100).toFixed(2));
347
+ return {
348
+ version: '2.0.0-beta',
349
+ generatedAt: new Date().toISOString(),
350
+ workspace: state.workspace,
351
+ bundlePath: state.bundlePath,
352
+ maxParallel: state.maxParallel,
353
+ totalTasks: total,
354
+ summary,
355
+ completionRate,
356
+ lastEvents: state.history.slice(-30),
357
+ };
358
+ }
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ import { statusCommand } from './commands/status';
13
13
  import { cleanCommand } from './commands/clean';
14
14
  import { doctorCommand } from './commands/doctor';
15
15
  import { handoffCommand } from './commands/handoff';
16
+ import { executeCommand } from './commands/execute';
16
17
 
17
18
  const program = new Command();
18
19
  const pkgVersion = (() => {
@@ -158,4 +159,18 @@ program
158
159
  .option('--dry-run', 'Preview handoff generation plan')
159
160
  .action(handoffCommand);
160
161
 
162
+ program
163
+ .command('execute')
164
+ .description('Run v2 beta execution state machine from handoff bundle')
165
+ .option('-w, --workspace <dir>', 'Workspace directory', '.')
166
+ .option('-b, --bundle <path>', 'Path to handoff_bundle.json (optional)')
167
+ .option('-p, --max-parallel <count>', 'Max parallel running tasks', '4')
168
+ .option('-r, --retry <count>', 'Retry times per task after failure', '1')
169
+ .option('--complete <ids>', 'Mark task IDs as completed, comma-separated')
170
+ .option('--fail <ids>', 'Mark task IDs as failed, comma-separated')
171
+ .option('--error <message>', 'Failure reason when using --fail')
172
+ .option('--reset', 'Reset existing run state and reinitialize from bundle')
173
+ .option('--dry-run', 'Preview execution transitions without writing state')
174
+ .action(executeCommand);
175
+
161
176
  program.parse();