**未认领,待核实定性。** #4311 runtime 片(PR #5045)实施中的观察,修复需改运行时行为、超出该片边界,按 PD#10 立案。 ## 观察(来自 `packages/runtime/src/domains/packages.ts` 的实读) - `install` / `updatePackageManifest`:优先走 protocol service 持久化到 `sys_packages`,服务缺席时才回落 in-memory; - `enable` / `disable` / `get` / `uninstall`:**直接读写 in-memory registry**,不经持久化路径。 若属实,后果是:enable/disable/uninstall 的状态变更**重启即失** —— 管理员禁用一个包,进程重启后它复活。这与 install 路径的语义不一致,像是持久化通道接了一半。 ## 待核实 1. enable/disable 状态是否确实只活在内存(有没有别的落库路径,例如 boot 时从 sys_packages 重放); 2. 若 boot 重放存在,那么不对称只是"写路径分裂"而非数据丢失 —— 定性从 bug 降为一致性债; 3. `sys_packages` 的行里有没有 enabled 字段可承接。 核实第 1 条成立即标 `bug` 入队(维护者当前规则:只派 bug)。 ## 关联 - PR #5045(发现现场)、#4404(EngineSchemaRegistryView 契约,同文件同批被修的六个成员声明)
Activity
xuyushun441-sys commentedon Aug 4, 2026
核实完成 —— 原前提不成立,但挖出一个更窄的真 bug;本单改定性并收窄派发
只读核实(全部证据带 file:line,以 origin/main 为准)推翻了正文的"enable/disable 只写内存":
持久化存在,且是刻意设计:
packages/runtime/src/package-state-store.ts:70-77把 disabled 集合写进<OS_HOME>/package-state/<environmentId>.json,文件头 rationale 明写"intentionally a flat file rather than a sys_* object: package lifecycle state is runtime/operational state, not project metadata"。boot 回灌路径也存在且时序自洽:app-plugin.ts:226-248在 init(Phase 1)seed disabled 集合 →service-package/index.ts:200-253在 start(Phase 2)从sys_packages重放时,registry.installPackage消费它(registry.ts:1602-1608)把包装成 disabled。原文那种"直写内存、重启即失"的定性不成立,不按原文修。真 bug(本单收窄为它):empty-env 早退跳过 disabled seed
app-plugin.ts:196-201—— bundle 无 app 载荷时init提前 return,而 disabled seed 块(:226-248)在早退之后。empty env 恰恰是"包只来自 sys_packages / HTTP 安装"的场景(hydration 自己的注释就是这么写的)。后果:纯 DB 驱动的环境里,管理员禁用的包每次重启都复活。修法低风险:把 seed 块提到早退之前 —— 同一函数里
installDefaultHookBodyRunner/wireAuthoredTranslationSync已因同样理由被提前(:177-195 有注释先例)。测试盲区是它没被发现的原因:全仓零测试覆盖package-state-store/setInitialDisabledPackageIds,修复必须补上(含 empty-env 场景的回归测试)。记录为债、本单不修
package-state-store.tsrationale 的 ADR 级取舍,要改先改 ADR;DELETE /packages/:id双写清理sys_packages(protocol.ts:8429-8440,"so the package cannot resurrect at boot")但不清理 disabled 条目 → 同 id 重装会静默以 disabled 回来;sys_packages无 lifecycle 列(raw-SQL 表,无 spec 定义),统一到 DB 需 schema 变更。认领(PM 分派,收窄后)
session_018iARDqtrhQgz6fVHDeDkbQclaude/issue-5047-empty-env-disabled-seedpackages/runtime/src/app-plugin.ts+ 新测试)Generated by Claude Code
xuyushun441-sys commentedon Aug 4, 2026
审核通过 — PR #5117 已取消草稿并挂上 auto-merge(SQUASH)
修复是最小行序调整,验证是全真件的。 seed 提到 empty-env 早退之前,抽成带文档注释的私有方法,注释对齐同函数两个先例。要害在测试的成色:
PackageServicePlugin.start()重放 sys_packages,为此按 service-job 先例加了 devDependency + vitest alias,宁可引真件也不重实现被测对象 —— 重实现的 hydration 验证不了任何事。enabled: true / status: installed对false / disabled),非 empty 用例保持绿,store 单测独立于行序 —— 红的形状证明测试测的就是这个 bug,不是别的。package-state-store从零覆盖到 12 例,含环境 id 路径消毒(../../etc/evil逃不出目录)与坏 JSON 降级为空集 —— 核实报告点名的"为什么没被发现"被正面回答。getService('objectql')触点在无引擎 kernel 下仍能 boot(case 7 钉住)—— 行序调整没有引入新的启动依赖。runtime 全量 1150 测试绿(含 #5045 刚接的 typecheck),六道 check 门禁绿。lockfile 仅 devDependency 3 行,OSV 修复已在 main,无红。
三条一致性债照核实结论留档不扩面。dev 另纠了资源纪律文档里的一处错误:
--concurrency应为--workspace-concurrency且置于--filter前 —— 这个坑本会话已有四个 agent 踩过,值得进 skill 修订素材。Generated by Claude Code
fix(runtime): seed persisted disabled packages before the empty-env e…
spec/kernel: carve the package-registry persistence out of `marketpla…