"""adia-ui-kit-factory — generated by scripts/build/harness-manifests.mjs. Do not edit."""
import os
from pathlib import Path

_HERE = os.path.dirname(os.path.abspath(__file__))

# --- ui-architect (ADR-0091 C6) --------------------------------------------
# Generated /ui-architect Hermes command, implementing the portable ui-architect
# workflow (skills/ui-architect/SKILL.md) through delegate_task. Never
# hand-edit this block — regenerate via scripts/build/harness-manifests.mjs.
# The skill body is read from disk at COMMAND-INVOCATION time, never copied
# into this file, so SKILL.md stays the single authored copy (SPEC REQ-001).
import json as _ui_architect_json
import re as _ui_architect_re
import subprocess as _ui_architect_subprocess

_UI_ARCHITECT_MAX_LAPS = 4

_UI_ARCHITECT_ORIENTATION_TEMPLATE = "\n".join([
    "Rendering mode:  SPA | SSR | hybrid                            — signal: <file/dep/marker or words>",
    "Project shape:   single-surface | rollup | shared-foundation   — signal: <…>",
    "Shell:           admin | chat | editor | simple | embed | none — signal: <…>",
    "Task:            <task>                                        — signal: <the request>",
    "→ Route:         <skill(s)>, per the task table",
    "Verify target:   <what the executor produces to call this done>",
    "Open questions:  <unresolved axes, each with its named fallback; blank if none>",
])

_UI_ARCHITECT_BUILD_TEMPLATE = "\n".join([
    "BuildResult",
    "surface:         <screen/task identifier>",
    "orientationRef:  <the OrientationRecord this build executed>",
    "filesChanged:    <files written/edited, one per line or comma-list>",
    "gatesRun:        <builder self-checks and their pass/fail — adia-lint, validate_schema, check_anti_patterns, etc.>",
    "evidence:        <what was run/observed — probe output paths, screenshots, validator logs>",
    "selfCheck:       pass | fail | UNMEASURED — <reason>   (NEVER a ship/hold verdict)",
    'openIssues:      <unresolved items, or "none">',
])

_UI_ARCHITECT_VERIFY_TEMPLATE = "\n".join([
    "url:            <the probed page>",
    "consoleErrors:  pass | fail | UNMEASURED — <each error verbatim; empty = pass; UNMEASURED carries the reason>",
    "boundingBoxes:  pass | fail — <selector: w×h per key element; any 0×0 = fail>",
    "screenshot:     <path> @ deviceScaleFactor 2",
    'imageRead:      <what the pixels actually show — REQUIRED prose, never "looks fine">',
    "perf:           <navigation timing>ms vs <budget>ms — ADVISORY, never gates | UNMEASURED — <reason>",
    "a11y:           pass | fail | UNMEASURED — region role/label · overlays · heading roles · keyboard path · AA contrast",
    "structure:      adia-lint clean on every written file | <findings>",
    "verdict:        ship | hold — <one line naming the blocker if hold>",
])

def _ui_architect_skill_body():
    path = os.path.join(_HERE, "skills", "ui-architect", "SKILL.md")
    with open(path, "r", encoding="utf-8") as f:
        raw = f.read()
    m = _ui_architect_re.match(r"^---\n[\s\S]*?\n---\n?([\s\S]*)$", raw)
    return (m.group(1) if m else raw).strip()

def _ui_architect_run_linter(linter_name, text):
    linter_path = os.path.join(_HERE, "scripts", linter_name)
    proc = _ui_architect_subprocess.run([linter_path, "-"], input=text, capture_output=True, text=True)
    return proc.returncode == 0, (proc.stdout + proc.stderr).strip()

def _ui_architect_delegate(ctx, goal, context_text):
    raw = ctx.dispatch_tool("delegate_task", {"goal": goal, "context": context_text, "role": "leaf"})
    try:
        data = _ui_architect_json.loads(raw)
    except Exception:
        return "", "error"
    results = data.get("results") or []
    if not results:
        return "", "error"
    return results[0].get("summary") or "", results[0].get("status") or "error"

def _ui_architect_parse_gear(text):
    m = _ui_architect_re.search(r"^Gear:\s*([12])", text, _ui_architect_re.M | _ui_architect_re.I)
    return 2 if m and m.group(1) == "2" else 1

def _ui_architect_parse_waves(text):
    m = _ui_architect_re.search(r"^##\s*Waves\s*\n(.*?)(?:\n##|\n---|\Z)", text, _ui_architect_re.M | _ui_architect_re.S | _ui_architect_re.I)
    if not m:
        return ["the deliverable"]
    waves = [_ui_architect_re.sub(r"^[-*]\s*", "", w).strip() for w in m.group(1).splitlines()]
    waves = [w for w in waves if w]
    return waves or ["the deliverable"]

def _ui_architect_parse_verdict(text):
    m = _ui_architect_re.search(r"^verdict:\s*(ship|hold)\b", text, _ui_architect_re.M | _ui_architect_re.I)
    return m.group(1).lower() if m else "unknown"

def _ui_architect_planning_prompt(skill_body):
    parts = [
        skill_body,
        "---",
        "You are running the PLANNING pass of the ui-architect workflow above, in an isolated context",
        "(a separate delegate_task child with no memory of any other pass). Apply Gear selection to",
        "the goal given to you.",
        "",
        "Your final answer MUST start with a line 'Gear: 1' or 'Gear: 2', followed by exactly one",
        "app-planning OrientationRecord in EXACTLY this flat label: value line shape — no markdown",
        "headings, no table, no extra prose around it:",
        "",
        _UI_ARCHITECT_ORIENTATION_TEMPLATE,
        "",
        "If Gear 2 (a PRD/multi-surface brief), also include a '## Waves' heading with one",
        "'- <surface name>' line per surface — omit that heading entirely for Gear 1. Emit nothing else.",
    ]
    return "\n".join(parts)

def _ui_architect_composition_prompt(skill_body):
    parts = [
        skill_body,
        "---",
        "You are running the COMPOSITION pass of the ui-architect workflow above, in an isolated",
        "context, downstream of an OrientationRecord given to you as INPUT SIGNAL below — re-derive",
        "from it, never adopt it uninspected. Build the surface it describes.",
        "",
        "Your final answer MUST be exactly one BuildResult record in EXACTLY this flat label: value",
        "line shape — no markdown headings, no table, no extra prose around it — never a ship/hold",
        "verdict, that field is VerifyProof-exclusive:",
        "",
        _UI_ARCHITECT_BUILD_TEMPLATE,
        "",
        "Emit nothing else.",
    ]
    return "\n".join(parts)

def _ui_architect_qa_prompt(skill_body):
    parts = [
        skill_body,
        "---",
        "You are running the QA pass of the ui-architect workflow above, in an isolated context,",
        "independent of and downstream from the BuildResult given to you as INPUT SIGNAL below. You",
        "did not write this code — verify it fresh; never self-certify the builder's own report.",
        "",
        "Your final answer MUST be exactly one VerifyProof record in EXACTLY this flat label: value",
        "line shape — no markdown headings, no table, no extra prose around it, carrying the",
        "ship/hold verdict:",
        "",
        _UI_ARCHITECT_VERIFY_TEMPLATE,
        "",
        "Emit nothing else.",
    ]
    return "\n".join(parts)

def _ui_architect_run_wave(ctx, skill_body, top_orientation, wave, max_laps, log):
    findings = []
    last_verify = ""
    last_build = ""
    lap = 0
    while lap < max_laps:
        lap += 1
        log("  [%s] lap %d/%d — planning" % (wave, lap, max_laps))
        if lap == 1:
            plan_task = "Wave: %s\n\nTop-level OrientationRecord (INPUT SIGNAL):\n%s" % (wave, top_orientation)
        else:
            plan_task = "Wave: %s\n\nPrior VerifyProof findings to re-plan against (INPUT SIGNAL):\n%s" % (wave, last_verify)
        plan_out, _plan_status = _ui_architect_delegate(ctx, plan_task, _ui_architect_planning_prompt(skill_body))
        ok, lint_out = _ui_architect_run_linter("record-lint", plan_out)
        if not ok:
            findings.append("[%s] lap %d planning record-lint findings:\n%s" % (wave, lap, lint_out))

        log("  [%s] lap %d — composition" % (wave, lap))
        build_task = "Wave: %s\n\nOrientationRecord (INPUT SIGNAL):\n%s" % (wave, plan_out)
        build_out, _build_status = _ui_architect_delegate(ctx, build_task, _ui_architect_composition_prompt(skill_body))
        last_build = build_out
        ok, lint_out = _ui_architect_run_linter("build-result-lint", build_out)
        if not ok:
            findings.append("[%s] lap %d build-result-lint findings:\n%s" % (wave, lap, lint_out))

        log("  [%s] lap %d — QA" % (wave, lap))
        verify_task = "Wave: %s\n\nBuildResult (INPUT SIGNAL):\n%s" % (wave, build_out)
        verify_out, _verify_status = _ui_architect_delegate(ctx, verify_task, _ui_architect_qa_prompt(skill_body))
        last_verify = verify_out
        ok, lint_out = _ui_architect_run_linter("verify-proof-lint", verify_out)
        if not ok:
            findings.append("[%s] lap %d verify-proof-lint findings:\n%s" % (wave, lap, lint_out))

        verdict = _ui_architect_parse_verdict(verify_out)
        if max_laps == 1:
            return {"wave": wave, "laps": lap, "verdict": verdict, "verifyProof": last_verify, "buildResult": last_build, "findings": findings}
        if verdict == "ship":
            return {"wave": wave, "laps": lap, "verdict": verdict, "verifyProof": last_verify, "buildResult": last_build, "findings": findings}
        if lap >= max_laps:
            findings.append("[%s] hit the %d-lap cap without a ship verdict — escalating, not re-running blind." % (wave, max_laps))
            return {"wave": wave, "laps": lap, "verdict": "escalated", "verifyProof": last_verify, "buildResult": last_build, "findings": findings}
    return {"wave": wave, "laps": max_laps, "verdict": "escalated", "verifyProof": last_verify, "buildResult": last_build, "findings": findings}

def _ui_architect_command(raw_args, ctx):
    brief = (raw_args or "").strip()
    lines_out = []
    log = lambda line: lines_out.append(line)
    if not brief:
        return "ui-architect: no brief given. Usage: /ui-architect <brief, or a path to a PRD>"
    if not hasattr(ctx, "dispatch_tool"):
        return "ui-architect: no delegate_task-capable ctx available — cannot dispatch isolated passes."
    skill_body = _ui_architect_skill_body()
    log("ui-architect: dispatching an isolated PLANNING pass to size the brief (Gear selection)...")
    initial_out, _status = _ui_architect_delegate(ctx, brief, _ui_architect_planning_prompt(skill_body))
    ok, lint_out = _ui_architect_run_linter("record-lint", initial_out)
    gear = _ui_architect_parse_gear(initial_out)
    waves = _ui_architect_parse_waves(initial_out) if gear == 2 else ["the deliverable"]
    max_laps = _UI_ARCHITECT_MAX_LAPS if gear == 2 else 1
    log("ui-architect: GEAR %d — %d wave(s): %s" % (gear, len(waves), ", ".join(waves)))
    if not ok:
        log("ui-architect: initial OrientationRecord failed record-lint:\n%s" % lint_out)
    outcomes = [_ui_architect_run_wave(ctx, skill_body, initial_out, wave, max_laps, log) for wave in waves]
    shipped = sum(1 for o in outcomes if o["verdict"] == "ship")
    escalated = [o for o in outcomes if o["verdict"] == "escalated"]
    header = "ui-architect — GEAR %d — %d/%d wave(s) shipped" % (gear, shipped, len(outcomes))
    if escalated:
        header += ", %d escalated" % len(escalated)
    lines_out.append(header)
    lines_out.append("")
    for o in outcomes:
        lap_word = "lap" if o["laps"] == 1 else "laps"
        lines_out.append("## %s — %s (%d %s)" % (o["wave"], o["verdict"], o["laps"], lap_word))
        lines_out.append(o["verifyProof"] or "(no VerifyProof produced)")
        if o["findings"]:
            lines_out.append("Findings:")
            for f in o["findings"]:
                lines_out.append("  - %s" % f)
        lines_out.append("")
    return "\n".join(lines_out)

def _ui_architect_command_handler(_ctx_closure):
    def _handler(raw_args):
        return _ui_architect_command(raw_args, _ctx_closure)
    return _handler


def register(ctx):
    ctx.register_skill(
        name="app-audit",
        path=Path(os.path.join(_HERE, "skills", "app-audit", "SKILL.md")),
        description="Diagnose an EXISTING AdiaUI consumer codebase before touching it — recon, classify manifest/version/spec/capability drift, root-cause a DRIFT-caused wrong-output symptom via four-layer triage (skill/codebase/substrate/spec) instead of patching the surface. Use for \"audit this UI\", \"is this up to date\", \"what should we migrate\", \"doesn't match the reference\", \"looks unstyled/off-brand\", or a suspected-drifted @adia-ai/* consumer's version health check. Produces a ranked, evidence-cited report; hands CONFIRMED sweeps to a builder. NOT greenfield planning (app-planning) or confirmed migration (app-migration); NOT a live blank-screen/console-error check (surface-qa) or chart-specific render behavior (chart-selection); NOT a duplication review (project-scaffolding).",
    )
    ctx.register_skill(
        name="app-migration",
        path=Path(os.path.join(_HERE, "skills", "app-migration", "SKILL.md")),
        description="Migrates a consumer adia-ui app. Use when asked to \"migrate to v0.X\", \"upgrade @adia-ai/web-components\", \"fix breaking changes\", \"sweep deprecated attributes\", port @agent-ui-kit/foreign code, or change SPA↔SSR mode — grep audit, mechanical sweep, verify gates. NOT for authoring the MIGRATION GUIDE or cutting releases (package-release, forge plugin).",
    )
    ctx.register_skill(
        name="app-planning",
        path=Path(os.path.join(_HERE, "skills", "app-planning", "SKILL.md")),
        description="Cold-start router for adia-ui consumer-app work. Use when the user asks to \"build/start an adia-ui app\", \"add a surface\", \"orient in this repo\" — run FIRST, also on any task whose mode/shape/shell is undecided — classifies four axes on cited signals, emits an Orientation Record, routes onward. NOT for framework-monorepo internals (adia-ui-forge).",
    )
    ctx.register_skill(
        name="chart-selection",
        path=Path(os.path.join(_HERE, "skills", "chart-selection", "SKILL.md")),
        description="Which adia-ui component renders a chart, graph, sparkline, gauge, or heatmap, and how to wire its data/legend/theming. Use for \"add a chart\", \"show a graph\", \"visualize this data\", \"add a sparkline/gauge/heatmap\", or \"wire a chart legend\". NOT for the surrounding screen (screen-composition), color tokens (token-selection), or data fetching (data-wiring).",
    )
    ctx.register_skill(
        name="data-wiring",
        path=Path(os.path.join(_HERE, "skills", "data-wiring", "SKILL.md")),
        description="Data, state & hydration in an adia-ui app. Use for \"wire up the data\" / \"manage state\" / \"hydrate the island\": pattern choice (signals · shared app store · Service/Command · DataClient · property-API · data-*), hydration per mode (SPA/SSR/hybrid). NOT for host bootstrap/registration (host-wiring) or screen markup (screen-composition).",
    )
    ctx.register_skill(
        name="domain-planning",
        path=Path(os.path.join(_HERE, "skills", "domain-planning", "SKILL.md")),
        description="Reasons through a PRD, spec, mockup, schema, or role/user-story BEFORE any UI is chosen — resolves intent, domain entities, roles, tasks, and decisions, then scores a semantic wireframe against the gate dimensions. Use when the input is spec-shaped (not a signed-off wireframe) and no Domain Plan exists yet for it. Preloaded by app-planning-agent; produces the Orientation Record's Domain Plan block. NOT for composing the UI itself (screen-composition) or classifying rendering mode/shape/shell (app-planning).",
    )
    ctx.register_skill(
        name="find-unused",
        path=Path(os.path.join(_HERE, "skills", "find-unused", "SKILL.md")),
        description="Finds what a non-breaking @adia-ai upgrade shipped that this app never picked up — the opt-in layers nothing imports, the local workarounds a fixed bug made redundant, retired enum values still sitting in stored state, and the fixes that never reached MIGRATION.md. Use after \"we bumped and nothing broke\", \"what are we missing from 0.8.x\", \"are we actually using what we ship\", \"why is [scale]/[theme] doing nothing\", or when a PATCH span needs adoption rather than repair. NOT for breaking-change repair (app-migration); NOT for a first-time install (adia-scaffold); NOT for diagnosing a broken surface (app-audit); NOT for CSS-only redundancy in a theme file (theme-audit — the CSS-side sibling).",
    )
    ctx.register_skill(
        name="gen-ui-wiring",
        path=Path(os.path.join(_HERE, "skills", "gen-ui-wiring", "SKILL.md")),
        description="Authors a runtime generative-UI experience on the a2ui runtime — mounts a2ui-root/gen-root, wires generate_ui + data resolvers, grounds generation in a corpus (harvest chunks from our own pages, point retrieval at it). Use when END USERS generate UI at runtime. NOT for one-shot 'generate UI for X' screen asks (screen-composition), chat features (llm-wiring), or pipeline/MCP tool ops (adia-forge's a2ui-maintenance).",
    )
    ctx.register_skill(
        name="host-wiring",
        path=Path(os.path.join(_HERE, "skills", "host-wiring", "SKILL.md")),
        description="Wires an adia-ui app's host — picks SPA/SSR/hybrid, then that mode's registration, CSS cascade, routing ownership. Use for \"wire the host\", \"set up index.html\", unstyled or non-upgrading elements, \"HTMLElement is not defined\" under Next/Nuxt/SvelteKit/Astro. NOT for screen UI (screen-composition), data/state (data-wiring), app layout (project-scaffolding).",
    )
    ctx.register_skill(
        name="llm-wiring",
        path=Path(os.path.join(_HERE, "skills", "llm-wiring", "SKILL.md")),
        description="The @adia-ai/llm client contract — chat/streamChat streaming, StreamChunk, smart-proxy vs passthrough key security, chat-shell wiring. Use when adding a chat box or any LLM feature to an adia-ui app. NOT for runtime gen-UI (gen-ui-wiring), one-shot intent→screen composition (screen-composition), or @adia-ai/llm internals (adia-forge's llm-client-maintenance).",
    )
    ctx.register_skill(
        name="pattern-catalog",
        path=Path(os.path.join(_HERE, "skills", "pattern-catalog", "SKILL.md")),
        description="Index of adia-ui's pre-assembled surfaces — hundreds of patterns and template screens (auth, registration, onboarding, settings, dashboards) — see references/pattern-index.md for the current count. Use BEFORE composing any screen from primitives, or when asked \"is there an existing pattern/template for X\", \"start from a pattern\", \"what patterns exist\". Answers and points at source — NOT for composing new UI (screen-composition), shell chrome (shell-selection), or authoring new patterns (primitive-authoring).",
    )
    ctx.register_skill(
        name="project-scaffolding",
        path=Path(os.path.join(_HERE, "skills", "project-scaffolding", "SKILL.md")),
        description="Lays out an adia-ui app's on-disk structure — picks the project shape (single-surface / rollup / shared-foundation) and page form, scaffolds via scripts/adia-scaffold, gates on the structure rubric. Use for \"scaffold an app\", \"add a page/surface/component\" WHEN mode/shape are already decided, \"audit its structure\". If mode/shape/shell are still undecided, app-planning classifies first. NOT for the UI inside a screen (screen-composition) or host wiring (host-wiring).",
    )
    ctx.register_skill(
        name="screen-composition",
        path=Path(os.path.join(_HERE, "skills", "screen-composition", "SKILL.md")),
        description="Composes adia-ui screens from light-DOM catalog primitives — discovers tags/props via the a2ui MCP, themes via --a-* tokens. Use when asked to build or 'generate UI for' a screen, page, form, dashboard, or nav pattern, or when a PRD/spec/mockup needs UI. NOT for shell chrome (shell-selection), host wiring (host-wiring), runtime gen-UI (gen-ui-wiring).",
    )
    ctx.register_skill(
        name="shell-selection",
        path=Path(os.path.join(_HERE, "skills", "shell-selection", "SKILL.md")),
        description="Picks and composes an adia-ui page-chrome shell (@adia-ai/web-modules): admin (app frame), chat (LLM), editor (canvas+panes), simple (marketing/error), or embed. Use when asked to \"use a shell\", \"sidebar + topbar layout\", \"embed this surface\", or on shell markup debugging. NOT for screens inside it (screen-composition) or host/SSR wiring (host-wiring).",
    )
    ctx.register_skill(
        name="surface-qa",
        path=Path(os.path.join(_HERE, "skills", "surface-qa", "SKILL.md")),
        description="Browser-QA gate for a CONSUMER app's adia-ui surfaces — renders headless with zero console/page errors, non-zero bounding boxes, and a screenshot actually read, plus AdiaUI a11y checks. Use when shipping a surface, on \"verify/QA this page\" or a page that renders blank/empty, or when \"tests pass\" is the only evidence. NOT for composing/fixing UI (screen-composition), structural lint (adia-lint hook), or the framework repo's own dogfood/ demo-page sweep (forge's demo-audit).",
    )
    ctx.register_skill(
        name="table-composition",
        path=Path(os.path.join(_HERE, "skills", "table-composition", "SKILL.md")),
        description="Answers how to display/organize tabular data with table-ui: contained vs uncontained chrome, [raw] (consumer-owned body, a separate axis), opt-in striped rows, and resize/sort defaults that flip between JS .columns and declarative col-def forms, plus inline-edit-grid and tree/hierarchical-row patterns. Use for \"how do I show a table\", \"add sorting/filtering\", \"make this table striped\", \"columns aren't resizable\", \"card vs bare table\", \"editable/spreadsheet grid\", \"tree table / nested rows\", \"huge list of rows\". NOT for composing the surrounding screen (screen-composition), data wiring (data-wiring), OTHER non-table patterns (pattern-catalog), or 1000+-row virtualized lists (list-window-ui).",
    )
    ctx.register_skill(
        name="theme-audit",
        path=Path(os.path.join(_HERE, "skills", "theme-audit", "SKILL.md")),
        description="Classifies a consumer app's theme.css against what the adia-ui framework already ships, restated defaults, re-derived tokens, dead selectors, and hand-built component work. Runs `adia-theme-audit` against a theme file + app root; audits and reports, never rewrites. Use when a theme.css is suspected of restating the kit, after bumping `@adia-ai/web-components`, or before a `find-unused` sweep. NOT for rendering/grading a surface (surface-qa); NOT for picking a token going forward (token-selection); NOT for JS/markup an upgrade left unused (find-unused, the CSS-side sibling); NOT for the framework's OWN token layer in packages/web-components (a capability this skill's own body also references, not yet a shipped skill in either plugin, ticket 10036).",
    )
    ctx.register_skill(
        name="token-selection",
        path=Path(os.path.join(_HERE, "skills", "token-selection", "SKILL.md")),
        description="Answers which color token/role an adia-ui surface should use — role grammar, pairing laws, state families, the --a-* alias layer. Use when asked \"which token for this background/text/hover/border\" or \"--a-* or --md-sys-color-*\". ANSWERS only. NOT for composing the screen (screen-composition) or designing/verifying palettes (framework-side).",
    )
    ctx.register_skill(
        name="ui-architect",
        path=Path(os.path.join(_HERE, "skills", "ui-architect", "SKILL.md")),
        description="Whole-deliverable coordinator: runs the app-planning → screen-composition → surface-qa workflow for one entire multi-surface app or feature — gear selection, wave decomposition, generator-≠-reviewer separation, the four-lap plan/build/QA cap per wave, failure routing, and the closing VerifyProof. Portable across runtimes — permits native multi-agent delegation where the installed runtime provides it, and states the serial single-context fallback otherwise. Use on an end-to-end delivery ask: \"make an app that...\", \"coordinate everything in this PRD and open the PRs\", \"take this spec and ship the whole thing\". NOT for a lone classify/plan ask with nothing to deliver yet (app-planning keeps that territory entirely); NOT for one already-scoped screen (screen-composition); NOT for grading an existing surface (surface-qa).",
    )
    ctx.register_skill(
        name="wave-coordination",
        path=Path(os.path.join(_HERE, "skills", "wave-coordination", "SKILL.md")),
        description="Team-pattern mechanics for a multi-screen build under ui-architect's GEAR 2 — who merges parallel screen-composition-agent branches and when, PR/branch mechanics, shared-file conflict rules for shared-foundation shapes, and how to size a wave. Use when planning or running a GEAR-2 dispatch: \"how do two parallel screen-composition-agent branches come back together\", \"who merges\", \"how big should a wave be\", \"what happens when two screens touch the same shared file\". NOT for picking a project's shape (project-scaffolding, which this skill's conflict rules build on) or composing one screen (screen-composition).",
    )
    ctx.register_command(
        "ui-architect",
        _ui_architect_command_handler(ctx),
        description="Whole-deliverable coordinator: runs the app-planning → screen-composition → surface-qa workflow for one entire multi-surface app or feature — gear selection, wave decomposition, generator-≠-reviewer separation, the four-lap plan/build/QA cap per wave, failure routing, and the closing VerifyProof. Portable across runtimes — permits native multi-agent delegation where the installed runtime provides it, and states the serial single-context fallback otherwise. Use on an end-to-end delivery ask: \"make an app that...\", \"coordinate everything in this PRD and open the PRs\", \"take this spec and ship the whole thing\". NOT for a lone classify/plan ask with nothing to deliver yet (app-planning keeps that territory entirely); NOT for one already-scoped screen (screen-composition); NOT for grading an existing surface (surface-qa).",
        args_hint="<brief, or a path to a PRD>",
    )
