Taskboard fasst nach: stockende, entblockte und wartende Aufgaben erkennen und nachfassen (#646)
Alle 30 Minuten, als Abfrage statt Modelllauf: Agentenaufgabe in Arbeit ohne Aenderung (Vorgabe 24 h) -> einmal neu gestartet, stockt sie binnen einer Woche wieder, geht es an die Leitung bzw. den Menschen; blockiert mit erledigten Blockern -> wieder offen; @human-Aufgabe ueber 48 h -> in einer Sammelaufgabe fuer den Menschen; in_review ueber 48 h und wiederholtes LoopLimitExceeded (3 in 7 Tagen) -> Aufgabe an die Leitung. Einmal je Zustand, hoechstens 10 Nachfassungen je Durchgang, jede im Audit. Befunde liegen abfragbar in TaskFindings (fuer #680); WebUI-Karte 'Liegengeblieben'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
095722ae9c
commit
e42ec100b0
@@ -1298,5 +1298,19 @@
|
||||
"tasks.participants": "Besprechungsteilnehmer",
|
||||
"tasks.participantsPlaceholder": "agent-a, agent-b — leer: keine Besprechung",
|
||||
"tasks.participantsHint": "Mit Teilnehmern ist die Aufgabe eine Besprechung: Jeder spricht einmal, in dieser Reihenfolge, mit Tagesordnung (der Aufgabentext) und dem bisher Gesagten; der zugewiesene Agent leitet, schreibt das Ergebnis und legt die Aufgaben dafür an. Das Protokoll landet im Bereich seiner Einheit.",
|
||||
"tasks.meetingWith": "Besprechung mit {participants}"
|
||||
"tasks.meetingWith": "Besprechung mit {participants}",
|
||||
"tasks.findings.title": "Liegengeblieben ({n})",
|
||||
"tasks.findings.hint": "Vom Board alle 30 Minuten gefunden, nicht von einem Modell. Eine stockende Agentenaufgabe wird einmal neu gestartet; stockt sie wieder, erfährt es die Leitung ihrer Einheit. Was auf dich wartet, wird in einer Aufgabe gesammelt. Die Schwellen stehen in den Instanzeinstellungen (followUp).",
|
||||
"tasks.findings.pending": "Noch nicht nachgefasst — höchstens zehn Nachfassungen je Durchgang.",
|
||||
"tasks.findings.acted": "{action} — {time}",
|
||||
"tasks.findings.kind.stalled": "kein Fortschritt",
|
||||
"tasks.findings.kind.unblocked": "Blocker erledigt",
|
||||
"tasks.findings.kind.human_waiting": "wartet auf einen Menschen",
|
||||
"tasks.findings.kind.review_waiting": "wartet auf Abnahme",
|
||||
"tasks.findings.kind.step_limit": "endet an der Schrittgrenze",
|
||||
"tasks.findings.action.woken": "neu gestartet",
|
||||
"tasks.findings.action.unblocked": "wieder geöffnet",
|
||||
"tasks.findings.action.to_reviewer": "an Leitung oder Mensch gegeben",
|
||||
"tasks.findings.action.in_digest": "für dich gesammelt",
|
||||
"tasks.findings.action.none": "nichts zu tun"
|
||||
}
|
||||
|
||||
@@ -1298,5 +1298,19 @@
|
||||
"tasks.participants": "Meeting participants",
|
||||
"tasks.participantsPlaceholder": "agent-a, agent-b — empty: not a meeting",
|
||||
"tasks.participantsHint": "With participants the task is a meeting: each speaks once, in this order, with the agenda (the task message) and what was said before; the assigned agent chairs, writes the result and creates the tasks for it. Minutes go to the chair's unit workspace.",
|
||||
"tasks.meetingWith": "Meeting with {participants}"
|
||||
"tasks.meetingWith": "Meeting with {participants}",
|
||||
"tasks.findings.title": "Left lying ({n})",
|
||||
"tasks.findings.hint": "Found by the board every 30 minutes, not by a model. A stalled agent task is started again once; if it stalls again, its unit's lead hears of it. Tasks waiting for you are collected in one task. The thresholds are in the instance settings (followUp).",
|
||||
"tasks.findings.pending": "Not followed up yet — at most ten follow-ups per pass.",
|
||||
"tasks.findings.acted": "{action} — {time}",
|
||||
"tasks.findings.kind.stalled": "no progress",
|
||||
"tasks.findings.kind.unblocked": "blockers finished",
|
||||
"tasks.findings.kind.human_waiting": "waits for a human",
|
||||
"tasks.findings.kind.review_waiting": "waits for review",
|
||||
"tasks.findings.kind.step_limit": "ends at the step limit",
|
||||
"tasks.findings.action.woken": "started again",
|
||||
"tasks.findings.action.unblocked": "opened again",
|
||||
"tasks.findings.action.to_reviewer": "handed to the lead or a human",
|
||||
"tasks.findings.action.in_digest": "listed for you",
|
||||
"tasks.findings.action.none": "nothing to do"
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@ async function ladeTaskboard() {
|
||||
const bretter = brettAuswahl(alle);
|
||||
if (bretter) container.append(bretter);
|
||||
|
||||
// #646: what the board found left lying — shown above the tasks, never folded away.
|
||||
const liegen = await erstelleBefundKarte();
|
||||
if (liegen) container.append(liegen);
|
||||
|
||||
if (tasks.length === 0) {
|
||||
container.append(
|
||||
erstelleKarte(t("tasks.empty"), [
|
||||
@@ -517,3 +521,31 @@ async function oeffneAufgabenDialog(task) {
|
||||
|
||||
modal.oeffnen();
|
||||
}
|
||||
|
||||
/**
|
||||
* #646: Work that lives but does not move — found by the board, not by a model: stalled,
|
||||
* unblocked, waiting for a human or a review, ending at the step limit. Each with what was done.
|
||||
*/
|
||||
async function erstelleBefundKarte() {
|
||||
let befunde;
|
||||
try {
|
||||
befunde = (await api("/tasks/findings")) || [];
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (befunde.length === 0) return null;
|
||||
|
||||
const zeilen = befunde.map((b) => erstelleElement("div", { klasse: "werkzeug-zeile" },
|
||||
erstelleElement("div", { klasse: "werkzeug-info" },
|
||||
erstelleElement("strong", { text: `${b.taskId} · ${t(`tasks.findings.kind.${b.kind}`)}` }),
|
||||
erstelleElement("div", { text: b.title }),
|
||||
erstelleElement("div", { klasse: "werkzeug-beschreibung gedaempft", text: `${b.detail} · ${b.assignee}` }),
|
||||
erstelleElement("div", { klasse: "werkzeug-beschreibung text-klein", text: b.actedAt
|
||||
? t("tasks.findings.acted", { action: t(`tasks.findings.action.${b.action.replace(" ", "_")}`), time: formatiereDatumZeit(b.actedAt) })
|
||||
: t("tasks.findings.pending") }))));
|
||||
|
||||
return erstelleKarte(t("tasks.findings.title", { n: befunde.length }), [
|
||||
erstelleElement("p", { klasse: "gedaempft text-klein", text: t("tasks.findings.hint") }),
|
||||
...zeilen
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user