/** * 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 { 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();