@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/cli/index.js +139 -118
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +101 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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,
|