"""Transport for the `dev` domain — args in, delegate, format out.""" from __future__ import annotations import typer from tooling.core import cli, console from tooling.core.command import command from tooling.core.errors import ReachError from tooling.domains.dev import environment, service app = cli.domain("dev", "Developer environment and self-diagnosis.") @app.callback() def _domain() -> None: """Keeps `dev` a group (Typer collapses a single-command app).""" @app.command("install-godot") @command def install_godot( version: str = typer.Option(None, "--version", help="Godot version to install."), plan_only: bool = typer.Option( False, "--plan", help="Report what would be downloaded without doing it." ), ) -> None: """Install the pinned Godot build to ~/bin/godot4, if it is not already there.""" if plan_only: plan = environment.godot_plan(version) console.out(f"wanted {plan.wanted}") console.out(f"installed {plan.installed or '(none)'}") console.out(f"platform {plan.platform_tag}") console.out(f"url {plan.url}") console.verdict( "already current — nothing to do" if plan.already_current else "would download and install" ) return environment.install_godot(version) @app.command("install-rust") @command def install_rust() -> None: """Ensure clippy and rustfmt are present on the Rust toolchain.""" environment.install_rust() @app.command("worktree") @command def worktree( branch: str = typer.Argument(..., help="Branch name for the new worktree."), start: str = typer.Argument("HEAD", help="Start point."), plan_only: bool = typer.Option( False, "--plan", help="Report where it would go without creating it." ), ) -> None: """Create a worktree under .worktrees/ with the venv linked in.""" if plan_only: console.verdict(f"would create {environment.worktree_plan(branch)}") return environment.setup_worktree(branch, start) @app.command("perf") @command def perf( compare: bool = typer.Option( False, "--compare", help="Compare against the saved baseline instead of writing one." ), ) -> None: """Benchmark the server and write or check tests/perf/baseline.json.""" from tooling.domains.dev import perf as perf_module perf_module.run(compare) @app.command("clerk") @command def clerk( plan_only: bool = typer.Option( False, "--plan", help="Show the per-commit plan without spawning any clerk." ), ) -> None: """Review the push range for decision contradictions, one agent per commit.""" from tooling.domains.dev import clerk as clerk_module clerk_module.run(plan_only) @app.command("selftest") @command def selftest( seconds: float = typer.Option(2.0, "--seconds", "-s", help="Roughly how long to run."), fail: bool = typer.Option(False, "--fail", help="Exit non-zero at the end."), exit_code: int = typer.Option(1, "--exit-code", help="Which code to fail with."), ) -> None: """Emit progress for a while, then succeed or fail on purpose. A real diagnostic — "does streaming work end to end on this machine, can I tail it, does a failure survive a detached run?" — and the only command in reach slow enough to answer those by observation rather than argument. Every other verb finishes in milliseconds. """ for step, total in service.slow_work(seconds): console.event( f"step {step} of {total}", phase="selftest", progress=step / total, ) if fail: raise ReachError( f"selftest failed on purpose after {seconds:g}s", fix="this command failed because --fail was passed; drop it to succeed", exit_code=exit_code, ) console.verdict(f"selftest: OK — {seconds:g}s of progress, no failures")