pi-claude-supervisor 0.5.2 → 0.5.4
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 +22 -2
- package/README.cn.md +58 -40
- package/README.md +84 -43
- package/docs/architecture.md +108 -65
- package/docs/automation-hardening-plan.md +24 -22
- package/docs/autonomy-target.md +130 -0
- package/docs/engineering-plan.md +136 -138
- package/docs/implementation-review.md +37 -14
- package/docs/independent-review.md +23 -18
- package/docs/releasing.md +7 -2
- package/docs/testing.md +53 -27
- package/package.json +1 -1
- package/src/acceptance.ts +16 -0
- package/src/config.ts +31 -0
- package/src/decision-session-store.ts +27 -2
- package/src/decision-worker.ts +46 -18
- package/src/index.ts +46 -54
- package/src/notifications.ts +29 -11
- package/src/policy.ts +294 -22
- package/src/reviewer.ts +90 -10
- package/src/state.ts +7 -6
- package/src/supervisor.ts +332 -120
- package/src/types.ts +26 -1
- package/src/verifier.ts +106 -7
- package/src/worker/environment.ts +217 -0
- package/src/worker/process-adapter.ts +379 -77
- package/src/worker/process-tree.ts +218 -0
- package/src/worker/tmux-adapter.ts +669 -25
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
|
|
@@ -68,24 +77,25 @@ one capability from the other.
|
|
|
68
77
|
|
|
69
78
|
This is a control-boundary fixture and headless transport. It does not emulate a
|
|
70
79
|
terminal. Manual compatibility mode remains `process-pipe`; automatic mode
|
|
71
|
-
(`PI_CLAUDE_SUPERVISOR_MODE=auto`) defaults to Claude JSONL and
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
(`PI_CLAUDE_SUPERVISOR_MODE=auto`) defaults to Claude JSONL and can select the
|
|
81
|
+
Supervisor-owned tmux bridge. The bridge uses the CLI contract validated by the
|
|
82
|
+
fixed-version spike, renders the stream in the pane and carries structured records
|
|
83
|
+
through private framing on the same PTY; explicit adoption remains manual-only.
|
|
74
84
|
|
|
75
85
|
A worker exit automatically triggers cleanup, and terminal status waits for
|
|
76
|
-
that cleanup to be confirmed (or reports a cleanup error). On Linux
|
|
77
|
-
|
|
78
|
-
`required` mode performs a preflight and fails before Claude starts if cgroup
|
|
79
|
-
attachment or cleanup is unavailable.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
When cgroup v2 is unavailable,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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;
|
|
88
|
+
the `required` mode performs a preflight and fails before Claude starts if cgroup
|
|
89
|
+
attachment or cleanup is unavailable. Automatic JSONL workers always require the
|
|
90
|
+
same preflight and a guarded cgroup bootstrap; automatic startup fails closed on
|
|
91
|
+
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.
|
|
93
|
+
|
|
94
|
+
When cgroup v2 is unavailable, manual mode falls back to detached process-group
|
|
95
|
+
cleanup. That fallback is not recursive: `setsid()` descendants can escape, and
|
|
96
|
+
PID reuse between leader exit and cleanup is a host-level limitation. Production
|
|
97
|
+
deployments that require an atomic boundary should use a service-manager scope,
|
|
98
|
+
Job Object, pidfd-aware reaper, or equivalent supervisor.
|
|
89
99
|
Pi owns graceful `SIGTERM`/`SIGINT` handling and invokes the extension's
|
|
90
100
|
`session_shutdown` hook. The extension does not install a second `process.exit()`
|
|
91
101
|
handler, avoiding races with Pi terminal restoration and other extensions. `SIGSTOP`
|
|
@@ -95,42 +105,59 @@ host-fatal signals.
|
|
|
95
105
|
## tmux/PTY transport
|
|
96
106
|
|
|
97
107
|
`TmuxWorkerAdapter` is an explicit second transport, selected with
|
|
98
|
-
`PI_CLAUDE_SUPERVISOR_TRANSPORT=tmux`.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
`PI_CLAUDE_SUPERVISOR_TRANSPORT=tmux`. Both owned and adopted tmux currently
|
|
109
|
+
require Linux because pane identity and cleanup use `/proc`; manual tmux may use
|
|
110
|
+
cgroup `auto`/`off`. Automatic owned tmux additionally creates a required Linux
|
|
111
|
+
cgroup for the bridge and its descendants; it is rejected when cgroup v2 or the
|
|
112
|
+
parent-death guardian is unavailable.
|
|
113
|
+
An owned manual worker gets a private tmux server/socket and executes the
|
|
114
|
+
validated Claude command directly in the pane. An owned automatic worker instead
|
|
115
|
+
starts the Supervisor bridge through a cgroup-joining pane bootstrap, so its
|
|
116
|
+
bridge identity is not a manual adoption target. The worker
|
|
103
117
|
environment is supplied to the tmux server through the same least-privilege
|
|
104
118
|
environment builder; credentials are not copied into a file; credential-shaped
|
|
105
119
|
command arguments are rejected.
|
|
106
120
|
`load-buffer`, bracketed `paste-buffer` and `send-keys Enter` provide the input
|
|
107
121
|
boundary without interpolating a task into a shell command. C0/C1 terminal
|
|
108
|
-
control bytes are rejected; CRLF is normalized to a newline.
|
|
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.
|
|
109
128
|
|
|
110
129
|
The transport has three deliberately separate observations:
|
|
111
130
|
|
|
112
131
|
- `pipe-pane` provides an append-only raw PTY log for output polling and audit;
|
|
113
132
|
- `capture-pane` provides a bounded screen snapshot used only for stable prompt
|
|
114
133
|
detection and human display;
|
|
115
|
-
-
|
|
116
|
-
|
|
134
|
+
- the Supervisor-owned bridge emits Claude stream-json records as private framed
|
|
135
|
+
PTY control data; `pipe-pane` carries those records to the adapter without an
|
|
136
|
+
independent JSONL sidecar;
|
|
137
|
+
- Claude's own transcript, when available, remains the structured history. Ordinary
|
|
138
|
+
screen text is never relabeled as JSONL or permission evidence.
|
|
117
139
|
|
|
118
140
|
For an owned initial turn, the adapter emits a synthetic `turn_completed` only
|
|
119
141
|
after output activity and two stable input-prompt observations. Adopting an idle
|
|
120
142
|
prompt remains inactive and emits no synthetic completion. This is a liveness
|
|
121
143
|
signal, not proof that the task succeeded; the independent verifier remains
|
|
122
|
-
mandatory. Interactive dialogs,
|
|
123
|
-
|
|
124
|
-
|
|
144
|
+
mandatory. Interactive dialogs, trust prompts and ambiguous screens are interpreted by
|
|
145
|
+
the configured autonomy policy and recorded as evidence. An unresolved task is
|
|
146
|
+
parked or failed as a non-publishable candidate rather than requiring a human to
|
|
147
|
+
remain online. Human takeover remains an explicit kill/control path and stops
|
|
148
|
+
automatic messages until `resume-auto`.
|
|
125
149
|
|
|
126
150
|
`/supervise adopt-tmux` is explicit and validates the pinned pane's cwd and
|
|
127
151
|
process identity before attaching. Every later input, capture and signal uses
|
|
128
152
|
that immutable pane target; a replacement process is refused. Adopted sessions
|
|
129
153
|
are not owned: stop and Pi shutdown detach rather than kill them. Tmux commands
|
|
130
154
|
and serialized input waits have bounded deadlines so shutdown cannot hang
|
|
131
|
-
forever.
|
|
132
|
-
|
|
133
|
-
|
|
155
|
+
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
|
|
159
|
+
private tmux server teardown, including after partial session creation, and a
|
|
160
|
+
confirmed `kill-server` is sufficient cleanup evidence. A normal Claude
|
|
134
161
|
`--resume` starts another process from history and is not a live PTY migration.
|
|
135
162
|
|
|
136
163
|
## State machine
|
|
@@ -165,7 +192,9 @@ unconfirmed lease left by a crashed Pi is intentionally retained. Ordinary
|
|
|
165
192
|
recovery refuses it; an operator may use `recover --takeover` only when the old
|
|
166
193
|
owner is dead, the Worker process group is gone, and the lease independently
|
|
167
194
|
reads a real empty cgroup boundary for the old Worker. Missing or unverifiable
|
|
168
|
-
Worker evidence
|
|
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.
|
|
169
198
|
An explicitly adopted tmux session may hand off an existing lease only after
|
|
170
199
|
its owner identity is no longer live and its canonical cwd, tmux session/socket,
|
|
171
200
|
pane id, pane PID/start time, and pane command all match; ordinary starts
|
|
@@ -178,13 +207,20 @@ is alive; the extension periodically rechecks released sessions and removes the
|
|
|
178
207
|
lease only after the pane is confirmed gone. If that check fails, the lease is
|
|
179
208
|
retained rather than allowing a cwd overlap.
|
|
180
209
|
|
|
181
|
-
Before model or Worker execution, automatic starts
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
210
|
+
Before model or Worker execution, automatic starts validate a full existing Git
|
|
211
|
+
baseline, a non-bare worktree, a readable non-protected branch, the direct bare
|
|
212
|
+
`claude`/`claude.exe` command name, JSONL transport, runtime state/lease directories
|
|
213
|
+
and, when requested, the real writable cgroup-v2 boundary. The resolved Claude
|
|
214
|
+
executable is checked for an operator-owned, non-writable path and then pinned by
|
|
215
|
+
absolute path; `PI_CLAUDE_SUPERVISOR_TRUSTED_CLAUDE` can pin the expected identity. The initial repository HEAD is captured, and the repository boundary immediately
|
|
216
|
+
before the Worker adapter starts must report that exact same HEAD (recovery captures
|
|
217
|
+
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
|
|
185
221
|
sessions share an abort signal with the Supervisor, so operator stop/shutdown
|
|
186
222
|
wins without waiting for a full check timeout. Progress hooks expose starting,
|
|
187
|
-
Worker heartbeat, acceptance, review, repair and
|
|
223
|
+
Worker heartbeat, acceptance, review, repair and candidate/decision phases in the Pi UI.
|
|
188
224
|
|
|
189
225
|
Startup owns an `AbortController` and passes its signal to the adapter. A stop
|
|
190
226
|
or shutdown request aborts the controller and calls the adapter's out-of-band
|
|
@@ -221,20 +257,22 @@ unclean Pi restart, recovery is explicit: `/supervise recover [--takeover]
|
|
|
221
257
|
<task-id>` restores
|
|
222
258
|
the Decision Worker context and starts a new Claude Worker. It does not silently
|
|
223
259
|
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
|
-
|
|
260
|
+
fallback. Permission and other actions pass through the configured autonomy policy and
|
|
261
|
+
are recorded. The local development loop must not require synchronous human
|
|
262
|
+
approval for ordinary actions; a task that cannot safely produce a candidate is
|
|
263
|
+
parked or failed without granting remote/main authority. If the Decision Worker
|
|
264
|
+
API/model call fails, the system records `decision_worker_failed`, applies the
|
|
265
|
+
bounded retry/park policy and preserves the candidate evidence. Optional alert
|
|
266
|
+
delivery remains independent from event-log persistence, but notification is not
|
|
267
|
+
the control boundary.
|
|
231
268
|
|
|
232
269
|
## Acceptance, review and repair loop
|
|
233
270
|
|
|
234
271
|
A task may provide a structured `TaskSpec` with `goal`, `scope`, `constraints`,
|
|
235
|
-
`forbidden
|
|
272
|
+
`forbidden`, an ordered list of required or optional acceptance checks, and
|
|
273
|
+
`autonomy` (`unattended`, `requireLocalCommit`, `maxDecisionRetries`). A
|
|
236
274
|
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,
|
|
275
|
+
--check` acceptance check and unattended defaults. The verifier runs every configured check with argv,
|
|
238
276
|
bounded output and the same deterministic command policy; a Worker completion
|
|
239
277
|
claim never substitutes for these results.
|
|
240
278
|
|
|
@@ -243,35 +281,40 @@ fresh read-only Reviewer session. The Reviewer receives the task specification,
|
|
|
243
281
|
check results and bounded Worker completion evidence, but not the Decision Worker
|
|
244
282
|
conversation or control channel. It can inspect only `read`, `grep`, `find` and `ls`, and must return
|
|
245
283
|
`pass`, `revise` or `human` with bounded structured findings. Invalid Reviewer
|
|
246
|
-
output or a Reviewer API failure
|
|
284
|
+
output, incomplete evidence or a Reviewer API failure must prevent a candidate
|
|
285
|
+
from crossing the remote/main boundary; the local system may retry, repair or
|
|
286
|
+
park it without requiring a human to be online.
|
|
247
287
|
|
|
248
288
|
A `revise` result produces an audited repair round and sends a bounded corrective
|
|
249
289
|
instruction to a still-live `repairableSession` Worker. Checks and review then run again.
|
|
250
290
|
The repair budget defaults to three rounds; repeated findings and P0/P1 findings
|
|
251
|
-
stop automation and
|
|
291
|
+
stop automation and park a non-publishable candidate. A Worker that has already exited cannot be silently recreated
|
|
252
292
|
for repair; it remains failed/recoverable rather than replaying the original task. If a repair
|
|
253
|
-
or
|
|
293
|
+
or candidate branch cannot continue, a single idempotent terminalizer records
|
|
254
294
|
`verification_failed`, closes the Decision Worker and reports cleanup evidence; it never performs
|
|
255
295
|
a second `failed -> failed` transition.
|
|
256
296
|
|
|
257
|
-
Repository evidence is
|
|
258
|
-
|
|
259
|
-
|
|
297
|
+
Repository evidence is baseline-relative: the Supervisor records the initial HEAD,
|
|
298
|
+
then collects tracked committed/staged/unstaged changes, commit summaries after that
|
|
299
|
+
baseline and untracked regular files through bounded, component-safe, no-symlink reads.
|
|
300
|
+
Incomplete or truncated evidence is not sufficient for an independent `pass` verdict;
|
|
301
|
+
automatic mode parks a task when the required git baseline or local commit is unavailable. Acceptance
|
|
260
302
|
process output uses a bounded execution buffer before the smaller persisted evidence
|
|
261
303
|
limit, so a normal large test report is not misclassified as a failed command.
|
|
262
304
|
|
|
263
305
|
## Deliberate non-goals
|
|
264
306
|
|
|
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;
|
|
307
|
+
- giving the Worker remote push or main/integration merge authority;
|
|
308
|
+
- unauthenticated inbound webhook commands; outbound notifications are optional,
|
|
309
|
+
do not grant permission and do not replace the remote/main independent boundary;
|
|
310
|
+
- treating an unknown Claude interactive question as safe without task evidence or configured authorization;
|
|
311
|
+
- bypassing the configured Claude Code/task permissions;
|
|
270
312
|
- accepting model text as verification;
|
|
271
313
|
- shell command interpolation;
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
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;
|
|
275
318
|
- Claude CLI multi-version compatibility in the current stability milestone;
|
|
276
|
-
- OS sandbox
|
|
319
|
+
- full OS sandbox and low-privilege execution for custom Worker integrations in the current
|
|
277
320
|
lifecycle milestone.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# 自动化稳定性与生命周期加固计划
|
|
2
2
|
|
|
3
|
-
> 计划状态:Phase A–D
|
|
4
|
-
> 基线:`v0.5.
|
|
3
|
+
> 计划状态:Phase A–D、真实可编辑 repair/reacceptance、exact-head 独立只读 Review、受保护发布和本地无人值守闭环已完成;远程 push/main merge 仍是独立边界。
|
|
4
|
+
> 基线:`v0.5.2` / `eefc7bc`
|
|
5
5
|
> 真实验证:Claude Code `2.1.270`
|
|
6
6
|
> 记录日期:2026-09-14
|
|
7
7
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
-> argv/execFile 验收
|
|
16
16
|
-> 独立只读 Reviewer
|
|
17
17
|
-> P1/P2 阻塞发现
|
|
18
|
-
-> fail-closed /
|
|
18
|
+
-> fail-closed / parked non-publishable candidate
|
|
19
19
|
-> Worker、Pi、lease 清理
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -141,15 +141,18 @@ diff: (none)
|
|
|
141
141
|
- `repairableSession` 与 `persistentSession` 已分离;JSONL 仅支持当前进程内 repair,tmux 才声明持久恢复。
|
|
142
142
|
- `verifying` 的 stop/shutdown 使用统一 cleanup/finalize 路径,人工 stop 优先于验收结果,cleanup 不确定时保留恢复记录。
|
|
143
143
|
- paused Worker 不消耗 no-output watchdog;resume 重建 no-output 基准,但不重置累计 deadline。
|
|
144
|
-
- Reviewer evidence
|
|
145
|
-
- Acceptance 子进程、证据收集和 Reviewer 共享 abort signal;Pi UI 可看到 startup、Worker heartbeat、acceptance、review、repair 和
|
|
146
|
-
- 自动模式启动前检查运行目录、cwd、Worker
|
|
147
|
-
-
|
|
144
|
+
- Reviewer evidence 使用任务 baseline-relative diff、baseline 后 commit summaries、受限 untracked regular-file 内容、路径组件/symlink 门禁,并对 incomplete/truncated fail-closed。
|
|
145
|
+
- Acceptance 子进程、证据收集和 Reviewer 共享 abort signal;Pi UI 可看到 startup、Worker heartbeat、acceptance、review、repair 和 candidate/decision phases。
|
|
146
|
+
- 自动模式启动前检查运行目录、cwd、Worker 可执行文件、transport 依赖和 required cgroup;显式
|
|
147
|
+
`process-pipe` 仍仅限手动模式,Supervisor 自有 tmux bridge 可进入自动模式,被接管的
|
|
148
|
+
session 仍仅限手动 PTY transport。
|
|
149
|
+
- Reviewer/Decision Worker 只解析 assistant message 边界的最终文本;permission pending 会在自动响应后清除,候选状态不会被错误解除;扩大的 exec buffer 避免普通大测试报告被误判为命令失败。
|
|
148
150
|
|
|
149
|
-
|
|
151
|
+
本轮已完成:
|
|
150
152
|
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
+
- 普通本地命令和权限不再进入同步人工审批;Decision Worker 的无效输出、API 错误、Reviewer 失败、P0/P1、重复 finding、证据不完整和预算耗尽会进入 `blocked` 候选。
|
|
154
|
+
- TaskSpec 和环境变量提供 unattended/local-commit/Decision retry 控制;Worker 可在本地修改、测试、修复并提交,push、merge、发布和破坏性边界仍硬拒绝并写入审计。
|
|
155
|
+
- replay、候选通知和 baseline-relative commit evidence 覆盖正常完成、修复、歧义和挂起;保持独立 Review、保护 CI、Release Please 和 provenance 发布边界。
|
|
153
156
|
|
|
154
157
|
## 4. 实施顺序
|
|
155
158
|
|
|
@@ -157,23 +160,23 @@ diff: (none)
|
|
|
157
160
|
|
|
158
161
|
1. 增加 `repairableSession` capability。
|
|
159
162
|
2. JSONL 在当前 Supervisor 生命周期内支持 repair,仍不声明跨重启恢复。
|
|
160
|
-
3. 重构 repair/finalize/
|
|
163
|
+
3. 重构 repair/finalize/candidate 分支,保证终态转换和 Decision Worker closure 幂等。
|
|
161
164
|
4. `verifying` 支持 stop/shutdown,保留 cleanup 不确定时的 lease。
|
|
162
165
|
5. 增加真实非持久 adapter 和 stop-from-verifying 测试。
|
|
163
166
|
|
|
164
167
|
### Phase B:watchdog 与证据完整性
|
|
165
168
|
|
|
166
169
|
1. paused no-output 时钟暂停,resume 重建基准。
|
|
167
|
-
2. HEAD-relative diff 覆盖 staged/unstaged tracked
|
|
170
|
+
2. 记录任务开始时的 HEAD;baseline-relative diff 覆盖 committed/staged/unstaged tracked 修改,并记录 baseline 后 commits。
|
|
168
171
|
3. 安全收集 untracked regular-file evidence,防 symlink 和路径逃逸。
|
|
169
|
-
4. evidence truncation/incomplete
|
|
172
|
+
4. evidence truncation/incomplete 生成不可发布候选并自动挂起,不能自动 `pass`。
|
|
170
173
|
|
|
171
174
|
### Phase C:自动化协议和运行前保护
|
|
172
175
|
|
|
173
176
|
1. Reviewer/Decision Worker 按 assistant message 边界解析最终响应,不拼接所有工具回合文字。
|
|
174
177
|
2. 自动模式启动前执行 transport、Claude、cgroup、state/lease 目录 preflight。
|
|
175
178
|
3. 区分 Worker heartbeat、验收、Reviewer、repair 阶段,并提高实时可观测性。
|
|
176
|
-
4. 修复自动 permission 响应后的 stale pending request
|
|
179
|
+
4. 修复自动 permission 响应后的 stale pending request,并使本地决策不会依赖同步 human gate。
|
|
177
180
|
5. 清理 Pi extension 自己安装的 signal handler,避免与 Pi `session_shutdown` 竞争。
|
|
178
181
|
|
|
179
182
|
### Phase D:回归、真实演练和发布门禁
|
|
@@ -181,23 +184,22 @@ diff: (none)
|
|
|
181
184
|
1. 扩展 acceptance/replay/capability 矩阵。
|
|
182
185
|
2. 在临时 worktree 中使用真实 Claude 做一次受控 repair/reacceptance;禁止触碰主仓库。
|
|
183
186
|
3. 运行 `npm run check`、Pi/npm smoke、build 和真实只读 review。
|
|
184
|
-
4. 只有独立 Reviewer `pass`、所有检查通过、cleanup/lease
|
|
185
|
-
决定是否提交、合并或发布。
|
|
187
|
+
4. 只有独立 Reviewer `pass`、所有检查通过、cleanup/lease 证据完整后,才生成可交付本地候选;远程 push 和 main/integration merge 仍必须经过独立边界。
|
|
186
188
|
|
|
187
189
|
## 5. 验收矩阵
|
|
188
190
|
|
|
189
191
|
| 场景 | 预期 |
|
|
190
192
|
|---|---|
|
|
191
193
|
| JSONL Worker alive + P2 revise | 发送一次 bounded repair,重新验收 |
|
|
192
|
-
| JSONL Worker 已退出 + 验收失败 | 不抛非法 transition,记录 `verification_failed
|
|
193
|
-
| Reviewer `human` + Worker alive |
|
|
194
|
-
| Reviewer `human` + Worker 已退出 | 完成 cleanup、关闭 Decision Worker、保留 recoverable record |
|
|
194
|
+
| JSONL Worker 已退出 + 验收失败 | 不抛非法 transition,记录 `verification_failed`,生成不可发布候选 |
|
|
195
|
+
| Reviewer `human` + Worker alive | 不自动完成;按预算修复或挂起 `blocked` 候选,不要求人工在线 |
|
|
196
|
+
| Reviewer `human` + Worker 已退出 | 完成 cleanup、关闭 Decision Worker、保留 recoverable/parked record |
|
|
195
197
|
| `stop()` from `verifying` | `stopped`、cleanup confirmed 后释放 lease |
|
|
196
198
|
| shutdown from `verifying` | 不泄漏 Worker、Decision Worker 或 cwd lease |
|
|
197
199
|
| pause 超过 no-output timeout | 仍保持 paused |
|
|
198
200
|
| resume 后无输出 | 从 resume 时刻重新计算 timeout |
|
|
199
201
|
| staged + untracked 修改 | Reviewer evidence 包含两者 |
|
|
200
|
-
| evidence 截断/不可验证 | Reviewer
|
|
202
|
+
| evidence 截断/不可验证 | Reviewer 只能阻止 `pass`,候选自动挂起 |
|
|
201
203
|
| malformed/multi-message model output | 不误判为 pass/action |
|
|
202
204
|
| preflight 失败 | Claude 尚未启动前 fail-closed |
|
|
203
205
|
|
|
@@ -206,6 +208,6 @@ diff: (none)
|
|
|
206
208
|
- Reviewer 继续只允许 `read`、`grep`、`find`、`ls`。
|
|
207
209
|
- 验收命令继续使用 argv 和 `execFile`,不经过 shell 拼接。
|
|
208
210
|
- 不伪造 Claude `--resume`;`resumeSession` 仍然是明确能力声明。
|
|
209
|
-
-
|
|
211
|
+
- Worker 不得远程 push 或 merge 到 main/integration;发布仍走独立受保护 workflow。
|
|
210
212
|
- 不允许多 Worker 共享同一可写 worktree。
|
|
211
|
-
- P0/P1、重复 finding、超时、API 错误、无效输出和不完整证据继续 fail-closed
|
|
213
|
+
- P0/P1、重复 finding、超时、API 错误、无效输出和不完整证据继续 fail-closed,并自动生成不可发布/挂起候选,而不是要求同步人工响应。
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Confirmed autonomy target
|
|
2
|
+
|
|
3
|
+
> Owner-confirmed product requirement: local development is fully unattended; code entering a remote repository or the main/integration branch must cross an independent boundary.
|
|
4
|
+
|
|
5
|
+
This document is authoritative for the autonomy direction. Earlier planning text that treats a
|
|
6
|
+
human as a synchronous approval step for ordinary local development is historical conservative
|
|
7
|
+
baseline text and must not be used to add a new gate to the local development loop.
|
|
8
|
+
|
|
9
|
+
## 1. Target operating model
|
|
10
|
+
|
|
11
|
+
Once a task has been started with its task specification, the local development loop may run
|
|
12
|
+
without a human watching it:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
Worker edits and runs local commands
|
|
16
|
+
-> acceptance checks
|
|
17
|
+
-> independent Reviewer
|
|
18
|
+
-> bounded repair/reacceptance
|
|
19
|
+
-> local commit/candidate artifact
|
|
20
|
+
-> independent remote/main integration boundary
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The Supervisor may continue, answer, repair, test, review and commit locally. A human is not a
|
|
24
|
+
synchronous dependency for ordinary progress, routine ambiguity, or a normal failed test.
|
|
25
|
+
|
|
26
|
+
The system must still provide a kill switch, bounded execution, cleanup verification and a
|
|
27
|
+
complete audit trail. These are reliability and containment mechanisms, not requests for a human
|
|
28
|
+
to approve every development action. Automatic mode also records and revalidates a full existing
|
|
29
|
+
repository baseline, captures the startup HEAD and requires that exact HEAD again at
|
|
30
|
+
final pre-spawn, requires a non-protected branch and a pinned operator-owned direct Claude
|
|
31
|
+
JSONL Worker or Supervisor-owned tmux bridge, and by default requires a local commit before a candidate is deliverable.
|
|
32
|
+
|
|
33
|
+
## 2. Hard authority boundary
|
|
34
|
+
|
|
35
|
+
Automatic Worker supervision uses either the structured JSONL transport or a
|
|
36
|
+
Supervisor-owned tmux bridge. The bridge runs Claude's stream-json protocol inside the live
|
|
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.
|
|
47
|
+
|
|
48
|
+
A completed local task is a candidate until it passes the independent boundary. That boundary may
|
|
49
|
+
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.
|
|
51
|
+
|
|
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.
|
|
58
|
+
|
|
59
|
+
## 3. Unattended decision behavior
|
|
60
|
+
|
|
61
|
+
The Decision Worker should resolve ordinary development decisions from the task specification,
|
|
62
|
+
repository evidence and configured task policy, and record its assumptions and actions. It should
|
|
63
|
+
not turn every uncertainty into an interactive human prompt.
|
|
64
|
+
|
|
65
|
+
If the system cannot safely reach a candidate, it may automatically retry within the configured
|
|
66
|
+
budget, mark the task blocked/failed, preserve the worktree and evidence, or park it for later
|
|
67
|
+
inspection. “Parked for later inspection” is not the same as requiring a human to be online before
|
|
68
|
+
other tasks can proceed.
|
|
69
|
+
|
|
70
|
+
A task that reaches `blocked`, `review_pending` or `candidate_failed` must not be pushed or merged.
|
|
71
|
+
The same rule applies to a ready local candidate until the independent remote/main boundary accepts it.
|
|
72
|
+
It may be resumed, repaired or discarded later without weakening the remote/main boundary.
|
|
73
|
+
|
|
74
|
+
## 4. Acceptance and independent review
|
|
75
|
+
|
|
76
|
+
Acceptance and Reviewer remain automatic parts of the local loop:
|
|
77
|
+
|
|
78
|
+
- run all required checks;
|
|
79
|
+
- collect complete baseline-relative status, commit and untracked evidence;
|
|
80
|
+
- run the independent read-only Reviewer;
|
|
81
|
+
- apply bounded repair rounds;
|
|
82
|
+
- re-run acceptance and Review;
|
|
83
|
+
- produce a candidate with its evidence and assumptions.
|
|
84
|
+
|
|
85
|
+
Reviewer findings are first an automatic repair input. Exhausted budgets, incomplete evidence,
|
|
86
|
+
invalid output, duplicate findings or an unresolved finding produce a non-publishable
|
|
87
|
+
candidate/parked task; they do not by themselves require a synchronous takeover notification.
|
|
88
|
+
|
|
89
|
+
## 5. Notifications and shutdown
|
|
90
|
+
|
|
91
|
+
Progress, assumptions, failures and candidate readiness must be recorded in the event log. Live
|
|
92
|
+
notifications are optional delivery policy, not the local development control protocol.
|
|
93
|
+
|
|
94
|
+
Immediate shutdown remains appropriate for technical containment failures such as an unverified
|
|
95
|
+
Worker cleanup boundary, corrupted control state or an explicit operator kill. The system should
|
|
96
|
+
stop or park safely and retain evidence; it must not silently grant remote or main-branch access.
|
|
97
|
+
|
|
98
|
+
## 6. Current implementation
|
|
99
|
+
|
|
100
|
+
Automatic mode implements the local loop: policy decisions allow ordinary local development,
|
|
101
|
+
`AskUserQuestion` is converted to a denied interactive permission, the Decision Worker can
|
|
102
|
+
continue/redirect/answer/repair, acceptance and independent Review run without a human callback,
|
|
103
|
+
and unresolved situations become `blocked` candidates. The default task autonomy is unattended, requires a local commit, and permits two bounded
|
|
104
|
+
Decision Worker request retries. Automatic startup rejects non-Git/detached/bare/protected
|
|
105
|
+
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
|
|
108
|
+
executable identity is persisted with the Decision Worker recovery record and must match
|
|
109
|
+
again during recovery.
|
|
110
|
+
|
|
111
|
+
Legacy `humanRequired`, takeover and approval fields remain for compatibility and explicit operator
|
|
112
|
+
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.
|
|
117
|
+
|
|
118
|
+
## 7. Explicit non-goals of this target
|
|
119
|
+
|
|
120
|
+
This target does not authorize:
|
|
121
|
+
|
|
122
|
+
- remote push from the Worker;
|
|
123
|
+
- merge into `main` from the Worker;
|
|
124
|
+
- bypassing the independent integration boundary;
|
|
125
|
+
- silently treating incomplete evidence as success;
|
|
126
|
+
- claiming that a failed or parked task completed.
|
|
127
|
+
|
|
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.
|