794 lines
30 KiB
Python
794 lines
30 KiB
Python
"""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)
|