@scheduler-systems/gal-run 0.0.281 → 0.0.283

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.
Files changed (2) hide show
  1. package/dist/index.cjs +838 -378
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3970,7 +3970,7 @@ var cliVersion, defaultApiUrl, BUILD_CONSTANTS, constants_default;
3970
3970
  var init_constants = __esm({
3971
3971
  "src/constants.ts"() {
3972
3972
  "use strict";
3973
- cliVersion = true ? "0.0.281" : "0.0.0-dev";
3973
+ cliVersion = true ? "0.0.283" : "0.0.0-dev";
3974
3974
  defaultApiUrl = true ? "https://api.gal.run" : "http://localhost:3000";
3975
3975
  BUILD_CONSTANTS = Object.freeze([cliVersion, defaultApiUrl]);
3976
3976
  constants_default = BUILD_CONSTANTS;
@@ -4812,7 +4812,7 @@ function detectEnvironment() {
4812
4812
  return "dev";
4813
4813
  }
4814
4814
  try {
4815
- const version = true ? "0.0.281" : void 0;
4815
+ const version = true ? "0.0.283" : void 0;
4816
4816
  if (version && version.includes("-local")) {
4817
4817
  return "dev";
4818
4818
  }
@@ -5181,7 +5181,7 @@ function getId() {
5181
5181
  }
5182
5182
  function getCliVersion() {
5183
5183
  try {
5184
- return true ? "0.0.281" : "0.0.0-dev";
5184
+ return true ? "0.0.283" : "0.0.0-dev";
5185
5185
  } catch {
5186
5186
  return "0.0.0-dev";
5187
5187
  }
@@ -5550,6 +5550,30 @@ var init_platform_registry = __esm({
5550
5550
  complianceScan: false,
5551
5551
  stable: false
5552
5552
  }
5553
+ },
5554
+ higgsfield: {
5555
+ id: "higgsfield",
5556
+ directory: ".higgsfield",
5557
+ display: { fullName: "Higgsfield AI", shortName: "Higgsfield", icon: "\u{1F3A5}" },
5558
+ capabilities: {
5559
+ hooks: false,
5560
+ credentialSync: false,
5561
+ sessionRunner: false,
5562
+ complianceScan: false,
5563
+ stable: false
5564
+ }
5565
+ },
5566
+ jules: {
5567
+ id: "jules",
5568
+ directory: ".jules",
5569
+ display: { fullName: "Jules", shortName: "Jules", icon: "\u{1F916}" },
5570
+ capabilities: {
5571
+ hooks: false,
5572
+ credentialSync: false,
5573
+ sessionRunner: false,
5574
+ complianceScan: false,
5575
+ stable: false
5576
+ }
5553
5577
  }
5554
5578
  };
5555
5579
  ALL_PLATFORM_IDS = Object.keys(PLATFORM_REGISTRY);
@@ -5941,6 +5965,13 @@ var init_mal_cross_project = __esm({
5941
5965
  }
5942
5966
  });
5943
5967
 
5968
+ // ../../packages/types/dist/design-project.js
5969
+ var init_design_project = __esm({
5970
+ "../../packages/types/dist/design-project.js"() {
5971
+ "use strict";
5972
+ }
5973
+ });
5974
+
5944
5975
  // ../../packages/types/dist/index.js
5945
5976
  var GAL_TERMS_URL, GAL_PRIVACY_URL, PLATFORM_PATTERNS;
5946
5977
  var init_dist2 = __esm({
@@ -5993,6 +6024,7 @@ var init_dist2 = __esm({
5993
6024
  init_mal_self_evolution();
5994
6025
  init_mal_knowledge();
5995
6026
  init_mal_cross_project();
6027
+ init_design_project();
5996
6028
  GAL_TERMS_URL = "https://scheduler-systems.com/legal/en/gal-terms.pdf";
5997
6029
  GAL_PRIVACY_URL = "https://scheduler-systems.com/legal/en/gal-privacy.pdf";
5998
6030
  PLATFORM_PATTERNS = {
@@ -6157,6 +6189,20 @@ var init_dist2 = __esm({
6157
6189
  settingsFile: "",
6158
6190
  rulesDir: "",
6159
6191
  ruleExtensions: []
6192
+ },
6193
+ higgsfield: {
6194
+ platform: "higgsfield",
6195
+ directory: ".higgsfield",
6196
+ settingsFile: "",
6197
+ rulesDir: "",
6198
+ ruleExtensions: []
6199
+ },
6200
+ jules: {
6201
+ platform: "jules",
6202
+ directory: ".jules",
6203
+ settingsFile: "",
6204
+ rulesDir: "",
6205
+ ruleExtensions: []
6160
6206
  }
6161
6207
  };
6162
6208
  }
@@ -6887,7 +6933,9 @@ var init_OrganizationService = __esm({
6887
6933
  amp: this.createEmptyPlatformStats(orgName, "amp"),
6888
6934
  "ai-studio": this.createEmptyPlatformStats(orgName, "ai-studio"),
6889
6935
  "codex-cloud": this.createEmptyPlatformStats(orgName, "codex-cloud"),
6890
- kling: this.createEmptyPlatformStats(orgName, "kling")
6936
+ kling: this.createEmptyPlatformStats(orgName, "kling"),
6937
+ higgsfield: this.createEmptyPlatformStats(orgName, "higgsfield"),
6938
+ jules: this.createEmptyPlatformStats(orgName, "jules")
6891
6939
  };
6892
6940
  for (const result of scanResults) {
6893
6941
  const platformStats = platforms[result.platform];
@@ -7535,12 +7583,12 @@ function getFeatureFlags() {
7535
7583
  let isPartnerFromApi = false;
7536
7584
  if (!isInternalEnv) {
7537
7585
  try {
7538
- const { readFileSync: readFileSync37, existsSync: existsSync41 } = require("fs");
7539
- const { join: join45 } = require("path");
7540
- const { homedir: homedir22 } = require("os");
7541
- const configPath = join45(homedir22(), ".gal", "config.json");
7542
- if (existsSync41(configPath)) {
7543
- const config = JSON.parse(readFileSync37(configPath, "utf-8"));
7586
+ const { readFileSync: readFileSync38, existsSync: existsSync42 } = require("fs");
7587
+ const { join: join46 } = require("path");
7588
+ const { homedir: homedir23 } = require("os");
7589
+ const configPath = join46(homedir23(), ".gal", "config.json");
7590
+ if (existsSync42(configPath)) {
7591
+ const config = JSON.parse(readFileSync38(configPath, "utf-8"));
7544
7592
  const cacheAge = Date.now() - (config.flagsCachedAt || config.internalOrgsCheckedAt || 0);
7545
7593
  if (cacheAge < CACHE_MAX_AGE_MS) {
7546
7594
  const userOrgs = config.orgMemberships || [];
@@ -7764,7 +7812,8 @@ var init_feature_flags2 = __esm({
7764
7812
  "workflow",
7765
7813
  "work",
7766
7814
  "queue",
7767
- "automations"
7815
+ "automations",
7816
+ "run-design"
7768
7817
  ]
7769
7818
  };
7770
7819
  PREVIEW_COMMANDS = /* @__PURE__ */ new Set(["agent", "agent-session", "fleet", "runner", "queue", "work"]);
@@ -16975,7 +17024,7 @@ var require_thread_stream = __commonJS({
16975
17024
  var { version } = require_package2();
16976
17025
  var { EventEmitter: EventEmitter3 } = require("events");
16977
17026
  var { Worker } = require("worker_threads");
16978
- var { join: join45 } = require("path");
17027
+ var { join: join46 } = require("path");
16979
17028
  var { pathToFileURL } = require("url");
16980
17029
  var { wait } = require_wait();
16981
17030
  var {
@@ -17011,7 +17060,7 @@ var require_thread_stream = __commonJS({
17011
17060
  function createWorker(stream, opts) {
17012
17061
  const { filename, workerData } = opts;
17013
17062
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
17014
- const toExecute = bundlerOverrides["thread-stream-worker"] || join45(__dirname, "lib", "worker.js");
17063
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join46(__dirname, "lib", "worker.js");
17015
17064
  const worker = new Worker(toExecute, {
17016
17065
  ...opts.workerOpts,
17017
17066
  trackUnmanagedFds: false,
@@ -17397,7 +17446,7 @@ var require_transport = __commonJS({
17397
17446
  "use strict";
17398
17447
  var { createRequire } = require("module");
17399
17448
  var getCallers = require_caller();
17400
- var { join: join45, isAbsolute, sep } = require("node:path");
17449
+ var { join: join46, isAbsolute, sep } = require("node:path");
17401
17450
  var sleep2 = require_atomic_sleep();
17402
17451
  var onExit2 = require_on_exit_leak_free();
17403
17452
  var ThreadStream = require_thread_stream();
@@ -17460,7 +17509,7 @@ var require_transport = __commonJS({
17460
17509
  throw new Error("only one of target or targets can be specified");
17461
17510
  }
17462
17511
  if (targets) {
17463
- target = bundlerOverrides["pino-worker"] || join45(__dirname, "worker.js");
17512
+ target = bundlerOverrides["pino-worker"] || join46(__dirname, "worker.js");
17464
17513
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
17465
17514
  return {
17466
17515
  ...dest,
@@ -17478,7 +17527,7 @@ var require_transport = __commonJS({
17478
17527
  });
17479
17528
  });
17480
17529
  } else if (pipeline) {
17481
- target = bundlerOverrides["pino-worker"] || join45(__dirname, "worker.js");
17530
+ target = bundlerOverrides["pino-worker"] || join46(__dirname, "worker.js");
17482
17531
  options.pipelines = [pipeline.map((dest) => {
17483
17532
  return {
17484
17533
  ...dest,
@@ -17500,7 +17549,7 @@ var require_transport = __commonJS({
17500
17549
  return origin;
17501
17550
  }
17502
17551
  if (origin === "pino/file") {
17503
- return join45(__dirname, "..", "file.js");
17552
+ return join46(__dirname, "..", "file.js");
17504
17553
  }
17505
17554
  let fixTarget2;
17506
17555
  for (const filePath of callers) {
@@ -18489,7 +18538,7 @@ var require_safe_stable_stringify = __commonJS({
18489
18538
  return circularValue;
18490
18539
  }
18491
18540
  let res = "";
18492
- let join45 = ",";
18541
+ let join46 = ",";
18493
18542
  const originalIndentation = indentation;
18494
18543
  if (Array.isArray(value)) {
18495
18544
  if (value.length === 0) {
@@ -18503,7 +18552,7 @@ var require_safe_stable_stringify = __commonJS({
18503
18552
  indentation += spacer;
18504
18553
  res += `
18505
18554
  ${indentation}`;
18506
- join45 = `,
18555
+ join46 = `,
18507
18556
  ${indentation}`;
18508
18557
  }
18509
18558
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -18511,13 +18560,13 @@ ${indentation}`;
18511
18560
  for (; i < maximumValuesToStringify - 1; i++) {
18512
18561
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
18513
18562
  res += tmp2 !== void 0 ? tmp2 : "null";
18514
- res += join45;
18563
+ res += join46;
18515
18564
  }
18516
18565
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
18517
18566
  res += tmp !== void 0 ? tmp : "null";
18518
18567
  if (value.length - 1 > maximumBreadth) {
18519
18568
  const removedKeys = value.length - maximumBreadth - 1;
18520
- res += `${join45}"... ${getItemCount(removedKeys)} not stringified"`;
18569
+ res += `${join46}"... ${getItemCount(removedKeys)} not stringified"`;
18521
18570
  }
18522
18571
  if (spacer !== "") {
18523
18572
  res += `
@@ -18538,7 +18587,7 @@ ${originalIndentation}`;
18538
18587
  let separator = "";
18539
18588
  if (spacer !== "") {
18540
18589
  indentation += spacer;
18541
- join45 = `,
18590
+ join46 = `,
18542
18591
  ${indentation}`;
18543
18592
  whitespace = " ";
18544
18593
  }
@@ -18552,13 +18601,13 @@ ${indentation}`;
18552
18601
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
18553
18602
  if (tmp !== void 0) {
18554
18603
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
18555
- separator = join45;
18604
+ separator = join46;
18556
18605
  }
18557
18606
  }
18558
18607
  if (keyLength > maximumBreadth) {
18559
18608
  const removedKeys = keyLength - maximumBreadth;
18560
18609
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
18561
- separator = join45;
18610
+ separator = join46;
18562
18611
  }
18563
18612
  if (spacer !== "" && separator.length > 1) {
18564
18613
  res = `
@@ -18599,7 +18648,7 @@ ${originalIndentation}`;
18599
18648
  }
18600
18649
  const originalIndentation = indentation;
18601
18650
  let res = "";
18602
- let join45 = ",";
18651
+ let join46 = ",";
18603
18652
  if (Array.isArray(value)) {
18604
18653
  if (value.length === 0) {
18605
18654
  return "[]";
@@ -18612,7 +18661,7 @@ ${originalIndentation}`;
18612
18661
  indentation += spacer;
18613
18662
  res += `
18614
18663
  ${indentation}`;
18615
- join45 = `,
18664
+ join46 = `,
18616
18665
  ${indentation}`;
18617
18666
  }
18618
18667
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -18620,13 +18669,13 @@ ${indentation}`;
18620
18669
  for (; i < maximumValuesToStringify - 1; i++) {
18621
18670
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
18622
18671
  res += tmp2 !== void 0 ? tmp2 : "null";
18623
- res += join45;
18672
+ res += join46;
18624
18673
  }
18625
18674
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
18626
18675
  res += tmp !== void 0 ? tmp : "null";
18627
18676
  if (value.length - 1 > maximumBreadth) {
18628
18677
  const removedKeys = value.length - maximumBreadth - 1;
18629
- res += `${join45}"... ${getItemCount(removedKeys)} not stringified"`;
18678
+ res += `${join46}"... ${getItemCount(removedKeys)} not stringified"`;
18630
18679
  }
18631
18680
  if (spacer !== "") {
18632
18681
  res += `
@@ -18639,7 +18688,7 @@ ${originalIndentation}`;
18639
18688
  let whitespace = "";
18640
18689
  if (spacer !== "") {
18641
18690
  indentation += spacer;
18642
- join45 = `,
18691
+ join46 = `,
18643
18692
  ${indentation}`;
18644
18693
  whitespace = " ";
18645
18694
  }
@@ -18648,7 +18697,7 @@ ${indentation}`;
18648
18697
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
18649
18698
  if (tmp !== void 0) {
18650
18699
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
18651
- separator = join45;
18700
+ separator = join46;
18652
18701
  }
18653
18702
  }
18654
18703
  if (spacer !== "" && separator.length > 1) {
@@ -18706,20 +18755,20 @@ ${originalIndentation}`;
18706
18755
  indentation += spacer;
18707
18756
  let res2 = `
18708
18757
  ${indentation}`;
18709
- const join46 = `,
18758
+ const join47 = `,
18710
18759
  ${indentation}`;
18711
18760
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
18712
18761
  let i = 0;
18713
18762
  for (; i < maximumValuesToStringify - 1; i++) {
18714
18763
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
18715
18764
  res2 += tmp2 !== void 0 ? tmp2 : "null";
18716
- res2 += join46;
18765
+ res2 += join47;
18717
18766
  }
18718
18767
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
18719
18768
  res2 += tmp !== void 0 ? tmp : "null";
18720
18769
  if (value.length - 1 > maximumBreadth) {
18721
18770
  const removedKeys = value.length - maximumBreadth - 1;
18722
- res2 += `${join46}"... ${getItemCount(removedKeys)} not stringified"`;
18771
+ res2 += `${join47}"... ${getItemCount(removedKeys)} not stringified"`;
18723
18772
  }
18724
18773
  res2 += `
18725
18774
  ${originalIndentation}`;
@@ -18735,16 +18784,16 @@ ${originalIndentation}`;
18735
18784
  return '"[Object]"';
18736
18785
  }
18737
18786
  indentation += spacer;
18738
- const join45 = `,
18787
+ const join46 = `,
18739
18788
  ${indentation}`;
18740
18789
  let res = "";
18741
18790
  let separator = "";
18742
18791
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
18743
18792
  if (isTypedArrayWithEntries(value)) {
18744
- res += stringifyTypedArray(value, join45, maximumBreadth);
18793
+ res += stringifyTypedArray(value, join46, maximumBreadth);
18745
18794
  keys = keys.slice(value.length);
18746
18795
  maximumPropertiesToStringify -= value.length;
18747
- separator = join45;
18796
+ separator = join46;
18748
18797
  }
18749
18798
  if (deterministic) {
18750
18799
  keys = sort(keys, comparator);
@@ -18755,13 +18804,13 @@ ${indentation}`;
18755
18804
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
18756
18805
  if (tmp !== void 0) {
18757
18806
  res += `${separator}${strEscape(key2)}: ${tmp}`;
18758
- separator = join45;
18807
+ separator = join46;
18759
18808
  }
18760
18809
  }
18761
18810
  if (keyLength > maximumBreadth) {
18762
18811
  const removedKeys = keyLength - maximumBreadth;
18763
18812
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
18764
- separator = join45;
18813
+ separator = join46;
18765
18814
  }
18766
18815
  if (separator !== "") {
18767
18816
  res = `
@@ -21137,11 +21186,11 @@ function createApprovedConfigCommand() {
21137
21186
  const spinner = options.json ? null : ora(`Fetching approved config for "${org}"...`).start();
21138
21187
  try {
21139
21188
  let findMdFiles2 = function(dir) {
21140
- if (!existsSync41(dir)) return [];
21141
- const entries = readdirSync16(dir, { withFileTypes: true });
21189
+ if (!existsSync42(dir)) return [];
21190
+ const entries = readdirSync17(dir, { withFileTypes: true });
21142
21191
  const files = [];
21143
21192
  for (const entry of entries) {
21144
- const fullPath = join45(dir, entry.name);
21193
+ const fullPath = join46(dir, entry.name);
21145
21194
  if (entry.isDirectory()) files.push(...findMdFiles2(fullPath));
21146
21195
  else if (entry.name.endsWith(".md")) files.push(fullPath);
21147
21196
  }
@@ -21159,11 +21208,11 @@ function createApprovedConfigCommand() {
21159
21208
  }
21160
21209
  return;
21161
21210
  }
21162
- const { existsSync: existsSync41, readdirSync: readdirSync16, readFileSync: readFileSync37 } = await import("fs");
21163
- const { join: join45, relative: relative10, basename: basename9 } = await import("path");
21211
+ const { existsSync: existsSync42, readdirSync: readdirSync17, readFileSync: readFileSync38 } = await import("fs");
21212
+ const { join: join46, relative: relative10, basename: basename9 } = await import("path");
21164
21213
  const baseDir = options.dir || process.cwd();
21165
- const commandsDir = join45(baseDir, ".claude", "commands");
21166
- const agentsDir = join45(baseDir, ".claude", "agents");
21214
+ const commandsDir = join46(baseDir, ".claude", "commands");
21215
+ const agentsDir = join46(baseDir, ".claude", "agents");
21167
21216
  const localCommandNames = findMdFiles2(commandsDir).map(
21168
21217
  (f) => relative10(commandsDir, f).replace(/\.md$/, "").replace(/\//g, ":")
21169
21218
  );
@@ -30795,6 +30844,9 @@ function isAgentInstalled(agent) {
30795
30844
  } catch {
30796
30845
  return (0, import_fs15.existsSync)((0, import_path14.join)((0, import_os13.homedir)(), ".antigravity"));
30797
30846
  }
30847
+ case "codex":
30848
+ (0, import_child_process5.execSync)("which codex", { stdio: "ignore" });
30849
+ return true;
30798
30850
  case "amp":
30799
30851
  (0, import_child_process5.execSync)("which amp", { stdio: "ignore" });
30800
30852
  return true;
@@ -31186,13 +31238,13 @@ if (!state) {
31186
31238
  }
31187
31239
  }
31188
31240
 
31189
- if (state && state.lastSyncHash !== state.approvedConfigHash) {
31241
+ if (state && state.approvedConfigHash && state.lastSyncHash !== state.approvedConfigHash) {
31190
31242
  try {
31191
31243
  execSync('gal sync --pull --auto', { stdio: 'pipe', timeout: 5000 });
31192
31244
  state = readSyncState();
31193
31245
  } catch {}
31194
31246
 
31195
- if (state && state.lastSyncHash !== state.approvedConfigHash) {
31247
+ if (state && state.approvedConfigHash && state.lastSyncHash !== state.approvedConfigHash) {
31196
31248
  const days = Math.floor((Date.now() - new Date(state.lastSyncTimestamp).getTime()) / (24 * 60 * 60 * 1000));
31197
31249
  showMessage(\`\\u26a0\\ufe0f GAL: Config is \${days} day(s) behind \${state.organization}'s approved version.\\nRun: gal sync --pull\`, 'config_outdated');
31198
31250
  return;
@@ -32366,7 +32418,9 @@ function writeSyncStateV2(orgName, platformStates, hookSettings) {
32366
32418
  lastSyncTimestamp: primaryState?.lastSyncTimestamp,
32367
32419
  syncedFiles: primaryState?.syncedFiles,
32368
32420
  policyName: primaryState?.policyName,
32369
- version: primaryState?.approvedConfigVersion
32421
+ version: primaryState?.approvedConfigVersion,
32422
+ // After a successful sync, approved hash matches local hash
32423
+ approvedConfigHash: primaryState?.lastSyncHash
32370
32424
  };
32371
32425
  (0, import_fs19.writeFileSync)(statePath, JSON.stringify(state, null, 2), "utf-8");
32372
32426
  }
@@ -34708,60 +34762,90 @@ async function validateAfterSync(config, provider) {
34708
34762
  }
34709
34763
  }
34710
34764
  async function runPostLoginSetup(config) {
34711
- const hookResult = installHooks();
34712
- const syncResult = config.authToken ? await syncApprovedConfigAfterLogin({
34713
- apiUrl: config.apiUrl || defaultApiUrl5,
34714
- authToken: config.authToken,
34715
- orgName: config.defaultOrg
34716
- }) : {
34717
- status: "skipped",
34718
- directory: process.cwd(),
34719
- filesWritten: 0,
34720
- platforms: [],
34721
- message: "Authentication token missing; skipped initial sync."
34765
+ let hookResult;
34766
+ try {
34767
+ hookResult = installHooks();
34768
+ } catch {
34769
+ hookResult = { hookInstalled: false, rulesInstalled: false, errors: ["Hook installation failed unexpectedly"], results: [] };
34770
+ }
34771
+ let syncResult;
34772
+ try {
34773
+ syncResult = config.authToken ? await syncApprovedConfigAfterLogin({
34774
+ apiUrl: config.apiUrl || defaultApiUrl5,
34775
+ authToken: config.authToken,
34776
+ orgName: config.defaultOrg
34777
+ }) : {
34778
+ status: "skipped",
34779
+ directory: process.cwd(),
34780
+ filesWritten: 0,
34781
+ platforms: [],
34782
+ message: "Authentication token missing; skipped initial sync."
34783
+ };
34784
+ } catch {
34785
+ syncResult = {
34786
+ status: "failed",
34787
+ directory: process.cwd(),
34788
+ filesWritten: 0,
34789
+ platforms: [],
34790
+ message: "Sync failed unexpectedly during post-login setup."
34791
+ };
34792
+ }
34793
+ const TOOL_DISPLAY_NAMES = {
34794
+ claude: "Claude Code",
34795
+ cursor: "Cursor",
34796
+ windsurf: "Windsurf",
34797
+ gemini: "Gemini CLI",
34798
+ codex: "Codex CLI",
34799
+ amp: "Amp",
34800
+ antigravity: "Antigravity"
34722
34801
  };
34802
+ const toolIds = ["claude", "cursor", "windsurf", "gemini", "codex", "amp", "antigravity"];
34803
+ const configuredStatuses = /* @__PURE__ */ new Set(["installed", "updated", "up_to_date"]);
34804
+ const detectedTools = [];
34805
+ for (const id of toolIds) {
34806
+ if (isAgentInstalled(id)) {
34807
+ const hookForTool = hookResult.results.find((r) => r.agent === id);
34808
+ const configured = id === "claude" ? hookResult.hookInstalled || hookResult.errors.length === 0 : hookForTool ? configuredStatuses.has(hookForTool.status) : false;
34809
+ detectedTools.push({ name: TOOL_DISPLAY_NAMES[id] || id, id, configured });
34810
+ }
34811
+ }
34723
34812
  return {
34724
34813
  hooks: {
34725
34814
  installed: hookResult.hookInstalled || hookResult.rulesInstalled,
34726
34815
  errors: hookResult.errors,
34727
34816
  results: hookResult.results || []
34728
34817
  },
34729
- sync: syncResult
34818
+ sync: syncResult,
34819
+ detectedTools
34730
34820
  };
34731
34821
  }
34732
- function reportPostLoginSetup(result) {
34733
- console.log(source_default.green("\nSetup status:"));
34822
+ function reportPostLoginSetup(result, username, org) {
34823
+ console.log("");
34824
+ const authParts = [source_default.green("\u2713"), "Authenticated"];
34825
+ if (username) authParts.push(`as ${source_default.bold("@" + username)}`);
34826
+ if (org) authParts.push(`(${org})`);
34827
+ console.log(authParts.join(" "));
34734
34828
  if (result.hooks.errors.length > 0) {
34735
- console.log(source_default.yellow(` ! Claude hooks install incomplete: ${result.hooks.errors[0]}`));
34736
- console.log(source_default.dim(` Retry: ${source_default.cyan("gal hooks install")}`));
34737
- } else if (result.hooks.installed) {
34738
- console.log(source_default.dim(" \u2713 Claude auto-sync hooks ready"));
34829
+ console.log(source_default.yellow(`\u26A0 Hooks install incomplete: ${result.hooks.errors[0]}`));
34739
34830
  } else {
34740
- console.log(source_default.dim(" - Claude auto-sync hooks already up to date"));
34741
- }
34742
- if (result.hooks.results && result.hooks.results.length > 0) {
34743
- for (const r of result.hooks.results) {
34744
- const agentName = r.agent.charAt(0).toUpperCase() + r.agent.slice(1);
34745
- if (r.status === "installed" || r.status === "updated") {
34746
- console.log(source_default.dim(` \u2713 ${agentName} auto-sync hooks ready`));
34747
- } else if (r.status === "pending") {
34748
- console.log(source_default.dim(` \u2298 ${agentName} detected, hooks not yet available`));
34749
- } else if (r.status === "error") {
34750
- console.log(source_default.yellow(` ! ${agentName} hook install failed`));
34751
- }
34752
- }
34831
+ console.log(source_default.green("\u2713") + " Hooks installed \u2014 configs will sync at session start");
34753
34832
  }
34754
34833
  if (result.sync.status === "synced") {
34755
34834
  const platformLabel = result.sync.platforms.length > 0 ? result.sync.platforms.join(", ") : "approved configs";
34756
- console.log(source_default.dim(` \u2713 Initial sync complete in ${result.sync.directory} (${result.sync.filesWritten} files; ${platformLabel})`));
34757
- return;
34835
+ console.log(source_default.green("\u2713") + ` Approved config synced \u2014 ${result.sync.filesWritten} files applied (${platformLabel})`);
34836
+ } else if (result.sync.status === "skipped" || result.sync.status === "failed") {
34837
+ console.log(source_default.yellow("\u26A0 Sync skipped (no org config available yet) \u2014 retry: gal sync --pull"));
34758
34838
  }
34759
- if (result.sync.status === "skipped") {
34760
- console.log(source_default.yellow(` ! Initial sync skipped: ${result.sync.message || "No org config available yet."}`));
34761
- return;
34839
+ if (result.detectedTools.length > 0) {
34840
+ const toolNames = result.detectedTools.map((t) => t.name).join(", ");
34841
+ console.log(source_default.green("\u2713") + ` Detected: ${toolNames}`);
34842
+ } else {
34843
+ console.log(source_default.yellow("\u26A0 No AI coding tools detected. Install Claude Code, Cursor, or Windsurf, then run: gal hooks install"));
34844
+ }
34845
+ const hasErrors = result.hooks.errors.length > 0 || result.sync.status !== "synced" || result.detectedTools.length === 0;
34846
+ if (!hasErrors) {
34847
+ console.log(source_default.dim("\nYou're fully set up. GAL runs automatically from here."));
34762
34848
  }
34763
- console.log(source_default.yellow(` ! Initial sync could not complete: ${result.sync.message || "Unknown error"}`));
34764
- console.log(source_default.dim(` Retry: ${source_default.cyan("gal sync --pull")}`));
34765
34849
  }
34766
34850
  function startCallbackServer(timeout = 12e4) {
34767
34851
  return new Promise((resolve8, reject) => {
@@ -34871,11 +34955,13 @@ function createAuthCommand() {
34871
34955
  authToken: nonInteractiveToken,
34872
34956
  defaultOrg: config.defaultOrg
34873
34957
  });
34874
- console.log(source_default.green("\n\u2713 Credentials saved! (non-interactive mode)"));
34875
- reportPostLoginSetup(setupResult);
34876
- console.log(source_default.dim(`
34958
+ reportPostLoginSetup(setupResult, user.login, config.defaultOrg);
34959
+ const hasSetupErrors = setupResult.hooks.errors.length > 0 || setupResult.sync.status !== "synced" || setupResult.detectedTools.length === 0;
34960
+ if (hasSetupErrors) {
34961
+ console.log(source_default.dim(`
34877
34962
  Review status: ${source_default.cyan("gal auth status")}
34878
34963
  `));
34964
+ }
34879
34965
  process.exit(0);
34880
34966
  } catch (error2) {
34881
34967
  spinner2.fail(source_default.red("Token validation failed"));
@@ -34920,7 +35006,8 @@ Review status: ${source_default.cyan("gal auth status")}
34920
35006
  ConfigManager.save(config);
34921
35007
  trackAuthLogin(true);
34922
35008
  await refreshInternalStatus(apiUrl, token2);
34923
- await runPostLoginSetup({ apiUrl, authToken: token2, defaultOrg: config.defaultOrg });
35009
+ const setupResult2 = await runPostLoginSetup({ apiUrl, authToken: token2, defaultOrg: config.defaultOrg });
35010
+ reportPostLoginSetup(setupResult2, user2?.login, config.defaultOrg);
34924
35011
  process.exit(0);
34925
35012
  }
34926
35013
  spinner.text = "Opening browser for GitHub authentication...";
@@ -34969,11 +35056,13 @@ Review status: ${source_default.cyan("gal auth status")}
34969
35056
  console.log(source_default.dim(" \u26A0 Could not report status to dashboard"));
34970
35057
  }
34971
35058
  }
34972
- console.log(source_default.green("\n\u2713 Credentials saved!"));
34973
- reportPostLoginSetup(setupResult);
34974
- console.log(source_default.dim(`
35059
+ reportPostLoginSetup(setupResult, user?.login, config.defaultOrg);
35060
+ const hasSetupErrors = setupResult.hooks.errors.length > 0 || setupResult.sync.status !== "synced" || setupResult.detectedTools.length === 0;
35061
+ if (hasSetupErrors) {
35062
+ console.log(source_default.dim(`
34975
35063
  Review status: ${source_default.cyan("gal auth status")}
34976
35064
  `));
35065
+ }
34977
35066
  process.exit(0);
34978
35067
  } catch (error2) {
34979
35068
  spinner.fail(source_default.red("Authentication failed"));
@@ -35972,8 +36061,8 @@ var init_check = __esm({
35972
36061
  issues = [];
35973
36062
  interactive;
35974
36063
  autoFix;
35975
- constructor(projectPath, options = {}) {
35976
- this.projectPath = projectPath;
36064
+ constructor(projectPath2, options = {}) {
36065
+ this.projectPath = projectPath2;
35977
36066
  this.interactive = options.interactive || false;
35978
36067
  this.autoFix = options.autoFix || false;
35979
36068
  }
@@ -42140,13 +42229,13 @@ function getGitEmail() {
42140
42229
  }
42141
42230
  async function getLocalEnforcementStatus() {
42142
42231
  const { stat: stat5, readFile: readFile4 } = await import("node:fs/promises");
42143
- const { join: join45 } = await import("node:path");
42232
+ const { join: join46 } = await import("node:path");
42144
42233
  const platforms = [];
42145
42234
  let version = "0.0.0";
42146
42235
  let policyVersion = "0.0.0";
42147
42236
  const platformDirs = [".claude", ".cursor", ".gemini", ".codex", ".windsurf"];
42148
42237
  for (const dir of platformDirs) {
42149
- const hookPath = join45(process.cwd(), dir, "hooks", "gal-safety-hook.py");
42238
+ const hookPath = join46(process.cwd(), dir, "hooks", "gal-safety-hook.py");
42150
42239
  try {
42151
42240
  await stat5(hookPath);
42152
42241
  platforms.push(dir.replace(".", ""));
@@ -42159,7 +42248,7 @@ async function getLocalEnforcementStatus() {
42159
42248
  }
42160
42249
  }
42161
42250
  try {
42162
- const pkgPath = join45(import_meta.url.replace("file://", ""), "..", "..", "..", "package.json");
42251
+ const pkgPath = join46(import_meta.url.replace("file://", ""), "..", "..", "..", "package.json");
42163
42252
  const pkg = JSON.parse(await readFile4(pkgPath, "utf-8"));
42164
42253
  version = pkg.version || "0.1.0";
42165
42254
  } catch {
@@ -42671,8 +42760,8 @@ var init_headless = __esm({
42671
42760
  tasks = /* @__PURE__ */ new Map();
42672
42761
  runningProcesses = /* @__PURE__ */ new Map();
42673
42762
  projectPath;
42674
- constructor(projectPath = process.cwd(), config = {}) {
42675
- this.projectPath = projectPath;
42763
+ constructor(projectPath2 = process.cwd(), config = {}) {
42764
+ this.projectPath = projectPath2;
42676
42765
  this.config = { ...DEFAULT_CONFIG, ...config };
42677
42766
  this.ensureDirectories();
42678
42767
  this.loadTasks();
@@ -43240,7 +43329,7 @@ if __name__ == '__main__':
43240
43329
  `;
43241
43330
  }
43242
43331
  function createJoinCommand() {
43243
- const join45 = new Command("join").description("Join an organization using an invite code (GAL-100)").option("-c, --code <code>", "Invite code (e.g., GAL-XXXX-XXXX)").option("-e, --email <email>", "Developer email (defaults to git config)").option("--skip-hooks", "Skip enforcement hook installation").option("--dry-run", "Validate invite without joining").action(async (options) => {
43332
+ const join46 = new Command("join").description("Join an organization using an invite code (GAL-100)").option("-c, --code <code>", "Invite code (e.g., GAL-XXXX-XXXX)").option("-e, --email <email>", "Developer email (defaults to git config)").option("--skip-hooks", "Skip enforcement hook installation").option("--dry-run", "Validate invite without joining").action(async (options) => {
43244
43333
  const spinner = ora();
43245
43334
  if (!options.code) {
43246
43335
  console.log(source_default.bold("\nGAL Developer Onboarding\n"));
@@ -43356,7 +43445,7 @@ Error: ${useResult.error || "Unknown error"}`));
43356
43445
  process.exit(1);
43357
43446
  }
43358
43447
  });
43359
- return join45;
43448
+ return join46;
43360
43449
  }
43361
43450
  var import_node_os5, import_node_child_process2, import_node_crypto3, import_promises6, import_node_path4, defaultApiUrl9;
43362
43451
  var init_join = __esm({
@@ -45474,7 +45563,7 @@ Total duplications: ${source_default.yellow(duplicates.length)}`);
45474
45563
  );
45475
45564
  return cmd;
45476
45565
  }
45477
- async function analyzeQuality(projectPath, options) {
45566
+ async function analyzeQuality(projectPath2, options) {
45478
45567
  const issues = [];
45479
45568
  const metrics = {
45480
45569
  totalFiles: 0,
@@ -45485,7 +45574,7 @@ async function analyzeQuality(projectPath, options) {
45485
45574
  duplications: 0,
45486
45575
  technicalDebt: 0
45487
45576
  };
45488
- const files = getSourceFiles(projectPath);
45577
+ const files = getSourceFiles(projectPath2);
45489
45578
  metrics.totalFiles = files.length;
45490
45579
  for (const file of files) {
45491
45580
  try {
@@ -45496,7 +45585,7 @@ async function analyzeQuality(projectPath, options) {
45496
45585
  const line = lines[i];
45497
45586
  if (line.includes("console.log") && !file.includes("test")) {
45498
45587
  issues.push({
45499
- file: path2.relative(projectPath, file),
45588
+ file: path2.relative(projectPath2, file),
45500
45589
  line: i + 1,
45501
45590
  type: "warning",
45502
45591
  rule: "no-console",
@@ -45505,7 +45594,7 @@ async function analyzeQuality(projectPath, options) {
45505
45594
  }
45506
45595
  if (line.includes("TODO") || line.includes("FIXME")) {
45507
45596
  issues.push({
45508
- file: path2.relative(projectPath, file),
45597
+ file: path2.relative(projectPath2, file),
45509
45598
  line: i + 1,
45510
45599
  type: "info",
45511
45600
  rule: "no-todo",
@@ -45514,7 +45603,7 @@ async function analyzeQuality(projectPath, options) {
45514
45603
  }
45515
45604
  if (line.includes(": any") || line.includes("<any>")) {
45516
45605
  issues.push({
45517
- file: path2.relative(projectPath, file),
45606
+ file: path2.relative(projectPath2, file),
45518
45607
  line: i + 1,
45519
45608
  type: "warning",
45520
45609
  rule: "no-any",
@@ -45524,7 +45613,7 @@ async function analyzeQuality(projectPath, options) {
45524
45613
  }
45525
45614
  if (lines.length > DEFAULT_CONFIG2.maxFileLength) {
45526
45615
  issues.push({
45527
- file: path2.relative(projectPath, file),
45616
+ file: path2.relative(projectPath2, file),
45528
45617
  type: "warning",
45529
45618
  rule: "max-file-length",
45530
45619
  message: `File exceeds ${DEFAULT_CONFIG2.maxFileLength} lines (${lines.length})`
@@ -45545,8 +45634,8 @@ async function analyzeQuality(projectPath, options) {
45545
45634
  recommendations: generateRecommendations(issues, metrics)
45546
45635
  };
45547
45636
  }
45548
- async function analyzeComplexity(projectPath, threshold) {
45549
- const files = getSourceFiles(projectPath);
45637
+ async function analyzeComplexity(projectPath2, threshold) {
45638
+ const files = getSourceFiles(projectPath2);
45550
45639
  const highComplexity = [];
45551
45640
  let totalComplexity = 0;
45552
45641
  let functionCount = 0;
@@ -45557,7 +45646,7 @@ async function analyzeComplexity(projectPath, threshold) {
45557
45646
  const complexity = (matches?.length || 0) + 1;
45558
45647
  if (complexity > threshold) {
45559
45648
  highComplexity.push({
45560
- file: path2.relative(projectPath, file),
45649
+ file: path2.relative(projectPath2, file),
45561
45650
  complexity,
45562
45651
  threshold
45563
45652
  });
@@ -45572,11 +45661,11 @@ async function analyzeComplexity(projectPath, threshold) {
45572
45661
  avgComplexity: functionCount > 0 ? totalComplexity / functionCount : 0
45573
45662
  };
45574
45663
  }
45575
- async function findDuplications(projectPath, minLines) {
45664
+ async function findDuplications(projectPath2, minLines) {
45576
45665
  return [];
45577
45666
  }
45578
- async function calculateTechnicalDebt(projectPath) {
45579
- const report = await analyzeQuality(projectPath, {});
45667
+ async function calculateTechnicalDebt(projectPath2) {
45668
+ const report = await analyzeQuality(projectPath2, {});
45580
45669
  return {
45581
45670
  totalDebt: report.issues.length * 15,
45582
45671
  // 15 minutes per issue
@@ -47062,108 +47151,467 @@ var init_run = __esm({
47062
47151
  }
47063
47152
  });
47064
47153
 
47154
+ // src/commands/run-design.ts
47155
+ function ensureDir() {
47156
+ if (!(0, import_fs32.existsSync)(DESIGN_PROJECTS_DIR)) {
47157
+ (0, import_fs32.mkdirSync)(DESIGN_PROJECTS_DIR, { recursive: true });
47158
+ }
47159
+ }
47160
+ function projectPath(id) {
47161
+ return (0, import_path29.join)(DESIGN_PROJECTS_DIR, `${id}.json`);
47162
+ }
47163
+ function saveProject(project) {
47164
+ ensureDir();
47165
+ (0, import_fs32.writeFileSync)(projectPath(project.id), JSON.stringify(project, null, 2));
47166
+ }
47167
+ function loadProject(id) {
47168
+ const p = projectPath(id);
47169
+ if (!(0, import_fs32.existsSync)(p)) return null;
47170
+ try {
47171
+ return JSON.parse((0, import_fs32.readFileSync)(p, "utf-8"));
47172
+ } catch {
47173
+ return null;
47174
+ }
47175
+ }
47176
+ function getActiveId() {
47177
+ if (!(0, import_fs32.existsSync)(ACTIVE_FILE)) return null;
47178
+ try {
47179
+ const data = JSON.parse((0, import_fs32.readFileSync)(ACTIVE_FILE, "utf-8"));
47180
+ return data.id ?? null;
47181
+ } catch {
47182
+ return null;
47183
+ }
47184
+ }
47185
+ function setActiveId(id) {
47186
+ ensureDir();
47187
+ (0, import_fs32.writeFileSync)(ACTIVE_FILE, JSON.stringify({ id }, null, 2));
47188
+ }
47189
+ function getActiveProject() {
47190
+ const id = getActiveId();
47191
+ if (!id) return null;
47192
+ return loadProject(id);
47193
+ }
47194
+ function generateId() {
47195
+ return `dp-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
47196
+ }
47197
+ function generateSceneId() {
47198
+ return `sc-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
47199
+ }
47200
+ function renderStatusTable(project) {
47201
+ const COL_NUM = 3;
47202
+ const COL_SCENE = 25;
47203
+ const COL_IMAGE = 8;
47204
+ const COL_VIDEO = 8;
47205
+ const COL_STATUS = 8;
47206
+ const pad = (s, width) => s.padEnd(width).slice(0, width);
47207
+ const header = source_default.bold.white(`${project.name} `) + source_default.gray(`(${project.type} \xB7 ${project.scenes.length} scene${project.scenes.length !== 1 ? "s" : ""})`);
47208
+ const top = "\u250C" + "\u2500".repeat(COL_NUM + 2) + "\u252C" + "\u2500".repeat(COL_SCENE + 2) + "\u252C" + "\u2500".repeat(COL_IMAGE + 2) + "\u252C" + "\u2500".repeat(COL_VIDEO + 2) + "\u252C" + "\u2500".repeat(COL_STATUS + 2) + "\u2510";
47209
+ const headRow = "\u2502 " + source_default.bold(pad("#", COL_NUM)) + " \u2502 " + source_default.bold(pad("Scene", COL_SCENE)) + " \u2502 " + source_default.bold(pad("Image", COL_IMAGE)) + " \u2502 " + source_default.bold(pad("Video", COL_VIDEO)) + " \u2502 " + source_default.bold(pad("Status", COL_STATUS)) + " \u2502";
47210
+ const divider = "\u251C" + "\u2500".repeat(COL_NUM + 2) + "\u253C" + "\u2500".repeat(COL_SCENE + 2) + "\u253C" + "\u2500".repeat(COL_IMAGE + 2) + "\u253C" + "\u2500".repeat(COL_VIDEO + 2) + "\u253C" + "\u2500".repeat(COL_STATUS + 2) + "\u2524";
47211
+ const bottom = "\u2514" + "\u2500".repeat(COL_NUM + 2) + "\u2534" + "\u2500".repeat(COL_SCENE + 2) + "\u2534" + "\u2500".repeat(COL_IMAGE + 2) + "\u2534" + "\u2500".repeat(COL_VIDEO + 2) + "\u2534" + "\u2500".repeat(COL_STATUS + 2) + "\u2518";
47212
+ const rows = project.scenes.map((scene) => {
47213
+ const imageIcon = IMAGE_STATUS_ICON[scene.status.image] ?? " ";
47214
+ const videoIcon = VIDEO_STATUS_ICON[scene.status.video] ?? " ";
47215
+ let statusLabel;
47216
+ if (scene.status.image === "done" && (scene.status.video === "done" || scene.status.video === "not-needed")) {
47217
+ statusLabel = source_default.green("Done");
47218
+ } else if (scene.status.image !== "done") {
47219
+ statusLabel = source_default.yellow("Image");
47220
+ } else {
47221
+ statusLabel = source_default.cyan("Video");
47222
+ }
47223
+ return "\u2502 " + pad(String(scene.order), COL_NUM) + " \u2502 " + pad(scene.description, COL_SCENE) + " \u2502 " + pad(imageIcon, COL_IMAGE) + " \u2502 " + pad(videoIcon, COL_VIDEO) + " \u2502 " + pad(statusLabel, COL_STATUS) + " \u2502";
47224
+ });
47225
+ return [header, top, headRow, divider, ...rows, bottom].join("\n");
47226
+ }
47227
+ function handleInit(options) {
47228
+ const validTypes = ["image-only", "image-video", "story"];
47229
+ if (!validTypes.includes(options.type)) {
47230
+ console.error(
47231
+ source_default.red(`Error: --type must be one of: ${validTypes.join(", ")}`)
47232
+ );
47233
+ process.exit(1);
47234
+ }
47235
+ if (!options.name || options.name.trim() === "") {
47236
+ console.error(source_default.red("Error: --name is required"));
47237
+ process.exit(1);
47238
+ }
47239
+ const project = {
47240
+ id: generateId(),
47241
+ name: options.name.trim(),
47242
+ type: options.type,
47243
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
47244
+ scenes: [],
47245
+ metadata: {
47246
+ client: options.client
47247
+ }
47248
+ };
47249
+ saveProject(project);
47250
+ setActiveId(project.id);
47251
+ console.log(source_default.green("\nDesign project created successfully!\n"));
47252
+ console.log(source_default.bold(" Name:"), project.name);
47253
+ console.log(source_default.bold(" Type:"), project.type);
47254
+ console.log(source_default.bold(" ID: "), source_default.gray(project.id));
47255
+ if (options.client) {
47256
+ console.log(source_default.bold(" Client:"), options.client);
47257
+ }
47258
+ console.log(
47259
+ source_default.gray("\nNext: add scenes with "),
47260
+ source_default.cyan(`gal run-design add-scene "Scene description"`)
47261
+ );
47262
+ }
47263
+ function handleAddScene(description, options) {
47264
+ const project = getActiveProject();
47265
+ if (!project) {
47266
+ console.error(
47267
+ source_default.red("Error: No active design project. Run `gal run-design init` first.")
47268
+ );
47269
+ process.exit(1);
47270
+ }
47271
+ const needsVideo = project.type !== "image-only";
47272
+ const scene = {
47273
+ id: generateSceneId(),
47274
+ order: project.scenes.length + 1,
47275
+ description: description.trim(),
47276
+ referenceImageUrl: options.ref,
47277
+ status: {
47278
+ image: "pending",
47279
+ video: needsVideo ? "pending" : "not-needed"
47280
+ },
47281
+ assets: {}
47282
+ };
47283
+ project.scenes.push(scene);
47284
+ saveProject(project);
47285
+ console.log(
47286
+ source_default.green(`
47287
+ Scene ${scene.order} added: `) + source_default.white(scene.description)
47288
+ );
47289
+ if (options.ref) {
47290
+ console.log(source_default.gray(" Reference image:"), options.ref);
47291
+ }
47292
+ console.log(source_default.gray(` Total scenes: ${project.scenes.length}`));
47293
+ }
47294
+ function handleStatus(options) {
47295
+ let project;
47296
+ if (options.project) {
47297
+ project = loadProject(options.project);
47298
+ if (!project) {
47299
+ console.error(
47300
+ source_default.red(`Error: Project '${options.project}' not found`)
47301
+ );
47302
+ process.exit(1);
47303
+ }
47304
+ } else {
47305
+ project = getActiveProject();
47306
+ if (!project) {
47307
+ ensureDir();
47308
+ const files = (0, import_fs32.readdirSync)(DESIGN_PROJECTS_DIR).filter(
47309
+ (f) => f.endsWith(".json") && f !== "active.json"
47310
+ );
47311
+ if (files.length === 0) {
47312
+ console.log(
47313
+ source_default.yellow("No design projects found."),
47314
+ source_default.gray("Run `gal run-design init` to create one.")
47315
+ );
47316
+ } else {
47317
+ console.log(source_default.bold("\nAvailable projects:\n"));
47318
+ for (const file of files) {
47319
+ const p = loadProject(file.replace(".json", ""));
47320
+ if (p) {
47321
+ console.log(
47322
+ ` ${source_default.cyan(p.id)} ${source_default.white(p.name)} ${source_default.gray(p.type)} ${source_default.gray(p.scenes.length + " scenes")}`
47323
+ );
47324
+ }
47325
+ }
47326
+ console.log(
47327
+ source_default.gray("\nUse `gal run-design status --project <id>` to view a specific project.")
47328
+ );
47329
+ }
47330
+ return;
47331
+ }
47332
+ }
47333
+ console.log("\n" + renderStatusTable(project));
47334
+ const done = project.scenes.filter(
47335
+ (s) => s.status.image === "done" && (s.status.video === "done" || s.status.video === "not-needed")
47336
+ ).length;
47337
+ const total = project.scenes.length;
47338
+ const pct = total > 0 ? Math.round(done / total * 100) : 0;
47339
+ console.log(
47340
+ source_default.gray(`
47341
+ ${done}/${total} complete (${pct}%)`)
47342
+ );
47343
+ const activeId = getActiveId();
47344
+ if (project.id === activeId) {
47345
+ console.log(source_default.green(" Active project"));
47346
+ }
47347
+ console.log();
47348
+ }
47349
+ function handleScene(nStr, options) {
47350
+ const n = parseInt(nStr, 10);
47351
+ if (isNaN(n) || n < 1) {
47352
+ console.error(source_default.red("Error: scene number must be a positive integer"));
47353
+ process.exit(1);
47354
+ }
47355
+ let project;
47356
+ if (options.project) {
47357
+ project = loadProject(options.project);
47358
+ if (!project) {
47359
+ console.error(source_default.red(`Error: Project '${options.project}' not found`));
47360
+ process.exit(1);
47361
+ }
47362
+ } else {
47363
+ project = getActiveProject();
47364
+ if (!project) {
47365
+ console.error(
47366
+ source_default.red("Error: No active design project. Run `gal run-design init` first.")
47367
+ );
47368
+ process.exit(1);
47369
+ }
47370
+ }
47371
+ const scene = project.scenes.find((s) => s.order === n);
47372
+ if (!scene) {
47373
+ console.error(
47374
+ source_default.red(`Error: Scene ${n} not found in project '${project.name}'`)
47375
+ );
47376
+ process.exit(1);
47377
+ }
47378
+ let changed = false;
47379
+ if (options.imageDone) {
47380
+ scene.status.image = "done";
47381
+ changed = true;
47382
+ }
47383
+ if (options.videoDone) {
47384
+ if (scene.status.video === "not-needed") {
47385
+ console.error(
47386
+ source_default.yellow(`Warning: Scene ${n} video is marked as 'not-needed' for project type '${project.type}'. Marking done anyway.`)
47387
+ );
47388
+ }
47389
+ scene.status.video = "done";
47390
+ changed = true;
47391
+ }
47392
+ if (options.notes !== void 0) {
47393
+ scene.notes = options.notes;
47394
+ changed = true;
47395
+ }
47396
+ if (!changed) {
47397
+ console.log(
47398
+ source_default.yellow(
47399
+ "No changes made. Use --image-done, --video-done, or --notes to update the scene."
47400
+ )
47401
+ );
47402
+ return;
47403
+ }
47404
+ saveProject(project);
47405
+ console.log(
47406
+ source_default.green(`
47407
+ Scene ${n} updated: `) + source_default.white(scene.description)
47408
+ );
47409
+ console.log(
47410
+ source_default.bold(" Image:"),
47411
+ scene.status.image,
47412
+ " " + source_default.bold("Video:"),
47413
+ scene.status.video
47414
+ );
47415
+ if (scene.notes) {
47416
+ console.log(source_default.bold(" Notes:"), scene.notes);
47417
+ }
47418
+ }
47419
+ function handleSync() {
47420
+ const project = getActiveProject();
47421
+ if (!project) {
47422
+ ensureDir();
47423
+ (0, import_fs32.writeFileSync)(
47424
+ (0, import_path29.join)(DESIGN_PROJECTS_DIR, "extension-sync.json"),
47425
+ JSON.stringify(null, null, 2)
47426
+ );
47427
+ console.log(source_default.yellow("No active project. Extension card cleared."));
47428
+ return;
47429
+ }
47430
+ const done = project.scenes.filter(
47431
+ (s) => s.status.image === "done" && (s.status.video === "done" || s.status.video === "not-needed")
47432
+ ).length;
47433
+ const summary = {
47434
+ id: project.id,
47435
+ name: project.name,
47436
+ type: project.type,
47437
+ totalScenes: project.scenes.length,
47438
+ completedScenes: done
47439
+ };
47440
+ ensureDir();
47441
+ (0, import_fs32.writeFileSync)(
47442
+ (0, import_path29.join)(DESIGN_PROJECTS_DIR, "extension-sync.json"),
47443
+ JSON.stringify(summary, null, 2)
47444
+ );
47445
+ console.log(source_default.green("\nSynced active project to extension:\n"));
47446
+ console.log(source_default.bold(" Name:"), project.name);
47447
+ console.log(source_default.bold(" Scenes:"), `${done}/${project.scenes.length} complete`);
47448
+ const pct = project.scenes.length > 0 ? Math.round(done / project.scenes.length * 100) : 0;
47449
+ console.log(source_default.bold(" Progress:"), `${pct}%`);
47450
+ console.log(
47451
+ source_default.gray(
47452
+ "\nThe extension popup will show a status card for this project.\n"
47453
+ )
47454
+ );
47455
+ }
47456
+ function createRunDesignCommand() {
47457
+ const runDesign = new Command("run-design");
47458
+ runDesign.description("Creative production pipeline orchestrator (image \u2192 video)");
47459
+ const initCmd = new Command("init");
47460
+ initCmd.description("Create a new design project").requiredOption("-t, --type <type>", "Project type: image-only | image-video | story").requiredOption("-n, --name <name>", "Project name").option("-c, --client <client>", "Client name (optional)").action((options) => {
47461
+ handleInit(options);
47462
+ });
47463
+ const addSceneCmd = new Command("add-scene");
47464
+ addSceneCmd.description("Add a scene to the active project").argument("<description>", "Scene description").option("-r, --ref <imageUrl>", "Reference image URL").action((description, options) => {
47465
+ handleAddScene(description, options);
47466
+ });
47467
+ const statusCmd = new Command("status");
47468
+ statusCmd.description("Show scene progress table for the active project").option("-p, --project <id>", "Project ID (defaults to active project)").action((options) => {
47469
+ handleStatus(options);
47470
+ });
47471
+ const sceneCmd = new Command("scene");
47472
+ sceneCmd.description("Update a scene status").argument("<n>", "Scene number (1-based)").option("--image-done", "Mark image as done").option("--video-done", "Mark video as done").option("--notes <text>", "Add/update notes on the scene").option("-p, --project <id>", "Project ID (defaults to active project)").action((n, options) => {
47473
+ handleScene(n, options);
47474
+ });
47475
+ const syncCmd = new Command("sync");
47476
+ syncCmd.description("Write active project summary for Chrome extension status card").action(() => {
47477
+ handleSync();
47478
+ });
47479
+ runDesign.addCommand(initCmd);
47480
+ runDesign.addCommand(addSceneCmd);
47481
+ runDesign.addCommand(statusCmd);
47482
+ runDesign.addCommand(sceneCmd);
47483
+ runDesign.addCommand(syncCmd);
47484
+ return runDesign;
47485
+ }
47486
+ var import_os19, import_path29, import_fs32, DESIGN_PROJECTS_DIR, ACTIVE_FILE, IMAGE_STATUS_ICON, VIDEO_STATUS_ICON;
47487
+ var init_run_design = __esm({
47488
+ "src/commands/run-design.ts"() {
47489
+ "use strict";
47490
+ init_esm();
47491
+ init_source();
47492
+ import_os19 = require("os");
47493
+ import_path29 = require("path");
47494
+ import_fs32 = require("fs");
47495
+ DESIGN_PROJECTS_DIR = (0, import_path29.join)((0, import_os19.homedir)(), ".gal", "design-projects");
47496
+ ACTIVE_FILE = (0, import_path29.join)(DESIGN_PROJECTS_DIR, "active.json");
47497
+ IMAGE_STATUS_ICON = {
47498
+ pending: " ",
47499
+ generating: " ",
47500
+ done: " ",
47501
+ "needs-regen": " "
47502
+ };
47503
+ VIDEO_STATUS_ICON = {
47504
+ pending: " ",
47505
+ generating: " ",
47506
+ done: " ",
47507
+ "needs-regen": " ",
47508
+ "not-needed": " "
47509
+ };
47510
+ }
47511
+ });
47512
+
47065
47513
  // src/commands/scan.ts
47066
47514
  function scanPlatform(rootDir, pattern) {
47067
47515
  const configs = [];
47068
47516
  const platform5 = pattern.platform;
47069
- const platformDir = (0, import_path29.join)(rootDir, pattern.directory);
47517
+ const platformDir = (0, import_path30.join)(rootDir, pattern.directory);
47070
47518
  if (pattern.settingsFile) {
47071
- const settingsPath = (0, import_path29.join)(platformDir, pattern.settingsFile);
47072
- if ((0, import_fs32.existsSync)(settingsPath)) {
47519
+ const settingsPath = (0, import_path30.join)(platformDir, pattern.settingsFile);
47520
+ if ((0, import_fs33.existsSync)(settingsPath)) {
47073
47521
  configs.push({
47074
47522
  platform: platform5,
47075
47523
  type: "settings",
47076
47524
  name: pattern.settingsFile,
47077
47525
  path: settingsPath,
47078
- relativePath: (0, import_path29.relative)(rootDir, settingsPath),
47079
- sizeBytes: (0, import_fs32.statSync)(settingsPath).size
47526
+ relativePath: (0, import_path30.relative)(rootDir, settingsPath),
47527
+ sizeBytes: (0, import_fs33.statSync)(settingsPath).size
47080
47528
  });
47081
47529
  }
47082
47530
  }
47083
47531
  if (pattern.configFile) {
47084
- const configPath = (0, import_path29.join)(platformDir, pattern.configFile);
47085
- if ((0, import_fs32.existsSync)(configPath)) {
47532
+ const configPath = (0, import_path30.join)(platformDir, pattern.configFile);
47533
+ if ((0, import_fs33.existsSync)(configPath)) {
47086
47534
  configs.push({
47087
47535
  platform: platform5,
47088
47536
  type: "settings",
47089
47537
  name: pattern.configFile,
47090
47538
  path: configPath,
47091
- relativePath: (0, import_path29.relative)(rootDir, configPath),
47092
- sizeBytes: (0, import_fs32.statSync)(configPath).size
47539
+ relativePath: (0, import_path30.relative)(rootDir, configPath),
47540
+ sizeBytes: (0, import_fs33.statSync)(configPath).size
47093
47541
  });
47094
47542
  }
47095
47543
  }
47096
47544
  if (pattern.rulesDir) {
47097
- const rulesDir = (0, import_path29.join)(platformDir, pattern.rulesDir);
47098
- if ((0, import_fs32.existsSync)(rulesDir) && (0, import_fs32.statSync)(rulesDir).isDirectory()) {
47545
+ const rulesDir = (0, import_path30.join)(platformDir, pattern.rulesDir);
47546
+ if ((0, import_fs33.existsSync)(rulesDir) && (0, import_fs33.statSync)(rulesDir).isDirectory()) {
47099
47547
  scanDir(rulesDir, rootDir, platform5, "rules", pattern.ruleExtensions, configs);
47100
47548
  }
47101
47549
  }
47102
47550
  if (pattern.rulesFile) {
47103
- const rulesPath = (0, import_path29.join)(platformDir, pattern.rulesFile);
47104
- if ((0, import_fs32.existsSync)(rulesPath)) {
47551
+ const rulesPath = (0, import_path30.join)(platformDir, pattern.rulesFile);
47552
+ if ((0, import_fs33.existsSync)(rulesPath)) {
47105
47553
  configs.push({
47106
47554
  platform: platform5,
47107
47555
  type: "rules",
47108
47556
  name: pattern.rulesFile,
47109
47557
  path: rulesPath,
47110
- relativePath: (0, import_path29.relative)(rootDir, rulesPath),
47111
- sizeBytes: (0, import_fs32.statSync)(rulesPath).size
47558
+ relativePath: (0, import_path30.relative)(rootDir, rulesPath),
47559
+ sizeBytes: (0, import_fs33.statSync)(rulesPath).size
47112
47560
  });
47113
47561
  }
47114
47562
  }
47115
47563
  if (pattern.commandsDir) {
47116
- const commandsDir = (0, import_path29.join)(platformDir, pattern.commandsDir);
47117
- if ((0, import_fs32.existsSync)(commandsDir) && (0, import_fs32.statSync)(commandsDir).isDirectory()) {
47564
+ const commandsDir = (0, import_path30.join)(platformDir, pattern.commandsDir);
47565
+ if ((0, import_fs33.existsSync)(commandsDir) && (0, import_fs33.statSync)(commandsDir).isDirectory()) {
47118
47566
  scanDir(commandsDir, rootDir, platform5, "commands", [".md", ".toml"], configs);
47119
47567
  }
47120
47568
  }
47121
47569
  if (pattern.hooksDir) {
47122
- const hooksDir = (0, import_path29.join)(platformDir, pattern.hooksDir);
47123
- if ((0, import_fs32.existsSync)(hooksDir) && (0, import_fs32.statSync)(hooksDir).isDirectory()) {
47570
+ const hooksDir = (0, import_path30.join)(platformDir, pattern.hooksDir);
47571
+ if ((0, import_fs33.existsSync)(hooksDir) && (0, import_fs33.statSync)(hooksDir).isDirectory()) {
47124
47572
  scanDir(hooksDir, rootDir, platform5, "hooks", [".md", ".json", ".sh", ".ts", ".js"], configs);
47125
47573
  }
47126
47574
  }
47127
47575
  if (pattern.hooksConfigFile) {
47128
- const hooksConfigPath = (0, import_path29.join)(platformDir, pattern.hooksConfigFile);
47129
- if ((0, import_fs32.existsSync)(hooksConfigPath)) {
47576
+ const hooksConfigPath = (0, import_path30.join)(platformDir, pattern.hooksConfigFile);
47577
+ if ((0, import_fs33.existsSync)(hooksConfigPath)) {
47130
47578
  configs.push({
47131
47579
  platform: platform5,
47132
47580
  type: "hooks",
47133
47581
  name: pattern.hooksConfigFile,
47134
47582
  path: hooksConfigPath,
47135
- relativePath: (0, import_path29.relative)(rootDir, hooksConfigPath),
47136
- sizeBytes: (0, import_fs32.statSync)(hooksConfigPath).size
47583
+ relativePath: (0, import_path30.relative)(rootDir, hooksConfigPath),
47584
+ sizeBytes: (0, import_fs33.statSync)(hooksConfigPath).size
47137
47585
  });
47138
47586
  }
47139
47587
  }
47140
47588
  if (pattern.agentsDir) {
47141
- const agentsDir = (0, import_path29.join)(platformDir, pattern.agentsDir);
47142
- if ((0, import_fs32.existsSync)(agentsDir) && (0, import_fs32.statSync)(agentsDir).isDirectory()) {
47589
+ const agentsDir = (0, import_path30.join)(platformDir, pattern.agentsDir);
47590
+ if ((0, import_fs33.existsSync)(agentsDir) && (0, import_fs33.statSync)(agentsDir).isDirectory()) {
47143
47591
  scanDir(agentsDir, rootDir, platform5, "agents", [".md", ".toml", ".agent.md"], configs);
47144
47592
  }
47145
47593
  }
47146
47594
  if (pattern.skillsDir) {
47147
- const skillsDir = (0, import_path29.join)(platformDir, pattern.skillsDir);
47148
- if ((0, import_fs32.existsSync)(skillsDir) && (0, import_fs32.statSync)(skillsDir).isDirectory()) {
47595
+ const skillsDir = (0, import_path30.join)(platformDir, pattern.skillsDir);
47596
+ if ((0, import_fs33.existsSync)(skillsDir) && (0, import_fs33.statSync)(skillsDir).isDirectory()) {
47149
47597
  scanDir(skillsDir, rootDir, platform5, "skills", [".md"], configs);
47150
47598
  }
47151
47599
  }
47152
47600
  if (pattern.policiesDir) {
47153
- const policiesDir = (0, import_path29.join)(platformDir, pattern.policiesDir);
47154
- if ((0, import_fs32.existsSync)(policiesDir) && (0, import_fs32.statSync)(policiesDir).isDirectory()) {
47601
+ const policiesDir = (0, import_path30.join)(platformDir, pattern.policiesDir);
47602
+ if ((0, import_fs33.existsSync)(policiesDir) && (0, import_fs33.statSync)(policiesDir).isDirectory()) {
47155
47603
  scanDir(policiesDir, rootDir, platform5, "policies", [".toml", ".md"], configs);
47156
47604
  }
47157
47605
  }
47158
47606
  if (pattern.workflowsDir) {
47159
- const workflowsDir = (0, import_path29.join)(platformDir, pattern.workflowsDir);
47160
- if ((0, import_fs32.existsSync)(workflowsDir) && (0, import_fs32.statSync)(workflowsDir).isDirectory()) {
47607
+ const workflowsDir = (0, import_path30.join)(platformDir, pattern.workflowsDir);
47608
+ if ((0, import_fs33.existsSync)(workflowsDir) && (0, import_fs33.statSync)(workflowsDir).isDirectory()) {
47161
47609
  scanDir(workflowsDir, rootDir, platform5, "workflows", [".md"], configs);
47162
47610
  }
47163
47611
  }
47164
47612
  if (pattern.promptsDir) {
47165
- const promptsDir = (0, import_path29.join)(platformDir, pattern.promptsDir);
47166
- if ((0, import_fs32.existsSync)(promptsDir) && (0, import_fs32.statSync)(promptsDir).isDirectory()) {
47613
+ const promptsDir = (0, import_path30.join)(platformDir, pattern.promptsDir);
47614
+ if ((0, import_fs33.existsSync)(promptsDir) && (0, import_fs33.statSync)(promptsDir).isDirectory()) {
47167
47615
  scanDir(promptsDir, rootDir, platform5, "prompts", [".prompt.md", ".md"], configs);
47168
47616
  }
47169
47617
  }
@@ -47182,59 +47630,59 @@ function scanPlatform(rootDir, pattern) {
47182
47630
  for (const { key, type } of rootInstructionFiles) {
47183
47631
  const fileName = pattern[key];
47184
47632
  if (fileName) {
47185
- const rootPath = (0, import_path29.join)(rootDir, fileName);
47186
- const platformPath = (0, import_path29.join)(platformDir, fileName);
47187
- if ((0, import_fs32.existsSync)(rootPath)) {
47633
+ const rootPath = (0, import_path30.join)(rootDir, fileName);
47634
+ const platformPath = (0, import_path30.join)(platformDir, fileName);
47635
+ if ((0, import_fs33.existsSync)(rootPath)) {
47188
47636
  configs.push({
47189
47637
  platform: platform5,
47190
47638
  type,
47191
47639
  name: fileName,
47192
47640
  path: rootPath,
47193
- relativePath: (0, import_path29.relative)(rootDir, rootPath),
47194
- sizeBytes: (0, import_fs32.statSync)(rootPath).size
47641
+ relativePath: (0, import_path30.relative)(rootDir, rootPath),
47642
+ sizeBytes: (0, import_fs33.statSync)(rootPath).size
47195
47643
  });
47196
- } else if ((0, import_fs32.existsSync)(platformPath) && platformPath !== rootPath) {
47644
+ } else if ((0, import_fs33.existsSync)(platformPath) && platformPath !== rootPath) {
47197
47645
  configs.push({
47198
47646
  platform: platform5,
47199
47647
  type,
47200
47648
  name: fileName,
47201
47649
  path: platformPath,
47202
- relativePath: (0, import_path29.relative)(rootDir, platformPath),
47203
- sizeBytes: (0, import_fs32.statSync)(platformPath).size
47650
+ relativePath: (0, import_path30.relative)(rootDir, platformPath),
47651
+ sizeBytes: (0, import_fs33.statSync)(platformPath).size
47204
47652
  });
47205
47653
  }
47206
47654
  }
47207
47655
  }
47208
47656
  if (pattern.mcpFile) {
47209
- const mcpPath = (0, import_path29.join)(rootDir, pattern.mcpFile);
47210
- if ((0, import_fs32.existsSync)(mcpPath)) {
47657
+ const mcpPath = (0, import_path30.join)(rootDir, pattern.mcpFile);
47658
+ if ((0, import_fs33.existsSync)(mcpPath)) {
47211
47659
  configs.push({
47212
47660
  platform: platform5,
47213
47661
  type: "mcp",
47214
47662
  name: pattern.mcpFile,
47215
47663
  path: mcpPath,
47216
- relativePath: (0, import_path29.relative)(rootDir, mcpPath),
47217
- sizeBytes: (0, import_fs32.statSync)(mcpPath).size
47664
+ relativePath: (0, import_path30.relative)(rootDir, mcpPath),
47665
+ sizeBytes: (0, import_fs33.statSync)(mcpPath).size
47218
47666
  });
47219
47667
  }
47220
47668
  }
47221
47669
  if (pattern.memoryDir) {
47222
- const memDir = (0, import_path29.join)(platformDir, pattern.memoryDir);
47223
- if ((0, import_fs32.existsSync)(memDir) && (0, import_fs32.statSync)(memDir).isDirectory()) {
47670
+ const memDir = (0, import_path30.join)(platformDir, pattern.memoryDir);
47671
+ if ((0, import_fs33.existsSync)(memDir) && (0, import_fs33.statSync)(memDir).isDirectory()) {
47224
47672
  const exts = pattern.memoryExtensions || [".md"];
47225
47673
  scanDir(memDir, rootDir, platform5, "memory", exts, configs);
47226
47674
  }
47227
47675
  }
47228
47676
  if (pattern.cliConfigFile) {
47229
- const cliPath = (0, import_path29.join)(platformDir, pattern.cliConfigFile);
47230
- if ((0, import_fs32.existsSync)(cliPath)) {
47677
+ const cliPath = (0, import_path30.join)(platformDir, pattern.cliConfigFile);
47678
+ if ((0, import_fs33.existsSync)(cliPath)) {
47231
47679
  configs.push({
47232
47680
  platform: platform5,
47233
47681
  type: "settings",
47234
47682
  name: pattern.cliConfigFile,
47235
47683
  path: cliPath,
47236
- relativePath: (0, import_path29.relative)(rootDir, cliPath),
47237
- sizeBytes: (0, import_fs32.statSync)(cliPath).size
47684
+ relativePath: (0, import_path30.relative)(rootDir, cliPath),
47685
+ sizeBytes: (0, import_fs33.statSync)(cliPath).size
47238
47686
  });
47239
47687
  }
47240
47688
  }
@@ -47242,9 +47690,9 @@ function scanPlatform(rootDir, pattern) {
47242
47690
  }
47243
47691
  function scanDir(dir, rootDir, platform5, type, extensions, configs) {
47244
47692
  try {
47245
- const entries = (0, import_fs32.readdirSync)(dir, { withFileTypes: true });
47693
+ const entries = (0, import_fs33.readdirSync)(dir, { withFileTypes: true });
47246
47694
  for (const entry of entries) {
47247
- const fullPath = (0, import_path29.join)(dir, entry.name);
47695
+ const fullPath = (0, import_path30.join)(dir, entry.name);
47248
47696
  if (entry.isDirectory()) {
47249
47697
  scanDir(fullPath, rootDir, platform5, type, extensions, configs);
47250
47698
  } else if (entry.isFile()) {
@@ -47255,8 +47703,8 @@ function scanDir(dir, rootDir, platform5, type, extensions, configs) {
47255
47703
  type,
47256
47704
  name: entry.name,
47257
47705
  path: fullPath,
47258
- relativePath: (0, import_path29.relative)(rootDir, fullPath),
47259
- sizeBytes: (0, import_fs32.statSync)(fullPath).size
47706
+ relativePath: (0, import_path30.relative)(rootDir, fullPath),
47707
+ sizeBytes: (0, import_fs33.statSync)(fullPath).size
47260
47708
  });
47261
47709
  }
47262
47710
  }
@@ -47273,7 +47721,7 @@ function createScanCommand() {
47273
47721
  const command = new Command("scan");
47274
47722
  command.description("Scan local directory for AI agent configurations (no auth required)").option("--path <path>", "Directory to scan (default: current directory or project root)").option("-p, --platform <platform>", `Filter by platform (${ALL_PLATFORM_IDS.join(", ")})`).option("--format <format>", "Output format: table (default) or json", "table").option("-r, --recursive", "Scan subdirectories for additional projects").option("--include-global", "Include global/home-directory memory locations").action(async (options) => {
47275
47723
  const targetDir = options.path ? options.path : findProjectRoot(process.cwd());
47276
- if (!(0, import_fs32.existsSync)(targetDir)) {
47724
+ if (!(0, import_fs33.existsSync)(targetDir)) {
47277
47725
  console.error(source_default.red(`Directory not found: ${targetDir}`));
47278
47726
  process.exit(1);
47279
47727
  }
@@ -47304,12 +47752,12 @@ function createScanCommand() {
47304
47752
  }
47305
47753
  }
47306
47754
  if (options.includeGlobal) {
47307
- const home = (0, import_os19.homedir)();
47755
+ const home = (0, import_os20.homedir)();
47308
47756
  for (const loc of GLOBAL_MEMORY_LOCATIONS) {
47309
47757
  if (platformFilter && loc.platform !== platformFilter) continue;
47310
47758
  for (const relPath of loc.paths) {
47311
- const globalDir = (0, import_path29.join)(home, relPath);
47312
- if (!(0, import_fs32.existsSync)(globalDir) || !(0, import_fs32.statSync)(globalDir).isDirectory()) continue;
47759
+ const globalDir = (0, import_path30.join)(home, relPath);
47760
+ if (!(0, import_fs33.existsSync)(globalDir) || !(0, import_fs33.statSync)(globalDir).isDirectory()) continue;
47313
47761
  const globalConfigs = [];
47314
47762
  scanDir(globalDir, home, loc.platform, "memory", loc.extensions, globalConfigs);
47315
47763
  if (globalConfigs.length > 0) {
@@ -47385,15 +47833,15 @@ function createScanCommand() {
47385
47833
  });
47386
47834
  return command;
47387
47835
  }
47388
- var import_fs32, import_path29, import_os19, GLOBAL_MEMORY_LOCATIONS, PLATFORM_LABELS, PLATFORM_COLORS;
47836
+ var import_fs33, import_path30, import_os20, GLOBAL_MEMORY_LOCATIONS, PLATFORM_LABELS, PLATFORM_COLORS;
47389
47837
  var init_scan = __esm({
47390
47838
  "src/commands/scan.ts"() {
47391
47839
  "use strict";
47392
47840
  init_esm();
47393
47841
  init_source();
47394
- import_fs32 = require("fs");
47395
- import_path29 = require("path");
47396
- import_os19 = require("os");
47842
+ import_fs33 = require("fs");
47843
+ import_path30 = require("path");
47844
+ import_os20 = require("os");
47397
47845
  init_dist2();
47398
47846
  init_project_detection();
47399
47847
  GLOBAL_MEMORY_LOCATIONS = [
@@ -48046,8 +48494,8 @@ function createSandboxCommand() {
48046
48494
  return sandboxCmd;
48047
48495
  }
48048
48496
  async function validateConfigFile(sandbox, options) {
48049
- const configPath = import_path30.default.resolve(options.config);
48050
- const fileName = import_path30.default.basename(configPath);
48497
+ const configPath = import_path31.default.resolve(options.config);
48498
+ const fileName = import_path31.default.basename(configPath);
48051
48499
  const spinner = ora(`Loading configuration: ${fileName}`).start();
48052
48500
  try {
48053
48501
  const configContent = await import_promises8.default.readFile(configPath, "utf-8");
@@ -48162,7 +48610,7 @@ async function startInteractiveSession(sandbox) {
48162
48610
  rl.on("close", resolve8);
48163
48611
  });
48164
48612
  }
48165
- var import_promises8, import_path30;
48613
+ var import_promises8, import_path31;
48166
48614
  var init_sandbox = __esm({
48167
48615
  "src/commands/sandbox.ts"() {
48168
48616
  "use strict";
@@ -48171,7 +48619,7 @@ var init_sandbox = __esm({
48171
48619
  init_ora();
48172
48620
  init_e2b_sandbox();
48173
48621
  import_promises8 = __toESM(require("fs/promises"), 1);
48174
- import_path30 = __toESM(require("path"), 1);
48622
+ import_path31 = __toESM(require("path"), 1);
48175
48623
  }
48176
48624
  });
48177
48625
 
@@ -48180,7 +48628,7 @@ function isTestFile(filename) {
48180
48628
  return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
48181
48629
  }
48182
48630
  function isImplFile(filename) {
48183
- const ext = (0, import_path31.extname)(filename);
48631
+ const ext = (0, import_path32.extname)(filename);
48184
48632
  if (!IMPL_EXTENSIONS.has(ext)) return false;
48185
48633
  if (isTestFile(filename)) return false;
48186
48634
  if (IGNORE_FILES.has(filename)) return false;
@@ -48195,16 +48643,16 @@ function scanDirectory(dir, maxDepth = 6) {
48195
48643
  if (depth > maxDepth) return;
48196
48644
  let entries;
48197
48645
  try {
48198
- entries = (0, import_fs33.readdirSync)(currentDir);
48646
+ entries = (0, import_fs34.readdirSync)(currentDir);
48199
48647
  } catch {
48200
48648
  return;
48201
48649
  }
48202
48650
  for (const entry of entries) {
48203
48651
  if (IGNORE_DIRS.has(entry)) continue;
48204
- const fullPath = (0, import_path31.join)(currentDir, entry);
48652
+ const fullPath = (0, import_path32.join)(currentDir, entry);
48205
48653
  let stat5;
48206
48654
  try {
48207
- stat5 = (0, import_fs33.statSync)(fullPath);
48655
+ stat5 = (0, import_fs34.statSync)(fullPath);
48208
48656
  } catch {
48209
48657
  continue;
48210
48658
  }
@@ -48214,7 +48662,7 @@ function scanDirectory(dir, maxDepth = 6) {
48214
48662
  }
48215
48663
  walk(fullPath, depth + 1);
48216
48664
  } else if (stat5.isFile()) {
48217
- const relPath = (0, import_path31.relative)(dir, fullPath);
48665
+ const relPath = (0, import_path32.relative)(dir, fullPath);
48218
48666
  if (isTestFile(entry)) {
48219
48667
  testFiles.push(relPath);
48220
48668
  } else if (isImplFile(entry)) {
@@ -48234,15 +48682,15 @@ function findSpecFiles(dir) {
48234
48682
  if (depth > 4) return;
48235
48683
  let entries;
48236
48684
  try {
48237
- entries = (0, import_fs33.readdirSync)(currentDir);
48685
+ entries = (0, import_fs34.readdirSync)(currentDir);
48238
48686
  } catch {
48239
48687
  return;
48240
48688
  }
48241
48689
  for (const entry of entries) {
48242
- const fullPath = (0, import_path31.join)(currentDir, entry);
48690
+ const fullPath = (0, import_path32.join)(currentDir, entry);
48243
48691
  let stat5;
48244
48692
  try {
48245
- stat5 = (0, import_fs33.statSync)(fullPath);
48693
+ stat5 = (0, import_fs34.statSync)(fullPath);
48246
48694
  } catch {
48247
48695
  continue;
48248
48696
  }
@@ -48258,10 +48706,10 @@ function findSpecFiles(dir) {
48258
48706
  }
48259
48707
  function findImplFilesWithoutTests(implFiles, testFiles) {
48260
48708
  const testBasenames = new Set(
48261
- testFiles.map((f) => (0, import_path31.basename)(f).replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, ""))
48709
+ testFiles.map((f) => (0, import_path32.basename)(f).replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, ""))
48262
48710
  );
48263
48711
  return implFiles.filter((f) => {
48264
- const base = (0, import_path31.basename)(f).replace(/\.(ts|tsx|js|jsx)$/, "");
48712
+ const base = (0, import_path32.basename)(f).replace(/\.(ts|tsx|js|jsx)$/, "");
48265
48713
  return !testBasenames.has(base);
48266
48714
  });
48267
48715
  }
@@ -48291,8 +48739,8 @@ function runChecks(basePath) {
48291
48739
  const weight2 = 25;
48292
48740
  maxScore += weight2;
48293
48741
  const hasSpecs = specFiles.length > 0;
48294
- const hasClaudeDir = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".claude"));
48295
- const hasSpecsDir = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "specs"));
48742
+ const hasClaudeDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude"));
48743
+ const hasSpecsDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "specs"));
48296
48744
  let specScore = 0;
48297
48745
  if (hasSpecs) specScore += 15;
48298
48746
  if (hasClaudeDir) specScore += 5;
@@ -48311,8 +48759,8 @@ function runChecks(basePath) {
48311
48759
  }
48312
48760
  const weight3 = 15;
48313
48761
  maxScore += weight3;
48314
- const hasClaudeMd = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "CLAUDE.md"));
48315
- const hasClaudeSettings = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".claude", "settings.json"));
48762
+ const hasClaudeMd = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "CLAUDE.md"));
48763
+ const hasClaudeSettings = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude", "settings.json"));
48316
48764
  let claudeScore = 0;
48317
48765
  if (hasClaudeMd) claudeScore += 10;
48318
48766
  if (hasClaudeSettings) claudeScore += 5;
@@ -48330,9 +48778,9 @@ function runChecks(basePath) {
48330
48778
  }
48331
48779
  const weight4 = 15;
48332
48780
  maxScore += weight4;
48333
- const hasPackageJson = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "package.json"));
48334
- const hasReadme = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "README.md"));
48335
- const hasTsConfig = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "tsconfig.json"));
48781
+ const hasPackageJson = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "package.json"));
48782
+ const hasReadme = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "README.md"));
48783
+ const hasTsConfig = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "tsconfig.json"));
48336
48784
  let structureScore = 0;
48337
48785
  if (hasPackageJson) structureScore += 5;
48338
48786
  if (hasReadme) structureScore += 5;
@@ -48352,9 +48800,9 @@ function runChecks(basePath) {
48352
48800
  });
48353
48801
  const weight5 = 15;
48354
48802
  maxScore += weight5;
48355
- const hasGitDir = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".git"));
48356
- const hasGithubDir = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".github"));
48357
- const hasWorkflows = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".github", "workflows"));
48803
+ const hasGitDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".git"));
48804
+ const hasGithubDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".github"));
48805
+ const hasWorkflows = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".github", "workflows"));
48358
48806
  let gitScore = 0;
48359
48807
  if (hasGitDir) gitScore += 5;
48360
48808
  if (hasGithubDir) gitScore += 5;
@@ -48693,8 +49141,8 @@ function createSdlcCommand() {
48693
49141
  spinner.start("Scanning git history and local artifacts...");
48694
49142
  const basePath = process.cwd();
48695
49143
  const SDLC_PHASES_ORDERED = ["specify", "design", "test", "implement", "deploy-verify", "review", "merge"];
48696
- const hasSpec = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "spec.md")) || (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "specs")) || (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".claude", "spec.md"));
48697
- const hasPlan = (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "plan.md")) || (0, import_fs33.existsSync)((0, import_path31.join)(basePath, ".claude", "plan.md")) || (0, import_fs33.existsSync)((0, import_path31.join)(basePath, "tasks.md"));
49144
+ const hasSpec = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "spec.md")) || (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "specs")) || (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude", "spec.md"));
49145
+ const hasPlan = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "plan.md")) || (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude", "plan.md")) || (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "tasks.md"));
48698
49146
  const scanResult = scanDirectory(basePath);
48699
49147
  const hasTests = scanResult.testFiles.length > 0;
48700
49148
  const hasImpl = scanResult.implFiles.length > 0;
@@ -48837,15 +49285,15 @@ function createSdlcCommand() {
48837
49285
  });
48838
49286
  return cmd;
48839
49287
  }
48840
- var import_fs33, import_path31, import_child_process10, IMPL_EXTENSIONS, IGNORE_DIRS, IGNORE_FILES;
49288
+ var import_fs34, import_path32, import_child_process10, IMPL_EXTENSIONS, IGNORE_DIRS, IGNORE_FILES;
48841
49289
  var init_sdlc = __esm({
48842
49290
  "src/commands/sdlc.ts"() {
48843
49291
  "use strict";
48844
49292
  init_esm();
48845
49293
  init_source();
48846
49294
  init_ora();
48847
- import_fs33 = require("fs");
48848
- import_path31 = require("path");
49295
+ import_fs34 = require("fs");
49296
+ import_path32 = require("path");
48849
49297
  import_child_process10 = require("child_process");
48850
49298
  init_config_manager();
48851
49299
  IMPL_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
@@ -48964,10 +49412,10 @@ var init_security = __esm({
48964
49412
 
48965
49413
  // src/commands/status.ts
48966
49414
  function readTermsAcceptance() {
48967
- const configFile = (0, import_path32.join)((0, import_os20.homedir)(), ".gal", "config.json");
49415
+ const configFile = (0, import_path33.join)((0, import_os21.homedir)(), ".gal", "config.json");
48968
49416
  try {
48969
- if ((0, import_fs34.existsSync)(configFile)) {
48970
- const raw = JSON.parse((0, import_fs34.readFileSync)(configFile, "utf-8"));
49417
+ if ((0, import_fs35.existsSync)(configFile)) {
49418
+ const raw = JSON.parse((0, import_fs35.readFileSync)(configFile, "utf-8"));
48971
49419
  if (typeof raw.termsAcceptedAt === "string" && raw.termsAcceptedAt.length > 0) {
48972
49420
  return { accepted: true, acceptedAt: raw.termsAcceptedAt };
48973
49421
  }
@@ -49139,7 +49587,7 @@ function displayStatusJson(result, health) {
49139
49587
  }
49140
49588
  function isRateLimited(projectId) {
49141
49589
  try {
49142
- const raw = (0, import_fs34.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49590
+ const raw = (0, import_fs35.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49143
49591
  const cache = JSON.parse(raw);
49144
49592
  const lastReport = cache[projectId];
49145
49593
  if (lastReport && Date.now() - lastReport < RATE_LIMIT_MS) {
@@ -49153,13 +49601,13 @@ function recordReport(projectId) {
49153
49601
  try {
49154
49602
  let cache = {};
49155
49603
  try {
49156
- const raw = (0, import_fs34.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49604
+ const raw = (0, import_fs35.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49157
49605
  cache = JSON.parse(raw);
49158
49606
  } catch {
49159
49607
  }
49160
49608
  cache[projectId] = Date.now();
49161
- (0, import_fs34.mkdirSync)((0, import_path32.join)((0, import_os20.homedir)(), ".gal"), { recursive: true });
49162
- (0, import_fs34.writeFileSync)(DRIFT_REPORT_CACHE_PATH, JSON.stringify(cache));
49609
+ (0, import_fs35.mkdirSync)((0, import_path33.join)((0, import_os21.homedir)(), ".gal"), { recursive: true });
49610
+ (0, import_fs35.writeFileSync)(DRIFT_REPORT_CACHE_PATH, JSON.stringify(cache));
49163
49611
  } catch {
49164
49612
  }
49165
49613
  }
@@ -49264,16 +49712,16 @@ function createStatusCommand2() {
49264
49712
  });
49265
49713
  return command;
49266
49714
  }
49267
- var import_path32, import_os20, import_fs34, cliVersion6, defaultApiUrl15, PLATFORM_LABELS2, RATE_LIMIT_MS, DRIFT_REPORT_CACHE_PATH;
49715
+ var import_path33, import_os21, import_fs35, cliVersion6, defaultApiUrl15, PLATFORM_LABELS2, RATE_LIMIT_MS, DRIFT_REPORT_CACHE_PATH;
49268
49716
  var init_status = __esm({
49269
49717
  "src/commands/status.ts"() {
49270
49718
  "use strict";
49271
49719
  init_esm();
49272
49720
  init_source();
49273
49721
  init_ora();
49274
- import_path32 = require("path");
49275
- import_os20 = require("os");
49276
- import_fs34 = require("fs");
49722
+ import_path33 = require("path");
49723
+ import_os21 = require("os");
49724
+ import_fs35 = require("fs");
49277
49725
  init_gal_config_service();
49278
49726
  init_config_manager();
49279
49727
  init_CoreServiceProvider();
@@ -49289,7 +49737,7 @@ var init_status = __esm({
49289
49737
  ])
49290
49738
  );
49291
49739
  RATE_LIMIT_MS = 5 * 60 * 1e3;
49292
- DRIFT_REPORT_CACHE_PATH = (0, import_path32.join)((0, import_os20.homedir)(), ".gal", "drift-report-cache.json");
49740
+ DRIFT_REPORT_CACHE_PATH = (0, import_path33.join)((0, import_os21.homedir)(), ".gal", "drift-report-cache.json");
49293
49741
  }
49294
49742
  });
49295
49743
 
@@ -50617,13 +51065,13 @@ function getGitHookManager() {
50617
51065
  }
50618
51066
  return defaultManager;
50619
51067
  }
50620
- var import_child_process11, import_fs35, import_path33, DEFAULT_GIT_HOOK_CONFIG, GitHookManager, defaultManager;
51068
+ var import_child_process11, import_fs36, import_path34, DEFAULT_GIT_HOOK_CONFIG, GitHookManager, defaultManager;
50621
51069
  var init_git_hooks = __esm({
50622
51070
  "src/triggers/git-hooks.ts"() {
50623
51071
  "use strict";
50624
51072
  import_child_process11 = require("child_process");
50625
- import_fs35 = require("fs");
50626
- import_path33 = require("path");
51073
+ import_fs36 = require("fs");
51074
+ import_path34 = require("path");
50627
51075
  init_source();
50628
51076
  init_triggers();
50629
51077
  DEFAULT_GIT_HOOK_CONFIG = {
@@ -50666,12 +51114,12 @@ var init_git_hooks = __esm({
50666
51114
  if (this.gitDir) return this.gitDir;
50667
51115
  let currentPath = startPath;
50668
51116
  while (currentPath !== "/") {
50669
- const gitPath = (0, import_path33.join)(currentPath, ".git");
50670
- if ((0, import_fs35.existsSync)(gitPath)) {
51117
+ const gitPath = (0, import_path34.join)(currentPath, ".git");
51118
+ if ((0, import_fs36.existsSync)(gitPath)) {
50671
51119
  this.gitDir = gitPath;
50672
51120
  return gitPath;
50673
51121
  }
50674
- currentPath = (0, import_path33.dirname)(currentPath);
51122
+ currentPath = (0, import_path34.dirname)(currentPath);
50675
51123
  }
50676
51124
  return null;
50677
51125
  }
@@ -50681,8 +51129,8 @@ var init_git_hooks = __esm({
50681
51129
  * @param projectPath - The root path of the project; defaults to the current working directory
50682
51130
  * @returns An object containing arrays of installed and skipped hook type names
50683
51131
  */
50684
- installHooks(projectPath = process.cwd()) {
50685
- const gitDir = this.findGitDir(projectPath);
51132
+ installHooks(projectPath2 = process.cwd()) {
51133
+ const gitDir = this.findGitDir(projectPath2);
50686
51134
  if (!gitDir) {
50687
51135
  return {
50688
51136
  installed: [],
@@ -50693,29 +51141,29 @@ var init_git_hooks = __esm({
50693
51141
  ]
50694
51142
  };
50695
51143
  }
50696
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
50697
- if (!(0, import_fs35.existsSync)(hooksDir)) {
50698
- (0, import_fs35.mkdirSync)(hooksDir, { recursive: true });
51144
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
51145
+ if (!(0, import_fs36.existsSync)(hooksDir)) {
51146
+ (0, import_fs36.mkdirSync)(hooksDir, { recursive: true });
50699
51147
  }
50700
51148
  const installed = [];
50701
51149
  const skipped = [];
50702
51150
  const warnings = [];
50703
51151
  for (const hookType of this.config.hooks) {
50704
- const hookPath = (0, import_path33.join)(hooksDir, hookType);
51152
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
50705
51153
  const hookScript = this.generateHookScript(hookType);
50706
- if ((0, import_fs35.existsSync)(hookPath)) {
50707
- const existing = (0, import_fs35.readFileSync)(hookPath, "utf-8");
51154
+ if ((0, import_fs36.existsSync)(hookPath)) {
51155
+ const existing = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50708
51156
  if (existing.includes("GAL_HOOK_MARKER")) {
50709
- (0, import_fs35.writeFileSync)(hookPath, hookScript);
50710
- (0, import_fs35.chmodSync)(hookPath, "755");
51157
+ (0, import_fs36.writeFileSync)(hookPath, hookScript);
51158
+ (0, import_fs36.chmodSync)(hookPath, "755");
50711
51159
  installed.push(hookType);
50712
51160
  } else {
50713
51161
  console.log(source_default.yellow(`Skipping ${hookType}: existing hook found`));
50714
51162
  skipped.push(hookType);
50715
51163
  }
50716
51164
  } else {
50717
- (0, import_fs35.writeFileSync)(hookPath, hookScript);
50718
- (0, import_fs35.chmodSync)(hookPath, "755");
51165
+ (0, import_fs36.writeFileSync)(hookPath, hookScript);
51166
+ (0, import_fs36.chmodSync)(hookPath, "755");
50719
51167
  installed.push(hookType);
50720
51168
  }
50721
51169
  }
@@ -50727,17 +51175,17 @@ var init_git_hooks = __esm({
50727
51175
  * @param projectPath - The root path of the project; defaults to the current working directory
50728
51176
  * @returns An array of hook type names that were successfully removed
50729
51177
  */
50730
- uninstallHooks(projectPath = process.cwd()) {
50731
- const gitDir = this.findGitDir(projectPath);
51178
+ uninstallHooks(projectPath2 = process.cwd()) {
51179
+ const gitDir = this.findGitDir(projectPath2);
50732
51180
  if (!gitDir) {
50733
51181
  return [];
50734
51182
  }
50735
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
51183
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
50736
51184
  const removed = [];
50737
51185
  for (const hookType of this.config.hooks) {
50738
- const hookPath = (0, import_path33.join)(hooksDir, hookType);
50739
- if ((0, import_fs35.existsSync)(hookPath)) {
50740
- const content = (0, import_fs35.readFileSync)(hookPath, "utf-8");
51186
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
51187
+ if ((0, import_fs36.existsSync)(hookPath)) {
51188
+ const content = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50741
51189
  if (content.includes("GAL_HOOK_MARKER")) {
50742
51190
  const { unlinkSync: unlinkSync6 } = require("fs");
50743
51191
  unlinkSync6(hookPath);
@@ -50955,18 +51403,18 @@ exit 0
50955
51403
  * @param projectPath - The root path of the project; defaults to the current working directory
50956
51404
  * @returns An object with arrays of installed and missing hook type names
50957
51405
  */
50958
- isInstalled(projectPath = process.cwd()) {
50959
- const gitDir = this.findGitDir(projectPath);
51406
+ isInstalled(projectPath2 = process.cwd()) {
51407
+ const gitDir = this.findGitDir(projectPath2);
50960
51408
  if (!gitDir) {
50961
51409
  return { installed: [], missing: this.config.hooks };
50962
51410
  }
50963
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
51411
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
50964
51412
  const installed = [];
50965
51413
  const missing = [];
50966
51414
  for (const hookType of this.config.hooks) {
50967
- const hookPath = (0, import_path33.join)(hooksDir, hookType);
50968
- if ((0, import_fs35.existsSync)(hookPath)) {
50969
- const content = (0, import_fs35.readFileSync)(hookPath, "utf-8");
51415
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
51416
+ if ((0, import_fs36.existsSync)(hookPath)) {
51417
+ const content = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50970
51418
  if (content.includes("GAL_HOOK_MARKER")) {
50971
51419
  installed.push(hookType);
50972
51420
  } else {
@@ -50990,12 +51438,12 @@ function getFileWatcher() {
50990
51438
  }
50991
51439
  return defaultWatcher;
50992
51440
  }
50993
- var import_fs36, import_path34, DEFAULT_FILE_WATCHER_CONFIG, AGENT_CONFIG_PATTERNS, FileWatcher, defaultWatcher;
51441
+ var import_fs37, import_path35, DEFAULT_FILE_WATCHER_CONFIG, AGENT_CONFIG_PATTERNS, FileWatcher, defaultWatcher;
50994
51442
  var init_file_watcher = __esm({
50995
51443
  "src/triggers/file-watcher.ts"() {
50996
51444
  "use strict";
50997
- import_fs36 = require("fs");
50998
- import_path34 = require("path");
51445
+ import_fs37 = require("fs");
51446
+ import_path35 = require("path");
50999
51447
  init_source();
51000
51448
  init_triggers();
51001
51449
  DEFAULT_FILE_WATCHER_CONFIG = {
@@ -51051,13 +51499,13 @@ var init_file_watcher = __esm({
51051
51499
  const watching = [];
51052
51500
  const notFound = [];
51053
51501
  for (const watchPath of this.config.watchPaths) {
51054
- const fullPath = (0, import_path34.join)(basePath, watchPath);
51055
- if (!(0, import_fs36.existsSync)(fullPath)) {
51502
+ const fullPath = (0, import_path35.join)(basePath, watchPath);
51503
+ if (!(0, import_fs37.existsSync)(fullPath)) {
51056
51504
  notFound.push(watchPath);
51057
51505
  continue;
51058
51506
  }
51059
51507
  try {
51060
- const watcher = (0, import_fs36.watch)(
51508
+ const watcher = (0, import_fs37.watch)(
51061
51509
  fullPath,
51062
51510
  { recursive: this.config.recursive },
51063
51511
  (eventType, filename) => {
@@ -51104,7 +51552,7 @@ var init_file_watcher = __esm({
51104
51552
  * @returns True if the file matches any ignore pattern and should be skipped
51105
51553
  */
51106
51554
  shouldIgnore(filename) {
51107
- const name = (0, import_path34.basename)(filename);
51555
+ const name = (0, import_path35.basename)(filename);
51108
51556
  for (const pattern of this.config.ignorePatterns) {
51109
51557
  if (pattern.startsWith("*")) {
51110
51558
  if (name.endsWith(pattern.slice(1))) {
@@ -51130,7 +51578,7 @@ var init_file_watcher = __esm({
51130
51578
  * @param filename - The name of the file that changed
51131
51579
  */
51132
51580
  handleFileEvent(eventType, watchPath, filename) {
51133
- const fullPath = (0, import_path34.join)(watchPath, filename);
51581
+ const fullPath = (0, import_path35.join)(watchPath, filename);
51134
51582
  const debounceKey = `${eventType}:${fullPath}`;
51135
51583
  const existingTimer = this.debounceTimers.get(debounceKey);
51136
51584
  if (existingTimer) {
@@ -51150,13 +51598,13 @@ var init_file_watcher = __esm({
51150
51598
  * @param filename - The name of the file that changed
51151
51599
  */
51152
51600
  async processFileEvent(eventType, watchPath, filename) {
51153
- const fullPath = (0, import_path34.join)(watchPath, filename);
51601
+ const fullPath = (0, import_path35.join)(watchPath, filename);
51154
51602
  let fsEventType;
51155
51603
  let isDirectory = false;
51156
51604
  let size;
51157
51605
  try {
51158
- if ((0, import_fs36.existsSync)(fullPath)) {
51159
- const stats = (0, import_fs36.statSync)(fullPath);
51606
+ if ((0, import_fs37.existsSync)(fullPath)) {
51607
+ const stats = (0, import_fs37.statSync)(fullPath);
51160
51608
  isDirectory = stats.isDirectory();
51161
51609
  size = stats.size;
51162
51610
  fsEventType = eventType === "rename" ? "create" : "modify";
@@ -51301,12 +51749,12 @@ var init_file_watcher = __esm({
51301
51749
  this.config.watchPaths.push(path8);
51302
51750
  return true;
51303
51751
  }
51304
- const fullPath = (0, import_path34.join)(basePath, path8);
51305
- if (!(0, import_fs36.existsSync)(fullPath)) {
51752
+ const fullPath = (0, import_path35.join)(basePath, path8);
51753
+ if (!(0, import_fs37.existsSync)(fullPath)) {
51306
51754
  return false;
51307
51755
  }
51308
51756
  try {
51309
- const watcher = (0, import_fs36.watch)(
51757
+ const watcher = (0, import_fs37.watch)(
51310
51758
  fullPath,
51311
51759
  { recursive: this.config.recursive },
51312
51760
  (eventType, filename) => {
@@ -51619,9 +52067,9 @@ async function confirm(message) {
51619
52067
  });
51620
52068
  }
51621
52069
  function isGalCreatedFile(filePath) {
51622
- if (!(0, import_fs37.existsSync)(filePath)) return false;
52070
+ if (!(0, import_fs38.existsSync)(filePath)) return false;
51623
52071
  try {
51624
- const content = (0, import_fs37.readFileSync)(filePath, "utf-8");
52072
+ const content = (0, import_fs38.readFileSync)(filePath, "utf-8");
51625
52073
  const galMarkers = [
51626
52074
  "GAL Config",
51627
52075
  "GAL CLI",
@@ -51641,9 +52089,9 @@ function isGalCreatedFile(filePath) {
51641
52089
  }
51642
52090
  }
51643
52091
  function isNpmInstalledFile(filePath) {
51644
- if (!(0, import_fs37.existsSync)(filePath)) return false;
52092
+ if (!(0, import_fs38.existsSync)(filePath)) return false;
51645
52093
  try {
51646
- const content = (0, import_fs37.readFileSync)(filePath, "utf-8");
52094
+ const content = (0, import_fs38.readFileSync)(filePath, "utf-8");
51647
52095
  return content.includes("CURRENT_VERSION =") || content.includes("const CURRENT_VERSION");
51648
52096
  } catch {
51649
52097
  return false;
@@ -51660,15 +52108,15 @@ function detectFileSource(filePath) {
51660
52108
  }
51661
52109
  function detectUserLevelItems(options) {
51662
52110
  const items = [];
51663
- const claudeDir = (0, import_path35.join)((0, import_os21.homedir)(), ".claude");
51664
- const claudeHooksDir = (0, import_path35.join)(claudeDir, "hooks");
51665
- const statusLinesDir = (0, import_path35.join)(claudeDir, "status_lines");
52111
+ const claudeDir = (0, import_path36.join)((0, import_os22.homedir)(), ".claude");
52112
+ const claudeHooksDir = (0, import_path36.join)(claudeDir, "hooks");
52113
+ const statusLinesDir = (0, import_path36.join)(claudeDir, "status_lines");
51666
52114
  const includeNpm = options?.includeNpmInstalled ?? true;
51667
- if ((0, import_fs37.existsSync)(claudeHooksDir)) {
51668
- const files = (0, import_fs37.readdirSync)(claudeHooksDir);
52115
+ if ((0, import_fs38.existsSync)(claudeHooksDir)) {
52116
+ const files = (0, import_fs38.readdirSync)(claudeHooksDir);
51669
52117
  for (const file of files) {
51670
52118
  if (file.startsWith("gal-")) {
51671
- const filePath = (0, import_path35.join)(claudeHooksDir, file);
52119
+ const filePath = (0, import_path36.join)(claudeHooksDir, file);
51672
52120
  const source = detectFileSource(filePath);
51673
52121
  if (!includeNpm && source === "npm") {
51674
52122
  continue;
@@ -51683,11 +52131,11 @@ function detectUserLevelItems(options) {
51683
52131
  }
51684
52132
  }
51685
52133
  }
51686
- if ((0, import_fs37.existsSync)(statusLinesDir)) {
51687
- const files = (0, import_fs37.readdirSync)(statusLinesDir);
52134
+ if ((0, import_fs38.existsSync)(statusLinesDir)) {
52135
+ const files = (0, import_fs38.readdirSync)(statusLinesDir);
51688
52136
  for (const file of files) {
51689
52137
  if (file.startsWith("gal-")) {
51690
- const filePath = (0, import_path35.join)(statusLinesDir, file);
52138
+ const filePath = (0, import_path36.join)(statusLinesDir, file);
51691
52139
  const source = detectFileSource(filePath);
51692
52140
  if (!includeNpm && source === "npm") {
51693
52141
  continue;
@@ -51702,10 +52150,10 @@ function detectUserLevelItems(options) {
51702
52150
  }
51703
52151
  }
51704
52152
  }
51705
- const claudeSettingsPath = (0, import_path35.join)(claudeDir, "settings.json");
51706
- if ((0, import_fs37.existsSync)(claudeSettingsPath)) {
52153
+ const claudeSettingsPath = (0, import_path36.join)(claudeDir, "settings.json");
52154
+ if ((0, import_fs38.existsSync)(claudeSettingsPath)) {
51707
52155
  try {
51708
- const settings = JSON.parse((0, import_fs37.readFileSync)(claudeSettingsPath, "utf-8"));
52156
+ const settings = JSON.parse((0, import_fs38.readFileSync)(claudeSettingsPath, "utf-8"));
51709
52157
  if (settings.hooks?.SessionStart) {
51710
52158
  const hasGalHooks = settings.hooks.SessionStart.some(
51711
52159
  (entry) => entry.hooks?.some(
@@ -51752,14 +52200,14 @@ function detectUserLevelItems(options) {
51752
52200
  } catch {
51753
52201
  }
51754
52202
  }
51755
- const cursorDir = (0, import_path35.join)((0, import_os21.homedir)(), ".cursor");
51756
- const cursorHooksDir = (0, import_path35.join)(cursorDir, "hooks");
51757
- if ((0, import_fs37.existsSync)(cursorHooksDir)) {
51758
- const files = (0, import_fs37.readdirSync)(cursorHooksDir);
52203
+ const cursorDir = (0, import_path36.join)((0, import_os22.homedir)(), ".cursor");
52204
+ const cursorHooksDir = (0, import_path36.join)(cursorDir, "hooks");
52205
+ if ((0, import_fs38.existsSync)(cursorHooksDir)) {
52206
+ const files = (0, import_fs38.readdirSync)(cursorHooksDir);
51759
52207
  for (const file of files) {
51760
52208
  if (file.startsWith("gal-")) {
51761
52209
  items.push({
51762
- path: (0, import_path35.join)(cursorHooksDir, file),
52210
+ path: (0, import_path36.join)(cursorHooksDir, file),
51763
52211
  type: "file",
51764
52212
  reason: "GAL hook file for Cursor IDE",
51765
52213
  isGalOwned: true
@@ -51767,10 +52215,10 @@ function detectUserLevelItems(options) {
51767
52215
  }
51768
52216
  }
51769
52217
  }
51770
- const cursorHooksJsonPath = (0, import_path35.join)(cursorDir, "hooks.json");
51771
- if ((0, import_fs37.existsSync)(cursorHooksJsonPath)) {
52218
+ const cursorHooksJsonPath = (0, import_path36.join)(cursorDir, "hooks.json");
52219
+ if ((0, import_fs38.existsSync)(cursorHooksJsonPath)) {
51772
52220
  try {
51773
- const hooksConfig = JSON.parse((0, import_fs37.readFileSync)(cursorHooksJsonPath, "utf-8"));
52221
+ const hooksConfig = JSON.parse((0, import_fs38.readFileSync)(cursorHooksJsonPath, "utf-8"));
51774
52222
  const hookTypes = ["beforeShellExecution", "beforeSubmitPrompt"];
51775
52223
  for (const hookType of hookTypes) {
51776
52224
  if (hooksConfig.hooks?.[hookType]) {
@@ -51796,8 +52244,8 @@ function detectUserLevelItems(options) {
51796
52244
  }
51797
52245
  function detectProjectLevelItems(directory) {
51798
52246
  const items = [];
51799
- const galDir = (0, import_path35.join)(directory, ".gal");
51800
- if ((0, import_fs37.existsSync)(galDir)) {
52247
+ const galDir = (0, import_path36.join)(directory, ".gal");
52248
+ if ((0, import_fs38.existsSync)(galDir)) {
51801
52249
  items.push({
51802
52250
  path: galDir,
51803
52251
  type: "directory",
@@ -51805,8 +52253,8 @@ function detectProjectLevelItems(directory) {
51805
52253
  isGalOwned: true
51806
52254
  });
51807
52255
  }
51808
- const galConfig = (0, import_path35.join)(directory, "gal.config.json");
51809
- if ((0, import_fs37.existsSync)(galConfig)) {
52256
+ const galConfig = (0, import_path36.join)(directory, "gal.config.json");
52257
+ if ((0, import_fs38.existsSync)(galConfig)) {
51810
52258
  items.push({
51811
52259
  path: galConfig,
51812
52260
  type: "file",
@@ -51815,11 +52263,11 @@ function detectProjectLevelItems(directory) {
51815
52263
  });
51816
52264
  }
51817
52265
  const gitHookPaths = [
51818
- (0, import_path35.join)(directory, ".git", "hooks", "pre-commit"),
51819
- (0, import_path35.join)(directory, ".husky", "pre-commit")
52266
+ (0, import_path36.join)(directory, ".git", "hooks", "pre-commit"),
52267
+ (0, import_path36.join)(directory, ".husky", "pre-commit")
51820
52268
  ];
51821
52269
  for (const hookPath of gitHookPaths) {
51822
- if ((0, import_fs37.existsSync)(hookPath) && isGalCreatedFile(hookPath)) {
52270
+ if ((0, import_fs38.existsSync)(hookPath) && isGalCreatedFile(hookPath)) {
51823
52271
  items.push({
51824
52272
  path: hookPath,
51825
52273
  type: "file",
@@ -51829,18 +52277,18 @@ function detectProjectLevelItems(directory) {
51829
52277
  }
51830
52278
  }
51831
52279
  const setupFiles = [
51832
- { path: (0, import_path35.join)(directory, "CLAUDE.md"), reason: "GAL-generated CLAUDE.md" },
51833
- { path: (0, import_path35.join)(directory, ".claude", "settings.json"), reason: "GAL-generated settings" },
51834
- { path: (0, import_path35.join)(directory, ".claude", "commands", "review.md"), reason: "GAL-generated command" },
51835
- { path: (0, import_path35.join)(directory, ".claude", "commands", "check.md"), reason: "GAL-generated command" },
51836
- { path: (0, import_path35.join)(directory, ".github", "workflows", "ci.yml"), reason: "GAL-generated workflow" },
51837
- { path: (0, import_path35.join)(directory, ".github", "workflows", "pr-governance.yml"), reason: "GAL-generated workflow" },
51838
- { path: (0, import_path35.join)(directory, ".gitleaks.toml"), reason: "GAL-generated security config" },
51839
- { path: (0, import_path35.join)(directory, "SECURITY.md"), reason: "GAL-generated security docs" },
51840
- { path: (0, import_path35.join)(directory, ".env.example"), reason: "GAL-generated env template" }
52280
+ { path: (0, import_path36.join)(directory, "CLAUDE.md"), reason: "GAL-generated CLAUDE.md" },
52281
+ { path: (0, import_path36.join)(directory, ".claude", "settings.json"), reason: "GAL-generated settings" },
52282
+ { path: (0, import_path36.join)(directory, ".claude", "commands", "review.md"), reason: "GAL-generated command" },
52283
+ { path: (0, import_path36.join)(directory, ".claude", "commands", "check.md"), reason: "GAL-generated command" },
52284
+ { path: (0, import_path36.join)(directory, ".github", "workflows", "ci.yml"), reason: "GAL-generated workflow" },
52285
+ { path: (0, import_path36.join)(directory, ".github", "workflows", "pr-governance.yml"), reason: "GAL-generated workflow" },
52286
+ { path: (0, import_path36.join)(directory, ".gitleaks.toml"), reason: "GAL-generated security config" },
52287
+ { path: (0, import_path36.join)(directory, "SECURITY.md"), reason: "GAL-generated security docs" },
52288
+ { path: (0, import_path36.join)(directory, ".env.example"), reason: "GAL-generated env template" }
51841
52289
  ];
51842
52290
  for (const { path: path8, reason } of setupFiles) {
51843
- if ((0, import_fs37.existsSync)(path8) && isGalCreatedFile(path8)) {
52291
+ if ((0, import_fs38.existsSync)(path8) && isGalCreatedFile(path8)) {
51844
52292
  items.push({
51845
52293
  path: path8,
51846
52294
  type: "file",
@@ -51853,12 +52301,12 @@ function detectProjectLevelItems(directory) {
51853
52301
  }
51854
52302
  function removeGalStatusLineEntry(settingsPath) {
51855
52303
  try {
51856
- const settings = JSON.parse((0, import_fs37.readFileSync)(settingsPath, "utf-8"));
52304
+ const settings = JSON.parse((0, import_fs38.readFileSync)(settingsPath, "utf-8"));
51857
52305
  if (!settings.statusLine?.command?.includes("gal-")) {
51858
52306
  return false;
51859
52307
  }
51860
52308
  delete settings.statusLine;
51861
- (0, import_fs37.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
52309
+ (0, import_fs38.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
51862
52310
  return true;
51863
52311
  } catch {
51864
52312
  return false;
@@ -51866,7 +52314,7 @@ function removeGalStatusLineEntry(settingsPath) {
51866
52314
  }
51867
52315
  function removeGalHookEntries(settingsPath) {
51868
52316
  try {
51869
- const settings = JSON.parse((0, import_fs37.readFileSync)(settingsPath, "utf-8"));
52317
+ const settings = JSON.parse((0, import_fs38.readFileSync)(settingsPath, "utf-8"));
51870
52318
  let modified = false;
51871
52319
  for (const hookEvent of ["SessionStart", "UserPromptSubmit"]) {
51872
52320
  if (!settings.hooks?.[hookEvent]) continue;
@@ -51889,7 +52337,7 @@ function removeGalHookEntries(settingsPath) {
51889
52337
  delete settings.hooks;
51890
52338
  }
51891
52339
  if (modified) {
51892
- (0, import_fs37.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
52340
+ (0, import_fs38.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
51893
52341
  return true;
51894
52342
  }
51895
52343
  return false;
@@ -51899,7 +52347,7 @@ function removeGalHookEntries(settingsPath) {
51899
52347
  }
51900
52348
  function removeGalCursorHookEntries(hooksJsonPath) {
51901
52349
  try {
51902
- const hooksConfig = JSON.parse((0, import_fs37.readFileSync)(hooksJsonPath, "utf-8"));
52350
+ const hooksConfig = JSON.parse((0, import_fs38.readFileSync)(hooksJsonPath, "utf-8"));
51903
52351
  if (!hooksConfig.hooks) {
51904
52352
  return false;
51905
52353
  }
@@ -51923,7 +52371,7 @@ function removeGalCursorHookEntries(hooksJsonPath) {
51923
52371
  delete hooksConfig.hooks;
51924
52372
  }
51925
52373
  if (modified) {
51926
- (0, import_fs37.writeFileSync)(hooksJsonPath, JSON.stringify(hooksConfig, null, 2));
52374
+ (0, import_fs38.writeFileSync)(hooksJsonPath, JSON.stringify(hooksConfig, null, 2));
51927
52375
  return true;
51928
52376
  }
51929
52377
  return false;
@@ -51958,10 +52406,10 @@ function performUninstall(items, dryRun) {
51958
52406
  result.skipped.push(`${item.path} (no GAL statusLine found)`);
51959
52407
  }
51960
52408
  } else if (item.type === "directory") {
51961
- (0, import_fs37.rmSync)(item.path, { recursive: true, force: true });
52409
+ (0, import_fs38.rmSync)(item.path, { recursive: true, force: true });
51962
52410
  result.removed.push(item.path);
51963
52411
  } else {
51964
- (0, import_fs37.unlinkSync)(item.path);
52412
+ (0, import_fs38.unlinkSync)(item.path);
51965
52413
  result.removed.push(item.path);
51966
52414
  }
51967
52415
  } catch (error2) {
@@ -52057,15 +52505,15 @@ function createUninstallCommand() {
52057
52505
  });
52058
52506
  return command;
52059
52507
  }
52060
- var import_fs37, import_path35, import_os21, import_readline4;
52508
+ var import_fs38, import_path36, import_os22, import_readline4;
52061
52509
  var init_uninstall = __esm({
52062
52510
  "src/commands/uninstall.ts"() {
52063
52511
  "use strict";
52064
52512
  init_esm();
52065
52513
  init_source();
52066
- import_fs37 = require("fs");
52067
- import_path35 = require("path");
52068
- import_os21 = require("os");
52514
+ import_fs38 = require("fs");
52515
+ import_path36 = require("path");
52516
+ import_os22 = require("os");
52069
52517
  import_readline4 = require("readline");
52070
52518
  }
52071
52519
  });
@@ -52113,10 +52561,10 @@ ${source_default.cyan("/" + command.id)}`);
52113
52561
  new Command("install").description("Install universal commands to detected platforms").argument("[command-id]", "Command to install").option("--all", "Install all commands").option("-p, --path <path>", "Project path", process.cwd()).option("--platforms <platforms...>", "Specific platforms to install to").option("--force", "Overwrite existing commands").action(async (commandId, options) => {
52114
52562
  const spinner = ora("Installing universal commands...").start();
52115
52563
  try {
52116
- const projectPath = options.path;
52564
+ const projectPath2 = options.path;
52117
52565
  const platforms = options.platforms ? SUPPORTED_PLATFORMS.filter(
52118
52566
  (p) => options.platforms.includes(p.id)
52119
- ) : detectPlatforms2(projectPath).filter((p) => p.detected);
52567
+ ) : detectPlatforms2(projectPath2).filter((p) => p.detected);
52120
52568
  if (platforms.length === 0) {
52121
52569
  spinner.fail(source_default.yellow("No platforms detected"));
52122
52570
  console.log(
@@ -52134,7 +52582,7 @@ ${source_default.cyan("/" + command.id)}`);
52134
52582
  for (const command of commands) {
52135
52583
  if (!command.platforms.includes(platform5.id)) continue;
52136
52584
  const commandPath = path6.join(
52137
- projectPath,
52585
+ projectPath2,
52138
52586
  platform5.commandsPath,
52139
52587
  `${command.id}.md`
52140
52588
  );
@@ -52168,8 +52616,8 @@ ${source_default.cyan("/" + command.id)}`);
52168
52616
  new Command("sync").description("Sync commands across all detected platforms").option("-p, --path <path>", "Project path", process.cwd()).option("--dry-run", "Preview what would be synced without making changes").action(async (options) => {
52169
52617
  const spinner = ora("Syncing commands...").start();
52170
52618
  try {
52171
- const projectPath = options.path;
52172
- const platforms = detectPlatforms2(projectPath).filter(
52619
+ const projectPath2 = options.path;
52620
+ const platforms = detectPlatforms2(projectPath2).filter(
52173
52621
  (p) => p.detected
52174
52622
  );
52175
52623
  if (platforms.length < 2) {
@@ -52180,7 +52628,7 @@ ${source_default.cyan("/" + command.id)}`);
52180
52628
  }
52181
52629
  const sourcePlatform = platforms[0];
52182
52630
  const sourceDir = path6.join(
52183
- projectPath,
52631
+ projectPath2,
52184
52632
  sourcePlatform.commandsPath
52185
52633
  );
52186
52634
  if (!fs6.existsSync(sourceDir)) {
@@ -52191,7 +52639,7 @@ ${source_default.cyan("/" + command.id)}`);
52191
52639
  let synced = 0;
52192
52640
  const wouldSync = [];
52193
52641
  for (const platform5 of platforms.slice(1)) {
52194
- const targetDir = path6.join(projectPath, platform5.commandsPath);
52642
+ const targetDir = path6.join(projectPath2, platform5.commandsPath);
52195
52643
  if (!options.dryRun) {
52196
52644
  fs6.mkdirSync(targetDir, { recursive: true });
52197
52645
  }
@@ -52277,10 +52725,10 @@ Describe what the AI should do when this command is invoked.
52277
52725
  );
52278
52726
  return cmd;
52279
52727
  }
52280
- function detectPlatforms2(projectPath) {
52728
+ function detectPlatforms2(projectPath2) {
52281
52729
  return SUPPORTED_PLATFORMS.map((platform5) => ({
52282
52730
  ...platform5,
52283
- detected: fs6.existsSync(path6.join(projectPath, platform5.configPath)) || fs6.existsSync(path6.join(projectPath, platform5.commandsPath))
52731
+ detected: fs6.existsSync(path6.join(projectPath2, platform5.configPath)) || fs6.existsSync(path6.join(projectPath2, platform5.commandsPath))
52284
52732
  }));
52285
52733
  }
52286
52734
  var fs6, path6, SUPPORTED_PLATFORMS, UNIVERSAL_COMMANDS;
@@ -52483,27 +52931,27 @@ function compareVersions(v1, v2) {
52483
52931
  }
52484
52932
  function acquireLock() {
52485
52933
  try {
52486
- const galDir = (0, import_path36.join)((0, import_os22.homedir)(), ".gal");
52487
- if (!(0, import_fs38.existsSync)(galDir)) {
52488
- (0, import_fs38.mkdirSync)(galDir, { recursive: true });
52934
+ const galDir = (0, import_path37.join)((0, import_os23.homedir)(), ".gal");
52935
+ if (!(0, import_fs39.existsSync)(galDir)) {
52936
+ (0, import_fs39.mkdirSync)(galDir, { recursive: true });
52489
52937
  }
52490
- if ((0, import_fs38.existsSync)(UPDATE_LOCK_FILE)) {
52938
+ if ((0, import_fs39.existsSync)(UPDATE_LOCK_FILE)) {
52491
52939
  try {
52492
- const lockContent = (0, import_fs38.readFileSync)(UPDATE_LOCK_FILE, "utf-8");
52940
+ const lockContent = (0, import_fs39.readFileSync)(UPDATE_LOCK_FILE, "utf-8");
52493
52941
  const lockTime = parseInt(lockContent, 10);
52494
52942
  if (Number.isNaN(lockTime) || Date.now() - lockTime > 5 * 60 * 1e3) {
52495
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52943
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52496
52944
  } else {
52497
52945
  return false;
52498
52946
  }
52499
52947
  } catch {
52500
52948
  try {
52501
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52949
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52502
52950
  } catch {
52503
52951
  }
52504
52952
  }
52505
52953
  }
52506
- (0, import_fs38.writeFileSync)(UPDATE_LOCK_FILE, String(Date.now()), { flag: "wx" });
52954
+ (0, import_fs39.writeFileSync)(UPDATE_LOCK_FILE, String(Date.now()), { flag: "wx" });
52507
52955
  return true;
52508
52956
  } catch {
52509
52957
  return false;
@@ -52511,8 +52959,8 @@ function acquireLock() {
52511
52959
  }
52512
52960
  function releaseLock() {
52513
52961
  try {
52514
- if ((0, import_fs38.existsSync)(UPDATE_LOCK_FILE)) {
52515
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52962
+ if ((0, import_fs39.existsSync)(UPDATE_LOCK_FILE)) {
52963
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52516
52964
  }
52517
52965
  } catch {
52518
52966
  }
@@ -52623,7 +53071,7 @@ Retry manually with: ${source_default.cyan(installCommand)}`);
52623
53071
  });
52624
53072
  return command;
52625
53073
  }
52626
- var import_https, import_child_process12, import_fs38, import_path36, import_os22, UPDATE_LOCK_FILE, cliVersion7, REGISTRY_URL;
53074
+ var import_https, import_child_process12, import_fs39, import_path37, import_os23, UPDATE_LOCK_FILE, cliVersion7, REGISTRY_URL;
52627
53075
  var init_update = __esm({
52628
53076
  "src/commands/update.ts"() {
52629
53077
  "use strict";
@@ -52632,14 +53080,14 @@ var init_update = __esm({
52632
53080
  init_ora();
52633
53081
  import_https = __toESM(require("https"), 1);
52634
53082
  import_child_process12 = require("child_process");
52635
- import_fs38 = require("fs");
52636
- import_path36 = require("path");
52637
- import_os22 = require("os");
53083
+ import_fs39 = require("fs");
53084
+ import_path37 = require("path");
53085
+ import_os23 = require("os");
52638
53086
  init_constants();
52639
53087
  init_path_conflict();
52640
53088
  init_install();
52641
53089
  init_telemetry();
52642
- UPDATE_LOCK_FILE = (0, import_path36.join)((0, import_os22.homedir)(), ".gal", "update.lock");
53090
+ UPDATE_LOCK_FILE = (0, import_path37.join)((0, import_os23.homedir)(), ".gal", "update.lock");
52643
53091
  cliVersion7 = constants_default[0];
52644
53092
  REGISTRY_URL = getRegistryUrl();
52645
53093
  }
@@ -53147,9 +53595,9 @@ function createWorkflowCommand() {
53147
53595
  const apiUrl = process.env.GAL_API_URL || defaultApiUrl17;
53148
53596
  try {
53149
53597
  const spinner = ora(`Reading ${filePath}...`).start();
53150
- const absolutePath = import_path37.default.resolve(filePath);
53598
+ const absolutePath = import_path38.default.resolve(filePath);
53151
53599
  const content = await import_promises9.default.readFile(absolutePath, "utf-8");
53152
- const fileName = import_path37.default.basename(filePath);
53600
+ const fileName = import_path38.default.basename(filePath);
53153
53601
  let type = options.type;
53154
53602
  if (!type) {
53155
53603
  if (fileName.endsWith(".md")) {
@@ -53205,7 +53653,7 @@ function createWorkflowCommand() {
53205
53653
  spinner.fail(source_default.red("No organization found. Please connect GitHub via dashboard or use --org flag"));
53206
53654
  process.exit(1);
53207
53655
  }
53208
- const dirPath = import_path37.default.resolve(directory);
53656
+ const dirPath = import_path38.default.resolve(directory);
53209
53657
  const files = await import_promises9.default.readdir(dirPath);
53210
53658
  const workflowFiles = files.filter(
53211
53659
  (f) => f.endsWith(".md") || f.includes("hook") && (f.endsWith(".json") || f.endsWith(".py") || f.endsWith(".js"))
@@ -53217,7 +53665,7 @@ function createWorkflowCommand() {
53217
53665
  spinner.text = `Found ${workflowFiles.length} workflow files. Preparing batch test...`;
53218
53666
  const requests = [];
53219
53667
  for (const file of workflowFiles) {
53220
- const filePath = import_path37.default.join(dirPath, file);
53668
+ const filePath = import_path38.default.join(dirPath, file);
53221
53669
  const content = await import_promises9.default.readFile(filePath, "utf-8");
53222
53670
  const type = file.endsWith(".md") ? "command" : "hook";
53223
53671
  requests.push({
@@ -53315,7 +53763,7 @@ function displayTestResult(result) {
53315
53763
  }
53316
53764
  console.log();
53317
53765
  }
53318
- var import_promises9, import_path37, defaultApiUrl17;
53766
+ var import_promises9, import_path38, defaultApiUrl17;
53319
53767
  var init_workflow2 = __esm({
53320
53768
  "src/commands/workflow.ts"() {
53321
53769
  "use strict";
@@ -53323,7 +53771,7 @@ var init_workflow2 = __esm({
53323
53771
  init_source();
53324
53772
  init_ora();
53325
53773
  import_promises9 = __toESM(require("fs/promises"), 1);
53326
- import_path37 = __toESM(require("path"), 1);
53774
+ import_path38 = __toESM(require("path"), 1);
53327
53775
  init_constants();
53328
53776
  init_client();
53329
53777
  defaultApiUrl17 = constants_default[1];
@@ -53548,6 +53996,7 @@ var init_command_registry = __esm({
53548
53996
  init_quality();
53549
53997
  init_queue_seed();
53550
53998
  init_run();
53999
+ init_run_design();
53551
54000
  init_scan();
53552
54001
  init_sandbox_profiles();
53553
54002
  init_sandbox();
@@ -53596,6 +54045,7 @@ var init_command_registry = __esm({
53596
54045
  { name: "quality", create: createQualityCommand },
53597
54046
  { name: "queue", create: createQueueCommand },
53598
54047
  { name: "run", create: createRunCommand },
54048
+ { name: "run-design", create: createRunDesignCommand },
53599
54049
  { name: "scan", create: createScanCommand },
53600
54050
  { name: "sandbox", create: createSandboxCommand },
53601
54051
  { name: "sandbox-profiles", create: createSandboxProfilesCommand },
@@ -53647,11 +54097,11 @@ function getRegistryAuthToken2() {
53647
54097
  return void 0;
53648
54098
  }
53649
54099
  try {
53650
- const npmrcPath = (0, import_path38.join)((0, import_os23.homedir)(), ".npmrc");
53651
- if (!(0, import_fs39.existsSync)(npmrcPath)) {
54100
+ const npmrcPath = (0, import_path39.join)((0, import_os24.homedir)(), ".npmrc");
54101
+ if (!(0, import_fs40.existsSync)(npmrcPath)) {
53652
54102
  return void 0;
53653
54103
  }
53654
- const npmrc = (0, import_fs39.readFileSync)(npmrcPath, "utf-8");
54104
+ const npmrc = (0, import_fs40.readFileSync)(npmrcPath, "utf-8");
53655
54105
  const escapedHost = REGISTRY_HOST.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53656
54106
  const match = npmrc.match(
53657
54107
  new RegExp(`^//${escapedHost}/:_authToken=(.+)$`, "m")
@@ -53680,8 +54130,8 @@ function compareVersions2(v1, v2) {
53680
54130
  }
53681
54131
  function readUpdateCache() {
53682
54132
  try {
53683
- if ((0, import_fs39.existsSync)(UPDATE_CACHE_FILE)) {
53684
- return JSON.parse((0, import_fs39.readFileSync)(UPDATE_CACHE_FILE, "utf-8"));
54133
+ if ((0, import_fs40.existsSync)(UPDATE_CACHE_FILE)) {
54134
+ return JSON.parse((0, import_fs40.readFileSync)(UPDATE_CACHE_FILE, "utf-8"));
53685
54135
  }
53686
54136
  } catch {
53687
54137
  }
@@ -53689,10 +54139,10 @@ function readUpdateCache() {
53689
54139
  }
53690
54140
  function writeUpdateCache(cache) {
53691
54141
  try {
53692
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53693
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54142
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54143
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53694
54144
  }
53695
- (0, import_fs39.writeFileSync)(UPDATE_CACHE_FILE, JSON.stringify(cache));
54145
+ (0, import_fs40.writeFileSync)(UPDATE_CACHE_FILE, JSON.stringify(cache));
53696
54146
  } catch {
53697
54147
  }
53698
54148
  }
@@ -53742,8 +54192,8 @@ function checkForUpdates() {
53742
54192
  const autoUpdateDisabled = process.env.GAL_NO_AUTO_UPDATE === "1" || process.env.CI === "true";
53743
54193
  if (!isUpdateCommand && !autoUpdateDisabled) {
53744
54194
  try {
53745
- const lockFile = (0, import_path38.join)((0, import_os23.homedir)(), ".gal", "update.lock");
53746
- if (!(0, import_fs39.existsSync)(lockFile)) {
54195
+ const lockFile = (0, import_path39.join)((0, import_os24.homedir)(), ".gal", "update.lock");
54196
+ if (!(0, import_fs40.existsSync)(lockFile)) {
53747
54197
  const child = (0, import_child_process13.spawn)("gal", ["update"], {
53748
54198
  detached: true,
53749
54199
  stdio: "ignore",
@@ -53792,9 +54242,9 @@ function checkForUpdates() {
53792
54242
  function checkPathConflicts() {
53793
54243
  try {
53794
54244
  if (process.env.CI === "true" || process.argv.includes("--json")) return;
53795
- const CONFLICT_CACHE = (0, import_path38.join)(UPDATE_CACHE_DIR, "path-conflict-cache.json");
53796
- if ((0, import_fs39.existsSync)(CONFLICT_CACHE)) {
53797
- const cached = JSON.parse((0, import_fs39.readFileSync)(CONFLICT_CACHE, "utf-8"));
54245
+ const CONFLICT_CACHE = (0, import_path39.join)(UPDATE_CACHE_DIR, "path-conflict-cache.json");
54246
+ if ((0, import_fs40.existsSync)(CONFLICT_CACHE)) {
54247
+ const cached = JSON.parse((0, import_fs40.readFileSync)(CONFLICT_CACHE, "utf-8"));
53798
54248
  if (Date.now() - (cached.lastCheck || 0) < ONE_DAY) {
53799
54249
  if (cached.hasConflict) {
53800
54250
  process.on("exit", () => {
@@ -53808,10 +54258,10 @@ function checkPathConflicts() {
53808
54258
  const conflict = detectPathConflict(cliVersion9);
53809
54259
  const cacheData = { lastCheck: Date.now(), hasConflict: !!conflict };
53810
54260
  try {
53811
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53812
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54261
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54262
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53813
54263
  }
53814
- (0, import_fs39.writeFileSync)(CONFLICT_CACHE, JSON.stringify(cacheData));
54264
+ (0, import_fs40.writeFileSync)(CONFLICT_CACHE, JSON.stringify(cacheData));
53815
54265
  } catch {
53816
54266
  }
53817
54267
  if (conflict) {
@@ -53824,9 +54274,9 @@ function checkPathConflicts() {
53824
54274
  }
53825
54275
  function refreshOrgMemberships() {
53826
54276
  try {
53827
- const configPath = (0, import_path38.join)((0, import_os23.homedir)(), ".gal", "config.json");
53828
- if (!(0, import_fs39.existsSync)(configPath)) return;
53829
- const config = JSON.parse((0, import_fs39.readFileSync)(configPath, "utf-8"));
54277
+ const configPath = (0, import_path39.join)((0, import_os24.homedir)(), ".gal", "config.json");
54278
+ if (!(0, import_fs40.existsSync)(configPath)) return;
54279
+ const config = JSON.parse((0, import_fs40.readFileSync)(configPath, "utf-8"));
53830
54280
  if (!config.authToken) return;
53831
54281
  const checkedAt = config.orgMembershipsCheckedAt || 0;
53832
54282
  if (Date.now() - checkedAt < ONE_DAY) return;
@@ -53854,10 +54304,10 @@ function refreshOrgMemberships() {
53854
54304
  const isInternal = user.isInternal === true;
53855
54305
  config.internalOrgs = isInternal ? user.organizations : [];
53856
54306
  config.internalOrgsCheckedAt = Date.now();
53857
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53858
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54307
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54308
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53859
54309
  }
53860
- (0, import_fs39.writeFileSync)(configPath, JSON.stringify(config, null, 2));
54310
+ (0, import_fs40.writeFileSync)(configPath, JSON.stringify(config, null, 2));
53861
54311
  }
53862
54312
  } catch {
53863
54313
  }
@@ -53884,11 +54334,11 @@ function refreshOrgMemberships() {
53884
54334
  if (res.statusCode !== 200) return;
53885
54335
  const flags = JSON.parse(data);
53886
54336
  if (flags.orgAudienceTierMap) {
53887
- const freshConfig = JSON.parse((0, import_fs39.readFileSync)(configPath, "utf-8"));
54337
+ const freshConfig = JSON.parse((0, import_fs40.readFileSync)(configPath, "utf-8"));
53888
54338
  freshConfig.orgAudienceTierMap = flags.orgAudienceTierMap;
53889
54339
  freshConfig.orgPlanMap = flags.orgPlanMap || freshConfig.orgPlanMap || {};
53890
54340
  freshConfig.flagsCachedAt = Date.now();
53891
- (0, import_fs39.writeFileSync)(configPath, JSON.stringify(freshConfig, null, 2));
54341
+ (0, import_fs40.writeFileSync)(configPath, JSON.stringify(freshConfig, null, 2));
53892
54342
  }
53893
54343
  } catch {
53894
54344
  }
@@ -53907,7 +54357,7 @@ function refreshOrgMemberships() {
53907
54357
  } catch {
53908
54358
  }
53909
54359
  }
53910
- var import_dotenv, import_https2, import_child_process13, import_fs39, import_path38, import_os23, originalEmit, GLOBAL_TIMEOUT_MS, globalTimeout, cliVersion9, UPDATE_CACHE_DIR, UPDATE_CACHE_FILE, ONE_DAY, ONE_HOUR, REGISTRY_URL2, REGISTRY_HOST, sessionStartTime, isReadOnlyStatusCommand, isMachineMode, featureFlags, knownCommands, isKnownCommand, program2, allInternalFlags;
54360
+ var import_dotenv, import_https2, import_child_process13, import_fs40, import_path39, import_os24, originalEmit, GLOBAL_TIMEOUT_MS, globalTimeout, cliVersion9, UPDATE_CACHE_DIR, UPDATE_CACHE_FILE, ONE_DAY, ONE_HOUR, REGISTRY_URL2, REGISTRY_HOST, sessionStartTime, isReadOnlyStatusCommand, isMachineMode, featureFlags, knownCommands, isKnownCommand, program2, allInternalFlags;
53911
54361
  var init_index = __esm({
53912
54362
  "src/index.ts"() {
53913
54363
  "use strict";
@@ -53915,9 +54365,9 @@ var init_index = __esm({
53915
54365
  import_dotenv = __toESM(require_main(), 1);
53916
54366
  import_https2 = __toESM(require("https"), 1);
53917
54367
  import_child_process13 = require("child_process");
53918
- import_fs39 = require("fs");
53919
- import_path38 = require("path");
53920
- import_os23 = require("os");
54368
+ import_fs40 = require("fs");
54369
+ import_path39 = require("path");
54370
+ import_os24 = require("os");
53921
54371
  init_source();
53922
54372
  init_constants();
53923
54373
  init_sentry2();
@@ -53946,8 +54396,8 @@ var init_index = __esm({
53946
54396
  }, GLOBAL_TIMEOUT_MS);
53947
54397
  globalTimeout.unref();
53948
54398
  cliVersion9 = constants_default[0];
53949
- UPDATE_CACHE_DIR = (0, import_path38.join)((0, import_os23.homedir)(), ".gal");
53950
- UPDATE_CACHE_FILE = (0, import_path38.join)(UPDATE_CACHE_DIR, "update-cache.json");
54399
+ UPDATE_CACHE_DIR = (0, import_path39.join)((0, import_os24.homedir)(), ".gal");
54400
+ UPDATE_CACHE_FILE = (0, import_path39.join)(UPDATE_CACHE_DIR, "update-cache.json");
53951
54401
  ONE_DAY = 24 * 60 * 60 * 1e3;
53952
54402
  ONE_HOUR = 60 * 60 * 1e3;
53953
54403
  REGISTRY_URL2 = (() => {
@@ -54090,18 +54540,28 @@ var init_index = __esm({
54090
54540
  });
54091
54541
 
54092
54542
  // src/bootstrap.ts
54093
- var cliVersion10 = true ? "0.0.281" : "0.0.0-dev";
54543
+ var cliVersion10 = true ? "0.0.283" : "0.0.0-dev";
54094
54544
  var args = process.argv.slice(2);
54095
54545
  var requestedGlobalHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
54096
54546
  var requestedVersion = args.length === 1 && (args[0] === "--version" || args[0] === "-V");
54097
54547
  var globalHelpCommands = [
54548
+ " approve [options] Upload local configs to org approved config",
54549
+ " approved-config View and manage the org-approved AI agent configuration",
54098
54550
  " auth Manage GitHub authentication",
54551
+ " discover [orgName] Discover AI agent configurations across your organization repositories",
54099
54552
  " feedback [options] Send feedback about GAL",
54100
- " hooks Manage Claude Code hooks for auto-sync",
54553
+ " fetch [orgName] Fetch agent configurations from GAL API and write to local directory",
54554
+ " hooks Manage AI agent hooks for auto-sync",
54555
+ " join [options] Join an organization using an invite code",
54101
54556
  " mcp Set up and validate GAL hosted MCP connectivity",
54557
+ " memory Manage cross-provider AI agent memory/learnings (no auth required)",
54558
+ " policy Manage org-wide AI agent policies (enterprise)",
54559
+ " propose [description] Propose changes to your organization config",
54560
+ " scan [options] Scan local directory for AI agent configurations (no auth required)",
54102
54561
  " status [options] Check sync status, drift, and pending proposals",
54103
54562
  " sync [options] [orgName] Sync local configs with CISO-approved organization standard",
54104
- " update [options] Check for and apply CLI updates"
54563
+ " update [options] Check for and apply CLI updates",
54564
+ " workspace Manage workspaces (GitHub organizations and personal accounts)"
54105
54565
  ];
54106
54566
  if (process.env.GAL_INTERNAL === "true") {
54107
54567
  globalHelpCommands.splice(