fix(eu): Belastungsprobe folgt auch auf eine erfolgreiche Nachbelegung

Der erste Lauf mit den Gegenproben (Lage 64) zeigte, dass der Faktencheck
selbst jetzt ehrlich arbeitet. Der erste Durchgang liess 3 von 10 Behauptungen
offen, also 30 Prozent und damit genau das Niveau des Anthropic-Wegs. Vorher
waren es acht Laeufe hintereinander null.

Danach hob die Nachhak-Runde alle drei wieder auf bestaetigt, und der Lauf
endete erneut ohne eine einzige Unsicherheit.

Ursache war ein Denkfehler im Aufbau. Die zweite Runde war ein Entweder-oder.
Entweder wurde nachbelegt oder es lief die Belastungsprobe. Sobald nachbelegt
wurde, stand am Ende wieder alles auf bestaetigt und niemand prueft das nach.

Jetzt laufen beide Schritte nacheinander. Erst wird nachbelegt, danach greift
die Belastungsprobe, wenn kaum noch etwas offen ist. Sie prueft damit genau die
frisch vergebenen Bestaetigungen. Damit sie wirklich neu sucht, meldet die
Nachhak-Runde ihre Anfragen zurueck und die Belastungsprobe meidet auch diese.

Der Weg ueber die Anthropic-CLI bleibt unveraendert. 254 Pruefungen laufen ohne
Netzzugriff und ohne Kosten.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
claude-dev
2026-08-02 11:27:17 +00:00
Ursprung d948e3a7f4
Commit b00076d320
3 geänderte Dateien mit 82 neuen und 31 gelöschten Zeilen

Datei anzeigen

@@ -114,13 +114,16 @@ antworten.append(json_fakten([
antworten.append(json_fakten([
(F_TOTE, "confirmed", "laut [S1] https://example.org/a bestaetigt"),
]))
antworten.append(json_fakten([(F_TOTE, "confirmed", "haelt der Gegenprobe stand")]))
facts, usage = asyncio.run(fc.check("Ceuta", ARTS, "adhoc", "Deutsch"))
status = {f.get("claim", "")[:20]: f.get("status") for f in facts}
pruefe("A1 Erstsuche plant 7 Anfragen", aufrufe["such"][0]["max"] == 7)
pruefe("A2 Erstsuche kennt Titel und Schlagzeilen",
len(aufrufe["such"][0]["items"]) == 3, aufrufe["such"][0]["items"])
pruefe("A3 Nachhak-Runde ausgeloest",
len(aufrufe["such"]) == 2 and aufrufe["such"][1]["label"] == "Nachhak-Suche")
pruefe("A3 Nachhak-Runde und danach Belastungsprobe",
[a["label"] for a in aufrufe["such"]]
== ["Stuetzsuche", "Nachhak-Suche", "Belastungsprobe"],
[a["label"] for a in aufrufe["such"]])
pruefe("A4 Nachhak nur fuer die 2 offenen Punkte",
len(aufrufe["such"][1]["items"]) == 2, aufrufe["such"][1]["items"])
pruefe("A5 Nachhak meidet die alten Anfragen",
@@ -133,11 +136,12 @@ ev = [f["evidence"] for f in facts if f["claim"].startswith("In Ceuta")][0]
pruefe("A9 Nachrecherche mit URL in der Evidenz",
"Nachrecherche" in ev and "https://example.org/a" in ev, ev[:160])
pruefe("A10 kein Faktenverlust", len(facts) == 3, len(facts))
pruefe("A11 beide Modellaufrufe ohne Werkzeuge",
[m["tools"] for m in aufrufe["modell"]] == [None, None], aufrufe["modell"])
pruefe("A12 beide Modellaufrufe mit Belegblock",
pruefe("A11 alle Modellaufrufe ohne Werkzeuge",
[m["tools"] for m in aufrufe["modell"]] == [None, None, None], aufrufe["modell"])
pruefe("A12 alle Modellaufrufe mit Belegblock",
all(m["hat_belege"] for m in aufrufe["modell"]))
pruefe("A13 Kosten aufsummiert", round(usage.cost_usd, 3) == 0.12, usage.cost_usd)
pruefe("A13 Kosten aller drei Runden aufsummiert",
round(usage.cost_usd, 3) == 0.18, usage.cost_usd)
print("\nB) Ist alles belegt, folgt keine Nachbelegung sondern eine Belastungsprobe")
neu()
@@ -199,7 +203,10 @@ pruefe("E1 inkrementell nutzt die Belegsuche", len(aufrufe["such"]) >= 1, aufruf
pruefe("E2 alte offene Punkte fliessen in die Suche",
any("Alter offener Punkt" in i for i in aufrufe["such"][0]["items"]),
aufrufe["such"][0]["items"])
pruefe("E3 inkrementell hakt nach", len(aufrufe["such"]) == 2, len(aufrufe["such"]))
pruefe("E3 inkrementell hakt nach und prueft danach",
[a["label"] for a in aufrufe["such"]]
== ["Stuetzsuche", "Nachhak-Suche", "Belastungsprobe"],
[a["label"] for a in aufrufe["such"]])
pruefe("E4 inkrementelle Hochstufung greift",
any(f["claim"].startswith("Sanchez") and f["status"] == "confirmed" for f in facts_e),
[(f["claim"][:25], f["status"]) for f in facts_e])
@@ -246,8 +253,10 @@ facts_h, _ = asyncio.run(fc._eu_pruefen(
))
pruefe("H1 Gruppe plant die kleinere Suchmenge",
aufrufe["such"][0]["max"] == EU_VERIFY_GROUP_QUERIES, aufrufe["such"][0]["max"])
pruefe("H2 Gruppe hakt mit kleinerer Menge nach",
len(aufrufe["such"]) == 2 and aufrufe["such"][1]["max"] == EU_VERIFY_GROUP_FOLLOWUP_QUERIES,
pruefe("H2 Gruppe nutzt die kleinere Menge auch in den Folgerunden",
[a["max"] for a in aufrufe["such"]]
== [EU_VERIFY_GROUP_QUERIES, EU_VERIFY_GROUP_FOLLOWUP_QUERIES,
EU_VERIFY_GROUP_FOLLOWUP_QUERIES],
[a["max"] for a in aufrufe["such"]])
pruefe("H3 Gruppe stuft belegten Fakt hoch",
any(f["claim"].startswith("In Ceuta") and f["status"] == "confirmed" for f in facts_h),
@@ -345,6 +354,35 @@ pruefe("M2 keine Hochstufung durch die Belastungsprobe",
status_m.get(F_SANCHEZ[:20]) == "confirmed", status_m)
pruefe("M3 offener Punkt bleibt offen", status_m.get(F_TOTE[:20]) == "unconfirmed", status_m)
print("\nN1) Nach der Nachbelegung folgt die Belastungsprobe")
neu()
antworten.append(json_fakten([
(F_TOTE, "unconfirmed", "unklar"),
(F_SANCHEZ, "unconfirmed", "unklar"),
(F_GRENZE, "confirmed", "belegt"),
]))
# Die Nachbelegung hebt beide offenen Punkte hoch, danach ist nichts mehr offen.
antworten.append(json_fakten([
(F_TOTE, "confirmed", "[S1] https://example.org/a belegt es"),
(F_SANCHEZ, "confirmed", "[S1] https://example.org/a belegt es"),
]))
# Die Belastungsprobe nimmt eine der Bestaetigungen wieder zurueck.
antworten.append(json_fakten([
(F_TOTE, "unconfirmed", "[S1] nennt nur eine Schaetzung"),
]))
facts_n1, _ = asyncio.run(fc.check("Ceuta", ARTS, "adhoc", "Deutsch"))
status_n1 = {f["claim"][:20]: f["status"] for f in facts_n1}
pruefe("N1a beide Runden laufen nacheinander",
[a["label"] for a in aufrufe["such"]]
== ["Stuetzsuche", "Nachhak-Suche", "Belastungsprobe"],
[a["label"] for a in aufrufe["such"]])
pruefe("N1b Belastungsprobe meidet auch die Anfragen der Nachbelegung",
"Nachhak-Suche-q1" in aufrufe["such"][2]["avoid"], aufrufe["such"][2]["avoid"])
pruefe("N1c nicht haltbare Nachbelegung wird zurueckgenommen",
status_n1.get(F_TOTE[:20]) == "unconfirmed", status_n1)
pruefe("N1d haltbare Nachbelegung bleibt",
status_n1.get(F_SANCHEZ[:20]) == "confirmed", status_n1)
print("\nN) Widerspruch in der Nachhak-Runde stuft zurueck")
neu()
antworten.append(json_fakten([