1. Task 生命周期 FSM
每条任务必经 REFLECTING。不允许 OBSERVING 直接跳 COMPLETED。终态唯一出口 ARCHIVED。
stateDiagram-v2
[*] --> RECEIVED
RECEIVED --> PLANNING: 解析成功
RECEIVED --> FAILED: 解析失败 或 权限拒绝 或 预算用尽
PLANNING --> TOOL_EXECUTING: 计划就绪
PLANNING --> AWAITING_USER: 关键参数缺失
TOOL_EXECUTING --> OBSERVING: 工具返回
OBSERVING --> TOOL_EXECUTING: 仍有未完成步骤
OBSERVING --> AWAITING_USER: 高危 或 歧义
OBSERVING --> REFLECTING: 计划完成
AWAITING_USER --> TOOL_EXECUTING: 用户批准
AWAITING_USER --> FAILED: 用户拒绝 或 超时 10min
REFLECTING --> DISTILLING: success true
REFLECTING --> FAILED: success false
DISTILLING --> COMPLETED: 写回 skill plus memory
COMPLETED --> ARCHIVED: T plus 30 天
FAILED --> ARCHIVED: T plus 30 天
ARCHIVED --> [*]
RECEIVED + PLANNING ≤ 60s AWAITING_USER 默认超时 10min REFLECTING 强制路径 无 ARCHIVED 旁路
2. Skill 生命周期 FSM
评分采用 EWMA。低于 0.3 自动 DEPRECATED。用户 correction 是最强负权信号。
2.1 状态转移
stateDiagram-v2
[*] --> DRAFT
DRAFT --> CANDIDATE: 沙箱通过
DRAFT --> DEPRECATED: 沙箱连续失败 三次
CANDIDATE --> ACTIVE: 真实成功 三次以上 且 score 0.7 以上
CANDIDATE --> DEGRADED: score 在 0.3 至 0.7
ACTIVE --> DEGRADED: score 跌入 0.3 至 0.7
DEGRADED --> ACTIVE: score 0.7 以上 且 近 5 次成功率 80 以上
DEGRADED --> DEPRECATED: score 低于 0.3 或 连续失败 5 次
DEPRECATED --> ARCHIVED: T plus 30 天 或 被合并
ACTIVE --> ARCHIVED: 被合并
CANDIDATE --> ARCHIVED: 被合并
ARCHIVED --> [*]
2.2 score 更新
| 事件 | 公式 | 权重 |
|---|---|---|
| 成功一次 | 0.9 * s + 0.1 * 1.0 | 普通 |
| 失败一次 | 0.9 * s + 0.1 * 0.0 | 普通 |
| 沙箱通过 | max(s, 0.6) | 晋级 |
| 沙箱失败 | s * 0.5 | 降级 |
| thumbs-up | min(1, s + 0.1) | 强 |
| thumbs-down | s * 0.7 | 强 |
| 用户 correction | s * 0.5 + revise | 最强 |
3. Memory 层 FSM 与 GC
L0 / L1 永久。L2 / L3 到期迁移。GC 仅清理低置信度且长期未读的条目。
stateDiagram-v2
[*] --> L3_RECENT: 任务结束写入
L3_RECENT --> L4_SKILL: 蒸馏成 skill
L3_RECENT --> L5_ARCHIVE: 90 天未读且无 skill
L3_RECENT --> GC: confidence 低于 0.2 且 60 天未读
L4_SKILL --> L5_ARCHIVE: 关联 skill 进入 ARCHIVED
L4_SKILL --> GC: confidence 低于 0.2 且 60 天未读
L5_ARCHIVE --> GC: 365 天 且 confidence 低于 0.2
L0_PERM: L0 核心规则永久
L1_PREF: L1 用户偏好仅用户撤销时删
L2_ENV: L2 环境事实 90 天 或 doctor 续期
L2_ENV --> L1_PREF: 用户提升为偏好
GC --> [*]
L3 默认 30 天 L5 默认 365 天 单条 ≤ 64 KB 写入前必经 redaction
4. ER 数据模型
三主体:Task / Skill / Memory。Auth 与 Channel 旁挂。时间字段统一 RFC3339(如 2026-05-02T17:52:00Z)。
erDiagram
TASK ||--o{ TOOL_CALL : invokes
TASK ||--|| REFLECTION : produces
TASK ||--o{ AUDIT_EVENT : emits
TASK ||--o{ COST_EVENT : accrues
REFLECTION ||--o{ SKILL : creates_or_updates
REFLECTION ||--|| MEMORY_L3 : writes
SKILL ||--o{ SKILL_VERSION : versions
SKILL ||--o{ FAILURE_PATTERN : records
SKILL ||--o{ MEMORY_L4 : linked_to
MEMORY_L3 ||--o| MEMORY_L4 : distill_into
MEMORY_L3 ||--o| MEMORY_L5 : archive
MEMORY_L4 ||--o| MEMORY_L5 : archive_when_skill_archived
AUTH_RECORD ||--o{ TOOL_CALL : authorizes
CHANNEL_SENDER ||--o{ TASK : originates
POLICY_RULE ||--o{ AUDIT_EVENT : evaluates
VAULT_ENTRY ||--o{ AUDIT_EVENT : substituted_in
TASK {
string task_id PK
string user_input_safe
string source
string selected_model
string state
string started_at
string finished_at
}
SKILL {
string id PK
string kind
int version
float score
string state
string created_from_task FK
}
MEMORY_L3 {
string id PK
string content
float confidence
string ts
string source
}
VAULT_ENTRY {
string name PK
string value_redacted
string kind
string fingerprint
string created_at
}
5. 端到端时序(单任务)
从用户输入到 ARCHIVED。注意 redactor 在三个边界点都会脱敏。
sequenceDiagram
autonumber
participant U as 用户
participant CLI as evoclaw CLI
participant RED as Redactor
participant RT as ConversationRuntime
participant PROV as Provider
participant TOOL as Tool Registry
participant SK as Skill Tree
participant MEM as Memory
participant LOG as JSONL Log
U->>CLI: 输入任务
CLI->>RED: scrub user_input
RED-->>CLI: user_input_safe
CLI->>RT: run(user_input_safe)
RT->>LOG: 写 Task 记录
loop 直到不再请求工具
RT->>PROV: stream(messages, tools)
PROV-->>RT: assistant_text + tool_calls
RT->>RED: scrub assistant_text 与 args
RED-->>RT: scrubbed
alt 有工具调用
RT->>TOOL: invoke(call)
TOOL-->>RT: result
RT->>RED: scrub result
RED-->>RT: result_safe
RT->>LOG: 写 Turn 记录
end
end
RT->>PROV: 反思回合
PROV-->>RT: ReflectionRecord
RT->>SK: 蒸馏 + upsert skill
RT->>MEM: 写 L3 记录
RT->>LOG: 写 End 记录
RT-->>CLI: final_text
CLI-->>U: 输出
6. ACP 委派循环
当 provider 是 acp:<id> 时,EvoClaw 把上游 CLI spawn 成子进程,通过 ACP 把 prompt 喂过去。
sequenceDiagram
autonumber
participant U as 用户
participant RT as ConversationRuntime
participant AP as AcpProvider
participant CHILD as 外部 CLI
participant LOG as JSONL Log
U->>RT: run(user_input_safe)
RT->>AP: stream(req)
AP->>CHILD: spawn claude --acp
AP->>CHILD: initialize 握手
CHILD-->>AP: serverInfo
AP->>CHILD: session/new
CHILD-->>AP: session_id
AP->>CHILD: session/prompt(text)
CHILD-->>AP: 最终文本
AP-->>RT: stream events
RT->>LOG: 写 Turn 与 End
Note over CHILD: kill_on_drop true 自动 reap 子进程
7. MCP 工具调用
MCP 工具在 ToolRegistry 中以 mcp__<server>__<tool> 命名。鉴权 env 模型完全看不见。
sequenceDiagram
autonumber
participant RT as ConversationRuntime
participant TR as ToolRegistry
participant W as McpToolWrapper
participant SRV as MCP Server
participant LOG as JSONL Log
Note over TR: install_all 启动期 spawn 每个 server
TR->>W: 注册 mcp_github_list_issues
RT->>TR: invoke(mcp_github_list_issues, args)
TR->>W: run(ctx, args)
W->>SRV: tools call name args
SRV-->>W: ToolCallResult content isError
W-->>TR: 渲染后的文本
TR-->>RT: scrubbed result
RT->>LOG: 写 Turn
8. 权限阶梯
权限是全序阶梯 P0 ≤ P1 ≤ … ≤ P8。默认上限 P1;渠道硬封顶 P4。每个工具描述 ≤ 80 字符。
flowchart LR
classDef p0 fill:#0f3a2a,stroke:#34d399,color:#fff
classDef p1 fill:#0f3a44,stroke:#22d3ee,color:#fff
classDef p2 fill:#1a2f4a,stroke:#5fb3ff,color:#fff
classDef p3 fill:#2a1f4a,stroke:#a78bfa,color:#fff
classDef p4 fill:#3a2f0a,stroke:#facc15,color:#fff
classDef p5 fill:#3a210a,stroke:#fb923c,color:#fff
classDef p6 fill:#3a1414,stroke:#f87171,color:#fff
classDef p7 fill:#3a1424,stroke:#ec4899,color:#fff
classDef p8 fill:#1a0014,stroke:#ec4899,color:#fff
P0[P0 只读 read_file list_dir ask_user]:::p0
P1[P1 workspace 写 write_file patch_file]:::p1
P2[P2 本地安全 shell run_shell]:::p2
P3[P3 网络 web_fetch 与 MCP]:::p3
P4[P4 渠道封顶 浏览器类操作]:::p4
P5[P5 用户目录写]:::p5
P6[P6 系统修改]:::p6
P7[P7 凭证操作]:::p7
P8[P8 生产环境]:::p8
P0 --> P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7 --> P8
9. 闭环验收矩阵(审计员清单)
evoclaw doctor closure 扫 ~/.evoclaw/logs/*.jsonl 校对每一行。所有会话每行通过才算闭环。
| # | Producer | Consumer | 不变量 |
|---|---|---|---|
| 1 | Runtime | JSONL log | 每个任务首部恰好一条 Task 记录 |
| 2 | Runtime | JSONL log | 每个任务有 ≥ 1 条 Turn 记录 |
| 3 | Redactor | Task / Turn / End | 无字段含已注册 vault 值或已知密钥模式 |
| 4 | Runtime | JSONL log | 每个任务恰好一条 End 记录 |
| 5 | Runtime | End 记录 | state 是 COMPLETED 或 FAILED,永不为空 |
| 6 | Reflection | Memory L3 | 已完成任务 → 一条 L3 写入 |
| 7 | Distillation | Skill YAML | 已完成任务 → 0 或 1 条 DRAFT skill upsert |
| 8 | CostEngine | cost.jsonl | 每条 Turn → 一条 CostEvent (best-effort) |
| 9 | Provider | Audit Bus | 预算超限 → HardStop 事件入库 |
| 10 | ACP child | OS | kill_on_drop 自动 reap,跑完无僵尸 |
| 11 | MCP child | OS | 同 #10 — 每个 spawn 出来的 server 都被 reap |
| 12 | Vault | filesystem | vault.json 在 Unix 上 chmod 600 |
| 13 | Skill EWMA | Skill 状态 | score 跨阈值 → 状态在 ≤ 1 轮内迁移 |