Milestone v1 (v2.0.0): Mokosh — Session Capture #1
@@ -103,6 +103,8 @@ import {
|
||||
driveA30,
|
||||
// Plan 03-03 — password-filter PARTIAL (SPEC §10 #8 PARTIAL per D-P3-02)
|
||||
driveA31,
|
||||
// Plan 03-04 — RAM scaffolding best-effort (SPEC §10 #9 per D-P3-04)
|
||||
driveA32,
|
||||
getManifestVersion,
|
||||
} from './lib/harness-page-driver';
|
||||
import {
|
||||
@@ -271,7 +273,7 @@ async function assertA0_GrepGate(): Promise<{
|
||||
*/
|
||||
async function main(): Promise<number> {
|
||||
process.stdout.write('\nMokosh Plan 01-13 + 01-14 + 02-04 — UAT harness orchestrator\n');
|
||||
process.stdout.write('Architecture: A0 pre-flight + extension-internal page driver (A1..A14, A15..A17, A18..A22, A23, A24, A25, A26, A27, A28, A29, A30, A31)\n');
|
||||
process.stdout.write('Architecture: A0 pre-flight + extension-internal page driver (A1..A14, A15..A17, A18..A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32)\n');
|
||||
process.stdout.write('='.repeat(72) + '\n');
|
||||
|
||||
// A0 pre-flight (no Chrome launch needed; runs against built dist/).
|
||||
@@ -475,6 +477,13 @@ async function main(): Promise<number> {
|
||||
// mean the filter actually fired rather than the trivial "no
|
||||
// events at all" tautology).
|
||||
{ name: 'A31', drive: driveA31Wrapped },
|
||||
// Plan 03-04 A32: RAM scaffolding (SPEC §10 #9 best-effort per D-P3-04).
|
||||
// NOTE — Page.metrics is page-realm only; SW context is a separate
|
||||
// Puppeteer target (RESEARCH Pitfall 2). A32 is informational
|
||||
// scaffolding; the binding §10 #9 gate lives in Plan 03-05
|
||||
// VERIFICATION.md `human_verification` block. No wrapped const
|
||||
// needed — driveA32 takes only `page`.
|
||||
{ name: 'A32', drive: driveA32 },
|
||||
];
|
||||
|
||||
const buffers = { swConsole: handles.swConsole, offConsole: handles.offConsole };
|
||||
|
||||
@@ -2314,3 +2314,93 @@ export async function driveA31(
|
||||
error: pageResult.error,
|
||||
};
|
||||
}
|
||||
|
||||
/* ─── Plan 03-04 — driveA32 (RAM scaffolding best-effort) ──────────── */
|
||||
|
||||
/** RAM ceiling per SPEC §10 #9 + CON-ram-ceiling. */
|
||||
const A32_RAM_CEILING_BYTES = 50 * 1024 * 1024;
|
||||
/** Bytes-per-MB factor for diagnostic copy. */
|
||||
const A32_BYTES_PER_MB = 1024 * 1024;
|
||||
|
||||
/**
|
||||
* Drive A32 (Plan 03-04 — SPEC §10 #9 RAM best-effort per D-P3-04).
|
||||
*
|
||||
* Reads puppeteer.Page.metrics() against the harness page and asserts
|
||||
* JSHeapUsedSize is below the 50 MB ceiling. This is informational
|
||||
* scaffolding ONLY:
|
||||
*
|
||||
* - RESEARCH Pitfall 2: Page.metrics is page-realm only. The MV3
|
||||
* service worker is a separate Puppeteer target with its own V8
|
||||
* isolate; page.metrics() does not aggregate across workers/iframes.
|
||||
* - The page-realm value reported here is NOT the operator-facing
|
||||
* "extension background RAM" measurement that SPEC §10 #9 requires.
|
||||
* - The binding §10 #9 gate lives in Plan 03-05 VERIFICATION.md
|
||||
* `human_verification` block (operator runs chrome://memory-internals
|
||||
* OR chrome://extensions service-worker memory display).
|
||||
*
|
||||
* Why ship this anyway (per RESEARCH Open Question 3):
|
||||
* - Low cost (~30 lines; single API call; no new bundle surface).
|
||||
* - Exercises the Page.metrics API end-to-end so Phase 4 (programmatic
|
||||
* RAM measurement upgrade) inherits a working scaffold.
|
||||
* - Provides a sanity floor — if the harness page-realm heap ever
|
||||
* blows past 50 MB, something has gone catastrophically wrong in
|
||||
* the test infrastructure itself (not necessarily a §10 #9 regression
|
||||
* in production).
|
||||
*
|
||||
* The diagnostic line about page-realm scope MUST be emitted regardless
|
||||
* of pass/fail per Pitfall 2.
|
||||
*
|
||||
* @param page - The harness page from `launchHarnessBrowser`.
|
||||
* @returns AssertionRecord with 2 checks (heap returned + heap < 50 MB)
|
||||
* + explicit page-realm-only diagnostic.
|
||||
*/
|
||||
export async function driveA32(page: Page): Promise<AssertionRecord> {
|
||||
const checks: CheckRecord[] = [];
|
||||
const diagnostics: string[] = [];
|
||||
|
||||
// Pitfall 2 gate: emit the page-realm caveat BEFORE any other diagnostic
|
||||
// so it leads in the structured output (the operator sees it first).
|
||||
diagnostics.push(
|
||||
'NOTE: page-realm only; SW context measurement requires chrome://memory-internals operator verification per D-P3-04.',
|
||||
);
|
||||
|
||||
let metricsErr: string | null = null;
|
||||
let jsHeapBytes = -1;
|
||||
let jsHeapTotal = -1;
|
||||
try {
|
||||
const metrics = await page.metrics();
|
||||
jsHeapBytes = metrics.JSHeapUsedSize ?? -1;
|
||||
jsHeapTotal = metrics.JSHeapTotalSize ?? -1;
|
||||
} catch (err) {
|
||||
metricsErr = err instanceof Error ? err.message : String(err);
|
||||
}
|
||||
|
||||
const jsHeapMB = jsHeapBytes >= 0 ? jsHeapBytes / A32_BYTES_PER_MB : -1;
|
||||
diagnostics.push(`A32 JSHeapUsedSize=${jsHeapBytes} bytes (${jsHeapMB.toFixed(2)} MB)`);
|
||||
diagnostics.push(`A32 JSHeapTotalSize=${jsHeapTotal} bytes`);
|
||||
if (metricsErr !== null) {
|
||||
diagnostics.push(`A32 Page.metrics threw: ${metricsErr}`);
|
||||
}
|
||||
|
||||
checks.push({
|
||||
name: 'A32.1: Page.metrics returned a JSHeapUsedSize value >= 0',
|
||||
expected: '>= 0',
|
||||
actual: jsHeapBytes,
|
||||
passed: jsHeapBytes >= 0,
|
||||
});
|
||||
checks.push({
|
||||
name: `A32.2: Page-realm JS heap < ${A32_RAM_CEILING_BYTES / A32_BYTES_PER_MB} MB (NOTE: scaffolding only; SW context excluded per D-P3-04)`,
|
||||
expected: `< ${A32_RAM_CEILING_BYTES / A32_BYTES_PER_MB} MB`,
|
||||
actual: jsHeapMB >= 0 ? `${jsHeapMB.toFixed(2)} MB` : 'unavailable',
|
||||
passed: jsHeapBytes >= 0 && jsHeapBytes < A32_RAM_CEILING_BYTES,
|
||||
});
|
||||
|
||||
const passed = checks.every((c) => c.passed);
|
||||
return {
|
||||
passed,
|
||||
name: 'A32 — RAM scaffolding (best-effort; page-realm only per D-P3-04 / SPEC §10 #9)',
|
||||
checks,
|
||||
diagnostics,
|
||||
error: metricsErr ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user