sillyspec 3.19.2 → 3.20.1
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-knowledge/SKILL.md +270 -0
- package/.npmrc-tmp +1 -1
- package/package.json +2 -2
- package/src/brainstorm-postcheck.js +158 -0
- package/src/change-risk-profile.js +202 -17
- package/src/classify-change.js +73 -0
- package/src/index.js +59 -0
- package/src/run.js +171 -42
- package/src/stage-contract.js +14 -1
- package/src/stages/brainstorm-auto.js +229 -0
- package/src/stages/execute.js +36 -26
- package/src/stages/knowledge.js +498 -0
- package/src/stages/plan-postcheck.js +513 -0
- package/src/stages/plan.js +152 -346
- package/src/worktree-apply.js +141 -0
- package/test/decision-supersede.test.mjs +277 -0
- package/test/plan-optimization.test.mjs +572 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sillyspec:knowledge
|
|
3
|
+
description: Agent-safe knowledge base commands for SillySpec repositories. Search, inspect, validate, refresh, and propose knowledge entries.
|
|
4
|
+
argument-hint: "search --query \"<text>\" --limit N | inspect --id \"<id>\" | validate | refresh | propose --title \"<title>\" --category <name>"
|
|
5
|
+
version: "3.19.2"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 交互规范
|
|
9
|
+
当需要用户从多个选项中做出选择时,必须使用 Claude Code 内置的 AskUserQuestion 工具,将选项以参数传入。
|
|
10
|
+
|
|
11
|
+
## 何时使用此技能
|
|
12
|
+
Use this skill when working on a SillySpec repository and the task may depend on prior project knowledge, known issues, implementation patterns, scan-derived learnings, execute-stage knowledge hits, or `.sillyspec/knowledge`.
|
|
13
|
+
|
|
14
|
+
Before implementing changes, **first search the knowledge base** to avoid repeating known work or running into known issues.
|
|
15
|
+
|
|
16
|
+
## 命令列表
|
|
17
|
+
|
|
18
|
+
### 1. knowledge search — 搜索知识库
|
|
19
|
+
在执行任务前搜索相关知识。
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
sillyspec knowledge search --query "<task summary>" --limit 5
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**示例:**
|
|
26
|
+
```bash
|
|
27
|
+
sillyspec knowledge search --query "worktree baseline apply conflict" --limit 5
|
|
28
|
+
sillyspec knowledge search --query "postcheck validation error"
|
|
29
|
+
sillyspec knowledge search --query "GLM usage metadata"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**输出(JSON):**
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"ok": true,
|
|
36
|
+
"query": "worktree baseline",
|
|
37
|
+
"matches": [
|
|
38
|
+
{
|
|
39
|
+
"id": "patterns",
|
|
40
|
+
"path": "knowledge/patterns.md",
|
|
41
|
+
"title": "Patterns",
|
|
42
|
+
"summary": "每个阶段对应 `src/stages/` 下的独立模块...",
|
|
43
|
+
"score": 3,
|
|
44
|
+
"tags": ["worktree", "git-worktree", "WorktreeManager"],
|
|
45
|
+
"category": "Patterns"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**使用场景:**
|
|
52
|
+
- 实现新功能前,检查是否有现有模式可复用
|
|
53
|
+
- 遇到报错前,搜索是否是已知问题
|
|
54
|
+
- 修改特定模块前,了解约定和坑点
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### 2. knowledge inspect — 读取知识条目详情
|
|
59
|
+
搜索命中后,读取完整条目内容。
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
sillyspec knowledge inspect --id "<knowledge-id>"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**示例:**
|
|
66
|
+
```bash
|
|
67
|
+
sillyspec knowledge inspect --id "patterns"
|
|
68
|
+
sillyspec knowledge inspect --id "known-issues/sqljs-wasm-only"
|
|
69
|
+
sillyspec knowledge inspect --id "generated/worktree-baseline-conflict"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**输出(JSON):**
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"ok": true,
|
|
76
|
+
"entry": {
|
|
77
|
+
"id": "patterns",
|
|
78
|
+
"title": "Patterns",
|
|
79
|
+
"summary": "每个阶段对应 `src/stages/` 下的独立模块...",
|
|
80
|
+
"zone": "manual",
|
|
81
|
+
"path": "knowledge/patterns.md",
|
|
82
|
+
"meta": {
|
|
83
|
+
"author": "qinyi",
|
|
84
|
+
"created_at": "2026-06-19T12:40:00+08:00",
|
|
85
|
+
"updated_at": "2026-06-24T10:00:00+08:00"
|
|
86
|
+
},
|
|
87
|
+
"body": "完整 markdown 内容..."
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**zone 说明:**
|
|
93
|
+
- `manual` — 人工维护的知识(可直接信任)
|
|
94
|
+
- `generated` — 自动提取的知识(scan 生成,需人工审核)
|
|
95
|
+
- `proposed` — 提议待审核的知识(未合并)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### 3. knowledge validate — 校验知识库健康度
|
|
100
|
+
在 commit/archive 前检查知识库是否可用。
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
sillyspec knowledge validate
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**输出(JSON):**
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"ok": false,
|
|
110
|
+
"errors": [
|
|
111
|
+
{
|
|
112
|
+
"code": "broken_reference",
|
|
113
|
+
"path": "knowledge/generated/foo.md",
|
|
114
|
+
"referenced_in": "INDEX.md",
|
|
115
|
+
"display": "Foo Pattern"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"code": "empty_file",
|
|
119
|
+
"path": "knowledge/bar.md"
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"warnings": [
|
|
123
|
+
{
|
|
124
|
+
"code": "too_many_uncategorized",
|
|
125
|
+
"count": 12,
|
|
126
|
+
"path": "knowledge/uncategorized.md"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"code": "unregistered_file",
|
|
130
|
+
"path": "knowledge/new-file.md"
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**错误码说明:**
|
|
137
|
+
| code | 说明 |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `knowledge_dir_missing` | `.sillyspec/knowledge/` 目录不存在 |
|
|
140
|
+
| `missing_index` | `INDEX.md` 不存在 |
|
|
141
|
+
| `broken_reference` | INDEX.md 引用的文件不存在 |
|
|
142
|
+
| `empty_file` | 知识文件为空 |
|
|
143
|
+
| `too_many_uncategorized` | uncategorized.md 条目 ≥10,需清理 |
|
|
144
|
+
| `unregistered_file` | 手动知识文件未在 INDEX.md 注册 |
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### 4. knowledge refresh — 从 scan 文档刷新自动知识
|
|
149
|
+
**仅写 generated/ 区,不覆盖 manual/。**
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
sillyspec knowledge refresh
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**使用场景:**
|
|
156
|
+
- scan 阶段完成后,自动提取可复用知识
|
|
157
|
+
- archive 阶段完成后,沉淀长期有效的模式
|
|
158
|
+
|
|
159
|
+
**行为:**
|
|
160
|
+
1. 扫描 `.sillyspec/docs/<project>/scan/*.md`
|
|
161
|
+
2. 提取每个 `## 章节`(至少 3 行)作为知识条目
|
|
162
|
+
3. 写入 `.sillyspec/knowledge/generated/<slug>.md`
|
|
163
|
+
4. 生成 `generated/INDEX.md`
|
|
164
|
+
|
|
165
|
+
**输出(JSON):**
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"ok": true,
|
|
169
|
+
"generated_count": 8,
|
|
170
|
+
"new_count": 5,
|
|
171
|
+
"overwritten_count": 3,
|
|
172
|
+
"files": [
|
|
173
|
+
{ "file": "generated/worktree-isolation.md", "title": "...", "new": true },
|
|
174
|
+
{ "file": "generated/progress-management.md", "title": "...", "new": false }
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**注意事项:**
|
|
180
|
+
- generated/ 区知识是自动生成,不保证准确,需人工审核后合并到 manual/
|
|
181
|
+
- 已有文件会被覆盖( overwrite_count)
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### 5. knowledge propose — 提议新知识
|
|
186
|
+
不直接编辑 manual/,而是写入 proposed/ 供审核。
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
sillyspec knowledge propose --title "<title>" --category <category> --body "<content>" --from "<source>"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**参数说明:**
|
|
193
|
+
| 参数 | 必填 | 说明 |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| `--title` | ✅ | 知识标题 |
|
|
196
|
+
| `--category` | ❌ | 分类(默认 uncategorized),如 known-issues, patterns, conventions |
|
|
197
|
+
| `--body` | ❌ | 知识正文 |
|
|
198
|
+
| `--from` | ❌ | 来源标注(如 execute/quick/scan) |
|
|
199
|
+
|
|
200
|
+
**示例:**
|
|
201
|
+
```bash
|
|
202
|
+
sillyspec knowledge propose --title "GLM API 超时处理" --category known-issues --body "GLM 模型默认超时 30 秒..." --from "execute"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**输出(JSON):**
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"ok": true,
|
|
209
|
+
"id": "proposed/glm-api-timeout",
|
|
210
|
+
"path": "knowledge/proposed/glm-api-timeout.md",
|
|
211
|
+
"title": "GLM API 超时处理",
|
|
212
|
+
"category": "known-issues",
|
|
213
|
+
"new": true,
|
|
214
|
+
"action": "created"
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**后续流程:**
|
|
219
|
+
- archive/commit 阶段审核 proposed/ 条目
|
|
220
|
+
- 合格的合并到 manual/,不合格的删除
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Agent 使用指南
|
|
225
|
+
|
|
226
|
+
### 任务前必查
|
|
227
|
+
在开始实现新功能、修改现有代码、或遇到报错前:
|
|
228
|
+
1. `knowledge search --query "<任务关键词>"`
|
|
229
|
+
2. 命中则 `knowledge inspect --id "<id>"`
|
|
230
|
+
3. 遵循知识中的约定和避坑建议
|
|
231
|
+
|
|
232
|
+
### 发现新知识
|
|
233
|
+
执行任务中发现可复用模式或新坑:
|
|
234
|
+
1. `knowledge propose --title "<标题>" --category <分类> --body "<内容>"`
|
|
235
|
+
2. 不要直接编辑 `.sillyspec/knowledge/manual/*.md`
|
|
236
|
+
|
|
237
|
+
### 提交前校验
|
|
238
|
+
commit/archive 前检查知识库状态:
|
|
239
|
+
1. `knowledge validate`
|
|
240
|
+
2. 如有 errors,先修复再提交
|
|
241
|
+
|
|
242
|
+
### 扫描后刷新
|
|
243
|
+
scan 阶段完成后:
|
|
244
|
+
1. `knowledge refresh`
|
|
245
|
+
2. 审核生成的 `generated/*.md`,有用的合并到 manual/
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 禁止事项
|
|
250
|
+
|
|
251
|
+
❌ **不要直接编辑** `manual/` 或 `generated/` 中的知识文件
|
|
252
|
+
- 使用 `knowledge propose` 提议新知识
|
|
253
|
+
- 使用 `knowledge refresh` 刷新自动知识
|
|
254
|
+
|
|
255
|
+
❌ **不要使用 `grep` 或 `cat` 直接读取知识文件**
|
|
256
|
+
- 使用 `knowledge search` 和 `knowledge inspect`
|
|
257
|
+
- 它们使用与 execute 阶段相同的匹配引擎
|
|
258
|
+
|
|
259
|
+
❌ **不要让 agent 去审核 proposed/ 条目**
|
|
260
|
+
- 提议供人工审核,不要自动合并
|
|
261
|
+
- 只有用户明确要求才合并
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## 设计原则
|
|
266
|
+
|
|
267
|
+
- **Agent-safe:** 所有输出为 JSON,失败有明确错误码
|
|
268
|
+
- **写保护:** refresh 仅写 generated/,propose 仅写 proposed/,不碰 manual/
|
|
269
|
+
- **匹配引擎:** 使用 `knowledge-match.js`(与 execute 阶段一致)
|
|
270
|
+
- **审计友好:** 每个条目记录来源、创建/更新时间
|
package/.npmrc-tmp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
//registry.npmjs.org/:_authToken=
|
|
1
|
+
//registry.npmjs.org/:_authToken=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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sillyspec",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.1",
|
|
4
4
|
"description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
|
|
5
5
|
"icon": "logo.jpg",
|
|
6
6
|
"homepage": "https://sillyspec.ppdmq.top/",
|
|
@@ -37,4 +37,4 @@
|
|
|
37
37
|
"sql.js": "^1.14.1",
|
|
38
38
|
"ws": "^8.18"
|
|
39
39
|
}
|
|
40
|
-
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* brainstorm-postcheck.js — plan 阶段对 brainstorm 产物的校验
|
|
3
|
+
*
|
|
4
|
+
* 在 brainstorm → plan 之间执行,校验 brainstorm 产物完整性。
|
|
5
|
+
* PASS → 继续 plan
|
|
6
|
+
* WARN → 继续 plan,记录警告并分配补齐任务
|
|
7
|
+
* FAIL → 回退到 brainstorm 补齐(最多 2 次重试)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync, readFileSync } from 'fs'
|
|
11
|
+
import { join } from 'path'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 校验 brainstorm 产物完整性
|
|
15
|
+
* @param {string} changeDir - 变更目录路径(.sillyspec/changes/<change>)
|
|
16
|
+
* @returns {{ ok: boolean, level: 'PASS'|'WARN'|'FAIL', errors: string[], warnings: string[] }}
|
|
17
|
+
*/
|
|
18
|
+
export function checkBrainstormArtifacts(changeDir) {
|
|
19
|
+
const errors = []
|
|
20
|
+
const warnings = []
|
|
21
|
+
const brainstormDir = join(changeDir, 'brainstorm')
|
|
22
|
+
|
|
23
|
+
// ── 1. 产物完整性检查 ──
|
|
24
|
+
const requiredFiles = ['design.md', 'decisions.md', 'gaps.md', 'assumptions.md', 'next-action.json']
|
|
25
|
+
for (const file of requiredFiles) {
|
|
26
|
+
if (!existsSync(join(brainstormDir, file))) {
|
|
27
|
+
errors.push(`brainstorm/${file} 不存在`)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ── 2. next-action.json 有效性检查 ──
|
|
32
|
+
const nextActionFile = join(brainstormDir, 'next-action.json')
|
|
33
|
+
if (existsSync(nextActionFile)) {
|
|
34
|
+
try {
|
|
35
|
+
const nextAction = JSON.parse(readFileSync(nextActionFile, 'utf8'))
|
|
36
|
+
|
|
37
|
+
// 必填字段
|
|
38
|
+
if (!['ready_for_plan', 'waiting_for_user'].includes(nextAction.status)) {
|
|
39
|
+
errors.push(`next-action.json.status 无效值: ${nextAction.status}`)
|
|
40
|
+
}
|
|
41
|
+
if (typeof nextAction.has_blocking_questions !== 'boolean') {
|
|
42
|
+
errors.push(`next-action.json.has_blocking_questions 不是布尔值`)
|
|
43
|
+
}
|
|
44
|
+
if (!['high', 'medium', 'low'].includes(nextAction.decision_level)) {
|
|
45
|
+
warnings.push(`next-action.json.decision_level 无效值: ${nextAction.decision_level}`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 状态一致性
|
|
49
|
+
if (nextAction.status === 'waiting_for_user' && nextAction.has_blocking_questions !== true) {
|
|
50
|
+
errors.push(`next-action.json status=waiting_for_user 但 has_blocking_questions !== true`)
|
|
51
|
+
}
|
|
52
|
+
if (nextAction.status === 'ready_for_plan' && nextAction.has_blocking_questions === true) {
|
|
53
|
+
errors.push(`next-action.json status=ready_for_plan 但 has_blocking_questions === true`)
|
|
54
|
+
}
|
|
55
|
+
} catch (e) {
|
|
56
|
+
errors.push(`next-action.json 解析失败: ${e.message}`)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ── 3. design.md 覆盖度检查 ──
|
|
61
|
+
const designFile = join(brainstormDir, 'design.md')
|
|
62
|
+
if (existsSync(designFile)) {
|
|
63
|
+
const designContent = readFileSync(designFile, 'utf8')
|
|
64
|
+
|
|
65
|
+
// 必须覆盖的维度
|
|
66
|
+
if (!/(?:目标|goal|objective|背景|background|问题|problem)/i.test(designContent)) {
|
|
67
|
+
warnings.push('design.md 缺少设计目标/背景描述')
|
|
68
|
+
}
|
|
69
|
+
if (!/(?:范围|scope|总体方案|方案|approach)/i.test(designContent)) {
|
|
70
|
+
warnings.push('design.md 缺少总体方案描述')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 弱覆盖检测
|
|
74
|
+
if (/影响模块.*TBD|文件变更.*TBD|待定/i.test(designContent)) {
|
|
75
|
+
warnings.push('design.md 包含 TBD/待定内容')
|
|
76
|
+
}
|
|
77
|
+
if (!/(?:验收|acceptance|完成标准)/i.test(designContent)) {
|
|
78
|
+
warnings.push('design.md 缺少验收标准')
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── 4. gaps.md 覆盖度检查 ──
|
|
83
|
+
const gapsFile = join(brainstormDir, 'gaps.md')
|
|
84
|
+
if (existsSync(gapsFile)) {
|
|
85
|
+
const gapsContent = readFileSync(gapsFile, 'utf8')
|
|
86
|
+
const hasBlocker = /BLOCKER/i.test(gapsContent)
|
|
87
|
+
if (hasBlocker) {
|
|
88
|
+
errors.push('gaps.md 包含 BLOCKER 级缺口,需要先解决')
|
|
89
|
+
}
|
|
90
|
+
// 检查是否为空
|
|
91
|
+
const nonEmpty = gapsContent.split('\n').filter(l => l.trim() && !l.startsWith('#')).length
|
|
92
|
+
if (nonEmpty === 0) {
|
|
93
|
+
warnings.push('gaps.md 为空(brainstorm 可能遗漏了缺口分析)')
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ── 5. assumptions.md 风险检查 ──
|
|
98
|
+
const assumptionsFile = join(brainstormDir, 'assumptions.md')
|
|
99
|
+
if (existsSync(assumptionsFile)) {
|
|
100
|
+
const assumptionsContent = readFileSync(assumptionsFile, 'utf8')
|
|
101
|
+
if (/假设现有数据格式不变|假设.*API.*不变|假设.*性能.*可接受/i.test(assumptionsContent)) {
|
|
102
|
+
warnings.push('assumptions.md 包含高风险假设,需在 verify 阶段验证')
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── 6. decisions.md 一致性检查 ──
|
|
107
|
+
const decisionsFile = join(brainstormDir, 'decisions.md')
|
|
108
|
+
if (existsSync(decisionsFile)) {
|
|
109
|
+
const decisionsContent = readFileSync(decisionsFile, 'utf8')
|
|
110
|
+
const autoDecided = (decisionsContent.match(/AUTO_DECIDED/g) || []).length
|
|
111
|
+
const autoDecidedWithReason = (decisionsContent.match(/AUTO_DECIDED[\s\S]*?checklist/i) || []).length
|
|
112
|
+
if (autoDecided > 0 && autoDecidedWithReason < autoDecided) {
|
|
113
|
+
errors.push(`${autoDecided - autoDecidedWithReason} 个 AUTO_DECIDED 决策缺少 checklist 依据`)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ── 判定结果 ──
|
|
118
|
+
let level
|
|
119
|
+
if (errors.length > 0) {
|
|
120
|
+
level = 'FAIL'
|
|
121
|
+
} else if (warnings.length > 0) {
|
|
122
|
+
level = 'WARN'
|
|
123
|
+
} else {
|
|
124
|
+
level = 'PASS'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { ok: level !== 'FAIL', level, errors, warnings }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 执行 brainstorm postcheck(供 run.js 调用)
|
|
132
|
+
*/
|
|
133
|
+
export async function executeBrainstormPostcheck(cwd, platformOpts, changeName) {
|
|
134
|
+
const specBase = platformOpts?.specRoot || join(cwd, '.sillyspec')
|
|
135
|
+
const changeDir = join(specBase, 'changes', changeName)
|
|
136
|
+
if (!existsSync(changeDir)) {
|
|
137
|
+
console.log('⚠️ brainstorm postcheck: 变更目录不存在,跳过')
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const result = checkBrainstormArtifacts(changeDir)
|
|
142
|
+
|
|
143
|
+
if (result.level === 'PASS') {
|
|
144
|
+
console.log('✅ brainstorm postcheck: PASS')
|
|
145
|
+
} else if (result.level === 'WARN') {
|
|
146
|
+
console.log('⚠️ brainstorm postcheck: WARN')
|
|
147
|
+
for (const w of result.warnings) {
|
|
148
|
+
console.log(` - ${w}`)
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
console.error('❌ brainstorm postcheck: FAIL')
|
|
152
|
+
for (const e of result.errors) {
|
|
153
|
+
console.error(` - ${e}`)
|
|
154
|
+
}
|
|
155
|
+
console.error('\\n 请修复以上问题后重试,或使用 --skip-approval 跳过。')
|
|
156
|
+
process.exit(1)
|
|
157
|
+
}
|
|
158
|
+
}
|