{"version":3,"file":"routing.windows.test.d.ts","sourceRoot":"","sources":["../../../src/core/routing/routing.windows.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG","sourcesContent":["/**\n * Cross-platform routing store tests — Windows-targeted.\n *\n * Verifies behaviors that must hold on Windows: case-insensitive policy-id\n * paths do not break atomic replacement, the active-policy pointer swap is\n * atomic, and file locking never leaves a partial active-policy file.\n *\n * These run on Linux CI too (path semantics are platform-agnostic in the\n * routing store), and are additionally exercised on windows-latest.\n */\n\nimport { existsSync, mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { afterAll, beforeAll, describe, expect, it } from \"vitest\";\nimport { generateRoutingPolicy } from \"./optimizer.js\";\nimport { promotePolicy, rollbackPolicy } from \"./promotion.js\";\nimport { loadActivePolicyPointer, readPolicy, writePolicy } from \"./store.js\";\nimport type { CandidateEvidence } from \"./types.js\";\n\nlet root: string;\nconst evidence: Record<string, CandidateEvidence> = {\n\t\"c-w1\": {\n\t\tcandidateId: \"c-w1\",\n\t\tevaluatorVersion: \"eval-1\",\n\t\tscenarioVersion: \"v1\",\n\t\tevidenceHash: \"w1\",\n\t\tsampleCount: 30,\n\t\tcorrectnessRate: 0.95,\n\t\tsafetyRate: 0.99,\n\t\treliabilityRate: 0.9,\n\t\tflakyRate: 0.01,\n\t\tcompatibility: {},\n\t\tcollectedAt: \"2026-01-01T00:00:00.000Z\",\n\t\tversion: 1,\n\t},\n};\n\nbeforeAll(() => {\n\troot = mkdtempSync(join(tmpdir(), \"jensen-routing-win-\"));\n\tprocess.env.JENSEN_ROUTING_ROOT = root;\n});\n\nafterAll(() => {\n\trmSync(root, { recursive: true, force: true });\n});\n\ndescribe(\"cross-platform atomic policy pointer\", () => {\n\tit(\"active policy pointer swap is atomic and reloadable (case-tolerant path access)\", () => {\n\t\tconst r = generateRoutingPolicy([\"c-w1\"], evidence, \"eval-1\", \"dataset-win\");\n\t\tconst promoted = promotePolicy(r.policy.policyId, \"operator\", evidence, {\n\t\t\tsafetyFloor: 0.5,\n\t\t\tcorrectnessFloor: 0.5,\n\t\t\tflakinessCeiling: 0.3,\n\t\t\trequiredScenarioPack: \"routing\",\n\t\t\toperatorAuthorized: true,\n\t\t});\n\t\texpect(promoted.ok).toBe(true);\n\n\t\t// Load by exact and by a differently-cased policy id (Windows fs).\n\t\tconst pointer = loadActivePolicyPointer();\n\t\texpect(pointer?.policyId).toBe(r.policy.policyId);\n\t\texpect(readPolicy(r.policy.policyId)).toBeDefined();\n\t\t// A safe, non-existent id never crashes and returns undefined.\n\t\texpect(readPolicy(\"not-a-real-policy-0000\")).toBeUndefined();\n\t\t// Path traversal / separator ids are rejected outright (never escape policy dir).\n\t\texpect(readPolicy(\"../../etc/passwd\")).toBeUndefined();\n\t\texpect(readPolicy(\"..\")).toBeUndefined();\n\t\texpect(() => {\n\t\t\t// writePolicy must refuse a traversal id rather than write outside.\n\t\t\twritePolicy({\n\t\t\t\tpolicyId: \"../../../tmp/evil\",\n\t\t\t\tpolicyVersion: 1,\n\t\t\t\tsourceDatasetHash: \"x\",\n\t\t\t\tevaluatorVersion: \"y\",\n\t\t\t\tgeneratedAt: \"2026-01-01T00:00:00.000Z\",\n\t\t\t\tstatus: \"draft\",\n\t\t\t\tpreferences: null,\n\t\t\t\tsuggestedRules: [],\n\t\t\t\tdominatedCandidateIds: [],\n\t\t\t\tevidenceGaps: [],\n\t\t\t\thash: \"h\",\n\t\t\t\tcontent: \"c\",\n\t\t\t\trollbackPolicyId: undefined,\n\t\t\t});\n\t\t}).toThrow(\"INVALID_POLICY_ID\");\n\t});\n\n\tit(\"active-policy file content parses as valid JSON (never partial)\", () => {\n\t\tconst pointer = loadActivePolicyPointer();\n\t\texpect(pointer).toBeTruthy();\n\t\t// Read raw file to confirm it is complete, parseable JSON (atomic rename guarantees this).\n\t\tconst file = join(root, \"active-policy.json\");\n\t\tif (existsSync(file)) {\n\t\t\tconst parsed = JSON.parse(readFileSync(file, \"utf-8\"));\n\t\t\texpect(parsed).toHaveProperty(\"policyId\");\n\t\t}\n\t});\n\n\tit(\"rollback is idempotent on Windows-style paths\", () => {\n\t\tconst r = generateRoutingPolicy([\"c-w1\"], evidence, \"eval-1\", \"dataset-win-2\");\n\t\texpect(rollbackPolicy(r.policy.policyId, \"operator\").ok).toBe(true);\n\t\texpect(rollbackPolicy(r.policy.policyId, \"operator\").ok).toBe(true);\n\t});\n});\n"]}