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:
Zer4tul 2026-05-12 14:07:56 +08:00
parent 1bc7580ecc
commit e39a16498c
34 changed files with 2541 additions and 1555 deletions

View file

@ -0,0 +1,63 @@
## ADDED Requirements
### Requirement: SSH CLI execution mode
Orchestrator SHALL 支持通过 SSH 在远程主机上执行 Agent CLI 命令。这是 subprocess CLI 的跨机等价Orchestrator 构造上下文、主动启动 Agent、等待完成、收集输出。
#### Scenario: Execute Codex on remote host
- **WHEN** 任务分配给 host-worker-02 上的 Codex Agent
- **THEN** Orchestrator SHALL 通过 SSH 连接 host-worker-02
- **AND** 执行 `codex exec --json '{structured_prompt}'`
- **AND** 等待命令完成,解析 JSON 输出为 receipt
#### Scenario: Execute Claude Code on remote host
- **WHEN** 任务分配给 host-worker-03 上的 Claude Code Agent
- **THEN** Orchestrator SHALL 通过 SSH 连接 host-worker-03
- **AND** 执行 `claude -p '{structured_prompt}' --output-format json --dangerously-skip-permissions`
- **AND** 等待命令完成,解析 JSON 输出为 receipt
#### Scenario: SSH connection fails
- **WHEN** Orchestrator 无法 SSH 连接到目标主机
- **THEN** 任务 SHALL 标记为 `failed`,记录连接错误
- **AND** 如果 retry_count < max_retries SHALL 自动重试
#### Scenario: Agent CLI returns non-zero exit code
- **WHEN** 远程 CLI 命令返回非零退出码
- **THEN** 任务 SHALL 标记为 `failed`,记录 stderr 输出
### Requirement: Structured prompt construction
Orchestrator SHALL 为每个任务构造结构化 prompt通过 CLI 参数传入 Agent。Prompt 内容包括:任务目标、约束条件、影响文件范围、验证命令。
#### Scenario: Prompt for code task
- **WHEN** 任务为代码实现类型
- **THEN** prompt SHALL 包含Issue 标题和描述、任务约束(从 Issue labels 提取)、预期输出格式、验证命令(`cargo test` / `npm test`
#### Scenario: Prompt for review task
- **WHEN** 任务为代码审查类型
- **THEN** prompt SHALL 包含PR diff、审查要点、审查结果格式要求
### Requirement: CLI command templates
每种 Agent 类型 SHALL 有可配置的 CLI 命令模板。模板支持变量替换:`{prompt}``{work_dir}``{task_id}``{branch}`
#### Scenario: Codex CLI template
- **WHEN** Agent 类型为 `codex-cli`
- **THEN** 命令模板 SHALL 为 `codex exec --json '{prompt}'`
- **AND**`{work_dir}` 目录下执行
#### Scenario: Custom template
- **WHEN** 用户配置自定义 CLI 模板
- **THEN** SHALL 支持变量替换:`{prompt}``{work_dir}``{task_id}``{branch}`
### Requirement: Output parsing
Orchestrator SHALL 解析 Agent CLI 的 JSON 输出为 receipt。
#### Scenario: Parse Codex JSON output
- **WHEN** Codex CLI 输出 JSON
- **THEN** SHALL 提取statuscompleted/failed、summary、artifactschanged files、PR URL、duration
#### Scenario: Parse Claude Code JSON output
- **WHEN** Claude Code CLI 输出 JSON
- **THEN** SHALL 提取status、summary、artifacts、duration
#### Scenario: Malformed output
- **WHEN** Agent 输出无法解析为有效 JSON
- **THEN** 任务 SHALL 标记为 `failed`,记录原始输出