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

@@ -1682,8 +1682,10 @@ async def _preload_state(flow: Flow):
async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instructions: str,
research: bool = True, artefacts: bool = True, qa_force: bool = False,
auto_inventory: bool = True, auto_artefacts: bool = True,
status_out: dict | None = None) -> bool:
inventory: bool = True, status_out: dict | None = None) -> bool:
"""Run the inventory board (plus board 2 „Artefakte") until quiescence.
inventory=False = artefacts-only: board 1 is NOT run; board-2 cards are seeded from the
finished blocks and the QA gate stays open (the inventory is already done).
research=False = Continue: drain the existing queue, search nothing new.
qa_force=True overrides a failed QA gate (user clicked „Trotzdem fortsetzen").
auto_inventory: after the inventory QA, loop repair until 100 %/stall/10×, then open the
@@ -1704,22 +1706,28 @@ async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instr
pages = await db.list_content(topic)
flow.state["pages"] = pages or sorted(set(_crawl_index(folder).values()))
await _preload_state(flow)
stages = inventory_stages(ctx, flow)
stages = inventory_stages(ctx, flow) if inventory else []
inv_names = [st.stage for st in stages]
if artefacts:
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)
if not inventory: # board 1 does not run → seed the board-2 cards from the finished blocks
geseedet = await board_artefacts.seed_artefact_cards(topic, files)
if geseedet:
_log(topic, f"Board 2 (nur Artefakte): {geseedet} Karte(n) aus fertigen Blocks erzeugt")
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:
if QA_GATE_NOTE > 0 and inventory:
# 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 == "generate")
sub.gate = lambda: bool(flow.state.get("qa_ok") or flow.state.get("qa_force"))
elif not inventory:
flow.state["qa_ok"] = True # artefacts-only: no inventory gate, board 2 runs immediately
stages = chain_stages(stages)
if artefacts:
# Outline needs every block's TITLE + FACTS (aus generate), nothing later: cut the
@@ -1728,7 +1736,7 @@ async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instr
outline = next(s for s in stages if s.stage == "outline")
outline.upstream = [u for u in outline.upstream if u not in
("verify", "artefakte", "finalize", "konsolidierung")]
producers = _build_producers(ctx, flow, q, folder, instructions) if research else []
producers = _build_producers(ctx, flow, q, folder, instructions) if (research and inventory) else []
async def _as_producer(coro):
try:
@@ -1745,7 +1753,7 @@ async def run_boards(ctx: GenContext, set_p, files: dict, q: dict, folder, instr
# cancel hook: blocks.cancel_blocks flips is_cancelled; stop the flow with it
stopper = asyncio.create_task(_stop_on_cancel(ctx, flow))
watcher = (asyncio.create_task(_qa_gate_watch(ctx, flow, inv_names, set_p))
if artefacts and QA_GATE_NOTE > 0 else None)
if artefacts and QA_GATE_NOTE > 0 and inventory else None)
try:
try:
await kanban.run_flow(flow, stages, [_as_producer(p) for p in producers], set_p)