test_step6_gate_wiring.py 5.4 KB
#!/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)")