feat(runtime-host): add managed update reconciliation - #3720
Conversation
Download the exact npm package selected by update discovery, verify its registry integrity and packaged compatibility evidence, then hand it to the existing managed Host update transaction. Fence stale candidates so concurrent updates cannot overwrite a newer deployment. Generated-by: Codex
Bind registry artifacts to their verified integrity across deployment and route current selections through the existing readiness and repair transaction. Scope temporary acquisition to the update operation and prune inactive managed packages only after a healthy cutover. Generated-by: Codex
Fence selected updates by the current and target deployment paths so verified same-version packages cannot be skipped or admitted from stale compatibility evidence. Avoid deployment-lock reentry during forced recovery, and atomically detach package directories before cleanup so exact retries remain recoverable. Generated-by: Codex
Treat exact package identity, not semver alone, as current so same-version registry artifacts still pass compatibility admission. Keep repeated setup on the active package while idempotently restoring its operator launcher, preserving exact recovery after interrupted setup or cutover. Generated-by: Codex
Route both staged and existing packages through one deployment lifecycle so operator repair, cleanup, rollback, and exact-target recovery share the same authority. Keep npm acquisition state inside the update workspace while preserving the separate offline extraction cache.
Let each update invocation observe the managed installation and reconcile its current desired deployment instead of exposing a version-only recovery authority that cannot identify an exact package. Generated-by: Codex
me2seeks
left a comment
There was a problem hiding this comment.
Reviewed the 4d8efd8 reconciliation layer on top of #3687. The core shape is clean: state-free manual, one policy snapshot under a reconciliation lock, delegation to the verified selected-update transaction, and no second scheduler/updater state machine. I found two recovery-contract gaps in the inline comments below.
One scope/wording boundary: the persisted record is currently bound to clientDataRoot plus {serviceId, rootPath, rootId}. That is a useful exact managed-service target fence, but it is not yet the positive durable local-owner identity and transfer protocol tracked by #3709. This PR does not need to solve #3709; describing the current result as managed-service-target-bound or installation-scoped would avoid implying that the local owner gate is already closed.
简体中文
我按 #3687 之上的增量审查了 4d8efd8。整体形状很干净:manual 不保存冗余状态、reconciliation lock 内只读取一次 policy snapshot、复用已验证的 selected-update transaction,并且没有创建第二套 scheduler/updater 状态机。下面两条行内评论是仍需闭合的恢复契约问题。
另有一个范围与术语边界:当前持久记录实际绑定的是 clientDataRoot 与 {serviceId, rootPath, rootId}。这能为 managed service 提供精确 target fence,但还不是 #3709 所跟踪的 durable local owner 正向身份与 transfer protocol。本 PR 不需要顺手解决 #3709;将当前能力表述为 managed-service target binding 或 installation-scoped,可以避免让人误以为 local owner gate 已经闭合。
4d8efd8 to
c819f54
Compare
EnglishThanks for the scope distinction. I changed the PR wording from owner-bound to installation-scoped; this PR does not claim the durable local-owner identity or transfer protocol tracked by #3709. I did not retain the separate reconciliation lock after tracing its actual authority. It covered policy resolution and network work without making the full operation atomic, while duplicating the deployment transaction's concurrency boundary. Policy mutations and uninstall now use the existing deployment lock; reconciliation reads one atomic policy snapshot and delegates the exact {version, integrity} deployment to the existing transaction. This keeps one mutation authority without introducing a third lock domain. The same pass also fixed two independent contract gaps: JSON reconciliation now emits exactly one terminal JSON document, and uninstall revokes automatic policy before destructive lifecycle work. 简体中文感谢指出范围差异。我已将 PR 中的 owner-bound 改为 installation-scoped;本 PR 不宣称已经实现 #3709 跟踪的 durable local-owner identity 或 transfer protocol。 在追踪实际 authority 后,我没有保留独立的 reconciliation lock。它覆盖了 policy 解析与网络工作,却不能让完整操作具备原子性,同时又重复了 deployment transaction 的并发边界。现在 policy mutation 与 uninstall 复用现有 deployment lock;reconciliation 读取一份原子 policy snapshot,再把精确的 {version, integrity} deployment 交给现有 transaction。这样只保留一个 mutation authority,不新增第三个锁域。 同一轮还修复了两个独立契约缺口:JSON reconciliation 现在只输出一个 terminal JSON document;uninstall 会在破坏性 lifecycle 操作前撤销自动更新 policy。 |
| ): Promise<number> { | ||
| const deps = reconciliationDeps(overrides); | ||
| try { | ||
| const record = await deps.readPolicy(options.clientDataRoot); |
There was a problem hiding this comment.
[P1] Revalidate the policy snapshot before applying it
This snapshot is now read outside the deployment lock, while policy mutation is serialized only by that lock. That permits a stale reconcile to defeat a newer user decision:
- reconcile reads
latestand starts registry resolution; - the user changes the policy to
manual(orfixed B) under the deployment lock; - the old reconcile finishes resolution, acquires the deployment lock inside
applySelection, and still retires/cuts over to target A.
The terminal state is then policy manual/B with deployment A. In this PR there is no scheduler to correct it, and the manual case is specifically a revoked unattended-update authority that the stale operation still exercises.
I agree that a third reconciliation lock is unnecessary. The smaller authority-preserving fix is optimistic validation: once the existing deployment transaction acquires its lock and before retirement/cutover, re-read the policy and require it to equal the snapshot used for selection; if it changed, return a typed policy_changed/retry outcome (or restart selection). A focused race test should cover at least latest → manual.
简体中文
这里的 policy snapshot 已移到 deployment lock 外读取,而 policy mutation 只由这把 deployment lock 序列化,因此旧 reconcile 可能推翻用户更新后的决定:
- reconcile 读到
latest,开始 registry 解析; - 用户在 deployment lock 下把 policy 改为
manual(或fixed B); - 旧 reconcile 完成解析,在
applySelection内取得 deployment lock,仍然按旧 target A 执行 retirement/cutover。
最终会形成“持久 policy 是 manual/B,实际 deployment 是 A”。当前 PR 还没有 scheduler 自动纠正;尤其 manual 表示用户已撤销 unattended-update authority,但旧操作仍会继续使用该权限。
我同意不需要第三个 reconciliation lock。更小且保留 authority 的修复是 optimistic validation:现有 deployment transaction 取得锁后、retirement/cutover 前,重新读取 policy,并要求它与用于 selection 的 snapshot 相同;若已变化,返回类型化的 policy_changed/retry outcome(或重新 selection)。聚焦竞态测试至少应覆盖 latest → manual。
Distinguish a service-manager replacement that never committed from a target that committed but did not become ready. Restore the previous backend definition and config only in the former case; retain and stop the selected deployment when readiness leaves storage compatibility unknown. Generated-by: Codex
Persist one owner-bound update policy and resolve it to an exact, verified deployment before delegating to the existing update transaction. Keep manual mode state-free, serialize policy changes with reconciliation and uninstall, and expose bounded machine outcomes for future schedulers and clients. Generated-by: Codex
Make policy removal crash-durable and revoke unattended update authority before destructive uninstall work begins. Reuse the deployment lock for policy mutations and route update frames through one sink so JSON reconciliation emits one terminal document. Generated-by: Codex
f6b0edd to
962453a
Compare
English
Summary
manual | fixed | latest | nextmanaged update policy, with state-freemanualas the defaultreconcile-updatemachine contract for current, changed, active-work, manual-action, and retry outcomesThe current deployment is reused when it is already selected, avoiding an unnecessary package download on no-op reconciliation.
Fixes #3717
Refs #3228
Refs #3709
Verification
npm run buildnpm run typechecknpm run lintnpm run format:checknpm run check:asf-headersnpm --workspace maka-agent test— 448 passedmanualand reconciliation returnsdisabledDependency
AI use
Select exactly one:
Tool(s) and scope: OpenAI Codex implemented and tested the change under maintainer direction. Human review is still required before this Draft becomes ready.
Checklist
Does this PR entail a change in behavior?
简体中文
摘要
manual | fixed | latest | next,默认manual且不保存冗余状态reconcile-update机器契约,区分 current、changed、active work、manual action 与 retry outcome目标已是当前 deployment 时直接复用它,避免 no-op reconciliation 重复下载 package。
修复 #3717
关联 #3228
关联 #3709
验证
npm run buildnpm run typechecknpm run lintnpm run format:checknpm run check:asf-headersnpm --workspace maka-agent test— 448 项通过manual,reconciliation 返回disabled依赖
AI 使用
OpenAI Codex 在维护者指导下实现并测试了本次变更;Draft 转为 Ready 前仍需要人工审查。
Checklist