Skip to content

feat(runtime-host): add managed update reconciliation - #3720

Draft
M4n5ter wants to merge 9 commits into
apache:mainfrom
M4n5ter:feat/runtime-host-update-reconciliation
Draft

feat(runtime-host): add managed update reconciliation#3720
M4n5ter wants to merge 9 commits into
apache:mainfrom
M4n5ter:feat/runtime-host-update-reconciliation

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 24, 2026

Copy link
Copy Markdown
Member
English

Summary

  • persist one installation-scoped manual | fixed | latest | next managed update policy, with state-free manual as the default
  • resolve the policy to one exact version and verified package identity before delegating to the existing update transaction
  • expose a bounded reconcile-update machine contract for current, changed, active-work, manual-action, and retry outcomes
  • serialize policy changes and uninstall through the existing deployment authority; reconciliation consumes one atomic policy snapshot without adding a scheduler or updater daemon

The 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 build
  • npm run typecheck
  • npm run lint
  • npm run format:check
  • npm run check:asf-headers
  • npm --workspace maka-agent test — 448 passed
  • exercised the compiled CLI with a fresh Client Data Root and confirmed that policy defaults to manual and reconciliation returns disabled

Dependency

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

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

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
简体中文

摘要

  • 持久化 installation-scoped 的互斥策略 manual | fixed | latest | next,默认 manual 且不保存冗余状态
  • 在调用现有 update transaction 前,将策略解析为精确版本与已验证的 package identity
  • 提供有界的 reconcile-update 机器契约,区分 current、changed、active work、manual action 与 retry outcome
  • 由现有 deployment authority 序列化策略变更与 uninstall;reconciliation 只消费一份原子 policy snapshot,不引入 scheduler 或 updater daemon

目标已是当前 deployment 时直接复用它,避免 no-op reconciliation 重复下载 package。

修复 #3717

关联 #3228
关联 #3709

验证

  • npm run build
  • npm run typecheck
  • npm run lint
  • npm run format:check
  • npm run check:asf-headers
  • npm --workspace maka-agent test — 448 项通过
  • 使用全新 Client Data Root 运行编译后的 CLI,确认策略默认是 manual,reconciliation 返回 disabled

依赖

AI 使用

OpenAI Codex 在维护者指导下实现并测试了本次变更;Draft 转为 Ready 前仍需要人工审查。

Checklist

  • 测试覆盖新增行为,并能在缺少实现时失败
  • lint、format、typecheck 与受影响测试均已在本地通过
  • 本 PR 会改变行为,具体见上方摘要

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 me2seeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 已经闭合。

Comment thread packages/cli/src/runtime-host-update-policy-store.ts Outdated
Comment thread packages/runtime-host/src/operator/service-management-frame.ts Outdated
@M4n5ter
M4n5ter force-pushed the feat/runtime-host-update-reconciliation branch from 4d8efd8 to c819f54 Compare August 24, 2026 14:38
@M4n5ter

M4n5ter commented Aug 24, 2026

Copy link
Copy Markdown
Member Author

@me2seeks

English

Thanks 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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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:

  1. reconcile reads latest and starts registry resolution;
  2. the user changes the policy to manual (or fixed B) under the deployment lock;
  3. 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 可能推翻用户更新后的决定:

  1. reconcile 读到 latest,开始 registry 解析;
  2. 用户在 deployment lock 下把 policy 改为 manual(或 fixed B);
  3. 旧 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(runtime-host): add managed update reconciliation policy

2 participants