@wairon/cli 5.1.1-dev.56 → 5.1.1-dev.57

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.56";
68
+ WAIRON_VERSION = "5.1.1-dev.57";
69
69
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
70
70
  SUPPORTED_ALIASES = ["wai"];
71
71
  SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
@@ -1570,172 +1570,162 @@ var init_paths = __esm({
1570
1570
  }
1571
1571
  });
1572
1572
 
1573
- // src/core/detection.ts
1574
- function detectDomainCandidates(projectRoot2, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
1575
- const candidates = /* @__PURE__ */ new Map();
1576
- for (const c of detectGitSubmodules(projectRoot2)) {
1577
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
1578
- }
1579
- for (const c of detectNestedGitRepos(projectRoot2)) {
1580
- if (!candidates.has(c.path)) {
1581
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
1573
+ // src/utils/canonical-json.ts
1574
+ function canonicalize(value) {
1575
+ return JSON.stringify(sortKeys(value));
1576
+ }
1577
+ function compareOrdinal(a, b) {
1578
+ if (a < b) return -1;
1579
+ return a > b ? 1 : 0;
1580
+ }
1581
+ function sortKeys(v) {
1582
+ if (Array.isArray(v)) return v.map(sortKeys);
1583
+ if (v && typeof v === "object") {
1584
+ const src = v;
1585
+ const out = {};
1586
+ for (const k of Object.keys(src).sort()) {
1587
+ if (k === "createdAt" || k === "updatedAt") continue;
1588
+ out[k] = sortKeys(src[k]);
1582
1589
  }
1590
+ return out;
1583
1591
  }
1584
- const gitPaths = new Set(
1585
- Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
1586
- );
1587
- for (const c of detectPackageRoots(projectRoot2)) {
1588
- if (candidates.has(c.path)) continue;
1589
- const insideGit = Array.from(gitPaths).some(
1590
- (gp) => c.path === gp || c.path.startsWith(gp + "/")
1591
- );
1592
- if (insideGit) continue;
1593
- candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
1594
- }
1595
- const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
1596
- return deduplicateIds(sorted, alreadyTrackedIds);
1592
+ return v;
1597
1593
  }
1598
- function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
1599
- const idCount = /* @__PURE__ */ new Map();
1600
- for (const id of existingIds) {
1601
- idCount.set(id, (idCount.get(id) ?? 0) + 1);
1602
- }
1603
- for (const c of candidates) {
1604
- idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
1594
+ var init_canonical_json = __esm({
1595
+ "src/utils/canonical-json.ts"() {
1596
+ "use strict";
1605
1597
  }
1606
- return candidates.map((c) => {
1607
- if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
1608
- const parts = c.path.split("/");
1609
- const qualifiedId2 = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
1610
- return { ...c, suggestedId: qualifiedId2 };
1611
- });
1598
+ });
1599
+
1600
+ // src/core/statehash.ts
1601
+ function inIdentityOrder(specs) {
1602
+ return specs.map((spec) => ({ spec, content: canonicalize(spec) })).sort((a, b) => compareOrdinal(a.spec.id, b.spec.id) || compareOrdinal(a.content, b.content)).map((entry) => entry.spec);
1612
1603
  }
1613
- function parseGitmodules(filePath) {
1614
- const content = fs7.readFileSync(filePath, "utf-8");
1615
- const entries = [];
1616
- let current2 = {};
1617
- for (const line2 of content.split("\n")) {
1618
- const trimmed = line2.trim();
1619
- const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
1620
- if (headerMatch) {
1621
- if (current2.path) entries.push(current2);
1622
- current2 = { name: headerMatch[1] };
1623
- continue;
1624
- }
1625
- const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
1626
- if (keyVal) {
1627
- const [, key, value] = keyVal;
1628
- if (key === "path") current2.path = value.trim();
1629
- if (key === "url") current2.url = value.trim();
1630
- }
1604
+ function computeStateId() {
1605
+ const tree = {
1606
+ system: loadSystemSpec(),
1607
+ subsystems: inIdentityOrder(loadSubsystemSpecs()),
1608
+ components: inIdentityOrder(loadComponentSpecs()),
1609
+ interfaces: inIdentityOrder(loadInterfaceSpecs()),
1610
+ implementations: inIdentityOrder(loadImplementationSpecs()),
1611
+ types: inIdentityOrder(loadTypeSpecs())
1612
+ };
1613
+ const digest2 = crypto.createHash("sha256").update(canonicalize(tree)).digest("hex");
1614
+ return { algorithm: CONTENT_ALGORITHM, digest: digest2 };
1615
+ }
1616
+ function stateIdEquals(a, b) {
1617
+ return !!a && !!b && a.algorithm === b.algorithm && a.digest === b.digest;
1618
+ }
1619
+ var crypto, CONTENT_ALGORITHM;
1620
+ var init_statehash = __esm({
1621
+ "src/core/statehash.ts"() {
1622
+ "use strict";
1623
+ crypto = __toESM(require("crypto"));
1624
+ init_specs2();
1625
+ init_canonical_json();
1626
+ CONTENT_ALGORITHM = "sha256";
1631
1627
  }
1632
- if (current2.path) entries.push(current2);
1633
- return entries;
1628
+ });
1629
+
1630
+ // src/core/lockfile.ts
1631
+ function lockPath() {
1632
+ return aiDir("lock.json");
1634
1633
  }
1635
- function detectGitSubmodules(projectRoot2) {
1636
- const gitmodulesPath = path8.join(projectRoot2, ".gitmodules");
1637
- if (!fs7.existsSync(gitmodulesPath)) return [];
1638
- return parseGitmodules(gitmodulesPath).map((entry) => ({
1639
- suggestedId: pathToId(entry.path),
1640
- suggestedName: pathToName(entry.path),
1641
- path: normalizePath(entry.path),
1642
- type: "git-submodule",
1643
- alreadyTracked: false
1644
- }));
1634
+ function normalizeApprover(value) {
1635
+ if (value && typeof value === "object" && typeof value.id === "string") {
1636
+ const v = value;
1637
+ const source = v.source === "git" || v.source === "hosted" || v.source === "os" ? v.source : "legacy";
1638
+ return { id: v.id, ...v.name ? { name: v.name } : {}, source };
1639
+ }
1640
+ return { id: typeof value === "string" && value ? value : "unknown", source: "legacy" };
1645
1641
  }
1646
- function detectNestedGitRepos(projectRoot2) {
1647
- const results = [];
1648
- walkForGit(projectRoot2, projectRoot2, 0, results);
1649
- return results;
1642
+ function describeApprover(who) {
1643
+ const label = who.name ? `${who.name} (${who.id})` : who.id;
1644
+ return who.source === "hosted" ? `${label} [authenticated]` : label;
1650
1645
  }
1651
- function walkForGit(projectRoot2, currentDir, depth, results) {
1652
- if (depth > MAX_SCAN_DEPTH) return;
1653
- let entries;
1646
+ function readLockRecord() {
1654
1647
  try {
1655
- entries = fs7.readdirSync(currentDir, { withFileTypes: true });
1648
+ return normalizeRecord(JSON.parse(fs7.readFileSync(lockPath(), "utf8")));
1656
1649
  } catch {
1657
- return;
1658
- }
1659
- for (const entry of entries) {
1660
- if (!entry.isDirectory()) continue;
1661
- if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
1662
- const fullPath = path8.join(currentDir, entry.name);
1663
- const relPath = normalizePath(path8.relative(projectRoot2, fullPath));
1664
- if (relPath === "" || relPath === ".") continue;
1665
- const gitPath = path8.join(fullPath, ".git");
1666
- if (fs7.existsSync(gitPath)) {
1667
- results.push({
1668
- suggestedId: pathToId(relPath),
1669
- suggestedName: pathToName(relPath),
1670
- path: relPath,
1671
- type: "git-repo",
1672
- alreadyTracked: false
1673
- });
1674
- continue;
1675
- }
1676
- walkForGit(projectRoot2, fullPath, depth + 1, results);
1650
+ return null;
1677
1651
  }
1678
1652
  }
1679
- function detectPackageRoots(projectRoot2) {
1680
- const results = [];
1681
- walkForPackages(projectRoot2, projectRoot2, 0, results);
1682
- return results;
1683
- }
1684
- function walkForPackages(projectRoot2, currentDir, depth, results) {
1685
- if (depth > MAX_SCAN_DEPTH) return;
1686
- let entries;
1653
+ function readLockRecordAt(root) {
1687
1654
  try {
1688
- entries = fs7.readdirSync(currentDir, { withFileTypes: true });
1655
+ return normalizeRecord(JSON.parse(fs7.readFileSync(aiDirAt(root, "lock.json"), "utf8")));
1689
1656
  } catch {
1690
- return;
1691
- }
1692
- for (const entry of entries) {
1693
- if (!entry.isDirectory()) continue;
1694
- if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
1695
- const fullPath = path8.join(currentDir, entry.name);
1696
- const relPath = normalizePath(path8.relative(projectRoot2, fullPath));
1697
- if (relPath === "" || relPath === ".") continue;
1698
- const hasMarker = PACKAGE_MARKERS.some((m) => fs7.existsSync(path8.join(fullPath, m)));
1699
- if (hasMarker) {
1700
- results.push({
1701
- suggestedId: pathToId(relPath),
1702
- suggestedName: pathToName(relPath),
1703
- path: relPath,
1704
- type: "package-root",
1705
- alreadyTracked: false
1706
- });
1707
- }
1708
- walkForPackages(projectRoot2, fullPath, depth + 1, results);
1657
+ return null;
1709
1658
  }
1710
1659
  }
1711
- function pathToId(relPath) {
1712
- const basename15 = path8.basename(relPath);
1713
- return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
1660
+ function normalizeRecord(raw) {
1661
+ const record2 = raw;
1662
+ return { ...record2, lockedBy: normalizeApprover(record2.lockedBy) };
1714
1663
  }
1715
- function pathToName(relPath) {
1716
- const id = pathToId(relPath);
1717
- return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
1664
+ function writeLockRecord(record2) {
1665
+ const p = lockPath();
1666
+ fs7.mkdirSync(path8.dirname(p), { recursive: true });
1667
+ const tmp = `${p}.tmp`;
1668
+ fs7.writeFileSync(tmp, JSON.stringify(withSortedMaps(record2), null, 2) + "\n");
1669
+ fs7.renameSync(tmp, p);
1718
1670
  }
1719
- function normalizePath(p) {
1720
- return p.replace(/\\/g, "/");
1671
+ function withSortedMaps(record2) {
1672
+ const sorted = (m) => {
1673
+ if (!m) return void 0;
1674
+ const out = {};
1675
+ for (const k of Object.keys(m).sort()) out[k] = m[k];
1676
+ return out;
1677
+ };
1678
+ const specs = sorted(record2.specs);
1679
+ const children = sorted(record2.children);
1680
+ return {
1681
+ ...record2,
1682
+ ...specs ? { specs } : {},
1683
+ ...children ? { children } : {}
1684
+ };
1721
1685
  }
1722
- var fs7, path8, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
1723
- var init_detection = __esm({
1724
- "src/core/detection.ts"() {
1686
+ var fs7, path8;
1687
+ var init_lockfile = __esm({
1688
+ "src/core/lockfile.ts"() {
1725
1689
  "use strict";
1726
1690
  fs7 = __toESM(require("fs"));
1727
1691
  path8 = __toESM(require("path"));
1728
- init_defaults();
1729
- PACKAGE_MARKERS = [
1730
- "package.json",
1731
- "pyproject.toml",
1732
- "Cargo.toml",
1733
- "go.mod",
1734
- "build.gradle",
1735
- "build.gradle.kts",
1736
- "pom.xml"
1737
- ];
1738
- MAX_SCAN_DEPTH = 5;
1692
+ init_fs();
1693
+ }
1694
+ });
1695
+
1696
+ // src/core/spec-files.ts
1697
+ function readSpecFile(filePath) {
1698
+ return readYamlFile(filePath);
1699
+ }
1700
+ function writeSpecFile(filePath, document) {
1701
+ writeYamlFile(filePath, document);
1702
+ }
1703
+ function listSpecFiles(specsDir) {
1704
+ return listFilesRecursive(specsDir, SPEC_FILE_EXTENSION);
1705
+ }
1706
+ function removeSpecFile(filePath, specsRoot) {
1707
+ if (!fs8.existsSync(filePath)) return false;
1708
+ fs8.unlinkSync(filePath);
1709
+ pruneEmptyDirs(path9.dirname(filePath), path9.resolve(specsRoot));
1710
+ return true;
1711
+ }
1712
+ function pruneEmptyDirs(dir, specsRoot) {
1713
+ let at = dir;
1714
+ while (at !== specsRoot && at.startsWith(specsRoot)) {
1715
+ if (!fs8.existsSync(at) || fs8.readdirSync(at).length > 0) return;
1716
+ fs8.rmdirSync(at);
1717
+ at = path9.dirname(at);
1718
+ }
1719
+ }
1720
+ var fs8, path9, SPEC_FILE_EXTENSION;
1721
+ var init_spec_files = __esm({
1722
+ "src/core/spec-files.ts"() {
1723
+ "use strict";
1724
+ fs8 = __toESM(require("fs"));
1725
+ path9 = __toESM(require("path"));
1726
+ init_fs();
1727
+ init_yaml();
1728
+ SPEC_FILE_EXTENSION = ".yaml";
1739
1729
  }
1740
1730
  });
1741
1731
 
@@ -3295,7 +3285,7 @@ function hasFunctionBody(facts, symbol) {
3295
3285
  }
3296
3286
  function resolveImport(fromFile, specifier, knownPaths) {
3297
3287
  if (!specifier.startsWith(".")) return void 0;
3298
- const joined = pathKey(path9.posix.normalize(path9.posix.join(path9.posix.dirname(fromFile), specifier)));
3288
+ const joined = pathKey(path10.posix.normalize(path10.posix.join(path10.posix.dirname(fromFile), specifier)));
3299
3289
  const candidates = [
3300
3290
  joined,
3301
3291
  joined.replace(/\.js$/, ".ts"),
@@ -3311,11 +3301,11 @@ function resolveImport(fromFile, specifier, knownPaths) {
3311
3301
  }
3312
3302
  return void 0;
3313
3303
  }
3314
- var path9, NO_DECLARED_TYPES;
3304
+ var path10, NO_DECLARED_TYPES;
3315
3305
  var init_code_model = __esm({
3316
3306
  "src/models/code-model.ts"() {
3317
3307
  "use strict";
3318
- path9 = __toESM(require("path"));
3308
+ path10 = __toESM(require("path"));
3319
3309
  NO_DECLARED_TYPES = [];
3320
3310
  }
3321
3311
  });
@@ -3356,186 +3346,6 @@ var init_models = __esm({
3356
3346
  }
3357
3347
  });
3358
3348
 
3359
- // src/config/loader.ts
3360
- function loadTopologyConfig() {
3361
- assertProjectInitialized();
3362
- if (!pathExists(AI_PATHS.topologyConfig())) return createEmptyTopologyConfig();
3363
- const raw = readYamlFile(AI_PATHS.topologyConfig());
3364
- if (!raw) return createEmptyTopologyConfig();
3365
- return TopologyConfigSchema.parse(raw);
3366
- }
3367
- function saveTopologyConfig(config) {
3368
- writeYamlFile(AI_PATHS.topologyConfig(), config);
3369
- }
3370
- var init_loader = __esm({
3371
- "src/config/loader.ts"() {
3372
- "use strict";
3373
- init_fs();
3374
- init_yaml();
3375
- init_models();
3376
- init_paths();
3377
- }
3378
- });
3379
-
3380
- // src/utils/canonical-json.ts
3381
- function canonicalize(value) {
3382
- return JSON.stringify(sortKeys(value));
3383
- }
3384
- function compareOrdinal(a, b) {
3385
- if (a < b) return -1;
3386
- return a > b ? 1 : 0;
3387
- }
3388
- function sortKeys(v) {
3389
- if (Array.isArray(v)) return v.map(sortKeys);
3390
- if (v && typeof v === "object") {
3391
- const src = v;
3392
- const out = {};
3393
- for (const k of Object.keys(src).sort()) {
3394
- if (k === "createdAt" || k === "updatedAt") continue;
3395
- out[k] = sortKeys(src[k]);
3396
- }
3397
- return out;
3398
- }
3399
- return v;
3400
- }
3401
- var init_canonical_json = __esm({
3402
- "src/utils/canonical-json.ts"() {
3403
- "use strict";
3404
- }
3405
- });
3406
-
3407
- // src/core/statehash.ts
3408
- function inIdentityOrder(specs) {
3409
- return specs.map((spec) => ({ spec, content: canonicalize(spec) })).sort((a, b) => compareOrdinal(a.spec.id, b.spec.id) || compareOrdinal(a.content, b.content)).map((entry) => entry.spec);
3410
- }
3411
- function computeStateId() {
3412
- const tree = {
3413
- system: loadSystemSpec(),
3414
- subsystems: inIdentityOrder(loadSubsystemSpecs()),
3415
- components: inIdentityOrder(loadComponentSpecs()),
3416
- interfaces: inIdentityOrder(loadInterfaceSpecs()),
3417
- implementations: inIdentityOrder(loadImplementationSpecs()),
3418
- types: inIdentityOrder(loadTypeSpecs())
3419
- };
3420
- const digest2 = crypto.createHash("sha256").update(canonicalize(tree)).digest("hex");
3421
- return { algorithm: CONTENT_ALGORITHM, digest: digest2 };
3422
- }
3423
- function stateIdEquals(a, b) {
3424
- return !!a && !!b && a.algorithm === b.algorithm && a.digest === b.digest;
3425
- }
3426
- var crypto, CONTENT_ALGORITHM;
3427
- var init_statehash = __esm({
3428
- "src/core/statehash.ts"() {
3429
- "use strict";
3430
- crypto = __toESM(require("crypto"));
3431
- init_specs2();
3432
- init_canonical_json();
3433
- CONTENT_ALGORITHM = "sha256";
3434
- }
3435
- });
3436
-
3437
- // src/core/lockfile.ts
3438
- function lockPath() {
3439
- return aiDir("lock.json");
3440
- }
3441
- function normalizeApprover(value) {
3442
- if (value && typeof value === "object" && typeof value.id === "string") {
3443
- const v = value;
3444
- const source = v.source === "git" || v.source === "hosted" || v.source === "os" ? v.source : "legacy";
3445
- return { id: v.id, ...v.name ? { name: v.name } : {}, source };
3446
- }
3447
- return { id: typeof value === "string" && value ? value : "unknown", source: "legacy" };
3448
- }
3449
- function describeApprover(who) {
3450
- const label = who.name ? `${who.name} (${who.id})` : who.id;
3451
- return who.source === "hosted" ? `${label} [authenticated]` : label;
3452
- }
3453
- function readLockRecord() {
3454
- try {
3455
- return normalizeRecord(JSON.parse(fs8.readFileSync(lockPath(), "utf8")));
3456
- } catch {
3457
- return null;
3458
- }
3459
- }
3460
- function readLockRecordAt(root) {
3461
- try {
3462
- return normalizeRecord(JSON.parse(fs8.readFileSync(aiDirAt(root, "lock.json"), "utf8")));
3463
- } catch {
3464
- return null;
3465
- }
3466
- }
3467
- function normalizeRecord(raw) {
3468
- const record2 = raw;
3469
- return { ...record2, lockedBy: normalizeApprover(record2.lockedBy) };
3470
- }
3471
- function writeLockRecord(record2) {
3472
- const p = lockPath();
3473
- fs8.mkdirSync(path10.dirname(p), { recursive: true });
3474
- const tmp = `${p}.tmp`;
3475
- fs8.writeFileSync(tmp, JSON.stringify(withSortedMaps(record2), null, 2) + "\n");
3476
- fs8.renameSync(tmp, p);
3477
- }
3478
- function withSortedMaps(record2) {
3479
- const sorted = (m) => {
3480
- if (!m) return void 0;
3481
- const out = {};
3482
- for (const k of Object.keys(m).sort()) out[k] = m[k];
3483
- return out;
3484
- };
3485
- const specs = sorted(record2.specs);
3486
- const children = sorted(record2.children);
3487
- return {
3488
- ...record2,
3489
- ...specs ? { specs } : {},
3490
- ...children ? { children } : {}
3491
- };
3492
- }
3493
- var fs8, path10;
3494
- var init_lockfile = __esm({
3495
- "src/core/lockfile.ts"() {
3496
- "use strict";
3497
- fs8 = __toESM(require("fs"));
3498
- path10 = __toESM(require("path"));
3499
- init_fs();
3500
- }
3501
- });
3502
-
3503
- // src/core/spec-files.ts
3504
- function readSpecFile(filePath) {
3505
- return readYamlFile(filePath);
3506
- }
3507
- function writeSpecFile(filePath, document) {
3508
- writeYamlFile(filePath, document);
3509
- }
3510
- function listSpecFiles(specsDir) {
3511
- return listFilesRecursive(specsDir, SPEC_FILE_EXTENSION);
3512
- }
3513
- function removeSpecFile(filePath, specsRoot) {
3514
- if (!fs9.existsSync(filePath)) return false;
3515
- fs9.unlinkSync(filePath);
3516
- pruneEmptyDirs(path11.dirname(filePath), path11.resolve(specsRoot));
3517
- return true;
3518
- }
3519
- function pruneEmptyDirs(dir, specsRoot) {
3520
- let at = dir;
3521
- while (at !== specsRoot && at.startsWith(specsRoot)) {
3522
- if (!fs9.existsSync(at) || fs9.readdirSync(at).length > 0) return;
3523
- fs9.rmdirSync(at);
3524
- at = path11.dirname(at);
3525
- }
3526
- }
3527
- var fs9, path11, SPEC_FILE_EXTENSION;
3528
- var init_spec_files = __esm({
3529
- "src/core/spec-files.ts"() {
3530
- "use strict";
3531
- fs9 = __toESM(require("fs"));
3532
- path11 = __toESM(require("path"));
3533
- init_fs();
3534
- init_yaml();
3535
- SPEC_FILE_EXTENSION = ".yaml";
3536
- }
3537
- });
3538
-
3539
3349
  // src/core/narrative-labels.ts
3540
3350
  function resolveNarrativeLabels(methodName, steps) {
3541
3351
  const errors = [];
@@ -4274,14 +4084,14 @@ function embedJson(value) {
4274
4084
  }
4275
4085
  function loadCytoscapeLib() {
4276
4086
  const candidates = [
4277
- path12.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
4087
+ path11.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
4278
4088
  // src/core & dist/cli
4279
- path12.resolve(__dirname, "templates", "canvas", "cytoscape.min.js")
4089
+ path11.resolve(__dirname, "templates", "canvas", "cytoscape.min.js")
4280
4090
  // dist (library entry)
4281
4091
  ];
4282
4092
  for (const p of candidates) {
4283
- if (fs10.existsSync(p)) {
4284
- return fs10.readFileSync(p, "utf-8").replace(/<\/script/gi, "<\\/script");
4093
+ if (fs9.existsSync(p)) {
4094
+ return fs9.readFileSync(p, "utf-8").replace(/<\/script/gi, "<\\/script");
4285
4095
  }
4286
4096
  }
4287
4097
  throw new Error("Vendored cytoscape bundle not found (templates/canvas/cytoscape.min.js) \u2014 the wairon installation is incomplete.");
@@ -4293,12 +4103,12 @@ function renderCanvasHtml(model) {
4293
4103
  function escapeHtml(s) {
4294
4104
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4295
4105
  }
4296
- var fs10, path12, CANVAS_TEMPLATE;
4106
+ var fs9, path11, CANVAS_TEMPLATE;
4297
4107
  var init_canvas = __esm({
4298
4108
  "src/core/canvas.ts"() {
4299
4109
  "use strict";
4300
- fs10 = __toESM(require("fs"));
4301
- path12 = __toESM(require("path"));
4110
+ fs9 = __toESM(require("fs"));
4111
+ path11 = __toESM(require("path"));
4302
4112
  init_specs2();
4303
4113
  init_models();
4304
4114
  init_diagram_export();
@@ -8493,7 +8303,7 @@ function packStoreDir() {
8493
8303
  function packFiles(dir, prefix = "") {
8494
8304
  let entries;
8495
8305
  try {
8496
- entries = fs11.readdirSync(dir, { withFileTypes: true });
8306
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
8497
8307
  } catch {
8498
8308
  return [];
8499
8309
  }
@@ -8501,25 +8311,25 @@ function packFiles(dir, prefix = "") {
8501
8311
  for (const e of entries) {
8502
8312
  if (DIGEST_EXCLUDED.has(e.name)) continue;
8503
8313
  const rel2 = prefix ? `${prefix}/${e.name}` : e.name;
8504
- if (e.isDirectory()) out.push(...packFiles(path13.join(dir, e.name), rel2));
8314
+ if (e.isDirectory()) out.push(...packFiles(path12.join(dir, e.name), rel2));
8505
8315
  else if (e.isFile()) out.push(rel2);
8506
8316
  }
8507
8317
  return out.sort();
8508
8318
  }
8509
8319
  function computePackDigest(packDir) {
8510
8320
  const hash = crypto2.createHash("sha256");
8511
- const abs = path13.resolve(packDir);
8321
+ const abs = path12.resolve(packDir);
8512
8322
  let isFile = false;
8513
8323
  try {
8514
- isFile = fs11.statSync(abs).isFile();
8324
+ isFile = fs10.statSync(abs).isFile();
8515
8325
  } catch {
8516
8326
  }
8517
- const entries = isFile ? [[path13.basename(abs), abs]] : packFiles(abs).map((rel2) => [rel2, path13.join(abs, rel2)]);
8327
+ const entries = isFile ? [[path12.basename(abs), abs]] : packFiles(abs).map((rel2) => [rel2, path12.join(abs, rel2)]);
8518
8328
  for (const [rel2, full] of entries) {
8519
8329
  hash.update(rel2);
8520
8330
  hash.update("\0");
8521
8331
  try {
8522
- hash.update(fs11.readFileSync(full));
8332
+ hash.update(fs10.readFileSync(full));
8523
8333
  } catch {
8524
8334
  }
8525
8335
  hash.update("\0");
@@ -8528,7 +8338,7 @@ function computePackDigest(packDir) {
8528
8338
  }
8529
8339
  function readInstallRecord(packPath) {
8530
8340
  try {
8531
- const raw = readYamlFile(path13.join(packPath, INSTALL_RECORD));
8341
+ const raw = readYamlFile(path12.join(packPath, INSTALL_RECORD));
8532
8342
  return raw && typeof raw === "object" ? raw : {};
8533
8343
  } catch {
8534
8344
  return {};
@@ -8558,14 +8368,14 @@ function installedFrom(location, name, version) {
8558
8368
  function versionedEntries(nameDir, fallbackName) {
8559
8369
  let versions;
8560
8370
  try {
8561
- versions = fs11.readdirSync(nameDir, { withFileTypes: true });
8371
+ versions = fs10.readdirSync(nameDir, { withFileTypes: true });
8562
8372
  } catch {
8563
8373
  return [];
8564
8374
  }
8565
8375
  const out = [];
8566
8376
  for (const v of versions) {
8567
8377
  if (!v.isDirectory()) continue;
8568
- const versionDir = path13.join(nameDir, v.name);
8378
+ const versionDir = path12.join(nameDir, v.name);
8569
8379
  const entryFile = packDirEntry(versionDir);
8570
8380
  if (!entryFile) continue;
8571
8381
  out.push(installedFrom(versionDir, declaredName(entryFile) ?? fallbackName, v.name));
@@ -8573,7 +8383,7 @@ function versionedEntries(nameDir, fallbackName) {
8573
8383
  return out;
8574
8384
  }
8575
8385
  function storeEntryPacks(store, entry) {
8576
- const full = path13.join(store, entry.name);
8386
+ const full = path12.join(store, entry.name);
8577
8387
  if (entry.isFile()) {
8578
8388
  if (!PACK_FILE_RE.test(entry.name)) return [];
8579
8389
  const name = declaredName(full) ?? entry.name.replace(PACK_FILE_RE, "");
@@ -8588,7 +8398,7 @@ function listInstalledPacks() {
8588
8398
  const store = packStoreDir();
8589
8399
  let entries;
8590
8400
  try {
8591
- entries = fs11.readdirSync(store, { withFileTypes: true });
8401
+ entries = fs10.readdirSync(store, { withFileTypes: true });
8592
8402
  } catch {
8593
8403
  return [];
8594
8404
  }
@@ -8605,17 +8415,17 @@ function resolveInstalledPack(name, version) {
8605
8415
  return candidates[0];
8606
8416
  }
8607
8417
  function installPackFromDirectory(sourceDir, origin) {
8608
- const abs = path13.resolve(sourceDir);
8418
+ const abs = path12.resolve(sourceDir);
8609
8419
  const entryFile = packDirEntry(abs);
8610
8420
  if (!entryFile) {
8611
8421
  throw new Error(`"${sourceDir}" is not a pack directory (no pack.yaml | pack.cjs | index.cjs | \u2026).`);
8612
8422
  }
8613
- const manifest = readManifest(entryFile, path13.dirname(entryFile));
8423
+ const manifest = readManifest(entryFile, path12.dirname(entryFile));
8614
8424
  const version = manifest.version && manifest.version.length > 0 ? manifest.version : UNVERSIONED;
8615
- const dest = path13.join(packStoreDir(), manifest.name, version);
8616
- fs11.rmSync(dest, { recursive: true, force: true });
8617
- fs11.mkdirSync(path13.dirname(dest), { recursive: true });
8618
- fs11.cpSync(abs, dest, { recursive: true });
8425
+ const dest = path12.join(packStoreDir(), manifest.name, version);
8426
+ fs10.rmSync(dest, { recursive: true, force: true });
8427
+ fs10.mkdirSync(path12.dirname(dest), { recursive: true });
8428
+ fs10.cpSync(abs, dest, { recursive: true });
8619
8429
  const digest2 = computePackDigest(dest);
8620
8430
  const record2 = {
8621
8431
  origin,
@@ -8623,7 +8433,7 @@ function installPackFromDirectory(sourceDir, origin) {
8623
8433
  waironVersion: WAIRON_VERSION,
8624
8434
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
8625
8435
  };
8626
- writeYamlFile(path13.join(dest, INSTALL_RECORD), record2);
8436
+ writeYamlFile(path12.join(dest, INSTALL_RECORD), record2);
8627
8437
  return {
8628
8438
  name: manifest.name,
8629
8439
  version,
@@ -8638,23 +8448,23 @@ function uninstallPack(name, version) {
8638
8448
  const targets = listInstalledPacks().filter((p) => p.name === name && (!version || p.version === version));
8639
8449
  if (targets.length === 0) return false;
8640
8450
  for (const target of targets) {
8641
- fs11.rmSync(target.path, { recursive: true, force: true });
8642
- const parent = path13.dirname(target.path);
8643
- if (path13.resolve(parent) === path13.resolve(packStoreDir())) continue;
8451
+ fs10.rmSync(target.path, { recursive: true, force: true });
8452
+ const parent = path12.dirname(target.path);
8453
+ if (path12.resolve(parent) === path12.resolve(packStoreDir())) continue;
8644
8454
  try {
8645
- if (fs11.readdirSync(parent).length === 0) fs11.rmdirSync(parent);
8455
+ if (fs10.readdirSync(parent).length === 0) fs10.rmdirSync(parent);
8646
8456
  } catch {
8647
8457
  }
8648
8458
  }
8649
8459
  return true;
8650
8460
  }
8651
- var crypto2, fs11, path13, UNVERSIONED, INSTALL_RECORD, DIGEST_EXCLUDED, PACK_FILE_RE;
8461
+ var crypto2, fs10, path12, UNVERSIONED, INSTALL_RECORD, DIGEST_EXCLUDED, PACK_FILE_RE;
8652
8462
  var init_packstore = __esm({
8653
8463
  "src/core/packstore.ts"() {
8654
8464
  "use strict";
8655
8465
  crypto2 = __toESM(require("crypto"));
8656
- fs11 = __toESM(require("fs"));
8657
- path13 = __toESM(require("path"));
8466
+ fs10 = __toESM(require("fs"));
8467
+ path12 = __toESM(require("path"));
8658
8468
  init_yaml();
8659
8469
  init_defaults();
8660
8470
  init_version();
@@ -8681,26 +8491,26 @@ function emptyExtensions() {
8681
8491
  return { packNames: [], packs: [], rules: [], profiles: {}, languages: {}, skills: [], patterns: [], guarantees: [], assertions: [], instructions: [], errors: [], selectionFailures: [] };
8682
8492
  }
8683
8493
  function globalPacksDir() {
8684
- return process.env.WAIRON_PACKS_DIR ?? path14.join(os4.homedir(), ".wairon", "packs");
8494
+ return process.env.WAIRON_PACKS_DIR ?? path13.join(os4.homedir(), ".wairon", "packs");
8685
8495
  }
8686
8496
  function packDirEntry(dir) {
8687
8497
  for (const name of PACK_DIR_ENTRIES) {
8688
- const p = path14.join(dir, name);
8689
- if (fs12.existsSync(p)) return p;
8498
+ const p = path13.join(dir, name);
8499
+ if (fs11.existsSync(p)) return p;
8690
8500
  }
8691
8501
  return null;
8692
8502
  }
8693
8503
  function latestVersionDir(nameDir) {
8694
8504
  let versions;
8695
8505
  try {
8696
- versions = fs12.readdirSync(nameDir, { withFileTypes: true });
8506
+ versions = fs11.readdirSync(nameDir, { withFileTypes: true });
8697
8507
  } catch {
8698
8508
  return null;
8699
8509
  }
8700
8510
  let best = null;
8701
8511
  for (const v of versions) {
8702
8512
  if (!v.isDirectory()) continue;
8703
- const dir = path14.join(nameDir, v.name);
8513
+ const dir = path13.join(nameDir, v.name);
8704
8514
  if (!packDirEntry(dir)) continue;
8705
8515
  if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
8706
8516
  }
@@ -8709,13 +8519,13 @@ function latestVersionDir(nameDir) {
8709
8519
  function discoverPacks(dir) {
8710
8520
  let entries;
8711
8521
  try {
8712
- entries = fs12.readdirSync(dir, { withFileTypes: true });
8522
+ entries = fs11.readdirSync(dir, { withFileTypes: true });
8713
8523
  } catch {
8714
8524
  return [];
8715
8525
  }
8716
8526
  const refs = [];
8717
8527
  for (const e of entries.sort((a, b) => compareOrdinal(a.name, b.name))) {
8718
- const full = path14.join(dir, e.name);
8528
+ const full = path13.join(dir, e.name);
8719
8529
  if (e.isDirectory()) {
8720
8530
  if (packDirEntry(full)) refs.push(full);
8721
8531
  else {
@@ -8745,17 +8555,17 @@ function mergePack(out, pack, ref, scope, packDir) {
8745
8555
  foreignBuiltins: [.../* @__PURE__ */ new Set([...existing.foreignBuiltins, ...def.foreignBuiltins])]
8746
8556
  } : def;
8747
8557
  }
8748
- for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath: path14.resolve(packDir, s.source) });
8558
+ for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath: path13.resolve(packDir, s.source) });
8749
8559
  for (const p of pack.patterns) out.patterns.push({ ...p, pack: pack.name });
8750
8560
  out.guarantees = [.../* @__PURE__ */ new Set([...out.guarantees, ...pack.guarantees])];
8751
8561
  for (const a of pack.assertions) out.assertions.push({ ...a, pack: pack.name, fullCode: assertionFullCode(pack.name, a.code) });
8752
8562
  for (const b of pack.instructions) out.instructions.push({ ...b, pack: pack.name });
8753
8563
  }
8754
8564
  function resolvePackRef(ref, projectRoot2) {
8755
- const pathLike = ref.startsWith(".") || path14.isAbsolute(ref) || isYamlPath(ref);
8565
+ const pathLike = ref.startsWith(".") || path13.isAbsolute(ref) || isYamlPath(ref);
8756
8566
  if (!pathLike) return ref;
8757
- const resolved = path14.resolve(projectRoot2, ref);
8758
- if (fs12.existsSync(resolved) && fs12.statSync(resolved).isDirectory()) {
8567
+ const resolved = path13.resolve(projectRoot2, ref);
8568
+ if (fs11.existsSync(resolved) && fs11.statSync(resolved).isDirectory()) {
8759
8569
  const entry = packDirEntry(resolved);
8760
8570
  if (!entry) throw new Error(`directory pack has no entry file (${PACK_DIR_ENTRIES.join(" | ")})`);
8761
8571
  return entry;
@@ -8768,7 +8578,7 @@ function readManifest(target, projectRoot2) {
8768
8578
  if (raw == null) throw new Error("file not found or empty");
8769
8579
  return { ...DeclarativePackSchema.parse(raw), rules: [] };
8770
8580
  }
8771
- const req = (0, import_module.createRequire)(path14.join(projectRoot2, "package.json"));
8581
+ const req = (0, import_module.createRequire)(path13.join(projectRoot2, "package.json"));
8772
8582
  const modRaw = req(target);
8773
8583
  const mod = modRaw?.default ?? modRaw;
8774
8584
  const parsed = DeclarativePackSchema.parse({
@@ -8796,7 +8606,7 @@ function loadExtensionPacks(refs, projectRoot2) {
8796
8606
  try {
8797
8607
  const target = resolvePackRef(ref, projectRoot2);
8798
8608
  const manifest = readManifest(target, projectRoot2);
8799
- mergePack(out, manifest, ref, scope, path14.dirname(target));
8609
+ mergePack(out, manifest, ref, scope, path13.dirname(target));
8800
8610
  for (const r of manifest.rules) out.rules.push(r);
8801
8611
  } catch (e) {
8802
8612
  out.errors.push(`Extension pack "${ref}" failed to load: ${e instanceof Error ? e.message : String(e)}`);
@@ -8839,7 +8649,7 @@ function defaultPackSelections() {
8839
8649
  const entry = packDirEntry(pack.path) ?? pack.path;
8840
8650
  let manifest;
8841
8651
  try {
8842
- manifest = readManifest(entry, path14.dirname(entry));
8652
+ manifest = readManifest(entry, path13.dirname(entry));
8843
8653
  } catch {
8844
8654
  continue;
8845
8655
  }
@@ -8878,7 +8688,7 @@ function diagnoseProjectPacks() {
8878
8688
  const globalsApplied = [];
8879
8689
  if (globalsOn) {
8880
8690
  for (const ref of discoverPacks(globalPacksDir())) {
8881
- const match = installed.find((p) => path14.resolve(p.path) === path14.resolve(ref));
8691
+ const match = installed.find((p) => path13.resolve(p.path) === path13.resolve(ref));
8882
8692
  if (match) globalsApplied.push({ name: match.name, version: match.version });
8883
8693
  }
8884
8694
  }
@@ -8956,7 +8766,7 @@ function verifyIntegrity(selection, packDir, where) {
8956
8766
  };
8957
8767
  }
8958
8768
  function detectBundleStoreDrift(selection, bundleDir) {
8959
- const bundledVersion = path14.basename(bundleDir);
8769
+ const bundledVersion = path13.basename(bundleDir);
8960
8770
  const installed = resolveInstalledPack(selection.name, bundledVersion);
8961
8771
  if (!installed) return void 0;
8962
8772
  const bundleDigest = computePackDigest(bundleDir);
@@ -8970,34 +8780,34 @@ function detectBundleStoreDrift(selection, bundleDir) {
8970
8780
  };
8971
8781
  }
8972
8782
  function findBundledPack(projectRoot2, selection) {
8973
- const base = path14.join(projectRoot2, ".wai", "packs", selection.name);
8783
+ const base = path13.join(projectRoot2, ".wai", "packs", selection.name);
8974
8784
  if (selection.version) {
8975
- const pinned = path14.join(base, selection.version);
8785
+ const pinned = path13.join(base, selection.version);
8976
8786
  return packDirEntry(pinned) ? pinned : null;
8977
8787
  }
8978
8788
  if (packDirEntry(base)) return base;
8979
8789
  let versions;
8980
8790
  try {
8981
- versions = fs12.readdirSync(base, { withFileTypes: true });
8791
+ versions = fs11.readdirSync(base, { withFileTypes: true });
8982
8792
  } catch {
8983
8793
  return null;
8984
8794
  }
8985
8795
  let best = null;
8986
8796
  for (const v of versions) {
8987
8797
  if (!v.isDirectory()) continue;
8988
- const dir = path14.join(base, v.name);
8798
+ const dir = path13.join(base, v.name);
8989
8799
  if (!packDirEntry(dir)) continue;
8990
8800
  if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
8991
8801
  }
8992
8802
  return best?.dir ?? null;
8993
8803
  }
8994
- var fs12, os4, path14, import_module, import_zod9, ProfileDefSchema, LanguagePackDefSchema, PackSkillSchema, PackInstructionBlockSchema, PackInstructionsSchema, PatternDefSchema, AssertionSelectorSchema, assertionBase, PackAssertionSchema, DeclarativePackSchema, EXTENDABLE_BUILTIN_SKILLS, GLOBAL_PACKS_DEFAULT, PACK_DIR_ENTRIES, isYamlPath;
8804
+ var fs11, os4, path13, import_module, import_zod9, ProfileDefSchema, LanguagePackDefSchema, PackSkillSchema, PackInstructionBlockSchema, PackInstructionsSchema, PatternDefSchema, AssertionSelectorSchema, assertionBase, PackAssertionSchema, DeclarativePackSchema, EXTENDABLE_BUILTIN_SKILLS, GLOBAL_PACKS_DEFAULT, PACK_DIR_ENTRIES, isYamlPath;
8995
8805
  var init_extensions = __esm({
8996
8806
  "src/core/extensions.ts"() {
8997
8807
  "use strict";
8998
- fs12 = __toESM(require("fs"));
8808
+ fs11 = __toESM(require("fs"));
8999
8809
  os4 = __toESM(require("os"));
9000
- path14 = __toESM(require("path"));
8810
+ path13 = __toESM(require("path"));
9001
8811
  import_module = require("module");
9002
8812
  import_zod9 = require("zod");
9003
8813
  init_yaml();
@@ -15993,7 +15803,7 @@ function resolveTypeScript(projectRoot2) {
15993
15803
  return cached.ts;
15994
15804
  }
15995
15805
  let ts = null;
15996
- const bases = [path15.join(projectRoot2, "package.json"), __filename];
15806
+ const bases = [path14.join(projectRoot2, "package.json"), __filename];
15997
15807
  for (const base of bases) {
15998
15808
  try {
15999
15809
  const req = (0, import_module2.createRequire)(base);
@@ -16208,7 +16018,7 @@ function walkExact(ts, sourceText, fileName) {
16208
16018
  }
16209
16019
  function resolveRelativeModule(fromFile, specifier) {
16210
16020
  if (!specifier.startsWith(".")) return null;
16211
- const base = path15.resolve(path15.dirname(fromFile), specifier);
16021
+ const base = path14.resolve(path14.dirname(fromFile), specifier);
16212
16022
  const candidates = [
16213
16023
  base,
16214
16024
  base.replace(/\.js$/, ".ts"),
@@ -16216,12 +16026,12 @@ function resolveRelativeModule(fromFile, specifier) {
16216
16026
  `${base}.ts`,
16217
16027
  `${base}.tsx`,
16218
16028
  `${base}.js`,
16219
- path15.join(base, "index.ts"),
16220
- path15.join(base, "index.js")
16029
+ path14.join(base, "index.ts"),
16030
+ path14.join(base, "index.js")
16221
16031
  ];
16222
16032
  for (const c of candidates) {
16223
16033
  try {
16224
- if (fs13.statSync(c).isFile()) return c;
16034
+ if (fs12.statSync(c).isFile()) return c;
16225
16035
  } catch {
16226
16036
  }
16227
16037
  }
@@ -16229,11 +16039,11 @@ function resolveRelativeModule(fromFile, specifier) {
16229
16039
  }
16230
16040
  function reexportTarget(ts, filePath, specifier, projectRoot2, visited, exactCache) {
16231
16041
  const target = resolveRelativeModule(filePath, specifier);
16232
- if (!target || path15.relative(projectRoot2, target).startsWith("..")) return null;
16042
+ if (!target || path14.relative(projectRoot2, target).startsWith("..")) return null;
16233
16043
  let targetFacts = exactCache.get(target);
16234
16044
  if (targetFacts === void 0) {
16235
16045
  try {
16236
- targetFacts = walkExact(ts, fs13.readFileSync(target, "utf8"), target);
16046
+ targetFacts = walkExact(ts, fs12.readFileSync(target, "utf8"), target);
16237
16047
  } catch {
16238
16048
  targetFacts = null;
16239
16049
  }
@@ -16251,7 +16061,7 @@ function carryBody(facts, target, targetPath, local, exported, projectRoot2) {
16251
16061
  if (score !== void 0) facts.complexity.set(exported, Math.max(facts.complexity.get(exported) ?? 0, score));
16252
16062
  const targetCalls = target.calls.get(local);
16253
16063
  if (!targetCalls) return;
16254
- const carriedFrom = pathKey(path15.relative(projectRoot2, targetPath));
16064
+ const carriedFrom = pathKey(path14.relative(projectRoot2, targetPath));
16255
16065
  const sites = facts.calls.get(exported) ?? /* @__PURE__ */ new Map();
16256
16066
  for (const [key, site] of targetCalls) sites.set(carriedFrom + "|" + key, { ...site, from: site.from ?? carriedFrom });
16257
16067
  facts.calls.set(exported, sites);
@@ -16281,24 +16091,24 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
16281
16091
  const excluded = exclude.map(pathKey);
16282
16092
  const isExcluded = (key) => excluded.some((e) => key === e || key.startsWith(`${e}/`));
16283
16093
  const record2 = (absolute) => {
16284
- const key = pathKey(path15.relative(projectRoot2, absolute));
16094
+ const key = pathKey(path14.relative(projectRoot2, absolute));
16285
16095
  if (seen.has(key) || isExcluded(key)) return;
16286
- if (!EXTENSION_LANGUAGE[path15.extname(key).toLowerCase()]) return;
16096
+ if (!EXTENSION_LANGUAGE[path14.extname(key).toLowerCase()]) return;
16287
16097
  seen.add(key);
16288
16098
  found.push(key);
16289
16099
  };
16290
16100
  const descend = (dir) => {
16291
16101
  let entries;
16292
16102
  try {
16293
- entries = fs13.readdirSync(dir, { withFileTypes: true });
16103
+ entries = fs12.readdirSync(dir, { withFileTypes: true });
16294
16104
  } catch {
16295
16105
  return;
16296
16106
  }
16297
16107
  for (const entry of entries.slice().sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
16298
- const child = path15.join(dir, entry.name);
16108
+ const child = path14.join(dir, entry.name);
16299
16109
  if (entry.isDirectory()) {
16300
16110
  if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
16301
- if (isExcluded(pathKey(path15.relative(projectRoot2, child)))) continue;
16111
+ if (isExcluded(pathKey(path14.relative(projectRoot2, child)))) continue;
16302
16112
  descend(child);
16303
16113
  } else if (entry.isFile()) {
16304
16114
  record2(child);
@@ -16307,13 +16117,13 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
16307
16117
  };
16308
16118
  for (const root of roots) {
16309
16119
  const key = pathKey(root);
16310
- if (path15.isAbsolute(key) || path15.normalize(key).split(path15.sep)[0] === "..") continue;
16311
- const absolute = path15.resolve(projectRoot2, key);
16312
- if (path15.relative(projectRoot2, absolute).startsWith("..")) continue;
16120
+ if (path14.isAbsolute(key) || path14.normalize(key).split(path14.sep)[0] === "..") continue;
16121
+ const absolute = path14.resolve(projectRoot2, key);
16122
+ if (path14.relative(projectRoot2, absolute).startsWith("..")) continue;
16313
16123
  if (isExcluded(key)) continue;
16314
16124
  let stat;
16315
16125
  try {
16316
- stat = fs13.statSync(absolute);
16126
+ stat = fs12.statSync(absolute);
16317
16127
  } catch {
16318
16128
  continue;
16319
16129
  }
@@ -16339,23 +16149,23 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
16339
16149
  if (seen.has(sourcePath)) continue;
16340
16150
  seen.add(sourcePath);
16341
16151
  const empty = { declaredNames: [], anchoredNames: [], exportedNames: [], imports: [], reexports: [] };
16342
- if (path15.isAbsolute(sourcePath) || path15.normalize(sourcePath).split(path15.sep)[0] === "..") {
16152
+ if (path14.isAbsolute(sourcePath) || path14.normalize(sourcePath).split(path14.sep)[0] === "..") {
16343
16153
  files.push({ path: sourcePath, status: "escaped", ...empty });
16344
16154
  continue;
16345
16155
  }
16346
- const absolute = path15.resolve(projectRoot2, sourcePath);
16347
- if (path15.relative(projectRoot2, absolute).startsWith("..")) {
16156
+ const absolute = path14.resolve(projectRoot2, sourcePath);
16157
+ if (path14.relative(projectRoot2, absolute).startsWith("..")) {
16348
16158
  files.push({ path: sourcePath, status: "escaped", ...empty });
16349
16159
  continue;
16350
16160
  }
16351
16161
  let buffer;
16352
16162
  try {
16353
- const stat = fs13.statSync(absolute);
16163
+ const stat = fs12.statSync(absolute);
16354
16164
  if (!stat.isFile()) {
16355
16165
  files.push({ path: sourcePath, status: "missing", ...empty });
16356
16166
  continue;
16357
16167
  }
16358
- buffer = fs13.readFileSync(absolute);
16168
+ buffer = fs12.readFileSync(absolute);
16359
16169
  } catch {
16360
16170
  files.push({ path: sourcePath, status: "missing", ...empty });
16361
16171
  continue;
@@ -16365,7 +16175,7 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
16365
16175
  continue;
16366
16176
  }
16367
16177
  const text2 = buffer.toString("utf8");
16368
- const language = EXTENSION_LANGUAGE[path15.extname(sourcePath).toLowerCase()];
16178
+ const language = EXTENSION_LANGUAGE[path14.extname(sourcePath).toLowerCase()];
16369
16179
  let analyzed;
16370
16180
  if (language === "typescript" || language === "javascript") {
16371
16181
  const ts = resolveTypeScript(projectRoot2);
@@ -16409,7 +16219,7 @@ function readTestFiles(testRoots, projectRoot2) {
16409
16219
  for (const key of walkDeclaredRoots(testRoots, [], projectRoot2)) {
16410
16220
  let text2;
16411
16221
  try {
16412
- const buffer = fs13.readFileSync(path15.resolve(projectRoot2, key));
16222
+ const buffer = fs12.readFileSync(path14.resolve(projectRoot2, key));
16413
16223
  if (looksBinary(buffer)) continue;
16414
16224
  text2 = buffer.toString("utf8");
16415
16225
  } catch {
@@ -16446,12 +16256,12 @@ function findTestsReferencing(methods, projectRoot2, testRoots = []) {
16446
16256
  }
16447
16257
  return found;
16448
16258
  }
16449
- var fs13, path15, import_module2, EXTENSION_LANGUAGE, C_FAMILY_COMMENTS, NAMED_IMPORT_BINDINGS_RE, JS_PATTERNS, LANGUAGE_PATTERNS, PATTERN_ANALYSIS_MAX_BYTES, IDENTIFIER_RE, STRING_RE, tsResolutionCache, TS_RESOLUTION_RETRY_MS;
16259
+ var fs12, path14, import_module2, EXTENSION_LANGUAGE, C_FAMILY_COMMENTS, NAMED_IMPORT_BINDINGS_RE, JS_PATTERNS, LANGUAGE_PATTERNS, PATTERN_ANALYSIS_MAX_BYTES, IDENTIFIER_RE, STRING_RE, tsResolutionCache, TS_RESOLUTION_RETRY_MS;
16450
16260
  var init_source_analysis = __esm({
16451
16261
  "src/core/source-analysis.ts"() {
16452
16262
  "use strict";
16453
- fs13 = __toESM(require("fs"));
16454
- path15 = __toESM(require("path"));
16263
+ fs12 = __toESM(require("fs"));
16264
+ path14 = __toESM(require("path"));
16455
16265
  import_module2 = require("module");
16456
16266
  init_models();
16457
16267
  EXTENSION_LANGUAGE = {
@@ -17221,28 +17031,28 @@ var init_gate_identity = __esm({
17221
17031
 
17222
17032
  // src/core/variants.ts
17223
17033
  function globalVariantsDir() {
17224
- return process.env.WAIRON_VARIANTS_DIR ?? path16.join(os5.homedir(), ".wairon", "variants");
17034
+ return process.env.WAIRON_VARIANTS_DIR ?? path15.join(os5.homedir(), ".wairon", "variants");
17225
17035
  }
17226
17036
  function builtinVariantsDir() {
17227
17037
  const candidates = [
17228
- path16.resolve(__dirname, "..", "templates", "variants"),
17038
+ path15.resolve(__dirname, "..", "templates", "variants"),
17229
17039
  // src/core & dist/cli
17230
- path16.resolve(__dirname, "templates", "variants")
17040
+ path15.resolve(__dirname, "templates", "variants")
17231
17041
  // dist (library entry)
17232
17042
  ];
17233
- return candidates.find((dir) => fs14.existsSync(dir)) ?? candidates[0];
17043
+ return candidates.find((dir) => fs13.existsSync(dir)) ?? candidates[0];
17234
17044
  }
17235
17045
  function projectVariantsDir() {
17236
- return path16.join(getProjectRoot(), ".wai", "variants");
17046
+ return path15.join(getProjectRoot(), ".wai", "variants");
17237
17047
  }
17238
17048
  function variantFiles(dir) {
17239
17049
  let entries;
17240
17050
  try {
17241
- entries = fs14.readdirSync(dir, { withFileTypes: true });
17051
+ entries = fs13.readdirSync(dir, { withFileTypes: true });
17242
17052
  } catch {
17243
17053
  return [];
17244
17054
  }
17245
- 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));
17055
+ return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path15.join(dir, e.name));
17246
17056
  }
17247
17057
  function parseVariants(raw) {
17248
17058
  if (raw == null) return [];
@@ -17351,13 +17161,13 @@ function rebasedText(content, fromBase, toBase, rebasedContent) {
17351
17161
  }
17352
17162
  return serializeYaml(rebasedContent);
17353
17163
  }
17354
- var fs14, os5, path16, import_zod10, VariantDefSchema;
17164
+ var fs13, os5, path15, import_zod10, VariantDefSchema;
17355
17165
  var init_variants = __esm({
17356
17166
  "src/core/variants.ts"() {
17357
17167
  "use strict";
17358
- fs14 = __toESM(require("fs"));
17168
+ fs13 = __toESM(require("fs"));
17359
17169
  os5 = __toESM(require("os"));
17360
- path16 = __toESM(require("path"));
17170
+ path15 = __toESM(require("path"));
17361
17171
  import_zod10 = require("zod");
17362
17172
  init_yaml();
17363
17173
  init_fs();
@@ -17743,7 +17553,7 @@ var init_openapi = __esm({
17743
17553
 
17744
17554
  // src/core/surfaces.ts
17745
17555
  function surfacesDir(rootDir) {
17746
- return path17.join(rootDir, ".wai", SURFACES_DIRNAME);
17556
+ return path16.join(rootDir, ".wai", SURFACES_DIRNAME);
17747
17557
  }
17748
17558
  function audienceRank(audience) {
17749
17559
  const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
@@ -17901,12 +17711,12 @@ function projectSubsystemSurface(subsystemId) {
17901
17711
  }
17902
17712
  function listSnapshots(rootDir = getProjectRoot()) {
17903
17713
  const dir = surfacesDir(rootDir);
17904
- if (!fs15.existsSync(dir)) return [];
17714
+ if (!fs14.existsSync(dir)) return [];
17905
17715
  const out = [];
17906
- for (const file of fs15.readdirSync(dir)) {
17716
+ for (const file of fs14.readdirSync(dir)) {
17907
17717
  if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
17908
17718
  try {
17909
- out.push(SurfaceSnapshotSchema.parse(readYamlFile(path17.join(dir, file))));
17719
+ out.push(SurfaceSnapshotSchema.parse(readYamlFile(path16.join(dir, file))));
17910
17720
  } catch {
17911
17721
  }
17912
17722
  }
@@ -17917,10 +17727,10 @@ function snapshotFilename(projectName) {
17917
17727
  }
17918
17728
  function writeSnapshotIfChanged(snapshot, rootDir) {
17919
17729
  const dir = surfacesDir(rootDir);
17920
- fs15.mkdirSync(dir, { recursive: true });
17921
- const p = path17.join(dir, snapshotFilename(snapshot.projectName));
17730
+ fs14.mkdirSync(dir, { recursive: true });
17731
+ const p = path16.join(dir, snapshotFilename(snapshot.projectName));
17922
17732
  const next = SurfaceSnapshotSchema.parse(snapshot);
17923
- if (fs15.existsSync(p)) {
17733
+ if (fs14.existsSync(p)) {
17924
17734
  try {
17925
17735
  const existing = SurfaceSnapshotSchema.parse(readYamlFile(p));
17926
17736
  if (surfaceContentKey(existing) === surfaceContentKey(next)) {
@@ -17939,11 +17749,11 @@ function loadSurfaceSnapshots() {
17939
17749
  return listSnapshots();
17940
17750
  }
17941
17751
  function listMountSnapshots(mounts) {
17942
- const bound2 = path17.resolve(getProjectRoot());
17752
+ const bound2 = path16.resolve(getProjectRoot());
17943
17753
  const out = [];
17944
17754
  for (const namespace of mounts) {
17945
17755
  const dir = resolveSubprojectForNamespace(namespace);
17946
- if (!dir || path17.resolve(dir) === bound2) continue;
17756
+ if (!dir || path16.resolve(dir) === bound2) continue;
17947
17757
  const snapshots = listSnapshots(dir);
17948
17758
  if (snapshots.length > 0) out.push({ namespace, snapshots });
17949
17759
  }
@@ -17961,24 +17771,24 @@ function selectPortalSpec(renderedSet, portalId) {
17961
17771
  return [hit];
17962
17772
  }
17963
17773
  function perPortalPath(resolvedOut, portalId) {
17964
- const ext = path17.extname(resolvedOut);
17774
+ const ext = path16.extname(resolvedOut);
17965
17775
  const stem2 = ext ? resolvedOut.slice(0, -ext.length) : resolvedOut;
17966
17776
  return `${stem2}.${safeFilenamePart(portalId)}${ext}`;
17967
17777
  }
17968
17778
  function writeSurfaceFile(outPath, snapshot, renderedSet) {
17969
- const resolved = path17.resolve(outPath);
17970
- fs15.mkdirSync(path17.dirname(resolved), { recursive: true });
17779
+ const resolved = path16.resolve(outPath);
17780
+ fs14.mkdirSync(path16.dirname(resolved), { recursive: true });
17971
17781
  if (!renderedSet || renderedSet.length === 0) {
17972
17782
  writeYamlFile(resolved, snapshot);
17973
17783
  return [resolved];
17974
17784
  }
17975
17785
  if (renderedSet.length === 1) {
17976
- fs15.writeFileSync(resolved, renderedSet[0].document);
17786
+ fs14.writeFileSync(resolved, renderedSet[0].document);
17977
17787
  return [resolved];
17978
17788
  }
17979
17789
  return renderedSet.map((spec) => {
17980
17790
  const target = perPortalPath(resolved, spec.portalId);
17981
- fs15.writeFileSync(target, spec.document);
17791
+ fs14.writeFileSync(target, spec.document);
17982
17792
  return target;
17983
17793
  });
17984
17794
  }
@@ -18000,14 +17810,14 @@ function exportSurface(maxAudience, format, outPath, portalId) {
18000
17810
  return exportResult(snapshot, renderedSet, writtenPaths);
18001
17811
  }
18002
17812
  function importSurface(sourcePath, origin) {
18003
- const resolved = path17.resolve(sourcePath);
18004
- if (!fs15.existsSync(resolved)) {
17813
+ const resolved = path16.resolve(sourcePath);
17814
+ if (!fs14.existsSync(resolved)) {
18005
17815
  throw new Error(`Surface document not found: ${resolved}`);
18006
17816
  }
18007
- const body = fs15.readFileSync(resolved, "utf8");
17817
+ const body = fs14.readFileSync(resolved, "utf8");
18008
17818
  let snapshot;
18009
17819
  if (isOpenApiDocument(body)) {
18010
- const projectName = path17.basename(resolved).replace(/\.(json|ya?ml)$/i, "");
17820
+ const projectName = path16.basename(resolved).replace(/\.(json|ya?ml)$/i, "");
18011
17821
  snapshot = fromOpenApi(body, projectName);
18012
17822
  snapshot = { ...snapshot, origin };
18013
17823
  } else {
@@ -18070,12 +17880,12 @@ function surfaceContentKey(snapshot) {
18070
17880
  const { stateId, generatedAt, origin, ...content } = snapshot;
18071
17881
  return JSON.stringify(content);
18072
17882
  }
18073
- var fs15, path17, SURFACES_DIRNAME, CROSS_BOUNDARY_TARGETS;
17883
+ var fs14, path16, SURFACES_DIRNAME, CROSS_BOUNDARY_TARGETS;
18074
17884
  var init_surfaces = __esm({
18075
17885
  "src/core/surfaces.ts"() {
18076
17886
  "use strict";
18077
- fs15 = __toESM(require("fs"));
18078
- path17 = __toESM(require("path"));
17887
+ fs14 = __toESM(require("fs"));
17888
+ path16 = __toESM(require("path"));
18079
17889
  init_fs();
18080
17890
  init_yaml();
18081
17891
  init_filenames();
@@ -18381,13 +18191,13 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
18381
18191
  function resolveThroughParent(boundRoot, treatAllAsComplete, childRules) {
18382
18192
  const reach = getRequestParentReach();
18383
18193
  if (reach && !reach.parentReach) return null;
18384
- const ceiling = reach?.topRoot ? path18.resolve(reach.topRoot) : void 0;
18194
+ const ceiling = reach?.topRoot ? path17.resolve(reach.topRoot) : void 0;
18385
18195
  const chain = [];
18386
- let top = path18.resolve(boundRoot);
18196
+ let top = path17.resolve(boundRoot);
18387
18197
  while (top !== ceiling) {
18388
18198
  const hop = findChainingParent(top, ceiling);
18389
18199
  if (!hop) break;
18390
- const next = path18.resolve(hop.parentRoot);
18200
+ const next = path17.resolve(hop.parentRoot);
18391
18201
  if (ceiling && !isWithinOrEqual(ceiling, next)) break;
18392
18202
  chain.unshift(hop.subsystemId);
18393
18203
  top = next;
@@ -18434,8 +18244,8 @@ function isIdChar(ch) {
18434
18244
  return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-" || ch === "." || ch === ":";
18435
18245
  }
18436
18246
  function isWithinOrEqual(dir, target) {
18437
- const rel2 = path18.relative(dir, target);
18438
- return rel2 === "" || !rel2.startsWith("..") && !path18.isAbsolute(rel2);
18247
+ const rel2 = path17.relative(dir, target);
18248
+ return rel2 === "" || !rel2.startsWith("..") && !path17.isAbsolute(rel2);
18439
18249
  }
18440
18250
  function dedupeIssues(list2) {
18441
18251
  const seen = /* @__PURE__ */ new Set();
@@ -18456,7 +18266,7 @@ function settledStatusBearing(loaded) {
18456
18266
  if (!settled || settled.size === 0) return [];
18457
18267
  const root = getProjectRoot();
18458
18268
  const index = scanAllSpecs();
18459
- const rel2 = (abs) => path18.relative(root, abs).split(path18.sep).join("/");
18269
+ const rel2 = (abs) => path17.relative(root, abs).split(path17.sep).join("/");
18460
18270
  const out = [];
18461
18271
  const take = (specs, paths) => {
18462
18272
  for (const spec of specs) {
@@ -18486,7 +18296,7 @@ function computeGateStateId() {
18486
18296
  registerBuiltinRules();
18487
18297
  return computeGateIdentity(content, extensions, ruleSequence(), inputs, gate);
18488
18298
  }
18489
- var path18, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
18299
+ var path17, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
18490
18300
  var init_validation = __esm({
18491
18301
  "src/core/validation.ts"() {
18492
18302
  "use strict";
@@ -18502,7 +18312,7 @@ var init_validation = __esm({
18502
18312
  init_source_analysis();
18503
18313
  init_specs2();
18504
18314
  init_fs();
18505
- path18 = __toESM(require("path"));
18315
+ path17 = __toESM(require("path"));
18506
18316
  init_core();
18507
18317
  RESOLUTION_FAILURE_CODES = /* @__PURE__ */ new Set([
18508
18318
  "UNDEFINED_TYPE_REFERENCE",
@@ -19222,42 +19032,42 @@ function rebaseReference(ref, mount, direction, isMoved = () => false) {
19222
19032
  return relativizeId(travels ? qualifyId(left, to, NO_ROOT_SUBSYSTEMS) : target, to);
19223
19033
  }
19224
19034
  function isWithin(dir, file) {
19225
- const d = path19.resolve(dir);
19226
- const f = path19.resolve(file);
19227
- return f === d || f.startsWith(d + path19.sep);
19035
+ const d = path18.resolve(dir);
19036
+ const f = path18.resolve(file);
19037
+ return f === d || f.startsWith(d + path18.sep);
19228
19038
  }
19229
19039
  function canonicalPath(target) {
19230
- let existing = path19.resolve(target);
19040
+ let existing = path18.resolve(target);
19231
19041
  const rest = [];
19232
19042
  for (; ; ) {
19233
19043
  try {
19234
- fs16.lstatSync(existing);
19044
+ fs15.lstatSync(existing);
19235
19045
  break;
19236
19046
  } catch {
19237
- const up = path19.dirname(existing);
19238
- if (up === existing) return path19.resolve(target);
19239
- rest.unshift(path19.basename(existing));
19047
+ const up = path18.dirname(existing);
19048
+ if (up === existing) return path18.resolve(target);
19049
+ rest.unshift(path18.basename(existing));
19240
19050
  existing = up;
19241
19051
  }
19242
19052
  }
19243
19053
  try {
19244
- return path19.join(fs16.realpathSync.native(existing), ...rest);
19054
+ return path18.join(fs15.realpathSync.native(existing), ...rest);
19245
19055
  } catch {
19246
19056
  return null;
19247
19057
  }
19248
19058
  }
19249
19059
  function chainDirKey(dir) {
19250
- return canonicalPath(dir) ?? path19.resolve(dir);
19060
+ return canonicalPath(dir) ?? path18.resolve(dir);
19251
19061
  }
19252
19062
  function projectPathEscapesRoot(projectRoot2, projectPath, resolvedChildDir) {
19253
- if (path19.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
19063
+ if (path18.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
19254
19064
  const root = canonicalPath(projectRoot2);
19255
19065
  const child = canonicalPath(resolvedChildDir);
19256
19066
  return root === null || child === null || !isWithin(root, child);
19257
19067
  }
19258
19068
  function assertContainedProjectPath(projectRoot2, projectPath) {
19259
- const root = path19.resolve(projectRoot2);
19260
- const resolved = path19.resolve(root, projectPath);
19069
+ const root = path18.resolve(projectRoot2);
19070
+ const resolved = path18.resolve(root, projectPath);
19261
19071
  if (projectPathEscapesRoot(root, projectPath, resolved)) {
19262
19072
  throw new Error(
19263
19073
  `projectPath "${projectPath}" must resolve within the project root "${root}", but resolves to "${resolved}"; absolute, ../-escaping and link-escaping paths are rejected so a chained subproject is always contained by its parent.`
@@ -19268,12 +19078,12 @@ function assertContainedProjectPath(projectRoot2, projectPath) {
19268
19078
  function findChainingParent(childRoot, ceiling) {
19269
19079
  let childResolved;
19270
19080
  try {
19271
- childResolved = path19.resolve(childRoot);
19081
+ childResolved = path18.resolve(childRoot);
19272
19082
  } catch {
19273
19083
  return null;
19274
19084
  }
19275
- const bound2 = ceiling ? path19.resolve(ceiling) : void 0;
19276
- let dir = path19.dirname(childResolved);
19085
+ const bound2 = ceiling ? path18.resolve(ceiling) : void 0;
19086
+ let dir = path18.dirname(childResolved);
19277
19087
  for (let hops = 0; hops < 32; hops++) {
19278
19088
  if (bound2 && !isWithin(bound2, dir)) break;
19279
19089
  const specsDir = aiPathsAt(dir).specsDir();
@@ -19289,7 +19099,7 @@ function findChainingParent(childRoot, ceiling) {
19289
19099
  const projectPath = raw.projectPath;
19290
19100
  if (typeof projectPath === "string" && projectPath.trim() !== "") {
19291
19101
  try {
19292
- const mountDir = path19.resolve(dir, projectPath);
19102
+ const mountDir = path18.resolve(dir, projectPath);
19293
19103
  if (mountDir === childResolved && !projectPathEscapesRoot(dir, projectPath, mountDir)) {
19294
19104
  const id = raw.id;
19295
19105
  return { parentRoot: dir, subsystemId: typeof id === "string" ? id : "?" };
@@ -19300,14 +19110,14 @@ function findChainingParent(childRoot, ceiling) {
19300
19110
  }
19301
19111
  }
19302
19112
  }
19303
- const up = path19.dirname(dir);
19113
+ const up = path18.dirname(dir);
19304
19114
  if (up === dir) break;
19305
19115
  dir = up;
19306
19116
  }
19307
19117
  return null;
19308
19118
  }
19309
19119
  function inspectChainedRoots(rootDir = getProjectRoot()) {
19310
- const root = path19.resolve(rootDir);
19120
+ const root = path18.resolve(rootDir);
19311
19121
  const inspection = { roots: [], skipped: [] };
19312
19122
  const listed = /* @__PURE__ */ new Set();
19313
19123
  const walk2 = (projectDir, prefix, ancestors, depth) => {
@@ -19326,14 +19136,14 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
19326
19136
  const localId = typeof id === "string" ? id : "?";
19327
19137
  let childDir;
19328
19138
  try {
19329
- childDir = path19.resolve(projectDir, projectPath);
19139
+ childDir = path18.resolve(projectDir, projectPath);
19330
19140
  } catch {
19331
19141
  continue;
19332
19142
  }
19333
19143
  let reason;
19334
19144
  if (projectPathEscapesRoot(projectDir, projectPath, childDir)) reason = "escapes";
19335
19145
  else if (ancestors.has(chainDirKey(childDir))) reason = "cyclic";
19336
- else if (!fs16.existsSync(childDir)) reason = "missing";
19146
+ else if (!fs15.existsSync(childDir)) reason = "missing";
19337
19147
  else if (depth >= 32) reason = "too-deep";
19338
19148
  if (reason) {
19339
19149
  const mount = prefix ? qualifyDeclaredId(localId, prefix, true) : localId;
@@ -19343,7 +19153,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
19343
19153
  const key = chainDirKey(childDir);
19344
19154
  if (listed.has(key)) continue;
19345
19155
  listed.add(key);
19346
- inspection.roots.push(path19.relative(root, childDir).split(path19.sep).join("/"));
19156
+ inspection.roots.push(path18.relative(root, childDir).split(path18.sep).join("/"));
19347
19157
  walk2(childDir, prefix ? `${prefix}::${localId}` : localId, /* @__PURE__ */ new Set([...ancestors, key]), depth + 1);
19348
19158
  }
19349
19159
  };
@@ -19429,9 +19239,9 @@ function stripNamespaceFromImplementation(spec, prefix) {
19429
19239
  }
19430
19240
  function childRelativeFilePaths(spec, authoringRoot, childRoot) {
19431
19241
  const reexpress = (p) => {
19432
- if (path19.isAbsolute(p)) return p;
19433
- const rel2 = path19.relative(childRoot, path19.resolve(authoringRoot, p));
19434
- const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path19.sep}`) && !path19.isAbsolute(rel2);
19242
+ if (path18.isAbsolute(p)) return p;
19243
+ const rel2 = path18.relative(childRoot, path18.resolve(authoringRoot, p));
19244
+ const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path18.sep}`) && !path18.isAbsolute(rel2);
19435
19245
  return inside ? rel2.replace(/\\/g, "/") : p;
19436
19246
  };
19437
19247
  return {
@@ -19466,10 +19276,10 @@ function findOwner(id, components) {
19466
19276
  }) ?? null;
19467
19277
  }
19468
19278
  function moveComponentFolder(fromDir, toDir) {
19469
- if (path19.normalize(fromDir) === path19.normalize(toDir)) return false;
19470
- if (!fs16.existsSync(fromDir) || fs16.existsSync(toDir)) return false;
19471
- ensureDir(path19.dirname(toDir));
19472
- fs16.renameSync(fromDir, toDir);
19279
+ if (path18.normalize(fromDir) === path18.normalize(toDir)) return false;
19280
+ if (!fs15.existsSync(fromDir) || fs15.existsSync(toDir)) return false;
19281
+ ensureDir(path18.dirname(toDir));
19282
+ fs15.renameSync(fromDir, toDir);
19473
19283
  return true;
19474
19284
  }
19475
19285
  function formatZodIssues(error) {
@@ -19485,13 +19295,13 @@ function parseOrThrow(schema, value, kind, id) {
19485
19295
  function computeSpecTreeSignature(dirs) {
19486
19296
  const parts = [];
19487
19297
  for (const dir of dirs) {
19488
- if (!fs16.existsSync(dir)) {
19298
+ if (!fs15.existsSync(dir)) {
19489
19299
  parts.push(`${dir}:missing`);
19490
19300
  continue;
19491
19301
  }
19492
19302
  for (const f of listSpecFiles(dir)) {
19493
19303
  try {
19494
- const st = fs16.statSync(f);
19304
+ const st = fs15.statSync(f);
19495
19305
  parts.push(`${f}:${st.mtimeMs}:${st.size}`);
19496
19306
  } catch {
19497
19307
  parts.push(`${f}:gone`);
@@ -19884,7 +19694,7 @@ function refusedMoveSummary(from, to, methods, refusals, alternatives) {
19884
19694
  return `Refused: moving ${namedMethods(methods)} from "${from}" to "${to}" is refused by ${refusals.join(", ")}. Nothing was written. ` + (cheapest ? `The cheapest legal home is "${cheapest.component}" (${cheapest.newDependencies.length} new dependenc${cheapest.newDependencies.length === 1 ? "y" : "ies"}, ${cheapest.dependencyCount} of ${cheapest.dependencyLimit}).` : `No component of this subsystem can take them as they stand \u2014 ${alternatives.length} were weighed.`);
19885
19695
  }
19886
19696
  function workspaceFor(rootDir) {
19887
- const key = path19.resolve(rootDir);
19697
+ const key = path18.resolve(rootDir);
19888
19698
  let ws = workspaces.get(key);
19889
19699
  if (!ws) {
19890
19700
  ws = new SpecWorkspace(key);
@@ -20014,13 +19824,13 @@ function snapshotInputKey(snapshot) {
20014
19824
  return canonicalize(content);
20015
19825
  }
20016
19826
  function consumedSurfaceInputsAt(rootDir) {
20017
- const dir = path19.join(rootDir, ".wai", "surfaces");
19827
+ const dir = path18.join(rootDir, ".wai", "surfaces");
20018
19828
  if (!pathExists(dir)) return [];
20019
19829
  const keys = [];
20020
- for (const file of fs16.readdirSync(dir)) {
19830
+ for (const file of fs15.readdirSync(dir)) {
20021
19831
  if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
20022
19832
  try {
20023
- keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path19.join(dir, file)))));
19833
+ keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path18.join(dir, file)))));
20024
19834
  } catch {
20025
19835
  }
20026
19836
  }
@@ -20028,7 +19838,7 @@ function consumedSurfaceInputsAt(rootDir) {
20028
19838
  }
20029
19839
  function consumedContractInputs() {
20030
19840
  const root = getProjectRoot();
20031
- const roots = [root, ...listChainedRoots(root).map((rel2) => path19.join(root, rel2))];
19841
+ const roots = [root, ...listChainedRoots(root).map((rel2) => path18.join(root, rel2))];
20032
19842
  return roots.flatMap(consumedSurfaceInputsAt);
20033
19843
  }
20034
19844
  function readLockState(current2) {
@@ -20064,7 +19874,7 @@ function markSelectionsBundled(bundled) {
20064
19874
  projectConfigRepository.markSelectionsBundled(bundled);
20065
19875
  }
20066
19876
  function computeStateIdAt(root) {
20067
- const resolved = path19.resolve(root);
19877
+ const resolved = path18.resolve(root);
20068
19878
  return runWithProjectRoot(resolved, () => {
20069
19879
  workspaceFor(resolved).invalidate();
20070
19880
  const system = loadSystemSpec();
@@ -20102,7 +19912,7 @@ function snapshotSpecFiles() {
20102
19912
  }
20103
19913
  function restoreSpecFiles(snapshot) {
20104
19914
  for (const [file, content] of snapshot) {
20105
- fs16.writeFileSync(file, content);
19915
+ fs15.writeFileSync(file, content);
20106
19916
  }
20107
19917
  }
20108
19918
  function findLegacySpecFiles() {
@@ -20114,12 +19924,12 @@ function updateSpec(kind, id, delta, hooks, dryRun) {
20114
19924
  function moveMethods(from, to, methods, hooks, dryRun) {
20115
19925
  return current().moveMethods(from, to, methods, hooks, dryRun);
20116
19926
  }
20117
- var fs16, path19, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, COMPONENT_AUTH_SOURCE, DELTA_VERBS, JUMP_LABEL_TWINS, LABEL_TWIN_CONTAINERS, SpecWorkspace, DEFAULT_DEPENDENCY_LIMIT, PROSE_FIELDS, workspaces;
19927
+ var fs15, path18, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, COMPONENT_AUTH_SOURCE, DELTA_VERBS, JUMP_LABEL_TWINS, LABEL_TWIN_CONTAINERS, SpecWorkspace, DEFAULT_DEPENDENCY_LIMIT, PROSE_FIELDS, workspaces;
20118
19928
  var init_specs2 = __esm({
20119
19929
  "src/core/specs.ts"() {
20120
19930
  "use strict";
20121
- fs16 = __toESM(require("fs"));
20122
- path19 = __toESM(require("path"));
19931
+ fs15 = __toESM(require("fs"));
19932
+ path18 = __toESM(require("path"));
20123
19933
  init_paths();
20124
19934
  init_project_config();
20125
19935
  init_fs();
@@ -20154,7 +19964,7 @@ var init_specs2 = __esm({
20154
19964
  this.rootSubsystems = /* @__PURE__ */ new Set();
20155
19965
  this.scanVisitedSpecDirs = [];
20156
19966
  this.loaderIssues = [];
20157
- this.rootDir = path19.resolve(rootDir);
19967
+ this.rootDir = path18.resolve(rootDir);
20158
19968
  this.paths = aiPathsAt(this.rootDir);
20159
19969
  }
20160
19970
  invalidate() {
@@ -20197,8 +20007,8 @@ var init_specs2 = __esm({
20197
20007
  * qualifies the spec itself — so scoping a validate to a mount keeps it.
20198
20008
  */
20199
20009
  loaderIssueSpecId(file, rawId, namespacePrefix) {
20200
- const stem2 = path19.basename(file, ".yaml");
20201
- const local = rawId ?? (stem2.startsWith(".") ? path19.basename(path19.dirname(file)) : stem2);
20010
+ const stem2 = path18.basename(file, ".yaml");
20011
+ const local = rawId ?? (stem2.startsWith(".") ? path18.basename(path18.dirname(file)) : stem2);
20202
20012
  return namespacePrefix ? qualifyId(local, namespacePrefix, this.rootSubsystems) : local;
20203
20013
  }
20204
20014
  scanSpecsForProject(projectDir, namespacePrefix, visitedDirs, maxDepth, currentDepth) {
@@ -20208,10 +20018,10 @@ var init_specs2 = __esm({
20208
20018
  this.scanVisitedSpecDirs.push(specsDir);
20209
20019
  if (!pathExists(specsDir)) return index;
20210
20020
  const files = listSpecFiles(specsDir);
20211
- const systemYaml = path19.normalize(projectPaths.specsSystem());
20021
+ const systemYaml = path18.normalize(projectPaths.specsSystem());
20212
20022
  const localSubprojects = [];
20213
20023
  for (const file of files) {
20214
- const normFile = path19.normalize(file);
20024
+ const normFile = path18.normalize(file);
20215
20025
  if (normFile === systemYaml) continue;
20216
20026
  let detectedType = "spec";
20217
20027
  let rawId;
@@ -20255,7 +20065,7 @@ var init_specs2 = __esm({
20255
20065
  } else if ("contract" in raw) {
20256
20066
  detectedType = "implementation";
20257
20067
  const parsed = ImplementationSpecSchema.parse(raw);
20258
- const normalizeSourcePath = (p) => path19.relative(projectDir, path19.resolve(projectDir, p)).replace(/\\/g, "/");
20068
+ const normalizeSourcePath = (p) => path18.relative(projectDir, path18.resolve(projectDir, p)).replace(/\\/g, "/");
20259
20069
  if (parsed.sourcePath) parsed.sourcePath = normalizeSourcePath(parsed.sourcePath);
20260
20070
  for (const method2 of parsed.methods) {
20261
20071
  if (method2.sourcePath) method2.sourcePath = normalizeSourcePath(method2.sourcePath);
@@ -20381,7 +20191,7 @@ var init_specs2 = __esm({
20381
20191
  }
20382
20192
  if (currentDepth < maxDepth) {
20383
20193
  for (const subproj of localSubprojects) {
20384
- const childDir = path19.resolve(projectDir, subproj.projectPath);
20194
+ const childDir = path18.resolve(projectDir, subproj.projectPath);
20385
20195
  const mountId = namespacePrefix ? qualifyDeclaredId(subproj.subsystemId, namespacePrefix, true) : subproj.subsystemId;
20386
20196
  if (projectPathEscapesRoot(projectDir, subproj.projectPath, childDir)) {
20387
20197
  this.loaderIssues.push({
@@ -20401,7 +20211,7 @@ var init_specs2 = __esm({
20401
20211
  });
20402
20212
  continue;
20403
20213
  }
20404
- if (!fs16.existsSync(childDir)) {
20214
+ if (!fs15.existsSync(childDir)) {
20405
20215
  this.loaderIssues.push({
20406
20216
  severity: "error",
20407
20217
  code: "SUBPROJECT_NOT_FOUND",
@@ -20444,7 +20254,7 @@ var init_specs2 = __esm({
20444
20254
  const index = this.scanAll();
20445
20255
  const sub = index.subsystems.find((s) => s.id === currentPrefix);
20446
20256
  if (sub && sub.projectPath) {
20447
- const nextDir = path19.resolve(currentDir, sub.projectPath);
20257
+ const nextDir = path18.resolve(currentDir, sub.projectPath);
20448
20258
  if (projectPathEscapesRoot(currentDir, sub.projectPath, nextDir)) {
20449
20259
  this.loaderIssues.push({
20450
20260
  severity: "error",
@@ -20496,9 +20306,9 @@ var init_specs2 = __esm({
20496
20306
  return index.paths.subsystem[matches[0]];
20497
20307
  }
20498
20308
  if (pathExists(this.paths.specsSubsystemsDir()) && listFiles(this.paths.specsSubsystemsDir(), ".yaml").length > 0) {
20499
- return path19.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
20309
+ return path18.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
20500
20310
  }
20501
- return path19.join(this.paths.specsDir(), id, ".index.yaml");
20311
+ return path18.join(this.paths.specsDir(), id, ".index.yaml");
20502
20312
  }
20503
20313
  getComponentPath(id, subsystemId) {
20504
20314
  const index = this.scanAll();
@@ -20518,21 +20328,21 @@ var init_specs2 = __esm({
20518
20328
  if (owner) {
20519
20329
  const ownerPath = index.paths.component[owner.id];
20520
20330
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
20521
- return path19.join(path19.dirname(ownerPath), id, ".index.yaml");
20331
+ return path18.join(path18.dirname(ownerPath), id, ".index.yaml");
20522
20332
  }
20523
20333
  }
20524
20334
  if (subsystemId) {
20525
20335
  const subPath = this.getSubsystemPath(subsystemId);
20526
- const subDir = path19.dirname(subPath);
20336
+ const subDir = path18.dirname(subPath);
20527
20337
  if (subPath.endsWith(".index.yaml")) {
20528
- return path19.join(subDir, id, ".index.yaml");
20338
+ return path18.join(subDir, id, ".index.yaml");
20529
20339
  }
20530
20340
  }
20531
20341
  if (pathExists(this.paths.specsComponentsDir()) && listFiles(this.paths.specsComponentsDir(), ".yaml").length > 0) {
20532
- return path19.join(this.paths.specsComponentsDir(), `${id}.yaml`);
20342
+ return path18.join(this.paths.specsComponentsDir(), `${id}.yaml`);
20533
20343
  }
20534
20344
  const targetSubsystem = subsystemId || "default";
20535
- return path19.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
20345
+ return path18.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
20536
20346
  }
20537
20347
  getInterfacePath(id, componentId) {
20538
20348
  const index = this.scanAll();
@@ -20558,16 +20368,16 @@ var init_specs2 = __esm({
20558
20368
  }
20559
20369
  if (componentId) {
20560
20370
  const compPath = this.getComponentPath(componentId);
20561
- const compDir = path19.dirname(compPath);
20371
+ const compDir = path18.dirname(compPath);
20562
20372
  if (compPath.endsWith(".index.yaml")) {
20563
- return path19.join(compDir, ".interface.yaml");
20373
+ return path18.join(compDir, ".interface.yaml");
20564
20374
  }
20565
20375
  }
20566
20376
  if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
20567
- return path19.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
20377
+ return path18.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
20568
20378
  }
20569
20379
  const targetComponent = componentId || "default";
20570
- return path19.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
20380
+ return path18.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
20571
20381
  }
20572
20382
  getImplementationPath(id, contractId) {
20573
20383
  const index = this.scanAll();
@@ -20593,16 +20403,16 @@ var init_specs2 = __esm({
20593
20403
  }
20594
20404
  if (contractId) {
20595
20405
  const intfPath = this.getInterfacePath(contractId);
20596
- const intfDir = path19.dirname(intfPath);
20406
+ const intfDir = path18.dirname(intfPath);
20597
20407
  if (intfPath.endsWith(".interface.yaml")) {
20598
- return path19.join(intfDir, ".implementation.yaml");
20408
+ return path18.join(intfDir, ".implementation.yaml");
20599
20409
  }
20600
20410
  }
20601
20411
  if (pathExists(this.paths.specsImplementationsDir()) && listFiles(this.paths.specsImplementationsDir(), ".yaml").length > 0) {
20602
- return path19.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
20412
+ return path18.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
20603
20413
  }
20604
20414
  const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
20605
- return path19.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
20415
+ return path18.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
20606
20416
  }
20607
20417
  getTypePath(id, subsystemId, group) {
20608
20418
  const index = this.scanAll();
@@ -20633,7 +20443,7 @@ var init_specs2 = __esm({
20633
20443
  const groupPath = index.paths.group[targetGroup] || index.paths.group[plainGroup];
20634
20444
  if (groupPath) {
20635
20445
  const localId2 = id.split("::").pop();
20636
- return path19.join(path19.dirname(groupPath), `${localId2}.yaml`);
20446
+ return path18.join(path18.dirname(groupPath), `${localId2}.yaml`);
20637
20447
  }
20638
20448
  }
20639
20449
  let localId = id;
@@ -20646,12 +20456,12 @@ var init_specs2 = __esm({
20646
20456
  }
20647
20457
  if (subsystemId) {
20648
20458
  const subPath = this.getSubsystemPath(subsystemId);
20649
- const subDir = path19.dirname(subPath);
20459
+ const subDir = path18.dirname(subPath);
20650
20460
  if (subPath.endsWith(".index.yaml")) {
20651
- return path19.join(subDir, "types", `${localId}.yaml`);
20461
+ return path18.join(subDir, "types", `${localId}.yaml`);
20652
20462
  }
20653
20463
  }
20654
- return path19.join(this.paths.specsTypesDir(), `${localId}.yaml`);
20464
+ return path18.join(this.paths.specsTypesDir(), `${localId}.yaml`);
20655
20465
  }
20656
20466
  getGroupPath(id, subsystemId) {
20657
20467
  const index = this.scanAll();
@@ -20685,12 +20495,12 @@ var init_specs2 = __esm({
20685
20495
  }
20686
20496
  if (subsystemId) {
20687
20497
  const subPath = this.getSubsystemPath(subsystemId);
20688
- const subDir = path19.dirname(subPath);
20498
+ const subDir = path18.dirname(subPath);
20689
20499
  if (subPath.endsWith(".index.yaml")) {
20690
- return path19.join(subDir, "types", localId, ".index.yaml");
20500
+ return path18.join(subDir, "types", localId, ".index.yaml");
20691
20501
  }
20692
20502
  }
20693
- return path19.join(this.paths.specsTypesDir(), localId, ".index.yaml");
20503
+ return path18.join(this.paths.specsTypesDir(), localId, ".index.yaml");
20694
20504
  }
20695
20505
  // -------------------------------------------------------------------------
20696
20506
  // Level 0: System
@@ -20713,7 +20523,7 @@ var init_specs2 = __esm({
20713
20523
  }
20714
20524
  saveSystemSpec(spec) {
20715
20525
  const p = this.paths.specsSystem();
20716
- ensureDir(path19.dirname(p));
20526
+ ensureDir(path18.dirname(p));
20717
20527
  writeSpecFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
20718
20528
  invalidateSpecCache();
20719
20529
  }
@@ -20835,7 +20645,7 @@ var init_specs2 = __esm({
20835
20645
  }
20836
20646
  saveSubsystemSpec(spec, opts) {
20837
20647
  const p = this.getSubsystemPath(spec.id);
20838
- ensureDir(path19.dirname(p));
20648
+ ensureDir(path18.dirname(p));
20839
20649
  const { prefix } = splitNamespace(spec.id);
20840
20650
  if (!prefix && spec.projectPath && spec.projectPath.trim() !== "") {
20841
20651
  assertContainedProjectPath(this.rootDir, spec.projectPath);
@@ -20902,7 +20712,7 @@ var init_specs2 = __esm({
20902
20712
  saveComponentSpec(spec, opts) {
20903
20713
  const notices = [];
20904
20714
  const p = this.getComponentPath(spec.id, spec.subsystem);
20905
- ensureDir(path19.dirname(p));
20715
+ ensureDir(path18.dirname(p));
20906
20716
  const specToWrite = this.prepareComponentForWrite(spec);
20907
20717
  const existing = this.loadComponentSpec(spec.id);
20908
20718
  if (existing) {
@@ -20919,7 +20729,7 @@ var init_specs2 = __esm({
20919
20729
  const subsystemChanged = existing && existing.subsystem !== spec.subsystem && splitNamespace(existing.subsystem).localId !== splitNamespace(spec.subsystem).localId;
20920
20730
  if (subsystemChanged && !p.endsWith(".index.yaml")) {
20921
20731
  notices.push(
20922
- `component "${spec.id}" already exists at ${path19.relative(this.rootDir, p)} \u2014 the flat layout re-saves in place and never relocates the file. The subsystem field is now "${spec.subsystem}" (was "${existing.subsystem}").`
20732
+ `component "${spec.id}" already exists at ${path18.relative(this.rootDir, p)} \u2014 the flat layout re-saves in place and never relocates the file. The subsystem field is now "${spec.subsystem}" (was "${existing.subsystem}").`
20923
20733
  );
20924
20734
  }
20925
20735
  specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
@@ -20943,12 +20753,12 @@ var init_specs2 = __esm({
20943
20753
  if (owner) {
20944
20754
  const ownerPath = index.paths.component[owner.id];
20945
20755
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
20946
- const ownerSubDir = path19.dirname(this.getSubsystemPath(owner.subsystem));
20947
- return path19.join(ownerSubDir, owner.id, comp.id);
20756
+ const ownerSubDir = path18.dirname(this.getSubsystemPath(owner.subsystem));
20757
+ return path18.join(ownerSubDir, owner.id, comp.id);
20948
20758
  }
20949
20759
  }
20950
- const subDir = path19.dirname(this.getSubsystemPath(comp.subsystem));
20951
- return path19.join(subDir, comp.id);
20760
+ const subDir = path18.dirname(this.getSubsystemPath(comp.subsystem));
20761
+ return path18.join(subDir, comp.id);
20952
20762
  }
20953
20763
  /**
20954
20764
  * Move component folders so the physical tree mirrors ownership: each owned
@@ -20964,7 +20774,7 @@ var init_specs2 = __esm({
20964
20774
  if (!currentPath) continue;
20965
20775
  const desiredDir = this.desiredComponentDir(comp, index);
20966
20776
  if (!desiredDir) continue;
20967
- if (moveComponentFolder(path19.dirname(currentPath), desiredDir)) moved.push(comp.id);
20777
+ if (moveComponentFolder(path18.dirname(currentPath), desiredDir)) moved.push(comp.id);
20968
20778
  }
20969
20779
  if (moved.length) invalidateSpecCache();
20970
20780
  return moved;
@@ -21020,7 +20830,7 @@ var init_specs2 = __esm({
21020
20830
  if (!occupantId) return;
21021
20831
  if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
21022
20832
  throw new Error(
21023
- `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path19.relative(this.rootDir, p)}, and both ids resolve to that one file. Re-author "${occupantId}" instead, or delete it first if you meant to replace it.`
20833
+ `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path18.relative(this.rootDir, p)}, and both ids resolve to that one file. Re-author "${occupantId}" instead, or delete it first if you meant to replace it.`
21024
20834
  );
21025
20835
  }
21026
20836
  /** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
@@ -21028,12 +20838,12 @@ var init_specs2 = __esm({
21028
20838
  const notices = [];
21029
20839
  const p = this.getInterfacePath(spec.id, spec.component);
21030
20840
  this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
21031
- ensureDir(path19.dirname(p));
20841
+ ensureDir(path18.dirname(p));
21032
20842
  const specToWrite = this.prepareInterfaceForWrite(spec);
21033
20843
  const existing = this.loadInterfaceSpec(spec.id);
21034
20844
  if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
21035
20845
  notices.push(
21036
- `interface "${spec.id}" already exists at ${path19.relative(this.rootDir, p)} \u2014 re-saving updates the component binding field in place (now "${spec.component}", was "${existing.component}") and never moves the file.`
20846
+ `interface "${spec.id}" already exists at ${path18.relative(this.rootDir, p)} \u2014 re-saving updates the component binding field in place (now "${spec.component}", was "${existing.component}") and never moves the file.`
21037
20847
  );
21038
20848
  }
21039
20849
  if (existing) {
@@ -21090,12 +20900,12 @@ var init_specs2 = __esm({
21090
20900
  const notices = [];
21091
20901
  const p = this.getImplementationPath(spec.id, spec.contract);
21092
20902
  this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
21093
- ensureDir(path19.dirname(p));
20903
+ ensureDir(path18.dirname(p));
21094
20904
  const specToWrite = this.prepareImplementationForWrite(spec);
21095
20905
  const existing = this.loadImplementationSpec(spec.id);
21096
20906
  if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
21097
20907
  notices.push(
21098
- `implementation "${spec.id}" already exists at ${path19.relative(this.rootDir, p)} \u2014 re-saving updates the contract binding field in place (now "${spec.contract}", was "${existing.contract}") and never moves the file.`
20908
+ `implementation "${spec.id}" already exists at ${path18.relative(this.rootDir, p)} \u2014 re-saving updates the contract binding field in place (now "${spec.contract}", was "${existing.contract}") and never moves the file.`
21099
20909
  );
21100
20910
  }
21101
20911
  if (existing) {
@@ -21136,11 +20946,11 @@ var init_specs2 = __esm({
21136
20946
  const existing = this.loadTypeSpec(spec.id);
21137
20947
  const group = spec.group || (existing ? existing.group : void 0);
21138
20948
  const p = this.getTypePath(spec.id, spec.subsystem, group);
21139
- ensureDir(path19.dirname(p));
20949
+ ensureDir(path18.dirname(p));
21140
20950
  const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
21141
20951
  if (subsystemChanged) {
21142
20952
  notices.push(
21143
- `type "${spec.id}" already exists at ${path19.relative(this.rootDir, p)} \u2014 re-saving updates fields in place and never relocates the file. The subsystem field is now "${spec.subsystem ?? "(none)"}" (was "${existing.subsystem ?? "(none)"}").`
20953
+ `type "${spec.id}" already exists at ${path18.relative(this.rootDir, p)} \u2014 re-saving updates fields in place and never relocates the file. The subsystem field is now "${spec.subsystem ?? "(none)"}" (was "${existing.subsystem ?? "(none)"}").`
21144
20954
  );
21145
20955
  }
21146
20956
  if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
@@ -21178,7 +20988,7 @@ var init_specs2 = __esm({
21178
20988
  }
21179
20989
  saveGroupSpec(spec, opts) {
21180
20990
  const p = this.getGroupPath(spec.id);
21181
- ensureDir(path19.dirname(p));
20991
+ ensureDir(path18.dirname(p));
21182
20992
  const specToWrite = this.prepareGroupForWrite(spec);
21183
20993
  const existing = this.loadGroupSpec(spec.id);
21184
20994
  if (existing) {
@@ -21256,7 +21066,7 @@ var init_specs2 = __esm({
21256
21066
  };
21257
21067
  const out = /* @__PURE__ */ new Set();
21258
21068
  const add = (p) => {
21259
- if (p) out.add(path19.resolve(p));
21069
+ if (p) out.add(path18.resolve(p));
21260
21070
  };
21261
21071
  for (const s of this.loadSubsystemSpecs()) {
21262
21072
  if (!scopeSubsystem || s.id === scopeSubsystem || s.id.startsWith(`${scopeSubsystem}::`)) {
@@ -21327,16 +21137,16 @@ var init_specs2 = __esm({
21327
21137
  const files = /* @__PURE__ */ new Set();
21328
21138
  const sysPath = this.paths.specsSystem();
21329
21139
  if (pathExists(sysPath)) {
21330
- files.add(path19.resolve(sysPath));
21140
+ files.add(path18.resolve(sysPath));
21331
21141
  }
21332
21142
  for (const group of Object.values(index.paths)) {
21333
21143
  for (const file of Object.values(group)) {
21334
- files.add(path19.resolve(file));
21144
+ files.add(path18.resolve(file));
21335
21145
  }
21336
21146
  }
21337
21147
  for (const file of files) {
21338
- if (fs16.existsSync(file)) {
21339
- snapshot.set(file, fs16.readFileSync(file, "utf8"));
21148
+ if (fs15.existsSync(file)) {
21149
+ snapshot.set(file, fs15.readFileSync(file, "utf8"));
21340
21150
  }
21341
21151
  }
21342
21152
  return snapshot;
@@ -21350,20 +21160,20 @@ var init_specs2 = __esm({
21350
21160
  const files = listSpecFiles(specsDir);
21351
21161
  const legacy = [];
21352
21162
  for (const f of files) {
21353
- const base = path19.basename(f);
21354
- const dir = path19.dirname(f);
21163
+ const base = path18.basename(f);
21164
+ const dir = path18.dirname(f);
21355
21165
  if (base === "system.yaml") {
21356
- legacy.push({ path: f, expected: path19.join(dir, ".index.yaml") });
21166
+ legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
21357
21167
  } else if (base === "subsystem.yaml") {
21358
- legacy.push({ path: f, expected: path19.join(dir, ".index.yaml") });
21168
+ legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
21359
21169
  } else if (base === "component.yaml") {
21360
- legacy.push({ path: f, expected: path19.join(dir, ".index.yaml") });
21170
+ legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
21361
21171
  } else if (base === "group.yaml") {
21362
- legacy.push({ path: f, expected: path19.join(dir, ".index.yaml") });
21172
+ legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
21363
21173
  } else if (base === "interface.yaml") {
21364
- legacy.push({ path: f, expected: path19.join(dir, ".interface.yaml") });
21174
+ legacy.push({ path: f, expected: path18.join(dir, ".interface.yaml") });
21365
21175
  } else if (base === "implementation.yaml") {
21366
- legacy.push({ path: f, expected: path19.join(dir, ".implementation.yaml") });
21176
+ legacy.push({ path: f, expected: path18.join(dir, ".implementation.yaml") });
21367
21177
  }
21368
21178
  }
21369
21179
  return legacy;
@@ -22366,18 +22176,76 @@ var init_specs2 = __esm({
22366
22176
  }
22367
22177
  });
22368
22178
 
22179
+ // src/config/loader.ts
22180
+ function loadTopologyConfig() {
22181
+ assertProjectInitialized();
22182
+ if (!pathExists(AI_PATHS.topologyConfig())) return createEmptyTopologyConfig();
22183
+ const raw = readYamlFile(AI_PATHS.topologyConfig());
22184
+ if (!raw) return createEmptyTopologyConfig();
22185
+ return TopologyConfigSchema.parse(raw);
22186
+ }
22187
+ function saveTopologyConfig(config) {
22188
+ writeYamlFile(AI_PATHS.topologyConfig(), config);
22189
+ }
22190
+ var init_loader = __esm({
22191
+ "src/config/loader.ts"() {
22192
+ "use strict";
22193
+ init_fs();
22194
+ init_yaml();
22195
+ init_models();
22196
+ init_paths();
22197
+ }
22198
+ });
22199
+
22369
22200
  // src/core/domains.ts
22370
- var domains_exports = {};
22371
- __export(domains_exports, {
22372
- addFreeStandingDomain: () => addFreeStandingDomain,
22373
- deriveSubsystemDomains: () => deriveSubsystemDomains,
22374
- findDomain: () => findDomain,
22375
- listFreeStandingDomains: () => listFreeStandingDomains,
22376
- removeFreeStandingDomain: () => removeFreeStandingDomain,
22377
- resolveDomains: () => resolveDomains
22201
+ function addFreeStandingDomain(domain) {
22202
+ const config = loadTopologyConfig();
22203
+ if (config.domains.some((d) => d.id === domain.id)) {
22204
+ throw new WaironError(`A free-standing domain "${domain.id}" already exists in .wai/topology.yaml.`);
22205
+ }
22206
+ config.domains.push(domain);
22207
+ saveTopologyConfig(config);
22208
+ }
22209
+ function removeFreeStandingDomain(id) {
22210
+ const config = loadTopologyConfig();
22211
+ const idx = config.domains.findIndex((d) => d.id === id);
22212
+ if (idx === -1) {
22213
+ throw new WaironError(
22214
+ `"${id}" is not a free-standing domain. Subsystem-backed domains are derived from the spec tree and cannot be removed here.`
22215
+ );
22216
+ }
22217
+ config.domains.splice(idx, 1);
22218
+ saveTopologyConfig(config);
22219
+ }
22220
+ var init_domains = __esm({
22221
+ "src/core/domains.ts"() {
22222
+ "use strict";
22223
+ init_loader();
22224
+ init_errors();
22225
+ }
22378
22226
  });
22227
+
22228
+ // src/core/topology.ts
22229
+ function addFreeStanding(domain) {
22230
+ addFreeStandingDomain(domain);
22231
+ }
22232
+ function removeFreeStanding(id) {
22233
+ removeFreeStandingDomain(id);
22234
+ }
22235
+ function loadConfig() {
22236
+ return loadTopologyConfig();
22237
+ }
22238
+ var init_topology = __esm({
22239
+ "src/core/topology.ts"() {
22240
+ "use strict";
22241
+ init_domains();
22242
+ init_loader();
22243
+ }
22244
+ });
22245
+
22246
+ // src/core/domain_projector.ts
22379
22247
  function rel(p) {
22380
- return path20.relative(process.cwd(), p).replace(/\\/g, "/");
22248
+ return path19.relative(process.cwd(), p).replace(/\\/g, "/");
22381
22249
  }
22382
22250
  function deriveSubsystemDomains() {
22383
22251
  const subsystems = loadSubsystemSpecs();
@@ -22396,45 +22264,210 @@ function deriveSubsystemDomains() {
22396
22264
  };
22397
22265
  });
22398
22266
  }
22399
- function listFreeStandingDomains() {
22400
- return loadTopologyConfig().domains;
22401
- }
22402
22267
  function resolveDomains() {
22403
- return [...deriveSubsystemDomains(), ...listFreeStandingDomains()];
22404
- }
22405
- function findDomain(id) {
22406
- return resolveDomains().find((d) => d.id === id);
22268
+ const derived = deriveSubsystemDomains();
22269
+ const registered = loadConfig().domains;
22270
+ return [...derived, ...registered];
22407
22271
  }
22408
- function addFreeStandingDomain(domain) {
22409
- const config = loadTopologyConfig();
22410
- if (config.domains.some((d) => d.id === domain.id)) {
22411
- throw new WaironError(`A free-standing domain "${domain.id}" already exists in .wai/topology.yaml.`);
22272
+ var path19;
22273
+ var init_domain_projector = __esm({
22274
+ "src/core/domain_projector.ts"() {
22275
+ "use strict";
22276
+ path19 = __toESM(require("path"));
22277
+ init_specs2();
22278
+ init_topology();
22412
22279
  }
22413
- if (deriveSubsystemDomains().some((d) => d.id === domain.id)) {
22414
- throw new WaironError(`Domain id "${domain.id}" collides with a subsystem-derived domain.`);
22280
+ });
22281
+
22282
+ // src/core/domain_curator.ts
22283
+ function registerDomain(domain) {
22284
+ const taken = resolveDomains().find((d) => d.id === domain.id);
22285
+ if (taken) {
22286
+ throw new WaironError(refusal(taken));
22415
22287
  }
22416
- config.domains.push(domain);
22417
- saveTopologyConfig(config);
22288
+ addFreeStanding(domain);
22418
22289
  }
22419
- function removeFreeStandingDomain(id) {
22420
- const config = loadTopologyConfig();
22421
- const idx = config.domains.findIndex((d) => d.id === id);
22422
- if (idx === -1) {
22423
- throw new WaironError(
22424
- `"${id}" is not a free-standing domain. Subsystem-backed domains are derived from the spec tree and cannot be removed here.`
22290
+ function refusal(taken) {
22291
+ return taken.boundTo ? `Domain id "${taken.id}" collides with a subsystem-derived domain.` : `A free-standing domain "${taken.id}" already exists in .wai/topology.yaml.`;
22292
+ }
22293
+ function unregisterDomain(id) {
22294
+ removeFreeStanding(id);
22295
+ }
22296
+ var init_domain_curator = __esm({
22297
+ "src/core/domain_curator.ts"() {
22298
+ "use strict";
22299
+ init_domain_projector();
22300
+ init_topology();
22301
+ init_errors();
22302
+ }
22303
+ });
22304
+
22305
+ // src/core/detection.ts
22306
+ function detectDomainCandidates(projectRoot2, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
22307
+ const candidates = /* @__PURE__ */ new Map();
22308
+ for (const c of detectGitSubmodules(projectRoot2)) {
22309
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
22310
+ }
22311
+ for (const c of detectNestedGitRepos(projectRoot2)) {
22312
+ if (!candidates.has(c.path)) {
22313
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
22314
+ }
22315
+ }
22316
+ const gitPaths = new Set(
22317
+ Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
22318
+ );
22319
+ for (const c of detectPackageRoots(projectRoot2)) {
22320
+ if (candidates.has(c.path)) continue;
22321
+ const insideGit = Array.from(gitPaths).some(
22322
+ (gp) => c.path === gp || c.path.startsWith(gp + "/")
22425
22323
  );
22324
+ if (insideGit) continue;
22325
+ candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
22426
22326
  }
22427
- config.domains.splice(idx, 1);
22428
- saveTopologyConfig(config);
22327
+ const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
22328
+ return deduplicateIds(sorted, alreadyTrackedIds);
22429
22329
  }
22430
- var path20;
22431
- var init_domains = __esm({
22432
- "src/core/domains.ts"() {
22330
+ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
22331
+ const idCount = /* @__PURE__ */ new Map();
22332
+ for (const id of existingIds) {
22333
+ idCount.set(id, (idCount.get(id) ?? 0) + 1);
22334
+ }
22335
+ for (const c of candidates) {
22336
+ idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
22337
+ }
22338
+ return candidates.map((c) => {
22339
+ if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
22340
+ const parts = c.path.split("/");
22341
+ const qualifiedId2 = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
22342
+ return { ...c, suggestedId: qualifiedId2 };
22343
+ });
22344
+ }
22345
+ function parseGitmodules(filePath) {
22346
+ const content = fs16.readFileSync(filePath, "utf-8");
22347
+ const entries = [];
22348
+ let current2 = {};
22349
+ for (const line2 of content.split("\n")) {
22350
+ const trimmed = line2.trim();
22351
+ const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
22352
+ if (headerMatch) {
22353
+ if (current2.path) entries.push(current2);
22354
+ current2 = { name: headerMatch[1] };
22355
+ continue;
22356
+ }
22357
+ const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
22358
+ if (keyVal) {
22359
+ const [, key, value] = keyVal;
22360
+ if (key === "path") current2.path = value.trim();
22361
+ if (key === "url") current2.url = value.trim();
22362
+ }
22363
+ }
22364
+ if (current2.path) entries.push(current2);
22365
+ return entries;
22366
+ }
22367
+ function detectGitSubmodules(projectRoot2) {
22368
+ const gitmodulesPath = path20.join(projectRoot2, ".gitmodules");
22369
+ if (!fs16.existsSync(gitmodulesPath)) return [];
22370
+ return parseGitmodules(gitmodulesPath).map((entry) => ({
22371
+ suggestedId: pathToId(entry.path),
22372
+ suggestedName: pathToName(entry.path),
22373
+ path: normalizePath(entry.path),
22374
+ type: "git-submodule",
22375
+ alreadyTracked: false
22376
+ }));
22377
+ }
22378
+ function detectNestedGitRepos(projectRoot2) {
22379
+ const results = [];
22380
+ walkForGit(projectRoot2, projectRoot2, 0, results);
22381
+ return results;
22382
+ }
22383
+ function walkForGit(projectRoot2, currentDir, depth, results) {
22384
+ if (depth > MAX_SCAN_DEPTH) return;
22385
+ let entries;
22386
+ try {
22387
+ entries = fs16.readdirSync(currentDir, { withFileTypes: true });
22388
+ } catch {
22389
+ return;
22390
+ }
22391
+ for (const entry of entries) {
22392
+ if (!entry.isDirectory()) continue;
22393
+ if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
22394
+ const fullPath = path20.join(currentDir, entry.name);
22395
+ const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
22396
+ if (relPath === "" || relPath === ".") continue;
22397
+ const gitPath = path20.join(fullPath, ".git");
22398
+ if (fs16.existsSync(gitPath)) {
22399
+ results.push({
22400
+ suggestedId: pathToId(relPath),
22401
+ suggestedName: pathToName(relPath),
22402
+ path: relPath,
22403
+ type: "git-repo",
22404
+ alreadyTracked: false
22405
+ });
22406
+ continue;
22407
+ }
22408
+ walkForGit(projectRoot2, fullPath, depth + 1, results);
22409
+ }
22410
+ }
22411
+ function detectPackageRoots(projectRoot2) {
22412
+ const results = [];
22413
+ walkForPackages(projectRoot2, projectRoot2, 0, results);
22414
+ return results;
22415
+ }
22416
+ function walkForPackages(projectRoot2, currentDir, depth, results) {
22417
+ if (depth > MAX_SCAN_DEPTH) return;
22418
+ let entries;
22419
+ try {
22420
+ entries = fs16.readdirSync(currentDir, { withFileTypes: true });
22421
+ } catch {
22422
+ return;
22423
+ }
22424
+ for (const entry of entries) {
22425
+ if (!entry.isDirectory()) continue;
22426
+ if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
22427
+ const fullPath = path20.join(currentDir, entry.name);
22428
+ const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
22429
+ if (relPath === "" || relPath === ".") continue;
22430
+ const hasMarker = PACKAGE_MARKERS.some((m) => fs16.existsSync(path20.join(fullPath, m)));
22431
+ if (hasMarker) {
22432
+ results.push({
22433
+ suggestedId: pathToId(relPath),
22434
+ suggestedName: pathToName(relPath),
22435
+ path: relPath,
22436
+ type: "package-root",
22437
+ alreadyTracked: false
22438
+ });
22439
+ }
22440
+ walkForPackages(projectRoot2, fullPath, depth + 1, results);
22441
+ }
22442
+ }
22443
+ function pathToId(relPath) {
22444
+ const basename15 = path20.basename(relPath);
22445
+ return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
22446
+ }
22447
+ function pathToName(relPath) {
22448
+ const id = pathToId(relPath);
22449
+ return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
22450
+ }
22451
+ function normalizePath(p) {
22452
+ return p.replace(/\\/g, "/");
22453
+ }
22454
+ var fs16, path20, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
22455
+ var init_detection = __esm({
22456
+ "src/core/detection.ts"() {
22433
22457
  "use strict";
22458
+ fs16 = __toESM(require("fs"));
22434
22459
  path20 = __toESM(require("path"));
22435
- init_loader();
22436
- init_specs2();
22437
- init_errors();
22460
+ init_defaults();
22461
+ PACKAGE_MARKERS = [
22462
+ "package.json",
22463
+ "pyproject.toml",
22464
+ "Cargo.toml",
22465
+ "go.mod",
22466
+ "build.gradle",
22467
+ "build.gradle.kts",
22468
+ "pom.xml"
22469
+ ];
22470
+ MAX_SCAN_DEPTH = 5;
22438
22471
  }
22439
22472
  });
22440
22473
 
@@ -23541,7 +23574,7 @@ function resolveAgentTopology() {
23541
23574
  }
23542
23575
  }
23543
23576
  const now = (/* @__PURE__ */ new Date()).toISOString();
23544
- for (const dom of loadTopologyConfig().domains) {
23577
+ for (const dom of loadConfig().domains) {
23545
23578
  agents.push({
23546
23579
  id: `${dom.id}-owner`,
23547
23580
  name: `${dom.name ?? dom.id} Owner`,
@@ -23622,7 +23655,7 @@ var init_agent_resolver = __esm({
23622
23655
  "use strict";
23623
23656
  path23 = __toESM(require("path"));
23624
23657
  fs18 = __toESM(require("fs"));
23625
- init_loader();
23658
+ init_topology();
23626
23659
  init_paths();
23627
23660
  init_registry();
23628
23661
  init_project_config();
@@ -24005,8 +24038,7 @@ function renderDomainsDoc() {
24005
24038
  return lines.join("\n") + "\n";
24006
24039
  }
24007
24040
  function renderWaironGuide() {
24008
- const { resolveDomains: resolveDomains2 } = (init_domains(), __toCommonJS(domains_exports));
24009
- const domains = resolveDomains2();
24041
+ const domains = resolveDomains();
24010
24042
  let projectName = "this project";
24011
24043
  try {
24012
24044
  projectName = projectConfigRepository.load()?.name ?? projectName;
@@ -24090,7 +24122,7 @@ var init_context = __esm({
24090
24122
  init_fs();
24091
24123
  init_ai_guide();
24092
24124
  init_stamp();
24093
- init_domains();
24125
+ init_domain_projector();
24094
24126
  init_project_config();
24095
24127
  CONTEXT_PATHS = {
24096
24128
  dir: () => contextDir(),
@@ -28175,6 +28207,15 @@ var init_approver = __esm({
28175
28207
  });
28176
28208
 
28177
28209
  // src/core/index.ts
28210
+ function resolveDomains2() {
28211
+ return resolveDomains();
28212
+ }
28213
+ function addDomain(domain) {
28214
+ registerDomain(domain);
28215
+ }
28216
+ function removeDomain(id) {
28217
+ unregisterDomain(id);
28218
+ }
28178
28219
  function loadProjectConfig() {
28179
28220
  return projectConfigRepository.load();
28180
28221
  }
@@ -28185,8 +28226,9 @@ var init_core = __esm({
28185
28226
  "src/core/index.ts"() {
28186
28227
  "use strict";
28187
28228
  init_project_config();
28229
+ init_domain_projector();
28230
+ init_domain_curator();
28188
28231
  init_detection();
28189
- init_domains();
28190
28232
  init_templates();
28191
28233
  init_validation();
28192
28234
  init_extensions();
@@ -29047,7 +29089,7 @@ function createMcpServer(options = {}) {
29047
29089
  },
29048
29090
  () => {
29049
29091
  try {
29050
- return json(resolveDomains());
29092
+ return json(resolveDomains2());
29051
29093
  } catch (e) {
29052
29094
  return errText(String(e));
29053
29095
  }
@@ -30299,7 +30341,7 @@ var init_server = __esm({
30299
30341
  init_paths();
30300
30342
  init_validation();
30301
30343
  init_provision();
30302
- init_domains();
30344
+ init_core();
30303
30345
  init_authoring();
30304
30346
  init_variants();
30305
30347
  init_agent_resolver();
@@ -31062,6 +31104,18 @@ function generateAll2(agents, config, options) {
31062
31104
  function resolveExpectedOutputPaths2(agents, config) {
31063
31105
  return resolveExpectedOutputPaths(agents, config);
31064
31106
  }
31107
+ function resolveDomains3() {
31108
+ return resolveDomains2();
31109
+ }
31110
+ function addDomain2(domain) {
31111
+ addDomain(domain);
31112
+ }
31113
+ function removeDomain2(id) {
31114
+ removeDomain(id);
31115
+ }
31116
+ function detectDomainCandidates2(projectRoot2, trackedPaths, trackedIds) {
31117
+ return detectDomainCandidates(projectRoot2, trackedPaths, trackedIds);
31118
+ }
31065
31119
  async function runSubsystemAdd(id, options = {}) {
31066
31120
  logger.header("wairon subsystem add");
31067
31121
  if (!projectConfigExists2()) {
@@ -32730,12 +32784,10 @@ async function filteredCheckbox(config) {
32730
32784
 
32731
32785
  // src/commands/domains.ts
32732
32786
  init_paths();
32733
- init_detection();
32734
- init_domains();
32735
32787
  init_domain();
32736
32788
  async function runDomainsList() {
32737
32789
  assertProjectInitialized();
32738
- const domains = resolveDomains();
32790
+ const domains = resolveDomains3();
32739
32791
  if (domains.length === 0) {
32740
32792
  logger.info("No domains yet.");
32741
32793
  logger.info("Define subsystems in the spec tree, or run `wairon domains scan --add` for free-standing domains.");
@@ -32760,10 +32812,10 @@ function printDomain(domain) {
32760
32812
  async function runDomainsScan(options = {}) {
32761
32813
  assertProjectInitialized();
32762
32814
  const projectRoot2 = fromProjectRoot();
32763
- const existing = resolveDomains();
32815
+ const existing = resolveDomains3();
32764
32816
  const trackedPaths = new Set(existing.map((d) => d.path).filter((p) => !!p));
32765
32817
  const trackedIds = new Set(existing.map((d) => d.id));
32766
- const candidates = detectDomainCandidates(projectRoot2, trackedPaths, trackedIds);
32818
+ const candidates = detectDomainCandidates2(projectRoot2, trackedPaths, trackedIds);
32767
32819
  const newCandidates = candidates.filter((c) => !c.alreadyTracked && !trackedIds.has(c.suggestedId));
32768
32820
  if (newCandidates.length === 0) {
32769
32821
  logger.success("No new domain candidates found.");
@@ -32804,7 +32856,7 @@ async function runDomainsScan(options = {}) {
32804
32856
  ownedPaths: [`${candidate.path}/**`]
32805
32857
  });
32806
32858
  try {
32807
- addFreeStandingDomain(domain);
32859
+ addDomain2(domain);
32808
32860
  logger.success(`Added free-standing domain: ${domain.id} (${candidate.path})`);
32809
32861
  added++;
32810
32862
  } catch (err) {
@@ -32854,13 +32906,13 @@ async function runDomainsAdd(options = {}) {
32854
32906
  path: domainPath.trim() || void 0,
32855
32907
  ownedPaths
32856
32908
  });
32857
- addFreeStandingDomain(domain);
32909
+ addDomain2(domain);
32858
32910
  logger.success(`Free-standing domain "${domain.id}" added to .wai/topology.yaml.`);
32859
32911
  logger.info("Run `wairon generate` to produce its owner agent.");
32860
32912
  }
32861
32913
  async function runDomainsRemove(id) {
32862
32914
  assertProjectInitialized();
32863
- const domain = findDomain(id);
32915
+ const domain = resolveDomains3().find((d) => d.id === id);
32864
32916
  if (!domain) {
32865
32917
  logger.error(`Domain "${id}" not found.`);
32866
32918
  process.exit(1);
@@ -32882,7 +32934,7 @@ async function runDomainsRemove(id) {
32882
32934
  logger.info("Cancelled.");
32883
32935
  return;
32884
32936
  }
32885
- removeFreeStandingDomain(id);
32937
+ removeDomain2(id);
32886
32938
  logger.success(`Domain "${id}" removed. Run \`wairon generate\` to refresh agent files.`);
32887
32939
  }
32888
32940