sillyspec 3.26.15 → 3.27.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-explore/SKILL.md +10 -3
- package/.claude/skills/sillyspec-verify/SKILL.md +2 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/packages/dashboard/server/index.js +22 -6
- package/src/change-risk-profile.js +21 -6
- package/src/db.js +14 -3
- package/src/docs-check.js +598 -570
- package/src/doctor-diagnostics.js +53 -1
- package/src/endpoint-extractor.js +21 -2
- package/src/fs-atomic.js +4 -2
- package/src/git-helper.js +73 -5
- package/src/hooks/claude-pre-tool-use.cjs +10 -5
- package/src/hooks/worktree-guard.js +22 -3
- package/src/index.js +49 -6
- package/src/module-impact.js +21 -1
- package/src/module-resolve.js +211 -0
- package/src/modules.js +82 -2
- package/src/progress/step-store.js +12 -8
- package/src/progress.js +6 -2
- package/src/run/complete-handlers.js +17 -2
- package/src/run/complete.js +43 -7
- package/src/run/gates.js +83 -14
- package/src/run/prompt.js +16 -2
- package/src/run/quick-audit.js +5 -2
- package/src/run/shared.js +46 -18
- package/src/run/stage.js +37 -3
- package/src/stage-contract.js +14 -1
- package/src/stages/archive.js +3 -1
- package/src/stages/execute.js +170 -18
- package/src/stages/explore.js +11 -2
- package/src/stages/quick.js +4 -3
- package/src/stages/verify.js +9 -2
- package/src/sync.js +44 -3
- package/src/task-review.js +55 -7
- package/src/taskcard.js +52 -22
- package/src/verify-postcheck.js +223 -6
- package/src/worktree-apply.js +28 -10
- package/src/worktree-deps.js +59 -5
- package/src/worktree.js +70 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sillyspec:explore
|
|
3
|
-
description: 用于自由讨论、代码库调研、方案比较、画 ASCII
|
|
3
|
+
description: 用于自由讨论、代码库调研、方案比较、画 ASCII 图、澄清问题、生成 HTML 原型。适合用户说"分析下、讨论下、看看怎么设计、先别写代码、调研一下、画个结构图、帮我再分析下、画个原型、出个原型图、做个 demo 页"。默认只读不修改文件(仅用户明确要求时保存结论或生成原型),不实现功能。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## 交互规范
|
|
@@ -33,7 +33,7 @@ sillyspec run explore --status # 查看阶段状态
|
|
|
33
33
|
|
|
34
34
|
## 这是什么模式
|
|
35
35
|
|
|
36
|
-
**探索模式用于思考,不用于实现。**
|
|
36
|
+
**探索模式用于思考,不用于实现。** 你可以读文件、搜代码、调查代码库,但默认不写任何文件(用户明确要求保存结论或生成原型时除外),也绝不写实现代码。如果用户要求实现,提醒他们先退出探索模式。
|
|
37
37
|
|
|
38
38
|
**这不是一个工作流,是一种姿态。** 没有固定步骤、没有必需的输出。你是一个帮助用户思考的伙伴。
|
|
39
39
|
|
|
@@ -66,6 +66,12 @@ sillyspec run explore --status # 查看阶段状态
|
|
|
66
66
|
└─────────────────────────────────┘
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
+
**生成 HTML 原型**(仅用户明确要求时):讨论 UI/交互方案时,用户说"画个原型、出个原型图、做个 demo 页"才动手,平时最多提议。生成要求与 brainstorm 阶段原型对齐:
|
|
70
|
+
- 单文件 HTML(内联 CSS + JS),浏览器直接打开
|
|
71
|
+
- 高保真呈现讨论中的布局/组件/交互流程,风格对齐项目现有界面(先读 scan 文档与前端代码)
|
|
72
|
+
- 保存到 `.sillyspec/explore/prototype-<名称>.html`(用户指定其他位置则从其指定)
|
|
73
|
+
- 探索原型是讨论工具、不是交付物,也不是实现代码;后续进入 brainstorm 时可复制到变更目录复用
|
|
74
|
+
|
|
69
75
|
**暴露风险**:识别可能出错的地方、发现理解空白
|
|
70
76
|
|
|
71
77
|
## OpenSpec 上下文感知
|
|
@@ -90,6 +96,7 @@ cat .sillyspec/ROADMAP.md 2>/dev/null
|
|
|
90
96
|
|
|
91
97
|
- ❌ 写实现代码
|
|
92
98
|
- ❌ 安装依赖
|
|
93
|
-
- ❌
|
|
99
|
+
- ❌ 修改任何文件(除非用户明确要求保存发现或生成原型)
|
|
100
|
+
- ❌ 主动生成原型(必须用户明确要求;最多提议)
|
|
94
101
|
- ❌ 强行下结论
|
|
95
102
|
- ❌ 强行结构化(让模式自然涌现)
|
|
@@ -52,6 +52,8 @@ verify 是只读阶段(**禁止改代码/改 git 状态**,只检查 + 写报
|
|
|
52
52
|
## verify-result.md 格式
|
|
53
53
|
|
|
54
54
|
> 🔧 **机械探针 + 报告骨架一条命令**:`sillyspec verify-probes --change <变更名> --init`——探针 1(TODO 标记)/3(测试覆盖)/5(API 契约对账)/6(删除对账)CLI 跑完并预填进 verify-result.md 骨架(七章节、已存在不覆盖);探针 2/4(关键词/决策追踪)与断言抽查、集成盲区标注是语义判断,替换骨架里的 `<!--TODO-->` 完成。结论必须写明 PASS/FAIL——留「待填」会被 gate 判不过。
|
|
55
|
+
>
|
|
56
|
+
> 🔧 **test/lint 实测对账**:`--done` 时 CLI 亲自执行 local.yaml 的 `commands.test`(实测失败阻断 verify 完成)与 `commands.lint`(advisory 对账,实测失败会明示)——自报告与实测不符时以实测为准,勿谎报跑过。
|
|
55
57
|
|
|
56
58
|
```markdown
|
|
57
59
|
# 验证报告
|
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ SillySpec 进度库使用 SQLite 持久化(基于 Node.js 内置的 `node:sqli
|
|
|
109
109
|
|---|---|
|
|
110
110
|
| `/sillyspec:status` · `/sillyspec:state` | 查看进度 / 当前工作状态 |
|
|
111
111
|
| `/sillyspec:continue` | 自动判断并执行下一步 |
|
|
112
|
-
| `/sillyspec:explore` |
|
|
112
|
+
| `/sillyspec:explore` | 自由思考:画图、讨论、调研、HTML 原型 |
|
|
113
113
|
| `/sillyspec:quick` | 快速模式:跳过完整流程 |
|
|
114
114
|
| `/sillyspec:resume` | 恢复工作(支持大模块阶段进度) |
|
|
115
115
|
| `/sillyspec:doctor` | 项目自检与状态修复 |
|
package/package.json
CHANGED
|
@@ -468,10 +468,19 @@ function startServer({ port = 3456, open: openBrowser = true } = {}) {
|
|
|
468
468
|
res.end(JSON.stringify({ error: 'Missing project parameter' }))
|
|
469
469
|
return
|
|
470
470
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
471
|
+
// SEC-06 对齐:detail/content API 均已限"已发现项目内",此处此前漏校验——
|
|
472
|
+
// 任意绝对路径可列其 .sillyspec/docs 树与根文档文件名
|
|
473
|
+
isKnownProjectPath(projectPath).then(known => {
|
|
474
|
+
if (!known) {
|
|
475
|
+
res.writeHead(403)
|
|
476
|
+
res.end(JSON.stringify({ error: 'Unknown project path' }))
|
|
477
|
+
return
|
|
478
|
+
}
|
|
479
|
+
const docs = parseSillyspecDocsTree(projectPath)
|
|
480
|
+
res.setHeader('Content-Type', 'application/json')
|
|
481
|
+
res.writeHead(200)
|
|
482
|
+
res.end(JSON.stringify(docs))
|
|
483
|
+
})
|
|
475
484
|
return
|
|
476
485
|
}
|
|
477
486
|
|
|
@@ -591,8 +600,15 @@ function startServer({ port = 3456, open: openBrowser = true } = {}) {
|
|
|
591
600
|
break
|
|
592
601
|
case 'docs:get':
|
|
593
602
|
if (data.data?.projectPath) {
|
|
594
|
-
|
|
595
|
-
|
|
603
|
+
// SEC-06 对齐:与 /api/docs 同口径,仅已发现项目可列 docs 树
|
|
604
|
+
isKnownProjectPath(data.data.projectPath).then(known => {
|
|
605
|
+
if (!known) {
|
|
606
|
+
ws.send(JSON.stringify({ type: 'docs:tree', data: { error: 'Unknown project path' } }))
|
|
607
|
+
return
|
|
608
|
+
}
|
|
609
|
+
const docs = parseSillyspecDocsTree(data.data.projectPath)
|
|
610
|
+
ws.send(JSON.stringify({ type: 'docs:tree', data: docs }))
|
|
611
|
+
})
|
|
596
612
|
}
|
|
597
613
|
break
|
|
598
614
|
default:
|
|
@@ -90,19 +90,29 @@ export const VERIFICATION_NEEDS = {
|
|
|
90
90
|
},
|
|
91
91
|
real_daemon_backend_integration: {
|
|
92
92
|
desc: '真实 daemon↔backend 集成验证(非仅 mock 单测)。写「真实集成/端到端」的证据;',
|
|
93
|
-
|
|
93
|
+
// 同义扩充(坑 verify-literal-evidence-mismatch,2026-08-22 实证:证据第一轮就齐但表述
|
|
94
|
+
// 不含字面词被误拦三轮)——覆盖常见自然表述 + PID 登记句式(verify prompt 要求照写)
|
|
95
|
+
literals: ['端到端', 'integration test', 'e2e test', 'daemon.*backend', '真实集成',
|
|
96
|
+
'runtime evidence', '运行时证据', '联调', '打通', '实际请求', '真实请求', '跨进程',
|
|
97
|
+
'PID 已登记', 'verify-services'],
|
|
94
98
|
},
|
|
95
99
|
runtime_log_evidence: {
|
|
96
100
|
desc: 'Runtime Evidence section + 指向真实日志/证据片段。',
|
|
97
|
-
literals: ['Runtime Evidence', '运行时证据', 'daemon log', '日志片段'
|
|
101
|
+
literals: ['Runtime Evidence', '运行时证据', 'daemon log', '日志片段', '日志关键',
|
|
102
|
+
'日志:', '日志摘录', '日志', 'log 摘录', 'log 片段', '进程日志', 'PID 已登记', 'verify-services'],
|
|
98
103
|
},
|
|
99
104
|
real_startup_once: {
|
|
100
105
|
desc: '真实启动一次本变更触及的部署/启动入口(服务入口、CLI 主入口、守护进程等——须是本变更实际改动的那一类入口,不能拿无关进程的启动来凑数)。',
|
|
101
|
-
|
|
106
|
+
// 同义扩充(同坑):自然表述 + CLI 回执句式;checkIntegrationEvidence 另拼 CLI 回执文本
|
|
107
|
+
//(verify-services.receipt.json,服务回收器落盘)——结构化信号不依赖 agent 措辞
|
|
108
|
+
literals: ['启动.*一次', '实际.*启动', 'real startup', 'docker up', 'npm start', 'node server',
|
|
109
|
+
'真实启动', '拉起', '已启动', '进程启动', '服务启动', '启动验证',
|
|
110
|
+
'PID 已登记', 'verify-services'],
|
|
102
111
|
},
|
|
103
112
|
terminal_state_assertion: {
|
|
104
113
|
desc: '终态断言(建议项,不阻断):AgentRun running→completed/failed、session/lease end 状态同步。',
|
|
105
|
-
literals: ['terminal state', '终态', 'completed failed', 'session end', 'lease end'
|
|
114
|
+
literals: ['terminal state', '终态', 'completed failed', 'session end', 'lease end',
|
|
115
|
+
'生命周期终态', '状态同步'],
|
|
106
116
|
},
|
|
107
117
|
}
|
|
108
118
|
|
|
@@ -202,11 +212,16 @@ export function detectChangeRisk({ designContent = '', planContent = '', changed
|
|
|
202
212
|
|
|
203
213
|
/**
|
|
204
214
|
* 检查 verify-result.md 是否包含集成验证证据
|
|
215
|
+
*
|
|
216
|
+
* opts.extraEvidenceText(坑 verify-literal-evidence-mismatch,2026-08-22):调用方可注入
|
|
217
|
+
* CLI 结构化回执文本(如 verify-services.receipt.json 的服务回收回执)——它随 verifyContent
|
|
218
|
+
* 一起参与 literals 匹配,agent 真实起过服务且 CLI 回收过(有回执)时不再依赖其自然语言
|
|
219
|
+
* 措辞恰好含字面词,表述差异不再误拦。
|
|
205
220
|
*/
|
|
206
|
-
export function checkIntegrationEvidence(verifyContent, requiredVerification) {
|
|
221
|
+
export function checkIntegrationEvidence(verifyContent, requiredVerification, opts = {}) {
|
|
207
222
|
const errors = []
|
|
208
223
|
const warnings = []
|
|
209
|
-
const lower = verifyContent.toLowerCase()
|
|
224
|
+
const lower = (String(verifyContent || '') + '\n' + String(opts.extraEvidenceText || '')).toLowerCase()
|
|
210
225
|
|
|
211
226
|
// 字面证据正则从 VERIFICATION_NEEDS[k].literals 派生——与报错描述、prompt 事前契约严格同源,
|
|
212
227
|
// 杜绝历史上"描述说 A、正则查 B"的分叉(checkIntegrationEvidence 正则曾比 VERIFICATION_NEEDS
|
package/src/db.js
CHANGED
|
@@ -105,13 +105,19 @@ export class DB {
|
|
|
105
105
|
if (!existsSync(p)) return null;
|
|
106
106
|
return statSync(p).size === 0 ? 'empty' : 'ok';
|
|
107
107
|
};
|
|
108
|
-
// tryOpen: openDatabase(path) + prepare 探测双保险(防打开成功但内容非 SQLite
|
|
108
|
+
// tryOpen: openDatabase(path) + prepare 探测双保险(防打开成功但内容非 SQLite)。
|
|
109
|
+
// 探测前先设 busy_timeout(2026-08-21 审查 BUG-7):init() 的 applyPragmas 在 _openWithFallback
|
|
110
|
+
// 之后才跑,探测 SELECT 此前以 busy_timeout=0(SQLite 默认)执行——他者进程 CHECKPOINT 改写
|
|
111
|
+
// 主库时探测立即 SQLITE_BUSY,3 次重试总窗口仅 350ms,大 WAL 下 checkpoint 秒级 → 健康库
|
|
112
|
+
// 被误判"损坏"硬抛错。先设 busy_timeout 让探测自身等待锁,重试只剩消化瞬时抖动。
|
|
109
113
|
const tryOpen = (p) => {
|
|
110
114
|
let db;
|
|
111
115
|
try { db = openDatabase(p); }
|
|
112
116
|
catch { return null; }
|
|
113
|
-
try {
|
|
114
|
-
|
|
117
|
+
try {
|
|
118
|
+
db.exec('PRAGMA busy_timeout = 5000');
|
|
119
|
+
db.prepare('SELECT count(*) FROM sqlite_master').get(); return db;
|
|
120
|
+
} catch { try { db.close(); } catch { /* 关闭失败忽略 */ } return null; }
|
|
115
121
|
};
|
|
116
122
|
|
|
117
123
|
// 1. 主库(0 字节=截断信号,必须走回退,故门禁要求 'ok' 有内容)
|
|
@@ -144,6 +150,11 @@ export class DB {
|
|
|
144
150
|
: 'sillyspec.db 损坏';
|
|
145
151
|
console.warn(`⚠️ ${reason},已从 .bak 备份恢复。`);
|
|
146
152
|
bakDb.close();
|
|
153
|
+
// 覆盖前救援快照(2026-08-21 审查 BUG-7):主库有内容但打不开("损坏")时,其中可能
|
|
154
|
+
// 含比 .bak 更新的数据——静默覆盖即静默丢。best-effort 留一份 .corrupt-<ts> 副本供人工恢复。
|
|
155
|
+
if (primaryRaw === 'ok') {
|
|
156
|
+
try { copyFileSync(this.dbPath, `${this.dbPath}.corrupt-${Date.now()}`); } catch { /* 救援失败不阻断恢复 */ }
|
|
157
|
+
}
|
|
147
158
|
// node:sqlite 绑定路径,无 _save:把 .bak 内容 copy 回主库,统一用 dbPath。
|
|
148
159
|
// 体检 BUG-18:主库可能正被其他进程(daemon/另一 CLI)打开——Windows 覆盖他人
|
|
149
160
|
// 打开的文件抛 EPERM/EBUSY,短暂退避重试(持有者通常是瞬时句柄),仍失败 fail-loud
|