pi-claude-supervisor 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/README.cn.md +45 -36
- package/README.md +70 -41
- package/docs/architecture.md +65 -38
- package/docs/automation-hardening-plan.md +23 -22
- package/docs/autonomy-target.md +127 -0
- package/docs/engineering-plan.md +136 -138
- package/docs/implementation-review.md +29 -14
- package/docs/independent-review.md +23 -18
- package/docs/releasing.md +7 -2
- package/docs/testing.md +36 -22
- package/package.json +1 -1
- package/src/acceptance.ts +16 -0
- package/src/config.ts +31 -0
- package/src/decision-session-store.ts +19 -1
- package/src/decision-worker.ts +46 -18
- package/src/index.ts +37 -48
- package/src/notifications.ts +29 -11
- package/src/policy.ts +196 -21
- package/src/reviewer.ts +26 -1
- package/src/state.ts +7 -6
- package/src/supervisor.ts +329 -119
- package/src/types.ts +23 -0
- package/src/verifier.ts +88 -6
- package/src/worker/environment.ts +169 -0
- package/src/worker/process-adapter.ts +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.5.3](https://github.com/btnalit/pi-claude-supervisor/compare/v0.5.2...v0.5.3) (2026-09-15)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* harden unattended local lifecycle ([#27](https://github.com/btnalit/pi-claude-supervisor/issues/27)) ([2bb29d3](https://github.com/btnalit/pi-claude-supervisor/commit/2bb29d3c31f5196f208716723d89b6b538777939))
|
|
11
|
+
|
|
5
12
|
## [0.5.2](https://github.com/btnalit/pi-claude-supervisor/compare/v0.5.1...v0.5.2) (2026-09-14)
|
|
6
13
|
|
|
7
14
|
|
|
@@ -32,10 +39,14 @@ All notable changes to this project will be documented here.
|
|
|
32
39
|
- Pause and rebase the no-output watchdog clock across pause/resume while retaining the cumulative deadline.
|
|
33
40
|
- Include staged, unstaged and bounded untracked evidence in independent Review, with symlink/path safety and fail-closed completeness.
|
|
34
41
|
- Harden assistant-message output framing, startup/runtime preflight, permission gates, bounded acceptance buffers and lifecycle progress reporting.
|
|
42
|
+
- Close automatic startup baseline/worktree/branch validation gaps, including persisted recovery baselines and the final pre-spawn boundary recheck.
|
|
43
|
+
- Replace shell-policy lexical bypasses with quote-aware parsing, nested-shell inspection and protected Git-ref checks; deny dynamic shell expansions while preserving literal argv values, and reject arbitrary non-Claude automatic executables.
|
|
44
|
+
- Normalize malformed custom Reviewer values to blocking reports, persist recovery baselines and the resolved Claude executable identity, filter automatic environment variables with a deny-by-default allowlist, and compare the exact startup HEAD at the adapter spawn boundary.
|
|
45
|
+
- Keep protected CI checks on the exact checked-out commit while giving automatic-mode fixtures a local validation branch and an owned deterministic Claude executable.
|
|
35
46
|
|
|
36
47
|
### Remaining hardening gate
|
|
37
48
|
|
|
38
|
-
-
|
|
49
|
+
- Open the protected pull request and complete independent CI/integration review; the exact-head read-only review, real editable Claude `2.1.270` repair/reacceptance drill and cleanup/lease evidence are recorded in `docs/automation-hardening-plan.md`.
|
|
39
50
|
|
|
40
51
|
### Added
|
|
41
52
|
|
package/README.cn.md
CHANGED
|
@@ -8,24 +8,31 @@
|
|
|
8
8
|
|
|
9
9
|
用于 Pi 的 Claude Code Worker 监督扩展。MVP 中 Pi 负责生命周期、状态机、策略门和独立验收;Worker 只是被显式启动的子进程。
|
|
10
10
|
|
|
11
|
-
> `v0.5.
|
|
12
|
-
> process pipe,不是 PTY;自动模式只使用 Claude JSONL
|
|
11
|
+
> `v0.5.2` 已发布为单 Worker recovery 基线。默认手动 transport 是无额外依赖的
|
|
12
|
+
> process pipe,不是 PTY;自动模式只使用 Claude JSONL,tmux 保留为手动交互。当前工作树已实现
|
|
13
13
|
> repairable/persistent 能力拆分、可取消验收/Reviewer、证据完整性门禁、启动前
|
|
14
14
|
> preflight 和阶段进度通知;真实 Claude Code `2.1.270` 允许编辑的
|
|
15
|
-
> repair/reacceptance 演练已在隔离临时 worktree
|
|
16
|
-
>
|
|
15
|
+
> repair/reacceptance 演练已在隔离临时 worktree 通过。确认的产品目标是本地开发
|
|
16
|
+
> 完全无人值守;详见 [自动化目标](docs/autonomy-target.md)。代码进入远程仓库或
|
|
17
|
+
> main/integration 分支必须经过独立边界,Worker 不拥有 push/merge 权限;自动模式仅使用
|
|
18
|
+
> JSONL,tmux 保留为手动交互 transport。
|
|
19
|
+
>
|
|
20
|
+
> **无人值守状态:** 自动模式会自主完成本地修改、测试、有限修复、验收、独立 Review
|
|
21
|
+
> 和本地提交检查;无法形成候选时自动挂起为不可发布候选。可选出站通知不授予权限,
|
|
22
|
+
> push 和 main/integration merge 仍必须经过独立边界。
|
|
17
23
|
|
|
18
24
|
## 关键安全边界
|
|
19
25
|
|
|
20
26
|
- 不会在扩展加载时自动启动 Worker。
|
|
21
27
|
- 不经过 shell 启动子进程。
|
|
22
|
-
- Worker
|
|
23
|
-
-
|
|
28
|
+
- Worker 只继承最小环境;自动模式采用默认拒绝的环境变量 allowlist,过滤远程凭据并禁用 Git/包管理器 credential helper。自动模式只能选择文档列出的 Claude provider 变量;任意自定义变量仅限手动集成。
|
|
29
|
+
- 本地命令和权限行为按任务/运行时授权策略处理;超出授权的动作自动拒绝或挂起,不要求同步人工响应。
|
|
24
30
|
- Linux 上优先使用可写的 cgroup v2 清理后代进程,包括 `setsid()` 后代;不可用时回退到进程组清理。需要强制失败闭环时,embedding 集成可使用 `cgroupMode: "required"`,并会在 Claude 启动前执行 preflight。
|
|
25
|
-
-
|
|
31
|
+
- 自动模式只接受裸的 `claude`/`claude.exe` 命令名,并从 Supervisor 的 PATH 解析、固定由操作者拥有的可执行文件(或使用 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` 固定路径);显式路径和可写/不可信位置会被拒绝。它请求 fail-closed 的 Claude Code Bash sandbox,禁止 Bash 子进程出站联网;命令策略仍是第二道门。手动/自定义集成必须自行提供等效 host/network 边界。
|
|
26
32
|
- Worker 声称完成只会进入 `verifying`,不能作为成功证据。
|
|
27
33
|
- 默认独立验收命令为 `git diff --check`。
|
|
28
|
-
-
|
|
34
|
+
- 目标是任务启动后本地开发无人值守:Worker 可以修改、测试、修复和本地提交;Worker 必须没有远程 push 或合并到 `main`/integration 分支的权限。
|
|
35
|
+
- 扩展运行时不执行 merge、deploy、release 或 publish;远程/main 集成和仓库 Release 必须经过独立受保护边界。
|
|
29
36
|
- 默认 4 小时总时限、20 分钟无输出 watchdog 超时即停止 Worker;paused 期间不消耗无输出预算,resume 会重建基准但不会重置总时限。嵌入调用方可将对应选项设为 `0` 关闭。
|
|
30
37
|
- 验收命令、仓库证据收集和独立 Reviewer 共用 abort signal,人工 stop/shutdown 不必等待完整超时。
|
|
31
38
|
|
|
@@ -42,14 +49,14 @@ pi install npm:pi-claude-supervisor
|
|
|
42
49
|
```bash
|
|
43
50
|
export PI_CLAUDE_SUPERVISOR_MODE=auto
|
|
44
51
|
export PI_CLAUDE_SUPERVISOR_WORKER='claude --safe-mode --tools Bash'
|
|
45
|
-
#
|
|
52
|
+
# 可选:候选/失败通知;generic 或 wecom
|
|
46
53
|
export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_URL='https://example.invalid/webhook'
|
|
47
54
|
export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_FORMAT=generic
|
|
48
55
|
# export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_SECRET='shared-secret'
|
|
49
56
|
```
|
|
50
57
|
|
|
51
|
-
|
|
52
|
-
`exit` 事件唤醒 Decision Worker
|
|
58
|
+
自动模式默认并且只能使用 `claude-jsonl`,通过 `result`、`control_request` 和进程
|
|
59
|
+
`exit` 事件唤醒 Decision Worker;tmux 仅用于手动屏幕交互,不使用 JSONL 权限协议,也不会依赖 `/supervise poll` 轮询。本版本固定按已验证设备的
|
|
53
60
|
Claude CLI `2.1.270` 运行,跨版本兼容性不在本轮范围内。
|
|
54
61
|
|
|
55
62
|
然后在 Pi 中使用:
|
|
@@ -79,44 +86,47 @@ Claude CLI `2.1.270` 运行,跨版本兼容性不在本轮范围内。
|
|
|
79
86
|
"acceptance": [
|
|
80
87
|
{ "id": "tests", "name": "tests", "command": "npm", "args": ["test"], "required": true }
|
|
81
88
|
],
|
|
82
|
-
"maxRepairRounds": 3
|
|
89
|
+
"maxRepairRounds": 3,
|
|
90
|
+
"autonomy": {
|
|
91
|
+
"unattended": true,
|
|
92
|
+
"requireLocalCommit": true,
|
|
93
|
+
"maxDecisionRetries": 2
|
|
94
|
+
}
|
|
83
95
|
}
|
|
84
96
|
```
|
|
85
97
|
|
|
86
|
-
|
|
98
|
+
候选/失败通知的 generic JSON 格式为(旧 human-intervention webhook 名称保持兼容):
|
|
87
99
|
|
|
88
100
|
```json
|
|
89
101
|
{
|
|
90
|
-
"schema": "pi-claude-supervisor/
|
|
91
|
-
"event": "
|
|
102
|
+
"schema": "pi-claude-supervisor/candidate/v1",
|
|
103
|
+
"event": "candidate_status",
|
|
92
104
|
"task": { "id": "...", "goal": "...", "cwd": "..." },
|
|
93
105
|
"worker": { "id": "..." },
|
|
94
106
|
"reason": "...",
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
107
|
+
"status": "ready|blocked|failed",
|
|
108
|
+
"deliverable": false,
|
|
109
|
+
"note": "This notification does not grant remote push or main/integration merge permission."
|
|
98
110
|
}
|
|
99
111
|
```
|
|
100
112
|
|
|
101
|
-
当前 webhook
|
|
113
|
+
当前 webhook 只是出站候选通知,不直接接受批准命令;显式 stop、takeover 等兼容控制仍通过 Pi。
|
|
102
114
|
自动模式会将 Decision Worker 会话持久化到状态目录。Pi 非正常重启后,`/supervise sessions`
|
|
103
115
|
会显示 `recoverable` 任务;显式执行 `/supervise recover [--takeover] <task-id>` 会恢复 Decision Worker 上下文并
|
|
104
116
|
重新启动 Claude Worker,不会静默恢复或重复执行任务。旧 Pi 进程已退出且租约确认旧 Worker
|
|
105
117
|
进程组已消失且 cgroup 仍是真实、可读取的空边界时,才可显式添加 `--takeover`;缺失、仍存活或无法确认的 Worker 会被拒绝。持久 tmux
|
|
106
118
|
Worker 应使用 `adopt-tmux`,而不是 takeover。
|
|
107
|
-
自动模式下,Decision Worker
|
|
108
|
-
再根据任务和仓库证据自动回答;无法确定时才升级人工。如需微信内闭环,需要另建带签名验证、
|
|
109
|
-
一次性 action token 和重放保护的入站 callback 服务。
|
|
119
|
+
自动模式下,Decision Worker 在任务授权范围内自动处理普通问题、测试失败和修复轮次,记录假设和证据;无法形成可交付候选时自动挂起并保留证据,而不是要求人工必须在线。可通过 `PI_CLAUDE_SUPERVISOR_REQUIRE_LOCAL_COMMIT=0` 或 task `autonomy.requireLocalCommit` 关闭本地 commit 要求,但自动模式仍要求有效 Git baseline 和非保护 worktree;远程 push 和 main/integration merge 仍由独立边界控制。
|
|
110
120
|
|
|
111
121
|
`v0.5.0` 已完成并发布“多命令验收—独立只读 Reviewer—结构化修复轮次—再次验收”闭环。
|
|
112
|
-
任务可通过 API 或 JSON spec 提供 `goal`、`scope`、`constraints`、`forbidden
|
|
113
|
-
`acceptance`
|
|
114
|
-
`read`、`grep`、`find`、`ls
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
任务可通过 API 或 JSON spec 提供 `goal`、`scope`、`constraints`、`forbidden`、多个
|
|
123
|
+
`acceptance` 命令和 `autonomy` 控制;旧的纯文本任务继续使用默认 `git diff --check`。
|
|
124
|
+
Reviewer 只能使用 `read`、`grep`、`find`、`ls`,不会修改工作树或批准权限。自动模式在
|
|
125
|
+
Worker 启动前捕获 git baseline,要求完整的 baseline-relative tracked/commit/untracked evidence,
|
|
126
|
+
并在默认情况下要求 Worker 在非保护分支本地 commit;无效输出、证据不完整、重复 finding、P0/P1 或预算耗尽
|
|
127
|
+
会自动挂起候选。自动模式拒绝 process-pipe 和 tmux,并在模型执行前检查目录、可执行文件、依赖
|
|
128
|
+
和 cgroup;Worker 环境会过滤远程仓库凭据并禁用 Git 全局凭据 helper。详见 [自动化目标](docs/autonomy-target.md)。协同多 Worker 属于后续独立开发阶段,
|
|
129
|
+
自动模式只接受裸的直接 Claude 命令名,会固定解析后的操作者拥有的可执行文件,并请求 fail-closed 的 Claude Code Bash sandbox;任意自定义可执行文件和显式可执行路径会在自动模式拒绝。需要固定路径时设置 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE`。手动/自定义 Worker 的完整 host-level sandbox 仍需由集成方提供。
|
|
120
130
|
|
|
121
131
|
### tmux/PTY 交互模式
|
|
122
132
|
|
|
@@ -125,8 +135,7 @@ exact-head 独立只读 Review;协同多 Worker 属于后续独立开发阶段
|
|
|
125
135
|
```bash
|
|
126
136
|
export PI_CLAUDE_SUPERVISOR_TRANSPORT=tmux
|
|
127
137
|
export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode plan'
|
|
128
|
-
#
|
|
129
|
-
# export PI_CLAUDE_SUPERVISOR_MODE=auto
|
|
138
|
+
# tmux 仅为手动交互;无人值守 Decision Worker 必须使用 JSONL。
|
|
130
139
|
# 接管非默认 tmux server 时可选:
|
|
131
140
|
# export PI_CLAUDE_SUPERVISOR_TMUX_SOCKET=/path/to/tmux.sock
|
|
132
141
|
```
|
|
@@ -134,7 +143,8 @@ export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode plan'
|
|
|
134
143
|
`/supervise start <task>` 会在私有 tmux server 中启动 Claude,并返回可复制的 attach 命令。
|
|
135
144
|
可以在另一个终端 attach 到同一个 PTY,观察或人工输入。多行消息通过 tmux buffer 和 Enter
|
|
136
145
|
发送,不会把消息拼接进 shell 命令;`pipe-pane` 记录原始输出,`capture-pane` 检测稳定的 Claude
|
|
137
|
-
输入提示,并复用 watchdog
|
|
146
|
+
输入提示,并复用 watchdog、审计和独立验收流程;由于 tmux 没有结构化权限边界,
|
|
147
|
+
不会在 tmux 中启用自动 Decision Worker 或无人值守远程边界策略。
|
|
138
148
|
|
|
139
149
|
如果 Claude 已由你在 tmux 中启动,可以显式接管且不会重放原始任务:
|
|
140
150
|
|
|
@@ -149,8 +159,7 @@ export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode plan'
|
|
|
149
159
|
`tmux kill-session`。`/supervise takeover <task-id>` 会暂停 Decision Worker 自动发送,只有
|
|
150
160
|
`/supervise resume-auto <task-id>` 才恢复。
|
|
151
161
|
|
|
152
|
-
PTY 屏幕文字不是 Claude JSONL
|
|
153
|
-
屏幕文字当作结构化权限证据。普通终端里已经运行的 Claude 不能安全迁移进 tmux;`--resume`
|
|
162
|
+
PTY 屏幕文字不是 Claude JSONL,不能把屏幕文字当作结构化权限证据。TUI 决策应按任务授权策略处理并记录;无法形成候选时可以自动挂起,不要求人工持续在线。普通终端里已经运行的 Claude 不能安全迁移进 tmux;`--resume`
|
|
154
163
|
是读取历史的新进程,不是实时 attach。实时测试请使用 plan/read-only 参数。
|
|
155
164
|
|
|
156
165
|
可以从不同工作目录启动多个任务会话;活动会话不能共享同一 cwd,建议每个任务使用独立 worktree:
|
|
@@ -169,4 +178,4 @@ PTY 屏幕文字不是 Claude JSONL。权限/信任对话框和无法确定的 T
|
|
|
169
178
|
|
|
170
179
|
Pull Request 必须通过聚合的 `CI / Quality gate`。Release Please 根据 Conventional Commits 创建版本 PR;维护者合并后,Release workflow 会针对精确 tag commit 重新验证,并通过受保护的 `npm` environment 使用 npm provenance 发布。
|
|
171
180
|
|
|
172
|
-
详细内容见 [engineering-plan.md](docs/engineering-plan.md)、[independent-review.md](docs/independent-review.md)、[architecture.md](docs/architecture.md)、[testing.md](docs/testing.md) 和 [releasing.md](docs/releasing.md)。
|
|
181
|
+
详细内容见 [engineering-plan.md](docs/engineering-plan.md)、[autonomy-target.md](docs/autonomy-target.md)、[independent-review.md](docs/independent-review.md)、[architecture.md](docs/architecture.md)、[testing.md](docs/testing.md) 和 [releasing.md](docs/releasing.md)。
|
package/README.md
CHANGED
|
@@ -10,26 +10,33 @@ A policy-gated [Pi](https://pi.dev) extension for supervising a Claude Code work
|
|
|
10
10
|
The MVP keeps Pi in control of lifecycle, state, policy and verification while the
|
|
11
11
|
worker remains an explicitly started child process.
|
|
12
12
|
|
|
13
|
-
> **Release status:** `v0.5.
|
|
13
|
+
> **Release status:** `v0.5.2` is the released single-Worker recovery baseline. The
|
|
14
14
|
> default manual transport is dependency-free process pipes, not PTY. Automatic
|
|
15
|
-
> supervision uses Claude JSONL
|
|
16
|
-
>
|
|
17
|
-
> completeness gates, startup preflight and phase
|
|
18
|
-
> edit-capable Claude Code `2.1.270` repair/reacceptance
|
|
19
|
-
> isolated temporary worktree
|
|
20
|
-
>
|
|
21
|
-
>
|
|
15
|
+
> supervision uses Claude JSONL only; tmux is manual-only because it has no structured
|
|
16
|
+
> permission boundary. Repairable-vs-persistent capabilities,
|
|
17
|
+
> cancellable verification, evidence completeness gates, startup preflight and phase
|
|
18
|
+
> progress reporting. A real edit-capable Claude Code `2.1.270` repair/reacceptance
|
|
19
|
+
> drill passed in an isolated temporary worktree. The confirmed product target is
|
|
20
|
+
> unattended local development; see [the autonomy target](docs/autonomy-target.md).
|
|
21
|
+
> Remote push and merge into the main/integration branch remain outside Worker authority
|
|
22
|
+
> and must cross an independent boundary.
|
|
23
|
+
>
|
|
24
|
+
> **Autonomy status:** automatic mode continues local editing, testing, bounded repair,
|
|
25
|
+
> acceptance, independent Review and local-commit enforcement without a synchronous human
|
|
26
|
+
> callback. Unresolvable work is parked as a non-publishable candidate; optional outbound
|
|
27
|
+
> notifications do not approve actions.
|
|
22
28
|
|
|
23
29
|
## Safety boundary
|
|
24
30
|
|
|
25
31
|
- The extension never starts a worker automatically.
|
|
26
32
|
- Worker commands are launched without a shell.
|
|
27
|
-
- Workers receive a minimal environment; credentials
|
|
28
|
-
-
|
|
29
|
-
-
|
|
33
|
+
- Workers receive a minimal environment; automatic mode uses a deny-by-default variable allowlist, strips remote credentials and disables Git/package credential helpers. Only documented Claude provider variables may be selected for automatic mode; arbitrary custom variables remain manual-only.
|
|
34
|
+
- Local command and permission behavior follows the configured task/runtime policy; actions outside that authority are rejected or parked without requiring a synchronous human response.
|
|
35
|
+
- Automatic mode admits only the bare `claude`/`claude.exe` command name, resolves and pins an operator-owned executable from the supervisor PATH (or `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE`), and rejects explicit paths or writable/untrusted locations. It requests a fail-closed Claude Code Bash sandbox with no outbound domains; command policy remains a second guard. Manual/custom integrations must provide their own equivalent host/network boundary.
|
|
30
36
|
- A worker completion is only a transition to `verifying`; it is not evidence of success.
|
|
31
37
|
- Verification is an independent host command (default: `git diff --check`).
|
|
32
|
-
-
|
|
38
|
+
- Target local development runs unattended after a task starts: the Worker may edit, test, repair and commit locally. The Worker must have no authority or credentials to push remotely or merge into `main`/an integration branch.
|
|
39
|
+
- The extension never performs merge, deploy, release, or publish at runtime. Remote/main integration and repository releases cross independent protected boundaries.
|
|
33
40
|
- A 4-hour wall-clock and 20-minute no-output watchdog stop a worker by default for long development tasks; embedding callers can set either to `0` to disable.
|
|
34
41
|
- On Linux, the adapter automatically uses a writable cgroup v2 for descendant cleanup, including `setsid()` descendants; it falls back to process-group cleanup when unavailable. Use `cgroupMode: "required"` for a fail-closed integration; required mode is preflighted before Claude starts.
|
|
35
42
|
- Acceptance commands, repository evidence collection and independent Review share an abort signal, so operator stop/shutdown does not wait for a full command or model timeout.
|
|
@@ -86,7 +93,12 @@ a shell), for example:
|
|
|
86
93
|
"acceptance": [
|
|
87
94
|
{ "id": "tests", "name": "tests", "command": "npm", "args": ["test"], "required": true }
|
|
88
95
|
],
|
|
89
|
-
"maxRepairRounds": 3
|
|
96
|
+
"maxRepairRounds": 3,
|
|
97
|
+
"autonomy": {
|
|
98
|
+
"unattended": true,
|
|
99
|
+
"requireLocalCommit": true,
|
|
100
|
+
"maxDecisionRetries": 2
|
|
101
|
+
}
|
|
90
102
|
}
|
|
91
103
|
```
|
|
92
104
|
|
|
@@ -109,25 +121,37 @@ worktrees; same-directory starts are rejected even when concurrent, and
|
|
|
109
121
|
parallelism, not coordinated multi-worker collaboration. A future multi-worker
|
|
110
122
|
milestone will add explicit parent/child task graphs, dependencies, bounded
|
|
111
123
|
scheduling, structured handoffs, aggregate acceptance and graph-aware recovery;
|
|
112
|
-
it will not
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
124
|
+
it will not grant any Worker remote push or main/integration merge authority.
|
|
125
|
+
Unattended local development is the target operating mode; a blocked or failed
|
|
126
|
+
candidate is parked with its evidence rather than made dependent on a human being
|
|
127
|
+
online. Automatic mode accepts only the bare direct Claude command name, pins its
|
|
128
|
+
operator-owned resolved executable path, and uses a fail-closed Bash sandbox with no
|
|
129
|
+
outbound domains; arbitrary custom executables and explicit executable paths are rejected
|
|
130
|
+
in automatic mode. Set `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` when the resolved path must
|
|
131
|
+
be pinned explicitly. Manual/custom integrations must provide an equivalent host/network
|
|
132
|
+
boundary.
|
|
133
|
+
Set `PI_CLAUDE_SUPERVISOR_REQUIRE_LOCAL_COMMIT=0` only for a task that intentionally
|
|
134
|
+
produces no local commit candidate, or set `autonomy.requireLocalCommit` in its spec;
|
|
135
|
+
automatic mode still requires a valid Git baseline and non-protected worktree.
|
|
136
|
+
`PI_CLAUDE_SUPERVISOR_UNATTENDED=0` opts a task out of automatic Decision Worker control;
|
|
137
|
+
a required local commit is checked on a non-protected task branch;
|
|
138
|
+
`PI_CLAUDE_SUPERVISOR_MAX_DECISION_RETRIES` bounds transient Decision Worker retries.
|
|
117
139
|
|
|
118
140
|
The `v0.5.0` automation milestone adds a structured acceptance pipeline:
|
|
119
141
|
multiple argv-based checks, an independent read-only Reviewer, bounded structured
|
|
120
142
|
findings and repair rounds. Legacy text tasks keep the default `git diff --check`.
|
|
121
143
|
The Reviewer only has `read`, `grep`, `find` and `ls`; it cannot edit files or grant
|
|
122
|
-
permissions.
|
|
123
|
-
bounded untracked evidence,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
permissions. Automatic mode requires complete baseline-relative tracked, commit and
|
|
145
|
+
bounded untracked evidence, repairs a live `repairableSession` Worker within a
|
|
146
|
+
bounded budget, enforces a local commit when enabled, and prevents a non-publishable
|
|
147
|
+
candidate from crossing the remote/main boundary. Automatic mode rejects explicit
|
|
148
|
+
`process-pipe` and preflights runtime prerequisites. Invalid output, unavailable
|
|
149
|
+
evidence, duplicate findings, P0/P1 findings and exhausted repair budgets park the
|
|
150
|
+
candidate without waiting for a human; see [the autonomy target](docs/autonomy-target.md).
|
|
127
151
|
Coordinated multi-worker scheduling is a later milestone; CI uses deterministic fake
|
|
128
152
|
Workers/replay fixtures, and real multi-worker Claude tests remain authenticated
|
|
129
|
-
manual Spikes.
|
|
130
|
-
|
|
153
|
+
manual Spikes. Full host-level sandboxing and low-privilege execution for custom
|
|
154
|
+
integrations remain separate hardening work.
|
|
131
155
|
|
|
132
156
|
Automatic mode persists the Pi Decision Worker session under the configured state
|
|
133
157
|
directory. After an unclean Pi restart, `/supervise sessions` lists recoverable
|
|
@@ -138,9 +162,12 @@ the old Worker's process group is gone and its cgroup is a real, readable empty
|
|
|
138
162
|
boundary; missing or unverifiable Worker evidence is refused.
|
|
139
163
|
For a persistent tmux Worker, use explicit `adopt-tmux` instead of takeover.
|
|
140
164
|
The adapter intentionally does not inherit arbitrary host environment variables.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`PI_CLAUDE_SUPERVISOR_WORKER_ENV=ANTHROPIC_API_KEY
|
|
165
|
+
Manual embedding integrations may pass credentials through an explicit
|
|
166
|
+
`WorkerStartInput.env`; automatic mode accepts only documented Claude provider
|
|
167
|
+
variables, for example `PI_CLAUDE_SUPERVISOR_WORKER_ENV=ANTHROPIC_API_KEY`, and
|
|
168
|
+
filters remote credentials and configuration-injection variables. The host-side
|
|
169
|
+
`PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` setting pins the executable identity and is not
|
|
170
|
+
passed into the Worker environment.
|
|
144
171
|
|
|
145
172
|
### tmux/PTY transport
|
|
146
173
|
|
|
@@ -150,19 +177,20 @@ For an interactive Claude Code window, opt in to the tmux transport:
|
|
|
150
177
|
export PI_CLAUDE_SUPERVISOR_TRANSPORT=tmux
|
|
151
178
|
export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode plan'
|
|
152
179
|
# tmux does not support cgroup required mode; use cgroup mode auto/off.
|
|
153
|
-
#
|
|
154
|
-
# export PI_CLAUDE_SUPERVISOR_MODE=auto
|
|
180
|
+
# tmux is manual-only; automatic Decision Worker supervision requires JSONL.
|
|
155
181
|
# Optional, only when adopting a non-default tmux server:
|
|
156
182
|
# export PI_CLAUDE_SUPERVISOR_TMUX_SOCKET=/path/to/tmux.sock
|
|
157
183
|
```
|
|
158
184
|
|
|
159
185
|
`/supervise start <task>` starts Claude in a private tmux server and reports a
|
|
160
186
|
literal attach command. Use that command in another terminal to watch or
|
|
161
|
-
manually interact with the same PTY
|
|
187
|
+
manually interact with the same PTY; attaching is optional for unattended local
|
|
188
|
+
development. The adapter sends multi-line input through
|
|
162
189
|
tmux buffers and Enter, never by interpolating the message into a shell command.
|
|
163
|
-
It records the PTY stream with `pipe-pane
|
|
164
|
-
stable Claude input prompt
|
|
165
|
-
|
|
190
|
+
It records the PTY stream with `pipe-pane` and uses `capture-pane` to detect a
|
|
191
|
+
stable Claude input prompt. Because tmux has no structured permission boundary,
|
|
192
|
+
automatic Decision Worker supervision is disabled for this transport; use JSONL for
|
|
193
|
+
unattended decisions, repair and protected command enforcement.
|
|
166
194
|
|
|
167
195
|
A session that you started yourself can be explicitly adopted without replaying
|
|
168
196
|
the task:
|
|
@@ -183,12 +211,13 @@ kill-session` yourself when the adopted window should be closed.
|
|
|
183
211
|
`/supervise takeover <task-id>` disables automatic Decision Worker messages;
|
|
184
212
|
resume them only with `/supervise resume-auto <task-id>`.
|
|
185
213
|
|
|
186
|
-
PTY screen text is not Claude JSONL
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
`adopt-tmux` after restart. Use
|
|
214
|
+
PTY screen text is not Claude JSONL and must not be treated as structured
|
|
215
|
+
permission evidence. TUI decisions follow the configured autonomy policy and are
|
|
216
|
+
recorded; an unresolved task may be parked without requiring a human to remain
|
|
217
|
+
online. A normal terminal Claude process cannot be migrated into tmux, and
|
|
218
|
+
`--resume` is historical recovery rather than live PTY attach. Owned tmux sessions
|
|
219
|
+
survive a Pi disconnect and require an explicit `adopt-tmux` after restart. Use
|
|
220
|
+
plan/read-only flags for live testing.
|
|
192
221
|
|
|
193
222
|
## Development
|
|
194
223
|
|
|
@@ -202,7 +231,7 @@ npm run check:workflows
|
|
|
202
231
|
npm run build
|
|
203
232
|
```
|
|
204
233
|
|
|
205
|
-
See [the engineering plan](docs/engineering-plan.md), [the independent review](docs/independent-review.md),
|
|
234
|
+
See [the engineering plan](docs/engineering-plan.md), [the confirmed autonomy target](docs/autonomy-target.md), [the independent review](docs/independent-review.md),
|
|
206
235
|
[architecture](docs/architecture.md), [testing](docs/testing.md), and [releasing](docs/releasing.md).
|
|
207
236
|
|
|
208
237
|
Pull requests are gated by the aggregated `CI / Quality gate`. Release Please
|
package/docs/architecture.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
|
+
> The confirmed target is fully unattended local development with an independent remote/main boundary. Automatic mode implements the local editing, testing, repair, acceptance, Review and local-commit loop; unresolved work becomes a parked candidate. Legacy human/takeover APIs remain compatibility controls only. See [autonomy-target.md](autonomy-target.md).
|
|
4
|
+
|
|
3
5
|
## Control boundary
|
|
4
6
|
|
|
5
7
|
Pi owns the `Supervisor`. The supervisor owns the task state machine, event log,
|
|
@@ -17,12 +19,16 @@ Supervisor -> Policy Gate -> WorkerAdapter -> child process
|
|
|
17
19
|
```
|
|
18
20
|
|
|
19
21
|
The Worker cannot advance a task directly to `completed`. A clean worker exit
|
|
20
|
-
moves the supervisor to `verifying`; only
|
|
21
|
-
`completed`.
|
|
22
|
+
moves the supervisor to `verifying`; only successful acceptance, independent Review,
|
|
23
|
+
complete evidence and the configured local-commit boundary move it to `completed`.
|
|
24
|
+
An unresolvable automatic path moves it to `blocked`, never to a publishable result.
|
|
22
25
|
|
|
23
26
|
The extension keeps a registry of independent task sessions. Each session has
|
|
24
27
|
its own Supervisor, watchdog, state machine and Worker handle, while the event
|
|
25
|
-
log is shared and protected by an inter-process lock.
|
|
28
|
+
log is shared and protected by an inter-process lock. Once a task starts, the
|
|
29
|
+
local development loop is intended to run unattended: the Worker may edit, test,
|
|
30
|
+
repair and commit locally. Remote push and merge into `main`/an integration branch
|
|
31
|
+
are outside Worker authority and cross an independent boundary. Concurrent active sessions must use non-overlapping canonical working
|
|
26
32
|
directories/worktrees; same-cwd and parent/child cwd starts are rejected before
|
|
27
33
|
spawn, including concurrent starts, to prevent uncoordinated edits. Pending starts
|
|
28
34
|
are also awaited during Pi shutdown.
|
|
@@ -40,8 +46,11 @@ graph, roles, dependencies, bounded concurrency and structured handoff
|
|
|
40
46
|
artifacts. Child Workers must communicate through validated evidence and event
|
|
41
47
|
references rather than another Worker's control channel. Each child is accepted
|
|
42
48
|
independently; the parent can complete only after aggregate acceptance and
|
|
43
|
-
independent Review. Integration
|
|
44
|
-
|
|
49
|
+
independent Review. Integration and conflict resolution remain separate from the local development
|
|
50
|
+
loop. The Worker cannot push remotely or merge into `main`/an integration branch;
|
|
51
|
+
the independent integration boundary may combine read-only review, CI and an
|
|
52
|
+
authorized integration action in a separate integration worktree. Rejection or
|
|
53
|
+
shutdown leaves the candidate local.
|
|
45
54
|
|
|
46
55
|
Recovery and shutdown must be graph-aware: a parent with an unknown child state
|
|
47
56
|
cannot complete, cancellation must propagate within a bounded budget, and Pi
|
|
@@ -119,9 +128,11 @@ For an owned initial turn, the adapter emits a synthetic `turn_completed` only
|
|
|
119
128
|
after output activity and two stable input-prompt observations. Adopting an idle
|
|
120
129
|
prompt remains inactive and emits no synthetic completion. This is a liveness
|
|
121
130
|
signal, not proof that the task succeeded; the independent verifier remains
|
|
122
|
-
mandatory. Interactive dialogs,
|
|
123
|
-
|
|
124
|
-
|
|
131
|
+
mandatory. Interactive dialogs, trust prompts and ambiguous screens are interpreted by
|
|
132
|
+
the configured autonomy policy and recorded as evidence. An unresolved task is
|
|
133
|
+
parked or failed as a non-publishable candidate rather than requiring a human to
|
|
134
|
+
remain online. Human takeover remains an explicit kill/control path and stops
|
|
135
|
+
automatic messages until `resume-auto`.
|
|
125
136
|
|
|
126
137
|
`/supervise adopt-tmux` is explicit and validates the pinned pane's cwd and
|
|
127
138
|
process identity before attaching. Every later input, capture and signal uses
|
|
@@ -165,7 +176,9 @@ unconfirmed lease left by a crashed Pi is intentionally retained. Ordinary
|
|
|
165
176
|
recovery refuses it; an operator may use `recover --takeover` only when the old
|
|
166
177
|
owner is dead, the Worker process group is gone, and the lease independently
|
|
167
178
|
reads a real empty cgroup boundary for the old Worker. Missing or unverifiable
|
|
168
|
-
Worker evidence
|
|
179
|
+
Worker evidence retains the lease and parks the task rather than performing unsafe
|
|
180
|
+
reclamation; later recovery can inspect or clean it without requiring an operator to
|
|
181
|
+
be online.
|
|
169
182
|
An explicitly adopted tmux session may hand off an existing lease only after
|
|
170
183
|
its owner identity is no longer live and its canonical cwd, tmux session/socket,
|
|
171
184
|
pane id, pane PID/start time, and pane command all match; ordinary starts
|
|
@@ -178,13 +191,20 @@ is alive; the extension periodically rechecks released sessions and removes the
|
|
|
178
191
|
lease only after the pane is confirmed gone. If that check fails, the lease is
|
|
179
192
|
retained rather than allowing a cwd overlap.
|
|
180
193
|
|
|
181
|
-
Before model or Worker execution, automatic starts
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
Before model or Worker execution, automatic starts validate a full existing Git
|
|
195
|
+
baseline, a non-bare worktree, a readable non-protected branch, the direct bare
|
|
196
|
+
`claude`/`claude.exe` command name, JSONL transport, runtime state/lease directories
|
|
197
|
+
and, when requested, the real writable cgroup-v2 boundary. The resolved Claude
|
|
198
|
+
executable is checked for an operator-owned, non-writable path and then pinned by
|
|
199
|
+
absolute path; `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` can pin the expected identity. The initial repository HEAD is captured, and the repository boundary immediately
|
|
200
|
+
before the Worker adapter starts must report that exact same HEAD (recovery captures
|
|
201
|
+
and compares its current HEAD separately while retaining the persisted baseline).
|
|
202
|
+
The built-in process adapter invokes the same assertion through `preSpawnCheck`
|
|
203
|
+
after cgroup/executable setup and immediately before `spawn`; a failed preflight
|
|
204
|
+
is fail-closed and does not start Claude. Long acceptance commands and Reviewer
|
|
185
205
|
sessions share an abort signal with the Supervisor, so operator stop/shutdown
|
|
186
206
|
wins without waiting for a full check timeout. Progress hooks expose starting,
|
|
187
|
-
Worker heartbeat, acceptance, review, repair and
|
|
207
|
+
Worker heartbeat, acceptance, review, repair and candidate/decision phases in the Pi UI.
|
|
188
208
|
|
|
189
209
|
Startup owns an `AbortController` and passes its signal to the adapter. A stop
|
|
190
210
|
or shutdown request aborts the controller and calls the adapter's out-of-band
|
|
@@ -221,20 +241,22 @@ unclean Pi restart, recovery is explicit: `/supervise recover [--takeover]
|
|
|
221
241
|
<task-id>` restores
|
|
222
242
|
the Decision Worker context and starts a new Claude Worker. It does not silently
|
|
223
243
|
resume or duplicate a task. It does not poll to detect turn completion. A watchdog timer remains only as a deadlock safety
|
|
224
|
-
fallback. Permission actions pass through
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
244
|
+
fallback. Permission and other actions pass through the configured autonomy policy and
|
|
245
|
+
are recorded. The local development loop must not require synchronous human
|
|
246
|
+
approval for ordinary actions; a task that cannot safely produce a candidate is
|
|
247
|
+
parked or failed without granting remote/main authority. If the Decision Worker
|
|
248
|
+
API/model call fails, the system records `decision_worker_failed`, applies the
|
|
249
|
+
bounded retry/park policy and preserves the candidate evidence. Optional alert
|
|
250
|
+
delivery remains independent from event-log persistence, but notification is not
|
|
251
|
+
the control boundary.
|
|
231
252
|
|
|
232
253
|
## Acceptance, review and repair loop
|
|
233
254
|
|
|
234
255
|
A task may provide a structured `TaskSpec` with `goal`, `scope`, `constraints`,
|
|
235
|
-
`forbidden
|
|
256
|
+
`forbidden`, an ordered list of required or optional acceptance checks, and
|
|
257
|
+
`autonomy` (`unattended`, `requireLocalCommit`, `maxDecisionRetries`). A
|
|
236
258
|
legacy plain-text task is normalized to a goal with the default `git diff
|
|
237
|
-
--check` acceptance check. The verifier runs every configured check with argv,
|
|
259
|
+
--check` acceptance check and unattended defaults. The verifier runs every configured check with argv,
|
|
238
260
|
bounded output and the same deterministic command policy; a Worker completion
|
|
239
261
|
claim never substitutes for these results.
|
|
240
262
|
|
|
@@ -243,35 +265,40 @@ fresh read-only Reviewer session. The Reviewer receives the task specification,
|
|
|
243
265
|
check results and bounded Worker completion evidence, but not the Decision Worker
|
|
244
266
|
conversation or control channel. It can inspect only `read`, `grep`, `find` and `ls`, and must return
|
|
245
267
|
`pass`, `revise` or `human` with bounded structured findings. Invalid Reviewer
|
|
246
|
-
output or a Reviewer API failure
|
|
268
|
+
output, incomplete evidence or a Reviewer API failure must prevent a candidate
|
|
269
|
+
from crossing the remote/main boundary; the local system may retry, repair or
|
|
270
|
+
park it without requiring a human to be online.
|
|
247
271
|
|
|
248
272
|
A `revise` result produces an audited repair round and sends a bounded corrective
|
|
249
273
|
instruction to a still-live `repairableSession` Worker. Checks and review then run again.
|
|
250
274
|
The repair budget defaults to three rounds; repeated findings and P0/P1 findings
|
|
251
|
-
stop automation and
|
|
275
|
+
stop automation and park a non-publishable candidate. A Worker that has already exited cannot be silently recreated
|
|
252
276
|
for repair; it remains failed/recoverable rather than replaying the original task. If a repair
|
|
253
|
-
or
|
|
277
|
+
or candidate branch cannot continue, a single idempotent terminalizer records
|
|
254
278
|
`verification_failed`, closes the Decision Worker and reports cleanup evidence; it never performs
|
|
255
279
|
a second `failed -> failed` transition.
|
|
256
280
|
|
|
257
|
-
Repository evidence is
|
|
258
|
-
|
|
259
|
-
|
|
281
|
+
Repository evidence is baseline-relative: the Supervisor records the initial HEAD,
|
|
282
|
+
then collects tracked committed/staged/unstaged changes, commit summaries after that
|
|
283
|
+
baseline and untracked regular files through bounded, component-safe, no-symlink reads.
|
|
284
|
+
Incomplete or truncated evidence is not sufficient for an independent `pass` verdict;
|
|
285
|
+
automatic mode parks a task when the required git baseline or local commit is unavailable. Acceptance
|
|
260
286
|
process output uses a bounded execution buffer before the smaller persisted evidence
|
|
261
287
|
limit, so a normal large test report is not misclassified as a failed command.
|
|
262
288
|
|
|
263
289
|
## Deliberate non-goals
|
|
264
290
|
|
|
265
|
-
-
|
|
266
|
-
- unauthenticated inbound webhook commands; outbound notifications
|
|
267
|
-
permission and do not replace
|
|
268
|
-
- treating an unknown Claude interactive question as safe
|
|
269
|
-
- bypassing Claude Code permissions;
|
|
291
|
+
- giving the Worker remote push or main/integration merge authority;
|
|
292
|
+
- unauthenticated inbound webhook commands; outbound notifications are optional,
|
|
293
|
+
do not grant permission and do not replace the remote/main independent boundary;
|
|
294
|
+
- treating an unknown Claude interactive question as safe without task evidence or configured authorization;
|
|
295
|
+
- bypassing the configured Claude Code/task permissions;
|
|
270
296
|
- accepting model text as verification;
|
|
271
297
|
- shell command interpolation;
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
298
|
+
- a host-level network sandbox for manual integrations. Automatic mode does not admit
|
|
299
|
+
arbitrary custom executables: its supported Worker is direct Claude, which requests a
|
|
300
|
+
fail-closed Claude Code Bash sandbox with no outbound domains; command policy and
|
|
301
|
+
credential filtering remain defense in depth;
|
|
275
302
|
- Claude CLI multi-version compatibility in the current stability milestone;
|
|
276
|
-
- OS sandbox
|
|
303
|
+
- full OS sandbox and low-privilege execution for custom Worker integrations in the current
|
|
277
304
|
lifecycle milestone.
|