{"repo": "alanho2025/kiwi-ai-interview-agent", "files": {"backend/src/services/agenticSafeguards/safeguardShared.js": {"d7d497976be123e6652b2ff2a3efe17d833b2bac": {"t": 1785745552.3772738, "n": 3052, "h": "cbaf1878ecc72023", "c": "/**\n * File responsibility: Shared helpers for controlled agentic safeguards.\n * Main responsibilities:\n * - Keep safeguard verdict names stable across JD parsing and CV-JD matching.\n * - Centralise feature flags so mock tests can opt into review while real flows always run safeguards.\n */\n\nexport const SAFEGUARD_VERDICTS = {\n PASS: 'pass',\n REVISE: 'revise',\n REJECT: 'reject',\n};\n\nexport const isMockAiMode = () => process.env.AI_TEST_MODE === 'mock';\nexport const isRealAiMode = () => process.env.AI_TEST_MODE === 'real';\n\nconst isExplicitFalse = (value) => ['false', '0', 'no', 'off'].includes(String(value || '').toLowerCase());\n\nexport const shouldRunAgenticSafeguard = () => {\n if (isExplicitFalse(process.env.AGENTIC_SAFEGUARDS_ENABLED)) return false;\n if (isExplicitFalse(process.env.ENABLE_AGENTIC_SAFEGUARDS)) return false;\n return true;\n};\n\nexport const assertSafeguardProviderConfigured = () => {\n if (isMockAiMode()) return;\n if (!process.env.DEEPSEEK_API_KEY) {\n throw new Error('DEEPSEEK_API_KEY is required because agentic safeguards are mandatory outside mock mode.');\n }\n};\n\nexport const getMaxSafeguardReparseAttempts = () => {\n const configured = Number(process.env.AGENTIC_SAFEGUARD_MAX_REPARSE_ATTEMPTS || 1);\n return Number.isFinite(configured) && configured >= 0 ? Math.min(configured, 2) : 1;\n};\n\nexport const buildSkippedSafeguardResult = (reason) => ({\n verdict: SAFEGUARD_VERDICTS.PASS,\n confidence: 1,\n blockOutput: false,\n blockMatch: false,\n skipped: true,\n repairApplied: false,\n parseAttempts: 1,\n finalStatus: 'safeguard_skipped',\n issues: [],\n reparseInstructions: [],\n reason,\n});\n\nexport const normalizeVerdict = (value = '') => {\n const normalized = String(value || '').toLowerCase().trim();\n if (Object.values(SAFEGUARD_VERDICTS).includes(normalized)) return normalized;\n return SAFEGUARD_VERDICTS.REVISE;\n};\n\nexport const ensureArray = (value) => (Array.isArray(value) ? value.filter(Boolean) : []);\n\nexport const normalizeIssue = (issue = {}) => ({\n field: String(issue.field || 'unknown'),\n severity: ['low', 'medium', 'high'].includes(issue.severity) ? issue.severity : 'medium',\n problem: String(issue.problem || issue.reason || 'Unspecified safeguard issue.'),\n action: String(issue.action || issue.suggestedAction || ''),\n});\n\nexport const normalizeSafeguardReview = (review = {}, fallback = {}) => {\n const verdict = normalizeVerdict(review.verdict || fallback.verdict);\n return {\n verdict,\n confidence: Number.isFinite(Number(review.confidence)) ? Number(review.confidence) : (fallback.confidence ?? 0.5),\n blockOutput: Boolean(review.blockOutput ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n blockMatch: Boolean(review.blockMatch ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n issues: ensureArray(review.issues || fallback.issues).map(normalizeIssue),\n reparseInstructions: ensureArray(review.reparseInstructions || fallback.reparseInstructions).map(String),\n reasoning: String(review.reasoning || review.reason || fallback.reasoning || ''),\n };\n};\n"}, "9df6b75a68c49d7dcca673d2335216229c5fe547": {"t": 1785754154.7211595, "n": 3052, "h": "cbaf1878ecc72023", "c": "/**\n * File responsibility: Shared helpers for controlled agentic safeguards.\n * Main responsibilities:\n * - Keep safeguard verdict names stable across JD parsing and CV-JD matching.\n * - Centralise feature flags so mock tests can opt into review while real flows always run safeguards.\n */\n\nexport const SAFEGUARD_VERDICTS = {\n PASS: 'pass',\n REVISE: 'revise',\n REJECT: 'reject',\n};\n\nexport const isMockAiMode = () => process.env.AI_TEST_MODE === 'mock';\nexport const isRealAiMode = () => process.env.AI_TEST_MODE === 'real';\n\nconst isExplicitFalse = (value) => ['false', '0', 'no', 'off'].includes(String(value || '').toLowerCase());\n\nexport const shouldRunAgenticSafeguard = () => {\n if (isExplicitFalse(process.env.AGENTIC_SAFEGUARDS_ENABLED)) return false;\n if (isExplicitFalse(process.env.ENABLE_AGENTIC_SAFEGUARDS)) return false;\n return true;\n};\n\nexport const assertSafeguardProviderConfigured = () => {\n if (isMockAiMode()) return;\n if (!process.env.DEEPSEEK_API_KEY) {\n throw new Error('DEEPSEEK_API_KEY is required because agentic safeguards are mandatory outside mock mode.');\n }\n};\n\nexport const getMaxSafeguardReparseAttempts = () => {\n const configured = Number(process.env.AGENTIC_SAFEGUARD_MAX_REPARSE_ATTEMPTS || 1);\n return Number.isFinite(configured) && configured >= 0 ? Math.min(configured, 2) : 1;\n};\n\nexport const buildSkippedSafeguardResult = (reason) => ({\n verdict: SAFEGUARD_VERDICTS.PASS,\n confidence: 1,\n blockOutput: false,\n blockMatch: false,\n skipped: true,\n repairApplied: false,\n parseAttempts: 1,\n finalStatus: 'safeguard_skipped',\n issues: [],\n reparseInstructions: [],\n reason,\n});\n\nexport const normalizeVerdict = (value = '') => {\n const normalized = String(value || '').toLowerCase().trim();\n if (Object.values(SAFEGUARD_VERDICTS).includes(normalized)) return normalized;\n return SAFEGUARD_VERDICTS.REVISE;\n};\n\nexport const ensureArray = (value) => (Array.isArray(value) ? value.filter(Boolean) : []);\n\nexport const normalizeIssue = (issue = {}) => ({\n field: String(issue.field || 'unknown'),\n severity: ['low', 'medium', 'high'].includes(issue.severity) ? issue.severity : 'medium',\n problem: String(issue.problem || issue.reason || 'Unspecified safeguard issue.'),\n action: String(issue.action || issue.suggestedAction || ''),\n});\n\nexport const normalizeSafeguardReview = (review = {}, fallback = {}) => {\n const verdict = normalizeVerdict(review.verdict || fallback.verdict);\n return {\n verdict,\n confidence: Number.isFinite(Number(review.confidence)) ? Number(review.confidence) : (fallback.confidence ?? 0.5),\n blockOutput: Boolean(review.blockOutput ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n blockMatch: Boolean(review.blockMatch ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n issues: ensureArray(review.issues || fallback.issues).map(normalizeIssue),\n reparseInstructions: ensureArray(review.reparseInstructions || fallback.reparseInstructions).map(String),\n reasoning: String(review.reasoning || review.reason || fallback.reasoning || ''),\n };\n};\n"}, "ea669e14f3e75ddca2d937710be535a2257a1cc3": {"t": 1785754156.010973, "n": 2776, "h": "bb96e7873f14a5da", "c": "/**\n * File responsibility: Shared helpers for controlled agentic safeguards.\n * Main responsibilities:\n * - Keep safeguard verdict names stable across JD parsing and CV-JD matching.\n * - Centralise feature flags so mock tests can opt into review while real flows always run safeguards.\n */\n\nexport const SAFEGUARD_VERDICTS = {\n PASS: 'pass',\n REVISE: 'revise',\n REJECT: 'reject',\n};\n\nexport const isMockAiMode = () => process.env.AI_TEST_MODE === 'mock';\nexport const isRealAiMode = () => process.env.AI_TEST_MODE === 'real';\n\nexport const shouldRunAgenticSafeguard = () => true;\n\nexport const assertSafeguardProviderConfigured = () => {\n if (isMockAiMode()) return;\n if (!process.env.DEEPSEEK_API_KEY) {\n throw new Error('DEEPSEEK_API_KEY is required because agentic safeguards are mandatory outside mock mode.');\n }\n};\n\nexport const getMaxSafeguardReparseAttempts = () => {\n const configured = Number(process.env.AGENTIC_SAFEGUARD_MAX_REPARSE_ATTEMPTS || 1);\n return Number.isFinite(configured) && configured >= 0 ? Math.min(configured, 2) : 1;\n};\n\nexport const buildSkippedSafeguardResult = (reason) => ({\n verdict: SAFEGUARD_VERDICTS.PASS,\n confidence: 1,\n blockOutput: false,\n blockMatch: false,\n skipped: true,\n repairApplied: false,\n parseAttempts: 1,\n finalStatus: 'safeguard_skipped',\n issues: [],\n reparseInstructions: [],\n reason,\n});\n\nexport const normalizeVerdict = (value = '') => {\n const normalized = String(value || '').toLowerCase().trim();\n if (Object.values(SAFEGUARD_VERDICTS).includes(normalized)) return normalized;\n return SAFEGUARD_VERDICTS.REVISE;\n};\n\nexport const ensureArray = (value) => (Array.isArray(value) ? value.filter(Boolean) : []);\n\nexport const normalizeIssue = (issue = {}) => ({\n field: String(issue.field || 'unknown'),\n severity: ['low', 'medium', 'high'].includes(issue.severity) ? issue.severity : 'medium',\n problem: String(issue.problem || issue.reason || 'Unspecified safeguard issue.'),\n action: String(issue.action || issue.suggestedAction || ''),\n});\n\nexport const normalizeSafeguardReview = (review = {}, fallback = {}) => {\n const verdict = normalizeVerdict(review.verdict || fallback.verdict);\n return {\n verdict,\n confidence: Number.isFinite(Number(review.confidence)) ? Number(review.confidence) : (fallback.confidence ?? 0.5),\n blockOutput: Boolean(review.blockOutput ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n blockMatch: Boolean(review.blockMatch ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n issues: ensureArray(review.issues || fallback.issues).map(normalizeIssue),\n reparseInstructions: ensureArray(review.reparseInstructions || fallback.reparseInstructions).map(String),\n reasoning: String(review.reasoning || review.reason || fallback.reasoning || ''),\n };\n};\n"}, "18bed71a5847192b5ecafa4a75948f8e89228959": {"t": 1785754158.5541346, "n": 2869, "h": "c3a35adcc4080ba8", "c": "/**\n * File responsibility: Shared helpers for controlled agentic safeguards.\n * Main responsibilities:\n * - Keep safeguard verdict names stable across JD parsing and CV-JD matching.\n * - Centralise feature flags so mock tests can opt into review while real flows always run safeguards.\n */\n\nexport const SAFEGUARD_VERDICTS = {\n PASS: 'pass',\n REVISE: 'revise',\n REJECT: 'reject',\n};\n\nexport const isMockAiMode = () => process.env.AI_TEST_MODE === 'mock';\nexport const isRealAiMode = () => process.env.AI_TEST_MODE === 'real';\n\nexport const shouldRunAgenticSafeguard = () => {\n if (isMockAiMode()) return process.env.ENABLE_AGENTIC_SAFEGUARDS === 'true';\n return true;\n};\n\nexport const assertSafeguardProviderConfigured = () => {\n if (isMockAiMode()) return;\n if (!process.env.DEEPSEEK_API_KEY) {\n throw new Error('DEEPSEEK_API_KEY is required because agentic safeguards are mandatory outside mock mode.');\n }\n};\n\nexport const getMaxSafeguardReparseAttempts = () => {\n const configured = Number(process.env.AGENTIC_SAFEGUARD_MAX_REPARSE_ATTEMPTS || 1);\n return Number.isFinite(configured) && configured >= 0 ? Math.min(configured, 2) : 1;\n};\n\nexport const buildSkippedSafeguardResult = (reason) => ({\n verdict: SAFEGUARD_VERDICTS.PASS,\n confidence: 1,\n blockOutput: false,\n blockMatch: false,\n skipped: true,\n repairApplied: false,\n parseAttempts: 1,\n finalStatus: 'safeguard_skipped',\n issues: [],\n reparseInstructions: [],\n reason,\n});\n\nexport const normalizeVerdict = (value = '') => {\n const normalized = String(value || '').toLowerCase().trim();\n if (Object.values(SAFEGUARD_VERDICTS).includes(normalized)) return normalized;\n return SAFEGUARD_VERDICTS.REVISE;\n};\n\nexport const ensureArray = (value) => (Array.isArray(value) ? value.filter(Boolean) : []);\n\nexport const normalizeIssue = (issue = {}) => ({\n field: String(issue.field || 'unknown'),\n severity: ['low', 'medium', 'high'].includes(issue.severity) ? issue.severity : 'medium',\n problem: String(issue.problem || issue.reason || 'Unspecified safeguard issue.'),\n action: String(issue.action || issue.suggestedAction || ''),\n});\n\nexport const normalizeSafeguardReview = (review = {}, fallback = {}) => {\n const verdict = normalizeVerdict(review.verdict || fallback.verdict);\n return {\n verdict,\n confidence: Number.isFinite(Number(review.confidence)) ? Number(review.confidence) : (fallback.confidence ?? 0.5),\n blockOutput: Boolean(review.blockOutput ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n blockMatch: Boolean(review.blockMatch ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n issues: ensureArray(review.issues || fallback.issues).map(normalizeIssue),\n reparseInstructions: ensureArray(review.reparseInstructions || fallback.reparseInstructions).map(String),\n reasoning: String(review.reasoning || review.reason || fallback.reasoning || ''),\n };\n};\n"}, "531672aa130aac96f7e02e3b993dca4765c77ce6": {"t": 1785754159.8292193, "n": 2572, "h": "6fea71f2f6dfab6a", "c": "/**\n * File responsibility: Shared helpers for controlled agentic safeguards.\n * Main responsibilities:\n * - Keep safeguard verdict names stable across JD parsing and CV-JD matching.\n * - Centralise feature flags so normal dev/test flows can enable or skip DeepSeek review predictably.\n */\n\nexport const SAFEGUARD_VERDICTS = {\n PASS: 'pass',\n REVISE: 'revise',\n REJECT: 'reject',\n};\n\nexport const isMockAiMode = () => process.env.AI_TEST_MODE === 'mock';\nexport const isRealAiMode = () => process.env.AI_TEST_MODE === 'real';\n\nexport const shouldRunAgenticSafeguard = () => process.env.ENABLE_AGENTIC_SAFEGUARDS === 'true';\n\nexport const getMaxSafeguardReparseAttempts = () => {\n const configured = Number(process.env.AGENTIC_SAFEGUARD_MAX_REPARSE_ATTEMPTS || 1);\n return Number.isFinite(configured) && configured >= 0 ? Math.min(configured, 2) : 1;\n};\n\nexport const buildSkippedSafeguardResult = (reason) => ({\n verdict: SAFEGUARD_VERDICTS.PASS,\n confidence: 1,\n blockOutput: false,\n blockMatch: false,\n skipped: true,\n repairApplied: false,\n parseAttempts: 1,\n finalStatus: 'safeguard_skipped',\n issues: [],\n reparseInstructions: [],\n reason,\n});\n\nexport const normalizeVerdict = (value = '') => {\n const normalized = String(value || '').toLowerCase().trim();\n if (Object.values(SAFEGUARD_VERDICTS).includes(normalized)) return normalized;\n return SAFEGUARD_VERDICTS.REVISE;\n};\n\nexport const ensureArray = (value) => (Array.isArray(value) ? value.filter(Boolean) : []);\n\nexport const normalizeIssue = (issue = {}) => ({\n field: String(issue.field || 'unknown'),\n severity: ['low', 'medium', 'high'].includes(issue.severity) ? issue.severity : 'medium',\n problem: String(issue.problem || issue.reason || 'Unspecified safeguard issue.'),\n action: String(issue.action || issue.suggestedAction || ''),\n});\n\nexport const normalizeSafeguardReview = (review = {}, fallback = {}) => {\n const verdict = normalizeVerdict(review.verdict || fallback.verdict);\n return {\n verdict,\n confidence: Number.isFinite(Number(review.confidence)) ? Number(review.confidence) : (fallback.confidence ?? 0.5),\n blockOutput: Boolean(review.blockOutput ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n blockMatch: Boolean(review.blockMatch ?? (verdict !== SAFEGUARD_VERDICTS.PASS)),\n issues: ensureArray(review.issues || fallback.issues).map(normalizeIssue),\n reparseInstructions: ensureArray(review.reparseInstructions || fallback.reparseInstructions).map(String),\n reasoning: String(review.reasoning || review.reason || fallback.reasoning || ''),\n };\n};\n"}}}}