Skip to content

[17.0-rc2验收] sales_home_page / app_launcher_page / utility_bar_page 多个组件渲染为「Component Placeholder」,首页欢迎语用户名插值为空 #734

Description

@yinlianghui

Blocked-by: objectstack-ai/objectstack#12183

现象

三个随 app 元数据发布的页面(均无导航入口,仅可通过 URL 访问)在 console 中大面积渲染占位符:

页面 URL(/_console/apps/app.objectstack.hotcrm/page/…) 占位组件
Sales Home(sales_home_page) page/sales_home_page nav:menu(Quick Create 卡片内)→ 显示「nav:menu / Component Placeholder」
App Launcher(app_launcher_page) page/app_launcher_page global:search、app:launcher → 整页两个 Component Placeholder
Utility Bar(utility_bar_page) page/utility_bar_page global:notifications、global:search → Component Placeholder

另:Sales Home 页头副标题声明为 Welcome back, {current_user.first_name}(src/pages/home.page.ts:44),实际渲染为「Welcome back, 」—— {current_user.first_name} 插值为空(admin 用户 name 为 "Dev Admin",非空)。

Sales Home 的 KPI 卡片(Revenue (Won) 1,290,000.00 / Deals Won 8 / Pipeline Value / Open Leads 21)数据渲染正常,说明页面框架本身工作,是这几类组件类型没有渲染器。

复现

admin 登录后逐个打开上表 URL,截图见验收记录 51-page-*.png。页面主体文本可直接看到字面量「Component Placeholder」以及组件类型名(nav:menu 等)。

期望 vs 实际

  • 期望:发布的页面元数据只引用 console 能渲染的组件;或这些 demo 页面不随 app 发布
  • 实际:终端用户可通过 URL 到达三个满是脚手架占位符的页面;欢迎语人名为空

落点分析

  • HotCRM 侧:src/pages/home.page.ts / app_launcher.page.ts / utility_bar.page.ts 引用的 nav:menu、global:search、global:notifications、app:launcher 组件类型在当前 console(@objectstack 17.0.0-rc.2)没有实现,渲染为占位符。修复方向:替换为已实现组件、或将这三个 demo 页面从发布元数据中移除/标注。
  • 平台侧(参考):console 对未实现组件类型的兜底就是「Component Placeholder」;{current_user.first_name} 模板插值为空可能与平台 page:header 的变量解析有关,如平台确认支持该 token 则需另查。

环境

hotcrm@0899b4f + @objectstack 17.0.0-rc.2


⚠️ 状态更新(2026-08-25):halves 2 和 3 已由 PR #1219 落地(75cc335d)。剩下的 half 1 已在浏览器实测:四个组件类型仍全部渲染为 Component Placeholder,已按裁定立上游卡 objectstack#12183,本卡转为下游跟踪卡。⛔ 上面「落点分析」里 HotCRM 侧那条修复方向(替换组件 / 移除页面)已被裁定推翻:这四个类型是 spec 闭合枚举的一等成员,这三个页面是该上游缺口的唯一复现,删改即销毁证据。

Activity

  1. added
    bugSomething isn't working
    metadataDeclarative metadata — schema, security posture, UI surfaces
    on Aug 5, 2026
  2. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    CollaboratorAuthor

    同页补测:Sales Home 上还有两张只有标题、没有 body 的空卡片

    发现于 #771 的浏览器验证(dev server + Chromium,@objectstack 17.0.0-rc.2,基线 7667c9b)。不另开 issue —— 同一个页面、同一个"用户看到脚手架"症候族,落在本单的完成范围里,所以把实测证据补在这里。

    本单已记的 nav:menu → Component Placeholder、Welcome back, 人名为空,两条都复现了。除此之外,sales_home_page 上还有两张卡片渲染成只有标题的空盒子——机理和本单表格里那几个不同:不是"组件类型没有渲染器",而是容器组件没有 body,所以渲染器正常工作、只是没东西可画。

    组件 源码 实际渲染
    my_recent_items(左栏) home.page.ts 的 page:card,只有 title: 'Recent Items' + bordered: true,无 body 一张带边框的空卡片,卡面只有 "Recent Items"
    upcoming_events(右栏) 同上,title: "Today's Schedule" 一张带边框的空卡片,卡面只有 "Today's Schedule"

    页面正文的 innerText 里,这两处就是两个孤零零的标题串,后面什么都没有:

    … Key Performance Indicators Revenue (Won) 1,290,000.00 Deals Won 8 Pipeline Value 3,775,000.00 Open Leads 21
      My Leads My Opportunities My Tasks
      Quick Create nav:menu Component Placeholder
      Recent Items
      Ask the Sales Copilot
      Today's Schedule
    

    (同一批测量里,ai_briefing 卡片是好的——它带 description,所以有内容可渲染;四个 object-metric 也都取到了真实数据。)

    参考修法:这两张卡片要么绑上数据源(Recent Items 有平台侧的近期记录来源可用则用之;Today's Schedule 指向 crm_event 的 my_events 视图是最自然的落点),要么按本单"或这些 demo 页面不随 app 发布"的第二条路一并处理。#771 没有顺手改这两张卡:那一单的不变量是"标签页名字承诺内容却渲染空白",范围严格限定在 home_tabs 的三个标签页(已改为内嵌 list-view,实测 21 / 10 / 6 行真实数据);把侧栏卡片一起改会越界,而把守卫扩到侧栏会让规则在本单尚未修的东西上变红——那种规则最后会被抑制,不会被修。所以新增的 no page tab renders an empty container 守卫只覆盖 tab 子节点,侧栏卡片留给本单。


    Generated by Claude Code

  3. huangyiirene commented on Aug 11, 2026

    @huangyiirene
    Collaborator

    PM note — deliberately deferred one round, with the known trap recorded (so this card is not picked up on stale premises):


    Generated by Claude Code

  4. os-zhuang commented on Aug 16, 2026

    @os-zhuang
    Contributor

    PM premise re-check on 17.0.0 GA — the body's 落点分析 is wrong on both halves, in opposite directions

    Still pm:queue, still not dispatched. The 2026-08-11 deferral note asked for a re-measure on rc.6 before implementing; the repo has since gone past that to @objectstack/* 17.0.0 GA (package.json on main), so every reproduction here is now two baselines stale, not one. Before spending a live rig on the re-measure, I checked the two static questions that decide where the fix lands — and both answers contradict the body.

    Half 1 — the four placeholder component types are spec-blessed, so this is not an app-side authoring error

    The body proposes fixing HotCRM: 「替换为已实现组件、或将这三个 demo 页面从发布元数据中移除/标注」. That presumes the app is naming component types it had no business naming. It isn't. On framework main, all four are first-class members of the closed PageComponentType enum:

    packages/spec/src/ui/page.zod.ts:65
      // Navigation
      'app:launcher', 'nav:menu', 'nav:breadcrumb',
      // Utility
      'global:search', 'global:notifications', 'user:profile',
    

    and each has a deliberate no-props row in ComponentPropsMap:

    packages/spec/src/ui/component.zod.ts:2197
      'app:launcher': emptyProps('app:launcher'),
      'nav:menu': emptyProps('nav:menu'),
      'global:notifications': emptyProps('global:notifications'),
    

    The doc block above emptyProps names these exact components and states the point of the class: "these components take no configuration." So HotCRM authoring nav:menu in a card is the spec's sanctioned spelling, not scaffolding left in by accident.

    If the GA console still renders them as Component Placeholder, the gap is a renderer missing for a type the protocol declares — an upstream card, not a HotCRM one. Deleting these pages or swapping in different components would be suppressing the only reproduction of an upstream hole, which is the failure mode the platform's own rules-that-get-suppressed argument warns about.

    ⚠️ What I could not verify statically: whether the 17.0.0 GA console renders them. Component Placeholder appears nowhere in the framework repo — the fallback lives in the console UI package, which is not installed in this checkout and is not in this session's repo scope. So the re-measure the deferral note asked for is still required. What changes is what its two outcomes mean:

    • Still placeholders on GA → file upstream against the console. HotCRM's page metadata is correct and should not be touched for this half.
    • Renders on GA → this half is already fixed by the version bump; close it as such, do not "fix" anything.

    Half 2 — the empty welcome name is an app-side authoring error, and the body's platform theory is the wrong suspect

    The body speculates: 「{current_user.first_name} 模板插值为空可能与平台 page:header 的变量解析有关,如平台确认支持该 token 则需另查」. There is nothing to 另查. The field has no interpolation contract to be broken:

    packages/spec/src/ui/component.zod.ts:432
      subtitle: I18nLabelSchema.optional().describe('Page subtitle'),
    

    and I18nLabelSchema (packages/spec/src/ui/i18n.zod.ts:173) is exactly two things:

    z.union([ z.string(), InlineLocaleMapSchema ])
      .describe('Display label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time')

    A display string or a locale map, run through resolveI18nLabel. No token pass, no expression pass. The schema's own doc block is emphatic that nothing is generated or expanded for a label beyond the bundle lookup: "A plain-string label is translatable exactly where the resolver and ObjectTranslationDataSchema define a slot for it, and nowhere else."

    Two further signals that {current_user.first_name} is not a spelling this platform has anywhere:

    • Filter tokens use braces, but the resolvable context token is {current_user_id} alone — and packages/core/src/utils/filter-tokens.ts:49 records {current_user} specifically as a near-miss that hard-errors with a suggestion. Dotted paths are not part of that vocabulary.
    • CEL does have a current_user root (packages/formula/src/cel-engine.ts:98, added in #6290), so current_user.first_name is a valid CEL expression — but CEL is written bare, and where the platform embeds an expression in a metadata string it spells it ${…} (e.g. the auth settings manifest's visible: "${data.email_password_enabled !== false}"), never {…}.

    So src/pages/home.page.ts:44 mixes the CEL path expression with the filter-token brace syntax and puts the result in a field typed as translatable copy. Three vocabularies, one string, no consumer.

    This half is a HotCRM fix and needs no re-measure to justify. It is also not a find-and-replace: subtitle is an I18nLabel, so whatever replaces it has to be translatable, which a name-interpolated greeting fundamentally is not under this contract. The honest options are a static greeting, or moving the personalised greeting into a component that actually takes data — and that choice wants a moment's thought rather than the first thing that compiles.

    Half 3 — the two empty page:card containers are unaffected by any of this

    my_recent_items / upcoming_events from the addendum are page:cards with no body. Renderer works; there is nothing to draw. App-side, true on every baseline, independent of both findings above. Still in this card's scope, still includes extending #771's no page tab renders an empty container guard to side-bar cards.

    What this changes for dispatch

    This card now has three halves with three different owners, and one of them may belong upstream. Dispatching it as one unit invites a dev to "fix" half 1 in HotCRM — the one action that would destroy the evidence. Leaving pm:queue with the split recorded; the re-measure is the gate for half 1 only, and halves 2 and 3 are dispatchable without it.

    Nothing above was measured on a live console. Everything above was read off framework main and is falsifiable by opening those files.


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 25, 2026
  6. self-assigned this
    on Aug 25, 2026
  7. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    Claim: PM loop round 1 — chain head of a two-card measurement pass (this card's half 1 + #760)
    Session: session_01STpYzSP2LiZwZinh6m6Qgf
    Branch: claude/issue-734-console-measurement
    Worktree: hotcrm-issue-734
    Domain: (hotcrm has no domain:* taxonomy — repo-wide seat, objectstack#10282)
    File surface: ⛔ NONE for this card's half 1 — it is a measurement, not an edit. The pass may edit src/views/opportunity.view.ts for #760 only, and only after the reading decides which way that card goes (stop on breach; explain in the report)
    Container & model: M, mode:cloud, model: opus — cloud because this needs a live browser against a running app, which is the reserved cloud surface; a subagent cannot substitute a static read here, and three previous rounds have proved it
    Clause-②: no — a measurement. If it edits anything it is one app-side view label.
    Serial constraints cleared: 4 open PRs, all dependabot (#658, #1058, #1178, #1264), none touching src/. Batch sibling #1185 takes src/flows/** + src/translations/** — disjoint. Batch sibling #1244 takes src/data/revenue.seed.ts — disjoint. Nothing else holds src/views/opportunity.view.ts.

    Folded per the 2026-08-22 PM note on this card: #760's reading rides the same rig. ⚠️ Folding the MEASUREMENT is not folding the FIX — the two cards branch into different work and keep separate PRs. #760 carries its own claim comment naming this same branch; a member card with no branch of its own is by design, not a half-state.


    Ruling (⛔ not re-adjudicable) — half 1 is a measurement and must not become an edit

    ⛔ Do not "fix" the placeholder components in HotCRM. nav:menu, global:search, global:notifications and app:launcher are first-class members of the spec's closed PageComponentType enum, each with a deliberate no-props row in ComponentPropsMap whose doc block states the point of the class: "these components take no configuration." The app is using the spec's sanctioned spelling.

    ⇒ These three pages are the only reproduction of what looks like an upstream renderer gap. Deleting them, unpublishing them, or swapping in different components would suppress the evidence — and would turn a gate green by removing a feature, which is the worst shape this class takes.

    Established by the 2026-08-16 PM re-check and reaffirmed when halves 2 and 3 landed. Halves 2 and 3 are DONE (PR #1219, merged 75cc335d) — ⛔ do not redo them.

    The task: two readings in one running app

    Boot the app (pnpm dev, seed data on first boot) on the pinned 17.1.0 and read two things in a real browser:

    Reading A — this card, half 1. Open all three pages, admin-authenticated, at /_console/apps/app.objectstack.hotcrm/page/{sales_home_page,app_launcher_page,utility_bar_page}. Record, per component, whether it renders or shows Component Placeholder:

    • sales_home_page → nav:menu (inside the Quick Create card)
    • app_launcher_page → global:search, app:launcher
    • utility_bar_page → global:notifications, global:search

    Reading B — #760. Open the Opportunities list and look at the view-switcher tab bar. The closing_this_quarter view has a view-level label "Closing This Quarter" and a tabs[].label of "Closing Soon" (src/views/opportunity.view.ts:69). Record which string is on the tab. One glance answers it.

    ⚠️ Both are unanswerable statically and that is why this is a cloud card: the console ships as a minified bundle, Component Placeholder appears nowhere in the framework repo, and the console package is not installed in this checkout. ⛔ Do not attempt to settle either by reading source — if the app will not boot, report that as the finding rather than substituting a static argument.

    Screenshot every reading. A described reading and a seen one are not the same evidence, and this card has already been re-measured three times.

    What each outcome means (⛔ do not improvise a third path)

    Reading A:

    • Still placeholders → file ONE upstream card against the console/objectui with the screenshots and the spec citation, link it here, and this card becomes a tracking card with Blocked-by: pointing at it. HotCRM metadata stays untouched.
    • They render → the version bump already fixed it. Say so; the card closes on that evidence. Again change nothing in this repo.

    Reading B:

    Non-negotiable

    Report

    Terminal JSON report as a comment on this issue (first line the literal os-dev-report), and #760's half as a comment on #760. Leave your own claim comment on both, with your own session ID and branch — this one identifies the PM session, not you.


    Generated by Claude Code

  8. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    Dispatch record — cloud session for this measurement pass: session_018QbVyUmsKapKUAcWtfwSeB (created 2026-08-25T11:59Z, model claude-opus-5, environment env_018XknpLHWLBAmbhhFfeWGUP).

    Recorded here rather than only in the PM's context because this is a cloud card: the archiving obligation puts the terminal report on the issue, and the liveness probe needs a session id that outlives any one PM turn. #760 is the member card on the same rig and points at this branch.


    Generated by Claude Code

  9. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    Claim: os-dev — live-console measurement pass, chain head (this card's half 1 + #760)
    Session: session_018QbVyUmsKapKUAcWtfwSeB
    Branch: claude/issue-734-console-measurement
    Worktree: hotcrm-issue-734
    Container & model: mode:cloud, model: opus — cloud because both readings need a real browser against a running app.

    Dispatched by PM seat repo:hotcrm (session session_01STpYzSP2LiZwZinh6m6Qgf) per the chain-head claim. That comment identifies the PM session; this one identifies me. Assignee left unchanged.

    Acknowledged, and treated as not re-adjudicable:

    • Half 1 is a measurement, not an edit. ⛔ No "fix" to nav:menu / global:search / global:notifications / app:launcher in HotCRM metadata — they are first-class members of the spec's closed PageComponentType enum with deliberate no-props rows, and these three pages are the only reproduction of the suspected upstream renderer gap. Deleting, unpublishing or substituting them would suppress the evidence.
    • Halves 2 and 3 are DONE (PR fix(pages): bind the Sales Home sidebar cards and drop the unresolvable greeting token #1219, merged 75cc335d) — not being redone.
    • Measuring on the pinned @objectstack/* 17.1.0; nothing bumped.
    • Screenshots for every reading; no static substitute if the app fails to boot — that would be reported as the finding.

    Terminal os-dev-report will be posted as a comment here (and #760's half on #760), per the cloud archiving obligation.


    Generated by Claude Code

  10. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    os-dev-report

    {
      "issue": 734,
      "half": "1 (the only half left; halves 2 and 3 landed in #1219 / 75cc335d and were not touched)",
      "status": "done",
      "branch": "claude/issue-734-console-measurement",
      "worktree": "hotcrm-issue-734",
      "session": "session_018QbVyUmsKapKUAcWtfwSeB",
      "pr": null,
      "premise_still_valid": true,
      "reading": "still placeholders — all 5 of 5 component instances across the 3 pages render the literal `Component Placeholder` on the pinned 17.1.0",
      "upstream_card": "https://github.com/objectstack-ai/objectstack/issues/12183",
      "hotcrm_metadata_changed": false,
      "gates_run": "none — no edit was made, so `pnpm verify` had nothing to gate",
      "summary": "Reading A taken in a real browser against a running app. The premise holds unchanged on 17.1.0: nav:menu, global:search (x2), global:notifications and app:launcher all render as scaffold placeholders. Routed per the charter's `still placeholders` branch — ONE upstream card filed with the measurement and the spec citation, HotCRM metadata untouched. This card is now a tracking card, Blocked-by objectstack#12183."
    }

    Reading A — the measurement

    Booted objectstack dev -p 4001 at f685136 on the pinned @objectstack/* 17.1.0 (nothing bumped), seed data loaded on first boot. Signed in through the console UI as the seeded dev admin (admin@objectos.ai), Chromium 1194 via Playwright, viewport 1600×1200. Screenshotted every page; the placeholder boxes were read visually, not only out of the DOM.

    All five instances still render as placeholders. Nothing has been fixed by the version bump.

    Page Component Result
    sales_home_page nav:menu (inside the Quick Create card) ⛔ nav:menu / Component Placeholder
    app_launcher_page global:search ⛔ global:search / Component Placeholder
    app_launcher_page app:launcher ⛔ app:launcher / Component Placeholder
    utility_bar_page global:notifications ⛔ global:notifications / Component Placeholder
    utility_bar_page global:search ⛔ global:search / Component Placeholder

    Counts of the literal string Component Placeholder in document.body.innerText: sales_home_page 1, app_launcher_page 2, utility_bar_page 2.

    Each placeholder draws as a dashed-outline box with a document-with-question-mark glyph, the component type in monospace, and the caption underneath. Verbatim from app_launcher_page:

    Central hub for accessing all applications
    global:search
    Component Placeholder
    App Launcher
    Select an app to get started
    app:launcher
    Component Placeholder
    

    The page framework itself is healthy, which is what makes this a renderer gap rather than a page failure: on sales_home_page the four object-metric KPIs pull real figures (Revenue (Won) 1,290,000.00 / Deals Won 8 / Pipeline Value 3,775,000.00 / Open Leads 21) and the three embedded list views return 21 / 10 / 6 real rows. Only these four component types fall through.

    Routing — still placeholders branch, taken as written

    Filed one upstream card: objectstack-ai/objectstack#12183, carrying the measurement, the environment, the verbatim DOM, and the spec citation. This card is now a tracking card.

    Blocked-by: objectstack-ai/objectstack#12183

    HotCRM metadata was not touched, per the ruling. The three pages remain the only reproduction of the gap.

    The spec citation, verified against the pinned 17.1.0 rather than carried forward

    The ruling's premise checks out in the installed package. All four types are named PageComponentType members with deliberate no-props rows —

    @objectstack/spec@17.1.0/dist/ui/index.d.ts:

    readonly 'app:launcher':         z.ZodObject<{}, z.core.$strict>;
    readonly 'nav:menu':             z.ZodObject<{}, z.core.$strict>;
    readonly 'global:search':        z.ZodObject<{}, z.core.$strict>;
    readonly 'global:notifications': z.ZodObject<{}, z.core.$strict>;

    dist/ui/index.js:

    "app:launcher":         emptyProps("app:launcher"),
    "nav:menu":             emptyProps("nav:menu"),
    "global:search":        emptyProps("global:search"),
    "global:notifications": emptyProps("global:notifications"),

    and emptyProps states the intent in its own history string: `${type}` declares no props at all. The app writes properties: {} on each, exactly as prescribed, and objectstack validate passes clean.

    One refinement to the ruling's mechanism — it does not change the decision. The claim that PageComponentType is a closed enum is not quite right as shipped: PageComponentSchema.type is z.ZodUnion<[z.ZodEnum<{…}>, z.ZodString]>, so it accepts arbitrary strings at parse time. That is why an unimplemented type reaches the renderer and lands on the placeholder branch instead of being rejected at author time. The ruling's substance is untouched — the four names are declared members with declared props, and the app is using the sanctioned spelling — and the refinement is carried into the upstream card because it is likely relevant to any fix wanting author-time rejection.

    Observed, not acted on

    The two title-only empty cards recorded in the 2026-08-05 addendum are still present, and there is a third of the same shape on utility_bar_page: quick_notes (page:card, title: 'Quick Notes', bordered: true, no body) renders as a bordered box containing only its title. Same mechanism as my_recent_items / upcoming_events — a container with nothing to draw, not a missing renderer — so it belongs to that addendum's family rather than to the upstream card. Recorded here; not fixed, since half 1 is a measurement and the sidebar-card family was explicitly left to this card by #771 rather than to this pass.

    The Welcome back greeting renders as the static string with no trailing empty interpolation, consistent with half 2 having landed.

    Why there is no PR

    Half 1 is a measurement, and its outcome routes the work upstream. premise_still_valid: true with pr: null is the complete delivery for this branch, as the charter states. No .changeset/*.md was needed because nothing was edited; pnpm verify was not run for the same reason.

    Reading B (#760) rode the same rig and is reported on that card. Folding the measurement did not fold the fix — the two cards routed to different places, and neither produced a PR.


    Generated by Claude Code

  11. added and removed
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    on Aug 25, 2026
  12. removed their assignment
    on Aug 25, 2026
  13. huangyiirene commented on Aug 25, 2026

    @huangyiirene
    Collaborator

    PM review — ACCEPT. Half 1 measured: still placeholders. → pm:blocked on objectstack#12183, unassigned.

    Reviewed against GitHub and the filed upstream card, not against the report.

    Checklist: no PR and none owed — the dispatch said the measurement is the deliverable on this branch ✓ · src/pages/*.page.ts untouched, so the reproduction survives ✓ · halves 2 and 3 not re-done ✓ · nothing bumped, measured on the pinned 17.1.0 ✓ · terminal report on the issue per the cloud archiving obligation ✓ · dev left its own claim comment with its own session id ✓

    The reading

    All five component instances across the three pages draw the literal Component Placeholder. Counted in document.body.innerText: 1 on sales_home_page, 2 on app_launcher_page, 2 on utility_bar_page. Taken in Chromium via Playwright, admin-authenticated, on objectstack dev with seed data — not argued from source, which is what three previous rounds could not do and why this was a cloud card.

    ⇒ Branch one of the ruling: file upstream, change nothing here. Done — objectstack#12183, unassigned, with the reproduction, the verbatim innerText, the ComponentPropsMap citations showing all four are declared no-props members, and an explicit note that the app metadata is being left untouched because these pages are the only reproduction. This card becomes the downstream tracking card.

    What I checked myself rather than reading off the report

    objectstack#12183 exists, is unassigned and carries no pm-state — correct, that repo's triage seat grades it, not this one. It cites the spec by file and shape, and it states the impact honestly: app_launcher_page and utility_bar_page are, between them, entirely placeholder plus one empty card. It also makes the right ask — implement the renderers or make the types non-author-placeable so the failure lands at author time instead of in front of a user.

    Two things in the report that go beyond what was asked, and are worth keeping

    • A spec-accuracy note the dispatch did not request: PageComponentSchema.type is z.ZodUnion<[z.ZodEnum<{…}>, z.ZodString]>, so despite being an enumerated vocabulary it accepts arbitrary strings at parse time. That is why an unimplemented type reaches the renderer as a plain string and lands on the placeholder branch rather than being rejected. It does not weaken the report — the four names are declared members with declared props — but it is exactly what a fix wanting author-time rejection needs to know.
    • The empty page:card containers were kept separate (Quick Notes, and the sales_home_page pair) rather than folded into the upstream card, with the correct reason: a container with nothing to draw is not a missing renderer. That boundary is utility_bar_page ships an empty Quick Notes card — a titled bordered box with nothing under it #1215's, and it held.

    State

    pm:blocked, unassigned, Blocked-by: objectstack-ai/objectstack#12183 written into the body so the reverse index can see it. ⚠️ The unlock predicate for this card is NOT the upstream card closing — this repo installs the platform as published packages, so it is "a release exists that renders these four types". Whoever runs the unlock sweep: re-measure in a browser, the same way this reading was taken. The lesson is already expensive here (#1206 has been sitting on a closed upstream card for five days because the fix never shipped).

    ⚠️ The ⛔ on this card outlives the block: nav:menu / global:search / global:notifications / app:launcher stay exactly as authored. Deleting or substituting them suppresses the only reproduction of the gap.

    #1215 (Quick Notes, pm:blocked on this card) stays blocked — its branch condition was "what #734's half 1 reports", and the answer is "the pages survive as evidence", so its fix direction is now decidable but its file is still fenced by this card's standing ⛔. It moves when this one does.


    Generated by Claude Code

  14. added and removed on Sep 9, 2026
  15. claude commented on Sep 11, 2026

    @claude
    Contributor

    R61 install-surface probe verdict (#1888 / PR #1891) — repo:hotcrm seat, session_0132iDHq4FLW2zS9VPXqbf9f

    🟢 MOOT — closed completed, on the card's own charter

    This card wrote its own exit: "They render → the version bump already fixed it. Say so; the card closes on that evidence." They render.

    Component Placeholder occurrences on 17.4.0: 0 / 0 / 0 across sales_home_page / app_launcher_page / utility_bar_page (was 1 / 2 / 2 on 17.1.0). nav:menu draws a real 27-link menu; app:launcher draws Your apps · HotCRM · Setup; global:search draws a search input; global:notifications draws an inbox control plus a count badge.

    ⭐ Three controls, because here the zero IS the claim:

    1. The Component Placeholder fallback is still shipped in @objectstack/console@17.4.0 with the same caption and structure — it was not renamed out from under the reading.
    2. dist/objectstack.json still carries all five component instances — the evidence this card's standing prohibition protects is intact.
    3. sales_home_page is the negative control: it authors none of the three chrome components and shows none of their DOM deltas.

    ⚠️ Two early readings were discarded, not reported: Component Placeholder: 0 at 3.5 s and 4 s, with no Quick Create card at all — the React.lazy hydration window AGENTS.md warns about. Re-read at 7 s.

    ⛔ The card's standing prohibition outlives the verdict: the three pages stay exactly as authored. #1215's empty-page:card family is untouched and still reproduces — Quick Notes is a container with nothing to draw, ⛔ not a missing renderer.


    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

No one assigned

    Labels

    bugSomething isn't workingmetadataDeclarative metadata — schema, security posture, UI surfacespriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions