substrate-ai 0.2.28 → 0.2.30

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.
@@ -814,114 +814,5 @@ var AdapterRegistry = class {
814
814
  };
815
815
 
816
816
  //#endregion
817
- //#region src/core/errors.ts
818
- /**
819
- * Error definitions for Substrate
820
- * Provides structured error hierarchy for all toolkit operations
821
- */
822
- /** Base error class for all Substrate errors */
823
- var AdtError = class AdtError extends Error {
824
- code;
825
- context;
826
- constructor(message, code, context = {}) {
827
- super(message);
828
- this.name = "AdtError";
829
- this.code = code;
830
- this.context = context;
831
- if (Error.captureStackTrace) Error.captureStackTrace(this, AdtError);
832
- }
833
- toJSON() {
834
- return {
835
- name: this.name,
836
- message: this.message,
837
- code: this.code,
838
- context: this.context,
839
- stack: this.stack
840
- };
841
- }
842
- };
843
- /** Error thrown when task configuration is invalid */
844
- var TaskConfigError = class extends AdtError {
845
- constructor(message, context = {}) {
846
- super(message, "TASK_CONFIG_ERROR", context);
847
- this.name = "TaskConfigError";
848
- }
849
- };
850
- /** Error thrown when a worker/agent operation fails */
851
- var WorkerError = class extends AdtError {
852
- constructor(message, context = {}) {
853
- super(message, "WORKER_ERROR", context);
854
- this.name = "WorkerError";
855
- }
856
- };
857
- /** Error thrown when a worker/agent cannot be found */
858
- var WorkerNotFoundError = class extends AdtError {
859
- constructor(agentId) {
860
- super(`Worker agent not found: ${agentId}`, "WORKER_NOT_FOUND", { agentId });
861
- this.name = "WorkerNotFoundError";
862
- }
863
- };
864
- /** Error thrown when a task graph is invalid */
865
- var TaskGraphError = class extends AdtError {
866
- constructor(message, context = {}) {
867
- super(message, "TASK_GRAPH_ERROR", context);
868
- this.name = "TaskGraphError";
869
- }
870
- };
871
- /** Error thrown when a task graph has cycles (deadlock) */
872
- var TaskGraphCycleError = class extends TaskGraphError {
873
- constructor(cycle) {
874
- super(`Circular dependency detected in task graph: ${cycle.join(" -> ")}`, { cycle });
875
- this.name = "TaskGraphCycleError";
876
- }
877
- };
878
- /** Error thrown when a budget limit is exceeded */
879
- var BudgetExceededError = class extends AdtError {
880
- constructor(limit, current, context = {}) {
881
- super(`Budget cap exceeded: current=${String(current)}, limit=${String(limit)}`, "BUDGET_EXCEEDED", {
882
- limit,
883
- current,
884
- ...context
885
- });
886
- this.name = "BudgetExceededError";
887
- }
888
- };
889
- /** Error thrown when git operations fail */
890
- var GitError = class extends AdtError {
891
- constructor(message, context = {}) {
892
- super(message, "GIT_ERROR", context);
893
- this.name = "GitError";
894
- }
895
- };
896
- /** Error thrown when configuration is invalid or missing */
897
- var ConfigError = class extends AdtError {
898
- constructor(message, context = {}) {
899
- super(message, "CONFIG_ERROR", context);
900
- this.name = "ConfigError";
901
- }
902
- };
903
- /** Error thrown when state recovery fails */
904
- var RecoveryError = class extends AdtError {
905
- constructor(message, context = {}) {
906
- super(message, "RECOVERY_ERROR", context);
907
- this.name = "RecoveryError";
908
- }
909
- };
910
- /** Error thrown when a config file uses an incompatible format version */
911
- var ConfigIncompatibleFormatError = class extends AdtError {
912
- constructor(message, context = {}) {
913
- super(message, "CONFIG_INCOMPATIBLE_FORMAT", context);
914
- this.name = "ConfigIncompatibleFormatError";
915
- }
916
- };
917
- /** Error thrown when a task graph file uses an incompatible format version */
918
- var TaskGraphIncompatibleFormatError = class extends AdtError {
919
- constructor(message, context = {}) {
920
- super(message, "TASK_GRAPH_INCOMPATIBLE_FORMAT", context);
921
- this.name = "TaskGraphIncompatibleFormatError";
922
- }
923
- };
924
-
925
- //#endregion
926
- export { AdapterRegistry, AdtError, BudgetExceededError, ClaudeCodeAdapter, CodexCLIAdapter, ConfigError, ConfigIncompatibleFormatError, GeminiCLIAdapter, GitError, RecoveryError, TaskConfigError, TaskGraphCycleError, TaskGraphError, TaskGraphIncompatibleFormatError, WorkerError, WorkerNotFoundError };
927
- //# sourceMappingURL=errors-CswS7Mzg.js.map
817
+ export { AdapterRegistry, ClaudeCodeAdapter, CodexCLIAdapter, GeminiCLIAdapter };
818
+ //# sourceMappingURL=adapter-registry-PsWhP_1Q.js.map
package/dist/cli/index.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-BCyrbL3w.js";
3
- import { createLogger, deepMask } from "../logger-D2fS2ccL.js";
4
- import { AdapterRegistry, ConfigError, ConfigIncompatibleFormatError } from "../errors-CswS7Mzg.js";
5
- import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema, SUPPORTED_CONFIG_FORMAT_VERSIONS, SubstrateConfigSchema, defaultConfigMigrator } from "../version-manager-impl-CtzNu7YZ.js";
6
- import { createEventBus } from "../helpers-DljGJnFF.js";
2
+ import { DEFAULT_CONFIG, DEFAULT_ROUTING_POLICY, DatabaseWrapper, SUBSTRATE_OWNED_SETTINGS_KEYS, VALID_PHASES, buildPipelineStatusOutput, createConfigSystem, createContextCompiler, createDispatcher, createImplementationOrchestrator, createPackLoader, createPhaseOrchestrator, createStopAfterGate, findPackageRoot, formatOutput, formatPhaseCompletionSummary, formatPipelineStatusHuman, formatPipelineSummary, formatTokenTelemetry, getAllDescendantPids, getAutoHealthData, getSubstrateDefaultSettings, parseDbTimestampAsUtc, registerHealthCommand, registerRunCommand, resolveBmadMethodSrcPath, resolveBmadMethodVersion, resolveMainRepoRoot, runAnalysisPhase, runMigrations, runPlanningPhase, runSolutioningPhase, validateStopAfterFromConflict } from "../run-Ajt187oE.js";
3
+ import { createLogger } from "../logger-D2fS2ccL.js";
4
+ import { AdapterRegistry } from "../adapter-registry-PsWhP_1Q.js";
5
+ import { CURRENT_CONFIG_FORMAT_VERSION, CURRENT_TASK_GRAPH_VERSION, PartialSubstrateConfigSchema } from "../config-migrator-DSi8KhQC.js";
6
+ import { ConfigError, createEventBus } from "../helpers-RL22dYtn.js";
7
7
  import { addTokenUsage, createDecision, createPipelineRun, getDecisionsByCategory, getDecisionsByPhaseForRun, getLatestRun, getTokenUsageSummary, listRequirements, updatePipelineRun } from "../decisions-Dq4cAA2L.js";
8
8
  import { ESCALATION_DIAGNOSIS, EXPERIMENT_RESULT, OPERATIONAL_FINDING, STORY_METRICS, aggregateTokenUsageForRun, compareRunMetrics, getBaselineRunMetrics, getRunMetrics, getStoryMetricsForRun, incrementRunRestarts, listRunMetrics, tagRunAsBaseline } from "../operational-CnMlvWqc.js";
9
9
  import { abortMerge, createWorktree, getConflictingFiles, getMergedFiles, getOrphanedWorktrees, performMerge, removeBranch, removeWorktree, simulateMerge, verifyGitVersion } from "../git-utils-CtmrZrHS.js";
10
- import { registerUpgradeCommand } from "../upgrade-CJ0JFQ2c.js";
10
+ import "../version-manager-impl-CizNmmLT.js";
11
+ import { registerUpgradeCommand } from "../upgrade-Cvwtnwl4.js";
11
12
  import { Command } from "commander";
12
13
  import { fileURLToPath } from "url";
13
14
  import { dirname, join, resolve } from "path";
@@ -256,73 +257,9 @@ function registerAdaptersCommand(program, version, registry) {
256
257
  });
257
258
  }
258
259
 
259
- //#endregion
260
- //#region src/modules/config/defaults.ts
261
- const DEFAULT_CLAUDE_PROVIDER = {
262
- enabled: false,
263
- subscription_routing: "auto",
264
- max_concurrent: 2,
265
- rate_limit: {
266
- tokens: 22e4,
267
- window_seconds: 18e3
268
- },
269
- api_key_env: "ANTHROPIC_API_KEY",
270
- api_billing: false
271
- };
272
- const DEFAULT_CODEX_PROVIDER = {
273
- enabled: false,
274
- subscription_routing: "api",
275
- max_concurrent: 2,
276
- api_key_env: "OPENAI_API_KEY",
277
- api_billing: true
278
- };
279
- const DEFAULT_GEMINI_PROVIDER = {
280
- enabled: false,
281
- subscription_routing: "api",
282
- max_concurrent: 2,
283
- api_key_env: "GOOGLE_API_KEY",
284
- api_billing: true
285
- };
286
- const DEFAULT_GLOBAL_SETTINGS = {
287
- log_level: "info",
288
- max_concurrent_tasks: 4,
289
- budget_cap_tokens: 0,
290
- budget_cap_usd: 0
291
- };
292
- const DEFAULT_ROUTING_POLICY = {
293
- default_provider: "claude",
294
- rules: [
295
- {
296
- task_type: "planning",
297
- preferred_provider: "claude",
298
- fallback_providers: ["gemini", "codex"]
299
- },
300
- {
301
- task_type: "coding",
302
- preferred_provider: "claude",
303
- fallback_providers: ["codex", "gemini"]
304
- },
305
- {
306
- task_type: "review",
307
- preferred_provider: "claude",
308
- fallback_providers: ["gemini"]
309
- }
310
- ]
311
- };
312
- const DEFAULT_CONFIG = {
313
- config_format_version: "1",
314
- task_graph_version: "1",
315
- global: DEFAULT_GLOBAL_SETTINGS,
316
- providers: {
317
- claude: DEFAULT_CLAUDE_PROVIDER,
318
- codex: DEFAULT_CODEX_PROVIDER,
319
- gemini: DEFAULT_GEMINI_PROVIDER
320
- }
321
- };
322
-
323
260
  //#endregion
324
261
  //#region src/cli/commands/init.ts
325
- const logger$17 = createLogger("init");
262
+ const logger$16 = createLogger("init");
326
263
  const __dirname = dirname(new URL(import.meta.url).pathname);
327
264
  const INIT_EXIT_SUCCESS = 0;
328
265
  const INIT_EXIT_ERROR = 1;
@@ -343,7 +280,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
343
280
  const version = resolveBmadMethodVersion();
344
281
  if (force && bmadExists) process.stderr.write(`Warning: Replacing existing _bmad/ framework with bmad-method@${version}\n`);
345
282
  process.stdout.write(`Scaffolding BMAD framework from bmad-method@${version}\n`);
346
- logger$17.info({
283
+ logger$16.info({
347
284
  version,
348
285
  dest: bmadDest
349
286
  }, "Scaffolding BMAD framework");
@@ -353,7 +290,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
353
290
  const destDir = join(bmadDest, dir);
354
291
  mkdirSync(destDir, { recursive: true });
355
292
  cpSync(srcDir, destDir, { recursive: true });
356
- logger$17.info({
293
+ logger$16.info({
357
294
  dir,
358
295
  dest: destDir
359
296
  }, "Scaffolded BMAD framework directory");
@@ -372,7 +309,7 @@ async function scaffoldBmadFramework(projectRoot, force, outputFormat) {
372
309
  "document_output_language: English"
373
310
  ].join("\n") + "\n";
374
311
  await writeFile(configFile, configStub, "utf8");
375
- logger$17.info({ configFile }, "Generated _bmad/_config/config.yaml stub");
312
+ logger$16.info({ configFile }, "Generated _bmad/_config/config.yaml stub");
376
313
  }
377
314
  }
378
315
  const CLAUDE_MD_START_MARKER = "<!-- substrate:start -->";
@@ -387,7 +324,7 @@ async function scaffoldClaudeMd(projectRoot) {
387
324
  try {
388
325
  sectionContent = await readFile(templatePath, "utf8");
389
326
  } catch {
390
- logger$17.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
327
+ logger$16.warn({ templatePath }, "CLAUDE.md substrate section template not found; skipping");
391
328
  return;
392
329
  }
393
330
  if (!sectionContent.endsWith("\n")) sectionContent += "\n";
@@ -405,7 +342,7 @@ async function scaffoldClaudeMd(projectRoot) {
405
342
  newContent = existingContent + separator + sectionContent;
406
343
  }
407
344
  await writeFile(claudeMdPath, newContent, "utf8");
408
- logger$17.info({ claudeMdPath }, "Wrote substrate section to CLAUDE.md");
345
+ logger$16.info({ claudeMdPath }, "Wrote substrate section to CLAUDE.md");
409
346
  }
410
347
  async function scaffoldStatuslineScript(projectRoot) {
411
348
  const pkgRoot = findPackageRoot(__dirname);
@@ -416,7 +353,7 @@ async function scaffoldStatuslineScript(projectRoot) {
416
353
  try {
417
354
  content = await readFile(templatePath, "utf8");
418
355
  } catch {
419
- logger$17.warn({ templatePath }, "statusline.sh template not found; skipping");
356
+ logger$16.warn({ templatePath }, "statusline.sh template not found; skipping");
420
357
  return;
421
358
  }
422
359
  const claudeDir = join(projectRoot, ".claude");
@@ -424,7 +361,7 @@ async function scaffoldStatuslineScript(projectRoot) {
424
361
  mkdirSync(claudeDir, { recursive: true });
425
362
  await writeFile(statuslinePath, content, "utf8");
426
363
  chmodSync(statuslinePath, 493);
427
- logger$17.info({ statuslinePath }, "Wrote .claude/statusline.sh");
364
+ logger$16.info({ statuslinePath }, "Wrote .claude/statusline.sh");
428
365
  }
429
366
  async function scaffoldClaudeSettings(projectRoot) {
430
367
  const claudeDir = join(projectRoot, ".claude");
@@ -440,7 +377,7 @@ async function scaffoldClaudeSettings(projectRoot) {
440
377
  if (!merged["$schema"]) merged["$schema"] = "https://json.schemastore.org/claude-code-settings.json";
441
378
  mkdirSync(claudeDir, { recursive: true });
442
379
  await writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
443
- logger$17.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
380
+ logger$16.info({ settingsPath }, "Wrote substrate settings to .claude/settings.json");
444
381
  }
445
382
  function resolveBmadMethodInstallerLibPath(fromDir = __dirname) {
446
383
  try {
@@ -510,7 +447,7 @@ async function compileBmadAgents(bmadDir) {
510
447
  writeFileSync(mdPath, result.xml, "utf-8");
511
448
  compiled++;
512
449
  } catch (compileErr) {
513
- logger$17.debug({
450
+ logger$16.debug({
514
451
  err: compileErr,
515
452
  file
516
453
  }, "Failed to compile agent YAML");
@@ -531,9 +468,9 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
531
468
  const _require = createRequire(join(__dirname, "synthetic.js"));
532
469
  try {
533
470
  const compiledCount = await compileBmadAgents(bmadDir);
534
- if (compiledCount > 0) logger$17.info({ compiledCount }, "Compiled agent YAML files to MD");
471
+ if (compiledCount > 0) logger$16.info({ compiledCount }, "Compiled agent YAML files to MD");
535
472
  } catch (compileErr) {
536
- logger$17.warn({ err: compileErr }, "Agent compilation failed; agent commands may be incomplete");
473
+ logger$16.warn({ err: compileErr }, "Agent compilation failed; agent commands may be incomplete");
537
474
  }
538
475
  const { AgentCommandGenerator } = _require(join(installerLibPath, "ide", "shared", "agent-command-generator.js"));
539
476
  const { WorkflowCommandGenerator } = _require(join(installerLibPath, "ide", "shared", "workflow-command-generator.js"));
@@ -545,7 +482,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
545
482
  const manifestGen = new ManifestGenerator();
546
483
  await manifestGen.generateManifests(bmadDir, allModules, [], { ides: ["claude-code"] });
547
484
  } catch (manifestErr) {
548
- logger$17.warn({ err: manifestErr }, "ManifestGenerator failed; workflow/task commands may be incomplete");
485
+ logger$16.warn({ err: manifestErr }, "ManifestGenerator failed; workflow/task commands may be incomplete");
549
486
  }
550
487
  const commandsDir = join(projectRoot, ".claude", "commands");
551
488
  mkdirSync(commandsDir, { recursive: true });
@@ -561,7 +498,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
561
498
  const taskToolCount = await taskToolGen.writeDashArtifacts(commandsDir, taskToolArtifacts);
562
499
  const total = agentCount + workflowCount + taskToolCount;
563
500
  if (outputFormat !== "json") process.stdout.write(`Generated ${String(total)} Claude Code commands (${String(agentCount)} agents, ${String(workflowCount)} workflows, ${String(taskToolCount)} tasks/tools)\n`);
564
- logger$17.info({
501
+ logger$16.info({
565
502
  agentCount,
566
503
  workflowCount,
567
504
  taskToolCount,
@@ -571,7 +508,7 @@ async function scaffoldClaudeCommands(projectRoot, outputFormat) {
571
508
  } catch (err) {
572
509
  const msg = err instanceof Error ? err.message : String(err);
573
510
  if (outputFormat !== "json") process.stderr.write(`Warning: .claude/commands/ generation failed: ${msg}\n`);
574
- logger$17.warn({ err }, "scaffoldClaudeCommands failed; init continues");
511
+ logger$16.warn({ err }, "scaffoldClaudeCommands failed; init continues");
575
512
  }
576
513
  }
577
514
  const PROVIDER_DEFAULTS = DEFAULT_CONFIG.providers;
@@ -646,7 +583,7 @@ async function runInitAction(options) {
646
583
  discoveryReport = await registry.discoverAndRegister();
647
584
  } catch (err) {
648
585
  const message = err instanceof Error ? err.message : String(err);
649
- logger$17.error({ err }, "Adapter discovery failed");
586
+ logger$16.error({ err }, "Adapter discovery failed");
650
587
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, `Adapter discovery failed: ${message}`) + "\n");
651
588
  else process.stderr.write(` Error: adapter discovery failed — ${message}\n`);
652
589
  return INIT_EXIT_ERROR;
@@ -695,12 +632,12 @@ async function runInitAction(options) {
695
632
  return INIT_EXIT_ERROR;
696
633
  }
697
634
  if (force && existsSync(localManifest)) {
698
- logger$17.info({ pack: packName }, "Replacing existing pack with bundled version");
635
+ logger$16.info({ pack: packName }, "Replacing existing pack with bundled version");
699
636
  process.stderr.write(`Warning: Replacing existing pack '${packName}' with bundled version\n`);
700
637
  }
701
638
  mkdirSync(dirname(packPath), { recursive: true });
702
639
  cpSync(bundledPackPath, packPath, { recursive: true });
703
- logger$17.info({
640
+ logger$16.info({
704
641
  pack: packName,
705
642
  dest: packPath
706
643
  }, "Scaffolded methodology pack");
@@ -753,7 +690,7 @@ async function runInitAction(options) {
753
690
  const msg = err instanceof Error ? err.message : String(err);
754
691
  if (outputFormat === "json") process.stdout.write(formatOutput(null, "json", false, msg) + "\n");
755
692
  else process.stderr.write(`Error: ${msg}\n`);
756
- logger$17.error({ err }, "init failed");
693
+ logger$16.error({ err }, "init failed");
757
694
  return INIT_EXIT_ERROR;
758
695
  }
759
696
  }
@@ -772,246 +709,6 @@ function registerInitCommand(program, _version, registry) {
772
709
  });
773
710
  }
774
711
 
775
- //#endregion
776
- //#region src/modules/config/version-utils.ts
777
- /**
778
- * Check whether a version string is in a list of supported versions.
779
- *
780
- * @param version - Version string to check
781
- * @param supported - List of supported version strings
782
- * @returns true if version is in the supported list
783
- */
784
- function isVersionSupported(version, supported) {
785
- return supported.includes(version);
786
- }
787
- /**
788
- * Format the standard "unsupported version" error message.
789
- *
790
- * @param formatType - 'config' or 'task_graph'
791
- * @param version - The unsupported version string found
792
- * @param supported - List of supported version strings
793
- * @returns Formatted error message string
794
- */
795
- function formatUnsupportedVersionError(formatType, version, supported) {
796
- if (formatType === "config") return `Configuration format version "${version}" is not supported. This toolkit supports: ${supported.join(", ")}. Please upgrade the toolkit: npm install -g substrate@latest`;
797
- return `Task graph format version "${version}" is not supported. This toolkit supports: ${supported.join(", ")}. Please upgrade the toolkit: npm install -g substrate@latest`;
798
- }
799
-
800
- //#endregion
801
- //#region src/modules/config/config-system-impl.ts
802
- const logger$16 = createLogger("config");
803
- function deepMerge(base, override) {
804
- const result = { ...base };
805
- for (const [key, val] of Object.entries(override)) if (val !== null && val !== void 0 && typeof val === "object" && !Array.isArray(val) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) result[key] = deepMerge(result[key], val);
806
- else if (val !== void 0) result[key] = val;
807
- return result;
808
- }
809
- /**
810
- * Map of ADT_ environment variable names to config paths.
811
- * Only overrides scalar values; does not support nested structures via env.
812
- */
813
- const ENV_VAR_MAP = {
814
- ADT_LOG_LEVEL: "global.log_level",
815
- ADT_MAX_CONCURRENT_TASKS: "global.max_concurrent_tasks",
816
- ADT_BUDGET_CAP_TOKENS: "global.budget_cap_tokens",
817
- ADT_BUDGET_CAP_USD: "global.budget_cap_usd",
818
- ADT_WORKSPACE_DIR: "global.workspace_dir",
819
- ADT_CLAUDE_ENABLED: "providers.claude.enabled",
820
- ADT_CODEX_ENABLED: "providers.codex.enabled",
821
- ADT_GEMINI_ENABLED: "providers.gemini.enabled"
822
- };
823
- /**
824
- * Read relevant environment variables and return a partial config overlay.
825
- */
826
- function readEnvOverrides() {
827
- const overrides = {};
828
- for (const [envKey, configPath] of Object.entries(ENV_VAR_MAP)) {
829
- const rawValue = process.env[envKey];
830
- if (rawValue === void 0) continue;
831
- const parts = configPath.split(".");
832
- let cursor = overrides;
833
- for (let i = 0; i < parts.length - 1; i++) {
834
- const part = parts[i] ?? "";
835
- if (cursor[part] === void 0) cursor[part] = {};
836
- cursor = cursor[part];
837
- }
838
- const lastKey = parts[parts.length - 1] ?? "";
839
- if (rawValue === "true") cursor[lastKey] = true;
840
- else if (rawValue === "false") cursor[lastKey] = false;
841
- else if (/^\d+$/.test(rawValue)) cursor[lastKey] = parseInt(rawValue, 10);
842
- else if (/^\d*\.\d+$/.test(rawValue)) cursor[lastKey] = parseFloat(rawValue);
843
- else cursor[lastKey] = rawValue;
844
- }
845
- const parsed = PartialSubstrateConfigSchema.safeParse(overrides);
846
- if (!parsed.success) {
847
- logger$16.warn({ errors: parsed.error.issues }, "Invalid environment variable overrides ignored");
848
- return {};
849
- }
850
- return parsed.data;
851
- }
852
- /**
853
- * Get a value from a nested object using dot-notation key.
854
- */
855
- function getByPath(obj, path$2) {
856
- const parts = path$2.split(".");
857
- let cursor = obj;
858
- for (const part of parts) {
859
- if (cursor === null || cursor === void 0 || typeof cursor !== "object") return void 0;
860
- cursor = cursor[part];
861
- }
862
- return cursor;
863
- }
864
- /**
865
- * Return a deep clone of `obj` with `path` set to `value`.
866
- * Creates intermediate objects as needed.
867
- */
868
- function setByPath(obj, path$2, value) {
869
- const parts = path$2.split(".");
870
- const result = { ...obj };
871
- let cursor = result;
872
- for (let i = 0; i < parts.length - 1; i++) {
873
- const part = parts[i] ?? "";
874
- const existing = cursor[part];
875
- if (existing === null || existing === void 0 || typeof existing !== "object") cursor[part] = {};
876
- else cursor[part] = { ...existing };
877
- cursor = cursor[part];
878
- }
879
- const lastKey = parts[parts.length - 1] ?? "";
880
- cursor[lastKey] = value;
881
- return result;
882
- }
883
- var ConfigSystemImpl = class {
884
- _config = null;
885
- _projectConfigDir;
886
- _globalConfigDir;
887
- _cliOverrides;
888
- constructor(options = {}) {
889
- this._projectConfigDir = options.projectConfigDir ? resolve(options.projectConfigDir) : resolve(process.cwd(), ".substrate");
890
- this._globalConfigDir = options.globalConfigDir ? resolve(options.globalConfigDir) : resolve(homedir(), ".substrate");
891
- this._cliOverrides = options.cliOverrides ?? {};
892
- }
893
- get isLoaded() {
894
- return this._config !== null;
895
- }
896
- async load() {
897
- let merged = structuredClone(DEFAULT_CONFIG);
898
- const globalConfig = await this._loadYamlFile(join(this._globalConfigDir, "config.yaml"));
899
- if (globalConfig !== null) merged = deepMerge(merged, globalConfig);
900
- const projectConfig = await this._loadYamlFile(join(this._projectConfigDir, "config.yaml"));
901
- if (projectConfig !== null) merged = deepMerge(merged, projectConfig);
902
- const envOverrides = readEnvOverrides();
903
- if (Object.keys(envOverrides).length > 0) merged = deepMerge(merged, envOverrides);
904
- if (Object.keys(this._cliOverrides).length > 0) merged = deepMerge(merged, this._cliOverrides);
905
- const result = SubstrateConfigSchema.safeParse(merged);
906
- if (!result.success) {
907
- const issues = result.error.issues.map((issue) => ` • ${issue.path.join(".")}: ${issue.message}`).join("\n");
908
- throw new ConfigError(`Configuration validation failed:\n${issues}`, { issues: result.error.issues });
909
- }
910
- this._config = result.data;
911
- logger$16.debug("Configuration loaded successfully");
912
- }
913
- getConfig() {
914
- if (this._config === null) throw new ConfigError("Configuration has not been loaded. Call load() before getConfig().", {});
915
- return this._config;
916
- }
917
- get(key) {
918
- const config = this.getConfig();
919
- return getByPath(config, key);
920
- }
921
- async set(key, value) {
922
- const current = this.getConfig();
923
- const existing = getByPath(current, key);
924
- if (existing === void 0) throw new ConfigError(`Unknown config key: ${key}`, { key });
925
- if (typeof existing === "object" && existing !== null) throw new ConfigError(`Cannot set object key "${key}" — use a more specific dot-notation path`, { key });
926
- let projectConfigRaw = {};
927
- const projectConfigPath = join(this._projectConfigDir, "config.yaml");
928
- const existingYaml = await this._loadYamlFile(projectConfigPath);
929
- if (existingYaml !== null) projectConfigRaw = existingYaml;
930
- const updated = setByPath(projectConfigRaw, key, value);
931
- const partial = PartialSubstrateConfigSchema.safeParse(updated);
932
- if (!partial.success) {
933
- const issues = partial.error.issues.map((i) => ` • ${i.path.join(".")}: ${i.message}`).join("\n");
934
- throw new ConfigError(`Invalid value for "${key}":\n${issues}`, {
935
- key,
936
- value,
937
- issues: partial.error.issues
938
- });
939
- }
940
- await mkdir(this._projectConfigDir, { recursive: true });
941
- const yamlStr = yaml.dump(updated);
942
- await writeFile(projectConfigPath, yamlStr, "utf-8");
943
- await this.load();
944
- }
945
- getMasked() {
946
- const config = this.getConfig();
947
- return deepMask(config);
948
- }
949
- getConfigFormatVersion() {
950
- return CURRENT_CONFIG_FORMAT_VERSION;
951
- }
952
- isCompatible(version) {
953
- return SUPPORTED_CONFIG_FORMAT_VERSIONS.includes(version);
954
- }
955
- async _fileExists(filePath) {
956
- try {
957
- await access(filePath);
958
- return true;
959
- } catch {
960
- return false;
961
- }
962
- }
963
- async _loadYamlFile(filePath) {
964
- if (!await this._fileExists(filePath)) return null;
965
- try {
966
- const raw = await readFile(filePath, "utf-8");
967
- let parsed = yaml.load(raw);
968
- if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
969
- const rawObj = parsed;
970
- const version = rawObj["config_format_version"];
971
- if (version !== void 0 && typeof version === "string" && !isVersionSupported(version, SUPPORTED_CONFIG_FORMAT_VERSIONS)) if (defaultConfigMigrator.canMigrate(version, CURRENT_CONFIG_FORMAT_VERSION)) {
972
- const migrationOutput = defaultConfigMigrator.migrate(rawObj, version, CURRENT_CONFIG_FORMAT_VERSION, filePath);
973
- if (migrationOutput.result.success) {
974
- logger$16.info({
975
- from: version,
976
- to: CURRENT_CONFIG_FORMAT_VERSION,
977
- backup: migrationOutput.result.backupPath
978
- }, "Config auto-migrated successfully");
979
- parsed = migrationOutput.config;
980
- } else throw new ConfigIncompatibleFormatError(`Config migration failed: ${migrationOutput.result.manualStepsRequired.join("; ")}`, {
981
- filePath,
982
- version
983
- });
984
- } else throw new ConfigIncompatibleFormatError(formatUnsupportedVersionError("config", version, SUPPORTED_CONFIG_FORMAT_VERSIONS), { filePath });
985
- }
986
- const result = PartialSubstrateConfigSchema.safeParse(parsed);
987
- if (!result.success) {
988
- const issues = result.error.issues.map((i) => ` • ${i.path.join(".")}: ${i.message}`).join("\n");
989
- throw new ConfigError(`Invalid config file at ${filePath}:\n${issues}`, {
990
- filePath,
991
- issues: result.error.issues
992
- });
993
- }
994
- return result.data;
995
- } catch (err) {
996
- if (err instanceof ConfigError) throw err;
997
- if (err instanceof ConfigIncompatibleFormatError) throw err;
998
- const message = err instanceof Error ? err.message : String(err);
999
- throw new ConfigError(`Failed to read config file at ${filePath}: ${message}`, { filePath });
1000
- }
1001
- }
1002
- };
1003
- /**
1004
- * Create a new ConfigSystem instance.
1005
- *
1006
- * @example
1007
- * const config = createConfigSystem()
1008
- * await config.load()
1009
- * const cfg = config.getConfig()
1010
- */
1011
- function createConfigSystem(options = {}) {
1012
- return new ConfigSystemImpl(options);
1013
- }
1014
-
1015
712
  //#endregion
1016
713
  //#region src/cli/commands/config.ts
1017
714
  const logger$15 = createLogger("config-cmd");
@@ -2874,7 +2571,7 @@ async function runSupervisorAction(options, deps = {}) {
2874
2571
  try {
2875
2572
  const { createExperimenter } = await import(
2876
2573
  /* @vite-ignore */
2877
- "../experimenter-bc40oi8p.js"
2574
+ "../experimenter-f_Y1rreV.js"
2878
2575
  );
2879
2576
  const { getLatestRun: getLatest } = await import(
2880
2577
  /* @vite-ignore */
@@ -2888,7 +2585,7 @@ async function runSupervisorAction(options, deps = {}) {
2888
2585
  const expDb = expDbWrapper.db;
2889
2586
  const { runRunAction: runPipeline } = await import(
2890
2587
  /* @vite-ignore */
2891
- "../run-CIgIYtKf.js"
2588
+ "../run-KBcR3Jpi.js"
2892
2589
  );
2893
2590
  const runStoryFn = async (opts) => {
2894
2591
  const exitCode = await runPipeline({
@@ -6964,8 +6661,8 @@ async function createProgram() {
6964
6661
  /** Fire-and-forget startup version check (story 8.3, AC3/AC5) */
6965
6662
  function checkForUpdatesInBackground(currentVersion) {
6966
6663
  if (process.env.SUBSTRATE_NO_UPDATE_CHECK === "1") return;
6967
- import("../upgrade-DzpjKYlD.js").then(async () => {
6968
- const { createVersionManager } = await import("../version-manager-impl-BDfiGXWX.js");
6664
+ import("../upgrade-CImByfkk.js").then(async () => {
6665
+ const { createVersionManager } = await import("../version-manager-impl-aL5IemIm.js");
6969
6666
  const vm = createVersionManager();
6970
6667
  const result = await vm.checkForUpdates();
6971
6668
  if (result.updateAvailable) {