init: OpenSpec project scaffolding with proposal, design, specs, tasks

- 7 capabilities: agent-registry, task-router, receipt-protocol,
  forgejo-integration, matrix-chatops, agent-adapter, orchestrator-core
- Tech stack: Rust + axum + zigbuild (single binary)
- Forgejo as task source of truth
- Matrix as real-time ChatOps layer
- Adapter pattern for multi-agent type support
This commit is contained in:
Zer4tul 2026-05-11 14:37:43 +08:00
commit aabd52ed52
19 changed files with 1938 additions and 0 deletions

View file

@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-11

View file

@ -0,0 +1,250 @@
## Context
当前有多台机器WSL2 workstation、MacBook、可能的云服务器运行不同类型的 AI Agent
- **OpenClaw**Jeeves orchestrator + 多个 sub-agent
- **Claude Code**:本地 CLI 编码
- **Codex CLI**OpenAI 编码
- **Hermes Agent**:其他类型
- **ACP-compatible agents**Devin 等
现状Agent 之间无统一协同机制,任务靠人工传递,进度靠人工追踪,没有结构化的完成验证。
已有基础设施:
- **Matrix**0x08.org homeserver 已运行
- **Forgejo**:需要部署(建议自建,或用 Gitea 替代)
- 各机器可以互相网络通信
## Goals / Non-Goals
**Goals:**
- 建立统一的 Agent 编排平台,支持任意类型 Agent 加入
- Forgejo Issue/PR 作为任务事实来源,人类和 Agent 共用同一界面
- Matrix 作为实时协同层,提供 ChatOps 和通知
- 结构化 receipt 协议,不信任模型口头声明
- 最小化对现有 Agent 的侵入性adapter 模式)
- 可扩展:新 Agent 类型只需实现 adapter 即可接入
**Non-Goals:**
- 不做 Agent 自身的改进Agent 内部行为不在 scope 内)
- 不做 IDE 集成VS Code / JetBrains 插件)
- 不做 LLM provider 管理(使用各 Agent 自己的 provider 配置)
- 不做前端 Web UIPhase 1 用 Forgejo + Matrix 作为 UI
- 不替换 cc-connect / cc-telegram-bridge它们可以作为 adapter 接入)
## Decisions
### Decision 1: Forgejo而非 Gitea作为 Git 平台
**选择**: Forgejo
**理由**:
- Forgejo 是 Gitea 的社区 fork治理更开放
- 内置 CI/CDForgejo Actions未来可扩展
- API 兼容 Gitea迁移成本低
- 支持 F3 (Friendly Forge Format),数据可移植
**替代方案**:
- Gitea更成熟但治理有争议公司化
- GitHub不方便自建网络可达性差
- GitLab太重资源消耗大
### Decision 2: Orchestrator 用 Rust + zigbuild
**选择**: Rust + cargo-zigbuild交叉编译
**理由**:
- 内存安全:无 GC、无 data race、无 null pointer
- 单二进制部署zigbuild 交叉编译,无 libc 兼容性问题
- 性能:原生性能,适合长运行服务
- 类型系统:强类型 + algebraic data types适合状态机建模
- 生态reqwestHTTP、matrix-sdkMatrix、rusqliteSQLite、serdeJSON/TOML
- 交叉编译cargo-zigbuild 一行命令产出 Linux/macOS/Windows 二进制
**替代方案**:
- TypeScript (Node.js):开发快但需要运行时,非单二进制
- Go单二进制但内存安全不如 Rust交叉编译有 libc 问题
### Decision 3: Agent-Orchestrator 通信用 HTTP APIaxum
**选择**: Agent 通过 HTTP API 与 Orchestrator 通信Orchestrator 端用 axum 框架
**理由**:
- 跨语言、跨平台:任何 Agent 都能发 HTTP 请求
- 防火墙友好
- 与 Forgejo webhook 统一协议栈
- axum 是 Rust 生态最成熟的 async HTTP 框架
**替代方案**:
- WebSocket实时性好但复杂度高重连逻辑麻烦
- gRPC性能好但 Agent 端实现门槛高
- Message QueueNATS/Redis增加基础设施依赖
### Decision 4: Event sourcing 作为审计基础rusqlite
**选择**: 所有状态变更作为不可变事件 append 到 SQLite通过 rusqlite 访问
**理由**:
- 完整审计追踪
- 可重放
- 轻量,不需要外部数据库,适合单二进制打包
- rusqlite 是 Rust 生态最成熟的 SQLite 绑定
- 适合中小规模 Agent 舰队(< 100 agents
**替代方案**:
- PostgreSQL强大但引入运维复杂度破坏单二进制部署
- JSON 文件:简单但无查询能力
- 只记录当前状态:无法审计
### Decision 5: Adapter 模式接入多类型 Agent
**选择**: 定义统一 adapter interface各 Agent 实现自己的 adapter
**理由**:
- 最小侵入Agent 不需要改内部逻辑
- 可扩展:新 Agent 类型只需写 adapter
- 隔离adapter 故障不影响 Orchestrator
**adapter 执行方式**:
- Claude Code adapterspawn `claude -p` 子进程
- Codex adapterspawn `codex exec` 子进程
- OpenClaw adapter调用 gateway HTTP API
- ACP adapter通过 ACP 协议 WebSocket
- Shell adapter执行任意 shell 命令(最通用)
### Decision 6: 配置用 TOML
**选择**: TOML与 cc-connect 一致)
**理由**:
- 人类可读性好
- 类型比 YAML 更明确
- cc-connect 已验证
## Risks / Trade-offs
### Risk: Agent 执行环境差异
不同机器上的 Agent 运行环境OS、依赖、权限不同可能导致同一任务在不同 Agent 上行为不一致。
**Mitigation**: adapter 负责环境检查任务描述尽量环境无关receipt 验证在 Forgejo 侧(与执行环境解耦)。
### Risk: Orchestrator 单点故障
Orchestrator 挂了,整个舰队停摆。
**Mitigation**: Phase 1 接受单点Orchestrator 做到无状态(状态在 SQLite + Forgejo快速重启恢复。
### Risk: Forgejo webhook 延迟或丢失
网络抖动可能导致 webhook 丢失。
**Mitigation**: Orchestrator 定期轮询 Forgejo 做对账reconciliation弥补 webhook 丢失。
### Risk: Agent 心跳风暴
大量 Agent 同时发心跳可能导致 Orchestrator 负载过高。
**Mitigation**: 心跳间隔可配置(默认 60sOrchestrator 做好限流。
### Trade-off: 简单性 vs 实时性
选择 HTTP 而非 WebSocket/MQ 意味着实时性稍差。
→ 对于任务编排场景秒级延迟完全可接受。Matrix 通知提供实时感。
## Architecture Overview
```
┌─────────────┐ webhook ┌──────────────────┐
│ Forgejo │ ───────────────→ │ Orchestrator │
│ (Git+Issue) │ ←─── API ────── │ (Node.js) │
└─────────────┘ │ │
│ - Agent Registry │
┌─────────────┐ HTTP API │ - Task Router │
│ Matrix │ ←──────────────→│ - Event Log │
│ (ChatOps) │ │ - Receipt Validator│
└─────────────┘ └────────┬─────────┘
│ HTTP API
┌───────────────────┼───────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Adapter A │ │ Adapter B │ │ Adapter C │
│ Claude Code │ │ Codex CLI │ │ OpenClaw │
│ (host-01) │ │ (host-02) │ │ (host-03) │
└─────────────┘ └─────────────┘ └─────────────┘
```
## Data Model (Core)
```typescript
interface Agent {
agent_id: string;
agent_type: "openclaw" | "claude-code" | "codex-cli" | "hermes" | "acp" | "shell";
hostname: string;
capabilities: string[];
max_concurrency: number;
current_tasks: number;
status: "online" | "offline" | "draining";
last_heartbeat_at: string; // ISO 8601
registered_at: string;
metadata: Record<string, string>;
}
interface Task {
task_id: string;
source: string; // "forgejo:<repo>#<issue>"
type: string; // from label: "code", "review", "test", "deploy", "research"
priority: "low" | "normal" | "high" | "urgent";
status: TaskStatus;
assigned_agent_id?: string;
requirements: string; // Issue body
labels: string[];
created_at: string;
assigned_at?: string;
started_at?: string;
completed_at?: string;
retry_count: number;
max_retries: number;
timeout_seconds: number;
}
type TaskStatus = "created" | "assigned" | "running" | "completed" | "failed" | "agent_lost" | "cancelled";
interface Receipt {
task_id: string;
agent_id: string;
status: "completed" | "failed" | "partial";
duration_seconds: number;
summary: string;
artifacts: Artifact[];
error?: string;
}
interface Artifact {
type: "pr" | "commit" | "file" | "comment" | "url";
url?: string;
path?: string;
description?: string;
}
interface TaskEvent {
event_id: string;
task_id: string;
event_type: string; // "created", "assigned", "started", "receipt_submitted", "completed", "failed", ...
agent_id?: string;
timestamp: string;
payload: Record<string, unknown>;
}
```
## Migration Plan
1. **部署 Forgejo**:自建实例,配置 webhook
2. **部署 Orchestrator**Node.js 进程,连接 Forgejo + Matrix
3. **实现 Claude Code adapter**:第一个 adapter验证端到端流程
4. **实现 Codex adapter**:第二个 adapter
5. **实现 OpenClaw adapter**:第三个 adapter可选 Phase 2
6. **逐步迁移现有任务到 Forgejo Issue**
### Rollback
- Orchestrator 可随时停止,不影响 Forgejo 和 Matrix
- Agent 可独立运行(只是没有编排)
- 所有状态在 Forgejo Issue + SQLite可手动接管
## Open Questions
1. ~~**Forgejo 部署位置**~~:✅ 已部署在 arm0.0x08.org域名 git.0x08.org
2. **Orchestrator 部署位置**TBDarm0 / WSL2 / 独立机器)
3. **Agent 工作目录策略**:每个任务 clone 新 worktree 还是共享 workspace
4. **权限模型**Issue comment 中的 `/assign` 命令是否需要权限控制?
5. **cc-connect 集成**:✅ 放 Phase 2

View file

@ -0,0 +1,37 @@
## Why
多台机器上运行着不同类型的 AI AgentOpenClaw、Claude Code、Codex、Hermes Agent 等目前缺乏统一的跨机任务编排与协同机制。Agent 之间只能靠人工传递上下文,无法自动分发任务、追踪进度、回写结果。需要一个 **agent-fleet platform**,让任意类型的 Agent 通过统一的协议加入舰队,接收任务、汇报状态、协同完成复杂工程。
## What Changes
- **引入 Git 仓库Forgejo作为任务事实来源**Issue = 任务单元PR = 交付物Label/Milestone = 分类与排期
- **引入实时协同层**Matrix 作为 ChatOps 通道Agent 状态变更、任务分配、完成通知等通过 Matrix 房间实时推送
- **建立 Agent Registry**:每台机器上的 Agent 启动时向 Registry 注册(类型、能力、负载),支持动态发现与路由
- **建立 Task Router**Orchestrator 根据 Issue 类型、Agent 能力、负载状态,自动将任务路由到合适的 Agent
- **建立结构化 Receipt 协议**Agent 完成工作后回写结构化 receiptIssue comment / PR / Matrix 通知),系统不信任模型口头声明
- **支持多 Agent 类型**OpenClaw、Claude Code、Codex CLI、Hermes Agent、任意 ACP-compatible agent只要能读写 Git repo 并发 Matrix 消息即可加入
- **支持 hooks/webhook**Forgejo webhook → 路由到编排层 → 触发 Agent 执行
## Capabilities
### New Capabilities
- `agent-registry`: Agent 注册、心跳、能力声明、动态发现。每台机器上的 Agent 启动时注册自身类型、hostname、能力标签、当前负载Orchestrator 据此做任务路由
- `task-router`: 任务解析与分发。从 Forgejo Issue/PR 事件中解析任务需求,匹配 Agent 能力与负载,生成执行指令并投递
- `receipt-protocol`: 结构化完成回执。Agent 完成工作后必须回写结构化 receiptIssue comment / PR / Matrix 通知),系统据此判定完成状态,不依赖模型口头声明
- `forgejo-integration`: 与 Forgejo 的双向集成。监听 Issue/PR webhook 事件Agent 执行完成后回写 comment、创建 PR、更新 label/milestone
- `matrix-chatops`: Matrix 实时协同层。Agent 状态变更、任务分配、完成通知、人类审批等通过 Matrix 房间流转;支持 slash command 触发编排操作
- `agent-adapter`: 多类型 Agent 适配层。定义统一 adapter 接口,各类型 AgentOpenClaw、Claude Code、Codex CLI、Hermes Agent、ACP agent实现自己的 adapter接入统一编排
- `orchestrator-core`: 编排核心。管理任务生命周期created → assigned → running → completed/failed调度 Agent处理超时/重试/升级,维护全局状态
### Modified Capabilities
(初始项目,无既有 capability 需修改)
## Impact
- **新系统**:需要部署 Forgejo 实例 + Matrix homeserver或复用现有
- **网络**:各机器需要能访问 Forgejo APIHTTP、Matrix federationHTTPS、Orchestrator APIHTTP/WebSocket
- **Agent 端**:每种 Agent 需要实现 adapter最小要求能读 Git repo、能调用 Forgejo API 写 comment/PR、能发 Matrix 消息
- **依赖**ForgejoGit + Issue + PR + webhook、Matrix实时消息、Node.js/PythonOrchestrator runtime
- **运维**:需要 monitor Agent 心跳、任务超时、Forgejo webhook 健康检查

View file

@ -0,0 +1,41 @@
## ADDED Requirements
### Requirement: Unified adapter interface
系统 SHALL 定义统一的 Agent Adapter 接口,所有类型的 Agent 通过实现该接口接入编排系统。
Adapter 接口 SHALL 至少包含:
- `register()` — 注册到 Registry
- `heartbeat()` — 发送心跳
- `execute(task)` — 接收并执行任务
- `submit_receipt(receipt)` — 提交 receipt
- `deregister()` — 注销
#### Scenario: Claude Code adapter implementation
- **WHEN** 使用 Claude Code adapter
- **THEN** `execute(task)` SHALL 将任务 prompt 注入 `claude -p --output-format json`,在工作目录中执行,解析输出为 receipt
#### Scenario: Codex CLI adapter implementation
- **WHEN** 使用 Codex adapter
- **THEN** `execute(task)` SHALL 使用 `codex exec --json` 执行任务,解析输出为 receipt
#### Scenario: OpenClaw adapter implementation
- **WHEN** 使用 OpenClaw adapter
- **THEN** `execute(task)` SHALL 通过 OpenClaw gateway API 或 CLI 触发 agent 执行
#### Scenario: ACP-compatible agent adapter
- **WHEN** 使用 ACP adapter
- **THEN** `execute(task)` SHALL 通过 ACP 协议启动 agent session传递任务 prompt收集输出
### Requirement: Adapter configuration
每个 Agent 实例 SHALL 通过配置文件指定 adapter 类型、连接参数、工作目录、环境变量。
#### Scenario: Configuration file format
- **WHEN** Agent 实例配置为 Claude Code 类型
- **THEN** 配置文件 SHALL 包含:`{adapter: "claude-code", work_dir: "/path/to/repo", model: "sonnet", max_concurrency: 2, capabilities: ["code:typescript", "review"]}`
### Requirement: Adapter health check
Adapter SHALL 提供健康检查能力:检查底层 Agent 是否可用CLI 是否安装、API 是否可达)。
#### Scenario: Claude Code CLI not found
- **WHEN** Claude Code adapter 初始化时检测到 `claude` CLI 未安装
- **THEN** Adapter SHALL 返回健康检查失败Agent 注册 SHALL 被拒绝

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Agent self-registration
每台机器上的 Agent 启动时 SHALL 向 Orchestrator Registry 注册自身信息agent_id、agent_typeopenclaw / claude-code / codex-cli / hermes / acp 等、hostname、capabilities能力标签列表、max_concurrency、metadata版本、工作目录等
#### Scenario: New agent starts and registers
- **WHEN** 一个新的 Codex CLI Agent 在 host-worker-02 上启动
- **THEN** 它 SHALL 调用 `POST /api/v1/agents/register`Orchestrator 记录该 Agent 信息并返回 agent_id 和 registry token
#### Scenario: Duplicate registration with same agent_id
- **WHEN** 已注册的 Agent 重启后再次注册(相同 agent_id
- **THEN** 系统 SHALL 更新该 Agent 的信息hostname、capabilities 等)而非创建重复条目
### Requirement: Agent heartbeat
已注册的 Agent SHALL 每隔可配置的间隔(默认 60 秒发送心跳。Orchestrator 据此判定 Agent 是否在线。
#### Scenario: Agent sends heartbeat on time
- **WHEN** Agent 在 60 秒内发送心跳
- **THEN** Orchestrator 更新 `last_heartbeat_at` 并保持 Agent 状态为 `online`
#### Scenario: Agent misses 3 consecutive heartbeats
- **WHEN** Agent 连续 3 个心跳周期未发送心跳180 秒)
- **THEN** Orchestrator SHALL 将该 Agent 状态标记为 `offline`,并将该 Agent 上所有 `running` 状态的任务标记为 `agent_lost`
### Requirement: Agent capability declaration
Agent 注册时 SHALL 声明自己的能力标签(如 `code:typescript``code:python``review``test``deploy``research`。Task Router 据此匹配任务。
#### Scenario: Task requiring specific capability
- **WHEN** 一个 Issue 被标记为 `agent:review` 且需要 TypeScript 能力
- **THEN** Task Router SHALL 只将其分配给声明了 `review``code:typescript` 能力的在线 Agent
### Requirement: Agent graceful deregistration
Agent 正常关闭时 SHALL 调用 `POST /api/v1/agents/deregister`Orchestrator 将其标记为 `offline`
#### Scenario: Agent deregisters on shutdown
- **WHEN** Agent 调用 deregister API
- **THEN** Orchestrator SHALL 将该 Agent 状态设为 `offline`,该 Agent 上所有 `running` 任务 SHALL 被重新入队
### Requirement: Agent list and query
Orchestrator SHALL 提供 API 查询当前所有注册 Agent 的状态、能力、负载。
#### Scenario: Query agents by capability
- **WHEN** 调用 `GET /api/v1/agents?capability=code:python&status=online`
- **THEN** 返回所有在线且声明了 `code:python` 能力的 Agent 列表

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Webhook endpoint for Forgejo
Orchestrator SHALL 暴露 HTTP webhook endpoint 接收 Forgejo 事件:`POST /api/v1/webhooks/forgejo`
#### Scenario: Forgejo sends issue event
- **WHEN** Forgejo 配置了指向 Orchestrator 的 webhookIssue 事件触发
- **THEN** Orchestrator SHALL 接收、验证签名、解析事件体,并路由到 Task Router
#### Scenario: Invalid webhook signature
- **WHEN** 收到的 webhook 签名验证失败
- **THEN** Orchestrator SHALL 返回 401 并记录安全日志
### Requirement: Issue to task conversion
Orchestrator SHALL 将 Forgejo Issue 转换为内部任务保持双向映射Issue URL ↔ task_id。
#### Scenario: Issue created with agent label
- **WHEN** Issue #42 在 repo `my-project` 中创建,带 `agent:code` 标签
- **THEN** 创建任务,`source = "forgejo:my-project#42"`,任务状态为 `created`
### Requirement: Task status sync back to Issue
任务状态变更 SHALL 同步回 Forgejo Issuelabel 更新(`status:todo``status:doing``status:done`、milestone 更新、assignee 更新。
#### Scenario: Task assigned to agent
- **WHEN** 任务被分配给 Agent `worker-03`
- **THEN** 对应 Issue 的 assignee SHALL 更新为 `worker-03` 对应的 Forgejo 用户label SHALL 添加 `status:doing`
#### Scenario: Task completed
- **WHEN** 任务状态变为 `completed`
- **THEN** Issue label SHALL 从 `status:doing` 变为 `status:done`Issue comment SHALL 写入 receipt summary
### Requirement: PR creation and update
Agent 通过 Orchestrator 创建的 PR SHALL 关联到原始 Issue通过 description 或 `Closes #N` 引用)。
#### Scenario: Agent creates PR via Orchestrator
- **WHEN** Agent 在 receipt 中声明需要创建 PR
- **THEN** Orchestrator SHALL 协助创建 PR或验证 Agent 直接创建的 PR确保 PR body 包含 `Closes #<issue-number>`
### Requirement: Forgejo API authentication
Orchestrator SHALL 使用 Forgejo API token 进行所有 API 调用(读取 Issue、创建 comment、更新 label、创建 PR 等)。
#### Scenario: Token rotation
- **WHEN** Forgejo API token 过期
- **THEN** Orchestrator SHALL 返回明确错误并通过 Matrix 通知管理员

View file

@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Matrix room as coordination channel
Orchestrator SHALL 使用 Matrix 房间作为实时协同通道Agent 状态变更、任务分配、完成通知、人类审批等事件 SHALL 推送到 Matrix。
#### Scenario: Task assigned notification
- **WHEN** 任务 #42 被分配给 Agent `worker-03`
- **THEN** Matrix 协同房间 SHALL 收到通知:`📋 #42 → worker-03 [code:typescript]`
#### Scenario: Agent offline alert
- **WHEN** Agent `worker-03` 连续 3 次心跳失败
- **THEN** Matrix 房间 SHALL 收到告警:`⚠️ worker-03 offline — 2 running tasks affected`
### Requirement: Slash commands for orchestration
人类 SHALL 能通过 Matrix slash command 触发编排操作。
#### Scenario: /fleet status
- **WHEN** 人类发送 `/fleet status`
- **THEN** Bot SHALL 回复所有 Agent 当前状态表格Agent ID、类型、状态、当前任务数、能力
#### Scenario: /assign command
- **WHEN** 人类发送 `/assign worker-03 #42`
- **THEN** 任务 #42 SHALL 被手动分配给 worker-03
#### Scenario: /retry command
- **WHEN** 人类发送 `/retry #42`
- **THEN** 失败的任务 #42 SHALL 被重新入队
### Requirement: Matrix notifications for receipts
每个 receipt 回写 SHALL 触发 Matrix 通知包含任务状态、摘要、artifact 链接。
#### Scenario: Task completed notification
- **WHEN** 任务 #42 的 receipt 验证通过,状态为 `completed`
- **THEN** Matrix 房间 SHALL 收到通知:`✅ #42 completed by worker-03 — PR #15 — "修复登录验证 bug"`
#### Scenario: Task failed notification
- **WHEN** 任务 #42 失败
- **THEN** Matrix 房间 SHALL 收到通知:`❌ #42 failed — worker-03 — "构建超时"`
### Requirement: Per-agent Matrix thread
每个 Agent SHALL 有独立的 Matrix thread或 topic用于该 Agent 的执行日志、状态更新、调试输出。
#### Scenario: Agent execution log
- **WHEN** Agent worker-03 开始执行任务 #42
- **THEN** worker-03 的 thread SHALL 收到执行开始消息,后续日志更新也在此 thread

View file

@ -0,0 +1,44 @@
## ADDED Requirements
### Requirement: Task lifecycle state machine
Orchestrator SHALL 维护任务的状态机:`created``assigned``running``completed` / `failed` / `agent_lost` / `cancelled`。每次状态转换 SHALL 记录时间戳和触发原因。
#### Scenario: Full happy path
- **WHEN** Issue 创建 → Agent 匹配 → Agent 接受 → 执行完成 → Receipt 验证通过
- **THEN** 状态 SHALL 按序流转:`created``assigned``running``completed`
#### Scenario: Agent lost during execution
- **WHEN** 执行中的 Agent 心跳超时,状态变为 `offline`
- **THEN** 任务状态 SHALL 变为 `agent_lost`Task Router SHALL 根据策略决定重新入队或标记 `failed`
### Requirement: Task timeout handling
任务 SHALL 有可配置的超时时间(默认 30 分钟)。超时后 SHALL 自动标记为 `failed`
#### Scenario: Task exceeds timeout
- **WHEN** 任务 #42 执行超过 30 分钟无 receipt
- **THEN** 任务 SHALL 标记为 `failed`reason 为 `timeout`Issue comment 写入超时通知
### Requirement: Task retry policy
失败的任务 SHALL 根据可配置的重试策略(最大重试次数、退避间隔)自动或手动重试。
#### Scenario: Auto-retry on transient failure
- **WHEN** 任务因 `agent_lost` 失败,重试策略允许最多 2 次自动重试
- **THEN** 任务 SHALL 重新入队,分配给下一个可用 Agent
#### Scenario: Max retries exceeded
- **WHEN** 任务已重试 2 次仍失败
- **THEN** 任务 SHALL 保持 `failed` 状态Matrix SHALL 通知人工介入
### Requirement: Global task queue
Orchestrator SHALL 维护全局任务队列,按优先级排序。高优先级任务 SHALL 优先分配。
#### Scenario: Priority ordering
- **WHEN** 队列中有 `priority:low` 任务 #10`priority:high` 任务 #42
- **THEN** 任务 #42 SHALL 先于 #10 被分配
### Requirement: Event sourcing for audit
所有任务状态转换、Agent 事件、receipt 提交 SHALL 作为不可变事件记录到 event log。
#### Scenario: Task history query
- **WHEN** 查询任务 #42 的历史
- **THEN** 返回完整的事件序列created → assigned to worker-03 → running → receipt submitted → completed每条带时间戳

View file

@ -0,0 +1,41 @@
## ADDED Requirements
### Requirement: Structured receipt format
Agent 完成任务后 SHALL 回写结构化 receipt。Receipt 包含task_id、agent_id、statuscompleted / failed / partial、duration_seconds、summary、artifactsPR URL、文件路径等、error失败时
#### Scenario: Successful task completion with PR
- **WHEN** Agent 完成代码任务并创建了 PR #15
- **THEN** Agent SHALL 提交 receipt`{status: "completed", artifacts: [{type: "pr", url: "https://forgejo.example/repo/pulls/15"}], summary: "..."}`
#### Scenario: Partial completion
- **WHEN** Agent 完成了部分工作但未能全部完成
- **THEN** Agent SHALL 提交 receipt`{status: "partial", summary: "完成 3/5 个文件修改test_auth.ts 超时", artifacts: [...]}`
### Requirement: Receipt delivery channels
Receipt SHALL 通过至少一个持久化渠道回写Forgejo Issue comment必须+ Matrix 通知(可选)。
#### Scenario: Receipt written as Issue comment
- **WHEN** Agent 提交 receipt
- **THEN** Orchestrator SHALL 在对应 Issue 下创建结构化 comment包含 status emoji + summary + artifact links
#### Scenario: Receipt triggers Matrix notification
- **WHEN** Receipt 写入成功
- **THEN** Orchestrator SHALL 向 Matrix 协同房间发送通知消息,包含任务状态和关键信息
### Requirement: Receipt validation
Orchestrator SHALL 验证 receipt 中的 artifact 声明(如 PR 是否真实存在)。
#### Scenario: PR artifact validation
- **WHEN** Receipt 声明创建了 PR #15
- **THEN** Orchestrator SHALL 通过 Forgejo API 验证 PR #15 确实存在,若不存在 SHALL 将任务标记为 `failed` 并通知 Agent
#### Scenario: Comment artifact validation
- **WHEN** Receipt 声明在某个文件中做了修改
- **THEN** Orchestrator SHALL 验证对应 commit/PR 包含该修改
### Requirement: No-trust policy
系统 SHALL NOT 仅凭 Agent 的文本输出判定任务完成。只有结构化 receipt + artifact 验证通过才算 `completed`
#### Scenario: Agent says done without receipt
- **WHEN** Agent 在 Matrix 发消息说"任务完成了"但未提交 receipt
- **THEN** 任务 SHALL 保持 `running` 状态,超时后按 `failed` 处理

View file

@ -0,0 +1,52 @@
## ADDED Requirements
### Requirement: Forgejo webhook event ingestion
Orchestrator SHALL 监听 Forgejo webhook 事件Issue 创建/更新/标签变更、PR 创建/更新/合并、Push 等),解析为内部任务事件。
#### Scenario: New issue with agent label
- **WHEN** Forgejo 上创建了新 Issue带有 `agent:code` 标签
- **THEN** Orchestrator SHALL 接收到 `issues` webhook 事件,解析为 `task.created` 事件,提取 Issue 编号、标题、描述、标签、仓库信息
#### Scenario: Issue label changed to trigger assignment
- **WHEN** Issue 的标签从 `agent:code` 变更为 `agent:review`
- **THEN** Orchestrator SHALL 生成 `task.reroute` 事件,重新匹配具备 `review` 能力的 Agent
### Requirement: Task parsing from Issue
Orchestrator SHALL 将 Issue 解析为结构化任务task_id、sourceforgejo issue URL、type由标签推断、priority由 label/milestone 推断、requirementsIssue body、labels。
#### Scenario: Issue with priority label
- **WHEN** Issue 带有 `priority:high` 标签和 `agent:code` 标签
- **THEN** 解析出的任务 SHALL 包含 `priority: "high"``type: "code"`
### Requirement: Agent matching and assignment
Task Router SHALL 根据任务类型、所需能力、Agent 负载和在线状态,将任务分配给最合适的 Agent。
#### Scenario: Match by capability and load
- **WHEN** 一个 `code:typescript` + `review` 类型的任务需要分配
- **THEN** Task Router SHALL 选择声明了对应能力、当前并发任务数未达上限、且状态为 `online` 的 Agent
#### Scenario: No matching agent available
- **WHEN** 没有在线 Agent 满足任务所需能力
- **THEN** 任务 SHALL 进入 `queued` 状态Task Router SHALL 通过 Matrix 通知人工介入
### Requirement: Task lifecycle management
任务 SHALL 具有明确的生命周期状态:`created``assigned``running``completed` / `failed` / `agent_lost`
#### Scenario: Task completes successfully
- **WHEN** Agent 通过 receipt 协议报告任务完成
- **THEN** 任务状态 SHALL 变更为 `completed`Issue 标签 SHALL 更新为 `status:done`
#### Scenario: Task fails with error
- **WHEN** Agent 报告任务失败,附带错误信息
- **THEN** 任务状态 SHALL 变更为 `failed`Issue comment SHALL 写入错误摘要Task Router SHALL 根据策略决定重试或升级
### Requirement: Manual task assignment
人类 SHALL 能通过 Matrix slash command 或 Forgejo Issue comment 手动指定任务分配给特定 Agent。
#### Scenario: Manual assignment via Matrix
- **WHEN** 人类在 Matrix 发送 `/assign @worker-03 issue#42`
- **THEN** Task Router SHALL 将 Issue #42 分配给 agent_id 为 `worker-03` 的 Agent无论自动匹配结果
#### Scenario: Manual assignment via Issue comment
- **WHEN** 人类在 Issue #42 评论 `/assign worker-03`
- **THEN** 效果同上

View file

@ -0,0 +1,82 @@
## 1. 项目脚手架与基础设施
- [ ] 1.1 初始化 Node.js 项目package.json、tsconfig.json、ESLint、Vitest
- [ ] 1.2 搭建项目目录结构src/core、src/adapters、src/integrations、src/api
- [ ] 1.3 部署 Forgejo 实例WSL2 或 Docker创建初始 repo 和 webhook token
- [ ] 1.4 配置 Matrix bot 账号(复用现有 @jeeves:0x08.org 或新建专用 bot
- [ ] 1.5 编写 config.toml schema 和示例配置文件
## 2. Orchestrator Core
- [ ] 2.1 实现数据模型Agent、Task、Receipt、Artifact、TaskEvent 类型定义
- [ ] 2.2 实现 Event StoreSQLite append-only event log写入和查询接口
- [ ] 2.3 实现 Task 状态机created → assigned → running → completed/failed/agent_lost/cancelled
- [ ] 2.4 实现全局任务队列:按优先级排序,支持入队/出队/重新入队
- [ ] 2.5 实现任务超时检测:定时扫描 running 任务,超时标记为 failed
- [ ] 2.6 实现重试策略:可配置 max_retries + 退避间隔,自动重试 transient failure
- [ ] 2.7 编写 Orchestrator Core 单元测试
## 3. Agent Registry
- [ ] 3.1 实现 `POST /api/v1/agents/register`Agent 注册,支持重复注册更新
- [ ] 3.2 实现 `POST /api/v1/agents/heartbeat`:心跳更新,记录 last_heartbeat_at
- [ ] 3.3 实现 `POST /api/v1/agents/deregister`:注销,重新入队该 Agent 的 running 任务
- [ ] 3.4 实现 `GET /api/v1/agents`:查询 Agent 列表,支持 capability 和 status 过滤
- [ ] 3.5 实现心跳超时检测后台定时扫描3 次超时标记 offline触发 agent_lost
- [ ] 3.6 编写 Agent Registry 单元测试
## 4. Forgejo Integration
- [ ] 4.1 实现 Forgejo API clientIssue CRUD、Comment、Label、PR、Webhook 验证
- [ ] 4.2 实现 `POST /api/v1/webhooks/forgejo`:接收 Forgejo webhook验证签名解析事件
- [ ] 4.3 实现 Issue → Task 转换:解析 label 推断 type/priority创建 Task 对象
- [ ] 4.4 实现 Task 状态 → Issue label 同步status:todo/doing/doneassignee 更新
- [ ] 4.5 实现 Receipt → Issue comment 回写:结构化 commentemoji + summary + artifact links
- [ ] 4.6 实现 Reconciliation对账定期轮询 Forgejo Issue弥补 webhook 丢失
- [ ] 4.7 编写 Forgejo Integration 单元测试和集成测试
## 5. Matrix ChatOps
- [ ] 5.1 实现 Matrix bot 连接:使用 matrix-bot-sdk连接 0x08.org homeserver
- [ ] 5.2 实现 `/fleet status` slash command展示所有 Agent 状态
- [ ] 5.3 实现 `/assign <agent> <issue>` slash command手动分配任务
- [ ] 5.4 实现 `/retry <issue>` slash command重新入队失败任务
- [ ] 5.5 实现通知推送task assigned、completed、failed、agent offline 等事件推送到协同房间
- [ ] 5.6 实现 per-agent thread每个 Agent 的执行日志发到独立 thread/topic
- [ ] 5.7 编写 Matrix ChatOps 单元测试
## 6. Receipt Protocol
- [ ] 6.1 实现 `POST /api/v1/receipts`:接收 Agent 提交的 receipt
- [ ] 6.2 实现 receipt validation验证 PR 是否存在Forgejo API 查询、commit 是否包含修改
- [ ] 6.3 实现 no-trust 检查:任务只在 receipt 验证通过后才变更为 completed
- [ ] 6.4 编写 Receipt Protocol 单元测试
## 7. Agent Adapter Interface
- [ ] 7.1 定义 adapter interface TypeScript 类型register/heartbeat/execute/submit_receipt/deregister
- [ ] 7.2 实现 adapter 配置加载:从 config.toml 读取各 Agent 实例的 adapter 类型和参数
- [ ] 7.3 实现 adapter health checkCLI 检查、API 可达性检查
- [ ] 7.4 实现 adapter runner管理 adapter 生命周期(启动、心跳、停止)
## 8. Claude Code Adapter第一个具体实现
- [ ] 8.1 实现 Claude Code adapterspawn `claude -p --output-format json`,注入 task prompt
- [ ] 8.2 解析 Claude Code JSON 输出为 receipt提取 PR、文件修改、summary
- [ ] 8.3 实现 workspace 管理:为每个任务创建/复用 git worktree
- [ ] 8.4 编写 Claude Code adapter 集成测试
## 9. Codex CLI Adapter第二个具体实现
- [ ] 9.1 实现 Codex adapterspawn `codex exec --json`,注入 task prompt
- [ ] 9.2 解析 Codex JSON 输出为 receipt
- [ ] 9.3 实现 Codex session resume可选
- [ ] 9.4 编写 Codex adapter 集成测试
## 10. 端到端验证
- [ ] 10.1 部署完整系统Forgejo + Orchestrator + Matrix bot + 1 个 Claude Code Agent
- [ ] 10.2 端到端测试:创建 Issue → webhook → 任务创建 → Agent 分配 → 执行 → Receipt → Issue comment → Matrix 通知
- [ ] 10.3 端到端测试Agent 离线 → 心跳超时 → 任务 agent_lost → 重新入队
- [ ] 10.4 端到端测试:任务超时 → 自动 failed → Matrix 通知
- [ ] 10.5 编写运维文档:部署、配置、排障