sillyspec 3.29.4 → 3.29.5
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/assets/command-cards/run-archive.md +26 -0
- package/assets/command-cards/run-brainstorm.md +33 -0
- package/assets/command-cards/run-execute.md +29 -0
- package/assets/command-cards/run-plan.md +27 -0
- package/assets/command-cards/run-quick.md +34 -0
- package/assets/command-cards/run-verify.md +29 -0
- package/assets/command-cards/status.md +27 -0
- package/package.json +1 -1
- package/round4/account.mjs +85 -0
- package/round4/brief-autocompact.md +34 -0
- package/round4/brief-session-replay.md +50 -0
- package/round4/deep-read-synthesis.md +38 -0
- package/round4/extract-full.mjs +38 -0
- package/round4/extract-timeline.mjs +43 -0
- package/round4/find-sessions.mjs +13 -0
- package/round4/full-r4-l.md +4707 -0
- package/round4/full-r4-o-l.md +4300 -0
- package/round4/full-r4-os.md +1681 -0
- package/round4/full-r4-sf.md +4255 -0
- package/round4/full-r4-sq.md +1734 -0
- package/round4/gate-audit-relay-receipt.md +30 -0
- package/round4/gate-value-audit.md +52 -0
- package/round4/prereg.md +67 -0
- package/round4/prompt-R4-L.md +63 -0
- package/round4/prompt-R4-O-L.md +59 -0
- package/round4/prompt-R4-O-S.md +56 -0
- package/round4/prompt-R4-S-F.md +60 -0
- package/round4/prompt-R4-S-Q.md +66 -0
- package/round4/r4-os-timeline.txt +297 -0
- package/round4/r4-sf-timeline.txt +738 -0
- package/round4/r4-sq-timeline.txt +322 -0
- package/round4/r4l-timeline.txt +793 -0
- package/round4/r4ol-timeline.txt +729 -0
- package/round4/r4sf-timeline.txt +852 -0
- package/round4/result-S.md +171 -0
- package/round4/result-final.md +46 -0
- package/round4/result-quality.md +63 -0
- package/src/command-cards.js +73 -0
- package/src/contract-matrix.js +26 -5
- package/src/diagnostic-codes.js +2 -1
- package/src/index.js +33 -6
- package/src/init.js +25 -8
- package/src/machine-interface.js +88 -3
- package/src/module-impact.js +51 -22
- package/src/run/command.js +4 -0
- package/src/run/complete-handlers.js +36 -1
- package/src/run/complete.js +6 -3
- package/src/run/gate-snapshot.js +10 -4
- package/src/run/gates.js +114 -37
- package/src/run/quick-audit.js +28 -2
- package/src/run/shared.js +3 -1
- package/src/stages/execute.js +2 -2
- package/src/stages/plan-postcheck.js +33 -19
- package/src/taskcard-frontmatter.js +57 -0
- package/src/verify-postcheck.js +59 -1
- package/src/verify-probes.js +45 -23
package/src/verify-probes.js
CHANGED
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync } from 'fs'
|
|
28
28
|
import { join, dirname, basename, resolve, isAbsolute, relative } from 'path'
|
|
29
|
-
import jsYaml from 'js-yaml'
|
|
30
29
|
import { gitQuiet, unquoteGitPath } from './git-helper.js'
|
|
31
30
|
import { hasUnconfirmedPrefill } from './prefill.js'
|
|
32
31
|
import {
|
|
@@ -36,6 +35,7 @@ import { parseFileChangeListDetailed } from './change-list.js'
|
|
|
36
35
|
import { parseDecisions } from './decision-distill.js'
|
|
37
36
|
import { parseAllowedPaths, parseRepo, parseRepoRegistry } from './stages/plan-postcheck.js'
|
|
38
37
|
import { verifyApiParity, _readWorktreeMeta } from './contract-matrix.js'
|
|
38
|
+
import { parseTaskFrontmatter } from './taskcard-frontmatter.js'
|
|
39
39
|
import { RECEIPT_SOURCE_CROSS_LAYER_RE as RECEIPT_CROSS_LAYER_RE, RECEIPT_SOURCE_UNIT_RE as RECEIPT_UNIT_RE, CLI_SMOKE_SOURCE_MARK as SMOKE_RECEIPT_SOURCE_MARK } from './change-risk-profile.js'
|
|
40
40
|
import { splitOwnVsForeignDiffFiles } from './foreign-declared.js'
|
|
41
41
|
import { resolveSpecDir, resolveRuntimeRoot, detectWorktreeSpecDrift } from './run/shared.js'
|
|
@@ -1073,7 +1073,7 @@ function designHasSubmitEndpoint(text) {
|
|
|
1073
1073
|
// sectionHint(命中的接口段头列表,审计注记)。
|
|
1074
1074
|
// 落盘面(数据通道=落盘即消费,stage-contract 零 import 纪律):backfillFactsFromMdAndTests
|
|
1075
1075
|
// 主路径写 facts.apiFace / facts.consumerHints,task-05 validator 经 facts 消费不经函数调用。
|
|
1076
|
-
const API_FACE_SECTION_RE =
|
|
1076
|
+
const API_FACE_SECTION_RE = /接口|端点|\bapi\b|\brest\b/i // quick-B 词边界:OpenAPI 标题(api 前邻字母)不再误收进 sectionHint
|
|
1077
1077
|
const API_FACE_METHOD_RE = /(?:^|[^A-Za-z])(GET|POST|PUT|DELETE|PATCH)(?![A-Za-z])/
|
|
1078
1078
|
// 路径样式 token:/ 起始、前邻非字母数字(日期 2026/09/17 的 /09 前是数字段不认),
|
|
1079
1079
|
// 首字符字母数字/_/-/{,后续段字符含 {}/: 模板形态(/orders/{id}、/orders/:id 全串命中)
|
|
@@ -1713,26 +1713,34 @@ const PROBE7_NONTESTABLE_RE = /文档|部署|doc|deploy|manual|config/i
|
|
|
1713
1713
|
|
|
1714
1714
|
/**
|
|
1715
1715
|
* 解析 task-NN.md frontmatter 的 acceptance(string/array 双形态归一为数组)。
|
|
1716
|
-
*
|
|
1717
|
-
*
|
|
1716
|
+
* 解析归一 taskcard-frontmatter.js 单一源(2026-09-20-taskcard-yaml-hardgate:此前坏 YAML
|
|
1717
|
+
* catch 返回 [] 冒充「无 acceptance」,探针 7 渲染假防御文案)——status 三态让调用方区分
|
|
1718
|
+
* 「真无 acceptance」与「frontmatter 非法 YAML」。口径锚 src/stages/plan-postcheck.js
|
|
1719
|
+
* acceptance best-effort 段(string → 原文单条、array → 逐条)。
|
|
1718
1720
|
* @param {string} content task 卡全文
|
|
1719
|
-
* @returns {
|
|
1720
|
-
*
|
|
1721
|
+
* @returns {{ status: 'no-frontmatter'|'invalid-yaml'|'ok', acceptance: string[],
|
|
1722
|
+
* error: {message: string, line: number, column: number}|null }}
|
|
1723
|
+
* no-frontmatter = 无 frontmatter(调用方跳过该卡);invalid-yaml = frontmatter 非法 YAML
|
|
1724
|
+
* (acceptance 不可读,error 带文件 1 基行:列);ok = 合法解析,acceptance 归一数组
|
|
1725
|
+
* (frontmatter 在场但无 acceptance → [],此时防御行为真——plan-postcheck 已拦缺失)
|
|
1721
1726
|
*/
|
|
1722
1727
|
export function parseTaskAcceptance(content) {
|
|
1723
|
-
const
|
|
1724
|
-
if (!
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1728
|
+
const parsed = parseTaskFrontmatter(content)
|
|
1729
|
+
if (!parsed.hasFrontmatter) return { status: 'no-frontmatter', acceptance: [], error: null }
|
|
1730
|
+
if (!parsed.ok) return { status: 'invalid-yaml', acceptance: [], error: parsed.error }
|
|
1731
|
+
const fmObj = parsed.fm || {}
|
|
1732
|
+
if (typeof fmObj.acceptance === 'string') {
|
|
1733
|
+
const t = fmObj.acceptance.trim()
|
|
1734
|
+
return { status: 'ok', acceptance: t ? [t] : [], error: null }
|
|
1735
|
+
}
|
|
1736
|
+
if (Array.isArray(fmObj.acceptance)) {
|
|
1737
|
+
return {
|
|
1738
|
+
status: 'ok',
|
|
1739
|
+
acceptance: fmObj.acceptance.filter(x => typeof x === 'string' && x.trim() !== '').map(x => x.trim()),
|
|
1740
|
+
error: null,
|
|
1733
1741
|
}
|
|
1734
|
-
}
|
|
1735
|
-
return []
|
|
1742
|
+
}
|
|
1743
|
+
return { status: 'ok', acceptance: [], error: null }
|
|
1736
1744
|
}
|
|
1737
1745
|
|
|
1738
1746
|
/**
|
|
@@ -1939,6 +1947,12 @@ function renderProbe7Lines(p7) {
|
|
|
1939
1947
|
for (const t of (p7.tasks || [])) {
|
|
1940
1948
|
L.push('')
|
|
1941
1949
|
L.push(`**${t.task}**`)
|
|
1950
|
+
if (t.fmError) {
|
|
1951
|
+
// 坏 YAML 如实陈述(2026-09-20-taskcard-yaml-hardgate):非「无 acceptance」防御——
|
|
1952
|
+
// plan 门禁 0b 硬校验应已拦截;已过 plan 门仍见此行 = 门禁失效信号(可反馈工具缺陷)
|
|
1953
|
+
L.push(`- ⚠️ frontmatter 非法 YAML(${t.task}.md:${t.fmError.line}:${t.fmError.column} ${mdEscapeCell(t.fmError.message, 160)})——acceptance 不可读,本行非「无 acceptance」防御;plan 门禁 frontmatter 硬校验应已拦截,若已过 plan 门仍见此行即门禁失效信号`)
|
|
1954
|
+
continue
|
|
1955
|
+
}
|
|
1942
1956
|
if (!Array.isArray(t.acceptance) || t.acceptance.length === 0) {
|
|
1943
1957
|
L.push('- (卡无 acceptance——防御,plan-postcheck 已拦)')
|
|
1944
1958
|
continue
|
|
@@ -2138,10 +2152,17 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
|
|
|
2138
2152
|
try {
|
|
2139
2153
|
for (const f of readdirSync(tasksDir).filter(n => /^task-\d+\.md$/.test(n)).sort()) {
|
|
2140
2154
|
const raw = readFileSync(join(tasksDir, f), 'utf8')
|
|
2141
|
-
|
|
2142
|
-
|
|
2155
|
+
// 三态分流(2026-09-20-taskcard-yaml-hardgate):no-frontmatter 跳卡(原 null 语义);
|
|
2156
|
+
// invalid-yaml 挂 fmError 进条目——渲染层区分「坏 YAML」与「真无 acceptance」防御行
|
|
2157
|
+
const parsed = parseTaskAcceptance(raw)
|
|
2158
|
+
if (parsed.status === 'no-frontmatter') continue // 无 frontmatter → 跳过(plan-postcheck 已拦)
|
|
2143
2159
|
const fmId = (raw.match(/^id:\s*(\S+)/m) || [])[1]
|
|
2144
|
-
cards.push({
|
|
2160
|
+
cards.push({
|
|
2161
|
+
task: fmId || f.replace(/\.md$/, ''),
|
|
2162
|
+
acceptance: parsed.acceptance,
|
|
2163
|
+
fmError: parsed.status === 'invalid-yaml' ? parsed.error : null,
|
|
2164
|
+
raw,
|
|
2165
|
+
})
|
|
2145
2166
|
}
|
|
2146
2167
|
} catch { /* tasks 目录不可读 → applicable 维持 false */ }
|
|
2147
2168
|
probe7.applicable = cards.length > 0
|
|
@@ -2196,6 +2217,7 @@ export function runVerifyProbes({ cwd, changeName, specDir = null }) {
|
|
|
2196
2217
|
probe7.tasks.push({
|
|
2197
2218
|
task: card.task,
|
|
2198
2219
|
acceptance: card.acceptance,
|
|
2220
|
+
fmError: card.fmError || null,
|
|
2199
2221
|
testFiles,
|
|
2200
2222
|
hints: buildAcceptanceHints(card.acceptance, testFiles, cwd, wtRoot, probe7CrossRoots),
|
|
2201
2223
|
})
|
|
@@ -2568,7 +2590,7 @@ function renderApiCoverageMatrixLines(apiFace) {
|
|
|
2568
2590
|
L.push('<!-- 预填说明:端点行由 CLI 机械预填,判定/用例依据 ID/结果/证据由 agent 逐格填写——用例依据 ID 锚点五形态:design接口表#METHOD /path、权限矩阵[角色×动作]、契约表@行标识、DDL@列名、载荷@构造点路径(须真实命中对应表/段,防空指)。 -->')
|
|
2569
2591
|
L.push('<!-- 文法注释:子行 = 端点行下一行、两空格缩进、以「↳ <消费端>:」前缀书写(消费端细分承接面,不计矩阵行账);探索行 = 判定 uncovered 且证据列含 [探索] 标记(探索性验证不算覆盖)。 -->')
|
|
2570
2592
|
if (endpoints.length === 0 && declared === null) {
|
|
2571
|
-
L.push('- 无接口面(design 接口段解析零端点且无「本变更接口面:N 端点」声明行)——本变更若实际触碰接口,先补 design 接口段表格或声明行,再重跑 `verify-probes --init`
|
|
2593
|
+
L.push('- 无接口面(design 接口段解析零端点且无「本变更接口面:N 端点」声明行)——本变更若实际触碰接口,先补 design 接口段表格或声明行,再重跑 `verify-probes --change <变更名> --init --force` 重生成本段(⚠️ 全骨架重生成,手填结论会重置——先备份;quick-B 起 --force 通道存在);判级 critical 的零面拦截归 validator')
|
|
2572
2594
|
return L
|
|
2573
2595
|
}
|
|
2574
2596
|
if (endpoints.length > 0 && declared !== null && declared !== endpoints.length) {
|
|
@@ -2582,7 +2604,7 @@ function renderApiCoverageMatrixLines(apiFace) {
|
|
|
2582
2604
|
}
|
|
2583
2605
|
} else {
|
|
2584
2606
|
L.push(`| 本变更接口面:${declared} 端点(agent 声明) | <待填:五选一> | <待填:用例 ID> | <待填> | <待填:锚点> |`)
|
|
2585
|
-
L.push('<!-- 解析零行降级(D-005):接口面以 agent 声明为准(对账分母=声明数);声明与实际不符时补 design 接口段表格后重跑 --init
|
|
2607
|
+
L.push('<!-- 解析零行降级(D-005):接口面以 agent 声明为准(对账分母=声明数);声明与实际不符时补 design 接口段表格后重跑 --init --force 重生成本段(quick-B:--force 才有刷新通道,手填内容会重置先备份) -->')
|
|
2586
2608
|
}
|
|
2587
2609
|
L.push('<!-- advisory 尾注(warning 计算归 validator,本段只留位):有消费端未填子行的端点将列于此(advisory——消费端归类=design 清单启发式,数据面 facts.consumerHints);写端点(POST/PUT/DELETE/PATCH)未在权限矩阵段声明的将列于此(advisory——补行或显式豁免「无权限约束」,数据面 facts.apiFace.writeEndpoints;表缺行会让派生框架继承你的洞) -->')
|
|
2588
2610
|
return L
|