From d678967fcf9489fd943bb17c7baf3c59f930d821 Mon Sep 17 00:00:00 2001 From: godosa Date: Wed, 7 Oct 2026 17:01:53 +0200 Subject: orch: needs-owner parks task After: its human task, lane keeps picking Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01JEAjUkQRrCYX5MZhWxdtj2 --- wf.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'wf.py') diff --git a/wf.py b/wf.py index 122b7db..ac4aadc 100755 --- a/wf.py +++ b/wf.py @@ -1597,7 +1597,7 @@ def cmd_gate(args) -> int: # ------------------------------------------------------------------ orchestrator GO_ON = ("done", "done+gate-red", "sliced") # outcomes after which the lane picks its next task -PARK = ("handback", "awaiting", "post-check-red") # block only that task (park_task), the lane keeps picking +PARK = ("handback", "awaiting", "needs-owner", "post-check-red") # block only that task (park_task), lane keeps picking def orch_main(args) -> tuple[Path, Project]: @@ -1783,7 +1783,8 @@ ARCHIVED = "archived, nothing to mark" def park_task(root: Path, id: str, final: str, words: list[str]) -> str: - """Block only this task after a handback/awaiting/post-check-red: blocked on its open a-id, else + """Block only this task after a handback/awaiting/needs-owner/post-check-red: needs-owner → After: its + open Needs-human item (status cleared); awaiting → blocked on its open a-id; else Sessions: owner (+ status cleared on a handback) and a note. Returns what it did (alert text).""" p = load_project(argparse.Namespace(project=str(root)), write=True) if id not in p.doc.ids(): @@ -1792,7 +1793,16 @@ def park_task(root: Path, id: str, final: str, words: list[str]) -> str: why = " ".join(words[1:]) or "-" open_a = {i.id for s in p.doc.sections if s.key == "awaiting" for i in s.items} a = next((w for w in words[1:] if w.strip("[]") in open_a), None) if final == "awaiting" else None - if (item.status or "").startswith("blocked:"): + open_h = {i.id for i in p.doc.section("human").items} + h = next((w.strip("[]") for w in words[1:] if w.strip("[]") in open_h), None) \ + if final == "needs-owner" else None + if h: # owner-only step: After: it, picked again once the owner's wf done archives it + if h not in item.after: + tasks.set_fields(p.doc, id, after=item.after + [h]) + if item.status: + tasks.set_status(p.doc, id, None) + done = f"after {h}" + elif (item.status or "").startswith("blocked:"): done = f"already {item.status}" elif a: tasks.set_status(p.doc, id, f"blocked: [[{a.strip('[]')}]]") @@ -1806,7 +1816,7 @@ def park_task(root: Path, id: str, final: str, words: list[str]) -> str: tasks.add_note(p.doc, id, f"orch {datetime.date.today().isoformat()}: {final} ({why}) → {done}; " "lane kept picking, owner decides") p.save(False) - if done.endswith("status cleared"): + if done.endswith("status cleared") or h: unclaim(p.cfg, [id]) return done @@ -2346,7 +2356,7 @@ def parser() -> argparse.ArgumentParser: op.add_argument("--recovery", metavar="WHY", help="prompt gets 'Recovery: WHY' (crashed worker, one retry)") op = osub.add_parser("post", help="after the worker's report: post-check (done: archive line, branch gone, " "worktree clean and in master, else wf merge; wf check), leftover commit otherwise, " - "out/wf-orch.log line, out/wf-cost.log line (--agent); awaiting/handback/post-check-red park only the task (blocked / Sessions: owner + note, 'alert:' line); then the next pick or 'stop lane'") + "out/wf-orch.log line, out/wf-cost.log line (--agent); awaiting/needs-owner/handback/post-check-red park only the task (blocked / After: h-task / Sessions: owner + note, 'alert:' line); then the next pick or 'stop lane'") op.add_argument("id") op.add_argument("lane") op.add_argument("--result", metavar="LINE", help="the report's result line (default: done if archived, else no-report)") -- cgit