|
|
/**
|
|
|
* Widget 地址 commit 稳定性探针(单测 + 可选实网循环)
|
|
|
*
|
|
|
* 默认:跑金样本/定位器/策略相关单测并输出摘要
|
|
|
* 实网:需 dev:start + RPA_MOCK_MODE=false,设置 PROBE_WIDGET_LOOPS=5
|
|
|
*
|
|
|
* PowerShell:
|
|
|
* npm run probe:widget-address
|
|
|
* $env:PROBE_WIDGET_LOOPS="3"; npm run probe:widget-address
|
|
|
*/
|
|
|
import { spawnSync } from "node:child_process";
|
|
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
|
import { join } from "node:path";
|
|
|
import {
|
|
|
findGoldStandardTargets,
|
|
|
loadAllGoldStandardTargets,
|
|
|
} from "@/workers/rpa/gold-standard-targets";
|
|
|
import { loadReconVerdict } from "@/workers/rpa/fix-place/recon-helpers";
|
|
|
|
|
|
const loops = Number(process.env.PROBE_WIDGET_LOOPS ?? "0");
|
|
|
|
|
|
function runUnitSuite(): boolean {
|
|
|
const result = spawnSync(
|
|
|
"npx",
|
|
|
[
|
|
|
"vitest",
|
|
|
"run",
|
|
|
"__tests__/workers/rpa/gold-standard-targets.test.ts",
|
|
|
"__tests__/workers/rpa/mothership-styled-locator.test.ts",
|
|
|
"__tests__/workers/rpa/address-adapter-diagnostics.test.ts",
|
|
|
"__tests__/workers/rpa/place-commit-strategy.test.ts",
|
|
|
"__tests__/workers/rpa/mothership-styled-suggestion-click.test.ts",
|
|
|
"__tests__/workers/rpa/axel-selection-bridge.test.ts",
|
|
|
],
|
|
|
{ stdio: "inherit", shell: true },
|
|
|
);
|
|
|
return result.status === 0;
|
|
|
}
|
|
|
|
|
|
function summarizeGoldCoverage(): void {
|
|
|
const targets = loadAllGoldStandardTargets();
|
|
|
const verdict = loadReconVerdict();
|
|
|
console.log("\n[widget-address-probe] 金样本条目:", targets.length);
|
|
|
console.log("[widget-address-probe] recon verdict:", verdict.verdict);
|
|
|
console.log(
|
|
|
"[widget-address-probe] googleMapsLoaded:",
|
|
|
verdict.googleMapsLoaded,
|
|
|
"reactFiberKey:",
|
|
|
verdict.reactFiberKey,
|
|
|
);
|
|
|
|
|
|
const sample = findGoldStandardTargets(
|
|
|
"La Concha Key West, Autograph Collection, Duval Street, Key West, Florida, USA",
|
|
|
{ street: "Duval Street", city: "Key West", state: "FL", zip: "" },
|
|
|
"pickup",
|
|
|
40,
|
|
|
);
|
|
|
console.log(
|
|
|
"[widget-address-probe] Key West 金样本匹配:",
|
|
|
sample.length,
|
|
|
sample[0]?.textPreview.slice(0, 48) ?? "—",
|
|
|
);
|
|
|
}
|
|
|
|
|
|
function runRealLoop(): { pass: number; fail: number } {
|
|
|
let pass = 0;
|
|
|
let fail = 0;
|
|
|
for (let i = 0; i < loops; i += 1) {
|
|
|
console.log(`\n[widget-address-probe] prove:rpa-chain loop ${i + 1}/${loops}`);
|
|
|
const result = spawnSync("npm", ["run", "prove:rpa-chain"], {
|
|
|
stdio: "inherit",
|
|
|
shell: true,
|
|
|
env: {
|
|
|
...process.env,
|
|
|
RPA_MOCK_MODE: "false",
|
|
|
RPA_ADDRESS_MODE: "real",
|
|
|
},
|
|
|
});
|
|
|
if (result.status === 0) {
|
|
|
pass += 1;
|
|
|
} else {
|
|
|
fail += 1;
|
|
|
}
|
|
|
}
|
|
|
return { pass, fail };
|
|
|
}
|
|
|
|
|
|
function readLatestChainProof(): { verdict?: string; placeHits?: number } {
|
|
|
const dir = join(process.cwd(), ".rpa");
|
|
|
if (!existsSync(dir)) {
|
|
|
return {};
|
|
|
}
|
|
|
const files = readdirSync(dir)
|
|
|
.filter((name: string) => name.startsWith("chain-proof-") && name.endsWith(".json"))
|
|
|
.sort()
|
|
|
.reverse();
|
|
|
if (!files.length) {
|
|
|
return {};
|
|
|
}
|
|
|
const raw = JSON.parse(readFileSync(join(dir, files[0]!), "utf8")) as {
|
|
|
verdict?: string;
|
|
|
workerLogSnippet?: string;
|
|
|
};
|
|
|
const snippet = raw.workerLogSnippet ?? "";
|
|
|
const placeHits = (snippet.match(/axel\/location\/place/g) ?? []).length;
|
|
|
return { verdict: raw.verdict, placeHits };
|
|
|
}
|
|
|
|
|
|
async function main(): Promise<void> {
|
|
|
console.log("=== Widget Address Commit Stability Probe ===\n");
|
|
|
summarizeGoldCoverage();
|
|
|
|
|
|
const unitOk = runUnitSuite();
|
|
|
if (!unitOk) {
|
|
|
console.error("\n[widget-address-probe] 单测失败");
|
|
|
process.exit(1);
|
|
|
}
|
|
|
|
|
|
if (loops > 0) {
|
|
|
const { pass, fail } = runRealLoop();
|
|
|
const rate = loops > 0 ? (pass / loops) * 100 : 0;
|
|
|
const latest = readLatestChainProof();
|
|
|
console.log("\n[widget-address-probe] 实网循环结果:", {
|
|
|
loops,
|
|
|
pass,
|
|
|
fail,
|
|
|
successRate: `${rate.toFixed(1)}%`,
|
|
|
latestVerdict: latest.verdict,
|
|
|
latestLogPlaceHits: latest.placeHits,
|
|
|
});
|
|
|
if (rate < 95) {
|
|
|
console.error("[widget-address-probe] 成功率低于 95% 目标");
|
|
|
process.exit(1);
|
|
|
}
|
|
|
} else {
|
|
|
console.log(
|
|
|
"\n[widget-address-probe] 单测通过。实网循环请设置 PROBE_WIDGET_LOOPS=3~10",
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void main();
|