"""The resurrect bundle (goal 8 task 4): standalone (no-project) tasks and comment-resurrected terminal items. - A task created with project_id 0 dispatches with EMPTY co-developed and reference arrays, the "standalone" project name, and completes on its completion report. - A human comment on a TERMINAL goal (complete) re-opens the goal, its run task returns to suspended-offerable, and the resuming assignment carries the comment + the re-open line in its resume notice. - A human comment on a TERMINAL plain task re-queues it, the next assignment carries the comment. - A terminal goal-owned WORKER task keeps comments closed (the page hides the composer; the service path is the goal's alone). """ from harness import * # noqa: F401,F403 — the shared wire helpers def run(ctx): auth, fake, fake_id, fake_token = ctx.auth, ctx.fake, ctx.fake_id, ctx.fake_token def create_goal(fields): act(auth, slot_public(auth, "/goals", "goals")["create"], fields) rows = [g for g in slot_public(auth, "/goals", "goals")["goals"] if g["title"] == fields["title"]] return int(rows[0]["id"]) def run_task_of(goal_id): conn = db() try: row = conn.execute( "select id from tasks where goal_id = ? and kind = 'goal_run'", (goal_id,)).fetchone() return int(row[0]) if row else None finally: conn.close() print("== standalone task: created with no project, dispatched, done ==") state = slot_public(auth, "/tasks", "tasks") act(auth, state["create"], { "project_id": "0", "title": "Standalone research", "description": "Summarise the fleet's flaky tests.", "priority": "3", }) standalone = task_id_of("Standalone research") detail = task_state(auth, standalone) check(detail["status"] == "draft" and int(detail["project_id"]) == 0, "a project_id 0 task creates in draft (project_id %s)" % detail["project_id"]) page = http_get_page(auth, "/tasks/%d" % standalone) # Goal 41 T5: the context line is the breadcrumb trail now; a # standalone task carries NO project crumb (and no project link). crumbs = detail.get("crumbs", []) check(len(crumbs) == 2 and crumbs[0]["label"] == "Tasks" and crumbs[1]["href"] is None and "#%d " % standalone in crumbs[1]["label"], "a standalone task's crumbs are Tasks / #id (no project crumb): %r" % crumbs) check('class="breadcrumb"' in page and "/projects/" not in page, "the task page renders the breadcrumb trail, not a project link") check("(standalone)" in http_get_page(auth, "/tasks"), "the tasks list still marks the standalone task") check("No project (standalone)" in http_get_page(auth, "/tasks"), "the create form offers the No project (standalone) option") enqueue_task(auth, standalone) check(wait_for(lambda: len(fake.start_payloads) > 0 or False, timeout=30, what="standalone /start push") is not None, "the dispatcher pushes the standalone task to the fake saddle") payload = fake.start_payloads[-1] task_obj = payload.get("task") or {} check(task_obj.get("project_name") == "standalone", "the standalone assignment names the project 'standalone' (%s)" % task_obj.get("project_name")) check(task_obj.get("co_developed") == [] and task_obj.get("reference") == [], "the standalone assignment ships EMPTY co-developed and reference arrays") check(task_obj.get("branch_from", "x") == "", "the standalone assignment carries no branch_from") check(wait_task_done(auth, standalone) is not None, "the standalone task completes on its report") print("== terminal plain task: a comment re-queues it ==") plain = create_queued(auth, { "project_id": "1", "title": "Resurrect me", "description": "A plain project task that finishes.", "priority": "4"}) check(wait_task_done(auth, plain) is not None, "the plain task completes") detail = task_state(auth, plain) act(auth, detail["comment"], {"body": "Please also cover the retry path."}) detail = task_state(auth, plain) check(detail["status"] == "queued", "the comment re-queued the terminal plain task (%s)" % detail["status"]) check(any("cover the retry path" in c["body"] for c in detail["comments"]), "the resurrecting comment rides the thread") conn = db() summary_kept = conn.execute( "select summary from tasks where id = ?", (plain,)).fetchone()[0] conn.close() check(summary_kept and len(summary_kept) > 0, "the earlier round's completion summary survives the re-open") check(wait_for(lambda: len(fake.start_payloads) > 1 or False, timeout=30, what="requeued dispatch") is not None, "the re-queued task dispatches again") def comment_reached_agent(): for payload in fake.start_payloads: task_obj = payload.get("task") or {} if task_obj.get("id") == plain and any( "cover the retry path" in c["body"] for c in task_obj.get("comments", [])): return True return any("cover the retry path" in (c.get("text") or "") for c in fake.comment_log) # The comment reaches the agent by EITHER channel: inside an # assignment payload, or via the live /task-update push to the # RUNNING daemon (the delivered flag) — the dispatcher tick races # the dispatch, so wait for whichever lands. check(wait_for(comment_reached_agent, timeout=30, what="comment delivery") is not None, "the second round receives the resurrecting comment (assignment or live push)") check(wait_task_done(auth, plain) is not None, "the second round completes") print("== terminal goal: a comment re-opens it and resumes the agent ==") # One behaviour per ROUND: round 1 plans (parks blocked), round 2 # (the approved resume) suspends, round 3 (the force-woke resume) # submits the completion report. fake.goal_script = [("plan", "# Resurrect plan\n\n1. Finish quickly"), ("suspend",), ("done", "# Completion\n\nThe report stands.")] goal = create_goal({"project_id": "1", "title": "Resurrect goal", "brief": "Completes, then re-opens on a comment.", "branch_name": "goal/resurrect"}) # (Goal 27 refinements — the parking guard: the round-2 suspend # needs a live wake source under the goal.) conn = db() conn.execute("insert into tasks (project_id, goal_id, kind, title, status," " priority, mode, creator, created_at) values (1, ?, 'task'," " 'Resurrect live worker', 'blocked', 5, 'implement', 'goal'," " strftime('%s','now'))", (goal,)) conn.commit() conn.close() act(auth, goal_state(goal)["start"], {}) check(wait_for(lambda: run_task_of(goal) is not None or False, timeout=30, what="goal run task appears") is not None, "starting the goal creates its run task") run_task = run_task_of(goal) check(wait_for(lambda: goal_state(goal)["status"] == "plan_review" or False, timeout=90, what="goal plans") is not None, "the goal reaches plan review") pending = goal_state(goal)["plan_pending_block"] act(auth, pending["answer_action"], {"verdict": "accept"}) check(wait_for(lambda: goal_state(goal)["status"] == "active" or False, timeout=60, what="plan approved") is not None, "approving the plan activates the goal") check(wait_for(lambda: task_state(auth, run_task)["status"] == "suspended" or False, timeout=60, what="agent parks") is not None, "the agent parks after the plan") # Round 3 needs a wake: force-wake the parked agent so its scripted # done round (the completion report) runs. state = goal_state(goal) act(auth, state["force_wake"], {}) # The completion round: the scripted done parks the run for review. check(wait_for(lambda: goal_state(goal)["status"] == "completion_review" or False, timeout=90, what="completion review opens") is not None, "the scripted done round enters completion review") block = goal_state(goal)["completion_pending_block"] act(auth, block["answer_action"], {"verdict": "accept"}) check(wait_for(lambda: goal_state(goal)["status"] == "complete" or False, timeout=30, what="goal completes") is not None, "accepting the completion completes the goal") check(wait_for(lambda: task_state(auth, run_task)["status"] == "done" or False, timeout=30, what="run task done") is not None, "the run task closed done with the goal") goal_page = http_get_page(auth, "/goals/%d" % goal) check("stm-action=\"goal.comment\"" in goal_page, "the terminal goal page keeps the comment composer open") check("commenting re-opens it" in goal_page, "the composer explains the resurrect semantics on a terminal goal") state = goal_state(goal) act(auth, state["comment"], {"body": "One more sweep of the edge cases, please."}) check(wait_for(lambda: goal_state(goal)["status"] == "active" or False, timeout=30, what="goal re-opens") is not None, "the comment re-opened the completed goal") check(wait_for(lambda: task_state(auth, run_task)["status"] == "suspended" or False, timeout=30, what="run re-offerable") is not None, "the DONE run task returned to suspended (the parked-resume shape)") conn = db() report_kept = conn.execute( "select completion_report from goals where id = ?", (goal,)).fetchone()[0] seeded = conn.execute( "select count(*) from sessions where task_id = ?", (run_task,)).fetchone()[0] conn.close() check(report_kept and len(report_kept) > 0, "the completion report stays on the re-opened goal") check(seeded >= 1, "the resurrected run carries a session row (the resume anchor)") goal_comments = goal_state(goal)["comments"] check(any("edge cases" in c["body"] for c in goal_comments), "the resurrecting comment rides the goal thread") # force_wake made the parked run offerable at once: the dispatcher # hands it back and the resuming assignment carries the notice. assignments_before = len(fake.goal_assignments) check(wait_for(lambda: len(fake.goal_assignments) > assignments_before or False, timeout=60, what="resurrected agent resumes") is not None, "the resurrected goal agent resumes on its saddle") resumed = fake.goal_assignments[-1] check((resumed.get("task") or {}).get("id") == run_task, "the resuming assignment is the run task") check("re-opened by a human comment" in (resumed.get("resume_notice") or ""), "the resume notice names the comment-driven re-open") check(any("edge cases" in c["body"] for c in (resumed.get("task") or {}).get("comments", [])) or any("edge cases" in (c.get("text") or "") for c in fake.comment_log), "the resuming agent receives the comment (assignment or live push)") print("== terminal goal worker: comments stay closed ==") conn = db() worker = conn.execute( "insert into tasks (project_id, goal_id, kind, title, status, priority," " mode, creator, completed_at, created_at)" " values (1, ?, 'task', 'Dead worker', 'done', 5," " 'implement', 'goal', strftime('%s','now'), strftime('%s','now'))", (goal,)).lastrowid conn.commit() conn.close() worker_page = http_get_page(auth, "/tasks/%d" % worker) check("Comments are closed" in worker_page, "a terminal goal-owned task page explains the closed comments") # The gate lives in the template (statum hides the branch at render; # the served markup carries no branch text to match — pages.py's # Edit-button precedent): the composer must sit inside the # goal-owned-terminal negation and the closed notice inside the # positive gate. template = open(os.path.join(REPO, "src", "pages", "task_detail.html")).read() composer_at = template.find('