"""WP30 command-line interface. Every subcommand returns a meaningful exit code.""" from __future__ import annotations import argparse, sys def main(argv=None): ap = argparse.ArgumentParser(prog="wp30") sub = ap.add_subparsers(dest="cmd", required=True) p = sub.add_parser("doctor"); p.add_argument("--output", default="evidence/environment.json") p = sub.add_parser("sources"); p.add_argument("action", choices=["audit"]); p.add_argument("--config", default="configs/literature.yaml") p = sub.add_parser("data"); p.add_argument("action", choices=["prepare", "validate"]); p.add_argument("--config", default="configs/data.yaml"); p.add_argument("--manifest", default="data/manifests/splits.json") p = sub.add_parser("models"); p.add_argument("action", choices=["probe"]); p.add_argument("--config", default="configs/models.yaml") p = sub.add_parser("validate-cache"); p.add_argument("--config", default="configs/cache_validation.yaml") p = sub.add_parser("plan"); p.add_argument("--config", required=True); p.add_argument("--output", required=True) p = sub.add_parser("run"); p.add_argument("--config", required=True); p.add_argument("--resume", action="store_true"); p.add_argument("--limit", type=int, default=None); p.add_argument("--dry-run", action="store_true") p = sub.add_parser("protocol"); p.add_argument("action", choices=["freeze"]); p.add_argument("--config", required=True) p = sub.add_parser("analyze"); p.add_argument("--protocol", default="protocol/frozen.json") p = sub.add_parser("report"); p.add_argument("--protocol", default="protocol/frozen.json") p = sub.add_parser("reproduce"); p.add_argument("--profile", default="reproduction/minimal.yaml") p = sub.add_parser("audit-artifacts"); p.add_argument("--root", default=".") p = sub.add_parser("train-mapper"); p.add_argument("--config", default="configs/mapper.yaml") p = sub.add_parser("worker"); p.add_argument("--port", type=int, default=9430); p.add_argument("--model", required=True) a = ap.parse_args(argv) if a.cmd == "doctor": from .doctor import main as f; return f(a.output) if a.cmd == "sources": from .literature import audit; return audit(a.config) if a.cmd == "data": from .data.prepare import prepare, validate return prepare(a.config) if a.action == "prepare" else validate(a.manifest) if a.cmd == "models": from .models_probe import probe; return probe(a.config) if a.cmd == "validate-cache": from .validate_cache import main as f; return f(a.config) if a.cmd == "plan": from .runner import plan; return plan(a.config, a.output) if a.cmd == "run": from .runner import run; return run(a.config, resume=a.resume, limit=a.limit, dry_run=a.dry_run) if a.cmd == "protocol": from .protocol import freeze; return freeze(a.config) if a.cmd == "analyze": from .analysis.analyze import main as f; return f(a.protocol) if a.cmd == "report": from .analysis.report import main as f; return f(a.protocol) if a.cmd == "reproduce": from .reproduce import main as f; return f(a.profile) if a.cmd == "audit-artifacts": from .audit import main as f; return f(a.root) if a.cmd == "train-mapper": from .mapper import train_main; return train_main(a.config) if a.cmd == "worker": from .transport import serve; return serve(a.port, a.model) return 2 if __name__ == "__main__": sys.exit(main())