From ef7d7f12ce445ffdac4a616f40fa483c7ea221d6 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Sat, 16 May 2026 19:02:56 +0800 Subject: [PATCH] auto-sync: 2026-05-16 19:02:56 --- docs/design/topic11-multi-project-proposal.md | 43 ------------------- 1 file changed, 43 deletions(-) diff --git a/docs/design/topic11-multi-project-proposal.md b/docs/design/topic11-multi-project-proposal.md index f054a15..d291568 100644 --- a/docs/design/topic11-multi-project-proposal.md +++ b/docs/design/topic11-multi-project-proposal.md @@ -511,49 +511,6 @@ def _get_session_id(self, agent_id: str, task_id: str) -> str: | Agent 完成回调丢失 | 计数器不归零 | 超时兜底:working 任务超过 `task_timeout` 视为完成,计数器 -1 | | _registry.yaml 并发写入 | 数据损坏 | _registry.yaml 只在 CLI 操作时读写(非 tick 热路径),tick 状态用内存 dict | -### 5.5 启动状态恢复(v2 新增) - -Daemon 进程崩溃后由 PM2 自动重启。启动时需要恢复所有项目状态。 - -**持久化层**(已天然支持,无需额外处理): -- `_registry.yaml` → 项目列表、状态、配置 -- 每个 `blackboard.db` → 任务状态(pending/working/completed/failed...) -- SQLite WAL 模式 → 崩溃时未提交的事务自动回滚,数据完整性有保障 - -**内存层**(需要恢复): -- `ActiveAgentCounter` → 重启后归零 -- `DaemonHealth` → 重启后归零 - -**恢复流程**: - -```python -def start(self): - registry = load_registry() - for project_id, meta in registry["projects"].items(): - if meta["status"] != "active": - continue - # 启动 ProjectSlot - self._start_slot(project_id, meta) - # 第一次 tick 时,_check_working_tasks() 会扫描所有 working 任务 - # 超时的 → 视为完成(decrement 不需要,因为计数器从零开始) - # 未超时的 → 继续等待(计数器会在下次 tick 重新追踪) -``` - -**working 任务的幽灵问题**: - -Daemon 崩溃时可能有 Agent 正在执行。重启后这些任务在 blackboard.db 中仍是 `working` 状态,但 Agent 子进程已经死了(Daemon 重启不等于 Agent 重启,但 Daemon 崩溃通常意味着整个环境有问题)。 - -处理策略: -1. 启动时扫描所有 working 任务 -2. 检查 Agent 子进程是否还活着(如果有 PID 记录的话) -3. 进程已死 + 超过 `task_timeout` → 标记为 `failed`(原因:"Daemon restart, agent process lost") -4. 进程已死 + 未超时 → 标记为 `failed`(保守策略:Daemon 重启后不信任幽灵任务) -5. 不尝试重新执行——用户可以手动 `retry` - -**为什么保守**:Daemon 崩溃是不正常事件。此时 Agent 子进程的状态不可预测(可能写了半个 output.json),重新执行比尝试恢复更安全。 - -**task_attempts 表**的 `attempt_index` 会递增,retry 时从新的 attempt 开始,不覆盖之前的尝试记录。 - ### 6.1 项目管理命令 ```bash