5.0 KiB
Production handoff recovery
仅在生产发布被 coding-session handoff 阻塞、manifest 进入 failed_closed,或存在 needs_review / 不确定命令时读取。
目标是保留 fail-closed 语义,在明确授权下终结歧义状态,并证明没有误重放命令。
先冻结发布,不先解锁
- 停止发布切换和自动重试;记录 release ID、候选 SHA、manifest ID、阻塞发生阶段与原始错误。
- 不把“继续”“再试一次”解释为 replay、force-end 或生产发布授权。向用户展示证据后,确认语句应绑定 manifest、 条目数量或 command ID、目标 action/outcome、是否禁止 replay,以及要继续发布的精确 SHA。
- 不直接更新 handoff、command、execution 表来改变状态。优先走已部署版本的内部治理 API;只有 API 无法恢复且 已获得对应操作授权时,才可调用该版本现有 domain repository,并保留 lifecycle event 与 audit log。
只读证据盘点
对 manifest 中每条 item 核对并保存摘要:
- command ID、session/project/computer ID、command status、execution state;
- manifest 记录的 authority term、transport generation、execution generation,以及当前实际值;
- command/execution lease 是否过期,outbox 是否仍有 active/pending 记录;
- session 中是否还有其他活跃命令或新事件;
- daemon acknowledgement、result/receipt、审计事件是否能证明执行或未执行。
若 lease/outbox 仍活跃、存在新命令、证据相互矛盾,或无法排除外部副作用,停止恢复并请求新的人工判断。
Action 与 outcome 必须匹配证据
no_action / not_executed:只有权威证据能证明命令从未执行,且治理接口允许该组合时使用。terminate / terminated:用于显式受控终结仍处于 uncertain/active 语义的命令;先通过 domain 操作取消 command、 force-end execution、完成 session 并写审计,再完成 reconciliation,不产生 replay。mark_failed / failed:证据确认失败、且不能安全恢复为成功或未执行时使用。replay / replayed_success:仅在用户明确授权 replay 且 exactly-once/幂等边界得到证明时使用。发布解卡绝不能默认 replay。
不要为了迎合预先选择的 outcome 忽略现场证据;如果授权与可证明事实不兼容,停止并把差异报告给用户。
受治理恢复顺序
- 使用精确 manifest/item 建立或读取 reconciliation case。
- 取得具备 action、evidence digest、operator 和有效期约束的审批。
- 记录 decision;执行 domain 终结或治理 apply;随后用权威运行态证据 confirm terminal outcome。
- 若 apply 返回
COMMAND_AUTHORITY_CHANGED,不要覆盖或绕过。重新读取当前三类 generation 和新活动:- generation 只因刚完成的受控终结而变化,且无新命令、lease/outbox 时,可在同一授权 action 下幂等续办;
- generation 对应新工作或原因不明时,停止并重新审批。
- 每个 item 都 terminal 后,确认 manifest 自动或受治理地进入
reconciled,再启动新的发布尝试。
凭据失败发生在事务前时应视为零变更并记录。不要反复猜测 owner 凭据;不得打印连接串或密钥。若必须使用运行时
slark_app 连接,只能通过已部署 domain repository、正确的 per-transaction project/user RLS context 和审计路径操作。
零重放与发布恢复验收
恢复完成至少证明:
terminalCount == totalCount,每条 decision action 与 terminal outcome 等于用户授权;- 禁止 replay 的场景下,decision action=
replay数和 execution replay attempt 增量均为 0; terminate/terminated场景下,command=cancelled、execution=force_ended,并存在对应 lifecycle/audit 证据;- 旧 manifest=
reconciled,没有 active handoff reservation 残留。
继续生产发布时使用新 governed release / handoff manifest,不复用 failed-closed manifest。重新检查候选仍是最新
origin/main、同 SHA staging eligibility receipt 仍有效、工作树干净;任何一项变化都回到 staging 与人工确认门禁。
发布成功后再独立执行一次 scripts/verify-deploy.sh,并只读核对:release=succeeded/complete、target/actual Web、
Server、daemon、artifact SHA 全相等、lease 已释放、finished 已记录、新 manifest=verified、舰队在线数不低于基线。
将旧 manifest reconciliation 与新发布证据一起回写 ai-proj。
--no-mirror 的解释边界
pnpm release:prod默认走deploy.sh --backend --no-install --no-mirror;不上传 daemon 镜像资产。- 发布过程仍可能在隔离 candidate 目录构建 daemon binary,用于同 SHA 验证或部署运行态 daemon;这不是镜像上传。
- mirror freshness 告警表示镜像源仍旧,国内安装器可能回退到较慢 upstream。它不阻断当前生产运行态发布。
- 补传 mirror 是单独的外部写操作,需要单独授权和凭据;不能为了消除告警在发布收尾时顺手执行。