sillyspec 3.12.1 → 3.12.3

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.
@@ -527,7 +527,7 @@ PASS / PASS WITH NOTES / FAIL
527
527
 
528
528
  **临时文件:** `_env-detect.md`(环境探测中间产物,扫描完成后删除)
529
529
 
530
- **断点续扫:** "断点续扫检测"步骤检查已有文档,只生成缺失的
530
+ **断点续扫:** "检查已有扫描文档和子项目列表"步骤检查已有文档,**必须停下来问用户**选择「全部重新扫描」或「只补缺失文档」,不能自行决定跳过。
531
531
 
532
532
  **生命周期:** scan 阶段生成 → 被后续所有阶段(brainstorm/propose/plan/execute/verify)作为上下文读取
533
533
 
@@ -578,7 +578,9 @@ modules:
578
578
 
579
579
  ### `<module>.md` — 模块当前状态描述
580
580
 
581
- **创建时机:** archive 阶段 `sync-module-docs` 步骤(首次受影响时创建,后续更新)
581
+ **创建时机:**
582
+ - scan 阶段"生成模块核心文档"步骤(可选,首次全量生成,需用户确认)
583
+ - archive 阶段 `sync-module-docs` 步骤(首次受影响时创建,后续更新)
582
584
 
583
585
  **大体结构:**
584
586
  ```markdown
@@ -627,7 +629,8 @@ modules:
627
629
  - 更新头部元数据:`> 最后更新:YYYY-MM-DD` 和 `> 最近变更:<change-name>`
628
630
 
629
631
  **更新时机:**
630
- - archive 阶段 `sync-module-docs` 步骤(通过 module-impact.md 驱动)
632
+ - scan 阶段"生成模块核心文档"步骤(首次全量生成,需用户确认)
633
+ - archive 阶段 `sync-module-docs` 步骤(通过 module-impact.md 驱动增量更新)
631
634
  - quick 阶段"暂存和更新记录"步骤(直接匹配 git diff 文件到模块,同步更新)
632
635
 
633
636
  **消费方:** brainstorm/propose/plan/execute 阶段"加载上下文"时读取,作为开发参考
@@ -1034,6 +1037,7 @@ graph LR
1034
1037
  | `AGENTS.md` 等 | 选了 codex/gemini/opencode 工具 | init | AI 工具读取 |
1035
1038
  | `projects/*.yaml` | init 自动创建 | init | 子项目上下文加载 |
1036
1039
  | `modules/_module-map.yaml` | scan 可选步骤 | scan | archive/plan/execute |
1040
+ | `modules/<module>.md` | scan 可选步骤(全量生成)+ archive sync-module-docs | scan/archive | propose/plan/execute/verify/quick |
1037
1041
  | `verify-result.md` | verify 阶段输出 | verify | 验证报告存档 |
1038
1042
 
1039
1043
 
@@ -1047,7 +1051,7 @@ sillyspec init
1047
1051
  ├─→ .sillyspec/knowledge/
1048
1052
  └─→ .gitignore (追加 .sillyspec/.runtime/)
1049
1053
 
1050
- scan 阶段
1054
+ scan 阶段(12 步,完成后重置)
1051
1055
 
1052
1056
  ├─→ docs/<name>/scan/ARCHITECTURE.md
1053
1057
  ├─→ docs/<name>/scan/CONVENTIONS.md
@@ -1057,6 +1061,7 @@ scan 阶段
1057
1061
  ├─→ docs/<name>/scan/CONCERNS.md
1058
1062
  ├─→ docs/<name>/scan/PROJECT.md
1059
1063
  ├─→ docs/<name>/modules/_module-map.yaml (可选)
1064
+ ├─→ docs/<name>/modules/<module>.md (可选,需用户确认)
1060
1065
  └─→ .sillyspec/local.yaml
1061
1066
 
1062
1067
  brainstorm 阶段
@@ -1093,13 +1098,15 @@ verify 阶段
1093
1098
 
1094
1099
  └─→ changes/<name>/verify-result.md
1095
1100
 
1096
- quick 阶段(辅助阶段,不走完整流程)
1101
+ quick 阶段(辅助阶段,不走完整流程,完成后重置)
1097
1102
 
1098
1103
  ├─→ .sillyspec/quicklog/QUICKLOG-<user>.md (无 --change 时)
1099
1104
  ├─→ .sillyspec/.runtime/worktrees/<name>/meta.json
1100
1105
  ├─→ .sillyspec/.runtime/gate-status.json
1101
1106
  └─→ docs/<name>/modules/<module>.md (直接同步,不经过 module-impact.md)
1102
1107
 
1108
+ > quick 阶段"理解任务"步骤会加载模块文档作为上下文参考。
1109
+
1103
1110
  archive 阶段
1104
1111
 
1105
1112
  ├─→ changes/<name>/module-impact.md
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.12.1",
3
+ "version": "3.12.3",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
@@ -5,7 +5,7 @@
5
5
  * 纯判断模块,不做实际的 hook 注入。
6
6
  *
7
7
  * P0 优化:
8
- * - 阶段检测 fallback:gate-status.json → progress.json currentStage
8
+ * - 阶段检测 fallback:gate-status.json → sillyspec.db currentStage
9
9
  * - 拦截提示针对每个阶段给出具体修复建议
10
10
  */
11
11
 
@@ -100,41 +100,27 @@ function readGateStatus(cwd) {
100
100
  }
101
101
 
102
102
  /**
103
- * 从 progress.json fallback 读取 currentStage
104
- * 优先级:gate-status.json > 全局 progress.json > 变更级 progress.json
103
+ * 从 sillyspec.db 读取 currentStage
104
+ * 优先级:gate-status.json > sillyspec.db
105
105
  * @param {string} cwd
106
106
  * @returns {string|null} 阶段名,null 表示无法确定
107
107
  */
108
108
  function readCurrentStage(cwd) {
109
- // 1. gate-status.json(权威来源)
109
+ // 1. gate-status.json(高速缓存,权威来源)
110
110
  const gateStatus = readGateStatus(cwd)
111
111
  if (gateStatus && gateStatus.stage) return gateStatus.stage
112
112
 
113
- // 2. 全局 progress.json
114
- const globalProgress = path.join(cwd, '.sillyspec', '.runtime', 'progress.json')
115
- if (existsSync(globalProgress)) {
116
- try {
117
- const data = JSON.parse(readFileSync(globalProgress, 'utf8'))
118
- if (data.currentStage) return data.currentStage
119
- } catch { /* skip */ }
120
- }
121
-
122
- // 3. 变更级 progress.json(从 global.json 找到活跃变更)
123
- const globalFile = path.join(cwd, '.sillyspec', '.runtime', 'global.json')
124
- if (existsSync(globalFile)) {
125
- try {
126
- const global = JSON.parse(readFileSync(globalFile, 'utf8'))
127
- const changesDir = path.join(cwd, '.sillyspec', 'changes')
128
- for (const cn of (global.activeChanges || [])) {
129
- const pp = path.join(changesDir, cn, 'progress.json')
130
- if (!existsSync(pp)) continue
131
- try {
132
- const data = JSON.parse(readFileSync(pp, 'utf8'))
133
- if (data.currentStage) return data.currentStage
134
- } catch { /* skip */ }
135
- }
136
- } catch { /* skip */ }
137
- }
113
+ // 2. sillyspec.db 读取(通过 sqlite3 CLI 同步调用)
114
+ const dbPath = path.join(cwd, '.sillyspec', '.runtime', 'sillyspec.db')
115
+ if (!existsSync(dbPath)) return null
116
+ try {
117
+ const { execSync } = require('child_process')
118
+ const result = execSync(
119
+ `sqlite3 "${dbPath}" "SELECT current_stage FROM changes WHERE status='active' AND current_stage IN ('execute','quick') ORDER BY last_active DESC LIMIT 1"`,
120
+ { encoding: 'utf8', timeout: 2000 }
121
+ ).trim()
122
+ return result || null
123
+ } catch { /* sqlite3 CLI 不可用或查询失败 */ }
138
124
 
139
125
  return null
140
126
  }
@@ -149,35 +135,17 @@ function isNoWorktreeMode(cwd) {
149
135
  const gateStatus = readGateStatus(cwd)
150
136
  if (gateStatus && gateStatus.noWorktree) return true
151
137
 
152
- // 2. 检查 progress.json
153
- const progressFiles = [
154
- path.join(cwd, '.sillyspec', '.runtime', 'progress.json'),
155
- ]
156
- for (const p of progressFiles) {
157
- if (!existsSync(p)) continue
158
- try {
159
- const data = JSON.parse(readFileSync(p, 'utf8'))
160
- if (data.noWorktree) return true
161
- } catch { /* skip */ }
162
- }
163
-
164
- // 3. 检查变更级 progress.json
165
- const runtimeDir = path.join(cwd, '.sillyspec', '.runtime')
166
- const globalFile = path.join(runtimeDir, 'global.json')
167
- if (existsSync(globalFile)) {
168
- try {
169
- const global = JSON.parse(readFileSync(globalFile, 'utf8'))
170
- const changesDir = path.join(cwd, '.sillyspec', 'changes')
171
- for (const cn of (global.activeChanges || [])) {
172
- const pp = path.join(changesDir, cn, 'progress.json')
173
- if (!existsSync(pp)) continue
174
- try {
175
- const data = JSON.parse(readFileSync(pp, 'utf8'))
176
- if (data.noWorktree) return true
177
- } catch { /* skip */ }
178
- }
179
- } catch { /* skip */ }
180
- }
138
+ // 2. sillyspec.db 读取
139
+ const dbPath = path.join(cwd, '.sillyspec', '.runtime', 'sillyspec.db')
140
+ if (!existsSync(dbPath)) return false
141
+ try {
142
+ const { execSync } = require('child_process')
143
+ const result = execSync(
144
+ `sqlite3 "${dbPath}" "SELECT no_worktree FROM changes WHERE status='active' AND current_stage IN ('execute','quick') LIMIT 1"`,
145
+ { encoding: 'utf8', timeout: 2000 }
146
+ ).trim()
147
+ return result === '1'
148
+ } catch { /* sqlite3 CLI 不可用或查询失败 */ }
181
149
 
182
150
  return false
183
151
  }
package/src/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * SillySpec CLI — 安装工具
5
5
  *
6
6
  * 只负责两件事:init(安装命令模板)和 setup(安装 MCP 工具)。
7
- * 状态管理通过 progress.json 完成,使用 `sillyspec progress` 命令。
7
+ * 状态管理通过 sillyspec.db(SQLite)完成,使用 `sillyspec progress` 命令。
8
8
  */
9
9
  import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
10
10
  import { join, resolve } from 'path';
@@ -39,7 +39,7 @@ SillySpec CLI — 规范驱动开发工具包
39
39
  quick, explore, status, doctor
40
40
 
41
41
  sillyspec progress <cmd> 进度记录(轻量,不强制顺序)
42
- init 初始化 progress.json
42
+ init 初始化项目数据库
43
43
  show 查看当前进度
44
44
  set-stage <stage> 设置当前阶段
45
45
  add-step <stage> <name> 添加步骤
package/src/init.js CHANGED
@@ -56,7 +56,7 @@ const INJECTION_CONTENT = `## SillySpec — 规范驱动开发
56
56
  - 遵循 \`.sillyspec/docs/<project>/scan/CONVENTIONS.md\` 中的代码风格
57
57
 
58
58
  ### 工作流程
59
- - 读取当前变更的 progress.json 确认当前阶段(使用 \`sillyspec progress show\`)
59
+ - 读取 sillyspec.db 确认当前阶段(使用 \`sillyspec progress show\`)
60
60
  - 各阶段产出文件位于 \`.sillyspec/changes/<变更名>/\` 下
61
61
  `;
62
62
 
package/src/progress.js CHANGED
@@ -3,11 +3,12 @@
3
3
  *
4
4
  * 纯 Node.js,无外部依赖。支持多变更并行。
5
5
  *
6
- * 存储结构(v3):
7
- * .sillyspec/.runtime/global.json全局状态(项目名、活跃变更列表)
8
- * .sillyspec/changes/<name>/progress.json 每个变更独立的阶段/步骤状态
6
+ * 存储结构:
7
+ * .sillyspec/.runtime/sillyspec.dbSQLite 数据库(权威状态源)
8
+ * .sillyspec/.runtime/global.json 全局状态缓存(项目名、活跃变更列表)
9
+ * .sillyspec/.runtime/gate-status.json — worktree-guard 门禁状态缓存
9
10
  *
10
- * 向后兼容:如果存在旧的 .sillyspec/.runtime/progress.json,自动迁移。
11
+ * 历史迁移:v1/v2 使用 progress.json 文件,v3 已全部迁移至 SQLite。
11
12
  */
12
13
 
13
14
  import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'fs';
@@ -17,7 +18,6 @@ import { DB } from './db.js';
17
18
  const RUNTIME_DIR = '.sillyspec/.runtime';
18
19
  const CHANGES_DIR = '.sillyspec/changes';
19
20
  const GLOBAL_FILE = 'global.json';
20
- const PROGRESS_FILE = 'progress.json';
21
21
  const CURRENT_VERSION = 3;
22
22
  const VALID_STAGES = ['scan', 'brainstorm', 'propose', 'plan', 'execute', 'verify', 'archive', 'quick', 'explore'];
23
23
  const VALID_STATUSES = ['pending', 'in-progress', 'completed', 'failed', 'blocked'];
@@ -154,7 +154,7 @@ export class ProgressManager {
154
154
  * 读取指定变更的 progress(SQL 版)
155
155
  * @param {string} cwd
156
156
  * @param {string|null} changeName - 变更名,null 时尝试自动检测
157
- * @returns {Promise<object|null>} 与旧版 progress.json 结构完全一致的 JS 对象
157
+ * @returns {Promise<object|null>} SQLite 查询结果一致的 JS 对象
158
158
  */
159
159
  async read(cwd, changeName = null) {
160
160
  // 自动检测变更名
@@ -759,7 +759,7 @@ export class ProgressManager {
759
759
  async _showChange(cwd, changeName) {
760
760
  const data = await this.read(cwd, changeName);
761
761
  if (!data) {
762
- console.log(`❌ 未找到变更 ${changeName} 的 progress.json`);
762
+ console.log(`❌ 未找到变更 ${changeName}`);
763
763
  return;
764
764
  }
765
765
 
@@ -816,7 +816,7 @@ export class ProgressManager {
816
816
 
817
817
  async validate(cwd, changeName = null) {
818
818
  const data = await this.read(cwd, changeName);
819
- if (!data) { console.log('❌ 无法读取 progress.json'); return false; }
819
+ if (!data) { console.log('❌ 无法读取进度数据'); return false; }
820
820
 
821
821
  const errors = [];
822
822
  if (!data._version || !Number.isInteger(data._version) || data._version < 1) {
@@ -825,7 +825,7 @@ export class ProgressManager {
825
825
  if (!data.stages || typeof data.stages !== 'object') errors.push('缺少 stages');
826
826
  if (!VALID_STAGES.every(s => data.stages[s])) errors.push('缺少阶段定义');
827
827
 
828
- if (errors.length === 0) { console.log('✅ progress.json 格式正确'); return true; }
828
+ if (errors.length === 0) { console.log('✅ 进度数据格式正确'); return true; }
829
829
 
830
830
  console.log(`⚠️ 发现问题,尝试修复...`);
831
831
  let fixed = { ...data, stages: { ...data.stages } };
@@ -852,7 +852,7 @@ export class ProgressManager {
852
852
  async reset(cwd, stage, changeName = null) {
853
853
  if (stage) {
854
854
  const data = await this.read(cwd, changeName);
855
- if (!data) { console.log('❌ 无法读取 progress.json'); return; }
855
+ if (!data) { console.log('❌ 无法读取进度数据'); return; }
856
856
  if (!data.stages[stage]) { console.log(`❌ 未知阶段: ${stage}`); return; }
857
857
  data.stages[stage] = emptyStage();
858
858
  data.lastActive = new Date().toLocaleString('zh-CN',{hour12:false});
package/src/run.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * sillyspec run 命令实现
3
3
  *
4
4
  * CLI 成为流程引擎,AI 变成步骤执行器。
5
- * 支持多变更并行:每个变更独立 progress.json。
5
+ * 支持多变更并行:每个变更状态存储在 sillyspec.db 中。
6
6
  */
7
7
  import { basename, join } from 'path'
8
8
  import { existsSync, readdirSync, mkdirSync, writeFileSync, appendFileSync, readFileSync, statSync } from 'fs'
@@ -146,10 +146,10 @@ async function ensureStageSteps(progress, stageName, cwd) {
146
146
  /**
147
147
  * 输出当前步骤的 prompt
148
148
  */
149
- function outputStep(stageName, stepIndex, steps, cwd, changeName) {
149
+ async function outputStep(stageName, stepIndex, steps, cwd, changeName, dbProjectName) {
150
150
  const step = steps[stepIndex]
151
151
  const total = steps.length
152
- const projectName = basename(cwd)
152
+ const projectName = dbProjectName || basename(cwd)
153
153
 
154
154
  const personas = {
155
155
  brainstorm: `### 🎯 你的角色:资深架构师
@@ -190,7 +190,12 @@ function outputStep(stageName, stepIndex, steps, cwd, changeName) {
190
190
  console.log(guardrails.trim())
191
191
  console.log('')
192
192
  }
193
- console.log(step.prompt)
193
+ let promptText = step.prompt
194
+ // 替换 prompt 中的占位符
195
+ if (projectName && promptText.includes('<project>')) {
196
+ promptText = promptText.replace(/<project>/g, projectName)
197
+ }
198
+ console.log(promptText)
194
199
  console.log(`\n### ⚠️ 铁律`)
195
200
  console.log('- **文档是核心资产,代码是文档的产物。** 没有文档就没有代码——文档是 AI 的记忆,是团队协作的基础,是后续维护的唯一依据。任何代码产出必须先有对应的设计/规范文档支撑。')
196
201
  console.log('- 只做本步骤描述的操作,不得自行扩展或跳过')
@@ -268,9 +273,14 @@ export async function runCommand(args, cwd) {
268
273
  if (autoChange) {
269
274
  progress = await pm.initChange(cwd, autoChange)
270
275
  } else if (isAuxiliary) {
271
- // 辅助阶段(scan/explore/quick/doctor/status)不需要 currentChange
272
- // 但仍然需要初始化一个空的 progress 对象以避免后续引用报错
273
- progress = { currentStage: stageName, stages: {}, lastActive: new Date().toLocaleString('zh-CN', { hour12: false }) }
276
+ // 辅助阶段(scan/explore/quick/doctor/status)自动使用默认变更名
277
+ const autoName = changeName || resolveChangeNameAuto(cwd) || 'default'
278
+ changeName = autoName
279
+ progress = await pm.initChange(cwd, autoName)
280
+ // initChange 可能因 project 表为空返回 null
281
+ if (!progress) {
282
+ progress = { currentStage: stageName, stages: {}, lastActive: new Date().toLocaleString('zh-CN', { hour12: false }), project: '' }
283
+ }
274
284
  } else {
275
285
  // brainstorm / propose 作为流程入口,自动生成变更名并初始化
276
286
  if (stageName === 'brainstorm' || stageName === 'propose') {
@@ -281,7 +291,7 @@ export async function runCommand(args, cwd) {
281
291
  progress = await pm.initChange(cwd, autoName)
282
292
  changeName = autoName
283
293
  } else {
284
- console.error('❌ 未找到 progress.json,请先运行 sillyspec init 或指定 --change <变更名>')
294
+ console.error('❌ 未找到进度数据,请先运行 sillyspec init 或指定 --change <变更名>')
285
295
  process.exit(1)
286
296
  }
287
297
  }
@@ -409,7 +419,7 @@ async function runStage(pm, progress, stageName, cwd, changeName, skipApproval =
409
419
 
410
420
  const defSteps = await getStageSteps(stageName, cwd, progress)
411
421
  if (defSteps && defSteps[currentIdx]) {
412
- outputStep(stageName, currentIdx, defSteps, cwd, changeName)
422
+ await outputStep(stageName, currentIdx, defSteps, cwd, changeName, progress.project || null)
413
423
  }
414
424
  }
415
425
 
@@ -654,7 +664,7 @@ async function completeStep(pm, progress, stageName, cwd, outputText, inputText
654
664
  const defSteps = await getStageSteps(stageName, cwd, progress)
655
665
  console.log(`✅ Step ${currentIdx + 1}/${steps.length} 完成:${steps[currentIdx].name}\n`)
656
666
  if (printNext) {
657
- outputStep(stageName, nextPendingIdx, defSteps, cwd, changeName)
667
+ await outputStep(stageName, nextPendingIdx, defSteps, cwd, changeName, progress.project || null)
658
668
  }
659
669
  return { stageCompleted: false, currentIdx, nextPendingIdx }
660
670
  }
@@ -692,7 +702,7 @@ async function skipStep(pm, progress, stageName, cwd, changeName) {
692
702
  const nextPendingIdx = steps.findIndex(s => s.status === 'pending')
693
703
  if (nextPendingIdx !== -1 && defSteps) {
694
704
  console.log('')
695
- outputStep(stageName, nextPendingIdx, defSteps, cwd, changeName)
705
+ await outputStep(stageName, nextPendingIdx, defSteps, cwd, changeName, progress.project || null)
696
706
  }
697
707
  }
698
708
 
@@ -837,7 +847,7 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
837
847
  }
838
848
  }
839
849
  }
840
- outputStep(currentStage, pendingIdx, defSteps, cwd, changeName)
850
+ await outputStep(currentStage, pendingIdx, defSteps, cwd, changeName, progress.project || null)
841
851
  return
842
852
  }
843
853
 
@@ -867,7 +877,7 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
867
877
  }
868
878
  }
869
879
  }
870
- outputStep(currentStage, nextPendingIdx, defSteps, cwd, changeName)
880
+ await outputStep(currentStage, nextPendingIdx, defSteps, cwd, changeName, progress.project || null)
871
881
  return
872
882
  }
873
883
 
@@ -909,6 +919,6 @@ async function runAutoMode(pm, progress, cwd, flags, changeName) {
909
919
  }
910
920
  }
911
921
  }
912
- outputStep(next, firstPending, nextSteps, cwd, changeName)
922
+ await outputStep(next, firstPending, nextSteps, cwd, changeName, progress.project || null)
913
923
  }
914
924
  }
@@ -165,7 +165,7 @@ module-impact.md 路径 + 影响模块数量 + 未匹配文件数量`,
165
165
  1. 如果 \`.sillyspec/ROADMAP.md\` 存在,标记对应 Phase 为已完成
166
166
  2. \`git add .sillyspec/changes/\` — 暂存归档结果(不要 commit,由用户通过统一提交工具处理)
167
167
  3. \`git add .sillyspec/docs/\` — 暂存模块文档更新(如有)
168
- 4. 更新 progress.json:
168
+ 4. 更新 sillyspec.db 中的阶段状态:
169
169
  - 清除当前变更信息(归档后不再活跃)
170
170
  - 如果是主变更(有 MASTER.md),标记所有阶段为 ✅,然后清除
171
171
  - 历史记录追加时间 + 归档完成
@@ -5,7 +5,7 @@ export const definition = {
5
5
  steps: [
6
6
  {
7
7
  name: '状态检查',
8
- prompt: `检查当前变更的 progress.json 确认当前状态。
8
+ prompt: `检查当前变更的进度状态(sillyspec.db)。
9
9
 
10
10
  ### 操作
11
11
  1. 运行 \`sillyspec progress show\`
@@ -18,15 +18,10 @@ export const definition = {
18
18
  for d in .sillyspec .sillyspec/projects .sillyspec/docs .sillyspec/changes .sillyspec/.runtime; do
19
19
  [ -d "$d" ] && echo "✅ $d" || echo "❌ $d"
20
20
  done
21
- # 检查 progress.json(支持新版按变更隔离和旧版全局)
22
- if [ -d .sillyspec/changes ]; then
23
- PROGRESS_FILE=$(find .sillyspec/changes -maxdepth 2 -name progress.json | head -1)
24
- fi
25
- if [ -z "$PROGRESS_FILE" ]; then
26
- PROGRESS_FILE='.sillyspec/.runtime/progress.json'
27
- fi
28
- [ -f "$PROGRESS_FILE" ] && echo "✅ progress.json 存在 ($PROGRESS_FILE)" || echo "❌ progress.json 不存在"
29
- node -e "JSON.parse(require('fs').readFileSync('$PROGRESS_FILE','utf8')); console.log('✅ progress.json 可解析')" 2>/dev/null || echo "⚠️ progress.json 不可解析"
21
+ # 检查 sillyspec.db(SQLite 权威状态源)
22
+ DB_FILE='.sillyspec/.runtime/sillyspec.db'
23
+ [ -f "$DB_FILE" ] && echo "✅ sillyspec.db 存在" || echo "❌ sillyspec.db 不存在"
24
+ sqlite3 "$DB_FILE" "SELECT count(*) FROM project" 2>/dev/null && echo "✅ sillyspec.db 可查询" || echo "⚠️ sillyspec.db 不可查询"
30
25
  \`\`\`
31
26
 
32
27
  ### 2. 项目配置检查
@@ -46,40 +41,31 @@ done
46
41
 
47
42
  ### 3. 进度数据一致性
48
43
  \`\`\`bash
49
- # 读取 currentChange 并检查目录存在性
50
- node -e "
51
- const p = JSON.parse(require('fs').readFileSync(process.env.PROGRESS_FILE || '.sillyspec/.runtime/progress.json','utf8'));
52
- const cc = p.currentChange;
53
- if (!cc) { console.log('ℹ️ 无当前变更'); process.exit(0); }
54
- const dir = '.sillyspec/changes/' + cc;
55
- const exists = require('fs').existsSync(dir);
56
- console.log(exists ? '✅ currentChange 目录存在: ' + cc : '❌ currentChange 目录不存在: ' + cc);
57
- // 检查各阶段产出
58
- const stages = p.stages || {};
59
- for (const [name, sd] of Object.entries(stages)) {
60
- if (sd.status === 'completed' && sd.steps.length > 0) {
61
- const hasOutput = sd.steps.some(s => s.output && s.output.trim());
62
- console.log(' ' + name + ': ' + (hasOutput ? '✅ 有产出' : '⚠️ 已完成但无产出记录'));
63
- }
64
- }
65
- " 2>/dev/null || echo "⚠️ 无法读取 progress.json"
44
+ # sillyspec.db 读取活跃变更并检查目录存在性
45
+ DB_FILE='.sillyspec/.runtime/sillyspec.db'
46
+ if [ ! -f "$DB_FILE" ]; then echo "⚠️ sillyspec.db 不存在"; exit 0; fi
47
+ ACTIVE_CHANGE=$(sqlite3 "$DB_FILE" "SELECT name FROM changes WHERE status='active' ORDER BY last_active DESC LIMIT 1" 2>/dev/null)
48
+ if [ -z "$ACTIVE_CHANGE" ]; then echo "ℹ️ 无当前变更"; exit 0; fi
49
+ echo "当前变更: $ACTIVE_CHANGE"
50
+ DIR=".sillyspec/changes/$ACTIVE_CHANGE"
51
+ [ -d "$DIR" ] && echo "✅ 变更目录存在: $ACTIVE_CHANGE" || echo "❌ 变更目录不存在: $ACTIVE_CHANGE"
52
+ # 检查各阶段状态
53
+ sqlite3 -header -column "$DB_FILE" "SELECT stage, status FROM stages s JOIN changes c ON s.change_id=c.id WHERE c.name='$ACTIVE_CHANGE' ORDER BY s.stage" 2>/dev/null || echo "⚠️ 无法查询阶段数据"
66
54
  \`\`\`
67
55
 
68
56
  ### 4. 孤儿文件检查
69
57
  \`\`\`bash
58
+ DB_FILE='.sillyspec/.runtime/sillyspec.db'
59
+ if [ ! -f "$DB_FILE" ]; then echo "⚠️ sillyspec.db 不存在"; exit 0; fi
70
60
  node -e "
71
61
  const fs = require('fs');
72
62
  const dir = '.sillyspec/changes';
73
63
  if (!fs.existsSync(dir)) { console.log('ℹ️ changes/ 目录不存在'); process.exit(0); }
74
64
  const subs = fs.readdirSync(dir).filter(f => fs.statSync(dir+'/'+f).isDirectory());
75
65
  if (subs.length === 0) { console.log('ℹ️ 无变更目录'); process.exit(0); }
76
- let progress;
77
- try { progress = JSON.parse(fs.readFileSync(process.env.PROGRESS_FILE || '.sillyspec/.runtime/progress.json','utf8')); } catch { console.log('⚠️ 无法读取 progress.json'); subs.forEach(s => console.log('❓ ' + s)); process.exit(0); }
78
- const known = new Set();
79
- if (progress.currentChange) known.add(progress.currentChange);
80
- for (const sd of Object.values(progress.stages || {})) {
81
- (sd.steps || []).forEach(s => { if (s.output) known.add(s.output); });
82
- }
66
+ const { execSync } = require('child_process');
67
+ let known;
68
+ try { const rows = execSync('sqlite3 -json \".sillyspec/.runtime/sillyspec.db\" \"SELECT name FROM changes WHERE status=\\\"active\\\"\"', {encoding:'utf8'}).trim(); known = new Set(JSON.parse(rows).map(r => r.name)); } catch { known = new Set(); }
83
69
  subs.forEach(s => {
84
70
  console.log(known.has(s) ? '✅ ' + s + ' — 已关联' : '⚠️ ' + s + ' — 孤儿目录(可清理)');
85
71
  });
@@ -124,12 +110,12 @@ done
124
110
 
125
111
  ### 1. 探测构建工具
126
112
  \`\`\`bash
127
- # 确定项目路径(使用 progress.json 中的项目或当前目录)
128
- PROJECT_DIR=$(node -e "
113
+ # 确定项目路径(使用 sillyspec.db 中的项目路径或当前目录)
114
+ PROJECT_DIR=$(sqlite3 -json '.sillyspec/.runtime/sillyspec.db' "SELECT name FROM project WHERE id=1" 2>/dev/null | node -e "const r=JSON.parse(require('fs').readFileSync(0,'utf8'));console.log(r.length>0&&r[0].name?r[0].name:'.')" 2>/dev/null || node -e "
129
115
  const fs=require('fs');
130
- try{const fs=require('fs'),path=require('path');const changesDir='.sillyspec/changes';let pp=null;if(fs.existsSync(changesDir)){const entries=fs.readdirSync(changesDir,{withFileTypes:true}).filter(e=>e.isDirectory()&&e.name!=='archive');if(entries.length===1)pp=path.join(changesDir,entries[0].name,'progress.json');}if(!pp)pp='.sillyspec/.runtime/progress.json';const p=JSON.parse(fs.readFileSync(pp,'utf8'));if(p.project){console.log(p.project);process.exit(0)}}catch{}
131
- const files=fs.readdirSync('.sillyspec/projects').filter(f=>f.endsWith('.yaml'));
116
+ try{const files=fs.readdirSync('.sillyspec/projects').filter(f=>f.endsWith('.yaml'));
132
117
  if(files.length>0){const c=fs.readFileSync('.sillyspec/projects/'+files[0],'utf8');const m=c.match(/^path:\\s*(.+)/m);console.log(m?m[1].trim():'.')}else console.log('.')
118
+ }catch{console.log('.')}
133
119
  " 2>/dev/null)
134
120
  echo "项目目录: $PROJECT_DIR"
135
121
 
@@ -264,7 +250,7 @@ timeout 5 which docker 2>/dev/null && echo "✅ Docker 可用" || echo "ℹ️ D
264
250
  ✅ .sillyspec/ 目录结构 — 正常
265
251
  ✅ projects/*.yaml — N 个项目已注册
266
252
  ⚠️ local.yaml (xxx) — 缺少 test 命令
267
- progress.json — brainstorm 标记完成但 design.md 不存在
253
+ sillyspec.db 阶段状态 — brainstorm 标记完成但 design.md 不存在
268
254
 
269
255
  ## 构建环境
270
256
  ✅ Node.js v23.4.0 — 可用
@@ -291,7 +277,7 @@ timeout 5 which docker 2>/dev/null && echo "✅ Docker 可用" || echo "ℹ️ D
291
277
  - 缺少 local.yaml → \`sillyspec init\` 重新生成,或手动创建
292
278
  - local.yaml 缺少 build/test → 补充对应命令
293
279
  - 缺少 STACK.md → \`sillyspec run scan\` 重新扫描
294
- - progress.json 不一致 → \`sillyspec run <阶段> --reset\` 重置对应阶段
280
+ - sillyspec.db 状态不一致 → \`sillyspec run <阶段> --reset\` 重置对应阶段
295
281
  - 孤儿目录 → 确认后 \`rm -rf .sillyspec/changes/<目录名>\`
296
282
  - Maven 私服不可达 → 检查 VPN、settings.xml 配置、私服状态
297
283
  - Git remote 不可达 → 检查网络、SSH key 或凭证
@@ -322,6 +322,7 @@ ${taskSummary}
322
322
  1. 任务目标(简短描述)
323
323
  2. 蓝图文件路径(让子代理自行读取详情)
324
324
  3. 编码铁律:先读后写、TDD、不编造方法、只做蓝图里写的事、遵守边界处理规则、不超出 allowed_paths
325
+ 4. 如存在模块文档(.sillyspec/docs/*/modules/),按需读取涉及模块的 <module>.md 参考接口约定和数据流
325
326
 
326
327
  ### Wave 开始前
327
328
  1. 读取 design.md 的「编码铁律」章节(如果存在),严格遵守
@@ -27,5 +27,5 @@ export const stageRegistry = {
27
27
  doctor: { ...doctor, ...auxiliaryFlag }
28
28
  }
29
29
 
30
- // 辅助命令(在没有 progress.json 时也可执行)
30
+ // 辅助命令(在无活跃变更时也可执行)
31
31
  export const auxiliaryStages = ['scan', 'quick', 'explore', 'archive', 'status', 'doctor']
@@ -316,8 +316,13 @@ export function buildCoordinatorStep(changeDir, taskNames) {
316
316
 
317
317
  操作:
318
318
  1. 读取 ${changeDir}/design.md 和 ${changeDir}/plan.md 了解上下文
319
- 2. 读取相关源文件了解现有代码
320
- 3. 按以下格式编写任务蓝图并保存到 ${changeDir}/tasks/task-${num}.md:
319
+ 2. 读取相关模块文档(如存在):
320
+ - \
321
+ ls .sillyspec/docs/*/modules/_module-map.yaml 2>/dev/null\
322
+ 确认模块划分,读取涉及模块的 \
323
+ ls .sillyspec/docs/*/modules/*.md 2>/dev/null\
324
+ 3. 读取相关源文件了解现有代码
325
+ 4. 按以下格式编写任务蓝图并保存到 ${changeDir}/tasks/task-${num}.md:
321
326
 
322
327
  ---
323
328
  id: task-${num}
@@ -17,6 +17,11 @@ export const definition = {
17
17
  6. 如有 \`--change\`,加载设计文档:\`cat .sillyspec/changes/<change-name>/design.md 2>/dev/null\`(理解设计意图)
18
18
  7. 如有需要,查询知识库:\`cat .sillyspec/knowledge/INDEX.md 2>/dev/null\`
19
19
 
20
+ ### 模块文档加载
21
+ 8. 读取 \`.sillyspec/docs/<project>/modules/_module-map.yaml\`(不存在则跳过以下步骤)
22
+ 9. 根据任务描述初步判断可能涉及的模块
23
+ 10. 读取匹配到的 \`.sillyspec/docs/<project>/modules/<module>.md\`
24
+
20
25
  ### 创建任务记录(必须执行)
21
26
  理解完任务后,立即创建记录文件:
22
27
  1. \`git config user.name\` 获取用户名
@@ -57,7 +62,7 @@ worktree 路径 + 变更名 + 分支名`,
57
62
  prompt: `实现任务。
58
63
 
59
64
  ### 工作目录
60
- 你必须在 worktree 中工作(将子代理的 cwd 设为上一步记录的 worktree 路径)。
65
+ 你必须在上一步记录的 worktree 路径中工作。
61
66
  不要在主工作区修改源码文件。所有代码变更只在 worktree 中进行。
62
67
 
63
68
  ### 操作
@@ -44,11 +44,16 @@ export const definition = {
44
44
  1. \`ls .sillyspec/projects/*.yaml 2>/dev/null | grep -q .\` — 检查已有文档
45
45
  1. \`ls .sillyspec/docs/*/scan/ 2>/dev/null\` — 检查已有文档
46
46
  2. \`wc -l .sillyspec/docs/*/scan/*.md 2>/dev/null\` — 文档行数
47
- 3. 已有 3 份 → 建议升级深度扫描;已有 7 份 → 建议刷新或跳过
48
- 5. 显示子项目列表供选择扫描范围
47
+ 3. 显示子项目列表供选择扫描范围
48
+
49
+ ### ⛔ 重要:已有文档时的处理
50
+ 如果发现已有 scan 文档(如 7 份齐全),**必须停下来问用户**:
51
+ - 列出已有文档状态(哪些存在、哪些缺失)
52
+ - 明确提供两个选项:**重新扫描(全部覆盖)** 或 **只补扫描缺失的文档**
53
+ - **不要自行决定跳过**,等用户选择后再继续
49
54
 
50
55
  ### 输出
51
- 已有文档状态 + 扫描建议`,
56
+ 已有文档状态 + 等待用户选择`,
52
57
  outputHint: '工作区和文档状态',
53
58
  optional: false
54
59
  },
@@ -71,7 +76,7 @@ export const definition = {
71
76
  prompt: `检测已有扫描文档,只生成缺失的。
72
77
 
73
78
  ### 操作
74
- 1. \`PROJECT=$(python3 -c "import sys,json,glob; files=glob.glob('.sillyspec/changes/*/progress.json'); print(json.load(open(files[0])).get('project','')) if files else print('')" 2>/dev/null || basename "$(pwd)")\`
79
+ 1. \`PROJECT=$(sqlite3 -json '.sillyspec/.runtime/sillyspec.db' "SELECT name FROM project WHERE id=1" 2>/dev/null | node -e "const r=JSON.parse(require('fs').readFileSync(0,'utf8'));console.log(r.length>0?r[0].name:'')" 2>/dev/null || basename "$(pwd)")\`
75
80
  2. 检查 7 份文档是否存在:ARCHITECTURE、STRUCTURE、CONVENTIONS、INTEGRATIONS、TESTING、CONCERNS、PROJECT
76
81
  3. 列出已有 ✅ 和缺失 ⬜
77
82
  4. 只生成缺失的文档
@@ -82,73 +87,67 @@ export const definition = {
82
87
  optional: false
83
88
  },
84
89
  {
85
- name: '深度扫描 — 技术架构',
86
- prompt: `扫描技术栈 + 数据库 Schema + 架构模式。参考 _env-detect.md。
87
-
88
- ### 操作
89
- 1. grep/rg 搜索(\`@Entity\`、\`schema.prisma\`、\`models.py\` 等),**禁止读源码全文**
90
- 2. Schema 只记表名+说明+字段数
91
- 3. 写入 \`.sillyspec/docs/<project>/scan/ARCHITECTURE.md\`
92
- 4. 包含 \`## 技术栈\` \`## 架构概览\` \`## 数据模型(摘要)\`
93
-
94
- ### 输出
95
- ARCHITECTURE.md 路径
96
-
97
- ### 注意
98
- - 路径用反引号,不编造`,
99
- outputHint: 'ARCHITECTURE.md 路径',
100
- optional: false
101
- },
102
- {
103
- name: '深度扫描代码约定',
104
- prompt: `扫描框架隐形规则 + 实体继承 + 代码风格。参考 _env-detect.md
105
-
106
- ### 操作
107
- 1. 用 grep 搜索拦截器/插件/逻辑删除/基类/审计字段,**禁止读源码全文**
108
- 2. 根据检测到的语言/框架自行决定搜索什么模式
109
- 3. 提取 3-5 个典型示例
110
- 4. 写入 \`.sillyspec/docs/<project>/scan/CONVENTIONS.md\`
111
- 5. 包含 \`## 框架隐形规则\` \`## 实体继承规范\` \`## 代码风格\`
112
-
113
- ### 输出
114
- CONVENTIONS.md 路径
115
-
116
- ### 注意
117
- - 路径用反引号,不编造`,
118
- outputHint: 'CONVENTIONS.md 路径',
119
- optional: false
120
- },
121
- {
122
- name: '深度扫描 目录结构和集成',
123
- prompt: `扫描目录结构 + 外部集成。参考 _env-detect.md。
124
-
125
- ### 操作
126
- 1. 用 find/ls/tree 和 grep,**禁止读源码全文**
127
- 2. 搜索 API 调用、MQ 配置、缓存、第三方 SDK
128
- 3. 写入 \`.sillyspec/docs/<project>/scan/STRUCTURE.md\`(目录树+模块说明)
129
- 4. 写入 \`.sillyspec/docs/<project>/scan/INTEGRATIONS.md\`(按类型分组)
130
-
131
- ### 输出
132
- STRUCTURE.md 和 INTEGRATIONS.md 路径
133
-
134
- ### 注意
135
- - 路径用反引号,不编造`,
136
- outputHint: 'STRUCTURE.md + INTEGRATIONS.md 路径',
137
- optional: false
138
- },
139
- {
140
- name: '深度扫描 — 测试和债务',
141
- prompt: `扫描测试现状 + 技术债务 + 项目概览。参考 _env-detect.md。
142
-
143
- ### 操作
144
- 1. 用 grep 搜索测试文件、TODO/FIXME、过时依赖,**禁止读源码全文**
145
- 2. 写入 \`.sillyspec/docs/<project>/scan/TESTING.md\`(测试结构)
146
- 3. 写入 \`.sillyspec/docs/<project>/scan/CONCERNS.md\`(按严重程度分组)
147
- 4. 写入 \`.sillyspec/docs/<project>/scan/PROJECT.md\`(项目信息)
148
-
149
- ### 输出
150
- TESTING.md、CONCERNS.md、PROJECT.md 路径`,
151
- outputHint: '三份文档路径',
90
+ name: '深度扫描 — 7 份文档(子代理并行)',
91
+ prompt: `使用子代理并行生成 7 份扫描文档。**你必须使用子代理执行,不要自己写文档。**
92
+
93
+ ### 执行方式
94
+ 1. 为每个扫描任务启动独立子代理(可并行),每个子代理负责 1-2 份文档
95
+ 2. 子代理直接用 grep/rg 搜索源码并写入文件,结果不回传到你的上下文
96
+ 3. 等待所有子代理完成后,验证文件是否生成且非空
97
+
98
+ ### 子代理任务分配
99
+
100
+ **子代理 A — 技术架构**
101
+ 目标文件:\`.sillyspec/docs/<project>/scan/ARCHITECTURE.md\`
102
+ 搜索范围:技术栈 + 数据库 Schema + 架构模式
103
+ - 用 grep/rg 搜索(\`@Entity\`、\`schema.prisma\`、\`models.py\` 等),**禁止读源码全文**
104
+ - Schema 只记表名+说明+字段数
105
+ - 包含 \`## 技术栈\` \`## 架构概览\` \`## 数据模型(摘要)\`
106
+ - 参考 _env-detect.md(如存在)
107
+
108
+ **子代理 B代码约定**
109
+ 目标文件:\`.sillyspec/docs/<project>/scan/CONVENTIONS.md\`
110
+ 搜索范围:框架隐形规则 + 实体继承 + 代码风格
111
+ - 用 grep 搜索拦截器/插件/逻辑删除/基类/审计字段,**禁止读源码全文**
112
+ - 根据检测到的语言/框架自行决定搜索什么模式
113
+ - 提取 3-5 个典型示例
114
+ - 包含 \`## 框架隐形规则\` \`## 实体继承规范\` \`## 代码风格\`
115
+ - 参考 _env-detect.md(如存在)
116
+
117
+ **子代理 C — 目录结构 + 外部集成**
118
+ 目标文件:\`.sillyspec/docs/<project>/scan/STRUCTURE.md\` + \`.sillyspec/docs/<project>/scan/INTEGRATIONS.md\`
119
+ 搜索范围:目录树 + 模块说明 + 外部集成
120
+ - 用 find/ls/tree 和 grep,**禁止读源码全文**
121
+ - 搜索 API 调用、MQ 配置、缓存、第三方 SDK
122
+ - STRUCTURE.md:目录树+模块说明
123
+ - INTEGRATIONS.md:外部集成(按类型分组)
124
+ - 参考 _env-detect.md(如存在)
125
+
126
+ **子代理 D — 测试 + 债务 + 项目概览**
127
+ 目标文件:\`.sillyspec/docs/<project>/scan/TESTING.md\` + \`.sillyspec/docs/<project>/scan/CONCERNS.md\` + \`.sillyspec/docs/<project>/scan/PROJECT.md\`
128
+ 搜索范围:测试文件 + TODO/FIXME + 过时依赖 + 项目信息
129
+ - 用 grep 搜索测试文件、TODO/FIXME、过时依赖,**禁止读源码全文**
130
+ - TESTING.md:测试结构
131
+ - CONCERNS.md:技术债务(按严重程度分组)
132
+ - PROJECT.md:项目概览
133
+ - 参考 _env-detect.md(如存在)
134
+
135
+ ### 每个子代理的共同要求
136
+ - **上下文注入**:主 agent 在启动子代理前,必须将以下信息拼入子代理 prompt:
137
+ - 项目名(<project>)
138
+ - 断点续扫步骤列出的缺失文档列表(哪些要生成、哪些跳过)
139
+ - 环境探测结果摘要(构建工具、语言框架、关键依赖)
140
+ - _env-detect.md 内容(如存在,直接贴入)
141
+ - 路径用反引号,不编造
142
+ - 目标文件不存在则创建,已存在则覆盖
143
+ - 只生成缺失文档(根据断点续扫结果)
144
+
145
+ ### 完成后
146
+ 验证 7 份文档全部生成且非空,列出结果:
147
+ - ✅ ARCHITECTURE.md / ❌ 缺失
148
+ - ✅ CONVENTIONS.md / ❌ 缺失
149
+ - ...`,
150
+ outputHint: '7 份文档生成状态',
152
151
  optional: false
153
152
  },
154
153
  {
@@ -235,15 +234,72 @@ _module-map.yaml 生成结果(已存在/已生成/模块列表)`,
235
234
  outputHint: '_module-map.yaml 生成状态',
236
235
  optional: true
237
236
  },
237
+ {
238
+ name: '生成模块核心文档',
239
+ prompt: `根据 _module-map.yaml 中的模块划分,为每个模块生成核心文档(用于后续归档和开发上下文)。
240
+
241
+ ### 操作
242
+ 1. 读取 \`.sillyspec/docs/<project>/modules/_module-map.yaml\`,获取模块列表和路径
243
+ 2. 检查 \`.sillyspec/docs/<project>/modules/\` 下已有的模块文档(<module>.md)
244
+ 3. 列出每个模块的状态:已有文档 / 缺失
245
+ 4. **必须停下来问用户**:
246
+ - 展示模块列表及现有文档状态
247
+ - 明确提供选项:**为缺失模块生成初始文档** / **全部重新生成(覆盖已有)** / **跳过**
248
+ 5. 用户选择后执行
249
+
250
+ ### 生成方法(子代理并行,只针对用户选中的模块)
251
+ **你必须为每个模块启动独立子代理执行,不要自己写文档。**
252
+
253
+ 每个子代理的 prompt(**主 agent 启动前必须拼入**:
254
+ - 模块名和路径(从 _module-map.yaml 读取)
255
+ - 环境探测结果摘要(构建工具、语言框架)
256
+ - scan 文档关键信息摘要(ARCHITECTURE.md 的技术栈、CONVENTIONS.md 的代码风格要点,如已生成)
257
+ \`\`\`
258
+ 模块名:<module-name>
259
+ 模块路径:<glob patterns>
260
+ 目标文件:.sillyspec/docs/<project>/modules/<module>.md
261
+
262
+ 操作:
263
+ 1. 用 grep/rg 搜索模块路径范围内的源码(禁止读源码全文)
264
+ 2. 提取:模块职责、对外接口(导出函数/API)、关键依赖、设计要点
265
+ 3. 按以下模板写入目标文件:
266
+
267
+ # <module-name>
268
+ > 最后更新:YYYY-MM-DD
269
+ > 最近变更:scan(初始生成)
270
+ > 模块路径:<glob patterns>
271
+
272
+ ## 职责
273
+ ## 当前设计
274
+ ## 对外接口(表格)
275
+ ## 关键数据流
276
+ ## 设计决策(表格)
277
+ ## 依赖关系
278
+ ## 注意事项
279
+ ## 变更索引(表格,初始为空)
280
+
281
+ 规则:
282
+ - 不要编造接口或依赖,只写 grep/rg 能搜到的
283
+ - 模板与 archive 阶段格式一致
284
+ \`\`\`
285
+
286
+ 等待所有子代理完成,验证文件是否生成且非空。
287
+
288
+ ### 输出
289
+ 已生成的模块文档路径列表`,
290
+ outputHint: '模块文档生成状态',
291
+ optional: true
292
+ },
238
293
  {
239
294
  name: '自检和提交',
240
295
  prompt: `验证扫描完整性,清理并提交。
241
296
 
242
297
  ### 操作
243
- 1. 检查 7 份文档是否全部生成
244
- 2. 自检门控:ARCHITECTURE(技术栈+Schema摘要)、CONVENTIONS(隐形规则+代码风格)、STRUCTURE(目录结构)、INTEGRATIONS(外部依赖)、TESTING(测试现状)、CONCERNS(技术债务)、PROJECT(项目概览)
245
- 3. 清理:\`rm -f .sillyspec/docs/<project>/scan/_env-detect.md\`
246
- 4. \`git add .sillyspec/\` — 暂存扫描结果(不要 commit,由用户通过统一提交工具处理)
298
+ 1. 检查 7 份 scan 文档是否全部生成
299
+ 2. 检查模块文档状态(如有)
300
+ 3. 自检门控:ARCHITECTURE(技术栈+Schema摘要)、CONVENTIONS(隐形规则+代码风格)、STRUCTURE(目录结构)、INTEGRATIONS(外部依赖)、TESTING(测试现状)、CONCERNS(技术债务)、PROJECT(项目概览)
301
+ 4. 清理:\`rm -f .sillyspec/docs/<project>/scan/_env-detect.md\`
302
+ 5. \`git add .sillyspec/\` — 暂存扫描结果(不要 commit,由用户通过统一提交工具处理)
247
303
 
248
304
  ### 输出
249
305
  扫描完整性报告