跳轉到

Bullinv Forge:MVP 開發規格書

本文件供工程團隊實作使用,與 MVP 完整定義 對齊。若兩者有衝突,以本文件「實作決策」章節為準並回寫產品文件。

0. 文件目的與讀者

  • 讀者:後端、前端、DevOps、負責 Worker 的工程師。
  • 目標:在約 4~8 週(依人力)內交付可內部試用的 MVP(見驗收清單)。

1. 技術選型(建議預設)

層級 建議 說明
前端 Next.js(App Router)+ TypeScript 與業界一致,SSR/CSR 皆可。
後端 API Python 3.11+ + FastAPI(或等價框架) AI 生態與迭代速度友善。
Worker Python 獨立進程(同 repo 或同套件 worker 模組) 與 API 共用 domain 型別與 client。
資料庫 PostgreSQL 15+ 單一主庫;MVP 不使用 pgvector
ORM / Migration SQLAlchemy 2 + Alembic(或 SQLModel) 依團隊習慣二選一。
快取 / 佇列 可不使用;若需要佇列可用 DB job 表或 Redis(選配) MVP 優先簡單。
容器 Docker Compose(api + web + db + worker) 內部部署一致。

Go / Node 後端:若團隊全棧熟 Go,可替換 API 層,但需自行補齊本規格中的 API 契約與遷移;預設以 Python 為準。

2. 系統架構與服務邊界

2.1 進程清單(MVP)

  1. webNext.js,對使用者瀏覽器。
  2. api:REST(+ 可選 WebSocket/SSE 給 run 串流,選配)。
  3. worker:輪詢 api、執行 CLI、回報 run 事件。
  4. postgres:主資料庫。
flowchart LR
  Browser --> web
  web --> api
  api --> postgres
  worker --> api
  worker --> LocalCLI[codex_or_claude]
  api --> LinearAPI[Linear_API_optional]

2.2 責任邊界

服務 負責 不負責
web UI、表單驗證、呼叫 api、顯示 run 時間線 不直接呼叫 Linear;不持有 service token(除使用者 OAuth 若未來做)
api Auth、授權、Task/Run CRUD、狀態機、Webhook、Linear adapter、發佈給 worker 的「可執行任務」 不在 request 內長跑 CLI
worker 認領/執行、spawn CLI、寫 run events、回寫狀態 不對外暴露 HTTP(可僅出站)

3. 認證與授權

3.1 使用者(瀏覽器)

  • MVP 建議JWT(access + refresh)或 session cookie,擇一。
  • 所有 /api/v1/*(除 login/health)需驗證。
  • 角色workspace_adminworkspace_memberreview 可由 workspace_admin 兼任或獨立 flag(MVP 可簡化為 admin 可審核)。

3.2 Worker

  • 使用 長效 API Token(hash 存 DB,明文僅建立時顯示一次)。
  • Header:Authorization: Bearer <worker_token>
  • Token 綁定:workspace_id + 可選 agent_id 列表(或 worker 註冊時動態 claim agent)。

3.3 Linear(若整合)

  • OAuth 或 API Key 僅存於 server(環境變數或加密欄位);永不下發給前端

4. 資料模型(資料表草案)

命名採 snake_case。以下為 MVP 最小集;可增索引與 audit 欄位。

4.1 users

欄位 型別 說明
id uuid PK
email text unique
password_hash text nullable 若走 OIDC 可空
created_at timestamptz

4.2 workspaces

欄位 型別 說明
id uuid PK
name text
created_at timestamptz

4.3 workspace_members

欄位 型別 說明
workspace_id uuid FK
user_id uuid FK
role text admin | member
PK (workspace_id, user_id)

4.4 agents

欄位 型別 說明
id uuid PK
workspace_id uuid FK
display_name text
runtime_type text MVP 固定 cli
cli_command text 例如 codex
is_active boolean
created_at timestamptz

4.5 tasks

欄位 型別 說明
id uuid PK
workspace_id uuid FK
title text
description text nullable
status text 見 MVP 狀態機
priority text low/medium/high/urgent
assignee_type text human/agent/unassigned
assignee_user_id uuid nullable
assignee_agent_id uuid nullable
source_system text nullable linear
source_ref_id text nullable
source_url text nullable
created_by_user_id uuid nullable
created_at / updated_at timestamptz

索引(workspace_id, status)(workspace_id, updated_at desc)(source_system, source_ref_id) unique partial where both non-null。

4.6 task_comments

欄位 型別 說明
id uuid PK
task_id uuid FK
author_type text user/system
author_user_id uuid nullable
body text
created_at timestamptz

4.7 runs

欄位 型別 說明
id uuid PK
task_id uuid FK
agent_id uuid FK
status text pending/running/completed/failed/cancelled
started_at timestamptz
ended_at timestamptz nullable
exit_code int nullable
error_summary text nullable
workdir_path text nullable 除錯用,可僅 server 可見

4.8 run_events

欄位 型別 說明
id bigserial PK
run_id uuid FK
seq int 每 run 內遞增
occurred_at timestamptz
type text run_started/log/run_completed/run_failed/…
payload jsonb

約束(run_id, seq) unique。

4.9 worker_tokens(或 api_tokens

欄位 型別 說明
id uuid PK
workspace_id uuid FK
token_hash text
label text
created_at timestamptz
revoked_at timestamptz nullable

5. API 契約(REST 草案)

前綴:/api/v1。回應 JSON。錯誤格式:{ "error": { "code", "message", "details?" } }

5.1 Auth

  • POST /auth/register(內部用可關閉,僅 admin 建帳)
  • POST /auth/login → tokens
  • POST /auth/refresh
  • GET /auth/me

5.2 Workspaces

  • GET /workspaces
  • POST /workspaces
  • GET /workspaces/{id}
  • POST /workspaces/{id}/members(admin)

5.3 Tasks

  • GET /workspaces/{ws_id}/tasks?status=&assignee_type=&q=
  • POST /workspaces/{ws_id}/tasks
  • GET /tasks/{id}
  • PATCH /tasks/{id}(狀態、指派、優先級)
  • POST /tasks/{id}/comments
  • POST /tasks/{id}/claim(human 或 worker 流程擇一)
  • POST /tasks/{id}/submit-reviewin_review
  • POST /tasks/{id}/review-decision body: { "decision": "approve"|"reject" }

5.4 Agents

  • GET /workspaces/{ws_id}/agents
  • POST /workspaces/{ws_id}/agents
  • PATCH /agents/{id}

5.5 Runs

  • GET /tasks/{task_id}/runs
  • GET /runs/{run_id}
  • GET /runs/{run_id}/events?after_seq=(分頁)

5.6 Worker 專用(可掛在 /worker/v1 以免與使用者 API 混淆)

  • POST /worker/v1/heartbeat body: { "hostname", "agent_ids": [] }
  • GET /worker/v1/assignments?workspace_id=&agent_id=
    回傳:下一筆待執行 task + run 草稿 id 或建立指令。
  • POST /worker/v1/runs/{run_id}/events batch append
  • PATCH /worker/v1/runs/{run_id} 完成/失敗
  • PATCH /worker/v1/tasks/{task_id} 同步 task 狀態(或由 run 完成時後端一併更新)

實作決策(MVP 建議):Worker 輪詢 GET /worker/v1/assignments 每 3~5 秒;認領時由 API transaction 將 task 從 queuedclaimed 並建立 run,避免雙執行。

6. Worker 執行規格

6.1 環境變數(建議)

變數 說明
FORGE_API_URL API base,如 https://api.internal
FORGE_WORKER_TOKEN
FORGE_WORKSPACE_ID 預設 workspace
FORGE_AGENT_ID 本機對應的 agent
FORGE_WORK_ROOT 工作目錄根,預設 ~/forge_workspaces
FORGE_POLL_INTERVAL_SEC 預設 3
FORGE_RUN_TIMEOUT_SEC 預設 7200

6.2 執行步驟

  1. Heartbeat(可選)。
  2. Poll assignments。
  3. 若取得 task:建立 run(若 API 尚未建則先 POST 建立 run)。
  4. 建立 workdir = FORGE_WORK_ROOT/{task_id}/{run_id}
  5. titledescription、上下文寫入 task.md 或透過 stdin 餵給 CLI(實作選一,全專案統一)。
  6. subprocess.run([cli_command, ...], cwd=workdir, timeout=...),串流 stdout/stderr → run_events type=log
  7. 結束:run_completed / run_failed,更新 task 為 completed/failed/in_review(規則見下)。

6.3 完成規則(MVP 建議寫死)

  • exit_code == 0 且無致命錯誤 → task → in_review(若開啟審核)或直接 completed(可由 workspace 設定 require_review boolean)。
  • exit_code != 0 或 timeout → task → failederror_summary 寫入最後 500 字內摘要。

7. Linear 整合規格(MVP)

7.1 目標

  • Forge tasks.source_* 與 Linear issue 對齊。
  • 至少一種同步路徑(擇一實作):

選項 1 — Webhook:Linear → Forge POST /integrations/linear/webhook,驗簽後 upsert task。

選項 2 — 週期同步:Cron 或 api 內 scheduler 每 N 分鐘拉取指定 team 的 issues,upsert task。

7.2 對應欄位(建議)

Linear Forge
issue id source_ref_id
url source_url
title title
description description
state 映射到 status(需建映射表或簡化對照)

7.3 回寫(P1 可選)

  • Run 完成後呼叫 Linear API 新增 comment:Forge run 連結 + 一行摘要。

8. 前端頁面清單(MVP)

路由 功能
/login 登入
/w/[wsId]/tasks 任務列表 + 篩選
/w/[wsId]/tasks/[taskId] 詳情、留言、狀態操作、runs、events
/w/[wsId]/agents Agent CRUD、顯示最後心跳
/w/[wsId]/settings workspace 名稱、require_review、token 管理(admin)

9. 非功能需求

  • Log:結構化 JSON log,X-Request-Id
  • CORS:僅允許 web origin。
  • Secret:12 factor,禁止 commit .env
  • DB 遷移:所有 schema 必須有 Alembic revision。

10. 測試與驗收

10.1 自動化(最低)

  • API:pytest 覆蓋 auth、task 狀態轉移、worker assignment 併發(單測模擬兩 worker)。
  • 前端:關鍵路徑 e2e 可選(Playwright)。

10.2 MVP 驗收清單(工程)

  • [ ] docker compose up 可啟動 web + api + db + worker。
  • [ ] 使用者可登入、建立 workspace、建立 task、指派 agent。
  • [ ] Worker 可執行 mock CLI(測試用 echo script)並寫入 run events。
  • [ ] UI 可看到 run 時間線。
  • [ ] Review:可演示 approve/reject。
  • [ ] Linear:至少完成「建立 Forge task 帶 source 連結」或「從 Linear 同步一筆」其中一條(與產品對齊)。

11. 建議迭代順序(給排程)

週次 交付
1 DB schema、Auth、Workspace、Task CRUD API、最小 web 列表
2 Task 詳情、Comment、Agent CRUD、狀態機
3 Worker PoC + run/run_events + UI 時間線
4 Review、錯誤處理、token、部署 compose、Linear 整合 alpha
5~6 打磨、權限、文件、optional 回寫 Linear / e2e

12. 與其他文件關係