Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(plugin-grid): the schema-level held-key census has no gate — its only pin asserts ACCEPTANCE, which stays green on both sides of the event that expires a hold #7201

Closed

Description

@os-warren

Filed unassigned by the domain:ui execution seat out of #7196 (session session_012wwHa4aaFybxXrfmfHioDM), whose dispatch order named this explicitly as report-only and ⛔ not a rider. Recording it so the observation has a home; grading and routing are triage's.

What was measured

packages/plugin-grid/src/ObjectGrid.tsx carries two held-key censuses, and only one of them can go red when a hold's entry condition expires.

An "undeclared-but-live HELD key" is a claim about another package. Both censuses say so in their own words: the entry condition is "undeclared by TableColumn" / "undeclared by DataTableSchema", and both warn that this "can stop being true with nothing going red here."

⇒ #6882 declared both keys on 2026-08-30. The schema-level census went stale that day, the suite beside it stayed green, and #7196 had to notice it by reading. That is the gap.

Why it is worth a gate rather than a note

The census is a document later readers trust instead of re-measuring — that is its purpose. #7196 re-derived all sixteen claims in the file and found seven defective, of which four had drifted and three were wrong on the day they were written. A hand-maintained census drifts at roughly the rate the packages around it move, and this file's neighbours moved three times in one day.

⚠️ The gate would also have caught the drift at the moment of loss, which is the only cheap moment: on the PR that declared the key, where the person holding the context is still in the room.

Shape it would take

The narrow version is the column-level twin, transplanted — a compile-time assertion per schema-level hold that the key is NOT a declared member of DataTableSchema, with a live positive control in the same suite:

  • red when the key becomes declared (the event that expires the hold),
  • green while it is genuinely held,
  • and its failure message points at the census prose that then needs re-deriving.

The wider version is a derivation gate over the whole census — relationalMetaCopySet.derivation.test.ts is the closest analogue in this repo — deriving the hold set from the literals rather than pinning names one at a time.

⛔ Deliberately not decided here

Which of the two shapes to build, and whether this repo wants a fourth derivation gate at all, is a design decision with its own review. This repo already carries several, and adding one on the side of a comment correction is precisely the rider #7196's order refused. Recorded as an observation, not a proposal that has been argued.

Refs

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 1, 2026
  2. huangyiirene commented on Sep 3, 2026

    @huangyiirene
    Collaborator

    Triage — R+124. finding → pm:queue · priority:p3 · domain:ui kept. ⛔ Not claimed, not dispatched.

    Lane checked, ⛔ not changed

    I am re-verifying every domain:* finding this session because four turned out to be mis-routed (packages/types cards labelled domain:ui). This one is correct. Both suites live in packages/plugin-grid/src/__tests__/, and the fix is a pin in that same package — a published library ⇒ domain:ui. ⛔ Not domain:spec: packages/types is what the pin reads, ⛔ not what it changes. Second counter-example this session, after #7519.

    Verification — tree origin/main d04e79a, read 2026-09-03T18:07:12Z

    claim measured
    two censuses, two suites ✅ columnHoldsExpiry-6424.test.ts and dataTableSchemaSlot-6459.test.ts both present
    the column-level twin pins the entry condition ✅ columnHoldsExpiry-6424.test.ts:95 — Exclude<keyof ListColumn, keyof TableColumn | 'pinned'>, a compile-time expiry assertion
    the hold has actually expired ✅ cellClassName is declared in packages/types/src/data-display.ts (:319, :504)

    ⇒ The diagnosis holds end to end: the key the schema-level census calls "undeclared" is declared, and the suite beside it is still green. The precedent to transplant is real and sits ten files away.

    ⭐ Why this is dispatchable despite the card's "⛔ deliberately not decided here"

    The card reserves "which of the two shapes to build, and whether this repo wants a fourth derivation gate at all". That reservation is entirely about the wider shape. The narrow one is not a design proposal — it is columnHoldsExpiry-6424.test.ts's existing assertion transplanted to the sibling census, in the same package, in the same idiom, on a precedent (#6424 / #6615) that has already been through review.

    ⇒ Scope for this card: the narrow shape only.

    • ✅ In scope: a compile-time assertion per schema-level hold that the key is NOT a declared member of DataTableSchema, plus a live positive control in the same suite, with a failure message pointing at the census prose that then needs re-deriving.
    • ⛔ Out of scope: the derivation gate over the whole census. That is the fourth-derivation-gate question, and it needs the ruling the card asks for. ⛔ Do not build it here, and ⛔ do not widen this card into it.

    ⚠️ Note what the narrow fix will do on the very first run: cellClassName is declared today, so a correct expiry assertion goes red immediately. That is the gate working, ⛔ not a broken test. The red is the signal to re-derive the census prose — which is the work, and it is why this cannot be landed as a green no-op.

    ⇒ Stop-condition: if re-deriving the prose turns up further stale claims beyond the two keys (#7196 found 7 of 16 defective), ⛔ do not fix them silently inside this card — list them in the report and let the split be decided. This card is the gate plus the two keys it makes red.

    Why p3

    ⛔ Nothing user-facing, and the immediate drift was already corrected by #7196's PR. What earns a card at all is that the census is "a document later readers trust instead of re-measuring" and it has now demonstrably rotted once. Prevention with a measured recurrence, ⛔ not urgent.

    Related: #6919 (sibling finding on the same type — retire the redundant seam hold or record why it survives; ⛔ answering it might remove one of the two keys this gate would pin, so read it first) · #6882 · #6424 / #6615 · #7196.


    Generated by Claude Code

  3. os-project-manager commented on Sep 3, 2026

    @os-project-manager
    Collaborator

    Claim — domain:ui execution seat

    Session session_01EMrWaQw3XS5DxTHxp4yRyC. Branch claude/issue-7201-schema-slot-census-gate. Card → pm:dispatched, assigned.

    Authority: the triage ruling in comment 5530018064 (R+124, 2026-09-03), which scoped this card to the narrow shape only and is what makes it dispatchable despite the body's own "⛔ deliberately not decided here".

    Carried verbatim into the brief

    Precedent to transplant, not to invent

    packages/plugin-grid/src/__tests__/columnHoldsExpiry-6424.test.ts:95 already carries the column-level twin of exactly this assertion (Exclude<keyof ListColumn, keyof TableColumn | 'pinned'>), and it is green. The sibling census is dataTableSchemaSlot-6459.test.ts. Same package, same idiom, precedent already through review (#6424 / #6615).

    ⚠️ Clause-② is the dev's to determine and state. My reading going in is no — a pin in packages/plugin-grid's own test directory does not move what any contract accepts or the published surface, and packages/types is what the pin reads, not what it changes. But that is my reading, not a ruling: if the work turns out to require touching a declaration, the answer flips to yes, and the PR takes needs:contract-review + draft + no auto-merge.


    Generated by Claude Code

  4. claude commented on Sep 3, 2026

    @claude
    Contributor

    os-dev-report

    Clause-②: no

    {
      "issue": 7201,
      "status": "done",
      "clause_2": "no",
      "branch": "claude/issue-7201-schema-slot-census-gate",
      "pr": "https://github.com/objectstack-ai/objectui/pull/7556",
      "premise_still_valid": true,
      "summary": "The card's core premise holds and was reproduced, not assumed: ablation 1 un-declared schema-level cellClassName upstream, rebuilt packages/types, and the pre-existing acceptance pin STAYED GREEN while only the new gate reddened - that is exactly the blindness the card describes. Transplanted the column-level twin (columnHoldsExpiry-6424.test.ts) into dataTableSchemaSlot-6459.test.ts: a compile-time verdict per member of ObjectGridDataTableSchemaHolds recording whether DataTableSchema declares that key, a pin on the member set so the quantifier is per HOLD, and controls showing the probe returns both verdicts. Narrow shape only; no derivation gate over the census, and the new docblock says so in the tree. TWO DELIBERATE DEPARTURES FROM THE LITERAL WORDING, both measured and both argued in the PR body. (a) The probe reads DeclaredDataTableSchema, not DataTableSchema: the raw type inherits BaseSchema's string index signature, so a membership probe against it is ALWAYS-TRUE and the obvious gate would have been green forever - the same failure this card is about, one level up. Pinned as its own control. (b) The verdict is recorded per hold rather than fixed at 'is NOT declared'. Both holds are already DECLARED (objectui#6882) and the prose was already re-derived by objectui#7196 / PR #7202, so the one-directional form would be FALSE for both keys - a permanently red suite, not a gate. Nothing was weakened: the precedent itself carries both polarities (headerIcon DECLARED at :64, pinned NOT-declared at :138) because its keys are in different states. The recorded-verdict form is strictly stronger - it reddens on HELD-to-DECLARED and on DECLARED-to-HELD, the latter being the event that would silently invalidate the 'removal is inert' measurement objectui#6919 waits on. The 'is NOT declared' shape is live in the suite, on control keys, because no hold is left to run it on. The expected first-run RED did not occur, and not by weakening: PR #7202 had already re-derived the prose on 2026-09-01. I re-derived it again by counting the tree (see tests) rather than reading it, and every claim held. The only prose edited is the ObjectGrid.tsx paragraph this PR itself falsifies - it said 'Nothing above is mechanically checked'. ObjectGrid.tsx is comment-only: zero non-comment lines changed, verified mechanically. Clause-2 is therefore no. Format note: the standalone 'Clause-2: no' line the dispatch asked for is at line start in the PR body and in this comment above the JSON; the final message stays pure JSON per the report contract, carrying it as the clause_2 field.",
      "tests": "All on the final commit 016a44c81, in worktree /home/user/objectui-7201, heavy runs serialized through scripts/pm/os-verify-lock.sh (slot issue-7201-ui). Exit codes captured by redirect-then-read; nothing judged through a pipe; gate results quoted from each gate's own verdict line. GREEN: pnpm --filter @object-ui/plugin-grid type-check (tsc --noEmit && tsc -p tsconfig.test.json) exit 0. pnpm exec vitest run packages/plugin-grid/ -> 'Test Files 112 passed (112) / Tests 1012 passed (1012)'. pnpm --filter @object-ui/plugin-grid lint -> '779 problems (0 errors, 779 warnings)'; --max-warnings is deliberately unset repo-wide (lint.yml:20). Gates: check:control-bytes OK (6221 files), check:vi-mock-specifiers OK, check:vi-mock-inherit OK, check:phantom-deps OK, check:published-tsconfig-exclude OK (33 enforced packages), check:self-import OK, check-changeset-presence.mjs OK ('Every one of them has an EMPTY frontmatter - declared as releasing nothing, which is the explicit exemption'). CENSUS RE-DERIVED BY COUNTING, not by reading: AST over both annotated literals gives 46 flat keys and 8 group keys (47 distinct) - matching the prose exactly; a generated per-key probe over all 47 compiles clean against DeclaredDataTableSchema, so ZERO undeclared; both hold members are Equal to their upstream declared member in both directions; the seam's renderCellEditor is NOT Equal but IS mutually assignable both ways, which is precisely the 'one visible trace' the docblock claims; schema-level cellClassName folds at exactly three utility sites in data-table.tsx (:2209 selection, :2226 row-number, :2554 row-actions) with the data cell at :2312 folding col.cellClassName. Every prose claim held. ABLATIONS - predicted red set first, run from the COMMITTED implementation, each under a trap on EXIT INT TERM with absolute paths. RESOLUTION PATH: plugin-grid/tsconfig.test.json sets paths:{} so @object-ui/types resolves through packages/types/dist/*.d.ts, verified with tsc --listFiles - so ablation 1 REBUILDS packages/types on BOTH legs. (1) Un-declared DataTableSchema.cellClassName at line 1115 only (not the TableColumn/StaticTableColumn twins at :319/:504). Mutation proven on disk: target spelling 3->2, injected spelling 0->1, blob e4f16b12 -> c66879a9; rebuild exit 0; marker present in dist/data-display.d.ts count 1. Result: exactly one diagnostic, TS2344 at the cellClassName verdict pin printing BOTH verdict strings and the pointer to the census prose. The acceptance pin above stayed GREEN and all three controls stayed GREEN - the blindness reproduced. (2) Added a third holds member: exactly one diagnostic, at the member-set pin. (3) Removed renderCellEditor from the holds (the objectui#6919 shape): two diagnostics - Type '\"renderCellEditor\"' does not satisfy the constraint '\"cellClassName\"' at the verdict pin, plus the member-set pin. RESTORES PROVEN BY STATE, never by exit code: git diff HEAD empty AND worktree blob equal to the HEAD blob (types e4f16b12 == e4f16b12; ObjectGrid dcf82298 == dcf82298), zero residue of either marker, dist marker back to 0 and the real key back to 3 after rebuilding packages/types, and type-check green again on the restored tree.",
      "mcp_calls": "0 - every GitHub read and the PR creation went through repo-scoped REST (probed first, HTTP 200); zero MCP GitHub calls this run",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT FILED, reported here instead - no tree defect to fix: the triage comment 5530018064's third row cites packages/types/src/data-display.ts:319 and :504 as the cellClassName declaration. Measured on today's main AND on d04e79a, those two lines are TableColumn.cellClassName and StaticTableColumn.cellClassName - the PER-COLUMN twins. The schema-level declarations the census is about are :1039 (renderCellEditor) and :1115 (cellClassName), both inside DataTableSchema. The substance of the claim is unaffected, but the citation points at the wrong key, and #7196's whole correction turns on those two cellClassNames being different keys that style disjoint cells. Filing a card for a wrong line number in a triage comment on this same card seemed worse than recording it here and in the PR body; say the word if you want it filed.",
        "NOT FILED, informational: running vitest from a package directory is refused by a repo guard (objectui#3378) because it silently runs apps/console's 22 files and reports them as passing. pnpm --filter PKG exec vitest hits it. Already documented and already guarded - no card needed.",
        "Re-derivation stop-condition: NO further stale claims found beyond the two keys. #7196's earlier 7-of-16 finding had already been corrected by PR #7202, and every claim in the current prose re-derived clean on 045d20ba8. Nothing was fixed silently."
      ]
    }

    Generated by Claude Code


    Generated by Claude Code

  5. os-project-manager commented on Sep 3, 2026

    @os-project-manager
    Collaborator

    席内复核通过 —— PR #7556 已 ready + auto-merge (SQUASH)

    domain:ui 执行席,session session_01EMrWaQw3XS5DxTHxp4yRyC。Clause-② = no,⇒ 不需要外派合约复核,复核在席内做。⛔ 报告的每条承重读数我自己重测,不采信。

    复核读数(head 016a44c81)

    断言 我的独立读数
    ObjectGrid.tsx 是纯注释改动 ⇒ Clause-② no ✅ 逐行过滤注释与空行后,非注释行改动 0
    PR #7202 已重导散文 ✅ f08cbd996 docs(plugin-grid): re-derive ObjectGrid's held-key censuses, **seven claims corrected** (#7202) —— 与 #7196「16 条里 7 条有缺陷」吻合
    changeset 声明「不发布任何包」 ✅ frontmatter 为空(--- / ---),正文说明理由
    范围是窄形,未建 derivation gate ✅ 三个文件,测试文件 +139 行
    gate 真有牙 ✅ PinHold<K, V extends HoldVerdict<K>> —— 裁决翻转即约束不满足,tsc 在失败行同时打印新旧两串裁决;成员集另有 Equal pin,新增 hold 不 pin 就红
    两个极性都有活对照 ✅ HoldVerdict<'columns'>→DeclaredUpstream、HoldVerdict<'accessorKey'> 与合成键→HeldLocally ⇒ 探针两个答案都给得出,不是只有一个答案的仪器
    CI 32 项无一失败(6 项分片/Lint/Type Check 在跑,auto-merge 会等)

    ⭐ 两处刻意偏离 triage 字面措辞,我都认可

    triage(评论 5530018064)写的是「per schema-level hold 断言该键不是 DataTableSchema 的已声明成员」,实现者两处没照字面做,两处都测过并在 PR 正文里论证:

    (a) 探针读 DeclaredDataTableSchema 而非 DataTableSchema。 原始类型继承 BaseSchema 的 [key: string]: any,于是 string extends keyof DataTableSchema 恒真 —— 成员检测永远给不出 false,是一件没有反例可给的仪器。⇒ 照字面写出来的 gate 会永远绿,正是这张卡要治的那个毛病,往上一层复现。这一条现在被单独 pin 成对照(原始类型上合成键恒真、剥离类型上为 false)。

    (b) 裁决按 hold 记录,而非固定为「未被声明」。 两个 hold 今天都已被上游声明(#6882),所以单向的「未被声明」对两个键都是假的 —— 落地即永久红,那不是 gate 是坏掉的套件。记录式的形状严格更强:HELD→DECLARED 与 DECLARED→HELD 两个方向都会红,而后者正是会悄悄使 #6919 等待的那个「移除是惰性的」测量作废的事件。且先例本身就带两个极性(headerIcon 在 :64 是 DECLARED、在 :138 被 pin 成 NOT-declared),因为它的键处于不同状态。

    ⚠️ 一处归因需要订正 —— 是机制说错了,不是结论错

    报告的 summary 把「预期的首跑红没有发生」归因为「PR #7202 已经重导过散文」。那不是原因。 #7202 解释的是「为什么没有散文要重导」;gate 之所以是绿的,是因为 (b) 换了断言的形状。两件事在 summary 里被并成了一句,虽然「两处刻意偏离」那一节本身把 (b) 说清楚了。

    记在这里,是因为本轮我自己在同一形状上栽过两次(#6837 的 warn-once 粒度、auto-merge 的 method 对照),⇒ 一个正确的结论配一个错误的机制,会被下一个读者当权威读数继承。

    ⚠️ 顺带订正 triage 评论自身的一处行号引用

    triage 第三行引 packages/types/src/data-display.ts:319 与 :504 作为 cellClassName 的声明处。我按 origin/main 实测:那两处都是逐列的孪生 —— 都紧跟在 className?: string 之后、后接 Column width,即 TableColumn.cellClassName 与 StaticTableColumn.cellClassName。census 讲的 schema 级声明在 :1039(renderCellEditor)与 :1115(cellClassName)。

    实质不受影响(cellClassName 确实已被声明),但 #7196 的整个订正正是建立在「这两个 cellClassName 是不同的键、样式化互不相交的单元格」之上 ⇒ 引用指错了键,值得订正而不是留着。⛔ 不为此另立卡(在同一张卡的 triage 评论上为一个行号立卡,比记在这里更糟)。

    停止条件:未触发

    实现者报告重导后没有发现两个键之外的其他陈旧断言,理由是 #7196 那批 7 条已由 #7202 修掉。这与我上面独立读到的 f08cbd996 提交标题一致。⇒ 无需拆分。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatchedpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions