Skip to main content
Glama
Zorabi

Concordia

by Zorabi

Concordia

面向 Codex 与 ZCode 的 local-first MCP 多代理协作控制面,支持单机 stdio 与可选的跨机器 Redis relay。

Concordia 以结构化任务、事件、租约和 Git worktree,将“规划与验收”与“实施”分开:Codex 创建任务、回答问题、审查交付;ZCode 原子领取任务、实施、按需使用其子代理,并提交可审查的 commit 与验证证据。状态保存在协调主机的本地 SQLite;双方既可在单机直接连接,也可在都没有公网 IP 时通过 Redis 中转。

它适合在一台机器或“远程 Codex + ZCode 执行主机”的两机拓扑中,可靠地协调一个或少量 Git 仓库,不依赖 GitHub Issue 或共享在线文档。

它解决什么问题

  • 任务是契约:目标、目标仓库、允许路径、约束、验收条件与交付项均为结构化字段。

  • 事件是沟通:进度、提问、回答、心跳、失败、返工和批准都是带序号的持久事件。

  • 提交是证据:ZCode 提交的 SHA、变更文件、检查结果和风险进入任务记录,供 Codex 审查。

  • 租约防止双写:过期重领后旧执行者会被围栏拒绝,不能继续写入事件或提交。

  • worktree 隔离写入:每次领取使用独立 Git branch/worktree,避免并发任务互相污染。

  • 事件驱动唤醒代理:可选 codex-wakerzcode-waker 常驻进程在普通 Node.js 中监听事件;仅在需要审查、回答、领取或返工时启动对应代理 turn。

Related MCP server: SafeFlo

边界与非目标

当前版本面向单协调节点、同一可信用户或团队、少量并发任务。已实现 SQLite 持久化、任务状态机、Git 隔离、幂等写入、租约恢复、ZCode 插件、Codex 事件唤醒器,以及基于 Redis Streams 和角色签名的跨机器 relay。尚不提供:

  • 多用户身份、仓库级 ACL 或租户隔离;

  • 多协调节点高可用或 PostgreSQL;

  • 多个独立 ZCode 执行机之间的路径映射和 Git 对象传输;

  • Web Dashboard 或面向第三方的通用推送订阅;

  • 自动合并、推送远程 Git、发布制品或部署;

  • 强制 ZCode 使用某个子代理,或替代理制订实现计划;

  • 映射为 ZCode 原生侧边栏任务。

合并、推送、发布与生产操作须由用户或上层协调者明确执行。

架构

单机模式

Codex ── stdio MCP ─┐
                    ├── Concordia ── SQLite(任务、事件、交付物)
ZCode ── stdio MCP ─┘        │
                              ├── 目标 Git 仓库/.worktrees/<task>-zcode-a<attempt>
                              ├── codex-waker ──> Codex App Server(按事件启动审查 turn)
                              └── zcode-waker ──> ZCode CLI(按事件启动或恢复实施 turn)

跨机器 Redis 模式

Codex MCP relay client ──┐
                         ├── 出站 TLS ──> Redis Streams/response keys
ZCode MCP relay client ──┘                         │
                                                  │ 出站连接
                                      Concordia relay coordinator(ZCode/Git 主机)
                                                  ├── 本机 SQLite
                                                  └── 本机 Git 仓库与 worktrees

远程模式必须把协调器部署在持有目标 Git 仓库的执行主机上。两端只需主动连接同一 Redis,无需公网 IP 或入站端口;claim_tasksubmit_task 仍在协调主机执行本机 Git/worktree 强校验。详细部署、令牌、Codex/ZCode 配置和安全限制见 跨机器协调指南

这里有两个不同的目录:

  • Concordia 源码目录:本仓库,包含 src/、构建产物与 zcode-plugin/;例如 /absolute/path/to/concordia

  • 被管理的目标 Git 仓库:代理真正修改的业务项目;例如 /absolute/path/to/example-app。任务 workspace 必须是它的 Git 根目录。worktree 创建在这个目标仓库内,而非 Concordia 源码目录。

单机模式下,Codex 与 ZCode 可运行各自的 stdio MCP 服务进程;只要两端的 CONCORDIA_DB 指向同一绝对 SQLite 路径,便可共享状态。跨机器模式下,SQLite 只保留在协调主机本地,远程客户端通过 Redis relay 访问,禁止多台机器直接打开网络共享目录中的 SQLite 文件。

状态生命周期

DRAFT 是协议中保留的类型;当前 create_task 会直接创建并发布为 READY

READY ── claim ──> CLAIMED ── progress ──> RUNNING ── submit ──> REVIEW
                                             │                       │
                                             ├─ question ─> WAITING_INPUT
                                             │               └─ answer ─> RUNNING
                                             ├─ failed ───> FAILED
                                             ├─ cancelled ─> CANCELLED
                                             └──────────────── request_changes ─> READY(重新领取)
                                                                approve ─────────> APPROVED

终态为 APPROVEDFAILEDCANCELLED。只有 Codex 能创建、审批或要求返工;只有 ZCode 能领取和提交任务。

前置条件

  • Node.js 22.13+(使用 node:sqlite)。

  • Git,且每个目标工作区必须是可访问的 Git 仓库根目录。

  • npm。

  • 可使用 Codex 和/或 ZCode 的 MCP 功能。

  • 跨机器模式额外需要 Redis 7+ 或兼容服务;单机模式不需要 Redis 服务。

node --version
git --version
npm --version

安装、构建与运行

Concordia 源码目录执行:

npm install
npm run build
npm test

构建产生:

  • dist/src/index.js:本机 stdio MCP 服务;

  • dist/src/relay.js:运行在 ZCode/Git 主机上的 Redis relay coordinator;

  • dist/src/codex-waker.js:运行在 Codex 主机上的事件监听与 App Server 唤醒进程;

  • dist/src/zcode-waker.js:运行在 ZCode 主机上的事件监听与 ZCode CLI 唤醒进程;

  • zcode-plugin/dist/index.mjs:随 ZCode 本地插件分发的单文件 bundle。

服务使用 stdio,通常由 MCP 客户端启动。以下命令只用于验证进程可启动,随后会等待标准输入上的 MCP 客户端:

CONCORDIA_ROOTS=/absolute/path/to/example-app \
CONCORDIA_AGENT_ID=codex \
npm start

MCP 协议仅写 stdout;启动与错误日志写 stderr。默认数据库为启动目录的 .concordia/state.db。实际同时使用 Codex 和 ZCode 时,应配置同一个绝对 CONCORDIA_DB,避免不同 cwd 产生两个状态库。

若希望 Codex 在 ZCode 提交、提问或失败时自动恢复审查任务,而不是让模型持续调用 wait_events,启动可选事件唤醒器:

CONCORDIA_TRANSPORT=stdio \
CONCORDIA_ROOTS=/absolute/path/to/example-app \
CONCORDIA_DB=/absolute/path/to/example-app/.concordia/state.db \
CONCORDIA_WAKER_DB=/absolute/path/to/example-app/.concordia/waker.db \
npm run start:waker

waker 空闲时只运行 Node.js 事件循环,不调用模型。完整配置、跨机器路径规则、可靠性语义和故障排查见 Codex 事件唤醒器指南。 可复制的环境变量起点见 .env.waker.example

同样地,如需让 ZCode 在新任务、Codex 回答或要求返工时恢复实施会话,而不依赖会话内反复调用 wait_events,在 ZCode CLI 所在机器启动:

CONCORDIA_TRANSPORT=stdio \
CONCORDIA_ROOTS=/absolute/path/to/example-app \
CONCORDIA_DB=/absolute/path/to/example-app/.concordia/state.db \
CONCORDIA_ZCODE_WAKER_DB=/absolute/path/to/example-app/.concordia/zcode-waker.db \
npm run start:zcode-waker

zcode-waker 空闲时也不会调用模型。它先按事件 taskId 精确领取并把 CLI 目录绑定到返回的 worktree,再用 --prompt --json --surface terminal --mode build 创建会话;后续事件用 --resume sess_* 恢复同一任务会话。Concordia 不调用 Computer Use,也不干预 ZCode agent 自身的工具选择;CLI 子进程不继承 waker 的 relay/API 凭据。详见 ZCode 事件唤醒器指南,可复制配置见 .env.zcode-waker.example

跨机器协调器使用:

CONCORDIA_ROOTS=/absolute/path/to/repositories \
CONCORDIA_DB=/absolute/path/to/state.db \
CONCORDIA_REDIS_URL='rediss://user:password@redis.example.com:6379/0' \
CONCORDIA_RELAY_NAMESPACE='team-a' \
CONCORDIA_RELAY_CODEX_TOKEN='<至少 32 字符的随机 token>' \
CONCORDIA_RELAY_ZCODE_TOKEN='<另一个至少 32 字符的随机 token>' \
npm run start:relay

协调器不监听入站 HTTP 端口,只主动连接 Redis。跨网络使用 rediss://,完整配置见 跨机器协调指南

配置

变量

必填

默认值

说明

CONCORDIA_TRANSPORT

stdio

MCP 客户端传输模式:stdio 直接访问本机状态,redis 通过中转。

CONCORDIA_AGENT_ID

只允许 codexzcode;角色不匹配的工具会被拒绝。

CONCORDIA_ROOTS

stdio/协调器

允许的目标项目根目录;Redis client 不设置。

CONCORDIA_DB

<cwd>/.concordia/state.db

stdio/协调器使用的本机 SQLite;Redis client 不设置,绝不能跨机器共享。

CONCORDIA_REDIS_URL

Redis 模式

Redis URL;远程默认要求 rediss://

CONCORDIA_RELAY_NAMESPACE

concordia

隔离不同部署的 Redis 键,1–64 个安全字符。

CONCORDIA_RELAY_CODEX_TOKEN

Codex relay/协调器

Codex 请求 HMAC token,至少 32 字符。

CONCORDIA_RELAY_ZCODE_TOKEN

ZCode relay/协调器

ZCode 请求 HMAC token,至少 32 字符且与 Codex token 不同。

例如:

CONCORDIA_ROOTS=/Users/me/src/project-a,/Users/me/src/project-b

路径范围字段 ownedPathsexcludedPathschangedFiles 必须使用相对工作区的 POSIX 路径,例如 src/api,不要使用反斜杠。

接入 Codex 与 ZCode

下面使用一组固定示例路径。配置时请把它们全部替换为你机器上的真实绝对路径:

含义

本节示例值

Concordia 源码目录

/Users/me/tools/concordia

被管理的目标 Git 仓库

/Users/me/src/example-app

双端共享数据库

/Users/me/src/example-app/.concordia/state.db

先完成一次构建并确认两个入口文件存在:

cd /Users/me/tools/concordia
npm install
npm run build

test -f /Users/me/tools/concordia/dist/src/index.js
test -f /Users/me/tools/concordia/zcode-plugin/dist/index.mjs
git -C /Users/me/src/example-app rev-parse --show-toplevel

最后一条命令应输出 /Users/me/src/example-app。如果输出的是其他目录,应把后续配置中的目标仓库路径改成实际 Git 根目录。

在 Codex 中配置

Codex 桌面应用、CLI 和 IDE 扩展在同一 Codex host 上共用 MCP 配置。配置文件可放在全局 ~/.codex/config.toml,也可放在可信目标项目的 .codex/config.toml。以下方式任选一种,详见 Codex MCP 官方文档

方式 A:编辑 config.toml(推荐)

将以下内容追加到 ~/.codex/config.toml。如果只想让服务器在一个项目中可用,则追加到 /Users/me/src/example-app/.codex/config.toml

[mcp_servers.concordia]
command = "node"
args = ["/Users/me/tools/concordia/dist/src/index.js"]
cwd = "/Users/me/src/example-app"
enabled = true
startup_timeout_sec = 20
# wait_events 最长等待 60 秒,工具超时需略大于 60 秒。
tool_timeout_sec = 70

[mcp_servers.concordia.env]
CONCORDIA_TRANSPORT = "stdio"
CONCORDIA_ROOTS = "/Users/me/src/example-app"
CONCORDIA_DB = "/Users/me/src/example-app/.concordia/state.db"
CONCORDIA_AGENT_ID = "codex"

注意:

  • args 指向 Concordia 源码构建出的 dist/src/index.js,不是目标项目中的文件。

  • cwdCONCORDIA_ROOTSCONCORDIA_DB 指向被管理的目标项目。

  • CONCORDIA_AGENT_ID 在 Codex 端必须是 codex

  • 管理多个仓库时,可用逗号或系统路径分隔符连接多个 CONCORDIA_ROOTS;每个任务的 workspace 仍必须是其中某个 Git 仓库的根目录。

保存后重启 Codex MCP server:桌面应用可进入 Settings → MCP servers,找到 concordia 后选择 Restart;CLI 或 IDE 扩展可重新启动会话。然后在 Codex 会话中输入 /mcp,应能看到 concordia 及其 8 个工具。

方式 B:使用 Codex CLI 添加

如果本机安装了 Codex CLI,可以运行:

codex mcp add concordia \
  --env CONCORDIA_TRANSPORT=stdio \
  --env CONCORDIA_ROOTS=/Users/me/src/example-app \
  --env CONCORDIA_DB=/Users/me/src/example-app/.concordia/state.db \
  --env CONCORDIA_AGENT_ID=codex \
  -- node /Users/me/tools/concordia/dist/src/index.js

codex mcp list

CLI 写入的也是 Codex MCP 配置。该命令已经显式指定数据库和允许根目录,因此不依赖 MCP 进程从哪个目录启动。如需 cwd、超时等精细选项,再按方式 A 编辑生成的 ~/.codex/config.toml

Codex 端验证

在一个新的 Codex 会话中要求它“调用 Concordia 的 list_tasks”。若返回任务列表或空数组,说明连接成功。Codex 端具有读取权限,并可调用 create_task、以 sender: "codex" 发送 ANSWER/CANCELLED,以及调用 review_task;它不能领取或提交任务。

在 ZCode 中配置

推荐安装仓库内置插件,因为它会同时提供 Concordia MCP server 和 /tasks/task/watch 命令。也可以只手动添加 MCP server,但手动方式不会安装这些斜杠命令。参见 ZCode Plugin 文档ZCode MCP 文档

插件安装后的待办查看、任务领取、事件监听和提交操作,详见 ZCode 使用指南

方式 A:安装 Concordia 插件(推荐)

本仓库根目录的 marketplace.json 已将 zcode-plugin/ 声明为可安装插件。操作步骤:

  1. 先按前文执行 npm run build,确保 zcode-plugin/dist/index.mjs 存在。

  2. 在 ZCode 中打开目标项目 /Users/me/src/example-app,不要把 Concordia 源码目录当作目标项目打开。

  3. 打开 Settings → Plugins。如果页面提示先打开 workspace,请先完成上一步。

  4. 点击右上角 Create → Add marketplace

  5. 本地开发时选择目录 /Users/me/tools/concordia;发布 GitHub 后也可以填写 Concordia 仓库 URL。

  6. Personal 区域找到 concordia-local marketplace,再找到 concordia 插件,点击 Install 并确认已启用。

  7. 打开 Settings → MCP Servers,在 Plugin MCP servers 分组确认 plugin:concordia:concordia 已启用。

  8. 新建一个 ZCode 会话,输入 /tasks。能够返回任务表或“没有匹配任务”即表示插件和 MCP 都已加载。

插件内置的 zcode-plugin/.mcp.json 为:

{
  "mcpServers": {
    "concordia": {
      "type": "stdio",
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/dist/index.mjs"],
      "cwd": "${CLAUDE_PROJECT_DIR}",
      "env": {
        "CONCORDIA_TRANSPORT": "stdio",
        "CONCORDIA_ROOTS": "${CLAUDE_PROJECT_DIR}",
        "CONCORDIA_DB": "${CLAUDE_PROJECT_DIR}/.concordia/state.db",
        "CONCORDIA_AGENT_ID": "zcode"
      },
      "enabled": true,
      "timeoutMs": 70000
    }
  }
}

其中:

  • ${CLAUDE_PLUGIN_ROOT}(也可写成 ${ZCODE_PLUGIN_ROOT})由 ZCode 替换为已安装插件目录。

  • ${CLAUDE_PROJECT_DIR} 由 ZCode 替换为当前打开的目标项目根目录。

  • CONCORDIA_DB 会展开为 /Users/me/src/example-app/.concordia/state.db;前面的 Codex 配置必须指向完全相同的文件。

  • timeoutMs 略大于 wait_events 允许的最长 60 秒等待,避免正常长轮询被客户端提前中止。

修改 Concordia 或插件源码后,应重新运行 npm run build,然后在 ZCode 的 Marketplace sources 中刷新 concordia-local。如果插件已经被复制进 ZCode 缓存而非直接引用源码,刷新或重新安装后再开新会话。

方式 B:只手动添加 MCP server

不需要斜杠命令时,可在 ZCode 中打开 Settings → MCP Servers → New MCP Server,选择 Workspace scope,切换到 Full configuration,粘贴以下 JSON:

{
  "mcpServers": {
    "concordia": {
      "type": "stdio",
      "command": "node",
      "args": ["/Users/me/tools/concordia/zcode-plugin/dist/index.mjs"],
      "cwd": "/Users/me/src/example-app",
      "env": {
        "CONCORDIA_TRANSPORT": "stdio",
        "CONCORDIA_ROOTS": "/Users/me/src/example-app",
        "CONCORDIA_DB": "/Users/me/src/example-app/.concordia/state.db",
        "CONCORDIA_AGENT_ID": "zcode"
      },
      "enabled": true,
      "timeoutMs": 70000
    }
  }
}

也可以手动写入目标项目的 /Users/me/src/example-app/.zcode/config.json

{
  "mcp": {
    "servers": {
      "concordia": {
        "command": "node",
        "args": ["/Users/me/tools/concordia/zcode-plugin/dist/index.mjs"],
        "cwd": "/Users/me/src/example-app",
        "env": {
          "CONCORDIA_TRANSPORT": "stdio",
          "CONCORDIA_ROOTS": "/Users/me/src/example-app",
          "CONCORDIA_DB": "/Users/me/src/example-app/.concordia/state.db",
          "CONCORDIA_AGENT_ID": "zcode"
        },
        "enable": true
      }
    }
  }
}

ZCode 的用户级配置位于 ~/.zcode/cli/config.json,项目级配置位于 <project>/.zcode/config.json。本工具建议使用项目级配置,以免一个固定 cwd 和数据库路径意外应用到所有项目。保存后在 MCP 列表确认服务器已启用,并新建会话测试 list_tasks

双端联通验证

  1. 分别启动或重启 Codex 与 ZCode 中的 concordia MCP server。

  2. 在 Codex 中调用 create_task 创建一个目标仓库为 /Users/me/src/example-app 的任务。

  3. 在 ZCode 中运行 /tasks,或要求 ZCode 调用 list_tasks

  4. 如果 ZCode 能看到刚创建的任务,说明两端正在使用同一数据库。

  5. 若看不到,优先核对两端 CONCORDIA_DB 的绝对路径是否逐字符一致,再检查两端 CONCORDIA_ROOTS 是否包含目标 Git 根目录。

插件提供的 /tasks/task <task-id>/watch <task-id> 是只读辅助命令;真正的领取、提交和审核仍由 MCP 工具完成。

切换为跨机器 Redis relay

只有需要跨设备时才设置 CONCORDIA_TRANSPORT=redis。远端 Codex 的最小配置为:

[mcp_servers.concordia]
command = "node"
args = ["/Users/me/tools/concordia/dist/src/index.js"]
enabled = true
startup_timeout_sec = 20
tool_timeout_sec = 80

[mcp_servers.concordia.env]
CONCORDIA_AGENT_ID = "codex"
CONCORDIA_TRANSPORT = "redis"
CONCORDIA_REDIS_URL = "rediss://user:password@redis.example.com:6379/0"
CONCORDIA_RELAY_NAMESPACE = "team-a"
CONCORDIA_RELAY_CODEX_TOKEN = "<至少 32 字符的 Codex token>"

ZCode/Git 机器需要另外运行 npm run start:relay。ZCode MCP 可设置同一个 Redis URL 与 namespace、使用独立的 CONCORDIA_RELAY_ZCODE_TOKEN;也可在协调主机继续用默认 stdio,直接连接协调器所用的本机 SQLite。Redis 模式下,任务 workspace 一律填写 ZCode/Git 机器上的绝对路径。

可直接复制的 ZCode JSON、协调器命令、Redis ACL/TLS 要求和联通步骤见 跨机器协调指南

MCP 工具

工具返回 JSON 内容及结构化结果。业务错误统一形如 { code, message, retryable, details? }。每次写操作都需唯一 idempotencyKey(最长 256 字符);完全相同的重试返回原结果,不重复写入。

工具

角色

作用与关键输入

create_task

Codex

创建并发布 READY 任务。输入 specidempotencyKey

claim_task

ZCode

原子领取任务;可按 taskId 精确领取事件对应任务,或按 workspace 筛选最早匹配任务;leaseSeconds 为 1–3600(默认 60)。无任务返回 { task: null };成功包含 leaseToken

get_task

两者

获取任务契约、状态、租约摘要、交付物、提交记录与近期事件;eventLimit 默认 20、最大 100。

list_tasks

两者

statusassigneeworkspaceupdatedAfterlimit 筛选;默认 20、最大 100。

send_event

两者

追加授权事件;可带 expectedVersion。ZCode 的写入必须带当前 leaseToken

wait_events

两者

查询 afterEventId 后的新事件,最长等待 60 秒(默认 30 秒);超时返回空数组。

submit_task

ZCode

提交当前 attempt worktree 的 HEAD commit、精确变更列表、检查、风险和摘要,转入 REVIEW

review_task

Codex

REVIEW 任务 approverequest_changes;返工至少需要一条 finding。

send_event 权限:

发送者

可发送事件

Codex

ANSWERCANCELLED

ZCode

PROGRESSQUESTIONAGENT_STATUSHEARTBEATFAILED

TASK_CREATEDTASK_CLAIMEDCOMPLETEDCHANGES_REQUESTEDAPPROVED 由专用工具生成,不能经 send_event 伪造。

任务契约

{
  id: string;                 // 字母数字开头,最多 128 字符,可含 . _ -
  objective: string;
  workspace: string;          // 目标 Git 仓库根目录,不是 Concordia 源码目录
  baseCommit?: string;        // 省略时创建时解析为目标仓库 HEAD 的完整 SHA
  ownedPaths: string[];       // 至少一个相对路径
  excludedPaths?: string[];
  constraints: string[];
  acceptance: string[];       // 至少一项
  deliverables: ("commit" | "changed_files" | "checks" | "risks")[];
  delegation: { mode: "auto" | "disabled"; maxConcurrency: number; maxDepth: 1 };
  timeoutSeconds: number;
}

baseCommit 在创建时解析为完整 SHA。timeoutSecondsdelegation.modemaxConcurrency 目前是被验证和保存的契约信息,不会由运行时自动杀死、调度或限流代理;maxDepth 必须为 1

提交检查只接受以下 commandId 白名单:buildformat-checkgit-diff-checklintnpm-buildnpm-lintnpm-testnpm-typechecktesttypecheck。Concordia 记录检查证据,不会执行 payload 中的 shell 命令。

leaseToken、attempt 与 worktree

租约与 fencing token

claim_task 成功结果中的 leaseToken 是当前执行权的短期凭据。ZCode 必须把它带入后续每个 send_event(包括 HEARTBEAT)及 submit_task。token 不会进入 get_task、事件、提交记录或日志;不要回显、提交或持久化它。

默认租约 60 秒。长任务应在到期前用 HEARTBEAT 续租,并可传 leaseSeconds(1–3600)。租约过期后另一个领取者可以接手,服务会颁发新 token;旧 token 被围栏拒绝。expectedVersion 是可选的乐观并发控制,适合读—改—写过程。

提交进入 REVIEW 时租约立即失效。Codex 要求返工后任务回到 READY;ZCode 必须再次调用 claim_task,在新 attempt worktree 中继续,并使用新 leaseToken。旧 token 永远不能恢复使用。

每个 attempt 的独立工作区

每次领取创建或复用该尝试专属路径:

<目标 Git 仓库>/.worktrees/<task-id>-zcode-a<attempt>/

对应分支为 concordia/<task-id>-zcode-a<attempt>。首次从 baseCommit 建立;租约过期后的新 attempt 从上一次 worktree 的已提交 HEAD 快照恢复(没有可恢复 worktree 时从 base commit 开始)。旧 attempt 目录不会被新 attempt 重用。

ZCode 必须修改 claim_task 返回的 task.worktreePath,而不是目标仓库的原始检出目录。 提交时服务验证:

  1. 目标仓库/worktree 均在允许根目录内,且不存在符号链接逃逸;

  2. baseCommit 仍解析为原完整 SHA,提交历史从其演进;

  3. 提交 SHA 是当前 attempt worktree 的完整、不可变 HEAD

  4. changedFiles 与 Git diff 精确一致;

  5. 最终 diff、所有中间提交及未提交改动仅触及 ownedPaths,且不触及 excludedPaths

端到端示例

假设目标仓库为 /absolute/path/to/example-app,两端均连接 /absolute/path/to/example-app/.concordia/state.db。以下 JSON 是 MCP 工具参数,不是 shell 命令。

  1. Codex 获取目标仓库基准并调用 create_task

    git -C /absolute/path/to/example-app rev-parse HEAD
    {
      "spec": {
        "id": "docs-api-001",
        "objective": "为 API 客户端补充使用文档",
        "workspace": "/absolute/path/to/example-app",
        "baseCommit": "<完整 SHA>",
        "ownedPaths": ["docs", "README.md"],
        "excludedPaths": [".github"],
        "constraints": ["不要修改运行时代码"],
        "acceptance": ["文档包含安装与 API 示例", "npm test 通过"],
        "deliverables": ["commit", "changed_files", "checks", "risks"],
        "delegation": { "mode": "auto", "maxConcurrency": 1, "maxDepth": 1 },
        "timeoutSeconds": 1800
      },
      "idempotencyKey": "docs-api-001:create:v1"
    }
  2. ZCode 领取并保存返回的 task.worktreePathleaseToken。由 zcode-waker 唤醒时必须传入事件对应的 taskId,避免领取另一个 READY 任务:

    { "agentId": "zcode", "taskId": "docs-api-001", "workspace": "/absolute/path/to/example-app" }
  3. 在返回的 attempt worktree 工作,并用 token 上报进度:

    {
      "taskId": "docs-api-001",
      "sender": "zcode",
      "recipient": "codex",
      "type": "PROGRESS",
      "payload": { "phase": "writing", "summary": "正在编写 API 示例" },
      "idempotencyKey": "docs-api-001:progress:writing",
      "leaseToken": "<领取结果的 leaseToken>"
    }

    该事件将 CLAIMED 变为 RUNNING。需要澄清时发送 QUESTION;Codex 用 ANSWER 回复,任务从 WAITING_INPUT 返回 RUNNING。长任务发送 HEARTBEAT 续租。

  4. 返回的 worktree 中完成、验证、提交:

    cd /absolute/path/to/example-app/.worktrees/docs-api-001-zcode-a1
    npm test
    git add docs README.md
    git commit -m "docs: add API client guide"
    git rev-parse HEAD
  5. ZCode 调用 submit_taskcommit 为完整 SHA,changedFiles 必须与 baseCommit..commit diff 完全一致:

    {
      "taskId": "docs-api-001",
      "leaseToken": "<领取结果的 leaseToken>",
      "commit": "<完整提交 SHA>",
      "changedFiles": ["README.md", "docs/api-client.md"],
      "checks": [{ "commandId": "npm-test", "exitCode": 0, "summary": "npm test passed" }],
      "risks": [],
      "summary": "补充 API 客户端安装、认证和调用示例。",
      "idempotencyKey": "docs-api-001:submit:1"
    }
  6. Codex 用 get_task 读取交付证据并审查 diff,之后调用 review_task

    {
      "taskId": "docs-api-001",
      "decision": "approve",
      "summary": "文档内容和测试证据已核对。",
      "idempotencyKey": "docs-api-001:approve:1"
    }

    返工时使用 decision: "request_changes" 并给出至少一个 { path?, line?, severity, message } finding。任务会回到 READY,ZCode 需要重新领取。批准只表示任务协议完成,不会自动合并 worktree branch;后续合并、cherry-pick 或丢弃由用户或上层协调者决定。

ZCode 命令

命令

用途

/tasks [status]

列出当前工作区近期任务;可按一个或多个状态过滤,显示 ID、状态、执行者、更新时间和目标。

/task <task-id>

显示任务契约、状态、路径范围、验收条件、租约摘要、交付证据与近期事件。

/watch <task-id>

读取当前事件游标后循环 wait_events 显示新事件;终态、用户中止或达到观察限制时停止。

这些都是查询/观察命令,不会领取、提交或审核任务。

安全模型

Concordia 的边界是“可信用户/团队 + 明确工作区白名单”,不是完整的多租户平台。已实现的约束包括:

  • 必须显式声明 codexzcode;工具和事件发送者均做角色校验;

  • CONCORDIA_ROOTS 限制目标工作区,且工作区必须为该根内的 Git 仓库根;

  • 路径范围拒绝绝对路径、..、反斜杠、Git/Concordia 控制目录和越界符号链接;

  • worktree 及既有目录会解析真实路径,防止逃离目标仓库;

  • SQLite 使用外键、WAL、事务和任务 version 乐观锁;事件 idempotency key 全局唯一;

  • leaseToken 使用时序安全比较,轮换后旧领取者无法继续写入;

  • Redis relay 使用分角色 HMAC-SHA256 签名、时间戳、nonce 防重放、响应 TTL 和单协调器锁;

  • 远程 Redis 默认强制 rediss://,角色 token 与 Redis 凭据均不进入日志;

  • submit_task 不执行任意命令;只记录白名单检查 ID 的结果;

  • 业务错误不回显环境变量、凭据或完整命令输出。

任何能读写本地数据库、Git 工作区、Redis 数据或 MCP 配置的用户仍在同一信任域。跨机器生产部署应使用 Redis ACL 和 TLS。

测试与开发

npm run typecheck  # 严格 TypeScript 类型检查
npm run build      # 编译服务并打包 ZCode 插件
npm test           # build 后运行 Node 内置测试

若本机有测试 Redis,可额外执行真实 relay 往返测试:

CONCORDIA_TEST_REDIS_URL=redis://127.0.0.1:6379 npm test

测试覆盖完整领取—运行—提交—返工重领—批准流程、并发领取、幂等、租约恢复、fencing token、数据库重启持久化、事件等待、两个 waker 的游标与投递恢复、Codex App Server 与 ZCode CLI 生命周期、基准提交验证、worktree 恢复、relay 签名/权限/TLS 校验,以及路径/符号链接/提交历史范围校验。

详见:系统设计开发指南ZCode 使用指南Codex 事件唤醒器指南ZCode 事件唤醒器指南

目录结构

concordia/                         # Concordia 源码目录
├── src/
│   ├── index.ts                   # stdio MCP server 与 8 个工具
│   ├── protocol.ts                # 类型、验证、错误模型
│   ├── database.ts                # SQLite 初始化、迁移、事务
│   ├── events.ts                  # 事件追加、查询、有界等待
│   ├── tasks.ts                   # 状态机、租约、幂等、交付验证
│   ├── workspace.ts               # Git/worktree、路径范围
│   ├── relay-protocol.ts          # relay 签名信封与安全校验
│   ├── relay-client.ts            # Redis 模式 MCP client
│   ├── relay.ts                   # Redis Streams coordinator
│   ├── codex-app-server.ts        # Codex App Server JSONL 客户端
│   ├── zcode-cli.ts               # ZCode headless CLI 客户端
│   ├── waker-source.ts            # SQLite/Redis 共享事件源
│   ├── codex-waker.ts             # 事件过滤、唤醒与重试循环
│   ├── zcode-waker.ts             # ZCode CLI 事件唤醒与重试循环
│   └── waker-state.ts             # 独立游标、线程和投递状态库
├── tests/                         # 核心、relay、CLI 与 waker 测试
├── marketplace.json               # ZCode 本地/GitHub marketplace 入口
├── zcode-plugin/                  # 可加载的 ZCode 本地插件
│   ├── .mcp.json
│   ├── .zcode-plugin/plugin.json
│   └── commands/                  # /tasks、/task、/watch
├── docs/
│   ├── zcode-usage.md            # ZCode 待办、监听与执行指南
│   ├── codex-waker.md            # Codex 事件驱动唤醒与部署
│   ├── zcode-waker.md            # ZCode 事件驱动唤醒与部署
│   ├── design.md
│   └── development.md
├── package.json
├── .env.waker.example             # Codex waker 环境变量模板
├── .env.zcode-waker.example       # ZCode waker 环境变量模板
└── tsconfig.json

<目标 Git 仓库>/
└── .worktrees/<task>-zcode-a<attempt>/  # Concordia 运行时创建

本仓库 .gitignore 忽略 node_modules/dist/.concordia/.worktrees/ 和 TypeScript 构建缓存。

开源协议

Concordia 使用 MIT License 开源。你可以自由使用、复制、修改、合并、发布和分发本软件,但必须保留原始版权与许可声明。本软件按“原样”提供,不附带任何明示或默示担保。

故障排查

现象

处理

CONCORDIA_AGENT_ID is required

为 MCP server 设置 CONCORDIA_AGENT_ID=codexzcode

CONCORDIA_ROOTS must contain at least one allowed root

配置至少一个存在的目标项目根目录。

WORKSPACE_DENIED

确认 workspace 是位于 CONCORDIA_ROOTS 内的目标 Git 仓库根,而不是其子目录或 Concordia 源码目录;检查软链接。

两端看不到彼此任务

两端 CONCORDIA_DB 必须是同一个绝对文件。若 ZCode 使用默认值,Codex 应设为 <目标仓库>/.concordia/state.db

Redis relay request timed out

确认协调器运行中,Redis URL、数据库编号和 namespace 一致,ACL 允许所需命令。

远程 redis:// 被拒绝

生产环境改用 rediss://;只有可信开发网络才设置 CONCORDIA_RELAY_ALLOW_INSECURE=true

claim_task 返回 task: null

没有匹配的 READY 任务,也没有过期可恢复任务;用 list_tasks 查看。

LEASE_CONFLICT

token 不正确、租约过期或已被重领。重新领取,切勿复用旧 token。

STALE_VERSION

读取后任务被其他写操作改变;重新 get_task 后继续。

BASE_COMMIT_MISMATCH

基准 SHA 无法解析或尝试历史不从其演进;检查 Git 历史和任务 baseCommit

PATH_SCOPE_VIOLATION / 提交被拒绝

核对 ownedPaths/excludedPaths;最终 diff、中间提交与未提交改动必须全部在允许范围内。

提交不是当前 HEAD

在当前 task.worktreePath 中提交,并传 git rev-parse HEAD 的完整 SHA。

SQLite 初始化被锁定

稍后重试;初始化有有限重试。若持续发生,检查异常进程是否占用同一数据库。

waker.event_failed 反复出现

检查 Codex CLI 登录、App Server、Codex 端 Concordia MCP 与 waker.db 中的 last_error

当前限制

  • 当前版本为 0.4.0package.json 标为 private: true,尚未作为 npm 包发布。

  • Node 的 node:sqlite 在部分 Node 22 发行版可能显示实验性 API 警告;采用前请按自身 Node 策略评估。

  • Redis relay 当前只支持单活动协调器,不提供多协调器高可用、远程备份或自动清理旧 attempt worktree。

  • timeoutSecondsdelegation.maxConcurrencydelegation.mode 不会被运行时强制调度或限流。

  • wait_events 是最多 60 秒的轮询等待;交互会话需自行维护游标。可选 codex-wakerzcode-waker 能在模型外持久监听并按事件启动或恢复对应代理 turn。

  • 提交路径校验不替代人工/自动代码审查、CI、合并策略和发布流程。

Related MCP Connectors

Related MCP Servers