import { createHash } from "node:crypto"; import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs"; import { homedir, tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { createInterface } from "node:readline"; import { applyRestorePlan, createBackup, databaseError, planBackup, planRestore, type RestorePlan } from "../database.ts"; import { readLiveHubClaim } from "../hub-autostart.ts"; import { refreshModelInventory } from "../model-inventory.ts"; import { listInventoryModels, listRoleBindings, loadRoutePolicy, rolesForInventoryModel, setRouteState, updateRouteState } from "../routes.ts"; import { runVisionGate } from "../vision-gate.ts"; import { KxmConfigError, discoverKxmProjectRoot, lookupKxmResource, type KxmInitializationPlan, } from "../project-config.ts"; import { initializeKxmProject } from "../init.ts"; import { diffKxmProjectAgainstRevision, formatKxmPermissionDiff } from "../permission.ts"; import { readKxmLocalBindings, kxmUserStateRoot } from "../bindings.ts"; import { loadKxmProject } from "../project-config.ts"; import { kxmLiveRunPrerequisites, type KxmRunHandoff } from "../engine.ts"; import { attachKxmSupervisor, ensureKxmSupervisor, kxmRuntimeRequest, kxmSupervisorStatus, type KxmProjectSyncStatus, } from "../runtime-supervisor.ts"; import { kxmRuntimePaths, runtimeError } from "../runtime-store.ts"; import { assembleTenantStatus, formatTenantStatus } from "../tenant-status.ts"; import { resolveClientAdminAuthToken } from "../hub-env.ts"; import { defaultProjectName } from "../project-name.ts"; import { effectiveHubBindingScope } from "../hub-binding.ts"; import { formatHarnessInventory, probeHarnessesAsync, } from "../harness.ts"; import { fetchLatestKxmVersion, kxmReleaseAssetName, noticeFromVersions, planKxmPackageUpdate, readInstalledKxmVersion, verifyReleaseAssetDigest, writeUpdateCache, type KxmPackageUpdateStep, type KxmUpdateConfig, type KxmUpdateNotice, } from "../kxm-update.ts"; import { loadKxmUpdateConfig } from "../kxm-update-config.ts"; import type { InstallKindReport, InstallProbe } from "../kxm-install-kind.ts"; import { print, printPlan, refuseDryRun, type CliIo, type CliSpawnResult, type Runtime } from "./types.ts"; export const kxmDriveCliSeams: { ensureSupervisor?: typeof ensureKxmSupervisor; runtimeRequest?: typeof kxmRuntimeRequest; } = {}; export function initPlanPayload(plan: KxmInitializationPlan): Record { return { mode: plan.mode, inspectedFrom: plan.inspectedFrom, ...(plan.projectRoot ? { projectRoot: plan.projectRoot } : {}), ...(plan.legacyRoot ? { legacyRoot: plan.legacyRoot } : {}), changesRequired: plan.changesRequired, legacyInputs: plan.legacyInputs, issues: plan.issues, ...(plan.configRevision ? { configRevision: plan.configRevision } : {}), }; } export function explicitRepositoryBindings(values: readonly string[]): Readonly> { const result: Record = Object.create(null) as Record; for (const value of values) { const separator = value.indexOf("="); const repositoryId = separator < 0 ? "" : value.slice(0, separator).trim(); const path = separator < 0 ? "" : value.slice(separator + 1).trim(); if (!repositoryId || !path) { throw new KxmConfigError([{ phase: "discovery", code: "repository_binding_argument_invalid", file: "--repository", message: "repository bindings must use ", }]); } if (Object.hasOwn(result, repositoryId)) { throw new KxmConfigError([{ phase: "discovery", code: "repository_binding_argument_duplicate", file: "--repository", message: `repository binding ${repositoryId} was supplied more than once`, }]); } result[repositoryId] = path; } return result; } export async function cmdKxmInit( runtime: Runtime, options: { name?: string | undefined; projectId?: string | undefined; repository?: string[] | undefined }, postHooks?: { maybeOfferCompletionInstall?: (runtime: Runtime) => Promise; maybeOfferGuideSetup?: (runtime: Runtime) => Promise; }, ): Promise { if (runtime.workspaceFlag !== undefined) { print(runtime.io, runtime.json, { ok: false, command: "init", error: "workspace_option_unsupported", }, "kxm init discovers the authoritative Git root from the current directory; --workspace is not supported"); return 2; } try { const initialized = initializeKxmProject(runtime.cwd, { ...(options.name?.trim() ? { projectName: options.name.trim() } : {}), ...(options.projectId?.trim() ? { projectId: options.projectId.trim() } : {}), repositoryBindings: explicitRepositoryBindings(options.repository ?? []), localStateRoot: kxmUserStateRoot({ env: runtime.env }), dryRun: runtime.dryRun, }); const starterGuidance = initialized.action === "created" || (initialized.action === "planned" && initialized.plan.mode === "create") ? [ "defaultHarness: pi and the npm test gate are generic starter settings, not repository detection.", "For Claude, set defaultHarness: claude in .kxm/project.yaml, update any explicit harness overrides in .kxm/agents/*.yaml, and configure compatible agent models.", "For .NET or other non-npm repositories, set gates.test.argv in .kxm/gates.yaml to the repository's actual test runner before driving a workflow.", ] : []; const payload = { ok: initialized.action !== "planned" || runtime.dryRun, command: "init", action: initialized.action, ...initPlanPayload(initialized.plan), files: initialized.files, ...(initialized.configRevision ? { configRevision: initialized.configRevision } : {}), ...(initialized.localBindingFile ? { localBindingFile: initialized.localBindingFile } : {}), ...(initialized.bindingsChanged === undefined ? {} : { bindingsChanged: initialized.bindingsChanged }), ...(initialized.repairPlan === undefined ? {} : { repairPlan: initialized.repairPlan }), ...(initialized.resumePending === undefined ? {} : { resumePending: initialized.resumePending }), ...(initialized.transactionKind === undefined ? {} : { transactionKind: initialized.transactionKind }), plannedOnly: initialized.action === "planned", ...(starterGuidance.length > 0 ? { guidance: starterGuidance } : {}), }; const finishInit = (code: number, text: string): number => { print(runtime.io, runtime.json, payload, [text, ...starterGuidance].join("\n")); return code; }; if (initialized.action === "created") { if (postHooks?.maybeOfferCompletionInstall) await postHooks.maybeOfferCompletionInstall(runtime); if (postHooks?.maybeOfferGuideSetup) await postHooks.maybeOfferGuideSetup(runtime); return finishInit(0, `initialized KXM project at ${initialized.projectRoot ?? runtime.cwd}`); } if (initialized.action === "joined") { if (postHooks?.maybeOfferCompletionInstall) await postHooks.maybeOfferCompletionInstall(runtime); if (postHooks?.maybeOfferGuideSetup) await postHooks.maybeOfferGuideSetup(runtime); return finishInit(0, `joined KXM project at ${initialized.projectRoot ?? runtime.cwd}`); } if (initialized.action === "repaired") { return finishInit(0, `repaired KXM project at ${initialized.projectRoot ?? runtime.cwd}`); } if (initialized.action === "resumed") { return finishInit(0, `resumed KXM ${initialized.transactionKind ?? "initialization"} at ${initialized.projectRoot ?? runtime.cwd}`); } if (initialized.action === "validated") { return finishInit(0, `validated KXM project at ${initialized.projectRoot ?? runtime.cwd}`); } if (runtime.dryRun) { return finishInit(0, `init plan: ${initialized.plan.mode}`); } const next = initialized.plan.mode === "legacy" ? "legacy state is not migrated by this build: initialise a fresh project directory and copy the YAML definitions you want to keep" : initialized.repairPlan?.issues.length ? "managed-template repair is blocked by conflicts or authority changes; local files were preserved" : "partial or provenance-free KXM state requires explicit repair; no files were overwritten"; // Name each validation issue, so a definition error reads as one instead of // only as a repair refusal. return finishInit(1, [next, ...initialized.plan.issues.map((issue) => `${issue.file}: ${issue.code}: ${issue.message}`)].join("\n")); } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "init", error: "initialization_failed", issues: error.issues, }, `KXM initialization failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "init", error: "initialization_io_failed", }, "KXM initialization failed because a local filesystem operation did not complete"); return 1; } } /** The checkout backup and restore act for, found as the Runtime finds it, so the * project's event store key is the one the Runtime derives. */ function backupProjectRoot(runtime: Runtime): string { return discoverKxmProjectRoot(runtime.cwd) ?? runtime.cwd; } export async function cmdBackup(runtime: Runtime, options: { out?: string | undefined; allProjects?: boolean | undefined }): Promise { try { const backupOptions = { projectRoot: backupProjectRoot(runtime), env: runtime.env, ...(options.allProjects === true ? { allProjects: true } : {}), ...(options.out ? { outDir: resolve(runtime.cwd, options.out) } : {}), }; if (runtime.dryRun) { const plan = planBackup(backupOptions); printPlan( runtime, { command: "backup", scope: plan.scope, outDir: plan.outDir, stores: plan.stores, files: plan.files }, [ ...[...plan.stores, ...plan.files].map((entry) => ({ action: "write" as const, target: join(plan.outDir, entry.backupFile) })), { action: "write", target: join(plan.outDir, "manifest.json") }, ], `back up ${plan.stores.length} store(s) and ${plan.files.length} file(s) (${plan.scope} scope) to ${plan.outDir} (sources are not opened, so their WAL is not checkpointed)`, ); return 0; } const { manifest, outDir } = createBackup(backupOptions); const complete = manifest.complete === true; const payload = { ok: complete, command: "backup", backupId: manifest.backupId, outDir, manifest, }; const summary = [ complete ? `Created SQLite backup with ${manifest.stores.length} store(s) (${manifest.scope ?? "project"} scope):` : `Backup is incomplete (${manifest.omitted?.length ?? 0} omitted); not ok:`, ...manifest.stores.map((s) => ` - ${s.storeId}: ${s.sourcePath} -> ${s.backupFile} (schema v${s.schemaVersion}, ${s.bytes} bytes, sha256 ${s.sha256.slice(0, 12)}...)`), ...(manifest.omitted ?? []).map((id) => ` - omitted ${id}`), `Manifest: ${join(outDir, "manifest.json")}`, ].join("\n"); print(runtime.io, runtime.json, payload, summary); return complete ? 0 : 1; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "backup", error: "backup_failed", issues: error.issues }, `backup failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "backup", error: "backup_failed", message: error instanceof Error ? error.message : String(error) }, `backup failed: ${error instanceof Error ? error.message : String(error)}`); return 1; } } /** * Refuse while anything holds the stores a restore would overwrite. Replacing a * SQLite file under an open connection loses the writer's next commit or corrupts * the store, and the supervisor holds the registry and every project's event store * open. Reads only: the registry is opened read-only and the hub claim is a file, * so the check is the same under --dry-run. */ function assertRestoreTargetsStopped(runtime: Runtime, plan: RestorePlan): void { const paths = kxmRuntimePaths({ env: runtime.env }); let supervisor: ReturnType; try { supervisor = kxmSupervisorStatus(paths, { readOnly: true }); } catch (error) { // Fail closed, but name the way out: a registry too broken to read is also one a // restore may be meant to replace. throw databaseError( "restore_runtime_unverified", paths.registryDb, `cannot read the Runtime registry to check whether the supervisor is running (${error instanceof Error ? error.message : String(error)}); stop the Runtime, move the registry aside, and restore again`, ); } if (supervisor.running) { throw databaseError( "restore_runtime_running", paths.registryDb, `the Runtime supervisor is running (pid ${String(supervisor.pid)}); stop it with \`kxm runtime stop\` and keep it stopped until the restore finishes`, ); } for (const store of plan.stores) { if (store.storeId !== "hub-store") continue; const claim = readLiveHubClaim(dirname(store.targetPath)); if (claim) { throw databaseError( "restore_hub_running", store.targetPath, `a hub (pid ${String(claim.pid)}) is running on ${store.targetPath}; stop it with \`kxm hub stop\` before restoring`, ); } } } export async function cmdRestore(runtime: Runtime, manifestArg: string, options: { allProjects?: boolean | undefined } = {}): Promise { try { const plan = planRestore(resolve(runtime.cwd, manifestArg), { projectRoot: backupProjectRoot(runtime), env: runtime.env, ...(options.allProjects === true ? { allProjects: true } : {}), }); assertRestoreTargetsStopped(runtime, plan); if (runtime.dryRun) { printPlan( runtime, { command: "restore", backupId: plan.backupId, manifestPath: plan.manifestPath, ...(plan.scope !== undefined ? { scope: plan.scope } : {}), stores: plan.stores.map(({ storeId, targetPath, schemaVersion }) => ({ storeId, targetPath, schemaVersion })), files: plan.files.map(({ id, targetPath }) => ({ id, targetPath })), }, [ ...plan.stores.flatMap((store) => [ { action: "write" as const, target: store.targetPath }, ...[`${store.targetPath}-wal`, `${store.targetPath}-shm`] .filter((file) => existsSync(file)) .map((file) => ({ action: "delete" as const, target: file })), ]), ...plan.files.map((file) => ({ action: "write" as const, target: file.targetPath })), ], `restore ${plan.stores.length} store(s) and ${plan.files.length} file(s) from ${plan.manifestPath}; digests verified against the manifest`, ); return 0; } const result = applyRestorePlan(plan); const payload = { ok: true, command: "restore", backupId: result.backupId, manifestPath: result.manifestPath, ...(plan.scope !== undefined ? { scope: plan.scope } : {}), restoredStores: result.restoredStores, }; const summary = [ `Restored ${result.restoredStores.length} SQLite store(s) from ${result.manifestPath}:`, ...result.restoredStores.map((s) => ` - ${s.storeId}: -> ${s.sourcePath} (schema v${s.schemaVersion}, integrity ${s.integrity})`), ].join("\n"); print(runtime.io, runtime.json, payload, summary); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "restore", error: "restore_failed", issues: error.issues }, `restore failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "restore", error: "restore_failed", message: error instanceof Error ? error.message : String(error) }, `restore failed: ${error instanceof Error ? error.message : String(error)}`); return 1; } } export async function cmdKxmTrust(runtime: Runtime, check: boolean, options: { base?: string | undefined }): Promise { if (runtime.workspaceFlag !== undefined) { print(runtime.io, runtime.json, { ok: false, command: check ? "trust check" : "trust diff", error: "workspace_option_unsupported", }, "kxm trust discovers the authoritative Git root from the current directory; --workspace is not supported"); return 2; } const command = check ? "trust check" : "trust diff"; try { const projectRoot = discoverKxmProjectRoot(runtime.cwd) ?? runtime.cwd; const bindings = readKxmLocalBindings(projectRoot, { stateRoot: kxmUserStateRoot({ env: runtime.env }) }); const diff = diffKxmProjectAgainstRevision(projectRoot, options.base?.trim() || "HEAD", { repositoryBindings: bindings?.repositories ?? {}, }); const payload = { ok: !check || !diff.requiresReview, command, baseRevision: diff.baseRevision, candidateRevision: diff.candidateRevision, requiresReview: diff.requiresReview, expansions: diff.expansions.length, narrowings: diff.narrowings.length, neutralChanges: diff.neutralChanges.length, changes: diff.changes, }; const text = formatKxmPermissionDiff(diff); if (check && diff.requiresReview) { print(runtime.io, runtime.json, payload, `${text}\ntrust check failed: review every expansion above before merging`); return 1; } print(runtime.io, runtime.json, payload, text); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command, error: "trust_diff_failed", issues: error.issues }, `permission diff failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command, error: "trust_diff_io_failed" }, "permission diff failed because a local filesystem or Git operation did not complete"); return 1; } } /** The supervisor a run read talks to. Normally it is started on demand; under * `--dry-run` a read may only attach, because starting the Runtime is a change. */ async function readSupervisor(runtime: Runtime, command: string): Promise> | number> { if (!runtime.dryRun) return await (kxmDriveCliSeams.ensureSupervisor ?? ensureKxmSupervisor)({ env: runtime.env }); const attached = await attachKxmSupervisor({ env: runtime.env }); return attached ?? refuseDryRun(runtime.io, runtime.json, command, "the Runtime supervisor is not running and --dry-run will not start it"); } /** Creation is not execution; local runs are driven and inspected in the runs namespace. */ export function runEngineNotice(runId: string, defaultHarness: string, prerequisites: readonly KxmRunHandoff[]): string { return [ `No steps executed. Project default harness: ${defaultHarness}; per-agent harness settings take precedence.`, ...prerequisites.map((item) => `Live prerequisite${item.stepId ? ` (${item.stepId})` : ""}: ${item.detail}`), "Live execution uses one-shot harness calls; no hub or Pi worker is required. Check installation/authentication with kxm harness list.", `${prerequisites.length > 0 ? "Resolve the prerequisites above, then execute" : "Execute"}: kxm runs drive ${runId} --wait`, `Inspect: kxm runs status ${runId} --json; receipt: kxm runs receipt ${runId} --json; cancel: kxm runs cancel ${runId}`, "These are local Runtime runs, not webhook workflows; use kxm runs, not kxm workflow get.", ].join("\n"); } /** Where `kxm run ` would create its run, or the exit code of the * refusal it already printed. Reads only; shared with `task run --dry-run`. */ export function resolveKxmRunTarget( runtime: Runtime, workflow: string | undefined, forTask = false, envelope: Record = {}, allowDefaultWorkflow = false, ): { projectRoot: string; workflowId: string; configRevision: string; defaultHarness: string; prerequisites: KxmRunHandoff[] } | number { if (runtime.workspaceFlag !== undefined) { print(runtime.io, runtime.json, { ok: false, command: "run", error: "workspace_option_unsupported", ...envelope, }, "kxm run discovers the authoritative project from the current directory; --workspace is not supported"); return 2; } if (!workflow && !forTask && !allowDefaultWorkflow) { print(runtime.io, runtime.json, { ok: false, command: "run", error: "workflow_required", ...envelope }, "usage: kxm run [prompt]"); return 2; } const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "run", error: "project_required", ...envelope }, "kxm run requires a KXM project (run kxm init first)"); return 1; } const bundle = loadKxmProject(projectRoot, {}); const workflowId = workflow ?? String(bundle.project.value.defaultWorkflow ?? "default"); if (!lookupKxmResource(bundle.workflows.values(), workflowId, "workflow")) { print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_workflow_unknown", workflow: workflowId, ...envelope }, `workflow ${workflowId} does not exist in this project`); return 1; } const defaultHarness = String(bundle.project.value.defaultHarness ?? "pi"); const prerequisites = kxmLiveRunPrerequisites(bundle, workflowId, projectRoot); if (forTask && prerequisites.length > 0) { print(runtime.io, runtime.json, { ok: false, command: "task run", error: "run_execution_unavailable", workflowId, defaultHarness, execution: { status: "not_started", mode: "live", prerequisites }, }, `task run refused; no run created or task changed (default harness: ${defaultHarness}).\n${prerequisites.map((item) => `${item.stepId ?? workflowId}: ${item.detail}`).join("\n")}`); return 1; } return { projectRoot, workflowId, configRevision: bundle.configRevision, defaultHarness, prerequisites }; } export async function cmdKxmRun( runtime: Runtime, workflow: string | undefined, promptParts: string[], forTask = false, call?: { brief?: string; prompt?: string; runIdOut?: { runId?: string }; allowDefaultWorkflow?: boolean }, ): Promise { const envelope = call?.brief !== undefined ? { brief: call.brief } : {}; try { const target = resolveKxmRunTarget(runtime, workflow, forTask, envelope, call?.allowDefaultWorkflow === true); if (typeof target === "number") return target; const { projectRoot } = target; if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "run", dryRun: true, ...envelope, ...target, }, `run plan: workflow ${target.workflowId} at ${target.configRevision.slice(0, 19)}… (no run created)`); return 0; } const supervisor = await (kxmDriveCliSeams.ensureSupervisor ?? ensureKxmSupervisor)({ env: runtime.env }); const prompt = call?.prompt !== undefined ? call.prompt : promptParts.join(" ").trim(); const acceptance = await (kxmDriveCliSeams.runtimeRequest ?? kxmRuntimeRequest)(supervisor, "POST", "/v1/runs", { projectRoot, workflowId: target.workflowId, prompt, }); const run = acceptance.run as { runId: string; homeRuntimeId: string; status: string; configRevision: string }; if (call?.runIdOut) call.runIdOut.runId = run.runId; print(runtime.io, runtime.json, { ok: true, command: "run", ...envelope, execution: { status: "not_started", mode: "live", defaultHarness: target.defaultHarness, authentication: "not_checked", prerequisites: target.prerequisites, nextSteps: { harnesses: "kxm harness list", drive: `kxm runs drive ${run.runId} --wait`, status: `kxm runs status ${run.runId} --json`, receipt: `kxm runs receipt ${run.runId} --json`, }, }, idempotent: acceptance.idempotent === true, run, supervisor: { runtimeId: supervisor.runtimeId, port: supervisor.port, started: supervisor.started }, }, `run ${run.status}: ${run.runId} (home ${run.homeRuntimeId.slice(0, 12)}…, config ${run.configRevision.slice(0, 19)}…)\n${runEngineNotice(run.runId, target.defaultHarness, target.prerequisites)}`); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_failed", issues: error.issues, ...envelope }, `run failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "run", error: "run_io_failed", ...envelope }, "run failed because a local operation did not complete"); return 1; } } interface KxmStatusDrive { driveId?: string; mode?: string; openedAt?: string; receipt?: { settlement?: { kind?: string; status?: string; reason?: string; handoff?: { reason?: string; attemptId?: string }; }; } | null; verified?: boolean; divergence?: string; } function formatCancelledStatus(reason: string): string { return reason.length > 0 ? `cancelled (${reason})` : "cancelled"; } function formatDriveStatusLine(runStatus: string, drive: KxmStatusDrive | undefined): string | undefined { if (!drive || typeof drive.driveId !== "string" || drive.driveId.length === 0) return undefined; const receipt = drive.receipt ?? null; if (receipt === null) { if (runStatus === "running" || runStatus === "blocked_uncertain") { return `drive ${drive.driveId}: open`; } return `drive ${drive.driveId}: no receipt (orphaned)`; } const kind = receipt.settlement?.kind; const reason = typeof receipt.settlement?.reason === "string" ? receipt.settlement.reason : ""; if (kind === "unsettled") { return `drive ${drive.driveId}: unsettled ${reason}`.trimEnd(); } if (kind === "handoff") { return drive.verified === true ? `drive ${drive.driveId}: handoff (receipt verified)` : `drive ${drive.driveId}: handoff`; } if (receipt.settlement?.status === "cancelled") { const label = formatCancelledStatus(reason); return drive.verified === true ? `drive ${drive.driveId}: ${label} (receipt verified)` : `drive ${drive.driveId}: ${label}`; } if (drive.verified === true) { return `drive ${drive.driveId}: completed (receipt verified)`; } return `drive ${drive.driveId}: completed`; } function formatRunStatusLine( run: { runId: string; status: string; workflowId: string; updatedAt: string }, drive: KxmStatusDrive | undefined, ): string { const reason = typeof drive?.receipt?.settlement?.reason === "string" ? drive.receipt.settlement.reason : ""; const handoff = drive?.receipt?.settlement?.handoff; const attemptId = typeof handoff?.attemptId === "string" ? handoff.attemptId : ""; const handoffReason = typeof handoff?.reason === "string" ? handoff.reason : ""; const statusLabel = run.status === "cancelled" ? formatCancelledStatus(reason) : run.status === "cancelling" && attemptId.length > 0 && handoffReason.length > 0 ? `cancelling (attempt ${attemptId}, ${handoffReason})` : run.status; return `run ${run.runId}: ${statusLabel} (workflow ${run.workflowId}, updated ${run.updatedAt})`; } export async function cmdKxmRunStatus(runtime: Runtime, runId: string): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runs status", error: "project_required" }, "kxm runs status requires a KXM project (run kxm init first)"); return 1; } const supervisor = await readSupervisor(runtime, "runs status"); if (typeof supervisor === "number") return supervisor; const result = await (kxmDriveCliSeams.runtimeRequest ?? kxmRuntimeRequest)(supervisor, "GET", `/v1/runs/${encodeURIComponent(runId)}?projectRoot=${encodeURIComponent(projectRoot)}`); const run = result.run as { runId: string; status: string; workflowId: string; configRevision: string; updatedAt: string }; const drive = result.drive as KxmStatusDrive | undefined; const driveLine = formatDriveStatusLine(run.status, drive); print( runtime.io, runtime.json, { ok: true, command: "runs status", projectRoot, run, ...(drive !== undefined ? { drive } : {}) }, `${formatRunStatusLine(run, drive)}\nroot ${projectRoot}${driveLine ? `\n${driveLine}` : ""}`, ); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runs status", error: "run_status_failed", issues: error.issues }, `run status failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runs status", error: "run_status_io_failed" }, "run status failed because a local operation did not complete"); return 1; } } const DEFAULT_DRIVE_WAIT_MS = 60_000; const MAX_DRIVE_WAIT_MS = 600_000; function parseDriveWaitTimeoutMs(raw: number | string | undefined): number | undefined { if (raw === undefined) return DEFAULT_DRIVE_WAIT_MS; const value = typeof raw === "number" ? raw : Number(typeof raw === "string" ? raw.trim() : raw); if (!Number.isInteger(value) || value < 1 || value > MAX_DRIVE_WAIT_MS) return undefined; return value; } function sleepMs(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } function driveWaitCompleted(drive: KxmStatusDrive | undefined): boolean { return drive?.verified === true && drive.receipt?.settlement?.kind === "terminal" && drive.receipt.settlement.status === "completed"; } export async function cmdKxmRunDrive( runtime: Runtime, runId: string, simulated: boolean, options: { wait?: boolean; timeoutMs?: number | string } = {}, ): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "project_required" }, "kxm runs drive requires a KXM project (run kxm init first)"); return 1; } const mode = simulated ? "simulated" : "live"; if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "runs drive", dryRun: true, runId, mode }, `drive plan: run ${runId} in ${mode} mode (no events written)`); return 0; } const timeoutMs = options.wait === true ? parseDriveWaitTimeoutMs(options.timeoutMs) : DEFAULT_DRIVE_WAIT_MS; if (options.wait === true && timeoutMs === undefined) { print( runtime.io, runtime.json, { ok: false, command: "runs drive", error: "run_drive_timeout_invalid" }, `run drive --wait --timeout-ms must be an integer between 1 and ${MAX_DRIVE_WAIT_MS}`, ); return 1; } const supervisor = await (kxmDriveCliSeams.ensureSupervisor ?? ensureKxmSupervisor)({ env: runtime.env }); const request = kxmDriveCliSeams.runtimeRequest ?? kxmRuntimeRequest; const result = await request(supervisor, "POST", `/v1/runs/${encodeURIComponent(runId)}/drive?projectRoot=${encodeURIComponent(projectRoot)}`, { mode }); const driveId = result.driveId; const poll = result.poll; const status = result.status; if (typeof driveId !== "string" || driveId.length === 0 || typeof poll !== "string" || poll.length === 0 || status !== "accepted") { print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "run_drive_io_failed" }, "run drive failed because a local operation did not complete"); return 1; } if (options.wait !== true) { print( runtime.io, runtime.json, { ok: true, command: "runs drive", runId, driveId, poll, mode, status }, `drive ${driveId}: accepted (poll ${poll})`, ); return 0; } const deadline = Date.now() + timeoutMs!; let interval = 25; while (true) { const stateResult = await request(supervisor, "GET", `/v1/runs/${encodeURIComponent(runId)}?projectRoot=${encodeURIComponent(projectRoot)}`); const drive = stateResult.drive as KxmStatusDrive | undefined; if (drive?.receipt) { print( runtime.io, runtime.json, { ok: driveWaitCompleted(drive), command: "runs drive", receipt: drive.receipt, verified: drive.verified === true }, JSON.stringify(drive.receipt, null, 2), ); return driveWaitCompleted(drive) ? 0 : 1; } const remaining = deadline - Date.now(); if (remaining <= 0) break; await sleepMs(Math.min(interval, remaining)); interval = Math.min(Math.floor(interval * 1.5), 250); } print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "timeout" }, "drive wait timed out"); return 1; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "run_drive_failed", issues: error.issues }, `run drive failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runs drive", error: "run_drive_io_failed" }, "run drive failed because a local operation did not complete"); return 1; } } export async function cmdKxmRunCancel(runtime: Runtime, runId: string): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runs cancel", error: "project_required" }, "kxm runs cancel requires a KXM project (run kxm init first)"); return 1; } if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "runs cancel", dryRun: true, runId }, `cancel plan: run ${runId} (no events written)`); return 0; } const supervisor = await ensureKxmSupervisor({ env: runtime.env }); const result = await kxmRuntimeRequest(supervisor, "POST", `/v1/runs/${encodeURIComponent(runId)}/cancel?projectRoot=${encodeURIComponent(projectRoot)}`, {}); const run = result.run as { runId: string; status: string }; print(runtime.io, runtime.json, { ok: true, command: "runs cancel", idempotent: result.idempotent === true, run, }, `run ${run.runId}: ${run.status}`); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runs cancel", error: "run_cancel_failed", issues: error.issues }, `run cancel failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runs cancel", error: "run_cancel_io_failed" }, "run cancel failed because a local operation did not complete"); return 1; } } export async function cmdKxmRunList(runtime: Runtime): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runs list", error: "project_required" }, "kxm runs list requires a KXM project (run kxm init first)"); return 1; } const bundle = loadKxmProject(projectRoot, {}); const projectId = String(bundle.project.value.id); const supervisor = await readSupervisor(runtime, "runs list"); if (typeof supervisor === "number") return supervisor; const result = await kxmRuntimeRequest(supervisor, "GET", `/v1/projects/${encodeURIComponent(projectId)}/runs?projectRoot=${encodeURIComponent(projectRoot)}`); const runs = (result.runs ?? []) as Array<{ runId: string; status: string; workflowId: string; createdAt: string; projectionError?: string }>; print( runtime.io, runtime.json, { ok: true, command: "runs list", runs }, runs.length === 0 ? "no runs" : runs.map((run) => `${run.runId} ${run.status} ${run.workflowId} ${run.createdAt}${run.projectionError ? ` [state unverified: ${run.projectionError}]` : ""}`).join("\n"), ); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runs list", error: "run_list_failed", issues: error.issues }, `run list failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runs list", error: "run_list_io_failed" }, "run list failed because a local operation did not complete"); return 1; } } export async function cmdTenantStatus(runtime: Runtime, options: { project?: string | undefined } = {}): Promise { let projectRoot: string | undefined; let projectId: string; try { projectRoot = discoverKxmProjectRoot(runtime.cwd) ?? undefined; if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "tenant status", error: "project_required" }, "kxm tenant status requires a KXM project (run kxm init first)"); return 1; } const bundle = loadKxmProject(projectRoot, {}); const yamlProjectId = String(bundle.project.value.id); projectId = defaultProjectName(runtime.cwd, runtime.env, options.project); const root = projectRoot; const payload = await assembleTenantStatus({ project: projectId, hubUrl: runtime.serverUrl, // Admin-scoped route: resolve the admin credential only (a project token would 401), // and resolve it inside the hub source so a malformed persisted record degrades that // one source instead of aborting the Runtime read with it. resolveAdminToken: () => resolveClientAdminAuthToken(runtime.env), bindingScope: effectiveHubBindingScope(runtime.serverUrl, runtime.env), fetchImpl: runtime.fetchImpl, runtime: { listRuns: async () => { // Attach only: a status read must never conjure a supervisor. "Nothing is // running" is an answer the portal can render, not a condition to repair. const handle = await attachKxmSupervisor({ env: runtime.env }); if (!handle) { throw runtimeError("runtime_supervisor_not_running", "runtime", "no live runtime supervisor on this box"); } const result = await kxmRuntimeRequest(handle, "GET", `/v1/projects/${encodeURIComponent(yamlProjectId)}/runs?projectRoot=${encodeURIComponent(root)}`); const runs = (result.runs ?? []) as Array>; return runs.map((run) => ({ runId: String(run.runId ?? ""), status: String(run.status ?? "unknown"), homeRuntimeId: String(run.homeRuntimeId ?? ""), ...(typeof run.workflowId === "string" ? { workflowId: run.workflowId } : {}), ...(typeof run.createdAt === "string" ? { createdAt: run.createdAt } : {}), ...(typeof run.updatedAt === "string" ? { updatedAt: run.updatedAt } : {}), ...(typeof run.projectionError === "string" ? { projectionError: run.projectionError } : {}), source: (typeof run.projectionError === "string" ? "runtime-cached" : "runtime-authoritative") as "runtime-cached" | "runtime-authoritative", })); }, }, }); if (payload.hub.state !== "ok" && payload.runtime.state !== "ok") { print( runtime.io, runtime.json, { ok: false, command: "tenant status", error: "tenant_status_no_source", payload }, `neither source could be read: hub ${payload.hub.reason ?? "unknown"}, runtime ${payload.runtime.reason ?? "unknown"}`, ); return 1; } print(runtime.io, runtime.json, { ok: true, command: "tenant status", ...payload }, formatTenantStatus(payload)); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "tenant status", error: "tenant_status_failed", issues: error.issues }, `tenant status failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "tenant status", error: "tenant_status_io_failed" }, "tenant status failed because a local operation did not complete"); return 1; } } export async function cmdHarnessList(runtime: Runtime): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); const defaultHarness = projectRoot ? String(loadKxmProject(projectRoot).project.value.defaultHarness ?? "pi") : undefined; const inventory = await probeHarnessesAsync({ env: runtime.env, defaultHarness }); print(runtime.io, runtime.json, { ok: true, command: "harness list", ...inventory }, formatHarnessInventory(inventory)); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "harness list", error: "harness_list_failed", issues: error.issues }, `harness list failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "harness list", error: "harness_list_io_failed" }, "harness list failed because a local operation did not complete"); return 1; } } export async function selectInventoryModel(runtime: Runtime, requested?: string | undefined): Promise { const models = listInventoryModels(runtime.dirs.workdir); if (requested) return models.find((model) => model.toLowerCase() === requested.toLowerCase()); if (runtime.json || !process.stdin.isTTY || models.length === 0) return undefined; runtime.io.stdout(models.slice(0, 100).map((model, index) => `${index + 1}. ${model}`).join("\n") + "\nSelect model number: "); const rl = createInterface({ input: process.stdin, output: process.stderr }); const answer = await new Promise((resolve) => rl.once("line", resolve)); rl.close(); const index = Number.parseInt(answer.trim(), 10) - 1; return Number.isInteger(index) && index >= 0 && index < models.length ? models[index] : undefined; } export async function cmdRouteChange(runtime: Runtime, status: "admitted" | "disabled", requested?: string | undefined): Promise { const model = await selectInventoryModel(runtime, requested); if (!model) { print(runtime.io, runtime.json, { ok: false, command: `routes ${status}`, error: "model_selection_required" }, "select a model from the refreshed inventory"); return 2; } if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, dryRun: true }, `would ${status === "admitted" ? "admit" : "disable"} ${model}`); return 0; } const policy = updateRouteState(runtime.dirs.workdir, model, status); print(runtime.io, runtime.json, { ok: true, command: `routes ${status}`, model, policy }, `${status} ${model}`); return 0; } export async function cmdModelsScreen(runtime: Runtime): Promise { const models = listInventoryModels(runtime.dirs.workdir); if (runtime.json || !process.stdin.isTTY) { print(runtime.io, runtime.json, { ok: false, command: "models", error: "interactive_tty_required" }, "kxm models requires an interactive terminal"); return 2; } const rl = createInterface({ input: process.stdin, output: process.stderr }); const ask = (q: string) => new Promise((resolve) => rl.question(q, resolve)); try { while (true) { const policy = loadRoutePolicy(runtime.dirs.workdir); runtime.io.stdout(models.map((m, i) => `${i + 1}. ${m} [${policy.admitted.includes(m) ? "admitted" : policy.disabled.includes(m) ? "disabled" : "unset"}] roles:${rolesForInventoryModel(runtime.dirs.workdir, m).join(",") || "-"}`).join("\n") + "\n"); const command = (await ask("[a]dmit [d]isable [r]ole-add [x]ole-remove [q]uit: ")).trim().toLowerCase(); if (command === "q" || command === "quit") return 0; const index = Number.parseInt((await ask("model number: ")).trim(), 10) - 1; if (!Number.isInteger(index) || !models[index]) continue; const model = models[index]; if (command === "a" || command === "d") setRouteState(runtime.dirs.workdir, model, command === "a" ? "admitted" : "disabled"); else if (command === "r" || command === "x") { try { setRouteState(runtime.dirs.workdir, model, "admitted", (await ask("role: ")).trim(), command === "x"); } catch (error) { runtime.io.stderr(`${error instanceof Error ? error.message : "unknown route"}\n`); } } } } finally { rl.close(); } } export async function cmdRouteList(runtime: Runtime): Promise { const policy = loadRoutePolicy(runtime.dirs.workdir); const membership = Object.entries(listRoleBindings(runtime.dirs.workdir)).flatMap(([role, ids]) => ids.map((id) => `${role} ${id}`)); print(runtime.io, runtime.json, { ok: true, command: "routes list", policy, membership }, [...policy.admitted.map((x) => `admitted ${x}`), ...policy.disabled.map((x) => `disabled ${x}`), ...membership].join("\n") || "no route decisions"); return 0; } export async function cmdRouteCount(runtime: Runtime): Promise { const policy = loadRoutePolicy(runtime.dirs.workdir); const summary = `${policy.admitted.length} admitted / ${policy.disabled.length} disabled`; print(runtime.io, runtime.json, { ok: true, command: "routes count", admitted: policy.admitted.length, disabled: policy.disabled.length, summary }, summary); return 0; } export interface VisionAssertOptions { image?: string | undefined; question?: string | undefined; route?: string | undefined; timeoutMs?: string | undefined; expect?: string | undefined; } /** Judge a captured UI screenshot through the admitted vision gate. Exit 0 * when the verdict resolves and matches --expect (or when no expectation was * given and the verdict resolved); fail-closed divergences exit 1. */ export async function cmdVisionAssert(runtime: Runtime, options: VisionAssertOptions): Promise { const image = options.image?.trim(); const question = options.question?.trim(); if (!image || !question) { print(runtime.io, runtime.json, { ok: false, command: "vision assert", error: "image_and_question_required" }, "both --image and --question are required"); return 2; } let expect: boolean | undefined; if (options.expect !== undefined) { if (options.expect !== "true" && options.expect !== "false") { print(runtime.io, runtime.json, { ok: false, command: "vision assert", error: "expect_invalid" }, "--expect must be true or false"); return 2; } expect = options.expect === "true"; } let timeoutMs: number | undefined; if (options.timeoutMs !== undefined) { const parsed = Number(options.timeoutMs); if (!Number.isInteger(parsed)) { print(runtime.io, runtime.json, { ok: false, command: "vision assert", error: "timeout_invalid" }, "--timeout-ms must be an integer"); return 2; } timeoutMs = parsed; } const result = await runVisionGate({ projectRoot: runtime.dirs.workdir, imagePath: resolve(runtime.cwd, image), question, ...(options.route !== undefined ? { route: options.route } : {}), ...(timeoutMs !== undefined ? { timeoutMs } : {}), }); const pass = result.verdict !== null && (expect === undefined || result.verdict === expect); print( runtime.io, runtime.json, { ok: pass, command: "vision assert", ...(expect !== undefined ? { expect } : {}), ...result }, result.verdict === null ? `vision gate fail-closed: ${result.divergence}` : `verdict ${result.verdict}${expect !== undefined ? ` (expected ${expect})` : ""}`, ); return pass ? 0 : 1; } export async function cmdModelInventoryRefresh(runtime: Runtime): Promise { if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "models inventory refresh", dryRun: true }, "would refresh .kxm/models/inventory.yaml"); return 0; } const inventory = await refreshModelInventory({ outputRoot: runtime.dirs.workdir, env: runtime.env }); const failed = Object.values(inventory.sources).some((source) => !source.ok); print(runtime.io, runtime.json, { ok: !failed, command: "models inventory refresh", output: ".kxm/models/inventory.yaml", ...inventory }, `wrote ${inventory.models.length} models to .kxm/models/inventory.yaml`); return failed ? 1 : 0; } export async function cmdKxmRuntime(runtime: Runtime, action: string): Promise { const paths = kxmRuntimePaths({ env: runtime.env }); try { if (action === "start") { if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "runtime start", dryRun: true }, "runtime supervisor would auto-start"); return 0; } const supervisor = await ensureKxmSupervisor({ env: runtime.env }); print(runtime.io, runtime.json, { ok: true, command: "runtime start", runtimeId: supervisor.runtimeId, port: supervisor.port, started: supervisor.started, }, `runtime supervisor ${supervisor.started ? "started" : "already running"}: ${supervisor.runtimeId} on 127.0.0.1:${supervisor.port}`); return 0; } if (action === "status") { // Liveness alone was not enough to answer "is my outbox draining?" — the // supervisor ran clean while 23 rows sat refused by the hub. The sync block // is that answer, read from the process that actually pushes. const status = kxmSupervisorStatus(paths); const sync = status.running ? await readKxmSupervisorSync(runtime) : undefined; print(runtime.io, runtime.json, { ok: true, command: "runtime status", ...status, ...(sync ? { sync } : {}) }, [ status.running ? `runtime supervisor running: ${status.runtimeId} pid ${status.pid} on 127.0.0.1:${status.port}` : "runtime supervisor is not running", ...formatKxmSyncStatus(sync, status.running), ].join("\n")); return status.running ? 0 : 1; } if (action === "sync-retry") { const supervisor = await attachKxmSupervisor({ env: runtime.env }); if (!supervisor) { print(runtime.io, runtime.json, { ok: false, command: "runtime sync-retry", error: "runtime_not_running" }, "runtime supervisor is not running"); return 1; } const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runtime sync-retry", error: "project_required" }, "kxm runtime sync-retry requires a KXM project (run kxm init first)"); return 1; } if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "runtime sync-retry", projectRoot, dryRun: true }, "would re-queue rows the hub durably refused"); return 0; } const result = await kxmRuntimeRequest(supervisor, "POST", "/v1/sync/retry", { projectRoot }); print(runtime.io, runtime.json, { ok: true, command: "runtime sync-retry", ...result }, `re-queued ${String(result.retried ?? 0)} refused outbox rows for ${String(result.projectId ?? projectRoot)}`); return 0; } if (action === "stop") { const status = kxmSupervisorStatus(paths); if (!status.running || !status.port) { print(runtime.io, runtime.json, { ok: true, command: "runtime stop", stopped: false }, "runtime supervisor is not running"); return 0; } if (runtime.dryRun) { print(runtime.io, runtime.json, { ok: true, command: "runtime stop", dryRun: true }, `would stop runtime supervisor pid ${status.pid}`); return 0; } const supervisor = await ensureKxmSupervisor({ env: runtime.env }); await kxmRuntimeRequest(supervisor, "POST", "/v1/shutdown", {}); print(runtime.io, runtime.json, { ok: true, command: "runtime stop", stopped: true }, `runtime supervisor ${status.runtimeId} stopping`); return 0; } print(runtime.io, runtime.json, { ok: false, command: "runtime", error: "unknown_action" }, `unknown runtime action: ${action}`); return 2; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runtime", error: "runtime_failed", issues: error.issues }, `runtime failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runtime", error: "runtime_io_failed" }, "runtime failed because a local operation did not complete"); return 1; } } /** What the running supervisor last saw from the hub, or why it could not say. */ async function readKxmSupervisorSync(runtime: Runtime): Promise { const supervisor = await attachKxmSupervisor({ env: runtime.env }); if (!supervisor) return undefined; try { const response = await kxmRuntimeRequest(supervisor, "GET", "/v1/sync/status"); return response.projects as unknown as KxmProjectSyncStatus[]; } catch { return undefined; } } function formatKxmSyncStatus(sync: KxmProjectSyncStatus[] | undefined, running: boolean): string[] { // Nothing was asked, so nothing failed to answer. Saying "did not answer" here // would blame a supervisor that was never up. if (!running) return []; if (sync === undefined) return ["sync: the supervisor is running but did not answer /v1/sync/status"]; if (sync.length === 0) return ["sync: no project registered with this Runtime yet"]; return sync.map((project) => { const codes = project.outbox.refusals.map((refusal) => `${refusal.code} x${refusal.count}`).join(", "); // A store this build refuses to open reports zeros it cannot read, not an // empty outbox. Saying "pending 0" there would send the operator looking // somewhere else while every row in the project sits unreachable. if (project.storeReadable === false) { // "cannot open this project", not "its store is unreadable": what the // supervisor actually sees is whatever `openKxmRuntimeContext` refused — // an out-of-date event store *or* a project config a newer brake rejects. // Witnessed on kxm-dev-svr on 0.7.94, where it was the workflow config. return `sync ${project.projectId}: blocked (this build cannot open the project) — ${project.lastError ?? "unknown reason"}`; } const counts = `pending ${project.outbox.pending}, acked ${project.outbox.acked}, refused ${project.outbox.refused}`; const tail = project.state === "refusing" ? ` (${codes || "see log"}) — fix the hub, then: kxm runtime sync-retry` : project.state === "blocked" ? ` — last error: ${project.lastError ?? "unreachable"}${project.nextAttemptAt ? `; next attempt ${project.nextAttemptAt}` : ""}` : ""; return `sync ${project.projectId}: ${project.state} (${counts})${tail}`; }); } export async function cmdKxmRunReceipt(runtime: Runtime, runId: string, options: { all?: boolean } = {}): Promise { try { const projectRoot = discoverKxmProjectRoot(runtime.cwd); if (!projectRoot) { print(runtime.io, runtime.json, { ok: false, command: "runs receipt", error: "project_required" }, "kxm runs receipt requires a KXM project (run kxm init first)"); return 1; } const supervisor = await readSupervisor(runtime, "runs receipt"); if (typeof supervisor === "number") return supervisor; const result = await (kxmDriveCliSeams.runtimeRequest ?? kxmRuntimeRequest)( supervisor, "GET", `/v1/runs/${encodeURIComponent(runId)}/drive?projectRoot=${encodeURIComponent(projectRoot)}`, ); if (!Array.isArray(result.receipts)) { print(runtime.io, runtime.json, { ok: false, command: "runs receipt", error: "run_receipt_io_failed" }, "run receipt failed because a local operation did not complete"); return 1; } const receipts = result.receipts as unknown[]; if (receipts.length === 0) { print(runtime.io, runtime.json, { ok: false, command: "runs receipt", error: "no_receipts" }, `run ${runId} has no drive receipts`); return 1; } if (options.all === true) { print(runtime.io, runtime.json, { ok: true, command: "runs receipt", receipts }, JSON.stringify(receipts, null, 2)); return 0; } const latest = receipts[0]; const settlement = latest && typeof latest === "object" && "settlement" in latest ? (latest as { settlement: unknown }).settlement : latest; print(runtime.io, runtime.json, { ok: true, command: "runs receipt", receipt: latest }, JSON.stringify(settlement, null, 2)); return 0; } catch (error) { if (error instanceof KxmConfigError) { print(runtime.io, runtime.json, { ok: false, command: "runs receipt", error: "run_receipt_failed", issues: error.issues }, `run receipt failed: ${error.message}`); return 1; } print(runtime.io, runtime.json, { ok: false, command: "runs receipt", error: "run_receipt_io_failed" }, "run receipt failed because a local operation did not complete"); return 1; } }