@wairon/cli 5.1.1-dev.53 → 5.1.1-dev.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -65,7 +65,7 @@ var init_defaults = __esm({
65
65
  copilot: ".github/prompts",
66
66
  codex: ".codex/agents"
67
67
  };
68
- WAIRON_VERSION = "5.1.1-dev.53";
68
+ WAIRON_VERSION = "5.1.1-dev.55";
69
69
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
70
70
  SUPPORTED_ALIASES = ["wai"];
71
71
  SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
@@ -22768,6 +22768,270 @@ var init_treetransfer = __esm({
22768
22768
  }
22769
22769
  });
22770
22770
 
22771
+ // src/exporters/claude.ts
22772
+ function toolsFor(budget) {
22773
+ const base = TOOLS_BY_CLASS[budget.toolClass];
22774
+ if (!base) return void 0;
22775
+ if (budget.allowNestedDelegation && !base.includes("Agent")) {
22776
+ return [...base, "Agent"];
22777
+ }
22778
+ if (!budget.allowNestedDelegation) {
22779
+ return base.filter((t) => t !== "Agent");
22780
+ }
22781
+ return base;
22782
+ }
22783
+ function mcpServersFor(access) {
22784
+ return access === "none" ? "[]" : void 0;
22785
+ }
22786
+ function yamlScalar(value) {
22787
+ return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
22788
+ }
22789
+ var path22, MODEL_BY_TIER, TOOLS_BY_CLASS, ClaudeExporter;
22790
+ var init_claude = __esm({
22791
+ "src/exporters/claude.ts"() {
22792
+ "use strict";
22793
+ path22 = __toESM(require("path"));
22794
+ init_fs();
22795
+ MODEL_BY_TIER = {
22796
+ small: "haiku",
22797
+ standard: "sonnet",
22798
+ large: "opus",
22799
+ frontier: "fable"
22800
+ };
22801
+ TOOLS_BY_CLASS = {
22802
+ "read-only": ["Read", "Grep", "Glob"],
22803
+ implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
22804
+ orchestrate: ["Agent", "SendMessage", "TodoWrite"],
22805
+ // `full` means "inherit everything" — expressed by omitting the field.
22806
+ full: void 0
22807
+ };
22808
+ ClaudeExporter = class {
22809
+ constructor(options = {}) {
22810
+ this.options = options;
22811
+ this.targetType = "claude";
22812
+ }
22813
+ outputPath(ctx) {
22814
+ const { agent, target, projectRoot: projectRoot2 } = ctx;
22815
+ const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
22816
+ return path22.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
22817
+ }
22818
+ export(ctx) {
22819
+ const { agent, renderedInstructions, budget } = ctx;
22820
+ const filePath = this.outputPath(ctx);
22821
+ const frontmatter = [
22822
+ `name: ${agent.name}`,
22823
+ `description: ${yamlScalar(agent.description)}`
22824
+ ];
22825
+ if (budget && this.options.emitBudget) {
22826
+ if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
22827
+ if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
22828
+ if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
22829
+ const tools = toolsFor(budget);
22830
+ if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
22831
+ const servers = mcpServersFor(budget.mcp);
22832
+ if (servers) frontmatter.push(`mcpServers: ${servers}`);
22833
+ }
22834
+ const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
22835
+ const changed = writeFileIfChanged(filePath, content);
22836
+ return { outputPath: filePath, content, unchanged: !changed };
22837
+ }
22838
+ };
22839
+ }
22840
+ });
22841
+
22842
+ // src/exporters/custom.ts
22843
+ var path23, CustomExporter;
22844
+ var init_custom = __esm({
22845
+ "src/exporters/custom.ts"() {
22846
+ "use strict";
22847
+ path23 = __toESM(require("path"));
22848
+ init_fs();
22849
+ CustomExporter = class {
22850
+ constructor() {
22851
+ this.targetType = "custom";
22852
+ }
22853
+ outputPath(ctx) {
22854
+ const { agent, target, projectRoot: projectRoot2 } = ctx;
22855
+ if (!("outputDir" in target)) {
22856
+ throw new Error("CustomExporter requires target.outputDir");
22857
+ }
22858
+ return path23.resolve(projectRoot2, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
22859
+ }
22860
+ export(ctx) {
22861
+ const { agent, target, renderedInstructions } = ctx;
22862
+ const label = "label" in target ? target.label : "Custom";
22863
+ const filePath = this.outputPath(ctx);
22864
+ const content = [
22865
+ "---",
22866
+ `name: ${agent.name}`,
22867
+ `description: ${agent.description}`,
22868
+ `id: ${agent.id}`,
22869
+ `target: ${label}`,
22870
+ "---",
22871
+ "",
22872
+ renderedInstructions,
22873
+ ""
22874
+ ].join("\n");
22875
+ const changed = writeFileIfChanged(filePath, content);
22876
+ return { outputPath: filePath, content, unchanged: !changed };
22877
+ }
22878
+ };
22879
+ }
22880
+ });
22881
+
22882
+ // src/exporters/gemini.ts
22883
+ function yamlString(value) {
22884
+ if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
22885
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
22886
+ }
22887
+ return value;
22888
+ }
22889
+ var path24, GeminiExporter;
22890
+ var init_gemini = __esm({
22891
+ "src/exporters/gemini.ts"() {
22892
+ "use strict";
22893
+ path24 = __toESM(require("path"));
22894
+ init_fs();
22895
+ GeminiExporter = class {
22896
+ constructor() {
22897
+ this.targetType = "gemini";
22898
+ }
22899
+ outputPath(ctx) {
22900
+ const { agent, target, projectRoot: projectRoot2 } = ctx;
22901
+ const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
22902
+ return path24.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
22903
+ }
22904
+ export(ctx) {
22905
+ const { agent, renderedInstructions } = ctx;
22906
+ const filePath = this.outputPath(ctx);
22907
+ const indentedInstructions = renderedInstructions.split("\n").map((line2) => line2.length > 0 ? ` ${line2}` : "").join("\n");
22908
+ const content = [
22909
+ `name: ${yamlString(agent.name)}`,
22910
+ `description: ${yamlString(agent.description)}`,
22911
+ `system_prompt: |`,
22912
+ indentedInstructions,
22913
+ ""
22914
+ ].join("\n");
22915
+ const changed = writeFileIfChanged(filePath, content);
22916
+ return { outputPath: filePath, content, unchanged: !changed };
22917
+ }
22918
+ };
22919
+ }
22920
+ });
22921
+
22922
+ // src/exporters/registry.ts
22923
+ function getExporter(target) {
22924
+ const type = typeof target === "string" ? target : target.type;
22925
+ const exporter = EXPORTERS.get(type);
22926
+ if (!exporter) {
22927
+ throw new WaironError(`No exporter registered for target type: "${type}"`);
22928
+ }
22929
+ return exporter;
22930
+ }
22931
+ var EXPORTERS;
22932
+ var init_registry2 = __esm({
22933
+ "src/exporters/registry.ts"() {
22934
+ "use strict";
22935
+ init_claude();
22936
+ init_custom();
22937
+ init_gemini();
22938
+ init_errors();
22939
+ EXPORTERS = /* @__PURE__ */ new Map([
22940
+ ["claude", new ClaudeExporter({ emitBudget: true })],
22941
+ ["gemini", new GeminiExporter()],
22942
+ ["agy", new GeminiExporter()],
22943
+ ["cursor", new ClaudeExporter()],
22944
+ ["copilot", new ClaudeExporter()],
22945
+ ["codex", new ClaudeExporter()],
22946
+ ["custom", new CustomExporter()]
22947
+ ]);
22948
+ }
22949
+ });
22950
+
22951
+ // src/exporters/base.ts
22952
+ var WAIRON_MANAGED_MARKER, WAIRON_MANAGED_BANNER;
22953
+ var init_base = __esm({
22954
+ "src/exporters/base.ts"() {
22955
+ "use strict";
22956
+ WAIRON_MANAGED_MARKER = "wairon:managed";
22957
+ WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
22958
+ }
22959
+ });
22960
+
22961
+ // src/exporters/generate.ts
22962
+ function generateAgent(agent, projectConfig, options = {}) {
22963
+ const projectRoot2 = options.projectRoot ?? getProjectRoot();
22964
+ const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
22965
+ const rendered = `${WAIRON_MANAGED_BANNER}
22966
+ ${composeAgentBrief(agent.id).instructions}`;
22967
+ const results = [];
22968
+ const budget = resolveBudget(
22969
+ deriveExecutionProfile(agent),
22970
+ projectConfig.execution,
22971
+ agent.id
22972
+ );
22973
+ for (const agentTarget of agent.targets) {
22974
+ const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
22975
+ if (!targetConfig) continue;
22976
+ if (options.filterTargets) {
22977
+ const type = "type" in targetConfig ? targetConfig.type : targetConfig;
22978
+ if (!options.filterTargets.includes(type)) continue;
22979
+ }
22980
+ if (!options.dryRun) {
22981
+ results.push(getExporter(targetConfig).export({
22982
+ agent,
22983
+ template,
22984
+ renderedInstructions: rendered,
22985
+ projectRoot: projectRoot2,
22986
+ target: targetConfig,
22987
+ budget
22988
+ }));
22989
+ }
22990
+ }
22991
+ return { agent, results };
22992
+ }
22993
+ function generateAll(agents, projectConfig, options = {}) {
22994
+ let pool = agents;
22995
+ if (options.filterDomainIds && options.filterDomainIds.length > 0) {
22996
+ const ids = new Set(options.filterDomainIds);
22997
+ pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
22998
+ }
22999
+ return pool.map((agent) => generateAgent(agent, projectConfig, options));
23000
+ }
23001
+ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot2 = getProjectRoot()) {
23002
+ const expected = /* @__PURE__ */ new Set();
23003
+ for (const agent of agents) {
23004
+ for (const agentTarget of agent.targets) {
23005
+ const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
23006
+ if (!targetConfig) continue;
23007
+ const ctx = { agent, projectRoot: projectRoot2, target: targetConfig };
23008
+ expected.add(path25.resolve(getExporter(targetConfig).outputPath(ctx)));
23009
+ }
23010
+ }
23011
+ return expected;
23012
+ }
23013
+ function resolveTargetConfig(agentTarget, projectConfig) {
23014
+ const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
23015
+ return projectConfig.targets.find((t) => {
23016
+ if (typeof t === "string") return t === targetType;
23017
+ return t.type === targetType;
23018
+ });
23019
+ }
23020
+ var path25;
23021
+ var init_generate = __esm({
23022
+ "src/exporters/generate.ts"() {
23023
+ "use strict";
23024
+ path25 = __toESM(require("path"));
23025
+ init_templates();
23026
+ init_agent_resolver();
23027
+ init_execution_profile();
23028
+ init_budget_policy();
23029
+ init_fs();
23030
+ init_registry2();
23031
+ init_base();
23032
+ }
23033
+ });
23034
+
22771
23035
  // src/core/stereotype-migration.ts
22772
23036
  function retireSpecialists(apply) {
22773
23037
  const components = loadComponentSpecs();
@@ -22924,12 +23188,12 @@ function digest(content) {
22924
23188
  return crypto3.createHash("sha256").update(normalized, "utf8").digest("hex");
22925
23189
  }
22926
23190
  function currentSpecDigests(root = getProjectRoot()) {
22927
- const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path22.resolve(root, s.projectPath).split(path22.sep).join("/")}/`);
23191
+ const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path26.resolve(root, s.projectPath).split(path26.sep).join("/")}/`);
22928
23192
  const out = {};
22929
23193
  for (const [abs, content] of snapshotSpecFiles()) {
22930
- const normalized = path22.resolve(abs).split(path22.sep).join("/");
23194
+ const normalized = path26.resolve(abs).split(path26.sep).join("/");
22931
23195
  if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
22932
- out[path22.relative(root, abs).split(path22.sep).join("/")] = digest(content);
23196
+ out[path26.relative(root, abs).split(path26.sep).join("/")] = digest(content);
22933
23197
  }
22934
23198
  return out;
22935
23199
  }
@@ -22987,7 +23251,7 @@ function currentChildPins(mounts, root = getProjectRoot()) {
22987
23251
  const pins = {};
22988
23252
  for (const mount of mounts) {
22989
23253
  if (!mount.projectPath || mount.id.includes("::")) continue;
22990
- const child = readLockRecordAt(path22.resolve(root, mount.projectPath));
23254
+ const child = readLockRecordAt(path26.resolve(root, mount.projectPath));
22991
23255
  if (child) pins[mount.id] = pinOf(child.stateId);
22992
23256
  }
22993
23257
  return pins;
@@ -23003,12 +23267,12 @@ function movedChildren(mounts, root = getProjectRoot()) {
23003
23267
  }
23004
23268
  return moved;
23005
23269
  }
23006
- var crypto3, path22;
23270
+ var crypto3, path26;
23007
23271
  var init_approval = __esm({
23008
23272
  "src/core/approval.ts"() {
23009
23273
  "use strict";
23010
23274
  crypto3 = __toESM(require("crypto"));
23011
- path22 = __toESM(require("path"));
23275
+ path26 = __toESM(require("path"));
23012
23276
  init_fs();
23013
23277
  init_specs2();
23014
23278
  init_lockfile();
@@ -23089,6 +23353,7 @@ var init_core = __esm({
23089
23353
  init_treetransfer();
23090
23354
  init_extensions();
23091
23355
  init_agent_resolver();
23356
+ init_generate();
23092
23357
  init_treetransfer();
23093
23358
  init_provision();
23094
23359
  init_stereotype_migration();
@@ -23465,13 +23730,13 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
23465
23730
  function resolveThroughParent(boundRoot, treatAllAsComplete, childRules) {
23466
23731
  const reach = getRequestParentReach();
23467
23732
  if (reach && !reach.parentReach) return null;
23468
- const ceiling = reach?.topRoot ? path23.resolve(reach.topRoot) : void 0;
23733
+ const ceiling = reach?.topRoot ? path27.resolve(reach.topRoot) : void 0;
23469
23734
  const chain = [];
23470
- let top = path23.resolve(boundRoot);
23735
+ let top = path27.resolve(boundRoot);
23471
23736
  while (top !== ceiling) {
23472
23737
  const hop = findChainingParent(top, ceiling);
23473
23738
  if (!hop) break;
23474
- const next = path23.resolve(hop.parentRoot);
23739
+ const next = path27.resolve(hop.parentRoot);
23475
23740
  if (ceiling && !isWithinOrEqual(ceiling, next)) break;
23476
23741
  chain.unshift(hop.subsystemId);
23477
23742
  top = next;
@@ -23518,8 +23783,8 @@ function isIdChar(ch) {
23518
23783
  return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-" || ch === "." || ch === ":";
23519
23784
  }
23520
23785
  function isWithinOrEqual(dir, target) {
23521
- const rel2 = path23.relative(dir, target);
23522
- return rel2 === "" || !rel2.startsWith("..") && !path23.isAbsolute(rel2);
23786
+ const rel2 = path27.relative(dir, target);
23787
+ return rel2 === "" || !rel2.startsWith("..") && !path27.isAbsolute(rel2);
23523
23788
  }
23524
23789
  function dedupeIssues(list2) {
23525
23790
  const seen = /* @__PURE__ */ new Set();
@@ -23540,7 +23805,7 @@ function settledStatusBearing(loaded) {
23540
23805
  if (!settled || settled.size === 0) return [];
23541
23806
  const root = getProjectRoot();
23542
23807
  const index = scanAllSpecs();
23543
- const rel2 = (abs) => path23.relative(root, abs).split(path23.sep).join("/");
23808
+ const rel2 = (abs) => path27.relative(root, abs).split(path27.sep).join("/");
23544
23809
  const out = [];
23545
23810
  const take = (specs, paths) => {
23546
23811
  for (const spec of specs) {
@@ -23570,7 +23835,7 @@ function computeGateStateId() {
23570
23835
  registerBuiltinRules();
23571
23836
  return computeGateIdentity(content, extensions, ruleSequence(), inputs, gate);
23572
23837
  }
23573
- var path23, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
23838
+ var path27, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
23574
23839
  var init_validation = __esm({
23575
23840
  "src/core/validation.ts"() {
23576
23841
  "use strict";
@@ -23586,7 +23851,7 @@ var init_validation = __esm({
23586
23851
  init_source_analysis();
23587
23852
  init_specs2();
23588
23853
  init_fs();
23589
- path23 = __toESM(require("path"));
23854
+ path27 = __toESM(require("path"));
23590
23855
  init_core();
23591
23856
  RESOLUTION_FAILURE_CODES = /* @__PURE__ */ new Set([
23592
23857
  "UNDEFINED_TYPE_REFERENCE",
@@ -24306,42 +24571,42 @@ function rebaseReference(ref, mount, direction, isMoved = () => false) {
24306
24571
  return relativizeId(travels ? qualifyId(left, to, NO_ROOT_SUBSYSTEMS) : target, to);
24307
24572
  }
24308
24573
  function isWithin(dir, file) {
24309
- const d = path24.resolve(dir);
24310
- const f = path24.resolve(file);
24311
- return f === d || f.startsWith(d + path24.sep);
24574
+ const d = path28.resolve(dir);
24575
+ const f = path28.resolve(file);
24576
+ return f === d || f.startsWith(d + path28.sep);
24312
24577
  }
24313
24578
  function canonicalPath(target) {
24314
- let existing = path24.resolve(target);
24579
+ let existing = path28.resolve(target);
24315
24580
  const rest = [];
24316
24581
  for (; ; ) {
24317
24582
  try {
24318
24583
  fs18.lstatSync(existing);
24319
24584
  break;
24320
24585
  } catch {
24321
- const up = path24.dirname(existing);
24322
- if (up === existing) return path24.resolve(target);
24323
- rest.unshift(path24.basename(existing));
24586
+ const up = path28.dirname(existing);
24587
+ if (up === existing) return path28.resolve(target);
24588
+ rest.unshift(path28.basename(existing));
24324
24589
  existing = up;
24325
24590
  }
24326
24591
  }
24327
24592
  try {
24328
- return path24.join(fs18.realpathSync.native(existing), ...rest);
24593
+ return path28.join(fs18.realpathSync.native(existing), ...rest);
24329
24594
  } catch {
24330
24595
  return null;
24331
24596
  }
24332
24597
  }
24333
24598
  function chainDirKey(dir) {
24334
- return canonicalPath(dir) ?? path24.resolve(dir);
24599
+ return canonicalPath(dir) ?? path28.resolve(dir);
24335
24600
  }
24336
24601
  function projectPathEscapesRoot(projectRoot2, projectPath, resolvedChildDir) {
24337
- if (path24.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
24602
+ if (path28.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
24338
24603
  const root = canonicalPath(projectRoot2);
24339
24604
  const child = canonicalPath(resolvedChildDir);
24340
24605
  return root === null || child === null || !isWithin(root, child);
24341
24606
  }
24342
24607
  function assertContainedProjectPath(projectRoot2, projectPath) {
24343
- const root = path24.resolve(projectRoot2);
24344
- const resolved = path24.resolve(root, projectPath);
24608
+ const root = path28.resolve(projectRoot2);
24609
+ const resolved = path28.resolve(root, projectPath);
24345
24610
  if (projectPathEscapesRoot(root, projectPath, resolved)) {
24346
24611
  throw new Error(
24347
24612
  `projectPath "${projectPath}" must resolve within the project root "${root}", but resolves to "${resolved}"; absolute, ../-escaping and link-escaping paths are rejected so a chained subproject is always contained by its parent.`
@@ -24352,12 +24617,12 @@ function assertContainedProjectPath(projectRoot2, projectPath) {
24352
24617
  function findChainingParent(childRoot, ceiling) {
24353
24618
  let childResolved;
24354
24619
  try {
24355
- childResolved = path24.resolve(childRoot);
24620
+ childResolved = path28.resolve(childRoot);
24356
24621
  } catch {
24357
24622
  return null;
24358
24623
  }
24359
- const bound2 = ceiling ? path24.resolve(ceiling) : void 0;
24360
- let dir = path24.dirname(childResolved);
24624
+ const bound2 = ceiling ? path28.resolve(ceiling) : void 0;
24625
+ let dir = path28.dirname(childResolved);
24361
24626
  for (let hops = 0; hops < 32; hops++) {
24362
24627
  if (bound2 && !isWithin(bound2, dir)) break;
24363
24628
  const specsDir = aiPathsAt(dir).specsDir();
@@ -24373,7 +24638,7 @@ function findChainingParent(childRoot, ceiling) {
24373
24638
  const projectPath = raw.projectPath;
24374
24639
  if (typeof projectPath === "string" && projectPath.trim() !== "") {
24375
24640
  try {
24376
- const mountDir = path24.resolve(dir, projectPath);
24641
+ const mountDir = path28.resolve(dir, projectPath);
24377
24642
  if (mountDir === childResolved && !projectPathEscapesRoot(dir, projectPath, mountDir)) {
24378
24643
  const id = raw.id;
24379
24644
  return { parentRoot: dir, subsystemId: typeof id === "string" ? id : "?" };
@@ -24384,14 +24649,14 @@ function findChainingParent(childRoot, ceiling) {
24384
24649
  }
24385
24650
  }
24386
24651
  }
24387
- const up = path24.dirname(dir);
24652
+ const up = path28.dirname(dir);
24388
24653
  if (up === dir) break;
24389
24654
  dir = up;
24390
24655
  }
24391
24656
  return null;
24392
24657
  }
24393
24658
  function inspectChainedRoots(rootDir = getProjectRoot()) {
24394
- const root = path24.resolve(rootDir);
24659
+ const root = path28.resolve(rootDir);
24395
24660
  const inspection = { roots: [], skipped: [] };
24396
24661
  const listed = /* @__PURE__ */ new Set();
24397
24662
  const walk2 = (projectDir, prefix, ancestors, depth) => {
@@ -24410,7 +24675,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
24410
24675
  const localId = typeof id === "string" ? id : "?";
24411
24676
  let childDir;
24412
24677
  try {
24413
- childDir = path24.resolve(projectDir, projectPath);
24678
+ childDir = path28.resolve(projectDir, projectPath);
24414
24679
  } catch {
24415
24680
  continue;
24416
24681
  }
@@ -24427,7 +24692,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
24427
24692
  const key = chainDirKey(childDir);
24428
24693
  if (listed.has(key)) continue;
24429
24694
  listed.add(key);
24430
- inspection.roots.push(path24.relative(root, childDir).split(path24.sep).join("/"));
24695
+ inspection.roots.push(path28.relative(root, childDir).split(path28.sep).join("/"));
24431
24696
  walk2(childDir, prefix ? `${prefix}::${localId}` : localId, /* @__PURE__ */ new Set([...ancestors, key]), depth + 1);
24432
24697
  }
24433
24698
  };
@@ -24513,9 +24778,9 @@ function stripNamespaceFromImplementation(spec, prefix) {
24513
24778
  }
24514
24779
  function childRelativeFilePaths(spec, authoringRoot, childRoot) {
24515
24780
  const reexpress = (p) => {
24516
- if (path24.isAbsolute(p)) return p;
24517
- const rel2 = path24.relative(childRoot, path24.resolve(authoringRoot, p));
24518
- const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path24.sep}`) && !path24.isAbsolute(rel2);
24781
+ if (path28.isAbsolute(p)) return p;
24782
+ const rel2 = path28.relative(childRoot, path28.resolve(authoringRoot, p));
24783
+ const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path28.sep}`) && !path28.isAbsolute(rel2);
24519
24784
  return inside ? rel2.replace(/\\/g, "/") : p;
24520
24785
  };
24521
24786
  return {
@@ -24550,9 +24815,9 @@ function findOwner(id, components) {
24550
24815
  }) ?? null;
24551
24816
  }
24552
24817
  function moveComponentFolder(fromDir, toDir) {
24553
- if (path24.normalize(fromDir) === path24.normalize(toDir)) return false;
24818
+ if (path28.normalize(fromDir) === path28.normalize(toDir)) return false;
24554
24819
  if (!fs18.existsSync(fromDir) || fs18.existsSync(toDir)) return false;
24555
- ensureDir(path24.dirname(toDir));
24820
+ ensureDir(path28.dirname(toDir));
24556
24821
  fs18.renameSync(fromDir, toDir);
24557
24822
  return true;
24558
24823
  }
@@ -24968,7 +25233,7 @@ function refusedMoveSummary(from, to, methods, refusals, alternatives) {
24968
25233
  return `Refused: moving ${namedMethods(methods)} from "${from}" to "${to}" is refused by ${refusals.join(", ")}. Nothing was written. ` + (cheapest ? `The cheapest legal home is "${cheapest.component}" (${cheapest.newDependencies.length} new dependenc${cheapest.newDependencies.length === 1 ? "y" : "ies"}, ${cheapest.dependencyCount} of ${cheapest.dependencyLimit}).` : `No component of this subsystem can take them as they stand \u2014 ${alternatives.length} were weighed.`);
24969
25234
  }
24970
25235
  function workspaceFor(rootDir) {
24971
- const key = path24.resolve(rootDir);
25236
+ const key = path28.resolve(rootDir);
24972
25237
  let ws = workspaces.get(key);
24973
25238
  if (!ws) {
24974
25239
  ws = new SpecWorkspace(key);
@@ -25098,13 +25363,13 @@ function snapshotInputKey(snapshot) {
25098
25363
  return canonicalize(content);
25099
25364
  }
25100
25365
  function consumedSurfaceInputsAt(rootDir) {
25101
- const dir = path24.join(rootDir, ".wai", "surfaces");
25366
+ const dir = path28.join(rootDir, ".wai", "surfaces");
25102
25367
  if (!pathExists(dir)) return [];
25103
25368
  const keys = [];
25104
25369
  for (const file of fs18.readdirSync(dir)) {
25105
25370
  if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
25106
25371
  try {
25107
- keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path24.join(dir, file)))));
25372
+ keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path28.join(dir, file)))));
25108
25373
  } catch {
25109
25374
  }
25110
25375
  }
@@ -25112,7 +25377,7 @@ function consumedSurfaceInputsAt(rootDir) {
25112
25377
  }
25113
25378
  function consumedContractInputs() {
25114
25379
  const root = getProjectRoot();
25115
- const roots = [root, ...listChainedRoots(root).map((rel2) => path24.join(root, rel2))];
25380
+ const roots = [root, ...listChainedRoots(root).map((rel2) => path28.join(root, rel2))];
25116
25381
  return roots.flatMap(consumedSurfaceInputsAt);
25117
25382
  }
25118
25383
  function readLockState(current2) {
@@ -25148,7 +25413,7 @@ function markSelectionsBundled(bundled) {
25148
25413
  projectConfigRepository.markSelectionsBundled(bundled);
25149
25414
  }
25150
25415
  function computeStateIdAt(root) {
25151
- const resolved = path24.resolve(root);
25416
+ const resolved = path28.resolve(root);
25152
25417
  return runWithProjectRoot(resolved, () => {
25153
25418
  workspaceFor(resolved).invalidate();
25154
25419
  const system = loadSystemSpec();
@@ -25198,12 +25463,12 @@ function updateSpec(kind, id, delta, hooks, dryRun) {
25198
25463
  function moveMethods(from, to, methods, hooks, dryRun) {
25199
25464
  return current().moveMethods(from, to, methods, hooks, dryRun);
25200
25465
  }
25201
- var fs18, path24, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, COMPONENT_AUTH_SOURCE, DELTA_VERBS, JUMP_LABEL_TWINS, LABEL_TWIN_CONTAINERS, SpecWorkspace, DEFAULT_DEPENDENCY_LIMIT, PROSE_FIELDS2, workspaces;
25466
+ var fs18, path28, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, COMPONENT_AUTH_SOURCE, DELTA_VERBS, JUMP_LABEL_TWINS, LABEL_TWIN_CONTAINERS, SpecWorkspace, DEFAULT_DEPENDENCY_LIMIT, PROSE_FIELDS2, workspaces;
25202
25467
  var init_specs2 = __esm({
25203
25468
  "src/core/specs.ts"() {
25204
25469
  "use strict";
25205
25470
  fs18 = __toESM(require("fs"));
25206
- path24 = __toESM(require("path"));
25471
+ path28 = __toESM(require("path"));
25207
25472
  init_loader();
25208
25473
  init_project_config();
25209
25474
  init_fs();
@@ -25238,7 +25503,7 @@ var init_specs2 = __esm({
25238
25503
  this.rootSubsystems = /* @__PURE__ */ new Set();
25239
25504
  this.scanVisitedSpecDirs = [];
25240
25505
  this.loaderIssues = [];
25241
- this.rootDir = path24.resolve(rootDir);
25506
+ this.rootDir = path28.resolve(rootDir);
25242
25507
  this.paths = aiPathsAt(this.rootDir);
25243
25508
  }
25244
25509
  invalidate() {
@@ -25281,8 +25546,8 @@ var init_specs2 = __esm({
25281
25546
  * qualifies the spec itself — so scoping a validate to a mount keeps it.
25282
25547
  */
25283
25548
  loaderIssueSpecId(file, rawId, namespacePrefix) {
25284
- const stem2 = path24.basename(file, ".yaml");
25285
- const local = rawId ?? (stem2.startsWith(".") ? path24.basename(path24.dirname(file)) : stem2);
25549
+ const stem2 = path28.basename(file, ".yaml");
25550
+ const local = rawId ?? (stem2.startsWith(".") ? path28.basename(path28.dirname(file)) : stem2);
25286
25551
  return namespacePrefix ? qualifyId(local, namespacePrefix, this.rootSubsystems) : local;
25287
25552
  }
25288
25553
  scanSpecsForProject(projectDir, namespacePrefix, visitedDirs, maxDepth, currentDepth) {
@@ -25292,10 +25557,10 @@ var init_specs2 = __esm({
25292
25557
  this.scanVisitedSpecDirs.push(specsDir);
25293
25558
  if (!pathExists(specsDir)) return index;
25294
25559
  const files = listSpecFiles(specsDir);
25295
- const systemYaml = path24.normalize(projectPaths.specsSystem());
25560
+ const systemYaml = path28.normalize(projectPaths.specsSystem());
25296
25561
  const localSubprojects = [];
25297
25562
  for (const file of files) {
25298
- const normFile = path24.normalize(file);
25563
+ const normFile = path28.normalize(file);
25299
25564
  if (normFile === systemYaml) continue;
25300
25565
  let detectedType = "spec";
25301
25566
  let rawId;
@@ -25339,7 +25604,7 @@ var init_specs2 = __esm({
25339
25604
  } else if ("contract" in raw) {
25340
25605
  detectedType = "implementation";
25341
25606
  const parsed = ImplementationSpecSchema.parse(raw);
25342
- const normalizeSourcePath = (p) => path24.relative(projectDir, path24.resolve(projectDir, p)).replace(/\\/g, "/");
25607
+ const normalizeSourcePath = (p) => path28.relative(projectDir, path28.resolve(projectDir, p)).replace(/\\/g, "/");
25343
25608
  if (parsed.sourcePath) parsed.sourcePath = normalizeSourcePath(parsed.sourcePath);
25344
25609
  for (const method2 of parsed.methods) {
25345
25610
  if (method2.sourcePath) method2.sourcePath = normalizeSourcePath(method2.sourcePath);
@@ -25465,7 +25730,7 @@ var init_specs2 = __esm({
25465
25730
  }
25466
25731
  if (currentDepth < maxDepth) {
25467
25732
  for (const subproj of localSubprojects) {
25468
- const childDir = path24.resolve(projectDir, subproj.projectPath);
25733
+ const childDir = path28.resolve(projectDir, subproj.projectPath);
25469
25734
  const mountId = namespacePrefix ? qualifyDeclaredId(subproj.subsystemId, namespacePrefix, true) : subproj.subsystemId;
25470
25735
  if (projectPathEscapesRoot(projectDir, subproj.projectPath, childDir)) {
25471
25736
  this.loaderIssues.push({
@@ -25528,7 +25793,7 @@ var init_specs2 = __esm({
25528
25793
  const index = this.scanAll();
25529
25794
  const sub = index.subsystems.find((s) => s.id === currentPrefix);
25530
25795
  if (sub && sub.projectPath) {
25531
- const nextDir = path24.resolve(currentDir, sub.projectPath);
25796
+ const nextDir = path28.resolve(currentDir, sub.projectPath);
25532
25797
  if (projectPathEscapesRoot(currentDir, sub.projectPath, nextDir)) {
25533
25798
  this.loaderIssues.push({
25534
25799
  severity: "error",
@@ -25580,9 +25845,9 @@ var init_specs2 = __esm({
25580
25845
  return index.paths.subsystem[matches[0]];
25581
25846
  }
25582
25847
  if (pathExists(this.paths.specsSubsystemsDir()) && listFiles(this.paths.specsSubsystemsDir(), ".yaml").length > 0) {
25583
- return path24.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
25848
+ return path28.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
25584
25849
  }
25585
- return path24.join(this.paths.specsDir(), id, ".index.yaml");
25850
+ return path28.join(this.paths.specsDir(), id, ".index.yaml");
25586
25851
  }
25587
25852
  getComponentPath(id, subsystemId) {
25588
25853
  const index = this.scanAll();
@@ -25602,21 +25867,21 @@ var init_specs2 = __esm({
25602
25867
  if (owner) {
25603
25868
  const ownerPath = index.paths.component[owner.id];
25604
25869
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
25605
- return path24.join(path24.dirname(ownerPath), id, ".index.yaml");
25870
+ return path28.join(path28.dirname(ownerPath), id, ".index.yaml");
25606
25871
  }
25607
25872
  }
25608
25873
  if (subsystemId) {
25609
25874
  const subPath = this.getSubsystemPath(subsystemId);
25610
- const subDir = path24.dirname(subPath);
25875
+ const subDir = path28.dirname(subPath);
25611
25876
  if (subPath.endsWith(".index.yaml")) {
25612
- return path24.join(subDir, id, ".index.yaml");
25877
+ return path28.join(subDir, id, ".index.yaml");
25613
25878
  }
25614
25879
  }
25615
25880
  if (pathExists(this.paths.specsComponentsDir()) && listFiles(this.paths.specsComponentsDir(), ".yaml").length > 0) {
25616
- return path24.join(this.paths.specsComponentsDir(), `${id}.yaml`);
25881
+ return path28.join(this.paths.specsComponentsDir(), `${id}.yaml`);
25617
25882
  }
25618
25883
  const targetSubsystem = subsystemId || "default";
25619
- return path24.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
25884
+ return path28.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
25620
25885
  }
25621
25886
  getInterfacePath(id, componentId) {
25622
25887
  const index = this.scanAll();
@@ -25642,16 +25907,16 @@ var init_specs2 = __esm({
25642
25907
  }
25643
25908
  if (componentId) {
25644
25909
  const compPath = this.getComponentPath(componentId);
25645
- const compDir = path24.dirname(compPath);
25910
+ const compDir = path28.dirname(compPath);
25646
25911
  if (compPath.endsWith(".index.yaml")) {
25647
- return path24.join(compDir, ".interface.yaml");
25912
+ return path28.join(compDir, ".interface.yaml");
25648
25913
  }
25649
25914
  }
25650
25915
  if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
25651
- return path24.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
25916
+ return path28.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
25652
25917
  }
25653
25918
  const targetComponent = componentId || "default";
25654
- return path24.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
25919
+ return path28.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
25655
25920
  }
25656
25921
  getImplementationPath(id, contractId) {
25657
25922
  const index = this.scanAll();
@@ -25677,16 +25942,16 @@ var init_specs2 = __esm({
25677
25942
  }
25678
25943
  if (contractId) {
25679
25944
  const intfPath = this.getInterfacePath(contractId);
25680
- const intfDir = path24.dirname(intfPath);
25945
+ const intfDir = path28.dirname(intfPath);
25681
25946
  if (intfPath.endsWith(".interface.yaml")) {
25682
- return path24.join(intfDir, ".implementation.yaml");
25947
+ return path28.join(intfDir, ".implementation.yaml");
25683
25948
  }
25684
25949
  }
25685
25950
  if (pathExists(this.paths.specsImplementationsDir()) && listFiles(this.paths.specsImplementationsDir(), ".yaml").length > 0) {
25686
- return path24.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
25951
+ return path28.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
25687
25952
  }
25688
25953
  const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
25689
- return path24.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
25954
+ return path28.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
25690
25955
  }
25691
25956
  getTypePath(id, subsystemId, group) {
25692
25957
  const index = this.scanAll();
@@ -25717,7 +25982,7 @@ var init_specs2 = __esm({
25717
25982
  const groupPath = index.paths.group[targetGroup] || index.paths.group[plainGroup];
25718
25983
  if (groupPath) {
25719
25984
  const localId2 = id.split("::").pop();
25720
- return path24.join(path24.dirname(groupPath), `${localId2}.yaml`);
25985
+ return path28.join(path28.dirname(groupPath), `${localId2}.yaml`);
25721
25986
  }
25722
25987
  }
25723
25988
  let localId = id;
@@ -25730,12 +25995,12 @@ var init_specs2 = __esm({
25730
25995
  }
25731
25996
  if (subsystemId) {
25732
25997
  const subPath = this.getSubsystemPath(subsystemId);
25733
- const subDir = path24.dirname(subPath);
25998
+ const subDir = path28.dirname(subPath);
25734
25999
  if (subPath.endsWith(".index.yaml")) {
25735
- return path24.join(subDir, "types", `${localId}.yaml`);
26000
+ return path28.join(subDir, "types", `${localId}.yaml`);
25736
26001
  }
25737
26002
  }
25738
- return path24.join(this.paths.specsTypesDir(), `${localId}.yaml`);
26003
+ return path28.join(this.paths.specsTypesDir(), `${localId}.yaml`);
25739
26004
  }
25740
26005
  getGroupPath(id, subsystemId) {
25741
26006
  const index = this.scanAll();
@@ -25769,12 +26034,12 @@ var init_specs2 = __esm({
25769
26034
  }
25770
26035
  if (subsystemId) {
25771
26036
  const subPath = this.getSubsystemPath(subsystemId);
25772
- const subDir = path24.dirname(subPath);
26037
+ const subDir = path28.dirname(subPath);
25773
26038
  if (subPath.endsWith(".index.yaml")) {
25774
- return path24.join(subDir, "types", localId, ".index.yaml");
26039
+ return path28.join(subDir, "types", localId, ".index.yaml");
25775
26040
  }
25776
26041
  }
25777
- return path24.join(this.paths.specsTypesDir(), localId, ".index.yaml");
26042
+ return path28.join(this.paths.specsTypesDir(), localId, ".index.yaml");
25778
26043
  }
25779
26044
  // -------------------------------------------------------------------------
25780
26045
  // Level 0: System
@@ -25797,7 +26062,7 @@ var init_specs2 = __esm({
25797
26062
  }
25798
26063
  saveSystemSpec(spec) {
25799
26064
  const p = this.paths.specsSystem();
25800
- ensureDir(path24.dirname(p));
26065
+ ensureDir(path28.dirname(p));
25801
26066
  writeSpecFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
25802
26067
  invalidateSpecCache();
25803
26068
  }
@@ -25919,7 +26184,7 @@ var init_specs2 = __esm({
25919
26184
  }
25920
26185
  saveSubsystemSpec(spec, opts) {
25921
26186
  const p = this.getSubsystemPath(spec.id);
25922
- ensureDir(path24.dirname(p));
26187
+ ensureDir(path28.dirname(p));
25923
26188
  const { prefix } = splitNamespace(spec.id);
25924
26189
  if (!prefix && spec.projectPath && spec.projectPath.trim() !== "") {
25925
26190
  assertContainedProjectPath(this.rootDir, spec.projectPath);
@@ -25986,7 +26251,7 @@ var init_specs2 = __esm({
25986
26251
  saveComponentSpec(spec, opts) {
25987
26252
  const notices = [];
25988
26253
  const p = this.getComponentPath(spec.id, spec.subsystem);
25989
- ensureDir(path24.dirname(p));
26254
+ ensureDir(path28.dirname(p));
25990
26255
  const specToWrite = this.prepareComponentForWrite(spec);
25991
26256
  const existing = this.loadComponentSpec(spec.id);
25992
26257
  if (existing) {
@@ -26003,7 +26268,7 @@ var init_specs2 = __esm({
26003
26268
  const subsystemChanged = existing && existing.subsystem !== spec.subsystem && splitNamespace(existing.subsystem).localId !== splitNamespace(spec.subsystem).localId;
26004
26269
  if (subsystemChanged && !p.endsWith(".index.yaml")) {
26005
26270
  notices.push(
26006
- `component "${spec.id}" already exists at ${path24.relative(this.rootDir, p)} \u2014 the flat layout re-saves in place and never relocates the file. The subsystem field is now "${spec.subsystem}" (was "${existing.subsystem}").`
26271
+ `component "${spec.id}" already exists at ${path28.relative(this.rootDir, p)} \u2014 the flat layout re-saves in place and never relocates the file. The subsystem field is now "${spec.subsystem}" (was "${existing.subsystem}").`
26007
26272
  );
26008
26273
  }
26009
26274
  specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
@@ -26027,12 +26292,12 @@ var init_specs2 = __esm({
26027
26292
  if (owner) {
26028
26293
  const ownerPath = index.paths.component[owner.id];
26029
26294
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
26030
- const ownerSubDir = path24.dirname(this.getSubsystemPath(owner.subsystem));
26031
- return path24.join(ownerSubDir, owner.id, comp.id);
26295
+ const ownerSubDir = path28.dirname(this.getSubsystemPath(owner.subsystem));
26296
+ return path28.join(ownerSubDir, owner.id, comp.id);
26032
26297
  }
26033
26298
  }
26034
- const subDir = path24.dirname(this.getSubsystemPath(comp.subsystem));
26035
- return path24.join(subDir, comp.id);
26299
+ const subDir = path28.dirname(this.getSubsystemPath(comp.subsystem));
26300
+ return path28.join(subDir, comp.id);
26036
26301
  }
26037
26302
  /**
26038
26303
  * Move component folders so the physical tree mirrors ownership: each owned
@@ -26048,7 +26313,7 @@ var init_specs2 = __esm({
26048
26313
  if (!currentPath) continue;
26049
26314
  const desiredDir = this.desiredComponentDir(comp, index);
26050
26315
  if (!desiredDir) continue;
26051
- if (moveComponentFolder(path24.dirname(currentPath), desiredDir)) moved.push(comp.id);
26316
+ if (moveComponentFolder(path28.dirname(currentPath), desiredDir)) moved.push(comp.id);
26052
26317
  }
26053
26318
  if (moved.length) invalidateSpecCache();
26054
26319
  return moved;
@@ -26104,7 +26369,7 @@ var init_specs2 = __esm({
26104
26369
  if (!occupantId) return;
26105
26370
  if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
26106
26371
  throw new Error(
26107
- `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path24.relative(this.rootDir, p)}, and both ids resolve to that one file. Re-author "${occupantId}" instead, or delete it first if you meant to replace it.`
26372
+ `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path28.relative(this.rootDir, p)}, and both ids resolve to that one file. Re-author "${occupantId}" instead, or delete it first if you meant to replace it.`
26108
26373
  );
26109
26374
  }
26110
26375
  /** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
@@ -26112,12 +26377,12 @@ var init_specs2 = __esm({
26112
26377
  const notices = [];
26113
26378
  const p = this.getInterfacePath(spec.id, spec.component);
26114
26379
  this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
26115
- ensureDir(path24.dirname(p));
26380
+ ensureDir(path28.dirname(p));
26116
26381
  const specToWrite = this.prepareInterfaceForWrite(spec);
26117
26382
  const existing = this.loadInterfaceSpec(spec.id);
26118
26383
  if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
26119
26384
  notices.push(
26120
- `interface "${spec.id}" already exists at ${path24.relative(this.rootDir, p)} \u2014 re-saving updates the component binding field in place (now "${spec.component}", was "${existing.component}") and never moves the file.`
26385
+ `interface "${spec.id}" already exists at ${path28.relative(this.rootDir, p)} \u2014 re-saving updates the component binding field in place (now "${spec.component}", was "${existing.component}") and never moves the file.`
26121
26386
  );
26122
26387
  }
26123
26388
  if (existing) {
@@ -26174,12 +26439,12 @@ var init_specs2 = __esm({
26174
26439
  const notices = [];
26175
26440
  const p = this.getImplementationPath(spec.id, spec.contract);
26176
26441
  this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
26177
- ensureDir(path24.dirname(p));
26442
+ ensureDir(path28.dirname(p));
26178
26443
  const specToWrite = this.prepareImplementationForWrite(spec);
26179
26444
  const existing = this.loadImplementationSpec(spec.id);
26180
26445
  if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
26181
26446
  notices.push(
26182
- `implementation "${spec.id}" already exists at ${path24.relative(this.rootDir, p)} \u2014 re-saving updates the contract binding field in place (now "${spec.contract}", was "${existing.contract}") and never moves the file.`
26447
+ `implementation "${spec.id}" already exists at ${path28.relative(this.rootDir, p)} \u2014 re-saving updates the contract binding field in place (now "${spec.contract}", was "${existing.contract}") and never moves the file.`
26183
26448
  );
26184
26449
  }
26185
26450
  if (existing) {
@@ -26220,11 +26485,11 @@ var init_specs2 = __esm({
26220
26485
  const existing = this.loadTypeSpec(spec.id);
26221
26486
  const group = spec.group || (existing ? existing.group : void 0);
26222
26487
  const p = this.getTypePath(spec.id, spec.subsystem, group);
26223
- ensureDir(path24.dirname(p));
26488
+ ensureDir(path28.dirname(p));
26224
26489
  const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
26225
26490
  if (subsystemChanged) {
26226
26491
  notices.push(
26227
- `type "${spec.id}" already exists at ${path24.relative(this.rootDir, p)} \u2014 re-saving updates fields in place and never relocates the file. The subsystem field is now "${spec.subsystem ?? "(none)"}" (was "${existing.subsystem ?? "(none)"}").`
26492
+ `type "${spec.id}" already exists at ${path28.relative(this.rootDir, p)} \u2014 re-saving updates fields in place and never relocates the file. The subsystem field is now "${spec.subsystem ?? "(none)"}" (was "${existing.subsystem ?? "(none)"}").`
26228
26493
  );
26229
26494
  }
26230
26495
  if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
@@ -26262,7 +26527,7 @@ var init_specs2 = __esm({
26262
26527
  }
26263
26528
  saveGroupSpec(spec, opts) {
26264
26529
  const p = this.getGroupPath(spec.id);
26265
- ensureDir(path24.dirname(p));
26530
+ ensureDir(path28.dirname(p));
26266
26531
  const specToWrite = this.prepareGroupForWrite(spec);
26267
26532
  const existing = this.loadGroupSpec(spec.id);
26268
26533
  if (existing) {
@@ -26340,7 +26605,7 @@ var init_specs2 = __esm({
26340
26605
  };
26341
26606
  const out = /* @__PURE__ */ new Set();
26342
26607
  const add = (p) => {
26343
- if (p) out.add(path24.resolve(p));
26608
+ if (p) out.add(path28.resolve(p));
26344
26609
  };
26345
26610
  for (const s of this.loadSubsystemSpecs()) {
26346
26611
  if (!scopeSubsystem || s.id === scopeSubsystem || s.id.startsWith(`${scopeSubsystem}::`)) {
@@ -26411,11 +26676,11 @@ var init_specs2 = __esm({
26411
26676
  const files = /* @__PURE__ */ new Set();
26412
26677
  const sysPath = this.paths.specsSystem();
26413
26678
  if (pathExists(sysPath)) {
26414
- files.add(path24.resolve(sysPath));
26679
+ files.add(path28.resolve(sysPath));
26415
26680
  }
26416
26681
  for (const group of Object.values(index.paths)) {
26417
26682
  for (const file of Object.values(group)) {
26418
- files.add(path24.resolve(file));
26683
+ files.add(path28.resolve(file));
26419
26684
  }
26420
26685
  }
26421
26686
  for (const file of files) {
@@ -26434,20 +26699,20 @@ var init_specs2 = __esm({
26434
26699
  const files = listSpecFiles(specsDir);
26435
26700
  const legacy = [];
26436
26701
  for (const f of files) {
26437
- const base = path24.basename(f);
26438
- const dir = path24.dirname(f);
26702
+ const base = path28.basename(f);
26703
+ const dir = path28.dirname(f);
26439
26704
  if (base === "system.yaml") {
26440
- legacy.push({ path: f, expected: path24.join(dir, ".index.yaml") });
26705
+ legacy.push({ path: f, expected: path28.join(dir, ".index.yaml") });
26441
26706
  } else if (base === "subsystem.yaml") {
26442
- legacy.push({ path: f, expected: path24.join(dir, ".index.yaml") });
26707
+ legacy.push({ path: f, expected: path28.join(dir, ".index.yaml") });
26443
26708
  } else if (base === "component.yaml") {
26444
- legacy.push({ path: f, expected: path24.join(dir, ".index.yaml") });
26709
+ legacy.push({ path: f, expected: path28.join(dir, ".index.yaml") });
26445
26710
  } else if (base === "group.yaml") {
26446
- legacy.push({ path: f, expected: path24.join(dir, ".index.yaml") });
26711
+ legacy.push({ path: f, expected: path28.join(dir, ".index.yaml") });
26447
26712
  } else if (base === "interface.yaml") {
26448
- legacy.push({ path: f, expected: path24.join(dir, ".interface.yaml") });
26713
+ legacy.push({ path: f, expected: path28.join(dir, ".interface.yaml") });
26449
26714
  } else if (base === "implementation.yaml") {
26450
- legacy.push({ path: f, expected: path24.join(dir, ".implementation.yaml") });
26715
+ legacy.push({ path: f, expected: path28.join(dir, ".implementation.yaml") });
26451
26716
  }
26452
26717
  }
26453
26718
  return legacy;
@@ -27459,7 +27724,7 @@ __export(agent_resolver_exports, {
27459
27724
  });
27460
27725
  function listFilesRecursiveSafe(dirPath, ext) {
27461
27726
  if (!fs19.existsSync(dirPath)) return [];
27462
- const nameLower = path25.basename(dirPath).toLowerCase();
27727
+ const nameLower = path29.basename(dirPath).toLowerCase();
27463
27728
  const IGNORED_DIRS = /* @__PURE__ */ new Set([
27464
27729
  "node_modules",
27465
27730
  "target",
@@ -27477,7 +27742,7 @@ function listFilesRecursiveSafe(dirPath, ext) {
27477
27742
  const entries = fs19.readdirSync(dirPath, { withFileTypes: true });
27478
27743
  const files = [];
27479
27744
  for (const entry of entries) {
27480
- const fullPath = path25.join(dirPath, entry.name);
27745
+ const fullPath = path29.join(dirPath, entry.name);
27481
27746
  if (entry.isDirectory()) {
27482
27747
  files.push(...listFilesRecursiveSafe(fullPath, ext));
27483
27748
  } else if (entry.isFile() && entry.name.endsWith(ext)) {
@@ -27490,8 +27755,8 @@ function getProjectFiles(projectDir) {
27490
27755
  let files = projectFilesCache.get(projectDir);
27491
27756
  if (!files) {
27492
27757
  files = [];
27493
- const srcDir = path25.join(projectDir, "src");
27494
- const legacySrcDir = path25.join(projectDir, "legacy-src");
27758
+ const srcDir = path29.join(projectDir, "src");
27759
+ const legacySrcDir = path29.join(projectDir, "legacy-src");
27495
27760
  let searchDir = projectDir;
27496
27761
  if (pathExists(srcDir)) {
27497
27762
  searchDir = srcDir;
@@ -27506,7 +27771,7 @@ function getProjectFiles(projectDir) {
27506
27771
  files.push(...listFilesRecursiveSafe(searchDir, ext));
27507
27772
  }
27508
27773
  const rootDir = getProjectRoot();
27509
- files = files.map((f) => path25.relative(rootDir, f).replace(/\\/g, "/"));
27774
+ files = files.map((f) => path29.relative(rootDir, f).replace(/\\/g, "/"));
27510
27775
  projectFilesCache.set(projectDir, files);
27511
27776
  }
27512
27777
  return files;
@@ -27531,8 +27796,8 @@ function inferSourcePathForComponent(comp, subsystems) {
27531
27796
  let bestFile = null;
27532
27797
  let bestScore = -1;
27533
27798
  for (const f of files) {
27534
- const ext = path25.extname(f);
27535
- const base = path25.basename(f, ext).toLowerCase();
27799
+ const ext = path29.extname(f);
27800
+ const base = path29.basename(f, ext).toLowerCase();
27536
27801
  if (candidates.has(base)) {
27537
27802
  let score = 0;
27538
27803
  const normalizedPath = f.toLowerCase();
@@ -27629,7 +27894,7 @@ function resolveAgentTopology() {
27629
27894
  });
27630
27895
  for (const sub of subsystems) {
27631
27896
  if (sub.projectPath) {
27632
- const mountSpecPath = path25.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
27897
+ const mountSpecPath = path29.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
27633
27898
  agents.push({
27634
27899
  id: `${sub.id}-owner`,
27635
27900
  name: `${sub.name} (chained subproject)`,
@@ -27651,9 +27916,9 @@ function resolveAgentTopology() {
27651
27916
  }
27652
27917
  const subComponents = components.filter((c) => c.subsystem === sub.id);
27653
27918
  const ownedPaths = [];
27654
- ownedPaths.push(path25.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
27919
+ ownedPaths.push(path29.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
27655
27920
  for (const c of subComponents) {
27656
- ownedPaths.push(path25.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
27921
+ ownedPaths.push(path29.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
27657
27922
  }
27658
27923
  if (!config.rules.generateComponentImplementers) {
27659
27924
  for (const comp of subComponents) {
@@ -27729,10 +27994,10 @@ function resolveAgentTopology() {
27729
27994
  }
27730
27995
  const dependencies = comp.dependsOn.map((depId) => `${depId}-implementer`);
27731
27996
  const readPaths = [
27732
- path25.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
27733
- path25.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
27734
- ...compInterfaces.map((i) => path25.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
27735
- ...compImpls.map((impl) => path25.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
27997
+ path29.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
27998
+ path29.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
27999
+ ...compInterfaces.map((i) => path29.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
28000
+ ...compImpls.map((impl) => path29.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
27736
28001
  ];
27737
28002
  agents.push({
27738
28003
  id: `${comp.id}-implementer`,
@@ -27821,11 +28086,11 @@ ${guidance.trim()}
27821
28086
  budget
27822
28087
  };
27823
28088
  }
27824
- var path25, fs19, projectFilesCache, UnknownAgentError;
28089
+ var path29, fs19, projectFilesCache, UnknownAgentError;
27825
28090
  var init_agent_resolver = __esm({
27826
28091
  "src/core/agent_resolver.ts"() {
27827
28092
  "use strict";
27828
- path25 = __toESM(require("path"));
28093
+ path29 = __toESM(require("path"));
27829
28094
  fs19 = __toESM(require("fs"));
27830
28095
  init_loader();
27831
28096
  init_project_config();
@@ -27859,12 +28124,12 @@ __export(loader_exports, {
27859
28124
  saveTopologyConfig: () => saveTopologyConfig
27860
28125
  });
27861
28126
  function aiPathsAt(rootDir) {
27862
- const resolvedRoot = path26.resolve(rootDir);
28127
+ const resolvedRoot = path30.resolve(rootDir);
27863
28128
  const aiDirAt2 = (...segments) => {
27864
- const waiPath = path26.join(resolvedRoot, ".wai");
27865
- const waironPath = path26.join(resolvedRoot, ".wairon");
28129
+ const waiPath = path30.join(resolvedRoot, ".wai");
28130
+ const waironPath = path30.join(resolvedRoot, ".wairon");
27866
28131
  const base = !fs20.existsSync(waiPath) && fs20.existsSync(waironPath) ? waironPath : waiPath;
27867
- return path26.join(base, ...segments);
28132
+ return path30.join(base, ...segments);
27868
28133
  };
27869
28134
  const specsDir = () => projectConfigRepositoryAt(resolvedRoot).specsDir();
27870
28135
  return {
@@ -27881,12 +28146,12 @@ function aiPathsAt(rootDir) {
27881
28146
  contextDomainsMd: () => aiDirAt2("context", "domains.md"),
27882
28147
  contextWaironGuideMd: () => aiDirAt2("context", "wairon-guide.md"),
27883
28148
  specsDir,
27884
- specsSystem: () => path26.join(specsDir(), ".index.yaml"),
27885
- specsSubsystemsDir: () => path26.join(specsDir(), "subsystems"),
27886
- specsComponentsDir: () => path26.join(specsDir(), "components"),
27887
- specsInterfacesDir: () => path26.join(specsDir(), "interfaces"),
27888
- specsImplementationsDir: () => path26.join(specsDir(), "implementations"),
27889
- specsTypesDir: () => path26.join(specsDir(), "types")
28149
+ specsSystem: () => path30.join(specsDir(), ".index.yaml"),
28150
+ specsSubsystemsDir: () => path30.join(specsDir(), "subsystems"),
28151
+ specsComponentsDir: () => path30.join(specsDir(), "components"),
28152
+ specsInterfacesDir: () => path30.join(specsDir(), "interfaces"),
28153
+ specsImplementationsDir: () => path30.join(specsDir(), "implementations"),
28154
+ specsTypesDir: () => path30.join(specsDir(), "types")
27890
28155
  };
27891
28156
  }
27892
28157
  function isProjectInitialized() {
@@ -27917,12 +28182,12 @@ function loadTopologyConfig() {
27917
28182
  function saveTopologyConfig(config) {
27918
28183
  writeYamlFile(AI_PATHS.topologyConfig(), config);
27919
28184
  }
27920
- var fs20, path26, AI_PATHS;
28185
+ var fs20, path30, AI_PATHS;
27921
28186
  var init_loader = __esm({
27922
28187
  "src/config/loader.ts"() {
27923
28188
  "use strict";
27924
28189
  fs20 = __toESM(require("fs"));
27925
- path26 = __toESM(require("path"));
28190
+ path30 = __toESM(require("path"));
27926
28191
  init_fs();
27927
28192
  init_yaml();
27928
28193
  init_errors();
@@ -29990,7 +30255,7 @@ async function scopeToClientWorkspace(server) {
29990
30255
  } catch {
29991
30256
  dir = null;
29992
30257
  }
29993
- if (dir && (fs21.existsSync(path28.join(dir, ".wai")) || fs21.existsSync(path28.join(dir, ".wairon")))) {
30258
+ if (dir && (fs21.existsSync(path32.join(dir, ".wai")) || fs21.existsSync(path32.join(dir, ".wairon")))) {
29994
30259
  setProjectRoot(dir);
29995
30260
  process.stderr.write(`[wairon mcp] scoped to client workspace root: ${dir}
29996
30261
  `);
@@ -30014,7 +30279,7 @@ async function startMcpServer() {
30014
30279
  } catch {
30015
30280
  }
30016
30281
  }
30017
- var import_mcp, import_stdio, import_zod11, import_types3, fs21, path28, import_url, TYPE_REF_GRAMMAR, staleServerOutput, SPEC_KINDS, STATUS_ORDER, specWriteReceiptOutput, specChangeOutput, specChangeReportOutput, validationIssueOutput, validateTreeOutput, getSpecOutput, SERVER_BUILD_STAMP, STALE_SERVER_WARNING, SPEC_WRITE_TOOLS, listChangedEmitters, STORE_MANAGED_FIELDS, statusInput, ALWAYS_CARRIED_FIELDS, SKILL_RESOURCE_MIME, AGENT_BRIEF_SCHEME;
30282
+ var import_mcp, import_stdio, import_zod11, import_types3, fs21, path32, import_url, TYPE_REF_GRAMMAR, staleServerOutput, SPEC_KINDS, STATUS_ORDER, specWriteReceiptOutput, specChangeOutput, specChangeReportOutput, validationIssueOutput, validateTreeOutput, getSpecOutput, SERVER_BUILD_STAMP, STALE_SERVER_WARNING, SPEC_WRITE_TOOLS, listChangedEmitters, STORE_MANAGED_FIELDS, statusInput, ALWAYS_CARRIED_FIELDS, SKILL_RESOURCE_MIME, AGENT_BRIEF_SCHEME;
30018
30283
  var init_server = __esm({
30019
30284
  "src/mcp/server.ts"() {
30020
30285
  "use strict";
@@ -30023,7 +30288,7 @@ var init_server = __esm({
30023
30288
  import_zod11 = require("zod");
30024
30289
  import_types3 = require("@modelcontextprotocol/sdk/types.js");
30025
30290
  fs21 = __toESM(require("fs"));
30026
- path28 = __toESM(require("path"));
30291
+ path32 = __toESM(require("path"));
30027
30292
  import_url = require("url");
30028
30293
  init_fs();
30029
30294
  init_yaml();
@@ -30197,18 +30462,18 @@ __export(mcp_exports, {
30197
30462
  validateConfigDir: () => validateConfigDir
30198
30463
  });
30199
30464
  function geminiGlobalDir(override) {
30200
- return override || process.env["GEMINI_CONFIG_DIR"] || path29.join(os7.homedir(), ".gemini");
30465
+ return override || process.env["GEMINI_CONFIG_DIR"] || path33.join(os7.homedir(), ".gemini");
30201
30466
  }
30202
30467
  function claudeMcpConfigPath(useGlobal, override) {
30203
- if (!useGlobal) return path29.join(process.cwd(), ".mcp.json");
30468
+ if (!useGlobal) return path33.join(process.cwd(), ".mcp.json");
30204
30469
  const dir = override || process.env["CLAUDE_CONFIG_DIR"];
30205
- return dir ? path29.join(dir, ".claude.json") : path29.join(os7.homedir(), ".claude.json");
30470
+ return dir ? path33.join(dir, ".claude.json") : path33.join(os7.homedir(), ".claude.json");
30206
30471
  }
30207
30472
  function validateConfigDir(dir, backend) {
30208
- const resolved = path29.resolve(dir);
30473
+ const resolved = path33.resolve(dir);
30209
30474
  const agent = backend === "claude" ? "Claude" : "Gemini/Antigravity";
30210
30475
  if (!fs22.existsSync(resolved)) {
30211
- const parent = path29.dirname(resolved);
30476
+ const parent = path33.dirname(resolved);
30212
30477
  if (!fs22.existsSync(parent)) {
30213
30478
  throw new WaironError(`--config-dir "${dir}" does not exist and its parent is missing \u2014 check the path.`);
30214
30479
  }
@@ -30224,7 +30489,7 @@ function validateConfigDir(dir, backend) {
30224
30489
  logger.warn(`Config dir "${resolved}" is empty; proceeding (treating it as a fresh ${agent} config dir).`);
30225
30490
  return;
30226
30491
  }
30227
- if (!markers.some((m) => fs22.existsSync(path29.join(resolved, m)))) {
30492
+ if (!markers.some((m) => fs22.existsSync(path33.join(resolved, m)))) {
30228
30493
  throw new WaironError(
30229
30494
  `"${dir}" does not look like a ${agent} config directory (none of ${markers.slice(0, 4).join(", ")} found). Point --config-dir at the agent's config directory.`
30230
30495
  );
@@ -30232,12 +30497,12 @@ function validateConfigDir(dir, backend) {
30232
30497
  }
30233
30498
  async function runMcpServe() {
30234
30499
  const { setProjectRoot: setProjectRoot2, getProjectRoot: getProjectRoot2, findProjectRoot: findProjectRoot2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
30235
- const cwd = path29.resolve(process.cwd());
30500
+ const cwd = path33.resolve(process.cwd());
30236
30501
  const envDir = process.env["WAIRON_PROJECT_DIR"];
30237
30502
  let resolved;
30238
30503
  let how;
30239
- if (envDir && fs22.existsSync(path29.join(envDir, ".wai"))) {
30240
- resolved = path29.resolve(envDir);
30504
+ if (envDir && fs22.existsSync(path33.join(envDir, ".wai"))) {
30505
+ resolved = path33.resolve(envDir);
30241
30506
  how = "WAIRON_PROJECT_DIR (pinned at install)";
30242
30507
  } else {
30243
30508
  const found = findProjectRoot2(cwd);
@@ -30263,10 +30528,10 @@ async function runMcpServe() {
30263
30528
  }
30264
30529
  function mcpConfigCandidates(cwd) {
30265
30530
  return [
30266
- path29.join(cwd, ".mcp.json"),
30531
+ path33.join(cwd, ".mcp.json"),
30267
30532
  claudeMcpConfigPath(true),
30268
- path29.join(cwd, ".gemini", "settings.json"),
30269
- path29.join(geminiGlobalDir(), "antigravity-cli", "mcp_config.json")
30533
+ path33.join(cwd, ".gemini", "settings.json"),
30534
+ path33.join(geminiGlobalDir(), "antigravity-cli", "mcp_config.json")
30270
30535
  ];
30271
30536
  }
30272
30537
  function detectHostedMcpSource(cwd = process.cwd()) {
@@ -30353,15 +30618,15 @@ async function runMcpInstall(options = {}) {
30353
30618
  let settingsPath;
30354
30619
  if (backend === "gemini") {
30355
30620
  if (useGlobal) {
30356
- configBase = path29.join(geminiGlobalDir(options.configDir), "antigravity-cli");
30357
- settingsPath = path29.join(configBase, "mcp_config.json");
30621
+ configBase = path33.join(geminiGlobalDir(options.configDir), "antigravity-cli");
30622
+ settingsPath = path33.join(configBase, "mcp_config.json");
30358
30623
  } else {
30359
- configBase = path29.join(process.cwd(), ".gemini");
30360
- settingsPath = path29.join(configBase, "settings.json");
30624
+ configBase = path33.join(process.cwd(), ".gemini");
30625
+ settingsPath = path33.join(configBase, "settings.json");
30361
30626
  }
30362
30627
  } else {
30363
30628
  settingsPath = claudeMcpConfigPath(useGlobal, options.configDir);
30364
- configBase = path29.dirname(settingsPath);
30629
+ configBase = path33.dirname(settingsPath);
30365
30630
  }
30366
30631
  let settings = {};
30367
30632
  if (fs22.existsSync(settingsPath)) {
@@ -30374,7 +30639,7 @@ async function runMcpInstall(options = {}) {
30374
30639
  const mcpServers = settings["mcpServers"] ?? {};
30375
30640
  const agentLabel = backend === "gemini" ? "Antigravity" : "Claude";
30376
30641
  const isPackaged = typeof process.pkg !== "undefined";
30377
- const scriptPath = process.argv[1] ? path29.resolve(process.argv[1]).replace(/\\/g, "/") : null;
30642
+ const scriptPath = process.argv[1] ? path33.resolve(process.argv[1]).replace(/\\/g, "/") : null;
30378
30643
  const useDirectNode = !isPackaged && scriptPath && (scriptPath.endsWith(".js") || scriptPath.endsWith(".ts"));
30379
30644
  const env = useGlobal ? {} : { WAIRON_PROJECT_DIR: process.cwd().replace(/\\/g, "/") };
30380
30645
  const desiredEntry = options.hostedUrl ? hostedMcpEntry(options) : useDirectNode ? { command: "node", args: [scriptPath, "mcp", "serve"], env } : { command: "wairon", args: ["mcp", "serve"], env };
@@ -30413,8 +30678,8 @@ async function runMcpStatus() {
30413
30678
  if (!projectConfig) throw new ProjectNotInitializedError();
30414
30679
  const claudeProject = claudeMcpConfigPath(false);
30415
30680
  const claudeGlobal = claudeMcpConfigPath(true);
30416
- const geminiProject = path29.join(process.cwd(), ".gemini", "settings.json");
30417
- const geminiGlobal = path29.join(geminiGlobalDir(), "antigravity-cli", "mcp_config.json");
30681
+ const geminiProject = path33.join(process.cwd(), ".gemini", "settings.json");
30682
+ const geminiGlobal = path33.join(geminiGlobalDir(), "antigravity-cli", "mcp_config.json");
30418
30683
  logger.blank();
30419
30684
  logger.info(`${import_chalk5.default.bold("wairon MCP Server")}`);
30420
30685
  logger.blank();
@@ -30464,7 +30729,7 @@ function hostedMcpEntry(options) {
30464
30729
  }
30465
30730
  function removeLegacyGlobalPlugin() {
30466
30731
  const home = process.env["USERPROFILE"] ?? process.env["HOME"] ?? os7.homedir();
30467
- const pluginDir = path29.join(home, ".gemini", "config", "plugins", "wairon");
30732
+ const pluginDir = path33.join(home, ".gemini", "config", "plugins", "wairon");
30468
30733
  try {
30469
30734
  if (fs22.existsSync(pluginDir)) {
30470
30735
  fs22.rmSync(pluginDir, { recursive: true, force: true });
@@ -30476,13 +30741,13 @@ function removeLegacyGlobalPlugin() {
30476
30741
  }
30477
30742
  return false;
30478
30743
  }
30479
- var fs22, os7, path29, import_chalk5;
30744
+ var fs22, os7, path33, import_chalk5;
30480
30745
  var init_mcp = __esm({
30481
30746
  "src/commands/mcp.ts"() {
30482
30747
  "use strict";
30483
30748
  fs22 = __toESM(require("fs"));
30484
30749
  os7 = __toESM(require("os"));
30485
- path29 = __toESM(require("path"));
30750
+ path33 = __toESM(require("path"));
30486
30751
  import_chalk5 = __toESM(require("chalk"));
30487
30752
  init_logger();
30488
30753
  init_loader();
@@ -30726,7 +30991,7 @@ function isSupportedAlias(name) {
30726
30991
  }
30727
30992
 
30728
30993
  // src/commands/init.ts
30729
- var path30 = __toESM(require("path"));
30994
+ var path34 = __toESM(require("path"));
30730
30995
  var import_chalk6 = __toESM(require("chalk"));
30731
30996
  var import_inquirer = __toESM(require("inquirer"));
30732
30997
  init_logger();
@@ -30737,12 +31002,13 @@ init_yaml();
30737
31002
  init_loader();
30738
31003
 
30739
31004
  // src/commands/subsystem.ts
30740
- var path27 = __toESM(require("path"));
31005
+ var path31 = __toESM(require("path"));
30741
31006
  init_logger();
30742
31007
  init_errors();
30743
31008
  init_fs();
30744
31009
  init_core();
30745
31010
  init_core();
31011
+ init_core();
30746
31012
  function composeAgentBrief2(agentId) {
30747
31013
  return composeAgentBrief(agentId);
30748
31014
  }
@@ -30791,6 +31057,15 @@ function defaultPackSelections2() {
30791
31057
  function readLockState2(current2) {
30792
31058
  return readLockState(current2);
30793
31059
  }
31060
+ function renderDiagram2(format) {
31061
+ return renderDiagram(format);
31062
+ }
31063
+ function generateAll2(agents, config, options) {
31064
+ return generateAll(agents, config, options);
31065
+ }
31066
+ function resolveExpectedOutputPaths2(agents, config) {
31067
+ return resolveExpectedOutputPaths(agents, config);
31068
+ }
30794
31069
  async function runSubsystemAdd(id, options = {}) {
30795
31070
  logger.header("wairon subsystem add");
30796
31071
  if (!projectConfigExists2()) {
@@ -30820,9 +31095,9 @@ async function runSubsystemAdd(id, options = {}) {
30820
31095
  updatedAt: now
30821
31096
  };
30822
31097
  createChainedSubsystem2(subsystem, displayName);
30823
- const childDir = path27.resolve(getProjectRoot(), options.projectPath);
31098
+ const childDir = path31.resolve(getProjectRoot(), options.projectPath);
30824
31099
  logger.success(`Added external subsystem "${id}" \u2192 ${options.projectPath}`);
30825
- logger.info(`Scaffolded child project at ${path27.relative(process.cwd(), childDir) || "."}`);
31100
+ logger.info(`Scaffolded child project at ${path31.relative(process.cwd(), childDir) || "."}`);
30826
31101
  logger.info(`Design its spec tree from this parent using namespaced ids (e.g. ${id}::<component>).`);
30827
31102
  }
30828
31103
  async function runSubsystemMove(id, options = {}) {
@@ -30845,9 +31120,9 @@ async function runSubsystemExternalize(id, options = {}) {
30845
31120
  throw new WaironError("--project-path (the subproject destination) is required.");
30846
31121
  }
30847
31122
  externalizeSubsystem(id, options.projectPath);
30848
- const childDir = path27.resolve(getProjectRoot(), options.projectPath);
31123
+ const childDir = path31.resolve(getProjectRoot(), options.projectPath);
30849
31124
  logger.success(`Externalized subsystem "${id}" \u2192 ${options.projectPath}`);
30850
- logger.info(`Moved its specs into ${path27.relative(process.cwd(), childDir) || "."} (now a standalone subproject).`);
31125
+ logger.info(`Moved its specs into ${path31.relative(process.cwd(), childDir) || "."} (now a standalone subproject).`);
30851
31126
  logger.info("Move the source code there yourself, then run `wairon validate` to confirm the tree.");
30852
31127
  }
30853
31128
  async function runSubsystemInternalize(id) {
@@ -30904,7 +31179,7 @@ async function runInit(options = {}) {
30904
31179
  logger.header("wairon init");
30905
31180
  const cwd = process.cwd();
30906
31181
  const ancestorRoot = findSystemRoot(cwd);
30907
- if (ancestorRoot && path30.resolve(ancestorRoot) === path30.resolve(cwd)) {
31182
+ if (ancestorRoot && path34.resolve(ancestorRoot) === path34.resolve(cwd)) {
30908
31183
  logger.info("Project already initialized.");
30909
31184
  logger.info("Design your spec tree with the SDD architect skill, then run `wairon generate`.");
30910
31185
  return;
@@ -30920,8 +31195,8 @@ async function runInit(options = {}) {
30920
31195
  await runInitInteractive();
30921
31196
  }
30922
31197
  async function runInitAsExternalSubsystem(parentRoot, cwd, options) {
30923
- const relPath = path30.relative(parentRoot, cwd) || ".";
30924
- const defaultId = path30.basename(cwd);
31198
+ const relPath = path34.relative(parentRoot, cwd) || ".";
31199
+ const defaultId = path34.basename(cwd);
30925
31200
  logger.info(`Detected a parent wairon project at ${parentRoot}`);
30926
31201
  logger.info(`This directory ("${relPath}") is not yet a wairon project.`);
30927
31202
  if (!options.yes) {
@@ -30981,7 +31256,7 @@ async function runInitAsExternalSubsystem(parentRoot, cwd, options) {
30981
31256
  }
30982
31257
  async function runInitNonInteractive() {
30983
31258
  const cwd = process.cwd();
30984
- const projectName = path30.basename(cwd);
31259
+ const projectName = path34.basename(cwd);
30985
31260
  const now = (/* @__PURE__ */ new Date()).toISOString();
30986
31261
  const targets = [defaultTargetConfig("claude"), defaultTargetConfig("agy")];
30987
31262
  const projectConfig = buildProjectConfig(projectName, targets, now, "backend");
@@ -31001,7 +31276,7 @@ async function runInitNonInteractive() {
31001
31276
  }
31002
31277
  async function runInitInteractive() {
31003
31278
  const cwd = process.cwd();
31004
- const defaultProjectName = path30.basename(cwd);
31279
+ const defaultProjectName = path34.basename(cwd);
31005
31280
  const { projectName } = await import_inquirer.default.prompt([
31006
31281
  {
31007
31282
  type: "input",
@@ -31146,7 +31421,7 @@ async function executeInit(projectName, projectConfig, guidePlan) {
31146
31421
  if (guidePlan.claudeLocal) {
31147
31422
  const p = localGuideFilePath(projectRoot2, "claude");
31148
31423
  injectGuide(p, "local");
31149
- logger.success(`Injected wairon guide into ${path30.relative(cwd, p)}`);
31424
+ logger.success(`Injected wairon guide into ${path34.relative(cwd, p)}`);
31150
31425
  writeRootGuideDelegator(projectRoot2, "claude");
31151
31426
  logger.success(`Created root CLAUDE.md delegator pointing to .claude/CLAUDE.md`);
31152
31427
  }
@@ -31158,7 +31433,7 @@ async function executeInit(projectName, projectConfig, guidePlan) {
31158
31433
  if (guidePlan.geminiLocal) {
31159
31434
  const p = localGuideFilePath(projectRoot2, "gemini");
31160
31435
  injectGuide(p, "local");
31161
- logger.success(`Injected wairon guide into ${path30.relative(cwd, p)}`);
31436
+ logger.success(`Injected wairon guide into ${path34.relative(cwd, p)}`);
31162
31437
  writeRootGuideDelegator(projectRoot2, "gemini");
31163
31438
  logger.success(`Created root GEMINI.md delegator pointing to .gemini/GEMINI.md`);
31164
31439
  }
@@ -31378,232 +31653,7 @@ var path35 = __toESM(require("path"));
31378
31653
  init_logger();
31379
31654
  init_loader();
31380
31655
  init_errors();
31381
-
31382
- // src/exporters/generate.ts
31383
- var path34 = __toESM(require("path"));
31384
- init_core();
31385
- init_execution_profile();
31386
- init_budget_policy();
31387
- init_fs();
31388
-
31389
- // src/exporters/claude.ts
31390
- var path31 = __toESM(require("path"));
31391
- init_fs();
31392
- var MODEL_BY_TIER = {
31393
- small: "haiku",
31394
- standard: "sonnet",
31395
- large: "opus",
31396
- frontier: "fable"
31397
- };
31398
- var TOOLS_BY_CLASS = {
31399
- "read-only": ["Read", "Grep", "Glob"],
31400
- implement: ["Read", "Grep", "Glob", "Edit", "Write", "Bash"],
31401
- orchestrate: ["Agent", "SendMessage", "TodoWrite"],
31402
- // `full` means "inherit everything" — expressed by omitting the field.
31403
- full: void 0
31404
- };
31405
- function toolsFor(budget) {
31406
- const base = TOOLS_BY_CLASS[budget.toolClass];
31407
- if (!base) return void 0;
31408
- if (budget.allowNestedDelegation && !base.includes("Agent")) {
31409
- return [...base, "Agent"];
31410
- }
31411
- if (!budget.allowNestedDelegation) {
31412
- return base.filter((t) => t !== "Agent");
31413
- }
31414
- return base;
31415
- }
31416
- function mcpServersFor(access) {
31417
- return access === "none" ? "[]" : void 0;
31418
- }
31419
- function yamlScalar(value) {
31420
- return /[:#\n]/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value;
31421
- }
31422
- var ClaudeExporter = class {
31423
- constructor(options = {}) {
31424
- this.options = options;
31425
- this.targetType = "claude";
31426
- }
31427
- outputPath(ctx) {
31428
- const { agent, target, projectRoot: projectRoot2 } = ctx;
31429
- const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
31430
- return path31.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
31431
- }
31432
- export(ctx) {
31433
- const { agent, renderedInstructions, budget } = ctx;
31434
- const filePath = this.outputPath(ctx);
31435
- const frontmatter = [
31436
- `name: ${agent.name}`,
31437
- `description: ${yamlScalar(agent.description)}`
31438
- ];
31439
- if (budget && this.options.emitBudget) {
31440
- if (budget.modelTier) frontmatter.push(`model: ${MODEL_BY_TIER[budget.modelTier]}`);
31441
- if (budget.effort) frontmatter.push(`effort: ${budget.effort}`);
31442
- if (budget.maxTurns !== void 0) frontmatter.push(`maxTurns: ${budget.maxTurns}`);
31443
- const tools = toolsFor(budget);
31444
- if (tools) frontmatter.push(`tools: ${tools.join(", ")}`);
31445
- const servers = mcpServersFor(budget.mcp);
31446
- if (servers) frontmatter.push(`mcpServers: ${servers}`);
31447
- }
31448
- const content = ["---", ...frontmatter, "---", "", renderedInstructions, ""].join("\n");
31449
- const changed = writeFileIfChanged(filePath, content);
31450
- return { outputPath: filePath, content, unchanged: !changed };
31451
- }
31452
- };
31453
-
31454
- // src/exporters/custom.ts
31455
- var path32 = __toESM(require("path"));
31456
- init_fs();
31457
- var CustomExporter = class {
31458
- constructor() {
31459
- this.targetType = "custom";
31460
- }
31461
- outputPath(ctx) {
31462
- const { agent, target, projectRoot: projectRoot2 } = ctx;
31463
- if (!("outputDir" in target)) {
31464
- throw new Error("CustomExporter requires target.outputDir");
31465
- }
31466
- return path32.resolve(projectRoot2, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
31467
- }
31468
- export(ctx) {
31469
- const { agent, target, renderedInstructions } = ctx;
31470
- const label = "label" in target ? target.label : "Custom";
31471
- const filePath = this.outputPath(ctx);
31472
- const content = [
31473
- "---",
31474
- `name: ${agent.name}`,
31475
- `description: ${agent.description}`,
31476
- `id: ${agent.id}`,
31477
- `target: ${label}`,
31478
- "---",
31479
- "",
31480
- renderedInstructions,
31481
- ""
31482
- ].join("\n");
31483
- const changed = writeFileIfChanged(filePath, content);
31484
- return { outputPath: filePath, content, unchanged: !changed };
31485
- }
31486
- };
31487
-
31488
- // src/exporters/gemini.ts
31489
- var path33 = __toESM(require("path"));
31490
- init_fs();
31491
- var GeminiExporter = class {
31492
- constructor() {
31493
- this.targetType = "gemini";
31494
- }
31495
- outputPath(ctx) {
31496
- const { agent, target, projectRoot: projectRoot2 } = ctx;
31497
- const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
31498
- return path33.resolve(projectRoot2, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
31499
- }
31500
- export(ctx) {
31501
- const { agent, renderedInstructions } = ctx;
31502
- const filePath = this.outputPath(ctx);
31503
- const indentedInstructions = renderedInstructions.split("\n").map((line2) => line2.length > 0 ? ` ${line2}` : "").join("\n");
31504
- const content = [
31505
- `name: ${yamlString(agent.name)}`,
31506
- `description: ${yamlString(agent.description)}`,
31507
- `system_prompt: |`,
31508
- indentedInstructions,
31509
- ""
31510
- ].join("\n");
31511
- const changed = writeFileIfChanged(filePath, content);
31512
- return { outputPath: filePath, content, unchanged: !changed };
31513
- }
31514
- };
31515
- function yamlString(value) {
31516
- if (/[:#\[\]{},&*!|>'"%@`]/.test(value) || value.startsWith(" ") || value.endsWith(" ")) {
31517
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
31518
- }
31519
- return value;
31520
- }
31521
-
31522
- // src/exporters/registry.ts
31523
- init_errors();
31524
- var EXPORTERS = /* @__PURE__ */ new Map([
31525
- ["claude", new ClaudeExporter({ emitBudget: true })],
31526
- ["gemini", new GeminiExporter()],
31527
- ["agy", new GeminiExporter()],
31528
- ["cursor", new ClaudeExporter()],
31529
- ["copilot", new ClaudeExporter()],
31530
- ["codex", new ClaudeExporter()],
31531
- ["custom", new CustomExporter()]
31532
- ]);
31533
- function getExporter(target) {
31534
- const type = typeof target === "string" ? target : target.type;
31535
- const exporter = EXPORTERS.get(type);
31536
- if (!exporter) {
31537
- throw new WaironError(`No exporter registered for target type: "${type}"`);
31538
- }
31539
- return exporter;
31540
- }
31541
-
31542
- // src/exporters/base.ts
31543
- var WAIRON_MANAGED_MARKER = "wairon:managed";
31544
- var WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
31545
-
31546
- // src/exporters/generate.ts
31547
- function generateAgent(agent, projectConfig, options = {}) {
31548
- const projectRoot2 = options.projectRoot ?? getProjectRoot();
31549
- const template = loadTemplate(agent.template, projectConfig.globalTemplatesDir);
31550
- const rendered = `${WAIRON_MANAGED_BANNER}
31551
- ${composeAgentBrief(agent.id).instructions}`;
31552
- const results = [];
31553
- const budget = resolveBudget(
31554
- deriveExecutionProfile(agent),
31555
- projectConfig.execution,
31556
- agent.id
31557
- );
31558
- for (const agentTarget of agent.targets) {
31559
- const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
31560
- if (!targetConfig) continue;
31561
- if (options.filterTargets) {
31562
- const type = "type" in targetConfig ? targetConfig.type : targetConfig;
31563
- if (!options.filterTargets.includes(type)) continue;
31564
- }
31565
- if (!options.dryRun) {
31566
- results.push(getExporter(targetConfig).export({
31567
- agent,
31568
- template,
31569
- renderedInstructions: rendered,
31570
- projectRoot: projectRoot2,
31571
- target: targetConfig,
31572
- budget
31573
- }));
31574
- }
31575
- }
31576
- return { agent, results };
31577
- }
31578
- function generateAll(agents, projectConfig, options = {}) {
31579
- let pool = agents;
31580
- if (options.filterDomainIds && options.filterDomainIds.length > 0) {
31581
- const ids = new Set(options.filterDomainIds);
31582
- pool = agents.filter((a) => ids.has(a.domainRoot ?? "root"));
31583
- }
31584
- return pool.map((agent) => generateAgent(agent, projectConfig, options));
31585
- }
31586
- function resolveExpectedOutputPaths(agents, projectConfig, projectRoot2 = getProjectRoot()) {
31587
- const expected = /* @__PURE__ */ new Set();
31588
- for (const agent of agents) {
31589
- for (const agentTarget of agent.targets) {
31590
- const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
31591
- if (!targetConfig) continue;
31592
- const ctx = { agent, projectRoot: projectRoot2, target: targetConfig };
31593
- expected.add(path34.resolve(getExporter(targetConfig).outputPath(ctx)));
31594
- }
31595
- }
31596
- return expected;
31597
- }
31598
- function resolveTargetConfig(agentTarget, projectConfig) {
31599
- const targetType = typeof agentTarget === "string" ? agentTarget : agentTarget.type;
31600
- return projectConfig.targets.find((t) => {
31601
- if (typeof t === "string") return t === targetType;
31602
- return t.type === targetType;
31603
- });
31604
- }
31605
-
31606
- // src/commands/generate.ts
31656
+ init_base();
31607
31657
  init_context();
31608
31658
  init_fs();
31609
31659
  init_project();
@@ -31666,7 +31716,7 @@ async function generateLayer(options = {}) {
31666
31716
  } else if (options.dryRun) {
31667
31717
  logger.info("Dry run \u2014 rules.materializeAgentFiles is off: no agent files are written; leftover managed files would be removed.");
31668
31718
  } else if (options.prune !== false) {
31669
- const candidateDirs = [...resolveExpectedOutputPaths(agents, projectConfig)].map((p) => path35.dirname(p));
31719
+ const candidateDirs = [...resolveExpectedOutputPaths2(agents, projectConfig)].map((p) => path35.dirname(p));
31670
31720
  const removed = pruneStaleAgents(/* @__PURE__ */ new Set(), candidateDirs);
31671
31721
  if (removed > 0) {
31672
31722
  logger.info(`Removed ${removed} previously materialized agent file(s) \u2014 agents are served as live briefs (sdd_get_agent_brief); opt back in with rules.materializeAgentFiles: true.`);
@@ -31710,7 +31760,7 @@ function materializeAgentLayer(agents, projectConfig, options) {
31710
31760
  }
31711
31761
  logger.info(`Generating ${agentPool.length} agent(s)...`);
31712
31762
  logger.blank();
31713
- const summaries = generateAll(agents, projectConfig, {
31763
+ const summaries = generateAll2(agents, projectConfig, {
31714
31764
  filterTargets,
31715
31765
  filterDomainIds,
31716
31766
  dryRun: options.dryRun
@@ -31734,7 +31784,7 @@ function materializeAgentLayer(agents, projectConfig, options) {
31734
31784
  }
31735
31785
  let prunedCount = 0;
31736
31786
  if (!options.dryRun && options.prune !== false) {
31737
- prunedCount = pruneStaleAgents(resolveExpectedOutputPaths(agents, projectConfig));
31787
+ prunedCount = pruneStaleAgents(resolveExpectedOutputPaths2(agents, projectConfig));
31738
31788
  }
31739
31789
  logger.blank();
31740
31790
  if (options.dryRun) {
@@ -33240,10 +33290,6 @@ var path39 = __toESM(require("path"));
33240
33290
  init_logger();
33241
33291
  init_loader();
33242
33292
  init_fs();
33243
- init_diagram();
33244
- init_canvas();
33245
- init_diagram_export();
33246
- init_validation();
33247
33293
  init_errors();
33248
33294
  var FORMATS = ["mermaid", "canvas", "drawio", "excalidraw"];
33249
33295
  function applyFormat(options) {
@@ -33260,18 +33306,9 @@ function applyFormat(options) {
33260
33306
  // mermaid is the default path — no flag needed
33261
33307
  };
33262
33308
  }
33263
- function collectIssues() {
33264
- try {
33265
- const config = loadProjectConfig4();
33266
- if (config) return validateSddTree({ rules: config.rules, projectType: config.projectType }).issues;
33267
- } catch {
33268
- }
33269
- return validateSddTree().issues;
33270
- }
33271
- function writeCanvas(dest) {
33272
- const model = buildCanvasModel(collectIssues());
33309
+ function writeArtifact(dest, content) {
33273
33310
  ensureDir(path39.dirname(path39.resolve(dest)));
33274
- fs27.writeFileSync(dest, renderCanvasHtml(model), "utf-8");
33311
+ fs27.writeFileSync(dest, content, "utf-8");
33275
33312
  }
33276
33313
  function parseSequenceRef(ref) {
33277
33314
  const sep9 = ref.includes(":") ? ref.lastIndexOf(":") : ref.lastIndexOf(".");
@@ -33287,23 +33324,21 @@ async function runDiagram(rawOptions = {}) {
33287
33324
  const options = applyFormat(rawOptions);
33288
33325
  if (options.canvas && !options.all) {
33289
33326
  const dest2 = options.out ?? path39.join(AI_PATHS.docsDir(), "diagrams", "canvas.html");
33290
- writeCanvas(dest2);
33327
+ writeArtifact(dest2, renderDiagram2("canvas"));
33291
33328
  logger.success(`Interactive canvas written to ${dest2}`);
33292
33329
  logger.info("Open it in a browser \u2014 fully self-contained (works offline).");
33293
33330
  return;
33294
33331
  }
33295
33332
  if (options.drawio && !options.all) {
33296
33333
  const dest2 = options.out ?? path39.join(AI_PATHS.docsDir(), "diagrams", "architecture.drawio");
33297
- ensureDir(path39.dirname(path39.resolve(dest2)));
33298
- fs27.writeFileSync(dest2, generateDrawioXml(buildCanvasModel()), "utf-8");
33334
+ writeArtifact(dest2, renderDiagram2("drawio"));
33299
33335
  logger.success(`draw.io diagram written to ${dest2}`);
33300
33336
  logger.info("Open with draw.io / diagrams.net (or import into tools that accept the format).");
33301
33337
  return;
33302
33338
  }
33303
33339
  if (options.excalidraw && !options.all) {
33304
33340
  const dest2 = options.out ?? path39.join(AI_PATHS.docsDir(), "diagrams", "architecture.excalidraw");
33305
- ensureDir(path39.dirname(path39.resolve(dest2)));
33306
- fs27.writeFileSync(dest2, generateExcalidrawScene(buildCanvasModel()), "utf-8");
33341
+ writeArtifact(dest2, renderDiagram2("excalidraw"));
33307
33342
  logger.success(`Excalidraw scene written to ${dest2}`);
33308
33343
  logger.info("Open with excalidraw.com or the VS Code extension.");
33309
33344
  return;
@@ -33311,7 +33346,7 @@ async function runDiagram(rawOptions = {}) {
33311
33346
  const wantsMermaid = options.format?.toLowerCase().startsWith("mermaid") || !!options.subsystem || !!options.sequence;
33312
33347
  if (!options.all && !options.sequence && !wantsMermaid) {
33313
33348
  const dest2 = options.out ?? path39.join(AI_PATHS.docsDir(), "diagrams", "canvas.html");
33314
- writeCanvas(dest2);
33349
+ writeArtifact(dest2, renderDiagram2("canvas"));
33315
33350
  logger.success(`Interactive canvas written to ${dest2}`);
33316
33351
  logger.info("Open it in a browser \u2014 fully self-contained (works offline). Other formats: --format mermaid|drawio|excalidraw.");
33317
33352
  return;
@@ -33324,17 +33359,14 @@ async function runDiagram(rawOptions = {}) {
33324
33359
  return;
33325
33360
  }
33326
33361
  for (const file of files) {
33327
- const dest2 = path39.join(outDir, file.relPath);
33328
- ensureDir(path39.dirname(dest2));
33329
- fs27.writeFileSync(dest2, toMarkdown(file), "utf-8");
33330
- }
33331
- writeCanvas(path39.join(outDir, "canvas.html"));
33332
- const exportModel = buildCanvasModel();
33333
- fs27.writeFileSync(path39.join(outDir, "architecture.drawio"), generateDrawioXml(exportModel), "utf-8");
33334
- fs27.writeFileSync(path39.join(outDir, "architecture.excalidraw"), generateExcalidrawScene(exportModel), "utf-8");
33362
+ writeArtifact(path39.join(outDir, file.relPath), toMarkdown(file));
33363
+ }
33364
+ writeArtifact(path39.join(outDir, "canvas.html"), renderDiagram2("canvas"));
33365
+ writeArtifact(path39.join(outDir, "architecture.drawio"), renderDiagram2("drawio"));
33366
+ writeArtifact(path39.join(outDir, "architecture.excalidraw"), renderDiagram2("excalidraw"));
33335
33367
  const graph = loadSpecGraph();
33336
33368
  const indexPath = path39.join(outDir, "README.md");
33337
- fs27.writeFileSync(indexPath, diagramSetIndex(files, graph.systemName), "utf-8");
33369
+ writeArtifact(indexPath, diagramSetIndex(files, graph.systemName));
33338
33370
  logger.success(`Generated ${files.length} diagram(s) + interactive canvas.html + index into ${outDir}`);
33339
33371
  for (const file of files.slice(0, 12)) {
33340
33372
  logger.info(` ${file.relPath}`);
@@ -33356,15 +33388,14 @@ async function runDiagram(rawOptions = {}) {
33356
33388
  title = `${options.subsystem} \u2014 components`;
33357
33389
  defaultDest = path39.join(diagramsDir, "subsystems", `${options.subsystem.replace(/::/g, "--")}.md`);
33358
33390
  } else {
33359
- mermaid = generateComponentDiagram();
33391
+ mermaid = renderDiagram2("mermaid");
33360
33392
  title = "Component architecture";
33361
33393
  defaultDest = path39.join(diagramsDir, "system.md");
33362
33394
  }
33363
33395
  const dest = options.out ?? defaultDest;
33364
- ensureDir(path39.dirname(path39.resolve(dest)));
33365
33396
  const content = dest.endsWith(".mmd") ? `${mermaid}
33366
33397
  ` : toMarkdown({ relPath: dest, title, mermaid });
33367
- fs27.writeFileSync(dest, content, "utf-8");
33398
+ writeArtifact(dest, content);
33368
33399
  logger.success(`Mermaid diagram written to ${dest}`);
33369
33400
  logger.info("Renders on GitHub/IDE previews; use a .mmd --out path for raw Mermaid.");
33370
33401
  }
@@ -46597,7 +46628,6 @@ function startHostServer(cfg) {
46597
46628
 
46598
46629
  // src/commands/host.ts
46599
46630
  init_fs();
46600
- init_canvas();
46601
46631
 
46602
46632
  // src/core/demo-seed.ts
46603
46633
  init_specs2();
@@ -47292,7 +47322,7 @@ async function runHostDemo(options = {}) {
47292
47322
  const rec = createProject(cfg, cred, id, unitId);
47293
47323
  const summary = runWithProjectRoot(rec.rootPath, () => {
47294
47324
  seedDemoTree();
47295
- const model = buildCanvasModel();
47325
+ const model = buildCanvasDataModel();
47296
47326
  return {
47297
47327
  subsystems: model.subsystems.length,
47298
47328
  components: model.components.length,