From db22a44014a31e8b1658d655109e922885ca100e Mon Sep 17 00:00:00 2001 From: os-steve Date: Wed, 19 Aug 2026 06:34:41 +0000 Subject: [PATCH] docs(objectql): drop the unverified "268KB" from the ./core boundary claim (#9803) The `@objectstack/objectql/core` entry comment sold the ADR-0076 D2 boundary with a hard byte figure ("the 268KB metadata protocol"). It is not merely stale - it never had a stated unit, and no refresh can supply one. Provenance, re-derivable with `git cat-file -s :`: 268,886 B packages/objectql/src/protocol.ts @ d9fe95fcf 268,921 B packages/metadata-protocol/src/protocol.ts @ 13dbcf2d0 (#2415) 1,054,749 B packages/metadata-protocol/src/protocol.ts @ HEAD The figure was raw source bytes of ONE file - what ADR-0076's premise paragraph counted on 2026-06-28 (268,886 B = 268.9 decimal KB). It was then re-pointed at a whole package ("the 268KB metadata-management layer"), a unit it never had. There is also no single right number to write instead. Measured today: 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 straddling "268KB" in both directions, before an embedder's own bundler and tree-shaking are considered. So the figure goes rather than getting refreshed: exclusion is the load-bearing claim and the D2 ratchet already pins it. Removed from core.ts and both embed-objectql sites; the provenance above is recorded, commit-pinned, in the ratchet test header. Adds a second assertion to that existing ratchet test so core.ts cannot quote a byte figure for the excluded weight again. It is a content assertion on one file, not a size ratchet: no threshold, and it can only fire on a KB/MB figure written into core.ts. Replayed over all 14 states of core.ts since the file was created: red at 13 (every one of them this same line), green only at this fix. docs/adr/0076-objectql-core-tiering.md keeps its three uses: governed surface, and historically accurate there - it describes protocol.ts the file. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XqDQYVU5smx29ts9pAErja --- examples/embed-objectql/README.md | 2 +- examples/embed-objectql/src/index.ts | 2 +- .../src/core-boundary.ratchet.test.ts | 65 ++++++++++++++++++- packages/objectql/src/core.ts | 7 +- 4 files changed, 70 insertions(+), 6 deletions(-) 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 {