From de9e05486d979c4287069a0d02a5b25135c0d651 Mon Sep 17 00:00:00 2001 From: edithatogo <15080672+edithatogo@users.noreply.github.com> Date: Fri, 21 Aug 2026 09:21:05 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B9=20Extract=20file=20loading/parsing?= =?UTF-8?q?=20from=20evaluateSchedulingFreezePolicy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎯 What: Extracted the logic for reading, parsing, and validating the freeze policy file into a separate `loadFreezePolicy` helper function. 💡 Why: `evaluateSchedulingFreezePolicy` was large and had mixed concerns (orchestrating the evaluation vs parsing JSON and validating schemas). Extracting the IO and parsing logic simplifies the main function making it easier to read and maintain. ✅ Verification: Ran `npm run verify:agent` which includes linting, formatting, and the full test suite. ✨ Result: `evaluateSchedulingFreezePolicy` is shorter and focused purely on the policy evaluation decision. --- src/policy/scheduling-freeze.ts | 105 ++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/src/policy/scheduling-freeze.ts b/src/policy/scheduling-freeze.ts index 22696fda..084108e7 100644 --- a/src/policy/scheduling-freeze.ts +++ b/src/policy/scheduling-freeze.ts @@ -95,59 +95,18 @@ export async function evaluateSchedulingFreezePolicy(params: { return decision; } - const policyText = await readTextFile(params.freezePolicyPath); - if (policyText === undefined) { - return { - allowed: false, - policyPath: params.freezePolicyPath, - cataloguePath: params.cataloguePath, - reason: `Could not read freeze-policy file: ${params.freezePolicyPath}`, - status: "invalid", - catalogueSummary, - }; - } - - let parsed: unknown; - try { - parsed = JSON.parse(policyText); - } catch { - return { - allowed: false, - policyPath: params.freezePolicyPath, - cataloguePath: params.cataloguePath, - reason: `Freeze-policy file is not valid JSON: ${params.freezePolicyPath}`, - status: "invalid", - catalogueSummary, - }; - } - - const parsedPolicy = PolicyEnvelopeSchema.safeParse(parsed); - if (!parsedPolicy.success) { - const firstIssue = parsedPolicy.error.issues[0]; - const detail = firstIssue?.message ?? "unknown schema issue"; + const loadResult = await loadFreezePolicy(params.freezePolicyPath); + if (!loadResult.success) { return { allowed: false, policyPath: params.freezePolicyPath, cataloguePath: params.cataloguePath, - reason: `Freeze-policy schema validation failed (${params.freezePolicyPath}): ${detail}`, - status: "invalid", + reason: loadResult.reason, + status: loadResult.status, catalogueSummary, }; } - - const policy: SchedulingFreezePolicy = { - schemaVersion: parsedPolicy.data.schemaVersion ?? 1, - status: parsedPolicy.data.status, - active: parsedPolicy.data.active, - reason: parsedPolicy.data.reason, - reasonCode: parsedPolicy.data.reasonCode, - freezeUntil: parsedPolicy.data.freezeUntil, - resumeAt: parsedPolicy.data.resumeAt, - until: parsedPolicy.data.until, - note: parsedPolicy.data.note, - source: parsedPolicy.data.source, - raw: parsed, - }; + const policy = loadResult.policy; const active = isPolicyActive(policy, now); if (!active) { @@ -311,3 +270,57 @@ function validateExternalCatalogue(cataloguePath: string | undefined): Promise< function extractArrayCount(value: unknown): number | undefined { return Array.isArray(value) ? value.length : undefined; } + +async function loadFreezePolicy( + policyPath: string, +): Promise< + | { success: true; policy: SchedulingFreezePolicy } + | { success: false; reason: string; status: "invalid" } +> { + const policyText = await readTextFile(policyPath); + if (policyText === undefined) { + return { + success: false, + reason: `Could not read freeze-policy file: ${policyPath}`, + status: "invalid", + }; + } + + let parsed: unknown; + try { + parsed = JSON.parse(policyText); + } catch { + return { + success: false, + reason: `Freeze-policy file is not valid JSON: ${policyPath}`, + status: "invalid", + }; + } + + const parsedPolicy = PolicyEnvelopeSchema.safeParse(parsed); + if (!parsedPolicy.success) { + const firstIssue = parsedPolicy.error.issues[0]; + const detail = firstIssue?.message ?? "unknown schema issue"; + return { + success: false, + reason: `Freeze-policy schema validation failed (${policyPath}): ${detail}`, + status: "invalid", + }; + } + + const policy: SchedulingFreezePolicy = { + schemaVersion: parsedPolicy.data.schemaVersion ?? 1, + status: parsedPolicy.data.status, + active: parsedPolicy.data.active, + reason: parsedPolicy.data.reason, + reasonCode: parsedPolicy.data.reasonCode, + freezeUntil: parsedPolicy.data.freezeUntil, + resumeAt: parsedPolicy.data.resumeAt, + until: parsedPolicy.data.until, + note: parsedPolicy.data.note, + source: parsedPolicy.data.source, + raw: parsed, + }; + + return { success: true, policy }; +}