10 Commits
4 changed files with 225 additions and 19 deletions
+48 -4
View File
@@ -7,22 +7,66 @@ The AI coding agent built for the terminal.
**Unix (Linux/macOS):**
```bash
curl -fsSL http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/main/install | bash
curl -fsSL https://eightarms.net/Octopus/octopus-release/raw/branch/main/install | bash
```
**Windows (PowerShell):**
```powershell
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/main/install.ps1 | iex
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
irm https://eightarms.net/Octopus/octopus-release/raw/branch/main/install.ps1 | iex
```
### Manual install
If the one-liner fails with a connection error, the direct connection to `eightarms.net` is likely being filtered on your network. Download the archive for your platform from the [releases page](https://eightarms.net/Octopus/octopus-release/releases/latest) and install it manually instead.
**Unix (Linux/macOS):**
```bash
# after downloading octopus-<platform>.tar.gz from the releases page
tar -xzf octopus-linux-x64.tar.gz
sudo mv octopus /usr/local/bin/
octopus --version
```
**Windows (PowerShell):**
After downloading `octopus-windows-x64.zip` from the releases page:
```powershell
$zip = "$env:USERPROFILE\Downloads\octopus-windows-x64.zip"
$dest = "$env:USERPROFILE\.octopus\bin"
$tmp = Join-Path $env:TEMP "octopus_manual"
New-Item -ItemType Directory -Force -Path $dest,$tmp | Out-Null
Expand-Archive -Path $zip -DestinationPath $tmp -Force
Copy-Item "$tmp\octopus.exe" "$dest\octopus.exe" -Force
Remove-Item -Recurse -Force $tmp
$p = [Environment]::GetEnvironmentVariable('Path','User')
if ($p -notlike "*$dest*") { [Environment]::SetEnvironmentVariable('Path', ($p.TrimEnd(';') + ";$dest"), 'User') }
& "$dest\octopus.exe" --version
```
Open a **new** terminal and run `octopus`.
## Desktop (beta)
Prefer a GUI? The Octopus desktop app ships a Windows beta build alongside the CLI:
- **Windows:** download [`octopus-desktop-win-x64.exe`](https://eightarms.net/Octopus/octopus-release/releases/download/desktop-beta/octopus-desktop-win-x64.exe) from the [`desktop-beta` channel](https://eightarms.net/Octopus/octopus-release/releases/tag/desktop-beta) and run the installer. Installed builds auto-update themselves from the same channel.
- This is a beta channel — expect rough edges. macOS builds are on the way but not published yet.
## Documentation
Visit the [documentation](http://octopus.51zxtx.com:3000/fourbroad/octopus/wiki) for usage guides and API reference.
Visit the [documentation](https://eightarms.net/Octopus/octopus/wiki) for usage guides and API reference.
## Workflow
Curious how Octopus organizes agent work? Read about the **ticket-driven workflow system** (in Chinese): [docs/workflow.zh.md](docs/workflow.zh.md)
## Development
The source code and issue tracker are available at the [private development repository](http://octopus.51zxtx.com:3000/fourbroad/octopus).
The source code and issue tracker are available at the [private development repository](https://eightarms.net/Octopus/octopus).
## License
+162
View File
@@ -0,0 +1,162 @@
# Octopus 工单驱动的工作流体系
> Octopus 不只是一个会写代码的终端 AI 代理——它是一套**以工单为契约、以门禁为骨架**的工程化工作流体系。每一个功能、每一个修复、每一次重构,都作为一张类型化工单进入管线,沿着确定的路由前进,穿过强制的评审与验证门禁,最终带着完整的可审计记录落进主干。
## 为什么需要工单驱动
AI 代理写代码的能力已经足够强,真正的工程难题在于**治理**。在 Octopus 中,工单(issue)不是旁路的需求登记簿,而是流程的驱动轴,它同时解决四件事:
| 难题 | 工单驱动给出的答案 |
| --- | --- |
| **边界** | 一张工单天然划定"做什么 / 不做什么",代理的每次行动都有明确授权范围 |
| **验收** | 工单携带验收标准(acceptance criteria),完成与否可被第三方验证,而不是"看起来对了" |
| **审计** | 从分解、评审、实现到验证,每一步都产出持久化工件,事后可以回答"这个变更为什么发生、经过谁之手" |
| **并行** | 多个人类与多个代理会话基于工单分工协作,互不踩踏(配合 git worktree 会话隔离) |
支撑这一切的铁律是**声明纪律(claim discipline**:任何状态断言——"测试通过"、"缺陷已修复"、"工作完成"——都必须有**当轮产出的新鲜证据**(命令、输出、退出码)支撑。置信不是证据,上一次运行的结果不是证据,"改动看起来对"更不是证据。
## 类型驱动路由:标签即流程
每张工单的 `Kind/*` 标签决定它的整条流程路线——进入哪个技能、跳过哪些阶段、哪些门禁必须保留。这套路由由一张**路由表**(`workflow-routing.yaml`)声明式定义,主会话在任何动作之前先经 **Step 0 路由解析**`route_resolver`)查表,而不是临场自由发挥。
当前路由表速览:
| 工单类型 | 入口技能 | 保留的强制门禁 | 语义要点 |
| --- | --- | --- | --- |
| `Kind/Epic` | `analyze-dag` | review-dag, verify | 需求聚合 → 分解为任务 DAG(见下节) |
| `Kind/Feature` | `analyze-dag` | review-dag, review-code, verify | 新功能同样走 DAG 管线;退化情形(工单自带实现)保留 review-code |
| `Kind/Task` | 继承父级 | review-code, verify | DAG 父级下的子工单,走任务路由 implement → review-code → verify |
| `Kind/Bug` | `implement`bugfix 模式) | review-code, verify | 缺陷报告本身就是规格说明——无需需求/设计阶段,但修复必须被证明 |
| `Kind/Security` | `implement`bugfix 模式) | review-code, verify | 紧急缺陷处理;若改动认证/权限契约,属设计级触发 → 升格 `Kind/Feature` |
| `Kind/Refactor` | `implement`refactor 模式) | review-code, verify | 行为保持不变的重构;大型跨文件重构在迭代内分批 |
| `Kind/Testing` | `implement` | review-code, verify | 仅测试变更;verify 强制(测试必须跑绿) |
| `Kind/Process` | `review-artifact`(过程审计) | audit-process | 改的是 `.octopus/` 工作流系统本身——先审计再落地 |
| `Kind/Documentation` | 直接编辑 | (可选轻量评审) | 文档不进完整管线,除非它编码了一份契约 |
| `Kind/MVP` | 交互模式(无管线) | 无 | 早期概念:工单体即文档,维护决策日志与债务登记 |
| 无标签 | 自然语言匹配 | 按匹配结果 | 未标注的工单行为与路由启用前完全一致 |
三条结构性原则:
1. **路由是纯增量的(additive**:路由只能跳过某类工单*不需要*的阶段,永远不能削弱强制门禁。路由表的 `skip` 与技能自身的强制门取**交集**——两边都同意可跳,才算可跳。
2. **标签错了不悄悄改**:如果 `Kind/Bug` 挂在了一个功能形态的工单上,代理不会擅自改标签,而是按标签走路由、同时显式上报不匹配——标签的正确性归创建者所有。
3. **大 Bug 升格规则**:根因是设计决策、或改动共享契约/公共 API/数据迁移的缺陷,已经超出了 Bug 类型的容量——强制升格 `Kind/Feature` 走小型 DAG(预期 1–3 节点),绝不把设计级变更硬塞进 bugfix 通道。
## DAG 工单管线:分解即计划
`Kind/Epic``Kind/Feature` 进入 **DAG 工单管线**——工作流体系最核心的特征。传统做法里"路线图 → 需求 → 设计 → 迭代计划"是四份会互相漂移的文档;Octopus 把它们合并成**一份任务 DAG 工件**:
```
analyze-dag 分解 ──▶ 任务 DAG 工件 ──▶ review-dag 单门 ──PASS──▶ 建 Kind/Task 子工单
(节点=验收标准 (TOPO/REQMAP/ │
边=跨节点契约 RELEASE 三维评审) ▼
拓扑=执行计划) 每张子工单:
implement → review-code → verify
```
**分解(analyze-dag**。Analyst 把 Epic 分解为一张任务 DAG:每个 `task` 节点就是一条可验收的工作项,每条边是节点之间的**契约**(跨会话接口承诺),拓扑顺序就是执行计划。分解产出即冻结副本,后续所有会话以它为共同基线。
**单门评审(review-dag**。三个维度并行评审:**TOPO**(拓扑合理吗)、**REQMAP**(验收标准覆盖需求吗)、**RELEASE**(切分可发布吗)。这一道门替代了旧体系的"设计空间评审 + 迭代计划评审"两道门,且**结构性永不裁剪**never_trim)。
**深度即档位(size_derivation**。评审深度不是拍脑袋定的,由 DAG 的实测属性派生:
| 维度 | D1 | D2 | D3 | D4 |
| --- | --- | --- | --- | --- |
| 节点数 | ≤3 | 48 | 915 | >15 |
| 跨会话边数 | 0 | — | ≤3 | ≥4 |
| 契约变更面 | 无 | — | 仅新增 | 破坏性 |
取三维最坏值定 D1–D4,D1 由 1 名评审员 2 轮收敛,D4 是 5 名评审员(TOPO:2 REQMAP:2 RELEASE:1 分维)最多 4 轮。**分解即定档**——不再需要人工挂规模标签。
**运行期增长信号**。实现期现实与分解漂移时,管线不装死:节点分裂、出现评审范围外的新跨会话边、已冻结契约被破坏——任何一条触发都强制**重新派生深度 + 重跑 review-dag**。工单类型也不是一成不变的:现实超出标签容量时,"按书面执行、把疑点摆上桌面"、可见地重分类。
**里程碑汇聚(verify_milestone**。跨会话扇入 ≥2 的汇聚点自动焊入里程碑;全部入边任务完成且绿灯后触发集成验证(DoD 矩阵由 DAG 切片自动生成)。里程碑本身不建工单——它的完成定义由 verify 承担。
## 强制门禁:review-code 与 verify
管线里的每段生产工作后面都紧跟一道评审门禁,**没有例外路径**:
- **review-code**——代码评审门。按风险档位并行派出最多 10 名独立评审员(Explorer 子代理),每人一个维度对照评审清单扫描,Worker 编排者汇总发现、开发者修订,迭代至收敛。DAG 任务模式下评审对照冻结的 DAG 节点规格与跨会话契约做范围比对——节点实现蔓延出分解边界本身就是发现。
- **verify**——验证门。运行迭代的 DoD(完成定义)矩阵、集成测试、NFR 校验与回归检查。**迭代在所有 DoD 项通过之前不算完成**——无论代码看起来多好。
- **评审轮次预算**。默认 2 轮、高风险 3 轮封顶——超预算未收敛即 STOP,剩余发现转入技术债务登记册收口,不允许无限马拉松式评审。
## 人机决策门:自动批准的边界
代理需要不停地做流程决策("评审通过了,进入下一阶段吗?")。Octopus 把决策门分成性质完全不同的两类:
**执行类门禁可以白名单放行**`auto_approve.stages` 声明哪些阶段的问题可自动通过(如 `review-code``verify``audit-process`)。即便自动放行,还有一条**活人降级链**:有真人在线看着会话(L1)→ 问题落到 Gitea 工单评论等回复(L2)→ 才轮到推荐项自动默认(L3)。
**业务决策永远必须人答**。以下类别的问题**无条件强制人工确认**(`destructive` 铁律,任何白名单都不覆盖):
1. 合并 PR 到主干 / 打 tag / 发版 / 上生产
2. 生产数据库写入(含迁移、回填)
3. 计费与套餐变更
4. 组织 / 租户结构变更
5. 删除持久资源
6. 超出会话生命周期的持久配置写入
一条阶段白名单授予的是"执行门可以不间断前进",**永远不是**"业务决策可以自问自答"。
## 工单生命周期治理
- **认领与 WIP 上限**:开放的无主工作票超过上限(默认 40 张)时,新工作票必须携带排期证据,否则降为登记册行——用机制而非纪律防止工单堆积。
- **冲刺降档(sprint-mode)**:冲刺期间独立工单创建冻结、登记照常(严重度零丢失),开关回落后登记行按正常链路升格。失败证据类工单不受降档影响——失败必须立即可见。
- **MVP 早期概念模式**:一张工单、一个线程、零管线开销;工单体即文档(每决策一行:选了什么/为什么/何时失效)。出现第二个消费者、外部契约或决策冲突即"毕业"——升格标签,反向进入 DAG 管线的回填模式。
- **生产者预检(preflight)**:复盘阶段统计每条路线首轮评审 FAIL/WARN 的高频根因,把 Top 根因作为检查清单**注入**该路线的实现派发(如"动手前每个验收标准必须映射到可证伪的测试断言")——在人犯错之前提醒人,而不是在评审里再抓一遍。清单项的进入与退出都有数据阈值,提示词永不自动变异。
## 两层工件体系:过程即档案
每个工作流运行(run)的所有产物落入**两层工件体系**,索引守卫保证可恢复、可审计:
| 层 | 位置 | 受众 | 内容 |
| --- | --- | --- | --- |
| Tier 1 | `.octopus/runs/{slug}/` | 机器 | 运行索引、DAG 冻结副本、每轮评审发现 JSON、DoD 矩阵 |
| Tier 2 | Gitea wiki `{slug}/` 空间 | 人 | 评审综合报告、计划页、叙述性文档 |
配套的**压缩纪律**保证长管线跑得完:上下文压缩只发生在干净的阶段边界(工件已持久化之后),且由容量触发器驱动;压缩后代理不依赖对话记忆,而是**重读持久化工件**恢复现场。任何压缩摘要开头都有身份卡,先核对身份再继续干活——防止拿着上一个会话的残影做这个会话的决定。
## 多智能体协作模型
Octopus 的主会话是**协调者而非工人**:
- **Explorer 子代理**——只读探索:找文件、搜模式、回答"X 怎么工作",结果即时返回;
- **Worker 子代理**——多步执行:写代码、跑测试、修失败,**先持久化产出再结束**;
- **并行派发**——独立子任务一次性并行发出,避免主会话上下文被文件内容与工具输出淹没。
会话级隔离由 **git worktree 纪律**保障:并发分支工作必须各占独立 worktree(主 checkout 单占用),分支劫持事故有审计日志可归因;子代理共享同一工作流 worktree——隔离发生在工作流之间,而不是协同的子代理之间。
## 合并队列:落地的最后一道秩序
代码评审收敛后,PR 打上 `ready-to-merge` 标签进入**服务端串行合并队列**:
- 队头 PR 由协调机器人校验"标签 + 双绿(CI 检查 + 合并门)+ 风险双检(有 `Risk/Low` 且无 `Risk/High`"后 approve 并合并;
- 非队头 PR 自动做 keep-mergeable 保活(绝不手写合并 main 的保活提交);
- 机械类低风险 PR(依赖升级、锁文件、bot 作者)走 **fast-lane** 快速通道自动补标签;
- 真冲突的 PR 经 merge-tree 预探后出队留痕,不动分支。
## 一张工单的完整旅程
以一个新功能为例,把所有机制串起来:
1. **创建**:功能工单打上 `Kind/Feature` 标签,写清动机与验收期望;
2. **路由**:主会话 Step 0 查路由表 → DAG 管线,先过过程评估门再动手;
3. **分解**`analyze-dag` 产出任务 DAG——节点是验收标准、边是契约、拓扑是计划;实测属性派生出 D1–D4 档位;
4. **单门**`review-dag` 三维并行评审(拓扑/需求映射/可发布性),迭代至收敛 PASS;
5. **拆票**:聚合代理为每个任务节点建一张 `Kind/Task` 子工单,父工单聚合状态总览;
6. **实现**:每张子工单独立走 `implement`(含生产者预检)——在独立 worktree 分支上;
7. **代码评审**`review-code` 多评审员对照节点规格与冻结契约并行扫描,轮次预算内收敛;
8. **验证**`verify` 跑 DoD 矩阵与集成测试;跨会话汇聚点触发里程碑验证;
9. **落地**PR 打 `ready-to-merge` 进合并队列,双绿 + 风险双检通过后自动合并进主干;
10. **归档**:全部工件已在两层体系留档,工单关闭——过程即档案。
## 小结
工单驱动不是"给 AI 加了个 TODO 列表",而是一套完整的工程治理契约:
- **类型即路由**——标签决定流程,流程不再临场发挥;
- **分解即计划**——一份 DAG 工件替代四份会漂移的文档;
- **门禁即质量**——评审与验证不可绕过、不可裁剪、有轮次预算;
- **证据即真相**——没有新鲜证据的状态断言一律无效;
- **工件即档案**——过程可恢复、决策可追溯;
- **人在环上**——执行门可自动,业务决策永远人工。
这套体系本身也是工单驱动的:对 `.octopus/` 工作流系统的任何改进都走 `Kind/Process` 过程审计路由——系统吃自己的狗粮。
+9 -9
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Public release repository:
# http://octopus.51zxtx.com:3000/fourbroad/octopus-release
# https://eightarms.net/Octopus/octopus-release
set -euo pipefail
APP=octopus
@@ -22,8 +22,8 @@ Options:
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
Examples:
curl -fsSL https://octopus.51zxtx.com/install | bash
curl -fsSL https://octopus.51zxtx.com/install | bash -s -- --version 1.0.180
curl -fsSL https://eightarms.net/install | bash
curl -fsSL https://eightarms.net/install | bash -s -- --version 1.0.180
./install --binary /path/to/octopus
EOF
}
@@ -183,24 +183,24 @@ else
fi
if [ -z "$requested_version" ]; then
specific_version=$(curl -s "${GITEA_API_URL:-http://octopus.51zxtx.com:3000/api/v1}/repos/fourbroad/octopus-release/releases?limit=1" | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
specific_version=$(curl -s "${GITEA_API_URL:-https://eightarms.net/api/v1}/repos/Octopus/octopus-release/releases?limit=1" | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
if [[ $? -ne 0 || -z "$specific_version" ]]; then
echo -e "${RED}Failed to fetch version information${NC}"
exit 1
fi
url="${OCTOPUS_DOWNLOAD_BASE:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/download/v${specific_version}/$filename"
url="${OCTOPUS_DOWNLOAD_BASE:-https://eightarms.net}/Octopus/octopus-release/releases/download/v${specific_version}/$filename"
else
# Strip leading 'v' if present
requested_version="${requested_version#v}"
url="${OCTOPUS_DOWNLOAD_BASE:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/download/v${requested_version}/$filename"
url="${OCTOPUS_DOWNLOAD_BASE:-https://eightarms.net}/Octopus/octopus-release/releases/download/v${requested_version}/$filename"
specific_version=$requested_version
# Verify the release exists before downloading
http_status=$(curl -sI -o /dev/null -w "%{http_code}" "${GITEA_URL:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases/tag/v${requested_version}")
http_status=$(curl -sI -o /dev/null -w "%{http_code}" "${GITEA_URL:-https://eightarms.net}/Octopus/octopus-release/releases/tag/v${requested_version}")
if [ "$http_status" = "404" ]; then
echo -e "${RED}Error: Release v${requested_version} not found${NC}"
echo -e "${MUTED}Available releases: ${GITEA_URL:-http://octopus.51zxtx.com:3000}/fourbroad/octopus-release/releases${NC}"
echo -e "${MUTED}Available releases: ${GITEA_URL:-https://eightarms.net}/Octopus/octopus-release/releases${NC}"
exit 1
fi
fi
@@ -456,6 +456,6 @@ echo -e ""
echo -e "cd <project> ${MUTED}# Open directory${NC}"
echo -e "octopus ${MUTED}# Run command${NC}"
echo -e ""
echo -e "${MUTED}For more information visit ${NC}https://octopus.51zxtx.com/docs"
echo -e "${MUTED}For more information visit ${NC}https://eightarms.net/docs"
echo -e ""
echo -e ""
+6 -6
View File
@@ -1,5 +1,5 @@
#Requires -Version 5.1
# Public release repository: http://octopus.51zxtx.com:3000/fourbroad/octopus-release
# Public release repository: https://eightarms.net/Octopus/octopus-release
<#
.SYNOPSIS
Octopus installer for Windows.
@@ -14,10 +14,10 @@
Do not add the install directory to the user PATH.
.EXAMPLE
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/dev/install.ps1 | iex
irm https://eightarms.net/Octopus/octopus-release/raw/branch/dev/install.ps1 | iex
.EXAMPLE
irm http://octopus.51zxtx.com:3000/fourbroad/octopus-release/raw/branch/dev/install.ps1 | iex; Install-Octopus -Version 0.1.3
irm https://eightarms.net/Octopus/octopus-release/raw/branch/dev/install.ps1 | iex; Install-Octopus -Version 0.1.3
#>
[CmdletBinding()]
param(
@@ -29,8 +29,8 @@ Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$APP = "octopus"
$REPO = "fourbroad/octopus-release"
$baseUrl = if ($env:OCTOPUS_DOWNLOAD_BASE) { $env:OCTOPUS_DOWNLOAD_BASE } else { "http://octopus.51zxtx.com:3000" }
$REPO = "Octopus/octopus-release"
$baseUrl = if ($env:OCTOPUS_DOWNLOAD_BASE) { $env:OCTOPUS_DOWNLOAD_BASE } else { "https://eightarms.net" }
$INSTALL_DIR = Join-Path $env:USERPROFILE ".octopus\bin"
function Write-Color([string]$Text, [string]$Color = "White") {
@@ -194,7 +194,7 @@ function Install-Octopus {
Write-Host " octopus " -NoNewline; Write-Host "# Run command" -ForegroundColor DarkGray
Write-Host ""
Write-Host "For more information visit " -NoNewline -ForegroundColor DarkGray
Write-Host "https://octopus.51zxtx.com/docs"
Write-Host "https://eightarms.net/docs"
Write-Host ""
}