Skip to content

Commit 892eb66

Browse files
docs(spec): key the fieldPatches example option by a value crm_account.industry stores (#28827)
<!-- claude-projects-attribution: {"github_login":"os-steve"} --> _Requested by **Steve** · [project thread](https://claude.ai/code/project/chan_01FdL1XeUyvVNxLreh3F4Qi9?thread=cmsg_01FdL1XeUyvVNxLreh3F4Qi9Woe1WqkwqEbbQEviGw1m5U)_ Fixes #28803 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:`fieldPatches` 文档示例里的选项键从 `tech` 改成 `crm_account.industry` 真实存储的值 `technology`(`technology: { label: 'Tech' }`),覆盖 spec 描述、TSDoc、选项列表拒收文案、对象扩展指南和两份未发布的 changeset。 - 为什么改:原示例照抄会在 `os validate` 和安装时被拒(该字段没有 `tech` 这个选项),文档在教一个坏例子;技能包那份已在 #28795 修好,这里补齐其余几份。 - 风险与回滚:纯文案,schema 接受/拒收的结果不变;回滚即 revert 本 PR。 - 先看:`packages/spec/src/data/object.zod.ts`(三处示例文字)、`content/docs/data-modeling/object-extensions.mdx`、`content/docs/references/data/object.mdx`(重新生成的参考页)。 - 两分钟验证:`git grep -n "tech: {" -- packages/spec/src content/docs skills .changeset ':!*.test.ts'`,预期没有任何输出。 - 需要你做的:无,席位落地。 ## What changes - `packages/spec/src/data/object.zod.ts`: the `fieldPatches` `.describe()` example, the `ObjectExtensionSchema` TSDoc example, and the refusal text for an option list under `options` now read `options: { technology: { label: 'Tech' } }`. `crm_account.industry` (`examples/app-crm/src/objects/account.object.ts`) stores `technology`, `finance`, `healthcare`, `retail`, `other`; `tech` is none of them, so a copy was refused with reason `option`. - `content/docs/data-modeling/object-extensions.mdx`: the guide's example, same re-key. - `content/docs/references/data/object.mdx`: re-recorded by `check:generated --fix` (only `check:docs` was stale). - `.changeset/28565-field-patch-applied.md` and `.changeset/28560-field-patch-slot.md`: both still unreleased (present in `.changeset/` on `main` at 1617b7f, no Version Packages release has consumed them), so their copies of the example are re-keyed too. The 28560 copy is a fifth copy the card did not list. - `.changeset/28803-field-patches-example.md`: spec patch. No forced test edits. Test fixtures that patch `tech` (`field-customization.test.ts`, `field-patches-derived.test.ts`, and the cli / metadata-core / objectql / cloud-connection field-patch tests) build their own objects and do not pin the documented example text, so they stay as they are. ## Tests - `pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/data` and `pnpm --filter @objectstack/spec typecheck`: Test Files 154 passed (154), Tests 4756 passed, 1 todo; VERDICT command-exit 0. - `pnpm --filter @objectstack/spec build && check:generated`: 1 of 14 stale (`check:docs`), fixed with `--fix`, then all up to date. ## Acceptance notes - Prose only; no consumer package test is owed (no accept/reject result changes). - **Pending release notes corrected, so `Check Changeset` stays red by design.** This PR edits two changesets it did not add, both still pending (no Version Packages release has consumed them): `.changeset/28565-field-patch-applied.md` (named by the card, its example line) and `.changeset/28560-field-patch-slot.md` (a fifth copy of the same example, not named by the card). In each, only the option key and label inside the code example change, from `tech: { label: 'Technology' }` to `technology: { label: 'Tech' }`; no sentence about behaviour changes. This is the DELIBERATE CORRECTION class `check-empty-changeset.mjs` names: the gate stays red, `skip-changeset` is not applied, and the correction needs a written confirmation on this PR. Restoring either file from the base would republish an example that `os validate` refuses. - Merged `origin/main` at 663b7c0 with `scripts/pm/os-regen-merge.sh` (#28791 had edited `object.zod.ts` and `object-extensions.mdx`); no conflict, and `check:generated` reports all 14 artifacts up to date on the merged head. ## Verification All readings on head `0c29908fd8` (the merge of main). <details><summary>spec tests and typecheck</summary> `bash scripts/pm/os-verify-lock.sh -c 'pnpm --filter @objectstack/spec test && pnpm --filter @objectstack/spec typecheck'`: Test Files 788 passed (788), Tests 23268 passed, 1 todo; `VERDICT command-exit 0`. </details> <details><summary>generated artifacts</summary> Before the merge: `check:generated` found 1 of 14 stale (`check:docs`, `content/docs/references/data/object.mdx`), fixed with `--fix`. After the merge: `pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated`: all 14 generated artifacts up to date; `VERDICT command-exit 0`. </details> <details><summary>derived gate list</summary> `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` listed 97 commands; each ran on this head with its exit code recorded. 96 exit 0. `node scripts/check-empty-changeset.mjs --base origin/main` exits 1 on the two pending changesets above, as designed. Reconciliation: `97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN` (a derived zero, every line carries an exit code). Seven gates first exited 3 (prerequisites: unbuilt packages, shallow clone); after a full `turbo run build` and `git fetch --unshallow` all seven exit 0. Local-only: `check-dev-prereqs` exit 0, `check:skill-frame-freshness` exit 0. </details> --- _Generated by [Claude Code](https://claude.ai/code/session_01ADHkmQfYHca8dfoXTJfeKp)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 839aae5 commit 892eb66

6 files changed

Lines changed: 18 additions & 8 deletions

File tree

‎.changeset/28560-field-patch-slot.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ objectExtensions: [{
1616
industry: {
1717
label: 'Sector',
1818
inlineHelpText: 'The market the account sells into',
19-
options: { tech: { label: 'Technology' } },
19+
options: { technology: { label: 'Tech' } },
2020
},
2121
},
2222
}]

‎.changeset/28565-field-patch-applied.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ADR-0146 D10's second rule, live. The per-field display patch an object extensio
1717
objectExtensions: [{
1818
extend: 'crm_account',
1919
fieldPatches: {
20-
industry: { label: 'Sector', inlineHelpText: 'The market the account sells into', options: { tech: { label: 'Technology' } } },
20+
industry: { label: 'Sector', inlineHelpText: 'The market the account sells into', options: { technology: { label: 'Tech' } } },
2121
},
2222
}]
2323
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
docs(spec): the documented `fieldPatches` example keys its option by a value `crm_account.industry` really stores
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The `fieldPatches` description, its TSDoc example and the refusal text for an option list under `options` showed `options: { tech: { label: 'Technology' } }`. `crm_account.industry` stores `technology`, not `tech`, so a copy of that example was refused at `os validate` and at install as naming an option the field does not have. The example now reads `options: { technology: { label: 'Tech' } }`. Prose only: no schema accepts or refuses anything differently.

‎content/docs/data-modeling/object-extensions.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export const AccountWordingExtension = defineObjectExtension({
110110
industry: {
111111
label: 'Sector',
112112
inlineHelpText: 'The market the account sells into.',
113-
options: { tech: { label: 'Technology' } }, // addressed by the stored value
113+
options: { technology: { label: 'Tech' } }, // addressed by the stored value
114114
},
115115
},
116116
});

‎content/docs/references/data/object.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ const result = ApiMethod.parse(data);
576576
| :--- | :--- | :--- | :--- |
577577
| **extend** | `string` | ✅ | Target object name (FQN) to extend |
578578
| **fields** | `Record<string, { name?: string; label?: string; type: Enum<'text' \| 'textarea' \| 'email' \| 'url' \| 'phone' \| 'password' \| 'secret' \| …>; description?: string; … }>` | optional | Fields to add/override |
579-
| **fieldPatches** | `Record<string, { label?: string; description?: string; inlineHelpText?: string; placeholder?: string; … }>` | optional | Display patches of the target object's own fields, keyed by field name: change a vendor field's display properties (BASE_FIELD_DISPLAY_WHITELIST: label, description, help text, placeholder, option labels) without taking the field over, so its type, values and rules stay the vendor's and its upgrades still apply (ADR-0146 D10). Applied by the registry merge (`mergeObjectDefinitions`) after the additive merges, on every object read: a tenant's own text keeps winning, and between two extensions the higher `priority` wins. A patch naming a field or option value the target does not have is refused at install and by `os validate`. Example: `fieldPatches: { industry: { label: 'Sector', inlineHelpText: 'The market the account sells into', options: { tech: { label: 'Technology' } } } }`. |
579+
| **fieldPatches** | `Record<string, { label?: string; description?: string; inlineHelpText?: string; placeholder?: string; … }>` | optional | Display patches of the target object's own fields, keyed by field name: change a vendor field's display properties (BASE_FIELD_DISPLAY_WHITELIST: label, description, help text, placeholder, option labels) without taking the field over, so its type, values and rules stay the vendor's and its upgrades still apply (ADR-0146 D10). Applied by the registry merge (`mergeObjectDefinitions`) after the additive merges, on every object read: a tenant's own text keeps winning, and between two extensions the higher `priority` wins. A patch naming a field or option value the target does not have is refused at install and by `os validate`. Example: `fieldPatches: { industry: { label: 'Sector', inlineHelpText: 'The market the account sells into', options: { technology: { label: 'Tech' } } } }`. |
580580
| **label** | `string` | optional | Override label for the extended object |
581581
| **pluralLabel** | `string` | optional | Override plural label for the extended object |
582582
| **description** | `string` | optional | Override description for the extended object |

‎packages/spec/src/data/object.zod.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4835,7 +4835,7 @@ const FieldDisplayPatchSchema = lazySchema(() => {
48354835
error: (issue) =>
48364836
issue.code === 'invalid_type' && Array.isArray(issue.input)
48374837
? 'A field patch\'s `options` is a map keyed by each option\'s stored value — ' +
4838-
'`options: { tech: { label: \'Technology\' } }` — not the field\'s option list: which options ' +
4838+
'`options: { technology: { label: \'Tech\' } }` — not the field\'s option list: which options ' +
48394839
'exist stays the vendor\'s (ADR-0146 D6).'
48404840
: undefined,
48414841
}).optional().describe(
@@ -4879,7 +4879,7 @@ function refuseExtensionFieldPatchKeys(fieldPatches: unknown, ctx: z.RefinementC
48794879
* fields: { sales_stage: Field.select([...]) },
48804880
* // A base field's display properties only (ADR-0146 D10), applied by the
48814881
* // registry merge (`mergeObjectDefinitions`) — see `fieldPatches`.
4882-
* fieldPatches: { industry: { label: 'Sector', options: { tech: { label: 'Technology' } } } },
4882+
* fieldPatches: { industry: { label: 'Sector', options: { technology: { label: 'Tech' } } } },
48834883
* }]
48844884
* ```
48854885
*/
@@ -4964,8 +4964,8 @@ export const ObjectExtensionSchema = lazySchema(() => strictObject({
49644964
'the additive merges, on every object read: a tenant\'s own text keeps winning, and between two ' +
49654965
'extensions the higher `priority` wins. A patch naming a field or option value the target does not ' +
49664966
'have is refused at install and by `os validate`. Example: `fieldPatches: { industry: { label: ' +
4967-
'\'Sector\', inlineHelpText: \'The market the account sells into\', options: { tech: { label: ' +
4968-
'\'Technology\' } } } }`.',
4967+
'\'Sector\', inlineHelpText: \'The market the account sells into\', options: { technology: { label: ' +
4968+
'\'Tech\' } } } }`.',
49694969
),
49704970

49714971
/** Override label */

0 commit comments

Comments
 (0)