Files
makelore/.project-docs/10-decisions/proposals/20260825-pi-worker-exit-thinking-5e7c2a91__pi-runtime-resilience-hardening.md
T

26 KiB
Raw Blame History

Pi Runtime 鲁棒性加固规范与实施计划

0. 文档信息

字段 值
状态 PI-R001 已实施并完成验证;PI-R002 保持后续任务
规划任务 20260825-pi-runtime-resilience-plan-4b8e2c71
当前文档所有者 20260825-pi-worker-exit-thinking-5e7c2a91
规划基线 274187e3cfe2ae6cb97f2b4bcb422b3fdf06fbf2
原始规范 20260822-pi-runtime-spec-b6e2c9a4__pi-runtime-cutover-spec.md
原始票据图 20260822-pi-runtime-spec-b6e2c9a4__pi-runtime-cutover-tickets.md
故障诊断 20260825-pi-stuck-processing-diagnosis-7c4e91a2
当前实施任务 20260825-pi-worker-exit-thinking-5e7c2a91
当前实施基线 274187e3cfe2ae6cb97f2b4bcb422b3fdf06fbf2
Pi 版本 @earendil-works/pi-coding-agent@0.84.2,保持精确 pin
日期 2026-08-25

本文是既有 OpenCode → Pi 硬切换规范的事故后补充,不修改原 18 节点 / 31 边 DAG,也不恢复 OpenCode fallback。它把原规范中的 RUN-004、RUN-007、RPC-004、API-003、UX-023、UX-026 和第 18 节故障恢复要求收紧为可执行、可观测、可在最终 Windows 安装包中故障注入的合同。

本次不承诺第三方 Pi 进程“永不退出”。产品承诺是:Pi worker 可以失败,但 Makelore 应用不随之退出;Conversation 不永久锁死;未确认的请求不自动重发;任何 worker 重建都有明确原因并受 generation 隔离。

1. 事实、推测与未验证边界

1.1 已确认事实

  1. 事故发生后 Electron Main 与 Renderer 仍存活,目标 Pi RPC worker 已不存在。
  2. 目标 session JSONL 结构有效;最后是 assistant toolUse(task_state) 与对应 toolResult,没有后续权威 agent_settled。
  3. PiWorkerPool.handleInvalidation() 已将 worker 标为 crashed、释放 top-level permit 并发出 worker.crashed。
  4. PiConversationRuntime.onPoolEvent() 对 worker.crashed 只投影 worker.state,没有调用已有 failRun(),因此 worker 已错误而 run 仍为 running。
  5. PiConversationRuntime.abort() 在 worker 已退出时请求失败,当前 catch 会恢复旧的 running 状态,造成第二条永久锁死路径。
  6. Renderer 的“生成中”“当前对话正在处理”和 Send 禁用均由 run 状态派生;Renderer 是无效 Main 状态的下游表现,不是根因。
  7. 复制 session 后,使用最终安装包 Electron executable、Pi 0.84.2、实际 Makelore extension 与受控 loopback Provider 的 11 类故障矩阵均正常 agent_settled;普通 HTTP 500、已测的 partial/malformed SSE、正常 task_state 和 copied session 不是此次退出的确定性原因。
  8. 当前 PI_RPC_EXITED 没有携带已有的脱敏 stderr 诊断;Main 日志也不能区分自发退出、RPC 协议失效后强杀和 Main 主动 stop。
  9. set_thinking_level=high 在当前托管模型形状下可能实际得到 effective off,但产品仍持久化请求值;该能力合同错误已确认,但没有证据表明它导致了 worker 退出。

1.2 合理推测

  • 当前最严重的产品缺陷不是“发生了一个未知退出”,而是生命周期模块未把退出收敛为 Conversation 终态,并且缺少能定位退出发起方的结构化证据。
  • 只增加自动重启或固定时长 watchdog 会掩盖状态机缺陷,并可能重复执行已经被 Provider 或 tool 接受的 mutation。
  • 保持一 Conversation 一 worker 的隔离模型,比改成单一全局 Pi daemon 更能控制故障半径。

1.3 尚未验证

  • 本次 worker 消失究竟是一次真实 HTTPS/Undici/Electron-Node 异常、Main 侧 RPC protocol invalidation,还是主动 stop/rebuild 竞态,现有 artifact 无法判定。
  • 真实 Provider 的认证、代理、限流、响应差异、真实并发和跨 worker 凭据隔离仍未验证。用户已将其标记为 Explicitly Waived / Accepted Risk,realTurnVerified=false。
  • macOS x64/arm64 与 native non-WSL Linux 的发布证据状态不因本规范改变。

2. 目标与非目标

2.1 目标

  1. Pi worker 异常退出不得导致 Electron Main、Renderer 或整个应用退出。
  2. matching generation 的 worker 一旦不可用,任何仍活动的 run 必须有界收敛到 status=error、terminalReason=failed、recoverable=true。
  3. Composer 在故障终态恢复编辑/恢复操作,不得继续显示无界“处理中”。
  4. crash、abort、agent_settled、recover 和 generation replacement 必须按 Conversation + generation 串行且终态单调。
  5. accepted 或 uncertain prompt 永不自动重放;recover 复用同一产品 Conversation 和已有 Pi session binding。
  6. 每个 Main 主动 stop、protocol invalidation 和 unexpected exit 可明确区分,且诊断不泄露敏感内容。
  7. thinking level 只持久化 Pi 实际支持并接受的 effective level;切换本身不得隐式重启正常 worker。
  8. 最终 Windows 安装包具备确定性故障注入证明,而不是只依赖 fake child 单测。

2.2 非目标

  • 不保证操作系统、Electron、Pi、原生依赖或 Provider 永不失败。
  • 不新增全局 runtime start/stop/restart UI。
  • 不引入 OpenCode fallback、双 runtime、兼容层、feature flag 或 Pi 上游 fork。
  • 不添加“长时间无输出就杀 worker”的通用 Provider watchdog。
  • 不自动重发 prompt、steer、follow-up、fork、compact 或任何 mutation RPC。
  • 不把 loopback/fault injection 写成真实 Provider Pass。
  • 不在本票据完成 macOS 或 native non-WSL Linux 发布验收。

3. 架构裁决

3.1 深模块与 seam

继续由 Main-owned PiConversationRuntime 作为产品 Conversation 生命周期的深模块。Renderer、Host route 和 store 只消费 Makelore-owned Snapshot/Patch 与稳定错误;它们不理解 Pi process、RPC、stderr 或 stop reason。

内部职责保持:

  • PiWorkerProcess:spawn、RPC 字节流、exit/close、协议失效、有限诊断和进程树退出。
  • PiWorkerPool:Conversation → worker/generation 归属、permit、LRU、active run、replacement 与 crash event。
  • PiConversationRuntime:产品 run 状态、event projection、terminalization、recover/hydration 与 Host SSE。
  • PiSessionRegistry:Conversation 与 session binding、模型和 thinking metadata 的持久化。
  • extension/subagent/write-lease 模块:generation/run-owned 资源,失败时可由同一生命周期收敛路径取消。

不得新增一个只转发这些方法的浅层“supervisor service”。需要的行为应深化现有三个模块,并以现有 CodingConversationRuntime interface 作为外部 test seam。

3.2 核心不变量

ID 不变量
RES-INV-001 同一 Conversation 不允许长期存在 worker=crashed/error 且 run=running/aborting/retrying/compacting。
RES-INV-002 matching generation 的 crash 只能结束目标 Conversation;其他 Conversation 的 Snapshot、run、queue、worker 与 draft 不变化。
RES-INV-003 terminal run 单调;较晚到达的 close、abort rejection 或旧 generation event 不得覆盖 completed/aborted/failed。
RES-INV-004 clientRequestId 已 accepted 或状态 uncertain 时,不得因 recover/SSE reconnect/worker replacement 自动再次执行 mutation。
RES-INV-005 每个 generation replacement 必须有 Main-owned bounded reason;没有 reason 的 replacement 是测试失败。
RES-INV-006 running worker 不因 LRU、thinking change、同账号 model change 或普通 diagnostics 被 stop。
RES-INV-007 worker crash 后 permit、interaction、extension run、child、process lease 与 write lease 最终全部释放。
RES-INV-008 recover 使用原 Conversation/session binding;不截断、覆盖或静默替换旧 JSONL。
RES-INV-009 原始 stderr、Provider body、prompt、tool 内容、Header、Token、账号 ID、完整路径不进入 Renderer 或普通日志。

3.3 目标状态流

idle/ready -> preparing/queued -> running -> settling -> idle/completed
                                  |             |
                                  |             +-> late close: keep completed
                                  +-> worker exit/protocol invalidation
                                      -> error/failed/recoverable
                                      -> explicit recover
                                      -> new generation + same session binding
                                      -> hydrate -> idle

不存在从 worker exit 返回旧 running 的边;不存在从 recover 自动重发旧 prompt 的边。

4. 故障分类与重建政策

4.1 进程终止分类

分类 判断来源 产品动作 重建政策
Main intentional stop stop 前已记录 reason 按原业务完成清理;不伪装 crash 仅由对应显式操作或安全边界继续
RPC protocol invalidation strict framer/RPC 判定 保留 PI_RPC_PROTOCOL_ERROR,强制结束目标 generation 用户 recover;mutation 不重放
Unexpected exit 无 intentional stop、无既有 protocol invalidation 的 exit/close 保留 PI_RPC_EXITED 内部分类并投影稳定 recoverable runtime error 用户 recover;mutation 不重放
App shutdown app_shutdown reason 拒绝新 prompt,3 秒 graceful 后整树 kill 下次启动按 registry reopen
Idle eviction idle_eviction reason,且 run 已 idle 保留 session binding,不投影 run failure 下次显式 prepare 可重开
Stale resource rebuild stale_resource_rebuild reason active run 先 settled;旧 generation 失效 settled 后一次重建
Recover/dispose/fork replacement 对应显式 reason 取消旧 generation 资源并保持产品语义 只执行该操作要求的 replacement

Main 主动 stop reason 使用有限内部类型,至少覆盖:

app_shutdown
idle_eviction
stale_resource_rebuild
recover
dispose
fork_replacement
protocol_invalidation
test_injection

实现可使用与当前调用点等价的更精确名称,但禁止自由文本 reason 和缺省 reason。

4.2 自动动作边界

  • 保留既有只读 RPC 在 generation 不变时最多一次 retry 的合同。
  • spawn/ready 失败继续进入明确 recoverable error,不添加后台无限拉起。
  • accepted run 的 worker 退出后不自动新建 generation,也不自动重发请求。
  • 用户显式 recover 才执行“关闭旧 generation → 清理 → spawn → reopen same binding → hydrate”。
  • Provider 的 429/5xx 只使用 Pi 自己的有界 retry;Main 不叠加 retry。
  • 不使用无 token/无事件时长作为 worker 死亡判断。合法的模型推理、工具执行和 compaction 可能很长。

5. 运行时终态与竞态合同

5.1 worker.crashed

PiConversationRuntime 必须把 crash handling 放入目标 Conversation 的 projection chain:

  1. 读取事件携带的 Conversation、generation 和原始 PiProcessError。
  2. 若 Snapshot 不存在或 generation 已过期,只做脱敏 lifecycle 记录,不改产品状态。
  3. 取消该 generation 的 interaction、extension run、child 与其他 run-owned 资源。
  4. 若 matching run 仍为活动状态,调用统一 failRun(),投影 status=error、terminalReason=failed、settledAt 与稳定 recoverable error。
  5. 投影 worker error state。
  6. 若 run 已被较早的权威 agent_settled 终结,不得改写终态。

5.2 abort()

  • live worker 的正常 abort 继续等待权威 agent_settled,不得伪造成功。
  • abort request 失败后必须重新读取最新 run 与 matching worker generation。
  • run 已 terminal:保留终态并返回/投影对应结果。
  • worker 已 crashed/absent 且仍是同一活动 run:收敛到与 crash 相同的 failed/recoverable 终态。
  • worker 仍 live、abort RPC 只是可恢复命令错误:可以恢复原活动态并返回错误,但必须证明 worker 仍归该 generation。
  • 任何路径都不得把 error/completed/aborted 恢复成 running。

5.3 事件顺序

必须覆盖以下交错:

  1. worker.crashed -> abort rejection;最终 failed。
  2. abort request -> worker.crashed;最终 failed,不回到 running。
  3. agent_settled(completed) -> close;保持 completed。
  4. worker.crashed -> late agent_settled from old generation;忽略 late event,保持 failed。
  5. recover generation N+1 -> generation N late response/event/interaction;全部丢弃。
  6. 目标 Conversation crash 时另一个 Conversation running/settled;另一个不受影响。

6. 资源与会话完整性

6.1 必须收敛的资源

资源 所有者 crash 后要求
top-level running permit Worker pool 释放一次,计数不得为负
queued run Worker pool 目标项以原始错误拒绝,不重排其他 FIFO
process lease Worker pool/process budget finally 释放
interaction Interaction store generation/run scoped cancel
extension run binding Extension host/UI clear/end,旧 token 无效
subagent dispatch/child permit Scheduler parent crash 向下取消并释放
child process Child opener 有界 stop/kill,零残留
project write lease Write lease holder/waiter 均可取消,其他项目不受影响

所有清理动作必须可重复;一个 cleanup step 失败不得阻止后续资源释放。不得用吞掉所有错误来伪装成功,首个失败应进入脱敏诊断。

6.2 Session 与请求安全

  • worker exit 保留 session JSONL 和 registry binding。
  • recover 不创建新的产品 Conversation,不改变稳定 Conversation ID。
  • hydrate 从 get_state/get_entries 重建 Snapshot,并继续使用 generation fence。
  • 已持久化的 assistant/tool 结果可以水合;尚未确认的 prompt 不重发。
  • draft、待上传 attachment 和 optimistic user node 按现有 request reconciliation 规则保留。
  • session unreadable 继续 fail closed;不得自动截断或覆盖文件。

7. Model、thinking 与 revision 合同

7.1 Thinking

  1. 调用前获取或使用已验证的 get_available_thinking_levels 能力。
  2. 不支持的 level 必须拒绝,或由明确产品规则选择并展示有效值;不得请求 high 却持久化一个 Pi 实际为 off 的假状态。
  3. set_thinking_level 成功后读取 Pi effective state,只有 effective value 可写入 Registry 和 Snapshot。
  4. 写 Registry 失败时保持旧产品状态并投影稳定 persistence error。
  5. thinking change 不 replacement worker generation。
  6. 当 Provider 无法真正关闭 reasoning 时,UI 不得把“关闭思考”表现为可保证抑制 Provider reasoning 的能力。

7.2 Model 与资源 revision

  • 同 Provider account 的 model change 继续使用 set_model,不重建 worker。
  • 跨 Provider account 只重建目标 Conversation,并保持现有 credential isolation。
  • Provider/resource/credential revision 在 run active 时只标记 stale;settled 后用显式 reason 重建。
  • revision rebuild、recover、fork replacement 的 generation reason 必须进入 Main-only lifecycle 记录。

8. 可观测性与隐私

8.1 Main-only lifecycle 事件

至少记录以下结构化事件:

worker.stop_requested
worker.protocol_invalidated
worker.exit
worker.close
worker.crashed
run.failed
worker.replacement_started
worker.replacement_ready
worker.recovered

允许字段:匿名/局部 Conversation 标识、runId 局部标识、generation、stage、stop reason、错误 code、exit code、signal、cold/warm、duration、是否完成各类 cleanup。

禁止字段:prompt、assistant 内容、thinking 内容、tool 名称/参数/结果、文件内容、完整路径、Provider body、Header、Token、credential、账号 ID、完整 request ID。

8.2 错误保真

  • PiWorkerProcess 在 PI_RPC_EXITED 中附带已有的 bounded/redacted stderr tail。
  • protocol invalidation 保留原 PI_RPC_PROTOCOL_ERROR,后续 close 不得覆盖错误类别。
  • intentional stop 不能被 close handler 再标成 crash。
  • stderr 只进入 Main-owned diagnostic/log,不进入 Renderer DTO。
  • 若新安装包再次发生问题,证据必须能直接回答“谁发起 stop、哪类 invalidation、哪个 generation、退出码/信号是什么”。

如结构化证据仍只显示无法解释的原生异常终止,再单独评估 opt-in Windows dump;本票据不先引入 crash-dump 基础设施。

9. 用户体验合同

  • worker crash 后,目标 Conversation 在 Main 收到 exit/invalidated 后不晚于 2 秒进入 recoverable error。
  • Textarea 保持可编辑;Composer 不再显示无界“当前对话正在处理”。
  • UI 显示固定中文说明:本地 Agent 已中断,原请求未自动重发。
  • 提供目标 Conversation 的 recover 操作;recover 失败保持可再次操作的错误态,不进入永久 recovering。
  • 另一个 Conversation 的生成、输入、队列和错误不变化。
  • 技术 stderr、exit code、内部路径和 stop reason 不直接展示给普通用户;诊断面板只保留安全结构化状态。

10. 实施票据与阶段

本规范新增事故后纠正票据 PI-R001,不插入或重写原 18 节点 / 31 边 cutover DAG。

PI-R001 — Pi worker failure convergence and explainable lifecycle

字段 值
状态 已授权;实施中
实施任务 20260825-pi-worker-exit-thinking-5e7c2a91
基线 274187e3cfe2ae6cb97f2b4bcb422b3fdf06fbf2
依赖 已交付的 Pi hard cutover、Windows proxy/session reopen hotfix、故障诊断任务
解锁 新 Windows 安装包人工复测;后续 PI-R002 soak/现场归因

阶段 A:生命周期终态

  • 修改 electron/coding-runtime/pi/runtime.ts 的 crash projection 与 abort race。
  • 必要时调整 worker-pool.ts 事件载荷,但不得扩大公共 Renderer interface。
  • 先添加 red-capable 回归,再修改实现。

产物:worker crash/abort/settled 的单调状态机;目标 run 不再永久 active。

阶段 B:退出分类与 stop reason

  • 修改 worker-process.ts、process-errors.ts、worker-pool.ts、telemetry.ts。
  • 显式标注所有 stop 调用点;保留 protocol/exit 原始分类与脱敏 stderr。
  • 证明 intentional stop 不被 close 误判,protocol failure 不被 exit 覆盖。

产物:可解释 generation replacement 与下一次现场问题所需的最小证据。

阶段 C:资源收敛

  • 覆盖 extension、interaction、subagent、process budget 和 write lease 的 crash cleanup。
  • 复用现有 cleanup seam,不新增全局协调器。
  • 验证 cleanup 部分失败时仍继续释放其余资源。

产物:目标故障后所有活动/等待计数归零,其他 Conversation 继续运行。

阶段 D:thinking 能力合同

  • 修改 runtime.ts、provider-config.ts、managed catalog/Registry 相关代码。
  • 只持久化 effective level,unsupported level 不伪装成功。
  • 验证 thinking change 和同账号 model change 不产生 generation replacement。

产物:UI、Registry 与 Pi 实际状态一致。

阶段 E:Host、Renderer 与安装包证明

  • 覆盖 electron/api/routes/coding-conversations.ts、src/stores/coding-conversations.ts、CodingChatPanel.tsx、CodingComposer.tsx、CodingConversationHeader.tsx 的现有 seam。
  • 扩展 release-proof.ts、fake child、Windows Electron E2E 与 packaged proof。
  • 生成新的 Windows x64 NSIS,并返回路径、大小、SHA-256 和 clean candidate commit。

产物:最终安装包中可复现的强制退出、恢复和零残留证明。

PI-R002 — Soak and incident classification follow-up

PI-R002 不与 PI-R001 并发实施,也不阻断当前修复包交付。它在 PI-R001 安装包完成后执行:

  1. 以受控 loopback 连续运行 create/open/prompt/tool/abort/recover,并随机注入目标 worker exit。
  2. 在 4 parent + 4 child 压力中注入单点失败,确认隔离和计数收敛。
  3. 观察 normal path 的 generation replacement:每次都必须有已知 reason,未知 reason 为失败。
  4. 若用户真实环境再次发生退出,读取新的结构化诊断确定 initiating class,再决定是本地修复、上游 Pi issue 还是 Windows/Electron 原生诊断。

真实 Provider 因用户 waiver 不属于 PI-R002 hard gate;这意味着产品只能宣称本地 runtime failure containment 已验证,不能宣称所有真实 Provider 行为已验证。

11. 验收矩阵

ID 场景 必须结果
RES-ACC-001 accepted running + unexpected worker exit ≤2 秒投影 run error/failed/recoverable;Composer 解锁;应用存活
RES-ACC-002 worker exit 后点击 abort 不恢复 running;最终仍为 failed/recoverable
RES-ACC-003 abort 与 exit 交错 终态单调;资源只释放一次
RES-ACC-004 agent_settled 后 close completed/aborted 不被改成 failed
RES-ACC-005 crash 后旧 generation event 被丢弃,不修改新 Snapshot
RES-ACC-006 Conversation A crash、B running B 正常 settled,B generation/run/draft 不变
RES-ACC-007 strict JSONL protocol violation 保留 protocol error,记录 protocol stop reason,目标 worker 被清理
RES-ACC-008 deliberate idle eviction/app shutdown/recover 各自记录正确 reason,不记为 unexpected crash
RES-ACC-009 crash 时存在 interaction/child/write lease 全部取消/释放;其他 Conversation/项目不受影响
RES-ACC-010 recover existing Conversation 复用 session binding,hydrate 成功,不自动重发原 prompt
RES-ACC-011 thinking level unsupported 拒绝或返回实际 effective level,不持久化假值
RES-ACC-012 thinking 与同账号 model change worker generation 不变化
RES-ACC-013 stderr 含 token/header/content 形状 Main 诊断有界脱敏;Renderer/日志无敏感值
RES-ACC-014 final packaged fault injection 真实 app.asar Main + packaged Pi 通过 crash/recover/isolation/cleanup
RES-ACC-015 应用退出 3 秒 graceful/强杀合同生效,最终本任务 Pi/Electron 残留进程为 0
RES-ACC-016 正常 packaged flow 无无原因 generation replacement;既有 cold/warm/acceptance 预算不回退

12. 测试与发布门禁

12.1 Focused tests

  • tests/unit/pi-conversation-runtime.test.ts
  • tests/unit/pi-worker-pool.test.ts
  • tests/unit/pi-worker-process-real.test.ts
  • tests/unit/pi-rpc-foundation.test.ts
  • tests/unit/pi-subagent.test.ts
  • tests/unit/pi-write-lease.test.ts
  • tests/unit/coding-conversations-store.test.tsx
  • tests/unit/coding-chat-panel.test.tsx
  • 对应 Host route、release proof 和 managed model tests

每个行为变更必须先有能在旧实现失败的正确 seam 回归。不得只断言函数“没有抛错”;必须断言最终 Snapshot、generation、资源计数、日志分类和 prompt 未重放。

12.2 必跑命令

使用 packageManager 固定的 pnpm 10.33.4:

corepack pnpm install --frozen-lockfile
corepack pnpm run typecheck
corepack pnpm run lint:check
corepack pnpm test
corepack pnpm run build:vite
corepack pnpm run test:electron:windows
corepack pnpm run package:win
corepack pnpm run verify:publish-runtime
corepack pnpm run verify:artifact:win
corepack pnpm run verify:artifact:pi
corepack pnpm run test:pi-subagent:packaged

12.3 Packaged fault injection

最终 clean candidate 的 Windows 安装包必须覆盖:

  1. running 中强制退出真实 packaged Pi worker;Main/Renderer 存活。
  2. abort-after-exit;不会回到 running。
  3. settled-before-close;completed 不被覆盖。
  4. strict framer protocol invalidation;错误分类不被 close 覆盖。
  5. deliberate stop;reason 与 crash 分类分离。
  6. 目标 recover;原 binding/hydration 保留,原 uncertain prompt 不重发。
  7. 两 Conversation 隔离;只杀一个 worker,另一个完成。
  8. parent/child/write lease/process budget 清理;所有 active/waiting 计数归零。
  9. thinking/model 变更不造成非预期 generation replacement。
  10. stderr redaction 与退出后零残留进程。

报告必须绑定:代码 commit、安装器路径、字节数、SHA-256、Electron/Node/Pi 版本、测试样本、realTurnVerified=false 和未完成平台边界。

13. 提交与合并批次

推荐批次如下,每批都可独立审阅:

  1. test: reproduce Pi worker exit lifecycle lock:只加入 crash/abort/ordering red tests。
  2. fix: terminalize Pi worker failures:runtime/pool 最小状态机修复与资源收敛。
  3. feat: classify Pi worker lifecycle exits:stop reason、错误保真、脱敏 diagnostics。
  4. fix: persist effective Pi thinking level:capability/effective state 与 no-restart tests。
  5. test: prove packaged Pi failure recovery:Host/Renderer/E2E/release proof。
  6. docs: record Pi resilience qualification:任务证据、安装器信息和剩余风险。

合并前必须审阅累计 diff;不得把旧 hotfix worktree、诊断临时脚本、构建输出、安装器、用户数据或敏感日志提交进 Git。

14. 阻断与停止条件

出现以下任一情况,实施任务不得宣称完成:

  • crash 后仍能得到 worker error + active run 的组合。
  • abort-after-exit 仍恢复 running/aborting。
  • accepted prompt 在 recover、SSE reconnect 或 worker replacement 中被再次发送。
  • cleanup 只在 happy path 归零,fault injection 后有 orphan process/permit/lease。
  • protocol error 被后续 close 覆盖成普通 exit。
  • 任一 generation replacement 缺少 reason。
  • thinking UI/Registry 与 Pi effective state 不一致。
  • packaged proof 只使用 repo-source composition 或 fake process,没有穿过最终 app.asar Main 与 packaged Pi。
  • 最终 Windows artifact/runtime closure、Electron E2E、build 或文档门禁失败。

若完成上述本地合同需要修改 Pi 上游包、引入全局 daemon 或改变真实 Provider waiver,实施者必须停止并回报,不得自行扩大架构方向。

15. 风险与发布口径

  • PI-R001 通过后可以宣称:Windows 最终安装包已验证 Pi worker 故障隔离、Conversation 终态收敛、显式恢复、无自动重放、退出可观测和零残留。
  • 不得宣称:Pi 永不崩溃、真实 Provider 永不触发新协议问题、跨平台 release-ready。
  • 真实 Provider:Explicitly Waived / Accepted Risk,realTurnVerified=false,不是 Pass。
  • macOS x64/arm64、native non-WSL Linux:状态不变,不是本票据 Pass。
  • 新诊断上线后若再现问题,优先使用结构化 exit/stop evidence 定位;不要先增加重启次数、watchdog 或内容日志。