@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 +657 -605
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +24740 -26042
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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/
|
|
1574
|
-
function
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
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
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
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
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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
|
-
|
|
1633
|
-
|
|
1628
|
+
});
|
|
1629
|
+
|
|
1630
|
+
// src/core/lockfile.ts
|
|
1631
|
+
function lockPath() {
|
|
1632
|
+
return aiDir("lock.json");
|
|
1634
1633
|
}
|
|
1635
|
-
function
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
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
|
|
1647
|
-
const
|
|
1648
|
-
|
|
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
|
|
1652
|
-
if (depth > MAX_SCAN_DEPTH) return;
|
|
1653
|
-
let entries;
|
|
1646
|
+
function readLockRecord() {
|
|
1654
1647
|
try {
|
|
1655
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
1712
|
-
const
|
|
1713
|
-
return
|
|
1660
|
+
function normalizeRecord(raw) {
|
|
1661
|
+
const record2 = raw;
|
|
1662
|
+
return { ...record2, lockedBy: normalizeApprover(record2.lockedBy) };
|
|
1714
1663
|
}
|
|
1715
|
-
function
|
|
1716
|
-
const
|
|
1717
|
-
|
|
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
|
|
1720
|
-
|
|
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
|
|
1723
|
-
var
|
|
1724
|
-
"src/core/
|
|
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
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
4087
|
+
path11.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
|
|
4278
4088
|
// src/core & dist/cli
|
|
4279
|
-
|
|
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 (
|
|
4284
|
-
return
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4295
4105
|
}
|
|
4296
|
-
var
|
|
4106
|
+
var fs9, path11, CANVAS_TEMPLATE;
|
|
4297
4107
|
var init_canvas = __esm({
|
|
4298
4108
|
"src/core/canvas.ts"() {
|
|
4299
4109
|
"use strict";
|
|
4300
|
-
|
|
4301
|
-
|
|
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 =
|
|
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(
|
|
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 =
|
|
8321
|
+
const abs = path12.resolve(packDir);
|
|
8512
8322
|
let isFile = false;
|
|
8513
8323
|
try {
|
|
8514
|
-
isFile =
|
|
8324
|
+
isFile = fs10.statSync(abs).isFile();
|
|
8515
8325
|
} catch {
|
|
8516
8326
|
}
|
|
8517
|
-
const entries = isFile ? [[
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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,
|
|
8423
|
+
const manifest = readManifest(entryFile, path12.dirname(entryFile));
|
|
8614
8424
|
const version = manifest.version && manifest.version.length > 0 ? manifest.version : UNVERSIONED;
|
|
8615
|
-
const dest =
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
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(
|
|
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
|
-
|
|
8642
|
-
const parent =
|
|
8643
|
-
if (
|
|
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 (
|
|
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,
|
|
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
|
-
|
|
8657
|
-
|
|
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 ??
|
|
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 =
|
|
8689
|
-
if (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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(".") ||
|
|
8565
|
+
const pathLike = ref.startsWith(".") || path13.isAbsolute(ref) || isYamlPath(ref);
|
|
8756
8566
|
if (!pathLike) return ref;
|
|
8757
|
-
const resolved =
|
|
8758
|
-
if (
|
|
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)(
|
|
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,
|
|
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,
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
8783
|
+
const base = path13.join(projectRoot2, ".wai", "packs", selection.name);
|
|
8974
8784
|
if (selection.version) {
|
|
8975
|
-
const pinned =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
8808
|
+
fs11 = __toESM(require("fs"));
|
|
8999
8809
|
os4 = __toESM(require("os"));
|
|
9000
|
-
|
|
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 = [
|
|
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 =
|
|
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
|
-
|
|
16220
|
-
|
|
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 (
|
|
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 ||
|
|
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,
|
|
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(
|
|
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(
|
|
16094
|
+
const key = pathKey(path14.relative(projectRoot2, absolute));
|
|
16285
16095
|
if (seen.has(key) || isExcluded(key)) return;
|
|
16286
|
-
if (!EXTENSION_LANGUAGE[
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 (
|
|
16311
|
-
const absolute =
|
|
16312
|
-
if (
|
|
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 =
|
|
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 (
|
|
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 =
|
|
16347
|
-
if (
|
|
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 =
|
|
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 =
|
|
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[
|
|
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 =
|
|
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
|
|
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
|
-
|
|
16454
|
-
|
|
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 ??
|
|
17034
|
+
return process.env.WAIRON_VARIANTS_DIR ?? path15.join(os5.homedir(), ".wairon", "variants");
|
|
17225
17035
|
}
|
|
17226
17036
|
function builtinVariantsDir() {
|
|
17227
17037
|
const candidates = [
|
|
17228
|
-
|
|
17038
|
+
path15.resolve(__dirname, "..", "templates", "variants"),
|
|
17229
17039
|
// src/core & dist/cli
|
|
17230
|
-
|
|
17040
|
+
path15.resolve(__dirname, "templates", "variants")
|
|
17231
17041
|
// dist (library entry)
|
|
17232
17042
|
];
|
|
17233
|
-
return candidates.find((dir) =>
|
|
17043
|
+
return candidates.find((dir) => fs13.existsSync(dir)) ?? candidates[0];
|
|
17234
17044
|
}
|
|
17235
17045
|
function projectVariantsDir() {
|
|
17236
|
-
return
|
|
17046
|
+
return path15.join(getProjectRoot(), ".wai", "variants");
|
|
17237
17047
|
}
|
|
17238
17048
|
function variantFiles(dir) {
|
|
17239
17049
|
let entries;
|
|
17240
17050
|
try {
|
|
17241
|
-
entries =
|
|
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) =>
|
|
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
|
|
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
|
-
|
|
17168
|
+
fs13 = __toESM(require("fs"));
|
|
17359
17169
|
os5 = __toESM(require("os"));
|
|
17360
|
-
|
|
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
|
|
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 (!
|
|
17714
|
+
if (!fs14.existsSync(dir)) return [];
|
|
17905
17715
|
const out = [];
|
|
17906
|
-
for (const file of
|
|
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(
|
|
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
|
-
|
|
17921
|
-
const p =
|
|
17730
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
17731
|
+
const p = path16.join(dir, snapshotFilename(snapshot.projectName));
|
|
17922
17732
|
const next = SurfaceSnapshotSchema.parse(snapshot);
|
|
17923
|
-
if (
|
|
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 =
|
|
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 ||
|
|
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 =
|
|
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 =
|
|
17970
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
18004
|
-
if (!
|
|
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 =
|
|
17817
|
+
const body = fs14.readFileSync(resolved, "utf8");
|
|
18008
17818
|
let snapshot;
|
|
18009
17819
|
if (isOpenApiDocument(body)) {
|
|
18010
|
-
const projectName =
|
|
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
|
|
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
|
-
|
|
18078
|
-
|
|
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 ?
|
|
18194
|
+
const ceiling = reach?.topRoot ? path17.resolve(reach.topRoot) : void 0;
|
|
18385
18195
|
const chain = [];
|
|
18386
|
-
let top =
|
|
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 =
|
|
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 =
|
|
18438
|
-
return rel2 === "" || !rel2.startsWith("..") && !
|
|
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) =>
|
|
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
|
|
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
|
-
|
|
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 =
|
|
19226
|
-
const f =
|
|
19227
|
-
return f === d || f.startsWith(d +
|
|
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 =
|
|
19040
|
+
let existing = path18.resolve(target);
|
|
19231
19041
|
const rest = [];
|
|
19232
19042
|
for (; ; ) {
|
|
19233
19043
|
try {
|
|
19234
|
-
|
|
19044
|
+
fs15.lstatSync(existing);
|
|
19235
19045
|
break;
|
|
19236
19046
|
} catch {
|
|
19237
|
-
const up =
|
|
19238
|
-
if (up === existing) return
|
|
19239
|
-
rest.unshift(
|
|
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
|
|
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) ??
|
|
19060
|
+
return canonicalPath(dir) ?? path18.resolve(dir);
|
|
19251
19061
|
}
|
|
19252
19062
|
function projectPathEscapesRoot(projectRoot2, projectPath, resolvedChildDir) {
|
|
19253
|
-
if (
|
|
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 =
|
|
19260
|
-
const resolved =
|
|
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 =
|
|
19081
|
+
childResolved = path18.resolve(childRoot);
|
|
19272
19082
|
} catch {
|
|
19273
19083
|
return null;
|
|
19274
19084
|
}
|
|
19275
|
-
const bound2 = ceiling ?
|
|
19276
|
-
let dir =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
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(
|
|
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 (
|
|
19433
|
-
const rel2 =
|
|
19434
|
-
const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${
|
|
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 (
|
|
19470
|
-
if (!
|
|
19471
|
-
ensureDir(
|
|
19472
|
-
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
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 =
|
|
19827
|
+
const dir = path18.join(rootDir, ".wai", "surfaces");
|
|
20018
19828
|
if (!pathExists(dir)) return [];
|
|
20019
19829
|
const keys = [];
|
|
20020
|
-
for (const file of
|
|
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(
|
|
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) =>
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
20122
|
-
|
|
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 =
|
|
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 =
|
|
20201
|
-
const local = rawId ?? (stem2.startsWith(".") ?
|
|
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 =
|
|
20021
|
+
const systemYaml = path18.normalize(projectPaths.specsSystem());
|
|
20212
20022
|
const localSubprojects = [];
|
|
20213
20023
|
for (const file of files) {
|
|
20214
|
-
const normFile =
|
|
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) =>
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
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
|
|
20309
|
+
return path18.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
|
|
20500
20310
|
}
|
|
20501
|
-
return
|
|
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
|
|
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 =
|
|
20336
|
+
const subDir = path18.dirname(subPath);
|
|
20527
20337
|
if (subPath.endsWith(".index.yaml")) {
|
|
20528
|
-
return
|
|
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
|
|
20342
|
+
return path18.join(this.paths.specsComponentsDir(), `${id}.yaml`);
|
|
20533
20343
|
}
|
|
20534
20344
|
const targetSubsystem = subsystemId || "default";
|
|
20535
|
-
return
|
|
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 =
|
|
20371
|
+
const compDir = path18.dirname(compPath);
|
|
20562
20372
|
if (compPath.endsWith(".index.yaml")) {
|
|
20563
|
-
return
|
|
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
|
|
20377
|
+
return path18.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
|
|
20568
20378
|
}
|
|
20569
20379
|
const targetComponent = componentId || "default";
|
|
20570
|
-
return
|
|
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 =
|
|
20406
|
+
const intfDir = path18.dirname(intfPath);
|
|
20597
20407
|
if (intfPath.endsWith(".interface.yaml")) {
|
|
20598
|
-
return
|
|
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
|
|
20412
|
+
return path18.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
|
|
20603
20413
|
}
|
|
20604
20414
|
const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
|
|
20605
|
-
return
|
|
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
|
|
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 =
|
|
20459
|
+
const subDir = path18.dirname(subPath);
|
|
20650
20460
|
if (subPath.endsWith(".index.yaml")) {
|
|
20651
|
-
return
|
|
20461
|
+
return path18.join(subDir, "types", `${localId}.yaml`);
|
|
20652
20462
|
}
|
|
20653
20463
|
}
|
|
20654
|
-
return
|
|
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 =
|
|
20498
|
+
const subDir = path18.dirname(subPath);
|
|
20689
20499
|
if (subPath.endsWith(".index.yaml")) {
|
|
20690
|
-
return
|
|
20500
|
+
return path18.join(subDir, "types", localId, ".index.yaml");
|
|
20691
20501
|
}
|
|
20692
20502
|
}
|
|
20693
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
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 ${
|
|
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 =
|
|
20947
|
-
return
|
|
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 =
|
|
20951
|
-
return
|
|
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(
|
|
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 ${
|
|
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(
|
|
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 ${
|
|
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(
|
|
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 ${
|
|
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(
|
|
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 ${
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
21144
|
+
files.add(path18.resolve(file));
|
|
21335
21145
|
}
|
|
21336
21146
|
}
|
|
21337
21147
|
for (const file of files) {
|
|
21338
|
-
if (
|
|
21339
|
-
snapshot.set(file,
|
|
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 =
|
|
21354
|
-
const dir =
|
|
21163
|
+
const base = path18.basename(f);
|
|
21164
|
+
const dir = path18.dirname(f);
|
|
21355
21165
|
if (base === "system.yaml") {
|
|
21356
|
-
legacy.push({ path: f, expected:
|
|
21166
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21357
21167
|
} else if (base === "subsystem.yaml") {
|
|
21358
|
-
legacy.push({ path: f, expected:
|
|
21168
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21359
21169
|
} else if (base === "component.yaml") {
|
|
21360
|
-
legacy.push({ path: f, expected:
|
|
21170
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21361
21171
|
} else if (base === "group.yaml") {
|
|
21362
|
-
legacy.push({ path: f, expected:
|
|
21172
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21363
21173
|
} else if (base === "interface.yaml") {
|
|
21364
|
-
legacy.push({ path: f, expected:
|
|
21174
|
+
legacy.push({ path: f, expected: path18.join(dir, ".interface.yaml") });
|
|
21365
21175
|
} else if (base === "implementation.yaml") {
|
|
21366
|
-
legacy.push({ path: f, expected:
|
|
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
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
22373
|
-
|
|
22374
|
-
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
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
|
|
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
|
-
|
|
22404
|
-
|
|
22405
|
-
|
|
22406
|
-
return resolveDomains().find((d) => d.id === id);
|
|
22268
|
+
const derived = deriveSubsystemDomains();
|
|
22269
|
+
const registered = loadConfig().domains;
|
|
22270
|
+
return [...derived, ...registered];
|
|
22407
22271
|
}
|
|
22408
|
-
|
|
22409
|
-
|
|
22410
|
-
|
|
22411
|
-
|
|
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
|
-
|
|
22414
|
-
|
|
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
|
-
|
|
22417
|
-
saveTopologyConfig(config);
|
|
22288
|
+
addFreeStanding(domain);
|
|
22418
22289
|
}
|
|
22419
|
-
function
|
|
22420
|
-
|
|
22421
|
-
|
|
22422
|
-
|
|
22423
|
-
|
|
22424
|
-
|
|
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
|
-
|
|
22428
|
-
|
|
22327
|
+
const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
|
|
22328
|
+
return deduplicateIds(sorted, alreadyTrackedIds);
|
|
22429
22329
|
}
|
|
22430
|
-
|
|
22431
|
-
|
|
22432
|
-
|
|
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
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
32937
|
+
removeDomain2(id);
|
|
32886
32938
|
logger.success(`Domain "${id}" removed. Run \`wairon generate\` to refresh agent files.`);
|
|
32887
32939
|
}
|
|
32888
32940
|
|