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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -65,7 +65,7 @@ var init_defaults = __esm({
65
65
  copilot: ".github/prompts",
66
66
  codex: ".codex/agents"
67
67
  };
68
- WAIRON_VERSION = "5.1.1-dev.16";
68
+ WAIRON_VERSION = "5.1.1-dev.17";
69
69
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
70
70
  SUPPORTED_ALIASES = ["wai"];
71
71
  SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
@@ -382,10 +382,10 @@ ${GUIDE_MARKER_END}
382
382
  fs4.writeFileSync(filePath, newContent, "utf-8");
383
383
  }
384
384
  function stripGuideSection(content) {
385
- const start = content.indexOf(GUIDE_MARKER_START);
385
+ const start2 = content.indexOf(GUIDE_MARKER_START);
386
386
  const end = content.indexOf(GUIDE_MARKER_END);
387
- if (start === -1 || end === -1) return content;
388
- return content.slice(0, start) + content.slice(end + GUIDE_MARKER_END.length);
387
+ if (start2 === -1 || end === -1) return content;
388
+ return content.slice(0, start2) + content.slice(end + GUIDE_MARKER_END.length);
389
389
  }
390
390
  function writeRootGuideDelegator(projectRoot2, targetType) {
391
391
  if (targetType === "claude") {
@@ -1118,7 +1118,7 @@ function defaultNarrativeDetail(component) {
1118
1118
  if (componentType === "Portal" || componentType === "Observer" || componentType === "Adapter") {
1119
1119
  return "calls-only";
1120
1120
  }
1121
- if (componentType === "Store" || componentType === "Index" || componentType === "Registry") {
1121
+ if (componentType === "Store" || componentType === "Index" || componentType === "Query" || componentType === "Registry") {
1122
1122
  return "intent";
1123
1123
  }
1124
1124
  return "full";
@@ -1151,7 +1151,7 @@ function implementationSourceFiles(impl) {
1151
1151
  for (const method2 of impl.methods ?? []) add(method2.sourcePath);
1152
1152
  return files;
1153
1153
  }
1154
- var import_zod7, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, PatternRefSchema, EventBindingSchema, ExternalLinkTypeSchema, ExternalLinkSchema, PortalAuthSchemeSchema, PortalAuthSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, FindingDeclarationSchema, MethodSignatureSchema, INTENT_FLOOR_MIN_CHARS, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, NamedOpenApiSpecSchema, GroupSpecSchema;
1154
+ var import_zod7, SpecIdSchema, SpecStatusSchema, BoundaryItemSchema, RequirementItemSchema, DatabaseSpecSchema, DiagramConfigSchema, SURFACE_AUDIENCES, SurfaceAudienceSchema, SystemPublicInterfaceSchema, SystemSpecSchema, PublicInterfaceTypeSchema, PublicInterfaceSchema, TrustedLinkSchema, LintAllowSchema, LintConfigSchema, ExtDataSchema, LifecycleEntrypointSchema, SubsystemSpecSchema, ComponentTypeSchema, PATTERN_TYPES, PortalTypeSchema, DispatchBindingSchema, DurabilitySchema, DependencyClassSchema, PatternRefSchema, EventBindingSchema, ExternalLinkTypeSchema, ExternalLinkSchema, PortalAuthSchemeSchema, PortalAuthSchema, ComponentSpecSchema, HttpMethodSchema, TransportSchema, EndpointSchema, SEMANTIC_GUARANTEES, GuaranteeSchema, MethodParamSchema, FindingDeclarationSchema, MethodSignatureSchema, INTENT_FLOOR_MIN_CHARS, InterfaceSpecSchema, NarrativeStepTypeSchema, LoopKindSchema, SwitchCaseSchema, CatchClauseSchema, ParallelBranchSchema, NarrativeStepSchema, NarrativeDetailSchema, ConformanceTierSchema, MethodImplementationSchema, ImplementationSpecSchema, TypeKindSchema, TypeFieldSchema, TypeMethodSchema, InvariantSchema, TypeSpecSchema, SurfaceOriginSchema, SurfaceTypeDefSchema, SurfaceContractEntrySchema, SurfaceSnapshotSchema, NamedOpenApiSpecSchema, GroupSpecSchema;
1155
1155
  var init_specs = __esm({
1156
1156
  "src/models/specs.ts"() {
1157
1157
  "use strict";
@@ -1317,21 +1317,27 @@ var init_specs = __esm({
1317
1317
  "Actor",
1318
1318
  "Store",
1319
1319
  "Index",
1320
+ "Query",
1321
+ // Repository member for computed reads over its Store
1320
1322
  "Registry",
1321
1323
  "Adapter",
1322
1324
  "Observer",
1323
- "Specialist",
1324
1325
  "View",
1325
1326
  // Pure presenter/UI component
1326
1327
  // Patterns (compositions of blocks)
1327
1328
  "Repository",
1328
- "Gateway",
1329
1329
  "FeatureComponent",
1330
1330
  // Logic Hook + View Presenter pattern
1331
- "RouterComponent"
1331
+ "RouterComponent",
1332
1332
  // Switch/routing component pattern
1333
+ // Retired stereotypes: still parsed so a tree using them loads and the
1334
+ // rules can report them (STEREOTYPE_RETIRED), never authored new
1335
+ "Specialist",
1336
+ // logic is an Orchestrator with a dependencyClass
1337
+ "Gateway"
1338
+ // a gateway is a Portal with the gateway variant
1333
1339
  ]);
1334
- PATTERN_TYPES = /* @__PURE__ */ new Set(["Repository", "Gateway", "FeatureComponent", "RouterComponent"]);
1340
+ PATTERN_TYPES = /* @__PURE__ */ new Set(["Repository", "FeatureComponent", "RouterComponent"]);
1335
1341
  PortalTypeSchema = import_zod7.z.enum(["HTTP_API", "gRPC", "GraphQL", "MessageBus", "CLI", "NamedPipe", "IPC", "Custom"]);
1336
1342
  DispatchBindingSchema = import_zod7.z.object({
1337
1343
  /** Capability name exactly as dispatched at runtime (e.g. "shadow_module.get"). */
@@ -1344,6 +1350,7 @@ var init_specs = __esm({
1344
1350
  description: import_zod7.z.string().optional()
1345
1351
  });
1346
1352
  DurabilitySchema = import_zod7.z.enum(["ram-projection", "durable", "read-through", "cache"]);
1353
+ DependencyClassSchema = import_zod7.z.enum(["pure", "read"]);
1347
1354
  PatternRefSchema = import_zod7.z.object({
1348
1355
  id: import_zod7.z.string(),
1349
1356
  version: import_zod7.z.string().optional()
@@ -1398,6 +1405,8 @@ var init_specs = __esm({
1398
1405
  dispatch: import_zod7.z.array(DispatchBindingSchema).optional(),
1399
1406
  /** Store-only: whether held state survives restart (see DurabilitySchema). */
1400
1407
  durability: DurabilitySchema.optional(),
1408
+ /** Orchestrator-only: what the logic may depend on; unset means a workflow (see DependencyClassSchema). */
1409
+ dependencyClass: DependencyClassSchema.optional(),
1401
1410
  /** Topics this component publishes to (see EventBindingSchema). */
1402
1411
  emits: import_zod7.z.array(EventBindingSchema).optional(),
1403
1412
  /** Topics this component consumes (see EventBindingSchema) — typical on Observers. */
@@ -1488,9 +1497,10 @@ var init_specs = __esm({
1488
1497
  }).optional(),
1489
1498
  /**
1490
1499
  * The finding codes this method can report, each with its default severity
1491
- * and summary (see FindingDeclarationSchema). Each declared code must appear
1492
- * as a string literal in the method's source file (UNREALIZED_FINDING). A
1493
- * code is declared once per method.
1500
+ * and summary (see FindingDeclarationSchema). Each declared code must be
1501
+ * anchored in the method's source file as a string literal or a
1502
+ * property-access name (UNREALIZED_FINDING). A code is declared once per
1503
+ * method.
1494
1504
  */
1495
1505
  findings: import_zod7.z.array(FindingDeclarationSchema).superRefine((findings, ctx) => {
1496
1506
  const seen = /* @__PURE__ */ new Set();
@@ -6493,9 +6503,9 @@ var init_integration_conformance = __esm({
6493
6503
  if (impl.simPath) adopted.add(comp.subsystem);
6494
6504
  }
6495
6505
  const isTechBoundary = (compId) => (implsByComponent.get(compId) ?? []).some((i) => (i.technologies ?? []).length > 0);
6496
- const reachFrom = (start) => {
6497
- const seen = /* @__PURE__ */ new Set([start]);
6498
- const stack = [start];
6506
+ const reachFrom = (start2) => {
6507
+ const seen = /* @__PURE__ */ new Set([start2]);
6508
+ const stack = [start2];
6499
6509
  while (stack.length) {
6500
6510
  const from = stack.pop();
6501
6511
  const facts = factsByPath.get(from);
@@ -8878,14 +8888,14 @@ function buildExcalidrawScene(model, L) {
8878
8888
  const src = rectById[edge.from], tgt = rectById[edge.to];
8879
8889
  if (!a || !b || !src || !tgt) return;
8880
8890
  const leftToRight = b.x >= a.x + a.w;
8881
- const start = leftToRight ? { x: a.x + a.w, y: a.y + a.h / 2 } : { x: a.x, y: a.y + a.h / 2 };
8891
+ const start2 = leftToRight ? { x: a.x + a.w, y: a.y + a.h / 2 } : { x: a.x, y: a.y + a.h / 2 };
8882
8892
  const end = leftToRight ? { x: b.x, y: b.y + b.h / 2 } : { x: b.x + b.w, y: b.y + b.h / 2 };
8883
8893
  const id = "edge-" + edgeN++;
8884
- const arrow = base(id, "arrow", { x: start.x, y: start.y, w: Math.abs(end.x - start.x), h: Math.abs(end.y - start.y) });
8894
+ const arrow = base(id, "arrow", { x: start2.x, y: start2.y, w: Math.abs(end.x - start2.x), h: Math.abs(end.y - start2.y) });
8885
8895
  arrow.roundness = { type: 2 };
8886
8896
  arrow.strokeColor = edge.cross ? "#c26767" : "#8d97a5";
8887
8897
  arrow.strokeWidth = edge.cross ? 2 : 1;
8888
- arrow.points = [[0, 0], [end.x - start.x, end.y - start.y]];
8898
+ arrow.points = [[0, 0], [end.x - start2.x, end.y - start2.y]];
8889
8899
  arrow.lastCommittedPoint = null;
8890
8900
  arrow.startBinding = { elementId: src.id, focus: 0, gap: 4 };
8891
8901
  arrow.endBinding = { elementId: tgt.id, focus: 0, gap: 4 };
@@ -14556,28 +14566,52 @@ var init_domains = __esm({
14556
14566
  function globalVariantsDir() {
14557
14567
  return process.env.WAIRON_VARIANTS_DIR ?? path16.join(os5.homedir(), ".wairon", "variants");
14558
14568
  }
14559
- function readVariantsDir(dir) {
14569
+ function builtinVariantsDir() {
14570
+ const candidates = [
14571
+ path16.resolve(__dirname, "..", "templates", "variants"),
14572
+ // src/core & dist/cli
14573
+ path16.resolve(__dirname, "templates", "variants")
14574
+ // dist (library entry)
14575
+ ];
14576
+ return candidates.find((dir) => fs12.existsSync(dir)) ?? candidates[0];
14577
+ }
14578
+ function projectVariantsDir() {
14579
+ return path16.join(getProjectRoot(), ".wai", "variants");
14580
+ }
14581
+ function variantFiles(dir) {
14560
14582
  let entries;
14561
14583
  try {
14562
14584
  entries = fs12.readdirSync(dir, { withFileTypes: true });
14563
14585
  } catch {
14564
14586
  return [];
14565
14587
  }
14588
+ return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path16.join(dir, e.name));
14589
+ }
14590
+ function parseVariants(raw) {
14591
+ if (raw == null) return [];
14592
+ return (Array.isArray(raw) ? raw : [raw]).map((item) => VariantDefSchema.parse(item));
14593
+ }
14594
+ function reportSkippedFile(file, err) {
14595
+ console.error(`[variants] skipped "${file}": ${err instanceof Error ? err.message : String(err)}`);
14596
+ }
14597
+ function readVariantsDir(dir) {
14566
14598
  const out = [];
14567
- for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
14568
- if (!e.isFile() || !/\.ya?ml$/i.test(e.name)) continue;
14569
- const full = path16.join(dir, e.name);
14599
+ for (const file of variantFiles(dir)) {
14570
14600
  try {
14571
- const raw = readYamlFile(full);
14572
- if (raw == null) continue;
14573
- const items = Array.isArray(raw) ? raw : [raw];
14574
- for (const item of items) out.push(VariantDefSchema.parse(item));
14601
+ out.push(...parseVariants(readYamlFile(file)));
14575
14602
  } catch (err) {
14576
- console.error(`[variants] skipped "${full}": ${err instanceof Error ? err.message : String(err)}`);
14603
+ reportSkippedFile(file, err);
14577
14604
  }
14578
14605
  }
14579
14606
  return out;
14580
14607
  }
14608
+ function mergeById(...layers) {
14609
+ const byId = /* @__PURE__ */ new Map();
14610
+ for (const layer of layers) {
14611
+ for (const v of layer) byId.set(v.id, v);
14612
+ }
14613
+ return [...byId.values()];
14614
+ }
14581
14615
  function resolveVariantGuidance(component, allComponents, variantsById) {
14582
14616
  if (!component.variant) return null;
14583
14617
  const def = variantsById.get(component.variant);
@@ -14611,10 +14645,11 @@ function composeVariantGuidance(comps, allComponents, variantsById) {
14611
14645
  }
14612
14646
  function loadProjectVariants() {
14613
14647
  try {
14614
- const byId = /* @__PURE__ */ new Map();
14615
- for (const v of readVariantsDir(globalVariantsDir())) byId.set(v.id, v);
14616
- for (const v of readVariantsDir(path16.join(getProjectRoot(), ".wai", "variants"))) byId.set(v.id, v);
14617
- return [...byId.values()];
14648
+ return mergeById(
14649
+ readVariantsDir(builtinVariantsDir()),
14650
+ readVariantsDir(globalVariantsDir()),
14651
+ readVariantsDir(projectVariantsDir())
14652
+ );
14618
14653
  } catch {
14619
14654
  return [];
14620
14655
  }
@@ -14632,7 +14667,7 @@ var init_variants = __esm({
14632
14667
  VariantDefSchema = import_zod10.z.object({
14633
14668
  /** Variant id referenced by a component's `variant` (e.g. "publisher", "org/external-config-adapter"). */
14634
14669
  id: import_zod10.z.string().min(1),
14635
- /** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Specialist, …). */
14670
+ /** The core stereotype this variant specializes — authoritative for generic semantics (Adapter, Orchestrator, …). */
14636
14671
  base: import_zod10.z.string().min(1),
14637
14672
  /** How to implement a component of this variant — the recipe the implementer follows and reuses across same-variant components. */
14638
14673
  guidance: import_zod10.z.string().min(1),
@@ -16417,10 +16452,10 @@ var require_node = __commonJS({
16417
16452
  0
16418
16453
  ]);
16419
16454
  var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
16420
- var freb = function(eb, start) {
16455
+ var freb = function(eb, start2) {
16421
16456
  var b = new u16(31);
16422
16457
  for (var i2 = 0; i2 < 31; ++i2) {
16423
- b[i2] = start += 1 << eb[i2 - 1];
16458
+ b[i2] = start2 += 1 << eb[i2 - 1];
16424
16459
  }
16425
16460
  var r = new i32(b[30]);
16426
16461
  for (var i2 = 1; i2 < 30; ++i2) {
@@ -24815,7 +24850,7 @@ NOTICE:
24815
24850
  name: import_zod11.z.string().describe("Human-readable display name"),
24816
24851
  description: import_zod11.z.string().describe("Responsibility / internal architecture details"),
24817
24852
  subsystem: import_zod11.z.string().describe("The L1 subsystem ID this component belongs to"),
24818
- componentType: import_zod11.z.enum(["Portal", "Orchestrator", "Supervisor", "Actor", "Store", "Index", "Registry", "Adapter", "Observer", "Specialist", "Repository", "Gateway"]).describe("The building block, or pattern (Repository/Gateway)"),
24853
+ 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"),
24819
24854
  owns: import_zod11.z.array(import_zod11.z.string()).optional().describe("Member block ids privately owned by this component (patterns only)"),
24820
24855
  dependsOn: import_zod11.z.array(import_zod11.z.string()).optional().describe("IDs of other components this collaborates with (facades or standalone blocks)"),
24821
24856
  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."),
@@ -24827,6 +24862,7 @@ NOTICE:
24827
24862
  description: import_zod11.z.string().optional()
24828
24863
  })).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)."),
24829
24864
  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."),
24865
+ 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."),
24830
24866
  emits: import_zod11.z.array(import_zod11.z.object({
24831
24867
  topic: import_zod11.z.string().describe("Topic/channel name exactly as used on the bus"),
24832
24868
  event: import_zod11.z.string().optional().describe("Optional event name within the topic (informational; pairing is by topic)"),
@@ -24844,10 +24880,10 @@ NOTICE:
24844
24880
  server,
24845
24881
  "sdd_add_component",
24846
24882
  {
24847
- description: `Add an L2 Component under a subsystem. componentType is a building block (Portal, Orchestrator, Supervisor, Actor, Store, Index, Registry, Adapter, Observer, Specialist) or a pattern (Repository, Gateway). Patterns set "owns" (their private member blocks); all components set "dependsOn" (collaborators \u2014 facades or standalone blocks). Held/persisted state (configs, permissions, sessions, caches): model the Repository recipe \u2014 a Store + Registry (write) + Index (read) owned by a Repository facade consumers depend on; a deliberately standalone Store is the sanctioned lightweight form (workflow-layer consumers + lint.allow on UNOWNED_STORE). Never hold state as fields inside an Orchestrator/Specialist because a Store link was refused. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced (an omitted array is CLEARED), while lint.allow, a Portal's auth, variant, patterns and externalLinks are carried forward \u2014 edit those with sdd_update_spec.`,
24883
+ description: `Add an L2 Component under a subsystem. componentType is a building block (Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer) or the pattern Repository. Specialist and Gateway are retired (STEREOTYPE_RETIRED) and cannot be authored: logic is an Orchestrator with a dependencyClass (pure | read; unset = a workflow), and a gateway is a Portal with the gateway variant (set variant with sdd_update_spec). Patterns set "owns" (their private member blocks); all components set "dependsOn" (collaborators \u2014 facades or standalone blocks). Held/persisted state (configs, permissions, sessions, caches): model the Repository recipe \u2014 a Store + Registry (write) + Index (read), plus a Query for computed reads over the Store, owned by a Repository facade consumers depend on; a deliberately standalone Store is the sanctioned lightweight form (workflow-layer consumers + lint.allow on UNOWNED_STORE). Never hold state as fields inside an Orchestrator because a Store link was refused. Re-running it on an existing id RE-AUTHORS it: the fields above are replaced (an omitted array is CLEARED), while lint.allow, a Portal's auth, variant, patterns and externalLinks are carried forward \u2014 edit those with sdd_update_spec.`,
24848
24884
  inputSchema: componentInput
24849
24885
  },
24850
- ({ id, name, description, subsystem, componentType, owns, dependsOn, portalType, basePath, dispatch, durability, emits, subscribesTo, ext }) => {
24886
+ ({ id, name, description, subsystem, componentType, owns, dependsOn, portalType, basePath, dispatch, durability, dependencyClass, emits, subscribesTo, ext }) => {
24851
24887
  try {
24852
24888
  const { loadSubsystemSpec: loadSubsystemSpec2, loadComponentSpec: loadComponentSpec2 } = requireSpecs();
24853
24889
  const sub = loadSubsystemSpec2(subsystem);
@@ -24865,6 +24901,7 @@ NOTICE:
24865
24901
  ...basePath ? { basePath } : {},
24866
24902
  ...dispatch ? { dispatch } : {},
24867
24903
  ...durability ? { durability } : {},
24904
+ ...dependencyClass ? { dependencyClass } : {},
24868
24905
  ...emits ? { emits } : {},
24869
24906
  ...subscribesTo ? { subscribesTo } : {},
24870
24907
  ...ext ? { ext } : {},
@@ -24916,7 +24953,7 @@ NOTICE:
24916
24953
  code: import_zod11.z.string().describe("UPPER_SNAKE finding code, unique within the method; a pack's codes carry the pack prefix (<PACK>_<CODE>)"),
24917
24954
  severity: import_zod11.z.enum(["error", "warning"]).describe("Default severity, before project severity overrides and draft-context downgrades"),
24918
24955
  summary: import_zod11.z.string().describe("One line saying what the finding means")
24919
- })).optional().describe("The finding codes this method can report, each with its default severity and summary. Each declared code must appear as a string literal in the method's source file (UNREALIZED_FINDING). A code is declared once per method; sdd_update_spec upserts and deletes findings by code."),
24956
+ })).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."),
24920
24957
  ext: import_zod11.z.record(import_zod11.z.unknown()).optional().describe("Opaque pack/tool extension data for this method (namespaced keys) \u2014 preserved verbatim")
24921
24958
  };
24922
24959
  const interfaceMethodInputFields = Object.keys(interfaceMethodShape);
@@ -24932,7 +24969,7 @@ NOTICE:
24932
24969
  server,
24933
24970
  "sdd_define_interface",
24934
24971
  {
24935
- description: "Define an L3 Contract / Interface with method signatures for a component. Prefer supplying structured `params` per method \u2014 they are the authoritative source for type checking (the free-form signature string then becomes display-only and is never heuristically parsed). A method declares the finding codes it reports in `findings` ({code, severity, summary}); each code must appear as a string literal in the method's source file. Re-defining an existing id REPLACES the method list: a method left out of the input is REMOVED (and reported); spec-level lint/ext and each method's endpoint binding are carried forward.",
24972
+ description: "Define an L3 Contract / Interface with method signatures for a component. Prefer supplying structured `params` per method \u2014 they are the authoritative source for type checking (the free-form signature string then becomes display-only and is never heuristically parsed). A method declares the finding codes it reports in `findings` ({code, severity, summary}); each code must be anchored in the method's source file, as a string literal or a property-access name (UNREALIZED_FINDING). Re-defining an existing id REPLACES the method list: a method left out of the input is REMOVED (and reported); spec-level lint/ext and each method's endpoint binding are carried forward.",
24936
24973
  inputSchema: interfaceInput
24937
24974
  },
24938
24975
  ({ id, name, description, component, methods }) => {
@@ -27566,14 +27603,14 @@ var http = __toESM(require("http"));
27566
27603
  var https = __toESM(require("https"));
27567
27604
  init_defaults();
27568
27605
  function downloadFile(url, dest) {
27569
- return new Promise((resolve31, reject) => {
27606
+ return new Promise((resolve32, reject) => {
27570
27607
  const file = fs23.createWriteStream(dest);
27571
27608
  const get4 = url.startsWith("https://") ? https.get : http.get;
27572
27609
  get4(url, { headers: { "User-Agent": `wairon/${WAIRON_VERSION}` }, agent: false }, (res) => {
27573
27610
  if (res.statusCode === 301 || res.statusCode === 302) {
27574
27611
  file.close();
27575
27612
  res.destroy();
27576
- downloadFile(res.headers.location, dest).then(resolve31).catch(reject);
27613
+ downloadFile(res.headers.location, dest).then(resolve32).catch(reject);
27577
27614
  return;
27578
27615
  }
27579
27616
  if (res.statusCode !== 200) {
@@ -27585,7 +27622,7 @@ function downloadFile(url, dest) {
27585
27622
  res.pipe(file);
27586
27623
  file.on("finish", () => {
27587
27624
  res.destroy();
27588
- file.close(() => resolve31());
27625
+ file.close(() => resolve32());
27589
27626
  });
27590
27627
  file.on("error", (err) => {
27591
27628
  res.destroy();
@@ -27762,7 +27799,7 @@ function releaseChannelLabel(tag) {
27762
27799
  return version.slice(dash + 1).replace(/\.\d+$/, "") || "stable";
27763
27800
  }
27764
27801
  function fetchReleases(repo) {
27765
- return new Promise((resolve31, reject) => {
27802
+ return new Promise((resolve32, reject) => {
27766
27803
  const url = `https://api.github.com/repos/${repo}/releases?per_page=100`;
27767
27804
  const options = {
27768
27805
  headers: {
@@ -27782,7 +27819,7 @@ function fetchReleases(repo) {
27782
27819
  return;
27783
27820
  }
27784
27821
  try {
27785
- resolve31(JSON.parse(data));
27822
+ resolve32(JSON.parse(data));
27786
27823
  } catch {
27787
27824
  reject(new Error("Failed to parse GitHub API response"));
27788
27825
  }
@@ -27957,7 +27994,7 @@ async function filteredCheckbox(config) {
27957
27994
  32,
27958
27995
  Math.max(...items.map((i) => i.label.length))
27959
27996
  );
27960
- return new Promise((resolve31) => {
27997
+ return new Promise((resolve32) => {
27961
27998
  const checked = /* @__PURE__ */ new Set();
27962
27999
  let cursor = 0;
27963
28000
  let filterIdx = 0;
@@ -28024,7 +28061,7 @@ async function filteredCheckbox(config) {
28024
28061
  );
28025
28062
  teardown();
28026
28063
  const result = items.filter((_, idx) => checked.has(idx)).map((i) => i.value);
28027
- resolve31(result);
28064
+ resolve32(result);
28028
28065
  }
28029
28066
  function abort() {
28030
28067
  process.stdout.write("\n");
@@ -36181,7 +36218,7 @@ async function awaitApproval(cfg, credential, requestId, timeoutSeconds) {
36181
36218
  let current2 = req;
36182
36219
  while (current2.status === "pending" && Date.now() < deadline) {
36183
36220
  const remaining = deadline - Date.now();
36184
- await new Promise((resolve31) => setTimeout(resolve31, Math.min(AWAIT_POLL_INTERVAL_MS, remaining)));
36221
+ await new Promise((resolve32) => setTimeout(resolve32, Math.min(AWAIT_POLL_INTERVAL_MS, remaining)));
36185
36222
  expirePendingApprovals(cfg.dataDir, (/* @__PURE__ */ new Date()).toISOString());
36186
36223
  current2 = getApprovalRequestById(cfg.dataDir, requestId) ?? current2;
36187
36224
  }
@@ -41431,6 +41468,52 @@ function serveSharedDownload(cfg, token, kind, req, res) {
41431
41468
  res.end(result.content);
41432
41469
  }
41433
41470
 
41471
+ // src/server/backup-schedule.ts
41472
+ var TICK_MS = 6e4;
41473
+ var timer;
41474
+ function sweep(config) {
41475
+ try {
41476
+ runPeriodicGitSync(config);
41477
+ } catch (err) {
41478
+ console.error("[git-sync] project sweep failed: " + (err instanceof Error ? err.message : String(err)));
41479
+ }
41480
+ try {
41481
+ runPeriodicBackingSync(config);
41482
+ } catch (err) {
41483
+ console.error("[git-backing] backing sweep failed: " + (err instanceof Error ? err.message : String(err)));
41484
+ }
41485
+ }
41486
+ function start(config) {
41487
+ if (timer) clearInterval(timer);
41488
+ timer = setInterval(() => sweep(config), TICK_MS);
41489
+ timer.unref();
41490
+ }
41491
+ function stop() {
41492
+ if (timer) {
41493
+ clearInterval(timer);
41494
+ timer = void 0;
41495
+ }
41496
+ }
41497
+
41498
+ // src/server/instance-bootstrap.ts
41499
+ var DEV_UNIT_ID = "local";
41500
+ function bootstrapInstance(cfg) {
41501
+ ensureInstanceIdentity(cfg.dataDir);
41502
+ if (cfg.devMode && !getOrganizationUnit(cfg.dataDir, DEV_UNIT_ID)) {
41503
+ const system = { userId: "system", kind: "service", issuer: "local" };
41504
+ createUnit(cfg.dataDir, {
41505
+ id: DEV_UNIT_ID,
41506
+ name: "Local Development",
41507
+ kind: "team",
41508
+ slug: DEV_UNIT_ID,
41509
+ // a root unit's qualified id IS its slug
41510
+ status: "active",
41511
+ createdAt: "",
41512
+ createdBy: system
41513
+ });
41514
+ }
41515
+ }
41516
+
41434
41517
  // src/server/http.ts
41435
41518
  var MAX_BODY_BYTES = 8 * 1024 * 1024;
41436
41519
  var PayloadTooLargeError = class extends Error {
@@ -41855,23 +41938,6 @@ async function routeAdmin(cfg, req, res) {
41855
41938
  sendJson(res, 400, { error: err instanceof Error ? err.message : String(err) });
41856
41939
  }
41857
41940
  }
41858
- var DEV_UNIT_ID = "local";
41859
- function initHostInstance(cfg) {
41860
- ensureInstanceIdentity(cfg.dataDir);
41861
- if (cfg.devMode && !getOrganizationUnit(cfg.dataDir, DEV_UNIT_ID)) {
41862
- const system = { userId: "system", kind: "service", issuer: "local" };
41863
- createUnit(cfg.dataDir, {
41864
- id: DEV_UNIT_ID,
41865
- name: "Local Development",
41866
- kind: "team",
41867
- slug: DEV_UNIT_ID,
41868
- // a root unit's qualified id IS its slug
41869
- status: "active",
41870
- createdAt: "",
41871
- createdBy: system
41872
- });
41873
- }
41874
- }
41875
41941
  function warnIfDataDirUnmigrated(cfg) {
41876
41942
  try {
41877
41943
  const report2 = migratePermissionModel(cfg.dataDir, false);
@@ -41906,7 +41972,7 @@ function startHostServer(cfg) {
41906
41972
  );
41907
41973
  }
41908
41974
  }
41909
- initHostInstance(cfg);
41975
+ bootstrapInstance(cfg);
41910
41976
  warnIfDataDirUnmigrated(cfg);
41911
41977
  const dataServer = http2.createServer((req, res) => routeData(cfg, req, res));
41912
41978
  const adminServer = http2.createServer((req, res) => {
@@ -41917,23 +41983,10 @@ function startHostServer(cfg) {
41917
41983
  });
41918
41984
  dataServer.listen(cfg.port, cfg.host);
41919
41985
  adminServer.listen(cfg.adminPort, cfg.adminHost);
41920
- const GIT_SYNC_TICK_MS = 6e4;
41921
- const gitSyncTimer = setInterval(() => {
41922
- try {
41923
- runPeriodicGitSync(cfg);
41924
- } catch (err) {
41925
- console.error("[git-sync] project sweep failed: " + (err instanceof Error ? err.message : String(err)));
41926
- }
41927
- try {
41928
- runPeriodicBackingSync(cfg);
41929
- } catch (err) {
41930
- console.error("[git-backing] backing sweep failed: " + (err instanceof Error ? err.message : String(err)));
41931
- }
41932
- }, GIT_SYNC_TICK_MS);
41933
- gitSyncTimer.unref();
41986
+ start(cfg);
41934
41987
  return {
41935
41988
  close() {
41936
- clearInterval(gitSyncTimer);
41989
+ stop();
41937
41990
  getRealtimeHub().closeAll();
41938
41991
  dataServer.close();
41939
41992
  adminServer.close();
@@ -42494,11 +42547,11 @@ async function runServe(options = {}) {
42494
42547
  logger.info(` data dir: ${import_chalk17.default.gray(cfg.dataDir)}`);
42495
42548
  logger.blank();
42496
42549
  logger.info("Press Ctrl+C to stop.");
42497
- await new Promise((resolve31) => {
42550
+ await new Promise((resolve32) => {
42498
42551
  const shutdown = () => {
42499
42552
  logger.info("Shutting down\u2026");
42500
42553
  handle.close();
42501
- resolve31();
42554
+ resolve32();
42502
42555
  };
42503
42556
  process.on("SIGINT", shutdown);
42504
42557
  process.on("SIGTERM", shutdown);
@@ -42563,11 +42616,11 @@ async function runDev(options = {}) {
42563
42616
  logger.blank();
42564
42617
  logger.info("An agent edits specs; refresh the page to see the live graph. Press Ctrl+C to stop.");
42565
42618
  if (options.open) openBrowser(url);
42566
- await new Promise((resolve31) => {
42619
+ await new Promise((resolve32) => {
42567
42620
  const shutdown = () => {
42568
42621
  logger.info("Shutting down\u2026");
42569
42622
  handle.close();
42570
- resolve31();
42623
+ resolve32();
42571
42624
  };
42572
42625
  process.on("SIGINT", shutdown);
42573
42626
  process.on("SIGTERM", shutdown);