附录 A:源码导航与阅读路线
A.1 先建立五层目录地图
multica-0.4.10/
├── server/
│ ├── cmd/ # Server、CLI、Migration、Backfill 入口
│ ├── internal/ # 私有控制平面与 Daemon 实现
│ ├── pkg/ # Agent、Protocol、DB、Redaction 等可复用包
│ └── migrations/ # PostgreSQL 演进历史
├── packages/
│ ├── core/ # Headless API、Query、Store、Schema、Realtime
│ ├── ui/ # 无业务 Core 依赖的视觉 Primitive
│ └── views/ # 跨 Web/Desktop 共享业务 View
├── apps/
│ ├── web/ # Next.js Host
│ ├── desktop/ # Electron Host + Daemon 管理
│ ├── mobile/ # 独立 Expo/React Native 实现
│ └── docs/ # 产品文档站
├── deploy/helm/multica/ # Kubernetes Chart
├── .github/workflows/ # CI/Release
├── Dockerfile* # Backend/Web Image
└── docker-compose*.yml # 本地与 Self-host
阅读时先判断问题属于:
- 控制平面;
- 执行平面;
- 交互平面;
- 外部集成;
- 运维平面。
否则很容易在同名的 Task、Session、Runtime、Message 间来回跳。
A.2 最短架构阅读路线
第一次只读这些文件:
- README.md:产品表面与启动方式;
- server/cmd/server/main.go:Server 组合根;
- server/cmd/server/router.go:Middleware、Handler 与 Route;
- server/internal/service/task.go:任务状态机;
- server/internal/daemon/daemon.go:本地执行主循环;
- server/pkg/agent/agent.go:Provider 抽象;
- packages/core/api/client.ts:前端 HTTP 边界;
- packages/core/realtime/use-realtime-sync.ts:前端事件一致性;
- packages/views/issues:共享业务 UI;
- apps/web/app/[workspaceSlug]:Route-driven Host。
这条路线先建立控制流,再补数据模型。若先从 262 个 Migration 逐个读,成本很高且缺少产品语义。
A.3 Server 启动问题看哪里
| 问题 | 首要文件 | 关键内容 |
|---|---|---|
| Server 启动了什么 | cmd/server/main.go | Pool、Redis、Bus、Worker、Shutdown |
| Route 在哪里注册 | cmd/server/router.go | Chi Route Group 与 Handler Wiring |
| Health 为何失败 | cmd/server/health.go | DB Ping、完整 Migration Set |
| DB Pool 为什么慢 | cmd/server/dbstats.go | Pool 参数与周期统计 |
| Runtime 被标离线 | cmd/server/runtime_sweeper.go | Heartbeat/Liveness 与 Sweeper |
| Migration 卡住 | cmd/migrate/main.go | Advisory Lock、Hook、执行顺序 |
| 配置来自哪里 | docker-compose.selfhost.yml | 主要环境变量与默认值 |
A.4 认证与 Workspace 问题看哪里
| 问题 | 首要文件 |
|---|---|
| JWT/PAT/Task Token 分流 | middleware/auth.go |
| Daemon Token 与兼容路径 | middleware/daemon_auth.go |
| Workspace Slug/ID 优先级 | middleware/workspace.go |
| Token 生成与 Hash | auth/jwt.go |
| Cookie 与登录 | handler/auth.go |
| PAT 缓存 | internal/auth |
| Owner/Human Actor Guard | handler/actor_guards.go |
| Rate Limit/代理 IP | middleware/ratelimit.go |
排障时同时记录 Token Prefix、Auth Path、Workspace ID 与 Actor Source。只说“401”信息不足。
A.5 Issue、Comment 与触发问题看哪里
| 问题 | 首要文件 | 搜索词 |
|---|---|---|
| Issue CRUD/Assignment | handler/issue.go | CreateIssue、Assign、shouldEnqueue |
| Comment 创建与回复 | handler/comment.go | CreateComment |
| Mention 解析 | handler/comment.go | computeCommentAgentTriggers |
| Mention 权限 | handler/comment.go | canInvokeAgent |
| 线程 Root/Reply | queries/comment.sql | GetThreadRoot |
| Issue Service | service/issue.go | EnqueueTask |
| Trigger Outcome UI | core/issues | trigger outcome |
先确认 Comment 是否已写库,再确认 Trigger Outcome。不要把“评论成功”与“Agent 入队成功”当同一个状态。
A.6 Task 卡住看哪里
queued
- service/task.go:Enqueue、Notify、Claim;
- queries/agent.sql:Candidate、Priority、SKIP LOCKED;
- handler/daemon.go:Daemon Claim Endpoint;
- daemon/wakeup.go:控制连接与 Wakeup;
- daemon/wsrpc.go:WS-first Claim。
dispatched
- daemon/daemon.go:Prepare Lease、handleTask、runTask;
- daemon/execenv:Prepare/Reuse;
- daemon/repocache:Clone/Worktree;
- daemon/local_directory.go:路径锁与安全检查。
running
- pkg/agent:Provider Parser/Process;
- daemon/daemon.go:Inactivity、Cancel、Message Batch;
- daemon/client.go:Report/Terminal Retry;
- handler/daemon.go:Task Message 与 Callback。
terminal 但投影异常
- service/task.go:CompleteTask/FailTask;
- queries/chat.sql:Chat Input/Assistant Message;
- queries/task_usage.sql:用量;
- queries/task_message.sql:执行轨迹。
A.7 Daemon 启动与 Runtime 问题看哪里
| 问题 | 首要文件 |
|---|---|
| 配置默认/Env | daemon/config.go |
| Daemon 构造与 Run | daemon/daemon.go |
| Runtime 注册/重注册 | daemon/daemon.go |
| API Client | daemon/client.go |
| WS Control | daemon/wakeup.go |
| Reconcile | daemon/reconcile.go |
| 本地健康端点 | daemon/health.go |
| 自更新 | daemon/auto_update.go |
| 磁盘统计/GC | daemon/diskusage.go、daemon/gc.go |
A.8 执行环境问题看哪里
| 子问题 | 文件 |
|---|---|
| Fresh Prepare/Reuse | execenv/execenv.go |
| 可杀死 Helper | execenv/isolation.go |
| Task Env/Marker | execenv/context.go |
| Sidecar 清理 | execenv/sidecar_manifest.go |
| Runtime 指令文件 | execenv/runtime_config.go |
| Codex HOME | execenv/codex_home.go |
| Codex Sandbox | execenv/codex_sandbox.go |
| Hermes HOME | execenv/hermes_home.go |
| OpenClaw Config | execenv/openclaw_config.go |
| Repo Cache | daemon/repocache |
任何“Cleanup”代码都要先分清 Managed Environment 与 Local Directory,后者必须保留用户内容。
A.9 增加或修复 Provider 看哪里
入口是 pkg/agent/agent.go 的 Backend Factory。
当前 Provider 文件通常按名称分开:
- Claude:claude.go;
- Codex:codex.go;
- Cursor:cursor.go;
- Pi:pi.go;
- OpenCode:opencode.go;
- OpenClaw:openclaw.go;
- Hermes:hermes.go;
- Copilot:copilot.go;
- 其他文件位于同目录。
扩展时还要同步:
- Model Listing:models.go;
- Thinking 映射:thinking.go;
- Daemon Binary Discovery/Version;
- Provider HOME/Skill/MCP;
- Prompt 走 stdin 还是 argv;
- Windows Launcher;
- Protocol Fixture 与 Terminal Error;
- Frontend Provider Schema/Icon。
A.10 Context、Prompt 与 Session 看哪里
| 问题 | 文件 |
|---|---|
| Claim Payload 字段 | daemon/types.go |
| Opening Prompt | daemon/prompt.go |
| Task Snapshot 组装 | handler/daemon.go |
| Prior Session 查询 | queries/agent.sql |
| Session Poison | daemon/poisoned.go |
| Thread Name | daemon/thread_name.go |
| Agent Template | internal/agenttmpl |
Prompt Bug 常常不是字符串问题,而是 Claim Payload 缺字段、Resume 选错 Session 或 Context Snapshot 时机错误。
A.11 Skill、MCP 与 Connected App 看哪里
| 子系统 | 文件 |
|---|---|
| Skill CRUD/Import | handler/skill.go |
| Archive Import | handler/skill_import_archive.go |
| Skill Bundle Wire | pkg/skillbundle |
| Daemon Skill Cache | daemon/skill_cache.go |
| Runtime Local Skill | daemon/local_skills.go |
| Runtime MCP | daemon/runtime_mcp.go |
| Connected App Schema | runtimeapps |
| Composio Adapter | integrations/composio |
A.12 Realtime 与缓存问题看哪里
Server
- events/bus.go:同步 Bus;
- realtime:Browser Hub/Redis;
- daemonws:Daemon Control Hub;
- pkg/protocol/events.go:Event 名;
- pkg/protocol/messages.go:WS Message Shape。
Frontend
- core/realtime:连接与 Cache Coordinator;
- use-realtime-sync.ts:全局订阅;
- issues/cache-coordinator.ts:Issue Cache;
- chat/queries.ts:Task Message Seq Merge;
- types/events.ts:前端 Event Type。
查缓存 Bug 时同时检查 Event Payload 是否携带 Workspace/Issue/Chat Session ID,以及 Query Key 是否包含 Workspace Namespace。
A.13 Web、Desktop、Mobile 问题看哪里
Web
- Route:apps/web/app/[workspaceSlug];
- Host Adapter:apps/web/platform;
- Feature/Marketing 与业务 View 分开。
Desktop
- 主进程:apps/desktop/src/main;
- Preload:apps/desktop/src/preload;
- Renderer:apps/desktop/src/renderer;
- Daemon 管理:daemon-manager.ts;
- CLI Bootstrap:cli-bootstrap.ts;
- Updater:updater.ts。
Mobile
Mobile 不是直接复用 Views:
- API:apps/mobile/data/api.ts;
- Schema:apps/mobile/data/schemas.ts;
- Query/Mutation:apps/mobile/data;
- Realtime:apps/mobile/data/realtime;
- Secure Storage:secure-storage.ts;
- Screen:apps/mobile/app。
修改共享 API Contract 时必须分别检查 Core Schema 与 Mobile Schema。
A.14 Chat、通知与外部渠道看哪里
| 子系统 | 文件 |
|---|---|
| Chat API/Projection | handler/chat.go |
| Chat SQL | queries/chat.sql |
| Inbox | handler/inbox.go |
| Notification Listener | cmd/server/notification_listeners.go |
| Channel Engine | integrations/channel |
| Slack | integrations/slack |
| Lark/Feishu | integrations/lark |
| Channel SQL/Dedup | queries/channel.sql |
| CLI Chat Read | cmd_chat.go |
外部消息丢失优先沿 Message ID → Dedup Claim → Identity Binding → Chat Message → Debounced Trigger → Task 查。
A.15 Squad 看哪里
- Handler:handler/squad.go;
- Service 编排:service/task.go、service/issue.go;
- No-action 协议:service/squad_no_action.go;
- Task Leader/Worker 路由:service/task.go;
- SQL:queries/squad.sql;
- CLI:cmd_squad.go;
- Frontend:core/squads、views/squads。
调试协作循环时保留 Leader Task、Worker Task、Trigger Comment、Source Task 与 Deferred Escalation 的所有 ID。
A.16 Autopilot 与 Webhook 看哪里
- Handler:handler/autopilot.go;
- Webhook:handler/autopilot_webhook.go;
- Service:service/autopilot.go;
- Scheduler:internal/scheduler;
- SQL:queries/autopilot.sql、queries/webhook_delivery.sql;
- CLI:cmd_autopilot.go;
- Frontend:core/autopilots、views/autopilots。
Webhook 返回 Accepted 只表示 Admission/Run 已持久化;Delivery Worker 与实际 Task仍可能随后失败。
A.17 GitHub/VCS 看哪里
GitHub App
Token-based VCS
查 PR 状态倒退时比较 Provider Event Timestamp、持久 Row Updated At 与 Monotonic Upsert 条件。
A.18 CLI 问题看哪里
- Root/Cobra:cmd/multica/main.go;
- Command:server/cmd/multica;
- Config:internal/cli/config.go;
- HTTP Client:internal/cli/client.go;
- Error/Exit Code:internal/cli/errors.go;
- Update:internal/cli/update.go。
任务内 CLI 身份问题重点看 newAPIClient、resolveToken、resolveWorkspaceID 与 Daemon Task Marker。
A.19 数据库演进怎么读
推荐顺序:
- pkg/db/queries:先从业务 Query理解当前访问模式;
- pkg/db/generated/models.go:看当前 Row Shape;
- migrations:只追相关表的演进;
- 对照 Handler/Service 的事务边界;
- 最后看 Test Fixture。
不要从旧 Migration中的外键/级联规则直接推断当前新表规范;仓库约束明确要求新设计减少数据库 FK/Cascade,由 Service 维护跨域一致性。
A.20 测试与部署看哪里
| 问题 | 文件 |
|---|---|
| 本地总入口 | Makefile |
| Go Test Wrapper | scripts/test-go.sh |
| Web/Go CI | .github/workflows/ci.yml |
| Mobile CI | .github/workflows/mobile-verify.yml |
| Release | .github/workflows/release.yml |
| Compose | docker-compose.selfhost.yml |
| Helm | deploy/helm/multica |
| Metrics | internal/metrics |
A.21 实用搜索命令
在 multica-0.4.10 根目录运行:
# 找一个 HTTP Route 的注册与 Handler
rg -n '"/api/.+keyword|func \(h \*Handler\).*Keyword' server
# 找一个事件的生产者与消费者
rg -n 'task:completed|EventTaskCompleted' server packages apps
# 找一个数据库 Query 的定义与调用
rg -n 'CreateAgentTask|ClaimAgentTask' server/pkg/db/queries server/internal
# 找状态写入
rg -n "status = 'running'|Status:.*running|EventTaskRunning" server
# 找全部环境变量
rg -o 'os\.Getenv\("[A-Z0-9_]+"\)|os\.LookupEnv\("[A-Z0-9_]+"\)' server \
| sort -u
# 找 Provider 分支
rg -n 'provider ==|switch provider|case "codex"|case "claude"' server/internal/daemon server/pkg/agent
# 找 Frontend Query Key 与失效点
rg -n 'queryKey:|invalidateQueries|setQueryData' packages/core
# 找跨 Workspace 风险点
rg -n 'WorkspaceID|workspace_id|X-Workspace' server/internal/handler server/internal/service
# 找并发所有权语句
rg -n 'FOR UPDATE|SKIP LOCKED|advisory_lock|claim_token|lease' server
# 找输入长度限制
rg -n 'MaxBytesReader|LimitReader|max.*Bytes' server/internal/handler
A.22 一次代码改动的追踪模板
若要增加一个业务字段:
Migration
→ sqlc Query / Generated Model
→ Handler Request/Response
→ Service Transaction/Event
→ Protocol Event Payload
→ Core Zod/Type
→ Query Key/Mutation/Realtime
→ Shared View
→ Web/Desktop Host
→ Mobile 独立 Schema/Screen
→ CLI(若暴露)
→ Tests/Docs
若要增加一个任务能力:
Agent/Runtime 配置
→ Task 入队快照
→ Claim Response
→ daemon.Task
→ ExecEnv Materialization
→ Prompt/Provider Args
→ Message/Usage/Terminal
→ UI/CLI
中间任何一层遗漏,常见结果是“配置能保存但运行看不到”或“Server发了字段但旧客户端解析丢失”。
A.23 推荐专题路线
后端开发者
01 → 03 → 04 → 05 → 06 → 12 → 20 → 21。
Daemon/Provider 开发者
01 → 06 → 07 → 08 → 09 → 10 → 11 → 19 → 21。
前端开发者
02 → 04 → 05 → 12 → 13 → 14 → 15 → 21。
平台/SRE
03 → 04 → 06 → 07 → 12 → 17 → 20 → 21。
集成开发者
04 → 05 → 11 → 12 → 15 → 17 → 18 → 20。
多 Agent 工作流开发者
05 → 06 → 10 → 16 → 17 → 21。
A.24 阅读源码时的五个防误判提示
- 目录标签与 package version不同:本快照目录是 0.4.10,根 package.json 仍是 0.2.0。
- Task、Session、Chat Session不同:先看字段归属。
- Event 不等于事实源:事件可能重放、丢失或乱序。
- Provider 能力不完全对称:同一 Backend Interface 后仍有协议分支。
- Mobile 不是 Core/Views 的薄 Host:API Contract变更需要单独更新。
附录 B 将这些对象、状态和不变量压成速查表。