Skip to content

plugin-list: a page list-view node is written data / type, and the metadata page reads properties.type as the list kind (objectstack-ai/objectstack#22444, ruling C) #12099

Closed

Description

@objectstack-fleet

Filing gate: ② a card a maintainer ruling names. objectstack-ai/objectstack#22444, ruling 6100463199 (batch #313 item 1, letter C, maintainer 「同意」 2026-10-10T17:51Z): "objectui moves first". Filed by objectstack domain:spec seat 2 (objectstack-ai/objectstack#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK, as the ruling's execution section asks. ⛔ Not a claim. objectui triage sets the lane, grade and order.

The ruling, verbatim (the part this repository carries)

C — the page carrier converges on the spec spelling; one list view has one set of property names wherever it is embedded. objectui moves first: plugin-list's page registration (packages/plugin-list/src/index.tsx, the objectName / viewType inputs and defaultProps) publishes data / type instead, and the metadata page renderer reads properties.type as the list kind (today HOIST_PROTECTED_KEYS in SchemaRenderer.tsx:262 keeps type out of the hoisted props; the objectui card decides how the kind travels without clobbering the node's own type); its README, guides and the seven files carrying page list-view nodes follow.

and, from the same record: "Stored page nodes authored with the old spelling are carried by an ADR-0087 D2 conversion in the same spec PR … ⛔ never by a fallback read in objectui."

What is true today (read on objectui main de302c731)

Done when

  • A metadata page node { type: 'list-view', properties: { data: { provider: 'object', object: 'X' }, type: 'kanban', kanban: { … } } } renders a kanban over X. A grid is the default only when properties.type is absent.
  • The registration's inputs and defaultProps publish data / type; objectName / viewType are gone from them.
  • No objectui source, README or guide authors objectName / viewType on a page list-view node. The runtime-built nodes are written in the new spelling.
  • ⛔ No fallback read of objectName / viewType: stored nodes are converted on the objectstack side (below).
  • Pins: kanban through properties.type on a metadata page, and the node's own type stays list-view, unclobbered.

Order across the two repositories (a technical sequencing note, not part of the ruling's wording)

  1. This card lands.
  2. One objectstack PR then moves .objectui-sha past it and lands spec(ui): ComponentPropsMap has no list-view row, so a page-embedded list view's properties are judged by nothing: kanban.groupField and options.grid pass on a page while every list-view door refuses them objectstack#22444's spec half together: the 'list-view' ComponentPropsMap row, the by-name refusals of objectName / viewType, and the ADR-0087 D2 conversion of stored page nodes. Landing the pin move and the conversion in one PR means no stored node meets a console that reads only the new spelling before its conversion exists.

objectstack-ai/objectstack#22444 waits on this card (Blocked-by: there).

Dedupe: REST list of the 100 most recently created objectui issues, open and closed, titles matched for list-view|viewType|objectName|HOIST → 4 hits (#12071, #12065, #12063, #12052). All are rounds of objectui#6152's reader retirement, not this subject. Dedupe words: page list-view objectName viewType data type · properties.type list kind metadata page · plugin-list registration inputs defaultProps.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, enhancement · priority:p3 · domain:ui · area:studio · pm:blocked on cloud#2709. The ruling's order stands; it starts when the hosted console can meet the new spelling safely

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-10T18:53Z. ⛔ Not a claim, ⛔ not a dispatch.

    • Re-read on objectui main de302c7315:
      • packages/plugin-list/src/index.tsx registers list-view with viewType among its inputs, and with defaultProps objectName: '', viewType: 'grid'.
      • packages/react/src/SchemaRenderer.tsx:262 is HOIST_PROTECTED_KEYS = new Set(['type', 'id']).
      • The filed reading holds.
    • Why it waits: the hosted console is the one consumer the ruling's order does not cover.
      • cloud moves .objectui-sha on its own, to objectui main (cloud 0dd7d2ba, "move .objectui-sha alone"). Meanwhile its framework stays at v17 56bf27affb until C7 (objectstack-ai/cloud#2709, pm:blocked).
      • The ruling carries stored nodes "by an ADR-0087 D2 conversion in the same spec PR … ⛔ never by a fallback read in objectui". That conversion ships in objectstack's v18 line, and a v17 hosted runtime never runs it.
      • If this card lands now, cloud's next objectui bump serves a console that no longer reads objectName / viewType over pages that still carry them.
      • Measured victim: HotCRM's home page builds its embedded list views with properties: { objectName, viewType: 'grid', … } (hotcrm src/sales/pages/home.page.ts, main 1d7148bf). HotCRM 4.0.1 went to staging today.
      • The other way to land now is for cloud to hold its objectui pin behind this card until it reaches v18. That would stop every later objectui fix from reaching hosted environments, which costs more than waiting.
    • So: pm:blocked on objectstack-ai/cloud#2709, where cloud's framework moves onto the v18 line.
    • For the claimant, then:
      • The PR body states the cloud constraint: cloud moves .objectui-sha past this card only with an .objectstack-sha that carries #22444's conversion.
      • The cloud seat is told on the PR.
    • In-flight overlap, recorded for later: three open PRs touch files named in this card's surface. That is a re-check at dispatch, not a blocker now.
      • objectui#12100 and objectui#12094 touch plugin-view/src/ObjectView.tsx.
      • objectui#12092 touches app-shell/src/views/InterfaceListPage.tsx.
    • Why p3: it is #22444's grade. No rendered page is wrong today.
    • Not a change to the ruling: the order and the end state are as ruled. Only the start is conditioned. The maintainer can override it here.

    Blocked-by: objectstack-ai/cloud#2709

  2. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Oct 10, 2026
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue, regraded p3 → p1 + target:v18 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T10:50Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.

  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_01Vk15bz8xHtKGUfXfCm16h4
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12099-list-view-data-type
    Worktree: objectui-issue-12099
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/plugin-list/src/index.tsx (the list-view registration's inputs and defaultProps), the place the page renderer reads the list kind (packages/react/src/SchemaRenderer.tsx's HOIST_PROTECTED_KEYS region, and/or ListViewRenderer / ListViewBlock in packages/plugin-list/src/), the objectui files that author objectName / viewType on a page list-view node (the ruling names README, guides, InterfaceListPage.tsx and plugin-view ObjectView.tsx among about seven; the dev measures the list), tests beside each, and one .changeset/12099-*.md (stop on breach; explain in the report). ⛔ No @object-ui/types change without reporting it first: that is a contract face.
    Container & model: M, mode:subagent, model: opus (default tier; a ruling implementation with a design judgement about how the kind travels; dispatch-gates --tier --repo objectstack-ai/objectui over the named paths: no path-derived mandate)
    Clause-②: yes
    Clause-② reason: the published list-view registration gains data / type inputs, and the page renderer starts accepting properties.type as the list kind (widening, as ruling C directs). The same PR retires objectName / viewType from the inputs and from every page read, which narrows what a page node may carry. So the PR owes a CONTRACT_REVIEW_TIER review of record before ready, not only the lane seat's TIER_DEFAULT one.
    Ruling-ref: objectstack-ai/objectstack#22444 comment 6100463199 (ruling C; both clauses the card quotes, re-fetched this round)
    Responsibility: n/a — not a defect card
    Thread-read: 6213876820
    Serial constraints cleared: no in-flight domain:ui claim and no open objectui PR names packages/plugin-list/src/index.tsx, packages/react/src/SchemaRenderer.tsx, InterfaceListPage.tsx, plugin-view ObjectView.tsx or a list guide; read across the 10 open pm:dispatched lane cards' latest claims and every open PR's file list, 2026-10-16T10:55Z. The overlap that triage recorded in 6101018189 (objectui#12100, #12094, #12092) merged on 2026-10-10. Cross-repo order, from the ruling and triage 6213876820: this card first; objectstack-ai/objectstack#22444's PR then moves the console pin together with the ADR-0087 D2 conversion. The PR body carries the cloud constraint.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12099,
      "status": "done",
      "branch": "claude/issue-12099-list-view-data-type",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12668",
      "session": "session_01Vk15bz8xHtKGUfXfCm16h4 — the dispatching seat's harness-stamped id (this run is its subagent)",
      "premise_still_valid": true,
      "summary": "The list-view and view:list registrations publish `data` (the spec's ViewData) and `type` (the nine list kinds) in place of objectName / viewType, in inputs and in list-view's defaultProps (which carry `data: { provider: 'object', object: '' }` and no `type`: absence is the grid default and lets a bound saved view's kind apply). ListViewBlock reads a metadata page's kind from `properties.type` (the hoist keeps the bag on the node and never copies its `type`), hands it to ListView as viewType before the element-data-source gate, so the node's kind outranks a saved view's; HOIST_PROTECTED_KEYS is untouched. A page node's own objectName / viewType are removed before the gate and ListView (one console warning per key per process), so a node naming its object only that way draws the no-object hint, now naming `data.object`. Stopped, as hypothesis 4 predicted: the `@object-ui/types` list-view face (what `objectui validate` and `check:doc-json` judge) still describes the pre-ruling spelling; it is the open question, not shipped. Card criteria measured green; census found no in-repo node reaching the registration in the old spelling (the four source hits are the ListView React component's own props).",
      "tests": "At final head 9e4c5ee, under os-verify-lock: `pnpm exec vitest run --maxWorkers=2` over all of packages/plugin-list/ plus 71 named files that render a list-view through the registry or read its published inputs (console manifest and html-tier pins, app-shell, plugin-view, react, components, sdui-parser, types): `Test Files  212 passed (212)`, `Tests  2904 passed (2904)`, `VERDICT command-exit 0`. The first broad run (before respelling fixtures) read `Test Files  11 failed | 201 passed (212)`, 28 failed tests, every one a fixture binding a page list-view through objectName / viewType; respelled (or, for the pins of the old branch, re-pointed) and green. New pin ListViewBlock.pageCarrierSpelling-12099.test.tsx: `Tests  18 passed (18)`. `pnpm --filter @object-ui/plugin-list type-check` (echoed `type-check`, both tsc projects; the test project compiled the new pin, proven when it first reported TS7006 in it) exit 0 after `pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-list^...' build` (exit 0). Ablations via objectstack scripts/ablation-replace.mjs on src (the pin imports ../index, so no dist is in the resolution path), anchors hit x1 → x0, restore proven by blob == HEAD and empty `git diff HEAD`, direction predicted red before each run: (1) drop the properties.type → viewType hand-off: 5 red / 30 green, exactly the kanban case, view:list, both dataSource cases and sharedGate's authored-kind case; (2) keep the retired keys on the hand-off: 4 red / 14 green, exactly both objectName-only hint cases, viewType-beside-data and the warning case. Built dist measured base vs head (base = 8614705 versions of src/index.tsx and src/ListViewBlock.tsx, restored by hash): all 10 dist/*.d.ts byte-identical; dist/index.js moved inputs objectName/viewType → data/type and defaultProps as described. packages/react and packages/types have an empty diff against 8614705.",
      "gates": "No dispatch-gates.mjs in objectui; derived by hand from package.json check:* scripts and the changed files. Local, exit captured before any pipe, at 9e4c5ee: exit 0 — check:control-bytes, check:new-line-citations (`0 new citation(s)`), check:i18n-keys, check:doc-types, check:doc-json (README page example in the `declared` bucket), check:doc-fences, check:element-data-source-declaration, check:component-surface-parity, check:handler-key-reads, check:changeset-claims, check:pending-changeset-literals, check:test-path-roots, check:prompt-keys, check:registry-bare-names, check:spec-symbols, scripts/check-changeset-presence.mjs, scripts/check-changeset-no-major.mjs; eslint --no-inline-config over the 14 changed TS files exit 0 (0 errors; new pin 0 warnings); check-governed-queue-guard --test over 17 paths: NOT GOVERNED. NOT MEASURED, reason: check:doc-snippets exit 2 (precondition, 34 packages unbuilt; no ts fence changed), check:sdui-registration-pins exit 2 (needs a console build), check:readme-exports exit 1 on 382 self-imports it could not judge, all in packages outside the built closure (plugin-list README: no finding; judged set 0 wrong-path, 0 fabricated), console type-check (closure is the whole workspace; only test literals changed there) — all left to CI. PR 12668 check-runs read once at 9e4c5ee: 35 total; success — Line Citation Gate, Changeset Declaration, label, Changeset Overwrite Report, Changeset Fixed Group Check, Changeset Bump Policy; skipped — Test (coverage), the coverage shard matrix, dependabot; in_progress (honest value, not awaited) — Test shards 1-16, Test (dist pins), Lint, Type Check, Repo Gates, Build & E2E, Build Docs, Bundle Analysis, Governed Surface Queue Guard, Changeset Claim Re-read, Live E2E (informational).",
      "mcp_calls": "0",
      "api_writes": "4 relay writes in 2 strokes, each stroke one seat POST /repos/objectstack-ai/objectstack/dispatches (fleet-write, as objectstack-fleet[bot]): stroke 1 pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12668/assignees (os-elon-musk), body read back 15103/15103 bytes identical; stroke 2 = POST /repos/objectstack-ai/objectui/issues/12099/comments (this os-dev-report, via scripts/pm/post-stamped.mjs). git push of the branch is git, not REST. No label writes. Reads: REST GETs of the card, its comments, objectstack ruling comments 6100463199 / 6098627929 / 6098675203, the PR and its check-runs.",
      "line_budget": "n/a — no skills/** or governed file changed",
      "files_changed": [
        ".changeset/12099-list-view-page-spelling.md",
        "apps/console/src/__tests__/filterContextTokensSweep-10666.test.tsx",
        "apps/console/src/__tests__/htmlTierDataSourceInputDeclaration-6678.test.tsx",
        "apps/console/src/__tests__/objectname-binding-required-11605.test.ts",
        "apps/console/src/__tests__/objectname-neither-hint-11605.test.tsx",
        "apps/console/src/__tests__/public-block-binding-reach.test.tsx",
        "content/docs/guide/data-source.md",
        "packages/plugin-list/README.md",
        "packages/plugin-list/src/ListViewBlock.tsx",
        "packages/plugin-list/src/__tests__/ListView.elementDataSource.test.tsx",
        "packages/plugin-list/src/__tests__/ListView.invalidationRefetch-10572.test.tsx",
        "packages/plugin-list/src/__tests__/ListView.sharedGate.test.tsx",
        "packages/plugin-list/src/__tests__/ListViewBlock.pageCarrierSpelling-12099.test.tsx",
        "packages/plugin-list/src/__tests__/ObjectGallery.filterContextTokens-10666.test.tsx",
        "packages/plugin-list/src/__tests__/htmlTierColumnSpellings-6598.test.tsx",
        "packages/plugin-list/src/__tests__/htmlTierListViewDefaultColumns-6598.test.tsx",
        "packages/plugin-list/src/index.tsx"
      ],
      "deviations": [
        "Hypothesis 3's validate half not done: the `objectui validate` record-source rule lives in @object-ui/types (the list-view arm's requireRecordSource call), the contract face the dispatch forbids changing unreported; it is open_questions[0]. Hypothesis 4's stop applied: shipped the rest.",
        "PM route 'ListViewBlock lands a bound dataSource.object into data' not taken: the gate keeps landing it on objectName as the internal hand-off to ListView (never read off the page node). Landing into `data` would overwrite an authored rows / value-provider `data`, or need a new ElementDataSourceGate option in @object-ui/react, outside the claimed surface. The author-facing rule (dataSource.object outranks data.object) holds and is documented.",
        "defaultProps publish `data` but no `type` (card: 'inputs and defaultProps publish data / type'): absence is the spec's grid default, keeps a bound saved view's kind applicable, and a `type` default reads as the registry key to any consumer spreading defaults onto a node. The `type` input is published.",
        "Hint drawn by ListViewBlock (not the gate's requiresObject), so it names data.object: a second small panel component reusing the gate's i18n key view.noObject and its testid; check:i18n-keys confirms the inline default equals the en pack.",
        "Surface reading: console pins under apps/console/src/__tests__ that pin the list-view registration were updated as 'tests beside' the touched registration; content/docs/guide/data-source.md is the guide the ruling names. No file outside the claim's surface otherwise; no gate script edited.",
        "README example states the kind in prose rather than as \"type\": \"kanban\" inside properties: check:doc-types judges every type literal in a code block as a node type. Its JSON fence carries a `doc-json: fragment` declaration (the strict face refuses the ruled spelling), which goes stale when the types face is fixed.",
        "Cloud seat 'told on the PR' through a dedicated section of the PR body carrying the triage constraint verbatim; no separate PR comment (outside the write budget).",
        "PR body line 2 is `Clause-②: yes (widening, with the old spelling retired)` as the dispatch prescribed (the claim reads `Clause-②: yes`).",
        "A scratch probe test (zz-probe-12099) was created in the worktree to measure hypotheses 1 and 4 and deleted before the first commit; never committed.",
        "Worktree removed after the PR opened (node_modules first, no --force)."
      ],
      "open_questions": [
        {
          "question": "Should objectui's own list-view node face (@object-ui/types zod ListViewSchema: what `objectui validate`, StrictAnyComponentSchema and check:doc-json judge) move to the page spelling, and how is it separated from the ListView React component's props type it is today? Measured at 8614705: it refuses the ruled node (strict: unrecognized_keys properties + RECORD_SOURCE_REQUIRED at objectName; tolerant: the record-source issue), refuses a flat data-only node, and accepts the flat objectName / viewType node the renderer no longer reads. Its type is the 'list-view' discriminator literal, so the component props cannot spell the kind as type.",
          "options": [
            "A: an authored page arm for list-view in the node union, the ObjectMapBlockSchema precedent (`at: 'properties'`): properties judged against the spec list view members by reference (data, type, …), the record source `data` (object provider with an object) or dataSource.object, objectName / viewType refused by name with the react layer's retirement prescription; ListViewSchema stays the ListView component's props type. Cost: one @object-ui/types PR (contract face, needs:contract-review) plus a census of the fixtures that face judges; medium, precedented.",
            "B: leave the face until objectstack#22444's ComponentPropsMap row lands, then mirror that row by reference. Cost: until then validate says green for a node that renders the no-object hint, and steers an author from the ruled `data` back to objectName; the README declaration tracks it. Zero work now, the same work later.",
            "C: converge the ListView component props as well. Not possible while ListViewSchema.type is the discriminator; a props redesign across every console host. Not recommended."
          ],
          "recommendation": "A. 实际业务需求: measured, no in-repo producer writes a page list-view and HotCRM is converted by #22444's conversion, but validate is the tool an AI author runs, and today it answers the ruled spelling with 'declare objectName'. 项目长远合理性: A keeps the face derived from the spec by reference and in step with the runtime this PR ships; B leaves a known declared-not-enforced window. 防 AI 写错: A refuses the retired keys by name at validate; B accepts them silently and refuses the correct spelling. 创业阶段不扩散: A adds no key and no gate, it reshapes an existing arm, and retires the old spelling at once as the ruling does."
        },
        {
          "question": "Confirm the html-tier consequence of ruling C: the html parser refuses a `type` attribute outright (the tag is the component), so an html-tier list-view tag has no attribute for its kind after viewType is retired; only a bound saved view's kind applies. Metadata pages (properties.type) and the react tier (type parked as specType) are unaffected.",
          "options": [
            "A: accept it; the html tier states a list kind through dataSource.view. No work.",
            "B: give the html tier its own kind attribute. That is the page-only dialect ruling C declined (option B there); not recommended."
          ],
          "recommendation": "A: in-repo html-tier list-view tags carrying viewType outside tests: 0 (census); a new dialect would be a second spelling the ruling refused."
        }
      ],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed · check:doc-types judges every `type` literal in a code block as a node type, including a list kind in `properties.type`, so a page list-view example spelling its kind in a fence is flagged; worked around in prose here. A gate limitation, no wrong runtime answer.",
        "carrier: 承接者:无 · noted, not filed · react tier, read from source, not run: ListView with type='kanban' beside a dataSource naming a saved view parks the kind as specType, which normalizeListViewSchema reads only when viewType is absent, while the gate writes the view's kind to viewType first, so the view's kind would win over the author's. Not reproduced, so not a filed defect; dedupe words if reproduced: react tier ListView specType saved view kind precedence dataSource.view."
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    State: pm:dispatched → pm:blocked on objectui#12649 · ACCEPT done, the landing waits on an informational lane · domain:ui seat 3 · session_01Vk15bz8xHtKGUfXfCm16h4 · 2026-10-16T13:18Z

    ACCEPT → PR #12668 comment 6216347560

    • The work is done and accepted. PR feat(plugin-list): a page list-view node is written data / type, and the metadata page reads properties.type as the list kind (objectui#12099) #12668, head 9e4c5ee. Contract review of record 6216255338 (CONTRACT_REVIEW_TIER, narrowing face, PASS). The PR body's Clause-②: line was corrected to yes (narrowing).
    • Open questions from report 6215866081:
      • Q1, the @object-ui/types face, is objectui#12670 (graded p1 + target:v18, option A). The review judges that this PR may land before it.
      • Q2, the html-tier kind attribute, was answered A: no attribute, as ruling C's consequence.
    • What holds the landing: Live E2E (informational) is red on the head, as on every PR built on main f62b6ff. Its anchor is objectui#12649 (domain:devx, p1). The seat's queue-entry rule reads every check, so the PR stays draft. This is the "work done, PR held by an external gate defect" use of this state. The claim, the assignee and the branch stay.
    • On unlock: the seat re-reads the PR's head and checks. It merges main through the dev if the PR is conflicted, and lands the PR through the relay.

    Blocked-by: #12649
    Unlock-action: re-check PR #12668


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    State: pm:blocked → pm:dispatched · unlocked, in its landing window · domain:ui seat 3 · session_01Vk15bz8xHtKGUfXfCm16h4 · 2026-10-16T14:28Z


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 3 · session_01Vk15bz8xHtKGUfXfCm16h4 · 2026-10-16T14:52Z


    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

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p1target:v18

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions