@wairon/cli 5.1.1-dev.43 → 5.1.1-dev.44
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 +103 -31
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +102 -29
- package/dist/index.js.map +1 -1
- package/dist/templates/skills/sdd-narrative.md +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1222,7 +1222,7 @@ var init_defaults = __esm({
|
|
|
1222
1222
|
copilot: ".github/prompts",
|
|
1223
1223
|
codex: ".codex/agents"
|
|
1224
1224
|
};
|
|
1225
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
1225
|
+
WAIRON_VERSION = "5.1.1-dev.44";
|
|
1226
1226
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
1227
1227
|
ARCHITECT_AGENT_ID = "agent-architect";
|
|
1228
1228
|
ARCHITECT_TEMPLATE_ID = "architect";
|
|
@@ -1574,6 +1574,11 @@ function passesIntentFloor(text, methodName) {
|
|
|
1574
1574
|
if (norm(t) === norm(methodName)) return false;
|
|
1575
1575
|
return true;
|
|
1576
1576
|
}
|
|
1577
|
+
function parseDeclaredCall(ref) {
|
|
1578
|
+
const at = ref.lastIndexOf(".");
|
|
1579
|
+
if (at <= 0 || at === ref.length - 1) return null;
|
|
1580
|
+
return { compId: ref.slice(0, at), methodName: ref.slice(at + 1) };
|
|
1581
|
+
}
|
|
1577
1582
|
function methodSourceFile(method, implementationSourcePath) {
|
|
1578
1583
|
return method.sourcePath || implementationSourcePath || void 0;
|
|
1579
1584
|
}
|
|
@@ -2204,6 +2209,31 @@ var init_specs = __esm({
|
|
|
2204
2209
|
intent: import_zod8.z.string().optional(),
|
|
2205
2210
|
/** Conformance tier for THIS method (overrides the spec-level default). */
|
|
2206
2211
|
conformance: ConformanceTierSchema.optional(),
|
|
2212
|
+
/**
|
|
2213
|
+
* The calls this method makes, when its narrative does not show them.
|
|
2214
|
+
*
|
|
2215
|
+
* The mirror of the contract's `invokedBy`: that declares the caller
|
|
2216
|
+
* OUTSIDE the modeled graph, this declares the callees INSIDE it. It lives
|
|
2217
|
+
* here and not on the L3 method because what a method CALLS is a property
|
|
2218
|
+
* of the realization — the detail dial that hides the steps is here, and two
|
|
2219
|
+
* implementations of one contract may reach different collaborators —
|
|
2220
|
+
* whereas an external caller is a fact about the contract's role that must
|
|
2221
|
+
* hold for every realization.
|
|
2222
|
+
*
|
|
2223
|
+
* Each entry names one target the way the debt register and a lint allow
|
|
2224
|
+
* name a unit: `<component>.<method>` (a `covers` entry is the same
|
|
2225
|
+
* spelling with the step number a declaration has no equivalent of). A
|
|
2226
|
+
* third vocabulary for "which method" would be the worse outcome.
|
|
2227
|
+
*
|
|
2228
|
+
* The narrative graph walk takes exactly these edges for a method with no
|
|
2229
|
+
* narrative, and NOTHING else: an undeclared collaborator is not reached,
|
|
2230
|
+
* so a lower detail dial no longer vouches for everything the component
|
|
2231
|
+
* declares. Each entry gets the same target validation a `call` step gets
|
|
2232
|
+
* (the component resolves, the caller declares it, the method is on its
|
|
2233
|
+
* contract). Refused beside a non-empty narrative, where the steps already
|
|
2234
|
+
* say what is called and a second spelling could only disagree.
|
|
2235
|
+
*/
|
|
2236
|
+
calls: import_zod8.z.array(import_zod8.z.string().min(1)).optional(),
|
|
2207
2237
|
/**
|
|
2208
2238
|
* The code-level name realizing this contract method in the sourcePath
|
|
2209
2239
|
* file, when it legitimately differs from the intent-language contract
|
|
@@ -2240,7 +2270,16 @@ var init_specs = __esm({
|
|
|
2240
2270
|
* stereotypes should bind tech directly (TECH_ON_LOGIC_COMPONENT).
|
|
2241
2271
|
*/
|
|
2242
2272
|
technologies: import_zod8.z.array(import_zod8.z.string()).optional(),
|
|
2243
|
-
methods: import_zod8.z.array(MethodImplementationSchema).default([]),
|
|
2273
|
+
methods: import_zod8.z.array(MethodImplementationSchema).default([]).superRefine((methods, ctx) => {
|
|
2274
|
+
methods.forEach((m, i) => {
|
|
2275
|
+
if (!m.calls?.length || m.narrative.length === 0) return;
|
|
2276
|
+
ctx.addIssue({
|
|
2277
|
+
code: import_zod8.z.ZodIssueCode.custom,
|
|
2278
|
+
path: [i, "calls"],
|
|
2279
|
+
message: `Method "${m.name}" declares calls AND a narrative \u2014 \`calls\` says what a method calls when its narrative does not show it, and this one has ${m.narrative.length} step(s) that already do. Add the call step, or drop the declaration.`
|
|
2280
|
+
});
|
|
2281
|
+
});
|
|
2282
|
+
}),
|
|
2244
2283
|
/** Spec-level narrative detail default for all methods (each may override). */
|
|
2245
2284
|
detail: NarrativeDetailSchema.optional(),
|
|
2246
2285
|
/** Spec-level conformance tier default (each method may override). */
|
|
@@ -9784,16 +9823,36 @@ var init_contract_symmetry = __esm({
|
|
|
9784
9823
|
});
|
|
9785
9824
|
|
|
9786
9825
|
// src/core/rules/narrative/narrative-target-references.ts
|
|
9787
|
-
var narrativeTargetReferencesRule;
|
|
9826
|
+
var targetsOf, narrativeTargetReferencesRule;
|
|
9788
9827
|
var init_narrative_target_references = __esm({
|
|
9789
9828
|
"src/core/rules/narrative/narrative-target-references.ts"() {
|
|
9790
9829
|
"use strict";
|
|
9830
|
+
init_models();
|
|
9831
|
+
targetsOf = (implMethod) => {
|
|
9832
|
+
const entries = [];
|
|
9833
|
+
for (const step of implMethod.narrative) {
|
|
9834
|
+
if (step.type !== "call" && step.type !== "dispatch" && step.type !== "register") continue;
|
|
9835
|
+
entries.push({
|
|
9836
|
+
kind: step.type,
|
|
9837
|
+
stepNumber: step.stepNumber,
|
|
9838
|
+
targetComponent: step.targetComponent,
|
|
9839
|
+
targetMethod: step.targetMethod,
|
|
9840
|
+
assertsGuarantees: step.assertsGuarantees
|
|
9841
|
+
});
|
|
9842
|
+
}
|
|
9843
|
+
for (const ref of implMethod.calls ?? []) {
|
|
9844
|
+
const parsed = parseDeclaredCall(ref);
|
|
9845
|
+
entries.push(parsed ? { kind: "declared", targetComponent: parsed.compId, targetMethod: parsed.methodName } : { kind: "declared", unparsed: ref });
|
|
9846
|
+
}
|
|
9847
|
+
return entries;
|
|
9848
|
+
};
|
|
9791
9849
|
narrativeTargetReferencesRule = {
|
|
9792
9850
|
name: "narrative-target-references",
|
|
9793
|
-
description:
|
|
9851
|
+
description: `A narrative call, dispatch or register step must name a target component, and a target method unless it dispatches; a method's declared calls name the same pair as one "<component>.<method>" reference, the spelling the conformance debt register and a lint allow name a unit with. A target this tree contains must be a collaborator the calling component declares, must carry the named method on one of its interfaces, and that method must declare every semantic guarantee the entry asserts.`,
|
|
9794
9852
|
codes: [
|
|
9795
9853
|
{ code: "MISSING_TARGET_COMPONENT", defaultSeverity: "error", summary: "Call/register step missing targetComponent" },
|
|
9796
9854
|
{ code: "MISSING_TARGET_METHOD", defaultSeverity: "error", summary: "Call/register step missing targetMethod" },
|
|
9855
|
+
{ code: "MALFORMED_DECLARED_CALL", defaultSeverity: "error", summary: 'Declared call that is not a "<component>.<method>" reference' },
|
|
9797
9856
|
{ code: "UNDECLARED_DEPENDENCY_CALL", defaultSeverity: "error", summary: "Call step targets a component the caller does not depend on or own" },
|
|
9798
9857
|
{ code: "INVALID_TARGET_METHOD_REFERENCE", defaultSeverity: "error", summary: "Call step targets a method not on any target interface" },
|
|
9799
9858
|
{ code: "NARRATIVE_SEMANTIC_UNBACKED", defaultSeverity: "warning", summary: "Narrative asserts a guarantee the called contract does not declare" }
|
|
@@ -9805,25 +9864,35 @@ var init_narrative_target_references = __esm({
|
|
|
9805
9864
|
const isDraftCtx = ctx.isImplementationDraft(impl);
|
|
9806
9865
|
const caller = ctx.componentMap.get(contract.component);
|
|
9807
9866
|
for (const implMethod of impl.methods) {
|
|
9808
|
-
for (const
|
|
9809
|
-
|
|
9810
|
-
if (
|
|
9867
|
+
for (const entry of targetsOf(implMethod)) {
|
|
9868
|
+
const where = entry.stepNumber === void 0 ? "" : ` (step ${entry.stepNumber})`;
|
|
9869
|
+
if (entry.unparsed !== void 0) {
|
|
9870
|
+
ctx.addIssue(
|
|
9871
|
+
"error",
|
|
9872
|
+
"MALFORMED_DECLARED_CALL",
|
|
9873
|
+
`Method "${implMethod.name}" in implementation "${impl.id}" declares the call "${entry.unparsed}", which is not a "<component>.<method>" reference \u2014 the spelling the conformance debt register and a lint allow name a unit with.`,
|
|
9874
|
+
impl.id,
|
|
9875
|
+
isDraftCtx
|
|
9876
|
+
);
|
|
9877
|
+
continue;
|
|
9878
|
+
}
|
|
9879
|
+
if (!entry.targetComponent) {
|
|
9811
9880
|
ctx.addIssue(
|
|
9812
9881
|
"error",
|
|
9813
9882
|
"MISSING_TARGET_COMPONENT",
|
|
9814
|
-
`Method "${implMethod.name}" in implementation "${impl.id}" has a ${
|
|
9883
|
+
`Method "${implMethod.name}" in implementation "${impl.id}" has a ${entry.kind} step (${entry.stepNumber}) missing "targetComponent".`,
|
|
9815
9884
|
impl.id,
|
|
9816
9885
|
isDraftCtx
|
|
9817
9886
|
);
|
|
9818
9887
|
continue;
|
|
9819
9888
|
}
|
|
9820
|
-
const target =
|
|
9821
|
-
const verb =
|
|
9822
|
-
if (
|
|
9889
|
+
const target = entry.targetComponent;
|
|
9890
|
+
const verb = entry.kind === "dispatch" ? "dispatches through" : entry.kind === "register" ? "registers callback" : entry.kind === "declared" ? "declares a call to" : "calls";
|
|
9891
|
+
if (entry.kind !== "dispatch" && !entry.targetMethod) {
|
|
9823
9892
|
ctx.addIssue(
|
|
9824
9893
|
"error",
|
|
9825
9894
|
"MISSING_TARGET_METHOD",
|
|
9826
|
-
`Method "${implMethod.name}" in implementation "${impl.id}" has a ${
|
|
9895
|
+
`Method "${implMethod.name}" in implementation "${impl.id}" has a ${entry.kind} step (${entry.stepNumber}) missing "targetMethod".`,
|
|
9827
9896
|
impl.id,
|
|
9828
9897
|
isDraftCtx
|
|
9829
9898
|
);
|
|
@@ -9834,16 +9903,16 @@ var init_narrative_target_references = __esm({
|
|
|
9834
9903
|
ctx.addIssue(
|
|
9835
9904
|
"error",
|
|
9836
9905
|
"UNDECLARED_DEPENDENCY_CALL",
|
|
9837
|
-
`Method "${implMethod.name}" in implementation "${impl.id}" (component "${caller.id}") ${verb} component "${target}"
|
|
9906
|
+
`Method "${implMethod.name}" in implementation "${impl.id}" (component "${caller.id}") ${verb} component "${target}"${where} but component "${caller.id}" does not list "${target}" as a dependency.`,
|
|
9838
9907
|
impl.id,
|
|
9839
9908
|
isDraftCtx || ctx.isComponentDraft(caller.id)
|
|
9840
9909
|
);
|
|
9841
9910
|
}
|
|
9842
|
-
if (
|
|
9911
|
+
if (entry.kind === "dispatch") continue;
|
|
9843
9912
|
const targetInterfaces = ctx.interfacesByComponent.get(target) ?? [];
|
|
9844
9913
|
let targetMethodSpec;
|
|
9845
9914
|
for (const targetIntf of targetInterfaces) {
|
|
9846
|
-
const found = targetIntf.methods.find((m) => m.name ===
|
|
9915
|
+
const found = targetIntf.methods.find((m) => m.name === entry.targetMethod);
|
|
9847
9916
|
if (found) {
|
|
9848
9917
|
targetMethodSpec = found;
|
|
9849
9918
|
break;
|
|
@@ -9853,19 +9922,19 @@ var init_narrative_target_references = __esm({
|
|
|
9853
9922
|
ctx.addIssue(
|
|
9854
9923
|
"error",
|
|
9855
9924
|
"INVALID_TARGET_METHOD_REFERENCE",
|
|
9856
|
-
`Method "${implMethod.name}" in implementation "${impl.id}" ${verb} method "${
|
|
9925
|
+
`Method "${implMethod.name}" in implementation "${impl.id}" ${verb} method "${entry.targetMethod}" on component "${target}" which is not defined on any of its interfaces${where}.`,
|
|
9857
9926
|
impl.id,
|
|
9858
9927
|
isDraftCtx || ctx.isComponentDraft(target)
|
|
9859
9928
|
);
|
|
9860
9929
|
continue;
|
|
9861
9930
|
}
|
|
9862
9931
|
const declared = new Set(targetMethodSpec.guarantees ?? []);
|
|
9863
|
-
for (const g of
|
|
9932
|
+
for (const g of entry.assertsGuarantees ?? []) {
|
|
9864
9933
|
if (!declared.has(g)) {
|
|
9865
9934
|
ctx.addIssue(
|
|
9866
9935
|
"warning",
|
|
9867
9936
|
"NARRATIVE_SEMANTIC_UNBACKED",
|
|
9868
|
-
`Step ${
|
|
9937
|
+
`Step ${entry.stepNumber} of "${implMethod.name}" in implementation "${impl.id}" explicitly asserts guarantee "${g}", but the method it calls \u2014 "${entry.targetMethod}" on "${target}" \u2014 does not list "${g}" among its L3 contract guarantees. Declare it on that method (and ensure its shape can deliver it), or revise the narrative.`,
|
|
9869
9938
|
impl.id,
|
|
9870
9939
|
isDraftCtx || ctx.isComponentDraft(target)
|
|
9871
9940
|
);
|
|
@@ -12556,15 +12625,11 @@ function walk(ctx, seeds, options = {}) {
|
|
|
12556
12625
|
if (edge.methodName) enqueueMethod(edge.compId, edge.methodName);
|
|
12557
12626
|
}
|
|
12558
12627
|
}
|
|
12559
|
-
|
|
12560
|
-
const
|
|
12561
|
-
if (
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
reachComponent(depId);
|
|
12565
|
-
enqueueAllMethods(depId);
|
|
12566
|
-
}
|
|
12567
|
-
}
|
|
12628
|
+
for (const ref of methodImpl.calls ?? []) {
|
|
12629
|
+
const parsed = parseDeclaredCall(ref);
|
|
12630
|
+
if (!parsed || !ctx.componentMap.has(parsed.compId)) continue;
|
|
12631
|
+
reachComponent(parsed.compId);
|
|
12632
|
+
enqueueMethod(parsed.compId, parsed.methodName);
|
|
12568
12633
|
}
|
|
12569
12634
|
}
|
|
12570
12635
|
return {
|
|
@@ -12629,7 +12694,9 @@ var init_unused_detection = __esm({
|
|
|
12629
12694
|
"INVOKED_BY_REDUNDANT",
|
|
12630
12695
|
`Method "${m.name}" on component "${intf.component}" declares invokedBy (${m.invokedBy.kind}), but the internal narrative walk already reaches it \u2014 the declaration is stale; remove it.`,
|
|
12631
12696
|
intf.id,
|
|
12632
|
-
isDraftCtx
|
|
12697
|
+
isDraftCtx,
|
|
12698
|
+
void 0,
|
|
12699
|
+
{ at: m.name }
|
|
12633
12700
|
);
|
|
12634
12701
|
}
|
|
12635
12702
|
}
|
|
@@ -12657,7 +12724,11 @@ var init_unused_detection = __esm({
|
|
|
12657
12724
|
"UNUSED_METHOD",
|
|
12658
12725
|
`Method "${m.name}" on component "${comp.id}" is defined but never called by any narrative step.`,
|
|
12659
12726
|
intf.id,
|
|
12660
|
-
isDraftCtx
|
|
12727
|
+
isDraftCtx,
|
|
12728
|
+
void 0,
|
|
12729
|
+
// The site is the method, so an allow covers exactly the one it
|
|
12730
|
+
// names - never its neighbours on the same interface.
|
|
12731
|
+
{ at: m.name }
|
|
12661
12732
|
);
|
|
12662
12733
|
}
|
|
12663
12734
|
}
|
|
@@ -27361,6 +27432,7 @@ __export(src_exports, {
|
|
|
27361
27432
|
packEntryLabel: () => packEntryLabel,
|
|
27362
27433
|
packEntryRef: () => packEntryRef,
|
|
27363
27434
|
packStoreDir: () => packStoreDir,
|
|
27435
|
+
parseDeclaredCall: () => parseDeclaredCall,
|
|
27364
27436
|
parseTemplate: () => parseTemplate,
|
|
27365
27437
|
parseYaml: () => parseYaml,
|
|
27366
27438
|
passesIntentFloor: () => passesIntentFloor,
|
|
@@ -28099,6 +28171,7 @@ function loadProjectConfig4() {
|
|
|
28099
28171
|
packEntryLabel,
|
|
28100
28172
|
packEntryRef,
|
|
28101
28173
|
packStoreDir,
|
|
28174
|
+
parseDeclaredCall,
|
|
28102
28175
|
parseTemplate,
|
|
28103
28176
|
parseYaml,
|
|
28104
28177
|
passesIntentFloor,
|