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.
- package/.claude/skills/sillyspec-archive/SKILL.md +21 -21
- package/.claude/skills/sillyspec-auto/SKILL.md +83 -83
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +44 -44
- package/.claude/skills/sillyspec-commit/SKILL.md +106 -106
- package/.claude/skills/sillyspec-continue/SKILL.md +45 -45
- package/.claude/skills/sillyspec-doctor/SKILL.md +31 -31
- package/.claude/skills/sillyspec-execute/SKILL.md +30 -30
- package/.claude/skills/sillyspec-explore/SKILL.md +109 -109
- package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
- package/.claude/skills/sillyspec-plan/SKILL.md +21 -21
- package/.claude/skills/sillyspec-propose/SKILL.md +21 -21
- package/.claude/skills/sillyspec-quick/SKILL.md +21 -21
- package/.claude/skills/sillyspec-resume/SKILL.md +68 -68
- package/.claude/skills/sillyspec-scan/SKILL.md +21 -21
- package/.claude/skills/sillyspec-state/SKILL.md +54 -54
- package/.claude/skills/sillyspec-status/SKILL.md +21 -21
- package/.claude/skills/sillyspec-verify/SKILL.md +21 -21
- package/.claude/skills/sillyspec-workspace/SKILL.md +157 -157
- package/.husky/pre-push +13 -13
- package/CLAUDE.md +18 -18
- package/README.md +198 -188
- package/SKILL.md +90 -91
- package/bin/sillyspec.js +2 -2
- package/docs/brainstorm-plan-contract.md +64 -64
- package/docs/plan-execute-contract.md +123 -123
- package/docs/platform-scan-protocol.md +298 -298
- package/docs/revision-mode.md +115 -115
- package/docs/sillyspec/file-lifecycle/known-implementation-gaps.md +99 -99
- package/docs/sillyspec/file-lifecycle/platform-workflows-sync.md +218 -218
- package/docs/sillyspec/file-lifecycle/stage-artifacts.md +167 -167
- package/docs/sillyspec/file-lifecycle/storage-and-state.md +148 -148
- package/docs/sillyspec/file-lifecycle/worktree-and-guard.md +211 -193
- package/docs/sillyspec/file-lifecycle.md +125 -125
- package/docs/workflow-contract-regression.md +106 -106
- package/docs/worktree-isolation.md +252 -252
- package/package.json +40 -40
- package/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -7446
- package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -1
- package/packages/dashboard/dist/index.html +16 -16
- package/packages/dashboard/index.html +15 -15
- package/packages/dashboard/package-lock.json +2384 -2384
- package/packages/dashboard/package.json +25 -25
- package/packages/dashboard/server/executor.js +86 -86
- package/packages/dashboard/server/index.js +588 -588
- package/packages/dashboard/server/parser.js +526 -526
- package/packages/dashboard/server/watcher.js +344 -344
- package/packages/dashboard/src/App.vue +558 -558
- package/packages/dashboard/src/components/ActionBar.vue +93 -93
- package/packages/dashboard/src/components/CommandPalette.vue +96 -96
- package/packages/dashboard/src/components/DetailPanel.vue +137 -137
- package/packages/dashboard/src/components/LogStream.vue +65 -65
- package/packages/dashboard/src/components/PipelineStage.vue +95 -95
- package/packages/dashboard/src/components/PipelineView.vue +156 -156
- package/packages/dashboard/src/components/ProjectList.vue +210 -210
- package/packages/dashboard/src/components/StageBadge.vue +67 -67
- package/packages/dashboard/src/components/StepCard.vue +94 -94
- package/packages/dashboard/src/components/detail/DocsDetail.vue +48 -48
- package/packages/dashboard/src/components/detail/GitDetail.vue +61 -61
- package/packages/dashboard/src/components/detail/TechDetail.vue +43 -43
- package/packages/dashboard/src/composables/useDashboard.js +170 -170
- package/packages/dashboard/src/composables/useKeyboard.js +119 -119
- package/packages/dashboard/src/composables/useWebSocket.js +129 -129
- package/packages/dashboard/src/main.js +8 -8
- package/packages/dashboard/src/style.css +132 -132
- package/packages/dashboard/vite.config.js +18 -18
- package/src/brainstorm-postcheck.js +158 -158
- package/src/change-list.js +52 -52
- package/src/change-risk-profile.js +352 -352
- package/src/classify-change.js +73 -73
- package/src/constants.js +70 -70
- package/src/contract-matrix.js +278 -278
- package/src/db.js +201 -201
- package/src/endpoint-extractor.js +315 -315
- package/src/hooks/claude-pre-tool-use.cjs +125 -125
- package/src/hooks/worktree-guard.js +653 -653
- package/src/index.js +922 -900
- package/src/init.js +431 -431
- package/src/knowledge-match.js +130 -130
- package/src/migrate.js +117 -117
- package/src/modules.js +482 -482
- package/src/progress.js +1734 -1734
- package/src/run.js +3465 -3358
- package/src/scan-postcheck.js +387 -383
- package/src/setup.js +398 -398
- package/src/stage-contract.js +700 -700
- package/src/stages/archive.js +160 -160
- package/src/stages/brainstorm-auto.js +229 -229
- package/src/stages/brainstorm.js +645 -645
- package/src/stages/doctor.js +365 -365
- package/src/stages/execute.js +625 -625
- package/src/stages/explore.js +34 -34
- package/src/stages/index.js +29 -29
- package/src/stages/knowledge.js +498 -498
- package/src/stages/plan-postcheck.js +511 -513
- package/src/stages/plan.js +582 -582
- package/src/stages/propose.js +174 -174
- package/src/stages/quick.js +82 -82
- package/src/stages/scan.js +558 -558
- package/src/stages/status.js +65 -65
- package/src/stages/verify.js +322 -322
- package/src/sync.js +497 -497
- package/src/task-review.js +346 -346
- package/src/workflow.js +785 -785
- package/src/worktree-apply.js +549 -549
- package/src/worktree-deps.js +185 -0
- package/src/worktree.js +982 -932
- package/templates/workflows/archive-impact.yaml +79 -79
- package/templates/workflows/scan-docs.yaml +132 -132
- package/test/brainstorm-plan-contract.test.mjs +273 -273
- package/test/check-syntax.mjs +26 -26
- package/test/contract-artifacts.test.mjs +323 -323
- package/test/decision-supersede.test.mjs +277 -277
- package/test/knowledge-match.test.mjs +231 -231
- package/test/plan-execute-contract.test.mjs +330 -330
- package/test/plan-optimization.test.mjs +572 -572
- package/test/platform-artifacts.test.mjs +166 -166
- package/test/platform-failure-samples.test.mjs +199 -199
- package/test/platform-recovery-chain.test.mjs +167 -167
- package/test/platform-recovery.test.mjs +136 -136
- package/test/platform-scan-p0.test.mjs +168 -168
- package/test/revision-v1.test.mjs +1145 -1145
- package/test/run-scan-project-parse.test.mjs +200 -200
- package/test/run-tests.mjs +48 -48
- package/test/scan-knowledge.test.mjs +175 -175
- package/test/scan-paths.test.mjs +68 -68
- package/test/scan-postcheck.test.mjs +197 -197
- package/test/spec-dir.test.mjs +206 -206
- package/test/stage-contract.test.mjs +299 -299
- package/test/stage-definitions.test.mjs +39 -39
- package/test/wait-gates.test.mjs +496 -496
- package/test/worktree-deps-provision.test.mjs +148 -0
- package/test/worktree-guard.test.mjs +71 -71
- package/test/worktree-native-overlay.test.mjs +188 -188
|
@@ -1,273 +1,273 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Brainstorm → Plan Contract v1 测试
|
|
3
|
-
*
|
|
4
|
-
* 验证 design.md 到 plan 的输入契约:
|
|
5
|
-
* 1. 合法 design 通过
|
|
6
|
-
* 2. 缺关键章节失败
|
|
7
|
-
* 3. warning 不阻断
|
|
8
|
-
*/
|
|
9
|
-
import { validateDesignForPlan } from '../src/stages/plan.js'
|
|
10
|
-
|
|
11
|
-
let failed = 0
|
|
12
|
-
const failures = []
|
|
13
|
-
|
|
14
|
-
function assert(condition, msg) {
|
|
15
|
-
if (!condition) {
|
|
16
|
-
failed++
|
|
17
|
-
failures.push(msg)
|
|
18
|
-
console.log(` ❌ FAIL: ${msg}`)
|
|
19
|
-
} else {
|
|
20
|
-
console.log(` ✅ PASS: ${msg}`)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
console.log('=== Brainstorm → Plan Contract v1 测试 ===\n')
|
|
25
|
-
|
|
26
|
-
// ─────────────────────────────────────────
|
|
27
|
-
// Case 1: valid design 通过
|
|
28
|
-
// ─────────────────────────────────────────
|
|
29
|
-
console.log('--- Case 1: valid design 通过 ---')
|
|
30
|
-
{
|
|
31
|
-
const design = `# Design: 用户认证系统
|
|
32
|
-
|
|
33
|
-
## 背景
|
|
34
|
-
需要实现用户认证。
|
|
35
|
-
|
|
36
|
-
## 设计目标
|
|
37
|
-
- 支持 OAuth2
|
|
38
|
-
- 支持手机号登录
|
|
39
|
-
|
|
40
|
-
## 非目标
|
|
41
|
-
- 不做 SSO
|
|
42
|
-
|
|
43
|
-
## 总体方案
|
|
44
|
-
使用 JWT + Refresh Token。
|
|
45
|
-
|
|
46
|
-
## 决策
|
|
47
|
-
- D-001@v1: 选择 JWT 而非 Session
|
|
48
|
-
|
|
49
|
-
## 约束
|
|
50
|
-
- 必须兼容现有 API
|
|
51
|
-
|
|
52
|
-
## 文件变更清单
|
|
53
|
-
| 操作 | 文件路径 | 说明 |
|
|
54
|
-
|------|---------|------|
|
|
55
|
-
| 新增 | src/auth.js | 认证模块 |
|
|
56
|
-
`
|
|
57
|
-
const result = validateDesignForPlan(design)
|
|
58
|
-
assert(result.ok, '完整 design 应校验通过')
|
|
59
|
-
assert(result.errors.length === 0, '不应有 errors')
|
|
60
|
-
assert(result.warnings.length === 0, '不应有 warnings')
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ─────────────────────────────────────────
|
|
64
|
-
// Case 2: empty design 失败
|
|
65
|
-
// ─────────────────────────────────────────
|
|
66
|
-
console.log('\n--- Case 2: empty design 失败 ---')
|
|
67
|
-
{
|
|
68
|
-
assert(!validateDesignForPlan('').ok, '空字符串应失败')
|
|
69
|
-
assert(!validateDesignForPlan(null).ok, 'null 应失败')
|
|
70
|
-
assert(!validateDesignForPlan(' ').ok, '纯空格应失败')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ─────────────────────────────────────────
|
|
74
|
-
// Case 3: missing goal 失败
|
|
75
|
-
// ─────────────────────────────────────────
|
|
76
|
-
console.log('\n--- Case 3: missing goal/背景 失败 ---')
|
|
77
|
-
{
|
|
78
|
-
const design = `# Design
|
|
79
|
-
|
|
80
|
-
## 总体方案
|
|
81
|
-
用 JWT。
|
|
82
|
-
|
|
83
|
-
## 决策
|
|
84
|
-
D-001@v1: 选 JWT
|
|
85
|
-
`
|
|
86
|
-
const result = validateDesignForPlan(design)
|
|
87
|
-
assert(!result.ok, '缺目标/背景应失败')
|
|
88
|
-
assert(result.errors.some(e => e.includes('目标') || e.includes('背景')), '错误应提到目标/背景')
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ─────────────────────────────────────────
|
|
92
|
-
// Case 4: missing scope/方案 失败
|
|
93
|
-
// ─────────────────────────────────────────
|
|
94
|
-
console.log('\n--- Case 4: missing scope/方案 失败 ---')
|
|
95
|
-
{
|
|
96
|
-
const design = `# Design
|
|
97
|
-
|
|
98
|
-
## 背景
|
|
99
|
-
需要认证。
|
|
100
|
-
|
|
101
|
-
## 决策
|
|
102
|
-
D-001@v1: 选 JWT
|
|
103
|
-
`
|
|
104
|
-
const result = validateDesignForPlan(design)
|
|
105
|
-
assert(!result.ok, '缺范围/方案应失败')
|
|
106
|
-
assert(result.errors.some(e => e.includes('范围') || e.includes('方案')), '错误应提到范围/方案')
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// ─────────────────────────────────────────
|
|
110
|
-
// Case 5: missing decisions 失败
|
|
111
|
-
// ─────────────────────────────────────────
|
|
112
|
-
console.log('\n--- Case 5: missing decisions 失败 ---')
|
|
113
|
-
{
|
|
114
|
-
const design = `# Design
|
|
115
|
-
|
|
116
|
-
## 背景
|
|
117
|
-
需要认证。
|
|
118
|
-
|
|
119
|
-
## 总体方案
|
|
120
|
-
用 JWT。
|
|
121
|
-
`
|
|
122
|
-
const result = validateDesignForPlan(design)
|
|
123
|
-
assert(!result.ok, '缺决策应失败')
|
|
124
|
-
assert(result.errors.some(e => e.includes('决策')), '错误应提到决策')
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// ─────────────────────────────────────────
|
|
128
|
-
// Case 6: decisions.md 引用也算决策
|
|
129
|
-
// ─────────────────────────────────────────
|
|
130
|
-
console.log('\n--- Case 6: decisions.md 引用算决策 ---')
|
|
131
|
-
{
|
|
132
|
-
const design = `# Design
|
|
133
|
-
|
|
134
|
-
## 背景
|
|
135
|
-
需要认证。
|
|
136
|
-
|
|
137
|
-
## 总体方案
|
|
138
|
-
用 JWT。详见 decisions.md。
|
|
139
|
-
|
|
140
|
-
## 文件变更清单
|
|
141
|
-
| 操作 | 文件 | 说明 |
|
|
142
|
-
`
|
|
143
|
-
const result = validateDesignForPlan(design)
|
|
144
|
-
assert(result.ok, 'decisions.md 引用应满足决策检查')
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// ─────────────────────────────────────────
|
|
148
|
-
// Case 7: missing non-goals 只有 warning
|
|
149
|
-
// ─────────────────────────────────────────
|
|
150
|
-
console.log('\n--- Case 7: missing non-goals warning ---')
|
|
151
|
-
{
|
|
152
|
-
const design = `# Design
|
|
153
|
-
|
|
154
|
-
## 背景
|
|
155
|
-
需要认证。
|
|
156
|
-
|
|
157
|
-
## 总体方案
|
|
158
|
-
用 JWT。
|
|
159
|
-
|
|
160
|
-
## 决策
|
|
161
|
-
D-001@v1: 选 JWT
|
|
162
|
-
|
|
163
|
-
## 约束
|
|
164
|
-
必须兼容现有 API。
|
|
165
|
-
`
|
|
166
|
-
const result = validateDesignForPlan(design)
|
|
167
|
-
assert(result.ok, '缺非目标不应阻断')
|
|
168
|
-
assert(result.warnings.some(w => w.includes('非目标') || w.includes('Non-goals')), '应有非目标 warning')
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ─────────────────────────────────────────
|
|
172
|
-
// Case 8: missing constraints 只有 warning
|
|
173
|
-
// ─────────────────────────────────────────
|
|
174
|
-
console.log('\n--- Case 8: missing constraints warning ---')
|
|
175
|
-
{
|
|
176
|
-
const design = `# Design
|
|
177
|
-
|
|
178
|
-
## 目标
|
|
179
|
-
实现认证。
|
|
180
|
-
|
|
181
|
-
## 设计方案
|
|
182
|
-
用 JWT。
|
|
183
|
-
|
|
184
|
-
## 决策
|
|
185
|
-
选择 JWT。
|
|
186
|
-
|
|
187
|
-
## 非目标
|
|
188
|
-
不做 SSO。
|
|
189
|
-
`
|
|
190
|
-
const result = validateDesignForPlan(design)
|
|
191
|
-
assert(result.ok, '缺约束不应阻断')
|
|
192
|
-
assert(result.warnings.some(w => w.includes('约束') || w.includes('风险') || w.includes('Trade-off')), '应有约束/风险 warning')
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// ─────────────────────────────────────────
|
|
196
|
-
// Case 9: missing 文件变更清单 warning
|
|
197
|
-
// ─────────────────────────────────────────
|
|
198
|
-
console.log('\n--- Case 9: missing 文件变更清单 warning ---')
|
|
199
|
-
{
|
|
200
|
-
const design = `# Design
|
|
201
|
-
|
|
202
|
-
## 背景
|
|
203
|
-
需要认证。
|
|
204
|
-
|
|
205
|
-
## 总体方案
|
|
206
|
-
用 JWT。
|
|
207
|
-
|
|
208
|
-
## 决策
|
|
209
|
-
D-001@v1: 选 JWT
|
|
210
|
-
`
|
|
211
|
-
const result = validateDesignForPlan(design)
|
|
212
|
-
assert(result.ok, '缺文件变更清单不应阻断')
|
|
213
|
-
assert(result.warnings.some(w => w.includes('文件变更')), '应有文件变更 warning')
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// ─────────────────────────────────────────
|
|
217
|
-
// Case 10: 英文 design 通过
|
|
218
|
-
// ─────────────────────────────────────────
|
|
219
|
-
console.log('\n--- Case 10: 英文 design 通过 ---')
|
|
220
|
-
{
|
|
221
|
-
const design = `# Design: Auth System
|
|
222
|
-
|
|
223
|
-
## Background
|
|
224
|
-
We need authentication.
|
|
225
|
-
|
|
226
|
-
## Solution
|
|
227
|
-
Use JWT + Refresh Token.
|
|
228
|
-
|
|
229
|
-
## Decision
|
|
230
|
-
D-001@v1: Choose JWT over Session
|
|
231
|
-
|
|
232
|
-
## Non-goals
|
|
233
|
-
No SSO.
|
|
234
|
-
|
|
235
|
-
## Constraints
|
|
236
|
-
Must be backwards compatible.
|
|
237
|
-
`
|
|
238
|
-
const result = validateDesignForPlan(design)
|
|
239
|
-
assert(result.ok, '英文 design 应校验通过')
|
|
240
|
-
assert(result.errors.length === 0, '不应有 errors')
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ─────────────────────────────────────────
|
|
244
|
-
// Case 11: 最小合法 design
|
|
245
|
-
// ─────────────────────────────────────────
|
|
246
|
-
console.log('\n--- Case 11: 最小合法 design ---')
|
|
247
|
-
{
|
|
248
|
-
const design = `# Design
|
|
249
|
-
|
|
250
|
-
## 目标
|
|
251
|
-
修 bug。
|
|
252
|
-
|
|
253
|
-
## 方案
|
|
254
|
-
改代码。
|
|
255
|
-
|
|
256
|
-
## 决策
|
|
257
|
-
D-001@v1: 直接改。
|
|
258
|
-
`
|
|
259
|
-
const result = validateDesignForPlan(design)
|
|
260
|
-
assert(result.ok, '最小合法 design 应通过')
|
|
261
|
-
// 可能有 warning 但 ok
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// ── 结果 ──
|
|
265
|
-
console.log(`\n${'='.repeat(50)}`)
|
|
266
|
-
console.log(`✅ 通过: ${11 - failed} ❌ 失败: ${failed}`)
|
|
267
|
-
if (failures.length > 0) {
|
|
268
|
-
console.log(`失败项:`)
|
|
269
|
-
failures.forEach(f => console.log(` - ${f}`))
|
|
270
|
-
}
|
|
271
|
-
console.log(`${'='.repeat(50)}`)
|
|
272
|
-
|
|
273
|
-
if (failed > 0) process.exit(1)
|
|
1
|
+
/**
|
|
2
|
+
* Brainstorm → Plan Contract v1 测试
|
|
3
|
+
*
|
|
4
|
+
* 验证 design.md 到 plan 的输入契约:
|
|
5
|
+
* 1. 合法 design 通过
|
|
6
|
+
* 2. 缺关键章节失败
|
|
7
|
+
* 3. warning 不阻断
|
|
8
|
+
*/
|
|
9
|
+
import { validateDesignForPlan } from '../src/stages/plan.js'
|
|
10
|
+
|
|
11
|
+
let failed = 0
|
|
12
|
+
const failures = []
|
|
13
|
+
|
|
14
|
+
function assert(condition, msg) {
|
|
15
|
+
if (!condition) {
|
|
16
|
+
failed++
|
|
17
|
+
failures.push(msg)
|
|
18
|
+
console.log(` ❌ FAIL: ${msg}`)
|
|
19
|
+
} else {
|
|
20
|
+
console.log(` ✅ PASS: ${msg}`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log('=== Brainstorm → Plan Contract v1 测试 ===\n')
|
|
25
|
+
|
|
26
|
+
// ─────────────────────────────────────────
|
|
27
|
+
// Case 1: valid design 通过
|
|
28
|
+
// ─────────────────────────────────────────
|
|
29
|
+
console.log('--- Case 1: valid design 通过 ---')
|
|
30
|
+
{
|
|
31
|
+
const design = `# Design: 用户认证系统
|
|
32
|
+
|
|
33
|
+
## 背景
|
|
34
|
+
需要实现用户认证。
|
|
35
|
+
|
|
36
|
+
## 设计目标
|
|
37
|
+
- 支持 OAuth2
|
|
38
|
+
- 支持手机号登录
|
|
39
|
+
|
|
40
|
+
## 非目标
|
|
41
|
+
- 不做 SSO
|
|
42
|
+
|
|
43
|
+
## 总体方案
|
|
44
|
+
使用 JWT + Refresh Token。
|
|
45
|
+
|
|
46
|
+
## 决策
|
|
47
|
+
- D-001@v1: 选择 JWT 而非 Session
|
|
48
|
+
|
|
49
|
+
## 约束
|
|
50
|
+
- 必须兼容现有 API
|
|
51
|
+
|
|
52
|
+
## 文件变更清单
|
|
53
|
+
| 操作 | 文件路径 | 说明 |
|
|
54
|
+
|------|---------|------|
|
|
55
|
+
| 新增 | src/auth.js | 认证模块 |
|
|
56
|
+
`
|
|
57
|
+
const result = validateDesignForPlan(design)
|
|
58
|
+
assert(result.ok, '完整 design 应校验通过')
|
|
59
|
+
assert(result.errors.length === 0, '不应有 errors')
|
|
60
|
+
assert(result.warnings.length === 0, '不应有 warnings')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─────────────────────────────────────────
|
|
64
|
+
// Case 2: empty design 失败
|
|
65
|
+
// ─────────────────────────────────────────
|
|
66
|
+
console.log('\n--- Case 2: empty design 失败 ---')
|
|
67
|
+
{
|
|
68
|
+
assert(!validateDesignForPlan('').ok, '空字符串应失败')
|
|
69
|
+
assert(!validateDesignForPlan(null).ok, 'null 应失败')
|
|
70
|
+
assert(!validateDesignForPlan(' ').ok, '纯空格应失败')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─────────────────────────────────────────
|
|
74
|
+
// Case 3: missing goal 失败
|
|
75
|
+
// ─────────────────────────────────────────
|
|
76
|
+
console.log('\n--- Case 3: missing goal/背景 失败 ---')
|
|
77
|
+
{
|
|
78
|
+
const design = `# Design
|
|
79
|
+
|
|
80
|
+
## 总体方案
|
|
81
|
+
用 JWT。
|
|
82
|
+
|
|
83
|
+
## 决策
|
|
84
|
+
D-001@v1: 选 JWT
|
|
85
|
+
`
|
|
86
|
+
const result = validateDesignForPlan(design)
|
|
87
|
+
assert(!result.ok, '缺目标/背景应失败')
|
|
88
|
+
assert(result.errors.some(e => e.includes('目标') || e.includes('背景')), '错误应提到目标/背景')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ─────────────────────────────────────────
|
|
92
|
+
// Case 4: missing scope/方案 失败
|
|
93
|
+
// ─────────────────────────────────────────
|
|
94
|
+
console.log('\n--- Case 4: missing scope/方案 失败 ---')
|
|
95
|
+
{
|
|
96
|
+
const design = `# Design
|
|
97
|
+
|
|
98
|
+
## 背景
|
|
99
|
+
需要认证。
|
|
100
|
+
|
|
101
|
+
## 决策
|
|
102
|
+
D-001@v1: 选 JWT
|
|
103
|
+
`
|
|
104
|
+
const result = validateDesignForPlan(design)
|
|
105
|
+
assert(!result.ok, '缺范围/方案应失败')
|
|
106
|
+
assert(result.errors.some(e => e.includes('范围') || e.includes('方案')), '错误应提到范围/方案')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ─────────────────────────────────────────
|
|
110
|
+
// Case 5: missing decisions 失败
|
|
111
|
+
// ─────────────────────────────────────────
|
|
112
|
+
console.log('\n--- Case 5: missing decisions 失败 ---')
|
|
113
|
+
{
|
|
114
|
+
const design = `# Design
|
|
115
|
+
|
|
116
|
+
## 背景
|
|
117
|
+
需要认证。
|
|
118
|
+
|
|
119
|
+
## 总体方案
|
|
120
|
+
用 JWT。
|
|
121
|
+
`
|
|
122
|
+
const result = validateDesignForPlan(design)
|
|
123
|
+
assert(!result.ok, '缺决策应失败')
|
|
124
|
+
assert(result.errors.some(e => e.includes('决策')), '错误应提到决策')
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─────────────────────────────────────────
|
|
128
|
+
// Case 6: decisions.md 引用也算决策
|
|
129
|
+
// ─────────────────────────────────────────
|
|
130
|
+
console.log('\n--- Case 6: decisions.md 引用算决策 ---')
|
|
131
|
+
{
|
|
132
|
+
const design = `# Design
|
|
133
|
+
|
|
134
|
+
## 背景
|
|
135
|
+
需要认证。
|
|
136
|
+
|
|
137
|
+
## 总体方案
|
|
138
|
+
用 JWT。详见 decisions.md。
|
|
139
|
+
|
|
140
|
+
## 文件变更清单
|
|
141
|
+
| 操作 | 文件 | 说明 |
|
|
142
|
+
`
|
|
143
|
+
const result = validateDesignForPlan(design)
|
|
144
|
+
assert(result.ok, 'decisions.md 引用应满足决策检查')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ─────────────────────────────────────────
|
|
148
|
+
// Case 7: missing non-goals 只有 warning
|
|
149
|
+
// ─────────────────────────────────────────
|
|
150
|
+
console.log('\n--- Case 7: missing non-goals warning ---')
|
|
151
|
+
{
|
|
152
|
+
const design = `# Design
|
|
153
|
+
|
|
154
|
+
## 背景
|
|
155
|
+
需要认证。
|
|
156
|
+
|
|
157
|
+
## 总体方案
|
|
158
|
+
用 JWT。
|
|
159
|
+
|
|
160
|
+
## 决策
|
|
161
|
+
D-001@v1: 选 JWT
|
|
162
|
+
|
|
163
|
+
## 约束
|
|
164
|
+
必须兼容现有 API。
|
|
165
|
+
`
|
|
166
|
+
const result = validateDesignForPlan(design)
|
|
167
|
+
assert(result.ok, '缺非目标不应阻断')
|
|
168
|
+
assert(result.warnings.some(w => w.includes('非目标') || w.includes('Non-goals')), '应有非目标 warning')
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ─────────────────────────────────────────
|
|
172
|
+
// Case 8: missing constraints 只有 warning
|
|
173
|
+
// ─────────────────────────────────────────
|
|
174
|
+
console.log('\n--- Case 8: missing constraints warning ---')
|
|
175
|
+
{
|
|
176
|
+
const design = `# Design
|
|
177
|
+
|
|
178
|
+
## 目标
|
|
179
|
+
实现认证。
|
|
180
|
+
|
|
181
|
+
## 设计方案
|
|
182
|
+
用 JWT。
|
|
183
|
+
|
|
184
|
+
## 决策
|
|
185
|
+
选择 JWT。
|
|
186
|
+
|
|
187
|
+
## 非目标
|
|
188
|
+
不做 SSO。
|
|
189
|
+
`
|
|
190
|
+
const result = validateDesignForPlan(design)
|
|
191
|
+
assert(result.ok, '缺约束不应阻断')
|
|
192
|
+
assert(result.warnings.some(w => w.includes('约束') || w.includes('风险') || w.includes('Trade-off')), '应有约束/风险 warning')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// ─────────────────────────────────────────
|
|
196
|
+
// Case 9: missing 文件变更清单 warning
|
|
197
|
+
// ─────────────────────────────────────────
|
|
198
|
+
console.log('\n--- Case 9: missing 文件变更清单 warning ---')
|
|
199
|
+
{
|
|
200
|
+
const design = `# Design
|
|
201
|
+
|
|
202
|
+
## 背景
|
|
203
|
+
需要认证。
|
|
204
|
+
|
|
205
|
+
## 总体方案
|
|
206
|
+
用 JWT。
|
|
207
|
+
|
|
208
|
+
## 决策
|
|
209
|
+
D-001@v1: 选 JWT
|
|
210
|
+
`
|
|
211
|
+
const result = validateDesignForPlan(design)
|
|
212
|
+
assert(result.ok, '缺文件变更清单不应阻断')
|
|
213
|
+
assert(result.warnings.some(w => w.includes('文件变更')), '应有文件变更 warning')
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ─────────────────────────────────────────
|
|
217
|
+
// Case 10: 英文 design 通过
|
|
218
|
+
// ─────────────────────────────────────────
|
|
219
|
+
console.log('\n--- Case 10: 英文 design 通过 ---')
|
|
220
|
+
{
|
|
221
|
+
const design = `# Design: Auth System
|
|
222
|
+
|
|
223
|
+
## Background
|
|
224
|
+
We need authentication.
|
|
225
|
+
|
|
226
|
+
## Solution
|
|
227
|
+
Use JWT + Refresh Token.
|
|
228
|
+
|
|
229
|
+
## Decision
|
|
230
|
+
D-001@v1: Choose JWT over Session
|
|
231
|
+
|
|
232
|
+
## Non-goals
|
|
233
|
+
No SSO.
|
|
234
|
+
|
|
235
|
+
## Constraints
|
|
236
|
+
Must be backwards compatible.
|
|
237
|
+
`
|
|
238
|
+
const result = validateDesignForPlan(design)
|
|
239
|
+
assert(result.ok, '英文 design 应校验通过')
|
|
240
|
+
assert(result.errors.length === 0, '不应有 errors')
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ─────────────────────────────────────────
|
|
244
|
+
// Case 11: 最小合法 design
|
|
245
|
+
// ─────────────────────────────────────────
|
|
246
|
+
console.log('\n--- Case 11: 最小合法 design ---')
|
|
247
|
+
{
|
|
248
|
+
const design = `# Design
|
|
249
|
+
|
|
250
|
+
## 目标
|
|
251
|
+
修 bug。
|
|
252
|
+
|
|
253
|
+
## 方案
|
|
254
|
+
改代码。
|
|
255
|
+
|
|
256
|
+
## 决策
|
|
257
|
+
D-001@v1: 直接改。
|
|
258
|
+
`
|
|
259
|
+
const result = validateDesignForPlan(design)
|
|
260
|
+
assert(result.ok, '最小合法 design 应通过')
|
|
261
|
+
// 可能有 warning 但 ok
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ── 结果 ──
|
|
265
|
+
console.log(`\n${'='.repeat(50)}`)
|
|
266
|
+
console.log(`✅ 通过: ${11 - failed} ❌ 失败: ${failed}`)
|
|
267
|
+
if (failures.length > 0) {
|
|
268
|
+
console.log(`失败项:`)
|
|
269
|
+
failures.forEach(f => console.log(` - ${f}`))
|
|
270
|
+
}
|
|
271
|
+
console.log(`${'='.repeat(50)}`)
|
|
272
|
+
|
|
273
|
+
if (failed > 0) process.exit(1)
|
package/test/check-syntax.mjs
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process'
|
|
2
|
-
import { readdirSync, statSync } from 'node:fs'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
|
|
5
|
-
const roots = ['src']
|
|
6
|
-
const files = []
|
|
7
|
-
|
|
8
|
-
function walk(dir) {
|
|
9
|
-
for (const entry of readdirSync(dir)) {
|
|
10
|
-
const full = join(dir, entry)
|
|
11
|
-
const st = statSync(full)
|
|
12
|
-
if (st.isDirectory()) {
|
|
13
|
-
walk(full)
|
|
14
|
-
continue
|
|
15
|
-
}
|
|
16
|
-
if (/\.(js|cjs|mjs)$/.test(entry)) files.push(full)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
for (const root of roots) walk(root)
|
|
21
|
-
|
|
22
|
-
for (const file of files.sort()) {
|
|
23
|
-
execFileSync(process.execPath, ['--check', file], { stdio: 'inherit' })
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(`Checked ${files.length} JavaScript files`)
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { readdirSync, statSync } from 'node:fs'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
|
|
5
|
+
const roots = ['src']
|
|
6
|
+
const files = []
|
|
7
|
+
|
|
8
|
+
function walk(dir) {
|
|
9
|
+
for (const entry of readdirSync(dir)) {
|
|
10
|
+
const full = join(dir, entry)
|
|
11
|
+
const st = statSync(full)
|
|
12
|
+
if (st.isDirectory()) {
|
|
13
|
+
walk(full)
|
|
14
|
+
continue
|
|
15
|
+
}
|
|
16
|
+
if (/\.(js|cjs|mjs)$/.test(entry)) files.push(full)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for (const root of roots) walk(root)
|
|
21
|
+
|
|
22
|
+
for (const file of files.sort()) {
|
|
23
|
+
execFileSync(process.execPath, ['--check', file], { stdio: 'inherit' })
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(`Checked ${files.length} JavaScript files`)
|