189 lines
11 KiB
TypeScript
189 lines
11 KiB
TypeScript
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-<short-sha>"))
|
|
&& agentRunUsage.some((line) => line.includes("control-plane status --source-commit <full-sha>")),
|
|
"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/<taskId>"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun events run/<runId> --after-seq 0 --limit 100"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun logs session/<sessionId> --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/<runId> --command <commandId>"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun ack task/<taskId> --reader-id cli"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun cancel task/<taskId> --reason <text> --dry-run"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun dispatch task/<taskId>"))
|
|
&& 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/<sessionId> --prompt-stdin"))
|
|
&& agentRunUsage.some((line) => line.includes("agentrun send session/<sessionId> --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 <file>|-\");"),
|
|
"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, unknown>): 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 agentRunEventSummary(item: Record<string, unknown>, payload: Record<string, unknown>): string")
|
|
&& agentRunSource.includes("push(payload.failureKind)")
|
|
&& agentRunSource.includes("push(error.message)")
|
|
&& agentRunSource.includes("push(error.additionalDetails)")
|
|
&& agentRunSource.includes("push(payload.phase)")
|
|
&& agentRunSource.includes("function agentRunEventCommandId(item: Record<string, unknown>, payload: Record<string, unknown>): string"),
|
|
"AgentRun logs/events must render payload error, backend phase, and command id summaries by default",
|
|
);
|
|
|
|
assertCondition(
|
|
agentRunSource.includes("function commandOutputSummary(payload: Record<string, unknown>): string | null")
|
|
&& agentRunSource.includes("function summarizeStructuredCliOutput(value: Record<string, unknown>): string | null")
|
|
&& agentRunSource.includes("function parseJsonRecordFromText(raw: string): Record<string, unknown> | null")
|
|
&& agentRunSource.includes('if (type === "command_output")')
|
|
&& agentRunSource.includes("push(commandOutputSummary(payload))")
|
|
&& agentRunSource.includes('if (type !== "command_output")'),
|
|
"AgentRun command_output summaries must use a dedicated low-noise renderer instead of raw payload JSON",
|
|
);
|
|
|
|
assertCondition(
|
|
agentRunSource.includes("isLowSignalJsonField")
|
|
&& agentRunSource.includes('key === "generatedAt" || key === "cli" || key === "version" || key === "valuesRedacted" || key === "secretMaterialStored"')
|
|
&& agentRunSource.includes('firstPathText(value, ["action", "operation", "command", "kind"])')
|
|
&& agentRunSource.includes('"traceId", "lastTraceId", "trace.traceId", "trace.id", "body.traceId", "body.trace.id", "providerTrace.traceId", "runnerTrace.traceId"')
|
|
&& agentRunSource.includes('"sessionId", "session.sessionId", "body.sessionId", "workspace.selectedAgentSessionId", "workspace.selectedConversation.sessionId"')
|
|
&& agentRunSource.includes('"conversationId", "session.conversationId", "body.conversationId", "workspace.selectedConversationId", "workspace.selectedConversation.conversationId"')
|
|
&& agentRunSource.includes('"providerProfile", "backendProfile", "profile", "session.providerProfile", "workspace.providerProfile"')
|
|
&& agentRunSource.includes('"pipelineRun", "pipelineRunName", "pipelineRun.name", "pipeline.runName", "pipeline.name"')
|
|
&& agentRunSource.includes("function summarizePartialJsonCommandOutput(raw: string): string | null")
|
|
&& agentRunSource.includes("if (failure !== null || isFailureLikeStatus(status))"),
|
|
"AgentRun command_output summaries must prefer business fields and suppress metadata-only JSON headers",
|
|
);
|
|
|
|
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 logs/events expose payload error and backend phase summaries",
|
|
"AgentRun command_output summaries use a dedicated low-noise renderer",
|
|
"AgentRun command_output summaries prefer business fields over metadata headers",
|
|
"AgentRun dry-run mutations keep resource-command follow-up",
|
|
],
|
|
}));
|