This commit is contained in:
team3
2026-07-08 18:55:36 +02:00
parent 224ba1ed4f
commit 9a6ab0937b
15 changed files with 172 additions and 55 deletions

View File

@@ -270,3 +270,15 @@ async def test_ram_gate_cancelled_scope(ram_gate):
def test_meminfo_reads_proc():
mem = agents._meminfo()
assert mem is not None and 0 < mem[0] <= mem[1] # Linux-Testumgebung
def test_agent_ebene_klassifiziert_board():
"""Board-2-Marker (art-/sb-/crossblock/outline) → artefacts; alles andere → inventory."""
T = "shopware"
for key in (f"blocks-{T}-research-a1", f"blocks-{T}-pair-x", f"blocks-{T}-naming-y",
f"blocks-{T}-gruppierung-h-cTOP", f"blocks-{T}-dedup-z"):
assert agents.agent_ebene(key) == "inventory", key
for key in (f"blocks-{T}-alpha-sb-enrich-h", f"blocks-{T}-alpha-sb-verify-h-j1",
f"blocks-{T}-alpha-art-gen-h-t1", f"blocks-{T}-alpha-art-check-h",
f"blocks-{T}-sub-crossblock-h-j1", f"blocks-{T}-outline-judge"):
assert agents.agent_ebene(key) == "artefacts", key

View File

@@ -1237,7 +1237,7 @@ async def test_reset_generate_behaelt_subs_loescht_artefakte(testdb, tmp_path):
(arbeit / "ab-alpha").mkdir(parents=True)
(arbeit / "ab-alpha" / "facts.json").write_text("{}", encoding="utf-8")
files = {"arbeit": arbeit}
for k in ("sidecar", "facts", "sub_roh", "question_pattern", "artefakte"):
for k in ("sidecar", "facts", "sub_roh", "question_pattern", "artefakte", "outline"):
files[k] = tmp_path / f"{k}.json"
files[k].write_text("{}", encoding="utf-8")
moved = await bi.reset_board_from_stage(TOPIC, "artefacts", "generate", files)
@@ -1245,7 +1245,7 @@ async def test_reset_generate_behaelt_subs_loescht_artefakte(testdb, tmp_path):
assert len(await db.list_subblocks(TOPIC)) == 1 # Sub bleibt (Board-1-Eigentum)
assert not await db.list_question_pattern(TOPIC, "alpha") # abgeleitete Frage weg
assert not (arbeit / "ab-alpha").exists()
assert all(not files[k].exists() for k in ("sidecar", "facts", "sub_roh", "question_pattern", "artefakte"))
assert all(not files[k].exists() for k in ("sidecar", "facts", "sub_roh", "question_pattern", "artefakte", "outline"))
# ── Naming-Abstraktion: freier Name nur mit Anker ───────────────────────────────────

View File

@@ -72,6 +72,27 @@ async def test_e2e_guide(fake_welt, testdb, tmp_path):
assert await pruefe_guide_invarianten(TOPIC) == []
async def test_e2e_only_artefacts(fake_welt, testdb, tmp_path):
"""Artefakt-only (inventory=False): nach removeArtefacts läuft NUR Board 2 auf den
fertigen Blocks — kein Board 1, keine Research-Agenten. Karten aus done_block geseedet."""
ok, files = await _lauf(tmp_path)
assert ok
db = testdb
subs_vorher = {r["sub_norm"] for r in await db.list_subblocks(TOPIC)}
assert subs_vorher
# Artefakte entfernen (Karten zurück auf generate, Board-1-Subs bleiben)
await bi.reset_board_from_stage(TOPIC, "artefacts", "generate", files)
fake_welt.calls.clear()
ctx = GenContext(topic=TOPIC, provider="claude", is_cancelled=lambda: False)
ok2 = await asyncio.wait_for(
bi.run_boards(ctx, lambda *a, **k: None, files, {"type": "thema"}, None, "",
research=False, inventory=False), timeout=60)
assert ok2
assert not any("-research-" in k for k in fake_welt.calls) # Board 1 lief NICHT
assert any("-sb-enrich-" in k or "-sb-verify-" in k for k in fake_welt.calls) # Board 2 lief
assert {r["sub_norm"] for r in await db.list_subblocks(TOPIC)} == subs_vorher # vollständig
async def test_e2e_rerun_idempotent(fake_welt, testdb, tmp_path):
"""Zweiter Lauf (Continue, research=False) hinterlässt keine Waisen/Reste."""
ok, files = await _lauf(tmp_path)

View File

@@ -284,6 +284,23 @@ async def test_events_run_summary_aggregates(testdb):
assert s["tokens"] == {"input": 15, "output": 2, "cache_read": 80, "cache_write": 1}
async def test_events_run_summary_per_board(testdb):
"""meta.board scoped die Aggregation: board="artefacts" summiert nur Artefakt-Agenten."""
db = testdb
db.set_current_run(TOPIC, "r2")
await db.add_event(TOPIC, "agent", key="inv", status="ok", dur_ms=1000,
meta={"board": "inventory", "tokens": {"input": 10, "output": 2}})
await db.add_event(TOPIC, "agent", key="art", status="ok", dur_ms=2000,
meta={"board": "artefacts", "tokens": {"input": 5, "output": 7}})
db.set_current_run(TOPIC, None)
art = await db.events_run_summary(TOPIC, "r2", board="artefacts")
assert art["agents"]["gesamt"] == 1
assert art["tokens"] == {"input": 5, "output": 7, "cache_read": 0, "cache_write": 0}
inv = await db.events_run_summary(TOPIC, "r2", board="inventory")
assert inv["agents"]["gesamt"] == 1 and inv["tokens"]["input"] == 10
assert (await db.events_run_summary(TOPIC, "r2"))["agents"]["gesamt"] == 2 # ohne board = alle
async def test_topic_delete_entfernt_guides_und_kanban(testdb, tmp_path, monkeypatch):
"""DELETE /topics: guides/guide_cards/kanban_cards mitlöschen — GET /topics leitet
Topics aus guides ab, sonst taucht das gelöschte Topic sofort wieder auf."""