@wairon/cli 5.1.1-dev.43 → 5.1.1-dev.45

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
@@ -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.43";
1225
+ WAIRON_VERSION = "5.1.1-dev.45";
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: "A narrative call, dispatch or register step must name a target component, and a target method unless it dispatches. 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 step asserts.",
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 step of implMethod.narrative) {
9809
- if (step.type !== "call" && step.type !== "dispatch" && step.type !== "register") continue;
9810
- if (!step.targetComponent) {
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 ${step.type} step (${step.stepNumber}) missing "targetComponent".`,
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 = step.targetComponent;
9821
- const verb = step.type === "dispatch" ? "dispatches through" : step.type === "register" ? "registers callback" : "calls";
9822
- if (step.type !== "dispatch" && !step.targetMethod) {
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 ${step.type} step (${step.stepNumber}) missing "targetMethod".`,
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}" (step ${step.stepNumber}) but component "${caller.id}" does not list "${target}" as a dependency.`,
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 (step.type === "dispatch") continue;
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 === step.targetMethod);
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 "${step.targetMethod}" on component "${target}" which is not defined on any of its interfaces (step ${step.stepNumber}).`,
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 step.assertsGuarantees ?? []) {
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 ${step.stepNumber} of "${implMethod.name}" in implementation "${impl.id}" explicitly asserts guarantee "${g}", but the method it calls \u2014 "${step.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.`,
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
- if (methodImpl.narrative.length === 0) {
12560
- const comp = ctx.componentMap.get(compId);
12561
- if (comp && effectiveDetail(methodImpl, impl, comp).level !== "full") {
12562
- for (const depId of [...comp.dependsOn, ...comp.owns]) {
12563
- if (!ctx.componentMap.has(depId)) continue;
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,