import { readFileSync } from "node:fs"; import { agentRunHelp } from "./src/agentrun"; import { rootHelp } from "./src/help"; function assertCondition(condition: unknown, message: string, detail: unknown = {}): void { if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`); } const agentRunUsage = Array.isArray((agentRunHelp() as { usage?: unknown }).usage) ? ((agentRunHelp() as { usage: unknown[] }).usage).map(String) : []; assertCondition( agentRunUsage.some((line) => line.includes("control-plane cleanup-runs --min-age-minutes 30 --limit 200 --dry-run")) && agentRunUsage.some((line) => line.includes("control-plane cleanup-runs --min-age-minutes 30 --limit 200 --confirm")) && agentRunUsage.some((line) => line.includes("control-plane cleanup-released-pvs --limit 200 --dry-run")) && agentRunUsage.some((line) => line.includes("control-plane cleanup-released-pvs --limit 200 --confirm")), "AgentRun help must expose controlled CI workspace retention commands", agentRunUsage, ); assertCondition( agentRunUsage.some((line) => line.includes("control-plane status --pipeline-run agentrun-v01-ci-")) && agentRunUsage.some((line) => line.includes("control-plane status --source-commit ")), "AgentRun help must expose targeted control-plane status drill-down options", agentRunUsage, ); assertCondition( agentRunUsage.some((line) => line.includes("agentrun get tasks --queue commander --limit 20")) && agentRunUsage.some((line) => line.includes("agentrun describe task/")) && agentRunUsage.some((line) => line.includes("agentrun events run/ --after-seq 0 --limit 100")) && agentRunUsage.some((line) => line.includes("agentrun logs session/ --tail 100")), "AgentRun help must expose Kubernetes-style resource observation primitives", agentRunUsage, ); assertCondition( !agentRunUsage.some((line) => line.includes("agentrun v01")), "AgentRun help must hide the v01 lane from user-facing CLI entrypoints", agentRunUsage, ); assertCondition( agentRunUsage.some((line) => line.includes("agentrun result run/ --command ")) && agentRunUsage.some((line) => line.includes("agentrun ack task/ --reader-id cli")) && agentRunUsage.some((line) => line.includes("agentrun cancel task/ --reason --dry-run")) && agentRunUsage.some((line) => line.includes("agentrun dispatch task/")) && agentRunUsage.some((line) => line.includes("agentrun create task --aipod Artificer --prompt-stdin")) && agentRunUsage.some((line) => line.includes("agentrun apply -f - --dry-run")) && agentRunUsage.some((line) => line.includes("agentrun steer session/ --prompt-stdin")) && agentRunUsage.some((line) => line.includes("agentrun send session/ --aipod Artificer --prompt-stdin")), "AgentRun help must expose resource lifecycle control primitives", agentRunUsage, ); assertCondition( (agentRunHelp() as { output?: unknown }).output === "human by default; use -o json|yaml or --raw for machine/debug output", "AgentRun help must declare human output as the default and machine output as opt-in", agentRunHelp(), ); const globalHelp = JSON.stringify(rootHelp()); assertCondition( globalHelp.includes("agentrun get|describe|events|logs|result|ack|cancel|dispatch|create|apply|steer|send"), "global help must index AgentRun v0.1 entrypoints", rootHelp(), ); const agentRunSource = readFileSync("scripts/src/agentrun.ts", "utf8"); const runtimeJsonFallback = "\"node <<'NODE' || printf '{}\\\\n'\""; assertCondition( agentRunSource.includes(runtimeJsonFallback) && agentRunSource.includes("const sourceCommit = params.find((entry) => entry?.name === 'revision')?.value || null;"), "AgentRun control-plane status must degrade empty runtime JSON snippets instead of failing the whole status probe", ); assertCondition( agentRunSource.includes('type AgentRunBridgeCaptureBackend = "local-backend-core-broker" | "remote-frontend-websocket"') && agentRunSource.includes('reason: "runner-environment"') && agentRunSource.includes('degradedReason: "capture-backend-unavailable"') && agentRunSource.includes('failureKind: "bridge-execution-environment"'), "AgentRun CLI bridge must use the remote frontend backend in runner/no-Docker environments and classify bridge failures separately", ); assertCondition( !agentRunSource.includes('degradedReason: "agentrun-cli-bridge-failed"'), "AgentRun CLI bridge must not collapse official AgentRun failures into bridge failures", ); assertCondition( agentRunSource.includes("const resourceArgs = action === undefined ? actionArgs : [action, ...actionArgs];") && agentRunSource.includes("const options = parseResourceOptions(resourceArgs);") && agentRunSource.includes("const file = options.file ?? requiredContext(\"apply\", \"-f |-\");"), "AgentRun resource parser must parse verb-level flags such as apply -f - before requiring runtime config", ); assertCondition( agentRunSource.includes('if (verb === "dispatch") return await resourceDispatch') && agentRunSource.includes('bridgeActionArgs, options') && agentRunSource.includes('runAgentRunRestCommand(config, "queue", ["dispatch"') && agentRunSource.includes('taskListState(options)') && agentRunSource.includes('["commander", "--reader-id", options.readerId'), "AgentRun resources must wrap task dispatch and keep default get tasks on active list visibility", ); assertCondition( agentRunSource.includes("function renderFailureLines(value: Record): string[]") && agentRunSource.includes('lines.push(`Failure: ${failureKind}`)') && agentRunSource.includes('lines.push(`Message: ${failureMessage}`)') && agentRunSource.includes("const failure = renderFailureLines(data);") && agentRunSource.includes("const failure = renderFailureLines(value);"), "AgentRun resource human output must expose failure kind and message without requiring JSON output", ); assertCondition( agentRunSource.includes("const effectiveLimit = options.tail ?? options.limit;") && agentRunSource.includes("resourceLogsTailResult(config, ref.name, effectiveLimit, options.fullText)") && agentRunSource.includes("clientTail: {") && agentRunSource.includes("return renderEventLike(command, result, { ...options, limit: effectiveLimit }, \"Log\""), "AgentRun logs must map --tail N into render-only client tailing for human and raw outputs", ); assertCondition( agentRunSource.includes("function rerunWithoutDryRun(command: string): string") && agentRunSource.includes("options.dryRun ? [rerunWithoutDryRun(command)] : undefined"), "AgentRun dry-run resource mutations must return resource-command follow-up instead of official bridge internals", ); console.log(JSON.stringify({ ok: true, checks: [ "AgentRun command help exposes cleanup-runs and cleanup-released-pvs", "AgentRun command help exposes targeted control-plane status drill-down options", "AgentRun command help exposes resource observation primitives", "AgentRun command help hides the v01 lane from user-facing CLI entrypoints", "AgentRun command help exposes resource lifecycle control primitives", "AgentRun command help declares human output by default", "global help indexes AgentRun v0.1 entrypoints", "AgentRun control-plane status degrades empty runtime JSON snippets", "AgentRun CLI bridge selects remote frontend backend in runner/no-Docker environments", "AgentRun CLI bridge keeps AgentRun failures distinct from bridge failures", "AgentRun resource parser supports apply -f -", "AgentRun resource task dispatch and active task list visibility", "AgentRun resource failure output is visible in human mode", "AgentRun logs tail is enforced by the render-only client", "AgentRun dry-run mutations keep resource-command follow-up", ], }));