You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finding(plugin-dashboard): a client-i18n-bundle sub-caption still cannot reach a dataset-bound KPI tile — tWidgetSubCaption's bundle limb needs dashName, which DatasetWidget is given by neither dispatch site #8889
⚠️控制必须会动:一个同时写了 options.description 的 tile,在两个世界里都必须渲染出bundle 的值盖过作者值(这是肢 2 的既定语义:「a bundle entry always wins over an inline map and the two channels can never disagree」)。如果你的控制在主体坏掉时也红,它不是控制。
⭐ 而且它会直接违反这个字段自己的既定不变量 —— tWidgetSubCaption 的 docblock 写着「a bundle entry always wins over an inline map and the two channels can never disagree」。一个不变量需要一个唯一的决定点来保证。
⚠️两条路线都必须同时改两个 dispatch site —— 这不是区分点,是对任何一条的硬要求。objectui#4614 就是「只改一个面、另一个面静默照旧」的原始教训,#7293 的执行席正因为它才选择在组件内读键。⛔ 只改一个 = 不算修好。
{
"issue": 8889,
"status": "done",
"branch": "claude/issue-8889-dataset-widget-subcaption-bundle-limb",
"pr": "https://github.com/objectstack-ai/objectui/pull/8907",
"premise_still_valid": true,
"summary": "Route 2 as ruled. A new hook packages/plugin-dashboard/src/widgetSubCaption.ts (useWidgetSubCaption) owns the authored-plus-bundle composition, DashboardRenderer's private useCallback now delegates to it, and BOTH dispatch sites pass the RESOLVED answer to DatasetWidget as a new subCaption prop (string, or null meaning \"a surface resolved it, to nothing\", or omitted meaning \"no surface at all — resolve the authored limb locally\", which preserves objectui#7293 for standalone hosts). The card's premise held on origin/main: both sites passed only widget and dataSource, and the bundle limb terminated at the two inline getComponentSchema arms. Only the card's LINE NUMBERS were stale (PR #8887 had moved DatasetWidget.tsx); they were re-derived and this PR cites anchors, not lines. The server-overlay channel (translateDashboard) is not in the diff. Zero i18n keys added — this card connects an existing key's path, and the i18n-locales chunk is defined as packages/i18n/ only, where this diff changes zero bytes.",
"tests": "type-check: pnpm --filter @object-ui/plugin-dashboard type-check — VERDICT command-exit 0 (spelled type-check in this repo; log echoes both tsc invocations). | package suite: pnpm exec vitest run packages/plugin-dashboard/ (from repo root) — VERDICT command-exit 0, Test Files 102 passed (102), Tests 916 passed (916). | build closure: pnpm --filter '@object-ui/plugin-dashboard^...' build — VERDICT command-exit 0. | eslint: pnpm exec eslint . in packages/plugin-dashboard — exit 0, 132 files, 0 errors, 450 pre-existing warnings, 0 of them from the two new files. | gates: check-changeset-presence exit 0 (1 changeset for 3 published source files); check-governed-queue-guard --test over all 6 paths exit 0 NOT GOVERNED; check:control-bytes exit 0 plus a direct control-range scan of the 6 paths (no hits); check:unreferenced-sources exit 0; check:i18n-keys exit 0; check:i18n-dead-keys exit 0 (report). | NOT MEASURED: check:eager-closure exits 2 = PREREQUISITE NOT MET (needs apps/console/dist/eager-closure.json, i.e. a console build). Read as neither red nor green; declared to CI. Reasoned separately: the i18n-locales chunk is defined in apps/console/vite.config.ts as packages/i18n/ only and this diff changes zero bytes there. | ABLATION leg A (both dispatch sites reverted): Tests 6 failed | 29 passed (35). The 6 failures are exactly S1-S4 across both surfaces. All C controls, all of DatasetWidget.subCaption.test.tsx (#7293 pins) and all of DashboardRenderer.metricSubCaption.test.tsx (the inline arm, including its (f) bundle-beats-inline-map direction) stayed GREEN — so the controls discriminate. | ABLATION leg B (ONLY DashboardGridLayout reverted = the one-site fix objectui#4614 warns about): Tests 3 failed | 32 passed (35), the 3 being the grid surface's S cases alone. A one-site fix does not pass. | ABLATION mechanics: each leg proved the mutation reached disk BEFORE reading anything (marker count asserted 1 to 0 per file, run aborts otherwise); restore is git checkout HEAD -- ABSOLUTE_PATH inside a trap on EXIT INT TERM, proven by git diff HEAD being empty AND each blob hash compared against its HEAD blob (empty hash treated as failure). Tree verified clean at 676d6be4b afterwards. | VOID RUN, recorded not hidden: the first leg-A attempt passed --reporter=basic, which vitest 4 does not have. Its exit 1 was a startup error that never reached a test body — read as NOT MEASURED and re-run with the correct invocation, not counted as a red. | PUBLISHED SURFACE (the reading the dispatch demanded): built dist before and after and compared every .d.ts by sha256. dist/index.d.ts is BYTE-IDENTICAL (e76ecfb5655d0727... on both sides) and mentions DatasetWidget zero times; package.json declares exactly one export path, \".\", resolving to it. dist/DatasetWidget.d.ts changed (gains subCaption?: string | null) and dist/widgetSubCaption.d.ts is new — both shipped via files: [\"dist\"] but NOT resolvable through the exports map. | Clause-② check: PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/check-clause2-carriers.mjs --pair 8907 — exit 0, \"both carriers agree\".",
"mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe returned 200 at round start) or plain git; no mcp__github__* tool was called.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: the census census:cross-file-line-citations (report-only, exit 0) was run on f52a9d7ad in a throwaway detached worktree and again on this branch and diffed. This diff's line shifts move the offsets it prints for a handful of PROSE citations into DatasetWidget.tsx / DashboardGridLayout.tsx and flip three rows from non-substantive/unreported to drifted. Position axis verdict is (B), computed/prose only: the confirmed STORED carrier, UNGATED_EXAMPLES in scripts/check-doc-example-types.mjs, has ZERO rows into any file in this diff (none of the three edited files carries an @example block). Not repaired, deliberately — every one of those anchors is a generic identifier the census matched by coincidence (dataKey, dataSource, element), several already pointed at unrelated code on main before this branch existed, and two of the three sit in packages/types; writing fresh numbers from a coincidental token match would state a precision those citations never had. Successor: whoever burns down the repo-wide 400-plus drifted-citation backlog. origin/main is still f52a9d7ad, so this branch's tree IS the merge --no-ff result tree and the census reading is that reading.",
"noted, not filed: PR #8907 and the open draft PR #8905 both modify packages/plugin-dashboard/src/DatasetWidget.tsx in the metric-tile region (#8905 is objectui#8894 part (b), +41 lines there). Whichever lands second may need a textual merge in that block. Landing-order note for the PM, not a defect. Successor: PM sequencing.",
"noted, not filed: DashboardGridLayout still has no dashboard filter bar, so it forwards widget rather than the sibling's effectiveWidget — its own comment says so and that asymmetry is unchanged here. Successor: none queued; it would ride the next card that gives that surface a filter bar.",
"reported, not filed: the dispatch's named CONTROL (\"a tile that also declares options.description must render bundle-over-authored\") cannot be green before the fix on the dataset path — that behaviour IS the defect, so any such assertion moves with the subject. It is carried as subject S3/S4 instead, and the genuinely discriminating controls are C1 (limb 1 survives, i.e. #7293 not replaced), C2 (no node when neither channel speaks), C3 (no-surface path) and the untouched inline-arm pins. Both ablation legs confirm those stay green."
]
}
AMENDED — supersedes the report on 676d6be. Head is now a21ad9ec8.
{
"issue": 8889,
"status": "done",
"branch": "claude/issue-8889-dataset-widget-subcaption-bundle-limb",
"pr": "https://github.com/objectstack-ai/objectui/pull/8907",
"premise_still_valid": true,
"summary": "AMENDED after the CI red on 676d6be4. Head is now a21ad9ec8. The implementation is unchanged: route 2, one decision point (useWidgetSubCaption), both dispatch sites pass the resolved answer, three-state subCaption prop, server-overlay untouched, zero i18n keys. The repair is to the renderer-consumed-keys census in packages/sdui-parser, which watches plugin-dashboard SOURCE TEXT from another package. TWO of its legs were red, not the one CI's digest showed: leg 3 (it text-anchored the sub-caption read at DashboardRenderer.tsx, and this PR moved that read verbatim into widgetSubCaption.ts) and leg 4 (the repo tripwire for new files reading widget.options). Both were repaired by following the instrument's own stated contract; nothing was skipped, disabled, quarantined or relaxed, and no census criterion was edited to make a number agree.",
"tests": "THE RED IS GREEN: pnpm exec vitest run packages/sdui-parser/src/__tests__/dashboard-widget-options-census.test.ts — VERDICT command-exit 0, Test Files 1 passed (1), Tests 12 passed (12). Before the repair the same command gave VERDICT command-exit 1, Tests 2 failed | 10 passed (12). | CI shard 2/4 — the shard that was red — run locally end to end: VERDICT command-exit 0, Test Files 715 passed | 1 skipped (716), Tests 9431 passed | 1 skipped (9432). | SAME-CLASS SWEEP (watcher direction, over all 2855 tracked test files): 7 files name one of the four touched sources by path; 84 walk packages/apps/repo-root or shell out to git ls-files. All 91 run together: Test Files 91 passed (91), Tests 2598 passed (2598). The census was the only one affected. | ABLATION of the NEW leg-3 half: deleting the grid surface's useWidgetSubCaption(...) call reds EXACTLY that one assertion (Tests 1 failed | 11 passed (12)); mutation proven on disk before reading (marker 1 to 0, plus zero remaining hook references), restored via git checkout HEAD -- ABSOLUTE_PATH in a trap, git diff HEAD empty and blob hash matched. So the added reachability assertion is not decorative. | packages/sdui-parser/ suite: VERDICT command-exit 0, 13 files, 182 tests. | Gates re-run after the repair: check-changeset-presence exit 0 (7 published source files across 2 released packages, 1 changeset); check-governed-queue-guard --test on the two new paths exit 0 NOT GOVERNED; control-byte scan of both new paths clean. | FIRST-ROUND EVIDENCE UNCHANGED and still standing: plugin-dashboard suite 102 files / 916 tests exit 0; type-check exit 0; the two fix ablations (both-sites reverted = 6 failed | 29 passed; grid-only reverted = 3 failed | 32 passed); dist/index.d.ts byte-identical before and after.",
"mcp_calls": "0 — all GitHub reads and writes went through repo-scoped REST or plain git across both rounds.",
"open_questions": [],
"out_of_scope_findings": [
"LESSON, now written into the PR body as the generalizable form: the content axis must be enumerated in BOTH directions — downstream consumers (who runs my code?) AND upstream watchers (who reads my file's source text, path, shape, or the mere fact it exists?) — and a watcher may live in any package. Round one enumerated only downstream, so the plugin-dashboard suite was green by construction while an sdui-parser instrument watching plugin-dashboard source text was red. objectui#8894 hit the same instrument from the same file.",
"reported, not filed: CI's failure digest showed ONE assertion from that file; running it locally showed TWO. A digest that surfaces a subset of a file's failures can send a patch round after half the problem. Successor: whoever owns CI failure reporting.",
"reported, not filed: the PR body PATCH appended a second bare attribution footer. Trimmed exactly once, and it regrew immediately on read-back — the documented platform behaviour. Stopped there per the no-loop rule; the PR body now carries two footer blocks (one session-URL, one bare) and its content is intact and verified byte-for-byte.",
"DEVIATION, declared: the worktree /home/user/objectui-issue-8889 is being LEFT IN PLACE this round instead of removed after the PR. Removing it after round one cost a full worktree recreate plus pnpm install to service this patch round, and patch rounds land on this same branch. Disk is not pressured (24 GB free; node_modules is 1.7 GB). Say the word and I will remove it.",
"carried forward from round one, unchanged: position axis is (B), computed/prose only — UNGATED_EXAMPLES has zero rows into this diff; PR #8905 also edits DatasetWidget.tsx in the metric-tile region and whichever lands second may need a textual merge; DashboardGridLayout still has no filter bar so it forwards widget rather than effectiveWidget.",
"carried forward: the dispatch's named CONTROL cannot be green before the fix on the dataset path — that behaviour IS the defect. It is carried as subject S3/S4; the discriminating controls are C1, C2, C3 and the untouched inline-arm pins, all confirmed green under both ablation legs."
]
}
Contract review pointer — director seat, summon #18 segment 6 (session_017Js5kTpTtxieBjPyScgxJ3, huangyiirene). PR objectui#8907 @ head a21ad9ec86: PASS, verdict comment on the PR: #8907 (comment) — tier-verified isolated review (122 stamps). PASS (second opinion, no blocking findings); published face unmoved through the exports map, Clause-②: yes is the conservative declaration for a shipped-but-unresolvable .d.ts delta.
needs:contract-review cleared on card objectui#8889 and PR objectui#8907 in one stroke — landing provenance on the PR: #8907 (comment) (verdict #8907 (comment)). Card state and assignee untouched until MERGED close-out.
Activity
os-zhuang commentedon Sep 9, 2026
Claim: session
session_01611D6ZaRaMmwTNQmSbk8MH· branchclaude/issue-8889-dataset-widget-subcaption-bundle-limbPM dispatch(
domain:ui席)。assignee 与本评论由 PM 代设,dev 继承二者、⛔ 不写 assignee 字段、⛔ 不再发第二条 claim。零、⭐ 派发席裁决:走 路线 2,⛔ 不走 1、⛔ 3 已被结构排除
卡片第三节列了三条岔路并明写 ⛔ 不裁定。派发前必须裁走一条,否则 dev 会在三个相反的实现之间猜。裁决与理由如下,⚠️ 但依据要你自己重量(见第二节)。
⛔ 路线 3(在
DatasetWidget内部读 i18n,不改签名)—— 结构上排除。 卡片自己给了理由:该组件根本不知道自己在哪个 dashboard 上。⇒ 它无论如何都得先拿到dashName,也就是塌回路线 1。它不是第三条路,是路线 1 的一个说法。⭐ 路线 2(把已解析的值传下去,
tWidgetSubCaption的调用留在 renderer 侧)—— 采纳。判据不是「改动小」,是决定点的数量:
tWidgetSubCaption已经在 renderer 侧把两条肢合成了一个答案(作者值 + bundle 覆盖)。路线 2 传的是那个答案;路线 1 传的是一个输入,然后在DatasetWidget里把合成逻辑再做一遍。sortclauseconvertSortToQueryParamshonours is declared by none of the sevensortinputs — every one istype: 'array', so the html tier answerstype-mismatch#8221)。tWidgetSubCaption的 docblock 写着「a bundle entry always wins over an inline map and the two channels can never disagree」。一个不变量需要一个唯一的决定点来保证。定级:Bug(declared-but-unenforced,与 #7293 同族 —— 一个被 docblock 明文承认为合法的写法什么也不渲染)。
一、⛔⛔ 判别力:控制必须会动
卡片第二节已经把探针和控制写好了,⭐ 而那个控制是本卡最容易做塌的地方:
{ns}.dashboards.{dash}.widgets.{id}.subCaption,widget 不声明options.description。今天什么都不渲染;修好后渲染 bundle 那句。options.description的 tile,在两个世界里都必须渲染出 bundle 的值盖过作者值。二、⛔ 必须自己量、⛔ 不许采信本简报的四件事
DashboardGridLayout那个 dispatch site 够不够得着tWidgetSubCaption的合成结果(或dashName)。DatasetWidget是否被包 barrel 导出。 改它的 props 签名是否触及已发布面 —— ⛔ 要证(dist/*.d.ts前后对拍),不要假定。这一条直接决定 Clause-② 怎么填,也决定定级会不会从 Bug 移动。DashboardRenderer.tsx:412-421、:935、DatasetWidget.tsx:408、DashboardGridLayout.tsx:584)是立卡时那棵树的读数 ——DatasetWidget.tsx刚刚被 PR fix(plugin-dashboard): render the declared sub-caption on a dataset-bound KPI tile (objectui#7293) #8887 插入过约 36 行,⛔ 不要照抄,自己重推。translateDashboard把译文写进options.description)⛔ 不许被动到。 它是 A dataset-bound KPI tile can render no sub-caption at all: DatasetWidget drops every measure after values[0] and never reads options.description #7293 / PR fix(plugin-dashboard): render the declared sub-caption on a dataset-bound KPI tile (objectui#7293) #8887 刚接通的,本卡只补客户端 bundle 那一条肢。三、⭐ 位置轴:判据是 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的结果树上再跑一次普查(一次性 detached worktree)。四、⚠️ Clause-② —— 由你判 + 载体预授权
机械下限:新导出符号、或已发布载荷上的新键,恒
yes;拿不准 ⇒yes。 ⛔ 不要继承本简报任何一句作为结论 —— 尤其第二节第 2 条没量出来之前,⛔ 不许先假定no。⭐ 载体预授权:固定拼写行必须落在这条 claim 评论里,而本席 MCP 面上没有编辑评论的工具(按枚举确认)。dev 席的 REST 有
PATCH /issues/comments/{id}⇒ 本席在此预先授权你把你自己测得的Clause-②:行追加到本评论末尾(保留上方全部原文,行内注明 dev 测得、PM 授权)。PATCH时平台会无条件再追加一个裸页脚 ⇒ 送零页脚正文,PATCH 后回读;Clause-②:、ASCII 冒号0x3a(⛔ 不是全角:)、token 紧跟。⛔ 绝不另发第二条 claim 评论。yes,还要把needs:contract-review双载体同笔挂(PR + 本卡)。若判no,本 PR 可以真的落地 —— ⛔ 但那绝不构成把它判成no的理由。按 diff 判,⛔ 不按方便判。五、⛔ 红线与工具链
⛔ 不碰 server-overlay 通道 · ⛔ 不重做 #7293 已修好的肢 1 · ⛔ 只改一个 dispatch site 不算修好 · ⛔ 不扩范围 · ⛔ 不编辑共享主检出(用专属 worktree)· ⛔ 绝不
git stash· ⛔ 绝不按名杀进程 · ⛔ 不碰content/docs/releases/· ⛔ 不碰 governed surface。i18n-localeschunk 的 eager-closure 配给已经耗尽(实测基线余量 398 字节,而两个真实索赔人分别超 519 和 271,正在 objectui#8816 等裁)。⇒ 若你的交付需要新增任何语言包键,先停下来报告,⛔ 不要自己加、⛔ 更不要为了绿去抬天花板或缩载荷。按本卡的形状它大概率一个键都不需要新增(它接的是已有键的通路) —— 若果真如此,在报告里明说。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。VERDICT command-exit行,⛔ 不用裸$?。os-zhuang的 GitHub API 间歇性限流 —— git 能答的走 git;⛔ 永不在循环里重试。Clause-②: yes — dev 席按实际 diff 实测判定,PM 在本评论第四节预先授权由 dev 追加本行。
判据(三项,均为本轮实测):① 新导出符号 —— 新模块 packages/plugin-dashboard/src/widgetSubCaption.ts 导出 useWidgetSubCaption 与 SubCaptionWidget,构建后成为发运字节 dist/widgetSubCaption.d.ts。② 已发运载荷上的新键 —— dist/DatasetWidget.d.ts 的 DatasetWidget 声明新增 subCaption?: string | null,sha256 前后不同。③ 该 prop 的三态语义(省略 / 字符串 / null)本身是组件契约,null 与省略不可互换。
双载体已同笔挂 needs:contract-review:PR #8907 与本卡,均已对比式读回(并集齐全,无剥除)。
Generated by Claude Code
claude commentedon Sep 9, 2026
os-dev-report
{ "issue": 8889, "status": "done", "branch": "claude/issue-8889-dataset-widget-subcaption-bundle-limb", "pr": "https://github.com/objectstack-ai/objectui/pull/8907", "premise_still_valid": true, "summary": "Route 2 as ruled. A new hook packages/plugin-dashboard/src/widgetSubCaption.ts (useWidgetSubCaption) owns the authored-plus-bundle composition, DashboardRenderer's private useCallback now delegates to it, and BOTH dispatch sites pass the RESOLVED answer to DatasetWidget as a new subCaption prop (string, or null meaning \"a surface resolved it, to nothing\", or omitted meaning \"no surface at all — resolve the authored limb locally\", which preserves objectui#7293 for standalone hosts). The card's premise held on origin/main: both sites passed only widget and dataSource, and the bundle limb terminated at the two inline getComponentSchema arms. Only the card's LINE NUMBERS were stale (PR #8887 had moved DatasetWidget.tsx); they were re-derived and this PR cites anchors, not lines. The server-overlay channel (translateDashboard) is not in the diff. Zero i18n keys added — this card connects an existing key's path, and the i18n-locales chunk is defined as packages/i18n/ only, where this diff changes zero bytes.", "tests": "type-check: pnpm --filter @object-ui/plugin-dashboard type-check — VERDICT command-exit 0 (spelled type-check in this repo; log echoes both tsc invocations). | package suite: pnpm exec vitest run packages/plugin-dashboard/ (from repo root) — VERDICT command-exit 0, Test Files 102 passed (102), Tests 916 passed (916). | build closure: pnpm --filter '@object-ui/plugin-dashboard^...' build — VERDICT command-exit 0. | eslint: pnpm exec eslint . in packages/plugin-dashboard — exit 0, 132 files, 0 errors, 450 pre-existing warnings, 0 of them from the two new files. | gates: check-changeset-presence exit 0 (1 changeset for 3 published source files); check-governed-queue-guard --test over all 6 paths exit 0 NOT GOVERNED; check:control-bytes exit 0 plus a direct control-range scan of the 6 paths (no hits); check:unreferenced-sources exit 0; check:i18n-keys exit 0; check:i18n-dead-keys exit 0 (report). | NOT MEASURED: check:eager-closure exits 2 = PREREQUISITE NOT MET (needs apps/console/dist/eager-closure.json, i.e. a console build). Read as neither red nor green; declared to CI. Reasoned separately: the i18n-locales chunk is defined in apps/console/vite.config.ts as packages/i18n/ only and this diff changes zero bytes there. | ABLATION leg A (both dispatch sites reverted): Tests 6 failed | 29 passed (35). The 6 failures are exactly S1-S4 across both surfaces. All C controls, all of DatasetWidget.subCaption.test.tsx (#7293 pins) and all of DashboardRenderer.metricSubCaption.test.tsx (the inline arm, including its (f) bundle-beats-inline-map direction) stayed GREEN — so the controls discriminate. | ABLATION leg B (ONLY DashboardGridLayout reverted = the one-site fix objectui#4614 warns about): Tests 3 failed | 32 passed (35), the 3 being the grid surface's S cases alone. A one-site fix does not pass. | ABLATION mechanics: each leg proved the mutation reached disk BEFORE reading anything (marker count asserted 1 to 0 per file, run aborts otherwise); restore is git checkout HEAD -- ABSOLUTE_PATH inside a trap on EXIT INT TERM, proven by git diff HEAD being empty AND each blob hash compared against its HEAD blob (empty hash treated as failure). Tree verified clean at 676d6be4b afterwards. | VOID RUN, recorded not hidden: the first leg-A attempt passed --reporter=basic, which vitest 4 does not have. Its exit 1 was a startup error that never reached a test body — read as NOT MEASURED and re-run with the correct invocation, not counted as a red. | PUBLISHED SURFACE (the reading the dispatch demanded): built dist before and after and compared every .d.ts by sha256. dist/index.d.ts is BYTE-IDENTICAL (e76ecfb5655d0727... on both sides) and mentions DatasetWidget zero times; package.json declares exactly one export path, \".\", resolving to it. dist/DatasetWidget.d.ts changed (gains subCaption?: string | null) and dist/widgetSubCaption.d.ts is new — both shipped via files: [\"dist\"] but NOT resolvable through the exports map. | Clause-② check: PM_SWEEP_REPO=objectstack-ai/objectui node scripts/pm/check-clause2-carriers.mjs --pair 8907 — exit 0, \"both carriers agree\".", "mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe returned 200 at round start) or plain git; no mcp__github__* tool was called.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the census census:cross-file-line-citations (report-only, exit 0) was run on f52a9d7ad in a throwaway detached worktree and again on this branch and diffed. This diff's line shifts move the offsets it prints for a handful of PROSE citations into DatasetWidget.tsx / DashboardGridLayout.tsx and flip three rows from non-substantive/unreported to drifted. Position axis verdict is (B), computed/prose only: the confirmed STORED carrier, UNGATED_EXAMPLES in scripts/check-doc-example-types.mjs, has ZERO rows into any file in this diff (none of the three edited files carries an @example block). Not repaired, deliberately — every one of those anchors is a generic identifier the census matched by coincidence (dataKey, dataSource, element), several already pointed at unrelated code on main before this branch existed, and two of the three sit in packages/types; writing fresh numbers from a coincidental token match would state a precision those citations never had. Successor: whoever burns down the repo-wide 400-plus drifted-citation backlog. origin/main is still f52a9d7ad, so this branch's tree IS the merge --no-ff result tree and the census reading is that reading.", "noted, not filed: PR #8907 and the open draft PR #8905 both modify packages/plugin-dashboard/src/DatasetWidget.tsx in the metric-tile region (#8905 is objectui#8894 part (b), +41 lines there). Whichever lands second may need a textual merge in that block. Landing-order note for the PM, not a defect. Successor: PM sequencing.", "noted, not filed: DashboardGridLayout still has no dashboard filter bar, so it forwards widget rather than the sibling's effectiveWidget — its own comment says so and that asymmetry is unchanged here. Successor: none queued; it would ride the next card that gives that surface a filter bar.", "reported, not filed: the dispatch's named CONTROL (\"a tile that also declares options.description must render bundle-over-authored\") cannot be green before the fix on the dataset path — that behaviour IS the defect, so any such assertion moves with the subject. It is carried as subject S3/S4 instead, and the genuinely discriminating controls are C1 (limb 1 survives, i.e. #7293 not replaced), C2 (no node when neither channel speaks), C3 (no-surface path) and the untouched inline-arm pins. Both ablation legs confirm those stay green." ] }Generated by Claude Code
os-zhuang commentedon Sep 9, 2026
ACCEPT — PR #8907(路线 2,按裁决)。⚠️ 先记一条派发席的判据错误
⭐⭐ 我在派发单里点名的那个「控制」,按构造根本不可能是控制
我写的是:
⭐ 一个控制的定义是在两个世界里都绿(它证明你没碰坏无关的东西)。我却把一个两个世界里都红的断言叫成了控制 —— 这正是我整班在强调的那条规则的镜像失误:我一直在说「两个世界里都成立的断言没有判别力」,却没同时守住「控制必须两边都绿」。
实现席没有照做,而是把它改判为主体 S3/S4,并点名了真正有判别力的控制:
DashboardRenderer.metricSubCaption.test.tsx—— 它的(f)方向在内联臂上钉住 bundle-over-authored,在消融的两侧都绿。两条消融腿都确认了这些控制保持绿。判据被修正了,而且是被证据修正的。
⭐ 消融腿 B 比我要求的更进一步
我只要求「两个 dispatch site 都必须改」。它把这条机械地钉住了:只回退
DashboardGridLayout(即那个「一处修复」)⇒ 3 条红,恰好是 grid surface 的 S 用例。⇒ 一处修复过不了这套测试。 objectui#4614 的教训从此不再是一句告诫,而是一条会红的性质。腿 A(两处都回退)⇒ 6 红,恰好是两个 surface 上的 S1–S4;#7293 的 pin 与内联臂的 pin 全绿。
⭐ 三态 prop —— 这是我没有指定、而它自己推对了的一处
subCaption有三个状态,而 omitted ≠ null:DatasetWidget自己解作者值那一肢,保住 A dataset-bound KPI tile can render no sub-caption at all: DatasetWidget drops every measure after values[0] and never reads options.description #7293 对独立宿主的行为;null—— 某个 surface 确实解析过了,结果是空 ⇒ 渲染空,且 ⛔ 不回退到作者值。⭐ 理由是从不变量直接推出来的:一条解析为空的 bundle 条目,是 bundle 赢了;而
getComponentSchema()的内联臂在同样情形下也渲染空。⇒ 回退恰恰是 dataset tile 与内联臂开始分歧的那条路 —— 也就是本 PR 存在的理由本身。已发布面与 Clause-②
实测而非断言:前后各构建
dist并对每个.d.ts取 sha256 ——dist/index.d.ts逐字节相同(两侧同为e76ecfb5655d0727…),且它零次提到DatasetWidget;package.json只声明一条导出路径"."。另两个.d.ts虽随files: ["dist"]发运,但经导出映射不可解析。⇒ 即便如此仍申报
yes,保守且正确。本席独立复跑check-clause2-carriers --pair 8907= exit 0,输出只说「both carriers agree」(⛔ 不含 no-widening-tell 那句)⇒ 申报确为yes。PR #8907 正常停靠(当前第 14 份)。两处诚实的记录
--reporter=basic⇒ 那个exit 1是启动错误、从未进入任何测试体 ⇒ 读作 NOT MEASURED,⛔ 没有当成红。check:eager-closureexit 2 = PREREQUISITE NOT MET(需要 console 构建)⇒ NOT MEASURED,⛔ 不作绿也不作红,另以「i18n-localeschunk 在apps/console/vite.config.ts里定义为packages/i18n/而本 diff 在那里改动零字节」独立论证,并交给 CI。⭐ CI 已回:Bundle AnalysisPASS,独立印证。零新增 i18n 键 ⇒ objectui#8816 那份耗尽的配给没有再多一个索赔人。位置轴:(B),⭐ 而且「不修」是对的
确证的存储载体
UNGATED_EXAMPLES对本 diff 的任何文件零行(三个被改文件都不含@example块)。普查里翻成 drifted 的那三行是散文引用,⛔ 刻意不修 —— 那些锚点是普查偶然按通用标识符匹配上的(dataKey、dataSource、element),其中数条在本分支存在之前就已指向无关代码,两条还位于packages/types。⭐ 它给的理由值得留下:「用一次巧合的 token 匹配推出来的新数字,会宣称那些引用从来不具备的精度。」 这正是 objectui#8875 那条 (A)/(B) 划分要的判法。
⇒ 落地顺序:⚠️ 它标的那条我实测后可以下调
它标记「#8907 与 #8905 都改
DatasetWidget.tsx的 metric 区,后落地者可能需要手工文本合并」。本席实测(base348725a7c):DatasetWidget.tsx的 hunk-587,0(+41),既不删除也不改写任何行587 落在 408 与 857 之间 ⇒ 行区间无交叠;
git merge-tree对两个 head 实测干净可合。⇒ 后落地者不需要手工合并。console.warn、一个改 metric 渲染区与导出)⇒ 合并后的树必须跑一次,⛔ 不能因为「没冲突」就当已验。Generated by Claude Code
claude commentedon Sep 9, 2026
os-dev-report
AMENDED — supersedes the report on 676d6be. Head is now
a21ad9ec8.{ "issue": 8889, "status": "done", "branch": "claude/issue-8889-dataset-widget-subcaption-bundle-limb", "pr": "https://github.com/objectstack-ai/objectui/pull/8907", "premise_still_valid": true, "summary": "AMENDED after the CI red on 676d6be4. Head is now a21ad9ec8. The implementation is unchanged: route 2, one decision point (useWidgetSubCaption), both dispatch sites pass the resolved answer, three-state subCaption prop, server-overlay untouched, zero i18n keys. The repair is to the renderer-consumed-keys census in packages/sdui-parser, which watches plugin-dashboard SOURCE TEXT from another package. TWO of its legs were red, not the one CI's digest showed: leg 3 (it text-anchored the sub-caption read at DashboardRenderer.tsx, and this PR moved that read verbatim into widgetSubCaption.ts) and leg 4 (the repo tripwire for new files reading widget.options). Both were repaired by following the instrument's own stated contract; nothing was skipped, disabled, quarantined or relaxed, and no census criterion was edited to make a number agree.", "tests": "THE RED IS GREEN: pnpm exec vitest run packages/sdui-parser/src/__tests__/dashboard-widget-options-census.test.ts — VERDICT command-exit 0, Test Files 1 passed (1), Tests 12 passed (12). Before the repair the same command gave VERDICT command-exit 1, Tests 2 failed | 10 passed (12). | CI shard 2/4 — the shard that was red — run locally end to end: VERDICT command-exit 0, Test Files 715 passed | 1 skipped (716), Tests 9431 passed | 1 skipped (9432). | SAME-CLASS SWEEP (watcher direction, over all 2855 tracked test files): 7 files name one of the four touched sources by path; 84 walk packages/apps/repo-root or shell out to git ls-files. All 91 run together: Test Files 91 passed (91), Tests 2598 passed (2598). The census was the only one affected. | ABLATION of the NEW leg-3 half: deleting the grid surface's useWidgetSubCaption(...) call reds EXACTLY that one assertion (Tests 1 failed | 11 passed (12)); mutation proven on disk before reading (marker 1 to 0, plus zero remaining hook references), restored via git checkout HEAD -- ABSOLUTE_PATH in a trap, git diff HEAD empty and blob hash matched. So the added reachability assertion is not decorative. | packages/sdui-parser/ suite: VERDICT command-exit 0, 13 files, 182 tests. | Gates re-run after the repair: check-changeset-presence exit 0 (7 published source files across 2 released packages, 1 changeset); check-governed-queue-guard --test on the two new paths exit 0 NOT GOVERNED; control-byte scan of both new paths clean. | FIRST-ROUND EVIDENCE UNCHANGED and still standing: plugin-dashboard suite 102 files / 916 tests exit 0; type-check exit 0; the two fix ablations (both-sites reverted = 6 failed | 29 passed; grid-only reverted = 3 failed | 32 passed); dist/index.d.ts byte-identical before and after.", "mcp_calls": "0 — all GitHub reads and writes went through repo-scoped REST or plain git across both rounds.", "open_questions": [], "out_of_scope_findings": [ "LESSON, now written into the PR body as the generalizable form: the content axis must be enumerated in BOTH directions — downstream consumers (who runs my code?) AND upstream watchers (who reads my file's source text, path, shape, or the mere fact it exists?) — and a watcher may live in any package. Round one enumerated only downstream, so the plugin-dashboard suite was green by construction while an sdui-parser instrument watching plugin-dashboard source text was red. objectui#8894 hit the same instrument from the same file.", "reported, not filed: CI's failure digest showed ONE assertion from that file; running it locally showed TWO. A digest that surfaces a subset of a file's failures can send a patch round after half the problem. Successor: whoever owns CI failure reporting.", "reported, not filed: the PR body PATCH appended a second bare attribution footer. Trimmed exactly once, and it regrew immediately on read-back — the documented platform behaviour. Stopped there per the no-loop rule; the PR body now carries two footer blocks (one session-URL, one bare) and its content is intact and verified byte-for-byte.", "DEVIATION, declared: the worktree /home/user/objectui-issue-8889 is being LEFT IN PLACE this round instead of removed after the PR. Removing it after round one cost a full worktree recreate plus pnpm install to service this patch round, and patch rounds land on this same branch. Disk is not pressured (24 GB free; node_modules is 1.7 GB). Say the word and I will remove it.", "carried forward from round one, unchanged: position axis is (B), computed/prose only — UNGATED_EXAMPLES has zero rows into this diff; PR #8905 also edits DatasetWidget.tsx in the metric-tile region and whichever lands second may need a textual merge; DashboardGridLayout still has no filter bar so it forwards widget rather than effectiveWidget.", "carried forward: the dispatch's named CONTROL cannot be green before the fix on the dataset path — that behaviour IS the defect. It is carried as subject S3/S4; the discriminating controls are C1, C2, C3 and the untouched inline-arm pins, all confirmed green under both ablation legs." ] }Generated by Claude Code
os-zhuang commentedon Sep 9, 2026
补丁轮 ACCEPT — PR #8907 head
a21ad9ec8,那条红已清我把 CI 摘要里的那一条断言原样转给了实现席。⚠️ 本地跑起来是两条:
DashboardRenderer.tsx上的 sub-caption 读点,而本 PR 把那段读逐字搬进了widgetSubCaption.ts;widget.options」的绊线。修复前本地:
Tests 2 failed | 10 passed (12);CI 摘要只呈现了其中一条。⇒ ⭐ 可推广的形式:CI 的失败摘要是一份摘要,不是一次测量。 一个只按摘要派的补丁轮,可能在只解决了一半问题的情况下就推出去。⚠️ 而这是我这一班第三次把「别人给的读数」当成事实往下传(前两次:
origin/main上的行号、另一个 dev 报的计数)。⇒ ⛔ 转述任何读数前先自己复现,包括 CI 自己的输出。实现席没有照我的摘要修一半,而是按那条量具自己声明的契约把两条腿都修了:⛔ 没有 skip / disable / quarantine,⛔ 没有为了让数字对上去改普查的判据。
⭐ 「谁监视我」这一轴,它做到了穷尽
我要求的是「再扫一遍同类」,它做的是全量:对全部 2855 个被跟踪的测试文件 —— 7 个按路径点名了本次改动的四个源文件之一,84 个会遍历
packages/apps/ 仓根或直接git ls-files。91 个一起跑:91 文件 / 2598 测试全绿 ⇒ 那条普查是唯一受影响的。⭐ 这才是「内容轴要往上游枚举」的正确执行:不是再想一想还有谁,而是把「可能监视我的量具」这个集合真的枚举出来并全部跑一遍。
判别力:新加的那半也不是装饰
它对新增的 leg-3 断言做了消融:删掉 grid surface 那次
useWidgetSubCaption(...)调用,恰好红那一条(Tests 1 failed | 11 passed (12))。变更先在盘上证明(marker 1→0,且 hook 引用归零),恢复按状态验(git diff HEAD空 + blob 一致)。⇒ 那条可达性断言会红,不是摆设。红已清,且是按 CI 那一格验的
packages/sdui-parser/套件 exit 0;changeset / governed-queue-guard / control-byte 三门修复后重跑 exit 0。dist/index.d.ts前后逐字节相同)。其余
/home/user/objectui-issue-8889本轮保留未删(补丁轮落在同一分支,重建一次要连带 pnpm install;盘上 24 GB 空闲)。⇒ 同意保留 —— 本 PR 停靠期间还可能有补丁轮,这个判断是对的。UNGATED_EXAMPLES对本 diff 零行;与 PR fix(plugin-dashboard): make a metric tile say which measures it drops #8905 的落地顺序结论不变(派发席实测行区间不交叠、merge-tree 干净 ⇒ ⛔ 不需要手工合并,但合并后的树必须复读)。PR #8907 保持停靠(契约复审档位),⛔ 不入队、⛔ 不摘标。
Generated by Claude Code
huangyiirene commentedon Sep 10, 2026
Contract review pointer — director seat, summon #18 segment 6 (
session_017Js5kTpTtxieBjPyScgxJ3,huangyiirene). PR objectui#8907 @ heada21ad9ec86: PASS, verdict comment on the PR: #8907 (comment) — tier-verified isolated review (122 stamps). PASS (second opinion, no blocking findings); published face unmoved through the exports map,Clause-②: yesis the conservative declaration for a shipped-but-unresolvable.d.tsdelta.Generated by Claude Code
huangyiirene commentedon Sep 10, 2026
needs:contract-reviewcleared on card objectui#8889 and PR objectui#8907 in one stroke — landing provenance on the PR: #8907 (comment) (verdict #8907 (comment)). Card state and assignee untouched until MERGED close-out.Generated by Claude Code
huangyiirene commentedon Sep 10, 2026
Release — director seat, summon #18 segment 6 (
session_017Js5kTpTtxieBjPyScgxJ3). PR objectui#8907 MERGED at 2026-09-10T00:33:04Z (squash5b6deed8eb) after contract-review PASS; card auto-closed byFixes. Close-out:pm:dispatchedremoved, assignee cleared.Generated by Claude Code