@wairon/cli 5.1.1-dev.96 → 5.1.1-dev.98

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
@@ -1672,15 +1672,15 @@ var require_node = __commonJS({
1672
1672
  var slzh = function(d, b) {
1673
1673
  return b + 30 + b2(d, b + 26) + b2(d, b + 28);
1674
1674
  };
1675
- var zh = function(d, b, z12) {
1675
+ var zh = function(d, b, z13) {
1676
1676
  var fnl = b2(d, b + 28), efl = b2(d, b + 30), fn = strFromU8(d.subarray(b + 46, b + 46 + fnl), !(b2(d, b + 8) & 2048)), es = b + 46 + fnl;
1677
- var _a2 = z64hs(d, es, efl, z12, b4(d, b + 20), b4(d, b + 24), b4(d, b + 42)), sc = _a2[0], su = _a2[1], off = _a2[2];
1677
+ var _a2 = z64hs(d, es, efl, z13, b4(d, b + 20), b4(d, b + 24), b4(d, b + 42)), sc = _a2[0], su = _a2[1], off = _a2[2];
1678
1678
  return [b2(d, b + 10), sc, su, fn, es + efl + b2(d, b + 32), off];
1679
1679
  };
1680
- var z64hs = function(d, b, l, z12, sc, su, off) {
1680
+ var z64hs = function(d, b, l, z13, sc, su, off) {
1681
1681
  var nsc = sc == 4294967295, nsu = su == 4294967295, noff = off == 4294967295, e = b + l;
1682
1682
  var nf = nsc + nsu + noff;
1683
- if (z12 && nf) {
1683
+ if (z13 && nf) {
1684
1684
  for (; b + 4 < e; b += 4 + b2(d, b + 2)) {
1685
1685
  if (b2(d, b) == 1) {
1686
1686
  return [
@@ -1691,7 +1691,7 @@ var require_node = __commonJS({
1691
1691
  ];
1692
1692
  }
1693
1693
  }
1694
- if (z12 < 2)
1694
+ if (z13 < 2)
1695
1695
  err(13);
1696
1696
  }
1697
1697
  return [sc, su, off, 0];
@@ -2300,18 +2300,18 @@ var require_node = __commonJS({
2300
2300
  if (lft) {
2301
2301
  var c = lft;
2302
2302
  var o = b4(data, e + 16);
2303
- var z12 = b4(data, e - 20) == 117853008;
2304
- if (z12) {
2303
+ var z13 = b4(data, e - 20) == 117853008;
2304
+ if (z13) {
2305
2305
  var ze = b4(data, e - 12);
2306
- z12 = b4(data, ze) == 101075792;
2307
- if (z12) {
2306
+ z13 = b4(data, ze) == 101075792;
2307
+ if (z13) {
2308
2308
  c = lft = b4(data, ze + 32);
2309
2309
  o = b4(data, ze + 48);
2310
2310
  }
2311
2311
  }
2312
2312
  var fltr = opts && opts.filter;
2313
2313
  var _loop_3 = function(i3) {
2314
- var _a2 = zh(data, o, z12), c_1 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);
2314
+ var _a2 = zh(data, o, z13), c_1 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);
2315
2315
  o = no;
2316
2316
  var cbl = function(e2, d) {
2317
2317
  if (e2) {
@@ -2366,18 +2366,18 @@ var require_node = __commonJS({
2366
2366
  if (!c)
2367
2367
  return {};
2368
2368
  var o = b4(data, e + 16);
2369
- var z12 = b4(data, e - 20) == 117853008;
2370
- if (z12) {
2369
+ var z13 = b4(data, e - 20) == 117853008;
2370
+ if (z13) {
2371
2371
  var ze = b4(data, e - 12);
2372
- z12 = b4(data, ze) == 101075792;
2373
- if (z12) {
2372
+ z13 = b4(data, ze) == 101075792;
2373
+ if (z13) {
2374
2374
  c = b4(data, ze + 32);
2375
2375
  o = b4(data, ze + 48);
2376
2376
  }
2377
2377
  }
2378
2378
  var fltr = opts && opts.filter;
2379
2379
  for (var i2 = 0; i2 < c; ++i2) {
2380
- var _a2 = zh(data, o, z12), c_2 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);
2380
+ var _a2 = zh(data, o, z13), c_2 = _a2[0], sc = _a2[1], su = _a2[2], fn = _a2[3], no = _a2[4], off = _a2[5], b = slzh(data, off);
2381
2381
  o = no;
2382
2382
  if (!fltr || fltr({
2383
2383
  name: fn,
@@ -3414,9 +3414,30 @@ __export(src_exports, {
3414
3414
  CustomTargetConfigSchema: () => CustomTargetConfigSchema,
3415
3415
  CustomTargetSchema: () => CustomTargetSchema,
3416
3416
  DEFAULT_TARGET_DIRS: () => DEFAULT_TARGET_DIRS,
3417
+ DESIGN_APPROVALS: () => DESIGN_APPROVALS,
3418
+ DESIGN_DEPENDENCY_ROLES: () => DESIGN_DEPENDENCY_ROLES,
3419
+ DESIGN_FORMAT: () => DESIGN_FORMAT,
3420
+ DESIGN_FORMAT_VERSION: () => DESIGN_FORMAT_VERSION,
3417
3421
  DatabaseSpecSchema: () => DatabaseSpecSchema,
3418
3422
  DependencyClassSchema: () => DependencyClassSchema,
3423
+ DesignApprovalSchema: () => DesignApprovalSchema,
3424
+ DesignComponentSchema: () => DesignComponentSchema,
3425
+ DesignDependencyRoleSchema: () => DesignDependencyRoleSchema,
3426
+ DesignDependencySchema: () => DesignDependencySchema,
3419
3427
  DesignDepthSchema: () => DesignDepthSchema,
3428
+ DesignExportEntrySchema: () => DesignExportEntrySchema,
3429
+ DesignExportSchema: () => DesignExportSchema,
3430
+ DesignFieldSchema: () => DesignFieldSchema,
3431
+ DesignImplementationSchema: () => DesignImplementationSchema,
3432
+ DesignInterfaceSchema: () => DesignInterfaceSchema,
3433
+ DesignMethodBodySchema: () => DesignMethodBodySchema,
3434
+ DesignMethodSchema: () => DesignMethodSchema,
3435
+ DesignParamSchema: () => DesignParamSchema,
3436
+ DesignProjectSchema: () => DesignProjectSchema,
3437
+ DesignSourceSchema: () => DesignSourceSchema,
3438
+ DesignSubsystemSchema: () => DesignSubsystemSchema,
3439
+ DesignTypeRefSchema: () => DesignTypeRefSchema,
3440
+ DesignTypeSchema: () => DesignTypeSchema,
3420
3441
  DiagramConfigSchema: () => DiagramConfigSchema,
3421
3442
  DispatchBindingSchema: () => DispatchBindingSchema,
3422
3443
  DoctorOptionsError: () => DoctorOptionsError,
@@ -3476,6 +3497,8 @@ __export(src_exports, {
3476
3497
  PortalAuthSchemeSchema: () => PortalAuthSchemeSchema,
3477
3498
  PortalMountSchema: () => PortalMountSchema,
3478
3499
  PortalTypeSchema: () => PortalTypeSchema,
3500
+ PreviousIdsSchema: () => PreviousIdsSchema,
3501
+ PreviousNamesSchema: () => PreviousNamesSchema,
3479
3502
  ProfileSelectionSubjectSchema: () => ProfileSelectionSubjectSchema,
3480
3503
  ProjectConfigSchema: () => ProjectConfigSchema,
3481
3504
  ProjectNotInitializedError: () => ProjectNotInitializedError,
@@ -3519,6 +3542,7 @@ __export(src_exports, {
3519
3542
  TopologyConfigSchema: () => TopologyConfigSchema,
3520
3543
  TransportSchema: () => TransportSchema,
3521
3544
  TrustedLinkSchema: () => TrustedLinkSchema,
3545
+ TypeExpressionSchema: () => TypeExpressionSchema,
3522
3546
  TypeFieldSchema: () => TypeFieldSchema,
3523
3547
  TypeKindSchema: () => TypeKindSchema,
3524
3548
  TypeMethodSchema: () => TypeMethodSchema,
@@ -3606,6 +3630,7 @@ __export(src_exports, {
3606
3630
  ensureDir: () => ensureDir,
3607
3631
  ensureProjectInitialized: () => ensureProjectInitialized,
3608
3632
  excerptParent: () => excerpt,
3633
+ exportDesign: () => exportDesign3,
3609
3634
  exportSpecTree: () => exportSpecTree,
3610
3635
  exportTargetKey: () => exportTargetKey,
3611
3636
  exportUsage: () => exportUsage,
@@ -3755,6 +3780,7 @@ __export(src_exports, {
3755
3780
  renameComponent: () => renameComponent,
3756
3781
  renameId: () => renameProjectId,
3757
3782
  renameMethod: () => renameMethod,
3783
+ renameType: () => renameType,
3758
3784
  renderDiagram: () => renderDiagram,
3759
3785
  repairForeignStepFields: () => repairForeignStepFields,
3760
3786
  repairSignatures: () => repairSignatures,
@@ -3794,6 +3820,7 @@ __export(src_exports, {
3794
3820
  settledSpecPaths: () => settledSpecPaths,
3795
3821
  signatureFacts: () => signatureFacts,
3796
3822
  signatureTypeRefs: () => signatureTypeRefs,
3823
+ specIndexRetiredBy: () => specIndexRetiredBy,
3797
3824
  specPathsInScope: () => specPathsInScope,
3798
3825
  splitNamespace: () => splitNamespace,
3799
3826
  stepConfigVerdict: () => stepConfigVerdict,
@@ -6996,6 +7023,22 @@ var PortalMountSchema = import_zod8.z.object({
6996
7023
  */
6997
7024
  via: import_zod8.z.string().optional()
6998
7025
  });
7026
+ var PreviousIdsSchema = import_zod8.z.array(import_zod8.z.string().min(1));
7027
+ var PreviousNamesSchema = import_zod8.z.array(import_zod8.z.string().min(1));
7028
+ function specIndexRetiredBy(index, kind, id) {
7029
+ const holders = kind === "component" ? index.components : kind === "interface" ? index.interfaces : kind === "implementation" ? index.implementations : kind === "type" ? index.types : [];
7030
+ for (const holder of holders) {
7031
+ if (!holder.previousIds?.length) continue;
7032
+ const key = kind === "type" && holder.subsystem && !holder.id.startsWith(`${holder.subsystem}::`) ? `${holder.subsystem}::${holder.id}` : holder.id;
7033
+ const cut = key.lastIndexOf("::");
7034
+ const namespace = cut >= 0 ? key.slice(0, cut + 2) : "";
7035
+ for (const previous of holder.previousIds) {
7036
+ const previousKey = previous.includes("::") ? previous : namespace + previous;
7037
+ if (previousKey === id) return key;
7038
+ }
7039
+ }
7040
+ return void 0;
7041
+ }
6999
7042
  var ComponentSpecSchema = import_zod8.z.object({
7000
7043
  id: SpecIdSchema,
7001
7044
  name: import_zod8.z.string(),
@@ -7039,6 +7082,8 @@ var ComponentSpecSchema = import_zod8.z.object({
7039
7082
  * satisfies the source requirement for a source-less implementation (suppresses
7040
7083
  * MISSING_SOURCE_PATH); `informative` links are context only. */
7041
7084
  externalLinks: import_zod8.z.array(ExternalLinkSchema).optional(),
7085
+ /** The rename trace (see PreviousIdsSchema). */
7086
+ previousIds: PreviousIdsSchema.optional(),
7042
7087
  /** Per-spec lint suppressions (see LintConfigSchema). */
7043
7088
  lint: LintConfigSchema.optional(),
7044
7089
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
@@ -7162,11 +7207,16 @@ var MethodSignatureSchema = import_zod8.z.object({
7162
7207
  */
7163
7208
  guarantees: import_zod8.z.array(GuaranteeSchema).optional(),
7164
7209
  /**
7165
- * State-effect direction of this method on its component's held state. Required on a
7166
- * durable Store's contract methods so the durability round-trip rule can pair external
7167
- * writes with hydration read-backs (MISSING_HYDRATION); optional elsewhere.
7210
+ * What this method does to its component's held state: `read` observes it, `write`
7211
+ * modifies an entity's domain fields, and `lifecycle` creates, destroys, or
7212
+ * (un)registers an entity's existence or membership without modifying its fields —
7213
+ * closed under composition (a lifecycle method calls only read and lifecycle methods,
7214
+ * LIFECYCLE_CALLS_WRITE). Required on a durable Store's contract methods so the
7215
+ * durability round-trip rule can pair mutations with hydration read-backs
7216
+ * (MISSING_HYDRATION); a Supervisor may call a data component it does not own only
7217
+ * through read and lifecycle methods (SUPERVISOR_WRITE_SHORTCUT). Optional elsewhere.
7168
7218
  */
7169
- effect: import_zod8.z.enum(["read", "write"]).optional(),
7219
+ effect: import_zod8.z.enum(["read", "write", "lifecycle"]).optional(),
7170
7220
  /**
7171
7221
  * Typed acknowledgment of a real caller OUTSIDE the modeled narrative graph
7172
7222
  * (runtime timer/hook, external system, sibling subsystem). Unused-detection
@@ -7201,6 +7251,8 @@ var MethodSignatureSchema = import_zod8.z.object({
7201
7251
  seen.add(finding2.code);
7202
7252
  });
7203
7253
  }).optional(),
7254
+ /** The method's rename trace (see PreviousNamesSchema). */
7255
+ previousNames: PreviousNamesSchema.optional(),
7204
7256
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
7205
7257
  ext: ExtDataSchema.optional()
7206
7258
  });
@@ -7268,6 +7320,8 @@ var InterfaceSpecSchema = import_zod8.z.object({
7268
7320
  component: import_zod8.z.string(),
7269
7321
  // References L2 Component id
7270
7322
  methods: import_zod8.z.array(StoredMethodSignatureSchema).default([]),
7323
+ /** The rename trace (see PreviousIdsSchema). */
7324
+ previousIds: PreviousIdsSchema.optional(),
7271
7325
  /** Per-spec lint suppressions (see LintConfigSchema). */
7272
7326
  lint: LintConfigSchema.optional(),
7273
7327
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
@@ -7558,6 +7612,8 @@ var ImplementationSpecSchema = import_zod8.z.object({
7558
7612
  detail: NarrativeDetailSchema.optional(),
7559
7613
  /** Spec-level conformance tier default (each method may override). */
7560
7614
  conformance: ConformanceTierSchema.optional(),
7615
+ /** The rename trace (see PreviousIdsSchema). */
7616
+ previousIds: PreviousIdsSchema.optional(),
7561
7617
  /** Per-spec lint suppressions (see LintConfigSchema). */
7562
7618
  lint: LintConfigSchema.optional(),
7563
7619
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
@@ -7733,6 +7789,8 @@ var TypeSpecSchema = import_zod8.z.object({
7733
7789
  * as `InvoiceLine`.
7734
7790
  */
7735
7791
  symbol: import_zod8.z.string().optional(),
7792
+ /** The rename trace (see PreviousIdsSchema): ids this type held within its owner. */
7793
+ previousIds: PreviousIdsSchema.optional(),
7736
7794
  /** Per-spec lint suppressions (see LintConfigSchema). */
7737
7795
  lint: LintConfigSchema.optional(),
7738
7796
  /** Opaque pack/tool extension data (see ExtDataSchema) — preserved verbatim. */
@@ -9382,12 +9440,12 @@ function exportTargetKey(e) {
9382
9440
 
9383
9441
  // src/models/project-family.ts
9384
9442
  var path10 = __toESM(require("path"));
9385
- function walkMemberPath(byKey2, start, segments) {
9443
+ function walkMemberPath(byKey3, start, segments) {
9386
9444
  let node = start;
9387
9445
  for (const segment of segments.slice(0, -1)) {
9388
9446
  const next = node.aliases.get(segment);
9389
9447
  if (next !== void 0) {
9390
- const found = byKey2.get(next);
9448
+ const found = byKey3.get(next);
9391
9449
  if (!found) return null;
9392
9450
  node = found;
9393
9451
  continue;
@@ -9399,13 +9457,13 @@ function walkMemberPath(byKey2, start, segments) {
9399
9457
  return { project: node, name: segments[segments.length - 1] };
9400
9458
  }
9401
9459
  function landReference(projects, reference, from) {
9402
- const byKey2 = new Map(projects.map((p) => [p.namespace, p]));
9403
- const origin = byKey2.get(from);
9404
- const root = byKey2.get("");
9460
+ const byKey3 = new Map(projects.map((p) => [p.namespace, p]));
9461
+ const origin = byKey3.get(from);
9462
+ const root = byKey3.get("");
9405
9463
  if (!reference.includes("::")) return { kind: "project", project: from, name: reference };
9406
9464
  const land = (form, start, segments2) => {
9407
9465
  if (!start) return { kind: "unresolved", form };
9408
- const walked = walkMemberPath(byKey2, start, segments2);
9466
+ const walked = walkMemberPath(byKey3, start, segments2);
9409
9467
  if (walked === "outside") return { kind: "outside", form };
9410
9468
  if (walked) return { kind: "project", form, project: walked.project.namespace, name: walked.name };
9411
9469
  return { kind: "unresolved", form };
@@ -9417,7 +9475,7 @@ function landReference(projects, reference, from) {
9417
9475
  while (segments[0] === "super") {
9418
9476
  segments.shift();
9419
9477
  if (!node || node.parent === void 0) return { kind: "outside", form: "super" };
9420
- node = byKey2.get(node.parent);
9478
+ node = byKey3.get(node.parent);
9421
9479
  }
9422
9480
  if (segments.length === 0 || !node) return { kind: "unresolved", form: "super" };
9423
9481
  return land("super", node, segments);
@@ -9429,11 +9487,11 @@ function landReference(projects, reference, from) {
9429
9487
  return land(segments.length === 2 ? "alias" : "path", origin, segments);
9430
9488
  }
9431
9489
  if (origin.subsystems.has(first)) return { kind: "project", project: from, name: segments[segments.length - 1] };
9432
- const fromRoot = root ? walkMemberPath(byKey2, root, segments) : null;
9490
+ const fromRoot = root ? walkMemberPath(byKey3, root, segments) : null;
9433
9491
  if (fromRoot && fromRoot !== "outside") return { kind: "project", form: "path", project: fromRoot.project.namespace, name: fromRoot.name };
9434
9492
  const byId = projects.filter((p) => p.id === first || p.namespace !== "" && p.namespace === first);
9435
9493
  if (byId.length === 1) {
9436
- const walked = walkMemberPath(byKey2, byId[0], segments.slice(1));
9494
+ const walked = walkMemberPath(byKey3, byId[0], segments.slice(1));
9437
9495
  if (walked === "outside") return { kind: "outside", form: "path" };
9438
9496
  if (walked) return { kind: "project", form: "path", project: walked.project.namespace, name: walked.name };
9439
9497
  }
@@ -9573,6 +9631,188 @@ function selectsFamily(options, declaresMembers) {
9573
9631
  return declaresMembers && options?.memberDepth !== 0;
9574
9632
  }
9575
9633
 
9634
+ // src/models/design-export.ts
9635
+ var import_zod9 = require("zod");
9636
+ var DESIGN_FORMAT = "wairon-design";
9637
+ var DESIGN_FORMAT_VERSION = "1.0";
9638
+ var DESIGN_APPROVALS = ["locked", "stale", "unlocked", "unjudged"];
9639
+ var DesignApprovalSchema = import_zod9.z.enum(DESIGN_APPROVALS);
9640
+ var DESIGN_DEPENDENCY_ROLES = ["member", "external"];
9641
+ var DesignDependencyRoleSchema = import_zod9.z.enum(DESIGN_DEPENDENCY_ROLES);
9642
+ var ExtSchema = import_zod9.z.record(import_zod9.z.unknown());
9643
+ var TypeExpressionSchema = import_zod9.z.lazy(
9644
+ () => import_zod9.z.object({
9645
+ form: import_zod9.z.enum(["primitive", "named", "list", "set", "map", "optional", "union", "async", "applied"]),
9646
+ name: import_zod9.z.string().optional(),
9647
+ args: import_zod9.z.array(TypeExpressionSchema)
9648
+ }).passthrough()
9649
+ );
9650
+ var DesignTypeRefSchema = import_zod9.z.object({
9651
+ text: import_zod9.z.string(),
9652
+ expression: TypeExpressionSchema.optional()
9653
+ }).passthrough();
9654
+ var DesignParamSchema = import_zod9.z.object({
9655
+ name: import_zod9.z.string(),
9656
+ type: DesignTypeRefSchema,
9657
+ optional: import_zod9.z.boolean(),
9658
+ description: import_zod9.z.string().optional()
9659
+ }).passthrough();
9660
+ var DesignFieldSchema = import_zod9.z.object({
9661
+ name: import_zod9.z.string(),
9662
+ type: DesignTypeRefSchema,
9663
+ optional: import_zod9.z.boolean(),
9664
+ description: import_zod9.z.string().optional(),
9665
+ key: import_zod9.z.string().optional(),
9666
+ references: import_zod9.z.string().optional()
9667
+ }).passthrough();
9668
+ var DeclaredInvocationSchema = MethodSignatureSchema.shape.invokedBy.unwrap().passthrough();
9669
+ var DesignMethodSchema = import_zod9.z.object({
9670
+ key: import_zod9.z.string(),
9671
+ name: import_zod9.z.string(),
9672
+ description: import_zod9.z.string().optional(),
9673
+ params: import_zod9.z.array(DesignParamSchema),
9674
+ returns: DesignTypeRefSchema,
9675
+ signature: import_zod9.z.string(),
9676
+ signatureType: import_zod9.z.string().optional(),
9677
+ effect: import_zod9.z.string().optional(),
9678
+ guarantees: import_zod9.z.array(import_zod9.z.string()),
9679
+ invokedBy: DeclaredInvocationSchema.optional(),
9680
+ endpoint: import_zod9.z.record(import_zod9.z.string()).optional(),
9681
+ formerly: import_zod9.z.array(import_zod9.z.string()),
9682
+ ext: ExtSchema.optional()
9683
+ }).passthrough();
9684
+ var DesignExportEntrySchema = import_zod9.z.object({
9685
+ publicName: import_zod9.z.string(),
9686
+ targetKind: import_zod9.z.string(),
9687
+ target: import_zod9.z.string(),
9688
+ audience: import_zod9.z.string().optional(),
9689
+ version: import_zod9.z.string().optional(),
9690
+ stability: import_zod9.z.string().optional()
9691
+ }).passthrough();
9692
+ var DesignDependencySchema = import_zod9.z.object({
9693
+ alias: import_zod9.z.string(),
9694
+ projectId: import_zod9.z.string(),
9695
+ role: DesignDependencyRoleSchema,
9696
+ digest: import_zod9.z.string().optional(),
9697
+ uses: import_zod9.z.array(import_zod9.z.string())
9698
+ }).passthrough();
9699
+ var DesignSourceSchema = import_zod9.z.object({
9700
+ projectId: import_zod9.z.string(),
9701
+ stateId: import_zod9.z.string(),
9702
+ approved: import_zod9.z.boolean(),
9703
+ approval: DesignApprovalSchema
9704
+ }).passthrough();
9705
+ var DesignProjectSchema = import_zod9.z.object({
9706
+ name: import_zod9.z.string(),
9707
+ vision: import_zod9.z.string(),
9708
+ boundaries: import_zod9.z.array(import_zod9.z.string()),
9709
+ requirements: import_zod9.z.array(import_zod9.z.string()),
9710
+ targetLanguage: import_zod9.z.string().optional(),
9711
+ exports: import_zod9.z.array(DesignExportEntrySchema)
9712
+ }).passthrough();
9713
+ var DesignSubsystemSchema = import_zod9.z.object({
9714
+ key: import_zod9.z.string(),
9715
+ name: import_zod9.z.string(),
9716
+ description: import_zod9.z.string(),
9717
+ status: import_zod9.z.string(),
9718
+ profile: import_zod9.z.string().optional(),
9719
+ targetLanguage: import_zod9.z.string().optional(),
9720
+ lifecycle: import_zod9.z.array(LifecycleEntrypointSchema.passthrough()),
9721
+ exports: import_zod9.z.array(DesignExportEntrySchema),
9722
+ trustedLinks: import_zod9.z.array(import_zod9.z.string()),
9723
+ ext: ExtSchema.optional()
9724
+ }).passthrough();
9725
+ var DesignComponentSchema = import_zod9.z.object({
9726
+ key: import_zod9.z.string(),
9727
+ name: import_zod9.z.string(),
9728
+ description: import_zod9.z.string(),
9729
+ status: import_zod9.z.string(),
9730
+ subsystem: import_zod9.z.string(),
9731
+ stereotype: import_zod9.z.string(),
9732
+ variant: import_zod9.z.string().optional(),
9733
+ dependencyClass: import_zod9.z.string().optional(),
9734
+ durability: import_zod9.z.string().optional(),
9735
+ portalType: import_zod9.z.string().optional(),
9736
+ owns: import_zod9.z.array(import_zod9.z.string()),
9737
+ dependsOn: import_zod9.z.array(import_zod9.z.string()),
9738
+ emits: import_zod9.z.array(EventBindingSchema.passthrough()),
9739
+ subscribesTo: import_zod9.z.array(EventBindingSchema.passthrough()),
9740
+ auth: PortalAuthSchema.passthrough().optional(),
9741
+ basePath: import_zod9.z.string().optional(),
9742
+ dispatch: import_zod9.z.array(DispatchBindingSchema.passthrough()),
9743
+ /** A listener's mounts as declared, each portal as a key: entrypoint facts. */
9744
+ mounts: import_zod9.z.array(PortalMountSchema.passthrough()),
9745
+ /** The pack-declared patterns the component realizes, as declared. */
9746
+ patterns: import_zod9.z.array(PatternRefSchema.passthrough()),
9747
+ /** The opaque external references the component documents, as declared. */
9748
+ externalLinks: import_zod9.z.array(ExternalLinkSchema.passthrough()),
9749
+ formerly: import_zod9.z.array(import_zod9.z.string()),
9750
+ ext: ExtSchema.optional()
9751
+ }).passthrough();
9752
+ var DesignInterfaceSchema = import_zod9.z.object({
9753
+ key: import_zod9.z.string(),
9754
+ component: import_zod9.z.string(),
9755
+ name: import_zod9.z.string(),
9756
+ description: import_zod9.z.string(),
9757
+ status: import_zod9.z.string(),
9758
+ methods: import_zod9.z.array(DesignMethodSchema),
9759
+ formerly: import_zod9.z.array(import_zod9.z.string()),
9760
+ ext: ExtSchema.optional()
9761
+ }).passthrough();
9762
+ var DesignMethodBodySchema = import_zod9.z.object({
9763
+ method: import_zod9.z.string(),
9764
+ detail: import_zod9.z.string(),
9765
+ intent: import_zod9.z.string().optional(),
9766
+ calls: import_zod9.z.array(import_zod9.z.string()),
9767
+ narrative: import_zod9.z.array(NarrativeStepSchema.passthrough())
9768
+ }).passthrough();
9769
+ var DesignImplementationSchema = import_zod9.z.object({
9770
+ key: import_zod9.z.string(),
9771
+ contract: import_zod9.z.string(),
9772
+ component: import_zod9.z.string(),
9773
+ name: import_zod9.z.string(),
9774
+ description: import_zod9.z.string(),
9775
+ status: import_zod9.z.string(),
9776
+ technologies: import_zod9.z.array(import_zod9.z.string()),
9777
+ sourcePath: import_zod9.z.string().optional(),
9778
+ methods: import_zod9.z.array(DesignMethodBodySchema),
9779
+ formerly: import_zod9.z.array(import_zod9.z.string()),
9780
+ ext: ExtSchema.optional()
9781
+ }).passthrough();
9782
+ var DesignTypeSchema = import_zod9.z.object({
9783
+ key: import_zod9.z.string(),
9784
+ kind: import_zod9.z.string(),
9785
+ name: import_zod9.z.string(),
9786
+ description: import_zod9.z.string().optional(),
9787
+ status: import_zod9.z.string().optional(),
9788
+ fields: import_zod9.z.array(DesignFieldSchema),
9789
+ methods: import_zod9.z.array(DesignMethodSchema),
9790
+ params: import_zod9.z.array(DesignParamSchema),
9791
+ returns: DesignTypeRefSchema.optional(),
9792
+ values: import_zod9.z.array(EnumValueSchema.passthrough()),
9793
+ holds: import_zod9.z.string().optional(),
9794
+ invariants: import_zod9.z.array(InvariantSchema.passthrough()),
9795
+ componentClass: import_zod9.z.string().optional(),
9796
+ database: import_zod9.z.string().optional(),
9797
+ table: import_zod9.z.string().optional(),
9798
+ linkedEntity: import_zod9.z.string().optional(),
9799
+ formerly: import_zod9.z.array(import_zod9.z.string()),
9800
+ ext: ExtSchema.optional()
9801
+ }).passthrough();
9802
+ var DesignExportSchema = import_zod9.z.object({
9803
+ format: import_zod9.z.literal(DESIGN_FORMAT),
9804
+ formatVersion: import_zod9.z.string().regex(/^\d+\.\d+$/),
9805
+ generator: import_zod9.z.string(),
9806
+ source: DesignSourceSchema,
9807
+ project: DesignProjectSchema,
9808
+ dependencies: import_zod9.z.array(DesignDependencySchema),
9809
+ subsystems: import_zod9.z.array(DesignSubsystemSchema),
9810
+ components: import_zod9.z.array(DesignComponentSchema),
9811
+ interfaces: import_zod9.z.array(DesignInterfaceSchema),
9812
+ implementations: import_zod9.z.array(DesignImplementationSchema),
9813
+ types: import_zod9.z.array(DesignTypeSchema)
9814
+ }).passthrough();
9815
+
9576
9816
  // src/core/narrative-labels.ts
9577
9817
  var SCALAR_REFS = [
9578
9818
  ["onTrueLabel", "onTrueStep"],
@@ -14786,7 +15026,7 @@ var MODEL = __MODEL_JSON__;
14786
15026
 
14787
15027
  // src/core/surfaces.ts
14788
15028
  var fs9 = __toESM(require("fs"));
14789
- var path13 = __toESM(require("path"));
15029
+ var path14 = __toESM(require("path"));
14790
15030
 
14791
15031
  // src/utils/filenames.ts
14792
15032
  function safeFilenamePart(value) {
@@ -14934,10 +15174,477 @@ function unpin(alias) {
14934
15174
  // src/core/openapi.ts
14935
15175
  var yaml2 = __toESM(require("js-yaml"));
14936
15176
 
15177
+ // src/config/defaults.ts
15178
+ var os2 = __toESM(require("os"));
15179
+ var path13 = __toESM(require("path"));
15180
+ var DEFAULT_TARGET_DIRS = {
15181
+ claude: ".claude/agents",
15182
+ gemini: ".gemini/agents",
15183
+ agy: ".gemini/agents",
15184
+ cursor: ".cursor/rules",
15185
+ copilot: ".github/prompts",
15186
+ codex: ".codex/agents"
15187
+ };
15188
+ function defaultTargetConfig(type) {
15189
+ return {
15190
+ type,
15191
+ outputDir: DEFAULT_TARGET_DIRS[type],
15192
+ enabled: true
15193
+ };
15194
+ }
15195
+ var WAIRON_VERSION = "5.1.1-dev.98";
15196
+ var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
15197
+ var ARCHITECT_AGENT_ID = "agent-architect";
15198
+ var ARCHITECT_TEMPLATE_ID = "architect";
15199
+ function globalTemplatesDir(projectOverride) {
15200
+ if (process.env.WAIRON_TEMPLATES_DIR) {
15201
+ return process.env.WAIRON_TEMPLATES_DIR;
15202
+ }
15203
+ if (projectOverride) {
15204
+ return projectOverride;
15205
+ }
15206
+ return path13.join(os2.homedir(), ".wairon", "templates");
15207
+ }
15208
+ var BACKEND_COMMANDS = {
15209
+ claude: "claude",
15210
+ gemini: "gemini"
15211
+ };
15212
+ function backendCommand(backend) {
15213
+ return BACKEND_COMMANDS[backend] ?? backend;
15214
+ }
15215
+ var SUPPORTED_ALIASES = ["wai"];
15216
+ var SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
15217
+ "node_modules",
15218
+ "dist",
15219
+ "build",
15220
+ "out",
15221
+ ".git",
15222
+ ".cache",
15223
+ "coverage",
15224
+ "__pycache__",
15225
+ ".venv",
15226
+ "venv",
15227
+ "target",
15228
+ // Rust
15229
+ "vendor"
15230
+ ]);
15231
+
15232
+ // src/core/design-export.ts
15233
+ var NoSystemSpecError = class extends Error {
15234
+ constructor() {
15235
+ super("no-system: the tree has no L0 system spec to export (.wai/specs holds no system spec).");
15236
+ this.code = "no-system";
15237
+ this.name = "NoSystemSpecError";
15238
+ }
15239
+ };
15240
+ var isOwn = (spec) => !spec.id.includes("::");
15241
+ var byKey = (a, b) => compareOrdinal(a.key, b.key);
15242
+ var KeyTable = class {
15243
+ constructor(components, interfaces, types, members = []) {
15244
+ this.components = /* @__PURE__ */ new Set();
15245
+ /** component key → the interfaces it declares. */
15246
+ this.interfacesOf = /* @__PURE__ */ new Map();
15247
+ this.typeRefCache = /* @__PURE__ */ new Map();
15248
+ /** bound key → `alias::publicName`, over every direct member. */
15249
+ this.publicNames = /* @__PURE__ */ new Map();
15250
+ /** alias → the public names this projection wrote a reference to. */
15251
+ this.used = /* @__PURE__ */ new Map();
15252
+ for (const m of members) for (const [bound2, name] of m.names) if (!this.publicNames.has(bound2)) this.publicNames.set(bound2, name);
15253
+ for (const c of components) this.components.add(c.id);
15254
+ for (const i of [...interfaces].sort((a, b) => compareOrdinal(a.id, b.id))) {
15255
+ const list = this.interfacesOf.get(i.component) ?? [];
15256
+ list.push(i);
15257
+ this.interfacesOf.set(i.component, list);
15258
+ }
15259
+ this.types = [...types].sort((a, b) => compareOrdinal(qualifiedTypeId(a), qualifiedTypeId(b)));
15260
+ }
15261
+ /** A contract method's key: `<interface key>.<name>` on the first of the component's interfaces declaring it, else the name as written. */
15262
+ methodKey(component, method) {
15263
+ if (!component) return method;
15264
+ const intf = (this.interfacesOf.get(component) ?? []).find((i) => i.methods.some((m) => m.name === method));
15265
+ return intf ? `${intf.id}.${method}` : method;
15266
+ }
15267
+ /** Whether `component.method` names a contract method of an own component — a method signature source. */
15268
+ isMethodSource(value) {
15269
+ const dot = value.lastIndexOf(".");
15270
+ if (dot <= 0 || dot === value.length - 1) return false;
15271
+ const head2 = value.slice(0, dot);
15272
+ const tail = value.slice(dot + 1);
15273
+ return this.components.has(head2) && (this.interfacesOf.get(head2) ?? []).some((i) => i.methods.some((m) => m.name === tail));
15274
+ }
15275
+ /**
15276
+ * The key of the own type a written name resolves to — same subsystem first,
15277
+ * then system-level, then any, ordinal by key within a rank — or null when
15278
+ * no own type answers to it (a generic parameter, or a name in another project).
15279
+ */
15280
+ typeKey(name, owner, kind) {
15281
+ const cacheKey = `${owner ?? ""}|${kind ?? ""}|${name}`;
15282
+ if (this.typeRefCache.has(cacheKey)) return this.typeRefCache.get(cacheKey);
15283
+ const rank = (t) => t.subsystem === owner ? 0 : t.subsystem === void 0 ? 1 : 2;
15284
+ const hit = this.types.filter((t) => (kind === void 0 || t.kind === kind) && (t.id === name || qualifiedTypeId(t) === name || typeMatchesRef(t, name))).sort((a, b) => rank(a) - rank(b))[0];
15285
+ const key = hit ? qualifiedTypeId(hit) : null;
15286
+ this.typeRefCache.set(cacheKey, key);
15287
+ return key;
15288
+ }
15289
+ /** A reference to a type field (`Type.field`) or a type, resolved to its key; as written when it resolves to nothing. */
15290
+ typeFieldRef(ref, owner) {
15291
+ const whole = this.typeKey(ref, owner);
15292
+ if (whole) return whole;
15293
+ const dot = ref.lastIndexOf(".");
15294
+ if (dot > 0) {
15295
+ const head2 = this.typeKey(ref.slice(0, dot), owner);
15296
+ if (head2) return `${head2}.${ref.slice(dot + 1)}`;
15297
+ const outside = this.external(ref.slice(0, dot));
15298
+ if (outside !== ref.slice(0, dot)) return `${outside}.${ref.slice(dot + 1)}`;
15299
+ }
15300
+ return this.external(ref);
15301
+ }
15302
+ /**
15303
+ * A reference as a consumer resolves it: a bound key of an item a direct
15304
+ * member exports as `alias::publicName` (recorded as used), anything else as
15305
+ * written — an own key, an external's reference (already `alias::name`), or
15306
+ * one binding no exported name, which the gate reports.
15307
+ */
15308
+ external(ref) {
15309
+ const name = this.publicNames.get(ref);
15310
+ if (name === void 0) return ref;
15311
+ const cut = name.indexOf("::");
15312
+ const alias = name.slice(0, cut);
15313
+ const set = this.used.get(alias) ?? /* @__PURE__ */ new Set();
15314
+ set.add(name.slice(cut + 2));
15315
+ this.used.set(alias, set);
15316
+ return name;
15317
+ }
15318
+ /** A component reference: an own component's key, or another project's item by its public name. */
15319
+ componentRef(ref) {
15320
+ return this.components.has(ref) ? ref : this.external(ref);
15321
+ }
15322
+ };
15323
+ function resolveExpression(expr, keys, owner) {
15324
+ const args = expr.args.map((a) => resolveExpression(a, keys, owner));
15325
+ if ((expr.form === "named" || expr.form === "applied") && expr.name !== void 0) {
15326
+ return { form: expr.form, name: keys.typeKey(expr.name, owner) ?? keys.external(expr.name), args };
15327
+ }
15328
+ return expr.name !== void 0 ? { form: expr.form, name: expr.name, args } : { form: expr.form, args };
15329
+ }
15330
+ function typeRef(text3, position, keys, owner) {
15331
+ const parse = parseTypeExpression(text3, position);
15332
+ if (!parse.expression) return { text: text3 };
15333
+ const expression = resolveExpression(parse.expression, keys, owner);
15334
+ return { text: canonicalTypeText(expression), expression };
15335
+ }
15336
+ function projectParams(params, position, keys, owner) {
15337
+ return (params ?? []).map((p) => ({
15338
+ name: p.name,
15339
+ type: typeRef(p.type, position, keys, owner),
15340
+ optional: p.optional === true,
15341
+ ...p.description !== void 0 ? { description: p.description } : {}
15342
+ }));
15343
+ }
15344
+ function exportEntry(e, keys) {
15345
+ const target = e.kind === "type" ? { targetKind: "type", target: keys.typeKey(String(e.typeDef), e.source) ?? keys.external(String(e.typeDef)) } : e.interface ? { targetKind: "interface", target: keys.external(e.interface) } : { targetKind: "component", target: keys.componentRef(String(e.component)) };
15346
+ return {
15347
+ publicName: e.publicName,
15348
+ ...target,
15349
+ ...e.audience !== void 0 ? { audience: e.audience } : {},
15350
+ ...e.version !== void 0 ? { version: e.version } : {},
15351
+ ...e.stability !== void 0 ? { stability: e.stability } : {}
15352
+ };
15353
+ }
15354
+ function exportRows(entries, keys) {
15355
+ return entries.map((e) => exportEntry(e, keys)).sort((a, b) => compareOrdinal(a.publicName, b.publicName) || compareOrdinal(`${a.targetKind}:${a.target}`, `${b.targetKind}:${b.target}`));
15356
+ }
15357
+ var boundaryText = (b) => typeof b === "string" ? b : b.description ? `${b.name}: ${b.description}` : b.name;
15358
+ var requirementText = (r) => typeof r === "string" ? r : r.description;
15359
+ function projectSection(system, table, keys) {
15360
+ return {
15361
+ name: system.name,
15362
+ vision: system.vision,
15363
+ boundaries: system.boundaries.map(boundaryText),
15364
+ requirements: system.globalRequirements.map(requirementText),
15365
+ ...system.targetLanguage !== void 0 ? { targetLanguage: system.targetLanguage } : {},
15366
+ exports: exportRows(table, keys)
15367
+ };
15368
+ }
15369
+ function dependency(binding, lock, keys) {
15370
+ const alias = binding.external.alias;
15371
+ const digest3 = lock?.externals[alias]?.digest;
15372
+ return {
15373
+ alias,
15374
+ projectId: binding.external.project,
15375
+ role: binding.external.role,
15376
+ ...digest3 !== void 0 ? { digest: digest3 } : {},
15377
+ uses: [.../* @__PURE__ */ new Set([...(binding.usage?.used ?? []).map((u) => u.publicName), ...keys.used.get(alias) ?? []])].sort(compareOrdinal)
15378
+ };
15379
+ }
15380
+ function memberDependency(member, lock, keys) {
15381
+ const digest3 = lock?.externals[member.alias]?.digest;
15382
+ return {
15383
+ alias: member.alias,
15384
+ projectId: member.projectId,
15385
+ role: "member",
15386
+ ...digest3 !== void 0 ? { digest: digest3 } : {},
15387
+ uses: [...keys.used.get(member.alias) ?? []].sort(compareOrdinal)
15388
+ };
15389
+ }
15390
+ function directMembers(family) {
15391
+ return family.nodes.filter((n) => n.parent === "" && n.namespace !== "").map((n) => {
15392
+ const alias = n.mountAlias ?? n.namespace;
15393
+ const names = /* @__PURE__ */ new Map();
15394
+ const bound2 = (key) => {
15395
+ const local = key.startsWith(`${n.namespace}::`) ? key : `${n.namespace}::${key}`;
15396
+ const last = `${n.namespace}::${key.split("::").pop() ?? key}`;
15397
+ return [.../* @__PURE__ */ new Set([local, last])];
15398
+ };
15399
+ const rows = [...resolveProjectExports(n.namespace).entries].sort((a, b) => compareOrdinal(a.publicName, b.publicName));
15400
+ for (const e of rows) {
15401
+ const name = `${alias}::${e.publicName}`;
15402
+ const targets = e.kind === "type" ? [e.typeDef] : e.interface !== void 0 ? [e.interface, e.component] : [e.component];
15403
+ for (const target of targets) {
15404
+ if (target === void 0) continue;
15405
+ for (const key of bound2(target)) if (!names.has(key)) names.set(key, name);
15406
+ }
15407
+ }
15408
+ return { alias, projectId: n.id ?? alias, names };
15409
+ }).sort((a, b) => compareOrdinal(a.alias, b.alias));
15410
+ }
15411
+ function subsystemSection(s, table, keys) {
15412
+ return {
15413
+ key: s.id,
15414
+ name: s.name,
15415
+ description: s.description,
15416
+ status: s.status,
15417
+ ...s.profile !== void 0 ? { profile: s.profile } : {},
15418
+ ...s.targetLanguage !== void 0 ? { targetLanguage: s.targetLanguage } : {},
15419
+ lifecycle: (s.lifecycle ?? []).map((l) => ({ ...l, component: keys.componentRef(l.component) })),
15420
+ exports: exportRows(table, keys),
15421
+ trustedLinks: s.trustedLinks.map((t) => t.subsystem),
15422
+ ...s.ext !== void 0 ? { ext: s.ext } : {}
15423
+ };
15424
+ }
15425
+ function componentSection(c, keys) {
15426
+ return {
15427
+ key: c.id,
15428
+ name: c.name,
15429
+ description: c.description,
15430
+ status: c.status,
15431
+ subsystem: c.subsystem,
15432
+ stereotype: c.componentType,
15433
+ ...c.variant !== void 0 ? { variant: c.variant } : {},
15434
+ ...c.dependencyClass !== void 0 ? { dependencyClass: c.dependencyClass } : {},
15435
+ ...c.durability !== void 0 ? { durability: c.durability } : {},
15436
+ ...c.portalType !== void 0 ? { portalType: c.portalType } : {},
15437
+ owns: c.owns.map((o) => keys.componentRef(o)),
15438
+ dependsOn: c.dependsOn.map((d) => keys.componentRef(d)),
15439
+ emits: (c.emits ?? []).map((e) => ({ ...e })),
15440
+ subscribesTo: (c.subscribesTo ?? []).map((e) => ({ ...e })),
15441
+ ...c.auth !== void 0 ? { auth: c.auth } : {},
15442
+ ...c.basePath !== void 0 ? { basePath: c.basePath } : {},
15443
+ dispatch: (c.dispatch ?? []).map((d) => ({ ...d, component: keys.componentRef(d.component) })),
15444
+ mounts: (c.mounts ?? []).map((m) => ({ ...m, portal: keys.componentRef(m.portal) })),
15445
+ patterns: (c.patterns ?? []).map((p) => ({ ...p })),
15446
+ externalLinks: (c.externalLinks ?? []).map((l) => ({ ...l })),
15447
+ formerly: [...c.previousIds ?? []],
15448
+ ...c.ext !== void 0 ? { ext: c.ext } : {}
15449
+ };
15450
+ }
15451
+ function contractMethod(intf, m, keys, owner) {
15452
+ const signatureType = m.signatureFrom !== void 0 && !keys.isMethodSource(m.signatureFrom) ? keys.typeKey(m.signatureFrom, owner, "signature") ?? void 0 : void 0;
15453
+ return {
15454
+ key: `${intf.id}.${m.name}`,
15455
+ name: m.name,
15456
+ description: m.description,
15457
+ params: projectParams(m.params, "param", keys, owner),
15458
+ returns: typeRef(m.returns, "returns", keys, owner),
15459
+ signature: m.signature,
15460
+ ...signatureType !== void 0 ? { signatureType } : {},
15461
+ ...m.effect !== void 0 ? { effect: m.effect } : {},
15462
+ guarantees: [...m.guarantees ?? []],
15463
+ ...m.invokedBy !== void 0 ? { invokedBy: { ...m.invokedBy } } : {},
15464
+ ...m.endpoint !== void 0 ? { endpoint: endpointFields(m.endpoint) } : {},
15465
+ formerly: [...m.previousNames ?? []],
15466
+ ...m.ext !== void 0 ? { ext: m.ext } : {}
15467
+ };
15468
+ }
15469
+ function endpointFields(endpoint) {
15470
+ const out = {};
15471
+ for (const [k, v] of Object.entries(endpoint)) if (v !== void 0) out[k] = String(v);
15472
+ return out;
15473
+ }
15474
+ function interfaceSection(intf, keys, owner) {
15475
+ return {
15476
+ key: intf.id,
15477
+ component: intf.component,
15478
+ name: intf.name,
15479
+ description: intf.description,
15480
+ status: intf.status,
15481
+ methods: intf.methods.map((m) => contractMethod(intf, m, keys, owner)),
15482
+ formerly: [...intf.previousIds ?? []],
15483
+ ...intf.ext !== void 0 ? { ext: intf.ext } : {}
15484
+ };
15485
+ }
15486
+ function stepWithKeys(step, keys) {
15487
+ const out = { ...step };
15488
+ if (step.targetMethod !== void 0) out.targetMethod = keys.methodKey(step.targetComponent, step.targetMethod);
15489
+ if (step.targetComponent !== void 0) out.targetComponent = keys.componentRef(step.targetComponent);
15490
+ const from = step.auth?.from;
15491
+ if (from !== void 0 && from.startsWith("component:")) {
15492
+ out.auth = { ...step.auth, from: `component:${keys.componentRef(from.slice("component:".length))}` };
15493
+ }
15494
+ return out;
15495
+ }
15496
+ function callKey(ref, keys) {
15497
+ const dot = ref.lastIndexOf(".");
15498
+ if (dot <= 0) return ref;
15499
+ const key = keys.methodKey(ref.slice(0, dot), ref.slice(dot + 1));
15500
+ return key.includes(".") ? key : `${keys.componentRef(ref.slice(0, dot))}.${ref.slice(dot + 1)}`;
15501
+ }
15502
+ function implementationSection(impl, contract, component, keys) {
15503
+ const methods = impl.methods.map((m) => ({
15504
+ method: `${impl.contract}.${m.name}`,
15505
+ detail: effectiveDetail(m, impl, component).level,
15506
+ ...m.intent !== void 0 ? { intent: m.intent } : {},
15507
+ calls: (m.calls ?? []).map((c) => callKey(c, keys)),
15508
+ narrative: m.narrative.map((s) => stepWithKeys(s, keys))
15509
+ }));
15510
+ return {
15511
+ key: impl.id,
15512
+ contract: impl.contract,
15513
+ component: contract?.component ?? component?.id ?? "",
15514
+ name: impl.name,
15515
+ description: impl.description,
15516
+ status: impl.status,
15517
+ technologies: (impl.technologies ?? []).map(technologyName),
15518
+ ...impl.sourcePath !== void 0 ? { sourcePath: impl.sourcePath } : {},
15519
+ methods,
15520
+ formerly: [...impl.previousIds ?? []],
15521
+ ...impl.ext !== void 0 ? { ext: impl.ext } : {}
15522
+ };
15523
+ }
15524
+ function typeSection(t, keys) {
15525
+ const key = qualifiedTypeId(t);
15526
+ const owner = t.subsystem;
15527
+ return {
15528
+ key,
15529
+ kind: t.kind,
15530
+ name: t.name,
15531
+ ...t.description !== void 0 ? { description: t.description } : {},
15532
+ fields: t.fields.map((f) => ({
15533
+ name: f.name,
15534
+ type: typeRef(f.type, "field", keys, owner),
15535
+ optional: f.optional === true,
15536
+ ...f.description !== void 0 ? { description: f.description } : {},
15537
+ ...f.key !== void 0 ? { key: f.key } : {},
15538
+ ...f.references !== void 0 ? { references: keys.typeFieldRef(f.references, owner) } : {}
15539
+ })),
15540
+ methods: t.methods.map((m) => ({
15541
+ key: `${key}.${m.name}`,
15542
+ name: m.name,
15543
+ ...m.description !== void 0 ? { description: m.description } : {},
15544
+ params: projectParams(m.params, "type-method-param", keys, owner),
15545
+ returns: typeRef(m.returns, "type-method-returns", keys, owner),
15546
+ signature: m.signature,
15547
+ guarantees: [],
15548
+ formerly: []
15549
+ })),
15550
+ params: t.kind === "signature" ? projectParams(t.params, "signature-param", keys, owner) : [],
15551
+ ...t.kind === "signature" && t.returns !== void 0 ? { returns: typeRef(t.returns, "signature-returns", keys, owner) } : {},
15552
+ values: (t.values ?? []).map((v) => ({ ...v })),
15553
+ ...t.holds !== void 0 ? { holds: t.holds } : {},
15554
+ invariants: (t.invariants ?? []).map((i) => ({ ...i })),
15555
+ ...t.componentClass !== void 0 ? { componentClass: keys.componentRef(t.componentClass) } : {},
15556
+ ...t.database !== void 0 ? { database: t.database } : {},
15557
+ ...t.table !== void 0 ? { table: t.table } : {},
15558
+ ...t.linkedEntity !== void 0 ? { linkedEntity: keys.typeKey(t.linkedEntity, owner) ?? keys.external(t.linkedEntity) } : {},
15559
+ formerly: [...t.previousIds ?? []],
15560
+ ...t.ext !== void 0 ? { ext: t.ext } : {}
15561
+ };
15562
+ }
15563
+ function sortedKeys(value) {
15564
+ if (Array.isArray(value)) return value.map(sortedKeys);
15565
+ if (value && typeof value === "object") {
15566
+ const src = value;
15567
+ const out = {};
15568
+ for (const k of Object.keys(src).sort(compareOrdinal)) {
15569
+ if (src[k] !== void 0) out[k] = sortedKeys(src[k]);
15570
+ }
15571
+ return out;
15572
+ }
15573
+ return value;
15574
+ }
15575
+ function projectIdOf(system) {
15576
+ try {
15577
+ const config = loadProjectConfig();
15578
+ return (config ? effectiveProjectId(config) : null) ?? system.name;
15579
+ } catch {
15580
+ return system.name;
15581
+ }
15582
+ }
15583
+ function exportDesign(approval) {
15584
+ const system = loadSystemSpec();
15585
+ if (!system) throw new NoSystemSpecError();
15586
+ const subsystems = loadSubsystemSpecs().filter(isOwn);
15587
+ const components = loadComponentSpecs().filter(isOwn);
15588
+ const interfaces = loadInterfaceSpecs().filter(isOwn);
15589
+ const implementations = loadImplementationSpecs().filter(isOwn);
15590
+ const types = loadTypeSpecs().filter(isOwn);
15591
+ const projectTable = resolveProjectExports();
15592
+ const subsystemTables = new Map(subsystems.map((s) => [s.id, resolveSubsystemExports(s.id).entries]));
15593
+ const projectId = projectIdOf(system);
15594
+ const bindings = resolveDeclared();
15595
+ const members = directMembers(graph());
15596
+ let lock = null;
15597
+ try {
15598
+ lock = externalsRepository.readLock();
15599
+ } catch {
15600
+ lock = null;
15601
+ }
15602
+ const stateId = computeStateId();
15603
+ const state = approval ?? "unjudged";
15604
+ const source = {
15605
+ projectId,
15606
+ stateId: `${stateId.algorithm}:${stateId.digest}`,
15607
+ approval: state,
15608
+ approved: state === "locked"
15609
+ };
15610
+ const keys = new KeyTable(components, interfaces, types, members);
15611
+ const componentById = new Map(components.map((c) => [c.id, c]));
15612
+ const interfaceById = new Map(interfaces.map((i) => [i.id, i]));
15613
+ const ownerOf4 = (componentId) => componentId !== void 0 ? componentById.get(componentId)?.subsystem : void 0;
15614
+ const project = projectSection(system, projectTable.entries, keys);
15615
+ const subsystemSections = subsystems.map((s) => subsystemSection(s, subsystemTables.get(s.id) ?? [], keys)).sort(byKey);
15616
+ const componentSections = components.map((c) => componentSection(c, keys)).sort(byKey);
15617
+ const interfaceSections = interfaces.map((i) => interfaceSection(i, keys, ownerOf4(i.component))).sort(byKey);
15618
+ const implementationSections = implementations.map((impl) => {
15619
+ const contract = interfaceById.get(impl.contract);
15620
+ return implementationSection(impl, contract, contract ? componentById.get(contract.component) : void 0, keys);
15621
+ }).sort(byKey);
15622
+ const typeSections = types.map((t) => typeSection(t, keys)).sort(byKey);
15623
+ const externalAliases = new Set(bindings.map((b) => b.external.alias));
15624
+ const dependencies = [
15625
+ ...bindings.map((b) => dependency(b, lock, keys)),
15626
+ ...members.filter((m) => !externalAliases.has(m.alias)).map((m) => memberDependency(m, lock, keys))
15627
+ ].sort((a, b) => compareOrdinal(a.alias, b.alias));
15628
+ const design = {
15629
+ format: DESIGN_FORMAT,
15630
+ formatVersion: DESIGN_FORMAT_VERSION,
15631
+ generator: WAIRON_VERSION,
15632
+ source,
15633
+ project,
15634
+ dependencies,
15635
+ subsystems: subsystemSections,
15636
+ components: componentSections,
15637
+ interfaces: interfaceSections,
15638
+ implementations: implementationSections,
15639
+ types: typeSections
15640
+ };
15641
+ return sortedKeys(design);
15642
+ }
15643
+
14937
15644
  // src/core/surfaces.ts
14938
15645
  var SURFACES_DIRNAME = "surfaces";
14939
15646
  function surfacesDir(rootDir) {
14940
- return path13.join(rootDir, ".wai", SURFACES_DIRNAME);
15647
+ return path14.join(rootDir, ".wai", SURFACES_DIRNAME);
14941
15648
  }
14942
15649
  function audienceRank(audience) {
14943
15650
  const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
@@ -15016,7 +15723,7 @@ function boundProjectId() {
15016
15723
  }
15017
15724
  }
15018
15725
  function contractEntry(entry, comp, interfaces) {
15019
- const methods = interfaces.filter((i) => i.component === comp.id && (!entry.interface || i.id === entry.interface)).flatMap((i) => i.methods).map(({ signatureFrom: _source, ...method }) => method);
15726
+ const methods = interfaces.filter((i) => i.component === comp.id && (!entry.interface || i.id === entry.interface)).flatMap((i) => i.methods).map(({ signatureFrom: _source, previousNames: _trace, ...method }) => method);
15020
15727
  return {
15021
15728
  id: entry.publicName,
15022
15729
  name: entry.name ?? comp.name,
@@ -15101,7 +15808,7 @@ function listSnapshots() {
15101
15808
  for (const file of fs9.readdirSync(dir)) {
15102
15809
  if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
15103
15810
  try {
15104
- out.push(SurfaceSnapshotSchema.parse(readYamlFile(path13.join(dir, file))));
15811
+ out.push(SurfaceSnapshotSchema.parse(readYamlFile(path14.join(dir, file))));
15105
15812
  } catch {
15106
15813
  }
15107
15814
  }
@@ -15112,7 +15819,7 @@ function snapshotFilename(projectName) {
15112
15819
  }
15113
15820
  function removeSnapshot(projectName) {
15114
15821
  const dir = surfacesDir(getProjectRoot());
15115
- const direct = path13.join(dir, snapshotFilename(projectName));
15822
+ const direct = path14.join(dir, snapshotFilename(projectName));
15116
15823
  if (fs9.existsSync(direct)) {
15117
15824
  fs9.unlinkSync(direct);
15118
15825
  return true;
@@ -15120,7 +15827,7 @@ function removeSnapshot(projectName) {
15120
15827
  if (!fs9.existsSync(dir)) return false;
15121
15828
  for (const file of fs9.readdirSync(dir)) {
15122
15829
  if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
15123
- const p = path13.join(dir, file);
15830
+ const p = path14.join(dir, file);
15124
15831
  try {
15125
15832
  const snap = SurfaceSnapshotSchema.parse(readYamlFile(p));
15126
15833
  if (snap.projectName === projectName) {
@@ -15159,6 +15866,32 @@ function listPinnedExternals() {
15159
15866
  return { alias, project: entry.project, entry, snapshot };
15160
15867
  });
15161
15868
  }
15869
+ function withSortedKeys(value) {
15870
+ if (Array.isArray(value)) return value.map(withSortedKeys);
15871
+ if (value && typeof value === "object") {
15872
+ const src = value;
15873
+ const out = {};
15874
+ for (const k of Object.keys(src).sort(compareOrdinal)) if (src[k] !== void 0) out[k] = withSortedKeys(src[k]);
15875
+ return out;
15876
+ }
15877
+ return value;
15878
+ }
15879
+ function writeDesignTo(targetPath, design) {
15880
+ const resolved = path14.resolve(targetPath);
15881
+ try {
15882
+ fs9.mkdirSync(path14.dirname(resolved), { recursive: true });
15883
+ fs9.writeFileSync(resolved, `${JSON.stringify(withSortedKeys(design), null, 2)}
15884
+ `, "utf8");
15885
+ } catch (e) {
15886
+ throw new Error(`Cannot write the design export to ${resolved}: ${e.message}`);
15887
+ }
15888
+ return resolved;
15889
+ }
15890
+ function exportDesign2(outPath, approval) {
15891
+ const design = exportDesign(approval);
15892
+ if (outPath) writeDesignTo(outPath, design);
15893
+ return design;
15894
+ }
15162
15895
  function listFamilyPins() {
15163
15896
  const snapshots = listSnapshots();
15164
15897
  const pins = snapshots.filter((snapshot) => snapshot.origin === "generated").map((snapshot) => ({
@@ -15177,8 +15910,8 @@ var UnknownExternalAliasError = class extends Error {
15177
15910
  };
15178
15911
  var OUT_OF_REACH = "its root is outside the request's reach";
15179
15912
  function isWithinDir(dir, target) {
15180
- const rel2 = path13.relative(path13.resolve(dir), path13.resolve(target));
15181
- return rel2 === "" || !rel2.startsWith("..") && !path13.isAbsolute(rel2);
15913
+ const rel2 = path14.relative(path14.resolve(dir), path14.resolve(target));
15914
+ return rel2 === "" || !rel2.startsWith("..") && !path14.isAbsolute(rel2);
15182
15915
  }
15183
15916
  function producerUnreadable(external) {
15184
15917
  const directory = external.directory;
@@ -15431,6 +16164,9 @@ function listExternals() {
15431
16164
  }
15432
16165
 
15433
16166
  // src/core/surface-portal.ts
16167
+ function exportDesign3(outPath, approval) {
16168
+ return exportDesign2(outPath, approval);
16169
+ }
15434
16170
  function listSnapshots2() {
15435
16171
  return listSnapshots();
15436
16172
  }
@@ -15464,7 +16200,7 @@ function pinnedParent2() {
15464
16200
 
15465
16201
  // src/core/family-validation.ts
15466
16202
  var fs10 = __toESM(require("fs"));
15467
- var path14 = __toESM(require("path"));
16203
+ var path15 = __toESM(require("path"));
15468
16204
 
15469
16205
  // src/models/pack-impact.ts
15470
16206
  function packSettings(manifest, profile) {
@@ -15641,7 +16377,7 @@ function referencedOf(nodes) {
15641
16377
  if (e.sourceKind === "hosted") {
15642
16378
  const lookup2 = getHostedLookup();
15643
16379
  const root = lookup2 && e.hosted !== void 0 ? lookup2(e.hosted) : null;
15644
- if (root) directory = path14.resolve(root);
16380
+ if (root) directory = path15.resolve(root);
15645
16381
  else problem = lookup2 ? `the hosted member \`${e.hosted}\` is unknown or outside this request's reach` : `hosted-only member \`${e.hosted}\`: available only through the hosted server`;
15646
16382
  }
15647
16383
  if (directory !== void 0 && !fs10.existsSync(directory)) {
@@ -15705,7 +16441,7 @@ function notSelectedHint(left) {
15705
16441
  }
15706
16442
  function run(options) {
15707
16443
  const family = graph();
15708
- const root = path14.resolve(getProjectRoot());
16444
+ const root = path15.resolve(getProjectRoot());
15709
16445
  const ceiling = reachCeiling(root, options.family);
15710
16446
  const selected = selectProjects(family, options);
15711
16447
  const issues = [];
@@ -15925,7 +16661,7 @@ function pinOf(parent, alias, subject) {
15925
16661
  }
15926
16662
  function projectApprovals(depth) {
15927
16663
  const family = graph();
15928
- const root = path14.resolve(getProjectRoot());
16664
+ const root = path15.resolve(getProjectRoot());
15929
16665
  const limit = depth ?? Infinity;
15930
16666
  const selected = family.nodes.filter((n) => depthOf(family, n) <= limit);
15931
16667
  const directoryOf = new Map(family.nodes.map((n) => [n.namespace, n.directory]));
@@ -15978,7 +16714,7 @@ function projectApprovals(depth) {
15978
16714
  function requiredBy(key) {
15979
16715
  return key === "" ? "the family root" : `"${key}"`;
15980
16716
  }
15981
- function requirementText(requirement) {
16717
+ function requirementText2(requirement) {
15982
16718
  return `"${requirement.pack}" ${requirement.version}${requirement.profile ? ` (profile "${requirement.profile}")` : ""}`;
15983
16719
  }
15984
16720
  function isBelow(family, node, ancestor) {
@@ -16033,7 +16769,7 @@ function judgeAdoption(requiring, member, requirements) {
16033
16769
  const out = [];
16034
16770
  const who = `The member ${named(member)}`;
16035
16771
  for (const requirement of requirements) {
16036
- const wanted = `${requirementText(requirement)}, required by ${requiredBy(requiring)}`;
16772
+ const wanted = `${requirementText2(requirement)}, required by ${requiredBy(requiring)}`;
16037
16773
  const adopted = entryFor(config, loaded, requirement.pack);
16038
16774
  if (!adopted) {
16039
16775
  out.push(policyIssue("POLICY_NOT_ADOPTED", `${who} does not select the pack ${wanted}. Select it in the member's own configuration (\`wairon pack use ${requirement.pack}@<version> --pin\` at its root).`, member));
@@ -16125,69 +16861,12 @@ var fs12 = __toESM(require("fs"));
16125
16861
  var os3 = __toESM(require("os"));
16126
16862
  var path17 = __toESM(require("path"));
16127
16863
  var import_module = require("module");
16128
- var import_zod9 = require("zod");
16864
+ var import_zod10 = require("zod");
16129
16865
 
16130
16866
  // src/core/packstore.ts
16131
16867
  var crypto3 = __toESM(require("crypto"));
16132
16868
  var fs11 = __toESM(require("fs"));
16133
16869
  var path16 = __toESM(require("path"));
16134
-
16135
- // src/config/defaults.ts
16136
- var os2 = __toESM(require("os"));
16137
- var path15 = __toESM(require("path"));
16138
- var DEFAULT_TARGET_DIRS = {
16139
- claude: ".claude/agents",
16140
- gemini: ".gemini/agents",
16141
- agy: ".gemini/agents",
16142
- cursor: ".cursor/rules",
16143
- copilot: ".github/prompts",
16144
- codex: ".codex/agents"
16145
- };
16146
- function defaultTargetConfig(type) {
16147
- return {
16148
- type,
16149
- outputDir: DEFAULT_TARGET_DIRS[type],
16150
- enabled: true
16151
- };
16152
- }
16153
- var WAIRON_VERSION = "5.1.1-dev.96";
16154
- var GITHUB_REPO = "SYW-Apps/Waffle-AIron";
16155
- var ARCHITECT_AGENT_ID = "agent-architect";
16156
- var ARCHITECT_TEMPLATE_ID = "architect";
16157
- function globalTemplatesDir(projectOverride) {
16158
- if (process.env.WAIRON_TEMPLATES_DIR) {
16159
- return process.env.WAIRON_TEMPLATES_DIR;
16160
- }
16161
- if (projectOverride) {
16162
- return projectOverride;
16163
- }
16164
- return path15.join(os2.homedir(), ".wairon", "templates");
16165
- }
16166
- var BACKEND_COMMANDS = {
16167
- claude: "claude",
16168
- gemini: "gemini"
16169
- };
16170
- function backendCommand(backend) {
16171
- return BACKEND_COMMANDS[backend] ?? backend;
16172
- }
16173
- var SUPPORTED_ALIASES = ["wai"];
16174
- var SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
16175
- "node_modules",
16176
- "dist",
16177
- "build",
16178
- "out",
16179
- ".git",
16180
- ".cache",
16181
- "coverage",
16182
- "__pycache__",
16183
- ".venv",
16184
- "venv",
16185
- "target",
16186
- // Rust
16187
- "vendor"
16188
- ]);
16189
-
16190
- // src/core/packstore.ts
16191
16870
  var UNVERSIONED = "0.0.0-unversioned";
16192
16871
  var INSTALL_RECORD = ".install.yaml";
16193
16872
  var DIGEST_EXCLUDED = /* @__PURE__ */ new Set([INSTALL_RECORD, ".git", "node_modules", ".DS_Store"]);
@@ -16355,10 +17034,10 @@ function uninstallPack(name, version) {
16355
17034
  }
16356
17035
 
16357
17036
  // src/core/extensions.ts
16358
- var ProfileDefSchema = import_zod9.z.object({
16359
- family: import_zod9.z.enum(["backend-like", "frontend-like", "neutral"]).default("neutral"),
16360
- forbiddenStereotypes: import_zod9.z.array(import_zod9.z.object({ types: import_zod9.z.array(import_zod9.z.string()).min(1), reason: import_zod9.z.string().min(1) })).default([]),
16361
- discouragedStereotypes: import_zod9.z.array(import_zod9.z.object({ types: import_zod9.z.array(import_zod9.z.string()).min(1), reason: import_zod9.z.string().min(1) })).default([]),
17037
+ var ProfileDefSchema = import_zod10.z.object({
17038
+ family: import_zod10.z.enum(["backend-like", "frontend-like", "neutral"]).default("neutral"),
17039
+ forbiddenStereotypes: import_zod10.z.array(import_zod10.z.object({ types: import_zod10.z.array(import_zod10.z.string()).min(1), reason: import_zod10.z.string().min(1) })).default([]),
17040
+ discouragedStereotypes: import_zod10.z.array(import_zod10.z.object({ types: import_zod10.z.array(import_zod10.z.string()).min(1), reason: import_zod10.z.string().min(1) })).default([]),
16362
17041
  /**
16363
17042
  * Edge deltas — the ALLOW half of the profile-scoped dependency matrix. An
16364
17043
  * entry LICENSES intra-subsystem dependsOn edges the builtin stereotype
@@ -16368,20 +17047,20 @@ var ProfileDefSchema = import_zod9.z.object({
16368
17047
  * boundary rules and pattern containment are never relaxable. The DENY
16369
17048
  * half is a `forbid-edge` declarative assertion.
16370
17049
  */
16371
- allowedEdges: import_zod9.z.array(import_zod9.z.object({
16372
- from: import_zod9.z.array(import_zod9.z.string().min(1)).min(1),
16373
- to: import_zod9.z.array(import_zod9.z.string().min(1)).min(1),
16374
- reason: import_zod9.z.string().min(1)
17050
+ allowedEdges: import_zod10.z.array(import_zod10.z.object({
17051
+ from: import_zod10.z.array(import_zod10.z.string().min(1)).min(1),
17052
+ to: import_zod10.z.array(import_zod10.z.string().min(1)).min(1),
17053
+ reason: import_zod10.z.string().min(1)
16375
17054
  })).default([]),
16376
17055
  rules: RulesConfigSchema.partial().optional()
16377
17056
  });
16378
- var LanguagePackDefSchema = import_zod9.z.object({
16379
- unsupportedFlow: import_zod9.z.record(import_zod9.z.string()).default({}),
16380
- foreignBuiltins: import_zod9.z.array(import_zod9.z.string()).optional()
17057
+ var LanguagePackDefSchema = import_zod10.z.object({
17058
+ unsupportedFlow: import_zod10.z.record(import_zod10.z.string()).default({}),
17059
+ foreignBuiltins: import_zod10.z.array(import_zod10.z.string()).optional()
16381
17060
  });
16382
- var PackSkillSchema = import_zod9.z.object({
17061
+ var PackSkillSchema = import_zod10.z.object({
16383
17062
  /** A NEW skill, installed namespaced as `<pack-id>-<id>`. Mutually exclusive with `extends`. */
16384
- id: import_zod9.z.string().min(1).optional(),
17063
+ id: import_zod10.z.string().min(1).optional(),
16385
17064
  /**
16386
17065
  * EXTEND a builtin skill (`sdd-architect` | `sdd-narrative` | `sdd-auditor` |
16387
17066
  * `sdd-implement`) instead of standing beside it.
@@ -16393,90 +17072,90 @@ var PackSkillSchema = import_zod9.z.object({
16393
17072
  * appended under `## Platform: <pack>`; the builtin stays wairon's, so an
16394
17073
  * upgrade still updates it.
16395
17074
  */
16396
- extends: import_zod9.z.string().min(1).optional(),
16397
- source: import_zod9.z.string().min(1),
16398
- targets: import_zod9.z.array(import_zod9.z.string()).default([])
17075
+ extends: import_zod10.z.string().min(1).optional(),
17076
+ source: import_zod10.z.string().min(1),
17077
+ targets: import_zod10.z.array(import_zod10.z.string()).default([])
16399
17078
  }).refine((s) => s.id === void 0 !== (s.extends === void 0), {
16400
17079
  message: "a pack skill declares either `id` (a new skill) or `extends` (a section appended to a builtin), not both and not neither"
16401
17080
  });
16402
- var PackInstructionBlockSchema = import_zod9.z.union([
17081
+ var PackInstructionBlockSchema = import_zod10.z.union([
16403
17082
  // Scalar shorthand: `instructions: >- …` — the common case, unscoped.
16404
- import_zod9.z.string().min(1).transform((text3) => ({ text: text3 })),
16405
- import_zod9.z.object({
16406
- text: import_zod9.z.string().min(1),
16407
- profile: import_zod9.z.array(import_zod9.z.string().min(1)).min(1).optional()
17083
+ import_zod10.z.string().min(1).transform((text3) => ({ text: text3 })),
17084
+ import_zod10.z.object({
17085
+ text: import_zod10.z.string().min(1),
17086
+ profile: import_zod10.z.array(import_zod10.z.string().min(1)).min(1).optional()
16408
17087
  })
16409
17088
  ]);
16410
- var PackInstructionsSchema = import_zod9.z.preprocess(
17089
+ var PackInstructionsSchema = import_zod10.z.preprocess(
16411
17090
  (raw) => raw === void 0 || raw === null ? [] : Array.isArray(raw) ? raw : [raw],
16412
- import_zod9.z.array(PackInstructionBlockSchema)
17091
+ import_zod10.z.array(PackInstructionBlockSchema)
16413
17092
  );
16414
- var PatternDefSchema = import_zod9.z.object({
16415
- id: import_zod9.z.string().min(1),
16416
- version: import_zod9.z.string().min(1),
16417
- description: import_zod9.z.string().optional(),
16418
- metadata: import_zod9.z.record(import_zod9.z.unknown()).optional()
17093
+ var PatternDefSchema = import_zod10.z.object({
17094
+ id: import_zod10.z.string().min(1),
17095
+ version: import_zod10.z.string().min(1),
17096
+ description: import_zod10.z.string().optional(),
17097
+ metadata: import_zod10.z.record(import_zod10.z.unknown()).optional()
16419
17098
  });
16420
- var AssertionSelectorSchema = import_zod9.z.object({
16421
- componentType: import_zod9.z.array(import_zod9.z.string().min(1)).optional(),
16422
- profile: import_zod9.z.array(import_zod9.z.string().min(1)).optional(),
16423
- id: import_zod9.z.string().min(1).optional()
17099
+ var AssertionSelectorSchema = import_zod10.z.object({
17100
+ componentType: import_zod10.z.array(import_zod10.z.string().min(1)).optional(),
17101
+ profile: import_zod10.z.array(import_zod10.z.string().min(1)).optional(),
17102
+ id: import_zod10.z.string().min(1).optional()
16424
17103
  });
16425
17104
  var assertionBase = {
16426
17105
  /** Pack-local code; surfaced namespaced as <PACK_NAME>_<CODE>. */
16427
- code: import_zod9.z.string().min(1),
16428
- severity: import_zod9.z.enum(["warning", "error"]).default("warning"),
17106
+ code: import_zod10.z.string().min(1),
17107
+ severity: import_zod10.z.enum(["warning", "error"]).default("warning"),
16429
17108
  /** The doctrine, stated for the finding message. */
16430
- reason: import_zod9.z.string().min(1)
17109
+ reason: import_zod10.z.string().min(1)
16431
17110
  };
16432
- var PackAssertionSchema = import_zod9.z.discriminatedUnion("kind", [
16433
- import_zod9.z.object({
16434
- kind: import_zod9.z.literal("forbid-edge"),
17111
+ var PackAssertionSchema = import_zod10.z.discriminatedUnion("kind", [
17112
+ import_zod10.z.object({
17113
+ kind: import_zod10.z.literal("forbid-edge"),
16435
17114
  ...assertionBase,
16436
17115
  from: AssertionSelectorSchema,
16437
17116
  to: AssertionSelectorSchema,
16438
- relation: import_zod9.z.array(import_zod9.z.enum(["dependsOn", "owns"])).default(["dependsOn", "owns"])
17117
+ relation: import_zod10.z.array(import_zod10.z.enum(["dependsOn", "owns"])).default(["dependsOn", "owns"])
16439
17118
  }),
16440
- import_zod9.z.object({
16441
- kind: import_zod9.z.literal("require-field"),
17119
+ import_zod10.z.object({
17120
+ kind: import_zod10.z.literal("require-field"),
16442
17121
  ...assertionBase,
16443
17122
  on: AssertionSelectorSchema,
16444
- level: import_zod9.z.enum(["component", "interface", "implementation"]).default("component"),
17123
+ level: import_zod10.z.enum(["component", "interface", "implementation"]).default("component"),
16445
17124
  /** A top-level spec field name, or one `ext.*` path — nothing else is addressable. */
16446
- field: import_zod9.z.string().min(1),
17125
+ field: import_zod10.z.string().min(1),
16447
17126
  /** Optional closed value set (string equality). */
16448
- values: import_zod9.z.array(import_zod9.z.string()).optional()
17127
+ values: import_zod10.z.array(import_zod10.z.string()).optional()
16449
17128
  }),
16450
- import_zod9.z.object({
16451
- kind: import_zod9.z.literal("endpoint-shape"),
17129
+ import_zod10.z.object({
17130
+ kind: import_zod10.z.literal("endpoint-shape"),
16452
17131
  ...assertionBase,
16453
17132
  on: AssertionSelectorSchema,
16454
17133
  /** Optional transport allowlist. */
16455
- transport: import_zod9.z.array(import_zod9.z.string().min(1)).optional(),
17134
+ transport: import_zod10.z.array(import_zod10.z.string().min(1)).optional(),
16456
17135
  /** Optional anchored regex over the transport's address field (path/topic/command/…). */
16457
- pathPattern: import_zod9.z.string().min(1).optional()
17136
+ pathPattern: import_zod10.z.string().min(1).optional()
16458
17137
  })
16459
17138
  ]);
16460
17139
  function assertionFullCode(packName, code) {
16461
17140
  const norm = (s) => s.toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
16462
17141
  return `${norm(packName)}_${norm(code)}`;
16463
17142
  }
16464
- var DeclarativePackSchema = import_zod9.z.object({
16465
- name: import_zod9.z.string().min(1),
16466
- version: import_zod9.z.string().optional(),
16467
- profiles: import_zod9.z.record(ProfileDefSchema).default({}),
16468
- languages: import_zod9.z.record(LanguagePackDefSchema).default({}),
16469
- skills: import_zod9.z.array(PackSkillSchema).default([]),
16470
- patterns: import_zod9.z.array(PatternDefSchema).default([]),
17143
+ var DeclarativePackSchema = import_zod10.z.object({
17144
+ name: import_zod10.z.string().min(1),
17145
+ version: import_zod10.z.string().optional(),
17146
+ profiles: import_zod10.z.record(ProfileDefSchema).default({}),
17147
+ languages: import_zod10.z.record(LanguagePackDefSchema).default({}),
17148
+ skills: import_zod10.z.array(PackSkillSchema).default([]),
17149
+ patterns: import_zod10.z.array(PatternDefSchema).default([]),
16471
17150
  /** Declarative rule assertions — instances of closed kinds, hosted-safe. */
16472
- assertions: import_zod9.z.array(PackAssertionSchema).default([]),
17151
+ assertions: import_zod10.z.array(PackAssertionSchema).default([]),
16473
17152
  /**
16474
17153
  * Semantic guarantee tokens this pack adds to the builtin vocabulary
16475
17154
  * (SEMANTIC_GUARANTEES). Declaring a token makes it legal on L3 method
16476
17155
  * `guarantees` and narrative `assertsGuarantees`; referenced tokens outside
16477
17156
  * builtin + declared are flagged UNKNOWN_GUARANTEE by the validator.
16478
17157
  */
16479
- guarantees: import_zod9.z.array(import_zod9.z.string().min(1)).default([]),
17158
+ guarantees: import_zod10.z.array(import_zod10.z.string().min(1)).default([]),
16480
17159
  /**
16481
17160
  * Connecting-agent guidance appended to wairon's own MCP `initialize`
16482
17161
  * instructions, attributed to this pack, in pack load order.
@@ -16491,7 +17170,7 @@ var DeclarativePackSchema = import_zod9.z.object({
16491
17170
  * explicit in the new project's `project.yaml` where it is visible in review
16492
17171
  * and removable — never silent authority over projects that never mentioned it.
16493
17172
  */
16494
- applyByDefault: import_zod9.z.boolean().default(false)
17173
+ applyByDefault: import_zod10.z.boolean().default(false)
16495
17174
  });
16496
17175
  var EXTENDABLE_BUILTIN_SKILLS = ["sdd-architect", "sdd-narrative", "sdd-auditor", "sdd-implement", "sdd-delegate"];
16497
17176
  function skillExtendErrors(skills) {
@@ -17126,7 +17805,7 @@ function buildImportGraph(index, universe) {
17126
17805
  function buildOwnershipIndex(ctx) {
17127
17806
  const ownedBy2 = /* @__PURE__ */ new Map();
17128
17807
  for (const comp of ctx.components) {
17129
- if (isRetired(comp) || !isPattern(comp)) continue;
17808
+ if (isRetired(comp) || !(isPattern(comp) || comp.componentType === "Supervisor")) continue;
17130
17809
  for (const memberId of comp.owns) {
17131
17810
  const member = ctx.componentMap.get(memberId);
17132
17811
  if (!member || isPattern(member)) continue;
@@ -17911,6 +18590,66 @@ var namedScalarTypesRule = {
17911
18590
  }
17912
18591
  };
17913
18592
 
18593
+ // src/core/rules/integrity/rename-traces.ts
18594
+ var CODE = "RENAME_TRACE_CONFLICT";
18595
+ function namespaceOf(key) {
18596
+ const cut = key.lastIndexOf("::");
18597
+ return cut >= 0 ? key.slice(0, cut + 2) : "";
18598
+ }
18599
+ function judgeKind(ctx, noun, live, holders, qualify) {
18600
+ const claimed = /* @__PURE__ */ new Map();
18601
+ for (const holder of holders) {
18602
+ for (const entry of holder.trace) {
18603
+ const key = qualify(entry, holder);
18604
+ const other = claimed.get(key);
18605
+ if (live.has(key) && key !== holder.key) {
18606
+ report(ctx, holder, `${holder.label} lists "${entry}" in its rename trace, but a live ${noun} has that key \u2014 a consumer of the design export would read the live ${noun} as this one renamed. Rename the newcomer, or unset the trace entry and accept that a consumer reads a delete plus an add.`);
18607
+ } else if (live.has(key)) {
18608
+ report(ctx, holder, `${holder.label} lists its own key "${entry}" in its rename trace \u2014 a rename never records the name it keeps. Unset the entry.`);
18609
+ } else if (other && other !== holder) {
18610
+ report(ctx, holder, `${holder.label} and ${other.label} both list "${entry}" in their rename traces \u2014 a consumer holding the old key cannot tell which one it became. Unset the entry on the one that was not renamed from it.`);
18611
+ }
18612
+ if (!other) claimed.set(key, holder);
18613
+ }
18614
+ }
18615
+ }
18616
+ function report(ctx, holder, message) {
18617
+ if (!ctx.isSpecInScope(holder.specId)) return;
18618
+ ctx.addIssue("warning", CODE, message, holder.specId);
18619
+ }
18620
+ var inNamespace = (entry, holder) => entry.includes("::") ? entry : namespaceOf(holder.key) + entry;
18621
+ var renameTracesRule = {
18622
+ name: "rename-traces",
18623
+ judges: "design",
18624
+ description: "A rename trace (a spec's previousIds, a contract method's previousNames) names keys that no longer exist, and is what lets a consumer of the design export tell a rename from a delete plus an add; it must therefore be unambiguous. Reported: a trace entry equal to a live key of the same kind (a component, interface or implementation id; a type id within the same owner; `<interface>.<method>` of a declared method), and one former key claimed by two elements of the same kind. The rename tools and the gated write refuse both (id-retired, name-retired), so a finding means a hand edit; the message names both holders and the way out \u2014 rename the newcomer, or unset the trace entry and accept the delete plus an add a consumer will read.",
18625
+ codes: [
18626
+ { code: CODE, defaultSeverity: "warning", summary: "A rename-trace entry equals a live key of the same kind, or two elements claim one former key" }
18627
+ ],
18628
+ check(ctx) {
18629
+ const specHolders = (specs, noun) => specs.filter((s) => s.previousIds?.length).map((s) => ({ key: s.id, specId: s.id, label: `${noun} "${s.id}"`, trace: s.previousIds }));
18630
+ judgeKind(ctx, "component", new Set(ctx.components.map((c) => c.id)), specHolders(ctx.components, "Component"), inNamespace);
18631
+ judgeKind(ctx, "interface", new Set(ctx.interfaces.map((i) => i.id)), specHolders(ctx.interfaces, "Interface"), inNamespace);
18632
+ judgeKind(ctx, "implementation", new Set(ctx.implementations.map((i) => i.id)), specHolders(ctx.implementations, "Implementation"), inNamespace);
18633
+ judgeKind(
18634
+ ctx,
18635
+ "type",
18636
+ new Set(ctx.types.map((t) => qualifiedTypeId(t))),
18637
+ ctx.types.filter((t) => t.previousIds?.length).map((t) => ({ key: qualifiedTypeId(t), specId: t.id, label: `Type "${qualifiedTypeId(t)}"`, trace: t.previousIds })),
18638
+ inNamespace
18639
+ );
18640
+ const methodHolders = [];
18641
+ const liveMethods = /* @__PURE__ */ new Set();
18642
+ for (const intf of ctx.interfaces) {
18643
+ for (const m of intf.methods) {
18644
+ const key = `${intf.id}.${m.name}`;
18645
+ liveMethods.add(key);
18646
+ if (m.previousNames?.length) methodHolders.push({ key, specId: intf.id, label: `Method "${key}"`, trace: m.previousNames });
18647
+ }
18648
+ }
18649
+ judgeKind(ctx, "contract method", liveMethods, methodHolders, inNamespace);
18650
+ }
18651
+ };
18652
+
17914
18653
  // src/core/rules/integrity/public-surface-binding.ts
17915
18654
  var publicSurfaceBindingRule = {
17916
18655
  name: "public-surface-binding",
@@ -18423,10 +19162,10 @@ var projectBoundariesRule = {
18423
19162
  var lintAllowsRule = {
18424
19163
  name: "lint-allows",
18425
19164
  judges: "design",
18426
- description: "Per-spec lint suppressions (lint.allow) must name real issue codes and actually suppress a finding \u2014 unknown codes and stale allows are flagged. An allow covers exactly the occurrence it names: a finding that reports a site is silenced only by an allow whose `at` is that site, a finding that reports none only by an allow that names none, and an aggregating finding only by an allow whose `covers` lists every unit it reports \u2014 a unit nobody listed is named back as new instead of inheriting a decision taken about its neighbours. So a coarse allow left on a rule that names sites, and an allow whose site the run no longer reports, are both UNUSED_LINT_ALLOW, and the finding names the sites that did fire. Allows silence warnings and notices; errors always surface.",
19165
+ description: "Per-spec lint suppressions (lint.allow) must name real issue codes and actually suppress a finding \u2014 unknown codes and stale allows are flagged. An allow covers exactly the occurrence it names: a finding that reports a site is silenced only by an allow whose `at` is that site, a finding that reports none only by an allow that names none, and an aggregating finding only by an allow whose `covers` lists every unit it reports \u2014 a unit nobody listed is named back as new instead of inheriting a decision taken about its neighbours. So a coarse allow left on a rule that names sites, and an allow whose site the run no longer reports, are both UNUSED_LINT_ALLOW, and the finding names the sites that did fire. Allows silence warnings and notices; errors always surface \u2014 so an allow naming a code that is an error on its spec (it fired there as one, or its resolved severity is error) covers nothing, and the finding says plainly that an error cannot be allowed rather than that the code never fired.",
18427
19166
  codes: [
18428
19167
  { code: "UNKNOWN_LINT_ALLOW_CODE", defaultSeverity: "warning", summary: "lint.allow names an issue code no registered rule emits" },
18429
- { code: "UNUSED_LINT_ALLOW", defaultSeverity: "warning", summary: "lint.allow entry matched no finding this run \u2014 the code never fired, or it fired at sites this allow does not name" }
19168
+ { code: "UNUSED_LINT_ALLOW", defaultSeverity: "warning", summary: "lint.allow entry covers nothing this run \u2014 the code never fired, it fired at sites this allow does not name, or it is an error, which no allow can cover" }
18430
19169
  ],
18431
19170
  check(ctx) {
18432
19171
  for (const a of ctx.lintAllows) {
@@ -18439,9 +19178,20 @@ var lintAllowsRule = {
18439
19178
  );
18440
19179
  continue;
18441
19180
  }
18442
- if (a.used) continue;
18443
19181
  const reported = ctx.sitesReported(a.specId, a.code);
18444
19182
  const at = a.at ? ` at "${a.at}"` : "";
19183
+ const fired = reported.unsited || reported.sites.length > 0;
19184
+ const isError = reported.errored || !fired && ctx.severityOf(a.code, a.specId) === "error";
19185
+ if (isError) {
19186
+ ctx.addIssue(
19187
+ "warning",
19188
+ "UNUSED_LINT_ALLOW",
19189
+ `Spec "${a.specId}" allows "${a.code}"${at} (reason: ${a.reason}), but "${a.code}" is an error${fired ? " and fired here as one" : ""}, and an error cannot be allowed \u2014 lint.allow silences warnings and notices only. Fix what the finding names, or remove the allow (a project may re-tune the code's severity in rules.sddRuleSeverity).`,
19190
+ a.specId
19191
+ );
19192
+ continue;
19193
+ }
19194
+ if (a.used) continue;
18445
19195
  let why;
18446
19196
  if (a.at && reported.unsited && reported.sites.length === 0) {
18447
19197
  why = `findings of "${a.code}" on this spec name no site at all, so this allow must not name one \u2014 drop the \`at\``;
@@ -18488,12 +19238,12 @@ var contractSymmetryRule = {
18488
19238
  );
18489
19239
  }
18490
19240
  }
18491
- for (const contractMethod of contract.methods) {
18492
- if (!implMethodNames.has(contractMethod.name)) {
19241
+ for (const contractMethod2 of contract.methods) {
19242
+ if (!implMethodNames.has(contractMethod2.name)) {
18493
19243
  ctx.addIssue(
18494
19244
  "error",
18495
19245
  "MISSING_IMPLEMENTATION_METHOD",
18496
- `Implementation "${impl.id}" is missing implementation for contract method "${contractMethod.name}" from interface "${contract.id}".`,
19246
+ `Implementation "${impl.id}" is missing implementation for contract method "${contractMethod2.name}" from interface "${contract.id}".`,
18497
19247
  impl.id,
18498
19248
  isDraftCtx
18499
19249
  );
@@ -19293,8 +20043,8 @@ var narrativeDetailRule = {
19293
20043
  const component = ctx.componentMap.get(contract.component);
19294
20044
  const isDraftCtx = ctx.isImplementationDraft(impl);
19295
20045
  for (const implMethod of impl.methods) {
19296
- const contractMethod = contract.methods.find((m) => m.name === implMethod.name);
19297
- if (!contractMethod) continue;
20046
+ const contractMethod2 = contract.methods.find((m) => m.name === implMethod.name);
20047
+ if (!contractMethod2) continue;
19298
20048
  if (implMethod.narrative.length > 0) continue;
19299
20049
  const eff = effectiveDetail(implMethod, impl, component);
19300
20050
  if (eff.level === "full") {
@@ -19307,7 +20057,7 @@ var narrativeDetailRule = {
19307
20057
  );
19308
20058
  continue;
19309
20059
  }
19310
- const prose = implMethod.intent ?? contractMethod.description;
20060
+ const prose = implMethod.intent ?? contractMethod2.description;
19311
20061
  if (!passesIntentFloor(prose, implMethod.name)) {
19312
20062
  ctx.addIssue(
19313
20063
  eff.explicit ? "error" : "warning",
@@ -19964,18 +20714,47 @@ var dataBlockDepsRule = {
19964
20714
  };
19965
20715
 
19966
20716
  // src/core/rules/doctrine/entrypoint-dependencies.ts
20717
+ function maintainedRegistries(ctx) {
20718
+ const maintained = /* @__PURE__ */ new Map();
20719
+ const add2 = (supervisorId, registryId) => {
20720
+ let set = maintained.get(supervisorId);
20721
+ if (!set) maintained.set(supervisorId, set = /* @__PURE__ */ new Set());
20722
+ set.add(registryId);
20723
+ };
20724
+ for (const comp of ctx.components) {
20725
+ if (comp.componentType !== "Supervisor" || isRetired(comp)) continue;
20726
+ for (const memberId of comp.owns) {
20727
+ if (ctx.componentMap.get(memberId)?.componentType === "Registry") add2(comp.id, memberId);
20728
+ }
20729
+ }
20730
+ for (const impl of ctx.implementations) {
20731
+ const contract = ctx.interfaceMap.get(impl.contract);
20732
+ const supervisor = contract ? ctx.componentMap.get(contract.component) : void 0;
20733
+ if (!supervisor || supervisor.componentType !== "Supervisor" || isRetired(supervisor)) continue;
20734
+ for (const implMethod of impl.methods) {
20735
+ for (const step of implMethod.narrative) {
20736
+ if (step.type !== "call" || !step.targetComponent || !step.targetMethod) continue;
20737
+ if (ctx.componentMap.get(step.targetComponent)?.componentType !== "Registry") continue;
20738
+ const called = ctx.interfaceMethodsOf(step.targetComponent).find((m) => m.name === step.targetMethod);
20739
+ if (called?.effect === "lifecycle") add2(supervisor.id, step.targetComponent);
20740
+ }
20741
+ }
20742
+ }
20743
+ return new Map([...maintained].map(([id, set]) => [id, [...set]]));
20744
+ }
19967
20745
  var entrypointDepsRule = {
19968
20746
  name: "entrypoint-dependencies",
19969
20747
  judges: "design",
19970
- description: "Judges the edges at the system's entry points and its process layer. Portals and Observers are top-level entry points and subscribers, so nothing may depend on them \u2014 and that is the edge's one finding, which is why no other matrix rule judges it. Downward, a Portal dispatches to Orchestrators and may READ through Indexes and Repository facades but never reaches Store/Registry/Query or an Adapter, while an Observer forwards to one Orchestrator or Supervisor over a message-bus Adapter. A View stays a passive presenter. A Supervisor reaches data only through workflows, and a component depending on a live Actor must also depend on a Supervisor that supervises it.",
20748
+ description: "Judges the edges at the system's entry points and its process layer. Portals and Observers are top-level entry points and subscribers, so nothing may depend on them \u2014 and that is the edge's one finding, which is why no other matrix rule judges it. Downward, a Portal dispatches to Orchestrators and may READ through Indexes and Repository facades but never reaches Store/Registry/Query or an Adapter, while an Observer forwards to one Orchestrator or Supervisor over a message-bus Adapter. A View stays a passive presenter. A Supervisor stays out of presentation; what it may do to the data it reaches is judged per call (supervisor-shared-data), and what it owns as its supervision state by the ownership rules. A component depending on a live Actor reaches it through the Actor's supervision: by depending on a Supervisor that supervises it, or on a Registry such a Supervisor maintains (owns, or calls with lifecycle-effect methods) \u2014 the lookup hop callers really take.",
19971
20749
  codes: [
19972
20750
  { code: "ARCHITECTURE_VIOLATION_PORTAL_DEP", defaultSeverity: "error", summary: "Component depending on a Portal/Observer" },
19973
20751
  { code: "ARCHITECTURE_VIOLATION_PORTAL_FORBIDDEN_DEP", defaultSeverity: "error", summary: "Portal/Observer reaching the data layer directly" },
19974
20752
  { code: "ARCHITECTURE_VIOLATION_VIEW_DEP", defaultSeverity: "error", summary: "View depending on persistence layers or on logic that is not pure" },
19975
- { code: "ARCHITECTURE_VIOLATION_SUPERVISOR_DEP", defaultSeverity: "error", summary: "Supervisor depending on anything but Actors, Orchestrators, Adapters or other Supervisors \u2014 it reaches data only through workflows" },
19976
- { code: "ACTOR_REACHED_WITHOUT_SUPERVISOR", defaultSeverity: "error", summary: "Component depending on a live Actor it does not supervise, without also depending on a Supervisor that supervises it \u2014 a live Actor is reached by id through its Supervisor" }
20753
+ { code: "ARCHITECTURE_VIOLATION_SUPERVISOR_DEP", defaultSeverity: "error", summary: "Supervisor depending on a presentation block (View, FeatureComponent, RouterComponent) \u2014 a Supervisor manages live processes; the data it reaches is judged per call by supervisor-shared-data" },
20754
+ { code: "ACTOR_REACHED_WITHOUT_SUPERVISOR", defaultSeverity: "error", summary: "Component depending on a live Actor it does not supervise, reaching it neither through a Supervisor that supervises it nor through a Registry such a Supervisor maintains \u2014 model the real lookup hop" }
19977
20755
  ],
19978
20756
  check(ctx) {
20757
+ const lookups = maintainedRegistries(ctx);
19979
20758
  for (const edge of ctx.dependencyEdges().matrix) {
19980
20759
  const comp = edge.from;
19981
20760
  const depComp = edge.to;
@@ -20011,27 +20790,32 @@ var entrypointDepsRule = {
20011
20790
  edge.draftContext
20012
20791
  );
20013
20792
  }
20014
- if (comp.componentType === "Supervisor" && ["Store", "Registry", "Repository", "Index", "Query", "View", "FeatureComponent", "RouterComponent"].includes(depComp.componentType)) {
20793
+ if (comp.componentType === "Supervisor" && ["View", "FeatureComponent", "RouterComponent"].includes(depComp.componentType)) {
20015
20794
  ctx.addIssue(
20016
20795
  "error",
20017
20796
  "ARCHITECTURE_VIOLATION_SUPERVISOR_DEP",
20018
- `Architectural violation: Supervisor "${comp.id}" cannot depend on ${stereotypeOf(depComp)} "${depComp.id}". A Supervisor reaches data only through workflows \u2014 depend on the Orchestrator, Actor or Adapter that does that work instead.` + storeHint,
20797
+ `Architectural violation: Supervisor "${comp.id}" cannot depend on ${stereotypeOf(depComp)} "${depComp.id}". A Supervisor manages live processes and stays out of presentation \u2014 the UI reaches the system through its Portals and workflows, never through a Supervisor's dependencies.`,
20019
20798
  comp.id,
20020
20799
  edge.draftContext
20021
20800
  );
20022
20801
  }
20023
20802
  if (depComp.componentType === "Actor" && comp.componentType !== "Supervisor") {
20024
- const reachedThroughSupervisor = comp.dependsOn.some((id) => {
20025
- const supervisor = ctx.componentMap.get(id);
20026
- return supervisor?.componentType === "Supervisor" && supervisor.dependsOn.includes(depComp.id);
20027
- });
20028
- if (!reachedThroughSupervisor) {
20029
- const supervisors = ctx.components.filter((c) => c.componentType === "Supervisor" && c.dependsOn.includes(depComp.id)).map((c) => `"${c.id}"`);
20030
- const remedy = supervisors.length > 0 ? `also depend on ${supervisors.length === 1 ? "its Supervisor" : "one of its Supervisors"} (${supervisors.join(", ")})` : `no Supervisor depends on "${depComp.id}" yet, so give the Actor a Supervisor that depends on it and depend on that Supervisor`;
20803
+ const supervisors = ctx.components.filter((c) => c.componentType === "Supervisor" && c.dependsOn.includes(depComp.id));
20804
+ const registries = supervisors.flatMap((s) => (lookups.get(s.id) ?? []).map((registry) => ({ registry, supervisor: s.id })));
20805
+ const reached = supervisors.some((s) => comp.dependsOn.includes(s.id)) || registries.some((r) => comp.dependsOn.includes(r.registry));
20806
+ if (!reached) {
20807
+ let remedy;
20808
+ if (registries.length > 0) {
20809
+ remedy = `depend on ${registries.length === 1 ? "the Registry" : "one of the Registries"} its Supervisor maintains (${registries.map((r) => `"${r.registry}", kept by "${r.supervisor}"`).join("; ")}) and look the Actor up by id there`;
20810
+ } else if (supervisors.length > 0) {
20811
+ remedy = `${supervisors.length === 1 ? "its Supervisor" : "its Supervisors"} (${supervisors.map((s) => `"${s.id}"`).join(", ")}) maintain no Registry of its live handles yet: model that lookup as a Registry the Supervisor keeps through lifecycle-effect methods (registering and unregistering a live handle), and depend on that Registry`;
20812
+ } else {
20813
+ remedy = `no Supervisor depends on "${depComp.id}" yet: give it a Supervisor that depends on it and maintains a Registry of its live handles through lifecycle-effect methods, and depend on that Registry`;
20814
+ }
20031
20815
  ctx.addIssue(
20032
20816
  "error",
20033
20817
  "ACTOR_REACHED_WITHOUT_SUPERVISOR",
20034
- `Architectural violation: ${stereotypeOf(comp)} "${comp.id}" depends on the live Actor "${depComp.id}" without a Supervisor that supervises it. A live Actor is reached by id through a Supervisor that supervises it \u2014 ${remedy}.`,
20818
+ `Architectural violation: ${stereotypeOf(comp)} "${comp.id}" depends on the live Actor "${depComp.id}" without reaching it through its supervision. A live Actor is found by id through a Registry its Supervisor maintains, or messaged through that Supervisor \u2014 ${remedy}.`,
20035
20819
  comp.id,
20036
20820
  edge.draftContext
20037
20821
  );
@@ -20045,9 +20829,9 @@ var entrypointDepsRule = {
20045
20829
  var portalWriteShortcutRule = {
20046
20830
  name: "portal-write-shortcut",
20047
20831
  judges: "design",
20048
- description: "A Portal narrative call step or dispatch-table binding that reaches a write-effect method on a Repository or Index directly is the write shortcut: the Portal\u2192data-facade edge is licensed for reads only, and a write routes through an Orchestrator that owns the workflow. A dispatch step reaches its server only through a table binding, so judging every binding judges each dispatch step that takes it, once, where the route is declared. Methods that carry no effect tag are not judged.",
20832
+ description: "A Portal narrative call step or dispatch-table binding that reaches a write- or lifecycle-effect method on a Repository or Index directly is the write shortcut: the Portal\u2192data-facade edge is licensed for reads only, and a mutation \u2014 a write, or a lifecycle change to what exists \u2014 routes through an Orchestrator that owns the workflow. A dispatch step reaches its server only through a table binding, so judging every binding judges each dispatch step that takes it, once, where the route is declared. Methods that carry no effect tag are not judged.",
20049
20833
  codes: [
20050
- { 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)" }
20834
+ { code: "PORTAL_WRITE_SHORTCUT", defaultSeverity: "error", summary: "Portal narrative call or dispatch-table binding reaches a write- or lifecycle-effect method on a Repository/Index directly \u2014 reads may shortcut, mutations route through an Orchestrator (judged on effect-tagged facade methods; untagged methods are not yet judged)" }
20051
20835
  ],
20052
20836
  check(ctx) {
20053
20837
  for (const impl of ctx.implementations) {
@@ -20061,11 +20845,11 @@ var portalWriteShortcutRule = {
20061
20845
  const target = ctx.componentMap.get(step.targetComponent);
20062
20846
  if (!target || target.componentType !== "Repository" && target.componentType !== "Index") continue;
20063
20847
  const targetMethod = ctx.interfaceMethodsOf(target.id).find((m) => m.name === step.targetMethod);
20064
- if (targetMethod?.effect !== "write") continue;
20848
+ if (targetMethod?.effect !== "write" && targetMethod?.effect !== "lifecycle") continue;
20065
20849
  ctx.addIssue(
20066
20850
  "error",
20067
20851
  "PORTAL_WRITE_SHORTCUT",
20068
- `Portal "${component.id}": step ${step.stepNumber} of "${implMethod.name}" calls write-effect method ${target.id}.${step.targetMethod} directly. The Portal\u2192${target.componentType} shortcut is licensed for READS only \u2014 route the write through an Orchestrator that owns the workflow.`,
20852
+ `Portal "${component.id}": step ${step.stepNumber} of "${implMethod.name}" calls ${targetMethod.effect}-effect method ${target.id}.${step.targetMethod} directly. The Portal\u2192${target.componentType} shortcut is licensed for READS only \u2014 route the ${targetMethod.effect === "write" ? "write" : "lifecycle change"} through an Orchestrator that owns the workflow.`,
20069
20853
  impl.id,
20070
20854
  isDraftCtx || ctx.isComponentDraft(target.id)
20071
20855
  );
@@ -20079,11 +20863,11 @@ var portalWriteShortcutRule = {
20079
20863
  const target = ctx.componentMap.get(binding.component);
20080
20864
  if (!target || target.componentType !== "Repository" && target.componentType !== "Index") continue;
20081
20865
  const targetMethod = ctx.interfaceMethodsOf(target.id).find((m) => m.name === binding.method);
20082
- if (targetMethod?.effect !== "write") continue;
20866
+ if (targetMethod?.effect !== "write" && targetMethod?.effect !== "lifecycle") continue;
20083
20867
  ctx.addIssue(
20084
20868
  "error",
20085
20869
  "PORTAL_WRITE_SHORTCUT",
20086
- `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.`,
20870
+ `Portal "${comp.id}": dispatch binding "${binding.capability}" routes to ${targetMethod.effect}-effect method ${target.id}.${binding.method} directly. The Portal\u2192${target.componentType} shortcut is licensed for READS only \u2014 route the ${targetMethod.effect === "write" ? "write" : "lifecycle change"} through an Orchestrator that owns the workflow.`,
20087
20871
  comp.id,
20088
20872
  isDraftCtx || ctx.isComponentDraft(target.id)
20089
20873
  );
@@ -20092,28 +20876,101 @@ var portalWriteShortcutRule = {
20092
20876
  }
20093
20877
  };
20094
20878
 
20879
+ // src/core/rules/doctrine/supervisor-shared-data.ts
20880
+ var DATA_COMPONENTS = /* @__PURE__ */ new Set(["Store", "Registry", "Repository", "Index", "Query"]);
20881
+ var supervisorSharedDataRule = {
20882
+ name: "supervisor-shared-data",
20883
+ judges: "design",
20884
+ description: "A Supervisor keeps its own supervision state (the Stores and Registries it owns) with full read and write, but data it does not own is shared: a Supervisor narrative call step that reaches a method of a Store, Registry, Repository, Index or Query the Supervisor does not own is legal only when that method declares effect read or lifecycle. A write \u2014 or a method that declares no effect \u2014 goes through a workflow: the Supervisor depends on the Orchestrator that does it. A read on behalf of a request still passes; in practice the paired write is what forces the workflow out, and the read moves with it.",
20885
+ codes: [
20886
+ { code: "SUPERVISOR_WRITE_SHORTCUT", defaultSeverity: "error", summary: "Supervisor narrative call reaches a method of a data component it does not own whose declared effect is neither read nor lifecycle \u2014 writes to shared data route through an Orchestrator" }
20887
+ ],
20888
+ check(ctx) {
20889
+ const ownership = ctx.ownershipIndex();
20890
+ for (const impl of ctx.implementations) {
20891
+ const contract = ctx.interfaceMap.get(impl.contract);
20892
+ const supervisor = contract ? ctx.componentMap.get(contract.component) : void 0;
20893
+ if (!supervisor || supervisor.componentType !== "Supervisor" || isRetired(supervisor)) continue;
20894
+ const isDraftCtx = ctx.isImplementationDraft(impl);
20895
+ for (const implMethod of impl.methods) {
20896
+ for (const step of implMethod.narrative) {
20897
+ if (step.type !== "call" || !step.targetComponent || !step.targetMethod) continue;
20898
+ const target = ctx.componentMap.get(step.targetComponent);
20899
+ if (!target || !DATA_COMPONENTS.has(target.componentType)) continue;
20900
+ if (ownership.ownerOf(target.id) === supervisor.id) continue;
20901
+ const called = ctx.interfaceMethodsOf(target.id).find((m) => m.name === step.targetMethod);
20902
+ if (!called || called.effect === "read" || called.effect === "lifecycle") continue;
20903
+ const what = called.effect === "write" ? "a write-effect method" : "a method that declares no effect";
20904
+ const untaggedHint = called.effect === "write" ? "" : ` If ${target.id}.${called.name} only reads, or only changes what exists, declare its effect (read or lifecycle).`;
20905
+ ctx.addIssue(
20906
+ "error",
20907
+ "SUPERVISOR_WRITE_SHORTCUT",
20908
+ `Supervisor "${supervisor.id}": step ${step.stepNumber} of "${implMethod.name}" calls ${target.id}.${called.name}, ${what} on ${target.componentType} "${target.id}", which the Supervisor does not own. A Supervisor reads shared data and changes what exists in it (read and lifecycle effects); a write to its fields goes through a workflow \u2014 depend on the Orchestrator that does it and call that instead.${untaggedHint}`,
20909
+ impl.id,
20910
+ isDraftCtx || ctx.isComponentDraft(target.id)
20911
+ );
20912
+ }
20913
+ }
20914
+ }
20915
+ }
20916
+ };
20917
+
20918
+ // src/core/rules/doctrine/lifecycle-effect-closure.ts
20919
+ var lifecycleEffectClosureRule = {
20920
+ name: "lifecycle-effect-closure",
20921
+ judges: "design",
20922
+ description: "A lifecycle-effect method may create, destroy, or (un)register an entity's existence or membership, never modify its domain fields \u2014 and the effect is closed under composition: its narrative may call only read- and lifecycle-effect methods besides its construction and local steps. A call step to a write-effect method from a lifecycle-effect method is a declaration error: the method is a write, or the write belongs to a workflow beside it. Called methods that declare no effect are not judged.",
20923
+ codes: [
20924
+ { code: "LIFECYCLE_CALLS_WRITE", defaultSeverity: "error", summary: "Lifecycle-effect method whose narrative calls a write-effect method \u2014 the lifecycle effect is closed under composition" }
20925
+ ],
20926
+ check(ctx) {
20927
+ for (const impl of ctx.implementations) {
20928
+ const contract = ctx.interfaceMap.get(impl.contract);
20929
+ if (!contract) continue;
20930
+ const declared = ctx.interfaceMethodsOf(contract.component);
20931
+ const isDraftCtx = ctx.isImplementationDraft(impl);
20932
+ for (const implMethod of impl.methods) {
20933
+ if (declared.find((m) => m.name === implMethod.name)?.effect !== "lifecycle") continue;
20934
+ for (const step of implMethod.narrative) {
20935
+ if (step.type !== "call" || !step.targetComponent || !step.targetMethod) continue;
20936
+ const called = ctx.interfaceMethodsOf(step.targetComponent).find((m) => m.name === step.targetMethod);
20937
+ if (called?.effect !== "write") continue;
20938
+ ctx.addIssue(
20939
+ "error",
20940
+ "LIFECYCLE_CALLS_WRITE",
20941
+ `"${contract.component}.${implMethod.name}" declares effect lifecycle, but step ${step.stepNumber} calls write-effect method ${step.targetComponent}.${step.targetMethod}. A lifecycle method creates, destroys or (un)registers what exists and never modifies domain fields, and the effect is closed under composition \u2014 it may call only read and lifecycle methods. Declare the method a write, or move the write to a workflow beside it.`,
20942
+ impl.id,
20943
+ isDraftCtx
20944
+ );
20945
+ }
20946
+ }
20947
+ }
20948
+ }
20949
+ };
20950
+
20095
20951
  // src/core/rules/doctrine/pattern-membership.ts
20096
20952
  var patternMembershipRule = {
20097
20953
  name: "pattern-membership",
20098
20954
  judges: "design",
20099
- description: "Only patterns (Repository/FeatureComponent/RouterComponent) own member blocks, and every pattern owns at least one. Each claim must name a component that exists and is itself a building block \u2014 patterns compose at the subsystem (L1) level, never by owning one another \u2014 and a block has exactly one owner, the first pattern to claim it.",
20955
+ description: "Only patterns (Repository/FeatureComponent/RouterComponent) own member blocks, and every pattern owns at least one. The one building block that may own is a Supervisor, which owns its supervision state and may own nothing at all; what it may own is pattern-containment's question. Each claim must name a component that exists and is itself a building block \u2014 patterns compose at the subsystem (L1) level, never by owning one another \u2014 and a block has exactly one owner, the first pattern or Supervisor to claim it.",
20100
20956
  codes: [
20101
20957
  { code: "EMPTY_PATTERN", defaultSeverity: "error", summary: "Pattern with no owned member blocks" },
20102
- { code: "BLOCK_OWNS_MEMBERS", defaultSeverity: "error", summary: "Building block using owns" },
20958
+ { code: "BLOCK_OWNS_MEMBERS", defaultSeverity: "error", summary: "Building block other than a Supervisor using owns" },
20103
20959
  { code: "INVALID_OWNED_MEMBER", defaultSeverity: "error", summary: "owns names a non-existent component" },
20104
20960
  { code: "PATTERN_OWNS_PATTERN", defaultSeverity: "error", summary: "Pattern owning another pattern" },
20105
- { code: "SHARED_OWNED_MEMBER", defaultSeverity: "error", summary: "Block owned by two patterns" }
20961
+ { code: "SHARED_OWNED_MEMBER", defaultSeverity: "error", summary: "Block owned by two owners (patterns or Supervisors)" }
20106
20962
  ],
20107
20963
  check(ctx) {
20108
20964
  for (const comp of ctx.components) {
20109
20965
  if (isRetired(comp)) continue;
20110
20966
  const isDraftCtx = ctx.isComponentDraft(comp.id);
20111
20967
  const pattern = isPattern(comp);
20968
+ const supervisor = comp.componentType === "Supervisor";
20112
20969
  if (pattern && comp.owns.length === 0) {
20113
20970
  ctx.addIssue("error", "EMPTY_PATTERN", `Pattern "${comp.id}" (${comp.componentType}) must own member blocks via "owns".`, comp.id, isDraftCtx);
20114
20971
  }
20115
- if (!pattern && comp.owns.length > 0) {
20116
- ctx.addIssue("error", "BLOCK_OWNS_MEMBERS", `Building block "${comp.id}" (${comp.componentType}) cannot own members; only patterns (${Array.from(PATTERN_TYPES).join("/")}) use "owns".`, comp.id, isDraftCtx);
20972
+ if (!pattern && !supervisor && comp.owns.length > 0) {
20973
+ ctx.addIssue("error", "BLOCK_OWNS_MEMBERS", `Building block "${comp.id}" (${comp.componentType}) cannot own members; only patterns (${Array.from(PATTERN_TYPES).join("/")}) use "owns", and a Supervisor for its supervision state.`, comp.id, isDraftCtx);
20117
20974
  }
20118
20975
  }
20119
20976
  const ownership = ctx.ownershipIndex();
@@ -20121,15 +20978,18 @@ var patternMembershipRule = {
20121
20978
  if (isRetired(comp)) continue;
20122
20979
  const isDraftCtx = ctx.isComponentDraft(comp.id);
20123
20980
  const pattern = isPattern(comp);
20981
+ const supervisor = comp.componentType === "Supervisor";
20124
20982
  for (const memberId of comp.owns) {
20125
20983
  const member = ctx.componentMap.get(memberId);
20126
20984
  if (!member) {
20127
20985
  ctx.addIssue("error", "INVALID_OWNED_MEMBER", `Component "${comp.id}" owns "${memberId}" which does not exist.`, comp.id, isDraftCtx);
20128
20986
  continue;
20129
20987
  }
20130
- if (!pattern) continue;
20988
+ if (!pattern && !supervisor) continue;
20131
20989
  if (isPattern(member)) {
20132
- 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);
20990
+ if (pattern) {
20991
+ 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);
20992
+ }
20133
20993
  continue;
20134
20994
  }
20135
20995
  const firstOwner = ownership.ownerOf(memberId);
@@ -20143,13 +21003,15 @@ var patternMembershipRule = {
20143
21003
 
20144
21004
  // src/core/rules/doctrine/pattern-containment.ts
20145
21005
  var REPOSITORY_MEMBERS = /* @__PURE__ */ new Set(["Store", "Registry", "Index", "Query", "Adapter"]);
21006
+ var SUPERVISION_STATE = /* @__PURE__ */ new Set(["Store", "Registry"]);
20146
21007
  var patternContainmentRule = {
20147
21008
  name: "pattern-containment",
20148
21009
  judges: "design",
20149
- description: "Holds each pattern to the containment its definition prescribes. A Repository may own only Store, Registry, Index, Query and (optionally) Adapter, judged member by member. A FeatureComponent owns exactly one Orchestrator (the logic side) and one or more Views (its faces \u2014 list, detail, form \u2014 sharing the one logic component), and nothing else. A RouterComponent owns exactly one Portal as its facade and at least one other child to route to. A counting pattern that still owns a retired member is not judged until that member is migrated: its counts change with the migration, and STEREOTYPE_RETIRED is the one finding.",
21010
+ description: "Holds each owner to the containment its definition prescribes. A Repository may own only Store, Registry, Index, Query and (optionally) Adapter, judged member by member. A Supervisor may own only its supervision state \u2014 Stores and Registries that are its own, one hop \u2014 judged member by member too. A FeatureComponent owns exactly one Orchestrator (the logic side) and one or more Views (its faces \u2014 list, detail, form \u2014 sharing the one logic component), and nothing else. A RouterComponent owns exactly one Portal as its facade and at least one other child to route to. A counting pattern that still owns a retired member is not judged until that member is migrated: its counts change with the migration, and STEREOTYPE_RETIRED is the one finding.",
20150
21011
  codes: [
20151
21012
  { code: "REPOSITORY_CONTAINMENT", defaultSeverity: "error", summary: "Repository owning a non Store/Registry/Index/Query/Adapter member" },
20152
21013
  { code: "FEATURE_COMPONENT_CONTAINMENT", defaultSeverity: "error", summary: "FeatureComponent not owning exactly one Orchestrator + one or more Views" },
21014
+ { code: "SUPERVISOR_CONTAINMENT", defaultSeverity: "error", summary: "Supervisor owning anything but a Store or Registry \u2014 a Supervisor owns only its supervision state" },
20153
21015
  { code: "ROUTER_COMPONENT_CONTAINMENT", defaultSeverity: "error", summary: "RouterComponent not owning exactly one Portal facade, or owning no children to route to" }
20154
21016
  ],
20155
21017
  check(ctx) {
@@ -20200,6 +21062,15 @@ var patternContainmentRule = {
20200
21062
  }
20201
21063
  }
20202
21064
  }
21065
+ for (const comp of ctx.components) {
21066
+ if (comp.componentType !== "Supervisor" || isRetired(comp)) continue;
21067
+ const isDraftCtx = ctx.isComponentDraft(comp.id);
21068
+ for (const memberId of comp.owns) {
21069
+ const member = ctx.componentMap.get(memberId);
21070
+ if (!member || isRetired(member) || SUPERVISION_STATE.has(member.componentType)) continue;
21071
+ ctx.addIssue("error", "SUPERVISOR_CONTAINMENT", `Supervisor "${comp.id}" owns "${memberId}" of type ${member.componentType}; a Supervisor owns only its supervision state \u2014 Stores and Registries that are its own. Depend on "${memberId}" as a collaborator instead.`, comp.id, isDraftCtx);
21072
+ }
21073
+ }
20203
21074
  }
20204
21075
  };
20205
21076
 
@@ -20207,7 +21078,7 @@ var patternContainmentRule = {
20207
21078
  var unownedBlocksRule = {
20208
21079
  name: "unowned-blocks",
20209
21080
  judges: "design",
20210
- description: `Judges the data blocks no pattern owns. A Store may stand alone deliberately \u2014 the sanctioned lightweight form for genuinely simple state, acknowledged with a lint.allow \u2014 while the recommended shape stays a Repository; what must never happen is folding the state into a consuming component, where no spec, diagram or conformance check can see it again. A Registry standing alone with no Store to write to is either mistyped (the "file-backed Registry" idiom, a fused persistent store that belongs typed Store) or orphaned. A Query has no standalone form at all: it computes reads over its own Repository's Store.`,
21081
+ description: `Judges the data blocks no owner (a pattern, or a Supervisor keeping its supervision state) owns. A Store may stand alone deliberately \u2014 the sanctioned lightweight form for genuinely simple state, acknowledged with a lint.allow \u2014 while the recommended shape stays a Repository; what must never happen is folding the state into a consuming component, where no spec, diagram or conformance check can see it again. A Registry standing alone with no Store to write to is either mistyped (the "file-backed Registry" idiom, a fused persistent store that belongs typed Store) or orphaned. A Query has no standalone form at all: it computes reads over its own Repository's Store.`,
20211
21082
  codes: [
20212
21083
  { 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" },
20213
21084
  { 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" },
@@ -20253,9 +21124,10 @@ var unownedBlocksRule = {
20253
21124
  var memberVisibilityRule = {
20254
21125
  name: "member-visibility",
20255
21126
  judges: "design",
20256
- description: "A component may depend on a block within its own group (it is the owning pattern, or a sibling member of the same pattern), on any pattern facade, or on a standalone block \u2014 never on a block privately owned by ANOTHER pattern, which must be reached through that pattern's facade. A retired depending component is skipped, as everywhere in this family.",
21127
+ description: "A component may depend on a block within its own group (it is the owner, or a sibling member of the same owner), on any pattern facade, or on a standalone block \u2014 never on a block privately owned by ANOTHER pattern, which must be reached through that pattern's facade. A Store or Registry a Supervisor owns is that Supervisor's supervision state and nobody else depends on it: a component that does is the intruder, and the finding is reported on it, naming the Supervisor and the state. A retired depending component is skipped, as everywhere in this family.",
20257
21128
  codes: [
20258
- { code: "VISIBILITY_VIOLATION", defaultSeverity: "error", summary: "Dependency on a block privately owned by another pattern" }
21129
+ { code: "VISIBILITY_VIOLATION", defaultSeverity: "error", summary: "Dependency on a block privately owned by another pattern" },
21130
+ { code: "SUPERVISION_STATE_INTRUSION", defaultSeverity: "error", summary: "Dependency on a Store or Registry a Supervisor owns as its supervision state \u2014 reported on the intruder, naming the Supervisor and the state" }
20259
21131
  ],
20260
21132
  check(ctx) {
20261
21133
  const ownership = ctx.ownershipIndex();
@@ -20266,7 +21138,12 @@ var memberVisibilityRule = {
20266
21138
  if (!owner) continue;
20267
21139
  if (owner === comp.id) continue;
20268
21140
  if (ownership.ownerOf(comp.id) === owner) continue;
20269
- ctx.addIssue("error", "VISIBILITY_VIOLATION", `Component "${comp.id}" depends on "${depId}", which is privately owned by pattern "${owner}". Depend on the facade "${owner}" instead.`, comp.id, ctx.isComponentDraft(comp.id) || ctx.isComponentDraft(depId));
21141
+ const isDraftCtx = ctx.isComponentDraft(comp.id) || ctx.isComponentDraft(depId);
21142
+ if (ctx.componentMap.get(owner)?.componentType === "Supervisor") {
21143
+ ctx.addIssue("error", "SUPERVISION_STATE_INTRUSION", `"${comp.id}" depends on "${depId}", which Supervisor "${owner}" owns as its supervision state. Supervision state is private to its Supervisor \u2014 nobody else depends on it. If "${comp.id}" needs this data it is shared data: move "${depId}" out of "${owner}"'s owns into a data component both depend on (the Supervisor keeping it through read and lifecycle calls), or reach what "${comp.id}" needs through "${owner}".`, comp.id, isDraftCtx);
21144
+ continue;
21145
+ }
21146
+ ctx.addIssue("error", "VISIBILITY_VIOLATION", `Component "${comp.id}" depends on "${depId}", which is privately owned by pattern "${owner}". Depend on the facade "${owner}" instead.`, comp.id, isDraftCtx);
20270
21147
  }
20271
21148
  }
20272
21149
  }
@@ -21399,9 +22276,9 @@ var durabilityRule = {
21399
22276
  // Stage 8: its verdict needs the whole system's specs, so a part judged alone skips it.
21400
22277
  needsWholeTree: true,
21401
22278
  judges: "design",
21402
- description: "A durable Store (persisted RAM projection) must carry effect-tagged contract methods, and its writes require a hydration read-back reachable from a lifecycle init entrypoint. read-through is exempt (every read IS the read-back), as are ram-projection (rebuilt not restored) and cache (evictable, loss-safe). The flagship semantic check is opt-out by declaration, never silently absent \u2014 the declaration itself is enforced by durability-declaration.",
22279
+ description: "A durable Store (persisted RAM projection) must carry effect-tagged contract methods, and its mutations \u2014 write-effect methods, and lifecycle-effect methods, which change what exists \u2014 require a hydration read-back reachable from a lifecycle init entrypoint. read-through is exempt (every read IS the read-back), as are ram-projection (rebuilt not restored) and cache (evictable, loss-safe). The flagship semantic check is opt-out by declaration, never silently absent \u2014 the declaration itself is enforced by durability-declaration.",
21403
22280
  codes: [
21404
- { code: "MISSING_EFFECT_TAG", defaultSeverity: "warning", summary: "Durable Store contract method lacks an effect: read | write tag" },
22281
+ { code: "MISSING_EFFECT_TAG", defaultSeverity: "warning", summary: "Durable Store contract method lacks an effect: read | write | lifecycle tag" },
21405
22282
  { code: "MISSING_HYDRATION", defaultSeverity: "error", summary: "Durable Store is written but no read-back is reachable from any lifecycle init entrypoint" }
21406
22283
  ],
21407
22284
  check(ctx) {
@@ -21429,7 +22306,7 @@ var durabilityRule = {
21429
22306
  isDraftCtx
21430
22307
  );
21431
22308
  }
21432
- const writes = methods.filter((method) => method.effect === "write");
22309
+ const writes = methods.filter((method) => method.effect === "write" || method.effect === "lifecycle");
21433
22310
  const reads = methods.filter((method) => method.effect === "read");
21434
22311
  if (writes.length === 0) continue;
21435
22312
  const hydrated = initReach !== null && reads.some((method) => initReach.reachesMethod(comp.id, method.name));
@@ -21622,10 +22499,10 @@ function familyAliases(family) {
21622
22499
  }
21623
22500
  return out;
21624
22501
  }
21625
- function typeRefReadings(typeRef, aliases) {
21626
- const [first, ...rest] = typeRef.split(/::|\./);
21627
- if (!rest.length) return [typeRef];
21628
- return [typeRef, ...(aliases.get(first) ?? []).map((key) => `${key}::${rest.join("::")}`)];
22502
+ function typeRefReadings(typeRef2, aliases) {
22503
+ const [first, ...rest] = typeRef2.split(/::|\./);
22504
+ if (!rest.length) return [typeRef2];
22505
+ return [typeRef2, ...(aliases.get(first) ?? []).map((key) => `${key}::${rest.join("::")}`)];
21629
22506
  }
21630
22507
  function resolveInvariantRef(ref, types, aliases = /* @__PURE__ */ new Map()) {
21631
22508
  const parts = splitInvariantRef(ref);
@@ -23095,8 +23972,8 @@ var asyncConformanceRule = {
23095
23972
  check(ctx) {
23096
23973
  const code = ctx.codeIndex();
23097
23974
  for (const { implementation, method, sourceFile, draftContext: draftContext4 } of ctx.implementationMethods()) {
23098
- const contractMethod = ctx.interfaceMap.get(implementation.contract)?.methods.find((m) => m.name === method.name);
23099
- if (!contractMethod || typeof contractMethod.returns !== "string" || !sourceFile) continue;
23975
+ const contractMethod2 = ctx.interfaceMap.get(implementation.contract)?.methods.find((m) => m.name === method.name);
23976
+ if (!contractMethod2 || typeof contractMethod2.returns !== "string" || !sourceFile) continue;
23100
23977
  const file = pathKey(sourceFile);
23101
23978
  const facts = code.factsAt(file);
23102
23979
  if (!facts || facts.status !== "analyzed" || facts.analysisGrade !== "exact") continue;
@@ -23105,7 +23982,7 @@ var asyncConformanceRule = {
23105
23982
  if (!signatures || !Object.prototype.hasOwnProperty.call(signatures, symbol)) continue;
23106
23983
  const bodies = signatures[symbol].length;
23107
23984
  if (bodies === 0) continue;
23108
- const returns = parseTypeExpression(contractMethod.returns, "returns");
23985
+ const returns = parseTypeExpression(contractMethod2.returns, "returns");
23109
23986
  if (!returns.expression) continue;
23110
23987
  const contractAsync = returns.expression.form === "async";
23111
23988
  const asyncBodies = (facts.asyncFunctions ?? []).filter((name) => name === symbol).length;
@@ -23114,7 +23991,7 @@ var asyncConformanceRule = {
23114
23991
  ctx.addIssue(
23115
23992
  "warning",
23116
23993
  "ASYNC_MISMATCH",
23117
- `Method "${method.name}" of contract "${implementation.contract}" returns "${contractMethod.returns}", which completes later, but ${subject} completes now \u2014 it is neither declared async nor annotated to return a Promise. Every caller is told to await a call that answers at once. Make the code async, or drop \`async\` from the returns.`,
23994
+ `Method "${method.name}" of contract "${implementation.contract}" returns "${contractMethod2.returns}", which completes later, but ${subject} completes now \u2014 it is neither declared async nor annotated to return a Promise. Every caller is told to await a call that answers at once. Make the code async, or drop \`async\` from the returns.`,
23118
23995
  implementation.id,
23119
23996
  draftContext4,
23120
23997
  void 0,
@@ -23124,7 +24001,7 @@ var asyncConformanceRule = {
23124
24001
  ctx.addIssue(
23125
24002
  "warning",
23126
24003
  "ASYNC_MISMATCH",
23127
- `Method "${method.name}" of contract "${implementation.contract}" returns "${contractMethod.returns}", which completes now, but ${subject} completes later (declared async, or annotated to return a Promise). Every caller built from the contract forgets to await it. Write the returns as "async ${contractMethod.returns}" \u2014 or, if the code is async by accident, make it complete now.`,
24004
+ `Method "${method.name}" of contract "${implementation.contract}" returns "${contractMethod2.returns}", which completes now, but ${subject} completes later (declared async, or annotated to return a Promise). Every caller built from the contract forgets to await it. Write the returns as "async ${contractMethod2.returns}" \u2014 or, if the code is async by accident, make it complete now.`,
23128
24005
  implementation.id,
23129
24006
  draftContext4,
23130
24007
  void 0,
@@ -24669,6 +25546,8 @@ var SDD_RULES = [
24669
25546
  typeExpressionsRule,
24670
25547
  enumTypesRule,
24671
25548
  namedScalarTypesRule,
25549
+ // The rename traces: a former key a consumer resolves must name one element.
25550
+ renameTracesRule,
24672
25551
  // Contracts and the targets narratives name, in four questions with one
24673
25552
  // owner each: does the implementation mirror its contract, does a target
24674
25553
  // inside this tree resolve, does a target that leaves it pin to exactly one
@@ -24722,6 +25601,10 @@ var SDD_RULES = [
24722
25601
  dataBlockDepsRule,
24723
25602
  entrypointDepsRule,
24724
25603
  portalWriteShortcutRule,
25604
+ // The process layer's data reach and the lifecycle effect's closure, both
25605
+ // read from narratives against the callee's declared effect.
25606
+ supervisorSharedDataRule,
25607
+ lifecycleEffectClosureRule,
24725
25608
  // Patterns in four questions: who may own and what a claim must name,
24726
25609
  // what each pattern must contain, which data blocks are left standing
24727
25610
  // alone, and who may see a private member.
@@ -26445,7 +27328,16 @@ function buildRuleContext(opts) {
26445
27328
  const sitesSeen = /* @__PURE__ */ new Map();
26446
27329
  const sitesReported = (specId, code) => {
26447
27330
  const seen = sitesSeen.get(`${specId}\0${code}`);
26448
- return { sites: [...seen?.sites ?? []], unsited: seen?.unsited ?? false };
27331
+ return { sites: [...seen?.sites ?? []], unsited: seen?.unsited ?? false, errored: seen?.errored ?? false };
27332
+ };
27333
+ const codeDefaults = new Map(opts.issueCodeSeverities ?? []);
27334
+ for (const a of opts.extensions?.assertions ?? []) {
27335
+ if (!codeDefaults.has(a.fullCode)) codeDefaults.set(a.fullCode, a.severity);
27336
+ }
27337
+ const severityOf = (code, specId) => {
27338
+ const defaultSeverity = codeDefaults.get(code);
27339
+ if (!defaultSeverity) return void 0;
27340
+ return getRuleSeverity(code, defaultSeverity, false, subsystemOfSpec.get(specId));
26449
27341
  };
26450
27342
  for (const s of subsystems) collectAllows(s.id, s.lint);
26451
27343
  for (const c of components) collectAllows(c.id, c.lint);
@@ -26488,9 +27380,10 @@ function buildRuleContext(opts) {
26488
27380
  if (specId) {
26489
27381
  const key = `${specId}\0${code}`;
26490
27382
  let seen = sitesSeen.get(key);
26491
- if (!seen) sitesSeen.set(key, seen = { sites: /* @__PURE__ */ new Set(), unsited: false });
27383
+ if (!seen) sitesSeen.set(key, seen = { sites: /* @__PURE__ */ new Set(), unsited: false, errored: false });
26492
27384
  if (parts) seen.sites.add(parts.at);
26493
27385
  else seen.unsited = true;
27386
+ if (severity === "error") seen.errored = true;
26494
27387
  }
26495
27388
  let allowClaimed = false;
26496
27389
  if (specId) {
@@ -26607,6 +27500,7 @@ function buildRuleContext(opts) {
26607
27500
  roundTripIssues: opts.roundTripIssues,
26608
27501
  lintAllows: lintAllows2,
26609
27502
  sitesReported,
27503
+ severityOf,
26610
27504
  knownIssueCodes: opts.knownIssueCodes,
26611
27505
  carriedFindings,
26612
27506
  carryableIssueCodes: opts.carryableIssueCodes ?? /* @__PURE__ */ new Set(),
@@ -26760,12 +27654,12 @@ function measure(candidate) {
26760
27654
  // src/core/rules/gate-identity.ts
26761
27655
  var crypto4 = __toESM(require("crypto"));
26762
27656
  var GATE_ALGORITHM = "sha256+content+doctrine+inputs+members";
26763
- var byKey = (items, key) => [...items].sort((a, b) => compareOrdinal(key(a), key(b)));
27657
+ var byKey2 = (items, key) => [...items].sort((a, b) => compareOrdinal(key(a), key(b)));
26764
27658
  function ruleIdentities(rules) {
26765
- return byKey(
27659
+ return byKey2(
26766
27660
  rules.map((r) => ({
26767
27661
  name: r.name,
26768
- codes: byKey(r.codes.map((c) => ({ code: c.code, severity: c.defaultSeverity })), (c) => c.code)
27662
+ codes: byKey2(r.codes.map((c) => ({ code: c.code, severity: c.defaultSeverity })), (c) => c.code)
26769
27663
  })),
26770
27664
  (r) => r.name
26771
27665
  );
@@ -26813,7 +27707,7 @@ function doctrineIdentity(doctrine2, builtinRules, gate) {
26813
27707
  * changed requirement stales the requiring project's lock.
26814
27708
  */
26815
27709
  composition: gate.composition ?? null,
26816
- packs: byKey(
27710
+ packs: byKey2(
26817
27711
  doctrine2.packs.map((p) => ({ name: p.name, version: p.version ?? null, scope: p.scope })),
26818
27712
  (p) => `${p.name}@${p.version ?? ""}#${p.scope}`
26819
27713
  ),
@@ -26821,13 +27715,13 @@ function doctrineIdentity(doctrine2, builtinRules, gate) {
26821
27715
  // the identity — a load-order change that flips a collision winner shows up here.
26822
27716
  profiles: doctrine2.profiles,
26823
27717
  languages: doctrine2.languages,
26824
- patterns: byKey(
27718
+ patterns: byKey2(
26825
27719
  doctrine2.patterns.map((p) => ({ id: p.id, version: p.version, pack: p.pack })),
26826
27720
  (p) => `${p.pack}/${p.id}@${p.version}`
26827
27721
  ),
26828
27722
  guarantees: [...doctrine2.guarantees].sort(),
26829
- assertions: byKey(doctrine2.assertions.map((a) => ({ ...a })), (a) => a.fullCode),
26830
- rules: byKey(
27723
+ assertions: byKey2(doctrine2.assertions.map((a) => ({ ...a })), (a) => a.fullCode),
27724
+ rules: byKey2(
26831
27725
  doctrine2.rules.map((r) => ({ name: r.name, codes: r.codes.map((c) => c.code).sort() })),
26832
27726
  (r) => r.name
26833
27727
  )
@@ -26838,7 +27732,7 @@ function computeGateIdentity(content, doctrine2, builtinRules, inputs, gate, mem
26838
27732
  content: content.digest,
26839
27733
  doctrine: doctrineIdentity(doctrine2, builtinRules, gate),
26840
27734
  inputs: [...inputs].sort(compareOrdinal),
26841
- members: byKey(Object.entries(members), ([alias]) => alias).map(([alias, subject]) => ({ alias, subject }))
27735
+ members: byKey2(Object.entries(members), ([alias]) => alias).map(([alias, subject]) => ({ alias, subject }))
26842
27736
  };
26843
27737
  const digest3 = crypto4.createHash("sha256").update(canonicalize(payload)).digest("hex");
26844
27738
  return { algorithm: GATE_ALGORITHM, digest: digest3 };
@@ -27039,6 +27933,7 @@ function runOwnersGate(rulesOrOptions, projectType = "backend") {
27039
27933
  const carryableCodes = new Set(
27040
27934
  knownIssueCodes().filter((rc) => rc.carryable).map((rc) => rc.code)
27041
27935
  );
27936
+ const codeSeverities = new Map(knownIssueCodes().map((rc) => [rc.code, rc.defaultSeverity]));
27042
27937
  const family = graph();
27043
27938
  const memberTables = family.nodes.filter((n) => n.namespace !== "").map((n) => resolveProjectExports(n.namespace));
27044
27939
  const producers = new Set(family.references.filter((r) => r.consumer === "").map((r) => r.producer));
@@ -27081,6 +27976,7 @@ function runOwnersGate(rulesOrOptions, projectType = "backend") {
27081
27976
  codeModel,
27082
27977
  roundTripIssues,
27083
27978
  knownIssueCodes: knownCodes,
27979
+ issueCodeSeverities: codeSeverities,
27084
27980
  carryableIssueCodes: carryableCodes,
27085
27981
  issues
27086
27982
  });
@@ -27181,8 +28077,8 @@ function judgePartAlone(config, scopeSubsystem) {
27181
28077
  issues.push(issue("warning", "EXTERNAL_CHECK_UNAVAILABLE", `The parent "${parentId}" governs its parts with a pack this machine cannot load at its pinned version, so its rules were not run here: ${failure}`));
27182
28078
  }
27183
28079
  const ownIds = new Set([...own.subsystems, ...own.components, ...own.interfaces, ...own.implementations, ...own.types].map((s) => s.id));
27184
- const isOwn = (id) => ownIds.has(id);
27185
- issues.push(...getLoaderIssues().filter((e) => !e.specId || isOwn(e.specId)));
28080
+ const isOwn2 = (id) => ownIds.has(id);
28081
+ issues.push(...getLoaderIssues().filter((e) => !e.specId || isOwn2(e.specId)));
27186
28082
  for (const [key, by] of namedKeys(own)) {
27187
28083
  if (ownIds.has(key) || context.ids.has(key)) continue;
27188
28084
  issues.push(issue("warning", "EXTERNAL_CHECK_UNAVAILABLE", `"${by}" names "${key}", which neither this part nor its pinned excerpt of "${parentId}" holds \u2014 used since the pin: re-pin with \`wairon externals pin\` while the parent is on disk.`, by));
@@ -27190,8 +28086,8 @@ function judgePartAlone(config, scopeSubsystem) {
27190
28086
  const ownSignatures = signatureFacts();
27191
28087
  const ownTypeSpellings = typeSpellingFacts();
27192
28088
  const partTypeSpellings = {
27193
- respellings: ownTypeSpellings.respellings.filter((r) => isOwn(r.specId)),
27194
- problems: ownTypeSpellings.problems.filter((p) => p.specId === void 0 || isOwn(p.specId))
28089
+ respellings: ownTypeSpellings.respellings.filter((r) => isOwn2(r.specId)),
28090
+ problems: ownTypeSpellings.problems.filter((p) => p.specId === void 0 || isOwn2(p.specId))
27195
28091
  };
27196
28092
  const resolved = resolveSignatures(
27197
28093
  [...own.interfaces, ...context.interfaces],
@@ -27238,7 +28134,7 @@ function judgePartAlone(config, scopeSubsystem) {
27238
28134
  packRequirements: [],
27239
28135
  surfaceSnapshots: [],
27240
28136
  codeModel,
27241
- roundTripIssues: dryRunSerializeSpecs(isOwn),
28137
+ roundTripIssues: dryRunSerializeSpecs(isOwn2),
27242
28138
  knownIssueCodes: knownCodes,
27243
28139
  carryableIssueCodes: new Set(knownIssueCodes().filter((rc) => rc.carryable).map((rc) => rc.code)),
27244
28140
  issues
@@ -28271,10 +29167,10 @@ function settle(owner, level, candidates, problems) {
28271
29167
  detail: `"${name}" is bound to ${targets.length} different targets (${targets.join(", ")}) by ${explicit.length ? "explicit entries" : "wildcard re-exports"}; it is left out of the table`
28272
29168
  });
28273
29169
  }
28274
- const byKey2 = /* @__PURE__ */ new Map();
28275
- for (const e of entries) byKey2.set(nameKey(e.publicName), [...byKey2.get(nameKey(e.publicName)) ?? [], e]);
29170
+ const byKey3 = /* @__PURE__ */ new Map();
29171
+ for (const e of entries) byKey3.set(nameKey(e.publicName), [...byKey3.get(nameKey(e.publicName)) ?? [], e]);
28276
29172
  const clashing = /* @__PURE__ */ new Set();
28277
- for (const group of byKey2.values()) {
29173
+ for (const group of byKey3.values()) {
28278
29174
  const targets = [...new Set(group.map((e) => exportTargetKey(e)))];
28279
29175
  if (group.length < 2 || targets.length < 2) continue;
28280
29176
  group.forEach((e) => clashing.add(e));
@@ -28592,7 +29488,7 @@ function pinnedUsageOf(consumer, alias) {
28592
29488
  function emptySignatureFacts() {
28593
29489
  return { sources: [], staleTexts: [] };
28594
29490
  }
28595
- function namespaceOf(key) {
29491
+ function namespaceOf2(key) {
28596
29492
  const at = key.lastIndexOf("::");
28597
29493
  return at === -1 ? "" : key.slice(0, at);
28598
29494
  }
@@ -28620,7 +29516,7 @@ function methodReading(tables, intf, value) {
28620
29516
  if (dot <= 0 || dot === value.length - 1) return null;
28621
29517
  const head2 = value.slice(0, dot);
28622
29518
  const tail = value.slice(dot + 1);
28623
- const ns = namespaceOf(intf.id);
29519
+ const ns = namespaceOf2(intf.id);
28624
29520
  const keys = [head2, ...ns && !head2.startsWith(`${ns}::`) ? [`${ns}::${head2}`] : []];
28625
29521
  for (const key of keys) {
28626
29522
  if (!tables.componentKeys.has(key)) continue;
@@ -28632,8 +29528,8 @@ function methodReading(tables, intf, value) {
28632
29528
  function typeReading(tables, intf, value) {
28633
29529
  const bound2 = value.includes("::") ? tables.boundTypes.get(`${intf.id}|${value}`) : void 0;
28634
29530
  const named2 = bound2 !== void 0 ? tables.types.filter((t) => t.id === bound2) : tables.types.filter((t) => t.id === value || typeMatchesRef(t, value));
28635
- const ns = namespaceOf(intf.id);
28636
- const local = (t) => namespaceOf(t.id) === ns ? 0 : 1;
29531
+ const ns = namespaceOf2(intf.id);
29532
+ const local = (t) => namespaceOf2(t.id) === ns ? 0 : 1;
28637
29533
  const ranked = [...named2].sort((a, b) => local(a) - local(b));
28638
29534
  return { signature: ranked.find((t) => t.kind === "signature"), other: ranked.find((t) => t.kind !== "signature") };
28639
29535
  }
@@ -29386,7 +30282,7 @@ function keyedSystem(system, key, subsystems) {
29386
30282
  };
29387
30283
  }
29388
30284
  function resolveFamilyTables(raws) {
29389
- const byKey2 = new Map(raws.map((r) => [r.record.namespace, r]));
30285
+ const byKey3 = new Map(raws.map((r) => [r.record.namespace, r]));
29390
30286
  const done = /* @__PURE__ */ new Set();
29391
30287
  const resolving = /* @__PURE__ */ new Set();
29392
30288
  const resolve41 = (raw) => {
@@ -29403,7 +30299,7 @@ function resolveFamilyTables(raws) {
29403
30299
  const source = e.from ?? e.subsystem;
29404
30300
  const producerKey = source !== void 0 ? raw.record.aliases.get(source) : void 0;
29405
30301
  if (producerKey === void 0 || producerTables.has(producerKey)) continue;
29406
- const producer = byKey2.get(producerKey);
30302
+ const producer = byKey3.get(producerKey);
29407
30303
  producerTables.set(producerKey, producer ? resolve41(producer) : null);
29408
30304
  audienceOf.set(producerKey, "project");
29409
30305
  }
@@ -33089,6 +33985,14 @@ var SpecWorkspace = class {
33089
33985
  }
33090
33986
  const receiving = this.moveTargetContract(to, ofTarget);
33091
33987
  if (typeof receiving === "string") return receiving;
33988
+ if (receiving) {
33989
+ for (const name of methods) {
33990
+ const holder2 = receiving.methods.find((m) => (m.previousNames ?? []).includes(`${receiving.id}.${name}`));
33991
+ if (holder2) {
33992
+ return `name-retired: "${receiving.id}" retired the name "${name}" \u2014 its method "${holder2.name}" lists "${receiving.id}.${name}" in its previousNames. Unsetting that previousNames releases the name.`;
33993
+ }
33994
+ }
33995
+ }
33092
33996
  const contractId = receiving?.id ?? `i${to}`;
33093
33997
  const holder = contracts.find((i) => i.id === contractId);
33094
33998
  if (!receiving && holder) {
@@ -33142,7 +34046,7 @@ var SpecWorkspace = class {
33142
34046
  for (const contract of contracts.filter((i) => i.component === source.id)) {
33143
34047
  const leaving = contract.methods.filter((m) => methods.includes(m.name));
33144
34048
  if (leaving.length === 0) continue;
33145
- arriving.push(...cloneSpec(leaving));
34049
+ arriving.push(...cloneSpec(leaving).map((m) => ({ ...m, previousNames: [...m.previousNames ?? [], `${contract.id}.${m.name}`] })));
33146
34050
  const remaining = cloneSpec(contract);
33147
34051
  remaining.methods = remaining.methods.filter((m) => !methods.includes(m.name));
33148
34052
  this.stageMoveEdit(plan6, "interface", contract.id, contract, remaining);
@@ -33325,9 +34229,9 @@ var SpecWorkspace = class {
33325
34229
  const reports = moveChangeReports(edits, false);
33326
34230
  const written = [];
33327
34231
  try {
33328
- for (const report2 of reports) {
33329
- const edit4 = edits.find((e) => e.kind === report2.kind && e.id === report2.id);
33330
- report2.notices.push(...this.saveMovedSpec(edit4.kind, edit4.after));
34232
+ for (const report3 of reports) {
34233
+ const edit4 = edits.find((e) => e.kind === report3.kind && e.id === report3.id);
34234
+ report3.notices.push(...this.saveMovedSpec(edit4.kind, edit4.after));
33331
34235
  written.push(edit4);
33332
34236
  }
33333
34237
  finish?.();
@@ -33568,6 +34472,9 @@ function getInterfacePath(id, componentId) {
33568
34472
  function getImplementationPath(id, contractId) {
33569
34473
  return current().getImplementationPath(id, contractId);
33570
34474
  }
34475
+ function getTypePath(id, subsystemId, group) {
34476
+ return current().getTypePath(id, subsystemId, group);
34477
+ }
33571
34478
  function loadSystemSpec() {
33572
34479
  return current().loadSystemSpec();
33573
34480
  }
@@ -35480,6 +36387,11 @@ function renameComponent(componentId, newId) {
35480
36387
  if (taken.length > 0) {
35481
36388
  throw new WaironError(`id-taken: the new id, or an id it implies, is already in use: ${taken.join(", ")}.`);
35482
36389
  }
36390
+ refuseRetiredIds([
36391
+ { kind: "component", id: newId },
36392
+ { kind: "interface", id: interfaceId },
36393
+ { kind: "implementation", id: implementationId }
36394
+ ]);
35483
36395
  const contracts = interfaces.filter((i) => i.component === componentId);
35484
36396
  const movingInterface = contracts.find((i) => i.id === `i${componentId}`);
35485
36397
  const movingImplementation = implementations.find((impl) => impl.id === `${componentId}_impl` && contracts.some((i) => i.id === impl.contract));
@@ -35501,18 +36413,21 @@ function renameComponent(componentId, newId) {
35501
36413
  return ref;
35502
36414
  };
35503
36415
  const specsDir = aiPathsAt(getProjectRoot()).specsDir();
36416
+ const derivesName = (entry) => entry.interface !== void 0 ? movingInterface !== void 0 && entry.interface === movingInterface.id : entry.typeDef === void 0 && entry.component === componentId;
36417
+ const keptDry = keepPublicNames(specsDir, derivesName, true);
35504
36418
  assertSpecsInReach(
35505
- [...renamed.map(({ kind, from }) => ({ kind, id: from })), ...rewriteRefFields(specsDir, remap, void 0, true), ...rekeyLintAllows(specsDir, rename, true)],
36419
+ [...renamed.map(({ kind, from }) => ({ kind, id: from })), ...keptDry.specs, ...rewriteRefFields(specsDir, remap, void 0, true), ...rekeyLintAllows(specsDir, rename, true)],
35506
36420
  `renaming component "${componentId}"`,
35507
36421
  Array.isArray(registerEdits) && registerEdits.length > 0
35508
36422
  );
35509
- const rewrittenRefs = rewriteRefFields(specsDir, remap);
36423
+ const kept = keepPublicNames(specsDir, derivesName);
36424
+ const rewrittenRefs = [...kept.specs, ...rewriteRefFields(specsDir, remap)];
35510
36425
  const allowsRekeyed = rekeyLintAllows(specsDir, rename);
35511
36426
  const rewritten = [...new Set([...rewrittenRefs, ...allowsRekeyed].filter((spec) => !renamed.some((moved) => moved.kind === spec.kind && moved.from === spec.id)).map((spec) => spec.id))];
35512
36427
  invalidateSpecCache();
35513
36428
  moveRenamedSpecs(componentId, newId, component, movingInterface, movingImplementation);
35514
36429
  const carried = projectConfigRepository.rekeyCarried(rename);
35515
- return { renamed, rewritten, carried };
36430
+ return { renamed, rewritten, carried, keptPublicNames: kept.names };
35516
36431
  }
35517
36432
  function moveRenamedSpecs(componentId, newId, component, movingInterface, movingImplementation) {
35518
36433
  const interfaceId = `i${newId}`;
@@ -35520,20 +36435,69 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
35520
36435
  const movedComponent2 = loadComponentSpec(componentId) ?? component;
35521
36436
  const movedInterface = movingInterface ? loadInterfaceSpec(movingInterface.id) ?? movingInterface : null;
35522
36437
  const movedImplementation = movingImplementation ? loadImplementationSpec(movingImplementation.id) ?? movingImplementation : null;
35523
- saveComponentSpec({ ...movedComponent2, id: newId });
35524
- if (movedInterface) saveInterfaceSpec({ ...movedInterface, id: interfaceId, component: newId });
36438
+ saveComponentSpec({ ...movedComponent2, id: newId, previousIds: traced(movedComponent2.previousIds, componentId) });
36439
+ if (movedInterface) {
36440
+ saveInterfaceSpec({ ...movedInterface, id: interfaceId, component: newId, previousIds: traced(movedInterface.previousIds, movedInterface.id) });
36441
+ }
35525
36442
  if (movedImplementation) {
35526
36443
  const oldFile = getImplementationPath(movedImplementation.id);
35527
36444
  if (path25.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path25.resolve(oldFile)) {
35528
36445
  fs16.unlinkSync(oldFile);
35529
36446
  }
35530
- saveImplementationSpec({ ...movedImplementation, id: implementationId });
36447
+ saveImplementationSpec({ ...movedImplementation, id: implementationId, previousIds: traced(movedImplementation.previousIds, movedImplementation.id) });
35531
36448
  }
35532
36449
  removeSpecFile2(getComponentPath(componentId), componentId);
35533
36450
  if (movingInterface) removeSpecFile2(getInterfacePath(movingInterface.id), movingInterface.id);
35534
36451
  if (movingImplementation) removeSpecFile2(getImplementationPath(movingImplementation.id), movingImplementation.id);
35535
36452
  invalidateSpecCache();
35536
36453
  }
36454
+ function traced(trace, former) {
36455
+ const out = [...trace ?? []];
36456
+ if (!out.includes(former)) out.push(former);
36457
+ return out;
36458
+ }
36459
+ function refuseRetiredIds(wanted) {
36460
+ const index = scanAllSpecs({ memberDepth: 0 });
36461
+ const retired = wanted.flatMap(({ kind, id }) => {
36462
+ const holder = specIndexRetiredBy(index, kind, id);
36463
+ return holder ? [`${kind} "${id}" is listed in the previousIds of "${holder}"`] : [];
36464
+ });
36465
+ if (retired.length > 0) {
36466
+ throw new WaironError(
36467
+ `id-retired: ${retired.join("; ")}. A consumer holding the old key would read the new spec as the renamed one; unsetting the holder's previousIds (sdd_update_spec unset) releases the id.`
36468
+ );
36469
+ }
36470
+ }
36471
+ function keepPublicNames(specsDir, derives, dryRun = false) {
36472
+ const names = [];
36473
+ const specs = [];
36474
+ for (const file of listFilesRecursive(specsDir, ".yaml")) {
36475
+ let raw;
36476
+ try {
36477
+ raw = readYamlFile(file);
36478
+ } catch {
36479
+ continue;
36480
+ }
36481
+ if (!raw || typeof raw !== "object") continue;
36482
+ const kind = specKind(raw);
36483
+ if (kind !== "subsystem" && kind !== "system" || !Array.isArray(raw.publicInterfaces)) continue;
36484
+ let changed = false;
36485
+ for (const entry of raw.publicInterfaces) {
36486
+ if (!entry || typeof entry !== "object" || entry.as !== void 0 || entry.id !== void 0) continue;
36487
+ if (!derives(entry)) continue;
36488
+ const source = entry.interface ?? entry.component ?? entry.typeDef;
36489
+ if (typeof source !== "string") continue;
36490
+ const name = source.split("::").pop() ?? source;
36491
+ entry.as = name;
36492
+ names.push(name);
36493
+ changed = true;
36494
+ }
36495
+ if (!changed) continue;
36496
+ if (!dryRun) writeYamlFile(file, raw);
36497
+ specs.push({ kind, id: kind === "system" ? "system" : String(raw.id) });
36498
+ }
36499
+ return { names: [...new Set(names)], specs };
36500
+ }
35537
36501
  function removeSpecFile2(file, id) {
35538
36502
  if (!fs16.existsSync(file)) return;
35539
36503
  try {
@@ -35582,6 +36546,12 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
35582
36546
  if (taken.length > 0) {
35583
36547
  throw new WaironError(`name-taken: ${taken.join(", ")} already declares a method under the name "${newName}".`);
35584
36548
  }
36549
+ const retiredOn = moving.flatMap((i) => i.methods.filter((m) => (m.previousNames ?? []).includes(`${i.id}.${newName}`)).map((m) => `"${i.id}.${m.name}"`));
36550
+ if (retiredOn.length > 0) {
36551
+ throw new WaironError(
36552
+ `name-retired: ${retiredOn.join(", ")} lists "${newName}" in its previousNames \u2014 the name is retired on that contract. Unsetting that previousNames releases it.`
36553
+ );
36554
+ }
35585
36555
  const implementations = loadImplementationSpecs();
35586
36556
  const movingContracts = new Set(moving.map((i) => i.id));
35587
36557
  const renamed = [];
@@ -35615,6 +36585,7 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
35615
36585
  methods: contract.methods.map((m) => m.name === methodName ? {
35616
36586
  ...m,
35617
36587
  name: newName,
36588
+ previousNames: traced(m.previousNames, `${contract.id}.${methodName}`),
35618
36589
  ...m.params === void 0 && m.signatureFrom === void 0 ? { signature: renameInSignature(m.signature, methodName, newName) } : {}
35619
36590
  } : m)
35620
36591
  });
@@ -35639,6 +36610,7 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
35639
36610
  const allowsRekeyed = rekeyLintAllows(specsDir, rename);
35640
36611
  const rewritten = [...new Set([...retargeted, ...allowsRekeyed].map((spec) => spec.id))];
35641
36612
  const mentions = collectMentions(specsDir, methodName, moving);
36613
+ const publishedIn = exportsPublishing(componentId, new Set(moving.map((i) => i.id)));
35642
36614
  const carried = projectConfigRepository.rekeyCarried(rename);
35643
36615
  return {
35644
36616
  component: componentId,
@@ -35648,9 +36620,25 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
35648
36620
  rewritten,
35649
36621
  mentions,
35650
36622
  ...pinnedSymbol ? { pinnedSymbol } : {},
35651
- carried
36623
+ carried,
36624
+ publishedIn
35652
36625
  };
35653
36626
  }
36627
+ function exportsPublishing(componentId, contracts) {
36628
+ const names = /* @__PURE__ */ new Set();
36629
+ const tables = [
36630
+ ...loadSubsystemSpecs().filter((s) => !s.id.includes("::")).map((s) => resolveSubsystemExports(s.id)),
36631
+ resolveProjectExports()
36632
+ ];
36633
+ for (const table of tables) {
36634
+ for (const entry of table.entries) {
36635
+ if (entry.kind !== "component" || entry.component !== componentId) continue;
36636
+ if (entry.interface !== void 0 && !contracts.has(entry.interface)) continue;
36637
+ names.add(entry.publicName);
36638
+ }
36639
+ }
36640
+ return [...names].sort();
36641
+ }
35654
36642
  function renameInSignature(signature, from, to) {
35655
36643
  return signature.replace(identifierPattern(from), to);
35656
36644
  }
@@ -35686,6 +36674,150 @@ function collectMentions(specsDir, methodName, moved) {
35686
36674
  function identifierPattern(methodName) {
35687
36675
  return new RegExp(`(?<![A-Za-z0-9_])${methodName}(?![A-Za-z0-9_])`);
35688
36676
  }
36677
+ function respellLike(written, oldId, newId) {
36678
+ const words2 = (id) => id.split(/[_-]+/).filter(Boolean);
36679
+ const pascal = (id) => words2(id).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
36680
+ const camel = (id) => {
36681
+ const p = pascal(id);
36682
+ return p.charAt(0).toLowerCase() + p.slice(1);
36683
+ };
36684
+ const kebab = (id) => words2(id).join("-");
36685
+ if (written === oldId) return newId;
36686
+ if (written === pascal(oldId)) return pascal(newId);
36687
+ if (written === camel(oldId)) return camel(newId);
36688
+ if (written === kebab(oldId)) return kebab(newId);
36689
+ if (written.includes("-")) return kebab(newId);
36690
+ return /^[A-Z]/.test(written) ? pascal(newId) : newId;
36691
+ }
36692
+ function renameType(typeId, newId) {
36693
+ const all = loadTypeSpecs();
36694
+ const cut = typeId.lastIndexOf("::");
36695
+ const qualifier = cut >= 0 ? typeId.slice(0, cut) : void 0;
36696
+ const ownSubsystem = qualifier !== void 0 && loadSubsystemSpecs().some((s) => s.id === qualifier);
36697
+ if (qualifier !== void 0 && !ownSubsystem) {
36698
+ throw new WaironError(`chained-type: "${typeId}" lives in another project; rename it from that project's own root.`);
36699
+ }
36700
+ const type = qualifier !== void 0 ? all.find((t) => t.id === typeId.slice(cut + 2) && t.subsystem === qualifier) ?? null : loadTypeSpec(typeId);
36701
+ if (!type) throw new WaironError(`type-missing: no type has the id "${typeId}".`);
36702
+ if (type.id.includes("::")) {
36703
+ throw new WaironError(`chained-type: "${type.id}" lives in another project; rename it from that project's own root.`);
36704
+ }
36705
+ const oldId = type.id;
36706
+ if (!SpecIdSchema.safeParse(newId).success) {
36707
+ throw new WaironError(`invalid-id: "${newId}" is not a lowercase identifier with no namespace separator.`);
36708
+ }
36709
+ const sameOwner = (t) => (t.subsystem ?? "") === (type.subsystem ?? "");
36710
+ if (all.some((t) => t !== type && t.id === newId && sameOwner(t))) {
36711
+ throw new WaironError(`id-taken: another type of ${type.subsystem ? `"${type.subsystem}"` : "the system"} already has the id "${newId}".`);
36712
+ }
36713
+ refuseRetiredIds([{ kind: "type", id: qualifiedTypeId({ id: newId, subsystem: type.subsystem }) }]);
36714
+ const rename = { specs: [{ from: oldId, to: newId }] };
36715
+ const registerEdits = projectConfigRepository.rekeyCarried(rename, true);
36716
+ const components = new Map(loadComponentSpecs().map((c) => [c.id, c.subsystem]));
36717
+ const others = all.filter((t) => t !== type);
36718
+ const namesType = (token, owner) => {
36719
+ if (!typeMatchesRef(type, token)) return false;
36720
+ if (!others.some((t) => typeMatchesRef(t, token))) return true;
36721
+ return (owner ?? "") === (type.subsystem ?? "");
36722
+ };
36723
+ const respellText = (text3, owner) => {
36724
+ if (typeof text3 !== "string") return text3;
36725
+ return text3.replace(/[A-Za-z_][A-Za-z0-9_-]*(?:(?:::|\.)[A-Za-z_][A-Za-z0-9_-]*)*/g, (token) => {
36726
+ if (!namesType(token, owner)) return token;
36727
+ const parts = token.split(/(::|\.)/);
36728
+ parts[parts.length - 1] = respellLike(parts[parts.length - 1], oldId, newId);
36729
+ return parts.join("");
36730
+ });
36731
+ };
36732
+ const specsDir = aiPathsAt(getProjectRoot()).specsDir();
36733
+ const derivesName = (entry) => entry.interface === void 0 && entry.component === void 0 && typeof entry.typeDef === "string" && namesType(entry.typeDef, void 0);
36734
+ const respellSpec = (raw) => {
36735
+ const kind = specKind(raw);
36736
+ const before = JSON.stringify(raw);
36737
+ const at = (holder, key, owner) => {
36738
+ if (holder && typeof holder[key] === "string") holder[key] = respellText(holder[key], owner);
36739
+ };
36740
+ const methodPositions = (method, owner, sourced) => {
36741
+ if (!method || typeof method !== "object") return;
36742
+ for (const p of Array.isArray(method.params) ? method.params : []) at(p, "type", owner);
36743
+ at(method, "returns", owner);
36744
+ if (sourced && typeof method.signatureFrom === "string" && namesType(method.signatureFrom, owner)) at(method, "signatureFrom", owner);
36745
+ if (typeof method.signature === "string") {
36746
+ if (Array.isArray(method.params)) method.signature = deriveMethodSignature(method) ?? method.signature;
36747
+ else {
36748
+ const close2 = method.signature.lastIndexOf(")");
36749
+ if (close2 >= 0) method.signature = method.signature.slice(0, close2 + 1) + respellText(method.signature.slice(close2 + 1), owner);
36750
+ }
36751
+ }
36752
+ };
36753
+ if (kind === "interface") {
36754
+ const owner = components.get(String(raw.component));
36755
+ for (const m of Array.isArray(raw.methods) ? raw.methods : []) methodPositions(m, owner, true);
36756
+ } else if (kind === "type") {
36757
+ const owner = typeof raw.subsystem === "string" ? raw.subsystem : void 0;
36758
+ for (const f of Array.isArray(raw.fields) ? raw.fields : []) {
36759
+ at(f, "type", owner);
36760
+ if (typeof f?.references === "string") {
36761
+ const [head2, ...rest] = f.references.split(".");
36762
+ if (namesType(head2, owner)) f.references = [respellText(head2, owner), ...rest].join(".");
36763
+ }
36764
+ }
36765
+ for (const p of Array.isArray(raw.params) ? raw.params : []) at(p, "type", owner);
36766
+ at(raw, "returns", owner);
36767
+ if (typeof raw.linkedEntity === "string" && namesType(raw.linkedEntity, owner)) at(raw, "linkedEntity", owner);
36768
+ for (const m of Array.isArray(raw.methods) ? raw.methods : []) methodPositions(m, owner, false);
36769
+ } else if (kind === "subsystem" || kind === "system") {
36770
+ const owner = kind === "subsystem" ? String(raw.id) : void 0;
36771
+ for (const e of Array.isArray(raw.publicInterfaces) ? raw.publicInterfaces : []) {
36772
+ if (e && typeof e.typeDef === "string" && namesType(e.typeDef, owner)) at(e, "typeDef", owner);
36773
+ }
36774
+ }
36775
+ return JSON.stringify(raw) !== before;
36776
+ };
36777
+ const respellAll = (dryRun) => {
36778
+ const out = [];
36779
+ for (const file of listFilesRecursive(specsDir, ".yaml")) {
36780
+ let raw;
36781
+ try {
36782
+ raw = readYamlFile(file);
36783
+ } catch {
36784
+ continue;
36785
+ }
36786
+ const kind = raw && typeof raw === "object" ? specKind(raw) : void 0;
36787
+ if (!kind || !respellSpec(raw)) continue;
36788
+ if (!dryRun) writeYamlFile(file, raw);
36789
+ out.push({ kind, id: kind === "system" ? "system" : String(raw.id) });
36790
+ }
36791
+ return out;
36792
+ };
36793
+ assertSpecsInReach(
36794
+ [{ kind: "type", id: oldId }, ...keepPublicNames(specsDir, derivesName, true).specs, ...respellAll(true), ...rekeyLintAllows(specsDir, rename, true)],
36795
+ `renaming type "${typeId}"`,
36796
+ Array.isArray(registerEdits) && registerEdits.length > 0
36797
+ );
36798
+ const kept = keepPublicNames(specsDir, derivesName);
36799
+ const respelled = respellAll(false);
36800
+ const allowsRekeyed = rekeyLintAllows(specsDir, rename);
36801
+ const rewritten = [...new Set([...kept.specs, ...respelled, ...allowsRekeyed].filter((spec) => !(spec.kind === "type" && spec.id === oldId)).map((spec) => spec.id))];
36802
+ invalidateSpecCache();
36803
+ const moved = loadTypeSpecs().find((t) => t.id === oldId && (t.subsystem ?? "") === (type.subsystem ?? "")) ?? type;
36804
+ saveSpec("type", { ...moved, id: newId, previousIds: traced(moved.previousIds, oldId) });
36805
+ invalidateSpecCache();
36806
+ removeSpecFile2(typeFileOf(oldId, type), oldId);
36807
+ if (loadTypeSpecs().some((t) => t.id === oldId && (t.subsystem ?? "") === (type.subsystem ?? ""))) deleteSpec("type", oldId);
36808
+ invalidateSpecCache();
36809
+ const carried = projectConfigRepository.rekeyCarried(rename);
36810
+ return {
36811
+ from: qualifiedTypeId(type),
36812
+ to: qualifiedTypeId({ id: newId, subsystem: type.subsystem }),
36813
+ rewritten,
36814
+ keptPublicNames: kept.names,
36815
+ carried
36816
+ };
36817
+ }
36818
+ function typeFileOf(id, type) {
36819
+ return getTypePath(id, type.subsystem, type.group);
36820
+ }
35689
36821
  function moveMountToMembers(alias) {
35690
36822
  const family = graph();
35691
36823
  const member = family.nodes.find((n) => n.parent === "" && n.mountAlias === alias);
@@ -35871,18 +37003,18 @@ function normalizePath(p) {
35871
37003
  var fs18 = __toESM(require("fs"));
35872
37004
  var os4 = __toESM(require("os"));
35873
37005
  var path27 = __toESM(require("path"));
35874
- var import_zod10 = require("zod");
35875
- var VariantDefSchema = import_zod10.z.object({
37006
+ var import_zod11 = require("zod");
37007
+ var VariantDefSchema = import_zod11.z.object({
35876
37008
  /** Variant id referenced by a component's `variant` (e.g. "publisher", "org/external-config-adapter"). */
35877
- id: import_zod10.z.string().min(1),
37009
+ id: import_zod11.z.string().min(1),
35878
37010
  /** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Orchestrator, …). */
35879
- base: import_zod10.z.string().min(1),
37011
+ base: import_zod11.z.string().min(1),
35880
37012
  /** How to implement a component of this variant — the recipe the implementer follows and reuses across same-variant components. */
35881
- guidance: import_zod10.z.string().min(1),
37013
+ guidance: import_zod11.z.string().min(1),
35882
37014
  /** Optional: this variant only applies for the given target language (else it applies everywhere). */
35883
- target: import_zod10.z.string().optional(),
37015
+ target: import_zod11.z.string().optional(),
35884
37016
  /** Optional: this variant only applies under the given architectural profile. */
35885
- profile: import_zod10.z.string().optional()
37017
+ profile: import_zod11.z.string().optional()
35886
37018
  });
35887
37019
  function globalVariantsDir() {
35888
37020
  return process.env.WAIRON_VARIANTS_DIR ?? path27.join(os4.homedir(), ".wairon", "variants");
@@ -37045,19 +38177,19 @@ function retireSpecialists(apply3) {
37045
38177
  if (decision === void 0) return "pending";
37046
38178
  return decision === "unset" ? "neither" : decision;
37047
38179
  }
37048
- const dependency = byId.get(id);
37049
- if (dependency?.componentType === "Orchestrator" && dependency.dependencyClass) return dependency.dependencyClass;
37050
- if (dependency && DATA_FACADES.has(dependency.componentType)) return "facade";
38180
+ const dependency2 = byId.get(id);
38181
+ if (dependency2?.componentType === "Orchestrator" && dependency2.dependencyClass) return dependency2.dependencyClass;
38182
+ if (dependency2 && DATA_FACADES.has(dependency2.componentType)) return "facade";
37051
38183
  return "neither";
37052
38184
  };
37053
38185
  const described = (id) => {
37054
- const dependency = byId.get(id);
38186
+ const dependency2 = byId.get(id);
37055
38187
  const fit = fitOf(id);
37056
38188
  let what;
37057
- if (!dependency) what = "missing";
38189
+ if (!dependency2) what = "missing";
37058
38190
  else if (fit === "pure" || fit === "read") what = fit;
37059
- else if (dependency.componentType === "Orchestrator" || specialistIds.has(id)) what = "workflow";
37060
- else what = dependency.componentType;
38191
+ else if (dependency2.componentType === "Orchestrator" || specialistIds.has(id)) what = "workflow";
38192
+ else what = dependency2.componentType;
37061
38193
  return `${id} (${what})`;
37062
38194
  };
37063
38195
  const reasonFor = (specialist, decision, settled2) => {
@@ -38242,7 +39374,7 @@ function buildServerInstructions2() {
38242
39374
  // src/mcp/server.ts
38243
39375
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
38244
39376
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
38245
- var import_zod11 = require("zod");
39377
+ var import_zod12 = require("zod");
38246
39378
  var import_types12 = require("@modelcontextprotocol/sdk/types.js");
38247
39379
  var path48 = __toESM(require("path"));
38248
39380
  var crypto10 = __toESM(require("crypto"));
@@ -38354,6 +39486,7 @@ function refuseUnknownOwner(kind, merged, storedOwner) {
38354
39486
  }
38355
39487
  var STORE_MANAGED_FIELDS = /* @__PURE__ */ new Set(["status", "updatedAt"]);
38356
39488
  var ALWAYS_CARRIED_FIELDS = /* @__PURE__ */ new Set(["ext"]);
39489
+ var TRACED_KINDS = /* @__PURE__ */ new Set(["component", "interface", "implementation", "type"]);
38357
39490
  var STATUS_ORDER = ["draft", "design", "complete"];
38358
39491
  var STATUSED_KINDS = /* @__PURE__ */ new Set(["subsystem", "component", "interface", "implementation"]);
38359
39492
  var MISSING_PARENT = {
@@ -38400,6 +39533,10 @@ function applyRestatement(restatement, loaded, parent) {
38400
39533
  const carried = carryInto(restatement, existing, candidate);
38401
39534
  const cleared = clearedByOmission(existing, candidate, restatement.fields);
38402
39535
  stampLifecycle(candidate, existing, status.status);
39536
+ if (restatement.kind === "interface") {
39537
+ const retired = retiredMethodNames(existing, candidate);
39538
+ if (retired) return refused(restatement, replacedExisting, `${retired} Nothing was written.`);
39539
+ }
38403
39540
  if (restatement.kind === "interface") {
38404
39541
  const restated = restatedSources(candidate.methods);
38405
39542
  if (restated.length) return refused(restatement, replacedExisting, `${restatedSourceRefusal(String(candidate.id), restated)} Nothing was written.`);
@@ -38494,9 +39631,32 @@ function carryInto(restatement, existing, candidate) {
38494
39631
  for (const field of carryUnexpressed(prev, method, restatement.memberFields)) carried.push(`${field} (${String(method.name)})`);
38495
39632
  }
38496
39633
  }
39634
+ if (restatement.kind === "interface" && !restatement.memberFields && Array.isArray(candidate.methods)) {
39635
+ const stored = existing.methods ?? [];
39636
+ for (const method of candidate.methods) {
39637
+ const prev = stored.find((p) => p.name === method.name);
39638
+ if (prev?.previousNames === void 0 || method.previousNames !== void 0) continue;
39639
+ method.previousNames = prev.previousNames;
39640
+ carried.push(`previousNames (${String(method.name)})`);
39641
+ }
39642
+ }
38497
39643
  carried.push(...carryUnexpressed(existing, candidate, [...restatement.fields, "createdAt"]));
38498
39644
  return carried;
38499
39645
  }
39646
+ function retiredMethodNames(existing, candidate) {
39647
+ const id = String(candidate.id);
39648
+ const storedNames = new Set((existing?.methods ?? []).map((m) => m.name));
39649
+ const methods = Array.isArray(candidate.methods) ? candidate.methods : [];
39650
+ const holders = [...methods, ...existing?.methods ?? []];
39651
+ for (const method of methods) {
39652
+ if (storedNames.has(method.name)) continue;
39653
+ const holder = holders.find((m) => m !== method && (m.previousNames ?? []).includes(`${id}.${method.name}`));
39654
+ if (holder) {
39655
+ return `Refusing to write interface "${id}": name-retired \u2014 the new method "${method.name}" takes a name this contract retired ("${holder.name}" lists "${id}.${method.name}" in its previousNames). Unsetting that previousNames releases the name.`;
39656
+ }
39657
+ }
39658
+ return void 0;
39659
+ }
38500
39660
  function carryUnexpressed(existing, next, expressed) {
38501
39661
  if (!existing) return [];
38502
39662
  const carried = [];
@@ -38603,6 +39763,16 @@ function writeSpec(restatement) {
38603
39763
  const parent = parentRef ? loadSpec(parentRef.kind, parentRef.id) : null;
38604
39764
  const id = restatement.kind === "system" ? "system" : restatement.spec.id;
38605
39765
  const existing = loadSpec(restatement.kind, id);
39766
+ if (!existing && TRACED_KINDS.has(restatement.kind)) {
39767
+ const spec = restatement.spec;
39768
+ const key = restatement.kind === "type" ? qualifiedTypeId(spec) : spec.id;
39769
+ const holder = specIndexRetiredBy(scanAllSpecs({ memberDepth: 0 }), restatement.kind, key);
39770
+ if (holder) {
39771
+ throw new Error(
39772
+ `id-retired: ${restatement.kind} "${spec.id}" is listed in the previousIds of "${holder}", which was renamed from it. Left alone, a consumer holding the old key would read the new spec as the renamed one. Unsetting the holder's previousIds (sdd_update_spec with {"unset": ["previousIds"]}) releases the id, at the cost that such a consumer reads a delete and an add. Nothing was written.`
39773
+ );
39774
+ }
39775
+ }
38606
39776
  const application = applyRestatement(restatement, existing, parent);
38607
39777
  if (application.refusal !== void 0) throw new Error(application.refusal);
38608
39778
  const gateNotices = restatement.kind === "component" ? judgeComponent(application.spec, bound2) : [];
@@ -38672,17 +39842,17 @@ function updateSpecGated(kind, id, delta, dryRun) {
38672
39842
  const testRoots = bound2.rules?.conformance?.testRoots ?? [];
38673
39843
  const stored = loadSpec(kind, id);
38674
39844
  const gate = componentCandidateGate(bound2, stored?.subsystem, stored);
38675
- const report2 = updateSpec(kind, id, delta, gate, dryRun);
38676
- const changed = changedMethods(report2);
39845
+ const report3 = updateSpec(kind, id, delta, gate, dryRun);
39846
+ const changed = changedMethods(report3);
38677
39847
  if (changed.length > 0 && testRoots.length > 0) {
38678
39848
  const written = Array.isArray(delta?.methods) ? delta.methods : [];
38679
- report2.testsToRevisit = testsInvalidatedBy(kind, id, changed, [stored], bound2, written);
39849
+ report3.testsToRevisit = testsInvalidatedBy(kind, id, changed, [stored], bound2, written);
38680
39850
  }
38681
- return report2;
39851
+ return report3;
38682
39852
  }
38683
- function changedMethods(report2) {
39853
+ function changedMethods(report3) {
38684
39854
  const named2 = /* @__PURE__ */ new Set();
38685
- for (const change of report2.changes) {
39855
+ for (const change of report3.changes) {
38686
39856
  const [field, name] = change.path.split(".");
38687
39857
  if (field === "methods" && name) named2.add(name);
38688
39858
  }
@@ -39473,10 +40643,10 @@ function addPin(ctx, consumer, alias) {
39473
40643
  function planEntry(ctx, producer, ref, table, reason) {
39474
40644
  const target = targetOf(ref);
39475
40645
  if (!target) {
39476
- return report(ctx, "target-missing", ref, `${ref.specId} names "${ref.target}", but ${label3(producer.namespace)} declares no component, subsystem-owned type or project-level type of that id \u2014 the reference is wrong`);
40646
+ return report2(ctx, "target-missing", ref, `${ref.specId} names "${ref.target}", but ${label3(producer.namespace)} declares no component, subsystem-owned type or project-level type of that id \u2014 the reference is wrong`);
39477
40647
  }
39478
40648
  if (target.kind === "subsystem") {
39479
- return report(ctx, "subsystem-reference", ref, `${ref.specId} re-exports ${label3(producer.namespace)}'s subsystem "${target.id}" wholesale \u2014 no L0 entry short of exporting it expresses that; rewrite the reference to name the items it uses`);
40649
+ return report2(ctx, "subsystem-reference", ref, `${ref.specId} re-exports ${label3(producer.namespace)}'s subsystem "${target.id}" wholesale \u2014 no L0 entry short of exporting it expresses that; rewrite the reference to name the items it uses`);
39480
40650
  }
39481
40651
  if (target.source === void 0) return decideOwnType(ctx, producer, ref, target, table, reason);
39482
40652
  return decideEntry(ctx, producer, ref, target, table, resolveSubsystemExports(target.source), reason);
@@ -39498,7 +40668,7 @@ function decideOwnType(ctx, producer, ref, target, table, reason) {
39498
40668
  const local = localIn3(producer.namespace, target.id);
39499
40669
  const taken = table.entries.find((e) => e.publicName === local && exportTargetKey(e) !== key) ?? entryOf(ctx, producer).exports.find((e) => e.publicName === local && (e.component ?? e.typeDef) !== local);
39500
40670
  if (taken) {
39501
- return report(ctx, "name-taken", ref, `"${local}" already names another item in ${label3(producer.namespace)} \u2014 export the type "${target.id}" under a name a person chooses`);
40671
+ return report2(ctx, "name-taken", ref, `"${local}" already names another item in ${label3(producer.namespace)} \u2014 export the type "${target.id}" under a name a person chooses`);
39502
40672
  }
39503
40673
  mergeEntry(entryOf(ctx, producer), target, void 0, local, local, ref, reason);
39504
40674
  return "planned";
@@ -39507,18 +40677,18 @@ function decideEntry(ctx, producer, ref, target, table, published, reason) {
39507
40677
  const key = targetKey(target);
39508
40678
  const at = published.entries.filter((e) => exportTargetKey({ ...e, interface: void 0 }) === key);
39509
40679
  if (at.length === 0) {
39510
- return report(ctx, "target-unpublished", ref, `"${target.id}" is not in its subsystem's L1 table, so no L0 re-export can follow it \u2014 publish it at L1 first, or the reference is wrong`);
40680
+ return report2(ctx, "target-unpublished", ref, `"${target.id}" is not in its subsystem's L1 table, so no L0 re-export can follow it \u2014 publish it at L1 first, or the reference is wrong`);
39511
40681
  }
39512
40682
  const exported = table.entries.filter((e) => exportTargetKey({ ...e, interface: void 0 }) === key);
39513
40683
  if (exported.length > 0 && reachableThrough(exported, ref)) return "present";
39514
40684
  if (exported.length > 0 || !reachableThrough(at, ref)) {
39515
- return report(ctx, "narrowed", ref, `"${target.id}" is exported under a narrowing that does not declare "${ref.member ?? "what the reference reaches"}" \u2014 widen the narrowing or reach another member`);
40685
+ return report2(ctx, "narrowed", ref, `"${target.id}" is exported under a narrowing that does not declare "${ref.member ?? "what the reference reaches"}" \u2014 widen the narrowing or reach another member`);
39516
40686
  }
39517
40687
  const local = localIn3(producer.namespace, target.id);
39518
40688
  const publicName = local.split("::").pop();
39519
40689
  const taken = table.entries.find((e) => e.publicName === publicName && exportTargetKey({ ...e, interface: void 0 }) !== key) ?? entryOf(ctx, producer).exports.find((e) => e.publicName === publicName && (e.component ?? e.typeDef) !== local);
39520
40690
  if (taken) {
39521
- return report(ctx, "name-taken", ref, `"${publicName}" already names another item in ${label3(producer.namespace)} \u2014 export "${target.id}" under a name a person chooses`);
40691
+ return report2(ctx, "name-taken", ref, `"${publicName}" already names another item in ${label3(producer.namespace)} \u2014 export "${target.id}" under a name a person chooses`);
39522
40692
  }
39523
40693
  mergeEntry(entryOf(ctx, producer), target, localIn3(producer.namespace, target.source), local, publicName, ref, reason);
39524
40694
  return "planned";
@@ -39559,7 +40729,7 @@ function addSorted(list, value) {
39559
40729
  list.sort();
39560
40730
  }
39561
40731
  }
39562
- function report(ctx, kind, ref, detail) {
40732
+ function report2(ctx, kind, ref, detail) {
39563
40733
  ctx.findings.push({ kind, project: ref.producer, detail, reference: ref, blocking: false });
39564
40734
  return "refused";
39565
40735
  }
@@ -42100,30 +43270,30 @@ function structured(content, data) {
42100
43270
  return { content: [{ type: "text", text: content }], structuredContent: data };
42101
43271
  }
42102
43272
  function migrationTool(request, dryRun) {
42103
- let report2;
43273
+ let report3;
42104
43274
  try {
42105
- report2 = run2(request, dryRun);
43275
+ report3 = run2(request, dryRun);
42106
43276
  } catch (e) {
42107
43277
  return errMessage(e);
42108
43278
  }
42109
- const view = migrationView(report2, dryRun === true);
43279
+ const view = migrationView(report3, dryRun === true);
42110
43280
  const body = JSON.stringify(view, null, 2);
42111
- if (report2.plan.refusals.length > 0) return errText(`the ${request.verb} migration is refused; nothing was written.
43281
+ if (report3.plan.refusals.length > 0) return errText(`the ${request.verb} migration is refused; nothing was written.
42112
43282
  ${body}`);
42113
- if (!report2.applied && report2.outcome) {
42114
- const how = report2.outcome.restored ? "the family was restored exactly as before" : "some files could not be restored: a person must run `wairon doctor --fix` in the project";
42115
- return errText(`the ${request.verb} migration failed (${report2.outcome.failure ?? "unknown failure"}) and ${how}.
43283
+ if (!report3.applied && report3.outcome) {
43284
+ const how = report3.outcome.restored ? "the family was restored exactly as before" : "some files could not be restored: a person must run `wairon doctor --fix` in the project";
43285
+ return errText(`the ${request.verb} migration failed (${report3.outcome.failure ?? "unknown failure"}) and ${how}.
42116
43286
  ${body}`);
42117
43287
  }
42118
43288
  return structured(body, view);
42119
43289
  }
42120
- function migrationView(report2, dryRun) {
42121
- const plan6 = report2.plan;
43290
+ function migrationView(report3, dryRun) {
43291
+ const plan6 = report3.plan;
42122
43292
  return {
42123
43293
  dryRun,
42124
- applied: report2.applied,
42125
- relock: report2.applied ? report2.relock : plan6.relock,
42126
- ...report2.outcome ? { outcome: { committed: report2.outcome.committed, restored: report2.outcome.restored, unrestored: report2.outcome.unrestored, ...report2.outcome.failure ? { failure: report2.outcome.failure } : {} } } : {},
43294
+ applied: report3.applied,
43295
+ relock: report3.applied ? report3.relock : plan6.relock,
43296
+ ...report3.outcome ? { outcome: { committed: report3.outcome.committed, restored: report3.outcome.restored, unrestored: report3.outcome.unrestored, ...report3.outcome.failure ? { failure: report3.outcome.failure } : {} } } : {},
42127
43297
  plan: {
42128
43298
  verb: plan6.request.verb,
42129
43299
  familyRoot: plan6.familyRoot,
@@ -42139,69 +43309,69 @@ function jsonStructured(value) {
42139
43309
  return structured(JSON.stringify(value, null, 2), value);
42140
43310
  }
42141
43311
  var staleServerOutput = {
42142
- staleServer: import_zod11.z.boolean().optional().describe(
43312
+ staleServer: import_zod12.z.boolean().optional().describe(
42143
43313
  "True when the wairon build on disk changed after this server started \u2014 the structured twin of the text answer's STALE SERVER banner. When the rebuild left the spec and tool schemas alone, writes still go through; reconnect to run the new code."
42144
43314
  ),
42145
- writesRefused: import_zod11.z.boolean().optional().describe(
43315
+ writesRefused: import_zod12.z.boolean().optional().describe(
42146
43316
  "True when the rebuild changed a spec or tool schema (or its schemas could not be compared): every spec write through this server is refused and writes nothing, because it would silently drop the fields only the new build knows. The human has to reconnect the server (/mcp reconnect wairon)."
42147
43317
  )
42148
43318
  };
42149
43319
  var externalPinsOutput = {
42150
- pins: import_zod11.z.array(import_zod11.z.object({
42151
- alias: import_zod11.z.string(),
42152
- outcome: import_zod11.z.enum(["pinned", "unchanged", "unresolved", "unreachable"]),
42153
- project: import_zod11.z.string().optional(),
42154
- snapshot: import_zod11.z.string().optional(),
42155
- digest: import_zod11.z.string().optional(),
42156
- usedNames: import_zod11.z.number(),
42157
- unexported: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())),
42158
- detail: import_zod11.z.string().optional()
43320
+ pins: import_zod12.z.array(import_zod12.z.object({
43321
+ alias: import_zod12.z.string(),
43322
+ outcome: import_zod12.z.enum(["pinned", "unchanged", "unresolved", "unreachable"]),
43323
+ project: import_zod12.z.string().optional(),
43324
+ snapshot: import_zod12.z.string().optional(),
43325
+ digest: import_zod12.z.string().optional(),
43326
+ usedNames: import_zod12.z.number(),
43327
+ unexported: import_zod12.z.array(import_zod12.z.record(import_zod12.z.unknown())),
43328
+ detail: import_zod12.z.string().optional()
42159
43329
  })).describe("One outcome per alias pinned, in declaration order, with its unexported references."),
42160
43330
  ...staleServerOutput
42161
43331
  };
42162
43332
  var externalStatusesOutput = {
42163
- statuses: import_zod11.z.array(import_zod11.z.object({
42164
- alias: import_zod11.z.string(),
42165
- project: import_zod11.z.string(),
42166
- sourceKind: import_zod11.z.string(),
42167
- pinned: import_zod11.z.boolean(),
42168
- reachable: import_zod11.z.boolean(),
42169
- stale: import_zod11.z.boolean(),
42170
- drifted: import_zod11.z.boolean().optional(),
42171
- uses: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())),
42172
- detail: import_zod11.z.string().optional(),
42173
- outOfReach: import_zod11.z.boolean().optional(),
42174
- pinnedDigest: import_zod11.z.string().optional().describe("The content digest the lock recorded; provenance, never compared here."),
42175
- pinnedCommit: import_zod11.z.string().optional().describe("The producer commit the lock recorded, for one in another repository; provenance only.")
43333
+ statuses: import_zod12.z.array(import_zod12.z.object({
43334
+ alias: import_zod12.z.string(),
43335
+ project: import_zod12.z.string(),
43336
+ sourceKind: import_zod12.z.string(),
43337
+ pinned: import_zod12.z.boolean(),
43338
+ reachable: import_zod12.z.boolean(),
43339
+ stale: import_zod12.z.boolean(),
43340
+ drifted: import_zod12.z.boolean().optional(),
43341
+ uses: import_zod12.z.array(import_zod12.z.record(import_zod12.z.unknown())),
43342
+ detail: import_zod12.z.string().optional(),
43343
+ outOfReach: import_zod12.z.boolean().optional(),
43344
+ pinnedDigest: import_zod12.z.string().optional().describe("The content digest the lock recorded; provenance, never compared here."),
43345
+ pinnedCommit: import_zod12.z.string().optional().describe("The producer commit the lock recorded, for one in another repository; provenance only.")
42176
43346
  })).describe("One status per declared external, in declaration order; EXTERNAL_CHECK_UNAVAILABLE marks what could not be compared."),
42177
43347
  ...staleServerOutput
42178
43348
  };
42179
- function renderChangeReport(report2) {
42180
- const lines = [report2.dryRun ? `DRY RUN \u2014 nothing was written. ${report2.summary}` : report2.summary];
42181
- for (const change of report2.changes) {
43349
+ function renderChangeReport(report3) {
43350
+ const lines = [report3.dryRun ? `DRY RUN \u2014 nothing was written. ${report3.summary}` : report3.summary];
43351
+ for (const change of report3.changes) {
42182
43352
  const to = change.after === void 0 ? "" : `: ${JSON.stringify(change.after)}`;
42183
43353
  const from = change.before === void 0 ? "" : ` (was ${JSON.stringify(change.before)})`;
42184
- lines.push(`- ${change.path} ${report2.dryRun ? `would be ${change.change}` : change.change}${to}${from}`);
43354
+ lines.push(`- ${change.path} ${report3.dryRun ? `would be ${change.change}` : change.change}${to}${from}`);
42185
43355
  }
42186
- if (report2.ineffective.length) {
42187
- lines.push("", "NO EFFECT:", ...report2.ineffective.map((i) => `- ${i}`));
43356
+ if (report3.ineffective.length) {
43357
+ lines.push("", "NO EFFECT:", ...report3.ineffective.map((i) => `- ${i}`));
42188
43358
  }
42189
- if (report2.notices.length) lines.push("", "NOTICE:", ...report2.notices.map((n) => `- ${n}`));
42190
- if (report2.strippedKeys?.length) {
42191
- lines.push("", `DROPPED FROM THE STORED FILE (${report2.dryRun ? "would be " : ""}removed \u2014 the schema does not know them):`, ...report2.strippedKeys.map((k) => `- ${k}`));
43359
+ if (report3.notices.length) lines.push("", "NOTICE:", ...report3.notices.map((n) => `- ${n}`));
43360
+ if (report3.strippedKeys?.length) {
43361
+ lines.push("", `DROPPED FROM THE STORED FILE (${report3.dryRun ? "would be " : ""}removed \u2014 the schema does not know them):`, ...report3.strippedKeys.map((k) => `- ${k}`));
42192
43362
  }
42193
- lines.push(...renderRespellings(report2.respellings));
42194
- lines.push(...renderTestsToRevisit(report2.testsToRevisit));
43363
+ lines.push(...renderRespellings(report3.respellings));
43364
+ lines.push(...renderTestsToRevisit(report3.testsToRevisit));
42195
43365
  return lines.join("\n");
42196
43366
  }
42197
43367
  var SPEC_KINDS = ["system", "subsystem", "component", "interface", "implementation", "type"];
42198
43368
  var STATUS_VALUES = ["draft", "design", "complete"];
42199
- var testsToRevisitOutput = import_zod11.z.array(import_zod11.z.object({
42200
- method: import_zod11.z.string().describe("The contract method this write changed or deleted."),
42201
- symbol: import_zod11.z.string().describe("The code-level name searched for: the method's `symbol` when it declares one, else its name."),
42202
- imported: import_zod11.z.array(import_zod11.z.string()).describe("Test files that IMPORT that symbol \u2014 the high-confidence list, because an import is a binding and not a coincidence."),
42203
- mentioned: import_zod11.z.array(import_zod11.z.string()).describe("Test files that name the symbol without importing it \u2014 usually a test driving it through a portal. Empty when `indiscriminate` is true."),
42204
- indiscriminate: import_zod11.z.boolean().describe("True when the bare name matched more than a tenth of the test suite, so the mention list was withheld as noise.")
43369
+ var testsToRevisitOutput = import_zod12.z.array(import_zod12.z.object({
43370
+ method: import_zod12.z.string().describe("The contract method this write changed or deleted."),
43371
+ symbol: import_zod12.z.string().describe("The code-level name searched for: the method's `symbol` when it declares one, else its name."),
43372
+ imported: import_zod12.z.array(import_zod12.z.string()).describe("Test files that IMPORT that symbol \u2014 the high-confidence list, because an import is a binding and not a coincidence."),
43373
+ mentioned: import_zod12.z.array(import_zod12.z.string()).describe("Test files that name the symbol without importing it \u2014 usually a test driving it through a portal. Empty when `indiscriminate` is true."),
43374
+ indiscriminate: import_zod12.z.boolean().describe("True when the bare name matched more than a tenth of the test suite, so the mention list was withheld as noise.")
42205
43375
  })).describe(
42206
43376
  "The tests that encode a method this write changed or deleted, one entry per such method. Empty when the write touched no method, when the project declares no `rules.conformance.testRoots`, or when nothing references them. Read it before promising that existing tests still pass."
42207
43377
  );
@@ -42218,31 +43388,31 @@ function renderTestsToRevisit(entries) {
42218
43388
  }
42219
43389
  return lines;
42220
43390
  }
42221
- var typeRespellingOutput = import_zod11.z.object({
42222
- specId: import_zod11.z.string().describe("The interface or type holding the position."),
42223
- kind: import_zod11.z.enum(["interface", "type"]).describe("interface | type."),
42224
- path: import_zod11.z.string().describe("Where in the spec: methods.save.params.key, methods.save.returns, fields.createdAt, params.listener."),
42225
- written: import_zod11.z.string().describe("The text the input (or the stored file) held."),
42226
- stored: import_zod11.z.string().describe("The canonical spelling, which is what is stored and shown.")
43391
+ var typeRespellingOutput = import_zod12.z.object({
43392
+ specId: import_zod12.z.string().describe("The interface or type holding the position."),
43393
+ kind: import_zod12.z.enum(["interface", "type"]).describe("interface | type."),
43394
+ path: import_zod12.z.string().describe("Where in the spec: methods.save.params.key, methods.save.returns, fields.createdAt, params.listener."),
43395
+ written: import_zod12.z.string().describe("The text the input (or the stored file) held."),
43396
+ stored: import_zod12.z.string().describe("The canonical spelling, which is what is stored and shown.")
42227
43397
  });
42228
43398
  function renderRespellings(entries) {
42229
43399
  if (!entries.length) return [];
42230
43400
  return ["", "RESPELLED (stored canonical):", ...entries.map((r) => `- ${r.path}: "${r.written}" \u2192 "${r.stored}"`)];
42231
43401
  }
42232
43402
  var specWriteReceiptOutput = {
42233
- kind: import_zod11.z.enum(SPEC_KINDS).describe("The spec kind written."),
42234
- id: import_zod11.z.string().describe('The id the spec is stored under; "system" for the L0 singleton.'),
42235
- name: import_zod11.z.string().describe("The spec's display name as written."),
42236
- replacedExisting: import_zod11.z.boolean().describe(
43403
+ kind: import_zod12.z.enum(SPEC_KINDS).describe("The spec kind written."),
43404
+ id: import_zod12.z.string().describe('The id the spec is stored under; "system" for the L0 singleton.'),
43405
+ name: import_zod12.z.string().describe("The spec's display name as written."),
43406
+ replacedExisting: import_zod12.z.boolean().describe(
42237
43407
  "True when a spec already held this id and the call re-authored it in place rather than adding one. The notices then say what was carried forward, removed or cleared by the restatement."
42238
43408
  ),
42239
- status: import_zod11.z.enum(STATUS_VALUES).optional().describe(
43409
+ status: import_zod12.z.enum(STATUS_VALUES).optional().describe(
42240
43410
  "The lifecycle status written. Absent for the L0 and a type, which carry none."
42241
43411
  ),
42242
- notices: import_zod11.z.array(import_zod11.z.string()).describe(
43412
+ notices: import_zod12.z.array(import_zod12.z.string()).describe(
42243
43413
  "The notice lines the text answer lists, one per entry: what was carried forward, what a restatement removed, what an omission cleared, and every gate warning the write raised. Empty for a clean create."
42244
43414
  ),
42245
- respellings: import_zod11.z.array(typeRespellingOutput).describe(
43415
+ respellings: import_zod12.z.array(typeRespellingOutput).describe(
42246
43416
  "Each type position the write normalised: what the input wrote against the canonical spelling stored. Aliases are accepted, never refused, and this list is how an author learns the canonical form. Empty when every position was already canonical."
42247
43417
  ),
42248
43418
  testsToRevisit: testsToRevisitOutput,
@@ -42260,86 +43430,86 @@ ${respelledBlock}` : ""}${testsBlock ? `
42260
43430
  ${testsBlock}` : ""}`, receipt);
42261
43431
  }
42262
43432
  var specDeletionOutput = {
42263
- kind: import_zod11.z.enum(SPEC_KINDS).describe("The spec kind deleted."),
42264
- id: import_zod11.z.string().describe("The id the spec was stored under."),
42265
- deleted: import_zod11.z.boolean().describe("True when a spec document was removed."),
43433
+ kind: import_zod12.z.enum(SPEC_KINDS).describe("The spec kind deleted."),
43434
+ id: import_zod12.z.string().describe("The id the spec was stored under."),
43435
+ deleted: import_zod12.z.boolean().describe("True when a spec document was removed."),
42266
43436
  testsToRevisit: testsToRevisitOutput,
42267
43437
  ...staleServerOutput
42268
43438
  };
42269
43439
  var specChangeOutput = {
42270
- path: import_zod11.z.string().describe("The dotted path the change addresses, with names and indexes."),
42271
- change: import_zod11.z.enum(["set", "added", "removed", "cleared", "renumbered", "relocated"]).describe(
43440
+ path: import_zod12.z.string().describe("The dotted path the change addresses, with names and indexes."),
43441
+ change: import_zod12.z.enum(["set", "added", "removed", "cleared", "renumbered", "relocated"]).describe(
42272
43442
  "What happened at that path. A narrative is compared by step identity: `renumbered` is a run of unchanged steps shifted by an insert or delete (before/after name the ranges), `relocated` a jump field that followed its target to the target's new number."
42273
43443
  ),
42274
- before: import_zod11.z.string().optional().describe("The previous value, summarized; absent when there was none."),
42275
- after: import_zod11.z.string().optional().describe("The new value, summarized; absent when there is none.")
43444
+ before: import_zod12.z.string().optional().describe("The previous value, summarized; absent when there was none."),
43445
+ after: import_zod12.z.string().optional().describe("The new value, summarized; absent when there is none.")
42276
43446
  };
42277
43447
  var specChangeReportOutput = {
42278
- kind: import_zod11.z.enum(SPEC_KINDS).describe("The spec kind written."),
42279
- id: import_zod11.z.string().describe("The stored spec's id."),
42280
- written: import_zod11.z.boolean().describe("False when the merged spec equals what is stored: nothing reached disk."),
42281
- dryRun: import_zod11.z.boolean().describe(
43448
+ kind: import_zod12.z.enum(SPEC_KINDS).describe("The spec kind written."),
43449
+ id: import_zod12.z.string().describe("The stored spec's id."),
43450
+ written: import_zod12.z.boolean().describe("False when the merged spec equals what is stored: nothing reached disk."),
43451
+ dryRun: import_zod12.z.boolean().describe(
42282
43452
  "True when the caller asked what the delta WOULD do. `written` is false for a dry run exactly as it is for a delta that changed nothing, and only this field tells the two apart."
42283
43453
  ),
42284
- changes: import_zod11.z.array(import_zod11.z.object(specChangeOutput)).describe(
43454
+ changes: import_zod12.z.array(import_zod12.z.object(specChangeOutput)).describe(
42285
43455
  "Every change the write made; empty exactly when `written` is false."
42286
43456
  ),
42287
- ineffective: import_zod11.z.array(import_zod11.z.string()).describe(
43457
+ ineffective: import_zod12.z.array(import_zod12.z.string()).describe(
42288
43458
  "Every path the delta named that the write did not act on, each with why. Read it: a nested typo the permissive delta cannot refuse shows up here and nowhere else."
42289
43459
  ),
42290
- notices: import_zod11.z.array(import_zod11.z.string()).describe("Store placement notices, gate warnings and delta notices."),
42291
- respellings: import_zod11.z.array(typeRespellingOutput).describe(
43460
+ notices: import_zod12.z.array(import_zod12.z.string()).describe("Store placement notices, gate warnings and delta notices."),
43461
+ respellings: import_zod12.z.array(typeRespellingOutput).describe(
42292
43462
  "Each type position the write normalised (or, on a dry run, would): what the delta or the stored file wrote against the canonical spelling stored. Aliases are accepted and respelled, never refused \u2014 this is how the canonical form is taught. Empty when every position was already canonical."
42293
43463
  ),
42294
- summary: import_zod11.z.string().describe("One line for people."),
43464
+ summary: import_zod12.z.string().describe("One line for people."),
42295
43465
  testsToRevisit: testsToRevisitOutput,
42296
- strippedKeys: import_zod11.z.array(import_zod11.z.string()).optional().describe(
43466
+ strippedKeys: import_zod12.z.array(import_zod12.z.string()).optional().describe(
42297
43467
  "Keys the stored file carries that the level's schema does not know, each as `path: value`, which this write drops (or, on a dry run, would drop). Absent when there are none."
42298
43468
  ),
42299
43469
  ...staleServerOutput
42300
43470
  };
42301
43471
  var validationIssueOutput = {
42302
- severity: import_zod11.z.enum(["error", "warning", "notice"]).describe("The finding's severity after project overrides."),
42303
- code: import_zod11.z.string().describe("The rule code, UPPER_SNAKE \u2014 the stable handle to filter and suppress by."),
42304
- message: import_zod11.z.string().describe("What is wrong, named."),
42305
- agentId: import_zod11.z.string().optional().describe("The agent the finding concerns, when it concerns one."),
42306
- specId: import_zod11.z.string().optional().describe("The spec the finding concerns, when it concerns one."),
42307
- draftContext: import_zod11.z.boolean().optional().describe(
43472
+ severity: import_zod12.z.enum(["error", "warning", "notice"]).describe("The finding's severity after project overrides."),
43473
+ code: import_zod12.z.string().describe("The rule code, UPPER_SNAKE \u2014 the stable handle to filter and suppress by."),
43474
+ message: import_zod12.z.string().describe("What is wrong, named."),
43475
+ agentId: import_zod12.z.string().optional().describe("The agent the finding concerns, when it concerns one."),
43476
+ specId: import_zod12.z.string().optional().describe("The spec the finding concerns, when it concerns one."),
43477
+ draftContext: import_zod12.z.boolean().optional().describe(
42308
43478
  "True when the finding was raised against a draft/design spec \u2014 what the --ci gate waives."
42309
43479
  ),
42310
- resolution: import_zod11.z.object({
42311
- outcome: import_zod11.z.enum(["resolved", "missing", "ambiguous", "unavailable", "forbidden"]).describe("How the owner's gate resolved the reference, decided before the severity."),
42312
- owner: import_zod11.z.string().describe("The referring project's id: the one project whose gate judges the reference."),
42313
- callSite: import_zod11.z.string().describe("Where the reference is written: the referring spec and the position in it."),
42314
- canonicalTarget: import_zod11.z.string().optional().describe("The target in producer-id form, `<producer id>::<public name>`."),
42315
- inputDigest: import_zod11.z.string().optional().describe("The digest of the input the reference was judged against (a pin, or a member's live table)."),
42316
- reason: import_zod11.z.string().describe("One sentence saying why the outcome is what it is."),
42317
- importedVia: import_zod11.z.string().optional().describe("For a bare name resolved through a `use` import: the alias that supplied it.")
43480
+ resolution: import_zod12.z.object({
43481
+ outcome: import_zod12.z.enum(["resolved", "missing", "ambiguous", "unavailable", "forbidden"]).describe("How the owner's gate resolved the reference, decided before the severity."),
43482
+ owner: import_zod12.z.string().describe("The referring project's id: the one project whose gate judges the reference."),
43483
+ callSite: import_zod12.z.string().describe("Where the reference is written: the referring spec and the position in it."),
43484
+ canonicalTarget: import_zod12.z.string().optional().describe("The target in producer-id form, `<producer id>::<public name>`."),
43485
+ inputDigest: import_zod12.z.string().optional().describe("The digest of the input the reference was judged against (a pin, or a member's live table)."),
43486
+ reason: import_zod12.z.string().describe("One sentence saying why the outcome is what it is."),
43487
+ importedVia: import_zod12.z.string().optional().describe("For a bare name resolved through a `use` import: the alias that supplied it.")
42318
43488
  }).optional().describe(
42319
43489
  "On a finding about a cross-project reference: how the owner's gate resolved it, decided before the severity."
42320
43490
  ),
42321
- project: import_zod11.z.string().optional().describe(
43491
+ project: import_zod12.z.string().optional().describe(
42322
43492
  "In a family run: the key of the project whose gate the finding belongs to ('' for the family root)."
42323
43493
  )
42324
43494
  };
42325
43495
  var memberCreationOutput = {
42326
- configCreated: import_zod11.z.boolean().describe("Whether this call created the member's configuration; only then were the declaring project's required packs scaffolded."),
42327
- adopted: import_zod11.z.array(import_zod11.z.object({
42328
- name: import_zod11.z.string(),
42329
- version: import_zod11.z.string().optional(),
42330
- integrity: import_zod11.z.string().optional(),
42331
- source: import_zod11.z.string().optional(),
42332
- bundle: import_zod11.z.boolean().optional()
43496
+ configCreated: import_zod12.z.boolean().describe("Whether this call created the member's configuration; only then were the declaring project's required packs scaffolded."),
43497
+ adopted: import_zod12.z.array(import_zod12.z.object({
43498
+ name: import_zod12.z.string(),
43499
+ version: import_zod12.z.string().optional(),
43500
+ integrity: import_zod12.z.string().optional(),
43501
+ source: import_zod12.z.string().optional(),
43502
+ bundle: import_zod12.z.boolean().optional()
42333
43503
  })).describe("The selections written into the new member's extensions.packs, each pinned to the highest installed version its requirement admits."),
42334
- unadopted: import_zod11.z.array(import_zod11.z.object({
42335
- pack: import_zod11.z.string(),
42336
- version: import_zod11.z.string(),
42337
- profile: import_zod11.z.string().optional()
43504
+ unadopted: import_zod12.z.array(import_zod12.z.object({
43505
+ pack: import_zod12.z.string(),
43506
+ version: import_zod12.z.string(),
43507
+ profile: import_zod12.z.string().optional()
42338
43508
  })).describe("Requirements no installed version satisfies: nothing was written for them, and the next family run reports each as POLICY_NOT_ADOPTED."),
42339
- projectType: import_zod11.z.string().optional().describe("The profile written as the new member's projectType, when exactly one adopted requirement names one."),
42340
- as: import_zod11.z.string().describe("part | project: what was created (stage 8; a part by default)."),
42341
- storage: import_zod11.z.string().describe("contained | path | git: where its files live."),
42342
- commit: import_zod11.z.string().optional().describe("git: the commit the member was pinned at."),
43509
+ projectType: import_zod12.z.string().optional().describe("The profile written as the new member's projectType, when exactly one adopted requirement names one."),
43510
+ as: import_zod12.z.string().describe("part | project: what was created (stage 8; a part by default)."),
43511
+ storage: import_zod12.z.string().describe("contained | path | git: where its files live."),
43512
+ commit: import_zod12.z.string().optional().describe("git: the commit the member was pinned at."),
42343
43513
  ...staleServerOutput
42344
43514
  };
42345
43515
  function describeMemberPacks(creation) {
@@ -42354,36 +43524,36 @@ function describeMemberPacks(creation) {
42354
43524
  }
42355
43525
  return parts.join("");
42356
43526
  }
42357
- var doctrineChangeOutput = import_zod11.z.object({
42358
- axis: import_zod11.z.enum(["rule", "concept"]),
42359
- change: import_zod11.z.string().describe("loosened | raised | off | added | depth | inert | redefined | removed | discouraged | licensed | gated \u2014 stated, never judged."),
42360
- subject: import_zod11.z.string(),
42361
- profile: import_zod11.z.string().optional(),
42362
- from: import_zod11.z.string().optional(),
42363
- to: import_zod11.z.string().optional(),
42364
- reason: import_zod11.z.string().optional()
43527
+ var doctrineChangeOutput = import_zod12.z.object({
43528
+ axis: import_zod12.z.enum(["rule", "concept"]),
43529
+ change: import_zod12.z.string().describe("loosened | raised | off | added | depth | inert | redefined | removed | discouraged | licensed | gated \u2014 stated, never judged."),
43530
+ subject: import_zod12.z.string(),
43531
+ profile: import_zod12.z.string().optional(),
43532
+ from: import_zod12.z.string().optional(),
43533
+ to: import_zod12.z.string().optional(),
43534
+ reason: import_zod12.z.string().optional()
42365
43535
  });
42366
- var impactTotalsOutput = import_zod11.z.object({
42367
- key: import_zod11.z.string(),
42368
- id: import_zod11.z.string().optional(),
42369
- directory: import_zod11.z.string(),
42370
- valid: import_zod11.z.boolean(),
42371
- errors: import_zod11.z.number(),
42372
- warnings: import_zod11.z.number(),
42373
- notices: import_zod11.z.number()
43536
+ var impactTotalsOutput = import_zod12.z.object({
43537
+ key: import_zod12.z.string(),
43538
+ id: import_zod12.z.string().optional(),
43539
+ directory: import_zod12.z.string(),
43540
+ valid: import_zod12.z.boolean(),
43541
+ errors: import_zod12.z.number(),
43542
+ warnings: import_zod12.z.number(),
43543
+ notices: import_zod12.z.number()
42374
43544
  });
42375
43545
  var packImpactOutput = {
42376
- pack: import_zod11.z.string().describe("The pack measured."),
42377
- version: import_zod11.z.string().optional().describe("The version the candidate resolves to; absent for an unversioned pack."),
42378
- replaces: import_zod11.z.string().optional().describe("The version applied now under the same name, when the selection would replace it."),
42379
- direction: import_zod11.z.enum(["apply", "remove"]).describe("remove when the pack is already applied exactly as asked: the findings then read as what the pack accounts for now."),
42380
- doctrine: import_zod11.z.array(doctrineChangeOutput).describe("The pack's changes against wairon's defaults. Nothing in it is a finding."),
42381
- previousDoctrine: import_zod11.z.array(doctrineChangeOutput).optional().describe("On an update: the replaced version's changes against the same defaults."),
42382
- governing: import_zod11.z.array(import_zod11.z.string()).describe("The pack's profiles that would govern something in this project."),
42383
- findings: import_zod11.z.object({
42384
- introduced: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)),
42385
- resolved: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)),
42386
- regraded: import_zod11.z.array(import_zod11.z.object({ finding: import_zod11.z.object(validationIssueOutput), from: import_zod11.z.string() }))
43546
+ pack: import_zod12.z.string().describe("The pack measured."),
43547
+ version: import_zod12.z.string().optional().describe("The version the candidate resolves to; absent for an unversioned pack."),
43548
+ replaces: import_zod12.z.string().optional().describe("The version applied now under the same name, when the selection would replace it."),
43549
+ direction: import_zod12.z.enum(["apply", "remove"]).describe("remove when the pack is already applied exactly as asked: the findings then read as what the pack accounts for now."),
43550
+ doctrine: import_zod12.z.array(doctrineChangeOutput).describe("The pack's changes against wairon's defaults. Nothing in it is a finding."),
43551
+ previousDoctrine: import_zod12.z.array(doctrineChangeOutput).optional().describe("On an update: the replaced version's changes against the same defaults."),
43552
+ governing: import_zod12.z.array(import_zod12.z.string()).describe("The pack's profiles that would govern something in this project."),
43553
+ findings: import_zod12.z.object({
43554
+ introduced: import_zod12.z.array(import_zod12.z.object(validationIssueOutput)),
43555
+ resolved: import_zod12.z.array(import_zod12.z.object(validationIssueOutput)),
43556
+ regraded: import_zod12.z.array(import_zod12.z.object({ finding: import_zod12.z.object(validationIssueOutput), from: import_zod12.z.string() }))
42387
43557
  }).describe("The owner's-gate findings that differ between the current and the candidate configuration."),
42388
43558
  before: impactTotalsOutput.describe("The current configuration's totals."),
42389
43559
  after: impactTotalsOutput.describe("The candidate configuration's totals."),
@@ -42417,57 +43587,57 @@ function pendingBanner() {
42417
43587
  }
42418
43588
  }
42419
43589
  var validateTreeOutput = {
42420
- valid: import_zod11.z.boolean().describe("False when the tree holds at least one error; warnings and notices never make it false."),
42421
- errors: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)).describe("Every finding of severity error."),
42422
- warnings: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)).describe("Every finding of severity warning."),
42423
- notices: import_zod11.z.array(import_zod11.z.object(validationIssueOutput)).describe(
43590
+ valid: import_zod12.z.boolean().describe("False when the tree holds at least one error; warnings and notices never make it false."),
43591
+ errors: import_zod12.z.array(import_zod12.z.object(validationIssueOutput)).describe("Every finding of severity error."),
43592
+ warnings: import_zod12.z.array(import_zod12.z.object(validationIssueOutput)).describe("Every finding of severity warning."),
43593
+ notices: import_zod12.z.array(import_zod12.z.object(validationIssueOutput)).describe(
42424
43594
  "Every finding of severity notice: reported, never a failure \u2014 they never make the tree invalid and never fail `wairon validate --ci`."
42425
43595
  ),
42426
- hint: import_zod11.z.string().optional().describe(
43596
+ hint: import_zod12.z.string().optional().describe(
42427
43597
  "The owner's gate: present when the project declares externals \u2014 they were judged against their pins alone, and `wairon validate --family` composes them against their live producers. A family run: present when externals were left out because their producers lie outside the run's reach."
42428
43598
  ),
42429
- projects: import_zod11.z.array(import_zod11.z.object({
42430
- key: import_zod11.z.string().describe("The project's key in the family root's scan ('' for the root itself)."),
42431
- id: import_zod11.z.string().optional().describe("The project's effective id."),
42432
- directory: import_zod11.z.string().describe("The project's root directory."),
42433
- valid: import_zod11.z.boolean().describe("Whether its own gate found no error."),
42434
- errors: import_zod11.z.number().describe("Its own gate's error count."),
42435
- warnings: import_zod11.z.number().describe("Its own gate's warning count."),
42436
- notices: import_zod11.z.number().describe("Its own gate's notice count.")
43599
+ projects: import_zod12.z.array(import_zod12.z.object({
43600
+ key: import_zod12.z.string().describe("The project's key in the family root's scan ('' for the root itself)."),
43601
+ id: import_zod12.z.string().optional().describe("The project's effective id."),
43602
+ directory: import_zod12.z.string().describe("The project's root directory."),
43603
+ valid: import_zod12.z.boolean().describe("Whether its own gate found no error."),
43604
+ errors: import_zod12.z.number().describe("Its own gate's error count."),
43605
+ warnings: import_zod12.z.number().describe("Its own gate's warning count."),
43606
+ notices: import_zod12.z.number().describe("Its own gate's notice count.")
42437
43607
  })).optional().describe(
42438
43608
  "A family run only: one line per selected project (the root first) with its own gate's totals. Absent on the owner's gate."
42439
43609
  ),
42440
43610
  ...staleServerOutput
42441
43611
  };
42442
43612
  var getSpecOutput = {
42443
- kind: import_zod11.z.enum(SPEC_KINDS).describe("The kind of spec read."),
42444
- id: import_zod11.z.string().describe("The id it was read by."),
42445
- spec: import_zod11.z.record(import_zod11.z.unknown()).describe(
43613
+ kind: import_zod12.z.enum(SPEC_KINDS).describe("The kind of spec read."),
43614
+ id: import_zod12.z.string().describe("The id it was read by."),
43615
+ spec: import_zod12.z.record(import_zod12.z.unknown()).describe(
42446
43616
  "The stored spec, exactly as the text block renders it \u2014 minus the two derived markers below, which the text folds in and this answer keeps separate so nothing derived can be mistaken for stored."
42447
43617
  ),
42448
- partialResult: import_zod11.z.object({
42449
- shown: import_zod11.z.array(import_zod11.z.string()).describe("The method names this answer carries."),
42450
- omitted: import_zod11.z.number().describe("How many of the spec's methods are NOT in it."),
42451
- warning: import_zod11.z.string().describe("Why it must never be re-authored from.")
43618
+ partialResult: import_zod12.z.object({
43619
+ shown: import_zod12.z.array(import_zod12.z.string()).describe("The method names this answer carries."),
43620
+ omitted: import_zod12.z.number().describe("How many of the spec's methods are NOT in it."),
43621
+ warning: import_zod12.z.string().describe("Why it must never be re-authored from.")
42452
43622
  }).optional().describe(
42453
43623
  "Present only when `methods` filtered the read. A filtered spec is a partial one: sdd_define_interface and sdd_write_narrative REPLACE the method list, so re-authoring from it would delete every method left out."
42454
43624
  ),
42455
- variantGuidance: import_zod11.z.object({
42456
- variant: import_zod11.z.string().describe("The variant id the component declares."),
42457
- base: import_zod11.z.string().describe("The core stereotype it specializes."),
42458
- guidance: import_zod11.z.string().describe("How to implement a component of this variant."),
42459
- siblings: import_zod11.z.array(import_zod11.z.string()).describe("Other components of the same variant, to implement alike."),
42460
- target: import_zod11.z.string().optional().describe("The target language the variant scopes itself to, if any."),
42461
- profile: import_zod11.z.string().optional().describe("The architectural profile it scopes itself to, if any.")
43625
+ variantGuidance: import_zod12.z.object({
43626
+ variant: import_zod12.z.string().describe("The variant id the component declares."),
43627
+ base: import_zod12.z.string().describe("The core stereotype it specializes."),
43628
+ guidance: import_zod12.z.string().describe("How to implement a component of this variant."),
43629
+ siblings: import_zod12.z.array(import_zod12.z.string()).describe("Other components of the same variant, to implement alike."),
43630
+ target: import_zod12.z.string().optional().describe("The target language the variant scopes itself to, if any."),
43631
+ profile: import_zod12.z.string().optional().describe("The architectural profile it scopes itself to, if any.")
42462
43632
  }).optional().describe(
42463
43633
  "Derived, read-only guidance for a variant-tagged component \u2014 resolved from the variant registry, not part of the spec. Never write it back."
42464
43634
  ),
42465
- resolvedSignatures: import_zod11.z.array(import_zod11.z.object({
42466
- method: import_zod11.z.string().describe("The contract method that takes its signature from a source."),
42467
- signatureFrom: import_zod11.z.string().describe("The source it names, as the spec holds it."),
42468
- signature: import_zod11.z.string().describe("The text it shows, derived from the resolved params and returns."),
42469
- params: import_zod11.z.array(import_zod11.z.record(import_zod11.z.unknown())).optional().describe("The params the source supplies; absent when it supplies none (unresolved, ambiguous or chained)."),
42470
- returns: import_zod11.z.string().describe("The returns the source supplies (`unknown` when it supplies none).")
43635
+ resolvedSignatures: import_zod12.z.array(import_zod12.z.object({
43636
+ method: import_zod12.z.string().describe("The contract method that takes its signature from a source."),
43637
+ signatureFrom: import_zod12.z.string().describe("The source it names, as the spec holds it."),
43638
+ signature: import_zod12.z.string().describe("The text it shows, derived from the resolved params and returns."),
43639
+ params: import_zod12.z.array(import_zod12.z.record(import_zod12.z.unknown())).optional().describe("The params the source supplies; absent when it supplies none (unresolved, ambiguous or chained)."),
43640
+ returns: import_zod12.z.string().describe("The returns the source supplies (`unknown` when it supplies none).")
42471
43641
  })).optional().describe(
42472
43642
  "Derived, read-only: for a contract whose methods take their signature from a source, each such method's RESOLVED params, returns and text. The spec carries those methods in stored form (the signatureFrom alone) so it can be re-authored from as it is; never write these back beside the source."
42473
43643
  ),
@@ -42630,6 +43800,7 @@ var SPEC_WRITE_TOOLS = /* @__PURE__ */ new Set([
42630
43800
  "sdd_rename_member_alias",
42631
43801
  "sdd_rename_component",
42632
43802
  "sdd_rename_method",
43803
+ "sdd_rename_type",
42633
43804
  "sdd_add_component",
42634
43805
  "sdd_define_interface",
42635
43806
  "sdd_set_endpoints",
@@ -42651,10 +43822,10 @@ function reg(server, name, config, cb) {
42651
43822
  if (result.isError !== true && SPEC_WRITE_TOOLS.has(name)) listChangedEmitters.get(server)?.();
42652
43823
  return result;
42653
43824
  };
42654
- const strictConfig = config.inputSchema ? { ...config, inputSchema: import_zod11.z.object(config.inputSchema).strict() } : config;
43825
+ const strictConfig = config.inputSchema ? { ...config, inputSchema: import_zod12.z.object(config.inputSchema).strict() } : config;
42655
43826
  server.registerTool(name, strictConfig, guarded2);
42656
43827
  }
42657
- var statusInput = import_zod11.z.enum(STATUS_VALUES).optional().describe(
43828
+ var statusInput = import_zod12.z.enum(STATUS_VALUES).optional().describe(
42658
43829
  "The spec's lifecycle status. Omitted means draft for a NEW spec and the status already stored for a re-authoring, so a restatement never reopens a frozen spec. State it to author straight at design or complete instead of promoting afterwards. A status that would LOWER the stored one is refused \u2014 reopening a spec for revision is sdd_update_spec's job, which sets the demotion deliberately."
42659
43830
  );
42660
43831
  function createBareMcpServer(options = {}) {
@@ -42681,7 +43852,7 @@ function createBareMcpServer(options = {}) {
42681
43852
  "listAgents",
42682
43853
  {
42683
43854
  description: "List all AI agents registered in this project. Returns id, name, description, domainRoot, template, tags, and status for each agent. Filter by domainId to scope to one domain.",
42684
- inputSchema: { domainId: import_zod11.z.string().optional() }
43855
+ inputSchema: { domainId: import_zod12.z.string().optional() }
42685
43856
  },
42686
43857
  ({ domainId }) => {
42687
43858
  try {
@@ -42706,7 +43877,7 @@ function createBareMcpServer(options = {}) {
42706
43877
  "getAgent",
42707
43878
  {
42708
43879
  description: "Get full details of a specific agent by id, including ownership rules, context, and output targets.",
42709
- inputSchema: { id: import_zod11.z.string() }
43880
+ inputSchema: { id: import_zod12.z.string() }
42710
43881
  },
42711
43882
  ({ id }) => {
42712
43883
  try {
@@ -42739,7 +43910,7 @@ function createBareMcpServer(options = {}) {
42739
43910
  {
42740
43911
  description: "Validate the project's agent topology. Returns errors, warnings and notices (duplicate ids, overlapping ownership, missing paths, etc.). Supports optional subsystem scoping.",
42741
43912
  inputSchema: {
42742
- subsystem: import_zod11.z.string().optional().describe("Only validate topology for agents under the specified subsystem")
43913
+ subsystem: import_zod12.z.string().optional().describe("Only validate topology for agents under the specified subsystem")
42743
43914
  }
42744
43915
  },
42745
43916
  ({ subsystem }) => {
@@ -42782,11 +43953,11 @@ function createBareMcpServer(options = {}) {
42782
43953
  }
42783
43954
  );
42784
43955
  const systemInput = {
42785
- name: import_zod11.z.string().describe("Overarching name of the project/system"),
42786
- vision: import_zod11.z.string().describe("Vision, mission, and core goals of the system"),
42787
- boundaries: import_zod11.z.array(import_zod11.z.union([import_zod11.z.string(), import_zod11.z.object({ name: import_zod11.z.string(), description: import_zod11.z.string().optional() }).strict()])).optional().describe("System boundary rules or scope statements (strings or name/description objects)"),
42788
- globalRequirements: import_zod11.z.array(import_zod11.z.union([import_zod11.z.string(), import_zod11.z.object({ description: import_zod11.z.string() }).strict()])).optional().describe("Global functional and non-functional requirements (strings or description objects)"),
42789
- targetLanguage: import_zod11.z.string().optional().describe('Default implementation language for the system (e.g. "typescript", "rust", "python"). Subsystems may override. Enables language-aware validation.')
43956
+ name: import_zod12.z.string().describe("Overarching name of the project/system"),
43957
+ vision: import_zod12.z.string().describe("Vision, mission, and core goals of the system"),
43958
+ boundaries: import_zod12.z.array(import_zod12.z.union([import_zod12.z.string(), import_zod12.z.object({ name: import_zod12.z.string(), description: import_zod12.z.string().optional() }).strict()])).optional().describe("System boundary rules or scope statements (strings or name/description objects)"),
43959
+ globalRequirements: import_zod12.z.array(import_zod12.z.union([import_zod12.z.string(), import_zod12.z.object({ description: import_zod12.z.string() }).strict()])).optional().describe("Global functional and non-functional requirements (strings or description objects)"),
43960
+ targetLanguage: import_zod12.z.string().optional().describe('Default implementation language for the system (e.g. "typescript", "rust", "python"). Subsystems may override. Enables language-aware validation.')
42790
43961
  };
42791
43962
  const systemInputFields = Object.keys(systemInput);
42792
43963
  reg(
@@ -42820,34 +43991,34 @@ function createBareMcpServer(options = {}) {
42820
43991
  }
42821
43992
  }
42822
43993
  );
42823
- const publicInterfaceItemInput = import_zod11.z.object({
42824
- type: import_zod11.z.enum(["REST", "GraphQL", "MessageBus", "RPC", "Custom"]).optional().describe("Transport kind of an own item (required on an own component item); a re-export inherits its target's"),
42825
- details: import_zod11.z.string().optional().describe("Consumer-facing description of an own item (required on an own component item); a re-export inherits its target's"),
42826
- component: import_zod11.z.string().optional().describe("For an own item, the L2 component that realizes it (this subsystem's published surface); for a re-export, the component re-exported from `from`"),
42827
- interface: import_zod11.z.string().optional().describe("Optional L3 interface id the entry narrows to"),
42828
- consumers: import_zod11.z.array(import_zod11.z.string()).optional().describe("The subsystem ids this surface is published to. Absent, any subsystem may depend on the component; present, only these may \u2014 when every entry publishing the component names consumers, the union of the lists is the whole set, and a dependency from any other subsystem is CROSS_SUBSYSTEM_UNLISTED_CONSUMER. Every id must name a subsystem of the tree (PUBLIC_INTERFACE_UNKNOWN_CONSUMER)."),
42829
- from: import_zod11.z.string().optional().describe("Re-export source: another subsystem of this project. With neither component nor typeDef, the entry re-exports everything that subsystem exports (a wildcard)"),
42830
- typeDef: import_zod11.z.string().optional().describe("A type exported as is: owned by this subsystem, or re-exported from `from`"),
42831
- as: import_zod11.z.string().optional().describe("The public name; defaults to the narrowed interface, then the component or type id. Must fit [a-z0-9-_]+ (EXPORT_INVALID otherwise)")
43994
+ const publicInterfaceItemInput = import_zod12.z.object({
43995
+ type: import_zod12.z.enum(["REST", "GraphQL", "MessageBus", "RPC", "Custom"]).optional().describe("Transport kind of an own item (required on an own component item); a re-export inherits its target's"),
43996
+ details: import_zod12.z.string().optional().describe("Consumer-facing description of an own item (required on an own component item); a re-export inherits its target's"),
43997
+ component: import_zod12.z.string().optional().describe("For an own item, the L2 component that realizes it (this subsystem's published surface); for a re-export, the component re-exported from `from`"),
43998
+ interface: import_zod12.z.string().optional().describe("Optional L3 interface id the entry narrows to"),
43999
+ consumers: import_zod12.z.array(import_zod12.z.string()).optional().describe("The subsystem ids this surface is published to. Absent, any subsystem may depend on the component; present, only these may \u2014 when every entry publishing the component names consumers, the union of the lists is the whole set, and a dependency from any other subsystem is CROSS_SUBSYSTEM_UNLISTED_CONSUMER. Every id must name a subsystem of the tree (PUBLIC_INTERFACE_UNKNOWN_CONSUMER)."),
44000
+ from: import_zod12.z.string().optional().describe("Re-export source: another subsystem of this project. With neither component nor typeDef, the entry re-exports everything that subsystem exports (a wildcard)"),
44001
+ typeDef: import_zod12.z.string().optional().describe("A type exported as is: owned by this subsystem, or re-exported from `from`"),
44002
+ as: import_zod12.z.string().optional().describe("The public name; defaults to the narrowed interface, then the component or type id. Must fit [a-z0-9-_]+ (EXPORT_INVALID otherwise)")
42832
44003
  }).strict();
42833
44004
  const subsystemInput = {
42834
- id: import_zod11.z.string().describe("Lowercase identifier for the subsystem"),
42835
- name: import_zod11.z.string().describe("Human-readable display name"),
42836
- description: import_zod11.z.string().describe("Purpose and details of the subsystem"),
42837
- publicInterfaces: import_zod11.z.array(publicInterfaceItemInput).optional().describe("The subsystem's export table: its own entrypoints, each bound to a realizing component, and re-exports of what other subsystems of this project export"),
42838
- projectPath: import_zod11.z.string().optional().describe("REFUSED: the legacy L1 mount form. A subsystem is never a mount \u2014 declare a member project with sdd_add_member instead"),
42839
- targetLanguage: import_zod11.z.string().optional().describe("Override of the system-level targetLanguage for this subsystem"),
42840
- profile: import_zod11.z.string().optional().describe("Architectural profile override for this subsystem (built-ins: backend, frontend-reactive, frontend-controller, lowlevel-os, game-ecs, realtime-embedded, plc-cyclic; extension packs may add more \u2014 unknown names get UNKNOWN_PROFILE)"),
42841
- designDepth: import_zod11.z.enum(["components", "interfaces", "implementations", "narratives"]).optional().describe("How deep THIS subsystem commits to designing (overrides project rules.designDepth; default narratives = full depth). Expectation checks below the depth are gated \u2014 soundness of authored content always applies."),
42842
- trustedLinks: import_zod11.z.array(import_zod11.z.object({
42843
- subsystem: import_zod11.z.string().describe("Peer subsystem id"),
42844
- reason: import_zod11.z.string().describe('Why the coupling is sanctioned (e.g. "dispatch latency fast lane")')
44005
+ id: import_zod12.z.string().describe("Lowercase identifier for the subsystem"),
44006
+ name: import_zod12.z.string().describe("Human-readable display name"),
44007
+ description: import_zod12.z.string().describe("Purpose and details of the subsystem"),
44008
+ publicInterfaces: import_zod12.z.array(publicInterfaceItemInput).optional().describe("The subsystem's export table: its own entrypoints, each bound to a realizing component, and re-exports of what other subsystems of this project export"),
44009
+ projectPath: import_zod12.z.string().optional().describe("REFUSED: the legacy L1 mount form. A subsystem is never a mount \u2014 declare a member project with sdd_add_member instead"),
44010
+ targetLanguage: import_zod12.z.string().optional().describe("Override of the system-level targetLanguage for this subsystem"),
44011
+ profile: import_zod12.z.string().optional().describe("Architectural profile override for this subsystem (built-ins: backend, frontend-reactive, frontend-controller, lowlevel-os, game-ecs, realtime-embedded, plc-cyclic; extension packs may add more \u2014 unknown names get UNKNOWN_PROFILE)"),
44012
+ designDepth: import_zod12.z.enum(["components", "interfaces", "implementations", "narratives"]).optional().describe("How deep THIS subsystem commits to designing (overrides project rules.designDepth; default narratives = full depth). Expectation checks below the depth are gated \u2014 soundness of authored content always applies."),
44013
+ trustedLinks: import_zod12.z.array(import_zod12.z.object({
44014
+ subsystem: import_zod12.z.string().describe("Peer subsystem id"),
44015
+ reason: import_zod12.z.string().describe('Why the coupling is sanctioned (e.g. "dispatch latency fast lane")')
42845
44016
  }).strict()).optional().describe("Sanctioned tight couplings with peers \u2014 required to acknowledge a mutual subsystem dependency; the Adapter \u2192 published Portal shape still applies."),
42846
- lifecycle: import_zod11.z.array(import_zod11.z.object({
42847
- phase: import_zod11.z.enum(["init", "shutdown", "cyclic", "interrupt", "scheduled"]).describe("Which lifecycle/execution flow this roots (cyclic = every scan/tick, interrupt = hardware/OS interrupt, scheduled = timer/cron)"),
42848
- component: import_zod11.z.string().describe("Component id whose method the runtime invokes at this phase"),
42849
- method: import_zod11.z.string().describe("Method name on that component's interface"),
42850
- description: import_zod11.z.string().optional()
44017
+ lifecycle: import_zod12.z.array(import_zod12.z.object({
44018
+ phase: import_zod12.z.enum(["init", "shutdown", "cyclic", "interrupt", "scheduled"]).describe("Which lifecycle/execution flow this roots (cyclic = every scan/tick, interrupt = hardware/OS interrupt, scheduled = timer/cron)"),
44019
+ component: import_zod12.z.string().describe("Component id whose method the runtime invokes at this phase"),
44020
+ method: import_zod12.z.string().describe("Method name on that component's interface"),
44021
+ description: import_zod12.z.string().optional()
42851
44022
  }).strict()).optional().describe("Declared execution-flow roots \u2014 reachability entrypoints alongside Portals/Observers. Only init flows feed the durable-Store hydration check (MISSING_HYDRATION); cyclic/interrupt/scheduled root non-request/response execution models (PLC scan, ISR, cron)."),
42852
44023
  status: statusInput
42853
44024
  };
@@ -42892,8 +44063,8 @@ function createBareMcpServer(options = {}) {
42892
44063
  {
42893
44064
  description: "Set (replace) an existing subsystem's export table (its publicInterfaces). An OWN item binds type + details to the component (and optional interface) that realizes it, or exports a type the subsystem owns (typeDef). A RE-EXPORT names another subsystem of the project in `from` and one component (optionally narrowed with `interface`) or one typeDef from what it exports, optionally renamed with `as` \u2014 `from` alone re-exports everything it exports; type and details are optional on a re-export, which inherits its target's. Use this to backfill bindings once the subsystem's components exist \u2014 cross-subsystem dependencies may only target a component its owning subsystem publishes; a re-export is a name, not a licence. A replacement, not a merge: an entry left out is removed. An own entry's identity is its component and interface, a re-export's its source, item and name, so a list naming one identity twice is refused. Written through the authoring seam as one gated delta, and answered with the change report \u2014 every entry added, changed or removed, or that nothing changed \u2014 as structured content beside the sentence.",
42894
44065
  inputSchema: {
42895
- subsystem: import_zod11.z.string().describe("The L1 subsystem id to update"),
42896
- publicInterfaces: import_zod11.z.array(publicInterfaceItemInput).describe("The full replacement list of the subsystem's export table: own items and re-exports")
44066
+ subsystem: import_zod12.z.string().describe("The L1 subsystem id to update"),
44067
+ publicInterfaces: import_zod12.z.array(publicInterfaceItemInput).describe("The full replacement list of the subsystem's export table: own items and re-exports")
42897
44068
  },
42898
44069
  outputSchema: specChangeReportOutput
42899
44070
  },
@@ -42903,11 +44074,11 @@ function createBareMcpServer(options = {}) {
42903
44074
  if (!sub) return errText(`Subsystem "${subsystem}" does not exist.`);
42904
44075
  const delta = publicInterfacesReplacement(subsystem, sub.publicInterfaces ?? [], publicInterfaces);
42905
44076
  if (typeof delta === "string") return errText(delta);
42906
- const report2 = updateSpecGated("subsystem", subsystem, delta);
44077
+ const report3 = updateSpecGated("subsystem", subsystem, delta);
42907
44078
  return structured(
42908
44079
  `Updated public interfaces for subsystem "${subsystem}" (${publicInterfaces.length} ${publicInterfaces.length === 1 ? "entry" : "entries"}).
42909
- ${renderChangeReport(report2)}`,
42910
- report2
44080
+ ${renderChangeReport(report3)}`,
44081
+ report3
42911
44082
  );
42912
44083
  } catch (e) {
42913
44084
  return errMessage(e);
@@ -42920,10 +44091,10 @@ ${renderChangeReport(report2)}`,
42920
44091
  {
42921
44092
  description: "Create a member of the bound project at `source`, in the one members grammar: `services/scheduler` (contained), `../admin` (a sibling checkout), `git@host:acme/payments.git` (a git repository, pinned at its default branch head unless `#<commit>` is given). By default a PART (stage 8): a piece of this project stored in another folder or repository, whose subsystems are this project's own (local ids, the ordinary subsystem rules, this project's lock); it gets only a specs folder, plus a configuration naming this project when it is not contained. With `as: project` an independent PROJECT instead: its project content is created \u2014 a project.yaml declaring the alias as its id, its L0, and the bound project's required packs (composition.requirePolicies) once \u2014 and it is reached only as `alias::name` through its L0 exports. What a member is follows from that content. A git member is not scaffolded; the repository's content decides what it is. Boundaries are earned: create a part unless the piece needs its own team, release, approval or public surface; sdd_promote_member makes one later. Idempotent \u2014 the same call again writes nothing; a different member under the alias is refused.",
42922
44093
  inputSchema: {
42923
- alias: import_zod11.z.string().describe("The member's alias ([a-z0-9-_]+); a project's new id"),
42924
- source: import_zod11.z.string().describe("A contained path, a `../` sibling path, or a git URL (optionally `#<commit>`)"),
42925
- description: import_zod11.z.string().optional().describe("What the member is to this project; also the vision of a bootstrapped project L0"),
42926
- as: import_zod11.z.enum(["part", "project"]).optional().describe("project to create the project content; omitted creates a part")
44094
+ alias: import_zod12.z.string().describe("The member's alias ([a-z0-9-_]+); a project's new id"),
44095
+ source: import_zod12.z.string().describe("A contained path, a `../` sibling path, or a git URL (optionally `#<commit>`)"),
44096
+ description: import_zod12.z.string().optional().describe("What the member is to this project; also the vision of a bootstrapped project L0"),
44097
+ as: import_zod12.z.enum(["part", "project"]).optional().describe("project to create the project content; omitted creates a part")
42927
44098
  },
42928
44099
  outputSchema: memberCreationOutput
42929
44100
  },
@@ -42944,8 +44115,8 @@ ${renderChangeReport(report2)}`,
42944
44115
  {
42945
44116
  description: "What selecting (or updating to) an installed pack would change on the bound project, writing nothing \u2014 the pack's doctrine against wairon's defaults (rules loosened, raised, turned off or added; profiles, stereotype fencing, edge licenses, patterns, guarantees and language tables added, redefined or removed), which of its profiles would govern, and the findings that change here. A pack the project already applies exactly as asked is measured as removed, so the findings read as what it accounts for now. Nothing in it is a finding: packs exist to adjust wairon's checks, and a loosening is stated like any other change. Apply a pack with `wairon pack use`.",
42946
44117
  inputSchema: {
42947
- pack: import_zod11.z.string().describe("The pack name"),
42948
- version: import_zod11.z.string().optional().describe("An exact version; omitted, the latest installed")
44118
+ pack: import_zod12.z.string().describe("The pack name"),
44119
+ version: import_zod12.z.string().optional().describe("An exact version; omitted, the latest installed")
42949
44120
  },
42950
44121
  outputSchema: packImpactOutput
42951
44122
  },
@@ -42970,8 +44141,8 @@ ${renderChangeReport(report2)}`,
42970
44141
  {
42971
44142
  description: "Relocate a member's directory on disk and point its `members` entry there in one step (a member still declared in the legacy L1 form is moved into `members` first). Errors if the alias declares no member, or the new path escapes the project or already exists.",
42972
44143
  inputSchema: {
42973
- alias: import_zod11.z.string().describe("The member's alias"),
42974
- newPath: import_zod11.z.string().describe("The member's new root, relative to the bound project")
44144
+ alias: import_zod12.z.string().describe("The member's alias"),
44145
+ newPath: import_zod12.z.string().describe("The member's new root, relative to the bound project")
42975
44146
  }
42976
44147
  },
42977
44148
  ({ alias, newPath }) => {
@@ -42983,16 +44154,16 @@ ${renderChangeReport(report2)}`,
42983
44154
  }
42984
44155
  }
42985
44156
  );
42986
- const dryRunArg = import_zod11.z.boolean().optional().describe("Answer the plan and write nothing \u2014 run this first and show the plan");
44157
+ const dryRunArg = import_zod12.z.boolean().optional().describe("Answer the plan and write nothing \u2014 run this first and show the plan");
42987
44158
  reg(
42988
44159
  server,
42989
44160
  "sdd_externalize_subsystem",
42990
44161
  {
42991
44162
  description: "Move an internal subsystem out to the path. By default (stage 8) into a PART \u2014 a storage move: the subsystem's specs move to that directory (a new part, or the existing part there), and nothing else changes: no reference, export, external or lock entry, the same verdict. With `as: project`, into a member PROJECT instead, family-wide and all-or-nothing \u2014 the move followed by a promote: what crosses the new boundary exported and imported, references respelled `alias::name`, the new member's external for this project pinned, and every other family project's references checked to still resolve (a reference that would need a component made public refuses the plan). Source code is not moved. dryRun answers the plan and writes nothing; run it first and show the plan. Never locks: the answer names the projects to re-lock.",
42992
44163
  inputSchema: {
42993
- subsystem: import_zod11.z.string().describe("The subsystem to move out"),
42994
- path: import_zod11.z.string().describe("The part's root, relative to the bound project (a new directory, or an existing part's)"),
42995
- as: import_zod11.z.enum(["part", "project"]).optional().describe("part (default) or project"),
44164
+ subsystem: import_zod12.z.string().describe("The subsystem to move out"),
44165
+ path: import_zod12.z.string().describe("The part's root, relative to the bound project (a new directory, or an existing part's)"),
44166
+ as: import_zod12.z.enum(["part", "project"]).optional().describe("part (default) or project"),
42996
44167
  dryRun: dryRunArg
42997
44168
  }
42998
44169
  },
@@ -43004,8 +44175,8 @@ ${renderChangeReport(report2)}`,
43004
44175
  {
43005
44176
  description: "Promote a part of the bound project to an independent project in place (stage 8) \u2014 its files stay where they are; it gets an id, an L0 exporting exactly what the rest of the project uses of it, its references across the new boundary respelled `alias::name`, the parent declared as its external, and pins on both sides. Refused (each reason listed) for a part fetched from git, a trusted link that would cross the new boundary, a used component its subsystem does not publish, or an id already taken. All-or-nothing; dryRun answers the plan and writes nothing \u2014 run it first and show the plan. Never locks: the answer names the project to re-lock and the new one to lock.",
43006
44177
  inputSchema: {
43007
- alias: import_zod11.z.string().describe("The part's alias"),
43008
- id: import_zod11.z.string().optional().describe("The new project's id (default: the alias)"),
44178
+ alias: import_zod12.z.string().describe("The part's alias"),
44179
+ id: import_zod12.z.string().optional().describe("The new project's id (default: the alias)"),
43009
44180
  dryRun: dryRunArg
43010
44181
  }
43011
44182
  },
@@ -43017,11 +44188,11 @@ ${renderChangeReport(report2)}`,
43017
44188
  {
43018
44189
  description: "Demote a project member of the bound project to a part in place (stage 8) \u2014 sdd_promote_member's inverse: its files stay where they are; its own metadata goes to the homes the destination names (as sdd_internalize_member sends it), its L0, lock and pins end, its references across the old boundary become local ids, and its configuration is reduced to naming its parent. Refused while another family project consumes it (a part has no exports \u2014 each consumer listed), for a member fetched from git, or for internalize's reasons. All-or-nothing; dryRun answers the plan and writes nothing \u2014 run it first and show the plan. Never locks.",
43019
44190
  inputSchema: {
43020
- alias: import_zod11.z.string().describe("The project member's alias"),
43021
- destination: import_zod11.z.object({
43022
- home: import_zod11.z.string().optional().describe("The subsystem that receives the member's L0 vision"),
43023
- packs: import_zod11.z.enum(["adopt", "drop"]).optional().describe("adopt | drop: packs only the member selects"),
43024
- exports: import_zod11.z.array(import_zod11.z.string()).optional().describe("Public names of the member the bound project exports afterwards")
44191
+ alias: import_zod12.z.string().describe("The project member's alias"),
44192
+ destination: import_zod12.z.object({
44193
+ home: import_zod12.z.string().optional().describe("The subsystem that receives the member's L0 vision"),
44194
+ packs: import_zod12.z.enum(["adopt", "drop"]).optional().describe("adopt | drop: packs only the member selects"),
44195
+ exports: import_zod12.z.array(import_zod12.z.string()).optional().describe("Public names of the member the bound project exports afterwards")
43025
44196
  }).optional().describe("Where its own metadata goes (its home subsystem, packs to adopt or drop)"),
43026
44197
  dryRun: dryRunArg
43027
44198
  }
@@ -43038,10 +44209,10 @@ ${renderChangeReport(report2)}`,
43038
44209
  {
43039
44210
  description: "Fold a member \u2014 every subsystem of it \u2014 back into the bound project, sending its own metadata to the destination (its L0 vision to the `into` subsystem's description; its requirements, boundaries and databases to the bound L0; its language, profile and depth onto the moved subsystems; its members and externals to the bound project's; its packs adopted or dropped as `packs` says) and re-pointing every other family project that consumed it at the bound project. What has no home \u2014 its lock, pins, derived outputs \u2014 is listed as deleted. Refused for a member carrying conformance debt, a pack only it selects with no `packs` answer, or a name collision. All-or-nothing; dryRun answers the plan and writes nothing; run it first and show the plan. Never locks.",
43040
44211
  inputSchema: {
43041
- alias: import_zod11.z.string().describe("The member's alias"),
43042
- into: import_zod11.z.string().optional().describe("The home subsystem for the member's L0 vision; required when it holds several subsystems"),
43043
- packs: import_zod11.z.enum(["adopt", "drop"]).optional().describe("adopt | drop: packs only the member selects"),
43044
- exports: import_zod11.z.array(import_zod11.z.string()).optional().describe("Extra public names of the member the bound project exports afterwards"),
44212
+ alias: import_zod12.z.string().describe("The member's alias"),
44213
+ into: import_zod12.z.string().optional().describe("The home subsystem for the member's L0 vision; required when it holds several subsystems"),
44214
+ packs: import_zod12.z.enum(["adopt", "drop"]).optional().describe("adopt | drop: packs only the member selects"),
44215
+ exports: import_zod12.z.array(import_zod12.z.string()).optional().describe("Extra public names of the member the bound project exports afterwards"),
43045
44216
  dryRun: dryRunArg
43046
44217
  }
43047
44218
  },
@@ -43057,9 +44228,9 @@ ${renderChangeReport(report2)}`,
43057
44228
  {
43058
44229
  description: "Make an existing project at the path a member of the bound project, keeping its L0, subsystems, packs and lock (sdd_add_member scaffolds a new one instead). Refused when its id collides with a family project's. All-or-nothing; dryRun answers the plan and writes nothing. Never locks.",
43059
44230
  inputSchema: {
43060
- alias: import_zod11.z.string().describe("The alias to declare ([a-z0-9-_]+)"),
43061
- path: import_zod11.z.string().describe("The project's root, relative to the bound project"),
43062
- description: import_zod11.z.string().optional().describe("What the member is to this project"),
44231
+ alias: import_zod12.z.string().describe("The alias to declare ([a-z0-9-_]+)"),
44232
+ path: import_zod12.z.string().describe("The project's root, relative to the bound project"),
44233
+ description: import_zod12.z.string().optional().describe("What the member is to this project"),
43063
44234
  dryRun: dryRunArg
43064
44235
  }
43065
44236
  },
@@ -43071,8 +44242,8 @@ ${renderChangeReport(report2)}`,
43071
44242
  {
43072
44243
  description: "Move a project's id \u2014 the bound project's, or a member's named by its alias path \u2014 and every reference to the old id across the family (aliases that were the id, their references and re-exports, externals naming it, pins). The whole family must be in reach. Every project it writes must be re-locked; the answer names them. All-or-nothing; dryRun answers the plan and writes nothing; run it first and show the plan.",
43073
44244
  inputSchema: {
43074
- newId: import_zod11.z.string().describe("The new project id"),
43075
- project: import_zod11.z.string().optional().describe("The member's alias path from the bound project (e.g. billing/payments); the bound project when omitted"),
44245
+ newId: import_zod12.z.string().describe("The new project id"),
44246
+ project: import_zod12.z.string().optional().describe("The member's alias path from the bound project (e.g. billing/payments); the bound project when omitted"),
43076
44247
  dryRun: dryRunArg
43077
44248
  }
43078
44249
  },
@@ -43084,8 +44255,8 @@ ${renderChangeReport(report2)}`,
43084
44255
  {
43085
44256
  description: "Rename one alias of the bound project (a member or an external) and respell the bound project's references through it; nothing in any member or sibling changes. All-or-nothing; dryRun answers the plan and writes nothing. Never locks.",
43086
44257
  inputSchema: {
43087
- alias: import_zod11.z.string().describe("The alias as declared now"),
43088
- newAlias: import_zod11.z.string().describe("The new alias"),
44258
+ alias: import_zod12.z.string().describe("The alias as declared now"),
44259
+ newAlias: import_zod12.z.string().describe("The new alias"),
43089
44260
  dryRun: dryRunArg
43090
44261
  }
43091
44262
  },
@@ -43097,8 +44268,8 @@ ${renderChangeReport(report2)}`,
43097
44268
  {
43098
44269
  description: "Take a member out of the family; the bound project and every family consumer then reach it as an external by path, pinned. No reference text changes. Refused (audience-too-narrow, each export named with its users) while a family project uses an export the member gives the family alone, unless widen is set: then exactly those used exports are widened to the instance audience in the member's L0, each shown in the plan. All-or-nothing; dryRun answers the plan and writes nothing. Never locks.",
43099
44270
  inputSchema: {
43100
- alias: import_zod11.z.string().describe("The member's alias"),
43101
- widen: import_zod11.z.boolean().optional().describe("Widen the used family-only exports to the instance audience instead of refusing"),
44271
+ alias: import_zod12.z.string().describe("The member's alias"),
44272
+ widen: import_zod12.z.boolean().optional().describe("Widen the used family-only exports to the instance audience instead of refusing"),
43102
44273
  dryRun: dryRunArg
43103
44274
  }
43104
44275
  },
@@ -43110,8 +44281,8 @@ ${renderChangeReport(report2)}`,
43110
44281
  {
43111
44282
  description: "Make the bound project's external a member \u2014 sdd_detach_member's inverse. Locally the external is found by a path inside the bound project and adopted where it is; on a hosted instance it names a project by source.hosted and `path` says where to adopt it (the hosting server relocates it there). All-or-nothing; dryRun answers the plan and writes nothing. Never locks.",
43112
44283
  inputSchema: {
43113
- alias: import_zod11.z.string().describe("The external's alias"),
43114
- path: import_zod11.z.string().optional().describe("Hosted: the member path to adopt a source.hosted external at, relative to the bound project; a source.path external is adopted where it is"),
44284
+ alias: import_zod12.z.string().describe("The external's alias"),
44285
+ path: import_zod12.z.string().optional().describe("Hosted: the member path to adopt a source.hosted external at, relative to the bound project; a source.path external is adopted where it is"),
43115
44286
  dryRun: dryRunArg
43116
44287
  }
43117
44288
  },
@@ -43123,8 +44294,8 @@ ${renderChangeReport(report2)}`,
43123
44294
  {
43124
44295
  description: "Rename a component and rewrite every reference to it in the bound tree: dependsOn, owns and dispatch entries, lifecycle entrypoints, published interfaces at L1 and L0, narrative call/dispatch/register targets, an interface's component, an implementation's contract and an entity's componentClass. The interface named i<id> and the implementation named <id>_impl move to the new ids and files; interfaces and implementations named otherwise keep their ids. Findings keyed on the component follow it too: every lint allow naming it on an edge site or in a covered unit, and every entry of the debt register (.wai/project.yaml rules.conformance.carried) anchored on a renamed spec or naming the component in its site or units \u2014 rewritten in place, every comment and all other formatting of the register kept, so unchanged debt never reads as paid and new at once. A register that cannot be rewritten that precisely is refused before the first write. Display names are left as they are. Refuses, writing nothing: a component that does not exist (component-missing), one inside a chained subproject (chained-component \u2014 rename it from that project's own root), a new id that is not a lowercase identifier without a namespace separator (invalid-id), and a new id \u2014 or i<newId> or <newId>_impl \u2014 already in use (id-taken). Returns the specs moved, each with its old and new id, the ids of the other specs rewritten (lint allows included), and `carried`: each register edit \u2014 the entry by code, spec and site as it stood, the key changed (spec, at or covers), from and to.",
43125
44296
  inputSchema: {
43126
- id: import_zod11.z.string().describe("The component to rename (namespaced if needed)"),
43127
- newId: import_zod11.z.string().describe("Its new id: a lowercase identifier with no namespace separator")
44297
+ id: import_zod12.z.string().describe("The component to rename (namespaced if needed)"),
44298
+ newId: import_zod12.z.string().describe("Its new id: a lowercase identifier with no namespace separator")
43128
44299
  }
43129
44300
  },
43130
44301
  ({ id, newId }) => {
@@ -43141,10 +44312,10 @@ ${renderChangeReport(report2)}`,
43141
44312
  {
43142
44313
  description: "Rename a contract method and retarget every reference to it in the bound tree. The method moves on every interface of the component that declares it \u2014 its name, and the name inside its signature \u2014 and on the implementations of those contracts, carrying narrative, sourcePath, symbol, detail, intent and findings unchanged; an implementation that declared no symbol is pinned to the old name unless pinSymbol is false, so the function it already binds to keeps binding. Narrative call, register and dispatch steps naming this component and method, dispatch-table bindings and lifecycle entrypoints are retargeted, and so are the findings keyed on it: a lint allow at the method on a spec it moved in or covering `<component>.<method>`, and every debt-register entry (.wai/project.yaml rules.conformance.carried) keyed the same way \u2014 rewritten in place with every comment and all other formatting kept (a register that cannot be rewritten that precisely is refused before the first write). Prose is never rewritten and a gRPC endpoint binding keeps its wire method \u2014 renaming a contract method must not silently rename an RPC; both are reported as mentions. Refuses, writing nothing: a component that does not exist (component-missing), one inside a chained subproject (chained-component \u2014 rename its method from that project's own root), a new name that is not a camel-case identifier (invalid-name), a method the component does not declare (method-missing), and a name a moving contract already declares (name-taken). Returns the specs the method moved in, the specs retargeted (lint allows included), the specs whose prose still names it, the pinned symbol when one was set, and `carried`: each register edit.",
43143
44314
  inputSchema: {
43144
- id: import_zod11.z.string().describe("The component whose method is renamed (namespaced if needed)"),
43145
- method: import_zod11.z.string().describe("The method name as it stands"),
43146
- newName: import_zod11.z.string().describe("Its new name: a camel-case identifier"),
43147
- pinSymbol: import_zod11.z.boolean().optional().describe("Whether an implementation that declares no symbol is pinned to the old name so its function still binds; true when omitted")
44315
+ id: import_zod12.z.string().describe("The component whose method is renamed (namespaced if needed)"),
44316
+ method: import_zod12.z.string().describe("The method name as it stands"),
44317
+ newName: import_zod12.z.string().describe("Its new name: a camel-case identifier"),
44318
+ pinSymbol: import_zod12.z.boolean().optional().describe("Whether an implementation that declares no symbol is pinned to the old name so its function still binds; true when omitted")
43148
44319
  }
43149
44320
  },
43150
44321
  ({ id, method, newName, pinSymbol }) => {
@@ -43155,16 +44326,36 @@ ${renderChangeReport(report2)}`,
43155
44326
  }
43156
44327
  }
43157
44328
  );
44329
+ reg(
44330
+ server,
44331
+ "sdd_rename_type",
44332
+ {
44333
+ description: "Rename a type and rewrite every reference to it in the bound tree: every type position naming it (contract and type-method params and returns, fields, signature-type params and returns), a signatureFrom naming it as a signature type, and an L1 or L0 export entry's typeDef. Only the named members of a type expression that name this type are respelled, in the style they were written (`Invoice` \u2192 `Bill`, `invoice` \u2192 `bill`); the rest of the text stays as written. The type moves to the new id and file under the same owner, and its old id joins its rename trace (previousIds) so a consumer of the design export reads the rename as a rename; an export entry that derived its public name from the old id gets `as: <that name>` first, so the published name and every consumer's pin stay. Rename traces are never rewritten. Findings keyed on the type follow it: lint allows naming it, and every debt-register entry anchored on it, rewritten in place (a register that cannot be rewritten that precisely is refused before the first write). The display name is left as it is. Refuses, writing nothing: a type that does not exist (type-missing), one in another project (chained-type), a new id that is not a lowercase identifier (invalid-id), and a new id another type of the same owner holds (id-taken) or retired (id-retired \u2014 unsetting the holder's previousIds releases it). Returns from and to, the specs rewritten, keptPublicNames and `carried`: each register edit.",
44334
+ inputSchema: {
44335
+ id: import_zod12.z.string().describe("The type to rename (qualified by its owning subsystem if needed, `subsystem::id`)"),
44336
+ newId: import_zod12.z.string().describe("Its new id: a lowercase identifier with no namespace separator")
44337
+ }
44338
+ },
44339
+ ({ id, newId }) => {
44340
+ try {
44341
+ const bare = id.startsWith("::") ? id.slice(2) : id;
44342
+ const resolved = loadTypeSpec(bare) ? bare : id;
44343
+ return json(renameType(resolved, newId));
44344
+ } catch (e) {
44345
+ return errText(String(e));
44346
+ }
44347
+ }
44348
+ );
43158
44349
  reg(
43159
44350
  server,
43160
44351
  "sdd_move_methods",
43161
44352
  {
43162
44353
  description: "Move contract methods from one component to another, carrying each method's narrative, calls and bindings, and re-pointing every reference that named the old home: narrative call/register/dispatch steps, dispatch-table bindings, lifecycle entrypoints and `calls` entries. The target gains the dependencies the moved narratives call. Findings keyed on a moved method follow it: a lint allow anchored at it moves to the receiving spec, one covering `<from>.<method>` names `<to>.<method>`, and the debt register (.wai/project.yaml rules.conformance.carried) is rekeyed the same way in place, every comment and all other formatting kept \u2014 the report's `carried` lists each register edit, and a register that cannot be rewritten that precisely is refused before the first write. ONE all-or-nothing gated write: if a rule refuses the move nothing is written and the report names the rule plus where these methods could live instead, cheapest legal home first, with the requested target among them so its shortfall reads beside the others. Prose is never rewritten and a wire endpoint keeps its address \u2014 moving a method between components must not silently re-address an RPC; both are reported as mentions. A target that declares no contract yet receives one, i<target>, and when implementation entries travel and no implementation realizes the receiving contract, <target>_impl is created for them, inheriting the source implementation's sourcePath; the report's `created` names every spec the move created. Refuses before the first write (unmovable request): a component or method that does not exist, a method name already declared on the target, a source and target that are the same component, a target with several contracts none named i<target>, a contract or implementation to create whose id another spec already holds, and a component inside a chained subproject (move it from that project's own root). A dry run runs the whole move, gate included, and reports what it would have done.",
43163
44354
  inputSchema: {
43164
- from: import_zod11.z.string().describe("The component the methods belong to (namespaced if needed)"),
43165
- to: import_zod11.z.string().describe("The component that should receive them (namespaced if needed)"),
43166
- methods: import_zod11.z.array(import_zod11.z.string()).describe("The method names to move; every one must exist on the source contract"),
43167
- dryRun: import_zod11.z.boolean().optional().describe("Answer with what the move would do and write nothing")
44355
+ from: import_zod12.z.string().describe("The component the methods belong to (namespaced if needed)"),
44356
+ to: import_zod12.z.string().describe("The component that should receive them (namespaced if needed)"),
44357
+ methods: import_zod12.z.array(import_zod12.z.string()).describe("The method names to move; every one must exist on the source contract"),
44358
+ dryRun: import_zod12.z.boolean().optional().describe("Answer with what the move would do and write nothing")
43168
44359
  }
43169
44360
  },
43170
44361
  ({ from, to, methods, dryRun }) => {
@@ -43180,39 +44371,39 @@ ${renderChangeReport(report2)}`,
43180
44371
  }
43181
44372
  );
43182
44373
  const componentInput = {
43183
- id: import_zod11.z.string().describe("Lowercase identifier for the component"),
43184
- name: import_zod11.z.string().describe("Human-readable display name"),
43185
- description: import_zod11.z.string().describe("Responsibility / internal architecture details"),
43186
- subsystem: import_zod11.z.string().describe("The L1 subsystem ID this component belongs to"),
43187
- componentType: import_zod11.z.enum(["Portal", "Orchestrator", "Supervisor", "Actor", "Store", "Index", "Query", "Registry", "Adapter", "Observer", "Repository"]).describe("The building block, or the pattern Repository. Specialist and Gateway are retired and cannot be authored: logic is an Orchestrator with a dependencyClass, a gateway is a Portal with the gateway variant"),
43188
- owns: import_zod11.z.array(import_zod11.z.string()).optional().describe("Member block ids privately owned by this component (patterns only)"),
43189
- dependsOn: import_zod11.z.array(import_zod11.z.string()).optional().describe("IDs of other components this collaborates with (facades or standalone blocks)"),
43190
- portalType: import_zod11.z.enum(["HTTP_API", "gRPC", "GraphQL", "MessageBus", "CLI", "NamedPipe", "IPC", "Custom"]).optional().describe("Portal-only, and expected on every Portal. OMIT IT on any other componentType \u2014 passing it there is refused at the write (UNEXPECTED_PORTAL_FIELD), nothing is saved."),
43191
- basePath: import_zod11.z.string().optional().describe("Portal-only: base path/prefix all the portal's endpoints mount under. OMIT IT on any other componentType \u2014 passing it there is refused at the write (UNEXPECTED_PORTAL_FIELD), nothing is saved."),
43192
- dispatch: import_zod11.z.array(import_zod11.z.object({
43193
- capability: import_zod11.z.string().describe('Capability name exactly as dispatched at runtime (e.g. "shadow_module.get")'),
43194
- component: import_zod11.z.string().describe("Component id serving this capability (must also appear under dependsOn/owns)"),
43195
- method: import_zod11.z.string().describe("Method name on the serving component's interface"),
43196
- description: import_zod11.z.string().optional()
44374
+ id: import_zod12.z.string().describe("Lowercase identifier for the component"),
44375
+ name: import_zod12.z.string().describe("Human-readable display name"),
44376
+ description: import_zod12.z.string().describe("Responsibility / internal architecture details"),
44377
+ subsystem: import_zod12.z.string().describe("The L1 subsystem ID this component belongs to"),
44378
+ componentType: import_zod12.z.enum(["Portal", "Orchestrator", "Supervisor", "Actor", "Store", "Index", "Query", "Registry", "Adapter", "Observer", "Repository"]).describe("The building block, or the pattern Repository. Specialist and Gateway are retired and cannot be authored: logic is an Orchestrator with a dependencyClass, a gateway is a Portal with the gateway variant"),
44379
+ owns: import_zod12.z.array(import_zod12.z.string()).optional().describe("Member block ids privately owned by this component (patterns only)"),
44380
+ dependsOn: import_zod12.z.array(import_zod12.z.string()).optional().describe("IDs of other components this collaborates with (facades or standalone blocks)"),
44381
+ portalType: import_zod12.z.enum(["HTTP_API", "gRPC", "GraphQL", "MessageBus", "CLI", "NamedPipe", "IPC", "Custom"]).optional().describe("Portal-only, and expected on every Portal. OMIT IT on any other componentType \u2014 passing it there is refused at the write (UNEXPECTED_PORTAL_FIELD), nothing is saved."),
44382
+ basePath: import_zod12.z.string().optional().describe("Portal-only: base path/prefix all the portal's endpoints mount under. OMIT IT on any other componentType \u2014 passing it there is refused at the write (UNEXPECTED_PORTAL_FIELD), nothing is saved."),
44383
+ dispatch: import_zod12.z.array(import_zod12.z.object({
44384
+ capability: import_zod12.z.string().describe('Capability name exactly as dispatched at runtime (e.g. "shadow_module.get")'),
44385
+ component: import_zod12.z.string().describe("Component id serving this capability (must also appear under dependsOn/owns)"),
44386
+ method: import_zod12.z.string().describe("Method name on the serving component's interface"),
44387
+ description: import_zod12.z.string().optional()
43197
44388
  }).strict()).optional().describe("Portal-only: capability \u2192 component.method dispatch table for generic-handle portals. Gives the reachability walker real edges and is validated against target interfaces (UNSERVED_CAPABILITY)."),
43198
- mounts: import_zod11.z.array(import_zod11.z.object({
43199
- portal: import_zod11.z.string().describe("The mounted Portal's component id"),
43200
- prefixes: import_zod11.z.array(import_zod11.z.string()).describe('The path prefixes this listener routes to the portal. A path lies under a prefix when it equals it or continues it past a slash, so "/" covers only the root itself'),
43201
- via: import_zod11.z.string().optional().describe("The router entry the listener calls to hand the portal its request, exported by the PORTAL's own file (held to it: UNREALIZED_EXPORT_HANDLE). Omit when the listener calls the portal's contract methods directly, route by route")
44389
+ mounts: import_zod12.z.array(import_zod12.z.object({
44390
+ portal: import_zod12.z.string().describe("The mounted Portal's component id"),
44391
+ prefixes: import_zod12.z.array(import_zod12.z.string()).describe('The path prefixes this listener routes to the portal. A path lies under a prefix when it equals it or continues it past a slash, so "/" covers only the root itself'),
44392
+ via: import_zod12.z.string().optional().describe("The router entry the listener calls to hand the portal its request, exported by the PORTAL's own file (held to it: UNREALIZED_EXPORT_HANDLE). Omit when the listener calls the portal's contract methods directly, route by route")
43202
44393
  }).strict()).optional().describe("Portal-only: the portals this LISTENER serves, each under its path prefixes and through its router entry. Declaring the field \u2014 even as an empty array \u2014 marks this portal as a listener, the one kind of portal nothing else needs to mount. Checked by portal-mounts: a mount must name a Portal (MOUNT_TARGET_NOT_PORTAL), every HTTP endpoint of a mounted portal must lie under one of its prefixes (ENDPOINT_OUTSIDE_MOUNT), and a portal with HTTP endpoints that is neither a listener nor mounted by one is reported (UNMOUNTED_PORTAL)."),
43203
- durability: import_zod11.z.enum(["ram-projection", "durable", "read-through", "cache"]).optional().describe("Store-only \u2014 OMIT IT on any other componentType, where it is refused at the write (DURABILITY_ON_NON_STORE) and nothing is saved. Every Store should declare one (MISSING_DURABILITY): durable = persisted RAM projection (hydration read-back from a lifecycle init entrypoint required \u2014 MISSING_HYDRATION); read-through = persisted with no RAM copy (every read is the read-back, hydration exempt); ram-projection = rebuilt not restored; cache = evictable loss-safe memo state."),
43204
- dependencyClass: import_zod11.z.enum(["pure", "read"]).optional().describe("Orchestrator-only \u2014 OMIT IT on any other componentType, where it is refused at the write (DEPENDENCY_CLASS_ON_NON_ORCHESTRATOR) and nothing is saved. Declares what logic may depend on, enforced as a Store's durability is (DEPENDENCY_CLASS_VIOLATION): pure = depends only on pure Orchestrators (a computation over the values it is handed, e.g. an arbiter or codec); read = also on read Orchestrators, Repositories, Indexes and Adapters, never calling their write methods; unset = a workflow."),
43205
- emits: import_zod11.z.array(import_zod11.z.object({
43206
- topic: import_zod11.z.string().describe("Topic/channel name exactly as used on the bus"),
43207
- event: import_zod11.z.string().optional().describe("Optional event name within the topic (informational; pairing is by topic)"),
43208
- description: import_zod11.z.string().optional()
44394
+ durability: import_zod12.z.enum(["ram-projection", "durable", "read-through", "cache"]).optional().describe("Store-only \u2014 OMIT IT on any other componentType, where it is refused at the write (DURABILITY_ON_NON_STORE) and nothing is saved. Every Store should declare one (MISSING_DURABILITY): durable = persisted RAM projection (hydration read-back from a lifecycle init entrypoint required \u2014 MISSING_HYDRATION); read-through = persisted with no RAM copy (every read is the read-back, hydration exempt); ram-projection = rebuilt not restored; cache = evictable loss-safe memo state."),
44395
+ dependencyClass: import_zod12.z.enum(["pure", "read"]).optional().describe("Orchestrator-only \u2014 OMIT IT on any other componentType, where it is refused at the write (DEPENDENCY_CLASS_ON_NON_ORCHESTRATOR) and nothing is saved. Declares what logic may depend on, enforced as a Store's durability is (DEPENDENCY_CLASS_VIOLATION): pure = depends only on pure Orchestrators (a computation over the values it is handed, e.g. an arbiter or codec); read = also on read Orchestrators, Repositories, Indexes and Adapters, never calling their write methods; unset = a workflow."),
44396
+ emits: import_zod12.z.array(import_zod12.z.object({
44397
+ topic: import_zod12.z.string().describe("Topic/channel name exactly as used on the bus"),
44398
+ event: import_zod12.z.string().optional().describe("Optional event name within the topic (informational; pairing is by topic)"),
44399
+ description: import_zod12.z.string().optional()
43209
44400
  }).strict()).optional().describe("Topics this component publishes \u2014 every emitted topic needs a subscriber somewhere in the tree (UNCONSUMED_TOPIC)."),
43210
- subscribesTo: import_zod11.z.array(import_zod11.z.object({
43211
- topic: import_zod11.z.string().describe("Topic/channel name exactly as used on the bus"),
43212
- event: import_zod11.z.string().optional(),
43213
- description: import_zod11.z.string().optional()
44401
+ subscribesTo: import_zod12.z.array(import_zod12.z.object({
44402
+ topic: import_zod12.z.string().describe("Topic/channel name exactly as used on the bus"),
44403
+ event: import_zod12.z.string().optional(),
44404
+ description: import_zod12.z.string().optional()
43214
44405
  }).strict()).optional().describe("Topics this component consumes (typical on Observers) \u2014 every subscription needs an emitter somewhere in the tree (UNSOURCED_SUBSCRIPTION)."),
43215
- ext: import_zod11.z.record(import_zod11.z.unknown()).optional().describe('Opaque pack/tool extension data (namespaced keys, e.g. "mypack:priority") \u2014 preserved verbatim, never validated or interpreted by the core'),
44406
+ ext: import_zod12.z.record(import_zod12.z.unknown()).optional().describe('Opaque pack/tool extension data (namespaced keys, e.g. "mypack:priority") \u2014 preserved verbatim, never validated or interpreted by the core'),
43216
44407
  status: statusInput
43217
44408
  };
43218
44409
  const componentInputFields = Object.keys(componentInput);
@@ -43260,45 +44451,45 @@ ${renderChangeReport(report2)}`,
43260
44451
  }
43261
44452
  }
43262
44453
  );
43263
- const methodParamItem = import_zod11.z.object({
43264
- name: import_zod11.z.string(),
43265
- type: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The parameter's type")),
43266
- description: import_zod11.z.string().optional(),
43267
- optional: import_zod11.z.boolean().optional().describe(
44454
+ const methodParamItem = import_zod12.z.object({
44455
+ name: import_zod12.z.string(),
44456
+ type: import_zod12.z.string().describe(TYPE_REF_GRAMMAR("The parameter's type")),
44457
+ description: import_zod12.z.string().optional(),
44458
+ optional: import_zod12.z.boolean().optional().describe(
43268
44459
  'Whether the parameter may be OMITTED by a caller. It is not nullability: a parameter that must be passed but may be passed as nothing is a required parameter whose type says so \u2014 "ProjectConfig?". Say whichever is true; they are different contracts (both together: may be left out, and may be none).'
43269
44460
  )
43270
44461
  }).strict();
43271
44462
  const interfaceMethodShape = {
43272
- name: import_zod11.z.string(),
43273
- description: import_zod11.z.string(),
43274
- signature: import_zod11.z.string().optional().describe(
44463
+ name: import_zod12.z.string(),
44464
+ description: import_zod12.z.string(),
44465
+ signature: import_zod12.z.string().optional().describe(
43275
44466
  "Prose signature \u2014 only for a method WITHOUT params. With params the server derives and writes the text (`name(a: T, b?: U): R`) and ignores this one (a notice names one that differed); a method with a signatureFrom states none."
43276
44467
  ),
43277
- returns: import_zod11.z.string().optional().describe(TYPE_REF_GRAMMAR("The type the method answers with. Required unless signatureFrom is set, whose source supplies it")),
43278
- signatureFrom: import_zod11.z.string().min(1).optional().describe(
44468
+ returns: import_zod12.z.string().optional().describe(TYPE_REF_GRAMMAR("The type the method answers with. Required unless signatureFrom is set, whose source supplies it")),
44469
+ signatureFrom: import_zod12.z.string().min(1).optional().describe(
43279
44470
  "Take this method's params and returns from ONE source instead of stating them: a signature type id (`billing.change_listener`, `alias::name`) or a contract method `component.method` whose component this one names in dependsOn or owns (no chains). State it ALONE \u2014 params or returns beside it are refused (SIGNATURE_SOURCE_RESTATED). A value that names both a method and a signature type is ambiguous: qualify it."
43280
44471
  ),
43281
- params: import_zod11.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking, and the signature text is derived from them. Strongly preferred."),
43282
- guarantees: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe("Semantic guarantees the method promises (combinable); any guarantee a narrative step asserts must be declared here. Builtin tokens: idempotent | atomic | transactional | exactly-once; extension packs may declare more (any other token is UNKNOWN_GUARANTEE)"),
43283
- effect: import_zod11.z.enum(["read", "write"]).optional().describe("State-effect direction on the component's held state \u2014 required on a durable Store's contract methods so the durability round-trip rule can pair writes with hydration read-backs"),
43284
- invokedBy: import_zod11.z.object({
43285
- kind: import_zod11.z.enum(["runtime", "external", "sibling-subsystem"]).describe("Who owns the out-of-graph invocation: runtime (timer/signal/shutdown hook), external (a system outside this project), sibling-subsystem (a modeled sibling whose edge is not narrated here)"),
43286
- caller: import_zod11.z.string().optional().describe("WHO invokes it and when, as reviewable prose \u2014 missing or placeholder-thin prose is INVOKED_BY_UNDESCRIBED")
44472
+ params: import_zod12.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking, and the signature text is derived from them. Strongly preferred."),
44473
+ guarantees: import_zod12.z.array(import_zod12.z.string().min(1)).optional().describe("Semantic guarantees the method promises (combinable); any guarantee a narrative step asserts must be declared here. Builtin tokens: idempotent | atomic | transactional | exactly-once; extension packs may declare more (any other token is UNKNOWN_GUARANTEE)"),
44474
+ effect: import_zod12.z.enum(["read", "write", "lifecycle"]).optional().describe("What the method does to the component's held state: read observes it; write modifies an entity's domain fields; lifecycle creates, destroys, or (un)registers an entity's existence or membership without modifying its fields, and calls only read and lifecycle methods (LIFECYCLE_CALLS_WRITE). Required on a durable Store's contract methods so the durability round-trip rule can pair mutations with hydration read-backs; a Supervisor may call a data component it does not own only through read and lifecycle methods (SUPERVISOR_WRITE_SHORTCUT)"),
44475
+ invokedBy: import_zod12.z.object({
44476
+ kind: import_zod12.z.enum(["runtime", "external", "sibling-subsystem"]).describe("Who owns the out-of-graph invocation: runtime (timer/signal/shutdown hook), external (a system outside this project), sibling-subsystem (a modeled sibling whose edge is not narrated here)"),
44477
+ caller: import_zod12.z.string().optional().describe("WHO invokes it and when, as reviewable prose \u2014 missing or placeholder-thin prose is INVOKED_BY_UNDESCRIBED")
43287
44478
  }).strict().optional().describe("Typed acknowledgment of a real caller OUTSIDE the modeled narrative graph. Unused-detection seeds the method as an entrypoint so reachability propagates through its narrative (unlike lint.allow); a method the internal walk already reaches is flagged stale (INVOKED_BY_REDUNDANT). Prefer a `register` narrative step when the wiring is internal."),
43288
- findings: import_zod11.z.array(import_zod11.z.object({
43289
- code: import_zod11.z.string().describe("UPPER_SNAKE finding code, unique within the method; a pack's codes carry the pack prefix (<PACK>_<CODE>)"),
43290
- severity: import_zod11.z.enum(["error", "warning", "notice"]).describe("Default severity, before project severity overrides and draft-context downgrades. A notice is reported but never fails the gate"),
43291
- summary: import_zod11.z.string().describe("One line saying what the finding means")
44479
+ findings: import_zod12.z.array(import_zod12.z.object({
44480
+ code: import_zod12.z.string().describe("UPPER_SNAKE finding code, unique within the method; a pack's codes carry the pack prefix (<PACK>_<CODE>)"),
44481
+ severity: import_zod12.z.enum(["error", "warning", "notice"]).describe("Default severity, before project severity overrides and draft-context downgrades. A notice is reported but never fails the gate"),
44482
+ summary: import_zod12.z.string().describe("One line saying what the finding means")
43292
44483
  }).strict()).optional().describe("The finding codes this method can report, each with its default severity and summary. Each declared code must be anchored in the method's source file, as a string literal or a property-access name (UNREALIZED_FINDING). A code is declared once per method; sdd_update_spec upserts and deletes findings by code."),
43293
- ext: import_zod11.z.record(import_zod11.z.unknown()).optional().describe("Opaque pack/tool extension data for this method (namespaced keys) \u2014 preserved verbatim")
44484
+ ext: import_zod12.z.record(import_zod12.z.unknown()).optional().describe("Opaque pack/tool extension data for this method (namespaced keys) \u2014 preserved verbatim")
43294
44485
  };
43295
44486
  const interfaceMethodInputFields = Object.keys(interfaceMethodShape);
43296
44487
  const interfaceInput = {
43297
- id: import_zod11.z.string().describe('Lowercase identifier prefixed with "i", e.g. "istorage"'),
43298
- name: import_zod11.z.string().describe("Human-readable contract name"),
43299
- description: import_zod11.z.string().describe("Contract description and obligations"),
43300
- component: import_zod11.z.string().describe("The L2 component ID this interface belongs to"),
43301
- methods: import_zod11.z.array(import_zod11.z.object(interfaceMethodShape).strict()).optional().describe("List of method signature contracts"),
44488
+ id: import_zod12.z.string().describe('Lowercase identifier prefixed with "i", e.g. "istorage"'),
44489
+ name: import_zod12.z.string().describe("Human-readable contract name"),
44490
+ description: import_zod12.z.string().describe("Contract description and obligations"),
44491
+ component: import_zod12.z.string().describe("The L2 component ID this interface belongs to"),
44492
+ methods: import_zod12.z.array(import_zod12.z.object(interfaceMethodShape).strict()).optional().describe("List of method signature contracts"),
43302
44493
  status: statusInput
43303
44494
  };
43304
44495
  const interfaceInputFields = Object.keys(interfaceInput);
@@ -43335,24 +44526,24 @@ ${renderChangeReport(report2)}`,
43335
44526
  {
43336
44527
  description: "Bind concrete wire endpoints to existing L3 interface methods (required for every Portal). Pick `transport` and fill that transport's address fields. Run after sdd_define_interface. Written through the authoring seam as one gated delta, and answered with the change report \u2014 every binding set or changed, or that nothing changed \u2014 as structured content beside the sentence.",
43337
44528
  inputSchema: {
43338
- interface: import_zod11.z.string().describe('The L3 interface ID (e.g. "ibilling-gateway")'),
43339
- endpoints: import_zod11.z.array(import_zod11.z.object({
43340
- method: import_zod11.z.string().describe("The NAME of the interface method to bind (not the HTTP verb)"),
43341
- transport: import_zod11.z.enum(["HTTP", "gRPC", "GraphQL", "MessageBus", "NamedPipe", "IPC", "CLI", "Custom"]).describe("Wire protocol; must match the Portal's portalType"),
43342
- httpMethod: import_zod11.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]).optional().describe("HTTP: verb"),
43343
- path: import_zod11.z.string().optional().describe('HTTP: route path, e.g. "/v1/checkout"'),
43344
- service: import_zod11.z.string().optional().describe("gRPC: service name"),
43345
- rpcMethod: import_zod11.z.string().optional().describe("gRPC: rpc method name"),
43346
- operation: import_zod11.z.enum(["query", "mutation", "subscription"]).optional().describe("GraphQL: operation kind"),
43347
- field: import_zod11.z.string().optional().describe("GraphQL: root field name"),
43348
- topic: import_zod11.z.string().optional().describe("MessageBus: topic"),
43349
- event: import_zod11.z.string().optional().describe("MessageBus: event name"),
43350
- queue: import_zod11.z.string().optional().describe("MessageBus: optional queue/consumer group"),
43351
- direction: import_zod11.z.enum(["subscribe", "publish"]).optional().describe("MessageBus: subscribe (default) or publish"),
43352
- pipe: import_zod11.z.string().optional().describe('NamedPipe: pipe name, e.g. "\\\\.\\pipe\\gk-events"'),
43353
- channel: import_zod11.z.string().optional().describe("IPC: channel name"),
43354
- command: import_zod11.z.string().optional().describe("CLI: command/subcommand"),
43355
- address: import_zod11.z.string().optional().describe("Custom: free-form address")
44529
+ interface: import_zod12.z.string().describe('The L3 interface ID (e.g. "ibilling-gateway")'),
44530
+ endpoints: import_zod12.z.array(import_zod12.z.object({
44531
+ method: import_zod12.z.string().describe("The NAME of the interface method to bind (not the HTTP verb)"),
44532
+ transport: import_zod12.z.enum(["HTTP", "gRPC", "GraphQL", "MessageBus", "NamedPipe", "IPC", "CLI", "Custom"]).describe("Wire protocol; must match the Portal's portalType"),
44533
+ httpMethod: import_zod12.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]).optional().describe("HTTP: verb"),
44534
+ path: import_zod12.z.string().optional().describe('HTTP: route path, e.g. "/v1/checkout"'),
44535
+ service: import_zod12.z.string().optional().describe("gRPC: service name"),
44536
+ rpcMethod: import_zod12.z.string().optional().describe("gRPC: rpc method name"),
44537
+ operation: import_zod12.z.enum(["query", "mutation", "subscription"]).optional().describe("GraphQL: operation kind"),
44538
+ field: import_zod12.z.string().optional().describe("GraphQL: root field name"),
44539
+ topic: import_zod12.z.string().optional().describe("MessageBus: topic"),
44540
+ event: import_zod12.z.string().optional().describe("MessageBus: event name"),
44541
+ queue: import_zod12.z.string().optional().describe("MessageBus: optional queue/consumer group"),
44542
+ direction: import_zod12.z.enum(["subscribe", "publish"]).optional().describe("MessageBus: subscribe (default) or publish"),
44543
+ pipe: import_zod12.z.string().optional().describe('NamedPipe: pipe name, e.g. "\\\\.\\pipe\\gk-events"'),
44544
+ channel: import_zod12.z.string().optional().describe("IPC: channel name"),
44545
+ command: import_zod12.z.string().optional().describe("CLI: command/subcommand"),
44546
+ address: import_zod12.z.string().optional().describe("Custom: free-form address")
43356
44547
  }).strict()).describe("One binding per method")
43357
44548
  },
43358
44549
  outputSchema: specChangeReportOutput
@@ -43394,80 +44585,80 @@ ${renderChangeReport(report2)}`,
43394
44585
  methods.push({ name: e.method, endpoint: parsed.data });
43395
44586
  bound2.push(`${e.method}\u2192${e.transport}`);
43396
44587
  }
43397
- const report2 = updateSpecGated("interface", interfaceId, { methods });
44588
+ const report3 = updateSpecGated("interface", interfaceId, { methods });
43398
44589
  return structured(
43399
44590
  `Bound ${bound2.length} endpoint(s) on "${interfaceId}": ${bound2.join(", ")}.
43400
- ${renderChangeReport(report2)}`,
43401
- report2
44591
+ ${renderChangeReport(report3)}`,
44592
+ report3
43402
44593
  );
43403
44594
  } catch (e) {
43404
44595
  return errMessage(e);
43405
44596
  }
43406
44597
  }
43407
44598
  );
43408
- const stepNo = () => import_zod11.z.number().int().positive();
43409
- const labelRef = () => import_zod11.z.string().min(1);
43410
- const narrativeStepInput = import_zod11.z.object({
44599
+ const stepNo = () => import_zod12.z.number().int().positive();
44600
+ const labelRef = () => import_zod12.z.string().min(1);
44601
+ const narrativeStepInput = import_zod12.z.object({
43411
44602
  stepNumber: stepNo().optional().describe("Defaults to the 1-based array position \u2014 jump fields reference these numbers"),
43412
44603
  label: labelRef().optional().describe("Optional symbolic anchor for this step (unique per narrative). Every jump-by-number field has a *Label twin resolved against these anchors at write time \u2014 prefer labels over hand-counted step numbers"),
43413
- description: import_zod11.z.string(),
43414
- type: import_zod11.z.enum(["local", "call", "dispatch", "register", "branch", "switch", "loop", "try", "parallel", "jump", "return", "throw"]),
43415
- targetComponent: import_zod11.z.string().optional().describe("call/register/dispatch: L2 component id (for dispatch, the Portal routed through)"),
43416
- targetMethod: import_zod11.z.string().optional().describe("call/register: method name on the target. A register step hands the target method to the runtime as a callback (timer, event listener, shutdown hook): reachability follows the edge, but it is never an invocation \u2014 exempt from call-graph conformance, call-cycle detection, and the durability boot walk"),
43417
- auth: import_zod11.z.object({ from: import_zod11.z.string(), note: import_zod11.z.string().optional() }).strict().optional().describe("call/dispatch: the credential this step presents to an AUTHED callee Portal and WHERE it loads from (`from`). Opaque form (env:API_KEY, a config key, vault:path) = a design note wairon never resolves; modeled form `component:<id>` references the Adapter/Store that provides the secret and is validated (must resolve, be an Adapter/Store, and be wired to the presenter). Absence on a call into a Portal whose auth \u2260 none warns (PORTAL_AUTH_UNMET). The authenticated call itself should be made by an Adapter (AUTH_PRESENTER_NOT_ADAPTER)."),
43418
- detach: import_zod11.z.boolean().optional().describe("call/dispatch: fire-and-forget \u2014 issue the call and continue without awaiting the result (no later step consumes it)"),
43419
- capability: import_zod11.z.string().optional().describe("dispatch: the capability routed through the target Portal's dispatch table (validated against it \u2014 UNSERVED_CAPABILITY)"),
43420
- assertsGuarantees: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe("Semantic guarantees this step relies on \u2014 each must be declared in the called method's L3 guarantees (NARRATIVE_SEMANTIC_UNBACKED otherwise). Builtin tokens: idempotent | atomic | transactional | exactly-once; extension packs may declare more (any other token is UNKNOWN_GUARANTEE)"),
43421
- assertsInvariants: import_zod11.z.array(import_zod11.z.string()).optional().describe(`Declared entity invariants this step upholds, as "<type-id>.<invariant-id>" refs (UNKNOWN_INVARIANT_REF when unresolved); write-effect methods of the entity's componentClass must carry one per declared invariant (UNASSERTED_INVARIANT)`),
43422
- condition: import_zod11.z.string().optional().describe("branch / while / doWhile"),
44604
+ description: import_zod12.z.string(),
44605
+ type: import_zod12.z.enum(["local", "call", "dispatch", "register", "branch", "switch", "loop", "try", "parallel", "jump", "return", "throw"]),
44606
+ targetComponent: import_zod12.z.string().optional().describe("call/register/dispatch: L2 component id (for dispatch, the Portal routed through)"),
44607
+ targetMethod: import_zod12.z.string().optional().describe("call/register: method name on the target. A register step hands the target method to the runtime as a callback (timer, event listener, shutdown hook): reachability follows the edge, but it is never an invocation \u2014 exempt from call-graph conformance, call-cycle detection, and the durability boot walk"),
44608
+ auth: import_zod12.z.object({ from: import_zod12.z.string(), note: import_zod12.z.string().optional() }).strict().optional().describe("call/dispatch: the credential this step presents to an AUTHED callee Portal and WHERE it loads from (`from`). Opaque form (env:API_KEY, a config key, vault:path) = a design note wairon never resolves; modeled form `component:<id>` references the Adapter/Store that provides the secret and is validated (must resolve, be an Adapter/Store, and be wired to the presenter). Absence on a call into a Portal whose auth \u2260 none warns (PORTAL_AUTH_UNMET). The authenticated call itself should be made by an Adapter (AUTH_PRESENTER_NOT_ADAPTER)."),
44609
+ detach: import_zod12.z.boolean().optional().describe("call/dispatch: fire-and-forget \u2014 issue the call and continue without awaiting the result (no later step consumes it)"),
44610
+ capability: import_zod12.z.string().optional().describe("dispatch: the capability routed through the target Portal's dispatch table (validated against it \u2014 UNSERVED_CAPABILITY)"),
44611
+ assertsGuarantees: import_zod12.z.array(import_zod12.z.string().min(1)).optional().describe("Semantic guarantees this step relies on \u2014 each must be declared in the called method's L3 guarantees (NARRATIVE_SEMANTIC_UNBACKED otherwise). Builtin tokens: idempotent | atomic | transactional | exactly-once; extension packs may declare more (any other token is UNKNOWN_GUARANTEE)"),
44612
+ assertsInvariants: import_zod12.z.array(import_zod12.z.string()).optional().describe(`Declared entity invariants this step upholds, as "<type-id>.<invariant-id>" refs (UNKNOWN_INVARIANT_REF when unresolved); write-effect methods of the entity's componentClass must carry one per declared invariant (UNASSERTED_INVARIANT)`),
44613
+ condition: import_zod12.z.string().optional().describe("branch / while / doWhile"),
43423
44614
  onTrueStep: stepNo().optional().describe("branch: default = next step"),
43424
44615
  onTrueLabel: labelRef().optional().describe("branch: symbolic alternative to onTrueStep"),
43425
44616
  onFalseStep: stepNo().optional().describe("branch: required (or onFalseLabel)"),
43426
44617
  onFalseLabel: labelRef().optional().describe("branch: symbolic alternative to onFalseStep"),
43427
- on: import_zod11.z.string().optional().describe("switch: the dispatched value"),
43428
- cases: import_zod11.z.array(import_zod11.z.object({ value: import_zod11.z.string(), step: stepNo().optional(), label: labelRef().optional() }).strict()).optional().describe("switch: required; each case targets its region by step number or label"),
44618
+ on: import_zod12.z.string().optional().describe("switch: the dispatched value"),
44619
+ cases: import_zod12.z.array(import_zod12.z.object({ value: import_zod12.z.string(), step: stepNo().optional(), label: labelRef().optional() }).strict()).optional().describe("switch: required; each case targets its region by step number or label"),
43429
44620
  defaultStep: stepNo().optional().describe("switch: default = next step"),
43430
44621
  defaultLabel: labelRef().optional().describe("switch: symbolic alternative to defaultStep"),
43431
- loopKind: import_zod11.z.enum(["forEach", "for", "while", "doWhile"]).optional().describe('loop: default forEach when "over" is set, else while'),
43432
- over: import_zod11.z.string().optional().describe("loop forEach/for: iteration source"),
44622
+ loopKind: import_zod12.z.enum(["forEach", "for", "while", "doWhile"]).optional().describe('loop: default forEach when "over" is set, else while'),
44623
+ over: import_zod12.z.string().optional().describe("loop forEach/for: iteration source"),
43433
44624
  endStep: stepNo().optional().describe("loop/try: last step of the body region (required, or endLabel)"),
43434
44625
  endLabel: labelRef().optional().describe("loop/try: symbolic alternative to endStep"),
43435
- catches: import_zod11.z.array(import_zod11.z.object({ error: import_zod11.z.string(), step: stepNo().optional(), label: labelRef().optional() }).strict()).optional().describe("try: handler regions, each targeted by step number or label"),
44626
+ catches: import_zod12.z.array(import_zod12.z.object({ error: import_zod12.z.string(), step: stepNo().optional(), label: labelRef().optional() }).strict()).optional().describe("try: handler regions, each targeted by step number or label"),
43436
44627
  finallyStep: stepNo().optional().describe("try: first step of the always-runs region"),
43437
44628
  finallyLabel: labelRef().optional().describe("try: symbolic alternative to finallyStep"),
43438
- branches: import_zod11.z.array(import_zod11.z.object({ step: stepNo().optional(), label: labelRef().optional(), name: import_zod11.z.string().optional() }).strict()).optional().describe("parallel: >= 2 arm entries (step number or label), ascending, first = the step after the header; arms are contiguous sub-regions of body next..endStep, joining after endStep once ALL complete"),
44629
+ branches: import_zod12.z.array(import_zod12.z.object({ step: stepNo().optional(), label: labelRef().optional(), name: import_zod12.z.string().optional() }).strict()).optional().describe("parallel: >= 2 arm entries (step number or label), ascending, first = the step after the header; arms are contiguous sub-regions of body next..endStep, joining after endStep once ALL complete"),
43439
44630
  toStep: stepNo().optional().describe("jump: required (break/continue/rejoin), or toLabel"),
43440
44631
  toLabel: labelRef().optional().describe("jump: symbolic alternative to toStep \u2014 resolves to the labeled step at write time"),
43441
- outcome: import_zod11.z.string().optional().describe('return: e.g. "success", "not found"'),
43442
- error: import_zod11.z.string().optional().describe("throw: the raised error")
44632
+ outcome: import_zod12.z.string().optional().describe('return: e.g. "success", "not found"'),
44633
+ error: import_zod12.z.string().optional().describe("throw: the raised error")
43443
44634
  }).strict();
43444
- const detailEnum = import_zod11.z.enum(["full", "calls-only", "intent"]);
43445
- const conformanceEnum = import_zod11.z.enum(["declared", "anchored", "off"]);
44635
+ const detailEnum = import_zod12.z.enum(["full", "calls-only", "intent"]);
44636
+ const conformanceEnum = import_zod12.z.enum(["declared", "anchored", "off"]);
43446
44637
  const implMethodShape = {
43447
- name: import_zod11.z.string(),
43448
- sourcePath: import_zod11.z.string().optional().describe("Optional: the source file realizing THIS method when it is not the implementation's sourcePath (e.g. a command whose body lives in its own file); the implementation's sourcePath is the default. Relative to project root \u2014 for a chained subproject's implementation (qualified id), relative to that subproject's root; a path given relative to this root that lands inside the subproject is re-expressed for you"),
44638
+ name: import_zod12.z.string(),
44639
+ sourcePath: import_zod12.z.string().optional().describe("Optional: the source file realizing THIS method when it is not the implementation's sourcePath (e.g. a command whose body lives in its own file); the implementation's sourcePath is the default. Relative to project root \u2014 for a chained subproject's implementation (qualified id), relative to that subproject's root; a path given relative to this root that lands inside the subproject is re-expressed for you"),
43449
44640
  detail: detailEnum.optional().describe("Detail level for this method (overrides the spec default)"),
43450
- intent: import_zod11.z.string().optional().describe("detail: intent \u2014 behavioral prose (what it does and how it fails); substitute for a narrative"),
44641
+ intent: import_zod12.z.string().optional().describe("detail: intent \u2014 behavioral prose (what it does and how it fails); substitute for a narrative"),
43451
44642
  conformance: conformanceEnum.optional().describe("Conformance tier for this method (overrides the spec default)"),
43452
- symbol: import_zod11.z.string().optional().describe("Code-level name realizing this contract method in the sourcePath file, when it legitimately differs from the intent-language contract name (e.g. put realized by saveSnapshot)"),
43453
- exportedVia: import_zod11.z.string().optional().describe("The exported binding a consumer imports to REACH this method, when the realization is published as a value that composes it rather than exported in its own right (a rule module publishes callConformanceRule, and the method is the check inside it). Not symbol, which names the function itself: this names the route to it, so the surface check reads that export as promised. A handle the method's own source file does not actually export is reported (UNREALIZED_EXPORT_HANDLE) and allows nothing"),
43454
- ext: import_zod11.z.record(import_zod11.z.unknown()).optional().describe("Opaque pack/tool extension data for this method (namespaced keys) \u2014 preserved verbatim"),
43455
- narrative: import_zod11.z.array(narrativeStepInput).optional(),
43456
- calls: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe('The calls this method makes, when its narrative does not show them (detail: intent, or calls-only with no steps authored) \u2014 each as "<component>.<method>", the spelling the debt register and lint allows name a unit with. The narrative walk takes exactly these edges and no others, so an undeclared collaborator is NOT reached: this is what keeps unused-detection honest at a lower detail dial. Each entry is validated like a call step (the component resolves, this component declares it, the method is on its contract). Refused beside a non-empty narrative \u2014 add the call step there instead')
44643
+ symbol: import_zod12.z.string().optional().describe("Code-level name realizing this contract method in the sourcePath file, when it legitimately differs from the intent-language contract name (e.g. put realized by saveSnapshot)"),
44644
+ exportedVia: import_zod12.z.string().optional().describe("The exported binding a consumer imports to REACH this method, when the realization is published as a value that composes it rather than exported in its own right (a rule module publishes callConformanceRule, and the method is the check inside it). Not symbol, which names the function itself: this names the route to it, so the surface check reads that export as promised. A handle the method's own source file does not actually export is reported (UNREALIZED_EXPORT_HANDLE) and allows nothing"),
44645
+ ext: import_zod12.z.record(import_zod12.z.unknown()).optional().describe("Opaque pack/tool extension data for this method (namespaced keys) \u2014 preserved verbatim"),
44646
+ narrative: import_zod12.z.array(narrativeStepInput).optional(),
44647
+ calls: import_zod12.z.array(import_zod12.z.string().min(1)).optional().describe('The calls this method makes, when its narrative does not show them (detail: intent, or calls-only with no steps authored) \u2014 each as "<component>.<method>", the spelling the debt register and lint allows name a unit with. The narrative walk takes exactly these edges and no others, so an undeclared collaborator is NOT reached: this is what keeps unused-detection honest at a lower detail dial. Each entry is validated like a call step (the component resolves, this component declares it, the method is on its contract). Refused beside a non-empty narrative \u2014 add the call step there instead')
43457
44648
  };
43458
44649
  const implMethodInputFields = Object.keys(implMethodShape);
43459
44650
  const implInput = {
43460
- id: import_zod11.z.string().describe('Lowercase identifier, e.g. "vfs_storage"'),
43461
- name: import_zod11.z.string().describe("Human-readable implementation name"),
43462
- description: import_zod11.z.string().describe("Implementation details"),
43463
- contract: import_zod11.z.string().describe("The L3 Interface contract ID this implements"),
43464
- sourcePath: import_zod11.z.string().optional().describe("Optional: target source code file path relative to project root \u2014 for a chained subproject's implementation (qualified id), relative to that subproject's root; a path given relative to this root that lands inside the subproject is re-expressed for you"),
43465
- simPath: import_zod11.z.string().optional().describe("Optional: the committed integration-sim harness file (project-relative; N:1 sharing allowed). The validator proves it exists and its import graph wires the REAL modules (this component + each direct dependency; technology adapters may stay faked) \u2014 running it is CI's job. Declaring the first simPath in a subsystem activates MISSING_INTEGRATION_SIM for its other complete non-leaf implementations"),
43466
- technologies: import_zod11.z.array(import_zod11.z.union([import_zod11.z.string(), import_zod11.z.object({ name: import_zod11.z.string(), matches: import_zod11.z.array(import_zod11.z.string()).min(1).describe("The tokens the leakage and contract checks match INSTEAD of the name \u2014 for a technology whose name is also an ordinary word of the tree (the yaml package, the YAML format)") }).strict()])).optional().describe(`External technologies this implementation binds to (e.g. ["mysql"], or [{ "name": "yaml", "matches": ["yaml package", "parseDocument"] }] when the bare name would match a common word) \u2014 declares this component's ownership tree as the technology's home; references outside it are flagged (TECH_LEAKAGE) and contract identifiers must stay intent-language. Only for Adapter/Store/Registry/Index components.`),
43467
- injectedParams: import_zod11.z.array(import_zod11.z.string()).optional().describe("The parameter names this realization takes BEFORE the ones its contract declares \u2014 a config object, a data root, the transport handles a portal is handed. Supplied by whatever wires the component up, never by the caller the contract describes, which is why they belong here and not to the contract: another realization may hold them as fields instead. Declared rather than guessed, because a leading parameter the contract does not name cannot be told from one it named under a different name (`seed(config)` realized as `bootstrapInstance(cfg)`); a leading parameter this list does not name is reported (UNDECLARED_PARAM). Only a LEADING run is dropped \u2014 one of these names appearing after the contract's own parameters is an argument in the middle of the caller's list, not wiring"),
44651
+ id: import_zod12.z.string().describe('Lowercase identifier, e.g. "vfs_storage"'),
44652
+ name: import_zod12.z.string().describe("Human-readable implementation name"),
44653
+ description: import_zod12.z.string().describe("Implementation details"),
44654
+ contract: import_zod12.z.string().describe("The L3 Interface contract ID this implements"),
44655
+ sourcePath: import_zod12.z.string().optional().describe("Optional: target source code file path relative to project root \u2014 for a chained subproject's implementation (qualified id), relative to that subproject's root; a path given relative to this root that lands inside the subproject is re-expressed for you"),
44656
+ simPath: import_zod12.z.string().optional().describe("Optional: the committed integration-sim harness file (project-relative; N:1 sharing allowed). The validator proves it exists and its import graph wires the REAL modules (this component + each direct dependency; technology adapters may stay faked) \u2014 running it is CI's job. Declaring the first simPath in a subsystem activates MISSING_INTEGRATION_SIM for its other complete non-leaf implementations"),
44657
+ technologies: import_zod12.z.array(import_zod12.z.union([import_zod12.z.string(), import_zod12.z.object({ name: import_zod12.z.string(), matches: import_zod12.z.array(import_zod12.z.string()).min(1).describe("The tokens the leakage and contract checks match INSTEAD of the name \u2014 for a technology whose name is also an ordinary word of the tree (the yaml package, the YAML format)") }).strict()])).optional().describe(`External technologies this implementation binds to (e.g. ["mysql"], or [{ "name": "yaml", "matches": ["yaml package", "parseDocument"] }] when the bare name would match a common word) \u2014 declares this component's ownership tree as the technology's home; references outside it are flagged (TECH_LEAKAGE) and contract identifiers must stay intent-language. Only for Adapter/Store/Registry/Index components.`),
44658
+ injectedParams: import_zod12.z.array(import_zod12.z.string()).optional().describe("The parameter names this realization takes BEFORE the ones its contract declares \u2014 a config object, a data root, the transport handles a portal is handed. Supplied by whatever wires the component up, never by the caller the contract describes, which is why they belong here and not to the contract: another realization may hold them as fields instead. Declared rather than guessed, because a leading parameter the contract does not name cannot be told from one it named under a different name (`seed(config)` realized as `bootstrapInstance(cfg)`); a leading parameter this list does not name is reported (UNDECLARED_PARAM). Only a LEADING run is dropped \u2014 one of these names appearing after the contract's own parameters is an argument in the middle of the caller's list, not wiring"),
43468
44659
  detail: detailEnum.optional().describe("Spec-level narrative detail default for all methods"),
43469
44660
  conformance: conformanceEnum.optional().describe("Spec-level conformance tier default: declared | anchored | off (omitted = stereotype default: Portal \u2192 anchored, else declared)"),
43470
- methods: import_zod11.z.array(import_zod11.z.object(implMethodShape).strict()).optional().describe("Method implementations containing L5 narratives"),
44661
+ methods: import_zod12.z.array(import_zod12.z.object(implMethodShape).strict()).optional().describe("Method implementations containing L5 narratives"),
43471
44662
  status: statusInput
43472
44663
  };
43473
44664
  const implInputFields = Object.keys(implInput);
@@ -43514,46 +44705,46 @@ ${renderChangeReport(report2)}`,
43514
44705
  }
43515
44706
  );
43516
44707
  const typeInput = {
43517
- kind: import_zod11.z.enum(["entity", "value-object", "signature", "enum"]).describe("entity (owned by a subsystem), value-object (often system-level shared), signature \u2014 a named function type: params and returns, nothing else \u2014 or enum: a closed, ordered set of named values"),
43518
- id: import_zod11.z.string().describe("Lowercase identifier"),
43519
- name: import_zod11.z.string().describe("Human-readable name"),
43520
- description: import_zod11.z.string().optional(),
43521
- subsystem: import_zod11.z.string().optional().describe("Owning subsystem id; omit for a system-level shared value object. A subsystem the tree does not have is refused and nothing is written"),
43522
- group: import_zod11.z.string().optional().describe("Optional logical group ID to organize this type in subfolders"),
43523
- fields: import_zod11.z.array(import_zod11.z.object({
43524
- name: import_zod11.z.string(),
43525
- type: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The field's type")),
43526
- description: import_zod11.z.string().optional(),
43527
- optional: import_zod11.z.boolean().optional(),
43528
- key: import_zod11.z.enum(["primary", "unique", "foreign"]).optional().describe("Identity marker (PK/unique/FK) for ERD and database schema derivation"),
43529
- references: import_zod11.z.string().optional().describe('For foreign keys, the referenced type/table id and optional field, e.g. "invoice.id"')
44708
+ kind: import_zod12.z.enum(["entity", "value-object", "signature", "enum"]).describe("entity (owned by a subsystem), value-object (often system-level shared), signature \u2014 a named function type: params and returns, nothing else \u2014 or enum: a closed, ordered set of named values"),
44709
+ id: import_zod12.z.string().describe("Lowercase identifier"),
44710
+ name: import_zod12.z.string().describe("Human-readable name"),
44711
+ description: import_zod12.z.string().optional(),
44712
+ subsystem: import_zod12.z.string().optional().describe("Owning subsystem id; omit for a system-level shared value object. A subsystem the tree does not have is refused and nothing is written"),
44713
+ group: import_zod12.z.string().optional().describe("Optional logical group ID to organize this type in subfolders"),
44714
+ fields: import_zod12.z.array(import_zod12.z.object({
44715
+ name: import_zod12.z.string(),
44716
+ type: import_zod12.z.string().describe(TYPE_REF_GRAMMAR("The field's type")),
44717
+ description: import_zod12.z.string().optional(),
44718
+ optional: import_zod12.z.boolean().optional(),
44719
+ key: import_zod12.z.enum(["primary", "unique", "foreign"]).optional().describe("Identity marker (PK/unique/FK) for ERD and database schema derivation"),
44720
+ references: import_zod12.z.string().optional().describe('For foreign keys, the referenced type/table id and optional field, e.g. "invoice.id"')
43530
44721
  }).strict()).optional().describe('Data fields (type is a primitive or a qualified type id, e.g. "billing.Invoice")'),
43531
- methods: import_zod11.z.array(import_zod11.z.object({
43532
- name: import_zod11.z.string(),
43533
- signature: import_zod11.z.string().optional().describe("Prose signature \u2014 only for a method WITHOUT params; with params the server derives and writes the text"),
43534
- params: import_zod11.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking; the signature text is derived from them"),
43535
- returns: import_zod11.z.string().describe(TYPE_REF_GRAMMAR("The type the method answers with")),
43536
- description: import_zod11.z.string().optional(),
43537
- sourcePath: import_zod11.z.string().optional().describe("Source file realizing this method when the type's own sourcePath does not hold it \u2014 a pure type method often lives apart from the declaration"),
43538
- symbol: import_zod11.z.string().optional().describe("Code-level name realizing this method when it differs from the method name, e.g. narrative_step.foreignFields realized by narrativeStepForeignFields")
44722
+ methods: import_zod12.z.array(import_zod12.z.object({
44723
+ name: import_zod12.z.string(),
44724
+ signature: import_zod12.z.string().optional().describe("Prose signature \u2014 only for a method WITHOUT params; with params the server derives and writes the text"),
44725
+ params: import_zod12.z.array(methodParamItem).optional().describe("Structured parameters \u2014 authoritative for type checking; the signature text is derived from them"),
44726
+ returns: import_zod12.z.string().describe(TYPE_REF_GRAMMAR("The type the method answers with")),
44727
+ description: import_zod12.z.string().optional(),
44728
+ sourcePath: import_zod12.z.string().optional().describe("Source file realizing this method when the type's own sourcePath does not hold it \u2014 a pure type method often lives apart from the declaration"),
44729
+ symbol: import_zod12.z.string().optional().describe("Code-level name realizing this method when it differs from the method name, e.g. narrative_step.foreignFields realized by narrativeStepForeignFields")
43539
44730
  }).strict()).optional().describe("Pure intrinsic methods only"),
43540
- componentClass: import_zod11.z.string().optional().describe("Optional component id that implements or owns this logical entity"),
43541
- invariants: import_zod11.z.array(import_zod11.z.object({
43542
- id: import_zod11.z.string().describe("Stable invariant id, unique within the entity"),
43543
- description: import_zod11.z.string().describe("The property that must hold, stated precisely")
44731
+ componentClass: import_zod12.z.string().optional().describe("Optional component id that implements or owns this logical entity"),
44732
+ invariants: import_zod12.z.array(import_zod12.z.object({
44733
+ id: import_zod12.z.string().describe("Stable invariant id, unique within the entity"),
44734
+ description: import_zod12.z.string().describe("The property that must hold, stated precisely")
43544
44735
  }).strict()).optional().describe("Declared domain invariants (entities): every write-effect method of the componentClass must carry a narrative step asserting each (assertsInvariants) \u2014 declarations checked, enforcement never proven"),
43545
- database: import_zod11.z.string().optional().describe("Optional database id for table-schema types"),
43546
- table: import_zod11.z.string().optional().describe("Optional database table name for table-schema types"),
43547
- linkedEntity: import_zod11.z.string().optional().describe("Optional logical entity id represented by this table-schema type"),
43548
- sourcePath: import_zod11.z.string().optional().describe("Source file holding the declaration of this type (project-relative). Naming one turns the type into a claim on code: the file must resolve and the declaration must be anchored in it (UNREALIZED_TYPE)"),
43549
- symbol: import_zod11.z.string().optional().describe('Code-level name realizing the declaration when it differs from name, e.g. a type named "Invoice Line" declared as InvoiceLine'),
43550
- params: import_zod11.z.array(methodParamItem).optional().describe("kind signature only: the function type's parameters, in declared order (SIGNATURE_TYPE_MEMBERS on any other kind)"),
43551
- returns: import_zod11.z.string().optional().describe(TYPE_REF_GRAMMAR("kind signature only, and required there: the function type's one output")),
43552
- values: import_zod11.z.array(import_zod11.z.object({
43553
- name: import_zod11.z.string().min(1).describe(`The value's name, exactly as data carries it ("stable", "local_only")`),
43554
- description: import_zod11.z.string().optional().describe("What the value means")
44736
+ database: import_zod12.z.string().optional().describe("Optional database id for table-schema types"),
44737
+ table: import_zod12.z.string().optional().describe("Optional database table name for table-schema types"),
44738
+ linkedEntity: import_zod12.z.string().optional().describe("Optional logical entity id represented by this table-schema type"),
44739
+ sourcePath: import_zod12.z.string().optional().describe("Source file holding the declaration of this type (project-relative). Naming one turns the type into a claim on code: the file must resolve and the declaration must be anchored in it (UNREALIZED_TYPE)"),
44740
+ symbol: import_zod12.z.string().optional().describe('Code-level name realizing the declaration when it differs from name, e.g. a type named "Invoice Line" declared as InvoiceLine'),
44741
+ params: import_zod12.z.array(methodParamItem).optional().describe("kind signature only: the function type's parameters, in declared order (SIGNATURE_TYPE_MEMBERS on any other kind)"),
44742
+ returns: import_zod12.z.string().optional().describe(TYPE_REF_GRAMMAR("kind signature only, and required there: the function type's one output")),
44743
+ values: import_zod12.z.array(import_zod12.z.object({
44744
+ name: import_zod12.z.string().min(1).describe(`The value's name, exactly as data carries it ("stable", "local_only")`),
44745
+ description: import_zod12.z.string().optional().describe("What the value means")
43555
44746
  }).strict()).optional().describe("kind enum only, and required there: the values in declared order \u2014 the order is part of the design (a narrowest-first track list means something). Unique by name ignoring case and separators; no ordinals and no separate wire value"),
43556
- holds: import_zod11.z.string().optional().describe('kind value-object only: makes it a NAMED SCALAR \u2014 one primitive under a name (string, int, float, bool, bytes, date, datetime or duration), a newtype or type alias in every language (`type PackPath = string`), declared in place of fields. Not a union, not a named type, not any; fields beside it, or holds on another kind, is NAMED_SCALAR_MEMBERS. Aliases are respelled (boolean \u2192 bool) and number is refused ("int or float?")')
44747
+ holds: import_zod12.z.string().optional().describe('kind value-object only: makes it a NAMED SCALAR \u2014 one primitive under a name (string, int, float, bool, bytes, date, datetime or duration), a newtype or type alias in every language (`type PackPath = string`), declared in place of fields. Not a union, not a named type, not any; fields beside it, or holds on another kind, is NAMED_SCALAR_MEMBERS. Aliases are respelled (boolean \u2192 bool) and number is refused ("int or float?")')
43557
44748
  };
43558
44749
  const typeInputFields = Object.keys(typeInput);
43559
44750
  reg(
@@ -43610,9 +44801,9 @@ ${renderChangeReport(report2)}`,
43610
44801
  {
43611
44802
  description: "Validate the SDD spec tree, checking parent references, contract compatibility, narratives, and component type boundaries. Supports scoping and recursion controls. Findings come back as structured content too, under the schema this tool declares \u2014 errors, warnings and notices already split into three lists (a notice never makes the tree invalid and never fails --ci), each with its code, severity, message and the spec it concerns \u2014 so a caller filters them as objects instead of parsing the JSON text block and hoping its shape holds.",
43612
44803
  inputSchema: {
43613
- subsystem: import_zod11.z.string().optional().describe("Only validate the specified subsystem (granular)"),
43614
- recursive: import_zod11.z.boolean().optional().describe("At a project that declares members: the family run (true, the default) or the owner's gate alone (false)"),
43615
- family: import_zod11.z.boolean().optional().describe("Ask for the family run explicitly: every member's own gate, and this project's externals composed against their live producers within the request's reach (`wairon validate --family`)")
44804
+ subsystem: import_zod12.z.string().optional().describe("Only validate the specified subsystem (granular)"),
44805
+ recursive: import_zod12.z.boolean().optional().describe("At a project that declares members: the family run (true, the default) or the owner's gate alone (false)"),
44806
+ family: import_zod12.z.boolean().optional().describe("Ask for the family run explicitly: every member's own gate, and this project's externals composed against their live producers within the request's reach (`wairon validate --family`)")
43616
44807
  },
43617
44808
  outputSchema: validateTreeOutput
43618
44809
  },
@@ -43653,9 +44844,9 @@ ${renderChangeReport(report2)}`,
43653
44844
  {
43654
44845
  description: `Get/read the parsed JSON contents of a specific spec from the spec tree. Returns structural contents without file system path searching. Pass "methods" to read only the named methods of a contract, an implementation or a type \u2014 a 45-method spec fetched whole to look at one of them is the read side of the same waste a restatement is on the write side; the answer then carries a "partialResult" marker naming what was left out, and must never be re-authored from. For a variant-tagged COMPONENT the result also carries a derived, read-only "variantGuidance" (the variant's base, its implementation guidance, and the same-variant sibling components to implement alike) \u2014 it is resolved from the variant registry, not part of the spec, so never write it back. A contract's methods come back in their STORED form \u2014 a method that takes its signature from a source carries its signatureFrom, not the params the loader resolves into it \u2014 so the answer can be re-authored from as it is; the resolved params, returns and text of each such method come back as a derived, read-only "resolvedSignatures" marker. The structured content carries the same answer with the derived markers KEPT SEPARATE from the stored spec ({kind, id, spec, partialResult?, variantGuidance?, resolvedSignatures?}), so nothing derived can be mistaken for something stored; the text block folds them in as it always has.`,
43655
44846
  inputSchema: {
43656
- kind: import_zod11.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The kind of specification"),
43657
- id: import_zod11.z.string().describe('The identifier of the spec to fetch (the L0 system spec is a singleton \u2014 pass the system name or "system")'),
43658
- methods: import_zod11.z.array(import_zod11.z.string().min(1)).optional().describe("Return only these methods by name; every other field of the spec comes back unchanged. Only an interface, an implementation or a type declares methods \u2014 asking for one elsewhere is refused, as is a name the spec does not declare (the answer names the ones it does). Omit it for the whole spec.")
44847
+ kind: import_zod12.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The kind of specification"),
44848
+ id: import_zod12.z.string().describe('The identifier of the spec to fetch (the L0 system spec is a singleton \u2014 pass the system name or "system")'),
44849
+ methods: import_zod12.z.array(import_zod12.z.string().min(1)).optional().describe("Return only these methods by name; every other field of the spec comes back unchanged. Only an interface, an implementation or a type declares methods \u2014 asking for one elsewhere is refused, as is a name the spec does not declare (the answer names the ones it does). Omit it for the whole spec.")
43659
44850
  },
43660
44851
  outputSchema: getSpecOutput
43661
44852
  },
@@ -43740,8 +44931,8 @@ ${renderChangeReport(report2)}`,
43740
44931
  {
43741
44932
  description: "Delete a specification file from the spec tree and clean up any empty parent directories. Answers with a structured deletion beside the sentence: whether a spec was removed, and the tests that encode a method the deletion took away (when the project declares test roots).",
43742
44933
  inputSchema: {
43743
- kind: import_zod11.z.enum(["subsystem", "component", "interface", "implementation", "type"]).describe("The kind of spec to delete"),
43744
- id: import_zod11.z.string().describe("The ID of the spec to delete")
44934
+ kind: import_zod12.z.enum(["subsystem", "component", "interface", "implementation", "type"]).describe("The kind of spec to delete"),
44935
+ id: import_zod12.z.string().describe("The ID of the spec to delete")
43745
44936
  },
43746
44937
  outputSchema: specDeletionOutput
43747
44938
  },
@@ -43763,17 +44954,17 @@ ${testsBlock}` : ""}`, deletion);
43763
44954
  {
43764
44955
  description: "Update/patch an existing SDD specification (subsystem, component, interface, implementation, or type) using a granular delta. Updates fields, appends/merges array elements, or inserts/deletes narrative steps. Answers with exactly what changed, and with every path the delta named that the write did not act on. Type positions (the type of a param, a returns, the type of a field, the params and returns of a signature) are written in the neutral type grammar: an alias the delta writes (string[], T | null, boolean, Promise<T>) is stored canonical and listed under `respellings`, and a stored alias at a position the write keeps is respelled with it; a position the delta writes that has no canonical spelling (number \u2014 int or float?, an inline object or function type, a literal union, a union mixing in a primitive) is refused, naming the replacement, while one the stored spec already held is left alone. Pass dryRun to be told what it would do without writing it.",
43765
44956
  inputSchema: {
43766
- kind: import_zod11.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The spec kind to update (system = the singleton L0 \u2014 vision, boundaries, globalRequirements, databases, and publicInterfaces: the project export table, each entry a re-export {from, component, interface, typeDef, as, name, type, details, audience: project|department|instance|partner|external} \u2014 from alone re-exports everything a subsystem exports, and a legacy {id, subsystem} reads as {as, from})"),
43767
- id: import_zod11.z.string().describe("The ID of the spec to update (namespaced if needed)"),
43768
- delta: import_zod11.z.record(import_zod11.z.any()).describe(`The partial fields to merge into the spec. ARRAYS UPSERT, they do not replace: an array whose elements carry an identity is merged element-by-element, so a delta naming ONE element leaves the others intact. Identity is "name" or "id" by default, and per field: dispatch by "capability", a listener's mounts by "portal", lifecycle by phase+component+method, emits/subscribesTo by topic+event, trustedLinks by "subsystem", a subsystem's publicInterfaces by component+interface (or type+details for an entry not yet bound to a component, and by from+item+interface+as for a re-export or a type export), invariants and patterns by "id", lint.allow by "code" AND "at" (an allow covers one occurrence, so several may share a code on one spec), an interface method's findings by "code", boundaries by "name", globalRequirements by "description", switch cases by "value", try catches by "error". Identity merging applies at EVERY depth, including an array INSIDE an element (a method's params, a step's catches). Add "action: 'delete'" (or "remove: true") alongside that identity to REMOVE an element \u2014 including a stale lint allow. Arrays of plain STRINGS (owns, dependsOn, guarantees) carry no per-element identity and are replaced wholesale; pass [] to clear any array outright. To REMOVE an optional field entirely, list it in "unset": e.g. {"unset": ["basePath", "variant"]} \u2014 passing null/undefined means "no change" (they are skipped), and writing "" would leave the field present but empty, which is a different and usually wrong spec. Unsetting a required field is refused by schema validation, which names it. For narrative steps, match by "stepNumber" and use "action: 'insert'" (shifts subsequent steps up) or "action: 'delete'" (shifts subsequent steps down and removes it). Step entries apply in ASCENDING stepNumber order, each against the numbering the earlier entries of the SAME delta left behind \u2014 delete step 3 and step 7 becomes step 6 \u2014 so prefer labels, and restate the step's "label" or "description" on a delete to have it checked against the step actually addressed. Renumbering RELOCATES every flow jump field (onTrueStep/onFalseStep/cases.step/defaultStep/endStep/catches.step/finallyStep/toStep) in the same narrative. Only STORED jumps relocate: a jump the delta itself writes (on an inserted, appended or edited step) names its target in the numbering the WHOLE delta leaves behind, after all of its inserts and deletes, and no later step of the same delta moves it. A method the delta ADDS without a narrative is an intent-level method with none ([]). An element the delta NAMES merges field by field: a field it leaves out, or passes as null, keeps its stored value at EVERY depth (a method named without "narrative" keeps its steps, a step named without "catches" keeps them), while "narrative": [] CLEARS that method's steps \u2014 so leave a method you are not editing out of the delta. A delete is REJECTED when the narrative has no such step, when a jump still targets it (retarget the referrers first), when a restated label/description does not match, or when it is a loop/try/parallel header whose body would be left standing (retype the header first to dissolve the region, then delete it). Changing a step's "type" REBUILDS it for the new type: its description and label are kept and every field the new type cannot carry is dropped (returned as a NOTICE); a delta that retypes AND sets such a field is refused. A step delta is also refused when it carries a marker the merge does not recognise: a non-boolean "remove", an "action" that is neither "insert" nor "delete", a "captureJumps" outside an insert, or no "stepNumber" to address. Inserting AT a jump target relocates those jumps past the inserted step by default (a NOTICE is returned) \u2014 add "captureJumps": true on the inserted step to retarget entry jumps onto it (loop/try endStep region tails always relocate with the body and are never captured). Every jump field has a "*Label" twin (toLabel, onFalseLabel, endLabel, \u2026, and "label" on a cases/catches entry) resolved against step labels AFTER the merge, so a delta may anchor on a label only pre-existing steps carry; a label the delta supplies REPLACES the stored number it twins, while setting the number and its label together in one delta is refused as a contradiction. Reference ids in deltas may use LOCAL names \u2014 they are qualified against the spec's namespace exactly as the loader would. Per-spec lint suppression: set "lint: { allow: [{ code, at, covers, reason }] }" to silence a WARNING or NOTICE code on this spec only (errors always surface; stale allows are flagged). An allow covers EXACTLY the occurrence it names: "at" is the site the finding names (a contract method, an import edge "from -> to", a declared edge "component -> target") and is REQUIRED for a code whose findings report one, while a finding that reports no site is covered only by an allow that names none; "covers" lists the units an aggregating finding reports, and the allow silences it only when every one is listed. This delta is deliberately OPEN below its top level \u2014 the shapes nest further than a schema here should restate \u2014 so a key that is not a field at its depth is not refused, it is NAMED BACK under NO EFFECT in the answer, together with any value the spec already held and any "unset" that removed nothing. Read that list: it is where a nested typo shows up.`),
43769
- dryRun: import_zod11.z.boolean().optional().describe("Ask what this delta WOULD do instead of doing it. The whole write runs, the candidate gate included, and the answer is the change report it would have produced \u2014 marked DRY RUN, with nothing stamped and not one byte of the stored file moved. Use it before a delta that renumbers a long narrative.")
44957
+ kind: import_zod12.z.enum(["system", "subsystem", "component", "interface", "implementation", "type"]).describe("The spec kind to update (system = the singleton L0 \u2014 vision, boundaries, globalRequirements, databases, and publicInterfaces: the project export table, each entry a re-export {from, component, interface, typeDef, as, name, type, details, audience: project|department|instance|partner|external} \u2014 from alone re-exports everything a subsystem exports, and a legacy {id, subsystem} reads as {as, from})"),
44958
+ id: import_zod12.z.string().describe("The ID of the spec to update (namespaced if needed)"),
44959
+ delta: import_zod12.z.record(import_zod12.z.any()).describe(`The partial fields to merge into the spec. ARRAYS UPSERT, they do not replace: an array whose elements carry an identity is merged element-by-element, so a delta naming ONE element leaves the others intact. Identity is "name" or "id" by default, and per field: dispatch by "capability", a listener's mounts by "portal", lifecycle by phase+component+method, emits/subscribesTo by topic+event, trustedLinks by "subsystem", a subsystem's publicInterfaces by component+interface (or type+details for an entry not yet bound to a component, and by from+item+interface+as for a re-export or a type export), invariants and patterns by "id", lint.allow by "code" AND "at" (an allow covers one occurrence, so several may share a code on one spec), an interface method's findings by "code", boundaries by "name", globalRequirements by "description", switch cases by "value", try catches by "error". Identity merging applies at EVERY depth, including an array INSIDE an element (a method's params, a step's catches). Add "action: 'delete'" (or "remove: true") alongside that identity to REMOVE an element \u2014 including a stale lint allow. Arrays of plain STRINGS (owns, dependsOn, guarantees) carry no per-element identity and are replaced wholesale; pass [] to clear any array outright. To REMOVE an optional field entirely, list it in "unset": e.g. {"unset": ["basePath", "variant"]} \u2014 passing null/undefined means "no change" (they are skipped), and writing "" would leave the field present but empty, which is a different and usually wrong spec. Unsetting a required field is refused by schema validation, which names it. For narrative steps, match by "stepNumber" and use "action: 'insert'" (shifts subsequent steps up) or "action: 'delete'" (shifts subsequent steps down and removes it). Step entries apply in ASCENDING stepNumber order, each against the numbering the earlier entries of the SAME delta left behind \u2014 delete step 3 and step 7 becomes step 6 \u2014 so prefer labels, and restate the step's "label" or "description" on a delete to have it checked against the step actually addressed. Renumbering RELOCATES every flow jump field (onTrueStep/onFalseStep/cases.step/defaultStep/endStep/catches.step/finallyStep/toStep) in the same narrative. Only STORED jumps relocate: a jump the delta itself writes (on an inserted, appended or edited step) names its target in the numbering the WHOLE delta leaves behind, after all of its inserts and deletes, and no later step of the same delta moves it. A method the delta ADDS without a narrative is an intent-level method with none ([]). An element the delta NAMES merges field by field: a field it leaves out, or passes as null, keeps its stored value at EVERY depth (a method named without "narrative" keeps its steps, a step named without "catches" keeps them), while "narrative": [] CLEARS that method's steps \u2014 so leave a method you are not editing out of the delta. A delete is REJECTED when the narrative has no such step, when a jump still targets it (retarget the referrers first), when a restated label/description does not match, or when it is a loop/try/parallel header whose body would be left standing (retype the header first to dissolve the region, then delete it). Changing a step's "type" REBUILDS it for the new type: its description and label are kept and every field the new type cannot carry is dropped (returned as a NOTICE); a delta that retypes AND sets such a field is refused. A step delta is also refused when it carries a marker the merge does not recognise: a non-boolean "remove", an "action" that is neither "insert" nor "delete", a "captureJumps" outside an insert, or no "stepNumber" to address. Inserting AT a jump target relocates those jumps past the inserted step by default (a NOTICE is returned) \u2014 add "captureJumps": true on the inserted step to retarget entry jumps onto it (loop/try endStep region tails always relocate with the body and are never captured). Every jump field has a "*Label" twin (toLabel, onFalseLabel, endLabel, \u2026, and "label" on a cases/catches entry) resolved against step labels AFTER the merge, so a delta may anchor on a label only pre-existing steps carry; a label the delta supplies REPLACES the stored number it twins, while setting the number and its label together in one delta is refused as a contradiction. Reference ids in deltas may use LOCAL names \u2014 they are qualified against the spec's namespace exactly as the loader would. Per-spec lint suppression: set "lint: { allow: [{ code, at, covers, reason }] }" to silence a WARNING or NOTICE code on this spec only (errors always surface; stale allows are flagged). An allow covers EXACTLY the occurrence it names: "at" is the site the finding names (a contract method, an import edge "from -> to", a declared edge "component -> target") and is REQUIRED for a code whose findings report one, while a finding that reports no site is covered only by an allow that names none; "covers" lists the units an aggregating finding reports, and the allow silences it only when every one is listed. This delta is deliberately OPEN below its top level \u2014 the shapes nest further than a schema here should restate \u2014 so a key that is not a field at its depth is not refused, it is NAMED BACK under NO EFFECT in the answer, together with any value the spec already held and any "unset" that removed nothing. Read that list: it is where a nested typo shows up.`),
44960
+ dryRun: import_zod12.z.boolean().optional().describe("Ask what this delta WOULD do instead of doing it. The whole write runs, the candidate gate included, and the answer is the change report it would have produced \u2014 marked DRY RUN, with nothing stamped and not one byte of the stored file moved. Use it before a delta that renumbers a long narrative.")
43770
44961
  },
43771
44962
  outputSchema: specChangeReportOutput
43772
44963
  },
43773
44964
  ({ kind, id, delta, dryRun }) => {
43774
44965
  try {
43775
- const report2 = updateSpecGated(kind, id, delta, dryRun);
43776
- return structured(renderChangeReport(report2), report2);
44966
+ const report3 = updateSpecGated(kind, id, delta, dryRun);
44967
+ return structured(renderChangeReport(report3), report3);
43777
44968
  } catch (e) {
43778
44969
  return errText(String(e));
43779
44970
  }
@@ -43785,8 +44976,8 @@ ${testsBlock}` : ""}`, deletion);
43785
44976
  {
43786
44977
  description: "Get the completeness status dashboard of the SDD spec tree. Supports scoping and recursion controls.",
43787
44978
  inputSchema: {
43788
- subsystem: import_zod11.z.string().optional().describe("Only show status for the specified subsystem"),
43789
- recursive: import_zod11.z.boolean().optional().describe("Whether to descend into the members this project declares (default: true)")
44979
+ subsystem: import_zod12.z.string().optional().describe("Only show status for the specified subsystem"),
44980
+ recursive: import_zod12.z.boolean().optional().describe("Whether to descend into the members this project declares (default: true)")
43790
44981
  }
43791
44982
  },
43792
44983
  ({ subsystem, recursive }) => {
@@ -43800,14 +44991,14 @@ ${testsBlock}` : ""}`, deletion);
43800
44991
  } catch {
43801
44992
  approvals = void 0;
43802
44993
  }
43803
- const report2 = getStatusReport({
44994
+ const report3 = getStatusReport({
43804
44995
  subsystem,
43805
44996
  memberDepth,
43806
44997
  approvals
43807
44998
  });
43808
44999
  const family = statusFamilyContext();
43809
45000
  const verdict = approvalVerdict(approvals);
43810
- return text2(`${banner}${family}${report2.text}${verdict.text}`);
45001
+ return text2(`${banner}${family}${report3.text}${verdict.text}`);
43811
45002
  } catch (e) {
43812
45003
  return errText(`${banner}${String(e)}`);
43813
45004
  }
@@ -43819,7 +45010,7 @@ ${testsBlock}` : ""}`, deletion);
43819
45010
  {
43820
45011
  description: "Pin the bound project's declared externals (.wai/project.yaml `externals`) \u2014 the named aliases, else all \u2014 into .wai/externals/<alias>.yaml and .wai/externals.lock.yaml, recording the signature digest of every member the project's references use. Answers one outcome per alias (pinned, unchanged, unresolved, unreachable) with the references that land on no public name of the producer (export them from its L0 to pin them). A tree-scoped write: a producer the request may not read is reported unreachable, never read.",
43821
45012
  inputSchema: {
43822
- aliases: import_zod11.z.array(import_zod11.z.string()).optional().describe("The aliases to pin; all declared externals when omitted")
45013
+ aliases: import_zod12.z.array(import_zod12.z.string()).optional().describe("The aliases to pin; all declared externals when omitted")
43823
45014
  },
43824
45015
  outputSchema: externalPinsOutput
43825
45016
  },
@@ -43856,7 +45047,7 @@ ${testsBlock}` : ""}`, deletion);
43856
45047
  {
43857
45048
  description: "Compose the LIVE delegation brief for one resolved agent: the fully rendered instruction body plus the ownedPaths/readPaths scope fence \u2014 the dynamic replacement for generated per-component agent files. Fetch a brief and spawn a generic subagent with it: always fresh after a re-lock, no session restart needed. List agent ids via listAgents or resources/list (the wairon-agent:// entries).",
43858
45049
  inputSchema: {
43859
- agentId: import_zod11.z.string().describe("The resolved agent id (list via listAgents or resources/list)")
45050
+ agentId: import_zod12.z.string().describe("The resolved agent id (list via listAgents or resources/list)")
43860
45051
  }
43861
45052
  },
43862
45053
  ({ agentId }) => {
@@ -43918,9 +45109,30 @@ function loadProjectConfig3() {
43918
45109
  CustomTargetConfigSchema,
43919
45110
  CustomTargetSchema,
43920
45111
  DEFAULT_TARGET_DIRS,
45112
+ DESIGN_APPROVALS,
45113
+ DESIGN_DEPENDENCY_ROLES,
45114
+ DESIGN_FORMAT,
45115
+ DESIGN_FORMAT_VERSION,
43921
45116
  DatabaseSpecSchema,
43922
45117
  DependencyClassSchema,
45118
+ DesignApprovalSchema,
45119
+ DesignComponentSchema,
45120
+ DesignDependencyRoleSchema,
45121
+ DesignDependencySchema,
43923
45122
  DesignDepthSchema,
45123
+ DesignExportEntrySchema,
45124
+ DesignExportSchema,
45125
+ DesignFieldSchema,
45126
+ DesignImplementationSchema,
45127
+ DesignInterfaceSchema,
45128
+ DesignMethodBodySchema,
45129
+ DesignMethodSchema,
45130
+ DesignParamSchema,
45131
+ DesignProjectSchema,
45132
+ DesignSourceSchema,
45133
+ DesignSubsystemSchema,
45134
+ DesignTypeRefSchema,
45135
+ DesignTypeSchema,
43924
45136
  DiagramConfigSchema,
43925
45137
  DispatchBindingSchema,
43926
45138
  DoctorOptionsError,
@@ -43980,6 +45192,8 @@ function loadProjectConfig3() {
43980
45192
  PortalAuthSchemeSchema,
43981
45193
  PortalMountSchema,
43982
45194
  PortalTypeSchema,
45195
+ PreviousIdsSchema,
45196
+ PreviousNamesSchema,
43983
45197
  ProfileSelectionSubjectSchema,
43984
45198
  ProjectConfigSchema,
43985
45199
  ProjectNotInitializedError,
@@ -44023,6 +45237,7 @@ function loadProjectConfig3() {
44023
45237
  TopologyConfigSchema,
44024
45238
  TransportSchema,
44025
45239
  TrustedLinkSchema,
45240
+ TypeExpressionSchema,
44026
45241
  TypeFieldSchema,
44027
45242
  TypeKindSchema,
44028
45243
  TypeMethodSchema,
@@ -44110,6 +45325,7 @@ function loadProjectConfig3() {
44110
45325
  ensureDir,
44111
45326
  ensureProjectInitialized,
44112
45327
  excerptParent,
45328
+ exportDesign,
44113
45329
  exportSpecTree,
44114
45330
  exportTargetKey,
44115
45331
  exportUsage,
@@ -44259,6 +45475,7 @@ function loadProjectConfig3() {
44259
45475
  renameComponent,
44260
45476
  renameId,
44261
45477
  renameMethod,
45478
+ renameType,
44262
45479
  renderDiagram,
44263
45480
  repairForeignStepFields,
44264
45481
  repairSignatures,
@@ -44298,6 +45515,7 @@ function loadProjectConfig3() {
44298
45515
  settledSpecPaths,
44299
45516
  signatureFacts,
44300
45517
  signatureTypeRefs,
45518
+ specIndexRetiredBy,
44301
45519
  specPathsInScope,
44302
45520
  splitNamespace,
44303
45521
  stepConfigVerdict,