Files
ProgramadorBrasil 61ec71c5c7 feat: add 52 specialized AI agent skills (#217)
New skills covering 10 categories:

**Security & Audit**: 007 (STRIDE/PASTA/OWASP), cred-omega (secrets management)
**AI Personas**: Karpathy, Hinton, Sutskever, LeCun (4 sub-skills), Altman, Musk, Gates, Jobs, Buffett
**Multi-agent Orchestration**: agent-orchestrator, task-intelligence, multi-advisor
**Code Analysis**: matematico-tao (Terence Tao-inspired mathematical code analysis)
**Social & Messaging**: Instagram Graph API, Telegram Bot, WhatsApp Cloud API, social-orchestrator
**Image Generation**: AI Studio (Gemini), Stability AI, ComfyUI Gateway, image-studio router
**Brazilian Domain**: 6 auction specialist modules, 2 legal advisors, auctioneers data scraper
**Product & Growth**: design, invention, monetization, analytics, growth engine
**DevOps & LLM Ops**: Docker/CI-CD/AWS, RAG/embeddings/fine-tuning
**Skill Governance**: installer, sentinel auditor, context management

Each skill includes:
- Standardized YAML frontmatter (name, description, risk, source, tags, tools)
- Structured sections (Overview, When to Use, How it Works, Best Practices)
- Python scripts and reference documentation where applicable
- Cross-platform compatibility (Claude Code, Antigravity, Cursor, Gemini CLI, Codex CLI)

Co-authored-by: ProgramadorBrasil <214873561+ProgramadorBrasil@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 10:04:07 +01:00

225 lines
8.6 KiB
Python

"""
Gerador de relatorios Markdown.
Produz relatorio estruturado com resumo executivo, scores por skill,
findings por severidade, recomendacoes e plano de acao.
"""
from __future__ import annotations
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional
from config import DIMENSION_WEIGHTS, REPORTS_DIR, SEVERITY_ORDER, get_score_label
def _severity_icon(severity: str) -> str:
"""Retorna indicador textual de severidade."""
icons = {
"critical": "[CRITICO]",
"high": "[ALTO]",
"medium": "[MEDIO]",
"low": "[BAIXO]",
"info": "[INFO]",
}
return icons.get(severity, "[?]")
def _format_score(score: Optional[float]) -> str:
"""Formata score como string."""
if score is None:
return "N/A"
return f"{score:.0f}"
def generate_report(
snapshots: List[Dict[str, Any]],
findings: List[Dict[str, Any]],
recommendations: List[Dict[str, Any]],
overall_score: float,
previous_snapshots: Optional[List[Dict[str, Any]]] = None,
) -> str:
"""Gera relatorio Markdown completo."""
now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
lines: List[str] = []
# -- Header ----------------------------------------------------------------
lines.append("# Relatorio Sentinel - Auditoria do Ecossistema de Skills")
lines.append("")
lines.append(f"**Data:** {now}")
lines.append(f"**Skills Analisadas:** {len(snapshots)}")
lines.append(f"**Score Geral:** {overall_score:.0f}/100 ({get_score_label(overall_score)})")
lines.append("")
lines.append("---")
lines.append("")
# -- Resumo Executivo (tabela) ---------------------------------------------
lines.append("## Resumo Executivo")
lines.append("")
lines.append("| Skill | Score | Qualidade | Seguranca | Performance | Governanca | Docs | Deps |")
lines.append("|-------|-------|-----------|-----------|-------------|------------|------|------|")
for snap in sorted(snapshots, key=lambda s: -(s.get("overall_score") or 0)):
name = snap.get("skill_name", "?")
overall = _format_score(snap.get("overall_score"))
cq = _format_score(snap.get("code_quality"))
sec = _format_score(snap.get("security"))
perf = _format_score(snap.get("performance"))
gov = _format_score(snap.get("governance"))
doc = _format_score(snap.get("documentation"))
deps = _format_score(snap.get("dependencies"))
lines.append(f"| {name} | {overall} | {cq} | {sec} | {perf} | {gov} | {doc} | {deps} |")
lines.append("")
# -- Tendencias (se houver dados anteriores) --------------------------------
if previous_snapshots:
lines.append("## Tendencias")
lines.append("")
prev_map = {s["skill_name"]: s for s in previous_snapshots}
for snap in snapshots:
name = snap.get("skill_name", "?")
prev = prev_map.get(name)
if prev:
curr_score = snap.get("overall_score", 0) or 0
prev_score = prev.get("overall_score", 0) or 0
delta = curr_score - prev_score
if delta > 0:
trend = f"+{delta:.0f} pts"
elif delta < 0:
trend = f"{delta:.0f} pts"
else:
trend = "sem alteracao"
lines.append(f"- **{name}**: {prev_score:.0f} -> {curr_score:.0f} ({trend})")
lines.append("")
# -- Findings por Severidade ------------------------------------------------
lines.append("## Findings por Severidade")
lines.append("")
# Agrupar
by_severity: Dict[str, List[Dict[str, Any]]] = {}
for f in findings:
sev = f.get("severity", "info")
by_severity.setdefault(sev, []).append(f)
severity_labels = {
"critical": "Criticos",
"high": "Altos",
"medium": "Medios",
"low": "Baixos",
"info": "Informativos",
}
for sev in ["critical", "high", "medium", "low", "info"]:
items = by_severity.get(sev, [])
label = severity_labels.get(sev, sev)
lines.append(f"### {label} ({len(items)})")
lines.append("")
if not items:
lines.append("Nenhum.")
lines.append("")
continue
for f in items:
skill = f.get("skill_name", "?")
title = f.get("title", "?")
lines.append(f"- {_severity_icon(sev)} **[{skill}]** {title}")
if f.get("recommendation"):
lines.append(f" - Recomendacao: {f['recommendation']}")
if f.get("file_path"):
loc = f["file_path"]
if f.get("line_number"):
loc += f":{f['line_number']}"
lines.append(f" - Local: `{loc}`")
lines.append("")
# -- Analise por Skill -----------------------------------------------------
lines.append("## Analise por Skill")
lines.append("")
for snap in sorted(snapshots, key=lambda s: s.get("skill_name", "")):
name = snap.get("skill_name", "?")
overall = snap.get("overall_score", 0)
lines.append(f"### {name} ({_format_score(overall)}/100 - {get_score_label(overall or 0)})")
lines.append("")
lines.append(f"- Arquivos Python: {snap.get('file_count', 0)}")
lines.append(f"- Linhas de codigo: {snap.get('line_count', 0)}")
lines.append(f"- Qualidade: {_format_score(snap.get('code_quality'))} | "
f"Seguranca: {_format_score(snap.get('security'))} | "
f"Performance: {_format_score(snap.get('performance'))}")
lines.append(f"- Governanca: {_format_score(snap.get('governance'))} | "
f"Docs: {_format_score(snap.get('documentation'))} | "
f"Deps: {_format_score(snap.get('dependencies'))}")
lines.append("")
# Findings desta skill
skill_findings = [f for f in findings if f.get("skill_name") == name and f.get("severity") != "info"]
if skill_findings:
for f in sorted(skill_findings, key=lambda x: SEVERITY_ORDER.get(x.get("severity", "info"), 9)):
lines.append(f" - {_severity_icon(f['severity'])} {f['title']}")
else:
lines.append(" Nenhum finding significativo.")
lines.append("")
# -- Recomendacoes de Novas Skills -----------------------------------------
if recommendations:
lines.append("## Recomendacoes de Novas Skills")
lines.append("")
for i, rec in enumerate(recommendations, 1):
name = rec.get("suggested_name", "?")
priority = rec.get("priority", "?")
rationale = rec.get("rationale", "")
caps = rec.get("capabilities", [])
if isinstance(caps, str):
caps = [caps]
lines.append(f"### {i}. {name} (prioridade: {priority})")
lines.append("")
lines.append(f"**Razao:** {rationale}")
lines.append("")
if caps:
lines.append(f"**Capacidades:** {', '.join(caps)}")
lines.append("")
# -- Plano de Acao Priorizado ----------------------------------------------
lines.append("## Plano de Acao Priorizado")
lines.append("")
actionable = [
f for f in findings
if f.get("severity") in ("critical", "high", "medium") and f.get("recommendation")
]
actionable.sort(key=lambda x: (
SEVERITY_ORDER.get(x.get("severity", "info"), 9),
{"low": 0, "medium": 1, "high": 2}.get(x.get("effort", "medium"), 1),
))
if actionable:
lines.append("| # | Severidade | Skill | Acao | Esforco |")
lines.append("|---|-----------|-------|------|---------|")
for i, f in enumerate(actionable[:20], 1):
sev = f.get("severity", "?")
skill = f.get("skill_name", "?")
rec = f.get("recommendation", "?")[:80]
effort = f.get("effort", "?")
lines.append(f"| {i} | {sev} | {skill} | {rec} | {effort} |")
else:
lines.append("Nenhuma acao prioritaria identificada.")
lines.append("")
lines.append("---")
lines.append(f"*Gerado por skill-sentinel em {now}*")
return "\n".join(lines)
def save_report(content: str, filename: Optional[str] = None) -> str:
"""Salva relatorio em arquivo e retorna o path."""
if not filename:
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
filename = f"audit_{timestamp}.md"
filepath = REPORTS_DIR / filename
filepath.parent.mkdir(parents=True, exist_ok=True)
filepath.write_text(content, encoding="utf-8")
return str(filepath)