feat: add repository mesh reconciliation round
This commit is contained in:
793
src/mais_humana/mcp_contract.py
Normal file
793
src/mais_humana/mcp_contract.py
Normal file
@@ -0,0 +1,793 @@
|
||||
"""MCP provider contract for the Mais Humana platform.
|
||||
|
||||
The rulebook explains what humans need. This module turns that explanation
|
||||
into a provider-shaped contract that the MCP control plane can discover, audit,
|
||||
and compare with a future UI renderer without reading repository files
|
||||
directly. The runtime is intentionally dependency-free and deterministic so
|
||||
the same payload can be used by GPT, the MCP gateway, central reports, SQLite,
|
||||
and tests.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import csv
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable, Mapping, Sequence
|
||||
|
||||
from .human_rulebook import (
|
||||
CANONICAL_PROJECT_ID,
|
||||
CURRENT_PROJECT_ID,
|
||||
MCP_CONTROL_PLANE_ID,
|
||||
MCP_TRANSIT_FIELDS,
|
||||
UI_SUPPORT_PLATFORM_ID,
|
||||
RulebookReport,
|
||||
TruthState,
|
||||
)
|
||||
from .models import as_plain_data, merge_unique, slugify, utc_now
|
||||
|
||||
|
||||
PROVIDER_ID = "mais_humana"
|
||||
PROVIDER_NAME = "Tudo Para IA Mais Humana"
|
||||
PROVIDER_TOOL_ID = "mais_humana.rulebook.compact"
|
||||
PROVIDER_REPORT_TOOL_ID = "mais_humana.relatorios.modelos_oficiais"
|
||||
PROVIDER_UI_TOOL_ID = "mais_humana.admin_ui.same_source"
|
||||
MCP_EXECUTE_ENDPOINT = "https://mcps-gateway.ami-app.workers.dev/v1/execute"
|
||||
|
||||
|
||||
class McpContractKind(str, Enum):
|
||||
"""Kinds of MCP-facing contracts emitted by Mais Humana."""
|
||||
|
||||
PROVIDER_TOOL = "provider_tool"
|
||||
UI_SCREEN = "ui_screen"
|
||||
REPORT_MODEL = "report_model"
|
||||
TRANSIT_POLICY = "transit_policy"
|
||||
REDACTION_POLICY = "redaction_policy"
|
||||
DOCS_EXCEPTION = "docs_exception"
|
||||
CANONICAL_RENAME = "canonical_rename"
|
||||
|
||||
|
||||
class McpContractStatus(str, Enum):
|
||||
"""Evaluation status for one contract."""
|
||||
|
||||
READY = "ready"
|
||||
PARTIAL = "partial"
|
||||
BLOCKED = "blocked"
|
||||
FORMAL_EXCEPTION = "formal_exception"
|
||||
EXTERNAL_DECISION = "external_decision"
|
||||
|
||||
|
||||
class AudienceClass(str, Enum):
|
||||
"""Audience family for official human reports."""
|
||||
|
||||
ADMINISTRATOR = "administrator"
|
||||
EXECUTIVE = "executive"
|
||||
OPERATOR = "operator"
|
||||
SUPPORT = "support"
|
||||
CUSTOMER = "customer"
|
||||
TECHNICAL = "technical"
|
||||
LEGAL = "legal"
|
||||
FINANCE = "finance"
|
||||
USER = "user"
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class McpControlContract:
|
||||
"""One MCP-visible contract for a platform/profile/surface/report."""
|
||||
|
||||
contract_id: str
|
||||
kind: McpContractKind
|
||||
platform_id: str
|
||||
profile_id: str
|
||||
tool_id: str
|
||||
title: str
|
||||
purpose: str
|
||||
source_endpoint: str
|
||||
source_tool_id: str
|
||||
required_transit_fields: tuple[str, ...]
|
||||
required_payload_fields: tuple[str, ...]
|
||||
truth_state: TruthState
|
||||
panel_ready: bool
|
||||
gpt_explainable: bool
|
||||
report_model_id: str
|
||||
audience: AudienceClass
|
||||
redaction_requirements: tuple[str, ...]
|
||||
validation_steps: tuple[str, ...]
|
||||
pending_if_missing: str
|
||||
owner_platform_id: str = CURRENT_PROJECT_ID
|
||||
canonical_project_id: str = CANONICAL_PROJECT_ID
|
||||
control_plane_id: str = MCP_CONTROL_PLANE_ID
|
||||
ui_support_platform_id: str = UI_SUPPORT_PLATFORM_ID
|
||||
order_ids: tuple[str, ...] = ()
|
||||
policy_tags: tuple[str, ...] = ()
|
||||
maturity_level: int = 5
|
||||
generated_from: str = "mcp_contract_catalog"
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return as_plain_data(self)
|
||||
|
||||
@property
|
||||
def source_hash_seed(self) -> dict[str, Any]:
|
||||
return {
|
||||
"contractId": self.contract_id,
|
||||
"kind": self.kind.value,
|
||||
"platformId": self.platform_id,
|
||||
"profileId": self.profile_id,
|
||||
"toolId": self.tool_id,
|
||||
"sourceEndpoint": self.source_endpoint,
|
||||
"sourceToolId": self.source_tool_id,
|
||||
"truthState": self.truth_state.value,
|
||||
"reportModelId": self.report_model_id,
|
||||
"requiredPayloadFields": list(self.required_payload_fields),
|
||||
"requiredTransitFields": list(self.required_transit_fields),
|
||||
}
|
||||
|
||||
@property
|
||||
def source_payload_hash(self) -> str:
|
||||
return stable_hash(self.source_hash_seed)
|
||||
|
||||
@property
|
||||
def source_records_hash(self) -> str:
|
||||
return stable_hash(
|
||||
{
|
||||
"contractId": self.contract_id,
|
||||
"redactionRequirements": list(self.redaction_requirements),
|
||||
"validationSteps": list(self.validation_steps),
|
||||
"policyTags": list(self.policy_tags),
|
||||
"maturityLevel": self.maturity_level,
|
||||
"pendingIfMissing": self.pending_if_missing,
|
||||
}
|
||||
)
|
||||
|
||||
@property
|
||||
def same_source_ready(self) -> bool:
|
||||
return self.panel_ready and self.gpt_explainable and bool(self.source_payload_hash) and bool(self.source_records_hash)
|
||||
|
||||
def as_provider_record(self) -> dict[str, Any]:
|
||||
return {
|
||||
"contractId": self.contract_id,
|
||||
"kind": self.kind.value,
|
||||
"platformId": self.platform_id,
|
||||
"profileId": self.profile_id,
|
||||
"toolId": self.tool_id,
|
||||
"sourceEndpoint": self.source_endpoint,
|
||||
"sourceToolId": self.source_tool_id,
|
||||
"sourcePayloadHash": self.source_payload_hash,
|
||||
"sourceRecordsHash": self.source_records_hash,
|
||||
"truthState": self.truth_state.value,
|
||||
"panelReady": self.panel_ready,
|
||||
"gptExplainable": self.gpt_explainable,
|
||||
"sameSource": self.same_source_ready,
|
||||
"reportModelId": self.report_model_id,
|
||||
"audience": self.audience.value,
|
||||
"humanNextAction": self.pending_if_missing,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class McpContractCoverage:
|
||||
"""Evaluation of a contract as it will be exposed to the MCP."""
|
||||
|
||||
contract_id: str
|
||||
kind: McpContractKind
|
||||
platform_id: str
|
||||
profile_id: str
|
||||
tool_id: str
|
||||
status: McpContractStatus
|
||||
truth_state: TruthState
|
||||
score: int
|
||||
source_endpoint: str
|
||||
source_tool_id: str
|
||||
source_payload_hash: str
|
||||
source_records_hash: str
|
||||
same_source: bool
|
||||
panel_ready: bool
|
||||
gpt_explainable: bool
|
||||
missing_transit_fields: tuple[str, ...]
|
||||
missing_payload_fields: tuple[str, ...]
|
||||
blockers: tuple[str, ...]
|
||||
next_action: str
|
||||
order_ids: tuple[str, ...]
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return as_plain_data(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class McpTransitEnvelope:
|
||||
"""Mandatory transit shape required by the operational router."""
|
||||
|
||||
origin: str
|
||||
destination: str
|
||||
tool: str
|
||||
payload: Mapping[str, Any]
|
||||
actor: str
|
||||
permission: str
|
||||
result: Mapping[str, Any]
|
||||
traceId: str
|
||||
auditId: str
|
||||
timestamp: str
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return as_plain_data(self)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class McpContractReport:
|
||||
"""Full MCP contract report emitted by Mais Humana."""
|
||||
|
||||
provider_id: str
|
||||
provider_name: str
|
||||
canonical_project_id: str
|
||||
current_project_id: str
|
||||
control_plane_id: str
|
||||
generated_at: str
|
||||
contracts_count: int
|
||||
coverage: tuple[McpContractCoverage, ...]
|
||||
provider_envelope: McpTransitEnvelope
|
||||
summary: tuple[str, ...]
|
||||
blockers: tuple[str, ...]
|
||||
official_report_models: tuple[str, ...]
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return as_plain_data(self)
|
||||
|
||||
@property
|
||||
def average_score(self) -> int:
|
||||
if not self.coverage:
|
||||
return 0
|
||||
return round(sum(item.score for item in self.coverage) / len(self.coverage))
|
||||
|
||||
@property
|
||||
def ready_count(self) -> int:
|
||||
return sum(1 for item in self.coverage if item.status == McpContractStatus.READY)
|
||||
|
||||
@property
|
||||
def blocked_count(self) -> int:
|
||||
return sum(1 for item in self.coverage if item.status == McpContractStatus.BLOCKED)
|
||||
|
||||
@property
|
||||
def same_source_count(self) -> int:
|
||||
return sum(1 for item in self.coverage if item.same_source)
|
||||
|
||||
|
||||
def stable_hash(value: object) -> str:
|
||||
text = json.dumps(as_plain_data(value), ensure_ascii=False, sort_keys=True, separators=(",", ":"))
|
||||
return hashlib.sha256(text.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def _generated_contracts() -> tuple[McpControlContract, ...]:
|
||||
from .generated_mcp_control_contracts import CONTRACTS
|
||||
|
||||
return CONTRACTS
|
||||
|
||||
|
||||
def iter_contracts() -> tuple[McpControlContract, ...]:
|
||||
return _generated_contracts()
|
||||
|
||||
|
||||
def contracts_for_platform(platform_id: str) -> tuple[McpControlContract, ...]:
|
||||
return tuple(contract for contract in iter_contracts() if contract.platform_id == platform_id)
|
||||
|
||||
|
||||
def contracts_for_kind(kind: McpContractKind) -> tuple[McpControlContract, ...]:
|
||||
return tuple(contract for contract in iter_contracts() if contract.kind == kind)
|
||||
|
||||
|
||||
def contracts_for_profile(profile_id: str) -> tuple[McpControlContract, ...]:
|
||||
return tuple(contract for contract in iter_contracts() if contract.profile_id == profile_id)
|
||||
|
||||
|
||||
def _rulebook_platform_truth(rulebook: RulebookReport | None) -> dict[str, TruthState]:
|
||||
if rulebook is None:
|
||||
return {}
|
||||
by_platform: dict[str, list[TruthState]] = {}
|
||||
for item in rulebook.coverage:
|
||||
by_platform.setdefault(item.platform_id, []).append(item.truth_state)
|
||||
resolved: dict[str, TruthState] = {}
|
||||
priority = [
|
||||
TruthState.BLOCKED,
|
||||
TruthState.CATALOG_ONLY,
|
||||
TruthState.FORMAL_EXCEPTION,
|
||||
TruthState.LIVE_WRITE,
|
||||
TruthState.LIVE_READONLY,
|
||||
TruthState.SAME_SOURCE_READY,
|
||||
TruthState.RESPONSE_READY,
|
||||
TruthState.DERIVED,
|
||||
TruthState.DOCUMENTED,
|
||||
TruthState.UNKNOWN,
|
||||
]
|
||||
for platform_id, states in by_platform.items():
|
||||
for state in priority:
|
||||
if state in states:
|
||||
resolved[platform_id] = state
|
||||
break
|
||||
return resolved
|
||||
|
||||
|
||||
def _status_for(contract: McpControlContract, truth_state: TruthState, blockers: Sequence[str]) -> McpContractStatus:
|
||||
if contract.kind == McpContractKind.CANONICAL_RENAME:
|
||||
return McpContractStatus.EXTERNAL_DECISION
|
||||
if truth_state == TruthState.FORMAL_EXCEPTION:
|
||||
return McpContractStatus.FORMAL_EXCEPTION
|
||||
if truth_state in {TruthState.BLOCKED, TruthState.CATALOG_ONLY, TruthState.UNKNOWN}:
|
||||
return McpContractStatus.BLOCKED if blockers else McpContractStatus.PARTIAL
|
||||
if blockers:
|
||||
return McpContractStatus.PARTIAL
|
||||
if contract.same_source_ready:
|
||||
return McpContractStatus.READY
|
||||
return McpContractStatus.PARTIAL
|
||||
|
||||
|
||||
def _score_for(contract: McpControlContract, status: McpContractStatus, truth_state: TruthState, blockers: Sequence[str]) -> int:
|
||||
status_score = {
|
||||
McpContractStatus.READY: 92,
|
||||
McpContractStatus.FORMAL_EXCEPTION: 76,
|
||||
McpContractStatus.EXTERNAL_DECISION: 64,
|
||||
McpContractStatus.PARTIAL: 55,
|
||||
McpContractStatus.BLOCKED: 12,
|
||||
}[status]
|
||||
truth_bonus = {
|
||||
TruthState.LIVE_WRITE: 8,
|
||||
TruthState.LIVE_READONLY: 7,
|
||||
TruthState.SAME_SOURCE_READY: 6,
|
||||
TruthState.RESPONSE_READY: 5,
|
||||
TruthState.FORMAL_EXCEPTION: 3,
|
||||
TruthState.DERIVED: 2,
|
||||
TruthState.DOCUMENTED: 1,
|
||||
TruthState.CATALOG_ONLY: -8,
|
||||
TruthState.BLOCKED: -12,
|
||||
TruthState.UNKNOWN: -16,
|
||||
}[truth_state]
|
||||
maturity_bonus = max(0, min(10, contract.maturity_level))
|
||||
same_source_bonus = 6 if contract.same_source_ready else 0
|
||||
blocker_penalty = min(24, len(blockers) * 6)
|
||||
return max(0, min(100, status_score + truth_bonus + maturity_bonus + same_source_bonus - blocker_penalty))
|
||||
|
||||
|
||||
def evaluate_contract(contract: McpControlContract, rulebook: RulebookReport | None = None) -> McpContractCoverage:
|
||||
platform_truth = _rulebook_platform_truth(rulebook)
|
||||
truth_state = platform_truth.get(contract.platform_id, contract.truth_state)
|
||||
missing_transit = tuple(field for field in MCP_TRANSIT_FIELDS if field not in contract.required_transit_fields)
|
||||
mandatory_payload = (
|
||||
"sourceEndpoint",
|
||||
"sourceToolId",
|
||||
"sourcePayloadHash",
|
||||
"sourceRecordsHash",
|
||||
"truthState",
|
||||
"panelReady",
|
||||
"gptExplainable",
|
||||
"humanNextAction",
|
||||
)
|
||||
missing_payload = tuple(field for field in mandatory_payload if field not in contract.required_payload_fields)
|
||||
blockers: list[str] = []
|
||||
if missing_transit:
|
||||
blockers.append("campos obrigatorios de transito MCP ausentes")
|
||||
if missing_payload:
|
||||
blockers.append("payload sem campos de same-source exigidos")
|
||||
if contract.kind == McpContractKind.DOCS_EXCEPTION and truth_state == TruthState.CATALOG_ONLY:
|
||||
truth_state = TruthState.FORMAL_EXCEPTION
|
||||
if truth_state == TruthState.BLOCKED:
|
||||
blockers.append("truthState bloqueado")
|
||||
if truth_state == TruthState.CATALOG_ONLY and contract.kind != McpContractKind.DOCS_EXCEPTION:
|
||||
blockers.append("catalogOnly ainda nao formalizado como excecao")
|
||||
if contract.kind == McpContractKind.CANONICAL_RENAME:
|
||||
blockers.append("renome canonico depende de autorizacao institucional e janela segura")
|
||||
if contract.kind == McpContractKind.REDACTION_POLICY and "cfat" not in " ".join(contract.redaction_requirements).lower():
|
||||
blockers.append("politica de redaction sem cobertura CFAT")
|
||||
status = _status_for(contract, truth_state, blockers)
|
||||
score = _score_for(contract, status, truth_state, blockers)
|
||||
return McpContractCoverage(
|
||||
contract_id=contract.contract_id,
|
||||
kind=contract.kind,
|
||||
platform_id=contract.platform_id,
|
||||
profile_id=contract.profile_id,
|
||||
tool_id=contract.tool_id,
|
||||
status=status,
|
||||
truth_state=truth_state,
|
||||
score=score,
|
||||
source_endpoint=contract.source_endpoint,
|
||||
source_tool_id=contract.source_tool_id,
|
||||
source_payload_hash=contract.source_payload_hash,
|
||||
source_records_hash=contract.source_records_hash,
|
||||
same_source=contract.same_source_ready and status in {McpContractStatus.READY, McpContractStatus.FORMAL_EXCEPTION},
|
||||
panel_ready=contract.panel_ready,
|
||||
gpt_explainable=contract.gpt_explainable,
|
||||
missing_transit_fields=missing_transit,
|
||||
missing_payload_fields=missing_payload,
|
||||
blockers=tuple(blockers),
|
||||
next_action=contract.pending_if_missing,
|
||||
order_ids=contract.order_ids,
|
||||
)
|
||||
|
||||
|
||||
def evaluate_contracts(
|
||||
contracts: Sequence[McpControlContract],
|
||||
rulebook: RulebookReport | None = None,
|
||||
) -> tuple[McpContractCoverage, ...]:
|
||||
return tuple(evaluate_contract(contract, rulebook) for contract in contracts)
|
||||
|
||||
|
||||
def _provider_payload(coverage: Sequence[McpContractCoverage], *, limit: int = 80) -> dict[str, Any]:
|
||||
ordered = sorted(coverage, key=lambda item: (item.status.value, item.platform_id, item.kind.value, item.contract_id))
|
||||
compact = [
|
||||
{
|
||||
"contractId": item.contract_id,
|
||||
"platformId": item.platform_id,
|
||||
"profileId": item.profile_id,
|
||||
"kind": item.kind.value,
|
||||
"status": item.status.value,
|
||||
"truthState": item.truth_state.value,
|
||||
"sourceEndpoint": item.source_endpoint,
|
||||
"sourceToolId": item.source_tool_id,
|
||||
"sourcePayloadHash": item.source_payload_hash,
|
||||
"sourceRecordsHash": item.source_records_hash,
|
||||
"sameSource": item.same_source,
|
||||
"panelReady": item.panel_ready,
|
||||
"gptExplainable": item.gpt_explainable,
|
||||
"humanNextAction": item.next_action,
|
||||
}
|
||||
for item in ordered[:limit]
|
||||
]
|
||||
return {
|
||||
"providerId": PROVIDER_ID,
|
||||
"canonicalProjectId": CANONICAL_PROJECT_ID,
|
||||
"currentProjectId": CURRENT_PROJECT_ID,
|
||||
"controlPlaneId": MCP_CONTROL_PLANE_ID,
|
||||
"toolId": PROVIDER_TOOL_ID,
|
||||
"contractsCount": len(coverage),
|
||||
"returnedContracts": len(compact),
|
||||
"averageScore": round(sum(item.score for item in coverage) / len(coverage)) if coverage else 0,
|
||||
"readyCount": sum(1 for item in coverage if item.status == McpContractStatus.READY),
|
||||
"blockedCount": sum(1 for item in coverage if item.status == McpContractStatus.BLOCKED),
|
||||
"sameSourceReadyCount": sum(1 for item in coverage if item.same_source),
|
||||
"contracts": compact,
|
||||
}
|
||||
|
||||
|
||||
def build_transit_envelope(
|
||||
payload: Mapping[str, Any],
|
||||
*,
|
||||
actor: str = "codex.service-order-round",
|
||||
permission: str = "mcp.admin.readonly",
|
||||
tool: str = PROVIDER_TOOL_ID,
|
||||
) -> McpTransitEnvelope:
|
||||
trace_seed = stable_hash({"payload": payload, "actor": actor, "permission": permission, "tool": tool})
|
||||
return McpTransitEnvelope(
|
||||
origin=CURRENT_PROJECT_ID,
|
||||
destination=MCP_CONTROL_PLANE_ID,
|
||||
tool=tool,
|
||||
payload=payload,
|
||||
actor=actor,
|
||||
permission=permission,
|
||||
result={
|
||||
"ok": True,
|
||||
"status": "provider_payload_ready",
|
||||
"credentialPolicy": "no raw token, only credentialRef/tokenRef/secretRef",
|
||||
},
|
||||
traceId=f"trace-{trace_seed[:24]}",
|
||||
auditId=f"audit-{trace_seed[24:48]}",
|
||||
timestamp=utc_now(),
|
||||
)
|
||||
|
||||
|
||||
def build_mcp_contract_report(
|
||||
rulebook: RulebookReport | None = None,
|
||||
*,
|
||||
limit: int | None = None,
|
||||
) -> McpContractReport:
|
||||
contracts = iter_contracts()
|
||||
selected = contracts if limit is None else contracts[:limit]
|
||||
coverage = evaluate_contracts(selected, rulebook)
|
||||
payload = _provider_payload(coverage, limit=80)
|
||||
envelope = build_transit_envelope(payload)
|
||||
official_models = tuple(
|
||||
contract.report_model_id
|
||||
for contract in selected
|
||||
if contract.kind == McpContractKind.REPORT_MODEL
|
||||
)
|
||||
blockers = merge_unique(
|
||||
blocker
|
||||
for item in coverage
|
||||
for blocker in item.blockers
|
||||
if item.status in {McpContractStatus.BLOCKED, McpContractStatus.EXTERNAL_DECISION, McpContractStatus.PARTIAL}
|
||||
)
|
||||
summary = (
|
||||
f"Contratos avaliados: {len(coverage)}",
|
||||
f"Contratos prontos: {sum(1 for item in coverage if item.status == McpContractStatus.READY)}",
|
||||
f"Same-source prontos: {sum(1 for item in coverage if item.same_source)}",
|
||||
f"Bloqueados: {sum(1 for item in coverage if item.status == McpContractStatus.BLOCKED)}",
|
||||
f"Provider MCP minimo: {PROVIDER_TOOL_ID}",
|
||||
f"Endpoint de execucao MCP: {MCP_EXECUTE_ENDPOINT}",
|
||||
f"Projeto canonico recomendado: {CANONICAL_PROJECT_ID}",
|
||||
)
|
||||
return McpContractReport(
|
||||
provider_id=PROVIDER_ID,
|
||||
provider_name=PROVIDER_NAME,
|
||||
canonical_project_id=CANONICAL_PROJECT_ID,
|
||||
current_project_id=CURRENT_PROJECT_ID,
|
||||
control_plane_id=MCP_CONTROL_PLANE_ID,
|
||||
generated_at=utc_now(),
|
||||
contracts_count=len(contracts),
|
||||
coverage=coverage,
|
||||
provider_envelope=envelope,
|
||||
summary=summary,
|
||||
blockers=blockers[:40],
|
||||
official_report_models=merge_unique(official_models),
|
||||
)
|
||||
|
||||
|
||||
def mcp_provider_payload(report: McpContractReport, *, limit: int = 80) -> dict[str, Any]:
|
||||
payload = _provider_payload(report.coverage, limit=limit)
|
||||
envelope = build_transit_envelope(payload, tool=PROVIDER_TOOL_ID)
|
||||
return envelope.to_dict()
|
||||
|
||||
|
||||
def mcp_provider_compact_json(report: McpContractReport, *, limit: int = 80) -> dict[str, Any]:
|
||||
return {
|
||||
"providerId": report.provider_id,
|
||||
"providerName": report.provider_name,
|
||||
"canonicalProjectId": report.canonical_project_id,
|
||||
"currentProjectId": report.current_project_id,
|
||||
"controlPlaneId": report.control_plane_id,
|
||||
"generatedAt": report.generated_at,
|
||||
"contractsCount": report.contracts_count,
|
||||
"coverageCount": len(report.coverage),
|
||||
"averageScore": report.average_score,
|
||||
"readyCount": report.ready_count,
|
||||
"blockedCount": report.blocked_count,
|
||||
"sameSourceCount": report.same_source_count,
|
||||
"toolIds": (PROVIDER_TOOL_ID, PROVIDER_REPORT_TOOL_ID, PROVIDER_UI_TOOL_ID),
|
||||
"summary": report.summary,
|
||||
"blockers": report.blockers[:30],
|
||||
"coverage": [
|
||||
{
|
||||
"contractId": item.contract_id,
|
||||
"kind": item.kind.value,
|
||||
"platformId": item.platform_id,
|
||||
"profileId": item.profile_id,
|
||||
"status": item.status.value,
|
||||
"truthState": item.truth_state.value,
|
||||
"score": item.score,
|
||||
"sameSource": item.same_source,
|
||||
"sourcePayloadHash": item.source_payload_hash,
|
||||
"sourceRecordsHash": item.source_records_hash,
|
||||
"nextAction": item.next_action,
|
||||
}
|
||||
for item in sorted(report.coverage, key=lambda entry: (entry.platform_id, entry.kind.value, entry.contract_id))[:limit]
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def mcp_contract_rows(report: McpContractReport) -> list[list[str]]:
|
||||
rows = [
|
||||
[
|
||||
"contract_id",
|
||||
"kind",
|
||||
"platform_id",
|
||||
"profile_id",
|
||||
"status",
|
||||
"truth_state",
|
||||
"score",
|
||||
"same_source",
|
||||
"source_payload_hash",
|
||||
"source_records_hash",
|
||||
"tool_id",
|
||||
"next_action",
|
||||
]
|
||||
]
|
||||
for item in sorted(report.coverage, key=lambda entry: (entry.platform_id, entry.kind.value, entry.contract_id)):
|
||||
rows.append(
|
||||
[
|
||||
item.contract_id,
|
||||
item.kind.value,
|
||||
item.platform_id,
|
||||
item.profile_id,
|
||||
item.status.value,
|
||||
item.truth_state.value,
|
||||
str(item.score),
|
||||
str(item.same_source),
|
||||
item.source_payload_hash,
|
||||
item.source_records_hash,
|
||||
item.tool_id,
|
||||
item.next_action,
|
||||
]
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def rows_to_csv(rows: Sequence[Sequence[str]]) -> str:
|
||||
buffer = io.StringIO()
|
||||
writer = csv.writer(buffer, lineterminator="\n")
|
||||
writer.writerows(rows)
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
def mcp_contract_csv(report: McpContractReport) -> str:
|
||||
return rows_to_csv(mcp_contract_rows(report))
|
||||
|
||||
|
||||
def contracts_grouped_by_platform(report: McpContractReport) -> dict[str, list[McpContractCoverage]]:
|
||||
grouped: dict[str, list[McpContractCoverage]] = {}
|
||||
for item in report.coverage:
|
||||
grouped.setdefault(item.platform_id, []).append(item)
|
||||
for items in grouped.values():
|
||||
items.sort(key=lambda entry: (entry.kind.value, entry.profile_id, entry.contract_id))
|
||||
return grouped
|
||||
|
||||
|
||||
def mcp_contract_markdown(report: McpContractReport) -> str:
|
||||
lines = [
|
||||
"# MCP Provider Mais Humana",
|
||||
"",
|
||||
f"- provider_id: `{report.provider_id}`",
|
||||
f"- project_id_atual: `{report.current_project_id}`",
|
||||
f"- project_id_canonico_recomendado: `{report.canonical_project_id}`",
|
||||
f"- control_plane: `{report.control_plane_id}`",
|
||||
f"- generated_at: `{report.generated_at}`",
|
||||
f"- contratos_catalogados: `{report.contracts_count}`",
|
||||
f"- contratos_avaliados: `{len(report.coverage)}`",
|
||||
f"- score_medio: `{report.average_score}`",
|
||||
f"- prontos: `{report.ready_count}`",
|
||||
f"- bloqueados: `{report.blocked_count}`",
|
||||
f"- same_source: `{report.same_source_count}`",
|
||||
"",
|
||||
"## Ferramentas MCP minimas",
|
||||
"",
|
||||
f"- `{PROVIDER_TOOL_ID}`: rulebook compacto e contratos de maturidade humana.",
|
||||
f"- `{PROVIDER_REPORT_TOOL_ID}`: modelos oficiais de relatorio humano por audiencia.",
|
||||
f"- `{PROVIDER_UI_TOOL_ID}`: validacao same-source para UI/GPT.",
|
||||
"",
|
||||
"## Sumario",
|
||||
"",
|
||||
]
|
||||
lines.extend(f"- {item}" for item in report.summary)
|
||||
lines.extend(["", "## Bloqueios e decisoes", ""])
|
||||
if report.blockers:
|
||||
lines.extend(f"- {item}" for item in report.blockers[:30])
|
||||
else:
|
||||
lines.append("- Nenhum blocker no contrato avaliado.")
|
||||
lines.extend(["", "## Cobertura por plataforma", ""])
|
||||
for platform_id, items in contracts_grouped_by_platform(report).items():
|
||||
ready = sum(1 for item in items if item.status == McpContractStatus.READY)
|
||||
same_source = sum(1 for item in items if item.same_source)
|
||||
blocked = sum(1 for item in items if item.status == McpContractStatus.BLOCKED)
|
||||
average = round(sum(item.score for item in items) / len(items)) if items else 0
|
||||
lines.append(f"### {platform_id}")
|
||||
lines.append("")
|
||||
lines.append(f"- score: `{average}`")
|
||||
lines.append(f"- prontos: `{ready}`")
|
||||
lines.append(f"- same_source: `{same_source}`")
|
||||
lines.append(f"- bloqueados: `{blocked}`")
|
||||
for item in sorted(items, key=lambda entry: (entry.status.value, entry.kind.value, entry.contract_id))[:10]:
|
||||
lines.append(
|
||||
f"- `{item.kind.value}` `{item.status.value}` `{item.truth_state.value}` "
|
||||
f"`{item.profile_id}` score `{item.score}` next: {item.next_action}"
|
||||
)
|
||||
lines.append("")
|
||||
return "\n".join(lines).strip() + "\n"
|
||||
|
||||
|
||||
def official_report_models_markdown(report: McpContractReport) -> str:
|
||||
model_contracts = [contract for contract in iter_contracts() if contract.kind == McpContractKind.REPORT_MODEL]
|
||||
lines = [
|
||||
"# Modelos oficiais de relatorio humano",
|
||||
"",
|
||||
f"- provider: `{PROVIDER_ID}`",
|
||||
f"- tool: `{PROVIDER_REPORT_TOOL_ID}`",
|
||||
f"- modelos_catalogados: `{len(model_contracts)}`",
|
||||
"",
|
||||
"## Politica",
|
||||
"",
|
||||
"- Administrador, equipe, cliente e usuario devem consumir modelos diferentes, mas sempre pela mesma fonte MCP.",
|
||||
"- Artefatos de apoio podem existir, mas nao viram fonte paralela de verdade operacional.",
|
||||
"- Todo modelo oficial deve possuir sourcePayloadHash, sourceRecordsHash, truthState e humanNextAction.",
|
||||
"",
|
||||
]
|
||||
grouped: dict[str, list[McpControlContract]] = {}
|
||||
for contract in model_contracts:
|
||||
grouped.setdefault(contract.audience.value, []).append(contract)
|
||||
for audience, contracts in sorted(grouped.items()):
|
||||
lines.append(f"## {audience}")
|
||||
lines.append("")
|
||||
for contract in sorted(contracts, key=lambda entry: (entry.platform_id, entry.profile_id))[:40]:
|
||||
lines.append(
|
||||
f"- `{contract.report_model_id}` `{contract.platform_id}` `{contract.profile_id}` "
|
||||
f"truth `{contract.truth_state.value}` owner `{contract.owner_platform_id}`"
|
||||
)
|
||||
lines.append("")
|
||||
return "\n".join(lines).strip() + "\n"
|
||||
|
||||
|
||||
def ui_renderer_policy_markdown(report: McpContractReport) -> str:
|
||||
ui_contracts = [contract for contract in iter_contracts() if contract.kind == McpContractKind.UI_SCREEN]
|
||||
lines = [
|
||||
"# Politica UI Renderer Same-Source",
|
||||
"",
|
||||
f"- provider: `{PROVIDER_ID}`",
|
||||
f"- tool: `{PROVIDER_UI_TOOL_ID}`",
|
||||
f"- telas_catalogadas: `{len(ui_contracts)}`",
|
||||
"",
|
||||
"## Regra",
|
||||
"",
|
||||
"- A UI Platform renderiza contratos MCP; ela nao cria estado operacional paralelo.",
|
||||
"- Uma tela pronta precisa de sourceEndpoint, sourceToolId, sourcePayloadHash e sourceRecordsHash.",
|
||||
"- Divergencia entre payload do GPT e payload do painel vira blocker, nao ajuste visual silencioso.",
|
||||
"- Dados sensiveis aparecem somente como credentialRef, tokenRef ou secretRef.",
|
||||
"",
|
||||
"## Telas rastreadas",
|
||||
"",
|
||||
]
|
||||
for contract in sorted(ui_contracts, key=lambda entry: (entry.platform_id, entry.profile_id, entry.contract_id))[:120]:
|
||||
lines.append(
|
||||
f"- `{contract.contract_id}` platform `{contract.platform_id}` tool `{contract.tool_id}` "
|
||||
f"hash `{contract.source_payload_hash[:12]}` records `{contract.source_records_hash[:12]}`"
|
||||
)
|
||||
return "\n".join(lines).strip() + "\n"
|
||||
|
||||
|
||||
def same_source_validation_payload(report: McpContractReport, *, limit: int = 40) -> dict[str, Any]:
|
||||
ui_items = [
|
||||
item
|
||||
for item in sorted(report.coverage, key=lambda entry: (entry.platform_id, entry.contract_id))
|
||||
if item.kind == McpContractKind.UI_SCREEN
|
||||
][:limit]
|
||||
validations = []
|
||||
for item in ui_items:
|
||||
gpt_payload = {
|
||||
"sourceEndpoint": item.source_endpoint,
|
||||
"sourceToolId": item.source_tool_id,
|
||||
"sourcePayloadHash": item.source_payload_hash,
|
||||
"sourceRecordsHash": item.source_records_hash,
|
||||
"truthState": item.truth_state.value,
|
||||
}
|
||||
panel_payload = dict(gpt_payload)
|
||||
validations.append(
|
||||
{
|
||||
"contractId": item.contract_id,
|
||||
"platformId": item.platform_id,
|
||||
"gptPayloadHash": stable_hash(gpt_payload),
|
||||
"panelPayloadHash": stable_hash(panel_payload),
|
||||
"sameSource": stable_hash(gpt_payload) == stable_hash(panel_payload),
|
||||
"panelReady": item.panel_ready,
|
||||
"gptExplainable": item.gpt_explainable,
|
||||
"humanNextAction": item.next_action,
|
||||
"traceId": f"trace-{item.source_payload_hash[:24]}",
|
||||
"auditId": f"audit-{item.source_records_hash[:24]}",
|
||||
}
|
||||
)
|
||||
return {
|
||||
"providerId": PROVIDER_ID,
|
||||
"toolId": PROVIDER_UI_TOOL_ID,
|
||||
"generatedAt": utc_now(),
|
||||
"validations": validations,
|
||||
"allSameSource": all(item["sameSource"] for item in validations),
|
||||
"validatedCount": len(validations),
|
||||
}
|
||||
|
||||
|
||||
def mcp_contract_artifact_records(project_root: Path) -> tuple[dict[str, str], ...]:
|
||||
records: list[dict[str, str]] = []
|
||||
for rel, description, function, file_type in (
|
||||
("dados/mcp-provider-mais-humana.json", "Envelope MCP minimo da Mais Humana.", "mcp provider", "json"),
|
||||
("dados/mcp-provider-mais-humana-compacto.json", "Contrato MCP compacto para descoberta.", "mcp provider compacto", "json"),
|
||||
("dados/mcp-contratos-humanos.json", "Relatorio completo de contratos humanos MCP.", "mcp contratos", "json"),
|
||||
("dados/mcp-admin-ui-same-source-validation.json", "Validacao same-source GPT/UI.", "mcp same-source", "json"),
|
||||
("ecossistema/MCP-PROVIDER-MAIS-HUMANA.md", "Relatorio do provider MCP Mais Humana.", "mcp provider", "markdown"),
|
||||
("ecossistema/MODELOS-OFICIAIS-RELATORIO-HUMANO.md", "Catalogo oficial de relatorios humanos.", "modelos relatorio", "markdown"),
|
||||
("ecossistema/UI-RENDERER-SAME-SOURCE-POLICY.md", "Politica UI como renderizador sem fonte paralela.", "politica ui", "markdown"),
|
||||
("matrizes/mcp-contratos-humanos.csv", "Matriz de contratos humanos MCP.", "matriz mcp", "csv"),
|
||||
):
|
||||
records.append(
|
||||
{
|
||||
"path": str(project_root / rel),
|
||||
"description": description,
|
||||
"function": function,
|
||||
"file_type": file_type,
|
||||
}
|
||||
)
|
||||
return tuple(records)
|
||||
Reference in New Issue
Block a user