Skip to content

Commit d69f7e1

Browse files
docs(cli): record what docs/duplicate-name rests on after ADR-0048 §3.4 — no rule change (#19352)
Fixes #19248 Clause-②: no A card about a **justification**, not about a rule. `docs/duplicate-name` refuses two owners declaring one doc name; the claim it used to be explained by — *"one registration overwrites the other"* — was retired by ADR-0048. This PR quotes the ADR, sets it beside what the rule's message and docblock actually say today, and records the verdict. ⛔ **Nothing is relaxed.** No rule, message, severity or accept set moves. The at-tier reviewer's words on the originating flag were *"file it, do not relax it here."* --- ## 1. ADR-0048 §3.4 — verbatim Read from `docs/adr/0048-cross-package-metadata-collision.md` at this branch's base `13d52947d8`. The section **still exists under that number** and still carries the clause, so nothing had to be substituted for it. Reproduced whole, unedited: ```text ### 3.4 Per-item cross-package detection retires; same-package overwrite stays The original proposal's per-item guard threw `MetadataCollisionError` whenever two **different** packages registered the same `(type, name)`. Under package-scoped resolution that is exactly the case we now *support*: package ids are always distinct, so prefer-local always disambiguates two different packages — there is no unresolvable cross-package clash to detect. The cross-package **throw is retired**; two distinct packages coexist on the same bare name by construction. What remains is the narrow, genuinely-ambiguous case the guard still earns its keep on: **a write with no real package provenance** (a `sys_metadata`/runtime overlay) is governed by the ADR-0005 overlay precedence (artifact-vs-DB warning, unchanged), and **same-package re-registration** simply overwrites (idempotent reload). Authoring-time hygiene — an author shipping two `page/home` in one package — stays covered by the `naming/namespace-prefix` lint in `os lint`. ``` ADR-0048's header reads **Status: Revised (2026-06-13)**, and §5 files Phase 2 (backend) as `[done]`, repeating the same retirement: *"The per-item **cross-package throw is retired** (§3.4) — two distinct packages coexist on the same bare name."* ## 2. What `docs/duplicate-name` asserts today The rule fires from two sites in `packages/cli/src/utils/collect-docs.ts`. **a. Within one owner** — `lintDocs`: ```ts message: `Duplicate doc name "${doc.name}" (inline defineStack docs and src/docs/*.md files share one namespace).`, ``` **b. Across owners** — `lintDocNamesAcrossOwners`, the arm the per-package split (#18431 / #18962) had to preserve: ```ts message: `Doc name "${name}" is declared by ${labels.join(' and ')}. One artifact may not ship one doc name twice — rename one. Doc names are namespace-prefixed for authoring hygiene, and ADR-0130 D1 lets packages of one artifact SHARE a namespace, so the prefix does not keep these apart.`, ``` Its docblock already declined the retired claim **by name**, before this card: > ⚠️ The REASON is authoring hygiene, and ⛔ deliberately not "one silently overwrites the other at > registration". That sentence is this module's older framing and ADR-0048 retired it [...] What > survives there is exactly what this is: an authoring-time hygiene lint. ## 3. Verdict — the stated justification is one the ADR still supports **No wording change is warranted, and none was made.** Setting the two texts side by side: | | ADR-0048 §3.4 | the rule's message + docblock | |:---|:---|:---| | what is retired | the per-item **runtime throw** on a cross-package clash | the phrase *"one silently overwrites the other at registration"*, declined explicitly | | why it is retired | package ids are distinct, items are keyed composite (PACKAGEID colon NAME) and resolution is package-scoped, so two packages coexist | quoted in the same terms, citing §3.3 and §3.4 | | what survives | *"Authoring-time hygiene [...] stays covered by the [...] lint in `os lint`"* | *"Doc names are namespace-prefixed **for authoring hygiene**"* | | runtime claim made | none | **none** | §3.4 retires a runtime throw and nothing else. The class this lint belongs to is named in the same clause as the thing that survives. Neither message asserts anything about what the runtime does, so the card's recorded expectation — *"`collect-docs.ts`'s message now says so explicitly"* — is **verified rather than assumed**, and the correct outcome is to record it, not to edit it. Two further confirmations, both measured on this base: - the prose page that states the rule, `content/docs/ui/doc-pages.mdx`, is **already** post-ADR-0048 — *"two installed packages may each ship a doc with the same bare name and coexist — neither silently overwrites the other"* — so the ADR text required no edit there either; - ADR-0130 D1 (*"A release artifact MAY carry N package manifests"*, co-owning one namespace) is live and makes the cross-owner case reachable on purpose, which is what the message cites. ## 4. What this PR therefore changes One docblock, plus its changeset. The rule's **behaviour, message text and severity are byte-identical.** - the ADR's own two surviving sentences are quoted **verbatim** into the rule's docblock, so the next reader does not re-derive a retired clause second-hand — the failure this card was opened about; - the docblock's *"is filed rather than changed here"* now names **#19248**, so the standing disagreement is findable from the code; - the boundary between the two open questions is stated: the **reason** is settled, the **severity** is not — §3.4 hands authoring hygiene to a *warning-only* lint while this rule is `severity: 'error'`. That is a question about the level, and this PR deliberately does not answer it. ### Changeset `patch` on `@objectstack/cli`, **not** `skip-changeset` — derived, not assumed. The package's published `files[]` is `["dist","README.md","CHANGELOG.md"]` and it builds with plain `tsc -p tsconfig.build.json` (no `removeComments`), so the comment reaches the tarball. Measured on the rebuilt artifact: new clause present in `dist/utils/collect-docs.js` (1), replaced spelling absent from all of `dist` (0), `dist/**/*.d.ts` carries 0 of it (the block sits above a non-exported helper), with the rule's own runtime message as the positive control resolving to that same file. Published JS bytes move; the declaration surface does not. Same reading, same package, as the precedent at `.changeset/15295-serve-observability-mirror-comment.md`. ## Acceptance notes ⛔ Noted, not fixed here — all outside this card's file surface. 1. **This file's HEADER docblock still states the retired claim as the live justification.** `packages/cli/src/utils/collect-docs.ts` lines 23-26 read: *"**Lint**: namespace-prefix naming (doc uniqueness is logical — the metadata registry key carries no package coordinate, so a bare-name collision silently overwrites across packages)"*. That is the retired sentence, and it near-quotes ADR-0048 **§1.1** — a *Context* heading the ADR's own §3.1/§3.3/§3.4 then overturned. It is the only live occurrence left in the repository outside the ADR itself and the CHANGELOG history. It is **not** edited here because it is outside this card's declared file surface and because it justifies `docs/namespace-prefix` as well as doc uniqueness, so correcting it is a judgment about a second rule. Flagged for a card of its own; the corrected phrasing is already pinned two hundred lines below it in the same file. 2. **The severity question named in §3 above** — `error` here versus the warning-only lint §3.4 assigns authoring hygiene to. Pre-existing, and explicitly out of scope for this card. ⛔ Swept and clean: every other rule in this module (`docs/uncollected-directory`, `docs/flat-directory`, `docs/frontmatter-tags`, `docs/filename`, `docs/orphan-translation`, `docs/duplicate-translation`, `docs/namespace-required`, `docs/namespace-prefix`, `docs/no-images`, `docs/no-mdx`, `docs/broken-link`) cites ADR-0046 §3.2 / §3.4 or ADR-0130 D4, and each of those sections was checked to still exist and still say what is cited. No other retired justification found. --- _Generated by [Claude Code](https://claude.ai/code/session_01QCdUBjM47SxioST9z5Zwdf)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2b3eb17 commit d69f7e1

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
'@objectstack/cli': patch
3+
---
4+
5+
`collect-docs.ts` records what the `docs/duplicate-name` refusal rests on now that ADR-0048 §3.4 retired its older justification (#19248)
6+
7+
`docs/duplicate-name` refuses two owners declaring one doc name. The claim it
8+
was once explained by — *"one registration overwrites the other"* — was retired
9+
by ADR-0048, and a refusal whose stated justification no longer exists is worth
10+
examining rather than inheriting second-hand. #19248 examined it.
11+
12+
**The verdict is that no wording change was warranted**, and the ADR text is
13+
quoted into the rule's own docblock so the next reader does not have to
14+
re-derive it. §3.4 retires a RUNTIME throw and nothing else — *"The
15+
cross-package **throw is retired**; two distinct packages coexist on the same
16+
bare name by construction."* — while keeping, in the same clause, the class
17+
this lint belongs to: *"Authoring-time hygiene — an author shipping two
18+
`page/home` in one package — stays covered by the `naming/namespace-prefix`
19+
lint in `os lint`."* Both sentences are quoted verbatim, checked against
20+
`docs/adr/0048-cross-package-metadata-collision.md` on this branch's base
21+
(`13d52947d8`) rather than recalled.
22+
23+
The message already said `for authoring hygiene` and already declined the
24+
retired claim by name, so what shipped was correct and stays byte-identical.
25+
What the docblock gains is the ADR's own words, the card number the standing
26+
**severity** disagreement is filed under, and the boundary between the two
27+
questions: §3.4 hands authoring hygiene to a warning-only lint while this one
28+
is `severity: 'error'`, which is a live question about the level and not about
29+
the reason.
30+
31+
⛔ No behaviour changes. No rule, message, severity or accept set moves; the
32+
only edited bytes are inside one docblock comment.
33+
34+
**This ships, which is why it carries a changeset rather than
35+
`skip-changeset`.** `@objectstack/cli`'s published `files[]` is
36+
`["dist","README.md","CHANGELOG.md"]` and the package builds with plain `tsc`
37+
(`tsc -p tsconfig.build.json`, no `removeComments`), so the comment is emitted
38+
into the tarball — measured on the rebuilt artifact: the new clause is present
39+
in `dist/utils/collect-docs.js` (1 occurrence), the replaced spelling is absent
40+
from all of `dist` (0), and `dist/**/*.d.ts` carries 0 of it because the block
41+
sits above a non-exported helper. The rule's own runtime message resolves to
42+
that same file as the positive control. So the published JS bytes move while
43+
the declaration surface does not.

‎packages/cli/src/utils/collect-docs.ts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -934,8 +934,23 @@ function bodyDocsOf(packages: unknown, index: number): DocItem[] {
934934
* cross-package throw is retired"). What survives there is exactly what this
935935
* is: an authoring-time hygiene lint. ⚠️ That `os build` refuses the shape at
936936
* all is a standing disagreement with ADR-0048 §3.4 which PREDATES this card
937-
* and is filed rather than changed here — ⛔ relaxing a refusal that shipped is
938-
* not a rider on a widening.
937+
* and is filed as #19248 rather than changed here — ⛔ relaxing a refusal that
938+
* shipped is not a rider on a widening.
939+
*
940+
* #19248 read §3.4 back and settled the justification rather than moving it.
941+
* The clause retires a RUNTIME throw and nothing else — *"The cross-package
942+
* **throw is retired**; two distinct packages coexist on the same bare name by
943+
* construction."* — while keeping the class this lint belongs to: *"Authoring-time
944+
* hygiene — an author shipping two `page/home` in one package — stays covered by
945+
* the `naming/namespace-prefix` lint in `os lint`."* So the reason stated above is
946+
* the one that survived §3.4, and ⛔ no wording change was warranted. What #19248
947+
* left open is the SEVERITY, not the reason: §3.4 hands authoring hygiene to a
948+
* warning-only lint while this one is `severity: 'error'`.
949+
*
950+
* ⚠️ "this module's older framing" above is not gone — it is still live in this
951+
* file's HEADER docblock, which states the retired claim as the current reason for
952+
* the naming lints. Out of #19248's file surface (it also justifies
953+
* `docs/namespace-prefix`), so it is reported, not edited here.
939954
*/
940955
function lintDocNamesAcrossOwners(
941956
sets: ReadonlyArray<{ label: string; docs: readonly DocItem[] }>,

0 commit comments

Comments
 (0)