This commit is contained in:
Team3
2026-07-04 23:47:04 +02:00
parent 2d9ca00b47
commit 4105146c59
40 changed files with 2053 additions and 3208 deletions

View File

@@ -1669,21 +1669,24 @@ async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instr
import board_artefacts # lazy — board_artefacts imports blocks too
flow.state["spawn_artefact"] = board_artefacts.make_spawner(topic, files)
await board_artefacts.ensure_outline_card(topic)
migriert = await board_artefacts.migriere_alt_karten(topic)
if migriert:
_log(topic, f"Board 2: {migriert} Karte(n) der alten Stage-Struktur → generate")
stages += board_artefacts.artefact_stages(ctx, flow, files, q, folder, instructions)
if QA_GATE_NOTE > 0:
# QA gate: board 2 waits until the inventory QA passed (or the user forces).
# Costs pipelining (board 2 no longer starts per finished block) but saves
# tokens on a bad foundation — the watcher below runs the QA and decides.
sub = next(st for st in stages if st.stage == "subblocks")
sub = next(st for st in stages if st.stage == "generate")
sub.gate = lambda: bool(flow.state.get("qa_ok") or flow.state.get("qa_force"))
stages = chain_stages(stages)
if artefacts:
# Outline needs every block's TITLE + FACTS, nothing later: cut the post-facts
# artefact stages from its barrier so it runs parallel to levels…finalize of the
# slowest block (makespan tail). Inventory stages all stay — no late blocks.
# Outline needs every block's TITLE + FACTS (aus generate), nothing later: cut the
# post-generate stages from its barrier so it runs parallel to verify…finalize AND
# zur Cross-Dedup-Barriere des langsamsten Blocks (makespan tail).
outline = next(s for s in stages if s.stage == "outline")
outline.upstream = [u for u in outline.upstream if u not in
("levels", "relevance", "question_pattern", "artefacts", "finalize")]
("verify", "artefakte", "finalize", "konsolidierung")]
producers = _build_producers(ctx, flow, q, folder, instructions) if research else []
async def _as_producer(coro):
@@ -1712,7 +1715,7 @@ async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instr
if ctx.is_cancelled():
return False
if flow.state.get("qa_paused"):
return True # kein Fehler: Flow hielt am QA-Gate, Karten warten in subblocks
return True # kein Fehler: Flow hielt am QA-Gate, Karten warten in generate
await _write_final(topic, files)
await _write_run_summary(topic, flow)
return True
@@ -1834,14 +1837,11 @@ COLUMNS = [
("inventory", "done_block", "Fertig", "block"),
("inventory", "rejected", "Verworfen", None),
("inventory", "grouped", "Zusammengelegt", "block"),
("artefacts", "subblocks", "Subbausteine", "ablock"),
("artefacts", "facts", "Fakten", "ablock"),
("artefacts", "levels", "Stufen", "ablock"),
("artefacts", "relevance", "Relevanz", "ablock"),
("artefacts", "konsolidierung", "Konsolidierung", "ablock"),
("artefacts", "question_pattern", "Fragen", "ablock"),
("artefacts", "artefacts", "Lernkarten", "ablock"),
("artefacts", "generate", "Erzeugen", "ablock"),
("artefacts", "verify", "Prüfen", "ablock"),
("artefacts", "artefakte", "Lernmittel", "ablock"),
("artefacts", "finalize", "Zusammenführen", "ablock"),
("artefacts", "konsolidierung", "Konsolidierung", "ablock"),
("artefacts", "outline", "Gliederung", "outline"),
("artefacts", "done_artefact", "Fertig", "ablock"),
]
@@ -1849,18 +1849,16 @@ COLUMNS = [
_TITLE_STAGES = ["ingest", "cluster"]
_CLUSTER_STAGES = ["pair_check", "consensus_gate", "clarify", "naming", "naming_check"]
_BLOCK_STAGES = ["fragment_filter", "dedup", "grouping", "gap_check", "done"]
_ART_STAGES = ["subblocks", "facts", "levels", "relevance", "konsolidierung", "question_pattern",
"artefacts", "finalize", "outline"]
_ART_STAGES = ["generate", "verify", "artefakte", "finalize", "konsolidierung", "outline"]
# where a requeued dead card restarts, by kind
_DEAD_RESTART = {"title": "cluster", "cluster": "pair_check", "block": "fragment_filter",
"ablock": "subblocks", "outline": "outline"}
"ablock": "generate", "outline": "outline"}
_VERDICT_KEYS = ("reason", "votes", "judges", "merged_into", "parent_norm", "mirrored_norm")
DONE_ART = "done_artefact"
# Board-2 stage → its fine-step group in blocks.PHASEN (drives the per-card stepper).
_STAGE_PHASE = {"subblocks": "Subblocks", "facts": "Facts", "levels": "Levels",
"relevance": "Relevance", "question_pattern": "Questions", "artefacts": "Artefacts"}
_STAGE_PHASE = {"generate": "Generate", "verify": "Verify", "artefakte": "Artefakte"}
_PHASE_STEPS = {name: steps for name, steps in blocks.PHASEN}
@@ -1928,7 +1926,7 @@ def _qa_view(topic: str, counts: dict, flow) -> dict | None:
note = r.get("note")
if note is None:
return None
wartend = counts.get("artefacts", {}).get("subblocks", 0)
wartend = counts.get("artefacts", {}).get("generate", 0)
pausiert = bool(note < QA_GATE_NOTE and wartend and flow is None)
return {"note": note, "note_artefakte": r.get("note_artefakte"),
"schwelle": QA_GATE_NOTE, "pausiert": pausiert,
@@ -1997,7 +1995,7 @@ async def reset_board_from_stage(topic: str, board: str, stage: str, files: dict
await _requeue(r, "outline")
elif r["stage"] in later:
await _requeue(r, stage)
if stage == "subblocks": # full artefact re-derive → also the DB mirrors
if stage == "generate": # full artefact re-derive → also the DB mirrors
await db.delete_subblocks(topic)
await db.delete_question_pattern(topic)
await db.delete_sub_artefakte(topic)
@@ -2013,7 +2011,7 @@ async def reset_board_from_stage(topic: str, board: str, stage: str, files: dict
async def restart_artefact_card(topic: str, card_id: str) -> bool:
"""Restart ONE artefacts card from `subblocks` — wipes only ITS derived DB rows
"""Restart ONE artefacts card from `generate` — wipes only ITS derived DB rows
(per-block work-dir slots overwrite themselves; finalize re-upserts later).
Only call while nothing is generating (the route guards). → False if unknown."""
card = await db.kanban_get_card(topic, "artefacts", card_id)
@@ -2024,7 +2022,7 @@ async def restart_artefact_card(topic: str, card_id: str) -> bool:
await db.delete_sub_artefakte(topic, card_id)
p = {k: v for k, v in card["payload"].items() if k in ("title", "description")}
await db.kanban_set_payload(topic, "artefacts", card_id, p)
await db.kanban_advance(topic, "artefacts", card_id, "subblocks")
await db.kanban_advance(topic, "artefacts", card_id, "generate")
await db.add_event(topic, "reset", key=f"artefacts:{card_id}", status="card-restart")
return True