diff --git a/examples/embed-objectql/README.md b/examples/embed-objectql/README.md index 1e8adfbadf..bd6856bd94 100644 --- a/examples/embed-objectql/README.md +++ b/examples/embed-objectql/README.md @@ -15,7 +15,7 @@ import { ObjectQL } from '@objectstack/objectql/core'; `@objectstack/objectql/core` exposes the engine, registry, hooks, and validation only. It does **not** pull in `ObjectQLPlugin`, the kernel factory, or -`@objectstack/metadata-protocol` (the 268KB metadata-management layer), so none +`@objectstack/metadata-protocol` (the metadata-management layer), so none of that lands in your bundle. (The batteries-included `@objectstack/objectql` entry still re-exports everything for full hosts.) diff --git a/examples/embed-objectql/src/index.ts b/examples/embed-objectql/src/index.ts index 9cb8530f3e..a63baeaccd 100644 --- a/examples/embed-objectql/src/index.ts +++ b/examples/embed-objectql/src/index.ts @@ -4,7 +4,7 @@ // // This imports from `@objectstack/objectql/core` — the LEAN entry. It pulls the // data engine (query/CRUD/hooks/validation) only: NO kernel, NO ObjectQLPlugin, -// and NOT `@objectstack/metadata-protocol` (the 268KB metadata-management layer). +// and NOT `@objectstack/metadata-protocol` (the metadata-management layer). // Ideal for a thin, latency-sensitive host (e.g. a gateway) that wants the // engine and the *same* object definitions as the full platform, without the // platform itself. diff --git a/packages/objectql/src/core-boundary.ratchet.test.ts b/packages/objectql/src/core-boundary.ratchet.test.ts index 844fa1686f..0252c8399b 100644 --- a/packages/objectql/src/core-boundary.ratchet.test.ts +++ b/packages/objectql/src/core-boundary.ratchet.test.ts @@ -4,7 +4,47 @@ // (src/core.ts) and its entire local import closure must NOT depend on the kernel // plugin, the kernel factory, or the metadata-management protocol — so a thin // embedder importing `@objectstack/objectql/core` never pulls -// `@objectstack/metadata-protocol` (or its 268KB) into its graph. +// `@objectstack/metadata-protocol` into its graph. +// +// --------------------------------------------------------------------------- +// Why no byte figure is quoted for what is excluded (#9803) +// +// The entry comment used to sell this boundary with a hard number. That number +// was real once, but it never measured the thing the sentence claimed. Full +// provenance, each line re-derivable with `git cat-file -s :` +// (measured 2026-08-19; the extraction predates the default shallow clone, so +// `git fetch --deepen=1200` first): +// +// 268,886 B packages/objectql/src/protocol.ts @ d9fe95fcf +// the pre-extraction SOURCE FILE — what ADR-0076's premise +// paragraph counted. 268,886 B = 268.9 decimal KB, hence "268KB". +// 268,921 B packages/metadata-protocol/src/protocol.ts @ 13dbcf2d0 +// the same file as it landed in the new package, 2026-06-28, +// "extract metadata-protocol + add lean ./core entry (ADR-0076 +// Step 1)" (#2415). +// 1,054,749 B packages/metadata-protocol/src/protocol.ts @ HEAD +// 3.9x the quoted figure — and that is ONE file of a package +// whose src tree totals ~3.6 MB (`find … -type f | xargs wc -c`). +// +// So the figure was raw source bytes of a single file, and was then re-pointed +// at a whole package ("the 268KB metadata-management layer") — a unit it never +// had. Re-measuring cannot repair that, because there is no one number to +// re-measure. "The size of @objectstack/metadata-protocol" on 2026-08-19, after +// `pnpm --filter @objectstack/metadata-protocol build`, via `wc -c` and +// `gzip -9 -c | wc -c`: +// +// 169,718 B dist/index.js, gzipped (LESS than the quoted figure) +// 591,087 B dist/index.js, raw +// 1,054,749 B src/protocol.ts (the quoted figure's own unit) +// 1,513,973 B src/**/*.ts, excluding tests +// 3,637,237 B src/**/*.ts +// +// A 21x spread that straddles "268KB" in BOTH directions, before an embedder's +// own bundler and tree-shaking are even considered. The defect is therefore not +// staleness — it is that the figure never had a stated unit, and no refresh can +// supply one. The claim worth making is EXCLUSION, and the test below is what +// pins it. The second test keeps a figure from growing back into core.ts. +// --------------------------------------------------------------------------- // // If this test fails, you added a forbidden import somewhere reachable from // core.ts. Keep metadata/plugin/kernel concerns out of the core closure. @@ -70,4 +110,27 @@ describe('ADR-0076 D2 — @objectstack/objectql/core boundary', () => { // sanity: the engine itself IS in the closure expect([...visited].some((f) => f.endsWith('/engine.ts'))).toBe(true); }); + + // #9803. The exclusion claim is pinned by the test above. A byte figure for + // the excluded weight is pinned by nothing, so core.ts must not state one — + // that is how "268KB" sat there unverified from 2026-06-28 until #9803. + // Scope is deliberately this package's entry only: the historical figures in + // this file's own header are provenance (dated, commit-pinned), not a claim, + // and are meant to stay. + it('core.ts quotes no unverifiable byte figure for the excluded weight', () => { + const src = readFileSync(resolve(SRC, 'core.ts'), 'utf8'); + const offenders = src + .split('\n') + .filter((line) => /^\s*(?:\/\/|\/\*|\*)/.test(line)) + .filter((line) => /metadata[- ](?:protocol|management)/i.test(line)) + .filter((line) => /\b\d[\d.,]*\s*(?:[KMG]i?B|kB)\b/.test(line)) + .map((line) => line.trim()); + + expect( + offenders, + `core.ts states a byte figure for the excluded metadata protocol:\n${offenders.join( + '\n', + )}\nNothing re-measures such a number. State the exclusion, not a size — see this file's header.`, + ).toEqual([]); + }); }); diff --git a/packages/objectql/src/core.ts b/packages/objectql/src/core.ts index f2a1a1a3d2..b44a867b00 100644 --- a/packages/objectql/src/core.ts +++ b/packages/objectql/src/core.ts @@ -4,12 +4,13 @@ // registry, hooks, validation, in-memory aggregation, utilities — WITHOUT the // kernel plugin (`ObjectQLPlugin`), the kernel factory, or any metadata // management (`@objectstack/metadata-protocol`). Embedders that want only the -// engine (e.g. a thin gateway) import from `@objectstack/objectql/core` so the -// 268KB metadata protocol is never pulled into their dependency graph. +// engine (e.g. a thin gateway) import from `@objectstack/objectql/core` so +// `@objectstack/metadata-protocol` is never pulled into their dependency graph. // // A boundary ratchet (ADR-0076 D2) keeps this entry free of protocol/plugin // imports; do not add `./plugin`, `./kernel-factory`, or `@objectstack/metadata-protocol` -// re-exports here. +// re-exports here. That ratchet — not a byte figure — is what backs the sentence +// above; see core-boundary.ratchet.test.ts for why no size is quoted (#9803). // Registry export {