speccore 8.3.181 → 8.3.188

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.agents/skills/spec-analyze/SKILL.md +2 -169
  2. package/.agents/skills/spec-ask/SKILL.md +2 -177
  3. package/.agents/skills/spec-change/SKILL.md +2 -214
  4. package/.agents/skills/spec-dashboard/SKILL.md +1 -76
  5. package/.agents/skills/spec-deploy/SKILL.md +2 -298
  6. package/.agents/skills/spec-doc2spec/SKILL.md +2 -116
  7. package/.agents/skills/spec-done/SKILL.md +2 -203
  8. package/.agents/skills/spec-execute/SKILL.md +2 -178
  9. package/.agents/skills/spec-help/SKILL.md +1 -75
  10. package/.agents/skills/spec-iteration-create/SKILL.md +2 -123
  11. package/.agents/skills/spec-plan/SKILL.md +2 -117
  12. package/.agents/skills/spec-pr/SKILL.md +2 -203
  13. package/.agents/skills/spec-run/SKILL.md +16 -0
  14. package/.agents/skills/spec-spec2doc/SKILL.md +2 -121
  15. package/.agents/skills/spec-split/SKILL.md +2 -208
  16. package/.agents/skills/spec-task-create/SKILL.md +2 -151
  17. package/.agents/skills/spec-verify/SKILL.md +2 -214
  18. package/.agents/skills/spec-welcome/SKILL.md +1 -67
  19. package/.agents/skills/speccore-router/SKILL.md +14 -2
  20. package/README.en.md +9 -9
  21. package/README.md +2 -1
  22. package/dist/cli.js +24 -25
  23. package/dist/cli.js.map +1 -1
  24. package/dist/commands/about.js +1 -1
  25. package/dist/commands/about.js.map +1 -1
  26. package/dist/commands/analyze.d.ts +1 -0
  27. package/dist/commands/analyze.d.ts.map +1 -1
  28. package/dist/commands/analyze.js +94 -7
  29. package/dist/commands/analyze.js.map +1 -1
  30. package/dist/commands/ask.js +6 -6
  31. package/dist/commands/ask.js.map +1 -1
  32. package/dist/commands/dev.d.ts +2 -0
  33. package/dist/commands/dev.d.ts.map +1 -1
  34. package/dist/commands/dev.js +102 -1
  35. package/dist/commands/dev.js.map +1 -1
  36. package/dist/commands/doctor.js +28 -0
  37. package/dist/commands/doctor.js.map +1 -1
  38. package/dist/commands/execute.js +3 -3
  39. package/dist/commands/execute.js.map +1 -1
  40. package/dist/commands/init.d.ts.map +1 -1
  41. package/dist/commands/init.js +31 -52
  42. package/dist/commands/init.js.map +1 -1
  43. package/dist/commands/iteration/split.d.ts.map +1 -1
  44. package/dist/commands/iteration/split.js +12 -39
  45. package/dist/commands/iteration/split.js.map +1 -1
  46. package/dist/commands/knowledge.d.ts +0 -12
  47. package/dist/commands/knowledge.d.ts.map +1 -1
  48. package/dist/commands/knowledge.js +0 -80
  49. package/dist/commands/knowledge.js.map +1 -1
  50. package/dist/commands/refresh.d.ts.map +1 -1
  51. package/dist/commands/refresh.js +10 -0
  52. package/dist/commands/refresh.js.map +1 -1
  53. package/dist/commands/search.d.ts +1 -0
  54. package/dist/commands/search.d.ts.map +1 -1
  55. package/dist/commands/search.js +38 -0
  56. package/dist/commands/search.js.map +1 -1
  57. package/dist/commands/update.d.ts.map +1 -1
  58. package/dist/commands/update.js +13 -3
  59. package/dist/commands/update.js.map +1 -1
  60. package/dist/core/agent-adapter.d.ts +6 -0
  61. package/dist/core/agent-adapter.d.ts.map +1 -1
  62. package/dist/core/agent-adapter.js +56 -172
  63. package/dist/core/agent-adapter.js.map +1 -1
  64. package/dist/core/agents/defaults/code-generator.md +64 -0
  65. package/dist/core/agents/defaults/code-reviewer.md +5 -0
  66. package/dist/core/agents/defaults/compiler.md +7 -0
  67. package/dist/core/agents/defaults/compliance-checker.md +2 -0
  68. package/dist/core/agents/defaults/dependency-analyst.md +5 -0
  69. package/dist/core/agents/defaults/doc-sync-agent.md +5 -0
  70. package/dist/core/agents/defaults/effort-estimator.md +28 -0
  71. package/dist/core/agents/defaults/global-analyzer.md +66 -0
  72. package/dist/core/agents/defaults/impact-analyst.md +5 -0
  73. package/dist/core/agents/defaults/interaction-designer.md +5 -0
  74. package/dist/core/agents/defaults/performance-expert.md +2 -0
  75. package/dist/core/agents/defaults/product-analyst-backend.md +6 -0
  76. package/dist/core/agents/defaults/product-analyst-frontend.md +6 -0
  77. package/dist/core/agents/defaults/product-analyst.md +5 -0
  78. package/dist/core/agents/defaults/regression-tester.md +5 -0
  79. package/dist/core/agents/defaults/requirement-analyzer.md +72 -0
  80. package/dist/core/agents/defaults/risk-assessor.md +5 -0
  81. package/dist/core/agents/defaults/schedule-planner.md +5 -0
  82. package/dist/core/agents/defaults/security-reviewer-finance.md +6 -0
  83. package/dist/core/agents/defaults/security-reviewer.md +7 -0
  84. package/dist/core/agents/defaults/task-decomposer.md +5 -0
  85. package/dist/core/agents/defaults/test-engineer.md +2 -0
  86. package/dist/core/agents/defaults/test-reviewer.md +5 -0
  87. package/dist/core/agents/engine/agent-loader.d.ts.map +1 -1
  88. package/dist/core/agents/engine/agent-loader.js +76 -6
  89. package/dist/core/agents/engine/agent-loader.js.map +1 -1
  90. package/dist/core/agents/engine/types.d.ts +5 -0
  91. package/dist/core/agents/engine/types.d.ts.map +1 -1
  92. package/dist/core/analyze-engine.d.ts.map +1 -1
  93. package/dist/core/analyze-engine.js +73 -82
  94. package/dist/core/analyze-engine.js.map +1 -1
  95. package/dist/core/ask-engine.d.ts +0 -58
  96. package/dist/core/ask-engine.d.ts.map +1 -1
  97. package/dist/core/ask-engine.js +63 -361
  98. package/dist/core/ask-engine.js.map +1 -1
  99. package/dist/core/business-rules.d.ts +36 -0
  100. package/dist/core/business-rules.d.ts.map +1 -0
  101. package/dist/core/business-rules.js +109 -0
  102. package/dist/core/business-rules.js.map +1 -0
  103. package/dist/core/change-impact-global.d.ts.map +1 -1
  104. package/dist/core/change-impact-global.js +4 -3
  105. package/dist/core/change-impact-global.js.map +1 -1
  106. package/dist/core/code-scanner.d.ts +1 -0
  107. package/dist/core/code-scanner.d.ts.map +1 -1
  108. package/dist/core/code-scanner.js +32 -3
  109. package/dist/core/code-scanner.js.map +1 -1
  110. package/dist/core/content-delivery.d.ts +59 -0
  111. package/dist/core/content-delivery.d.ts.map +1 -0
  112. package/dist/core/content-delivery.js +219 -0
  113. package/dist/core/content-delivery.js.map +1 -0
  114. package/dist/core/global-artifacts.d.ts.map +1 -1
  115. package/dist/core/global-artifacts.js +262 -19
  116. package/dist/core/global-artifacts.js.map +1 -1
  117. package/dist/core/global-retrieval.d.ts +38 -0
  118. package/dist/core/global-retrieval.d.ts.map +1 -0
  119. package/dist/core/global-retrieval.js +100 -0
  120. package/dist/core/global-retrieval.js.map +1 -0
  121. package/dist/core/html-prototype.d.ts +22 -0
  122. package/dist/core/html-prototype.d.ts.map +1 -0
  123. package/dist/core/html-prototype.js +103 -0
  124. package/dist/core/html-prototype.js.map +1 -0
  125. package/dist/core/multi-lang-parser.d.ts +43 -0
  126. package/dist/core/multi-lang-parser.d.ts.map +1 -0
  127. package/dist/core/multi-lang-parser.js +317 -0
  128. package/dist/core/multi-lang-parser.js.map +1 -0
  129. package/dist/core/pipeline-engine.js +16 -16
  130. package/dist/core/pipeline-engine.js.map +1 -1
  131. package/dist/core/platform-inference.d.ts +35 -0
  132. package/dist/core/platform-inference.d.ts.map +1 -0
  133. package/dist/core/platform-inference.js +205 -0
  134. package/dist/core/platform-inference.js.map +1 -0
  135. package/dist/core/prompt-builder.d.ts +1 -1
  136. package/dist/core/prompt-builder.d.ts.map +1 -1
  137. package/dist/core/prompt-builder.js +101 -75
  138. package/dist/core/prompt-builder.js.map +1 -1
  139. package/dist/core/refresh-scheduler.d.ts +50 -0
  140. package/dist/core/refresh-scheduler.d.ts.map +1 -0
  141. package/dist/core/refresh-scheduler.js +139 -0
  142. package/dist/core/refresh-scheduler.js.map +1 -0
  143. package/dist/core/reverse-requirement.d.ts +54 -0
  144. package/dist/core/reverse-requirement.d.ts.map +1 -0
  145. package/dist/core/reverse-requirement.js +277 -0
  146. package/dist/core/reverse-requirement.js.map +1 -0
  147. package/dist/core/schemas/task.schema.d.ts +2 -2
  148. package/dist/core/spec-skeleton.d.ts.map +1 -1
  149. package/dist/core/spec-skeleton.js +123 -0
  150. package/dist/core/spec-skeleton.js.map +1 -1
  151. package/dist/core/unified-config.d.ts +14 -0
  152. package/dist/core/unified-config.d.ts.map +1 -1
  153. package/dist/core/unified-config.js +94 -10
  154. package/dist/core/unified-config.js.map +1 -1
  155. package/dist/core/unified-retrieval.d.ts.map +1 -1
  156. package/dist/core/unified-retrieval.js +34 -8
  157. package/dist/core/unified-retrieval.js.map +1 -1
  158. package/dist/utils/task-utils.d.ts +4 -0
  159. package/dist/utils/task-utils.d.ts.map +1 -1
  160. package/dist/utils/task-utils.js +18 -0
  161. package/dist/utils/task-utils.js.map +1 -1
  162. package/package.json +5 -3
  163. package/vendor/tree-sitter/tree-sitter-go.wasm +0 -0
  164. package/vendor/tree-sitter/tree-sitter-java.wasm +0 -0
  165. package/vendor/tree-sitter/tree-sitter-python.wasm +0 -0
  166. package/vendor/tree-sitter/tree-sitter-rust.wasm +0 -0
  167. package/.agents/agents/README.md +0 -79
  168. package/.agents/agents/spec-analyzer.md +0 -41
  169. package/.agents/agents/spec-architect.md +0 -57
  170. package/.agents/agents/spec-change-detector.md +0 -55
  171. package/.agents/agents/spec-clarifier.md +0 -83
  172. package/.agents/agents/spec-executor.md +0 -41
  173. package/.agents/agents/spec-gatekeeper.md +0 -84
  174. package/.agents/agents/spec-global-analyzer.md +0 -111
  175. package/.agents/agents/spec-knowledge-curator.md +0 -54
  176. package/.agents/agents/spec-reviewer.md +0 -46
  177. package/.agents/agents/spec-security-auditor.md +0 -56
  178. package/.agents/agents/spec-tester.md +0 -120
  179. package/.agents/skills/spec-analyze/references/analysis-report.md +0 -9
  180. package/.agents/skills/spec-execute/references/code-output.md +0 -13
  181. package/.agents/skills/spec-plan/references/plan-template.md +0 -29
  182. package/.agents/skills/spec-task-create/references/requirement-template.md +0 -23
  183. package/dist/commands/bugfix.d.ts +0 -17
  184. package/dist/commands/bugfix.d.ts.map +0 -1
  185. package/dist/commands/bugfix.js +0 -301
  186. package/dist/commands/bugfix.js.map +0 -1
  187. package/dist/commands/help-quick.d.ts +0 -3
  188. package/dist/commands/help-quick.d.ts.map +0 -1
  189. package/dist/commands/help-quick.js +0 -66
  190. package/dist/commands/help-quick.js.map +0 -1
  191. package/dist/commands/index-update.d.ts +0 -8
  192. package/dist/commands/index-update.d.ts.map +0 -1
  193. package/dist/commands/index-update.js +0 -180
  194. package/dist/commands/index-update.js.map +0 -1
  195. package/dist/commands/schedule.d.ts +0 -26
  196. package/dist/commands/schedule.d.ts.map +0 -1
  197. package/dist/commands/schedule.js +0 -182
  198. package/dist/commands/schedule.js.map +0 -1
  199. package/dist/commands/watch.d.ts +0 -11
  200. package/dist/commands/watch.d.ts.map +0 -1
  201. package/dist/commands/watch.js +0 -166
  202. package/dist/commands/watch.js.map +0 -1
  203. package/dist/core/ai-markdown.d.ts +0 -5
  204. package/dist/core/ai-markdown.d.ts.map +0 -1
  205. package/dist/core/ai-markdown.js +0 -29
  206. package/dist/core/ai-markdown.js.map +0 -1
  207. package/dist/core/schedule-engine.d.ts +0 -25
  208. package/dist/core/schedule-engine.d.ts.map +0 -1
  209. package/dist/core/schedule-engine.js +0 -281
  210. package/dist/core/schedule-engine.js.map +0 -1
  211. package/dist/core/schedule-store.d.ts +0 -119
  212. package/dist/core/schedule-store.d.ts.map +0 -1
  213. package/dist/core/schedule-store.js +0 -216
  214. package/dist/core/schedule-store.js.map +0 -1
@@ -1,25 +0,0 @@
1
- /**
2
- * 启动调度守护进程
3
- * 作为独立子进程运行,父进程立即返回
4
- */
5
- export declare function startDaemon(): boolean;
6
- /**
7
- * 停止调度守护进程
8
- */
9
- export declare function stopDaemon(): boolean;
10
- /**
11
- * 守护进程主循环(在 daemon --foreground 子进程中运行)
12
- */
13
- export declare function runDaemonLoop(): Promise<void>;
14
- /**
15
- * 检查守护进程是否在运行
16
- */
17
- export declare function isDaemonRunning(): boolean;
18
- /**
19
- * 检查守护进程状态并显示
20
- */
21
- export declare function daemonStatus(): Promise<{
22
- running: boolean;
23
- pid: number | null;
24
- }>;
25
- //# sourceMappingURL=schedule-engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schedule-engine.d.ts","sourceRoot":"","sources":["../../src/core/schedule-engine.ts"],"names":[],"mappings":"AAgFA;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAuBrC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAgBpC;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAkEnD;AA6CD;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAatF"}
@@ -1,281 +0,0 @@
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.startDaemon = startDaemon;
37
- exports.stopDaemon = stopDaemon;
38
- exports.runDaemonLoop = runDaemonLoop;
39
- exports.isDaemonRunning = isDaemonRunning;
40
- exports.daemonStatus = daemonStatus;
41
- const child_process_1 = require("child_process");
42
- const path_1 = require("path");
43
- const logger_1 = require("../utils/logger");
44
- const schedule_store_1 = require("./schedule-store");
45
- /**
46
- * 调度引擎 — 负责守护进程的启停和任务到时触发
47
- */
48
- /** 检查间隔(毫秒) */
49
- const POLL_INTERVAL = 30000; // 30 秒轮询一次
50
- /** 守护进程锁文件 */
51
- const LOCK_FILE = '.speccore/local/schedule.lock';
52
- /**
53
- * 查找 speccore daemon 进程(跨平台)
54
- * macOS/Linux: pgrep -f
55
- * Windows: tasklist /FI "IMAGENAME eq node.exe" + wmic 查命令行
56
- */
57
- function findDaemonPids() {
58
- const myPid = process.pid;
59
- const pids = [];
60
- // 方法1: 用 schedule.json 记录的 daemonPid(可靠)
61
- try {
62
- const { loadScheduleStore } = require('./schedule-store');
63
- const store = loadScheduleStore();
64
- if (store.daemonRunning && store.daemonPid && store.daemonPid !== myPid) {
65
- try {
66
- process.kill(store.daemonPid, 0); // 0 信号不杀进程,只检测
67
- pids.push(store.daemonPid);
68
- return pids;
69
- }
70
- catch {
71
- store.daemonRunning = false;
72
- store.daemonPid = null;
73
- }
74
- }
75
- }
76
- catch { }
77
- // 方法2: 命令行查找(兜底)
78
- try {
79
- if (process.platform === 'win32') {
80
- const tasklistOut = (0, child_process_1.execSync)('tasklist /FI "IMAGENAME eq node.exe" /NH /FO CSV', {
81
- encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore']
82
- });
83
- const pidsFromTasklist = new Set();
84
- for (const line of tasklistOut.split('\n')) {
85
- const m = line.match(/^"node\.exe","(\d+)"/);
86
- if (m)
87
- pidsFromTasklist.add(parseInt(m[1]));
88
- }
89
- for (const pid of pidsFromTasklist) {
90
- if (pid === myPid)
91
- continue;
92
- try {
93
- const wmicOut = (0, child_process_1.execSync)(`wmic process where "ProcessId=${pid}" get CommandLine /format:csv`, { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
94
- if (wmicOut.includes('schedule daemon') && wmicOut.includes('--foreground')) {
95
- pids.push(pid);
96
- }
97
- }
98
- catch { }
99
- }
100
- }
101
- else {
102
- const result = (0, child_process_1.execSync)(`pgrep -f "schedule daemon.*--foreground"`, { encoding: 'utf-8' });
103
- for (const line of result.trim().split('\n')) {
104
- const pid = parseInt(line);
105
- if (!isNaN(pid) && pid !== myPid)
106
- pids.push(pid);
107
- }
108
- }
109
- }
110
- catch { }
111
- return pids;
112
- }
113
- /**
114
- * 启动调度守护进程
115
- * 作为独立子进程运行,父进程立即返回
116
- */
117
- function startDaemon() {
118
- // 检查是否已在运行
119
- const existing = findDaemonPids();
120
- if (existing.length > 0) {
121
- logger_1.logger.warn(`Schedule daemon is already running (PID: ${existing.join(', ')})`);
122
- return false;
123
- }
124
- // 以 detached 模式启动子进程
125
- const child = (0, child_process_1.spawn)(process.execPath, [(0, path_1.join)(__dirname, '..', '..', 'dist', 'cli.js'), 'schedule', 'daemon', '--foreground'], {
126
- detached: true,
127
- stdio: 'ignore',
128
- cwd: process.cwd(),
129
- });
130
- child.unref();
131
- logger_1.logger.success(`Schedule daemon started (PID: ${child.pid})`);
132
- logger_1.logger.info(`It will check for due tasks every ${POLL_INTERVAL / 1000}s`);
133
- return true;
134
- }
135
- /**
136
- * 停止调度守护进程
137
- */
138
- function stopDaemon() {
139
- const pids = findDaemonPids();
140
- if (pids.length === 0) {
141
- logger_1.logger.warn('No schedule daemon running');
142
- return false;
143
- }
144
- for (const pid of pids) {
145
- try {
146
- process.kill(pid, 'SIGTERM');
147
- logger_1.logger.info(`Stopped daemon process (PID: ${pid})`);
148
- }
149
- catch (e) {
150
- logger_1.logger.warn(`Failed to stop PID ${pid}: ${e.message}`);
151
- }
152
- }
153
- return true;
154
- }
155
- /**
156
- * 守护进程主循环(在 daemon --foreground 子进程中运行)
157
- */
158
- async function runDaemonLoop() {
159
- logger_1.logger.info('Schedule daemon started');
160
- logger_1.logger.info(`Polling every ${POLL_INTERVAL / 1000}s for due tasks...`);
161
- await (0, schedule_store_1.updateDaemonStatus)(true, process.pid);
162
- // 优雅退出
163
- const cleanup = async () => {
164
- logger_1.logger.info('Shutting down schedule daemon...');
165
- await (0, schedule_store_1.updateDaemonStatus)(false, null);
166
- process.exit(0);
167
- };
168
- process.on('SIGTERM', cleanup);
169
- process.on('SIGINT', cleanup);
170
- // 主循环
171
- let idleCheckTimer = null;
172
- let idleCount = 0; // 连续空闲检查次数,>=3 退出
173
- const doIdleCheck = () => {
174
- idleCount++;
175
- if (idleCount >= 3) {
176
- logger_1.logger.info('No pending tasks ×3 (15min) — daemon stopping (idle)');
177
- (0, schedule_store_1.updateDaemonStatus)(false, null);
178
- clearInterval(interval);
179
- process.exit(0);
180
- return;
181
- }
182
- logger_1.logger.info(`No pending tasks (idle check ${idleCount}/3, next in 5min)`);
183
- idleCheckTimer = setTimeout(doIdleCheck, 5 * 60 * 1000); // 5 分钟后再查
184
- };
185
- const check = async () => {
186
- try {
187
- // 有新任务到来 → 取消空闲倒计时,恢复正常轮询
188
- if (idleCheckTimer) {
189
- clearTimeout(idleCheckTimer);
190
- idleCheckTimer = null;
191
- idleCount = 0;
192
- }
193
- const dueTasks = await (0, schedule_store_1.getDueTasks)();
194
- for (const task of dueTasks) {
195
- await executeScheduledTask(task);
196
- }
197
- const { getPendingTasks } = await Promise.resolve().then(() => __importStar(require('./schedule-store')));
198
- const remaining = await getPendingTasks();
199
- if (remaining.length === 0 && !idleCheckTimer) {
200
- // 首次发现无 pending → 启动 5 分钟空闲倒计时
201
- idleCount = 0;
202
- logger_1.logger.info('No pending tasks — will check 3× every 5min before stopping');
203
- doIdleCheck();
204
- }
205
- else if (remaining.length > 0) {
206
- logger_1.logger.info(`Idle: ${remaining.length} pending`);
207
- }
208
- }
209
- catch (err) {
210
- // 保持运行,记录错误
211
- }
212
- };
213
- // 启动时立即检查一次
214
- await check();
215
- // 定时轮询
216
- const interval = setInterval(check, POLL_INTERVAL);
217
- // 不要 unref — daemon 需要事件循环保持存活
218
- }
219
- /**
220
- * 执行单个调度任务
221
- */
222
- async function executeScheduledTask(task) {
223
- logger_1.logger.info(`\n━━━ 到期任务: ${task.name} (${task.id}) ━━━`);
224
- // 直接执行到期任务,不再写触发文件等人来捞
225
- try {
226
- const { spawnSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
227
- const args = ['execute'];
228
- if (task.taskId) {
229
- args.push('-t', task.taskId);
230
- }
231
- if (task.all) {
232
- args.push('--all');
233
- }
234
- if (task.iteration) {
235
- args.push('-I', task.iteration);
236
- }
237
- args.push('--auto', '--force');
238
- logger_1.logger.info(` 🚀 自动执行: speccore ${args.join(' ')}`);
239
- const result = spawnSync('speccore', args, {
240
- cwd: process.cwd(),
241
- stdio: ['ignore', 'pipe', 'pipe'],
242
- timeout: 600000, // 10分钟超时
243
- encoding: 'utf-8',
244
- });
245
- if (result.status === 0) {
246
- await (0, schedule_store_1.updateScheduleTask)(task.id, { status: 'completed', result: '执行成功' });
247
- logger_1.logger.success(` ✅ ${task.name} 执行完成`);
248
- }
249
- else {
250
- const errMsg = (result.stderr || result.stdout || '').slice(-500);
251
- await (0, schedule_store_1.updateScheduleTask)(task.id, { status: 'failed', result: errMsg });
252
- logger_1.logger.error(` ❌ ${task.name} 执行失败 (exit ${result.status})`);
253
- }
254
- }
255
- catch (e) {
256
- await (0, schedule_store_1.updateScheduleTask)(task.id, { status: 'failed', result: e.message });
257
- logger_1.logger.error(` ❌ 执行异常: ${e.message}`);
258
- }
259
- }
260
- /**
261
- * 检查守护进程是否在运行
262
- */
263
- function isDaemonRunning() {
264
- return findDaemonPids().length > 0;
265
- }
266
- /**
267
- * 检查守护进程状态并显示
268
- */
269
- async function daemonStatus() {
270
- const store = await (0, schedule_store_1.loadScheduleStore)();
271
- const actualRunning = isDaemonRunning();
272
- // 自动修复不一致状态
273
- if (store.daemonRunning !== actualRunning) {
274
- await (0, schedule_store_1.updateDaemonStatus)(actualRunning, actualRunning ? store.daemonPid : null);
275
- }
276
- return {
277
- running: actualRunning,
278
- pid: actualRunning ? store.daemonPid : null,
279
- };
280
- }
281
- //# sourceMappingURL=schedule-engine.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schedule-engine.js","sourceRoot":"","sources":["../../src/core/schedule-engine.ts"],"names":[],"mappings":"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"}
@@ -1,119 +0,0 @@
1
- /**
2
- * 调度任务状态
3
- */
4
- export type ScheduleTaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'ready';
5
- /**
6
- * 单个调度任务
7
- */
8
- export interface ScheduleTask {
9
- /** 唯一 ID,自动生成 */
10
- id: string;
11
- /** 任务名称/描述 */
12
- name: string;
13
- /** 目标迭代 */
14
- iteration: string;
15
- /** 指定执行的 Task ID(单个模式),null 表示批量模式 */
16
- taskId: string | null;
17
- /** 是否 --all 批量模式 */
18
- all: boolean;
19
- /** 调度时间,格式: "2026-08-10 21:00:00" */
20
- scheduledAt: string;
21
- /** ISO 8601 格式的调度时间 */
22
- scheduledAtISO: string;
23
- /** 任务状态 */
24
- status: ScheduleTaskStatus;
25
- /** 创建时间 */
26
- createdAt: string;
27
- /** 实际执行时间 */
28
- executedAt: string | null;
29
- /** 执行结果摘要 */
30
- result: string | null;
31
- /** 执行参数 (传递给 execute 命令的额外选项) */
32
- execOptions: {
33
- batchSize?: number;
34
- parallel?: number;
35
- assignee?: string;
36
- type?: string;
37
- priority?: string;
38
- status?: string;
39
- platform?: string;
40
- backend?: boolean;
41
- frontend?: boolean;
42
- };
43
- }
44
- /**
45
- * 调度存储文件
46
- */
47
- export interface ScheduleStore {
48
- /** 版本号 */
49
- version: number;
50
- /** 所有调度任务 */
51
- tasks: ScheduleTask[];
52
- /** 守护进程是否在运行 */
53
- daemonRunning: boolean;
54
- /** 守护进程 PID */
55
- daemonPid: number | null;
56
- /** 最后更新时间 */
57
- updatedAt: string;
58
- }
59
- /**
60
- * 解析时间字符串 "2026-08-10 21:00:00" 为 Date 和 ISO 字符串
61
- */
62
- export declare function parseScheduleTime(timeStr: string): {
63
- date: Date;
64
- iso: string;
65
- };
66
- /**
67
- * 格式化时间为 "YYYY-MM-DD HH:mm:ss"
68
- */
69
- export declare function formatScheduleTime(date: Date): string;
70
- /**
71
- * 加载调度存储
72
- */
73
- export declare function loadScheduleStore(): Promise<ScheduleStore>;
74
- /**
75
- * 保存调度存储
76
- */
77
- export declare function saveScheduleStore(store: ScheduleStore): Promise<void>;
78
- /**
79
- * 创建调度任务
80
- */
81
- export declare function createScheduleTask(params: {
82
- name: string;
83
- iteration: string;
84
- taskId: string | null;
85
- all: boolean;
86
- scheduledAt: string;
87
- execOptions?: ScheduleTask['execOptions'];
88
- }): Promise<ScheduleTask>;
89
- /**
90
- * 获取所有待执行的任务(按调度时间排序)
91
- */
92
- export declare function getPendingTasks(): Promise<ScheduleTask[]>;
93
- /**
94
- * 获取所有任务(按状态筛选)
95
- */
96
- export declare function listScheduleTasks(status?: ScheduleTaskStatus): Promise<ScheduleTask[]>;
97
- /** 获取单个调度任务详情 */
98
- export declare function getScheduleTask(id: string): Promise<ScheduleTask | null>;
99
- /**
100
- * 更新任务状态
101
- */
102
- export declare function updateScheduleTask(taskId: string, updates: Partial<Pick<ScheduleTask, 'status' | 'executedAt' | 'result'>>): Promise<ScheduleTask | null>;
103
- /**
104
- * 取消调度任务
105
- */
106
- export declare function cancelScheduleTask(taskId: string): Promise<ScheduleTask | null>;
107
- /**
108
- * 删除调度任务(物理删除)
109
- */
110
- export declare function deleteScheduleTask(taskId: string): Promise<boolean>;
111
- /**
112
- * 获取所有已到期但未执行的任务
113
- */
114
- export declare function getDueTasks(): Promise<ScheduleTask[]>;
115
- /**
116
- * 更新守护进程状态
117
- */
118
- export declare function updateDaemonStatus(running: boolean, pid: number | null): Promise<void>;
119
- //# sourceMappingURL=schedule-store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schedule-store.d.ts","sourceRoot":"","sources":["../../src/core/schedule-store.ts"],"names":[],"mappings":"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"}
@@ -1,216 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseScheduleTime = parseScheduleTime;
4
- exports.formatScheduleTime = formatScheduleTime;
5
- exports.loadScheduleStore = loadScheduleStore;
6
- exports.saveScheduleStore = saveScheduleStore;
7
- exports.createScheduleTask = createScheduleTask;
8
- exports.getPendingTasks = getPendingTasks;
9
- exports.listScheduleTasks = listScheduleTasks;
10
- exports.getScheduleTask = getScheduleTask;
11
- exports.updateScheduleTask = updateScheduleTask;
12
- exports.cancelScheduleTask = cancelScheduleTask;
13
- exports.deleteScheduleTask = deleteScheduleTask;
14
- exports.getDueTasks = getDueTasks;
15
- exports.updateDaemonStatus = updateDaemonStatus;
16
- const fs_extra_1 = require("fs-extra");
17
- const path_1 = require("path");
18
- const SCHEDULE_PATH = (0, path_1.join)(process.cwd(), '.speccore', 'local', 'schedule.json');
19
- /**
20
- * 生成唯一 ID
21
- */
22
- function generateId() {
23
- const ts = Date.now().toString(36);
24
- const rand = Math.random().toString(36).substring(2, 8);
25
- return `sch-${ts}-${rand}`;
26
- }
27
- /**
28
- * 解析时间字符串 "2026-08-10 21:00:00" 为 Date 和 ISO 字符串
29
- */
30
- function parseScheduleTime(timeStr) {
31
- // 支持 "YYYY-MM-DD HH:mm:ss" 格式
32
- const match = timeStr.match(/^(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})$/);
33
- if (!match) {
34
- throw new Error(`Invalid time format: "${timeStr}". Expected: YYYY-MM-DD HH:mm:ss (e.g., 2026-08-10 21:00:00)`);
35
- }
36
- const [, y, m, d, h, min, s] = match;
37
- // 使用本地时间构造
38
- const date = new Date(parseInt(y), parseInt(m) - 1, parseInt(d), parseInt(h), parseInt(min), parseInt(s));
39
- if (isNaN(date.getTime())) {
40
- throw new Error(`Invalid date/time: "${timeStr}"`);
41
- }
42
- return { date, iso: date.toISOString() };
43
- }
44
- /**
45
- * 格式化时间为 "YYYY-MM-DD HH:mm:ss"
46
- */
47
- function formatScheduleTime(date) {
48
- const y = date.getFullYear();
49
- const m = String(date.getMonth() + 1).padStart(2, '0');
50
- const d = String(date.getDate()).padStart(2, '0');
51
- const h = String(date.getHours()).padStart(2, '0');
52
- const min = String(date.getMinutes()).padStart(2, '0');
53
- const s = String(date.getSeconds()).padStart(2, '0');
54
- return `${y}-${m}-${d} ${h}:${min}:${s}`;
55
- }
56
- /**
57
- * 加载调度存储
58
- */
59
- async function loadScheduleStore() {
60
- if (await (0, fs_extra_1.pathExists)(SCHEDULE_PATH)) {
61
- return await (0, fs_extra_1.readJson)(SCHEDULE_PATH);
62
- }
63
- return {
64
- version: 1,
65
- tasks: [],
66
- daemonRunning: false,
67
- daemonPid: null,
68
- updatedAt: new Date().toISOString(),
69
- };
70
- }
71
- /**
72
- * 保存调度存储
73
- */
74
- async function saveScheduleStore(store) {
75
- await (0, fs_extra_1.ensureDir)((0, path_1.join)(process.cwd(), '.speccore', 'local'));
76
- store.updatedAt = new Date().toISOString();
77
- store.version = (store.version || 0) + 1;
78
- await (0, fs_extra_1.writeJson)(SCHEDULE_PATH, store, { spaces: 2 });
79
- }
80
- /**
81
- * 带版本锁的原子操作,防止并发写入覆盖
82
- */
83
- async function withStoreLock(fn, maxRetries = 3) {
84
- for (let i = 0; i < maxRetries; i++) {
85
- const store = await loadScheduleStore();
86
- const { result, store: newStore } = await fn(store);
87
- const preVersion = store.version;
88
- const currentStore = await loadScheduleStore();
89
- if (currentStore.version !== preVersion) {
90
- // 被其他进程修改了 → 重试
91
- if (i < maxRetries - 1)
92
- continue;
93
- }
94
- await saveScheduleStore(newStore);
95
- return result;
96
- }
97
- throw new Error('Failed to save schedule: max retries exceeded');
98
- }
99
- /**
100
- * 创建调度任务
101
- */
102
- async function createScheduleTask(params) {
103
- const { date, iso } = parseScheduleTime(params.scheduledAt);
104
- const now = new Date();
105
- if (date <= now) {
106
- throw new Error(`Scheduled time must be in the future. Got: ${params.scheduledAt}, current: ${formatScheduleTime(now)}`);
107
- }
108
- return withStoreLock(async (store) => {
109
- const task = {
110
- id: generateId(),
111
- name: params.name,
112
- iteration: params.iteration,
113
- taskId: params.taskId,
114
- all: params.all,
115
- scheduledAt: params.scheduledAt,
116
- scheduledAtISO: iso,
117
- status: 'pending',
118
- createdAt: now.toISOString(),
119
- executedAt: null,
120
- result: null,
121
- execOptions: params.execOptions || {},
122
- };
123
- store.tasks.push(task);
124
- return { result: task, store };
125
- });
126
- }
127
- /**
128
- * 获取所有待执行的任务(按调度时间排序)
129
- */
130
- async function getPendingTasks() {
131
- const store = await loadScheduleStore();
132
- return store.tasks
133
- .filter(t => t.status === 'pending')
134
- .sort((a, b) => new Date(a.scheduledAtISO).getTime() - new Date(b.scheduledAtISO).getTime());
135
- }
136
- /**
137
- * 获取所有任务(按状态筛选)
138
- */
139
- async function listScheduleTasks(status) {
140
- const store = await loadScheduleStore();
141
- if (status) {
142
- return store.tasks.filter(t => t.status === status);
143
- }
144
- return [...store.tasks].sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
145
- }
146
- /** 获取单个调度任务详情 */
147
- async function getScheduleTask(id) {
148
- const store = await loadScheduleStore();
149
- return store.tasks.find(t => t.id.startsWith(id)) || null;
150
- }
151
- /**
152
- * 更新任务状态
153
- */
154
- async function updateScheduleTask(taskId, updates) {
155
- return withStoreLock(async (store) => {
156
- const task = store.tasks.find(t => t.id === taskId);
157
- if (!task)
158
- return { result: null, store };
159
- if (updates.status !== undefined)
160
- task.status = updates.status;
161
- if (updates.executedAt !== undefined)
162
- task.executedAt = updates.executedAt;
163
- if (updates.result !== undefined)
164
- task.result = updates.result;
165
- return { result: task, store };
166
- });
167
- }
168
- /**
169
- * 取消调度任务
170
- */
171
- async function cancelScheduleTask(taskId) {
172
- const store = await loadScheduleStore();
173
- const task = store.tasks.find(t => t.id === taskId);
174
- if (!task)
175
- return null;
176
- if (task.status !== 'pending') {
177
- throw new Error(`Cannot cancel task "${taskId}" — current status is "${task.status}"`);
178
- }
179
- task.status = 'cancelled';
180
- await saveScheduleStore(store);
181
- return task;
182
- }
183
- /**
184
- * 删除调度任务(物理删除)
185
- */
186
- async function deleteScheduleTask(taskId) {
187
- const store = await loadScheduleStore();
188
- const idx = store.tasks.findIndex(t => t.id === taskId);
189
- if (idx === -1)
190
- return false;
191
- store.tasks.splice(idx, 1);
192
- await saveScheduleStore(store);
193
- return true;
194
- }
195
- /**
196
- * 获取所有已到期但未执行的任务
197
- */
198
- async function getDueTasks() {
199
- const store = await loadScheduleStore();
200
- const now = new Date();
201
- return store.tasks.filter(t => {
202
- if (t.status !== 'pending')
203
- return false;
204
- return new Date(t.scheduledAtISO) <= now;
205
- });
206
- }
207
- /**
208
- * 更新守护进程状态
209
- */
210
- async function updateDaemonStatus(running, pid) {
211
- const store = await loadScheduleStore();
212
- store.daemonRunning = running;
213
- store.daemonPid = pid;
214
- await saveScheduleStore(store);
215
- }
216
- //# sourceMappingURL=schedule-store.js.map