update
This commit is contained in:
@@ -621,6 +621,10 @@ def test_reference_strip_and_is_reference():
|
||||
== "N P via nicht-deterministische Turingmaschine"
|
||||
assert strip("Bemerkung 7.22") == ""
|
||||
assert strip("Vertex Cover") == "Vertex Cover" # kein Katalog-Gerüst → unverändert
|
||||
# Zuschreibungs-Klammer vor ':' gehört zum Katalog-Gerüst (aak: "(Lawler 1976): …" überlebte)
|
||||
assert strip("Satz 7.12 (Lawler 1976): Minimum-Weight Perfect Matching") \
|
||||
== "Minimum-Weight Perfect Matching"
|
||||
assert strip("(a1=1)-SubsetSum Problem") == "(a1=1)-SubsetSum Problem" # Mathe-Klammer bleibt
|
||||
assert isref("Bemerkung 7.22") and isref("Satz 7.18") and isref("Korollar 6.18")
|
||||
assert isref("Bedingung (**)")
|
||||
assert not isref("Satz 7.13 (Christofides)") # hat Konzept → keine Referenz
|
||||
@@ -1577,3 +1581,62 @@ def test_gruppierung_prompt_rendert_zielband(tmp_path):
|
||||
p = _prompt("Blocks-Gruppierung", topic="t", candidates="x", list="1. a",
|
||||
out_path=tmp_path / "g.json", theme_lo=4, theme_hi=8, n_items=9)
|
||||
assert "~4–8 themes" in p and "(9 items)" in p
|
||||
|
||||
|
||||
async def test_attach_nachzuegler_wird_sub_statt_zwergblock(testdb, tmp_path, monkeypatch):
|
||||
"""Nachzügler-Atom (Supplement-/Lücken-Welle) mit passendem fertigen Block →
|
||||
wird dessen Sub (Bottom-up), Karte → grouped/attach, Board-2-Karte → generate.
|
||||
Ohne Zuordnung bleibt das Atom standalone (Erstwelle: keine done_blocks → no-op)."""
|
||||
db = testdb
|
||||
ctx = GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False)
|
||||
flow = _mk_flow(tmp_path)
|
||||
# fertiger Block mit Board-2-Karte
|
||||
await db.kanban_upsert_card(TOPIC, B, "b1", "block", "done_block",
|
||||
{"title": "Turingmaschinen", "description": "Modelle und Akzeptanz",
|
||||
"mirrored_norm": "turingmaschinen", "children": ["Palindrom-TM"]})
|
||||
await db.kanban_upsert_card(TOPIC, "artefacts", "turingmaschinen", "ablock", "done_artefact",
|
||||
{"title": "Turingmaschinen"})
|
||||
rows = [{"card_id": "n1", "payload": {"title": "Halteproblem", "description": "hält die TM?"},
|
||||
"title": "Halteproblem", "description": "hält die TM?", "title_norm": "halteproblem"}]
|
||||
await db.kanban_upsert_card(TOPIC, B, "n1", "block", "grouping", rows[0]["payload"])
|
||||
|
||||
async def fake_slot(ctx2, label, *, key, prompt, role, capabilities, payload, timeout):
|
||||
assert "-gruppierung-attach-" in key and "Turingmaschinen" in prompt
|
||||
m = re.search(r"(/\S+\.json)", prompt) # files-Agent: out_path aus dem Prompt schreiben
|
||||
from pathlib import Path
|
||||
Path(m.group(1)).write_text('{"additions": [{"umbrella": 0, "members": [1]}]}', encoding="utf-8")
|
||||
return bi.OK, payload((0, "", ""))
|
||||
|
||||
monkeypatch.setattr(bi, "run_single_slot", fake_slot)
|
||||
attached = await bi._attach_nachzuegler(ctx, flow, rows)
|
||||
assert attached == {"n1"}
|
||||
subs = {r["sub_norm"] for r in await db.list_subblocks(TOPIC, "turingmaschinen")}
|
||||
assert "halteproblem" in subs
|
||||
card = await db.kanban_get_card(TOPIC, B, "n1")
|
||||
assert card["stage"] == "grouped" and card["payload"]["reason"] == "attach"
|
||||
assert card["payload"]["merged_into"] == "Turingmaschinen"
|
||||
b2 = await db.kanban_get_card(TOPIC, "artefacts", "turingmaschinen")
|
||||
assert b2["stage"] == "generate" # Re-Anreicherung des neuen Subs
|
||||
block = await db.kanban_get_card(TOPIC, B, "b1")
|
||||
assert "Halteproblem" in block["payload"]["children"]
|
||||
|
||||
|
||||
async def test_attach_nachzuegler_ohne_zuordnung_bleibt_standalone(testdb, tmp_path, monkeypatch):
|
||||
db = testdb
|
||||
ctx = GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False)
|
||||
flow = _mk_flow(tmp_path)
|
||||
await db.kanban_upsert_card(TOPIC, B, "b1", "block", "done_block",
|
||||
{"title": "Turingmaschinen", "mirrored_norm": "turingmaschinen"})
|
||||
rows = [{"card_id": "n2", "payload": {"title": "Ganz neues Konzept"},
|
||||
"title": "Ganz neues Konzept", "description": "", "title_norm": "ganz neues konzept"}]
|
||||
await db.kanban_upsert_card(TOPIC, B, "n2", "block", "grouping", rows[0]["payload"])
|
||||
|
||||
async def fake_slot(ctx2, label, **kw):
|
||||
m = re.search(r"(/\S+\.json)", kw["prompt"])
|
||||
from pathlib import Path
|
||||
Path(m.group(1)).write_text('{"additions": []}', encoding="utf-8")
|
||||
return bi.OK, kw["payload"]((0, "", ""))
|
||||
|
||||
monkeypatch.setattr(bi, "run_single_slot", fake_slot)
|
||||
assert await bi._attach_nachzuegler(ctx, flow, rows) == set()
|
||||
assert (await db.kanban_get_card(TOPIC, B, "n2"))["stage"] == "grouping"
|
||||
|
||||
@@ -103,3 +103,13 @@ def test_fidelity_guard_prefers_faithful_plaintext():
|
||||
assert blx._pick_conversion(None, plain)[1] == "pdftotext"
|
||||
assert blx._pick_conversion(md_ok, None)[1] == "pymupdf4llm"
|
||||
assert blx._pick_conversion(None, None) is None
|
||||
|
||||
|
||||
def test_entzerre_hyphen_space():
|
||||
"""Regel C: GROSSLAUF + Leerzeichen vor Bindestrich-Kompositum („NP -vollständig",
|
||||
Makro-Spacing) wird gemerged; echter Gedankenstrich („X - y") bleibt."""
|
||||
assert blx._entzerre_pdf_woerter("die NP -vollständigkeit gilt") == "die NP-vollständigkeit gilt"
|
||||
assert blx._entzerre_pdf_woerter("Begriffe der NP -schwere und NP -vollständigkeit") == \
|
||||
"Begriffe der NP-schwere und NP-vollständigkeit"
|
||||
assert blx._entzerre_pdf_woerter("Term X - y bleibt") == "Term X - y bleibt"
|
||||
assert blx._entzerre_pdf_woerter("Liste:\n-punkt eins") == "Liste:\n-punkt eins"
|
||||
|
||||
@@ -333,3 +333,15 @@ def test_offene_luecken_filtert_freispruch_und_nein():
|
||||
"konzept_luecken": ["Satz von Foo"]}
|
||||
lk, kl = qa.offene_luecken(rep)
|
||||
assert [x["vorschau"] for x in lk] == ["a"] and kl == ["Satz von Foo"]
|
||||
|
||||
|
||||
def test_named_results_ueberspringt_umbrochene_saetze():
|
||||
"""Doppelpunkt-Fang, der am Zeilenumbruch endet und klein weiterläuft, ist ein
|
||||
umbrochener SATZ, kein Konzeptname — solche Phantom-Lücken kann kein Block ankern.
|
||||
Echte Namen (auch \\n-terminiert mit großer Folgezeile) bleiben."""
|
||||
text = ("Konsequenz von Satz 6.16: Wenn ein NP-vollständiges Entscheidungsproblem in P\n"
|
||||
"liegt, dann sind alle NP Entscheidungsprobleme in P.\n\n"
|
||||
"Satz 7.13 (Christofides). Beweis folgt.\n"
|
||||
"Satz 6.24: Cook-Levin.\n"
|
||||
"Satz 9.1: Vier-Farben-Satz\nDer Beweis nutzt Computer.\n")
|
||||
assert sorted(qa._named_results({"f": text})) == ["Christofides", "Cook-Levin", "Vier-Farben-Satz"]
|
||||
|
||||
Reference in New Issue
Block a user