// SPEC: PJ2026-01060307 控制面模块化 draft-2026-06-25-p0. entry module for scripts/src/agentrun.ts.

// Moved mechanically from scripts/src/agentrun.ts:1-302 for #903.

// SPEC: PJ2026-01020108 cancel lifecycle + PJ2026-01020205 AipodSpec binding + PJ2026-01020302 session policy + PJ2026-01020305 cancel control + PJ2026-01060305/06 YAML execution policy and bounded output draft-2026-06-25-p0.
// Exposes AgentRun lane-scoped policy, AipodSpec SecretRef binding, cancel lifecycle, and bounded default output in the UniDesk CLI.
import { chmodSync, copyFileSync, existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { spawnSync } from "node:child_process";
import { rootPath, type UniDeskConfig } from "../config";
import type { RenderedCliResult } from "../output";
import { applyLocalCaddyManagedSite } from "../pk01-caddy";
import { runSshCommandCapture, type SshCaptureResult } from "../ssh";
import { runRemoteSshCommandCapture } from "../remote";
import { startJob } from "../jobs";
import {
  AGENTRUN_CONFIG_PATH,
  agentRunLaneSummary,
  agentRunPipelineRunName,
  agentRunProviderCredentialRefs,
  resolveAgentRunLaneTarget,
  type AgentRunCancelLifecycleSpec,
  type AgentRunLaneSpec,
} from "../agentrun-lanes";
import {
  agentRunImageArtifact,
  placeholderAgentRunImage,
  renderedFilesDigest,
  renderedObjectsDigest,
  renderAgentRunControlPlaneManifests,
  renderAgentRunGitopsFiles,
  type AgentRunArtifactService,
} from "../agentrun-manifests";
import { sha256Fingerprint } from "../platform-infra-ops-library";
import { decideCicdDeliveryMutation, resolveCicdDeliveryAuthority } from "../cicd-delivery-authority";

import type { AgentRunResourceVerb, AgentRunRestCompatGroup } from "./utils";
import { controlPlaneApply, controlPlanePlan, parseCleanupReleasedPvOptions, parseCleanupRunnersOptions, parseCleanupRunsOptions, parseCleanupSessionPvcsOptions, parseConfirmOptions, parseGitMirrorOptions, parseLaneConfirmOptions, parseRefreshOptions, parseSecretSyncOptions, status } from "./control-plane";
import { gitMirrorStatus } from "./git-mirror";
import { agentRunNativeDevelopmentHelp, runAgentRunNativeDevelopmentCommand } from "./native-development";
import { agentRunExplain, isRecord, parseGitMirrorStatusOptions, parseStatusOptions, parseTriggerOptions } from "./options";
import { renderAgentRunControlPlaneActionSummary, renderAgentRunControlPlanePlanSummary, renderAgentRunControlPlaneStatusSummary } from "./public-exposure";
import { providerProfileHelp, runProviderProfileCommand } from "./provider-profile";
import { renderedCliResult } from "./render";
import { AGENTRUN_RESOURCE_TRANSPORT_SCOPE, agentRunGetKindHelp, runAgentRunResourceCommand } from "./resource-actions";
import { runAgentRunRestCompatCommand, runGitMirrorJob, startAsyncAgentRunJob } from "./rest-bridge";
import { renderAgentRunSecretSyncResult } from "./secret-sync-output";
import { exposeAgentRun, restartYamlLane, secretSync, triggerCurrent } from "./trigger";
import { unsupported } from "./utils";
import { cleanupLocalPostgres, cleanupReleasedPvs, cleanupRunners, cleanupRuns, cleanupSessionPvcs, refresh } from "./yaml-lane";

export function agentRunHelp(): unknown {
  return {
    command: "agentrun get|describe|events|logs|result|ack|cancel|retry|dispatch|create|apply|send|explain",
    output: "human by default; use -o json|yaml or --raw for machine/debug output",
    usage: [
      "bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
      "bun scripts/cli.ts agentrun describe run/<runId> --node NC01 --lane nc01-v02",
      "bun scripts/cli.ts agentrun get tasks -o wide",
      "bun scripts/cli.ts agentrun get tasks -o json",
      "bun scripts/cli.ts agentrun describe \"修复 HWLAB 的 cicd\"",
      "bun scripts/cli.ts agentrun describe task/<taskId> --input -o json",
      "bun scripts/cli.ts agentrun events \"修复 HWLAB 的 cicd\" --after-seq 0 --expect 10 --timeout 120s --limit 100",
      "bun scripts/cli.ts agentrun events run/<runId> --detail-seq <seq>",
      "bun scripts/cli.ts agentrun logs \"修复 HWLAB 的 cicd\" --tail 100",
      "bun scripts/cli.ts agentrun result \"修复 HWLAB 的 cicd\"",
      "bun scripts/cli.ts agentrun ack task/<taskId> --reader-id cli",
      "bun scripts/cli.ts agentrun cancel task/<taskId> --reason <text> --dry-run",
      "bun scripts/cli.ts agentrun retry task/<taskId> --idempotency-key <key> --reason <text> --dry-run",
      "bun scripts/cli.ts agentrun get attempts --task <taskId> --limit 20",
      "bun scripts/cli.ts agentrun dispatch task/<taskId>",
      "bun scripts/cli.ts agentrun create task --aipod Artificer --title \"修复 HWLAB 的 cicd\" --prompt-stdin --idempotency-key <key>",
      "bun scripts/cli.ts agentrun create task --aipod Artificer --title \"修复 HWLAB 的 cicd\" --target <Target> --target-workspace <absolute-task-worktree> --repo <owner/repo> --ref <branch> --mdtodo-id <opaque-task-reference> --prompt-stdin [--dry-run]",
      "bun scripts/cli.ts agentrun apply -f - --dry-run",
      "bun scripts/cli.ts agentrun send session/<sessionId> --aipod Artificer --prompt-stdin",
      "bun scripts/cli.ts agentrun explain task",
      "bun scripts/cli.ts agentrun explain session-policy",
      "bun scripts/cli.ts agentrun native-development manager start|stop|restart|status|logs",
      "bun scripts/cli.ts agentrun control-plane plan --node NC01 --lane nc01-v02",
      "bun scripts/cli.ts agentrun control-plane status --node NC01 --lane nc01-v02",
      "bun scripts/cli.ts platform-infra pipelines-as-code history --target NC01 --consumer agentrun-nc01-v02 --limit 10",
      "bun scripts/cli.ts agentrun control-plane platform-maintenance --help",
      "bun scripts/cli.ts agentrun control-plane legacy-cicd --help",
      "bun scripts/cli.ts agentrun control-plane status",
      "bun scripts/cli.ts agentrun control-plane status --full",
      "bun scripts/cli.ts agentrun control-plane status --pipeline-run <yaml-lane-pipelinerun>",
      "bun scripts/cli.ts agentrun control-plane status --source-commit <full-sha>",
      "bun scripts/cli.ts agentrun control-plane cleanup-runners --node NC01 --lane nc01-v02 --dry-run",
      "bun scripts/cli.ts agentrun control-plane cleanup-runners --node NC01 --lane nc01-v02 --confirm",
      "bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit 200 --dry-run",
      "bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit 200 --confirm",
      "bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit 200 --dry-run",
      "bun scripts/cli.ts agentrun control-plane cleanup-released-pvs --limit 200 --confirm",
      "bun scripts/cli.ts agentrun control-plane cleanup-local-postgres --node NC01 --lane nc01-v02 --dry-run",
      "bun scripts/cli.ts agentrun control-plane cleanup-local-postgres --node NC01 --lane nc01-v02 --confirm",
      "bun scripts/cli.ts agentrun provider-profile plan --node NC01 --lane nc01-v02 --profile gpt.pika",
      "bun scripts/cli.ts agentrun provider-profile apply --node NC01 --lane nc01-v02 --profile gpt.pika --confirm",
      "bun scripts/cli.ts agentrun provider-profile status --node NC01 --lane nc01-v02 --profile gpt.pika",
      "bun scripts/cli.ts agentrun provider-profile validate --node NC01 --lane nc01-v02 --profile gpt.pika --wait",
      "bun scripts/cli.ts agentrun git-mirror status",
      "bun scripts/cli.ts agentrun git-mirror status --full",
      "bun scripts/cli.ts agentrun git-mirror legacy-ops --help",
    ],
    resources: ["task/qt", "attempt", "run", "command/cmd", "runnerjob/rjob", "session/ses", "aipodspec/aps"],
    description: "Operate AgentRun through Kubernetes-style resource verbs. Human output is compact by default; -o json|yaml returns the UniDesk render-only client schema, --raw exposes the REST envelope, and target-trans uses the selected Target k3s service proxy plus a host directory probe for Artificer target tasks.",
    legacyCompatibility: "queue/runs/commands/runner/sessions/aipod-specs remain compatibility groups; new commander work should use get/describe/events/logs/result/ack/cancel/retry/dispatch/create/apply/send. sessions turn/steer are removed; use send only.",
    cicdBoundary: "NC01 PaC consumer 的 PR merge 只更新 source authority；发布必须先 release plan，再由 CLI 手动发送 PaC webhook。legacy 与平台维护写入口只在显式 scoped help 中展示。",
  };
}

export async function runAgentRunCommand(config: UniDeskConfig | null, args: string[]): Promise<Record<string, unknown> | RenderedCliResult> {
  const route = normalizeAgentRunCommandArgs(args);
  const { group, action, actionArgs } = route;
  if (group === undefined || isHelpArg(group)) return renderAgentRunHelp(route.canonicalArgs);
  if (group === "native-development" && (isHelpArg(action) || actionArgs.some(isHelpArg))) return agentRunNativeDevelopmentHelp();
  if (isHelpArg(action) || actionArgs.some(isHelpArg)) return renderAgentRunHelp(route.canonicalArgs);
  if (isResourceVerb(group)) return await runAgentRunResourceCommand(config, group, action, actionArgs, route.canonicalArgs);
  if (isAgentRunRestCompatGroup(group)) {
    return await runAgentRunRestCompatCommand(config, group, route.forwardArgs, route.canonicalArgs);
  }
  if (group === "native-development") return runAgentRunNativeDevelopmentCommand(route.forwardArgs);
  if (config === null) throw new Error("agentrun control-plane and git-mirror commands require UniDesk config");
  if (group === "control-plane") {
    if (action === "plan") {
      const options = parseStatusOptions(actionArgs);
      const result = await controlPlanePlan(config, options);
      return options.full || options.raw ? result : renderAgentRunControlPlanePlanSummary(result);
    }
    if (action === "apply") return await controlPlaneApply(config, parseLaneConfirmOptions(actionArgs));
    if (action === "status") {
      const options = parseStatusOptions(actionArgs);
      const result = await status(config, options);
      return options.full || options.raw ? result : renderAgentRunControlPlaneStatusSummary(result);
    }
    if (action === "secret-sync") {
      const options = parseSecretSyncOptions(actionArgs);
      return renderAgentRunSecretSyncResult(await secretSync(config, options), options);
    }
    if (action === "restart") {
      const options = parseLaneConfirmOptions(actionArgs);
      const result = await restartYamlLane(config, options);
      return options.full || options.raw ? result : renderAgentRunControlPlaneActionSummary(result, "AGENTRUN CONTROL-PLANE RESTART");
    }
    if (action === "expose") return await exposeAgentRun(config, parseConfirmOptions(actionArgs));
    if (action === "trigger-current") {
      const options = parseTriggerOptions(actionArgs);
      const target = resolveAgentRunLaneTarget(options);
      const decision = agentRunDeliveryMutationDecision(target, "trigger-current");
      if (!decision.allowed) return decision.result;
      const result = await triggerCurrent(config, options);
      return options.full || options.raw || !isRecord(result.target) ? result : renderAgentRunControlPlaneActionSummary(result, "AGENTRUN TRIGGER CURRENT");
    }
    if (action === "refresh") {
      const options = parseRefreshOptions(actionArgs);
      const target = resolveAgentRunLaneTarget(options);
      const decision = agentRunDeliveryMutationDecision(target, "refresh");
      if (!decision.allowed) return decision.result;
      const result = await refresh(config, options);
      return options.full || options.raw ? result : renderAgentRunControlPlaneActionSummary(result, "AGENTRUN CONTROL-PLANE REFRESH");
    }
    if (action === "cleanup-runners") {
      const options = parseCleanupRunnersOptions(actionArgs);
      const result = await cleanupRunners(config, options);
      return options.full || options.raw ? result : renderAgentRunControlPlaneActionSummary(result, "AGENTRUN RUNNER CLEANUP");
    }
    if (action === "cleanup-runs") return await cleanupRuns(config, parseCleanupRunsOptions(actionArgs));
    if (action === "cleanup-session-pvcs") {
      return await cleanupSessionPvcs(config, parseCleanupSessionPvcsOptions(actionArgs));
    }
    if (action === "cleanup-local-postgres") return await cleanupLocalPostgres(config, parseLaneConfirmOptions(actionArgs));
    if (action === "cleanup-released-pvs") return await cleanupReleasedPvs(config, parseCleanupReleasedPvOptions(actionArgs));
  }
  if (group === "provider-profile") return await runProviderProfileCommand(config, action, actionArgs);
  if (group === "git-mirror") {
    if (action === "status") return await gitMirrorStatus(config, parseGitMirrorStatusOptions(actionArgs));
    if (action === "sync" || action === "flush") {
      const options = parseGitMirrorOptions(actionArgs);
      const target = resolveAgentRunLaneTarget(options);
      const { spec } = target;
      const decision = agentRunDeliveryMutationDecision(target, `git-mirror-${action}`);
      if (!decision.allowed) return decision.result;
      if (options.confirm && !options.wait) {
        return startAsyncAgentRunJob(
          `agentrun_${spec.lane}_git_mirror_${action}`,
          ["bun", "scripts/cli.ts", "agentrun", "git-mirror", action, "--node", spec.nodeId, "--lane", spec.lane, "--confirm", "--wait", "--timeout-seconds", String(options.timeoutSeconds)],
          `Run AgentRun ${spec.version} git mirror ${action} on ${spec.nodeId}`,
        );
      }
      return await runGitMirrorJob(config, action, options);
    }
  }
  return unsupported(route.canonicalArgs);
}

function agentRunDeliveryMutationDecision(
  target: ReturnType<typeof resolveAgentRunLaneTarget>,
  action: "trigger-current" | "refresh" | "git-mirror-sync" | "git-mirror-flush",
) {
  const authority = resolveCicdDeliveryAuthority({
    node: target.spec.nodeId,
    lane: target.spec.lane,
    sourceRepository: target.spec.source.repository,
    sourceBranch: target.spec.source.branch,
    declaredSourceAuthorityMode: target.spec.source.sourceAuthority?.mode ?? null,
    declaredConfigRef: target.configPath,
  });
  return decideCicdDeliveryMutation(authority, {
    command: action.startsWith("git-mirror-")
      ? `agentrun git-mirror ${action.slice("git-mirror-".length)}`
      : `agentrun control-plane ${action}`,
    statusCommand: `bun scripts/cli.ts agentrun control-plane status --node ${target.spec.nodeId} --lane ${target.spec.lane}`,
    action,
    node: target.spec.nodeId,
    lane: target.spec.lane,
  });
}

export function isAgentRunRestCompatGroup(group: string | undefined): group is AgentRunRestCompatGroup {
  return group === "queue" || group === "sessions" || group === "aipod-specs" || group === "aipods" || group === "runs" || group === "commands" || group === "runner";
}

export interface AgentRunCommandRoute {
  canonicalArgs: string[];
  group: string | undefined;
  action: string | undefined;
  actionArgs: string[];
  forwardArgs: string[];
}

export function normalizeAgentRunCommandArgs(args: string[]): AgentRunCommandRoute {
  const canonicalArgs = args[0] === "v01" ? args.slice(1) : args;
  const [group, action, ...actionArgs] = canonicalArgs;
  return {
    canonicalArgs,
    group,
    action,
    actionArgs,
    forwardArgs: canonicalArgs.slice(1),
  };
}

export function isHelpArg(value: string | undefined): boolean {
  return value === "help" || value === "--help" || value === "-h";
}

export function isResourceVerb(value: string | undefined): value is AgentRunResourceVerb {
  return value === "get"
    || value === "describe"
    || value === "events"
    || value === "logs"
    || value === "result"
    || value === "ack"
    || value === "cancel"
    || value === "retry"
    || value === "dispatch"
    || value === "create"
    || value === "apply"
    || value === "send"
    || value === "explain";
}

export function renderAgentRunHelp(args: string[]): RenderedCliResult {
  const text = agentRunHelpText(args);
  return renderedCliResult(true, "agentrun help", text);
}

export function agentRunHelpText(args: string[]): string {
  const [verb, kind] = args.filter((arg) => !isHelpArg(arg));
  if (verb === "get" && kind !== undefined) return agentRunGetKindHelp(kind);
  if (verb === "get") {
    return [
      `Usage: bun scripts/cli.ts agentrun get <resource> [options] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
      "",
      "Resources: tasks|attempts|sessions|runs|commands|runnerjobs|aipodspecs",
      "Output: table by default; use -o wide|name|json|yaml.",
      "",
      "Examples:",
      "  bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
      "  bun scripts/cli.ts agentrun get attempts --task <taskId> --limit 20",
      "  bun scripts/cli.ts agentrun get sessions --limit 20",
      "  bun scripts/cli.ts agentrun get tasks -o json",
    ].join("\n");
  }
  if (verb === "describe") {
    return [
      "Usage: bun scripts/cli.ts agentrun describe <kind/name> [--node <node> --lane <lane>] [--input] [--full] [-o json|yaml] [--raw]",
      "",
      "Kinds: task|run|command|runnerjob|session|aipodspec",
      "Examples:",
      "  bun scripts/cli.ts agentrun describe task/qt_...",
      "  bun scripts/cli.ts agentrun describe task/qt_... --input -o json",
      "  bun scripts/cli.ts agentrun describe run/<runId> --node NC01 --lane nc01-v02",
      "  bun scripts/cli.ts agentrun describe command/cmd_... --run <runId>",
      "  bun scripts/cli.ts agentrun describe session/<sessionId> --full",
    ].join("\n");
  }
  if (verb === "events") {
    return [
      `Usage: bun scripts/cli.ts agentrun events run/<runId> [--after-seq N] [--expect N [--timeout 120s]] [--limit 100] [-o json|yaml] [--full|--raw] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
      `       bun scripts/cli.ts agentrun events run/<runId> --detail-seq <seq> [-o json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
      `       bun scripts/cli.ts agentrun events run/<runId> --aggregate reuse [-o json|yaml] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`,
      "",
      "--expect waits in one manager-held request until N new events, target completion, or timeout; --timeout defaults to 120s. --limit remains an independent output budget.",
      "--detail-seq returns one bounded Secret-safe EventDetail projection. Use the separate --after-seq <seq-1> --limit 1 --full|--raw path only for explicit complete disclosure.",
      "--aggregate reuse automatically reads bounded pages and reports one-run/one-runner multi-turn reuse without raw event disclosure.",
    ].join("\n");
  }
  if (verb === "logs") {
    return `Usage: bun scripts/cli.ts agentrun logs session/<sessionId> [--tail 100|--after-seq N] [--limit 100] [--full-text] [-o json|yaml] [--raw] ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
  }
  if (verb === "result") {
    return `Usage: bun scripts/cli.ts agentrun result run/<runId> --command <commandId> ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}\n       bun scripts/cli.ts agentrun result command/<commandId> --run <runId> ${AGENTRUN_RESOURCE_TRANSPORT_SCOPE}`;
  }
  if (verb === "ack") {
    return "Usage: bun scripts/cli.ts agentrun ack task/<taskId>|session/<sessionId> [--reader-id cli]";
  }
  if (verb === "cancel") {
    return "Usage: bun scripts/cli.ts agentrun cancel task/<taskId>|session/<sessionId>|run/<runId>|command/<commandId> --reason <text> [--run <runId>] [--dry-run]";
  }
  if (verb === "retry") {
    return "Usage: bun scripts/cli.ts agentrun retry task/<taskId> --idempotency-key <key> --reason <text> [--dry-run] [--full] [-o json|yaml] [--raw]";
  }
  if (verb === "dispatch") {
    return "Usage: bun scripts/cli.ts agentrun dispatch task/<taskId>";
  }
  if (verb === "create") {
    return "Usage: bun scripts/cli.ts agentrun create task --aipod Artificer --title <中文短标题> --target <Target> --target-workspace <task-worktree> --repo <owner/repo> --ref <branch> --mdtodo-id <opaque-task-reference> --prompt-stdin [--idempotency-key <key>] [--dry-run]";
  }
  if (verb === "apply") {
    return "Usage: bun scripts/cli.ts agentrun apply -f task.yaml|json|- [--dry-run]\nTask manifests use kind: Task and spec: <AgentRun task payload>.";
  }
  if (verb === "send") {
    return "Usage: bun scripts/cli.ts agentrun send session/<sessionId> --aipod Artificer --prompt-stdin\nThe server decides whether this becomes an internal steer or a new turn from session state.";
  }
  if (verb === "explain") return agentRunExplain(kind ?? "task");
  if (verb === "control-plane") {
    if (kind === "legacy-cicd") {
      return [
        "Usage: bun scripts/cli.ts agentrun control-plane <trigger-current|refresh> --node <node> --lane <lane> [--dry-run|--confirm]",
        "",
        "Scope: explicit legacy/manual CI/CD only.",
        "The owning YAML delivery authority must resolve to legacy-manual. PaC migrated or unknown authority must fail closed and must not use these commands for delivery or recovery.",
      ].join("\n");
    }
    if (kind === "platform-maintenance") {
      return [
        "Usage: bun scripts/cli.ts agentrun control-plane <apply|secret-sync|restart|expose> --node <node> --lane <lane> [--dry-run|--confirm]",
        "       bun scripts/cli.ts agentrun control-plane secret-sync --node <node> --lane <lane> [--secret-id <yaml-secret-id>] --dry-run [-o json|yaml] [--full|--raw]",
        "",
        "Scope: explicit YAML-declared platform/configuration maintenance only.",
        "These commands do not replace the PaC source delivery chain and must not be used after a source PR merge to complete or recover rollout.",
      ].join("\n");
    }
    return [
      "Usage: bun scripts/cli.ts agentrun control-plane <action> [options]",
      "",
      "Default actions: plan, status, cleanup-runners, cleanup-runs, cleanup-session-pvcs, cleanup-local-postgres, cleanup-released-pvs",
      "Examples:",
      "  bun scripts/cli.ts agentrun control-plane plan --node NC01 --lane nc01-v02",
      "  bun scripts/cli.ts agentrun control-plane status --node NC01 --lane nc01-v02",
      "  bun scripts/cli.ts platform-infra pipelines-as-code history --target NC01 --consumer agentrun-nc01-v02 --limit 10",
      "  bun scripts/cli.ts agentrun control-plane status",
      "  bun scripts/cli.ts agentrun control-plane status --pipeline-run <yaml-lane-pipelinerun>",
      "  bun scripts/cli.ts agentrun control-plane cleanup-runners --node NC01 --lane nc01-v02 --dry-run",
      "  bun scripts/cli.ts agentrun control-plane cleanup-session-pvcs --node NC01 --lane nc01-v02 --dry-run",
      "  bun scripts/cli.ts agentrun control-plane cleanup-local-postgres --node NC01 --lane nc01-v02 --dry-run",
      "  bun scripts/cli.ts agentrun control-plane cleanup-runs --min-age-minutes 30 --limit 200 --dry-run",
      "",
      "Scoped maintenance help:",
      "  bun scripts/cli.ts agentrun control-plane platform-maintenance --help",
      "  bun scripts/cli.ts agentrun control-plane legacy-cicd --help",
      "PaC migrated consumer 的唯一触发是 release plan 后由 CLI 手动发送 PaC webhook；发布链故障先用 status/history 调查，再修 owning YAML/planner/controller/source。",
    ].join("\n");
  }
  if (verb === "provider-profile") return providerProfileHelp();
  if (verb === "git-mirror") {
    if (kind === "legacy-ops") {
      return [
        "Usage: bun scripts/cli.ts agentrun git-mirror <sync|flush> --node <node> --lane <lane> [--dry-run|--confirm] [--wait]",
        "",
        "Scope: explicit legacy/manual mirror maintenance only.",
        "The owning YAML delivery authority must resolve to legacy-manual. PaC migrated or unknown authority must fail closed.",
      ].join("\n");
    }
    return [
      "Usage: bun scripts/cli.ts agentrun git-mirror status [--full|--raw]",
      "",
      "PaC migrated consumer uses platform-infra Gitea/PaC status and never uses manual mirror sync/flush to complete delivery.",
      "Explicit legacy operations: bun scripts/cli.ts agentrun git-mirror legacy-ops --help",
    ].join("\n");
  }
  if (verb !== undefined && isAgentRunRestCompatGroup(verb)) {
    return [
      `Compatibility group: agentrun ${verb} ...`,
      "",
      "Use resource primitives for daily commander work:",
      "  bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
      "  bun scripts/cli.ts agentrun describe task/<taskId>",
      "  bun scripts/cli.ts agentrun describe run/<runId> --node NC01 --lane nc01-v02",
      "  bun scripts/cli.ts agentrun events run/<runId> --after-seq 0 --expect 10 --timeout 120s --limit 100",
      "  bun scripts/cli.ts agentrun logs session/<sessionId> --tail 100",
      "",
      "Use --raw on a resource command when you need the direct AgentRun REST envelope.",
    ].join("\n");
  }
  return [
    "Usage: bun scripts/cli.ts agentrun <verb> <resource> [options]",
    "",
    "Verbs: get, describe, events, logs, result, ack, cancel, retry, dispatch, create, apply, send, explain",
    "Resources: task/qt, attempt, run, command/cmd, runnerjob/rjob, session/ses, aipodspec/aps",
    "",
    "Common:",
    "  bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
    "  bun scripts/cli.ts agentrun describe task/<taskId>",
    "  bun scripts/cli.ts agentrun describe task/<taskId> --input -o json",
    "  bun scripts/cli.ts agentrun describe run/<runId> --node NC01 --lane nc01-v02",
    "  bun scripts/cli.ts agentrun events run/<runId> --after-seq 0 --expect 10 --timeout 120s --limit 100",
    "  bun scripts/cli.ts agentrun events run/<runId> --detail-seq <seq>",
    "  bun scripts/cli.ts agentrun logs session/<sessionId> --tail 100",
    "  bun scripts/cli.ts agentrun retry task/<taskId> --idempotency-key <key> --reason <text> --dry-run",
    "  bun scripts/cli.ts agentrun get attempts --task <taskId> --limit 20",
    "  bun scripts/cli.ts agentrun create task --aipod Artificer --title \"修复 HWLAB 的 cicd\" --target <Target> --target-workspace <task-worktree> --repo <owner/repo> --ref <branch> --mdtodo-id <opaque-task-reference> --prompt-stdin",
    "",
    "Machine/debug output:",
    "  -o json|yaml emits a stable UniDesk resource object without the global JSON envelope.",
    "  --raw emits the direct AgentRun REST envelope.",
    "  --target/--node/--lane selects a YAML Target; resource commands use its k3s service proxy, and target tasks probe targetWorkspace through trans.",
  ].join("\n");
}
