Skip to content

plugin-chatbot: the build-progress panel cannot express a verification phase — an unknown phase silently reads as 「Building…」, and its copy is hardcoded English #7388

Closed

Description

@hotlong

What the chat cannot say

cloud#1838 asks for phase semantics while the build agent verifies a change it just applied — 「正在校验…」 in the SSE stream or on the tool cards, so the user is not staring at an unlabelled spinner. The cloud side of that card landed a mechanical bound on the self-check loop, but the COPY half cannot be produced from cloud at all, because both channels that reach the chat are objectui-owned:

  1. packages/plugin-chatbot/src/mapMessages.ts — extractBuildProgress reads the reconciled data-build-progress part and coerces anything it does not recognise: const phase = d.phase === 'data' || d.phase === 'done' ? d.phase : 'structure'. A runtime that emitted phase: 'verify' would render as 「Building your app…」 with a spinner — actively wrong, since the build is finished and the app is being checked.
  2. packages/plugin-chatbot/src/ChatbotEnhanced.tsx — the panel's strings are hardcoded English (Building ${appLabel}…, adding sample data, Built ${appLabel}), and each tool card is titled humanizeToolName(tool.toolName), i.e. derived from the English tool id. Nothing in the tool result or the stream can change either.

So a Chinese user watching a confirmed change get verified sees an English spinner label plus a column of English tool names, and no statement that verification is what is happening.

Suggested shape

Two small, independent pieces:

  • Admit a verify phase in extractBuildProgress and give it its own line in the progress panel (localized like the rest of the console), so a runtime can announce the phase it is in. The reconciled-single-part mechanism already exists; only the accepted vocabulary and one label are missing.
  • Localize the panel's three hardcoded strings through the console's own i18n, since they are the only untranslated text in an otherwise localized surface.

Measured on the local rig (2026-09-03, cloud branch claude/issue-1838-bounded-post-apply-verification): after 「确认,就按这个方案建」 the confirm turn spent 111 seconds and 9 tool calls verifying and re-seeding AFTER apply_blueprint returned, with the panel still reading 「Building your app…」 the whole time.

Filed from cloud#1838, which fixed the loop's LENGTH; this is the part of that card that must be built here. No cloud change is blocked on it.

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 5, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 — domain:ui / priority:p2 / pm:queue / bug / i18n

    锚定 (anchoring):两块都落在 packages/plugin-chatbot ⇒ domain:ui。⛔ 不需要 cloud 侧任何动作(卡片自己也说 "No cloud change is blocked on it"),所以是 pm:queue。

    在 origin/main a472b07 上复核

    第 1 块 —— 成立,逐字:

    packages/plugin-chatbot/src/mapMessages.ts:682   function extractBuildProgress(parts: AnyPart[]): ChatBuildProgress | undefined {
    packages/plugin-chatbot/src/mapMessages.ts:692     const phase = d.phase === 'data' || d.phase === 'done' ? d.phase : 'structure';
    

    phase: 'verify' 会被强制成 'structure'。⭐ 补一条卡片没提、但同向的证据:紧邻的 :730 是同一形状的第二处(const phase: ChatBlueprintProgress['phase'] = d.phase === 'done' ? 'done' : 'designing';)。也就是说"未知 phase 静默折叠成一个默认值"在这个文件里是一种模式,不是一处疏漏 —— 接手者若要加词表,两处的口径应该一起想清楚(是否都该在遇到未知 phase 时至少 warn 一次)。

    第 2 块 —— ⚠️ 已经做了一半,卡片的描述过时了:

    packages/plugin-chatbot/src/ChatbotEnhanced.tsx:4025   <span>{isDone ? `Built ${appLabel ?? 'your app'}` : `Building ${appLabel ?? 'your app'}…`}</span>
    packages/plugin-chatbot/src/ChatbotEnhanced.tsx:4027     <span className="text-xs font-normal text-muted-foreground">adding sample data</span>
    

    那三个面板字符串确实还是硬编码英文 —— 这一半属实。

    但卡片还说 "each tool card is titled humanizeToolName(tool.toolName), i.e. derived from the English tool id. Nothing in the tool result or the stream can change either." —— 这一半今天不成立了:

    packages/plugin-chatbot/src/ChatbotEnhanced.tsx:1281      title: humanizeToolName(tool.toolName, translateToolTitle) || tool.toolName,
    packages/plugin-chatbot/src/ChatbotEnhanced.tsx:2073      // objectui#7254 / cloud#1658 — `humanizeToolName`'s translator seam has
    packages/plugin-chatbot/src/ChatbotEnhanced.tsx:2079      const friendlyTitle = humanizeToolName(tool.toolName, tt);
    

    humanizeToolName 已经有翻译接缝了(第二个实参),由 objectui#7254 / cloud#1658 装上,:2073 的注释就是记录。所以"一列英文工具名"这条要重新测:接缝在,问题可能变成"接缝喂的翻译表不全",那是另一种工作量。⛔ 接手者请先跑一次真实 rig 确认工具名今天到底显示成什么,再决定第 2 块的范围。

    定级理由

    priority:p2:

    • 不是缺少翻译,是显示了错误的状态。 卡片这句判断我复述并同意:apply 已经返回、正在校验时,面板仍写 "Building your app…" 加一个转圈 —— actively wrong,不是"未本地化"。
    • 实测有量级:在本地 rig 上(2026-09-03),确认回合在 apply_blueprint 返回之后又花了 111 秒、9 次工具调用做校验与重新播种,面板全程写着 "Building your app…"。111 秒盯着一个说错话的转圈,是真实体验损失。
    • 它是 cloud#1838 的 copy 半 —— 那张卡的机械半(自检循环的长度界)已经落地,用户看到的那一半在这里。

    不上 p1:无数据损坏、无越权、无静默错答(错的是状态标签,不是数据)。

    定型:Bug ⊕ 一处极小的授权面扩张

    • 面板字符串本地化 ⇒ 纯 Bug(其余界面都已本地化,这三条是孤岛)。
    • extractBuildProgress 接纳 verify ⇒ ⚠️ 扩大了接受的词表。但接受的是运行时发来的 phase 值,不是作者可写的元数据键 —— 不是"公共可授权面"。按机械边界测试不踩 manual floor;本席判定为 Bug(让声明=执行:运行时能发的 phase,UI 应当能表达)。⛔ 若执行席不同意这个判读,请在动手前提出,不要默默按 Feature 处理而卡住。

    ⛔ 给执行席的边界

    1. 两块独立,可以两个 PR,卡片自己就是这么分的("Two small, independent pieces")。建议先做本地化(无争议),再做 verify 词表。
    2. verify 那一块要与运行时对齐:objectui 接纳一个 verify phase,但谁来发它?卡片说"a runtime can announce the phase it is in" —— ⚠️ 若 cloud 侧今天并不发 verify,本卡落地后面板仍然写 "Building"。⛔ 动手前确认发送端的计划,否则做的是一个没有生产者的接收端(正是 finding(core): like / ilike are spec-valid AST operators that ValueDataSource's in-memory matcher does not implement — now refused loudly instead of matching every row #7383 记录的那类投机表面)。
    3. ⛔ 不要顺手把 :692 的兜底改成抛出或渲染未知 phase 的原始字符串 —— 那会把一个错标签换成一个泄漏内部枚举值的标签。加词表 + 保留兜底 + 考虑一次 warn,是安全的形状。
    4. 第 2 块动手前先测工具名的实际显示(见上),⛔ 别照抄卡片里已经过时的那句。

    ⛔ 分诊席不认领、不派单、不写码。


    Generated by Claude Code

  3. self-assigned this
    on Sep 9, 2026
  4. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    Contributor

    Claim: session session_01611D6ZaRaMmwTNQmSbk8MH · branch claude/issue-7388-chatbot-progress-phase-i18n

    PM dispatch(domain:ui 席)。assignee 与本评论由 PM 代设,dev 继承二者、⛔ 不写 assignee 字段、⛔ 不再发第二条 claim。

    ⭐ 先读分诊评论 5548561995 —— 它核过坐标、发现卡片有一半已经过时、并划了三条边界。本简报不重复它。


    一、⛔ 裁决:两块分开,第一块无条件做,第二块带前置

    块 内容 归属
    1 面板三条硬编码英文字符串走 console 自己的 i18n ✅ 无条件做 —— 其余界面都已本地化,这三条是孤岛,纯 Bug
    2 extractBuildProgress 接纳 verify phase + 面板给它自己的一行 ⚠️ 带前置,见第二节

    ⭐ 卡片自己就是这么分的("Two small, independent pieces")。可以两个 PR。建议先做第 1 块(无争议、能落地),第 2 块视前置结果而定。

    ⚠️ 关于第 2 块的型:它扩大的是运行时发来的 phase 值的接受词表,⛔ 不是作者可写的元数据键 ⇒ 分诊席判定不踩 manual floor,是 Bug(让声明=执行:运行时能发的 phase,UI 应当能表达)。⛔ 若你不同意这个判读,动手前提出,不要默默按 Feature 处理然后卡住。

    二、⚠️⚠️ 第 2 块的前置 —— 谁来发 verify?

    分诊席的原话,本席背书为硬前置:objectui 接纳一个 verify phase,但发送端呢? 若 cloud 侧今天并不发 verify,本卡落地后面板仍然写 "Building" —— 你做的是一个没有生产者的接收端,正是 objectui#7383 记录的那类投机表面。

    ⚠️ 而且这个前置可能在本仓答不了:本会话的仓库范围只有 objectstack 与 objectui,cloud 不在。⇒ 按这个顺序找:

    1. phase 词表是否在共享契约里声明(@objectstack/spec / packages/types 之类)?若 verify 在那里被声明,那就是生产者侧的证据,前置满足。
    2. 若只在 objectui 本地类型里,看有没有别的痕迹(SSE 契约文档、fixture、cloud#1838 在本仓留下的引用)。
    3. ⛔ 若在 objectui 里完全找不到 verify 被声明或被发送的证据:停手回报第 2 块,把第 1 块单独交付。⛔ 不要"先接上等以后有人发" —— 那正是本卡要避免的形状。

    ⚠️ 跨仓判定的老规矩:⛔ 按已发布的 release 判,不是上游仓的 main(本班已为这条付过学费)。

    三、⚠️ 卡片有一半已经过时 —— ⛔ 别照抄

    卡片说工具卡标题 humanizeToolName(tool.toolName) 派生自英文 tool id,且 "Nothing in the tool result or the stream can change either."

    今天不成立:humanizeToolName 已经有翻译接缝(第二个实参),由 objectui#7254 / cloud#1658 装上,文件里 :2073 的注释就是记录。

    ⇒ ⛔ 动手前先在真实 rig 上测一次工具名今天到底显示成什么。 接缝在,问题可能已经变成「喂给接缝的翻译表不全」—— 那是另一种工作量,范围要按实测定,⛔ 不按卡片那句过时的话定。

    四、⛔ 边界

    1. ⛔ 不要把 extractBuildProgress 的兜底改成抛出、或渲染未知 phase 的原始字符串 —— 那会把一个错标签换成一个泄漏内部枚举值的标签。安全形状是:加词表 + 保留兜底 + 考虑遇到未知 phase 时至少 warn 一次。
    2. ⭐ 分诊席发现同一形状的第二处:紧邻的 ChatBlueprintProgress 兜底(d.phase === 'done' ? 'done' : 'designing')。⇒ 「未知 phase 静默折叠成默认值」在这个文件里是一种模式,不是一处疏漏。若你加词表,两处的口径要一起想清楚(是否都该 warn 一次)。⚠️ 但 ⛔ 不要顺手改第二处的行为 —— 想清楚、写进 PR、必要时留 验收备注。
    3. ⚠️ 按符号重新定位,⛔ 不要相信分诊席引的行号(本班刚为位置漂移付过一次,类已立卡 objectui#8875)。

    五、验收 —— 类判据

    • 第 1 块:判据是「面板上不再有绕过 i18n 的英文字面量」,⛔ 不是「加了三个翻译键」。
    • 第 2 块(若前置满足):判据是「运行时发 verify 时,面板说的是校验,而不是仍在构建」。
    • ⭐ 控制要会动:一个已知 phase(data / done / structure)必须在两个世界里渲染得跟今天一模一样 —— 证明你没把兜底弄坏;⛔ 一个「主体坏了它也红」的控制不是控制。
    • 消融:从已提交树出发,把改动拿掉,先在盘上证明变异落了(marker 计数 和 blob hash),再跑,看它按用例名变红,按状态还原(git diff HEAD 为空 且 blob 回原值)。⛔ 只有退出码不算。

    六、⚠️ Clause-② —— 由你判 + 载体预授权

    机械下限:新导出符号、或已发布载荷上的新键,恒 yes;拿不准 ⇒ yes。⛔ 不要继承本简报任何一句作为结论 —— 分诊席说第 2 块「不踩 manual floor」是关于型的裁定,⛔ 不是替你做的 Clause-② 判定。

    ⭐ 载体预授权:固定拼写行必须落在这条 claim 评论里,本席 MCP 面上没有编辑评论的工具(按枚举确认);dev 席 REST 有 PATCH /issues/comments/{id} ⇒ 本席预先授权你把自己测得的 Clause-②: 行追加到本评论末尾(保留上方全部原文,行内注明 dev 测得、PM 授权)。⚠️ 按字节核对再发:行首 Clause-②:、ASCII 冒号 0x3a(⛔ 不是全角)。⛔ 绝不另发第二条 claim 评论(那是 misplaced,同样 exit 4 且看起来像已经答了)。见 objectstack#17213。

    ⚠️ 契约评审档位不可用(连续 16 次 429)。yes 会停队 —— ⛔ 不要因此改形状、降规格或自审。
    ⚠️ scripts/pm/check-widening-tells.mjs 在 objectui 不存在(住 objectstack),且裸 CLI 对 objectui 判定是瞎的(objectstack#17217)。⛔ 不是证据。

    七、⭐ 枚举,两条轴

    ⛔ 证明一个门看得见你的改动,不等于枚举了看得见你改动的门。①内容轴:谁读了你改动说的东西。②位置轴:谁按 file:line 指着你改的文件,以及我的改动移动了什么行。

    八、⛔ 红线

    ⛔ 绝不编辑共享主检出(用专属 worktree)· ⛔ 绝不 git stash · ⛔ 绝不按名杀进程 · ⛔ 不碰 content/docs/releases/ · ⛔ 不碰 governed surface · ⛔ 不扩范围(相关事实进 验收备注 并点名后继)· ⛔ 不碰 cloud(不在本会话仓库范围内)。

    ⚠️ 工具链(本班实测两次假绿):pnpm --filter PKG exec vitest run FILE 被 objectui#3378 守卫拒绝,会静默跑 console 的 22 个文件报绿;pnpm --filter PKG test 在无 test 脚本的包上匹配零个脚本 exit 0。⛔ 都不是读数。从仓根:pnpm exec vitest run packages/PKG/src/FILE。
    ⚠️ 门 exit 2 = PREREQUISITE NOT MET ⇒ NOT MEASURED,⛔ 不是红也不是绿。
    ⚠️ 共享身份 os-zhuang 的 GitHub API 间歇性限流 —— git 能答的走 git;⛔ 永不循环重试。


    Clause-②: yes — 新键落在已发布载荷上:@object-ui/i18n 导出 en / zh / … 十个 locale 对象(packages/i18n/src/index.ts 的 export { default as en } 等),本 PR 在每个对象上新增 chatbot.build.* 共 10 个键 ⇒ 踩机械下限。(useBuildGroupLabel 未导出,不是它触发的。)

    (上行由 dev 席实测并写入,PM 席在派发词里预先授权了这次追写;上方原文逐字未动。PR:#8888,已挂 needs:contract-review。)


    Generated by Claude Code

  5. claude commented on Sep 9, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 7388,
      "status": "needs_decision",
      "branch": "claude/issue-7388-chatbot-progress-phase-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8888",
      "premise_still_valid": false,
      "summary": "PIECE 1 DELIVERED, complete and mergeable on its own (draft PR #8888, `Part of #7388`, not a closing keyword). The build panel's own copy now resolves through the console pack as `chatbot.build.*` in all ten locales. Scoped to the PREDICATE, not to a key count: besides the three strings the card names, the panel also bypassed i18n on the five per-type row headings (`Objects`/`Views`/`Dashboards`/`App`/`Sample data`, one per row on EVERY build) and the `+N more` overflow counter. `BUILD_GROUP_LABEL`'s English Record became a static `useBuildGroupLabel()` switch (a computed key would be invisible to check-i18n-call-site-keys); its default arm keeps `?? type` verbatim, so an unknown artifact type still renders its raw type and never a raw key. No fallback was tightened, no new exported symbol. PIECE 2 STOPPED on its precondition, per the dispatch's step 3. TWO CARD PREMISES FALSIFIED, hence premise_still_valid=false. (a) The tool-name half is not merely stale, it is fully closed: `humanizeToolName`'s translator seam is live at BOTH call sites and the `chatbot.tool.*` table is COMPLETE - 35 keys in en and 35 in zh, aligned, including `verify_build`. There is no 'incomplete table' fallback problem either; nothing to do there. (b) Piece 2's producer does not exist AND the card's literal fix could not cover its own measured scenario - see open_questions. Piece 1's premise held verbatim.",
      "tests": "All from the repo root on final commit 5d50a3d0a, after building the two packages' closures. NEW PIN packages/plugin-chatbot/src/__tests__/buildPanelI18n-7388.test.tsx: `pnpm exec vitest run <that file>` exit 0, 'Test Files 1 passed (1)', 'Tests 12 passed (12)'. AFFECTED PACKAGES: `pnpm exec vitest run packages/plugin-chatbot/ packages/i18n/` exit 0, 'Test Files 107 passed (107)', 'Tests 1592 passed (1592)' - this includes the pre-existing provider-less English pins in ChatbotEnhanced.test.tsx, untouched. TYPECHECK: `pnpm --filter @object-ui/plugin-chatbot --filter @object-ui/i18n run type-check` exit 0, script name echoed, covering tsc --noEmit AND tsc -p tsconfig.test.json (so the pin is type-checked). GATES all exit 0: check:i18n-keys ('every in-scope call-site key resolves against the en pack (3001 keys), every literal inline defaultValue matches the value the pack serves, every call site passes exactly the arguments that value has holes for'), check:i18n-drift ('0 en value(s) changed (10 key(s) added, 0 removed)'), check:i18n-dead-keys, check:i18n-designer-parity, check:changeset-presence ('12 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)'), check:changeset-fixed, check:changeset-no-major, check:control-bytes, check:lockfile-integrity, check:vi-mock-specifiers, check:unreferenced-sources. check:governed-queue-guard --test => 'NOT GOVERNED - 13 path(s) checked against 5 governed surface(s); none matched'. ESLINT is a FULL population reading, not a narrowing: `pnpm exec eslint . --no-inline-config --format json` over 4674 files; 0 errors and 0 new warnings in the 13 files this PR touches (the 10 warnings on ChatbotEnhanced.tsx sit at :1844, :1915, :3778 - all pre-existing, none on a line this PR moved). NOT MEASURED, not red: check:readme-exports self-declares 'the population COLLAPSED -- this run proves nothing' (needs the whole workspace built); it names 26 OTHER packages' READMEs and neither of my two appears once they are built. Declared to CI. ABLATION from the committed tree, restoring the hard-coded `Building ${appLabel ?? 'your app'}...` literal: ON-DISK PROOF FIRST - HEAD blob b35dead95899bb524bea66c92299995123fe92a8 -> c46cee3add2c91758aa846b476e9d950b029c63d, marker counts inverted (new 1->0, old 0->1). Reddens BY TEST-CASE NAME and only on the subject: 'x localizes the in-flight header instead of hard-coding \"Building X...\"' and 'x localizes the unnamed-build stand-in, so the header is Chinese end to end'; 'Tests 2 failed | 10 passed (12)'. THE CONTROL DID NOT MOVE: all four 'control: a known phase renders exactly as it did before (en)' cases are among the 10 that passed - the ablated code renders 'Building CRM...' in English too, which is exactly why it is a real control. RESTORED BY STATE, not by exit code: git hash-object back to b35dead9..., `git diff HEAD` empty. HONESTY NOTE: the FIRST ablation attempt was VOID, not a reading - it passed `--reporter=basic`, which vitest 4 removed, so the run died in _createServer before entering any test body (same class as MODULE_NOT_FOUND exit 1). Redone with the default reporter; every number above is from the redone run.",
      "mcp_calls": "2 - issue_read(get) and issue_read(get_comments) on #7388. Everything else (PR create, PR body read-back, label add + read-back, claim-comment PATCH + read-back, report comment) went over the repo-scoped REST channel, probed first with a 200 on GET /repos/objectstack-ai/objectui.",
      "open_questions": [
        {
          "question": "PIECE 2's producer. Nothing declares or emits a `verify` phase on `data-build-progress`, and the card's literal fix cannot cover its OWN measured scenario. Evidence, in the dispatch's own three-step order: (1) SHARED CONTRACT - the published @objectstack/spec@17.4.0 (this branch's lockfile pin; judged by the published release, not upstream main) declares this channel only as `onProgress?: (part: { type: string; id?: string; data?: unknown })`. `data` is `unknown`: the phase vocabulary is not in the contract AT ALL. Across the whole published package the token `verify` appears only as the tool name `verify_build` and unrelated tokens (verifyEmail etc). The phase union 'structure'|'data'|'done' is declared ONLY in objectui's own private `ChatBuildProgress`, i.e. the receiver's own type. (2) NO OTHER TRACE IN-REPO - no `phase: 'verify'`, no cloud#1838 reference; `verify_build` does exist here but travels the TOOL-CARD channel and BuildDebugDrawer, not the `data-build-progress` phase channel. (3) STRONGER THAN 'no evidence': `data-build-progress` is emitted BY `apply_blueprint` through its own `ctx.onProgress`, and the card's own measurement is that the 111 seconds of verifying happened AFTER `apply_blueprint` RETURNED. A returned tool cannot emit another frame on its own channel - so even if cloud agreed to send `verify` today, 'admit a verify phase in extractBuildProgress' would still leave the panel reading 'Building' for exactly the 111 seconds the card is about. This is a producer/contract decision and cloud is out of this session's repo scope.",
          "options": [
            "A - Route piece 2 back to cloud#1838's side to pick the EMITTER first (which component sends a post-apply_blueprint progress frame, and on which channel), then re-file the objectui receiver card against that decision. Cost: one more hop before any UI lands. Benefit: the receiver is written against a real producer and a real channel, not a guess.",
            "B - Land the `verify` vocabulary in objectui now anyway. Cost: a receiver with no producer - exactly the speculative-surface class objectui#7383 records - AND it still would not fix the measured 111 seconds, because the emitting tool has already returned. Not recommended on either count.",
            "C - Re-scope piece 2 in objectui to the channel that CAN speak during those 111 seconds (the tool cards, which already render `verify_build` and are already fully translated), e.g. by having the panel reflect a running post-build verification instead of adding a phase to a dead channel. Cost: a different design, needs a product call. Benefit: no cloud change strictly required."
          ],
          "recommendation": "A, then reconsider C. A is what the dispatch's own step 3 asks for and it is the only option that fixes the emitter question rather than routing around it. I flag C because the third finding above changes the problem: the card assumed the phase channel was still open during verification and it is not, so even a cooperative cloud cannot satisfy the card as literally written. That fact should reach cloud#1838 with the routing. I did NOT implement any of the three."
        },
        {
          "question": "The second same-shape fallback next door (dispatch boundary 2). I reasoned about it and did NOT change its behaviour, as instructed; the reasoning is in the PR's 验收备注. In short the two are NOT symmetric: `extractBuildProgress` folds an unknown phase to 'structure', a mid state whose panel keeps spinning and keeps saying 'building' - the actively-wrong case; `extractBlueprintProgress` folds to 'designing', also a mid state, but its comment already states that as a CONTRACT ('Only `done` is authoritative; anything else (incl. absent) is still designing') and its panel is superseded by the authoritative 'Proposed plan' card as soon as the tool result lands, so a mis-fold has a bounded exposure window.",
          "options": [
            "A - Add the warn-once to `extractBuildProgress` only, and only in the same PR as the vocabulary.",
            "B - Add warn-once to both fallbacks now, in a separate PR.",
            "C - Leave both alone until piece 2 is routed."
          ],
          "recommendation": "A. Warning before the vocabulary exists is actively harmful: it would fire a false warning on EVERY frame carrying the very phase we are about to accept. The vocabulary and the definition of 'unknown' have to move together, so this belongs to piece 2's PR and not to piece 1's. C is the correct state until then, which is what I left."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed: 16 entries in ChatbotEnhanced's `L` labels object (emptyTitle, emptyDescription, clear, sendHint, copy, copied, regenerate, model, submit, uploadFiles, stopResponse, trace, viewTrace, toolDetailsHidden, sendFailedRateLimited, sendFailedGeneric) are spelled `labels?.x ?? 'English literal'` with NO `tt()` layer, while the objectui#7254 entries in the SAME object (toolCompleted, toolRunning, ...) do have one - so a host that does not feed `labels` gets English from half of one object. It is on the chat SHELL, not on this card's panel, so it is not in this PR. 承接者: 无 - no queued PR or person is going to touch that object, so I did not file it; PM's call whether it earns its own card.",
        "noted, not filed: toolchain fact worth recording - `vitest --reporter=basic` was REMOVED in vitest 4 and now dies at startup in `_createServer` with exit 1, which reads exactly like a red test run while never entering a test body. It bit this run once (the first ablation attempt, discarded). Same NOT-MEASURED class as MODULE_NOT_FOUND. No code defect, so no card.",
        "noted, not filed: `check:readme-exports` cannot produce a reading unless the WHOLE workspace is built - it self-declares 'the population COLLAPSED -- this run proves nothing' and implicates 26 packages. Correct behaviour (it fails loudly rather than green), just expensive locally. No card."
      ]
    }

    Generated by Claude Code

  6. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    Contributor

    PM 裁决 —— 第 1 块收下(PR #8888),第 2 块转 needs-user-decision

    执行席回报 status: needs_decision / premise_still_valid: false。第 1 块(构建面板自有文案的本地化)已独立交付,PR #8888 用 Part of #7388、⛔ 未用 closing keyword,所以合并它不会关掉还有一半开着的卡。本卡因第 2 块继续开着。

    ⛔ 本席能裁的,先裁掉:选项 B 出局

    执行席给的三条路里,B(「先把 verify 词表落进 objectui,发送端以后再说」)不成立,两条理由各自独立足够:

    1. 它盖不住卡片自己实测的那 111 秒(见下面那条决定性事实)—— 一个不解决卡片所述问题的改动,不是这张卡的修复。
    2. 它是没有生产者的接收端,正是 objectui#7383 记录的投机面类型。

    ⇒ ⛔ 不许走 B。 这一条是形状判定,属本席权限,⛔ 不必等任何人。

    ⭐⭐ 决定性的新事实 —— 它把问题本身改了

    执行席按派发词的三步顺序找发送端,三步全空(① 已发布的 @objectstack/spec@17.4.0 对这条通道只声明到 onProgress?: (part: { type: string; id?: string; data?: unknown }),data 是 unknown,phase 词表根本不在契约里;② 本仓无 phase: 'verify'、无 cloud#1838 引用,verify_build 走的是工具卡通道不是这条;③ 因此停手回报)。

    但它另外量到了一条比「找不到证据」强得多的事实:

    data-build-progress 是 apply_blueprint 通过自己的 ctx.onProgress 发的。而卡片自己实测的场景是「apply_blueprint 返回之后又花了 111 秒做校验」。一个已经返回的工具,不可能再往自己的通道上发帧。

    ⇒ 即便 cloud 今天就同意发 verify,「在 extractBuildProgress 里认一个 verify phase」这个字面方案,仍然会让面板在正好是本卡要修的那 111 秒里继续显示「Building」。

    ⚠️ 这不是「证据不足」,这是卡片的前提被证伪:卡片假设 phase 通道在校验期间仍然开着,而它不是。本席复核了这条推理的可检验部分(data-build-progress 在本仓的读取端 mapMessages.ts:723 确实只是「取最后一帧」的被动接收者,本仓不产生该帧),并把「apply_blueprint 是发送方」这半条标注为转述执行席的读数——它住在 cloud,本会话仓库范围内无法直读。

    为什么转 needs-user-decision 而不是本席续裁

    剩下的两条路都越出本席权限:

    内容 为什么本席裁不了
    A 回到 cloud#1838 一侧先定发送方(哪个组件在 apply_blueprint 返回后还能发进度帧、发在哪条通道上),再据此重开 objectui 的接收端卡 cloud 不在本会话的仓库范围内(本席只接 objectstack 与 objectui)。这是跨仓的发送端设计决定。
    C 在 objectui 侧改scope:改用那 111 秒里确实还在说话的通道(工具卡 —— 它已经渲染 verify_build,且 chatbot.tool.* 在 en/zh 各 35 键完全对齐),让面板反映「构建后校验进行中」,而不是往一条已死的通道上加 phase 这是产品判断:那 111 秒里界面该说什么,不是本席的裁量面。

    执行席的建议是 「A,然后重新考虑 C」,理由是 A 是唯一真正回答发送端问题、而不是绕开它的路;并强调上面那条决定性事实必须随路由一起送到 cloud#1838,否则那边会按一个已被证伪的前提去实现。本席认同这个次序,但 A 和 C 谁先谁后、以及 C 到底要不要做,需要维护者拍板。

    ⛔ 与此同时明确不做的事

    • ⛔ 不落 verify 词表(B 已出局)。
    • ⛔ 两处兜底都不加 warn。执行席的推理本席认同并复述:extractBuildProgress 折叠成 'structure'(中间态、面板继续转圈)与 extractBlueprintProgress 折叠成 'designing' 风险不对称——后者的注释已把这条写成契约("Only done is authoritative"),且其面板一旦 propose_blueprint 结果落地就被权威卡取代,暴露窗口有界。⭐ 而且先加 warn 再加词表,会让 verify 在落地前的每一帧刷一条假告警——词表和「未知值」的定义必须同一个 PR 一起动。⇒ 维持现状是正确状态。
    • ⛔ 不碰 humanizeToolName 那一半:执行席实测该接缝今天是通的、表也是满的(两个调用点都传活 translator;chatbot.tool.* 在 en/zh 各 35 键、完全对齐、含 verify_build)。卡片那句「a column of English tool names… Nothing in the tool result or the stream can change either」对平台工具今天完全不成立,连「表不全」这条退路都不成立。这一半无事可做。

    另:一条交 PM 判的观察,本席裁定不立卡

    ChatbotEnhanced 的 L 标签对象里有 16 条走 labels?.x ?? '英文字面量'、没有 tt() 层,而同一个对象里 objectui#7254 加的几条有。执行席按立卡阈值自问「哪一个 PR 或人会碰到这个对象」,答不出,于是没有替它立卡而是交上来——这个处置是对的,本席维持:⛔ 不立卡,承接者:无。若将来有人因别的理由动 L,这条记录在此。


    Generated by Claude Code

  7. claude commented on Sep 9, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 7388,
      "status": "blocked",
      "branch": "claude/issue-7388-chatbot-progress-phase-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8888",
      "premise_still_valid": false,
      "summary": "ROUND 2 = MEASUREMENT ONLY. No code changed: tree clean at 5d50a3d0a, 12 pins still 12/12. I did NOT raise the ceiling, did NOT move PER_CHUNK_BASELINE, did NOT split the chunk, did NOT touch check-eager-closure-budget.mjs, did not re-judge Clause-② and did not touch the claim comment. ANSWER TO THE QUESTION ASKED: no - this behaviour CANNOT be delivered without growing `i18n-locales` past its ceiling, and the reuse route fails on ARITHMETIC before the semantic question even matters. Reproduced CI exactly, locally: 455,519 gzip bytes against the 455,000 ceiling = OVER BY 519 BYTES. Measured at BASE (9553a5fa0, i.e. main before this PR): 454,602 bytes, so the headroom this PR inherited was 398 BYTES. My 10 keys x 10 locales cost 917 GZIP BYTES. To fit I would have to shed 519 of those 917 = 57%. BEST-CASE REUSE SAVES 128 BYTES. Measured, not estimated: removing outright all three keys that have ANY candidate at all (group.object, group.dashboard, group.seed) x 10 locales lands at 455,391 - STILL OVER BY 391. Adding the one further candidate (moreArtifacts) would recover roughly 43 more bytes and still leave ~348 short. So even a maximally aggressive, deliberately UNSAFE reuse of every candidate in the pack does not fit. Separately, every candidate also fails the semantic-identity test - per-key reasons in open_questions. => The correct endgame is the one you named: park behind objectui#8816. I did not edit the PR body, because you said you are already writing the blocker note there and two writers on one body collide; the numbers above are yours to use.",
      "tests": "MEASUREMENT RIG: worktree re-created at 5d50a3d0a, `pnpm install`, then `pnpm --filter '@object-ui/console...' run build` (the budget check exits 2 = PREREQUISITE NOT MET without it - 'No eager-closure report ... This is a broken gauge, not a passing budget'). BASELINE FIDELITY: my flattened `en` pack yields 3001 keys, which is exactly the count check:i18n-keys reports ('the en pack (3001 keys)') - so the census reads what the gate reads. POSITIVE CONTROL ON THE CENSUS PROBE (required, and it passes 3/3): probing 'Waiting for server…' hits console.ai.connectionWaiting; 'sample data' hits chatbot.plan.countSeedData; 'Preview' hits console.ai.previewDraft. So the zeros below are real zeros, not a broken probe. CENSUS RESULT by exact value, then broadened by KEY NAME and by fuzzy value (placeholders stripped) to guard against a false zero from a different string: Objects -> 3 candidates (appDesigner.objects, console.commandPalette.objects, search.typeObjects); Views -> 0; Dashboards -> 3 (console.breadcrumb.dashboards, console.commandPalette.dashboards, search.typeDashboards); App -> 0; Sample data -> 1 (chatbot.plan.countSeedData, lowercase); building/built -> console.ai.planBuilding ('Building…') / console.ai.planBuilt ('Built'); moreArtifacts -> perm.facet.more and calendar.moreEvents (both '+{{count}} more'); appFallback -> 0; addingSampleData -> 0. BYTE MEASUREMENT 1 (cost of the whole family), locale files reverted to BASE, console rebuilt: 454,602 bytes without my keys vs 455,519 with => 917 bytes. On-disk proof: en.ts blob dc38a277... -> e3892dff... and back; restored BY STATE, `git diff HEAD` empty. BYTE MEASUREMENT 2 (best-case reuse), the three candidate rows deleted from the chatbot.build.group block in all ten packs: 455,391 bytes => saving 128. On-disk proof: marker count 30 -> 0 AND en.ts blob dc38a277... -> 7de4379a... and back; restored BY STATE, `git diff HEAD` empty. TWO VOID READINGS DISCLOSED, neither used as a result. (i) The first attempt at measurement 2 anchored on `^        (object|dashboard|seed):` across the whole file, which matches 7 rows in en.ts, not 3 - the assertion fired and NOTHING was written (blob hash unchanged, reported saving 0). Re-anchored inside the `chatbot:` namespace and redone; only the redone numbers are above. The over-broad match happened because a PRE-EXISTING, unrelated `build: {` block also sits at indent 4 elsewhere in the pack. (ii) In measurement 1 my marker-count line was a broken `grep -c` aggregation and printed 0 both before and after; the load-bearing proof there was the blob hash, which was correct, and measurement 2's marker count (30 -> 0) works properly. AFTER both mutations: tree clean at 5d50a3d0a (`git status --porcelain` empty), and the 12 pins re-run green - `Test Files 1 passed (1)`, `Tests 12 passed (12)`. No gate needed re-running because no byte of the branch changed.",
      "mcp_calls": "2 for the whole run, unchanged this round - issue_read(get) and issue_read(get_comments) on #7388. Round 2 added zero MCP calls; the report comment went over the repo-scoped REST channel.",
      "open_questions": [
        {
          "question": "THE CEILING (objectui#8816). This PR is the first concrete claimant you predicted, and I can now put a number on its claim: the behaviour needs 917 bytes and the chunk had 398. The three routes #8816 lists are not equally available to it, which is a fact #8816 may want: RAISING the ceiling is the only one that actually admits this PR, because RATIONING cannot - the reuse budget in the whole pack is 128-171 bytes against a 519-byte gap - and SPLITTING the chunk is a structural change no localization PR should carry. I am not proposing any of them; that is the maintainer's ruling.",
          "options": [
            "A - Park #8888 behind #8816 and let the maintainer rule. Cost: the PR waits, but it was already parked on needs:contract-review (fable tier now 17 consecutive 429s), so this adds no delay at all.",
            "B - Ship a reduced localization that fits: drop the five per-type row headings and localize only the header frames. Cost: it FAILS the card's own acceptance predicate ('no English literal on the panel bypasses i18n') and leaves the most visible half - one English heading per row on every build - untouched. It also does not obviously fit: the five group keys are only part of the 917 bytes.",
            "C - Raise the ceiling here. ⛔ Not available to me: it answers #8816 on behalf of everyone, by whoever happened to arrive first."
          ],
          "recommendation": "A. B is the only self-service option and it buys a green check by deleting the part of the fix that mattered most, which is the trade the gate's own message forbids ('do not widen it just to get a green check' has a mirror image: do not shrink the payload just to get one either). The red is honest: this PR really does want 917 bytes that the chunk really does not have."
        },
        {
          "question": "REUSE, judged on semantics (moot for the byte question, but you asked for per-key reasons, and the answer is no for all of them). appDesigner.objects is a STEP LABEL in AppCreationWizard, paired with appDesigner.stepObjectsDesc and an icon - rename that wizard step and my row heading follows. console.commandPalette.objects / .dashboards are CommandGroup headings owned by the palette's own grouping convention. console.breadcrumb.dashboards is a route breadcrumb segment. search.typeObjects and search.typeDashboards have NO call site at all - reusing a dead key would resurrect it under new semantics. chatbot.plan.countSeedData is 'sample data' LOWERCASE, a mid-sentence count bit in the plan strip; it is not even string-equal to my title-case row heading, so reusing it would visibly change the rendered English and redden my own control. console.ai.planBuilding/planBuilt are the plan CARD's bare status words with no {{app}} hole - reusing them would drop the app name from the header, which is a behaviour change. perm.facet.more and calendar.moreEvents are a permissions-facet and a calendar-event overflow counter. STRUCTURAL FINDING behind all of this: the pack has NO shared/common noun table. 'Objects' exists three times and 'Dashboards' three times under three different per-surface namespaces, and perm.facet.more and calendar.moreEvents are byte-identical duplicates of each other. Per-surface keys ARE this pack's convention; reuse would be the deviation, not the tidy-up.",
          "options": [
            "A - Accept per-surface keys as the convention and leave the pack's shape alone.",
            "B - Introduce a shared noun namespace (common.objects / common.views / ...) and migrate the existing duplicates onto it. That WOULD create a legitimate reuse target and would shrink the chunk repo-wide.",
            "C - Reuse across surfaces ad hoc without a shared namespace."
          ],
          "recommendation": "A for this PR - B is a real idea and it points at the same bytes #8816 is arguing about, but it is a pack-wide refactor touching many surfaces, it is nobody's card yet, and it is emphatically not a rider on a chat-panel localization fix. C is what the fence forbids and I did not do it. If you want B explored, it wants its own card; I did not file one because it is a design proposal, not a defect."
        },
        {
          "question": "PIECE 2's producer - CARRIED FORWARD UNCHANGED from round 1, still open and untouched. Nothing declares or emits a `verify` phase on `data-build-progress`: the published @objectstack/spec@17.4.0 types that channel's payload as `data?: unknown`, so the phase vocabulary is not in the contract at all, and the union 'structure'|'data'|'done' is declared only in objectui's own private ChatBuildProgress. Stronger than 'no evidence': that channel is emitted BY apply_blueprint via its own ctx.onProgress, and the card's own measurement puts the 111 seconds of verifying AFTER apply_blueprint returned - a returned tool cannot emit another frame, so the card's literal fix could not cover its own scenario even with a cooperative cloud.",
          "options": [
            "A - Route piece 2 back to cloud#1838 to pick the EMITTER and the channel first, then re-file the objectui receiver card against that decision.",
            "B - Land the `verify` vocabulary anyway: a receiver with no producer (the objectui#7383 class), which also still would not fix the measured 111 seconds.",
            "C - Re-scope piece 2 onto the channel that CAN speak during those 111 seconds - the tool cards, which already render verify_build and are already fully translated."
          ],
          "recommendation": "A, then reconsider C. Unchanged from round 1. I implemented none of the three."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed: `search.typeObjects` and `search.typeDashboards` exist in all ten packs but have NO call site anywhere in packages/ or apps/. They are dead-key candidates, which is check:i18n-dead-keys' own territory - that gate is report-only by design and this is pre-existing, not something my diff moved. Deleting them would also shave the very chunk #8816 is arguing about, so I am recording it there rather than acting on it. 承接者: objectui#8816's decision, whoever takes it - that is the one piece of work certain to touch these bytes.",
        "noted, not filed: `perm.facet.more` and `calendar.moreEvents` carry byte-identical values ('+{{count}} more') in all ten packs, as do three copies of 'Objects' and three of 'Dashboards'. Same observation as above and same 承接者 - it is duplication, not a defect, and it only becomes actionable if #8816 rules toward rationing.",
        "noted, not filed (carried forward): the 16 `labels?.x ?? 'English literal'` entries in ChatbotEnhanced's `L` object with no tt() layer. Unchanged from round 1. 承接者: 无.",
        "noted, not filed (carried forward): `vitest --reporter=basic` was removed in vitest 4 and now dies at startup with exit 1, reading exactly like a red run while never entering a test body. Unchanged from round 1."
      ]
    }

    Generated by Claude Code

  8. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    Contract review pointer — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3, huangyiirene). PR objectui#8888 @ head 5d50a3d0ae: PASS (not clearable/landable yet), verdict comment on the PR: #8888 (comment) — tier-verified isolated review (79 stamps). contract PASS; ⛔ not clearable: the card side never carried needs:contract-review (--pair exit 4, one-sided hang, F2) and Bundle Analysis is red on head by this diff's own i18n chunk cost (F1, budget decision = objectui#8816). No patch round owed; PR waits on #8816. Part of #7388 — card already needs-user-decision.


    Generated by Claude Code

  9. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    needs:contract-review cleared on card objectui#7388 and PR objectui#8888 (verdict #8888 (comment)). ⛔ Landing held: Bundle Analysis is red on head 5d50a3d0ae by this diff's own i18n-chunk cost (+519 B over the 455,000 ceiling; F1) — a budget decision, objectui#8816, ⛔ no ceiling raised here. The card side never carried the label (one-sided hang, --pair exit 4, F2): this seat hung it on the card and cleared both in one stroke so the timeline reads as a two-sided clear. Part of #7388; the card stays open and already carries needs-user-decision (A vs C). Flip when #8816 resolves and the check is green on head. Card state and assignee untouched.


    Generated by Claude Code

  10. os-litant commented on Sep 10, 2026

    @os-litant
    Contributor

    决策分析 —— 总监席第 21 场 · 批 #110 · 3/5(session_01QVMnxyWBx8cAQMsV6akDV9,2026-09-10T08:2xZ)—— 第 2 块:校验阶段该由谁来说、从哪条通道说

    Governing text:已发布 @objectstack/spec@17.4.0 对 data-build-progress 只声明 onProgress?: (part: { type: string; id?: string; data?: unknown })——phase 词表不在契约里;objectui#7383(无生产者的接收端 = 投机面)。不改协议(除非裁 A 后 cloud 侧把 phase 词表提进契约,那是另一张协议卡)。
    前提:ui 席 5607854883 已裁 B 出局;第 1 块 PR #8888 只等 objectui#8816。

    一句话问题:AI 在「建完之后再校验」的 111 秒里,聊天面板仍写着「正在构建…」;而发进度的那条通道在校验开始前就已经关了(发送方 apply_blueprint 已返回),所以「让面板认识 verify 这个阶段」这个字面修法救不了这 111 秒。

    选项 × 真实代价

    做什么 客户可感知的后果
    A 回到 cloud#1838 侧先定发送方与通道(apply_blueprint 返回后谁还能发进度帧、发在哪),再据此重立 objectui 接收端卡 多一跳;接收端对着真实生产者写
    C objectui 侧改用 111 秒里仍在说话的通道(工具卡:已渲染 verify_build、chatbot.tool.* en/zh 各 35 键已全译),让面板反映「构建后校验进行中」 不动 cloud;但「校验中」是从工具卡状态推断的

    业务含义直译:A=「先定谁来喊、从哪喊,再装喇叭」;C=「用现成的广播喊」。

    四轴:① A 契约先行(phase 词表要么进契约要么明确不进),避免 objectui 私有枚举与 cloud 各说各话;C 是消费端推断,长期两份真理。② 拉动实测:111 秒 / 9 次工具调用盯着一个说错话的转圈。③ A 响亮(契约声明 phase,未知值可 warn);C 推断错了是静默错标签。④ A 多一跳但不新增面;C 是一次产品设计(那 111 秒界面该说什么)。

    推荐:A(并把「apply_blueprint 返回后通道已关」这条事实随路由送到 cloud#1838);回退 C。
    置信缺口:cloud 不在本会话仓库范围,「apply_blueprint 是发送方」是执行席读数的转述。

    裁后执行:裁 A ⇒ 本卡第 2 块 pm:blocked + Blocked-by: objectstack-ai/cloud#<n>(cloud 席立卡;cloud 席现空缺,由可达席或您本人立);第 1 块 PR #8888 只等 #8816。裁 C ⇒ ui 席 pm:queue,先出一版设计说明再施工。

    os-decision-facets

    • ① 项目长远合理性:A 契约先行,避免两份 phase 真理。
    • ② 实际业务拉动:111 秒错标签实测。
    • ③ 防 AI 犯错:A 响亮;C 推断错则静默。
    • ④ 创业阶段不扩散:A 不增面;C 是产品设计。
      推荐 A;置信缺口:cloud 侧发送方为转述。

    Generated by Claude Code

  11. os-litant commented on Sep 10, 2026

    @os-litant
    Contributor

    Recorded, not ruled — director seat, summon #21 (session_01QVMnxyWBx8cAQMsV6akDV9, 2026-09-10T08:4xZ). Decision batch #110 item 3 presented piece 2 (A: route the emitter question back to cloud#1838 · C: re-scope onto the tool-card channel) at 5615377764. The maintainer's reply in the director chat, verbatim and untranslated: 「7388 已经转给其他人处理」. ⇒ This card is handed off by the maintainer; the director seat records it and does not follow it (precedent: the 「维护者移交他人、本席只记不跟」 rows on the seat post). ⛔ No A/C letter recorded; labels, assignee and body untouched. Piece 1 (PR #8888) still lands behind objectui#8816, ruled A this summon — that half is unaffected by the handoff.


    Generated by Claude Code

  12. os-tesla commented on Sep 12, 2026

    @os-tesla
    Collaborator

    State set to pm:awaiting-maintainer — handed off by the maintainer on 2026-09-10; the decision inbox is closed for this summon (director seat, 2026-09-12)

    The maintainer's word on this card is recorded at 5615811546 (summon #21, verbatim 「7388 已经转给其他人处理」): piece 2 (who emits the verify-phase progress after apply_blueprint returns, and on which channel) is with a person outside the seat loop. It has sat in the decision inbox since with no letter to record, which is the same shape as objectstack#17147 this summon; both leave the inbox the same way.

    Maintainer-action: piece 2 is with the person the maintainer handed it to; exit when a card or PR (cloud#1838's side, or an objectui re-scope) names the emitter and channel, or the maintainer says so. Piece 1 (PR #8888 behind objectui#8816, ruled A) is unaffected.

    State: needs-user-decision → pm:awaiting-maintainer; bug / domain:ui / i18n / priority:p2 kept; assignee untouched.


    Generated by Claude Code

  13. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    Contributor

    Closed on the maintainer's word: piece 1 landed; piece 2 stays with the person the maintainer handed it to

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-27T03:14Z.

    Provenance. The instruction is the maintainer's. The words, verbatim: 「Governed Surface Queue Guard 已加;9430 关;7696 关;objectui#7388 关;」 and 「2443 关」. Where: the maintainer's chat with this session (session_01W89enF2dYV7K4N2Fbfj33f), 2026-09-27. It answered the second batch of pm:awaiting-maintainer cards, which this seat presented card by card.

    • Piece 1, delivered: PR objectui#8888 (merged 2026-09-10T07:52Z) localized the build-progress panel's own copy. On objectui origin/main the panel's strings go through t('chatbot.build.*').
    • Piece 2, not tracked here: who emits a verify-phase progress frame after apply_blueprint returns, and on which channel. The maintainer handed it off on 2026-09-10 (「7388 已经转给其他人处理」, recorded at 5615811546). Today extractBuildProgress (packages/plugin-chatbot/src/mapMessages.ts:841) still reads an unknown phase as structure. If the emitter is defined later (cloud#1838's side), the objectui receiver is a new card that names that producer.
    • The assignee (os-zhuang) is left as it was.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seati18npriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions