#!/usr/bin/env python3 """VERIFY: Step5 reference 分支的 target 前缀缺口(learn_queue #1323 retry, 2026-10-11) 病理(实测):`_verify_and_apply` 的 `otype=="reference"` 分支用 rglob(f"*/{target}/SKILL.md") 而 `target` = learn_target 原文,新建 skill 型吸收带 `new:` 前缀 (如 new:context-language-models-meta-reasoning)⇒ 谓词恒不命中, 「skill 真的落在磁盘上」这道边界事实验不到,只剩 memory.json 短语回退可 grounding。 #1323 因此被判 FINGERPRINT_FAIL(attempt=2),白烧一次重试。 TDD:TC1 是 RED(旧谓词找不到磁盘上真实存在的 skill),TC2 是 GREEN(去前缀后命中), TC3 源码守卫(防回退),TC4 复现 memory 短语回退链(旧路径的唯一活路), TC5 验收本轮真实产物(learn_queue #1323 的 summary 锚点行是否真在 memory.json 中)。 """ import pathlib import sys SKILLS = pathlib.Path("/data/data/com.termux/files/home/.dsh/skills") MEM = pathlib.Path("/data/data/com.termux/files/home/pixelphone/memory.json") APP = pathlib.Path("/data/data/com.termux/files/home/wechat-viewer/app.py") SUMMARY = pathlib.Path("/data/data/com.termux/files/home/tmp/learn_absorb_ca36d4acb352.md.summary.md") RAW_TARGET = "new:context-language-models-meta-reasoning" # learn_target 原文 SKILL_NAME = "context-language-models-meta-reasoning" FAIL = 0 def rglob_skill(tgt): return list(SKILLS.rglob(f"*/{tgt}/SKILL.md")) or list(SKILLS.rglob(f"{tgt}/SKILL.md")) def strip_prefix(t): for pfx in ("new:", "update:"): if t.startswith(pfx): return t[len(pfx):].strip() return t def step5_mem_fallback(outline, result_summary, mem_text): """复现 app.py 的 memory.json 回退链(fingerprint → elif outline 四窗口短语)。""" fingerprint = (result_summary or "").strip()[:30] if fingerprint and fingerprint in mem_text: return "fingerprint" for ph in [outline[i:i + 20] for i in range(0, min(80, len(outline)), 20)]: if len(ph.strip()) >= 10 and ph.strip() in mem_text: return f"phrase:{ph.strip()}" return None print("=== TC1(RED/实测缺口): 旧谓词拿带前缀 target 直接 rglob ===") old = rglob_skill(RAW_TARGET) print(f" {'✅' if not old else '❌'} 旧谓词命中 {len(old)} 个(期望 0,即磁盘上的 skill 被漏掉)") if old: FAIL += 1 on_disk = rglob_skill(SKILL_NAME) print(f" {'✅' if on_disk else '❌'} 该 skill 其实在磁盘上: {[str(p) for p in on_disk]}(前提事实)") if not on_disk: FAIL += 1 print("\n=== TC2(GREEN/修复): 去 new:/update: 前缀后再 rglob ===") new = rglob_skill(strip_prefix(RAW_TARGET)) print(f" {'✅' if new else '❌'} 去前缀后命中 {len(new)} 个 → {[str(p) for p in new]}") if not new: FAIL += 1 print(f" ✅ strip_prefix 幂等性: {strip_prefix(SKILL_NAME)!r} / {strip_prefix('update:'+SKILL_NAME)!r}") assert strip_prefix(SKILL_NAME) == SKILL_NAME and strip_prefix("update:" + SKILL_NAME) == SKILL_NAME print("\n=== TC3(源码守卫/防回退) ===") src = APP.read_text(encoding="utf-8") start = src.find("if not verified_fingerprint and otype == \"reference\" and target:") end = src.find("for sf in skill_files:", start) branch = src[start:end] checks = [ ("分支内出现 tgt_resolved", "tgt_resolved" in branch), ("去前缀循环覆盖 new:", '"new:"' in branch), ("rglob 用的是 tgt_resolved 而非原 target", "rglob(f\"*/{target}/SKILL.md\")" not in branch), ] for label, ok in checks: print(f" {'✅' if ok else '❌'} {label}") if not ok: FAIL += 1 print("\n=== TC4(复现 memory 短语回退链,旧路径的唯一活路) ===") mem_text = MEM.read_text(encoding="utf-8") header_only = "# 学习摘要 — Meta 两篇论文:把 Agent 控制权从 harness 交还模型\n\n正文…" print(f" {'✅' if step5_mem_fallback(header_only, '', mem_text) is None else '❌'} " f"纯中文标题式摘要开头 → 回退不命中(复现 #1323 的 FINGERPRINT_FAIL)") if step5_mem_fallback(header_only, "", mem_text) is not None: FAIL += 1 anchor = "CLM/meta-reasoning anchors (learn_queue #1323): 163 in-place edits, 6-8K tokens" hit = step5_mem_fallback(anchor + " 其余正文", "# 学习完成报告\n\n## 学习内容\n- 标题: Meta 连", mem_text) print(f" {'✅' if hit else '❌'} ASCII 锚点行式开头 → 回退命中({hit})") if not hit: FAIL += 1 print("\n=== TC5(本轮真实产物验收) ===") if SUMMARY.exists(): s = SUMMARY.read_text(encoding="utf-8") outline = s[:500] real = step5_mem_fallback(outline, "# 学习完成报告\n\n## 学习内容\n- 标题: Meta 连", mem_text) print(f" {'✅' if real else '❌'} summary 首 80 字能在 memory.json 中 grounding → {real}") if not real: FAIL += 1 print(f" ✅ 首行纯 ASCII(不受 JSON 转义影响): {all(ord(c) < 128 for c in s[:80])}") else: print(" ⚠️ summary 文件不在,跳过(吸收后 cleanup 会删除)") print(f"\n{'✅ ALL PASS' if FAIL == 0 else f'❌ {FAIL} FAILED'}") sys.exit(0 if FAIL == 0 else 1)