@wairon/cli 5.1.1-dev.71 → 5.1.1-dev.72

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
@@ -3539,12 +3539,7 @@ __export(src_exports, {
3539
3539
  defaultNarrativeDetail: () => defaultNarrativeDetail,
3540
3540
  defaultPackSelections: () => defaultPackSelections,
3541
3541
  defaultTargetConfig: () => defaultTargetConfig,
3542
- deleteComponentSpec: () => deleteComponentSpec,
3543
- deleteImplementationSpec: () => deleteImplementationSpec,
3544
- deleteInterfaceSpec: () => deleteInterfaceSpec,
3545
3542
  deleteSpec: () => deleteSpec,
3546
- deleteSubsystemSpec: () => deleteSubsystemSpec,
3547
- deleteTypeSpec: () => deleteTypeSpec,
3548
3543
  deregisterPackRef: () => deregisterPackRef,
3549
3544
  deriveExecutionProfile: () => deriveExecutionProfile,
3550
3545
  derivedDocPaths: () => derivedDocPaths,
@@ -3672,14 +3667,8 @@ __export(src_exports, {
3672
3667
  runWithProjectBinding: () => runWithProjectBinding,
3673
3668
  runWithProjectRoot: () => runWithProjectRoot,
3674
3669
  sameContract: () => sameContract,
3675
- saveComponentSpec: () => saveComponentSpec,
3676
- saveImplementationSpec: () => saveImplementationSpec,
3677
- saveInterfaceSpec: () => saveInterfaceSpec,
3678
3670
  saveSpec: () => saveSpec,
3679
- saveSubsystemSpec: () => saveSubsystemSpec,
3680
- saveSystemSpec: () => saveSystemSpec,
3681
3671
  saveTopologyConfig: () => saveTopologyConfig,
3682
- saveTypeSpec: () => saveTypeSpec,
3683
3672
  serializeYaml: () => serializeYaml,
3684
3673
  setExecutionTier: () => setExecutionTier,
3685
3674
  setLogLevel: () => setLogLevel,
@@ -5206,7 +5195,13 @@ var PublicInterfaceSchema = import_zod8.z.object({
5206
5195
  /** The L2 component that realizes this public interface (the subsystem's published surface). */
5207
5196
  component: SpecIdSchema.optional(),
5208
5197
  /** Optional L3 interface on that component backing this entry. */
5209
- interface: SpecIdSchema.optional()
5198
+ interface: SpecIdSchema.optional(),
5199
+ /**
5200
+ * The subsystems this surface is published to. Absent, anyone may depend on
5201
+ * it; present, only these subsystems may — when every entry publishing the
5202
+ * component names consumers, the union of those lists is the whole set.
5203
+ */
5204
+ consumers: import_zod8.z.array(SpecIdSchema).optional()
5210
5205
  });
5211
5206
  var TrustedLinkSchema = import_zod8.z.object({
5212
5207
  /** The peer subsystem id this link sanctions tight coupling with. */
@@ -11596,7 +11591,7 @@ function defaultTargetConfig(type) {
11596
11591
  enabled: true
11597
11592
  };
11598
11593
  }
11599
- var WAIRON_VERSION = "5.1.1-dev.71";
11594
+ var WAIRON_VERSION = "5.1.1-dev.72";
11600
11595
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
11601
11596
  var ARCHITECT_AGENT_ID = "agent-architect";
11602
11597
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -12779,6 +12774,32 @@ var publicSurfaceBindingRule = {
12779
12774
  }
12780
12775
  };
12781
12776
 
12777
+ // src/core/rules/integrity/public-surface-consumers.ts
12778
+ var publicSurfaceConsumersRule = {
12779
+ name: "public-surface-consumers",
12780
+ description: "Every subsystem a published surface names as its consumer must exist in the tree. A consumers list restricts who may depend on the surface, so an id that names nothing locks the surface against a caller nobody can be \u2014 and a typo there silently locks out the caller that was meant, which the boundary rule would then report against the wrong party.",
12781
+ codes: [
12782
+ { code: "PUBLIC_INTERFACE_UNKNOWN_CONSUMER", defaultSeverity: "error", summary: "A published surface names as its consumer a subsystem the tree does not have" }
12783
+ ],
12784
+ check(ctx) {
12785
+ const known = new Set(ctx.subsystems.map((s) => s.id));
12786
+ for (const sub of ctx.subsystems) {
12787
+ for (const pi of sub.publicInterfaces) {
12788
+ for (const consumer of pi.consumers ?? []) {
12789
+ if (known.has(consumer)) continue;
12790
+ ctx.addIssue(
12791
+ "error",
12792
+ "PUBLIC_INTERFACE_UNKNOWN_CONSUMER",
12793
+ `Subsystem "${sub.id}" publishes "${pi.component ?? `${pi.type} ${pi.details}`}" to consumer "${consumer}", which names no subsystem of this tree. Name an existing subsystem, or drop the id \u2014 a consumers list admits only the subsystems it names.`,
12794
+ sub.id,
12795
+ isDraftSubsystem(sub)
12796
+ );
12797
+ }
12798
+ }
12799
+ }
12800
+ }
12801
+ };
12802
+
12782
12803
  // src/core/rules/integrity/public-surface-declared-type.ts
12783
12804
  var pubTypeMatches = (piType, ct, portalType) => {
12784
12805
  switch (piType) {
@@ -14148,14 +14169,15 @@ var authSourceWiringRule = {
14148
14169
  // src/core/rules/doctrine/subsystem-boundary-dependencies.ts
14149
14170
  var subsystemBoundaryDepsRule = {
14150
14171
  name: "subsystem-boundary-dependencies",
14151
- description: "Judges every dependsOn edge that leaves its own subsystem, and every one that resolves nowhere. Across subsystems the shape is client Adapter \u2192 published remote Portal, OR a direct in-process edge licensed by a trustedLink declared on the SOURCE subsystem (the published-Portal target requirement applies either way). A reference that names nothing in this tree is resolved against the stored surface snapshots: a hit is a DECLARED remote portal and the same Adapter requirement applies to it, snapshots of several providers that disagree make the reference ambiguous, and a reference authored to leave this root that no snapshot covers warns instead of erroring. Boundary rules are never relaxed by a pack profile.",
14172
+ description: "Judges every dependsOn edge that leaves its own subsystem, and every one that resolves nowhere. Across subsystems the shape is client Adapter \u2192 published remote Portal, OR a direct in-process edge licensed by a trustedLink declared on the SOURCE subsystem (the published-Portal target requirement applies either way). A published surface may also name the subsystems it serves (a publicInterfaces entry's consumers): a component every one of whose entries names consumers may be depended on only from those subsystems, which is how a provider keeps a surface \u2014 the raw spec writes \u2014 away from a door that must not reach it. A reference that names nothing in this tree is resolved against the stored surface snapshots: a hit is a DECLARED remote portal and the same Adapter requirement applies to it, snapshots of several providers that disagree make the reference ambiguous, and a reference authored to leave this root that no snapshot covers warns instead of erroring. Boundary rules are never relaxed by a pack profile.",
14152
14173
  codes: [
14153
14174
  { code: "INVALID_DEPENDENCY_REFERENCE", defaultSeverity: "error", summary: "dependsOn names a non-existent component" },
14154
14175
  { code: "CROSS_TREE_REF_UNRESOLVED", defaultSeverity: "warning", summary: "Cross-tree dependsOn (super::/:: form) with no surface snapshot covering it" },
14155
14176
  { code: "SURFACE_REF_AMBIGUOUS", defaultSeverity: "error", summary: "Cross-tree dependsOn matched by surface snapshots of several providers with different contracts" },
14156
14177
  { code: "CROSS_SUBSYSTEM_NON_ADAPTER", defaultSeverity: "error", summary: "Non-Adapter component crossing a subsystem boundary" },
14157
14178
  { code: "CROSS_SUBSYSTEM_PRIVATE_ACCESS", defaultSeverity: "error", summary: "Cross-subsystem dependency on an unpublished component" },
14158
- { code: "CROSS_SUBSYSTEM_TARGET_NON_PORTAL", defaultSeverity: "error", summary: "Cross-subsystem hop entering through a non-Portal" }
14179
+ { code: "CROSS_SUBSYSTEM_TARGET_NON_PORTAL", defaultSeverity: "error", summary: "Cross-subsystem hop entering through a non-Portal" },
14180
+ { code: "CROSS_SUBSYSTEM_UNLISTED_CONSUMER", defaultSeverity: "error", summary: "Cross-subsystem dependency on a surface published only to other subsystems" }
14159
14181
  ],
14160
14182
  check(ctx) {
14161
14183
  for (const edge of ctx.dependencyEdges().all) {
@@ -14238,9 +14260,24 @@ var subsystemBoundaryDepsRule = {
14238
14260
  edge.draftContext
14239
14261
  );
14240
14262
  }
14263
+ const publishedTo = restrictedConsumers(ctx, depComp.subsystem, depComp.id);
14264
+ if (publishedTo && !publishedTo.includes(comp.subsystem)) {
14265
+ ctx.addIssue(
14266
+ "error",
14267
+ "CROSS_SUBSYSTEM_UNLISTED_CONSUMER",
14268
+ `Boundary violation: "${comp.id}" (subsystem "${comp.subsystem}") depends on "${depComp.id}", which subsystem "${depComp.subsystem}" publishes only to ${publishedTo.map((s) => `"${s}"`).join(", ")}. Depend on a surface published to "${comp.subsystem}" instead, or \u2014 when "${comp.subsystem}" really is a caller the provider meant to serve \u2014 add it to the entry's consumers.`,
14269
+ comp.id,
14270
+ edge.draftContext
14271
+ );
14272
+ }
14241
14273
  }
14242
14274
  }
14243
14275
  };
14276
+ function restrictedConsumers(ctx, subsystemId, componentId) {
14277
+ const entries = (ctx.subsystems.find((s) => s.id === subsystemId)?.publicInterfaces ?? []).filter((pi) => pi.component === componentId);
14278
+ if (entries.length === 0 || entries.some((pi) => pi.consumers === void 0)) return null;
14279
+ return [...new Set(entries.flatMap((pi) => pi.consumers ?? []))];
14280
+ }
14244
14281
 
14245
14282
  // src/core/rules/doctrine/stereotype-terms.ts
14246
14283
  var NEVER_INLINE_STATE = " Never resolve this by merging the store's state into the consuming component \u2014 state hidden inside a logic block is invisible to the spec and unrecoverable.";
@@ -18733,10 +18770,11 @@ var SDD_RULES = [
18733
18770
  assertionForbiddenEdgesRule,
18734
18771
  assertionRequiredFieldsRule,
18735
18772
  assertionEndpointShapesRule,
18736
- // The published surface in three questions: what backs the entry, whether
18737
- // that component's stereotype can realize the type it declares, and whether
18738
- // the contract it binds is that component's own.
18773
+ // The published surface in four questions: what backs the entry, who it is
18774
+ // published to, whether that component's stereotype can realize the type it
18775
+ // declares, and whether the contract it binds is that component's own.
18739
18776
  publicSurfaceBindingRule,
18777
+ publicSurfaceConsumersRule,
18740
18778
  publicSurfaceDeclaredTypeRule,
18741
18779
  publicSurfaceBoundContractRule,
18742
18780
  cyclesRule,
@@ -21441,7 +21479,10 @@ function stripNamespaceFromSubsystem(spec, prefix) {
21441
21479
  publicInterfaces: spec.publicInterfaces.map((pi) => ({
21442
21480
  ...pi,
21443
21481
  component: pi.component ? relMember(pi.component) : void 0,
21444
- interface: pi.interface ? relMember(pi.interface) : void 0
21482
+ interface: pi.interface ? relMember(pi.interface) : void 0,
21483
+ // consumers name SUBSYSTEMS — peers of this one, so they are relative to
21484
+ // the namespace the subsystem itself is declared in, never its members'.
21485
+ ...pi.consumers ? { consumers: pi.consumers.map((c) => c.includes("::") ? relativizeId(c, prefix) : c) } : {}
21445
21486
  })),
21446
21487
  lifecycle: spec.lifecycle?.map((le) => ({
21447
21488
  ...le,
@@ -22049,7 +22090,10 @@ var SpecWorkspace = class {
22049
22090
  publicInterfaces: sub.publicInterfaces.map((p) => ({
22050
22091
  ...p,
22051
22092
  component: p.component ? qualifyId(p.component, componentPrefix, this.rootSubsystems) : void 0,
22052
- interface: p.interface ? qualifyId(p.interface, componentPrefix, this.rootSubsystems) : void 0
22093
+ interface: p.interface ? qualifyId(p.interface, componentPrefix, this.rootSubsystems) : void 0,
22094
+ // Each consumer is a subsystem reference: qualified into the namespace
22095
+ // this subsystem is declared in, like a component's `subsystem` field.
22096
+ ...p.consumers ? { consumers: p.consumers.map((c) => qualifySubsystemRef(c, namespacePrefix, this.rootSubsystems)) } : {}
22053
22097
  })),
22054
22098
  lifecycle: sub.lifecycle?.map((le) => ({
22055
22099
  ...le,
@@ -23663,7 +23707,8 @@ var SpecWorkspace = class {
23663
23707
  out.publicInterfaces = out.publicInterfaces.map((pi) => ({
23664
23708
  ...pi,
23665
23709
  ...typeof pi?.component === "string" ? { component: qm(pi.component) } : {},
23666
- ...typeof pi?.interface === "string" ? { interface: qm(pi.interface) } : {}
23710
+ ...typeof pi?.interface === "string" ? { interface: qm(pi.interface) } : {},
23711
+ ...Array.isArray(pi?.consumers) ? { consumers: pi.consumers.map((c) => typeof c === "string" ? qualifySubsystemRef(c, prefix, this.rootSubsystems) : c) } : {}
23667
23712
  }));
23668
23713
  }
23669
23714
  if (Array.isArray(out.lifecycle)) {
@@ -24274,9 +24319,6 @@ function loadSubsystemSpec(id) {
24274
24319
  function saveSubsystemSpec(spec) {
24275
24320
  current().saveSubsystemSpec(spec);
24276
24321
  }
24277
- function deleteSubsystemSpec(id) {
24278
- return current().deleteSubsystemSpec(id);
24279
- }
24280
24322
  function loadComponentSpecs() {
24281
24323
  return current().loadComponentSpecs();
24282
24324
  }
@@ -24286,9 +24328,6 @@ function loadComponentSpec(id) {
24286
24328
  function saveComponentSpec(spec, opts) {
24287
24329
  return current().saveComponentSpec(spec, opts);
24288
24330
  }
24289
- function deleteComponentSpec(id) {
24290
- return current().deleteComponentSpec(id);
24291
- }
24292
24331
  function loadInterfaceSpecs() {
24293
24332
  return current().loadInterfaceSpecs();
24294
24333
  }
@@ -24298,9 +24337,6 @@ function loadInterfaceSpec(id) {
24298
24337
  function saveInterfaceSpec(spec, opts) {
24299
24338
  return current().saveInterfaceSpec(spec, opts);
24300
24339
  }
24301
- function deleteInterfaceSpec(id) {
24302
- return current().deleteInterfaceSpec(id);
24303
- }
24304
24340
  function loadImplementationSpecs() {
24305
24341
  return current().loadImplementationSpecs();
24306
24342
  }
@@ -24310,18 +24346,12 @@ function loadImplementationSpec(id) {
24310
24346
  function saveImplementationSpec(spec, opts) {
24311
24347
  return current().saveImplementationSpec(spec, opts);
24312
24348
  }
24313
- function deleteImplementationSpec(id) {
24314
- return current().deleteImplementationSpec(id);
24315
- }
24316
24349
  function loadTypeSpecs() {
24317
24350
  return current().loadTypeSpecs();
24318
24351
  }
24319
24352
  function loadTypeSpec(id) {
24320
24353
  return current().loadTypeSpec(id);
24321
24354
  }
24322
- function saveTypeSpec(spec) {
24323
- return current().saveTypeSpec(spec);
24324
- }
24325
24355
  function dryRunSerializeSpecs(include) {
24326
24356
  return current().dryRunSerializeSpecs(include);
24327
24357
  }
@@ -24397,9 +24427,6 @@ function computeStateIdAt(root) {
24397
24427
  return `${s.algorithm}:${s.digest}`;
24398
24428
  });
24399
24429
  }
24400
- function deleteTypeSpec(id) {
24401
- return current().deleteTypeSpec(id);
24402
- }
24403
24430
  function specPathsInScope(scopeSubsystem) {
24404
24431
  return current().specPathsInScope(scopeSubsystem);
24405
24432
  }
@@ -27119,12 +27146,7 @@ function loadProjectConfig4() {
27119
27146
  defaultNarrativeDetail,
27120
27147
  defaultPackSelections,
27121
27148
  defaultTargetConfig,
27122
- deleteComponentSpec,
27123
- deleteImplementationSpec,
27124
- deleteInterfaceSpec,
27125
27149
  deleteSpec,
27126
- deleteSubsystemSpec,
27127
- deleteTypeSpec,
27128
27150
  deregisterPackRef,
27129
27151
  deriveExecutionProfile,
27130
27152
  derivedDocPaths,
@@ -27252,14 +27274,8 @@ function loadProjectConfig4() {
27252
27274
  runWithProjectBinding,
27253
27275
  runWithProjectRoot,
27254
27276
  sameContract,
27255
- saveComponentSpec,
27256
- saveImplementationSpec,
27257
- saveInterfaceSpec,
27258
27277
  saveSpec,
27259
- saveSubsystemSpec,
27260
- saveSystemSpec,
27261
27278
  saveTopologyConfig,
27262
- saveTypeSpec,
27263
27279
  serializeYaml,
27264
27280
  setExecutionTier,
27265
27281
  setLogLevel,