"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ADDRESS_TRUTH_GATE_SCHEMA_VERSION = void 0; exports.resolveAddressTruthGate = resolveAddressTruthGate; exports.toAddressTruthGateContract = toAddressTruthGateContract; exports.buildAddressTruthGateDebugFields = buildAddressTruthGateDebugFields; exports.attachAddressTruthGate = attachAddressTruthGate; exports.ADDRESS_TRUTH_GATE_SCHEMA_VERSION = "address_truth_gate_v1"; function toRecordObject(value) { if (!value || typeof value !== "object" || Array.isArray(value)) { return null; } return value; } function toNonEmptyString(value) { if (value === null || value === undefined) { return null; } const text = String(value).trim(); return text.length > 0 ? text : null; } function toStringList(value) { if (!Array.isArray(value)) { return []; } return value .map((item) => toNonEmptyString(item)) .filter((item) => Boolean(item)); } function isTruthGateStatus(value) { return (value === "full_confirmed" || value === "partial_supported" || value === "blocked_missing_anchor" || value === "blocked_route_expectation_failure" || value === "blocked_execution_error" || value === "limited_temporal_or_contextual" || value === "unknown"); } function isCarryoverDepth(value) { return value === "full" || value === "root_only" || value === "object_only" || value === "meta_only" || value === "none"; } function isLimitedReasonCategory(value) { return (value === "empty_match" || value === "missing_anchor" || value === "recipe_visibility_gap" || value === "execution_error" || value === "unsupported"); } function isRuntimeReadiness(value) { return (value === "LIVE_QUERYABLE" || value === "LIVE_QUERYABLE_WITH_LIMITS" || value === "REQUIRES_SPECIALIZED_RECIPE" || value === "DEEP_ONLY" || value === "UNKNOWN"); } function normalizeReasonCode(value) { const normalized = value .trim() .replace(/[^\p{L}\p{N}_.:-]+/gu, "_") .replace(/^_+|_+$/g, "") .toLowerCase(); return normalized.length > 0 ? normalized.slice(0, 120) : null; } function pushReason(target, value) { const text = toNonEmptyString(value); if (!text) { return; } const normalized = normalizeReasonCode(text); if (normalized && !target.includes(normalized)) { target.push(normalized); } } function hasFilterScope(filters) { if (!filters) { return false; } const scopeKeys = [ "period_from", "period_to", "as_of_date", "organization", "counterparty", "contract", "account", "item", "warehouse", "document_type", "document_ref", "status" ]; return scopeKeys.some((key) => toNonEmptyString(filters[key]) !== null); } function hasObjectFocus(input) { if (toNonEmptyString(input.filters?.item)) { return true; } if (input.semanticFrame?.selected_object_scope_detected) { return true; } if (input.semanticFrame?.anchor_kind === "selected_object" || input.semanticFrame?.anchor_kind === "item") { return true; } return (input.intent === "inventory_purchase_provenance_for_item" || input.intent === "inventory_purchase_documents_for_item" || input.intent === "inventory_sale_trace_for_item" || input.intent === "inventory_profitability_for_item" || input.intent === "inventory_purchase_to_sale_chain" || input.intent === "inventory_aging_by_purchase_date"); } function hasReusableRootScope(input) { if (hasFilterScope(input.filters)) { return true; } return Boolean(input.semanticFrame && input.semanticFrame.scope_kind !== "none"); } function truthGateStatusFrom(input) { if (input.truthGateStatusHint) { return input.truthGateStatusHint; } const missingRequiredFilters = input.missingRequiredFilters ?? []; const reasonCodes = input.reasons ?? []; const heuristicOpenItemsFallback = Boolean(input.intent === "open_items_by_counterparty_or_contract" && (reasonCodes.includes("confirmed_balance_unavailable_fallback_to_heuristic_candidates") || reasonCodes.includes("open_items_account_query_override_to_movements"))); if (input.routeExpectationStatus === "mismatch") { return "blocked_route_expectation_failure"; } if (input.limitedReasonCategory === "execution_error") { return "blocked_execution_error"; } if (missingRequiredFilters.length > 0 || input.limitedReasonCategory === "missing_anchor") { return "blocked_missing_anchor"; } if (input.temporalGuardOutcome === "ambiguous_limited" || input.temporalAlignmentStatus === "conflicting") { return "limited_temporal_or_contextual"; } if (input.replyType === "factual" && input.limitedReasonCategory === "empty_match") { return "full_confirmed"; } if (heuristicOpenItemsFallback) { return "partial_supported"; } if (input.limitedReasonCategory === "empty_match" || input.limitedReasonCategory === "recipe_visibility_gap" || input.limitedReasonCategory === "unsupported" || input.replyType === "partial_coverage") { return "partial_supported"; } if ((input.rowsMatched ?? 0) > 0) { return "full_confirmed"; } return "unknown"; } function carryoverEligibilityFor(input, truthGateStatus) { if (truthGateStatus.startsWith("blocked")) { return "none"; } if (input.limitedReasonCategory === "recipe_visibility_gap" || input.limitedReasonCategory === "unsupported") { return "meta_only"; } if (hasObjectFocus(input)) { return "object_only"; } if (truthGateStatus === "limited_temporal_or_contextual") { return hasReusableRootScope(input) ? "root_only" : "meta_only"; } if (truthGateStatus === "full_confirmed" || truthGateStatus === "partial_supported") { return hasReusableRootScope(input) ? "root_only" : "meta_only"; } return "none"; } function explanationFor(truthGateStatus, limitedReasonCategory) { if (truthGateStatus === "full_confirmed") { return null; } if (truthGateStatus === "blocked_missing_anchor") { return "required_anchor_missing"; } if (truthGateStatus === "blocked_route_expectation_failure") { return "route_expectation_failed"; } if (truthGateStatus === "blocked_execution_error") { return "execution_failed"; } if (truthGateStatus === "limited_temporal_or_contextual") { return "temporal_or_contextual_limit"; } if (limitedReasonCategory === "recipe_visibility_gap") { return "specialized_recipe_required"; } if (limitedReasonCategory === "unsupported") { return "unsupported_in_current_contour"; } return truthGateStatus === "partial_supported" ? "evidence_or_coverage_is_partial" : "truth_gate_not_confirmed"; } function collectReasonCodes(input, truthGateStatus) { const reasons = []; pushReason(reasons, `address_truth_gate_${truthGateStatus}`); pushReason(reasons, input.routeExpectationReason); pushReason(reasons, input.limitedReasonCategory ? `limited_category_${input.limitedReasonCategory}` : null); (input.missingRequiredFilters ?? []).forEach((item) => pushReason(reasons, `missing_filter_${item}`)); (input.limitations ?? []).forEach((item) => pushReason(reasons, item)); (input.reasons ?? []).forEach((item) => pushReason(reasons, item)); return reasons.slice(0, 32); } function resolveAddressTruthGate(input) { const truthGateStatus = truthGateStatusFrom(input); return { schema_version: exports.ADDRESS_TRUTH_GATE_SCHEMA_VERSION, policy_owner: "addressTruthGatePolicy", truth_gate_status: truthGateStatus, carryover_eligibility: carryoverEligibilityFor(input, truthGateStatus), limited_reason_category: input.limitedReasonCategory ?? null, runtime_readiness: input.runtimeReadiness ?? "UNKNOWN", reason_codes: collectReasonCodes(input, truthGateStatus), blocked_or_limited_explanation: explanationFor(truthGateStatus, input.limitedReasonCategory ?? null) }; } function toAddressTruthGateContract(value) { const record = toRecordObject(value); if (!record) { return null; } const truthGateStatus = toNonEmptyString(record.truth_gate_status); const carryoverEligibility = toNonEmptyString(record.carryover_eligibility); const limitedReasonCategory = toNonEmptyString(record.limited_reason_category); const runtimeReadiness = toNonEmptyString(record.runtime_readiness); if (!isTruthGateStatus(truthGateStatus) || !isCarryoverDepth(carryoverEligibility) || !isRuntimeReadiness(runtimeReadiness)) { return null; } return { schema_version: exports.ADDRESS_TRUTH_GATE_SCHEMA_VERSION, policy_owner: "addressTruthGatePolicy", truth_gate_status: truthGateStatus, carryover_eligibility: carryoverEligibility, limited_reason_category: isLimitedReasonCategory(limitedReasonCategory) ? limitedReasonCategory : null, runtime_readiness: runtimeReadiness, reason_codes: toStringList(record.reason_codes).slice(0, 32), blocked_or_limited_explanation: toNonEmptyString(record.blocked_or_limited_explanation) }; } function buildAddressTruthGateDebugFields(input) { return { address_truth_gate_v1: resolveAddressTruthGate(input) }; } function attachAddressTruthGate(debugPayload, input) { return { ...debugPayload, ...buildAddressTruthGateDebugFields(input) }; }