Skip to content

Commit 09c1d91

Browse files
os-muskclaude
andauthored
docs(metadata): record what the errors leaf entry actually loads in its own header (#16981)
`packages/metadata/src/errors.ts` explains why the leaf subpath exists — the root entry pulls the manager, every loader and the YAML/filesystem machinery, and a consumer wanting a 40-line predicate should not load any of that. Measured, that promise half holds, and the header did not say which half. MEASURED 2026-09-08 on `origin/main` 8c1515e with `scripts/check-lean-entry-closure.mjs`'s exported `measure()`/`byPackage()`: both published conditions load four packages, and the manager, every loader, `chokidar`, `glob`, `js-yaml` and `readdirp` are absent from all of them — the accurate half, kept verbatim. But `import` evaluates 83 modules / 2,201,709 bytes and `require` 83 / 2,355,405, because `@objectstack/types` imports both `@objectstack/spec/api` (1,401,253 B) and `@objectstack/spec/security` (195,367 B) at module top as values. The header now carries that, with the two costs separated — 143 bytes of marginal in-repo contribution against the megabytes an out-of-repo consumer pays — and labels the figures PROVENANCE, dated and tree-pinned, with the instrument named so the next reader re-takes rather than quotes them. Claude-Session: https://claude.ai/code/session_01ADLdAs2pVcH17h9tZKWMBg Co-authored-by: Claude <noreply@anthropic.com>
1 parent b834b48 commit 09c1d91

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@objectstack/metadata": patch
3+
---
4+
5+
docs(metadata): the `@objectstack/metadata/errors` header records what the leaf entry actually loads — 4 packages, 83 modules, 2.2 MB — instead of leaving the reader to infer it is light (#15346)
6+
7+
`packages/metadata/src/errors.ts` is the leaf subpath `@objectstack/metadata/errors`, and its header explains why the subpath exists: the root entry pulls the manager, every loader and the YAML/filesystem machinery behind them, and "a consumer that wants a 40-line predicate should not have to load any of that". Measured, that promise half holds — and the header did not say which half.
8+
9+
**The half that holds, and stays:** MEASURED 2026-09-08 on `origin/main` `8c1515e847`, with `scripts/check-lean-entry-closure.mjs`'s exported `measure()`/`byPackage()` (one fresh child per published condition; module set collected through `module.registerHooks` unioned with `require.cache`). Both published conditions load exactly four packages, and the manager, every loader, `chokidar`, `glob`, `js-yaml` and `readdirp` are absent from all of them. That is the claim the header actually wrote, and it is accurate.
10+
11+
**The half that had drifted:** the general conclusion a reader takes away. `import` loads 83 modules / 2,201,709 bytes; `require` loads 83 / 2,355,405. Since the maintainer's 2026-08-30 ruling the file re-exports from `@objectstack/types`, which builds to one bundled module importing **both** `@objectstack/spec/api` (1,401,253 B) and `@objectstack/spec/security` (195,367 B) at module top, as values — `api` is the dominant edge at 7x `security`, and the two spec entries are independent of each other.
12+
13+
The header now separates the two costs the way the finding did, because conflating them is the available mistake: **in-repo the marginal contribution is 143 bytes** — the only current consumer of the subpath, `@objectstack/metadata-protocol`, declares `@objectstack/spec` itself and pays for that closure anyway — while the megabytes are what an **out-of-repo** consumer pays, which nothing here can measure. The figures are labelled PROVENANCE, dated and tree-pinned, in the manner the neighbouring gate keeps its own: nothing derives from them, nothing compares against them, and the header says to re-take them rather than quote them. They rot fast — the same measurement four days earlier at `6e67b86c0` found the same 83 modules but 2,487,842 bytes, 286,133 more, without this file changing at all.
14+
15+
**Why `patch` and not `skip-changeset`, measured rather than assumed.** `@objectstack/metadata` is released (17.3.0) and `errors.ts` is a shipped source file, so "a comment publishes nothing" needed checking rather than asserting. Building the package before and after the edit: `dist/errors.js`, `dist/errors.cjs`, `dist/errors.d.ts` and `dist/errors.d.cts` are **byte-identical** (esbuild strips the comment, and there is no `sourcesContent`), but `dist/errors.js.map` and `dist/errors.cjs.map` **change** — the export statement moved from source line 65 to line 113, so the `mappings` VLQ moves with it (`;AAgEA,…` → `;AAgHA,…`), at identical file size. `npm pack --dry-run` lists both maps in the tarball. So this diff does publish bytes from a released package, which is exactly what `skip-changeset` is not for. Nothing executable and no type changes: a consumer's stack traces resolve to the right source line, and that is the whole of it.

‎packages/metadata/src/errors.ts‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,54 @@
5151
* edge — and stays a single, greppable seam to delete if the maintainer later
5252
* takes option 2.
5353
*
54+
* ## What the subpath actually loads — measured, and only half as promised
55+
*
56+
* The paragraph above is about the manager and the YAML machinery, and that
57+
* half is accurate. MEASURED 2026-09-08 on `origin/main` 8c1515e847, with
58+
* `scripts/check-lean-entry-closure.mjs`'s exported `measure()`/`byPackage()`
59+
* (one fresh child per published condition, module set collected through
60+
* `module.registerHooks` unioned with `require.cache`): both conditions load
61+
* FOUR packages, and the manager, every loader, `chokidar`, `glob`, `js-yaml`
62+
* and `readdirp` are all absent from every one of them.
63+
*
64+
* What does NOT follow — and is the general conclusion a reader takes from
65+
* the paragraph above — is that the entry is therefore light:
66+
*
67+
* condition packages modules bytes
68+
* import (ESM) 4 83 2,201,709
69+
* require (CJS) 4 83 2,355,405
70+
*
71+
* the four: `@objectstack/spec`, `zod`, `@objectstack/types`, and
72+
* `@objectstack/metadata` — this file, 143 B of the ESM total.
73+
*
74+
* ⛔ Those figures are PROVENANCE, dated and tree-pinned in the manner the
75+
* script above keeps its own: nothing derives from them and nothing compares
76+
* against them. They rot. The same measurement at `6e67b86c0` four days
77+
* earlier found the same 83 modules but 2,487,842 bytes — 286,133 more —
78+
* without this file changing at all. ⇒ re-take them with that script rather
79+
* than quote them, and note what #9803 concluded for the neighbouring
80+
* boundary: the claim worth making is the EXCLUSION above, never a size.
81+
*
82+
* The weight arrives through the re-export, not through anything this package
83+
* ships. `@objectstack/types` builds to one bundled module which imports
84+
* `@objectstack/spec/api` (1,401,253 B) and `@objectstack/spec/security`
85+
* (195,367 B) at module top, both as VALUES; the two spec entries are
86+
* independent of each other and each pulls `zod`. `api` is thus the dominant
87+
* edge at 7x `security` — a chain wider than the `security`-only one #15346
88+
* recorded.
89+
*
90+
* ⚠️ Two different costs, and ⛔ never one. IN-REPO this entry's marginal
91+
* contribution is 143 bytes: the only current consumer of the subpath,
92+
* `@objectstack/metadata-protocol`, declares `@objectstack/spec` itself and
93+
* pays for that closure regardless. The megabytes are what an OUT-OF-REPO
94+
* consumer pays for a 40-line predicate — unmeasurable from here, which is
95+
* ⛔ not a reason to treat it as zero.
96+
*
97+
* Recorded, not repaired. Collapsing the chain means a lazy or type-only edge
98+
* from the predicate's home in `@objectstack/types` to `@objectstack/spec`,
99+
* which is a `packages/types` + `packages/spec` change and the `domain:spec`
100+
* seat's call rather than this lane's (#15346).
101+
*
54102
* ## Scope of the promise
55103
*
56104
* Only {@link isMissingTableError} is re-exported HERE. Its sibling

0 commit comments

Comments
 (0)