progmune-runtime 3.7.28 → 3.7.29

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.7.29] — 2026-09-14
4
+
5
+ ### 失败语料沉淀接通(知识网络入口修复)
6
+
7
+ - **断点**:信任引擎(trust CLI/agent/patrol/MCP)检出的违规从不写入失败语料库——此前只有 agent-loop 的 planner 失败会入 `.progmune_corpus`,引擎找到的真东西不进库,知识网络永远不喂新数据
8
+ - **修复**(`src/trust/engine.ts` `writeTrustFailuresToCorpus`):每次 evaluateTrust 的违规(cap 50/扫描)经 `recordFailure` 沉淀——intent=`trust-scan:<project>`、severity→SVL 阶梯映射(critical→SVL-4…low→SVL-1)、项目函数名快照(cap 300,语料挖掘词段门控输入)
9
+ - **去重**:同日同(项目+规则+函数)sidecar 去重——反复扫描不重复沉淀
10
+ - **噪声排除**:`PROTOCOL_CROSS_DOMAIN`/`PLAINTEXT_AUTH_WITHOUT_TLS`(已知高 FP、LLM 域映射抖动的 specific-check)不入语料;真实检出面(PATH_TRAVERSAL/SSRF/AUTHZ_CROSS_USER_WRITE/框架层/SSG)照常沉淀
11
+ - **测试隔离**:VITEST/NODE_ENV=test 跳过——单测不污染语料
12
+ - **首批入库验证**:本周 10 条真实检出全部入库存(openhop PATH_TRAVERSAL×4 + FASTIFY×1、open-webui SSRF×3 + AUTHZ_CROSS_USER_WRITE×1、mcp-from-openapi SSRF×1)——其中 open-webui 3 条 SSRF 命中的正是 fr-009 修复补丁加固的 web 加载器函数族,交叉验证 A3 扩展
13
+ - 语料经 immune-reporter 既有管线脱敏上传 hub(默认脱敏口径不变)
14
+
15
+ ### 回归
16
+
17
+ - build ✓ / 引擎测试 21 green ✓ / 语料写入全部 best-effort(永不打断扫描)
18
+
3
19
  ## [3.7.28] — 2026-09-14
4
20
 
5
21
  ### SSRF 检测 TS 化 + Python 形参污点扩展(A3,修复回归 fr-009/010/011 驱动)
package/dist/sdk.js CHANGED
@@ -20,7 +20,7 @@ const risk_model_1 = require("./risk-model");
20
20
  const protocol_knowledge_1 = require("./protocol-knowledge");
21
21
  const evidence_repository_1 = require("./evidence-repository");
22
22
  /** Runtime version — stable public identifier. Internal layers evolve underneath. */
23
- exports.RUNTIME_VERSION = "3.7.28";
23
+ exports.RUNTIME_VERSION = "3.7.29";
24
24
  function verify(filePath) {
25
25
  const cert = (0, certify_1.certify)(filePath);
26
26
  const kb = (0, protocol_knowledge_1.buildKnowledgeBase)();
@@ -140,6 +140,11 @@ async function evaluateTrust(ctx) {
140
140
  ...fiberResult.violations,
141
141
  ];
142
142
  // ═══════════════════════════════════════
143
+ // ── 失败语料沉淀(2026-09-14):信任引擎检出的违规写入本地语料库 ——
144
+ // 知识网络的入口。此前只有 agent-loop 的 planner 失败会入语料,
145
+ // trust 扫描(CLI/agent/patrol/MCP)检出的真违规不沉淀。
146
+ // 测试环境跳过;同日同(项目+规则+函数)去重;语料写入永不打断扫描。
147
+ writeTrustFailuresToCorpus(ctx, allViolations);
143
148
  // PHASE 3: SCORE
144
149
  // ═══════════════════════════════════════
145
150
  const policyResult = (0, score_calculator_1.scorePolicyCompliance)(allViolations);
@@ -1814,6 +1819,97 @@ function mapRiskSeverity(severity) {
1814
1819
  default: return "low";
1815
1820
  }
1816
1821
  }
1822
+ // ═══════════════════════════════════════════════════════════════
1823
+ // 失败语料沉淀(2026-09-14):信任引擎违规 → .progmune_corpus
1824
+ // ═══════════════════════════════════════════════════════════════
1825
+ const SEVERITY_TO_SVL = {
1826
+ critical: "SVL-4",
1827
+ high: "SVL-3",
1828
+ medium: "SVL-2",
1829
+ low: "SVL-1",
1830
+ };
1831
+ /** 与 failure-corpus.ts 相同的语料目录解析(模块加载时定死 cwd 的语义) */
1832
+ function trustCorpusDir() {
1833
+ if (process.env.PROGMUNE_CORPUS_DIR)
1834
+ return process.env.PROGMUNE_CORPUS_DIR;
1835
+ const projectDir = process.env.PROGMUNE_PROJECT_DIR || process.cwd();
1836
+ return path.join(projectDir, ".progmune_corpus");
1837
+ }
1838
+ /**
1839
+ * 把本次扫描检出的违规写入失败语料库(知识网络的入口)。
1840
+ * - 测试环境(VITEST/NODE_ENV=test)跳过——单测不得污染语料
1841
+ * - 同日同(项目+规则+函数)去重——反复扫描不重复沉淀
1842
+ * - 全部 best-effort:语料写入失败绝不打断扫描主流程
1843
+ */
1844
+ function writeTrustFailuresToCorpus(ctx, violations) {
1845
+ if (process.env.VITEST === "true" || process.env.NODE_ENV === "test")
1846
+ return;
1847
+ if (violations.length === 0)
1848
+ return;
1849
+ try {
1850
+ const { recordFailure } = require("../failure-corpus");
1851
+ const fs = require("fs");
1852
+ const corpusDir = trustCorpusDir();
1853
+ const date = new Date().toISOString().slice(0, 10);
1854
+ const dedupFile = path.join(corpusDir, `.trust-dedup-${date}.json`);
1855
+ let seen = {};
1856
+ try {
1857
+ seen = JSON.parse(fs.readFileSync(dedupFile, "utf-8"));
1858
+ }
1859
+ catch { /* fresh day */ }
1860
+ // 项目函数名快照(语料挖掘的词段门控输入),cap 300
1861
+ let projectFunctions = [];
1862
+ try {
1863
+ const irPath = path.join(ctx.projectPath, "ir.json");
1864
+ if (fs.existsSync(irPath)) {
1865
+ const ir = JSON.parse(fs.readFileSync(irPath, "utf-8"));
1866
+ const funcs = Array.isArray(ir) ? ir : (ir.functions || []);
1867
+ projectFunctions = funcs
1868
+ .map((f) => String(f.name))
1869
+ .filter((n) => n && !n.startsWith("__progmune_"))
1870
+ .slice(0, 300);
1871
+ }
1872
+ }
1873
+ catch { /* best-effort */ }
1874
+ let added = 0;
1875
+ for (const v of violations.slice(0, 50)) {
1876
+ // 已知高 FP 的 specific-check 规则不入语料——它们以 LLM 域映射
1877
+ // 抖动为主(open-webui 单次扫描 36 条 CROSS_DOMAIN),对语料挖掘
1878
+ // 是纯噪声。真实检出面(PATH_TRAVERSAL/SSRF/CROSS_USER_WRITE/
1879
+ // 框架层/SSG)照常沉淀。
1880
+ if (v.rule_id === "PROTOCOL_CROSS_DOMAIN" || v.rule_id === "PLAINTEXT_AUTH_WITHOUT_TLS")
1881
+ continue;
1882
+ const key = `${ctx.projectName}:${v.rule_id}:${v.function || ""}`;
1883
+ if (seen[key])
1884
+ continue;
1885
+ recordFailure({
1886
+ intent: `trust-scan:${ctx.projectName}`,
1887
+ projectFunctions,
1888
+ violatedSVL: (SEVERITY_TO_SVL[v.severity] || "SVL-2"),
1889
+ constraintType: v.rule_id,
1890
+ actionSequence: [
1891
+ {
1892
+ kind: "violation",
1893
+ function: v.function || "unknown",
1894
+ file: v.file,
1895
+ rule: v.rule_id,
1896
+ },
1897
+ ],
1898
+ errorDetail: (v.message || v.why || "").slice(0, 500),
1899
+ });
1900
+ seen[key] = true;
1901
+ added++;
1902
+ }
1903
+ if (added > 0) {
1904
+ try {
1905
+ fs.mkdirSync(corpusDir, { recursive: true });
1906
+ fs.writeFileSync(dedupFile, JSON.stringify(seen, null, 2));
1907
+ }
1908
+ catch { /* best-effort */ }
1909
+ }
1910
+ }
1911
+ catch { /* corpus write must never crash the scan */ }
1912
+ }
1817
1913
  function extractFunctionName(text) {
1818
1914
  if (!text)
1819
1915
  return "unknown";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "progmune-runtime",
3
- "version": "3.7.28",
3
+ "version": "3.7.29",
4
4
  "description": "Progmune — AI Trust Decision Engine. Verify AI-generated code before it reaches production. Outputs APPROVED / NEEDS_REVIEW / BLOCKED with evidence.",
5
5
  "files": [
6
6
  "dist/",