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.

list 从不渲染 children,且全仓不存在 item / index 迭代作用域 —— schema-expressions.md 的「Iteration scopes」整节是空头支票 #4797

Description

@yinlianghui

发现于 #4786 的实施,真实 SchemaRenderer 探针实测。

教学面的承诺

skills/objectui/guides/schema-expressions.md 的 "Iteration scopes (loops)" 一节写着:

Components like Grid, List, and Table inject scoped variables for each item
... Inside the loop body, item refers to the current element and index to its 0-based position.

并给出 { "type": "list", "bind": "users", "children": [ { "type": "card", ... "${item.name}" } ] }。

实测:两条都不成立

@@PROBE list/children-toplevel  text=""   ({type:'list',bind:'users',children:[{type:'text',content:'X'}]}, users=2 条)
@@PROBE list/items-as-nodes     text="AdaLinus"   ({type:'list',items:[{content:'Ada'},{content:'Linus'}]})

第一行:绑定了 2 条数据,渲染出 2 个空 li,children 一次都没进去。

成因(读码)

packages/components/src/renderers/data-display/list.tsx 的 render body:

{items.map((item: any, index: number) => (
  <li key={index} className={cn(typeof item === 'object' && item.className)}>
    {typeof item === 'string' ? item : item.content || renderChildren(item.body)}
  </li>
))}

它把绑定到的数据条目本身当作 schema 节点渲染(读 item.content / item.body),完全不看 schema.children。所以 list 是"数据即节点"的形态,不是"模板 + 迭代"的形态。

而 item / index 作用域:ExpressionEvaluator 在 packages/react/src/SchemaRenderer.tsx 里的 scope 是 { ...predicateScope, current_user, data: dataSource, page: pageVariables } —— 没有 item,也没有 index。全仓 grep 不到任何往求值作用域注入 item: / index: 的地方。

为什么 #4786 没有顺手改

#4786 的范围是拆 props 信封。这一节的示例确实带信封,但信封不是它的病根:把 title 提到节点上,${item.name} 既不会被求值(#4795)、children 也根本不会被渲染 —— 改完会变成一个"看起来修好了、其实照样空白"的示例,比原样更难被发现。故 #4786 的 PR 刻意保留了这一处信封原样,并在其甄别表里指向本单。

修法方向(需裁决)

  1. 实现迭代:给 list(以及 prose 里点名的 Grid / Table)加真正的模板迭代 + item/index 作用域注入。这是新能力,不是修 bug。
  2. 收缩文档:删掉「Iteration scopes」整节,改为如实描述 list 的"数据即节点"形态。

哪条都不该由实施 agent 自己猜 —— prose 承诺的是能力 1,代码实现的是形态 2。

参考

Activity

  1. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    Contributor

    Triage: needs-user-decision, type Feature. The docs promise iteration scopes (item/index, children templates) that no code implements — enforce-or-remove at the capability grain: build template iteration (a real new capability) or shrink the docs section to the measured "data-as-nodes" shape. Feature-vs-docs-retreat is an appetite call — human floor.

    Four prisms:

    1. Platform long-term coherence — either resolution closes a declared≠implemented split; leaving it teaches authors a fiction.
    2. Measured business pull — zero: ${item.*} never worked, so no usage can exist. No pull for the capability itself today.
    3. AI-agent error-resistance — the current prose is an AI trap: a schema-writing agent follows it into silently-empty lists. Docs retreat alone already removes the trap.
    4. Startup scope discipline — an iteration engine is meaningful permanent surface; docs retreat costs one section.

    Recommendation: retreat the docs now (describe the real list shape honestly); file the iteration capability as a separate spec-first design card only if product pull appears. Joint axis with #4795 — recommend ruling both in one sitting.


    Generated by Claude Code

  2. os-zhuang commented on Aug 17, 2026

    @os-zhuang
    Contributor

    Maintainer ruling (2026-08-17, recorded by PM session session_01NYgmGheCzM6NrHZN436Cxf). The maintainer accepted the decision-inbox report's recommendations in full, verbatim: 「同意」. Ruled together with #4795 (same evaluation contract):

    Ruled: docs retreat now; the iteration capability is not built and not carded.

    • The "Iteration scopes (loops)" section of skills/objectui/guides/schema-expressions.md is removed/rewritten to describe the measured list shape honestly (data-as-nodes: items are rendered via item.content/item.body; no children template, no item/index scope exists anywhere in the evaluator). The AI-author trap (a followed example rendering silently-empty lists) closes with the prose.
    • Zero measured pull for template iteration — ${item.*} never worked, so no usage can exist. A real iteration engine is meaningful permanent surface; it gets a spec-first design card only if product pull appears (named restart: a real app/authoring need for template-per-item rendering that data-as-nodes cannot express).
    • ⚠️ Note for the implementer: skills/** is the published-skills root — skills edits are ADR-class (human-merged, terminal three-piece), and the pm-dispatch tiering clause ① applies if any .claude/skills file is touched; this card's target is the published skills/objectui guide ⇒ human merge required.

    Label flipped needs-user-decision → pm:queue in the same stroke.


    Generated by Claude Code

  3. self-assigned this
    on Aug 18, 2026
  4. yinlianghui commented on Aug 18, 2026

    @yinlianghui
    ContributorAuthor

    认领(PM 派发,objectui 分片):session_01GTRjn8xBqp75dk7kFupVRt,分支 claude/issue-4797-iteration-scopes-retreat,os-dev 席即将开工。

    按维护者裁定(评论 5312062029)执行 docs retreat:重写 skills/objectui/guides/schema-expressions.md 的「Iteration scopes (loops)」节为实测的 data-as-nodes 形,迭代能力不立卡(命名重启条件已记录)。⚠️ skills 人合车道:PR 验收后 PM 只转 ready、不挂 auto-merge,留维护者亲合(PR #5080 先例)。文件面与在飞席位(RelatedList.tsx、SchemaRenderer.tsx、CLI knownTypes)不相交;与 #4795-方向3 同裁定轴但不同文件,无序依赖。


    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

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions