dsh-rule-engine 0.6.3 → 0.6.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/README.md +458 -425
- package/lib/core/authorization.js +12 -4
- package/lib/core/guard-core.js +55 -18
- package/lib/core/intent.js +1 -1
- package/lib/core/llm-intent.js +13 -5
- package/lib/core/matcher.js +19 -16
- package/lib/core/measure-kinds.js +127 -0
- package/lib/core/patterns.js +51 -8
- package/lib/core/state.js +12 -2
- package/lib/core/text-detect.js +20 -2
- package/lib/core/tool-catalog.js +16 -3
- package/lib/core/understander.js +23 -34
- package/lib/index.js +127 -19
- package/lib/messages.js +5 -0
- package/lib/service.js +43 -0
- package/package.json +4 -10
- package/scripts/audit-mount-consistency.mjs +0 -198
- package/scripts/build.sh +0 -13
- package/scripts/check-real.mjs +0 -24
- package/scripts/check-tool-coverage.mjs +0 -65
- package/scripts/dualtrack-check.mjs +0 -335
- package/scripts/dualtrack-whitelist.json +0 -7
- package/scripts/health-audit.mjs +0 -66
- package/scripts/lib/pnpm-exempt.mjs +0 -56
- package/scripts/local-residue-scan.mjs +0 -46
- package/scripts/plugins.json +0 -10
- package/scripts/probe-home.mjs +0 -3
- package/scripts/probe-intent.mjs +0 -14
- package/scripts/publish-aptitude-check.mjs +0 -102
- package/scripts/readme-version-check.mjs +0 -41
- package/scripts/release-plugin.mjs +0 -401
- package/scripts/rules-health.mjs +0 -55
- package/scripts/verify-all.mjs +0 -219
- package/scripts/verify-guard-live.mjs +0 -30
- package/scripts/verify-v474.mjs +0 -14
- package/upgrade-impact.json +0 -55
package/scripts/verify-all.mjs
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
// verify-all.mjs - 交付前体检报告(2026-08-26,对齐官方 docs/testing.zh.md 分层验证;0.5.9 增第⑤层;0.5.11 增第⑥层)。
|
|
2
|
-
// 六层:① 语法(lib 全部 .js node --check)
|
|
3
|
-
// ② 单元(test/run-all.mjs——单元+机制层,不含 e2e)
|
|
4
|
-
// ③ 组合冒烟(test/loader-smoke.e2e.mjs——真实接线 + 外部世界断言)
|
|
5
|
-
// ④ 真实判例(外部世界:近 24h 台账中 judge-pass/judge-false 记录数;
|
|
6
|
-
// 0 条 = WARN 提示需实弹,≥1 条 = 有真实裁决证据——读文件,不是自我报告)
|
|
7
|
-
// ⑤ 工具箱覆盖(scripts/check-tool-coverage.mjs——官方 tool-catalog 全集 vs 分类表,
|
|
8
|
-
// 任何 unknown = 未知工具首调处置会拦用户 → 红色(run_code 事故同类,K-01/K-06 门禁))
|
|
9
|
-
// ⑥ 变更工具守卫链覆盖(test/guardchain-coverage.test.mjs——规则 24④ 机器执行,
|
|
10
|
-
// 跨工具一致性测试:每个写/删/移工具在问句回合+无授权场景跑真实 guardDecision,
|
|
11
|
-
// 断言被拦或属豁免面——静默逃逸 = 红;工具名非安全边界,裁决链才是(K-04))
|
|
12
|
-
// 任一 ❌ → exit 1;⚠️(WARN)不阻塞但必须明示。
|
|
13
|
-
// 注意:子进程输出捕获需完整权限运行(受限模式 EPERM)。
|
|
14
|
-
import { execFileSync } from "node:child_process";
|
|
15
|
-
import { readdirSync, statSync, readFileSync, existsSync } from "node:fs";
|
|
16
|
-
import { dirname, join } from "node:path";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
18
|
-
import { exemptPkg } from "./lib/pnpm-exempt.mjs";
|
|
19
|
-
|
|
20
|
-
const root = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
21
|
-
const lines = [];
|
|
22
|
-
|
|
23
|
-
function step(name, cmd, args) {
|
|
24
|
-
try {
|
|
25
|
-
const out = execFileSync(cmd, args, { cwd: root, encoding: "utf8", stdio: "pipe", maxBuffer: 64 * 1024 * 1024 });
|
|
26
|
-
lines.push(`✅ ${name}`);
|
|
27
|
-
return out;
|
|
28
|
-
} catch (e) {
|
|
29
|
-
lines.push(`❌ ${name}`);
|
|
30
|
-
lines.push(String(e.stdout || e.stderr || e.message).slice(-500));
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ── ① 语法 ──
|
|
36
|
-
const files = [];
|
|
37
|
-
(function walk(d) {
|
|
38
|
-
for (const f of readdirSync(d)) {
|
|
39
|
-
const p = join(d, f);
|
|
40
|
-
if (statSync(p).isDirectory()) walk(p);
|
|
41
|
-
else if (/\.js$/.test(f)) files.push(p);
|
|
42
|
-
}
|
|
43
|
-
})(join(root, "lib"));
|
|
44
|
-
let sOk = true;
|
|
45
|
-
for (const f of files) {
|
|
46
|
-
try {
|
|
47
|
-
execFileSync(process.execPath, ["--check", f], { cwd: root, stdio: "pipe", encoding: "utf8" });
|
|
48
|
-
} catch (e) {
|
|
49
|
-
sOk = false;
|
|
50
|
-
lines.push(`❌ 语法 ${f}`);
|
|
51
|
-
lines.push(String(e.stderr || e.message).slice(-300));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (sOk) lines.push(`✅ 语法(${files.length} 个 lib 文件)`);
|
|
55
|
-
|
|
56
|
-
// ── ② 单元 ──
|
|
57
|
-
step("单元(test/run-all.mjs)", process.execPath, [join(root, "test", "run-all.mjs")]);
|
|
58
|
-
|
|
59
|
-
// ── ③ 组合冒烟 ──
|
|
60
|
-
step("组合冒烟(loader-smoke,真实接线+外部世界断言)", process.execPath, [join(root, "test", "loader-smoke.e2e.mjs")]);
|
|
61
|
-
|
|
62
|
-
// ── ⑤ 工具箱覆盖(0.5.9 门禁;0.6.0 B2′:素材经 CHECK_TOOL_CATALOG/--catalog 提供,缺素材=FAIL 含获取方式——
|
|
63
|
-
// 本机运行请设 CHECK_TOOL_CATALOG=D:\...\docs\docs-site-text\...;发布物内不硬编码任何本机路径) ──
|
|
64
|
-
step("工具箱覆盖(官方 tool-catalog vs 分类表,缺失即红)", process.execPath, [join(root, "scripts", "check-tool-coverage.mjs")]);
|
|
65
|
-
|
|
66
|
-
// ── ⑥ 变更工具守卫链覆盖(0.5.11 规则 24④ 跨工具一致性门禁) ──
|
|
67
|
-
step("变更工具守卫链覆盖(写/删/移工具问句回合不静默逃逸)", process.execPath, [join(root, "test", "guardchain-coverage.test.mjs")]);
|
|
68
|
-
|
|
69
|
-
// ── ⑦ 关联一致性门禁(0.5.11,用户定稿:验收 = 改动关联产物全做一遍,机器强制) ──
|
|
70
|
-
// ① test/*.test.mjs 全部被 run-all.mjs 收录(新增测试漏收录 = 红——guardchain 曾漏收)
|
|
71
|
-
// ② README 徽章版本 = package.json 版本(版本成对)
|
|
72
|
-
// ③ 文档:README/手册提及的"引擎已做"核心行为在 lib 中有落点(关键词级抽样,防"只写文档没实现")
|
|
73
|
-
let assocFail = [];
|
|
74
|
-
{
|
|
75
|
-
try {
|
|
76
|
-
const runAllText = readFileSync(join(root, "test", "run-all.mjs"), "utf8");
|
|
77
|
-
const testFiles = readdirSync(join(root, "test")).filter((f) => f.endsWith(".test.mjs"));
|
|
78
|
-
for (const f of testFiles) {
|
|
79
|
-
if (!runAllText.includes(f)) assocFail.push(`测试未收录 run-all.mjs:${f}`);
|
|
80
|
-
}
|
|
81
|
-
} catch (e) { assocFail.push(`run-all 收录检查失败:${e.message}`); }
|
|
82
|
-
try {
|
|
83
|
-
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
84
|
-
const readme = readFileSync(join(root, "README.md"), "utf8");
|
|
85
|
-
// 版本成对支持 -pre/-rc 后缀(工作区未发布代号如 0.5.11-pre;badge URL 编码 --pre)
|
|
86
|
-
const badge = readme.match(/version-([0-9.]+)(--pre|-pre)?-blue/);
|
|
87
|
-
const badgeVer = badge ? badge[1] + (badge[2] ? "-pre" : "") : null;
|
|
88
|
-
if (!badgeVer || badgeVer !== pkg.version) assocFail.push(`版本成对失败:package.json=${pkg.version} vs README badge=${badgeVer || "?"}`);
|
|
89
|
-
} catch (e) { assocFail.push(`版本成对检查失败:${e.message}`); }
|
|
90
|
-
// ③ 关键词落点:引擎宣称的六大能力,lib 中各有引用(防"文档说了、代码没做")
|
|
91
|
-
try {
|
|
92
|
-
const libText = readdirSync(join(root, "lib/core")).join(",");
|
|
93
|
-
const mustHave = ["tool-catalog", "lexicon", "guard-core", "intent", "authorization"];
|
|
94
|
-
for (const m of mustHave) {
|
|
95
|
-
if (!libText.includes(m + ".js")) assocFail.push(`核心落点缺失:lib/core/${m}.js`);
|
|
96
|
-
}
|
|
97
|
-
} catch (e) { assocFail.push(`核心落点检查失败:${e.message}`); }
|
|
98
|
-
}
|
|
99
|
-
if (assocFail.length > 0) {
|
|
100
|
-
for (const a of assocFail) lines.push(`❌ 关联一致性:${a}`);
|
|
101
|
-
} else {
|
|
102
|
-
lines.push("✅ 关联一致性(测试全部收录 / 版本成对 / 核心能力有落点)");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// ── ④ 真实判例(外部世界) ──
|
|
106
|
-
let judgeReal = 0;
|
|
107
|
-
const auditPath = join(process.env.DSH_HOME || join(process.env.USERPROFILE || "", ".dsh"), "rule-engine.log.jsonl");
|
|
108
|
-
const since = Date.now() - 24 * 3600 * 1000;
|
|
109
|
-
try {
|
|
110
|
-
for (const line of readFileSync(auditPath, "utf8").split("\n")) {
|
|
111
|
-
if (!line.includes("judge-pass") && !line.includes("judge-false")) continue;
|
|
112
|
-
const m = line.match(/"ts":"([^"]+)"/);
|
|
113
|
-
if (m && new Date(m[1]).getTime() >= since) judgeReal++;
|
|
114
|
-
}
|
|
115
|
-
} catch {
|
|
116
|
-
// 无日志:提示即可
|
|
117
|
-
}
|
|
118
|
-
if (judgeReal > 0) {
|
|
119
|
-
lines.push(`✅ 真实判例(近 24h judge-pass/judge-false = ${judgeReal} 条——裁决器真实工作证据)`);
|
|
120
|
-
} else {
|
|
121
|
-
lines.push("⚠️ 真实判例:近 24h 无 judge-pass/judge-false 记录——裁决器需要一次实弹(非阻塞 WARN,但说明运行证据尚未产生)");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// ── ⑧ 发布适用性门禁(T6,2026-08-31:通用化"陌生人视角"硬闸)──
|
|
125
|
-
// 无 AGENTS.md 冷启动 / 空白规则静默 / 任意编号规则声明式绑定 / 格式契约冒烟 / 个人标识扫描
|
|
126
|
-
step("发布适用性门禁(无 AGENTS.md 冷启动 / 空白规则 / 任意编号 / 个人标识扫描)", process.execPath, [join(root, "scripts", "publish-aptitude-check.mjs")]);
|
|
127
|
-
|
|
128
|
-
// ── ⑨ 发布门禁 B1(阶段 B,2026-09-04:README 版本四性一致性)──
|
|
129
|
-
step("发布门禁 B1(README 版本四性一致性:package.json/徽章/正文/历史表/固定源)", process.execPath, [join(root, "scripts", "readme-version-check.mjs")]);
|
|
130
|
-
|
|
131
|
-
// ── ⑩ 发布门禁 B2(阶段 B,2026-09-04:lib/ 本机痕迹扫描,词表唯一源)──
|
|
132
|
-
step("发布门禁 B2(lib/ 本机痕迹扫描——词表唯一源,命中即红)", process.execPath, [join(root, "scripts", "local-residue-scan.mjs")]);
|
|
133
|
-
|
|
134
|
-
// ── ⑩′ 发布门禁 B3:dualtrack-check(2026-09-09 第三批第 1 波:分层残留棘轮闸——
|
|
135
|
-
// 手册 SKILL.md:113「机器校验(dualtrack-check)为验收兜底」的落地;只许降不许升)──
|
|
136
|
-
step("发布门禁 B3(dualtrack 分层残留棘轮——超出基线即红)", process.execPath, [join(root, "scripts", "dualtrack-check.mjs")]);
|
|
137
|
-
|
|
138
|
-
// ── ⑪ 存在性扫描(泄露预防,2026-09-05:真实路径判据——REAL_PATHS_SCAN 指向扫描器,0 命中才算过;
|
|
139
|
-
// 未设置=WARN(本机增强门禁,通用环境无此工具)──
|
|
140
|
-
{
|
|
141
|
-
const scanReal = process.env.REAL_PATHS_SCAN;
|
|
142
|
-
if (scanReal) {
|
|
143
|
-
step("存在性扫描(真实路径判据,0 命中红线)", process.execPath, [scanReal, "--root", root]);
|
|
144
|
-
} else {
|
|
145
|
-
lines.push("⚠️ 存在性扫描:未设置 REAL_PATHS_SCAN(本机增强门禁;发布流水线建议设置)");
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// ── ⑫ 判据库回归(窗口 B 接入,2026-09-06:净化判据 L1 敏感串全集全历史 0 非白名单 + L2 根段未覆盖 0
|
|
150
|
-
// 红线——JUDGE_SCAN 指向本机判定门禁(stage1 判据库扫描器包装),未设置=WARN(本机增强门禁)──
|
|
151
|
-
{
|
|
152
|
-
const judgeScan = process.env.JUDGE_SCAN;
|
|
153
|
-
if (judgeScan) {
|
|
154
|
-
step("判据库回归(净化判据全历史 0 非白名单 + L2 未覆盖 0 红线)", process.execPath, [judgeScan, "--root", root]);
|
|
155
|
-
} else {
|
|
156
|
-
lines.push("⚠️ 判据库回归:未设置 JUDGE_SCAN(本机增强门禁;发布流水线建议设置)");
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// ── ⑬ pnpm 豁免校验(批次四 04 1.1 B1 口径;E-56 修活后为真跑校验:npm 已发布 latest 必须 ∈ minimumReleaseAgeExclude;
|
|
161
|
-
// 绝对口径(12.4/13.2 裁定):**link 装配不豁免**——四包 npm latest 必须 ∈ 豁免名单(防未来转非 link 装配踩坑 18)──
|
|
162
|
-
{
|
|
163
|
-
try {
|
|
164
|
-
const dshHome = process.env.DSH_HOME || join(process.env.USERPROFILE || "", ".dsh");
|
|
165
|
-
const wsYaml = readFileSync(join(dshHome, "profiles", "web", "pnpm-workspace.yaml"), "utf8");
|
|
166
|
-
const profPkg = JSON.parse(readFileSync(join(dshHome, "profiles", "web", "package.json"), "utf8"));
|
|
167
|
-
const pkgVerLocal = (p) => { try { return JSON.parse(readFileSync(join(dshHome, "profiles", "web", "node_modules", p, "package.json"), "utf8")).version; } catch { return null; } };
|
|
168
|
-
const fourPkgs = ["dsh-rule-engine", "dsh-rules-manager", "dsh-rules-manager-client", "dsh-rule-engine-client"];
|
|
169
|
-
const misses = [];
|
|
170
|
-
const viewFails = [];
|
|
171
|
-
// 豁免判定(单源:scripts/lib/pnpm-exempt.mjs——与 release-plugin 预插共享;一致性测试锁)
|
|
172
|
-
const exempt = (p, v) => exemptPkg(wsYaml, p, v);
|
|
173
|
-
for (const p of fourPkgs) {
|
|
174
|
-
const spec = profPkg.dependencies?.[p];
|
|
175
|
-
if (!spec) continue;
|
|
176
|
-
const isLink = typeof spec === "string" && spec.startsWith("link:");
|
|
177
|
-
const esc = p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
178
|
-
// ⑬ 强校验(12.4 修法绝对口径):npm 已发布 latest 必须 ∈ 豁免名单——**不因 link 装配豁免**
|
|
179
|
-
//(link 包其 npm 已发布版本仍须豁免——防未来转非 link 装配时踩坑 18);本机版校验仅非 link 执行
|
|
180
|
-
let latest = null;
|
|
181
|
-
try {
|
|
182
|
-
const npmCli = join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
183
|
-
latest = (process.platform === "win32" && existsSync(npmCli))
|
|
184
|
-
? execFileSync(process.execPath, [npmCli, "view", p, "version"], { encoding: "utf8", stdio: "pipe" }).trim()
|
|
185
|
-
: execFileSync("npm", ["view", p, "version"], { encoding: "utf8", stdio: "pipe" }).trim();
|
|
186
|
-
} catch { latest = null; viewFails.push(p); }
|
|
187
|
-
if (latest && !exempt(p, latest)) {
|
|
188
|
-
misses.push(`${p}@${latest}(npm latest 未豁免)`);
|
|
189
|
-
}
|
|
190
|
-
if (!isLink) {
|
|
191
|
-
const ver = pkgVerLocal(p);
|
|
192
|
-
if (ver && !exempt(p, ver)) misses.push(`${p}@${ver}(本机版未豁免)`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (process.env.VERIFY_ALL_TESTMODE === "1") { misses.push("TESTMODE 合成 miss(门禁活性自证——必须转红)"); viewFails.push("TESTMODE-合成"); }
|
|
196
|
-
if (viewFails.length) {
|
|
197
|
-
// E2:发布语境(VERIFY_ALL_STRICT=1,release-plugin 3.7 设置)viewFails>0 计 ❌(fail-closed);本地默认 ⚠️ 可见+抑制 ✅
|
|
198
|
-
const strictFail = process.env.VERIFY_ALL_STRICT === "1";
|
|
199
|
-
lines.push(strictFail
|
|
200
|
-
? `❌ pnpm 豁免校验:npm view 执行失败 ${viewFails.length} 包(${viewFails.join("、")})——发布语境 fail-closed(latest 未获取即阻断)`
|
|
201
|
-
: `⚠️ pnpm 豁免校验:npm view 执行失败 ${viewFails.length} 包(${viewFails.join("、")})——latest 未获取(fail-closed:未完成≠通过)`);
|
|
202
|
-
}
|
|
203
|
-
if (misses.length) {
|
|
204
|
-
lines.push(`❌ pnpm 豁免校验:${misses.join("、")} 不在 minimumReleaseAgeExclude(发布后首装会被静默跳过——见踩坑 18)`);
|
|
205
|
-
} else if (!viewFails.length) {
|
|
206
|
-
lines.push("✅ pnpm 豁免校验(四包 npm latest 均已豁免)");
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
lines.push("⚠️ pnpm 豁免校验:读取失败(本机 profile 缺失时跳过)");
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
console.log(lines.join("\n"));
|
|
214
|
-
const failed = lines.filter((l) => l.startsWith("❌"));
|
|
215
|
-
if (failed.length) {
|
|
216
|
-
console.log(`\nVERIFY FAIL:${failed.length} 项问题,见上`);
|
|
217
|
-
process.exit(1);
|
|
218
|
-
}
|
|
219
|
-
console.log("\nVERIFY ALL OK");
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// verify-guard-live.mjs — 0.5.11 运行态实弹验证(验收⑥):版本守卫端到端行为
|
|
2
|
-
// 场景:edit 一个版本化文件(SKILL.md 类),old 唯一、单行整句重写 → 应放行;多行真覆盖 → 应拦
|
|
3
|
-
import { validateEditedFile } from "../lib/core/version-guard.js";
|
|
4
|
-
|
|
5
|
-
// 模拟:current 含 3 行,old="第二行旧句"唯一出现,new="第二行新句"(单行整句重写)
|
|
6
|
-
const current = "第一行\n第二行旧句\n第三行\n";
|
|
7
|
-
const simulated = "第一行\n第二行新句\n第三行\n";
|
|
8
|
-
const old = "第二行旧句";
|
|
9
|
-
const newS = "第二行新句";
|
|
10
|
-
|
|
11
|
-
// 唯一性(模拟工具已确认 old 唯一)
|
|
12
|
-
const unique = current.split(old).length - 1 === 1;
|
|
13
|
-
console.log("old 唯一匹配:", unique, unique ? "✅" : "❌");
|
|
14
|
-
|
|
15
|
-
const res1 = validateEditedFile(current, simulated, old, newS, unique);
|
|
16
|
-
console.log("单行整句重写:", res1.ok ? "✅ 放行" : "❌ 拦截(" + (res1.errors || []).join(";") + ")");
|
|
17
|
-
|
|
18
|
-
// 多行真覆盖(old 两行被无关内容替换)
|
|
19
|
-
const current2 = "line1\nline2\nline3\n";
|
|
20
|
-
const sim2 = "line1\nREPLACED\n";
|
|
21
|
-
const res2 = validateEditedFile(current2, sim2, "line2\nline3", "REPLACED", true);
|
|
22
|
-
console.log("多行真覆盖:", res2.ok ? "❌ 放行(危险!)" : "✅ 拦截");
|
|
23
|
-
|
|
24
|
-
// 删除/缩短(old 子串 new)仍放行 = 正常删行
|
|
25
|
-
const res3 = validateEditedFile(current2, "line1\n", "line2\nline3", "", true);
|
|
26
|
-
console.log("删除行(new 为空=缩短):", res3.ok ? "✅ 放行(删除属正常编辑)" : "❌ 拦截");
|
|
27
|
-
|
|
28
|
-
const pass = res1.ok && !res2.ok && res3.ok;
|
|
29
|
-
console.log("\n=== " + (pass ? "LIVE VERIFY PASS" : "LIVE VERIFY FAIL") + " ===");
|
|
30
|
-
process.exit(pass ? 0 : 1);
|
package/scripts/verify-v474.mjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// verify-v474.mjs - v4.74 记录项引擎在位抽查(分点切分/规则2双检/词表跑)
|
|
2
|
-
import { parseUserIntents } from "../lib/core/intent.js";
|
|
3
|
-
import { actionWordsRe } from "../lib/core/lexicon.js";
|
|
4
|
-
import { evidenceMarkRe, timeWordsRe } from "../lib/core/patterns.js";
|
|
5
|
-
|
|
6
|
-
// ① 分点切分(标点后编号——用户"1、问2、问3、跑"同行)
|
|
7
|
-
const mixed = parseUserIntents("1、为什么预算会满?2、检查时间规则?3、跑");
|
|
8
|
-
console.log("分点(同行标点):", mixed.hasExecute && mixed.clauses[2].type === "execute" ? "✅" : "❌");
|
|
9
|
-
// ② 词表补跑(P8 小批 A 起词表经函数取;本机需 lexicons 配置注入中文词表)
|
|
10
|
-
console.log("词表含跑:", actionWordsRe().test("跑") ? "✅" : "❌");
|
|
11
|
-
// ③ 规则2双检:证据锚、具体时间词(P8 小批 B 起经访问器取;本机需 patterns 配置注入中文表)
|
|
12
|
-
console.log("规则2证据词表:", evidenceMarkRe().test("日志 ts=2026-08-27T15:21:05Z") ? "✅" : "❌");
|
|
13
|
-
console.log("规则2具体词(昨天):", timeWordsRe().test("昨天") ? "✅" : "❌");
|
|
14
|
-
console.log("规则2模糊词(之前):", timeWordsRe().test("之前") ? "❌(应不命中)" : "✅(不命中)");
|
package/upgrade-impact.json
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"versions": [
|
|
3
|
-
{
|
|
4
|
-
"version": "0.2.1",
|
|
5
|
-
"summary": "version-guard 放行非表格单行修改(整行替换但行首锚点一致),避免 edit 工具修改规则正文被误回滚",
|
|
6
|
-
"impacts": [
|
|
7
|
-
{
|
|
8
|
-
"rule": "25",
|
|
9
|
-
"level": "behavior-change",
|
|
10
|
-
"description": "validateEditAppend 新增非表格单行替换放行:行首锚点足够长且规则编号一致时允许整行修改;版本表格行仍保持仅重编号放行。"
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"userRulesUnaffected": true,
|
|
14
|
-
"notes": "升级只更新规则引擎插件本身,不修改 AGENTS.md / SKILL.md / 用户自定义规则。"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"version": "0.2.0",
|
|
18
|
-
"summary": "规则引擎设置面板、升级检查与影响展示;规则 19/21/22/24/25/27 执行口径升级",
|
|
19
|
-
"impacts": [
|
|
20
|
-
{
|
|
21
|
-
"rule": "19",
|
|
22
|
-
"level": "behavior-change",
|
|
23
|
-
"description": "知识沉淀载体从“仅手册”扩展为可选技能/脚本/仓库文档等;不改变用户已写规则文本。"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"rule": "21",
|
|
27
|
-
"level": "behavior-change",
|
|
28
|
-
"description": "规则审批改为分级确认,并新增“选项即边界”;不改变既有规则语义。"
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"rule": "22",
|
|
32
|
-
"level": "behavior-change",
|
|
33
|
-
"description": "被指出错误时需主动给出原因/改正/防再犯;引擎新增 D 级自证提醒。"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"rule": "27",
|
|
37
|
-
"level": "behavior-change",
|
|
38
|
-
"description": "装配变更检测从会话级改为全局 mountRevision + 本会话审计证据;其他会话未审计也会被拦。"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"rule": "24",
|
|
42
|
-
"level": "behavior-change",
|
|
43
|
-
"description": "新增手工编辑 profile package.json 的 dsh.profile.bundles 类型检查。"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"rule": "25",
|
|
47
|
-
"level": "behavior-change",
|
|
48
|
-
"description": "新增 dev_stage_add/call/promote/demote 通用执行器纳入覆盖与敏感授权检查。"
|
|
49
|
-
}
|
|
50
|
-
],
|
|
51
|
-
"userRulesUnaffected": true,
|
|
52
|
-
"notes": "升级只更新规则引擎插件本身,不修改 AGENTS.md / SKILL.md / 用户自定义规则。"
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
}
|