sillyspec 3.26.3 → 3.26.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.
@@ -33,6 +33,18 @@ sillyspec run quick --reset # 重置阶段(从头开始)
33
33
  sillyspec run quick --reopen --from-step N # 重新打开已完成阶段修订(N=序号或名称)
34
34
  ```
35
35
 
36
+ ### 已有进行中会话的恢复(sessionId)
37
+
38
+ `sillyspec run quick` / `run quick --done` / `--status` **不带 `--change` 时,是启动一个新 quick 会话**(CLI 分配新 `quick-<hash>` + 新 ql-ID,QUICKLOG 追加「进行中」条目),不是恢复正在进行的旧会话。多会话并发或中断恢复时,必须带上启动时 CLI 打印的 sessionId:
39
+
40
+ ```bash
41
+ sillyspec run quick --change quick-<hash> # 恢复查看该会话当前 step prompt
42
+ sillyspec run quick --done --change quick-<hash> --output "…" # 完成该会话步骤
43
+ ```
44
+
45
+ - 这里的 `--change quick-<hash>` 是「恢复到该 CLI 生成的 session」,与下方 `--linked-changes` 的关联业务变更语义不同:想关联真实业务变更才用 `--linked-changes`。
46
+ - 误启动的空壳会话:`sillyspec run quick --reset --change quick-<hash>` 重置其进度;QUICKLOG 里残留的「(quick 任务)」骨架条目需手动删除,不留占位条目。
47
+
36
48
  ## 通用参数(所有阶段适用)
37
49
 
38
50
  | 参数 | 说明 |
@@ -91,7 +103,7 @@ sillyspec run quick --files src/phone.ts,src/phone.test.ts
91
103
  - QUICKLOG 记录的**骨架由 CLI 接管**:启动时 CLI 自动分配 ql-ID 并在 `.sillyspec/quicklog/QUICKLOG-<user>.md` 写「进行中」条目(含关联变更 tasks.md),`--done` 时 CLI 自动翻「已完成」+ 勾选 task + 回填文件路径。ql-ID 分配/状态/task 你无需手写,只需用注入的 `<quicklog-id>` 在模块文档变更索引引用
92
104
  - **QUICKLOG 落盘已结构化(`--done` 后按需核对,多数无需手改)**:CLI 已落盘结构化条目——标题从 `--output` 的「需求:」自动提取、正文四字段自动分行、文件行用 `--file-notes` 时为多行带括注。`--done` 后只需核对:标题弱才改(禁留 `(quick 任务)` 占位);没用 `--file-notes` 时文件行是单行、可事后补括注(参照同文件早期丰富条目);正文 `需求:`/`根因:`/`方案:`/`结果:` 四段按需充实(禁只留一段「结果:」)。一条 quick = 一条独立 ql,不追加到旧条目
93
105
  - **收尾顺序(模块文档在 `--done` 前,QUICKLOG 在 `--done` 后,别记混)**:① 命中模块→改模块文档→`git add`;② `sillyspec run quick --done --change <id> --output "四字段" [--file-notes "..."]`(CLI 自动翻完成 + 勾 task + 落盘 QUICKLOG 标题/文件/正文);③ 核对 QUICKLOG 标题(CLI 已从「需求:」提取,仅弱标题才改)→若改了再 `git add`
94
- - **最后一步 `--done --output` 必须按结构化结果模板给全四字段**(逐项一句话):`需求:… 根因:… 方案:… 结果:…`。这是 QUICKLOG「结果:」归档的唯一来源;CLI 校验缺字段会拒绝 `--done`(exit 1),补全后重跑即可。前两个 step 的 `--output` 是中间摘要,不用此模板
106
+ - **最后一步 `--done --output` 必须按结构化结果模板给全四字段**(逐项一句话):`需求:… 根因:… 方案:… 结果:…`。这是 QUICKLOG「结果:」归档的唯一来源;CLI 校验缺字段会拒绝 `--done`(exit 1),补全后重跑即可。正文内避免嵌套全角冒号(如「方案:(说明 xxx):」这样标签后紧接嵌套冒号会被拆分判定缺字段),直接让标签接正文。前两个 step 的 `--output` 是中间摘要,不用此模板
95
107
  - **禁止**在没有运行 CLI 的情况下自行决定流程
96
108
 
97
109
  ## 用户指令
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sillyspec",
3
- "version": "3.26.3",
3
+ "version": "3.26.4",
4
4
  "description": "SillySpec CLI — 流程状态机,让 AI 严格按步骤来",
5
5
  "icon": "logo.jpg",
6
6
  "homepage": "https://sillyspec.ppdmq.top/",
package/src/db.js CHANGED
@@ -116,6 +116,17 @@ export class DB {
116
116
  if (readValid(this.dbPath) === 'ok') {
117
117
  const primaryDb = tryOpen(this.dbPath);
118
118
  if (primaryDb) return primaryDb;
119
+ // 并发首开竞争(2026-08-12 db-concurrency flaky 根因实证):多进程近乎同时
120
+ // new DB().init() 打开同一新建库时,tryOpen 的 prepare(SELECT count(*)) 可能撞上
121
+ // 他者进程的 CHECKPOINT 改写主库 → 瞬时失败返 null。此时主库存在且有内容,
122
+ // 非真损坏——有限重试消化锁竞争(复用 MAX_BUSY_RETRIES 退避,与 transaction 的
123
+ // SQLITE_BUSY 重试同基建)。真损坏重试也不会过,最终仍走 .bak 回退 / fail-loud,
124
+ // 防吞进度语义零回归。
125
+ for (let attempt = 0; attempt < MAX_BUSY_RETRIES; attempt++) {
126
+ _sleepSync(BUSY_BACKOFF_MS[attempt]);
127
+ const retryDb = tryOpen(this.dbPath);
128
+ if (retryDb) return retryDb;
129
+ }
119
130
  }
120
131
 
121
132
  // 2. .bak 回退(.bak 是恢复源:存在且能打开即用,含 0 字节空库;门禁只挡"不存在",
@@ -137,6 +137,9 @@ ${branchLine}
137
137
  2. 蓝图文件路径(让子代理按需读取详情,不要内联整份蓝图污染上下文)
138
138
  3. 编码铁律:先读后写、TDD、不编造方法、只做蓝图里写的事、遵守边界处理规则、不超出 allowedPaths
139
139
  4. 如存在模块文档(\`.sillyspec/docs/*/modules/\`),按需读取涉及模块的 <module>.md 参考接口约定与数据流
140
+ 5. 任务含测试代码时,把下方「测试用例设计」整段复制进子代理 prompt,要求子代理按此设计测试用例
141
+
142
+ {{include: testcase-design}}
140
143
  ${modeLine}
141
144
  ${allowedLine}
142
145
 
@@ -223,6 +223,9 @@ dispatch_worker 的 \`worker_prompt\` 参数必须传以下覆写文本(路径
223
223
  交 SillySpec 主体 git diff 回收(D-004)
224
224
  3. 不超出 allowedPaths,不碰其他 task 的文件
225
225
  4. 完成后输出简短自报(改了哪些文件 / 跑了哪些测试 / 是否存疑),不自报 review.json(SillySpec 自己写)
226
+ 5. 写测试时遵循下方「测试用例设计」规则:
227
+
228
+ {{include: testcase-design}}
226
229
  \`\`\`
227
230
 
228
231
  ### 终态轮询 + 超时 kill lease(UB-6)
@@ -1079,6 +1079,9 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
1079
1079
  console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
1080
1080
  console.log(' 提示:使用 --skip-approval 跳过审批检查')
1081
1081
  }
1082
+ if (approval.status === 'unknown') {
1083
+ console.warn(`⚠️ 变更 ${changeName} 的审批状态未知(${approval.reason || '请求失败'}),按本地模式放行(非审批中,无需等待)`)
1084
+ }
1082
1085
  }
1083
1086
  }
1084
1087
  await outputStep(currentStage, pendingIdx, defSteps, cwd, changeName, progress.project || null, platformOpts)
@@ -1109,6 +1112,9 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
1109
1112
  console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
1110
1113
  console.log(' 提示:使用 --skip-approval 跳过审批检查')
1111
1114
  }
1115
+ if (approval.status === 'unknown') {
1116
+ console.warn(`⚠️ 变更 ${changeName} 的审批状态未知(${approval.reason || '请求失败'}),按本地模式放行(非审批中,无需等待)`)
1117
+ }
1112
1118
  }
1113
1119
  }
1114
1120
  await outputStep(currentStage, nextPendingIdx, defSteps, cwd, changeName, progress.project || null, platformOpts)
@@ -1176,6 +1182,9 @@ async function runAutoMode(pm, progress, cwd, flags, changeName, platformOpts =
1176
1182
  console.log(`⏳ 变更 ${changeName} 的执行审批待处理中...`)
1177
1183
  console.log(' 提示:使用 --skip-approval 跳过审批检查')
1178
1184
  }
1185
+ if (approval.status === 'unknown') {
1186
+ console.warn(`⚠️ 变更 ${changeName} 的审批状态未知(${approval.reason || '请求失败'}),按本地模式放行(非审批中,无需等待)`)
1187
+ }
1179
1188
  }
1180
1189
  }
1181
1190
  await outputStep(next, firstPending, nextSteps, cwd, changeName, progress.project || null, platformOpts)
@@ -329,6 +329,8 @@ design.md 第一行标题必须用中文:# 设计文档(Design)— <变更
329
329
  - 长期术语只在 archive/scan 时再提升到 \`{SPEC_ROOT}/docs/<project>/glossary.md\`
330
330
  4. 格式自检(只查章节齐全;语义一致性/可行性/YAGNI 不在本步查,交给下一步 Design Grill 独立审查):
331
331
  - design.md 含全部必填章节(背景/设计目标/非目标/总体方案/文件变更清单/接口定义/风险登记)
332
+ - design.md 头部 YAML frontmatter 字段齐全(author/created_at/scale 等)——step8 完成契约硬要求,审查前就补齐避免后续 docHash 漂移
333
+ - design.md 含「自审」字面命中章节(自审 / Self-Review / Self-review)——step8 完成契约 brainstorm.design.self-review 硬要求,写在本步自审段即可
332
334
  - 如存在 decisions.md,design.md 是否引用所有当前版本 D-xxx@vN
333
335
  - 涉及 session/lease/agent_run/daemon/lifecycle 等关键词时,是否含「生命周期契约表」
334
336
  5. 缺章节 → 补齐后重检;章节齐全 → 进入下一步(Design Grill 做语义层交叉审查)
@@ -476,10 +478,10 @@ created_at: <now-datetime>
476
478
 
477
479
  ### proposal.md 格式要求
478
480
  \`\`\`markdown
479
- ---
480
- author: <git-user>
481
- created_at: <now-datetime>
482
- ---
481
+ ---
482
+ author: <git-user>
483
+ created_at: <now-datetime>
484
+ ---
483
485
  # 提案书(Proposal)
484
486
 
485
487
  ## 动机
@@ -503,10 +505,10 @@ created_at: <now-datetime>
503
505
 
504
506
  ### requirements.md 格式要求
505
507
  \`\`\`markdown
506
- ---
507
- author: <git-user>
508
- created_at: <now-datetime>
509
- ---
508
+ ---
509
+ author: <git-user>
510
+ created_at: <now-datetime>
511
+ ---
510
512
  # 需求规格(Requirements)
511
513
 
512
514
  ## 角色
@@ -535,18 +537,18 @@ Then 期望结果
535
537
  | D-001@v1 | FR-01 | ... |
536
538
  \`\`\`
537
539
 
538
- ### tasks.md 格式要求(scale=large 时生成骨架,plan 阶段展开)
539
- \`\`\`markdown
540
- ---
541
- author: <git-user>
542
- created_at: <now-datetime>
543
- ---
544
- # 任务清单(Tasks)
545
-
546
- - [ ] task-01: <任务名>
547
- - [ ] task-02: <任务名>
548
- \`\`\`
549
-
540
+ ### tasks.md 格式要求(scale=large 时生成骨架,plan 阶段展开)
541
+ \`\`\`markdown
542
+ ---
543
+ author: <git-user>
544
+ created_at: <now-datetime>
545
+ ---
546
+ # 任务清单(Tasks)
547
+
548
+ - [ ] task-01: <任务名>
549
+ - [ ] task-02: <任务名>
550
+ \`\`\`
551
+
550
552
  ### decisions.md 格式要求(仅在有 Grill/重大决策时生成)
551
553
  \`\`\`markdown
552
554
  # 决策记录(Decisions)
@@ -801,6 +801,9 @@ ${taskSummary}
801
801
  2. 蓝图文件路径(让子代理自行读取详情)
802
802
  3. 编码铁律:先读后写、TDD、不编造方法、只做蓝图里写的事、遵守边界处理规则、不超出 allowed_paths
803
803
  4. 如存在模块文档(.sillyspec/docs/*/modules/),按需读取涉及模块的 <module>.md 参考接口约定和数据流
804
+ 5. 任务含测试代码时,把下方「测试用例设计」整段复制进子代理 prompt,要求子代理按此设计测试用例
805
+
806
+ {{include: testcase-design}}
804
807
 
805
808
  ### Wave 开始前
806
809
  1. 读取 design.md 的「非目标」与「兼容策略」章节(如存在),确保子代理不超范围、不破坏旧逻辑
@@ -50,9 +50,11 @@ export const definition = {
50
50
  ### 操作
51
51
  1. 先读后写:调用已有方法前 \`cat\` 源文件确认签名,\`grep\` 确认方法存在
52
52
  2. 写代码完成任务
53
- 3. 如涉及逻辑变更,建议写单元测试验证(不强制,纯配置/文档/小改动可跳过)
53
+ 3. 如涉及逻辑变更,建议写单元测试验证(不强制,纯配置/文档/小改动可跳过);写测试时按下方「测试用例设计」检查
54
54
  4. **不要做无谓的全量编译/构建。** 但——跑针对性的单元测试始终允许且鼓励(见 step3);若本任务就是修测试/构建/基础设施本身,跑测试/构建即验收,应当跑,不算"编译"
55
55
 
56
+ {{include: testcase-design}}
57
+
56
58
  ### 输出
57
59
  实现摘要 + 修改文件列表
58
60
 
@@ -214,7 +214,7 @@ PASS / PASS WITH NOTES / FAIL
214
214
  ## 探针结果
215
215
  - 未实现标记扫描:...
216
216
  - 关键词覆盖:...
217
- - 测试覆盖:...
217
+ - 测试覆盖(含断言有效性抽查):...
218
218
  - 决策追踪覆盖:...
219
219
  - API 契约对账:...
220
220
  - 代码删除对账:声明修改/新增却被整文件删除 = 高风险;清单未列出的删除 = 未声明(CLI 会用 git diff --name-status HEAD advisory 复核,仅 warn 不阻断——是否 FAIL blocker 由你诚实判定)
package/src/sync.js CHANGED
@@ -517,7 +517,7 @@ export class SyncManager {
517
517
 
518
518
  if (!result) {
519
519
  console.warn(`[sync] 检查审批状态失败: ${changeName}`);
520
- return { status: 'pending', reason: '请求失败' };
520
+ return { status: 'unknown', reason: '请求失败(404/断网/超时),无法核实审批状态' };
521
521
  }
522
522
 
523
523
  // 更新本地 approvals 表
@@ -0,0 +1,12 @@
1
+ ### 测试用例设计(写测试时按此检查)
2
+
3
+ 写测试是为了拦住回归,不是"有测试文件"。
4
+ **基础习惯照做、不展开**:FIRST(快/独立/可重复/自校验/及时)、金字塔分层(单元为主/集成少量/E2E 只冒烟)、AAA 结构、测试名描述场景、测试数据轻量构造(Object Mother/Builder)、覆盖率不追数字。
5
+
6
+ 逐条对照检查:
7
+ 1. **覆盖**:正常路径 + 边界 + 异常/非法输入,不只写业务正例;单测全绿 ≠ 集成正确。
8
+ 2. **断言**:断言真实输出/副作用,禁止只"不抛错"的空断言;不 mock 被测方法自身。
9
+ 3. **行为 vs 实现**:走公开 API 测行为;重构后功能不变,测试不应失败。
10
+ 4. **契约与回归**:覆盖本次改动会破坏的既有行为与相邻模块接口;改公共签名/文案/常量时同步修复受影响既有测试并跑全量,禁止删断言凑绿。
11
+ 5. **时间敏感分支**:超时/重试/并发分支别真等——超时参数做成可注入,测试传毫秒级极小值或注入可控时钟推进,再断言超时后的行为(走哪个分支/返回什么/资源是否回收)。
12
+ 6. **隔离确定性**:独立 fixture、可重复跑,不依赖共享状态/执行顺序。
@@ -21,6 +21,7 @@ grep -rl "<关键词>" <源码目录>/ --include="*.java" --include="*.js" --inc
21
21
  2. 对每个 task,**递归**检查对应模块目录及其**所有子目录**下是否存在测试文件(*test*、*spec*、*Test*、*Spec*)——包括模块内 co-located 的 tests/ 目录(如 `backend/app/modules/*/tests/`),**不要只看顶层 `tests/`**,否则会把测试就在模块内部的项目误判为“无测试”
22
22
  3. 没有测试文件的 task 标记为 ⚠️ 缺少测试
23
23
  4. **集成盲区提示**:测试文件存在 ≠ 集成正确——路由/layout 守卫重定向、跨模块装配这类集成 bug 组件单测覆盖不到,只有集成/冒烟/E2E 才暴露。对路由/layout/跨进程装配敏感的 task,额外检查是否有集成冒烟覆盖;无则标 ⚠️ 集成层未验证(需人工或部署确认)
24
+ 5. **断言有效性抽查(与 execute「测试用例设计」闭环)**:测试文件存在 ≠ 测试有效。对最能代表本次变更行为的 2-3 个核心测试做抽查:① 断言验证真实输出/副作用,不是只"不抛错"的空断言、只测 getter/setter;② 覆盖边界/异常分支,不只业务正例;③ 走公开 API 测行为,不测实现细节(重构后功能不变测试不应失败)。不达标标 ⚠️ 断言薄弱或无效(advisory:CLI 不阻断,是否 FAIL 由你诚实判定;execute 已按「测试用例设计」写的,这里只抽查核验,不重审全量)
24
25
 
25
26
  **探针 4:决策追踪覆盖探针(如存在 decisions.md)**
26
27
  1. 从 decisions.md 提取所有当前版本 D-xxx@vN
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: sillyspec-onboard
3
+ description: 为未安装 SillySpec 的全新项目接入规范驱动开发工作流——引导安装 CLI、初始化接入、建立项目库,并把「用 SillySpec 走流程」确立为项目默认工作方式。适合用户说"给这个项目接上 sillyspec"或新项目开工前确认流程。
4
+ ---
5
+
6
+ ## 交互规范
7
+
8
+ **当需要用户从多个选项中做出选择时,必须使用 Claude Code 内置的 AskUserQuestion 工具,将选项以参数传入。** 涉及是否全局安装 CLI / 是否建立项目库等决策,让用户亲手拍板,不替用户做决定。
9
+
10
+ ## 何时使用
11
+
12
+ - 目标项目**没有安装/未接入** SillySpec(判断:项目根无 `.sillyspec/` 目录;或 `sillyspec --version` 命令不可用)
13
+ - 用户想让 SillySpec 成为该项目的开发流程控制器
14
+
15
+ ## 铁律
16
+
17
+ - **必须用 exec 工具(shell)执行 CLI,不编造命令**;命中的命令固定为下方公开 CLI,不自行发明子命令
18
+ - 本 skill 只做**接入动作**(安装/初始化/验证),不写业务代码、不改项目源码
19
+ - 全程在主工作区根执行 CLI,不进入 worktree
20
+ - 每个决策点用 AskUserQuestion 让用户拍板,不静默代选
21
+
22
+ ## 核心流程
23
+
24
+ ### Step 0: 判定接入状态
25
+
26
+ ```bash
27
+ # 项目根是否已有 .sillyspec/(已接入)
28
+ ls -d .sillyspec 2>/dev/null
29
+ # CLI 是否可用
30
+ sillyspec --version 2>/dev/null
31
+ ```
32
+
33
+ - 已接入(`.sillyspec/` 存在)→ 不重复接入,提示用户项目已用 SillySpec 管理,退出。
34
+ - 未接入但 CLI 已装 → 跳到 Step 2。
35
+ - 都无 → 继续 Step 1。
36
+
37
+ ### Step 1: 引导安装 CLI(全局)
38
+
39
+ ```bash
40
+ npm install -g sillyspec
41
+ ```
42
+
43
+ - 若当前环境沙箱/权限导致 `npm -g` 失败,提示用户用 `! npm install -g sillyspec` 手动执行(输出直达会话)。
44
+ - 装完验证:`sillyspec --version` 可输出版本号。
45
+
46
+ ### Step 2: 初始化接入项目
47
+
48
+ ```bash
49
+ sillyspec init
50
+ ```
51
+
52
+ `init` 会自动:创建 `.sillyspec/`(项目注册、文档中心、知识库、运行时进度库)、检测项目中的 AI 工具(Claude Code 等)、给 `CLAUDE.md` 注入 SillySpec 受管段(若项目已有文件)或生成完整指引模板(若没有)、安装对应命令模板/MCP 工具。
53
+
54
+ - 新项目为空目录时建议走 `sillyspec run scan`(见 Step 3)补齐项目库;已有代码但未接入的存量项目,先确认项目状态再决定是否 scan。
55
+ - 验证产物:
56
+ ```bash
57
+ ls .sillyspec/projects/ # 项目注册表
58
+ grep -c "SillySpec" CLAUDE.md # 受管段/指引已注入(>0)
59
+ ```
60
+
61
+ ### Step 3: 建立项目库(知识基石)
62
+
63
+ ```bash
64
+ sillyspec run scan
65
+ ```
66
+
67
+ 把项目的代码风格(CONVENTIONS.md)、架构(ARCHITECTURE.md)沉淀为后续 agent 的检索知识。这是「让后续 agent 不瞎猜」的关键一步,新项目建议立即做。
68
+
69
+ ### Step 4: 价值认知锚 —— 让后续 agent 愿意用
70
+
71
+ 接入完成后,**让"用 SillySpec 走流程"成为项目默认工作方式**靠的是已落盘的载体,不是本 skill(skill 是一次性的):
72
+
73
+ 1. 确认价值锚已就位:
74
+ - `CLAUDE.md` 含 SillySpec 段(Step 2 已验证)——agent 每次会话读取项目说明书时都会看到「禁止绕过流程 / 新功能走 brainstorm→plan→execute→verify→archive / 小修复走 quick」。
75
+ - `.claude/skills/` 含 SillySpec 持续 skill(init 已复制 plan/quick/brainstorm 等)——agent 在开发任务中 `/plan`、`/quick` 即走流程。
76
+ - `.sillyspec/` 进度库已建——进度自动落盘,多 agent 并发不互相覆盖。
77
+
78
+ 2. 向用户/后续 agent 说明价值(一句话口径,复用 init 注入的陈述,不另造文案):
79
+ > SillySpec 是给 Agent 调用的 CLI 流程控制器:你通过 CLI 告诉它"我在哪",它告诉你"下一步做什么";你执行步骤,它校验产出、推进状态,人类只在关键决策点介入审批。多 agent 同时操作代码时进度统一落盘、不丢不回滚。
80
+
81
+ 3. 给后续 agent 一个「开工首查」示例:
82
+ ```bash
83
+ sillyspec progress show # 看项目当前阶段/进行中变更
84
+ sillyspec run <stage> # 续跑当前阶段(brainstorm/plan/execute/verify/archive)
85
+ ```
86
+
87
+ ## 分发与安装(本 skill 是引导型)
88
+
89
+ 本 skill 是「接入引导」,只在新项目接入时用一次,**不应随项目复制进 `.claude/skills/` 长期留存**。使用方式二选一:
90
+
91
+ - **项目级一次性**:复制本 `SKILL.md` 到目标项目 `.claude/skills/sillyspec-onboard/SKILL.md`,接入完成后删除。
92
+ - **全局可用**:复制到 `~/.claude/skills/sillyspec-onboard/SKILL.md`(或 `~/.config/claude/skills/`,随 Claude Code 版本),任何新项目都能呼起 `/sillyspec-onboard`。