@beastmode-develeap/beastmode 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6402,13 +6402,13 @@ var init_server = __esm({
6402
6402
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6403
6403
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6404
6404
  import { z as z2 } from "zod";
6405
- import { readFileSync as readFileSync25, writeFileSync as writeFileSync22, existsSync as existsSync29, readdirSync as readdirSync10, mkdirSync as mkdirSync18 } from "fs";
6405
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync22, existsSync as existsSync29, readdirSync as readdirSync10, mkdirSync as mkdirSync18 } from "fs";
6406
6406
  import { join as join27, resolve as resolve18, basename as basename5 } from "path";
6407
6407
  import { randomUUID as randomUUID3 } from "crypto";
6408
6408
  function readJsonFile2(filePath) {
6409
6409
  if (!existsSync29(filePath)) return null;
6410
6410
  try {
6411
- return JSON.parse(readFileSync25(filePath, "utf-8"));
6411
+ return JSON.parse(readFileSync26(filePath, "utf-8"));
6412
6412
  } catch {
6413
6413
  return null;
6414
6414
  }
@@ -6435,7 +6435,7 @@ function getFactoryPath() {
6435
6435
  function readFactoryStatus(factoryDir) {
6436
6436
  const bmDir = join27(factoryDir, ".beastmode");
6437
6437
  const factoryIdentity = FactoryIdentitySchema.parse(
6438
- JSON.parse(readFileSync25(join27(bmDir, "factory.json"), "utf-8"))
6438
+ JSON.parse(readFileSync26(join27(bmDir, "factory.json"), "utf-8"))
6439
6439
  );
6440
6440
  const projectsDir = join27(bmDir, "projects");
6441
6441
  const projectCount = existsSync29(projectsDir) ? readdirSync10(projectsDir).filter((f) => f.endsWith(".json")).length : 0;
@@ -6443,7 +6443,7 @@ function readFactoryStatus(factoryDir) {
6443
6443
  let pluginNames = [];
6444
6444
  if (existsSync29(lockPath)) {
6445
6445
  try {
6446
- const lock = JSON.parse(readFileSync25(lockPath, "utf-8"));
6446
+ const lock = JSON.parse(readFileSync26(lockPath, "utf-8"));
6447
6447
  pluginNames = Object.keys(lock.plugins || {});
6448
6448
  } catch {
6449
6449
  }
@@ -6479,7 +6479,7 @@ function readFactoryStatus(factoryDir) {
6479
6479
  let pidAlive = false;
6480
6480
  if (existsSync29(pidFile)) {
6481
6481
  try {
6482
- daemonPid = parseInt(readFileSync25(pidFile, "utf-8").trim(), 10);
6482
+ daemonPid = parseInt(readFileSync26(pidFile, "utf-8").trim(), 10);
6483
6483
  process.kill(daemonPid, 0);
6484
6484
  pidAlive = true;
6485
6485
  } catch {
@@ -6503,7 +6503,7 @@ function readBoardItems(factoryDir) {
6503
6503
  const filePath = join27(factoryDir, ".beastmode", "board.json");
6504
6504
  if (!existsSync29(filePath)) return [];
6505
6505
  try {
6506
- const raw = JSON.parse(readFileSync25(filePath, "utf-8"));
6506
+ const raw = JSON.parse(readFileSync26(filePath, "utf-8"));
6507
6507
  return Array.isArray(raw.items) ? raw.items : [];
6508
6508
  } catch {
6509
6509
  return [];
@@ -6535,7 +6535,7 @@ function createMcpServer() {
6535
6535
  async ({ key_path }) => {
6536
6536
  const factoryDir = getFactoryPath();
6537
6537
  const configPath = join27(factoryDir, ".beastmode", "config.json");
6538
- const config = existsSync29(configPath) ? JSON.parse(readFileSync25(configPath, "utf-8")) : generateDefaults();
6538
+ const config = existsSync29(configPath) ? JSON.parse(readFileSync26(configPath, "utf-8")) : generateDefaults();
6539
6539
  try {
6540
6540
  const value = configGet(config, key_path);
6541
6541
  return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
@@ -6554,7 +6554,7 @@ function createMcpServer() {
6554
6554
  async ({ key_path, value }) => {
6555
6555
  const factoryDir = getFactoryPath();
6556
6556
  const configPath = join27(factoryDir, ".beastmode", "config.json");
6557
- const config = existsSync29(configPath) ? JSON.parse(readFileSync25(configPath, "utf-8")) : generateDefaults();
6557
+ const config = existsSync29(configPath) ? JSON.parse(readFileSync26(configPath, "utf-8")) : generateDefaults();
6558
6558
  const coerced = coerceValue(value);
6559
6559
  const updated = configSet(config, key_path, coerced);
6560
6560
  writeFileSync22(configPath, JSON.stringify(updated, null, 2) + "\n", "utf-8");
@@ -6673,7 +6673,7 @@ function createMcpServer() {
6673
6673
  const lockPath = join27(bmDir, "extensions.lock");
6674
6674
  if (existsSync29(lockPath)) {
6675
6675
  try {
6676
- const lock = JSON.parse(readFileSync25(lockPath, "utf-8"));
6676
+ const lock = JSON.parse(readFileSync26(lockPath, "utf-8"));
6677
6677
  plugins = lock.plugins || {};
6678
6678
  } catch {
6679
6679
  }
@@ -6713,7 +6713,7 @@ function createMcpServer() {
6713
6713
  }
6714
6714
  const projects = readdirSync10(projectsDir).filter((f) => f.endsWith(".json")).map((f) => {
6715
6715
  try {
6716
- return JSON.parse(readFileSync25(join27(projectsDir, f), "utf-8"));
6716
+ return JSON.parse(readFileSync26(join27(projectsDir, f), "utf-8"));
6717
6717
  } catch {
6718
6718
  return null;
6719
6719
  }
@@ -6859,7 +6859,7 @@ init_file_writer();
6859
6859
  import { Command } from "commander";
6860
6860
  import inquirer from "inquirer";
6861
6861
  import { resolve as resolve5, basename as basename4, join as join15 } from "path";
6862
- import { existsSync as existsSync17, writeFileSync as writeFileSync13, mkdirSync as mkdirSync12 } from "fs";
6862
+ import { existsSync as existsSync17, writeFileSync as writeFileSync13, mkdirSync as mkdirSync12, readFileSync as readFileSync14 } from "fs";
6863
6863
 
6864
6864
  // src/cli/utils/docker.ts
6865
6865
  import { existsSync as existsSync9 } from "fs";
@@ -6908,7 +6908,24 @@ function loginToGhcr(token) {
6908
6908
  timeout: 15e3,
6909
6909
  stdio: ["pipe", "pipe", "pipe"]
6910
6910
  });
6911
- return true;
6911
+ try {
6912
+ execSync(`docker manifest inspect ${GHCR_IMAGE_PREFIX}/board:latest`, {
6913
+ encoding: "utf-8",
6914
+ timeout: 15e3,
6915
+ stdio: ["pipe", "pipe", "pipe"]
6916
+ });
6917
+ return true;
6918
+ } catch {
6919
+ try {
6920
+ execSync("docker logout ghcr.io", {
6921
+ encoding: "utf-8",
6922
+ timeout: 5e3,
6923
+ stdio: ["pipe", "pipe", "pipe"]
6924
+ });
6925
+ } catch {
6926
+ }
6927
+ return false;
6928
+ }
6912
6929
  } catch {
6913
6930
  return false;
6914
6931
  }
@@ -7051,7 +7068,7 @@ function step(n, total, text) {
7051
7068
  }
7052
7069
 
7053
7070
  // src/cli/commands/init.ts
7054
- var initCommand = new Command("init").description("Create a new BeastMode factory").argument("[name]", "Factory name (default: current directory name)").option("--project <path>", "Path to target project").option("--preset <preset>", "Pipeline preset (full, lean, prototype, infra, docs)").option("--backend <backend>", "Task backend (beastmode-board, github-issues)").option("--deploy <target>", "Deploy target (pr-only, vercel, aws-ecs, ...)").option("--methodology <name>", "Development methodology plugin").option("--plugin <name>", "Install plugin (repeatable)", collect, []).option("--from <template>", "Import config from template file").option("--ui", "Open web wizard instead of CLI").option("--yes", "Accept all defaults (non-interactive)").option("--github-token <token>", "GitHub PAT (avoids interactive prompt)").option("--board-password <password>", "Board UI password (avoids interactive prompt)").action(async (name, opts) => {
7071
+ var initCommand = new Command("init").description("Create a new BeastMode factory").argument("[name]", "Factory name (default: current directory name)").option("--project <path>", "Path to target project").option("--preset <preset>", "Pipeline preset (full, lean, prototype, infra, docs)").option("--backend <backend>", "Task backend (beastmode-board, github-issues)").option("--deploy <target>", "Deploy target (pr-only, vercel, aws-ecs, ...)").option("--methodology <name>", "Development methodology plugin").option("--plugin <name>", "Install plugin (repeatable)", collect, []).option("--from <template>", "Import config from template file").option("--ui", "Open web wizard instead of CLI").option("--yes", "Accept all defaults (non-interactive)").option("--github-token <token>", "GitHub PAT (avoids interactive prompt)").option("--github-token-file <path>", "Read GitHub PAT from file (safer than --github-token)").option("--board-password <password>", "Board UI password (avoids interactive prompt)").option("--board-password-file <path>", "Read board password from file").action(async (name, opts) => {
7055
7072
  try {
7056
7073
  await runInit(name, opts);
7057
7074
  } catch (err) {
@@ -7063,6 +7080,9 @@ function collect(val, acc) {
7063
7080
  acc.push(val);
7064
7081
  return acc;
7065
7082
  }
7083
+ function readSecretFile(filePath) {
7084
+ return readFileSync14(resolve5(filePath), "utf-8").trim();
7085
+ }
7066
7086
  function isSourceRepo(dir) {
7067
7087
  return existsSync17(resolve5(dir, "daemon")) && existsSync17(resolve5(dir, "board")) && existsSync17(resolve5(dir, "cli"));
7068
7088
  }
@@ -7107,8 +7127,8 @@ async function runInit(name, opts) {
7107
7127
  throw new Error(`Factory already exists at ./${factoryName}. Use 'beastmode config' to modify.`);
7108
7128
  }
7109
7129
  if (opts.from) {
7110
- const { readFileSync: readFileSync28 } = await import("fs");
7111
- const templateContent = readFileSync28(resolve5(opts.from), "utf-8");
7130
+ const { readFileSync: readFileSync29 } = await import("fs");
7131
+ const templateContent = readFileSync29(resolve5(opts.from), "utf-8");
7112
7132
  const { parseTemplate: parseTemplate2 } = await Promise.resolve().then(() => (init_template_importer(), template_importer_exports));
7113
7133
  const template = parseTemplate2(templateContent);
7114
7134
  info(`Importing from template: ${opts.from}`);
@@ -7252,6 +7272,11 @@ async function runInit(name, opts) {
7252
7272
  task_backend: { adapter: backendAdapter }
7253
7273
  };
7254
7274
  const config = resolveDefaults(partialConfig, stack);
7275
+ if (opts.githubTokenFile && !process.env.GITHUB_TOKEN) {
7276
+ process.env.GITHUB_TOKEN = readSecretFile(opts.githubTokenFile);
7277
+ } else if (opts.githubToken && !process.env.GITHUB_TOKEN) {
7278
+ process.env.GITHUB_TOKEN = opts.githubToken;
7279
+ }
7255
7280
  const secretReport = validateSecrets(config, process.env, {
7256
7281
  deploy_target: deployTarget
7257
7282
  });
@@ -7288,8 +7313,8 @@ async function runInit(name, opts) {
7288
7313
  }
7289
7314
  }
7290
7315
  }
7291
- let uiPassword = "";
7292
- if (!opts.yes) {
7316
+ let uiPassword = opts.boardPassword || (opts.boardPasswordFile ? readSecretFile(opts.boardPasswordFile) : "") || "";
7317
+ if (!uiPassword && !opts.yes) {
7293
7318
  const answer = await inquirer.prompt([
7294
7319
  {
7295
7320
  type: "password",
@@ -7304,6 +7329,8 @@ async function runInit(name, opts) {
7304
7329
  } else {
7305
7330
  info("No board password \u2014 UI will be open (fine for local dev)");
7306
7331
  }
7332
+ } else if (uiPassword) {
7333
+ success("Board UI password set");
7307
7334
  }
7308
7335
  step(5, totalSteps, "Boot");
7309
7336
  const projectName = basename4(projectPath);
@@ -7356,7 +7383,7 @@ async function runImageModeInit(name, opts) {
7356
7383
  const factoryName = name || ".";
7357
7384
  const targetDir = resolve5(factoryName === "." ? "." : factoryName);
7358
7385
  step(1, totalSteps, "Credentials");
7359
- let githubToken = opts.githubToken || process.env.GITHUB_TOKEN || "";
7386
+ let githubToken = opts.githubToken || (opts.githubTokenFile ? readSecretFile(opts.githubTokenFile) : "") || process.env.GITHUB_TOKEN || "";
7360
7387
  if (!githubToken && !opts.yes) {
7361
7388
  const answer = await inquirer.prompt([
7362
7389
  {
@@ -7373,7 +7400,7 @@ async function runImageModeInit(name, opts) {
7373
7400
  } else {
7374
7401
  warn("GITHUB_TOKEN not set \u2014 add to .env later");
7375
7402
  }
7376
- let uiPassword = opts.boardPassword || "";
7403
+ let uiPassword = opts.boardPassword || (opts.boardPasswordFile ? readSecretFile(opts.boardPasswordFile) : "") || "";
7377
7404
  if (!uiPassword && !opts.yes) {
7378
7405
  const { password } = await inquirer.prompt([
7379
7406
  {
@@ -7481,7 +7508,7 @@ async function runImageModeInit(name, opts) {
7481
7508
  // src/cli/commands/export-config.ts
7482
7509
  init_export_adapter();
7483
7510
  import { Command as Command2 } from "commander";
7484
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync14, existsSync as existsSync18, readdirSync as readdirSync7 } from "fs";
7511
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync14, existsSync as existsSync18, readdirSync as readdirSync7 } from "fs";
7485
7512
  import { resolve as resolve6, join as join16 } from "path";
7486
7513
  function exportFactory(factoryDir, outputPath) {
7487
7514
  const bmDir = join16(factoryDir, ".beastmode");
@@ -7489,12 +7516,12 @@ function exportFactory(factoryDir, outputPath) {
7489
7516
  if (!existsSync18(configPath)) {
7490
7517
  throw new Error(`No factory found at ${factoryDir}`);
7491
7518
  }
7492
- const config = JSON.parse(readFileSync14(configPath, "utf-8"));
7493
- const identity = JSON.parse(readFileSync14(join16(bmDir, "factory.json"), "utf-8"));
7519
+ const config = JSON.parse(readFileSync15(configPath, "utf-8"));
7520
+ const identity = JSON.parse(readFileSync15(join16(bmDir, "factory.json"), "utf-8"));
7494
7521
  let plugins = [];
7495
7522
  const lockPath = join16(bmDir, "extensions.lock");
7496
7523
  if (existsSync18(lockPath)) {
7497
- const lock = JSON.parse(readFileSync14(lockPath, "utf-8"));
7524
+ const lock = JSON.parse(readFileSync15(lockPath, "utf-8"));
7498
7525
  plugins = Object.keys(lock.plugins || {});
7499
7526
  }
7500
7527
  const template = {
@@ -7530,14 +7557,14 @@ function createArtifactExportCommand(artifact) {
7530
7557
  throw new Error(`No scenarios directory found in run ${opts.run}`);
7531
7558
  }
7532
7559
  const files = readdirSync7(scenariosDir).filter((f) => f.endsWith(".md")).sort();
7533
- sourceContent = files.map((f) => readFileSync14(join16(scenariosDir, f), "utf-8")).join("\n\n---\n\n");
7560
+ sourceContent = files.map((f) => readFileSync15(join16(scenariosDir, f), "utf-8")).join("\n\n---\n\n");
7534
7561
  } else {
7535
7562
  const artifactFile = artifact === "nlspec" ? "nlspec.md" : "plan.md";
7536
7563
  const artifactPath = join16(runDir, artifactFile);
7537
7564
  if (!existsSync18(artifactPath)) {
7538
7565
  throw new Error(`${artifactFile} not found in run ${opts.run}`);
7539
7566
  }
7540
- sourceContent = readFileSync14(artifactPath, "utf-8");
7567
+ sourceContent = readFileSync15(artifactPath, "utf-8");
7541
7568
  }
7542
7569
  const result = runExportAdapter(opts.adapter, sourceContent);
7543
7570
  if (opts.output) {
@@ -7761,7 +7788,7 @@ init_skill_manager();
7761
7788
  init_presets();
7762
7789
  import { Command as Command6 } from "commander";
7763
7790
  import { resolve as resolve10 } from "path";
7764
- import { readFileSync as readFileSync15, existsSync as existsSync19 } from "fs";
7791
+ import { readFileSync as readFileSync16, existsSync as existsSync19 } from "fs";
7765
7792
  import { join as join17 } from "path";
7766
7793
  function listPluginsAction(factoryDir) {
7767
7794
  const lockPath = join17(factoryDir, ".beastmode", "extensions.lock");
@@ -7769,7 +7796,7 @@ function listPluginsAction(factoryDir) {
7769
7796
  console.log(" No plugins installed (extensions.lock not found).");
7770
7797
  return;
7771
7798
  }
7772
- const lock = JSON.parse(readFileSync15(lockPath, "utf-8"));
7799
+ const lock = JSON.parse(readFileSync16(lockPath, "utf-8"));
7773
7800
  const plugins = lock.plugins || {};
7774
7801
  const names = Object.keys(plugins);
7775
7802
  if (names.length === 0) {
@@ -7867,7 +7894,7 @@ var listCommand = new Command6("list").description("List installed extensions an
7867
7894
  // src/cli/commands/import-cmd.ts
7868
7895
  init_import_adapter();
7869
7896
  import { Command as Command7 } from "commander";
7870
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync15, mkdirSync as mkdirSync13, existsSync as existsSync20 } from "fs";
7897
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync15, mkdirSync as mkdirSync13, existsSync as existsSync20 } from "fs";
7871
7898
  import { resolve as resolve11, join as join18 } from "path";
7872
7899
  var VALID_ARTIFACTS = ["nlspec", "plan", "scenarios"];
7873
7900
  function createArtifactCommand(artifact) {
@@ -7877,7 +7904,7 @@ function createArtifactCommand(artifact) {
7877
7904
  if (!existsSync20(sourcePath)) {
7878
7905
  throw new Error(`Source file not found: ${sourcePath}`);
7879
7906
  }
7880
- const sourceContent = readFileSync16(sourcePath, "utf-8");
7907
+ const sourceContent = readFileSync17(sourcePath, "utf-8");
7881
7908
  const result = runImportAdapter(opts.adapter, sourceContent);
7882
7909
  if (opts.output) {
7883
7910
  const outputPath = resolve11(opts.output);
@@ -7913,7 +7940,7 @@ for (const artifact of VALID_ARTIFACTS) {
7913
7940
  init_status_checker();
7914
7941
  init_schemas();
7915
7942
  import { Command as Command8 } from "commander";
7916
- import { existsSync as existsSync21, readFileSync as readFileSync17, readdirSync as readdirSync8 } from "fs";
7943
+ import { existsSync as existsSync21, readFileSync as readFileSync18, readdirSync as readdirSync8 } from "fs";
7917
7944
  import { execSync as execSync4 } from "child_process";
7918
7945
  import { join as join19, resolve as resolve12 } from "path";
7919
7946
  function statusAction(factoryDir, opts) {
@@ -7922,7 +7949,7 @@ function statusAction(factoryDir, opts) {
7922
7949
  throw new Error(`No factory found at ${factoryDir}`);
7923
7950
  }
7924
7951
  const factoryJsonPath = join19(bmDir, "factory.json");
7925
- const rawIdentity = JSON.parse(readFileSync17(factoryJsonPath, "utf-8"));
7952
+ const rawIdentity = JSON.parse(readFileSync18(factoryJsonPath, "utf-8"));
7926
7953
  const factoryIdentity = FactoryIdentitySchema.parse(rawIdentity);
7927
7954
  const projectsDir = join19(bmDir, "projects");
7928
7955
  const projectCount = existsSync21(projectsDir) ? readdirSync8(projectsDir).filter((f) => f.endsWith(".json")).length : 0;
@@ -7932,7 +7959,7 @@ function statusAction(factoryDir, opts) {
7932
7959
  let mcpServers = {};
7933
7960
  if (existsSync21(mcpPath)) {
7934
7961
  try {
7935
- const raw = JSON.parse(readFileSync17(mcpPath, "utf-8"));
7962
+ const raw = JSON.parse(readFileSync18(mcpPath, "utf-8"));
7936
7963
  mcpServers = raw.servers || {};
7937
7964
  } catch {
7938
7965
  }
@@ -7941,7 +7968,7 @@ function statusAction(factoryDir, opts) {
7941
7968
  let hooks = {};
7942
7969
  if (existsSync21(hooksPath)) {
7943
7970
  try {
7944
- const raw = JSON.parse(readFileSync17(hooksPath, "utf-8"));
7971
+ const raw = JSON.parse(readFileSync18(hooksPath, "utf-8"));
7945
7972
  hooks = raw.hooks || {};
7946
7973
  } catch {
7947
7974
  }
@@ -7958,7 +7985,7 @@ function statusAction(factoryDir, opts) {
7958
7985
  let pidAlive = false;
7959
7986
  if (existsSync21(pidPath)) {
7960
7987
  try {
7961
- daemonPid = parseInt(readFileSync17(pidPath, "utf-8").trim(), 10);
7988
+ daemonPid = parseInt(readFileSync18(pidPath, "utf-8").trim(), 10);
7962
7989
  process.kill(daemonPid, 0);
7963
7990
  pidAlive = true;
7964
7991
  } catch {
@@ -8031,7 +8058,7 @@ var statusCommand = new Command8("status").description("Show factory status over
8031
8058
  // src/cli/commands/config-cmd.ts
8032
8059
  init_config_manager();
8033
8060
  import { Command as Command9 } from "commander";
8034
- import { existsSync as existsSync22, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "fs";
8061
+ import { existsSync as existsSync22, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "fs";
8035
8062
  import { join as join20, resolve as resolve13 } from "path";
8036
8063
  import { execSync as execSync5 } from "child_process";
8037
8064
  function readConfig2(factoryDir) {
@@ -8039,7 +8066,7 @@ function readConfig2(factoryDir) {
8039
8066
  if (!existsSync22(configPath)) {
8040
8067
  throw new Error("No config.json found. Run beastmode init first.");
8041
8068
  }
8042
- return JSON.parse(readFileSync18(configPath, "utf-8"));
8069
+ return JSON.parse(readFileSync19(configPath, "utf-8"));
8043
8070
  }
8044
8071
  function writeConfig2(factoryDir, config) {
8045
8072
  const configPath = join20(factoryDir, ".beastmode", "config.json");
@@ -8121,7 +8148,7 @@ init_schemas();
8121
8148
  init_version();
8122
8149
  init_plugin_resolver();
8123
8150
  import { Command as Command11 } from "commander";
8124
- import { existsSync as existsSync24, readFileSync as readFileSync20, readdirSync as readdirSync9 } from "fs";
8151
+ import { existsSync as existsSync24, readFileSync as readFileSync21, readdirSync as readdirSync9 } from "fs";
8125
8152
  import { join as join22, resolve as resolve15 } from "path";
8126
8153
  import { execSync as execSync6 } from "child_process";
8127
8154
  import { homedir as homedir2, platform } from "os";
@@ -8131,7 +8158,7 @@ import * as https from "https";
8131
8158
  // src/cli/commands/board.ts
8132
8159
  import { Command as Command10 } from "commander";
8133
8160
  import { resolve as resolve14, join as join21 } from "path";
8134
- import { existsSync as existsSync23, readFileSync as readFileSync19, mkdirSync as mkdirSync14, writeFileSync as writeFileSync17 } from "fs";
8161
+ import { existsSync as existsSync23, readFileSync as readFileSync20, mkdirSync as mkdirSync14, writeFileSync as writeFileSync17 } from "fs";
8135
8162
  var boardCommand = new Command10("board").description("Launch the BeastMode Board web UI").option("--port <number>", "Port to serve on", "7669").option("--host <host>", "Host to bind to (use 0.0.0.0 for external access)", "127.0.0.1").action(async (opts) => {
8136
8163
  try {
8137
8164
  await runBoard(opts);
@@ -8175,7 +8202,7 @@ async function runBoard(opts) {
8175
8202
  }
8176
8203
  }
8177
8204
  const factoryJsonPath = join21(factoryDir, ".beastmode", "factory.json");
8178
- const factoryJson = JSON.parse(readFileSync19(factoryJsonPath, "utf-8"));
8205
+ const factoryJson = JSON.parse(readFileSync20(factoryJsonPath, "utf-8"));
8179
8206
  const factoryName = factoryJson.factory_name || "BeastMode Factory";
8180
8207
  header(`BeastMode Board \u2014 ${factoryName}`);
8181
8208
  const { startServer: startServer2 } = await Promise.resolve().then(() => (init_server(), server_exports));
@@ -8413,7 +8440,7 @@ function checkProjectDirectory(factoryDir) {
8413
8440
  let anyFail = false;
8414
8441
  for (const file of projectFiles) {
8415
8442
  try {
8416
- const proj = JSON.parse(readFileSync20(join22(projectsDir, file), "utf-8"));
8443
+ const proj = JSON.parse(readFileSync21(join22(projectsDir, file), "utf-8"));
8417
8444
  const projPath = proj.path || "";
8418
8445
  const projName = proj.name || file.replace(".json", "");
8419
8446
  if (!projPath || !existsSync24(projPath)) {
@@ -8497,7 +8524,7 @@ function checkStack(factoryDir) {
8497
8524
  const stacks = [];
8498
8525
  for (const file of projectFiles) {
8499
8526
  try {
8500
- const proj = JSON.parse(readFileSync20(join22(projectsDir, file), "utf-8"));
8527
+ const proj = JSON.parse(readFileSync21(join22(projectsDir, file), "utf-8"));
8501
8528
  const name = proj.name || file.replace(".json", "");
8502
8529
  const detected = proj.stack?.detected || "unknown";
8503
8530
  const build = proj.stack?.build_command || "";
@@ -8546,7 +8573,7 @@ function checkBoardPassword(env, factoryDir) {
8546
8573
  for (const filePath of [dotEnv, secretsEnv]) {
8547
8574
  if (existsSync24(filePath)) {
8548
8575
  try {
8549
- const content = readFileSync20(filePath, "utf-8");
8576
+ const content = readFileSync21(filePath, "utf-8");
8550
8577
  const lines = content.split("\n");
8551
8578
  const line = lines.find((l) => l.startsWith("BEASTMODE_UI_PASSWORD="));
8552
8579
  if (line) {
@@ -8573,7 +8600,7 @@ function doctorAction(factoryDir, env) {
8573
8600
  let factoryIdentity = null;
8574
8601
  if (factoryDirExists) {
8575
8602
  try {
8576
- const raw = JSON.parse(readFileSync20(join22(bmDir, "factory.json"), "utf-8"));
8603
+ const raw = JSON.parse(readFileSync21(join22(bmDir, "factory.json"), "utf-8"));
8577
8604
  factoryIdentity = FactoryIdentitySchema.parse(raw);
8578
8605
  } catch {
8579
8606
  }
@@ -8584,7 +8611,7 @@ function doctorAction(factoryDir, env) {
8584
8611
  const configPath = join22(bmDir, "config.json");
8585
8612
  if (existsSync24(configPath)) {
8586
8613
  try {
8587
- const raw = JSON.parse(readFileSync20(configPath, "utf-8"));
8614
+ const raw = JSON.parse(readFileSync21(configPath, "utf-8"));
8588
8615
  const result = FactoryConfigSchema.safeParse(raw);
8589
8616
  if (result.success) {
8590
8617
  config = raw;
@@ -8605,7 +8632,7 @@ function doctorAction(factoryDir, env) {
8605
8632
  for (const file of readdirSync9(projectsDir)) {
8606
8633
  if (file.endsWith(".json")) {
8607
8634
  try {
8608
- const proj = JSON.parse(readFileSync20(join22(projectsDir, file), "utf-8"));
8635
+ const proj = JSON.parse(readFileSync21(join22(projectsDir, file), "utf-8"));
8609
8636
  if (proj.path) {
8610
8637
  projectPaths.push({
8611
8638
  name: proj.name || file.replace(".json", ""),
@@ -8627,7 +8654,7 @@ function doctorAction(factoryDir, env) {
8627
8654
  const manifestPath = join22(pluginsDir, pluginName, "manifest.json");
8628
8655
  if (existsSync24(manifestPath)) {
8629
8656
  try {
8630
- const manifest = JSON.parse(readFileSync20(manifestPath, "utf-8"));
8657
+ const manifest = JSON.parse(readFileSync21(manifestPath, "utf-8"));
8631
8658
  installedPlugins.push({
8632
8659
  name: pluginName,
8633
8660
  engine_version: manifest.engine_version || "*"
@@ -8736,21 +8763,21 @@ init_upgrader();
8736
8763
  init_schemas();
8737
8764
  init_version();
8738
8765
  import { Command as Command12 } from "commander";
8739
- import { existsSync as existsSync25, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "fs";
8766
+ import { existsSync as existsSync25, readFileSync as readFileSync22, writeFileSync as writeFileSync18 } from "fs";
8740
8767
  import { join as join23, resolve as resolve16 } from "path";
8741
8768
  function readIdentity(factoryDir) {
8742
8769
  const path = join23(factoryDir, ".beastmode", "factory.json");
8743
8770
  if (!existsSync25(path)) {
8744
8771
  throw new Error("No factory.json found. Run beastmode init first.");
8745
8772
  }
8746
- return FactoryIdentitySchema.parse(JSON.parse(readFileSync21(path, "utf-8")));
8773
+ return FactoryIdentitySchema.parse(JSON.parse(readFileSync22(path, "utf-8")));
8747
8774
  }
8748
8775
  function readConfig3(factoryDir) {
8749
8776
  const path = join23(factoryDir, ".beastmode", "config.json");
8750
8777
  if (!existsSync25(path)) {
8751
8778
  return {};
8752
8779
  }
8753
- return JSON.parse(readFileSync21(path, "utf-8"));
8780
+ return JSON.parse(readFileSync22(path, "utf-8"));
8754
8781
  }
8755
8782
  function upgradeCheckAction(factoryDir) {
8756
8783
  const identity = readIdentity(factoryDir);
@@ -8818,7 +8845,7 @@ var upgradeCommand = new Command12("upgrade").description("Upgrade engine versio
8818
8845
  // src/cli/commands/migrate.ts
8819
8846
  import { Command as Command13 } from "commander";
8820
8847
  import { resolve as resolve17, join as join24 } from "path";
8821
- import { existsSync as existsSync26, readFileSync as readFileSync22, mkdirSync as mkdirSync15, writeFileSync as writeFileSync19 } from "fs";
8848
+ import { existsSync as existsSync26, readFileSync as readFileSync23, mkdirSync as mkdirSync15, writeFileSync as writeFileSync19 } from "fs";
8822
8849
  init_migrator();
8823
8850
  var migrateCommand = new Command13("migrate").description("Migrate a daemon config into a .beastmode/ factory").option("--config <path>", "Path to beastmode.daemon.json").option("--dry-run", "Show what would be created without writing files").action(async (opts) => {
8824
8851
  try {
@@ -8839,7 +8866,7 @@ async function runMigrate(opts) {
8839
8866
  }
8840
8867
  header("BeastMode Migrate");
8841
8868
  info(`Reading daemon config from: ${configPath}`);
8842
- const configContent = readFileSync22(configPath, "utf-8");
8869
+ const configContent = readFileSync23(configPath, "utf-8");
8843
8870
  const daemonConfig = parseDaemonConfig(configContent);
8844
8871
  const runsDir = join24(cwd, "runs");
8845
8872
  let runDirs = [];
@@ -8857,7 +8884,7 @@ async function runMigrate(opts) {
8857
8884
  const cpPath = join24(runsDir, dir, "checkpoint.json");
8858
8885
  if (existsSync26(cpPath)) {
8859
8886
  try {
8860
- const cp = JSON.parse(readFileSync22(cpPath, "utf-8"));
8887
+ const cp = JSON.parse(readFileSync23(cpPath, "utf-8"));
8861
8888
  checkpoints.set(dir, cp);
8862
8889
  } catch {
8863
8890
  }
@@ -8954,7 +8981,7 @@ async function runMigrate(opts) {
8954
8981
  // src/cli/commands/run.ts
8955
8982
  import { Command as Command14 } from "commander";
8956
8983
  import { join as join25 } from "path";
8957
- import { existsSync as existsSync27, readFileSync as readFileSync23, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16 } from "fs";
8984
+ import { existsSync as existsSync27, readFileSync as readFileSync24, writeFileSync as writeFileSync20, mkdirSync as mkdirSync16 } from "fs";
8958
8985
  import { randomUUID as randomUUID2 } from "crypto";
8959
8986
  init_bridge();
8960
8987
  init_schemas();
@@ -8983,7 +9010,7 @@ async function runPipeline(projectName, opts) {
8983
9010
  throw new Error("Factory config not found. Run 'beastmode init' first.");
8984
9011
  }
8985
9012
  const factoryConfig = FactoryConfigSchema.parse(
8986
- JSON.parse(readFileSync23(configPath, "utf-8"))
9013
+ JSON.parse(readFileSync24(configPath, "utf-8"))
8987
9014
  );
8988
9015
  let projectConfig = null;
8989
9016
  const projectsDir = join25(bmDir, "projects");
@@ -9000,11 +9027,11 @@ async function runPipeline(projectName, opts) {
9000
9027
  throw new Error(`Project not found: ${projectName}`);
9001
9028
  }
9002
9029
  projectConfig = ProjectConfigSchema.parse(
9003
- JSON.parse(readFileSync23(join25(projectsDir, file), "utf-8"))
9030
+ JSON.parse(readFileSync24(join25(projectsDir, file), "utf-8"))
9004
9031
  );
9005
9032
  } else if (projectFiles.length > 0) {
9006
9033
  projectConfig = ProjectConfigSchema.parse(
9007
- JSON.parse(readFileSync23(join25(projectsDir, projectFiles[0]), "utf-8"))
9034
+ JSON.parse(readFileSync24(join25(projectsDir, projectFiles[0]), "utf-8"))
9008
9035
  );
9009
9036
  info(`Using project: ${projectConfig.name}`);
9010
9037
  }
@@ -9013,7 +9040,7 @@ async function runPipeline(projectName, opts) {
9013
9040
  let boardItems = [];
9014
9041
  if (existsSync27(boardPath)) {
9015
9042
  try {
9016
- const raw = JSON.parse(readFileSync23(boardPath, "utf-8"));
9043
+ const raw = JSON.parse(readFileSync24(boardPath, "utf-8"));
9017
9044
  boardItems = Array.isArray(raw.items) ? raw.items : [];
9018
9045
  } catch {
9019
9046
  boardItems = [];
@@ -9087,7 +9114,7 @@ async function runPipeline(projectName, opts) {
9087
9114
  const startTime = Date.now();
9088
9115
  const pollInterval = setInterval(() => {
9089
9116
  try {
9090
- const board = JSON.parse(readFileSync23(boardPath, "utf-8"));
9117
+ const board = JSON.parse(readFileSync24(boardPath, "utf-8"));
9091
9118
  const items = Array.isArray(board.items) ? board.items : [];
9092
9119
  const taskItem = items.find((i) => i.id === taskId);
9093
9120
  if (taskItem) {
@@ -9130,7 +9157,7 @@ async function runPipeline(projectName, opts) {
9130
9157
  // src/cli/commands/daemon-cmd.ts
9131
9158
  import { Command as Command15 } from "commander";
9132
9159
  import { join as join26 } from "path";
9133
- import { existsSync as existsSync28, readFileSync as readFileSync24, writeFileSync as writeFileSync21, mkdirSync as mkdirSync17 } from "fs";
9160
+ import { existsSync as existsSync28, readFileSync as readFileSync25, writeFileSync as writeFileSync21, mkdirSync as mkdirSync17 } from "fs";
9134
9161
  init_bridge();
9135
9162
  init_schemas();
9136
9163
  var daemonCommand = new Command15("daemon").description("Start the BeastMode daemon via bridge").option("--dry-run", "Generate config but don't start daemon").option(
@@ -9159,7 +9186,7 @@ async function runDaemon(opts) {
9159
9186
  throw new Error("Factory config not found. Run 'beastmode init' first.");
9160
9187
  }
9161
9188
  const factoryConfig = FactoryConfigSchema.parse(
9162
- JSON.parse(readFileSync24(configPath, "utf-8"))
9189
+ JSON.parse(readFileSync25(configPath, "utf-8"))
9163
9190
  );
9164
9191
  let projectConfig = null;
9165
9192
  const projectsDir = join26(bmDir, "projects");
@@ -9170,7 +9197,7 @@ async function runDaemon(opts) {
9170
9197
  );
9171
9198
  if (projectFiles.length > 0) {
9172
9199
  projectConfig = ProjectConfigSchema.parse(
9173
- JSON.parse(readFileSync24(join26(projectsDir, projectFiles[0]), "utf-8"))
9200
+ JSON.parse(readFileSync25(join26(projectsDir, projectFiles[0]), "utf-8"))
9174
9201
  );
9175
9202
  info(`Using project: ${projectConfig.name}`);
9176
9203
  }
@@ -9272,7 +9299,7 @@ var mcpCommand = new Command16("mcp").description("Start the BeastMode MCP serve
9272
9299
  // src/cli/commands/deploy.ts
9273
9300
  import { Command as Command17 } from "commander";
9274
9301
  import { resolve as resolve19, join as join28 } from "path";
9275
- import { existsSync as existsSync30, writeFileSync as writeFileSync23, readFileSync as readFileSync26 } from "fs";
9302
+ import { existsSync as existsSync30, writeFileSync as writeFileSync23, readFileSync as readFileSync27 } from "fs";
9276
9303
  import { execSync as execSync7 } from "child_process";
9277
9304
  import { randomBytes } from "crypto";
9278
9305
  import { fileURLToPath as fileURLToPath3 } from "url";
@@ -9362,8 +9389,8 @@ async function runDeploy(opts) {
9362
9389
  const host = opts.host;
9363
9390
  const dotEnv = join28(factoryDir, ".env");
9364
9391
  const secretsEnv = join28(bmDir, "secrets.env.local");
9365
- const envContent = existsSync30(dotEnv) ? readFileSync26(dotEnv, "utf-8") : "";
9366
- const secretsContent = existsSync30(secretsEnv) ? readFileSync26(secretsEnv, "utf-8") : "";
9392
+ const envContent = existsSync30(dotEnv) ? readFileSync27(dotEnv, "utf-8") : "";
9393
+ const secretsContent = existsSync30(secretsEnv) ? readFileSync27(secretsEnv, "utf-8") : "";
9367
9394
  const hasPassword = envContent.includes("BEASTMODE_UI_PASSWORD=") && !envContent.includes("BEASTMODE_UI_PASSWORD=\n") || secretsContent.includes("BEASTMODE_UI_PASSWORD=") && !secretsContent.includes("BEASTMODE_UI_PASSWORD=\n") || !!process.env.BEASTMODE_UI_PASSWORD;
9368
9395
  if (!hasPassword && opts.host === "0.0.0.0") {
9369
9396
  const generated = randomBytes(18).toString("base64url");
@@ -9372,7 +9399,7 @@ async function runDeploy(opts) {
9372
9399
  # Auto-generated board UI password (deploy)
9373
9400
  BEASTMODE_UI_PASSWORD=${generated}
9374
9401
  `;
9375
- writeFileSync23(target, (existsSync30(target) ? readFileSync26(target, "utf-8") : "") + append, "utf-8");
9402
+ writeFileSync23(target, (existsSync30(target) ? readFileSync27(target, "utf-8") : "") + append, "utf-8");
9376
9403
  info(`Board UI password auto-generated and saved to ${target}`);
9377
9404
  success(`Password: ${generated}`);
9378
9405
  info("Save this password \u2014 you'll need it to access the board UI.");
@@ -9990,12 +10017,12 @@ var logsCommand = new Command21("logs").description("Stream BeastMode service lo
9990
10017
 
9991
10018
  // src/cli/commands/update.ts
9992
10019
  import { Command as Command22 } from "commander";
9993
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync25 } from "fs";
10020
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync25 } from "fs";
9994
10021
  async function runUpdate(opts) {
9995
10022
  const cwd = opts.cwd ?? process.cwd();
9996
10023
  const composePath = requireComposeFile(cwd);
9997
10024
  if (opts.tag) {
9998
- let content = readFileSync27(composePath, "utf-8");
10025
+ let content = readFileSync28(composePath, "utf-8");
9999
10026
  const tagPattern = new RegExp(
10000
10027
  `(${GHCR_IMAGE_PREFIX.replace(/[/]/g, "\\/")}\\/(?:board|daemon|ui)):([\\w.\\-]+)`,
10001
10028
  "g"