140 lines
5.1 KiB
JavaScript
140 lines
5.1 KiB
JavaScript
/**
|
|
* Live verify the SIBLING_HERMES_HOME_DRIFT check.
|
|
*
|
|
* Prerequisites set up by the harness operator before running:
|
|
* 1. WSL has a ~/.hermes/ with at least one drifting field vs the
|
|
* Windows-side. (E.g. CUSTOM_API_KEY in WSL .env, absent on
|
|
* Windows side; or model.api_key in WSL config.yaml, absent on
|
|
* Windows side.)
|
|
* 2. Dev electron started with ENABLE_CDP=1 on this branch (the
|
|
* one that has wsl-detection.ts + config-health.ts with the
|
|
* new check).
|
|
*
|
|
* The probe:
|
|
* 1. Calls getConfigHealth() via IPC.
|
|
* 2. Filters for SIBLING_HERMES_HOME_DRIFT issues.
|
|
* 3. Prints each one's field + direction + autoFixable.
|
|
* 4. Picks an autoFixable one and calls autofixConfigIssue() on it.
|
|
* 5. Re-runs the audit; asserts that the same issue is no longer
|
|
* flagged (i.e. the auto-fix actually copied the value across).
|
|
*/
|
|
const { attach } = require("./e2e-attach");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const os = require("os");
|
|
|
|
const WIN_ENV = path.join(os.homedir(), "AppData", "Local", "hermes", ".env");
|
|
const WIN_ENV_BAK = WIN_ENV + ".wsl-drift-test-bk";
|
|
|
|
(async () => {
|
|
// Backup Windows .env so we can restore after the auto-fix test
|
|
if (fs.existsSync(WIN_ENV)) fs.copyFileSync(WIN_ENV, WIN_ENV_BAK);
|
|
|
|
try {
|
|
const { browser, page } = await attach();
|
|
|
|
// ── A. Run audit, look for drift issues ─────────────────────
|
|
const report = await page.evaluate(async () => {
|
|
return await window.hermesAPI.getConfigHealth();
|
|
});
|
|
const drifts = (report.issues || []).filter(
|
|
(i) => i.code === "SIBLING_HERMES_HOME_DRIFT",
|
|
);
|
|
console.log(
|
|
`[A] config-health report — ${report.issues.length} total issues, ${drifts.length} drift issues`,
|
|
);
|
|
for (const d of drifts) {
|
|
console.log(
|
|
` - field=${d.context?.field} direction=${d.context?.direction} severity=${d.severity} autoFixable=${d.autoFixable}`,
|
|
);
|
|
}
|
|
|
|
if (drifts.length === 0) {
|
|
console.log();
|
|
console.log(
|
|
"[VERDICT] 🔴 No drift detected. Either the WSL ~/.hermes/ doesn't exist, doesn't differ from Windows, OR the check isn't running.",
|
|
);
|
|
await browser.close();
|
|
process.exit(2);
|
|
}
|
|
|
|
// ── B. Auto-fix the first autoFixable drift ────────────────
|
|
const target = drifts.find((d) => d.autoFixable);
|
|
if (!target) {
|
|
console.log();
|
|
console.log(
|
|
"[VERDICT] ⚠️ Drift detected but none are autoFixable. Check the contexts above.",
|
|
);
|
|
await browser.close();
|
|
process.exit(3);
|
|
}
|
|
|
|
console.log();
|
|
console.log(`[B] applying auto-fix for ${target.context?.field}...`);
|
|
const fixResult = await page.evaluate(
|
|
async (issue) => {
|
|
return await window.hermesAPI.autofixConfigIssue(
|
|
issue.code,
|
|
undefined,
|
|
issue.context,
|
|
);
|
|
},
|
|
{ code: target.code, context: target.context },
|
|
);
|
|
console.log(`[B] auto-fix result:`, JSON.stringify(fixResult));
|
|
|
|
// ── C. Confirm Windows-side .env now has the value ──────────
|
|
const winEnvAfter = fs.readFileSync(WIN_ENV, "utf-8");
|
|
const fieldName = target.context?.field;
|
|
const valueInEnv = new RegExp(
|
|
`^${fieldName}=(.+)$`,
|
|
"m",
|
|
).exec(winEnvAfter);
|
|
console.log(
|
|
`[C] Windows-side .env now has ${fieldName}: ${valueInEnv ? "✓ value present" : "✗ still missing"}`,
|
|
);
|
|
|
|
// ── D. Re-run audit — the same drift should be gone ────────
|
|
const reportAfter = await page.evaluate(async () => {
|
|
return await window.hermesAPI.rerunConfigHealth();
|
|
});
|
|
const sameDriftStillPresent = (reportAfter.issues || []).some(
|
|
(i) =>
|
|
i.code === "SIBLING_HERMES_HOME_DRIFT" &&
|
|
i.context?.field === fieldName &&
|
|
i.context?.direction === "wsl-to-windows",
|
|
);
|
|
console.log(
|
|
`[D] re-run audit: same drift still present? ${sameDriftStillPresent ? "YES (BAD)" : "no (good)"}`,
|
|
);
|
|
|
|
await browser.close();
|
|
|
|
console.log();
|
|
const aOk = drifts.length > 0;
|
|
const bOk = fixResult.ok === true;
|
|
const cOk = !!valueInEnv;
|
|
const dOk = !sameDriftStillPresent;
|
|
console.log(`[VERDICT A] ${aOk ? "✅" : "🔴"} drift issues surfaced (${drifts.length})`);
|
|
console.log(`[VERDICT B] ${bOk ? "✅" : "🔴"} auto-fix returned ok:true`);
|
|
console.log(`[VERDICT C] ${cOk ? "✅" : "🔴"} field landed in Windows-side .env`);
|
|
console.log(`[VERDICT D] ${dOk ? "✅" : "🔴"} drift cleared from next audit`);
|
|
} finally {
|
|
// Restore .env so the live test doesn't pollute the user's setup
|
|
if (fs.existsSync(WIN_ENV_BAK)) {
|
|
fs.copyFileSync(WIN_ENV_BAK, WIN_ENV);
|
|
fs.unlinkSync(WIN_ENV_BAK);
|
|
}
|
|
console.log("[teardown] Windows-side .env restored");
|
|
}
|
|
})().catch((e) => {
|
|
try {
|
|
if (fs.existsSync(WIN_ENV_BAK)) {
|
|
fs.copyFileSync(WIN_ENV_BAK, WIN_ENV);
|
|
fs.unlinkSync(WIN_ENV_BAK);
|
|
}
|
|
} catch {}
|
|
console.error("FAILED:", e.stack || e.message || e);
|
|
process.exit(1);
|
|
});
|