@wairon/cli 5.1.1-dev.15 → 5.1.1-dev.17

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
@@ -1092,7 +1092,7 @@ var init_defaults = __esm({
1092
1092
  copilot: ".github/prompts",
1093
1093
  codex: ".codex/agents"
1094
1094
  };
1095
- WAIRON_VERSION = "5.1.1-dev.15";
1095
+ WAIRON_VERSION = "5.1.1-dev.17";
1096
1096
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
1097
1097
  ARCHITECT_AGENT_ID = "agent-architect";
1098
1098
  ARCHITECT_TEMPLATE_ID = "architect";
@@ -1406,7 +1406,7 @@ function defaultNarrativeDetail(component) {
1406
1406
  if (componentType === "Portal" || componentType === "Observer" || componentType === "Adapter") {
1407
1407
  return "calls-only";
1408
1408
  }
1409
- if (componentType === "Store" || componentType === "Index" || componentType === "Registry") {
1409
+ if (componentType === "Store" || componentType === "Index" || componentType === "Query" || componentType === "Registry") {
1410
1410
  return "intent";
1411
1411
  }
1412
1412
  return "full";
@@ -1414,6 +1414,17 @@ function defaultNarrativeDetail(component) {
1414
1414
  function isPattern(component) {
1415
1415
  return PATTERN_TYPES.has(component.componentType);
1416
1416
  }
1417
+ function isLogic(component) {
1418
+ const componentType = component.componentType;
1419
+ return componentType === "Orchestrator" || componentType === "Supervisor" || componentType === "Actor" || componentType === "Specialist";
1420
+ }
1421
+ function holdsState(component) {
1422
+ const componentType = component.componentType;
1423
+ return componentType === "Store" || componentType === "Index" || componentType === "Supervisor" || componentType === "Actor";
1424
+ }
1425
+ function isRetired(component) {
1426
+ return RETIRED_STEREOTYPES.has(component.componentType);
1427
+ }
1417
1428
  function passesIntentFloor(text, methodName) {
1418
1429
  if (!text) return false;
1419
1430
  const t = text.trim();
@@ -1439,7 +1450,7 @@ function implementationSourceFiles(impl) {
1439
1450
  for (const method of impl.methods ?? []) add(method.sourcePath);
1440
1451
  return files;
1441
1452
  }
1442
- var import_zod8, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, PatternRefSchema, EventBindingSchema, ExternalLinkTypeSchema, ExternalLinkSchema, PortalAuthSchemeSchema, PortalAuthSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, FindingDeclarationSchema, MethodSignatureSchema, INTENT_FLOOR_MIN_CHARS, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, NamedOpenApiSpecSchema, GroupSpecSchema;
1453
+ var import_zod8, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, RETIRED_STEREOTYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, DependencyClassSchema, PatternRefSchema, EventBindingSchema, ExternalLinkTypeSchema, ExternalLinkSchema, PortalAuthSchemeSchema, PortalAuthSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, FindingDeclarationSchema, MethodSignatureSchema, INTENT_FLOOR_MIN_CHARS, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, NamedOpenApiSpecSchema, GroupSpecSchema;
1443
1454
  var init_specs = __esm({
1444
1455
  "src/models/specs.ts"() {
1445
1456
  "use strict";
@@ -1605,21 +1616,28 @@ var init_specs = __esm({
1605
1616
  "Actor",
1606
1617
  "Store",
1607
1618
  "Index",
1619
+ "Query",
1620
+ // Repository member for computed reads over its Store
1608
1621
  "Registry",
1609
1622
  "Adapter",
1610
1623
  "Observer",
1611
- "Specialist",
1612
1624
  "View",
1613
1625
  // Pure presenter/UI component
1614
1626
  // Patterns (compositions of blocks)
1615
1627
  "Repository",
1616
- "Gateway",
1617
1628
  "FeatureComponent",
1618
1629
  // Logic Hook + View Presenter pattern
1619
- "RouterComponent"
1630
+ "RouterComponent",
1620
1631
  // Switch/routing component pattern
1632
+ // Retired stereotypes: still parsed so a tree using them loads and the
1633
+ // rules can report them (STEREOTYPE_RETIRED), never authored new
1634
+ "Specialist",
1635
+ // logic is an Orchestrator with a dependencyClass
1636
+ "Gateway"
1637
+ // a gateway is a Portal with the gateway variant
1621
1638
  ]);
1622
- PATTERN_TYPES = /* @__PURE__ */ new Set(["Repository", "Gateway", "FeatureComponent", "RouterComponent"]);
1639
+ PATTERN_TYPES = /* @__PURE__ */ new Set(["Repository", "FeatureComponent", "RouterComponent"]);
1640
+ RETIRED_STEREOTYPES = /* @__PURE__ */ new Set(["Specialist", "Gateway"]);
1623
1641
  PortalTypeSchema = import_zod8.z.enum(["HTTP_API", "gRPC", "GraphQL", "MessageBus", "CLI", "NamedPipe", "IPC", "Custom"]);
1624
1642
  DispatchBindingSchema = import_zod8.z.object({
1625
1643
  /** Capability name exactly as dispatched at runtime (e.g. "shadow_module.get"). */
@@ -1632,6 +1650,7 @@ var init_specs = __esm({
1632
1650
  description: import_zod8.z.string().optional()
1633
1651
  });
1634
1652
  DurabilitySchema = import_zod8.z.enum(["ram-projection", "durable", "read-through", "cache"]);
1653
+ DependencyClassSchema = import_zod8.z.enum(["pure", "read"]);
1635
1654
  PatternRefSchema = import_zod8.z.object({
1636
1655
  id: import_zod8.z.string(),
1637
1656
  version: import_zod8.z.string().optional()
@@ -1686,6 +1705,8 @@ var init_specs = __esm({
1686
1705
  dispatch: import_zod8.z.array(DispatchBindingSchema).optional(),
1687
1706
  /** Store-only: whether held state survives restart (see DurabilitySchema). */
1688
1707
  durability: DurabilitySchema.optional(),
1708
+ /** Orchestrator-only: what the logic may depend on; unset means a workflow (see DependencyClassSchema). */
1709
+ dependencyClass: DependencyClassSchema.optional(),
1689
1710
  /** Topics this component publishes to (see EventBindingSchema). */
1690
1711
  emits: import_zod8.z.array(EventBindingSchema).optional(),
1691
1712
  /** Topics this component consumes (see EventBindingSchema) — typical on Observers. */
@@ -1776,9 +1797,10 @@ var init_specs = __esm({
1776
1797
  }).optional(),
1777
1798
  /**
1778
1799
  * The finding codes this method can report, each with its default severity
1779
- * and summary (see FindingDeclarationSchema). Each declared code must appear
1780
- * as a string literal in the method's source file (UNREALIZED_FINDING). A
1781
- * code is declared once per method.
1800
+ * and summary (see FindingDeclarationSchema). Each declared code must be
1801
+ * anchored in the method's source file as a string literal or a
1802
+ * property-access name (UNREALIZED_FINDING). A code is declared once per
1803
+ * method.
1782
1804
  */
1783
1805
  findings: import_zod8.z.array(FindingDeclarationSchema).superRefine((findings, ctx) => {
1784
1806
  const seen = /* @__PURE__ */ new Set();
@@ -2766,15 +2788,13 @@ var init_hierarchy_integrity = __esm({
2766
2788
  }
2767
2789
  }
2768
2790
  for (const impl of ctx.implementations) {
2769
- const contract = ctx.interfaces.find((i) => i.id === impl.contract);
2770
- const isDraftCtx = impl.status === "draft" || impl.status === "design" || contract && (ctx.isComponentDraft(contract.component) || contract.status === "draft" || contract.status === "design");
2771
2791
  if (!ctx.interfaceIds.has(impl.contract)) {
2772
2792
  ctx.addIssue(
2773
2793
  "error",
2774
2794
  "INVALID_INTERFACE_REFERENCE",
2775
2795
  `Implementation "${impl.id}" references non-existent interface contract "${impl.contract}".`,
2776
2796
  impl.id,
2777
- isDraftCtx
2797
+ ctx.isImplementationDraft(impl)
2778
2798
  );
2779
2799
  }
2780
2800
  }
@@ -2890,11 +2910,7 @@ var init_type_references2 = __esm({
2890
2910
  for (const field of t.fields) {
2891
2911
  const refs = fieldTypeRefs(t, field.type);
2892
2912
  for (const ref of refs) {
2893
- if (ctx.isBuiltinType(ref)) {
2894
- continue;
2895
- }
2896
- const resolved = ctx.types.find((spec) => typeMatchesRef(spec, ref));
2897
- if (!resolved) {
2913
+ if (!ctx.isTypeResolved(ref, /* @__PURE__ */ new Set())) {
2898
2914
  ctx.addIssue(
2899
2915
  "error",
2900
2916
  "UNDEFINED_TYPE_REFERENCE",
@@ -3126,14 +3142,27 @@ var init_contract_symmetry_and_narratives = __esm({
3126
3142
  );
3127
3143
  continue;
3128
3144
  }
3129
- const isCrossTreeForm = ctx.isExternalNamespaceRef(step.targetComponent);
3130
- const fromSubsystem = ctx.componentMap.get(contract.component)?.subsystem;
3131
- const isCollapsedForm = !isCrossTreeForm && fromSubsystem !== void 0 && ctx.isCollapsedCrossTreeRef(step.targetComponent, fromSubsystem);
3145
+ const target = step.targetComponent;
3146
+ const isCrossTreeForm = ctx.isExternalNamespaceRef(target);
3147
+ const caller = ctx.componentMap.get(contract.component);
3148
+ const fromSubsystem = caller?.subsystem;
3149
+ const isCollapsedForm = !isCrossTreeForm && fromSubsystem !== void 0 && ctx.isCollapsedCrossTreeRef(target, fromSubsystem);
3150
+ const reportUndeclared = (reaches, surfaceResolved) => {
3151
+ if (!caller || target === caller.id || caller.dependsOn.includes(target) || caller.owns.includes(target)) return;
3152
+ ctx.addIssue(
3153
+ "error",
3154
+ "UNDECLARED_DEPENDENCY_CALL",
3155
+ `Method "${implMethod.name}" in implementation "${impl.id}" (component "${caller.id}") ${reaches} component "${target}" (step ${step.stepNumber}) but component "${caller.id}" does not list "${target}" as a dependency.`,
3156
+ impl.id,
3157
+ isDraftCtx || ctx.isComponentDraft(caller.id),
3158
+ surfaceResolved
3159
+ );
3160
+ };
3132
3161
  if (step.type === "dispatch") {
3133
- const dispatchTarget = ctx.componentMap.get(step.targetComponent);
3162
+ const dispatchTarget = ctx.componentMap.get(target);
3134
3163
  if (!dispatchTarget) {
3135
3164
  if (isCrossTreeForm || isCollapsedForm) {
3136
- const resolved = ctx.resolveSurfaceRef(step.targetComponent, fromSubsystem);
3165
+ const resolved = ctx.resolveSurfaceRef(target, fromSubsystem);
3137
3166
  if (resolved.kind === "ambiguous") {
3138
3167
  ctx.addIssue(
3139
3168
  "error",
@@ -3141,7 +3170,7 @@ var init_contract_symmetry_and_narratives = __esm({
3141
3170
  ambiguityMessage(
3142
3171
  resolved,
3143
3172
  `Method "${implMethod.name}" in implementation "${impl.id}" dispatches (step ${step.stepNumber}) through`,
3144
- step.targetComponent
3173
+ target
3145
3174
  ),
3146
3175
  impl.id,
3147
3176
  isDraftCtx
@@ -3149,11 +3178,12 @@ var init_contract_symmetry_and_narratives = __esm({
3149
3178
  continue;
3150
3179
  }
3151
3180
  if (resolved.kind === "resolved") {
3181
+ reportUndeclared("dispatches through", true);
3152
3182
  if (step.capability && !(resolved.entry.dispatch ?? []).some((b) => b.capability === step.capability)) {
3153
3183
  ctx.addIssue(
3154
3184
  "error",
3155
3185
  "SURFACE_REF_NOT_EXPOSED",
3156
- `Method "${implMethod.name}" in implementation "${impl.id}" dispatches capability "${step.capability}" through cross-tree portal "${step.targetComponent}" (step ${step.stepNumber}), but the surface snapshot of "${resolved.snapshot.projectName}" does not serve that capability on "${resolved.entry.id}".`,
3186
+ `Method "${implMethod.name}" in implementation "${impl.id}" dispatches capability "${step.capability}" through cross-tree portal "${target}" (step ${step.stepNumber}), but the surface snapshot of "${resolved.snapshot.projectName}" does not serve that capability on "${resolved.entry.id}".`,
3157
3187
  impl.id,
3158
3188
  isDraftCtx,
3159
3189
  true
@@ -3166,7 +3196,7 @@ var init_contract_symmetry_and_narratives = __esm({
3166
3196
  ctx.addIssue(
3167
3197
  "warning",
3168
3198
  "CROSS_TREE_REF_UNRESOLVED",
3169
- `Method "${implMethod.name}" in implementation "${impl.id}" dispatches through cross-tree component "${step.targetComponent}" (step ${step.stepNumber}), and no surface snapshot covers it \u2014 validate from the parent project, pin the family surfaces ("wairon surface pin"), or import the producing project's surface.`,
3199
+ `Method "${implMethod.name}" in implementation "${impl.id}" dispatches through cross-tree component "${target}" (step ${step.stepNumber}), and no surface snapshot covers it \u2014 validate from the parent project, pin the family surfaces ("wairon surface pin"), or import the producing project's surface.`,
3170
3200
  impl.id,
3171
3201
  isDraftCtx
3172
3202
  );
@@ -3174,23 +3204,14 @@ var init_contract_symmetry_and_narratives = __esm({
3174
3204
  ctx.addIssue(
3175
3205
  "error",
3176
3206
  "INVALID_TARGET_COMPONENT_REFERENCE",
3177
- `Method "${implMethod.name}" in implementation "${impl.id}" dispatches through component "${step.targetComponent}" which does not exist (step ${step.stepNumber}).`,
3207
+ `Method "${implMethod.name}" in implementation "${impl.id}" dispatches through component "${target}" which does not exist (step ${step.stepNumber}).`,
3178
3208
  impl.id,
3179
3209
  isDraftCtx
3180
3210
  );
3181
3211
  }
3182
3212
  continue;
3183
3213
  }
3184
- const dispatchCaller = ctx.componentMap.get(contract.component);
3185
- if (dispatchCaller && step.targetComponent !== dispatchCaller.id && !dispatchCaller.dependsOn.includes(step.targetComponent) && !dispatchCaller.owns.includes(step.targetComponent)) {
3186
- ctx.addIssue(
3187
- "error",
3188
- "UNDECLARED_DEPENDENCY_CALL",
3189
- `Method "${implMethod.name}" in implementation "${impl.id}" (component "${dispatchCaller.id}") dispatches through component "${step.targetComponent}" (step ${step.stepNumber}) but component "${dispatchCaller.id}" does not list "${step.targetComponent}" as a dependency.`,
3190
- impl.id,
3191
- isDraftCtx || ctx.isComponentDraft(dispatchCaller.id)
3192
- );
3193
- }
3214
+ reportUndeclared("dispatches through");
3194
3215
  continue;
3195
3216
  }
3196
3217
  const verb = step.type === "register" ? "registers callback" : "calls";
@@ -3204,10 +3225,10 @@ var init_contract_symmetry_and_narratives = __esm({
3204
3225
  );
3205
3226
  continue;
3206
3227
  }
3207
- const targetComp = ctx.componentMap.get(step.targetComponent);
3228
+ const targetComp = ctx.componentMap.get(target);
3208
3229
  if (!targetComp) {
3209
3230
  if (isCrossTreeForm || isCollapsedForm) {
3210
- const resolved = ctx.resolveSurfaceRef(step.targetComponent, fromSubsystem);
3231
+ const resolved = ctx.resolveSurfaceRef(target, fromSubsystem);
3211
3232
  if (resolved.kind === "ambiguous") {
3212
3233
  ctx.addIssue(
3213
3234
  "error",
@@ -3215,7 +3236,7 @@ var init_contract_symmetry_and_narratives = __esm({
3215
3236
  ambiguityMessage(
3216
3237
  resolved,
3217
3238
  `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} "${step.targetMethod}" (step ${step.stepNumber}) on`,
3218
- step.targetComponent
3239
+ target
3219
3240
  ),
3220
3241
  impl.id,
3221
3242
  isDraftCtx
@@ -3223,12 +3244,13 @@ var init_contract_symmetry_and_narratives = __esm({
3223
3244
  continue;
3224
3245
  }
3225
3246
  if (resolved.kind === "resolved") {
3247
+ reportUndeclared(verb, true);
3226
3248
  const surfaceMethod = resolved.entry.methods.find((m) => m.name === step.targetMethod);
3227
3249
  if (!surfaceMethod) {
3228
3250
  ctx.addIssue(
3229
3251
  "error",
3230
3252
  "SURFACE_REF_NOT_EXPOSED",
3231
- `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} "${step.targetMethod}" on cross-tree component "${step.targetComponent}" (step ${step.stepNumber}), but the surface snapshot of "${resolved.snapshot.projectName}" does not expose that method on "${resolved.entry.id}".`,
3253
+ `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} "${step.targetMethod}" on cross-tree component "${target}" (step ${step.stepNumber}), but the surface snapshot of "${resolved.snapshot.projectName}" does not expose that method on "${resolved.entry.id}".`,
3232
3254
  impl.id,
3233
3255
  isDraftCtx,
3234
3256
  true
@@ -3255,7 +3277,7 @@ var init_contract_symmetry_and_narratives = __esm({
3255
3277
  ctx.addIssue(
3256
3278
  "warning",
3257
3279
  "CROSS_TREE_REF_UNRESOLVED",
3258
- `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} cross-tree component "${step.targetComponent}" (step ${step.stepNumber}), and no surface snapshot covers it \u2014 validate from the parent project, pin the family surfaces ("wairon surface pin"), or import the producing project's surface.`,
3280
+ `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} cross-tree component "${target}" (step ${step.stepNumber}), and no surface snapshot covers it \u2014 validate from the parent project, pin the family surfaces ("wairon surface pin"), or import the producing project's surface.`,
3259
3281
  impl.id,
3260
3282
  isDraftCtx
3261
3283
  );
@@ -3263,26 +3285,15 @@ var init_contract_symmetry_and_narratives = __esm({
3263
3285
  ctx.addIssue(
3264
3286
  "error",
3265
3287
  "INVALID_TARGET_COMPONENT_REFERENCE",
3266
- `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} component "${step.targetComponent}" which does not exist (step ${step.stepNumber}).`,
3288
+ `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} component "${target}" which does not exist (step ${step.stepNumber}).`,
3267
3289
  impl.id,
3268
3290
  isDraftCtx
3269
3291
  );
3270
3292
  }
3271
3293
  continue;
3272
3294
  }
3273
- const callingComponent = ctx.componentMap.get(contract.component);
3274
- if (callingComponent && step.targetComponent !== callingComponent.id) {
3275
- if (!callingComponent.dependsOn.includes(step.targetComponent) && !callingComponent.owns.includes(step.targetComponent)) {
3276
- ctx.addIssue(
3277
- "error",
3278
- "UNDECLARED_DEPENDENCY_CALL",
3279
- `Method "${implMethod.name}" in implementation "${impl.id}" (component "${callingComponent.id}") ${verb} component "${step.targetComponent}" (step ${step.stepNumber}) but component "${callingComponent.id}" does not list "${step.targetComponent}" as a dependency.`,
3280
- impl.id,
3281
- isDraftCtx || ctx.isComponentDraft(callingComponent.id)
3282
- );
3283
- }
3284
- }
3285
- const targetInterfaces = ctx.interfacesByComponent.get(step.targetComponent) ?? [];
3295
+ reportUndeclared(verb);
3296
+ const targetInterfaces = ctx.interfacesByComponent.get(target) ?? [];
3286
3297
  let targetMethodSpec;
3287
3298
  for (const targetIntf of targetInterfaces) {
3288
3299
  const found = targetIntf.methods.find((m) => m.name === step.targetMethod);
@@ -3295,9 +3306,9 @@ var init_contract_symmetry_and_narratives = __esm({
3295
3306
  ctx.addIssue(
3296
3307
  "error",
3297
3308
  "INVALID_TARGET_METHOD_REFERENCE",
3298
- `Method "${implMethod.name}" in implementation "${impl.id}" ${verb} method "${step.targetMethod}" on component "${step.targetComponent}" which is not defined on any of its interfaces (step ${step.stepNumber}).`,
3309
+ `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}).`,
3299
3310
  impl.id,
3300
- isDraftCtx || ctx.isComponentDraft(step.targetComponent)
3311
+ isDraftCtx || ctx.isComponentDraft(target)
3301
3312
  );
3302
3313
  } else {
3303
3314
  const declared = new Set(targetMethodSpec.guarantees ?? []);
@@ -3307,9 +3318,9 @@ var init_contract_symmetry_and_narratives = __esm({
3307
3318
  ctx.addIssue(
3308
3319
  "warning",
3309
3320
  "NARRATIVE_SEMANTIC_UNBACKED",
3310
- `Step ${step.stepNumber} of "${implMethod.name}" in implementation "${impl.id}" explicitly asserts guarantee "${g}", but the method it calls \u2014 "${step.targetMethod}" on "${step.targetComponent}" \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.`,
3321
+ `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.`,
3311
3322
  impl.id,
3312
- isDraftCtx || ctx.isComponentDraft(step.targetComponent)
3323
+ isDraftCtx || ctx.isComponentDraft(target)
3313
3324
  );
3314
3325
  }
3315
3326
  }
@@ -3639,43 +3650,47 @@ var init_narrative_flow = __esm({
3639
3650
  });
3640
3651
 
3641
3652
  // src/core/rules/narrative/narrative-antipatterns.ts
3642
- function isTerminal(step, nextOf) {
3643
- if (step.type === "return" || step.type === "throw") return true;
3644
- const n = step.stepNumber;
3645
- switch (step.type) {
3646
- case "local":
3647
- case "call":
3648
- case "register":
3649
- case "dispatch":
3650
- return nextOf(n) === void 0;
3651
- case "branch":
3652
- return step.onTrueStep === void 0 && nextOf(n) === void 0;
3653
- case "switch":
3654
- return step.defaultStep === void 0 && nextOf(n) === void 0;
3655
- case "loop":
3656
- case "try":
3657
- return step.endStep !== void 0 && nextOf(step.endStep) === void 0;
3658
- default:
3659
- return false;
3660
- }
3653
+ function completedStepGraph(steps) {
3654
+ const numbers = steps.flatMap((s) => [
3655
+ s.stepNumber,
3656
+ s.onTrueStep,
3657
+ s.onFalseStep,
3658
+ s.defaultStep,
3659
+ s.endStep,
3660
+ s.finallyStep,
3661
+ s.toStep,
3662
+ ...(s.cases ?? []).map((c) => c.step),
3663
+ ...(s.catches ?? []).map((c) => c.step),
3664
+ ...(s.branches ?? []).map((b) => b.step)
3665
+ ]).filter((n) => n !== void 0);
3666
+ const completion = {
3667
+ stepNumber: Math.max(0, ...numbers) + 1,
3668
+ description: "The method completes by falling off the end of its narrative",
3669
+ type: "return"
3670
+ };
3671
+ return stepGraph({ narrative: [...steps, completion] });
3661
3672
  }
3662
3673
  function isUnavoidable(steps, target) {
3663
- const { stepNumbers: nums, stepAt, nextOf, successorsOf } = stepGraph({ narrative: steps });
3664
- if (nums.length === 0) return false;
3665
- if (nums[0] === target) return true;
3666
- const visited = /* @__PURE__ */ new Set();
3667
- const stack = [nums[0]];
3668
- while (stack.length) {
3669
- const n = stack.pop();
3670
- if (n === target || visited.has(n)) continue;
3671
- visited.add(n);
3672
- const s = stepAt(n);
3673
- if (isTerminal(s, nextOf)) return false;
3674
- for (const t of successorsOf(n)) {
3675
- if (t !== target && !visited.has(t)) stack.push(t);
3674
+ if (steps.length === 0) return false;
3675
+ const graph = completedStepGraph(steps);
3676
+ const completes = /* @__PURE__ */ new Set();
3677
+ const canComplete = (n) => {
3678
+ const s = graph.stepAt(n);
3679
+ if (s.type === "return" || s.type === "throw") return true;
3680
+ const arms = s.type === "parallel" ? (s.branches ?? []).map((b) => b.step).filter((e) => graph.stepAt(e) !== void 0) : [];
3681
+ if (arms.length) return arms.every((e) => completes.has(e));
3682
+ return graph.successorsOf(n).some((t) => completes.has(t));
3683
+ };
3684
+ const order = [...graph.stepNumbers].reverse();
3685
+ for (let grew = true; grew; ) {
3686
+ grew = false;
3687
+ for (const n of order) {
3688
+ if (n === target || completes.has(n) || !canComplete(n)) continue;
3689
+ completes.add(n);
3690
+ grew = true;
3676
3691
  }
3677
3692
  }
3678
- return true;
3693
+ return !completes.has(graph.stepNumbers[0]);
3679
3694
  }
3680
3695
  function stronglyConnected(nums, successorsOf) {
3681
3696
  const index = /* @__PURE__ */ new Map();
@@ -3727,11 +3742,12 @@ function stronglyConnected(nums, successorsOf) {
3727
3742
  }
3728
3743
  return sccs;
3729
3744
  }
3730
- var narrativeAntipatternsRule;
3745
+ var byCodeUnit, narrativeAntipatternsRule;
3731
3746
  var init_narrative_antipatterns = __esm({
3732
3747
  "src/core/rules/narrative/narrative-antipatterns.ts"() {
3733
3748
  "use strict";
3734
3749
  init_models();
3750
+ byCodeUnit = (a, b) => a < b ? -1 : a > b ? 1 : 0;
3735
3751
  narrativeAntipatternsRule = {
3736
3752
  name: "narrative-antipatterns",
3737
3753
  description: "Provable narrative bugs, caught at spec level before implementation: a step-graph cycle with no exit edge and no return/throw member never terminates by construction (INESCAPABLE_CYCLE); a branch or switch whose arms all target the same step decides nothing (MEANINGLESS_BRANCH); a method-level call cycle across components in which every call edge is unavoidable on every entry-to-exit path is unbounded recursion (UNCONDITIONAL_CALL_CYCLE \u2014 dispatch steps resolved through their portal tables; a cycle with even one guarded edge is NOT flagged, since prose conditions are never judged). Structure-only claims \u2014 warnings, lint.allow-suppressible.",
@@ -3750,29 +3766,33 @@ var init_narrative_antipatterns = __esm({
3750
3766
  const steps = implMethod.narrative;
3751
3767
  if (!steps.length) continue;
3752
3768
  const where = `Method "${implMethod.name}" in implementation "${impl.id}": `;
3753
- const graph = stepGraph(implMethod);
3769
+ const graph = completedStepGraph(steps);
3770
+ const decisionTargets = (stepNumber, explicit, fallThroughField) => {
3771
+ const targets = new Set(explicit);
3772
+ if (fallThroughField !== void 0) targets.add(fallThroughField);
3773
+ else for (const t of graph.successorsOf(stepNumber)) targets.add(t);
3774
+ return [...targets];
3775
+ };
3754
3776
  for (const s of steps) {
3755
3777
  if (s.type === "branch" && s.onFalseStep !== void 0) {
3756
- const onTrue = s.onTrueStep ?? graph.nextOf(s.stepNumber);
3757
- if (onTrue !== void 0 && onTrue === s.onFalseStep) {
3778
+ const targets = decisionTargets(s.stepNumber, [s.onFalseStep], s.onTrueStep);
3779
+ if (targets.length === 1) {
3758
3780
  ctx.addIssue(
3759
3781
  "warning",
3760
3782
  "MEANINGLESS_BRANCH",
3761
- `${where}branch step ${s.stepNumber} sends both arms to step ${onTrue} \u2014 the condition decides nothing. Point the arms at different steps, or replace the branch with a local step.`,
3783
+ `${where}branch step ${s.stepNumber} sends both arms to step ${targets[0]} \u2014 the condition decides nothing. Point the arms at different steps, or replace the branch with a local step.`,
3762
3784
  impl.id,
3763
3785
  isDraftCtx
3764
3786
  );
3765
3787
  }
3766
3788
  }
3767
3789
  if (s.type === "switch" && s.cases?.length) {
3768
- const targets = new Set(s.cases.map((c) => c.step));
3769
- const def = s.defaultStep ?? graph.nextOf(s.stepNumber);
3770
- if (def !== void 0) targets.add(def);
3771
- if (targets.size === 1) {
3790
+ const targets = decisionTargets(s.stepNumber, s.cases.map((c) => c.step), s.defaultStep);
3791
+ if (targets.length === 1) {
3772
3792
  ctx.addIssue(
3773
3793
  "warning",
3774
3794
  "MEANINGLESS_BRANCH",
3775
- `${where}switch step ${s.stepNumber} sends every case (and the default) to step ${[...targets][0]} \u2014 the dispatch decides nothing.`,
3795
+ `${where}switch step ${s.stepNumber} sends every case (and the default) to step ${targets[0]} \u2014 the dispatch decides nothing.`,
3776
3796
  impl.id,
3777
3797
  isDraftCtx
3778
3798
  );
@@ -3845,8 +3865,8 @@ var init_narrative_antipatterns = __esm({
3845
3865
  if (!isCycle) continue;
3846
3866
  const memberEdges = keys.flatMap((k) => (adjacency.get(k) ?? []).filter((e) => inScc.has(e.toKey)));
3847
3867
  if (memberEdges.length === 0) continue;
3848
- const anchor = [...memberEdges].sort((a, b) => a.fromKey.localeCompare(b.fromKey))[0];
3849
- const path27 = [...keys].sort().join(" \u2192 ");
3868
+ const anchor = [...memberEdges].sort((a, b) => byCodeUnit(a.fromKey, b.fromKey) || byCodeUnit(a.impl.id, b.impl.id) || a.stepNumber - b.stepNumber)[0];
3869
+ const path27 = [...keys].sort(byCodeUnit).join(" \u2192 ");
3850
3870
  ctx.addIssue(
3851
3871
  "warning",
3852
3872
  "UNCONDITIONAL_CALL_CYCLE",
@@ -4098,14 +4118,15 @@ var init_portal_endpoints = __esm({
4098
4118
  continue;
4099
4119
  }
4100
4120
  for (const intf of compInterfaces) {
4121
+ const isIntfDraft = intf.status === "draft" || intf.status === "design";
4101
4122
  for (const m of intf.methods) {
4102
4123
  if (m.endpoint) {
4103
4124
  ctx.addIssue(
4104
4125
  "error",
4105
4126
  "ARCHITECTURE_VIOLATION_NON_PORTAL_ENDPOINT",
4106
4127
  `Architectural violation: Component "${comp.id}" is a ${comp.componentType}, but method "${m.name}" on its interface "${intf.id}" declares an endpoint. Only Portal components may carry endpoints.`,
4107
- comp.id,
4108
- isDraftCtx
4128
+ intf.id,
4129
+ isDraftCtx || isIntfDraft
4109
4130
  );
4110
4131
  }
4111
4132
  }
@@ -4236,7 +4257,7 @@ var init_stereotype_dependencies = __esm({
4236
4257
  { code: "ARCHITECTURE_VIOLATION_ADAPTER_DEP", defaultSeverity: "error", summary: "Adapter depending on Orchestrators or Stores" },
4237
4258
  { code: "ARCHITECTURE_VIOLATION_INDEX_DEP", defaultSeverity: "error", summary: "Index depending on anything but its Store or an Adapter" },
4238
4259
  { code: "ARCHITECTURE_VIOLATION_VIEW_DEP", defaultSeverity: "error", summary: "View depending on logic/persistence layers" },
4239
- { code: "PORTAL_WRITE_SHORTCUT", defaultSeverity: "error", summary: "Portal narrative calls a write-effect method on a Repository/Index directly \u2014 reads may shortcut, writes route through an Orchestrator (judged on effect-tagged facade methods; untagged methods are not yet judged)" }
4260
+ { code: "PORTAL_WRITE_SHORTCUT", defaultSeverity: "error", summary: "Portal narrative call or dispatch-table binding reaches a write-effect method on a Repository/Index directly \u2014 reads may shortcut, writes route through an Orchestrator (judged on effect-tagged facade methods; untagged methods are not yet judged)" }
4240
4261
  ],
4241
4262
  check(ctx) {
4242
4263
  for (const comp of ctx.components) {
@@ -4308,10 +4329,11 @@ var init_stereotype_dependencies = __esm({
4308
4329
  crossDraft
4309
4330
  );
4310
4331
  } else if (depComp.componentType !== "Portal" && depComp.componentType !== "Gateway") {
4332
+ const crosser = comp.componentType === "Adapter" ? "client Adapter" : comp.componentType;
4311
4333
  ctx.addIssue(
4312
4334
  "error",
4313
4335
  "CROSS_SUBSYSTEM_TARGET_NON_PORTAL",
4314
- `Boundary violation: client Adapter "${comp.id}" enters subsystem "${depComp.subsystem}" through "${depComp.id}" (${depComp.componentType}), not its inbound Portal. A cross-subsystem hop must target the remote subsystem's Portal (its front door), which dispatches inward \u2014 publishing/depending on an internal ${depComp.componentType} leaks the boundary and breaks the distribution seam. Expose a Portal for "${depComp.subsystem}" and point this Adapter at it.`,
4336
+ `Boundary violation: ${crosser} "${comp.id}" enters subsystem "${depComp.subsystem}" through "${depComp.id}" (${depComp.componentType}), not its inbound Portal. A cross-subsystem hop must target the remote subsystem's Portal (its front door), which dispatches inward \u2014 publishing/depending on an internal ${depComp.componentType} leaks the boundary and breaks the distribution seam. Expose a Portal for "${depComp.subsystem}" and point "${comp.id}" at it.`,
4315
4337
  comp.id,
4316
4338
  crossDraft
4317
4339
  );
@@ -4435,6 +4457,23 @@ var init_stereotype_dependencies = __esm({
4435
4457
  }
4436
4458
  }
4437
4459
  }
4460
+ for (const comp of ctx.components) {
4461
+ if (comp.componentType !== "Portal" || !comp.dispatch || comp.dispatch.length === 0) continue;
4462
+ const isDraftCtx = ctx.isComponentDraft(comp.id);
4463
+ for (const binding of comp.dispatch) {
4464
+ const target = ctx.componentMap.get(binding.component);
4465
+ if (!target || target.componentType !== "Repository" && target.componentType !== "Index") continue;
4466
+ const targetMethod = ctx.interfaceMethodsOf(target.id).find((m) => m.name === binding.method);
4467
+ if (targetMethod?.effect !== "write") continue;
4468
+ ctx.addIssue(
4469
+ "error",
4470
+ "PORTAL_WRITE_SHORTCUT",
4471
+ `Portal "${comp.id}": dispatch binding "${binding.capability}" routes to write-effect method ${target.id}.${binding.method} directly. The Portal\u2192${target.componentType} shortcut is licensed for READS only \u2014 route the write through an Orchestrator that owns the workflow.`,
4472
+ comp.id,
4473
+ isDraftCtx || ctx.isComponentDraft(target.id)
4474
+ );
4475
+ }
4476
+ }
4438
4477
  }
4439
4478
  };
4440
4479
  }
@@ -4458,7 +4497,7 @@ var init_pattern_ownership = __esm({
4458
4497
  { code: "REPOSITORY_CONTAINMENT", defaultSeverity: "error", summary: "Repository owning a non Store/Registry/Index/Adapter member" },
4459
4498
  { code: "GATEWAY_CONTAINMENT", defaultSeverity: "error", summary: "Gateway owning a non Portal/Orchestrator/Specialist member" },
4460
4499
  { code: "FEATURE_COMPONENT_CONTAINMENT", defaultSeverity: "error", summary: "FeatureComponent not owning exactly one Orchestrator + one or more Views" },
4461
- { code: "ROUTER_COMPONENT_CONTAINMENT", defaultSeverity: "error", summary: "RouterComponent missing its Portal facade or children" },
4500
+ { code: "ROUTER_COMPONENT_CONTAINMENT", defaultSeverity: "error", summary: "RouterComponent not owning exactly one Portal facade, or owning no children to route to" },
4462
4501
  { code: "VISIBILITY_VIOLATION", defaultSeverity: "error", summary: "Dependency on a block privately owned by another pattern" },
4463
4502
  { code: "UNOWNED_STORE", defaultSeverity: "warning", summary: "Store not owned by any pattern \u2014 recommended shape is a Repository; a deliberate standalone Store needs a lint.allow" },
4464
4503
  { code: "REGISTRY_WITHOUT_STORE", defaultSeverity: "warning", summary: "Standalone Registry with no Store to write to \u2014 either mistyped (a fused file-backed store belongs typed Store) or orphaned" }
@@ -4480,14 +4519,15 @@ var init_pattern_ownership = __esm({
4480
4519
  ctx.addIssue("error", "INVALID_OWNED_MEMBER", `Component "${comp.id}" owns "${memberId}" which does not exist.`, comp.id, isDraftCtx);
4481
4520
  continue;
4482
4521
  }
4522
+ if (!pattern) continue;
4483
4523
  if (isPattern(member)) {
4484
4524
  ctx.addIssue("error", "PATTERN_OWNS_PATTERN", `Pattern "${comp.id}" owns "${memberId}", which is itself a pattern. Patterns own only building blocks \u2014 compose patterns at the subsystem (L1) level.`, comp.id, isDraftCtx);
4485
4525
  }
4486
- const prev = ownedBy.get(memberId);
4487
- if (prev && prev !== comp.id) {
4488
- ctx.addIssue("error", "SHARED_OWNED_MEMBER", `Block "${memberId}" is owned by both "${prev}" and "${comp.id}"; a block has exactly one owner.`, comp.id, isDraftCtx);
4526
+ const firstOwner = ownedBy.get(memberId);
4527
+ if (firstOwner && firstOwner !== comp.id) {
4528
+ ctx.addIssue("error", "SHARED_OWNED_MEMBER", `Block "${memberId}" is owned by both "${firstOwner}" and "${comp.id}"; a block has exactly one owner.`, comp.id, isDraftCtx);
4489
4529
  }
4490
- ownedBy.set(memberId, comp.id);
4530
+ if (!firstOwner) ownedBy.set(memberId, comp.id);
4491
4531
  }
4492
4532
  if (comp.componentType === "Repository") {
4493
4533
  const allowed = /* @__PURE__ */ new Set(["Store", "Registry", "Index", "Adapter"]);
@@ -4522,14 +4562,14 @@ var init_pattern_ownership = __esm({
4522
4562
  }
4523
4563
  }
4524
4564
  if (comp.componentType === "RouterComponent") {
4525
- let hasPortal = false;
4565
+ let portals = 0;
4526
4566
  let hasChildren = false;
4527
4567
  for (const memberId of comp.owns) {
4528
4568
  const t = ctx.componentMap.get(memberId)?.componentType;
4529
- if (t === "Portal") hasPortal = true;
4569
+ if (t === "Portal") portals++;
4530
4570
  else if (t) hasChildren = true;
4531
4571
  }
4532
- if (!hasPortal) {
4572
+ if (portals !== 1) {
4533
4573
  ctx.addIssue("error", "ROUTER_COMPONENT_CONTAINMENT", `RouterComponent "${comp.id}" must own exactly one Portal component to act as its facade.`, comp.id, isDraftCtx);
4534
4574
  }
4535
4575
  if (!hasChildren) {
@@ -5031,54 +5071,43 @@ var init_dependency_cycles = __esm({
5031
5071
  "use strict";
5032
5072
  cyclesRule = {
5033
5073
  name: "dependency-cycles",
5034
- description: "The component dependsOn graph must be a DAG; the first detected cycle is reported with its full path.",
5074
+ description: "The component dependsOn graph must be a DAG; the first cycle through a component in the run's scope is reported with its full path.",
5035
5075
  codes: [
5036
5076
  { code: "CIRCULAR_DEPENDENCY", defaultSeverity: "error", summary: "Circular dependency between components" }
5037
5077
  ],
5038
5078
  check(ctx) {
5039
- const visited = /* @__PURE__ */ new Set();
5040
- const recStack = /* @__PURE__ */ new Set();
5041
- const dfs = (compId, pathTrace) => {
5042
- visited.add(compId);
5043
- recStack.add(compId);
5044
- pathTrace.push(compId);
5045
- const comp = ctx.componentMap.get(compId);
5046
- if (comp) {
5047
- for (const depId of comp.dependsOn) {
5048
- if (!visited.has(depId)) {
5049
- if (dfs(depId, pathTrace)) {
5050
- recStack.delete(compId);
5051
- pathTrace.pop();
5052
- return true;
5053
- }
5054
- } else if (recStack.has(depId)) {
5079
+ const cycleFrom = (startId) => {
5080
+ const visited = /* @__PURE__ */ new Set([startId]);
5081
+ const pathTrace = [startId];
5082
+ const search = (compId) => {
5083
+ for (const depId of ctx.componentMap.get(compId)?.dependsOn ?? []) {
5084
+ if (depId === startId) {
5055
5085
  pathTrace.push(depId);
5056
- const cyclePath = pathTrace.slice(pathTrace.indexOf(depId)).join(" -> ");
5057
- const isDraftCtx = ctx.isComponentDraft(compId) || ctx.isComponentDraft(depId);
5058
- ctx.addIssue(
5059
- "error",
5060
- "CIRCULAR_DEPENDENCY",
5061
- `Circular dependency detected: ${cyclePath}`,
5062
- compId,
5063
- isDraftCtx
5064
- );
5065
- pathTrace.pop();
5066
- recStack.delete(compId);
5067
- pathTrace.pop();
5068
5086
  return true;
5069
5087
  }
5088
+ if (visited.has(depId)) continue;
5089
+ visited.add(depId);
5090
+ pathTrace.push(depId);
5091
+ if (search(depId)) return true;
5092
+ pathTrace.pop();
5070
5093
  }
5071
- }
5072
- recStack.delete(compId);
5073
- pathTrace.pop();
5074
- return false;
5094
+ return false;
5095
+ };
5096
+ return search(startId) ? pathTrace : void 0;
5075
5097
  };
5076
5098
  for (const comp of ctx.components) {
5077
- if (!visited.has(comp.id)) {
5078
- if (dfs(comp.id, [])) {
5079
- break;
5080
- }
5081
- }
5099
+ if (!ctx.isSpecInScope(comp.id)) continue;
5100
+ const cycle = cycleFrom(comp.id);
5101
+ if (!cycle) continue;
5102
+ const closing = cycle[cycle.length - 2];
5103
+ ctx.addIssue(
5104
+ "error",
5105
+ "CIRCULAR_DEPENDENCY",
5106
+ `Circular dependency detected: ${cycle.join(" -> ")}`,
5107
+ comp.id,
5108
+ ctx.isComponentDraft(comp.id) || ctx.isComponentDraft(closing)
5109
+ );
5110
+ return;
5082
5111
  }
5083
5112
  }
5084
5113
  };
@@ -5207,19 +5236,18 @@ var init_dispatch_tables = __esm({
5207
5236
  );
5208
5237
  continue;
5209
5238
  }
5210
- if (step.assertsGuarantees?.length) {
5211
- const boundMethod = ctx.interfaceMethodsOf(binding.component).find((m) => m.name === binding.method);
5212
- const declared = new Set(boundMethod?.guarantees ?? []);
5213
- for (const g of step.assertsGuarantees) {
5214
- if (!declared.has(g)) {
5215
- ctx.addIssue(
5216
- "warning",
5217
- "NARRATIVE_SEMANTIC_UNBACKED",
5218
- `${where} asserts guarantee "${g}", but capability "${step.capability}" resolves to "${binding.component}.${binding.method}", which does not list "${g}" among its L3 contract guarantees. Declare it there (and ensure its shape can deliver it), or revise the narrative.`,
5219
- impl.id,
5220
- isDraftCtx || ctx.isComponentDraft(binding.component)
5221
- );
5222
- }
5239
+ const boundMethod = ctx.interfaceMethodsOf(binding.component).find((m) => m.name === binding.method);
5240
+ if (!boundMethod) continue;
5241
+ const declared = new Set(boundMethod.guarantees ?? []);
5242
+ for (const g of step.assertsGuarantees ?? []) {
5243
+ if (!declared.has(g)) {
5244
+ ctx.addIssue(
5245
+ "warning",
5246
+ "NARRATIVE_SEMANTIC_UNBACKED",
5247
+ `${where} asserts guarantee "${g}", but capability "${step.capability}" resolves to "${binding.component}.${binding.method}", which does not list "${g}" among its L3 contract guarantees. Declare it there (and ensure its shape can deliver it), or revise the narrative.`,
5248
+ impl.id,
5249
+ isDraftCtx || ctx.isComponentDraft(binding.component)
5250
+ );
5223
5251
  }
5224
5252
  }
5225
5253
  }
@@ -5424,12 +5452,11 @@ var init_unused_detection = __esm({
5424
5452
  const invokedBySeeds = [];
5425
5453
  for (const intf of ctx.interfaces) {
5426
5454
  if (!ctx.componentMap.has(intf.component)) continue;
5427
- const comp = ctx.componentMap.get(intf.component);
5428
5455
  for (const m of intf.methods) {
5429
5456
  if (!m.invokedBy) continue;
5430
5457
  invokedBySeeds.push({ compId: intf.component, methodName: m.name });
5431
5458
  if (!ctx.isSpecInScope(intf.id)) continue;
5432
- const isDraftCtx = comp.status === "draft" || comp.status === "design" || intf.status === "draft" || intf.status === "design";
5459
+ const isDraftCtx = ctx.isComponentDraft(intf.component) || intf.status === "draft" || intf.status === "design";
5433
5460
  if (!passesIntentFloor(m.invokedBy.caller, m.name)) {
5434
5461
  ctx.addIssue(
5435
5462
  "warning",
@@ -5454,7 +5481,7 @@ var init_unused_detection = __esm({
5454
5481
  for (const comp of ctx.components) {
5455
5482
  if (!ctx.isSpecInScope(comp.id)) continue;
5456
5483
  if (!reach.reachesComponent(comp.id)) {
5457
- const isDraftCtx = comp.status === "draft" || comp.status === "design";
5484
+ const isDraftCtx = ctx.isComponentDraft(comp.id);
5458
5485
  ctx.addIssue(
5459
5486
  "warning",
5460
5487
  "UNUSED_COMPONENT",
@@ -5466,12 +5493,12 @@ var init_unused_detection = __esm({
5466
5493
  for (const intf of ctx.interfacesByComponent.get(comp.id) ?? []) {
5467
5494
  for (const m of intf.methods) {
5468
5495
  if (!reach.reachesMethod(comp.id, m.name)) {
5469
- const isDraftCtx = comp.status === "draft" || comp.status === "design" || intf.status === "draft" || intf.status === "design";
5496
+ const isDraftCtx = ctx.isComponentDraft(comp.id) || intf.status === "draft" || intf.status === "design";
5470
5497
  ctx.addIssue(
5471
5498
  "warning",
5472
5499
  "UNUSED_METHOD",
5473
5500
  `Method "${m.name}" on component "${comp.id}" is defined but never called by any narrative step.`,
5474
- comp.id,
5501
+ intf.id,
5475
5502
  isDraftCtx
5476
5503
  );
5477
5504
  }
@@ -5582,20 +5609,20 @@ var init_durability_round_trip = __esm({
5582
5609
  });
5583
5610
 
5584
5611
  // src/core/rules/wiring/untyped-seams.ts
5585
- function unwrapPromise(typeRef) {
5586
- const m = /^promise\s*<(.+)>$/i.exec(typeRef.trim());
5587
- return (m ? m[1] : typeRef).trim();
5612
+ function namesBareType(refs) {
5613
+ return refs.some((ref) => BARE_SEAM_TYPES.has(ref.toLowerCase()));
5588
5614
  }
5589
5615
  var BARE_SEAM_TYPES, untypedSeamRule;
5590
5616
  var init_untyped_seams = __esm({
5591
5617
  "src/core/rules/wiring/untyped-seams.ts"() {
5592
5618
  "use strict";
5619
+ init_models();
5593
5620
  BARE_SEAM_TYPES = /* @__PURE__ */ new Set(["json", "any", "unknown", "object"]);
5594
5621
  untypedSeamRule = {
5595
5622
  name: "untyped-seams",
5596
- description: "Methods on a subsystem's published components (its public surface) should not take or return bare Json/any/unknown \u2014 cross-subsystem contracts are the swap seam and must be typed. Generic-dispatch portals carry per-capability types via their dispatch table instead.",
5623
+ description: "Methods on a subsystem's published components (its public surface) should not take or return bare Json/any/unknown/object, judged through each method's type references so a prose signature is judged like structured params: cross-subsystem contracts are the swap seam and must be typed. Generic-dispatch portals carry per-capability types via their dispatch table instead.",
5597
5624
  codes: [
5598
- { code: "UNTYPED_SEAM", defaultSeverity: "warning", summary: "Bare Json/any/unknown parameter or return crossing a subsystem public surface" }
5625
+ { code: "UNTYPED_SEAM", defaultSeverity: "warning", summary: "Bare Json/any/unknown/object parameter or return crossing a subsystem public surface" }
5599
5626
  ],
5600
5627
  check(ctx) {
5601
5628
  for (const sub of ctx.subsystems) {
@@ -5609,14 +5636,17 @@ var init_untyped_seams = __esm({
5609
5636
  const isDraftCtx = ctx.isComponentDraft(compId) || intf.status === "draft" || intf.status === "design";
5610
5637
  for (const m of intf.methods) {
5611
5638
  const offenders = [];
5612
- for (const p of m.params ?? []) {
5613
- if (BARE_SEAM_TYPES.has(unwrapPromise(p.type).toLowerCase())) {
5614
- offenders.push(`param "${p.name}: ${p.type}"`);
5639
+ if (m.params && m.params.length > 0) {
5640
+ for (const p of m.params) {
5641
+ if (namesBareType(extractTypeIdentifiers(p.type))) {
5642
+ offenders.push(`param "${p.name}: ${p.type}"`);
5643
+ }
5615
5644
  }
5616
- }
5617
- const ret = unwrapPromise(m.returns ?? "");
5618
- if (BARE_SEAM_TYPES.has(ret.toLowerCase())) {
5619
- offenders.push(`return "${m.returns}"`);
5645
+ if (namesBareType(extractTypeIdentifiers(m.returns ?? ""))) {
5646
+ offenders.push(`return "${m.returns}"`);
5647
+ }
5648
+ } else if (namesBareType(methodTypeRefs(m))) {
5649
+ offenders.push(`signature "${m.signature}"`);
5620
5650
  }
5621
5651
  if (offenders.length) {
5622
5652
  ctx.addIssue(
@@ -5641,15 +5671,19 @@ function componentOfImpl(ctx, implContract) {
5641
5671
  const contract = ctx.interfaceMap.get(implContract);
5642
5672
  return contract ? ctx.componentMap.get(contract.component) : void 0;
5643
5673
  }
5644
- var DATA_STEREOTYPES, CLAIM_PHRASES, proseClaimRule;
5674
+ function withoutQuotedText(text) {
5675
+ return text.replace(QUOTED_SPAN, " ");
5676
+ }
5677
+ var DATA_STEREOTYPES, CLAIM_PHRASES, QUOTED_SPAN, proseClaimRule;
5645
5678
  var init_prose_claims = __esm({
5646
5679
  "src/core/rules/wiring/prose-claims.ts"() {
5647
5680
  "use strict";
5648
5681
  DATA_STEREOTYPES = /* @__PURE__ */ new Set(["Store", "Registry", "Index", "Adapter", "Repository"]);
5649
- CLAIM_PHRASES = /\b(persist(s|ed|ent)?|survives?\s+(a\s+)?restart|writ(es?|ten)\s+to\s+disk|registered\s+into|durabl[ey])\b/i;
5682
+ CLAIM_PHRASES = /\b(persist(s|ed|ent|ing|ence)?|survives?\s+(a\s+)?restart|writ(es?|ten)\s+to\s+disk|registered\s+into|durabl[ey])\b/i;
5683
+ QUOTED_SPAN = /"[^"]*"|“[^”]*”|`[^`]*`|(?<![\p{L}\p{N}])['‘](?:[^'‘’]|(?<=[\p{L}\p{N}])['’](?=[\p{L}\p{N}]))*['’](?![\p{L}\p{N}])/gu;
5650
5684
  proseClaimRule = {
5651
5685
  name: "prose-claims",
5652
- description: 'Flags durability/side-effect claims that exist only in prose: a local step description or an intent paragraph claiming persistence ("persisted", "survives restart", "registered into") on a logic component whose narrative has no call/dispatch edge to any data-layer component (Store/Registry/Index/Adapter/Repository). Data-layer components are exempt \u2014 they ARE the persistence.',
5686
+ description: 'Flags durability/side-effect claims that exist only in prose: a local step description or an intent paragraph claiming persistence ("persisted", "persistence", "survives restart", "registered into") on a logic component whose narrative has no call, register or dispatch edge to any data-layer component (Store/Registry/Index/Adapter/Repository). Text inside quotes or backticks names a value or quotes a message and claims nothing. Data-layer components are exempt \u2014 they ARE the persistence.',
5653
5687
  codes: [
5654
5688
  { code: "UNREALIZED_CLAIM", defaultSeverity: "warning", summary: "Durability/side-effect claim in prose with no matching structural edge" }
5655
5689
  ],
@@ -5660,11 +5694,11 @@ var init_prose_claims = __esm({
5660
5694
  if (DATA_STEREOTYPES.has(comp.componentType)) continue;
5661
5695
  const isDraftCtx = ctx.isImplementationDraft(impl);
5662
5696
  for (const implMethod of impl.methods) {
5663
- const stepClaims = implMethod.narrative.filter((step) => step.type === "local").map((step) => ({ step, claim: CLAIM_PHRASES.exec(step.description) })).filter((c) => c.claim !== null);
5664
- const intentClaim = implMethod.intent ? CLAIM_PHRASES.exec(implMethod.intent) : null;
5697
+ const stepClaims = implMethod.narrative.filter((step) => step.type === "local").map((step) => ({ step, claim: CLAIM_PHRASES.exec(withoutQuotedText(step.description)) })).filter((c) => c.claim !== null);
5698
+ const intentClaim = implMethod.intent ? CLAIM_PHRASES.exec(withoutQuotedText(implMethod.intent)) : null;
5665
5699
  if (!stepClaims.length && !intentClaim) continue;
5666
5700
  const hasDataEdge = implMethod.narrative.some((step) => {
5667
- if (step.type !== "call" && step.type !== "dispatch") return false;
5701
+ if (step.type !== "call" && step.type !== "register" && step.type !== "dispatch") return false;
5668
5702
  if (!step.targetComponent) return false;
5669
5703
  const target = ctx.componentMap.get(step.targetComponent);
5670
5704
  if (target && DATA_STEREOTYPES.has(target.componentType)) return true;
@@ -5677,7 +5711,7 @@ var init_prose_claims = __esm({
5677
5711
  ctx.addIssue(
5678
5712
  "warning",
5679
5713
  "UNREALIZED_CLAIM",
5680
- `Step ${step.stepNumber} of "${implMethod.name}" in implementation "${impl.id}" claims "${claim[0]}" but no call/dispatch edge in this narrative reaches a Store/Registry/Index/Adapter \u2014 realize the claim as a structural edge (and durability tags), or reword the prose.`,
5714
+ `Step ${step.stepNumber} of "${implMethod.name}" in implementation "${impl.id}" claims "${claim[0]}" but no call/register/dispatch edge in this narrative reaches a Store/Registry/Index/Adapter \u2014 realize the claim as a structural edge (and durability tags), or reword the prose.`,
5681
5715
  impl.id,
5682
5716
  isDraftCtx
5683
5717
  );
@@ -5736,6 +5770,10 @@ function stepAsserts(impl, methodName, type, invariantId) {
5736
5770
  (step) => (step.assertsInvariants ?? []).some((ref) => refMatchesInvariant(ref, type, invariantId))
5737
5771
  );
5738
5772
  }
5773
+ function isEntityDraft(t, ctx) {
5774
+ const sub = t.subsystem ? ctx.subsystems.find((s) => s.id === t.subsystem) : void 0;
5775
+ return sub !== void 0 && isDraftSubsystem(sub);
5776
+ }
5739
5777
  function resolveComponentClass(t, ctx) {
5740
5778
  if (!t.componentClass) return void 0;
5741
5779
  const direct = ctx.componentMap.get(t.componentClass);
@@ -5762,6 +5800,7 @@ var init_invariant_backing = __esm({
5762
5800
  for (const t of ctx.types) {
5763
5801
  const invariants = t.invariants ?? [];
5764
5802
  if (invariants.length === 0) continue;
5803
+ const entityDraft = isEntityDraft(t, ctx);
5765
5804
  const seen = /* @__PURE__ */ new Set();
5766
5805
  for (const inv of invariants) {
5767
5806
  if (seen.has(inv.id)) {
@@ -5769,7 +5808,8 @@ var init_invariant_backing = __esm({
5769
5808
  "error",
5770
5809
  "DUPLICATE_INVARIANT_ID",
5771
5810
  `Entity "${t.id}" declares invariant id "${inv.id}" more than once \u2014 invariant ids must be unique within the entity.`,
5772
- t.id
5811
+ t.id,
5812
+ entityDraft
5773
5813
  );
5774
5814
  }
5775
5815
  seen.add(inv.id);
@@ -5780,7 +5820,8 @@ var init_invariant_backing = __esm({
5780
5820
  "warning",
5781
5821
  "INVARIANT_UNANCHORED",
5782
5822
  `Entity "${t.id}" declares ${invariants.length} invariant(s) but ${t.componentClass ? `its componentClass "${t.componentClass}" does not resolve to a component` : "has no componentClass"} \u2014 without an owning component there is no write path to hold the invariant against. Link the lifecycle owner via componentClass.`,
5783
- t.id
5823
+ t.id,
5824
+ entityDraft
5784
5825
  );
5785
5826
  continue;
5786
5827
  }
@@ -5794,13 +5835,13 @@ var init_invariant_backing = __esm({
5794
5835
  "INVARIANT_UNANCHORED",
5795
5836
  `Entity "${t.id}" declares ${invariants.length} invariant(s) anchored to "${comp.id}", but none of that component's contract methods declare effect: write \u2014 the validator cannot identify the write paths that must assert them. Tag the mutating methods with effect: write.`,
5796
5837
  t.id,
5797
- ctx.isComponentDraft(comp.id)
5838
+ entityDraft || ctx.isComponentDraft(comp.id)
5798
5839
  );
5799
5840
  continue;
5800
5841
  }
5801
5842
  for (const { intf, method } of writeMethods) {
5802
5843
  for (const impl of ctx.implementationsByContract.get(intf.id) ?? []) {
5803
- const isDraftCtx = ctx.isImplementationDraft(impl);
5844
+ const isDraftCtx = entityDraft || ctx.isImplementationDraft(impl);
5804
5845
  for (const inv of invariants) {
5805
5846
  if (stepAsserts(impl, method.name, t, inv.id)) continue;
5806
5847
  ctx.addIssue(
@@ -5838,30 +5879,35 @@ var init_invariant_backing = __esm({
5838
5879
 
5839
5880
  // src/core/rules/wiring/event-topology.ts
5840
5881
  function collectEnds(ctx) {
5841
- const emitters = [];
5842
- const subscribers = [];
5882
+ const emitters = /* @__PURE__ */ new Map();
5883
+ const subscribers = /* @__PURE__ */ new Map();
5884
+ const addEnd = (ends, topic, compId, via) => {
5885
+ const key = `${compId}#${topic}`;
5886
+ const end = ends.get(key);
5887
+ if (!end) ends.set(key, { topic, compId, vias: [via] });
5888
+ else if (!end.vias.includes(via)) end.vias.push(via);
5889
+ };
5843
5890
  for (const comp of ctx.components) {
5844
5891
  for (const e of comp.emits ?? []) {
5845
- emitters.push({ topic: e.topic, compId: comp.id, via: "emits declaration" });
5892
+ addEnd(emitters, e.topic, comp.id, "emits declaration");
5846
5893
  }
5847
5894
  for (const s of comp.subscribesTo ?? []) {
5848
- subscribers.push({ topic: s.topic, compId: comp.id, via: "subscribesTo declaration" });
5895
+ addEnd(subscribers, s.topic, comp.id, "subscribesTo declaration");
5849
5896
  }
5850
5897
  }
5851
5898
  for (const intf of ctx.interfaces) {
5852
5899
  for (const method of intf.methods) {
5853
5900
  const ep = method.endpoint;
5854
5901
  if (!ep || ep.transport !== "MessageBus") continue;
5855
- const end = {
5856
- topic: ep.topic,
5857
- compId: intf.component,
5858
- via: `MessageBus endpoint on ${intf.id}.${method.name}`
5859
- };
5860
- if (ep.direction === "publish") emitters.push(end);
5861
- else subscribers.push(end);
5902
+ addEnd(
5903
+ ep.direction === "publish" ? emitters : subscribers,
5904
+ ep.topic,
5905
+ intf.component,
5906
+ `MessageBus endpoint on ${intf.id}.${method.name}`
5907
+ );
5862
5908
  }
5863
5909
  }
5864
- return { emitters, subscribers };
5910
+ return { emitters: [...emitters.values()], subscribers: [...subscribers.values()] };
5865
5911
  }
5866
5912
  var eventTopologyRule;
5867
5913
  var init_event_topology = __esm({
@@ -5869,7 +5915,7 @@ var init_event_topology = __esm({
5869
5915
  "use strict";
5870
5916
  eventTopologyRule = {
5871
5917
  name: "event-topology",
5872
- description: "Bipartite completeness of the declared pub/sub graph: every topic a component emits (emits declarations, MessageBus publish endpoints) must have at least one subscriber (subscribesTo declarations, MessageBus subscribe endpoints), and every subscription must have at least one source. Pairing is by exact topic name. Trees that declare no event edges see nothing \u2014 the rule costs request/response systems zero noise. Warnings + lint.allow: a topic produced for (or consumed from) an EXTERNAL system is a legitimate, declarable exception.",
5918
+ description: "Bipartite completeness of the declared pub/sub graph: every topic a component emits (emits declarations, MessageBus publish endpoints) must have at least one subscriber (subscribesTo declarations, MessageBus subscribe endpoints), and every subscription must have at least one source. Pairing is by exact topic name, and a topic is reported once per component however many declarations bind it there. Trees that declare no event edges see nothing \u2014 the rule costs request/response systems zero noise. Warnings + lint.allow: a topic produced for (or consumed from) an EXTERNAL system is a legitimate, declarable exception.",
5873
5919
  codes: [
5874
5920
  { code: "UNCONSUMED_TOPIC", defaultSeverity: "warning", summary: "Topic is emitted but nothing in the tree subscribes to it" },
5875
5921
  { code: "UNSOURCED_SUBSCRIPTION", defaultSeverity: "warning", summary: "Topic is subscribed to but nothing in the tree emits it" }
@@ -5884,7 +5930,7 @@ var init_event_topology = __esm({
5884
5930
  ctx.addIssue(
5885
5931
  "warning",
5886
5932
  "UNCONSUMED_TOPIC",
5887
- `Component "${e.compId}" emits topic "${e.topic}" (${e.via}), but nothing in this tree subscribes to it \u2014 the event goes nowhere. Wire a subscriber (subscribesTo, or a MessageBus subscribe endpoint), fix the topic name, or lint.allow with the external consumer named.`,
5933
+ `Component "${e.compId}" emits topic "${e.topic}" (${e.vias.join(", ")}), but nothing in this tree subscribes to it \u2014 the event goes nowhere. Wire a subscriber (subscribesTo, or a MessageBus subscribe endpoint), fix the topic name, or lint.allow with the external consumer named.`,
5888
5934
  e.compId,
5889
5935
  ctx.isComponentDraft(e.compId)
5890
5936
  );
@@ -5894,7 +5940,7 @@ var init_event_topology = __esm({
5894
5940
  ctx.addIssue(
5895
5941
  "warning",
5896
5942
  "UNSOURCED_SUBSCRIPTION",
5897
- `Component "${s.compId}" subscribes to topic "${s.topic}" (${s.via}), but nothing in this tree emits it \u2014 the handler can never fire from inside this system. Wire the emitter (emits, or a MessageBus publish endpoint), fix the topic name, or lint.allow with the external source named.`,
5943
+ `Component "${s.compId}" subscribes to topic "${s.topic}" (${s.vias.join(", ")}), but nothing in this tree emits it \u2014 the handler can never fire from inside this system. Wire the emitter (emits, or a MessageBus publish endpoint), fix the topic name, or lint.allow with the external source named.`,
5898
5944
  s.compId,
5899
5945
  ctx.isComponentDraft(s.compId)
5900
5946
  );
@@ -5913,13 +5959,13 @@ var init_structural_conformance = __esm({
5913
5959
  quoteList = (names) => names.map((n) => `"${n}"`).join(", ");
5914
5960
  structuralConformanceRule = {
5915
5961
  name: "structural-conformance",
5916
- description: "Code\u2194spec Level 1: every source file an implementation names \u2014 its own sourcePath and each method's \u2014 must resolve to a real file inside the project root, and every L3 contract method must be realized in its own source file (the method's sourcePath, else the implementation's) at its conformance tier (declared | anchored | off; Portals default to anchored, everything else to declared; per-method `symbol` maps intent-language names to code names), and every finding code a contract method declares must appear as a string literal in that file (UNREALIZED_FINDING). A file that escapes the root, is missing or cannot be read is reported once and blocks only the methods realized in it. Findings carry the analysis grade (exact AST | pattern table | generic scan) so weaker analysis is visible. Implementations under chained subsystems (projectPath) validate standalone in their own project run and are skipped here.",
5962
+ description: "Code\u2194spec Level 1: every source file an implementation names \u2014 its own sourcePath and each method's \u2014 must resolve to a real file inside the project root, and every L3 contract method must be realized in its own source file (the method's sourcePath, else the implementation's) at its conformance tier (declared | anchored | off; Portals default to anchored, everything else to declared; per-method `symbol` maps intent-language names to code names), and every finding code a contract method declares must be anchored in that file \u2014 as a string literal or, at exact grade, a property-access name (UNREALIZED_FINDING). A file that escapes the root, is missing or cannot be read is reported once and blocks only the methods realized in it. Findings carry the analysis grade (exact AST | pattern table | generic scan) so weaker analysis is visible. Implementations under chained subsystems (projectPath) validate standalone in their own project run and are skipped here.",
5917
5963
  codes: [
5918
5964
  { code: "MISSING_SOURCE_PATH", defaultSeverity: "warning", summary: "An implementation names no source file at all, or a contract method is left without one \u2014 structural conformance cannot link it to code" },
5919
5965
  { code: "MISSING_SOURCE_FILE", defaultSeverity: "error", summary: "A source file an implementation or one of its methods names does not resolve to a file on disk" },
5920
5966
  { code: "SOURCE_PATH_ESCAPES_ROOT", defaultSeverity: "error", summary: "A source file an implementation or one of its methods names is absolute or escapes the project root (containment refusal)" },
5921
5967
  { code: "UNREALIZED_METHOD", defaultSeverity: "warning", summary: "An L3 contract method has no anchor in its own source file (the method's sourcePath, else the implementation's) at the required conformance tier" },
5922
- { code: "UNREALIZED_FINDING", defaultSeverity: "warning", summary: "A finding code a contract method declares does not appear as a string literal in the method's source file" },
5968
+ { code: "UNREALIZED_FINDING", defaultSeverity: "warning", summary: "A finding code a contract method declares appears in the method's source file neither as a string literal nor as a property-access name (below exact grade, any identifier counts)" },
5923
5969
  { code: "CONFORMANCE_ANALYSIS_SKIPPED", defaultSeverity: "warning", summary: "A source file an implementation or one of its methods names could not be analyzed (binary/unreadable) \u2014 realization of the methods in it was not checked" },
5924
5970
  { code: "CONFORMANCE_DEGRADED", defaultSeverity: "warning", summary: "TypeScript/JavaScript files were analyzed below exact grade (compiler not resolvable) \u2014 dependency conformance skips them" }
5925
5971
  ],
@@ -5929,7 +5975,7 @@ var init_structural_conformance = __esm({
5929
5975
  lookups.set(pathKey(facts.path), {
5930
5976
  declared: /* @__PURE__ */ new Set([...facts.declaredNames, ...facts.exportedNames]),
5931
5977
  anchored: /* @__PURE__ */ new Set([...facts.declaredNames, ...facts.exportedNames, ...facts.anchoredNames]),
5932
- literals: new Set(facts.anchoredNames),
5978
+ findingAnchors: new Set(facts.anchoredNames),
5933
5979
  facts
5934
5980
  });
5935
5981
  }
@@ -6049,11 +6095,11 @@ var init_structural_conformance = __esm({
6049
6095
  if (!checked) continue;
6050
6096
  const { file, lookup } = checked;
6051
6097
  for (const finding of method.findings) {
6052
- if (lookup.literals.has(finding.code)) continue;
6098
+ if (lookup.findingAnchors.has(finding.code)) continue;
6053
6099
  ctx.addIssue(
6054
6100
  "warning",
6055
6101
  "UNREALIZED_FINDING",
6056
- `Method "${method.name}" of contract "${impl.contract}" declares finding "${finding.code}", but "${file}" has no string literal "${finding.code}" (analysis grade: ${lookup.facts.analysisGrade}) \u2014 report the finding under its declared code, or remove the declaration.`,
6102
+ `Method "${method.name}" of contract "${impl.contract}" declares finding "${finding.code}", but "${file}" has no string literal or property-access name "${finding.code}" (analysis grade: ${lookup.facts.analysisGrade}) \u2014 report the finding under its declared code, or remove the declaration.`,
6057
6103
  impl.id,
6058
6104
  draft
6059
6105
  );
@@ -6169,12 +6215,18 @@ var init_hidden_state = __esm({
6169
6215
  check(ctx) {
6170
6216
  const byPath = /* @__PURE__ */ new Map();
6171
6217
  for (const impl of ctx.implementations) {
6172
- if (impl.conformance === "off") continue;
6173
6218
  const contract = ctx.interfaceMap.get(impl.contract);
6174
6219
  const component = contract ? ctx.componentMap.get(contract.component) : void 0;
6175
6220
  if (!component) continue;
6176
6221
  if (ctx.isInChainedSubproject(component.subsystem)) continue;
6177
- for (const file of implementationSourceFiles(impl)) {
6222
+ const trusted = [];
6223
+ if (impl.sourcePath && impl.conformance !== "off") trusted.push(impl.sourcePath);
6224
+ for (const method of impl.methods) {
6225
+ if ((method.conformance ?? impl.conformance) === "off") continue;
6226
+ const file = methodSourceFile(method, impl.sourcePath);
6227
+ if (file) trusted.push(file);
6228
+ }
6229
+ for (const file of trusted) {
6178
6230
  const key = pathKey(file);
6179
6231
  const list = byPath.get(key) ?? [];
6180
6232
  if (list.some((m) => m.impl === impl)) continue;
@@ -6325,7 +6377,7 @@ var init_dependency_conformance = __esm({
6325
6377
  const fromFiles = filesByComponent.get(component.id);
6326
6378
  if (!fromFiles) continue;
6327
6379
  const isMountingDeclarer = component.componentType === "Portal" || component.componentType === "Observer";
6328
- const declaredTargets = [...component.dependsOn, ...component.owns ?? []];
6380
+ const declaredTargets = [.../* @__PURE__ */ new Set([...component.dependsOn, ...component.owns ?? []])];
6329
6381
  for (const targetId of declaredTargets) {
6330
6382
  const target = ctx.componentMap.get(targetId);
6331
6383
  if (!target) continue;
@@ -6346,11 +6398,14 @@ var init_dependency_conformance = __esm({
6346
6398
  }
6347
6399
  const impls = implsByComponent.get(component.id) ?? [];
6348
6400
  const anchor = impls[0];
6401
+ const declaredDependsOn = component.dependsOn.includes(targetId);
6402
+ const declaredOwns = (component.owns ?? []).includes(targetId);
6403
+ const relation = declaredDependsOn && declaredOwns ? "dependsOn and owns" : declaredDependsOn ? "dependsOn" : "owns";
6349
6404
  const draft = ctx.isComponentDraft(component.id) || ctx.isComponentDraft(targetId) || impls.some((i) => ctx.isImplementationDraft(i));
6350
6405
  ctx.addIssue(
6351
6406
  "warning",
6352
6407
  "UNREALIZED_DEPENDENCY",
6353
- `Component "${component.id}" declares ${component.dependsOn.includes(targetId) ? "dependsOn" : "owns"} "${targetId}", but no runtime import connects their source files (${[...fromFiles].join(", ")} \u219B ${target.subsystem !== component.subsystem ? `subsystem ${target.subsystem}` : [...filesByComponent.get(targetId) ?? []].join(", ")}) \u2014 either the collaboration is wired indirectly (DI) or the declared edge is stale.`,
6408
+ `Component "${component.id}" declares ${relation} "${targetId}", but no runtime import connects their source files (${[...fromFiles].join(", ")} \u219B ${target.subsystem !== component.subsystem ? `subsystem ${target.subsystem}` : [...filesByComponent.get(targetId) ?? []].join(", ")}) \u2014 either the collaboration is wired indirectly (DI) or the declared edge is stale.`,
6354
6409
  anchor?.id ?? component.id,
6355
6410
  draft
6356
6411
  );
@@ -6382,28 +6437,28 @@ var init_integration_conformance = __esm({
6382
6437
  const filesByComponent = /* @__PURE__ */ new Map();
6383
6438
  const filesBySubsystem = /* @__PURE__ */ new Map();
6384
6439
  const implsByComponent = /* @__PURE__ */ new Map();
6440
+ const adopted = /* @__PURE__ */ new Set();
6441
+ const exists = (p) => {
6442
+ const status = factsByPath.get(p)?.status;
6443
+ return status === "analyzed" || status === "unreadable";
6444
+ };
6385
6445
  for (const impl of ctx.implementations) {
6386
6446
  const contract = ctx.interfaceMap.get(impl.contract);
6387
6447
  const comp = contract ? ctx.componentMap.get(contract.component) : void 0;
6388
- if (!comp) continue;
6448
+ if (!comp || ctx.isInChainedSubproject(comp.subsystem)) continue;
6389
6449
  if (!implsByComponent.has(comp.id)) implsByComponent.set(comp.id, []);
6390
6450
  implsByComponent.get(comp.id).push(impl);
6391
6451
  for (const file of implementationSourceFiles(impl)) {
6392
6452
  const p = pathKey(file);
6453
+ if (!exists(p)) continue;
6393
6454
  if (!filesByComponent.has(comp.id)) filesByComponent.set(comp.id, /* @__PURE__ */ new Set());
6394
6455
  filesByComponent.get(comp.id).add(p);
6395
6456
  if (!filesBySubsystem.has(comp.subsystem)) filesBySubsystem.set(comp.subsystem, /* @__PURE__ */ new Set());
6396
6457
  filesBySubsystem.get(comp.subsystem).add(p);
6397
6458
  }
6459
+ if (impl.simPath) adopted.add(comp.subsystem);
6398
6460
  }
6399
6461
  const isTechBoundary = (compId) => (implsByComponent.get(compId) ?? []).some((i) => (i.technologies ?? []).length > 0);
6400
- const adopted = /* @__PURE__ */ new Set();
6401
- for (const impl of ctx.implementations) {
6402
- if (!impl.simPath) continue;
6403
- const contract = ctx.interfaceMap.get(impl.contract);
6404
- const comp = contract ? ctx.componentMap.get(contract.component) : void 0;
6405
- if (comp) adopted.add(comp.subsystem);
6406
- }
6407
6462
  const reachFrom = (start) => {
6408
6463
  const seen = /* @__PURE__ */ new Set([start]);
6409
6464
  const stack = [start];
@@ -6600,8 +6655,8 @@ var init_coupling_health = __esm({
6600
6655
  );
6601
6656
  }
6602
6657
  }
6603
- const threshold = ctx.rules?.complexity?.maxComponentDependencies ?? DEFAULT_GOD_COMPONENT_THRESHOLD;
6604
6658
  for (const comp of ctx.components) {
6659
+ const threshold = ctx.complexityConfigFor(comp.subsystem)?.maxComponentDependencies ?? DEFAULT_GOD_COMPONENT_THRESHOLD;
6605
6660
  if (comp.dependsOn.length > threshold) {
6606
6661
  ctx.addIssue(
6607
6662
  "warning",
@@ -6729,7 +6784,7 @@ var init_target_language = __esm({
6729
6784
  if (!lang) continue;
6730
6785
  const gaps = gapsFor(lang);
6731
6786
  if (Object.keys(gaps).length === 0) continue;
6732
- const isDraftCtx = impl.status === "draft" || impl.status === "design" || contract.status === "draft" || contract.status === "design" || ctx.isComponentDraft(contract.component);
6787
+ const isDraftCtx = ctx.isImplementationDraft(impl);
6733
6788
  for (const implMethod of impl.methods) {
6734
6789
  for (const step of implMethod.narrative) {
6735
6790
  const constructs = [
@@ -6831,7 +6886,7 @@ var init_technology_boundaries = __esm({
6831
6886
  "TECH_ON_LOGIC_COMPONENT",
6832
6887
  `Implementation "${impl.id}" binds technology (${impl.technologies.join(", ")}) on component "${comp.id}" (${comp.componentType}). Technology belongs behind a data-layer seam \u2014 extract an Adapter (or Store/Registry/Index) behind an intent interface and let this component depend on that.`,
6833
6888
  impl.id,
6834
- ctx.isComponentDraft(comp.id)
6889
+ ctx.isImplementationDraft(impl)
6835
6890
  );
6836
6891
  }
6837
6892
  const compSet = ownsClosure(ownershipRoot(comp.id));
@@ -6869,7 +6924,7 @@ var init_technology_boundaries = __esm({
6869
6924
  "VENDOR_NAME_IN_CONTRACT",
6870
6925
  `Interface "${intf.id}" exposes technology "${home.label}" in contract identifiers (method${offending.length > 1 ? "s" : ""}: ${offending.join(", ")}). Name the intent, not the vendor \u2014 the technology is owned by component ${ownersDesc(home)} and must stay swappable behind this contract.`,
6871
6926
  intf.id,
6872
- ctx.isComponentDraft(intf.component)
6927
+ ctx.isComponentDraft(intf.component) || intf.status === "draft" || intf.status === "design"
6873
6928
  );
6874
6929
  }
6875
6930
  }
@@ -6900,7 +6955,8 @@ var init_technology_boundaries = __esm({
6900
6955
  "warning",
6901
6956
  "TECH_LEAKAGE",
6902
6957
  `Subsystem "${sub.id}" references "${home.label}" outside the technology's owning boundary (component ${ownersDesc(home)}).`,
6903
- sub.id
6958
+ sub.id,
6959
+ isDraftSubsystem(sub)
6904
6960
  );
6905
6961
  }
6906
6962
  }
@@ -6913,7 +6969,7 @@ var init_technology_boundaries = __esm({
6913
6969
  "TECH_LEAKAGE",
6914
6970
  `Interface "${intf.id}" describes "${home.label}" outside its owning boundary (component ${ownersDesc(home)}) \u2014 consumers must not know backend specifics.`,
6915
6971
  intf.id,
6916
- ctx.isComponentDraft(intf.component)
6972
+ ctx.isComponentDraft(intf.component) || intf.status === "draft" || intf.status === "design"
6917
6973
  );
6918
6974
  }
6919
6975
  }
@@ -6933,7 +6989,8 @@ var init_technology_boundaries = __esm({
6933
6989
  "warning",
6934
6990
  "TECH_LEAKAGE",
6935
6991
  `Implementation "${impl.id}" references "${home.label}" outside its owning boundary \u2014 call the intent interface of component ${ownersDesc(home)} instead of naming its technology.`,
6936
- impl.id
6992
+ impl.id,
6993
+ ctx.isImplementationDraft(impl)
6937
6994
  );
6938
6995
  }
6939
6996
  }
@@ -6996,6 +7053,7 @@ var casingPatterns, isAllUppercase, namingRule;
6996
7053
  var init_naming_conventions = __esm({
6997
7054
  "src/core/rules/heuristic/naming-conventions.ts"() {
6998
7055
  "use strict";
7056
+ init_models();
6999
7057
  casingPatterns = {
7000
7058
  camelCase: /^[a-z][a-zA-Z0-9]*$/,
7001
7059
  PascalCase: /^[A-Z][a-zA-Z0-9]*$/,
@@ -7016,9 +7074,10 @@ var init_naming_conventions = __esm({
7016
7074
  for (const sub of ctx.subsystems) {
7017
7075
  const namingConfig = ctx.namingConfigFor(sub.id);
7018
7076
  if (!namingConfig?.subsystems) continue;
7077
+ const isDraft = isDraftSubsystem(sub);
7019
7078
  const baseId = getBaseId(sub.id);
7020
- checkNamedValue(ctx, baseId, namingConfig.subsystems, `Subsystem ID "${sub.id}" does not match naming convention "${namingConfig.subsystems}".`, sub.id);
7021
- checkNamedValue(ctx, sub.name, namingConfig.subsystems, `Subsystem Name "${sub.name}" does not match naming convention "${namingConfig.subsystems}".`, sub.id);
7079
+ checkNamedValue(ctx, baseId, namingConfig.subsystems, `Subsystem ID "${sub.id}" does not match naming convention "${namingConfig.subsystems}".`, sub.id, isDraft);
7080
+ checkNamedValue(ctx, sub.name, namingConfig.subsystems, `Subsystem Name "${sub.name}" does not match naming convention "${namingConfig.subsystems}".`, sub.id, isDraft);
7022
7081
  }
7023
7082
  for (const comp of ctx.components) {
7024
7083
  const namingConfig = ctx.namingConfigFor(comp.subsystem);
@@ -7103,7 +7162,7 @@ var init_naming_conventions = __esm({
7103
7162
  const intf = ctx.interfaceMap.get(impl.contract);
7104
7163
  const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
7105
7164
  const namingConfig = ctx.namingConfigFor(comp?.subsystem);
7106
- const isDraft = impl.status === "draft" || impl.status === "design";
7165
+ const isDraft = ctx.isImplementationDraft(impl);
7107
7166
  if (namingConfig?.methods) {
7108
7167
  for (const m of impl.methods) {
7109
7168
  checkNamedValue(ctx, m.name, namingConfig.methods, `Implementation method "${m.name}" on "${impl.id}" does not match naming convention "${namingConfig.methods}".`, impl.id, isDraft);
@@ -7167,6 +7226,7 @@ var complexityRule;
7167
7226
  var init_complexity_and_metadata = __esm({
7168
7227
  "src/core/rules/heuristic/complexity-and-metadata.ts"() {
7169
7228
  "use strict";
7229
+ init_models();
7170
7230
  complexityRule = {
7171
7231
  name: "complexity-and-metadata",
7172
7232
  description: "Enforces metadata documentation completeness (checking if descriptions are missing or too short) and structural complexity caps (limits on methods per interface, dependencies per component, and narrative steps per method) configured globally or in architectural profiles.",
@@ -7182,7 +7242,8 @@ var init_complexity_and_metadata = __esm({
7182
7242
  check(ctx) {
7183
7243
  for (const sub of ctx.subsystems) {
7184
7244
  const docConfig = ctx.documentationConfigFor(sub.id);
7185
- checkDescription(ctx, sub.description, docConfig?.requireDescriptions ?? false, docConfig?.minDescriptionLength, sub.id, "Subsystem", false);
7245
+ const isSubDraft = isDraftSubsystem(sub);
7246
+ checkDescription(ctx, sub.description, docConfig?.requireDescriptions ?? false, docConfig?.minDescriptionLength, sub.id, "Subsystem", isSubDraft);
7186
7247
  const complexityConfig = ctx.complexityConfigFor(sub.id);
7187
7248
  const directComponents = ctx.components.filter((c) => c.subsystem === sub.id).length;
7188
7249
  if (complexityConfig?.maxSubsystemComponents !== void 0 && directComponents > complexityConfig.maxSubsystemComponents) {
@@ -7190,7 +7251,8 @@ var init_complexity_and_metadata = __esm({
7190
7251
  "warning",
7191
7252
  "EXCESSIVE_SUBSYSTEM_COMPONENTS",
7192
7253
  `Subsystem "${sub.id}" has ${directComponents} direct components, exceeding the configured limit of ${complexityConfig.maxSubsystemComponents}.`,
7193
- sub.id
7254
+ sub.id,
7255
+ isSubDraft
7194
7256
  );
7195
7257
  }
7196
7258
  }
@@ -7266,7 +7328,7 @@ var init_complexity_and_metadata = __esm({
7266
7328
  const intf = ctx.interfaceMap.get(impl.contract);
7267
7329
  const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
7268
7330
  const complexityConfig = ctx.complexityConfigFor(comp?.subsystem);
7269
- const isDraft = impl.status === "draft" || impl.status === "design";
7331
+ const isDraft = ctx.isImplementationDraft(impl);
7270
7332
  if (complexityConfig?.maxNarrativeSteps !== void 0) {
7271
7333
  for (const m of impl.methods) {
7272
7334
  if (m.narrative.length > complexityConfig.maxNarrativeSteps) {
@@ -13980,7 +14042,7 @@ function buildRuleContext(opts) {
13980
14042
  return rules.sddRuleSeverity[ruleCode];
13981
14043
  }
13982
14044
  const sub = subsystemId ? subsystems.find((s) => s.id === subsystemId) : void 0;
13983
- const profileSeverity = extensions.profiles[sub?.profile ?? projectType]?.rules?.sddRuleSeverity?.[ruleCode];
14045
+ const profileSeverity = extensions.profiles[sub?.profile || projectType]?.rules?.sddRuleSeverity?.[ruleCode];
13984
14046
  if (profileSeverity) {
13985
14047
  return profileSeverity;
13986
14048
  }
@@ -14219,28 +14281,52 @@ var init_candidate = __esm({
14219
14281
  function globalVariantsDir() {
14220
14282
  return process.env.WAIRON_VARIANTS_DIR ?? path12.join(os3.homedir(), ".wairon", "variants");
14221
14283
  }
14222
- function readVariantsDir(dir) {
14284
+ function builtinVariantsDir() {
14285
+ const candidates = [
14286
+ path12.resolve(__dirname, "..", "templates", "variants"),
14287
+ // src/core & dist/cli
14288
+ path12.resolve(__dirname, "templates", "variants")
14289
+ // dist (library entry)
14290
+ ];
14291
+ return candidates.find((dir) => fs9.existsSync(dir)) ?? candidates[0];
14292
+ }
14293
+ function projectVariantsDir() {
14294
+ return path12.join(getProjectRoot(), ".wai", "variants");
14295
+ }
14296
+ function variantFiles(dir) {
14223
14297
  let entries;
14224
14298
  try {
14225
14299
  entries = fs9.readdirSync(dir, { withFileTypes: true });
14226
14300
  } catch {
14227
14301
  return [];
14228
14302
  }
14303
+ return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path12.join(dir, e.name));
14304
+ }
14305
+ function parseVariants(raw) {
14306
+ if (raw == null) return [];
14307
+ return (Array.isArray(raw) ? raw : [raw]).map((item) => VariantDefSchema.parse(item));
14308
+ }
14309
+ function reportSkippedFile(file, err) {
14310
+ console.error(`[variants] skipped "${file}": ${err instanceof Error ? err.message : String(err)}`);
14311
+ }
14312
+ function readVariantsDir(dir) {
14229
14313
  const out = [];
14230
- for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
14231
- if (!e.isFile() || !/\.ya?ml$/i.test(e.name)) continue;
14232
- const full = path12.join(dir, e.name);
14314
+ for (const file of variantFiles(dir)) {
14233
14315
  try {
14234
- const raw = readYamlFile(full);
14235
- if (raw == null) continue;
14236
- const items = Array.isArray(raw) ? raw : [raw];
14237
- for (const item of items) out.push(VariantDefSchema.parse(item));
14316
+ out.push(...parseVariants(readYamlFile(file)));
14238
14317
  } catch (err) {
14239
- console.error(`[variants] skipped "${full}": ${err instanceof Error ? err.message : String(err)}`);
14318
+ reportSkippedFile(file, err);
14240
14319
  }
14241
14320
  }
14242
14321
  return out;
14243
14322
  }
14323
+ function mergeById(...layers) {
14324
+ const byId = /* @__PURE__ */ new Map();
14325
+ for (const layer of layers) {
14326
+ for (const v of layer) byId.set(v.id, v);
14327
+ }
14328
+ return [...byId.values()];
14329
+ }
14244
14330
  function resolveVariantGuidance(component, allComponents, variantsById) {
14245
14331
  if (!component.variant) return null;
14246
14332
  const def = variantsById.get(component.variant);
@@ -14274,14 +14360,55 @@ function composeVariantGuidance(comps, allComponents, variantsById) {
14274
14360
  }
14275
14361
  function loadProjectVariants() {
14276
14362
  try {
14277
- const byId = /* @__PURE__ */ new Map();
14278
- for (const v of readVariantsDir(globalVariantsDir())) byId.set(v.id, v);
14279
- for (const v of readVariantsDir(path12.join(getProjectRoot(), ".wai", "variants"))) byId.set(v.id, v);
14280
- return [...byId.values()];
14363
+ return mergeById(
14364
+ readVariantsDir(builtinVariantsDir()),
14365
+ readVariantsDir(globalVariantsDir()),
14366
+ readVariantsDir(projectVariantsDir())
14367
+ );
14281
14368
  } catch {
14282
14369
  return [];
14283
14370
  }
14284
14371
  }
14372
+ function listProjectVariants() {
14373
+ return mergeById(readVariantsDir(projectVariantsDir()));
14374
+ }
14375
+ function rebaseProjectVariants(fromBase, toBase) {
14376
+ const rebased = [];
14377
+ for (const file of variantFiles(projectVariantsDir())) {
14378
+ const content = readFileOrNull(file);
14379
+ if (content === null) continue;
14380
+ let raw;
14381
+ let variants;
14382
+ try {
14383
+ raw = parseYaml(content, file);
14384
+ variants = parseVariants(raw);
14385
+ } catch (err) {
14386
+ reportSkippedFile(file, err);
14387
+ continue;
14388
+ }
14389
+ const matching = variants.filter((v) => v.base === fromBase);
14390
+ if (matching.length === 0) continue;
14391
+ writeFile(file, rebasedText(content, fromBase, toBase, withRebasedEntries(raw, fromBase, toBase)));
14392
+ for (const v of matching) {
14393
+ if (!rebased.includes(v.id)) rebased.push(v.id);
14394
+ }
14395
+ }
14396
+ return rebased;
14397
+ }
14398
+ function withRebasedEntries(raw, fromBase, toBase) {
14399
+ const rebase = (entry) => entry.base === fromBase ? { ...entry, base: toBase } : entry;
14400
+ return Array.isArray(raw) ? raw.map(rebase) : rebase(raw);
14401
+ }
14402
+ function rebasedText(content, fromBase, toBase, rebasedContent) {
14403
+ const escaped = fromBase.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14404
+ const baseLine = new RegExp(`^([ \\t]*(?:-[ \\t]+)?base:[ \\t]*)(["']?)${escaped}\\2(?=[ \\t]*(?:#.*)?$)`, "gm");
14405
+ const edited = content.replace(baseLine, (_line, key, quote) => `${key}${quote}${toBase}${quote}`);
14406
+ try {
14407
+ if (JSON.stringify(parseYaml(edited)) === JSON.stringify(rebasedContent)) return edited;
14408
+ } catch {
14409
+ }
14410
+ return serializeYaml(rebasedContent);
14411
+ }
14285
14412
  var fs9, os3, path12, import_zod10, VariantDefSchema;
14286
14413
  var init_variants = __esm({
14287
14414
  "src/core/variants.ts"() {
@@ -14295,7 +14422,7 @@ var init_variants = __esm({
14295
14422
  VariantDefSchema = import_zod10.z.object({
14296
14423
  /** Variant id referenced by a component's `variant` (e.g. "publisher", "org/external-config-adapter"). */
14297
14424
  id: import_zod10.z.string().min(1),
14298
- /** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Specialist, …). */
14425
+ /** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Orchestrator, …). */
14299
14426
  base: import_zod10.z.string().min(1),
14300
14427
  /** How to implement a component of this variant — the recipe the implementer follows and reuses across same-variant components. */
14301
14428
  guidance: import_zod10.z.string().min(1),
@@ -23525,6 +23652,7 @@ __export(src_exports, {
23525
23652
  DEFAULT_TARGET_DIRS: () => DEFAULT_TARGET_DIRS,
23526
23653
  DatabaseSpecSchema: () => DatabaseSpecSchema,
23527
23654
  DeclarativePackSchema: () => DeclarativePackSchema,
23655
+ DependencyClassSchema: () => DependencyClassSchema,
23528
23656
  DesignDepthSchema: () => DesignDepthSchema,
23529
23657
  DiagramConfigSchema: () => DiagramConfigSchema,
23530
23658
  DispatchBindingSchema: () => DispatchBindingSchema,
@@ -23582,6 +23710,7 @@ __export(src_exports, {
23582
23710
  ProjectProfileSelectionSchema: () => ProjectProfileSelectionSchema,
23583
23711
  PublicInterfaceSchema: () => PublicInterfaceSchema,
23584
23712
  PublicInterfaceTypeSchema: () => PublicInterfaceTypeSchema,
23713
+ RETIRED_STEREOTYPES: () => RETIRED_STEREOTYPES,
23585
23714
  RegistrySchema: () => RegistrySchema,
23586
23715
  RequirementItemSchema: () => RequirementItemSchema,
23587
23716
  RulesConfigSchema: () => RulesConfigSchema,
@@ -23732,6 +23861,7 @@ __export(src_exports, {
23732
23861
  hasContext: () => hasContext,
23733
23862
  hasSpecTree: () => hasSpecTree,
23734
23863
  hashGateState: () => hashGateState,
23864
+ holdsState: () => holdsState,
23735
23865
  implementationSourceFiles: () => implementationSourceFiles,
23736
23866
  importSpecTree: () => importSpecTree,
23737
23867
  importSurface: () => importSurface,
@@ -23742,10 +23872,12 @@ __export(src_exports, {
23742
23872
  internalizeSubsystem: () => internalizeSubsystem,
23743
23873
  invalidateSpecCache: () => invalidateSpecCache,
23744
23874
  isDraftSubsystem: () => isDraftSubsystem,
23875
+ isLogic: () => isLogic,
23745
23876
  isOpenApiDocument: () => isOpenApiDocument,
23746
23877
  isPattern: () => isPattern,
23747
23878
  isProjectInitialized: () => isProjectInitialized,
23748
23879
  isProvidedBy: () => isProvidedBy,
23880
+ isRetired: () => isRetired,
23749
23881
  listChainedRoots: () => listChainedRoots,
23750
23882
  listDirectChainedSubprojects: () => listDirectChainedSubprojects,
23751
23883
  listExternalInterfaces: () => listExternalInterfaces,
@@ -23754,6 +23886,7 @@ __export(src_exports, {
23754
23886
  listFreeStandingDomains: () => listFreeStandingDomains,
23755
23887
  listInstalledPacks: () => listInstalledPacks,
23756
23888
  listMountSnapshots: () => listMountSnapshots,
23889
+ listProjectVariants: () => listProjectVariants,
23757
23890
  listResources: () => listResources,
23758
23891
  listRules: () => listRules2,
23759
23892
  listSkillNames: () => listSkillNames,
@@ -23824,6 +23957,7 @@ __export(src_exports, {
23824
23957
  readResource: () => readResource,
23825
23958
  readSkillResource: () => readSkillResource,
23826
23959
  readYamlFile: () => readYamlFile,
23960
+ rebaseProjectVariants: () => rebaseProjectVariants,
23827
23961
  rebaseReference: () => rebaseReference,
23828
23962
  recordProfileSelection: () => recordProfileSelection,
23829
23963
  registerExporter: () => registerExporter,
@@ -24231,6 +24365,7 @@ function loadProjectConfig4() {
24231
24365
  DEFAULT_TARGET_DIRS,
24232
24366
  DatabaseSpecSchema,
24233
24367
  DeclarativePackSchema,
24368
+ DependencyClassSchema,
24234
24369
  DesignDepthSchema,
24235
24370
  DiagramConfigSchema,
24236
24371
  DispatchBindingSchema,
@@ -24288,6 +24423,7 @@ function loadProjectConfig4() {
24288
24423
  ProjectProfileSelectionSchema,
24289
24424
  PublicInterfaceSchema,
24290
24425
  PublicInterfaceTypeSchema,
24426
+ RETIRED_STEREOTYPES,
24291
24427
  RegistrySchema,
24292
24428
  RequirementItemSchema,
24293
24429
  RulesConfigSchema,
@@ -24438,6 +24574,7 @@ function loadProjectConfig4() {
24438
24574
  hasContext,
24439
24575
  hasSpecTree,
24440
24576
  hashGateState,
24577
+ holdsState,
24441
24578
  implementationSourceFiles,
24442
24579
  importSpecTree,
24443
24580
  importSurface,
@@ -24448,10 +24585,12 @@ function loadProjectConfig4() {
24448
24585
  internalizeSubsystem,
24449
24586
  invalidateSpecCache,
24450
24587
  isDraftSubsystem,
24588
+ isLogic,
24451
24589
  isOpenApiDocument,
24452
24590
  isPattern,
24453
24591
  isProjectInitialized,
24454
24592
  isProvidedBy,
24593
+ isRetired,
24455
24594
  listChainedRoots,
24456
24595
  listDirectChainedSubprojects,
24457
24596
  listExternalInterfaces,
@@ -24460,6 +24599,7 @@ function loadProjectConfig4() {
24460
24599
  listFreeStandingDomains,
24461
24600
  listInstalledPacks,
24462
24601
  listMountSnapshots,
24602
+ listProjectVariants,
24463
24603
  listResources,
24464
24604
  listRules,
24465
24605
  listSkillNames,
@@ -24530,6 +24670,7 @@ function loadProjectConfig4() {
24530
24670
  readResource,
24531
24671
  readSkillResource,
24532
24672
  readYamlFile,
24673
+ rebaseProjectVariants,
24533
24674
  rebaseReference,
24534
24675
  recordProfileSelection,
24535
24676
  registerExporter,