Skip to content

Commit fea6706

Browse files
docs(skills): objectstack-ui puts the create/edit form under form, not a named formViews entry (#21651)
Fixes #21537 Clause-②: no ## What this changes `ViewSchema.form` is a container's "Default form view" and `formViews` are "Additional named form views" (`packages/spec/src/ui/view.zod.ts` lines 4782 and 4784 at `origin/main` 15fe567). Since PR #21535 landed, `expandViewContainerWithDiagnostics` serves `form` as the one default form and promotes no named form in its place, so a container whose only form is a named `formViews` entry declares no default form. Three positions in the published `objectstack-ui` skill taught exactly that shape. Each now authors the create/edit form under `form`: 1. `skills/objectstack-ui/SKILL.md` — the subforms example (option 2 under entering a record together with its child line items): `formViews` with a `default` key becomes `form`, one nesting level fewer; the inline comments are kept. 2. `skills/objectstack-ui/rules/list-views.md` — the os:check marked `defineView` container: the `formViews` block with an `edit` key becomes `form`, placed after `list` in the schema's own declaration order (`list`, `form`, `listViews`, `formViews`); the callout now reads "Every view lives under `list` / `form` / `listViews` / `formViews`". 3. `skills/objectstack-ui/evals/views-apps-actions-pages.json` — eval 1's `expected_output` now expects `defineView({ list, form, listViews })` and "`form` with `type: 'simple'`". Its `must_contain` / `must_not_contain` reference no changed spelling and are untouched. Every `formViews` occurrence in `skills/objectstack-ui/**` at the base, and its disposition: | Location | Text | Disposition | |:--|:--|:--| | `SKILL.md:14` | "`formViews` `type: 'wizard'`" | legitimately named (wizard) — unchanged | | `SKILL.md:77` | subforms example, `formViews` with `default` | position 1 — moved to `form` | | `SKILL.md:207` | "Define default `list` + `form`, then named `listViews` / `formViews`" | the control row — unchanged; that table row is held by the in-flight sibling #21567, which is not addressed here | | `rules/list-views.md:14` | "aggregating the default `list`, named `listViews`, and `formViews`" | outside the claimed region (the container and the callout) — unchanged; see Acceptance notes | | `rules/list-views.md:29` | container `formViews` with `edit` | position 2 — moved to `form` | | `rules/list-views.md:38` | callout | position 2 — names `form` now | | `evals/views-apps-actions-pages.json:7` | eval 1 expected output | position 3 — expects `form` | | `evals/views-apps-actions-pages.json:57` and `:60` | wizard eval and its `must_contain` | legitimately named (wizard) — unchanged | ## Parse proof (built spec at a864ccc) `expandViewContainerWithDiagnostics('support_case', container)` imported from `packages/spec/dist`, on the `list-views.md` container before and after: - before (`formViews` with `edit`, no `form`): forms served = `support_case.edit`, `isDefault` absent; collisions none - after (`form`): forms served = `support_case.form`, `isDefault: true`; collisions none ## Readings Whole-file lines and ratchet tokens, before → after (base 15fe567 → a864ccc): | File | Lines | Tokens | Ceiling (headroom before → after) | |:--|:--|:--|:--| | `skills/objectstack-ui/SKILL.md` | 310 → 308 | 3854 → 3843 | 3856 (2 → 13) | | `skills/objectstack-ui/rules/list-views.md` | 302 → 300 | 3068 → 3065 | 3141 (73 → 76) | | `skills/objectstack-ui/evals/views-apps-actions-pages.json` | 65 → 65 | 1505 → 1502 | 1505 (0 → 3) | Whole package (sum of every `skills/**/SKILL.md`): 4397 → 4395 lines. No ceiling moved. No changeset: the diff publishes nothing from a released package (skill text only), so `skip-changeset` applies. ## Verification (all at a864ccc; every exit code captured before any pipe) - `pnpm --filter @objectstack/spec build` — exit 0 (under `scripts/pm/os-verify-lock.sh`, "VERDICT command-exit 0"). - `pnpm --filter @objectstack/spec run check:skill-examples` — exit 0: "260 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them"; the edited os:check container is among them. A first run exited 3 (PREREQUISITE NOT MET: `packages/client-react/dist` unbuilt, nothing measured); `@objectstack/types`, `core`, `client` and `client-react` were then built directly and the gate rerun. - `pnpm --filter @objectstack/spec run check:skill-docs` — exit 0 (`skills/README.md`, `content/docs/ai/skills-reference.mdx` in sync); `check:skill-refs` — exit 0 ("9 generated files in sync"). - `node scripts/check-skills-token-ratchet.mjs` — exit 0: "54 authored bundle file(s) within their ceilings"; `--self-test` exit 0 (65 cases). - `node scripts/pm/dispatch-gates.mjs --commands` with no paths derived 24 families from the diff at a864ccc; all 24 run, every exit 0; `--ran` reconciliation: "24 derived famil(ies) accounted for — 24 run, 0 NOT-MEASURED". The derived set equals the dispatch's list minus `check:skill-examples`, which was run anyway. `pnpm --filter @objectstack/lint run check:doc-formula-expressions` exited 3 (PREREQUISITE NOT MET) on the first run and 0 after `@objectstack/formula` and `@objectstack/lint` were built. `pnpm check:nul-bytes` exit 0. - Repo-wide `pnpm lint` is CI's run, not run locally (declared narrowing: the diff is Markdown and JSON only, no ESLint-governed file). ## 维护者速读(草稿) **改了什么。** 发布的 `objectstack-ui` 技能有三处把「新建/编辑表单」写在 `formViews` 的具名条目下(`default`、`edit`)。本 PR 把这三处改为容器的 `form` 键:SKILL.md 的子表单示例、list-views.md 的 `defineView` 示例及其提示框、评测文件第一条的预期输出。向导(wizard)表单是真正的附加具名表单,保持不动。 **为什么改。** spec 把 `form` 定义为容器的默认表单、`formViews` 定义为附加的具名表单。PR #21535 落地后,运行时只把 `form` 当默认表单,不再把第一个具名表单提升为默认。技能照旧教的话,AI 作者按示例写出的应用在规范层面没有默认表单,只靠前端的兜底才显得正常。按 NORTH-STAR 优先级规则 4,写给 AI 的技能说错一句等于产品缺陷;两者应随同一个版本发布。 **风险与代价(含回滚)。** 纯技能文本,不涉及代码与发布包,无 changeset。三个文件的 token 读数均净减(见上表),没有抬任何上限;`check:skill-examples` 证明改后的示例仍能编译,并用构建后的 spec 解析验证了改后容器的 `support_case.form` 被标为默认。回滚即 revert 本 PR 的单个 commit。残余:list-views.md 第 14 行的引言仍只列出 `list` / `listViews` / `formViews`(在认领的区域之外),见 Acceptance notes。 **席位意见。** **你要做的。** `skills/**` 是 Tier H 受管面:需要你的一次 APPROVED review;之后由席位落地。PR 保持 draft,不翻 ready、不挂 auto-merge。 ## Acceptance notes - `rules/list-views.md:14` ("aggregating the default `list`, named `listViews`, and `formViews`") omits `form` the same way the callout did. It sits outside the claimed region (the container and the callout), so it is untouched here; folding it in costs about four tokens against a headroom of 76 and is reported to the seat. - Eval 1's `must_contain` does not assert the `form` key (it never asserted the form key before either); adding `"form:"` would fit the remaining headroom of 3 tokens but is beyond the card's stated fix and is left to the seat. - Ordering: the dispatch's suggested route placed `form` after `listViews`; this PR follows the schema's declaration order (`list`, `form`, `listViews`, `formViews`) in the container, the callout and the eval, which is also the order of SKILL.md's "Define default `list` + `form`, then named `listViews` / `formViews`" row. - Sibling #21567 edits the same SKILL.md at the assembly table row; the regions are disjoint, `origin/main` was still at the base when this PR opened (no merge needed), and a second merge follows once that sibling lands. --- _Generated by [Claude Code](https://claude.ai/code/session_01CB6W87z22K2yjUCDyVrJRk)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent bff5aa2 commit fea6706

3 files changed

Lines changed: 14 additions & 18 deletions

File tree

‎skills/objectstack-ui/SKILL.md‎

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,14 @@ custom page or form config. Prefer, in order:
7474
relationship didn't mark inline:
7575

7676
```typescript
77-
formViews: {
78-
default: {
79-
type: 'simple',
80-
sections: [{ group: 'invoice_header' }], // a declared fieldGroup
81-
subforms: [
82-
{ childObject: 'invoice_line', // relationshipField + columns are
83-
title: 'Line Items', // derived from the child object;
84-
addLabel: 'Add line' }, // set `columns` here only to override.
85-
],
86-
},
77+
form: {
78+
type: 'simple',
79+
sections: [{ group: 'invoice_header' }], // a declared fieldGroup
80+
subforms: [
81+
{ childObject: 'invoice_line', // relationshipField + columns are
82+
title: 'Line Items', // derived from the child object;
83+
addLabel: 'Add line' }, // set `columns` here only to override.
84+
],
8785
},
8886
```
8987

‎skills/objectstack-ui/evals/views-apps-actions-pages.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"id": 1,
66
"prompt": "Create `src/views/support-case.view.ts`: a default grid (subject linking to the record, status, priority, owner, due date), a 'My Open Cases' list, a kanban by status, and a simple edit form.",
7-
"expected_output": "One `defineView({ list, listViews, formViews })` container — never a bare flat view object. `data: { provider: 'object', object: 'support_case' }`, `columns` with `link: true` on `subject`, a `listViews.my_open` entry with `filter` triples (`{ field: 'assigned_to', operator: 'equals', value: '{current_user_id}' }`), a kanban entry with the required top-level `columns` plus `kanban: { groupByField: 'status' }` (no top-level `groupBy`), and `formViews.edit` with `type: 'simple'` and `sections` referencing a declared field group.",
7+
"expected_output": "One `defineView({ list, form, listViews })` container — never a bare flat view object. `data: { provider: 'object', object: 'support_case' }`, `columns` with `link: true` on `subject`, a `listViews.my_open` entry with `filter` triples (`{ field: 'assigned_to', operator: 'equals', value: '{current_user_id}' }`), a kanban entry with the required top-level `columns` plus `kanban: { groupByField: 'status' }` (no top-level `groupBy`), and `form` with `type: 'simple'` and `sections` referencing a declared field group.",
88
"files": [],
99
"assertions": {
1010
"must_contain": ["defineView", "provider: 'object'", "listViews", "groupByField", "link: true", "{current_user_id}"],

‎skills/objectstack-ui/rules/list-views.md‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
### The `defineView` container (`*.view.ts` file shape)
1212

1313
Views ship **inside a `defineView` container** — one per object, aggregating
14-
the default `list`, named `listViews`, and `formViews`. The loader expands it
15-
into `<object>.<key>` view items that power the view switcher.
14+
the default `list` and `form`, named `listViews`, and `formViews`. The loader
15+
expands it into `<object>.<key>` view items that power the view switcher.
1616

1717
<!-- os:check -->
1818
```typescript
@@ -22,20 +22,18 @@ const data = { provider: 'object' as const, object: 'support_case' };
2222

2323
export const CaseViews = defineView({
2424
list: { label: 'All Cases', type: 'grid', data, columns: ['subject', 'status'] },
25+
form: { type: 'simple', data, sections: [{ group: 'case_detail' }] },
2526
listViews: {
2627
open: { label: 'Open', type: 'grid', data, columns: ['subject', 'status'],
2728
filter: [{ field: 'status', operator: 'equals', value: 'open' }] },
2829
},
29-
formViews: {
30-
edit: { type: 'simple', data, sections: [{ group: 'case_detail' }] },
31-
},
3230
});
3331
```
3432

3533
> **Never export a bare flat view object** (`{ name, label, type, columns }`
3634
> at top level). It is not a valid view container — nothing registers and no
37-
> view appears in the switcher. Every view lives under `list` / `listViews` /
38-
> `formViews`, exactly as in the `defineView` example above.
35+
> view appears in the switcher. Every view lives under `list` / `form` /
36+
> `listViews` / `formViews`, exactly as in the `defineView` example above.
3937
4038
### Data Source (`data`)
4139

0 commit comments

Comments
 (0)