Repository navigation
Commit a4c3246
docs(skills): teach an action param's widget key in the action dialog (#30684)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DRWthi8yfG9DK3ZmXw4eGpW)_
domain:skills#1 · os-elon-musk · session_016WV4cyNZ7aKsfF5vTBgKKn
Fixes #30549
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么:** 两个技能文件教动作参数的 `widget`:objectui 协议规则的内联参数清单加上
`widget`(写注册过的字段控件名,如 `text` 参数写 `'permission-ref'` 就是权限集选择器;未注册的名字退回
`type` 控件,批量对话框不读它,服务端仍按 `type` 校验);objectstack-ui 动作规则说清字段型参数只在沿用或重述字段
`type` 时继承字段的 `widget`,改了 `type` 要自己写 `widget`。
- **为什么改:** PR #30543 落地后控制台已读这个键,但技能没教,作者和 AI
仍写自由文本参数;原句还暗示字段型参数总会继承字段控件,与代码不符。
- **风险与回滚:** 只改文档,无 schema、键或行为变化;token 预算靠同文件删重复句付清,不抬上限。回滚即撤销本 PR。
- **先看:** ① `skills/objectui/rules/protocol.md` 的 Inline params 条;②
`skills/objectstack-ui/rules/actions.md` 的 Action Parameter Patterns 段;③
两文件中被删的重复句(付账用)。
- **两分钟验证:** `node scripts/check-skills-token-ratchet.mjs`,预期 actions.md
2259/2259、protocol.md 4352/4368,整体通过。
- **需要你做的:** 审阅并批准(`skills/**` 为 Tier H,需人工合并)。
## What changes
- `skills/objectui/rules/protocol.md`, "Inline params": the
widget-config list gains `widget`. It names a registered field widget
that draws the param instead of its `type` widget (`'permission-ref'` on
a `text` param is the permission-set picker); an unregistered name keeps
the `type` widget; the selection bar's bulk dialog ignores it; the
server validates by `type`.
- `skills/objectstack-ui/rules/actions.md`, "Action Parameter Patterns":
the field's `widget` is inherited only while the param keeps or restates
the field's `type`; a param that overrides `type` names its own
`widget`.
- One root changeset, `'@objectstack/skills': patch`.
Every taught fact is read off `origin/main` (`b77c160a`), not the card's
prose:
- `ui/packages/fields/src/resolveActionParams.ts` `inheritedWidget`: the
param's own `widget` wins; with no `type` the field's `widget` is
inherited; with a `type`, only when `resolveParamWidgetType(param.type)
=== resolveParamWidgetType(field.type)`. Inline and unresolved branches
copy `param.widget`.
- `ui/packages/app-shell/src/utils/paramToField.ts` `authoredWidgetKey`:
a name `resolveFormWidgetType` resolves (not the `text` fallback)
replaces the `type` widget key; otherwise the `type` widget stays.
- `packages/spec/liveness/action.json` `params.widget`: `live`; the
dispatcher still validates the submitted value by `type`; not read by
plugin-grid `bulkParamToField`.
- `permission-ref` is a registered widget
(`ui/packages/fields/src/FieldEditWidget.tsx`,
`ui/packages/components/src/renderers/form/form.tsx`).
### Token ratchet: paid by same-file deletion, no ceiling raise
| file | before (bytes / tokens) | after (bytes / tokens) | ceiling |
|---|---|---|---|
| `skills/objectstack-ui/rules/actions.md` | 9024 / 2256 | 9033 / 2259 |
2259 |
| `skills/objectui/rules/protocol.md` | 17456 / 4364 | 17408 / 4352 |
4368 |
Lines: actions.md 179 → 180, protocol.md 377 → 377 (whole-file `wc -l`).
No SKILL.md changes, so the package's SKILL.md sum is unchanged.
Deleted restatements (each already said elsewhere in the same file):
- protocol.md: "resolve the value in the host … or carry it on a `text`
node's `content`" under *Fields That are NOT Evaluated* (the Bindable
Text Keys rule says it, and now carries the `SchemaRenderer` wording);
"There is no way to opt a type in from metadata …" (the closed-list
sentence above it says it); "the third row works today, but its channel
is an open contract question" (the Keys Live on the Node rule says it,
and the sentence already points there).
- actions.md: "so a body that must scope by org reads it from `ctx`
explicitly" (the preceding sentence says how to read the org); the
`skipped while newTabUrl is set` comment (the prose says `newTabUrl`
skips the round-trip); `static template;` in a comment (the heading line
says static `target`).
## Why
After PR #30543 the action dialog draws a param's `widget`, but neither
skill named the key, and the actions rule promised that every
field-backed param inherits the field widget. Authors kept writing
free-text params where a picker exists.
## Acceptance notes
- The bulk dialog's limit is stated as a limit, not taught as supported
(card "Not in scope").
- The field-backed bullet in `protocol.md` still lists what is inherited
without `widget`; the inheritance rule is taught once, in `actions.md`,
to stay inside the ceiling.
## Verification
All local readings are on head `f49a7c33` (the only commit), base
`b77c160a`.
<details><summary>Gates: 44 derived families + pnpm lint</summary>
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 44 families from the diff; each ran
with its exit code captured before any pipe, then `--ran` reconciled: `✓
dispatch-gates --ran: 44 derived famil(ies) accounted for — 43 run, 1
NOT-MEASURED (1 DERIVED from a recorded exit 3).`
- 43 families: exit 0, including `check-skills-token-ratchet.mjs` (and
`--self-test`), `pnpm --dir ui exec vitest run scripts/`,
`check:skill-examples`, `check:doc-formula-expressions`,
`check:doc-authoring`, `check:skill-identifier-liveness`,
`check:nul-bytes`, `check-empty-changeset`, `check-changeset-no-major`,
`check-adr-0087-registration`.
- NOT MEASURED: `pnpm check:dual-build-cjs-loads`, reason: exit 3,
PREREQUISITE NOT MET (needs a whole-tree build; only the
`@objectstack/client-react...`, `@objectstack/formula`,
`@objectstack/lint...` closures were built). CI runs it.
- `pnpm lint`: exit 0.
- `check-commit-card-trailers.mjs --range origin/main..HEAD`: pass.
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cyNZ7aKsfF5vTBgKKn)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 254f2ec commit a4c3246
3 files changed
Lines changed: 28 additions & 15 deletions
File tree
- .changeset
- skills
- objectstack-ui/rules
- objectui/rules
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
119 | | - | |
| 118 | + | |
120 | 119 | | |
121 | 120 | | |
122 | 121 | | |
| |||
135 | 134 | | |
136 | 135 | | |
137 | 136 | | |
138 | | - | |
| 137 | + | |
139 | 138 | | |
140 | 139 | | |
141 | 140 | | |
| |||
156 | 155 | | |
157 | 156 | | |
158 | 157 | | |
159 | | - | |
| 158 | + | |
160 | 159 | | |
161 | 160 | | |
162 | 161 | | |
| |||
172 | 171 | | |
173 | 172 | | |
174 | 173 | | |
175 | | - | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
176 | 177 | | |
177 | 178 | | |
178 | 179 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
34 | | - | |
35 | | - | |
36 | | - | |
| 34 | + | |
37 | 35 | | |
38 | 36 | | |
39 | 37 | | |
| |||
95 | 93 | | |
96 | 94 | | |
97 | 95 | | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
102 | 99 | | |
103 | 100 | | |
104 | 101 | | |
| |||
247 | 244 | | |
248 | 245 | | |
249 | 246 | | |
250 | | - | |
251 | | - | |
| 247 | + | |
252 | 248 | | |
253 | 249 | | |
254 | 250 | | |
| |||
307 | 303 | | |
308 | 304 | | |
309 | 305 | | |
310 | | - | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
311 | 311 | | |
312 | 312 | | |
313 | 313 | | |
| |||
0 commit comments