---
id: question-gen-v3-construction-paradigm
title: question-gen v3 — 构造优先范式重构（全孪生 + 四家族真独立 + 坍缩度量）
type: design
created: 2026-07-15
status: draft
supersedes: 2026-07-15-question-gen-v2-grounded-contrastive-design.md
---

# question-gen v3：构造优先范式重构

## 1. 目标与范围

**完全重构**出题管线，**只做 Action Recognition 分支**。范式从 v2 的"自由生成候选池→打分过滤"（被 [2026-07-15-question-gen-paradigm-shift-construction-over-filtering.md] 判为 AFLite 死路）转向**"从视频树的结构化事实受控构造对比对，grounding/难度/唯一性由构造保证；难度/歧义用两个正交且真独立的信号验证；验收用配对坍缩度量而非原始准确率"**。

**范围铁律**：v3 只产 AR 题（全部 pair 格式）；11 个非 AR 题型仍走旧 `generate-v2`（single，byte-identical，零改动）。题库混格（AR pair + 非 AR single），评测/训练侧用 `QuestionUnit(single|pair)` 兼容。

**决策锁定**（本次 brainstorming）：① 全设计一次到位（6 子模式 + 完整契约）；② 全孪生格式（含 fine_grained 改造成对比对）；③ 全栈验证每题跑，不为成本砍；④ 四家族真独立裁判。

## 2. 范式与文献依据

依据 6 篇原文深读（`reference/papers-distractor-gen/`，证据页码见各深读报告）：

| 论文 | 移植的核心机制（本质，非表面） |
|------|------------------------------|
| Vinoground | 负项=正项**最小结构编辑**（bag-of-words 完全相同、只换单轴）；grounding 靠真实时序事实；**双向 AND** 消语言先验；0 帧盲答对照 |
| TempCompass | **冲突孪生对**（A 的干扰项=B 孪生体正解）；**去捷径坍缩度量**（配对准确率掉回随机=有效性证明）；多格式交叉一致性 |
| VITATECS | **aspect 正交分解 + 单轴等信息量非蕴含最小编辑**；precision-over-recall；**警告：纯词汇/名词替换→74.5-90.3% 可解**（禁止） |
| GroundAttack | 只换负项保 V/Q/A；grounding=独立度量真实视觉对齐；**软肋：wrongness 无独立验证**（必须外挂独立核验） |
| AFLite | **过滤救不了质量**（单信号混淆难/歧义）→ 后置过滤只作兜底 |
| AdVQA | **对抗前移生成端**（活求解器试答骗不过就重构）+ **独立于求解器的多裁判答案一致性**；自动对抗无核验→答案漂移 |

**核心不变量**：① 干扰项=视频里真实存在、但绑到错误查询点的事实（grounded 且 wrong 由构造保证）；② 答案核验器必须独立于被攻求解器；③ 度量用配对坍缩，非原始准确率。

## 3. 架构与数据流

```mermaid
flowchart TD
  T[视频树: 有序L1/L2/L3 + 结构化列表 + subtitle + frame_path] --> FS[fact_sampler 采可翻转结构化事实]
  FS --> AX{子模式→孪生轴路由}
  AX --> TB[twin_builder 构造孪生对 P/Q<br/>单轴最小编辑, bag-of-words 硬匹配, 禁蕴含]
  AX --> AB[attribute_binder 静态属性绑定<br/>需薄抽取层: 树自由文本→对象,属性,位置]
  TB --> L1[层1 结构构造保证: 相反事实锚定树节点]
  AB --> L1
  L1 --> L2[层2 坍缩度量: text-only盲答 + 单帧基线 掉回随机]
  L2 -->|未坍缩| RJ[拒/重构]
  L2 --> L3[层3 看帧核实: qwen+MiniMax 交叉查构造事实真伪]
  L3 -->|安慰剂: 错配帧分不坍塌| RJ
  L3 --> L4[层4 活求解器难度探针: deepseek AgentLoop 双向答对=太易]
  L4 -->|太易| RJ
  L4 --> L5[层5 独立多裁判歧义: kimi+qwen+MiniMax 三异家族判唯一性]
  L5 -->|歧义/双正解| RJ
  L5 --> L6[层6 多格式交叉: MC vs Y-N 求解器一致]
  L6 -->|不一致=格式捷径| RJ
  L6 --> ACC[on_accept 逐 unit 原子成对落盘]
  RJ --> QN[失败内容指纹入 quarantine 去重] --> BF[补构造迭代<br/>收敛上界+产量降级路径]
  BF --> FS
```

## 4. 六子模式构造算法

统一原理：**对锚定真实树事实的"正题"做单轴最小编辑得孪生"反题"，干扰项=视频里真实存在但绑到错误查询点的事实**。

**选项基数（契约锁定，§7 阈值全对齐）**：每个孪生子题 = **4 选 MCQ**（1 正解 + 3 干扰项），孪生 P/Q **共享同一 bag-of-words 选项集**（同词不同绑定），答案跨孪生翻转。

所有孪生对硬约束：
- **bag-of-words 硬匹配**（非"尽量"）、单轴、等信息量、动词/事件结构编辑（**严禁名词/属性词汇替换**，VITATECS 实测改 1 名词即 82% 可解）；
- **禁蕴含**：正解与各干扰项互不蕴含，由 **kimi 真 LLM 裁判判定**（text-embedding 仅作 bag-of-words 词形辅助，**不得作蕴含唯一信号**——审核 C7：embedding 近似蕴含是假绿灯）；
- **平衡/因子布局根治逐维众数（C1 根治，非仅事后指标）**：4 个选项在每个语义维度上每个取值出现次数均衡（→逐维众数无定义），构造后跑 `majority_vote_baseline(options)==answer → fail` **纯算法硬校验**，作阶段 2 CI hard-fail；
- **槽位强制反置**（防 C6 槽位偏置）+ **干扰项多样性**（3 个干扰项两两 embedding 距离须过下界门，防 GroundAttack distractor-similarity 扎堆一起被排除）；
- **题干模板对称（C8，防翻转轴泄露）**：before/after、first/last 题干本身会暴露翻转轴 → 题干须模板对称（不靠词面差异指示答案）；**pair 关系可解率（P+Q 盲答+规则解法）作构造期 hard-fail**，不只事后验收指标。

| 子模式 | 孪生轴 | 锚定树的什么 | 正/反题构造 | 干扰项来源 |
|--------|--------|-------------|------------|-----------|
| **temporal** | 时序换序 | L1 下有序 L2 序列或 L2 下有序 L3（`time_range`/`timestamp`，`children` 顺序=时序） | 正"X 之后是什么"→答真实后继；反 before↔after 翻转→答真实前驱 | 同视频真实存在但时序位置错的事件 |
| **cross_segment** | 主宾互换/first-last | `action_subjects`+`actions` 跨 L2 段 | 正"谁**先**做 X"、反"谁**后**做 X"，选项同集 | 别的段真实做该动作的主体 |
| **premature** | 早/晚段锚点 | 段位**随机**（early/mid/late/final 各占，不固定 final） | 正问最终态、反问指定中间态 | 过早锚定的早段真实读数 |
| **evidence_gap** | 诚实↔虚构因果 | 事件链 + `state_changes`(注意常 null，不可依赖) | 正支证据在场答=事实；反支证据缺席答="不可确定" | 树中未展示的合理因果延续（虚构但貌真） |
| **semantic_rigidity** | 同义↔字幕陷阱 | 树的 `subtitle` 字段 + 视觉 `event_description` | 正题字幕与视觉真相一致；反题字幕是陷阱（匹配干扰项） | 字幕字面项（与视觉真相冲突） |
| **fine_grained** | 同动作不同方式 | `ongoing_actions`+`visual_attributes`+看帧（需薄抽取） | 同一动作两个真实时刻的不同执行方式做对比 | 另一时刻该动作的真实不同方式 |

> **事实来源澄清（对齐 §9）**：上表"锚定树的什么"列对 temporal 是**树结构直取**；对其余 5 子模式**仅为索引/候选提示**——真正的 grounded 事实由 **§9 帧感知抽取层从真实帧感知 + 双 VLM 交叉核实**得出（树的 `state_changes` 常 null、`actions/action_subjects` 无绑定等有损，均由帧感知绕过）。

> **VITATECS 硬警告落地**：编辑必须落在**动词/事件结构**（时序/主宾/次数/方式），**严禁名词/属性词汇替换**（原文实测改 1 名词即 82% 可解）。每题构造后跑纯算法门校验单轴性 + bag-of-words 相等 + 逐维众数无定义。

> **非 temporal 子模式的范式合法性论证 + 必达归属**（回应 finding §5 与 VITATECS 静态退化警告；构造机制见 §9 帧核实抽取层）：
> - **cross_segment / premature / semantic_rigidity = 必达**（§15 阶段2）。合法性——编辑轴均落在**事件结构**（主体-动作绑定 / 段位状态 / 视觉真相 vs 字幕字面），**非静态名词替换**，不落入 VITATECS 退化区；grounding 由 §9 帧核实抽取保证。semantic_rigidity 作为必达静态类，编辑轴=视觉真相 vs 字幕字面。
> - **fine_grained = 实现+目标必达 + 运行时门兜底**：编辑轴是**动作执行方式（manner，属动词/事件结构轴：快↔慢、左手↔右手、单次↔重复）非静态名词**；grounding 由"两个真实时刻的方式对比"锚定。风险=未必总能找到两个真实对比时刻（产量）+ 方式差异是否够单轴等信息量。运行时合法性门不过则退 finding B 路线。
> - **evidence_gap = 实现+目标必达 + 运行时门兜底**："不可确定"选项**必须在正/反题对称出现**（防审核 C3"恒定文本靶"）；编辑轴=证据在场↔缺席（事件结构）；幻觉风险最高，运行时门不过退保守构造。

## 5. 四家族模型分工

| 角色 | 模型 | .env 变量 | 家族 |
|------|------|----------|------|
| 活求解器难度探针（复用 `core/agent` AgentLoop） | deepseek-v4-pro | SEARCH_LLM | A |
| 构造表面实现 + 看帧核实 | qwen3.6-plus | VL_LLM | B |
| 独立看帧核实（异家族交叉） | MiniMax-M3 | M3_VL_LLM | C |
| 独立歧义/唯一性 + **禁蕴含真裁判** | **kimi-for-coding** | **新增 JUDGE_PANEL_LLM** | D |
| **仅 bag-of-words 词形辅助**（非蕴含判定） | text-embedding-v4 | TEXT_EMBEDDING | 纯算法 |

> **禁蕴含/语义等价判定用 kimi 真 LLM 裁判**，text-embedding 只做"选项词袋是否相等"的词形辅助——**embedding 余弦不得作蕴含唯一信号**（审核 C7：测不出语义泛化蕴含，是假绿灯）。

> 图像嵌入 `qwen3-vl-embedding` 暂不可用（几何跨模态 grounding 推迟）；全孪生构造范式不依赖它。`kimi-for-coding` 需新增 .env 配置并**先测网关 newapi 是否服务**（实现第一步验证）。所有调用经 `GovernedLLMClient`（`adapters/llm.py`）治理，禁裸调。

## 6. 六层验证栈（每题全跑，机制种类各异，不共享失效模式）

| 层 | 机制种类 | 判据 | 失败处置 |
|----|---------|------|---------|
| **1 结构构造保证** | 符号 | 孪生答案=锚定树节点的相反事实，构造时即成立 | 构造非法→重构 |
| **2 坍缩度量** | **模型探针→统计判据**（非纯算法，见 §7 分类） | text-only 盲答（deepseek，**输入含 subtitle** 以捕字幕泄答案）+ 单帧基线（VLM）正确率**必须掉回随机**（4 选≈0.25；pair 双向≈0.0625）；超容差=可纯文本/单帧/字幕解→拒 | 拒+指纹去重 |
| **3 看帧核实 + 帧错配安慰剂** | 视觉感知 | qwen+MiniMax 交叉查"构造相反事实真成立、干扰项在查询点真不成立"；**安慰剂：喂错配帧分数须坍塌**（不坍塌=没真看帧）→拒 | 拒+重构 |
| **4 活求解器难度探针** | 行为/对抗 | deepseek AgentLoop 对 pair 双向作答；双向都对=太易→拒（对抗前移，AdVQA） | 拒+补构造 |
| **5 独立多裁判歧义核验** | 语义 | **多裁判 = kimi（D 文本）+ qwen（B 看帧）+ MiniMax（C 看帧）三异家族**，均独立于求解器（deepseek A）；判是否有干扰项也成立/双正解，AdVQA 式一致性（无共识/多数判双真→拒）。text-embedding **不算裁判** | 拒+指纹去重 |
| **6 多格式交叉一致性** | 跨格式 | 同一构造事实生成 **MC + Y/N 两格式**，求解器跨格式作答须一致；不一致=格式捷径而非真理解→拒（TempCompass 多格式交叉） | 拒+重构 |

> **ABSTAIN 处置明确 + 终态闭环（防旧非对称谬误 + Codex I5）**：任一 VLM 探针"无法给有效帧引用"→记 `ABSTAIN` 入**分层人工抽检队列**，既不自动放行（防"引不出=放过"）也不自动过杀。**必须有终态**：人工结论回写 `unit_verdict`（accept/reject）；**超 SLA 阈值未标注按 fail 处理**（防无限 pending 吞产量）。
> **难度/歧义两口径正交不复用**：难度=求解器答错（层4）；歧义=独立裁判判唯一性（层5）。永不用同一次评分兼两职。

## 7. 坍缩度量与反自证验收指标

**主验收=配对坍缩**（TempCompass 度量革命）：有效性证明不是原始准确率高，而是去捷径后掉回随机的幅度。

> **指标三分类（I3，防 R4 自证误分类）**：**纯结构指标**（逐维众数命中率、答案槽位卡方、pair 关系规则解法、distractor 距离）——不依赖任何模型，是真正的算法地锚；**模型探针指标**（text-only 盲答、单帧基线、帧错配安慰剂、双正解率+κ、多格式一致率）——依赖模型输出的统计判据，**不得当"纯算法"背书**；**人工/抽检指标**（难/烂混淆矩阵）——分层小样本人工双标签。三类须分别标注，验收结论以纯结构 + 人工为硬地锚，模型探针为辅助信号。

| 指标 | 靶向 | 手段（外部/纯算法/独立） |
|------|------|------------------------|
| 逐维众数命中率 | ②结构捷径 | 纯算法机械投票，阈值≈随机 |
| 答案槽位卡方 + pair 槽位反置率 | ②C6 | 纯统计 |
| text-only 盲答 / 单帧基线 掉回随机幅度 | 语言先验/单帧 | **模型探针**（deepseek 盲答 + VLM 单帧，非纯算法地锚，见上分类）|
| 帧错配安慰剂坍塌幅度 | ①虚假 grounding | 错配帧分数须显著坍塌 |
| pair 关系可解率 | ②C2 | P+Q 盲答+时序排序规则，须≈1/16 |
| **subtitle_answerability_rate** | ②字幕泄答案 | 仅喂 subtitle+选项盲答，须≈随机 |
| **distractor_similarity（多样性）** | GroundAttack 扎堆 | 3 干扰项两两 embedding 距离须过下界 |
| **多格式交叉一致率** | 格式捷径 | MC vs Y/N 求解器答案一致率（低=格式捷径） |
| 双正解率 + 裁判 κ | ③歧义 | kimi vs qwen/MiniMax（异家族），基线 33%→阈值≤5% |
| 难/烂混淆矩阵 | ④/R4 | 分层人工抽检小样本双标签（可选锚点） |
| quarantine_rate / backfill_yield_by_round / judge_disagreement_by_subpattern | R5/系统 | 观测落 run_store |

阈值全部进科研 YAML + harness run 快照（可复现、可扫动）；kimi/qwen endpoint 属工程 `.env`。

## 8. QuestionUnit 契约（贯穿采样/分批/聚合，混格题库）

`core/types.py` 新增 `QuestionUnit(single|pair)`：pair 载 `pair_id`/`twin_a`/`twin_b`/`flip_axis`/`unit_hash`/`collapse_metric`；`GeneratedQuestion` 加 `unit_id`/`pair_id`/`question_role`/`flip_axis`（默认值保非 AR single 不变）。

> **选项基数契约（锁定，与 §4/§7 对齐）**：每个 `GeneratedQuestion`（含 twin 的 P/Q 子题）**仍是 4 选 MCQ + 字母答案**，AgentLoop/harness 的 MCQ 作答契约**不变**；pair 语义只是"P、Q 共享 bag-of-words 选项集、答案翻转、双向 AND 聚合"。多格式的 Y/N 子题作为**验证探针**（层6）——**独立类型、独立存储表、硬校验其不进 benchmark/pools/predictions、不复用 `GeneratedQuestion`**（M1），仅在构造期核验一致性后即抛弃，不改 MCQ 契约。

**≥13 处改造入口**（复用审计 + 契约审核全表，v2 只覆盖 7 处，遗漏必崩）：

| 入口 | 文件 | 改造 |
|------|------|------|
| Global 三池切分 | `pools.py::build_pools`/`_sample_excluding` | 互斥单元 qid→pair_id，pair 同池 |
| per-category 切分 | `pools.py::_split_one_category` | 输入改 unit，pair 不跨 train/val |
| 分层采样 | `loader.py::stratified_sample` | 按 unit 计数，flatten 前 pair 不拆 |
| batching 对错桶 | `batching.py::_select_mixed_by_task_type` | 按 **unit correctness（双向 AND）** 分桶 |
| batching 整锁 | `batching.py::build_batches` | pair 像小类整组装箱，**同 batch 不拆**（否则坍缩算不出） |
| 聚合 | `inference.py::run_inference` | pair 按 pair_id 收齐→pair-level record 双向 AND；unit 粒度 total/correct |
| 序列化冻结/解冻 | `pools.py::_q_to_dict`/`_dict_to_q` + `save_pools.categories` | 显式写读 4 pair 字段 + 以 unit 记 train/val |
| gate 阶梯 | `gate_ladder.py::build_cold_entries`/`ladder_for`/`update_probs` | entry 迁 unit_id + **schema_version + 迁移脚本**（存量 gate_pools.json 失效防硬崩） + 冷启动 2:1/gamma-EMA/Beta 先验按 unit 重定义 |
| e-process | `core/evolution/validate.py::pair_block` | McNemar 臂配对按 unit（P AND Q 折叠后比对） |
| correctness 消费（C3） | `runner.py`（rollout 回写 163-190 / accept 合并 1125-1142 / val 回写 1442-1454 / quadrant 分桶 / probation / momentum 1719-1760）+ `core/evolution/validate.py`（`pair_block` 12-37 / `compute_accuracy` 72-85） | 见下"correctness API 规格"——**逐一列出并改写这 8+ 调用点**，非仅"新增视图" |
| **checkpoint/resume（C2，新增）** | `runner.py::epoch_batches`/`_batch_from_ids`（199-210/711-725） | 保存 **unit_id 序列**（非逐题 qid），恢复时展开完整 unit，防断点续跑后拆 pair |
| **gate BaselineCache（C2，新增）** | `gate_ladder.py::BaselineCache`（277-335） | 键从 qid 改 unit_id，基线缓存按 unit 记忆，防 P/Q 分开缓存污染双向 AND |
| 作弊门 | `adversarial_filter`→v3 难度探针 | pair 粒度判太易，禁半剔 |
| 读回 benchmark | `loader.py::load_benchmark` | 补读 4 pair 字段（`.get` 兼容旧 JSON） |
| 非 AR rng 隔离（I4） | `loader.py`（86-98/123-131/154-172 的 `rng.sample`）+ `pools.py`（604-612/811-815 的 split/shuffle） | **实现前先枚举所有 `rng.sample/shuffle` 调用点**；非 AR 抽样输入与 RNG 流固定，AR pair 折叠用**独立 seed namespace**，二者 draw 互不干扰 |

**correctness API 规格（C3，三对象转换边界，非口号）**：显式定义三个对象及转换——
- **逐题 predictions**（`question_id → prediction`）：唯一溯源真相，rollout 逐题写。
- **unit correctness**（`unit_id → bool`）：AR pair = P.pred==P.ans **AND** Q.pred==Q.ans；非 AR = 单题。由 predictions 折叠得出，供进化/gate/quadrant/momentum/probation **统一消费**。
- **pair collapse metric**（`pair_id → 坍缩指标`）：验收用，不进 correctness。

上表 8+ 调用点**逐一改写为消费 unit correctness**（含 `validate.py::compute_accuracy` 分母改 unit 数、`pair_block` McNemar 臂按 unit 折叠、quadrant 分桶按 unit_id）；e-process 的 delta 信号在 unit 粒度计算，防 P/Q 单题计分污染进化。**先写此 API 规格 + 调用点替换清单，再动实现。**

## 9. 帧感知 grounded 事实抽取层（一等公民，支撑全部 6 子模式）

**这是让 6 子模式全部进入必达、又不滑回 v2 生成-过滤陷阱的关键机制。核心原则：树只是有损索引，真正的 ground truth 是帧本身——抽取直接喂真实帧，不依赖树的有损自由文本。**

盘上每视频有真实关键帧（5 帧/L2 段，`store/videos/<id>/frames/`，L3 `frame_path` 定位）；需更密帧时按 video id 重下原视频补采（有界局限，见 §16）。`grounded_fact_extractor`（新建一等公民组件）：

1. **帧感知抽取（VLM 对真实帧做感知，非对文本做解读）**：把目标段/时刻的真实帧喂 VLM，直接感知结构化事实——cross_segment 感知 `(主体,动作,段)` 绑定；premature 感知"各段状态读数"；semantic_rigidity 感知"视觉真相"再与 `subtitle` 比；fine_grained 感知"动作执行方式"（左右手/快慢/次数）；evidence_gap 感知"哪些证据视觉在场"。树的 `event_description`/`entities` 仅作**索引与候选提示**，不作事实来源。
2. **双 VLM 交叉核实 + Fact schema（Codex C6）**：每条感知事实由 **qwen + MiniMax 两异家族 VLM 对同帧交叉核实**，落 **Fact schema**：`fact_id, subject, action, object, segment_id, frame_ids, polarity(真/假), verifier_refs, cross_agree, fact_type, difficulty_tier, negative_at_target`。**只有两 VLM 一致 + 多帧核实通过 + 绑定唯一的 fact 才进构造**；不一致/不唯一→丢弃。

### 9.1 构造合法性硬约束（Codex 三审 C3/C5/C1/C4，缺一即滑回歧义/伪难题）

- **判别性 + `negative_at_target` 排他（C5，最关键）**：干扰项**不是"任何真实事实绑错点"**——错绑定 ≠ 逻辑否定。必须：(a) 只选**判别性事实**（跨查询点/翻转轴会变的，非"表演者在台上"这类跨段持续/复现的事实）；(b) 每个干扰项显式 `negative_at_target`——**帧核实它在目标查询点确为假**（闭世界证据或翻转轴互斥证明），不过则**判双正解 hard-fail**。重复场景视频（同一主体贯穿）大量事实非判别，须按此剔除（产量由 §10 降级兜底）。
- **按 fact_type 的最小采样密度（C3）**：凡涉及**顺序/变化/次数/速度**的 fact（cross_segment 先后、premature 状态变化、evidence_gap 在场缺席、fine_grained 方式）——5 帧/段不足以稳定感知 → **触发密帧重采（按 video id 重下补帧）或降级**；不止 fine_grained。§9 为每个 fact_type 定最小密度。
- **fact_type 难度分层（C1）**：粗粒度物体/姿态感知可靠，但**主体-动作绑定/快慢/计数/证据缺席是高阶判断**——这些 fact_type 打高 `difficulty_tier`，走**更严核实**（更多帧 + 人工小样本校准），禁止当普通感知放行。
- **唯一绑定粒度 + 不唯一拆分（C4，防产量崩）**：定义唯一性粒度（同 segment/同 frame/同 action class/同 option set）；多主体多动作段不唯一时**给拆分策略**（拆到可唯一的粒度再构造），而非一律丢弃。
- **双 VLM 共享盲区校准（C2）**：两 VLM 一致**只降随机噪声、不排除同向幻觉**；加错配/遮挡/反提示一致性校准 + **人工小样本估 shared-error rate** 落验收面板；一致不当真值背书。

### 9.2 实证验证状态（小样本 spike，见 [2026-07-15-v3-frame-perception-spike-validation.md]）

5 视频×3 段、94 次 VLM 调用 + Claude 亲自看帧核查，**机制已验证站得住**：可抽取率 100%、判别性 ~83%、negative_at_target 实证有效（正确抓双正解）、双 VLM 一致 87%、粗时序 5 帧可感知、抽样无双 VLM 一致幻觉。据实证细化 5 条（须折进实现）：
1. **fact_sampler 加"动作性"前置筛**（样本含幻灯片/录屏非动作视频，抽取虽成功但对 AR 无意义）。
2. **fine_grained 密帧从"运行时兜底"升为"硬前置"**（实证：manner 5 帧确实不够，必须密帧重采或走 B 路线，不等运行时才发现）。
3. **manner 类 fact 不靠双 VLM 交叉核**（实证一致性低）→ 走更严核实（更多帧+人工小样本），对齐 §9.1 C1 难度分层。
4. **抽取主用详细但准确的 VLM（MiniMax 风格），保守 VLM（qwen）作交叉核**。
5. 多主体绑定未被 spike 压测（样本多单主体）→ 见 §16 开放风险。

**为何这不是 v2 陷阱、且比"从树文本抽取"更强**：v2 的失败是"VLM **判分**自由发明的干扰项"（判断题，不可靠）；这里是"VLM **感知**真实帧里有什么"（感知/描述题，可靠得多）——干扰项始终是**从真实帧感知到的真实事实绑到错误查询点**，从不自由发明、从不循环打分。wrongness 由构造保证（真事实、错绑定），grounding 由**真实帧感知 + 双 VLM 交叉**保证（短于人工标注下最强）。

**做不了**：bbox/像素坐标/精确计数/说话人 ID——放弃，不硬凑。

**grounding 强度诚实分档**（不抹平）：temporal = **结构保证**（树顺序，零模型依赖）；其余 5 = **帧感知验证保证**（真实帧 + 双 VLM 交叉 + Fact schema，模型依赖但锚在真实视觉证据，非自由发明）。两档都是合法 grounded，来源不同，须在验收报告分别标注。

## 10. 对抗前移、产量与续跑

- **难度探针前移**：构造后、落盘前即用 deepseek AgentLoop 试答（对抗前移），不是事后过滤。
- **失败题内容指纹去重**（R5 真正对症）：对**题面语义内容**（非 question_id）算指纹，`拒/太易/歧义` 的内容指纹入 quarantine 黑名单；补构造命中黑名单即丢（堵"等价题换皮重试穿门"）。
- **收敛上界**：`max_total_constructed`/`max_backfill_per_slot`/`min_pass_yield`；连续 N 轮低产即停并报告。
- **产量降级路径**（解产量危机，三选一写进配置）：欠产（如 22/30）作为**带质量标签的正式交付物**；或 min_pass_yield 触发转分层人工抽检；明确**质量优先于数量**，`generate_ar30.sh` 的 TARGET 变软。

## 11. 模块结构（Clean Architecture 四层）

**在现有 `app/question_gen/` 内按领域模块替换/重组**（对齐 CLAUDE.md §4.2"直接改原文件、不留向后兼容"与 §5"禁版本化并行目录"——**不建 `app/question_gen_v3/` 并行目录**）。废弃模块（generator_v2/synthesizer/distractor_selector/gates/pipeline_v2）**原地删除或改写**，新增领域模块同目录落位：`fact_sampler`（采可翻转事实）、`constructor`（子模式→孪生轴路由）、`twin_builder`（孪生构造）、`grounded_fact_extractor`（§9 帧核实事实抽取，喂 cross_segment/premature/semantic_rigidity/fine_grained/evidence_gap）、`difficulty_prober`（活求解器，**不兼答案裁判**）、`ambiguity_verifier`（kimi 独立多裁判）、`collapse_metric`（结构/探针/人工三类验收，见 §7）、`pipeline`（主编排，替换 pipeline_v2）；`run_store` 原地扩 pair 感知（不新建 run_store_v3）。

**复用地基**：`adapters/*` 全部（GovernedLLMClient/VLM/telemetry/熔断/缓存）、`core/protocols`（扩 `JudgePanelProvider`）、`core/types`（扩 QuestionUnit）、`app/harness/*`（pair 契约适配，见 §8）、`run_store.py`/`loader.py`（续跑/加载基建）。

**废弃**：`generator_v2`/`synthesizer`/`distractor_selector`/`gates`/`pipeline_v2` 主编排 + 对应 prompts/config。**拆解复用**：`adversarial_filter` 的孪生翻转构造 + 活求解器探针 + verdicts 续跑（去后置过滤外壳，提升为构造/核验主路径）。**借鉴语义**：`strategy_action_recognition` 的 6 skill 靶点 + flip_axis 标注。

## 12. 非功能性需求（重写必须继承，防隐式丢失）

| 维度 | 设计 |
|------|------|
| **持久化** | 逐 **unit** 原子成对落盘：pair 在内存 pending buffer 收齐 P+Q 后一次性进 accepted；全量 tmp + `os.replace`，**pair 同落或都不落**，崩溃不留半对 |
| **幂等性** | 同 seed→同构造；孪生由 flip_axis 确定性构造；VLM 非确定为既有属性；`unit_hash` 检测续跑失效 |
| **断点续跑** | progress（slot→status）；pair 以"整对完成"为 accepted 单位；verdicts 表按 (question_id/hash/config 指纹) 三元组续跑；config 指纹失效作废脏续跑 |
| **原子性** | 逐 unit 落盘；读回校验 pair 成对完整、剔孤儿；补构造续跑三件套（seq_offset/used_node_ids/embed_pool） |
| **治理/遥测** | 所有 LLM/VLM 经 GovernedLLMClient 五层栈；session_id 透传每次调用必录 telemetry |
| **并发/降级** | asyncio.Semaphore 限流；JSON 解析失败区分"契约违反 raise"vs"可降级 warning"，不静默 |

### 12.1 日志与可观测方案（须走 structured-logging skill）

v3 产生大量运行时数据。设计阶段先给出**表结构骨架**（对齐 CLAUDE.md §3 Phase 1.4"设计阶段强制项"，细节仍由 `structured-logging` skill 在 writing-plans 前定稿 + Wiki schema 注册）：

| 表 | 关键列 |
|----|--------|
| `unit_verdict` | unit_id, pair_id, sub_pattern, stage(层1-6), verdict(pass/fail), reason, metric_value, model, session_id |
| `collapse_metrics` | pair_id, text_only_acc, single_frame_acc, placebo_drop, majority_vote_hit, slot_chi2, distractor_min_dist, multiformat_consistency |
| `quarantine` | content_fingerprint, sub_pattern, quarantine_reason, round_no, ts |
| `resume_state` | slot_id/unit_id, status, config_fingerprint(断点恢复+失效检测), seq_offset |
| telemetry | 每次 LLM/VLM 调用（GovernedLLMClient 自动录，session_id 透传） |

基线指标（各门通过率、backfill_yield_by_round、judge_disagreement_by_subpattern）定义与阈值进科研 YAML + run 快照。

## 13. 错误处理

孪生构造失败（找不到真实相反事实）→该 slot 重构或走产量降级；VLM/裁判异常→slot 级隔离宽异常重出不崩整批；kimi/NLI 裁判不可用→明确报错不静默跳过（防漏歧义）；安慰剂/坍缩门模型不可用→报错。

## 14. 测试策略

- 单元：6 子模式孪生构造分流；bag-of-words 硬匹配校验；禁蕴含 NLI；逐维众数纯算法门；坍缩度量；pair 原子写/半写检测；双向 AND。
- 集成：AR 端到端（mock 四家族）→ pair 成对落盘、**六层验证全部生效（含层6 MC vs Y/N 多格式交叉的 mock 与失败路径）**、坍缩验收。
- 回归（pair 不拆）：`stratified_sample`/`build_batches`/`run_inference`/`pools.build_pools` 四处 pair 同进同出、同批、配对聚合、孤儿剔除；gate_ladder 迁移续跑不崩。
- 回归（非 AR byte-identical）：11 非 AR generate-v2 字节级不变，含 rng 隔离验证。
- Agent 类测试产出 MD（CLAUDE.md §4.6）。

## 15. 分期实现（一个设计，writing-plans 分阶段）

1. **契约地基**：QuestionUnit + ≥13 入口最小 pair 支持 + gate_ladder schema_version 迁移 + 非 AR rng 隔离 + pair 原子落盘。
2. **帧感知事实抽取层（§9）+ 构造器 + fact_sampler**。**v3 必达 = 全部 6 子模式**（用户决策：接受帧感知抽取风险）：
   - **temporal** grounding=树结构保证（零模型）；**其余 5**（cross_segment/premature/semantic_rigidity/fine_grained/evidence_gap）grounding=**§9 帧感知验证保证**（喂真实帧 + 双 VLM 交叉核 + Fact schema，见 §9）；
   - 六者共用 bag-of-words/禁蕴含/单轴/逐维众数平衡纯算法门 + 六层验证 + §9 题干模板对称 hard-fail（C8）。**帧感知抽取层是本阶段核心交付。**
   - **运行时合法性门兜底**：fine_grained（需两个真实对比时刻，可能超 5 帧/段密度→重下密帧）、evidence_gap（幻觉风险最高）各挂运行时门（帧核实+坍缩+小样本人工抽检），门不过该 pair 走 fallback（fine_grained 退 finding B 路线、evidence_gap 退保守构造）——**兜底是质量安全网，不是把子模式踢出必达**。
3. **六层验证栈**：坍缩度量（含 subtitle 输入）+ 看帧核实 + 帧错配安慰剂 + 难度探针（deepseek AgentLoop）+ kimi 独立歧义多裁判 + **多格式交叉一致（MC+Y/N）**。
4. **对抗前移 + 产量**：失败指纹去重 + quarantine + 收敛上界 + 产量降级路径 + 补构造迭代。
5. **验收面板 + 混格全链路**：反自证指标面板 + AR pair/非 AR single 端到端评分正确性验收。

> 质量闸门前移：§7 纯算法指标（逐维众数/坍缩/槽位卡方）在阶段 2 即作 CI hard-fail；难度探针在阶段 3 出早期难度信号——不等阶段 5 才验质量（对治上一版盲飞根因）。

## 16. 风险与回退

| 风险 | 回退 |
|------|------|
| kimi 网关不可用 | 实现第一步验证；退回 qwen+MiniMax 异家族双看帧裁判并标注局限 |
| **帧感知抽取风险（按 fact_type 的 failure taxonomy，C6）** | 逐类列失败路径 + 失败率进验收面板：稀疏帧漏检（顺序/变化/次数/速度类）→密帧重采/降级；双 VLM 共享盲区→错配/遮挡校准+人工 shared-error 抽样；**负事实不可证/双正解**→`negative_at_target` hard-fail（§9.1）；事实过宽跨段复用→判别性筛；ABSTAIN 吞吐→SLA 终态（§6）|
| **重复场景视频（同主体贯穿）大量事实非判别** | §9.1 判别性筛 + `negative_at_target` 剔双正解；产量由 §10 降级兜底（宁少勿歧义）。**spike 实证：连 GsYi 重复场景判别性仍 ~83%，双正解剔除率 ~17% 可控** |
| **多主体繁忙场景的唯一绑定（Codex C4，spike 未压测）** | 样本多单主体，唯一绑定风险未验证 → writing-plans/实现早期补一次多主体段实测；不唯一时按 §9.1 拆分粒度处理 |
| **fine_grained 产量/合法性**（"两时刻不同方式"未必总能找到、未必构成合法单轴编辑） | 运行时合法性门（帧核实+坍缩+人工抽检）；不过退 finding B 路线（生成候选+独立 wrongness 帧核验）；产量降级兜底 |
| **evidence_gap 虚构因果幻觉**（幻觉风险最高） | 运行时合法性门 + 保守构造 fallback；"不可确定"选项正/反题对称（防 C3 文本靶）|
| **semantic_rigidity（必达静态类）** | 编辑轴=视觉真相 vs 字幕字面（非名词替换，避 VITATECS 静态退化）；视觉真相由帧核实确证 |
| fine_grained/静态类产量低（找不到真实对比时刻） | 产量降级路径；必要时该子模式先缓 |
| 属性抽取层不准 | 抽取后 VLM 看帧复核；不准即弃该题 |
| gate_ladder 迁移破坏冷启动算法保真 | schema_version + 迁移脚本 + 2:1/gamma-EMA/Beta 按 unit 重定义并写入保真清单 |
| 混格题库拖累训练 | 阶段 5 先验评分正确性；必要时 AR pair 与非 AR 分池 |

## 17. 核心算法保真

v3 触及算法保真清单（`ARCHITECTURE.md §6`）第 5 项（信息阶梯冷启动 2:1/gamma-EMA/反泄漏）——因 gate_ladder 迁 unit_id，须逐条比对按 unit 重定义、不简化，并在 commit 标注。其余 11 项不涉及。

> **gate-unit 迁移 ADR（C4，阶段 1 强制交付，不得占位进实现）**：以下每项须有**可测试**的明确定义——① unit 的冷启动"对/错"如何从 P/Q 得出（建议 unit 错=P 或 Q 任一错）；② 2:1 错优先交错在 unit 上如何保持；③ unit `p_hat` 初值（Beta 先验参数）；④ gamma-EMA 观测来源（predictions 折叠成 unit 观测再更新，防 `update_probs` 按 qid 匹配失效致 EMA 停摆）；⑤ probe_quota 按 unit 还是按题抽；⑥ 存量 `gate_pools.json`（无 schema_version、qid 键）的处理：加 `schema_version` + 拒绝或一次性迁移脚本；⑦ 反泄漏（run_id 含 `_gate_` 过滤）不受影响的确认。

## 相关
- 范式依据：[2026-07-15-question-gen-paradigm-shift-construction-over-filtering.md]
- 前序审核：[2026-07-15-question-gen-v2-adversarial-audit.md]
- 被取代：[2026-07-15-question-gen-v2-grounded-contrastive-design.md]
- 论文：`reference/papers-distractor-gen/`（6 篇深读）
