Repository navigation
docs: taught action:* nodes move their executor keys into the spec properties bag (objectui#11183) - #11317
Conversation
…uilder object-form move their props into the spec's properties bag The spec's PageComponentSchema is .strict() (ADR-0089 D3a) and refuses a flat actionType / target on a component node; objectui's strict authoring face refuses the same keys. Every taught action:button node under AGENTS.md, skills/objectui and content/docs/guide now writes the block's props in the properties bag, as the ComponentPropsMap row declares them. Same move for the record:activity example in plugin-detail.mdx (limit / showCompleted) and the page-builder "Form plugin example" (object-form, refused flat by name since objectui#11291). The runtime reads both spellings through the SchemaRenderer properties hoist, so only documents change. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg
… node in the properties bag, with a derived flat control held-public-block-arms-10872: the taught node now validates AS WRITTEN on both faces and on the spec's PageComponentSchema; the pre-move flat spelling is derived from the taught node (bag hoisted flat) and pinned as refused by exactly actionType and target on both strict faces, while the tolerant face still keeps it. registered-types-validate-ratchet-10859: lit control that the extracted node is in the bag spelling. Empty-frontmatter changeset: docs and pins only, nothing released. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Head resolved from Check-runs on the head (read three times, last at 2026-10-01T03:13Z): 43 runs — 40 Rulings taken as input: the card body's ruling A (the ① Derived judgments(a) Every edited fence, on three faces. 11
(b) The prose beside the nodes. Every refusal sentence names its refuser; none says (c) (d) Riders. (e) The measured NON-edit of (f) The two pins. (g) PR objectui#11069 overlap. Read its diff: on (h) Scope fences. (i) Census. Re-ran the instrument at the head: 11 hits under the roots, every node's own level is (j) Rule #11. PR body, changeset and every added diff line scanned for (k) Added lines on ② Semver levelDocs, two test files, one changeset. ③ Boundary flags
Governed-surface posture is correct: draft, awaiting an APPROVED review from Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读改了什么:把教给 AI 的 11 处 为什么改:分诊对 #10872 的裁决 A—— 风险与代价(含回滚):不改运行时、不改校验器,空 changeset 不发包;复审(契约复审档,记录 5924066480)逐个范例在三张面上核过。回滚 = revert。留给后续的: 席位意见:建议批准,并先于 PR #11069 合入。 你要做的:在本 PR 上留一条 APPROVED review(os-zhuang 或 hotlong);之后由本席翻 ready、挂 auto-merge 入队。 Generated by Claude Code |
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
Red check on this PR, read by the skills seat ( What is red. Why it is not this PR's. None of those five files is in this PR's diff (12 files: docs, What the seat does. One re-run of the failed job now, as the confirmation the rule allows. Green ⇒ auto-merge (armed 05:48Z) takes the PR back into the queue on its own; the seat clears Generated by Claude Code |
|
Second reading, skills seat ( The re-run of Act: Generated by Claude Code |
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
…jectui#11168 slice 3, round 3, third merge) origin/main advanced to 5638529 while the round-3 gates ran: #11317 (docs), #11352 (types, fields) and #11350 (plugin-grid, core). No conflict. #11352 also edits packages/types objectql.ts, objectql.zod.ts and zod-mirror-parity.test.ts, which this branch edits too; it auto-merged, and the gates are re-run at this head. The guard is untouched by this merge, so its census still reads as at 2817b5f: objectui#11168 5, unjudgedBlocks 2, refusedArms 0. Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT Co-authored-by: Claude <noreply@anthropic.com>
Fixes #11183
Clause-②: no
Every taught
action:*node underAGENTS.md,skills/objectui/**andcontent/docs/guide/**now writes the block's props in the spec'spropertiesbag, as the@objectstack/specComponentPropsMaprow declares them, instead of flat on the node. Triage's ruling on the objectui#10872 fork, carried by the card: A, thepropertiesbag is the contract. The spec'sPageComponentSchemais.strict()(ADR-0089 D3a) and refuses a node-levelactionType/targetas mis-layered; objectui'sStrictAnyComponentSchemarefuses the same two keys. The runtime reads both spellings through theSchemaRendererpropertieshoist, so only documents and their pins change — ⛔ no runtime or validator code in this diff.Order: this PR lands BEFORE PR objectui#11069 (objectui#5250,
objectui validateonto the strict face). objectui#5250 carriesBlocked-by: #11183; PR objectui#11069 touchescontent/docs/guide/layout.mdandschema-rendering.mdin other sections than the ones edited here (itslayout.mdhunk is thelabel/textparagraph under the page-buttons passage; itsschema-rendering.mdhunk is the three validation doors), so it mergesmainafter this lands with no textual overlap.Governed surface:
AGENTS.md,skills/objectui/SKILL.md,skills/objectui/guides/page-builder.md,skills/objectui/rules/protocol.md(node scripts/check-governed-queue-guard.mjs --testanswers exit 3, GOVERNED). This PR stays draft until an APPROVED review byos-zhuangorhotlong; the claiming seat lands it. Cross-lane surface (content/docs/**,packages/**pins), declared on the claim comment of the card.维护者速读(草稿)
改了什么。 文档与测试,零运行时代码。我们教给作者(和 AI)的
action:button示例,把actionType/target这类执行器键从节点顶层挪进了properties包里 —— 共 11 个节点、10 个文件(受管面 4 个:AGENTS.md第 #4 条、skills/objectui/SKILL.md、guides/page-builder.md、rules/protocol.md;非受管 6 个:content/docs/guide/下 4 篇指南、content/docs/plugins/plugin-detail.mdx、随同的两条 pin 测试)。同一家族的两处 rider 一并处理:plugin-detail 指南里的record:activity示例(limit/showCompleted进包),以及 page-builder 技能里的object-form表单示例(objectui#11291 落地后objectui validate已按名拒绝扁平写法)。另附一个空 frontmatter 的 changeset(声明不发版)。为什么改。 spec 的
PageComponentSchema是.strict()的(ADR-0089 D3a),节点顶层出现actionType/target会被当作错层键直接拒绝;objectui 自己的严格校验面StrictAnyComponentSchema同样拒绝这两个键。PR objectui#11069 正要把objectui validate切到这个严格面,届时受管规程文件里的标准示例就会变成校验器拒收的节点,而 agent 会照抄示例。裁决是「教的内容向 spec 靠」,不是反过来给 objectui 开一条 spec 拒绝的扁平通道。实测:12 个被改示例在改前全部被两个严格面拒绝,改后在宽容面、严格面、spec 三面全部通过(见下方 census)。风险与代价(含回滚)。 运行时无变化:
SchemaRenderer把properties整包提升到节点上再交给渲染器,两种拼写渲染结果相同;guide-layout-page-buttons-7926这条真实渲染 pin 读的就是 layout 指南里被改的那段 JSON,改后 Edit / Delete 两个按钮照常画出。代价是示例各长了 2–5 行。回滚:revert 本 PR 即可,没有任何生成物、锁文件或发布物需要同步;但回滚后 objectui#11069 不能先落地,否则规程示例会被校验器拒收。席位意见。(留空)
你要做的。 作为受管面 PR,需要你(
os-zhuang/hotlong)在本 PR 上留一条 APPROVED review;之后由认领席翻 ready 并入合并队列,⛔ 本 PR 不自行 ready、不自行入队。请顺手确认AGENTS.md#4 的新措辞(「props 住在properties包里,⛔ 不写在节点顶层」)是你希望 agent 读到的规则。Census (the gate the card asks for)
Instrument: for every
"type": "action:button|icon|group|menu"node undercontent/docs/**,skills/**,AGENTS.md,README.md(grep -rnE '"type":\s*"action:(button|icon|group|menu)"' content/docs skills AGENTS.md README.md), the keys written at the node's own level —actionType,target,endpoint,method,name,icon,variant,params,label— before the next node or the closing brace.caa0cd392(objectuiorigin/mainat cut)f580661Per site (base → branch), by heading, all in one commit each:
propertiesAGENTS.mdlabel,actionType,targetskills/objectui/SKILL.mdlabel,actionType,targetskills/objectui/rules/protocol.mdlabel,actionType,targetskills/objectui/guides/page-builder.mdlabel,actionType,targetskills/objectui/guides/page-builder.mdobject-formrider)objectName,mode,fieldscontent/docs/guide/quick-start.mdlabel,actionType,targetcontent/docs/guide/record-edit-modes.mdlabel,icon,actionType, and the already-baggedparamsstays in the same bagcontent/docs/guide/schema-rendering.mdname,label,actionType,endpoint,methodcontent/docs/guide/layout.mdname,label,variant,icon,actionTypecontent/docs/plugins/plugin-detail.mdxrecord:activityblock" (record:activityrider)limit,showCompletedEach edited fence judged on three faces (a probe run from
packages/typesagainst the sourcezod/index.zod.tsand the installed@objectstack/spec17.5.0): at base, every one of the 12 is refused byStrictAnyComponentSchemaand by the spec'sPageComponentSchemawith exactly the flat keys named above (theobject-formone is refused on the tolerant face too, by name, since objectui#11291); on this branch all 12 pass tolerant, strict and spec. The prose beside each fence moved with it: the sentence "the node's own keys carry that executor's arguments" now reads "the row's other keys" / "the bag's other keys", and each site says why the flat spelling is refused.skills/**line readings (the governed-surface reading, lines; no token meter exists for this surface —check:skill-eval-tokensmeters evalmust_containtokens, not file length):SKILL.md137 → 142,guides/page-builder.md346 → 353,rules/protocol.md364 → 370; bundleskills/objectui/**/*.md4782 → 4800; allSKILL.mdfiles 137 → 142. The whole increase is the bag's two wrapper lines per fence plus the one-sentence refusal note; nothing was re-wrapped.Pins moved
packages/types/src/__tests__/held-public-block-arms-10872.test.ts(reads the quick-start's "Add Actions" fence): the taught node now validates AS WRITTEN on both faces and on the spec'sPageComponentSchema; the pre-move flat spelling is DERIVED from the taught node (bag hoisted flat) and pinned as refused by exactlyactionTypeandtargeton both strict faces while the tolerant face still keeps it — so the reading of the refusal stays live and moves with the page.packages/cli/src/__tests__/registered-types-validate-ratchet-10859.test.ts(same fence, throughobjectui validate): lit control that the extracted node is in the bag spelling; the row still passes the tolerant facevalidateruns today and will pass the strict one PR objectui#11069 wires. ⛔ Its header andrefusedAtTypehelper — the lines PR objectui#11069 edits — are untouched here.git checkout BASE -- content/docs/guide/quick-start.md⇒ 4 red (reads the taught node … bag spelling,strict face: the taught node AS WRITTEN … validates,the spec's own PageComponentSchema accepts the taught node as written, the ratchet'svalidates a page with the taught action:button node), 60 green;git checkout HEAD -- …restored,git diff HEADempty,git hash-objectof the page equals its HEAD blobca70f902fc5c….Gates run locally (head
f580661; exit codes read before any pipe)Derived from
.github/workflows/*.ymlonorigin/main(41 files, the same count the working tree lists): my diff touches**/*.md,content/**,.changeset/**AND twopackages/*/src/__tests__/*.test.ts, so theDecide whether this change needs a full runstep inlint.yml/ci.ymlanswersshould_run=true, every always-on doc gate fires, andchangeset-guard.ymlfires on the.changeset/**path.node scripts/check-skills-paths.mjsnode scripts/check-skill-examples.mjs --self-test·node scripts/check-skill-examples.mjs(both after the scoped build its--build-filternames, 30 tasks; before the build both answer exit 2 = could not run, not a verdict)node scripts/check-skill-eval-tokens.mjs --self-test·node scripts/check-skill-eval-tokens.mjsnode scripts/check-new-cross-file-line-citations.mjsnode scripts/check-control-bytes.mjsnode scripts/check-doc-*.mjsnode scripts/check-doc-snippet-types.mjs(after the full buildpnpm turbo run build --filter='!@object-ui/site', 43 tasks)node scripts/check-changeset-presence.mjs·node scripts/check-changeset-no-major.mjs·check-changeset-claims·check-pending-changeset-literalsnode scripts/check-readme-exports.mjs(after the full build)node scripts/check-*.mjsnode scripts/check-comment-mask-corpus.mjs·node scripts/markdown-test-inputs.mjs --auditnode scripts/check-governed-queue-guard.mjs --test AGENTS.md skills/objectui/SKILL.md skills/objectui/guides/page-builder.md skills/objectui/rules/protocol.mdlint.ymlroster)pnpm lint --concurrency=2(47 tasks, 0 errors) ·node scripts/check-vi-mock-override-shape.mjs·node scripts/check-test-path-roots.mjs·pnpm --filter '@object-ui/cli...' build·pnpm checkci.yml) — the affected testspnpm exec vitest runon the two moved pins +guide-layout-page-buttons-7926(3 files, 71 tests) · the other eight ledgered readers of the edited docs (8 files, 87 tests) · the rootscripts/suite (177 files, 5371 tests, 2 skipped)tsc -p packages/types/tsconfig.test.json·tsc --noEmitinpackages/cli·eslinton the two test filesNot run locally, declared to CI: the full
pnpm testshards (ci.yml), Live E2E, Spec Main Shape Gate (it builds@objectstack/specfrom objectstackmainon the runner), Bundle Analysis. Heavy steps ran under/home/user/objectstack/scripts/pm/os-verify-lock.sh(three locked runs: the scoped build 234 s held, the scripts suite + lint, the full build + two gates after a 452 s queue wait).Acceptance notes
packages/plugin-detail/README.md— theitemshalf of therecord:activityrider is NOT moved, by measurement.ComponentPropsMap['record:activity']on the installed spec has noitemskey (its keys:aria,enableMentions,enableReactions,enableThreading,filterMode,limit,showCommentInput,showCompleted,showFilterToggle,showSubscriptionToggle,types,unifiedTimeline), and both objectui faces refuseproperties.itemsby name, so the bag spelling would turn a working example into a refused one. The README's example is TSX code composing aDetailViewSchemawhose Activity tab hands the block a host-supplied feed —record-activity.tsxreadsschema.itemsas the first of its three feed sources — the same runtime-slot shape asrecord:history'sentries. Left as is; reported in the dev report for thedomain:uilane to rule on whetheritemswants a named RUNTIME SLOT refusal on the authoring faces.packages/app-shell/README.mdteaches two flataction:buttonnodes (navigate_create/navigate_edit, under "The handler name goes inactionType"), the twin of therecord-edit-modes.mdpassage moved here. Outside the claimed surface; in the dev report as a finding, not edited.content/docs/api/schema-reference.md"ActionSchema" teaches"type": "action"nodes withactionType: "ajax"and anapikey — a vocabularyschema-rendering.mditself says no action renderer forwards. Not anaction:*public block; not edited.check:skill-eval-tokensmeters skill-file length; it meters evalmust_containtokens against the bundle (its header's "THE ORACLE" section). No length ceiling gate exists forskills/**in this tree; the line readings above are reported in its place.guides/app-composition.mdnav label) does not ride this PR; that file is untouched.Session:
session_01KTZmMfzVzjNvyaLyQ8mHvg(PM loop round 11, claim comment 5923347428).Generated by Claude Code