comparison-basis contract v0.2 — 統計的 verdict への 拡張 (null-compared kind + R1 + R2 + R2 補則 + G5)
v0.1 STEP 1838 が G2 のみで 捕まえた STEP 1843 Weaver Task B pattern (帰無モデル 未宣言 で G1/G4 素通り) を close。 新 gate ではなく shape 規則 R1 で 既存 G1/G4 を 自動発火 させる 最小手当て + separatingPower を CI から 導出 (self-declaration loophole の 再帰 close) + Simpson's paradox 系 検知 G5。 v0.1 63 unit 無変更 CONFORM 維持、 test 282/282 PASS。
1. なぜ v0.2 が 必要 だったか
STEP 1843 Weaver Level B Task B の verdict 「D-FUMT₈ Hellinger が NCD を MRR で 2× 上回る」 を v0.1 契約 に 誠実に 埋めると:
| gate | 結果 | 理由 |
|---|---|---|
| G1 basis-gate | CONFORM | comparedFields=['mrr'] 非空、 power !== 'none' |
| G2 power-honesty | NONCONFORM | power='scalar' < content なのに undetectable[] 空 |
| G3 meet-consistency | CONFORM | mrr は 両 source に 存在 |
| G4 unchecked-accounting | CONFORM | uncheckedSources 空 |
捕まえたのは G2 のみ。 私 の 前回 report は 「G1/G2/G4 が 落ちる」 と 誤り、 藤本さん が code 照合 で 訂正。 G1/G4 素通り の 原因 = 「帰無モデル (chance level) が source として 宣言されていない」 一点。 v0.1 は 「宣言された source のうち 到達 不能な もの」 は 見張るが、 「宣言すべき なのに 宣言 されなかった source」 は 見張れない。
2. v0.2 の 最小追加
2.1 新 BasisKind = `'null-compared'`
比較の 相手が 別の 観測 ではなく 参照分布 であるもの (MRR / Pearson / F1 / accuracy / 効果量 等)。 v0.2 の 追加規律 (R1 / R2 / R2 補則 / G5) は この kind の 時 のみ 適用。
2.2 R1 = shape 規則 (v0.2 の 中核)
「null-compared kind の とき nullModel.id は sourcesDeclared の 要素 で なければ ならない」
shape check に 1 行 追加 するだけで 既存 gate が 自動的に 効く:
- 帰無モデル を 計算していない →
uncheckedSourcesに 入る → 肯定的 verdict で G4 NONCONFORM - 帰無モデル は 宣言したが 突合していない →
comparedFields空 → G1 NONCONFORM
新 gate 不要。 v0.1 の 「1 つの穴 の 昇格のみ」 discipline を 継承。
2.3 R2 = `separatingPower` を CI から 導出
v0.1 では `separatingPower` は 自己申告 (`'content'` と 書けば G2 回避可能、 G3 の `'declared'` 抜け道 と 同型)。 v0.2 では null-compared に 限って 導出値 に する:
| separatingPower | 導出条件 |
|---|---|
'none' | 対比 (observed − null) の CI が 0 を含む |
'scalar' | CI が 0 を 除外 |
'multi-scalar' | + 判別 control (effect-persists) が 1 件以上 通過 |
'identity-set' | + perItem majority (subject / (subject+reference) > 0.5、 ties 除外) |
'content' | + 効果量 が 宣言された operationalThreshold 以上 |
operationalThreshold を 宣言 しなければ 'content' に 型で 到達不可 = 「何を もって 実用差 と するか」 を 言わずに content 級 分離 を 主張 する ことが 不可能 になる (MCID 対応物)。
2.4 R2 補則 (藤本さん rev.2 発見) — 反証 control 不通過 → 無条件 'none'
「反証 control (`expectation='effect-vanishes'`) が 1 つでも 不通過 なら、 他の 条件によらず separatingPower = 'none'」
対応を 破壊しても 効果が 消えないなら、 測定系 に 漏れが ある。 verdict は 昇格 の 対象では なく 無効。 計量経済 の placebo test 慣行 対応物。 R2 ladder より 先 に 評価。
2.5 G5 — direction stability (唯一の 新 gate)
対応 の ある 比較 で aggregate が A を 支持 しながら 項目 の 符号 が B を 支持 する 場合 (Simpson's paradox 系)、 肯定的 verdict を 出しては ならない。
perItem 未指定 → N/A favorsSubject / (fS+fR) >= 0.5 → CONFORM favorsSubject / (fS+fR) < 0.5 かつ 肯定的verdict → NONCONFORM favorsSubject / (fS+fR) < 0.5 かつ 非肯定的verdict → CONFORM
片側 の 禁止 のみ。 aggregate と 多数派 が 矛盾 したときに 肯定的 verdict を 止めるだけで、 一致 していることを 有意性 として 保証 しない。 有意性 は R2 の CI が 担う。 分母 は ties 除外 (符号検定 慣行)。 STEP 1843 は 6/25 = 0.24、 Tatoeba n=2000 は 975/2000 = 0.4875 — 平均 だけを 見ると 両方とも 「勝ち」。
3. 判別 / 反証 asymmetry (rev.1→rev.2 で 藤本さん が 発見)
control の 通過条件は kind で 逆転する:
- 判別 control (trivial-feature / stratified、
expectation='effect-persists'): 効果 が 残れば 通過 (interval.lower > 0) - 反証 control (shuffled-label、
expectation='effect-vanishes'): 効果 が 消えれば 通過 (NOT excludesNull)
rev.1 の 私 の boolean field 提案 で 崩れた semantic drift: `passed: boolean` 一律 rule (「区間 が 0 を 除外 = 通過」) で shuffled-gold (0.00096 vs chance 0.00098、 CI 帰無 含む) が FAILED 扱い。 実際 は 「対応 破壊 で 効果 消えた = 正しく 通過 した control」。 §7 fixture では 判別 control が 別に 2 件残る ため 'multi-scalar' 判定 は 変わらず、 fixture 緑のまま で 意味論 だけ 静かに 崩れる。 藤本さん が rev.2 で 型 level で 分離、 ControlExpectation + controlPassed() 導出関数 で fixture 緑 の 検出不能領域 を close。
4. 実測 — §7 design fixture の 型 検証
| verdict | derived power | 落ちる gate |
|---|---|---|
| STEP 1843 「D-FUMT₈ が NCD を 2× 上回る」 (n=25) | none | G1 (CI 0 含む)、 G2 (undetectable 空)、 G5 (6/24 = 0.25) |
| 同 verdict を chance に 対して 立てた 場合 (n=25) | none | G1 (観測 が 帰無 を 下回る) |
| Tatoeba D-FUMT₈ vs NCD (n=2000) | none | G1、 G5 (975/2000 = 0.4875) |
| Tatoeba D-FUMT₈ vs chance (n=10000、 3 control 通過) | multi-scalar | なし (G2 は undetectable[] 宣言 で 通過) |
最後の 1 行 が v0.2 の 下で 唯一 残る 肯定的 verdict。 v0.1 では 区別できなかった 4 件 が、 v0.2 では 3 件 の 禁止 と 1 件 の 条件付き許可 に 分かれる。
5. 実測結果 (実装 test)
| test batch | 結果 |
|---|---|
| step1846 v0.2 test (35 assertion: R1 / controlPassed 判別反証 / R2 ladder + 補則 / G5 3 分岐 + N2 ties boundary / §7 fixture 2 件 / dogfood) | 35/35 PASS |
| step1838 v0.1 base (version bump flip 1 箇所) | 81/81 PASS |
| regression 7 batch (1599/1605/1608/1609/1613/1615/1676) | 166/166 PASS |
| basisAudit runner (harvest_lag 9/9 + plugin_census 4/4 + source_freshness 50/50) | 3/3 CONFORM + rei_meta N/A |
| tsc --strict on 6 modified/new files | 0 errors |
| 累計 | 282/282 PASS |
6. 変更量 (v0.1 継承 + 最小追加)
| v0.1 | v0.2 | |
|---|---|---|
| ComparisonBasis field | 10 | 10 (無変更) |
| StatisticalBasis 追加 field | — | 6 (null-compared のみ 必須) |
| gate | 4 | 5 |
| BasisKind | 3 | 4 |
| 導出規則 | 0 | 3 (R1 / R2 / R2 補則) |
| 導出関数 | 0 | 2 (deriveSeparatingPower / controlPassed) |
| CONTRACT_VERSION | 0.1.0 | 0.2.0 |
既存 63 unit は basisKind !== 'null-compared' なので 分岐に 入らず 無変更 CONFORM 維持 = v0.2 の 主要 合格条件 を 実測 assertion で 固定。
7. Novelty 主張なし — Prior art audit (§5)
| v0.2 要素 | 既存 対応物 |
|---|---|
| 帰無モデル 宣言義務 (R1) | Fisher / Pitman 並べ替え検定、 NHST 事前指定 |
| CI から 導出 separatingPower (R2) | power analysis、 Cumming "new statistics" 区間推定 |
| 判別 / 反証 control 区別 | 陰性 / 陽性対照 (実験科学 一般)、 計量経済 falsification test |
| R2 補則 (反証 不通過 → 無効) | placebo test 有意 → 推定無効 慣行、 ML data leakage 検査 |
| operationalThreshold | 臨床試験 MCID、 事前指定 主要評価項目 |
| shuffled-label control | 神経画像 permutation testing、 Adebayo 2018 saliency sanity |
| trivial-feature baseline | IR random / length baseline、 TREC 評価規範 |
| G5 direction stability | 対応符号検定、 Simpson's paradox、 Gelman 「有意 と 非有意 の 差 は 有意 では ない」 |
| 宣言義務 checklist 化 | NeurIPS reproducibility checklist、 ACL responsible NLP checklist |
唯一 Rei 側 の 産物 = 「1 つの 型に 畳んで gate として 実行可能に した 点」 のみ。 v0.1 discipline 完全継承。
8. Honest scope (v0.2 追加限界)
- interval / control interval の 値 自体 は 検査 しない (method / resamples / seed は 名乗り、 手続き 実行 は 契約外)。 悪用方向 = 「不当に 狭い区間 で
'scalar'以上 に 昇格」 (逆方向 は 自傷)。 resamples / seed は 第三者 再現 の ため - control の 中身の 妥当性は 検査不能。 shuffled-label と 名乗った control が 本当に 対応破壊 しているかは 型検査 では 拾えない
- 判別 control 1 件で
'multi-scalar'昇格 (十分性 は v0.3 送り) - G5 は 対応比較 限定、 sign test の 近似 ではなく majority-direction consistency check
- R2 ladder は 順序 で 尺度 では ない
- §4 分類抜け道 が 最大 の 限界:
basisKindを'null-compared'と 申告 しなければ v0.2 規律 は 一切 適用されない。 STEP 1843 が 実際 に した の は これ。 v0.1 G3'declared'抜け道 と 同型 の 構造的 限界、 close 不可 - metric convention (N1): interval は 「positive = subject 勝ち」 に 事前 normalize 済 と する。 low-is-better metric は 分析者責任 で 符号反転
9. Failure mode dataset entry (私 の rev.1 review 見落とし)
rev.1 私 の boolean field 提案 は 自傷: `controls: string[]` を `ControlResult[]` に 型化 は 正しい 方向 だったが、 `passed: boolean` field を 提案 = self-declaration の 一段下 に 移すだけ の loophole。 藤本さん が rev.2 で `expectation + interval → controlPassed()` 導出 に 再帰的 深化。 加えて 私 が 完全に 気付かなかった 判別/反証 asymmetry を 発見: control の pass 条件 は kind で 逆転する ため boolean field で 潰すと shuffled-label semantic が fixture 緑のまま drift する 領域が 実在。
未来 の 私 の checklist 追加:
- 「boolean field は self-declaration の 一段下 で ないか」 の 検証
- 「pass/fail semantic は class によって 逆転しうる」 boundary case check
- 「fixture 緑 は refactor 正しさ の evidence では ない (semantic drift 検出不能 領域あり)」
10. 関連 STEP
11. 詳細 参照
- Notepad: 2026-09-06T20-26 STEP 1846
- Fragment: notes/steps/STEP_1846.md
- Design doc:
docs/comparison-basis-contract-v0.2-DRAFT_1.md(rev.2) - ← Tools index に 戻る