#!/usr/bin/env node const assert = require("assert"); const cp = require("child_process"); const fs = require("fs"); const os = require("os"); const path = require("path"); const repo = path.resolve(__dirname, ".."); const project = path.join(repo, "examples/launch-build-demo"); const isolatedCwd = fs.mkdtempSync(path.join(os.tmpdir(), "clusterflux-cli-output-")); const isolatedHome = fs.mkdtempSync(path.join(os.tmpdir(), "clusterflux-cli-home-")); function clusterflux(args, env = {}, cwd = isolatedCwd) { return cp.execFileSync( "cargo", [ "run", "-q", "--manifest-path", path.join(repo, "Cargo.toml"), "-p", "clusterflux-cli", "--bin", "clusterflux", "--", ...args, ], { cwd, encoding: "utf8", env: { ...process.env, HOME: isolatedHome, USERPROFILE: isolatedHome, XDG_CONFIG_HOME: path.join(isolatedHome, ".config"), XDG_DATA_HOME: path.join(isolatedHome, ".local", "share"), XDG_STATE_HOME: path.join(isolatedHome, ".local", "state"), ...env, }, } ); } function json(args, env, cwd) { return JSON.parse(clusterflux(args, env, cwd)); } function assertHuman(name, output, requiredPatterns) { assert( !output.trimStart().startsWith("{"), `${name} default output should be human-readable text, not JSON` ); for (const pattern of requiredPatterns) { assert.match(output, pattern, `${name} human output missing ${pattern}`); } } const helpHuman = clusterflux(["help"]); assertHuman("help", helpHuman, [ /Primary workflow:/, /clusterflux login --browser/, /clusterflux project init/, /clusterflux node attach; clusterflux-node --worker/, /Clusterflux: Launch Virtual Process/, /Hosted account creation happens in the browser login flow/, /--json/, ]); const loginHuman = clusterflux([ "login", "--plan", "--coordinator", "https://coord.example.test", ]); assertHuman("login", loginHuman, [ /Clusterflux login/, /flow: browser/, ]); const loginJson = json([ "login", "--plan", "--coordinator", "https://coord.example.test", "--json", ]); assert.strictEqual(loginJson.coordinator, "https://coord.example.test"); assert(loginJson.human_flow.Browser); assert.strictEqual(loginJson.human_flow.Browser.hosted_callback, true); assert.strictEqual(loginJson.human_flow.Browser.cli_submits_identity_claims, false); const doctorHuman = clusterflux(["doctor"]); assertHuman("doctor", doctorHuman, [ /Clusterflux doctor/, /coordinator reachability: not_configured/, /dependencies:/, /auth:/, /node capabilities:/, /node readiness: (ready_to_attach|local_dependencies_missing|limited_capabilities)/, /node next:/, ]); const doctorJson = json(["doctor", "--json"]); assert.strictEqual(doctorJson.coordinator_reachability.checked, false); assert.strictEqual(doctorJson.coordinator_reachability.status, "not_configured"); assert( ["ready_to_attach", "local_dependencies_missing", "limited_capabilities"].includes( doctorJson.node_readiness_summary.status ) ); assert.strictEqual(doctorJson.node_readiness_summary.explicit_attach_required, true); assert.strictEqual( doctorJson.node_readiness_summary.command_execution_capability, true ); assert(Array.isArray(doctorJson.node_readiness_summary.missing_local_dependencies)); assert(doctorJson.node_readiness_summary.next_actions.length >= 2); const authJson = json(["auth", "status", "--json"], { CLUSTERFLUX_TOKEN: "token", CLUSTERFLUX_TOKEN_EXPIRES_AT: "2026-07-04T00:00:00Z", }, isolatedCwd); assert.strictEqual(authJson.session.kind, "human"); assert.strictEqual(authJson.session.token_expiry_posture, "expires_at"); assert.strictEqual(authJson.session.expires_at, "2026-07-04T00:00:00Z"); assert.strictEqual(authJson.coordinator_account_status.checked, false); assert.strictEqual(authJson.coordinator_account_status.account_status, "unknown"); assert.strictEqual( authJson.coordinator_account_status.private_moderation_details_exposed, false ); const inspectHuman = clusterflux(["bundle", "inspect", "--project", project]); assertHuman("bundle inspect", inspectHuman, [ /Clusterflux bundle inspect/, /bundle: sha256:/, /environments:/, ]); const inspectJson = json(["bundle", "inspect", "--project", project, "--json"]); assert.strictEqual(inspectJson.project, project); assert.match(inspectJson.metadata.identity, /^sha256:/); assert.match(inspectJson.metadata.wasm_code, /^sha256:/); assert.strictEqual(inspectJson.metadata.task_metadata.default_entrypoint, "build"); assert.deepStrictEqual(inspectJson.metadata.task_metadata.entrypoints, [ "build", "fail", "identity", "long-join", "park-wake", "restart", ]); assert.strictEqual( inspectJson.metadata.source_metadata.transfer_policy.coordinator_receives_source_bytes_by_default, false ); assert.strictEqual( inspectJson.metadata.source_metadata.transfer_policy.default_full_repo_tarball, false ); assert.strictEqual(inspectJson.metadata.debug_metadata.dap_virtual_process, true); assert.strictEqual( inspectJson.metadata.large_input_policy.selected_inputs_are_content_digests, true ); assert.strictEqual(inspectJson.metadata.large_input_policy.selected_input_bytes_included, false); assert.strictEqual(inspectJson.metadata.large_input_policy.full_repository_bytes_included, false); assert.strictEqual( inspectJson.metadata.large_input_policy.silent_task_argument_serialization, false ); assert(inspectJson.metadata.large_input_policy.supported_handle_types.includes("SourceSnapshot")); assert.strictEqual( inspectJson.metadata.restart_compatibility.source_edits_can_restart_from_clean_task_boundary, true ); assert.strictEqual( inspectJson.metadata.restart_compatibility.requires_clean_checkpoint_boundary, true ); assert.strictEqual( inspectJson.metadata.restart_compatibility.compares_task_abi, inspectJson.metadata.task_metadata.task_abi ); assert.strictEqual( inspectJson.metadata.restart_compatibility.incompatible_changes_require_whole_process_restart, true ); console.log("CLI output mode smoke passed");