reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
function parseArgs(argv) {
const args = {
caseDir: '',
requireLive: false,
tlsClient: '',
beforeRealRequest: false,
strictP2: false,
json: false,
markdown: false,
help: false,
};
for (let i = 2; i < argv.length; i++) {
const arg = argv[i];
if (arg === '--case-dir' || arg === '--case' || arg === '-d') args.caseDir = argv[++i] || '';
else if (arg === '--require-live') args.requireLive = true;
else if (arg === '--tls-client') args.tlsClient = argv[++i] || '';
else if (arg === '--before-real-request') args.beforeRealRequest = true;
else if (arg === '--strict-p2') args.strictP2 = true;
else if (arg === '--json') args.json = true;
else if (arg === '--markdown') args.markdown = true;
else if (arg === '--help' || arg === '-h') args.help = true;
else throw new Error(`未知参数:${arg}`);
}
if (!args.json && !args.markdown) args.markdown = true;
return args;
}
function usage() {
return `用法:
node scripts/check_environment_closure.js --case-dir case --before-real-request --markdown
node scripts/check_environment_closure.js --case-dir case --before-real-request --require-live --tls-client curl_cffi --json
说明:统一执行 Trace-runtime、WebAPI 行为、对象形状和 XHR/fetch 请求语义闭环。真实请求前必须使用 --before-real-request,任一组件失败都会阻断。`;
}
function exists(file) {
try { return fs.existsSync(file); } catch { return false; }
}
function stat(file) {
try { return fs.statSync(file); } catch { return null; }
}
function walk(root, out = []) {
if (!exists(root)) return out;
const st = stat(root);
if (!st) return out;
if (st.isFile()) {
out.push(root);
return out;
}
if (!st.isDirectory()) return out;
for (const name of fs.readdirSync(root)) walk(path.join(root, name), out);
return out;
}
function hasTraceEvidence(caseDir) {
const fixed = [
path.join(caseDir, 'ruyi-trace'),
path.join(caseDir, 'tmp', 'env-trace.jsonl'),
path.join(caseDir, 'tmp', 'missing-env.json'),
path.join(caseDir, 'notes', 'trace-api-inventory.json'),
path.join(caseDir, 'notes', 'trace-runtime-contract.json'),
];
if (fixed.some(exists)) return true;
return walk(caseDir).some(file => {
const relative = (path.relative(caseDir, file) || '.').replace(/\\/g, '/');
if (/(^|\/)(node_modules|dist|build|coverage|vendor)(\/|$)/i.test(relative)) return false;
return /(?:^|\/)(?:trace|ruyitrace|missing-env)[^/]*\.(?:json|jsonl|ndjson|log|txt)$/i.test(relative);
});
}
function evidenceFiles(caseDir) {
const roots = ['阶段报告', 'notes', 'tmp', 'fixtures', 'ruyi-trace', 'result'];
const files = [];
for (const root of roots) {
for (const file of walk(path.join(caseDir, root))) {
const relative = (path.relative(caseDir, file) || '.').replace(/\\/g, '/');
if (/(^|\/)(node_modules|dist|build|coverage|vendor|third_party|third-party)(\/|$)/i.test(relative)) continue;
if (!/\.(?:md|txt|log|json|jsonl|ndjson|js|mjs|cjs|ts|py|html)$/i.test(file)) continue;
files.push(file);
if (files.length >= 2000) return files;
}
}
return files;
}
function scanCaseEvidence(caseDir) {
const resultDir = path.join(caseDir, 'result');
let hasBrowserEnv = false;
let hasNetworkImpl = false;
let networkEvidence = false;
let webapiEvidence = false;
let realmLifecycleEvidence = false;
let domCrudEvidence = false;
let objectShapeEvidence = false;
const hits = {
network: [],
webapi: [],
realmLifecycle: [],
domCrud: [],
objectShape: [],
};
const recordHit = (type, file) => {
const relative = (path.relative(caseDir, file) || '.').replace(/\\/g, '/');
if (hits[type].length < 8 && !hits[type].includes(relative)) hits[type].push(relative);
};
for (const file of evidenceFiles(caseDir)) {
let text = '';
try { text = fs.readFileSync(file, 'utf8').slice(0, 300000); } catch { continue; }
const relative = (path.relative(caseDir, file) || '.').replace(/\\/g, '/');
const inResult = relative.startsWith('result/');
if (/\b(XMLHttpRequest|fetch|sendBeacon|Request|Response|Headers)\b|network-transcript|xhr-fetch/i.test(text)
|| /(?:browser|node)-network-transcript\.(?:json|ndjson)$/i.test(relative)) {
networkEvidence = true;
recordHit('network', file);
if (inResult && /\.(?:js|mjs|cjs|ts|py)$/i.test(file)) hasNetworkImpl = true;
}
if (/\b(window|document|navigator|EventTarget|Storage|Performance|Element|Node)\b/.test(text)
|| /(?:browser|node)-env-detection-(?:baseline|audit)\.json$/i.test(relative)) {
webapiEvidence = true;
recordHit('webapi', file);
if (inResult && /\.(?:js|mjs|cjs|ts|py)$/i.test(file)) hasBrowserEnv = true;
}
if (/iframe|contentWindow|contentDocument|defaultView|\bWorker\b|WorkerGlobalScope|MessageChannel|MessagePort|postMessage|terminate/i.test(text)) {
realmLifecycleEvidence = true;
webapiEvidence = true;
recordHit('realmLifecycle', file);
recordHit('webapi', file);
}
if (/appendChild|removeChild|insertBefore|replaceChild|replaceChildren|cloneNode|importNode|adoptNode|innerHTML|DOMParser|querySelector|MutationObserver|childNodes|getElementsBy/i.test(text)) {
domCrudEvidence = true;
webapiEvidence = true;
recordHit('domCrud', file);
recordHit('webapi', file);
}
if (/Object\.keys|Object\.getOwnPropertyNames|Object\.getOwnPropertyDescriptor|Reflect\.ownKeys|prototypeChain|ownKeys|private-state-leakage/i.test(text)) {
objectShapeEvidence = true;
recordHit('objectShape', file);
}
}
for (const file of walk(resultDir)) {
if (!/\.(js|mjs|cjs|ts|py)$/i.test(file)) continue;
const relative = (path.relative(resultDir, file) || '.').replace(/\\/g, '/');
if (/(^|\/)(node_modules|dist|build|coverage)(\/|$)/i.test(relative)) continue;
let text = '';
try { text = fs.readFileSync(file, 'utf8'); } catch { continue; }
if (/(^|\/)src\/(?:env|node-runtime\/env)\//i.test(relative)
|| /\b(window|document|navigator|EventTarget|Storage|Performance|Element|Node)\b/.test(text)) {
hasBrowserEnv = true;
}
if (/\b(XMLHttpRequest|fetch|sendBeacon|Request|Response|Headers)\b/.test(text)) hasNetworkImpl = true;
}
return {
resultDir,
hasBrowserEnv,
hasNetworkImpl,
networkEvidence,
webapiEvidence,
realmLifecycleEvidence,
domCrudEvidence,
objectShapeEvidence,
hits,
};
}
function collectMetrics(value, out = {}, depth = 0) {
if (!value || typeof value !== 'object' || depth > 6) return out;
const keys = new Set([
'baselineId',
'traceSourceHash',
'contractHash',
'runtimeSourceHash',
'blockingMismatches',
'mismatched',
'networkMismatches',
'extraNodeRequests',
'extraNodeEvents',
'networkAttempts',
'sameSessionVerified',
'roundTripCount',
]);
if (Array.isArray(value)) {
for (const item of value.slice(0, 50)) collectMetrics(item, out, depth + 1);
return out;
}
for (const [key, item] of Object.entries(value)) {
if (keys.has(key) && item !== '' && item !== null && typeof item !== 'undefined') {
if (!out[key]) out[key] = [];
const encoded = typeof item === 'object' ? JSON.stringify(item) : String(item);
if (!out[key].includes(encoded) && out[key].length < 10) out[key].push(encoded);
}
if (item && typeof item === 'object') collectMetrics(item, out, depth + 1);
}
return out;
}
function summarizeComponentData(data) {
if (!data || typeof data !== 'object') return data;
return {
schemaVersion: data.schemaVersion || '',
clean: data.clean,
passed: data.passed,
metrics: collectMetrics(data),
summary: data.summary && typeof data.summary === 'object' ? data.summary : undefined,
problems: Array.isArray(data.problems) ? data.problems.slice(0, 20) : [],
warnings: Array.isArray(data.warnings) ? data.warnings.slice(0, 10) : [],
};
}
function runJson(scriptDir, script, args) {
const command = [path.join(scriptDir, script), ...args, '--json'];
const ret = spawnSync(process.execPath, command, {
encoding: 'utf8',
windowsHide: true,
timeout: 180000,
});
let rawData = null;
try { rawData = JSON.parse(String(ret.stdout || '').trim()); } catch {}
return {
script,
exitCode: ret.status,
clean: ret.status === 0 && rawData && rawData.clean !== false && rawData.passed !== false,
data: summarizeComponentData(rawData),
stderr: String(ret.stderr || '').trim().slice(0, 2000),
stdoutPreview: rawData ? '' : String(ret.stdout || '').trim().slice(0, 2000),
};
}
function check(args) {
const caseDir = path.resolve(args.caseDir || '.');
const scriptDir = __dirname;
const signals = scanCaseEvidence(caseDir);
const trace = hasTraceEvidence(caseDir);
const components = [];
if (trace) {
const traceArgs = ['--case-dir', caseDir, '--require-runtime-closure'];
if (args.beforeRealRequest) traceArgs.push('--require-stage-audit');
components.push(runJson(scriptDir, 'check_trace_api_coverage.js', traceArgs));
}
if (signals.hasBrowserEnv
|| signals.webapiEvidence
|| signals.objectShapeEvidence
|| trace
|| args.beforeRealRequest) {
components.push(runJson(scriptDir, 'check_object_shape_audit.js', ['--case-dir', caseDir, '--require']));
components.push(runJson(scriptDir, 'check_webapi_env_detection_matrix.js', ['--case-dir', caseDir, '--require']));
}
if (signals.hasBrowserEnv || signals.hasNetworkImpl || signals.webapiEvidence || args.beforeRealRequest) {
components.push(runJson(scriptDir, 'check_code_quality.js', ['--case-dir', caseDir]));
}
if (signals.hasBrowserEnv || signals.hasNetworkImpl || signals.webapiEvidence) {
components.push(runJson(scriptDir, 'check_webapi_addon_coverage.js', ['--case-dir', caseDir, '--warnings-as-errors']));
}
if (signals.hasNetworkImpl || signals.networkEvidence || args.requireLive) {
const semanticsArgs = ['--case-dir', caseDir, '--require', '--require-no-send', '--out', path.join(caseDir, 'tmp', 'xhr-fetch-semantics-audit.json')];
components.push(runJson(scriptDir, 'check_xhr_fetch_semantics.js', semanticsArgs));
const bridgeArgs = ['--case-dir', caseDir];
if (args.requireLive || args.beforeRealRequest) bridgeArgs.push('--require-live');
if (args.tlsClient) bridgeArgs.push('--tls-client', args.tlsClient);
components.push(runJson(scriptDir, 'check_xhr_fetch_session_bridge.js', bridgeArgs));
}
const problems = [];
for (const component of components) {
if (!component.clean) {
const detail = component.data && Array.isArray(component.data.problems)
? component.data.problems.slice(0, 20).join(';')
: (component.stderr || component.stdoutPreview || `exit=${component.exitCode}`);
problems.push(`${component.script} 未通过:${detail}`);
}
}
if (args.beforeRealRequest && !components.length) problems.push('真实请求前没有触发任何环境闭环组件,说明 case 结构或检测信号缺失');
return {
schemaVersion: 'environment-closure/v3',
generatedBy: 'check_environment_closure.js',
caseDir,
clean: problems.length === 0,
beforeRealRequest: args.beforeRealRequest,
requireLive: args.requireLive,
tlsClient: args.tlsClient || '',
signals: {
trace,
browserEnv: signals.hasBrowserEnv,
networkImpl: signals.hasNetworkImpl,
networkEvidence: signals.networkEvidence,
webapiEvidence: signals.webapiEvidence,
realmLifecycleEvidence: signals.realmLifecycleEvidence,
domCrudEvidence: signals.domCrudEvidence,
objectShapeEvidence: signals.objectShapeEvidence,
evidenceFiles: signals.hits,
},
components,
problems,
};
}
function renderMarkdown(result) {
const lines = [
'# 补环境闭环总门禁',
'',
`- case:${result.caseDir}`,
`- 真实请求前模式:${result.beforeRealRequest ? '是' : '否'}`,
`- 要求 live session:${result.requireLive ? '是' : '否'}`,
`- TLS 客户端:${result.tlsClient || '未指定'}`,
`- 是否通过:${result.clean ? '是' : '否'}`,
'',
'## 检测信号',
`- Trace:${result.signals.trace ? '是' : '否'}`,
`- 浏览器环境实现:${result.signals.browserEnv ? '是' : '否'}`,
`- XHR/fetch 实现:${result.signals.networkImpl ? '是' : '否'}`,
`- 网络证据:${result.signals.networkEvidence ? '是' : '否'}`,
`- Realm / 消息生命周期证据:${result.signals.realmLifecycleEvidence ? '是' : '否'}`,
`- DOM CRUD 证据:${result.signals.domCrudEvidence ? '是' : '否'}`,
'',
'## 组件',
];
if (!result.components.length) lines.push('- 无');
for (const component of result.components) {
lines.push(`- ${component.script}:${component.clean ? '通过' : '失败'},exit=${component.exitCode}`);
const metrics = component.data && component.data.metrics ? component.data.metrics : {};
const metricText = Object.entries(metrics)
.map(([key, values]) => `${key}=${values.join('|')}`)
.join(';');
if (metricText) lines.push(` ${metricText}`);
}
if (result.problems.length) {
lines.push('', '## 阻断问题');
for (const problem of result.problems) lines.push(`- ${problem}`);
}
return `${lines.join('\n')}\n`;
}
if (require.main === module) {
try {
const args = parseArgs(process.argv);
if (args.help) {
console.log(usage());
process.exit(0);
}
const result = check(args);
if (args.json) console.log(JSON.stringify(result, null, 2));
if (args.markdown) process.stdout.write(renderMarkdown(result));
process.exit(result.clean ? 0 : 1);
} catch (err) {
console.error(err.message || String(err));
console.error(usage());
process.exit(1);
}
}
module.exports = { check };