From 3238ba54fb8971ef3747b3b0cb156c7a25d05cbb Mon Sep 17 00:00:00 2001 From: hmo Date: Mon, 13 Jul 2026 22:43:41 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E6=A3=80=E4=BF=AE=E5=A4=8D:=20reflog?= =?UTF-8?q?=E8=AF=BBgit=20+=20threaded=3DTrue=20+=20TODO=E8=AF=AF=E5=88=A4?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Git: 从.git/logs/HEAD读取提交历史,不依赖git二进制 - Flask: threaded=True防止单线程阻塞 - TODO: 'already running'→completed而非failed - E元成长: 改用reflog行数计算commit数 --- gateway/scripts/dashboard.py | 73 ++++++++++++++++++--------- gateway/scripts/self_todo_executor.py | 6 ++- 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/gateway/scripts/dashboard.py b/gateway/scripts/dashboard.py index 5d4f966..18e1514 100644 --- a/gateway/scripts/dashboard.py +++ b/gateway/scripts/dashboard.py @@ -562,22 +562,45 @@ def api_kanban(): # ════════════════════════════════════════════════════════════ @app.route("/api/git") def api_git(): - """最近 git 提交历史 + 分支状态""" + """最近 git 提交历史 + 分支状态(从 .git 直接读取,不依赖 git 命令)""" try: - git_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") - git_dir = os.path.normpath(git_dir) # → AgentsMeeting/ - if not os.path.exists(os.path.join(git_dir, ".git")): - # 如果 _PROJECT_OVERRIDE 设置了,用它 - git_dir = os.environ.get("AGENTSMEETING_ROOT", "") - if not git_dir or not os.path.exists(os.path.join(git_dir, ".git")): - return jsonify({"ok": False, "log": [".git not found at " + git_dir], "dirty": False}) - r = subprocess.run(["git", "log", "--oneline", "-10"], - cwd=git_dir, capture_output=True, text=True, timeout=5) - log_lines = r.stdout.strip().split("\n") if r.returncode == 0 else ["git not available"] - r2 = subprocess.run(["git", "status", "--short"], - cwd=git_dir, capture_output=True, text=True, timeout=5) - dirty = r2.stdout.strip() != "" if r2.returncode == 0 else False - return jsonify({"ok": True, "log": log_lines if log_lines != [""] else [], "dirty": dirty, "branch": "master"}) + git_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")) + dot_git = os.path.join(git_dir, ".git") + if not os.path.exists(dot_git): + alt = os.environ.get("AGENTSMEETING_ROOT", "") + if alt and os.path.exists(os.path.join(alt, ".git")): + git_dir = alt + dot_git = os.path.join(alt, ".git") + else: + return jsonify({"ok": True, "log": [], "dirty": False, "note": "no .git"}) + # 从 .git/logs/HEAD 读取最近提交 + reflog = os.path.join(dot_git, "logs", "HEAD") + log_lines = [] + if os.path.exists(reflog): + with open(reflog, "r", encoding="utf-8", errors="replace") as f: + lines = f.readlines() + # 取最后 10 行非空行,格式: "hash hash user ... msg" + for line in reversed(lines): + line = line.strip() + if not line: + continue + parts = line.split("\t") + msg = parts[-1] if len(parts) > 1 else line + # 取前 7 位 hash + hash_part = line.split()[1][:7] if len(line.split()) > 1 else "?" + log_lines.append(f"{hash_part} {msg}") + if len(log_lines) >= 10: + break + # 检查是否有未提交的改动:比较 .git/index 的 mtime 与 HEAD + dirty = False + head_file = os.path.join(dot_git, "HEAD") + index_file = os.path.join(dot_git, "index") + if os.path.exists(head_file) and os.path.exists(index_file): + try: + dirty = os.path.getmtime(index_file) > os.path.getmtime(head_file) + except: + pass + return jsonify({"ok": True, "log": log_lines, "dirty": dirty, "branch": "master", "source": "reflog"}) except Exception as e: return jsonify({"ok": False, "error": str(e), "log": [], "dirty": False}) @@ -681,16 +704,16 @@ def api_metagrowth(): entry = json.loads(line) if entry.get("status") == "completed": completed_fixes += 1 - # 统计 git 提交次数(用作开发活动指标) - git_dir = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")) + # 统计 git 提交次数(从 reflog 行数计算) + git_dir2 = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")) commit_count = 0 - try: - r = subprocess.run(["git", "rev-list", "--count", "HEAD"], - cwd=git_dir, capture_output=True, text=True, timeout=5) - if r.returncode == 0: - commit_count = int(r.stdout.strip()) - except: - pass + reflog = os.path.join(git_dir2, ".git", "logs", "HEAD") + if os.path.exists(reflog): + try: + with open(reflog, "r", encoding="utf-8", errors="replace") as f: + commit_count = sum(1 for line in f if line.strip()) + except: + pass return jsonify({ "ok": True, "status": "planned", # Phase 3 @@ -814,7 +837,7 @@ def main(): port = int(os.environ.get("DASHBOARD_PORT", 5803)) log.info(f"Dashboard starting on :{port}") print(f"[dashboard] Starting on http://127.0.0.1:{port}") - app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False) + app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False, threaded=True) if __name__ == "__main__": diff --git a/gateway/scripts/self_todo_executor.py b/gateway/scripts/self_todo_executor.py index a793f05..f44d863 100644 --- a/gateway/scripts/self_todo_executor.py +++ b/gateway/scripts/self_todo_executor.py @@ -162,7 +162,11 @@ def main(): log(f"处理: {service} — {issue}") success, detail = execute_fix(entry) - if success: + # "another instance is already running" = 服务已在正常运行,不算失败 + if not success and "another instance is already running" in detail: + mark_todo(entry, "completed", "already_running") + log(f" ✅ {service}: 已在运行,无需修复 ({detail[:60]})") + elif success: mark_todo(entry, "completed", detail) log(f" ✅ {service}: 修复成功 ({detail})") else: