mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 22:58:42 -10:00
fix(slice-21 FR-5c test determinism): epoch config mtime + simulated-uptime discriminator (OPR.0.3.2.21.FR-5)
Forward-fix on guard BLOCKING qitem-20260602042720-e27ec982. Test-determinism issue; product code unchanged. Where it bit: - workspace-routes.test.ts /doctor "healthy" fixture set the test config mtime to `Date.now() - 60_000`. - The route handler computes daemon start as `Date.now() - process.uptime() * 1000`. - When the Vitest worker has been alive longer than 60 seconds (common in full-repo runs or worker re-use), daemon start is OLDER than the config mtime → check #5 flips to warn → summary becomes {ok:6, warn:1, fail:0} → test fails for reasons unrelated to product code. Fix: - Set the route-test config mtime to `new Date(0)` (epoch 1970-01-01) so the route handler's process.uptime()-derived daemon start is GUARANTEED newer than the config mtime regardless of worker uptime. - Added a `daemon_reload_needed` deterministic comment hint at the fixture site so the next contributor sees why epoch was chosen over a relative offset. Required discriminator added (guard's recipe): - New test "POST /doctor stays healthy under simulated long worker uptime" patches `process.uptime` via Object.defineProperty to return 10 years in seconds, hits the healthy fixture, and asserts summary stays {ok:7, warn:0, fail:0} + check #5 status stays "ok". Restores the original process.uptime in a finally block so subsequent tests aren't poisoned. - Mutation target: if the route-test config mtime were set back to `Date.now() - 60_000`, this test would fail under the patched uptime regardless of actual worker timing. Why this matters beyond the immediate fix: The orchestrator-level tests in workspace-doctor.test.ts pass daemonStartTime explicitly (`new Date(Date.now() - 5_000)`) rather than relying on process.uptime(). Those are deterministic. The route test is the only place where process.uptime() drives daemonStartTime; the fixture's mtime ANCHOR therefore needs to be absolute-old, not relative. Verification: - packages/daemon tsc EXIT=0 - packages/daemon workspace-doctor.test.ts + workspace-routes.test.ts: 44/44 PASS (43 + 1 new uptime-determinism discriminator) - Pre-commit staged-diff grep for forbidden-attribution pattern: ZERO matches - Pre-commit FULL-CONTENT grep on every touched file (touch-event- scope rule): ZERO matches - Commit body verification grep clean per banked discipline - git diff --cached --stat: 1 file (+48 / -2) Branch: slice-21-fr-5-rig-workspace-doctor off LOCAL maine154a5ce. Chain:a4b4b67d(FR-5a, CLEAR) →e5d61983(FR-5b, BLOCKED) →bc5ec05f(FR-5b fix-up, CLEAR) →6b21ce3c(FR-5c, BLOCKED on test determinism; product code untouched in this fix-up) → this commit (FR-5c test determinism fix-up). LOCAL only, NO push. Files: - packages/daemon/test/workspace-routes.test.ts (+48 / -2)
This commit is contained in:
1 parent
6b21ce3c86
commit
784222d30d
1 file changed
+48
-2
@@ -100,8 +100,14 @@ describe("workspace doctor HTTP route (slice-21 FR-5)", () => {
|
||||
// shape (value/source/defaultValue).
|
||||
configPath = path.join(doctorDir, ".test-config.json");
|
||||
fs.writeFileSync(configPath, "{}");
|
||||
const oldMtime = new Date(Date.now() - 60_000);
|
||||
fs.utimesSync(configPath, oldMtime, oldMtime);
|
||||
// Config-file mtime is forced to epoch (1970-01-01) so the route's
|
||||
// process.uptime()-derived daemon start is GUARANTEED newer than
|
||||
// the config mtime regardless of Vitest worker uptime. A relative
|
||||
// offset like Date.now() - 60_000 flips check #5 to warn when the
|
||||
// worker has been alive longer than the offset (banked guard
|
||||
// BLOCKER on FR-5c qitem-20260602042720-e27ec982).
|
||||
const epochMtime = new Date(0);
|
||||
fs.utimesSync(configPath, epochMtime, epochMtime);
|
||||
|
||||
const stubStore = {
|
||||
configPath,
|
||||
@@ -205,4 +211,44 @@ describe("workspace doctor HTTP route (slice-21 FR-5)", () => {
|
||||
const body = await res.json() as { workspaceRoot: string };
|
||||
expect(body.workspaceRoot).toBe(doctorDir);
|
||||
});
|
||||
|
||||
// GUARD BLOCKER-1 (qitem-20260602042720-e27ec982) determinism
|
||||
// discriminator: even under a long process.uptime() (simulating a
|
||||
// long-running Vitest worker), the healthy fixture must still
|
||||
// return summary {ok:7, warn:0, fail:0}. A regression where the
|
||||
// route-test config mtime was set relative to Date.now() instead
|
||||
// of an absolute-old epoch would flip check #5 to warn under any
|
||||
// worker uptime greater than the relative offset.
|
||||
it("POST /doctor stays healthy under simulated long worker uptime", async () => {
|
||||
const origUptime = process.uptime;
|
||||
// Force daemon start to a far past time (≈10 years ago at the
|
||||
// current Date.now()); the epoch-1970 config mtime must still be
|
||||
// older.
|
||||
Object.defineProperty(process, "uptime", {
|
||||
value: () => 60 * 60 * 24 * 365 * 10,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
try {
|
||||
const res = await doctorApp.request("/api/workspace/doctor", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
expect(res.status).toBe(200);
|
||||
const body = await res.json() as {
|
||||
summary: { ok: number; warn: number; fail: number };
|
||||
checks: Array<{ check: string; status: string }>;
|
||||
};
|
||||
expect(body.summary).toEqual({ ok: 7, warn: 0, fail: 0 });
|
||||
const reload = body.checks.find((c) => c.check === "daemon_reload_needed");
|
||||
expect(reload?.status).toBe("ok");
|
||||
} finally {
|
||||
Object.defineProperty(process, "uptime", {
|
||||
value: origUptime,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user