@scheduler-systems/gal-run 0.0.280 → 0.0.282

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 +833 -375
  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.280" : "0.0.0-dev";
3973
+ cliVersion = true ? "0.0.282" : "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.280" : void 0;
4815
+ const version = true ? "0.0.282" : 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.280" : "0.0.0-dev";
5184
+ return true ? "0.0.282" : "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;
@@ -34708,60 +34760,90 @@ async function validateAfterSync(config, provider) {
34708
34760
  }
34709
34761
  }
34710
34762
  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."
34763
+ let hookResult;
34764
+ try {
34765
+ hookResult = installHooks();
34766
+ } catch {
34767
+ hookResult = { hookInstalled: false, rulesInstalled: false, errors: ["Hook installation failed unexpectedly"], results: [] };
34768
+ }
34769
+ let syncResult;
34770
+ try {
34771
+ syncResult = config.authToken ? await syncApprovedConfigAfterLogin({
34772
+ apiUrl: config.apiUrl || defaultApiUrl5,
34773
+ authToken: config.authToken,
34774
+ orgName: config.defaultOrg
34775
+ }) : {
34776
+ status: "skipped",
34777
+ directory: process.cwd(),
34778
+ filesWritten: 0,
34779
+ platforms: [],
34780
+ message: "Authentication token missing; skipped initial sync."
34781
+ };
34782
+ } catch {
34783
+ syncResult = {
34784
+ status: "failed",
34785
+ directory: process.cwd(),
34786
+ filesWritten: 0,
34787
+ platforms: [],
34788
+ message: "Sync failed unexpectedly during post-login setup."
34789
+ };
34790
+ }
34791
+ const TOOL_DISPLAY_NAMES = {
34792
+ claude: "Claude Code",
34793
+ cursor: "Cursor",
34794
+ windsurf: "Windsurf",
34795
+ gemini: "Gemini CLI",
34796
+ codex: "Codex CLI",
34797
+ amp: "Amp",
34798
+ antigravity: "Antigravity"
34722
34799
  };
34800
+ const toolIds = ["claude", "cursor", "windsurf", "gemini", "codex", "amp", "antigravity"];
34801
+ const configuredStatuses = /* @__PURE__ */ new Set(["installed", "updated", "up_to_date"]);
34802
+ const detectedTools = [];
34803
+ for (const id of toolIds) {
34804
+ if (isAgentInstalled(id)) {
34805
+ const hookForTool = hookResult.results.find((r) => r.agent === id);
34806
+ const configured = id === "claude" ? hookResult.hookInstalled || hookResult.errors.length === 0 : hookForTool ? configuredStatuses.has(hookForTool.status) : false;
34807
+ detectedTools.push({ name: TOOL_DISPLAY_NAMES[id] || id, id, configured });
34808
+ }
34809
+ }
34723
34810
  return {
34724
34811
  hooks: {
34725
34812
  installed: hookResult.hookInstalled || hookResult.rulesInstalled,
34726
34813
  errors: hookResult.errors,
34727
34814
  results: hookResult.results || []
34728
34815
  },
34729
- sync: syncResult
34816
+ sync: syncResult,
34817
+ detectedTools
34730
34818
  };
34731
34819
  }
34732
- function reportPostLoginSetup(result) {
34733
- console.log(source_default.green("\nSetup status:"));
34820
+ function reportPostLoginSetup(result, username, org) {
34821
+ console.log("");
34822
+ const authParts = [source_default.green("\u2713"), "Authenticated"];
34823
+ if (username) authParts.push(`as ${source_default.bold("@" + username)}`);
34824
+ if (org) authParts.push(`(${org})`);
34825
+ console.log(authParts.join(" "));
34734
34826
  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"));
34827
+ console.log(source_default.yellow(`\u26A0 Hooks install incomplete: ${result.hooks.errors[0]}`));
34739
34828
  } 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
- }
34829
+ console.log(source_default.green("\u2713") + " Hooks installed \u2014 configs will sync at session start");
34753
34830
  }
34754
34831
  if (result.sync.status === "synced") {
34755
34832
  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;
34833
+ console.log(source_default.green("\u2713") + ` Approved config synced \u2014 ${result.sync.filesWritten} files applied (${platformLabel})`);
34834
+ } else if (result.sync.status === "skipped" || result.sync.status === "failed") {
34835
+ console.log(source_default.yellow("\u26A0 Sync skipped (no org config available yet) \u2014 retry: gal sync --pull"));
34758
34836
  }
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;
34837
+ if (result.detectedTools.length > 0) {
34838
+ const toolNames = result.detectedTools.map((t) => t.name).join(", ");
34839
+ console.log(source_default.green("\u2713") + ` Detected: ${toolNames}`);
34840
+ } else {
34841
+ console.log(source_default.yellow("\u26A0 No AI coding tools detected. Install Claude Code, Cursor, or Windsurf, then run: gal hooks install"));
34842
+ }
34843
+ const hasErrors = result.hooks.errors.length > 0 || result.sync.status !== "synced" || result.detectedTools.length === 0;
34844
+ if (!hasErrors) {
34845
+ console.log(source_default.dim("\nYou're fully set up. GAL runs automatically from here."));
34762
34846
  }
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
34847
  }
34766
34848
  function startCallbackServer(timeout = 12e4) {
34767
34849
  return new Promise((resolve8, reject) => {
@@ -34871,11 +34953,13 @@ function createAuthCommand() {
34871
34953
  authToken: nonInteractiveToken,
34872
34954
  defaultOrg: config.defaultOrg
34873
34955
  });
34874
- console.log(source_default.green("\n\u2713 Credentials saved! (non-interactive mode)"));
34875
- reportPostLoginSetup(setupResult);
34876
- console.log(source_default.dim(`
34956
+ reportPostLoginSetup(setupResult, user.login, config.defaultOrg);
34957
+ const hasSetupErrors = setupResult.hooks.errors.length > 0 || setupResult.sync.status !== "synced" || setupResult.detectedTools.length === 0;
34958
+ if (hasSetupErrors) {
34959
+ console.log(source_default.dim(`
34877
34960
  Review status: ${source_default.cyan("gal auth status")}
34878
34961
  `));
34962
+ }
34879
34963
  process.exit(0);
34880
34964
  } catch (error2) {
34881
34965
  spinner2.fail(source_default.red("Token validation failed"));
@@ -34920,7 +35004,8 @@ Review status: ${source_default.cyan("gal auth status")}
34920
35004
  ConfigManager.save(config);
34921
35005
  trackAuthLogin(true);
34922
35006
  await refreshInternalStatus(apiUrl, token2);
34923
- await runPostLoginSetup({ apiUrl, authToken: token2, defaultOrg: config.defaultOrg });
35007
+ const setupResult2 = await runPostLoginSetup({ apiUrl, authToken: token2, defaultOrg: config.defaultOrg });
35008
+ reportPostLoginSetup(setupResult2, user2?.login, config.defaultOrg);
34924
35009
  process.exit(0);
34925
35010
  }
34926
35011
  spinner.text = "Opening browser for GitHub authentication...";
@@ -34969,11 +35054,13 @@ Review status: ${source_default.cyan("gal auth status")}
34969
35054
  console.log(source_default.dim(" \u26A0 Could not report status to dashboard"));
34970
35055
  }
34971
35056
  }
34972
- console.log(source_default.green("\n\u2713 Credentials saved!"));
34973
- reportPostLoginSetup(setupResult);
34974
- console.log(source_default.dim(`
35057
+ reportPostLoginSetup(setupResult, user?.login, config.defaultOrg);
35058
+ const hasSetupErrors = setupResult.hooks.errors.length > 0 || setupResult.sync.status !== "synced" || setupResult.detectedTools.length === 0;
35059
+ if (hasSetupErrors) {
35060
+ console.log(source_default.dim(`
34975
35061
  Review status: ${source_default.cyan("gal auth status")}
34976
35062
  `));
35063
+ }
34977
35064
  process.exit(0);
34978
35065
  } catch (error2) {
34979
35066
  spinner.fail(source_default.red("Authentication failed"));
@@ -35972,8 +36059,8 @@ var init_check = __esm({
35972
36059
  issues = [];
35973
36060
  interactive;
35974
36061
  autoFix;
35975
- constructor(projectPath, options = {}) {
35976
- this.projectPath = projectPath;
36062
+ constructor(projectPath2, options = {}) {
36063
+ this.projectPath = projectPath2;
35977
36064
  this.interactive = options.interactive || false;
35978
36065
  this.autoFix = options.autoFix || false;
35979
36066
  }
@@ -42140,13 +42227,13 @@ function getGitEmail() {
42140
42227
  }
42141
42228
  async function getLocalEnforcementStatus() {
42142
42229
  const { stat: stat5, readFile: readFile4 } = await import("node:fs/promises");
42143
- const { join: join45 } = await import("node:path");
42230
+ const { join: join46 } = await import("node:path");
42144
42231
  const platforms = [];
42145
42232
  let version = "0.0.0";
42146
42233
  let policyVersion = "0.0.0";
42147
42234
  const platformDirs = [".claude", ".cursor", ".gemini", ".codex", ".windsurf"];
42148
42235
  for (const dir of platformDirs) {
42149
- const hookPath = join45(process.cwd(), dir, "hooks", "gal-safety-hook.py");
42236
+ const hookPath = join46(process.cwd(), dir, "hooks", "gal-safety-hook.py");
42150
42237
  try {
42151
42238
  await stat5(hookPath);
42152
42239
  platforms.push(dir.replace(".", ""));
@@ -42159,7 +42246,7 @@ async function getLocalEnforcementStatus() {
42159
42246
  }
42160
42247
  }
42161
42248
  try {
42162
- const pkgPath = join45(import_meta.url.replace("file://", ""), "..", "..", "..", "package.json");
42249
+ const pkgPath = join46(import_meta.url.replace("file://", ""), "..", "..", "..", "package.json");
42163
42250
  const pkg = JSON.parse(await readFile4(pkgPath, "utf-8"));
42164
42251
  version = pkg.version || "0.1.0";
42165
42252
  } catch {
@@ -42671,8 +42758,8 @@ var init_headless = __esm({
42671
42758
  tasks = /* @__PURE__ */ new Map();
42672
42759
  runningProcesses = /* @__PURE__ */ new Map();
42673
42760
  projectPath;
42674
- constructor(projectPath = process.cwd(), config = {}) {
42675
- this.projectPath = projectPath;
42761
+ constructor(projectPath2 = process.cwd(), config = {}) {
42762
+ this.projectPath = projectPath2;
42676
42763
  this.config = { ...DEFAULT_CONFIG, ...config };
42677
42764
  this.ensureDirectories();
42678
42765
  this.loadTasks();
@@ -43240,7 +43327,7 @@ if __name__ == '__main__':
43240
43327
  `;
43241
43328
  }
43242
43329
  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) => {
43330
+ 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
43331
  const spinner = ora();
43245
43332
  if (!options.code) {
43246
43333
  console.log(source_default.bold("\nGAL Developer Onboarding\n"));
@@ -43356,7 +43443,7 @@ Error: ${useResult.error || "Unknown error"}`));
43356
43443
  process.exit(1);
43357
43444
  }
43358
43445
  });
43359
- return join45;
43446
+ return join46;
43360
43447
  }
43361
43448
  var import_node_os5, import_node_child_process2, import_node_crypto3, import_promises6, import_node_path4, defaultApiUrl9;
43362
43449
  var init_join = __esm({
@@ -45474,7 +45561,7 @@ Total duplications: ${source_default.yellow(duplicates.length)}`);
45474
45561
  );
45475
45562
  return cmd;
45476
45563
  }
45477
- async function analyzeQuality(projectPath, options) {
45564
+ async function analyzeQuality(projectPath2, options) {
45478
45565
  const issues = [];
45479
45566
  const metrics = {
45480
45567
  totalFiles: 0,
@@ -45485,7 +45572,7 @@ async function analyzeQuality(projectPath, options) {
45485
45572
  duplications: 0,
45486
45573
  technicalDebt: 0
45487
45574
  };
45488
- const files = getSourceFiles(projectPath);
45575
+ const files = getSourceFiles(projectPath2);
45489
45576
  metrics.totalFiles = files.length;
45490
45577
  for (const file of files) {
45491
45578
  try {
@@ -45496,7 +45583,7 @@ async function analyzeQuality(projectPath, options) {
45496
45583
  const line = lines[i];
45497
45584
  if (line.includes("console.log") && !file.includes("test")) {
45498
45585
  issues.push({
45499
- file: path2.relative(projectPath, file),
45586
+ file: path2.relative(projectPath2, file),
45500
45587
  line: i + 1,
45501
45588
  type: "warning",
45502
45589
  rule: "no-console",
@@ -45505,7 +45592,7 @@ async function analyzeQuality(projectPath, options) {
45505
45592
  }
45506
45593
  if (line.includes("TODO") || line.includes("FIXME")) {
45507
45594
  issues.push({
45508
- file: path2.relative(projectPath, file),
45595
+ file: path2.relative(projectPath2, file),
45509
45596
  line: i + 1,
45510
45597
  type: "info",
45511
45598
  rule: "no-todo",
@@ -45514,7 +45601,7 @@ async function analyzeQuality(projectPath, options) {
45514
45601
  }
45515
45602
  if (line.includes(": any") || line.includes("<any>")) {
45516
45603
  issues.push({
45517
- file: path2.relative(projectPath, file),
45604
+ file: path2.relative(projectPath2, file),
45518
45605
  line: i + 1,
45519
45606
  type: "warning",
45520
45607
  rule: "no-any",
@@ -45524,7 +45611,7 @@ async function analyzeQuality(projectPath, options) {
45524
45611
  }
45525
45612
  if (lines.length > DEFAULT_CONFIG2.maxFileLength) {
45526
45613
  issues.push({
45527
- file: path2.relative(projectPath, file),
45614
+ file: path2.relative(projectPath2, file),
45528
45615
  type: "warning",
45529
45616
  rule: "max-file-length",
45530
45617
  message: `File exceeds ${DEFAULT_CONFIG2.maxFileLength} lines (${lines.length})`
@@ -45545,8 +45632,8 @@ async function analyzeQuality(projectPath, options) {
45545
45632
  recommendations: generateRecommendations(issues, metrics)
45546
45633
  };
45547
45634
  }
45548
- async function analyzeComplexity(projectPath, threshold) {
45549
- const files = getSourceFiles(projectPath);
45635
+ async function analyzeComplexity(projectPath2, threshold) {
45636
+ const files = getSourceFiles(projectPath2);
45550
45637
  const highComplexity = [];
45551
45638
  let totalComplexity = 0;
45552
45639
  let functionCount = 0;
@@ -45557,7 +45644,7 @@ async function analyzeComplexity(projectPath, threshold) {
45557
45644
  const complexity = (matches?.length || 0) + 1;
45558
45645
  if (complexity > threshold) {
45559
45646
  highComplexity.push({
45560
- file: path2.relative(projectPath, file),
45647
+ file: path2.relative(projectPath2, file),
45561
45648
  complexity,
45562
45649
  threshold
45563
45650
  });
@@ -45572,11 +45659,11 @@ async function analyzeComplexity(projectPath, threshold) {
45572
45659
  avgComplexity: functionCount > 0 ? totalComplexity / functionCount : 0
45573
45660
  };
45574
45661
  }
45575
- async function findDuplications(projectPath, minLines) {
45662
+ async function findDuplications(projectPath2, minLines) {
45576
45663
  return [];
45577
45664
  }
45578
- async function calculateTechnicalDebt(projectPath) {
45579
- const report = await analyzeQuality(projectPath, {});
45665
+ async function calculateTechnicalDebt(projectPath2) {
45666
+ const report = await analyzeQuality(projectPath2, {});
45580
45667
  return {
45581
45668
  totalDebt: report.issues.length * 15,
45582
45669
  // 15 minutes per issue
@@ -47062,108 +47149,467 @@ var init_run = __esm({
47062
47149
  }
47063
47150
  });
47064
47151
 
47152
+ // src/commands/run-design.ts
47153
+ function ensureDir() {
47154
+ if (!(0, import_fs32.existsSync)(DESIGN_PROJECTS_DIR)) {
47155
+ (0, import_fs32.mkdirSync)(DESIGN_PROJECTS_DIR, { recursive: true });
47156
+ }
47157
+ }
47158
+ function projectPath(id) {
47159
+ return (0, import_path29.join)(DESIGN_PROJECTS_DIR, `${id}.json`);
47160
+ }
47161
+ function saveProject(project) {
47162
+ ensureDir();
47163
+ (0, import_fs32.writeFileSync)(projectPath(project.id), JSON.stringify(project, null, 2));
47164
+ }
47165
+ function loadProject(id) {
47166
+ const p = projectPath(id);
47167
+ if (!(0, import_fs32.existsSync)(p)) return null;
47168
+ try {
47169
+ return JSON.parse((0, import_fs32.readFileSync)(p, "utf-8"));
47170
+ } catch {
47171
+ return null;
47172
+ }
47173
+ }
47174
+ function getActiveId() {
47175
+ if (!(0, import_fs32.existsSync)(ACTIVE_FILE)) return null;
47176
+ try {
47177
+ const data = JSON.parse((0, import_fs32.readFileSync)(ACTIVE_FILE, "utf-8"));
47178
+ return data.id ?? null;
47179
+ } catch {
47180
+ return null;
47181
+ }
47182
+ }
47183
+ function setActiveId(id) {
47184
+ ensureDir();
47185
+ (0, import_fs32.writeFileSync)(ACTIVE_FILE, JSON.stringify({ id }, null, 2));
47186
+ }
47187
+ function getActiveProject() {
47188
+ const id = getActiveId();
47189
+ if (!id) return null;
47190
+ return loadProject(id);
47191
+ }
47192
+ function generateId() {
47193
+ return `dp-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
47194
+ }
47195
+ function generateSceneId() {
47196
+ return `sc-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
47197
+ }
47198
+ function renderStatusTable(project) {
47199
+ const COL_NUM = 3;
47200
+ const COL_SCENE = 25;
47201
+ const COL_IMAGE = 8;
47202
+ const COL_VIDEO = 8;
47203
+ const COL_STATUS = 8;
47204
+ const pad = (s, width) => s.padEnd(width).slice(0, width);
47205
+ const header = source_default.bold.white(`${project.name} `) + source_default.gray(`(${project.type} \xB7 ${project.scenes.length} scene${project.scenes.length !== 1 ? "s" : ""})`);
47206
+ 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";
47207
+ 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";
47208
+ 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";
47209
+ 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";
47210
+ const rows = project.scenes.map((scene) => {
47211
+ const imageIcon = IMAGE_STATUS_ICON[scene.status.image] ?? " ";
47212
+ const videoIcon = VIDEO_STATUS_ICON[scene.status.video] ?? " ";
47213
+ let statusLabel;
47214
+ if (scene.status.image === "done" && (scene.status.video === "done" || scene.status.video === "not-needed")) {
47215
+ statusLabel = source_default.green("Done");
47216
+ } else if (scene.status.image !== "done") {
47217
+ statusLabel = source_default.yellow("Image");
47218
+ } else {
47219
+ statusLabel = source_default.cyan("Video");
47220
+ }
47221
+ 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";
47222
+ });
47223
+ return [header, top, headRow, divider, ...rows, bottom].join("\n");
47224
+ }
47225
+ function handleInit(options) {
47226
+ const validTypes = ["image-only", "image-video", "story"];
47227
+ if (!validTypes.includes(options.type)) {
47228
+ console.error(
47229
+ source_default.red(`Error: --type must be one of: ${validTypes.join(", ")}`)
47230
+ );
47231
+ process.exit(1);
47232
+ }
47233
+ if (!options.name || options.name.trim() === "") {
47234
+ console.error(source_default.red("Error: --name is required"));
47235
+ process.exit(1);
47236
+ }
47237
+ const project = {
47238
+ id: generateId(),
47239
+ name: options.name.trim(),
47240
+ type: options.type,
47241
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
47242
+ scenes: [],
47243
+ metadata: {
47244
+ client: options.client
47245
+ }
47246
+ };
47247
+ saveProject(project);
47248
+ setActiveId(project.id);
47249
+ console.log(source_default.green("\nDesign project created successfully!\n"));
47250
+ console.log(source_default.bold(" Name:"), project.name);
47251
+ console.log(source_default.bold(" Type:"), project.type);
47252
+ console.log(source_default.bold(" ID: "), source_default.gray(project.id));
47253
+ if (options.client) {
47254
+ console.log(source_default.bold(" Client:"), options.client);
47255
+ }
47256
+ console.log(
47257
+ source_default.gray("\nNext: add scenes with "),
47258
+ source_default.cyan(`gal run-design add-scene "Scene description"`)
47259
+ );
47260
+ }
47261
+ function handleAddScene(description, options) {
47262
+ const project = getActiveProject();
47263
+ if (!project) {
47264
+ console.error(
47265
+ source_default.red("Error: No active design project. Run `gal run-design init` first.")
47266
+ );
47267
+ process.exit(1);
47268
+ }
47269
+ const needsVideo = project.type !== "image-only";
47270
+ const scene = {
47271
+ id: generateSceneId(),
47272
+ order: project.scenes.length + 1,
47273
+ description: description.trim(),
47274
+ referenceImageUrl: options.ref,
47275
+ status: {
47276
+ image: "pending",
47277
+ video: needsVideo ? "pending" : "not-needed"
47278
+ },
47279
+ assets: {}
47280
+ };
47281
+ project.scenes.push(scene);
47282
+ saveProject(project);
47283
+ console.log(
47284
+ source_default.green(`
47285
+ Scene ${scene.order} added: `) + source_default.white(scene.description)
47286
+ );
47287
+ if (options.ref) {
47288
+ console.log(source_default.gray(" Reference image:"), options.ref);
47289
+ }
47290
+ console.log(source_default.gray(` Total scenes: ${project.scenes.length}`));
47291
+ }
47292
+ function handleStatus(options) {
47293
+ let project;
47294
+ if (options.project) {
47295
+ project = loadProject(options.project);
47296
+ if (!project) {
47297
+ console.error(
47298
+ source_default.red(`Error: Project '${options.project}' not found`)
47299
+ );
47300
+ process.exit(1);
47301
+ }
47302
+ } else {
47303
+ project = getActiveProject();
47304
+ if (!project) {
47305
+ ensureDir();
47306
+ const files = (0, import_fs32.readdirSync)(DESIGN_PROJECTS_DIR).filter(
47307
+ (f) => f.endsWith(".json") && f !== "active.json"
47308
+ );
47309
+ if (files.length === 0) {
47310
+ console.log(
47311
+ source_default.yellow("No design projects found."),
47312
+ source_default.gray("Run `gal run-design init` to create one.")
47313
+ );
47314
+ } else {
47315
+ console.log(source_default.bold("\nAvailable projects:\n"));
47316
+ for (const file of files) {
47317
+ const p = loadProject(file.replace(".json", ""));
47318
+ if (p) {
47319
+ console.log(
47320
+ ` ${source_default.cyan(p.id)} ${source_default.white(p.name)} ${source_default.gray(p.type)} ${source_default.gray(p.scenes.length + " scenes")}`
47321
+ );
47322
+ }
47323
+ }
47324
+ console.log(
47325
+ source_default.gray("\nUse `gal run-design status --project <id>` to view a specific project.")
47326
+ );
47327
+ }
47328
+ return;
47329
+ }
47330
+ }
47331
+ console.log("\n" + renderStatusTable(project));
47332
+ const done = project.scenes.filter(
47333
+ (s) => s.status.image === "done" && (s.status.video === "done" || s.status.video === "not-needed")
47334
+ ).length;
47335
+ const total = project.scenes.length;
47336
+ const pct = total > 0 ? Math.round(done / total * 100) : 0;
47337
+ console.log(
47338
+ source_default.gray(`
47339
+ ${done}/${total} complete (${pct}%)`)
47340
+ );
47341
+ const activeId = getActiveId();
47342
+ if (project.id === activeId) {
47343
+ console.log(source_default.green(" Active project"));
47344
+ }
47345
+ console.log();
47346
+ }
47347
+ function handleScene(nStr, options) {
47348
+ const n = parseInt(nStr, 10);
47349
+ if (isNaN(n) || n < 1) {
47350
+ console.error(source_default.red("Error: scene number must be a positive integer"));
47351
+ process.exit(1);
47352
+ }
47353
+ let project;
47354
+ if (options.project) {
47355
+ project = loadProject(options.project);
47356
+ if (!project) {
47357
+ console.error(source_default.red(`Error: Project '${options.project}' not found`));
47358
+ process.exit(1);
47359
+ }
47360
+ } else {
47361
+ project = getActiveProject();
47362
+ if (!project) {
47363
+ console.error(
47364
+ source_default.red("Error: No active design project. Run `gal run-design init` first.")
47365
+ );
47366
+ process.exit(1);
47367
+ }
47368
+ }
47369
+ const scene = project.scenes.find((s) => s.order === n);
47370
+ if (!scene) {
47371
+ console.error(
47372
+ source_default.red(`Error: Scene ${n} not found in project '${project.name}'`)
47373
+ );
47374
+ process.exit(1);
47375
+ }
47376
+ let changed = false;
47377
+ if (options.imageDone) {
47378
+ scene.status.image = "done";
47379
+ changed = true;
47380
+ }
47381
+ if (options.videoDone) {
47382
+ if (scene.status.video === "not-needed") {
47383
+ console.error(
47384
+ source_default.yellow(`Warning: Scene ${n} video is marked as 'not-needed' for project type '${project.type}'. Marking done anyway.`)
47385
+ );
47386
+ }
47387
+ scene.status.video = "done";
47388
+ changed = true;
47389
+ }
47390
+ if (options.notes !== void 0) {
47391
+ scene.notes = options.notes;
47392
+ changed = true;
47393
+ }
47394
+ if (!changed) {
47395
+ console.log(
47396
+ source_default.yellow(
47397
+ "No changes made. Use --image-done, --video-done, or --notes to update the scene."
47398
+ )
47399
+ );
47400
+ return;
47401
+ }
47402
+ saveProject(project);
47403
+ console.log(
47404
+ source_default.green(`
47405
+ Scene ${n} updated: `) + source_default.white(scene.description)
47406
+ );
47407
+ console.log(
47408
+ source_default.bold(" Image:"),
47409
+ scene.status.image,
47410
+ " " + source_default.bold("Video:"),
47411
+ scene.status.video
47412
+ );
47413
+ if (scene.notes) {
47414
+ console.log(source_default.bold(" Notes:"), scene.notes);
47415
+ }
47416
+ }
47417
+ function handleSync() {
47418
+ const project = getActiveProject();
47419
+ if (!project) {
47420
+ ensureDir();
47421
+ (0, import_fs32.writeFileSync)(
47422
+ (0, import_path29.join)(DESIGN_PROJECTS_DIR, "extension-sync.json"),
47423
+ JSON.stringify(null, null, 2)
47424
+ );
47425
+ console.log(source_default.yellow("No active project. Extension card cleared."));
47426
+ return;
47427
+ }
47428
+ const done = project.scenes.filter(
47429
+ (s) => s.status.image === "done" && (s.status.video === "done" || s.status.video === "not-needed")
47430
+ ).length;
47431
+ const summary = {
47432
+ id: project.id,
47433
+ name: project.name,
47434
+ type: project.type,
47435
+ totalScenes: project.scenes.length,
47436
+ completedScenes: done
47437
+ };
47438
+ ensureDir();
47439
+ (0, import_fs32.writeFileSync)(
47440
+ (0, import_path29.join)(DESIGN_PROJECTS_DIR, "extension-sync.json"),
47441
+ JSON.stringify(summary, null, 2)
47442
+ );
47443
+ console.log(source_default.green("\nSynced active project to extension:\n"));
47444
+ console.log(source_default.bold(" Name:"), project.name);
47445
+ console.log(source_default.bold(" Scenes:"), `${done}/${project.scenes.length} complete`);
47446
+ const pct = project.scenes.length > 0 ? Math.round(done / project.scenes.length * 100) : 0;
47447
+ console.log(source_default.bold(" Progress:"), `${pct}%`);
47448
+ console.log(
47449
+ source_default.gray(
47450
+ "\nThe extension popup will show a status card for this project.\n"
47451
+ )
47452
+ );
47453
+ }
47454
+ function createRunDesignCommand() {
47455
+ const runDesign = new Command("run-design");
47456
+ runDesign.description("Creative production pipeline orchestrator (image \u2192 video)");
47457
+ const initCmd = new Command("init");
47458
+ 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) => {
47459
+ handleInit(options);
47460
+ });
47461
+ const addSceneCmd = new Command("add-scene");
47462
+ addSceneCmd.description("Add a scene to the active project").argument("<description>", "Scene description").option("-r, --ref <imageUrl>", "Reference image URL").action((description, options) => {
47463
+ handleAddScene(description, options);
47464
+ });
47465
+ const statusCmd = new Command("status");
47466
+ statusCmd.description("Show scene progress table for the active project").option("-p, --project <id>", "Project ID (defaults to active project)").action((options) => {
47467
+ handleStatus(options);
47468
+ });
47469
+ const sceneCmd = new Command("scene");
47470
+ 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) => {
47471
+ handleScene(n, options);
47472
+ });
47473
+ const syncCmd = new Command("sync");
47474
+ syncCmd.description("Write active project summary for Chrome extension status card").action(() => {
47475
+ handleSync();
47476
+ });
47477
+ runDesign.addCommand(initCmd);
47478
+ runDesign.addCommand(addSceneCmd);
47479
+ runDesign.addCommand(statusCmd);
47480
+ runDesign.addCommand(sceneCmd);
47481
+ runDesign.addCommand(syncCmd);
47482
+ return runDesign;
47483
+ }
47484
+ var import_os19, import_path29, import_fs32, DESIGN_PROJECTS_DIR, ACTIVE_FILE, IMAGE_STATUS_ICON, VIDEO_STATUS_ICON;
47485
+ var init_run_design = __esm({
47486
+ "src/commands/run-design.ts"() {
47487
+ "use strict";
47488
+ init_esm();
47489
+ init_source();
47490
+ import_os19 = require("os");
47491
+ import_path29 = require("path");
47492
+ import_fs32 = require("fs");
47493
+ DESIGN_PROJECTS_DIR = (0, import_path29.join)((0, import_os19.homedir)(), ".gal", "design-projects");
47494
+ ACTIVE_FILE = (0, import_path29.join)(DESIGN_PROJECTS_DIR, "active.json");
47495
+ IMAGE_STATUS_ICON = {
47496
+ pending: " ",
47497
+ generating: " ",
47498
+ done: " ",
47499
+ "needs-regen": " "
47500
+ };
47501
+ VIDEO_STATUS_ICON = {
47502
+ pending: " ",
47503
+ generating: " ",
47504
+ done: " ",
47505
+ "needs-regen": " ",
47506
+ "not-needed": " "
47507
+ };
47508
+ }
47509
+ });
47510
+
47065
47511
  // src/commands/scan.ts
47066
47512
  function scanPlatform(rootDir, pattern) {
47067
47513
  const configs = [];
47068
47514
  const platform5 = pattern.platform;
47069
- const platformDir = (0, import_path29.join)(rootDir, pattern.directory);
47515
+ const platformDir = (0, import_path30.join)(rootDir, pattern.directory);
47070
47516
  if (pattern.settingsFile) {
47071
- const settingsPath = (0, import_path29.join)(platformDir, pattern.settingsFile);
47072
- if ((0, import_fs32.existsSync)(settingsPath)) {
47517
+ const settingsPath = (0, import_path30.join)(platformDir, pattern.settingsFile);
47518
+ if ((0, import_fs33.existsSync)(settingsPath)) {
47073
47519
  configs.push({
47074
47520
  platform: platform5,
47075
47521
  type: "settings",
47076
47522
  name: pattern.settingsFile,
47077
47523
  path: settingsPath,
47078
- relativePath: (0, import_path29.relative)(rootDir, settingsPath),
47079
- sizeBytes: (0, import_fs32.statSync)(settingsPath).size
47524
+ relativePath: (0, import_path30.relative)(rootDir, settingsPath),
47525
+ sizeBytes: (0, import_fs33.statSync)(settingsPath).size
47080
47526
  });
47081
47527
  }
47082
47528
  }
47083
47529
  if (pattern.configFile) {
47084
- const configPath = (0, import_path29.join)(platformDir, pattern.configFile);
47085
- if ((0, import_fs32.existsSync)(configPath)) {
47530
+ const configPath = (0, import_path30.join)(platformDir, pattern.configFile);
47531
+ if ((0, import_fs33.existsSync)(configPath)) {
47086
47532
  configs.push({
47087
47533
  platform: platform5,
47088
47534
  type: "settings",
47089
47535
  name: pattern.configFile,
47090
47536
  path: configPath,
47091
- relativePath: (0, import_path29.relative)(rootDir, configPath),
47092
- sizeBytes: (0, import_fs32.statSync)(configPath).size
47537
+ relativePath: (0, import_path30.relative)(rootDir, configPath),
47538
+ sizeBytes: (0, import_fs33.statSync)(configPath).size
47093
47539
  });
47094
47540
  }
47095
47541
  }
47096
47542
  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()) {
47543
+ const rulesDir = (0, import_path30.join)(platformDir, pattern.rulesDir);
47544
+ if ((0, import_fs33.existsSync)(rulesDir) && (0, import_fs33.statSync)(rulesDir).isDirectory()) {
47099
47545
  scanDir(rulesDir, rootDir, platform5, "rules", pattern.ruleExtensions, configs);
47100
47546
  }
47101
47547
  }
47102
47548
  if (pattern.rulesFile) {
47103
- const rulesPath = (0, import_path29.join)(platformDir, pattern.rulesFile);
47104
- if ((0, import_fs32.existsSync)(rulesPath)) {
47549
+ const rulesPath = (0, import_path30.join)(platformDir, pattern.rulesFile);
47550
+ if ((0, import_fs33.existsSync)(rulesPath)) {
47105
47551
  configs.push({
47106
47552
  platform: platform5,
47107
47553
  type: "rules",
47108
47554
  name: pattern.rulesFile,
47109
47555
  path: rulesPath,
47110
- relativePath: (0, import_path29.relative)(rootDir, rulesPath),
47111
- sizeBytes: (0, import_fs32.statSync)(rulesPath).size
47556
+ relativePath: (0, import_path30.relative)(rootDir, rulesPath),
47557
+ sizeBytes: (0, import_fs33.statSync)(rulesPath).size
47112
47558
  });
47113
47559
  }
47114
47560
  }
47115
47561
  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()) {
47562
+ const commandsDir = (0, import_path30.join)(platformDir, pattern.commandsDir);
47563
+ if ((0, import_fs33.existsSync)(commandsDir) && (0, import_fs33.statSync)(commandsDir).isDirectory()) {
47118
47564
  scanDir(commandsDir, rootDir, platform5, "commands", [".md", ".toml"], configs);
47119
47565
  }
47120
47566
  }
47121
47567
  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()) {
47568
+ const hooksDir = (0, import_path30.join)(platformDir, pattern.hooksDir);
47569
+ if ((0, import_fs33.existsSync)(hooksDir) && (0, import_fs33.statSync)(hooksDir).isDirectory()) {
47124
47570
  scanDir(hooksDir, rootDir, platform5, "hooks", [".md", ".json", ".sh", ".ts", ".js"], configs);
47125
47571
  }
47126
47572
  }
47127
47573
  if (pattern.hooksConfigFile) {
47128
- const hooksConfigPath = (0, import_path29.join)(platformDir, pattern.hooksConfigFile);
47129
- if ((0, import_fs32.existsSync)(hooksConfigPath)) {
47574
+ const hooksConfigPath = (0, import_path30.join)(platformDir, pattern.hooksConfigFile);
47575
+ if ((0, import_fs33.existsSync)(hooksConfigPath)) {
47130
47576
  configs.push({
47131
47577
  platform: platform5,
47132
47578
  type: "hooks",
47133
47579
  name: pattern.hooksConfigFile,
47134
47580
  path: hooksConfigPath,
47135
- relativePath: (0, import_path29.relative)(rootDir, hooksConfigPath),
47136
- sizeBytes: (0, import_fs32.statSync)(hooksConfigPath).size
47581
+ relativePath: (0, import_path30.relative)(rootDir, hooksConfigPath),
47582
+ sizeBytes: (0, import_fs33.statSync)(hooksConfigPath).size
47137
47583
  });
47138
47584
  }
47139
47585
  }
47140
47586
  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()) {
47587
+ const agentsDir = (0, import_path30.join)(platformDir, pattern.agentsDir);
47588
+ if ((0, import_fs33.existsSync)(agentsDir) && (0, import_fs33.statSync)(agentsDir).isDirectory()) {
47143
47589
  scanDir(agentsDir, rootDir, platform5, "agents", [".md", ".toml", ".agent.md"], configs);
47144
47590
  }
47145
47591
  }
47146
47592
  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()) {
47593
+ const skillsDir = (0, import_path30.join)(platformDir, pattern.skillsDir);
47594
+ if ((0, import_fs33.existsSync)(skillsDir) && (0, import_fs33.statSync)(skillsDir).isDirectory()) {
47149
47595
  scanDir(skillsDir, rootDir, platform5, "skills", [".md"], configs);
47150
47596
  }
47151
47597
  }
47152
47598
  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()) {
47599
+ const policiesDir = (0, import_path30.join)(platformDir, pattern.policiesDir);
47600
+ if ((0, import_fs33.existsSync)(policiesDir) && (0, import_fs33.statSync)(policiesDir).isDirectory()) {
47155
47601
  scanDir(policiesDir, rootDir, platform5, "policies", [".toml", ".md"], configs);
47156
47602
  }
47157
47603
  }
47158
47604
  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()) {
47605
+ const workflowsDir = (0, import_path30.join)(platformDir, pattern.workflowsDir);
47606
+ if ((0, import_fs33.existsSync)(workflowsDir) && (0, import_fs33.statSync)(workflowsDir).isDirectory()) {
47161
47607
  scanDir(workflowsDir, rootDir, platform5, "workflows", [".md"], configs);
47162
47608
  }
47163
47609
  }
47164
47610
  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()) {
47611
+ const promptsDir = (0, import_path30.join)(platformDir, pattern.promptsDir);
47612
+ if ((0, import_fs33.existsSync)(promptsDir) && (0, import_fs33.statSync)(promptsDir).isDirectory()) {
47167
47613
  scanDir(promptsDir, rootDir, platform5, "prompts", [".prompt.md", ".md"], configs);
47168
47614
  }
47169
47615
  }
@@ -47182,59 +47628,59 @@ function scanPlatform(rootDir, pattern) {
47182
47628
  for (const { key, type } of rootInstructionFiles) {
47183
47629
  const fileName = pattern[key];
47184
47630
  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)) {
47631
+ const rootPath = (0, import_path30.join)(rootDir, fileName);
47632
+ const platformPath = (0, import_path30.join)(platformDir, fileName);
47633
+ if ((0, import_fs33.existsSync)(rootPath)) {
47188
47634
  configs.push({
47189
47635
  platform: platform5,
47190
47636
  type,
47191
47637
  name: fileName,
47192
47638
  path: rootPath,
47193
- relativePath: (0, import_path29.relative)(rootDir, rootPath),
47194
- sizeBytes: (0, import_fs32.statSync)(rootPath).size
47639
+ relativePath: (0, import_path30.relative)(rootDir, rootPath),
47640
+ sizeBytes: (0, import_fs33.statSync)(rootPath).size
47195
47641
  });
47196
- } else if ((0, import_fs32.existsSync)(platformPath) && platformPath !== rootPath) {
47642
+ } else if ((0, import_fs33.existsSync)(platformPath) && platformPath !== rootPath) {
47197
47643
  configs.push({
47198
47644
  platform: platform5,
47199
47645
  type,
47200
47646
  name: fileName,
47201
47647
  path: platformPath,
47202
- relativePath: (0, import_path29.relative)(rootDir, platformPath),
47203
- sizeBytes: (0, import_fs32.statSync)(platformPath).size
47648
+ relativePath: (0, import_path30.relative)(rootDir, platformPath),
47649
+ sizeBytes: (0, import_fs33.statSync)(platformPath).size
47204
47650
  });
47205
47651
  }
47206
47652
  }
47207
47653
  }
47208
47654
  if (pattern.mcpFile) {
47209
- const mcpPath = (0, import_path29.join)(rootDir, pattern.mcpFile);
47210
- if ((0, import_fs32.existsSync)(mcpPath)) {
47655
+ const mcpPath = (0, import_path30.join)(rootDir, pattern.mcpFile);
47656
+ if ((0, import_fs33.existsSync)(mcpPath)) {
47211
47657
  configs.push({
47212
47658
  platform: platform5,
47213
47659
  type: "mcp",
47214
47660
  name: pattern.mcpFile,
47215
47661
  path: mcpPath,
47216
- relativePath: (0, import_path29.relative)(rootDir, mcpPath),
47217
- sizeBytes: (0, import_fs32.statSync)(mcpPath).size
47662
+ relativePath: (0, import_path30.relative)(rootDir, mcpPath),
47663
+ sizeBytes: (0, import_fs33.statSync)(mcpPath).size
47218
47664
  });
47219
47665
  }
47220
47666
  }
47221
47667
  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()) {
47668
+ const memDir = (0, import_path30.join)(platformDir, pattern.memoryDir);
47669
+ if ((0, import_fs33.existsSync)(memDir) && (0, import_fs33.statSync)(memDir).isDirectory()) {
47224
47670
  const exts = pattern.memoryExtensions || [".md"];
47225
47671
  scanDir(memDir, rootDir, platform5, "memory", exts, configs);
47226
47672
  }
47227
47673
  }
47228
47674
  if (pattern.cliConfigFile) {
47229
- const cliPath = (0, import_path29.join)(platformDir, pattern.cliConfigFile);
47230
- if ((0, import_fs32.existsSync)(cliPath)) {
47675
+ const cliPath = (0, import_path30.join)(platformDir, pattern.cliConfigFile);
47676
+ if ((0, import_fs33.existsSync)(cliPath)) {
47231
47677
  configs.push({
47232
47678
  platform: platform5,
47233
47679
  type: "settings",
47234
47680
  name: pattern.cliConfigFile,
47235
47681
  path: cliPath,
47236
- relativePath: (0, import_path29.relative)(rootDir, cliPath),
47237
- sizeBytes: (0, import_fs32.statSync)(cliPath).size
47682
+ relativePath: (0, import_path30.relative)(rootDir, cliPath),
47683
+ sizeBytes: (0, import_fs33.statSync)(cliPath).size
47238
47684
  });
47239
47685
  }
47240
47686
  }
@@ -47242,9 +47688,9 @@ function scanPlatform(rootDir, pattern) {
47242
47688
  }
47243
47689
  function scanDir(dir, rootDir, platform5, type, extensions, configs) {
47244
47690
  try {
47245
- const entries = (0, import_fs32.readdirSync)(dir, { withFileTypes: true });
47691
+ const entries = (0, import_fs33.readdirSync)(dir, { withFileTypes: true });
47246
47692
  for (const entry of entries) {
47247
- const fullPath = (0, import_path29.join)(dir, entry.name);
47693
+ const fullPath = (0, import_path30.join)(dir, entry.name);
47248
47694
  if (entry.isDirectory()) {
47249
47695
  scanDir(fullPath, rootDir, platform5, type, extensions, configs);
47250
47696
  } else if (entry.isFile()) {
@@ -47255,8 +47701,8 @@ function scanDir(dir, rootDir, platform5, type, extensions, configs) {
47255
47701
  type,
47256
47702
  name: entry.name,
47257
47703
  path: fullPath,
47258
- relativePath: (0, import_path29.relative)(rootDir, fullPath),
47259
- sizeBytes: (0, import_fs32.statSync)(fullPath).size
47704
+ relativePath: (0, import_path30.relative)(rootDir, fullPath),
47705
+ sizeBytes: (0, import_fs33.statSync)(fullPath).size
47260
47706
  });
47261
47707
  }
47262
47708
  }
@@ -47273,7 +47719,7 @@ function createScanCommand() {
47273
47719
  const command = new Command("scan");
47274
47720
  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
47721
  const targetDir = options.path ? options.path : findProjectRoot(process.cwd());
47276
- if (!(0, import_fs32.existsSync)(targetDir)) {
47722
+ if (!(0, import_fs33.existsSync)(targetDir)) {
47277
47723
  console.error(source_default.red(`Directory not found: ${targetDir}`));
47278
47724
  process.exit(1);
47279
47725
  }
@@ -47304,12 +47750,12 @@ function createScanCommand() {
47304
47750
  }
47305
47751
  }
47306
47752
  if (options.includeGlobal) {
47307
- const home = (0, import_os19.homedir)();
47753
+ const home = (0, import_os20.homedir)();
47308
47754
  for (const loc of GLOBAL_MEMORY_LOCATIONS) {
47309
47755
  if (platformFilter && loc.platform !== platformFilter) continue;
47310
47756
  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;
47757
+ const globalDir = (0, import_path30.join)(home, relPath);
47758
+ if (!(0, import_fs33.existsSync)(globalDir) || !(0, import_fs33.statSync)(globalDir).isDirectory()) continue;
47313
47759
  const globalConfigs = [];
47314
47760
  scanDir(globalDir, home, loc.platform, "memory", loc.extensions, globalConfigs);
47315
47761
  if (globalConfigs.length > 0) {
@@ -47385,15 +47831,15 @@ function createScanCommand() {
47385
47831
  });
47386
47832
  return command;
47387
47833
  }
47388
- var import_fs32, import_path29, import_os19, GLOBAL_MEMORY_LOCATIONS, PLATFORM_LABELS, PLATFORM_COLORS;
47834
+ var import_fs33, import_path30, import_os20, GLOBAL_MEMORY_LOCATIONS, PLATFORM_LABELS, PLATFORM_COLORS;
47389
47835
  var init_scan = __esm({
47390
47836
  "src/commands/scan.ts"() {
47391
47837
  "use strict";
47392
47838
  init_esm();
47393
47839
  init_source();
47394
- import_fs32 = require("fs");
47395
- import_path29 = require("path");
47396
- import_os19 = require("os");
47840
+ import_fs33 = require("fs");
47841
+ import_path30 = require("path");
47842
+ import_os20 = require("os");
47397
47843
  init_dist2();
47398
47844
  init_project_detection();
47399
47845
  GLOBAL_MEMORY_LOCATIONS = [
@@ -48046,8 +48492,8 @@ function createSandboxCommand() {
48046
48492
  return sandboxCmd;
48047
48493
  }
48048
48494
  async function validateConfigFile(sandbox, options) {
48049
- const configPath = import_path30.default.resolve(options.config);
48050
- const fileName = import_path30.default.basename(configPath);
48495
+ const configPath = import_path31.default.resolve(options.config);
48496
+ const fileName = import_path31.default.basename(configPath);
48051
48497
  const spinner = ora(`Loading configuration: ${fileName}`).start();
48052
48498
  try {
48053
48499
  const configContent = await import_promises8.default.readFile(configPath, "utf-8");
@@ -48162,7 +48608,7 @@ async function startInteractiveSession(sandbox) {
48162
48608
  rl.on("close", resolve8);
48163
48609
  });
48164
48610
  }
48165
- var import_promises8, import_path30;
48611
+ var import_promises8, import_path31;
48166
48612
  var init_sandbox = __esm({
48167
48613
  "src/commands/sandbox.ts"() {
48168
48614
  "use strict";
@@ -48171,7 +48617,7 @@ var init_sandbox = __esm({
48171
48617
  init_ora();
48172
48618
  init_e2b_sandbox();
48173
48619
  import_promises8 = __toESM(require("fs/promises"), 1);
48174
- import_path30 = __toESM(require("path"), 1);
48620
+ import_path31 = __toESM(require("path"), 1);
48175
48621
  }
48176
48622
  });
48177
48623
 
@@ -48180,7 +48626,7 @@ function isTestFile(filename) {
48180
48626
  return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
48181
48627
  }
48182
48628
  function isImplFile(filename) {
48183
- const ext = (0, import_path31.extname)(filename);
48629
+ const ext = (0, import_path32.extname)(filename);
48184
48630
  if (!IMPL_EXTENSIONS.has(ext)) return false;
48185
48631
  if (isTestFile(filename)) return false;
48186
48632
  if (IGNORE_FILES.has(filename)) return false;
@@ -48195,16 +48641,16 @@ function scanDirectory(dir, maxDepth = 6) {
48195
48641
  if (depth > maxDepth) return;
48196
48642
  let entries;
48197
48643
  try {
48198
- entries = (0, import_fs33.readdirSync)(currentDir);
48644
+ entries = (0, import_fs34.readdirSync)(currentDir);
48199
48645
  } catch {
48200
48646
  return;
48201
48647
  }
48202
48648
  for (const entry of entries) {
48203
48649
  if (IGNORE_DIRS.has(entry)) continue;
48204
- const fullPath = (0, import_path31.join)(currentDir, entry);
48650
+ const fullPath = (0, import_path32.join)(currentDir, entry);
48205
48651
  let stat5;
48206
48652
  try {
48207
- stat5 = (0, import_fs33.statSync)(fullPath);
48653
+ stat5 = (0, import_fs34.statSync)(fullPath);
48208
48654
  } catch {
48209
48655
  continue;
48210
48656
  }
@@ -48214,7 +48660,7 @@ function scanDirectory(dir, maxDepth = 6) {
48214
48660
  }
48215
48661
  walk(fullPath, depth + 1);
48216
48662
  } else if (stat5.isFile()) {
48217
- const relPath = (0, import_path31.relative)(dir, fullPath);
48663
+ const relPath = (0, import_path32.relative)(dir, fullPath);
48218
48664
  if (isTestFile(entry)) {
48219
48665
  testFiles.push(relPath);
48220
48666
  } else if (isImplFile(entry)) {
@@ -48234,15 +48680,15 @@ function findSpecFiles(dir) {
48234
48680
  if (depth > 4) return;
48235
48681
  let entries;
48236
48682
  try {
48237
- entries = (0, import_fs33.readdirSync)(currentDir);
48683
+ entries = (0, import_fs34.readdirSync)(currentDir);
48238
48684
  } catch {
48239
48685
  return;
48240
48686
  }
48241
48687
  for (const entry of entries) {
48242
- const fullPath = (0, import_path31.join)(currentDir, entry);
48688
+ const fullPath = (0, import_path32.join)(currentDir, entry);
48243
48689
  let stat5;
48244
48690
  try {
48245
- stat5 = (0, import_fs33.statSync)(fullPath);
48691
+ stat5 = (0, import_fs34.statSync)(fullPath);
48246
48692
  } catch {
48247
48693
  continue;
48248
48694
  }
@@ -48258,10 +48704,10 @@ function findSpecFiles(dir) {
48258
48704
  }
48259
48705
  function findImplFilesWithoutTests(implFiles, testFiles) {
48260
48706
  const testBasenames = new Set(
48261
- testFiles.map((f) => (0, import_path31.basename)(f).replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, ""))
48707
+ testFiles.map((f) => (0, import_path32.basename)(f).replace(/\.(test|spec)\.(ts|tsx|js|jsx)$/, ""))
48262
48708
  );
48263
48709
  return implFiles.filter((f) => {
48264
- const base = (0, import_path31.basename)(f).replace(/\.(ts|tsx|js|jsx)$/, "");
48710
+ const base = (0, import_path32.basename)(f).replace(/\.(ts|tsx|js|jsx)$/, "");
48265
48711
  return !testBasenames.has(base);
48266
48712
  });
48267
48713
  }
@@ -48291,8 +48737,8 @@ function runChecks(basePath) {
48291
48737
  const weight2 = 25;
48292
48738
  maxScore += weight2;
48293
48739
  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"));
48740
+ const hasClaudeDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude"));
48741
+ const hasSpecsDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "specs"));
48296
48742
  let specScore = 0;
48297
48743
  if (hasSpecs) specScore += 15;
48298
48744
  if (hasClaudeDir) specScore += 5;
@@ -48311,8 +48757,8 @@ function runChecks(basePath) {
48311
48757
  }
48312
48758
  const weight3 = 15;
48313
48759
  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"));
48760
+ const hasClaudeMd = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "CLAUDE.md"));
48761
+ const hasClaudeSettings = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".claude", "settings.json"));
48316
48762
  let claudeScore = 0;
48317
48763
  if (hasClaudeMd) claudeScore += 10;
48318
48764
  if (hasClaudeSettings) claudeScore += 5;
@@ -48330,9 +48776,9 @@ function runChecks(basePath) {
48330
48776
  }
48331
48777
  const weight4 = 15;
48332
48778
  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"));
48779
+ const hasPackageJson = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "package.json"));
48780
+ const hasReadme = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "README.md"));
48781
+ const hasTsConfig = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, "tsconfig.json"));
48336
48782
  let structureScore = 0;
48337
48783
  if (hasPackageJson) structureScore += 5;
48338
48784
  if (hasReadme) structureScore += 5;
@@ -48352,9 +48798,9 @@ function runChecks(basePath) {
48352
48798
  });
48353
48799
  const weight5 = 15;
48354
48800
  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"));
48801
+ const hasGitDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".git"));
48802
+ const hasGithubDir = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".github"));
48803
+ const hasWorkflows = (0, import_fs34.existsSync)((0, import_path32.join)(basePath, ".github", "workflows"));
48358
48804
  let gitScore = 0;
48359
48805
  if (hasGitDir) gitScore += 5;
48360
48806
  if (hasGithubDir) gitScore += 5;
@@ -48693,8 +49139,8 @@ function createSdlcCommand() {
48693
49139
  spinner.start("Scanning git history and local artifacts...");
48694
49140
  const basePath = process.cwd();
48695
49141
  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"));
49142
+ 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"));
49143
+ 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
49144
  const scanResult = scanDirectory(basePath);
48699
49145
  const hasTests = scanResult.testFiles.length > 0;
48700
49146
  const hasImpl = scanResult.implFiles.length > 0;
@@ -48837,15 +49283,15 @@ function createSdlcCommand() {
48837
49283
  });
48838
49284
  return cmd;
48839
49285
  }
48840
- var import_fs33, import_path31, import_child_process10, IMPL_EXTENSIONS, IGNORE_DIRS, IGNORE_FILES;
49286
+ var import_fs34, import_path32, import_child_process10, IMPL_EXTENSIONS, IGNORE_DIRS, IGNORE_FILES;
48841
49287
  var init_sdlc = __esm({
48842
49288
  "src/commands/sdlc.ts"() {
48843
49289
  "use strict";
48844
49290
  init_esm();
48845
49291
  init_source();
48846
49292
  init_ora();
48847
- import_fs33 = require("fs");
48848
- import_path31 = require("path");
49293
+ import_fs34 = require("fs");
49294
+ import_path32 = require("path");
48849
49295
  import_child_process10 = require("child_process");
48850
49296
  init_config_manager();
48851
49297
  IMPL_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
@@ -48964,10 +49410,10 @@ var init_security = __esm({
48964
49410
 
48965
49411
  // src/commands/status.ts
48966
49412
  function readTermsAcceptance() {
48967
- const configFile = (0, import_path32.join)((0, import_os20.homedir)(), ".gal", "config.json");
49413
+ const configFile = (0, import_path33.join)((0, import_os21.homedir)(), ".gal", "config.json");
48968
49414
  try {
48969
- if ((0, import_fs34.existsSync)(configFile)) {
48970
- const raw = JSON.parse((0, import_fs34.readFileSync)(configFile, "utf-8"));
49415
+ if ((0, import_fs35.existsSync)(configFile)) {
49416
+ const raw = JSON.parse((0, import_fs35.readFileSync)(configFile, "utf-8"));
48971
49417
  if (typeof raw.termsAcceptedAt === "string" && raw.termsAcceptedAt.length > 0) {
48972
49418
  return { accepted: true, acceptedAt: raw.termsAcceptedAt };
48973
49419
  }
@@ -49139,7 +49585,7 @@ function displayStatusJson(result, health) {
49139
49585
  }
49140
49586
  function isRateLimited(projectId) {
49141
49587
  try {
49142
- const raw = (0, import_fs34.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49588
+ const raw = (0, import_fs35.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49143
49589
  const cache = JSON.parse(raw);
49144
49590
  const lastReport = cache[projectId];
49145
49591
  if (lastReport && Date.now() - lastReport < RATE_LIMIT_MS) {
@@ -49153,13 +49599,13 @@ function recordReport(projectId) {
49153
49599
  try {
49154
49600
  let cache = {};
49155
49601
  try {
49156
- const raw = (0, import_fs34.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49602
+ const raw = (0, import_fs35.readFileSync)(DRIFT_REPORT_CACHE_PATH, "utf-8");
49157
49603
  cache = JSON.parse(raw);
49158
49604
  } catch {
49159
49605
  }
49160
49606
  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));
49607
+ (0, import_fs35.mkdirSync)((0, import_path33.join)((0, import_os21.homedir)(), ".gal"), { recursive: true });
49608
+ (0, import_fs35.writeFileSync)(DRIFT_REPORT_CACHE_PATH, JSON.stringify(cache));
49163
49609
  } catch {
49164
49610
  }
49165
49611
  }
@@ -49264,16 +49710,16 @@ function createStatusCommand2() {
49264
49710
  });
49265
49711
  return command;
49266
49712
  }
49267
- var import_path32, import_os20, import_fs34, cliVersion6, defaultApiUrl15, PLATFORM_LABELS2, RATE_LIMIT_MS, DRIFT_REPORT_CACHE_PATH;
49713
+ var import_path33, import_os21, import_fs35, cliVersion6, defaultApiUrl15, PLATFORM_LABELS2, RATE_LIMIT_MS, DRIFT_REPORT_CACHE_PATH;
49268
49714
  var init_status = __esm({
49269
49715
  "src/commands/status.ts"() {
49270
49716
  "use strict";
49271
49717
  init_esm();
49272
49718
  init_source();
49273
49719
  init_ora();
49274
- import_path32 = require("path");
49275
- import_os20 = require("os");
49276
- import_fs34 = require("fs");
49720
+ import_path33 = require("path");
49721
+ import_os21 = require("os");
49722
+ import_fs35 = require("fs");
49277
49723
  init_gal_config_service();
49278
49724
  init_config_manager();
49279
49725
  init_CoreServiceProvider();
@@ -49289,7 +49735,7 @@ var init_status = __esm({
49289
49735
  ])
49290
49736
  );
49291
49737
  RATE_LIMIT_MS = 5 * 60 * 1e3;
49292
- DRIFT_REPORT_CACHE_PATH = (0, import_path32.join)((0, import_os20.homedir)(), ".gal", "drift-report-cache.json");
49738
+ DRIFT_REPORT_CACHE_PATH = (0, import_path33.join)((0, import_os21.homedir)(), ".gal", "drift-report-cache.json");
49293
49739
  }
49294
49740
  });
49295
49741
 
@@ -50617,13 +51063,13 @@ function getGitHookManager() {
50617
51063
  }
50618
51064
  return defaultManager;
50619
51065
  }
50620
- var import_child_process11, import_fs35, import_path33, DEFAULT_GIT_HOOK_CONFIG, GitHookManager, defaultManager;
51066
+ var import_child_process11, import_fs36, import_path34, DEFAULT_GIT_HOOK_CONFIG, GitHookManager, defaultManager;
50621
51067
  var init_git_hooks = __esm({
50622
51068
  "src/triggers/git-hooks.ts"() {
50623
51069
  "use strict";
50624
51070
  import_child_process11 = require("child_process");
50625
- import_fs35 = require("fs");
50626
- import_path33 = require("path");
51071
+ import_fs36 = require("fs");
51072
+ import_path34 = require("path");
50627
51073
  init_source();
50628
51074
  init_triggers();
50629
51075
  DEFAULT_GIT_HOOK_CONFIG = {
@@ -50666,12 +51112,12 @@ var init_git_hooks = __esm({
50666
51112
  if (this.gitDir) return this.gitDir;
50667
51113
  let currentPath = startPath;
50668
51114
  while (currentPath !== "/") {
50669
- const gitPath = (0, import_path33.join)(currentPath, ".git");
50670
- if ((0, import_fs35.existsSync)(gitPath)) {
51115
+ const gitPath = (0, import_path34.join)(currentPath, ".git");
51116
+ if ((0, import_fs36.existsSync)(gitPath)) {
50671
51117
  this.gitDir = gitPath;
50672
51118
  return gitPath;
50673
51119
  }
50674
- currentPath = (0, import_path33.dirname)(currentPath);
51120
+ currentPath = (0, import_path34.dirname)(currentPath);
50675
51121
  }
50676
51122
  return null;
50677
51123
  }
@@ -50681,8 +51127,8 @@ var init_git_hooks = __esm({
50681
51127
  * @param projectPath - The root path of the project; defaults to the current working directory
50682
51128
  * @returns An object containing arrays of installed and skipped hook type names
50683
51129
  */
50684
- installHooks(projectPath = process.cwd()) {
50685
- const gitDir = this.findGitDir(projectPath);
51130
+ installHooks(projectPath2 = process.cwd()) {
51131
+ const gitDir = this.findGitDir(projectPath2);
50686
51132
  if (!gitDir) {
50687
51133
  return {
50688
51134
  installed: [],
@@ -50693,29 +51139,29 @@ var init_git_hooks = __esm({
50693
51139
  ]
50694
51140
  };
50695
51141
  }
50696
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
50697
- if (!(0, import_fs35.existsSync)(hooksDir)) {
50698
- (0, import_fs35.mkdirSync)(hooksDir, { recursive: true });
51142
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
51143
+ if (!(0, import_fs36.existsSync)(hooksDir)) {
51144
+ (0, import_fs36.mkdirSync)(hooksDir, { recursive: true });
50699
51145
  }
50700
51146
  const installed = [];
50701
51147
  const skipped = [];
50702
51148
  const warnings = [];
50703
51149
  for (const hookType of this.config.hooks) {
50704
- const hookPath = (0, import_path33.join)(hooksDir, hookType);
51150
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
50705
51151
  const hookScript = this.generateHookScript(hookType);
50706
- if ((0, import_fs35.existsSync)(hookPath)) {
50707
- const existing = (0, import_fs35.readFileSync)(hookPath, "utf-8");
51152
+ if ((0, import_fs36.existsSync)(hookPath)) {
51153
+ const existing = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50708
51154
  if (existing.includes("GAL_HOOK_MARKER")) {
50709
- (0, import_fs35.writeFileSync)(hookPath, hookScript);
50710
- (0, import_fs35.chmodSync)(hookPath, "755");
51155
+ (0, import_fs36.writeFileSync)(hookPath, hookScript);
51156
+ (0, import_fs36.chmodSync)(hookPath, "755");
50711
51157
  installed.push(hookType);
50712
51158
  } else {
50713
51159
  console.log(source_default.yellow(`Skipping ${hookType}: existing hook found`));
50714
51160
  skipped.push(hookType);
50715
51161
  }
50716
51162
  } else {
50717
- (0, import_fs35.writeFileSync)(hookPath, hookScript);
50718
- (0, import_fs35.chmodSync)(hookPath, "755");
51163
+ (0, import_fs36.writeFileSync)(hookPath, hookScript);
51164
+ (0, import_fs36.chmodSync)(hookPath, "755");
50719
51165
  installed.push(hookType);
50720
51166
  }
50721
51167
  }
@@ -50727,17 +51173,17 @@ var init_git_hooks = __esm({
50727
51173
  * @param projectPath - The root path of the project; defaults to the current working directory
50728
51174
  * @returns An array of hook type names that were successfully removed
50729
51175
  */
50730
- uninstallHooks(projectPath = process.cwd()) {
50731
- const gitDir = this.findGitDir(projectPath);
51176
+ uninstallHooks(projectPath2 = process.cwd()) {
51177
+ const gitDir = this.findGitDir(projectPath2);
50732
51178
  if (!gitDir) {
50733
51179
  return [];
50734
51180
  }
50735
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
51181
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
50736
51182
  const removed = [];
50737
51183
  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");
51184
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
51185
+ if ((0, import_fs36.existsSync)(hookPath)) {
51186
+ const content = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50741
51187
  if (content.includes("GAL_HOOK_MARKER")) {
50742
51188
  const { unlinkSync: unlinkSync6 } = require("fs");
50743
51189
  unlinkSync6(hookPath);
@@ -50955,18 +51401,18 @@ exit 0
50955
51401
  * @param projectPath - The root path of the project; defaults to the current working directory
50956
51402
  * @returns An object with arrays of installed and missing hook type names
50957
51403
  */
50958
- isInstalled(projectPath = process.cwd()) {
50959
- const gitDir = this.findGitDir(projectPath);
51404
+ isInstalled(projectPath2 = process.cwd()) {
51405
+ const gitDir = this.findGitDir(projectPath2);
50960
51406
  if (!gitDir) {
50961
51407
  return { installed: [], missing: this.config.hooks };
50962
51408
  }
50963
- const hooksDir = (0, import_path33.join)(gitDir, "hooks");
51409
+ const hooksDir = (0, import_path34.join)(gitDir, "hooks");
50964
51410
  const installed = [];
50965
51411
  const missing = [];
50966
51412
  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");
51413
+ const hookPath = (0, import_path34.join)(hooksDir, hookType);
51414
+ if ((0, import_fs36.existsSync)(hookPath)) {
51415
+ const content = (0, import_fs36.readFileSync)(hookPath, "utf-8");
50970
51416
  if (content.includes("GAL_HOOK_MARKER")) {
50971
51417
  installed.push(hookType);
50972
51418
  } else {
@@ -50990,12 +51436,12 @@ function getFileWatcher() {
50990
51436
  }
50991
51437
  return defaultWatcher;
50992
51438
  }
50993
- var import_fs36, import_path34, DEFAULT_FILE_WATCHER_CONFIG, AGENT_CONFIG_PATTERNS, FileWatcher, defaultWatcher;
51439
+ var import_fs37, import_path35, DEFAULT_FILE_WATCHER_CONFIG, AGENT_CONFIG_PATTERNS, FileWatcher, defaultWatcher;
50994
51440
  var init_file_watcher = __esm({
50995
51441
  "src/triggers/file-watcher.ts"() {
50996
51442
  "use strict";
50997
- import_fs36 = require("fs");
50998
- import_path34 = require("path");
51443
+ import_fs37 = require("fs");
51444
+ import_path35 = require("path");
50999
51445
  init_source();
51000
51446
  init_triggers();
51001
51447
  DEFAULT_FILE_WATCHER_CONFIG = {
@@ -51051,13 +51497,13 @@ var init_file_watcher = __esm({
51051
51497
  const watching = [];
51052
51498
  const notFound = [];
51053
51499
  for (const watchPath of this.config.watchPaths) {
51054
- const fullPath = (0, import_path34.join)(basePath, watchPath);
51055
- if (!(0, import_fs36.existsSync)(fullPath)) {
51500
+ const fullPath = (0, import_path35.join)(basePath, watchPath);
51501
+ if (!(0, import_fs37.existsSync)(fullPath)) {
51056
51502
  notFound.push(watchPath);
51057
51503
  continue;
51058
51504
  }
51059
51505
  try {
51060
- const watcher = (0, import_fs36.watch)(
51506
+ const watcher = (0, import_fs37.watch)(
51061
51507
  fullPath,
51062
51508
  { recursive: this.config.recursive },
51063
51509
  (eventType, filename) => {
@@ -51104,7 +51550,7 @@ var init_file_watcher = __esm({
51104
51550
  * @returns True if the file matches any ignore pattern and should be skipped
51105
51551
  */
51106
51552
  shouldIgnore(filename) {
51107
- const name = (0, import_path34.basename)(filename);
51553
+ const name = (0, import_path35.basename)(filename);
51108
51554
  for (const pattern of this.config.ignorePatterns) {
51109
51555
  if (pattern.startsWith("*")) {
51110
51556
  if (name.endsWith(pattern.slice(1))) {
@@ -51130,7 +51576,7 @@ var init_file_watcher = __esm({
51130
51576
  * @param filename - The name of the file that changed
51131
51577
  */
51132
51578
  handleFileEvent(eventType, watchPath, filename) {
51133
- const fullPath = (0, import_path34.join)(watchPath, filename);
51579
+ const fullPath = (0, import_path35.join)(watchPath, filename);
51134
51580
  const debounceKey = `${eventType}:${fullPath}`;
51135
51581
  const existingTimer = this.debounceTimers.get(debounceKey);
51136
51582
  if (existingTimer) {
@@ -51150,13 +51596,13 @@ var init_file_watcher = __esm({
51150
51596
  * @param filename - The name of the file that changed
51151
51597
  */
51152
51598
  async processFileEvent(eventType, watchPath, filename) {
51153
- const fullPath = (0, import_path34.join)(watchPath, filename);
51599
+ const fullPath = (0, import_path35.join)(watchPath, filename);
51154
51600
  let fsEventType;
51155
51601
  let isDirectory = false;
51156
51602
  let size;
51157
51603
  try {
51158
- if ((0, import_fs36.existsSync)(fullPath)) {
51159
- const stats = (0, import_fs36.statSync)(fullPath);
51604
+ if ((0, import_fs37.existsSync)(fullPath)) {
51605
+ const stats = (0, import_fs37.statSync)(fullPath);
51160
51606
  isDirectory = stats.isDirectory();
51161
51607
  size = stats.size;
51162
51608
  fsEventType = eventType === "rename" ? "create" : "modify";
@@ -51301,12 +51747,12 @@ var init_file_watcher = __esm({
51301
51747
  this.config.watchPaths.push(path8);
51302
51748
  return true;
51303
51749
  }
51304
- const fullPath = (0, import_path34.join)(basePath, path8);
51305
- if (!(0, import_fs36.existsSync)(fullPath)) {
51750
+ const fullPath = (0, import_path35.join)(basePath, path8);
51751
+ if (!(0, import_fs37.existsSync)(fullPath)) {
51306
51752
  return false;
51307
51753
  }
51308
51754
  try {
51309
- const watcher = (0, import_fs36.watch)(
51755
+ const watcher = (0, import_fs37.watch)(
51310
51756
  fullPath,
51311
51757
  { recursive: this.config.recursive },
51312
51758
  (eventType, filename) => {
@@ -51619,9 +52065,9 @@ async function confirm(message) {
51619
52065
  });
51620
52066
  }
51621
52067
  function isGalCreatedFile(filePath) {
51622
- if (!(0, import_fs37.existsSync)(filePath)) return false;
52068
+ if (!(0, import_fs38.existsSync)(filePath)) return false;
51623
52069
  try {
51624
- const content = (0, import_fs37.readFileSync)(filePath, "utf-8");
52070
+ const content = (0, import_fs38.readFileSync)(filePath, "utf-8");
51625
52071
  const galMarkers = [
51626
52072
  "GAL Config",
51627
52073
  "GAL CLI",
@@ -51641,9 +52087,9 @@ function isGalCreatedFile(filePath) {
51641
52087
  }
51642
52088
  }
51643
52089
  function isNpmInstalledFile(filePath) {
51644
- if (!(0, import_fs37.existsSync)(filePath)) return false;
52090
+ if (!(0, import_fs38.existsSync)(filePath)) return false;
51645
52091
  try {
51646
- const content = (0, import_fs37.readFileSync)(filePath, "utf-8");
52092
+ const content = (0, import_fs38.readFileSync)(filePath, "utf-8");
51647
52093
  return content.includes("CURRENT_VERSION =") || content.includes("const CURRENT_VERSION");
51648
52094
  } catch {
51649
52095
  return false;
@@ -51660,15 +52106,15 @@ function detectFileSource(filePath) {
51660
52106
  }
51661
52107
  function detectUserLevelItems(options) {
51662
52108
  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");
52109
+ const claudeDir = (0, import_path36.join)((0, import_os22.homedir)(), ".claude");
52110
+ const claudeHooksDir = (0, import_path36.join)(claudeDir, "hooks");
52111
+ const statusLinesDir = (0, import_path36.join)(claudeDir, "status_lines");
51666
52112
  const includeNpm = options?.includeNpmInstalled ?? true;
51667
- if ((0, import_fs37.existsSync)(claudeHooksDir)) {
51668
- const files = (0, import_fs37.readdirSync)(claudeHooksDir);
52113
+ if ((0, import_fs38.existsSync)(claudeHooksDir)) {
52114
+ const files = (0, import_fs38.readdirSync)(claudeHooksDir);
51669
52115
  for (const file of files) {
51670
52116
  if (file.startsWith("gal-")) {
51671
- const filePath = (0, import_path35.join)(claudeHooksDir, file);
52117
+ const filePath = (0, import_path36.join)(claudeHooksDir, file);
51672
52118
  const source = detectFileSource(filePath);
51673
52119
  if (!includeNpm && source === "npm") {
51674
52120
  continue;
@@ -51683,11 +52129,11 @@ function detectUserLevelItems(options) {
51683
52129
  }
51684
52130
  }
51685
52131
  }
51686
- if ((0, import_fs37.existsSync)(statusLinesDir)) {
51687
- const files = (0, import_fs37.readdirSync)(statusLinesDir);
52132
+ if ((0, import_fs38.existsSync)(statusLinesDir)) {
52133
+ const files = (0, import_fs38.readdirSync)(statusLinesDir);
51688
52134
  for (const file of files) {
51689
52135
  if (file.startsWith("gal-")) {
51690
- const filePath = (0, import_path35.join)(statusLinesDir, file);
52136
+ const filePath = (0, import_path36.join)(statusLinesDir, file);
51691
52137
  const source = detectFileSource(filePath);
51692
52138
  if (!includeNpm && source === "npm") {
51693
52139
  continue;
@@ -51702,10 +52148,10 @@ function detectUserLevelItems(options) {
51702
52148
  }
51703
52149
  }
51704
52150
  }
51705
- const claudeSettingsPath = (0, import_path35.join)(claudeDir, "settings.json");
51706
- if ((0, import_fs37.existsSync)(claudeSettingsPath)) {
52151
+ const claudeSettingsPath = (0, import_path36.join)(claudeDir, "settings.json");
52152
+ if ((0, import_fs38.existsSync)(claudeSettingsPath)) {
51707
52153
  try {
51708
- const settings = JSON.parse((0, import_fs37.readFileSync)(claudeSettingsPath, "utf-8"));
52154
+ const settings = JSON.parse((0, import_fs38.readFileSync)(claudeSettingsPath, "utf-8"));
51709
52155
  if (settings.hooks?.SessionStart) {
51710
52156
  const hasGalHooks = settings.hooks.SessionStart.some(
51711
52157
  (entry) => entry.hooks?.some(
@@ -51752,14 +52198,14 @@ function detectUserLevelItems(options) {
51752
52198
  } catch {
51753
52199
  }
51754
52200
  }
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);
52201
+ const cursorDir = (0, import_path36.join)((0, import_os22.homedir)(), ".cursor");
52202
+ const cursorHooksDir = (0, import_path36.join)(cursorDir, "hooks");
52203
+ if ((0, import_fs38.existsSync)(cursorHooksDir)) {
52204
+ const files = (0, import_fs38.readdirSync)(cursorHooksDir);
51759
52205
  for (const file of files) {
51760
52206
  if (file.startsWith("gal-")) {
51761
52207
  items.push({
51762
- path: (0, import_path35.join)(cursorHooksDir, file),
52208
+ path: (0, import_path36.join)(cursorHooksDir, file),
51763
52209
  type: "file",
51764
52210
  reason: "GAL hook file for Cursor IDE",
51765
52211
  isGalOwned: true
@@ -51767,10 +52213,10 @@ function detectUserLevelItems(options) {
51767
52213
  }
51768
52214
  }
51769
52215
  }
51770
- const cursorHooksJsonPath = (0, import_path35.join)(cursorDir, "hooks.json");
51771
- if ((0, import_fs37.existsSync)(cursorHooksJsonPath)) {
52216
+ const cursorHooksJsonPath = (0, import_path36.join)(cursorDir, "hooks.json");
52217
+ if ((0, import_fs38.existsSync)(cursorHooksJsonPath)) {
51772
52218
  try {
51773
- const hooksConfig = JSON.parse((0, import_fs37.readFileSync)(cursorHooksJsonPath, "utf-8"));
52219
+ const hooksConfig = JSON.parse((0, import_fs38.readFileSync)(cursorHooksJsonPath, "utf-8"));
51774
52220
  const hookTypes = ["beforeShellExecution", "beforeSubmitPrompt"];
51775
52221
  for (const hookType of hookTypes) {
51776
52222
  if (hooksConfig.hooks?.[hookType]) {
@@ -51796,8 +52242,8 @@ function detectUserLevelItems(options) {
51796
52242
  }
51797
52243
  function detectProjectLevelItems(directory) {
51798
52244
  const items = [];
51799
- const galDir = (0, import_path35.join)(directory, ".gal");
51800
- if ((0, import_fs37.existsSync)(galDir)) {
52245
+ const galDir = (0, import_path36.join)(directory, ".gal");
52246
+ if ((0, import_fs38.existsSync)(galDir)) {
51801
52247
  items.push({
51802
52248
  path: galDir,
51803
52249
  type: "directory",
@@ -51805,8 +52251,8 @@ function detectProjectLevelItems(directory) {
51805
52251
  isGalOwned: true
51806
52252
  });
51807
52253
  }
51808
- const galConfig = (0, import_path35.join)(directory, "gal.config.json");
51809
- if ((0, import_fs37.existsSync)(galConfig)) {
52254
+ const galConfig = (0, import_path36.join)(directory, "gal.config.json");
52255
+ if ((0, import_fs38.existsSync)(galConfig)) {
51810
52256
  items.push({
51811
52257
  path: galConfig,
51812
52258
  type: "file",
@@ -51815,11 +52261,11 @@ function detectProjectLevelItems(directory) {
51815
52261
  });
51816
52262
  }
51817
52263
  const gitHookPaths = [
51818
- (0, import_path35.join)(directory, ".git", "hooks", "pre-commit"),
51819
- (0, import_path35.join)(directory, ".husky", "pre-commit")
52264
+ (0, import_path36.join)(directory, ".git", "hooks", "pre-commit"),
52265
+ (0, import_path36.join)(directory, ".husky", "pre-commit")
51820
52266
  ];
51821
52267
  for (const hookPath of gitHookPaths) {
51822
- if ((0, import_fs37.existsSync)(hookPath) && isGalCreatedFile(hookPath)) {
52268
+ if ((0, import_fs38.existsSync)(hookPath) && isGalCreatedFile(hookPath)) {
51823
52269
  items.push({
51824
52270
  path: hookPath,
51825
52271
  type: "file",
@@ -51829,18 +52275,18 @@ function detectProjectLevelItems(directory) {
51829
52275
  }
51830
52276
  }
51831
52277
  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" }
52278
+ { path: (0, import_path36.join)(directory, "CLAUDE.md"), reason: "GAL-generated CLAUDE.md" },
52279
+ { path: (0, import_path36.join)(directory, ".claude", "settings.json"), reason: "GAL-generated settings" },
52280
+ { path: (0, import_path36.join)(directory, ".claude", "commands", "review.md"), reason: "GAL-generated command" },
52281
+ { path: (0, import_path36.join)(directory, ".claude", "commands", "check.md"), reason: "GAL-generated command" },
52282
+ { path: (0, import_path36.join)(directory, ".github", "workflows", "ci.yml"), reason: "GAL-generated workflow" },
52283
+ { path: (0, import_path36.join)(directory, ".github", "workflows", "pr-governance.yml"), reason: "GAL-generated workflow" },
52284
+ { path: (0, import_path36.join)(directory, ".gitleaks.toml"), reason: "GAL-generated security config" },
52285
+ { path: (0, import_path36.join)(directory, "SECURITY.md"), reason: "GAL-generated security docs" },
52286
+ { path: (0, import_path36.join)(directory, ".env.example"), reason: "GAL-generated env template" }
51841
52287
  ];
51842
52288
  for (const { path: path8, reason } of setupFiles) {
51843
- if ((0, import_fs37.existsSync)(path8) && isGalCreatedFile(path8)) {
52289
+ if ((0, import_fs38.existsSync)(path8) && isGalCreatedFile(path8)) {
51844
52290
  items.push({
51845
52291
  path: path8,
51846
52292
  type: "file",
@@ -51853,12 +52299,12 @@ function detectProjectLevelItems(directory) {
51853
52299
  }
51854
52300
  function removeGalStatusLineEntry(settingsPath) {
51855
52301
  try {
51856
- const settings = JSON.parse((0, import_fs37.readFileSync)(settingsPath, "utf-8"));
52302
+ const settings = JSON.parse((0, import_fs38.readFileSync)(settingsPath, "utf-8"));
51857
52303
  if (!settings.statusLine?.command?.includes("gal-")) {
51858
52304
  return false;
51859
52305
  }
51860
52306
  delete settings.statusLine;
51861
- (0, import_fs37.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
52307
+ (0, import_fs38.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
51862
52308
  return true;
51863
52309
  } catch {
51864
52310
  return false;
@@ -51866,7 +52312,7 @@ function removeGalStatusLineEntry(settingsPath) {
51866
52312
  }
51867
52313
  function removeGalHookEntries(settingsPath) {
51868
52314
  try {
51869
- const settings = JSON.parse((0, import_fs37.readFileSync)(settingsPath, "utf-8"));
52315
+ const settings = JSON.parse((0, import_fs38.readFileSync)(settingsPath, "utf-8"));
51870
52316
  let modified = false;
51871
52317
  for (const hookEvent of ["SessionStart", "UserPromptSubmit"]) {
51872
52318
  if (!settings.hooks?.[hookEvent]) continue;
@@ -51889,7 +52335,7 @@ function removeGalHookEntries(settingsPath) {
51889
52335
  delete settings.hooks;
51890
52336
  }
51891
52337
  if (modified) {
51892
- (0, import_fs37.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
52338
+ (0, import_fs38.writeFileSync)(settingsPath, JSON.stringify(settings, null, 2));
51893
52339
  return true;
51894
52340
  }
51895
52341
  return false;
@@ -51899,7 +52345,7 @@ function removeGalHookEntries(settingsPath) {
51899
52345
  }
51900
52346
  function removeGalCursorHookEntries(hooksJsonPath) {
51901
52347
  try {
51902
- const hooksConfig = JSON.parse((0, import_fs37.readFileSync)(hooksJsonPath, "utf-8"));
52348
+ const hooksConfig = JSON.parse((0, import_fs38.readFileSync)(hooksJsonPath, "utf-8"));
51903
52349
  if (!hooksConfig.hooks) {
51904
52350
  return false;
51905
52351
  }
@@ -51923,7 +52369,7 @@ function removeGalCursorHookEntries(hooksJsonPath) {
51923
52369
  delete hooksConfig.hooks;
51924
52370
  }
51925
52371
  if (modified) {
51926
- (0, import_fs37.writeFileSync)(hooksJsonPath, JSON.stringify(hooksConfig, null, 2));
52372
+ (0, import_fs38.writeFileSync)(hooksJsonPath, JSON.stringify(hooksConfig, null, 2));
51927
52373
  return true;
51928
52374
  }
51929
52375
  return false;
@@ -51958,10 +52404,10 @@ function performUninstall(items, dryRun) {
51958
52404
  result.skipped.push(`${item.path} (no GAL statusLine found)`);
51959
52405
  }
51960
52406
  } else if (item.type === "directory") {
51961
- (0, import_fs37.rmSync)(item.path, { recursive: true, force: true });
52407
+ (0, import_fs38.rmSync)(item.path, { recursive: true, force: true });
51962
52408
  result.removed.push(item.path);
51963
52409
  } else {
51964
- (0, import_fs37.unlinkSync)(item.path);
52410
+ (0, import_fs38.unlinkSync)(item.path);
51965
52411
  result.removed.push(item.path);
51966
52412
  }
51967
52413
  } catch (error2) {
@@ -52057,15 +52503,15 @@ function createUninstallCommand() {
52057
52503
  });
52058
52504
  return command;
52059
52505
  }
52060
- var import_fs37, import_path35, import_os21, import_readline4;
52506
+ var import_fs38, import_path36, import_os22, import_readline4;
52061
52507
  var init_uninstall = __esm({
52062
52508
  "src/commands/uninstall.ts"() {
52063
52509
  "use strict";
52064
52510
  init_esm();
52065
52511
  init_source();
52066
- import_fs37 = require("fs");
52067
- import_path35 = require("path");
52068
- import_os21 = require("os");
52512
+ import_fs38 = require("fs");
52513
+ import_path36 = require("path");
52514
+ import_os22 = require("os");
52069
52515
  import_readline4 = require("readline");
52070
52516
  }
52071
52517
  });
@@ -52113,10 +52559,10 @@ ${source_default.cyan("/" + command.id)}`);
52113
52559
  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
52560
  const spinner = ora("Installing universal commands...").start();
52115
52561
  try {
52116
- const projectPath = options.path;
52562
+ const projectPath2 = options.path;
52117
52563
  const platforms = options.platforms ? SUPPORTED_PLATFORMS.filter(
52118
52564
  (p) => options.platforms.includes(p.id)
52119
- ) : detectPlatforms2(projectPath).filter((p) => p.detected);
52565
+ ) : detectPlatforms2(projectPath2).filter((p) => p.detected);
52120
52566
  if (platforms.length === 0) {
52121
52567
  spinner.fail(source_default.yellow("No platforms detected"));
52122
52568
  console.log(
@@ -52134,7 +52580,7 @@ ${source_default.cyan("/" + command.id)}`);
52134
52580
  for (const command of commands) {
52135
52581
  if (!command.platforms.includes(platform5.id)) continue;
52136
52582
  const commandPath = path6.join(
52137
- projectPath,
52583
+ projectPath2,
52138
52584
  platform5.commandsPath,
52139
52585
  `${command.id}.md`
52140
52586
  );
@@ -52168,8 +52614,8 @@ ${source_default.cyan("/" + command.id)}`);
52168
52614
  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
52615
  const spinner = ora("Syncing commands...").start();
52170
52616
  try {
52171
- const projectPath = options.path;
52172
- const platforms = detectPlatforms2(projectPath).filter(
52617
+ const projectPath2 = options.path;
52618
+ const platforms = detectPlatforms2(projectPath2).filter(
52173
52619
  (p) => p.detected
52174
52620
  );
52175
52621
  if (platforms.length < 2) {
@@ -52180,7 +52626,7 @@ ${source_default.cyan("/" + command.id)}`);
52180
52626
  }
52181
52627
  const sourcePlatform = platforms[0];
52182
52628
  const sourceDir = path6.join(
52183
- projectPath,
52629
+ projectPath2,
52184
52630
  sourcePlatform.commandsPath
52185
52631
  );
52186
52632
  if (!fs6.existsSync(sourceDir)) {
@@ -52191,7 +52637,7 @@ ${source_default.cyan("/" + command.id)}`);
52191
52637
  let synced = 0;
52192
52638
  const wouldSync = [];
52193
52639
  for (const platform5 of platforms.slice(1)) {
52194
- const targetDir = path6.join(projectPath, platform5.commandsPath);
52640
+ const targetDir = path6.join(projectPath2, platform5.commandsPath);
52195
52641
  if (!options.dryRun) {
52196
52642
  fs6.mkdirSync(targetDir, { recursive: true });
52197
52643
  }
@@ -52277,10 +52723,10 @@ Describe what the AI should do when this command is invoked.
52277
52723
  );
52278
52724
  return cmd;
52279
52725
  }
52280
- function detectPlatforms2(projectPath) {
52726
+ function detectPlatforms2(projectPath2) {
52281
52727
  return SUPPORTED_PLATFORMS.map((platform5) => ({
52282
52728
  ...platform5,
52283
- detected: fs6.existsSync(path6.join(projectPath, platform5.configPath)) || fs6.existsSync(path6.join(projectPath, platform5.commandsPath))
52729
+ detected: fs6.existsSync(path6.join(projectPath2, platform5.configPath)) || fs6.existsSync(path6.join(projectPath2, platform5.commandsPath))
52284
52730
  }));
52285
52731
  }
52286
52732
  var fs6, path6, SUPPORTED_PLATFORMS, UNIVERSAL_COMMANDS;
@@ -52483,27 +52929,27 @@ function compareVersions(v1, v2) {
52483
52929
  }
52484
52930
  function acquireLock() {
52485
52931
  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 });
52932
+ const galDir = (0, import_path37.join)((0, import_os23.homedir)(), ".gal");
52933
+ if (!(0, import_fs39.existsSync)(galDir)) {
52934
+ (0, import_fs39.mkdirSync)(galDir, { recursive: true });
52489
52935
  }
52490
- if ((0, import_fs38.existsSync)(UPDATE_LOCK_FILE)) {
52936
+ if ((0, import_fs39.existsSync)(UPDATE_LOCK_FILE)) {
52491
52937
  try {
52492
- const lockContent = (0, import_fs38.readFileSync)(UPDATE_LOCK_FILE, "utf-8");
52938
+ const lockContent = (0, import_fs39.readFileSync)(UPDATE_LOCK_FILE, "utf-8");
52493
52939
  const lockTime = parseInt(lockContent, 10);
52494
52940
  if (Number.isNaN(lockTime) || Date.now() - lockTime > 5 * 60 * 1e3) {
52495
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52941
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52496
52942
  } else {
52497
52943
  return false;
52498
52944
  }
52499
52945
  } catch {
52500
52946
  try {
52501
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52947
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52502
52948
  } catch {
52503
52949
  }
52504
52950
  }
52505
52951
  }
52506
- (0, import_fs38.writeFileSync)(UPDATE_LOCK_FILE, String(Date.now()), { flag: "wx" });
52952
+ (0, import_fs39.writeFileSync)(UPDATE_LOCK_FILE, String(Date.now()), { flag: "wx" });
52507
52953
  return true;
52508
52954
  } catch {
52509
52955
  return false;
@@ -52511,8 +52957,8 @@ function acquireLock() {
52511
52957
  }
52512
52958
  function releaseLock() {
52513
52959
  try {
52514
- if ((0, import_fs38.existsSync)(UPDATE_LOCK_FILE)) {
52515
- (0, import_fs38.unlinkSync)(UPDATE_LOCK_FILE);
52960
+ if ((0, import_fs39.existsSync)(UPDATE_LOCK_FILE)) {
52961
+ (0, import_fs39.unlinkSync)(UPDATE_LOCK_FILE);
52516
52962
  }
52517
52963
  } catch {
52518
52964
  }
@@ -52623,7 +53069,7 @@ Retry manually with: ${source_default.cyan(installCommand)}`);
52623
53069
  });
52624
53070
  return command;
52625
53071
  }
52626
- var import_https, import_child_process12, import_fs38, import_path36, import_os22, UPDATE_LOCK_FILE, cliVersion7, REGISTRY_URL;
53072
+ var import_https, import_child_process12, import_fs39, import_path37, import_os23, UPDATE_LOCK_FILE, cliVersion7, REGISTRY_URL;
52627
53073
  var init_update = __esm({
52628
53074
  "src/commands/update.ts"() {
52629
53075
  "use strict";
@@ -52632,14 +53078,14 @@ var init_update = __esm({
52632
53078
  init_ora();
52633
53079
  import_https = __toESM(require("https"), 1);
52634
53080
  import_child_process12 = require("child_process");
52635
- import_fs38 = require("fs");
52636
- import_path36 = require("path");
52637
- import_os22 = require("os");
53081
+ import_fs39 = require("fs");
53082
+ import_path37 = require("path");
53083
+ import_os23 = require("os");
52638
53084
  init_constants();
52639
53085
  init_path_conflict();
52640
53086
  init_install();
52641
53087
  init_telemetry();
52642
- UPDATE_LOCK_FILE = (0, import_path36.join)((0, import_os22.homedir)(), ".gal", "update.lock");
53088
+ UPDATE_LOCK_FILE = (0, import_path37.join)((0, import_os23.homedir)(), ".gal", "update.lock");
52643
53089
  cliVersion7 = constants_default[0];
52644
53090
  REGISTRY_URL = getRegistryUrl();
52645
53091
  }
@@ -53147,9 +53593,9 @@ function createWorkflowCommand() {
53147
53593
  const apiUrl = process.env.GAL_API_URL || defaultApiUrl17;
53148
53594
  try {
53149
53595
  const spinner = ora(`Reading ${filePath}...`).start();
53150
- const absolutePath = import_path37.default.resolve(filePath);
53596
+ const absolutePath = import_path38.default.resolve(filePath);
53151
53597
  const content = await import_promises9.default.readFile(absolutePath, "utf-8");
53152
- const fileName = import_path37.default.basename(filePath);
53598
+ const fileName = import_path38.default.basename(filePath);
53153
53599
  let type = options.type;
53154
53600
  if (!type) {
53155
53601
  if (fileName.endsWith(".md")) {
@@ -53205,7 +53651,7 @@ function createWorkflowCommand() {
53205
53651
  spinner.fail(source_default.red("No organization found. Please connect GitHub via dashboard or use --org flag"));
53206
53652
  process.exit(1);
53207
53653
  }
53208
- const dirPath = import_path37.default.resolve(directory);
53654
+ const dirPath = import_path38.default.resolve(directory);
53209
53655
  const files = await import_promises9.default.readdir(dirPath);
53210
53656
  const workflowFiles = files.filter(
53211
53657
  (f) => f.endsWith(".md") || f.includes("hook") && (f.endsWith(".json") || f.endsWith(".py") || f.endsWith(".js"))
@@ -53217,7 +53663,7 @@ function createWorkflowCommand() {
53217
53663
  spinner.text = `Found ${workflowFiles.length} workflow files. Preparing batch test...`;
53218
53664
  const requests = [];
53219
53665
  for (const file of workflowFiles) {
53220
- const filePath = import_path37.default.join(dirPath, file);
53666
+ const filePath = import_path38.default.join(dirPath, file);
53221
53667
  const content = await import_promises9.default.readFile(filePath, "utf-8");
53222
53668
  const type = file.endsWith(".md") ? "command" : "hook";
53223
53669
  requests.push({
@@ -53315,7 +53761,7 @@ function displayTestResult(result) {
53315
53761
  }
53316
53762
  console.log();
53317
53763
  }
53318
- var import_promises9, import_path37, defaultApiUrl17;
53764
+ var import_promises9, import_path38, defaultApiUrl17;
53319
53765
  var init_workflow2 = __esm({
53320
53766
  "src/commands/workflow.ts"() {
53321
53767
  "use strict";
@@ -53323,7 +53769,7 @@ var init_workflow2 = __esm({
53323
53769
  init_source();
53324
53770
  init_ora();
53325
53771
  import_promises9 = __toESM(require("fs/promises"), 1);
53326
- import_path37 = __toESM(require("path"), 1);
53772
+ import_path38 = __toESM(require("path"), 1);
53327
53773
  init_constants();
53328
53774
  init_client();
53329
53775
  defaultApiUrl17 = constants_default[1];
@@ -53548,6 +53994,7 @@ var init_command_registry = __esm({
53548
53994
  init_quality();
53549
53995
  init_queue_seed();
53550
53996
  init_run();
53997
+ init_run_design();
53551
53998
  init_scan();
53552
53999
  init_sandbox_profiles();
53553
54000
  init_sandbox();
@@ -53596,6 +54043,7 @@ var init_command_registry = __esm({
53596
54043
  { name: "quality", create: createQualityCommand },
53597
54044
  { name: "queue", create: createQueueCommand },
53598
54045
  { name: "run", create: createRunCommand },
54046
+ { name: "run-design", create: createRunDesignCommand },
53599
54047
  { name: "scan", create: createScanCommand },
53600
54048
  { name: "sandbox", create: createSandboxCommand },
53601
54049
  { name: "sandbox-profiles", create: createSandboxProfilesCommand },
@@ -53647,11 +54095,11 @@ function getRegistryAuthToken2() {
53647
54095
  return void 0;
53648
54096
  }
53649
54097
  try {
53650
- const npmrcPath = (0, import_path38.join)((0, import_os23.homedir)(), ".npmrc");
53651
- if (!(0, import_fs39.existsSync)(npmrcPath)) {
54098
+ const npmrcPath = (0, import_path39.join)((0, import_os24.homedir)(), ".npmrc");
54099
+ if (!(0, import_fs40.existsSync)(npmrcPath)) {
53652
54100
  return void 0;
53653
54101
  }
53654
- const npmrc = (0, import_fs39.readFileSync)(npmrcPath, "utf-8");
54102
+ const npmrc = (0, import_fs40.readFileSync)(npmrcPath, "utf-8");
53655
54103
  const escapedHost = REGISTRY_HOST.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53656
54104
  const match = npmrc.match(
53657
54105
  new RegExp(`^//${escapedHost}/:_authToken=(.+)$`, "m")
@@ -53680,8 +54128,8 @@ function compareVersions2(v1, v2) {
53680
54128
  }
53681
54129
  function readUpdateCache() {
53682
54130
  try {
53683
- if ((0, import_fs39.existsSync)(UPDATE_CACHE_FILE)) {
53684
- return JSON.parse((0, import_fs39.readFileSync)(UPDATE_CACHE_FILE, "utf-8"));
54131
+ if ((0, import_fs40.existsSync)(UPDATE_CACHE_FILE)) {
54132
+ return JSON.parse((0, import_fs40.readFileSync)(UPDATE_CACHE_FILE, "utf-8"));
53685
54133
  }
53686
54134
  } catch {
53687
54135
  }
@@ -53689,10 +54137,10 @@ function readUpdateCache() {
53689
54137
  }
53690
54138
  function writeUpdateCache(cache) {
53691
54139
  try {
53692
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53693
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54140
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54141
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53694
54142
  }
53695
- (0, import_fs39.writeFileSync)(UPDATE_CACHE_FILE, JSON.stringify(cache));
54143
+ (0, import_fs40.writeFileSync)(UPDATE_CACHE_FILE, JSON.stringify(cache));
53696
54144
  } catch {
53697
54145
  }
53698
54146
  }
@@ -53742,8 +54190,8 @@ function checkForUpdates() {
53742
54190
  const autoUpdateDisabled = process.env.GAL_NO_AUTO_UPDATE === "1" || process.env.CI === "true";
53743
54191
  if (!isUpdateCommand && !autoUpdateDisabled) {
53744
54192
  try {
53745
- const lockFile = (0, import_path38.join)((0, import_os23.homedir)(), ".gal", "update.lock");
53746
- if (!(0, import_fs39.existsSync)(lockFile)) {
54193
+ const lockFile = (0, import_path39.join)((0, import_os24.homedir)(), ".gal", "update.lock");
54194
+ if (!(0, import_fs40.existsSync)(lockFile)) {
53747
54195
  const child = (0, import_child_process13.spawn)("gal", ["update"], {
53748
54196
  detached: true,
53749
54197
  stdio: "ignore",
@@ -53792,9 +54240,9 @@ function checkForUpdates() {
53792
54240
  function checkPathConflicts() {
53793
54241
  try {
53794
54242
  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"));
54243
+ const CONFLICT_CACHE = (0, import_path39.join)(UPDATE_CACHE_DIR, "path-conflict-cache.json");
54244
+ if ((0, import_fs40.existsSync)(CONFLICT_CACHE)) {
54245
+ const cached = JSON.parse((0, import_fs40.readFileSync)(CONFLICT_CACHE, "utf-8"));
53798
54246
  if (Date.now() - (cached.lastCheck || 0) < ONE_DAY) {
53799
54247
  if (cached.hasConflict) {
53800
54248
  process.on("exit", () => {
@@ -53808,10 +54256,10 @@ function checkPathConflicts() {
53808
54256
  const conflict = detectPathConflict(cliVersion9);
53809
54257
  const cacheData = { lastCheck: Date.now(), hasConflict: !!conflict };
53810
54258
  try {
53811
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53812
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54259
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54260
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53813
54261
  }
53814
- (0, import_fs39.writeFileSync)(CONFLICT_CACHE, JSON.stringify(cacheData));
54262
+ (0, import_fs40.writeFileSync)(CONFLICT_CACHE, JSON.stringify(cacheData));
53815
54263
  } catch {
53816
54264
  }
53817
54265
  if (conflict) {
@@ -53824,9 +54272,9 @@ function checkPathConflicts() {
53824
54272
  }
53825
54273
  function refreshOrgMemberships() {
53826
54274
  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"));
54275
+ const configPath = (0, import_path39.join)((0, import_os24.homedir)(), ".gal", "config.json");
54276
+ if (!(0, import_fs40.existsSync)(configPath)) return;
54277
+ const config = JSON.parse((0, import_fs40.readFileSync)(configPath, "utf-8"));
53830
54278
  if (!config.authToken) return;
53831
54279
  const checkedAt = config.orgMembershipsCheckedAt || 0;
53832
54280
  if (Date.now() - checkedAt < ONE_DAY) return;
@@ -53854,10 +54302,10 @@ function refreshOrgMemberships() {
53854
54302
  const isInternal = user.isInternal === true;
53855
54303
  config.internalOrgs = isInternal ? user.organizations : [];
53856
54304
  config.internalOrgsCheckedAt = Date.now();
53857
- if (!(0, import_fs39.existsSync)(UPDATE_CACHE_DIR)) {
53858
- (0, import_fs39.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
54305
+ if (!(0, import_fs40.existsSync)(UPDATE_CACHE_DIR)) {
54306
+ (0, import_fs40.mkdirSync)(UPDATE_CACHE_DIR, { recursive: true });
53859
54307
  }
53860
- (0, import_fs39.writeFileSync)(configPath, JSON.stringify(config, null, 2));
54308
+ (0, import_fs40.writeFileSync)(configPath, JSON.stringify(config, null, 2));
53861
54309
  }
53862
54310
  } catch {
53863
54311
  }
@@ -53884,11 +54332,11 @@ function refreshOrgMemberships() {
53884
54332
  if (res.statusCode !== 200) return;
53885
54333
  const flags = JSON.parse(data);
53886
54334
  if (flags.orgAudienceTierMap) {
53887
- const freshConfig = JSON.parse((0, import_fs39.readFileSync)(configPath, "utf-8"));
54335
+ const freshConfig = JSON.parse((0, import_fs40.readFileSync)(configPath, "utf-8"));
53888
54336
  freshConfig.orgAudienceTierMap = flags.orgAudienceTierMap;
53889
54337
  freshConfig.orgPlanMap = flags.orgPlanMap || freshConfig.orgPlanMap || {};
53890
54338
  freshConfig.flagsCachedAt = Date.now();
53891
- (0, import_fs39.writeFileSync)(configPath, JSON.stringify(freshConfig, null, 2));
54339
+ (0, import_fs40.writeFileSync)(configPath, JSON.stringify(freshConfig, null, 2));
53892
54340
  }
53893
54341
  } catch {
53894
54342
  }
@@ -53907,7 +54355,7 @@ function refreshOrgMemberships() {
53907
54355
  } catch {
53908
54356
  }
53909
54357
  }
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;
54358
+ 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
54359
  var init_index = __esm({
53912
54360
  "src/index.ts"() {
53913
54361
  "use strict";
@@ -53915,9 +54363,9 @@ var init_index = __esm({
53915
54363
  import_dotenv = __toESM(require_main(), 1);
53916
54364
  import_https2 = __toESM(require("https"), 1);
53917
54365
  import_child_process13 = require("child_process");
53918
- import_fs39 = require("fs");
53919
- import_path38 = require("path");
53920
- import_os23 = require("os");
54366
+ import_fs40 = require("fs");
54367
+ import_path39 = require("path");
54368
+ import_os24 = require("os");
53921
54369
  init_source();
53922
54370
  init_constants();
53923
54371
  init_sentry2();
@@ -53946,8 +54394,8 @@ var init_index = __esm({
53946
54394
  }, GLOBAL_TIMEOUT_MS);
53947
54395
  globalTimeout.unref();
53948
54396
  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");
54397
+ UPDATE_CACHE_DIR = (0, import_path39.join)((0, import_os24.homedir)(), ".gal");
54398
+ UPDATE_CACHE_FILE = (0, import_path39.join)(UPDATE_CACHE_DIR, "update-cache.json");
53951
54399
  ONE_DAY = 24 * 60 * 60 * 1e3;
53952
54400
  ONE_HOUR = 60 * 60 * 1e3;
53953
54401
  REGISTRY_URL2 = (() => {
@@ -54090,18 +54538,28 @@ var init_index = __esm({
54090
54538
  });
54091
54539
 
54092
54540
  // src/bootstrap.ts
54093
- var cliVersion10 = true ? "0.0.280" : "0.0.0-dev";
54541
+ var cliVersion10 = true ? "0.0.282" : "0.0.0-dev";
54094
54542
  var args = process.argv.slice(2);
54095
54543
  var requestedGlobalHelp = args.length === 1 && (args[0] === "--help" || args[0] === "-h");
54096
54544
  var requestedVersion = args.length === 1 && (args[0] === "--version" || args[0] === "-V");
54097
54545
  var globalHelpCommands = [
54546
+ " approve [options] Upload local configs to org approved config",
54547
+ " approved-config View and manage the org-approved AI agent configuration",
54098
54548
  " auth Manage GitHub authentication",
54549
+ " discover [orgName] Discover AI agent configurations across your organization repositories",
54099
54550
  " feedback [options] Send feedback about GAL",
54100
- " hooks Manage Claude Code hooks for auto-sync",
54551
+ " fetch [orgName] Fetch agent configurations from GAL API and write to local directory",
54552
+ " hooks Manage AI agent hooks for auto-sync",
54553
+ " join [options] Join an organization using an invite code",
54101
54554
  " mcp Set up and validate GAL hosted MCP connectivity",
54555
+ " memory Manage cross-provider AI agent memory/learnings (no auth required)",
54556
+ " policy Manage org-wide AI agent policies (enterprise)",
54557
+ " propose [description] Propose changes to your organization config",
54558
+ " scan [options] Scan local directory for AI agent configurations (no auth required)",
54102
54559
  " status [options] Check sync status, drift, and pending proposals",
54103
54560
  " sync [options] [orgName] Sync local configs with CISO-approved organization standard",
54104
- " update [options] Check for and apply CLI updates"
54561
+ " update [options] Check for and apply CLI updates",
54562
+ " workspace Manage workspaces (GitHub organizations and personal accounts)"
54105
54563
  ];
54106
54564
  if (process.env.GAL_INTERNAL === "true") {
54107
54565
  globalHelpCommands.splice(