File size: 2,740 Bytes
4bcb8ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env python3
"""
cli.py — Interface de Linha de Comando do Protocolo de Auditoria Civica TecnoPopular.
Permite avaliar qualquer ferramenta civica via URL e gerar laudos tecnicos em JSON e Markdown.
"""
import argparse
import json
import sys
from pathlib import Path

from models import AuditRubric
from evaluator import CivicEvaluator


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Protocolo de Auditoria Civica TecnoPopular (CTP-1.0) - Inspecao Tecnica"
    )
    parser.add_argument("--url", required=True, help="URL pública da ferramenta cívica a ser auditada")
    parser.add_argument("--name", required=True, help="Nome legível da iniciativa")
    parser.add_argument("--id", default="", help="Slug / Identificador único (opcional)")
    parser.add_argument("--repo", default=None, help="URL do repositório público de código (opcional)")
    parser.add_argument("--sources", nargs="*", default=None, help="Fontes primárias declaradas (ex: TSE IBGE CGU)")
    parser.add_argument("--output-json", default="", help="Caminho para salvar o laudo em JSON")
    parser.add_argument("--output-md", default="", help="Caminho para salvar a síntese em Markdown")

    args = parser.parse_args()

    tool_id = args.id or args.name.lower().replace(" ", "-")
    evaluator = CivicEvaluator()

    print(f"[*] Iniciando auditoria técnica de: {args.name} ({args.url})")
    report = evaluator.audit_target(
        tool_id=tool_id,
        tool_name=args.name,
        target_url=args.url,
        declared_repo=args.repo,
        declared_sources=args.sources
    )

    print("\n" + "=" * 70)
    print(f"LAUDO DE AUDITORIA CIVICA: {report.tool_name}")
    print("=" * 70)
    print(f"Status:            {report.status.value.upper()}")
    print(f"Selo/Classificacao: {report.badge_label}")
    print(f"Score Total:       {report.total_score:.1f} / 100")
    print(f"Bloqueador Critico: {'SIM' if report.has_critical_blocker else 'NAO'}")
    print("-" * 70)
    print("NOTAS POR DIMENSAO:")
    for dim, score in report.dimension_scores.items():
        st = "APROVADO" if score.is_passing else "AJUSTE RECOMENDADO"
        print(f"  - {dim.value:25} {score.raw_score:5.1f}/100 ({score.weighted_score:4.1f} pts) [{st}]")
    print("=" * 70)

    if args.output_json:
        p_json = Path(args.output_json)
        p_json.write_text(report.model_dump_json(indent=2), encoding="utf-8")
        print(f"[+] Laudo estruturado salvo em: {p_json}")

    if args.output_md:
        p_md = Path(args.output_md)
        p_md.write_text(report.summary_markdown, encoding="utf-8")
        print(f"[+] Sintese Markdown salva em: {p_md}")

    return 0


if __name__ == "__main__":
    sys.exit(main())