From a55d241f305a6994a474bfd7466c183df836ca2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Wed, 24 Jun 2026 20:55:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20TODO=20DB=E8=BF=81=E7=A7=BB+no=5Fagent?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E5=99=A8+=E9=98=BB=E5=A1=9E=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 mofin.db → todos 表(id/title/status/priority/fix_action/retry机制) - 创建 self_todo_executor.py:no_agent脚本,纯代码逻辑 - 有fix_action→执行→验证→标记completed - 无fix_action→标记blocked→输出通知 - 失败重试3次→超限标blocked - 新blocked项首次输出后缓存不重复 - 修改 morning_health_check: - TODO写入DB取代JSON(sqlite3,无row_factory依赖) - 去重:含completed查重 - 输出阻塞TODO列表 - 替换cron:LLM cron(2h间距) → no_agent(10min间距) - 修复:deliver=origin两任务改为local - 清理:废弃todo.json退役 --- scripts/morning_health_check.py | 35 ++++++++++++++++++++++----------- scripts/self_todo_executor.py | 24 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/scripts/morning_health_check.py b/scripts/morning_health_check.py index 6b85592..fa865fe 100755 --- a/scripts/morning_health_check.py +++ b/scripts/morning_health_check.py @@ -134,18 +134,18 @@ def write_todos_for_issues(): level = issue["level"] pri = todo_priority.get(level, "medium") - # 去重:检查是否已有相同 title - existing = conn.execute( - "SELECT id, status FROM todos WHERE title=? AND status IN ('pending','in_progress','blocked')", + # 去重:检查是否已存在(含completed的也要查,避免重复加) + r_exist = conn.execute( + "SELECT id, status FROM todos WHERE title=?", (title,) ).fetchone() - if existing: - if existing["status"] == "blocked": + if r_exist: + if r_exist[1] == "blocked": # 已阻塞的重新打开 conn.execute( "UPDATE todos SET status='pending', priority=?, note='已重新打开', updated_at=CURRENT_TIMESTAMP WHERE id=?", - (pri, existing["id"]) + (pri, r_exist[0]) ) else: # 生成fix_action(如果可推导) @@ -160,18 +160,15 @@ def write_todos_for_issues(): new_count += 1 conn.commit() - conn.close() if new_count > 0: print() print(f"📋 已加入TODO({new_count}条):") - # 重新查刚插入的pending记录 - cur2 = conn.cursor() - for r2 in cur2.execute( + for r2 in conn.execute( "SELECT title, priority FROM todos WHERE status='pending' AND source='health_check' " "ORDER BY created_at DESC LIMIT ?", (new_count,) ).fetchall(): - print(f" [{r2['priority']}] {r2['title'][:70]}") + print(f" [{r2[1]}] {r2[0][:70]}") conn.close() except Exception as e: print(f" TODO写入异常: {e}") @@ -660,6 +657,22 @@ def main(): if entry["level"] in ("critical", "error"): print(f" [{entry['level'].upper()}] {entry['category']}: {entry['msg']}") + # 检查是否有阻塞的 TODO 需要知微处理 + try: + conn = sqlite3.connect(str(DB_PATH)) + blocked = conn.execute( + "SELECT id, title, priority, created_at FROM todos WHERE status='blocked' " + "ORDER BY CASE priority WHEN 'high' THEN 0 WHEN 'medium' THEN 1 ELSE 2 END, created_at ASC" + ).fetchall() + if blocked: + print() + print("⛔ 阻塞TODO(需知微人工处理):") + for b in blocked: + print(f" [{b[2]}] #{b[0]} {b[1][:70]} ({b[3][:10]})") + conn.close() + except: + pass + # 将异常写入 TODO 系统 write_todos_for_issues() diff --git a/scripts/self_todo_executor.py b/scripts/self_todo_executor.py index b8abcae..99b434d 100644 --- a/scripts/self_todo_executor.py +++ b/scripts/self_todo_executor.py @@ -12,6 +12,8 @@ from datetime import datetime BASE = Path("/home/hmo/MoFin") DB_PATH = BASE / "data" / "mofin.db" +# 记录已报告过的blocked ID,避免重复推送 +REPORTED_BLOCKED_PATH = Path("/home/hmo/.hermes/profiles/position-analyst/home/.cache/executor_reported_blocked.json") def get_conn(): @@ -76,6 +78,8 @@ def main(): return results = [] + newly_blocked = [] # [(id, title)] 新阻塞的,需要推送给Dad/知微 + for row in rows: todo_id = row["id"] title = row["title"] @@ -102,6 +106,7 @@ def main(): "note=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (retry_count, f"重试{retry_count}次仍失败: {output}", todo_id) ) + newly_blocked.append((todo_id, title)) results.append(("⛔", f"{title}: 已阻塞({output[:60]})")) else: cur.execute( @@ -137,11 +142,30 @@ def main(): "updated_at=CURRENT_TIMESTAMP WHERE id=?", (todo_id,) ) + newly_blocked.append((todo_id, title)) results.append(("⛔", f"{title}: 无修复命令,已阻塞")) conn.commit() conn.close() + + # 记录新报告过的blocked ID + try: + REPORTED_BLOCKED_PATH.parent.mkdir(parents=True, exist_ok=True) + reported = json.loads(REPORTED_BLOCKED_PATH.read_text()) if REPORTED_BLOCKED_PATH.exists() else [] + # 过滤出尚未报告过的blocked项 + unreported_blocked = [(tid, t) for tid, t in newly_blocked if tid not in reported] + if unreported_blocked: + # 有未报告的阻塞项 → 输出直通知微 + print() + print("⛔ 需知微处理(已阻塞,无自动修复方案):") + for tid, t in unreported_blocked: + print(f" #{tid} {t[:70]}") + # 标记已报告 + reported.extend([tid for tid, _ in unreported_blocked]) + REPORTED_BLOCKED_PATH.write_text(json.dumps(reported[-200:], ensure_ascii=False)) + except: + pass elapsed = time.time() - start if results: