praetor-execd 規格 v0.1

狀態:設計稿

這份文件定義 praetor-execd 的完整規格。

praetor-execd 是 Praetor 在 subscription executor mode 下使用的宿主機 bridge。

它負責在 不把 Codex / Claude Code 重裝進 Docker 的前提下,讓 Docker 內的 Praetor worker 能受控地呼叫宿主機上已安裝、已登入的 executors。

---

1. 一句話定義

praetor-execd 是一個 只在宿主機本地監聽、只接受受限任務規格、只允許已註冊 executors、只在 allowlisted workspace 內執行 的本機 executor bridge。

它不是:

---

2. 設計目標

praetor-execd 要同時滿足:

1. 讓 Praetor 使用宿主機既有的 Codex / Claude Code

2. 不要求在 Docker 內重裝或重新登入 CLI

3. 讓 Praetor 維持自己的治理與 checkpoint 模型

4. 將底層 CLI 的互動性標準化為 Praetor 可理解的狀態

5. 在安全邊界上嚴格限制 scope、路徑、executor 類型與請求來源

6. 對失敗、取消、超時、auth 過期、approval 要有一致行為

---

3. 非目標

v0.1 的 praetor-execd 不應承擔:

---

4. 角色分工

4.1 Praetor worker 負責

4.2 praetor-execd 負責

4.3 底層 executor 負責

---

5. 信任邊界

5.1 邊界總覽

Owner
  ↓
Praetor Web / Mobile / Telegram
  ↓
Praetor API / Worker (Docker)
  ↓
praetor-execd (Host, loopback only)
  ↓
Codex / Claude Code (Host process)
  ↓
Host workspace

5.2 基本原則

---

6. 支援矩陣

v0.1 正式支援:

可預留但不在 v0.1 正式支援:

每個 executor 都應註冊為明確類型,不接受任意 binary 路徑。

---

7. 部署與程序模型

7.1 執行位置

praetor-execd 必須跑在 Praetor host 上,而不是 Docker stack 內。

7.2 監聽方式

v0.1 建議:

不建議 v0.1:

說明:

7.3 單機常駐進程

praetor-execd 應該是單一常駐 process,內部可管理多個 child process。

它需要:

---

8. 設定檔模型

建議使用:

範例:

server:
  host: 127.0.0.1
  port: 9417
  auth_token: env:PRAETOR_EXECUTOR_BRIDGE_TOKEN

paths:
  host_workspace_root: /absolute/path/to/workspace
  allowed_roots:
    - /absolute/path/to/workspace
  deny_roots:
    - /absolute/path/to/workspace/Archive
    - /absolute/path/to/workspace/.praetor/secrets

executors:
  codex:
    enabled: true
    command: codex
    args: []
    healthcheck: ["codex", "--version"]
    requires_login: true
    supports_noninteractive_batch: true
    supports_cancel: true

  claude_code:
    enabled: true
    command: claude
    args: []
    healthcheck: ["claude", "--version"]
    requires_login: true
    supports_noninteractive_batch: true
    supports_cancel: true

runtime:
  max_concurrent_runs: 2
  default_timeout_seconds: 1800
  max_event_buffer: 5000
  persist_run_logs: true
  log_dir: /absolute/path/to/workspace/.praetor/bridge-logs

8.1 必要欄位

8.2 環境變數覆蓋

至少支援:

---

9. Path Mapping 模型

Praetor 在容器內看到的是 container path,praetor-execd 在 host 上看到的是 host path。

因此 request 必須帶上:

path_mapping:
  container_workspace_root: /app/workspace
  host_workspace_root: /absolute/path/to/workspace
  target_workdir: /app/workspace/Projects/Website

bridge 在執行前應:

1. 驗證 target_workdir 以 container_workspace_root 開頭

2. 將其轉換到 host_workspace_root

3. 做 realpath normalization

4. 驗證結果仍落在 allowlist 內

5. 驗證不在 denylist 內

若任一步驟失敗,直接回 permission_error

---

10. Request / Response 原則

10.1 認證

所有 API 都要求:

token 不通過時:

10.2 Content Type

統一使用:

10.3 Response envelope

建議統一格式:

{
  "ok": true,
  "data": {},
  "error": null
}

錯誤時:

{
  "ok": false,
  "data": null,
  "error": {
    "code": "permission_error",
    "message": "Target path is outside allowed roots."
  }
}

---

11. API Surface

v0.1 正式 API:

可選:

11.1 GET /health

用途:

回傳:

{
  "ok": true,
  "data": {
    "status": "healthy",
    "version": "0.1.0",
    "uptime_seconds": 1024,
    "configured_executors": ["codex", "claude_code"]
  },
  "error": null
}

11.2 GET /executors

用途:

回傳欄位建議:

範例:

{
  "ok": true,
  "data": {
    "executors": [
      {
        "name": "codex",
        "enabled": true,
        "binary_found": true,
        "login_state": "authenticated",
        "supports_noninteractive_batch": true,
        "supports_cancel": true
      }
    ]
  },
  "error": null
}

11.3 POST /runs

用途:

最小 request:

{
  "request_id": "req_123",
  "mission_id": "mission_build_site",
  "task_id": "task_generate_homepage",
  "executor": "codex",
  "timeout_seconds": 1800,
  "path_mapping": {
    "container_workspace_root": "/app/workspace",
    "host_workspace_root": "/absolute/path/to/workspace",
    "target_workdir": "/app/workspace/Projects/Website"
  },
  "task_spec": {
    "title": "Generate homepage draft",
    "instructions": "Work only in the target folder. Do not delete files.",
    "input_files": [
      "/app/workspace/Projects/Website/PROJECT.md"
    ],
    "expected_outputs": [
      "/app/workspace/Projects/Website/homepage.md"
    ],
    "approval_policy": {
      "allow_destructive_write": false,
      "allow_shell": false
    }
  }
}

立即回應:

{
  "ok": true,
  "data": {
    "run_id": "run_abc",
    "status": "accepted",
    "executor": "codex"
  },
  "error": null
}

11.4 GET /runs/{id}

用途:

回傳欄位建議:

11.5 GET /runs/{id}/events

用途:

v0.1 可以先用:

v0.2 可升級:

事件範例:

{
  "ok": true,
  "data": {
    "events": [
      {
        "seq": 1,
        "type": "run_started",
        "ts": "2026-04-24T12:00:00Z"
      },
      {
        "seq": 2,
        "type": "stdout",
        "ts": "2026-04-24T12:00:05Z",
        "data": "Reading project files..."
      },
      {
        "seq": 3,
        "type": "normalized_status",
        "ts": "2026-04-24T12:00:40Z",
        "data": {
          "status": "completed"
        }
      }
    ],
    "next_seq": 4
  },
  "error": null
}

11.6 POST /runs/{id}/cancel

用途:

回傳:

---

12. Run State Machine

12.1 Internal state

accepted
→ validating
→ queued
→ starting
→ running
→ collecting
→ normalizing
→ completed

失敗分支:

accepted
→ validating
→ rejected
running
→ cancelling
→ cancelled
running
→ failed_transient
running
→ failed_permanent

12.2 Normalized status

Praetor 真正該讀的是 normalized status,而不是 child process 細節。

正式狀態:

---

13. Event Model

13.1 事件類型

建議至少支援:

13.2 Event 字段

每個事件至少包含:

13.3 Event 保留策略

v0.1 建議:

---

14. Child Process Model

14.1 啟動原則

bridge 不應直接用 shell 拼字串。

應使用:

14.2 Environment allowlist

只應傳入必要環境變數,例如:

不應把整個 Docker app 環境原樣轉發。

14.3 Working directory

每次 run 必須綁定單一 host target_workdir。

如果 task spec 需要跨多個資料夾:

---

15. Non-interactive Batch 策略

這一節是 praetor-execd 最關鍵的部分。

15.1 原則

Praetor 的產品目標是:

因此 bridge 需要優先選擇 executor 的非互動執行方式。

15.2 若 executor 支援原生非互動模式

bridge 應:

15.3 若 executor 不完全支援非互動模式

bridge 仍應:

- auth_required

- interactive_approval_required

- 或其他對應 normalized status

15.4 v0.1 判斷原則

v0.1 不追求完美模擬所有 CLI 行為。

重點是:

---

16. Artifact / Change Detection

bridge 應協助 Praetor 收集:

v0.1 可用:

不要求 v0.1:

---

17. Usage 與成本資料

bridge 若能從 executor 取得 usage,應回傳:

若取不到,也至少回傳:

不要因為抓不到 token 就讓 run 失敗。

---

18. Error Normalization

bridge 必須把底層錯誤統一成可被 Praetor 使用的錯誤類型。

建議至少分類:

每種錯誤都應帶:

---

19. Healthcheck 模型

19.1 Bridge health

Bridge health 應檢查:

19.2 Executor health

每個 executor health 應檢查:

19.3 Health 狀態分級

---

20. Concurrency 與排程

20.1 基本原則

v0.1 不應允許無限制平行 runs。

建議:

20.2 為什麼要保守

因為 subscription executors 常受:

影響。

保守一點比「理論上能多開」更穩。

---

21. 安全規則

21.1 絕對規則

bridge 不應:

21.2 Host 路徑規則

bridge 必須做:

21.3 Token 規則

---

22. Run Logs 與可追溯性

每個 run 至少應保存:

建議儲存在:

---

23. 與 Praetor Onboarding 的整合

當使用者在 onboarding 選擇 subscription_executor 時:

1. Praetor 先打 GET /health

2. 再打 GET /executors

3. 檢查:

- bridge reachable

- target executor enabled

- binary found

- login_state 可接受

4. 成功才允許完成 runtime 選擇

若失敗,UI 應明確提示:

---

24. 與 Praetor Worker 的整合

Worker 對 bridge 的最小流程:

1. 建立 task spec

2. 呼叫 POST /runs

3. 輪詢 GET /runs/{id} 或 GET /runs/{id}/events

4. 收到 normalized status

5. 將結果映射到 mission state

Task spec 應可攜帶:

model_profile: fast | standard | reasoning | critical
native_subagents: disallowed | allowed

Bridge / executor adapter 可以把 model_profile 映射為 executor-specific model 或 effort setting。若 executor 支援 native subagents / dynamic workflows,只有在 native_subagents: allowed 時才可使用;Praetor 不要求 bridge 暴露每個內部 subagent,但 normalized result 應包含:

Praetor 不在 v1 管理 first-party subagent lifecycle;這些能力屬於 Codex / Claude Code 等 executor 的內部實作。

對應關係建議:

| Bridge normalized status | Praetor mission handling |

|---|---|

| completed | 進入 review 或完成 |

| paused_budget | waiting approval / budget extension |

| paused_decision | waiting owner decision |

| paused_risk | risk checkpoint |

| auth_required | settings / executor reconnect |

| interactive_approval_required | checkpoint requiring owner review |

| failed_transient | 可重試 |

| failed_permanent | 轉人工介入 |

---

25. 實作建議

25.1 技術選擇

建議:

理由:

25.2 v0.1 實作順序

1. config loader

2. auth middleware

3. GET /health

4. GET /executors

5. POST /runs

6. child process capture

7. GET /runs/{id}

8. GET /runs/{id}/events

9. POST /runs/{id}/cancel

10. artifact diff

11. normalized status mapping

---

26. v0.1 仍可接受的限制

v0.1 可以接受:

v0.1 不應接受:

---

27. 最後結論

praetor-execd 的本質不是「幫 Praetor 開 shell」。

它是:

一個把宿主機 subscription executors 安全地包裝成可治理、可追蹤、可非互動批次執行的本機 bridge。

只要這層做對: