sillyspec 3.29.4 → 3.30.0

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 (148) hide show
  1. package/.claude/skills/sillyspec-auto/SKILL.md +54 -54
  2. package/.claude/skills/sillyspec-brainstorm/SKILL.md +2 -2
  3. package/.claude/skills/sillyspec-commit/SKILL.md +1 -1
  4. package/.claude/skills/sillyspec-flow/SKILL.md +57 -0
  5. package/.claude/skills/sillyspec-quick/SKILL.md +18 -116
  6. package/AGENTS.md +38 -20
  7. package/SKILL.md +9 -3
  8. package/assets/command-cards/flow.md +32 -0
  9. package/assets/command-cards/run-archive.md +26 -0
  10. package/assets/command-cards/run-brainstorm.md +33 -0
  11. package/assets/command-cards/run-execute.md +29 -0
  12. package/assets/command-cards/run-plan.md +27 -0
  13. package/assets/command-cards/run-quick.md +17 -0
  14. package/assets/command-cards/run-verify.md +29 -0
  15. package/assets/command-cards/status.md +27 -0
  16. package/package.json +2 -1
  17. package/packages/dashboard/server/executor.js +2 -1
  18. package/packages/dashboard/server/parser.js +7 -7
  19. package/r7-test-env/README-R7-TEST.md +93 -0
  20. package/r7-test-env/demo-project/lib/calc.js +6 -0
  21. package/r7-test-env/demo-project/package.json +1 -0
  22. package/r7-test-env/demo-project/test.js +10 -0
  23. package/r7-test-env/prompt-R7-SMOKE.md +41 -0
  24. package/r7-test-env/sillyspec-r7.cmd +3 -0
  25. package/round4/account.mjs +98 -0
  26. package/round4/b1-analyze-task08.mjs +40 -0
  27. package/round4/b1-b1-target-validation.md +32 -0
  28. package/round4/b3a-prompt-audit-result.md +66 -0
  29. package/round4/b3a-prompt-audit.mjs +89 -0
  30. package/round4/brief-autocompact.md +34 -0
  31. package/round4/brief-session-replay.md +50 -0
  32. package/round4/deep-read-synthesis.md +38 -0
  33. package/round4/extract-full.mjs +38 -0
  34. package/round4/extract-timeline.mjs +43 -0
  35. package/round4/find-sessions.mjs +13 -0
  36. package/round4/full-r4-l.md +4707 -0
  37. package/round4/full-r4-o-l.md +4300 -0
  38. package/round4/full-r4-os.md +1681 -0
  39. package/round4/full-r4-sf.md +4255 -0
  40. package/round4/full-r4-sq.md +1734 -0
  41. package/round4/gate-audit-relay-receipt.md +30 -0
  42. package/round4/gate-value-audit.md +52 -0
  43. package/round4/optimization-plan.md +165 -0
  44. package/round4/prereg.md +67 -0
  45. package/round4/prompt-R4-L.md +63 -0
  46. package/round4/prompt-R4-O-L.md +59 -0
  47. package/round4/prompt-R4-O-S.md +56 -0
  48. package/round4/prompt-R4-S-F.md +60 -0
  49. package/round4/prompt-R4-S-Q.md +66 -0
  50. package/round4/r4-final-report.html +347 -0
  51. package/round4/r4-os-timeline.txt +297 -0
  52. package/round4/r4-sf-timeline.txt +738 -0
  53. package/round4/r4-sq-timeline.txt +322 -0
  54. package/round4/r4l-timeline.txt +793 -0
  55. package/round4/r4ol-timeline.txt +729 -0
  56. package/round4/r4sf-timeline.txt +852 -0
  57. package/round4/r5-scenario-matrix.md +46 -0
  58. package/round4/result-S.md +171 -0
  59. package/round4/result-final.md +46 -0
  60. package/round4/result-quality.md +63 -0
  61. package/src/change-list.js +9 -0
  62. package/src/classify-change.js +6 -0
  63. package/src/command-cards.js +74 -0
  64. package/src/commit-guard.js +2 -0
  65. package/src/config-schema.js +64 -12
  66. package/src/contract-matrix.js +26 -5
  67. package/src/db.js +35 -4
  68. package/src/decision-distill.js +9 -3
  69. package/src/diagnostic-codes.js +2 -1
  70. package/src/docs-check.js +1 -1
  71. package/src/doctor-diagnostics.js +44 -2
  72. package/src/flow-draft.js +748 -0
  73. package/src/flow-parity.js +236 -0
  74. package/src/flow-review.js +184 -0
  75. package/src/flow.js +1492 -0
  76. package/src/foreign-declared.js +17 -1
  77. package/src/fr-index.js +396 -22
  78. package/src/fs-atomic.js +5 -1
  79. package/src/git-helper.js +2 -2
  80. package/src/greenfield-bootstrap.js +98 -0
  81. package/src/handoff.js +120 -7
  82. package/src/hunk-attribution.js +191 -0
  83. package/src/index.js +602 -21
  84. package/src/init.js +25 -8
  85. package/src/knowledge-classify.js +47 -1
  86. package/src/knowledge-digest.js +162 -0
  87. package/src/knowledge-quicklog.js +246 -0
  88. package/src/machine-draft.js +128 -0
  89. package/src/machine-interface.js +194 -7
  90. package/src/mcp-server.js +1 -0
  91. package/src/module-impact.js +51 -22
  92. package/src/module-resolve.js +3 -1
  93. package/src/preview-progress.js +160 -0
  94. package/src/progress/change-registry.js +11 -3
  95. package/src/progress/shared.js +3 -2
  96. package/src/progress.js +56 -13
  97. package/src/quicklog.js +44 -6
  98. package/src/redomain.js +147 -0
  99. package/src/review-material-pack.js +204 -1
  100. package/src/run/archive-distill.js +4 -2
  101. package/src/run/bg-sync.js +67 -0
  102. package/src/run/command.js +127 -10
  103. package/src/run/complete-handlers.js +363 -73
  104. package/src/run/complete.js +356 -74
  105. package/src/run/gate-snapshot-ledger.js +213 -0
  106. package/src/run/gate-snapshot.js +260 -38
  107. package/src/run/gates.js +482 -268
  108. package/src/run/green-cache.js +123 -0
  109. package/src/run/junction-rm.js +70 -0
  110. package/src/run/next.js +14 -0
  111. package/src/run/prompt.js +185 -55
  112. package/src/run/quick-audit.js +213 -14
  113. package/src/run/shared.js +123 -4
  114. package/src/run/stage.js +182 -216
  115. package/src/run/test-ledger.js +264 -0
  116. package/src/run/verify-quality-scan.js +84 -7
  117. package/src/scope-audit.js +6 -1
  118. package/src/sentinel-assertions.js +114 -0
  119. package/src/setup.js +3 -3
  120. package/src/spec-sync.js +41 -1
  121. package/src/stage-contract.js +26 -8
  122. package/src/stage-review-checklist.js +2 -0
  123. package/src/stage-review.js +7 -2
  124. package/src/stage-templates.js +157 -0
  125. package/src/stages/archive.js +2 -0
  126. package/src/stages/brainstorm.js +24 -106
  127. package/src/stages/execute.js +222 -85
  128. package/src/stages/knowledge.js +74 -1
  129. package/src/stages/plan-postcheck.js +385 -20
  130. package/src/stages/plan.js +23 -1
  131. package/src/stages/quick.js +10 -2
  132. package/src/stages/verify.js +4 -2
  133. package/src/sync.js +81 -23
  134. package/src/task-done.js +181 -0
  135. package/src/task-review.js +8 -55
  136. package/src/taskcard-frontmatter.js +57 -0
  137. package/src/test-bindings.js +549 -0
  138. package/src/timeline.js +218 -0
  139. package/src/ui-visual.js +175 -0
  140. package/src/verify-draft.js +214 -0
  141. package/src/verify-postcheck.js +919 -159
  142. package/src/verify-probes.js +103 -25
  143. package/src/watcher.js +1031 -0
  144. package/src/worktree-apply.js +44 -4
  145. package/src/worktree-deps.js +22 -8
  146. package/src/worktree-policy.js +42 -0
  147. package/src/worktree.js +102 -15
  148. package/templates/agents-instruction.md +37 -18
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ // B3a prompt 审计 v3(只读,db 全量口径):
3
+ // A. R4-L 主会话 CLI 渲染体量按子命令归因(修正 v2 分类正则)
4
+ // B. 近重复渲染检测(同头签名多次渲染 = 瘦身/缓存首要候选)
5
+ // C. 实跑措辞的规则转发率(execute.js buildWavePrompt 口径)
6
+ // 用法:node b3a-prompt-audit.mjs
7
+ import { DatabaseSync } from 'node:sqlite';
8
+ import { writeFileSync } from 'node:fs';
9
+
10
+ const db = new DatabaseSync('C:/Users/qinyi/.zcode/cli/db/db.sqlite', { readOnly: true });
11
+ const sid = 'sess_5cb66a7e-2ba6-44f9-9916-226fc553778b';
12
+ const parts = db.prepare(
13
+ 'SELECT data, time_created tc FROM part WHERE session_id=? ORDER BY time_created ASC, sequence ASC'
14
+ ).all(sid);
15
+ const t0 = Number(parts[0].tc);
16
+
17
+ const calls = [];
18
+ const agentPrompts = [];
19
+ for (const row of parts) {
20
+ const d = JSON.parse(row.data);
21
+ if (d.type !== 'tool') continue;
22
+ const rel = ((Number(d.time?.created ?? row.tc) - t0) / 60000).toFixed(0);
23
+ const inp = d.state?.input ?? {};
24
+ if (d.tool === 'Bash') {
25
+ const cmd = String(inp.command ?? '');
26
+ if (!/sillyspec/.test(cmd)) continue;
27
+ // 子命令 = sillyspec 后跳过所有 --flag(含带引号值)后的第一个词
28
+ const m = cmd.match(/sillyspec\s+(?:--[\w-]+(?:\s+(?:"[^"]*"|\S+))?\s+)*([\w-]+)/);
29
+ calls.push({ rel, sub: m ? m[1] : '?', chars: String(d.state?.output ?? '').length, out: String(d.state?.output ?? '') });
30
+ }
31
+ if (d.tool === 'Agent' || d.tool === 'Task')
32
+ agentPrompts.push({ rel, prompt: String(inp.prompt ?? '') });
33
+ }
34
+
35
+ const by = {};
36
+ for (const c of calls) {
37
+ by[c.sub] ??= { n: 0, chars: 0, max: 0 };
38
+ by[c.sub].n++; by[c.sub].chars += c.chars; by[c.sub].max = Math.max(by[c.sub].max, c.chars);
39
+ }
40
+ const total = Object.values(by).reduce((s, v) => s + v.chars, 0);
41
+
42
+ // 近重复:输出头部 200 字(压缩空白)做签名
43
+ const sig = {};
44
+ for (const c of calls) {
45
+ const s = c.out.slice(0, 200).replace(/\s+/g, ' ').replace(/\|/g, '/');
46
+ (sig[s] ??= []).push(c);
47
+ }
48
+ const dups = Object.entries(sig).filter(([, v]) => v.length > 1).sort((a, b) => b[1].length - a[1].length);
49
+
50
+ // 实跑措辞规则转发率
51
+ const SIGS = [
52
+ 'workdir 参数是强制必传', '破坏隔离', '调度者 + 审查者', '你不要自己写代码',
53
+ '禁止读', '禁止 push', '工作目录(强制', 'allowed_paths', 'TDD', '先读后写',
54
+ ];
55
+ const cliAll = calls.map(c => c.out).join('\n');
56
+ const agentAll = agentPrompts.map(a => a.prompt).join('\n');
57
+
58
+ const L = [];
59
+ L.push('# B3a prompt 审计——db 全量口径(2026-09-21,v3 修正版)');
60
+ L.push('');
61
+ L.push(`## A. CLI 渲染体量(R4-L 主会话,${calls.length} 次 sillyspec Bash,合计 ${(total / 1024).toFixed(0)}KB ≈ ${Math.round(total / 3.5 / 1000)}K tokens)`);
62
+ L.push('');
63
+ L.push('| 子命令 | 次数 | 累计KB | 最大单次KB |');
64
+ L.push('|---|---|---|---|');
65
+ for (const [k, v] of Object.entries(by).sort((a, b) => b[1].chars - a[1].chars))
66
+ L.push(`| ${k} | ${v.n} | ${(v.chars / 1024).toFixed(1)} | ${(v.max / 1024).toFixed(1)} |`);
67
+ L.push('');
68
+ L.push('## B. 近重复渲染(头部签名相同出现 >1 次——重复注入的直接瘦身候选)');
69
+ L.push('');
70
+ L.push('| 次数 | 单次体量 | 头部签名 |');
71
+ L.push('|---|---|---|');
72
+ for (const [k, v] of dups.slice(0, 10))
73
+ L.push(`| ×${v.length} | ~${(v[0].chars / 1024).toFixed(1)}KB | ${k.slice(0, 90)} |`);
74
+ const dupChars = dups.reduce((s, [, v]) => s + v.length * v[0].chars, 0);
75
+ L.push('');
76
+ L.push(`近重复渲染累计 ≈${(dupChars / 1024).toFixed(0)}KB(占 CLI 渲染总量 ${((dupChars / total) * 100).toFixed(0)}%)。`);
77
+ L.push('');
78
+ L.push('## C. 实跑措辞规则转发率(execute.js buildWavePrompt 口径 → 编排者组装的子代理 prompt)');
79
+ L.push('');
80
+ L.push('| 规则(实跑措辞) | CLI 渲染 | 转发进子代理 prompt |');
81
+ L.push('|---|---|---|');
82
+ for (const s of SIGS)
83
+ L.push(`| ${s} | ${cliAll.split(s).length - 1} | ${agentAll.split(s).length - 1} |`);
84
+ L.push('');
85
+ L.push(`Agent 派发 ${agentPrompts.length} 次,prompt 合计 ${(agentPrompts.reduce((s, a) => s + a.prompt.length, 0) / 1024).toFixed(1)}KB(均值 ${(agentPrompts.reduce((s, a) => s + a.prompt.length, 0) / agentPrompts.length / 1024).toFixed(1)}KB,最大 ${Math.max(...agentPrompts.map(a => a.prompt.length)) / 1024 | 0}KB)。`);
86
+ const outPath = new URL('b3a-prompt-audit-result.md', import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1');
87
+ writeFileSync(outPath, L.join('\n') + '\n', 'utf8');
88
+ console.log(L.join('\n'));
89
+ db.close();
@@ -0,0 +1,34 @@
1
+ ---
2
+ author: qinyi
3
+ created_at: 2026-09-20 17:19:12
4
+ ---
5
+ # 提案书(Proposal)— claude 引擎 autocompact 配置(provider 级)
6
+
7
+ ## 动机
8
+
9
+ claude 引擎长会话在 ~160K tokens 触发引擎自动压缩(默认 believed limit 200K × ~80% 设计点),生产会话(6e213eb3,113 轮)频繁被压。平台无干预手段,用户希望按 provider 配置压缩行为(更晚压缩/关闭/预计算)。
10
+
11
+ ## 关键问题
12
+
13
+ 1. 平台管道已有 `settings_config → lease 透传 → claude-settings 白名单 → settings.json` 机制(attribution 等键先例),但白名单不含任何 autocompact 键——配置写了也不生效。
14
+ 2. 前端 provider 表单无 autocompact 入口,用户只能手改数据库 JSON。
15
+ 3. window 配置超过模型实际窗口会撞硬限报错而非压缩——需要风险提示承载(用户自担的配置面)。
16
+
17
+ ## 变更范围
18
+
19
+ - daemon:claude-settings.ts 白名单加三键(值守护:window 正整数/两开关布尔)。
20
+ - 前端:llm-provider-form claude 分支「引擎自动压缩」区(三键 + 风险提示)。
21
+ - 文档:daemon.md 增量段。
22
+
23
+ ## 不在范围内(显式清单)
24
+
25
+ - profile 级配置(D-001 否决)
26
+ - pi/codex 引擎压缩配置
27
+ - 阈值比例可配(SDK 无可写项)
28
+
29
+ ## 成功标准(可验证)
30
+
31
+ - settings_config 配 `{"autoCompactWindow": 230000}` 的 claude provider 会话,daemon spawn 后 `$CLAUDE_CONFIG_DIR/settings.json` 含该键(单测断言)
32
+ - 三键值守护:window=0/负数/非整数、开关非布尔 → 不写入(单测)
33
+ - 前端表单 claude 分支渲染三键控件并正确提交进 settings_config;非 claude 不渲染(组件测试)
34
+ - 既有 attribution/env 白名单行为零回归(既有用例全绿)
@@ -0,0 +1,50 @@
1
+ ---
2
+ author: qinyi
3
+ created_at: 2026-09-19 20:55:00
4
+ ---
5
+ # 提案书(Proposal)
6
+
7
+ ## 动机
8
+
9
+ SillySpec CLI 自动上报创建的会话(origin=tool_report 且未继续过对话)打开后看到的
10
+ 是**日志元数据卡列表**,不是用户预期的会话内容。用户明确要求:「应该直接按 会话
11
+ 样式展示,只是数据来源不一样而已」「token 信息也要能获取到」「不光 zcode 其他
12
+ agent 也要核对能正确获取与正确显示」。
13
+
14
+ ## 关键问题
15
+
16
+ 1. **形态错位**:对话内容藏在每条日志卡的「查看内容」320px 嵌套小窗里,主对话被
17
+ 埋在元数据与子代理日志中间(实证会话 137ddfff:1 主日志 + 5 条子代理日志),
18
+ 没有「会话」的样子。
19
+ 2. **内容错位**:自主运行日志的 user 角色消息多为系统注入(task-notification),
20
+ 现渲染当用户气泡处理,直接「内容不对」;轮次边界(zcode turnId)与 token 用量
21
+ (response.usage 五项)都在日志里但解析层全部丢弃。
22
+ 3. **harness 覆盖断层**:claude-code 格式规整且含 usage 但无解析器(只能看原文);
23
+ cursor-agent transcript 干净可解析但整条上报链路缺失;cursor IDE 二进制格式点开
24
+ 是 409 死胡同。
25
+
26
+ ## 变更范围
27
+
28
+ - 前端:回放主体组件 AgentReplayBody(适配器 → TurnTimeline 真组件复用)、系统事件
29
+ 中性行、工作会话折叠条、不可用三态、token 徽标与累计显示。
30
+ - daemon:NormalizedLogMessage 扩展(usage/turnId/model/durationMs/sender)+ zcode
31
+ 补字段 + 新增 claude-code、cursor-agent 两个解析器 + RPC totalUsage。
32
+ - backend:messages 端点 schema 可选新字段透传 + gen:types(零表结构改动)。
33
+ - docs:cursor-agent 上报链路跨仓跟进记录。
34
+
35
+ ## 不在范围内(显式清单)
36
+
37
+ - 不做解析产物落库(L3 持久化,单独决策)
38
+ - 不做 cursor-agent 作为 provider 接入(运行时 token 捕获,另行立项)
39
+ - 不做 cursor IDE store.db 对话化(blob 库 + 无 token)
40
+ - 不动已激活 tool_report 会话路径与 chat 会话
41
+ - 不改 sillyspec 仓(cursor-agent 扫描上报仅记录跨仓跟进)
42
+
43
+ ## 成功标准(可验证)
44
+
45
+ - 打开纯 tool_report 会话:主体即会话时间线(对话/全部视图可用),主日志为正文、
46
+ 子代理在「工作会话」折叠条,系统事件显示为中性行非用户气泡。
47
+ - zcode/claude-code 回放可见每轮 token(输入/输出/上下文)与会话累计;数据源无
48
+ token(cursor-agent)时显示「未知」。
49
+ - 老 daemon / 机器离线 / 格式不支持 / 文件缺失时回退到显式中文提示,不弹错框。
50
+ - 全量既有测试不受影响(activated 路径、查看内容语义、上报/归属链路零改动)。
@@ -0,0 +1,38 @@
1
+ # R4 五会话全量深读·综合判读(2026-09-21,四子代理并行精读)
2
+
3
+ ## 一、「质量差距是不是小概率」的最终答案:不是,两记实锤
4
+
5
+ **实锤 1:大任务 OpenSpec 侧存在同类缺陷。** R4-O-L 的 daemon 解析器 registry 键名(`claude-code-transcript-jsonl` 等)是**按命名惯例自造的**,未与上报侧(sillyspec CLI,禁读无法对证)核验;且仓内既有测试常量 `claude-transcript-jsonl` 已经暗示了另一种命名——若不符,解析器永不触发、静默 unsupported,**流程内无任何环节能发现**。与错键(autoCompactPreCompute)同一缺陷类:**外部契约事实未经核验即落码,自洽测试掩护其穿越全部关卡**。两个独立 OpenSpec 跑、两实例——这是系统性暴露面,不是运气。
6
+
7
+ **实锤 2(最锐利):两个 agent 生成了同一个错误先验。** R4-S-Q(sillyspec)在 [3.2m] 同样猜了 `autoCompactPrecompute`、[3.9m] 甚至专门搜了这个词——**但先验证再落码**,搜出真名 `precomputeCompactionEnabled`。同模型、同先验、同错误生成;唯一差别是有无验证步。**错误生成是确定性的,拦截是结构性的。**
8
+
9
+ B 侧错键穿越了六道关卡(proposal→spec→design→tasks→测试→archive),全绿——格式校验不校验事实,文档链越长只是把同一个错复制得更体面。
10
+
11
+ ## 二、效率面的新分解(深读修正)
12
+
13
+ **R4-L(185min)**:~118min(64%)是子代理扇出等待+后台门禁+额度事故(4 路并发派发触发额度耗尽,中断 ~17min 由用户恢复);主代理自身生成 <1/3;无效功 ~28min(CLI 旗标摩擦、review.json 两次归位、Wave6 --done 因输出 tail 截断三连跑、verify-result 槽格式学费、嵌套 worktree 下 module-docs-sync 失效、重复 pnpm install)。代码层零返工、15 commit 全净;无联网核验但用本机真实数据(38 个 cursor store.db 全量实测)做了更硬的核验。
14
+
15
+ **R4-O-L(80min)快的解剖**:零子代理(省 40-60m)+ 决策链短(20-30m)+ 只跑相关测试(10-20m)+ 无视觉验收(10-15m)+ 无独立审查(10-20m)+ 探查前置零返工。反直觉:探查占 24%(快来自读得多);最大黑洞是环境(venv/转义 ~8m);最强审查者是遗留测试套件(7 处精确 toEqual 断言逼显式化契约变更)。
16
+
17
+ **R4-S-F(171min)**:verify 92min 中 **75-80min(82%)是纯门禁运行**(7 次 --done、9 次全量门禁);agent 有效工作仅 ~15m。三方拆账:CLI ≈50%、agent ≈12%、环境 ≈6%。新发现的结构性问题:① 同一 CLI 内 `gate verify`(独立跑)PASS 与 `verify --done` FAIL 并存——**两套矛盾判定路径误导诊断 16min**;② 「越正确越被罚」——agent 正确地不动并行会话归属的债文件,快照 overlay 因此永远取 HEAD 带债版,门禁结构性奖励越权改他人文件;③ 根因(快照说明+advisory 提示)一直躺在后台日志里,晚读全文多烧 20min。**重跑地板:不改工具 ~60min;修三处(lint 前置/门禁缓存/检查前置)~45min**——全流程与 quick 的合理差距应是 ~20min 仪式成本,不是本次的 130min。
18
+
19
+ **小任务对(41.2 vs 21.5)**:19.7min 差逐项对平——两轮门禁 +19.9m(纯等待)、存量债清偿 +1.9m、联网核验 +1.2m、stash 对照 +0.6m、终态观测 +1.3m,减 B 的四件套/排障/阅读 ~6.7m。**两侧纯编码测试速度等价**(5-6m)。A 的门禁误拦反而触发正向行为(清债+全量复验拿到 mypy 963 文件级保证)。
20
+
21
+ ## 三、两侧 agent 的真实面貌(修正刻板印象)
22
+
23
+ - OpenSpec 侧 agent **探索纪律很强**(真实数据探针、搜而不信、诚实披露风险)——缺陷不在 agent 能力,在流程无核验结构。
24
+ - sillyspec 侧 R4-S-F 的排障有 15min 绕路(未早读日志全文)、两次被 gate verify 的误导 PASS 带偏。
25
+ - B 侧两个真亮点值得吸收:**前端依赖后台安装与改码并行**(墙钟并行度);**三态下拉表达「键缺省 vs 显式 false」**(语义优于 A 的不对称 checkbox)。
26
+
27
+ ## 四、修复清单增量(在已办五项 + 两缺口之外,新增)
28
+
29
+ 1. **`gate verify` 与 `verify --done` 判定路径统一**(矛盾输出,16min 级误导)
30
+ 2. 门禁失败输出 tail 截断问题(Wave6 三连跑根因)——失败时给全量日志路径提示
31
+ 3. 嵌套 worktree 下 module-docs-sync 失效(24 文件全未匹配)
32
+ 4. verify-result 槽格式旧版拒收的一次性学费(--init 提示要更早)
33
+ 5. 编排层:并发派发上限感知(4 路齐发触发额度耗尽)
34
+ 6. (对 OpenSpec 的镜像建议,供对比参考):外部契约事实表 + 来源强制校验 + vendored sdk.d.ts 的 10 秒 grep 检查——错键当场现形
35
+
36
+ ## 五、方法论沉淀
37
+
38
+ 「验证全在模型侧(自愿)」与「验证全在机器侧(盲跑)」恰好各错一半——两个流程的真正差距不是仪式多少,而是**防线是否对准缺陷类**:OpenSpec 六道格式关零事实核验;sillyspec 有事实核验结构但机器门禁 40%+ 假拦+双跑浪费。
@@ -0,0 +1,38 @@
1
+ // 全量会话导出:node extract-full.mjs <session前缀> <输出文件>
2
+ // 正文全量、reasoning 截 300、工具输入截 500(命令全文)、工具输出截 700
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ import { writeFileSync } from 'node:fs';
5
+
6
+ const [prefix, outFile] = process.argv.slice(2);
7
+ const db = new DatabaseSync('C:/Users/qinyi/.zcode/cli/db/db.sqlite', { readOnly: true });
8
+ const sess = db.prepare('SELECT id, title, time_created FROM session WHERE id LIKE ?').get('sess_' + prefix + '%');
9
+ if (!sess) { console.error('not found'); process.exit(1); }
10
+
11
+ const parts = db.prepare(
12
+ `SELECT p.data, p.time_created tc, JSON_EXTRACT(m.data,'$.role') role
13
+ FROM part p JOIN message m ON p.message_id = m.id
14
+ WHERE p.session_id = ? ORDER BY p.time_created ASC, p.sequence ASC`
15
+ ).all(sess.id);
16
+
17
+ const t0 = Number(sess.time_created);
18
+ const lines = [`# ${sess.title}`, `# 会话 ${sess.id} 起点 ${new Date(t0).toISOString()}`, ''];
19
+ for (const row of parts) {
20
+ const d = JSON.parse(row.data);
21
+ const rel = ((Number(d.time?.created ?? row.tc) - t0) / 60000).toFixed(1);
22
+ const clean = (s, n) => String(s ?? '').replace(/\u001b\[[0-9;]*m/g, '').slice(0, n);
23
+ if (d.type === 'text') {
24
+ lines.push(`\n[${rel}m] ${String(row.role).toUpperCase()} 正文:\n${clean(d.text, 6000)}`);
25
+ } else if (d.type === 'reasoning') {
26
+ const r = clean(d.text ?? d.summary, 300);
27
+ if (r.trim()) lines.push(`[${rel}m] (思考) ${r}`);
28
+ } else if (d.type === 'tool') {
29
+ const inp = d.state?.input ?? {};
30
+ const key = inp.command ?? inp.file_path ?? inp.path ?? inp.pattern ?? inp.prompt ?? JSON.stringify(inp);
31
+ lines.push(`\n[${rel}m] 🛠 ${d.tool} ${d.state?.status === 'running' ? '(未完成)' : ''}\n 输入: ${clean(key, inp.command ? 2500 : 500)}`);
32
+ const out = clean(String(d.state?.output ?? ''), 700);
33
+ if (out.trim()) lines.push(` 输出: ${out.replace(/\n+/g, '\n ')}`);
34
+ }
35
+ }
36
+ writeFileSync(outFile, lines.join('\n'), 'utf8');
37
+ console.log(`wrote ${outFile}: ${lines.length} lines, ${(lines.join('\n').length / 1024).toFixed(0)}KB`);
38
+ db.close();
@@ -0,0 +1,43 @@
1
+ // 用法:node extract-timeline.mjs <session前缀> <输出文件>
2
+ // 从 zcode db.sqlite 提取会话时间线:文本节选 + 工具调用(名/输入头/输出头)
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ import { writeFileSync } from 'node:fs';
5
+
6
+ const [prefix, outFile] = process.argv.slice(2);
7
+ const db = new DatabaseSync('C:/Users/qinyi/.zcode/cli/db/db.sqlite', { readOnly: true });
8
+
9
+ const sess = db.prepare('SELECT id FROM session WHERE id LIKE ?').get('sess_' + prefix + '%');
10
+ if (!sess) { console.error('session not found'); process.exit(1); }
11
+
12
+ const parts = db.prepare(
13
+ `SELECT p.data, m.time_created mt, JSON_EXTRACT(m.data,'$.role') role
14
+ FROM part p JOIN message m ON p.message_id = m.id
15
+ WHERE p.session_id = ? ORDER BY p.sequence`
16
+ ).all(sess.id);
17
+
18
+ const t0 = parts.length ? Number(JSON.parse(parts[0].data).time?.created ?? parts[0].mt) : 0;
19
+ const lines = [];
20
+ let lastTs = t0;
21
+ for (const row of parts) {
22
+ const d = JSON.parse(row.data);
23
+ const ts = Number(d.time?.created ?? row.mt);
24
+ if (ts > lastTs) lastTs = ts;
25
+ const rel = ((ts - t0) / 60000).toFixed(1);
26
+ const one = (s, n) => String(s ?? '').replace(/\s+/g, ' ').slice(0, n);
27
+ if (d.type === 'text') {
28
+ lines.push(`[${rel}m] ${row.role?.toUpperCase()} TEXT: ${one(d.text, 200)}`);
29
+ } else if (d.type === 'reasoning') {
30
+ // 只留极短摘要,标注存在性
31
+ lines.push(`[${rel}m] ${row.role?.toUpperCase()} think: ${one(d.text ?? d.summary, 90)}`);
32
+ } else if (d.type === 'tool') {
33
+ const inp = d.state?.input ?? {};
34
+ const key = inp.file_path ?? inp.command ?? inp.path ?? inp.pattern ?? JSON.stringify(inp);
35
+ const outHead = one(String(d.state?.output ?? ''), 140);
36
+ lines.push(`[${rel}m] TOOL ${d.tool}: ${one(key, 150)}`);
37
+ if (outHead) lines.push(` → ${outHead}`);
38
+ }
39
+ }
40
+ lines.push(`\n[last-part @ +${((lastTs - t0) / 60000).toFixed(1)}m]`);
41
+ writeFileSync(outFile, lines.join('\n'), 'utf8');
42
+ console.log(`wrote ${outFile}: ${lines.length} lines, span ${((lastTs - t0) / 60000).toFixed(1)}min`);
43
+ db.close();
@@ -0,0 +1,13 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ const db = new DatabaseSync('C:/Users/qinyi/.zcode/cli/db/db.sqlite', { readOnly: true });
3
+ const from = Date.parse('2026-09-20T15:00:00+08:00');
4
+ const to = Date.parse('2026-09-21T06:00:00+08:00');
5
+ console.log('window', from, '->', to, new Date(from).toISOString());
6
+ const rows = db.prepare(
7
+ 'SELECT id, title, time_created, parent_id FROM session WHERE time_created >= ? AND time_created <= ? ORDER BY time_created'
8
+ ).all(from, to);
9
+ for (const r of rows) {
10
+ const top = r.parent_id ? ' child-of-' + String(r.parent_id).slice(5, 13) : 'TOP ';
11
+ console.log(new Date(Number(r.time_created)).toISOString().slice(5, 16), top, r.id.slice(5, 13), (r.title || '').slice(0, 75));
12
+ }
13
+ db.close();