fix: cmd_flow 同步 org + cmd_done 写入 outputMeta + STATE_ORG_MAP 补全 Next + 心跳阈值调整

1. cmd_flow 流转时同步更新 org=to_dept 并记录 agent 归属,修复看板流转
   后仍显示旧部门的问题(#149 根因之一)
2. cmd_done 完成时立即写入 outputMeta,不再依赖异步补充
3. STATE_ORG_MAP 补全 'Next': '尚书省',修复 Next 状态 org 字段为空
4. 心跳阈值从 3/10min 调整为 5/15min,减少误报

Refs #162, Fixes #149
This commit is contained in:
cft0808
2026-03-25 22:26:33 +08:00
parent 0de1a54f20
commit 362e1ae6b8
2 changed files with 19 additions and 4 deletions

View File

@@ -29,6 +29,7 @@
# 🔥 实时进展汇报Agent 主动调用,频率不限)
python3 kanban_update.py progress JJC-20260223-012 "正在分析需求拟定3个子方案" "1.调研技术选型|2.撰写设计文档|3.实现原型"
"""
import datetime
import json, pathlib, sys, subprocess, logging, os, re
_BASE = pathlib.Path(__file__).resolve().parent.parent
@@ -43,7 +44,8 @@ from file_lock import atomic_json_read, atomic_json_update # noqa: E402
from utils import now_iso # noqa: E402
STATE_ORG_MAP = {
'Taizi': '太子', 'Zhongshu': '中书省', 'Menxia': '门下省', 'Assigned': '尚书省',
'Taizi': '太子', 'Zhongshu': '中书省', 'Menxia': '门下省',
'Assigned': '尚书省', 'Next': '尚书省',
'Doing': '执行中', 'Review': '尚书省', 'Done': '完成', 'Blocked': '阻塞',
}
@@ -261,14 +263,19 @@ def cmd_state(task_id, new_state, now_text=None):
def cmd_flow(task_id, from_dept, to_dept, remark):
"""添加流转记录(原子操作)"""
clean_remark = _sanitize_remark(remark)
agent_id = _infer_agent_id_from_runtime()
agent_label = _AGENT_LABELS.get(agent_id, agent_id)
def modifier(tasks):
t = find_task(tasks, task_id)
if not t:
log.error(f'任务 {task_id} 不存在')
return tasks
t.setdefault('flow_log', []).append({
"at": now_iso(), "from": from_dept, "to": to_dept, "remark": clean_remark
"at": now_iso(), "from": from_dept, "to": to_dept, "remark": clean_remark,
"agent": agent_id, "agentLabel": agent_label,
})
# 同步更新 org使看板能正确显示当前所属部门
t['org'] = to_dept
t['updatedAt'] = now_iso()
return tasks
atomic_json_update(TASKS_FILE, modifier, [])
@@ -290,6 +297,14 @@ def cmd_done(task_id, output_path='', summary=''):
"at": now_iso(), "from": t.get('org', '执行部门'),
"to": "皇上", "remark": f"✅ 完成:{summary or '任务已完成'}"
})
# 同步设置 outputMeta避免依赖 refresh_live_data.py 异步补充
if output_path:
p = pathlib.Path(output_path)
if p.exists():
ts = datetime.datetime.fromtimestamp(p.stat().st_mtime).strftime('%Y-%m-%d %H:%M:%S')
t['outputMeta'] = {"exists": True, "lastModified": ts}
else:
t['outputMeta'] = {"exists": False, "lastModified": None}
t['updatedAt'] = now_iso()
return tasks
atomic_json_update(TASKS_FILE, modifier, [])

View File

@@ -55,9 +55,9 @@ def main():
pass
if age_sec is None:
t['heartbeat'] = {'status': 'unknown', 'label': '⚪ 未知', 'ageSec': None}
elif age_sec < 180:
elif age_sec < 300:
t['heartbeat'] = {'status': 'active', 'label': f'🟢 活跃 {int(age_sec//60)}分钟前', 'ageSec': int(age_sec)}
elif age_sec < 600:
elif age_sec < 900:
t['heartbeat'] = {'status': 'warn', 'label': f'🟡 可能停滞 {int(age_sec//60)}分钟前', 'ageSec': int(age_sec)}
else:
t['heartbeat'] = {'status': 'stalled', 'label': f'🔴 已停滞 {int(age_sec//60)}分钟', 'ageSec': int(age_sec)}