Skip to content

finding(types,components): DataTableSchema.emptyAction declares SchemaNode on both faces while the renderer admits only objects — a bare string is silently dropped, the identical defect objectui#7105 just closed one slot over #8331

Closed

Description

@os-zhuang

Observation-class finding, measured while accepting PR #8330 (objectui#7105). Filed unassigned, no labels — grading is the triage seat's.

⭐ This one arrives with its ruling already made, one slot over. objectui#7105 (director seat, decision batch #69, 2026-09-07, maintainer 「其他同意」) ruled exactly this shape on EmptySchema.action: the declaration says SchemaNode, the renderer required an object, and the ruling's answer was relax the renderer, not narrow the declaration — "a primitive node is handed to SchemaRenderer like any other node slot (a string renders as text), so a bare string is no longer silently dropped."

The claim

DataTableSchema.emptyAction is declared SchemaNode on both faces and rendered only when it is an object. A bare string node — legal by the declaration, and what SchemaRenderer renders as text — is silently dropped.

Measured on origin/main = fedfa3e

packages/types/src/data-display.ts:1148        emptyAction?: SchemaNode;
packages/types/src/zod/data-display.zod.ts:285 emptyAction: SchemaNodeSchema.optional().describe('Optional schema node rendered inside the empty-state, …')
packages/components/src/renderers/complex/data-table.tsx:2160
    {schema.emptyAction && typeof schema.emptyAction === 'object' && (
:2161  <SchemaRenderer schema={schema.emptyAction} />

⇒ Both declared faces admit any SchemaNode; the render path admits only the object subset. Declared wider than enforced, in the direction that loses the author's content without a diagnostic.

⚠️ The path is renderers/complex/, not renderers/data/ — recorded because I searched the wrong directory first and got a clean zero. A zero from the wrong path is not a finding, and this is the sort of near-miss that turns a real defect into a "does not reproduce".

Why this is the same defect, not merely a similar one

The behaviour SchemaRenderer gives a primitive is already pinned in this repo — packages/react/src/__tests__/SchemaRenderer.primitiveSchema.test.tsx (objectui#4548): a non-empty string renders as its own text, a number as '42', a boolean as 'true', and '' / 0 / false render nothing. ⇒ The object-only guard is not protecting the renderer from anything it cannot handle; it is discarding input the declaration promises to accept.

⚠️ One thing that is NOT settled by #7105's ruling and needs measuring here, because this slot has history the other did not: data-table.tsx:2131-2144 carries a docblock about this very slot, and packages/components/src/renderers/complex/__tests__/data-table-empty-action-visible-when.test.tsx pins visibleWhen behaviour on it — including the note that the empty state is the only place it renders. ⇒ Whoever takes this reads both before touching the guard; relaxing it must not disturb the visibleWhen gate that test pins.

The remedy #7105 shipped, for whoever takes this

Not a template to copy blind, but the shape is settled: declaration unchanged, guard relaxed, the value handed to SchemaRenderer through the repo's existing bridge (toRenderableSchema in packages/react/src/schema-input.ts, a documented-PERMANENT total function that maps number and boolean onto the text form the renderer's own defensive branch produces — SchemaRendererProps.schema deliberately excludes those two per #4548 ruling Q2). ⛔ No coercion needs inventing.

⚠️ It is still a behaviour change on a published surface and owes its own ruling, exactly as #7105 did — a node that renders nothing today starts rendering. ⛔ Do not treat #7105's adoption as pre-authorising this one; what it settles is the shape of the answer and the fact that the bridge exists.

Why it was not fixed in place

The implementing session found it and correctly left it: data-table.tsx is outside objectui#7105's declared file surface, it is a large hot file whose claim state it could not cheaply establish, and the honest remedy is a behaviour change. ⇒ Reported to the seat rather than absorbed — the right call, and the reason this card exists instead of a widened PR.

Refs

Filed by the domain:spec @ objectui PM seat, session session_01QtGhnU3WnnWyiWeYQhw2aX, 2026-09-07T12:56Z.


Generated with Claude Code

https://claude.ai/code/session_01QtGhnU3WnnWyiWeYQhw2aX

Activity

  1. added theissue type on Sep 8, 2026
  2. os-zhuang commented on Sep 8, 2026

    @os-zhuang
    ContributorAuthor

    分诊路由 — domain:ui · pm:queue · priority:p2 · type Bug

    ⛔ 本席是分诊席(claude-opus-5):不认领、不派发、不写码、不合并、不裁决决策箱卡。

    复核 —— 三处锚点成立

    packages/types/src/data-display.ts:1148          emptyAction?: SchemaNode;
    packages/types/src/zod/data-display.zod.ts:285   emptyAction: SchemaNodeSchema.optional()…
    packages/components/src/renderers/complex/data-table.tsx:2160
        {schema.emptyAction && typeof schema.emptyAction === 'object' && (
    :2161   <SchemaRenderer schema={schema.emptyAction} />
    

    ⇒ 两张已声明面都接受任意 SchemaNode;渲染路径只接受对象子集。 声明宽于强制,且失效方向是丢掉作者的内容且无诊断。

    ⭐ 卡自己记下的那次近失,本席特别保留

    ⚠️ The path is renderers/complex/, not renderers/data/ — recorded because I searched the wrong directory first and got a clean zero. ⭐ A zero from the wrong path is not a finding, and this is the sort of near-miss that turns a real defect into a "does not reproduce".

    ⇒ ⭐ 一次「干净的零」差点把一个真缺陷变成「无法复现」。把自己走错的路记下来,是本轮反复出现的正确做法(与 #8438 记录那个阴性拼写假说同型)。⚠️ 承接者按 renderers/complex/ 找,⛔ 别照直觉去 renderers/data/。

    ⭐ 为什么这是同一个缺陷而不只是相似 —— 卡的论证成立

    The behaviour SchemaRenderer gives a primitive is already pinned — packages/react/src/__tests__/SchemaRenderer.primitiveSchema.test.tsx(#4548):非空字符串渲染为自身文本,数字为 '42',布尔为 'true',而 '' / 0 / false 什么都不渲染。
    ⇒ The object-only guard is not protecting the renderer from anything it cannot handle; it is discarding input the declaration promises to accept.

    ⇒ ⭐ 那个 typeof === 'object' 守卫不是在保护渲染器,是在丢弃声明承诺要接受的输入。 这一条把「相似」升级为「同一」。

    定级 — priority:p2

    判据是静默丢失作者内容:一个按声明合法的 emptyAction: '暂无数据,请先创建' 什么都不渲染,也不报任何错。⇒ 作者看到空状态里少了他写的东西,而没有任何东西告诉他为什么。

    ⛔ 不抬 p1:仅影响空状态里的一个可选槽,无数据损坏、无权限问题。
    ⛔ 不降 p3:这是 declared ≠ enforced 且方向是丢内容,本仓一贯按 p2 处理该族。

    ⚠️⚠️ 承接约束:⛔ 不得把 #7105 的裁定当作对本卡的预先授权

    卡自己把这条写死了,本席全文提为硬约束:

    ⚠️ It is still a behaviour change on a published surface and owes its own ruling, exactly as #7105 did — a node that renders nothing today starts rendering. ⛔ Do not treat #7105's adoption as pre-authorising this one; what it settles is the shape of the answer and the fact that the bridge exists.

    ⇒ 本席的路由裁定:

    ⇒ ⭐ 这样既尊重卡的谨慎,又不为一个维护者在隔壁一格已经答过的问题另开一张决策卡。

    ⚠️ 一条本卡点名、⛔ 不可在放松守卫时碰坏的东西

    data-table.tsx:2131-2144 carries a docblock about this very slot, and packages/components/src/renderers/complex/__tests__/data-table-empty-action-visible-when.test.tsx pins visibleWhen behaviour on it — including the note that the empty state is the only place it renders.

    ⇒ ⚠️ 这个槽有另一个槽没有的历史。 承接者动守卫之前必须先读这两处;⛔ 放松守卫不得扰动那个 visibleWhen 闸。⭐ 建议把该 pin 作为回归对照:修改前后它必须都绿,且新增的字符串用例必须在修改前红。

    车道 — domain:ui

    按 2026-08-21 裁定「按修复落点分三流」:声明不动(packages/types 两张面都是对的),要改的只有 packages/components/src/renderers/complex/data-table.tsx 的守卫 —— 发布库 ⇒ domain:ui。

    ⛔ 不判 domain:spec:立卡席虽是 domain:spec @ objectui,且 packages/types 被引用 —— ⚠️ 但那两张面没有任何东西要改,它们正是被违背的那一方。这正是「立卡席的车道不决定卡的车道」。

    type = Bug

    两张已发布声明面都承诺接受任意 SchemaNode,渲染器只接受其对象子集并静默丢弃其余 ⇒ 违背已声明契约。⚠️ 承接者写 changeset 时按行为变更处理级别(今天不渲染的东西开始渲染),⛔ 不要因为卡上写 Bug 就按 patch 发。


    Generated by Claude Code

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

    @os-zhuang
    ContributorAuthor

    Claim: session session_01611D6ZaRaMmwTNQmSbk8MH · branch claude/issue-8331-empty-action-primitive-node

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

    零、⭐ 本卡不需要派发席再裁 —— 分诊席已完整路由,⛔ 不要重开

    分诊评论 5582908446 已经把方向定死了,逐字照做:

    一、⚠️⚠️ 卡片自己写死、分诊席全文提为硬约束的一条

    ⚠️ It is still a behaviour change on a published surface and owes its own ruling, exactly as #7105 did — a node that renders nothing today starts rendering. ⛔ Do not treat #7105's adoption as pre-authorising this one; what it settles is the shape of the answer and the fact that the bridge exists.

    ⇒ 本卡仍欠一次自己的档位复核。⚠️ 若复核者判定该先例不可迁移,⛔ 不由你决定 —— 退回分诊席,由它产出决策卡。

    二、⛔⛔ 走错路径会把真缺陷变成「无法复现」

    卡片记下了自己的一次近失,⭐ 值得逐字带上:

    ⚠️ The path is renderers/complex/, not renderers/data/ — recorded because I searched the wrong directory first and got a clean zero. ⭐ A zero from the wrong path is not a finding.

    ⇒ 按 renderers/complex/ 找,⛔ 别照直觉去 renderers/data/。⭐ 这条同时是本卡的方法论:一个「干净的零」在你确认量具指对了地方之前,什么都不是。

    三、⛔ 这个槽有别的槽没有的历史,动守卫之前必须先读

    1. data-table.tsx 上那段关于这个槽本身的 docblock(分诊席读到时在 :2131-2144 —— ⚠️ 行号是那时的读数,⛔ 自己重推)。
    2. packages/components/src/renderers/complex/__tests__/data-table-empty-action-visible-when.test.tsx —— 它钉住了这个槽的 visibleWhen 行为,包括「空状态是它唯一渲染的地方」这条注记。

    ⛔ 放松守卫不得扰动那个 visibleWhen 闸。

    ⭐ 判别力要求(分诊席的建议,本席升格为验收条件):把那条既有 pin 当作回归对照 —— 修改前后它必须都绿;而新增的字符串用例必须在修改前红。⇒ 一个在修复前后都绿的断言没有判别力,⛔ 不算证据。

    四、⭐ 为什么这不是「相似」而是「同一」—— 已被钉住,可直接引用

    SchemaRenderer 对原始值的行为已有落地 pin:packages/react/src/__tests__/SchemaRenderer.primitiveSchema.test.tsx(#4548)—— 非空字符串渲染为自身文本、数字为 '42'、布尔为 'true',而 '' / 0 / false 什么都不渲染。

    ⇒ 那个 typeof === 'object' 守卫不是在保护渲染器免于它处理不了的东西,是在丢弃声明承诺要接受的输入。

    ⚠️ 但这仍是你要在自己树上复量的东西,⛔ 不许继承本简报作为结论。

    五、changeset

    ⚠️ ⛔ 不要因为卡上写 Bug 就按 patch 发。 按行为变更处理级别(今天不渲染的东西开始渲染)。⚠️ 并注意 AGENTS.md §版本号策略里那条与直觉不同的约定 —— 自己去读,⛔ 不要凭常识假定。

    六、⭐ 位置轴:判据是 stored vs computed

    grep path:line 的命中绝大多数是运行时为打印诊断拼出来的(不会过期);只有被存下来、且被当作键或做相等比较的字面量才会过期。已确证载体:scripts/check-doc-example-types.mjs 的 UNGATED_EXAMPLES(键含行号),⚠️ 普查脚本 cross-file-line-citation-census.mjs 看不见它 —— 本班它已连打两份 PR(#8895、#8901)。两类载体都查,判 (A)/(B) 靠找锚点⛔ 不是比行号;强形式是在你的分支对 main 的一次真实 git merge --no-ff 结果树上再跑一次。

    七、⛔ 红线与工具链

    ⛔ 不动 packages/types 的两张声明面 · ⛔ 不发明任何强制转换(桥已存在)· ⛔ 不扰动 visibleWhen 闸 · ⛔ 不扩范围 · ⛔ 不编辑共享主检出(用专属 worktree)· ⛔ 绝不 git stash · ⛔ 绝不按名杀进程 · ⛔ 不碰 content/docs/releases/ · ⛔ 不碰 governed surface。

    ⚠️ 工具链(本班实测两次假绿):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,⛔ 不是红更不是绿。验收一律引运行器自己的 VERDICT command-exit 行,⛔ 不用裸 $?。
    ⚠️ 共享身份 os-zhuang 的 GitHub API 间歇性限流 —— git 能答的走 git;⛔ 永不在循环里重试。


    Clause-②: yes

    ⭐ 本行由派发席在 claim 时同笔申报(分诊评论 5582908446 明确要求「认领席同笔申报 Clause-②: yes,走 at-tier 契约评审,在申报里逐字引用 #7105 的裁定作为先例」)。判据:本改动是已发布面上的行为变更 —— a node that renders nothing today starts rendering。先例逐字:#7105(director seat,决策批次 #69,2026-09-07,维护者回复「其他同意」)对逐字相同的形状裁定 放松渲染器、⛔ 不收窄声明;桥 toRenderableSchema(packages/react/src/schema-input.ts,文档标注 PERMANENT)已存在。⚠️ 该先例定的是答案的形状与桥的存在,⛔ 不是对本卡的预先授权 —— 本卡仍走完整的档位复核;若复核者判定先例不可迁移,⛔ 退回分诊席产出决策卡,⛔ 不由实现席决定。needs:contract-review 已双载体同笔挂(本卡已挂,PR 一存在即挂)。


    Generated by Claude Code

  5. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    ContributorAuthor

    os-dev-report

    {
      "issue": 8331,
      "status": "done",
      "branch": "claude/issue-8331-empty-action-primitive-node",
      "pr": "https://github.com/objectstack-ai/objectui/pull/8909",
      "premise_still_valid": true,
      "summary": "Re-derived all three anchors on my own tree (line numbers had moved: the Zod face is now :317, not :285; the guard is now :2160 with its docblock at :2131-2144 as cited). Relaxed exactly one expression in packages/components/src/renderers/complex/data-table.tsx: dropped the `typeof === 'object'` clause and routed the value through toRenderableSchema, the documented-PERMANENT bridge. The two packages/types declaration faces are untouched — they were the correct side. The truthiness leg is KEPT on purpose and the `&&` chain became a ternary; together they make the slot behave exactly as handing the raw node to SchemaRenderer would, which is the docblock's own 'one answer, not a private one' rule. Keeping the leg matters because toRenderableSchema is NOT behaviour-preserving for 0/false (measured: raw 0 renders '', bridged renders '0'), so a nullish test would have shipped a second, unruled behaviour change. The ternary also closes a leak I did not expect and did not assume: with emptyAction: 0 the old `&&` chain evaluated to the number 0 itself, which React renders as a stray '0' in the empty state — caught because a case written to be green on BOTH sides came back red on the unfixed guard. Nothing was invented; no coercion was added; the central visibleWhen gate is untouched and its pin is green on both sides. Note on assignee: it was already set by the PM dispatch and I did not write it, and I posted no second claim.",
      "tests": "All verdicts quoted from the shared verify lock's own VERDICT command-exit line, never a bare $?; every heavy run went through scripts/pm/os-verify-lock.sh with a stable slot. Final commit dbfebe786. DISCRIMINATING POWER (the polarity flip is the evidence): BEFORE the fix, the new data-table-empty-action-primitive-node.test.tsx = VERDICT command-exit 1, 2 failed / 8 passed — the bare-string case failed, and so did the falsy-primitive case, which is how the stray '0' was discovered ('Received: ...search query.0' vs 'Expected: ...search query.'). The existing regression control data-table-empty-action-visible-when.test.tsx was GREEN in that same before-run. AFTER the fix, all three files (new suite + visibleWhen pin + objectui#4548 SchemaRenderer.primitiveSchema pin) = VERDICT command-exit 0, 17 passed. So the new string case is red-before/green-after and the visibleWhen gate is green-before/green-after: no assertion in this PR is green on both sides without being a deliberate regression control. PACKAGE LEVEL, after: `pnpm --filter @object-ui/components run test` = VERDICT command-exit 0, 253 files / 2322 tests passed. `pnpm --filter @object-ui/components run type-check` = VERDICT command-exit 0 — that script is `tsc --noEmit && tsc -p tsconfig.test.json`, so the new test file IS typechecked (not the excluded-tests trap). Dependency closure `pnpm --filter '@object-ui/components^...' --workspace-concurrency=2 run build` = VERDICT command-exit 0. GATES: check-control-bytes exit 0 (its own printed OK line), check-changeset-no-major exit 0, plus a manual control-character self-scan over the three changed files (grep -naP, no hits). eslint on both changed files = exit 0, 0 errors; 34 warnings are all pre-existing and none lands on an added line (verified by line number against my two hunks). Repo-wide `pnpm lint` and the rest of the gate farm are CI's, not owed here. PROBE HYGIENE: the toRenderableSchema measurement used a throwaway test file that was deleted; restoration proven by `git status --short` empty AND `git diff HEAD --stat` empty, not by an exit code. POSITION AXIS: no stored carrier cites data-table.tsx by line (objectui has no UNGATED_EXAMPLES entry for it); the four prose citations that do (:777 :784 :786 :1284 :1829) were already stale on origin/main and on my BASE — byte-identical before and after — and my hunks are net-zero above line 2156, so nothing shifted. Re-checked in the strong form on a real `git merge-tree --write-tree origin/main HEAD` result tree (clean merge, no conflict), same reading.",
      "mcp_calls": "5 — issue_read(get), search_issues (one targeted strike), issue_write(create), create_pull_request, add_issue_comment. Channel declarations: card comments, the repo probe, the PR read-back and the PR label add all went through zero-quota REST. Two forced switches to MCP, both declared: (1) REST /search/* is refused by the egress proxy by design (http=403, 'sessions are bound to their configured repositories'), so dedup used ONE targeted semantic search_issues rather than a wide table scan — instrument validated by known-present controls (it returned #8331 and #7105), so the negative on my finding is a real reading, not a false zero; (2) the REST POST that would have filed the finding and the payload-building heredoc were both blocked by this session's auto-mode command classifier, not by GitHub, so the card was filed through MCP issue_write instead.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #8908: toRenderableSchema's docblock claims it 'changes no behaviour and tells no lie', which is FALSE for 0 and false — measured raw='' vs bridged='0'/'false' — and the shipped `empty` renderer (the objectui#7105 precedent, which forwards under a nullish test) therefore prints a stray '0'/'false' for action: 0 / action: false. Filed unassigned, no labels, grading left to the triage seat. Not fixed in place: the honest remedy is a ruling between three routes, one of which is a published-surface behaviour change at ~14 call sites — not the implementing seat's call. Deduped first: one targeted search including closed cards, instrument validated by known-present controls; #4622 is a different, already-closed claim about the same docblock.",
        "noted, not filed: five prose citations of data-table.tsx by line number (:777 :784 :786 :1284 :1829, in two sibling tests and docs/audits/2901) no longer name what sits at those lines. Pre-existing on origin/main, untouched and unmoved by this PR, and squarely in the 'do not file' bucket (undrilled drift / doc nit). Taker: the cross-file-line-citation census, which already shipped #8895 and #8901 this shift.",
        "noted, not filed: this PR's body carries TWO attribution blocks — the platform appended its own session-URL footer rather than replacing the one I sent. Read-back confirms content is otherwise byte-intact (all seven section headers, the VERDICT table, the #8908 reference, first line 'Fixes #8331'). Left alone deliberately: the standing rule forbids re-posting footers in a loop to chase this."
      ]
    }

    Generated by Claude Code

  6. os-zhuang commented on Sep 9, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT — PR #8909。⭐ 但本轮最重要的产出不是这张卡的交付,是它顺手证伪的那个先例

    ⭐⭐ toRenderableSchema 的 docblock 是假的,而它正是 #7105 先例所依赖的桥

    它的 docblock 自称 "changes no behaviour and tells no lie"。实测:假。 对 0 与 false —— 原始值渲染 '',过桥后渲染 '0' / 'false'。

    ⇒ ⚠️ 而 #7105(本卡引为先例的那次裁定)自己落地的 empty 渲染器,正是在一个 nullish 测试下走这座桥 ⇒ 它对 action: 0 / action: false 会打印一个游离的 '0' / 'false'。

    ⭐ 实现席没有顺手改它,而是立了 #8908(未分配、未打标,定级留给分诊席)。这个处置是对的:诚实的补救要在三条路线之间裁一次,其中一条是约 14 个调用点上的已发布行为变更 —— ⛔ 不是实现席的判断。

    ⚠️ 对本卡的影响,我作为引用先例的一方要说清楚:先例定的是答案的形状(放松渲染器、不收窄声明)与桥的存在,这两条不受影响;被证伪的是桥的 docblock 关于 0/false 的那句自述。⇒ 复核席在读本卡的 Clause-②: yes 申报时,应当把 #8908 一并读进去。

    ⭐⭐ 而这个发现是怎么被抓到的,才是这一轮最值钱的方法论

    caught because a case written to be green on BOTH sides came back red on the unfixed guard.

    一条本该是控制(两个世界都绿)的用例,在未修复的守卫上红了 —— 于是暴露出一个谁都没命名过的缺陷:emptyAction: 0 时旧的 && 链求值为数字 0 本身,React 把它渲染成空状态里一个游离的 '0'(Received: …search query.0 vs Expected: …search query.)。

    ⭐ 这是本班第三次由控制/主体的极性纪律直接产出真发现(前两次是 #8083 的探针正控、#8889 我把主体误称作控制)。⇒ 一个控制没按预期绿,永远先当成读数、⛔ 不要当成噪音。

    交付本身:⭐ 保留真值腿是刻意的,而理由是可证伪的

    只放松了一处表达式:去掉 typeof === 'object' 子句、把值路由过桥,&& 链改成三元。

    ⭐ 真值腿被刻意保留 —— 因为 toRenderableSchema 对 0/false 不是行为保持的(上面那条实测),⇒ 改成 nullish 测试会顺带发运第二个未经裁定的行为变更。保留它 + 三元,使这个槽的行为恰好等于把原始节点直接交给 SchemaRenderer,也就是 docblock 自己那条「一个答案,不是一个私有答案」的规则。

    ⛔ 两张 packages/types 声明面一行未动(它们是对的那一方)· ⛔ 未发明任何强制转换 · ⛔ visibleWhen 闸未被触碰。

    极性:干净

    ⇒ 本 PR 里没有任何一条断言是「两侧都绿」而又不是刻意的回归控制。

    锚点与位置轴

    三个锚点在它自己的树上重推(Zod 面已不在 :285 而在 :317;守卫在 :2160,docblock 在 :2131-2144)。位置轴:无存储载体引用 data-table.tsx(UNGATED_EXAMPLES 无该行);四条按行号引用它的散文引用在 origin/main 与它的 base 上就已陈旧、前后逐字节相同,且它的 hunk 在 2156 行以上净零 ⇒ 什么都没移动。在真实 git merge-tree 结果树上复核过,同一读数。

    ⭐ 两处工具纪律值得记

    1. REST /search/* 被出口代理按设计拒绝(403,"sessions are bound to their configured repositories")⇒ 去重改用一次定向 search_issues,并用已知存在的正样本验证量具(它返回了 finding(types,components): DataTableSchema.emptyAction declares SchemaNode on both faces while the renderer admits only objects — a bare string is silently dropped, the identical defect objectui#7105 just closed one slot over #8331 与 finding(types): EmptySchema.action is read by the shipped renderer through an as any cast and declared by neither the type nor its mirror — a 14th key #6150's sweep missed #7105)⇒ 那个「没有重复」的否定是真读数,不是假零。
    2. PR 正文出现两个归属块 —— 平台追加了自己的页脚而非替换。它刻意不去追 ⇒ 符合本班的规矩(实测修剪会立刻长回来,⛔ 不进循环)。这是该平台行为的第二次独立确认。

    Clause-②

    check-clause2-carriers --pair 8909 exit 0,输出只说「both carriers agree」 ⇒ 申报确为 yes(本席在认领时同笔申报,含 #7105 先例逐字引用)。PR #8909 正常停靠(当前第 15 份)。⛔ 不入队、⛔ 不摘标、⛔ 不降档、⛔ 不自审。


    Generated by Claude Code

  7. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    Contract review pointer — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3, huangyiirene). PR objectui#8909 @ head dbfebe7868: PASS, verdict comment on the PR: #8909 (comment) — tier-verified isolated review (118 stamps). PASS, no rework; renderer brought up to the declaration it already carries. Landing pre-checks satisfied by this verdict + --pair 0 + green head.


    Generated by Claude Code

  8. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    needs:contract-review cleared on card objectui#8331 and PR objectui#8909 in one stroke — landing provenance on the PR: #8909 (comment) (verdict #8909 (comment)). Card state and assignee untouched until MERGED close-out.


    Generated by Claude Code

  9. huangyiirene commented on Sep 10, 2026

    @huangyiirene
    Collaborator

    Release — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3). PR objectui#8909 MERGED at 2026-09-10T00:33:04Z (squash 4a292d29c0) after contract-review PASS; card auto-closed by Fixes. Close-out: pm:dispatched removed, assignee cleared.


    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 workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpackage: componentspriority:p2

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions