sillyspec 3.29.5 → 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 (110) 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-brainstorm.md +1 -1
  10. package/assets/command-cards/run-quick.md +8 -25
  11. package/package.json +2 -1
  12. package/packages/dashboard/server/executor.js +2 -1
  13. package/packages/dashboard/server/parser.js +7 -7
  14. package/r7-test-env/README-R7-TEST.md +93 -0
  15. package/r7-test-env/demo-project/lib/calc.js +6 -0
  16. package/r7-test-env/demo-project/package.json +1 -0
  17. package/r7-test-env/demo-project/test.js +10 -0
  18. package/r7-test-env/prompt-R7-SMOKE.md +41 -0
  19. package/r7-test-env/sillyspec-r7.cmd +3 -0
  20. package/round4/account.mjs +18 -5
  21. package/round4/b1-analyze-task08.mjs +40 -0
  22. package/round4/b1-b1-target-validation.md +32 -0
  23. package/round4/b3a-prompt-audit-result.md +66 -0
  24. package/round4/b3a-prompt-audit.mjs +89 -0
  25. package/round4/optimization-plan.md +165 -0
  26. package/round4/r4-final-report.html +347 -0
  27. package/round4/r5-scenario-matrix.md +46 -0
  28. package/src/change-list.js +9 -0
  29. package/src/classify-change.js +6 -0
  30. package/src/command-cards.js +2 -1
  31. package/src/commit-guard.js +2 -0
  32. package/src/config-schema.js +64 -12
  33. package/src/db.js +35 -4
  34. package/src/decision-distill.js +9 -3
  35. package/src/docs-check.js +1 -1
  36. package/src/doctor-diagnostics.js +44 -2
  37. package/src/flow-draft.js +748 -0
  38. package/src/flow-parity.js +236 -0
  39. package/src/flow-review.js +184 -0
  40. package/src/flow.js +1492 -0
  41. package/src/foreign-declared.js +17 -1
  42. package/src/fr-index.js +396 -22
  43. package/src/fs-atomic.js +5 -1
  44. package/src/git-helper.js +2 -2
  45. package/src/greenfield-bootstrap.js +98 -0
  46. package/src/handoff.js +120 -7
  47. package/src/hunk-attribution.js +191 -0
  48. package/src/index.js +570 -16
  49. package/src/knowledge-classify.js +47 -1
  50. package/src/knowledge-digest.js +162 -0
  51. package/src/knowledge-quicklog.js +246 -0
  52. package/src/machine-draft.js +128 -0
  53. package/src/machine-interface.js +107 -5
  54. package/src/mcp-server.js +1 -0
  55. package/src/module-resolve.js +3 -1
  56. package/src/preview-progress.js +160 -0
  57. package/src/progress/change-registry.js +11 -3
  58. package/src/progress/shared.js +3 -2
  59. package/src/progress.js +56 -13
  60. package/src/quicklog.js +44 -6
  61. package/src/redomain.js +147 -0
  62. package/src/review-material-pack.js +204 -1
  63. package/src/run/archive-distill.js +4 -2
  64. package/src/run/bg-sync.js +67 -0
  65. package/src/run/command.js +123 -10
  66. package/src/run/complete-handlers.js +327 -72
  67. package/src/run/complete.js +350 -71
  68. package/src/run/gate-snapshot-ledger.js +213 -0
  69. package/src/run/gate-snapshot.js +250 -34
  70. package/src/run/gates.js +370 -233
  71. package/src/run/green-cache.js +123 -0
  72. package/src/run/junction-rm.js +70 -0
  73. package/src/run/next.js +14 -0
  74. package/src/run/prompt.js +185 -55
  75. package/src/run/quick-audit.js +185 -12
  76. package/src/run/shared.js +120 -3
  77. package/src/run/stage.js +182 -216
  78. package/src/run/test-ledger.js +264 -0
  79. package/src/run/verify-quality-scan.js +84 -7
  80. package/src/scope-audit.js +6 -1
  81. package/src/sentinel-assertions.js +114 -0
  82. package/src/setup.js +3 -3
  83. package/src/spec-sync.js +41 -1
  84. package/src/stage-contract.js +26 -8
  85. package/src/stage-review-checklist.js +2 -0
  86. package/src/stage-review.js +7 -2
  87. package/src/stage-templates.js +157 -0
  88. package/src/stages/archive.js +2 -0
  89. package/src/stages/brainstorm.js +24 -106
  90. package/src/stages/execute.js +221 -84
  91. package/src/stages/knowledge.js +74 -1
  92. package/src/stages/plan-postcheck.js +352 -1
  93. package/src/stages/plan.js +23 -1
  94. package/src/stages/quick.js +10 -2
  95. package/src/stages/verify.js +4 -2
  96. package/src/sync.js +81 -23
  97. package/src/task-done.js +181 -0
  98. package/src/task-review.js +8 -55
  99. package/src/test-bindings.js +549 -0
  100. package/src/timeline.js +218 -0
  101. package/src/ui-visual.js +175 -0
  102. package/src/verify-draft.js +214 -0
  103. package/src/verify-postcheck.js +860 -158
  104. package/src/verify-probes.js +59 -3
  105. package/src/watcher.js +1031 -0
  106. package/src/worktree-apply.js +44 -4
  107. package/src/worktree-deps.js +22 -8
  108. package/src/worktree-policy.js +42 -0
  109. package/src/worktree.js +102 -15
  110. package/templates/agents-instruction.md +37 -18
@@ -28,11 +28,13 @@ import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from '
28
28
  import { join, dirname, basename, resolve, isAbsolute, relative } from 'path'
29
29
  import { gitQuiet, unquoteGitPath } from './git-helper.js'
30
30
  import { hasUnconfirmedPrefill } from './prefill.js'
31
+ import { runUiVisualProbe, renderUiVisualProbeLines, readUiVisualGate } from './ui-visual.js'
31
32
  import {
32
33
  FACTS_SCHEMA_VERSION, EVIDENCE_SLOT_HEADING, RECEIPT_SLOT_HEADING, parseEvidenceSlots,
33
34
  } from './verify-facts-schema.js'
34
35
  import { parseFileChangeListDetailed } from './change-list.js'
35
36
  import { parseDecisions } from './decision-distill.js'
37
+ import { writeChangeTrace, orphanAccRef } from './test-bindings.js'
36
38
  import { parseAllowedPaths, parseRepo, parseRepoRegistry } from './stages/plan-postcheck.js'
37
39
  import { verifyApiParity, _readWorktreeMeta } from './contract-matrix.js'
38
40
  import { parseTaskFrontmatter } from './taskcard-frontmatter.js'
@@ -2222,6 +2224,36 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
2222
2224
  hints: buildAcceptanceHints(card.acceptance, testFiles, cwd, wtRoot, probe7CrossRoots),
2223
2225
  })
2224
2226
  }
2227
+ // ── trace 落盘(2026-09-24-fr-test-bindings task-03,fr-test-binding 写侧):矩阵归属
2228
+ // 行→candidate(requirement_ids join→局部 FR 锚;无锚→orphan 指纹 row_id,D-005)。
2229
+ // 预填≠确认(discovery=machine/confirmed_by=null);fail-open:落盘异常不炸探针。──
2230
+ try {
2231
+ if (probe7.applicable && changeName) {
2232
+ const traceRows = []
2233
+ for (const t of probe7.tasks) {
2234
+ if (!Array.isArray(t.testFiles) || t.testFiles.length === 0) continue
2235
+ const card = cards.find(c => c.task === t.task)
2236
+ const reqIds = ((String(card && card.raw || '').match(/^requirement_ids:\s*\[([^\]]*)\]/m) || [])[1] || '')
2237
+ .split(',').map(x => x.trim().replace(/['"]/g, '')).filter(Boolean)
2238
+ ;(t.acceptance || []).forEach((item, i) => {
2239
+ traceRows.push({
2240
+ anchor: reqIds[0] || null,
2241
+ row_id: changeName + ':' + t.task + ':' + orphanAccRef(i, String(item)),
2242
+ tests: t.testFiles,
2243
+ reason: 'spec',
2244
+ state: 'candidate',
2245
+ discovery: 'machine',
2246
+ confirmed_by: null,
2247
+ source_change: changeName,
2248
+ })
2249
+ })
2250
+ }
2251
+ if (traceRows.length > 0) {
2252
+ const w = writeChangeTrace(join(specBase, 'changes', changeName), changeName, traceRows)
2253
+ if (w.changed) console.log('🔗 探针 7 绑定候选落盘:' + traceRows.length + ' 行 → ' + w.path)
2254
+ }
2255
+ }
2256
+ } catch { /* trace 落盘 fail-open(探针行为不变,下次构建重试) */ }
2225
2257
  }
2226
2258
  }
2227
2259
 
@@ -2265,6 +2297,16 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
2265
2297
  probe11.warnings = [`探针 11 执行失败(fail-soft 跳过):${e && e.message ? e.message : e}`]
2266
2298
  }
2267
2299
 
2300
+ // ── 探针 12:UI 视觉证据(分级门;2026-09-27-ui-visual-guidance——过程引导的收口对账面:
2301
+ // 只验证据在场不产新证据;缺证据默认 ⚠️,ui_visual_gate=error 升阻断;视觉降级无用户
2302
+ // 裁决留痕恒 error(堵 D-004 型静默降级)。fail-soft 同 8-11。──
2303
+ let probe12 = { applicable: false, uiTouched: false, level: 'ok', notes: [] }
2304
+ try {
2305
+ probe12 = runUiVisualProbe({ changeDir: join(specBase, 'changes', changeName), gate: readUiVisualGate(specBase) })
2306
+ } catch (e) {
2307
+ probe12.notes = [`探针 12 执行失败(fail-soft 跳过):${e && e.message ? e.message : e}`]
2308
+ }
2309
+
2268
2310
  // ── 接口面 + 消费端归类(task-04 / FR-05 / D-005~D-007):design.md 接口段 tolerant
2269
2311
  // 解析 + 清单消费端归类——骨架「## 接口验证覆盖矩阵」段预填与 facts 落盘
2270
2312
  // (backfillFactsFromMdAndTests)共用同一解析器(单一产物源,不各读各的)。fail-soft:
@@ -2278,7 +2320,7 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
2278
2320
  }
2279
2321
  } catch { /* design 读/解析异常 → 空面(fail-soft) */ }
2280
2322
 
2281
- return { probe1, probe3, probe5, probe6, probe7, probe8, probe9, probe10, apiFace, consumerHints }
2323
+ return { probe1, probe3, probe5, probe6, probe7, probe8, probe9, probe10, probe12, apiFace, consumerHints }
2282
2324
  }
2283
2325
 
2284
2326
  /**
@@ -2390,6 +2432,8 @@ export function renderVerifyProbesReport(result) {
2390
2432
  L.push(...(renderProbe10Lines(result.probe10 || { applicable: false, checkedFiles: 0, unclearedFiles: [], notes: [] })))
2391
2433
  // 探针 11 紧随 10;旧 result 无 probe11 键 → 不适用兜底(8/9/10 同款零回归口径)。
2392
2434
  L.push(...(renderProbe11Lines(result.probe11 || { applicable: false, entryCount: 0, findings: [], warnings: [] })))
2435
+ // 探针 12 紧随 11(UI 视觉证据分级门);旧 result 无 probe12 键 → 不适用兜底零回归。
2436
+ L.push(...(renderUiVisualProbeLines(result.probe12 || { applicable: false, notes: [] })))
2393
2437
  return L.join('\n')
2394
2438
  }
2395
2439
 
@@ -2587,10 +2631,15 @@ function renderApiCoverageMatrixLines(apiFace) {
2587
2631
  const declared = face && typeof face.declared === 'number' ? face.declared : null
2588
2632
  const L = [`${API_MATRIX_HEADING} [层:人工判断——CLI 预填复核]`]
2589
2633
  L.push('<!-- 口径注记(与探针 7 互指,R-07):探针 7 = 验收项 × 测试承接面(每条 acceptance 由哪些测试承接);本矩阵 = 接口端点 × 验证用例面(design 接口段每个端点由哪些验证用例/冒烟步骤覆盖)——两者并排互补,双矩阵并行存在。端点集来自 design.md 接口段 tolerant 解析(parseDesignApiTable:段头宽收 + 方法/路径双条件),预填≠结论,agent 逐行复核。判定枚举(五选一):covered / covered-service / partial / uncovered / non-testable——covered-service 适用:端点行为由 service 层等非端点层测试锁定;证据须含测试文件锚点三形态之一(`.test.` / file:line / 反引号包裹的路径或测试名)。 -->')
2590
- L.push('<!-- 预填说明:端点行由 CLI 机械预填,判定/用例依据 ID/结果/证据由 agent 逐格填写——用例依据 ID 锚点五形态:design接口表#METHOD /path、权限矩阵[角色×动作]、契约表@行标识、DDL@列名、载荷@构造点路径(须真实命中对应表/段,防空指)。 -->')
2634
+ L.push('<!-- 预填说明:端点行由 CLI 机械预填,判定/用例依据 ID/结果/证据由 agent 逐格填写——用例依据 ID 锚点五形态(可复制样例):design接口表#POST /api/xx(# 后必须 METHOD /path,仅表名/行号/散文描述不计命中)、权限矩阵[admin×读]、契约表@任务卡字段清单、DDL@users.id、载荷@e2e_body.json(须真实命中对应表/段,防空指)。 -->')
2591
2635
  L.push('<!-- 文法注释:子行 = 端点行下一行、两空格缩进、以「↳ <消费端>:」前缀书写(消费端细分承接面,不计矩阵行账);探索行 = 判定 uncovered 且证据列含 [探索] 标记(探索性验证不算覆盖)。 -->')
2592
2636
  if (endpoints.length === 0 && declared === null) {
2593
- L.push('- 无接口面(design 接口段解析零端点且无「本变更接口面:N 端点」声明行)——本变更若实际触碰接口,先补 design 接口段表格或声明行,再重跑 `verify-probes --change <变更名> --init --force` 重生成本段(⚠️ 全骨架重生成,手填结论会重置——先备份;quick-B 起 --force 通道存在);判级 critical 的零面拦截归 validator')
2637
+ // 分诊(2026-09-23 执行会话实证:散文式接口定义(### 标题+prose)解析零端点,提示被埋没——
2638
+ // sectionHint 非空 = 接口段标题在场而行解析零,定向报「表格形态才进矩阵」,左移修复时机)
2639
+ const sectionHeads = face && Array.isArray(face.sectionHint) ? face.sectionHint : []
2640
+ L.push(sectionHeads.length > 0
2641
+ ? `- 无接口面(检测到接口段标题「${sectionHeads[0]}」但表格解析零端点)——矩阵只解析表格形态(每端点一行 METHOD | path),散文式接口定义不进矩阵。修复:接口定义改为表格(每端点一行 METHOD /path)或加声明行「本变更接口面:N 端点」,再重跑 \`verify-probes --change <变更名> --init --force\` 重生成本段(⚠️ 全骨架重生成,手填结论会重置——先备份);判级 critical 的零面拦截归 validator`
2642
+ : `- 无接口面(design 接口段解析零端点且无「本变更接口面:N 端点」声明行)——本变更若实际触碰接口,先补 design 接口段表格或声明行,再重跑 \`verify-probes --change <变更名> --init --force\` 重生成本段(⚠️ 全骨架重生成,手填结论会重置——先备份);判级 critical 的零面拦截归 validator`)
2594
2643
  return L
2595
2644
  }
2596
2645
  if (endpoints.length > 0 && declared !== null && declared !== endpoints.length) {
@@ -2747,6 +2796,13 @@ export function writeVerifyFacts(changeDir, result, changeName, opts = {}) {
2747
2796
  } catch { /* 首次落盘/v1/损坏 → 全新快照(v1 无固化段,直接升 v2) */ }
2748
2797
  writeFileSync(factsPath, JSON.stringify(facts, null, 2) + '\n')
2749
2798
  console.log(`📝 已刷新 verify-facts.json 机器底稿: ${factsPath}(v2 分段合并,固化段保留;CLI 全权写,勿手改)${opts.platformNote || ''}`)
2799
+ // 左移警告(2026-09-23 执行会话实证:散文式接口定义到 verify 期才被零面拦下,表格形态要求
2800
+ // 埋在骨架注记里没人看——--init 刷完 facts 就在控制台点名,修复时机从 verify 收口提前到此刻)
2801
+ const face = result && result.apiFace
2802
+ if (face && Array.isArray(face.sectionHint) && face.sectionHint.length > 0
2803
+ && (!face.endpoints || face.endpoints.length === 0) && face.declared == null) {
2804
+ console.warn(`⚠️ design 检测到接口段标题「${face.sectionHint[0]}」但表格解析零端点——接口验证覆盖矩阵只解析表格形态(每端点一行 METHOD | path),散文式接口定义不进矩阵。修复:design.md 接口定义改表格或加声明行「本变更接口面:N 端点」后重跑 --init。`)
2805
+ }
2750
2806
  return { facts, path: factsPath }
2751
2807
  }
2752
2808