File size: 2,800 Bytes
d5341cc
 
 
1cdb3e3
d5341cc
 
1cdb3e3
 
 
 
 
d5341cc
 
 
 
 
 
1cdb3e3
 
d5341cc
 
1cdb3e3
 
 
 
 
 
 
 
 
 
d5341cc
 
1cdb3e3
 
 
 
 
d5341cc
1cdb3e3
d5341cc
 
 
 
 
 
 
 
 
 
 
 
1cdb3e3
d5341cc
1cdb3e3
 
 
d5341cc
1cdb3e3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d5341cc
 
 
 
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
71
72
73
74
75
76
77
78
79
80
81
82
83
"""CLI entry point for CodeTribunal."""

import json
import sys
from pathlib import Path

import click

from code_tribunal.config import TribunalConfig
from code_tribunal.evidence import gather_evidence_parallel
from code_tribunal.courtroom import Courtroom


@click.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("--output", "-o", type=click.Path(), help="Save full report to file (JSON)")
@click.option("--evidence-only", is_flag=True, help="Only run Phase 1 (GritQL evidence), skip trial")
@click.option("--parallel", is_flag=True, default=True, help="Use parallel GritQL scanning (default)")
def main(path: str, output: str | None, evidence_only: bool, parallel: bool) -> None:
    """Put your code on trial. PATH is the directory or zip to investigate."""

    config = TribunalConfig()

    if not config.is_configured:
        click.echo("Error: ZAI_API_KEY not set. Configure .env file.")
        sys.exit(1)

    click.echo("=" * 60)
    click.echo("  CODETRIBUNAL — THE AI COURTROOM")
    click.echo("=" * 60)

    if evidence_only:
        from code_tribunal.evidence import gather_evidence
        click.echo("\n[Phase 1] Gathering evidence with GritQL...")
        if parallel:
            report = gather_evidence_parallel(path)
        else:
            report = gather_evidence(path)
        click.echo(report.to_text())

        if output:
            Path(output).write_text(json.dumps({
                "findings": [str(f) for f in report.findings],
                "stats": {
                    "files": report.file_count,
                    "total": len(report.findings),
                    "by_severity": {s: len(i) for s, i in report.findings_by_severity.items()},
                },
            }, indent=2))
            click.echo(f"\nReport saved to {output}")
        return

    courtroom = Courtroom(config)

    click.echo("\nRunning full pipeline...\n")
    for event in courtroom.run(path):
        click.echo(f"  [{event.phase.value}] {event.status}")

    state = courtroom.pipeline.state
    if state and state.verdict:
        click.echo("\n" + "=" * 60)
        click.echo("  VERDICT")
        click.echo("=" * 60)
        click.echo(state.verdict)

    if output and state:
        Path(output).write_text(json.dumps({
            "evidence": state.evidence_report,
            "investigation": state.investigation_reports,
            "transcript": state.trial_transcript,
            "verdict": state.verdict,
            "report": state.report,
            "stats": {
                "files_scanned": state.files_scanned,
                "total_findings": state.total_findings,
            },
        }, indent=2, default=str))
        click.echo(f"\nFull report saved to {output}")


if __name__ == "__main__":
    main()