Files
PolyGateway/research-wiki/findings/2026-09-09-134-thinking-contracts-validation.md
T

19 KiB
Raw Blame History

type, node_id, title, date
type node_id title date
finding finding:2026-09-09-134-thinking-contracts-validation 1.3.4 T0T4 与 T7 确定性验证 2026-09-09

1.3.4 T0T4T7 实施验证

状态:本轮限定的生产契约与确定性测试已实现;不是整个版本验收。原T0–T4/T7记录保留;T5/T6和T8文档续作见文末,独立验证/live/发布未执行。所有原始输出在 tests/outputs/134/,不提交。

基线与修改边界

项目 实际证据
起点 6a09054,保留既有两个本地测试提交,工作区仅原 .pi/ 与待提交设计/计划
T0 静态 t0-check.log.exitmake check,退出 0import-linter 1 kept
T0 指定测试 t0-baseline.log.exit660 passed,退出 0
生产范围 只修改 thinkingprovidersclientopenai_compat 四文件;端口、类型、缓存指纹、遥测 schema、embeddingOCR 循环未改
文档回滚 2553fc7dda5556wiki 工具 add_entity 会覆盖无 frontmatter 的同名文件,故先补原文 frontmatter,再以节点存在性保护调用工具,显式登记图节点/implements 边

红绿证据

任务 红证据 绿证据
T1 AUTO 成员/MiniMax/未知告警 t1-red.log9 failed103 passed;都是未拒绝/旧 medium/缺不保证文案 t1-green.log112 passed
T1 可执行迁移文案 t1-guidance-red.log1 failed,旧错误无配置例 t13-followup-green.log220 passed(含探针收尾)
T2 on_base 不偷带档 t2-wire-red.log:12 failed,旧解析接受非法开启片段 t2-green.log137 passed
T2 raw 纯守卫 隔离 raw-guard 变异:28 failed,含嵌套根与所有档位 还原退出 0;详见 mutation-summary.json
T3 标准 raw 实际 HTTP t3-raw-red-valid.log21 failed,旧 transport 发出了冲突请求 t3-green.log526 passed(工厂/配置/transportretry/纯解析)
T3 前置/准入 t3-entry-red.log:4 failed,旧工厂构造后端/请求进入洋葱/冲突未拒绝 同上;额外半开探针测试证明可再次取得探针且 inflight=0
T3 自定义根 隔离 custom-guard 变异:3 failed,丢 wire 后私有根绕过 t3-custom-green.log3 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→True6 failedOCR False→True12 failedtextlayout 独立红) t7-final-green.log328 passed
T7 阳性/emitter chat True→False:并发实际档断言失败;去 applies 短路:6 failed 各还原退出 0chat 糖失败 auto、nearest 失败 medium/成功 low 另有真实链路断言

隔离副本来源由 mutation-import.log 验证,路径为 /tmp/pgw134-mutation-*;无 .env、reference、.pi/。脚本 mutate.py、汇总 mutation-summary.json、逐例 mutation-*-red.log/.exitmutation-*-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 TrueFalse。t3-isolated-green.log207 passed
factory 失败随 T3 提交进入历史 8e61a66 当时附带上述未隔离测试;随后 71f1bdf 独立修复。最终工作区全绿;不声称每个历史提交均全绿
per-call 迁移工厂测试缺缓存参数 合成 env 仍为 cache_backend=noneloader 正确清空 namespacettl;改为 memory+显式 TTL,新测试 9 passed,不改生产配置默认
conda run 默认捕获模式下 stdin 脚本未执行 T0 第一次文档提交只有原始两文件;通过 --no-capture-output 重跑安全登记并单独提交,未将第一次零输出当登记成功
pi-lens LSP 报缺 pytestloguru、旧 StrEnum Literal 噪音、Python 3.12 语法不支持 非 conda 解释器限制;父监督明确批准记录并继续既定 conda pytestruffimport-linter,不改枚举/不加 ignore。后续异步 stale 测试报告已标 superseded,最终实际全量单测输出为准

当前检查与后续门

检查 结果
conda run --no-capture-output -n PolyGateway pytest tests/unit/ -q last-unit.log/.exit1241 passed3.95 秒,退出 0
make check last-check.log/.exit:格式/ruffimport-linter通过,退出 0
git diff --check 通过
本轮网络/slow 未执行;所有 HTTP 为 MockTransportSQLite 为临时文件,无付费调用
独立 verifier/集成/slow/下游迁移 由父会话后续执行,本轮不声明通过;设计所列真实缺测和下游缺失仍有效

日志方案沿已批设计:未知能力沿既有 loguru warning,实际调用仍经 TelemetryEmitter 单点出口,四类行来源和 NULL 契约用既有 schema 验证,不新增运行时数据面。

T5/T6 与 T8 文档续作(起点 16fa0ca)

本续作禁止发布/slow/付费调用,未改任何生产文件。已读完整批准设计、计划及 TDDstructured-loggingcommit 技能。独立验证与全量集成/live 仍由父会话负责,本节不表示整个版本验收完成。

门/节点 本会话实际结果/原始日志(tests/outputs/134/
受影响基线 t56-baseline.logclient/config/openai_compat 338 passed
T5 新模块首次 t5-first.log:98 passed;首次无行为红不计TDD,红证据来自下述隔离变异
当前受影响 t56-current-diagnostics-proof.logclient/live_evidence/config 325 passed;旧异步2/131通知已被当前结果取代
日常全单元 t56-accepted-unit.log/.exit1357 passedexit 0(其后仅取证关联/报告字段收尾,受影响325再通过,最终门见提交日志)
静态 t56-accepted-check.logmake check 通过;compileall 测试支持模块通过;生产43模块123依赖、1契约通过
live 采集 t56-accepted-collect.log/.exite2e 90 tests collectedexit 0;仅采集,不是真实通过

隔离语义红→还原绿

仓库外临时副本只复制 src/tests/必要工程文件,不复制 .env、reference、.piPYTHONPATH及 cwd 指向副本,import来源见 t56-mutation-import.logt56-consumer-mutation-import.log。每个变异均目标 AssertionError、退出1,恢复散列一致后节点退出0,不靠 import error 当红。

变异 目标节点(tests/unit/test_live_evidence.py 红/还原
整类 skip test_whole_exception_class_skip_is_forbidden 10
正文子串 model_not_found test_incomplete_or_ambiguous_error_body_fails 10
UNKNOWN 安静→PASS test_coverage_is_proposition_specific 10
缺轮缩分母 test_missing_round_never_reduces_denominator 10
身份无证据→skip test_identity_requires_independent_raw_evidence 10
丢第一轮 test_round_consumer_keeps_first_success_when_second_assertion_fails 10
部分档未覆盖→模型PASS test_partial_uncovered_and_failed_rounds_never_become_model_pass 10
不交付独立raw快照 test_raw_identity_snapshot_reaches_round_consumer 10

汇总与逐例日志:t56-mutation-summary.jsont56-consumer-mutation-summary.jsont56-mutation-*-{red,restored}.log;脚本 mutate-live.pymutate-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=95T10 NONE 26×5=130及条件长复核≤78,开启57档×5=285,默认基线15,其他chat6+embed1=7;总上界703,不含既有治理重试/结构化重问。没有执行这些调用。

调试与未验证项

实际处置
新RetryPolicy测试参数误写base_delay_s 当前工具实报TypeError,查源码后改backoff_base_s/backoff_max_s239及后续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预期拒绝未验证、需人工基线
结构化反馈重问(已被本次审查修复替代) 原固定摘要会误拒正常反馈重问,独立审查判 P1;不再保留为可接受限制,修复与真实 StructuredMW 离线两响应证据见下节
发布/集成/live/下游 本任务未执行,M2空wire、M3非流式UNKNOWN、身份不足、三项目实际配置缺失仍保留为证据门

文档已同步README M1M9、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/0t56-precommit-affected.log 331 passed(包含生产默认factory节点),t56-precommit-check.log/.exit make check通过/0t56-precommit-collect.log 90 collectedt56-precommit-compile.log通过;git diff --check通过,git diff --quiet -- src确认生产零差异。T8仅文档部分完成,不勾选完整验收门。

独立审查四项修复(起点 d332287)

按 receiving-code-review 对照实际调用链核验 verify134/live-contracts.md:四项均成立。此处沿用户限定仅更新既有 finding/plan,不新建图实体或扩写设计。生产/版本零差异;没有 live、付费请求或子代理。本节是实现者核验,不冒充新一轮独立复审。

审查项/核验依据 最小修复与守卫
P1 结构化重问:StructuredMW._with_feedback 追加两消息,旧 hook 固定完整摘要必错 仅结构化模型 smoke 启用原提示词前缀摘要、成对 assistant/user 字符串与已有预算;首个 attempt 仍精确原消息。薄委托保存本次摘要只校验 HTTP 保真,不从 wire 反填预期,不关闭重问。真实 GatewayClientStructuredMWMockTransport 缺字段→合法响应恰两 HTTP PASS;破坏前缀、角色、内容类型、配对、预算、wire 均 FAIL;首轮凭空反馈另有 FAIL 守卫
P1 未登记候选:旧 None 分支被置 cannot_disableABSENT 假失败 明确 observation-only,先全轮请求/身份资格,再 UNCOVEREDABSENTOBSERVEDUNKNOWN 与资格 FAIL 四组运行真实 T10 消费者(剔除 .env 读取语句),不调用模型、不改长复核条件或轮次
P1 结论重新 UUID,多个型号失去对应关系 每用例显式传同一 run/model;子运行用该 run 下唯一 matrix_id 关联,结论含完整计划/完成分母。L1–L8、T10短长/各档/默认全部复用;两型号一 PASS 一 UNCOVERED,在 NONE、tiers、L8 三组逐文件验证关联和轮数
P2 机器字段未落盘 仅精确 model_not_found 保留;其他字符串(含假凭据 sentinel)为 omitted;写入端再拒未知机器值,绝不输出任意上游 type

本轮先红后绿与验证

日志位于 tests/outputs/134/,各命令结果后立即保存 .exit,原命令不接管道。

命令/节点 红证据 绿证据
pytest tests/unit/test_live_evidence.py -k structured_reask -q review-f1-red1 failed6 passed,合法两响应误判 FAILexit 1 review-f1-green7 passedexit 0
pytest tests/unit/test_live_evidence.py -k first_attempt_requires -q review-f1-first-red:首轮多反馈被放行,1 failedexit 1 review-final-affected:含该节点共129 passedexit 0
pytest tests/unit/test_live_evidence.py -k unregistered_candidate -q review-f2-redABSENT 被误判FAIL1 failed3 passedexit 1 review-f2-green4 passedexit 0
pytest tests/unit/test_live_evidence.py -k capability_conclusions -q review-f3-red:三组结论缺型号断言红,3 failed,exit 1 review-f3-green:三组+未登记四组共7 passedexit 0
pytest tests/unit/test_live_evidence.py -k safe_machine_type -q review-f4-red:三组缺机器字段,3 failedexit 1 review-f4-green3 passedexit 0
conda run --no-capture-output -n PolyGateway pytest tests/unit/ -q review-final-unit1375 passedexit 0
make check review-final-check:格式/ruffimport-linter 1 keptexit 0
conda run --no-capture-output -n PolyGateway pytest tests/e2e/ -m slow --collect-only -q review-final-collect90 collectedexit 0;不是90通过

上表节点命令也均加 conda run --no-capture-output -n PolyGateway;未使用缺 import 的伪红。最终受影响文件129单测通过,相比111新增18节点。pi-lens仍提示非conda缺httpx/pytest/pydantic及StrEnum等旧噪音,按已批准方向记录后继续conda门;新增测试命名空间显式 Any 类型,不抑制真实错误。

尚未完成:修复后独立复审、集成/make test覆盖率、真实能力取证、下游迁移和发布;T8/T9保持未勾选。M2空wire、M3非流UNKNOWN、真实机器拒绝白名单及外部服务状态不因离线绿变成已覆盖。

重启恢复与 embedding 报告补漏(起点 3eb22d2

恢复时实际分支为 feature/1.3.4-thinking-contractsHEAD=3eb22d2,已跟踪工作区无差异,仅既有 .pi/ 未跟踪;前轮代码提交仍在,重启未丢代码。按用户限定只修测试与本 finding,不动生产 API/版本/计划,不联网、不付费、不运行 slow、不派子代理。本节为实现者验证,不冒充独立复审或版本验收。

tests/outputs/134/slow-gate.log 保留,大小 1625 字节;slow-gate.exit 不存在,属于重启中断、未取得终态,不能宣称 slow 通过。修复前后 SHA-256 均为 05967dcf749b13db815dd80449a0db5b3e7ad2144aa2ae216f8c9ab5ecb21bf5。历史日志不覆盖、不续写,也不把旧 full-gate 作为本轮测试证据。

根因/范围 本轮修复与证据
embedding 消费者遗漏四个字段 仅在原 finally 报告出口增加 requested_model=source.modelprovider=source.providerplanned_rounds=1completed_rounds=1;完成计数指已收尾轮次,FAIL/UNCOVERED 也计入,不代表成功。沿用原 matrixroundsessionparentattempt 关联,不新建报告框架
环境可覆盖请求型号 既有 test_live_evidence.py 增加真实 probe 消费者回归:AST 仅剔除 .envpytestmark 顶层读取,合成环境实际经过 GatewaySettings;两种 probe 型号覆盖都与原 chat 型号不同,HTTP 与报告必须等于本次 source,不能拿默认型号占位
成功与所有目标错误路径 真实 OpenAICompatTransportLiveCaptureObservedTransport+报告写入;仅 HTTP 边界 MockTransport。两型号×成功/503/严格404ConnectError 共8节点,分别 PASSFAILUNCOVEREDFAIL;同时断言唯一报告、逻辑 UUID/attempt 配对、请求校验、状态/错误类型与客户端关闭
安全边界 假凭据及私有提示词 sentinel 放入成功 model 回显、错误正文和请求异常;逐份 Markdown 断言不泄漏,仍只写安全机器枚举/固定原因,不复制原始正文与异常

日志均在 tests/outputs/134/,命令不接管道,先保存真实退出码到同名 .exit 再展示输出。

命令(pytest 前缀均为 conda run --no-capture-output -n PolyGateway 实际结果/日志
pytest tests/unit/test_live_evidence.py -k embed_probe_report -q(修复前) embed-report-red.log/.exit8 failed129 deselectedexit 1;八例均在真实报告消费处 KeyError: requested_model,不是 importmock 签名失败
同命令(四字段补齐后) embed-report-green.log/.exit8 passed129 deselectedexit 0
pytest tests/unit/test_live_evidence.py tests/unit/test_embedding.py tests/unit/test_openai_compat.py::TestDefaultClientFactory -q embed-report-affected.log/.exit188 passedexit 0
pytest tests/unit/ -q embed-report-unit.log/.exit1383 passedexit 0;格式化后 embed-report-final-unit.log/.exit1383 passed4.45秒,exit 0
make check 首次 embed-report-check.log/.exit 为新断言排版失败(exit 2),不是行为红;仅对该测试文件运行 conda ruff format。embed-report-check-green.log/.exit:94文件格式合格、ruff通过、import-linter 1 kept0 brokenexit 0

pi-lens 仍报非 conda 解释器缺 httpxpytestdotenvpydantic 及旧 StrEnum 噪音;按任务授权记录,不添加 ignore、不改枚举、不扩环境修复范围。实际 conda 解释器为 /home/iomgaa/miniconda3/envs/PolyGateway/bin/python,本会话导入四依赖成功(httpx 0.28.1、pytest 9.1.1、python-dotenv 1.2.3、pydantic 2.13.4)。conda 启动器自身另有 base Python 3.13 的 RequestsDependencyWarning;未静音,不宣称输出零告警,测试进程与静态门实际退出0。

本修复不补写真正缺失的历史报告、不改变 embedding 能力判据;真实服务、slow、下游与发布证据仍由后续验收负责。