@wairon/cli 5.1.1-dev.81 → 5.1.1-dev.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3403,6 +3403,7 @@ __export(src_exports, {
3403
3403
  CarriedDebtSchema: () => CarriedDebtSchema,
3404
3404
  CarriedFindingSchema: () => CarriedFindingSchema,
3405
3405
  CatchClauseSchema: () => CatchClauseSchema,
3406
+ ChainingMigrationRefusedError: () => ChainingMigrationRefusedError,
3406
3407
  ClaudeExporter: () => ClaudeExporter,
3407
3408
  ComplexityRuleConfigSchema: () => ComplexityRuleConfigSchema,
3408
3409
  ComponentSpecSchema: () => ComponentSpecSchema,
@@ -3419,6 +3420,7 @@ __export(src_exports, {
3419
3420
  DesignDepthSchema: () => DesignDepthSchema,
3420
3421
  DiagramConfigSchema: () => DiagramConfigSchema,
3421
3422
  DispatchBindingSchema: () => DispatchBindingSchema,
3423
+ DoctorOptionsError: () => DoctorOptionsError,
3422
3424
  DocumentationRuleConfigSchema: () => DocumentationRuleConfigSchema,
3423
3425
  DomainSchema: () => DomainSchema,
3424
3426
  DomainTypeSchema: () => DomainTypeSchema,
@@ -3546,6 +3548,7 @@ __export(src_exports, {
3546
3548
  createProjectConfig: () => createProjectConfig,
3547
3549
  currentChildPins: () => currentChildPins,
3548
3550
  currentRootBinding: () => currentRootBinding,
3551
+ declareExternal: () => declareExternal,
3549
3552
  declaredExternals: () => declaredExternals,
3550
3553
  declaredPackNames: () => declaredPackNames,
3551
3554
  declaredProfileIds: () => declaredProfileIds,
@@ -3715,6 +3718,7 @@ __export(src_exports, {
3715
3718
  schemaFingerprint: () => schemaFingerprint,
3716
3719
  serializeYaml: () => serializeYaml,
3717
3720
  setExecutionTier: () => setExecutionTier,
3721
+ setId: () => setProjectId,
3718
3722
  setLogLevel: () => setLogLevel,
3719
3723
  setProjectRoot: () => setProjectRoot,
3720
3724
  setProjectType: () => setProjectType,
@@ -3746,6 +3750,7 @@ module.exports = __toCommonJS(src_exports);
3746
3750
  // src/config/project-config.ts
3747
3751
  var fs2 = __toESM(require("fs"));
3748
3752
  var path3 = __toESM(require("path"));
3753
+ var YAML = __toESM(require("yaml"));
3749
3754
  var import_zod4 = require("zod");
3750
3755
 
3751
3756
  // src/utils/fs.ts
@@ -3943,6 +3948,20 @@ var BundleNotFoundError = class extends WaironError {
3943
3948
  this.name = "BundleNotFoundError";
3944
3949
  }
3945
3950
  };
3951
+ var DoctorOptionsError = class extends WaironError {
3952
+ constructor(detail) {
3953
+ super(`wairon doctor: ${detail}`);
3954
+ this.name = "DoctorOptionsError";
3955
+ }
3956
+ };
3957
+ var ChainingMigrationRefusedError = class extends WaironError {
3958
+ constructor(reasons) {
3959
+ super(`The chaining migration was not applied; nothing was written:
3960
+ ${reasons.map((r) => ` - ${r}`).join("\n")}`);
3961
+ this.reasons = reasons;
3962
+ this.name = "ChainingMigrationRefusedError";
3963
+ }
3964
+ };
3946
3965
 
3947
3966
  // src/models/identity-rename.ts
3948
3967
  var EDGE = " -> ";
@@ -4684,7 +4703,12 @@ function projectConfigFsAdapterAt(rootDir) {
4684
4703
  return readYamlFile(file());
4685
4704
  },
4686
4705
  writeDocument(document) {
4687
- writeYamlFile(file(), document);
4706
+ const text2 = readFileOrNull(file());
4707
+ if (text2 === null) {
4708
+ writeYamlFile(file(), document);
4709
+ return;
4710
+ }
4711
+ writeFile(file(), editDocumentText(text2, document, root));
4688
4712
  },
4689
4713
  documentExists() {
4690
4714
  return fs2.existsSync(file());
@@ -4872,6 +4896,213 @@ function rewriteScalarsInText(text2, edits, root) {
4872
4896
  }
4873
4897
  return next;
4874
4898
  }
4899
+ var FRESH_TEXT_OPTIONS = {
4900
+ indent: 2,
4901
+ indentSeq: true,
4902
+ lineWidth: 100,
4903
+ customTags: ["timestamp"]
4904
+ };
4905
+ var PARSE_OPTIONS = { customTags: ["timestamp"] };
4906
+ function sameValue(a, b) {
4907
+ if (a instanceof Date || b instanceof Date) {
4908
+ return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
4909
+ }
4910
+ if (Array.isArray(a) || Array.isArray(b)) {
4911
+ return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => sameValue(item, b[i]));
4912
+ }
4913
+ if (isPlainObject(a) || isPlainObject(b)) {
4914
+ if (!isPlainObject(a) || !isPlainObject(b)) return false;
4915
+ const keysA = Object.keys(a).filter((k) => a[k] !== void 0);
4916
+ const keysB = Object.keys(b).filter((k) => b[k] !== void 0);
4917
+ return keysA.length === keysB.length && keysA.every((k) => hasOwn(b, k) && sameValue(a[k], b[k]));
4918
+ }
4919
+ return a === b;
4920
+ }
4921
+ function lineStartOf(text2, pos) {
4922
+ return text2.lastIndexOf("\n", pos - 1) + 1;
4923
+ }
4924
+ function lineEndFrom(text2, pos) {
4925
+ if (pos === 0 || text2[pos - 1] === "\n") return pos;
4926
+ const newline = text2.indexOf("\n", pos);
4927
+ return newline < 0 ? text2.length : newline + 1;
4928
+ }
4929
+ function indentBlock(text2, col) {
4930
+ const pad = " ".repeat(col);
4931
+ const body = text2.endsWith("\n") ? text2 : `${text2}
4932
+ `;
4933
+ return body.split("\n").map((line, i, all) => line === "" || i === all.length - 1 ? line : pad + line).join("\n");
4934
+ }
4935
+ function freshBlock(value, col) {
4936
+ return indentBlock(YAML.stringify(value, FRESH_TEXT_OPTIONS), col);
4937
+ }
4938
+ function schemaFieldOrder(at) {
4939
+ const objectsOf = (schema) => {
4940
+ const shape = shapeOf(schema);
4941
+ if (shape instanceof import_zod4.z.ZodObject) return [shape];
4942
+ if (shape instanceof import_zod4.z.ZodUnion) return shape._def.options.flatMap(objectsOf);
4943
+ return [];
4944
+ };
4945
+ let current2 = ProjectConfigSchema;
4946
+ for (const segment of at) {
4947
+ if (current2 === null) return null;
4948
+ const shape = shapeOf(current2);
4949
+ if (typeof segment === "number") {
4950
+ current2 = shape instanceof import_zod4.z.ZodArray ? shape.element : null;
4951
+ } else if (shape instanceof import_zod4.z.ZodRecord) {
4952
+ current2 = shape._def.valueType;
4953
+ } else {
4954
+ current2 = objectsOf(current2).map((o) => o.shape[segment]).find((s) => s !== void 0) ?? null;
4955
+ }
4956
+ }
4957
+ if (current2 === null) return null;
4958
+ const fields = objectsOf(current2).flatMap((o) => Object.keys(o.shape));
4959
+ return fields.length > 0 ? [...new Set(fields)] : null;
4960
+ }
4961
+ function inlineScalar(value, style) {
4962
+ if (value !== null && typeof value === "object") return null;
4963
+ const quoting = style === "QUOTE_SINGLE" || style === "QUOTE_DOUBLE" ? style : "PLAIN";
4964
+ const text2 = YAML.stringify(value, { ...FRESH_TEXT_OPTIONS, lineWidth: 0, defaultStringType: quoting }).replace(/\n$/, "");
4965
+ return text2.includes("\n") ? null : text2;
4966
+ }
4967
+ var DocumentReconciler = class {
4968
+ constructor(text2, doc) {
4969
+ this.text = text2;
4970
+ this.doc = doc;
4971
+ this.splices = [];
4972
+ }
4973
+ /** Reconcile one node to its target; `replace` rewrites the node wholesale where an edit cannot be precise. */
4974
+ node(node, target, at, replace) {
4975
+ if (YAML.isNode(node) && sameValue(node.toJS(this.doc, { maxAliasCount: -1 }), target)) return;
4976
+ if (YAML.isMap(node) && !node.flow && node.items.length > 0 && isPlainObject(target) && Object.keys(target).length > 0) {
4977
+ this.mapping(node, target, at, replace);
4978
+ } else if (YAML.isSeq(node) && !node.flow && node.items.length > 0 && Array.isArray(target) && target.length > 0) {
4979
+ this.sequence(node, target, at);
4980
+ } else if (YAML.isScalar(node) && !this.scalarInPlace(node, target)) {
4981
+ replace(target);
4982
+ } else if (!YAML.isScalar(node)) {
4983
+ replace(target);
4984
+ }
4985
+ }
4986
+ /** A changed one-line scalar, replaced in its own quoting; false when it is not one. */
4987
+ scalarInPlace(node, target) {
4988
+ const [start, end] = node.range ?? [0, 0];
4989
+ const flowStyle = node.type === "PLAIN" || node.type === "QUOTE_SINGLE" || node.type === "QUOTE_DOUBLE";
4990
+ if (!flowStyle || start === end) return false;
4991
+ const written = inlineScalar(target, node.type);
4992
+ if (written === null) return false;
4993
+ this.splices.push({ start, end, text: written, rank: 0 });
4994
+ return true;
4995
+ }
4996
+ /** Where a pair's text starts (its key's line) and ends (the line after its value). */
4997
+ pairSpan(pair) {
4998
+ const key = pair.key;
4999
+ const start = lineStartOf(this.text, key.range[0]);
5000
+ const value = pair.value;
5001
+ const valueEnd = value && value.range ? value.range[1] : key.range[1];
5002
+ return { start, end: lineEndFrom(this.text, valueEnd), col: key.range[0] - start };
5003
+ }
5004
+ /** Where a sequence item's text starts (its dash's line) and ends, and the dash's column. */
5005
+ itemSpan(item) {
5006
+ let dash = item.range[0] - 1;
5007
+ while (dash >= 0 && /\s/.test(this.text[dash])) dash -= 1;
5008
+ const start = lineStartOf(this.text, dash);
5009
+ return { start, end: lineEndFrom(this.text, item.range[1]), col: dash - start };
5010
+ }
5011
+ /** The first line of the comment block directly above the line starting at `lineStart`. */
5012
+ commentBlockStart(lineStart) {
5013
+ let start = lineStart;
5014
+ while (start > 0) {
5015
+ const above = lineStartOf(this.text, start - 1);
5016
+ if (!this.text.slice(above, start).trim().startsWith("#")) break;
5017
+ start = above;
5018
+ }
5019
+ return start;
5020
+ }
5021
+ mapping(map, target, at, replace) {
5022
+ const keyOf = (pair) => String(YAML.isScalar(pair.key) ? pair.key.value : pair.key);
5023
+ const kept = map.items.filter((pair) => target[keyOf(pair)] !== void 0);
5024
+ if (kept.length === 0) {
5025
+ replace(target);
5026
+ return;
5027
+ }
5028
+ for (const pair of map.items) {
5029
+ const key = keyOf(pair);
5030
+ const span = this.pairSpan(pair);
5031
+ if (target[key] === void 0) {
5032
+ this.splices.push({ start: span.start, end: span.end, text: "", rank: 0 });
5033
+ continue;
5034
+ }
5035
+ this.node(pair.value, target[key], [...at, key], (value) => {
5036
+ this.splices.push({ start: span.start, end: span.end, text: freshBlock({ [key]: value }, span.col), rank: 0 });
5037
+ });
5038
+ }
5039
+ this.insertNewKeys(map, kept, target, at, keyOf);
5040
+ }
5041
+ /**
5042
+ * Insert the keys the document adds at their place in the schema's field
5043
+ * order: after the nearest preceding schema field the mapping keeps, else
5044
+ * before the nearest following one (above its comments), else after the
5045
+ * mapping's last key.
5046
+ */
5047
+ insertNewKeys(map, kept, target, at, keyOf) {
5048
+ const present = new Map(kept.map((pair) => [keyOf(pair), pair]));
5049
+ const order = schemaFieldOrder(at) ?? [];
5050
+ const col = this.pairSpan(kept[0]).col;
5051
+ const added = Object.keys(target).filter((key) => target[key] !== void 0 && !map.items.some((pair) => keyOf(pair) === key));
5052
+ added.forEach((key, n) => {
5053
+ const index = order.indexOf(key);
5054
+ const before = index < 0 ? void 0 : order.slice(0, index).reverse().find((k) => present.has(k));
5055
+ const after = index < 0 ? void 0 : order.slice(index + 1).find((k) => present.has(k));
5056
+ const offset = before !== void 0 ? this.pairSpan(present.get(before)).end : after !== void 0 ? this.commentBlockStart(this.pairSpan(present.get(after)).start) : this.pairSpan(kept[kept.length - 1]).end;
5057
+ const rank = -at.length * 1e5 + (index < 0 ? order.length + n : index);
5058
+ this.splices.push({ start: offset, end: offset, text: freshBlock({ [key]: target[key] }, col), rank });
5059
+ });
5060
+ }
5061
+ sequence(seq, target, at) {
5062
+ seq.items.forEach((item, i) => {
5063
+ const span = this.itemSpan(item);
5064
+ if (i >= target.length) {
5065
+ this.splices.push({ start: span.start, end: span.end, text: "", rank: 0 });
5066
+ return;
5067
+ }
5068
+ this.node(item, target[i], [...at, i], (value) => {
5069
+ this.splices.push({ start: span.start, end: span.end, text: freshBlock([value], span.col), rank: 0 });
5070
+ });
5071
+ });
5072
+ if (target.length > seq.items.length) {
5073
+ const last = this.itemSpan(seq.items[seq.items.length - 1]);
5074
+ this.splices.push({ start: last.end, end: last.end, text: freshBlock(target.slice(seq.items.length), last.col), rank: -(at.length + 1) * 1e5 });
5075
+ }
5076
+ }
5077
+ };
5078
+ function applySplices(text2, splices) {
5079
+ const ordered = [...splices].sort((a, b) => b.start - a.start || b.end - a.end || b.rank - a.rank);
5080
+ let out = text2;
5081
+ for (const splice of ordered) out = out.slice(0, splice.start) + splice.text + out.slice(splice.end);
5082
+ return out;
5083
+ }
5084
+ function editDocumentText(text2, document, root) {
5085
+ const refuse = (why) => {
5086
+ throw new WaironError(`Cannot write .wai/project.yaml at ${root} as an edit of the file: ${why}. Nothing was written.`);
5087
+ };
5088
+ const crlf = text2.includes("\r\n");
5089
+ const source = crlf ? text2.replace(/\r\n/g, "\n") : text2;
5090
+ const doc = YAML.parseDocument(source, PARSE_OPTIONS);
5091
+ if (doc.errors.length > 0) refuse(`the file does not parse (${doc.errors[0].message})`);
5092
+ const reconciler = new DocumentReconciler(source, doc);
5093
+ reconciler.node(doc.contents, document, [], (value) => {
5094
+ reconciler.splices.push({ start: 0, end: source.length, text: YAML.stringify(value, FRESH_TEXT_OPTIONS), rank: 0 });
5095
+ });
5096
+ const edited = applySplices(source, reconciler.splices);
5097
+ let reread;
5098
+ try {
5099
+ reread = parseYaml(edited);
5100
+ } catch (e) {
5101
+ refuse(`the edited text does not parse (${e instanceof Error ? e.message : String(e)})`);
5102
+ }
5103
+ if (!sameValue(reread, document)) refuse("the edited text does not read back as the document to write");
5104
+ return crlf ? edited.replace(/\n/g, "\r\n") : edited;
5105
+ }
4875
5106
  function parseConfig(document, root) {
4876
5107
  try {
4877
5108
  return ProjectConfigSchema.parse(document);
@@ -5043,6 +5274,38 @@ function registryOver(store, root) {
5043
5274
  });
5044
5275
  store.rewriteScalars(edits, dryRun);
5045
5276
  return rekeys;
5277
+ },
5278
+ setId(id) {
5279
+ if (!PROJECT_ID_RE.test(id)) {
5280
+ throw new WaironError(`Refusing to declare the project id "${id}" at ${root}: it breaks the project-id grammar ([a-z0-9-_.], starting and ending alphanumeric).`);
5281
+ }
5282
+ const config = current2();
5283
+ if (config.id === id) return false;
5284
+ if (config.id !== void 0) {
5285
+ throw new WaironError(
5286
+ `Refusing to declare the project id "${id}" at ${root}: the project already declares "${config.id}". An id is immutable; moving it is the rename migration, never a set.`
5287
+ );
5288
+ }
5289
+ save({ ...config, id });
5290
+ return true;
5291
+ },
5292
+ declareExternal(alias, declaration2) {
5293
+ if (!EXTERNAL_ALIAS_RE.test(alias)) {
5294
+ throw new WaironError(`Refusing to declare the external "${alias}" at ${root}: an alias must fit [a-z0-9-_]+.`);
5295
+ }
5296
+ if (declaration2.project !== void 0 && !PROJECT_ID_RE.test(declaration2.project)) {
5297
+ throw new WaironError(`Refusing to declare the external "${alias}" at ${root}: the producer id "${declaration2.project}" breaks the project-id grammar.`);
5298
+ }
5299
+ const config = current2();
5300
+ const existing = config.externals?.[alias];
5301
+ if (existing !== void 0) {
5302
+ if (sameValue(existing, declaration2)) return false;
5303
+ throw new WaironError(
5304
+ `Refusing to declare the external "${alias}" at ${root} as ${JSON.stringify(declaration2)}: it is already declared as ${JSON.stringify(existing)}, and a declaration a person wrote is never overwritten.`
5305
+ );
5306
+ }
5307
+ save({ ...config, externals: { ...config.externals, [alias]: declaration2 } });
5308
+ return true;
5046
5309
  }
5047
5310
  };
5048
5311
  }
@@ -5130,6 +5393,12 @@ function projectConfigRepositoryOver(adapter, rootDir) {
5130
5393
  },
5131
5394
  rekeyCarried(rename, dryRun) {
5132
5395
  return registry.rekeyCarried(rename, dryRun);
5396
+ },
5397
+ setId(id) {
5398
+ return registry.setId(id);
5399
+ },
5400
+ declareExternal(alias, declaration2) {
5401
+ return registry.declareExternal(alias, declaration2);
5133
5402
  }
5134
5403
  };
5135
5404
  }
@@ -5182,6 +5451,12 @@ var projectConfigRepository = {
5182
5451
  },
5183
5452
  rekeyCarried(rename, dryRun) {
5184
5453
  return bound().rekeyCarried(rename, dryRun);
5454
+ },
5455
+ setId(id) {
5456
+ return bound().setId(id);
5457
+ },
5458
+ declareExternal(alias, declaration2) {
5459
+ return bound().declareExternal(alias, declaration2);
5185
5460
  }
5186
5461
  };
5187
5462
 
@@ -12680,7 +12955,7 @@ function defaultTargetConfig(type) {
12680
12955
  enabled: true
12681
12956
  };
12682
12957
  }
12683
- var WAIRON_VERSION = "5.1.1-dev.81";
12958
+ var WAIRON_VERSION = "5.1.1-dev.82";
12684
12959
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
12685
12960
  var ARCHITECT_AGENT_ID = "agent-architect";
12686
12961
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -23384,7 +23659,10 @@ function resolveProjectTable(system, subsystems, components, interfaces, types,
23384
23659
  source.subsystem,
23385
23660
  sourceTable,
23386
23661
  { component: e.component, interface: e.interface, typeDef: e.typeDef },
23387
- () => e.as ?? e.id ?? e.interface ?? e.component ?? e.typeDef,
23662
+ // The default public name is the item's own LOCAL id: a member's L0 is
23663
+ // read with its ids qualified into its mount, and its entry names the
23664
+ // item as the member wrote it.
23665
+ () => e.as ?? e.id ?? localName2(e.interface ?? e.component ?? e.typeDef),
23388
23666
  false,
23389
23667
  problems
23390
23668
  );
@@ -23505,7 +23783,7 @@ function landingEntries(ref, visible, interfaces, componentIds) {
23505
23783
  });
23506
23784
  }
23507
23785
  if (ref.position === "type" || ref.position === "reexport") {
23508
- const typed = visible.filter((e) => e.kind === "type" && (e.typeDef === ref.target || matchTypeRef(ref.target, e.typeDef ?? "")));
23786
+ const typed = visible.filter((e) => e.kind === "type" && (e.typeDef === ref.target || matchTypeRef(ref.target, e.typeDef ?? "") || ref.target === `${e.source}::${localName2(e.typeDef ?? "")}`));
23509
23787
  if (typed.length > 0 || ref.position === "type") return typed;
23510
23788
  }
23511
23789
  return [];
@@ -27206,6 +27484,12 @@ function deregisterPackRef(ref) {
27206
27484
  function markSelectionsBundled(bundled) {
27207
27485
  projectConfigRepository.markSelectionsBundled(bundled);
27208
27486
  }
27487
+ function setProjectId(id) {
27488
+ return projectConfigRepository.setId(id);
27489
+ }
27490
+ function declareExternal(alias, declaration2) {
27491
+ return projectConfigRepository.declareExternal(alias, declaration2);
27492
+ }
27209
27493
  function computeStateIdAt(root) {
27210
27494
  const resolved = path17.resolve(root);
27211
27495
  return runWithProjectRoot(resolved, () => {
@@ -32505,6 +32789,7 @@ function loadProjectConfig3() {
32505
32789
  CarriedDebtSchema,
32506
32790
  CarriedFindingSchema,
32507
32791
  CatchClauseSchema,
32792
+ ChainingMigrationRefusedError,
32508
32793
  ClaudeExporter,
32509
32794
  ComplexityRuleConfigSchema,
32510
32795
  ComponentSpecSchema,
@@ -32521,6 +32806,7 @@ function loadProjectConfig3() {
32521
32806
  DesignDepthSchema,
32522
32807
  DiagramConfigSchema,
32523
32808
  DispatchBindingSchema,
32809
+ DoctorOptionsError,
32524
32810
  DocumentationRuleConfigSchema,
32525
32811
  DomainSchema,
32526
32812
  DomainTypeSchema,
@@ -32648,6 +32934,7 @@ function loadProjectConfig3() {
32648
32934
  createProjectConfig,
32649
32935
  currentChildPins,
32650
32936
  currentRootBinding,
32937
+ declareExternal,
32651
32938
  declaredExternals,
32652
32939
  declaredPackNames,
32653
32940
  declaredProfileIds,
@@ -32817,6 +33104,7 @@ function loadProjectConfig3() {
32817
33104
  schemaFingerprint,
32818
33105
  serializeYaml,
32819
33106
  setExecutionTier,
33107
+ setId,
32820
33108
  setLogLevel,
32821
33109
  setProjectRoot,
32822
33110
  setProjectType,