diff --git a/prompt_templates/review_pangtong.md b/prompt_templates/review_pangtong.md index f8d2882..c01b066 100644 --- a/prompt_templates/review_pangtong.md +++ b/prompt_templates/review_pangtong.md @@ -26,3 +26,11 @@ - 同时看审查者和被审者的论据 - 以原始任务目标为唯一准绳,不偏袒任何一方 - 给出明确裁决(approve/需要修改),不要模棱两可 + +## 需求探索 +- 收到模糊需求时,通过 checkpoint(decision/verify) 向用户提问 +- 每次只问一个核心问题,不要一次问多个 +- 问题要具体到可选项,不要问开放式问题 +- 用户回答后,把澄清后的需求写入黑板 comment +- 需求清晰后,更新任务描述(title/description),然后正常拆解执行 +- 不要在需求不清晰时就开始拆解任务 diff --git a/src/api/blackboard_routes.py b/src/api/blackboard_routes.py index f996c30..088d898 100644 --- a/src/api/blackboard_routes.py +++ b/src/api/blackboard_routes.py @@ -319,6 +319,19 @@ async def add_comment(project_id: str, task_id: str, body: Dict[str, Any]): mentions=merged_mentions) if merged_mentions: bb.record_mentions(cid, task_id, merged_mentions) + # #10: SSE 通知前端黑板有新 comment + try: + from src.api.sse_routes import get_broker + broker = get_broker() + broker.publish_sync("comment_added", { + "project_id": project_id, + "task_id": task_id, + "comment_id": cid, + "author": body["author"], + }) + except Exception: + pass + return {"ok": True, "comment_id": cid, "mentions": merged_mentions} diff --git a/src/frontend/src/store.ts b/src/frontend/src/store.ts index 4f08815..1b8235a 100644 --- a/src/frontend/src/store.ts +++ b/src/frontend/src/store.ts @@ -744,6 +744,10 @@ export function startSSE() { s.loadV2Tasks(); } _pushSseEvent({ id: `sse-${Date.now()}`, type: 'info', title: `任务更新`, message: `${data.old_status || '?'} → ${data.new_status || '?'}`, time: new Date().toISOString(), read: false, source: 'event', taskId: data.task_id, projectId: data.project_id }); + // #10: task_updated 时也刷新 TaskModal(如果正在显示) + if (s.modalTaskId === data.task_id) { + s.loadV2TaskDetail(data.task_id); + } } catch { /* ignore */ } }); _es.addEventListener('task_created', () => { @@ -775,6 +779,27 @@ export function startSSE() { _pushSseEvent({ id: `sse-${Date.now()}`, type: 'error', title: `任务失败`, message: `${data.task_id || ''} 执行失败`, time: new Date().toISOString(), read: false, source: 'event', taskId: data.task_id, projectId: data.project_id }); } catch { /* ignore */ } }); + // #10: comment_added → 刷新 TaskModal + _es.addEventListener('comment_added', (e: MessageEvent) => { + try { + const data = JSON.parse(e.data); + const s = useStore.getState(); + // 双重检查:task_id + project_id 防跨项目误刷新 + if (s.modalTaskId === data.task_id && (s.v2taskDetail as any)?._projectId === data.project_id) { + s.loadV2TaskDetail(data.task_id); + } + } catch { /* ignore */ } + }); + // #10: checkpoint_resolved → 刷新 TaskModal + _es.addEventListener('checkpoint_resolved', (e: MessageEvent) => { + try { + const data = JSON.parse(e.data); + const s = useStore.getState(); + if (s.modalTaskId === data.task_id && (s.v2taskDetail as any)?._projectId === data.project_id) { + s.loadV2TaskDetail(data.task_id); + } + } catch { /* ignore */ } + }); _es.onerror = () => { _es?.close(); _es = null;