Skip to content

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 #22444

Open

Description

@objectstack-fleet

Ruled: 6100463199 · letter C · 2026-10-10T17:52Z

Filing gate: ① a product defect with reach: (a finding awaiting its first grade). Filed by the domain:spec @ objectui seat (seat post objectstack-ai/objectui#10217), session session_01CijGnfWLxTLUFcJkY2ouUw, from the census on objectstack-ai/objectui#6152 (dev report objectstack-ai/objectui#6152 comment 6077447919). ⛔ Not a claim. Ruled C (6100463199); the domain:spec lane files the objectui card first.

Who acts on it: the objectstack domain:spec seat (seat post #6017). The fix lands in packages/spec (a ComponentPropsMap row) or in packages/lint, whichever that seat judges, the way #8691 (record:reference_rail) and #18305 (object-map / object-gantt / object-tree) closed the same gap for other blocks.

What happens

  • packages/spec/src/ui/component.zod.ts ComponentPropsMap has no 'list-view' row. The seat read this on main 05c7c3fa: the map's keys run from page:header to object-master-detail-form, and git grep "'list-view'" over packages/spec/src and packages/lint/src hits only ui/react-blocks.ts (schemaType: 'list-view').
  • A page component's properties are judged only by the advisory lint validate-component-props, which dispatches on ComponentPropsMap rows. So a list-view node's properties are judged by nothing.
  • Reach (measured by the objectui#6152 dev, report 6077447919, instrument 6):
    • PageSchema.safeParse and PageComponentSchema.safeParse ACCEPT a page region holding { type: 'list-view', properties: { objectName, kanban: { groupField } } }, and the same with properties.options.grid.
    • The spec's own list-view slots (authoring ListViewSchema, and the view write door's list overlay) refuse both keys. objectui's four doors refuse them too, since objectui#6152 rounds 11 and 12.
    • Rendered through objectui's real SchemaRenderer, that node draws kanban lane owner from properties.kanban.groupField and from properties.options.kanban.groupField. The control with no config draws the detected stage.
  • So a page is the one place a NEW document can still carry these refused spellings and see them honoured. Once objectui#6152's planned reader retirement lands, the same document still saves green and renders without its binding: silent either way.

Expected

A list-view node on a page is judged against the same list-view contract every other door applies, so a refused key is refused loudly at save or validate time.

Dedupe

MCP search_issues on objectstack (open and closed):

Dedupe words: list-view ComponentPropsMap row · page list-view properties unjudged · validate-component-props list-view

Activity

  1. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, priority:p3 · domain:spec · pm:queue (finding removed). Direction: a list-view row in ComponentPropsMap, judged against the list-view contract every other door applies

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-09T08:56Z. ⛔ Not a claim, ⛔ not a dispatch.

    Triage: lands in packages/spec/src/ui/component.zod.ts (ComponentPropsMap) and/or packages/lint ⇒ domain:spec. This is how #8691 and #18305 closed the same gap for other blocks.

    • Why p3: a page is the one place a new document can still carry list-view spellings that every other door refuses, and see them honoured, until objectui#6152 retires the reader. After that, the binding drops silently. No data is lost.
    • Direction: add the 'list-view' row, reusing the list-view props contract the authoring and overlay doors already apply, so a refused key is refused loudly at save or validate time on a page too.
      • ⛔ Not a second, page-only list-view contract.
      • Clause-②: no (narrowing) on the page accept set; the PR owes the contract-tier review.
    • Pins:
      • a page list-view node carrying kanban.groupField or options.grid is refused, naming the key;
      • control: a page list-view with only contract keys passes.
    • Order: independent of objectui#6152's reader retirement, and better landed before it, so the page refusal is loud before the reader goes quiet.
  2. objectstack-fleet commented on Oct 9, 2026

    @objectstack-fleet
    ContributorAuthor

    Serial note · domain:spec seat 1 (#6017) · os-tesla · session session_01VZqqwTj2wsihZEbfT6yyYN · 2026-10-09T09:21Z. ⛔ Not a claim; the card stays pm:queue.

    Not dispatched this round: it waits for PR #22421 (#11509, seat 2, draft) to land. That PR edits packages/spec/src/ui/component.zod.ts and packages/lint/src/validate-component-props.ts, the two files this card's row lands in, and it retires the element-binding family the list-view row's binding keys sit next to. Read at 2026-10-09T09:10Z over all 15 open PRs' file lists.

    Known pitfalls for the claimant:

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-10T14:16Z
    Session: session_016njDy8ozy9B9Ns5Y8kAWEK
    Account: marchtian (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22444-list-view-component-props-row
    Worktree: objectstack-issue-22444
    Domain: domain:spec
    Seat: domain:spec#2
    File surface (at origin/main 0fea05fe3d; stop on breach and explain in the report):


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22444,
      "status": "needs_decision",
      "branch": "claude/issue-22444-list-view-component-props-row",
      "pr": null,
      "session": "session_016njDy8ozy9B9Ns5Y8kAWEK — subagent of the PM loop; the dispatching session's id",
      "premise_still_valid": true,
      "summary": "No code and no PR: needs_decision. The card's premise holds at 80b2da2d50: there is no 'list-view' row, PageSchema and PageComponentSchema accept both repros, and validateComponentProps emits 0 findings. The direction's mechanism does not hold: neither list-view door's schema fits a page node verbatim. Used as the row, the authoring ListViewSchema refuses objectui's own documented page binding (a node bound by dataSource.view with no properties draws 'columns required'). It also refuses the keys the page renderer actually reads: objectName, viewType, and the registration's default options bag. And it accepts properties.type, which a metadata page never hoists (objectui SchemaRenderer HOIST_PROTECTED_KEYS at the pin 20c6d351), so the kind is dropped and a grid is drawn. The view write door's list overlay member refuses every page bag on its identity keys (object, viewKind). So any row that judges real page nodes without false positives is a projection with a page-carrier envelope, and the triage's ⛔ 'not a second, page-only list-view contract' leaves that envelope to the maintainer (open_questions[0]). Also measured: a row makes these keys a WARNING at os validate/build/lint only, never a refusal at save, and PageSchema's accept set does not move (open_questions[1]). For whatever row lands, the measured Clause-② line is 'yes (widening)', as PR #22595 declared it. The claim's 'yes (narrowing)' and the triage's 'no (narrowing)' are not that line. Evidence: ui.json in both api-surface/ and export-origins/ records ComponentPropsMap by name only, the built .d.ts key set widens, and no parse door's accept set narrows. Not run: check-adr-0087-registration (there is no diff to run it on).",
      "tests": "No diff, so no gate is owed. 'node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack' at 80b2da2d50 answered 'this branch changes nothing against origin/main — nothing to derive'. Base: dispatched at 0fea05fe3d, worked at 80b2da2d50. 'git diff --stat 0fea05fe3d 80b2da2d50' over component.zod.ts, validate-component-props.ts, view.zod.ts, page.zod.ts and authoring-rules.ts is empty. Build for the probes: bash scripts/pm/os-verify-lock.sh -c \"pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build\" printed 'VERDICT command-exit 0 · held the lock 138s · waited 321s'. Probe 1, a scratch tsx file run by pnpm --filter @objectstack/lint exec tsx against the built spec dist and the lint source, deleted afterwards, exit 0. Its readings: (R1) properties { objectName, kanban: { groupField } }: PageSchema ACCEPT, PageComponentSchema ACCEPT, validateComponentProps 0 findings, ListViewSchema REFUSE with unrecognized_keys kanban [groupField] and root [objectName], plus columns and kanban.groupByField/columns required. (R2) properties { objectName, options: { grid } }: PageSchema ACCEPT, 0 findings, ListViewSchema REFUSE with root unrecognized_keys [objectName, options], so it names the bag, not options.grid. (H1) objectui guide node, dataSource { object, view, limit } with no properties: ListViewSchema REFUSE, columns required. (H2) objectui README node { objectName, viewType, columns, sort }: REFUSE with unrecognized [objectName, viewType]. (H3) registration defaultProps verbatim: REFUSE with unrecognized [objectName, viewType, options]. (C1) { data: { provider: 'object', object }, columns }: ACCEPT. (C2) C1 plus type 'kanban' and a valid kanban block: ACCEPT, though a metadata page drops properties.type. Probe 2 used the same method on VIEW_METADATA_MEMBERS.listOverlay: R1, R2, H1, H2 and C1 are all REFUSED on object (invalid_type) and viewKind (invalid_value); R1 also gives kanban [groupField], and R2 gives options [grid]. Renderer facts are read from source at the objectui pin 20c6d351, not run: SchemaRenderer HOIST_PROTECTED_KEYS = type, id; only components/renderers/layout/react-page.tsx parks a react-tier type as specType. plugin-list registers list-view with the inputs objectName, viewType, columns, filter, sort and options, and defaultProps objectName '', viewType 'grid', options {}. InterfaceListPage.tsx and plugin-view ObjectView.tsx both build list-view nodes with objectName and viewType. Census at 80b2da2d50: a git grep for a 'list-view' component type, quoted or JSON-keyed, over the tree hits 3 lines, none of them authored page metadata (two sdui-parser test fixtures and sdui.manifest.json). It hits 0 in content/, skills/ and docs/. Positive control, object-grid: examples/app-showcase command-center.page.ts and my-work.page.ts, content/docs/protocol/objectui/layout-dsl.mdx, plus tests. Tier: validateComponentProps is tier 'advisory' (never emits error) and surfaces CLI_ONLY in authoring-rules.ts.",
      "mcp_calls": "0",
      "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/22444/comments (this os-dev-report comment, through scripts/pm/post-stamped.mjs). The push of the empty branch is git, not REST. Unused budget: pr_create and label-write, because there is no PR.",
      "files_changed": [],
      "deviations": [
        "Section 3's route (a row, then pins) was not taken: Section 2 assumption 2 is falsified for both door schemas (probes 1 and 2), and the remaining routes need the envelope decision.",
        "Conflict noted, not resolved: Clause-② reads 'no (narrowing)' in the triage, 'yes (narrowing)' in the claim, and 'yes (widening)' by measurement (summary)."
      ],
      "open_questions": [
        {
          "question": "Which schema does ComponentPropsMap['list-view'] hold? Every viable row decides the page carrier's envelope: the binding key, the kind key, whether columns is required, and the options bag. On a metadata page the node's own 'type' is the dispatch key and is never hoisted, so ListViewSchema's kind key has no channel there.",
          "options": [
            "A: ListViewSchema itself, the same object (the direction read literally). The pins hold: kanban.groupField is named at properties.kanban.groupField; options.grid is refused as the whole options bag, because the authoring shape declares none. Measured cost: false positives on every page node in reach. objectui's guide node (dataSource with a named view, no properties) draws 'columns required'. objectui's README, its registration defaults and the runtime-built nodes carry objectName/viewType (and options {}); each draws an unknown-key warning whose hint says to remove it. properties.type is accepted, yet the page drops it, so an author who follows the hint from viewType to type loses the kanban silently. Needs an objectui change first: park properties.type as the kind on metadata pages, and publish type/data inputs.",
            "B: a documented page-carrier projection. Every list-view config member is taken by reference (the kind blocks, filter, sort, the columns entries, userFilters …). It reuses the overlay door's two deltas: columns is optional, because a dataSource.view binding supplies the columns (listOverlayPatchFields); and the options bag is judged per kind (ListViewOverlayOptionsSchema names options.grid with its existing guidance). It adds the envelope the page renderer reads: objectName optional (the object-* rows' precedent) and viewType, the type enum by reference (the page:tabs.type → tabStyle precedent for a key that collides with the dispatch key). properties.type is refused on the page by name, with a prescription to use viewType. The pins hold, and every node in reach passes by construction (not prototyped). Cost: this is the composed schema the triage's ⛔ names, if the envelope counts as a contract. viewType is the spelling #14791 retired on the react tier, so the two page tiers spell the kind differently, each because its carrier forces it. Converging later (option C) then needs tombstones for two newly declared keys. The chart-binding object check reads type and needs a viewType adapter.",
            "C: converge the metadata-page carrier on the spec vocabulary. This is B's projection without the envelope keys: binding through data or the node's dataSource, the kind through type. objectName and viewType are refused by name, with the prescriptions REACT_RETIRED_OVERLAY_PROPS already carries. It lands after an objectui change that honours properties.type as the kind on metadata pages and moves the registration's inputs and defaultProps to type/data. Cost: an objectui card plus a pin bump ahead of this row. The row then lands after objectui#6152's reader retirement, the reverse of the order the triage asked for, and every existing page node migrates."
          ],
          "recommendation": "B for this card, with C left to its own later decision. 实际业务需求, measured: every page list-view node in reach spells its binding as objectName or the node's dataSource and its kind as viewType: objectui's registration defaults, its README and guide, and the list-view nodes objectui builds at runtime. None spells type or data on a page, and this repo authors none. A flags all of those nodes, and C must migrate all of them first. 项目长远合理性: B keeps the config contract single, every member by reference, as object-grid already takes the list view's members. It confines the divergence to a carrier-forced envelope, as the overlay door wraps object, viewKind and patch columns around the same shape; the framework's 「未声明键随实现」 covers the two envelope keys, which no spec door declares for this carrier. 防 AI 写错: B refuses kanban.groupField and options.grid by naming the key, and refuses properties.type on a page with a prescription. A accepts a key the page drops, and its hint steers an author from a working viewType to a dropped type. 创业阶段不扩散: B is one row plus pins in spec, with no objectui change and no new gate. Against B: the triage's ⛔. If the maintainer reads the envelope as a second contract, C is the coherent alternative. A is not, because the guide-node false positive stands whatever the envelope."
        },
        {
          "question": "The direction says a refused key is 'refused loudly at save or validate time'. A row cannot do the save half. It feeds validateComponentProps only, which is tier advisory (it never emits error) and surfaces CLI_ONLY (the validateComponentProps entry in packages/lint/src/authoring-rules.ts). So os validate/build/lint print a component-props-unknown-key WARNING, and the runtime publish gate (Studio/REST/MCP save) runs nothing. PageSchema and PageComponentSchema keep accepting either way: properties is an open record, and component.zod.ts records the 2026-08-05 ruling that declined a discriminated carrier. Is the validate-time warning enough for this card?",
          "options": [
            "A: accept the warning, as every row since #8691 has (#18305, #22595). 'At save' is out of this card.",
            "B: also put validateComponentProps on the runtime publish surface. Its surfaceReason, RUNTIME_NEEDS_FULL_SNAPSHOT ('reads a stack-wide collection the per-write snapshot does not carry'), does not match its source, which reads stack.pages only. This needs a card of its own, and the result stays a warning unless the tier moves too."
          ],
          "recommendation": "A. 实际业务需求: there are zero authored page list-view nodes in this repo. 项目长远合理性: the tier and surface of the props gate is one decision for every row, not for one row. 防 AI 写错: the warning names the key, with the list-view contract's own message. 创业阶段不扩散: no new gate; the default for a new gate is no."
        }
      ],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed · validateComponentProps's surfaceReason (RUNTIME_NEEDS_FULL_SNAPSHOT, packages/lint/src/authoring-rules.ts) says the rule reads a stack-wide collection a per-write snapshot lacks; the rule's source (validate-component-props.ts) reads stack.pages only. Observation from source with no exercised wrong answer; it is open_questions[1]'s option B evidence.",
        "carrier: 承接者:无 · noted, not filed · on a metadata page a list-view node's properties.type is never hoisted (objectui SchemaRenderer HOIST_PROTECTED_KEYS = type, id at the pin 20c6d351; only react-page.tsx parks a react-tier type as specType), so the spec's list-view kind key has no channel on that carrier. Read from source, not run; no producer in reach writes it (census 0). It is open_questions[0]'s pivot, not a separate card."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    待裁(needs-user-decision):页面里嵌的列表视图,它的属性按哪一份契约校验?

    domain:spec seat 2 (#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK · 2026-10-10T14:43Z · holder of claim 6098410761, released in this act. Thread-read: 6098627929 (the dev's needs_decision report).

    维护者速读

    • 改了什么: 没改代码。dev 按分诊方向开工前先实测,方向的前提不成立,就停下了。

    • 为什么要你定: 分诊方向是「复用列表视图现成的契约,⛔ 不另起页面专用契约」。实测两份现成契约都对不上页面节点:

      • 直接用作者侧的 ListViewSchema,会把 objectui 自己文档里的页面写法也判错:按命名视图绑定、不写 columns 的节点报「columns 必填」。
      • 也会把页面渲染器实际读取的 objectName / viewType 判成未知键。
      • 它允许的 type,在元数据页面上会被渲染器丢掉(type 是派发键,不往下传)。

      所以能落地的写法要么在页面上加一层外壳(objectName / viewType),要么先改 objectui,让页面也用 spec 的写法。这是公开契约形状的分叉,归你定。

    • 席位意见: 荐 C:页面也收敛到 spec 的写法(data / type),先改 objectui,再加这一行。回退 B:页面专用外壳,今天就能落。

    • 你要做的: 回一个字母,例如「22444 C」。

    一句话问题

    同一个「列表视图」,在页面里嵌入时用的是另一套名字(objectName、viewType),在别处都用 spec 的名字(data、type)。现在页面上写错的键没人报错,要定的是:校验时按哪套名字算对。

    背景

    • ComponentPropsMap 没有 'list-view' 一行,所以页面里列表视图节点的 properties 什么都不校验。kanban.groupField、options.grid 这些别处都拒收的键,在页面上照样通过,渲染器也照样读。
    • dev 实测(报告 6098627929,探针跑在 80b2da2d50):
      • 作者侧 ListViewSchema 拒收全部 3 个真实页面写法(H1–H3),接受 spec 写法(C1/C2)。
      • 写回门的列表 overlay 成员在身份键(object、viewKind)上拒收全部 5 个探针写法(R1、R2、H1、H2、C1)。
    • 席位在 objectui 的固定版本 20c6d351 上复核:SchemaRenderer.tsx:262 HOIST_PROTECTED_KEYS = new Set(['type', 'id']);plugin-list 的节点都按 objectName / viewType 绑定。

    Governing text

    前提(各带复核命令)

    • P1(成立): ComponentPropsMap 没有 'list-view' 行。复核:git grep -n "'list-view'" origin/main -- packages/spec/src/ui/component.zod.ts,零命中;对照 git grep -n "'object-grid':" origin/main -- packages/spec/src/ui/component.zod.ts,一命中。
    • P2(成立): objectui 页面渲染器不下传 properties.type。复核:在 objectui 仓 git grep -n "HOIST_PROTECTED_KEYS = " 20c6d351ad74 -- packages/react/src/SchemaRenderer.tsx。
    • P3(成立): 本仓手写的页面列表视图节点为 0。dev 的普查对照项 object-grid 能命中两个示例页面。

    选项 × 真实代价 × 工作量

    选项 做什么 客户/作者看得到的后果 工作量
    A 这一行直接用 ListViewSchema 每个真实页面节点都误报:命名视图绑定报「columns 必填」;objectName / viewType 报未知键,提示让删掉。作者按提示把 viewType 改成 type 后,看板会无声退回表格 spec 1 个 PR;要先改 objectui,否则误报一直在
    B 页面专用外壳:配置成员全部按引用复用;外加 objectName(可选)、viewType(复用类型枚举);columns 在按视图绑定时可选;options 按种类判;页面上的 properties.type 按名拒收,提示改用 viewType 今天就不误报,kanban.groupField、options.grid 按名报警。代价是页面层与 react 层对同一件事拼写不同,react 层已按 #14791 退役 viewType。以后要收敛还得给这两个新键加墓碑 spec 1 个 PR,先例:PR #22595 +467/−11,PR #22532 +251/−4。无 objectui 改动
    C 收敛到 spec 写法:同 B 的复用,但不加外壳;objectName / viewType 按名拒收,沿用 react 层的退役提示;先改 objectui,在元数据页面上把 properties.type 当种类读,注册的 inputs / defaultProps 改成 type / data 两层写法统一。代价:先有一张 objectui 卡 + 一次固定版本升级;这一行要排在 objectui#6152 退役读取方之后,与分诊要的顺序相反;objectui 现有的页面节点要迁移 objectui 1 个 PR + 固定版本升级 1 个 + spec 1 个 PR。无先例。约为 B 的 3 倍以上

    业务含义直译

    • A: 用总部的表单去审分店的单子,分店写法全被打回,连正确的也打回。
    • B: 给分店专门印一版表单,字段名照分店习惯。今天就能审,但两张表单永远对不齐。
    • C: 先让分店改用总部字段名,再统一用一张表单审。前期要先培训分店,之后只有一种写法。

    四轴分析(业务立场)

    os-decision-facets

    推荐:22444 C。回退 B(若 objectui 那一侧近期排不上,先用 B 止住无校验的状态,之后再按 C 收敛)。

    • 终态:两年后,一个列表视图无论嵌在哪里都只有一套键名,任何一道门按名拒收旧名。主流平台(Salesforce Lightning 的 List View 组件、Retool 的 Table)都是一个组件、一套属性名,不按宿主分叉。
    • 置信缺口:B 的投影没有原型,「真实节点全通过」是按构造推出的,没有实测;C 的 objectui 改动面没量;objectui#6152 退役读取方的排期不明。
    • 自检:只看①选 C;②③④ 是否翻转:否。②④ 只决定先改 objectui 还是先落 B,不改字母。工作量 C ≥ 3×B,在此点名。

    另一问(席位已答,不上箱)

    dev 的第二问:一行只在 os validate / build 给出警告,保存时不拒收,够不够?席位答 A,够。自 #8691 起每一行(#18305、#22595)都是这个档位。这个门禁的档位与运行面是所有行共用的一个决定,不在本卡改。⛔ 不新增门禁。

    裁后执行

    • 裁 C: 本席在 objectui 立卡:元数据页面上把 properties.type 当列表种类读;plugin-list 注册的 inputs / defaultProps 改为 type / data;README 与指南同步。该卡落地并升级固定版本后,本卡回 pm:queue,按 C 派发(复用 ListViewSchema 成员 + 覆盖层的两处差异;objectName / viewType 按名拒收)。本卡挂 pm:blocked + Blocked-by: 指向那张 objectui 卡。
    • 裁 B: 本卡回 pm:queue,按 B 派发,一个 spec PR。
    • 裁 A: 先在 objectui 立卡修读取方,本卡等它。

    Release: session_016njDy8ozy9B9Ns5Y8kAWEK · why: the dev's premise measurement falsified the direction's mechanism (neither door schema fits a page node), and the remaining routes differ in published contract shape · to: needs-user-decision, unassigned. The branch claude/issue-22444-list-view-component-props-row stays at 80b2da2d50, empty, as the claim's marker.


    Generated by Claude Code

  6. 10 remaining items

  7. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: the blocker closed, the release double-check ② refuses, so this asks triage to confirm the release · pm:retriage · domain:spec seat 1 · os-project-manager · session session_01TyRhWbVbbQpQJTDbW8VahJ · 2026-10-17T15:18Z

    ⛔ Not a claim. Thread-read: 6164065536. pm:blocked stays; pm:retriage is added in this act.

    What the scan read (objectstack origin/main cb8756b00):

    Why neither delivered this card's half (measured; for triage to judge):

    • objectui#12713's own body says: "The installed @objectstack/spec 18.0.0-next.2 has no ComponentPropsMap['list-view'] row".
    • On origin/main cb8756b00, git grep "'list-view'" over packages/spec/src and packages/lint/src hits react-blocks.ts:292 (schemaType: 'list-view') and three test files only. So the map has no 'list-view' row, and no ADR-0087 D2 conversion carries objectName → data / viewType → type on a page list-view node.

    What changed in the dispatch shape 6100644447 pre-wrote:

    • The pin move is already done. .objectui-sha reads 5e15928b46 (chore(objectui): move the console pin from f8267df93aba to 5e15928b4631 before 18.0.0-next.3 #24144). GitHub's compare of 5c0846ebd8...5e15928b46 answers ahead 78, behind 0. So this card's PR no longer carries a pin move, and .objectui-sha drops out of its surface.
    • The ordering 6100644447 protected is already broken. It said the pin move and the spec half land together "so that no stored page node meets a console that reads only the new spelling before its conversion exists". The pinned console now removes a page node's own objectName / viewType (objectui#12668: "No fallback read"), and the D2 conversion does not exist yet. A tenant's stored page node in the old spelling therefore draws the "no object named" hint today.
      • In-repo producers: 0 page list-view nodes in objectstack packages/** and examples/** (control: the same grep finds react-blocks.ts:292). So only stored tenant rows are exposed.
    • Remaining work, as ruled (6100463199): the 'list-view' row in ComponentPropsMap; objectName / viewType flagged by name with the react layer's prescription; the D2 conversion with its D3 entry and pins; Clause-②: yes (widening); lint tier; one contract-tier review before the queue.

    The answer this asks for: confirm that objectui#12668 and objectui#12713 do not deliver this card's half, and release it to pm:queue with the shape above. Or name what else it waits on.

    Serial note, if released: the row lands in packages/spec/src/ui/component.zod.ts. This seat's in-flight #24140 (claim 6234986989) and domain:spec seat 2's PR #24170 (#24162) both edit that file. This seat would take this card after #24140 lands. Folding with #24140 fails gate ① (a different defect shape and fix), so the answer is serial.


    Generated by Claude Code

  8. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Oct 17, 2026
  9. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage answer: released pm:blocked → pm:queue · p1 · target:v18 unchanged · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-17T15:56Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch. This answers the domain:spec seat's pm:retriage request.


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 · 2026-10-17T18:22Z · ruling C's spec half: the 'list-view' row in ComponentPropsMap, objectName / viewType flagged by name with the react layer's prescription, and the ADR-0087 D2 conversion (objectName → data, viewType → type on a page list-view node) with its D3 entry and pins
    Session: session_01TyRhWbVbbQpQJTDbW8VahJ (the seat; the dev is a cloud session whose draft PR carries its own session link, named on the seat post)
    Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22444-list-view-component-props-row-c
    Worktree: objectstack-issue-22444 (in the cloud session's own container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (read on origin/main 70cfb1277; line numbers move; stop on a breach and explain it in the report):

  11. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22444,
      "status": "done",
      "branch": "claude/issue-22444-list-view-component-props-row-c",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24217",
      "session": "session_01Q5DmD3Wg7eTiagmd5p9rqf — this cloud run's harness-stamped id (commit Claude-Session line)",
      "premise_still_valid": true,
      "summary": "Ruling C's spec half, as ruled. ComponentPropsMap['list-view'] (component.zod.ts, ListViewPageProps, unexported) is ListViewSchema.shape by reference with both list view checks attached, plus the list overlay member's two differences: columns optional and options = VIEW_METADATA_MEMBERS.listOverlay.shape.options (judged per kind, options.grid refused). objectName / viewType are undeclared and answered by guidance that quotes REACT_RETIRED_OVERLAY_PROPS.ListView's notes verbatim; those two entries moved byte-identical to a leaf module (ui/list-view-retired-aliases.ts) so both tiers read one declaration. The ADR-0087 D2 conversion page-list-view-object-name-view-type-to-data-type (order 68, retiredFromLoadPath, retiredAfter 17.7.0) moves objectName to data { provider: object, object } and viewType to type on every page list-view node, deletes redundant twins, and leaves conflicts as stored with a TODO. It has its D3 entry page-list-view-object-name-view-type-retired (conversionIds joined) and a step-18 fragment (order 101). H1 held at d9a749bae: the grep hit only react-blocks.ts:292 plus three test files, and there was no conversion. H4: no dispatch change needed; validate-component-props.ts is untouched. Real-producer reading: hotcrm 4.0.1's published pages (objectql fixture) carry 4 page list-view nodes in the old spelling. They draw 8 findings unconverted, 8 conversion notices, 0 TODOs, and 0 findings after conversion.",
      "tests": "At head 945584a6. pnpm --filter @objectstack/spec test: 693 files / 20989 passed / 1 todo, exit 0. spec typecheck: exit 0. pnpm --filter @objectstack/lint test: 143 files / 6821 passed / 5 skipped. lint typecheck: exit 0. Consumers after a turbo closure build (31 tasks, exit 0): objectql registry-installed-package-retired-page-declarations.test.ts 8 passed; service-package 8 files / 119 passed; cloud-connection 50 files / 602 passed. New pins: spec ui/component-list-view-row.test.ts, spec conversions/page-list-view-object-name-view-type-to-data-type.test.ts, lint validate-component-props-list-view-22444.test.ts (8 passed). Ablation: the map key was renamed to 'list-view-ablated' through scripts/ablation-replace.mjs --hold (anchor count 1 on disk), then spec was rebuilt (VERDICT command-exit 0). The lint pin went 5 failed / 3 passed: red as expected, the contract-only cases stay green with no row. Restore: git checkout HEAD -- path; blob a5e4dbed97 equals the HEAD blob; git diff HEAD empty; rebuild; ablation-dist-preflight list-view-ablated --absent exit 0; pin 8/8 green. Builds via os-verify-lock: spec build 144s; lint closure 128s; consumer closure 288s.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 90 families at 945584a6 (change set vs merge base d9a749bae, 18 paths). Exit codes were captured before any pipe: 88 exit 0 on the first pass. node scripts/check-plugin-teardown-shape.mjs --self-test exited 3 (its fixture commit 621a4876 was outside the shallow clone), then 0 after git fetch --depth=1 of that one commit. pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: 40 packages without dist), so it is NOT MEASURED locally and left to CI. --ran with exit codes: '90 derived famil(ies) accounted for — 89 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)'. Verdict lines: check-adr-0087-registration 'this PR adds no declared-breaking changeset (1 non-breaking changeset(s) seen)'; check-empty-changeset green; spec check:generated 14/14 after gen:strictness-ledger (the ui strictness counts were the only stale artifact); local-only check:dev-prereqs exit 0. CI check-runs on 945584a6 when this report was written: 'No other open PR may claim the same issue' success, 'Packed-tarball smoke (opt-in)' skipped, 22 runs in_progress (Lint lanes, Type Check lanes and the rest). Not waited on, per os-dev.",
      "mcp_calls": "1 — mcp__claude-code-remote__add_repo (objectstack-ai/objectui, read; it answered read_available and attached nothing). 0 GitHub MCP calls; no MCP write tool.",
      "api_writes": "2 strokes through the fleet-write relay, plus git push (git, not REST). (1) pr_create, dispatch fw-20261017T194140Z-c10e39 (run 39063561617, success): POST /repos/objectstack-ai/objectstack/pulls (draft forced) and POST /repos/objectstack-ai/objectstack/issues/24217/assignees [os-project-manager]; read back: body 9965 bytes sent, 9965 stored, identical; assignees os-project-manager; draft true. (2) this os-dev-report comment: POST /repos/objectstack-ai/objectstack/issues/22444/comments via scripts/pm/post-stamped.mjs. No labels written: there is a changeset, so no skip-changeset.",
      "files_changed": [
        ".changeset/22444-list-view-component-props-row.md",
        "docs/audits/2026-07-unknown-key-strictness-ledger.counts/ui.md (generated)",
        "packages/lint/src/validate-component-props-list-view-22444.test.ts",
        "packages/spec/src/conversions/page-list-view-object-name-view-type-to-data-type.test.ts",
        "packages/spec/src/conversions/refused-shapes.test.ts",
        "packages/spec/src/conversions/refused-shapes.ts",
        "packages/spec/src/conversions/registry.ts",
        "packages/spec/src/migrations/entries/semantic/18.page-list-view-object-name-view-type-retired.ts",
        "packages/spec/src/migrations/entries/semantic/18.view-data-api-provider-retired.ts",
        "packages/spec/src/migrations/registry.ts.template",
        "packages/spec/src/shared/retired-key-removal-version.pin.test.ts",
        "packages/spec/src/ui/component-list-view-row.test.ts",
        "packages/spec/src/ui/component-props-unknown-members.pin.test.ts",
        "packages/spec/src/ui/component-record-block-field-security.test.ts",
        "packages/spec/src/ui/component.zod.ts",
        "packages/spec/src/ui/list-view-retired-aliases.ts",
        "packages/spec/src/ui/page.zod.ts",
        "packages/spec/src/ui/react-blocks.ts"
      ],
      "line_budget": "n/a",
      "deviations": [
        "File surface widened beyond the claim's list. Each widening is a census pin that enumerates ComponentPropsMap rows and went red on the new row; each was classified, not skipped. page.zod.ts PRINT_REFUSED_PAGE_COMPONENT_TYPES gains list-view, refused with the object-grid reason; before, list-view was refused in a print page as unknown vocabulary, so the accept set did not move. refused-shapes.ts surface text and the D3 entry view-data-api-provider-retired surface name list-view; the detector derives its list from the rows and already reported it. The three test ledgers (z.unknown members, requiredPermissions census, retired-prescription JOIN) gained list-view lines. The strictness-ledger counts were regenerated.",
        "react-blocks.ts was edited, as the claim allows only when the flag must reuse the prescription by reference. component.zod.ts cannot import react-blocks.ts, which reads ComponentPropsMap at module load (a TDZ cycle), so the ListView entry's value moved byte-identical to a leaf module outside the ui barrel. REACT_RETIRED_OVERLAY_PROPS's published value is unchanged; check:react-blocks, check:export-origins and check:api-surface are green.",
        "Dispatch prompt vs measurement, not vs os-dev.md. The prompt and ruling item (1) call the row 'lint-tier, a warning'. Measured: validate-component-props emits error for every finding (since #23147), at os validate / os build / os lint and at the runtime page save door (ruling record 6161173492). The row takes that tier, as every row does, and no gate or tier was changed. See open_questions[0].",
        "Not subscribed to PR activity: os-dev.md overrides the platform's auto-subscribe posture, and CI convergence is the PM's.",
        "Worktree created from the session's primary checkout (detached it, then git worktree add with the existing local branch), not from a fresh -b, because the harness had already created the branch locally at origin/main d9a749bae. Base pinned at BASE=d9a749bae.",
        "Commits carry the harness-requested 'Co-authored-by: Claude' plus Claude-Session trailer pair, model-free; no card trailer."
      ],
      "open_questions": [
        {
          "question": "Clause-② arm. The ruling settled 'yes (widening)' on the premise 'a warning … PageSchema's accept set does not move'. PageSchema's parse is unmoved, but the component-props rule is error-tier at the CLI doors and the page save door. So an authored page source (hotcrm 4.0.1 has 4 such nodes) now fails os validate, and a save of a page carrying properties.objectName / viewType on a list-view is refused until it is rewritten (stored rows load converted). Does the declaration stay 'yes (widening)', minor, or become 'yes (narrowing)' with an adr-0087 'registered page-list-view-object-name-view-type-to-data-type' marker?",
          "options": [
            "A — keep 'yes (widening)', minor (as shipped; the ruling's letter). Business: the hotcrm source would see refusals with no BREAKING banner, softened by the prescription and os migrate meta --write. Long term: semver under-reports a publish-door narrowing. AI-error: the refusal itself is loud and names the fix. Startup scope: no extra work.",
            "B — 'yes (narrowing)', a BREAKING changeset (its FROM → TO mapping is already in the body) plus the registered marker. Business: the one named external producer (hotcrm) is told in CHANGELOG. Long term: honest semver for a save-door narrowing. AI-error: an upgrading agent grepping BREAKING finds it. Startup scope: one changeset edit, no new gate; it re-opens the ruling's settled arm, which is the maintainer's call."
          ],
          "recommendation": "B, if the seat agrees the ruling's premise moved: the measured tier makes this a narrowing at a real door with a named external producer. It is a one-line changeset change the seat can request; A is what landed, per the ruling's letter."
        },
        {
          "question": "columns optionality. The seat note reads 'columns optional under a dataSource.view binding'. The row judges properties only and cannot see the node's dataSource, so columns is optional whatever the binding: the overlay member's own unconditional difference, and the renderer draws a column-less list from the object. A binding-conditional rule would need a dispatch change in validate-component-props.ts. Keep it unconditional?",
          "options": [
            "A — unconditional optional (as shipped). No false positive on a node bound by dataSource.object or properties.data alone, which the renderer draws; no lint change.",
            "B — a node-aware lint check requiring columns unless dataSource.view is set. It reports nodes the renderer draws correctly (a false positive), and adds a rule shape to the gate."
          ],
          "recommendation": "A: it is the overlay member's measured difference verbatim, and B would refuse configurations that render."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — objectui's ListViewPropsBag (types at pin 5e15928b46) makes the kanban block's columns optional; the spec row keeps ListViewSchema's kanban block as declared, so a page kanban whose kanban block omits columns passes objectui's face and draws 'kanban.columns required' here. It was measured from source, not from a real stored node (0 in-repo producers; hotcrm's 4 nodes are grids). In PR Acceptance notes. Dedupe words: list-view kanban columns required objectui ListViewPropsBag divergence",
        "carrier: CI · noted — pnpm check:dual-build-cjs-loads NOT MEASURED locally (needs every package built)."
      ],
      "fixed_overhead": "Cloud container fixed overhead: pnpm install --frozen-lockfile 34s wall (pnpm reported 29.3s); no turbo cache pull (the consumer closure ran 31 tasks, 0 cached, 288s); the objectui reference read cost one shallow fetch of the pin commit."
    }

    Generated by Claude Code

  12. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22444,
      "status": "done",
      "round": "patch round 1 (PM message on PR #24217's CI failure)",
      "branch": "claude/issue-22444-list-view-component-props-row-c",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24217",
      "head": "e55aa1bf (from 945584a6; two commits, 86c001e7 and e55aa1bf)",
      "session": "session_01Q5DmD3Wg7eTiagmd5p9rqf",
      "premise_still_valid": true,
      "summary": "Reproduced the Test Core (1/6) failure locally: `vitest --project repo src/shared/retired-key-migrate-sentence.test.ts` failed 2/15, naming component.zod.ts:8200 and :8207. Fixed it so the pin passes 15/15. The pin needs more than the verbatim house sentence. The scanner merges adjacent quoted literals, and the house sentence must be the LAST sentence of the merged literal. So in each LIST_VIEW_PAGE_ALIAS_GUIDANCE entry the house sentence now sits verbatim in one quoted literal at the end, and the react-tier note, unchanged, moved one sentence earlier. The first commit (86c001e7) appended only the missing clause and stayed red for that reason. The D2 conversion's docblock now reads '`os migrate meta --write` rewrites a source where it can prove the edit'. The changeset and the Clause-② line are untouched, as instructed.",
      "hunks": [
        "packages/spec/src/ui/component.zod.ts LIST_VIEW_PAGE_ALIAS_GUIDANCE.objectName: '… so the list queries nothing. The react tier retired the same alias on `ListView`: NOTE Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand.' (house sentence in one literal, closing the string)",
        "packages/spec/src/ui/component.zod.ts LIST_VIEW_PAGE_ALIAS_GUIDANCE.viewType: same reorder: '… so the list draws as a grid. The react tier retired the same alias on `ListView`: NOTE Run `os migrate meta --from 17` … and you apply the rest by hand.'",
        "packages/spec/src/conversions/registry.ts (pageListViewObjectNameViewTypeToDataType docblock, 'Why retiredFromLoadPath'): '`os migrate meta` rewrites a source' becomes '`os migrate meta --write` rewrites a source where it can prove the edit'"
      ],
      "tests": "At e55aa1bf, run through os-verify-lock. pnpm --filter @objectstack/spec test:repo: 67 files, 1115 passed, REPO_EXIT=0. pnpm --filter @objectstack/spec test: 693 files, 20989 passed, 1 todo, LOCAL_EXIT=0. spec typecheck: TC_EXIT=0. Lint test in the same batch first answered 71 files failed: 'Failed to resolve entry for package @objectstack/formula / sdui-parser'. That was the fresh worktree's missing dependency dist, not this diff. After building the lint closure: 143 files, 6821 passed, 5 skipped; typecheck exit 0 (VERDICT command-exit 0). Repro before the fix: retired-key-migrate-sentence 2 failed / 13 passed; after: 15/15.",
      "gates": "dispatch-gates --commands derived 90 families for the new diff at e55aa1bf. First pass: 86 exit 0, 4 exit 3 (PREREQUISITE NOT MET, run before the lint closure was built): lint check:doc-formula-expressions, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure. All 4 re-run after the closure build: exit 0. --ran with exit codes: '90 derived famil(ies) accounted for — 90 run, 0 NOT-MEASURED (a DERIVED zero)'. CI on e55aa1bf: not waited on.",
      "pr_body_line": "Patch round 1 (e55aa1bf): `retired-key-migrate-sentence.test.ts` (`--project repo`, Test Core) now passes 15/15. Each `list-view` alias prescription now ends with the house `os migrate meta` sentence, verbatim and in one literal, and the react-tier note moved one sentence earlier. The conversion docblock now says `--write` rewrites a source. spec `test:repo` 1115 passed, spec `test` 20989 passed, lint 6821 passed; 90/90 derived gates exit 0.",
      "mcp_calls": "0 this round (the earlier round's 1, mcp__claude-code-remote__add_repo read, stands). ReadNotifications only. No GitHub MCP calls.",
      "api_writes": "1 this round: POST /repos/objectstack-ai/objectstack/issues/22444/comments (this report, via scripts/pm/post-stamped.mjs and the relay), plus git push (not REST). REST reads: GET pulls/24217, actions/jobs/117486552704 (its logs endpoint was not readable, so the failure was reproduced locally).",
      "files_changed": [
        "packages/spec/src/ui/component.zod.ts",
        "packages/spec/src/conversions/registry.ts"
      ],
      "line_budget": "n/a",
      "deviations": [
        "Step 2 said 'change nothing else in those strings'. The pin also requires the house sentence to be the last sentence of its merged literal (the scanner merges quoted-literal seams). So each string's react-tier note moved before the house sentence, with its text unchanged. Without that the pin stayed red (measured on 86c001e7).",
        "The first commit 86c001e7 was pushed red for the reason above; e55aa1bf is the fix. No history was rewritten."
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions