fix(seed-summary): count the marketplace rehydrate heal in the boot banner, and make the counter accumulate#3452
fix(seed-summary): count the marketplace rehydrate heal in the boot banner, and make the counter accumulate#3452os-zhuang wants to merge 1 commit into
Conversation
…anner, and make the counter accumulate The boot-banner Seeds line (#3435) was fed by a `seed-summary` kernel counter only AppPlugin's config-app seed wrote to. The marketplace rehydrate heal (#3421) seeds an installed package's sample data in the same boot-quiet window but wrote nothing — so a marketplace package's healed rows, and critically its empty "installed but 0 rows" state, were absent from the banner. Two latent bugs blocked simply folding it in: 1. The counter read its prior total via `(ctx as any).kernel?.getService`, but the PluginContext has no `.kernel` handle — the read was always undefined, so every write was a blind overwrite, never an accumulation. 2. registerService throws on a duplicate name, so the second writer's registration threw and was silently dropped. Fix: a shared accumulateSeedSummary(ctx, delta) in @objectstack/types registers one mutable counter object and mutates it in place — race- and cache-safe regardless of seed-source order. AppPlugin and the marketplace heal both use it. The heal reports healed rows and forces a non-zero rejected on a zero-row heal so "installed but 0 rows" escalates to the banner warning. Verified on showcase: fresh boot reads "292 inserted · 6 updated" (130 config + 162 HotCRM heal) instead of "130 · 6". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📓 Docs Drift CheckThis PR changes 3 package(s): 17 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
|
Superseded by #3444, which merged while this PR's CI was running. #3444 implements the same marketplace-heal boot-summary observability with a richer per-source model ( Note: the sibling defect this PR's investigation surfaced — the SAME dead- |
背景
#3435 刚合并,给启动 banner 加了
Seeds:行(由 kernel 的seed-summary计数器驱动),并修了 showcase 项目种子的 FSM 出生态问题。但那个计数器只有 AppPlugin 的 config app 种子会写。marketplace 的 rehydrate heal(#3421,在同一个 boot-quiet 窗口把已装包的样例数据补进空库)什么都不写 —— 于是 marketplace 包 heal 出来的行、以及最关键的「装了但 0 行」空状态,在 banner 上完全不可见(而这正是这条 Seeds 行存在的意义)。showcase 实测:banner 读130 inserted · 6 updated,而 HotCRM 在旁边静默 heal 了 162 行,一个数都没进 banner。两个把「直接 fold-in」卡住的潜伏 bug
排查中发现 #3435 的计数器本身就不工作,只是单 config app 场景掩盖了:
(ctx as any).kernel?.getService('seed-summary')读旧值,但插件PluginContext(packages/core/src/kernel.ts:76)根本没有.kernel句柄 —— 只有getService/registerService。所以每次读都是 undefined,每次写都是盲覆盖,从不累加。registerService(name, …)(kernel.ts:195)遇到重名直接throw 'already registered'。第二个写入方的注册抛出被 try/catch 吞掉。两者叠加,fix(showcase): seed all five projects through the FSM + surface seed outcomes in the boot banner (#3415) #3435 注释里的 "accumulates across apps" 从来没成立过 —— 谁最后写谁赢。showcase 的 130 行多阶段 FSM 种子超过 8s budget 后台晚写,正好把 marketplace 的值覆回130·6。修复
@objectstack/types新增共享的accumulateSeedSummary(ctx, delta):注册一个可变计数对象一次,之后所有写入方就地 mutate 它 —— 与种子来源顺序无关、且不受 kernelgetService缓存影响,race/cache 双安全(第一个注册者赢,后来者 catch 掉 already-registered 并取回同一个对象继续 mutate)。AppPlugin 与 marketplace heal 都改用它。heal 把补进的行记为 inserted/updated;heal 落 0 行时强制 rejected≥1,让「装了但 0 行」升级成 banner 的黄色告警。验证
showcase fresh boot 现在 banner 读
292 inserted · 6 updated(130 config + 162 HotCRM heal),不再是130 · 6;crm_opportunity=61、crm_contact=5 实测在库。新增单测:@objectstack/typesaccumulateSeedSummary 6 例(含「第二写入方必须累加不被 already-registered 吞掉」「已被读取方持有的对象引用能看到后续写入」),marketplace heal 6 例(healed 计入 / 空 heal 升 rejected / loader 错误数透传 / present·purged 不动计数器 / 叠加在 config 之上)。types 32、cloud-connection 69、runtime 587 全绿。与 #3435 的关系
只在 #3435 之上做加法:复用它的
seed-summary服务与 banner 渲染(printSeedSummary未改动),补齐它没覆盖的 marketplace 路径,并修好它那个单 config app 场景没暴露的累加 bug。备注
发现但不在本 PR 范围:
(ctx as any).kernel的死用法在仓库里还有两处(app-plugin.ts:752与marketplace-install-local-plugin.ts:887的seed-datasets注册)—— 它们的写靠?? ctx.registerService兜底能工作,但读 prev 同样恒 undefined。多租户 per-org replay 依赖 seed-datasets,值得单独 audit(已在我的多租户时序 audit 待办里)。🤖 Generated with Claude Code