test(05-05): BA9 bundle-budget + BA10 fixture-parity gates + BA5 harness-sentinel extension
- BA9: summed gz size of fixtures dataset + routing/src + web/src/route sources <= 204800 bytes, measurement printed every run (D-11, T-05-12) - BA10: every committed pairId must appear in the shipped JS assets (the BA7 analog — a stale fixture-less bundle is unshippable) - BA5: ROUTE_PROFILE_HARNESS_ONLY joins the harness-leak token scan (the 05-05 route-profiles module must be dead-code-eliminated from dist) - TDD note: gates target artifacts already shipped by 05-02/05-04, so no failing RED run exists; mechanism teeth proven (bogus pairId absent)
This commit is contained in:
@@ -35,6 +35,14 @@
|
|||||||
* OFFICIAL Telegram SDK script is loaded EXTERNALLY from
|
* OFFICIAL Telegram SDK script is loaded EXTERNALLY from
|
||||||
* telegram.org (not bundled) and may contain crypto internals of
|
* telegram.org (not bundled) and may contain crypto internals of
|
||||||
* its own.
|
* its own.
|
||||||
|
* BA9 the route payload fits the D-11 bundle budget: the summed gzipped
|
||||||
|
* size of the fixture dataset (routing/src/data/route-fixtures.json),
|
||||||
|
* every routing/src *.ts, and every web/src/route *.ts is ≤ 204800
|
||||||
|
* bytes (200 KiB) — and the measurement is PRINTED on every run (the
|
||||||
|
* budget is visible, never discovered). T-05-12.
|
||||||
|
* BA10 the shipped JS carries EVERY pairId from the committed
|
||||||
|
* route-fixtures.json (the BA7 analog, T-05-12/D-11): a stale bundle
|
||||||
|
* that lost the fixtures could never serve a route.
|
||||||
*
|
*
|
||||||
* If web/dist does not exist, every case fails with a build-first message.
|
* If web/dist does not exist, every case fails with a build-first message.
|
||||||
*/
|
*/
|
||||||
@@ -43,8 +51,10 @@ import { readdirSync, readFileSync, existsSync } from "node:fs";
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import { gzipSync } from "node:zlib";
|
||||||
import { test } from "./harness.mjs";
|
import { test } from "./harness.mjs";
|
||||||
import gazetteer from "../../search/src/data/kl-gazetteer.json" with { type: "json" };
|
import gazetteer from "../../search/src/data/kl-gazetteer.json" with { type: "json" };
|
||||||
|
import routeFixtures from "../../routing/src/data/route-fixtures.json" with { type: "json" };
|
||||||
|
|
||||||
const WEB = path.join(fileURLToPath(new URL(import.meta.url)), "..", "..");
|
const WEB = path.join(fileURLToPath(new URL(import.meta.url)), "..", "..");
|
||||||
const DIST = join(WEB, "dist");
|
const DIST = join(WEB, "dist");
|
||||||
@@ -123,14 +133,14 @@ test("BA5 production bundle carries NO Mock-Telegram installer in ANY emitted fi
|
|||||||
assert.ok(existsSync(DIST), claimBuildFirst().message);
|
assert.ok(existsSync(DIST), claimBuildFirst().message);
|
||||||
const jsAssets = jsFiles.map((f) => readFileSync(f, "utf8")).join("");
|
const jsAssets = jsFiles.map((f) => readFileSync(f, "utf8")).join("");
|
||||||
const allHtml = htmlFiles.map((f) => readFileSync(f, "utf8")).join("");
|
const allHtml = htmlFiles.map((f) => readFileSync(f, "utf8")).join("");
|
||||||
for (const token of ["installMockWebApp", "__ARAHARAH_MOCK__"]) {
|
for (const token of ["installMockWebApp", "__ARAHARAH_MOCK__", "ROUTE_PROFILE_HARNESS_ONLY"]) {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
!jsAssets.includes(token),
|
!jsAssets.includes(token),
|
||||||
`installMockWebApp gate: "${token}" found in a web/dist JS asset — the mock survived tree-shaking`,
|
`harness-leak gate: "${token}" found in a web/dist JS asset — the mock survived tree-shaking`,
|
||||||
);
|
);
|
||||||
assert.ok(
|
assert.ok(
|
||||||
!allHtml.includes(token),
|
!allHtml.includes(token),
|
||||||
`installMockWebApp gate: "${token}" found in an emitted web/dist HTML (${htmlFiles.join(", ")}) — the runner page's profile block shipped`,
|
`harness-leak gate: "${token}" found in an emitted web/dist HTML (${htmlFiles.join(", ")}) — the runner page's profile block shipped`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -174,3 +184,61 @@ test("BA8 the shipped bundle carries NO deep-link crypto (D-11, T-04-40)", () =>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ————— the route family's production-build gates (05-05, D-11, T-05-12) ————— */
|
||||||
|
|
||||||
|
/* BA9's inputs: every committed file the route experience ADDS to the web
|
||||||
|
* bundle — the fixture dataset, the routing workspace sources, and the web
|
||||||
|
* route modules. All are committed files, production-shaped by construction.
|
||||||
|
* The minified route code's gz size is approximated by its SOURCE gz size —
|
||||||
|
* the approximation is conservative in the gate's favor at these sizes
|
||||||
|
* (minified+gzipped code is smaller than source gzipped), and the 200 KiB
|
||||||
|
* ceiling carries an order-of-magnitude headroom (05-RESEARCH Finding 1:
|
||||||
|
* the fixtures dominate at ~16.6 KB gz). A silent fixture bloat (someone
|
||||||
|
* re-fetching with overview=full&steps=true) fails HERE, at the build gate —
|
||||||
|
* never surfaces as a slow webview (T-05-12). */
|
||||||
|
const ROUTE_INPUT_DIRS = [
|
||||||
|
join(WEB, "..", "routing", "src"),
|
||||||
|
join(WEB, "src", "route"),
|
||||||
|
];
|
||||||
|
const ROUTE_FIXTURES_FILE = join(WEB, "..", "routing", "src", "data", "route-fixtures.json");
|
||||||
|
|
||||||
|
function collectTsFiles(dir) {
|
||||||
|
const out = [];
|
||||||
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
||||||
|
const full = join(dir, entry.name);
|
||||||
|
if (entry.isDirectory()) out.push(...collectTsFiles(full));
|
||||||
|
else if (entry.name.endsWith(".ts")) out.push(full);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("BA9 the route payload fits the 200 KiB gz bundle budget, measured and printed (D-11, T-05-12)", () => {
|
||||||
|
assert.ok(existsSync(DIST), claimBuildFirst().message);
|
||||||
|
const inputs = [ROUTE_FIXTURES_FILE, ...ROUTE_INPUT_DIRS.flatMap((dir) => collectTsFiles(dir))];
|
||||||
|
assert.ok(inputs.length >= 10, `scanned a real input set (found ${inputs.length} files)`);
|
||||||
|
const total = inputs.reduce((sum, f) => sum + gzipSync(readFileSync(f)).length, 0);
|
||||||
|
/* The measurement is VISIBLE on every run (D-11: "enforced as a BA
|
||||||
|
* build-artifact gate" — a budget nobody sees is a hope, not a gate). */
|
||||||
|
console.log(`BA9 route bundle budget: ${total} / 204800 gz bytes`);
|
||||||
|
assert.ok(
|
||||||
|
total <= 204800,
|
||||||
|
`route payload is ${total} gz bytes — over the 204800-byte (200 KiB) D-11 budget by ${total - 204800}. ` +
|
||||||
|
`Shrink the fixtures (simplified geometry) or the route code before shipping (T-05-12).`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("BA10 the shipped bundle carries EVERY committed pairId (the BA7 fixture-parity analog, T-05-12)", () => {
|
||||||
|
assert.ok(existsSync(DIST_ASSETS), claimBuildFirst().message);
|
||||||
|
const bundle = jsFiles
|
||||||
|
.filter((f) => f.startsWith(DIST_ASSETS))
|
||||||
|
.map((f) => readFileSync(f, "utf8"))
|
||||||
|
.join("");
|
||||||
|
assert.ok(routeFixtures.pairs.length >= 10, `scanned a real dataset (found ${routeFixtures.pairs.length} pairs)`);
|
||||||
|
for (const pair of routeFixtures.pairs) {
|
||||||
|
assert.ok(
|
||||||
|
bundle.includes(pair.pairId),
|
||||||
|
`pairId "${pair.pairId}" is MISSING from the shipped web bundle — a stale bundle that lost the fixtures could never serve a route (T-05-12); fixtures are never renamed, only added`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user