STEP 1647 — LLM-as-judge comparator v0.1

STEP 1647 2026-09-01 test 50/50 PASS STEP 1631 regression 48/48 clean stub adapter で fan noise ゼロ
rei-aios · invariance-checker (STEP 1631) の pluggable async comparator layer

1. 契機

STEP 1637 v0.1 empirical で判明した pain point: numericMatch は 「最後の整数抽出 + tolerance 比較」 の 表層 comparator。 モデルが 答えを 冒頭に書いたり 途中で 分岐 output を出すと 抽出誤り = FALSE 側の artifact に 偏る。 chat-Claude 2026-08-31 「self-referential ゆえ discipline 必要 + 陰性対照必須」 warning に応答して primitive 側で 2 discipline を設計に埋め込む。

2. 骨格

AsyncAnswerEquivalence   (Promise-returning cousin of AnswerEquivalence)
   ↑
llmJudgeComparator(adapter, opts)
   ↑
JudgeAdapter    (pluggable HTTP client)
   ├── stubJudge*             deterministic, 6 factory (test/fan-zero)
   ├── ollamaJudgeAdapter     local, no cloud budget
   └── anthropicJudgeAdapter  cloud, requires ANTHROPIC_API_KEY

multiVoteJudge(base, votes, minAgreement) → self-consistency wrapper
singleInvarianceVerdictAsync / statisticalInvarianceVerdictAsync
   = async cousins of sync primitives (I1-I5 decision table identical)

3. 決定表 (judge → EquivalenceOutcome)

DECISIONmapping (default)rationale
EQUIVALENT{ equivalent: true, confidence: 1 }judge 確信、 invariance 保存
DIFFERENT{ equivalent: false, confidence: 1 }judge 確信、 invariance 破壊
ABSTAIN{ equivalent: null, confidence: 0 }NEITHER 側で吸収 (default)
PARSE_ERROR{ equivalent: null, confidence: 0 }judge の 出力 format 崩れ = NEITHER

abstainAsNeither: false オプションで ABSTAIN → false 転換 (safer 側)。

4. Judge prompt (canonical、 module-level 固定)

You are judging whether two answers to the same math problem are numerically equivalent.

--- Answer A ---
<text A>

--- Answer B ---
<text B>

Rules:
- Focus ONLY on the final numeric answer, not the working steps.
- Different phrasings of the same number are equivalent (e.g., "200", "two hundred", "\boxed{200}", "answer: 200").
- If either answer is missing / incomplete / not-a-number, output ABSTAIN.
- Do not solve the problem. Only compare the final answers as given.

Respond in this EXACT format, one field per line, no extra text:
DECISION: EQUIVALENT | DIFFERENT | ABSTAIN
REASON: <one short sentence>
NUMERIC_A: <extracted number or NULL>
NUMERIC_B: <extracted number or NULL>

JUDGE_PROMPT_ID = 'invariance-checker/judge/v1' — audit trail invariant。 caller custom prompt は 別 promptId 宣言責任 (v0.2 defer)。

5. 順序原則 (定数化禁止)

6. 陰性対照 (caller 責任)

judge 妥当性は 単独 test では 立証できない (self-referential trap)。 caller が empirical loop で以下を実行:

  1. 恒等 pair (答え同一) → 全 EQUIVALENT 期待
  2. 明確 mismatch pair (無関係な別問題答え) → 全 DIFFERENT 期待
  3. abstain pair (片方 empty / non-numeric) → 全 ABSTAIN 期待

3 種の 期待通り 出れば judge は 少なくとも 明白 3 case で 動作。 微妙 中間 case は STEP 1645 destructive transforms + STEP 1637 corpus で 4 象限 confusion matrix 経由で 測定。

7. Test

npm run test:step164750/50 PASS (9 section):

  1. JUDGE_PROMPT_ID 安定 + prompt shape (5 assert)
  2. parseJudgeResponse 全 4 decision + numeric 抽出 (7)
  3. Stub adapters 6 factory (7)
  4. llmJudgeComparator (8: absence / EQ / DIFF / ABSTAIN toggle / err / PARSE_ERROR)
  5. multiVoteJudge 過半数 + 満場一致 discipline (6)
  6. promoteSync (2)
  7. singleInvarianceVerdictAsync I1-I5 mirror (4)
  8. statisticalInvarianceVerdictAsync (5)
  9. Negative-control self-test with numeric-simulated stub (3)

STEP 1631 primitive regression: 48/48 clean (sync path 影響なし)。

8. 反証条件 (Popper self-application)

  1. Stub always-equivalent adapter → equivalent=false を返す
  2. Stub always-different adapter → equivalent=true を返す
  3. multiVoteJudge(votes=3, minAgreement=3) に 2-1 split → null 以外
  4. abstainAsNeither: false で ABSTAIN → null (should → false)
  5. promoteSync(exactMatch()) が sync exactMatch と 異なる outcome

全 5 条件、 test Section 3-6 で 発火せず。 現時点で 反証なし。

9. Honest scope

  • v0.1 は infrastructure。 実 empirical (実 judge model で 陰性対照 3-pattern を pass するか) は 別 STEP
  • Judge model の 自動選定 なし — caller が adapter 明示指定 (self-reference 予防のため)
  • Confidence calibration の 数式化 なし — judge raw output の confidence は 使わない (raw 出力 保存のみ)
  • 意味論的等価 の 数学的定義 なし — numerical-answer 等価 に focus、 wider semantic invariance は 別 STEP
  • 陰性対照 の 自動混入 なし — STEP 1645 destructive transforms 経由で caller 責任
  • Judge の bias 監視 primitive なし — 「always-equivalent pathology」 の 早期検知は v0.2 candidate

10. Trade-off

11. v0.2+ candidate

関連

STEP 1647 · 2026-09-01 · rei-aios home