import fs from "node:fs"; import path from "node:path"; import { DEV_ENDPOINT } from "../../../internal/protocol/index.mjs"; const DEFAULT_PROJECTS = [ { projectId: "proj_mvp-l6", name: "HWLAB L6 MVP", status: "active", environment: "dev", updatedAt: "2026-05-21T00:00:00.000Z" }, { projectId: "proj_cloud-web", name: "Cloud Web Skeleton", status: "active", environment: "dev", updatedAt: "2026-05-20T12:00:00.000Z" } ]; function loadRuntimeFixture(cwd) { const fixturePath = path.resolve(cwd, "fixtures/mvp/runtime.json"); if (!fs.existsSync(fixturePath)) { return null; } const raw = fs.readFileSync(fixturePath, "utf8"); return JSON.parse(raw); } function resolveRuntime(cwd) { const fixture = loadRuntimeFixture(cwd); if (fixture) { return fixture; } return { endpoints: { dev: DEV_ENDPOINT }, projects: DEFAULT_PROJECTS, mvpSteps: [ "browser/CLI/gateway", "master hwlab-edge-proxy", "frp", "D601 hwlab-dev/hwlab-router", "cloud-web/cloud-api", "hardware trusted closed loop", "agent automation closed loop", "evidence record", "worker cleanup" ], loops: [ { name: "hardware trusted closed loop" }, { name: "agent automation closed loop" } ], evidence: [], cleanup: [] }; } function formatJson(value) { return JSON.stringify(value, null, 2); } function writeLine(stream, line = "") { stream.write(`${line}\n`); } function writeProjectList(runtime, stdout) { writeLine(stdout, "hwlab-cli project list"); writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`); for (const project of runtime.projects ?? []) { writeLine( stdout, `${project.projectId} | ${project.name} | ${project.status} | ${project.environment} | ${project.updatedAt}` ); } } function writeHealth(runtime, stdout) { writeLine(stdout, "hwlab-cli health"); writeLine(stdout, "status: ok"); writeLine(stdout, `environment: dev`); writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`); writeLine(stdout, `projects: ${(runtime.projects ?? []).length}`); } function writeDryRun(runtime, stdout) { writeLine(stdout, "hwlab-cli test e2e --env dev --mvp --dry-run"); writeLine(stdout, `endpoint: ${runtime.endpoints?.dev ?? DEV_ENDPOINT}`); writeLine(stdout, "mvp route:"); writeLine( stdout, ` ${runtime.serviceRoute?.join(" -> ") ?? "browser/CLI/gateway -> master hwlab-edge-proxy -> frp -> D601 hwlab-dev/hwlab-router -> cloud-web/cloud-api"}` ); for (const step of runtime.mvpSteps ?? []) { writeLine(stdout, `- ${step}`); } writeLine(stdout, "closed loops:"); for (const loop of runtime.loops ?? []) { writeLine(stdout, `- ${loop.name}${loop.description ? `: ${loop.description}` : ""}`); } writeLine(stdout, "evidence record:"); for (const evidence of runtime.evidence ?? []) { writeLine( stdout, `- ${evidence.evidenceId} | ${evidence.kind} | ${evidence.serviceId} | ${evidence.uri}` ); } writeLine(stdout, "worker cleanup:"); for (const step of runtime.cleanup ?? []) { writeLine(stdout, `- ${step}`); } writeLine(stdout, "dry-run only: no DEV/PROD changes were made"); } function writeHelp(stdout) { writeLine(stdout, "hwlab-cli"); writeLine(stdout, "commands:"); writeLine(stdout, " health"); writeLine(stdout, " project list"); writeLine(stdout, " test e2e --env dev --mvp --dry-run"); } function parseArgs(args) { const flags = new Set(); const options = new Map(); const rest = []; for (let index = 0; index < args.length; index += 1) { const arg = args[index]; if (arg.startsWith("--")) { flags.add(arg); const next = args[index + 1]; if (next && !next.startsWith("--")) { options.set(arg, next); index += 1; } } else { rest.push(arg); } } return { flags, options, rest }; } export async function runCli(argv, io) { const stdout = io.stdout ?? process.stdout; const stderr = io.stderr ?? process.stderr; const runtime = resolveRuntime(io.cwd ?? process.cwd()); const [command = "help", subcommand, ...rest] = argv; const { flags, options } = parseArgs(rest); if (command === "health") { writeHealth(runtime, stdout); return 0; } if (command === "project" && subcommand === "list") { writeProjectList(runtime, stdout); return 0; } if (command === "test" && subcommand === "e2e") { const env = options.get("--env") ?? null; const isDryRun = flags.has("--dry-run"); const isMvp = flags.has("--mvp"); if (env !== "dev") { writeLine(stderr, "only --env dev is supported in the skeleton"); return 1; } if (!isMvp || !isDryRun) { writeLine(stderr, "use --mvp --dry-run for the skeleton"); return 1; } writeDryRun(runtime, stdout); return 0; } if (command === "project" && !subcommand) { writeLine(stderr, "usage: hwlab-cli project list"); return 1; } if (command === "test" && !subcommand) { writeLine(stderr, "usage: hwlab-cli test e2e --env dev --mvp --dry-run"); return 1; } writeHelp(stdout); return 0; } export function formatRuntime(runtime) { return formatJson(runtime); }