"""Compile governance findings into service-order continuity.""" from __future__ import annotations from dataclasses import dataclass from typing import Iterable, Sequence from .governance_models import EcosystemGovernancePortfolio, GovernanceOrderCandidate from .models import OrderStatus, OrderType, ServiceOrder, incrementing_id, merge_unique, slugify @dataclass(slots=True) class CompiledOrderSet: """Service-order set produced from recommendations and governance checks.""" service_orders: tuple[ServiceOrder, ...] source_candidates: tuple[GovernanceOrderCandidate, ...] executive_count: int managerial_count: int notes: tuple[str, ...] def to_dict(self) -> dict[str, object]: return { "service_orders": [order.to_dict() for order in self.service_orders], "source_candidates": [candidate.to_dict() for candidate in self.source_candidates], "executive_count": self.executive_count, "managerial_count": self.managerial_count, "notes": self.notes, } def priority_rank(value: str) -> int: lowered = value.lower() if lowered in {"critica", "critico", "critical"}: return 4 if lowered in {"alta", "high"}: return 3 if lowered in {"media", "medium"}: return 2 if lowered in {"baixa", "low"}: return 1 return 0 def candidate_sort_key(candidate: GovernanceOrderCandidate) -> tuple[int, str, str]: return (-priority_rank(candidate.priority), candidate.platform_id, candidate.title) def candidate_to_service_order(candidate: GovernanceOrderCandidate, index: int, project_id: str = "tudo-para-ia-mais-humana") -> ServiceOrder: prefix = "EXECUTIVA" if candidate.order_type == OrderType.EXECUTIVE else "GERENCIAL" return ServiceOrder( order_id=incrementing_id(prefix, index, candidate.title), order_type=candidate.order_type, project_id=project_id, title=candidate.title, purpose=candidate.purpose, object_scope=( f"Plataforma relacionada: {candidate.platform_id}. " "Checks de origem: " + ", ".join(candidate.source_check_ids) ), reason=candidate.reason, expected_result=candidate.expected_result, affected_paths=candidate.affected_paths, validations=candidate.validations, ready_criteria=( "check de governanca reavaliado", "evidencia registrada", "validacao executada ou pendencia real declarada", "SQL semantico atualizado", ), status=OrderStatus.PLANNED, priority=candidate.priority, ) def dedupe_service_orders(orders: Iterable[ServiceOrder]) -> tuple[ServiceOrder, ...]: seen: set[tuple[str, str, str]] = set() output: list[ServiceOrder] = [] for order in orders: key = (order.order_type.value, slugify(order.title), order.object_scope[:80]) if key in seen: continue seen.add(key) output.append(order) return tuple(output) def select_candidates(candidates: Sequence[GovernanceOrderCandidate], order_type: OrderType, limit: int) -> tuple[GovernanceOrderCandidate, ...]: typed = [candidate for candidate in candidates if candidate.order_type == order_type] typed.sort(key=candidate_sort_key) return tuple(typed[:limit]) def compile_governance_orders( portfolio: EcosystemGovernancePortfolio, min_executive: int = 5, min_managerial: int = 5, project_id: str = "tudo-para-ia-mais-humana", ) -> CompiledOrderSet: executive_candidates = list(select_candidates(portfolio.order_candidates, OrderType.EXECUTIVE, min_executive)) managerial_candidates = list(select_candidates(portfolio.order_candidates, OrderType.MANAGERIAL, min_managerial)) notes: list[str] = [] if len(executive_candidates) < min_executive: notes.append( f"Somente {len(executive_candidates)} candidatas executivas reais foram encontradas; " "nao foram criadas ordens artificiais." ) if len(managerial_candidates) < min_managerial: notes.append( f"Somente {len(managerial_candidates)} candidatas gerenciais reais foram encontradas; " "nao foram criadas ordens artificiais." ) orders: list[ServiceOrder] = [] for index, candidate in enumerate(executive_candidates, start=1): orders.append(candidate_to_service_order(candidate, index, project_id)) for index, candidate in enumerate(managerial_candidates, start=1): orders.append(candidate_to_service_order(candidate, index, project_id)) service_orders = dedupe_service_orders(orders) return CompiledOrderSet( service_orders=service_orders, source_candidates=tuple(executive_candidates + managerial_candidates), executive_count=sum(1 for order in service_orders if order.order_type == OrderType.EXECUTIVE), managerial_count=sum(1 for order in service_orders if order.order_type == OrderType.MANAGERIAL), notes=tuple(notes), ) def merge_order_sets(primary: Sequence[ServiceOrder], governance: Sequence[ServiceOrder], min_executive: int = 5, min_managerial: int = 5) -> tuple[ServiceOrder, ...]: merged: list[ServiceOrder] = list(primary) executive_count = sum(1 for order in merged if order.order_type == OrderType.EXECUTIVE) managerial_count = sum(1 for order in merged if order.order_type == OrderType.MANAGERIAL) for order in governance: if order.order_type == OrderType.EXECUTIVE and executive_count >= min_executive: continue if order.order_type == OrderType.MANAGERIAL and managerial_count >= min_managerial: continue merged.append(order) if order.order_type == OrderType.EXECUTIVE: executive_count += 1 else: managerial_count += 1 return dedupe_service_orders(merged) def compiled_orders_markdown(compiled: CompiledOrderSet) -> str: lines = [ "# Ordens compiladas por governanca", "", f"- executivas: `{compiled.executive_count}`", f"- gerenciais: `{compiled.managerial_count}`", f"- candidatas de origem: `{len(compiled.source_candidates)}`", "", ] if compiled.notes: lines.append("## Observacoes") lines.append("") lines.extend(f"- {note}" for note in compiled.notes) lines.append("") lines.append("## Ordens") lines.append("") for order in compiled.service_orders: lines.append(f"### {order.order_id}") lines.append("") lines.append(f"- tipo: `{order.order_type.value}`") lines.append(f"- prioridade: `{order.priority}`") lines.append(f"- titulo: {order.title}") lines.append(f"- motivo: {order.reason}") lines.append(f"- resultado: {order.expected_result}") lines.append("- validacoes:") for validation in order.validations: lines.append(f" - {validation}") lines.append("") return "\n".join(lines).strip() + "\n" def order_coverage_rows(compiled: CompiledOrderSet) -> list[list[str]]: rows = [["order_id", "type", "priority", "title", "paths", "validations"]] for order in compiled.service_orders: rows.append( [ order.order_id, order.order_type.value, order.priority, order.title, " | ".join(order.affected_paths), " | ".join(order.validations), ] ) return rows def source_candidate_rows(compiled: CompiledOrderSet) -> list[list[str]]: rows = [["candidate_id", "platform", "type", "priority", "title", "source_checks"]] for candidate in compiled.source_candidates: rows.append( [ candidate.candidate_id, candidate.platform_id, candidate.order_type.value, candidate.priority, candidate.title, " | ".join(candidate.source_check_ids), ] ) return rows def active_queue_from_orders(orders: Sequence[ServiceOrder]) -> tuple[str, ...]: return tuple(order.order_id for order in orders if order.status == OrderStatus.PLANNED) def explain_order_gap(compiled: CompiledOrderSet, order_type: OrderType, minimum: int = 5) -> str: actual = compiled.executive_count if order_type == OrderType.EXECUTIVE else compiled.managerial_count label = "executivas" if order_type == OrderType.EXECUTIVE else "gerenciais" if actual >= minimum: return f"Minimo de ordens {label} cumprido: {actual}/{minimum}." return f"Minimo de ordens {label} parcial: {actual}/{minimum}; faltam checks reais suficientes." def order_set_summary(compiled: CompiledOrderSet) -> tuple[str, ...]: return ( explain_order_gap(compiled, OrderType.EXECUTIVE), explain_order_gap(compiled, OrderType.MANAGERIAL), f"Candidatas usadas: {len(compiled.source_candidates)}.", f"Fila ativa compilada: {len(active_queue_from_orders(compiled.service_orders))}.", ) def combine_order_notes(*sets: CompiledOrderSet) -> tuple[str, ...]: notes: list[str] = [] for item in sets: notes.extend(item.notes) notes.extend(order_set_summary(item)) return merge_unique(notes)