"""Seller-facing Deal Desk service helpers."""

from __future__ import annotations

import json
import re
import secrets
from dataclasses import dataclass
from datetime import date, datetime, timezone
from pathlib import Path
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field, computed_field

from g_gremlin import sfdc as sfdc_helpers
from g_gremlin.autopilot.contracts import PlanSource, PlanStep, PlanV1
from g_gremlin.autopilot.executor import PlanExecutor
from g_gremlin.autopilot.policy import AutonomyPolicy, compute_policy_hash
from g_gremlin.autopilot.receipts import ReceiptWriter, load_receipt
from g_gremlin.autopilot.tools import get_default_registry

from .adapters.router import resolve_quote_adapter, seller_quote_support as route_seller_quote_support
from .config import DealDeskConfig, load_dealdesk_config
from .context import ArtifactRef, DealContextV1
from .documents import inventory_close_documents
from .extraction import extract_structured_close_document_evidence, preflight_close_document_inventory
from .eventing import (
    _advance_close_workflow_state,
    build_pattern_update_event,
    resolve_crm_org_id,
    save_pattern_update_events,
    update_context_for_close_progression,
    utc_now_iso,
)
from .forensics import build_deal_pattern_profile, fetch_historical_opportunities
from .handlers import _fetch_opportunity_snapshot, _pattern_profile_stale, handle_dealdesk_quote_readiness
from .history import (
    CloseCertificationRunV1,
    document_evidence_escalated,
    summarize_close_document_evidence,
)
from .integrity import build_quote_integrity_assessment, capture_quote_document_fingerprints
from .profiles import FieldMappingCandidate, QuoteAdapterCapabilityProfileV1, QuoteEnvironmentProfileV1
from .quote_intelligence import (
    DealDeskQuoteIntelligenceResponseV1,
    load_dealdesk_quote_intelligence,
)
from .readiness import QuoteReadinessResult, ReadinessIssue, evaluate_quote_readiness
from .reconciliation import ReconciliationPacketV1, build_reconciliation_packet_from_readiness
from .store import DealDeskStore
from .triggers import PostCloseTriggerRunV1, PostCloseTriggerV1, build_post_close_trigger_registry

_SELLER_FIX_SUPPORTED_FIELD_TYPES = {"string", "textarea", "phone", "url", "email", "picklist", "date", "datetime", "boolean"}
_SELLER_FIX_BLOCKED_FIELD_NAMES = {"Amount", "StageName", "OwnerId", "ForecastCategoryName", "Pricebook2Id", "Probability"}
_SELLER_FIX_BLOCKED_NAME_TOKENS = ("amount", "arr", "mrr", "acv", "tcv", "discount", "price", "owner")
_SELLER_CONTACT_ID_RE = re.compile(r"^003[a-zA-Z0-9]{12,15}$")
_SELLER_EMAIL_RE = re.compile(r"^[^\s@]+@[^\s@]+\.[^\s@]+$")
_SELLER_PRODUCT_ID_RE = re.compile(r"^(?:01t|01u|01v)[a-zA-Z0-9]{12,15}$", re.IGNORECASE)
_SELLER_ACTIVE_QUOTE_TERMINAL_STATUS_TOKENS = {
    "cancelled",
    "canceled",
    "declined",
    "denied",
    "expired",
    "ordered",
    "rejected",
    "superseded",
    "void",
    "voided",
}
_DEAL_LOOKUP_STOPWORDS = {
    "a",
    "an",
    "and",
    "blocking",
    "close",
    "deal",
    "for",
    "health",
    "is",
    "of",
    "on",
    "opportunity",
    "status",
    "the",
    "this",
    "to",
    "what",
    "whats",
    "where",
}
CloseCertificationEntrypoint = Literal["submitted_for_close", "closed_won_retro"]
CloseProgressionStatus = Literal[
    "not_attempted",
    "progressed",
    "approval_required",
    "already_closed_won",
    "skipped",
    "blocked",
]
PostCloseExecutionStatus = Literal[
    "not_attempted",
    "preview_required",
    "approval_required",
    "executed",
    "skipped",
    "failed",
    "escalated",
]
QuoteIntentOperation = Literal[
    "update_discount_pct",
    "update_term_months",
    "update_payment_terms",
    "add_product",
    "remove_product",
    "update_quantity",
]
QuoteIntentSemanticKey = Literal["discount_pct", "term_months", "payment_terms", "line_item"]
QuoteLineReferenceType = Literal["product_id", "product_code", "product_name"]
QuoteLineResolutionStatus = Literal["resolved", "ambiguous", "not_found", "unsupported"]
QuotePreviewStatus = Literal["preview_ready", "unsupported", "ambiguous", "no_quote"]
QuotePreviewPolicyState = Literal["clean", "approval_likely", "review_required", "unsupported"]


@dataclass(frozen=True)
class _CloseProgressionExecution:
    status: CloseProgressionStatus
    target_stage_name: str | None = None
    receipt_run_id: str | None = None
    receipt_dir: str | None = None
    approval_required: bool = False
    pending_run_id: str | None = None
    pending_plan_path: Path | None = None


@dataclass(frozen=True)
class _PostCloseExecution:
    status: PostCloseExecutionStatus
    trigger_runs: list[PostCloseTriggerRunV1]
    approval_required: bool = False
    pending_run_id: str | None = None
    pending_plan_path: Path | None = None


@dataclass(frozen=True)
class _QuoteRecordSnapshot:
    quote_id: str
    object_name: str
    label: str
    status: str
    amount: float | None = None
    expiration_date: str | None = None
    created_at: str | None = None
    last_modified_at: str | None = None
    is_primary: bool = False
    is_syncing: bool = False
    is_ordered: bool = False
    current_reason: str = ""


@dataclass(frozen=True)
class _QuoteApprovalProcessSnapshot:
    process_id: str
    quote_id: str
    status: str
    created_at: str | None = None
    completed_at: str | None = None
    submitted_by_name: str | None = None
    last_actor_name: str | None = None


@dataclass(frozen=True)
class _QuoteApprovalWorkitemSnapshot:
    process_id: str
    actor_id: str | None
    actor_name: str | None
    original_actor_name: str | None
    created_at: str | None = None


@dataclass(frozen=True)
class _QuoteLineItemSnapshot:
    line_item_id: str
    quote_id: str
    object_name: str
    product_id: str | None
    product_code: str | None
    product_name: str
    quantity: float | None = None
    unit_price: float | None = None
    net_price: float | None = None
    pricebook_entry_id: str | None = None
    line_number: str | None = None


class _SellerServiceModel(BaseModel):
    model_config = ConfigDict(extra="ignore")

    def to_dict(self) -> dict[str, Any]:
        return self.model_dump(exclude_none=False, by_alias=True)


class SellerActionHintV1(_SellerServiceModel):
    action_key: str
    label: str
    detail: str
    field_name: str | None = None


class SellerDealHealthSummaryV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    lifecycle_state: str
    close_workflow_state: str
    readiness_mode: str
    overall_confidence: float
    blocker_count: int = 0
    warning_count: int = 0
    info_count: int = 0
    blockers: list[ReadinessIssue] = Field(default_factory=list)
    warnings: list[ReadinessIssue] = Field(default_factory=list)
    infos: list[ReadinessIssue] = Field(default_factory=list)
    next_actions: list[SellerActionHintV1] = Field(default_factory=list)
    latest_reconciliation_packet_id: str | None = None
    latest_close_review_generated_at: str | None = None
    latest_close_review_disposition: str | None = None
    latest_close_review_summary: str = ""
    latest_document_evidence_status: str = "not_required"
    latest_document_summary: str = ""
    latest_document_extraction_status: str = "not_attempted"
    latest_document_discrepancy_count: int = 0
    latest_document_evidence_summary: str = ""
    latest_quote_integrity_status: str = "not_available"
    latest_quote_integrity_summary: str = ""
    latest_quote_integrity_discrepancy_count: int = 0
    latest_quote_fingerprint_count: int = 0
    latest_quote_binary_mismatch_count: int = 0
    latest_quote_semantic_mismatch_count: int = 0

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerDealHealthSummary/v1"


class SellerDealLookupCandidateV1(_SellerServiceModel):
    opportunity_id: str
    name: str
    account_name: str | None = None
    stage_name: str | None = None
    close_date: str | None = None
    owner_name: str | None = None
    amount: float | None = None

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerDealLookupCandidate/v1"


class SellerDealLookupResultV1(_SellerServiceModel):
    version: int = 1
    query: str
    crm_org_id: str
    org_alias: str | None = None
    status: str
    resolved_opportunity_id: str | None = None
    candidate_count: int = 0
    truncated: bool = False
    candidates: list[SellerDealLookupCandidateV1] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerDealLookupResult/v1"


class CloseCertificationResultV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    entrypoint: CloseCertificationEntrypoint
    lifecycle_state: str
    close_workflow_state: str
    overall_disposition: str
    reconciliation_packet_id: str
    reconciliation_packet_path: str
    blocker_count: int = 0
    approval_required_count: int = 0
    auto_fixable_count: int = 0
    document_evidence_status: str = "not_required"
    document_candidate_count: int = 0
    document_contract_candidate_count: int = 0
    document_summary: str = ""
    document_extraction_status: str = "not_attempted"
    document_evidence_count: int = 0
    document_comparison_count: int = 0
    document_discrepancy_count: int = 0
    document_evidence_summary: str = ""
    quote_integrity_status: str = "not_available"
    quote_integrity_summary: str = ""
    quote_integrity_discrepancy_count: int = 0
    quote_fingerprint_count: int = 0
    quote_binary_mismatch_count: int = 0
    quote_semantic_mismatch_count: int = 0
    progression_status: CloseProgressionStatus = "not_attempted"
    progression_target_stage: str | None = None
    progression_receipt_run_id: str | None = None
    progression_receipt_dir: str | None = None
    progression_approval_required: bool = False
    progression_pending_run_id: str | None = None
    progression_pending_plan_path: str | None = None
    post_close_status: PostCloseExecutionStatus = "not_attempted"
    post_close_trigger_runs: list[PostCloseTriggerRunV1] = Field(default_factory=list)
    post_close_approval_required: bool = False
    post_close_pending_run_id: str | None = None
    post_close_pending_plan_path: str | None = None
    triggered_at: str
    close_submitted_at: str | None = None
    next_actions: list[SellerActionHintV1] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "CloseCertificationResult/v1"


class CloseReviewSubmissionV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    lifecycle_state: str
    close_workflow_state: str
    overall_disposition: str
    reconciliation_packet_id: str
    reconciliation_packet_path: str
    blocker_count: int = 0
    approval_required_count: int = 0
    auto_fixable_count: int = 0
    document_evidence_status: str = "not_required"
    document_candidate_count: int = 0
    document_contract_candidate_count: int = 0
    document_summary: str = ""
    document_extraction_status: str = "not_attempted"
    document_evidence_count: int = 0
    document_comparison_count: int = 0
    document_discrepancy_count: int = 0
    document_evidence_summary: str = ""
    quote_integrity_status: str = "not_available"
    quote_integrity_summary: str = ""
    quote_integrity_discrepancy_count: int = 0
    quote_fingerprint_count: int = 0
    quote_binary_mismatch_count: int = 0
    quote_semantic_mismatch_count: int = 0
    progression_status: CloseProgressionStatus = "not_attempted"
    progression_target_stage: str | None = None
    progression_receipt_run_id: str | None = None
    progression_receipt_dir: str | None = None
    progression_approval_required: bool = False
    progression_pending_run_id: str | None = None
    progression_pending_plan_path: str | None = None
    post_close_status: PostCloseExecutionStatus = "not_attempted"
    post_close_trigger_runs: list[PostCloseTriggerRunV1] = Field(default_factory=list)
    post_close_approval_required: bool = False
    post_close_pending_run_id: str | None = None
    post_close_pending_plan_path: str | None = None
    submitted_at: str
    next_actions: list[SellerActionHintV1] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "CloseReviewSubmission/v1"


class SellerFieldFixResultV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    field_name: str
    field_value: Any
    receipt_run_id: str | None = None
    receipt_dir: str | None = None
    receipt_outcome: str
    applied: bool = False
    already_set: bool = False
    approval_required: bool = False
    current_value: Any | None = None
    pending_run_id: str | None = None
    pending_plan_path: str | None = None
    lifecycle_state: str
    close_workflow_state: str
    updated_summary: SellerDealHealthSummaryV1

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerFieldFixResult/v1"


class SellerContactRoleResultV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    contact_reference: str
    contact_id: str
    contact_email: str | None = None
    role_name: str
    primary_contact_field_name: str
    receipt_run_id: str | None = None
    receipt_dir: str | None = None
    receipt_outcome: str
    applied: bool = False
    already_set: bool = False
    approval_required: bool = False
    current_primary_contact_id: str | None = None
    pending_run_id: str | None = None
    pending_plan_path: str | None = None
    lifecycle_state: str
    close_workflow_state: str
    updated_summary: SellerDealHealthSummaryV1

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerContactRoleResult/v1"


class SellerQuoteRecordV1(_SellerServiceModel):
    version: int = 1
    quote_id: str
    object_name: str
    label: str
    status: str
    amount: float | None = None
    expiration_date: str | None = None
    created_at: str | None = None
    last_modified_at: str | None = None
    is_primary: bool = False
    is_syncing: bool = False
    is_ordered: bool = False
    current_reason: str = ""

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteRecord/v1"


class SellerQuoteApproverV1(_SellerServiceModel):
    version: int = 1
    label: str
    actor_id: str | None = None
    source: Literal["live_pending", "expected_route"] = "live_pending"
    detail: str | None = None

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteApprover/v1"


class SellerQuoteEvidenceV1(_SellerServiceModel):
    version: int = 1
    source_type: str
    label: str
    detail: str

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteEvidence/v1"


class SellerQuoteStatusResultV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    lifecycle_state: str
    close_workflow_state: str
    readiness_mode: str
    detected_engine: str
    status: Literal["supported", "partial", "unsupported", "ambiguous", "no_quote"]
    support_reason: str = ""
    capability_gaps: list[str] = Field(default_factory=list)
    quote_count: int = 0
    selected_quote: SellerQuoteRecordV1 | None = None
    additional_quotes: list[SellerQuoteRecordV1] = Field(default_factory=list)
    approval_state: str = "not_requested"
    approval_submitted_at: str | None = None
    approval_completed_at: str | None = None
    matched_approval_route_names: list[str] = Field(default_factory=list)
    pending_approvers: list[SellerQuoteApproverV1] = Field(default_factory=list)
    expected_approvers: list[SellerQuoteApproverV1] = Field(default_factory=list)
    stale: bool = False
    stale_reasons: list[str] = Field(default_factory=list)
    conflict: bool = False
    conflict_reasons: list[str] = Field(default_factory=list)
    latest_reconciliation_packet_id: str | None = None
    latest_quote_integrity_status: str = "not_available"
    latest_quote_integrity_summary: str = ""
    evidence: list[SellerQuoteEvidenceV1] = Field(default_factory=list)
    next_step: str = ""

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteStatusResult/v1"


class SellerQuoteLineItemV1(_SellerServiceModel):
    version: int = 1
    line_item_id: str | None = None
    object_name: str
    quote_id: str
    product_id: str | None = None
    product_code: str | None = None
    product_name: str
    quantity: float | None = None
    quantity_display: str = ""
    unit_price: float | None = None
    unit_price_display: str = ""
    net_price: float | None = None
    net_price_display: str = ""
    pricebook_entry_id: str | None = None
    line_number: str | None = None

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteLineItem/v1"


class SellerQuoteLineItemPreviewV1(_SellerServiceModel):
    version: int = 1
    operation: Literal["add_product", "remove_product", "update_quantity"]
    target_label: str
    line_object_name: str
    product_reference_type: QuoteLineReferenceType
    product_reference_value: str
    resolution_status: QuoteLineResolutionStatus = "resolved"
    resolution_reason: str = ""
    current_lines: list[SellerQuoteLineItemV1] = Field(default_factory=list)
    proposed_line: SellerQuoteLineItemV1 | None = None
    diff_lines: list[str] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteLineItemPreview/v1"


class QuoteIntentV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    raw_request: str = ""
    operation: QuoteIntentOperation
    semantic_key: QuoteIntentSemanticKey
    target_label: str
    requested_value_raw: str
    requested_value_display: str
    requested_discount_pct: float | None = None
    requested_term_months: int | None = None
    requested_payment_terms: str | None = None
    requested_product_reference: str | None = None
    requested_product_reference_type: QuoteLineReferenceType | None = None
    requested_quantity: float | None = None

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "QuoteIntent/v1"


class SellerQuoteChangeFieldPreviewV1(_SellerServiceModel):
    version: int = 1
    semantic_key: Literal["discount_pct", "term_months", "payment_terms"]
    label: str
    object_name: str
    field_name: str
    mapping_confidence: float = Field(default=0.0, ge=0.0, le=1.0)
    current_value: Any | None = None
    current_value_display: str = ""
    proposed_value: Any | None = None
    proposed_value_display: str = ""

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteChangeFieldPreview/v1"


class SellerQuoteRevisionPreviewV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    execution_mode: Literal["preview_only"] = "preview_only"
    status: QuotePreviewStatus
    detected_engine: str
    support_reason: str = ""
    capability_gaps: list[str] = Field(default_factory=list)
    readiness_mode: str
    intent: QuoteIntentV1
    selected_quote: SellerQuoteRecordV1 | None = None
    field_preview: SellerQuoteChangeFieldPreviewV1 | None = None
    line_item_preview: SellerQuoteLineItemPreviewV1 | None = None
    approval_state: str = "not_requested"
    preview_readiness_mode: str = "review_required"
    preview_policy_state: QuotePreviewPolicyState = "review_required"
    preview_policy_reasons: list[str] = Field(default_factory=list)
    matched_approval_route_names: list[str] = Field(default_factory=list)
    recommended_approval_roles: list[str] = Field(default_factory=list)
    apply_supported: bool = True
    apply_support_reason: str = ""
    evidence: list[SellerQuoteEvidenceV1] = Field(default_factory=list)
    next_step: str = ""

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteRevisionPreview/v1"


class SellerQuoteRevisionApplyResultV1(_SellerServiceModel):
    version: int = 1
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    context_id: str | None = None
    execution_mode: Literal["apply"] = "apply"
    intent: QuoteIntentV1
    field_preview: SellerQuoteChangeFieldPreviewV1 | None = None
    line_item_preview: SellerQuoteLineItemPreviewV1 | None = None
    preview_policy_state: QuotePreviewPolicyState = "review_required"
    receipt_run_id: str | None = None
    receipt_dir: str | None = None
    receipt_outcome: str
    applied: bool = False
    already_set: bool = False
    approval_required: bool = False
    pending_run_id: str | None = None
    pending_plan_path: str | None = None
    updated_quote_status: SellerQuoteStatusResultV1

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteRevisionApplyResult/v1"


class SellerQuoteRevisionApprovalContextV1(_SellerServiceModel):
    version: int = 1
    run_id: str
    opportunity_id: str
    crm_org_id: str
    org_alias: str | None = None
    detected_engine: str | None = None
    intent: QuoteIntentV1
    selected_quote: SellerQuoteRecordV1
    field_preview: SellerQuoteChangeFieldPreviewV1 | None = None
    line_item_preview: SellerQuoteLineItemPreviewV1 | None = None
    preview_policy_state: QuotePreviewPolicyState = "review_required"
    preview_policy_reasons: list[str] = Field(default_factory=list)
    matched_approval_route_names: list[str] = Field(default_factory=list)
    recommended_approval_roles: list[str] = Field(default_factory=list)
    evidence: list[SellerQuoteEvidenceV1] = Field(default_factory=list)

    @computed_field(alias="$schema")
    @property
    def schema(self) -> str:
        return "SellerQuoteRevisionApprovalContext/v1"


def get_seller_deal_health_summary(
    *,
    opportunity_id: str,
    org_alias: str | None = None,
    state_dir: str | None = None,
    force_refresh: bool = False,
) -> SellerDealHealthSummaryV1:
    store = DealDeskStore(state_dir)
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    readiness, context = _readiness_and_context(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=crm_org_id,
        force_refresh=force_refresh,
    )
    latest_packet = store.load_latest_reconciliation_packet(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    blockers = [issue for issue in readiness.issues if issue.severity == "blocking"]
    warnings = [issue for issue in readiness.issues if issue.severity == "warning"]
    infos = [issue for issue in readiness.issues if issue.severity == "info"]
    readiness_actions = _next_actions_for_issues(readiness.issues)
    latest_review_actions = _next_actions_for_latest_close_review(latest_packet)
    if latest_review_actions and not readiness.issues:
        next_actions = latest_review_actions
    else:
        next_actions = _merge_seller_action_hints(readiness_actions, latest_review_actions)
    return SellerDealHealthSummaryV1(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context_id=context.context_id,
        lifecycle_state=context.lifecycle_state,
        close_workflow_state=context.close_workflow_state,
        readiness_mode=readiness.readiness_mode,
        overall_confidence=readiness.overall_confidence,
        blocker_count=len(blockers),
        warning_count=len(warnings),
        info_count=len(infos),
        blockers=blockers,
        warnings=warnings,
        infos=infos,
        next_actions=next_actions,
        latest_reconciliation_packet_id=(
            latest_packet.packet_id if latest_packet is not None else context.latest_reconciliation_packet_id
        ),
        latest_close_review_generated_at=(
            latest_packet.generated_at if latest_packet is not None else None
        ),
        latest_close_review_disposition=(
            latest_packet.overall_disposition if latest_packet is not None else None
        ),
        latest_close_review_summary=(
            latest_packet.summary if latest_packet is not None else ""
        ),
        latest_document_evidence_status=(
            latest_packet.document_evidence_status if latest_packet is not None else "not_required"
        ),
        latest_document_summary=(
            latest_packet.document_summary if latest_packet is not None else ""
        ),
        latest_document_extraction_status=(
            latest_packet.document_extraction_status if latest_packet is not None else "not_attempted"
        ),
        latest_document_discrepancy_count=(
            latest_packet.document_discrepancy_count if latest_packet is not None else 0
        ),
        latest_document_evidence_summary=(
            latest_packet.document_evidence_summary if latest_packet is not None else ""
        ),
        latest_quote_integrity_status=(
            latest_packet.quote_integrity_status if latest_packet is not None else "not_available"
        ),
        latest_quote_integrity_summary=(
            latest_packet.quote_integrity_summary if latest_packet is not None else ""
        ),
        latest_quote_integrity_discrepancy_count=(
            latest_packet.quote_integrity_discrepancy_count if latest_packet is not None else 0
        ),
        latest_quote_fingerprint_count=(
            latest_packet.quote_fingerprint_count if latest_packet is not None else 0
        ),
        latest_quote_binary_mismatch_count=(
            latest_packet.quote_binary_mismatch_count if latest_packet is not None else 0
        ),
        latest_quote_semantic_mismatch_count=(
            latest_packet.quote_semantic_mismatch_count if latest_packet is not None else 0
        ),
    )


def get_seller_quote_status_summary(
    *,
    opportunity_id: str,
    org_alias: str | None = None,
    state_dir: str | None = None,
    force_refresh: bool = False,
) -> SellerQuoteStatusResultV1:
    store = DealDeskStore(state_dir)
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    readiness, context = _readiness_and_context(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=crm_org_id,
        force_refresh=force_refresh,
    )
    environment_profile = store.load_quote_environment_profile(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    if environment_profile is None:
        raise RuntimeError(
            f"Deal Desk quote environment profile was not persisted for opportunity {opportunity_id}."
        )

    latest_packet = store.load_latest_reconciliation_packet(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    opportunity_snapshot = _load_opportunity_quote_status_snapshot(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
    )
    config = store.load_effective_config(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        default_loader=load_dealdesk_config,
    )
    stage_name = (
        str(opportunity_snapshot.get("StageName") or "").strip()
        or str((context.original_request or {}).get("StageName") or "").strip()
        or None
    )
    opportunity_amount = _coerce_float_value(
        opportunity_snapshot.get("Amount"),
        (context.original_request or {}).get("Amount"),
        (context.normalized_quote_request or {}).get("amount"),
    )
    quote_intelligence = load_dealdesk_quote_intelligence(
        store.state_dir,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        stage=stage_name,
        amount=opportunity_amount,
    )
    support_status, support_reason, capability_gaps = _seller_quote_support(
        environment_profile=environment_profile,
    )
    evidence = _seller_quote_base_evidence(
        environment_profile=environment_profile,
        stage_name=stage_name,
        opportunity_amount=opportunity_amount,
        quote_intelligence=quote_intelligence,
    )

    if support_status in {"unsupported", "ambiguous"}:
        return SellerQuoteStatusResultV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            context_id=context.context_id,
            lifecycle_state=context.lifecycle_state,
            close_workflow_state=context.close_workflow_state,
            readiness_mode=readiness.readiness_mode,
            detected_engine=environment_profile.detected_engine,
            status=support_status,
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            latest_reconciliation_packet_id=(
                latest_packet.packet_id if latest_packet is not None else context.latest_reconciliation_packet_id
            ),
            latest_quote_integrity_status=(
                latest_packet.quote_integrity_status if latest_packet is not None else "not_available"
            ),
            latest_quote_integrity_summary=(
                latest_packet.quote_integrity_summary if latest_packet is not None else ""
            ),
            evidence=evidence,
            next_step=(
                "Ask RevOps to confirm which quote stack is authoritative before relying on seller-facing quote status in Slack."
                if support_status == "ambiguous"
                else "Use the native quote tool or the control-plane quote-intelligence review surface for this stack."
            ),
        )

    try:
        quote_rows = _load_supported_quote_records(
            opportunity_id=opportunity_id,
            detected_engine=environment_profile.detected_engine,
            org_alias=org_alias,
        )
    except Exception as exc:
        support_reason = str(exc) or "Unable to load supported quote records for the detected quote stack."
        capability_gaps = list(dict.fromkeys([*capability_gaps, support_reason]))
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_query",
                label="Quote Query",
                detail=(
                    "Gremlin could not load supported quote records on the detected quote object: "
                    f"{support_reason}"
                ),
            )
        )
        return SellerQuoteStatusResultV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            context_id=context.context_id,
            lifecycle_state=context.lifecycle_state,
            close_workflow_state=context.close_workflow_state,
            readiness_mode=readiness.readiness_mode,
            detected_engine=environment_profile.detected_engine,
            status="unsupported",
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            matched_approval_route_names=_matched_route_names(quote_intelligence),
            expected_approvers=_expected_quote_approvers(quote_intelligence),
            latest_reconciliation_packet_id=(
                latest_packet.packet_id if latest_packet is not None else context.latest_reconciliation_packet_id
            ),
            latest_quote_integrity_status=(
                latest_packet.quote_integrity_status if latest_packet is not None else "not_available"
            ),
            latest_quote_integrity_summary=(
                latest_packet.quote_integrity_summary if latest_packet is not None else ""
            ),
            evidence=evidence,
            next_step=(
                "Use the native quote tool for this deal until RevOps confirms the supported quote "
                "object shape for this org."
            ),
        )
    if not quote_rows:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_query",
                label="Quote Query",
                detail="No supported quote records were linked to this opportunity on the detected quote object.",
            )
        )
        return SellerQuoteStatusResultV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            context_id=context.context_id,
            lifecycle_state=context.lifecycle_state,
            close_workflow_state=context.close_workflow_state,
            readiness_mode=readiness.readiness_mode,
            detected_engine=environment_profile.detected_engine,
            status="no_quote",
            support_reason="No supported quote was linked to this opportunity.",
            capability_gaps=capability_gaps,
            matched_approval_route_names=_matched_route_names(quote_intelligence),
            expected_approvers=_expected_quote_approvers(quote_intelligence),
            latest_reconciliation_packet_id=(
                latest_packet.packet_id if latest_packet is not None else context.latest_reconciliation_packet_id
            ),
            latest_quote_integrity_status=(
                latest_packet.quote_integrity_status if latest_packet is not None else "not_available"
            ),
            latest_quote_integrity_summary=(
                latest_packet.quote_integrity_summary if latest_packet is not None else ""
            ),
            evidence=evidence,
            next_step=(
                "No supported quote is linked to this deal yet. Open or create the quote in the native quote tool; "
                "Gremlin stays read-only in this slice."
            ),
        )

    selected_quote = _select_quote_record(quote_rows)
    selected_quote_amount = selected_quote.amount if selected_quote is not None else opportunity_amount
    if selected_quote_amount is not None:
        quote_intelligence = load_dealdesk_quote_intelligence(
            store.state_dir,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            stage=stage_name,
            amount=selected_quote_amount,
        )
    live_approval_supported = _seller_quote_live_approval_supported(environment_profile)
    processes: list[_QuoteApprovalProcessSnapshot] = []
    workitems: list[_QuoteApprovalWorkitemSnapshot] = []
    approval_visibility_error: str | None = None
    if live_approval_supported:
        try:
            processes = _load_quote_approval_processes(
                quote_ids=[item.quote_id for item in quote_rows],
                org_alias=org_alias,
            )
        except Exception as exc:
            approval_visibility_error = (
                str(exc) or "Unable to load live approval visibility for the detected quote stack."
            )
            live_approval_supported = False
        else:
            if processes:
                try:
                    workitems = _load_quote_approval_workitems(
                        process_ids=[item.process_id for item in processes],
                        org_alias=org_alias,
                    )
                except Exception as exc:
                    approval_visibility_error = (
                        str(exc) or "Unable to load live approval visibility for the detected quote stack."
                    )
                    live_approval_supported = False
    if approval_visibility_error:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="approval_live",
                label="Approval Visibility",
                detail=(
                    "Gremlin could not load live approval visibility for the selected quote stack: "
                    f"{approval_visibility_error}"
                ),
            )
        )
    approval_state, approval_submitted_at, approval_completed_at, pending_approvers = _quote_approval_state(
        selected_quote=selected_quote,
        processes=processes,
        workitems=workitems,
        quote_intelligence=quote_intelligence,
        live_approval_supported=live_approval_supported,
    )
    stale_reasons = _seller_quote_stale_reasons(
        selected_quote=selected_quote,
        config=config,
    )
    conflict_reasons = _seller_quote_conflict_reasons(
        quote_rows=quote_rows,
        selected_quote=selected_quote,
        latest_packet=latest_packet,
    )
    evidence.extend(_seller_quote_record_evidence(selected_quote=selected_quote, quote_rows=quote_rows))
    evidence.extend(
        _seller_quote_approval_evidence(
            selected_quote=selected_quote,
            processes=processes,
            workitems=workitems,
            quote_intelligence=quote_intelligence,
            live_approval_supported=live_approval_supported,
        )
    )
    evidence.extend(_seller_quote_integrity_evidence(latest_packet=latest_packet))

    status = "partial" if support_status == "partial" or not live_approval_supported else "supported"
    if not live_approval_supported:
        approval_gap_reasons = (
            [
                "Live approval-state visibility is unavailable because Gremlin could not load approval records for this quote stack.",
                approval_visibility_error,
            ]
            if approval_visibility_error
            else [
                "Live approval-state visibility is unavailable because approval objects were not discovered for this quote stack."
            ]
        )
        capability_gaps = list(dict.fromkeys([*capability_gaps, *approval_gap_reasons]))
        if not support_reason:
            support_reason = "Quote status is supported, but live approval-state visibility is not available here."

    return SellerQuoteStatusResultV1(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context_id=context.context_id,
        lifecycle_state=context.lifecycle_state,
        close_workflow_state=context.close_workflow_state,
        readiness_mode=readiness.readiness_mode,
        detected_engine=environment_profile.detected_engine,
        status=status,
        support_reason=support_reason,
        capability_gaps=capability_gaps,
        quote_count=len(quote_rows),
        selected_quote=_quote_record_model(selected_quote) if selected_quote is not None else None,
        additional_quotes=[
            _quote_record_model(item)
            for item in quote_rows
            if selected_quote is None or item.quote_id != selected_quote.quote_id
        ],
        approval_state=approval_state,
        approval_submitted_at=approval_submitted_at,
        approval_completed_at=approval_completed_at,
        matched_approval_route_names=_matched_route_names(quote_intelligence),
        pending_approvers=pending_approvers,
        expected_approvers=_expected_quote_approvers(quote_intelligence),
        stale=bool(stale_reasons),
        stale_reasons=stale_reasons,
        conflict=bool(conflict_reasons),
        conflict_reasons=conflict_reasons,
        latest_reconciliation_packet_id=(
            latest_packet.packet_id if latest_packet is not None else context.latest_reconciliation_packet_id
        ),
        latest_quote_integrity_status=(
            latest_packet.quote_integrity_status if latest_packet is not None else "not_available"
        ),
        latest_quote_integrity_summary=(
            latest_packet.quote_integrity_summary if latest_packet is not None else ""
        ),
        evidence=evidence,
        next_step=_seller_quote_next_step(
            status=status,
            stale_reasons=stale_reasons,
            conflict_reasons=conflict_reasons,
            approval_state=approval_state,
            pending_approvers=pending_approvers,
            expected_approvers=_expected_quote_approvers(quote_intelligence),
            live_approval_supported=live_approval_supported,
        ),
    )


def build_quote_intent_v1(
    *,
    opportunity_id: str,
    operation: QuoteIntentOperation,
    requested_value: str,
    raw_request: str = "",
    org_alias: str | None = None,
) -> QuoteIntentV1:
    normalized_operation = _normalize_quote_intent_operation(operation)
    requested_value_raw = _strip_balanced_quotes(str(requested_value or "").strip())
    if not requested_value_raw:
        raise RuntimeError("Quote preview requires a concrete target value.")
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)

    if normalized_operation == "update_discount_pct":
        discount_pct = _parse_quote_intent_discount_pct(requested_value_raw)
        return QuoteIntentV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            raw_request=str(raw_request or "").strip(),
            operation=normalized_operation,
            semantic_key="discount_pct",
            target_label="Discount %",
            requested_value_raw=requested_value_raw,
            requested_value_display=f"{discount_pct:.2f}%",
            requested_discount_pct=discount_pct,
        )
    if normalized_operation == "update_term_months":
        term_months = _parse_quote_intent_term_months(requested_value_raw)
        return QuoteIntentV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            raw_request=str(raw_request or "").strip(),
            operation=normalized_operation,
            semantic_key="term_months",
            target_label="Term Length",
            requested_value_raw=requested_value_raw,
            requested_value_display=f"{term_months} months",
            requested_term_months=term_months,
        )
    if normalized_operation == "update_payment_terms":
        payment_terms = _normalize_quote_intent_payment_terms(requested_value_raw)
        return QuoteIntentV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            raw_request=str(raw_request or "").strip(),
            operation=normalized_operation,
            semantic_key="payment_terms",
            target_label="Payment Terms",
            requested_value_raw=requested_value_raw,
            requested_value_display=payment_terms,
            requested_payment_terms=payment_terms,
        )
    if normalized_operation in {"add_product", "remove_product", "update_quantity"}:
        payload = _parse_quote_intent_line_item_payload(requested_value_raw)
        product_reference = str(payload.get("product_reference") or "").strip()
        if not product_reference:
            raise RuntimeError("Line-item preview requires an explicit product code, product name, or product id.")
        product_reference_type = _normalize_quote_line_reference_type(
            payload.get("product_reference_type"),
            product_reference,
        )
        quantity_raw = payload.get("quantity")
        quantity = _parse_quote_intent_line_quantity(quantity_raw) if quantity_raw not in (None, "") else None
        if normalized_operation == "add_product" and quantity is None:
            raise RuntimeError("Add-product preview requires an explicit quantity such as `qty 5`.")
        if normalized_operation == "update_quantity":
            if quantity is None:
                raise RuntimeError("Quantity preview requires a concrete quantity such as `to 5`.")
            if quantity <= 0:
                raise RuntimeError("Quantity preview requires a value greater than zero.")
        display_value = _quote_line_intent_display_value(
            operation=normalized_operation,
            product_reference=product_reference,
            quantity=quantity,
        )
        return QuoteIntentV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            raw_request=str(raw_request or "").strip(),
            operation=normalized_operation,
            semantic_key="line_item",
            target_label=_quote_line_intent_target_label(normalized_operation),
            requested_value_raw=requested_value_raw,
            requested_value_display=display_value,
            requested_product_reference=product_reference,
            requested_product_reference_type=product_reference_type,
            requested_quantity=quantity,
        )
    raise RuntimeError(f"Unsupported quote intent operation: {normalized_operation}")


def preview_seller_quote_revision(
    *,
    intent: QuoteIntentV1,
    state_dir: str | None = None,
    force_refresh: bool = False,
) -> SellerQuoteRevisionPreviewV1:
    store = DealDeskStore(state_dir)
    readiness, context = _readiness_and_context(
        opportunity_id=intent.opportunity_id,
        org_alias=intent.org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=intent.crm_org_id,
        force_refresh=force_refresh,
    )
    environment_profile = store.load_quote_environment_profile(
        crm_org_id=intent.crm_org_id,
        org_alias=intent.org_alias,
    )
    if environment_profile is None:
        raise RuntimeError(
            f"Deal Desk quote environment profile was not persisted for opportunity {intent.opportunity_id}."
        )

    quote_status = get_seller_quote_status_summary(
        opportunity_id=intent.opportunity_id,
        org_alias=intent.org_alias,
        state_dir=str(store.state_dir),
        force_refresh=force_refresh,
    )

    if _quote_intent_is_line_item(intent):
        return _preview_seller_quote_line_item_revision(
            intent=intent,
            store=store,
            readiness=readiness,
            context=context,
            environment_profile=environment_profile,
            quote_status=quote_status,
        )

    if quote_status.status in {"unsupported", "ambiguous", "no_quote"} or quote_status.selected_quote is None:
        preview_status: QuotePreviewStatus = (
            "ambiguous"
            if quote_status.status == "ambiguous"
            else "no_quote"
            if quote_status.status == "no_quote"
            else "unsupported"
        )
        return SellerQuoteRevisionPreviewV1(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            context_id=context.context_id,
            status=preview_status,
            detected_engine=quote_status.detected_engine,
            support_reason=quote_status.support_reason,
            capability_gaps=list(quote_status.capability_gaps),
            readiness_mode=readiness.readiness_mode,
            intent=intent,
            selected_quote=quote_status.selected_quote,
            approval_state=quote_status.approval_state,
            preview_readiness_mode=readiness.readiness_mode,
            preview_policy_state="unsupported",
            preview_policy_reasons=[
                *[reason for reason in list(quote_status.conflict_reasons or [])[:2]],
                *[reason for reason in list(quote_status.stale_reasons or [])[:2]],
            ],
            matched_approval_route_names=list(quote_status.matched_approval_route_names),
            recommended_approval_roles=[],
            evidence=list(quote_status.evidence),
            next_step=quote_status.next_step,
        )

    capability_profile = environment_profile.adapter_capability_profile
    if capability_profile is not None and "update_quote" not in set(capability_profile.supported_capabilities or []):
        return SellerQuoteRevisionPreviewV1(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            context_id=context.context_id,
            status="unsupported",
            detected_engine=quote_status.detected_engine,
            support_reason="The detected quote stack does not currently advertise update_quote support for guided quote revision.",
            capability_gaps=list(capability_profile.notes or []),
            readiness_mode=readiness.readiness_mode,
            intent=intent,
            selected_quote=quote_status.selected_quote,
            approval_state=quote_status.approval_state,
            preview_readiness_mode=readiness.readiness_mode,
            preview_policy_state="unsupported",
            preview_policy_reasons=[],
            matched_approval_route_names=list(quote_status.matched_approval_route_names),
            recommended_approval_roles=[],
            evidence=list(quote_status.evidence),
            next_step="Preview is available only for quote stacks that support guided header updates. Use the native quote tool for this stack.",
        )

    field_mapping = _best_quote_header_field_mapping(
        field_mappings=environment_profile.field_mappings,
        semantic_key=intent.semantic_key,
        object_name=quote_status.selected_quote.object_name,
    )
    if field_mapping is None:
        return SellerQuoteRevisionPreviewV1(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            context_id=context.context_id,
            status="unsupported",
            detected_engine=quote_status.detected_engine,
            support_reason=(
                f"Gremlin could not resolve a {intent.target_label.lower()} field on the selected "
                f"{quote_status.selected_quote.object_name} record."
            ),
            capability_gaps=[
                f"No confirmed {intent.semantic_key} field mapping exists on {quote_status.selected_quote.object_name}."
            ],
            readiness_mode=readiness.readiness_mode,
            intent=intent,
            selected_quote=quote_status.selected_quote,
            approval_state=quote_status.approval_state,
            preview_readiness_mode=readiness.readiness_mode,
            preview_policy_state="unsupported",
            preview_policy_reasons=[],
            matched_approval_route_names=list(quote_status.matched_approval_route_names),
            recommended_approval_roles=[],
            evidence=list(quote_status.evidence),
            next_step="Ask RevOps to confirm the quote header field mapping for this org before guided quote revision is enabled.",
        )

    current_value_load_error: str | None = None
    try:
        current_value = _load_quote_header_field_value(
            quote_id=quote_status.selected_quote.quote_id,
            object_name=quote_status.selected_quote.object_name,
            field_name=field_mapping.field_name,
            org_alias=intent.org_alias,
        )
    except Exception as exc:
        current_value = None
        current_value_load_error = str(exc) or "Unable to load the current quote header value."
    field_preview = _quote_field_preview_model(
        intent=intent,
        field_mapping=field_mapping,
        object_name=quote_status.selected_quote.object_name,
        current_value=current_value,
    )

    header_apply_supported, header_apply_support_reason = _quote_header_apply_support(
        capability_profile=capability_profile,
        detected_engine=quote_status.detected_engine,
    )
    capability_gaps = list(quote_status.capability_gaps)
    capability_gaps.extend(
        _quote_header_apply_capability_gaps(
            capability_profile=capability_profile,
            apply_supported=header_apply_supported,
        )
    )

    preview_readiness: QuoteReadinessResult | None = None
    preview_readiness_error: str | None = None
    try:
        preview_readiness = _preview_quote_request_readiness(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            state_dir=str(store.state_dir),
            environment_profile=environment_profile,
            context=context,
            quote_request=_quote_request_from_intent(intent),
            force_refresh=force_refresh,
        )
    except Exception as exc:
        preview_readiness_error = str(exc) or "Preview readiness evaluation was unavailable."

    preview_policy_reasons = _quote_preview_policy_reasons(
        quote_status=quote_status,
        preview_readiness=preview_readiness,
        preview_readiness_error=preview_readiness_error,
    )
    preview_policy_state = _quote_preview_policy_state(
        quote_status=quote_status,
        preview_readiness=preview_readiness,
    )
    evidence = list(quote_status.evidence)
    evidence.extend(
        _quote_preview_evidence(
            intent=intent,
            field_mapping=field_mapping,
            field_preview=field_preview,
            preview_readiness=preview_readiness,
            preview_readiness_error=preview_readiness_error,
            current_value_load_error=current_value_load_error,
        )
    )

    preview = SellerQuoteRevisionPreviewV1(
        opportunity_id=intent.opportunity_id,
        crm_org_id=intent.crm_org_id,
        org_alias=intent.org_alias,
        context_id=context.context_id,
        status="preview_ready",
        detected_engine=quote_status.detected_engine,
        support_reason=quote_status.support_reason,
        capability_gaps=capability_gaps,
        readiness_mode=readiness.readiness_mode,
        intent=intent,
        selected_quote=quote_status.selected_quote,
        field_preview=field_preview,
        approval_state=quote_status.approval_state,
        preview_readiness_mode=(
            preview_readiness.readiness_mode if preview_readiness is not None else readiness.readiness_mode
        ),
        preview_policy_state=preview_policy_state,
        preview_policy_reasons=preview_policy_reasons,
        matched_approval_route_names=list(quote_status.matched_approval_route_names),
        recommended_approval_roles=(
            list(preview_readiness.recommended_approval_roles) if preview_readiness is not None else []
        ),
        apply_supported=header_apply_supported,
        apply_support_reason=header_apply_support_reason,
        evidence=evidence,
        next_step="",
    )
    preview = _with_quote_revision_apply_support(
        preview=preview,
        capability_profile=capability_profile,
    )
    return preview.model_copy(
        update={
            "next_step": _quote_preview_next_step(
                apply_supported=preview.apply_supported,
                preview_policy_state=preview_policy_state,
                quote_status=quote_status,
                preview_readiness=preview_readiness,
            )
        }
    )


def apply_seller_quote_revision(
    *,
    intent: QuoteIntentV1,
    policy: AutonomyPolicy,
    state_dir: str | None = None,
) -> SellerQuoteRevisionApplyResultV1:
    store = DealDeskStore(state_dir)
    preview = preview_seller_quote_revision(
        intent=intent,
        state_dir=str(store.state_dir),
        force_refresh=True,
    )
    if _quote_intent_is_line_item(intent):
        return _apply_seller_quote_line_item_revision(
            intent=intent,
            preview=preview,
            policy=policy,
            store=store,
        )
    if not preview.apply_supported:
        raise RuntimeError(
            preview.apply_support_reason
            or "Guided quote apply is not enabled for this preview."
        )
    if preview.status != "preview_ready" or preview.selected_quote is None or preview.field_preview is None:
        raise RuntimeError(preview.next_step or "Guided quote revision is not available for this request.")
    if preview.preview_policy_state in {"review_required", "unsupported"}:
        raise RuntimeError(preview.next_step or "This quote change is blocked pending RevOps review.")
    if not _quote_is_active_status(preview.selected_quote.status):
        raise RuntimeError("The selected quote is not in a mutable status for guided header revision.")

    current_value = preview.field_preview.current_value
    proposed_value = preview.field_preview.proposed_value
    if _quote_header_values_match(
        semantic_key=preview.field_preview.semantic_key,
        current_value=current_value,
        proposed_value=proposed_value,
    ):
        updated_quote_status = get_seller_quote_status_summary(
            opportunity_id=intent.opportunity_id,
            org_alias=intent.org_alias,
            state_dir=str(store.state_dir),
            force_refresh=True,
        )
        return SellerQuoteRevisionApplyResultV1(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            context_id=preview.context_id,
            intent=intent,
            field_preview=preview.field_preview,
            preview_policy_state=preview.preview_policy_state,
            receipt_outcome="already_set",
            applied=False,
            already_set=True,
            updated_quote_status=updated_quote_status,
        )

    plan = _build_seller_quote_revision_plan(
        preview=preview,
        org_alias=intent.org_alias,
    )
    plan.policy_hash = compute_policy_hash(policy)
    registry = get_default_registry()
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = "dealdesk_seller_quote_revision"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )
    if receipt.outcome == "approval_required":
        try:
            save_seller_quote_revision_approval_context(
                preview=preview,
                run_id=str(pending_run_id or plan.run_id),
                state_dir=str(store.state_dir),
            )
        except Exception:
            # Approval UX context is best-effort; do not fail the pending write if serialization misses.
            pass
    if receipt.outcome == "success":
        _save_seller_quote_revision_event(
            store=store,
            preview=preview,
            intent=intent,
            source_receipt_id=plan.run_id,
            receipt_dir=Path(receipt_dir),
        )
    updated_quote_status = get_seller_quote_status_summary(
        opportunity_id=intent.opportunity_id,
        org_alias=intent.org_alias,
        state_dir=str(store.state_dir),
        force_refresh=True,
    )
    return SellerQuoteRevisionApplyResultV1(
        opportunity_id=intent.opportunity_id,
        crm_org_id=intent.crm_org_id,
        org_alias=intent.org_alias,
        context_id=preview.context_id,
        intent=intent,
        field_preview=preview.field_preview,
        preview_policy_state=preview.preview_policy_state,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        receipt_outcome=receipt.outcome,
        applied=receipt.outcome == "success",
        approval_required=receipt.outcome == "approval_required",
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        updated_quote_status=updated_quote_status,
    )


def save_seller_quote_revision_approval_context(
    *,
    preview: SellerQuoteRevisionPreviewV1,
    run_id: str,
    state_dir: str | None = None,
) -> Path | None:
    if preview.selected_quote is None or (
        preview.field_preview is None and preview.line_item_preview is None
    ):
        return None
    context = SellerQuoteRevisionApprovalContextV1(
        run_id=run_id,
        opportunity_id=preview.opportunity_id,
        crm_org_id=preview.crm_org_id,
        org_alias=preview.org_alias,
        detected_engine=preview.detected_engine,
        intent=preview.intent,
        selected_quote=preview.selected_quote,
        field_preview=preview.field_preview,
        line_item_preview=preview.line_item_preview,
        preview_policy_state=preview.preview_policy_state,
        preview_policy_reasons=list(preview.preview_policy_reasons or []),
        matched_approval_route_names=list(preview.matched_approval_route_names or []),
        recommended_approval_roles=list(preview.recommended_approval_roles or []),
        evidence=list(preview.evidence or []),
    )
    path = _seller_quote_revision_approval_context_path(state_dir=state_dir, run_id=run_id)
    path.parent.mkdir(parents=True, exist_ok=True)
    temp_path = path.with_suffix(".json.tmp")
    temp_path.write_text(
        json.dumps(context.to_dict(), indent=2, sort_keys=True),
        encoding="utf-8",
    )
    temp_path.replace(path)
    return path


def load_seller_quote_revision_approval_context(
    *,
    run_id: str,
    state_dir: str | None = None,
) -> SellerQuoteRevisionApprovalContextV1 | None:
    path = _seller_quote_revision_approval_context_path(state_dir=state_dir, run_id=run_id)
    if not path.exists():
        return None
    try:
        payload = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return None
    if not isinstance(payload, dict):
        return None
    try:
        return SellerQuoteRevisionApprovalContextV1.model_validate(payload)
    except Exception:
        return None


def _apply_seller_quote_line_item_revision(
    *,
    intent: QuoteIntentV1,
    preview: SellerQuoteRevisionPreviewV1,
    policy: AutonomyPolicy,
    store: DealDeskStore,
) -> SellerQuoteRevisionApplyResultV1:
    if not preview.apply_supported:
        raise RuntimeError(
            preview.apply_support_reason
            or "Guided line-item apply is not available for this quote stack or requested operation."
        )
    if preview.status != "preview_ready" or preview.selected_quote is None or preview.line_item_preview is None:
        raise RuntimeError(preview.next_step or "Guided line-item revision is not available for this request.")
    if preview.preview_policy_state in {"review_required", "unsupported"}:
        raise RuntimeError(preview.next_step or "This quote line-item change is blocked pending RevOps review.")
    if not _quote_is_active_status(preview.selected_quote.status):
        raise RuntimeError("The selected quote is not in a mutable status for guided line-item revision.")
    if preview.detected_engine != "standard_quotes":
        raise RuntimeError(
            "Guided line-item apply currently supports Salesforce Standard Quotes only. This quote stack remains preview-only."
        )

    line_item_preview = preview.line_item_preview
    if intent.operation not in {"add_product", "remove_product", "update_quantity"}:
        raise RuntimeError(
            "Guided line-item apply currently supports add-product, remove-product, and quantity updates on standard quotes."
        )
    if str(line_item_preview.line_object_name or "").strip() != "QuoteLineItem":
        raise RuntimeError("Guided line-item apply currently requires Salesforce QuoteLineItem records.")

    current_line = line_item_preview.current_lines[0] if line_item_preview.current_lines else None
    if intent.operation == "remove_product":
        if current_line is None or not str(current_line.line_item_id or "").strip():
            raise RuntimeError("Guided remove-product apply requires an exact current QuoteLineItem match.")
    elif intent.operation == "update_quantity":
        proposed_line = line_item_preview.proposed_line
        if current_line is None or not str(current_line.line_item_id or "").strip() or proposed_line is None:
            raise RuntimeError("Guided quantity updates require an exact current QuoteLineItem match.")
        if _quote_line_quantity_matches(current_line.quantity, proposed_line.quantity):
            updated_quote_status = get_seller_quote_status_summary(
                opportunity_id=intent.opportunity_id,
                org_alias=intent.org_alias,
                state_dir=str(store.state_dir),
                force_refresh=True,
            )
            return SellerQuoteRevisionApplyResultV1(
                opportunity_id=intent.opportunity_id,
                crm_org_id=intent.crm_org_id,
                org_alias=intent.org_alias,
                context_id=preview.context_id,
                intent=intent,
                line_item_preview=line_item_preview,
                preview_policy_state=preview.preview_policy_state,
                receipt_outcome="already_set",
                applied=False,
                already_set=True,
                updated_quote_status=updated_quote_status,
            )
    elif line_item_preview.proposed_line is None or not str(line_item_preview.proposed_line.pricebook_entry_id or "").strip():
        raise RuntimeError("Guided add-product apply requires an exact active PricebookEntry match on the current quote.")

    plan = _build_seller_quote_revision_plan(
        preview=preview,
        org_alias=intent.org_alias,
    )
    plan.policy_hash = compute_policy_hash(policy)
    registry = get_default_registry()
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = "dealdesk_seller_quote_revision"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )
    if receipt.outcome == "approval_required":
        try:
            save_seller_quote_revision_approval_context(
                preview=preview,
                run_id=str(pending_run_id or plan.run_id),
                state_dir=str(store.state_dir),
            )
        except Exception:
            pass
    if receipt.outcome == "success":
        _save_seller_quote_revision_event(
            store=store,
            preview=preview,
            intent=intent,
            source_receipt_id=plan.run_id,
            receipt_dir=Path(receipt_dir),
        )
    updated_quote_status = get_seller_quote_status_summary(
        opportunity_id=intent.opportunity_id,
        org_alias=intent.org_alias,
        state_dir=str(store.state_dir),
        force_refresh=True,
    )
    return SellerQuoteRevisionApplyResultV1(
        opportunity_id=intent.opportunity_id,
        crm_org_id=intent.crm_org_id,
        org_alias=intent.org_alias,
        context_id=preview.context_id,
        intent=intent,
        line_item_preview=line_item_preview,
        preview_policy_state=preview.preview_policy_state,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        receipt_outcome=receipt.outcome,
        applied=receipt.outcome == "success",
        approval_required=receipt.outcome == "approval_required",
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        updated_quote_status=updated_quote_status,
    )


def lookup_seller_active_deals(
    *,
    query: str,
    org_alias: str | None = None,
    limit: int = 5,
) -> SellerDealLookupResultV1:
    normalized_query = _normalize_seller_deal_lookup_query(query)
    if not normalized_query:
        raise RuntimeError("query is required for seller deal lookup.")

    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    candidates, truncated = _lookup_active_opportunity_candidates(
        query=normalized_query,
        org_alias=org_alias,
        limit=max(1, min(int(limit or 5), 10)),
    )
    if len(candidates) == 1:
        status = "resolved"
        resolved_opportunity_id = candidates[0].opportunity_id
    elif candidates:
        status = "multiple_matches"
        resolved_opportunity_id = None
    else:
        status = "not_found"
        resolved_opportunity_id = None
    return SellerDealLookupResultV1(
        query=normalized_query,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        status=status,
        resolved_opportunity_id=resolved_opportunity_id,
        candidate_count=len(candidates),
        truncated=truncated,
        candidates=candidates,
    )


def submit_deal_for_close_review(
    *,
    opportunity_id: str,
    policy: AutonomyPolicy | None = None,
    org_alias: str | None = None,
    state_dir: str | None = None,
    force_refresh: bool = False,
) -> CloseReviewSubmissionV1:
    certification = run_close_certification(
        opportunity_id=opportunity_id,
        entrypoint="submitted_for_close",
        policy=policy,
        org_alias=org_alias,
        state_dir=state_dir,
        force_refresh=force_refresh,
    )
    return CloseReviewSubmissionV1(
        opportunity_id=certification.opportunity_id,
        crm_org_id=certification.crm_org_id,
        org_alias=certification.org_alias,
        context_id=certification.context_id,
        lifecycle_state=certification.lifecycle_state,
        close_workflow_state=certification.close_workflow_state,
        overall_disposition=certification.overall_disposition,
        reconciliation_packet_id=certification.reconciliation_packet_id,
        reconciliation_packet_path=certification.reconciliation_packet_path,
        blocker_count=certification.blocker_count,
        approval_required_count=certification.approval_required_count,
        auto_fixable_count=certification.auto_fixable_count,
        document_evidence_status=certification.document_evidence_status,
        document_candidate_count=certification.document_candidate_count,
        document_contract_candidate_count=certification.document_contract_candidate_count,
        document_summary=certification.document_summary,
        document_extraction_status=certification.document_extraction_status,
        document_evidence_count=certification.document_evidence_count,
        document_comparison_count=certification.document_comparison_count,
        document_discrepancy_count=certification.document_discrepancy_count,
        document_evidence_summary=certification.document_evidence_summary,
        quote_integrity_status=certification.quote_integrity_status,
        quote_integrity_summary=certification.quote_integrity_summary,
        quote_integrity_discrepancy_count=certification.quote_integrity_discrepancy_count,
        quote_fingerprint_count=certification.quote_fingerprint_count,
        quote_binary_mismatch_count=certification.quote_binary_mismatch_count,
        quote_semantic_mismatch_count=certification.quote_semantic_mismatch_count,
        progression_status=certification.progression_status,
        progression_target_stage=certification.progression_target_stage,
        progression_receipt_run_id=certification.progression_receipt_run_id,
        progression_receipt_dir=certification.progression_receipt_dir,
        progression_approval_required=certification.progression_approval_required,
        progression_pending_run_id=certification.progression_pending_run_id,
        progression_pending_plan_path=certification.progression_pending_plan_path,
        post_close_status=certification.post_close_status,
        post_close_trigger_runs=certification.post_close_trigger_runs,
        post_close_approval_required=certification.post_close_approval_required,
        post_close_pending_run_id=certification.post_close_pending_run_id,
        post_close_pending_plan_path=certification.post_close_pending_plan_path,
        submitted_at=str(certification.close_submitted_at or certification.triggered_at),
        next_actions=certification.next_actions,
    )


def run_close_certification(
    *,
    opportunity_id: str,
    entrypoint: CloseCertificationEntrypoint,
    policy: AutonomyPolicy | None = None,
    org_alias: str | None = None,
    state_dir: str | None = None,
    force_refresh: bool = False,
) -> CloseCertificationResultV1:
    store = DealDeskStore(state_dir)
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    normalized_entrypoint = _normalize_close_certification_entrypoint(entrypoint)
    triggered_at = utc_now_iso()
    config = store.load_effective_config(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        default_loader=load_dealdesk_config,
    )
    readiness, context = _readiness_and_context(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=crm_org_id,
        force_refresh=force_refresh,
    )
    document_inventory = inventory_close_documents(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        config=config,
    )
    document_inventory = preflight_close_document_inventory(
        inventory=document_inventory,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
    )
    quote_fingerprints = capture_quote_document_fingerprints(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context=context,
        inventory_candidates=document_inventory.candidates,
        captured_at=triggered_at,
    )
    _persist_quote_document_fingerprints(store=store, fingerprints=quote_fingerprints)
    document_extraction = extract_structured_close_document_evidence(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        config=config,
        inventory=document_inventory,
        state_dir=str(store.state_dir),
    )
    quote_integrity = build_quote_integrity_assessment(
        context=context,
        config=config,
        document_extraction=document_extraction,
        current_fingerprints=quote_fingerprints,
        persisted_fingerprints=store.list_quote_document_fingerprints(
            opportunity_id=opportunity_id,
            quote_id=_active_quote_id(context),
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        ),
    )
    packet = build_reconciliation_packet_from_readiness(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        opportunity_id=opportunity_id,
        readiness=readiness,
        context=context,
        document_inventory=document_inventory,
        document_extraction=document_extraction,
        quote_integrity=quote_integrity,
        block_close_if_missing_documents=bool(config.attachment_rules.block_close_if_missing),
        generated_at=triggered_at,
    )
    packet_path = store.save_reconciliation_packet(packet)
    _apply_close_certification_context(
        context=context,
        packet=packet,
        packet_path=str(packet_path),
        entrypoint=normalized_entrypoint,
        observed_at=triggered_at,
    )
    store.save_context(context)

    event = build_pattern_update_event(
        source_type="close_submission",
        crm_org_id=crm_org_id,
        opportunity_id=opportunity_id,
        source_ref=str(packet_path),
        observed_at=triggered_at,
        raw_record={
            "Id": opportunity_id,
            "close_workflow_state": context.close_workflow_state,
            "entrypoint": normalized_entrypoint,
        },
        extracted_motion_id=context.inferred_motion_id,
        confidence=readiness.overall_confidence,
        outcome=packet.overall_disposition,
        custom={
            "entrypoint": normalized_entrypoint,
            "packet_id": packet.packet_id,
            "blocking_discrepancy_count": packet.blocking_discrepancy_count,
            "approval_required_count": packet.approval_required_count,
            "auto_fixable_count": packet.auto_fixable_count,
            "close_submitted_at": context.close_submitted_at,
            "certification_state": context.close_workflow_state,
        },
        evidence_ids=[opportunity_id, packet.packet_id, normalized_entrypoint],
    )
    save_pattern_update_events(
        store=store,
        events=[event],
        org_alias=org_alias,
        refresh_profile=True,
    )
    progression = _execute_close_progression_after_certification(
        store=store,
        crm_org_id=crm_org_id,
        opportunity_id=opportunity_id,
        packet=packet,
        entrypoint=normalized_entrypoint,
        policy=policy,
        org_alias=org_alias,
        observed_at=triggered_at,
    )
    post_close = _execute_post_close_triggers_after_certification(
        store=store,
        crm_org_id=crm_org_id,
        opportunity_id=opportunity_id,
        packet=packet,
        entrypoint=normalized_entrypoint,
        progression=progression,
        policy=policy,
        org_alias=org_alias,
        observed_at=triggered_at,
    )
    final_context = store.load_context(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    if final_context is None:
        raise RuntimeError(f"Deal Desk context was not persisted for opportunity {opportunity_id}.")

    result = CloseCertificationResultV1(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context_id=final_context.context_id,
        entrypoint=normalized_entrypoint,
        lifecycle_state=final_context.lifecycle_state,
        close_workflow_state=final_context.close_workflow_state,
        overall_disposition=packet.overall_disposition,
        reconciliation_packet_id=packet.packet_id,
        reconciliation_packet_path=str(packet_path),
        blocker_count=packet.blocking_discrepancy_count,
        approval_required_count=packet.approval_required_count,
        auto_fixable_count=packet.auto_fixable_count,
        document_evidence_status=packet.document_evidence_status,
        document_candidate_count=packet.document_candidate_count,
        document_contract_candidate_count=packet.document_contract_candidate_count,
        document_summary=packet.document_summary,
        document_extraction_status=packet.document_extraction_status,
        document_evidence_count=packet.document_evidence_count,
        document_comparison_count=packet.document_comparison_count,
        document_discrepancy_count=packet.document_discrepancy_count,
        document_evidence_summary=packet.document_evidence_summary,
        quote_integrity_status=packet.quote_integrity_status,
        quote_integrity_summary=packet.quote_integrity_summary,
        quote_integrity_discrepancy_count=packet.quote_integrity_discrepancy_count,
        quote_fingerprint_count=packet.quote_fingerprint_count,
        quote_binary_mismatch_count=packet.quote_binary_mismatch_count,
        quote_semantic_mismatch_count=packet.quote_semantic_mismatch_count,
        progression_status=progression.status,
        progression_target_stage=progression.target_stage_name,
        progression_receipt_run_id=progression.receipt_run_id,
        progression_receipt_dir=progression.receipt_dir,
        progression_approval_required=progression.approval_required,
        progression_pending_run_id=progression.pending_run_id,
        progression_pending_plan_path=str(progression.pending_plan_path) if progression.pending_plan_path else None,
        post_close_status=post_close.status,
        post_close_trigger_runs=post_close.trigger_runs,
        post_close_approval_required=post_close.approval_required,
        post_close_pending_run_id=post_close.pending_run_id,
        post_close_pending_plan_path=str(post_close.pending_plan_path) if post_close.pending_plan_path else None,
        triggered_at=triggered_at,
        close_submitted_at=final_context.close_submitted_at,
        next_actions=_next_actions_for_close_certification(
            issues=readiness.issues,
            progression_status=progression.status,
            target_stage_name=progression.target_stage_name,
            document_evidence_status=packet.document_evidence_status,
            document_summary=packet.document_summary,
            document_extraction_status=packet.document_extraction_status,
            document_evidence_summary=packet.document_evidence_summary,
            document_discrepancy_count=packet.document_discrepancy_count,
            quote_integrity_status=packet.quote_integrity_status,
            quote_integrity_summary=packet.quote_integrity_summary,
            quote_integrity_discrepancy_count=packet.quote_integrity_discrepancy_count,
            post_close_status=post_close.status,
            post_close_trigger_runs=post_close.trigger_runs,
        ),
    )
    close_run = _build_close_certification_run(
        result=result,
        packet=packet,
    )
    close_run_path = store.save_close_certification_run(close_run)
    _append_close_certification_run_artifact(
        final_context,
        path=str(close_run_path),
        created_at=triggered_at,
    )
    store.save_context(final_context)
    return result


def _execute_close_progression_after_certification(
    *,
    store: DealDeskStore,
    crm_org_id: str,
    opportunity_id: str,
    packet: ReconciliationPacketV1,
    entrypoint: CloseCertificationEntrypoint,
    policy: AutonomyPolicy | None,
    org_alias: str | None,
    observed_at: str,
) -> _CloseProgressionExecution:
    config = store.load_effective_config(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        default_loader=load_dealdesk_config,
    )
    target_stage_name = str(config.stages.close_won_stage or "Closed Won").strip() or "Closed Won"
    step_mode = str(config.certification_steps.close_progression.mode or "auto").strip().lower() or "auto"

    if packet.overall_disposition != "queued_for_certification":
        return _CloseProgressionExecution(status="not_attempted", target_stage_name=target_stage_name)
    if entrypoint == "closed_won_retro":
        return _CloseProgressionExecution(status="already_closed_won", target_stage_name=target_stage_name)
    if step_mode == "skip":
        return _CloseProgressionExecution(status="skipped", target_stage_name=target_stage_name)
    if step_mode == "auto" and policy is None:
        return _CloseProgressionExecution(status="not_attempted", target_stage_name=target_stage_name)

    before_snapshot = _load_close_progression_snapshot(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
    )
    current_stage_name = str(before_snapshot.get("StageName") or "").strip()
    if current_stage_name.lower() == target_stage_name.lower():
        update_context_for_close_progression(
            store=store,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            opportunity_id=opportunity_id,
            observed_at=observed_at,
            account_id=str(before_snapshot.get("AccountId") or "").strip() or None,
        )
        return _CloseProgressionExecution(status="already_closed_won", target_stage_name=target_stage_name)

    plan = _build_close_progression_plan(
        opportunity_id=opportunity_id,
        target_stage_name=target_stage_name,
        org_alias=org_alias,
    )
    if step_mode == "approve":
        pending_run_id, pending_plan_path = _persist_pending_plan(
            plan=plan,
            state_dir=store.state_dir,
        )
        return _CloseProgressionExecution(
            status="approval_required",
            target_stage_name=target_stage_name,
            approval_required=True,
            pending_run_id=pending_run_id,
            pending_plan_path=pending_plan_path,
        )
    if policy is None:
        return _CloseProgressionExecution(status="not_attempted", target_stage_name=target_stage_name)
    plan.policy_hash = compute_policy_hash(policy)
    registry = get_default_registry()
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = "dealdesk_close_progression"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )

    if receipt.outcome == "success":
        progressed_at = str(receipt.completed_at or observed_at)
        source_ref = str((Path(receipt_dir) / "receipt.json").resolve())
        raw_record = dict(before_snapshot)
        raw_record["Id"] = opportunity_id
        raw_record["StageName"] = target_stage_name
        event = build_pattern_update_event(
            source_type="close_progression",
            crm_org_id=crm_org_id,
            opportunity_id=opportunity_id,
            source_ref=source_ref,
            observed_at=progressed_at,
            source_receipt_id=plan.run_id,
            raw_record=raw_record,
            confidence=0.97,
            outcome="progressed",
            custom={
                "previous_stage_name": current_stage_name or None,
                "target_stage_name": target_stage_name,
            },
            evidence_ids=[opportunity_id, packet.packet_id, plan.run_id],
        )
        save_pattern_update_events(
            store=store,
            events=[event],
            org_alias=org_alias,
            refresh_profile=True,
        )
        update_context_for_close_progression(
            store=store,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            opportunity_id=opportunity_id,
            observed_at=progressed_at,
            receipt_id=plan.run_id,
            account_id=str(before_snapshot.get("AccountId") or "").strip() or None,
        )
        return _CloseProgressionExecution(
            status="progressed",
            target_stage_name=target_stage_name,
            receipt_run_id=plan.run_id,
            receipt_dir=str(receipt_dir),
        )

    if receipt.outcome == "approval_required":
        return _CloseProgressionExecution(
            status="approval_required",
            target_stage_name=target_stage_name,
            receipt_run_id=plan.run_id,
            receipt_dir=str(receipt_dir),
            approval_required=True,
            pending_run_id=pending_run_id,
            pending_plan_path=pending_plan_path,
        )

    return _CloseProgressionExecution(
        status="blocked",
        target_stage_name=target_stage_name,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
    )


def _load_close_progression_snapshot(
    *,
    opportunity_id: str,
    org_alias: str | None,
) -> dict[str, Any]:
    escaped_id = sfdc_helpers.escape_soql_value(opportunity_id)
    rows = sfdc_helpers.run_soql(
        f"SELECT Id, StageName, AccountId FROM Opportunity WHERE Id = '{escaped_id}' LIMIT 1",
        org_alias=org_alias,
    )
    return rows[0] if rows else {}


def _build_close_progression_plan(
    *,
    opportunity_id: str,
    target_stage_name: str,
    org_alias: str | None,
) -> PlanV1:
    run_id = (
        f"dealdesk_close_progress_{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}_{secrets.token_hex(4)}"
    )
    return PlanV1(
        run_id=run_id,
        source=PlanSource(type="close_progression"),
        summary=f"Deal Desk progress {opportunity_id} to {target_stage_name}",
        source_kind="dealdesk_close_progression",
        evidence_ids=[opportunity_id, target_stage_name],
        steps=[
            PlanStep(
                step_id="progress_final_close_stage",
                tool="sfdc.record.update",
                args={
                    "sobject": "Opportunity",
                    "record_id": opportunity_id,
                    "fields": {"StageName": target_stage_name},
                    "org_alias": org_alias,
                },
                risk_level=1,
                idempotency_key=f"dealdesk_close_progression:{opportunity_id}:{target_stage_name}",
                evidence_ids=[opportunity_id, target_stage_name],
            )
        ],
        approvals_required=True,
    )


def _execute_post_close_triggers_after_certification(
    *,
    store: DealDeskStore,
    crm_org_id: str,
    opportunity_id: str,
    packet: ReconciliationPacketV1,
    entrypoint: CloseCertificationEntrypoint,
    progression: _CloseProgressionExecution,
    policy: AutonomyPolicy | None,
    org_alias: str | None,
    observed_at: str,
) -> _PostCloseExecution:
    if packet.overall_disposition != "queued_for_certification":
        return _PostCloseExecution(status="not_attempted", trigger_runs=[])
    if progression.status not in {"progressed", "already_closed_won"}:
        return _PostCloseExecution(status="not_attempted", trigger_runs=[])

    config = store.load_effective_config(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        default_loader=load_dealdesk_config,
    )
    step_mode = str(config.certification_steps.post_close_execution.mode or "auto").strip().lower() or "auto"
    if step_mode == "skip":
        return _PostCloseExecution(status="skipped", trigger_runs=[])
    triggers = build_post_close_trigger_registry(config)
    if not triggers:
        return _PostCloseExecution(status="not_attempted", trigger_runs=[])

    registry = get_default_registry()
    saved_runs: list[PostCloseTriggerRunV1] = []
    overall_status: PostCloseExecutionStatus = "not_attempted"
    approval_required = False
    pending_run_id: str | None = None
    pending_plan_path: Path | None = None
    executed_any = False
    escalated_failure = False

    for trigger in triggers:
        if not trigger.enabled:
            disabled_run = PostCloseTriggerRunV1(
                run_id=_build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="live"),
                trigger_key=trigger.trigger_key,
                trigger_label=trigger.label,
                tool_name=trigger.tool_name,
                opportunity_id=opportunity_id,
                crm_org_id=crm_org_id,
                org_alias=org_alias,
                mode="live",
                status="disabled",
                on_failure=trigger.on_failure,
                blocking=trigger.on_failure == "block",
                observed_at=observed_at,
                notes=["Trigger is disabled in Deal Desk post-close configuration."],
            )
            store.save_post_close_trigger_run(disabled_run)
            saved_runs.append(disabled_run)
            continue

        if not trigger.supported or not trigger.tool_name:
            failed_run = PostCloseTriggerRunV1(
                run_id=_build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="live"),
                trigger_key=trigger.trigger_key,
                trigger_label=trigger.label,
                tool_name=trigger.tool_name,
                opportunity_id=opportunity_id,
                crm_org_id=crm_org_id,
                org_alias=org_alias,
                mode="live",
                status="failed",
                on_failure=trigger.on_failure,
                blocking=trigger.on_failure == "block",
                observed_at=observed_at,
                notes=list(trigger.notes or ["Unsupported post-close trigger."]),
            )
            store.save_post_close_trigger_run(failed_run)
            saved_runs.append(failed_run)
            if trigger.on_failure == "block":
                return _PostCloseExecution(status="failed", trigger_runs=saved_runs)
            escalated_failure = True
            overall_status = "escalated"
            continue

        if trigger.require_preview_before_live and not trigger.preview_approved:
            preview_run = _execute_post_close_trigger_preview(
                store=store,
                registry=registry,
                trigger=trigger,
                crm_org_id=crm_org_id,
                opportunity_id=opportunity_id,
                org_alias=org_alias,
                observed_at=observed_at,
            )
            store.save_post_close_trigger_run(preview_run)
            saved_runs.append(preview_run)
            if preview_run.status == "failed":
                if trigger.on_failure == "block":
                    return _PostCloseExecution(status="failed", trigger_runs=saved_runs)
                escalated_failure = True
                overall_status = "escalated"
            elif preview_run.status != "disabled":
                overall_status = "preview_required"
                if not pending_run_id and str(preview_run.pending_run_id or "").strip():
                    pending_run_id = preview_run.pending_run_id
                if pending_plan_path is None and str(preview_run.pending_plan_path or "").strip():
                    pending_plan_path = Path(str(preview_run.pending_plan_path))
            continue

        if step_mode == "approve":
            approval_run = _stage_post_close_trigger_live_approval(
                store=store,
                registry=registry,
                trigger=trigger,
                crm_org_id=crm_org_id,
                opportunity_id=opportunity_id,
                org_alias=org_alias,
                observed_at=observed_at,
            )
            store.save_post_close_trigger_run(approval_run)
            saved_runs.append(approval_run)
            return _PostCloseExecution(
                status="approval_required",
                trigger_runs=saved_runs,
                approval_required=True,
                pending_run_id=approval_run.pending_run_id,
                pending_plan_path=Path(approval_run.pending_plan_path) if approval_run.pending_plan_path else None,
            )

        live_run = _execute_post_close_trigger_live(
            store=store,
            registry=registry,
            trigger=trigger,
            crm_org_id=crm_org_id,
            opportunity_id=opportunity_id,
            org_alias=org_alias,
            policy=policy,
            observed_at=observed_at,
        )
        store.save_post_close_trigger_run(live_run)
        saved_runs.append(live_run)

        if live_run.status == "approval_required":
            return _PostCloseExecution(
                status="approval_required",
                trigger_runs=saved_runs,
                approval_required=True,
                pending_run_id=live_run.pending_run_id,
                pending_plan_path=Path(live_run.pending_plan_path) if live_run.pending_plan_path else None,
            )
        if live_run.status == "failed":
            if trigger.on_failure == "block":
                return _PostCloseExecution(status="failed", trigger_runs=saved_runs)
            escalated_failure = True
            overall_status = "escalated"
            continue
        if live_run.status == "executed":
            executed_any = True
            if overall_status == "not_attempted":
                overall_status = "executed"

    if overall_status == "preview_required":
        return _PostCloseExecution(
            status="preview_required",
            trigger_runs=saved_runs,
            pending_run_id=pending_run_id,
            pending_plan_path=pending_plan_path,
        )
    if escalated_failure:
        return _PostCloseExecution(status="escalated", trigger_runs=saved_runs)
    if executed_any:
        return _PostCloseExecution(status="executed", trigger_runs=saved_runs)
    return _PostCloseExecution(status="not_attempted", trigger_runs=saved_runs)


def _execute_post_close_trigger_preview(
    *,
    store: DealDeskStore,
    registry,
    trigger: PostCloseTriggerV1,
    crm_org_id: str,
    opportunity_id: str,
    org_alias: str | None,
    observed_at: str,
) -> PostCloseTriggerRunV1:
    run_id = _build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="preview")
    tool_def = registry.get_tool(trigger.tool_name)
    handler = registry.get_handler(trigger.tool_name)
    if handler is None:
        return PostCloseTriggerRunV1(
            run_id=run_id,
            trigger_key=trigger.trigger_key,
            trigger_label=trigger.label,
            tool_name=trigger.tool_name,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            mode="preview",
            status="failed",
            on_failure=trigger.on_failure,
            blocking=trigger.on_failure == "block",
            observed_at=observed_at,
            notes=[f"No handler is registered for {trigger.tool_name}."],
        )

    step = PlanStep(
        step_id=f"post_close_preview_{trigger.trigger_key}",
        tool=trigger.tool_name,
        args={
            "record_ids": [opportunity_id],
            "source_opp_id": opportunity_id,
            "org_alias": org_alias,
            "crm_org_id": crm_org_id,
            "state_dir": str(store.state_dir),
            "run_id": run_id,
            "preview_only": True,
        },
        risk_level=0,
        evidence_ids=[opportunity_id, trigger.trigger_key, "preview"],
    )
    try:
        result = handler(step, tool_def)
    except Exception as exc:
        return PostCloseTriggerRunV1(
            run_id=run_id,
            trigger_key=trigger.trigger_key,
            trigger_label=trigger.label,
            tool_name=trigger.tool_name,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            mode="preview",
            status="failed",
            on_failure=trigger.on_failure,
            blocking=trigger.on_failure == "block",
            observed_at=observed_at,
            notes=[str(exc)],
        )

    after_payload = result.get("after") if isinstance(result, dict) and isinstance(result.get("after"), dict) else {}
    before_payload = result.get("before") if isinstance(result, dict) and isinstance(result.get("before"), dict) else {}
    result_status = str(after_payload.get("status") or "preview").strip() or "preview"
    run_status: Literal["preview_generated", "disabled"] = (
        "disabled" if result_status == "disabled" else "preview_generated"
    )
    notes = []
    pending_run_id: str | None = None
    pending_plan_path: Path | None = None
    if run_status == "preview_generated":
        live_plan = _build_post_close_trigger_plan(
            trigger=trigger,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            run_id=_build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="live"),
            state_dir=store.state_dir,
            registry=registry,
        )
        pending_run_id, pending_plan_path = _persist_pending_plan(
            plan=live_plan,
            state_dir=store.state_dir,
        )
        notes.append(
            "Preview generated. Approve preview in Deal Desk config before live execution."
        )
    return PostCloseTriggerRunV1(
        run_id=run_id,
        trigger_key=trigger.trigger_key,
        trigger_label=trigger.label,
        tool_name=trigger.tool_name,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        mode="preview",
        status=run_status,
        on_failure=trigger.on_failure,
        blocking=trigger.on_failure == "block",
        observed_at=observed_at,
        result_status=result_status,
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        target_ids=[str(target) for target in result.get("targets", []) if str(target or "").strip()],
        before=before_payload,
        after=after_payload,
        notes=notes,
    )


def _stage_post_close_trigger_live_approval(
    *,
    store: DealDeskStore,
    registry,
    trigger: PostCloseTriggerV1,
    crm_org_id: str,
    opportunity_id: str,
    org_alias: str | None,
    observed_at: str,
) -> PostCloseTriggerRunV1:
    staged_preview_run = _find_latest_pending_post_close_preview_run(
        store=store,
        trigger_key=trigger.trigger_key,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    plan = _load_staged_pending_plan(
        pending_plan_path=(
            str(staged_preview_run.pending_plan_path or "").strip()
            if staged_preview_run is not None
            else None
        ),
    )
    if plan is None:
        run_id = _build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="live")
        plan = _build_post_close_trigger_plan(
            trigger=trigger,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            run_id=run_id,
            state_dir=store.state_dir,
            registry=registry,
        )
    else:
        run_id = plan.run_id
    pending_run_id, pending_plan_path = _persist_pending_plan(
        plan=plan,
        state_dir=store.state_dir,
    )
    existing_live_run = store.load_post_close_trigger_run(
        run_id=run_id,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    if (
        existing_live_run is not None
        and existing_live_run.mode == "live"
        and existing_live_run.status == "approval_required"
    ):
        return existing_live_run
    notes = ["Post-close execution step is set to approve. Operator approval is required before live execution."]
    if staged_preview_run is not None and staged_preview_run.pending_plan_path:
        notes.append(
            f"Reusing staged pending plan from preview run {staged_preview_run.run_id}."
        )
    return PostCloseTriggerRunV1(
        run_id=run_id,
        trigger_key=trigger.trigger_key,
        trigger_label=trigger.label,
        tool_name=trigger.tool_name,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        mode="live",
        status="approval_required",
        on_failure=trigger.on_failure,
        blocking=trigger.on_failure == "block",
        observed_at=observed_at,
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        notes=notes,
    )


def _execute_post_close_trigger_live(
    *,
    store: DealDeskStore,
    registry,
    trigger: PostCloseTriggerV1,
    crm_org_id: str,
    opportunity_id: str,
    org_alias: str | None,
    policy: AutonomyPolicy | None,
    observed_at: str,
) -> PostCloseTriggerRunV1:
    run_id = _build_post_close_trigger_run_id(trigger_key=trigger.trigger_key, mode="live")
    if policy is None:
        return PostCloseTriggerRunV1(
            run_id=run_id,
            trigger_key=trigger.trigger_key,
            trigger_label=trigger.label,
            tool_name=trigger.tool_name,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            mode="live",
            status="skipped",
            on_failure=trigger.on_failure,
            blocking=trigger.on_failure == "block",
            observed_at=observed_at,
            notes=["Live post-close execution requires a policy."],
        )

    staged_preview_run = _find_latest_pending_post_close_preview_run(
        store=store,
        trigger_key=trigger.trigger_key,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    plan = _load_staged_pending_plan(
        pending_plan_path=(
            str(staged_preview_run.pending_plan_path or "").strip()
            if staged_preview_run is not None
            else None
        ),
    )
    if plan is None:
        plan = _build_post_close_trigger_plan(
            trigger=trigger,
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            run_id=run_id,
            state_dir=store.state_dir,
            registry=registry,
        )
    else:
        run_id = plan.run_id
    plan.policy_hash = compute_policy_hash(policy)
    existing_live_run = store.load_post_close_trigger_run(
        run_id=run_id,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    if existing_live_run is not None and existing_live_run.mode == "live":
        return existing_live_run
    existing_receipt_dir = _receipt_dir_for_run(store.state_dir, run_id)
    if existing_receipt_dir is not None:
        return _build_post_close_trigger_run_from_existing_receipt(
            store=store,
            trigger=trigger,
            plan=plan,
            crm_org_id=crm_org_id,
            opportunity_id=opportunity_id,
            org_alias=org_alias,
            observed_at=observed_at,
            receipt_dir=existing_receipt_dir,
        )
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = f"dealdesk_post_close_trigger:{trigger.trigger_key}"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )

    change = receipt.changes[0] if receipt.changes else None
    before_payload = change.before if change is not None and isinstance(change.before, dict) else {}
    after_payload = change.after if change is not None and isinstance(change.after, dict) else {}
    targets = [str(target) for target in (change.targets if change is not None else []) if str(target or "").strip()]
    result_status = str(after_payload.get("status") or receipt.outcome).strip() or receipt.outcome
    run_status = _live_post_close_trigger_status(receipt_outcome=receipt.outcome, result_status=result_status)

    if receipt.outcome == "success" and run_status == "executed":
        _save_post_close_trigger_event(
            store=store,
            trigger=trigger,
            crm_org_id=crm_org_id,
            opportunity_id=opportunity_id,
            org_alias=org_alias,
            observed_at=str(receipt.completed_at or observed_at),
            source_ref=str((Path(receipt_dir) / "receipt.json").resolve()),
            source_receipt_id=plan.run_id,
            result_status=result_status,
            target_ids=targets,
        )

    notes: list[str] = []
    if run_status == "approval_required":
        notes.append("Approval is required before this post-close trigger can execute.")
    elif run_status == "failed":
        notes.append(f"Post-close trigger returned receipt outcome {receipt.outcome}.")

    return PostCloseTriggerRunV1(
        run_id=run_id,
        trigger_key=trigger.trigger_key,
        trigger_label=trigger.label,
        tool_name=trigger.tool_name,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        mode="live",
        status=run_status,
        on_failure=trigger.on_failure,
        blocking=trigger.on_failure == "block",
        observed_at=str(receipt.completed_at or observed_at),
        result_status=result_status,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        target_ids=targets,
        before=before_payload,
        after=after_payload,
        notes=notes,
    )


def _build_post_close_trigger_plan(
    *,
    trigger: PostCloseTriggerV1,
    opportunity_id: str,
    crm_org_id: str,
    org_alias: str | None,
    run_id: str,
    state_dir: Path,
    registry,
) -> PlanV1:
    tool_def = registry.get_tool(trigger.tool_name)
    risk_level = int(getattr(tool_def, "risk_level", 2) or 2)
    return PlanV1(
        run_id=run_id,
        source=PlanSource(type="post_close_trigger"),
        summary=f"Deal Desk post-close trigger {trigger.label} for {opportunity_id}",
        source_kind="dealdesk_post_close_trigger",
        evidence_ids=[opportunity_id, trigger.trigger_key, crm_org_id],
        steps=[
            PlanStep(
                step_id=f"post_close_{trigger.trigger_key}",
                tool=trigger.tool_name,
                args={
                    "record_ids": [opportunity_id],
                    "source_opp_id": opportunity_id,
                    "org_alias": org_alias,
                    "crm_org_id": crm_org_id,
                    "state_dir": str(state_dir),
                    "run_id": run_id,
                    "preview_only": False,
                },
                risk_level=risk_level,
                idempotency_key=f"dealdesk_post_close_trigger:{trigger.trigger_key}:{opportunity_id}",
                evidence_ids=[opportunity_id, trigger.trigger_key],
            )
        ],
        approvals_required=True,
    )


def _save_post_close_trigger_event(
    *,
    store: DealDeskStore,
    trigger: PostCloseTriggerV1,
    crm_org_id: str,
    opportunity_id: str,
    org_alias: str | None,
    observed_at: str,
    source_ref: str,
    source_receipt_id: str,
    result_status: str,
    target_ids: list[str],
) -> None:
    event = build_pattern_update_event(
        source_type="post_close_trigger",
        crm_org_id=crm_org_id,
        opportunity_id=opportunity_id,
        source_ref=source_ref,
        observed_at=observed_at,
        source_receipt_id=source_receipt_id,
        raw_record={"Id": opportunity_id, "trigger_key": trigger.trigger_key, "status": result_status},
        confidence=0.96,
        outcome=result_status,
        custom={
            "trigger_key": trigger.trigger_key,
            "trigger_label": trigger.label,
            "tool_name": trigger.tool_name,
            "status": result_status,
        },
        evidence_ids=[opportunity_id, source_receipt_id, *target_ids],
    )
    save_pattern_update_events(
        store=store,
        events=[event],
        org_alias=org_alias,
        refresh_profile=True,
    )


def _live_post_close_trigger_status(
    *,
    receipt_outcome: str,
    result_status: str,
) -> Literal["executed", "approval_required", "disabled", "failed"]:
    if receipt_outcome == "approval_required":
        return "approval_required"
    if receipt_outcome != "success":
        return "failed"
    normalized_result = str(result_status or "").strip().lower()
    if normalized_result == "disabled":
        return "disabled"
    return "executed"


def _build_post_close_trigger_run_id(
    *,
    trigger_key: str,
    mode: Literal["preview", "live"],
) -> str:
    return (
        f"dealdesk_post_close_{trigger_key}_{mode}_"
        f"{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}_{secrets.token_hex(4)}"
    )


def _next_actions_for_close_certification(
    *,
    issues: list[ReadinessIssue],
    progression_status: CloseProgressionStatus,
    target_stage_name: str | None,
    document_evidence_status: str,
    document_summary: str,
    document_extraction_status: str,
    document_evidence_summary: str,
    document_discrepancy_count: int,
    quote_integrity_status: str,
    quote_integrity_summary: str,
    quote_integrity_discrepancy_count: int,
    post_close_status: PostCloseExecutionStatus,
    post_close_trigger_runs: list[PostCloseTriggerRunV1],
) -> list[SellerActionHintV1]:
    if progression_status == "approval_required":
        return [
            SellerActionHintV1(
                action_key="await_close_approval",
                label="Await approval",
                detail=(
                    f"Final close progression to {target_stage_name or 'Closed Won'} "
                    "is pending RevOps approval."
                ),
            )
        ]
    if progression_status == "blocked":
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail="Close certification passed, but final close progression did not execute automatically.",
            )
        ]
    if progression_status == "skipped":
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail="Close certification passed, but final close progression is set to skip in Deal Desk config.",
            )
        ]
    if str(document_evidence_status or "").strip() in {"missing", "ambiguous"}:
        detail = document_summary or "Close evidence needs review before final close."
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    if str(document_extraction_status or "").strip() in {"unsupported", "partial"} or int(document_discrepancy_count or 0) > 0:
        detail = document_evidence_summary or "Structured document evidence needs RevOps review before final close."
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    if str(quote_integrity_status or "").strip() in {"review_required", "blocked"} or int(quote_integrity_discrepancy_count or 0) > 0:
        detail = quote_integrity_summary or "Quote integrity verification requires Finance and RevOps review before final close."
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    if post_close_status == "approval_required":
        pending_run_id = next(
            (
                str(run.pending_run_id or "").strip()
                for run in post_close_trigger_runs
                if run.status == "approval_required" and str(run.pending_run_id or "").strip()
            ),
            "",
        )
        detail = "A post-close trigger is pending RevOps approval."
        if pending_run_id:
            detail = f"Post-close execution is pending RevOps approval as run {pending_run_id}."
        return [
            SellerActionHintV1(
                action_key="await_post_close_approval",
                label="Await approval",
                detail=detail,
            )
        ]
    if post_close_status == "preview_required":
        preview_trigger = next(
            (run.trigger_label for run in post_close_trigger_runs if run.status == "preview_generated"),
            "the next post-close trigger",
        )
        return [
            SellerActionHintV1(
                action_key="review_post_close_preview",
                label="Ask RevOps",
                detail=f"{preview_trigger} preview is ready. RevOps must approve live execution in config.",
            )
        ]
    if post_close_status in {"failed", "escalated"}:
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail="A post-close trigger did not complete automatically.",
            )
        ]
    if progression_status in {"progressed", "already_closed_won"}:
        return []
    if not issues:
        return []
    return _next_actions_for_issues(issues)


def _next_actions_for_latest_close_review(
    packet: ReconciliationPacketV1 | None,
) -> list[SellerActionHintV1]:
    if packet is None:
        return []
    if str(packet.document_evidence_status or "").strip() in {"missing", "ambiguous"}:
        detail = packet.document_summary or "Close evidence needs review before final close."
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    if (
        str(packet.document_extraction_status or "").strip() in {"unsupported", "partial"}
        or int(packet.document_discrepancy_count or 0) > 0
    ):
        detail = (
            packet.document_evidence_summary
            or "Structured document evidence needs RevOps review before final close."
        )
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    if (
        str(packet.quote_integrity_status or "").strip() in {"review_required", "blocked"}
        or int(packet.quote_integrity_discrepancy_count or 0) > 0
    ):
        detail = (
            packet.quote_integrity_summary
            or "Quote integrity verification requires Finance and RevOps review before final close."
        )
        return [
            SellerActionHintV1(
                action_key="route_revops",
                label="Ask RevOps",
                detail=detail,
            )
        ]
    return []


def apply_seller_missing_field_fix(
    *,
    opportunity_id: str,
    field_name: str,
    field_value: str,
    policy: AutonomyPolicy,
    org_alias: str | None = None,
    state_dir: str | None = None,
) -> SellerFieldFixResultV1:
    normalized_field_name = str(field_name or "").strip()
    raw_field_value = str(field_value or "").strip()
    if not normalized_field_name:
        raise RuntimeError("field_name is required for seller field fixes.")
    if not raw_field_value:
        raise RuntimeError("field_value is required for seller field fixes.")

    store = DealDeskStore(state_dir)
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    readiness, context = _readiness_and_context(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=crm_org_id,
        force_refresh=True,
    )
    issue = _find_fixable_missing_field_issue(readiness.issues, normalized_field_name)
    if issue is None:
        raise RuntimeError(
            f"{normalized_field_name} is not currently an eligible missing-field blocker on opportunity {opportunity_id}."
        )

    field_meta = _load_opportunity_field_meta(normalized_field_name, org_alias=org_alias)
    coerced_value = _coerce_seller_field_value(field_meta, raw_field_value)
    current_value = _load_current_opportunity_field_value(
        opportunity_id=opportunity_id,
        field_name=normalized_field_name,
        org_alias=org_alias,
    )
    if _seller_field_values_match(field_meta, current_value, coerced_value):
        updated_summary = get_seller_deal_health_summary(
            opportunity_id=opportunity_id,
            org_alias=org_alias,
            state_dir=str(store.state_dir),
            force_refresh=True,
        )
        return SellerFieldFixResultV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            context_id=context.context_id,
            field_name=normalized_field_name,
            field_value=coerced_value,
            receipt_outcome="already_set",
            applied=False,
            already_set=True,
            current_value=current_value,
            lifecycle_state=updated_summary.lifecycle_state,
            close_workflow_state=updated_summary.close_workflow_state,
            updated_summary=updated_summary,
        )

    plan = _build_seller_field_fix_plan(
        opportunity_id=opportunity_id,
        field_name=normalized_field_name,
        field_value=coerced_value,
        org_alias=org_alias,
    )
    plan.policy_hash = compute_policy_hash(policy)
    registry = get_default_registry()
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = "dealdesk_seller_field_fix"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )
    updated_summary = get_seller_deal_health_summary(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        force_refresh=True,
    )
    return SellerFieldFixResultV1(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context_id=context.context_id,
        field_name=normalized_field_name,
        field_value=coerced_value,
        current_value=current_value,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        receipt_outcome=receipt.outcome,
        applied=receipt.outcome == "success",
        approval_required=receipt.outcome == "approval_required",
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        lifecycle_state=updated_summary.lifecycle_state,
        close_workflow_state=updated_summary.close_workflow_state,
        updated_summary=updated_summary,
    )


def apply_seller_contact_role_add(
    *,
    opportunity_id: str,
    contact_reference: str,
    role_name: str,
    policy: AutonomyPolicy,
    org_alias: str | None = None,
    state_dir: str | None = None,
) -> SellerContactRoleResultV1:
    normalized_contact_reference = str(contact_reference or "").strip()
    normalized_role_name = _strip_balanced_quotes(str(role_name or "").strip())
    if not normalized_contact_reference:
        raise RuntimeError("contact_reference is required for seller contact adds.")
    if not normalized_role_name:
        raise RuntimeError("role_name is required for seller contact adds.")

    store = DealDeskStore(state_dir)
    crm_org_id = resolve_crm_org_id(org_alias=org_alias)
    readiness, context = _readiness_and_context(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        crm_org_id=crm_org_id,
        force_refresh=True,
    )
    issue = _find_primary_contact_issue(readiness.issues)
    if issue is None:
        raise RuntimeError(
            f"A primary-contact blocker is not currently active on opportunity {opportunity_id}."
        )

    primary_contact_field_name = str(issue.field_name or "").strip()
    if not primary_contact_field_name:
        raise RuntimeError(
            "The active primary-contact blocker does not expose an Opportunity contact field. Route this to RevOps."
        )

    field_meta = _load_primary_contact_field_meta(primary_contact_field_name, org_alias=org_alias)
    contact = _resolve_seller_contact_reference(
        contact_reference=normalized_contact_reference,
        org_alias=org_alias,
    )
    opportunity_state = _load_opportunity_primary_contact_state(
        opportunity_id=opportunity_id,
        primary_contact_field_name=primary_contact_field_name,
        org_alias=org_alias,
    )
    _validate_contact_account_alignment(
        opportunity_state=opportunity_state,
        contact=contact,
        opportunity_id=opportunity_id,
    )
    normalized_role_name = _coerce_opportunity_contact_role(
        role_name=normalized_role_name,
        org_alias=org_alias,
    )

    contact_id = str(contact.get("Id") or "").strip()
    if not contact_id:
        raise RuntimeError("Resolved contact did not include an Id.")
    contact_email = str(contact.get("Email") or "").strip() or None
    current_primary_contact_id = str(opportunity_state.get(primary_contact_field_name) or "").strip() or None
    existing_roles = _load_existing_opportunity_contact_roles(
        opportunity_id=opportunity_id,
        contact_id=contact_id,
        org_alias=org_alias,
    )

    conflicting_role = _find_conflicting_contact_role(existing_roles, normalized_role_name)
    if conflicting_role is not None:
        raise RuntimeError(
            f"Contact {contact_id} is already attached to {opportunity_id} with role "
            f"{conflicting_role!r}; changing existing contact roles is outside this seller path."
        )

    role_already_attached = _has_matching_contact_role(existing_roles, normalized_role_name)
    primary_already_set = _seller_field_values_match(field_meta, current_primary_contact_id, contact_id)
    if role_already_attached and primary_already_set:
        updated_summary = get_seller_deal_health_summary(
            opportunity_id=opportunity_id,
            org_alias=org_alias,
            state_dir=str(store.state_dir),
            force_refresh=True,
        )
        return SellerContactRoleResultV1(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
            context_id=context.context_id,
            contact_reference=normalized_contact_reference,
            contact_id=contact_id,
            contact_email=contact_email,
            role_name=normalized_role_name,
            primary_contact_field_name=primary_contact_field_name,
            receipt_outcome="already_set",
            applied=False,
            already_set=True,
            current_primary_contact_id=current_primary_contact_id,
            lifecycle_state=updated_summary.lifecycle_state,
            close_workflow_state=updated_summary.close_workflow_state,
            updated_summary=updated_summary,
        )

    plan = _build_seller_contact_role_plan(
        opportunity_id=opportunity_id,
        contact_id=contact_id,
        role_name=normalized_role_name,
        primary_contact_field_name=primary_contact_field_name,
        create_contact_role=not role_already_attached,
        update_primary_contact=not primary_already_set,
        org_alias=org_alias,
    )
    plan.policy_hash = compute_policy_hash(policy)
    registry = get_default_registry()
    executor = PlanExecutor(policy=policy, registry=registry, state_dir=store.state_dir)
    receipt = executor.execute(plan)
    receipt.source_kind = "dealdesk_seller_contact_role_add"
    writer = ReceiptWriter(store.state_dir)
    receipt_dir = writer.write(receipt, plan)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )
    updated_summary = get_seller_deal_health_summary(
        opportunity_id=opportunity_id,
        org_alias=org_alias,
        state_dir=str(store.state_dir),
        force_refresh=True,
    )
    return SellerContactRoleResultV1(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        context_id=context.context_id,
        contact_reference=normalized_contact_reference,
        contact_id=contact_id,
        contact_email=contact_email,
        role_name=normalized_role_name,
        primary_contact_field_name=primary_contact_field_name,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        receipt_outcome=receipt.outcome,
        applied=receipt.outcome == "success",
        approval_required=receipt.outcome == "approval_required",
        current_primary_contact_id=current_primary_contact_id,
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        lifecycle_state=updated_summary.lifecycle_state,
        close_workflow_state=updated_summary.close_workflow_state,
        updated_summary=updated_summary,
    )


def _persist_pending_plan_if_approval_required(
    *,
    plan: PlanV1,
    receipt_outcome: str,
    state_dir: Path,
) -> tuple[str | None, Path | None]:
    if receipt_outcome != "approval_required":
        return None, None
    return _persist_pending_plan(plan=plan, state_dir=state_dir)


def _persist_pending_plan(
    *,
    plan: PlanV1,
    state_dir: Path,
) -> tuple[str, Path]:
    existing = _find_existing_pending_plan(
        plan=plan,
        state_dir=state_dir,
    )
    if existing is not None:
        return existing
    pending_dir = Path(state_dir) / "pending" / plan.run_id
    pending_dir.mkdir(parents=True, exist_ok=True)
    pending_plan_path = pending_dir / "plan.json"
    pending_plan_path.write_text(json.dumps(plan.to_dict(), indent=2), encoding="utf-8")
    return plan.run_id, pending_plan_path


def _find_existing_pending_plan(
    *,
    plan: PlanV1,
    state_dir: Path,
) -> tuple[str, Path] | None:
    pending_root = Path(state_dir) / "pending"
    if not pending_root.exists():
        return None
    for candidate_path in sorted(pending_root.glob("*/plan.json")):
        try:
            payload = json.loads(candidate_path.read_text(encoding="utf-8"))
        except Exception:
            continue
        if not isinstance(payload, dict):
            continue
        try:
            candidate_plan = PlanV1.from_dict(payload)
        except Exception:
            continue
        if str(candidate_plan.plan_hash or "").strip() != str(plan.plan_hash or "").strip():
            continue
        if str(candidate_plan.policy_hash or "").strip() != str(plan.policy_hash or "").strip():
            continue
        return candidate_plan.run_id, candidate_path
    return None


def _load_staged_pending_plan(*, pending_plan_path: str | None) -> PlanV1 | None:
    raw_path = str(pending_plan_path or "").strip()
    if not raw_path:
        return None
    path = Path(raw_path)
    if not path.exists():
        return None
    try:
        payload = json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return None
    if not isinstance(payload, dict):
        return None
    try:
        return PlanV1.from_dict(payload)
    except Exception:
        return None


def _receipt_dir_for_run(state_dir: Path, run_id: str) -> Path | None:
    normalized_run_id = str(run_id or "").strip()
    if not normalized_run_id:
        return None
    receipt_dir = Path(state_dir) / "receipts" / normalized_run_id
    receipt_path = receipt_dir / "receipt.json"
    if not receipt_path.exists():
        return None
    return receipt_dir


def _build_post_close_trigger_run_from_existing_receipt(
    *,
    store: DealDeskStore,
    trigger: PostCloseTriggerV1,
    plan: PlanV1,
    crm_org_id: str,
    opportunity_id: str,
    org_alias: str | None,
    observed_at: str,
    receipt_dir: Path,
) -> PostCloseTriggerRunV1:
    receipt = load_receipt(store.state_dir, plan.run_id)
    pending_run_id, pending_plan_path = _persist_pending_plan_if_approval_required(
        plan=plan,
        receipt_outcome=receipt.outcome,
        state_dir=store.state_dir,
    )
    change = receipt.changes[0] if receipt.changes else None
    before_payload = change.before if change is not None and isinstance(change.before, dict) else {}
    after_payload = change.after if change is not None and isinstance(change.after, dict) else {}
    targets = [str(target) for target in (change.targets if change is not None else []) if str(target or "").strip()]
    result_status = str(after_payload.get("status") or receipt.outcome).strip() or receipt.outcome
    run_status = _live_post_close_trigger_status(receipt_outcome=receipt.outcome, result_status=result_status)
    notes: list[str] = []
    if run_status == "approval_required":
        notes.append("Approval is required before this post-close trigger can execute.")
    elif run_status == "failed":
        notes.append(f"Post-close trigger returned receipt outcome {receipt.outcome}.")
    else:
        notes.append("Using the existing receipt for a previously executed staged post-close plan.")
    return PostCloseTriggerRunV1(
        run_id=plan.run_id,
        trigger_key=trigger.trigger_key,
        trigger_label=trigger.label,
        tool_name=trigger.tool_name,
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        mode="live",
        status=run_status,
        on_failure=trigger.on_failure,
        blocking=trigger.on_failure == "block",
        observed_at=str(receipt.completed_at or observed_at),
        result_status=result_status,
        receipt_run_id=plan.run_id,
        receipt_dir=str(receipt_dir),
        pending_run_id=pending_run_id,
        pending_plan_path=str(pending_plan_path) if pending_plan_path is not None else None,
        target_ids=targets,
        before=before_payload,
        after=after_payload,
        notes=notes,
    )


def _find_latest_pending_post_close_preview_run(
    *,
    store: DealDeskStore,
    trigger_key: str,
    opportunity_id: str,
    crm_org_id: str,
    org_alias: str | None,
) -> PostCloseTriggerRunV1 | None:
    candidates = [
        item
        for item in store.list_post_close_trigger_runs(
            opportunity_id=opportunity_id,
            crm_org_id=crm_org_id,
            org_alias=org_alias,
        )
        if item.mode == "preview"
        and item.status == "preview_generated"
        and item.trigger_key == trigger_key
        and (str(item.pending_run_id or "").strip() or str(item.pending_plan_path or "").strip())
    ]
    if not candidates:
        return None
    return max(candidates, key=lambda item: str(item.observed_at or ""))


def _readiness_and_context(
    *,
    opportunity_id: str,
    org_alias: str | None,
    state_dir: str,
    crm_org_id: str,
    force_refresh: bool,
) -> tuple[QuoteReadinessResult, DealContextV1]:
    step = PlanStep(
        step_id=f"seller_{opportunity_id}",
        tool="dealdesk.quote.readiness",
        args={
            "opportunity_id": opportunity_id,
            "org_alias": org_alias,
            "state_dir": state_dir,
            "crm_org_id": crm_org_id,
            "force_refresh": force_refresh,
        },
        risk_level=0,
    )
    result = handle_dealdesk_quote_readiness(step, None)
    after = result.get("after") if isinstance(result, dict) else {}
    if not isinstance(after, dict):
        raise RuntimeError("Deal Desk readiness handler returned an invalid payload.")
    readiness_payload = after.get("readiness")
    if not isinstance(readiness_payload, dict):
        raise RuntimeError("Deal Desk readiness handler did not return readiness details.")
    readiness = QuoteReadinessResult.model_validate(readiness_payload)
    store = DealDeskStore(state_dir)
    context = store.load_context(opportunity_id=opportunity_id, crm_org_id=crm_org_id, org_alias=org_alias)
    if context is None:
        raise RuntimeError(f"Deal Desk context was not persisted for opportunity {opportunity_id}.")
    return readiness, context


def _next_actions_for_issues(issues: list[ReadinessIssue]) -> list[SellerActionHintV1]:
    actions: list[SellerActionHintV1] = []
    seen: set[tuple[str, str | None]] = set()
    for issue in issues:
        action = _action_hint_for_issue(issue)
        if action is None:
            continue
        key = (action.action_key, action.field_name)
        if key in seen:
            continue
        seen.add(key)
        actions.append(action)
    if not actions:
        actions.append(
            SellerActionHintV1(
                action_key="submit_for_close",
                label="Queue close review",
                detail="Deal is ready for close review intake.",
            )
        )
    return actions


def _merge_seller_action_hints(*groups: list[SellerActionHintV1]) -> list[SellerActionHintV1]:
    merged: list[SellerActionHintV1] = []
    seen: set[tuple[str, str | None]] = set()
    seen_details: set[tuple[str, str]] = set()
    for group in groups:
        for action in list(group or []):
            key = (action.action_key, action.field_name)
            detail_key = (
                str(action.action_key or "").strip().lower(),
                str(action.detail or "").strip().lower(),
            )
            if key in seen or detail_key in seen_details:
                continue
            seen.add(key)
            seen_details.add(detail_key)
            merged.append(action)
    return merged


def _action_hint_for_issue(issue: ReadinessIssue) -> SellerActionHintV1 | None:
    field_name = str(issue.field_name or "").strip() or None
    code = str(issue.code or "").strip().upper()
    if "PRIMARY_CONTACT" in code:
        return SellerActionHintV1(
            action_key="add_contact_role",
            label="Add contact",
            detail="Attach the required close contact to the active deal.",
            field_name=field_name,
        )
    if issue.severity == "blocking" and field_name and code.startswith("DD_MISSING_"):
        return SellerActionHintV1(
            action_key="fix_missing_field",
            label="Fix missing field",
            detail=f"Populate {field_name} on the active deal before close review.",
            field_name=field_name,
        )
    if "AMBIGUOUS" in code or code.startswith("DD_NO_"):
        return SellerActionHintV1(
            action_key="route_revops",
            label="Ask RevOps",
            detail=issue.message,
            field_name=field_name,
        )
    if issue.severity == "warning":
        return SellerActionHintV1(
            action_key="review_warning",
            label="Review discrepancy",
            detail=issue.message,
            field_name=field_name,
        )
    return None


def _normalize_close_certification_entrypoint(entrypoint: str) -> CloseCertificationEntrypoint:
    normalized = str(entrypoint or "").strip().lower()
    if normalized == "submitted_for_close":
        return "submitted_for_close"
    if normalized == "closed_won_retro":
        return "closed_won_retro"
    raise RuntimeError(
        f"Unsupported close certification entrypoint {entrypoint!r}. "
        "Expected one of: submitted_for_close, closed_won_retro."
    )


def _close_certification_states(
    *,
    entrypoint: CloseCertificationEntrypoint,
    overall_disposition: str,
) -> tuple[str, str]:
    disposition = str(overall_disposition or "").strip().lower()
    if disposition in {"block_close", "approval_required"}:
        return "exception_pending", "exception_pending"
    if entrypoint == "closed_won_retro":
        return "closed_won_progressed", "closed_won_progressed"
    return "certified", "certified"


def _apply_close_certification_context(
    *,
    context: DealContextV1,
    packet: ReconciliationPacketV1,
    packet_path: str,
    entrypoint: CloseCertificationEntrypoint,
    observed_at: str,
) -> None:
    lifecycle_state, close_workflow_state = _close_certification_states(
        entrypoint=entrypoint,
        overall_disposition=packet.overall_disposition,
    )
    context.updated_at = observed_at
    if entrypoint == "submitted_for_close":
        context.close_submitted_at = observed_at
    context.latest_reconciliation_packet_id = packet.packet_id
    if packet_path not in context.reconciliation_packet_paths:
        context.reconciliation_packet_paths.append(packet_path)
    _append_reconciliation_artifact(context, path=packet_path, created_at=observed_at)
    context.lifecycle_state = lifecycle_state
    if close_workflow_state == "exception_pending":
        context.close_workflow_state = "exception_pending"
    else:
        _advance_close_workflow_state(context, close_workflow_state)


def _append_reconciliation_artifact(context: DealContextV1, *, path: str, created_at: str) -> None:
    if any(item.type == "reconciliation_packet" and item.path == path for item in context.artifact_refs):
        return
    context.artifact_refs.append(
        ArtifactRef(type="reconciliation_packet", path=path, created_at=created_at)
    )


def _append_close_certification_run_artifact(context: DealContextV1, *, path: str, created_at: str) -> None:
    if any(item.type == "close_certification_run" and item.path == path for item in context.artifact_refs):
        return
    context.artifact_refs.append(
        ArtifactRef(type="close_certification_run", path=path, created_at=created_at)
    )


def _active_quote_id(context: DealContextV1 | None) -> str:
    if context is None or not context.quote_refs:
        return "unknown"
    refs = sorted(context.quote_refs, key=lambda item: str(item.created_at or ""))
    quote_id = str(refs[-1].quote_id or "").strip()
    return quote_id or "unknown"


def _persist_quote_document_fingerprints(
    *,
    store: DealDeskStore,
    fingerprints: list[Any],
) -> None:
    for fingerprint in fingerprints:
        store.save_quote_document_fingerprint(fingerprint)


def _close_certification_run_id(
    *,
    opportunity_id: str,
    entrypoint: CloseCertificationEntrypoint,
    triggered_at: str,
) -> str:
    stamp_source = re.sub(r"[^0-9]+", "", str(triggered_at or ""))
    stamp = stamp_source[:14] or datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
    entry_key = str(entrypoint or "").strip().lower().replace("_", "-") or "close"
    opp_key = re.sub(r"[^A-Za-z0-9]+", "", str(opportunity_id or ""))[-8:] or "opp"
    return f"dealdesk_close_run_{entry_key}_{opp_key}_{stamp}_{secrets.token_hex(4)}"


def _post_close_trigger_status_counts(trigger_runs: list[PostCloseTriggerRunV1]) -> dict[str, int]:
    counts: dict[str, int] = {}
    for item in trigger_runs:
        key = str(item.status or "").strip() or "unknown"
        counts[key] = counts.get(key, 0) + 1
    return counts


def _build_close_certification_run(
    *,
    result: CloseCertificationResultV1,
    packet: ReconciliationPacketV1,
) -> CloseCertificationRunV1:
    evidence_summary = summarize_close_document_evidence(packet.document_evidence)
    return CloseCertificationRunV1(
        run_id=_close_certification_run_id(
            opportunity_id=result.opportunity_id,
            entrypoint=result.entrypoint,
            triggered_at=result.triggered_at,
        ),
        opportunity_id=result.opportunity_id,
        crm_org_id=result.crm_org_id,
        org_alias=result.org_alias,
        context_id=result.context_id,
        entrypoint=result.entrypoint,
        triggered_at=result.triggered_at,
        close_submitted_at=result.close_submitted_at,
        lifecycle_state=result.lifecycle_state,
        close_workflow_state=result.close_workflow_state,
        overall_disposition=result.overall_disposition,
        reconciliation_packet_id=result.reconciliation_packet_id,
        reconciliation_packet_path=result.reconciliation_packet_path,
        blocker_count=result.blocker_count,
        approval_required_count=result.approval_required_count,
        auto_fixable_count=result.auto_fixable_count,
        document_evidence_status=result.document_evidence_status,
        document_candidate_count=result.document_candidate_count,
        document_contract_candidate_count=result.document_contract_candidate_count,
        document_summary=result.document_summary,
        document_extraction_status=result.document_extraction_status,
        document_evidence_count=result.document_evidence_count,
        document_comparison_count=result.document_comparison_count,
        document_discrepancy_count=result.document_discrepancy_count,
        document_evidence_summary=result.document_evidence_summary,
        document_extraction_method_counts=evidence_summary.method_counts,
        document_extraction_confidence_avg=evidence_summary.confidence_avg,
        document_extraction_confidence_min=evidence_summary.confidence_min,
        document_extraction_confidence_max=evidence_summary.confidence_max,
        document_extraction_confidence_sum=evidence_summary.confidence_sum,
        document_escalated=document_evidence_escalated(
            document_evidence_status=result.document_evidence_status,
            document_discrepancy_count=result.document_discrepancy_count,
            document_extraction_status=result.document_extraction_status,
        ),
        quote_integrity_status=result.quote_integrity_status,
        quote_integrity_summary=result.quote_integrity_summary,
        quote_integrity_discrepancy_count=result.quote_integrity_discrepancy_count,
        quote_fingerprint_count=result.quote_fingerprint_count,
        quote_binary_mismatch_count=result.quote_binary_mismatch_count,
        quote_semantic_mismatch_count=result.quote_semantic_mismatch_count,
        quote_integrity_escalated=(
            result.quote_integrity_status in {"review_required", "blocked"}
            or int(result.quote_integrity_discrepancy_count or 0) > 0
        ),
        progression_status=result.progression_status,
        progression_target_stage=result.progression_target_stage,
        progression_receipt_run_id=result.progression_receipt_run_id,
        progression_approval_required=result.progression_approval_required,
        progression_pending_run_id=result.progression_pending_run_id,
        post_close_status=result.post_close_status,
        post_close_trigger_run_ids=[item.run_id for item in result.post_close_trigger_runs],
        post_close_trigger_status_counts=_post_close_trigger_status_counts(result.post_close_trigger_runs),
        post_close_approval_required=result.post_close_approval_required,
        post_close_pending_run_id=result.post_close_pending_run_id,
    )


def _find_fixable_missing_field_issue(
    issues: list[ReadinessIssue],
    field_name: str,
) -> ReadinessIssue | None:
    normalized = str(field_name or "").strip().lower()
    for issue in issues:
        if issue.severity != "blocking":
            continue
        if not str(issue.code or "").strip().upper().startswith("DD_MISSING_"):
            continue
        if str(issue.field_name or "").strip().lower() != normalized:
            continue
        return issue
    return None


def _find_primary_contact_issue(issues: list[ReadinessIssue]) -> ReadinessIssue | None:
    for issue in issues:
        code = str(issue.code or "").strip().upper()
        if issue.severity != "blocking":
            continue
        if "PRIMARY_CONTACT" not in code:
            continue
        return issue
    return None


def _build_seller_field_fix_plan(
    *,
    opportunity_id: str,
    field_name: str,
    field_value: Any,
    org_alias: str | None,
) -> PlanV1:
    run_id = f"dealdesk_seller_fix_{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}_{secrets.token_hex(4)}"
    return PlanV1(
        run_id=run_id,
        source=PlanSource(type="seller_field_fix"),
        summary=f"Deal Desk seller fix {field_name} on {opportunity_id}",
        source_kind="dealdesk_seller_field_fix",
        evidence_ids=[opportunity_id, field_name],
        steps=[
            PlanStep(
                step_id="seller_fix_missing_field",
                tool="sfdc.record.update",
                args={
                    "sobject": "Opportunity",
                    "record_id": opportunity_id,
                    "fields": {field_name: field_value},
                    "org_alias": org_alias,
                },
                risk_level=0,
                idempotency_key=f"seller_fix:{opportunity_id}:{field_name}:{field_value}",
                evidence_ids=[opportunity_id, field_name],
            )
        ],
        approvals_required=False,
    )


def _build_seller_contact_role_plan(
    *,
    opportunity_id: str,
    contact_id: str,
    role_name: str,
    primary_contact_field_name: str,
    create_contact_role: bool,
    update_primary_contact: bool,
    org_alias: str | None,
) -> PlanV1:
    run_id = f"dealdesk_seller_contact_{datetime.now(timezone.utc).strftime('%Y%m%d%H%M%S')}_{secrets.token_hex(4)}"
    steps: list[PlanStep] = []
    if create_contact_role:
        steps.append(
            PlanStep(
                step_id="seller_add_opportunity_contact_role",
                tool="sfdc.record.create",
                args={
                    "sobject": "OpportunityContactRole",
                    "values": {
                        "OpportunityId": opportunity_id,
                        "ContactId": contact_id,
                        "Role": role_name,
                        "IsPrimary": True,
                    },
                    "org_alias": org_alias,
                },
                risk_level=0,
                idempotency_key=f"seller_contact_role:{opportunity_id}:{contact_id}:{role_name}",
                evidence_ids=[opportunity_id, contact_id, role_name],
            )
        )
    if update_primary_contact:
        steps.append(
            PlanStep(
                step_id="seller_set_primary_contact_field",
                tool="sfdc.record.update",
                args={
                    "sobject": "Opportunity",
                    "record_id": opportunity_id,
                    "fields": {primary_contact_field_name: contact_id},
                    "org_alias": org_alias,
                },
                risk_level=0,
                idempotency_key=f"seller_primary_contact:{opportunity_id}:{primary_contact_field_name}:{contact_id}",
                evidence_ids=[opportunity_id, contact_id, primary_contact_field_name],
            )
        )
    if not steps:
        raise RuntimeError("No contact-role actions were required for this seller request.")
    return PlanV1(
        run_id=run_id,
        source=PlanSource(type="seller_contact_role_add"),
        summary=f"Deal Desk seller add contact {contact_id} to {opportunity_id}",
        source_kind="dealdesk_seller_contact_role_add",
        evidence_ids=[opportunity_id, contact_id, role_name],
        steps=steps,
        approvals_required=False,
    )


def _seller_quote_support(
    *,
    environment_profile: QuoteEnvironmentProfileV1,
) -> tuple[Literal["supported", "partial", "unsupported", "ambiguous"], str, list[str]]:
    support = route_seller_quote_support(environment_profile=environment_profile)
    return support.status, support.reason, list(support.capability_gaps or [])


def _seller_quote_live_approval_supported(environment_profile: QuoteEnvironmentProfileV1) -> bool:
    adapter = resolve_quote_adapter(detected_engine=environment_profile.detected_engine)
    if adapter is None:
        return False
    return adapter.live_approval_supported(environment_profile=environment_profile)


def _seller_quote_base_evidence(
    *,
    environment_profile: QuoteEnvironmentProfileV1,
    stage_name: str | None,
    opportunity_amount: float | None,
    quote_intelligence: DealDeskQuoteIntelligenceResponseV1,
) -> list[SellerQuoteEvidenceV1]:
    quote_objects = ", ".join(environment_profile.quote_objects[:3]) or "none"
    details = (
        f"Detected engine `{environment_profile.detected_engine}` from quote objects: {quote_objects}. "
        f"Engine confidence: {environment_profile.engine_confidence:.2f}."
    )
    evidence = [
        SellerQuoteEvidenceV1(
            source_type="engine_detection",
            label="Quote Stack",
            detail=details,
        )
    ]
    if stage_name or opportunity_amount is not None:
        stage_text = stage_name or "unknown"
        amount_text = f"{opportunity_amount:,.2f}" if opportunity_amount is not None else "unknown"
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="opportunity_snapshot",
                label="Deal Shape",
                detail=f"Approval preview used stage `{stage_text}` and amount `{amount_text}`.",
            )
        )
    if quote_intelligence.approval_preview.route_count:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="approval_preview",
                label="Approval Routing",
                detail=(
                    f"Matched {quote_intelligence.approval_preview.matched_count} of "
                    f"{quote_intelligence.approval_preview.route_count} configured approval route(s)."
                ),
            )
        )
    return evidence


def _matched_route_names(quote_intelligence: DealDeskQuoteIntelligenceResponseV1) -> list[str]:
    return [
        str(item.route_name or "").strip()
        for item in quote_intelligence.approval_preview.items
        if item.matched and str(item.route_name or "").strip()
    ]


def _expected_quote_approvers(
    quote_intelligence: DealDeskQuoteIntelligenceResponseV1,
) -> list[SellerQuoteApproverV1]:
    approvers: list[SellerQuoteApproverV1] = []
    seen: set[tuple[str, str]] = set()
    for route in quote_intelligence.approval_preview.items:
        if not route.matched:
            continue
        for item in route.approvers:
            label = str(item.role or item.resolved_slack_id or item.resolved_channel_id or "").strip()
            if not label:
                continue
            detail_bits = [f"route `{route.route_name}`"]
            if item.resolved_slack_id:
                detail_bits.append(f"slack `{item.resolved_slack_id}`")
            if item.resolved_channel_id:
                detail_bits.append(f"channel `{item.resolved_channel_id}`")
            key = (label.lower(), "|".join(detail_bits).lower())
            if key in seen:
                continue
            seen.add(key)
            approvers.append(
                SellerQuoteApproverV1(
                    label=label,
                    source="expected_route",
                    detail=", ".join(detail_bits),
                )
            )
    return approvers


def _load_opportunity_quote_status_snapshot(
    *,
    opportunity_id: str,
    org_alias: str | None,
) -> dict[str, Any]:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, StageName, Amount, CloseDate, LastModifiedDate "
            f"FROM Opportunity WHERE Id = '{escaped_opportunity_id}' LIMIT 1"
        ),
        org_alias=org_alias,
    )
    if not rows:
        return {}
    return rows[0] if isinstance(rows[0], dict) else {}


def _load_supported_quote_records(
    *,
    opportunity_id: str,
    detected_engine: str,
    org_alias: str | None,
) -> list[_QuoteRecordSnapshot]:
    adapter = resolve_quote_adapter(detected_engine=detected_engine)
    if adapter is None:
        return []
    return adapter.load_quote_records(opportunity_id=opportunity_id, org_alias=org_alias)


def _load_standard_quote_records(
    *,
    opportunity_id: str,
    org_alias: str | None,
) -> list[_QuoteRecordSnapshot]:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, Name, QuoteNumber, Status, GrandTotal, ExpirationDate, CreatedDate, LastModifiedDate, IsSyncing "
            f"FROM Quote WHERE OpportunityId = '{escaped_opportunity_id}' "
            "ORDER BY IsSyncing DESC, LastModifiedDate DESC LIMIT 25"
        ),
        org_alias=org_alias,
    )
    records: list[_QuoteRecordSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        quote_id = str(row.get("Id") or "").strip()
        if not quote_id:
            continue
        name = str(row.get("Name") or row.get("QuoteNumber") or quote_id).strip() or quote_id
        is_syncing = _truthy(row.get("IsSyncing"))
        records.append(
            _QuoteRecordSnapshot(
                quote_id=quote_id,
                object_name="Quote",
                label=name,
                status=str(row.get("Status") or "Unknown").strip() or "Unknown",
                amount=_coerce_float_value(row.get("GrandTotal")),
                expiration_date=_normalize_iso_date_value(row.get("ExpirationDate")),
                created_at=_normalize_iso_datetime_value(row.get("CreatedDate")),
                last_modified_at=_normalize_iso_datetime_value(row.get("LastModifiedDate")),
                is_syncing=is_syncing,
                current_reason="selected because this is the synced standard quote" if is_syncing else "",
            )
        )
    return records


def _load_salesforce_cpq_quote_records(
    *,
    opportunity_id: str,
    org_alias: str | None,
) -> list[_QuoteRecordSnapshot]:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, Name, SBQQ__QuoteNumber__c, SBQQ__Status__c, SBQQ__Primary__c, SBQQ__Ordered__c, "
            "SBQQ__NetAmount__c, SBQQ__GrandTotal__c, SBQQ__ExpirationDate__c, CreatedDate, LastModifiedDate "
            f"FROM SBQQ__Quote__c WHERE SBQQ__Opportunity2__c = '{escaped_opportunity_id}' "
            "ORDER BY SBQQ__Primary__c DESC, LastModifiedDate DESC LIMIT 25"
        ),
        org_alias=org_alias,
    )
    records: list[_QuoteRecordSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        quote_id = str(row.get("Id") or "").strip()
        if not quote_id:
            continue
        name = str(row.get("Name") or row.get("SBQQ__QuoteNumber__c") or quote_id).strip() or quote_id
        is_primary = _truthy(row.get("SBQQ__Primary__c"))
        is_ordered = _truthy(row.get("SBQQ__Ordered__c"))
        current_reason = ""
        if is_primary:
            current_reason = "selected because this is the primary CPQ quote"
        elif is_ordered:
            current_reason = "selected because this quote is already ordered"
        records.append(
            _QuoteRecordSnapshot(
                quote_id=quote_id,
                object_name="SBQQ__Quote__c",
                label=name,
                status=str(row.get("SBQQ__Status__c") or "Unknown").strip() or "Unknown",
                amount=_coerce_float_value(row.get("SBQQ__NetAmount__c"), row.get("SBQQ__GrandTotal__c")),
                expiration_date=_normalize_iso_date_value(row.get("SBQQ__ExpirationDate__c")),
                created_at=_normalize_iso_datetime_value(row.get("CreatedDate")),
                last_modified_at=_normalize_iso_datetime_value(row.get("LastModifiedDate")),
                is_primary=is_primary,
                is_ordered=is_ordered,
                current_reason=current_reason,
            )
        )
    return records


def _select_quote_record(records: list[_QuoteRecordSnapshot]) -> _QuoteRecordSnapshot | None:
    if not records:
        return None
    ordered = sorted(records, key=_quote_record_sort_key, reverse=True)
    selected = ordered[0]
    if selected.current_reason:
        return selected
    return _QuoteRecordSnapshot(
        quote_id=selected.quote_id,
        object_name=selected.object_name,
        label=selected.label,
        status=selected.status,
        amount=selected.amount,
        expiration_date=selected.expiration_date,
        created_at=selected.created_at,
        last_modified_at=selected.last_modified_at,
        is_primary=selected.is_primary,
        is_syncing=selected.is_syncing,
        is_ordered=selected.is_ordered,
        current_reason="selected because it is the most recently updated supported quote",
    )


def _quote_record_sort_key(record: _QuoteRecordSnapshot) -> tuple[int, int, int, str, str]:
    return (
        1 if record.is_primary else 0,
        1 if record.is_syncing else 0,
        1 if record.is_ordered else 0,
        str(record.last_modified_at or ""),
        str(record.created_at or ""),
    )


def _quote_record_model(record: _QuoteRecordSnapshot) -> SellerQuoteRecordV1:
    return SellerQuoteRecordV1(
        quote_id=record.quote_id,
        object_name=record.object_name,
        label=record.label,
        status=record.status,
        amount=record.amount,
        expiration_date=record.expiration_date,
        created_at=record.created_at,
        last_modified_at=record.last_modified_at,
        is_primary=record.is_primary,
        is_syncing=record.is_syncing,
        is_ordered=record.is_ordered,
        current_reason=record.current_reason,
    )


def _load_quote_approval_processes(
    *,
    quote_ids: list[str],
    org_alias: str | None,
) -> list[_QuoteApprovalProcessSnapshot]:
    normalized_quote_ids = [str(item or "").strip() for item in quote_ids if str(item or "").strip()]
    if not normalized_quote_ids:
        return []
    quoted_ids = ", ".join(f"'{_soql_string_literal(item)}'" for item in normalized_quote_ids)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, TargetObjectId, Status, CreatedDate, CompletedDate, SubmittedBy.Name, LastActor.Name "
            f"FROM ProcessInstance WHERE TargetObjectId IN ({quoted_ids}) "
            "ORDER BY CreatedDate DESC LIMIT 50"
        ),
        org_alias=org_alias,
    )
    processes: list[_QuoteApprovalProcessSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        process_id = str(row.get("Id") or "").strip()
        quote_id = str(row.get("TargetObjectId") or "").strip()
        if not process_id or not quote_id:
            continue
        processes.append(
            _QuoteApprovalProcessSnapshot(
                process_id=process_id,
                quote_id=quote_id,
                status=str(row.get("Status") or "").strip() or "Unknown",
                created_at=_normalize_iso_datetime_value(row.get("CreatedDate")),
                completed_at=_normalize_iso_datetime_value(row.get("CompletedDate")),
                submitted_by_name=str(row.get("SubmittedBy.Name") or "").strip() or None,
                last_actor_name=str(row.get("LastActor.Name") or "").strip() or None,
            )
        )
    return processes


def _load_quote_approval_workitems(
    *,
    process_ids: list[str],
    org_alias: str | None,
) -> list[_QuoteApprovalWorkitemSnapshot]:
    normalized_process_ids = [str(item or "").strip() for item in process_ids if str(item or "").strip()]
    if not normalized_process_ids:
        return []
    quoted_ids = ", ".join(f"'{_soql_string_literal(item)}'" for item in normalized_process_ids)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, ProcessInstanceId, ActorId, Actor.Name, OriginalActor.Name, CreatedDate "
            f"FROM ProcessInstanceWorkitem WHERE ProcessInstanceId IN ({quoted_ids}) "
            "ORDER BY CreatedDate ASC LIMIT 50"
        ),
        org_alias=org_alias,
    )
    workitems: list[_QuoteApprovalWorkitemSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        process_id = str(row.get("ProcessInstanceId") or "").strip()
        if not process_id:
            continue
        workitems.append(
            _QuoteApprovalWorkitemSnapshot(
                process_id=process_id,
                actor_id=str(row.get("ActorId") or "").strip() or None,
                actor_name=str(row.get("Actor.Name") or "").strip() or None,
                original_actor_name=str(row.get("OriginalActor.Name") or "").strip() or None,
                created_at=_normalize_iso_datetime_value(row.get("CreatedDate")),
            )
        )
    return workitems


def _quote_approval_state(
    *,
    selected_quote: _QuoteRecordSnapshot | None,
    processes: list[_QuoteApprovalProcessSnapshot],
    workitems: list[_QuoteApprovalWorkitemSnapshot],
    quote_intelligence: DealDeskQuoteIntelligenceResponseV1,
    live_approval_supported: bool,
) -> tuple[str, str | None, str | None, list[SellerQuoteApproverV1]]:
    if selected_quote is None:
        return "not_requested", None, None, []

    selected_processes = [item for item in processes if item.quote_id == selected_quote.quote_id]
    selected_workitems = [
        item
        for item in workitems
        if any(process.process_id == item.process_id for process in selected_processes)
    ]
    pending_approvers: list[SellerQuoteApproverV1] = []
    seen: set[tuple[str, str | None]] = set()
    for item in selected_workitems:
        label = str(item.actor_name or item.original_actor_name or "").strip()
        if not label:
            continue
        key = (label.lower(), item.actor_id)
        if key in seen:
            continue
        seen.add(key)
        pending_approvers.append(
            SellerQuoteApproverV1(
                label=label,
                actor_id=item.actor_id,
                source="live_pending",
                detail=f"pending approval step opened at `{item.created_at}`" if item.created_at else None,
            )
        )

    pending_processes = [
        item
        for item in selected_processes
        if str(item.completed_at or "").strip() == ""
        and str(item.status or "").strip().lower() not in {"approved", "rejected", "removed"}
    ]
    if pending_approvers or pending_processes:
        submitted_at = max(
            [str(item.created_at or "") for item in pending_processes if str(item.created_at or "").strip()],
            default=None,
        )
        return "pending", submitted_at, None, pending_approvers
    if any(
        str(item.status or "").strip().lower() == "approved" or str(item.completed_at or "").strip()
        for item in selected_processes
    ):
        completed_at = max(
            [str(item.completed_at or "") for item in selected_processes if str(item.completed_at or "").strip()],
            default=None,
        )
        return "approved", None, completed_at, []
    if not live_approval_supported:
        return "unavailable", None, None, []
    if _expected_quote_approvers(quote_intelligence):
        return "not_requested", None, None, []
    return "not_required", None, None, []


def _seller_quote_stale_reasons(
    *,
    selected_quote: _QuoteRecordSnapshot | None,
    config: DealDeskConfig,
) -> list[str]:
    if selected_quote is None:
        return []
    reasons: list[str] = []
    now_utc = datetime.now(timezone.utc)
    expiration_dt = _parse_datetime_value(selected_quote.expiration_date)
    if expiration_dt is not None and expiration_dt.date() < now_utc.date():
        reasons.append(
            f"Quote `{selected_quote.label}` expired on `{expiration_dt.date().isoformat()}`."
        )
    stale_days = max(1, int(config.date_rules.close_date_not_stale_days or 30))
    last_modified_dt = _parse_datetime_value(selected_quote.last_modified_at)
    if last_modified_dt is not None:
        age_days = int((now_utc - last_modified_dt).days)
        if age_days > stale_days:
            reasons.append(
                f"Quote `{selected_quote.label}` was last modified on `{last_modified_dt.date().isoformat()}`, older than the current `{stale_days}`-day freshness window."
            )
    return reasons


def _seller_quote_conflict_reasons(
    *,
    quote_rows: list[_QuoteRecordSnapshot],
    selected_quote: _QuoteRecordSnapshot | None,
    latest_packet: ReconciliationPacketV1 | None,
) -> list[str]:
    reasons: list[str] = []
    if latest_packet is not None and (
        str(latest_packet.quote_integrity_status or "").strip() in {"review_required", "blocked"}
        or int(latest_packet.quote_integrity_discrepancy_count or 0) > 0
    ):
        reasons.append(
            latest_packet.quote_integrity_summary
            or "Latest close review found a quote integrity mismatch against close evidence."
        )
    active_quotes = [item for item in quote_rows if _quote_is_active_candidate(item)]
    if len(active_quotes) > 1:
        current_candidates = [item for item in active_quotes if item.is_primary or item.is_syncing]
        if len(current_candidates) > 1:
            reasons.append(
                "Multiple supported quotes are marked as current on this opportunity."
            )
        elif not current_candidates and selected_quote is not None:
            reasons.append(
                f"Multiple active quotes exist and Gremlin selected `{selected_quote.label}` only because it was updated most recently."
            )
    return reasons


def _seller_quote_record_evidence(
    *,
    selected_quote: _QuoteRecordSnapshot | None,
    quote_rows: list[_QuoteRecordSnapshot],
) -> list[SellerQuoteEvidenceV1]:
    if selected_quote is None:
        return []
    details = [
        f"{selected_quote.object_name} `{selected_quote.quote_id}`",
        f"status `{selected_quote.status}`",
    ]
    if selected_quote.amount is not None:
        details.append(f"amount `{selected_quote.amount:,.2f}`")
    if selected_quote.expiration_date:
        details.append(f"expires `{selected_quote.expiration_date}`")
    if selected_quote.last_modified_at:
        details.append(f"last modified `{selected_quote.last_modified_at}`")
    if selected_quote.current_reason:
        details.append(selected_quote.current_reason)
    evidence = [
        SellerQuoteEvidenceV1(
            source_type="quote_record",
            label="Selected Quote",
            detail=", ".join(details) + ".",
        )
    ]
    if len(quote_rows) > 1:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_inventory",
                label="Quote Inventory",
                detail=f"Gremlin found {len(quote_rows)} supported quote record(s) on this opportunity.",
            )
        )
    return evidence


def _seller_quote_approval_evidence(
    *,
    selected_quote: _QuoteRecordSnapshot | None,
    processes: list[_QuoteApprovalProcessSnapshot],
    workitems: list[_QuoteApprovalWorkitemSnapshot],
    quote_intelligence: DealDeskQuoteIntelligenceResponseV1,
    live_approval_supported: bool,
) -> list[SellerQuoteEvidenceV1]:
    if selected_quote is None:
        return []
    evidence: list[SellerQuoteEvidenceV1] = []
    selected_processes = [item for item in processes if item.quote_id == selected_quote.quote_id]
    selected_workitems = [
        item
        for item in workitems
        if any(process.process_id == item.process_id for process in selected_processes)
    ]
    if live_approval_supported:
        if selected_workitems:
            approver_names = ", ".join(
                sorted(
                    {
                        str(item.actor_name or item.original_actor_name or "").strip()
                        for item in selected_workitems
                        if str(item.actor_name or item.original_actor_name or "").strip()
                    }
                )
            )
            if approver_names:
                evidence.append(
                    SellerQuoteEvidenceV1(
                        source_type="approval_live",
                        label="Pending Approvers",
                        detail=f"Live Salesforce approval work items are open for: {approver_names}.",
                    )
                )
        elif selected_processes:
            latest_process = max(selected_processes, key=lambda item: str(item.created_at or ""))
            detail = f"Latest approval process status is `{latest_process.status}`."
            if latest_process.completed_at:
                detail += f" Completed at `{latest_process.completed_at}`."
            evidence.append(
                SellerQuoteEvidenceV1(
                    source_type="approval_live",
                    label="Approval History",
                    detail=detail,
                )
            )
    matched_routes = _matched_route_names(quote_intelligence)
    if matched_routes:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="approval_expected",
                label="Expected Route",
                detail=f"Current config matched approval route(s): {', '.join(matched_routes)}.",
            )
        )
    return evidence


def _seller_quote_integrity_evidence(
    *,
    latest_packet: ReconciliationPacketV1 | None,
) -> list[SellerQuoteEvidenceV1]:
    if latest_packet is None:
        return []
    if str(latest_packet.quote_integrity_status or "").strip() == "not_available":
        return []
    detail = (
        f"Latest reconciliation packet `{latest_packet.packet_id}` reports quote integrity "
        f"`{latest_packet.quote_integrity_status}`."
    )
    if latest_packet.quote_integrity_summary:
        detail += f" {latest_packet.quote_integrity_summary}"
    return [
        SellerQuoteEvidenceV1(
            source_type="quote_integrity",
            label="Latest Close Review",
            detail=detail,
        )
    ]


def _seller_quote_next_step(
    *,
    status: str,
    stale_reasons: list[str],
    conflict_reasons: list[str],
    approval_state: str,
    pending_approvers: list[SellerQuoteApproverV1],
    expected_approvers: list[SellerQuoteApproverV1],
    live_approval_supported: bool,
) -> str:
    if conflict_reasons:
        return "Ask RevOps to reconcile the conflicting quote evidence before using this quote for close."
    if stale_reasons:
        return "Refresh or replace the stale quote in the native quote tool. Gremlin stays read-only in this slice."
    if approval_state == "pending":
        if pending_approvers:
            names = ", ".join(item.label for item in pending_approvers)
            return f"Approval is in flight. Follow up with the current approver set: {names}."
        return "Approval is already in flight for the current quote."
    if approval_state == "not_requested" and expected_approvers:
        return "No live approval request is open yet. Submit the current quote in the native quote tool when it is ready."
    if not live_approval_supported and status == "partial":
        return "Quote status is available here, but approval-state visibility still needs RevOps review or control-plane inspection."
    return "No seller action is required from Gremlin's current read-only quote view."


def _normalize_quote_intent_operation(value: QuoteIntentOperation | str) -> QuoteIntentOperation:
    normalized = str(value or "").strip().lower()
    aliases = {
        "discount": "update_discount_pct",
        "discount_pct": "update_discount_pct",
        "discount_percent": "update_discount_pct",
        "term": "update_term_months",
        "term_months": "update_term_months",
        "payment_terms": "update_payment_terms",
        "payment": "update_payment_terms",
        "add_sku": "add_product",
        "remove_sku": "remove_product",
        "quantity": "update_quantity",
    }
    candidate = aliases.get(normalized, normalized)
    if candidate not in {
        "update_discount_pct",
        "update_term_months",
        "update_payment_terms",
        "add_product",
        "remove_product",
        "update_quantity",
    }:
        raise RuntimeError(f"Unsupported quote intent operation: {value}")
    return candidate  # type: ignore[return-value]


def _quote_intent_is_line_item(intent: QuoteIntentV1) -> bool:
    return str(intent.semantic_key or "").strip() == "line_item"


def _parse_quote_intent_line_item_payload(raw_value: str) -> dict[str, Any]:
    raw_text = str(raw_value or "").strip()
    if not raw_text:
        return {}
    try:
        payload = json.loads(raw_text)
    except Exception:
        return {"product_reference": raw_text}
    return payload if isinstance(payload, dict) else {"product_reference": raw_text}


def _normalize_quote_line_reference_type(
    value: Any,
    product_reference: str,
) -> QuoteLineReferenceType:
    normalized = str(value or "").strip().lower()
    if normalized in {"product_id", "product_code", "product_name"}:
        return normalized  # type: ignore[return-value]
    if _SELLER_PRODUCT_ID_RE.match(product_reference):
        return "product_id"
    if " " in product_reference.strip():
        return "product_name"
    return "product_code"


def _parse_quote_intent_line_quantity(value: Any) -> float:
    raw = str(value or "").strip().lower()
    if not raw:
        raise RuntimeError("Line-item preview requires a concrete quantity.")
    match = re.search(r"(\d+(?:\.\d+)?)", raw.replace(",", ""))
    if match is None:
        raise RuntimeError("Line-item preview requires a numeric quantity such as `5`.")
    quantity = float(match.group(1))
    if quantity <= 0:
        raise RuntimeError("Line-item preview requires a quantity greater than zero.")
    return round(quantity, 4)


def _quote_line_intent_target_label(operation: QuoteIntentOperation) -> str:
    if operation == "add_product":
        return "Add Product"
    if operation == "remove_product":
        return "Remove Product"
    if operation == "update_quantity":
        return "Update Quantity"
    raise RuntimeError(f"Unsupported line-item intent operation: {operation}")


def _quote_line_intent_display_value(
    *,
    operation: QuoteIntentOperation,
    product_reference: str,
    quantity: float | None,
) -> str:
    product_display = _quote_line_reference_display(product_reference)
    if operation == "add_product":
        return f"{product_display} x {_format_quantity(quantity)}"
    if operation == "remove_product":
        return product_display
    if operation == "update_quantity":
        return f"{product_display} -> {_format_quantity(quantity)}"
    raise RuntimeError(f"Unsupported line-item intent operation: {operation}")


def _parse_quote_intent_discount_pct(value: str) -> float:
    raw = str(value or "").strip()
    if not raw:
        raise RuntimeError("Discount preview requires a value such as `10%`.")
    has_percent = "%" in raw
    normalized = raw.replace("%", "").replace(",", "").strip()
    try:
        parsed = float(normalized)
    except Exception as exc:
        raise RuntimeError("Discount preview requires a numeric value such as `10%`.") from exc
    if parsed <= 0.0 or parsed > 100.0:
        raise RuntimeError("Discount preview requires a percentage between 0 and 100.")
    if not has_percent and parsed <= 1.0:
        raise RuntimeError("Use an explicit percent value like `10%` for discount preview.")
    return round(parsed, 4)


def _parse_quote_intent_term_months(value: str) -> int:
    raw = str(value or "").strip().lower()
    if not raw:
        raise RuntimeError("Term preview requires a value such as `24 months`.")
    match = re.search(r"(\d+(?:\.\d+)?)", raw)
    if match is None:
        raise RuntimeError("Term preview requires a numeric value such as `24 months`.")
    quantity = float(match.group(1))
    if quantity <= 0:
        raise RuntimeError("Term preview requires a positive term length.")
    if "year" in raw:
        months = int(round(quantity * 12))
    elif "month" in raw or "mo" in raw or raw == match.group(1):
        months = int(round(quantity))
    else:
        raise RuntimeError("Term preview currently supports month or year inputs only.")
    if months <= 0:
        raise RuntimeError("Term preview requires a positive month count.")
    return months


def _normalize_quote_intent_payment_terms(value: str) -> str:
    normalized = _strip_balanced_quotes(str(value or "").strip())
    if not normalized:
        raise RuntimeError("Payment-terms preview requires a concrete text value such as `Net 45`.")
    return normalized


def _quote_request_from_intent(intent: QuoteIntentV1) -> dict[str, Any]:
    if intent.semantic_key == "discount_pct" and intent.requested_discount_pct is not None:
        return {"discount_pct": intent.requested_discount_pct}
    if intent.semantic_key == "term_months" and intent.requested_term_months is not None:
        return {"term_months": intent.requested_term_months}
    if intent.semantic_key == "payment_terms" and intent.requested_payment_terms is not None:
        return {"payment_terms": intent.requested_payment_terms}
    if intent.semantic_key == "line_item" and intent.requested_product_reference:
        line_item: dict[str, Any] = {
            str(intent.requested_product_reference_type or "product_code"): intent.requested_product_reference,
        }
        if intent.requested_quantity is not None:
            line_item["quantity"] = intent.requested_quantity
        return {"line_items": [line_item]}
    return {}


def _quote_line_item_object_name(detected_engine: str) -> str:
    adapter = resolve_quote_adapter(detected_engine=detected_engine)
    if adapter is None:
        return "QuoteLineItem"
    return adapter.quote_line_item_object_name()


def _quote_line_reference_label(reference_type: QuoteLineReferenceType) -> str:
    if reference_type == "product_id":
        return "product id"
    if reference_type == "product_name":
        return "product name"
    return "product code"


def _quote_line_reference_display(value: str | None) -> str:
    return str(value or "").strip() or "Unknown product"


def _normalize_quote_product_reference(value: str | None) -> str:
    return re.sub(r"\s+", " ", _strip_balanced_quotes(str(value or "").strip())).strip().lower()


def _format_quantity(value: float | None) -> str:
    if value is None:
        return "Not available"
    if abs(value - round(value)) < 0.0001:
        return str(int(round(value)))
    return f"{value:.4f}".rstrip("0").rstrip(".")


def _format_currency(value: float | None) -> str:
    if value is None:
        return "Not available"
    return f"${value:,.2f}"


def _describe_sobject_field_names(
    sobject: str,
    *,
    org_alias: str | None,
) -> set[str]:
    payload = sfdc_helpers.describe_sobject(sobject, org_alias=org_alias)
    result = payload.get("result") if isinstance(payload.get("result"), dict) else payload
    raw_fields = result.get("fields") if isinstance(result, dict) else None
    if not isinstance(raw_fields, list):
        return set()
    return {
        str(field.get("name") or "").strip()
        for field in raw_fields
        if isinstance(field, dict) and str(field.get("name") or "").strip()
    }


def _load_supported_quote_line_items(
    *,
    quote_id: str,
    detected_engine: str,
    org_alias: str | None,
    reference_type: QuoteLineReferenceType,
) -> list[_QuoteLineItemSnapshot]:
    adapter = resolve_quote_adapter(detected_engine=detected_engine)
    if adapter is None:
        raise RuntimeError(f"Unsupported quote engine for line-item preview: {detected_engine}")
    return adapter.load_quote_line_items(
        quote_id=quote_id,
        org_alias=org_alias,
        reference_type=reference_type,
    )


def _load_standard_quote_line_items(
    *,
    quote_id: str,
    org_alias: str | None,
) -> list[_QuoteLineItemSnapshot]:
    escaped_quote_id = _soql_string_literal(quote_id)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, QuoteId, PricebookEntryId, Product2Id, Product2.Name, Product2.ProductCode, "
            "Quantity, UnitPrice, TotalPrice "
            f"FROM QuoteLineItem WHERE QuoteId = '{escaped_quote_id}' "
            "ORDER BY CreatedDate ASC LIMIT 200"
        ),
        org_alias=org_alias,
    )
    snapshots: list[_QuoteLineItemSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        line_item_id = str(row.get("Id") or "").strip()
        if not line_item_id:
            continue
        product_name = (
            str(row.get("Product2.Name") or "").strip()
            or str(row.get("Product2.ProductCode") or "").strip()
            or line_item_id
        )
        product_code = str(row.get("Product2.ProductCode") or "").strip() or None
        snapshots.append(
            _QuoteLineItemSnapshot(
                line_item_id=line_item_id,
                quote_id=str(row.get("QuoteId") or quote_id).strip() or quote_id,
                object_name="QuoteLineItem",
                product_id=str(row.get("Product2Id") or "").strip() or None,
                product_code=product_code,
                product_name=product_name,
                quantity=_coerce_float_value(row.get("Quantity")),
                unit_price=_coerce_float_value(row.get("UnitPrice")),
                net_price=_coerce_float_value(row.get("TotalPrice")),
                pricebook_entry_id=str(row.get("PricebookEntryId") or "").strip() or None,
            )
        )
    return snapshots


def _load_salesforce_cpq_quote_line_items(
    *,
    quote_id: str,
    org_alias: str | None,
    reference_type: QuoteLineReferenceType,
) -> list[_QuoteLineItemSnapshot]:
    available_fields = _describe_sobject_field_names("SBQQ__QuoteLine__c", org_alias=org_alias)
    required_fields = {"Id", "SBQQ__Quote__c", "SBQQ__Quantity__c"}
    missing_required = sorted(required_fields - available_fields)
    if missing_required:
        raise RuntimeError(
            "Salesforce CPQ quote lines are missing required fields for preview: "
            + ", ".join(missing_required)
        )
    reference_field = {
        "product_id": "SBQQ__Product__c",
        "product_code": "SBQQ__ProductCode__c",
        "product_name": "SBQQ__ProductName__c",
    }[reference_type]
    if reference_field not in available_fields:
        raise RuntimeError(
            f"Salesforce CPQ quote lines do not expose `{reference_field}`, so Gremlin cannot resolve this {reference_type} preview deterministically."
        )
    select_fields = ["Id", "SBQQ__Quote__c", "SBQQ__Quantity__c"]
    for field_name in (
        "SBQQ__Product__c",
        "SBQQ__ProductName__c",
        "SBQQ__ProductCode__c",
        "SBQQ__ListPrice__c",
        "SBQQ__NetPrice__c",
        "SBQQ__Number__c",
    ):
        if field_name in available_fields:
            select_fields.append(field_name)
    escaped_quote_id = _soql_string_literal(quote_id)
    rows = sfdc_helpers.run_soql(
        (
            f"SELECT {', '.join(select_fields)} "
            f"FROM SBQQ__QuoteLine__c WHERE SBQQ__Quote__c = '{escaped_quote_id}' "
            "ORDER BY CreatedDate ASC LIMIT 200"
        ),
        org_alias=org_alias,
    )
    snapshots: list[_QuoteLineItemSnapshot] = []
    for row in rows:
        if not isinstance(row, dict):
            continue
        line_item_id = str(row.get("Id") or "").strip()
        if not line_item_id:
            continue
        product_name = (
            str(row.get("SBQQ__ProductName__c") or "").strip()
            or str(row.get("SBQQ__ProductCode__c") or "").strip()
            or str(row.get("SBQQ__Product__c") or "").strip()
            or line_item_id
        )
        product_code = str(row.get("SBQQ__ProductCode__c") or "").strip() or None
        snapshots.append(
            _QuoteLineItemSnapshot(
                line_item_id=line_item_id,
                quote_id=str(row.get("SBQQ__Quote__c") or quote_id).strip() or quote_id,
                object_name="SBQQ__QuoteLine__c",
                product_id=str(row.get("SBQQ__Product__c") or "").strip() or None,
                product_code=product_code,
                product_name=product_name,
                quantity=_coerce_float_value(row.get("SBQQ__Quantity__c")),
                unit_price=_coerce_float_value(row.get("SBQQ__ListPrice__c")),
                net_price=_coerce_float_value(row.get("SBQQ__NetPrice__c")),
                line_number=str(row.get("SBQQ__Number__c") or "").strip() or None,
            )
        )
    return snapshots


def _load_opportunity_pricebook_id(
    *,
    opportunity_id: str,
    org_alias: str | None,
) -> str | None:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    rows = sfdc_helpers.run_soql(
        (
            "SELECT Id, Pricebook2Id "
            f"FROM Opportunity WHERE Id = '{escaped_opportunity_id}' LIMIT 1"
        ),
        org_alias=org_alias,
    )
    if not rows or not isinstance(rows[0], dict):
        return None
    return str(rows[0].get("Pricebook2Id") or "").strip() or None


def _query_active_pricebook_entries(
    *,
    pricebook_id: str,
    reference_type: QuoteLineReferenceType,
    reference_value: str,
    org_alias: str | None,
) -> list[dict[str, Any]]:
    field_name = {
        "product_id": "Product2Id",
        "product_code": "Product2.ProductCode",
        "product_name": "Product2.Name",
    }[reference_type]
    escaped_pricebook_id = _soql_string_literal(pricebook_id)
    escaped_reference_value = _soql_string_literal(reference_value)
    query = (
        "SELECT Id, UnitPrice, Product2Id, Product2.Name, Product2.ProductCode "
        "FROM PricebookEntry "
        f"WHERE Pricebook2Id = '{escaped_pricebook_id}' "
        "AND IsActive = TRUE "
        f"AND {field_name} = '{escaped_reference_value}' "
        "LIMIT 5"
    )
    return list(sfdc_helpers.run_soql(query, org_alias=org_alias))


def _match_quote_line_items(
    *,
    line_items: list[_QuoteLineItemSnapshot],
    reference_type: QuoteLineReferenceType,
    reference_value: str,
) -> list[_QuoteLineItemSnapshot]:
    normalized_reference = _normalize_quote_product_reference(reference_value)
    matches: list[_QuoteLineItemSnapshot] = []
    for item in line_items:
        candidate = _quote_line_item_reference_value(item, reference_type)
        if not candidate:
            continue
        if _normalize_quote_product_reference(candidate) == normalized_reference:
            matches.append(item)
    return matches


def _quote_line_item_reference_value(
    item: _QuoteLineItemSnapshot,
    reference_type: QuoteLineReferenceType,
) -> str | None:
    if reference_type == "product_id":
        return item.product_id
    if reference_type == "product_code":
        return item.product_code
    return item.product_name


def _quote_line_item_model(item: _QuoteLineItemSnapshot) -> SellerQuoteLineItemV1:
    return SellerQuoteLineItemV1(
        line_item_id=item.line_item_id,
        object_name=item.object_name,
        quote_id=item.quote_id,
        product_id=item.product_id,
        product_code=item.product_code,
        product_name=item.product_name,
        quantity=item.quantity,
        quantity_display=_format_quantity(item.quantity),
        unit_price=item.unit_price,
        unit_price_display=_format_currency(item.unit_price),
        net_price=item.net_price,
        net_price_display=_format_currency(item.net_price),
        pricebook_entry_id=item.pricebook_entry_id,
        line_number=item.line_number,
    )


def _quote_line_item_from_pricebook_entry(
    *,
    quote_id: str,
    object_name: str,
    row: dict[str, Any],
    quantity: float,
) -> SellerQuoteLineItemV1:
    unit_price = _coerce_float_value(row.get("UnitPrice"))
    net_price = unit_price * quantity if unit_price is not None else None
    product_name = (
        str(row.get("Product2.Name") or "").strip()
        or str(row.get("Product2.ProductCode") or "").strip()
        or str(row.get("Product2Id") or "").strip()
        or "Resolved Product"
    )
    product_code = str(row.get("Product2.ProductCode") or "").strip() or None
    return SellerQuoteLineItemV1(
        object_name=object_name,
        quote_id=quote_id,
        product_id=str(row.get("Product2Id") or "").strip() or None,
        product_code=product_code,
        product_name=product_name,
        quantity=quantity,
        quantity_display=_format_quantity(quantity),
        unit_price=unit_price,
        unit_price_display=_format_currency(unit_price),
        net_price=net_price,
        net_price_display=_format_currency(net_price),
        pricebook_entry_id=str(row.get("Id") or "").strip() or None,
    )


def _quote_line_item_with_quantity(
    current_line: SellerQuoteLineItemV1,
    *,
    quantity: float,
) -> SellerQuoteLineItemV1:
    unit_price = current_line.unit_price
    if unit_price is None and current_line.net_price is not None and current_line.quantity not in (None, 0):
        unit_price = float(current_line.net_price) / float(current_line.quantity)
    net_price = unit_price * quantity if unit_price is not None else current_line.net_price
    return current_line.model_copy(
        update={
            "quantity": quantity,
            "quantity_display": _format_quantity(quantity),
            "net_price": net_price,
            "net_price_display": _format_currency(net_price),
        }
    )


def _quote_line_quantity_matches(current_quantity: float | None, proposed_quantity: float | None) -> bool:
    if current_quantity is None or proposed_quantity is None:
        return False
    return abs(float(current_quantity) - float(proposed_quantity)) < 0.0001


def _best_quote_header_field_mapping(
    *,
    field_mappings: list[FieldMappingCandidate],
    semantic_key: str,
    object_name: str,
) -> FieldMappingCandidate | None:
    candidates = [
        item
        for item in field_mappings
        if str(item.semantic_key or "").strip() == semantic_key
        and str(item.object_name or "").strip() == object_name
    ]
    if not candidates:
        return None
    return max(
        candidates,
        key=lambda item: (
            1 if bool(item.confirmed) else 0,
            float(item.confidence),
            str(item.field_name or "").lower(),
        ),
    )


def _load_quote_header_field_value(
    *,
    quote_id: str,
    object_name: str,
    field_name: str,
    org_alias: str | None,
) -> Any:
    escaped_quote_id = _soql_string_literal(quote_id)
    query = f"SELECT Id, {field_name} FROM {object_name} WHERE Id = '{escaped_quote_id}' LIMIT 1"
    rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
    if not rows:
        raise RuntimeError(f"Quote {quote_id} was not found while loading preview field {field_name}.")
    if not isinstance(rows[0], dict):
        raise RuntimeError("Salesforce SOQL response did not return a quote row dictionary.")
    return rows[0].get(field_name)


def _quote_field_preview_model(
    *,
    intent: QuoteIntentV1,
    field_mapping: FieldMappingCandidate,
    object_name: str,
    current_value: Any,
) -> SellerQuoteChangeFieldPreviewV1:
    proposed_value = _quote_intent_proposed_value(intent)
    return SellerQuoteChangeFieldPreviewV1(
        semantic_key=intent.semantic_key,
        label=intent.target_label,
        object_name=object_name,
        field_name=field_mapping.field_name,
        mapping_confidence=float(field_mapping.confidence),
        current_value=current_value,
        current_value_display=_quote_semantic_display_value(intent.semantic_key, current_value),
        proposed_value=proposed_value,
        proposed_value_display=intent.requested_value_display,
    )


def _quote_intent_proposed_value(intent: QuoteIntentV1) -> Any:
    if intent.semantic_key == "discount_pct":
        return intent.requested_discount_pct
    if intent.semantic_key == "term_months":
        return intent.requested_term_months
    return intent.requested_payment_terms


def _quote_semantic_display_value(semantic_key: str, value: Any) -> str:
    if value in (None, ""):
        return "Not currently populated"
    if semantic_key == "discount_pct":
        parsed = _coerce_float_value(value)
        return f"{parsed:.2f}%" if parsed is not None else str(value)
    if semantic_key == "term_months":
        parsed = _coerce_int_value(value)
        return f"{parsed} months" if parsed is not None else str(value)
    return str(value)


def _coerce_int_value(value: Any) -> int | None:
    if value in (None, ""):
        return None
    try:
        return int(round(float(str(value).replace(",", "").strip())))
    except Exception:
        return None


def _preview_quote_request_readiness(
    *,
    opportunity_id: str,
    crm_org_id: str,
    org_alias: str | None,
    state_dir: str,
    environment_profile: QuoteEnvironmentProfileV1,
    context: DealContextV1,
    quote_request: dict[str, Any],
    force_refresh: bool,
) -> QuoteReadinessResult:
    store = DealDeskStore(state_dir)
    config = store.load_effective_config(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
        default_loader=load_dealdesk_config,
    )
    update_events = store.list_pattern_update_events(crm_org_id=crm_org_id, org_alias=org_alias)
    historical_rows: list[dict[str, Any]] = []
    pattern_profile = None if force_refresh else store.load_deal_pattern_profile(
        crm_org_id=crm_org_id,
        org_alias=org_alias,
    )
    if pattern_profile is None or _pattern_profile_stale(pattern_profile, update_events):
        historical_rows = fetch_historical_opportunities(org_alias=org_alias)
        pattern_profile = build_deal_pattern_profile(
            crm_org_id=crm_org_id,
            generated_at=datetime.now(timezone.utc).isoformat(),
            records=historical_rows,
            org_alias=org_alias,
            config=config,
            update_events=update_events,
        )
    if not historical_rows:
        historical_rows = fetch_historical_opportunities(org_alias=org_alias)
    opportunity_snapshot = _fetch_opportunity_snapshot(
        opportunity_id=opportunity_id,
        environment_profile=environment_profile,
        org_alias=org_alias,
    )
    preview_readiness, _preview_context = evaluate_quote_readiness(
        opportunity_id=opportunity_id,
        crm_org_id=crm_org_id,
        generated_at=datetime.now(timezone.utc).isoformat(),
        environment_profile=environment_profile,
        pattern_profile=pattern_profile,
        quote_request=quote_request,
        opportunity_snapshot=opportunity_snapshot,
        existing_context=context.model_copy(deep=True),
        historical_records=historical_rows,
        update_events=update_events,
    )
    return preview_readiness


def _preview_seller_quote_line_item_revision(
    *,
    intent: QuoteIntentV1,
    store: DealDeskStore,
    readiness: QuoteReadinessResult,
    context: DealContextV1,
    environment_profile: QuoteEnvironmentProfileV1,
    quote_status: SellerQuoteStatusResultV1,
) -> SellerQuoteRevisionPreviewV1:
    del store
    product_reference = str(intent.requested_product_reference or "").strip()
    reference_type = intent.requested_product_reference_type or "product_code"
    apply_support_reason = (
        "Guided line-item apply requires an exact current line or exact active SKU resolution on a supported standard quote."
    )
    line_preview = SellerQuoteLineItemPreviewV1(
        operation=intent.operation,  # type: ignore[arg-type]
        target_label=intent.target_label,
        line_object_name=_quote_line_item_object_name(quote_status.detected_engine),
        product_reference_type=reference_type,
        product_reference_value=product_reference,
    )
    evidence = list(quote_status.evidence)
    evidence.append(
        SellerQuoteEvidenceV1(
            source_type="quote_intent",
            label="Requested Change",
            detail=(
                f"{intent.target_label} preview normalized `{intent.requested_value_raw}` "
                f"to `{intent.requested_value_display}`."
            ),
        )
    )

    def _build_result(
        *,
        status: QuotePreviewStatus,
        support_reason: str = "",
        capability_gaps: list[str] | None = None,
        preview_policy_state: QuotePreviewPolicyState,
        preview_policy_reasons: list[str] | None = None,
        line_item_preview: SellerQuoteLineItemPreviewV1 | None = None,
        evidence_rows: list[SellerQuoteEvidenceV1] | None = None,
        next_step: str = "",
    ) -> SellerQuoteRevisionPreviewV1:
        return SellerQuoteRevisionPreviewV1(
            opportunity_id=intent.opportunity_id,
            crm_org_id=intent.crm_org_id,
            org_alias=intent.org_alias,
            context_id=context.context_id,
            status=status,
            detected_engine=quote_status.detected_engine,
            support_reason=support_reason,
            capability_gaps=list(capability_gaps or []),
            readiness_mode=readiness.readiness_mode,
            intent=intent,
            selected_quote=quote_status.selected_quote,
            line_item_preview=line_item_preview,
            approval_state=quote_status.approval_state,
            preview_readiness_mode=readiness.readiness_mode,
            preview_policy_state=preview_policy_state,
            preview_policy_reasons=list(preview_policy_reasons or []),
            matched_approval_route_names=list(quote_status.matched_approval_route_names),
            recommended_approval_roles=[],
            apply_supported=False,
            apply_support_reason=apply_support_reason,
            evidence=list(evidence_rows or []),
            next_step=next_step,
        )

    if quote_status.status in {"unsupported", "ambiguous", "no_quote"} or quote_status.selected_quote is None:
        preview_status: QuotePreviewStatus = (
            "ambiguous"
            if quote_status.status == "ambiguous"
            else "no_quote"
            if quote_status.status == "no_quote"
            else "unsupported"
        )
        unresolved_preview = line_preview.model_copy(
            update={
                "resolution_status": "ambiguous" if preview_status == "ambiguous" else "unsupported",
                "resolution_reason": quote_status.support_reason or quote_status.next_step,
            }
        )
        reasons = [item for item in [quote_status.support_reason, quote_status.next_step] if item]
        return _build_result(
            status=preview_status,
            support_reason=quote_status.support_reason,
            capability_gaps=list(quote_status.capability_gaps),
            preview_policy_state="unsupported",
            preview_policy_reasons=reasons,
            line_item_preview=unresolved_preview,
            evidence_rows=evidence,
            next_step=quote_status.next_step,
        )

    capability_profile = environment_profile.adapter_capability_profile
    supported_capabilities = (
        set(capability_profile.supported_capabilities or []) if capability_profile is not None else set()
    )
    if "read_line_items" not in supported_capabilities:
        support_reason = "The detected quote stack does not currently advertise read_line_items support for guided line-item preview."
        capability_gaps = list(quote_status.capability_gaps)
        capability_gaps.append("Line-item preview requires CRM-visible quote line objects on the supported quote stack.")
        unresolved_preview = line_preview.model_copy(
            update={
                "resolution_status": "unsupported",
                "resolution_reason": support_reason,
            }
        )
        return _build_result(
            status="unsupported",
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            preview_policy_state="unsupported",
            preview_policy_reasons=[support_reason],
            line_item_preview=unresolved_preview,
            evidence_rows=evidence,
            next_step="Use the native quote tool or the control-plane quote review surface for line-item changes on this stack.",
        )

    try:
        line_items = _load_supported_quote_line_items(
            quote_id=quote_status.selected_quote.quote_id,
            detected_engine=quote_status.detected_engine,
            org_alias=intent.org_alias,
            reference_type=reference_type,
        )
    except Exception as exc:
        support_reason = str(exc) or "Unable to load quote line items for preview."
        capability_gaps = list(quote_status.capability_gaps)
        capability_gaps.append(support_reason)
        unresolved_preview = line_preview.model_copy(
            update={
                "resolution_status": "unsupported",
                "resolution_reason": support_reason,
            }
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_line_inventory",
                label="Quote Line Inventory",
                detail=f"Gremlin could not load the selected quote lines: {support_reason}",
            )
        )
        return _build_result(
            status="unsupported",
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            preview_policy_state="unsupported",
            preview_policy_reasons=[support_reason],
            line_item_preview=unresolved_preview,
            evidence_rows=evidence,
            next_step="Use the native quote tool for this line-item change until RevOps confirms the quote-line surface for this org.",
        )

    evidence.append(
        SellerQuoteEvidenceV1(
            source_type="quote_line_inventory",
            label="Quote Line Inventory",
            detail=(
                f"Gremlin loaded {len(line_items)} `{line_preview.line_object_name}` row(s) from the selected quote "
                f"`{quote_status.selected_quote.label}`."
            ),
        )
    )
    policy_state = _quote_preview_policy_state(quote_status=quote_status, preview_readiness=None)
    policy_reasons = _quote_line_item_preview_policy_reasons(quote_status)
    if intent.operation == "remove_product" and policy_state == "clean":
        policy_state = "approval_likely"
        policy_reasons = [
            "Removing a quote line is destructive, so Gremlin keeps this change approval-gated in Slack.",
            *policy_reasons,
        ][:6]

    if intent.operation == "add_product":
        return _preview_quote_add_product_line_item(
            intent=intent,
            quote_status=quote_status,
            line_preview=line_preview,
            line_items=line_items,
            policy_state=policy_state,
            policy_reasons=policy_reasons,
            evidence=evidence,
            context_id=context.context_id,
            readiness_mode=readiness.readiness_mode,
        )

    return _preview_quote_existing_line_item_change(
        intent=intent,
        quote_status=quote_status,
        line_preview=line_preview,
        line_items=line_items,
        policy_state=policy_state,
        policy_reasons=policy_reasons,
        evidence=evidence,
        context_id=context.context_id,
        readiness_mode=readiness.readiness_mode,
    )


def _quote_preview_policy_reasons(
    *,
    quote_status: SellerQuoteStatusResultV1,
    preview_readiness: QuoteReadinessResult | None,
    preview_readiness_error: str | None,
) -> list[str]:
    reasons: list[str] = []
    if quote_status.selected_quote is not None and not _quote_is_active_status(quote_status.selected_quote.status):
        reasons.append(
            f"Selected quote `{quote_status.selected_quote.label}` is in terminal status `{quote_status.selected_quote.status}`."
        )
    if quote_status.conflict_reasons:
        reasons.extend(quote_status.conflict_reasons[:2])
    if quote_status.stale_reasons:
        reasons.extend(quote_status.stale_reasons[:2])
    if quote_status.approval_state == "pending":
        reasons.append("The current quote already has an approval process in flight.")
    if quote_status.matched_approval_route_names:
        reasons.append(
            "Current deal shape matches approval route(s): "
            + ", ".join(quote_status.matched_approval_route_names)
            + "."
        )
    if preview_readiness is not None:
        warning_messages = [
            issue.message
            for issue in preview_readiness.issues
            if issue.severity in {"blocking", "warning"}
        ]
        reasons.extend(warning_messages[:3])
        if preview_readiness.recommended_approval_roles:
            reasons.append(
                "Preview suggests approver role(s): "
                + ", ".join(preview_readiness.recommended_approval_roles)
                + "."
            )
    elif preview_readiness_error:
        reasons.append(f"Preview readiness analysis was unavailable: {preview_readiness_error}")
    deduped: list[str] = []
    seen: set[str] = set()
    for reason in reasons:
        normalized = str(reason or "").strip()
        if not normalized:
            continue
        key = normalized.lower()
        if key in seen:
            continue
        seen.add(key)
        deduped.append(normalized)
    return deduped[:6]


def _quote_line_item_preview_policy_reasons(
    quote_status: SellerQuoteStatusResultV1,
) -> list[str]:
    reasons = _quote_preview_policy_reasons(
        quote_status=quote_status,
        preview_readiness=None,
        preview_readiness_error=None,
    )
    reasons.append(
        "Line-item policy coverage is still narrow; Gremlin is relying on the current line diff and exact SKU resolution for this guided change."
    )
    deduped: list[str] = []
    seen: set[str] = set()
    for reason in reasons:
        normalized = str(reason or "").strip()
        if not normalized:
            continue
        lowered = normalized.lower()
        if lowered in seen:
            continue
        seen.add(lowered)
        deduped.append(normalized)
    return deduped[:6]


def _quote_line_item_preview_next_step(
    *,
    operation: QuoteIntentOperation,
    quote_status: SellerQuoteStatusResultV1,
    preview_policy_state: QuotePreviewPolicyState,
) -> str:
    if quote_status.selected_quote is not None and not _quote_is_active_status(quote_status.selected_quote.status):
        return "Preview only in this slice. The selected quote is already in a terminal status, so line-item changes should stay in the native tool."
    if quote_status.conflict:
        return "Preview only in this slice. Resolve the conflicting quote evidence with RevOps before relying on a line-item change."
    if quote_status.stale:
        return "Preview only in this slice. Refresh the stale quote in the native tool before relying on this line-item diff."
    if quote_status.detected_engine != "standard_quotes":
        return "Preview only in this slice. Guided line-item apply currently supports Salesforce Standard Quotes only, so this stack remains preview-only."
    if operation == "remove_product":
        return "If this removal diff is correct, request approval to remove the line from the current standard quote."
    if preview_policy_state == "approval_likely":
        return "If this line-item diff is correct, request approval to apply it on the current standard quote."
    if preview_policy_state == "clean":
        return "If this line-item diff is correct, you can apply it directly from Slack on the current standard quote."
    if operation == "add_product":
        return "Use this SKU-resolution diff to confirm the exact product before applying it on the current standard quote."
    return "Use this quantity diff to confirm the exact current line before applying it on the current standard quote."


def _quote_revision_apply_support(
    preview: SellerQuoteRevisionPreviewV1,
    *,
    capability_profile: QuoteAdapterCapabilityProfileV1 | None = None,
) -> tuple[bool, str]:
    adapter = resolve_quote_adapter(detected_engine=preview.detected_engine)
    if adapter is None:
        return False, "Guided quote apply is not available for this quote stack."
    adapter_supported, adapter_reason = adapter.preview_apply_support(preview=preview)
    if preview.line_item_preview is not None:
        return adapter_supported, adapter_reason
    header_supported, header_reason = _quote_header_apply_support(
        capability_profile=capability_profile,
        detected_engine=preview.detected_engine,
        adapter=adapter,
        adapter_apply_supported=adapter_supported,
    )
    if not header_supported:
        return False, header_reason
    return adapter_supported, adapter_reason


def _with_quote_revision_apply_support(
    preview: SellerQuoteRevisionPreviewV1,
    *,
    capability_profile: QuoteAdapterCapabilityProfileV1 | None = None,
) -> SellerQuoteRevisionPreviewV1:
    apply_supported, apply_support_reason = _quote_revision_apply_support(
        preview,
        capability_profile=capability_profile,
    )
    return preview.model_copy(
        update={
            "apply_supported": apply_supported,
            "apply_support_reason": apply_support_reason,
        }
    )


def _seller_quote_line_item_preview_result(
    *,
    intent: QuoteIntentV1,
    quote_status: SellerQuoteStatusResultV1,
    context_id: str | None,
    readiness_mode: str,
    status: QuotePreviewStatus,
    support_reason: str,
    capability_gaps: list[str],
    preview_policy_state: QuotePreviewPolicyState,
    preview_policy_reasons: list[str],
    line_item_preview: SellerQuoteLineItemPreviewV1,
    evidence: list[SellerQuoteEvidenceV1],
    next_step: str,
) -> SellerQuoteRevisionPreviewV1:
    preview = SellerQuoteRevisionPreviewV1(
        opportunity_id=intent.opportunity_id,
        crm_org_id=intent.crm_org_id,
        org_alias=intent.org_alias,
        context_id=context_id,
        status=status,
        detected_engine=quote_status.detected_engine,
        support_reason=support_reason,
        capability_gaps=list(capability_gaps),
        readiness_mode=readiness_mode,
        intent=intent,
        selected_quote=quote_status.selected_quote,
        line_item_preview=line_item_preview,
        approval_state=quote_status.approval_state,
        preview_readiness_mode=readiness_mode,
        preview_policy_state=preview_policy_state,
        preview_policy_reasons=list(preview_policy_reasons),
        matched_approval_route_names=list(quote_status.matched_approval_route_names),
        recommended_approval_roles=[],
        evidence=list(evidence),
        next_step=next_step,
    )
    return _with_quote_revision_apply_support(preview)


def _preview_quote_add_product_line_item(
    *,
    intent: QuoteIntentV1,
    quote_status: SellerQuoteStatusResultV1,
    line_preview: SellerQuoteLineItemPreviewV1,
    line_items: list[_QuoteLineItemSnapshot],
    policy_state: QuotePreviewPolicyState,
    policy_reasons: list[str],
    evidence: list[SellerQuoteEvidenceV1],
    context_id: str | None,
    readiness_mode: str,
) -> SellerQuoteRevisionPreviewV1:
    product_reference = str(intent.requested_product_reference or "").strip()
    reference_type = intent.requested_product_reference_type or "product_code"
    matched_lines = _match_quote_line_items(
        line_items=line_items,
        reference_type=reference_type,
        reference_value=product_reference,
    )
    matched_models = [_quote_line_item_model(item) for item in matched_lines[:3]]
    if matched_lines:
        resolution_reason = (
            f"Exact {_quote_line_reference_label(reference_type)} `{product_reference}` is already present on the selected quote."
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_line_resolution",
                label="Current Line Match",
                detail=resolution_reason,
            )
        )
        preview = line_preview.model_copy(
            update={
                "resolution_status": "unsupported",
                "resolution_reason": resolution_reason,
                "current_lines": matched_models,
            }
        )
        capability_gaps = list(quote_status.capability_gaps)
        capability_gaps.append(
            "Gremlin does not create duplicate quote lines in this slice; use quantity preview for the existing product line instead."
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="unsupported",
            support_reason="The requested product is already on the selected quote.",
            capability_gaps=capability_gaps,
            preview_policy_state="unsupported",
            preview_policy_reasons=[resolution_reason, *policy_reasons[:3]],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Use the quantity preview for the existing product line, or adjust the quote manually in the native tool.",
        )

    pricebook_id = _load_opportunity_pricebook_id(
        opportunity_id=intent.opportunity_id,
        org_alias=intent.org_alias,
    )
    if not pricebook_id:
        support_reason = "Opportunity pricebook is not populated, so Gremlin cannot resolve an add-product preview against the active SKU catalog."
        preview = line_preview.model_copy(
            update={
                "resolution_status": "unsupported",
                "resolution_reason": support_reason,
            }
        )
        capability_gaps = list(quote_status.capability_gaps)
        capability_gaps.append(
            "Add-product preview requires an active Opportunity pricebook for exact PricebookEntry resolution."
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="unsupported",
            support_reason=support_reason,
            capability_gaps=capability_gaps,
            preview_policy_state="unsupported",
            preview_policy_reasons=[support_reason],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Set the deal pricebook in Salesforce first, then retry the preview with an exact SKU or product name.",
        )

    pricebook_matches = _query_active_pricebook_entries(
        pricebook_id=pricebook_id,
        reference_type=reference_type,
        reference_value=product_reference,
        org_alias=intent.org_alias,
    )
    if not pricebook_matches:
        resolution_reason = (
            f"No active PricebookEntry matched {_quote_line_reference_label(reference_type)} "
            f"`{product_reference}` in Opportunity pricebook `{pricebook_id}`."
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="pricebook_resolution",
                label="SKU Resolution",
                detail=resolution_reason,
            )
        )
        preview = line_preview.model_copy(
            update={
                "resolution_status": "not_found",
                "resolution_reason": resolution_reason,
            }
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="unsupported",
            support_reason="Gremlin could not resolve the requested product in the active deal pricebook.",
            capability_gaps=list(quote_status.capability_gaps),
            preview_policy_state="unsupported",
            preview_policy_reasons=[resolution_reason],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Retry with the exact product code or confirm that the SKU is active in the current pricebook.",
        )
    if len(pricebook_matches) > 1:
        resolution_reason = (
            f"Multiple active PricebookEntry rows matched {_quote_line_reference_label(reference_type)} "
            f"`{product_reference}` in Opportunity pricebook `{pricebook_id}`."
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="pricebook_resolution",
                label="SKU Resolution",
                detail=resolution_reason,
            )
        )
        preview = line_preview.model_copy(
            update={
                "resolution_status": "ambiguous",
                "resolution_reason": resolution_reason,
            }
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="ambiguous",
            support_reason="Multiple active SKUs matched the requested product reference.",
            capability_gaps=list(quote_status.capability_gaps),
            preview_policy_state="unsupported",
            preview_policy_reasons=[resolution_reason],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Retry with a more exact product code or ask RevOps which SKU is authoritative for this deal.",
        )

    proposed_line = _quote_line_item_from_pricebook_entry(
        quote_id=str(quote_status.selected_quote.quote_id or "").strip(),
        object_name=line_preview.line_object_name,
        row=pricebook_matches[0],
        quantity=float(intent.requested_quantity or 0.0),
    )
    resolution_reason = (
        f"Resolved exact {_quote_line_reference_label(reference_type)} `{product_reference}` "
        f"to active PricebookEntry `{proposed_line.pricebook_entry_id}`."
    )
    evidence.append(
        SellerQuoteEvidenceV1(
            source_type="pricebook_resolution",
            label="SKU Resolution",
            detail=resolution_reason,
        )
    )
    diff_lines = [
        f"- *Action:* Add `{proposed_line.product_name}` to the selected quote.",
        f"- *Quantity:* `{proposed_line.quantity_display}`",
    ]
    if proposed_line.unit_price is not None:
        diff_lines.append(f"- *Default unit price:* `{proposed_line.unit_price_display}`")
    preview = line_preview.model_copy(
        update={
            "resolution_status": "resolved",
            "resolution_reason": resolution_reason,
            "proposed_line": proposed_line,
            "diff_lines": diff_lines,
        }
    )
    return _seller_quote_line_item_preview_result(
        intent=intent,
        quote_status=quote_status,
        context_id=context_id,
        readiness_mode=readiness_mode,
        status="preview_ready",
        support_reason=quote_status.support_reason,
        capability_gaps=list(quote_status.capability_gaps),
        preview_policy_state=policy_state,
        preview_policy_reasons=policy_reasons,
        line_item_preview=preview,
        evidence=evidence,
        next_step=_quote_line_item_preview_next_step(
            operation=intent.operation,
            quote_status=quote_status,
            preview_policy_state=policy_state,
        ),
    )


def _preview_quote_existing_line_item_change(
    *,
    intent: QuoteIntentV1,
    quote_status: SellerQuoteStatusResultV1,
    line_preview: SellerQuoteLineItemPreviewV1,
    line_items: list[_QuoteLineItemSnapshot],
    policy_state: QuotePreviewPolicyState,
    policy_reasons: list[str],
    evidence: list[SellerQuoteEvidenceV1],
    context_id: str | None,
    readiness_mode: str,
) -> SellerQuoteRevisionPreviewV1:
    product_reference = str(intent.requested_product_reference or "").strip()
    reference_type = intent.requested_product_reference_type or "product_code"
    matched_lines = _match_quote_line_items(
        line_items=line_items,
        reference_type=reference_type,
        reference_value=product_reference,
    )
    matched_models = [_quote_line_item_model(item) for item in matched_lines[:3]]
    if not matched_lines:
        resolution_reason = (
            f"No current quote line matched {_quote_line_reference_label(reference_type)} `{product_reference}`."
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_line_resolution",
                label="Current Line Match",
                detail=resolution_reason,
            )
        )
        preview = line_preview.model_copy(
            update={
                "resolution_status": "not_found",
                "resolution_reason": resolution_reason,
            }
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="unsupported",
            support_reason="Gremlin could not find that product on the selected quote.",
            capability_gaps=list(quote_status.capability_gaps),
            preview_policy_state="unsupported",
            preview_policy_reasons=[resolution_reason],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Retry with the exact product code or product name already present on the current quote.",
        )
    if len(matched_lines) > 1:
        resolution_reason = (
            f"Multiple current quote lines matched {_quote_line_reference_label(reference_type)} `{product_reference}`."
        )
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_line_resolution",
                label="Current Line Match",
                detail=resolution_reason,
            )
        )
        preview = line_preview.model_copy(
            update={
                "resolution_status": "ambiguous",
                "resolution_reason": resolution_reason,
                "current_lines": matched_models,
            }
        )
        return _seller_quote_line_item_preview_result(
            intent=intent,
            quote_status=quote_status,
            context_id=context_id,
            readiness_mode=readiness_mode,
            status="ambiguous",
            support_reason="Gremlin found multiple current quote lines for the requested product reference.",
            capability_gaps=list(quote_status.capability_gaps),
            preview_policy_state="unsupported",
            preview_policy_reasons=[resolution_reason],
            line_item_preview=preview,
            evidence=evidence,
            next_step="Use a more exact product code or ask RevOps which current line should be changed.",
        )

    current_line = _quote_line_item_model(matched_lines[0])
    resolution_reason = (
        f"Matched current quote line `{current_line.product_name}` by "
        f"{_quote_line_reference_label(reference_type)} `{product_reference}`."
    )
    evidence.append(
        SellerQuoteEvidenceV1(
            source_type="quote_line_resolution",
            label="Current Line Match",
            detail=resolution_reason,
        )
    )
    if intent.operation == "remove_product":
        diff_lines = [
            f"- *Action:* Remove `{current_line.product_name}` from the selected quote.",
            f"- *Current quantity:* `{current_line.quantity_display}`",
        ]
        preview = line_preview.model_copy(
            update={
                "resolution_status": "resolved",
                "resolution_reason": resolution_reason,
                "current_lines": [current_line],
                "diff_lines": diff_lines,
            }
        )
    else:
        proposed_line = _quote_line_item_with_quantity(
            current_line,
            quantity=float(intent.requested_quantity or 0.0),
        )
        diff_lines = [
            f"- *Action:* Update `{current_line.product_name}` quantity on the selected quote.",
            f"- *Current quantity:* `{current_line.quantity_display}`",
            f"- *Proposed quantity:* `{proposed_line.quantity_display}`",
        ]
        if _quote_line_quantity_matches(current_line.quantity, proposed_line.quantity):
            diff_lines.append("- *Signal:* The current line already matches the requested quantity.")
        preview = line_preview.model_copy(
            update={
                "resolution_status": "resolved",
                "resolution_reason": resolution_reason,
                "current_lines": [current_line],
                "proposed_line": proposed_line,
                "diff_lines": diff_lines,
            }
        )
    return _seller_quote_line_item_preview_result(
        intent=intent,
        quote_status=quote_status,
        context_id=context_id,
        readiness_mode=readiness_mode,
        status="preview_ready",
        support_reason=quote_status.support_reason,
        capability_gaps=list(quote_status.capability_gaps),
        preview_policy_state=policy_state,
        preview_policy_reasons=policy_reasons,
        line_item_preview=preview,
        evidence=evidence,
        next_step=_quote_line_item_preview_next_step(
            operation=intent.operation,
            quote_status=quote_status,
            preview_policy_state=policy_state,
        ),
    )


def _quote_preview_policy_state(
    *,
    quote_status: SellerQuoteStatusResultV1,
    preview_readiness: QuoteReadinessResult | None,
) -> QuotePreviewPolicyState:
    if quote_status.status in {"unsupported", "ambiguous", "no_quote"}:
        return "unsupported"
    if quote_status.selected_quote is not None and not _quote_is_active_status(quote_status.selected_quote.status):
        return "review_required"
    if quote_status.conflict:
        return "review_required"
    if preview_readiness is not None and any(issue.severity == "blocking" for issue in preview_readiness.issues):
        return "review_required"
    if quote_status.stale:
        return "review_required"
    if preview_readiness is not None and (
        preview_readiness.readiness_mode in {"review_required", "unsupported", "insufficient_evidence"}
        or any(issue.severity == "warning" for issue in preview_readiness.issues)
    ):
        return "approval_likely"
    if quote_status.approval_state in {"pending", "not_requested"} or quote_status.matched_approval_route_names:
        return "approval_likely"
    return "clean"


def _quote_preview_evidence(
    *,
    intent: QuoteIntentV1,
    field_mapping: FieldMappingCandidate,
    field_preview: SellerQuoteChangeFieldPreviewV1,
    preview_readiness: QuoteReadinessResult | None,
    preview_readiness_error: str | None,
    current_value_load_error: str | None,
) -> list[SellerQuoteEvidenceV1]:
    evidence = [
        SellerQuoteEvidenceV1(
            source_type="quote_intent",
            label="Requested Change",
            detail=f"{intent.target_label} preview normalized `{intent.requested_value_raw}` to `{intent.requested_value_display}`.",
        ),
        SellerQuoteEvidenceV1(
            source_type="field_mapping",
            label="Resolved Quote Field",
            detail=(
                f"Mapped `{intent.semantic_key}` to `{field_preview.object_name}.{field_preview.field_name}` "
                f"(confidence {field_mapping.confidence:.2f})."
            ),
        ),
    ]
    if current_value_load_error:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_field_read",
                label="Current Quote Value",
                detail=f"Current field value could not be loaded: {current_value_load_error}",
            )
        )
    else:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="quote_field_read",
                label="Current Quote Value",
                detail=(
                    f"Gremlin read `{field_preview.object_name}.{field_preview.field_name}` as "
                    f"`{field_preview.current_value_display}` on the selected quote."
                ),
            )
        )
    if preview_readiness is not None:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="preview_readiness",
                label="Readiness Preview",
                detail=(
                    f"Preview quote-readiness mode is `{preview_readiness.readiness_mode}` with "
                    f"{len(preview_readiness.issues)} issue(s) and "
                    f"{len(preview_readiness.recommended_approval_roles)} recommended approver role(s)."
                ),
            )
        )
    elif preview_readiness_error:
        evidence.append(
            SellerQuoteEvidenceV1(
                source_type="preview_readiness",
                label="Readiness Preview",
                detail=f"Preview readiness evaluation was unavailable: {preview_readiness_error}",
            )
        )
    return evidence


def _quote_preview_next_step(
    *,
    apply_supported: bool,
    preview_policy_state: QuotePreviewPolicyState,
    quote_status: SellerQuoteStatusResultV1,
    preview_readiness: QuoteReadinessResult | None,
) -> str:
    if quote_status.selected_quote is not None and not _quote_is_active_status(quote_status.selected_quote.status):
        return "Preview only in this slice. The selected quote is already in a terminal status, so guided header updates should not run on it."
    if quote_status.conflict:
        return "Preview is available, but the current quote has conflicting evidence. Ask RevOps to reconcile the quote before guided revision is enabled."
    if quote_status.stale:
        return "Preview is available, but the current quote is stale. Refresh the quote in the native tool before relying on guided revision."
    if apply_supported and preview_policy_state == "approval_likely":
        return "If this field diff is correct, request approval to apply it on the current quote."
    if apply_supported and preview_policy_state == "clean":
        return "If this field diff is correct, you can apply it directly from Slack on the current quote."
    if preview_policy_state == "approval_likely":
        return "Preview only in this slice. This change likely needs approval or RevOps review once guided apply is enabled."
    if preview_policy_state == "review_required":
        if preview_readiness is not None and preview_readiness.readiness_mode != "ready":
            return (
                "Preview only in this slice. Review the highlighted policy and readiness signals before changing the quote in the native tool."
            )
        return "Preview only in this slice. Review the quote status and approval context before making the change in the native tool."
    return "Preview only in this slice. No quote changes were applied; use this preview to validate the edit before updating the native quote."


def _quote_header_apply_support(
    *,
    capability_profile: QuoteAdapterCapabilityProfileV1 | None,
    detected_engine: str,
    adapter: Any | None = None,
    adapter_apply_supported: bool | None = None,
) -> tuple[bool, str]:
    if capability_profile is None:
        if adapter_apply_supported is False:
            return True, ""
        resolved_adapter = adapter or resolve_quote_adapter(detected_engine=detected_engine)
        if resolved_adapter is not None and resolved_adapter.allow_header_apply_without_capability_profile():
            return True, ""
        return (
            False,
            "Guided quote apply for this quote stack remains preview-only until capability discovery verifies `update_quote` support.",
        )
    supported_capabilities = set(capability_profile.supported_capabilities or [])
    if "update_quote" not in supported_capabilities:
        return (
            False,
            "Guided quote apply is not available because this stack does not advertise `update_quote` support.",
        )
    execution_verified_capabilities = set(capability_profile.execution_verified_capabilities or [])
    if "update_quote" in execution_verified_capabilities:
        return True, ""
    if detected_engine == "salesforce_cpq":
        return (
            False,
            "Guided quote apply for Salesforce CPQ remains preview-only in this slice. Gremlin can show the header diff, but quote mutation is not execution-verified yet.",
        )
    return (
        False,
        "Guided quote apply for this quote stack remains preview-only because `update_quote` is not execution-verified yet.",
    )


def _quote_header_apply_capability_gaps(
    *,
    capability_profile: QuoteAdapterCapabilityProfileV1 | None,
    apply_supported: bool,
) -> list[str]:
    if capability_profile is None or apply_supported:
        return []
    supported_capabilities = set(capability_profile.supported_capabilities or [])
    if "update_quote" not in supported_capabilities:
        return []
    gaps = [
        "`update_quote` remains inference-only on this stack, so guided header apply stays preview-only.",
    ]
    execution_verified = list(capability_profile.execution_verified_capabilities or [])
    if execution_verified:
        gaps.append(
            "Execution-verified today: "
            + ", ".join(f"`{item}`" for item in execution_verified[:4])
            + ("." if len(execution_verified) <= 4 else ", ...")
        )
    return gaps


def _quote_is_active_status(status: str | None) -> bool:
    status_tokens = {
        token
        for token in re.split(r"[^a-z0-9]+", str(status or "").strip().lower())
        if token
    }
    return not bool(status_tokens & _SELLER_ACTIVE_QUOTE_TERMINAL_STATUS_TOKENS)


def _quote_header_values_match(
    *,
    semantic_key: str,
    current_value: Any,
    proposed_value: Any,
) -> bool:
    if semantic_key == "discount_pct":
        current_float = _coerce_float_value(current_value)
        proposed_float = _coerce_float_value(proposed_value)
        if current_float is None or proposed_float is None:
            return False
        return abs(current_float - proposed_float) < 0.0001
    if semantic_key == "term_months":
        current_int = _coerce_int_value(current_value)
        proposed_int = _coerce_int_value(proposed_value)
        if current_int is None or proposed_int is None:
            return False
        return current_int == proposed_int
    if semantic_key == "payment_terms":
        return str(current_value or "").strip().lower() == str(proposed_value or "").strip().lower()
    return current_value == proposed_value


def _quote_revision_risk_level(preview_policy_state: QuotePreviewPolicyState) -> int:
    return 0 if preview_policy_state == "clean" else 1


def _seller_quote_revision_approval_context_path(
    *,
    state_dir: str | None,
    run_id: str,
) -> Path:
    return Path(state_dir or ".") / "pending" / str(run_id or "").strip() / "dealdesk_quote_change_context.json"


def _quote_revision_why_summary(preview: SellerQuoteRevisionPreviewV1) -> str:
    if preview.selected_quote is None:
        return "Seller requested a guided quote header change that requires review."
    signal_text = " ".join(str(item).strip() for item in list(preview.preview_policy_reasons or [])[:2] if str(item).strip())
    if preview.field_preview is not None:
        summary = (
            f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label} "
            f"from {preview.field_preview.current_value_display} to {preview.field_preview.proposed_value_display}. "
            f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
        )
    elif preview.line_item_preview is not None:
        current_line = preview.line_item_preview.current_lines[0] if preview.line_item_preview.current_lines else None
        proposed_line = preview.line_item_preview.proposed_line
        if preview.intent.operation == "add_product" and proposed_line is not None:
            summary = (
                f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label} "
                f"for {proposed_line.product_name} x {proposed_line.quantity_display}. "
                f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
            )
        elif preview.intent.operation == "update_quantity" and current_line is not None and proposed_line is not None:
            summary = (
                f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label} "
                f"for {current_line.product_name} from quantity {current_line.quantity_display} "
                f"to {proposed_line.quantity_display}. "
                f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
            )
        elif preview.intent.operation == "remove_product" and current_line is not None:
            summary = (
                f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label} "
                f"for {current_line.product_name} at quantity {current_line.quantity_display}. "
                f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
            )
        elif current_line is not None:
            summary = (
                f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label} "
                f"for {current_line.product_name}. "
                f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
            )
        else:
            summary = (
                f"Seller requested {preview.intent.target_label} on {preview.selected_quote.label}. "
                f"Preview policy state is {preview.preview_policy_state.replace('_', ' ')}."
            )
    else:
        summary = "Seller requested a guided quote change that requires review."
    if signal_text:
        summary += f" Signals: {signal_text}"
    return summary


def _quote_revision_diff_preview(preview: SellerQuoteRevisionPreviewV1) -> dict[str, Any]:
    if preview.selected_quote is None:
        return {}
    base = {
        "opportunity_id": preview.opportunity_id,
        "quote_id": preview.selected_quote.quote_id,
        "quote_label": preview.selected_quote.label,
        "quote_status": preview.selected_quote.status,
        "target_label": preview.intent.target_label,
        "preview_policy_state": preview.preview_policy_state,
        "preview_policy_reasons": list(preview.preview_policy_reasons or [])[:4],
        "matched_approval_routes": list(preview.matched_approval_route_names or [])[:4],
        "recommended_approval_roles": list(preview.recommended_approval_roles or [])[:4],
    }
    if preview.field_preview is not None:
        base.update(
            {
                "semantic_key": preview.field_preview.semantic_key,
                "resolved_field": f"{preview.field_preview.object_name}.{preview.field_preview.field_name}",
                "current_value": preview.field_preview.current_value_display,
                "proposed_value": preview.field_preview.proposed_value_display,
            }
        )
        return base
    if preview.line_item_preview is not None:
        current_lines = [
            {
                "line_item_id": item.line_item_id,
                "product_code": item.product_code,
                "product_name": item.product_name,
                "quantity": item.quantity_display,
                "unit_price": item.unit_price_display,
            }
            for item in list(preview.line_item_preview.current_lines or [])[:2]
        ]
        proposed_line = preview.line_item_preview.proposed_line
        base.update(
            {
                "semantic_key": "line_item",
                "operation": preview.line_item_preview.operation,
                "line_object_name": preview.line_item_preview.line_object_name,
                "product_reference_type": preview.line_item_preview.product_reference_type,
                "product_reference_value": preview.line_item_preview.product_reference_value,
                "resolution_status": preview.line_item_preview.resolution_status,
                "current_lines": current_lines,
                "proposed_line": (
                    {
                        "line_item_id": proposed_line.line_item_id,
                        "product_code": proposed_line.product_code,
                        "product_name": proposed_line.product_name,
                        "quantity": proposed_line.quantity_display,
                        "unit_price": proposed_line.unit_price_display,
                    }
                    if proposed_line is not None
                    else None
                ),
                "diff_lines": list(preview.line_item_preview.diff_lines or [])[:4],
            }
        )
        return base
    return base


def _build_standard_quote_line_item_revision_plan(
    *,
    preview: SellerQuoteRevisionPreviewV1,
    org_alias: str | None,
) -> PlanV1:
    if preview.selected_quote is None or preview.line_item_preview is None:
        raise RuntimeError("Quote line-item revision plan requires a selected quote and line-item preview.")
    if preview.detected_engine != "standard_quotes":
        raise RuntimeError("Guided line-item apply currently supports Salesforce Standard Quotes only.")
    run_id = (
        "dealdesk_seller_quote_change_"
        + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
        + "_"
        + secrets.token_hex(4)
    )
    line_preview = preview.line_item_preview
    risk_level = _quote_revision_risk_level(preview.preview_policy_state)
    if preview.intent.operation == "add_product":
        proposed_line = line_preview.proposed_line
        if proposed_line is None or not str(proposed_line.pricebook_entry_id or "").strip():
            raise RuntimeError("Add-product apply requires an exact proposed line with PricebookEntryId.")
        values: dict[str, Any] = {
            "QuoteId": preview.selected_quote.quote_id,
            "PricebookEntryId": proposed_line.pricebook_entry_id,
            "Quantity": proposed_line.quantity,
        }
        if proposed_line.unit_price is not None:
            values["UnitPrice"] = proposed_line.unit_price
        return PlanV1(
            run_id=run_id,
            source=PlanSource(type="seller_quote_revision"),
            summary=(
                f"Deal Desk seller change {preview.intent.target_label} on "
                f"{preview.selected_quote.quote_id}"
            ),
            source_kind="dealdesk_seller_quote_revision",
            why_summary=_quote_revision_why_summary(preview),
            evidence_ids=[
                preview.opportunity_id,
                preview.selected_quote.quote_id,
                preview.intent.semantic_key,
                preview.intent.requested_value_display,
            ],
            steps=[
                PlanStep(
                    step_id="seller_add_quote_line_item",
                    tool="sfdc.record.create",
                    args={
                        "sobject": "QuoteLineItem",
                        "values": values,
                        "org_alias": org_alias,
                    },
                    diff_preview=_quote_revision_diff_preview(preview),
                    risk_level=risk_level,
                    idempotency_key=(
                        f"seller_quote_revision:{preview.selected_quote.quote_id}:"
                        f"{proposed_line.pricebook_entry_id}:{json.dumps(values, sort_keys=True, default=str)}"
                    ),
                    evidence_ids=[
                        preview.opportunity_id,
                        preview.selected_quote.quote_id,
                        str(proposed_line.pricebook_entry_id),
                        preview.intent.requested_value_display,
                    ],
                )
            ],
            approvals_required=preview.preview_policy_state == "approval_likely",
        )
    if preview.intent.operation == "remove_product":
        current_line = line_preview.current_lines[0] if line_preview.current_lines else None
        if current_line is None or not str(current_line.line_item_id or "").strip():
            raise RuntimeError("Remove-product apply requires an exact current QuoteLineItem match.")
        return PlanV1(
            run_id=run_id,
            source=PlanSource(type="seller_quote_revision"),
            summary=(
                f"Deal Desk seller change {preview.intent.target_label} on "
                f"{preview.selected_quote.quote_id}"
            ),
            source_kind="dealdesk_seller_quote_revision",
            why_summary=_quote_revision_why_summary(preview),
            evidence_ids=[
                preview.opportunity_id,
                preview.selected_quote.quote_id,
                str(current_line.line_item_id),
                preview.intent.requested_value_display,
            ],
            steps=[
                PlanStep(
                    step_id="seller_remove_quote_line_item",
                    tool="sfdc.record.delete",
                    args={
                        "sobject": "QuoteLineItem",
                        "record_id": current_line.line_item_id,
                        "org_alias": org_alias,
                    },
                    diff_preview=_quote_revision_diff_preview(preview),
                    risk_level=risk_level,
                    idempotency_key=(
                        f"seller_quote_revision:{current_line.line_item_id}:delete:"
                        f"{json.dumps(current_line.line_item_id, sort_keys=True, default=str)}"
                    ),
                    evidence_ids=[
                        preview.opportunity_id,
                        preview.selected_quote.quote_id,
                        str(current_line.line_item_id),
                        preview.intent.requested_value_display,
                    ],
                )
            ],
            approvals_required=preview.preview_policy_state == "approval_likely",
        )
    if preview.intent.operation == "update_quantity":
        current_line = line_preview.current_lines[0] if line_preview.current_lines else None
        proposed_line = line_preview.proposed_line
        if current_line is None or proposed_line is None or not str(current_line.line_item_id or "").strip():
            raise RuntimeError("Quantity apply requires an exact current QuoteLineItem match.")
        return PlanV1(
            run_id=run_id,
            source=PlanSource(type="seller_quote_revision"),
            summary=(
                f"Deal Desk seller change {preview.intent.target_label} on "
                f"{preview.selected_quote.quote_id}"
            ),
            source_kind="dealdesk_seller_quote_revision",
            why_summary=_quote_revision_why_summary(preview),
            evidence_ids=[
                preview.opportunity_id,
                preview.selected_quote.quote_id,
                str(current_line.line_item_id),
                preview.intent.requested_value_display,
            ],
            steps=[
                PlanStep(
                    step_id="seller_update_quote_line_quantity",
                    tool="sfdc.record.update",
                    args={
                        "sobject": "QuoteLineItem",
                        "record_id": current_line.line_item_id,
                        "fields": {"Quantity": proposed_line.quantity},
                        "org_alias": org_alias,
                    },
                    diff_preview=_quote_revision_diff_preview(preview),
                    risk_level=risk_level,
                    idempotency_key=(
                        f"seller_quote_revision:{current_line.line_item_id}:Quantity:"
                        f"{json.dumps(proposed_line.quantity, sort_keys=True, default=str)}"
                    ),
                    evidence_ids=[
                        preview.opportunity_id,
                        preview.selected_quote.quote_id,
                        str(current_line.line_item_id),
                        preview.intent.requested_value_display,
                    ],
                )
            ],
            approvals_required=preview.preview_policy_state == "approval_likely",
        )
    raise RuntimeError("Guided line-item apply is not available for this requested operation.")


def _build_standard_quote_revision_plan(
    *,
    preview: SellerQuoteRevisionPreviewV1,
    org_alias: str | None,
) -> PlanV1:
    if not preview.apply_supported:
        raise RuntimeError(
            preview.apply_support_reason or "Guided quote apply is not enabled for this preview."
        )
    if preview.line_item_preview is not None:
        return _build_standard_quote_line_item_revision_plan(
            preview=preview,
            org_alias=org_alias,
        )
    if preview.selected_quote is None or preview.field_preview is None:
        raise RuntimeError("Quote revision plan requires a selected quote and field preview.")
    run_id = (
        "dealdesk_seller_quote_change_"
        + datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S")
        + "_"
        + secrets.token_hex(4)
    )
    field_name = preview.field_preview.field_name
    field_value = preview.field_preview.proposed_value
    risk_level = _quote_revision_risk_level(preview.preview_policy_state)
    return PlanV1(
        run_id=run_id,
        source=PlanSource(type="seller_quote_revision"),
        summary=(
            f"Deal Desk seller change {preview.intent.target_label} on "
            f"{preview.selected_quote.quote_id}"
        ),
        source_kind="dealdesk_seller_quote_revision",
        why_summary=_quote_revision_why_summary(preview),
        evidence_ids=[
            preview.opportunity_id,
            preview.selected_quote.quote_id,
            preview.intent.semantic_key,
            preview.intent.requested_value_display,
        ],
        steps=[
            PlanStep(
                step_id="seller_update_quote_header",
                tool="sfdc.record.update",
                args={
                    "sobject": preview.selected_quote.object_name,
                    "record_id": preview.selected_quote.quote_id,
                    "fields": {field_name: field_value},
                    "org_alias": org_alias,
                },
                diff_preview=_quote_revision_diff_preview(preview),
                risk_level=risk_level,
                idempotency_key=(
                    f"seller_quote_revision:{preview.selected_quote.quote_id}:"
                    f"{field_name}:{json.dumps(field_value, sort_keys=True, default=str)}"
                ),
                evidence_ids=[
                    preview.opportunity_id,
                    preview.selected_quote.quote_id,
                    field_name,
                    preview.intent.requested_value_display,
                ],
            )
        ],
        approvals_required=preview.preview_policy_state == "approval_likely",
    )


def _build_seller_quote_revision_plan(
    *,
    preview: SellerQuoteRevisionPreviewV1,
    org_alias: str | None,
) -> PlanV1:
    if not preview.apply_supported:
        raise RuntimeError(
            preview.apply_support_reason or "Guided quote apply is not enabled for this preview."
        )
    adapter = resolve_quote_adapter(detected_engine=preview.detected_engine)
    if adapter is None:
        raise RuntimeError(f"Guided quote apply is not available for quote stack `{preview.detected_engine}`.")
    return adapter.build_quote_revision_plan(preview=preview, org_alias=org_alias)


def _save_seller_quote_revision_event(
    *,
    store: DealDeskStore,
    preview: SellerQuoteRevisionPreviewV1,
    intent: QuoteIntentV1,
    source_receipt_id: str,
    receipt_dir: Path,
) -> None:
    if preview.selected_quote is None or (
        preview.field_preview is None and preview.line_item_preview is None
    ):
        return
    context = store.load_context(
        opportunity_id=preview.opportunity_id,
        crm_org_id=preview.crm_org_id,
        org_alias=preview.org_alias,
    )
    raw_record: dict[str, Any] = {
        "Id": preview.selected_quote.quote_id,
        "OpportunityId": preview.opportunity_id,
        "Status": preview.selected_quote.status,
    }
    custom: dict[str, Any] = {
        "engine": preview.detected_engine,
        "quote_id": preview.selected_quote.quote_id,
        "semantic_key": intent.semantic_key,
        "preview_policy_state": preview.preview_policy_state,
    }
    evidence_ids = [
        preview.opportunity_id,
        preview.selected_quote.quote_id,
        source_receipt_id,
        *[item.label for item in preview.evidence[:2]],
    ]
    if preview.field_preview is not None:
        raw_record[preview.field_preview.field_name] = preview.field_preview.proposed_value
        custom.update(
            {
                "header_only": True,
                "field_name": preview.field_preview.field_name,
            }
        )
    elif preview.line_item_preview is not None:
        line_preview = preview.line_item_preview
        line_model = line_preview.proposed_line or (line_preview.current_lines[0] if line_preview.current_lines else None)
        custom.update(
            {
                "header_only": False,
                "line_item": True,
                "operation": line_preview.operation,
                "line_object_name": line_preview.line_object_name,
                "product_reference_type": line_preview.product_reference_type,
                "product_reference_value": line_preview.product_reference_value,
            }
        )
        if line_model is not None:
            if line_model.line_item_id:
                raw_record["QuoteLineItemId"] = line_model.line_item_id
                evidence_ids.append(line_model.line_item_id)
            if line_model.product_id:
                raw_record["Product2Id"] = line_model.product_id
            if line_model.product_code:
                raw_record["ProductCode"] = line_model.product_code
                evidence_ids.append(line_model.product_code)
            raw_record["ProductName"] = line_model.product_name
            if line_model.pricebook_entry_id:
                raw_record["PricebookEntryId"] = line_model.pricebook_entry_id
            if line_model.quantity is not None:
                raw_record["Quantity"] = line_model.quantity
        raw_record["LineItemOperation"] = line_preview.operation
    event = build_pattern_update_event(
        source_type="quote_receipt",
        crm_org_id=preview.crm_org_id,
        opportunity_id=preview.opportunity_id,
        source_ref=str((receipt_dir / "receipt.json").resolve()),
        observed_at=utc_now_iso(),
        source_receipt_id=source_receipt_id,
        raw_record=raw_record,
        extracted_motion_id=context.inferred_motion_id if context is not None else None,
        confidence=1.0,
        discount_pct=intent.requested_discount_pct,
        term_months=intent.requested_term_months,
        payment_terms=intent.requested_payment_terms,
        outcome="updated",
        custom=custom,
        evidence_ids=evidence_ids,
    )
    save_pattern_update_events(
        store=store,
        events=[event],
        org_alias=preview.org_alias,
        refresh_profile=True,
    )


def _quote_is_active_candidate(record: _QuoteRecordSnapshot) -> bool:
    status_tokens = {
        token
        for token in re.split(r"[^a-z0-9]+", str(record.status or "").strip().lower())
        if token
    }
    return not bool(status_tokens & _SELLER_ACTIVE_QUOTE_TERMINAL_STATUS_TOKENS)


def _truthy(value: Any) -> bool:
    if isinstance(value, bool):
        return value
    return str(value or "").strip().lower() in {"1", "true", "yes", "y"}


def _coerce_float_value(*values: Any) -> float | None:
    for value in values:
        if value in (None, ""):
            continue
        try:
            return float(str(value).replace(",", "").strip())
        except Exception:
            continue
    return None


def _normalize_iso_date_value(value: Any) -> str | None:
    parsed = _parse_datetime_value(value)
    if parsed is None:
        return None
    return parsed.date().isoformat()


def _normalize_iso_datetime_value(value: Any) -> str | None:
    parsed = _parse_datetime_value(value)
    if parsed is None:
        return None
    return parsed.astimezone(timezone.utc).isoformat()


def _parse_datetime_value(value: Any) -> datetime | None:
    if value in (None, ""):
        return None
    if isinstance(value, datetime):
        return value if value.tzinfo is not None else value.replace(tzinfo=timezone.utc)
    if isinstance(value, date):
        return datetime.combine(value, datetime.min.time(), tzinfo=timezone.utc)
    raw = str(value).strip()
    if not raw:
        return None
    if len(raw) == 10:
        try:
            return datetime.combine(date.fromisoformat(raw), datetime.min.time(), tzinfo=timezone.utc)
        except Exception:
            pass
    normalized = raw[:-1] + "+00:00" if raw.endswith("Z") else raw
    try:
        parsed = datetime.fromisoformat(normalized)
    except Exception:
        return None
    return parsed if parsed.tzinfo is not None else parsed.replace(tzinfo=timezone.utc)


def _lookup_active_opportunity_candidates(
    *,
    query: str,
    org_alias: str | None,
    limit: int,
) -> tuple[list[SellerDealLookupCandidateV1], bool]:
    exact_rows = _run_active_opportunity_lookup_query(
        where_clause=(
            "(Name = '{query}' OR Account.Name = '{query}')".format(
                query=sfdc_helpers.escape_soql_value(query)
            )
        ),
        org_alias=org_alias,
        limit=limit,
    )
    if exact_rows:
        return _normalize_opportunity_lookup_rows(exact_rows, limit=limit)

    tokens = _seller_deal_lookup_tokens(query)
    if not tokens:
        tokens = [_sanitize_like_search_token(query)]
    token_clauses = [
        "(Name LIKE '%{token}%' OR Account.Name LIKE '%{token}%')".format(
            token=sfdc_helpers.escape_soql_value(token)
        )
        for token in tokens
        if token
    ]
    if not token_clauses:
        return [], False
    return _normalize_opportunity_lookup_rows(
        _run_active_opportunity_lookup_query(
            where_clause=" AND ".join(token_clauses),
            org_alias=org_alias,
            limit=limit,
        ),
        limit=limit,
    )


def _run_active_opportunity_lookup_query(
    *,
    where_clause: str,
    org_alias: str | None,
    limit: int,
) -> list[dict[str, Any]]:
    safe_limit = max(1, min(int(limit or 5), 10))
    query = (
        "SELECT Id, Name, Account.Name, StageName, CloseDate, Amount, Owner.Name, LastModifiedDate "
        "FROM Opportunity "
        f"WHERE IsClosed = false AND {where_clause} "
        "ORDER BY CloseDate ASC NULLS LAST, LastModifiedDate DESC "
        f"LIMIT {safe_limit + 1}"
    )
    rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
    return [row for row in rows if isinstance(row, dict)]


def _normalize_opportunity_lookup_rows(
    rows: list[dict[str, Any]],
    *,
    limit: int,
) -> tuple[list[SellerDealLookupCandidateV1], bool]:
    truncated = len(rows) > limit
    candidates: list[SellerDealLookupCandidateV1] = []
    seen: set[str] = set()
    for row in rows[:limit]:
        opportunity_id = str(row.get("Id") or "").strip()
        if not opportunity_id or opportunity_id in seen:
            continue
        seen.add(opportunity_id)
        amount = row.get("Amount")
        amount_value: float | None
        if amount in (None, ""):
            amount_value = None
        else:
            try:
                amount_value = float(amount)
            except Exception:
                amount_value = None
        candidates.append(
            SellerDealLookupCandidateV1(
                opportunity_id=opportunity_id,
                name=str(row.get("Name") or "").strip() or opportunity_id,
                account_name=str(row.get("Account.Name") or "").strip() or None,
                stage_name=str(row.get("StageName") or "").strip() or None,
                close_date=str(row.get("CloseDate") or "").strip() or None,
                owner_name=str(row.get("Owner.Name") or "").strip() or None,
                amount=amount_value,
            )
        )
    return candidates, truncated


def _load_current_opportunity_field_value(
    *,
    opportunity_id: str,
    field_name: str,
    org_alias: str | None,
) -> Any:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    query = (
        f"SELECT Id, {field_name} "
        f"FROM Opportunity WHERE Id = '{escaped_opportunity_id}' LIMIT 1"
    )
    rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
    if not rows:
        raise RuntimeError(f"Opportunity {opportunity_id} was not found in Salesforce.")
    if not isinstance(rows[0], dict):
        raise RuntimeError("Salesforce SOQL response did not return a row dictionary.")
    return rows[0].get(field_name)


def _load_opportunity_primary_contact_state(
    *,
    opportunity_id: str,
    primary_contact_field_name: str,
    org_alias: str | None,
) -> dict[str, Any]:
    escaped_opportunity_id = _soql_string_literal(opportunity_id)
    query = (
        f"SELECT Id, AccountId, {primary_contact_field_name} "
        f"FROM Opportunity WHERE Id = '{escaped_opportunity_id}' LIMIT 1"
    )
    rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
    if not rows:
        raise RuntimeError(f"Opportunity {opportunity_id} was not found in Salesforce.")
    if not isinstance(rows[0], dict):
        raise RuntimeError("Salesforce SOQL response did not return an Opportunity row dictionary.")
    return rows[0]


def _resolve_seller_contact_reference(
    *,
    contact_reference: str,
    org_alias: str | None,
) -> dict[str, Any]:
    normalized = str(contact_reference or "").strip()
    if _SELLER_CONTACT_ID_RE.match(normalized):
        query = (
            "SELECT Id, Email, AccountId "
            f"FROM Contact WHERE Id = '{_soql_string_literal(normalized)}' LIMIT 1"
        )
        rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
        if not rows:
            raise RuntimeError(f"Contact {normalized} was not found in Salesforce.")
        if not isinstance(rows[0], dict):
            raise RuntimeError("Salesforce SOQL response did not return a Contact row dictionary.")
        return rows[0]
    if _SELLER_EMAIL_RE.match(normalized):
        query = (
            "SELECT Id, Email, AccountId "
            f"FROM Contact WHERE Email = '{_soql_string_literal(normalized)}' LIMIT 2"
        )
        rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
        if not rows:
            raise RuntimeError(f"No Salesforce Contact was found for {normalized}.")
        if len(rows) > 1:
            raise RuntimeError(
                f"Multiple Salesforce Contacts matched {normalized}; use an explicit Salesforce Contact id instead."
            )
        if not isinstance(rows[0], dict):
            raise RuntimeError("Salesforce SOQL response did not return a Contact row dictionary.")
        return rows[0]
    raise RuntimeError("Contact adds require an existing Salesforce Contact id or exact contact email.")


def _load_existing_opportunity_contact_roles(
    *,
    opportunity_id: str,
    contact_id: str,
    org_alias: str | None,
) -> list[dict[str, Any]]:
    query = (
        "SELECT Id, ContactId, OpportunityId, Role, IsPrimary "
        "FROM OpportunityContactRole "
        f"WHERE OpportunityId = '{_soql_string_literal(opportunity_id)}' "
        f"AND ContactId = '{_soql_string_literal(contact_id)}'"
    )
    rows = sfdc_helpers.run_soql(query, org_alias=org_alias)
    return [row for row in rows if isinstance(row, dict)]


def _load_opportunity_field_meta(field_name: str, *, org_alias: str | None) -> dict[str, Any]:
    if field_name in _SELLER_FIX_BLOCKED_FIELD_NAMES:
        raise RuntimeError(f"{field_name} is outside the low-risk seller field-fix scope.")
    lowered = field_name.lower()
    if any(token in lowered for token in _SELLER_FIX_BLOCKED_NAME_TOKENS):
        raise RuntimeError(f"{field_name} is outside the low-risk seller field-fix scope.")

    payload = sfdc_helpers.describe_sobject("Opportunity", org_alias=org_alias)
    result = payload.get("result") if isinstance(payload.get("result"), dict) else payload
    fields = result.get("fields") if isinstance(result, dict) else None
    if not isinstance(fields, list):
        raise RuntimeError("Salesforce describe metadata for Opportunity did not include fields.")
    for row in fields:
        if not isinstance(row, dict):
            continue
        if str(row.get("name") or "").strip() != field_name:
            continue
        if row.get("updateable") is False:
            raise RuntimeError(f"{field_name} is not updateable on Opportunity.")
        field_type = str(row.get("type") or "").strip().lower()
        if field_type not in _SELLER_FIX_SUPPORTED_FIELD_TYPES:
            raise RuntimeError(f"{field_name} has unsupported field type {field_type or 'unknown'} for seller fixes.")
        return row
    raise RuntimeError(f"{field_name} was not found on Opportunity describe metadata.")


def _load_primary_contact_field_meta(field_name: str, *, org_alias: str | None) -> dict[str, Any]:
    payload = sfdc_helpers.describe_sobject("Opportunity", org_alias=org_alias)
    result = payload.get("result") if isinstance(payload.get("result"), dict) else payload
    fields = result.get("fields") if isinstance(result, dict) else None
    if not isinstance(fields, list):
        raise RuntimeError("Salesforce describe metadata for Opportunity did not include fields.")
    for row in fields:
        if not isinstance(row, dict):
            continue
        if str(row.get("name") or "").strip() != field_name:
            continue
        if row.get("updateable") is False:
            raise RuntimeError(f"{field_name} is not updateable on Opportunity.")
        field_type = str(row.get("type") or "").strip().lower()
        if field_type != "reference":
            raise RuntimeError(
                f"{field_name} is not a Contact lookup field on Opportunity and is outside this seller contact path."
            )
        reference_to = {str(value or "").strip() for value in row.get("referenceTo") or []}
        if "Contact" not in reference_to:
            raise RuntimeError(
                f"{field_name} does not reference Contact on Opportunity and is outside this seller contact path."
            )
        return row
    raise RuntimeError(
        f"{field_name} was not found on Opportunity describe metadata; route this primary-contact blocker to RevOps."
    )


def _coerce_opportunity_contact_role(*, role_name: str, org_alias: str | None) -> str:
    payload = sfdc_helpers.describe_sobject("OpportunityContactRole", org_alias=org_alias)
    result = payload.get("result") if isinstance(payload.get("result"), dict) else payload
    fields = result.get("fields") if isinstance(result, dict) else None
    if not isinstance(fields, list):
        raise RuntimeError("Salesforce describe metadata for OpportunityContactRole did not include fields.")
    role_field = next(
        (
            row
            for row in fields
            if isinstance(row, dict) and str(row.get("name") or "").strip() == "Role"
        ),
        None,
    )
    if not isinstance(role_field, dict):
        raise RuntimeError("OpportunityContactRole.Role metadata was not available.")
    normalized_role_name = _strip_balanced_quotes(role_name)
    active_values = {
        str(item.get("value") or "").strip()
        for item in role_field.get("picklistValues") or []
        if isinstance(item, dict) and item.get("active", True)
    }
    if active_values and normalized_role_name not in active_values:
        raise RuntimeError(f"{normalized_role_name} is not an active OpportunityContactRole role value.")
    return normalized_role_name


def _validate_contact_account_alignment(
    *,
    opportunity_state: dict[str, Any],
    contact: dict[str, Any],
    opportunity_id: str,
) -> None:
    opportunity_account_id = str(opportunity_state.get("AccountId") or "").strip()
    contact_account_id = str(contact.get("AccountId") or "").strip()
    if opportunity_account_id and contact_account_id and opportunity_account_id != contact_account_id:
        raise RuntimeError(
            f"Contact {contact.get('Id')} belongs to Account {contact_account_id}, not Opportunity {opportunity_id}'s "
            f"Account {opportunity_account_id}."
        )


def _has_matching_contact_role(existing_roles: list[dict[str, Any]], role_name: str) -> bool:
    normalized_role_name = str(role_name or "").strip().lower()
    for row in existing_roles:
        if str(row.get("Role") or "").strip().lower() == normalized_role_name:
            return True
    return False


def _find_conflicting_contact_role(existing_roles: list[dict[str, Any]], role_name: str) -> str | None:
    normalized_role_name = str(role_name or "").strip().lower()
    for row in existing_roles:
        existing_role = str(row.get("Role") or "").strip()
        if not existing_role:
            continue
        if existing_role.lower() != normalized_role_name:
            return existing_role
    return None


def _coerce_seller_field_value(field_meta: dict[str, Any], raw_value: str) -> Any:
    field_type = str(field_meta.get("type") or "").strip().lower()
    value = _strip_balanced_quotes(raw_value)
    if field_type in {"string", "textarea", "phone", "url", "email"}:
        length_limit = field_meta.get("length")
        if isinstance(length_limit, int) and length_limit > 0 and len(value) > length_limit:
            raise RuntimeError(f"Value exceeds the {length_limit}-character limit for {field_meta.get('name')}.")
        return value
    if field_type == "picklist":
        active_values = {
            str(item.get("value") or "").strip()
            for item in field_meta.get("picklistValues") or []
            if isinstance(item, dict) and item.get("active", True)
        }
        if active_values and value not in active_values:
            raise RuntimeError(
                f"{value} is not an active picklist value for {field_meta.get('name')}."
            )
        return value
    if field_type == "boolean":
        return _parse_boolean(value)
    if field_type == "date":
        try:
            return date.fromisoformat(value).isoformat()
        except Exception as exc:
            raise RuntimeError(f"{field_meta.get('name')} expects YYYY-MM-DD.") from exc
    if field_type == "datetime":
        normalized = value[:-1] + "+00:00" if value.endswith("Z") else value
        try:
            return datetime.fromisoformat(normalized).isoformat()
        except Exception as exc:
            raise RuntimeError(f"{field_meta.get('name')} expects an ISO-8601 datetime.") from exc
    raise RuntimeError(f"{field_meta.get('name')} has unsupported field type {field_type}.")


def _seller_field_values_match(field_meta: dict[str, Any], current_value: Any, target_value: Any) -> bool:
    if current_value in (None, "") and target_value in (None, ""):
        return True
    current_normalized = _normalize_seller_field_value_for_compare(field_meta, current_value)
    target_normalized = _normalize_seller_field_value_for_compare(field_meta, target_value)
    return current_normalized == target_normalized


def _normalize_seller_field_value_for_compare(field_meta: dict[str, Any], value: Any) -> Any:
    field_type = str(field_meta.get("type") or "").strip().lower()
    if value in (None, ""):
        return None
    if field_type in {"string", "textarea", "phone", "url", "email", "picklist"}:
        return str(value)
    if field_type == "boolean":
        if isinstance(value, bool):
            return value
        return _parse_boolean(str(value))
    if field_type == "date":
        if isinstance(value, date) and not isinstance(value, datetime):
            return value.isoformat()
        return date.fromisoformat(str(value)).isoformat()
    if field_type == "datetime":
        if isinstance(value, datetime):
            return value.astimezone(timezone.utc).isoformat()
        normalized = str(value)
        if normalized.endswith("Z"):
            normalized = normalized[:-1] + "+00:00"
        return datetime.fromisoformat(normalized).astimezone(timezone.utc).isoformat()
    return value


def _parse_boolean(value: str) -> bool:
    lowered = str(value or "").strip().lower()
    if lowered in {"true", "1", "yes", "y"}:
        return True
    if lowered in {"false", "0", "no", "n"}:
        return False
    raise RuntimeError("Boolean seller field fixes expect true/false.")


def _strip_balanced_quotes(value: str) -> str:
    text = str(value or "").strip()
    if len(text) >= 2 and text[0] == text[-1] and text[0] in {'"', "'"}:
        return text[1:-1].strip()
    return text


def _soql_string_literal(value: str) -> str:
    return str(value or "").replace("\\", "\\\\").replace("'", "\\'")


def _normalize_seller_deal_lookup_query(value: str) -> str:
    text = _strip_balanced_quotes(str(value or "").strip())
    text = re.sub(r"\s+", " ", text)
    return text.strip(" ?")


def _seller_deal_lookup_tokens(value: str) -> list[str]:
    normalized = _normalize_seller_deal_lookup_query(value)
    tokens: list[str] = []
    seen: set[str] = set()
    for raw_token in re.findall(r"[A-Za-z0-9][A-Za-z0-9'.-]*", normalized):
        cleaned = _sanitize_like_search_token(raw_token).lower()
        if not cleaned or cleaned in _DEAL_LOOKUP_STOPWORDS or cleaned in seen:
            continue
        seen.add(cleaned)
        tokens.append(cleaned)
    return tokens[:4]


def _sanitize_like_search_token(value: str) -> str:
    return re.sub(r"[%_]+", "", str(value or "").strip())


__all__ = [
    "SellerActionHintV1",
    "SellerDealHealthSummaryV1",
    "SellerDealLookupCandidateV1",
    "SellerDealLookupResultV1",
    "CloseReviewSubmissionV1",
    "SellerFieldFixResultV1",
    "SellerContactRoleResultV1",
    "SellerQuoteRecordV1",
    "SellerQuoteApproverV1",
    "SellerQuoteEvidenceV1",
    "SellerQuoteStatusResultV1",
    "SellerQuoteLineItemV1",
    "SellerQuoteLineItemPreviewV1",
    "QuoteIntentV1",
    "SellerQuoteChangeFieldPreviewV1",
    "SellerQuoteRevisionPreviewV1",
    "SellerQuoteRevisionApplyResultV1",
    "SellerQuoteRevisionApprovalContextV1",
    "apply_seller_missing_field_fix",
    "apply_seller_contact_role_add",
    "apply_seller_quote_revision",
    "build_quote_intent_v1",
    "get_seller_deal_health_summary",
    "get_seller_quote_status_summary",
    "load_seller_quote_revision_approval_context",
    "lookup_seller_active_deals",
    "preview_seller_quote_revision",
    "save_seller_quote_revision_approval_context",
    "submit_deal_for_close_review",
]
