Files
claw/tests/generated_scene_mock_runtime_harness_runner.js

359 lines
11 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const repoRoot = path.resolve(__dirname, '..');
const skillRoot = path.join(
repoRoot,
'examples',
'scene_skill_102_final_materialization_2026-04-19',
'skills',
);
const matrixPath = path.join(
repoRoot,
'tests',
'fixtures',
'generated_scene',
'scene_skill_102_mock_runtime_validation_matrix_2026-04-20.json',
);
const outputPath = path.join(
repoRoot,
'tests',
'fixtures',
'generated_scene',
'scene_skill_102_mock_runtime_harness_results_2026-04-20.json',
);
const reportPath = path.join(
repoRoot,
'docs',
'superpowers',
'reports',
'2026-04-20-scene-skill-102-mock-runtime-harness-report.md',
);
function readJson(file) {
return JSON.parse(fs.readFileSync(file, 'utf8'));
}
function writeJson(file, value) {
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
}
function findScript(sceneId) {
const scriptsDir = path.join(skillRoot, sceneId, 'scripts');
const scripts = fs
.readdirSync(scriptsDir)
.filter((name) => name.endsWith('.js') && !name.endsWith('.test.js'))
.sort();
if (scripts.length === 0) {
throw new Error(`no runtime script found for ${sceneId}`);
}
return path.join(scriptsDir, scripts[0]);
}
function createResponse(payload) {
return {
ok: true,
status: 200,
async json() {
return payload;
},
};
}
function parseBody(body) {
if (!body || typeof body !== 'string') return {};
try {
return JSON.parse(body);
} catch (_) {
return Object.fromEntries(
body
.split('&')
.filter(Boolean)
.map((part) => {
const [key, value = ''] = part.split('=');
return [decodeURIComponent(key), decodeURIComponent(value)];
}),
);
}
}
function makeRichRow() {
return {
id: 'row-1',
wkOrderNo: 'WK-1',
countyCodeName: 'COUNTY-1',
orgNo: 'ORG-1',
orgName: 'ORG-NAME',
ORG_NAME: 'ORG-NAME',
YGDL: '100',
LINE_LOSS_RATE: '1.23',
PPQ: '10',
UPQ: '9',
LOSS_PQ: '1',
countyName: 'COUNTY-1',
dyfjmZs: '1',
dyfjmHgZs: '1',
dyfjmHgl: '100%',
gyxzzrZs: '1',
gyxzzrHgZs: '1',
gyxzzrHgl: '100%',
dyjmZs: '1',
dyjmHgZs: '1',
dyjmHgl: '100%',
assetId: 'ASSET-1',
deviceName: 'DEVICE-1',
value: 'ok',
dataStatus: 'ok',
};
}
function installGlobals(archetype, expectedDomain, requestLog) {
delete global.$;
global.location = { hostname: expectedDomain || '' };
global.window = global;
global.document = {
title: 'mock page',
querySelector() {
return null;
},
querySelectorAll() {
return [];
},
};
global.fetch = async (url, options = {}) => {
requestLog.push({
via: 'fetch',
url: String(url),
method: options.method || 'GET',
body: options.body || '',
});
const body = parseBody(options.body);
const row = makeRichRow();
if (archetype === 'paginated_enrichment') {
if (body.page && Number(body.page) > 1) return createResponse({ data: [] });
if (String(url).includes('yx.gs.sgcc.com.cn')) {
return createResponse({ data: { enrichmentField: 'detail', ...row } });
}
return createResponse({ data: [row] });
}
if (archetype === 'multi_mode_request') {
return createResponse({ content: [row], data: [row], rows: [row] });
}
if (archetype === 'single_request_enrichment') {
return createResponse({ data: [row], rows: [row] });
}
if (archetype === 'multi_endpoint_inventory') {
return createResponse({ rows: [row], data: [row] });
}
if (archetype === 'local_doc_pipeline') {
return createResponse({ ok: true, data: [row], rows: [row] });
}
if (archetype === 'page_state_eval') {
return createResponse({ data: [row] });
}
return createResponse({ data: [row], rows: [row] });
};
}
function makeDeps(archetype, expectedDomain, requestLog) {
const validatePageContext = () => ({ ok: true });
if (archetype === 'host_bridge_workflow') {
return {
validatePageContext,
async invokeHostBridge(action, args) {
requestLog.push({ via: 'host-bridge', action, args });
return { ok: true, action, callbackId: 'mock-callback' };
},
async queryCallbackEndpoint(endpoint, args) {
requestLog.push({ via: 'callback', endpoint: endpoint.name, args });
return { data: [makeRichRow()] };
},
};
}
if (archetype === 'page_state_eval') {
return {
validatePageContext,
async queryState(args) {
requestLog.push({ via: 'page-state', args });
return { data: [makeRichRow()] };
},
};
}
return undefined;
}
async function runRepresentative(sceneId, archetype) {
const scriptPath = findScript(sceneId);
const report = readJson(path.join(skillRoot, sceneId, 'references', 'generation-report.json'));
const expectedDomain = report.bootstrap?.expectedDomain || '';
const requestLog = [];
const started = Date.now();
installGlobals(archetype, expectedDomain, requestLog);
delete require.cache[require.resolve(scriptPath)];
let mod;
try {
mod = require(scriptPath);
} catch (error) {
return {
sceneId,
archetype,
scriptPath: path.relative(repoRoot, scriptPath).replace(/\\/g, '/'),
scriptLoadStatus: 'script-load-fail',
mockRuntimeStatus: 'mock-runtime-fail',
failureReason: `script_load_failed:${error.message}`,
durationMs: Date.now() - started,
requestLog,
};
}
if (typeof mod.buildBrowserEntrypointResult !== 'function') {
return {
sceneId,
archetype,
scriptPath: path.relative(repoRoot, scriptPath).replace(/\\/g, '/'),
scriptLoadStatus: 'script-load-pass',
mockRuntimeStatus: 'mock-runtime-fail',
failureReason: 'missing_buildBrowserEntrypointResult_export',
durationMs: Date.now() - started,
requestLog,
};
}
const args = {
expected_domain: expectedDomain,
target_url: report.bootstrap?.targetUrl || '',
org_label: 'MOCK_ORG',
org_code: 'MOCK_ORG_CODE',
period_mode: report.defaultMode || 'month',
period_mode_code: report.defaultMode || 'month',
period_value: '2026-04',
period_payload: {},
};
try {
const deps = makeDeps(archetype, expectedDomain, requestLog);
const artifact = deps
? await mod.buildBrowserEntrypointResult(args, deps)
: await mod.buildBrowserEntrypointResult(args);
const artifactStatus = artifact?.status || 'missing';
const okStatuses = new Set(['ok', 'partial', 'empty']);
return {
sceneId,
archetype,
scriptPath: path.relative(repoRoot, scriptPath).replace(/\\/g, '/'),
scriptLoadStatus: 'script-load-pass',
mockDependencyStatus: 'mock-dependency-ready',
mockRuntimeStatus: okStatuses.has(artifactStatus)
? 'mock-runtime-pass'
: 'mock-runtime-fail',
artifactStatus,
artifactType: artifact?.type || null,
rowCount: Array.isArray(artifact?.rows) ? artifact.rows.length : null,
counts: artifact?.counts || {},
failureReason: okStatuses.has(artifactStatus)
? null
: `artifact_status_${artifactStatus}`,
durationMs: Date.now() - started,
requestLog,
};
} catch (error) {
return {
sceneId,
archetype,
scriptPath: path.relative(repoRoot, scriptPath).replace(/\\/g, '/'),
scriptLoadStatus: 'script-load-pass',
mockDependencyStatus: 'mock-dependency-ready',
mockRuntimeStatus: 'mock-runtime-fail',
failureReason: `runtime_exception:${error.message}`,
durationMs: Date.now() - started,
requestLog,
};
}
}
async function main() {
const matrix = readJson(matrixPath);
const representatives = matrix.representatives;
const records = [];
for (const archetype of Object.keys(representatives).sort()) {
for (const sceneId of representatives[archetype]) {
records.push(await runRepresentative(sceneId, archetype));
}
}
const byStatus = {};
const byArchetype = {};
for (const record of records) {
byStatus[record.mockRuntimeStatus] = (byStatus[record.mockRuntimeStatus] || 0) + 1;
byArchetype[record.archetype] = byArchetype[record.archetype] || {};
byArchetype[record.archetype][record.mockRuntimeStatus] =
(byArchetype[record.archetype][record.mockRuntimeStatus] || 0) + 1;
}
const result = {
runDate: '2026-04-20',
plan: '2026-04-20-scene-skill-102-mock-runtime-harness-implementation-plan.md',
execution: 'mock-runtime-only-no-browser-no-network',
sourceMatrix: 'tests/fixtures/generated_scene/scene_skill_102_mock_runtime_validation_matrix_2026-04-20.json',
summary: {
totalRepresentatives: records.length,
byStatus,
byArchetype,
productionNetworkUsed: false,
realBrowserUsed: false,
generatedSkillsModified: false,
},
representatives,
results: records,
};
writeJson(outputPath, result);
const lines = [];
lines.push('# Scene Skill 102 Mock Runtime Harness Report');
lines.push('');
lines.push('> Date: 2026-04-20');
lines.push('> Plan: `2026-04-20-scene-skill-102-mock-runtime-harness-implementation-plan.md`');
lines.push('');
lines.push('## Scope');
lines.push('');
lines.push('This run executed only representative generated scripts inside a local mock runtime. It did not use a real browser, real network, production credentials, or business systems. It did not modify generated skill packages.');
lines.push('');
lines.push('## Summary');
lines.push('');
lines.push('| Status | Count |');
lines.push('| --- | ---: |');
for (const [status, count] of Object.entries(byStatus).sort()) {
lines.push(`| \`${status}\` | ${count} |`);
}
lines.push('');
lines.push('## By Archetype');
lines.push('');
lines.push('| Archetype | Representatives | Result |');
lines.push('| --- | --- | --- |');
for (const archetype of Object.keys(representatives).sort()) {
const reps = representatives[archetype].join(', ');
const statuses = Object.entries(byArchetype[archetype] || {})
.map(([status, count]) => `${status}: ${count}`)
.join(', ');
lines.push(`| \`${archetype}\` | \`${reps}\` | ${statuses} |`);
}
lines.push('');
lines.push('## Interpretation');
lines.push('');
lines.push('Representative mock execution passing means the generated scripts can load and traverse their main control flow against fake dependencies. It does not mean every one of the 102 scripts was directly executed, and it does not mean production execution passed.');
lines.push('');
lines.push('## Next Step');
lines.push('');
lines.push('If continuing, the next bounded stage should expand mock runtime from representative execution to full 102 direct mock execution, or select a small pseudo-production batch if representative coverage is considered sufficient.');
lines.push('');
fs.writeFileSync(reportPath, `${lines.join('\n')}\n`, 'utf8');
console.log(JSON.stringify(result.summary, null, 2));
}
main().catch((error) => {
console.error(error);
process.exit(1);
});