1023 lines
81 KiB
TypeScript
1023 lines
81 KiB
TypeScript
// SPEC: PJ2026-01060509 出站诊断 draft-2026-06-26-p8-egress-job-friction.
|
||
// SPEC: PJ2026-01060703 CI/CD branch follower draft-2026-07-03-p0-branch-follower.
|
||
// Static CLI help for job aliases and server lifecycle progressive disclosure.
|
||
import { join } from "node:path";
|
||
import { ghHelp, ghScopedHelp } from "./gh";
|
||
import { authBrokerHelp } from "./auth-broker";
|
||
import { platformDbHelp } from "./platform-db";
|
||
import { secretsHelp } from "./secrets";
|
||
import { healthHelp } from "./health";
|
||
import { repoRoot } from "./config";
|
||
|
||
export function rootHelp(): unknown {
|
||
return {
|
||
entry: "bun scripts/cli.ts",
|
||
output: "json",
|
||
commands: [
|
||
{ command: "help", description: "List supported commands." },
|
||
{ command: "--main-server-ip <ip> <command>", description: "Run selected commands through the public frontend API; use --main-server-key only for legacy SSH transport." },
|
||
{ command: "config show", description: "Validate and print config.json as the single source of truth." },
|
||
{ command: "check [--full|--files|--scripts-typecheck|--scripts-typecheck-timeout-ms N|--check-heartbeat-ms N|--components|--compose|--logs|--recovery-guardrails|--rust] | check recovery-guardrails", description: "Run the lightweight default syntax/config gate or the low-noise read-only D601 recovery guardrails; long command checks emit progress heartbeats and bounded timeout details." },
|
||
{ command: "health [--json|--full|--skills-dir path|--threshold-bytes N]", description: "Check repo skill SKILL.md size health; files over 10 KiB alert and must move lower-frequency detail into .agents/skills/<skill_id>/references/." },
|
||
{ command: "server start", description: "Fire-and-forget build/start for database, backend-core, frontend, provider gateway, and managed main-server user services." },
|
||
{ command: "server stop", description: "Fire-and-forget docker-compose down for the fixed UniDesk stack." },
|
||
{ command: "server status", description: "Show fixed ports, containers, service health, and public URLs." },
|
||
{ command: "server swap status|ensure [--path /swapfile] [--size 2GiB] [--dry-run]", description: "Inspect or idempotently create host swap for low-memory main-server operation." },
|
||
{ command: "server logs [--tail-bytes N]", description: "Return bounded tails from file logs and docker logs." },
|
||
{ command: "server cleanup plan [--min-age-hours N] [--limit N]", description: "Dry-run Docker image cleanup plan only: list active/protected images, stale candidates older than the default 24h threshold, risk, estimated reclaim, and manual review commands without deleting anything." },
|
||
{ command: "gc plan|run|db-trace|policy|remote [--confirm] [--logs-keep-days N] [--include-browser-cache]", description: "One-time main-server or remote provider disk relief and low-risk anti-bloat policy for logs, journald, allowlisted /tmp artifacts, scoped core dumps and explicit trace telemetry retention; plan is read-only and run requires --confirm." },
|
||
{ command: "server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "Maintenance-only local Compose rebuild for reviewed main-server services; frontend standard release must use CI artifact plus deploy apply dev/prod artifact consumers." },
|
||
{ command: "server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>", description: "No-build single-service Compose restart for reviewed main-server maintenance recovery; returns an async job and validates the recreated container." },
|
||
{ command: "provider attach <providerId> [--master-server URL] [--up] [--force] | provider triage <providerId> [--observed-error text] [--observed-scope scope] [--microservice id ...] [--full|--raw]", description: "Generate the minimal external provider-gateway env/compose bundle or run the low-noise read-only provider health triage contract." },
|
||
{ command: "trans <route> [operation args...] (alias of ssh <route> ...)", description: "Open a Host SSH / WSL SSH maintenance session; provider WebSocket carries control and host.ssh.tcp-pool carries stdin/stdout/stderr data." },
|
||
{ command: "trans gh:/owner/repo[/pr|/issue][/number[/1]] ls|cat|rg|apply-patch", description: "Treat GitHub PRs/issues as virtual text directories; `issue ls --search/--state` covers filtered reads, `cat|rg` reads first-floor body text, and `apply-patch` updates `body.md` through UniDesk gh plus apply-patch v2." },
|
||
{ command: "trans <route> apply-patch < patch.diff", description: "Default remote text patch entry: apply a standard patch with the local TypeScript v2 engine while the remote route only reads and writes files." },
|
||
{ command: "trans <route> upload <local-file> <remote-file> | trans <route> download <remote-file> <local-file>", description: "Transfer whole files through SSH passthrough with automatic endpoint byte/SHA-256 verification; downloads stream stdout over host.ssh.tcp-pool." },
|
||
{ command: "trans <providerId> apply-patch-v1 [tool args...] < patch.diff", description: "Fallback to the injected legacy remote apply_patch helper directly over SSH passthrough and stream the patch from local stdin." },
|
||
{ command: "trans <providerId> py [script-args...] < script.py", description: "Run remote Python from local stdin through SSH passthrough without nested shell quoting; extra args become script argv." },
|
||
{ command: "trans <providerId> sh|bash [arg...] <<'SH|BASH' ...", description: "Run a remote POSIX sh or Bash body from local stdin; the operation name declares the shell dialect, and removed `script`/`shell` operations fail with a migration hint." },
|
||
{ command: "trans <providerId> skills [--scope all|wsl|windows] [--limit N]", description: "Discover WSL/Linux and, for WSL providers, Windows skill directories in one SSH passthrough call." },
|
||
{ command: "trans <providerId> find <path...> [--max-depth N] [--type d|f|l] [--contains TEXT] [--iname PATTERN] [--limit N] [--sort]", description: "Run a structured remote find command without nested shell quoting or parentheses." },
|
||
{ command: "trans <providerId> glob [--root DIR] [--pattern PATTERN] [--contains TEXT] [--type any|f|d] [--limit N] [--sort]", description: "Run remote glob matching through the injected helper without shell glob expansion." },
|
||
{ command: "trans <providerId>:/absolute/workspace <operation args...>", description: "Route directly into a host workspace while keeping the operation parser independent from the location." },
|
||
{ command: "trans <providerId>:k3s[:namespace:workload[:container]] <kubectl|logs|exec|sh|bash|apply-patch|apply-patch-v1|command> ...", description: "Locate a native k3s control plane or workload with route syntax, then run a separate operation with KUBECONFIG fixed and argv assembled by the CLI." },
|
||
{ command: "trans <providerId> argv <command> [args...]", description: "Run a non-interactive remote command with each argv token shell-quoted by UniDesk before SSH passthrough; use explicit `sh` or `bash` when shell features are required." },
|
||
{ command: "microservice list", description: "List UniDesk-managed user services and their provider/runtime mapping." },
|
||
{ command: "microservice status <id>", description: "Show one user service config, repository reference, backend mapping, and runtime status." },
|
||
{ command: "microservice health <id> [--compact|--raw|--full]", description: "Probe one user service through backend-core -> provider-gateway HTTP proxy; default output is compact, and code-queue uses a commander-safe liveness summary unless raw/full is requested." },
|
||
{ command: "microservice proxy <id> <path> [--method GET|POST|PUT|PATCH|DELETE] [--body-json JSON|--body-file path|--body-stdin] [--check-path] [--raw] [--max-body-bytes N]", description: "Access a private user-service backend path through the same frontend-only proxy used by WebUI; JSON request bodies are supported for controlled write/debug endpoints; --check-path (currently todo-note only) validates the path/method against the registered CLI-side endpoint catalog without contacting upstream." },
|
||
{ command: "microservice diagnostics <id> [--full|--raw]", description: "Split k3sctl-managed proxy health into a compact summary by default; use --full/--raw for complete evidence." },
|
||
{ command: "microservice tunnel-self-test <id>", description: "Trigger an expected provider HTTP tunnel failure and verify requestId/stage diagnostics are returned." },
|
||
{ command: "todo-note list|show|add|update|complete|reopen|remind|delete|undo|redo|create|rename|delete-list|health", description: "Manage Todo Note through concise list/todo resource commands; default output is a bounded table and --json is explicit." },
|
||
{ command: "decision upload <markdown-file> [--title text] [--type meeting|decision|goal|external_goal|internal_goal|blocker|debt|experiment] [--level|--priority G0|G1|G2|G3|P0|P1|P2|P3|none] [--doc-no DC-...] [--doc-type DCSN|GOAL|PLAN|RPRT|ACTN|ISSU|RETR|RQST|RESP|MINS] [--doc-priority P0|P1|P2|P3] [--signer text] [--issued-at ISO]", description: "Upload a meeting note or decision/requirement record through backend-core -> decision-center user-service proxy." },
|
||
{ command: "decision diary import <markdown-file> [--source-file path] [--tag tag] [--include-entries]", description: "Import a dated work log Markdown into PostgreSQL diary entries split as YYYY-MM/YYYY-MM-DD.md." },
|
||
{ command: "decision diary list [--month YYYY-MM] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--limit N] [--include-body]", description: "List daily Markdown diary entries stored by Decision Center." },
|
||
{ command: "decision diary history [--month YYYY-MM] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--limit N] [--include-body]", description: "Read diary history through the productized history API alias." },
|
||
{ command: "decision diary today [--edit --body-file path|--body text|--summary text] [--title text] [--tag tag]", description: "Get or create today's diary entry using the service's real current date; --edit saves today's Markdown and optional explicit summary." },
|
||
{ command: "decision diary months", description: "List available Decision Center diary months with day counts." },
|
||
{ command: "decision diary show <YYYY-MM-DD|id> [--source-file path]", description: "Show one daily diary Markdown entry; source-file disambiguates same-day entries from multiple imports." },
|
||
{ command: "decision diary edit|upsert <YYYY-MM-DD|id> [--body-file path|--body text] [--summary text] [--title text] [--source-file path] [--tag tag]", description: "Create or edit one daily diary entry through PUT /api/diary/entries/:idOrDate via backend-core proxy, keeping summary independent from body." },
|
||
{ command: "decision list [--doc-no DC-...] [--doc-type ...] [--doc-priority P0|P1|P2|P3] [--year YYYY] [--type ...] [--status ...] [--level|--priority ...] [--limit N] [--include-body]", description: "List Decision Center records through the user-service proxy; bodies are omitted unless --include-body is set." },
|
||
{ command: "decision requirement list|create|show|update|upsert [id|docNo] [--title text] [--body-file path] [--type external_goal|internal_goal|goal|decision|blocker|debt|experiment] [--doc-no DC-...] [--doc-type ...] [--doc-priority P0|P1|P2|P3] [--signer text] [--issued-at ISO]", description: "Manage productized requirement records over the PostgreSQL records model, excluding meeting records." },
|
||
{ command: "decision show <id|docNo>", description: "Show one Decision Center record." },
|
||
{ command: "deploy check|plan|apply [--file deploy.json|--env dev|prod] [--service id] [--commit full-sha] [--dry-run] [--force]", description: "Reconcile services from origin/master:deploy.json environments; --commit overrides one reviewed artifact consumer such as frontend for release/v1 validation or rollback. code-queue artifact consumption is dev-only." },
|
||
{ command: "cicd status --node <NODE>", description: "Show one node's CI/CD closeout summary across current Pipelines-as-Code consumers, including PipelineRun, Argo and runtime readiness." },
|
||
{ command: "cicd gitea-actions-poc plan|status", description: "Archived read-only CI/CD migration evidence for GH-1548/GH-1549; never use as a delivery or closeout path." },
|
||
{ command: "cicd branch-follower status|events|logs|taskrun|runtime|debug-step", description: "退役 branch-follower 的只读历史诊断;当前 lane 只使用 cicd status 与 platform-infra pipelines-as-code status/history 观察自动链。" },
|
||
{ command: "dev-env validate|prewarm-images|worktree add", description: "Validate D601 guardrails, prewarm dev images, or create UniDesk task worktrees with .worktreecopy local config copying." },
|
||
{ command: "artifact-registry plan|render|status|health|install|deploy-backend-core|deploy-service", description: "Manage the D601 host-managed CNCF Distribution registry and run pull-only artifact CD for supported services, including D601 direct, k3s-managed, and code-queue dev-only consumers." },
|
||
{ command: "auth-broker contract|health --dry-run|credential-request --dry-run|pr-preflight --dry-run", description: "Inspect the P0 Rust auth broker and CLI adapter contract without reading token values, writing GitHub, or starting services." },
|
||
{ command: "gh preflight|auth|issue|pr", description: "Run safe GitHub issue and PR CRUD/lifecycle operations through REST with body-file update replace/append, issue/comment apply_patch body patching, comment delete, token diagnostics, PR closeout preflight, hard delete unsupported, and guarded PR merge." },
|
||
{ command: "git github-push-fallback [--repo owner/name] [--branch branch] [--host-name host-or-ip] [--confirm]", description: "Plan or execute a one-shot GitHub push through ssh.github.com:443 without editing remotes; use only for reviewed DNS/port-22 push fallback." },
|
||
{ command: "commander contract|plan --dry-run|smoke --dry-run|approval request --dry-run", description: "Host Codex commander skeleton contract, no-daemon smoke plan, and dry-run approval preview without live bridges or message sends." },
|
||
{ command: "web-probe run|script|observe|sentinel --node <node> --lane <lane>", description: "Run YAML-selected HWLAB Web probes, long observe/analyze sessions, project-management MDTODO commands, and Web sentinel control through the single top-level web-probe entrypoint." },
|
||
{ command: "hwlab nodes control-plane|git-mirror|hwpod-preinstall|secret|test-accounts --node <node> --lane <lane>", description: "Manage HWLAB node/lane runtime prerequisites, including NC01 YAML-declared k3s infra/tools-image/Argo bootstrap, HWPOD preinstall configRefs, redacted test-account preparation, and NC01 v0.3 runtime lane, with the node identity passed as data." },
|
||
{ command: "hwlab nodes control-plane|git-mirror|hwpod-preinstall|secret|test-accounts --node NC01 --lane v03", description: "Operate the NC01 HWLAB v0.3 development and deployment lane from YAML source truth." },
|
||
{ command: "agentrun get|describe|events|logs|result|ack|cancel|dispatch|create|apply|send|control-plane|git-mirror", description: "Use AgentRun v0.1 resource primitives with low-noise human output by default; session follow-up uses send only and the server decides internal steer vs turn." },
|
||
{ command: "platform-infra sub2api|langbot|n8n|webterm|wechat-archive ...", description: "Deploy platform-infra services such as Sub2API, LangBot, n8n and Web Terminal, manage YAML-controlled public Caddy/FRP exposure and WeChat archive workflows, and inspect status/logs without printing secrets." },
|
||
{ command: "secrets plan|sync|status", description: "Plan, push and inspect YAML-declared local secret source keys to Kubernetes Secrets without printing or reverse-engineering values." },
|
||
{ command: "platform-db postgres plan|status|export-secrets|apply", description: "Manage YAML-declared host-native PostgreSQL 16 on PK01 for Sub2API/platform state, with PostgreSQL native TLS and redacted secret exports." },
|
||
{ command: "hwlab cd audit --env dev | hwlab cd status --env dev | hwlab cd apply --env dev --dry-run", description: "Archived HWLAB DEV CD diagnostics only; current HWLAB rollout uses NC01 GitOps." },
|
||
{ command: "code-agent-sandbox", description: "Independent Code Agent Sandbox service skeleton for adapter, mode, and credential-boundary diagnostics." },
|
||
{ command: "schedule list|get|runs|run|retry-run|delete", description: "Manage backend-core scheduled tasks and run history; schedule run <id> supports --wait-ms N and retry-run reuses the failed run's schedule." },
|
||
{ command: "schedule upsert-pgdata-backup [--time HH:MM] [--remote-base /SERVER_DATA/UNIDESK_PG_DATA]", description: "Create or update the daily PGDATA physical backup task that uploads monthly rotated archives to Baidu Netdisk." },
|
||
{ command: "codex deploy <commitId> [--target <id>] [--timeout-ms N]", description: "Disabled legacy Code Queue deploy path; use the dev-only artifact consumer instead." },
|
||
{ command: "codex submit|steer|resume|queue create|queue merge|move", description: "Frozen legacy Code Queue write commands; use agentrun create/apply/send for new commander work. Historical codex task/tasks/output/read/unread/queues remain available for archive troubleshooting." },
|
||
{ command: "codex skills-sync --dry-run [--full]", description: "Inspect the controlled runner skills hostPath lifecycle contract without copying files, restarting services, reading secrets, or mutating live runner paths." },
|
||
{ command: "codex execution-plane [--full|--raw]", description: "Read-only D601 native k3s Code Queue execution-plane inspection; compares formal deployments, deprecated Compose residuals, commit markers, pod digest, and mounted worktree HEAD." },
|
||
{ command: "codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/<name>] [--pr-create-dry-run --pr-create-dry-run-head <head>] [--issue N] [--full|--raw]", description: "Read-only PR admission check with compact commander output by default; use --full or --raw to expand the full runtime preflight, tool, and observation payload." },
|
||
{ command: "codex task <taskId> [--detail] [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]", description: "Fetch the bounded review view by default; --detail is still capped, while --full/trace/output explicitly expand evidence." },
|
||
{ command: "codex tasks [--view commander|supervisor|full] [--queue id] [--status status[,status]] [--unread|--unread-only] [--limit N] [--before-id id]", description: "Show Code Queue task state with progressive disclosure; --view commander is the recommended bounded host-commander loop, supervisor keeps compact sections, and full returns detailed rows." },
|
||
{ command: "codex unread [summary|list|mark-read] [--queue id] [--repo owner/name] [--issue N] [--status succeeded,failed,canceled] [--limit N] [--view summary|full] [--full] [--confirm]", description: "Summarize unread terminal backlog by repo, issue, status and queue with compact rows by default; per-task command blocks require --full/list, and batch mark-read requires --confirm." },
|
||
{ command: "codex output <taskId> [--tail|--from-start|--after-seq N|--before-seq N --limit N] [--full-text]", description: "Fetch paged raw Code Queue output records; default caps large limits/text previews, --full-text explicitly expands one seq window." },
|
||
{ command: "codex read <taskId>", description: "Mark one reviewed terminal task read and return terminal metadata plus final response; prompt/tool logs stay behind drill-down commands." },
|
||
{ command: "codex dev-ready", description: "Fetch execution-container readiness, including sanitized skill injection status from /api/dev-ready." },
|
||
{ command: "codex judge <taskId> --attempt N [--dry-run] [--include-prompt]", description: "Replay one stored Code Queue attempt through the same judge context builder and MiniMax judge call path used by the live queue worker." },
|
||
{ command: "codex steer <taskId> / codex resume <taskId>", description: "Frozen legacy execution mutation entries; use agentrun send/logs/events/result/ack/cancel against AgentRun resources instead." },
|
||
{ command: "codex steer-confirm <taskId> --steer-id <id> [--raw]", description: "Read-only lookup for a steerId in task trace so deliveryUnconfirmed can be resolved without resending the corrective prompt." },
|
||
{ command: "codex interrupt|cancel <taskId>", description: "Request interrupt for a running Code Queue task, or cancel a queued/retry_wait task, through the same private proxy." },
|
||
{ command: "codex queues [--full|--all] [--limit N] [--page N|--offset N]", description: "Read legacy Code Queue archive summaries. Legacy queue create/merge and move are frozen; use agentrun create/apply/get/cancel for new work." },
|
||
{ command: "job|jobs list [--limit N] [--include-command]", description: "List async jobs from /root/.unidesk/.state/jobs with a bounded default page and progress summaries." },
|
||
{ command: "job status|get|read <jobId|latest> [--tail-bytes N]", description: "Show job state with a structured progress summary and bounded stdout/stderr tails." },
|
||
{ command: "job cancel <jobId>", description: "Cancel a queued/running async job through the /root/.unidesk/.state/jobs control entry and keep a terminal canceled record." },
|
||
{ command: "debug health", description: "Probe internal core, nodes, system/Docker status, frontend, provider ingress, and public boundary." },
|
||
{ command: "debug ssh-pool <providerId>", description: "Show bounded host.ssh.tcp-pool labels for one provider, including ready/claimed/desired/lastError." },
|
||
{ command: "debug egress-proxy <providerId>", description: "Show provider-gateway egress proxy tunnel counts, stale tunnel diagnosis, active target summaries, and recent closed tunnel lifecycle without URL credential leakage." },
|
||
{ command: "debug provider-rootfs <providerId>", description: "Run a read-only provider-gateway rootfs diagnostic over trans: image id, runtime smoke, docker system df snapshot errors, and recent host_ssh lifecycle lines." },
|
||
{ command: "debug dispatch [providerId] [docker.ps|provider.upgrade|host.ssh|microservice.http|echo] [--wait-ms N]", description: "Submit a real internal-core dispatch request for CLI debugging." },
|
||
{ command: "debug task <taskId|latest>", description: "Read a dispatched task record from internal core for CLI debugging." },
|
||
{ command: "network perf [--service code-queue --path /api/tasks/overview?limit=30 --count N --concurrency N --label before|after]", description: "Benchmark frontend -> backend-core -> provider/adapter user-service networking and report latency/proxy-mode distributions." },
|
||
{ command: "ci install|status|run|publish-backend-core|publish-user-service|run-dev-e2e|logs", description: "Manage D601/G14 native k3s Tekton CI; artifact publish commands build commit-pinned images in CI without deploying CD." },
|
||
{ command: "e2e run [--only pattern[,pattern...]] [--skip pattern[,pattern...]]", description: "Run selected public/internal/Playwright E2E checks; use --only for focused iteration and rerun without filters for final regression." },
|
||
{ command: "bun scripts/playwright-cli.ts screenshot|open|eval ...", description: "Repo-owned Playwright wrapper for commander browser checks; headless by default, supports storage-state --session, and returns JSON guidance for unsupported interactive daemon commands." },
|
||
],
|
||
};
|
||
}
|
||
|
||
export function isHelpToken(value: string | undefined): boolean {
|
||
return value === "help" || value === "--help" || value === "-h";
|
||
}
|
||
|
||
export function serverHelp(action: string | undefined = undefined): unknown {
|
||
return {
|
||
command: action === undefined || isHelpToken(action) ? "server start|stop|status|swap|logs|cleanup|rebuild|restart" : `server ${action}`,
|
||
output: "json",
|
||
description: "Manage the fixed main-server Docker Compose stack without exposing backend-core REST publicly.",
|
||
usage: {
|
||
start: "bun scripts/cli.ts server start",
|
||
stop: "bun scripts/cli.ts server stop",
|
||
status: "bun scripts/cli.ts server status",
|
||
swap: "bun scripts/cli.ts server swap status|ensure [--path /swapfile] [--size 2GiB] [--dry-run]",
|
||
logs: "bun scripts/cli.ts server logs [--tail-bytes N]",
|
||
cleanup: "bun scripts/cli.ts server cleanup plan [--min-age-hours N] [--limit N]",
|
||
rebuild: "bun scripts/cli.ts server rebuild <backend-core|frontend|dev-frontend-proxy|provider-gateway|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
|
||
restart: "bun scripts/cli.ts server restart <backend-core|frontend|dev-frontend-proxy|provider-gateway|pk01-postgres-relay|code-queue-mgr|project-manager|baidu-netdisk|oa-event-flow>",
|
||
},
|
||
cleanupPlan: {
|
||
dryRunOnly: true,
|
||
mutation: false,
|
||
scope: "docker images only",
|
||
defaultMinAgeHours: 24,
|
||
protectedByDefault: [
|
||
"running containers and their image IDs",
|
||
"stopped containers and their image IDs until the container is reviewed separately",
|
||
"deploy.json/CI.json current commit-pinned images",
|
||
"database named volume, registry storage, Baidu Netdisk state and staging directories",
|
||
],
|
||
forbidden: ["docker prune", "docker volume rm", "compose down -v", "database cleanup without verified backup"],
|
||
},
|
||
publicEntrypoints: {
|
||
frontend: "prod UniDesk frontend",
|
||
devFrontend: "dev UniDesk frontend proxy to D601 unidesk-dev/frontend-dev",
|
||
providerIngress: "provider-gateway WebSocket ingress",
|
||
},
|
||
rustBoundary: {
|
||
masterServer: "do not use server rebuild backend-core for routine Rust iteration; only reviewed backend-core main-server online may use the constrained rebuild path",
|
||
d601: "use deploy apply --env dev --service backend-core and CI for Rust build/check",
|
||
},
|
||
maintenanceOnly: {
|
||
frontend: "server rebuild frontend is not standard release evidence; publish 127.0.0.1:5000/unidesk/frontend:<commit> with CI, then consume it with deploy apply --env dev/prod --service frontend --commit <full-sha>",
|
||
userServices: "server rebuild for main-server user services is reserved for local maintenance, bootstrap or recovery and must not replace commit-pinned artifact CD",
|
||
restart: "server restart is for no-build single-service recovery when the existing image is already present and the goal is to refresh runtime state",
|
||
},
|
||
nonRebuildableBoundary: {
|
||
upstreamImages: ["filebrowser", "filebrowser-d601"],
|
||
infrastructure: ["database", "k3sctl-adapter"],
|
||
d601ExecutionPlane: ["code-queue"],
|
||
policy: "unsupported objects return unsupported-server-rebuild and must not be coerced into main-server Compose source builds",
|
||
},
|
||
};
|
||
}
|
||
|
||
export type SshHelpScope =
|
||
| "argv" | "exec" | "git" | "node" | "kubectl" | "logs"
|
||
| "sh" | "bash" | "py" | "ps" | "cmd"
|
||
| "pwd" | "ls" | "cat" | "head" | "tail" | "stat" | "wc" | "rg" | "find" | "glob" | "skills"
|
||
| "apply-patch" | "apply-patch-v1" | "upload" | "download";
|
||
|
||
type SshOperationHelp = {
|
||
group: "process" | "shell" | "filesystem" | "patch" | "transfer";
|
||
description: string;
|
||
usage: string[];
|
||
notes?: string[];
|
||
};
|
||
|
||
const SSH_OPERATION_HELP: Record<SshHelpScope, SshOperationHelp> = {
|
||
argv: {
|
||
group: "process",
|
||
description: "以原始 argv 边界运行一个远端进程;需要管道、变量或重定向时改用 sh/bash。",
|
||
usage: ["trans <route> argv <command> [args...]", "trans D601:/workspace argv git status --short --branch"],
|
||
},
|
||
exec: {
|
||
group: "process",
|
||
description: "在 k3s workload route 中运行进程,并可显式透传 stdin 或指定容器内 cwd。",
|
||
usage: ["trans <provider>:k3s:<namespace>:<workload>[:<container>] exec [--cwd /path] [--stdin] -- <command> [args...]"],
|
||
},
|
||
git: {
|
||
group: "process",
|
||
description: "在 host/workspace 或 Windows workspace route 中运行 Git convenience wrapper。",
|
||
usage: ["trans <provider>:/workspace git status --short --branch", "trans <provider>:win/<drive>/<path> git diff --check"],
|
||
},
|
||
node: {
|
||
group: "process",
|
||
description: "在目标 route 中直接运行 Node.js argv。",
|
||
usage: ["trans <route> node -e 'console.log(process.version)'"],
|
||
},
|
||
kubectl: {
|
||
group: "process",
|
||
description: "在 k3s control-plane route 上执行有界 kubectl 诊断。",
|
||
usage: ["trans <provider>:k3s kubectl get pods -n <namespace>"],
|
||
},
|
||
logs: {
|
||
group: "process",
|
||
description: "从 k3s control-plane 或 workload route 读取有界日志。",
|
||
usage: ["trans <provider>:k3s:<namespace>:<workload> logs --tail 80", "trans <provider>:k3s logs -n <namespace> -l <selector> --tail 120"],
|
||
},
|
||
sh: {
|
||
group: "shell",
|
||
description: "从 stdin 或单个命令字符串执行远端 POSIX /bin/sh。",
|
||
usage: ["trans <route> sh <<'SH'", "trans <route> sh -- '<command && command>'"],
|
||
notes: ["sh -- 只接受一个 shell command string;单进程多 argv 使用 argv。"],
|
||
},
|
||
bash: {
|
||
group: "shell",
|
||
description: "仅在需要 pipefail、数组、[[ ]] 等 Bash 语法时执行远端 Bash。",
|
||
usage: ["trans <route> bash <<'BASH'", "trans <route> bash -- '<bash command>'"],
|
||
},
|
||
py: {
|
||
group: "shell",
|
||
description: "从本地 stdin 执行远端 Python 源码,并保留 script argv。",
|
||
usage: ["trans <route> py [script-args...] < script.py"],
|
||
},
|
||
ps: {
|
||
group: "shell",
|
||
description: "在 Windows route 中执行 PowerShell 源码或 argv;route 已包含 win。",
|
||
usage: ["trans <provider>:win[/<drive>/<path>] ps <<'PS'", "trans <provider>:win ps '<PowerShell source>'"],
|
||
},
|
||
cmd: {
|
||
group: "shell",
|
||
description: "在 Windows route 中以 UTF-8 环境执行 cmd.exe/batch。",
|
||
usage: ["trans <provider>:win[/<drive>/<path>] cmd <<'CMD'", "trans <provider>:win cmd ver"],
|
||
},
|
||
pwd: { group: "filesystem", description: "读取 Windows workspace 当前目录。", usage: ["trans <provider>:win/<drive>/<path> pwd"] },
|
||
ls: { group: "filesystem", description: "有界列出 Windows workspace 文件。", usage: ["trans <provider>:win/<drive>/<path> ls --limit 50"] },
|
||
cat: { group: "filesystem", description: "读取远端文本文件;二进制文件使用 download。", usage: ["trans <route> cat <path>"] },
|
||
head: { group: "filesystem", description: "按行读取远端文本文件开头。", usage: ["trans <route> head -n 40 <path>"] },
|
||
tail: { group: "filesystem", description: "按行读取远端文本文件结尾。", usage: ["trans <route> tail -n 40 <path>"] },
|
||
stat: { group: "filesystem", description: "读取远端文件元数据。", usage: ["trans <route> stat <path>"] },
|
||
wc: { group: "filesystem", description: "统计远端文本的行、词、字符或字节。", usage: ["trans <route> wc [-l|-w|-m|-c] <path>"] },
|
||
rg: { group: "filesystem", description: "执行有界远端 ripgrep;Windows route 使用受控 UTF-8 子集。", usage: ["trans <route> rg [options] <pattern> [path...]"] },
|
||
find: { group: "filesystem", description: "不依赖 shell quoting 的结构化远端 find。", usage: ["trans <route> find <path...> [--contains TEXT] [--limit N]"] },
|
||
glob: { group: "filesystem", description: "通过远端 helper 执行有界 glob 匹配。", usage: ["trans <route> glob [--root DIR] [--pattern PATTERN] [--limit N]"] },
|
||
skills: { group: "filesystem", description: "发现 WSL/Linux 及可选 Windows skill 目录。", usage: ["trans <provider> skills [--scope all|wsl|windows] [--limit N]"] },
|
||
"apply-patch": {
|
||
group: "patch",
|
||
description: "默认远端文本修改入口;本地 v2 engine 计算变更,route 仅负责读写。",
|
||
usage: ["trans <route> apply-patch [--cwd /path] < patch.diff"],
|
||
notes: ["失败后重读当前目标块并缩小 hunk;不得自动回退 apply-patch-v1 或整文件 upload。"],
|
||
},
|
||
"apply-patch-v1": {
|
||
group: "patch",
|
||
description: "显式调用 legacy remote apply_patch helper;只作为人工确认后的兼容入口。",
|
||
usage: ["trans <route> apply-patch-v1 [--allow-loose] < patch.diff"],
|
||
},
|
||
upload: {
|
||
group: "transfer",
|
||
description: "上传必要的二进制文件或生成物并自动核对字节数与 SHA-256。",
|
||
usage: ["trans <route> upload <local-file> <remote-file>"],
|
||
notes: ["远端文本读取使用 cat/rg,修改使用 apply-patch。"],
|
||
},
|
||
download: {
|
||
group: "transfer",
|
||
description: "下载必要的二进制文件或生成物并自动核对字节数与 SHA-256。",
|
||
usage: ["trans <route> download <remote-file> <local-file>"],
|
||
},
|
||
};
|
||
|
||
const SSH_OPERATION_GROUPS = {
|
||
process: ["argv", "exec", "git", "node", "kubectl", "logs"],
|
||
shell: ["sh", "bash", "py", "ps", "cmd"],
|
||
filesystem: ["pwd", "ls", "cat", "head", "tail", "stat", "wc", "rg", "find", "glob", "skills"],
|
||
patch: ["apply-patch", "apply-patch-v1"],
|
||
transfer: ["upload", "download"],
|
||
} as const satisfies Record<SshOperationHelp["group"], readonly SshHelpScope[]>;
|
||
|
||
const SSH_HELP_SCOPES = Object.keys(SSH_OPERATION_HELP) as SshHelpScope[];
|
||
const SSH_HELP_SCOPE_SET = new Set<string>(SSH_HELP_SCOPES);
|
||
|
||
function sshEntrypoint(): "trans" | "tran" | "ssh" {
|
||
const rawEntrypoint = process.env.UNIDESK_SSH_ENTRYPOINT?.trim();
|
||
return rawEntrypoint === "trans" || rawEntrypoint === "tran" || rawEntrypoint === "ssh" ? rawEntrypoint : "ssh";
|
||
}
|
||
|
||
export function sshHelpScope(args: string[]): SshHelpScope | undefined {
|
||
const [top, helpToken, scope] = args;
|
||
if (top !== "ssh" || args.length !== 3 || !isHelpToken(helpToken) || !SSH_HELP_SCOPE_SET.has(scope ?? "")) return undefined;
|
||
return scope as SshHelpScope;
|
||
}
|
||
|
||
export function sshHelp(scope: SshHelpScope | undefined = undefined): unknown {
|
||
if (scope === "download") return sshDownloadHelp();
|
||
if (scope !== undefined) return sshOperationHelp(scope);
|
||
const entrypoint = sshEntrypoint();
|
||
const operationGroups = Object.fromEntries(
|
||
Object.entries(SSH_OPERATION_GROUPS).map(([group, operations]) => [group, operations.join(" | ")]),
|
||
);
|
||
return {
|
||
command: `${entrypoint} --help`,
|
||
output: "json",
|
||
description: "通过 provider-gateway bridge 访问 Host SSH、WSL、Windows 或 k3s 目标。",
|
||
routeSyntax: {
|
||
general: `${entrypoint} <route> <operation> [operation-args...]`,
|
||
hostWorkspace: "<provider>:/absolute/workspace",
|
||
k3sControlPlane: "<provider>:k3s",
|
||
k3sWorkload: "<provider>:k3s:<namespace>:<workload>[:<container>]",
|
||
windowsWorkspace: "<provider>:win[/<drive>/<path>]",
|
||
githubContent: "gh:/<owner>/<repo>[/issue|/pr]/<number>",
|
||
},
|
||
operationGroups,
|
||
scopedHelp: {
|
||
command: `${entrypoint} --help <operation>`,
|
||
availableOperationCount: SSH_HELP_SCOPES.length,
|
||
examples: [`${entrypoint} --help apply-patch`, `${entrypoint} --help download`, `${entrypoint} --help ps`],
|
||
},
|
||
boundaries: [
|
||
"route 只定位目标,route 后的 token 全部交给 operation parser。",
|
||
"单进程优先 argv;shell 逻辑显式使用 sh/bash,Windows 使用 ps/cmd。",
|
||
"远端文本读取优先 cat/rg,修改优先 apply-patch;upload/download 仅用于必要的二进制或生成物。",
|
||
"普通 trans 短连接上限保持 60s;长流程使用受控 submit-and-poll 入口。",
|
||
],
|
||
};
|
||
}
|
||
|
||
function sshOperationHelp(scope: Exclude<SshHelpScope, "download">): unknown {
|
||
const entrypoint = sshEntrypoint();
|
||
const detail = SSH_OPERATION_HELP[scope];
|
||
return {
|
||
command: `${entrypoint} --help ${scope}`,
|
||
output: "json",
|
||
scope,
|
||
group: detail.group,
|
||
description: detail.description,
|
||
routeSyntax: `${entrypoint} <route> ${scope} [operation-args...]`,
|
||
usage: detail.usage.map((value) => value.replace(/^trans\b/u, entrypoint)),
|
||
notes: detail.notes ?? [],
|
||
next: [`${entrypoint} --help`, `${entrypoint} --help ${scope}`],
|
||
};
|
||
}
|
||
|
||
function sshDownloadHelp(): unknown {
|
||
const configuredRepoRoot = process.env.UNIDESK_TRANS_REPO_ROOT?.trim() || null;
|
||
const entrypoint = sshEntrypoint();
|
||
return {
|
||
command: `${entrypoint} --help download`,
|
||
output: "json",
|
||
scope: "download",
|
||
description: "下载一个必要的二进制文件或生成物,并自动核对远端/本地字节数与 SHA-256;远端文本改用 cat/rg/apply-patch。",
|
||
runtime: {
|
||
entrypoint,
|
||
repoRoot,
|
||
cliPath: join(repoRoot, "scripts", "ssh-cli.ts"),
|
||
cwdSelectsRepoRoot: false,
|
||
rootSelection: {
|
||
environmentVariable: "UNIDESK_TRANS_REPO_ROOT",
|
||
configuredValue: configuredRepoRoot,
|
||
explicitExample: `UNIDESK_TRANS_REPO_ROOT=${repoRoot} trans --help download`,
|
||
note: "The PATH wrapper selects its source root independently of cwd; set UNIDESK_TRANS_REPO_ROOT explicitly when validating a worktree implementation.",
|
||
},
|
||
},
|
||
usage: [
|
||
"trans <route> download <remote-file> <local-file>",
|
||
"trans <route> download --inactivity-timeout-ms <milliseconds> <remote-file> <local-file>",
|
||
"trans --help download",
|
||
],
|
||
options: {
|
||
"--inactivity-timeout-ms <milliseconds>": "Allow a controlled progress-emitting download to stay open while data continues flowing; ordinary trans operations retain the short runtime budget.",
|
||
},
|
||
contract: {
|
||
hint: "避免对远端文本反复 upload/download;读取优先使用 cat/rg,修改优先使用 apply-patch。",
|
||
pathOrder: ["remote-file", "local-file"],
|
||
transport: "host.ssh.tcp-pool",
|
||
strategy: "tcp-pool-stdout-stream",
|
||
progress: "unidesk.ssh.download.progress JSON is emitted on stderr with bytes, remainingBytes and throughputBytesPerSecond.",
|
||
verification: {
|
||
automatic: true,
|
||
fields: ["bytes", "sha256"],
|
||
success: "verified=true and verification.match.{bytes,sha256}=true",
|
||
partialFilePolicy: "The local target is removed when streaming or verification fails.",
|
||
},
|
||
},
|
||
examples: {
|
||
host: "trans D601:/tmp download /tmp/trace.json ./trace.json",
|
||
k3sWorkload: "trans NC01:k3s:hwlab-v03:hwlab-cloud-api:hwlab-cloud-api download /tmp/trace.json ./trace.json",
|
||
windowsDrive: "trans D601:win download 'D:\\tmp\\trace.json' ./trace.json",
|
||
explicitWorktree: `UNIDESK_TRANS_REPO_ROOT=${repoRoot} trans NC01:k3s:hwlab-v03:hwlab-cloud-api:hwlab-cloud-api download /tmp/trace.json ./trace.json`,
|
||
},
|
||
notes: [
|
||
"A k3s download requires a workload route; the control-plane-only <provider>:k3s route cannot name a remote file inside a workload.",
|
||
"Windows drive-letter paths are mapped through the same provider's WSL /mnt/<drive> host route before verified stdout streaming.",
|
||
"The final JSON result is the integrity proof; a separate manual sha256sum comparison is not required.",
|
||
],
|
||
};
|
||
}
|
||
|
||
function configHelp(): unknown {
|
||
return {
|
||
command: "config show",
|
||
output: "json",
|
||
usage: "bun scripts/cli.ts config show",
|
||
description: "Validate and print the root config.json single source of truth.",
|
||
};
|
||
}
|
||
|
||
function microserviceHelp(): unknown {
|
||
return {
|
||
command: "microservice list|status|health|diagnostics|tunnel-self-test|proxy",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts microservice list",
|
||
"bun scripts/cli.ts microservice status <id> [--full|--raw]",
|
||
"bun scripts/cli.ts microservice health <id> [--compact|--full|--raw]",
|
||
"bun scripts/cli.ts microservice diagnostics <id> [--full|--raw]",
|
||
"bun scripts/cli.ts microservice tunnel-self-test <id>",
|
||
"bun scripts/cli.ts microservice proxy <id> <path> [--method GET|POST|PUT|PATCH|DELETE] [--body-json JSON|--body-file path|--body-stdin] [--check-path] [--raw] [--full] [--max-body-bytes N]",
|
||
],
|
||
description: "Access UniDesk-managed user services through the same backend-core/provider proxy path used by the WebUI.",
|
||
};
|
||
}
|
||
|
||
function decisionHelp(): unknown {
|
||
return {
|
||
command: "decision upload|list|show|health|diary|requirement|deployment|storage",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts decision upload <markdown-file> [--title text] [--type meeting|decision] [--doc-no DC-...]",
|
||
"bun scripts/cli.ts decision list [--doc-no DC-...] [--doc-type GOAL] [--doc-priority P0] [--year YYYY] [--limit N]",
|
||
"bun scripts/cli.ts decision show <id|docNo>",
|
||
"bun scripts/cli.ts decision health",
|
||
"bun scripts/cli.ts decision diary import|list|history|months|today|show|edit|upsert ...",
|
||
"bun scripts/cli.ts decision requirement list|create|show|update|upsert ... [--doc-no DC-...] [--doc-type GOAL] [--doc-priority P0] [--signer text] [--issued-at ISO]",
|
||
"bun scripts/cli.ts decision deployment plan|render|status [--config config/unidesk-host-k8s.yaml]",
|
||
"bun scripts/cli.ts decision deployment apply --dry-run|--confirm [--config config/unidesk-host-k8s.yaml]",
|
||
"bun scripts/cli.ts decision storage plan|status|verify [--config config/unidesk-host-k8s.yaml]",
|
||
"bun scripts/cli.ts decision storage migrate --dry-run|--confirm [--config config/unidesk-host-k8s.yaml]",
|
||
],
|
||
description: "Operate Decision Center through the registered user-service proxy and manage its NC01 YAML-first k8s deployment.",
|
||
};
|
||
}
|
||
|
||
function providerHelp(): unknown {
|
||
return {
|
||
command: "provider attach|triage",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts provider attach <providerId> [--master-server URL] [--up] [--force]",
|
||
"bun scripts/cli.ts provider triage <providerId> [--observed-error text] [--observed-scope scope] [--microservice id ...] [--full|--raw]",
|
||
],
|
||
description: "Generate the minimal provider-gateway attach env/compose bundle or run the read-only provider health triage contract.",
|
||
};
|
||
}
|
||
|
||
function gcHelp(): unknown {
|
||
return {
|
||
command: "gc plan|run|db-trace|policy|remote",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts gc plan",
|
||
"bun scripts/cli.ts gc run --confirm",
|
||
"bun scripts/cli.ts gc plan --logs-keep-days 7 --docker-log-max-bytes 50M --journal-target-size 512M",
|
||
"bun scripts/cli.ts gc run --confirm --build-cache-all --include-browser-cache",
|
||
"bun scripts/cli.ts gc run --confirm --include-browser-cache",
|
||
"bun scripts/cli.ts gc plan --target-use-percent 59 --include-state-artifacts --state-artifact-keep-days 14 --full",
|
||
"bun scripts/cli.ts gc plan --include-codex-sessions --include-merged-worktrees --include-state-stale-scratch",
|
||
"bun scripts/cli.ts gc db-trace plan --before-date 2026-05-25",
|
||
"bun scripts/cli.ts gc db-trace run --confirm --before-date 2026-05-25 --vacuum-full",
|
||
"bun scripts/cli.ts gc policy plan",
|
||
"bun scripts/cli.ts gc policy install",
|
||
"bun scripts/cli.ts gc remote G14 plan",
|
||
"bun scripts/cli.ts gc remote G14 plan --target-use-percent 50 --include-hwlab-registry",
|
||
"bun scripts/cli.ts gc remote G14 run --confirm",
|
||
"bun scripts/cli.ts gc remote G14 status --job-id <id>",
|
||
"bun scripts/cli.ts gc plan --full",
|
||
],
|
||
description: "Plan or execute YAML-configured bounded one-time disk relief for file logs, Docker json logs, systemd journal, Docker BuildKit cache, allowlisted /tmp artifacts, opt-in UniDesk .state/session/worktree retention, scoped remote core dumps and explicitly scoped database trace telemetry retention.",
|
||
safety: {
|
||
default: "plan is read-only and mutation=false",
|
||
runGuard: "run requires --confirm",
|
||
configSource: "config/unidesk-cli.yaml#gc owns retention windows, include defaults, worktree roots/baseRef, scan budgets, output limits and .state allowlist roots",
|
||
protected: ["PostgreSQL PGDATA", "Docker volumes", "Docker images", ".state/recovery", ".state/codex-queue/codex-home", ".state/deploy/work", ".state/baidu-netdisk", "Codex auth/config", "active/unmerged/dirty worktree/runtime image/snapshot", "D601 registry storage"],
|
||
database: "default gc run is database diagnostic-only; gc db-trace is the explicit trace telemetry retention path and requires --confirm plus --vacuum-full",
|
||
},
|
||
options: {
|
||
"--logs-keep-days N": "delete UniDesk file logs older than N days; default 7",
|
||
"--file-log-max-bytes SIZE": "compact newer large file logs above SIZE; default 50M",
|
||
"--file-log-tail-bytes SIZE": "tail bytes kept when compacting file logs; default 20M",
|
||
"--docker-log-max-bytes SIZE": "truncate Docker json-file logs above SIZE; default 50M",
|
||
"--journal-target-size SIZE": "vacuum systemd journal to SIZE; default 512M",
|
||
"--build-cache-until DURATION": "prune Docker builder cache unused for duration; default 24h",
|
||
"--build-cache-all": "prune all Docker builder cache without an until filter",
|
||
"--tmp-min-age-hours N": "delete allowlisted /tmp artifacts older than N hours; default 24",
|
||
"--core-dump-min-age-hours N": "remote only: delete untracked allowlisted core.<pid> dumps older than N hours; default 1",
|
||
"--no-core-dumps": "remote only: do not include scoped core dump cleanup candidates",
|
||
"--include-hwlab-registry": "remote G14 only: opt in to conservative HWLAB registry tag and stale manifest-revision retention plus official registry garbage-collect",
|
||
"--registry-gc-only": "remote G14 only: run official registry garbage-collect without deleting additional tags; intended for interrupted registry retention recovery",
|
||
"--registry-keep-per-repo N": "remote registry only: keep at least N newest tags per service repo; default 20, minimum 1",
|
||
"--registry-min-age-hours N": "remote registry only: keep all tags newer than N hours; default 48, minimum 0",
|
||
"--target-use-percent N": "evaluate whether planned candidates can reduce root filesystem use to N%; reports required reclaim, projected use, shortfall and safe-stop decision",
|
||
"--job-id ID": "remote status only: inspect a long-running remote gc job",
|
||
"--limit N": "number of candidates returned and executed by run when --full is not set; default 50",
|
||
"--result-limit N": "number of per-candidate run results returned when --full is not set; default 50",
|
||
"--full|--raw": "return and run against all candidates rather than the default bounded page",
|
||
"--include-browser-cache": "also remove /root/.unidesk/.state/playwright-browsers cache",
|
||
"--include-tool-caches": "local and remote explicit opt-in: remove rebuildable npm/npx/Bun package caches from fixed allowlisted paths",
|
||
"--include-state-artifacts": "manual local gc only: opt in to stale UniDesk .state artifact retention for allowlisted diagnostic files and deploy artifact direct directories",
|
||
"--state-artifact-keep-days N": "keep recent UniDesk .state artifacts for N days; default 14; must be a positive integer",
|
||
"--include-state-stale-scratch": "manual local gc only: opt in to YAML allowlisted stale .state scratch roots; roots and keepHours come from config/unidesk-cli.yaml#gc",
|
||
"--include-codex-sessions": "manual local gc only: delete inactive session files under YAML codexSessions.root after codexSessions.keepHours; never deletes auth/config",
|
||
"--include-merged-worktrees": "manual local gc only: remove inactive .worktree entries whose HEAD is merged into or cherry-equivalent to YAML baseRef; run rechecks full clean status before deletion",
|
||
"--worktree-scan-budget-ms N": "temporary override for YAML mergedWorktrees.scanBudgetMs; over-budget worktrees are protected, not deleted",
|
||
"--worktree-cherry-check-timeout-ms N": "temporary override for YAML mergedWorktrees.cherryCheckTimeoutMs",
|
||
"db-trace --before-date YYYY-MM-DD": "plan or delete default trace telemetry event types before the date",
|
||
"db-trace run --vacuum-full": "rewrite public.oa_events after deletion so df can reclaim disk; requires maintenance window",
|
||
"policy plan|install": "render or install journald caps and a daily low-risk gc systemd timer from config/unidesk-cli.yaml#gc.policyTimer",
|
||
"remote <providerId> plan|run": "run bounded GC through UniDesk SSH passthrough on a provider host; G14 protects HWLAB k3s/runtime/PVC/workspace paths, and HWLAB registry retention is explicit opt-in with workload-ref, digest-closure, recent-tag and per-repo tag protection",
|
||
"--no-file-logs|--no-docker-logs|--no-journal|--no-build-cache|--no-tmp|--no-db-summary": "disable one collector",
|
||
},
|
||
reference: "docs/reference/gc.md",
|
||
};
|
||
}
|
||
|
||
function commanderHelp(): unknown {
|
||
return {
|
||
command: "commander contract|plan|smoke|approval",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts commander contract",
|
||
"bun scripts/cli.ts commander plan --dry-run [--session-id id]",
|
||
"bun scripts/cli.ts commander smoke --dry-run [--session-id id]",
|
||
"bun scripts/cli.ts commander approval request --action <action> --dry-run [--reason text] [--task-id id]",
|
||
],
|
||
description: "Inspect the local host Codex commander skeleton contract, dry-run planner, no-daemon smoke validation plan, state helpers, trace summary aggregator, and approval draft preview.",
|
||
boundary: [
|
||
"the current skeleton is local-only and never attaches to live bridges",
|
||
"dry-run commands never open SSH, PTY, or stdio bridges",
|
||
"high-risk actions only produce a <=200 char Chinese ClaudeQQ approval draft and notification-path-unavailable blocker",
|
||
"authorized future sends must use backend-core /api/microservices/claudeqq/proxy, not local skill or powershell paths",
|
||
"token and secret values must never be printed",
|
||
],
|
||
reference: "docs/reference/host-codex-commander.md",
|
||
};
|
||
}
|
||
|
||
function scheduleHelp(): unknown {
|
||
return {
|
||
command: "schedule list|get|runs|run|retry-run|delete|upsert-pgdata-backup",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts schedule list",
|
||
"bun scripts/cli.ts schedule get <id>",
|
||
"bun scripts/cli.ts schedule runs --limit N",
|
||
"bun scripts/cli.ts schedule runs [scheduleId] [--limit N]",
|
||
"bun scripts/cli.ts schedule run <id> [--wait-ms N]",
|
||
"bun scripts/cli.ts schedule retry-run <failedRunId>",
|
||
"bun scripts/cli.ts schedule delete <id>",
|
||
"bun scripts/cli.ts schedule upsert-pgdata-backup [--time HH:MM] [--remote-base path]",
|
||
],
|
||
description: "Manage backend-core scheduled tasks and run history through the private core API. Global runs use schedule runs --limit N; schedule-specific runs pass a non-numeric schedule id.",
|
||
};
|
||
}
|
||
|
||
function codexHelp(): unknown {
|
||
return {
|
||
command: "codex trace|deploy|submit|task|tasks|unread|output|read|dev-ready|skills-sync|execution-plane|pr-preflight|judge|steer|resume|interrupt|cancel|queues|queue|move",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts codex trace list [--root ~/.codex] [--limit 30]",
|
||
"bun scripts/cli.ts codex trace active [--root ~/.codex]",
|
||
"bun scripts/cli.ts codex trace grep --session <id> --pattern 'playwright|auth-login-failed' [--since ISO]",
|
||
"bun scripts/cli.ts codex trace grep --session <id> --messages --pattern 'Playwright|web-probe'",
|
||
"bun scripts/cli.ts codex trace grep --session <id> --failed-only [--tool exec_command]",
|
||
"bun scripts/cli.ts codex trace grep --pattern 'playwright|auth-login-failed' [--file sessions/...jsonl] [--since ISO]",
|
||
"bun scripts/cli.ts codex trace collect [--root ~/.codex] [--output /root/.unidesk/.state/codex-trace/<timestamp>] [--limit 30]",
|
||
"bun scripts/cli.ts codex trace show --session <id> [--root ~/.codex] [--tail-bytes 12000]",
|
||
"bun scripts/cli.ts codex deploy <commitId> # disabled legacy deployment entry",
|
||
"bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
|
||
"bun scripts/cli.ts agentrun describe aipodspec/Artificer",
|
||
"bun scripts/cli.ts agentrun create task --aipod Artificer --prompt-stdin",
|
||
"bun scripts/cli.ts agentrun apply -f - --dry-run",
|
||
"bun scripts/cli.ts agentrun logs session/<sessionId> --tail 100",
|
||
"bun scripts/cli.ts codex submit # frozen legacy write entry; returns legacy-code-queue-frozen",
|
||
"bun scripts/cli.ts codex task <taskId> [--detail] [--trace --tail|--from-start|--after-seq N|--before-seq N --limit N] [--full]",
|
||
"bun scripts/cli.ts codex tasks [--view commander|supervisor|full] [--queue id] [--status succeeded,running] [--unread|--unread-only] [--limit N] [--before-id id]",
|
||
"bun scripts/cli.ts codex unread [--repo owner/name] [--issue N] [--limit N]",
|
||
"bun scripts/cli.ts codex unread mark-read [--repo owner/name] [--issue N] [--limit N] --confirm",
|
||
"bun scripts/cli.ts codex output <taskId> [--tail|--from-start|--after-seq N|--before-seq N --limit N] [--full-text]",
|
||
"bun scripts/cli.ts codex read <taskId>",
|
||
"bun scripts/cli.ts codex dev-ready",
|
||
"bun scripts/cli.ts codex skills-sync --dry-run [--full]",
|
||
"bun scripts/cli.ts codex execution-plane [--full|--raw]",
|
||
"bun scripts/cli.ts codex pr-preflight [--remote] [--push-dry-run --push-dry-run-ref refs/heads/probe/<name>] [--pr-create-dry-run --pr-create-dry-run-head <head>] [--issue N] [--full|--raw]",
|
||
"bun scripts/cli.ts codex judge <taskId> --attempt N [--dry-run] [--include-prompt]",
|
||
"bun scripts/cli.ts agentrun send session/<sessionId> --prompt-stdin",
|
||
"bun scripts/cli.ts codex steer <taskId> # frozen legacy write entry",
|
||
"bun scripts/cli.ts codex resume <taskId> # frozen legacy write entry",
|
||
"bun scripts/cli.ts codex steer-confirm <taskId> --steer-id <id> [--raw]",
|
||
"bun scripts/cli.ts codex interrupt|cancel <taskId>",
|
||
"bun scripts/cli.ts codex queues [--commander] [--full|--all] [--limit N] [--page N|--offset N] # legacy archive read-only",
|
||
],
|
||
promptInput: {
|
||
recommended: ["--prompt-stdin", "--prompt-file"],
|
||
stdin: "Use a quoted heredoc or pipe when the prompt contains newlines, quotes, backticks, JSON, Markdown tables, or shell-sensitive text.",
|
||
file: "Use --prompt-file for reviewed or reusable dispatch prompts; --file is an alias.",
|
||
positional: "Keep positional prompt usage to short one-line smoke prompts only.",
|
||
sourceRule: "Exactly one prompt source is accepted: positional prompt, --prompt-file, or --prompt-stdin.",
|
||
},
|
||
executionMode: {
|
||
validModes: ["default", "windows-native"],
|
||
boundary: "Legacy Code Queue submit is frozen; new runtime placement is selected by AgentRun task payloads.",
|
||
permissionVisibility: "Legacy Code Queue read commands expose historical runner metadata only; new tasks use AgentRun resource primitives.",
|
||
},
|
||
submitSummary: {
|
||
default: "codex submit/enqueue now returns ok=false, frozen=true, degradedReason=legacy-code-queue-frozen and AgentRun replacement commands.",
|
||
replacement: "Use bun scripts/cli.ts agentrun apply -f - with a quoted YAML heredoc for structured work, or agentrun create task --aipod Artificer --prompt-stdin for one prompt task.",
|
||
noDoubleWrite: "UniDesk does not mirror AgentRun submissions into old Code Queue and does not migrate old history into AgentRun.",
|
||
rawDrillDown: "Use codex tasks/task/output/read/unread/queues only for legacy archive inspection.",
|
||
},
|
||
readOutput: {
|
||
default: "codex read marks a terminal task read and returns terminal metadata, final response, last error/judge, counts, and drill-down commands.",
|
||
disclosure: "Full prompt, tool logs, and feedback prompts are not printed by codex read; use codex task/detail/trace/output for progressive disclosure.",
|
||
},
|
||
localTrace: {
|
||
defaultRoot: "~/.codex",
|
||
defaultIncludes: ["sessions/*.jsonl", "history.jsonl", "shell_snapshots", "*.log", "trace-named text files"],
|
||
defaultExcludes: ["auth/config", "sqlite", "cache/.tmp/generated_images/plugins/skills"],
|
||
active: "codex trace active finds open Codex session JSONL files from /proc without requiring lsof and prints copyable session ids.",
|
||
grep: "codex trace grep supports --session <id>, --messages, --tools, --tool <name>, and --failed-only. It defaults to active/recent sessions, uses rg/raw prefiltering for speed, prioritizes messages/tool inputs, and folds tool outputs unless --include-output or -o wide is explicit.",
|
||
output: "Default output is concise text/table; use -o json|yaml|name|wide for machine or wider output.",
|
||
collectOutput: "/root/.unidesk/.state/codex-trace/<timestamp>/manifest.json",
|
||
note: "Use --root <dir> to scan another local Codex trace directory; collect copies bounded files locally and never uploads or deletes source files.",
|
||
},
|
||
unreadTriage: {
|
||
default: "codex unread is read-only by default and returns counts, buckets, compact task rows, and one-time drill-down templates; per-task command blocks require --full or list.",
|
||
mutationGuard: "Batch mark-read is blocked unless the explicit mark-read subcommand is used with --confirm; use codex read <taskId> for per-task review.",
|
||
disclosure: "Raw prompt, final response, trace and output are omitted; use the returned task/detail/trace/output/read commands for drill-down.",
|
||
},
|
||
queuesSummary: {
|
||
default: "codex queues defaults to commander-first summary mode; --commander is an explicit alias, while --full keeps the same bounded queue rows with compatibility metadata.",
|
||
commanderPath: "data.queues.commander",
|
||
stableRowsPath: "data.queues.items[]",
|
||
fields: ["activeRunnerCount", "source", "target=15", "slotDeficit", "runningTasks", "heartbeat.fresh", "heartbeat.risk", "heartbeat.staleRecoveryCandidates", "queuedCount"],
|
||
rule: "Use data.queues.commander.activeRunnerCount and slotDeficit for quick capacity decisions; activeQueueIds are scheduler-local and can be empty during split-brain live.",
|
||
},
|
||
executionPlane: {
|
||
command: "bun scripts/cli.ts codex execution-plane",
|
||
mutation: false,
|
||
kubeconfig: "/etc/rancher/k3s/k3s.yaml",
|
||
namespace: "unidesk",
|
||
defaultPolicy: "compact drift/residual summary; deployments, pods and services require --full, raw sanitized observations require --raw",
|
||
blockers: ["deployment-drift", "deprecated-compose-residual", "d601-k3s-guard-blocked"],
|
||
},
|
||
examples: {
|
||
agentRunCommander: "bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
|
||
agentRunAipod: "bun scripts/cli.ts agentrun create task --aipod Artificer --prompt-stdin",
|
||
agentRunSubmit: "bun scripts/cli.ts agentrun apply -f - --dry-run",
|
||
agentRunTrace: "bun scripts/cli.ts agentrun logs session/<sessionId> --tail 100",
|
||
frozenLegacySubmit: "bun scripts/cli.ts codex submit --prompt-file /tmp/code-queue-prompt.md",
|
||
},
|
||
disclosure: {
|
||
defaultPolicy: "low-noise JSON by default; write commands confirm persistence, list/detail/output commands return bounded summaries with drill-down commands",
|
||
expand: ["codex task <taskId> --full", "codex task <taskId> --trace --limit N", "codex output <taskId> --after-seq N --limit N --full-text", "codex tasks --view full --limit N", "codex skills-sync --dry-run --full", "codex execution-plane --full"],
|
||
},
|
||
activityFields: {
|
||
path: "data.queues.activity and data.supervisor.activity",
|
||
effectiveActiveTaskCount: "Commander-facing active count derived from database active/running tasks and heartbeat-fresh runners.",
|
||
commanderConcurrency: "Use data.supervisor.commanderConcurrency.activeRunnerCount or data.queues.commanderConcurrency.activeRunnerCount for concurrency decisions; the block states the 15-runner arithmetic and intervention signal.",
|
||
schedulerLocalActiveQueueCount: "Only queues currently visible in this scheduler-local active-run slot view; zero does not override DB or heartbeat activity.",
|
||
heartbeatFreshActiveTaskCount: "Heartbeat-effective active runner count used to avoid split-brain zero-active mistakes.",
|
||
},
|
||
supervisorView: {
|
||
activeRunning: "Use data.supervisor.activeRunning.count for exact active running+judging count when exact=true; data.supervisor.running.returned is only the compact row page.",
|
||
redline: "data.supervisor.activeRunning.redline names the count field, routine target, burst redline, hard redline, and decisionReady flag.",
|
||
limitSemantics: "filters.requestedLimit preserves the user input; filters.limit/effectiveLimit shows the capped query budget; section outputBudget/rowPage show returned-row caps.",
|
||
},
|
||
description: "Operate legacy Code Queue as a read-only archive through bounded task/output/read/unread/queues views. New task dispatch, retry/resume, queue mutation, move, and workdir mutation are frozen and replaced by AgentRun resource primitives via bun scripts/cli.ts agentrun get|describe|events|logs|result|ack|cancel|dispatch|create|apply|send.",
|
||
};
|
||
}
|
||
|
||
function jobHelp(): unknown {
|
||
return {
|
||
command: "job|jobs list|status|get|read|cancel",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts job list [--limit N] [--include-command]",
|
||
"bun scripts/cli.ts job status <jobId|latest> [--tail-bytes N]",
|
||
"bun scripts/cli.ts jobs get <jobId|latest> [--tail-bytes N]",
|
||
"bun scripts/cli.ts job cancel <jobId>",
|
||
],
|
||
description: "Inspect or cancel fire-and-forget job state from /root/.unidesk/.state/jobs with structured progress summaries and bounded log tails. `jobs get/read` are compatibility aliases for `job status`; server lifecycle commands return this drill-down by default and reserve full JSON for --full/--raw.",
|
||
};
|
||
}
|
||
|
||
function debugHelp(): unknown {
|
||
return {
|
||
command: "debug health|ssh-pool|egress-proxy|provider-rootfs|dispatch|task",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts debug health",
|
||
"bun scripts/cli.ts debug ssh-pool <providerId>",
|
||
"bun scripts/cli.ts debug egress-proxy <providerId>",
|
||
"bun scripts/cli.ts debug provider-rootfs <providerId>",
|
||
"bun scripts/cli.ts debug dispatch [providerId] [docker.ps|provider.upgrade|host.ssh|microservice.http|echo] [--wait-ms N]",
|
||
"bun scripts/cli.ts debug task <taskId|latest>",
|
||
],
|
||
description: "Debug the real core/provider/dispatch paths. ssh-pool and egress-proxy are separate so SSH/control readiness is not conflated with long download tunnel activity; do not use debug commands as formal TEST.md acceptance steps.",
|
||
};
|
||
}
|
||
|
||
function networkHelp(): unknown {
|
||
return {
|
||
command: "network perf",
|
||
output: "json",
|
||
usage: "bun scripts/cli.ts network perf [--service id --path /api/path --count N --concurrency N --label text]",
|
||
description: "Benchmark frontend/backend/provider user-service networking with bounded JSON latency summaries.",
|
||
};
|
||
}
|
||
|
||
function e2eHelp(): unknown {
|
||
return {
|
||
command: "e2e run",
|
||
output: "json",
|
||
usage: "bun scripts/cli.ts e2e run [--only pattern[,pattern...]] [--skip pattern[,pattern...]]",
|
||
description: "Run selected public/internal/Playwright E2E checks; use filters for focused iteration and full run for final regression.",
|
||
};
|
||
}
|
||
|
||
function devEnvHelp(): unknown {
|
||
return {
|
||
command: "dev-env validate|prewarm-images|worktree add",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts dev-env validate [--manifest path] [--kubectl-dry-run]",
|
||
"bun scripts/cli.ts dev-env prewarm-images [--image image] [--target <id>] [--no-pull] [--dry-run]",
|
||
"bun scripts/cli.ts dev-env worktree add .worktree/<task> --branch <branch> [--from origin/master] [--copy-local] [--overwrite-local] [--json]",
|
||
],
|
||
description: "Validate D601 unidesk-dev guardrails, prewarm foundation images, or create task worktrees with allowlisted local config copying.",
|
||
};
|
||
}
|
||
|
||
function artifactRegistryHelp(): unknown {
|
||
return {
|
||
command: "artifact-registry plan|render|status|health|install|deploy-backend-core|deploy-service",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts artifact-registry plan [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry render [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry status [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry health [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry install [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --service baidu-netdisk --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --service frontend --env prod --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --service frontend --env dev --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service decision-center --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service project-manager --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service oa-event-flow --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service code-queue-mgr --commit <full-sha> --dry-run [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service findjob --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service pipeline --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service met-nonlinear --commit <full-sha> --dry-run [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service met-nonlinear --commit <full-sha> --dry-run [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service k3sctl-adapter --commit <full-sha> --dry-run [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service mdtodo --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env prod --service claudeqq --commit <full-sha> [--dry-run] [--run-now] [--target <id>]",
|
||
"bun scripts/cli.ts artifact-registry deploy-service --env dev --service code-queue --commit <full-sha> --dry-run [--target <id>]",
|
||
],
|
||
description: "Manage the declaration, rendered files and readonly checks for the D601 host-managed CNCF Distribution artifact registry.",
|
||
boundary: [
|
||
"registry endpoint is D601 loopback 127.0.0.1:5000 only",
|
||
"service is host-managed by systemd + Docker Compose, not k3s-managed",
|
||
"install writes the rendered host unit/config and starts the registry",
|
||
"deploy-backend-core only pulls commit-pinned backend-core artifacts and does not build backend-core on the master server",
|
||
"deploy-service currently supports backend-core, baidu-netdisk, prod/dev frontend, decision-center, mdtodo, claudeqq, project-manager, oa-event-flow, code-queue-mgr, findjob, pipeline, met-nonlinear, k3sctl-adapter, and dev-only code-queue as standardized consumers; Todo Note uses NC01 PaC/Argo",
|
||
"findjob and pipeline have D601 direct dev/prod Compose artifact consumers; met-nonlinear is runtime-verification blocked; k3sctl-adapter is supervisor-only",
|
||
"code-queue has no prod artifact deploy target; dev requests are dry-run evidence only unless a human operator or supervisor authorizes DEV apply outside Code Queue",
|
||
"status and health use provider-gateway Host SSH readonly checks",
|
||
],
|
||
legacyEntrypoints: {
|
||
"deploy-backend-core": {
|
||
deprecated: true,
|
||
enabled: false,
|
||
replacement: "bun scripts/cli.ts deploy apply --env prod --service backend-core --commit <full-sha>",
|
||
},
|
||
},
|
||
};
|
||
}
|
||
|
||
function agentRunHelpSummary(): unknown {
|
||
return {
|
||
command: "agentrun get|describe|events|logs|result|ack|cancel|dispatch|create|apply|send|control-plane|git-mirror",
|
||
output: "human by default; use -o json|yaml or --raw",
|
||
usage: [
|
||
"bun scripts/cli.ts agentrun get tasks --queue commander --limit 20",
|
||
"bun scripts/cli.ts agentrun describe task/<taskId>",
|
||
"bun scripts/cli.ts agentrun events run/<runId> --after-seq 0 --limit 100",
|
||
"bun scripts/cli.ts agentrun logs session/<sessionId> --tail 100",
|
||
"bun scripts/cli.ts agentrun result run/<runId> --command <commandId>",
|
||
"bun scripts/cli.ts agentrun ack task/<taskId>",
|
||
"bun scripts/cli.ts agentrun dispatch task/<taskId>",
|
||
"bun scripts/cli.ts agentrun create task --aipod Artificer --prompt-stdin",
|
||
"bun scripts/cli.ts agentrun control-plane status",
|
||
],
|
||
description: "Operate AgentRun v0.1 resources with Kubernetes-style verbs and progressive disclosure. Legacy queue/runs/commands/runner/sessions bridge groups remain for raw compatibility.",
|
||
};
|
||
}
|
||
|
||
function platformInfraHelpSummary(): unknown {
|
||
return {
|
||
command: "platform-infra sub2api|egress-proxy|langbot|n8n|webterm|wechat-archive|gitea ...",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts platform-infra sub2api plan",
|
||
"bun scripts/cli.ts platform-infra sub2api status [--full|--raw]",
|
||
"bun scripts/cli.ts platform-infra sub2api codex-pool validate",
|
||
"bun scripts/cli.ts platform-infra sub2api codex-pool trace --request-id <requestId>",
|
||
"bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-image status",
|
||
"bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-probe --account unidesk-codex-hy --confirm",
|
||
"bun scripts/cli.ts platform-infra sub2api codex-pool sentinel-report",
|
||
"bun scripts/cli.ts platform-infra egress-proxy benchmark --target D601 --profile no-mirror --confirm",
|
||
"bun scripts/cli.ts platform-infra egress-proxy benchmark-status --target D601 --profile no-mirror",
|
||
"bun scripts/cli.ts platform-infra egress-proxy traffic --target D601 --sample-seconds 15",
|
||
"bun scripts/cli.ts platform-infra egress-proxy k3s-build-benchmark --targets D601,D518 --profile no-mirror-600m --dry-run",
|
||
"bun scripts/cli.ts platform-infra langbot plan",
|
||
"bun scripts/cli.ts platform-infra langbot apply --confirm",
|
||
"bun scripts/cli.ts platform-infra langbot status",
|
||
"bun scripts/cli.ts platform-infra langbot query --path /api/v1/platform/bots",
|
||
"bun scripts/cli.ts platform-infra n8n plan",
|
||
"bun scripts/cli.ts platform-infra n8n apply --confirm",
|
||
"bun scripts/cli.ts platform-infra n8n status",
|
||
"bun scripts/cli.ts platform-infra n8n validate --full",
|
||
"bun scripts/cli.ts platform-infra webterm apply --confirm",
|
||
"bun scripts/cli.ts platform-infra webterm status",
|
||
"bun scripts/cli.ts platform-infra webterm validate",
|
||
"bun scripts/cli.ts platform-infra webterm logs --target local-7682 --tail 100",
|
||
"bun scripts/cli.ts platform-infra wechat-archive plan",
|
||
"bun scripts/cli.ts platform-infra wechat-archive apply --confirm",
|
||
"bun scripts/cli.ts platform-infra wechat-archive validate --full",
|
||
"bun scripts/cli.ts platform-infra wechat-archive pull --remote-path /UniDesk/WeChatArchive/...",
|
||
"bun scripts/cli.ts platform-infra wechat-archive wcf-host-status --full",
|
||
"bun scripts/cli.ts platform-infra wechat-archive collector-status --full",
|
||
"bun scripts/cli.ts platform-infra gitea status --target NC01",
|
||
"bun scripts/cli.ts platform-infra gitea validate --target NC01",
|
||
"bun scripts/cli.ts platform-infra gitea mirror status --target NC01",
|
||
"bun scripts/cli.ts platform-infra gitea mirror webhook status --target NC01",
|
||
"bun scripts/cli.ts platform-infra pipelines-as-code status --target NC01",
|
||
"bun scripts/cli.ts platform-infra pipelines-as-code history --target NC01 --limit 10",
|
||
],
|
||
description: "Operate platform-infra services such as Sub2API, shared egress-proxy benchmarks, LangBot, n8n, Web Terminal, WeChat archive workflows, the YAML-controlled Codex pool, and internal Gitea for the GH-1548/GH-1549 CI/CD migration.",
|
||
};
|
||
}
|
||
|
||
function hwlabNodeHelpSummary(): unknown {
|
||
return {
|
||
command: "hwlab nodes control-plane|git-mirror|hwpod-preinstall|observability|secret|test-accounts --node <node> --lane <lane>",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra plan --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra tools-image status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra argo status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra egress-benchmark --node NC01 --lane v03 --profile no-mirror --confirm",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra ci-build-benchmark --node NC01 --lane v03 --profile no-mirror-full --confirm",
|
||
"bun scripts/cli.ts hwlab nodes control-plane infra ci-build-benchmark status --node NC01 --lane v03 --profile no-mirror-full",
|
||
"bun scripts/cli.ts hwlab nodes control-plane status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes git-mirror status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes hwpod-preinstall plan --node NC01 --lane v03 --dry-run",
|
||
"bun scripts/cli.ts hwlab nodes observability performance-summary --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes secret status --node NC01 --lane v03 --name <secret>",
|
||
"bun scripts/cli.ts hwlab nodes test-accounts status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab nodes test-accounts sync --node NC01 --lane v03 --confirm",
|
||
],
|
||
description: "Operate NC01 HWLAB v0.3 runtime prerequisites from YAML source truth. The infra subcommand manages node-local CI/CD, git-mirror, public Dockerfile tools image, egress benchmarks, and declarative Argo CD prerequisites; hwpod-preinstall renders NC01/v03 HWPOD/MDTODO/gateway configRefs without runtime mutation; observability reads runtime metrics and authenticated Web Performance summaries; test-accounts prepares UniDesk YAML-declared admin/test account API keys with redacted sourceRef/fingerprint output. Web probe commands moved to top-level `bun scripts/cli.ts web-probe`.",
|
||
};
|
||
}
|
||
|
||
function webProbeHelpSummary(): unknown {
|
||
return {
|
||
command: "web-probe run|script|observe|sentinel --node <node> --lane <lane>",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts web-probe run --node NC01 --lane v03 --wait-messages-ms 1000",
|
||
"bun scripts/cli.ts web-probe observe start --node NC01 --lane v03 --target-path /workbench --sample-interval-ms 5000",
|
||
"bun scripts/cli.ts web-probe observe collect webobs-xxxx --view turn-summary",
|
||
"bun scripts/cli.ts web-probe observe collect webobs-xxxx --view timeline --turn 1",
|
||
"bun scripts/cli.ts web-probe sentinel plan --node NC01 --lane v03 --dry-run",
|
||
"bun scripts/cli.ts web-probe sentinel inspect-url 'https://monitor.pikapython.com/?run=sentinel-run-xxxx'",
|
||
"bun scripts/cli.ts web-probe sentinel inspect-id trc_xxxx --node NC01 --lane v03 --sentinel jd01-web-probe-sentinel",
|
||
],
|
||
description: "Run target node/lane HWLAB Cloud Web probes, long observe/analyze sessions, project-management MDTODO commands, and Web sentinel YAML-first control through a single top-level implementation. Monitor-web links and evidence ids should enter through sentinel inspect-url/inspect-id before report or observe drill-down.",
|
||
};
|
||
}
|
||
|
||
function cicdHelpSummary(): unknown {
|
||
return {
|
||
command: "cicd status --node <NODE>",
|
||
output: "text by default; use --json, --raw, or -o json|yaml for machine output",
|
||
usage: [
|
||
"bun scripts/cli.ts cicd status --node NC01",
|
||
"bun scripts/cli.ts cicd status --node NC01 --full",
|
||
],
|
||
description: "Node-level CI/CD status is the primary read path for PaC-migrated consumers. Gitea Actions and branch-follower are archived diagnostics and are not delivery or closeout paths.",
|
||
};
|
||
}
|
||
|
||
function hwlabLegacyRuntimeHelpSummary(): unknown {
|
||
return {
|
||
command: "hwlab g14 retirement",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts hwlab g14 retirement status",
|
||
"bun scripts/cli.ts hwlab g14 retirement plan",
|
||
],
|
||
description: "Archived legacy helper surface. Current HWLAB development and deployment use NC01 node commands.",
|
||
};
|
||
}
|
||
|
||
function hwlabHelpSummary(): unknown {
|
||
return {
|
||
command: "hwlab nodes|g14|cd",
|
||
output: "json",
|
||
usage: [
|
||
"bun scripts/cli.ts hwlab nodes control-plane status --node NC01 --lane v03",
|
||
"bun scripts/cli.ts hwlab cd audit --env dev",
|
||
],
|
||
description: "HWLAB operations. Current runtime work uses NC01 node commands; old cd/g14 surfaces are archived diagnostics only.",
|
||
};
|
||
}
|
||
|
||
function helpFallback(help: unknown, error: unknown): unknown {
|
||
if (typeof help !== "object" || help === null || Array.isArray(help)) return help;
|
||
return {
|
||
...help,
|
||
degraded: true,
|
||
degradedReason: "help-module-load-failed",
|
||
error: error instanceof Error ? error.message : String(error),
|
||
};
|
||
}
|
||
|
||
async function loadHelp(loader: () => Promise<unknown>, fallback: unknown): Promise<unknown> {
|
||
try {
|
||
return await loader();
|
||
} catch (error) {
|
||
return helpFallback(fallback, error);
|
||
}
|
||
}
|
||
|
||
export async function staticNamespaceHelp(args: string[]): Promise<unknown | null> {
|
||
const [top, sub] = args;
|
||
if (!args.slice(1).some(isHelpToken)) return null;
|
||
if (top === "config") return configHelp();
|
||
if (top === "health") return healthHelp();
|
||
if (top === "microservice") return microserviceHelp();
|
||
if (top === "decision" || top === "decision-center") return decisionHelp();
|
||
if (top === "provider") return providerHelp();
|
||
if (top === "gc") return gcHelp();
|
||
if (top === "commander") return commanderHelp();
|
||
if (top === "schedule") return scheduleHelp();
|
||
if (top === "codex" && sub === "trace") return null;
|
||
if (top === "codex") return codexHelp();
|
||
if (top === "job") return jobHelp();
|
||
if (top === "debug") return debugHelp();
|
||
if (top === "network") return networkHelp();
|
||
if (top === "e2e") return e2eHelp();
|
||
if (top === "dev-env") return devEnvHelp();
|
||
if (top === "artifact-registry") return artifactRegistryHelp();
|
||
if (top === "auth-broker") return authBrokerHelp();
|
||
if (top === "gh") return ghScopedHelp(args.slice(1)) ?? ghHelp();
|
||
if (top === "cicd") return loadHelp(async () => (await import("./cicd")).cicdHelp(), cicdHelpSummary());
|
||
if (top === "agentrun") return loadHelp(async () => (await import("./agentrun")).agentRunHelp(), agentRunHelpSummary());
|
||
if (top === "platform-infra" && (sub === "pipelines-as-code" || sub === "pac")) {
|
||
return loadHelp(
|
||
async () => (await import("./platform-infra-pipelines-as-code")).runPlatformInfraPipelinesAsCodeCommand({} as never, args.slice(2)),
|
||
platformInfraHelpSummary(),
|
||
);
|
||
}
|
||
if (top === "platform-infra" && sub === "gitea") {
|
||
return loadHelp(
|
||
async () => (await import("./platform-infra-gitea")).runPlatformInfraGiteaCommand({} as never, args.slice(2)),
|
||
platformInfraHelpSummary(),
|
||
);
|
||
}
|
||
if (top === "platform-infra" && sub === "observability") {
|
||
return loadHelp(
|
||
async () => (await import("./platform-infra-observability")).runPlatformObservabilityCommand({} as never, args.slice(2)),
|
||
platformInfraHelpSummary(),
|
||
);
|
||
}
|
||
if (top === "platform-infra") return loadHelp(async () => (await import("./platform-infra")).platformInfraHelp(), platformInfraHelpSummary());
|
||
if (top === "platform-db") return platformDbHelp();
|
||
if (top === "secrets") return secretsHelp();
|
||
if (top === "web-probe") return loadHelp(async () => (await import("./web-probe")).webProbeHelp(), webProbeHelpSummary());
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes") && args[2] === "web-probe") return null;
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes") && args[2] === "control-plane" && args[3] === "infra") {
|
||
return loadHelp(async () => (await import("./hwlab-node-control-plane")).hwlabNodeControlPlaneInfraHelp(), hwlabNodeHelpSummary());
|
||
}
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes") && args[2] === "control-plane" && (args[3] === "platform-maintenance" || args[3] === "legacy-cicd")) {
|
||
const scope = args[3];
|
||
return loadHelp(async () => (await import("./hwlab-node-help")).hwlabNodeHelp(scope), hwlabNodeHelpSummary());
|
||
}
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes") && args[2] === "test-accounts") {
|
||
return loadHelp(async () => (await import("./hwlab-test-accounts")).hwlabTestAccountsHelp(), hwlabNodeHelpSummary());
|
||
}
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes") && args[2] === "hwpod-preinstall") {
|
||
return loadHelp(async () => (await import("./hwlab-node-hwpod-preinstall")).hwlabNodeHwpodPreinstallHelp(), hwlabNodeHelpSummary());
|
||
}
|
||
if (top === "hwlab" && (sub === "node" || sub === "nodes")) return loadHelp(async () => (await import("./hwlab-node")).hwlabNodeHelp(), hwlabNodeHelpSummary());
|
||
if (top === "hwlab" && sub === "g14") return loadHelp(async () => (await import("./hwlab-legacy-runtime")).hwlabLegacyRuntimeHelp(), hwlabLegacyRuntimeHelpSummary());
|
||
if (top === "hwlab") return loadHelp(async () => (await import("./hwlab-cd")).hwlabHelp(), hwlabHelpSummary());
|
||
return null;
|
||
}
|