org_level_loop.py 2.87 KB
"""U-017: Org-level Loop closed loop (architecture doc §11 MVP acceptance
criterion 4) -- ties U-015 (root-cause judgment) + U-016 (routing) + real
Coder/Validator calls into one function: given a task sitting at
'validating' with a known bug, autonomously locate root cause, route to
the right Org Agent, drive the fix, and re-validate back to 'done'.
"""

from src import bug_record, org_loop_route, org_node_trigger, root_cause_trace

_ROUTE_FOR_CATEGORY = {"coder": "fast_lane", "planning": "full_replan"}


def run_fix_loop(conn, task_id, target_folder_path, bug_description, context, fix_prompt, verify_prompt, timeout=300):
    """Returns {"root_cause_category", "route", "verified", "final_status",
    "verify_response"}. Raises root_cause_trace.InconclusiveEscalateError if
    the 3 perspectives don't reach 2/3 agreement (same as U-015 -- this
    function doesn't add its own fallback for that, matching 04-P's own
    "升级人工" answer to disagreement)."""
    perspective_fns = [
        root_cause_trace.real_validator_perspective(
            name, bug_description, context, target_folder_path,
            trigger_fn=org_node_trigger.trigger_org_node, timeout=timeout,
        )
        for name in ("correctness", "requirement_completeness", "skill_defect")
    ]
    judgment = root_cause_trace.judge_root_cause(perspective_fns)
    category = judgment["root_cause_category"]
    route = _ROUTE_FOR_CATEGORY.get(category, "full_replan")

    bug_record.create_bug_record(
        conn, task_id=task_id, description=bug_description,
        root_cause_category=category, root_cause_detail=judgment["root_cause_detail"],
        suggested_route=route,
    )
    org_loop_route.route_org_loop(conn, task_id, route)

    fixer_node = "coder" if route == "fast_lane" else "planner"
    org_node_trigger.trigger_org_node(fixer_node, fix_prompt, target_folder_path, timeout=timeout)

    verify_response = org_node_trigger.trigger_org_node("validator", verify_prompt, target_folder_path, timeout=timeout)
    verified = "PASS" in verify_response.upper()

    if verified:
        # A real Work Graph would move coding/planning_brd_prd_sdd back to
        # 'validating' once the fixer's own Work Graph completes (U-011/012/013,
        # same mechanism U-014 uses) -- no separate controller exists for that
        # hop, so this mirrors it directly rather than inventing one just for
        # this Unit.
        conn.execute("UPDATE task SET status = 'validating' WHERE task_id = ?", (task_id,))
        conn.commit()
        org_loop_route.close_task_done(conn, task_id)
        final_status = "done"
    else:
        final_status = conn.execute("SELECT status FROM task WHERE task_id = ?", (task_id,)).fetchone()[0]

    return {
        "root_cause_category": category,
        "route": route,
        "verified": verified,
        "final_status": final_status,
        "verify_response": verify_response,
    }