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,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