fix(kanban): judge unachievable goals as blocked, never done

This commit is contained in:
itsflownium
2026-09-02 18:46:45 +10:00
committed by Teknium
parent d3e2ace1dd
commit 1bd9fce6cb
5 changed files with 195 additions and 33 deletions
+33 -10
View File
@@ -2311,18 +2311,23 @@ def _worker_run_id_for(task_id: str) -> Optional[int]:
return None
def _goal_mode_handoff_rejection(task: Optional[kb.Task], evidence: str) -> Optional[str]:
"""Apply the goal judge to every terminal worker handoff, including review."""
def _goal_mode_handoff_rejection(task: Optional[kb.Task], evidence: str):
"""Apply the goal judge to every terminal worker handoff, including review.
Returns ``(verdict, reason_or_None)`` — ``"done"`` allows the handoff;
``"blocked"`` means the judge ruled the goal unachievable (#100954);
``"continue"``/``"wait"`` reject with the judge's reason.
"""
if task is None or not task.goal_mode:
return None
return ("done", None)
try:
from agent.auxiliary_client import get_text_auxiliary_client
client, model = get_text_auxiliary_client("goal_judge")
except Exception:
return None
return ("done", None)
if client is None or not model:
return None
return ("done", None)
from hermes_cli.goals import judge_goal
@@ -2341,7 +2346,7 @@ def _goal_mode_handoff_rejection(task: Optional[kb.Task], evidence: str) -> Opti
judge_exc,
exc_info=True,
)
return reason if verdict != "done" else None
return (verdict, None if verdict == "done" else reason)
def _cmd_complete(args: argparse.Namespace) -> int:
@@ -2379,11 +2384,21 @@ def _cmd_complete(args: argparse.Namespace) -> int:
# to every terminal handoff so request-review cannot bypass the
# acceptance contract that protects complete.
task = kb.get_task(conn, tid)
rejection = _goal_mode_handoff_rejection(
gate_verdict, rejection = _goal_mode_handoff_rejection(
task,
(summary or args.result or "").strip(),
)
if rejection is not None:
if gate_verdict == "blocked":
print(
f"kanban: goal completion of {tid} rejected: judge ruled "
f"the goal unachievable — {rejection}. Re-scope with "
f"kanban edit, or record the block with kanban block "
f"instead of completing.",
file=sys.stderr,
)
failed.append(tid)
continue
if gate_verdict == "continue" or rejection is not None:
print(
f"kanban: goal completion of {tid} rejected by judge: {rejection}. "
f"Provide evidence matching the task's acceptance criteria.",
@@ -2532,11 +2547,19 @@ def _cmd_request_review(args: argparse.Namespace) -> int:
return 2
reviewer = getattr(args, "reviewer", None)
with kb.connect_closing() as conn:
rejection = _goal_mode_handoff_rejection(
gate_verdict, rejection = _goal_mode_handoff_rejection(
kb.get_task(conn, tid),
summary or "",
)
if rejection is not None:
if gate_verdict == "blocked":
print(
f"kanban: goal review handoff of {tid} rejected: judge ruled "
f"the goal unachievable — {rejection}. Record the block with "
f"kanban block instead of requesting review.",
file=sys.stderr,
)
return 1
if gate_verdict == "continue" or rejection is not None:
print(
f"kanban: goal review handoff of {tid} rejected by judge: "
f"{rejection}. Provide acceptance evidence matching the task.",