NODEDC_MISSION_CORE/src/k1link/simulation/cli.py

99 lines
2.7 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
from typing import Annotated
import typer
from rich.console import Console
from rich.table import Table
from k1link.simulation import S0ProfileError, run_s0_doctor
app = typer.Typer(
name="missioncore-sim",
help="Fail-closed qualification tooling for the Mission Core Polygon.",
no_args_is_help=True,
)
s0_app = typer.Typer(
help="SIM S0 compatibility and infrastructure qualification.",
no_args_is_help=True,
)
app.add_typer(s0_app, name="s0")
console = Console()
def _default_profile() -> Path:
return Path(__file__).resolve().parents[3] / "simulation" / "s0" / "qualification-profile.yaml"
DEFAULT_PROFILE = _default_profile()
@s0_app.command("doctor")
def s0_doctor(
profile: Annotated[
Path,
typer.Option(
"--profile",
help="Strict SIM S0 qualification profile.",
exists=True,
dir_okay=False,
readable=True,
),
] = DEFAULT_PROFILE,
evidence: Annotated[
Path | None,
typer.Option(
"--evidence",
help="Optional digest-bound target-worker evidence manifest.",
exists=True,
dir_okay=False,
readable=True,
),
] = None,
json_output: Annotated[
bool,
typer.Option("--json", help="Emit the complete report as JSON."),
] = False,
) -> None:
"""Inspect contracts and local target readiness without changing the host."""
try:
report = run_s0_doctor(profile, evidence_path=evidence)
except (OSError, S0ProfileError) as exc:
if json_output:
console.print_json(
json.dumps(
{
"schema_version": "missioncore.simulation-s0-doctor/v1",
"verdict": "blocked",
"error": str(exc),
}
)
)
else:
console.print(f"[red]SIM S0 profile rejected:[/red] {exc}")
raise typer.Exit(code=2) from exc
payload = report.to_dict()
if json_output:
console.print_json(json.dumps(payload))
return
table = Table(title=f"SIM S0 doctor — {report.profile_id}")
table.add_column("Check")
table.add_column("Status")
table.add_column("Detail")
colors = {"pass": "green", "fail": "red", "unknown": "yellow"}
for check in report.checks:
status = check.status.value
styled_status = f"[{colors[status]}]{status}[/{colors[status]}]"
table.add_row(check.identifier, styled_status, check.detail)
console.print(table)
console.print(f"Verdict: [bold]{report.verdict.value.upper()}[/bold]")
if __name__ == "__main__":
app()