附录 B:术语、状态机与不变量速查
本附录不是新的功能介绍,而是前 21 章的“压缩索引”。当界面、API、数据库、Daemon 和 Agent CLI 对同一件事使用不同名字时,先回到这里确认对象、状态和责任边界,再沿源码链接下钻。
1. 为什么 Multica 特别需要一份术语表
Multica 同时横跨协作产品、任务调度、机器运行时、Agent 协议、代码仓库和外部集成。许多词在日常交流中可以互换,但在实现中不能互换:
- “Agent 在线”可能是协作者对象存在、Runtime 在线,或某台 Daemon 正在连接;
- “任务开始”可能指记录已创建、已被调度、已被 Runtime 接收,或 Agent 子进程真的开始执行;
- “会话”可能指 Multica Chat Session,也可能指上游 Provider Session;
- “完成”只说明某个状态机抵达终态,不自动代表代码已经提交、推送、合并或部署。
这类歧义会直接造成错误的查询、错误的告警和错误的恢复动作。下面先给出最重要的对象关系。
2. 核心领域对象
| 术语 | 精确定义 | 不是什么 | 主要落点 |
|---|---|---|---|
| Workspace | 多租户、权限、数据查询和事件订阅的第一边界 | 不是单纯的 UI 分组 | 服务查询、认证中间件、所有 workspace-scoped 资源 |
| User | 全局账号身份 | 不等于某个 Workspace 中的权限 | 认证与个人资料 |
| Member | User 在某个 Workspace 中的成员关系与角色 | 不是独立登录账号 | Workspace 授权 |
| Agent | 可被分配工作、带 Provider 配置与协作身份的持久对象 | 不是进程,也不保证在线 | Agent service、数据库 agent 记录 |
| Daemon | 运行在某台机器、连接服务器并执行任务的长生命周期进程 | 不是 Agent,也不是单个 Task | cmd/daemon、Daemon WebSocket |
| Runtime | 某 Workspace 内 Agent、Provider、Profile 与执行位置的注册关系 | 不是操作系统进程本身 | Runtime service、调度约束 |
| Task | 一次不可变历史意义上的执行尝试;重试通常创建子 Task | 不是 Issue,也不是 Provider Session | tasks、Task service |
| Provider Session | Claude、Codex、ACP 等上游执行器用于续接上下文的会话标识 | 不是 Multica Chat Session | Agent backend、task session 字段 |
| Chat Session | Multica 产品中的一段用户与 Agent 对话 | 不等于上游模型会话 | Chat service、前端 Chat 状态 |
| Issue | 可被分配、评论、追踪状态的协作工作项 | 不等于执行尝试 | Issue service |
| Comment Thread | Issue 中触发、补充和追问任务的协作上下文 | 不是 Task message 流 | Comment / Issue trigger |
| Task Message | Agent 执行期间产生的规范化增量消息 | 不是普通 Issue 评论 | Task event/message persistence |
| Project | Workspace 内组织 Issue、资源与视图的产品对象 | 不是 Git 仓库的同义词 | Project service |
| Repository | VCS 仓库元数据和远端协作对象 | 不必然等于本地工作目录 | GitHub/VCS service |
| Workdir | 某次执行实际读写代码的位置 | 不等于仓库裸缓存 | Daemon environment |
| Env Root | Multica 管理执行环境时的根目录 | 不是用户任意指定目录 | Environment manager |
| Bare Cache | 为减少重复 clone 而保存的裸仓库缓存 | 不是 Agent 的可编辑工作树 | Repo cache |
| Worktree | 从缓存或仓库为任务准备的可编辑检出 | 不是永久业务记录 | Repo checkout / GC |
| Skill | Workspace 中可分发、启停、版本化的能力包 | 不等于 MCP Server | Skill service |
| Runtime Local Skill | Daemon 在本机发现、可上报的 Skill | 不保证已安装到 Workspace | Daemon skill discovery |
| MCP Server | 向 Agent 暴露工具的 Model Context Protocol 服务 | 不等于 Connected App | Prompt/runtime capability assembly |
| Connected App | OAuth 或第三方平台连接,为 Skill/MCP 提供外部能力 | 不等于 MCP 协议本身 | Connected App service |
| Squad | Leader 与 Worker Agent 的协作拓扑 | 不是一个共享进程 | Squad service |
| Autopilot | 定时或 webhook 驱动的自动化定义 | 不是一次执行 | Autopilot service |
| Autopilot Trigger | 触发条件和入口配置 | 不是调度后的 Run | Trigger persistence |
| Rule Version | Autopilot 规则的不可变版本快照 | 不是可直接执行的 Task | Rule version persistence |
| Autopilot Run | 一次自动化编排实例,可能创建 Issue 或直接建 Task | 不等于其下游 Task | Autopilot run service |
| Webhook Delivery | 一次外部 webhook 的接收、验签、去重与处理记录 | 不代表业务已成功完成 | Webhook delivery queries |
| Event Bus | 提交后向实时客户端传播变化的通知通道 | 不是权威数据存储 | In-process/Redis bus |
| Browser WebSocket | 面向 UI 的 workspace 事件订阅 | 不是 Daemon 控制通道 | WebSocket handler |
| Daemon WebSocket | Server 与执行节点之间的调度、心跳和 RPC 通道 | 不是浏览器事件流 | Daemon protocol |
2.1 三个最容易混淆的对象
判断问题时可用四个问题拆开:
- Agent 记录是否存在且可被当前 Workspace 使用?
- 是否有满足 Provider/Profile/执行模式的 Runtime?
- 承载 Runtime 的 Daemon 是否在线并有并发容量?
- 当前 Task 到底处于排队、已派发还是已运行?
3. Task 状态机
Task 是整个系统最重要的持久状态机。状态定义分散在 SQL 查询、Task service、Daemon 协议和前端展示中,因此不能只看一个枚举。
| 状态 | 含义 | 谁推进 | 可否视为正在执行 |
|---|---|---|---|
deferred | 因重试退避等原因延后,尚未进入可领取队列 | Task service / 延迟调度 | 否 |
queued | 已具备调度资格,等待合适 Runtime 领取 | Server claim loop | 否 |
dispatched | Server 已把领取权交给某 Runtime,并建立 claim fencing | Server + Daemon 握手 | 尚不能保证 |
waiting_local_directory | 需要用户本地目录,Daemon 正等待目录准备或授权 | Daemon / 本地目录流程 | 否 |
running | Daemon 已确认开始执行 | Daemon | 是 |
completed | 本次执行成功终止 | Daemon / Task finalization | 终态 |
failed | 本次执行失败终止,并记录结构化失败原因 | Daemon、Server recovery | 终态 |
cancelled | 被用户或系统取消 | API、Daemon、reconcile | 终态 |
3.1 状态机必须记住的约束
queued只表示可被领取,不表示某台机器已经收到任务。dispatched是所有权转移的中间态,不等于 Agent 子进程已运行。- 只有 Daemon 确认实际启动后才进入
running。 completed、failed、cancelled是终态。- 重试不应把原 Task 从终态改回
queued;它创建带父子关系的新 Task,从而保留审计历史和尝试预算。 - claim 最终化失败时,
dispatched可以通过严格的比较并交换条件回退到queued;这不是普通业务状态迁移。 - stale dispatch 的回收依赖 claim generation、派发时间和当前状态,不能只用“最后更新时间过旧”粗暴重派。
- 终态写入必须带状态条件,避免完成、失败与取消互相覆盖。
3.2 “成功”到底成功了什么
Task completed 只表示 Agent backend 返回了平台认可的成功结果,并完成 Task 收尾。它不自动保证:
- 修改已形成 Git commit;
- commit 已 push 到远端;
- Pull Request 已创建;
- CI 已通过;
- PR 已合并;
- 生产环境已部署;
- Issue 已进入
done。
这些结果应由 VCS、Issue、CI 或部署系统各自的状态与证据确认。
3.3 Task 事件名称
实时层围绕 Task 常见的事件/阶段包括:
| 事件或阶段 | 用途 |
|---|---|
task:queued | 新任务进入队列 |
task:dispatch | 向 Daemon 下发任务 |
task:waiting_local_directory | 等待用户本地目录 |
task:running | 已确认开始执行 |
task:progress | 进度或心跳类变化 |
task:message | 规范化 Agent 消息增量 |
task:completed | 成功终态 |
task:failed | 失败终态 |
task:cancelled | 取消终态 |
事件名是通知契约;数据库 Task 行仍是权威状态。
4. Runtime、Daemon 与连接状态
4.1 Runtime 在线状态
Runtime 面向产品通常呈现为:
online:存在有效 Daemon 连接和心跳,可参与调度;offline:无有效承载连接,不应继续分配新工作。
4.2 Daemon 本地健康状态
CLI/本地控制面还可能展示:
starting:进程已启动,尚未完成连接或就绪;running:本地进程健康;stopped:本地进程未运行。
这套本地生命周期与 Server 视角的 Runtime online/offline 不等价。网络分区时可能出现“本地进程 running,但 Server 已判定 Runtime offline”。
4.3 心跳与失联恢复
失联恢复必须同时处理两类事实:
- Runtime 是否还能承接新任务;
- 已处于
dispatched/running的 Task 是否需要失败、回收或重试。
5. Agent backend 与消息协议速查
5.1 支持的 Provider 标识
当前 Agent 注册层可见的 Provider 标识包括:
| Provider | Provider | Provider | Provider |
|---|---|---|---|
claude | codebuddy | codex | copilot |
opencode | deveco | openclaw | hermes |
pi | cursor | kimi | kiro |
antigravity | qoder | traecli | grok |
qwen |
注册入口见 server/pkg/agent/agent.go。
5.2 协议族而非单一协议
| 协议族 | 代表 Provider | 适配难点 |
|---|---|---|
| Stream JSON | Claude、CodeBuddy、Qwen、Cursor | 增量事件、工具调用配对、最终结果判定 |
| App Server JSON-RPC | Codex | 初始化、线程/turn 生命周期、JSON-RPC 相关性 |
| ACP | Hermes、Kimi、Kiro、Qoder、Trae CLI、Grok | capability 协商、session load、MCP transport |
| Run JSON | OpenCode、DevEco | 不同事件 schema 和 provider-executed tool |
| 独立 JSON 协议 | Copilot、OpenClaw、Pi | 各自的消息与会话语义 |
| transcript / 非交互执行 | Antigravity | 日志解析、终态错误提升 |
Provider 的共同点不是命令行参数,而是最终都被归一化为平台消息和结果。
5.3 统一消息类型
| 类型 | 含义 |
|---|---|
text | 面向用户的自然语言输出 |
thinking | 推理或计划型内容;展示与持久化需服从产品策略 |
tool-use | Agent 发起工具调用 |
tool-result | 工具执行结果 |
status | 生命周期或进度状态 |
error | 明确错误消息 |
log | 诊断日志,不一定面向最终用户 |
归一化层要维持序列顺序、工具调用关联、时间戳单调性和终态唯一性。
5.4 backend 结果状态
Provider 适配器常见最终结果包括:
completedfailedabortedtimeoutcancelled
它们是 Agent backend 结果,不应未经转换就直接当作 Task 数据库状态。Task service 负责映射、分类、重试和最终化。
6. 结构化失败原因
失败原因定义和分类入口见 server/pkg/taskfailure/failure.go 与 server/pkg/taskfailure/classify.go。
6.1 平台侧失败
| 原因码 | 典型含义 | 优先检查 |
|---|---|---|
queued_expired | 长时间没有可用 Runtime 或容量 | Runtime 在线、Provider/Profile 匹配、并发上限 |
runtime_offline | 承载 Runtime 离线 | Daemon 连接、心跳、网络 |
runtime_recovery | 失联后的平台恢复收尾 | reconcile 日志、claim generation |
timeout | 平台任务超时 | Task deadline、Agent 是否仍有输出 |
iteration_limit | 超过允许迭代次数 | prompt 复杂度、工具循环 |
agent_blocked | Agent 明确阻塞 | 阻塞原因、缺少用户输入或权限 |
api_invalid_request | API 请求本身不合法 | handler validation、请求参数 |
6.2 Agent / Provider 侧失败
| 原因码 | 典型含义 | 是否常适合自动重试 |
|---|---|---|
agent_error.provider_auth_or_access | 登录、API key、组织或模型访问权限 | 否,先修复凭据/权限 |
agent_error.provider_quota_limit | 余额、额度或用量上限 | 通常否 |
agent_error.provider_capacity_or_rate_limit | 429/529、上游拥塞 | 是,带退避 |
agent_error.provider_server_error | Provider 5xx 或内部错误 | 通常是,带上限 |
agent_error.provider_network | 断流、DNS、连接拒绝、网络超时 | 是,按预算退避 |
agent_error.process_failure | CLI 非零退出或进程异常 | 视 stderr 与可执行文件而定 |
agent_error.empty_or_unparseable_output | 输出为空或协议解析失败 | 先检查版本和适配器 |
agent_error.agent_timeout | Agent backend 自身超时 | 视任务幂等性重试 |
agent_error.context_overflow | 上下文窗口溢出 | 否;应缩减上下文或新建会话 |
agent_error.missing_config | 缺少 Provider 必需配置 | 否 |
agent_error.model_not_found_or_unavailable | 模型名无效或不可用 | 否,修正模型配置 |
agent_error.runtime_version_unsupported | CLI/Runtime 版本不兼容 | 否,升级或降级 |
agent_error.runtime_missing_executable | 找不到 Provider CLI | 否,安装并修复 PATH |
agent_error.unknown | 无法可靠归类 | 人工检查原始错误 |
“可自动重试”仍需满足 Task 的最大尝试次数、父子尝试预算和幂等性要求。
7. Autopilot 与 Webhook 状态机
7.1 Autopilot Run
当前 service 创建 Run 时通常会根据执行模式直接进入 issue_created 或 running。逻辑上可把触发到落库前看作 pending,但排障时应以数据库实际状态为准。
| 状态 | 含义 |
|---|---|
issue_created | 已创建 Issue,后续通过 Issue 触发链执行 |
running | Run-only 模式已创建/关联下游 Task |
completed | 下游结果满足成功条件 |
failed | 调度、Issue/Task 或下游执行失败 |
skipped | 规则、幂等或业务条件决定不执行 |
实现入口见 server/internal/service/autopilot.go。
7.2 Webhook Delivery
| 状态 | 含义 |
|---|---|
queued | 已通过入口校验并等待处理 |
dispatched | 某个处理者已持有 claim |
rejected | 验签或入口策略拒绝 |
ignored | 合法但不匹配触发条件 |
failed | 处理过程失败 |
Webhook HTTP 响应还可能表达 duplicate 或 skipped;它们不一定是 delivery 表中的持久状态,不能混用。
7.3 签名校验结果
| 签名状态 | 含义 |
|---|---|
not_required | 当前入口未要求签名 |
valid | 签名存在且验证通过 |
invalid | 签名存在但验证失败 |
missing | 要求签名但请求未提供 |
Webhook 被 HTTP 层接收,只能证明入口处理成功;它不证明 Run 已创建,更不证明下游 Task 成功。
8. 认证凭据与前缀
| 凭据 | 前缀/形态 | 使用者 | 作用域 |
|---|---|---|---|
| 用户 PAT | mul_ | CLI / API 用户 | 用户身份与其可访问 Workspace |
| Cloud Node PAT | mcn_ | 云执行节点 | 节点注册和受限控制面 |
| Daemon Token | mdt_ | Daemon | 机器/Runtime 连接 |
| Task Token | mat_ | 单次任务环境 | 强约束到 Task 能访问的 API |
| JWT | 无固定前缀 | Web 会话 | 用户浏览器认证 |
关键不变量:
- 凭据只用于它被设计的信任边界,不能用 Daemon token 代替用户 token;
- Task token 的 workspace、task、agent 等约束必须在服务端重新校验;
- Token 原文不得进入日志、Task message、Agent prompt 或分析事件;
- CLI profile 负责选择凭据,不改变服务端授权判断;
- 本地任务环境缺少 Task token 或任务标记时,应 fail closed,而不是回退使用用户全权凭据。
9. 实时事件与一致性
协议中的资源事件命名空间包括:
| 类别 | 资源 |
|---|---|
| 工作项 | issue、issue_metadata、comment、reaction、issue_reaction |
| 执行 | agent、task、daemon、chat、autopilot、squad |
| 工作区 | workspace、member、subscriber、activity、invitation |
| 组织 | project、project_resource、label、issue_labels、property、issue_properties、pin |
| 能力 | skill |
| 集成 | github_installation、pull_request、vcs_connection、lark_installation、slack_installation |
完整常量见 server/pkg/protocol/events.go。
9.1 Event Bus 的四条不变量
- 业务变更先持久化,事件用于传播已经成立的事实。
- 浏览器收到事件后可以增量更新,也可以失效并重取;HTTP/DB 是最终真相。
- 多实例部署必须使用跨实例 Bus,否则连接在 A 实例、写入发生在 B 实例时会漏通知。
- 事件可能重复、延迟或在断线期间丢失,消费者必须幂等并具备重同步路径。
9.2 消息顺序
Task message 需要可比较的序号或单调时间戳。Provider 原始时间不可靠时,适配层应保证平台写入顺序。前端不能仅用到达顺序推断业务因果。
10. Capability 协商
Capability 是兼容性门禁,不是装饰字段。
10.1 Daemon capability
| Capability | 含义 |
|---|---|
skill-bundles-v1 | 支持服务端下发/同步 Skill bundle |
coalesced-comments-v1 | 支持合并后的评论上下文协议 |
rpc-v1 | 支持 Daemon RPC 控制消息 |
10.2 App capability
| Capability | 含义 |
|---|---|
chat-draft-restore-v1 | 客户端能安全恢复 Chat 草稿,不需要服务端回显 prompt |
常量与注释见 server/pkg/protocol/messages.go。
兼容原则:
- Server 只有在对端声明 capability 后才发送新语义;
- 未声明时走旧协议或降级路径;
- capability 表示“理解并能正确处理”,不能仅因为字段可解析就声明;
- 新 capability 应有双向兼容测试和旧版本回退测试。
11. 并发控制与 fencing 速查
| 场景 | 主要原语 | 防止的问题 |
|---|---|---|
| 批量领取 queued Task | 事务、FOR UPDATE SKIP LOCKED | 多调度者领取同一任务 |
| Task 派发最终化 | 状态条件、claim generation、dispatched_at | 旧 Daemon 或旧派发覆盖新所有者 |
| 执行环境准备 | prepare lease | 两个执行者同时创建/清理同一 workdir |
| Autopilot scheduler | lease token + heartbeat | 多实例重复触发 |
| Webhook worker | claim token | 同一 delivery 被并行处理 |
| 外部渠道消息 | dedup/claim token | 重复投递创建重复任务 |
| Task 终态 | conditional update | complete/fail/cancel 竞态覆盖 |
| 消息持久化 | sequence / 单调时间 | 流消息乱序 |
| Skill/配置同步 | content hash / version | 无变化重复下发、旧版本覆盖新版本 |
| API 创建 | idempotency key / unique index | 客户端重试造成重复业务对象 |
11.1 fencing 的核心判断
“我曾经拥有过这个任务”不足以写入。每一次副作用都要证明:
- 当前 Task 仍处于允许该写入的状态;
- 当前 claim generation/token 仍是最新;
- 当前 Daemon/Run/Delivery 仍是所有者;
- 终态尚未被另一条路径写入。
12. 数据与多租户不变量
12.1 Workspace 边界
- 每个 workspace-scoped API 都要从认证上下文解析 Workspace,并验证 Member 关系;
- SQL 查询应显式带
workspace_id,不能只靠上层“已经查过”; - 从 Task、Issue、Agent、Project 等对象跳转时,要确认关联对象属于同一 Workspace;
- 事件订阅和 publish topic 必须带 Workspace 隔离;
- 缓存键、React Query key、幂等键也必须纳入 Workspace。
12.2 数据库约束策略
当前仓库约定倾向于在新设计中避免用外键级联承载业务语义,删除与归档由 service 显式处理。历史 migration 可能保留旧式外键,阅读时应区分“现存遗产”和“新增规则”。
12.3 审计历史
- Task 重试创建新尝试,不重写旧终态;
- Autopilot Rule 用版本快照保留当时规则;
- Webhook Delivery 保存入口、验签与处理证据;
- 需要追责的对象优先归档或追加记录,不以 hard delete 抹掉历史;
- 用户可见评论与机器执行消息分别建模,避免将诊断流污染协作历史。
13. 执行环境不变量
| 模式 | 工作目录来源 | 平台能否安全 GC | 典型风险 |
|---|---|---|---|
| 托管仓库环境 | bare cache + task worktree | 能,受租约和状态保护 | 并发 checkout、陈旧 worktree |
| 已有本地仓库 | 用户指定目录 | 只能做受限操作 | 覆盖用户未提交变更 |
| 等待本地目录 | 用户/桌面端后续提供 | 尚不能执行 | 误把 dispatched 当 running |
| 无仓库任务 | 临时环境或服务配置 | 能 | 缺少预期源码上下文 |
必须保持:
- GC 不删除 active lease、running Task 或用户自有目录;
- worktree 路径经过根目录约束和规范化,不能目录穿越;
- checkout、prepare、cleanup 都是可恢复步骤;
- 对用户仓库默认保留未提交更改,不执行破坏性 reset;
- 仓库认证材料只在必要进程环境中短暂存在;
- “目录存在”不等于“仓库处于正确 revision 且可安全执行”。
14. Prompt 与上下文不变量
Prompt 是多个受信程度不同的上下文层组装结果:
关键原则:
- 用户评论、Issue 文本、仓库文件和外部 webhook 都是不可信内容,不得覆盖系统授权边界;
- Workspace Context 不是单段 prompt,而是一组可追踪来源;
- Secret 不应写进 prompt;需要凭据的能力通过受控环境或工具调用提供;
- coalesced comments 要保留作者、顺序和触发点,不能拼接成无法区分来源的一段文本;
- Provider Session 可续接对话,但权限与工作区上下文每次任务都应重新验证;
- 上下文溢出应缩减、总结或新建会话,而不是盲目重试同一 payload。
15. 前端分层不变量
| 层 | 责任 | 不应承担 |
|---|---|---|
packages/core | 类型、API client、query keys、跨端状态与业务 hooks | 浏览器或移动端专属 UI |
packages/ui | 纯 UI 组件与设计系统 | 服务请求和业务 store |
packages/views | 可复用业务视图 | 宿主路由、宿主 store、平台 API |
| Web/Desktop host | 路由、Browser 能力、桌面桥接 | 复制 core 业务逻辑 |
| Mobile app | 移动导航、原生适配、独立宿主 | 假设 DOM 或桌面 IPC 存在 |
状态约定:
- React Query 管理服务端状态;
- Zustand 管理客户端偏好、局部交互或跨组件 UI 状态;
- query key 必须带 Workspace;
- WebSocket 用于更新/失效缓存,不能成为唯一数据源;
- API 边界通过 schema 解析;
parseWithFallback只用于有明确兼容策略的降级; views通过 props/callback 接收宿主能力,避免反向依赖应用层。
16. 一条状态该找谁负责
| 现象 | 首要责任层 | 第一证据 | 下一跳 |
|---|---|---|---|
Task 一直 queued | Server 调度 | Task 行、候选 Runtime 查询 | Runtime 在线、并发和 Provider/Profile |
Task 卡在 dispatched | Server ↔ Daemon 握手 | claim generation、Daemon WS 日志 | reconcile 与派发确认 |
卡在 waiting_local_directory | Desktop/CLI/Daemon 本地目录流程 | local-directory 请求与响应 | 路径权限和目录标记 |
已 running 但无消息 | Agent backend | 子进程、stdout/stderr、协议 parser | Provider CLI 版本与认证 |
| 显示成功但没看到代码 | 执行环境/VCS | workdir、git status、commit/push 证据 | Task output 与 VCS integration |
| UI 不刷新 | 实时层/前端缓存 | WS 事件、query key、HTTP 重取 | Redis Bus 与 workspace topic |
| Autopilot 重复运行 | scheduler 幂等 | lease token、trigger key、Run 记录 | 多实例租约与唯一约束 |
| Webhook 收到但没运行 | webhook worker/规则 | Delivery 状态、签名、匹配结果 | Autopilot Run / Task |
| Agent 显示离线 | Runtime/Daemon | Server 心跳与连接记录 | 本地 daemon status、网络 |
| 重试次数异常 | Task retry policy | 父子 Task、attempt/max_attempts | failure reason 分类 |
| 跨 Workspace 数据异常 | 授权/查询 | workspace_id 和 Member 校验 | SQL 条件、cache/query key |
17. 常见错误等式
下面这些等式全部是错的:
| 错误等式 | 正确理解 |
|---|---|
| Agent = Daemon | Agent 是协作者配置;Daemon 是机器进程 |
| Agent = Runtime | 一个 Agent 可有不同 Provider/Profile 的 Runtime |
| Runtime online = 本地进程存在 | Server 需要有效连接和心跳证据 |
| Task = Issue | Issue 是协作工作项;Task 是一次执行尝试 |
| Task = Provider Session | Task 属于平台;Session 属于上游执行器 |
| Chat Session = Provider Session | 一个是产品对话,一个是执行器续接标识 |
| Comment = Task Message | 评论属于协作历史;Task message 属于执行流 |
queued = 正在运行 | queued 仅表示等待领取 |
dispatched = Agent 已启动 | 仍需 Daemon 确认 running |
completed = 已提交/推送/部署 | 需分别查询 Git、VCS、CI、部署状态 |
| Event = 数据真相 | Event 是通知;DB/HTTP 是权威 |
| Webhook 2xx = 自动化成功 | 只证明入口已处理 |
| 本地目录存在 = 环境就绪 | 还需 revision、权限、租约与安全检查 |
| MCP = Connected App | MCP 是工具协议;Connected App 是外部连接 |
| Skill 已发现 = Skill 已安装启用 | 本地发现、Workspace 安装和 Runtime 下发是不同阶段 |
18. 阅读状态机的源码入口
| 主题 | 入口 |
|---|---|
| Task 创建、领取、运行、终态、重试 | server/internal/service/task.go |
| Task SQL 原子迁移 | server/pkg/db/queries/agent.sql |
| 失败原因与重试属性 | server/pkg/taskfailure/failure.go |
| Provider 错误分类 | server/pkg/taskfailure/classify.go |
| Daemon 协议与 capability | server/pkg/protocol/messages.go |
| 实时资源事件 | server/pkg/protocol/events.go |
| Agent backend 注册 | server/pkg/agent/agent.go |
| Autopilot Run | server/internal/service/autopilot.go |
| Webhook Delivery SQL | server/pkg/db/queries/webhook_delivery.sql |
| Runtime/Daemon 协调 | server/internal/daemon |
| 前端 query key 与 API | packages/core |
19. 排障最短路径
遇到任何“Agent 没有工作”的问题,可按这条顺序查:
不要从 UI spinner 直接推断后端状态,也不要先从 Provider 日志开始。Task 行和 claim 是跨层关联所有证据的主键。
20. 版本阅读声明
本附录对应 multica-0.4.10 源码快照。它刻意区分:
- 代码中真实持久化的状态;
- service 内部的逻辑阶段;
- HTTP 响应或 UI 展示用的状态;
- Provider backend 的原始结果。
后续版本若新增 Provider、Task 状态或 capability,应同时更新:
- 状态机及合法迁移;
- SQL 条件与并发 fencing;
- Server/Daemon 协议兼容;
- 前端 schema、query key 和展示;
- metrics label allowlist;
- 失败恢复与端到端测试;
- 本附录和相应章节。
至此,主文 21 章中的对象、状态和边界可以通过本附录快速交叉定位;若要顺序阅读源码,请配合附录 A:源码导航与阅读路线。