Skip to content

publish-drafts 可见性翻转中途失败时,已翻转的 app 从响应里整批消失 —— unhiddenApps 丢了,metadata:reloaded 也漏播 #5242

Closed

Description

@os-zhuang

发现于 #4754 的实现期(修 packages/runtime/src/domains/packages.ts 那处静默 catch 时读到)。未认领 —— 只是记录。观察类:操作幂等,重跑一次就好。

现象

POST /packages/:id/publish-drafts 的 ADR-0045 可见性翻转段(packages/runtime/src/domains/packages.ts),结构是:

const unhidden: string[] = [];
for (const app of apps) {
    if (app?.hidden === true && typeof app.name === 'string') {
        await protocol.saveMetaItem({ /* … hidden: false … */ });
        unhidden.push(app.name);
    }
}
if (unhidden.length > 0) result.unhiddenApps = unhidden;   // ← 只在循环全程无异常时才执行

unhiddenApps 的赋值在循环之后、try 之内。所以 5 个 app 里第 3 个 saveMetaItem 抛异常时:前 2 个确实已经翻转并落盘了,但 unhidden 数组随栈丢弃,result.unhiddenApps 压根不存在。

后果(两层,都不大)

  1. 响应少报了真实发生的事。 调用方看到的是「翻转失败」,看不到「其中 2 个已经成功」。属于 AGENTS.md「Route & surface ownership」第 4 条(machine-readable surfaces must not lie)的轻量版 —— 不是撒谎,是漏报。
  2. metadata:reloaded 对这 2 个 app 漏播。 紧跟其后的重绑定段读的正是这个字段:
...(((result as any)?.unhiddenApps ?? []) as string[]).map((n) => `app/${n}`)

字段缺失 → 这 2 个已经变可见的 app 不进 changed → boot-cached 的消费者(首当其冲是 automation engine)不重新同步它们,得等下一次重启。

为什么不塞进 #4754

#4754 的范围是「saveMetaItem 进词表 + 逐处判持久性丢失」,那处 catch 已按范本改成 error 并写清后果与修复动作。本条是同一段代码里的另一个缺陷(部分进度的报告丢失),和日志级别无关,改它要动 unhidden 的作用域和响应语义 —— 与该单的清账互不依赖,单独立卡。

建议做法

把 unhidden 提到 try 之外,并在 catch 里一并回填:成功多少就报多少。重跑本身是幂等的(已翻转的 app hidden !== true,循环会跳过),所以这纯粹是让报告与事实一致,不改变恢复路径。

关联

#4754(同一段 catch 的日志级别清账)、ADR-0045(publish 让包 live 且可见)、AGENTS.md「Route & surface ownership」第 4 条。

Activity

  1. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    发现分诊轮判级(session_01VkPSGsX9o17MsGv3Lbxu2w,2026-08-05):晋级 pm:queue,同时挂 pm:blocked。

    Blocked-by: #5155

    两点说明:

    1. 域标由 domain:engine 改 domain:cli:按锚定规则(修复落点的包),本单落点 packages/runtime/src/domains/packages.ts,packages/runtime 属 cli 域 —— 原 engine 标签是按主题猜的,cli 车道 PM 据实纠正。
    2. 暂缓派发:在飞 HttpDispatcher 把「本请求解析出的 kernel」存在实例字段上(this.kernel),多租户 host 上并发请求会互相串改 #5155(claude/issue-5155-dispatcher-request-kernel)的声明文件面含 packages/runtime/src/domains/** 全量(DomainHandlerDeps 重接线),与本单同文件。HttpDispatcher 把「本请求解析出的 kernel」存在实例字段上(this.kernel),多租户 host 上并发请求会互相串改 #5155 落地后解锁,届时先核对 packages.ts 的 unhiddenApps 段是否被重接线移动过再派。

    前提核验见 #4604 01:57Z(对 b4ad98435 成立:赋值在循环之后)。晋级理由:翻转中途失败时已落盘的 app 从响应整批消失,metadata:reloaded 连带漏播 —— 用户可达的静默丢数据。维护者可否决。


    Generated by Claude Code

  2. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    解锁(cli 车道 PM,session_01VkPSGsX9o17MsGv3Lbxu2w,2026-08-05):Blocked-by #5155 已随 PR #5385 合并(main fd8521f92)达成,摘 pm:blocked 回队列。前提已按解锁条款对新 main 重核:unhiddenApps 赋值仍在 packages/runtime/src/domains/packages.ts:230、仍在循环之后,重接线未移动该段 —— 前提完好,可正常派发。派发时注意:该文件刚被 #5385 重签名(域处理器改收 context 首参),dev 以 origin/main 现状为准。


    Generated by Claude Code

  3. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    🔒 认领:PM 循环第 2 轮(cli 车道)
    会话:session_01VkPSGsX9o17MsGv3Lbxu2w
    分支:claude/issue-5242-packages-unhidden-apps
    Worktree:objectstack-issue-5242
    域:domain:cli
    文件面:packages/runtime/src/domains/packages.ts + 测试 + changeset。与同批 #5341 / #5382(均在 packages/cli)不相交;#5385 已合并,本文件无在飞触碰。

    同日 churn(高):本文件今日刚被 #5385 重签名(域处理器改收 context 首参、kernel 从 context.kernel 取)—— issue 引用的行号与周边结构已变,前提本身已由 PM 对 fd8521f92 重核成立(packages.ts:230 赋值仍在循环之后)。基于合并后代码工作,新增改动遵循 #5385 确立的显式传参姿态。


    Generated by Claude Code

  4. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    ✅ 验收通过 —— PR #5392,转 ready 挂合并队列(队列等全绿收单)

    对实况复核(cli 车道 PM,session_01VkPSGsX9o17MsGv3Lbxu2w):

    CI 完成项绿,余项由 auto-merge 等待。跟到 MERGED。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions