sillyspec 3.20.2 → 3.20.4

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 (133) hide show
  1. package/.claude/skills/sillyspec-archive/SKILL.md +21 -21
  2. package/.claude/skills/sillyspec-auto/SKILL.md +83 -83
  3. package/.claude/skills/sillyspec-brainstorm/SKILL.md +44 -44
  4. package/.claude/skills/sillyspec-commit/SKILL.md +106 -106
  5. package/.claude/skills/sillyspec-continue/SKILL.md +45 -45
  6. package/.claude/skills/sillyspec-doctor/SKILL.md +31 -31
  7. package/.claude/skills/sillyspec-execute/SKILL.md +30 -30
  8. package/.claude/skills/sillyspec-explore/SKILL.md +109 -109
  9. package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
  10. package/.claude/skills/sillyspec-plan/SKILL.md +21 -21
  11. package/.claude/skills/sillyspec-propose/SKILL.md +21 -21
  12. package/.claude/skills/sillyspec-quick/SKILL.md +21 -21
  13. package/.claude/skills/sillyspec-resume/SKILL.md +68 -68
  14. package/.claude/skills/sillyspec-scan/SKILL.md +21 -21
  15. package/.claude/skills/sillyspec-state/SKILL.md +54 -54
  16. package/.claude/skills/sillyspec-status/SKILL.md +21 -21
  17. package/.claude/skills/sillyspec-verify/SKILL.md +21 -21
  18. package/.claude/skills/sillyspec-workspace/SKILL.md +157 -157
  19. package/.husky/pre-push +13 -13
  20. package/CLAUDE.md +18 -18
  21. package/README.md +198 -188
  22. package/SKILL.md +90 -91
  23. package/bin/sillyspec.js +2 -2
  24. package/docs/brainstorm-plan-contract.md +64 -64
  25. package/docs/plan-execute-contract.md +123 -123
  26. package/docs/platform-scan-protocol.md +298 -298
  27. package/docs/revision-mode.md +115 -115
  28. package/docs/sillyspec/file-lifecycle/known-implementation-gaps.md +99 -99
  29. package/docs/sillyspec/file-lifecycle/platform-workflows-sync.md +218 -218
  30. package/docs/sillyspec/file-lifecycle/stage-artifacts.md +167 -167
  31. package/docs/sillyspec/file-lifecycle/storage-and-state.md +148 -148
  32. package/docs/sillyspec/file-lifecycle/worktree-and-guard.md +211 -193
  33. package/docs/sillyspec/file-lifecycle.md +125 -125
  34. package/docs/workflow-contract-regression.md +106 -106
  35. package/docs/worktree-isolation.md +252 -252
  36. package/package.json +40 -40
  37. package/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -7446
  38. package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -1
  39. package/packages/dashboard/dist/index.html +16 -16
  40. package/packages/dashboard/index.html +15 -15
  41. package/packages/dashboard/package-lock.json +2384 -2384
  42. package/packages/dashboard/package.json +25 -25
  43. package/packages/dashboard/server/executor.js +86 -86
  44. package/packages/dashboard/server/index.js +588 -588
  45. package/packages/dashboard/server/parser.js +526 -526
  46. package/packages/dashboard/server/watcher.js +344 -344
  47. package/packages/dashboard/src/App.vue +558 -558
  48. package/packages/dashboard/src/components/ActionBar.vue +93 -93
  49. package/packages/dashboard/src/components/CommandPalette.vue +96 -96
  50. package/packages/dashboard/src/components/DetailPanel.vue +137 -137
  51. package/packages/dashboard/src/components/LogStream.vue +65 -65
  52. package/packages/dashboard/src/components/PipelineStage.vue +95 -95
  53. package/packages/dashboard/src/components/PipelineView.vue +156 -156
  54. package/packages/dashboard/src/components/ProjectList.vue +210 -210
  55. package/packages/dashboard/src/components/StageBadge.vue +67 -67
  56. package/packages/dashboard/src/components/StepCard.vue +94 -94
  57. package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -48
  58. package/packages/dashboard/src/components/detail/GitDetail.vue +61 -61
  59. package/packages/dashboard/src/components/detail/TechDetail.vue +43 -43
  60. package/packages/dashboard/src/composables/useDashboard.js +170 -170
  61. package/packages/dashboard/src/composables/useKeyboard.js +119 -119
  62. package/packages/dashboard/src/composables/useWebSocket.js +129 -129
  63. package/packages/dashboard/src/main.js +8 -8
  64. package/packages/dashboard/src/style.css +132 -132
  65. package/packages/dashboard/vite.config.js +18 -18
  66. package/src/brainstorm-postcheck.js +158 -158
  67. package/src/change-list.js +52 -52
  68. package/src/change-risk-profile.js +352 -352
  69. package/src/classify-change.js +73 -73
  70. package/src/constants.js +70 -70
  71. package/src/contract-matrix.js +278 -278
  72. package/src/db.js +201 -201
  73. package/src/endpoint-extractor.js +315 -315
  74. package/src/hooks/claude-pre-tool-use.cjs +125 -125
  75. package/src/hooks/worktree-guard.js +653 -653
  76. package/src/index.js +922 -900
  77. package/src/init.js +431 -431
  78. package/src/knowledge-match.js +130 -130
  79. package/src/migrate.js +117 -117
  80. package/src/modules.js +482 -482
  81. package/src/progress.js +1734 -1734
  82. package/src/run.js +3465 -3358
  83. package/src/scan-postcheck.js +387 -383
  84. package/src/setup.js +398 -398
  85. package/src/stage-contract.js +700 -700
  86. package/src/stages/archive.js +160 -160
  87. package/src/stages/brainstorm-auto.js +229 -229
  88. package/src/stages/brainstorm.js +645 -645
  89. package/src/stages/doctor.js +365 -365
  90. package/src/stages/execute.js +625 -625
  91. package/src/stages/explore.js +34 -34
  92. package/src/stages/index.js +29 -29
  93. package/src/stages/knowledge.js +498 -498
  94. package/src/stages/plan-postcheck.js +511 -513
  95. package/src/stages/plan.js +582 -582
  96. package/src/stages/propose.js +174 -174
  97. package/src/stages/quick.js +82 -82
  98. package/src/stages/scan.js +558 -558
  99. package/src/stages/status.js +65 -65
  100. package/src/stages/verify.js +322 -322
  101. package/src/sync.js +497 -497
  102. package/src/task-review.js +346 -346
  103. package/src/workflow.js +785 -785
  104. package/src/worktree-apply.js +549 -549
  105. package/src/worktree-deps.js +185 -0
  106. package/src/worktree.js +982 -932
  107. package/templates/workflows/archive-impact.yaml +79 -79
  108. package/templates/workflows/scan-docs.yaml +132 -132
  109. package/test/brainstorm-plan-contract.test.mjs +273 -273
  110. package/test/check-syntax.mjs +26 -26
  111. package/test/contract-artifacts.test.mjs +323 -323
  112. package/test/decision-supersede.test.mjs +277 -277
  113. package/test/knowledge-match.test.mjs +231 -231
  114. package/test/plan-execute-contract.test.mjs +330 -330
  115. package/test/plan-optimization.test.mjs +572 -572
  116. package/test/platform-artifacts.test.mjs +166 -166
  117. package/test/platform-failure-samples.test.mjs +199 -199
  118. package/test/platform-recovery-chain.test.mjs +167 -167
  119. package/test/platform-recovery.test.mjs +136 -136
  120. package/test/platform-scan-p0.test.mjs +168 -168
  121. package/test/revision-v1.test.mjs +1145 -1145
  122. package/test/run-scan-project-parse.test.mjs +200 -200
  123. package/test/run-tests.mjs +48 -48
  124. package/test/scan-knowledge.test.mjs +175 -175
  125. package/test/scan-paths.test.mjs +68 -68
  126. package/test/scan-postcheck.test.mjs +197 -197
  127. package/test/spec-dir.test.mjs +206 -206
  128. package/test/stage-contract.test.mjs +299 -299
  129. package/test/stage-definitions.test.mjs +39 -39
  130. package/test/wait-gates.test.mjs +496 -496
  131. package/test/worktree-deps-provision.test.mjs +148 -0
  132. package/test/worktree-guard.test.mjs +71 -71
  133. package/test/worktree-native-overlay.test.mjs +188 -188
@@ -1,175 +1,175 @@
1
- /**
2
- * P0 补丁验证 — 4 类测试
3
- *
4
- * 1. 平台 scan prompt 不含正向写入 .sillyspec/ 指令
5
- * 2. 安全说明文字不被 prompt 自检误杀
6
- * 3. 平台模式不执行 git add {SPEC_ROOT}
7
- * 4. source_root 污染检查覆盖所有子目录/文件
8
- * 5. run.js 占位符替换补齐(平台+本地)
9
- *
10
- * 跑法: node test/platform-scan-p0.test.mjs
11
- */
12
-
13
- import { join, basename } from 'path'
14
- import { existsSync, mkdirSync, writeFileSync, rmSync, readdirSync } from 'fs'
15
- import { execSync } from 'child_process'
16
- import { readFile } from 'fs/promises'
17
- import { fileURLToPath } from 'url'
18
-
19
- const __dirname = fileURLToPath(new URL('.', import.meta.url))
20
- const passed = []
21
- const failed = []
22
-
23
- function assert(label, condition, detail) {
24
- if (condition) {
25
- passed.push(label)
26
- } else {
27
- failed.push({ label, detail })
28
- }
29
- }
30
-
31
- // ── 测试 1:scan.js 模板不含裸 .sillyspec 输出路径 ──
32
- {
33
- const { definition } = await import('../src/stages/scan.js')
34
- const prompts = definition.steps.map(s => s.prompt).join('\n')
35
-
36
- // 所有 .sillyspec 出现都应该是「禁止说明」,不是写入指令
37
- const writePatterns = [
38
- /write.*\.sillyspec\/docs/i,
39
- /save.*\.sillyspec\/docs/i,
40
- /create.*\.sillyspec\/docs/i,
41
- /mkdir.*\.sillyspec\/docs/i,
42
- ]
43
- for (const p of writePatterns) {
44
- assert(`scan 模板无写入 .sillyspec/docs: ${p}`, !p.test(prompts),
45
- p.test(prompts) ? `命中: ${prompts.match(p)[0]}` : '')
46
- }
47
-
48
- // 应该使用占位符
49
- assert('scan 模板使用 {WORKFLOWS_ROOT}', prompts.includes('{WORKFLOWS_ROOT}'))
50
- assert('scan 模板使用 {SPEC_ROOT}', prompts.includes('{SPEC_ROOT}'))
51
- assert('scan 模板使用 {DOCS_ROOT}', prompts.includes('{DOCS_ROOT}'))
52
-
53
- // 平台模式下 git add 应该是条件判断
54
- assert('scan 模板平台模式跳过 git add', prompts.includes('如果平台模式:跳过 git add'))
55
- assert('scan 模板非平台模式 git add .sillyspec/', prompts.includes('git add .sillyspec/'))
56
- }
57
-
58
- // ── 测试 2:prompt 自检不误杀安全说明 ──
59
- {
60
- // 导入 run.js 中的正则
61
- const writeCtxRe = /(?<!不要|禁止|严禁)(?:save[\s.]+to|write|create|mkdir|git add|写入|保存到|写入到)[^a-zA-Z]*\.sillyspec\/[a-z]/i
62
-
63
- // 安全说明 — 不应命中
64
- const safeLines = [
65
- '严禁写入源码目录或相对路径 `.sillyspec/`',
66
- '⚠️ 不要写入 .sillyspec/docs',
67
- 'source_root 下存在 .sillyspec/docs 文件',
68
- '不允许从 cwd 推导 .sillyspec 路径',
69
- ]
70
- for (const line of safeLines) {
71
- assert(`安全说明不误杀: "${line.slice(0, 40)}"`, !writeCtxRe.test(line),
72
- '误杀! 命中了安全说明文字')
73
- }
74
-
75
- // 写入指令 — 应该命中
76
- const badLines = [
77
- '写入 `.sillyspec/docs/ARCHITECTURE.md`',
78
- 'save to `.sillyspec/docs/ARCHITECTURE.md`',
79
- 'create `.sillyspec/docs/ARCH.md`',
80
- 'git add .sillyspec/docs/',
81
- 'write 到 .sillyspec/docs/',
82
- ]
83
- for (const line of badLines) {
84
- assert(`写入指令应命中: "${line.slice(0, 40)}"`, writeCtxRe.test(line),
85
- '漏杀! 没有捕获写入指令')
86
- }
87
- }
88
-
89
- // ── 测试 3:safeGit 使用 -c safe.directory(不污染全局 config) ──
90
- {
91
- const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
92
-
93
- assert('safeGit 不含 --global', !runSrc.includes('git config --global'),
94
- '发现 --global,会污染容器 git config')
95
-
96
- assert('safeGit 使用 -c safe.directory', runSrc.includes("safe.directory=${cwd}"),
97
- '未发现 -c safe.directory per-command 参数')
98
-
99
- assert('safeGit 使用 -C cwd', runSrc.includes("-C', cwd"),
100
- '未发现 -C cwd 参数')
101
-
102
- assert('safeGit 返回 { value, error }', runSrc.includes("return { value, error: "),
103
- 'safeGit 返回值不是 { value, error } 结构')
104
-
105
- assert('manifest 包含 source_commit_error 字段',
106
- runSrc.includes("source_commit_error:"), 'manifest 缺少 source_commit_error')
107
- }
108
-
109
- // ── 测试 4:postcheck 污染检查覆盖所有子目录 ──
110
- {
111
- const postcheckSrc = await readFile(join(__dirname, '..', 'src', 'scan-postcheck.js'), 'utf8')
112
-
113
- const requiredSubs = ['docs', 'projects', 'workflows', 'knowledge']
114
- for (const sub of requiredSubs) {
115
- assert(`postcheck 检查 ${sub} 污染`,
116
- postcheckSrc.includes(`'${sub}'`) && postcheckSrc.includes("'.sillyspec', sub)"),
117
- `postcheck 未检查 .sillyspec/${sub}/ 污染`)
118
- }
119
-
120
- assert('postcheck 检查 manifest.json', postcheckSrc.includes('manifest.json'))
121
- assert('postcheck 检查 local.yaml', postcheckSrc.includes('local.yaml'))
122
- assert('污染 severity 使用枚举', postcheckSrc.includes('CHECK_SEVERITY'))
123
- }
124
-
125
- // ── 测试 5:run.js 占位符替换补齐 ──
126
- {
127
- const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
128
-
129
- // 平台模式块
130
- const platformMarker = 'promptText.replace(/\\{WORKFLOWS_ROOT\\}'
131
- assert('平台模式替换 {WORKFLOWS_ROOT}', runSrc.includes('{WORKFLOWS_ROOT}') && runSrc.includes('workflowsRoot'))
132
- assert('平台模式替换 {KNOWLEDGE_ROOT}', runSrc.includes('{KNOWLEDGE_ROOT}') && runSrc.includes('knowledgeRoot'))
133
- assert('平台模式替换 {SPEC_ROOT}', runSrc.includes('{SPEC_ROOT}') && runSrc.includes("specSillyspec"))
134
-
135
- // 非平台模式块
136
- assert('非平台模式替换 {WORKFLOWS_ROOT}', runSrc.includes('workflowsRoot'))
137
- assert('非平台模式替换 {KNOWLEDGE_ROOT}', runSrc.includes('knowledgeRoot'))
138
- assert('非平台模式替换 {SPEC_ROOT}', runSrc.includes('{SPEC_ROOT}'))
139
- }
140
-
141
- // ── 测试 6:quick step 1 prompt 强制要求 quicklog ──
142
- {
1
+ /**
2
+ * P0 补丁验证 — 4 类测试
3
+ *
4
+ * 1. 平台 scan prompt 不含正向写入 .sillyspec/ 指令
5
+ * 2. 安全说明文字不被 prompt 自检误杀
6
+ * 3. 平台模式不执行 git add {SPEC_ROOT}
7
+ * 4. source_root 污染检查覆盖所有子目录/文件
8
+ * 5. run.js 占位符替换补齐(平台+本地)
9
+ *
10
+ * 跑法: node test/platform-scan-p0.test.mjs
11
+ */
12
+
13
+ import { join, basename } from 'path'
14
+ import { existsSync, mkdirSync, writeFileSync, rmSync, readdirSync } from 'fs'
15
+ import { execSync } from 'child_process'
16
+ import { readFile } from 'fs/promises'
17
+ import { fileURLToPath } from 'url'
18
+
19
+ const __dirname = fileURLToPath(new URL('.', import.meta.url))
20
+ const passed = []
21
+ const failed = []
22
+
23
+ function assert(label, condition, detail) {
24
+ if (condition) {
25
+ passed.push(label)
26
+ } else {
27
+ failed.push({ label, detail })
28
+ }
29
+ }
30
+
31
+ // ── 测试 1:scan.js 模板不含裸 .sillyspec 输出路径 ──
32
+ {
33
+ const { definition } = await import('../src/stages/scan.js')
34
+ const prompts = definition.steps.map(s => s.prompt).join('\n')
35
+
36
+ // 所有 .sillyspec 出现都应该是「禁止说明」,不是写入指令
37
+ const writePatterns = [
38
+ /write.*\.sillyspec\/docs/i,
39
+ /save.*\.sillyspec\/docs/i,
40
+ /create.*\.sillyspec\/docs/i,
41
+ /mkdir.*\.sillyspec\/docs/i,
42
+ ]
43
+ for (const p of writePatterns) {
44
+ assert(`scan 模板无写入 .sillyspec/docs: ${p}`, !p.test(prompts),
45
+ p.test(prompts) ? `命中: ${prompts.match(p)[0]}` : '')
46
+ }
47
+
48
+ // 应该使用占位符
49
+ assert('scan 模板使用 {WORKFLOWS_ROOT}', prompts.includes('{WORKFLOWS_ROOT}'))
50
+ assert('scan 模板使用 {SPEC_ROOT}', prompts.includes('{SPEC_ROOT}'))
51
+ assert('scan 模板使用 {DOCS_ROOT}', prompts.includes('{DOCS_ROOT}'))
52
+
53
+ // 平台模式下 git add 应该是条件判断
54
+ assert('scan 模板平台模式跳过 git add', prompts.includes('如果平台模式:跳过 git add'))
55
+ assert('scan 模板非平台模式 git add .sillyspec/', prompts.includes('git add .sillyspec/'))
56
+ }
57
+
58
+ // ── 测试 2:prompt 自检不误杀安全说明 ──
59
+ {
60
+ // 导入 run.js 中的正则
61
+ const writeCtxRe = /(?<!不要|禁止|严禁)(?:save[\s.]+to|write|create|mkdir|git add|写入|保存到|写入到)[^a-zA-Z]*\.sillyspec\/[a-z]/i
62
+
63
+ // 安全说明 — 不应命中
64
+ const safeLines = [
65
+ '严禁写入源码目录或相对路径 `.sillyspec/`',
66
+ '⚠️ 不要写入 .sillyspec/docs',
67
+ 'source_root 下存在 .sillyspec/docs 文件',
68
+ '不允许从 cwd 推导 .sillyspec 路径',
69
+ ]
70
+ for (const line of safeLines) {
71
+ assert(`安全说明不误杀: "${line.slice(0, 40)}"`, !writeCtxRe.test(line),
72
+ '误杀! 命中了安全说明文字')
73
+ }
74
+
75
+ // 写入指令 — 应该命中
76
+ const badLines = [
77
+ '写入 `.sillyspec/docs/ARCHITECTURE.md`',
78
+ 'save to `.sillyspec/docs/ARCHITECTURE.md`',
79
+ 'create `.sillyspec/docs/ARCH.md`',
80
+ 'git add .sillyspec/docs/',
81
+ 'write 到 .sillyspec/docs/',
82
+ ]
83
+ for (const line of badLines) {
84
+ assert(`写入指令应命中: "${line.slice(0, 40)}"`, writeCtxRe.test(line),
85
+ '漏杀! 没有捕获写入指令')
86
+ }
87
+ }
88
+
89
+ // ── 测试 3:safeGit 使用 -c safe.directory(不污染全局 config) ──
90
+ {
91
+ const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
92
+
93
+ assert('safeGit 不含 --global', !runSrc.includes('git config --global'),
94
+ '发现 --global,会污染容器 git config')
95
+
96
+ assert('safeGit 使用 -c safe.directory', runSrc.includes("safe.directory=${cwd}"),
97
+ '未发现 -c safe.directory per-command 参数')
98
+
99
+ assert('safeGit 使用 -C cwd', runSrc.includes("-C', cwd"),
100
+ '未发现 -C cwd 参数')
101
+
102
+ assert('safeGit 返回 { value, error }', runSrc.includes("return { value, error: "),
103
+ 'safeGit 返回值不是 { value, error } 结构')
104
+
105
+ assert('manifest 包含 source_commit_error 字段',
106
+ runSrc.includes("source_commit_error:"), 'manifest 缺少 source_commit_error')
107
+ }
108
+
109
+ // ── 测试 4:postcheck 污染检查覆盖所有子目录 ──
110
+ {
111
+ const postcheckSrc = await readFile(join(__dirname, '..', 'src', 'scan-postcheck.js'), 'utf8')
112
+
113
+ const requiredSubs = ['docs', 'projects', 'workflows', 'knowledge']
114
+ for (const sub of requiredSubs) {
115
+ assert(`postcheck 检查 ${sub} 污染`,
116
+ postcheckSrc.includes(`'${sub}'`) && postcheckSrc.includes("'.sillyspec', sub)"),
117
+ `postcheck 未检查 .sillyspec/${sub}/ 污染`)
118
+ }
119
+
120
+ assert('postcheck 检查 manifest.json', postcheckSrc.includes('manifest.json'))
121
+ assert('postcheck 检查 local.yaml', postcheckSrc.includes('local.yaml'))
122
+ assert('污染 severity 使用枚举', postcheckSrc.includes('CHECK_SEVERITY'))
123
+ }
124
+
125
+ // ── 测试 5:run.js 占位符替换补齐 ──
126
+ {
127
+ const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
128
+
129
+ // 平台模式块
130
+ const platformMarker = 'promptText.replace(/\\{WORKFLOWS_ROOT\\}'
131
+ assert('平台模式替换 {WORKFLOWS_ROOT}', runSrc.includes('{WORKFLOWS_ROOT}') && runSrc.includes('workflowsRoot'))
132
+ assert('平台模式替换 {KNOWLEDGE_ROOT}', runSrc.includes('{KNOWLEDGE_ROOT}') && runSrc.includes('knowledgeRoot'))
133
+ assert('平台模式替换 {SPEC_ROOT}', runSrc.includes('{SPEC_ROOT}') && runSrc.includes("specSillyspec"))
134
+
135
+ // 非平台模式块
136
+ assert('非平台模式替换 {WORKFLOWS_ROOT}', runSrc.includes('workflowsRoot'))
137
+ assert('非平台模式替换 {KNOWLEDGE_ROOT}', runSrc.includes('knowledgeRoot'))
138
+ assert('非平台模式替换 {SPEC_ROOT}', runSrc.includes('{SPEC_ROOT}'))
139
+ }
140
+
141
+ // ── 测试 6:quick step 1 prompt 强制要求 quicklog ──
142
+ {
143
143
  const { definition } = await import('../src/stages/quick.js')
144
144
  const step1Prompt = definition.steps[0].prompt
145
145
  const step3Prompt = definition.steps[2].prompt
146
-
147
- assert('quick step 1 包含 ⛔ 标记', step1Prompt.includes('⛔'))
148
- assert('quick step 1 包含「不能跳过」', step1Prompt.includes('不能跳过'))
146
+
147
+ assert('quick step 1 包含 ⛔ 标记', step1Prompt.includes('⛔'))
148
+ assert('quick step 1 包含「不能跳过」', step1Prompt.includes('不能跳过'))
149
149
  assert('quick step 1 包含 quicklog 未创建 warning', step1Prompt.includes('quicklog 未创建'))
150
150
  assert('quick step 1 输出要求 quicklog 第一行', step1Prompt.includes('第一行确认'))
151
151
  assert('quick step 3 禁止 git add -A', step3Prompt.includes('禁止使用 `git add -A`'))
152
152
  assert('quick step 3 使用 scoped git add', step3Prompt.includes('git add -- <file...>'))
153
-
154
- // run.js 审计包含 quicklog 检查
155
- const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
156
- assert('quick 审计检查 quicklog 目录存在', runSrc.includes('quicklog 目录不存在'))
157
- assert('quick 审计检查 quicklog 为空', runSrc.includes('quicklog 目录为空'))
158
- }
159
-
160
- // ── 结果 ──
161
- console.log(`\n${'='.repeat(50)}`)
162
- console.log(`✅ 通过: ${passed.length}`)
163
- console.log(`❌ 失败: ${failed.length}`)
164
- console.log(`${'='.repeat(50)}`)
165
-
166
- if (failed.length > 0) {
167
- console.log('\n失败详情:')
168
- for (const f of failed) {
169
- console.log(` ❌ ${f.label}`)
170
- if (f.detail) console.log(` ${f.detail}`)
171
- }
172
- throw new Error("test failed")
173
- } else {
174
- console.log('\n🎉 全部 P0 测试通过!')
175
- }
153
+
154
+ // run.js 审计包含 quicklog 检查
155
+ const runSrc = await readFile(join(__dirname, '..', 'src', 'run.js'), 'utf8')
156
+ assert('quick 审计检查 quicklog 目录存在', runSrc.includes('quicklog 目录不存在'))
157
+ assert('quick 审计检查 quicklog 为空', runSrc.includes('quicklog 目录为空'))
158
+ }
159
+
160
+ // ── 结果 ──
161
+ console.log(`\n${'='.repeat(50)}`)
162
+ console.log(`✅ 通过: ${passed.length}`)
163
+ console.log(`❌ 失败: ${failed.length}`)
164
+ console.log(`${'='.repeat(50)}`)
165
+
166
+ if (failed.length > 0) {
167
+ console.log('\n失败详情:')
168
+ for (const f of failed) {
169
+ console.log(` ❌ ${f.label}`)
170
+ if (f.detail) console.log(` ${f.detail}`)
171
+ }
172
+ throw new Error("test failed")
173
+ } else {
174
+ console.log('\n🎉 全部 P0 测试通过!')
175
+ }