98 lines
3.4 KiB
Python
98 lines
3.4 KiB
Python
"""Generate operational playbooks oriented to human roles."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Sequence
|
|
|
|
from .catalog import HUMAN_PROFILES, PROFILE_BY_ID
|
|
from .models import PlatformHumanReport, Recommendation, as_plain_data
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class PlaybookStep:
|
|
step_id: str
|
|
title: str
|
|
action: str
|
|
evidence_needed: str
|
|
done_when: str
|
|
|
|
def to_dict(self) -> dict[str, object]:
|
|
return as_plain_data(self)
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class HumanPlaybook:
|
|
playbook_id: str
|
|
profile_id: str
|
|
title: str
|
|
purpose: str
|
|
steps: tuple[PlaybookStep, ...]
|
|
|
|
def to_dict(self) -> dict[str, object]:
|
|
return as_plain_data(self)
|
|
|
|
|
|
def step_from_recommendation(profile_id: str, recommendation: Recommendation, index: int) -> PlaybookStep:
|
|
return PlaybookStep(
|
|
step_id=f"{profile_id}-{recommendation.platform_id}-{index}",
|
|
title=recommendation.title,
|
|
action=recommendation.reason,
|
|
evidence_needed=", ".join(recommendation.validation_steps or ("validacao operacional",)),
|
|
done_when=recommendation.expected_impact,
|
|
)
|
|
|
|
|
|
def build_playbook_for_profile(profile_id: str, reports: Sequence[PlatformHumanReport]) -> HumanPlaybook:
|
|
profile = PROFILE_BY_ID[profile_id]
|
|
candidate_recommendations: list[Recommendation] = []
|
|
for report in reports:
|
|
profile_cells = [cell for cell in report.cells if cell.profile_id == profile_id]
|
|
weak = profile_cells and profile_cells[0].score < 70
|
|
if profile_id in report.platform.expected_profiles or weak:
|
|
candidate_recommendations.extend(report.recommendations[:3])
|
|
if not candidate_recommendations:
|
|
for report in reports[:3]:
|
|
candidate_recommendations.extend(report.recommendations[:1])
|
|
candidate_recommendations.sort(key=lambda item: (-item.priority, item.platform_id))
|
|
steps = tuple(
|
|
step_from_recommendation(profile_id, recommendation, index)
|
|
for index, recommendation in enumerate(candidate_recommendations[:8], start=1)
|
|
)
|
|
return HumanPlaybook(
|
|
playbook_id=f"playbook-{profile_id}",
|
|
profile_id=profile_id,
|
|
title=f"Playbook humano - {profile.name}",
|
|
purpose=(
|
|
f"Orientar {profile.name} a interpretar estado, evidencias e proximas acoes "
|
|
"sem depender de leitura direta do codigo."
|
|
),
|
|
steps=steps,
|
|
)
|
|
|
|
|
|
def build_playbooks(reports: Sequence[PlatformHumanReport]) -> tuple[HumanPlaybook, ...]:
|
|
return tuple(build_playbook_for_profile(profile.profile_id, reports) for profile in HUMAN_PROFILES)
|
|
|
|
|
|
def playbooks_markdown(playbooks: Sequence[HumanPlaybook]) -> str:
|
|
lines = ["# Playbooks humanos", ""]
|
|
for playbook in playbooks:
|
|
lines.append(f"## {playbook.title}")
|
|
lines.append("")
|
|
lines.append(playbook.purpose)
|
|
lines.append("")
|
|
for step in playbook.steps:
|
|
lines.append(f"### {step.title}")
|
|
lines.append("")
|
|
lines.append(f"- acao: {step.action}")
|
|
lines.append(f"- evidencia necessaria: {step.evidence_needed}")
|
|
lines.append(f"- pronto quando: {step.done_when}")
|
|
lines.append("")
|
|
return "\n".join(lines).strip() + "\n"
|
|
|
|
|
|
def playbook_summary(playbooks: Sequence[HumanPlaybook]) -> dict[str, int]:
|
|
return {playbook.profile_id: len(playbook.steps) for playbook in playbooks}
|
|
|