@logicseek/hello-cc 1.1.0 → 1.1.1

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
@@ -16,6 +16,56 @@ the release description from the current changelog section. Use
16
16
  `npm run release:github` with `GH_TOKEN` or `GITHUB_TOKEN` only for local
17
17
  backfills.
18
18
 
19
+ ## 1.1.1
20
+
21
+ ### Summary
22
+
23
+ This maintenance release completes native submission recovery and shutdown
24
+ verification, improves ownership diagnostics, and tightens Web request and file
25
+ boundaries while retaining the existing workbench and provider interfaces.
26
+
27
+ ### Highlights
28
+
29
+ - Keep CLI submission listings separate for each coordination database in the
30
+ same project. Validate saved database bindings before filtering, and continue
31
+ rejecting same-ID retries against a different database. Document offline
32
+ receipt inspection and recovery with the original submission ID.
33
+ - Give owned stdio providers time to handle EOF and reap their ordinary child
34
+ processes. Confirm process exit and stdio closure before reporting shutdown;
35
+ retain incomplete-cleanup receipts and explicit retry behavior. Preserve safe
36
+ loopback listener error codes and endpoints for ownership startup failures.
37
+ - Require any supplied Origin to match for Web writes, including Bearer-authenticated
38
+ requests. Keep cookie writes dependent on affirmative same-origin evidence and
39
+ preserve CLI requests without Origin. Query tokens remain restricted to login
40
+ and browser session exchange.
41
+ - Preserve the original Web submission when the same Claude executor confirms
42
+ its first session ID after a lost send response. Keep worker, generation,
43
+ body and already-known session IDs fenced, and retain bounded HTTP retry
44
+ diagnostics without storing response text or credentials.
45
+ - Refuse project file browsing, previews, status and context-file search on
46
+ native Windows before filesystem access. Return HTTP 503 with WSL guidance
47
+ instead of a pathname-based fallback; verify the guard on a Windows runner.
48
+ - Restore omitted regressions for provider reconnects, authoritative completion,
49
+ duplicate reply/ACK suppression, uncertain deliveries, directory replacement
50
+ before spawn and Claude hook root receipts. Add repeatable Claude transcript
51
+ fork checks using the actual SDK and CLI with either local fixture responses
52
+ or the caller's configured model route.
53
+ - Distinguish missing dead-pane PID evidence from a changed PID during tmux GC.
54
+ Newer tmux versions can hide the PID after terminal exit; retain those sessions
55
+ and their database bindings, and verify both supported observation modes in CI.
56
+
57
+ ### Validation
58
+
59
+ Focused native, ownership and real HTTP tests cover the repaired paths. Installed
60
+ package and browser acceptance use isolated projects and provider fixtures.
61
+ Separate authenticated checks cover Codex, Claude and DSH replies, memory,
62
+ close/resume and interruption, plus scoped communication between providers.
63
+ Codex approval rejection and five deterministic official DSH approval scenarios
64
+ are checked separately. Claude model checks establish the configured route,
65
+ not access to an untested Anthropic model. These checks do not establish employee
66
+ device, 24-hour endurance, capacity or business acceptance. The release retains
67
+ its own immutable package and validation receipts without changing prior archives.
68
+
19
69
  ## 1.1.0
20
70
 
21
71
  ### Summary
package/README.md CHANGED
@@ -13,17 +13,17 @@
13
13
 
14
14
  <p align="center"><b>English</b> | <a href="README.zh-CN.md">中文</a></p>
15
15
 
16
- `hello-cc` is a local control plane for Claude Code, Codex, and other coding
17
- CLI sessions. It gives every terminal in one project a shared task board,
18
- mailbox, lock table, and browser console while keeping the real local terminal
19
- as the source of interaction.
16
+ `hello-cc` is a local multi-agent workbench for Claude Code, Codex, and DeepSeek
17
+ Harness. Start background Agents from the browser or continue managed local
18
+ terminal sessions, with a shared project task board, mailbox, lock table, and
19
+ handoffs.
20
20
 
21
21
  <p align="center">
22
- <img src="assets/screenshots/web-console.png" width="900" alt="hello-cc Web console showing agent sessions, task state, locks, messages, and terminal output">
22
+ <img src="assets/screenshots/web-console.png" width="900" alt="hello-cc 1.1.0 Web workbench showing background Agents, a structured conversation, tool activity, and shared project state">
23
23
  </p>
24
24
 
25
25
  <p align="center">
26
- <em>One local Web console for tmux-backed Claude Code, Codex, tasks, locks, messages, and handoffs.</em>
26
+ <em>One local workbench for Claude, Codex, and DeepSeek Harness: conversations, tools, approvals, and project coordination. Screenshot uses demo data.</em>
27
27
  </p>
28
28
 
29
29
  It is built for developers who run multiple AI coding agents in the same repo
@@ -37,6 +37,14 @@ pre-migration backup; downgrading that database is unsupported. Provider peer
37
37
  IDs now hash the full provider session value and old IDs are not remapped.
38
38
  Runtime API v2 and per-connection terminal action tokens are required.
39
39
 
40
+ Version 1.1.0 also binds project state, managed launches, and verified Codex
41
+ history to the selected directory's filesystem identity. Stable, trusted
42
+ projects can use `<project>/.hello-cc/mesh.db`; projects requiring private state
43
+ use `~/.hello-cc/projects/<canonical-root-hash>/mesh.db`, with separate generations
44
+ for replacement directories. Existing private v1 bindings require a reviewed
45
+ offline upgrade. See [project identity and private state](docs/private-state.md)
46
+ before migrating or recovering an existing store.
47
+
40
48
  Liveness follows tmux/non-tmux process evidence: sleep or detachment does not
41
49
  kill a live session, and only unknown evidence receives the bounded 120-second
42
50
  grace. `hcc gc` retains history unless `--history` is explicit. `--tls` encrypts
@@ -46,12 +54,21 @@ LANs, and an authenticated browser may select any existing server directory.
46
54
 
47
55
  ## Highlights
48
56
 
49
- - **Shared project memory**: peers, tasks, messages, locks, handoffs, and
50
- events are stored in `<project>/.hello-cc/mesh.db`.
51
- - **Real terminal control**: Web attaches to the same local tmux pane as your
52
- terminal, not a separate browser-only shell.
53
- - **Claude/Codex awareness**: hooks inject live `hcc` state before model turns,
54
- so agents can answer from current project state.
57
+ - **Background Agents**: create Codex, Claude, and DeepSeek Harness workers
58
+ directly from Web; save a default provider, model, and working directory per
59
+ project.
60
+ - **Structured conversations**: follow messages, tool activity, delivery receipts,
61
+ and supported approval or user-input requests in the same session.
62
+ - **Local and Web workflows**: continue the same native worker through CLI and
63
+ Web, or attach to a managed local tmux pane. Advanced options also offer Codex
64
+ App Server sessions.
65
+ - **Project files**: browse and preview files and generated artifacts, upload new
66
+ files, and edit supported text with version checks.
67
+ - **Shared project memory**: peers, tasks, messages, locks, handoffs, and events
68
+ live in the project's SQLite bus, separate from other projects.
69
+ - **Live agent coordination**: hooks and scoped MCP tools expose project tasks
70
+ and inboxes to connected agents; DeepSeek Harness also supports hooks and
71
+ Cordis integration.
55
72
  - **Conflict avoidance**: advisory locks and handoffs make multi-agent editing
56
73
  explicit.
57
74
  - **Explicit team splits**: `hcc team plan/start/status` turns one parallel
@@ -63,9 +80,12 @@ LANs, and an authenticated browser may select any existing server directory.
63
80
 
64
81
  ## Install And Manage
65
82
 
66
- hello-cc supports Linux and macOS. Node.js 24 or newer is required, and
67
- browser-controllable terminals require `tmux`. Native Windows shells are not
68
- currently supported; use WSL for a Linux-like environment.
83
+ hello-cc supports Linux and macOS on arm64 and x64. Node.js 24 or newer is
84
+ required. `hcc web` requires `tmux`, including when you plan to create background
85
+ Agents from Web. Native Windows shells are not currently supported; use WSL
86
+ and install the dependencies inside it.
87
+ File browsing, previews, status and context-file search refuse native Windows
88
+ with `PROJECT_FILE_READ_UNAVAILABLE` (HTTP 503); there is no pathname-based fallback.
69
89
 
70
90
  Linux has richer process auto-discovery through `/proc`. On macOS, use
71
91
  hello-cc shims or `hcc peer start` for reliable tmux-managed terminal sessions.
@@ -103,10 +123,18 @@ hcc --version
103
123
  hcc --help
104
124
  ```
105
125
 
126
+ Install and authenticate the provider you want to use in the environment that
127
+ runs hello-cc. Background Agents require an App Server-compatible Codex CLI,
128
+ the optional Claude Agent SDK for Claude, or DeepSeek Harness with ACP support
129
+ (the supported Harness baseline is `0.2.0-rc.2`). See
130
+ [Native worker requirements](docs/native.md#requirements) for setup, including
131
+ the Claude SDK installation command, and [DeepSeek Harness](docs/dsh.md) for its
132
+ integration modes.
133
+
106
134
  If npm reports `EACCES`, use a Node version manager or a user-owned npm prefix;
107
135
  do not work around it with `sudo npm install -g`.
108
136
 
109
- Update an existing global install:
137
+ Update an existing global install to the npm `latest` channel:
110
138
 
111
139
  ```bash
112
140
  hcc update
@@ -157,6 +185,25 @@ shims, starts or reuses the Web console, and returns the terminal to you.
157
185
  Use `hcc up` when you want local coordination commands without the Web console
158
186
  or shims.
159
187
 
188
+ ### Start A Background Agent
189
+
190
+ 1. Select the project in Web and click **New Agent**.
191
+ 2. Choose Codex, Claude, or DeepSeek Harness; **Background Agent** is the default.
192
+ The selected provider must already be installed and authenticated.
193
+ 3. Keep the project root or choose a directory inside it. Leave the model empty
194
+ to use the provider's configured default, then create the Agent.
195
+ 4. Send a prompt, follow the conversation and tool activity, and explicitly
196
+ respond to any supported approval or user-input requests.
197
+
198
+ **Settings** saves project defaults for future background Agents. **History**
199
+ browses retained workers and offers explicit resume for eligible closed workers.
200
+ Closing the page or stopping Web leaves the independent native runtime and
201
+ workers running; use **Close executor** or `hcc native close --peer <peer>`
202
+ when you want to close a worker. See [Native Workers](docs/native.md#start-from-web)
203
+ for lifecycle details.
204
+
205
+ ### Continue A Managed Local Terminal
206
+
160
207
  After the first shim install, open a new terminal or reload the rc file for
161
208
  your shell:
162
209
 
@@ -164,7 +211,7 @@ your shell:
164
211
  - zsh: `source ~/.zshrc`
165
212
  - fish: `source ~/.config/fish/config.fish`
166
213
 
167
- Start normal agent sessions from the project:
214
+ Start normal Claude/Codex terminal sessions from the project:
168
215
 
169
216
  ```bash
170
217
  claude
@@ -175,10 +222,14 @@ codex resume <session-id>
175
222
 
176
223
  Those sessions become tmux-backed peers that can be seen and controlled from
177
224
  Web while remaining usable from the local terminal. The shims only use the
178
- current project's runtime file. If you start `claude` or `codex` in a directory
179
- where `hcc web` has not created `.hello-cc/runtime.json`, the shim falls back to
180
- the real provider CLI instead of using the global Web runtime or creating a new
181
- project database.
225
+ runtime resolved for the current project, including its private state directory
226
+ when applicable. Without a current-project Web runtime, they fall back to the
227
+ real provider CLI; they do not use the global Web runtime to register unrelated
228
+ directories or create project databases.
229
+
230
+ Web controls HCC-managed workers and terminals. Cooperation with an existing
231
+ provider desktop App uses separate opt-in adapters; see
232
+ [Desktop Agent communication](docs/app-bridge.md) for the supported paths.
182
233
 
183
234
  ## Basic Workflow
184
235
 
@@ -213,6 +264,10 @@ generic session-isolation assumptions.
213
264
  project setup and Web launch, with real-model and local-package acceptance evidence.
214
265
  - [Native Workers](docs/native.md): HCC-owned Codex, Claude SDK, and dsh ACP
215
266
  workers, delivery receipts, permissions, and saved-session ownership.
267
+ - [Web Workflows (Chinese)](docs/web-handoff.zh-CN.md): new Agents, project files,
268
+ structured interactions, history, and local/Web handoffs.
269
+ - [Desktop Agent Communication](docs/app-bridge.md): opt-in cooperation with
270
+ original provider Apps and their execution boundaries.
216
271
  - [Changelog](CHANGELOG.md): release notes for published versions.
217
272
  - [Design Notes](docs/design.md): product boundaries and coordination model.
218
273
  - [Implementation Notes](docs/implementation.md): architecture and internal
package/README.zh-CN.md CHANGED
@@ -13,20 +13,25 @@
13
13
 
14
14
  <p align="center"><a href="README.md">English</a> | <b>中文</b></p>
15
15
 
16
- `hello-cc` 是 Claude Code、Codex 和其他编程 CLI 会话的本地控制平面。它让同一个项目里的终端共享任务板、消息、锁、交接和浏览器控制台,同时保留真实本地终端作为主要交互入口。
16
+ `hello-cc` 是 Claude、Codex 和 DeepSeek Harness 的本地多 Agent 工作台。你可以在 Web 中新建后台 Agent,查看结构化对话和工具审批,也可以继续使用真实本地终端;同一项目中的 Agent 共享任务板、消息、锁和交接。
17
17
 
18
18
  <p align="center">
19
- <img src="assets/screenshots/web-console.png" width="900" alt="hello-cc Web 控制台,展示 agent 会话、任务状态、锁、消息和终端输出">
19
+ <img src="assets/screenshots/web-console.png" width="900" alt="hello-cc Web 工作台,展示后台 Agent、结构化对话、工具审批和项目协作">
20
20
  </p>
21
21
 
22
22
  <p align="center">
23
- <em>一个本地 Web 控制台,统一管理 tmux-backed Claude Code、Codex、任务、锁、消息和交接。</em>
23
+ <em>在一个本地 Web 工作台中管理 Claude、Codex、DeepSeek Harness 后台 Agent 与受管终端。截图使用演示数据。</em>
24
24
  </p>
25
25
 
26
26
  它适合在同一个仓库里同时运行多个 AI 编程 agent 的场景:让它们知道彼此在做什么,而不是各自猜测。
27
27
 
28
28
  ## v1 兼容性与信任边界
29
29
 
30
+ 1.1.0 将项目状态、受管启动、Web/native 会话和 Codex 历史绑定到所选目录的
31
+ 文件系统身份。同一路径被替换时使用独立状态分代;历史私有 v1 绑定升级到 v2
32
+ 需核实原目录并停止全部写入者。状态位置和迁移命令见
33
+ [项目目录身份与私有状态](docs/private-state.zh-CN.md)。
34
+
30
35
  1.0.0 会在生成并校验升级前备份后,把项目数据库升级到 schema v7;升级后的
31
36
  数据库不支持降级。provider peer ID 改为对完整 provider session 值做哈希,旧 ID
32
37
  不会自动映射或迁移。受保护的接口使用 Runtime API v2,终端 action token 按
@@ -40,9 +45,12 @@ unknown 证据获得最长 120 秒宽限。`hcc gc` 默认保留历史,必须
40
45
 
41
46
  ## 特色
42
47
 
43
- - **项目本地共享状态**:peers、tasks、messages、locks、handoffs 和 events 写入 `<project>/.hello-cc/mesh.db`。
44
- - **Web 控制真实终端**:浏览器 attach 到和本地终端相同的 tmux pane,不是浏览器里另开的临时 shell。
45
- - **Claude/Codex 感知项目状态**:hooks 会在模型回答前注入实时 `hcc` 状态。
48
+ - **多 provider 后台 Agent**:直接从 Web 新建 Claude、Codex 或 DeepSeek Harness worker,查看结构化对话、工具执行和投递回执,处理工具审批与问题。
49
+ - **项目启动默认值**:保存默认 provider、模型和项目内工作目录,供后续 Web 新建 Agent 使用。
50
+ - **项目文件与产物**:在 Web 预览文本、Markdown、HTML、图片和 PDF,显式上传文件或编辑文本。
51
+ - **项目共享 SQLite 总线**:peers、tasks、messages、locks、handoffs 和 events 保存在项目状态中;位置可以是 `<project>/.hello-cc/`、`~/.hello-cc/projects/<hash>/` 或独立 generation,详见[状态指南](docs/private-state.zh-CN.md)。
52
+ - **本地与 Web 续接**:Web 接入 HCC 持有的 native worker 或已有受管 tmux pane,继续同一执行器;本地 CLI 也可继续处理。已有桌面 App 保留自身执行器,通过单独的[接入方式](docs/app-bridge.zh-CN.md)协作。
53
+ - **Agent 感知项目状态**:Claude/Codex hooks、DeepSeek Harness 集成和受限 MCP 工具提供实时 `hcc` 状态与协作操作。
46
54
  - **减少编辑冲突**:通过 advisory lock 和 handoff 显式协调多 agent 修改。
47
55
  - **显式团队拆分**:`hcc team plan/start/status` 可以把一个并行任务拆成可审计
48
56
  子任务,不会隐藏地自动启动进程。
@@ -51,8 +59,16 @@ unknown 证据获得最长 120 秒宽限。`hcc gc` 默认保留历史,必须
51
59
 
52
60
  ## 安装和维护
53
61
 
54
- hello-cc 支持 Linux 和 macOS。需要 Node.js 24 或更新版本;可被浏览器控制的
55
- 终端需要 `tmux`。当前不支持原生 Windows shell;Windows 用户建议使用 WSL。
62
+ hello-cc 支持 Linux 和 macOS。需要 Node.js 24 或更新版本;`hcc web` 和受管
63
+ 终端需要 `tmux`。发行包包含 macOS/Linux arm64 与 x64 的目录交接 helper。
64
+ 当前不支持原生 Windows shell;Windows 用户建议使用 WSL。
65
+ 原生 Windows 上的文件浏览、预览、状态和上下文文件搜索会明确返回
66
+ `PROJECT_FILE_READ_UNAVAILABLE`(HTTP 503),不再回退到不安全的路径读取。
67
+
68
+ 在运行 hello-cc 的同一环境中安装并登录所需 provider。Codex 后台 Agent 需要支持
69
+ App Server 的 Codex CLI;DeepSeek Harness 后台 Agent 需要 DSH ACP runtime;
70
+ Claude 后台 Agent 使用可选的 Claude Agent SDK,hello-cc 不会自动安装它。
71
+ 具体版本和安装方式见 [Native 指南](docs/native.zh-CN.md#环境准备)。
56
72
 
57
73
  Linux 可以通过 `/proc` 做更完整的进程自动发现。macOS 上建议通过 hello-cc
58
74
  shim 或 `hcc peer start` 启动会话,以获得可靠的 tmux 托管终端。
@@ -141,6 +157,20 @@ local: http://127.0.0.1:8787/?token=<runtime-token>&project=/path/to/project
141
157
  `hcc web --local` 仍然是 Web 模式,只是限制监听在本机 loopback。只想使用本地
142
158
  协作命令、不启动 Web 控制台、不安装 shims 时,使用 `hcc up`。
143
159
 
160
+ ### 从 Web 新建后台 Agent
161
+
162
+ 1. 打开上述 URL,选择项目并点击“新建 Agent”。
163
+ 2. 选择 Codex、Claude 或 DeepSeek Harness,使用默认的“后台 Agent”方式。
164
+ 3. 核对工作目录与模型后创建;模型留空使用 provider 当前配置,名称留空自动生成。
165
+ 4. 在会话中发送提示,查看结构化对话与投递回执,并按需处理审批。顶部“设置”可保存项目启动默认值,“文件”可预览、上传和编辑项目文件。
166
+
167
+ 后台服务按需启动,无需先运行 `hcc native start`。关闭页面或停止 Web 不会关闭
168
+ 独立的后台 worker;不再需要时,明确使用“关闭执行器”或 `hcc native close --peer NAME`。
169
+ 恢复已关闭的 worker 可使用项目栏“历史”中的“HCC 保留历史”。详细操作见
170
+ [Web 指南](docs/web-handoff.zh-CN.md)和 [Native 指南](docs/native.zh-CN.md)。
171
+
172
+ ### 继续使用本地终端
173
+
144
174
  第一次安装 shim 后,打开新终端,或根据当前 shell 重新加载配置:
145
175
 
146
176
  - bash: `source ~/.bashrc`
@@ -157,9 +187,9 @@ codex resume <session-id>
157
187
  ```
158
188
 
159
189
  这些会话会成为 tmux-backed peer,可以继续在本地终端里使用,也可以被 Web 控制台观察和操作。
160
- shim 只使用当前项目自己的 runtime 文件。如果你在没有通过 `hcc web` 创建
161
- `.hello-cc/runtime.json` 的目录里启动 `claude` 或 `codex`,shim 会回退到真实
162
- provider CLI,不会使用全局 Web runtime,也不会为这个目录新建项目数据库。
190
+ shim 只使用解析后的当前项目 runtime;它可能位于项目局部或私有状态目录。
191
+ 如果当前项目没有通过 `hcc web` 建立可用 runtime,启动 `claude` 或 `codex` 时
192
+ 会回退到真实 provider CLI,不会使用全局 Web runtime,也不会为这个目录新建项目数据库。
163
193
 
164
194
  ## 基本流程
165
195
 
@@ -192,6 +222,10 @@ hcc task done --id 1 --summary "Done"
192
222
  项目配置与 Web 启动;附真实模型和本地包验收记录。
193
223
  - [Native 后台 worker](docs/native.zh-CN.md):HCC 持有的 Codex、Claude SDK、dsh ACP
194
224
  worker,以及投递回执、权限和保存会话的所有权边界。
225
+ - [Web 新建与本地续接](docs/web-handoff.zh-CN.md):后台 Agent、项目启动默认值、文件上传编辑、控制权和历史恢复。
226
+ - [桌面 Agent 通信](docs/app-bridge.zh-CN.md):DSH 空闲收件唤醒、Codex 会话内协作和可选 Claude Desktop Mod。
227
+ - [设计说明](docs/design.md)与[实现说明](docs/implementation.md)(英文):产品边界、协作语义、协议与技术栈。
228
+ - [架构设计](docs/architecture.zh-CN.md):模块边界、依赖方向与目录结构。
195
229
  - [更新日志](CHANGELOG.md):已发布版本的 release notes。
196
230
 
197
231
  ## 测试
Binary file
package/docs/commands.md CHANGED
@@ -158,6 +158,11 @@ hcc inject PEER TEXT [--no-enter]
158
158
  These commands create or attach tmux-backed terminals that can be viewed and
159
159
  controlled from the Web console.
160
160
 
161
+ `hcc tmux gc --older-than 14` previews database-proven stale sessions; add `--yes`
162
+ to delete eligible sessions, or `--peer PEER` to restrict the plan. If tmux omits
163
+ the PID of an exited pane, GC reports `tmux_dead_process_pid_unknown` and retains
164
+ both the session and its binding. Age and pane death alone do not authorize deletion.
165
+
161
166
  ## Messages
162
167
 
163
168
  ```text
@@ -143,6 +143,11 @@ hcc inject PEER TEXT [--no-enter]
143
143
 
144
144
  这些命令创建或接入 tmux-backed 终端,让 Web 控制台可以观察和操作它们。
145
145
 
146
+ `hcc tmux gc --older-than 14` 预览数据库能证明归属的过期会话;添加 `--yes`
147
+ 才会删除符合条件的会话,`--peer PEER` 可限定目标。若 tmux 不再提供已退出
148
+ pane 的 PID,GC 返回 `tmux_dead_process_pid_unknown`,保留会话及数据库绑定。
149
+ 仅凭会话年龄或 pane 已退出,不会获得自动删除权限。
150
+
146
151
  ## 消息
147
152
 
148
153
  ```text
package/docs/native.md CHANGED
@@ -64,11 +64,21 @@ ID together. If the native delivery projection was not yet saved, retry or
64
64
  worker recovery repairs the original delivery while retaining local user
65
65
  origin. Retrying an existing `uncertain` delivery does not replay execution.
66
66
 
67
+ When no ID is supplied, the CLI durably journals a generated ID before sending.
68
+ Use `hcc native submissions [--peer NAME]` to inspect these IDs and saved receipts
69
+ even while the runtime is offline. Listings are scoped to the selected project
70
+ database. `unconfirmed` means that no queue receipt was saved; the request may
71
+ already have been sent. Inspect deliveries and retry the original ID with the
72
+ same peer, sender, task and body instead of submitting a new message.
73
+
67
74
  Web offers **Retry same submission** for an unconfirmed send. Explicit
68
75
  confirmation follows receipt inspection, and the retry must retain the original
69
76
  executor and body. Later draft edits are preserved. Executor or project changes
70
77
  disable the old retry. Missing durable pending records or expired messages are
71
78
  rejected rather than sent as new work.
79
+ For Claude's first send, the same executor may confirm its initially absent
80
+ session ID before a retry. That confirmation preserves the original submission;
81
+ changed owners, generations, bodies or already-known session IDs remain rejected.
72
82
 
73
83
  ## Requirements
74
84
 
@@ -226,6 +236,7 @@ policy and cannot override it; the child is independently verified before use.
226
236
  | `hcc native fork` | Required `--parent NAME --peer NEW_NAME`; optional `--model MODEL --binary PATH`; forks an HCC-owned Codex or Claude session into a new worker |
227
237
  | `hcc native send` | Required `--peer NAME --body TEXT`; optional `--from NAME --task ID --submission-id ID`; returns a durable message/submission receipt |
228
238
  | `hcc native deliveries` | Optional `--peer NAME`; inspect delivery receipts |
239
+ | `hcc native submissions` | Optional `--peer NAME`; inspect the selected database's locally journaled submission IDs and queue receipts, including offline |
229
240
  | `hcc native events` | Required `--peer NAME`; optional `--after ID`; inspect a bounded event history |
230
241
  | `hcc native requests` | Requires `--peer NAME`; inspect pending requests bound to this executor, session and turn |
231
242
  | `hcc native respond` | Requires `--peer NAME --request ID --decision accept\|decline\|cancel`; use `--response-file JSON` for permission subsets, answers or MCP form content |
@@ -238,6 +249,18 @@ Inspect `native status` to check the outcome. If provider shutdown fails, HCC
238
249
  retains runtime ownership and reports the error in `status.shutdown_error`;
239
250
  resolve the reported problem and retry `native down`.
240
251
 
252
+ Owned stdio providers first receive EOF so they can finish cleanup themselves.
253
+ HCC escalates to SIGTERM and SIGKILL if needed, and requires both direct process
254
+ exit and closed stdio pipes before confirming transport shutdown. If an inherited
255
+ pipe stays open, `NATIVE_CLOSE_FAILED` reports `NATIVE_STDIO_CLOSE_TIMEOUT`; HCC
256
+ keeps runtime ownership for an explicit retry. It does not signal an already
257
+ exited PID or guess ownership of detached descendants.
258
+
259
+ An ownership listener permission or resource failure reports
260
+ `NATIVE_OWNERSHIP_UNAVAILABLE` with a bounded OS error code, errno, syscall and
261
+ loopback endpoint. These failures are distinct from an existing runtime owner
262
+ and do not start a provider or retry the bind as ordinary lock contention.
263
+
241
264
  Worker events retain semantic output and completion evidence; token deltas are
242
265
  not persisted as delivery receipts. The runtime keeps local state under
243
266
  `<resolved-project-state>/native/` (project-local or private storage described
@@ -464,6 +487,23 @@ harness checks explicit approval and rejection and continuing the original
464
487
  session. It uses existing authentication/quota, cleans test provider homes and
465
488
  processes, and never attaches to existing user conversations.
466
489
 
490
+ For repeatable Claude transcript-fork diagnosis, run the actual installed SDK
491
+ and its CLI with a deterministic local Messages fixture:
492
+
493
+ ```sh
494
+ node scripts/claude-fork-acceptance.mjs --fixture \
495
+ --claude-package /absolute/path/to/claude-agent-sdk \
496
+ --output /absolute/path/to/fork-receipt.json
497
+ ```
498
+
499
+ It snapshots parent and child message hashes immediately after copying and
500
+ before the first child query, then checks initial recall, branch isolation,
501
+ child resume and a closed-parent fork. Failures retain available history hashes
502
+ before removing the private project and provider home. This mode uses no model
503
+ or credentials. Replace `--fixture` with `--run-live` to use existing routing/auth
504
+ and provider quota; only the model reported in that receipt is verified. Neither
505
+ mode can recover the cause of a historical failure whose transcripts were removed.
506
+
467
507
 
468
508
  `--provider dsh --dsh-bin /absolute/path/to/dsh` uses the installed public launcher
469
509
  and existing `DEEPSEEK_API_KEY`. The harness adds an official `tools/pre-execute`
@@ -54,10 +54,18 @@ fork;HCC 不用 transcript 重放冒充原生 fork。
54
54
  重试或 worker 恢复会补齐原记录,保留用户请求来源。已有 `uncertain` 投递不会
55
55
  因为重试被自动重放。
56
56
 
57
+ 未指定 ID 时,CLI 会先将自动生成的 ID 持久写入本地日志,再发送请求。
58
+ 使用 `hcc native submissions [--peer NAME]` 查看这些 ID 和已保存的队列回执;
59
+ runtime 离线时也能查询,列表只包含当前选择的项目数据库。`unconfirmed` 表示
60
+ 没有保存队列回执,请求仍可能已发送。应先核对 deliveries,再沿用原 ID、peer、
61
+ sender、task 和正文重试,避免提交一条新消息。
62
+
57
63
  Web 遇到未确认提交时提供“沿用原提交重试”。此操作需核对持久回执后明确确认,
58
64
  并保持原执行器身份与原正文;之后编辑的草稿会保留。执行器或项目变化时禁用原
59
65
  提交重试。没有匹配的持久 pending 记录、或原消息已被清理时拒绝重试;不会把
60
66
  原 ID 当作新工作发送。
67
+ Claude 首次发送时尚未确认的 session ID,可由同一执行器在重试前完成确认,
68
+ 继续沿用原提交。owner、generation、正文或已知 session ID 的变化仍会被拒绝。
61
69
 
62
70
  ## 环境准备
63
71
 
@@ -193,6 +201,7 @@ HCC 不为只读 worker 注入自有的任务/锁/结果写操作 MCP,也
193
201
  | `hcc native fork` | 必须 `--parent NAME --peer NEW_NAME`;可选 `--model MODEL --binary PATH`;复制 HCC 持有的 Codex 或 Claude 会话到新 worker |
194
202
  | `hcc native send` | 必须 `--peer NAME --body TEXT`;可选 `--from NAME --task ID --submission-id ID`;返回持久消息/submission 回执 |
195
203
  | `hcc native deliveries` | 可选 `--peer NAME`,查看投递回执 |
204
+ | `hcc native submissions` | 可选 `--peer NAME`,查看当前数据库的本地 submission ID 和队列回执,支持离线查询 |
196
205
  | `hcc native events` | 必须 `--peer NAME`;可选 `--after ID`,查看有界事件历史 |
197
206
  | `hcc native requests` | 必须 `--peer NAME`;查看与该执行器、会话、turn 绑定的待处理请求 |
198
207
  | `hcc native respond` | 必须 `--peer NAME --request ID --decision accept\|decline\|cancel`;权限子集、问题答案或 MCP 表单内容通过 `--response-file JSON` 提交 |
@@ -204,6 +213,16 @@ HCC 不为只读 worker 注入自有的任务/锁/结果写操作 MCP,也
204
213
  确认结果。若 provider 关闭失败,HCC 保留 runtime owner,并在
205
214
  `status.shutdown_error` 报告错误;处理所报问题后,再次执行 `native down`。
206
215
 
216
+ HCC 先向自有 stdio provider 发送 EOF,让 provider 有机会自行清理,再按需升级为
217
+ SIGTERM 和 SIGKILL。确认传输关闭需要直接进程退出且 stdio 管道全部关闭。
218
+ 若继承的管道仍被占用,`NATIVE_CLOSE_FAILED` 会报告 `NATIVE_STDIO_CLOSE_TIMEOUT`,
219
+ runtime 保留所有权,等待明确重试。HCC 不会向已退出的 PID 发信号,也不会猜测
220
+ 脱离原连接的后代进程归属。
221
+
222
+ 所有权监听器遇到权限或资源故障时,报告 `NATIVE_OWNERSHIP_UNAVAILABLE`,包含
223
+ 限定范围的系统错误码、errno、syscall 和 loopback 端点。此类故障与已有 runtime
224
+ 占用分别报告,不会启动 provider,也不会作为普通锁竞争反复尝试绑定。
225
+
207
226
  事件保留语义输出和完成证据,不把 token delta 持久化为投递回执。runtime 状态位于
208
227
  `<解析后的项目状态目录>/native/`,可以是项目局部或上方说明的私有状态;协作记录
209
228
  仍写入所选 HCC 数据库。控制接口是独立于 Web
@@ -392,6 +411,21 @@ Web 验证覆盖服务与 bridge 控制接口,尚不等于完整浏览器操
392
411
  解析,不注入 query 函数。脚本验证明确批准与拒绝、原会话续接,退出后关闭测试
393
412
  进程并清理临时 provider home;使用现有认证和调用额度。它不连接现有用户会话。
394
413
 
414
+ Claude 转录分叉的可重复诊断可使用实际安装的 SDK 和其 CLI,配合本地确定性
415
+ Messages 响应服务运行:
416
+
417
+ ```sh
418
+ node scripts/claude-fork-acceptance.mjs --fixture \
419
+ --claude-package /absolute/path/to/claude-agent-sdk \
420
+ --output /absolute/path/to/fork-receipt.json
421
+ ```
422
+
423
+ 脚本在复制后、首次子查询前立即保存父子消息哈希,验证首次回忆、父子分支隔离、
424
+ 子会话恢复及关闭父会话后再分叉。失败时也先保存可读历史的摘要,再清理私有项目
425
+ 和 provider home。此模式不调用模型或使用真实凭据;改用 `--run-live` 会使用现有
426
+ 路由和认证并消耗额度,验收仅覆盖回执实际报告的模型。两种模式都不能恢复已清理
427
+ 转录的历史失败原因。
428
+
395
429
  `--provider dsh --dsh-bin /absolute/path/to/dsh` 使用已安装的公开 launcher 和现有
396
430
  `DEEPSEEK_API_KEY`。脚本在私有 ACP profile 中通过公开 `tools/pre-execute` 策略
397
431
  让两个指定验收文件的写入请求审批;审批请求来自真实模型工具调用,不注入 ACP 请求。
@@ -58,6 +58,11 @@ export function validateTmuxGcDeadProcessEvidence(stored = {}, observed = {}, op
58
58
  const authority = validateTmuxAuthorityEvidence(stored, observed);
59
59
  if (!authority.ok) return authority;
60
60
  if (!observed.pane_dead) return { ok: false, reason: 'tmux_pane_not_dead' };
61
+ // Newer tmux versions omit pane_pid once its PTY is closed. A dead pane
62
+ // without that binding is insufficient authority for automatic deletion.
63
+ if (!Number.isSafeInteger(observed.pane_pid) || observed.pane_pid <= 0) {
64
+ return { ok: false, reason: 'tmux_dead_process_pid_unknown' };
65
+ }
61
66
  if (Number(observed.pane_pid) !== Number(stored.process_identity.pid)) {
62
67
  return { ok: false, reason: 'tmux_dead_process_pid_changed' };
63
68
  }
@@ -34,6 +34,7 @@ export class JsonRpcProcess {
34
34
  this.buffer = '';
35
35
  this.closed = false;
36
36
  this.child = null;
37
+ this.childClosed = false;
37
38
  this.closePromise = null;
38
39
  this.lastCloseError = null;
39
40
  }
@@ -45,6 +46,8 @@ export class JsonRpcProcess {
45
46
  this.child = spawnPinnedCwdProcess(binary, args, {
46
47
  cwd: cwd || process.cwd(), env, expectedIdentity, shell: false, stdio: ['pipe', 'pipe', 'pipe']
47
48
  });
49
+ // Keep the close receipt even when close() is called after direct exit.
50
+ this.child.once('close', () => { this.childClosed = true; });
48
51
  this.child.stdout.setEncoding('utf8');
49
52
  this.child.stdout.on('data', (chunk) => this.read(chunk));
50
53
  // Drain stderr without putting credentials or unbounded provider logs into
@@ -164,27 +167,47 @@ export class JsonRpcProcess {
164
167
  this.fail(new CliError('NATIVE_TRANSPORT_CLOSED', 'Native provider connection closed', { uncertain: true }));
165
168
  const child = this.child;
166
169
  // A failed spawn has no PID and emits close/error, but never exit.
167
- if (!child?.pid || child.exitCode !== null || child.signalCode !== null) {
170
+ if (!child?.pid || this.childClosed) {
168
171
  this.closePromise = Promise.resolve();
169
172
  return this.closePromise;
170
173
  }
171
174
  this.closePromise = new Promise((resolve, reject) => {
175
+ let eofTimer;
172
176
  let termTimer;
173
177
  let killTimer;
178
+ let stdioTimer;
179
+ let settled = false;
180
+ const hasExited = () => child.exitCode !== null || child.signalCode !== null;
174
181
  const cleanup = () => {
182
+ clearTimeout(eofTimer);
175
183
  clearTimeout(termTimer);
176
184
  clearTimeout(killTimer);
185
+ clearTimeout(stdioTimer);
177
186
  child.removeListener('exit', exited);
187
+ child.removeListener('close', finished);
178
188
  child.removeListener('error', failed);
179
189
  };
180
- const exited = () => { cleanup(); resolve(); };
190
+ const finished = () => {
191
+ if (settled) return;
192
+ settled = true; cleanup(); resolve();
193
+ };
181
194
  const failed = (error) => {
195
+ if (settled) return;
196
+ settled = true;
182
197
  cleanup();
183
198
  this.lastCloseError = new CliError('NATIVE_CLOSE_FAILED', 'Cannot confirm native provider process termination', {
184
199
  pid: child.pid, uncertain: true, cause: error.code || error.message
185
200
  });
186
201
  reject(this.lastCloseError);
187
202
  };
203
+ const exited = () => {
204
+ clearTimeout(eofTimer); clearTimeout(termTimer); clearTimeout(killTimer);
205
+ if (this.childClosed) return finished();
206
+ // Never signal an exited PID or guess ownership of descendants. Keep
207
+ // an unclosed inherited pipe visible as incomplete transport cleanup.
208
+ if (!stdioTimer) stdioTimer = setTimeout(() => failed(new CliError('NATIVE_STDIO_CLOSE_TIMEOUT',
209
+ 'Native provider exited but its stdio did not close')), this.options.closeKillTimeoutMs ?? 2000);
210
+ };
188
211
  const signal = (name) => {
189
212
  try {
190
213
  if (!child.kill(name)) {
@@ -195,16 +218,27 @@ export class JsonRpcProcess {
195
218
  } catch (error) { failed(error); return false; }
196
219
  };
197
220
  child.once('exit', exited);
221
+ child.once('close', finished);
198
222
  child.once('error', failed);
199
- termTimer = setTimeout(() => {
200
- if (child.exitCode !== null || child.signalCode !== null) return exited();
201
- // Sending SIGKILL is not an exit receipt. Continue waiting for exit.
202
- killTimer = setTimeout(() => failed(new CliError('NATIVE_EXIT_TIMEOUT',
203
- 'Native provider did not report exit after SIGKILL')), this.options.closeKillTimeoutMs ?? 2000);
204
- signal('SIGKILL');
205
- }, this.options.closeGraceMs ?? 2000);
206
- try { child.stdin.end(); } catch {}
207
- signal('SIGTERM');
223
+ if (hasExited()) return exited();
224
+ const terminate = () => {
225
+ if (settled) return;
226
+ clearTimeout(eofTimer);
227
+ if (hasExited()) return exited();
228
+ termTimer = setTimeout(() => {
229
+ if (hasExited()) return exited();
230
+ // Sending SIGKILL is not a close receipt. Continue waiting for exit
231
+ // and closed stdio, with a separate bounded wait after direct exit.
232
+ killTimer = setTimeout(() => failed(new CliError('NATIVE_EXIT_TIMEOUT',
233
+ 'Native provider did not report exit after SIGKILL')), this.options.closeKillTimeoutMs ?? 2000);
234
+ signal('SIGKILL');
235
+ }, this.options.closeGraceMs ?? 2000);
236
+ signal('SIGTERM');
237
+ };
238
+ // Let the provider handle EOF and reap its own ordinary subprocesses
239
+ // before escalating. closeGraceMs retains its SIGTERM-to-SIGKILL meaning.
240
+ eofTimer = setTimeout(terminate, this.options.closeEofGraceMs ?? 1000);
241
+ try { child.stdin.end(); } catch { terminate(); }
208
242
  });
209
243
  const closing = this.closePromise;
210
244
  void closing.catch(() => {