sillyspec 3.28.13 → 3.29.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.
- package/package.json +1 -1
- package/src/blast-surface.js +168 -0
- package/src/ceremony-tier.js +359 -0
- package/src/change-risk-profile.js +72 -199
- package/src/config-schema.js +21 -0
- package/src/decisions-io.js +32 -0
- package/src/design-facts.js +1 -0
- package/src/doctor-diagnostics.js +119 -1
- package/src/index.js +92 -5
- package/src/knowledge-stats.js +25 -0
- package/src/modules.js +28 -0
- package/src/prefill.js +491 -0
- package/src/probe7-anchor-check.js +8 -6
- package/src/quick-gate-profile.js +8 -4
- package/src/quick-session-owner.js +63 -0
- package/src/review-dispatch.js +473 -1
- package/src/review-material-pack.js +265 -0
- package/src/review-tier.js +185 -41
- package/src/run/archive-distill.js +6 -0
- package/src/run/command.js +158 -87
- package/src/run/complete-handlers.js +82 -1
- package/src/run/complete.js +37 -1
- package/src/run/gates.js +301 -19
- package/src/run/prompt.js +423 -21
- package/src/run/shared.js +36 -0
- package/src/run/verify-quality-scan.js +14 -6
- package/src/scope-audit.js +8 -1
- package/src/span-risk-surface.js +127 -0
- package/src/stage-contract-spec.js +2 -2
- package/src/stage-contract.js +102 -81
- package/src/stage-review.js +26 -2
- package/src/stages/brainstorm.js +28 -15
- package/src/stages/execute.js +10 -2
- package/src/stages/plan.js +29 -12
- package/src/stages/verify.js +7 -7
- package/src/taskcard.js +3 -0
- package/src/verify-postcheck.js +375 -20
- package/src/verify-probes.js +117 -10
- package/src/worktree.js +1 -1
- package/templates/prompts/taskcard-rules.md +1 -0
- package/templates/prompts/verify-probes.md +1 -1
package/src/verify-probes.js
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* 探针7 验收×测试覆盖矩阵:task 卡 acceptance 自解析(jsYaml,string/array 双形态)+ 双源结构
|
|
13
13
|
* 归属(allowed_paths 测试模式 ∪ execute-runs review.json changedFiles test/ 前缀)+
|
|
14
14
|
* 关键词命中提示(命中≠判定,不参与门禁;2026-09-14-acceptance-test-matrix)
|
|
15
|
+
* 探针10 预填注清零(error 门):design.md + tasks/task-*.md 白名单槽宿主文件集逐个
|
|
16
|
+
* hasUnconfirmedPrefill(注在场=未确认)——--init 预填进探针段 + gates.js verify 收尾
|
|
17
|
+
* 复跑同一实现阻断(门禁梯度 error 档;2026-09-18-artifact-prefill task-03)
|
|
15
18
|
* 探针2(关键词提取半语义)/探针3.4 集成盲区/3.5 断言抽查/探针4(决策追踪语义)留 agent。
|
|
16
19
|
*
|
|
17
20
|
* verify-result.md 骨架:七章节固定结构 + 探针结果机械预填 + 其余章节 <!--TODO--> 占位。 probe1-noqa
|
|
@@ -22,9 +25,10 @@
|
|
|
22
25
|
* 供事后独立复跑审计;重复 --init 覆盖为最近一次 init 快照)。
|
|
23
26
|
*/
|
|
24
27
|
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'fs'
|
|
25
|
-
import { join, dirname, basename, resolve, isAbsolute } from 'path'
|
|
28
|
+
import { join, dirname, basename, resolve, isAbsolute, relative } from 'path'
|
|
26
29
|
import jsYaml from 'js-yaml'
|
|
27
30
|
import { gitQuiet, unquoteGitPath } from './git-helper.js'
|
|
31
|
+
import { hasUnconfirmedPrefill } from './prefill.js'
|
|
28
32
|
import {
|
|
29
33
|
FACTS_SCHEMA_VERSION, EVIDENCE_SLOT_HEADING, RECEIPT_SLOT_HEADING, parseEvidenceSlots,
|
|
30
34
|
} from './verify-facts-schema.js'
|
|
@@ -1642,6 +1646,58 @@ export function runProbe9GuardConsistency({ specBase, cwd, wtRoot = null, change
|
|
|
1642
1646
|
}
|
|
1643
1647
|
|
|
1644
1648
|
|
|
1649
|
+
// ── 探针 10(预填注清零,2026-09-18-artifact-prefill task-03 / FR-03 / D-003@v1 门禁梯度·error 档)──
|
|
1650
|
+
// 背景:三槽预填(src/prefill.js,task-01)的确认动作是「删注」——注在场 = 白名单槽未确认
|
|
1651
|
+
// (预填≠结论)。brainstorm/plan --done 是 advisory(忘删=提示,gates.js 轻档),本探针是梯度
|
|
1652
|
+
// 收口的 error 档:--init 预填进 verify-result.md 探针段(agent 在 verify 阶段看到 ❌ 面),
|
|
1653
|
+
// gates.js verify 收尾复跑本函数同源阻断(verify 完成是 archive 前置——「归档前注清零」的落点)。
|
|
1654
|
+
// 检测复用 task-01 的 hasUnconfirmedPrefill(PREFILL_NOTE 字面包含即未确认);已知误报面:
|
|
1655
|
+
// 散文引用注字面量(如设计文档描述注协议本身)会命中——不追求语义区分,❌ 面向 agent 核对
|
|
1656
|
+
// (真未确认 → 删注;纯散文 → 改写措辞),gate 侧文案同口径。
|
|
1657
|
+
const PROBE10_HEADING = '#### 探针 10:预填注清零(error 门)'
|
|
1658
|
+
|
|
1659
|
+
/**
|
|
1660
|
+
* 探针 10 主体:changeDir 的 design.md + tasks/task-*.md(预填白名单槽宿主文件集——与
|
|
1661
|
+
* gates.js advisory 门 / verify 收尾 error 门同一检测面)逐文件 hasUnconfirmedPrefill。
|
|
1662
|
+
* - applicable:至少一个在检文件存在(变更目录缺失 / 全缺席 → false + 注记,纯骨架零红门禁);
|
|
1663
|
+
* - unclearedFiles:含未删预填注的文件(changeDir 相对、正斜杠,design.md 在前、task 卡按名序);
|
|
1664
|
+
* - 只读不写、无 git 依赖(与 probe8/9 的 design 清单解析面独立——design.md 缺失仍可查
|
|
1665
|
+
* task 卡,反之亦然)。
|
|
1666
|
+
* @param {{ specBase: string, changeName: string }} args
|
|
1667
|
+
* @returns {{applicable: boolean, checkedFiles: number, unclearedFiles: string[], notes: string[]}}
|
|
1668
|
+
*/
|
|
1669
|
+
export function runProbe10PrefillNoteClearance({ specBase, changeName }) {
|
|
1670
|
+
const out = { applicable: false, checkedFiles: 0, unclearedFiles: [], notes: [] }
|
|
1671
|
+
if (!specBase || !changeName) {
|
|
1672
|
+
out.notes.push('入参缺失(specBase/changeName)——检测面空')
|
|
1673
|
+
return out
|
|
1674
|
+
}
|
|
1675
|
+
const changeDir = join(specBase, 'changes', changeName)
|
|
1676
|
+
if (!existsSync(changeDir)) {
|
|
1677
|
+
out.notes.push(`变更目录不存在(${changeDir})`)
|
|
1678
|
+
return out
|
|
1679
|
+
}
|
|
1680
|
+
const candidates = [join(changeDir, 'design.md')]
|
|
1681
|
+
try {
|
|
1682
|
+
const tasksDir = join(changeDir, 'tasks')
|
|
1683
|
+
if (existsSync(tasksDir)) {
|
|
1684
|
+
candidates.push(...readdirSync(tasksDir).filter(n => /^task-.+\.md$/.test(n)).sort().map(n => join(tasksDir, n)))
|
|
1685
|
+
}
|
|
1686
|
+
} catch { /* tasks 目录不可读 → 只检 design.md */ }
|
|
1687
|
+
for (const p of candidates) {
|
|
1688
|
+
if (!existsSync(p)) continue
|
|
1689
|
+
out.checkedFiles++
|
|
1690
|
+
if (hasUnconfirmedPrefill(p)) out.unclearedFiles.push(relative(changeDir, p).split('\\').join('/'))
|
|
1691
|
+
}
|
|
1692
|
+
if (out.checkedFiles === 0) {
|
|
1693
|
+
out.notes.push('无在检文件(design.md 与 tasks/task-*.md 均缺席——纯骨架/中间态)')
|
|
1694
|
+
return out
|
|
1695
|
+
}
|
|
1696
|
+
out.applicable = true
|
|
1697
|
+
return out
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
|
|
1645
1701
|
const PROBE7_HEADING = '#### 探针 7:验收×测试覆盖矩阵'
|
|
1646
1702
|
// execute run id 格式(与 task-review.js isValidExecuteRunId 同口径锚定,防提示词注入/路径穿越)
|
|
1647
1703
|
const PROBE7_EXEC_RUN_ID_RE = /^exec-\d{4}-\d{2}-\d{2}-\d{6}(?:-[a-z0-9]{1,8}){0,2}$/
|
|
@@ -1870,8 +1926,8 @@ function renderProbe7Lines(p7) {
|
|
|
1870
1926
|
L.push('- 不适用(无 TaskCard)')
|
|
1871
1927
|
return L
|
|
1872
1928
|
}
|
|
1873
|
-
L.push('<!-- 口径注记:探针 3 = 模块目录递归存在性面(allowed_paths 目录附近有没有测试);探针 7 = allowed_paths ∪ review changedFiles ∪ 直接下游卡测试 结构归属承接面(每条 acceptance 由哪些测试承接;下游消费卡的测试可承接上游 provider 的 acceptance——probe7-provider-tests-in-consumer-card);两者并排冲突以 7
|
|
1874
|
-
L.push('<!-- 预填说明(ql-20260915-004):判定列为 CLI 机械预填,agent 逐格复核改写——规则:无归属→uncovered(文档/部署/doc/deploy/manual/config 类词→non-testable);有归属且命中≥1→covered;有归属零命中→partial。covered/partial 证据须含测试锚点三形态之一(file:line / `.test.` 测试文件名 / 反引号包裹的路径或测试名),行号可省;uncovered/non-testable 证据自由形态。预填≠结论:与事实不符的格子必须改写(枚举须保持 covered/partial/uncovered/non-testable 纯值,备注写在证据列)。 -->')
|
|
1929
|
+
L.push('<!-- 口径注记:探针 3 = 模块目录递归存在性面(allowed_paths 目录附近有没有测试);探针 7 = allowed_paths ∪ review changedFiles ∪ 直接下游卡测试 结构归属承接面(每条 acceptance 由哪些测试承接;下游消费卡的测试可承接上游 provider 的 acceptance——probe7-provider-tests-in-consumer-card);两者并排冲突以 7 为准。判定枚举(五选一):covered / covered-service / partial / uncovered / non-testable(covered-service 适用:端点行为由 service 层等非端点层测试锁定,证据附测试锚点;non-testable 是文档/部署类显式逃生门)。关键词命中只是提示,命中≠判定。 -->')
|
|
1930
|
+
L.push('<!-- 预填说明(ql-20260915-004):判定列为 CLI 机械预填,agent 逐格复核改写——规则:无归属→uncovered(文档/部署/doc/deploy/manual/config 类词→non-testable);有归属且命中≥1→covered;有归属零命中→partial。covered/covered-service/partial 证据须含测试锚点三形态之一(file:line / `.test.` 测试文件名 / 反引号包裹的路径或测试名),行号可省;uncovered/non-testable 证据自由形态。预填≠结论:与事实不符的格子必须改写(枚举须保持 covered/covered-service/partial/uncovered/non-testable 纯值,备注写在证据列)。 -->')
|
|
1875
1931
|
// 零自动化承接计数(坑 review-zero-coverage-unwalked,2026-09-16 EHS 二次复核实证:execute
|
|
1876
1932
|
// 期 review 走查面事实上跟着测试覆盖走——「新增-部门支线测试充分,编辑路径与相关方支线
|
|
1877
1933
|
// 零覆盖」恰是 5 个 P1 的藏身处。矩阵渲染时顺带计数零承接条目,verify 复核强制显式走查
|
|
@@ -2163,6 +2219,16 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
|
|
|
2163
2219
|
probe9.notes = [`探针 9 执行失败(fail-soft 跳过):${e && e.message ? e.message : e}`]
|
|
2164
2220
|
}
|
|
2165
2221
|
|
|
2222
|
+
// ── 探针 10:预填注清零(error 门;2026-09-18-artifact-prefill task-03——门禁梯度 error 档
|
|
2223
|
+
// 的检测单点:--init 预填本段 + gates.js verify 收尾 error 门 / brainstorm·plan advisory 复跑
|
|
2224
|
+
// 同一实现,不二算。fail-soft 同探针 8/9:异常降级 not-applicable 注记不炸整体。──
|
|
2225
|
+
let probe10 = { applicable: false, checkedFiles: 0, unclearedFiles: [], notes: [] }
|
|
2226
|
+
try {
|
|
2227
|
+
probe10 = runProbe10PrefillNoteClearance({ specBase, changeName })
|
|
2228
|
+
} catch (e) {
|
|
2229
|
+
probe10.notes = [`探针 10 执行失败(fail-soft 跳过):${e && e.message ? e.message : e}`]
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2166
2232
|
// ── 接口面 + 消费端归类(task-04 / FR-05 / D-005~D-007):design.md 接口段 tolerant
|
|
2167
2233
|
// 解析 + 清单消费端归类——骨架「## 接口验证覆盖矩阵」段预填与 facts 落盘
|
|
2168
2234
|
// (backfillFactsFromMdAndTests)共用同一解析器(单一产物源,不各读各的)。fail-soft:
|
|
@@ -2176,7 +2242,7 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
|
|
|
2176
2242
|
}
|
|
2177
2243
|
} catch { /* design 读/解析异常 → 空面(fail-soft) */ }
|
|
2178
2244
|
|
|
2179
|
-
return { probe1, probe3, probe5, probe6, probe7, probe8, probe9, apiFace, consumerHints }
|
|
2245
|
+
return { probe1, probe3, probe5, probe6, probe7, probe8, probe9, probe10, apiFace, consumerHints }
|
|
2180
2246
|
}
|
|
2181
2247
|
|
|
2182
2248
|
/**
|
|
@@ -2283,6 +2349,9 @@ export function renderVerifyProbesReport(result) {
|
|
|
2283
2349
|
// 探针 9 紧随探针 8;旧 result 无 probe9 键(存量调用方/合成 result)→ applicable=false
|
|
2284
2350
|
// 渲染「不适用」行 + notes,零回归(探针 7 兜底口径同款)。
|
|
2285
2351
|
L.push(...(renderProbe9Lines(result.probe9 || { applicable: false, javaFileCount: 0, groupCount: 0, inconsistentGroups: [], notes: [] })))
|
|
2352
|
+
// 探针 10 紧随探针 9;旧 result 无 probe10 键(存量调用方/合成 result)→ applicable=false
|
|
2353
|
+
// 渲染「不适用」行 + notes,零回归(探针 8/9 兜底口径同款)。
|
|
2354
|
+
L.push(...(renderProbe10Lines(result.probe10 || { applicable: false, checkedFiles: 0, unclearedFiles: [], notes: [] })))
|
|
2286
2355
|
return L.join('\n')
|
|
2287
2356
|
}
|
|
2288
2357
|
|
|
@@ -2369,6 +2438,31 @@ function renderProbe9Lines(p9) {
|
|
|
2369
2438
|
return L
|
|
2370
2439
|
}
|
|
2371
2440
|
|
|
2441
|
+
/**
|
|
2442
|
+
* 渲染探针 10 段(renderProbe9Lines 同构;error 门口径注记随段输出——❌ 面是 verify 完成
|
|
2443
|
+
* 前须清零的死信,不是 advisory 复核面)。汇总行「预填注未清 N 处」的 N 为后续一致性抽查
|
|
2444
|
+
* 锚点扩展留位(verify-postcheck 锚点面归后续任务,本卡只出 producer 侧——probe9 先例同款)。
|
|
2445
|
+
* @param {{applicable: boolean, checkedFiles?: number, unclearedFiles: string[], notes: string[]}} p10
|
|
2446
|
+
* @returns {string[]} 行数组(含段标题)
|
|
2447
|
+
*/
|
|
2448
|
+
function renderProbe10Lines(p10) {
|
|
2449
|
+
const L = [PROBE10_HEADING]
|
|
2450
|
+
if (!p10 || !p10.applicable) {
|
|
2451
|
+
L.push('- 不适用(design.md 与 tasks/task-*.md 均缺席——纯骨架/中间态,预填注无从在场)')
|
|
2452
|
+
for (const n of (p10 && p10.notes) || []) L.push(`- ℹ️ ${n}`)
|
|
2453
|
+
return L
|
|
2454
|
+
}
|
|
2455
|
+
L.push('<!-- 口径注记:预填注(来源注协议)在场 = 白名单槽未确认(预填≠结论);删注 = 确认动作。本探针是门禁梯度 error 档——verify --done 时 gate 复跑同源检测,注未清零阻断完成(归档前清零兜底)。已知误报面:散文引用注字面量会命中(如文档描述注协议本身)——核对后真未确认则删注,纯散文则改写措辞,不得删探针段。 -->')
|
|
2456
|
+
if ((p10.unclearedFiles || []).length > 0) {
|
|
2457
|
+
L.push(`- ❌ 预填注未清 ${p10.unclearedFiles.length} 处(error 门——verify 完成前须逐槽核对后删注):`)
|
|
2458
|
+
for (const f of p10.unclearedFiles) L.push(`- ❌ \`${mdEscapeCell(f, 120)}\` 仍含未删预填注`)
|
|
2459
|
+
} else {
|
|
2460
|
+
L.push(`- ✅ 预填注清零(${p10.checkedFiles ?? 0} 个在检文件无未确认预填)`)
|
|
2461
|
+
}
|
|
2462
|
+
for (const n of p10.notes || []) L.push(`- ℹ️ ${n}`)
|
|
2463
|
+
return L
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2372
2466
|
// ── 接口验证覆盖矩阵段渲染(task-04 / FR-05 / D-005~D-007)──
|
|
2373
2467
|
// 骨架新写路径(generateVerifyResultSkeleton)与缺段补齐(ensureApiCoverageMatrixSection)
|
|
2374
2468
|
// 共用单一实现——renderProbe7Lines 先例。不动 probe7 既有矩阵(独立 ## 章节并行存在,口径
|
|
@@ -2380,7 +2474,7 @@ const API_MATRIX_WRITE_METHODS = new Set(['POST', 'PUT', 'DELETE', 'PATCH'])
|
|
|
2380
2474
|
|
|
2381
2475
|
/**
|
|
2382
2476
|
* 渲染「## 接口验证覆盖矩阵」段(task-04)。
|
|
2383
|
-
* 三态:解析有端点 → 逐端点预填行(判定列
|
|
2477
|
+
* 三态:解析有端点 → 逐端点预填行(判定列 `<待填:五选一>` 占位,同 probe7 预填口径供 agent
|
|
2384
2478
|
* 复核);解析零行有声明 → 声明占位行「本变更接口面:<N> 端点(agent 声明)」(D-005 零解析
|
|
2385
2479
|
* 降级,对账分母=声明数);零解析零声明 → 「无接口面」注记行(非判级 critical 变更零行为
|
|
2386
2480
|
* 注记即可——判级 critical 的 error 拦截归 task-05 validator)。段尾 advisory 占位注记
|
|
@@ -2393,7 +2487,7 @@ function renderApiCoverageMatrixLines(apiFace) {
|
|
|
2393
2487
|
const endpoints = face && Array.isArray(face.endpoints) ? face.endpoints : []
|
|
2394
2488
|
const declared = face && typeof face.declared === 'number' ? face.declared : null
|
|
2395
2489
|
const L = [`${API_MATRIX_HEADING} [层:人工判断——CLI 预填复核]`]
|
|
2396
|
-
L.push('<!-- 口径注记(与探针 7 互指,R-07):探针 7 = 验收项 × 测试承接面(每条 acceptance 由哪些测试承接);本矩阵 = 接口端点 × 验证用例面(design 接口段每个端点由哪些验证用例/冒烟步骤覆盖)——两者并排互补,双矩阵并行存在。端点集来自 design.md 接口段 tolerant 解析(parseDesignApiTable:段头宽收 + 方法/路径双条件),预填≠结论,agent
|
|
2490
|
+
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 / 反引号包裹的路径或测试名)。 -->')
|
|
2397
2491
|
L.push('<!-- 预填说明:端点行由 CLI 机械预填,判定/用例依据 ID/结果/证据由 agent 逐格填写——用例依据 ID 锚点五形态:design接口表#METHOD /path、权限矩阵[角色×动作]、契约表@行标识、DDL@列名、载荷@构造点路径(须真实命中对应表/段,防空指)。 -->')
|
|
2398
2492
|
L.push('<!-- 文法注释:子行 = 端点行下一行、两空格缩进、以「↳ <消费端>:」前缀书写(消费端细分承接面,不计矩阵行账);探索行 = 判定 uncovered 且证据列含 [探索] 标记(探索性验证不算覆盖)。 -->')
|
|
2399
2493
|
if (endpoints.length === 0 && declared === null) {
|
|
@@ -2407,10 +2501,10 @@ function renderApiCoverageMatrixLines(apiFace) {
|
|
|
2407
2501
|
L.push('|---|---|---|---|---|')
|
|
2408
2502
|
if (endpoints.length > 0) {
|
|
2409
2503
|
for (const ep of endpoints) {
|
|
2410
|
-
L.push(`| ${mdEscapeCell(`${ep.method} ${ep.path}`, 160)} |
|
|
2504
|
+
L.push(`| ${mdEscapeCell(`${ep.method} ${ep.path}`, 160)} | <待填:五选一> | <待填:用例 ID> | <待填> | <待填:锚点> |`)
|
|
2411
2505
|
}
|
|
2412
2506
|
} else {
|
|
2413
|
-
L.push(`| 本变更接口面:${declared} 端点(agent 声明) |
|
|
2507
|
+
L.push(`| 本变更接口面:${declared} 端点(agent 声明) | <待填:五选一> | <待填:用例 ID> | <待填> | <待填:锚点> |`)
|
|
2414
2508
|
L.push('<!-- 解析零行降级(D-005):接口面以 agent 声明为准(对账分母=声明数);声明与实际不符时补 design 接口段表格后重跑 --init 刷新本段 -->')
|
|
2415
2509
|
}
|
|
2416
2510
|
L.push('<!-- advisory 尾注(warning 计算归 validator,本段只留位):有消费端未填子行的端点将列于此(advisory——消费端归类=design 清单启发式,数据面 facts.consumerHints);写端点(POST/PUT/DELETE/PATCH)未在权限矩阵段声明的将列于此(advisory——补行或显式豁免「无权限约束」,数据面 facts.apiFace.writeEndpoints;表缺行会让派生框架继承你的洞) -->')
|
|
@@ -2437,6 +2531,7 @@ export function buildVerifyFacts(result, { changeName, now } = {}) {
|
|
|
2437
2531
|
const p6 = (result && result.probe6) || {}
|
|
2438
2532
|
const p8 = (result && result.probe8) || {}
|
|
2439
2533
|
const p9 = (result && result.probe9) || {}
|
|
2534
|
+
const p10 = (result && result.probe10) || {}
|
|
2440
2535
|
// v2(2026-09-08-ir-verify-facts):probes 机器段原样;conclusion/tests/requiredEvidence/
|
|
2441
2536
|
// runtimeEvidence/factsConsistency 五段是 slot-backfill/实测回填段(D-001@v2),--init 快照
|
|
2442
2537
|
// 不落键(writeVerifyFacts 分段合并时保留既有固化段),由 backfillFactsFromMdAndTests 填。
|
|
@@ -2496,6 +2591,13 @@ export function buildVerifyFacts(result, { changeName, now } = {}) {
|
|
|
2496
2591
|
inconsistentGroups: len(p9.inconsistentGroups),
|
|
2497
2592
|
}),
|
|
2498
2593
|
},
|
|
2594
|
+
probe10: {
|
|
2595
|
+
command,
|
|
2596
|
+
metrics: defined({
|
|
2597
|
+
checkedFiles: num(p10.checkedFiles),
|
|
2598
|
+
unclearedFiles: len(p10.unclearedFiles),
|
|
2599
|
+
}),
|
|
2600
|
+
},
|
|
2499
2601
|
},
|
|
2500
2602
|
}
|
|
2501
2603
|
}
|
|
@@ -3239,10 +3341,13 @@ export function buildDecisionChainMatrix(changeDir) {
|
|
|
3239
3341
|
const id = (raw.match(/^id:\s*(\S+)/m) || [])[1] || f.replace(/\.md$/, '')
|
|
3240
3342
|
const decLine = (raw.match(/^decision_ids:\s*\[([^\]]*)\]/m) || [])[1] || ''
|
|
3241
3343
|
const reqLine = (raw.match(/^requirement_ids:\s*\[([^\]]*)\]/m) || [])[1] || ''
|
|
3344
|
+
// token 剥首尾成对引号:流式数组的引号写法(['D-001@v1'])是合法 YAML 且 agent Edit 填值
|
|
3345
|
+
// 主流形态,只 trim 不剥会让引号卡与 decisions.md 裸 id 永不相等(矩阵静默全量 ⚠️)
|
|
3346
|
+
const stripQuotes = (s) => s.trim().replace(/^['"](.*)['"]$/, '$1').trim()
|
|
3242
3347
|
taskRefs.push({
|
|
3243
3348
|
task: id,
|
|
3244
|
-
decisions: new Set(decLine.split(',').map(
|
|
3245
|
-
reqs: new Set(reqLine.split(',').map(
|
|
3349
|
+
decisions: new Set(decLine.split(',').map(stripQuotes).filter(Boolean)),
|
|
3350
|
+
reqs: new Set(reqLine.split(',').map(stripQuotes).filter(Boolean)),
|
|
3246
3351
|
})
|
|
3247
3352
|
}
|
|
3248
3353
|
}
|
|
@@ -3308,6 +3413,8 @@ export function generateVerifyResultSkeleton(result) {
|
|
|
3308
3413
|
const L = [
|
|
3309
3414
|
'# 验证报告(骨架由 `sillyspec verify-probes --change <变更名> --init` 生成)',
|
|
3310
3415
|
'',
|
|
3416
|
+
'> 引用规范:矩阵证据/测试结果等处的源码位置写仓根相对全路径+行号(src/foo.js:123)——裸文件名在 docs-check 层1 靠 basename 全仓扫描找候选,找不到候选或关键词窗口不匹配即失效,到 pre-push 才拦(2026-09-19 实证 64 处返工)。',
|
|
3417
|
+
'',
|
|
3311
3418
|
'> 探针结果已机械预填;其余章节把 `<!--TODO-->` 替换为真实内容。**结论只认「结论枚举:」槽行**——', /* probe1-noqa */
|
|
3312
3419
|
'> 槽行留「<待填:三选一>」会被 gate 判不过(fail-closed),正文其他位置的 PASS/FAIL 字样不参与判定。',
|
|
3313
3420
|
'>',
|
package/src/worktree.js
CHANGED
|
@@ -1751,7 +1751,7 @@ export class WorktreeManager {
|
|
|
1751
1751
|
const escapes = detectEditableInstallEscape(wtPath);
|
|
1752
1752
|
if (escapes.length > 0) {
|
|
1753
1753
|
issues.push({ type: 'editable-install-escape', name, fixable: false,
|
|
1754
|
-
detail: `worktree venv 含 ${escapes.length} 个 editable install 指向 worktree 外(${escapes.slice(0, 5).map(e => `${e.pkg}→${e.target}`).join(', ')}${escapes.length > 5 ? ' 等' : ''})——gen:types/后端命令会静默加载 worktree
|
|
1754
|
+
detail: `worktree venv 含 ${escapes.length} 个 editable install 指向 worktree 外(${escapes.slice(0, 5).map(e => `${e.pkg}→${e.target}`).join(', ')}${escapes.length > 5 ? ' 等' : ''})——gen:types/后端命令会静默加载 worktree 外旧代码。轻量出口:跑生成链前设 PYTHONPATH=<worktree>/backend(PYTHONPATH 优先于 .pth);彻底修复:worktree 内重装(uv sync / uv pip install -e .)` });
|
|
1755
1755
|
}
|
|
1756
1756
|
} catch { /* 探测失败不阻断 doctor */ }
|
|
1757
1757
|
}
|
|
@@ -6,6 +6,7 @@ TaskCard 格式规则(必须严格遵守):
|
|
|
6
6
|
- implementation: 列表,每条一个具体步骤
|
|
7
7
|
- acceptance: 列表,每条可独立验证(不是表格)
|
|
8
8
|
- verify: 列表,实际可执行的命令
|
|
9
|
+
- 中间验证定向优先:node --test <本任务测试文件>;全量 npm test 留 task 收口与 verify --done
|
|
9
10
|
- constraints: 列表,明确边界(含 brownfield 兼容、异常处理)
|
|
10
11
|
- 不需要:修改文件章节、覆盖来源章节、接口定义章节、TDD 步骤章节、参考章节
|
|
11
12
|
- frontmatter 必须以三减号结尾闭合(开头和结尾各一行 ---)。缺结尾会让 postcheck 提取不到 frontmatter,误报「字段缺失 / allowed_paths 为空」
|
|
@@ -33,4 +33,4 @@ CLI 的 missing backend endpoint 是 advisory(不硬阻断归档)——但 c
|
|
|
33
33
|
以 git 事实为准(真实 > 声明);CLI 的三态(合规/高风险/未声明)是机械判定,是否构成 FAIL blocker 由你诚实判定,务必如实记录——静默删除代码是 verify 的最大盲区。
|
|
34
34
|
|
|
35
35
|
**探针 7 补充(CLI 已预填矩阵归属与提示,你填判定与证据)**
|
|
36
|
-
验收×测试覆盖矩阵:CLI 机械半边已预填——逐 task 解析 TaskCard acceptance(frontmatter)、双源结构归属测试文件(allowed_paths 测试模式 ∪ execute review changedFiles 中 test/
|
|
36
|
+
验收×测试覆盖矩阵:CLI 机械半边已预填——逐 task 解析 TaskCard acceptance(frontmatter)、双源结构归属测试文件(allowed_paths 测试模式 ∪ execute review changedFiles 中 test/ 路径)、关键词命中提示(命中≠判定,仅提示)。你逐行填判定槽五枚举(covered / covered-service / partial / uncovered / non-testable——covered-service 适用:端点行为由 service 层等非端点层测试锁定,证据附测试锚点;non-testable 是文档/部署类显式逃生门)与证据:covered/covered-service/partial 附测试锚点(`.test.` 文件或 file:line),non-testable 附一句理由;判定或证据未填 fail-closed,阻断 verify `--done`。与探针 3 口径差异:探针 3 查模块目录有没有测试文件(存在性面),探针 7 查每条 acceptance 由哪些测试承接(承接面);两者并排冲突以 7 为准。
|