"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ASSISTANT_EVIDENCE_PLANNER_SCHEMA_VERSION = void 0; exports.buildAssistantEvidencePlanner = buildAssistantEvidencePlanner; exports.ASSISTANT_EVIDENCE_PLANNER_SCHEMA_VERSION = "assistant_evidence_planner_v1"; function toNonEmptyString(value) { if (value === null || value === undefined) { return null; } const text = String(value).trim(); return text.length > 0 ? text : null; } 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 normalized = normalizeReasonCode(value); if (normalized && !target.includes(normalized)) { target.push(normalized); } } function uniqueStrings(values) { const result = []; for (const value of values) { const text = toNonEmptyString(value); if (text && !result.includes(text)) { result.push(text); } } return result; } function providedAxesFromMeaning(meaning) { const result = []; if ((meaning?.explicit_entity_candidates?.length ?? 0) > 0) { result.push("counterparty"); result.push("business_entity"); } if (toNonEmptyString(meaning?.explicit_organization_scope)) { result.push("organization"); } if (toNonEmptyString(meaning?.explicit_date_scope)) { result.push("period"); } if (toNonEmptyString(meaning?.asked_aggregation_axis)) { result.push("aggregate_axis"); } if (toNonEmptyString(meaning?.metadata_scope_hint)) { result.push("metadata_scope"); } return uniqueStrings(result); } function missingAxes(requiredAxes, providedAxes) { return requiredAxes.filter((axis) => !providedAxes.includes(axis)); } const USER_ACTIONABLE_AXIS_SET = new Set([ "counterparty", "business_entity", "organization", "period", "as_of_date", "item", "supplier", "buyer", "warehouse", "document", "contract", "metadata_scope", "lane_family_choice" ]); function userActionableMissingAxes(axes) { return axes.filter((axis) => USER_ACTIONABLE_AXIS_SET.has(axis)); } function coverageExpectationFor(graph) { if (graph?.proof_expectation === "bounded_inference") { return "bounded_inference"; } if (graph?.proof_expectation === "clarification_required") { return "clarification"; } return "confirmed_coverage"; } function answerModeFor(input) { if (input.plannerStatus === "needs_clarification") { return "clarification_required"; } if (input.plannerStatus === "blocked") { return "checked_sources_only"; } if (input.coverageExpectation === "bounded_inference") { return "bounded_business_inference"; } if (input.coverageExpectation === "clarification") { return "clarification_required"; } return "confirmed_business_answer"; } function requiredUserLayersFor(answerMode) { if (answerMode === "clarification_required") { return ["clarifying_question", "why_needed", "available_calculation"]; } if (answerMode === "bounded_business_inference") { return ["business_conclusion", "key_figures", "evidence_boundary", "next_step"]; } if (answerMode === "checked_sources_only") { return ["checked_sources_boundary", "unknowns", "next_probe"]; } return ["direct_business_answer", "key_figures", "evidence_boundary", "next_step"]; } function buildAssistantEvidencePlanner(input) { const graph = input.dataNeedGraph ?? null; const plan = input.discoveryPlan; const turnMeaning = plan.turn_meaning_ref; const requiredAxes = uniqueStrings(plan.required_axes); const providedAxes = providedAxesFromMeaning(turnMeaning); const graphClarificationGaps = uniqueStrings(graph?.clarification_gaps ?? []); const additionalAxisGaps = uniqueStrings(input.additionalMissingAxes ?? []).filter((axis) => !providedAxes.includes(axis) && (requiredAxes.includes(axis) || USER_ACTIONABLE_AXIS_SET.has(axis))); const axisGaps = uniqueStrings([...additionalAxisGaps, ...missingAxes(requiredAxes, providedAxes)]); const actionableAxisGaps = userActionableMissingAxes(axisGaps); const clarificationGaps = uniqueStrings([...graphClarificationGaps, ...axisGaps]); const coverageExpectation = coverageExpectationFor(graph); const answerMode = answerModeFor({ plannerStatus: input.plannerStatus, coverageExpectation }); const reasonCodes = uniqueStrings(plan.reason_codes); pushReason(reasonCodes, "evidence_planner_contract_built"); if (graph) { pushReason(reasonCodes, "evidence_planner_consumed_data_need_graph"); } if (clarificationGaps.length > 0) { pushReason(reasonCodes, "evidence_planner_has_missing_axes_or_gaps"); } return { schema_version: exports.ASSISTANT_EVIDENCE_PLANNER_SCHEMA_VERSION, policy_owner: "assistantEvidencePlanner", planner_status: input.plannerStatus, semantic_data_need: toNonEmptyString(input.semanticDataNeed), selected_chain_id: input.selectedChainId, data_need: { business_fact_family: graph?.business_fact_family ?? null, action_family: graph?.action_family ?? null, aggregation_need: graph?.aggregation_need ?? null, comparison_need: graph?.comparison_need ?? null, ranking_need: graph?.ranking_need ?? null, time_scope_need: graph?.time_scope_need ?? null, proof_expectation: graph?.proof_expectation ?? null, subject_candidates: uniqueStrings(graph?.subject_candidates ?? []) }, evidence_axes: { required_axes: requiredAxes, provided_axes: providedAxes, missing_axes: axisGaps, user_actionable_missing_axes: actionableAxisGaps, clarification_gaps: clarificationGaps }, primitive_plan: { selected_chain_id: input.selectedChainId, allowed_primitives: plan.allowed_primitives, rejected_primitives: plan.rejected_primitives, execution_budget: plan.execution_budget }, coverage_gate: { requires_evidence_gate: true, expected_coverage: coverageExpectation, answer_permission_if_satisfied: answerMode, answer_may_use_raw_model_claims: false }, answer_contract: { answer_mode: answerMode, required_user_layers: requiredUserLayersFor(answerMode), forbidden_overclaim_flags: uniqueStrings(graph?.forbidden_overclaim_flags ?? []), must_keep_internal_mechanics_hidden: true }, reason_codes: reasonCodes }; }