from __future__ import annotations import json import unittest from pathlib import Path from mais_humana.catalog import get_platform from mais_humana.cli import main from mais_humana.matrix import build_global_recommendations, build_matrix, build_platform_reports from mais_humana.operational_dossier import ( ACTIVE_ORDER_IDS, build_execution_round_dossier, build_platform_dossier, dossier_compact_rows, dossier_to_markdown, order_justifications_markdown, write_csv_lines, ) from mais_humana.operational_models import GateOutcome, HumanReadinessStage, OrderClosureStatus from mais_humana.orders import build_exit_orders from mais_humana.reports import generate from mais_humana.scanner import scan_platform from mais_humana.storage import table_counts from tests.helpers import make_tmp class OperationalDossierTests(unittest.TestCase): def make_repo(self, root: Path, platform_id: str, readme: str, code: str = "") -> Path: platform = get_platform(platform_id) repo = root / platform.repo_name repo.mkdir(parents=True) (repo / "README.md").write_text(readme, encoding="utf-8") (repo / "src").mkdir() (repo / "src" / "index.ts").write_text( code or "export const readiness = { health: true, panelReady: true, sameSource: true, credentialRef: 'credential:test' };\n", encoding="utf-8", ) (repo / "openapi.json").write_text(json.dumps({"openapi": "3.1.0"}), encoding="utf-8") (repo / "package.json").write_text(json.dumps({"scripts": {"test": "node --test", "smoke": "node smoke.js"}}), encoding="utf-8") (repo / "index.test.ts").write_text("test('ok', () => true)\n", encoding="utf-8") return repo def build_reports(self, root: Path, platform_ids: tuple[str, ...]): scans = tuple(scan_platform(root, get_platform(platform_id)) for platform_id in platform_ids) cells = build_matrix(scans) return build_platform_reports(scans, cells) def test_platform_dossier_detects_panel_same_source_and_known_blocker(self) -> None: tmp = make_tmp() self.make_repo( tmp, "docs", "Docs catalogOnly precisa decisao formal; panelReady sameSource openapi readiness audit trace.", ) reports = self.build_reports(tmp, ("docs",)) recommendations = build_global_recommendations(reports) dossier = build_platform_dossier(reports[0], recommendations) self.assertEqual(dossier.platform_id, "docs") self.assertTrue(dossier.panel_ready) self.assertTrue(dossier.same_source_ready) self.assertGreaterEqual(dossier.blocker_count, 1) self.assertIn(dossier.stage, {HumanReadinessStage.CATALOG_ONLY, HumanReadinessStage.BLOCKED, HumanReadinessStage.PANEL_READY}) docs_gate = [gate for gate in dossier.gates if gate.gate_id.endswith(".docs")][0] self.assertIn(docs_gate.outcome, {GateOutcome.BLOCKED, GateOutcome.PASS}) def test_round_dossier_links_active_orders_to_platforms_and_output_orders(self) -> None: tmp = make_tmp() self.make_repo(tmp, "business", "Business entitlement checkout panelReady sameSource readiness invoice blocker policy.") self.make_repo(tmp, "compliance", "Compliance admin_view readiness panelReady sameSource retention policy audit openapi.") self.make_repo(tmp, "integracoes", "Integracoes BYOK credentialRef readiness Cloudflare wrangler smoke provider.") reports = self.build_reports(tmp, ("business", "compliance", "integracoes")) recommendations = build_global_recommendations(reports) output_orders = build_exit_orders(recommendations) dossier = build_execution_round_dossier(tmp, reports, recommendations, output_orders, active_order_ids=ACTIVE_ORDER_IDS[:5]) self.assertEqual(len(dossier.order_justifications), 5) self.assertTrue(dossier.output_orders) platforms = {item.platform_id for item in dossier.order_justifications} self.assertIn("business", platforms) self.assertIn("compliance", platforms) statuses = {item.closure_status for item in dossier.order_justifications} self.assertTrue(statuses.intersection({OrderClosureStatus.COMPLETED, OrderClosureStatus.PARTIAL, OrderClosureStatus.BLOCKED})) markdown = dossier_to_markdown(dossier) self.assertIn("Dossie operacional humano", markdown) self.assertIn("Ordens executadas", markdown) justifications = order_justifications_markdown(dossier) self.assertIn("Justificativa das ordens", justifications) csv_text = write_csv_lines(dossier_compact_rows(dossier)) self.assertIn("platform,stage,status", csv_text) def test_generate_writes_dossier_artifacts_and_semantic_tables(self) -> None: tmp = make_tmp() root = tmp / "eco" project = tmp / "human" central = tmp / "central" root.mkdir() central.mkdir() self.make_repo(root, "docs", "Docs catalogOnly panelReady sameSource openapi readiness.") self.make_repo(root, "integracoes", "Integracoes BYOK credentialRef readiness wrangler Cloudflare smoke.") bundle = generate(root, project, central) self.assertTrue((project / "dados" / "dossie-operacional-humano.json").exists()) self.assertTrue((project / "ecossistema" / "DOSSIE-OPERACIONAL-HUMANO.md").exists()) self.assertTrue((project / "ecossistema" / "JUSTIFICATIVA-ORDENS-DE-SERVICO.md").exists()) self.assertTrue((project / "matrizes" / "dossie-operacional-humano.csv").exists()) self.assertTrue((central / "reports" / "EXECUTADO__rodada-operacional-mais-humana.md").exists()) counts = table_counts(central / "controle-semantico.sqlite") self.assertGreater(counts["round_dossiers"], 0) self.assertGreater(counts["order_justifications"], 0) generated_paths = {item.path for item in bundle.generated_files} self.assertIn("dados/dossie-operacional-humano.json", generated_paths) def test_cli_dossier_returns_success(self) -> None: tmp = make_tmp() code = main(["dossier", "--ecosystem-root", str(tmp), "--project-root", str(tmp / "human")]) self.assertEqual(code, 0) if __name__ == "__main__": unittest.main()