From 36152cd8e6e4c4d3a22b547f19f3fe8cca39a385 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Nov 2026 07:51:24 +0000 Subject: [PATCH 1/3] docs(skills): the data skill's Field Groups section teaches a group's visibleWhen and requiresFeature examples-objects.md names the two ways a whole field group is hidden: visibleWhen (CEL over the record; FALSE or a fault hides the group, header included) and requiresFeature (a PUBLIC_AUTH_FEATURES flag, refused when unknown, lowered at parse into the group's visibleWhen and stripped, AND-composed after an authored predicate), with sys_organization's Group Structure section as the example. Paid by deleting restatement in the same file; the token ratchet row re-locks at the landed count (1756 -> 1751). Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01L9qibxLYNwSMSVQkj55gA6 --- ...eld-group-visible-when-requires-feature.md | 10 +++++++ scripts/check-skills-token-ratchet.mjs | 8 +++++- .../references/examples-objects.md | 26 ++++++++----------- 3 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 .changeset/30812-field-group-visible-when-requires-feature.md diff --git a/.changeset/30812-field-group-visible-when-requires-feature.md b/.changeset/30812-field-group-visible-when-requires-feature.md new file mode 100644 index 00000000000..855822ebac1 --- /dev/null +++ b/.changeset/30812-field-group-visible-when-requires-feature.md @@ -0,0 +1,10 @@ +--- +'@objectstack/skills': patch +--- + +docs(skills): the data skill's Field Groups section teaches a group's `visibleWhen` and `requiresFeature` + +Clause-②: no +Metadata-protocol: none + +`skills/objectstack-data/references/examples-objects.md` now names the two ways a whole field group (header included) is hidden: `visibleWhen`, a CEL predicate over the record that hides the group when FALSE or when it faults, and `requiresFeature`, a deployment feature flag from the `PUBLIC_AUTH_FEATURES` set, refused when unknown, lowered at parse into the group's `visibleWhen` and stripped, AND-combined after an authored `visibleWhen`; both are presentation only. The real example is `sys_organization`'s Group Structure section, hidden on a single-organization deployment with `requiresFeature: 'multiOrgEnabled'`. The text is paid for by deleting restatements in the same file (the intro sentence, the migrations paragraph, the deprecated-flag aside, the strictness sentence under Metadata Protection, a dangling "see above" and a path comment), so the file's token ceiling moves down, not up. diff --git a/scripts/check-skills-token-ratchet.mjs b/scripts/check-skills-token-ratchet.mjs index 2d2a9b19146..0779fb58bda 100644 --- a/scripts/check-skills-token-ratchet.mjs +++ b/scripts/check-skills-token-ratchet.mjs @@ -1002,7 +1002,13 @@ export const CEILINGS = new Map([ // stale `{ type: 'lookup', reference: 'user' }` fields (an object that does // not exist) became `type: 'user'`; -10 tokens, the row follows the // measurement down, zero headroom. - ['skills/objectstack-data/references/examples-objects.md', 1756], + // 1756 -> 1751: RE-LOCK at the landed count after a net cut — the Field + // Groups section now names a group's `visibleWhen` and `requiresFeature` + // (lowered into `visibleWhen` at parse, unknown flag refused, AND-composed + // after an authored predicate) with the `sys_organization` example, paid by + // deleting restatement in the same file; -5 tokens, the row follows the + // measurement down, zero headroom. + ['skills/objectstack-data/references/examples-objects.md', 1751], ['skills/objectstack-data/references/lint-rules.md', 970], // 1299 -> 1566 (#26297): the `columns` dataset key and `applyOn: 'create'` // — a column a job or an admin owns after the first load is written on diff --git a/skills/objectstack-data/references/examples-objects.md b/skills/objectstack-data/references/examples-objects.md index 18867a37ad6..1e74d19efb3 100644 --- a/skills/objectstack-data/references/examples-objects.md +++ b/skills/objectstack-data/references/examples-objects.md @@ -2,20 +2,24 @@ ## Field Groups (MVP) -Organize fields into logical groups (e.g., "Contact Information", "Billing", -"System") for forms, detail pages, and editors. - - Declare groups on `ObjectSchema.fieldGroups` — **array order is the display order**. - Assign each field to a group via `Field.group`, which references an `ObjectFieldGroup.key`. In-group display order equals the traversal order of `fields`. -- Group keys must be `snake_case`; group labels are human-readable. +- Group keys must be `snake_case`. - Optional per-group: `icon`, `description`, and `collapse` (`'none'` always open · `'expanded'` collapsible, starts open · - `'collapsed'` collapsible, starts closed — replaces the deprecated - `defaultExpanded` flag, ADR-0085). Groups render identically on forms, + `'collapsed'` collapsible, starts closed). Groups render identically on forms, modals, and detail pages; for a bespoke single-page layout assign a custom Page instead. +- Hide a whole group, header included, with `visibleWhen` (CEL over + `record.*`; FALSE or a fault hides it) or `requiresFeature` (a deployment + feature flag from `PUBLIC_AUTH_FEATURES`; an unknown flag is refused). At + parse `requiresFeature` is lowered into the group's `visibleWhen` and + stripped, AND-combined after an authored `visibleWhen`. Presentation only: + the fields stay readable through the API. `sys_organization` hides Parent + Organization and Sort Order on one organization: + `{ key: 'group_structure', label: 'Group Structure', requiresFeature: 'multiOrgEnabled' }`. ```typescript @@ -44,10 +48,6 @@ export default ObjectSchema.create({ }); ``` -**Supported migrations at this layer:** add / rename / delete / reorder groups -(edit the `fieldGroups` array), assign a field to a group (edit `Field.group`). -Explicit per-field in-group ordering is deferred to a future iteration. - ## Quick-Start Template @@ -60,7 +60,7 @@ export default ObjectSchema.create({ pluralLabel: 'Support Cases', description: 'A customer-reported issue tracked to resolution.', icon: 'life-buoy', - sharingModel: 'private', // required in practice — see above + sharingModel: 'private', // required in practice highlightFields: ['subject', 'status', 'priority'], enable: { trackHistory: true, @@ -160,9 +160,6 @@ protection?: { } ``` -The block is `.strict()`: `reason` is **required** (min 1 / max 500 chars) and -unknown keys are rejected. - | `lock` | Edit | Delete | Typical use | |:---|:---:|:---:|:---| | `none` (default) | ✅ | ✅ | Normal authored metadata | @@ -174,7 +171,6 @@ unknown keys are rejected. ```typescript -// src/objects/sys-user.object.ts import { ObjectSchema } from '@objectstack/spec/data'; export const SysUserObject = ObjectSchema.create({ From 62fd849b787c6a483cba47e8964a7a1e203d7480 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Nov 2026 08:54:00 +0000 Subject: [PATCH 2/3] chore(skills): re-lock the examples-objects token row at the merged landed count (1737) Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01L9qibxLYNwSMSVQkj55gA6 --- scripts/check-skills-token-ratchet.mjs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/check-skills-token-ratchet.mjs b/scripts/check-skills-token-ratchet.mjs index 0779fb58bda..f5d257ce644 100644 --- a/scripts/check-skills-token-ratchet.mjs +++ b/scripts/check-skills-token-ratchet.mjs @@ -1002,13 +1002,14 @@ export const CEILINGS = new Map([ // stale `{ type: 'lookup', reference: 'user' }` fields (an object that does // not exist) became `type: 'user'`; -10 tokens, the row follows the // measurement down, zero headroom. - // 1756 -> 1751: RE-LOCK at the landed count after a net cut — the Field + // 1756 -> 1737: RE-LOCK at the landed count after two net cuts — the Field // Groups section now names a group's `visibleWhen` and `requiresFeature` // (lowered into `visibleWhen` at parse, unknown flag refused, AND-composed // after an authored predicate) with the `sys_organization` example, paid by - // deleting restatement in the same file; -5 tokens, the row follows the - // measurement down, zero headroom. - ['skills/objectstack-data/references/examples-objects.md', 1751], + // deleting restatement in the same file (-5), on top of the hook-example + // rename that dropped its intro line (-14) and left headroom; the row + // follows the measurement down, zero headroom. + ['skills/objectstack-data/references/examples-objects.md', 1737], ['skills/objectstack-data/references/lint-rules.md', 970], // 1299 -> 1566 (#26297): the `columns` dataset key and `applyOn: 'create'` // — a column a job or an admin owns after the first load is written on From 2e81ba6a138a69860097d3f1775187119a2ba08b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Nov 2026 09:30:25 +0000 Subject: [PATCH 3/3] docs(skills): name the module that holds PUBLIC_AUTH_FEATURES in the Field Groups bullet Contract review should-fix: the flag vocabulary is named with its module (@objectstack/spec/kernel) so a skill reader has more than a bare symbol to find. Paid in the same file by dropping the custom-Page aside, whose rule lives in the ui skill; the token row re-locks down at 1728. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01L9qibxLYNwSMSVQkj55gA6 --- scripts/check-skills-token-ratchet.mjs | 9 +++++---- .../references/examples-objects.md | 14 +++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/scripts/check-skills-token-ratchet.mjs b/scripts/check-skills-token-ratchet.mjs index f5d257ce644..1936d3d219f 100644 --- a/scripts/check-skills-token-ratchet.mjs +++ b/scripts/check-skills-token-ratchet.mjs @@ -1002,14 +1002,15 @@ export const CEILINGS = new Map([ // stale `{ type: 'lookup', reference: 'user' }` fields (an object that does // not exist) became `type: 'user'`; -10 tokens, the row follows the // measurement down, zero headroom. - // 1756 -> 1737: RE-LOCK at the landed count after two net cuts — the Field + // 1756 -> 1728: RE-LOCK at the landed count after two net cuts — the Field // Groups section now names a group's `visibleWhen` and `requiresFeature` // (lowered into `visibleWhen` at parse, unknown flag refused, AND-composed // after an authored predicate) with the `sys_organization` example, paid by // deleting restatement in the same file (-5), on top of the hook-example - // rename that dropped its intro line (-14) and left headroom; the row - // follows the measurement down, zero headroom. - ['skills/objectstack-data/references/examples-objects.md', 1737], + // rename that dropped its intro line (-14) and left headroom, then the + // review's module pointer paid by the custom-Page aside (the ui skill's + // rule); the row follows the measurement down, zero headroom. + ['skills/objectstack-data/references/examples-objects.md', 1728], ['skills/objectstack-data/references/lint-rules.md', 970], // 1299 -> 1566 (#26297): the `columns` dataset key and `applyOn: 'create'` // — a column a job or an admin owns after the first load is written on diff --git a/skills/objectstack-data/references/examples-objects.md b/skills/objectstack-data/references/examples-objects.md index e3e3a82518c..b0da44a9cb4 100644 --- a/skills/objectstack-data/references/examples-objects.md +++ b/skills/objectstack-data/references/examples-objects.md @@ -10,15 +10,15 @@ - Optional per-group: `icon`, `description`, and `collapse` (`'none'` always open · `'expanded'` collapsible, starts open · `'collapsed'` collapsible, starts closed). Groups render identically on forms, - modals, and detail pages; for a bespoke single-page layout assign a - custom Page instead. + modals, and detail pages. - Hide a whole group, header included, with `visibleWhen` (CEL over `record.*`; FALSE or a fault hides it) or `requiresFeature` (a deployment - feature flag from `PUBLIC_AUTH_FEATURES`; an unknown flag is refused). At - parse `requiresFeature` is lowered into the group's `visibleWhen` and - stripped, AND-combined after an authored `visibleWhen`. Presentation only: - the fields stay readable through the API. `sys_organization` hides Parent - Organization and Sort Order on one organization: + feature flag from `PUBLIC_AUTH_FEATURES` in `@objectstack/spec/kernel`; an + unknown flag is refused). At parse `requiresFeature` is lowered into the + group's `visibleWhen` and stripped, AND-combined after an authored + `visibleWhen`. Presentation only: the fields stay readable through the API. + `sys_organization` hides Parent Organization and Sort Order on one + organization: `{ key: 'group_structure', label: 'Group Structure', requiresFeature: 'multiOrgEnabled' }`.