feat: dual execution model (SSH CLI + HTTP pull)
- ExecutionMode enum: SshCli (orchestrator dispatches) | HttpPull (agent pulls) - SSH CLI executor: spawn remote agents via ssh + CLI template - Local subprocess as SSH special case (localhost) - HostConfig with capability matching and load-based selection - Dispatch loop: scan created tasks → select host → execute → update - CliAdapterConfig: CLI templates for Codex and Claude Code - Structured prompt construction (Issue → goal/constraints/validation) - Output parsers: Codex JSON, Claude Code JSON, raw fallback - TaskStatus::ReviewPending + review_count loop limit - Forgejo webhook: pull_request (opened→review_pending, merged→completed) - Forgejo webhook: push events (task/* branch → last_activity_at) - HTTP API: dequeue only returns http_pull tasks - HTTP API: status update only for http_pull mode - Token auth config for http_pull agents - Adapter module rewritten: AgentAdapter trait removed → config-driven CLI templates - New fields: execution_mode, assigned_host, branch_name, pr_title, last_activity_at, review_count - 30/30 tests pass
This commit is contained in:
parent
1bc7580ecc
commit
e39a16498c
34 changed files with 2541 additions and 1555 deletions
|
|
@ -0,0 +1,2 @@
|
|||
schema: spec-driven
|
||||
created: 2026-05-12
|
||||
107
openspec/changes/adapter-cross-machine-revision/design.md
Normal file
107
openspec/changes/adapter-cross-machine-revision/design.md
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
## Context
|
||||
|
||||
当前 adapter interface 基于 spawn 本地进程模式,无法满足跨机协同的核心目标。实际使用中暴露了通知机制不可靠的问题(Codex 完成任务后 Jeeves 收不到通知)。
|
||||
|
||||
核心认知转变:
|
||||
- **Orchestrator 不调用 Agent,Agent 调用 Orchestrator**(pull 模型)
|
||||
- **Git/Forgejo 是状态追踪的 source of truth**(PR 生命周期 = 任务生命周期)
|
||||
- **通知 = Git 事件**(push → 进度信号,PR opened → 完成通知,PR merged → receipt 验证)
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Agent 通过 HTTP API 主动拉取任务、更新状态、提交 receipt(任何机器、任何语言)
|
||||
- 利用 Forgejo PR webhook 作为可靠的状态追踪和通知机制
|
||||
- 消除"Agent 完成但无人知道"的问题
|
||||
- Agent client 可以是任何语言实现(curl 就能交互)
|
||||
|
||||
**Non-Goals:**
|
||||
- 不实现 Agent 侧的 client SDK(Agent 自己决定用什么语言/方式调用 HTTP API)
|
||||
- 不实现 Orchestrator → Agent 的主动推送(pull 模型足够,Phase 2 可加 SSE)
|
||||
- 不修改 Forgejo webhook 已有的实现(复用现有 `POST /api/v1/webhooks/forgejo`)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: Pull 模型(Agent 主动拉取任务)
|
||||
|
||||
**选择**: Agent 通过 `POST /api/v1/tasks/dequeue` 主动拉取
|
||||
|
||||
**理由**:
|
||||
- 跨机场景下 Orchestrator 无法主动连接 Agent(防火墙、NAT、离线)
|
||||
- Agent 最清楚自己什么时候有空
|
||||
- Pull 模型天然负载均衡——空闲 Agent 自然拉更多任务
|
||||
- 无需长连接、无需消息队列
|
||||
|
||||
**替代方案**:
|
||||
- Push 模型(Orchestrator 推送):需要 Agent 暴露端点,复杂度高
|
||||
- 消息队列(NATS/Redis):增加基础设施依赖
|
||||
|
||||
### Decision 2: Forgejo PR lifecycle 作为通知机制
|
||||
|
||||
**选择**: 利用 Git 事件(push → PR opened → PR merged)作为任务状态追踪
|
||||
|
||||
**理由**:
|
||||
- Forgejo webhook 已经实现,可靠性由 Forgejo 保证
|
||||
- PR 本身就是 code review 流程——天然对应任务的"完成→验证"流程
|
||||
- 解决了实际遇到的通知丢失问题:即使 Agent 直接通知失败,Forgejo webhook 仍然会触发
|
||||
- PR merged = 自动 receipt 验证(PR 存在且被 merge = 代码确实被接受)
|
||||
|
||||
**替代方案**:
|
||||
- SSE/WebSocket 推送:需要保持长连接,跨网络不可靠
|
||||
- Agent 回调 URL:需要 Agent 暴露端点
|
||||
- 轮询:可行但延迟高,且不解决"Agent 完成后通知谁"的问题
|
||||
|
||||
### Decision 3: Registry token 认证
|
||||
|
||||
**选择**: Agent 注册后获得 token,后续请求需携带
|
||||
|
||||
**理由**:
|
||||
- 轻量级,不需要 OAuth 或 JWT
|
||||
- 防止未授权的 Agent 领取任务
|
||||
- token 在重新注册时刷新
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[Pull 延迟] Agent 需要定期 dequeue 轮询** → Agent 可以在 heartbeat 周期内顺便 dequeue,不增加额外开销
|
||||
- **[PR 必需] 强制要求 Agent 创建 PR** → 非 PR 任务通过 `/complete` 端点完成,两条路径在 receipt 验证层汇合
|
||||
- **[Forgejo 单点] Forgejo 挂了通知就断了** → Forgejo 本身是 Git source of truth,挂了整个流程都停,可接受
|
||||
- **[死循环] Review 循环可能无限** → max_retries 限制 + review_count 跟踪
|
||||
|
||||
## Key Design Principles (from community best practices)
|
||||
|
||||
基于 ChatGPT 讨论和社区最佳实践的几个核心原则:
|
||||
|
||||
1. **Agent 是纯函数 worker**:输入 task + artifact,输出 artifact + state change。不保留跨任务状态。
|
||||
2. **状态机驱动,不对话驱动**:所有 Agent 只对共享状态(SQLite + Forgejo)读写,由 Orchestrator loop 推进流程
|
||||
3. **结构化 handoff**:Agent 之间不传 chat history,只传结构化 artifact(receipt、plan、review)
|
||||
4. **Git worktree 隔离**:每个 task 独立分支,避免并发冲突
|
||||
5. **Deterministic verification**:不依赖 Agent 自我判断,用 `cargo test` / `npm test` 等确定性验证
|
||||
6. **80/20 原则**:80% 自动运行,20% 人类介入(失败、架构决策、优先级调整)
|
||||
7. **外部调度 + 内部自治**:agent-fleet 只管理任务状态和 artifact 流转,Agent 的执行 runtime(hooks、compaction、sandbox、tool loop、session 管理)由 Agent 自己负责。agent-fleet 是 Kubernetes,Agent 是 Pod。
|
||||
8. **不替代 Agent runtime**:Claude Code / Codex / OpenCode 的价值在于它们的 runtime,不是模型本身。agent-fleet 不重新实现 tool loop、context compaction、patch management 等。
|
||||
|
||||
基于 ChatGPT 讨论和社区最佳实践的几个核心原则:
|
||||
|
||||
1. **Agent 是纯函数 worker**:输入 task + artifact,输出 artifact + state change。不保留跨任务状态。
|
||||
2. **状态机驱动,不对话驱动**:所有 Agent 只对共享状态(SQLite + Forgejo)读写,由 Orchestrator loop 推进流程
|
||||
3. **结构化 handoff**:Agent 之间不传 chat history,只传结构化 artifact(receipt、plan、review)
|
||||
4. **Git worktree 隔离**:每个 task 独立分支,避免并发冲突
|
||||
5. **Deterministic verification**:不依赖 Agent 自我判断,用 `cargo test` / `npm test` 等确定性验证
|
||||
6. **80/20 原则**:80% 自动运行,20% 人类介入(失败、架构决策、优先级调整)
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 新增 `POST /api/v1/tasks/dequeue` 端点
|
||||
2. 新增 `POST /api/v1/tasks/{task_id}/status` 端点
|
||||
3. 新增 `GET /api/v1/tasks/{task_id}` 端点
|
||||
4. 扩展 Forgejo webhook 处理:支持 `pull_request` 和 `push` 事件
|
||||
5. 重写 `src/adapters/mod.rs`:从 AgentAdapter trait 改为 Agent Protocol 描述文档
|
||||
6. 新增 token 认证中间件
|
||||
7. 更新测试
|
||||
|
||||
## Open Questions
|
||||
|
||||
_(resolved — 见下方)_
|
||||
|
||||
- ~~非 PR 任务(research、review)如何触发完成通知?~~ → 使用 `POST /api/v1/tasks/{id}/complete` + receipt,与 PR 路径在 receipt 验证层汇合
|
||||
- ~~Token 认证是否需要在 Phase 1 实现?~~ → 必须在 Phase 1 实现,否则无法安全对接远程 Agent
|
||||
37
openspec/changes/adapter-cross-machine-revision/proposal.md
Normal file
37
openspec/changes/adapter-cross-machine-revision/proposal.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
## Why
|
||||
|
||||
当前 adapter interface 设计基于 **spawn 本地进程** 模式(`execute(task)` 由 orchestrator 主动调用 Agent),这无法满足跨机协同的核心目标:
|
||||
|
||||
1. **spawn 只能本机执行**:无法调度远程机器上的 Agent
|
||||
2. **ACP 只能同实例通信**:无法跨 OpenClaw 实例
|
||||
3. **主动推送模式不可靠**:Orchestrator 无法主动通知远端 Agent 执行任务(可能离线、网络不通)
|
||||
|
||||
此外,**通知机制缺失**是一个实际遇到的生产问题:Codex 写完代码后,Jeeves 没有可靠的方式收到完成通知,导致任务卡住直到人工干预。
|
||||
|
||||
agent-fleet 的核心价值是**跨机 Agent 协同**,需要一个基于 HTTP 的、可靠的 pull + push 混合模式。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **BREAKING**: `AgentAdapter` trait 中的 `execute(task)` 方法移除。Orchestrator 不主动调用 Agent 执行,而是 Agent 主动拉取任务
|
||||
- 新增 **Agent pull 模式**:`POST /api/v1/tasks/dequeue` — Agent 主动请求领取任务
|
||||
- 新增 **Git-based 状态追踪**:Agent 执行完成后推送代码到 Forgejo → Forgejo PR webhook 触发状态更新 → 替代 unreliable 的直接通知
|
||||
- 新增 **任务状态查询**:`GET /api/v1/tasks/{task_id}` — Agent 可轮询任务状态
|
||||
- 保留 receipt 提交(`POST /api/v1/receipts`)作为最终确认
|
||||
- Adapter config 从"本地执行参数"改为"远程 Agent 连接信息"
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `task-assignment-protocol`: Agent 任务拉取协议(dequeue + 状态更新 + receipt 确认)
|
||||
- `notification-via-forgejo`: 基于 Git/Forgejo 的状态追踪和通知机制(PR webhook → 状态同步)
|
||||
|
||||
### Modified Capabilities
|
||||
- `agent-adapter`: 从"本地 spawn 执行"改为"远程 Agent 通过 HTTP API 自主交互"。Adapter interface 不再包含 execute(),改为 Agent 侧的客户端 SDK 协议
|
||||
- `agent-registry`: 补充 Agent 认证机制(registry token),确保只有注册的 Agent 能领取任务
|
||||
|
||||
## Impact
|
||||
|
||||
- **代码**:`src/adapters/mod.rs` 重写(AgentAdapter trait → AgentClient SDK 协议描述)
|
||||
- **API**:新增 `POST /api/v1/tasks/dequeue`,新增 `GET /api/v1/tasks/{task_id}`
|
||||
- **通知机制**:利用现有 Forgejo PR webhook 作为状态追踪和通知通道,无需新增基础设施
|
||||
- **配置**:adapter config 从本地参数改为 Agent 连接信息
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Unified adapter interface
|
||||
系统 SHALL 定义统一的 Agent 客户端协议(非 trait),描述远程 Agent 如何通过 HTTP API 与 Orchestrator 交互。Agent 可以运行在任何机器上,只要能访问 Orchestrator 的 HTTP 端点。
|
||||
|
||||
协议 SHALL 包含:
|
||||
- `POST /api/v1/agents/register` — 注册到 Registry
|
||||
- `POST /api/v1/agents/heartbeat` — 发送心跳
|
||||
- `POST /api/v1/tasks/dequeue` — 主动拉取任务(替代被动的 execute)
|
||||
- `POST /api/v1/tasks/{task_id}/status` — 更新任务状态
|
||||
- `GET /api/v1/tasks/{task_id}` — 查询任务详情
|
||||
- `POST /api/v1/receipts` — 提交 receipt
|
||||
- `POST /api/v1/agents/deregister` — 注销
|
||||
|
||||
#### Scenario: Remote Agent on different machine
|
||||
- **WHEN** Agent `worker-03` 运行在 host-worker-02(与 Orchestrator 不同机器)
|
||||
- **THEN** Agent SHALL 通过 HTTP 调用 Orchestrator API 完成注册、领取任务、提交 receipt
|
||||
- **AND** 无需 SSH、无需共享文件系统、无需同一 OpenClaw 实例
|
||||
|
||||
#### Scenario: OpenClaw-managed Agent
|
||||
- **WHEN** Agent 由 OpenClaw 管理(如 Jeeves 调度 Codex)
|
||||
- **THEN** OpenClaw Agent SHALL 作为 Orchestrator 的客户端,通过 HTTP API 调用
|
||||
- **AND** 任务的实际执行由 OpenClaw 内部的 ACP 机制完成
|
||||
|
||||
### Requirement: Adapter configuration
|
||||
每个 Agent 实例 SHALL 通过配置文件指定 Orchestrator 连接信息、自身身份、工作参数。
|
||||
|
||||
#### Scenario: Remote Agent configuration
|
||||
- **WHEN** Agent 在远程机器上配置
|
||||
- **THEN** 配置 SHALL 包含:`{orchestrator_url: "http://arm0:9090", agent_id: "worker-03", token: "xxx", capabilities: ["code:rust"], work_dir: "/path/to/repo"}`
|
||||
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Adapter health check
|
||||
**Reason**: Orchestrator 不再主动连接 Agent。健康检查通过心跳机制实现——Agent 主动发心跳,Orchestrator 检测超时。
|
||||
**Migration**: 已有心跳机制(`POST /api/v1/agents/heartbeat` + TimeoutChecker)覆盖此需求。
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Agent self-registration
|
||||
每台机器上的 Agent 启动时 SHALL 向 Orchestrator Registry 注册自身信息。注册成功后 SHALL 返回 registry token,后续 API 调用需携带此 token。
|
||||
|
||||
#### Scenario: New agent starts and registers
|
||||
- **WHEN** 一个远程 Agent 在 host-worker-02 上启动
|
||||
- **THEN** 它 SHALL 调用 `POST /api/v1/agents/register`
|
||||
- **AND** Orchestrator 记录该 Agent 信息并返回 `{agent_id, registry_token}`
|
||||
- **AND** 后续所有 Agent API 调用 SHALL 在 header 中携带 `Authorization: Bearer {registry_token}`
|
||||
|
||||
#### Scenario: Duplicate registration with same agent_id
|
||||
- **WHEN** 已注册的 Agent 重启后再次注册(相同 agent_id)
|
||||
- **THEN** 系统 SHALL 更新该 Agent 的信息并返回新的 registry token
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
## ADDED Requirements
|
||||
|
||||
### Requirement: Git branch as task execution unit
|
||||
每个任务 SHALL 关联一个 Git 分支。Agent 在该分支上工作,通过 PR 提交结果。分支命名约定:`task/{task_id}`(例如 `task/org%2Frepo%2342`)。
|
||||
|
||||
#### Scenario: Agent creates branch for task
|
||||
- **WHEN** Agent 领取任务 org/repo#42
|
||||
- **THEN** Agent SHALL 在目标仓库创建分支 `task/org%2Frepo%2342`(基于 master/main)
|
||||
|
||||
#### Scenario: Agent pushes commits to task branch
|
||||
- **WHEN** Agent 执行过程中产生代码变更
|
||||
- **THEN** Agent SHALL 推送 commit 到对应的 task 分支
|
||||
|
||||
### Requirement: PR webhook as completion notification
|
||||
Agent 完成任务后 SHALL 在 Forgejo 创建 Pull Request。Forgejo 的 PR webhook 触发 Orchestrator 状态更新,替代不可靠的直接通知。
|
||||
|
||||
#### Scenario: Agent creates PR → Orchestrator receives webhook
|
||||
- **WHEN** Agent 为任务 org/repo#42 创建 PR
|
||||
- **AND** Forgejo 触发 `pull_request.opened` webhook
|
||||
- **THEN** Orchestrator SHALL 收到 webhook,识别 PR 标题或分支名中的 task_id
|
||||
- **AND** 将任务状态更新为 `review_pending`(等待 receipt 验证)
|
||||
|
||||
#### Scenario: PR merged → receipt auto-validated
|
||||
- **WHEN** PR 被 merge
|
||||
- **AND** Forgejo 触发 `pull_request.merged` webhook
|
||||
- **THEN** Orchestrator SHALL 自动将任务状态转为 `completed`,生成 receipt
|
||||
- **AND** 在对应 Issue 添加评论:`✅ Task completed — PR #15 merged`
|
||||
|
||||
### Requirement: Task branch and PR naming convention
|
||||
Orchestrator SHALL 在任务详情中返回预期的分支名和 PR 标题格式,供 Agent 使用。
|
||||
|
||||
#### Scenario: Task detail includes branch info
|
||||
- **WHEN** Agent 查询 `GET /api/v1/tasks/org/repo#42`
|
||||
- **THEN** 返回 JSON SHALL 包含 `branch_name` 和 `pr_title` 字段
|
||||
- **AND** `branch_name` 格式为 `task/{url_encoded_task_id}`
|
||||
- **AND** `pr_title` 格式为 `feat: {issue_title} (#{issue_number})`
|
||||
|
||||
### Requirement: Push events as progress tracking
|
||||
Forgejo push webhook SHALL 作为 Agent 工作进度的间接信号。
|
||||
|
||||
#### Scenario: Agent pushes to task branch
|
||||
- **WHEN** Forgejo 触发 `push` webhook,目标分支匹配 `task/*` 模式
|
||||
- **THEN** Orchestrator SHALL 记录该 push 事件作为任务进度信号
|
||||
- **AND** 更新任务的 `last_activity_at` 时间戳
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
## ADDED Requirements
|
||||
|
||||
### Requirement: Agent task dequeue (pull model)
|
||||
Agent SHALL 通过 `POST /api/v1/tasks/dequeue` 主动拉取任务。Orchestrator 根据 Agent 声明的 capabilities 匹配最优任务,原子性地分配给该 Agent。
|
||||
|
||||
#### Scenario: Agent dequeues a matching task
|
||||
- **WHEN** Agent `worker-03` 发送 `POST /api/v1/tasks/dequeue`,body 包含 `{agent_id: "worker-03", capabilities: ["code:rust", "review"]}`
|
||||
- **THEN** Orchestrator SHALL 在单个事务中找到 status=created 且匹配 capabilities 的最高优先级任务
|
||||
- **AND** 将该任务状态转为 `assigned`,assigned_agent_id 设为 `worker-03`
|
||||
- **AND** 返回任务详情 JSON
|
||||
|
||||
#### Scenario: No matching task available
|
||||
- **WHEN** Agent 发送 dequeue 但无匹配任务
|
||||
- **THEN** Orchestrator SHALL 返回 204 No Content
|
||||
|
||||
### Requirement: Agent task status update
|
||||
Agent 执行过程中 SHALL 通过 `POST /api/v1/tasks/{task_id}/status` 更新任务状态。
|
||||
|
||||
#### Scenario: Agent starts execution
|
||||
- **WHEN** Agent 开始执行任务,发送 `POST /api/v1/tasks/org/repo#42/status` body `{status: "running"}`
|
||||
- **THEN** Orchestrator SHALL 将任务状态更新为 `running`,记录 started_at
|
||||
|
||||
#### Scenario: Agent reports progress
|
||||
- **WHEN** Agent 发送状态更新但任务已不在 assigned 给该 Agent
|
||||
- **THEN** Orchestrator SHALL 返回 403 Forbidden
|
||||
|
||||
### Requirement: Single task detail query
|
||||
Orchestrator SHALL 提供 `GET /api/v1/tasks/{task_id}` 返回单个任务详情。
|
||||
|
||||
#### Scenario: Query existing task
|
||||
- **WHEN** 发送 `GET /api/v1/tasks/org/repo#42`
|
||||
- **THEN** 返回任务完整信息 JSON(包含所有字段和事件历史)
|
||||
|
||||
#### Scenario: Query non-existent task
|
||||
- **WHEN** 发送 `GET /api/v1/tasks/nonexistent`
|
||||
- **THEN** 返回 404 Not Found
|
||||
|
||||
### Requirement: Agent authentication
|
||||
Agent 调用任务相关 API(dequeue、status update、receipt)时 SHALL 携带注册时获得的 token。Orchestrator SHALL 验证 token 有效性。
|
||||
|
||||
#### Scenario: Valid token
|
||||
- **WHEN** Agent 携带有效 token 调用 dequeue
|
||||
- **THEN** 请求正常处理
|
||||
|
||||
#### Scenario: Invalid or missing token
|
||||
- **WHEN** Agent 不携带 token 或 token 无效
|
||||
- **THEN** 返回 401 Unauthorized
|
||||
|
||||
### Requirement: Non-PR task completion endpoint
|
||||
对于不产生 PR 的任务(research、review 等),Agent SHALL 通过 `POST /api/v1/tasks/{task_id}/complete` 显式提交完成,并附带 receipt。
|
||||
|
||||
#### Scenario: Agent completes a non-PR task
|
||||
- **WHEN** Agent 发送 `POST /api/v1/tasks/org/repo#42/complete`,附带 receipt
|
||||
- **THEN** Orchestrator SHALL 验证 receipt(与 `POST /api/v1/receipts` 相同验证逻辑)
|
||||
- **AND** 任务状态转为 `completed`
|
||||
|
||||
#### Scenario: Non-owner attempts to complete
|
||||
- **WHEN** 非 assigned Agent 尝试 complete
|
||||
- **THEN** 返回 403 Forbidden
|
||||
|
||||
### Requirement: Review loop limit
|
||||
任务在 `running` ↔ `review_pending` 之间循环 SHALL 有最大次数限制,防止死循环。
|
||||
|
||||
#### Scenario: Review loop exceeds limit
|
||||
- **WHEN** 任务的 review 循环次数超过 `max_retries`
|
||||
- **THEN** Orchestrator SHALL 将任务标记为 `failed`
|
||||
- **AND** 在对应 Issue 添加评论说明超限原因
|
||||
48
openspec/changes/adapter-cross-machine-revision/tasks.md
Normal file
48
openspec/changes/adapter-cross-machine-revision/tasks.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
## 1. API 端点新增
|
||||
|
||||
- [ ] 1.1 实现 `POST /api/v1/tasks/dequeue`:Agent 主动拉取任务,根据 capabilities 匹配,原子分配(复用 EventStore::dequeue_and_assign)
|
||||
- [ ] 1.2 实现 `POST /api/v1/tasks/{task_id}/status`:Agent 更新任务状态(assigned→running 等),验证 agent 归属
|
||||
- [ ] 1.3 实现 `GET /api/v1/tasks/{task_id}`:返回单个任务详情 JSON
|
||||
- [ ] 1.4 实现 `POST /api/v1/tasks/{task_id}/complete`:非 PR 任务显式完成 + receipt 验证
|
||||
- [ ] 1.5 在 EventStore 中添加 `read_task_with_events(task_id)` 方法(任务详情 + 事件历史)
|
||||
- [ ] 1.6 在 `src/main.rs` 注册新路由
|
||||
|
||||
## 2. Token 认证
|
||||
|
||||
- [ ] 2.1 在 register 响应中生成并返回 registry_token(随机 UUID 或 HMAC)
|
||||
- [ ] 2.2 在 EventStore 中存储 agent_id → token 映射
|
||||
- [ ] 2.3 实现 axum middleware 验证 `Authorization: Bearer {token}` header
|
||||
- [ ] 2.4 将 middleware 应用于任务相关端点(dequeue、status、complete、receipt)
|
||||
- [ ] 2.5 heartbeat 和 deregister 端点也要求 token 认证
|
||||
|
||||
## 3. Forgejo webhook 扩展
|
||||
|
||||
- [ ] 3.1 扩展 Forgejo webhook handler 支持 `pull_request` 事件(opened、merged)
|
||||
- [ ] 3.2 PR opened → 从分支名解析 task_id → 更新任务状态为 `review_pending`
|
||||
- [ ] 3.3 PR merged → 从分支名解析 task_id → 自动生成 receipt → 任务状态转为 `completed` → Issue 评论
|
||||
- [ ] 3.4 扩展 Forgejo webhook handler 支持 `push` 事件:匹配 `task/*` 分支 → 更新 `last_activity_at`
|
||||
- [ ] 3.5 在 Task 模型中添加 `branch_name`、`pr_title`、`last_activity_at` 字段
|
||||
|
||||
## 4. State machine 扩展
|
||||
|
||||
- [ ] 4.1 添加 `review_pending` 状态(running → review_pending → completed/running)
|
||||
- [ ] 4.2 添加 `review_count` 字段到 Task,跟踪 review 循环次数
|
||||
- [ ] 4.3 review_count 超过 max_retries 时自动标记 failed
|
||||
|
||||
## 5. Adapter 模块重写
|
||||
|
||||
- [ ] 5.1 重写 `src/adapters/mod.rs`:移除 `AgentAdapter` trait 和 `AdapterRunner`,改为 Agent Protocol 文档
|
||||
- [ ] 5.2 保留 `AdapterInstanceConfig` 和 `AdapterKind`(用于配置和文档生成)
|
||||
- [ ] 5.3 移除 `AdapterRunner`(Agent 自行管理生命周期)
|
||||
|
||||
## 6. 测试与验证
|
||||
|
||||
- [ ] 6.1 `cargo check` 通过
|
||||
- [ ] 6.2 `cargo test` 全部通过
|
||||
- [ ] 6.3 新增 dequeue 测试(匹配成功、无匹配任务、并发 dequeue)
|
||||
- [ ] 6.4 新增 status update 测试(正常更新、非所属 Agent 被拒)
|
||||
- [ ] 6.5 新增 token 认证测试(有效 token、无效 token、缺失 token)
|
||||
- [ ] 6.6 新增 complete 端点测试(正常完成、非 owner 被拒)
|
||||
- [ ] 6.7 新增 Forgejo PR webhook 测试(PR opened → review_pending、PR merged → completed)
|
||||
- [ ] 6.8 新增 push webhook 测试(task 分支 → last_activity_at 更新)
|
||||
- [ ] 6.9 新增 review loop limit 测试(超过 max_retries → failed)
|
||||
Loading…
Add table
Add a link
Reference in a new issue