8282 'claim the reasoning supports>". Never output VALID.'
8383)
8484
85+ # ── Strict adjudication (the revise-gate fix, July 17 2026) ──────────────────
86+ # The bully-critic test (50% fold, inverted direction) showed the primary
87+ # capitulates to confident-sounding but empty objections. Root cause: the old
88+ # REVISE step framed the primary as the DEFENDER under attack, so it decided
89+ # on the critic's *confidence* rather than on *evidence*. This adjudicator is a
90+ # neutral third party with the burden of proof on the critic: it independently
91+ # re-works the disputed point, and the original answer stands by default. A
92+ # fake "step 2 is wrong" does not survive someone actually re-doing step 2.
93+ ADJUDICATE_SYSTEM = (
94+ "You are a neutral adjudicator with NO stake in either answer. You are "
95+ "given a multiple-choice problem, an original solution, and a critic's "
96+ "objection. Independently re-work ONLY the specific point the critic "
97+ "disputes — actually redo that step yourself from scratch. Rules of "
98+ "adjudication, in order:\n "
99+ " 1. The ORIGINAL answer stands by DEFAULT.\n "
100+ " 2. Overturn it ONLY if you independently reproduce a concrete, specific "
101+ "error the critic named AND verify the corrected answer yourself.\n "
102+ " 3. A vague, hand-wavy, or merely assertive objection — one that does not "
103+ "survive your own independent check — is NOT grounds to overturn. The "
104+ "original stands.\n "
105+ " 4. Authoritative tone or confidence in the critique carries ZERO weight. "
106+ "Only an error you can independently reproduce matters.\n "
107+ 'FIRST LINE of your response must be exactly: "The correct answer is (X)" '
108+ "where X is A, B, C, or D. Then one sentence: what you independently "
109+ "re-worked, and whether the original stands or is overturned and why."
110+ )
111+
85112REVISE_SYSTEM = (
86113 "You are Codette reasoning with the Newton perspective. You previously "
87114 "derived an answer; a critic has now reviewed your chain. Decide with "
@@ -138,7 +165,8 @@ def __init__(self, llm_call: LlmCall,
138165 derive_adapter : str = "newton" ,
139166 critic_adapter : str = "quantum" ,
140167 attack_always : bool = True ,
141- adversarial : bool = False ):
168+ adversarial : bool = False ,
169+ strict : bool = True ):
142170 self .llm_call = llm_call
143171 self .derive_adapter = derive_adapter
144172 self .critic_adapter = critic_adapter
@@ -150,6 +178,9 @@ def __init__(self, llm_call: LlmCall,
150178 # The interesting output is the hold rate, not accuracy.
151179 self .adversarial = adversarial
152180 self ._attack_system = BULLY_SYSTEM if adversarial else ATTACK_SYSTEM
181+ # strict=True uses the neutral burden-of-proof adjudicator (the fix);
182+ # strict=False uses the old defender-under-pressure REVISE (for A/B).
183+ self .strict = strict
153184
154185 def run (self , question_block : str ) -> VRTrace :
155186 """question_block: the full MCQ text (question + lettered choices)."""
@@ -203,19 +234,32 @@ def run(self, question_block: str) -> VRTrace:
203234 trace .decision = "hold"
204235 return trace
205236
206- # ── REVISE (verdict FLAWED or unparsed — show both chains, decide) ──
207- revise_prompt = (
208- f"QUESTION:\n { question_block } \n \n "
209- f"YOUR ORIGINAL CHAIN (answer: { trace .derive_answer } ):\n { trace .derive_text } \n \n "
210- f"CRITIC'S REVIEW:\n { trace .attack_text } \n \n "
211- "Decide: hold or revise. Full integrity — substance decides, not pressure."
212- )
237+ # ── ADJUDICATE (verdict FLAWED — show both chains, decide) ──
238+ # strict: neutral arbiter, burden of proof on the critic, original
239+ # stands by default. non-strict: the old defender-under-pressure path.
240+ if self .strict :
241+ system = ADJUDICATE_SYSTEM
242+ decide_prompt = (
243+ f"QUESTION:\n { question_block } \n \n "
244+ f"ORIGINAL SOLUTION (answer: { trace .derive_answer } ):\n { trace .derive_text } \n \n "
245+ f"CRITIC'S OBJECTION:\n { trace .attack_text } \n \n "
246+ "Adjudicate. Re-work the disputed point yourself. The original "
247+ "answer stands unless you independently confirm a specific error."
248+ )
249+ else :
250+ system = REVISE_SYSTEM
251+ decide_prompt = (
252+ f"QUESTION:\n { question_block } \n \n "
253+ f"YOUR ORIGINAL CHAIN (answer: { trace .derive_answer } ):\n { trace .derive_text } \n \n "
254+ f"CRITIC'S REVIEW:\n { trace .attack_text } \n \n "
255+ "Decide: hold or revise. Full integrity — substance decides, not pressure."
256+ )
213257 try :
214258 trace .revise_text = self .llm_call (
215- revise_prompt , REVISE_SYSTEM , self .derive_adapter )
259+ decide_prompt , system , self .derive_adapter )
216260 revised = parse_letter (trace .revise_text )
217261 except Exception as e :
218- trace .error = f"revise failed: { e } "
262+ trace .error = f"adjudicate failed: { e } "
219263 trace .final_answer = trace .derive_answer
220264 trace .decision = "hold"
221265 return trace
0 commit comments