"""Command-line entry point for configuration and model preflight.""" from __future__ import annotations import argparse import json from pathlib import Path import subprocess import sys from .analysis import AnalysisError, analyze_pilot_report from .backend_experiment import BackendExperimentError, run_backend_experiment from .confirmatory_retrieval import ConfirmatoryRetrievalError, run_confirmatory_retrieval from .lm_studio import LMStudioClient, LMStudioError from .lm_studio_embeddings import EmbeddingStudioError, LMStudioEmbeddingClient from .interactive_experiment import ( InteractiveExperimentError, run_iterative_final, run_one_shot_and_queries, run_refined_retrieval, ) from .llm_localization import LocalizationError, run_localization from .live_agent_experiment import LiveAgentExperimentError, run_live_agent_experiment from .lm_studio_management import LMStudioManagementError from .pilot import PilotError, run_static_retrieval_pilot from .protocol_experiment import ( ProtocolExperimentError, run_protocol_experiment, run_retrieval_protocol_experiment, run_study4_ancillary, ) from .repair_experiment import RepairExperimentError, run_repair_experiment from .robustness_experiment import RobustnessExperimentError, run_robustness_experiment from .study2_experiment import ( Study2ExperimentError, run_study2_experiment, run_study2_reliability, ) from .study5_experiment import Study5ExperimentError, run_study5_experiment from .specs import ( SpecError, load_embeddings, load_experiments, load_harnesses, load_models, load_task_split, project_root, validate_configuration_tree, ) def _root(value: str | None) -> Path: return Path(value).resolve() if value else project_root() def command_validate(args: argparse.Namespace) -> int: root = _root(args.root) errors, warnings = validate_configuration_tree(root) for warning in warnings: print(f"WARNING: {warning}") for error in errors: print(f"ERROR: {error}", file=sys.stderr) if errors: return 1 print(f"Configuration tree is valid: {root}") return 0 def command_list_harnesses(args: argparse.Namespace) -> int: for spec in load_harnesses(_root(args.root)).values(): print( f"{spec.harness_id}\t{spec.name}\t{spec.config_hash[:12]}\t" f"L={int(spec.lexical)} S={int(spec.syntax == 'tree_sitter')} " f"D={int(spec.dense)} G={spec.graph_hops} Q={spec.query_policy} " f"I={spec.interface} P={spec.packing} C={spec.control}" ) return 0 def command_plan(args: argparse.Namespace) -> int: root = _root(args.root) experiments = load_experiments(root) try: experiment = experiments[args.experiment] except KeyError: print(f"Unknown experiment {args.experiment}; choices: {sorted(experiments)}", file=sys.stderr) return 1 manifest_path = root / "configs" / "study5" / f"{experiment.experiment_id}_cells.json" manifest = ( json.loads(manifest_path.read_text(encoding="utf-8")) if manifest_path.is_file() else None ) per_task = experiment.cells_per_task() total_cells = per_task * args.tasks if manifest is not None: manifest_tasks = {item["task_id"] for item in manifest["cells"]} if args.tasks != len(manifest_tasks): print( f"Study 5 manifest fixes task_count={len(manifest_tasks)}; " f"ignoring requested --tasks={args.tasks}", file=sys.stderr, ) per_task = int(manifest["planned_cells"]) // len(manifest_tasks) total_cells = int(manifest["planned_cells"]) result = { "experiment_id": experiment.experiment_id, "mode": experiment.mode, "harness_count": len(experiment.harness_ids), "backend_ids": experiment.backend_ids, "model_ids": experiment.model_ids, "context_budgets": experiment.context_budgets, "seeds": experiment.seeds, "repetitions": experiment.repetitions, "cells_per_task": per_task, "task_count": len(manifest_tasks) if manifest is not None else args.tasks, "total_cells": total_cells, "manifest": str(manifest_path) if manifest is not None else None, } print(json.dumps(result, indent=2)) return 0 def command_probe_model(args: argparse.Namespace) -> int: models = load_models(_root(args.root)) try: spec = models[args.model] client = LMStudioClient(spec, timeout_seconds=args.timeout) discovery, resolved = client.resolve() output: dict[str, object] = { "expected_model": spec.canonical_name, "model_config_hash": spec.config_hash, "resolved": resolved.to_dict(), "discovery_errors": discovery.endpoint_errors, } if args.infer: output["inference_probe"] = client.inference_probe(resolved.inference_key) print(json.dumps(output, indent=2, sort_keys=True)) return 0 except (KeyError, SpecError, LMStudioError) as exc: print(f"MODEL PREFLIGHT FAILED: {exc}", file=sys.stderr) return 1 def command_probe_embedding(args: argparse.Namespace) -> int: embeddings = load_embeddings(_root(args.root)) try: spec = embeddings[args.embedding] client = LMStudioEmbeddingClient(spec, timeout_seconds=args.timeout) output: dict[str, object] = { "embedding_id": spec.embedding_id, "embedding_config_hash": spec.config_hash, "resolved": client.resolve(), } if args.infer: output["inference_probe"] = client.probe().to_dict() # Capture the actual loaded-instance context after possible JIT load. output["resolved"] = client.resolve() print(json.dumps(output, indent=2, sort_keys=True)) return 0 except (KeyError, SpecError, EmbeddingStudioError) as exc: print(f"EMBEDDING PREFLIGHT FAILED: {exc}", file=sys.stderr) return 1 def command_doctor(args: argparse.Namespace) -> int: root = _root(args.root) errors, warnings = validate_configuration_tree(root) if args.experiment: experiments = load_experiments(root) harnesses = load_harnesses(root) embeddings = load_embeddings(root) experiment = experiments.get(args.experiment) if experiment is None: errors.append(f"unknown experiment {args.experiment}") else: split_path = root / "tasks" / "splits" / f"{experiment.task_split}.txt" if not load_task_split(split_path): errors.append( f"{experiment.experiment_id} cannot run until task split " f"{experiment.task_split} contains eligible task IDs" ) if any(harnesses[item].dense for item in experiment.harness_ids): embedding = embeddings[experiment.embedding_id] if embedding.status != "ready": errors.append( f"{experiment.experiment_id} cannot run dense treatments until " f"{embedding.embedding_id} is configured" ) for warning in warnings: print(f"WARNING: {warning}") for error in errors: print(f"ERROR: {error}", file=sys.stderr) return 1 if errors else 0 def command_run_pilot(args: argparse.Namespace) -> int: root = _root(args.root) try: summary = run_static_retrieval_pilot( root=root, repository=Path(args.repository).resolve(), experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, candidate_limit=args.candidate_limit, ) print(json.dumps(summary, indent=2, sort_keys=True)) return 0 except (PilotError, EmbeddingStudioError) as exc: print(f"PILOT FAILED: {exc}", file=sys.stderr) return 1 def command_summarize_pilot(args: argparse.Namespace) -> int: root = _root(args.root) report_path = Path(args.report).resolve() try: revision_result = subprocess.run( ["git", "rev-parse", "HEAD"], cwd=root, check=True, capture_output=True, text=True, timeout=30, ) summary = analyze_pilot_report(root, report_path, revision_result.stdout.strip()) rendered = json.dumps(summary, indent=2, sort_keys=True) + "\n" if args.output: output = Path(args.output).resolve() output.parent.mkdir(parents=True, exist_ok=True) with output.open("x", encoding="utf-8") as handle: handle.write(rendered) print(rendered, end="") return 0 except (AnalysisError, OSError, subprocess.SubprocessError) as exc: print(f"ANALYSIS FAILED: {exc}", file=sys.stderr) return 1 def command_run_localization(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_localization( root=root, repository=Path(args.repository).resolve(), ranking_path=Path(args.ranking).resolve(), task_id=args.task, harness_id=args.harness, experiment_id=args.experiment, candidate_limit=args.candidate_limit, timeout_seconds=args.timeout, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (LocalizationError, LMStudioError, PilotError, OSError) as exc: print(f"LOCALIZATION FAILED: {exc}", file=sys.stderr) return 1 def command_run_confirmatory_retrieval(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_confirmatory_retrieval( root=root, repository=Path(args.repository).resolve(), experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, candidate_limit=args.candidate_limit, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (ConfirmatoryRetrievalError, EmbeddingStudioError, PilotError, OSError) as exc: print(f"CONFIRMATORY RETRIEVAL FAILED: {exc}", file=sys.stderr) return 1 def command_run_backend_experiment(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_backend_experiment( root=root, repository=Path(args.repository).resolve(), experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, backend_filter=set(args.backend) if args.backend else None, harness_filter=set(args.harness) if args.harness else None, candidate_limit=args.candidate_limit, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (BackendExperimentError, EmbeddingStudioError, OSError) as exc: print(f"BACKEND EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_interactive(args: argparse.Namespace) -> int: root = _root(args.root) kwargs = { "root": root, "repository": Path(args.repository).resolve(), "task_filter": set(args.task) if args.task else None, "harness_filter": set(args.harness) if args.harness else None, } try: if args.phase in {"one_shot", "query"}: result = run_one_shot_and_queries(phase=args.phase, **kwargs) elif args.phase == "refined_retrieval": result = run_refined_retrieval(**kwargs) elif args.phase == "iterative_final": result = run_iterative_final(**kwargs) else: raise InteractiveExperimentError(f"unknown phase {args.phase}") print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (InteractiveExperimentError, LMStudioError, EmbeddingStudioError, OSError) as exc: print(f"INTERACTIVE EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_repairs(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_repair_experiment( root=root, repository=Path(args.repository).resolve(), task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (RepairExperimentError, LMStudioError, OSError, subprocess.SubprocessError) as exc: print(f"REPAIR EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_robustness(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_robustness_experiment( root=root, repository=Path(args.repository).resolve(), experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, seed_filter=set(args.seed) if args.seed else None, candidate_limit=args.candidate_limit, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except (RobustnessExperimentError, EmbeddingStudioError, PilotError, OSError) as exc: print(f"ROBUSTNESS EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_live_agent(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_live_agent_experiment( root=root, repository=Path(args.repository).resolve(), experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, ) print(json.dumps(result, indent=2, sort_keys=True)) return 0 except ( LiveAgentExperimentError, LMStudioManagementError, LMStudioError, EmbeddingStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"LIVE AGENT EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_study2(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_study2_experiment( root=root, experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, treatment_filter=set(args.treatment) if args.treatment else None, model_filter=set(args.model) if args.model else None, stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( Study2ExperimentError, PilotError, LMStudioManagementError, LMStudioError, EmbeddingStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"STUDY 2 EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_study2_reliability(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_study2_reliability( root=root, manifest_path=Path(args.manifest).resolve() if args.manifest else None, stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( Study2ExperimentError, PilotError, LMStudioManagementError, LMStudioError, EmbeddingStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"STUDY 2 RELIABILITY RUN FAILED: {exc}", file=sys.stderr) return 1 def command_run_protocol(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_protocol_experiment( root=root, experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, interface_filter=set(args.interface) if args.interface else None, model_filter=set(args.model) if args.model else None, stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "accepted_edit_count": result["accepted_edit_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( ProtocolExperimentError, PilotError, LMStudioManagementError, LMStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"PROTOCOL EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_retrieval_protocol(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_retrieval_protocol_experiment( root=root, experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, model_filter=set(args.model) if args.model else None, stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "accepted_edit_count": result["accepted_edit_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( ProtocolExperimentError, PilotError, LMStudioManagementError, LMStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"RETRIEVAL PROTOCOL EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def command_run_study4_ancillary(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_study4_ancillary( root=root, manifest_path=Path(args.manifest).resolve(), stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "accepted_edit_count": result["accepted_edit_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( ProtocolExperimentError, PilotError, LMStudioManagementError, LMStudioError, EmbeddingStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"STUDY 4 ANCILLARY FAILED: {exc}", file=sys.stderr) return 1 def command_run_study5(args: argparse.Namespace) -> int: root = _root(args.root) try: result = run_study5_experiment( root=root, experiment_id=args.experiment, task_filter=set(args.task) if args.task else None, harness_filter=set(args.harness) if args.harness else None, interface_filter=set(args.interface) if args.interface else None, model_filter=set(args.model) if args.model else None, stop_server_when_complete=not args.keep_server_running, ) print( json.dumps( { "experiment_id": result["experiment_id"], "code_revision": result["code_revision"], "run_count": result["run_count"], "accepted_edit_count": result["accepted_edit_count"], "applicable_patch_count": result["applicable_patch_count"], "resolved_count": result["resolved_count"], "report_path": result["report_path"], }, indent=2, sort_keys=True, ) ) return 0 except ( Study5ExperimentError, ProtocolExperimentError, PilotError, LMStudioManagementError, LMStudioError, EmbeddingStudioError, OSError, subprocess.SubprocessError, ) as exc: print(f"STUDY 5 EXPERIMENT FAILED: {exc}", file=sys.stderr) return 1 def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(prog="harness-research") parser.add_argument("--root", help="project root (defaults to the installed source tree)") subparsers = parser.add_subparsers(dest="command", required=True) validate = subparsers.add_parser("validate", help="validate all configuration files") validate.set_defaults(func=command_validate) listing = subparsers.add_parser("list-harnesses", help="list immutable harness identities") listing.set_defaults(func=command_list_harnesses) plan = subparsers.add_parser("plan", help="expand experiment cells without running them") plan.add_argument("--experiment", required=True) plan.add_argument("--tasks", type=int, default=1) plan.set_defaults(func=command_plan) probe = subparsers.add_parser("probe-model", help="discover and verify Qwen in LM Studio") probe.add_argument("--model", default="M001") probe.add_argument("--timeout", type=float, default=10.0) probe.add_argument("--infer", action="store_true", help="also run a semantic completion probe") probe.set_defaults(func=command_probe_model) embedding_probe = subparsers.add_parser( "probe-embedding", help="discover and verify the pinned LM Studio embedding model", ) embedding_probe.add_argument("--embedding", default="EMB001") embedding_probe.add_argument("--timeout", type=float, default=30.0) embedding_probe.add_argument( "--infer", action="store_true", help="also verify vector dimensions, normalization, and distinctness", ) embedding_probe.set_defaults(func=command_probe_embedding) doctor = subparsers.add_parser("doctor", help="check whether an experiment is runnable") doctor.add_argument("--experiment") doctor.set_defaults(func=command_doctor) pilot = subparsers.add_parser("run-pilot", help="run the immutable E00 retrieval pilot") pilot.add_argument("--experiment", default="E00") pilot.add_argument("--repository", default="data/repos/gitlab-runner") pilot.add_argument("--task", action="append", help="limit to a task ID; repeatable") pilot.add_argument("--harness", action="append", help="limit to a harness ID; repeatable") pilot.add_argument("--candidate-limit", type=int, default=200) pilot.set_defaults(func=command_run_pilot) summarize = subparsers.add_parser("summarize-pilot", help="audit and summarize an E00 report") summarize.add_argument("--report", required=True) summarize.add_argument("--output") summarize.set_defaults(func=command_summarize_pilot) localization = subparsers.add_parser( "run-localization", help="run one blinded Qwen localization cell" ) localization.add_argument("--experiment", default="E06") localization.add_argument("--repository", default="data/repos/gitlab-runner") localization.add_argument("--ranking", required=True) localization.add_argument("--task", required=True) localization.add_argument("--harness", required=True) localization.add_argument("--candidate-limit", type=int, default=10) localization.add_argument("--timeout", type=float, default=900.0) localization.set_defaults(func=command_run_localization) confirmatory = subparsers.add_parser( "run-confirmatory-retrieval", help="run frozen E01 retrieval treatments" ) confirmatory.add_argument("--experiment", default="E01") confirmatory.add_argument("--repository", default="data/repos/gitlab-runner") confirmatory.add_argument("--task", action="append") confirmatory.add_argument("--harness", action="append") confirmatory.add_argument("--candidate-limit", type=int, default=200) confirmatory.set_defaults(func=command_run_confirmatory_retrieval) backend = subparsers.add_parser("run-backends", help="run frozen E05 backend cells") backend.add_argument("--experiment", default="E05") backend.add_argument("--repository", default="data/repos/gitlab-runner") backend.add_argument("--task", action="append") backend.add_argument("--backend", action="append") backend.add_argument("--harness", action="append") backend.add_argument("--candidate-limit", type=int, default=200) backend.set_defaults(func=command_run_backend_experiment) interactive = subparsers.add_parser("run-interactive", help="run one phase of E02") interactive.add_argument( "--phase", required=True, choices=("one_shot", "query", "refined_retrieval", "iterative_final"), ) interactive.add_argument("--repository", default="data/repos/gitlab-runner") interactive.add_argument("--task", action="append") interactive.add_argument("--harness", action="append") interactive.set_defaults(func=command_run_interactive) repairs = subparsers.add_parser("run-repairs", help="run frozen E03 repair cells") repairs.add_argument("--repository", default="data/repos/gitlab-runner") repairs.add_argument("--task", action="append") repairs.add_argument("--harness", action="append") repairs.set_defaults(func=command_run_repairs) robustness = subparsers.add_parser("run-robustness", help="run frozen E04 robustness cells") robustness.add_argument("--experiment", default="E04") robustness.add_argument("--repository", default="data/repos/gitlab-runner") robustness.add_argument("--task", action="append") robustness.add_argument("--harness", action="append") robustness.add_argument("--seed", action="append", type=int) robustness.add_argument("--candidate-limit", type=int, default=200) robustness.set_defaults(func=command_run_robustness) live_agent = subparsers.add_parser( "run-live-agent", help="run the frozen E07 live search/read/edit/test agent" ) live_agent.add_argument("--experiment", default="E07") live_agent.add_argument("--repository", default="data/repos/gitlab-runner") live_agent.add_argument("--task", action="append") live_agent.add_argument("--harness", action="append") live_agent.set_defaults(func=command_run_live_agent) study2 = subparsers.add_parser( "run-study2", help="run/resume the prospective E08 multi-repository study" ) study2.add_argument("--experiment", default="E08") study2.add_argument("--task", action="append") study2.add_argument("--treatment", action="append") study2.add_argument("--model", action="append") study2.add_argument("--keep-server-running", action="store_true") study2.set_defaults(func=command_run_study2) reliability = subparsers.add_parser( "run-study2-reliability", help="run/resume the frozen E08 stochastic reliability cells", ) reliability.add_argument("--manifest") reliability.add_argument("--keep-server-running", action="store_true") reliability.set_defaults(func=command_run_study2_reliability) protocol = subparsers.add_parser( "run-protocol-study", help="run/resume the prospective E09 model-by-edit-interface study", ) protocol.add_argument("--experiment", default="E09") protocol.add_argument("--task", action="append") protocol.add_argument("--interface", action="append") protocol.add_argument("--model", action="append") protocol.add_argument("--keep-server-running", action="store_true") protocol.set_defaults(func=command_run_protocol) retrieval_protocol = subparsers.add_parser( "run-retrieval-protocol-study", help="run/resume the prospective E10 fresh-task retrieval study", ) retrieval_protocol.add_argument("--experiment", default="E10") retrieval_protocol.add_argument("--task", action="append") retrieval_protocol.add_argument("--harness", action="append") retrieval_protocol.add_argument("--model", action="append") retrieval_protocol.add_argument("--keep-server-running", action="store_true") retrieval_protocol.set_defaults(func=command_run_retrieval_protocol) study4_ancillary = subparsers.add_parser( "run-study4-ancillary", help="run/resume a frozen Study 4 reliability or context manifest", ) study4_ancillary.add_argument("--manifest", required=True) study4_ancillary.add_argument("--keep-server-running", action="store_true") study4_ancillary.set_defaults(func=command_run_study4_ancillary) study5 = subparsers.add_parser( "run-study5", help="run/resume a frozen manifest-driven Study 5 harness experiment", ) study5.add_argument("--experiment", required=True, choices=("E13", "E14", "E15", "E16")) study5.add_argument("--task", action="append") study5.add_argument("--harness", action="append") study5.add_argument("--interface", action="append") study5.add_argument("--model", action="append") study5.add_argument("--keep-server-running", action="store_true") study5.set_defaults(func=command_run_study5) return parser def main(argv: list[str] | None = None) -> int: parser = build_parser() args = parser.parse_args(argv) try: return int(args.func(args)) except SpecError as exc: print(f"CONFIGURATION ERROR: {exc}", file=sys.stderr) return 1 if __name__ == "__main__": raise SystemExit(main())