Skip to content

Commit 4cfb351

Browse files
docs(skills): name the pluralLabel exception to "an extension can add but never remove" (#30722)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DRJUuDG85hCcfSGBtmU6XdK)_ domain:skills#1 · os-elon-musk · session_016WV4cx4foyi3wUWBrRHCmF Fixes #30466 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:`objectstack-data` 技能「对象扩展」一节仍说扩展“只能加、不能删”,但补上唯一的例外:扩展改了 `label` 却没给 `pluralLabel` 时,基础对象的复数名会被清掉(租户自己写的复数除外),要保留就两个一起写。 - 为什么改:PR #30459(#30391)落地后合并规则就是这样,原句对 `pluralLabel` 不再准确;这是那次合同评审的 should-fix 2。 - 风险与回滚:只改技能文档一句话,无代码、无 schema 变化;回滚即 revert。 - 先看:`skills/objectstack-data/SKILL.md` 第 349–350 行;规则出处 `packages/objectql/src/registry.ts` 的 `mergeObjectDefinitions`(第 916 行)。 - 两分钟验证:`node scripts/check-skills-token-ratchet.mjs | grep "objectstack-data/SKILL.md "`,预期 `6122 / 6123`。 - 需要你做的:ADR-0029 D9.2 第 473 行“has no expression for *removal* at all”一句是否加修订注,由你定(本 PR 不碰 ADR)。 ## What changes - `skills/objectstack-data/SKILL.md` § Object Extension Model keeps "an extension can add but never remove" and names the one exception: a new `label` without `pluralLabel` clears the base plural unless a tenant authored it, so an author sets both. - The rule is read off `origin/main`, `packages/objectql/src/registry.ts` `mergeObjectDefinitions`: `if (extension.pluralLabel === undefined && extension.label !== merged.label && !yields('pluralLabel')) delete merged.pluralLabel;`, inside the `extension.label !== undefined && !yields('label')` branch. So the plural survives when the extension repeats the running label, when the tenant authored the plural (the ADR-0029 D9.2a yield), or when the tenant authored the label (the label itself yields). - Token payment, same file: the Lifecycle Hooks pointer line drops its parenthetical second link to `references/data-hooks.md`. That file is already linked from the catalog list (L46) and from the backfill paragraph (L160), so the parenthetical restated a link. - `.changeset/30466-extension-plurallabel-exception.md`: `'@objectstack/skills': patch`. ## Tests Docs-only. No behaviour changes, so no test or ablation applies. ## Acceptance notes - Out of scope by the order, for the seat to raise for Tier H: ADR-0029 D9.2, `docs/adr/0029-kernel-object-ownership-and-platform-objects-decomposition.md` L472–473, "`mergeObjectDefinitions` merges fields additively (...) and has no expression for *removal* at all." Since PR #30459 it has one, for `pluralLabel`. No decision moves (the sentence argues about fields in an overlay); whether it gets an amendment note is the maintainer's. ## Verification Skills readings (lines and tokens): - `skills/objectstack-data/SKILL.md`: 464 → 465 lines; 6116 → 6122 tokens (ceiling 6123, headroom 7 → 1). Net +6 after the same-file deletion, inside the existing headroom. The ceiling row is not touched. - Whole package, all `SKILL.md`: 4534 → 4535 lines. Bundle total (whole shipped tree, ratchet reading): 226234 → 226240 tokens. Gates, head `a069bdb668` (`dispatch-gates --commands`, 44 derived families, plus `pnpm lint`): - 40 families exit 0, and `pnpm lint` exit 0. `--ran` reconciliation: "44 derived famil(ies) accounted for — 40 run, 4 NOT-MEASURED". - `check:doc-formula-expressions` first exited 3 (prerequisite); after `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` it exits 0. - NOT MEASURED: `check:dts-closure`, `check:dual-build-cjs-loads`, `check:lean-entry-closure`, `check:sourcemap-no-sources-content`. Reason: exit 3, they need a whole-tree build. They read package `dist/` output, which this docs-only diff does not change; CI measures them. <details><summary>COMMAND :: exit CODE record</summary> ```text node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 node scripts/check-closing-keyword-parity.mjs :: exit 0 node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 node scripts/check-comment-mask-corpus.mjs :: exit 0 node scripts/check-doc-route-spelling.mjs --advisory :: exit 0 node scripts/check-doc-route-spelling.mjs --self-test :: exit 0 node scripts/check-dts-emitted.mjs --self-test :: exit 0 node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 node scripts/check-empty-changeset.mjs --self-test :: exit 0 node scripts/check-skills-token-ratchet.mjs :: exit 0 node scripts/check-skills-token-ratchet.mjs --self-test :: exit 0 node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0 node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0 node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0 node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 node scripts/release-pending-publish.mjs --self-test :: exit 0 pnpm --filter @objectstack/spec run check:skill-docs :: exit 0 pnpm check:agent-test-spelling :: exit 0 pnpm check:changeset-gate-self-tests :: exit 0 pnpm check:ci-filter-parity :: exit 0 pnpm check:closed-ceremony-text :: exit 0 pnpm check:corpus-claim-drift :: exit 0 pnpm check:cross-package-test-inputs :: exit 0 pnpm check:doc-authoring :: exit 0 pnpm check:driver-memory-census :: exit 0 pnpm check:dts-closure :: exit 3 pnpm check:dual-build-cjs-loads :: exit 3 pnpm check:gitlink-declared :: exit 0 pnpm check:lean-entry-closure :: exit 3 pnpm check:merge-driver :: exit 0 pnpm check:nul-bytes :: exit 0 pnpm check:pm-governed-merges :: exit 0 pnpm check:pm-skill-id-lint :: exit 0 pnpm check:published-files :: exit 0 pnpm check:refd-timer-probe :: exit 0 pnpm check:role-word :: exit 0 pnpm check:skill-compatibility :: exit 0 pnpm check:skill-frame-sync :: exit 0 pnpm check:skill-identifier-liveness :: exit 0 pnpm check:sourcemap-no-sources-content :: exit 3 pnpm check:watch-hint-literal :: exit 0 pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 pnpm lint :: exit 0 ``` </details> --- _Generated by [Claude Code](https://claude.ai/code/session_016WV4cx4foyi3wUWBrRHCmF)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent b5eb61d commit 4cfb351

2 files changed

Lines changed: 13 additions & 2 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/skills': patch
3+
---
4+
5+
docs(skills): an object extension that renames `label` without `pluralLabel` clears the base plural
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
`objectstack-data` § Object Extension Model still says an extension can add but never remove, and now names the one exception the object fold has: an extension that sets a new `label` and no `pluralLabel` takes the base's `pluralLabel` off the served object unless a tenant authored that plural, so an author who renames an object sets both to keep a plural. An extension that repeats the label it extends removes nothing. The Lifecycle Hooks pointer line drops its second link to `references/data-hooks.md`, which the catalog list and the backfill paragraph already link. No schema, key or behaviour changes.

‎skills/objectstack-data/SKILL.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ See [rules/indexing.md](./rules/indexing.md) for composite indexes, unique scope
337337
refused), the retired `type` / `partial`, and partial / gin / gist indexes at the
338338
database layer.
339339

340-
→ Moved verbatim to [references/examples-objects.md](./references/examples-objects.md) § Lifecycle Hooks (the hooks reference itself is [references/data-hooks.md](./references/data-hooks.md)).
340+
→ Moved verbatim to [references/examples-objects.md](./references/examples-objects.md) § Lifecycle Hooks.
341341

342342
---
343343

@@ -346,7 +346,8 @@ database layer.
346346
To add fields/validations/indexes to an object you do not own, author
347347
`defineObjectExtension({ extend, fields, fieldPatches, priority })` and register it on
348348
`defineStack({ objectExtensions: [...] })`. `priority` sets merge order (default
349-
`200`, range `0–999`); an extension can add but never remove. ⛔ Not the same key
349+
`200`, range `0–999`); an extension can add but never remove, except that a new
350+
`label` without `pluralLabel` clears the base plural unless a tenant authored it (set both). ⛔ Not the same key
350351
as object-level `ownership` (the record-ownership enum
351352
`'user' | 'business_unit' | 'org' | 'none'`). Schema:
352353
`node_modules/@objectstack/spec/src/data/object.zod.ts` (`ObjectExtensionSchema`).

0 commit comments

Comments
 (0)