import os import sys from pathlib import Path import click import yaml from dotenv import load_dotenv load_dotenv() DATA_DIR = Path("data") RAW_PATH = DATA_DIR / "raw.json" METRICS_PATH = DATA_DIR / "metrics.json" ANALYSIS_PATH = DATA_DIR / "analysis.json" SUMMARY_PATH = DATA_DIR / "summary.json" def _load_config() -> dict: config_path = Path("config.yaml") if not config_path.exists(): click.echo("Error: config.yaml not found. Copy and edit it before running.", err=True) sys.exit(1) with open(config_path) as f: return yaml.safe_load(f) def _require_env(key: str) -> str: value = os.getenv(key) if not value: click.echo(f"Error: {key} is not set. Add it to .env or your environment.", err=True) sys.exit(1) return value def _require_anthropic_auth() -> None: import shutil has_api_key = bool(os.getenv("ANTHROPIC_API_KEY")) has_cli = shutil.which("claude") is not None if not has_api_key and not has_cli: click.echo( "Error: no Anthropic credentials found. " "Set ANTHROPIC_API_KEY or ensure the 'claude' CLI is installed.", err=True, ) sys.exit(1) @click.group() def cli(): """GitHub Developer Performance Analysis Tool.""" @cli.command() def collect(): """Fetch GitHub data and save to data/raw.json.""" from collectors.github import collect as _collect config = _load_config() token = _require_env("GITHUB_TOKEN") click.echo("Starting GitHub data collection...") _collect(config, token, RAW_PATH) click.echo("Collection complete.") @cli.command() def analyze(): """Run Claude analysis on data/raw.json → data/analysis.json.""" from analyzers.claude import analyze as _analyze from metrics.calculator import calculate as _calculate if not RAW_PATH.exists(): click.echo(f"Error: {RAW_PATH} not found. Run 'collect' first.", err=True) sys.exit(1) _require_anthropic_auth() config = _load_config() click.echo("Computing quantitative metrics...") _calculate(RAW_PATH, METRICS_PATH) click.echo("Running Claude qualitative analysis...") _analyze(config, RAW_PATH, ANALYSIS_PATH) click.echo("Analysis complete.") @cli.command() def report(): """Print the performance report from cached data.""" from reporters.cli import print_report for path in [METRICS_PATH, ANALYSIS_PATH]: if not path.exists(): click.echo(f"Error: {path} not found. Run 'analyze' first.", err=True) sys.exit(1) config = _load_config() print_report(METRICS_PATH, ANALYSIS_PATH, config) @cli.command() def summarize(): """Run deep narrative summary and comparative redundancy analysis.""" from analyzers.summarizer import summarize as _summarize for path in [RAW_PATH, METRICS_PATH, ANALYSIS_PATH]: if not path.exists(): click.echo(f"Error: {path} not found. Run 'analyze' first.", err=True) sys.exit(1) _require_anthropic_auth() click.echo("Running deep narrative summary...") _summarize(RAW_PATH, METRICS_PATH, ANALYSIS_PATH, SUMMARY_PATH) @cli.command() def run(): """Run the full pipeline: collect → analyze → report.""" from collectors.github import collect as _collect from analyzers.claude import analyze as _analyze from metrics.calculator import calculate as _calculate from reporters.cli import print_report config = _load_config() token = _require_env("GITHUB_TOKEN") _require_anthropic_auth() click.echo("=== Step 1/3: Collecting GitHub data ===") _collect(config, token, RAW_PATH) click.echo("\n=== Step 2/3: Computing metrics & running Claude analysis ===") _calculate(RAW_PATH, METRICS_PATH) _analyze(config, RAW_PATH, ANALYSIS_PATH) click.echo("\n=== Step 3/3: Generating report ===") print_report(METRICS_PATH, ANALYSIS_PATH, config) if __name__ == "__main__": cli()