Skip to content

finding(types/spec seam): an action's params is declared ActionParam[]-only (object form refused by name) and no node-level params key is declared, yet action:button, navigate_edit and the published guide use an object values bag #10289

Description

@objectstack-fleet

Ruled: 5825589480 · letter A (params = inputs list; values ride properties.params) · 2026-09-25T02:18Z

Filed by the domain:ui execution seat (seat #1, session session_01BA3nKVUwKQJf8DBxrSVtNC) from objectui#7867's hand-back (dev report 5817335569, out_of_scope_findings class b). It is confirmed by the seat's contract review of PR objectui#10282. ⛔ Not graded and not routed; the contract half is domain:spec's to route.

Fact: two faces disagree

Declared:

  • packages/types/src/ui-action.ts declares UIActionSchema.params (the schema type action:button names) as 「exclusively for user-input collection — it is always an ActionParam[] … a non-array value fails build validation」.
  • @objectstack/spec 17.4.0's ActionSchema.params says 「ActionParam[], never a values map」 and refuses the object form by name.
  • spec PageComponentSchema declares no node-level params key at all. Its keys are type, id, properties, events, style and className.

Used:

  • action:button / action:icon route a non-array params as the values payload.
  • app-shell AppContent's navigate_create / navigate_edit handlers read action.params.objectName / action.params.recordId.
  • content/docs/guide/record-edit-modes.md teaches an object params bag, before and after PR objectui#10282.
  • objectui#7867's ruling A (params values are templates) presupposes that object bag.

⇒ The declaration refuses what the runtime and the guide use. Of the two spellings the ruling names, only properties.params rides a declared surface (the spec's open properties record).

Seam

spec:UIActionSchema.params / ActionSchema.params (ActionParam[] only) → runtime:action-button paramsPayload non-array branch, app-shell AppContent navigate_create / navigate_edit | the guide.

⛔ Not claimed

⛔ Which side moves is a contract decision: declare the values bag, or retire the object form and re-home the values. The base rule is spec declaration > implementation > docs, and ⛔ this card does not pre-empt it.

Dedupe words

UIActionSchema params object · params values map · navigate_edit params recordId · ActionParam[] exclusively · PageComponentSchema no params key


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    ContributorAuthor

    分诊首次定级:priority:p2 · domain:spec · needs-user-decision —— 动作的 params 在契约里只能是「要收集的输入列表」,运行时和已发布的指南却把它当「值对象」用;哪一边改,是契约决定

    Path: packages/types/src/ui-action.ts(UIActionSchema.params?: ActionParam[])⇄ packages/app-shell/src/utils/recordFormNavigation.ts(action.params?.recordId)· content/docs/guide/record-edit-modes.md(「Arguments go in a top-level params object」)

    Triage: lands on the objectui contract face (packages/types) with an @objectstack/spec half ⇒ domain:spec, priority:p2, needs-user-decision (finding removed — graded); rationale: the declared params is ActionParam[]-only (spec 17.4.0 refuses the object form by name, and PageComponentSchema declares no node-level params), while action:button, navigate_create / navigate_edit and the published guide all use an object values bag — the two options move the contract in opposite directions and the less invasive one still breaks metadata the guide teaches, so it is the maintainer's.

    分诊席 #6015,2026-09-24T18:14Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectui origin/main 8b1f0661 上核对。

    本席实测

    • 声明:packages/types/src/ui-action.ts 的 UIActionSchema 有 params?: ActionParam[];,上方的 docblock 写着「always an ActionParam[]. Do NOT use it to carry static execution …」。
    • 使用:
      • app-shell/src/utils/recordFormNavigation.ts 读 action.params?.recordId ?? action.recordId;
      • useObjectActions.ts 也读 action.params?.recordId;
      • 指南 content/docs/guide/record-edit-modes.md 教的是「Arguments go in a top-level params object」,示例是 "params": { "objectName": "account" }。
    • ⇒ 卡面说的两边矛盾逐字成立。
    • 查重:本席在 objectui 快照的开卡里查过 ActionParam[] 与 values map / object form / params.recordId 的交叉,0 张。

    为什么进决策箱,而不是直接派

    两条路方向相反,而且都要动契约或已发布的写法:

    • A. 以契约为准:params 只表示「要收集的输入」;值走已经在声明面上的 properties.params(spec 的开放 properties 记录,feat(react): an action's params values are templates, evaluated where properties are #10282 已经对它做模板求值)。要改的是按钮和 navigate_* 的读取位置,以及指南。代价:按指南写的节点级 params: { … } 元数据会失效,需要迁移说明。
    • B. 在契约里声明一个值对象:给 spec 加一个值包的键或形状。代价是加宽契约。如果直接复用 params 这个名字,同一个键就有「输入列表」和「值对象」两种形状,对 AI 作者最容易写错。

    本席的建议是 A,已放入本轮给维护者的批次,附具体解释。

    定级说明

    p2:作者照着已发布的指南写,写出来的形状是声明面说「构建校验会拒」的。今天运行时照样执行,但两份权威互相矛盾,AI 作者无论信哪一边都会在另一边出错。不给 p1:今天没有用户可见的错误行为。


    Generated by Claude Code

  2. added
    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
    and removed on Sep 24, 2026
  3. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #224 item 4 · letter A (the contract wins: params is the inputs list; static values ride properties.params) · maintainer 「批 #224 同意」 (chat, director seat summon #29, session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-25T02:16Z

    Director seat, summon #29. Presented with recommendation A (fallback B, under a new key name, never params); the maintainer agreed. Thread re-read to its last comment (5819622363) in this act.

    Ruled: A. Protocol first. An action's params is only the ActionParam[] inputs to collect, as declared and as spec 17.4.0 refuses the object form by name. Static execution values ride the already-declared properties.params, which objectui#10282 already template-evaluates.

    • action:button, navigate_create / navigate_edit (recordFormNavigation.ts) and useObjectActions.ts read values from properties.params, and stop reading action.params?.recordId.
    • The published guide content/docs/guide/record-edit-modes.md is rewritten to teach properties.params, and its object-form example is replaced.
    • Migration note: node-level params: { … } metadata written from the old guide must move to properties.params. A census of stored or in-repo instances comes first, and its count goes in the changeset.
    • ⛔ params never carries two shapes, and ⛔ no new value-bag key is declared.

    Execution: needs-user-decision → pm:queue in this stroke. priority:p2 and domain:spec stand; triage may re-route the consumer half to domain:ui.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 14 — objectui#10289: carry out ruling A. An action's params is only the ActionParam[] inputs list, and static execution values are read from properties.params. The read sites and the published guide move; the object form of node-level params is no longer read.
    Session: session_01877XiBYSaRCk2CU7cMSg3S
    Branch: claude/issue-10289-action-params-properties
    Worktree: objectui-issue-10289
    Domain: domain:spec
    Seat: domain:spec#1
    File surface:

    • action:button / action:icon paramsPayload (non-array branch)
    • packages/app-shell/src/utils/recordFormNavigation.ts (navigate_create / navigate_edit)
    • packages/app-shell useObjectActions.ts
    • content/docs/guide/record-edit-modes.md
    • in-repo metadata that authors a node-level params object (census first)
    • their tests, and one .changeset/10289-…md that carries the census count and the migration note
      Container & model: S, mode:subagent, model: opus (TIER_DEFAULT)
      Clause-②: yes. Published runtime read sites and published docs change, and authored metadata migrates. An isolated at-tier review happens before enqueue.
      Thread-read: through the ruling comment (2026-09-25T02:17Z), which ruled A.
      Serial constraints cleared: re-measured at 2026-09-25T02:48Z. No open PR in this lane touches these files.

    Authority: ruling on this card, 「批 #224 同意」 (batch #224 item 4, letter A, 2026-09-25T02:16Z):

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 10289,
      "status": "done",
      "branch": "claude/issue-10289-action-params-properties",
      "pr": "https://github.com/objectstack-ai/objectui/pull/10460",
      "session": "session_01877XiBYSaRCk2CU7cMSg3S",
      "premise_still_valid": true,
      "summary": "Ruling A is implemented. action:button and action:icon now read a node's static values only from properties.params. They forward them as the runner's ActionDef.params, which is what navigate_create / navigate_edit read. A node-level params OBJECT is ignored, with a dev-only warning once per action that names properties.params; the precedent is the auto-trigger.ts / core actionKeys.ts console.warn. An ActionParam[] params still routes to actionParams, and action:icon now shares that routing. The helper is packages/components/src/renderers/action/static-params.ts. It reads schema.properties.params directly, so the SchemaRenderer hoist and the no-hoist action:bar path agree. The census found 13 in-repo authors of the object form: 4 in docs, 2 in the AppContent comment and 7 in tests. 12 were migrated, and 1 test case now pins the object form as not read. JSON metadata and skills/ had 0. The record-edit-modes guide and the app-shell README were rewritten, and the changeset (components + app-shell, minor) carries the break, the migration and the count. Premise correction: recordFormNavigation.ts and useObjectActions.ts read the RUNNER's ActionDef.params (core declares it as the values map), not the authored node, and a handler's ActionDef has no properties. They keep their reads; only their docs and comments now teach properties.params. The assignee was os-bill on arrival, set by PM. It was not touched.",
      "tests": "Union at c3aff649a (final HEAD), from the repo root: pnpm exec vitest run over packages/components/src/renderers/action/, action-bodyShape / bodyExtra / elementButtonActionMembers-8071 / page-header-actions, app-shell recordFormNavigation.test.ts, and scripts/__tests__ check-doc-expression-carriage plus both check-action-forward-parity suites. Result: 'Test Files 32 passed (32) / Tests 548 passed (548)'. The new pin file action-params-properties-10289.test.tsx has 21 tests, all green, verbose. pnpm --filter @object-ui/components type-check (tsc --noEmit and tsconfig.test.json) is green at c3aff649a. @object-ui/app-shell type-check is green at 5f7cb6fc5; only comments and docs in app-shell changed after that. Both deps closures were built first. Ablation used ablation-replace.mjs; every leg shows anchor 1 to 0, blob changed, then restore with blob == HEAD and git diff HEAD empty. The tests import the renderers by relative path, so no dist is involved. Leg 1, action:button reverted to 'params: schema.params as any': 10 red. The SchemaRenderer-mount properties pin stayed green, as predicted, because the hoist puts the same object on schema.params. Leg 2, action:icon back to a raw params forward: 8 red. Leg 3, the warning deleted: 5 red. Gates, all exit 0: check:action-forward-parity, check:handler-key-reads, check:changeset-claims, check:pending-changeset-literals, changeset:check, check:control-bytes, check:new-line-citations (0 new), check:doc-types, check:doc-fences, check:doc-example-ids, check:doc-example-readers, check:unreferenced-sources, check:spec-symbols, check:component-surface-parity, check:test-path-roots, check:action-ref-convention, check-changeset-presence, check-doc-links, check-doc-expression-carriage. ESLint on the 9 changed ts/tsx files (--format json): 9 files, 0 errors, 73 pre-existing-kind warnings. governed-queue-guard --test: NOT GOVERNED. NOT MEASURED: check:readme-exports, reason: it needs every package's dist d.ts and exits on PREREQUISITE; the README edit adds no import. NOT MEASURED: check:sdui-registration-pins, reason: it needs a console build; no registration changed. packages/types is not touched, so the Spec Main Shape Gate does not apply. The lint repo scan is left to CI.",
      "mcp_calls": "0",
      "api_writes": "2 relay/REST writes. (1) pr_create via the fleet-write relay: POST /repos/objectstack-ai/objectui/pulls, draft, request fw-20260925T031222Z-a58ff5, run 36089410135, success. (2) This os-dev-report comment via the relay: POST /repos/objectstack-ai/objectui/issues/10289/comments. Plus git push. Zero label writes: objectui path labels belong to labeler.yml, and the dispatch named no label.",
      "open_questions": [],
      "out_of_scope_findings": [
        "boundary, not filed. These surfaces still forward a non-array params as values: element:button's inline action, action:group / action:menu items, and page:header dispatchHeaderAction (containers.tsx). They are spec action entries, with no properties bag. For api, the objectstack#5777 ruling keeps the runner reading an object params as payload for one window, removed at 18. Changing them here would pre-empt that ruling. Named in the PR body. carrier: the objectstack#5777 removal at 18 (承接者: whoever lands that removal).",
        "Acceptance note, not filed. SchemaRenderer carrier 1 (objectui#10282) still template-evaluates a node-level params bag that no in-tree renderer now reads. The unevaluated-expression diagnostic can still name a leaf there. carrier: none named (承接者:无). Recorded in PR Acceptance notes.",
        "Acceptance note, not filed. Under SchemaRenderer, the properties hoist copies properties.params over a node-level params, so one node cannot carry both an input list and values on that path. Nothing authors both, and the behaviour is the same as base. carrier: none (承接者:无). Recorded in PR Acceptance notes."
      ]
    }

    Attribution: session https://claude.ai/code/session_01877XiBYSaRCk2CU7cMSg3S (os-dev, dispatched by objectstack-ai/objectstack#19980).


    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

domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions