test_step6_falsifiable_bet_reconciliation.py
6.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
"""VERIFY: Step6 「可证伪的下注」交付物契约 + 对账环观测登记 gap
(falsifiable-bet-agent-loop, learn_queue #1399, 2026-10-13 Step6 审计)
学到的知识(原文 L7):
把 Agent 交付物重新定义为「可证伪的下注」——每条策略写明**预测区间 + 引用知识 +
证伪条件**;到期逐条对账预期与实际;若不达标先分叉归因(做法错 / 引用知识本身错),
后者进**知识治理**而非再标一个 failed。
判据句:「无预测区间 + 无证伪条件的交付物 = 不可对账 = 不可学习」。
病理 WHERE=step6_apply apply-done 的对账环入口
WHY=交付物契约只要求「报告完成 + human gate」,不要求预测区间/证伪条件
⇒ 到期无可对账之物,失败只能标 applied,区分不出「做法错」与「引用知识错」,
知识缺陷被记成运气差(下一轮原样再踩)。
实测:learning_results 666 行中 human_feedback 非空 = 1,且该行是
MACHINE_FLAG(endorser=NONE) ⇒ 人工对账行 = 0,对账环从未闭合。
修复:
1) `_has_falsifiable_bet(text)`(全文检测,与存储解耦,CLM #1323 同口径)
2) Step6 报告模板补「- 可证伪的下注: [预测区间 + 引用知识 + 证伪条件 + 对账日期]」
3) `_on_apply_done` 观测登记:缺失 → gate=RECONCILIATION_UNDEFINED / action=REPLAN
4) VerifyReason 登记 RECONCILIATION_UNDEFINED / KNOWLEDGE_ATTRIBUTION_UNFORKED
TDD:
TC1 (RED/复现旧病理) 旧契约下「只写成功标准」的报告被静默接受 → 不可对账
TC2 (GREEN/真实数据) circle.db 实测:人工对账/背书行 = 0(对账环未闭合)
TC3 (GREEN/判别力) 三件套齐全→True;只有成功标准→False;有预测无证伪→False
TC4 (源码守卫/防回退) app.py 含 helper + 两个 reason code 定义与注册 + 模板行 + 登记块
TC5 (冻结重跑 spot check) 同一输入 3 次采样,结果一致(确定性纯函数)
"""
import pathlib
import sqlite3
APP = pathlib.Path("/data/data/com.termux/files/home/wechat-viewer/app.py")
DB = pathlib.Path("/data/data/com.termux/files/home/wechat-viewer/circle.db")
SKILL = pathlib.Path(
"/data/data/com.termux/files/home/.dsh/skills/autonomous-ai-agents/"
"falsifiable-bet-agent-loop/SKILL.md")
FAIL = 0
def old_accepted(report_text, has_human_flag):
"""复现旧契约:只看「报告完成 + human gate 关键词」,不校验预测/证伪条件。"""
return bool(report_text) and bool(has_human_flag is not None)
def has_falsifiable_bet(text):
"""复现新逻辑(与 app.py `_has_falsifiable_bet` 同判据)。"""
t = text or ""
has_prediction = ("预测区间" in t) or ("可证伪的下注" in t) or ("对账日期" in t)
has_falsifier = ("证伪条件" in t) or ("算被证伪" in t) or ("算被推翻" in t)
return has_prediction and has_falsifier
def check(name, ok, detail=""):
global FAIL
print(("PASS " if ok else "FAIL ") + name + (f" — {detail}" if detail else ""))
if not ok:
FAIL += 1
SRC = APP.read_text(encoding="utf-8")
# ── TC1 (RED) 旧病理可复现:只有成功标准的报告被旧契约静默接受 ──
old_report = "# Step 6 知识应用报告\n- 自动修复: 无\n- Human gate: 无\n整体效果不错,已应用。\n"
check("TC1 旧契约静默接受「无预测无证伪」报告(病理可复现)",
old_accepted(old_report, "") is True and has_falsifiable_bet(old_report) is False,
"旧=True 新=False ⇒ 修复确实新增了拦截面")
# ── TC2 (GREEN) 真实数据:对账环未闭合 ──
human_rows = None
fb_total = None
try:
c = sqlite3.connect(str(DB))
human_rows = c.execute(
"SELECT COUNT(*) FROM learning_results WHERE human_feedback LIKE '[HUMAN_CONFIRM%'"
).fetchone()[0]
fb_total = c.execute(
"SELECT COUNT(*) FROM learning_results WHERE human_feedback IS NOT NULL "
"AND human_feedback != ''").fetchone()[0]
c.close()
except Exception as e: # pragma: no cover
check("TC2 读 circle.db", False, str(e))
check("TC2 人工对账/背书行 = 0(对账环从未闭合,实证)",
human_rows == 0, f"human_confirm_rows={human_rows} 机器标记行总数={fb_total}")
# ── TC3 (GREEN) 判别力 ──
pos = "- 可证伪的下注: 预测区间 2~5 次复用;引用知识 X;证伪条件=30 天内复用 <1 次即算被证伪;对账日期 11-13"
pred_only = "- 可证伪的下注: 预测区间 2~5 次复用;引用知识 X"
fals_only = "- 证伪条件=复用 <1 次即算被证伪"
neg = "- 自动修复: 改了 3 行代码\n- 结论: 效果不错\n"
check("TC3a 三件套齐全 → True", has_falsifiable_bet(pos) is True)
check("TC3b 有预测无证伪 → False", has_falsifiable_bet(pred_only) is False)
check("TC3c 有证伪无预测 → False", has_falsifiable_bet(fals_only) is False)
check("TC3d 只有成功标准 → False", has_falsifiable_bet(neg) is False)
check("TC3e 空/None 不炸 → False", has_falsifiable_bet("") is False and has_falsifiable_bet(None) is False)
# ── TC4 (源码守卫/防回退) ──
check("TC4a helper 定义在 app.py", "def _has_falsifiable_bet(text: str) -> bool:" in SRC)
check("TC4b reason code 定义",
"VerifyReason.RECONCILIATION_UNDEFINED:" in SRC
and "RECONCILIATION_UNDEFINED = \"RECONCILIATION_UNDEFINED\"" in SRC)
check("TC4c 归因分叉 reason code 定义",
"KNOWLEDGE_ATTRIBUTION_UNFORKED = \"KNOWLEDGE_ATTRIBUTION_UNFORKED\"" in SRC)
check("TC4d 报告模板含「可证伪的下注」行",
"- 可证伪的下注: [预测区间 + 引用知识 + 证伪条件 + 对账日期" in SRC)
check("TC4e apply-done 登记块(全文检测 + 不改 learn status 口径说明)",
"node=step6_apply.bet_contract" in SRC
and "if not _has_falsifiable_bet(_apply_full):" in SRC)
check("TC4f skill 有 dependencies 声明(4C Composable)",
"dependencies:" in SKILL.read_text(encoding="utf-8"))
check("TC4g skill 悬空引用已修正(meta/agentic-rl-reward-verification 不再被引用)",
"`meta/agentic-rl-reward-verification`:" not in SKILL.read_text(encoding="utf-8"))
# ── TC5 (冻结重跑 spot check) 同一输入 3 次采样一致 ──
samples = [[has_falsifiable_bet(x) for x in (pos, pred_only, fals_only, neg, "")] for _ in range(3)]
check("TC5 3 次采样结果一致(确定性纯函数)",
samples[0] == samples[1] == samples[2],
f"samples={samples[0]}")
print()
print(f"{'ALL PASS' if FAIL == 0 else str(FAIL) + ' FAILED'} (TC1–TC5)")
raise SystemExit(1 if FAIL else 0)