#!/usr/bin/env python3 """Step 6 Gate 接线审计(Microsoft-Decision-1 位点/校验节点知识, learn_queue #1434, 2026-10-14 吸收) 知识判据(原文 L7):企业现场最容易被省掉的恰恰是「校验」——该有的检验节点被跳过, 规则都讲过,但动手写 Skill 时默认倾向仍占上风。**闸门必须由 harness 强制,不靠 prompt 提醒。** 病理(HGB WHERE×WHY): WHERE = Step6 apply-done 的校验节点登记环 WHY = reason code 在 VerifyReason 里声明、在 Step6 报告模板里被「prompt 提醒」, 但从无任何调用方 ⇒ 该检验节点在运行时并不存在(prompt 提醒 ≠ harness 闸门)。 实测:89 个码中 60 个 0 调用方,其中 NO_ENDORSER / GENERALIZATION_RISK 两个码的**唯一**存在形式就是 Step6 提示词里的一句话。 测试用例: TC1 _reason_code_wiring_probe() 契约(keys + 计数自洽) TC2 接线后 prompt_only 收缩:NO_ENDORSER / GENERALIZATION_RISK 不再 prompt-only TC3 _has_endorser() 语义(背书人字段 / NO_ENDORSER 显式声明) TC4 _has_generalization_check() 语义(泛化性核查字段) TC5 源码守卫:_on_apply_done 真的发射 endorser / generalization 两个 node trace TC6 /api/learn/gate-audit 的 layer4_health 暴露接线读数(否则离线审计看不到) """ import re import sys from pathlib import Path APP = Path("/data/data/com.termux/files/home/wechat-viewer/app.py") src = APP.read_text(encoding="utf-8") sys.path.insert(0, "/data/data/com.termux/files/home/wechat-viewer") FAIL = [] def check(cond, label): print((" PASS " if cond else " FAIL ") + label) if not cond: FAIL.append(label) print("TC1 _reason_code_wiring_probe() 契约") try: import app as _app probe = _app._reason_code_wiring_probe() for k in ("n_declared", "n_wired", "n_unwired", "n_prompt_only", "prompt_only", "unwired"): check(k in probe, f"key 存在: {k}") check(probe["n_declared"] == probe["n_wired"] + probe["n_unwired"], f"计数自洽 wired+unwired=declared ({probe['n_wired']}+{probe['n_unwired']}=" f"{probe['n_declared']})") check(probe["n_prompt_only"] == len(probe["prompt_only"]), "n_prompt_only 与列表长度一致") check(probe["n_declared"] > 50, f"声明码数 > 50(实测 {probe['n_declared']})") except Exception as e: check(False, f"_reason_code_wiring_probe 不可用: {e}") print("TC2 prompt_only 收缩(NO_ENDORSER / GENERALIZATION_RISK 已接线)") try: check("NO_ENDORSER" not in probe["prompt_only"], "NO_ENDORSER 不再是 prompt-only(已有 harness 闸门)") check("GENERALIZATION_RISK" not in probe["prompt_only"], "GENERALIZATION_RISK 不再是 prompt-only(已有 harness 闸门)") check(probe["n_prompt_only"] < 4, f"prompt_only 数 < 4(实测 {probe['n_prompt_only']}: {probe['prompt_only']})") except Exception as e: check(False, f"TC2 异常: {e}") print("TC3 _has_endorser() 语义") try: _he = _app._has_endorser check(_he("## Step 6\n- 背书人: 火星人\r\n") is True, "命中 `背书人:` 字段") check(_he("- 背书人: NO_ENDORSER\n") is True, "命中 NO_ENDORSER 显式声明") check(_he("- 背书人: user=yibooo\n") is True, "命中 endorser 具名") check(_he("# Step 6 知识应用报告\n- Gate 密度评分: 5/10\n") is False, "无背书人字段 → False(Gate PASS 不算背书人)") check(_he("") is False, "空文本 → False") except Exception as e: check(False, f"TC3 异常: {e}") print("TC4 _has_generalization_check() 语义") try: _hg = _app._has_generalization_check check(_hg("- 泛化性核查 (RRSI): generalization\n") is True, "命中泛化性核查字段") check(_hg("- 泛化性核查: memorization → GENERALIZATION_RISK\n") is True, "memorization 判定也算已核查(判定本身合规)") check(_hg("- Gate 密度评分: 5/10\n- 执行轨迹评分: 4/10\n") is False, "无泛化性核查字段 → False(memorization 风险未报)") check(_hg("") is False, "空文本 → False") except Exception as e: check(False, f"TC4 异常: {e}") print("TC5 源码守卫:_on_apply_done 发射两个 node trace") check("node=step6_apply.endorser" in src, "发射 node=step6_apply.endorser") check("node=step6_apply.generalization" in src, "发射 node=step6_apply.generalization") check(re.search(r'gate=\{VerifyReason\.NO_ENDORSER\}', src) is not None, "endorser 闸门 gate=VerifyReason.NO_ENDORSER(非裸字面量)") check(re.search(r'gate=\{VerifyReason\.GENERALIZATION_RISK\}', src) is not None, "generalization 闸门 gate=VerifyReason.GENERALIZATION_RISK") # 检测用全文(CLM #1323:检测与存储解耦) _m = re.search(r"if not _has_endorser\((\w+)\)", src) check(_m is not None and _m.group(1) == "_apply_full", f"背书人检测用全文(实参 {_m.group(1) if _m else 'N/A'},须为 _apply_full)") print("TC6 gate-audit 暴露接线读数") check("reason_code_wiring" in src, "layer4_health 字段 reason_code_wiring 已接线(离线审计可见)") print() if FAIL: print(f"RED — {len(FAIL)} 项未通过:") for f in FAIL: print(" -", f) sys.exit(1) print(f"GREEN — 全部通过(reason codes: {probe['n_declared']} 声明 / " f"{probe['n_wired']} 已接线 / {probe['n_prompt_only']} 仍 prompt-only)")