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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
finding(components): the static table renderer reads 9 of the 20 keys TableSchema/TableColumn declare — hoverable, striped, align, sortable, cell and 6 more are inert, and the reference page documents two of them as working #5474
Found while implementing #5350 (retiring that renderer's undeclared column aliases). Observation class — filed unassigned and deliberately NOT fixed there, because which way it resolves is an ADR-0049 enforce-or-remove contract decision, not a re-spelling. #5350 stayed inside the spelling question the family ruling settled.
Measured
Every key packages/components/src/renderers/complex/table.tsx reads, derived from the file rather than recalled:
Eleven declared keys are never read. hoverable and striped even carry @default annotations (true / false) describing behaviour that does not exist on this renderer.
The published page documents two of them as working
and its copyable example sets "hoverable": true, "striped": true. Both are inert. The section header one line above likewise reads "A data table with columns, optional striping, and hover effects."
This is the same declared-but-unenforced shape as #5373 (type: 'crud': four declaration faces, no renderer), one level down: the type renders, but a majority of what it declares does not. #5350 corrected the same section's spelling contract and deliberately left hoverable/striped in the example, because deleting them would have pre-empted this decision.
Not merely cosmetic for AI authoring
align and sortable are the two most likely for a generator to emit — a right-aligned amount column is the obvious thing to author, and the pre-#5350 reference example did exactly that ({ "name": "amount", "label": "Amount", "align": "right" }). It is accepted, type-checks, and does nothing, with no diagnostic. Same silent class as #5349.
The routes, not pre-decided
Implement the inert keys on this renderer (hoverable/striped/align are a few lines each; sortable/filterable/resizable/editable/cell are substantially more, and arguably why data-table exists).
Retire them from TableSchema/TableColumn under ADR-0049 and point authors at data-table for the interactive set — the narrow reading being that table is deliberately the dumb static renderer and its type over-declares.
Split the type: keep TableColumn as the rich shared shape data-table honours and give the static renderer a narrow declared subset, so declared = enforced holds per renderer.
Route 2 or 3 look consistent with the startup-focus / implementation-first standing instruction, but the pick is a maintainer call. Note TableColumn is shared: DataTableSchema and others consume it, so a retirement must be checked against those consumers first — this is not a single-renderer edit.
Reproduce
grep -oE '(schema|col)\.[a-zA-Z]+' packages/components/src/renderers/complex/table.tsx | sort -u
sed -n '227,278p' packages/types/src/data-display.ts # TableColumn
sed -n '285,313p' packages/types/src/data-display.ts # TableSchema
sed -n '394,422p' content/docs/api/schema-reference.md # the page, post-#5350
Related: #5350 (the spelling half, which left this alone), #5373 (same enforce-or-remove class), #5349 (the silence).
Triage (first-touch): routed to the decision inbox (needs-user-decision, domain:ui, type Task). Eleven declared-but-inert keys on a published authoring surface, two of them documented as working — this is an enforce-or-remove contract-shape call, which is the manual floor. Chinese four-facet analysis below.
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat, session_01ApyDuQY2fkunMCqXiqvBhR)
The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Option C — split the types. TableColumn remains the rich shared shape that data-table honours, and the static table renderer gets its own narrow declared subset, so declared = enforced holds per renderer. Execution follows the ADR-0049 retirement path for the keys leaving the static renderer's surface (tombstones, schema-reference doc sync, palette/generator sweep), and the shared-consumer surface of TableColumn (DataTableSchema and any others) must be enumerated before the split. Attached condition from the batch: the teaching-material removal (deleting the hoverable/striped teaching from schema-reference.md) may be split out as its own standalone first card. Fallback recorded in the analysis stands: if the shared-consumer audit shows the split's cost is prohibitive, the fallback is Option B (plain retirement pointing authors at data-table).
State: needs-user-decision removed → pm:queue (ready for dispatch).
Dispatching this round (R27) at the contract-review tier — the maintainer's ruled Option C splits a published type, and the keys leaving the static renderer's surface go down the ADR-0049 retirement path.
{
"issue": 5474,
"status": "done",
"branch": "claude/issue-5474-static-table-narrow-types",
"pr": "https://github.com/objectstack-ai/objectui/pull/5822",
"premise_still_valid": true,
"summary": "Option C executed verbatim: new narrow StaticTableColumn (header/accessorKey/className/cellClassName/width) + interface/zod exports; TableSchema.columns moved to it; the 11 never-read keys retired as ADR-0049 tombstones (?: never / z.never().optional(), crud.ts confirm convention) so authored values are refused loudly with the key named — rich TableColumn byte-untouched and pinned untouched. Census re-derived with a stronger instrument (full-file read + SchemaRenderer prop-flow; the instrument now lives in-tree and fails on destructure/computed/helper patterns that would blind it): card's 9-read/11-inert numbers exact. Shared consumers enumerated (DataTableSchema, CRUDSchema, views.ts relations, CRUDBuilder, zod DataTableSchema) — all stay rich; fallback B not needed. Doc sync: schema-reference §TableSchema loses the hoverable/striped teaching (example + table + intro), columns row now names the enforced subset; sweep cleaned types/examples json + site playground; palette inputs description gains cellClassName.",
"tests": "All at c3cb8c3c4 (the branch's single commit). Union: pnpm exec vitest run packages/types/ packages/components/src/renderers/ scripts/__tests__/doc-version-claims.test.ts scripts/__tests__/check-doc-links.test.ts -> 'Test Files 126 passed (126) / Tests 1318 passed (1318)'. Typecheck: 5 tsc projects green (types: noEmit+examples+tests; components: noEmit+tests) against the rebuilt turbo closure — components leg imports StaticTableColumn through dist/index.d.ts, a symbol only the new build carries, so green cannot be stale. Reverse verification, both legs from committed state, predicted direction red observed: (A) soften hoverable tombstone -> 'Tests 2 failed | 19 passed' (refusal pin + tombstone-set pin); (B) delete the renderer's cellClassName read -> instrument red on 'declared live but never read'. Ablation rebuild statement: no build leg needed — the root vitest config aliases @object-ui/types and /zod to src, so the mutated files ARE what vitest loads; mutations confirmed on disk by anchored grep before each run (leg A marker=1/removed-anchor=0; leg B col.cellClassName=0), restores proven by inverse counts, trap-guarded scripts. Gates: check-changeset-presence OK ('5 source file(s) of 2 released package(s) ... declares 1 changeset(s)'); check:control-bytes/doc-types/spec-symbols exit=0; turbo lint types+components '3 successful'. check:doc-snippets self-reported NOT RUN locally (needs full workspace build) — declared narrowing, closed by CI. CI read once by name at ~10.5 min after run start (13 runs on head c3cb8c3c4): all completed, 12 success + Dependabot Auto-merge skipped, zero failure/cancelled, mergeable_state clean — including Doc Snippet Types success and CI success. No 'Build Docs'-named workflow materialized on this head; the completed/no-failure/clean judge holds over the actual 13.",
"open_questions": [],
"out_of_scope_findings": [
"filed as #5821: rich TableColumnSchema zod mirror omits `editable` — a key data-table reads at 3 sites is silently stripped by validation, so a column locked editable:false re-opens after parse (#4605 class; my rich-accept test loop excludes editable with a comment pointing at it)",
"NOT re-filed: stale skills teaching of `label` on a static table column (skills/objectui/guides/schema-expressions.md) already open as #5473 — search-first caught it; nothing new added there"
]
}
Activity
os-zhuang commentedon Aug 21, 2026
Triage (first-touch): routed to the decision inbox (needs-user-decision, domain:ui, type Task). Eleven declared-but-inert keys on a published authoring surface, two of them documented as working — this is an enforce-or-remove contract-shape call, which is the manual floor. Chinese four-facet analysis below.
os-decision-facets(四棱卡面块;标记按字面文本写入)
一句话问题:静态表格组件的「使用说明书」列了 20 个旋钮,实际接线的只有 9 个 —— 文档还专门教用户去拧那 11 个没接线的(斑马纹、悬浮高亮、右对齐都在内),拧了没反应也不报错。
选项与真实代价:
四棱:
置信缺口(本分析看不见什么):TableColumn 的全部消费者面未清点(卡内点名 DataTableSchema,可能还有别家);存量用户 schema 里这 11 个键的实际书写量未测(若大量存在,B/C 的迁移提示要更周全)。裁后执行:C 或 B 均按 ADR-0049 退役正道立实施卡入 ui 车道(墓碑、schema-reference 文档同步、palette/生成器扫尾),A 则拆卡按能力逐个排队;文档先行修正(schema-reference 删 hoverable/striped 教学)可作首段独立小卡。
Generated by Claude Code
huangyiirene commentedon Aug 22, 2026
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat,
session_01ApyDuQY2fkunMCqXiqvBhR)The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Option C — split the types.
TableColumnremains the rich shared shape thatdata-tablehonours, and the statictablerenderer gets its own narrow declared subset, sodeclared = enforcedholds per renderer. Execution follows the ADR-0049 retirement path for the keys leaving the static renderer's surface (tombstones, schema-reference doc sync, palette/generator sweep), and the shared-consumer surface ofTableColumn(DataTableSchemaand any others) must be enumerated before the split. Attached condition from the batch: the teaching-material removal (deleting thehoverable/stripedteaching fromschema-reference.md) may be split out as its own standalone first card. Fallback recorded in the analysis stands: if the shared-consumer audit shows the split's cost is prohibitive, the fallback is Option B (plain retirement pointing authors atdata-table).State:
needs-user-decisionremoved →pm:queue(ready for dispatch).Generated by Claude Code
claude commentedon Aug 23, 2026
Claim —
domain:uiexecution seat.session_01EuPCi56cnGyykygi3z9w4mclaude/issue-5474-static-table-narrow-typesDispatching this round (R27) at the contract-review tier — the maintainer's ruled Option C splits a published type, and the keys leaving the static renderer's surface go down the ADR-0049 retirement path.
Generated by Claude Code
feat(types): split the static table column type off the rich TableCol…
claude commentedon Aug 23, 2026
os-dev-report
{ "issue": 5474, "status": "done", "branch": "claude/issue-5474-static-table-narrow-types", "pr": "https://github.com/objectstack-ai/objectui/pull/5822", "premise_still_valid": true, "summary": "Option C executed verbatim: new narrow StaticTableColumn (header/accessorKey/className/cellClassName/width) + interface/zod exports; TableSchema.columns moved to it; the 11 never-read keys retired as ADR-0049 tombstones (?: never / z.never().optional(), crud.ts confirm convention) so authored values are refused loudly with the key named — rich TableColumn byte-untouched and pinned untouched. Census re-derived with a stronger instrument (full-file read + SchemaRenderer prop-flow; the instrument now lives in-tree and fails on destructure/computed/helper patterns that would blind it): card's 9-read/11-inert numbers exact. Shared consumers enumerated (DataTableSchema, CRUDSchema, views.ts relations, CRUDBuilder, zod DataTableSchema) — all stay rich; fallback B not needed. Doc sync: schema-reference §TableSchema loses the hoverable/striped teaching (example + table + intro), columns row now names the enforced subset; sweep cleaned types/examples json + site playground; palette inputs description gains cellClassName.", "tests": "All at c3cb8c3c4 (the branch's single commit). Union: pnpm exec vitest run packages/types/ packages/components/src/renderers/ scripts/__tests__/doc-version-claims.test.ts scripts/__tests__/check-doc-links.test.ts -> 'Test Files 126 passed (126) / Tests 1318 passed (1318)'. Typecheck: 5 tsc projects green (types: noEmit+examples+tests; components: noEmit+tests) against the rebuilt turbo closure — components leg imports StaticTableColumn through dist/index.d.ts, a symbol only the new build carries, so green cannot be stale. Reverse verification, both legs from committed state, predicted direction red observed: (A) soften hoverable tombstone -> 'Tests 2 failed | 19 passed' (refusal pin + tombstone-set pin); (B) delete the renderer's cellClassName read -> instrument red on 'declared live but never read'. Ablation rebuild statement: no build leg needed — the root vitest config aliases @object-ui/types and /zod to src, so the mutated files ARE what vitest loads; mutations confirmed on disk by anchored grep before each run (leg A marker=1/removed-anchor=0; leg B col.cellClassName=0), restores proven by inverse counts, trap-guarded scripts. Gates: check-changeset-presence OK ('5 source file(s) of 2 released package(s) ... declares 1 changeset(s)'); check:control-bytes/doc-types/spec-symbols exit=0; turbo lint types+components '3 successful'. check:doc-snippets self-reported NOT RUN locally (needs full workspace build) — declared narrowing, closed by CI. CI read once by name at ~10.5 min after run start (13 runs on head c3cb8c3c4): all completed, 12 success + Dependabot Auto-merge skipped, zero failure/cancelled, mergeable_state clean — including Doc Snippet Types success and CI success. No 'Build Docs'-named workflow materialized on this head; the completed/no-failure/clean judge holds over the actual 13.", "open_questions": [], "out_of_scope_findings": [ "filed as #5821: rich TableColumnSchema zod mirror omits `editable` — a key data-table reads at 3 sites is silently stripped by validation, so a column locked editable:false re-opens after parse (#4605 class; my rich-accept test loop excludes editable with a comment pointing at it)", "NOT re-filed: stale skills teaching of `label` on a static table column (skills/objectui/guides/schema-expressions.md) already open as #5473 — search-first caught it; nothing new added there" ] }Generated by Claude Code
feat(types): split the static table column type off the rich TableCol…
Declare headerIcon on TableColumn; tombstone it on the static column …
feat(types,plugin-dashboard): land the #6425 per-key ruling — declare…
feat(types): declare `fitContent` on `TableColumn` (#6424)
fix(types): declare `editable` on the rich TableColumnSchema zod mirr…
Declare `headerIcon` on `TableColumn` (interface + zod mirror + stati…
feat(types,plugin-dashboard): land the objectstack-ai#6425 per-key ru…
feat(types): declare `fitContent` on `TableColumn` (objectstack-ai#6424…