@wairon/cli 5.1.1-dev.56 → 5.1.1-dev.58
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 +795 -722
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +24756 -26040
- 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.58";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -546,6 +546,21 @@ var init_yaml = __esm({
|
|
|
546
546
|
});
|
|
547
547
|
|
|
548
548
|
// src/models/execution.ts
|
|
549
|
+
function summarize(budget, profile) {
|
|
550
|
+
const lines = [
|
|
551
|
+
`- **Work shape**: ${profile.breadth} breadth, ${profile.reasoningDepth} reasoning${profile.writes ? "" : ", read-only"}${profile.delegates ? ", delegating" : ""}`,
|
|
552
|
+
`- **Why**: ${profile.rationale}`
|
|
553
|
+
];
|
|
554
|
+
if (budget.modelTier) lines.push(`- **Capability tier**: ${budget.modelTier}`);
|
|
555
|
+
if (budget.effort) lines.push(`- **Effort**: ${budget.effort}`);
|
|
556
|
+
if (budget.maxTurns !== void 0) {
|
|
557
|
+
lines.push(`- **Turn ceiling**: ${budget.maxTurns} (a circuit breaker \u2014 hitting it should read as a scoping error, not a limit to work up to)`);
|
|
558
|
+
}
|
|
559
|
+
lines.push(`- **Tool grant**: ${budget.toolClass}`);
|
|
560
|
+
lines.push(`- **May delegate further**: ${budget.allowNestedDelegation ? "yes" : "no"}`);
|
|
561
|
+
lines.push(`- **MCP access**: ${budget.mcp}`);
|
|
562
|
+
return lines;
|
|
563
|
+
}
|
|
549
564
|
var import_zod, WorkBreadthSchema, ReasoningDepthSchema, ExecutionProfileSchema, ModelTierSchema, EffortTierSchema, ToolClassSchema, McpAccessSchema, ExecutionBudgetSchema, BudgetTierSchema, BUDGET_TIER_DESCRIPTIONS, ExecutionConfigSchema;
|
|
550
565
|
var init_execution = __esm({
|
|
551
566
|
"src/models/execution.ts"() {
|
|
@@ -1570,172 +1585,162 @@ var init_paths = __esm({
|
|
|
1570
1585
|
}
|
|
1571
1586
|
});
|
|
1572
1587
|
|
|
1573
|
-
// src/
|
|
1574
|
-
function
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1588
|
+
// src/utils/canonical-json.ts
|
|
1589
|
+
function canonicalize(value) {
|
|
1590
|
+
return JSON.stringify(sortKeys(value));
|
|
1591
|
+
}
|
|
1592
|
+
function compareOrdinal(a, b) {
|
|
1593
|
+
if (a < b) return -1;
|
|
1594
|
+
return a > b ? 1 : 0;
|
|
1595
|
+
}
|
|
1596
|
+
function sortKeys(v) {
|
|
1597
|
+
if (Array.isArray(v)) return v.map(sortKeys);
|
|
1598
|
+
if (v && typeof v === "object") {
|
|
1599
|
+
const src = v;
|
|
1600
|
+
const out = {};
|
|
1601
|
+
for (const k of Object.keys(src).sort()) {
|
|
1602
|
+
if (k === "createdAt" || k === "updatedAt") continue;
|
|
1603
|
+
out[k] = sortKeys(src[k]);
|
|
1582
1604
|
}
|
|
1605
|
+
return out;
|
|
1583
1606
|
}
|
|
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);
|
|
1607
|
+
return v;
|
|
1597
1608
|
}
|
|
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);
|
|
1609
|
+
var init_canonical_json = __esm({
|
|
1610
|
+
"src/utils/canonical-json.ts"() {
|
|
1611
|
+
"use strict";
|
|
1605
1612
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
});
|
|
1613
|
+
});
|
|
1614
|
+
|
|
1615
|
+
// src/core/statehash.ts
|
|
1616
|
+
function inIdentityOrder(specs) {
|
|
1617
|
+
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
1618
|
}
|
|
1613
|
-
function
|
|
1614
|
-
const
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1619
|
+
function computeStateId() {
|
|
1620
|
+
const tree = {
|
|
1621
|
+
system: loadSystemSpec(),
|
|
1622
|
+
subsystems: inIdentityOrder(loadSubsystemSpecs()),
|
|
1623
|
+
components: inIdentityOrder(loadComponentSpecs()),
|
|
1624
|
+
interfaces: inIdentityOrder(loadInterfaceSpecs()),
|
|
1625
|
+
implementations: inIdentityOrder(loadImplementationSpecs()),
|
|
1626
|
+
types: inIdentityOrder(loadTypeSpecs())
|
|
1627
|
+
};
|
|
1628
|
+
const digest2 = crypto.createHash("sha256").update(canonicalize(tree)).digest("hex");
|
|
1629
|
+
return { algorithm: CONTENT_ALGORITHM, digest: digest2 };
|
|
1630
|
+
}
|
|
1631
|
+
function stateIdEquals(a, b) {
|
|
1632
|
+
return !!a && !!b && a.algorithm === b.algorithm && a.digest === b.digest;
|
|
1633
|
+
}
|
|
1634
|
+
var crypto, CONTENT_ALGORITHM;
|
|
1635
|
+
var init_statehash = __esm({
|
|
1636
|
+
"src/core/statehash.ts"() {
|
|
1637
|
+
"use strict";
|
|
1638
|
+
crypto = __toESM(require("crypto"));
|
|
1639
|
+
init_specs2();
|
|
1640
|
+
init_canonical_json();
|
|
1641
|
+
CONTENT_ALGORITHM = "sha256";
|
|
1631
1642
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1643
|
+
});
|
|
1644
|
+
|
|
1645
|
+
// src/core/lockfile.ts
|
|
1646
|
+
function lockPath() {
|
|
1647
|
+
return aiDir("lock.json");
|
|
1634
1648
|
}
|
|
1635
|
-
function
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
type: "git-submodule",
|
|
1643
|
-
alreadyTracked: false
|
|
1644
|
-
}));
|
|
1649
|
+
function normalizeApprover(value) {
|
|
1650
|
+
if (value && typeof value === "object" && typeof value.id === "string") {
|
|
1651
|
+
const v = value;
|
|
1652
|
+
const source = v.source === "git" || v.source === "hosted" || v.source === "os" ? v.source : "legacy";
|
|
1653
|
+
return { id: v.id, ...v.name ? { name: v.name } : {}, source };
|
|
1654
|
+
}
|
|
1655
|
+
return { id: typeof value === "string" && value ? value : "unknown", source: "legacy" };
|
|
1645
1656
|
}
|
|
1646
|
-
function
|
|
1647
|
-
const
|
|
1648
|
-
|
|
1649
|
-
return results;
|
|
1657
|
+
function describeApprover(who) {
|
|
1658
|
+
const label = who.name ? `${who.name} (${who.id})` : who.id;
|
|
1659
|
+
return who.source === "hosted" ? `${label} [authenticated]` : label;
|
|
1650
1660
|
}
|
|
1651
|
-
function
|
|
1652
|
-
if (depth > MAX_SCAN_DEPTH) return;
|
|
1653
|
-
let entries;
|
|
1661
|
+
function readLockRecord() {
|
|
1654
1662
|
try {
|
|
1655
|
-
|
|
1663
|
+
return normalizeRecord(JSON.parse(fs7.readFileSync(lockPath(), "utf8")));
|
|
1656
1664
|
} 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);
|
|
1665
|
+
return null;
|
|
1677
1666
|
}
|
|
1678
1667
|
}
|
|
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;
|
|
1668
|
+
function readLockRecordAt(root) {
|
|
1687
1669
|
try {
|
|
1688
|
-
|
|
1670
|
+
return normalizeRecord(JSON.parse(fs7.readFileSync(aiDirAt(root, "lock.json"), "utf8")));
|
|
1689
1671
|
} 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);
|
|
1672
|
+
return null;
|
|
1709
1673
|
}
|
|
1710
1674
|
}
|
|
1711
|
-
function
|
|
1712
|
-
const
|
|
1713
|
-
return
|
|
1675
|
+
function normalizeRecord(raw) {
|
|
1676
|
+
const record2 = raw;
|
|
1677
|
+
return { ...record2, lockedBy: normalizeApprover(record2.lockedBy) };
|
|
1714
1678
|
}
|
|
1715
|
-
function
|
|
1716
|
-
const
|
|
1717
|
-
|
|
1679
|
+
function writeLockRecord(record2) {
|
|
1680
|
+
const p = lockPath();
|
|
1681
|
+
fs7.mkdirSync(path8.dirname(p), { recursive: true });
|
|
1682
|
+
const tmp = `${p}.tmp`;
|
|
1683
|
+
fs7.writeFileSync(tmp, JSON.stringify(withSortedMaps(record2), null, 2) + "\n");
|
|
1684
|
+
fs7.renameSync(tmp, p);
|
|
1718
1685
|
}
|
|
1719
|
-
function
|
|
1720
|
-
|
|
1686
|
+
function withSortedMaps(record2) {
|
|
1687
|
+
const sorted = (m) => {
|
|
1688
|
+
if (!m) return void 0;
|
|
1689
|
+
const out = {};
|
|
1690
|
+
for (const k of Object.keys(m).sort()) out[k] = m[k];
|
|
1691
|
+
return out;
|
|
1692
|
+
};
|
|
1693
|
+
const specs = sorted(record2.specs);
|
|
1694
|
+
const children = sorted(record2.children);
|
|
1695
|
+
return {
|
|
1696
|
+
...record2,
|
|
1697
|
+
...specs ? { specs } : {},
|
|
1698
|
+
...children ? { children } : {}
|
|
1699
|
+
};
|
|
1721
1700
|
}
|
|
1722
|
-
var fs7, path8
|
|
1723
|
-
var
|
|
1724
|
-
"src/core/
|
|
1701
|
+
var fs7, path8;
|
|
1702
|
+
var init_lockfile = __esm({
|
|
1703
|
+
"src/core/lockfile.ts"() {
|
|
1725
1704
|
"use strict";
|
|
1726
1705
|
fs7 = __toESM(require("fs"));
|
|
1727
1706
|
path8 = __toESM(require("path"));
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1707
|
+
init_fs();
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
|
|
1711
|
+
// src/core/spec-files.ts
|
|
1712
|
+
function readSpecFile(filePath) {
|
|
1713
|
+
return readYamlFile(filePath);
|
|
1714
|
+
}
|
|
1715
|
+
function writeSpecFile(filePath, document) {
|
|
1716
|
+
writeYamlFile(filePath, document);
|
|
1717
|
+
}
|
|
1718
|
+
function listSpecFiles(specsDir) {
|
|
1719
|
+
return listFilesRecursive(specsDir, SPEC_FILE_EXTENSION);
|
|
1720
|
+
}
|
|
1721
|
+
function removeSpecFile(filePath, specsRoot) {
|
|
1722
|
+
if (!fs8.existsSync(filePath)) return false;
|
|
1723
|
+
fs8.unlinkSync(filePath);
|
|
1724
|
+
pruneEmptyDirs(path9.dirname(filePath), path9.resolve(specsRoot));
|
|
1725
|
+
return true;
|
|
1726
|
+
}
|
|
1727
|
+
function pruneEmptyDirs(dir, specsRoot) {
|
|
1728
|
+
let at = dir;
|
|
1729
|
+
while (at !== specsRoot && at.startsWith(specsRoot)) {
|
|
1730
|
+
if (!fs8.existsSync(at) || fs8.readdirSync(at).length > 0) return;
|
|
1731
|
+
fs8.rmdirSync(at);
|
|
1732
|
+
at = path9.dirname(at);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
var fs8, path9, SPEC_FILE_EXTENSION;
|
|
1736
|
+
var init_spec_files = __esm({
|
|
1737
|
+
"src/core/spec-files.ts"() {
|
|
1738
|
+
"use strict";
|
|
1739
|
+
fs8 = __toESM(require("fs"));
|
|
1740
|
+
path9 = __toESM(require("path"));
|
|
1741
|
+
init_fs();
|
|
1742
|
+
init_yaml();
|
|
1743
|
+
SPEC_FILE_EXTENSION = ".yaml";
|
|
1739
1744
|
}
|
|
1740
1745
|
});
|
|
1741
1746
|
|
|
@@ -3295,7 +3300,7 @@ function hasFunctionBody(facts, symbol) {
|
|
|
3295
3300
|
}
|
|
3296
3301
|
function resolveImport(fromFile, specifier, knownPaths) {
|
|
3297
3302
|
if (!specifier.startsWith(".")) return void 0;
|
|
3298
|
-
const joined = pathKey(
|
|
3303
|
+
const joined = pathKey(path10.posix.normalize(path10.posix.join(path10.posix.dirname(fromFile), specifier)));
|
|
3299
3304
|
const candidates = [
|
|
3300
3305
|
joined,
|
|
3301
3306
|
joined.replace(/\.js$/, ".ts"),
|
|
@@ -3311,11 +3316,11 @@ function resolveImport(fromFile, specifier, knownPaths) {
|
|
|
3311
3316
|
}
|
|
3312
3317
|
return void 0;
|
|
3313
3318
|
}
|
|
3314
|
-
var
|
|
3319
|
+
var path10, NO_DECLARED_TYPES;
|
|
3315
3320
|
var init_code_model = __esm({
|
|
3316
3321
|
"src/models/code-model.ts"() {
|
|
3317
3322
|
"use strict";
|
|
3318
|
-
|
|
3323
|
+
path10 = __toESM(require("path"));
|
|
3319
3324
|
NO_DECLARED_TYPES = [];
|
|
3320
3325
|
}
|
|
3321
3326
|
});
|
|
@@ -3356,186 +3361,6 @@ var init_models = __esm({
|
|
|
3356
3361
|
}
|
|
3357
3362
|
});
|
|
3358
3363
|
|
|
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
3364
|
// src/core/narrative-labels.ts
|
|
3540
3365
|
function resolveNarrativeLabels(methodName, steps) {
|
|
3541
3366
|
const errors = [];
|
|
@@ -4274,14 +4099,14 @@ function embedJson(value) {
|
|
|
4274
4099
|
}
|
|
4275
4100
|
function loadCytoscapeLib() {
|
|
4276
4101
|
const candidates = [
|
|
4277
|
-
|
|
4102
|
+
path11.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
|
|
4278
4103
|
// src/core & dist/cli
|
|
4279
|
-
|
|
4104
|
+
path11.resolve(__dirname, "templates", "canvas", "cytoscape.min.js")
|
|
4280
4105
|
// dist (library entry)
|
|
4281
4106
|
];
|
|
4282
4107
|
for (const p of candidates) {
|
|
4283
|
-
if (
|
|
4284
|
-
return
|
|
4108
|
+
if (fs9.existsSync(p)) {
|
|
4109
|
+
return fs9.readFileSync(p, "utf-8").replace(/<\/script/gi, "<\\/script");
|
|
4285
4110
|
}
|
|
4286
4111
|
}
|
|
4287
4112
|
throw new Error("Vendored cytoscape bundle not found (templates/canvas/cytoscape.min.js) \u2014 the wairon installation is incomplete.");
|
|
@@ -4293,12 +4118,12 @@ function renderCanvasHtml(model) {
|
|
|
4293
4118
|
function escapeHtml(s) {
|
|
4294
4119
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4295
4120
|
}
|
|
4296
|
-
var
|
|
4121
|
+
var fs9, path11, CANVAS_TEMPLATE;
|
|
4297
4122
|
var init_canvas = __esm({
|
|
4298
4123
|
"src/core/canvas.ts"() {
|
|
4299
4124
|
"use strict";
|
|
4300
|
-
|
|
4301
|
-
|
|
4125
|
+
fs9 = __toESM(require("fs"));
|
|
4126
|
+
path11 = __toESM(require("path"));
|
|
4302
4127
|
init_specs2();
|
|
4303
4128
|
init_models();
|
|
4304
4129
|
init_diagram_export();
|
|
@@ -8493,7 +8318,7 @@ function packStoreDir() {
|
|
|
8493
8318
|
function packFiles(dir, prefix = "") {
|
|
8494
8319
|
let entries;
|
|
8495
8320
|
try {
|
|
8496
|
-
entries =
|
|
8321
|
+
entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
8497
8322
|
} catch {
|
|
8498
8323
|
return [];
|
|
8499
8324
|
}
|
|
@@ -8501,25 +8326,25 @@ function packFiles(dir, prefix = "") {
|
|
|
8501
8326
|
for (const e of entries) {
|
|
8502
8327
|
if (DIGEST_EXCLUDED.has(e.name)) continue;
|
|
8503
8328
|
const rel2 = prefix ? `${prefix}/${e.name}` : e.name;
|
|
8504
|
-
if (e.isDirectory()) out.push(...packFiles(
|
|
8329
|
+
if (e.isDirectory()) out.push(...packFiles(path12.join(dir, e.name), rel2));
|
|
8505
8330
|
else if (e.isFile()) out.push(rel2);
|
|
8506
8331
|
}
|
|
8507
8332
|
return out.sort();
|
|
8508
8333
|
}
|
|
8509
8334
|
function computePackDigest(packDir) {
|
|
8510
8335
|
const hash = crypto2.createHash("sha256");
|
|
8511
|
-
const abs =
|
|
8336
|
+
const abs = path12.resolve(packDir);
|
|
8512
8337
|
let isFile = false;
|
|
8513
8338
|
try {
|
|
8514
|
-
isFile =
|
|
8339
|
+
isFile = fs10.statSync(abs).isFile();
|
|
8515
8340
|
} catch {
|
|
8516
8341
|
}
|
|
8517
|
-
const entries = isFile ? [[
|
|
8342
|
+
const entries = isFile ? [[path12.basename(abs), abs]] : packFiles(abs).map((rel2) => [rel2, path12.join(abs, rel2)]);
|
|
8518
8343
|
for (const [rel2, full] of entries) {
|
|
8519
8344
|
hash.update(rel2);
|
|
8520
8345
|
hash.update("\0");
|
|
8521
8346
|
try {
|
|
8522
|
-
hash.update(
|
|
8347
|
+
hash.update(fs10.readFileSync(full));
|
|
8523
8348
|
} catch {
|
|
8524
8349
|
}
|
|
8525
8350
|
hash.update("\0");
|
|
@@ -8528,7 +8353,7 @@ function computePackDigest(packDir) {
|
|
|
8528
8353
|
}
|
|
8529
8354
|
function readInstallRecord(packPath) {
|
|
8530
8355
|
try {
|
|
8531
|
-
const raw = readYamlFile(
|
|
8356
|
+
const raw = readYamlFile(path12.join(packPath, INSTALL_RECORD));
|
|
8532
8357
|
return raw && typeof raw === "object" ? raw : {};
|
|
8533
8358
|
} catch {
|
|
8534
8359
|
return {};
|
|
@@ -8558,14 +8383,14 @@ function installedFrom(location, name, version) {
|
|
|
8558
8383
|
function versionedEntries(nameDir, fallbackName) {
|
|
8559
8384
|
let versions;
|
|
8560
8385
|
try {
|
|
8561
|
-
versions =
|
|
8386
|
+
versions = fs10.readdirSync(nameDir, { withFileTypes: true });
|
|
8562
8387
|
} catch {
|
|
8563
8388
|
return [];
|
|
8564
8389
|
}
|
|
8565
8390
|
const out = [];
|
|
8566
8391
|
for (const v of versions) {
|
|
8567
8392
|
if (!v.isDirectory()) continue;
|
|
8568
|
-
const versionDir =
|
|
8393
|
+
const versionDir = path12.join(nameDir, v.name);
|
|
8569
8394
|
const entryFile = packDirEntry(versionDir);
|
|
8570
8395
|
if (!entryFile) continue;
|
|
8571
8396
|
out.push(installedFrom(versionDir, declaredName(entryFile) ?? fallbackName, v.name));
|
|
@@ -8573,7 +8398,7 @@ function versionedEntries(nameDir, fallbackName) {
|
|
|
8573
8398
|
return out;
|
|
8574
8399
|
}
|
|
8575
8400
|
function storeEntryPacks(store, entry) {
|
|
8576
|
-
const full =
|
|
8401
|
+
const full = path12.join(store, entry.name);
|
|
8577
8402
|
if (entry.isFile()) {
|
|
8578
8403
|
if (!PACK_FILE_RE.test(entry.name)) return [];
|
|
8579
8404
|
const name = declaredName(full) ?? entry.name.replace(PACK_FILE_RE, "");
|
|
@@ -8588,7 +8413,7 @@ function listInstalledPacks() {
|
|
|
8588
8413
|
const store = packStoreDir();
|
|
8589
8414
|
let entries;
|
|
8590
8415
|
try {
|
|
8591
|
-
entries =
|
|
8416
|
+
entries = fs10.readdirSync(store, { withFileTypes: true });
|
|
8592
8417
|
} catch {
|
|
8593
8418
|
return [];
|
|
8594
8419
|
}
|
|
@@ -8605,17 +8430,17 @@ function resolveInstalledPack(name, version) {
|
|
|
8605
8430
|
return candidates[0];
|
|
8606
8431
|
}
|
|
8607
8432
|
function installPackFromDirectory(sourceDir, origin) {
|
|
8608
|
-
const abs =
|
|
8433
|
+
const abs = path12.resolve(sourceDir);
|
|
8609
8434
|
const entryFile = packDirEntry(abs);
|
|
8610
8435
|
if (!entryFile) {
|
|
8611
8436
|
throw new Error(`"${sourceDir}" is not a pack directory (no pack.yaml | pack.cjs | index.cjs | \u2026).`);
|
|
8612
8437
|
}
|
|
8613
|
-
const manifest = readManifest(entryFile,
|
|
8438
|
+
const manifest = readManifest(entryFile, path12.dirname(entryFile));
|
|
8614
8439
|
const version = manifest.version && manifest.version.length > 0 ? manifest.version : UNVERSIONED;
|
|
8615
|
-
const dest =
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8440
|
+
const dest = path12.join(packStoreDir(), manifest.name, version);
|
|
8441
|
+
fs10.rmSync(dest, { recursive: true, force: true });
|
|
8442
|
+
fs10.mkdirSync(path12.dirname(dest), { recursive: true });
|
|
8443
|
+
fs10.cpSync(abs, dest, { recursive: true });
|
|
8619
8444
|
const digest2 = computePackDigest(dest);
|
|
8620
8445
|
const record2 = {
|
|
8621
8446
|
origin,
|
|
@@ -8623,7 +8448,7 @@ function installPackFromDirectory(sourceDir, origin) {
|
|
|
8623
8448
|
waironVersion: WAIRON_VERSION,
|
|
8624
8449
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8625
8450
|
};
|
|
8626
|
-
writeYamlFile(
|
|
8451
|
+
writeYamlFile(path12.join(dest, INSTALL_RECORD), record2);
|
|
8627
8452
|
return {
|
|
8628
8453
|
name: manifest.name,
|
|
8629
8454
|
version,
|
|
@@ -8638,23 +8463,23 @@ function uninstallPack(name, version) {
|
|
|
8638
8463
|
const targets = listInstalledPacks().filter((p) => p.name === name && (!version || p.version === version));
|
|
8639
8464
|
if (targets.length === 0) return false;
|
|
8640
8465
|
for (const target of targets) {
|
|
8641
|
-
|
|
8642
|
-
const parent =
|
|
8643
|
-
if (
|
|
8466
|
+
fs10.rmSync(target.path, { recursive: true, force: true });
|
|
8467
|
+
const parent = path12.dirname(target.path);
|
|
8468
|
+
if (path12.resolve(parent) === path12.resolve(packStoreDir())) continue;
|
|
8644
8469
|
try {
|
|
8645
|
-
if (
|
|
8470
|
+
if (fs10.readdirSync(parent).length === 0) fs10.rmdirSync(parent);
|
|
8646
8471
|
} catch {
|
|
8647
8472
|
}
|
|
8648
8473
|
}
|
|
8649
8474
|
return true;
|
|
8650
8475
|
}
|
|
8651
|
-
var crypto2,
|
|
8476
|
+
var crypto2, fs10, path12, UNVERSIONED, INSTALL_RECORD, DIGEST_EXCLUDED, PACK_FILE_RE;
|
|
8652
8477
|
var init_packstore = __esm({
|
|
8653
8478
|
"src/core/packstore.ts"() {
|
|
8654
8479
|
"use strict";
|
|
8655
8480
|
crypto2 = __toESM(require("crypto"));
|
|
8656
|
-
|
|
8657
|
-
|
|
8481
|
+
fs10 = __toESM(require("fs"));
|
|
8482
|
+
path12 = __toESM(require("path"));
|
|
8658
8483
|
init_yaml();
|
|
8659
8484
|
init_defaults();
|
|
8660
8485
|
init_version();
|
|
@@ -8681,26 +8506,26 @@ function emptyExtensions() {
|
|
|
8681
8506
|
return { packNames: [], packs: [], rules: [], profiles: {}, languages: {}, skills: [], patterns: [], guarantees: [], assertions: [], instructions: [], errors: [], selectionFailures: [] };
|
|
8682
8507
|
}
|
|
8683
8508
|
function globalPacksDir() {
|
|
8684
|
-
return process.env.WAIRON_PACKS_DIR ??
|
|
8509
|
+
return process.env.WAIRON_PACKS_DIR ?? path13.join(os4.homedir(), ".wairon", "packs");
|
|
8685
8510
|
}
|
|
8686
8511
|
function packDirEntry(dir) {
|
|
8687
8512
|
for (const name of PACK_DIR_ENTRIES) {
|
|
8688
|
-
const p =
|
|
8689
|
-
if (
|
|
8513
|
+
const p = path13.join(dir, name);
|
|
8514
|
+
if (fs11.existsSync(p)) return p;
|
|
8690
8515
|
}
|
|
8691
8516
|
return null;
|
|
8692
8517
|
}
|
|
8693
8518
|
function latestVersionDir(nameDir) {
|
|
8694
8519
|
let versions;
|
|
8695
8520
|
try {
|
|
8696
|
-
versions =
|
|
8521
|
+
versions = fs11.readdirSync(nameDir, { withFileTypes: true });
|
|
8697
8522
|
} catch {
|
|
8698
8523
|
return null;
|
|
8699
8524
|
}
|
|
8700
8525
|
let best = null;
|
|
8701
8526
|
for (const v of versions) {
|
|
8702
8527
|
if (!v.isDirectory()) continue;
|
|
8703
|
-
const dir =
|
|
8528
|
+
const dir = path13.join(nameDir, v.name);
|
|
8704
8529
|
if (!packDirEntry(dir)) continue;
|
|
8705
8530
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
8706
8531
|
}
|
|
@@ -8709,13 +8534,13 @@ function latestVersionDir(nameDir) {
|
|
|
8709
8534
|
function discoverPacks(dir) {
|
|
8710
8535
|
let entries;
|
|
8711
8536
|
try {
|
|
8712
|
-
entries =
|
|
8537
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
8713
8538
|
} catch {
|
|
8714
8539
|
return [];
|
|
8715
8540
|
}
|
|
8716
8541
|
const refs = [];
|
|
8717
8542
|
for (const e of entries.sort((a, b) => compareOrdinal(a.name, b.name))) {
|
|
8718
|
-
const full =
|
|
8543
|
+
const full = path13.join(dir, e.name);
|
|
8719
8544
|
if (e.isDirectory()) {
|
|
8720
8545
|
if (packDirEntry(full)) refs.push(full);
|
|
8721
8546
|
else {
|
|
@@ -8745,17 +8570,17 @@ function mergePack(out, pack, ref, scope, packDir) {
|
|
|
8745
8570
|
foreignBuiltins: [.../* @__PURE__ */ new Set([...existing.foreignBuiltins, ...def.foreignBuiltins])]
|
|
8746
8571
|
} : def;
|
|
8747
8572
|
}
|
|
8748
|
-
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath:
|
|
8573
|
+
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath: path13.resolve(packDir, s.source) });
|
|
8749
8574
|
for (const p of pack.patterns) out.patterns.push({ ...p, pack: pack.name });
|
|
8750
8575
|
out.guarantees = [.../* @__PURE__ */ new Set([...out.guarantees, ...pack.guarantees])];
|
|
8751
8576
|
for (const a of pack.assertions) out.assertions.push({ ...a, pack: pack.name, fullCode: assertionFullCode(pack.name, a.code) });
|
|
8752
8577
|
for (const b of pack.instructions) out.instructions.push({ ...b, pack: pack.name });
|
|
8753
8578
|
}
|
|
8754
8579
|
function resolvePackRef(ref, projectRoot2) {
|
|
8755
|
-
const pathLike = ref.startsWith(".") ||
|
|
8580
|
+
const pathLike = ref.startsWith(".") || path13.isAbsolute(ref) || isYamlPath(ref);
|
|
8756
8581
|
if (!pathLike) return ref;
|
|
8757
|
-
const resolved =
|
|
8758
|
-
if (
|
|
8582
|
+
const resolved = path13.resolve(projectRoot2, ref);
|
|
8583
|
+
if (fs11.existsSync(resolved) && fs11.statSync(resolved).isDirectory()) {
|
|
8759
8584
|
const entry = packDirEntry(resolved);
|
|
8760
8585
|
if (!entry) throw new Error(`directory pack has no entry file (${PACK_DIR_ENTRIES.join(" | ")})`);
|
|
8761
8586
|
return entry;
|
|
@@ -8768,7 +8593,7 @@ function readManifest(target, projectRoot2) {
|
|
|
8768
8593
|
if (raw == null) throw new Error("file not found or empty");
|
|
8769
8594
|
return { ...DeclarativePackSchema.parse(raw), rules: [] };
|
|
8770
8595
|
}
|
|
8771
|
-
const req = (0, import_module.createRequire)(
|
|
8596
|
+
const req = (0, import_module.createRequire)(path13.join(projectRoot2, "package.json"));
|
|
8772
8597
|
const modRaw = req(target);
|
|
8773
8598
|
const mod = modRaw?.default ?? modRaw;
|
|
8774
8599
|
const parsed = DeclarativePackSchema.parse({
|
|
@@ -8796,7 +8621,7 @@ function loadExtensionPacks(refs, projectRoot2) {
|
|
|
8796
8621
|
try {
|
|
8797
8622
|
const target = resolvePackRef(ref, projectRoot2);
|
|
8798
8623
|
const manifest = readManifest(target, projectRoot2);
|
|
8799
|
-
mergePack(out, manifest, ref, scope,
|
|
8624
|
+
mergePack(out, manifest, ref, scope, path13.dirname(target));
|
|
8800
8625
|
for (const r of manifest.rules) out.rules.push(r);
|
|
8801
8626
|
} catch (e) {
|
|
8802
8627
|
out.errors.push(`Extension pack "${ref}" failed to load: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -8839,7 +8664,7 @@ function defaultPackSelections() {
|
|
|
8839
8664
|
const entry = packDirEntry(pack.path) ?? pack.path;
|
|
8840
8665
|
let manifest;
|
|
8841
8666
|
try {
|
|
8842
|
-
manifest = readManifest(entry,
|
|
8667
|
+
manifest = readManifest(entry, path13.dirname(entry));
|
|
8843
8668
|
} catch {
|
|
8844
8669
|
continue;
|
|
8845
8670
|
}
|
|
@@ -8878,7 +8703,7 @@ function diagnoseProjectPacks() {
|
|
|
8878
8703
|
const globalsApplied = [];
|
|
8879
8704
|
if (globalsOn) {
|
|
8880
8705
|
for (const ref of discoverPacks(globalPacksDir())) {
|
|
8881
|
-
const match = installed.find((p) =>
|
|
8706
|
+
const match = installed.find((p) => path13.resolve(p.path) === path13.resolve(ref));
|
|
8882
8707
|
if (match) globalsApplied.push({ name: match.name, version: match.version });
|
|
8883
8708
|
}
|
|
8884
8709
|
}
|
|
@@ -8956,7 +8781,7 @@ function verifyIntegrity(selection, packDir, where) {
|
|
|
8956
8781
|
};
|
|
8957
8782
|
}
|
|
8958
8783
|
function detectBundleStoreDrift(selection, bundleDir) {
|
|
8959
|
-
const bundledVersion =
|
|
8784
|
+
const bundledVersion = path13.basename(bundleDir);
|
|
8960
8785
|
const installed = resolveInstalledPack(selection.name, bundledVersion);
|
|
8961
8786
|
if (!installed) return void 0;
|
|
8962
8787
|
const bundleDigest = computePackDigest(bundleDir);
|
|
@@ -8970,34 +8795,34 @@ function detectBundleStoreDrift(selection, bundleDir) {
|
|
|
8970
8795
|
};
|
|
8971
8796
|
}
|
|
8972
8797
|
function findBundledPack(projectRoot2, selection) {
|
|
8973
|
-
const base =
|
|
8798
|
+
const base = path13.join(projectRoot2, ".wai", "packs", selection.name);
|
|
8974
8799
|
if (selection.version) {
|
|
8975
|
-
const pinned =
|
|
8800
|
+
const pinned = path13.join(base, selection.version);
|
|
8976
8801
|
return packDirEntry(pinned) ? pinned : null;
|
|
8977
8802
|
}
|
|
8978
8803
|
if (packDirEntry(base)) return base;
|
|
8979
8804
|
let versions;
|
|
8980
8805
|
try {
|
|
8981
|
-
versions =
|
|
8806
|
+
versions = fs11.readdirSync(base, { withFileTypes: true });
|
|
8982
8807
|
} catch {
|
|
8983
8808
|
return null;
|
|
8984
8809
|
}
|
|
8985
8810
|
let best = null;
|
|
8986
8811
|
for (const v of versions) {
|
|
8987
8812
|
if (!v.isDirectory()) continue;
|
|
8988
|
-
const dir =
|
|
8813
|
+
const dir = path13.join(base, v.name);
|
|
8989
8814
|
if (!packDirEntry(dir)) continue;
|
|
8990
8815
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
8991
8816
|
}
|
|
8992
8817
|
return best?.dir ?? null;
|
|
8993
8818
|
}
|
|
8994
|
-
var
|
|
8819
|
+
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
8820
|
var init_extensions = __esm({
|
|
8996
8821
|
"src/core/extensions.ts"() {
|
|
8997
8822
|
"use strict";
|
|
8998
|
-
|
|
8823
|
+
fs11 = __toESM(require("fs"));
|
|
8999
8824
|
os4 = __toESM(require("os"));
|
|
9000
|
-
|
|
8825
|
+
path13 = __toESM(require("path"));
|
|
9001
8826
|
import_module = require("module");
|
|
9002
8827
|
import_zod9 = require("zod");
|
|
9003
8828
|
init_yaml();
|
|
@@ -14446,12 +14271,109 @@ var init_carried_debt = __esm({
|
|
|
14446
14271
|
}
|
|
14447
14272
|
});
|
|
14448
14273
|
|
|
14274
|
+
// src/core/rules/heuristic/method-cohesion.ts
|
|
14275
|
+
function groupsSharingCollaborators(calledBy) {
|
|
14276
|
+
const parent = /* @__PURE__ */ new Map();
|
|
14277
|
+
const find = (m) => {
|
|
14278
|
+
let root = m;
|
|
14279
|
+
while (parent.get(root) !== root) root = parent.get(root);
|
|
14280
|
+
return root;
|
|
14281
|
+
};
|
|
14282
|
+
const union = (a, b) => {
|
|
14283
|
+
const [ra, rb] = [find(a), find(b)];
|
|
14284
|
+
if (ra !== rb) parent.set(ra, rb);
|
|
14285
|
+
};
|
|
14286
|
+
const methods = [...calledBy.keys()];
|
|
14287
|
+
for (const m of methods) parent.set(m, m);
|
|
14288
|
+
for (let i = 0; i < methods.length; i++) {
|
|
14289
|
+
for (let j = i + 1; j < methods.length; j++) {
|
|
14290
|
+
const shares = [...calledBy.get(methods[i])].some((c) => calledBy.get(methods[j])?.has(c));
|
|
14291
|
+
if (shares) union(methods[i], methods[j]);
|
|
14292
|
+
}
|
|
14293
|
+
}
|
|
14294
|
+
const groups = /* @__PURE__ */ new Map();
|
|
14295
|
+
for (const m of methods) {
|
|
14296
|
+
const root = find(m);
|
|
14297
|
+
groups.set(root, [...groups.get(root) ?? [], m]);
|
|
14298
|
+
}
|
|
14299
|
+
return [...groups.values()];
|
|
14300
|
+
}
|
|
14301
|
+
function isForwardingMethod(narrative) {
|
|
14302
|
+
let handoffs = 0;
|
|
14303
|
+
for (const step of narrative) {
|
|
14304
|
+
if (step.type === "call" || step.type === "dispatch") handoffs++;
|
|
14305
|
+
else if (step.type !== "return") return false;
|
|
14306
|
+
}
|
|
14307
|
+
return handoffs === 1;
|
|
14308
|
+
}
|
|
14309
|
+
function isPureForwarder(methods) {
|
|
14310
|
+
const narrated = methods.filter((m) => (m.narrative ?? []).length > 0);
|
|
14311
|
+
return narrated.length > 0 && narrated.every((m) => isForwardingMethod(m.narrative ?? []));
|
|
14312
|
+
}
|
|
14313
|
+
function pureForwarderComponents(ctx) {
|
|
14314
|
+
const realized = /* @__PURE__ */ new Map();
|
|
14315
|
+
for (const impl of ctx.implementations) {
|
|
14316
|
+
const intf = ctx.interfaceMap.get(impl.contract);
|
|
14317
|
+
if (!intf) continue;
|
|
14318
|
+
realized.set(intf.component, [...realized.get(intf.component) ?? [], ...impl.methods]);
|
|
14319
|
+
}
|
|
14320
|
+
return new Set([...realized].filter(([, methods]) => isPureForwarder(methods)).map(([id]) => id));
|
|
14321
|
+
}
|
|
14322
|
+
var methodCohesionRule;
|
|
14323
|
+
var init_method_cohesion = __esm({
|
|
14324
|
+
"src/core/rules/heuristic/method-cohesion.ts"() {
|
|
14325
|
+
"use strict";
|
|
14326
|
+
methodCohesionRule = {
|
|
14327
|
+
name: "method-cohesion",
|
|
14328
|
+
description: "An Orchestrator's methods share collaborators; when they split into groups that call no component in common, the component holds more than one responsibility. Reported only where two or more groups each hold two or more methods, so a single specialized method is not a finding \u2014 and never on a pure forwarder, whose every narrated method is a single hand-off and whose responsibility therefore lives in what it forwards to.",
|
|
14329
|
+
codes: [
|
|
14330
|
+
{ code: "INCOHESIVE_METHODS", defaultSeverity: "warning", summary: "Orchestrator's methods form two or more groups of two or more that share no called component" }
|
|
14331
|
+
],
|
|
14332
|
+
check(ctx) {
|
|
14333
|
+
const subjects = [];
|
|
14334
|
+
for (const impl of ctx.implementations) {
|
|
14335
|
+
const intf = ctx.interfaceMap.get(impl.contract);
|
|
14336
|
+
const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
|
|
14337
|
+
if (!comp || comp.componentType !== "Orchestrator") continue;
|
|
14338
|
+
if (isPureForwarder(impl.methods)) continue;
|
|
14339
|
+
const calledBy = /* @__PURE__ */ new Map();
|
|
14340
|
+
for (const method2 of impl.methods) {
|
|
14341
|
+
const reached = /* @__PURE__ */ new Set();
|
|
14342
|
+
for (const step of method2.narrative ?? []) {
|
|
14343
|
+
if ((step.type === "call" || step.type === "dispatch") && step.targetComponent) reached.add(step.targetComponent);
|
|
14344
|
+
}
|
|
14345
|
+
if (reached.size > 0) calledBy.set(method2.name, reached);
|
|
14346
|
+
}
|
|
14347
|
+
subjects.push({ implementation: impl, component: comp, calledBy });
|
|
14348
|
+
}
|
|
14349
|
+
for (const { component, calledBy } of subjects) {
|
|
14350
|
+
if (calledBy.size < 2) continue;
|
|
14351
|
+
const groups = groupsSharingCollaborators(calledBy).filter((g) => g.length >= 2);
|
|
14352
|
+
if (groups.length < 2) continue;
|
|
14353
|
+
const described = groups.map((g) => {
|
|
14354
|
+
const collaborators = [...new Set(g.flatMap((m) => [...calledBy.get(m)]))].sort();
|
|
14355
|
+
return `${g.join(", ")} (calling ${collaborators.join(", ")})`;
|
|
14356
|
+
}).join("; ");
|
|
14357
|
+
ctx.addIssue(
|
|
14358
|
+
"warning",
|
|
14359
|
+
"INCOHESIVE_METHODS",
|
|
14360
|
+
`Orchestrator "${component.id}" holds ${groups.length} groups of methods that share no called component: ${described}. Split it along those groups, move the logic out until every method is a single hand-off (a pure forwarder is exempt), or acknowledge a deliberate facade with a reasoned lint.allow for INCOHESIVE_METHODS.`,
|
|
14361
|
+
component.id,
|
|
14362
|
+
ctx.isComponentDraft(component.id)
|
|
14363
|
+
);
|
|
14364
|
+
}
|
|
14365
|
+
}
|
|
14366
|
+
};
|
|
14367
|
+
}
|
|
14368
|
+
});
|
|
14369
|
+
|
|
14449
14370
|
// src/core/rules/heuristic/coupling-health.ts
|
|
14450
14371
|
var DEFAULT_GOD_COMPONENT_THRESHOLD, couplingRule;
|
|
14451
14372
|
var init_coupling_health = __esm({
|
|
14452
14373
|
"src/core/rules/heuristic/coupling-health.ts"() {
|
|
14453
14374
|
"use strict";
|
|
14454
14375
|
init_models();
|
|
14376
|
+
init_method_cohesion();
|
|
14455
14377
|
DEFAULT_GOD_COMPONENT_THRESHOLD = 8;
|
|
14456
14378
|
couplingRule = {
|
|
14457
14379
|
name: "coupling-health",
|
|
@@ -14460,7 +14382,7 @@ var init_coupling_health = __esm({
|
|
|
14460
14382
|
{ code: "MUTUAL_SUBSYSTEM_DEPENDENCY", defaultSeverity: "warning", summary: "Subsystems depend on each other without a declared trusted link" },
|
|
14461
14383
|
{ code: "INVALID_TRUSTED_LINK", defaultSeverity: "error", summary: "trustedLinks references a non-existent subsystem" },
|
|
14462
14384
|
{ code: "UNUSED_TRUSTED_LINK", defaultSeverity: "warning", summary: "trustedLinks declares a peer no dependency actually reaches" },
|
|
14463
|
-
{ code: "GOD_COMPONENT", defaultSeverity: "warning", summary: "Component with excessive dependency fan-out" }
|
|
14385
|
+
{ code: "GOD_COMPONENT", defaultSeverity: "warning", summary: "Component with excessive dependency fan-out; not reported on a pure forwarder, whose every narrated method is a single hand-off" }
|
|
14464
14386
|
],
|
|
14465
14387
|
check(ctx) {
|
|
14466
14388
|
const subsystemDeps = /* @__PURE__ */ new Map();
|
|
@@ -14532,9 +14454,10 @@ var init_coupling_health = __esm({
|
|
|
14532
14454
|
);
|
|
14533
14455
|
}
|
|
14534
14456
|
}
|
|
14457
|
+
const forwarders = pureForwarderComponents(ctx);
|
|
14535
14458
|
for (const comp of ctx.components) {
|
|
14536
14459
|
const threshold = ctx.complexityConfigFor(comp.subsystem)?.maxComponentDependencies ?? DEFAULT_GOD_COMPONENT_THRESHOLD;
|
|
14537
|
-
if (comp.dependsOn.length > threshold) {
|
|
14460
|
+
if (comp.dependsOn.length > threshold && !forwarders.has(comp.id)) {
|
|
14538
14461
|
ctx.addIssue(
|
|
14539
14462
|
"warning",
|
|
14540
14463
|
"GOD_COMPONENT",
|
|
@@ -15158,6 +15081,7 @@ var init_complexity_and_metadata = __esm({
|
|
|
15158
15081
|
"src/core/rules/heuristic/complexity-and-metadata.ts"() {
|
|
15159
15082
|
"use strict";
|
|
15160
15083
|
init_models();
|
|
15084
|
+
init_method_cohesion();
|
|
15161
15085
|
complexityRule = {
|
|
15162
15086
|
name: "complexity-and-metadata",
|
|
15163
15087
|
description: "Enforces metadata documentation completeness (checking if descriptions are missing or too short) and structural complexity caps (limits on methods per interface, parameters per method, dependencies per component, and components per subsystem) configured globally or in architectural profiles. A narrative's own length and shape are judged by narrative-complexity.",
|
|
@@ -15166,7 +15090,7 @@ var init_complexity_and_metadata = __esm({
|
|
|
15166
15090
|
{ code: "DESCRIPTION_TOO_SHORT", defaultSeverity: "warning", summary: "Description is shorter than the configured minimum length" },
|
|
15167
15091
|
{ code: "EXCESSIVE_METHODS", defaultSeverity: "warning", summary: "Interface declares more methods than the configured limit" },
|
|
15168
15092
|
{ code: "EXCESSIVE_METHOD_PARAMS", defaultSeverity: "warning", summary: "Interface method declares more parameters than the configured limit" },
|
|
15169
|
-
{ code: "EXCESSIVE_DEPENDENCIES", defaultSeverity: "warning", summary: "Component has more dependencies than the configured limit" },
|
|
15093
|
+
{ code: "EXCESSIVE_DEPENDENCIES", defaultSeverity: "warning", summary: "Component has more dependencies than the configured limit; not reported on a pure forwarder, whose fan-out is a routing table rather than knowledge" },
|
|
15170
15094
|
{ code: "EXCESSIVE_SUBSYSTEM_COMPONENTS", defaultSeverity: "warning", summary: "Subsystem has more direct components than the configured limit" }
|
|
15171
15095
|
],
|
|
15172
15096
|
check(ctx) {
|
|
@@ -15186,6 +15110,7 @@ var init_complexity_and_metadata = __esm({
|
|
|
15186
15110
|
);
|
|
15187
15111
|
}
|
|
15188
15112
|
}
|
|
15113
|
+
const forwarders = pureForwarderComponents(ctx);
|
|
15189
15114
|
for (const comp of ctx.components) {
|
|
15190
15115
|
const docConfig = ctx.documentationConfigFor(comp.subsystem);
|
|
15191
15116
|
const complexityConfig = ctx.complexityConfigFor(comp.subsystem);
|
|
@@ -15199,7 +15124,7 @@ var init_complexity_and_metadata = __esm({
|
|
|
15199
15124
|
"Component",
|
|
15200
15125
|
isDraft
|
|
15201
15126
|
);
|
|
15202
|
-
if (complexityConfig?.maxComponentDependencies !== void 0 && comp.dependsOn.length > complexityConfig.maxComponentDependencies) {
|
|
15127
|
+
if (complexityConfig?.maxComponentDependencies !== void 0 && comp.dependsOn.length > complexityConfig.maxComponentDependencies && !forwarders.has(comp.id)) {
|
|
15203
15128
|
ctx.addIssue(
|
|
15204
15129
|
"warning",
|
|
15205
15130
|
"EXCESSIVE_DEPENDENCIES",
|
|
@@ -15498,90 +15423,6 @@ var init_naming_discipline = __esm({
|
|
|
15498
15423
|
}
|
|
15499
15424
|
});
|
|
15500
15425
|
|
|
15501
|
-
// src/core/rules/heuristic/method-cohesion.ts
|
|
15502
|
-
function groupsSharingCollaborators(calledBy) {
|
|
15503
|
-
const parent = /* @__PURE__ */ new Map();
|
|
15504
|
-
const find = (m) => {
|
|
15505
|
-
let root = m;
|
|
15506
|
-
while (parent.get(root) !== root) root = parent.get(root);
|
|
15507
|
-
return root;
|
|
15508
|
-
};
|
|
15509
|
-
const union = (a, b) => {
|
|
15510
|
-
const [ra, rb] = [find(a), find(b)];
|
|
15511
|
-
if (ra !== rb) parent.set(ra, rb);
|
|
15512
|
-
};
|
|
15513
|
-
const methods = [...calledBy.keys()];
|
|
15514
|
-
for (const m of methods) parent.set(m, m);
|
|
15515
|
-
for (let i = 0; i < methods.length; i++) {
|
|
15516
|
-
for (let j = i + 1; j < methods.length; j++) {
|
|
15517
|
-
const shares = [...calledBy.get(methods[i])].some((c) => calledBy.get(methods[j])?.has(c));
|
|
15518
|
-
if (shares) union(methods[i], methods[j]);
|
|
15519
|
-
}
|
|
15520
|
-
}
|
|
15521
|
-
const groups = /* @__PURE__ */ new Map();
|
|
15522
|
-
for (const m of methods) {
|
|
15523
|
-
const root = find(m);
|
|
15524
|
-
groups.set(root, [...groups.get(root) ?? [], m]);
|
|
15525
|
-
}
|
|
15526
|
-
return [...groups.values()];
|
|
15527
|
-
}
|
|
15528
|
-
function isForwardingMethod(narrative) {
|
|
15529
|
-
let handoffs = 0;
|
|
15530
|
-
for (const step of narrative) {
|
|
15531
|
-
if (step.type === "call" || step.type === "dispatch") handoffs++;
|
|
15532
|
-
else if (step.type !== "return") return false;
|
|
15533
|
-
}
|
|
15534
|
-
return handoffs === 1;
|
|
15535
|
-
}
|
|
15536
|
-
var methodCohesionRule;
|
|
15537
|
-
var init_method_cohesion = __esm({
|
|
15538
|
-
"src/core/rules/heuristic/method-cohesion.ts"() {
|
|
15539
|
-
"use strict";
|
|
15540
|
-
methodCohesionRule = {
|
|
15541
|
-
name: "method-cohesion",
|
|
15542
|
-
description: "An Orchestrator's methods share collaborators; when they split into groups that call no component in common, the component holds more than one responsibility. Reported only where two or more groups each hold two or more methods, so a single specialized method is not a finding \u2014 and never on a pure forwarder, whose every narrated method is a single hand-off and whose responsibility therefore lives in what it forwards to.",
|
|
15543
|
-
codes: [
|
|
15544
|
-
{ code: "INCOHESIVE_METHODS", defaultSeverity: "warning", summary: "Orchestrator's methods form two or more groups of two or more that share no called component" }
|
|
15545
|
-
],
|
|
15546
|
-
check(ctx) {
|
|
15547
|
-
const subjects = [];
|
|
15548
|
-
for (const impl of ctx.implementations) {
|
|
15549
|
-
const intf = ctx.interfaceMap.get(impl.contract);
|
|
15550
|
-
const comp = intf ? ctx.componentMap.get(intf.component) : void 0;
|
|
15551
|
-
if (!comp || comp.componentType !== "Orchestrator") continue;
|
|
15552
|
-
const narrated = impl.methods.filter((m) => (m.narrative ?? []).length > 0);
|
|
15553
|
-
if (narrated.length > 0 && narrated.every((m) => isForwardingMethod(m.narrative ?? []))) continue;
|
|
15554
|
-
const calledBy = /* @__PURE__ */ new Map();
|
|
15555
|
-
for (const method2 of impl.methods) {
|
|
15556
|
-
const reached = /* @__PURE__ */ new Set();
|
|
15557
|
-
for (const step of method2.narrative ?? []) {
|
|
15558
|
-
if ((step.type === "call" || step.type === "dispatch") && step.targetComponent) reached.add(step.targetComponent);
|
|
15559
|
-
}
|
|
15560
|
-
if (reached.size > 0) calledBy.set(method2.name, reached);
|
|
15561
|
-
}
|
|
15562
|
-
subjects.push({ implementation: impl, component: comp, calledBy });
|
|
15563
|
-
}
|
|
15564
|
-
for (const { component, calledBy } of subjects) {
|
|
15565
|
-
if (calledBy.size < 2) continue;
|
|
15566
|
-
const groups = groupsSharingCollaborators(calledBy).filter((g) => g.length >= 2);
|
|
15567
|
-
if (groups.length < 2) continue;
|
|
15568
|
-
const described = groups.map((g) => {
|
|
15569
|
-
const collaborators = [...new Set(g.flatMap((m) => [...calledBy.get(m)]))].sort();
|
|
15570
|
-
return `${g.join(", ")} (calling ${collaborators.join(", ")})`;
|
|
15571
|
-
}).join("; ");
|
|
15572
|
-
ctx.addIssue(
|
|
15573
|
-
"warning",
|
|
15574
|
-
"INCOHESIVE_METHODS",
|
|
15575
|
-
`Orchestrator "${component.id}" holds ${groups.length} groups of methods that share no called component: ${described}. Split it along those groups, move the logic out until every method is a single hand-off (a pure forwarder is exempt), or acknowledge a deliberate facade with a reasoned lint.allow for INCOHESIVE_METHODS.`,
|
|
15576
|
-
component.id,
|
|
15577
|
-
ctx.isComponentDraft(component.id)
|
|
15578
|
-
);
|
|
15579
|
-
}
|
|
15580
|
-
}
|
|
15581
|
-
};
|
|
15582
|
-
}
|
|
15583
|
-
});
|
|
15584
|
-
|
|
15585
15426
|
// src/core/rules/repository.ts
|
|
15586
15427
|
function addRule(rule) {
|
|
15587
15428
|
ruleSet.push(rule);
|
|
@@ -15993,7 +15834,7 @@ function resolveTypeScript(projectRoot2) {
|
|
|
15993
15834
|
return cached.ts;
|
|
15994
15835
|
}
|
|
15995
15836
|
let ts = null;
|
|
15996
|
-
const bases = [
|
|
15837
|
+
const bases = [path14.join(projectRoot2, "package.json"), __filename];
|
|
15997
15838
|
for (const base of bases) {
|
|
15998
15839
|
try {
|
|
15999
15840
|
const req = (0, import_module2.createRequire)(base);
|
|
@@ -16208,7 +16049,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
16208
16049
|
}
|
|
16209
16050
|
function resolveRelativeModule(fromFile, specifier) {
|
|
16210
16051
|
if (!specifier.startsWith(".")) return null;
|
|
16211
|
-
const base =
|
|
16052
|
+
const base = path14.resolve(path14.dirname(fromFile), specifier);
|
|
16212
16053
|
const candidates = [
|
|
16213
16054
|
base,
|
|
16214
16055
|
base.replace(/\.js$/, ".ts"),
|
|
@@ -16216,12 +16057,12 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
16216
16057
|
`${base}.ts`,
|
|
16217
16058
|
`${base}.tsx`,
|
|
16218
16059
|
`${base}.js`,
|
|
16219
|
-
|
|
16220
|
-
|
|
16060
|
+
path14.join(base, "index.ts"),
|
|
16061
|
+
path14.join(base, "index.js")
|
|
16221
16062
|
];
|
|
16222
16063
|
for (const c of candidates) {
|
|
16223
16064
|
try {
|
|
16224
|
-
if (
|
|
16065
|
+
if (fs12.statSync(c).isFile()) return c;
|
|
16225
16066
|
} catch {
|
|
16226
16067
|
}
|
|
16227
16068
|
}
|
|
@@ -16229,11 +16070,11 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
16229
16070
|
}
|
|
16230
16071
|
function reexportTarget(ts, filePath, specifier, projectRoot2, visited, exactCache) {
|
|
16231
16072
|
const target = resolveRelativeModule(filePath, specifier);
|
|
16232
|
-
if (!target ||
|
|
16073
|
+
if (!target || path14.relative(projectRoot2, target).startsWith("..")) return null;
|
|
16233
16074
|
let targetFacts = exactCache.get(target);
|
|
16234
16075
|
if (targetFacts === void 0) {
|
|
16235
16076
|
try {
|
|
16236
|
-
targetFacts = walkExact(ts,
|
|
16077
|
+
targetFacts = walkExact(ts, fs12.readFileSync(target, "utf8"), target);
|
|
16237
16078
|
} catch {
|
|
16238
16079
|
targetFacts = null;
|
|
16239
16080
|
}
|
|
@@ -16251,7 +16092,7 @@ function carryBody(facts, target, targetPath, local, exported, projectRoot2) {
|
|
|
16251
16092
|
if (score !== void 0) facts.complexity.set(exported, Math.max(facts.complexity.get(exported) ?? 0, score));
|
|
16252
16093
|
const targetCalls = target.calls.get(local);
|
|
16253
16094
|
if (!targetCalls) return;
|
|
16254
|
-
const carriedFrom = pathKey(
|
|
16095
|
+
const carriedFrom = pathKey(path14.relative(projectRoot2, targetPath));
|
|
16255
16096
|
const sites = facts.calls.get(exported) ?? /* @__PURE__ */ new Map();
|
|
16256
16097
|
for (const [key, site] of targetCalls) sites.set(carriedFrom + "|" + key, { ...site, from: site.from ?? carriedFrom });
|
|
16257
16098
|
facts.calls.set(exported, sites);
|
|
@@ -16281,24 +16122,24 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
|
|
|
16281
16122
|
const excluded = exclude.map(pathKey);
|
|
16282
16123
|
const isExcluded = (key) => excluded.some((e) => key === e || key.startsWith(`${e}/`));
|
|
16283
16124
|
const record2 = (absolute) => {
|
|
16284
|
-
const key = pathKey(
|
|
16125
|
+
const key = pathKey(path14.relative(projectRoot2, absolute));
|
|
16285
16126
|
if (seen.has(key) || isExcluded(key)) return;
|
|
16286
|
-
if (!EXTENSION_LANGUAGE[
|
|
16127
|
+
if (!EXTENSION_LANGUAGE[path14.extname(key).toLowerCase()]) return;
|
|
16287
16128
|
seen.add(key);
|
|
16288
16129
|
found.push(key);
|
|
16289
16130
|
};
|
|
16290
16131
|
const descend = (dir) => {
|
|
16291
16132
|
let entries;
|
|
16292
16133
|
try {
|
|
16293
|
-
entries =
|
|
16134
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
16294
16135
|
} catch {
|
|
16295
16136
|
return;
|
|
16296
16137
|
}
|
|
16297
16138
|
for (const entry of entries.slice().sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
16298
|
-
const child =
|
|
16139
|
+
const child = path14.join(dir, entry.name);
|
|
16299
16140
|
if (entry.isDirectory()) {
|
|
16300
16141
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
16301
|
-
if (isExcluded(pathKey(
|
|
16142
|
+
if (isExcluded(pathKey(path14.relative(projectRoot2, child)))) continue;
|
|
16302
16143
|
descend(child);
|
|
16303
16144
|
} else if (entry.isFile()) {
|
|
16304
16145
|
record2(child);
|
|
@@ -16307,13 +16148,13 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
|
|
|
16307
16148
|
};
|
|
16308
16149
|
for (const root of roots) {
|
|
16309
16150
|
const key = pathKey(root);
|
|
16310
|
-
if (
|
|
16311
|
-
const absolute =
|
|
16312
|
-
if (
|
|
16151
|
+
if (path14.isAbsolute(key) || path14.normalize(key).split(path14.sep)[0] === "..") continue;
|
|
16152
|
+
const absolute = path14.resolve(projectRoot2, key);
|
|
16153
|
+
if (path14.relative(projectRoot2, absolute).startsWith("..")) continue;
|
|
16313
16154
|
if (isExcluded(key)) continue;
|
|
16314
16155
|
let stat;
|
|
16315
16156
|
try {
|
|
16316
|
-
stat =
|
|
16157
|
+
stat = fs12.statSync(absolute);
|
|
16317
16158
|
} catch {
|
|
16318
16159
|
continue;
|
|
16319
16160
|
}
|
|
@@ -16339,23 +16180,23 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16339
16180
|
if (seen.has(sourcePath)) continue;
|
|
16340
16181
|
seen.add(sourcePath);
|
|
16341
16182
|
const empty = { declaredNames: [], anchoredNames: [], exportedNames: [], imports: [], reexports: [] };
|
|
16342
|
-
if (
|
|
16183
|
+
if (path14.isAbsolute(sourcePath) || path14.normalize(sourcePath).split(path14.sep)[0] === "..") {
|
|
16343
16184
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
16344
16185
|
continue;
|
|
16345
16186
|
}
|
|
16346
|
-
const absolute =
|
|
16347
|
-
if (
|
|
16187
|
+
const absolute = path14.resolve(projectRoot2, sourcePath);
|
|
16188
|
+
if (path14.relative(projectRoot2, absolute).startsWith("..")) {
|
|
16348
16189
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
16349
16190
|
continue;
|
|
16350
16191
|
}
|
|
16351
16192
|
let buffer;
|
|
16352
16193
|
try {
|
|
16353
|
-
const stat =
|
|
16194
|
+
const stat = fs12.statSync(absolute);
|
|
16354
16195
|
if (!stat.isFile()) {
|
|
16355
16196
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
16356
16197
|
continue;
|
|
16357
16198
|
}
|
|
16358
|
-
buffer =
|
|
16199
|
+
buffer = fs12.readFileSync(absolute);
|
|
16359
16200
|
} catch {
|
|
16360
16201
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
16361
16202
|
continue;
|
|
@@ -16365,7 +16206,7 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16365
16206
|
continue;
|
|
16366
16207
|
}
|
|
16367
16208
|
const text2 = buffer.toString("utf8");
|
|
16368
|
-
const language = EXTENSION_LANGUAGE[
|
|
16209
|
+
const language = EXTENSION_LANGUAGE[path14.extname(sourcePath).toLowerCase()];
|
|
16369
16210
|
let analyzed;
|
|
16370
16211
|
if (language === "typescript" || language === "javascript") {
|
|
16371
16212
|
const ts = resolveTypeScript(projectRoot2);
|
|
@@ -16409,7 +16250,7 @@ function readTestFiles(testRoots, projectRoot2) {
|
|
|
16409
16250
|
for (const key of walkDeclaredRoots(testRoots, [], projectRoot2)) {
|
|
16410
16251
|
let text2;
|
|
16411
16252
|
try {
|
|
16412
|
-
const buffer =
|
|
16253
|
+
const buffer = fs12.readFileSync(path14.resolve(projectRoot2, key));
|
|
16413
16254
|
if (looksBinary(buffer)) continue;
|
|
16414
16255
|
text2 = buffer.toString("utf8");
|
|
16415
16256
|
} catch {
|
|
@@ -16446,12 +16287,12 @@ function findTestsReferencing(methods, projectRoot2, testRoots = []) {
|
|
|
16446
16287
|
}
|
|
16447
16288
|
return found;
|
|
16448
16289
|
}
|
|
16449
|
-
var
|
|
16290
|
+
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
16291
|
var init_source_analysis = __esm({
|
|
16451
16292
|
"src/core/source-analysis.ts"() {
|
|
16452
16293
|
"use strict";
|
|
16453
|
-
|
|
16454
|
-
|
|
16294
|
+
fs12 = __toESM(require("fs"));
|
|
16295
|
+
path14 = __toESM(require("path"));
|
|
16455
16296
|
import_module2 = require("module");
|
|
16456
16297
|
init_models();
|
|
16457
16298
|
EXTENSION_LANGUAGE = {
|
|
@@ -17221,28 +17062,28 @@ var init_gate_identity = __esm({
|
|
|
17221
17062
|
|
|
17222
17063
|
// src/core/variants.ts
|
|
17223
17064
|
function globalVariantsDir() {
|
|
17224
|
-
return process.env.WAIRON_VARIANTS_DIR ??
|
|
17065
|
+
return process.env.WAIRON_VARIANTS_DIR ?? path15.join(os5.homedir(), ".wairon", "variants");
|
|
17225
17066
|
}
|
|
17226
17067
|
function builtinVariantsDir() {
|
|
17227
17068
|
const candidates = [
|
|
17228
|
-
|
|
17069
|
+
path15.resolve(__dirname, "..", "templates", "variants"),
|
|
17229
17070
|
// src/core & dist/cli
|
|
17230
|
-
|
|
17071
|
+
path15.resolve(__dirname, "templates", "variants")
|
|
17231
17072
|
// dist (library entry)
|
|
17232
17073
|
];
|
|
17233
|
-
return candidates.find((dir) =>
|
|
17074
|
+
return candidates.find((dir) => fs13.existsSync(dir)) ?? candidates[0];
|
|
17234
17075
|
}
|
|
17235
17076
|
function projectVariantsDir() {
|
|
17236
|
-
return
|
|
17077
|
+
return path15.join(getProjectRoot(), ".wai", "variants");
|
|
17237
17078
|
}
|
|
17238
17079
|
function variantFiles(dir) {
|
|
17239
17080
|
let entries;
|
|
17240
17081
|
try {
|
|
17241
|
-
entries =
|
|
17082
|
+
entries = fs13.readdirSync(dir, { withFileTypes: true });
|
|
17242
17083
|
} catch {
|
|
17243
17084
|
return [];
|
|
17244
17085
|
}
|
|
17245
|
-
return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) =>
|
|
17086
|
+
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
17087
|
}
|
|
17247
17088
|
function parseVariants(raw) {
|
|
17248
17089
|
if (raw == null) return [];
|
|
@@ -17351,13 +17192,13 @@ function rebasedText(content, fromBase, toBase, rebasedContent) {
|
|
|
17351
17192
|
}
|
|
17352
17193
|
return serializeYaml(rebasedContent);
|
|
17353
17194
|
}
|
|
17354
|
-
var
|
|
17195
|
+
var fs13, os5, path15, import_zod10, VariantDefSchema;
|
|
17355
17196
|
var init_variants = __esm({
|
|
17356
17197
|
"src/core/variants.ts"() {
|
|
17357
17198
|
"use strict";
|
|
17358
|
-
|
|
17199
|
+
fs13 = __toESM(require("fs"));
|
|
17359
17200
|
os5 = __toESM(require("os"));
|
|
17360
|
-
|
|
17201
|
+
path15 = __toESM(require("path"));
|
|
17361
17202
|
import_zod10 = require("zod");
|
|
17362
17203
|
init_yaml();
|
|
17363
17204
|
init_fs();
|
|
@@ -17743,7 +17584,7 @@ var init_openapi = __esm({
|
|
|
17743
17584
|
|
|
17744
17585
|
// src/core/surfaces.ts
|
|
17745
17586
|
function surfacesDir(rootDir) {
|
|
17746
|
-
return
|
|
17587
|
+
return path16.join(rootDir, ".wai", SURFACES_DIRNAME);
|
|
17747
17588
|
}
|
|
17748
17589
|
function audienceRank(audience) {
|
|
17749
17590
|
const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
|
|
@@ -17901,12 +17742,12 @@ function projectSubsystemSurface(subsystemId) {
|
|
|
17901
17742
|
}
|
|
17902
17743
|
function listSnapshots(rootDir = getProjectRoot()) {
|
|
17903
17744
|
const dir = surfacesDir(rootDir);
|
|
17904
|
-
if (!
|
|
17745
|
+
if (!fs14.existsSync(dir)) return [];
|
|
17905
17746
|
const out = [];
|
|
17906
|
-
for (const file of
|
|
17747
|
+
for (const file of fs14.readdirSync(dir)) {
|
|
17907
17748
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
17908
17749
|
try {
|
|
17909
|
-
out.push(SurfaceSnapshotSchema.parse(readYamlFile(
|
|
17750
|
+
out.push(SurfaceSnapshotSchema.parse(readYamlFile(path16.join(dir, file))));
|
|
17910
17751
|
} catch {
|
|
17911
17752
|
}
|
|
17912
17753
|
}
|
|
@@ -17917,10 +17758,10 @@ function snapshotFilename(projectName) {
|
|
|
17917
17758
|
}
|
|
17918
17759
|
function writeSnapshotIfChanged(snapshot, rootDir) {
|
|
17919
17760
|
const dir = surfacesDir(rootDir);
|
|
17920
|
-
|
|
17921
|
-
const p =
|
|
17761
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
17762
|
+
const p = path16.join(dir, snapshotFilename(snapshot.projectName));
|
|
17922
17763
|
const next = SurfaceSnapshotSchema.parse(snapshot);
|
|
17923
|
-
if (
|
|
17764
|
+
if (fs14.existsSync(p)) {
|
|
17924
17765
|
try {
|
|
17925
17766
|
const existing = SurfaceSnapshotSchema.parse(readYamlFile(p));
|
|
17926
17767
|
if (surfaceContentKey(existing) === surfaceContentKey(next)) {
|
|
@@ -17939,11 +17780,11 @@ function loadSurfaceSnapshots() {
|
|
|
17939
17780
|
return listSnapshots();
|
|
17940
17781
|
}
|
|
17941
17782
|
function listMountSnapshots(mounts) {
|
|
17942
|
-
const bound2 =
|
|
17783
|
+
const bound2 = path16.resolve(getProjectRoot());
|
|
17943
17784
|
const out = [];
|
|
17944
17785
|
for (const namespace of mounts) {
|
|
17945
17786
|
const dir = resolveSubprojectForNamespace(namespace);
|
|
17946
|
-
if (!dir ||
|
|
17787
|
+
if (!dir || path16.resolve(dir) === bound2) continue;
|
|
17947
17788
|
const snapshots = listSnapshots(dir);
|
|
17948
17789
|
if (snapshots.length > 0) out.push({ namespace, snapshots });
|
|
17949
17790
|
}
|
|
@@ -17961,24 +17802,24 @@ function selectPortalSpec(renderedSet, portalId) {
|
|
|
17961
17802
|
return [hit];
|
|
17962
17803
|
}
|
|
17963
17804
|
function perPortalPath(resolvedOut, portalId) {
|
|
17964
|
-
const ext =
|
|
17805
|
+
const ext = path16.extname(resolvedOut);
|
|
17965
17806
|
const stem2 = ext ? resolvedOut.slice(0, -ext.length) : resolvedOut;
|
|
17966
17807
|
return `${stem2}.${safeFilenamePart(portalId)}${ext}`;
|
|
17967
17808
|
}
|
|
17968
17809
|
function writeSurfaceFile(outPath, snapshot, renderedSet) {
|
|
17969
|
-
const resolved =
|
|
17970
|
-
|
|
17810
|
+
const resolved = path16.resolve(outPath);
|
|
17811
|
+
fs14.mkdirSync(path16.dirname(resolved), { recursive: true });
|
|
17971
17812
|
if (!renderedSet || renderedSet.length === 0) {
|
|
17972
17813
|
writeYamlFile(resolved, snapshot);
|
|
17973
17814
|
return [resolved];
|
|
17974
17815
|
}
|
|
17975
17816
|
if (renderedSet.length === 1) {
|
|
17976
|
-
|
|
17817
|
+
fs14.writeFileSync(resolved, renderedSet[0].document);
|
|
17977
17818
|
return [resolved];
|
|
17978
17819
|
}
|
|
17979
17820
|
return renderedSet.map((spec) => {
|
|
17980
17821
|
const target = perPortalPath(resolved, spec.portalId);
|
|
17981
|
-
|
|
17822
|
+
fs14.writeFileSync(target, spec.document);
|
|
17982
17823
|
return target;
|
|
17983
17824
|
});
|
|
17984
17825
|
}
|
|
@@ -18000,14 +17841,14 @@ function exportSurface(maxAudience, format, outPath, portalId) {
|
|
|
18000
17841
|
return exportResult(snapshot, renderedSet, writtenPaths);
|
|
18001
17842
|
}
|
|
18002
17843
|
function importSurface(sourcePath, origin) {
|
|
18003
|
-
const resolved =
|
|
18004
|
-
if (!
|
|
17844
|
+
const resolved = path16.resolve(sourcePath);
|
|
17845
|
+
if (!fs14.existsSync(resolved)) {
|
|
18005
17846
|
throw new Error(`Surface document not found: ${resolved}`);
|
|
18006
17847
|
}
|
|
18007
|
-
const body =
|
|
17848
|
+
const body = fs14.readFileSync(resolved, "utf8");
|
|
18008
17849
|
let snapshot;
|
|
18009
17850
|
if (isOpenApiDocument(body)) {
|
|
18010
|
-
const projectName =
|
|
17851
|
+
const projectName = path16.basename(resolved).replace(/\.(json|ya?ml)$/i, "");
|
|
18011
17852
|
snapshot = fromOpenApi(body, projectName);
|
|
18012
17853
|
snapshot = { ...snapshot, origin };
|
|
18013
17854
|
} else {
|
|
@@ -18070,12 +17911,12 @@ function surfaceContentKey(snapshot) {
|
|
|
18070
17911
|
const { stateId, generatedAt, origin, ...content } = snapshot;
|
|
18071
17912
|
return JSON.stringify(content);
|
|
18072
17913
|
}
|
|
18073
|
-
var
|
|
17914
|
+
var fs14, path16, SURFACES_DIRNAME, CROSS_BOUNDARY_TARGETS;
|
|
18074
17915
|
var init_surfaces = __esm({
|
|
18075
17916
|
"src/core/surfaces.ts"() {
|
|
18076
17917
|
"use strict";
|
|
18077
|
-
|
|
18078
|
-
|
|
17918
|
+
fs14 = __toESM(require("fs"));
|
|
17919
|
+
path16 = __toESM(require("path"));
|
|
18079
17920
|
init_fs();
|
|
18080
17921
|
init_yaml();
|
|
18081
17922
|
init_filenames();
|
|
@@ -18381,13 +18222,13 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
|
|
|
18381
18222
|
function resolveThroughParent(boundRoot, treatAllAsComplete, childRules) {
|
|
18382
18223
|
const reach = getRequestParentReach();
|
|
18383
18224
|
if (reach && !reach.parentReach) return null;
|
|
18384
|
-
const ceiling = reach?.topRoot ?
|
|
18225
|
+
const ceiling = reach?.topRoot ? path17.resolve(reach.topRoot) : void 0;
|
|
18385
18226
|
const chain = [];
|
|
18386
|
-
let top =
|
|
18227
|
+
let top = path17.resolve(boundRoot);
|
|
18387
18228
|
while (top !== ceiling) {
|
|
18388
18229
|
const hop = findChainingParent(top, ceiling);
|
|
18389
18230
|
if (!hop) break;
|
|
18390
|
-
const next =
|
|
18231
|
+
const next = path17.resolve(hop.parentRoot);
|
|
18391
18232
|
if (ceiling && !isWithinOrEqual(ceiling, next)) break;
|
|
18392
18233
|
chain.unshift(hop.subsystemId);
|
|
18393
18234
|
top = next;
|
|
@@ -18434,8 +18275,8 @@ function isIdChar(ch) {
|
|
|
18434
18275
|
return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-" || ch === "." || ch === ":";
|
|
18435
18276
|
}
|
|
18436
18277
|
function isWithinOrEqual(dir, target) {
|
|
18437
|
-
const rel2 =
|
|
18438
|
-
return rel2 === "" || !rel2.startsWith("..") && !
|
|
18278
|
+
const rel2 = path17.relative(dir, target);
|
|
18279
|
+
return rel2 === "" || !rel2.startsWith("..") && !path17.isAbsolute(rel2);
|
|
18439
18280
|
}
|
|
18440
18281
|
function dedupeIssues(list2) {
|
|
18441
18282
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -18456,7 +18297,7 @@ function settledStatusBearing(loaded) {
|
|
|
18456
18297
|
if (!settled || settled.size === 0) return [];
|
|
18457
18298
|
const root = getProjectRoot();
|
|
18458
18299
|
const index = scanAllSpecs();
|
|
18459
|
-
const rel2 = (abs) =>
|
|
18300
|
+
const rel2 = (abs) => path17.relative(root, abs).split(path17.sep).join("/");
|
|
18460
18301
|
const out = [];
|
|
18461
18302
|
const take = (specs, paths) => {
|
|
18462
18303
|
for (const spec of specs) {
|
|
@@ -18486,7 +18327,7 @@ function computeGateStateId() {
|
|
|
18486
18327
|
registerBuiltinRules();
|
|
18487
18328
|
return computeGateIdentity(content, extensions, ruleSequence(), inputs, gate);
|
|
18488
18329
|
}
|
|
18489
|
-
var
|
|
18330
|
+
var path17, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
|
|
18490
18331
|
var init_validation = __esm({
|
|
18491
18332
|
"src/core/validation.ts"() {
|
|
18492
18333
|
"use strict";
|
|
@@ -18502,7 +18343,7 @@ var init_validation = __esm({
|
|
|
18502
18343
|
init_source_analysis();
|
|
18503
18344
|
init_specs2();
|
|
18504
18345
|
init_fs();
|
|
18505
|
-
|
|
18346
|
+
path17 = __toESM(require("path"));
|
|
18506
18347
|
init_core();
|
|
18507
18348
|
RESOLUTION_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
18508
18349
|
"UNDEFINED_TYPE_REFERENCE",
|
|
@@ -19222,42 +19063,42 @@ function rebaseReference(ref, mount, direction, isMoved = () => false) {
|
|
|
19222
19063
|
return relativizeId(travels ? qualifyId(left, to, NO_ROOT_SUBSYSTEMS) : target, to);
|
|
19223
19064
|
}
|
|
19224
19065
|
function isWithin(dir, file) {
|
|
19225
|
-
const d =
|
|
19226
|
-
const f =
|
|
19227
|
-
return f === d || f.startsWith(d +
|
|
19066
|
+
const d = path18.resolve(dir);
|
|
19067
|
+
const f = path18.resolve(file);
|
|
19068
|
+
return f === d || f.startsWith(d + path18.sep);
|
|
19228
19069
|
}
|
|
19229
19070
|
function canonicalPath(target) {
|
|
19230
|
-
let existing =
|
|
19071
|
+
let existing = path18.resolve(target);
|
|
19231
19072
|
const rest = [];
|
|
19232
19073
|
for (; ; ) {
|
|
19233
19074
|
try {
|
|
19234
|
-
|
|
19075
|
+
fs15.lstatSync(existing);
|
|
19235
19076
|
break;
|
|
19236
19077
|
} catch {
|
|
19237
|
-
const up =
|
|
19238
|
-
if (up === existing) return
|
|
19239
|
-
rest.unshift(
|
|
19078
|
+
const up = path18.dirname(existing);
|
|
19079
|
+
if (up === existing) return path18.resolve(target);
|
|
19080
|
+
rest.unshift(path18.basename(existing));
|
|
19240
19081
|
existing = up;
|
|
19241
19082
|
}
|
|
19242
19083
|
}
|
|
19243
19084
|
try {
|
|
19244
|
-
return
|
|
19085
|
+
return path18.join(fs15.realpathSync.native(existing), ...rest);
|
|
19245
19086
|
} catch {
|
|
19246
19087
|
return null;
|
|
19247
19088
|
}
|
|
19248
19089
|
}
|
|
19249
19090
|
function chainDirKey(dir) {
|
|
19250
|
-
return canonicalPath(dir) ??
|
|
19091
|
+
return canonicalPath(dir) ?? path18.resolve(dir);
|
|
19251
19092
|
}
|
|
19252
19093
|
function projectPathEscapesRoot(projectRoot2, projectPath, resolvedChildDir) {
|
|
19253
|
-
if (
|
|
19094
|
+
if (path18.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
|
|
19254
19095
|
const root = canonicalPath(projectRoot2);
|
|
19255
19096
|
const child = canonicalPath(resolvedChildDir);
|
|
19256
19097
|
return root === null || child === null || !isWithin(root, child);
|
|
19257
19098
|
}
|
|
19258
19099
|
function assertContainedProjectPath(projectRoot2, projectPath) {
|
|
19259
|
-
const root =
|
|
19260
|
-
const resolved =
|
|
19100
|
+
const root = path18.resolve(projectRoot2);
|
|
19101
|
+
const resolved = path18.resolve(root, projectPath);
|
|
19261
19102
|
if (projectPathEscapesRoot(root, projectPath, resolved)) {
|
|
19262
19103
|
throw new Error(
|
|
19263
19104
|
`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 +19109,12 @@ function assertContainedProjectPath(projectRoot2, projectPath) {
|
|
|
19268
19109
|
function findChainingParent(childRoot, ceiling) {
|
|
19269
19110
|
let childResolved;
|
|
19270
19111
|
try {
|
|
19271
|
-
childResolved =
|
|
19112
|
+
childResolved = path18.resolve(childRoot);
|
|
19272
19113
|
} catch {
|
|
19273
19114
|
return null;
|
|
19274
19115
|
}
|
|
19275
|
-
const bound2 = ceiling ?
|
|
19276
|
-
let dir =
|
|
19116
|
+
const bound2 = ceiling ? path18.resolve(ceiling) : void 0;
|
|
19117
|
+
let dir = path18.dirname(childResolved);
|
|
19277
19118
|
for (let hops = 0; hops < 32; hops++) {
|
|
19278
19119
|
if (bound2 && !isWithin(bound2, dir)) break;
|
|
19279
19120
|
const specsDir = aiPathsAt(dir).specsDir();
|
|
@@ -19289,7 +19130,7 @@ function findChainingParent(childRoot, ceiling) {
|
|
|
19289
19130
|
const projectPath = raw.projectPath;
|
|
19290
19131
|
if (typeof projectPath === "string" && projectPath.trim() !== "") {
|
|
19291
19132
|
try {
|
|
19292
|
-
const mountDir =
|
|
19133
|
+
const mountDir = path18.resolve(dir, projectPath);
|
|
19293
19134
|
if (mountDir === childResolved && !projectPathEscapesRoot(dir, projectPath, mountDir)) {
|
|
19294
19135
|
const id = raw.id;
|
|
19295
19136
|
return { parentRoot: dir, subsystemId: typeof id === "string" ? id : "?" };
|
|
@@ -19300,14 +19141,14 @@ function findChainingParent(childRoot, ceiling) {
|
|
|
19300
19141
|
}
|
|
19301
19142
|
}
|
|
19302
19143
|
}
|
|
19303
|
-
const up =
|
|
19144
|
+
const up = path18.dirname(dir);
|
|
19304
19145
|
if (up === dir) break;
|
|
19305
19146
|
dir = up;
|
|
19306
19147
|
}
|
|
19307
19148
|
return null;
|
|
19308
19149
|
}
|
|
19309
19150
|
function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
19310
|
-
const root =
|
|
19151
|
+
const root = path18.resolve(rootDir);
|
|
19311
19152
|
const inspection = { roots: [], skipped: [] };
|
|
19312
19153
|
const listed = /* @__PURE__ */ new Set();
|
|
19313
19154
|
const walk2 = (projectDir, prefix, ancestors, depth) => {
|
|
@@ -19326,14 +19167,14 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
19326
19167
|
const localId = typeof id === "string" ? id : "?";
|
|
19327
19168
|
let childDir;
|
|
19328
19169
|
try {
|
|
19329
|
-
childDir =
|
|
19170
|
+
childDir = path18.resolve(projectDir, projectPath);
|
|
19330
19171
|
} catch {
|
|
19331
19172
|
continue;
|
|
19332
19173
|
}
|
|
19333
19174
|
let reason;
|
|
19334
19175
|
if (projectPathEscapesRoot(projectDir, projectPath, childDir)) reason = "escapes";
|
|
19335
19176
|
else if (ancestors.has(chainDirKey(childDir))) reason = "cyclic";
|
|
19336
|
-
else if (!
|
|
19177
|
+
else if (!fs15.existsSync(childDir)) reason = "missing";
|
|
19337
19178
|
else if (depth >= 32) reason = "too-deep";
|
|
19338
19179
|
if (reason) {
|
|
19339
19180
|
const mount = prefix ? qualifyDeclaredId(localId, prefix, true) : localId;
|
|
@@ -19343,7 +19184,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
19343
19184
|
const key = chainDirKey(childDir);
|
|
19344
19185
|
if (listed.has(key)) continue;
|
|
19345
19186
|
listed.add(key);
|
|
19346
|
-
inspection.roots.push(
|
|
19187
|
+
inspection.roots.push(path18.relative(root, childDir).split(path18.sep).join("/"));
|
|
19347
19188
|
walk2(childDir, prefix ? `${prefix}::${localId}` : localId, /* @__PURE__ */ new Set([...ancestors, key]), depth + 1);
|
|
19348
19189
|
}
|
|
19349
19190
|
};
|
|
@@ -19429,9 +19270,9 @@ function stripNamespaceFromImplementation(spec, prefix) {
|
|
|
19429
19270
|
}
|
|
19430
19271
|
function childRelativeFilePaths(spec, authoringRoot, childRoot) {
|
|
19431
19272
|
const reexpress = (p) => {
|
|
19432
|
-
if (
|
|
19433
|
-
const rel2 =
|
|
19434
|
-
const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${
|
|
19273
|
+
if (path18.isAbsolute(p)) return p;
|
|
19274
|
+
const rel2 = path18.relative(childRoot, path18.resolve(authoringRoot, p));
|
|
19275
|
+
const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path18.sep}`) && !path18.isAbsolute(rel2);
|
|
19435
19276
|
return inside ? rel2.replace(/\\/g, "/") : p;
|
|
19436
19277
|
};
|
|
19437
19278
|
return {
|
|
@@ -19466,10 +19307,10 @@ function findOwner(id, components) {
|
|
|
19466
19307
|
}) ?? null;
|
|
19467
19308
|
}
|
|
19468
19309
|
function moveComponentFolder(fromDir, toDir) {
|
|
19469
|
-
if (
|
|
19470
|
-
if (!
|
|
19471
|
-
ensureDir(
|
|
19472
|
-
|
|
19310
|
+
if (path18.normalize(fromDir) === path18.normalize(toDir)) return false;
|
|
19311
|
+
if (!fs15.existsSync(fromDir) || fs15.existsSync(toDir)) return false;
|
|
19312
|
+
ensureDir(path18.dirname(toDir));
|
|
19313
|
+
fs15.renameSync(fromDir, toDir);
|
|
19473
19314
|
return true;
|
|
19474
19315
|
}
|
|
19475
19316
|
function formatZodIssues(error) {
|
|
@@ -19485,13 +19326,13 @@ function parseOrThrow(schema, value, kind, id) {
|
|
|
19485
19326
|
function computeSpecTreeSignature(dirs) {
|
|
19486
19327
|
const parts = [];
|
|
19487
19328
|
for (const dir of dirs) {
|
|
19488
|
-
if (!
|
|
19329
|
+
if (!fs15.existsSync(dir)) {
|
|
19489
19330
|
parts.push(`${dir}:missing`);
|
|
19490
19331
|
continue;
|
|
19491
19332
|
}
|
|
19492
19333
|
for (const f of listSpecFiles(dir)) {
|
|
19493
19334
|
try {
|
|
19494
|
-
const st =
|
|
19335
|
+
const st = fs15.statSync(f);
|
|
19495
19336
|
parts.push(`${f}:${st.mtimeMs}:${st.size}`);
|
|
19496
19337
|
} catch {
|
|
19497
19338
|
parts.push(`${f}:gone`);
|
|
@@ -19884,7 +19725,7 @@ function refusedMoveSummary(from, to, methods, refusals, alternatives) {
|
|
|
19884
19725
|
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
19726
|
}
|
|
19886
19727
|
function workspaceFor(rootDir) {
|
|
19887
|
-
const key =
|
|
19728
|
+
const key = path18.resolve(rootDir);
|
|
19888
19729
|
let ws = workspaces.get(key);
|
|
19889
19730
|
if (!ws) {
|
|
19890
19731
|
ws = new SpecWorkspace(key);
|
|
@@ -20014,13 +19855,13 @@ function snapshotInputKey(snapshot) {
|
|
|
20014
19855
|
return canonicalize(content);
|
|
20015
19856
|
}
|
|
20016
19857
|
function consumedSurfaceInputsAt(rootDir) {
|
|
20017
|
-
const dir =
|
|
19858
|
+
const dir = path18.join(rootDir, ".wai", "surfaces");
|
|
20018
19859
|
if (!pathExists(dir)) return [];
|
|
20019
19860
|
const keys = [];
|
|
20020
|
-
for (const file of
|
|
19861
|
+
for (const file of fs15.readdirSync(dir)) {
|
|
20021
19862
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
20022
19863
|
try {
|
|
20023
|
-
keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(
|
|
19864
|
+
keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path18.join(dir, file)))));
|
|
20024
19865
|
} catch {
|
|
20025
19866
|
}
|
|
20026
19867
|
}
|
|
@@ -20028,7 +19869,7 @@ function consumedSurfaceInputsAt(rootDir) {
|
|
|
20028
19869
|
}
|
|
20029
19870
|
function consumedContractInputs() {
|
|
20030
19871
|
const root = getProjectRoot();
|
|
20031
|
-
const roots = [root, ...listChainedRoots(root).map((rel2) =>
|
|
19872
|
+
const roots = [root, ...listChainedRoots(root).map((rel2) => path18.join(root, rel2))];
|
|
20032
19873
|
return roots.flatMap(consumedSurfaceInputsAt);
|
|
20033
19874
|
}
|
|
20034
19875
|
function readLockState(current2) {
|
|
@@ -20064,7 +19905,7 @@ function markSelectionsBundled(bundled) {
|
|
|
20064
19905
|
projectConfigRepository.markSelectionsBundled(bundled);
|
|
20065
19906
|
}
|
|
20066
19907
|
function computeStateIdAt(root) {
|
|
20067
|
-
const resolved =
|
|
19908
|
+
const resolved = path18.resolve(root);
|
|
20068
19909
|
return runWithProjectRoot(resolved, () => {
|
|
20069
19910
|
workspaceFor(resolved).invalidate();
|
|
20070
19911
|
const system = loadSystemSpec();
|
|
@@ -20102,7 +19943,7 @@ function snapshotSpecFiles() {
|
|
|
20102
19943
|
}
|
|
20103
19944
|
function restoreSpecFiles(snapshot) {
|
|
20104
19945
|
for (const [file, content] of snapshot) {
|
|
20105
|
-
|
|
19946
|
+
fs15.writeFileSync(file, content);
|
|
20106
19947
|
}
|
|
20107
19948
|
}
|
|
20108
19949
|
function findLegacySpecFiles() {
|
|
@@ -20114,12 +19955,12 @@ function updateSpec(kind, id, delta, hooks, dryRun) {
|
|
|
20114
19955
|
function moveMethods(from, to, methods, hooks, dryRun) {
|
|
20115
19956
|
return current().moveMethods(from, to, methods, hooks, dryRun);
|
|
20116
19957
|
}
|
|
20117
|
-
var
|
|
19958
|
+
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
19959
|
var init_specs2 = __esm({
|
|
20119
19960
|
"src/core/specs.ts"() {
|
|
20120
19961
|
"use strict";
|
|
20121
|
-
|
|
20122
|
-
|
|
19962
|
+
fs15 = __toESM(require("fs"));
|
|
19963
|
+
path18 = __toESM(require("path"));
|
|
20123
19964
|
init_paths();
|
|
20124
19965
|
init_project_config();
|
|
20125
19966
|
init_fs();
|
|
@@ -20154,7 +19995,7 @@ var init_specs2 = __esm({
|
|
|
20154
19995
|
this.rootSubsystems = /* @__PURE__ */ new Set();
|
|
20155
19996
|
this.scanVisitedSpecDirs = [];
|
|
20156
19997
|
this.loaderIssues = [];
|
|
20157
|
-
this.rootDir =
|
|
19998
|
+
this.rootDir = path18.resolve(rootDir);
|
|
20158
19999
|
this.paths = aiPathsAt(this.rootDir);
|
|
20159
20000
|
}
|
|
20160
20001
|
invalidate() {
|
|
@@ -20197,8 +20038,8 @@ var init_specs2 = __esm({
|
|
|
20197
20038
|
* qualifies the spec itself — so scoping a validate to a mount keeps it.
|
|
20198
20039
|
*/
|
|
20199
20040
|
loaderIssueSpecId(file, rawId, namespacePrefix) {
|
|
20200
|
-
const stem2 =
|
|
20201
|
-
const local = rawId ?? (stem2.startsWith(".") ?
|
|
20041
|
+
const stem2 = path18.basename(file, ".yaml");
|
|
20042
|
+
const local = rawId ?? (stem2.startsWith(".") ? path18.basename(path18.dirname(file)) : stem2);
|
|
20202
20043
|
return namespacePrefix ? qualifyId(local, namespacePrefix, this.rootSubsystems) : local;
|
|
20203
20044
|
}
|
|
20204
20045
|
scanSpecsForProject(projectDir, namespacePrefix, visitedDirs, maxDepth, currentDepth) {
|
|
@@ -20208,10 +20049,10 @@ var init_specs2 = __esm({
|
|
|
20208
20049
|
this.scanVisitedSpecDirs.push(specsDir);
|
|
20209
20050
|
if (!pathExists(specsDir)) return index;
|
|
20210
20051
|
const files = listSpecFiles(specsDir);
|
|
20211
|
-
const systemYaml =
|
|
20052
|
+
const systemYaml = path18.normalize(projectPaths.specsSystem());
|
|
20212
20053
|
const localSubprojects = [];
|
|
20213
20054
|
for (const file of files) {
|
|
20214
|
-
const normFile =
|
|
20055
|
+
const normFile = path18.normalize(file);
|
|
20215
20056
|
if (normFile === systemYaml) continue;
|
|
20216
20057
|
let detectedType = "spec";
|
|
20217
20058
|
let rawId;
|
|
@@ -20255,7 +20096,7 @@ var init_specs2 = __esm({
|
|
|
20255
20096
|
} else if ("contract" in raw) {
|
|
20256
20097
|
detectedType = "implementation";
|
|
20257
20098
|
const parsed = ImplementationSpecSchema.parse(raw);
|
|
20258
|
-
const normalizeSourcePath = (p) =>
|
|
20099
|
+
const normalizeSourcePath = (p) => path18.relative(projectDir, path18.resolve(projectDir, p)).replace(/\\/g, "/");
|
|
20259
20100
|
if (parsed.sourcePath) parsed.sourcePath = normalizeSourcePath(parsed.sourcePath);
|
|
20260
20101
|
for (const method2 of parsed.methods) {
|
|
20261
20102
|
if (method2.sourcePath) method2.sourcePath = normalizeSourcePath(method2.sourcePath);
|
|
@@ -20381,7 +20222,7 @@ var init_specs2 = __esm({
|
|
|
20381
20222
|
}
|
|
20382
20223
|
if (currentDepth < maxDepth) {
|
|
20383
20224
|
for (const subproj of localSubprojects) {
|
|
20384
|
-
const childDir =
|
|
20225
|
+
const childDir = path18.resolve(projectDir, subproj.projectPath);
|
|
20385
20226
|
const mountId = namespacePrefix ? qualifyDeclaredId(subproj.subsystemId, namespacePrefix, true) : subproj.subsystemId;
|
|
20386
20227
|
if (projectPathEscapesRoot(projectDir, subproj.projectPath, childDir)) {
|
|
20387
20228
|
this.loaderIssues.push({
|
|
@@ -20401,7 +20242,7 @@ var init_specs2 = __esm({
|
|
|
20401
20242
|
});
|
|
20402
20243
|
continue;
|
|
20403
20244
|
}
|
|
20404
|
-
if (!
|
|
20245
|
+
if (!fs15.existsSync(childDir)) {
|
|
20405
20246
|
this.loaderIssues.push({
|
|
20406
20247
|
severity: "error",
|
|
20407
20248
|
code: "SUBPROJECT_NOT_FOUND",
|
|
@@ -20444,7 +20285,7 @@ var init_specs2 = __esm({
|
|
|
20444
20285
|
const index = this.scanAll();
|
|
20445
20286
|
const sub = index.subsystems.find((s) => s.id === currentPrefix);
|
|
20446
20287
|
if (sub && sub.projectPath) {
|
|
20447
|
-
const nextDir =
|
|
20288
|
+
const nextDir = path18.resolve(currentDir, sub.projectPath);
|
|
20448
20289
|
if (projectPathEscapesRoot(currentDir, sub.projectPath, nextDir)) {
|
|
20449
20290
|
this.loaderIssues.push({
|
|
20450
20291
|
severity: "error",
|
|
@@ -20496,9 +20337,9 @@ var init_specs2 = __esm({
|
|
|
20496
20337
|
return index.paths.subsystem[matches[0]];
|
|
20497
20338
|
}
|
|
20498
20339
|
if (pathExists(this.paths.specsSubsystemsDir()) && listFiles(this.paths.specsSubsystemsDir(), ".yaml").length > 0) {
|
|
20499
|
-
return
|
|
20340
|
+
return path18.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
|
|
20500
20341
|
}
|
|
20501
|
-
return
|
|
20342
|
+
return path18.join(this.paths.specsDir(), id, ".index.yaml");
|
|
20502
20343
|
}
|
|
20503
20344
|
getComponentPath(id, subsystemId) {
|
|
20504
20345
|
const index = this.scanAll();
|
|
@@ -20518,21 +20359,21 @@ var init_specs2 = __esm({
|
|
|
20518
20359
|
if (owner) {
|
|
20519
20360
|
const ownerPath = index.paths.component[owner.id];
|
|
20520
20361
|
if (ownerPath && ownerPath.endsWith(".index.yaml")) {
|
|
20521
|
-
return
|
|
20362
|
+
return path18.join(path18.dirname(ownerPath), id, ".index.yaml");
|
|
20522
20363
|
}
|
|
20523
20364
|
}
|
|
20524
20365
|
if (subsystemId) {
|
|
20525
20366
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20526
|
-
const subDir =
|
|
20367
|
+
const subDir = path18.dirname(subPath);
|
|
20527
20368
|
if (subPath.endsWith(".index.yaml")) {
|
|
20528
|
-
return
|
|
20369
|
+
return path18.join(subDir, id, ".index.yaml");
|
|
20529
20370
|
}
|
|
20530
20371
|
}
|
|
20531
20372
|
if (pathExists(this.paths.specsComponentsDir()) && listFiles(this.paths.specsComponentsDir(), ".yaml").length > 0) {
|
|
20532
|
-
return
|
|
20373
|
+
return path18.join(this.paths.specsComponentsDir(), `${id}.yaml`);
|
|
20533
20374
|
}
|
|
20534
20375
|
const targetSubsystem = subsystemId || "default";
|
|
20535
|
-
return
|
|
20376
|
+
return path18.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
|
|
20536
20377
|
}
|
|
20537
20378
|
getInterfacePath(id, componentId) {
|
|
20538
20379
|
const index = this.scanAll();
|
|
@@ -20558,16 +20399,16 @@ var init_specs2 = __esm({
|
|
|
20558
20399
|
}
|
|
20559
20400
|
if (componentId) {
|
|
20560
20401
|
const compPath = this.getComponentPath(componentId);
|
|
20561
|
-
const compDir =
|
|
20402
|
+
const compDir = path18.dirname(compPath);
|
|
20562
20403
|
if (compPath.endsWith(".index.yaml")) {
|
|
20563
|
-
return
|
|
20404
|
+
return path18.join(compDir, ".interface.yaml");
|
|
20564
20405
|
}
|
|
20565
20406
|
}
|
|
20566
20407
|
if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
|
|
20567
|
-
return
|
|
20408
|
+
return path18.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
|
|
20568
20409
|
}
|
|
20569
20410
|
const targetComponent = componentId || "default";
|
|
20570
|
-
return
|
|
20411
|
+
return path18.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
|
|
20571
20412
|
}
|
|
20572
20413
|
getImplementationPath(id, contractId) {
|
|
20573
20414
|
const index = this.scanAll();
|
|
@@ -20593,16 +20434,16 @@ var init_specs2 = __esm({
|
|
|
20593
20434
|
}
|
|
20594
20435
|
if (contractId) {
|
|
20595
20436
|
const intfPath = this.getInterfacePath(contractId);
|
|
20596
|
-
const intfDir =
|
|
20437
|
+
const intfDir = path18.dirname(intfPath);
|
|
20597
20438
|
if (intfPath.endsWith(".interface.yaml")) {
|
|
20598
|
-
return
|
|
20439
|
+
return path18.join(intfDir, ".implementation.yaml");
|
|
20599
20440
|
}
|
|
20600
20441
|
}
|
|
20601
20442
|
if (pathExists(this.paths.specsImplementationsDir()) && listFiles(this.paths.specsImplementationsDir(), ".yaml").length > 0) {
|
|
20602
|
-
return
|
|
20443
|
+
return path18.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
|
|
20603
20444
|
}
|
|
20604
20445
|
const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
|
|
20605
|
-
return
|
|
20446
|
+
return path18.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
|
|
20606
20447
|
}
|
|
20607
20448
|
getTypePath(id, subsystemId, group) {
|
|
20608
20449
|
const index = this.scanAll();
|
|
@@ -20633,7 +20474,7 @@ var init_specs2 = __esm({
|
|
|
20633
20474
|
const groupPath = index.paths.group[targetGroup] || index.paths.group[plainGroup];
|
|
20634
20475
|
if (groupPath) {
|
|
20635
20476
|
const localId2 = id.split("::").pop();
|
|
20636
|
-
return
|
|
20477
|
+
return path18.join(path18.dirname(groupPath), `${localId2}.yaml`);
|
|
20637
20478
|
}
|
|
20638
20479
|
}
|
|
20639
20480
|
let localId = id;
|
|
@@ -20646,12 +20487,12 @@ var init_specs2 = __esm({
|
|
|
20646
20487
|
}
|
|
20647
20488
|
if (subsystemId) {
|
|
20648
20489
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20649
|
-
const subDir =
|
|
20490
|
+
const subDir = path18.dirname(subPath);
|
|
20650
20491
|
if (subPath.endsWith(".index.yaml")) {
|
|
20651
|
-
return
|
|
20492
|
+
return path18.join(subDir, "types", `${localId}.yaml`);
|
|
20652
20493
|
}
|
|
20653
20494
|
}
|
|
20654
|
-
return
|
|
20495
|
+
return path18.join(this.paths.specsTypesDir(), `${localId}.yaml`);
|
|
20655
20496
|
}
|
|
20656
20497
|
getGroupPath(id, subsystemId) {
|
|
20657
20498
|
const index = this.scanAll();
|
|
@@ -20685,12 +20526,12 @@ var init_specs2 = __esm({
|
|
|
20685
20526
|
}
|
|
20686
20527
|
if (subsystemId) {
|
|
20687
20528
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20688
|
-
const subDir =
|
|
20529
|
+
const subDir = path18.dirname(subPath);
|
|
20689
20530
|
if (subPath.endsWith(".index.yaml")) {
|
|
20690
|
-
return
|
|
20531
|
+
return path18.join(subDir, "types", localId, ".index.yaml");
|
|
20691
20532
|
}
|
|
20692
20533
|
}
|
|
20693
|
-
return
|
|
20534
|
+
return path18.join(this.paths.specsTypesDir(), localId, ".index.yaml");
|
|
20694
20535
|
}
|
|
20695
20536
|
// -------------------------------------------------------------------------
|
|
20696
20537
|
// Level 0: System
|
|
@@ -20713,7 +20554,7 @@ var init_specs2 = __esm({
|
|
|
20713
20554
|
}
|
|
20714
20555
|
saveSystemSpec(spec) {
|
|
20715
20556
|
const p = this.paths.specsSystem();
|
|
20716
|
-
ensureDir(
|
|
20557
|
+
ensureDir(path18.dirname(p));
|
|
20717
20558
|
writeSpecFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
|
|
20718
20559
|
invalidateSpecCache();
|
|
20719
20560
|
}
|
|
@@ -20835,7 +20676,7 @@ var init_specs2 = __esm({
|
|
|
20835
20676
|
}
|
|
20836
20677
|
saveSubsystemSpec(spec, opts) {
|
|
20837
20678
|
const p = this.getSubsystemPath(spec.id);
|
|
20838
|
-
ensureDir(
|
|
20679
|
+
ensureDir(path18.dirname(p));
|
|
20839
20680
|
const { prefix } = splitNamespace(spec.id);
|
|
20840
20681
|
if (!prefix && spec.projectPath && spec.projectPath.trim() !== "") {
|
|
20841
20682
|
assertContainedProjectPath(this.rootDir, spec.projectPath);
|
|
@@ -20902,7 +20743,7 @@ var init_specs2 = __esm({
|
|
|
20902
20743
|
saveComponentSpec(spec, opts) {
|
|
20903
20744
|
const notices = [];
|
|
20904
20745
|
const p = this.getComponentPath(spec.id, spec.subsystem);
|
|
20905
|
-
ensureDir(
|
|
20746
|
+
ensureDir(path18.dirname(p));
|
|
20906
20747
|
const specToWrite = this.prepareComponentForWrite(spec);
|
|
20907
20748
|
const existing = this.loadComponentSpec(spec.id);
|
|
20908
20749
|
if (existing) {
|
|
@@ -20919,7 +20760,7 @@ var init_specs2 = __esm({
|
|
|
20919
20760
|
const subsystemChanged = existing && existing.subsystem !== spec.subsystem && splitNamespace(existing.subsystem).localId !== splitNamespace(spec.subsystem).localId;
|
|
20920
20761
|
if (subsystemChanged && !p.endsWith(".index.yaml")) {
|
|
20921
20762
|
notices.push(
|
|
20922
|
-
`component "${spec.id}" already exists at ${
|
|
20763
|
+
`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
20764
|
);
|
|
20924
20765
|
}
|
|
20925
20766
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -20943,12 +20784,12 @@ var init_specs2 = __esm({
|
|
|
20943
20784
|
if (owner) {
|
|
20944
20785
|
const ownerPath = index.paths.component[owner.id];
|
|
20945
20786
|
if (ownerPath && ownerPath.endsWith(".index.yaml")) {
|
|
20946
|
-
const ownerSubDir =
|
|
20947
|
-
return
|
|
20787
|
+
const ownerSubDir = path18.dirname(this.getSubsystemPath(owner.subsystem));
|
|
20788
|
+
return path18.join(ownerSubDir, owner.id, comp.id);
|
|
20948
20789
|
}
|
|
20949
20790
|
}
|
|
20950
|
-
const subDir =
|
|
20951
|
-
return
|
|
20791
|
+
const subDir = path18.dirname(this.getSubsystemPath(comp.subsystem));
|
|
20792
|
+
return path18.join(subDir, comp.id);
|
|
20952
20793
|
}
|
|
20953
20794
|
/**
|
|
20954
20795
|
* Move component folders so the physical tree mirrors ownership: each owned
|
|
@@ -20964,7 +20805,7 @@ var init_specs2 = __esm({
|
|
|
20964
20805
|
if (!currentPath) continue;
|
|
20965
20806
|
const desiredDir = this.desiredComponentDir(comp, index);
|
|
20966
20807
|
if (!desiredDir) continue;
|
|
20967
|
-
if (moveComponentFolder(
|
|
20808
|
+
if (moveComponentFolder(path18.dirname(currentPath), desiredDir)) moved.push(comp.id);
|
|
20968
20809
|
}
|
|
20969
20810
|
if (moved.length) invalidateSpecCache();
|
|
20970
20811
|
return moved;
|
|
@@ -21020,7 +20861,7 @@ var init_specs2 = __esm({
|
|
|
21020
20861
|
if (!occupantId) return;
|
|
21021
20862
|
if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
|
|
21022
20863
|
throw new Error(
|
|
21023
|
-
`Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${
|
|
20864
|
+
`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
20865
|
);
|
|
21025
20866
|
}
|
|
21026
20867
|
/** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
|
|
@@ -21028,12 +20869,12 @@ var init_specs2 = __esm({
|
|
|
21028
20869
|
const notices = [];
|
|
21029
20870
|
const p = this.getInterfacePath(spec.id, spec.component);
|
|
21030
20871
|
this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
|
|
21031
|
-
ensureDir(
|
|
20872
|
+
ensureDir(path18.dirname(p));
|
|
21032
20873
|
const specToWrite = this.prepareInterfaceForWrite(spec);
|
|
21033
20874
|
const existing = this.loadInterfaceSpec(spec.id);
|
|
21034
20875
|
if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
|
|
21035
20876
|
notices.push(
|
|
21036
|
-
`interface "${spec.id}" already exists at ${
|
|
20877
|
+
`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
20878
|
);
|
|
21038
20879
|
}
|
|
21039
20880
|
if (existing) {
|
|
@@ -21090,12 +20931,12 @@ var init_specs2 = __esm({
|
|
|
21090
20931
|
const notices = [];
|
|
21091
20932
|
const p = this.getImplementationPath(spec.id, spec.contract);
|
|
21092
20933
|
this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
|
|
21093
|
-
ensureDir(
|
|
20934
|
+
ensureDir(path18.dirname(p));
|
|
21094
20935
|
const specToWrite = this.prepareImplementationForWrite(spec);
|
|
21095
20936
|
const existing = this.loadImplementationSpec(spec.id);
|
|
21096
20937
|
if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
|
|
21097
20938
|
notices.push(
|
|
21098
|
-
`implementation "${spec.id}" already exists at ${
|
|
20939
|
+
`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
20940
|
);
|
|
21100
20941
|
}
|
|
21101
20942
|
if (existing) {
|
|
@@ -21136,11 +20977,11 @@ var init_specs2 = __esm({
|
|
|
21136
20977
|
const existing = this.loadTypeSpec(spec.id);
|
|
21137
20978
|
const group = spec.group || (existing ? existing.group : void 0);
|
|
21138
20979
|
const p = this.getTypePath(spec.id, spec.subsystem, group);
|
|
21139
|
-
ensureDir(
|
|
20980
|
+
ensureDir(path18.dirname(p));
|
|
21140
20981
|
const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
|
|
21141
20982
|
if (subsystemChanged) {
|
|
21142
20983
|
notices.push(
|
|
21143
|
-
`type "${spec.id}" already exists at ${
|
|
20984
|
+
`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
20985
|
);
|
|
21145
20986
|
}
|
|
21146
20987
|
if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
|
|
@@ -21178,7 +21019,7 @@ var init_specs2 = __esm({
|
|
|
21178
21019
|
}
|
|
21179
21020
|
saveGroupSpec(spec, opts) {
|
|
21180
21021
|
const p = this.getGroupPath(spec.id);
|
|
21181
|
-
ensureDir(
|
|
21022
|
+
ensureDir(path18.dirname(p));
|
|
21182
21023
|
const specToWrite = this.prepareGroupForWrite(spec);
|
|
21183
21024
|
const existing = this.loadGroupSpec(spec.id);
|
|
21184
21025
|
if (existing) {
|
|
@@ -21256,7 +21097,7 @@ var init_specs2 = __esm({
|
|
|
21256
21097
|
};
|
|
21257
21098
|
const out = /* @__PURE__ */ new Set();
|
|
21258
21099
|
const add = (p) => {
|
|
21259
|
-
if (p) out.add(
|
|
21100
|
+
if (p) out.add(path18.resolve(p));
|
|
21260
21101
|
};
|
|
21261
21102
|
for (const s of this.loadSubsystemSpecs()) {
|
|
21262
21103
|
if (!scopeSubsystem || s.id === scopeSubsystem || s.id.startsWith(`${scopeSubsystem}::`)) {
|
|
@@ -21327,16 +21168,16 @@ var init_specs2 = __esm({
|
|
|
21327
21168
|
const files = /* @__PURE__ */ new Set();
|
|
21328
21169
|
const sysPath = this.paths.specsSystem();
|
|
21329
21170
|
if (pathExists(sysPath)) {
|
|
21330
|
-
files.add(
|
|
21171
|
+
files.add(path18.resolve(sysPath));
|
|
21331
21172
|
}
|
|
21332
21173
|
for (const group of Object.values(index.paths)) {
|
|
21333
21174
|
for (const file of Object.values(group)) {
|
|
21334
|
-
files.add(
|
|
21175
|
+
files.add(path18.resolve(file));
|
|
21335
21176
|
}
|
|
21336
21177
|
}
|
|
21337
21178
|
for (const file of files) {
|
|
21338
|
-
if (
|
|
21339
|
-
snapshot.set(file,
|
|
21179
|
+
if (fs15.existsSync(file)) {
|
|
21180
|
+
snapshot.set(file, fs15.readFileSync(file, "utf8"));
|
|
21340
21181
|
}
|
|
21341
21182
|
}
|
|
21342
21183
|
return snapshot;
|
|
@@ -21350,20 +21191,20 @@ var init_specs2 = __esm({
|
|
|
21350
21191
|
const files = listSpecFiles(specsDir);
|
|
21351
21192
|
const legacy = [];
|
|
21352
21193
|
for (const f of files) {
|
|
21353
|
-
const base =
|
|
21354
|
-
const dir =
|
|
21194
|
+
const base = path18.basename(f);
|
|
21195
|
+
const dir = path18.dirname(f);
|
|
21355
21196
|
if (base === "system.yaml") {
|
|
21356
|
-
legacy.push({ path: f, expected:
|
|
21197
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21357
21198
|
} else if (base === "subsystem.yaml") {
|
|
21358
|
-
legacy.push({ path: f, expected:
|
|
21199
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21359
21200
|
} else if (base === "component.yaml") {
|
|
21360
|
-
legacy.push({ path: f, expected:
|
|
21201
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21361
21202
|
} else if (base === "group.yaml") {
|
|
21362
|
-
legacy.push({ path: f, expected:
|
|
21203
|
+
legacy.push({ path: f, expected: path18.join(dir, ".index.yaml") });
|
|
21363
21204
|
} else if (base === "interface.yaml") {
|
|
21364
|
-
legacy.push({ path: f, expected:
|
|
21205
|
+
legacy.push({ path: f, expected: path18.join(dir, ".interface.yaml") });
|
|
21365
21206
|
} else if (base === "implementation.yaml") {
|
|
21366
|
-
legacy.push({ path: f, expected:
|
|
21207
|
+
legacy.push({ path: f, expected: path18.join(dir, ".implementation.yaml") });
|
|
21367
21208
|
}
|
|
21368
21209
|
}
|
|
21369
21210
|
return legacy;
|
|
@@ -22366,18 +22207,76 @@ var init_specs2 = __esm({
|
|
|
22366
22207
|
}
|
|
22367
22208
|
});
|
|
22368
22209
|
|
|
22210
|
+
// src/config/loader.ts
|
|
22211
|
+
function loadTopologyConfig() {
|
|
22212
|
+
assertProjectInitialized();
|
|
22213
|
+
if (!pathExists(AI_PATHS.topologyConfig())) return createEmptyTopologyConfig();
|
|
22214
|
+
const raw = readYamlFile(AI_PATHS.topologyConfig());
|
|
22215
|
+
if (!raw) return createEmptyTopologyConfig();
|
|
22216
|
+
return TopologyConfigSchema.parse(raw);
|
|
22217
|
+
}
|
|
22218
|
+
function saveTopologyConfig(config) {
|
|
22219
|
+
writeYamlFile(AI_PATHS.topologyConfig(), config);
|
|
22220
|
+
}
|
|
22221
|
+
var init_loader = __esm({
|
|
22222
|
+
"src/config/loader.ts"() {
|
|
22223
|
+
"use strict";
|
|
22224
|
+
init_fs();
|
|
22225
|
+
init_yaml();
|
|
22226
|
+
init_models();
|
|
22227
|
+
init_paths();
|
|
22228
|
+
}
|
|
22229
|
+
});
|
|
22230
|
+
|
|
22369
22231
|
// src/core/domains.ts
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
22373
|
-
|
|
22374
|
-
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
22232
|
+
function addFreeStandingDomain(domain) {
|
|
22233
|
+
const config = loadTopologyConfig();
|
|
22234
|
+
if (config.domains.some((d) => d.id === domain.id)) {
|
|
22235
|
+
throw new WaironError(`A free-standing domain "${domain.id}" already exists in .wai/topology.yaml.`);
|
|
22236
|
+
}
|
|
22237
|
+
config.domains.push(domain);
|
|
22238
|
+
saveTopologyConfig(config);
|
|
22239
|
+
}
|
|
22240
|
+
function removeFreeStandingDomain(id) {
|
|
22241
|
+
const config = loadTopologyConfig();
|
|
22242
|
+
const idx = config.domains.findIndex((d) => d.id === id);
|
|
22243
|
+
if (idx === -1) {
|
|
22244
|
+
throw new WaironError(
|
|
22245
|
+
`"${id}" is not a free-standing domain. Subsystem-backed domains are derived from the spec tree and cannot be removed here.`
|
|
22246
|
+
);
|
|
22247
|
+
}
|
|
22248
|
+
config.domains.splice(idx, 1);
|
|
22249
|
+
saveTopologyConfig(config);
|
|
22250
|
+
}
|
|
22251
|
+
var init_domains = __esm({
|
|
22252
|
+
"src/core/domains.ts"() {
|
|
22253
|
+
"use strict";
|
|
22254
|
+
init_loader();
|
|
22255
|
+
init_errors();
|
|
22256
|
+
}
|
|
22257
|
+
});
|
|
22258
|
+
|
|
22259
|
+
// src/core/topology.ts
|
|
22260
|
+
function addFreeStanding(domain) {
|
|
22261
|
+
addFreeStandingDomain(domain);
|
|
22262
|
+
}
|
|
22263
|
+
function removeFreeStanding(id) {
|
|
22264
|
+
removeFreeStandingDomain(id);
|
|
22265
|
+
}
|
|
22266
|
+
function loadConfig() {
|
|
22267
|
+
return loadTopologyConfig();
|
|
22268
|
+
}
|
|
22269
|
+
var init_topology = __esm({
|
|
22270
|
+
"src/core/topology.ts"() {
|
|
22271
|
+
"use strict";
|
|
22272
|
+
init_domains();
|
|
22273
|
+
init_loader();
|
|
22274
|
+
}
|
|
22378
22275
|
});
|
|
22276
|
+
|
|
22277
|
+
// src/core/domain_projector.ts
|
|
22379
22278
|
function rel(p) {
|
|
22380
|
-
return
|
|
22279
|
+
return path19.relative(process.cwd(), p).replace(/\\/g, "/");
|
|
22381
22280
|
}
|
|
22382
22281
|
function deriveSubsystemDomains() {
|
|
22383
22282
|
const subsystems = loadSubsystemSpecs();
|
|
@@ -22396,45 +22295,210 @@ function deriveSubsystemDomains() {
|
|
|
22396
22295
|
};
|
|
22397
22296
|
});
|
|
22398
22297
|
}
|
|
22399
|
-
function listFreeStandingDomains() {
|
|
22400
|
-
return loadTopologyConfig().domains;
|
|
22401
|
-
}
|
|
22402
22298
|
function resolveDomains() {
|
|
22403
|
-
|
|
22404
|
-
|
|
22405
|
-
|
|
22406
|
-
return resolveDomains().find((d) => d.id === id);
|
|
22299
|
+
const derived = deriveSubsystemDomains();
|
|
22300
|
+
const registered = loadConfig().domains;
|
|
22301
|
+
return [...derived, ...registered];
|
|
22407
22302
|
}
|
|
22408
|
-
|
|
22409
|
-
|
|
22410
|
-
|
|
22411
|
-
|
|
22303
|
+
var path19;
|
|
22304
|
+
var init_domain_projector = __esm({
|
|
22305
|
+
"src/core/domain_projector.ts"() {
|
|
22306
|
+
"use strict";
|
|
22307
|
+
path19 = __toESM(require("path"));
|
|
22308
|
+
init_specs2();
|
|
22309
|
+
init_topology();
|
|
22412
22310
|
}
|
|
22413
|
-
|
|
22414
|
-
|
|
22311
|
+
});
|
|
22312
|
+
|
|
22313
|
+
// src/core/domain_curator.ts
|
|
22314
|
+
function registerDomain(domain) {
|
|
22315
|
+
const taken = resolveDomains().find((d) => d.id === domain.id);
|
|
22316
|
+
if (taken) {
|
|
22317
|
+
throw new WaironError(refusal(taken));
|
|
22415
22318
|
}
|
|
22416
|
-
|
|
22417
|
-
saveTopologyConfig(config);
|
|
22319
|
+
addFreeStanding(domain);
|
|
22418
22320
|
}
|
|
22419
|
-
function
|
|
22420
|
-
|
|
22421
|
-
|
|
22422
|
-
|
|
22423
|
-
|
|
22424
|
-
|
|
22321
|
+
function refusal(taken) {
|
|
22322
|
+
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.`;
|
|
22323
|
+
}
|
|
22324
|
+
function unregisterDomain(id) {
|
|
22325
|
+
removeFreeStanding(id);
|
|
22326
|
+
}
|
|
22327
|
+
var init_domain_curator = __esm({
|
|
22328
|
+
"src/core/domain_curator.ts"() {
|
|
22329
|
+
"use strict";
|
|
22330
|
+
init_domain_projector();
|
|
22331
|
+
init_topology();
|
|
22332
|
+
init_errors();
|
|
22333
|
+
}
|
|
22334
|
+
});
|
|
22335
|
+
|
|
22336
|
+
// src/core/detection.ts
|
|
22337
|
+
function detectDomainCandidates(projectRoot2, alreadyTrackedPaths = /* @__PURE__ */ new Set(), alreadyTrackedIds = /* @__PURE__ */ new Set()) {
|
|
22338
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
22339
|
+
for (const c of detectGitSubmodules(projectRoot2)) {
|
|
22340
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22341
|
+
}
|
|
22342
|
+
for (const c of detectNestedGitRepos(projectRoot2)) {
|
|
22343
|
+
if (!candidates.has(c.path)) {
|
|
22344
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22345
|
+
}
|
|
22346
|
+
}
|
|
22347
|
+
const gitPaths = new Set(
|
|
22348
|
+
Array.from(candidates.values()).filter((c) => c.type === "git-submodule" || c.type === "git-repo").map((c) => c.path)
|
|
22349
|
+
);
|
|
22350
|
+
for (const c of detectPackageRoots(projectRoot2)) {
|
|
22351
|
+
if (candidates.has(c.path)) continue;
|
|
22352
|
+
const insideGit = Array.from(gitPaths).some(
|
|
22353
|
+
(gp) => c.path === gp || c.path.startsWith(gp + "/")
|
|
22425
22354
|
);
|
|
22355
|
+
if (insideGit) continue;
|
|
22356
|
+
candidates.set(c.path, { ...c, alreadyTracked: alreadyTrackedPaths.has(c.path) });
|
|
22426
22357
|
}
|
|
22427
|
-
|
|
22428
|
-
|
|
22358
|
+
const sorted = Array.from(candidates.values()).sort((a, b) => a.path.localeCompare(b.path));
|
|
22359
|
+
return deduplicateIds(sorted, alreadyTrackedIds);
|
|
22429
22360
|
}
|
|
22430
|
-
|
|
22431
|
-
|
|
22432
|
-
|
|
22361
|
+
function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
|
|
22362
|
+
const idCount = /* @__PURE__ */ new Map();
|
|
22363
|
+
for (const id of existingIds) {
|
|
22364
|
+
idCount.set(id, (idCount.get(id) ?? 0) + 1);
|
|
22365
|
+
}
|
|
22366
|
+
for (const c of candidates) {
|
|
22367
|
+
idCount.set(c.suggestedId, (idCount.get(c.suggestedId) ?? 0) + 1);
|
|
22368
|
+
}
|
|
22369
|
+
return candidates.map((c) => {
|
|
22370
|
+
if ((idCount.get(c.suggestedId) ?? 0) <= 1) return c;
|
|
22371
|
+
const parts = c.path.split("/");
|
|
22372
|
+
const qualifiedId2 = parts.length >= 2 ? pathToId(`${parts[parts.length - 2]}-${parts[parts.length - 1]}`) : c.suggestedId;
|
|
22373
|
+
return { ...c, suggestedId: qualifiedId2 };
|
|
22374
|
+
});
|
|
22375
|
+
}
|
|
22376
|
+
function parseGitmodules(filePath) {
|
|
22377
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
22378
|
+
const entries = [];
|
|
22379
|
+
let current2 = {};
|
|
22380
|
+
for (const line2 of content.split("\n")) {
|
|
22381
|
+
const trimmed = line2.trim();
|
|
22382
|
+
const headerMatch = trimmed.match(/^\[submodule "(.+)"\]$/);
|
|
22383
|
+
if (headerMatch) {
|
|
22384
|
+
if (current2.path) entries.push(current2);
|
|
22385
|
+
current2 = { name: headerMatch[1] };
|
|
22386
|
+
continue;
|
|
22387
|
+
}
|
|
22388
|
+
const keyVal = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
|
|
22389
|
+
if (keyVal) {
|
|
22390
|
+
const [, key, value] = keyVal;
|
|
22391
|
+
if (key === "path") current2.path = value.trim();
|
|
22392
|
+
if (key === "url") current2.url = value.trim();
|
|
22393
|
+
}
|
|
22394
|
+
}
|
|
22395
|
+
if (current2.path) entries.push(current2);
|
|
22396
|
+
return entries;
|
|
22397
|
+
}
|
|
22398
|
+
function detectGitSubmodules(projectRoot2) {
|
|
22399
|
+
const gitmodulesPath = path20.join(projectRoot2, ".gitmodules");
|
|
22400
|
+
if (!fs16.existsSync(gitmodulesPath)) return [];
|
|
22401
|
+
return parseGitmodules(gitmodulesPath).map((entry) => ({
|
|
22402
|
+
suggestedId: pathToId(entry.path),
|
|
22403
|
+
suggestedName: pathToName(entry.path),
|
|
22404
|
+
path: normalizePath(entry.path),
|
|
22405
|
+
type: "git-submodule",
|
|
22406
|
+
alreadyTracked: false
|
|
22407
|
+
}));
|
|
22408
|
+
}
|
|
22409
|
+
function detectNestedGitRepos(projectRoot2) {
|
|
22410
|
+
const results = [];
|
|
22411
|
+
walkForGit(projectRoot2, projectRoot2, 0, results);
|
|
22412
|
+
return results;
|
|
22413
|
+
}
|
|
22414
|
+
function walkForGit(projectRoot2, currentDir, depth, results) {
|
|
22415
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
22416
|
+
let entries;
|
|
22417
|
+
try {
|
|
22418
|
+
entries = fs16.readdirSync(currentDir, { withFileTypes: true });
|
|
22419
|
+
} catch {
|
|
22420
|
+
return;
|
|
22421
|
+
}
|
|
22422
|
+
for (const entry of entries) {
|
|
22423
|
+
if (!entry.isDirectory()) continue;
|
|
22424
|
+
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22425
|
+
const fullPath = path20.join(currentDir, entry.name);
|
|
22426
|
+
const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
|
|
22427
|
+
if (relPath === "" || relPath === ".") continue;
|
|
22428
|
+
const gitPath = path20.join(fullPath, ".git");
|
|
22429
|
+
if (fs16.existsSync(gitPath)) {
|
|
22430
|
+
results.push({
|
|
22431
|
+
suggestedId: pathToId(relPath),
|
|
22432
|
+
suggestedName: pathToName(relPath),
|
|
22433
|
+
path: relPath,
|
|
22434
|
+
type: "git-repo",
|
|
22435
|
+
alreadyTracked: false
|
|
22436
|
+
});
|
|
22437
|
+
continue;
|
|
22438
|
+
}
|
|
22439
|
+
walkForGit(projectRoot2, fullPath, depth + 1, results);
|
|
22440
|
+
}
|
|
22441
|
+
}
|
|
22442
|
+
function detectPackageRoots(projectRoot2) {
|
|
22443
|
+
const results = [];
|
|
22444
|
+
walkForPackages(projectRoot2, projectRoot2, 0, results);
|
|
22445
|
+
return results;
|
|
22446
|
+
}
|
|
22447
|
+
function walkForPackages(projectRoot2, currentDir, depth, results) {
|
|
22448
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
22449
|
+
let entries;
|
|
22450
|
+
try {
|
|
22451
|
+
entries = fs16.readdirSync(currentDir, { withFileTypes: true });
|
|
22452
|
+
} catch {
|
|
22453
|
+
return;
|
|
22454
|
+
}
|
|
22455
|
+
for (const entry of entries) {
|
|
22456
|
+
if (!entry.isDirectory()) continue;
|
|
22457
|
+
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22458
|
+
const fullPath = path20.join(currentDir, entry.name);
|
|
22459
|
+
const relPath = normalizePath(path20.relative(projectRoot2, fullPath));
|
|
22460
|
+
if (relPath === "" || relPath === ".") continue;
|
|
22461
|
+
const hasMarker = PACKAGE_MARKERS.some((m) => fs16.existsSync(path20.join(fullPath, m)));
|
|
22462
|
+
if (hasMarker) {
|
|
22463
|
+
results.push({
|
|
22464
|
+
suggestedId: pathToId(relPath),
|
|
22465
|
+
suggestedName: pathToName(relPath),
|
|
22466
|
+
path: relPath,
|
|
22467
|
+
type: "package-root",
|
|
22468
|
+
alreadyTracked: false
|
|
22469
|
+
});
|
|
22470
|
+
}
|
|
22471
|
+
walkForPackages(projectRoot2, fullPath, depth + 1, results);
|
|
22472
|
+
}
|
|
22473
|
+
}
|
|
22474
|
+
function pathToId(relPath) {
|
|
22475
|
+
const basename15 = path20.basename(relPath);
|
|
22476
|
+
return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
22477
|
+
}
|
|
22478
|
+
function pathToName(relPath) {
|
|
22479
|
+
const id = pathToId(relPath);
|
|
22480
|
+
return id.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
22481
|
+
}
|
|
22482
|
+
function normalizePath(p) {
|
|
22483
|
+
return p.replace(/\\/g, "/");
|
|
22484
|
+
}
|
|
22485
|
+
var fs16, path20, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
|
|
22486
|
+
var init_detection = __esm({
|
|
22487
|
+
"src/core/detection.ts"() {
|
|
22433
22488
|
"use strict";
|
|
22489
|
+
fs16 = __toESM(require("fs"));
|
|
22434
22490
|
path20 = __toESM(require("path"));
|
|
22435
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
22491
|
+
init_defaults();
|
|
22492
|
+
PACKAGE_MARKERS = [
|
|
22493
|
+
"package.json",
|
|
22494
|
+
"pyproject.toml",
|
|
22495
|
+
"Cargo.toml",
|
|
22496
|
+
"go.mod",
|
|
22497
|
+
"build.gradle",
|
|
22498
|
+
"build.gradle.kts",
|
|
22499
|
+
"pom.xml"
|
|
22500
|
+
];
|
|
22501
|
+
MAX_SCAN_DEPTH = 5;
|
|
22438
22502
|
}
|
|
22439
22503
|
});
|
|
22440
22504
|
|
|
@@ -23218,21 +23282,6 @@ function resolveBudget(profile, config, agentId) {
|
|
|
23218
23282
|
const override = config.overrides[agentId];
|
|
23219
23283
|
return override ? { ...budget, ...override } : budget;
|
|
23220
23284
|
}
|
|
23221
|
-
function describeBudget(profile, budget) {
|
|
23222
|
-
const lines = [
|
|
23223
|
-
`- **Work shape**: ${profile.breadth} breadth, ${profile.reasoningDepth} reasoning${profile.writes ? "" : ", read-only"}${profile.delegates ? ", delegating" : ""}`,
|
|
23224
|
-
`- **Why**: ${profile.rationale}`
|
|
23225
|
-
];
|
|
23226
|
-
if (budget.modelTier) lines.push(`- **Capability tier**: ${budget.modelTier}`);
|
|
23227
|
-
if (budget.effort) lines.push(`- **Effort**: ${budget.effort}`);
|
|
23228
|
-
if (budget.maxTurns !== void 0) {
|
|
23229
|
-
lines.push(`- **Turn ceiling**: ${budget.maxTurns} (a circuit breaker \u2014 hitting it should read as a scoping error, not a limit to work up to)`);
|
|
23230
|
-
}
|
|
23231
|
-
lines.push(`- **Tool grant**: ${budget.toolClass}`);
|
|
23232
|
-
lines.push(`- **May delegate further**: ${budget.allowNestedDelegation ? "yes" : "no"}`);
|
|
23233
|
-
lines.push(`- **MCP access**: ${budget.mcp}`);
|
|
23234
|
-
return lines;
|
|
23235
|
-
}
|
|
23236
23285
|
var TIER_ORDER, TIER_STEPS;
|
|
23237
23286
|
var init_budget_policy = __esm({
|
|
23238
23287
|
"src/core/budget_policy.ts"() {
|
|
@@ -23373,7 +23422,7 @@ function inferSourcePathForComponent(comp, subsystems) {
|
|
|
23373
23422
|
return null;
|
|
23374
23423
|
}
|
|
23375
23424
|
}
|
|
23376
|
-
function
|
|
23425
|
+
function summarize2(text2, max = 140) {
|
|
23377
23426
|
const clean = text2.replace(/\s+/g, " ").trim();
|
|
23378
23427
|
const period = clean.indexOf(". ");
|
|
23379
23428
|
const firstSentence = period > 0 ? clean.slice(0, period + 1) : clean;
|
|
@@ -23400,7 +23449,7 @@ function resolveAgentTopology() {
|
|
|
23400
23449
|
agents.push({
|
|
23401
23450
|
id: "system-architect",
|
|
23402
23451
|
name: `${system.name} Architect`,
|
|
23403
|
-
description: `Global architect for ${system.name} \u2014 owns the spec tree and topology. ${
|
|
23452
|
+
description: `Global architect for ${system.name} \u2014 owns the spec tree and topology. ${summarize2(system.vision)}`,
|
|
23404
23453
|
template: "architect",
|
|
23405
23454
|
creationReason: "Automatically inferred from L0 system spec",
|
|
23406
23455
|
ownedPaths: [".wai/specs/**"],
|
|
@@ -23480,7 +23529,7 @@ function resolveAgentTopology() {
|
|
|
23480
23529
|
agents.push({
|
|
23481
23530
|
id: `${sub.id}-owner`,
|
|
23482
23531
|
name: `${sub.name} Owner`,
|
|
23483
|
-
description: `Owns the ${sub.id} subsystem. ${
|
|
23532
|
+
description: `Owns the ${sub.id} subsystem. ${summarize2(sub.description)}`,
|
|
23484
23533
|
template: "domain-owner",
|
|
23485
23534
|
creationReason: `Automatically inferred from L1 subsystem spec: ${sub.id}`,
|
|
23486
23535
|
domainRoot: sub.id,
|
|
@@ -23541,11 +23590,11 @@ function resolveAgentTopology() {
|
|
|
23541
23590
|
}
|
|
23542
23591
|
}
|
|
23543
23592
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
23544
|
-
for (const dom of
|
|
23593
|
+
for (const dom of loadConfig().domains) {
|
|
23545
23594
|
agents.push({
|
|
23546
23595
|
id: `${dom.id}-owner`,
|
|
23547
23596
|
name: `${dom.name ?? dom.id} Owner`,
|
|
23548
|
-
description: dom.description ?
|
|
23597
|
+
description: dom.description ? summarize2(dom.description) : `Owner agent for the free-standing "${dom.id}" domain.`,
|
|
23549
23598
|
template: "domain-owner",
|
|
23550
23599
|
creationReason: "Inferred from a free-standing domain in .wai/topology.yaml",
|
|
23551
23600
|
domainRoot: dom.id,
|
|
@@ -23622,7 +23671,7 @@ var init_agent_resolver = __esm({
|
|
|
23622
23671
|
"use strict";
|
|
23623
23672
|
path23 = __toESM(require("path"));
|
|
23624
23673
|
fs18 = __toESM(require("fs"));
|
|
23625
|
-
|
|
23674
|
+
init_topology();
|
|
23626
23675
|
init_paths();
|
|
23627
23676
|
init_registry();
|
|
23628
23677
|
init_project_config();
|
|
@@ -24005,8 +24054,7 @@ function renderDomainsDoc() {
|
|
|
24005
24054
|
return lines.join("\n") + "\n";
|
|
24006
24055
|
}
|
|
24007
24056
|
function renderWaironGuide() {
|
|
24008
|
-
const
|
|
24009
|
-
const domains = resolveDomains2();
|
|
24057
|
+
const domains = resolveDomains();
|
|
24010
24058
|
let projectName = "this project";
|
|
24011
24059
|
try {
|
|
24012
24060
|
projectName = projectConfigRepository.load()?.name ?? projectName;
|
|
@@ -24090,7 +24138,7 @@ var init_context = __esm({
|
|
|
24090
24138
|
init_fs();
|
|
24091
24139
|
init_ai_guide();
|
|
24092
24140
|
init_stamp();
|
|
24093
|
-
|
|
24141
|
+
init_domain_projector();
|
|
24094
24142
|
init_project_config();
|
|
24095
24143
|
CONTEXT_PATHS = {
|
|
24096
24144
|
dir: () => contextDir(),
|
|
@@ -28175,6 +28223,15 @@ var init_approver = __esm({
|
|
|
28175
28223
|
});
|
|
28176
28224
|
|
|
28177
28225
|
// src/core/index.ts
|
|
28226
|
+
function resolveDomains2() {
|
|
28227
|
+
return resolveDomains();
|
|
28228
|
+
}
|
|
28229
|
+
function addDomain(domain) {
|
|
28230
|
+
registerDomain(domain);
|
|
28231
|
+
}
|
|
28232
|
+
function removeDomain(id) {
|
|
28233
|
+
unregisterDomain(id);
|
|
28234
|
+
}
|
|
28178
28235
|
function loadProjectConfig() {
|
|
28179
28236
|
return projectConfigRepository.load();
|
|
28180
28237
|
}
|
|
@@ -28185,8 +28242,9 @@ var init_core = __esm({
|
|
|
28185
28242
|
"src/core/index.ts"() {
|
|
28186
28243
|
"use strict";
|
|
28187
28244
|
init_project_config();
|
|
28245
|
+
init_domain_projector();
|
|
28246
|
+
init_domain_curator();
|
|
28188
28247
|
init_detection();
|
|
28189
|
-
init_domains();
|
|
28190
28248
|
init_templates();
|
|
28191
28249
|
init_validation();
|
|
28192
28250
|
init_extensions();
|
|
@@ -28215,6 +28273,8 @@ var init_core = __esm({
|
|
|
28215
28273
|
init_approver();
|
|
28216
28274
|
init_specs2();
|
|
28217
28275
|
init_project_config();
|
|
28276
|
+
init_execution_profile();
|
|
28277
|
+
init_budget_policy();
|
|
28218
28278
|
}
|
|
28219
28279
|
});
|
|
28220
28280
|
|
|
@@ -28916,7 +28976,7 @@ function renderAgentBriefMarkdown(brief) {
|
|
|
28916
28976
|
"",
|
|
28917
28977
|
"## Execution budget",
|
|
28918
28978
|
"",
|
|
28919
|
-
...
|
|
28979
|
+
...summarize(brief.budget, brief.profile),
|
|
28920
28980
|
"",
|
|
28921
28981
|
"Advisory \u2014 apply these when spawning. Map the capability tier onto your host tool's models; a tool that cannot express a field should ignore it rather than approximate it."
|
|
28922
28982
|
);
|
|
@@ -29047,7 +29107,7 @@ function createMcpServer(options = {}) {
|
|
|
29047
29107
|
},
|
|
29048
29108
|
() => {
|
|
29049
29109
|
try {
|
|
29050
|
-
return json(
|
|
29110
|
+
return json(resolveDomains2());
|
|
29051
29111
|
} catch (e) {
|
|
29052
29112
|
return errText(String(e));
|
|
29053
29113
|
}
|
|
@@ -30299,12 +30359,12 @@ var init_server = __esm({
|
|
|
30299
30359
|
init_paths();
|
|
30300
30360
|
init_validation();
|
|
30301
30361
|
init_provision();
|
|
30302
|
-
|
|
30362
|
+
init_core();
|
|
30303
30363
|
init_authoring();
|
|
30304
30364
|
init_variants();
|
|
30305
30365
|
init_agent_resolver();
|
|
30306
30366
|
init_core();
|
|
30307
|
-
|
|
30367
|
+
init_execution();
|
|
30308
30368
|
init_surfaces();
|
|
30309
30369
|
TYPE_REF_GRAMMAR = (what) => `${what}: a primitive/builtin or a defined type id (qualified across subsystems, e.g. "billing.Invoice" or "billing::Invoice"). Generics, arrays and UNIONS are all read, at any depth: "Invoice | null" (the commonest shape there is), "Invoice | undefined", "Invoice | Receipt", "Promise<Invoice | null>", "Map<string, Invoice | null>", "Invoice[] | null", "(Invoice | null)[]". Every identifier the string names must resolve \u2014 a union of two defined types means BOTH must exist. A union of string literals ("read" | "write") names no type and resolves to nothing.`;
|
|
30310
30370
|
staleServerOutput = {
|
|
@@ -31062,6 +31122,24 @@ function generateAll2(agents, config, options) {
|
|
|
31062
31122
|
function resolveExpectedOutputPaths2(agents, config) {
|
|
31063
31123
|
return resolveExpectedOutputPaths(agents, config);
|
|
31064
31124
|
}
|
|
31125
|
+
function resolveDomains3() {
|
|
31126
|
+
return resolveDomains2();
|
|
31127
|
+
}
|
|
31128
|
+
function addDomain2(domain) {
|
|
31129
|
+
addDomain(domain);
|
|
31130
|
+
}
|
|
31131
|
+
function removeDomain2(id) {
|
|
31132
|
+
removeDomain(id);
|
|
31133
|
+
}
|
|
31134
|
+
function detectDomainCandidates2(projectRoot2, trackedPaths, trackedIds) {
|
|
31135
|
+
return detectDomainCandidates(projectRoot2, trackedPaths, trackedIds);
|
|
31136
|
+
}
|
|
31137
|
+
function deriveExecutionProfile2(agent) {
|
|
31138
|
+
return deriveExecutionProfile(agent);
|
|
31139
|
+
}
|
|
31140
|
+
function resolveBudget2(profile, config, agentId) {
|
|
31141
|
+
return resolveBudget(profile, config, agentId);
|
|
31142
|
+
}
|
|
31065
31143
|
async function runSubsystemAdd(id, options = {}) {
|
|
31066
31144
|
logger.header("wairon subsystem add");
|
|
31067
31145
|
if (!projectConfigExists2()) {
|
|
@@ -32730,12 +32808,10 @@ async function filteredCheckbox(config) {
|
|
|
32730
32808
|
|
|
32731
32809
|
// src/commands/domains.ts
|
|
32732
32810
|
init_paths();
|
|
32733
|
-
init_detection();
|
|
32734
|
-
init_domains();
|
|
32735
32811
|
init_domain();
|
|
32736
32812
|
async function runDomainsList() {
|
|
32737
32813
|
assertProjectInitialized();
|
|
32738
|
-
const domains =
|
|
32814
|
+
const domains = resolveDomains3();
|
|
32739
32815
|
if (domains.length === 0) {
|
|
32740
32816
|
logger.info("No domains yet.");
|
|
32741
32817
|
logger.info("Define subsystems in the spec tree, or run `wairon domains scan --add` for free-standing domains.");
|
|
@@ -32760,10 +32836,10 @@ function printDomain(domain) {
|
|
|
32760
32836
|
async function runDomainsScan(options = {}) {
|
|
32761
32837
|
assertProjectInitialized();
|
|
32762
32838
|
const projectRoot2 = fromProjectRoot();
|
|
32763
|
-
const existing =
|
|
32839
|
+
const existing = resolveDomains3();
|
|
32764
32840
|
const trackedPaths = new Set(existing.map((d) => d.path).filter((p) => !!p));
|
|
32765
32841
|
const trackedIds = new Set(existing.map((d) => d.id));
|
|
32766
|
-
const candidates =
|
|
32842
|
+
const candidates = detectDomainCandidates2(projectRoot2, trackedPaths, trackedIds);
|
|
32767
32843
|
const newCandidates = candidates.filter((c) => !c.alreadyTracked && !trackedIds.has(c.suggestedId));
|
|
32768
32844
|
if (newCandidates.length === 0) {
|
|
32769
32845
|
logger.success("No new domain candidates found.");
|
|
@@ -32804,7 +32880,7 @@ async function runDomainsScan(options = {}) {
|
|
|
32804
32880
|
ownedPaths: [`${candidate.path}/**`]
|
|
32805
32881
|
});
|
|
32806
32882
|
try {
|
|
32807
|
-
|
|
32883
|
+
addDomain2(domain);
|
|
32808
32884
|
logger.success(`Added free-standing domain: ${domain.id} (${candidate.path})`);
|
|
32809
32885
|
added++;
|
|
32810
32886
|
} catch (err) {
|
|
@@ -32854,13 +32930,13 @@ async function runDomainsAdd(options = {}) {
|
|
|
32854
32930
|
path: domainPath.trim() || void 0,
|
|
32855
32931
|
ownedPaths
|
|
32856
32932
|
});
|
|
32857
|
-
|
|
32933
|
+
addDomain2(domain);
|
|
32858
32934
|
logger.success(`Free-standing domain "${domain.id}" added to .wai/topology.yaml.`);
|
|
32859
32935
|
logger.info("Run `wairon generate` to produce its owner agent.");
|
|
32860
32936
|
}
|
|
32861
32937
|
async function runDomainsRemove(id) {
|
|
32862
32938
|
assertProjectInitialized();
|
|
32863
|
-
const domain =
|
|
32939
|
+
const domain = resolveDomains3().find((d) => d.id === id);
|
|
32864
32940
|
if (!domain) {
|
|
32865
32941
|
logger.error(`Domain "${id}" not found.`);
|
|
32866
32942
|
process.exit(1);
|
|
@@ -32882,7 +32958,7 @@ async function runDomainsRemove(id) {
|
|
|
32882
32958
|
logger.info("Cancelled.");
|
|
32883
32959
|
return;
|
|
32884
32960
|
}
|
|
32885
|
-
|
|
32961
|
+
removeDomain2(id);
|
|
32886
32962
|
logger.success(`Domain "${id}" removed. Run \`wairon generate\` to refresh agent files.`);
|
|
32887
32963
|
}
|
|
32888
32964
|
|
|
@@ -48320,15 +48396,12 @@ function report(outcome) {
|
|
|
48320
48396
|
}
|
|
48321
48397
|
|
|
48322
48398
|
// src/cli/index.ts
|
|
48323
|
-
|
|
48399
|
+
init_execution();
|
|
48324
48400
|
|
|
48325
48401
|
// src/commands/execution.ts
|
|
48326
48402
|
var import_chalk21 = __toESM(require("chalk"));
|
|
48327
48403
|
init_logger();
|
|
48328
48404
|
init_errors();
|
|
48329
|
-
init_agent_resolver();
|
|
48330
|
-
init_execution_profile();
|
|
48331
|
-
init_budget_policy();
|
|
48332
48405
|
init_execution();
|
|
48333
48406
|
function assertInitialized() {
|
|
48334
48407
|
if (!projectConfigExists2()) {
|
|
@@ -48356,7 +48429,7 @@ async function showExecution() {
|
|
|
48356
48429
|
logger.info(`Enable with ${import_chalk21.default.bold("wairon execution set-tier default")}.`);
|
|
48357
48430
|
return;
|
|
48358
48431
|
}
|
|
48359
|
-
const agents =
|
|
48432
|
+
const agents = resolveAgentTopology2();
|
|
48360
48433
|
if (agents.length === 0) {
|
|
48361
48434
|
logger.blank();
|
|
48362
48435
|
logger.warn("No agents in the topology yet \u2014 nothing to budget.");
|
|
@@ -48364,8 +48437,8 @@ async function showExecution() {
|
|
|
48364
48437
|
}
|
|
48365
48438
|
logger.blank();
|
|
48366
48439
|
const rows = agents.map((agent) => {
|
|
48367
|
-
const profile =
|
|
48368
|
-
const budget =
|
|
48440
|
+
const profile = deriveExecutionProfile2(agent);
|
|
48441
|
+
const budget = resolveBudget2(profile, config.execution, agent.id);
|
|
48369
48442
|
return { agent, profile, budget };
|
|
48370
48443
|
});
|
|
48371
48444
|
const idWidth = Math.max(...rows.map((r) => r.agent.id.length));
|
|
@@ -48700,7 +48773,7 @@ async function runAgent(action, id) {
|
|
|
48700
48773
|
if (brief.budget && brief.profile) {
|
|
48701
48774
|
logger.blank();
|
|
48702
48775
|
logger.info("Execution budget (advisory \u2014 apply when spawning):");
|
|
48703
|
-
for (const line2 of
|
|
48776
|
+
for (const line2 of summarize(brief.budget, brief.profile)) {
|
|
48704
48777
|
logger.info(` ${line2.replace(/^- \*\*(.+?)\*\*: /, "$1: ")}`);
|
|
48705
48778
|
}
|
|
48706
48779
|
}
|