Files
2026-08-26 06:33:14 +09:30

5.0 KiB
Raw Permalink Blame History

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 忽略现场证据;如果授权与可证明事实不兼容,停止并把差异报告给用户。

受治理恢复顺序

  1. 使用精确 manifest/item 建立或读取 reconciliation case。
  2. 取得具备 action、evidence digest、operator 和有效期约束的审批。
  3. 记录 decision;执行 domain 终结或治理 apply;随后用权威运行态证据 confirm terminal outcome。
  4. 若 apply 返回 COMMAND_AUTHORITY_CHANGED,不要覆盖或绕过。重新读取当前三类 generation 和新活动:
    • generation 只因刚完成的受控终结而变化,且无新命令、lease/outbox 时,可在同一授权 action 下幂等续办;
    • generation 对应新工作或原因不明时,停止并重新审批。
  5. 每个 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 是单独的外部写操作,需要单独授权和凭据;不能为了消除告警在发布收尾时顺手执行。