dev-agent-find-task.py 9.72 KB
#!/usr/bin/env python3
"""
Dev Agent - Find next task with three-phase discovery.
Phase 1a: Continue unfinished main tasks (开发中/修复中 with pending subtasks)
Phase 1a.5: Pipeline recovery:
  (A) Stuck subtasks: main=待测 but has unfinished subtasks
  (B) Stale review-fail bugs: main=待测, completed/待测 subtask has 待修复 bugs
Phase 1b: New tasks (待办 requirement / 待修复 bug)
Outputs JSON to stdout, or "NO_TASKS" if nothing found.
"""
import json, os, sys

sys.path.insert(0, os.path.expanduser(
    "~/.hermes/skills/productivity/feishu-todo-sync/references"))
from pipeline_api import load_config, fetch_all

AH, AT, RT, BT = load_config()


def get_subtasks(records, parent_id):
    subs = []
    for r in records:
        parent = r.get("fields", {}).get("父记录")
        if parent and isinstance(parent, list) and len(parent) > 0:
            entry = parent[0]
            if entry is None:  # defend against [None]
                continue
            pids = entry.get("record_ids")
            if pids and parent_id in pids:
                subs.append(r)
    return subs


def is_main_task(record):
    parent = record.get("fields", {}).get("父记录")
    if not parent or not isinstance(parent, list) or len(parent) == 0:
        return True
    entry = parent[0]
    if entry is None:  # defend against [None]
        return True
    pids = entry.get("record_ids")
    return pids is None


def sort_by_priority(items):
    pri_map = {"P0-紧急": 0, "P1-高": 1, "P2-中": 2, "P3-低": 3, "P3": 3}
    return sorted(items, key=lambda x: pri_map.get(
        x.get("fields", {}).get("优先级", "P3-低"), 3))


req_records = fetch_all(RT)
bug_records = fetch_all(BT)

result = None

# ============================================================
# PHASE 1a: Continue unfinished main tasks
# ============================================================
for r in sort_by_priority(req_records):
    if not is_main_task(r):
        continue
    status = r.get("fields", {}).get("状态", "")
    if status != "开发中":
        continue
    subs = get_subtasks(req_records, r["record_id"])
    pending_subs = [s for s in subs if s.get("fields", {}).get("状态", "")
                    in ("待办", "开发中", "自测中")]
    if pending_subs:
        result = {
            "phase": "1a-continue", "table": "r",
            "record_id": r["record_id"],
            "title": r.get("fields", {}).get("需求标题", ""),
            "status": status,
            "all_subtasks": [{"id": s["record_id"],
                              "title": s.get("fields", {}).get("需求标题", ""),
                              "status": s.get("fields", {}).get("状态", "")}
                             for s in subs],
            "pending_subtasks": [{"id": s["record_id"],
                                  "title": s.get("fields", {}).get("需求标题", ""),
                                  "status": s.get("fields", {}).get("状态", "")}
                                 for s in pending_subs],
        }
        break

if not result:
    for r in sort_by_priority(bug_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "修复中":
            continue
        subs = get_subtasks(bug_records, r["record_id"])
        pending_subs = [s for s in subs if s.get("fields", {}).get("状态", "")
                        in ("待修复", "修复中", "自测中")]
        if pending_subs:
            result = {
                "phase": "1a-continue", "table": "b",
                "record_id": r["record_id"],
                "title": r.get("fields", {}).get("Bug标题", ""),
                "status": status,
                "all_subtasks": [{"id": s["record_id"],
                                  "title": s.get("fields", {}).get("Bug标题", ""),
                                  "status": s.get("fields", {}).get("状态", "")}
                                 for s in subs],
                "pending_subtasks": [{"id": s["record_id"],
                                      "title": s.get("fields", {}).get("Bug标题", ""),
                                      "status": s.get("fields", {}).get("状态", "")}
                                     for s in pending_subs],
            }
            break

# ============================================================
# PHASE 1a.5: Pipeline recovery
# ============================================================
if not result:
    # (A) Stuck subtasks: main=待测, but has unfinished subtasks
    for r in sort_by_priority(req_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "待测":
            continue
        subs = get_subtasks(req_records, r["record_id"])
        unfinished = [s for s in subs if s.get("fields", {}).get("状态", "")
                      in ("待办", "开发中", "自测中")]
        if unfinished:
            result = {
                "phase": "1a.5A-stuck", "table": "r",
                "record_id": r["record_id"],
                "title": r.get("fields", {}).get("需求标题", ""),
                "status": status,
                "unfinished_subtasks": [
                    {"id": s["record_id"],
                     "title": s.get("fields", {}).get("需求标题", ""),
                     "status": s.get("fields", {}).get("状态", "")}
                    for s in unfinished],
            }
            break

if not result:
    for r in sort_by_priority(bug_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "待测":
            continue
        subs = get_subtasks(bug_records, r["record_id"])
        unfinished = [s for s in subs if s.get("fields", {}).get("状态", "")
                      in ("待修复", "修复中", "自测中")]
        if unfinished:
            result = {
                "phase": "1a.5A-stuck", "table": "b",
                "record_id": r["record_id"],
                "title": r.get("fields", {}).get("Bug标题", ""),
                "status": status,
                "unfinished_subtasks": [
                    {"id": s["record_id"],
                     "title": s.get("fields", {}).get("Bug标题", ""),
                     "status": s.get("fields", {}).get("状态", "")}
                    for s in unfinished],
            }
            break

# (B) Stale review-fail bugs
if not result:
    for r in sort_by_priority(req_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "待测":
            continue
        subs = get_subtasks(req_records, r["record_id"])
        for s in subs:
            s_status = s.get("fields", {}).get("状态", "")
            if s_status not in ("已完成", "待测"):
                continue
            child_bugs = get_subtasks(bug_records, s["record_id"])
            pending_bugs = [b for b in child_bugs
                            if b.get("fields", {}).get("状态", "")
                            in ("待修复", "修复中", "自测中")]
            if pending_bugs:
                result = {
                    "phase": "1a.5B-stale-bug", "table": "r",
                    "record_id": r["record_id"],
                    "title": r.get("fields", {}).get("需求标题", ""),
                    "status": status,
                    "stale_subtask": {
                        "id": s["record_id"],
                        "title": s.get("fields", {}).get("需求标题", ""),
                        "status": s_status},
                    "pending_bugs": [
                        {"id": b["record_id"],
                         "title": b.get("fields", {}).get("Bug标题", ""),
                         "status": b.get("fields", {}).get("状态", "")}
                        for b in pending_bugs],
                }
                break
        if result:
            break

# ============================================================
# PHASE 1b: New tasks
# ============================================================
if not result:
    for r in sort_by_priority(req_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "待办":
            continue
        subs = get_subtasks(req_records, r["record_id"])
        result = {
            "phase": "1b-new", "table": "r",
            "record_id": r["record_id"],
            "title": r.get("fields", {}).get("需求标题", ""),
            "priority": r.get("fields", {}).get("优先级", ""),
            "status": status,
            "subtasks": [{"id": s["record_id"],
                          "title": s.get("fields", {}).get("需求标题", ""),
                          "status": s.get("fields", {}).get("状态", "")}
                         for s in subs],
        }
        break

if not result:
    for r in sort_by_priority(bug_records):
        if not is_main_task(r):
            continue
        status = r.get("fields", {}).get("状态", "")
        if status != "待修复":
            continue
        subs = get_subtasks(bug_records, r["record_id"])
        result = {
            "phase": "1b-new", "table": "b",
            "record_id": r["record_id"],
            "title": r.get("fields", {}).get("Bug标题", ""),
            "priority": r.get("fields", {}).get("优先级", ""),
            "status": status,
            "subtasks": [{"id": s["record_id"],
                          "title": s.get("fields", {}).get("Bug标题", ""),
                          "status": s.get("fields", {}).get("状态", "")}
                         for s in subs],
        }
        break

if result:
    print(json.dumps(result, ensure_ascii=False, indent=2))
else:
    print("NO_TASKS")