pi-claude-supervisor 0.5.4 → 0.6.0

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 CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented here.
4
4
 
5
+ ## [0.6.0](https://github.com/btnalit/pi-claude-supervisor/compare/v0.5.5...v0.6.0) (2026-09-16)
6
+
7
+
8
+ ### Features
9
+
10
+ * preserve full automatic Claude capabilities ([#34](https://github.com/btnalit/pi-claude-supervisor/issues/34)) ([f3ef24b](https://github.com/btnalit/pi-claude-supervisor/commit/f3ef24bf4e2bbbce27516a0e36c6000a00222b71))
11
+
12
+ ## [0.5.5](https://github.com/btnalit/pi-claude-supervisor/compare/v0.5.4...v0.5.5) (2026-09-15)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * ignore expected tmux teardown races ([ac7ad57](https://github.com/btnalit/pi-claude-supervisor/commit/ac7ad57efa835764ea02fa138f8837947a5d9c39))
18
+
5
19
  ## [0.5.4](https://github.com/btnalit/pi-claude-supervisor/compare/v0.5.3...v0.5.4) (2026-09-15)
6
20
 
7
21
 
@@ -52,6 +66,10 @@ All notable changes to this project will be documented here.
52
66
  - 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.
53
67
  - Add a Supervisor-owned automatic tmux bridge that renders Claude stream-json in a live PTY and carries structured records through private framing instead of an independent event sidecar; adopted sessions remain manual-only.
54
68
  - Add parent-identity tmux guardians, guarded Linux bootstrap readiness/cleanup, explicit nested-Agent/background-reviewer denial, and tolerant Reviewer prose/fence/repeated-JSON parsing with separate display-truncation markers.
69
+ - Preserve the complete Supervisor environment when automatic callers provide partial overrides, while still removing only `CLAUDECODE`.
70
+ - Keep direct Claude Bash permission events observable by adding a safe default mode and rejecting Bash preauthorization in CLI/settings configuration.
71
+ - Permit verified automatic tmux recovery after the guardian removes the session, with dead-owner/process/cgroup/session proofs before reclaiming the cwd lease; bind recovery to persisted Worker/cgroup identities, persist phased cleanup-pending state before reservation, replace the same lease record atomically, and repeat the effective-settings permission check immediately before the tmux bridge spawns Claude.
72
+ - Retain verified empty automatic cgroups until cwd lease release, persist a no-spawn startup marker and provisional identity before Worker spawn, bind lock release/reclamation to directory identity and owner tokens, and pin the automatic tmux bridge cwd.
55
73
 
56
74
  ### Release readiness
57
75
 
package/README.cn.md CHANGED
@@ -15,7 +15,8 @@
15
15
  > preflight 和阶段进度通知;真实 Claude Code `2.1.270` 允许编辑的
16
16
  > repair/reacceptance 演练已在隔离临时 worktree 通过。确认的产品目标是本地开发
17
17
  > 完全无人值守;详见 [自动化目标](docs/autonomy-target.md)。代码进入远程仓库或
18
- > main/integration 分支必须经过独立边界,Worker 不拥有 push/merge 权限。
18
+ > main/integration 分支仍必须经过独立边界;Supervisor 管理的直接 push/merge 请求会拒绝,
19
+ > 而嵌套/自定义能力的硬边界必须由独立保护机制提供。
19
20
  >
20
21
  > **无人值守状态:** 自动模式会自主完成本地修改、测试、有限修复、验收、独立 Review
21
22
  > 和本地提交检查;无法形成候选时自动挂起为不可发布候选。可选出站通知不授予权限,
@@ -25,13 +26,14 @@
25
26
 
26
27
  - 不会在扩展加载时自动启动 Worker。
27
28
  - 不经过 shell 启动子进程。
28
- - Worker 只继承最小环境;自动模式采用默认拒绝的环境变量 allowlist,过滤远程凭据并禁用 Git/包管理器 credential helper。自动模式只能选择文档列出的 Claude provider 变量;任意自定义变量仅限手动集成。
29
- - 本地命令和权限行为按任务/运行时授权策略处理;超出授权的动作自动拒绝或挂起,不要求同步人工响应。
29
+ - 手动 Worker 保留小型继承环境,调用方也可以显式传入任意变量。自动 Claude Worker 继承 Supervisor 的完整环境,只移除 `CLAUDECODE`(Claude Code 用它拒绝嵌套会话);远程凭据、Git/包管理器 helper、自定义配置和网络设置都不会被过滤。
30
+ - 自动模式保留完整 Claude Code 工具面,包括 Agent、Task、后台任务、插件和 MCP;会从生效的 `HOME`/`CLAUDE_CONFIG_DIR` 检查 CLI/配置,并拒绝预授权 `Bash` 的规则;在未指定时加入 Claude 的安全 `default` permission mode,使 Bash 请求仍能被 Supervisor 看到(不会移除 Bash 工具本身)。自动 tmux bridge 会在实际 spawn Claude 子进程前再次同步检查设置,启动间隙发生修改时 fail closed。适配器再添加 stream-json transport framing,并把所有 Worker 后代放入 Supervisor 自有的清理边界。由于没有同步在线用户,`AskUserQuestion` 会转换为普通文本。
31
+ - 本地命令和权限行为按任务/运行时策略处理;已知的直接 remote push/main-integration 操作和 Git 元数据写入仍会拒绝或挂起,不要求同步人工响应。嵌套/自定义工具继承这些能力并随 Worker 清理,不另起第二套 Supervisor 权限循环。
30
32
  - Linux 上优先使用可写的 cgroup v2 清理后代进程,包括 `setsid()` 后代;不可用时回退到进程组清理。需要强制失败闭环时,embedding 集成可使用 `cgroupMode: "required"`,并会在 Claude 启动前执行 preflight。
31
- - 自动模式只接受裸的 `claude`/`claude.exe` 命令名,并从 Supervisor 的 PATH 解析、固定由操作者拥有的可执行文件(或使用 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` 固定路径);显式路径和可写/不可信位置会被拒绝。它请求 fail-closed 的 Claude Code Bash sandbox,禁止 Bash 子进程出站联网;命令策略仍是第二道门。手动/自定义集成必须自行提供等效 host/network 边界。
33
+ - 自动模式只接受裸的 `claude`/`claude.exe` 命令名,并从 Supervisor 的 PATH 解析、固定由操作者拥有的可执行文件(或使用 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` 固定路径);显式路径和可写/不可信位置会被拒绝。自定义工具和嵌套 Worker 是受信任能力,硬性的 remote/main 边界仍必须由此进程之外的独立受保护边界提供。
32
34
  - Worker 声称完成只会进入 `verifying`,不能作为成功证据。
33
35
  - 默认独立验收命令为 `git diff --check`。
34
- - 目标是任务启动后本地开发无人值守:Worker 可以修改、测试、修复和本地提交;Worker 必须没有远程 push 或合并到 `main`/integration 分支的权限。
36
+ - 目标是任务启动后本地开发无人值守:Worker 可以修改、测试、修复和本地提交;Supervisor 管理的 remote push 或合并到 `main`/integration 分支请求仍会拒绝,嵌套/自定义能力的最终 remote/main 边界必须由独立保护机制提供。
35
37
  - 扩展运行时不执行 merge、deploy、release 或 publish;远程/main 集成和仓库 Release 必须经过独立受保护边界。
36
38
  - 默认 4 小时总时限、20 分钟无输出 watchdog 超时即停止 Worker;paused 期间不消耗无输出预算,resume 会重建基准但不会重置总时限。嵌入调用方可将对应选项设为 `0` 关闭。
37
39
  - 验收命令、仓库证据收集和独立 Reviewer 共用 abort signal,人工 stop/shutdown 不必等待完整超时。
@@ -48,7 +50,7 @@ pi install npm:pi-claude-supervisor
48
50
 
49
51
  ```bash
50
52
  export PI_CLAUDE_SUPERVISOR_MODE=auto
51
- export PI_CLAUDE_SUPERVISOR_WORKER='claude --safe-mode --tools Bash'
53
+ export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode acceptEdits'
52
54
  # 可选:候选/失败通知;generic 或 wecom
53
55
  export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_URL='https://example.invalid/webhook'
54
56
  export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_FORMAT=generic
@@ -58,7 +60,7 @@ export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_FORMAT=generic
58
60
  自动模式支持 `claude-jsonl` 和 Supervisor 自有的 tmux bridge;JSONL 的 `result`、
59
61
  `control_request` 和进程 `exit` 事件会唤醒 Decision Worker。tmux bridge 把结构化记录
60
62
  通过同一个 live PTY 的私有 terminal framing 传回适配器,不创建独立 JSONL sidecar;
61
- `adopt-tmux` 仍是手动模式。本版本固定按已验证设备的 Claude CLI `2.1.270` 运行,跨版本兼容性不在本轮范围内。
63
+ `adopt-tmux` 仍是手动模式。真实 Claude 检查默认从 `PATH` 解析当前 CLI(包括安装器提供的 `latest` 路径),支持 Claude Code `2.1.270` 及以上版本;本轮的已记录演练版本为 `2.1.270`。
62
64
 
63
65
  然后在 Pi 中使用:
64
66
 
@@ -115,9 +117,9 @@ export PI_CLAUDE_SUPERVISOR_HUMAN_WEBHOOK_FORMAT=generic
115
117
  自动模式会将 Decision Worker 会话持久化到状态目录。Pi 非正常重启后,`/supervise sessions`
116
118
  会显示 `recoverable` 任务;显式执行 `/supervise recover [--takeover] <task-id>` 会恢复 Decision Worker 上下文并
117
119
  重新启动 Claude Worker,不会静默恢复或重复执行任务。旧 Pi 进程已退出且租约确认旧 Worker
118
- 进程组已消失且 cgroup 仍是真实、可读取的空边界时,才可显式添加 `--takeover`;缺失、仍存活或无法确认的 Worker 会被拒绝。手动 owned tmux
120
+ 进程组已消失且 cgroup 仍是真实、可读取的空边界时,才可显式添加 `--takeover`;缺失、仍存活或无法确认的 Worker 会被拒绝。自动 Worker 会保留已验证为空的 cgroup,直到所属 cwd 租约释放,以覆盖正常退出后 Pi 在租约收尾前崩溃的窗口;释放租约时再删除它。租约获取时会先持久化“尚未 spawn”的启动标记;适配器会在创建 cgroup/socket 前持久化生成的资源计划,再分阶段记录 cgroup identity 和 tmux server identity,启动期崩溃恢复会检查并清理已创建但尚未完成登记的空资源,而不是假定没有资源。只有确认旧 owner 已退出后才能接管残留标记。租约拒绝被替换或改名的 cgroup。自动 tmux 还要求确认 Supervisor 所有、tmux server identity 已死亡、私有 tmux session 已消失,并先持久化 cleanup-pending 事务,再原子保留私有 socket;替换会复用旧租约记录,写入新租约后才释放保留并删除 guardian 留下的空 cgroup;若恢复中断,新的 Supervisor 会先协调该待清理事务。手动 owned tmux
119
121
  Worker 可在重启后使用 `adopt-tmux`,而不是 takeover;自动 bridge 会由 parent-death guardian
120
- 在 Supervisor 消失时终止,不提供自动 session 的重接管。
122
+ 在 Supervisor 消失时终止,只有通过上述证据检查的 `recover --takeover` 才能重新取得 cwd lease。
121
123
  自动模式下,Decision Worker 在任务授权范围内自动处理普通问题、测试失败和修复轮次,记录假设和证据;无法形成可交付候选时自动挂起并保留证据,而不是要求人工必须在线。可通过 `PI_CLAUDE_SUPERVISOR_REQUIRE_LOCAL_COMMIT=0` 或 task `autonomy.requireLocalCommit` 关闭本地 commit 要求,但自动模式仍要求有效 Git baseline 和非保护 worktree;远程 push 和 main/integration merge 仍由独立边界控制。
122
124
 
123
125
  `v0.5.0` 已完成并发布“多命令验收—独立只读 Reviewer—结构化修复轮次—再次验收”闭环。
@@ -127,8 +129,8 @@ Reviewer 只能使用 `read`、`grep`、`find`、`ls`,不会修改工作树或
127
129
  Worker 启动前捕获 git baseline,要求完整的 baseline-relative tracked/commit/untracked evidence,
128
130
  并在默认情况下要求 Worker 在非保护分支本地 commit;无效输出、证据不完整、重复 finding、P0/P1 或预算耗尽
129
131
  会自动挂起候选。自动模式拒绝 process-pipe,并在模型执行前检查目录、可执行文件、依赖
130
- 和 cgroup;Worker 环境会过滤远程仓库凭据并禁用 Git 全局凭据 helper。详见 [自动化目标](docs/autonomy-target.md)。协同多 Worker 属于后续独立开发阶段,
131
- 自动模式只接受裸的直接 Claude 命令名,会固定解析后的操作者拥有的可执行文件,并请求 fail-closed 的 Claude Code Bash sandbox;任意自定义可执行文件和显式可执行路径会在自动模式拒绝。需要固定路径时设置 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE`。手动/自定义 Worker 的完整 host-level sandbox 仍需由集成方提供。
132
+ 和 cgroup;Claude 的完整工具、Agent/Task、插件、MCP、网络和环境会保持可用。自动模式会在未指定时加入安全的 `default` permission mode,并拒绝 Bash 预授权;Bash 仍通过 Supervisor 可见的 permission request 使用。详见 [自动化目标](docs/autonomy-target.md)。协同多 Worker 属于后续独立开发阶段,
133
+ 自动模式只接受裸的直接 Claude 命令名,会固定解析后的操作者拥有的可执行文件;任意自定义可执行文件和显式可执行路径会在自动模式拒绝。需要固定路径时设置 `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE`。自定义工具和嵌套 Worker 的 remote/main 权限必须由独立 host/仓库边界保护。
132
134
 
133
135
  ### tmux/PTY 交互模式
134
136
 
@@ -150,7 +152,7 @@ export PI_CLAUDE_SUPERVISOR_WORKER='claude'
150
152
  输入提示,并复用 watchdog、审计和独立验收流程。自动模式会在 pane 内启动 bridge:它运行
151
153
  Claude stream-json、把可读输出渲染到附着的终端,并通过同一 PTY 的私有 framing 返回结构化
152
154
  记录;bridge 及其后代放入受 Supervisor 管理的 Linux cgroup,并由 parent-death guardian
153
- 保护;任一 containment 机制不可用时 fail closed。适配器直接从 PTY 原始 pipe 解析,因此没有
155
+ 保护;bridge 会在 spawn Claude 前再次读取生效设置,任一 containment 机制或权限检查不可用时 fail closed。适配器直接从 PTY 原始 pipe 解析,因此没有
154
156
  独立 JSONL sidecar。自动模式拒绝被接管的 session;Supervisor 自有 bridge 支持自动输入串行化、
155
157
  权限响应、turn 完成和 stop。
156
158
 
@@ -183,7 +185,7 @@ PTY 屏幕文字本身不是 Claude JSONL,不能把屏幕文字当作结构化
183
185
  当前支持的是**独立任务会话并行**,不是共享工作树的协同多 Worker。后续多 Worker
184
186
  开发任务会引入 parent/child 任务图、依赖、并发上限、结构化 handoff、汇总验收和
185
187
  跨进程恢复,但不会放宽“一个 worktree 一个写入者”的边界,也不会自动 merge 或 publish。
186
- 该阶段应安排在固定 Claude `2.1.270` 稳定性统计和单 Worker recovery 语义完成之后。
188
+ 该阶段应安排在 Claude `2.1.270` 以上版本的稳定性统计和单 Worker recovery 语义完成之后。
187
189
 
188
190
  Pull Request 必须通过聚合的 `CI / Quality gate`。Release Please 根据 Conventional Commits 创建版本 PR;维护者合并后,Release workflow 会针对精确 tag commit 重新验证,并通过受保护的 `npm` environment 使用 npm provenance 发布。
189
191
 
package/README.md CHANGED
@@ -16,8 +16,9 @@ worker remains an explicitly started child process.
16
16
  > sessions remain manual-only. Repairable-vs-persistent capabilities,
17
17
  > cancellable verification, evidence completeness gates, startup preflight and phase
18
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).
19
+ > drill passed in an isolated temporary worktree. Real-Claude validation resolves the
20
+ > current executable from `PATH` and accepts Claude Code `2.1.270` or newer. The
21
+ > confirmed product target is unattended local development; see [the autonomy target](docs/autonomy-target.md).
21
22
  > Remote push and merge into the main/integration branch remain outside Worker authority
22
23
  > and must cross an independent boundary.
23
24
  >
@@ -30,12 +31,13 @@ worker remains an explicitly started child process.
30
31
 
31
32
  - The extension never starts a worker automatically.
32
33
  - Worker commands are launched without a shell.
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.
34
+ - Manual workers retain the small inherited environment unless the caller supplies explicit variables. Automatic Claude workers inherit the supervisor environment unchanged except for `CLAUDECODE`, which must be removed so Claude can intentionally launch nested Claude sessions; credentials, Git/package helpers, custom settings and network configuration are not filtered.
35
+ - The full Claude Code tool surface is available in automatic mode, including agents, background tasks, plugins and MCP. Automatic mode refuses CLI/settings rules that pre-authorize `Bash`, and adds Claude's safe `default` permission mode when none is supplied, so Bash requests remain visible to the Supervisor; it does not remove the Bash tool. The adapter also adds stream-json transport framing and keeps every Worker descendant inside the Supervisor-owned cleanup boundary. `AskUserQuestion` is converted to ordinary text because no human is synchronously present.
36
+ - Local command and permission behavior follows the configured task/runtime policy; known direct remote push/main-integration operations and protected Git metadata remain rejected or parked without requiring a synchronous human response. Nested/custom tools run with the inherited capabilities and are cleaned with the Worker; they are not a second Supervisor permission loop.
37
+ - Automatic mode still 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. Manual/custom integrations must provide their own executable and host authority boundary.
36
38
  - A worker completion is only a transition to `verifying`; it is not evidence of success.
37
39
  - Verification is an independent host command (default: `git diff --check`).
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.
40
+ - Target local development runs unattended after a task starts: the Worker may edit, test, repair and commit locally. Supervisor-managed requests for remote push or merge into `main`/an integration branch remain denied, while the final remote/main boundary must independently protect trusted nested/custom capabilities.
39
41
  - The extension never performs merge, deploy, release, or publish at runtime. Remote/main integration and repository releases cross independent protected boundaries.
40
42
  - 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.
41
43
  - 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.
@@ -58,6 +60,11 @@ npm run check
58
60
  npm run build
59
61
  ```
60
62
 
63
+ Authenticated real-Claude spikes resolve `claude` from `PATH` by default, so
64
+ installer-managed `latest` links work without a versioned path. Set
65
+ `PI_CLAUDE_SUPERVISOR_REAL_CLAUDE_PATH` only when an explicit executable is needed;
66
+ the spikes require Claude Code `2.1.270` or newer and report the resolved path and version.
67
+
61
68
  ## Use
62
69
 
63
70
  Set the worker executable if needed, then use explicit commands in Pi:
@@ -108,7 +115,7 @@ be selected explicitly:
108
115
 
109
116
  ```bash
110
117
  export PI_CLAUDE_SUPERVISOR_TRANSPORT=jsonl
111
- export PI_CLAUDE_SUPERVISOR_WORKER='claude --safe-mode --tools ""'
118
+ export PI_CLAUDE_SUPERVISOR_WORKER='claude --permission-mode acceptEdits'
112
119
  ```
113
120
 
114
121
  This adds Claude Code stream-json flags and frames supervisor messages as JSONL.
@@ -124,12 +131,22 @@ scheduling, structured handoffs, aggregate acceptance and graph-aware recovery;
124
131
  it will not grant any Worker remote push or main/integration merge authority.
125
132
  Unattended local development is the target operating mode; a blocked or failed
126
133
  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.
134
+ online. Automatic mode preserves Claude Code's normal argument and extension surface:
135
+ its tools, agents, background tasks, plugins, MCP configuration, credentials and network
136
+ access are not replaced with a sandbox or allowlist. `CLAUDECODE` is removed from the
137
+ Worker environment so nested Claude sessions can start, and the Supervisor-owned cgroup
138
+ still cleans every descendant. Automatic mode adds a safe `default` permission mode
139
+ when omitted and rejects Bash preauthorization in the effective CLI/settings roots
140
+ (including an overridden `HOME`); Bash itself remains available through
141
+ Supervisor-visible permission requests. The automatic tmux bridge repeats that
142
+ settings check synchronously immediately before spawning Claude, so a mutation after
143
+ Supervisor preflight fails closed. The adapter also adds stream-json transport framing,
144
+ and its known direct command policy refuses remote push/main integration operations.
145
+ Automatic mode still accepts only the bare direct Claude command name, pins its
146
+ operator-owned resolved executable path, and rejects explicit executable paths or
147
+ writable/untrusted locations. Set `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` when the resolved
148
+ path must be pinned explicitly. Custom tools and nested workers are trusted capabilities,
149
+ so a hard remote/main boundary must remain independently protected outside this process.
133
150
  Set `PI_CLAUDE_SUPERVISOR_REQUIRE_LOCAL_COMMIT=0` only for a task that intentionally
134
151
  produces no local commit candidate, or set `autonomy.requireLocalCommit` in its spec;
135
152
  automatic mode still requires a valid Git baseline and non-protected worktree.
@@ -163,15 +180,30 @@ tasks; `/supervise recover [--takeover] <task-id>` explicitly restores the Decis
163
180
  context and starts a new Claude Worker. It never silently resumes or duplicates
164
181
  work. If the old Pi owner is dead, add `--takeover` only after the lease proves
165
182
  the old Worker's process group is gone and its cgroup is a real, readable empty
166
- boundary; missing or unverifiable Worker evidence is refused.
167
- For a persistent tmux Worker, use explicit `adopt-tmux` instead of takeover.
168
- The adapter intentionally does not inherit arbitrary host environment variables.
183
+ boundary; missing or unverifiable Worker evidence is refused. The lease also
184
+ persists the generated Worker/cgroup identity, including the cgroup device/inode,
185
+ and rejects a renamed or replaced cgroup. Automatic Workers retain a verified
186
+ empty cgroup until the owning cwd lease is released, covering a normal-exit
187
+ crash between Worker cleanup and lease finalization; release then removes it.
188
+ Automatic lease acquisition records a no-spawn startup marker and the adapter
189
+ persists its generated cgroup/socket plan before creating those resources,
190
+ then records cgroup and server identity in stages before spawn. Recovery
191
+ inspects and cleans a planned empty cgroup/session instead of assuming that
192
+ startup-only means no resource exists. A stale marker is reclaimable only after
193
+ its owner is proven dead because that adapter has not reached spawn. For an automatic tmux lease, takeover additionally requires Supervisor ownership,
194
+ dead tmux-server identity, a gone private tmux session, and a durable
195
+ cleanup-pending transaction plus atomic reservation of the private socket. The
196
+ replacement reuses the old lease record, and the reservation remains until that
197
+ replacement is written. Only then is the guardian-left-empty cgroup removed; a
198
+ fresh Supervisor can reconcile the pending transaction if recovery is
199
+ interrupted. For a persistent manual tmux Worker, use explicit `adopt-tmux`
200
+ instead of takeover.
169
201
  Manual embedding integrations may pass credentials through an explicit
170
- `WorkerStartInput.env`; automatic mode accepts only documented Claude provider
171
- variables, for example `PI_CLAUDE_SUPERVISOR_WORKER_ENV=ANTHROPIC_API_KEY`, and
172
- filters remote credentials and configuration-injection variables. The host-side
173
- `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` setting pins the executable identity and is not
174
- passed into the Worker environment.
202
+ `WorkerStartInput.env`. Automatic mode passes the full supervisor environment to the
203
+ Worker (except `CLAUDECODE`), including provider/remote credentials, credential helpers,
204
+ configuration and proxy settings. Keep the Supervisor's own environment appropriate for
205
+ the task; `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` pins executable identity but is otherwise
206
+ not used to select the Claude binary.
175
207
 
176
208
  ### tmux/PTY transport
177
209
 
@@ -197,8 +229,11 @@ In automatic mode the Supervisor starts a bridge in the pane: it runs Claude's
197
229
  stream-json protocol inside the live PTY, contains the bridge and descendants in
198
230
  an owned cgroup, fails closed when that containment or the Linux guardian is
199
231
  unavailable, renders readable deltas for the attached terminal, and returns
200
- structured records through private terminal framing on the same PTY.
201
- The adapter parses those records from the raw PTY pipe, so there is no independent
232
+ structured records through private terminal framing on the same PTY. The bridge
233
+ re-reads effective Claude settings in the same process immediately before its
234
+ child `spawn`, so a startup settings mutation fails closed instead of reaching
235
+ an unchecked Claude process. The adapter parses those records from the raw PTY
236
+ pipe, so there is no independent
202
237
  JSONL event sidecar. Automatic mode refuses adopted sessions; use JSONL or the owned
203
238
  bridge for unattended decisions, repair and protected command enforcement.
204
239
 
@@ -229,7 +264,9 @@ online. A normal terminal Claude process cannot be migrated into tmux, and
229
264
  `--resume` is historical recovery rather than live PTY attach. Manual owned tmux
230
265
  sessions survive a Pi disconnect and require an explicit `adopt-tmux` after
231
266
  restart; automatic owned sessions are terminated by their parent-death guardian
232
- when the Supervisor disappears. Use plan/read-only flags for live testing.
267
+ when the Supervisor disappears. A later `/supervise recover --takeover` may
268
+ reclaim an automatic lease only after the guardian, process, cgroup and private
269
+ tmux-session proofs pass. Use plan/read-only flags for live testing.
233
270
 
234
271
  ## Development
235
272
 
@@ -27,8 +27,9 @@ The extension keeps a registry of independent task sessions. Each session has
27
27
  its own Supervisor, watchdog, state machine and Worker handle, while the event
28
28
  log is shared and protected by an inter-process lock. Once a task starts, the
29
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
30
+ repair and commit locally. Supervisor-managed remote push and merge into `main`/an integration branch
31
+ requests remain outside the local loop and cross an independent boundary; custom/nested tools require
32
+ that boundary to enforce the same rule independently. Concurrent active sessions must use non-overlapping canonical working
32
33
  directories/worktrees; same-cwd and parent/child cwd starts are rejected before
33
34
  spawn, including concurrent starts, to prevent uncoordinated edits. Pending starts
34
35
  are also awaited during Pi shutdown.
@@ -83,13 +84,32 @@ fixed-version spike, renders the stream in the pane and carries structured recor
83
84
  through private framing on the same PTY; explicit adoption remains manual-only.
84
85
 
85
86
  A worker exit automatically triggers cleanup, and terminal status waits for
86
- that cleanup to be confirmed (or reports a cleanup error). On Linux, manual
87
- workers may use cgroup v2 automatically when the current user cgroup is writable;
87
+ that cleanup to be confirmed (or reports a cleanup error). Automatic Claude
88
+ startup rejects Bash preauthorization in the effective CLI/settings roots,
89
+ including an overridden `HOME`, and adds a safe `default` permission mode when
90
+ no mode was supplied, preserving the Supervisor's permission-event boundary
91
+ without removing the Bash tool. The automatic tmux bridge repeats the settings
92
+ inspection synchronously immediately before its Claude child `spawn`, so a
93
+ mutation after Supervisor preflight fails closed. On Linux,
94
+ manual workers may use cgroup v2 automatically when the current user cgroup is writable;
88
95
  the `required` mode performs a preflight and fails before Claude starts if cgroup
89
96
  attachment or cleanup is unavailable. Automatic JSONL workers always require the
90
97
  same preflight and a guarded cgroup bootstrap; automatic startup fails closed on
91
98
  non-Linux hosts or when the boundary cannot be established. Cgroup cleanup kills
92
- descendants even when they call `setsid()` or create another process group.
99
+ descendants even when they call `setsid()` or create another process group. If
100
+ an automatic parent-death bootstrap performs cleanup after the Supervisor is
101
+ killed, it leaves the now-empty cgroup as takeover evidence; the lease persists
102
+ the generated Worker/cgroup identity and cgroup device/inode, and explicit
103
+ recovery removes the cgroup only after those identities, the dead tmux server,
104
+ and the empty boundary pass. Automatic workers retain their verified empty
105
+ cgroup until the owning cwd lease is finalized, so a normal-exit crash remains
106
+ recoverable; explicit lease release then removes it. Takeover first persists a
107
+ cleanup-pending transaction in the existing lease, then atomically reserves the
108
+ gone private socket; it replaces that same lease record before removing the
109
+ guardian cgroup and clears the transaction only after all cleanup proofs
110
+ complete. A fresh lease reader can reconcile the pending transaction after a
111
+ crash, retaining a replacement lease during the replacement phase, while
112
+ ordinary manual worker cleanup still removes its cgroup.
93
113
 
94
114
  When cgroup v2 is unavailable, manual mode falls back to detached process-group
95
115
  cleanup. That fallback is not recursive: `setsid()` descendants can escape, and
@@ -113,18 +133,19 @@ parent-death guardian is unavailable.
113
133
  An owned manual worker gets a private tmux server/socket and executes the
114
134
  validated Claude command directly in the pane. An owned automatic worker instead
115
135
  starts the Supervisor bridge through a cgroup-joining pane bootstrap, so its
116
- bridge identity is not a manual adoption target. The worker
117
- environment is supplied to the tmux server through the same least-privilege
118
- environment builder; credentials are not copied into a file; credential-shaped
119
- command arguments are rejected.
136
+ bridge identity is not a manual adoption target. The worker environment is
137
+ passed through unchanged (apart from removing `CLAUDECODE` so nested Claude can
138
+ start); credentials are not copied into a file, and credential-shaped command
139
+ arguments are still rejected.
120
140
  `load-buffer`, bracketed `paste-buffer` and `send-keys Enter` provide the input
121
141
  boundary without interpolating a task into a shell command. C0/C1 terminal
122
- control bytes are rejected; CRLF is normalized to a newline. In automatic mode,
123
- the adapter snapshots the trusted direct Claude process and checks both the
124
- required Linux cgroup and process tree on every poll; a newly executed Claude or
125
- Reviewer descendant is a runtime policy failure and the owned session is stopped.
126
- This supplements the lexical Bash/file-tool boundary and is disabled for
127
- manual/adopted sessions.
142
+ control bytes are rejected; CRLF is normalized to a newline. Automatic agents,
143
+ background tasks, plugins, MCP servers and nested Claude processes stay in the
144
+ same cgroup and are cleaned with the Worker; they are intentionally not rejected
145
+ or polled as a nested-process policy failure. The lexical Bash/file-tool policy
146
+ still handles known direct remote/main operations, while custom descendants are
147
+ trusted and require an independent host/repository boundary for stronger
148
+ protection.
128
149
 
129
150
  The transport has three deliberately separate observations:
130
151
 
@@ -153,9 +174,13 @@ that immutable pane target; a replacement process is refused. Adopted sessions
153
174
  are not owned: stop and Pi shutdown detach rather than kill them. Tmux commands
154
175
  and serialized input waits have bounded deadlines so shutdown cannot hang
155
176
  forever. Manual sessions started by the adapter survive a Pi disconnect, but recovery
156
- after restart is explicit re-adoption; automatic sessions are intentionally
157
- terminated by their parent-death guardian when the Supervisor disappears. The
158
- extension never claims to attach to an arbitrary non-tmux PTY. Startup cleanup always attempts the
177
+ after restart is explicit re-adoption; automatic sessions are terminated by
178
+ their parent-death guardian when the Supervisor disappears. The guardian leaves
179
+ the verified empty automatic cgroup so `recover --takeover` can confirm the
180
+ private tmux session and Worker identities. Recovery reserves the gone private
181
+ socket, writes the replacement lease, and only then releases the reservation
182
+ and removes that cgroup. The extension never claims to attach to an arbitrary
183
+ non-tmux PTY. Startup cleanup always attempts the
159
184
  private tmux server teardown, including after partial session creation, and a
160
185
  confirmed `kill-server` is sufficient cleanup evidence. A normal Claude
161
186
  `--resume` starts another process from history and is not a live PTY migration.
@@ -191,10 +216,12 @@ only after the adapter confirms the worker and its descendant cleanup. An
191
216
  unconfirmed lease left by a crashed Pi is intentionally retained. Ordinary
192
217
  recovery refuses it; an operator may use `recover --takeover` only when the old
193
218
  owner is dead, the Worker process group is gone, and the lease independently
194
- reads a real empty cgroup boundary for the old Worker. Missing or unverifiable
195
- Worker evidence retains the lease and parks the task rather than performing unsafe
196
- reclamation; later recovery can inspect or clean it without requiring an operator to
197
- be online.
219
+ reads a real empty cgroup boundary for the old Worker. Automatic tmux takeover
220
+ additionally requires Supervisor ownership and a gone private tmux session, then
221
+ removes the guardian-left-empty cgroup only after all proofs pass. Missing or
222
+ unverifiable Worker evidence retains the lease and parks the task rather than
223
+ performing unsafe reclamation; later recovery can inspect or clean it without
224
+ requiring an operator to be online.
198
225
  An explicitly adopted tmux session may hand off an existing lease only after
199
226
  its owner identity is no longer live and its canonical cwd, tmux session/socket,
200
227
  pane id, pane PID/start time, and pane command all match; ordinary starts
@@ -215,9 +242,18 @@ executable is checked for an operator-owned, non-writable path and then pinned b
215
242
  absolute path; `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` can pin the expected identity. The initial repository HEAD is captured, and the repository boundary immediately
216
243
  before the Worker adapter starts must report that exact same HEAD (recovery captures
217
244
  and compares its current HEAD separately while retaining the persisted baseline).
218
- The built-in process adapter invokes the same assertion through `preSpawnCheck`
219
- after cgroup/executable setup and immediately before `spawn`; a failed preflight
220
- is fail-closed and does not start Claude. Long acceptance commands and Reviewer
245
+ Automatic lease acquisition also persists a no-spawn startup marker. Automatic
246
+ adapters then persist the generated Worker/cgroup identity and clear that marker
247
+ before the actual Worker spawn, closing the startup-registration crash window;
248
+ a stale marker can only be replaced after the old owner is proven dead because
249
+ its adapter has not reached spawn. Adapters persist their generated cgroup/socket
250
+ plan before creating those resources, persist cgroup identity before guardian or
251
+ session setup, and persist tmux-server identity before the final spawn check. Startup
252
+ recovery validates and cleans any planned empty resource it finds instead of
253
+ assuming the marker means no resource exists. The built-in process adapter invokes
254
+ the same assertion through `preSpawnCheck` after cgroup/executable setup and
255
+ immediately before `spawn`; a failed preflight is fail-closed and does not start
256
+ Claude. Long acceptance commands and Reviewer
221
257
  sessions share an abort signal with the Supervisor, so operator stop/shutdown
222
258
  wins without waiting for a full check timeout. Progress hooks expose starting,
223
259
  Worker heartbeat, acceptance, review, repair and candidate/decision phases in the Pi UI.
@@ -308,13 +344,12 @@ limit, so a normal large test report is not misclassified as a failed command.
308
344
  - unauthenticated inbound webhook commands; outbound notifications are optional,
309
345
  do not grant permission and do not replace the remote/main independent boundary;
310
346
  - treating an unknown Claude interactive question as safe without task evidence or configured authorization;
311
- - bypassing the configured Claude Code/task permissions;
347
+ - bypassing the known direct remote/main command and Git metadata boundaries;
312
348
  - accepting model text as verification;
313
349
  - shell command interpolation;
314
- - a host-level network sandbox for manual integrations. Automatic mode does not admit
315
- arbitrary custom executables: its supported Worker is direct Claude, which requests a
316
- fail-closed Claude Code Bash sandbox with no outbound domains; command policy and
317
- credential filtering remain defense in depth;
350
+ - a host-level network sandbox for automatic or manual integrations. Automatic mode
351
+ deliberately preserves Claude Code's normal environment, network, tools, agents,
352
+ plugins and MCP configuration; nested/custom descendants are trusted capabilities;
318
353
  - Claude CLI multi-version compatibility in the current stability milestone;
319
- - full OS sandbox and low-privilege execution for custom Worker integrations in the current
320
- lifecycle milestone.
354
+ - full OS sandbox and low-privilege execution for custom or nested Worker integrations in the
355
+ current lifecycle milestone.
@@ -35,26 +35,32 @@ JSONL Worker or Supervisor-owned tmux bridge, and by default requires a local co
35
35
  Automatic Worker supervision uses either the structured JSONL transport or a
36
36
  Supervisor-owned tmux bridge. The bridge runs Claude's stream-json protocol inside the live
37
37
  PTY, renders a human-readable display, and returns private framed records through the same
38
- PTY; adopted tmux sessions remain manual-only. The Worker and local automation do **not**
39
- receive authority or credentials for:
40
-
41
- - pushing code to a remote repository;
42
- - merging into `main` or another protected integration branch;
43
- - starting automatic candidate work directly on a protected integration branch; repositories with a
44
- branch use a non-protected local branch for unattended work;
45
- - inheriting Git/GitHub/package credential helpers or explicitly selected remote credentials in
46
- automatic mode.
38
+ PTY; adopted tmux sessions remain manual-only. Automatic local work still has no Supervisor API
39
+ for remote push or merging into `main` or another protected integration branch. It also refuses
40
+ known direct Bash forms of those operations, protected Git metadata writes and package publication.
41
+ Starting candidate work directly on a protected integration branch remains refused; automatic
42
+ repositories use a non-protected local branch.
43
+
44
+ Automatic Claude workers intentionally inherit credentials, helpers, network configuration and
45
+ custom Claude configuration. Agents, background tasks, plugins, MCP servers and nested Claude
46
+ processes are allowed and remain inside the Supervisor-owned process/cgroup cleanup boundary.
47
+ Those custom or nested capabilities are trusted local execution, not a second Supervisor
48
+ permission loop; an absolute remote/main security boundary for them must be provided by the
49
+ repository, host or protected integration service. To keep the direct Claude Bash boundary
50
+ observable, automatic startup adds the safe `default` permission mode when none is supplied and
51
+ rejects `--allowedTools`/settings rules that pre-authorize `Bash`; the Bash tool remains available
52
+ through a Supervisor-visible permission request. Settings are resolved from the effective
53
+ `HOME`/`CLAUDE_CONFIG_DIR`, and the automatic tmux bridge repeats this inspection immediately
54
+ before spawning Claude so a startup mutation fails closed.
47
55
 
48
56
  A completed local task is a candidate until it passes the independent boundary. That boundary may
49
57
  be a later read-only review, CI policy, a maintainer action, or an explicit shutdown/rejection.
50
- The Worker must not be able to bypass it through a prompt, a local decision, or a model response.
58
+ No local decision or model response may turn a blocked candidate into a published result.
51
59
 
52
- This is the required authority boundary. Automatic mode admits only the bare direct Claude
53
- command name and pins its operator-owned resolved executable because its fail-closed Claude Code
54
- sandbox is part of the supported boundary; explicit paths and arbitrary custom executables must
55
- use manual mode or an independently hardened integration. No additional
56
- synchronous human-approval boundary should be invented for local editing, local tests, local
57
- commits, or local repair unless the task owner explicitly configures one.
60
+ Automatic mode still admits only the bare direct Claude command name and pins its operator-owned
61
+ resolved executable. No additional synchronous human-approval boundary should be invented for
62
+ local editing, local tests, local commits or local repair unless the task owner explicitly
63
+ configures one.
58
64
 
59
65
  ## 3. Unattended decision behavior
60
66
 
@@ -103,17 +109,26 @@ continue/redirect/answer/repair, acceptance and independent Review run without a
103
109
  and unresolved situations become `blocked` candidates. The default task autonomy is unattended, requires a local commit, and permits two bounded
104
110
  Decision Worker request retries. Automatic startup rejects non-Git/detached/bare/protected
105
111
  repository states, malformed baselines, startup-HEAD races, the unstructured
106
- process-pipe transport and non-Claude or untrusted executable identities before Worker
107
- startup. The resolved
112
+ process-pipe transport, Bash-preauthorizing Claude arguments/settings and non-Claude or untrusted
113
+ executable identities before Worker startup. The resolved
108
114
  executable identity is persisted with the Decision Worker recovery record and must match
109
115
  again during recovery.
110
116
 
111
117
  Legacy `humanRequired`, takeover and approval fields remain for compatibility and explicit operator
112
118
  control. They are not entered by ordinary uncertainty, and a legacy approval object cannot override
113
- the deterministic remote push/main merge denial. The existing independent Review and protected
114
- CI/release paths remain the final external checks. Built-in automatic Claude workers request a fail-closed Claude Code Bash sandbox with no
115
- outbound domains; automatic command policy and credential filtering remain defense in depth.
116
- Full host-level sandboxing for custom Worker integrations is separate hardening work.
119
+ the deterministic known-command remote push/main merge denial. The existing independent Review
120
+ and protected CI/release paths remain the final external checks. Automatic Claude workers preserve
121
+ Claude Code's normal environment, network, tool, agent and MCP surface; `CLAUDECODE` is removed
122
+ only to permit intentional nested Claude sessions. The Supervisor-owned cgroup remains a cleanup
123
+ boundary, not a capability allowlist. Automatic tmux parent-death recovery leaves an empty
124
+ cgroup as evidence and permits `recover --takeover` only after Supervisor ownership, persisted
125
+ Worker/cgroup identity (including the cgroup device/inode), dead tmux-server identity, a gone
126
+ private session, and an empty cgroup are all confirmed. Automatic normal-exit cleanup retains an
127
+ empty cgroup until cwd lease release, and automatic lease acquisition records a no-spawn startup
128
+ marker that is cleared only after provisional Worker/cgroup identity is persisted before spawn.
129
+ Recovery atomically reserves the private socket until the replacement lease is written. Full host/repository
130
+ enforcement for untrusted custom or nested integrations remains the independent boundary's
131
+ responsibility.
117
132
 
118
133
  ## 7. Explicit non-goals of this target
119
134
 
@@ -125,6 +140,8 @@ This target does not authorize:
125
140
  - silently treating incomplete evidence as success;
126
141
  - claiming that a failed or parked task completed.
127
142
 
128
- Coordinated multi-Worker scheduling, OS sandboxing and broader CLI compatibility remain separate
129
- engineering milestones. They must not be used to add synchronous human approval to the local
130
- development loop.
143
+ Coordinated multi-Worker scheduling, OS sandboxing and validation of future breaking CLI/API
144
+ changes remain separate engineering milestones. The supported Claude Code compatibility floor is
145
+ `2.1.270`; versioned install paths are not fixed, but a newer CLI should still rerun the real
146
+ spikes before release. These milestones must not be used to add synchronous human approval to the
147
+ local development loop.