--- type: finding node_id: finding:2026-09-09-134-thinking-contracts-validation title: "1.3.4 T0–T4 与 T7 确定性验证" date: 2026-09-09 --- # 1.3.4 T0–T4/T7 实施验证 > 状态:本轮限定的生产契约与确定性测试已实现;不是整个版本验收。原T0–T4/T7记录保留;T5/T6和T8文档续作见文末,独立验证/live/发布未执行。所有原始输出在 `tests/outputs/134/`,不提交。 ## 基线与修改边界 | 项目 | 实际证据 | | --- | --- | | 起点 | `6a09054`,保留既有两个本地测试提交,工作区仅原 `.pi/` 与待提交设计/计划 | | T0 静态 | `t0-check.log`/`.exit`:make check,退出 0,import-linter 1 kept | | T0 指定测试 | `t0-baseline.log`/`.exit`:660 passed,退出 0 | | 生产范围 | 只修改 thinking/providers/client/openai_compat 四文件;端口、类型、缓存指纹、遥测 schema、embedding/OCR 循环未改 | | 文档回滚 | `2553fc7`/`dda5556`;wiki 工具 add_entity 会覆盖无 frontmatter 的同名文件,故先补原文 frontmatter,再以节点存在性保护调用工具,显式登记图节点/implements 边 | ## 红绿证据 | 任务 | 红证据 | 绿证据 | | --- | --- | --- | | T1 AUTO 成员/MiniMax/未知告警 | `t1-red.log`:9 failed,103 passed;都是未拒绝/旧 medium/缺不保证文案 | `t1-green.log`:112 passed | | T1 可执行迁移文案 | `t1-guidance-red.log`:1 failed,旧错误无配置例 | `t13-followup-green.log`:220 passed(含探针收尾) | | T2 on_base 不偷带档 | `t2-wire-red.log`:12 failed,旧解析接受非法开启片段 | `t2-green.log`:137 passed | | T2 raw 纯守卫 | 隔离 `raw-guard` 变异:28 failed,含嵌套根与所有档位 | 还原退出 0;详见 mutation-summary.json | | T3 标准 raw 实际 HTTP | `t3-raw-red-valid.log`:21 failed,旧 transport 发出了冲突请求 | `t3-green.log`:526 passed(工厂/配置/transport/retry/纯解析) | | T3 前置/准入 | `t3-entry-red.log`:4 failed,旧工厂构造后端/请求进入洋葱/冲突未拒绝 | 同上;额外半开探针测试证明可再次取得探针且 inflight=0 | | T3 自定义根 | 隔离 `custom-guard` 变异:3 failed,丢 wire 后私有根绕过 | `t3-custom-green.log`:3 passed | | T4 迁移 | `cache-isolation` 变异:去掉显式身份后能力/fallback/wire 各节点红 | `t4-final-green.log`:190 passed(缓存与遥测);新旧身份回滚、租户、多源和 per-call 覆盖均有断言 | | T4 命中遥测 | `cache-row` 变异:1 failed,历史 low 不应替代本次 medium | 还原退出 0 | | T7 客户端 NULL | embed False→True:6 failed;OCR False→True:12 failed(text/layout 独立红) | `t7-final-green.log`:328 passed | | T7 阳性/emitter | chat True→False:并发实际档断言失败;去 applies 短路:6 failed | 各还原退出 0;chat 糖失败 auto、nearest 失败 medium/成功 low 另有真实链路断言 | 隔离副本来源由 `mutation-import.log` 验证,路径为 `/tmp/pgw134-mutation-*`;无 `.env`、reference、`.pi/`。脚本 `mutate.py`、汇总 `mutation-summary.json`、逐例 `mutation-*-red.log/.exit` 和 `mutation-*-restored.log/.exit` 均留存。11 个变异全部退出 1,逐例还原全部退出 0,恢复后校验文件散列。factory 三个变异分别抓到 Authorization 缺失、timeout 退回 5 秒、trust_env 写死 True。 ## 调试记录(不把无效红当证据) | 现象 | 根因与处理 | | --- | --- | | 初始 raw 红测试反而 21 passed | 测试选 qwen 纯开关形态却请求 HIGH,旧实现先因形态拒绝;改用可表达 HIGH 的 openai 后全部因目标未拒绝而红。`t3-raw-red.log` 不计红证据,使用 `t3-raw-red-valid.log` | | 默认 HTTP factory 新测试 5 failed | 开发机 `socks://` 代理被 httpx 构造拒绝;测试 autouse 删除代理环境,仅隔离外部条件,不改生产 factory,仍分别验证 trust_env True/False。`t3-isolated-green.log`:207 passed | | factory 失败随 T3 提交进入历史 | `8e61a66` 当时附带上述未隔离测试;随后 `71f1bdf` 独立修复。最终工作区全绿;不声称每个历史提交均全绿 | | per-call 迁移工厂测试缺缓存参数 | 合成 env 仍为 cache_backend=none,loader 正确清空 namespace/ttl;改为 memory+显式 TTL,新测试 9 passed,不改生产配置默认 | | conda run 默认捕获模式下 stdin 脚本未执行 | T0 第一次文档提交只有原始两文件;通过 --no-capture-output 重跑安全登记并单独提交,未将第一次零输出当登记成功 | | pi-lens LSP 报缺 pytest/loguru、旧 StrEnum Literal 噪音、Python 3.12 语法不支持 | 非 conda 解释器限制;父监督明确批准记录并继续既定 conda pytest/ruff/import-linter,不改枚举/不加 ignore。后续异步 stale 测试报告已标 superseded,最终实际全量单测输出为准 | ## 当前检查与后续门 | 检查 | 结果 | | --- | --- | | `conda run --no-capture-output -n PolyGateway pytest tests/unit/ -q` | `last-unit.log/.exit`:**1241 passed,3.95 秒,退出 0** | | `make check` | `last-check.log/.exit`:格式/ruff/import-linter通过,退出 0 | | `git diff --check` | 通过 | | 本轮网络/slow | 未执行;所有 HTTP 为 MockTransport,SQLite 为临时文件,无付费调用 | | 独立 verifier/集成/slow/下游迁移 | 由父会话后续执行,本轮不声明通过;设计所列真实缺测和下游缺失仍有效 | 日志方案沿已批设计:未知能力沿既有 loguru warning,实际调用仍经 TelemetryEmitter 单点出口,四类行来源和 NULL 契约用既有 schema 验证,不新增运行时数据面。 ## T5/T6 与 T8 文档续作(起点 16fa0ca) 本续作禁止发布/slow/付费调用,未改任何生产文件。已读完整批准设计、计划及 TDD/structured-logging/commit 技能。独立验证与全量集成/live 仍由父会话负责,本节不表示整个版本验收完成。 | 门/节点 | 本会话实际结果/原始日志(tests/outputs/134/) | | --- | --- | | 受影响基线 | `t56-baseline.log`:client/config/openai_compat **338 passed** | | T5 新模块首次 | `t5-first.log`:98 passed;首次无行为红不计TDD,红证据来自下述隔离变异 | | 当前受影响 | `t56-current-diagnostics-proof.log`:client/live_evidence/config **325 passed**;旧异步2/131通知已被当前结果取代 | | 日常全单元 | `t56-accepted-unit.log/.exit`:**1357 passed,exit 0**(其后仅取证关联/报告字段收尾,受影响325再通过,最终门见提交日志) | | 静态 | `t56-accepted-check.log`:make check 通过;compileall 测试支持模块通过;生产43模块123依赖、1契约通过 | | live 采集 | `t56-accepted-collect.log/.exit`:e2e **90 tests collected,exit 0**;仅采集,不是真实通过 | ### 隔离语义红→还原绿 仓库外临时副本只复制 src/tests/必要工程文件,不复制 `.env`、reference、`.pi`;PYTHONPATH及 cwd 指向副本,import来源见 `t56-mutation-import.log`/`t56-consumer-mutation-import.log`。每个变异均目标 AssertionError、退出1,恢复散列一致后节点退出0,不靠 import error 当红。 | 变异 | 目标节点(tests/unit/test_live_evidence.py) | 红/还原 | | --- | --- | --- | | 整类 skip | test_whole_exception_class_skip_is_forbidden | 1/0 | | 正文子串 model_not_found | test_incomplete_or_ambiguous_error_body_fails | 1/0 | | UNKNOWN 安静→PASS | test_coverage_is_proposition_specific | 1/0 | | 缺轮缩分母 | test_missing_round_never_reduces_denominator | 1/0 | | 身份无证据→skip | test_identity_requires_independent_raw_evidence | 1/0 | | 丢第一轮 | test_round_consumer_keeps_first_success_when_second_assertion_fails | 1/0 | | 部分档未覆盖→模型PASS | test_partial_uncovered_and_failed_rounds_never_become_model_pass | 1/0 | | 不交付独立raw快照 | test_raw_identity_snapshot_reaches_round_consumer | 1/0 | 汇总与逐例日志:`t56-mutation-summary.json`、`t56-consumer-mutation-summary.json`、`t56-mutation-*-{red,restored}.log`;脚本 `mutate-live.py`/`mutate-live-consumer.py`。主工作区从未放回假绿策略。 ### 实现与矩阵边界 取证按 session/parent→attempt→HTTP;零HTTP和多HTTP分开,404严格唯一完整证据,成功非流式原始JSON独立解析并拒重复键。成功SSE不预读、不捕获。真实RetryMW两并发逻辑轮次各503→成功验证精确成功call_id;取消ContextVar复位、资源关闭与逐轮报告写失败显式失败均有离线节点。报告不保存任何原始正文/异常,白名单字段含校验布尔、状态、身份资格与固定安全原因;假凭据/提示词sentinel逐文件无泄漏。 四live文件均迁入窄通道,装配拒绝/平铺键/合成Protocol移入日常;外部Protocol缺包单列未覆盖。M3真实开启改medium,M2 AUTO复用既有T10档;L4迁为退出受管的raw-only高档,双来源本地拒绝由已实现单测守卫。L8不可关闭装配拒绝不计live,未知wire仍显式全None离线验证。UNKNOWN不靠completion长度或prompt锚点升格;L2b仅保留指定历史prompt锚点命题,不是关闭能力。 默认轮数/并发未增加,删除额外UNKNOWN长度锚点调用;T10保留既有一次重试设置,去除60s stall缩小值。静态矩阵:L1–L7合计93逻辑调用,L8可关闭19型号×5=95,T10 NONE 26×5=130及条件长复核≤78,开启57档×5=285,默认基线15,其他chat6+embed1=7;总上界703,不含既有治理重试/结构化重问。没有执行这些调用。 ### 调试与未验证项 | 项 | 实际处置 | | --- | --- | | 新RetryPolicy测试参数误写base_delay_s | 当前工具实报TypeError,查源码后改backoff_base_s/backoff_max_s,239及后续242/325通过;该失败不计目标红 | | make check初报SIM117/B017 | 合并测试上下文,按真实解析异常指定类型,不加ignore;最终静态门通过 | | pi-lens解释器/StrEnum噪音 | 记录 `t56-diagnostics.txt`,conda内真实导入与ruff为门,不改任务外枚举;pytest wrapper generator的return report是协议必需,独立next/send/StopIteration.value测试通过 | | T10型号→400机器字段基线不存在 | 父会话明确确认:不编造白名单,实际400默认FAIL并逐轮留证。纯负向契约精确类型/状态/type单独测试;具体live预期拒绝未验证、需人工基线 | | 结构化反馈重问 | 请求摘要预期固定,发生反馈重问更改messages时保守FAIL,不从待测payload补齐预期;未改生产结构化行为,不声称该取证分支已取得live覆盖 | | 发布/集成/live/下游 | 本任务未执行,M2空wire、M3非流式UNKNOWN、身份不足、三项目实际配置缺失仍保留为证据门 | 文档已同步README M1–M9、CHANGELOG未发布段、env注释、ARCH D11/5.1/7.5/7.8、旧设计替代指针及既有schema/metric;无版本bump、无新生产字段/DDL。Wiki站已下线,不虚报线上页更新。 续作提交:`73008ad test: apply evidence-based live checks without hiding regressions`。最终提交前实际门:`t56-precommit-unit.log/.exit` **1357 passed/0**,`t56-precommit-affected.log` **331 passed**(包含生产默认factory节点),`t56-precommit-check.log/.exit` **make check通过/0**,`t56-precommit-collect.log` **90 collected**,`t56-precommit-compile.log`通过;`git diff --check`通过,`git diff --quiet -- src`确认生产零差异。T8仅文档部分完成,不勾选完整验收门。