This commit is contained in:
team3
2026-07-08 21:14:33 +02:00
parent 9a6ab0937b
commit f9d77a113b
30 changed files with 1064 additions and 654 deletions

View File

@@ -702,6 +702,22 @@ async def set_block_status(topic: str, title_norm: str, status: str, title: str
await _update("blocks", fields, {"topic": topic, "title_norm": title_norm})
async def rename_block_norm(topic: str, alt_norm: str, neu_norm: str, neu_titel: str) -> None:
"""Block-Norm vollständig um-keyen (Repair: `(n)`-Kollisionssuffix ablegen): blocks-
Spiegel PLUS alle angehängten Tabellen in einer Transaktion — anders als
set_block_status(neu_norm=…) auch mit vorhandenen Subblocks/Fragen/Artefakten sicher."""
async with _tx() as db:
for table in ("subblocks", "question_pattern", "sub_artefakte"):
await db.execute(
f"UPDATE {table} SET block_norm = ?, block = ?, updated_at = ? "
"WHERE topic = ? AND block_norm = ?",
(neu_norm, neu_titel, _now(), topic, alt_norm))
await db.execute(
"UPDATE blocks SET title_norm = ?, title = ?, updated_at = ? "
"WHERE topic = ? AND title_norm = ?",
(neu_norm, neu_titel, _now(), topic, alt_norm))
async def delete_blocks(topic: str) -> None:
async with _tx() as db:
await db.execute("DELETE FROM blocks WHERE topic = ?", (topic,))
@@ -945,6 +961,35 @@ async def list_runs(topic: str, limit: int = 10) -> list[dict]:
return out
async def latest_board_runs(topic: str) -> dict:
"""Jüngster Lauf MIT Daten je Ebene — Anzeige-Quelle der Board-Kopfzeilen im Frontend.
„Nur Artefakte"-/Guide-Läufe bekommen eine frische run_id und lassen die anderen Ebenen
leer; der jüngste Lauf allein zeigt dann nichts. Hier zählt je Ebene der letzte Lauf,
der sie wirklich enthielt. inventory/artefacts via meta.$.board (agents.agent_ebene);
guide via run_id-Suffix „-g"+4hex (guide_board.run_guide_board setzt den Marker,
Blocks-Suffixe sind reines Hex — enthalten nie „g").
{ebene: {run_id, aktiv, agents, tokens, start, ende} | None}"""
db = await get_db()
out: dict = {}
for b in ("inventory", "artefacts"):
cur = await db.execute(
"SELECT run_id FROM events WHERE topic = ? AND kind = 'agent' AND run_id != '' "
"AND json_extract(meta,'$.board') = ? ORDER BY ts DESC LIMIT 1", (topic, b))
row = await cur.fetchone()
out[b] = None if row is None else {
"run_id": row[0], "aktiv": _current_run.get(topic) == row[0],
**await events_run_summary(topic, row[0], board=b)}
cur = await db.execute(
"SELECT run_id FROM events WHERE topic = ? AND kind = 'agent' AND run_id != '' "
"AND run_id GLOB '*-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f]' ORDER BY ts DESC LIMIT 1",
(topic,))
row = await cur.fetchone()
out["guide"] = None if row is None else {
"run_id": row[0], "aktiv": _current_run.get(topic) == row[0],
**await events_run_summary(topic, row[0])} # Guide: ganzer Lauf (Events sind untagged)
return out
async def kanban_dead(topic: str) -> list[dict]:
"""Dead-letter cards across boards (for the board UI + requeue)."""
return await kanban_cards(topic, stage="dead")