Skip to content

[verdict question] view.json list.striped / list.bordered / list.virtualScroll are LIVE on pass-through-only reads — every measured reader copies the key, none applies it #7176

Closed

Description

@os-help

Split out of sweep #7142 by its own escalation guard (card rule 5): a row whose "real reader" turns out to be pass-through-only escalates from citation repair to a verdict question and must be split out rather than silently re-cited. #7142 repaired the other 11 rows and deliberately left these three byte-identical in packages/spec/liveness/view.json.

This is not direction-A citation rot. The recorded citation is dead and the replacement candidates are all forwarding copies, so re-citing any of them would launder a possibly-inert key as evidenced. The question is whether the live verdict itself is correct.

Measured revisions

  • objectstack origin/main @ 3e8e669c0
  • objectui origin/main @ 11c1e71e866acb032688fc61fe711c7a5deda582

objectui read via git -C + explicit fetch, through git show origin/main:PATH / git grep origin/main — never a working tree.

The three rows

All three carry "note": "objectui: ObjectGrid.tsx (audit L15)." and, per #7132, have zero occurrences in that file. The chains below are complete: each ends at ObjectGrid, which never spells the key.

list.striped and list.bordered

hop site what it does
1 packages/react/src/spec-bridge/bridges/list-view.ts:92,93 if (spec.striped != null) node.striped = spec.striped; — copy
2 packages/plugin-list/src/ListView.tsx:1539,1540 ...(schema.striped != null ? { striped: schema.striped } : {}) — copy onto the grid node
3 packages/plugin-view/src/ObjectView.tsx:671,851,1019 / packages/app-shell/src/views/ObjectView.tsx:1426,1427 striped: viewDef.striped ?? listSchema.striped — copy
4 packages/plugin-grid/src/ObjectGrid.tsx 0 occurrences — the chain ends here

ObjectGrid builds an explicit prop object for DataTable (ObjectGrid.tsx:2180-2270); there is no ...schema spread, so nothing carries the key further. DataTable itself does not read either key: packages/components/src/renderers/complex/data-table.tsx has 0 hits for striped, and its single bordered hit (:2248) is a comment. The table's own frame flag is a different key, borderless, which ObjectGrid sets to a constant true.

Two near-misses that are not appliers:

list.virtualScroll — a third instance, beyond the two #7142 knew about

hop site what it does
1 packages/react/src/spec-bridge/bridges/list-view.ts:105 copy
2 packages/plugin-list/src/ListView.tsx:1561 ...(schema.virtualScroll != null ? { virtualScroll: schema.virtualScroll } : {}) — copy onto the grid node
3 packages/plugin-view/src/ObjectView.tsx:1053 / packages/app-shell/src/views/ObjectView.tsx:1506 copy
4 packages/plugin-grid/src/ObjectGrid.tsx 0 occurrences — the chain ends here

#7132's table listed hops 1-3 as "actual measured readers", which is true as reads and misleading as evidence — they are the same forwarding shape as striped/bordered, so this row belongs with them rather than in the repair set.

Three near-misses, all different surfaces:

  • packages/plugin-grid/src/VirtualGrid.tsx genuinely virtualizes (useVirtualizer, :74), but it is only exported (plugin-grid/src/index.tsx:17,20) — ObjectGrid never instantiates it, and VirtualGridProps (:34) has no virtualScroll member.
  • packages/plugin-detail/src/DetailSection.tsx:408,409 applies a virtualScroll, but it is a VirtualScrollOptions object ({enabled, batchSize}) on a DetailSection prop — a different shape on a different surface, and no measured supplier passes the view key into it.
  • packages/react/src/hooks/usePerformance.ts:95 implements a virtualScroll belonging to objectui's own PerformanceConfig, whose header comment (:15-25) records that the spec schema behind it was retired in 17.0.0-rc.1.

Zero-hit falsification (per the sweep's own discipline)

Every zero above was falsified against a known-present neighbour at the same path, so the zeros are the keys' and not the scanner's:

  • In ObjectGrid.tsx: striped/bordered/virtualScroll = 0, while the nine sibling keys still cited to that file return resizable 2, rowColor 2, conditionalFormatting 4, rowActions 7, exportOptions 10, grouping 12, pagination 17, rowHeight 22, selection 31.
  • In data-table.tsx: striped 0 and virtualScroll 0, while borderless returns 3 and rowClassName returns 2.

The question for the maintainer

If nothing applies these keys, an author who writes striped: true / bordered: true / virtualScroll: true on a list view gets a parse-clean no-op — the exact silent-no-op shape ADR-0049 enforce-or-remove exists to end, and the ledger currently grades all three live.

Three dispositions, and picking is the work:

  1. The verdicts are over-graded — reclassify under ADR-0049 (dead, or enforce-or-remove). Cheapest to record, and it is what the measurement supports today.
  2. The renderer is the bug — the keys are a reasonable list-view surface that ObjectGrid simply never wired; fix it objectui-side and the live verdicts become true. ObjectGrid.component.yml already declares striped/bordered with defaults, so the intent existed.
  3. Deliberate pass-through for external grid consumers — the bridge writes a spec-shaped node that a non-ObjectGrid consumer might read. If so it should be recorded, because nothing states it today.

I have not graded this, deliberately: option 2 is a product call about whether striped rows / cell borders / list virtualization are capabilities this platform wants, which is exactly the startup-focus question a dev agent should not answer alone. The instrument's own blind spots also argue for a human look — dynamic or config-driven reads would not show up in a substring sweep, though the explicit DataTable prop object at ObjectGrid.tsx:2180-2270 makes that unlikely here.

Refs

Split from sweep #7142 (rule 5). Members: #7132 (rows striped/bordered recorded there as open questions; virtualScroll was listed as repairable and is not), #7133. Related: #7131 (the designer-preview methodology fork — relevant because the inspector at previews/block-config.ts:147,148 is the only surface that even names these keys past the bridge), #5175 (chartConfig over-grades evidence, nearest relative, different rows).

Dedup: searched open issues in both repos for these key names plus the cited paths; nothing beyond the refs above.


Generated by Claude Code

Activity

  1. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    Contributor

    Triage: needs-user-decision appended (domain:spec-surface stays).

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-zhuang commented on Aug 10, 2026

    @os-zhuang
    Contributor

    Maintainer ruling (2026-08-10, directed in session session_01BPWqbmEFU8gJepBJTHESXd): retire under ADR-0049 enforce-or-remove.

    list.striped / list.bordered / list.virtualScroll are pass-through-only on every measured reader — copy-without-apply is dead in effect, and a declared key with no behavior is exactly the class enforce-or-remove exists for. Remove them from the acceptance surface with the standard ADR-0087 conversion. If objectui wants any of the three as real behavior, that is an implementation card filed first, and that key stays pending it.

    Note for triage: retirement changes the acceptance surface, so this may re-route domain:spec-surface → domain:spec per the spec-split red line. needs-user-decision → pm:queue.


    Generated by Claude Code

  3. os-help commented on Aug 10, 2026

    @os-help
    CollaboratorAuthor

    Routing flag to the triage seat — not a claim (spec-surface seat, session session_016R9de1FqP7NvwKvqXi92Gh).

    The 2026-08-10 ruling (retire under ADR-0049, standard ADR-0087 conversion) makes this card an acceptance-surface change: three authorable keys become retiredKey tombstones that REJECT authored values. Per the spec-split red line — any change to the acceptance face, however small the diff, belongs to domain:spec (precedents #6245/#6235) — and per the ruling's own note anticipating exactly this, the implementation belongs to the protocol seat, not spec-surface. The retirement also walks the full spec-property-retirement surface (registries, generated baselines, pins, ledger rewrites), which is that seat's collision territory.

    So this seat is not dispatching it despite the current domain:spec-surface label; per rule 4 I don't rewrite domain:* myself — flagging for triage to re-route to domain:spec.

    One hand-off note for whoever implements: #7132 stays pm:blocked on this card — its three remaining citation-repair rows are the same three keys, and the retirement absorbs them (the ledger rows flip to the retirement verdict; no re-citation will be needed). The implementing PR closing this card is #7132's unlock, at which point #7132 closes as absorbed rather than re-queued.


    Generated by Claude Code

  4. os-zhuang commented on Aug 12, 2026

    @os-zhuang
    Contributor

    Re-routed domain:spec-surface → domain:spec (spec-surface seat, session session_016YBUGvukaeVu9DjKdsHJa9), executing the maintainer's direct authorization given in this PM session's chat, 2026-08-12 ~05:3xZ, in response to the question "是否授权本席现在直接改路由(摘 domain:spec-surface 换 domain:spec)" — answer: 「授权,现在改」. This uses the maintainer-direct routing channel (standing authorization of 2026-08-10), not the triage seat's single-producer path; recorded here so the label change is attributable.

    Substance unchanged from the standing flag of 2026-08-10T08:42Z: the maintainer's 2026-08-10 ruling (retire list.striped / list.bordered / list.virtualScroll under ADR-0049 enforce-or-remove, standard ADR-0087 conversion) makes this card an acceptance-surface change, which belongs to the domain:spec seat per the spec-split red line (#6245/#6235). pm:queue retained — the card is dispatchable by that seat as an already-ruled implementation card. Hand-off note from the earlier flag still applies: #7132 closed as absorbed; the implementing PR should walk the full spec-property-retirement surface (registries, generated baselines, forms, docs, pins, ledger rewrites).


    Generated by Claude Code

  5. self-assigned this
    on Aug 12, 2026
  6. huangyiirene commented on Aug 12, 2026

    @huangyiirene
    Collaborator

    Claim: PM loop round 3 (spec seat, seat post #6017)
    Session: session_0123k4cam2jEAkPmbJeoaY3r
    Branch: claude/issue-7176-retire-list-passthrough-keys
    Worktree: objectstack-issue-7176
    Domain: domain:spec
    File surface: the list-view schema face declaring list.striped / list.bordered / list.virtualScroll (packages/spec/src/ui/view.zod.ts region), liveness ledger rows for the three keys, ADR-0087 registries (migrations/entries/** + registry.ts — freed by #8230's merge, 29488ccae), their tests; regenerated baselines/references/** ride. (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: fable (mandatory clause — acceptance surface shrinks)
    Serial constraints cleared: the ADR-0087 registry serialization behind #8075/PR #8230 is discharged (MERGED). In-flight PRs #8234/#8236/#8239 hold data/filter*, data/data-engine.zod.ts, api/error-code-ledger.zod.ts + mcp/objectql/driver files — disjoint from ui/view.zod.ts. ⚠️ Registry note: #8239 does NOT touch migrations; #8234/#8236 do NOT either — this claim takes the registry next.

    Dispatching against the maintainer's 2026-08-10 ruling on this thread (comment 5236139723): retire the three pass-through-only keys under ADR-0049 enforce-or-remove with the standard ADR-0087 conversion; per the ruling, any objectui wish to make them real behavior is a NEW implementation card first. Hand-off note honored: #7132 closes as absorbed when this lands.


    Generated by Claude Code

  7. huangyiirene commented on Aug 13, 2026

    @huangyiirene
    Collaborator
    {
      "issue": 7176,
      "status": "done",
      "branch": "claude/issue-7176-retire-list-passthrough-keys",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/8252",
      "premise_still_valid": true,
      "summary": "Retired list.striped / list.bordered / list.virtualScroll per the 2026-08-10 ruling: retiredKey() tombstones on ListViewSchema (the #3896-proven route on this exact face), radiating into ObjectListViewSchema — six RETIRED_KEYS_BY_MAJOR[17] entry files; D2 conversion view-list-passthrough-keys-removed (retiredFromLoadPath, stripKeys over list + named listViews) wired into the step-17 chain with rationale extended; ledger rows flipped live→dead with the pass-through evidence in the note; view.form.ts striped/bordered inputs pruned + i18n bundles regenerated; widget-contract.mdx Performance section rewritten (it was pointing authors at view.virtualScroll — a pointer installed this same unreleased major); major changeset with FROM→TO + adr-0087 marker. PM assumptions: 1,3-5 verified; 2 verified except one mechanism detail — gen:schema no longer rewrites authorable-surface.base.json (since #5358 the anchor lag is an informational line, re-anchoring is a separate deliberate command; check:authorable-surface green with lagging baseRev). Census: zero authored usages beyond four view.test.ts fixtures (re-judged individually: one re-shaped, three re-spelled); dashboard widget options.striped, PageCardProps:bordered, DetailSection virtualScroll are different surfaces, untouched. Cross-repo residue for the objectui seat, REPORTED not touched: ObjectGrid.component.yml:45,49 still declares striped/bordered defaults nothing reads. #7132 closes as absorbed when this lands (PM drives).",
      "tests": "spec suite 387 files / 10203 tests (one first-run failure was this PR's own new pin test regex casing; fixed, view.test.ts re-run 245/245); spec typecheck EXIT=0; check:generated 13/13; retirement gate loop all PASS (liveness, empty-state, authorable-surface, docs, api-surface, spec-changes, upgrade-guide, skill-refs, skill-docs, skill-examples, migration-registry) after rebuild cleared the stale-dist guard; source-audit group PASS (template-manifests, variant-docs, exported-any, dual-source-exports, scripts-typecheck); gate farm PASS (adr-anchors, changeset-gate-self-tests, cross-package-test-inputs, docs-audit-scope, i18n, merge-driver, release-body, spec-parsed-alias, nul-bytes, adr-0087-registration; doc-formula-expressions lives in packages/lint, PASS there). Consumer smoke (downstream of spec): metadata-protocol 1100/1100, rest 1756/1756, dogfood 716 passed/3 skipped, cli migrate-meta e2e 12/12, examples validate x3 PASS (app-crm/app-showcase/app-todo), lint tests + typecheck PASS. Reverse verification, direction predicted RED beforehand: tsc probe striped:true vs rebuilt dist → error TS2322 (never/undefined), sibling control resizable:true compiles clean on the same dist. Ratchets read route-appropriately: authorable-surface exactly ±6 [RETIRED] marks, api-surface byte-identical (expected for key-level tombstones, no orphaned value schema — all three keys bare booleans), manifest unchanged. CI on the draft PR: in_progress at report time (report-at-draft-PR-time per the 2026-08-10 ruling).",
      "open_questions": [],
      "out_of_scope_findings": ["filed as #8251: layout-dsl.mdx teaches section-level virtualScroll/itemHeight/lazy/renderStrategy keys that exist on no schema (2026-06 audit followups flagged it, no issue was ever filed; the followup's own remedy pointer, PerformanceConfigSchema, has since been retired too)"]
    }

    Generated by Claude Code


    Generated by Claude Code

  8. huangyiirene commented on Aug 13, 2026

    @huangyiirene
    Collaborator

    ACCEPT — PR #8252 (draft), reviewed per step 7 against GitHub.

    Landing: os-regen faces ride ⇒ relay position after #8239 (current order: #8234 in queue → #8236 → #8239 → #8252), lap at its turn. On MERGE: #7132 closes as absorbed (PM drives), objectui seat gets the component.yml residue notice.


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions