@wairon/cli 5.1.1-dev.57 → 5.1.1-dev.58

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
@@ -3578,6 +3578,7 @@ __export(src_exports, {
3578
3578
  deleteSubsystemSpec: () => deleteSubsystemSpec,
3579
3579
  deleteTypeSpec: () => deleteTypeSpec,
3580
3580
  deregisterPackRef: () => deregisterPackRef,
3581
+ deriveExecutionProfile: () => deriveExecutionProfile,
3581
3582
  describeApprover: () => describeApprover,
3582
3583
  detectDomainCandidates: () => detectDomainCandidates,
3583
3584
  diagnoseProjectPacks: () => diagnoseProjectPacks,
@@ -3755,6 +3756,7 @@ __export(src_exports, {
3755
3756
  renderWaironGuide: () => renderWaironGuide,
3756
3757
  repairForeignStepFields: () => repairForeignStepFields,
3757
3758
  resolveAgentTopology: () => resolveAgentTopology,
3759
+ resolveBudget: () => resolveBudget,
3758
3760
  resolveChainingParent: () => resolveChainingParent,
3759
3761
  resolveDomains: () => resolveDomains2,
3760
3762
  resolveExpectedOutputPaths: () => resolveExpectedOutputPaths,
@@ -11654,7 +11656,7 @@ function defaultTargetConfig(type) {
11654
11656
  enabled: true
11655
11657
  };
11656
11658
  }
11657
- var WAIRON_VERSION = "5.1.1-dev.57";
11659
+ var WAIRON_VERSION = "5.1.1-dev.58";
11658
11660
  var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
11659
11661
  var ARCHITECT_AGENT_ID = "agent-architect";
11660
11662
  var ARCHITECT_TEMPLATE_ID = "architect";
@@ -17055,6 +17057,96 @@ var carriedDebtRule = {
17055
17057
  }
17056
17058
  };
17057
17059
 
17060
+ // src/core/rules/heuristic/method-cohesion.ts
17061
+ function groupsSharingCollaborators(calledBy) {
17062
+ const parent = /* @__PURE__ */ new Map();
17063
+ const find = (m) => {
17064
+ let root = m;
17065
+ while (parent.get(root) !== root) root = parent.get(root);
17066
+ return root;
17067
+ };
17068
+ const union = (a, b) => {
17069
+ const [ra, rb] = [find(a), find(b)];
17070
+ if (ra !== rb) parent.set(ra, rb);
17071
+ };
17072
+ const methods = [...calledBy.keys()];
17073
+ for (const m of methods) parent.set(m, m);
17074
+ for (let i = 0; i < methods.length; i++) {
17075
+ for (let j = i + 1; j < methods.length; j++) {
17076
+ const shares = [...calledBy.get(methods[i])].some((c) => calledBy.get(methods[j])?.has(c));
17077
+ if (shares) union(methods[i], methods[j]);
17078
+ }
17079
+ }
17080
+ const groups = /* @__PURE__ */ new Map();
17081
+ for (const m of methods) {
17082
+ const root = find(m);
17083
+ groups.set(root, [...groups.get(root) ?? [], m]);
17084
+ }
17085
+ return [...groups.values()];
17086
+ }
17087
+ function isForwardingMethod(narrative) {
17088
+ let handoffs = 0;
17089
+ for (const step of narrative) {
17090
+ if (step.type === "call" || step.type === "dispatch") handoffs++;
17091
+ else if (step.type !== "return") return false;
17092
+ }
17093
+ return handoffs === 1;
17094
+ }
17095
+ function isPureForwarder(methods) {
17096
+ const narrated = methods.filter((m) => (m.narrative ?? []).length > 0);
17097
+ return narrated.length > 0 && narrated.every((m) => isForwardingMethod(m.narrative ?? []));
17098
+ }
17099
+ function pureForwarderComponents(ctx) {
17100
+ const realized = /* @__PURE__ */ new Map();
17101
+ for (const impl of ctx.implementations) {
17102
+ const intf = ctx.interfaceMap.get(impl.contract);
17103
+ if (!intf) continue;
17104
+ realized.set(intf.component, [...realized.get(intf.component) ?? [], ...impl.methods]);
17105
+ }
17106
+ return new Set([...realized].filter(([, methods]) => isPureForwarder(methods)).map(([id]) => id));
17107
+ }
17108
+ var methodCohesionRule = {
17109
+ name: "method-cohesion",
17110
+ description: "An Orchestrator's methods share collaborators; when they split into groups that call no component in common, the component holds more than one responsibility. Reported only where two or more groups each hold two or more methods, so a single specialized method is not a finding \u2014 and never on a pure forwarder, whose every narrated method is a single hand-off and whose responsibility therefore lives in what it forwards to.",
17111
+ codes: [
17112
+ { code: "INCOHESIVE_METHODS", defaultSeverity: "warning", summary: "Orchestrator's methods form two or more groups of two or more that share no called component" }
17113
+ ],
17114
+ check(ctx) {
17115
+ const subjects = [];
17116
+ for (const impl of ctx.implementations) {
17117
+ const intf = ctx.interfaceMap.get(impl.contract);
17118
+ const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
17119
+ if (!comp || comp.componentType !== "Orchestrator") continue;
17120
+ if (isPureForwarder(impl.methods)) continue;
17121
+ const calledBy = /* @__PURE__ */ new Map();
17122
+ for (const method of impl.methods) {
17123
+ const reached = /* @__PURE__ */ new Set();
17124
+ for (const step of method.narrative ?? []) {
17125
+ if ((step.type === "call" || step.type === "dispatch") && step.targetComponent) reached.add(step.targetComponent);
17126
+ }
17127
+ if (reached.size > 0) calledBy.set(method.name, reached);
17128
+ }
17129
+ subjects.push({ implementation: impl, component: comp, calledBy });
17130
+ }
17131
+ for (const { component, calledBy } of subjects) {
17132
+ if (calledBy.size < 2) continue;
17133
+ const groups = groupsSharingCollaborators(calledBy).filter((g) => g.length >= 2);
17134
+ if (groups.length < 2) continue;
17135
+ const described = groups.map((g) => {
17136
+ const collaborators = [...new Set(g.flatMap((m) => [...calledBy.get(m)]))].sort();
17137
+ return `${g.join(", ")} (calling ${collaborators.join(", ")})`;
17138
+ }).join("; ");
17139
+ ctx.addIssue(
17140
+ "warning",
17141
+ "INCOHESIVE_METHODS",
17142
+ `Orchestrator "${component.id}" holds ${groups.length} groups of methods that share no called component: ${described}. Split it along those groups, move the logic out until every method is a single hand-off (a pure forwarder is exempt), or acknowledge a deliberate facade with a reasoned lint.allow for INCOHESIVE_METHODS.`,
17143
+ component.id,
17144
+ ctx.isComponentDraft(component.id)
17145
+ );
17146
+ }
17147
+ }
17148
+ };
17149
+
17058
17150
  // src/core/rules/heuristic/coupling-health.ts
17059
17151
  var DEFAULT_GOD_COMPONENT_THRESHOLD = 8;
17060
17152
  var couplingRule = {
@@ -17064,7 +17156,7 @@ var couplingRule = {
17064
17156
  { code: "MUTUAL_SUBSYSTEM_DEPENDENCY", defaultSeverity: "warning", summary: "Subsystems depend on each other without a declared trusted link" },
17065
17157
  { code: "INVALID_TRUSTED_LINK", defaultSeverity: "error", summary: "trustedLinks references a non-existent subsystem" },
17066
17158
  { code: "UNUSED_TRUSTED_LINK", defaultSeverity: "warning", summary: "trustedLinks declares a peer no dependency actually reaches" },
17067
- { code: "GOD_COMPONENT", defaultSeverity: "warning", summary: "Component with excessive dependency fan-out" }
17159
+ { code: "GOD_COMPONENT", defaultSeverity: "warning", summary: "Component with excessive dependency fan-out; not reported on a pure forwarder, whose every narrated method is a single hand-off" }
17068
17160
  ],
17069
17161
  check(ctx) {
17070
17162
  const subsystemDeps = /* @__PURE__ */ new Map();
@@ -17136,9 +17228,10 @@ var couplingRule = {
17136
17228
  );
17137
17229
  }
17138
17230
  }
17231
+ const forwarders = pureForwarderComponents(ctx);
17139
17232
  for (const comp of ctx.components) {
17140
17233
  const threshold = ctx.complexityConfigFor(comp.subsystem)?.maxComponentDependencies ?? DEFAULT_GOD_COMPONENT_THRESHOLD;
17141
- if (comp.dependsOn.length > threshold) {
17234
+ if (comp.dependsOn.length > threshold && !forwarders.has(comp.id)) {
17142
17235
  ctx.addIssue(
17143
17236
  "warning",
17144
17237
  "GOD_COMPONENT",
@@ -17730,7 +17823,7 @@ var complexityRule = {
17730
17823
  { code: "DESCRIPTION_TOO_SHORT", defaultSeverity: "warning", summary: "Description is shorter than the configured minimum length" },
17731
17824
  { code: "EXCESSIVE_METHODS", defaultSeverity: "warning", summary: "Interface declares more methods than the configured limit" },
17732
17825
  { code: "EXCESSIVE_METHOD_PARAMS", defaultSeverity: "warning", summary: "Interface method declares more parameters than the configured limit" },
17733
- { code: "EXCESSIVE_DEPENDENCIES", defaultSeverity: "warning", summary: "Component has more dependencies than the configured limit" },
17826
+ { code: "EXCESSIVE_DEPENDENCIES", defaultSeverity: "warning", summary: "Component has more dependencies than the configured limit; not reported on a pure forwarder, whose fan-out is a routing table rather than knowledge" },
17734
17827
  { code: "EXCESSIVE_SUBSYSTEM_COMPONENTS", defaultSeverity: "warning", summary: "Subsystem has more direct components than the configured limit" }
17735
17828
  ],
17736
17829
  check(ctx) {
@@ -17750,6 +17843,7 @@ var complexityRule = {
17750
17843
  );
17751
17844
  }
17752
17845
  }
17846
+ const forwarders = pureForwarderComponents(ctx);
17753
17847
  for (const comp of ctx.components) {
17754
17848
  const docConfig = ctx.documentationConfigFor(comp.subsystem);
17755
17849
  const complexityConfig = ctx.complexityConfigFor(comp.subsystem);
@@ -17763,7 +17857,7 @@ var complexityRule = {
17763
17857
  "Component",
17764
17858
  isDraft
17765
17859
  );
17766
- if (complexityConfig?.maxComponentDependencies !== void 0 && comp.dependsOn.length > complexityConfig.maxComponentDependencies) {
17860
+ if (complexityConfig?.maxComponentDependencies !== void 0 && comp.dependsOn.length > complexityConfig.maxComponentDependencies && !forwarders.has(comp.id)) {
17767
17861
  ctx.addIssue(
17768
17862
  "warning",
17769
17863
  "EXCESSIVE_DEPENDENCIES",
@@ -18046,84 +18140,6 @@ var namingDisciplineRule = {
18046
18140
  }
18047
18141
  };
18048
18142
 
18049
- // src/core/rules/heuristic/method-cohesion.ts
18050
- function groupsSharingCollaborators(calledBy) {
18051
- const parent = /* @__PURE__ */ new Map();
18052
- const find = (m) => {
18053
- let root = m;
18054
- while (parent.get(root) !== root) root = parent.get(root);
18055
- return root;
18056
- };
18057
- const union = (a, b) => {
18058
- const [ra, rb] = [find(a), find(b)];
18059
- if (ra !== rb) parent.set(ra, rb);
18060
- };
18061
- const methods = [...calledBy.keys()];
18062
- for (const m of methods) parent.set(m, m);
18063
- for (let i = 0; i < methods.length; i++) {
18064
- for (let j = i + 1; j < methods.length; j++) {
18065
- const shares = [...calledBy.get(methods[i])].some((c) => calledBy.get(methods[j])?.has(c));
18066
- if (shares) union(methods[i], methods[j]);
18067
- }
18068
- }
18069
- const groups = /* @__PURE__ */ new Map();
18070
- for (const m of methods) {
18071
- const root = find(m);
18072
- groups.set(root, [...groups.get(root) ?? [], m]);
18073
- }
18074
- return [...groups.values()];
18075
- }
18076
- function isForwardingMethod(narrative) {
18077
- let handoffs = 0;
18078
- for (const step of narrative) {
18079
- if (step.type === "call" || step.type === "dispatch") handoffs++;
18080
- else if (step.type !== "return") return false;
18081
- }
18082
- return handoffs === 1;
18083
- }
18084
- var methodCohesionRule = {
18085
- name: "method-cohesion",
18086
- description: "An Orchestrator's methods share collaborators; when they split into groups that call no component in common, the component holds more than one responsibility. Reported only where two or more groups each hold two or more methods, so a single specialized method is not a finding \u2014 and never on a pure forwarder, whose every narrated method is a single hand-off and whose responsibility therefore lives in what it forwards to.",
18087
- codes: [
18088
- { code: "INCOHESIVE_METHODS", defaultSeverity: "warning", summary: "Orchestrator's methods form two or more groups of two or more that share no called component" }
18089
- ],
18090
- check(ctx) {
18091
- const subjects = [];
18092
- for (const impl of ctx.implementations) {
18093
- const intf = ctx.interfaceMap.get(impl.contract);
18094
- const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
18095
- if (!comp || comp.componentType !== "Orchestrator") continue;
18096
- const narrated = impl.methods.filter((m) => (m.narrative ?? []).length > 0);
18097
- if (narrated.length > 0 && narrated.every((m) => isForwardingMethod(m.narrative ?? []))) continue;
18098
- const calledBy = /* @__PURE__ */ new Map();
18099
- for (const method of impl.methods) {
18100
- const reached = /* @__PURE__ */ new Set();
18101
- for (const step of method.narrative ?? []) {
18102
- if ((step.type === "call" || step.type === "dispatch") && step.targetComponent) reached.add(step.targetComponent);
18103
- }
18104
- if (reached.size > 0) calledBy.set(method.name, reached);
18105
- }
18106
- subjects.push({ implementation: impl, component: comp, calledBy });
18107
- }
18108
- for (const { component, calledBy } of subjects) {
18109
- if (calledBy.size < 2) continue;
18110
- const groups = groupsSharingCollaborators(calledBy).filter((g) => g.length >= 2);
18111
- if (groups.length < 2) continue;
18112
- const described = groups.map((g) => {
18113
- const collaborators = [...new Set(g.flatMap((m) => [...calledBy.get(m)]))].sort();
18114
- return `${g.join(", ")} (calling ${collaborators.join(", ")})`;
18115
- }).join("; ");
18116
- ctx.addIssue(
18117
- "warning",
18118
- "INCOHESIVE_METHODS",
18119
- `Orchestrator "${component.id}" holds ${groups.length} groups of methods that share no called component: ${described}. Split it along those groups, move the logic out until every method is a single hand-off (a pure forwarder is exempt), or acknowledge a deliberate facade with a reasoned lint.allow for INCOHESIVE_METHODS.`,
18120
- component.id,
18121
- ctx.isComponentDraft(component.id)
18122
- );
18123
- }
18124
- }
18125
- };
18126
-
18127
18143
  // src/core/rules/repository.ts
18128
18144
  var SDD_RULES = [
18129
18145
  hierarchyRule,
@@ -27388,6 +27404,7 @@ function loadProjectConfig4() {
27388
27404
  deleteSubsystemSpec,
27389
27405
  deleteTypeSpec,
27390
27406
  deregisterPackRef,
27407
+ deriveExecutionProfile,
27391
27408
  describeApprover,
27392
27409
  detectDomainCandidates,
27393
27410
  diagnoseProjectPacks,
@@ -27565,6 +27582,7 @@ function loadProjectConfig4() {
27565
27582
  renderWaironGuide,
27566
27583
  repairForeignStepFields,
27567
27584
  resolveAgentTopology,
27585
+ resolveBudget,
27568
27586
  resolveChainingParent,
27569
27587
  resolveDomains,
27570
27588
  resolveExpectedOutputPaths,