@wairon/cli 5.1.1-dev.81 → 5.1.1-dev.82
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 +1306 -565
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +292 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -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.82";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -155,7 +155,7 @@ var init_logger = __esm({
|
|
|
155
155
|
});
|
|
156
156
|
|
|
157
157
|
// src/utils/errors.ts
|
|
158
|
-
var WaironError, ProjectNotInitializedError, TemplateNotFoundError;
|
|
158
|
+
var WaironError, ProjectNotInitializedError, TemplateNotFoundError, DoctorOptionsError, ChainingMigrationRefusedError;
|
|
159
159
|
var init_errors = __esm({
|
|
160
160
|
"src/utils/errors.ts"() {
|
|
161
161
|
"use strict";
|
|
@@ -179,6 +179,20 @@ var init_errors = __esm({
|
|
|
179
179
|
this.name = "TemplateNotFoundError";
|
|
180
180
|
}
|
|
181
181
|
};
|
|
182
|
+
DoctorOptionsError = class extends WaironError {
|
|
183
|
+
constructor(detail) {
|
|
184
|
+
super(`wairon doctor: ${detail}`);
|
|
185
|
+
this.name = "DoctorOptionsError";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
ChainingMigrationRefusedError = class extends WaironError {
|
|
189
|
+
constructor(reasons) {
|
|
190
|
+
super(`The chaining migration was not applied; nothing was written:
|
|
191
|
+
${reasons.map((r) => ` - ${r}`).join("\n")}`);
|
|
192
|
+
this.reasons = reasons;
|
|
193
|
+
this.name = "ChainingMigrationRefusedError";
|
|
194
|
+
}
|
|
195
|
+
};
|
|
182
196
|
}
|
|
183
197
|
});
|
|
184
198
|
|
|
@@ -1122,7 +1136,12 @@ function projectConfigFsAdapterAt(rootDir) {
|
|
|
1122
1136
|
return readYamlFile(file());
|
|
1123
1137
|
},
|
|
1124
1138
|
writeDocument(document) {
|
|
1125
|
-
|
|
1139
|
+
const text2 = readFileOrNull(file());
|
|
1140
|
+
if (text2 === null) {
|
|
1141
|
+
writeYamlFile(file(), document);
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
writeFile(file(), editDocumentText(text2, document, root));
|
|
1126
1145
|
},
|
|
1127
1146
|
documentExists() {
|
|
1128
1147
|
return fs4.existsSync(file());
|
|
@@ -1216,21 +1235,21 @@ function childrenOf(tokens, index) {
|
|
|
1216
1235
|
}
|
|
1217
1236
|
return out;
|
|
1218
1237
|
}
|
|
1219
|
-
function locateScalar(tokens,
|
|
1238
|
+
function locateScalar(tokens, path77) {
|
|
1220
1239
|
let region = tokens;
|
|
1221
|
-
for (let k = 0; k <
|
|
1222
|
-
const segment =
|
|
1223
|
-
if (region.length === 0) return `nothing is nested at ${
|
|
1240
|
+
for (let k = 0; k < path77.length; k += 1) {
|
|
1241
|
+
const segment = path77[k];
|
|
1242
|
+
if (region.length === 0) return `nothing is nested at ${path77.slice(0, k).join(".")}`;
|
|
1224
1243
|
const base = Math.min(...region.map((t) => t.col));
|
|
1225
|
-
const last = k ===
|
|
1244
|
+
const last = k === path77.length - 1;
|
|
1226
1245
|
let at;
|
|
1227
1246
|
if (typeof segment === "string") {
|
|
1228
1247
|
at = region.findIndex((t) => t.kind === "key" && t.col === base && t.name === segment);
|
|
1229
|
-
if (at < 0) return `no block key "${segment}" at ${
|
|
1248
|
+
if (at < 0) return `no block key "${segment}" at ${path77.slice(0, k).join(".") || "the document root"}`;
|
|
1230
1249
|
if (last) return region[at].valueStart !== void 0 ? region[at] : `"${segment}" holds no inline scalar`;
|
|
1231
1250
|
} else {
|
|
1232
1251
|
const items = region.map((t, i) => ({ t, i })).filter(({ t }) => t.kind === "item" && t.col === base);
|
|
1233
|
-
if (segment >= items.length) return `no block sequence item ${segment} at ${
|
|
1252
|
+
if (segment >= items.length) return `no block sequence item ${segment} at ${path77.slice(0, k).join(".")}`;
|
|
1234
1253
|
at = items[segment].i;
|
|
1235
1254
|
if (last) {
|
|
1236
1255
|
const value = region[at + 1];
|
|
@@ -1278,10 +1297,10 @@ function writeScalar(value, style) {
|
|
|
1278
1297
|
if (style === "plain" && /^[A-Za-z0-9_][A-Za-z0-9_./-]*$/.test(value)) return value;
|
|
1279
1298
|
return `'${value.replace(/'/g, "''")}'`;
|
|
1280
1299
|
}
|
|
1281
|
-
function setAt(document,
|
|
1300
|
+
function setAt(document, path77, value) {
|
|
1282
1301
|
let node = document;
|
|
1283
|
-
for (const segment of
|
|
1284
|
-
node[
|
|
1302
|
+
for (const segment of path77.slice(0, -1)) node = node[segment];
|
|
1303
|
+
node[path77[path77.length - 1]] = value;
|
|
1285
1304
|
}
|
|
1286
1305
|
function rewriteScalarsInText(text2, edits, root) {
|
|
1287
1306
|
const refuse = (why) => {
|
|
@@ -1309,6 +1328,95 @@ function rewriteScalarsInText(text2, edits, root) {
|
|
|
1309
1328
|
}
|
|
1310
1329
|
return next;
|
|
1311
1330
|
}
|
|
1331
|
+
function sameValue(a, b) {
|
|
1332
|
+
if (a instanceof Date || b instanceof Date) {
|
|
1333
|
+
return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
1334
|
+
}
|
|
1335
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
1336
|
+
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => sameValue(item, b[i]));
|
|
1337
|
+
}
|
|
1338
|
+
if (isPlainObject(a) || isPlainObject(b)) {
|
|
1339
|
+
if (!isPlainObject(a) || !isPlainObject(b)) return false;
|
|
1340
|
+
const keysA = Object.keys(a).filter((k) => a[k] !== void 0);
|
|
1341
|
+
const keysB = Object.keys(b).filter((k) => b[k] !== void 0);
|
|
1342
|
+
return keysA.length === keysB.length && keysA.every((k) => hasOwn(b, k) && sameValue(a[k], b[k]));
|
|
1343
|
+
}
|
|
1344
|
+
return a === b;
|
|
1345
|
+
}
|
|
1346
|
+
function lineStartOf(text2, pos) {
|
|
1347
|
+
return text2.lastIndexOf("\n", pos - 1) + 1;
|
|
1348
|
+
}
|
|
1349
|
+
function lineEndFrom(text2, pos) {
|
|
1350
|
+
if (pos === 0 || text2[pos - 1] === "\n") return pos;
|
|
1351
|
+
const newline = text2.indexOf("\n", pos);
|
|
1352
|
+
return newline < 0 ? text2.length : newline + 1;
|
|
1353
|
+
}
|
|
1354
|
+
function indentBlock(text2, col) {
|
|
1355
|
+
const pad = " ".repeat(col);
|
|
1356
|
+
const body = text2.endsWith("\n") ? text2 : `${text2}
|
|
1357
|
+
`;
|
|
1358
|
+
return body.split("\n").map((line2, i, all) => line2 === "" || i === all.length - 1 ? line2 : pad + line2).join("\n");
|
|
1359
|
+
}
|
|
1360
|
+
function freshBlock(value, col) {
|
|
1361
|
+
return indentBlock(YAML.stringify(value, FRESH_TEXT_OPTIONS), col);
|
|
1362
|
+
}
|
|
1363
|
+
function schemaFieldOrder(at) {
|
|
1364
|
+
const objectsOf = (schema) => {
|
|
1365
|
+
const shape = shapeOf(schema);
|
|
1366
|
+
if (shape instanceof import_zod4.z.ZodObject) return [shape];
|
|
1367
|
+
if (shape instanceof import_zod4.z.ZodUnion) return shape._def.options.flatMap(objectsOf);
|
|
1368
|
+
return [];
|
|
1369
|
+
};
|
|
1370
|
+
let current2 = ProjectConfigSchema;
|
|
1371
|
+
for (const segment of at) {
|
|
1372
|
+
if (current2 === null) return null;
|
|
1373
|
+
const shape = shapeOf(current2);
|
|
1374
|
+
if (typeof segment === "number") {
|
|
1375
|
+
current2 = shape instanceof import_zod4.z.ZodArray ? shape.element : null;
|
|
1376
|
+
} else if (shape instanceof import_zod4.z.ZodRecord) {
|
|
1377
|
+
current2 = shape._def.valueType;
|
|
1378
|
+
} else {
|
|
1379
|
+
current2 = objectsOf(current2).map((o) => o.shape[segment]).find((s) => s !== void 0) ?? null;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
if (current2 === null) return null;
|
|
1383
|
+
const fields = objectsOf(current2).flatMap((o) => Object.keys(o.shape));
|
|
1384
|
+
return fields.length > 0 ? [...new Set(fields)] : null;
|
|
1385
|
+
}
|
|
1386
|
+
function inlineScalar(value, style) {
|
|
1387
|
+
if (value !== null && typeof value === "object") return null;
|
|
1388
|
+
const quoting = style === "QUOTE_SINGLE" || style === "QUOTE_DOUBLE" ? style : "PLAIN";
|
|
1389
|
+
const text2 = YAML.stringify(value, { ...FRESH_TEXT_OPTIONS, lineWidth: 0, defaultStringType: quoting }).replace(/\n$/, "");
|
|
1390
|
+
return text2.includes("\n") ? null : text2;
|
|
1391
|
+
}
|
|
1392
|
+
function applySplices(text2, splices) {
|
|
1393
|
+
const ordered = [...splices].sort((a, b) => b.start - a.start || b.end - a.end || b.rank - a.rank);
|
|
1394
|
+
let out = text2;
|
|
1395
|
+
for (const splice of ordered) out = out.slice(0, splice.start) + splice.text + out.slice(splice.end);
|
|
1396
|
+
return out;
|
|
1397
|
+
}
|
|
1398
|
+
function editDocumentText(text2, document, root) {
|
|
1399
|
+
const refuse = (why) => {
|
|
1400
|
+
throw new WaironError(`Cannot write .wai/project.yaml at ${root} as an edit of the file: ${why}. Nothing was written.`);
|
|
1401
|
+
};
|
|
1402
|
+
const crlf = text2.includes("\r\n");
|
|
1403
|
+
const source = crlf ? text2.replace(/\r\n/g, "\n") : text2;
|
|
1404
|
+
const doc = YAML.parseDocument(source, PARSE_OPTIONS);
|
|
1405
|
+
if (doc.errors.length > 0) refuse(`the file does not parse (${doc.errors[0].message})`);
|
|
1406
|
+
const reconciler = new DocumentReconciler(source, doc);
|
|
1407
|
+
reconciler.node(doc.contents, document, [], (value) => {
|
|
1408
|
+
reconciler.splices.push({ start: 0, end: source.length, text: YAML.stringify(value, FRESH_TEXT_OPTIONS), rank: 0 });
|
|
1409
|
+
});
|
|
1410
|
+
const edited = applySplices(source, reconciler.splices);
|
|
1411
|
+
let reread;
|
|
1412
|
+
try {
|
|
1413
|
+
reread = parseYaml(edited);
|
|
1414
|
+
} catch (e) {
|
|
1415
|
+
refuse(`the edited text does not parse (${e instanceof Error ? e.message : String(e)})`);
|
|
1416
|
+
}
|
|
1417
|
+
if (!sameValue(reread, document)) refuse("the edited text does not read back as the document to write");
|
|
1418
|
+
return crlf ? edited.replace(/\n/g, "\r\n") : edited;
|
|
1419
|
+
}
|
|
1312
1420
|
function parseConfig(document, root) {
|
|
1313
1421
|
try {
|
|
1314
1422
|
return ProjectConfigSchema.parse(document);
|
|
@@ -1467,9 +1575,9 @@ function registryOver(store, root) {
|
|
|
1467
1575
|
const next = rekeyAnchor(rename, { spec: entry.spec, at, covers });
|
|
1468
1576
|
const base = ["rules", "conformance", "carried", g, "findings", f];
|
|
1469
1577
|
const named = { code: String(entry.code), spec: entry.spec, at: at ?? "" };
|
|
1470
|
-
const change = (
|
|
1578
|
+
const change = (path77, field, from, to) => {
|
|
1471
1579
|
if (from === to) return;
|
|
1472
|
-
edits.push({ path: [...base, ...
|
|
1580
|
+
edits.push({ path: [...base, ...path77], from, to });
|
|
1473
1581
|
rekeys.push({ ...named, field, from, to });
|
|
1474
1582
|
};
|
|
1475
1583
|
change(["spec"], "spec", entry.spec, next.spec);
|
|
@@ -1479,6 +1587,38 @@ function registryOver(store, root) {
|
|
|
1479
1587
|
});
|
|
1480
1588
|
store.rewriteScalars(edits, dryRun);
|
|
1481
1589
|
return rekeys;
|
|
1590
|
+
},
|
|
1591
|
+
setId(id) {
|
|
1592
|
+
if (!PROJECT_ID_RE.test(id)) {
|
|
1593
|
+
throw new WaironError(`Refusing to declare the project id "${id}" at ${root}: it breaks the project-id grammar ([a-z0-9-_.], starting and ending alphanumeric).`);
|
|
1594
|
+
}
|
|
1595
|
+
const config = current2();
|
|
1596
|
+
if (config.id === id) return false;
|
|
1597
|
+
if (config.id !== void 0) {
|
|
1598
|
+
throw new WaironError(
|
|
1599
|
+
`Refusing to declare the project id "${id}" at ${root}: the project already declares "${config.id}". An id is immutable; moving it is the rename migration, never a set.`
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
save4({ ...config, id });
|
|
1603
|
+
return true;
|
|
1604
|
+
},
|
|
1605
|
+
declareExternal(alias, declaration2) {
|
|
1606
|
+
if (!EXTERNAL_ALIAS_RE.test(alias)) {
|
|
1607
|
+
throw new WaironError(`Refusing to declare the external "${alias}" at ${root}: an alias must fit [a-z0-9-_]+.`);
|
|
1608
|
+
}
|
|
1609
|
+
if (declaration2.project !== void 0 && !PROJECT_ID_RE.test(declaration2.project)) {
|
|
1610
|
+
throw new WaironError(`Refusing to declare the external "${alias}" at ${root}: the producer id "${declaration2.project}" breaks the project-id grammar.`);
|
|
1611
|
+
}
|
|
1612
|
+
const config = current2();
|
|
1613
|
+
const existing = config.externals?.[alias];
|
|
1614
|
+
if (existing !== void 0) {
|
|
1615
|
+
if (sameValue(existing, declaration2)) return false;
|
|
1616
|
+
throw new WaironError(
|
|
1617
|
+
`Refusing to declare the external "${alias}" at ${root} as ${JSON.stringify(declaration2)}: it is already declared as ${JSON.stringify(existing)}, and a declaration a person wrote is never overwritten.`
|
|
1618
|
+
);
|
|
1619
|
+
}
|
|
1620
|
+
save4({ ...config, externals: { ...config.externals, [alias]: declaration2 } });
|
|
1621
|
+
return true;
|
|
1482
1622
|
}
|
|
1483
1623
|
};
|
|
1484
1624
|
}
|
|
@@ -1566,18 +1706,25 @@ function projectConfigRepositoryOver(adapter, rootDir) {
|
|
|
1566
1706
|
},
|
|
1567
1707
|
rekeyCarried(rename, dryRun) {
|
|
1568
1708
|
return registry.rekeyCarried(rename, dryRun);
|
|
1709
|
+
},
|
|
1710
|
+
setId(id) {
|
|
1711
|
+
return registry.setId(id);
|
|
1712
|
+
},
|
|
1713
|
+
declareExternal(alias, declaration2) {
|
|
1714
|
+
return registry.declareExternal(alias, declaration2);
|
|
1569
1715
|
}
|
|
1570
1716
|
};
|
|
1571
1717
|
}
|
|
1572
1718
|
function projectConfigRepositoryAt(rootDir) {
|
|
1573
1719
|
return projectConfigRepositoryOver(projectConfigFsAdapterAt(rootDir), rootDir);
|
|
1574
1720
|
}
|
|
1575
|
-
var fs4, path6, import_zod4, KEY_RE, USE_GLOBAL_PACKS_DEFAULT, bound, projectConfigRepository;
|
|
1721
|
+
var fs4, path6, YAML, import_zod4, KEY_RE, FRESH_TEXT_OPTIONS, PARSE_OPTIONS, DocumentReconciler, USE_GLOBAL_PACKS_DEFAULT, bound, projectConfigRepository;
|
|
1576
1722
|
var init_project_config = __esm({
|
|
1577
1723
|
"src/config/project-config.ts"() {
|
|
1578
1724
|
"use strict";
|
|
1579
1725
|
fs4 = __toESM(require("fs"));
|
|
1580
1726
|
path6 = __toESM(require("path"));
|
|
1727
|
+
YAML = __toESM(require("yaml"));
|
|
1581
1728
|
import_zod4 = require("zod");
|
|
1582
1729
|
init_fs();
|
|
1583
1730
|
init_yaml();
|
|
@@ -1586,6 +1733,124 @@ var init_project_config = __esm({
|
|
|
1586
1733
|
init_identity_rename();
|
|
1587
1734
|
init_project();
|
|
1588
1735
|
KEY_RE = /^('(?:[^']|'')*'|"(?:[^"\\]|\\.)*"|[^\s'"#{}[\],&*!|>%@`][^:#]*?)\s*:(?=\s|$)/;
|
|
1736
|
+
FRESH_TEXT_OPTIONS = {
|
|
1737
|
+
indent: 2,
|
|
1738
|
+
indentSeq: true,
|
|
1739
|
+
lineWidth: 100,
|
|
1740
|
+
customTags: ["timestamp"]
|
|
1741
|
+
};
|
|
1742
|
+
PARSE_OPTIONS = { customTags: ["timestamp"] };
|
|
1743
|
+
DocumentReconciler = class {
|
|
1744
|
+
constructor(text2, doc) {
|
|
1745
|
+
this.text = text2;
|
|
1746
|
+
this.doc = doc;
|
|
1747
|
+
this.splices = [];
|
|
1748
|
+
}
|
|
1749
|
+
/** Reconcile one node to its target; `replace` rewrites the node wholesale where an edit cannot be precise. */
|
|
1750
|
+
node(node, target, at, replace) {
|
|
1751
|
+
if (YAML.isNode(node) && sameValue(node.toJS(this.doc, { maxAliasCount: -1 }), target)) return;
|
|
1752
|
+
if (YAML.isMap(node) && !node.flow && node.items.length > 0 && isPlainObject(target) && Object.keys(target).length > 0) {
|
|
1753
|
+
this.mapping(node, target, at, replace);
|
|
1754
|
+
} else if (YAML.isSeq(node) && !node.flow && node.items.length > 0 && Array.isArray(target) && target.length > 0) {
|
|
1755
|
+
this.sequence(node, target, at);
|
|
1756
|
+
} else if (YAML.isScalar(node) && !this.scalarInPlace(node, target)) {
|
|
1757
|
+
replace(target);
|
|
1758
|
+
} else if (!YAML.isScalar(node)) {
|
|
1759
|
+
replace(target);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
/** A changed one-line scalar, replaced in its own quoting; false when it is not one. */
|
|
1763
|
+
scalarInPlace(node, target) {
|
|
1764
|
+
const [start2, end] = node.range ?? [0, 0];
|
|
1765
|
+
const flowStyle = node.type === "PLAIN" || node.type === "QUOTE_SINGLE" || node.type === "QUOTE_DOUBLE";
|
|
1766
|
+
if (!flowStyle || start2 === end) return false;
|
|
1767
|
+
const written = inlineScalar(target, node.type);
|
|
1768
|
+
if (written === null) return false;
|
|
1769
|
+
this.splices.push({ start: start2, end, text: written, rank: 0 });
|
|
1770
|
+
return true;
|
|
1771
|
+
}
|
|
1772
|
+
/** Where a pair's text starts (its key's line) and ends (the line after its value). */
|
|
1773
|
+
pairSpan(pair) {
|
|
1774
|
+
const key = pair.key;
|
|
1775
|
+
const start2 = lineStartOf(this.text, key.range[0]);
|
|
1776
|
+
const value = pair.value;
|
|
1777
|
+
const valueEnd = value && value.range ? value.range[1] : key.range[1];
|
|
1778
|
+
return { start: start2, end: lineEndFrom(this.text, valueEnd), col: key.range[0] - start2 };
|
|
1779
|
+
}
|
|
1780
|
+
/** Where a sequence item's text starts (its dash's line) and ends, and the dash's column. */
|
|
1781
|
+
itemSpan(item) {
|
|
1782
|
+
let dash = item.range[0] - 1;
|
|
1783
|
+
while (dash >= 0 && /\s/.test(this.text[dash])) dash -= 1;
|
|
1784
|
+
const start2 = lineStartOf(this.text, dash);
|
|
1785
|
+
return { start: start2, end: lineEndFrom(this.text, item.range[1]), col: dash - start2 };
|
|
1786
|
+
}
|
|
1787
|
+
/** The first line of the comment block directly above the line starting at `lineStart`. */
|
|
1788
|
+
commentBlockStart(lineStart) {
|
|
1789
|
+
let start2 = lineStart;
|
|
1790
|
+
while (start2 > 0) {
|
|
1791
|
+
const above = lineStartOf(this.text, start2 - 1);
|
|
1792
|
+
if (!this.text.slice(above, start2).trim().startsWith("#")) break;
|
|
1793
|
+
start2 = above;
|
|
1794
|
+
}
|
|
1795
|
+
return start2;
|
|
1796
|
+
}
|
|
1797
|
+
mapping(map, target, at, replace) {
|
|
1798
|
+
const keyOf = (pair) => String(YAML.isScalar(pair.key) ? pair.key.value : pair.key);
|
|
1799
|
+
const kept = map.items.filter((pair) => target[keyOf(pair)] !== void 0);
|
|
1800
|
+
if (kept.length === 0) {
|
|
1801
|
+
replace(target);
|
|
1802
|
+
return;
|
|
1803
|
+
}
|
|
1804
|
+
for (const pair of map.items) {
|
|
1805
|
+
const key = keyOf(pair);
|
|
1806
|
+
const span = this.pairSpan(pair);
|
|
1807
|
+
if (target[key] === void 0) {
|
|
1808
|
+
this.splices.push({ start: span.start, end: span.end, text: "", rank: 0 });
|
|
1809
|
+
continue;
|
|
1810
|
+
}
|
|
1811
|
+
this.node(pair.value, target[key], [...at, key], (value) => {
|
|
1812
|
+
this.splices.push({ start: span.start, end: span.end, text: freshBlock({ [key]: value }, span.col), rank: 0 });
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
this.insertNewKeys(map, kept, target, at, keyOf);
|
|
1816
|
+
}
|
|
1817
|
+
/**
|
|
1818
|
+
* Insert the keys the document adds at their place in the schema's field
|
|
1819
|
+
* order: after the nearest preceding schema field the mapping keeps, else
|
|
1820
|
+
* before the nearest following one (above its comments), else after the
|
|
1821
|
+
* mapping's last key.
|
|
1822
|
+
*/
|
|
1823
|
+
insertNewKeys(map, kept, target, at, keyOf) {
|
|
1824
|
+
const present = new Map(kept.map((pair) => [keyOf(pair), pair]));
|
|
1825
|
+
const order = schemaFieldOrder(at) ?? [];
|
|
1826
|
+
const col = this.pairSpan(kept[0]).col;
|
|
1827
|
+
const added = Object.keys(target).filter((key) => target[key] !== void 0 && !map.items.some((pair) => keyOf(pair) === key));
|
|
1828
|
+
added.forEach((key, n) => {
|
|
1829
|
+
const index = order.indexOf(key);
|
|
1830
|
+
const before = index < 0 ? void 0 : order.slice(0, index).reverse().find((k) => present.has(k));
|
|
1831
|
+
const after = index < 0 ? void 0 : order.slice(index + 1).find((k) => present.has(k));
|
|
1832
|
+
const offset = before !== void 0 ? this.pairSpan(present.get(before)).end : after !== void 0 ? this.commentBlockStart(this.pairSpan(present.get(after)).start) : this.pairSpan(kept[kept.length - 1]).end;
|
|
1833
|
+
const rank = -at.length * 1e5 + (index < 0 ? order.length + n : index);
|
|
1834
|
+
this.splices.push({ start: offset, end: offset, text: freshBlock({ [key]: target[key] }, col), rank });
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
sequence(seq, target, at) {
|
|
1838
|
+
seq.items.forEach((item, i) => {
|
|
1839
|
+
const span = this.itemSpan(item);
|
|
1840
|
+
if (i >= target.length) {
|
|
1841
|
+
this.splices.push({ start: span.start, end: span.end, text: "", rank: 0 });
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
this.node(item, target[i], [...at, i], (value) => {
|
|
1845
|
+
this.splices.push({ start: span.start, end: span.end, text: freshBlock([value], span.col), rank: 0 });
|
|
1846
|
+
});
|
|
1847
|
+
});
|
|
1848
|
+
if (target.length > seq.items.length) {
|
|
1849
|
+
const last = this.itemSpan(seq.items[seq.items.length - 1]);
|
|
1850
|
+
this.splices.push({ start: last.end, end: last.end, text: freshBlock(target.slice(seq.items.length), last.col), rank: -(at.length + 1) * 1e5 });
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
};
|
|
1589
1854
|
USE_GLOBAL_PACKS_DEFAULT = ProjectConfigSchema.shape.extensions.unwrap().parse({}).useGlobalPacks;
|
|
1590
1855
|
bound = () => projectConfigRepositoryAt(getProjectRoot());
|
|
1591
1856
|
projectConfigRepository = {
|
|
@@ -1633,6 +1898,12 @@ var init_project_config = __esm({
|
|
|
1633
1898
|
},
|
|
1634
1899
|
rekeyCarried(rename, dryRun) {
|
|
1635
1900
|
return bound().rekeyCarried(rename, dryRun);
|
|
1901
|
+
},
|
|
1902
|
+
setId(id) {
|
|
1903
|
+
return bound().setId(id);
|
|
1904
|
+
},
|
|
1905
|
+
declareExternal(alias, declaration2) {
|
|
1906
|
+
return bound().declareExternal(alias, declaration2);
|
|
1636
1907
|
}
|
|
1637
1908
|
};
|
|
1638
1909
|
}
|
|
@@ -3269,10 +3540,10 @@ function stepGraph(method2) {
|
|
|
3269
3540
|
const s = byNum.get(n);
|
|
3270
3541
|
if (s.type !== "parallel" || s.endStep === void 0 || !s.branches?.length) continue;
|
|
3271
3542
|
const entries = s.branches.map((b) => b.step).sort((a, b) => a - b);
|
|
3272
|
-
const
|
|
3543
|
+
const join56 = fallNext(s.endStep);
|
|
3273
3544
|
for (let i = 0; i < entries.length; i++) {
|
|
3274
3545
|
const armEnd = i + 1 < entries.length ? prevOf(entries[i + 1]) : s.endStep;
|
|
3275
|
-
if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd,
|
|
3546
|
+
if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join56);
|
|
3276
3547
|
}
|
|
3277
3548
|
}
|
|
3278
3549
|
const successorsOf = (n) => {
|
|
@@ -3363,17 +3634,17 @@ function stepConfigVerdict(method2) {
|
|
|
3363
3634
|
};
|
|
3364
3635
|
const labelled = /* @__PURE__ */ new Map();
|
|
3365
3636
|
for (const step of steps) {
|
|
3366
|
-
const
|
|
3367
|
-
if (!
|
|
3368
|
-
const first = labelled.get(
|
|
3637
|
+
const label3 = step.label;
|
|
3638
|
+
if (!label3) continue;
|
|
3639
|
+
const first = labelled.get(label3);
|
|
3369
3640
|
if (first !== void 0) {
|
|
3370
3641
|
problems.push({
|
|
3371
3642
|
stepNumber: step.stepNumber,
|
|
3372
3643
|
code: "DUPLICATE_STEP_LABEL",
|
|
3373
|
-
detail: `steps ${first} and ${step.stepNumber} share the label "${
|
|
3644
|
+
detail: `steps ${first} and ${step.stepNumber} share the label "${label3}". A label anchors one step for later deltas to address; two steps holding it makes every symbolic reference ambiguous and blocks all further edits to this implementation. Rename one.`
|
|
3374
3645
|
});
|
|
3375
3646
|
} else {
|
|
3376
|
-
labelled.set(
|
|
3647
|
+
labelled.set(label3, step.stepNumber);
|
|
3377
3648
|
}
|
|
3378
3649
|
}
|
|
3379
3650
|
const byNum = /* @__PURE__ */ new Map();
|
|
@@ -4051,9 +4322,9 @@ function buildDrawioXml(model, L) {
|
|
|
4051
4322
|
const parentId = nestInPattern ? "comp_" + owner.id : "sub_" + comp.subsystem;
|
|
4052
4323
|
const parentBox = nestInPattern ? L.boxes[owner.id] : L.subs[comp.subsystem];
|
|
4053
4324
|
const colors = COLORS[stereo(comp.componentType)];
|
|
4054
|
-
const
|
|
4325
|
+
const label3 = comp.name + "\n\xAB" + comp.componentType + (comp.portalType ? "/" + comp.portalType : "") + "\xBB";
|
|
4055
4326
|
const style = isPattern2 ? "rounded=1;fillColor=" + colors.fill + ";strokeColor=" + colors.stroke + ";dashed=1;verticalAlign=top;fontStyle=1;container=1;collapsible=1;whiteSpace=wrap;" : "rounded=1;fillColor=" + colors.fill + ";strokeColor=" + colors.stroke + ";whiteSpace=wrap;fontSize=11;" + (comp.public ? "strokeWidth=3;" : "");
|
|
4056
|
-
vertex("comp_" + comp.id, parentId,
|
|
4327
|
+
vertex("comp_" + comp.id, parentId, label3, style, box, parentBox);
|
|
4057
4328
|
});
|
|
4058
4329
|
let edgeN = 0;
|
|
4059
4330
|
model.edges.forEach(function(edge) {
|
|
@@ -4137,19 +4408,19 @@ function buildExcalidrawScene(model, L) {
|
|
|
4137
4408
|
}
|
|
4138
4409
|
function boundLabel(rect, text2, fontSize, verticalAlign) {
|
|
4139
4410
|
const id = rect.id + "-label";
|
|
4140
|
-
const
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4411
|
+
const label3 = base(id, "text", { x: rect.x + 8, y: rect.y + 6, w: rect.width - 16, h: 20 });
|
|
4412
|
+
label3.roundness = null;
|
|
4413
|
+
label3.text = text2;
|
|
4414
|
+
label3.originalText = text2;
|
|
4415
|
+
label3.fontSize = fontSize;
|
|
4416
|
+
label3.fontFamily = 1;
|
|
4417
|
+
label3.textAlign = "center";
|
|
4418
|
+
label3.verticalAlign = verticalAlign;
|
|
4419
|
+
label3.containerId = rect.id;
|
|
4420
|
+
label3.autoResize = true;
|
|
4421
|
+
label3.lineHeight = 1.25;
|
|
4151
4422
|
rect.boundElements.push({ id, type: "text" });
|
|
4152
|
-
return
|
|
4423
|
+
return label3;
|
|
4153
4424
|
}
|
|
4154
4425
|
const elements = [];
|
|
4155
4426
|
const rectById = {};
|
|
@@ -4174,8 +4445,8 @@ function buildExcalidrawScene(model, L) {
|
|
|
4174
4445
|
rect.strokeStyle = isPattern2 || stereo(comp.componentType) === "pattern" ? "dashed" : "solid";
|
|
4175
4446
|
elements.push(rect);
|
|
4176
4447
|
rectById[comp.id] = rect;
|
|
4177
|
-
const
|
|
4178
|
-
elements.push(boundLabel(rect,
|
|
4448
|
+
const label3 = comp.name + "\n\xAB" + comp.componentType + (comp.portalType ? "/" + comp.portalType : "") + "\xBB";
|
|
4449
|
+
elements.push(boundLabel(rect, label3, 11, isPattern2 ? "top" : "middle"));
|
|
4179
4450
|
});
|
|
4180
4451
|
let edgeN = 0;
|
|
4181
4452
|
model.edges.forEach(function(edge) {
|
|
@@ -9586,8 +9857,8 @@ function pinExternals(aliases) {
|
|
|
9586
9857
|
pins.push({ alias: binding.external.alias, outcome: "unresolved", project: binding.external.project, usedNames: 0, unexported: [], detail: binding.external.problem });
|
|
9587
9858
|
continue;
|
|
9588
9859
|
}
|
|
9589
|
-
const { pin, changed } = pinBinding(binding, lock);
|
|
9590
|
-
pins.push(
|
|
9860
|
+
const { pin: pin2, changed } = pinBinding(binding, lock);
|
|
9861
|
+
pins.push(pin2);
|
|
9591
9862
|
lockChanged ||= changed;
|
|
9592
9863
|
}
|
|
9593
9864
|
if (!named) {
|
|
@@ -10500,21 +10771,21 @@ function buildCodeIndex(model) {
|
|
|
10500
10771
|
const declarations = /* @__PURE__ */ new Map();
|
|
10501
10772
|
const anchors = /* @__PURE__ */ new Map();
|
|
10502
10773
|
const findingAnchors = /* @__PURE__ */ new Map();
|
|
10503
|
-
const namesAt = (cache2,
|
|
10504
|
-
const cached = cache2.get(
|
|
10774
|
+
const namesAt = (cache2, path77, make) => {
|
|
10775
|
+
const cached = cache2.get(path77);
|
|
10505
10776
|
if (cached) return cached;
|
|
10506
|
-
const f = facts.get(
|
|
10777
|
+
const f = facts.get(path77);
|
|
10507
10778
|
if (!f) return NO_NAMES;
|
|
10508
10779
|
const built = make(f);
|
|
10509
|
-
cache2.set(
|
|
10780
|
+
cache2.set(path77, built);
|
|
10510
10781
|
return built;
|
|
10511
10782
|
};
|
|
10512
10783
|
const republished = /* @__PURE__ */ new Map();
|
|
10513
|
-
const republishedFrom = (
|
|
10514
|
-
const cached = republished.get(
|
|
10784
|
+
const republishedFrom = (path77) => {
|
|
10785
|
+
const cached = republished.get(path77);
|
|
10515
10786
|
if (cached) return cached;
|
|
10516
|
-
const out = /* @__PURE__ */ new Set([
|
|
10517
|
-
const queue = [
|
|
10787
|
+
const out = /* @__PURE__ */ new Set([path77]);
|
|
10788
|
+
const queue = [path77];
|
|
10518
10789
|
while (queue.length) {
|
|
10519
10790
|
const from = queue.pop();
|
|
10520
10791
|
const f = facts.get(from);
|
|
@@ -10527,7 +10798,7 @@ function buildCodeIndex(model) {
|
|
|
10527
10798
|
}
|
|
10528
10799
|
}
|
|
10529
10800
|
}
|
|
10530
|
-
republished.set(
|
|
10801
|
+
republished.set(path77, out);
|
|
10531
10802
|
return out;
|
|
10532
10803
|
};
|
|
10533
10804
|
const NO_ORIGIN = /* @__PURE__ */ new Set();
|
|
@@ -10536,9 +10807,9 @@ function buildCodeIndex(model) {
|
|
|
10536
10807
|
return to ? republishedFrom(to) : NO_ORIGIN;
|
|
10537
10808
|
};
|
|
10538
10809
|
const scopeOf2 = (site, from) => {
|
|
10539
|
-
const
|
|
10540
|
-
const f = facts.get(
|
|
10541
|
-
return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path:
|
|
10810
|
+
const path77 = pathKey(site.from ?? from);
|
|
10811
|
+
const f = facts.get(path77);
|
|
10812
|
+
return f?.status === "analyzed" && f.analysisGrade === "exact" ? { path: path77, facts: f } : void 0;
|
|
10542
10813
|
};
|
|
10543
10814
|
const originOf2 = (site, from) => {
|
|
10544
10815
|
const resolved = scopeOf2(site, from);
|
|
@@ -10577,7 +10848,7 @@ function buildCodeIndex(model) {
|
|
|
10577
10848
|
if (site.via) for (const typeName of localTypesOf(f, site.via)) widenThroughType(typeName);
|
|
10578
10849
|
return out;
|
|
10579
10850
|
};
|
|
10580
|
-
const declarationsAt = (
|
|
10851
|
+
const declarationsAt = (path77) => namesAt(declarations, pathKey(path77), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames]));
|
|
10581
10852
|
const forwardsOf = (start2, name) => {
|
|
10582
10853
|
const out = [];
|
|
10583
10854
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10603,10 +10874,10 @@ function buildCodeIndex(model) {
|
|
|
10603
10874
|
return {
|
|
10604
10875
|
paths,
|
|
10605
10876
|
exactPaths,
|
|
10606
|
-
factsAt: (
|
|
10877
|
+
factsAt: (path77) => facts.get(pathKey(path77)),
|
|
10607
10878
|
declarationsAt,
|
|
10608
|
-
anchorsAt: (
|
|
10609
|
-
findingAnchorsAt: (
|
|
10879
|
+
anchorsAt: (path77) => namesAt(anchors, pathKey(path77), (f) => /* @__PURE__ */ new Set([...f.declaredNames, ...f.exportedNames, ...f.anchoredNames])),
|
|
10880
|
+
findingAnchorsAt: (path77) => namesAt(findingAnchors, pathKey(path77), (f) => new Set(f.anchoredNames)),
|
|
10610
10881
|
originOf: originOf2,
|
|
10611
10882
|
possibleOriginsOf,
|
|
10612
10883
|
forwardsOf
|
|
@@ -10645,10 +10916,10 @@ function buildRealizationIndex(ctx) {
|
|
|
10645
10916
|
return {
|
|
10646
10917
|
paths,
|
|
10647
10918
|
implementationsOf: (compId) => implsByComponent.get(compId) ?? NONE_IMPL,
|
|
10648
|
-
implementationsAt: (
|
|
10919
|
+
implementationsAt: (path77) => implsByPath.get(pathKey(path77)) ?? NONE_IMPL,
|
|
10649
10920
|
filesOf: (compId) => filesByComponent.get(compId) ?? NONE_PATH,
|
|
10650
10921
|
filesIn: (subsystemId) => filesBySubsystem.get(subsystemId) ?? NONE_PATH,
|
|
10651
|
-
componentsAt: (
|
|
10922
|
+
componentsAt: (path77) => componentsByPath.get(pathKey(path77)) ?? NONE_COMP
|
|
10652
10923
|
};
|
|
10653
10924
|
}
|
|
10654
10925
|
function buildImportGraph(index, universe) {
|
|
@@ -10660,22 +10931,22 @@ function buildImportGraph(index, universe) {
|
|
|
10660
10931
|
if (to && to !== from) into.add(to);
|
|
10661
10932
|
}
|
|
10662
10933
|
};
|
|
10663
|
-
const importsOf = (
|
|
10664
|
-
const cached = imports.get(
|
|
10934
|
+
const importsOf = (path77) => {
|
|
10935
|
+
const cached = imports.get(path77);
|
|
10665
10936
|
if (cached) return cached;
|
|
10666
|
-
const facts = index.factsAt(
|
|
10937
|
+
const facts = index.factsAt(path77);
|
|
10667
10938
|
const out = /* @__PURE__ */ new Set();
|
|
10668
|
-
if (facts?.status === "analyzed") resolveAll(
|
|
10669
|
-
imports.set(
|
|
10939
|
+
if (facts?.status === "analyzed") resolveAll(path77, facts.imports, out);
|
|
10940
|
+
imports.set(path77, out);
|
|
10670
10941
|
return out;
|
|
10671
10942
|
};
|
|
10672
|
-
const tracesOf = (
|
|
10673
|
-
const cached = traces.get(
|
|
10943
|
+
const tracesOf = (path77) => {
|
|
10944
|
+
const cached = traces.get(path77);
|
|
10674
10945
|
if (cached) return cached;
|
|
10675
|
-
const facts = index.factsAt(
|
|
10676
|
-
const out = new Set(importsOf(
|
|
10677
|
-
if (facts?.status === "analyzed") resolveAll(
|
|
10678
|
-
traces.set(
|
|
10946
|
+
const facts = index.factsAt(path77);
|
|
10947
|
+
const out = new Set(importsOf(path77));
|
|
10948
|
+
if (facts?.status === "analyzed") resolveAll(path77, facts.reexports, out);
|
|
10949
|
+
traces.set(path77, out);
|
|
10679
10950
|
return out;
|
|
10680
10951
|
};
|
|
10681
10952
|
return {
|
|
@@ -12455,11 +12726,11 @@ var init_unconditional_call_cycles = __esm({
|
|
|
12455
12726
|
const memberEdges = keys.flatMap((k) => (adjacency.get(k) ?? []).filter((e) => inScc.has(e.toKey)));
|
|
12456
12727
|
if (memberEdges.length === 0) continue;
|
|
12457
12728
|
const anchor = [...memberEdges].sort((a, b) => byCodeUnit(a.fromKey, b.fromKey) || byCodeUnit(a.impl.id, b.impl.id) || a.stepNumber - b.stepNumber)[0];
|
|
12458
|
-
const
|
|
12729
|
+
const path77 = [...keys].sort(byCodeUnit).join(" \u2192 ");
|
|
12459
12730
|
ctx.addIssue(
|
|
12460
12731
|
"warning",
|
|
12461
12732
|
"UNCONDITIONAL_CALL_CYCLE",
|
|
12462
|
-
`Call cycle with no guard: ${
|
|
12733
|
+
`Call cycle with no guard: ${path77} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
|
|
12463
12734
|
anchor.impl.id,
|
|
12464
12735
|
memberEdges.some((e) => ctx.isImplementationDraft(e.impl))
|
|
12465
12736
|
);
|
|
@@ -14382,8 +14653,8 @@ var init_lifecycle_entrypoints = __esm({
|
|
|
14382
14653
|
});
|
|
14383
14654
|
|
|
14384
14655
|
// src/core/rules/wiring/portal-mounts.ts
|
|
14385
|
-
function liesUnder(
|
|
14386
|
-
return
|
|
14656
|
+
function liesUnder(path77, prefix) {
|
|
14657
|
+
return path77 === prefix || path77.startsWith(prefix + "/");
|
|
14387
14658
|
}
|
|
14388
14659
|
var portalMountsRule;
|
|
14389
14660
|
var init_portal_mounts = __esm({
|
|
@@ -15378,12 +15649,12 @@ var init_method_realization = __esm({
|
|
|
15378
15649
|
);
|
|
15379
15650
|
continue;
|
|
15380
15651
|
}
|
|
15381
|
-
const
|
|
15652
|
+
const label3 = methodImpl?.symbol ? `"${method2.name}" (symbol "${symbol}")` : `"${method2.name}"`;
|
|
15382
15653
|
const weakHint = tier === "declared" && inAnchored ? " Only a weak string/word anchor exists \u2014 declare the symbol, map it via a per-method `symbol`, or dial this method to `anchored`." : "";
|
|
15383
15654
|
ctx.addIssue(
|
|
15384
15655
|
"warning",
|
|
15385
15656
|
"UNREALIZED_METHOD",
|
|
15386
|
-
`Method ${
|
|
15657
|
+
`Method ${label3} of contract "${impl.contract}" is not realized in "${file}" at the "${tier}" tier (analysis grade: ${facts.analysisGrade}).${weakHint}`,
|
|
15387
15658
|
impl.id,
|
|
15388
15659
|
draft
|
|
15389
15660
|
);
|
|
@@ -15693,11 +15964,11 @@ var init_hidden_state = __esm({
|
|
|
15693
15964
|
byPath.set(key, list2);
|
|
15694
15965
|
}
|
|
15695
15966
|
}
|
|
15696
|
-
for (const
|
|
15697
|
-
const facts = code.factsAt(
|
|
15967
|
+
for (const path77 of code.exactPaths) {
|
|
15968
|
+
const facts = code.factsAt(path77);
|
|
15698
15969
|
const bindings = facts.topLevelMutableBindings ?? [];
|
|
15699
15970
|
if (bindings.length === 0) continue;
|
|
15700
|
-
const mapped = byPath.get(
|
|
15971
|
+
const mapped = byPath.get(path77) ?? [];
|
|
15701
15972
|
if (mapped.length === 0) continue;
|
|
15702
15973
|
if (!mapped.every((m) => isStatelessLogic(m.component))) continue;
|
|
15703
15974
|
const anchor = [...mapped].sort((a, b) => a.impl.id.localeCompare(b.impl.id))[0];
|
|
@@ -15770,7 +16041,7 @@ var init_dependency_conformance = __esm({
|
|
|
15770
16041
|
}
|
|
15771
16042
|
return false;
|
|
15772
16043
|
};
|
|
15773
|
-
const draftAt = (
|
|
16044
|
+
const draftAt = (path77) => realization.implementationsAt(path77).some((impl) => ctx.isImplementationDraft(impl));
|
|
15774
16045
|
for (const fromPath of mappedPaths) {
|
|
15775
16046
|
const fromComponents = realization.componentsAt(fromPath);
|
|
15776
16047
|
for (const toPath of graph2.importsOf(fromPath)) {
|
|
@@ -15861,7 +16132,7 @@ var init_portal_imports = __esm({
|
|
|
15861
16132
|
}
|
|
15862
16133
|
return files;
|
|
15863
16134
|
};
|
|
15864
|
-
const draftAt = (
|
|
16135
|
+
const draftAt = (path77) => realization.implementationsAt(path77).some((impl) => ctx.isImplementationDraft(impl));
|
|
15865
16136
|
for (const fromPath of mappedPaths) {
|
|
15866
16137
|
const fromSubsystems = new Set(realization.componentsAt(fromPath).map((c) => c.subsystem));
|
|
15867
16138
|
for (const toPath of graph2.importsOf(fromPath)) {
|
|
@@ -16012,8 +16283,8 @@ var init_integration_sim_wiring = __esm({
|
|
|
16012
16283
|
const depFiles = depComp.subsystem !== comp.subsystem ? modulesIn(depComp.subsystem) : modulesOf(dep);
|
|
16013
16284
|
if (depFiles.length === 0) continue;
|
|
16014
16285
|
if (!depFiles.some((f) => reach2.has(f))) {
|
|
16015
|
-
const
|
|
16016
|
-
missing.push(
|
|
16286
|
+
const label3 = depComp.subsystem !== comp.subsystem ? `"${dep}" (any module of subsystem "${depComp.subsystem}")` : `"${dep}" (${depFiles.join(" | ")})`;
|
|
16287
|
+
missing.push(label3);
|
|
16017
16288
|
}
|
|
16018
16289
|
}
|
|
16019
16290
|
if (missing.length === 0) continue;
|
|
@@ -16131,27 +16402,27 @@ var init_type_realization = __esm({
|
|
|
16131
16402
|
for (const type of ctx.types) {
|
|
16132
16403
|
if (!type.sourcePath) continue;
|
|
16133
16404
|
if (type.subsystem && ctx.isInChainedSubproject(type.subsystem)) continue;
|
|
16134
|
-
const
|
|
16405
|
+
const blocked2 = /* @__PURE__ */ new Set();
|
|
16135
16406
|
for (const file of typeSourceFiles(type)) {
|
|
16136
16407
|
const key = pathKey(file);
|
|
16137
16408
|
const facts = code.factsAt(key);
|
|
16138
16409
|
if (!facts || facts.status === "analyzed") continue;
|
|
16139
|
-
|
|
16410
|
+
blocked2.add(key);
|
|
16140
16411
|
const problem = FILE_PROBLEMS[facts.status];
|
|
16141
16412
|
if (!problem) continue;
|
|
16142
16413
|
ctx.addIssue(problem.severity, problem.code, `${ownerOf2(type, file)} sourcePath "${file}" ${problem.detail}`, type.id);
|
|
16143
16414
|
}
|
|
16144
16415
|
const typeKey = pathKey(type.sourcePath);
|
|
16145
16416
|
const typeFacts = code.factsAt(typeKey);
|
|
16146
|
-
if (typeFacts && !
|
|
16417
|
+
if (typeFacts && !blocked2.has(typeKey)) {
|
|
16147
16418
|
const symbol = type.symbol ?? type.name;
|
|
16148
16419
|
const published = typeFacts.analysisGrade === "exact" ? new Set(typeFacts.reexportOnly ? [] : typeFacts.exportedNames) : code.declarationsAt(typeKey);
|
|
16149
16420
|
if (!published.has(symbol)) {
|
|
16150
|
-
const
|
|
16421
|
+
const label3 = type.symbol ? `"${type.name}" (symbol "${symbol}")` : `"${type.name}"`;
|
|
16151
16422
|
ctx.addIssue(
|
|
16152
16423
|
"warning",
|
|
16153
16424
|
"UNREALIZED_TYPE",
|
|
16154
|
-
`Type ${
|
|
16425
|
+
`Type ${label3} is not published by "${type.sourcePath}" (analysis grade: ${typeFacts.analysisGrade})${typeFacts.reexportOnly ? ", which is a pure re-export barrel and declares nothing of its own" : ""} \u2014 name the file the declaration lives in, or bind the code-level name with \`symbol\`.`,
|
|
16155
16426
|
type.id
|
|
16156
16427
|
);
|
|
16157
16428
|
}
|
|
@@ -16159,16 +16430,16 @@ var init_type_realization = __esm({
|
|
|
16159
16430
|
for (const method2 of type.methods ?? []) {
|
|
16160
16431
|
const file = method2.sourcePath ?? type.sourcePath;
|
|
16161
16432
|
const key = pathKey(file);
|
|
16162
|
-
if (
|
|
16433
|
+
if (blocked2.has(key)) continue;
|
|
16163
16434
|
const facts = code.factsAt(key);
|
|
16164
16435
|
if (!facts || facts.status !== "analyzed") continue;
|
|
16165
16436
|
const symbol = method2.symbol ?? method2.name;
|
|
16166
16437
|
if (code.declarationsAt(key).has(symbol)) continue;
|
|
16167
|
-
const
|
|
16438
|
+
const label3 = method2.symbol ? `"${method2.name}" (symbol "${symbol}")` : `"${method2.name}"`;
|
|
16168
16439
|
ctx.addIssue(
|
|
16169
16440
|
"warning",
|
|
16170
16441
|
"UNREALIZED_TYPE_METHOD",
|
|
16171
|
-
`Method ${
|
|
16442
|
+
`Method ${label3} of type "${type.id}" is not declared in "${file}" (analysis grade: ${facts.analysisGrade}) \u2014 a pure type method is often a free function named after its type; bind that name with \`symbol\`, or name the file it lives in with the method's own \`sourcePath\`.`,
|
|
16172
16443
|
type.id
|
|
16173
16444
|
);
|
|
16174
16445
|
}
|
|
@@ -16447,8 +16718,8 @@ var init_param_conformance = __esm({
|
|
|
16447
16718
|
});
|
|
16448
16719
|
|
|
16449
16720
|
// src/core/rules/conformance/route-coverage.ts
|
|
16450
|
-
function liesUnder2(
|
|
16451
|
-
return
|
|
16721
|
+
function liesUnder2(path77, prefix) {
|
|
16722
|
+
return path77 === prefix || path77.startsWith(prefix + "/");
|
|
16452
16723
|
}
|
|
16453
16724
|
function normalizeSegment(segment) {
|
|
16454
16725
|
return /^\{.+\}$/.test(segment) || segment.startsWith(":") ? "*" : segment;
|
|
@@ -20553,8 +20824,8 @@ function truncate(text2, max) {
|
|
|
20553
20824
|
const clean = text2.replace(/\s+/g, " ").trim();
|
|
20554
20825
|
return clean.length <= max ? clean : `${clean.slice(0, max - 1)}\u2026`;
|
|
20555
20826
|
}
|
|
20556
|
-
function nodeDecl(id,
|
|
20557
|
-
const l = escapeLabel(
|
|
20827
|
+
function nodeDecl(id, label3, comp) {
|
|
20828
|
+
const l = escapeLabel(label3);
|
|
20558
20829
|
if (comp.componentType === "Portal" || comp.componentType === "Observer") return `${id}(["${l}"])`;
|
|
20559
20830
|
if (comp.componentType === "Store" || comp.componentType === "Index") return `${id}[("${l}")]`;
|
|
20560
20831
|
if (PATTERN_TYPES.has(comp.componentType)) return `${id}[["${l}"]]`;
|
|
@@ -20631,8 +20902,8 @@ function generateComponentDiagram(options) {
|
|
|
20631
20902
|
lines.push(` subgraph ${ids.idFor(`sub:${subId}`)}["${subLabel}"]`);
|
|
20632
20903
|
for (const comp of comps) {
|
|
20633
20904
|
const nodeId = ids.idFor(comp.id);
|
|
20634
|
-
const
|
|
20635
|
-
lines.push(` ${nodeDecl(nodeId,
|
|
20905
|
+
const label3 = `${comp.name}<br/>\xAB${comp.componentType}\xBB`;
|
|
20906
|
+
lines.push(` ${nodeDecl(nodeId, label3, comp)}`);
|
|
20636
20907
|
assignClass(stereotypeClass(comp), nodeId);
|
|
20637
20908
|
if (graph2.publicComponents.has(comp.id)) assignClass("publicSurface", nodeId);
|
|
20638
20909
|
}
|
|
@@ -20977,8 +21248,8 @@ function makeNodes(roots) {
|
|
|
20977
21248
|
});
|
|
20978
21249
|
}
|
|
20979
21250
|
function describe(node) {
|
|
20980
|
-
const
|
|
20981
|
-
return node.namespace === "" ? `"${
|
|
21251
|
+
const label3 = node.id ?? node.name ?? "(no id)";
|
|
21252
|
+
return node.namespace === "" ? `"${label3}" (the bound root)` : `"${label3}" (mounted at "${node.namespace}")`;
|
|
20982
21253
|
}
|
|
20983
21254
|
function identityProblems(nodes) {
|
|
20984
21255
|
const problems = [];
|
|
@@ -21410,8 +21681,8 @@ function reach(audience) {
|
|
|
21410
21681
|
const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
|
|
21411
21682
|
return idx === -1 ? SURFACE_AUDIENCES.indexOf("instance") : idx;
|
|
21412
21683
|
}
|
|
21413
|
-
function classifySource(world, sourceId,
|
|
21414
|
-
if (!sourceId) return { kind: "unresolvable", detail: `"${
|
|
21684
|
+
function classifySource(world, sourceId, label3, context) {
|
|
21685
|
+
if (!sourceId) return { kind: "unresolvable", detail: `"${label3}" names no source subsystem and no item whose owner could supply one` };
|
|
21415
21686
|
const sub = world.subsystems.get(sourceId);
|
|
21416
21687
|
const ownSub = sub && (!context || (context.family.owners.get(sourceId) ?? context.namespace) === context.namespace);
|
|
21417
21688
|
if (sub && ownSub) return { kind: "subsystem", subsystem: sub };
|
|
@@ -21424,13 +21695,13 @@ function classifySource(world, sourceId, label2, context) {
|
|
|
21424
21695
|
return { kind: "project", namespace: external.producer, label: `external "${external.alias}"` };
|
|
21425
21696
|
}
|
|
21426
21697
|
if (external?.sourceKind === "path") {
|
|
21427
|
-
return { kind: "unresolvable", detail: `"${
|
|
21698
|
+
return { kind: "unresolvable", detail: `"${label3}" re-exports from external "${external.alias}", which is found only through source.path \xE2\u20AC\u201D the scan cannot follow its table, so a project re-exports only from projects of its family` };
|
|
21428
21699
|
}
|
|
21429
21700
|
if (external) {
|
|
21430
|
-
return { kind: "unresolvable", detail: `"${
|
|
21701
|
+
return { kind: "unresolvable", detail: `"${label3}" re-exports from external "${external.alias}", which does not resolve: ${external.problem}` };
|
|
21431
21702
|
}
|
|
21432
21703
|
}
|
|
21433
|
-
return { kind: "unresolvable", detail: `"${
|
|
21704
|
+
return { kind: "unresolvable", detail: `"${label3}" re-exports from "${sourceId}", which is neither a subsystem of this project, a member nor a declared external` };
|
|
21434
21705
|
}
|
|
21435
21706
|
function bindFromProject(owner, e, source, table, index, problems) {
|
|
21436
21707
|
const named = e.component !== void 0 || e.typeDef !== void 0 || e.interface !== void 0;
|
|
@@ -21465,16 +21736,16 @@ function resolveProjectTable(system, subsystems, components, interfaces, types,
|
|
|
21465
21736
|
const problems = [];
|
|
21466
21737
|
const candidates = [];
|
|
21467
21738
|
(system.publicInterfaces ?? []).forEach((e, index) => {
|
|
21468
|
-
const
|
|
21469
|
-
const source = classifySource(world, sourceOf(world, e),
|
|
21739
|
+
const label3 = e.as ?? e.id ?? e.interface ?? e.component ?? e.typeDef ?? `#${index + 1}`;
|
|
21740
|
+
const source = classifySource(world, sourceOf(world, e), label3, context);
|
|
21470
21741
|
if (source.kind === "unresolvable") {
|
|
21471
|
-
problems.push({ kind: "invalid", owner, publicName:
|
|
21742
|
+
problems.push({ kind: "invalid", owner, publicName: label3, detail: source.detail });
|
|
21472
21743
|
return;
|
|
21473
21744
|
}
|
|
21474
21745
|
if (source.kind === "project") {
|
|
21475
21746
|
const table = context.projectTable(source.namespace);
|
|
21476
21747
|
if (!table) {
|
|
21477
|
-
problems.push({ kind: "named-cycle", owner, publicName:
|
|
21748
|
+
problems.push({ kind: "named-cycle", owner, publicName: label3, targets: [owner, source.namespace], detail: `re-exports "${label3}" from ${source.label}, whose table leads back to this project without reaching the item` });
|
|
21478
21749
|
return;
|
|
21479
21750
|
}
|
|
21480
21751
|
candidates.push(...bindFromProject(owner, e, source, table, index, problems));
|
|
@@ -21488,7 +21759,10 @@ function resolveProjectTable(system, subsystems, components, interfaces, types,
|
|
|
21488
21759
|
source.subsystem,
|
|
21489
21760
|
sourceTable,
|
|
21490
21761
|
{ component: e.component, interface: e.interface, typeDef: e.typeDef },
|
|
21491
|
-
|
|
21762
|
+
// The default public name is the item's own LOCAL id: a member's L0 is
|
|
21763
|
+
// read with its ids qualified into its mount, and its entry names the
|
|
21764
|
+
// item as the member wrote it.
|
|
21765
|
+
() => e.as ?? e.id ?? localName2(e.interface ?? e.component ?? e.typeDef),
|
|
21492
21766
|
false,
|
|
21493
21767
|
problems
|
|
21494
21768
|
);
|
|
@@ -21606,7 +21880,7 @@ function landingEntries(ref, visible, interfaces, componentIds) {
|
|
|
21606
21880
|
});
|
|
21607
21881
|
}
|
|
21608
21882
|
if (ref.position === "type" || ref.position === "reexport") {
|
|
21609
|
-
const typed = visible.filter((e) => e.kind === "type" && (e.typeDef === ref.target || matchTypeRef(ref.target, e.typeDef ?? "")));
|
|
21883
|
+
const typed = visible.filter((e) => e.kind === "type" && (e.typeDef === ref.target || matchTypeRef(ref.target, e.typeDef ?? "") || ref.target === `${e.source}::${localName2(e.typeDef ?? "")}`));
|
|
21610
21884
|
if (typed.length > 0 || ref.position === "type") return typed;
|
|
21611
21885
|
}
|
|
21612
21886
|
return [];
|
|
@@ -22422,13 +22696,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
22422
22696
|
const isPlain = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
22423
22697
|
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
22424
22698
|
const at = (prefix, key) => prefix ? `${prefix}.${key}` : key;
|
|
22425
|
-
const say = (
|
|
22426
|
-
out.push(`${
|
|
22699
|
+
const say = (path77, why) => {
|
|
22700
|
+
out.push(`${path77} \u2014 ${why}`);
|
|
22427
22701
|
};
|
|
22428
|
-
const walkValue = (d, m, s,
|
|
22702
|
+
const walkValue = (d, m, s, path77, field) => {
|
|
22429
22703
|
if (Array.isArray(d)) {
|
|
22430
22704
|
if (!Array.isArray(m)) {
|
|
22431
|
-
say(
|
|
22705
|
+
say(path77, "the level does not have this field, so the write dropped it");
|
|
22432
22706
|
return;
|
|
22433
22707
|
}
|
|
22434
22708
|
if (field === "narrative" && d.some(carriesEditMarker)) return;
|
|
@@ -22436,32 +22710,32 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
22436
22710
|
if (carriesEditMarker(element)) continue;
|
|
22437
22711
|
const key = reportIdentityOf(field, element);
|
|
22438
22712
|
if (key === null) {
|
|
22439
|
-
if (!same(m, d)) say(
|
|
22440
|
-
else if (same(s, d)) say(
|
|
22713
|
+
if (!same(m, d)) say(path77, "the level does not keep this value, so the write dropped it");
|
|
22714
|
+
else if (same(s, d)) say(path77, "the stored spec already held this value");
|
|
22441
22715
|
return;
|
|
22442
22716
|
}
|
|
22443
22717
|
const mMatch = m.find((i) => reportIdentityOf(field, i) === key);
|
|
22444
22718
|
const sMatch = Array.isArray(s) ? s.find((i) => reportIdentityOf(field, i) === key) : void 0;
|
|
22445
22719
|
if (mMatch === void 0) {
|
|
22446
|
-
say(at(
|
|
22720
|
+
say(at(path77, key), "the write did not store this element");
|
|
22447
22721
|
continue;
|
|
22448
22722
|
}
|
|
22449
|
-
walk2(element, mMatch, sMatch, at(
|
|
22723
|
+
walk2(element, mMatch, sMatch, at(path77, key), field);
|
|
22450
22724
|
}
|
|
22451
22725
|
return;
|
|
22452
22726
|
}
|
|
22453
22727
|
if (isPlain(d)) {
|
|
22454
22728
|
if (!isPlain(m)) {
|
|
22455
|
-
say(
|
|
22729
|
+
say(path77, "the level does not have this field, so the write dropped it");
|
|
22456
22730
|
return;
|
|
22457
22731
|
}
|
|
22458
|
-
walk2(d, m, s,
|
|
22732
|
+
walk2(d, m, s, path77, field);
|
|
22459
22733
|
return;
|
|
22460
22734
|
}
|
|
22461
|
-
if (!same(m, d)) say(
|
|
22462
|
-
else if (same(s, d)) say(
|
|
22735
|
+
if (!same(m, d)) say(path77, "the write did not store it \u2014 the level's schema does not keep this value");
|
|
22736
|
+
else if (same(s, d)) say(path77, "the stored spec already held this value");
|
|
22463
22737
|
};
|
|
22464
|
-
function walk2(d, m, s,
|
|
22738
|
+
function walk2(d, m, s, path77, container) {
|
|
22465
22739
|
for (const [key, value] of Object.entries(d)) {
|
|
22466
22740
|
if (DELTA_VERBS.has(key) || JUMP_LABEL_TWINS.has(key)) continue;
|
|
22467
22741
|
if (key === "label" && LABEL_TWIN_CONTAINERS.has(container)) continue;
|
|
@@ -22471,13 +22745,13 @@ function ineffectiveDeltaPaths(delta, merged, stored) {
|
|
|
22471
22745
|
if (typeof name !== "string") continue;
|
|
22472
22746
|
const had = isPlain(s) && s[name] !== void 0;
|
|
22473
22747
|
const still = isPlain(m) && m[name] !== void 0;
|
|
22474
|
-
if (!had) say(at(
|
|
22475
|
-
else if (still) say(at(
|
|
22748
|
+
if (!had) say(at(path77, name), "unset named a field the stored spec did not have");
|
|
22749
|
+
else if (still) say(at(path77, name), "unset did not remove it");
|
|
22476
22750
|
}
|
|
22477
22751
|
continue;
|
|
22478
22752
|
}
|
|
22479
22753
|
if (value === void 0 || value === null) continue;
|
|
22480
|
-
const here = at(
|
|
22754
|
+
const here = at(path77, key);
|
|
22481
22755
|
const mValue = isPlain(m) ? m[key] : void 0;
|
|
22482
22756
|
const sValue = isPlain(s) ? s[key] : void 0;
|
|
22483
22757
|
if (mValue === void 0) {
|
|
@@ -22523,10 +22797,10 @@ function namesInProse(value, named) {
|
|
|
22523
22797
|
if (!value || typeof value !== "object") return false;
|
|
22524
22798
|
return Object.entries(value).some(([key, nested]) => typeof nested === "string" ? PROSE_FIELDS.has(key) && named.test(nested) : namesInProse(nested, named));
|
|
22525
22799
|
}
|
|
22526
|
-
function judgeMoveResult(hooks,
|
|
22800
|
+
function judgeMoveResult(hooks, plan2) {
|
|
22527
22801
|
const refusals = [];
|
|
22528
22802
|
const notices = [];
|
|
22529
|
-
for (const resulting of [
|
|
22803
|
+
for (const resulting of [plan2.edits.get(`component:${plan2.source.id}`), plan2.edits.get(`component:${plan2.target.id}`)]) {
|
|
22530
22804
|
if (!resulting) continue;
|
|
22531
22805
|
try {
|
|
22532
22806
|
const raised = hooks.gate?.("component", resulting.after);
|
|
@@ -22565,9 +22839,9 @@ function moveChangeReports(edits, dryRun) {
|
|
|
22565
22839
|
summary: edit.before === null ? `${dryRun ? "Would create" : "Created"} ${edit.kind} "${edit.id}" to receive the moved methods.` : `${dryRun ? "Would move" : "Moved"} into ${edit.kind} "${edit.id}": ${changes.length} change${changes.length === 1 ? "" : "s"}.`
|
|
22566
22840
|
}));
|
|
22567
22841
|
}
|
|
22568
|
-
function moveRename(from, to, methods,
|
|
22842
|
+
function moveRename(from, to, methods, plan2) {
|
|
22569
22843
|
return {
|
|
22570
|
-
specs:
|
|
22844
|
+
specs: plan2.rehomed.map(({ from: left, to: arrived }) => ({ from: left, to: arrived, sites: [...methods] })),
|
|
22571
22845
|
methods: methods.map((method2) => ({ component: from, method: method2, toComponent: to, toMethod: method2 }))
|
|
22572
22846
|
};
|
|
22573
22847
|
}
|
|
@@ -22816,6 +23090,12 @@ function deregisterPackRef(ref) {
|
|
|
22816
23090
|
function markSelectionsBundled(bundled) {
|
|
22817
23091
|
projectConfigRepository.markSelectionsBundled(bundled);
|
|
22818
23092
|
}
|
|
23093
|
+
function setProjectId(id) {
|
|
23094
|
+
return projectConfigRepository.setId(id);
|
|
23095
|
+
}
|
|
23096
|
+
function declareExternal(alias, declaration2) {
|
|
23097
|
+
return projectConfigRepository.declareExternal(alias, declaration2);
|
|
23098
|
+
}
|
|
22819
23099
|
function specPathsInScope(scopeSubsystem) {
|
|
22820
23100
|
return current().specPathsInScope(scopeSubsystem);
|
|
22821
23101
|
}
|
|
@@ -24446,23 +24726,23 @@ var init_specs2 = __esm({
|
|
|
24446
24726
|
for (const field of fields) delete out[field];
|
|
24447
24727
|
return out;
|
|
24448
24728
|
};
|
|
24449
|
-
const assertDeltaMarkers = (item,
|
|
24729
|
+
const assertDeltaMarkers = (item, label3) => {
|
|
24450
24730
|
if (!item || typeof item !== "object") return;
|
|
24451
24731
|
if ("remove" in item && typeof item.remove !== "boolean") {
|
|
24452
24732
|
throw new Error(
|
|
24453
|
-
`Refusing to update ${
|
|
24733
|
+
`Refusing to update ${label3}: "remove" must be the boolean true, got ${JSON.stringify(item.remove)}. A non-boolean is ignored, which would leave the element in place while reporting success.`
|
|
24454
24734
|
);
|
|
24455
24735
|
}
|
|
24456
24736
|
if ("action" in item && item.action !== "add" && item.action !== "delete") {
|
|
24457
24737
|
throw new Error(
|
|
24458
|
-
`Refusing to update ${
|
|
24738
|
+
`Refusing to update ${label3}: unknown action ${JSON.stringify(item.action)} \u2014 expected "add" or "delete". An unknown verb is ignored, which would leave the element in place while reporting success.`
|
|
24459
24739
|
);
|
|
24460
24740
|
}
|
|
24461
24741
|
};
|
|
24462
|
-
const assertUnmatchedIsAnAddition = (deltaItem, key, existingKeys,
|
|
24742
|
+
const assertUnmatchedIsAnAddition = (deltaItem, key, existingKeys, label3) => {
|
|
24463
24743
|
if (deltaItem?.remove === true || deltaItem?.action === "delete") {
|
|
24464
24744
|
throw new Error(
|
|
24465
|
-
`Refusing to delete ${
|
|
24745
|
+
`Refusing to delete ${label3} "${String(key)}": nothing with that identity exists. ` + (existingKeys.length ? `Present: ${existingKeys.map(String).join(", ")}.` : "The collection is empty.")
|
|
24466
24746
|
);
|
|
24467
24747
|
}
|
|
24468
24748
|
const near = existingKeys.find(
|
|
@@ -24470,7 +24750,7 @@ var init_specs2 = __esm({
|
|
|
24470
24750
|
);
|
|
24471
24751
|
if (near !== void 0) {
|
|
24472
24752
|
throw new Error(
|
|
24473
|
-
`Refusing to add ${
|
|
24753
|
+
`Refusing to add ${label3} "${String(key)}": "${String(near)}" already exists and differs only in case or separators. Use the existing identity to edit it, or pick a name that is not a near-duplicate.`
|
|
24474
24754
|
);
|
|
24475
24755
|
}
|
|
24476
24756
|
};
|
|
@@ -24963,16 +25243,16 @@ var init_specs2 = __esm({
|
|
|
24963
25243
|
const complaint = this.unmovableRequest(source, from, to, methods);
|
|
24964
25244
|
if (complaint) throw new Error(`unmovable request: ${complaint}`);
|
|
24965
25245
|
const contracts = this.loadInterfaceSpecs();
|
|
24966
|
-
const
|
|
24967
|
-
const repointed = this.repointToNewHome(from, to, methods,
|
|
24968
|
-
const mentions = this.moveMentions(from,
|
|
24969
|
-
const rename = moveRename(from, to, methods,
|
|
24970
|
-
this.rekeyMoveAllows(
|
|
25246
|
+
const plan2 = this.planMethodMove(source, to, methods, contracts);
|
|
25247
|
+
const repointed = this.repointToNewHome(from, to, methods, plan2);
|
|
25248
|
+
const mentions = this.moveMentions(from, plan2);
|
|
25249
|
+
const rename = moveRename(from, to, methods, plan2);
|
|
25250
|
+
this.rekeyMoveAllows(plan2, rename);
|
|
24971
25251
|
if (hooks) {
|
|
24972
|
-
const verdict = judgeMoveResult(hooks,
|
|
24973
|
-
|
|
25252
|
+
const verdict = judgeMoveResult(hooks, plan2);
|
|
25253
|
+
plan2.notices.push(...verdict.notices);
|
|
24974
25254
|
if (verdict.refusals.length > 0) {
|
|
24975
|
-
const alternatives = this.rankMoveHomes(hooks, from, to,
|
|
25255
|
+
const alternatives = this.rankMoveHomes(hooks, from, to, plan2);
|
|
24976
25256
|
return {
|
|
24977
25257
|
moved: false,
|
|
24978
25258
|
from,
|
|
@@ -24982,7 +25262,7 @@ var init_specs2 = __esm({
|
|
|
24982
25262
|
repointed: 0,
|
|
24983
25263
|
refusals: verdict.refusals,
|
|
24984
25264
|
alternatives,
|
|
24985
|
-
notices:
|
|
25265
|
+
notices: plan2.notices,
|
|
24986
25266
|
summary: refusedMoveSummary(from, to, methods, verdict.refusals, alternatives),
|
|
24987
25267
|
dryRun,
|
|
24988
25268
|
mentions,
|
|
@@ -24993,7 +25273,7 @@ var init_specs2 = __esm({
|
|
|
24993
25273
|
}
|
|
24994
25274
|
const carried = projectConfigRepository.rekeyCarried(rename, true);
|
|
24995
25275
|
if (dryRun) {
|
|
24996
|
-
const edits2 = moveChangeReports([...
|
|
25276
|
+
const edits2 = moveChangeReports([...plan2.edits.values()], true);
|
|
24997
25277
|
return {
|
|
24998
25278
|
moved: false,
|
|
24999
25279
|
from,
|
|
@@ -25003,15 +25283,15 @@ var init_specs2 = __esm({
|
|
|
25003
25283
|
repointed,
|
|
25004
25284
|
refusals: [],
|
|
25005
25285
|
alternatives: [],
|
|
25006
|
-
notices:
|
|
25007
|
-
summary: `Dry run: moving ${namedMethods(methods)} from "${from}" to "${to}" would touch ${edits2.length} spec${edits2.length === 1 ? "" : "s"}${createdClause(
|
|
25286
|
+
notices: plan2.notices,
|
|
25287
|
+
summary: `Dry run: moving ${namedMethods(methods)} from "${from}" to "${to}" would touch ${edits2.length} spec${edits2.length === 1 ? "" : "s"}${createdClause(plan2.created, "would create")} and re-point ${repointed} reference${repointed === 1 ? "" : "s"}${registerClause(carried, "would rekey")}. Nothing was written.`,
|
|
25008
25288
|
dryRun: true,
|
|
25009
25289
|
mentions,
|
|
25010
|
-
created:
|
|
25290
|
+
created: plan2.created,
|
|
25011
25291
|
carried
|
|
25012
25292
|
};
|
|
25013
25293
|
}
|
|
25014
|
-
const edits = this.writeMoveEdits([...
|
|
25294
|
+
const edits = this.writeMoveEdits([...plan2.edits.values()], () => {
|
|
25015
25295
|
projectConfigRepository.rekeyCarried(rename);
|
|
25016
25296
|
});
|
|
25017
25297
|
return {
|
|
@@ -25023,11 +25303,11 @@ var init_specs2 = __esm({
|
|
|
25023
25303
|
repointed,
|
|
25024
25304
|
refusals: [],
|
|
25025
25305
|
alternatives: [],
|
|
25026
|
-
notices:
|
|
25027
|
-
summary: `Moved ${namedMethods(methods)} from "${from}" to "${to}": ${edits.length} spec${edits.length === 1 ? "" : "s"} written${createdClause(
|
|
25306
|
+
notices: plan2.notices,
|
|
25307
|
+
summary: `Moved ${namedMethods(methods)} from "${from}" to "${to}": ${edits.length} spec${edits.length === 1 ? "" : "s"} written${createdClause(plan2.created, "created")}, ${repointed} reference${repointed === 1 ? "" : "s"} re-pointed${registerClause(carried, "rekeyed")}${mentions.length ? `, ${mentions.length} still naming the old home in prose or on the wire` : ""}.`,
|
|
25028
25308
|
dryRun: false,
|
|
25029
25309
|
mentions,
|
|
25030
|
-
created:
|
|
25310
|
+
created: plan2.created,
|
|
25031
25311
|
carried
|
|
25032
25312
|
};
|
|
25033
25313
|
}
|
|
@@ -25038,15 +25318,15 @@ var init_specs2 = __esm({
|
|
|
25038
25318
|
* covered `<from>.<method>` unit anywhere names `<to>.<method>`. An allow
|
|
25039
25319
|
* whose new home the plan does not stage stays where it is.
|
|
25040
25320
|
*/
|
|
25041
|
-
rekeyMoveAllows(
|
|
25321
|
+
rekeyMoveAllows(plan2, rename) {
|
|
25042
25322
|
const subjects = [...this.everySpecInTree()];
|
|
25043
|
-
for (const edit of
|
|
25044
|
-
const stagedAfter = (kind, id) =>
|
|
25323
|
+
for (const edit of plan2.edits.values()) if (edit.before === null) subjects.push({ kind: edit.kind, id: edit.id, spec: edit.after });
|
|
25324
|
+
const stagedAfter = (kind, id) => plan2.edits.get(`${kind}:${id}`)?.after;
|
|
25045
25325
|
for (const { kind, id, spec } of subjects) {
|
|
25046
25326
|
if (id.includes("::")) continue;
|
|
25047
25327
|
const allows = spec?.lint?.allow ?? [];
|
|
25048
25328
|
if (allows.length === 0) continue;
|
|
25049
|
-
const staged =
|
|
25329
|
+
const staged = plan2.edits.get(`${kind}:${id}`);
|
|
25050
25330
|
const subject = staged ? staged.after : cloneSpec(spec);
|
|
25051
25331
|
const kept = [];
|
|
25052
25332
|
let changed = false;
|
|
@@ -25064,7 +25344,7 @@ var init_specs2 = __esm({
|
|
|
25064
25344
|
}
|
|
25065
25345
|
if (!changed) continue;
|
|
25066
25346
|
subject.lint = { ...subject.lint, allow: kept };
|
|
25067
|
-
if (!staged) this.stageMoveEdit(
|
|
25347
|
+
if (!staged) this.stageMoveEdit(plan2, kind, id, spec, subject);
|
|
25068
25348
|
}
|
|
25069
25349
|
}
|
|
25070
25350
|
/**
|
|
@@ -25131,7 +25411,7 @@ var init_specs2 = __esm({
|
|
|
25131
25411
|
const target = this.loadComponentSpec(to);
|
|
25132
25412
|
const stated = this.moveTargetContract(to, contracts.filter((i) => i.component === to));
|
|
25133
25413
|
const implementations = this.loadImplementationSpecs();
|
|
25134
|
-
const
|
|
25414
|
+
const plan2 = {
|
|
25135
25415
|
edits: /* @__PURE__ */ new Map(),
|
|
25136
25416
|
source,
|
|
25137
25417
|
target,
|
|
@@ -25153,10 +25433,10 @@ var init_specs2 = __esm({
|
|
|
25153
25433
|
arriving.push(...cloneSpec(leaving));
|
|
25154
25434
|
const remaining = cloneSpec(contract);
|
|
25155
25435
|
remaining.methods = remaining.methods.filter((m) => !methods.includes(m.name));
|
|
25156
|
-
this.stageMoveEdit(
|
|
25157
|
-
|
|
25436
|
+
this.stageMoveEdit(plan2, "interface", contract.id, contract, remaining);
|
|
25437
|
+
plan2.rehomed.push({ from: contract.id, to: receiving.id });
|
|
25158
25438
|
if (contract.methods.length === leaving.length) {
|
|
25159
|
-
|
|
25439
|
+
plan2.notices.push(`"${contract.id}" is left with no methods \u2014 "${source.id}" no longer declares anything on it.`);
|
|
25160
25440
|
}
|
|
25161
25441
|
for (const impl of implementations.filter((i) => i.contract === contract.id)) {
|
|
25162
25442
|
const moving = impl.methods.filter((m) => methods.includes(m.name));
|
|
@@ -25165,22 +25445,22 @@ var init_specs2 = __esm({
|
|
|
25165
25445
|
for (const entry of moving) if (impl.sourcePath) realizedIn.set(entry.name, impl.sourcePath);
|
|
25166
25446
|
const kept = cloneSpec(impl);
|
|
25167
25447
|
kept.methods = kept.methods.filter((m) => !methods.includes(m.name));
|
|
25168
|
-
this.stageMoveEdit(
|
|
25448
|
+
this.stageMoveEdit(plan2, "implementation", impl.id, impl, kept);
|
|
25169
25449
|
leftImplementations.push(impl.id);
|
|
25170
25450
|
}
|
|
25171
25451
|
}
|
|
25172
|
-
this.stageMoveEdit(
|
|
25452
|
+
this.stageMoveEdit(plan2, "interface", receiving.id, stated, {
|
|
25173
25453
|
...cloneSpec(receiving),
|
|
25174
25454
|
methods: [...cloneSpec(receiving.methods), ...arriving]
|
|
25175
25455
|
});
|
|
25176
|
-
if (!stated)
|
|
25177
|
-
if (arriving.some((m) => m.endpoint))
|
|
25456
|
+
if (!stated) plan2.created.push(`interface "${receiving.id}"`);
|
|
25457
|
+
if (arriving.some((m) => m.endpoint)) plan2.wireBound.push(receiving.id);
|
|
25178
25458
|
if (stated && receiving.status !== void 0 && receiving.status !== statusOfContracts(contracts, source.id)) {
|
|
25179
|
-
|
|
25459
|
+
plan2.notices.push(`"${receiving.id}" is ${receiving.status} where the methods came from a ${statusOfContracts(contracts, source.id)} contract \u2014 the status of a moved method is the status of its new home.`);
|
|
25180
25460
|
}
|
|
25181
25461
|
for (const entry of travelling) {
|
|
25182
25462
|
if ((entry.narrative ?? []).length === 0 && !entry.intent) {
|
|
25183
|
-
|
|
25463
|
+
plan2.notices.push(`"${entry.name}" moves with an empty narrative and no intent \u2014 nothing followed it but its name.`);
|
|
25184
25464
|
}
|
|
25185
25465
|
}
|
|
25186
25466
|
const targetImpl = implementations.find((i) => i.contract === receiving.id);
|
|
@@ -25189,33 +25469,33 @@ var init_specs2 = __esm({
|
|
|
25189
25469
|
const file = realizedIn.get(entry.name);
|
|
25190
25470
|
if (entry.sourcePath || !file || file === targetImpl.sourcePath) continue;
|
|
25191
25471
|
entry.sourcePath = file;
|
|
25192
|
-
|
|
25472
|
+
plan2.notices.push(`"${entry.name}" keeps ${file} as its own sourcePath: it was realized there by default, and "${targetImpl.id}" names ${targetImpl.sourcePath ? targetImpl.sourcePath : "no file"} \u2014 moving a method is not moving its code.`);
|
|
25193
25473
|
}
|
|
25194
|
-
this.stageMoveEdit(
|
|
25474
|
+
this.stageMoveEdit(plan2, "implementation", targetImpl.id, targetImpl, {
|
|
25195
25475
|
...cloneSpec(targetImpl),
|
|
25196
25476
|
methods: [...cloneSpec(targetImpl.methods), ...travelling]
|
|
25197
25477
|
});
|
|
25198
|
-
for (const id of leftImplementations)
|
|
25478
|
+
for (const id of leftImplementations) plan2.rehomed.push({ from: id, to: targetImpl.id });
|
|
25199
25479
|
} else if (travelling.length > 0) {
|
|
25200
25480
|
const created = createdImplementation(target, receiving.id, source.id, travelling, implementations, contracts);
|
|
25201
|
-
this.stageMoveEdit(
|
|
25202
|
-
for (const id of leftImplementations)
|
|
25203
|
-
|
|
25204
|
-
|
|
25481
|
+
this.stageMoveEdit(plan2, "implementation", created.spec.id, null, created.spec);
|
|
25482
|
+
for (const id of leftImplementations) plan2.rehomed.push({ from: id, to: created.spec.id });
|
|
25483
|
+
plan2.created.push(created.named);
|
|
25484
|
+
plan2.notices.push(...created.notices);
|
|
25205
25485
|
}
|
|
25206
|
-
|
|
25486
|
+
plan2.reach = reachOf(travelling, source.id, new Set(methods)).filter((id) => id !== to);
|
|
25207
25487
|
const held = /* @__PURE__ */ new Set([...target.dependsOn ?? [], ...target.owns ?? []]);
|
|
25208
|
-
|
|
25209
|
-
this.stageMoveEdit(
|
|
25210
|
-
this.stageMoveEdit(
|
|
25488
|
+
plan2.newDependencies = plan2.reach.filter((id) => !held.has(id) && id !== to);
|
|
25489
|
+
this.stageMoveEdit(plan2, "component", source.id, source, cloneSpec(source));
|
|
25490
|
+
this.stageMoveEdit(plan2, "component", target.id, target, {
|
|
25211
25491
|
...cloneSpec(target),
|
|
25212
|
-
dependsOn: [...target.dependsOn ?? [], ...
|
|
25492
|
+
dependsOn: [...target.dependsOn ?? [], ...plan2.newDependencies]
|
|
25213
25493
|
});
|
|
25214
|
-
return
|
|
25494
|
+
return plan2;
|
|
25215
25495
|
}
|
|
25216
25496
|
/** Stage one spec's rewrite, keeping the version it started from as the snapshot a failed write restores. */
|
|
25217
|
-
stageMoveEdit(
|
|
25218
|
-
|
|
25497
|
+
stageMoveEdit(plan2, kind, id, before, after) {
|
|
25498
|
+
plan2.edits.set(`${kind}:${id}`, { kind, id, before, after });
|
|
25219
25499
|
}
|
|
25220
25500
|
/**
|
|
25221
25501
|
* Re-point every reference that names the old home, through the one
|
|
@@ -25225,7 +25505,7 @@ var init_specs2 = __esm({
|
|
|
25225
25505
|
* that is moving: another method of the same component, and another
|
|
25226
25506
|
* component's method of the same name, stay exactly where they point.
|
|
25227
25507
|
*/
|
|
25228
|
-
repointToNewHome(from, to, methods,
|
|
25508
|
+
repointToNewHome(from, to, methods, plan2) {
|
|
25229
25509
|
const moved = new Set(methods);
|
|
25230
25510
|
let repointed = 0;
|
|
25231
25511
|
const remap = (ref, position, owner) => {
|
|
@@ -25234,21 +25514,21 @@ var init_specs2 = __esm({
|
|
|
25234
25514
|
return to;
|
|
25235
25515
|
};
|
|
25236
25516
|
for (const { kind, id, spec } of this.everySpecInTree()) {
|
|
25237
|
-
const staged =
|
|
25517
|
+
const staged = plan2.edits.get(`${kind}:${id}`);
|
|
25238
25518
|
const subject = staged ? staged.after : cloneSpec(spec);
|
|
25239
25519
|
if (!rewriteSpecRefs(subject, remap)) continue;
|
|
25240
25520
|
if (staged) continue;
|
|
25241
25521
|
if (id.includes("::")) {
|
|
25242
|
-
|
|
25522
|
+
plan2.notices.push(`"${id}" lives in a chained subproject and still names "${from}" \u2014 re-point it from that project's own root.`);
|
|
25243
25523
|
repointed -= 1;
|
|
25244
25524
|
continue;
|
|
25245
25525
|
}
|
|
25246
|
-
this.stageMoveEdit(
|
|
25526
|
+
this.stageMoveEdit(plan2, kind, id, spec, subject);
|
|
25247
25527
|
}
|
|
25248
|
-
for (const edit of
|
|
25528
|
+
for (const edit of plan2.edits.values()) {
|
|
25249
25529
|
if (edit.before === null) rewriteSpecRefs(edit.after, remap);
|
|
25250
25530
|
}
|
|
25251
|
-
|
|
25531
|
+
plan2.notices.push(...this.callersOwingADependency(to, plan2));
|
|
25252
25532
|
return repointed;
|
|
25253
25533
|
}
|
|
25254
25534
|
/**
|
|
@@ -25257,13 +25537,13 @@ var init_specs2 = __esm({
|
|
|
25257
25537
|
* list, because a dependency nobody judged is exactly what the gate exists to
|
|
25258
25538
|
* prevent.
|
|
25259
25539
|
*/
|
|
25260
|
-
callersOwingADependency(to,
|
|
25540
|
+
callersOwingADependency(to, plan2) {
|
|
25261
25541
|
const contracts = this.loadInterfaceSpecs();
|
|
25262
25542
|
const owing = /* @__PURE__ */ new Set();
|
|
25263
|
-
for (const edit of
|
|
25543
|
+
for (const edit of plan2.edits.values()) {
|
|
25264
25544
|
const owner = edit.kind === "component" ? edit.id : contracts.find((i) => i.id === edit.after.contract)?.component;
|
|
25265
25545
|
if (!owner || owner === to) continue;
|
|
25266
|
-
const component = owner ===
|
|
25546
|
+
const component = owner === plan2.target.id ? plan2.target : this.loadComponentSpec(owner);
|
|
25267
25547
|
if (!component) continue;
|
|
25268
25548
|
const held = /* @__PURE__ */ new Set([...component.dependsOn ?? [], ...component.owns ?? []]);
|
|
25269
25549
|
if (!held.has(to)) owing.add(owner);
|
|
@@ -25278,11 +25558,11 @@ var init_specs2 = __esm({
|
|
|
25278
25558
|
* because the gate holds the judgement. `assess` answers rather than throws,
|
|
25279
25559
|
* so this is a search and not a sequence of caught exceptions.
|
|
25280
25560
|
*/
|
|
25281
|
-
rankMoveHomes(hooks, from, to,
|
|
25561
|
+
rankMoveHomes(hooks, from, to, plan2) {
|
|
25282
25562
|
const limit = this.dependencyLimit();
|
|
25283
|
-
const pool = this.loadComponentSpecs().filter((c) => c.subsystem ===
|
|
25284
|
-
if (!pool.some((c) => c.id === to)) pool.push(
|
|
25285
|
-
return pool.map((candidate) => weighMoveHome(hooks, candidate,
|
|
25563
|
+
const pool = this.loadComponentSpecs().filter((c) => c.subsystem === plan2.source.subsystem && c.id !== from);
|
|
25564
|
+
if (!pool.some((c) => c.id === to)) pool.push(plan2.target);
|
|
25565
|
+
return pool.map((candidate) => weighMoveHome(hooks, candidate, plan2.reach, limit)).sort((a, b) => Number(b.legal) - Number(a.legal) || a.newDependencies.length - b.newDependencies.length || a.component.localeCompare(b.component));
|
|
25286
25566
|
}
|
|
25287
25567
|
/**
|
|
25288
25568
|
* The project's `maxComponentDependencies`, so a candidate's dependency count
|
|
@@ -25312,8 +25592,8 @@ var init_specs2 = __esm({
|
|
|
25312
25592
|
* receiving contract whose moved methods keep their wire address. A move
|
|
25313
25593
|
* never edits prose and never re-addresses an RPC.
|
|
25314
25594
|
*/
|
|
25315
|
-
moveMentions(from,
|
|
25316
|
-
const mentions = new Set(
|
|
25595
|
+
moveMentions(from, plan2) {
|
|
25596
|
+
const mentions = new Set(plan2.wireBound);
|
|
25317
25597
|
const named = new RegExp(`(?<![A-Za-z0-9_])${from}(?![A-Za-z0-9_])`);
|
|
25318
25598
|
for (const { kind, id, spec } of this.everySpecInTree()) {
|
|
25319
25599
|
if (namesInProse(spec, named)) mentions.add(kind === "system" ? "system" : id);
|
|
@@ -25333,9 +25613,9 @@ var init_specs2 = __esm({
|
|
|
25333
25613
|
const reports = moveChangeReports(edits, false);
|
|
25334
25614
|
const written = [];
|
|
25335
25615
|
try {
|
|
25336
|
-
for (const
|
|
25337
|
-
const edit = edits.find((e) => e.kind ===
|
|
25338
|
-
|
|
25616
|
+
for (const report3 of reports) {
|
|
25617
|
+
const edit = edits.find((e) => e.kind === report3.kind && e.id === report3.id);
|
|
25618
|
+
report3.notices.push(...this.saveMovedSpec(edit.kind, edit.after));
|
|
25339
25619
|
written.push(edit);
|
|
25340
25620
|
}
|
|
25341
25621
|
finish?.();
|
|
@@ -26107,11 +26387,11 @@ function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
|
26107
26387
|
if (!movingContracts.has(implementation.contract)) continue;
|
|
26108
26388
|
const realization = implementation.methods.find((m) => m.name === methodName);
|
|
26109
26389
|
if (!realization) continue;
|
|
26110
|
-
const
|
|
26111
|
-
if (
|
|
26390
|
+
const pin2 = realization.symbol === void 0 && pinSymbol !== false;
|
|
26391
|
+
if (pin2) pinnedSymbol = methodName;
|
|
26112
26392
|
saveImplementationSpec({
|
|
26113
26393
|
...implementation,
|
|
26114
|
-
methods: implementation.methods.map((m) => m.name === methodName ? { ...m, name: newName, ...
|
|
26394
|
+
methods: implementation.methods.map((m) => m.name === methodName ? { ...m, name: newName, ...pin2 ? { symbol: methodName } : {} } : m)
|
|
26115
26395
|
});
|
|
26116
26396
|
renamed.push(implementation.id);
|
|
26117
26397
|
}
|
|
@@ -27206,14 +27486,14 @@ var init_custom = __esm({
|
|
|
27206
27486
|
}
|
|
27207
27487
|
export(ctx) {
|
|
27208
27488
|
const { agent, target, renderedInstructions } = ctx;
|
|
27209
|
-
const
|
|
27489
|
+
const label3 = "label" in target ? target.label : "Custom";
|
|
27210
27490
|
const filePath = this.outputPath(ctx);
|
|
27211
27491
|
const content = [
|
|
27212
27492
|
"---",
|
|
27213
27493
|
`name: ${agent.name}`,
|
|
27214
27494
|
`description: ${agent.description}`,
|
|
27215
27495
|
`id: ${agent.id}`,
|
|
27216
|
-
`target: ${
|
|
27496
|
+
`target: ${label3}`,
|
|
27217
27497
|
"---",
|
|
27218
27498
|
"",
|
|
27219
27499
|
renderedInstructions,
|
|
@@ -30410,7 +30690,7 @@ var require_dist = __commonJS({
|
|
|
30410
30690
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
30411
30691
|
}
|
|
30412
30692
|
var fs60 = __toESM2(require("fs"));
|
|
30413
|
-
var
|
|
30693
|
+
var path77 = __toESM2(require("path"));
|
|
30414
30694
|
var import_fflate = require_node();
|
|
30415
30695
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".hg", ".svn"]);
|
|
30416
30696
|
function listEntries(archive) {
|
|
@@ -30448,8 +30728,8 @@ var require_dist = __commonJS({
|
|
|
30448
30728
|
}
|
|
30449
30729
|
function writeTree(destDir, files) {
|
|
30450
30730
|
for (const file of files) {
|
|
30451
|
-
const absolute =
|
|
30452
|
-
fs60.mkdirSync(
|
|
30731
|
+
const absolute = path77.join(destDir, file.path);
|
|
30732
|
+
fs60.mkdirSync(path77.dirname(absolute), { recursive: true });
|
|
30453
30733
|
fs60.writeFileSync(absolute, file.contents);
|
|
30454
30734
|
}
|
|
30455
30735
|
}
|
|
@@ -30462,10 +30742,10 @@ var require_dist = __commonJS({
|
|
|
30462
30742
|
for (const entry of fs60.readdirSync(current2, { withFileTypes: true })) {
|
|
30463
30743
|
if (entry.isDirectory()) {
|
|
30464
30744
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
30465
|
-
walkPackDir(root,
|
|
30745
|
+
walkPackDir(root, path77.join(current2, entry.name), out);
|
|
30466
30746
|
} else if (entry.isFile()) {
|
|
30467
|
-
const absolute =
|
|
30468
|
-
const relative22 =
|
|
30747
|
+
const absolute = path77.join(current2, entry.name);
|
|
30748
|
+
const relative22 = path77.relative(root, absolute).split(path77.sep).join("/");
|
|
30469
30749
|
out.push({ path: relative22, contents: fs60.readFileSync(absolute) });
|
|
30470
30750
|
}
|
|
30471
30751
|
}
|
|
@@ -30561,9 +30841,9 @@ var require_dist = __commonJS({
|
|
|
30561
30841
|
function extractPack3(archiveBytes, destDir, limits) {
|
|
30562
30842
|
const effectiveLimits = limits === void 0 ? defaultLimits() : limits;
|
|
30563
30843
|
const entries = listEntries(archiveBytes);
|
|
30564
|
-
const
|
|
30844
|
+
const plan2 = planExtraction(entries, effectiveLimits);
|
|
30565
30845
|
const files = [];
|
|
30566
|
-
for (const approvedPath of
|
|
30846
|
+
for (const approvedPath of plan2.paths) {
|
|
30567
30847
|
const contents = inflateEntry(archiveBytes, approvedPath);
|
|
30568
30848
|
files.push({ path: approvedPath, contents });
|
|
30569
30849
|
}
|
|
@@ -30636,12 +30916,12 @@ var require_dist = __commonJS({
|
|
|
30636
30916
|
function extractTreeArchive3(archiveBytes, destDir, limits, refuseExecutableEntries) {
|
|
30637
30917
|
const effectiveLimits = limits === void 0 ? defaultTreeLimits() : limits;
|
|
30638
30918
|
const entries = listEntries(archiveBytes);
|
|
30639
|
-
const
|
|
30919
|
+
const plan2 = planTreeExtraction(entries, effectiveLimits);
|
|
30640
30920
|
if (refuseExecutableEntries === true) {
|
|
30641
|
-
assertPortableTreePaths(
|
|
30921
|
+
assertPortableTreePaths(plan2.paths);
|
|
30642
30922
|
}
|
|
30643
30923
|
const files = [];
|
|
30644
|
-
for (const approvedPath of
|
|
30924
|
+
for (const approvedPath of plan2.paths) {
|
|
30645
30925
|
const contents = inflateEntry(archiveBytes, approvedPath);
|
|
30646
30926
|
files.push({ path: approvedPath, contents });
|
|
30647
30927
|
}
|
|
@@ -30899,7 +31179,7 @@ var init_treetransfer = __esm({
|
|
|
30899
31179
|
});
|
|
30900
31180
|
|
|
30901
31181
|
// src/core/stereotype-migration.ts
|
|
30902
|
-
function retireSpecialists(
|
|
31182
|
+
function retireSpecialists(apply2) {
|
|
30903
31183
|
const components = loadComponentSpecs();
|
|
30904
31184
|
const byId = new Map(components.map((c) => [c.id, c]));
|
|
30905
31185
|
const specialists = components.filter((c) => c.componentType === "Specialist" && !c.id.includes("::")).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
@@ -30986,7 +31266,7 @@ function retireSpecialists(apply) {
|
|
|
30986
31266
|
reason: reasons.get(specialist.id)
|
|
30987
31267
|
};
|
|
30988
31268
|
});
|
|
30989
|
-
if (!
|
|
31269
|
+
if (!apply2) return { retyped, rebasedVariants: specialistVariants, applied: false };
|
|
30990
31270
|
for (const retype of retyped) {
|
|
30991
31271
|
const orchestrator = { ...byId.get(retype.component), componentType: "Orchestrator" };
|
|
30992
31272
|
delete orchestrator.dependencyClass;
|
|
@@ -31008,7 +31288,7 @@ var init_stereotype_migration = __esm({
|
|
|
31008
31288
|
});
|
|
31009
31289
|
|
|
31010
31290
|
// src/core/narrative-repair.ts
|
|
31011
|
-
function repairForeignStepFields(
|
|
31291
|
+
function repairForeignStepFields(apply2) {
|
|
31012
31292
|
const implementations = loadImplementationSpecs();
|
|
31013
31293
|
const repairs = [];
|
|
31014
31294
|
const changed = [];
|
|
@@ -31031,7 +31311,7 @@ function repairForeignStepFields(apply) {
|
|
|
31031
31311
|
}
|
|
31032
31312
|
if (touched) changed.push(impl);
|
|
31033
31313
|
}
|
|
31034
|
-
if (
|
|
31314
|
+
if (apply2 && changed.length) {
|
|
31035
31315
|
for (const impl of changed) saveImplementationSpec(impl);
|
|
31036
31316
|
invalidateSpecCache();
|
|
31037
31317
|
}
|
|
@@ -31047,8 +31327,8 @@ var init_narrative_repair = __esm({
|
|
|
31047
31327
|
|
|
31048
31328
|
// src/models/lock.ts
|
|
31049
31329
|
function describeApprover(who) {
|
|
31050
|
-
const
|
|
31051
|
-
return who.source === "hosted" ? `${
|
|
31330
|
+
const label3 = who.name ? `${who.name} (${who.id})` : who.id;
|
|
31331
|
+
return who.source === "hosted" ? `${label3} [authenticated]` : label3;
|
|
31052
31332
|
}
|
|
31053
31333
|
var init_lock = __esm({
|
|
31054
31334
|
"src/models/lock.ts"() {
|
|
@@ -32244,9 +32524,9 @@ function statusForCreate(restatement, existing) {
|
|
|
32244
32524
|
const held = stored !== void 0 && STATUS_ORDER.includes(stored) ? stored : void 0;
|
|
32245
32525
|
if (stated === void 0) return { status: held ?? "draft" };
|
|
32246
32526
|
if (held === void 0 || STATUS_ORDER.indexOf(stated) >= STATUS_ORDER.indexOf(held)) return { status: stated };
|
|
32247
|
-
const
|
|
32527
|
+
const label3 = `${restatement.kind} "${restatement.spec.id}"`;
|
|
32248
32528
|
return {
|
|
32249
|
-
refusal: `Refusing to re-author ${
|
|
32529
|
+
refusal: `Refusing to re-author ${label3} at status "${stated}": it is stored at "${held}", and a create tool never lowers a spec's status \u2014 a restatement that reopened a frozen spec would undo a lock without saying so. Nothing was written. To reopen it deliberately, use sdd_update_spec with {"status": "${stated}"}; to keep the level it has, leave status out.`
|
|
32250
32530
|
};
|
|
32251
32531
|
}
|
|
32252
32532
|
function carryInto(restatement, existing, candidate) {
|
|
@@ -32430,17 +32710,17 @@ function updateSpecGated(kind, id, delta, dryRun) {
|
|
|
32430
32710
|
const testRoots = bound2.rules?.conformance?.testRoots ?? [];
|
|
32431
32711
|
const stored = loadSpec(kind, id);
|
|
32432
32712
|
const gate = componentCandidateGate(bound2, stored?.subsystem);
|
|
32433
|
-
const
|
|
32434
|
-
const changed = changedMethods(
|
|
32713
|
+
const report3 = updateSpec(kind, id, delta, gate, dryRun);
|
|
32714
|
+
const changed = changedMethods(report3);
|
|
32435
32715
|
if (changed.length > 0 && testRoots.length > 0) {
|
|
32436
32716
|
const written = Array.isArray(delta?.methods) ? delta.methods : [];
|
|
32437
|
-
|
|
32717
|
+
report3.testsToRevisit = testsInvalidatedBy(kind, id, changed, [stored], bound2, written);
|
|
32438
32718
|
}
|
|
32439
|
-
return
|
|
32719
|
+
return report3;
|
|
32440
32720
|
}
|
|
32441
|
-
function changedMethods(
|
|
32721
|
+
function changedMethods(report3) {
|
|
32442
32722
|
const named = /* @__PURE__ */ new Set();
|
|
32443
|
-
for (const change of
|
|
32723
|
+
for (const change of report3.changes) {
|
|
32444
32724
|
const [field, name] = change.path.split(".");
|
|
32445
32725
|
if (field === "methods" && name) named.add(name);
|
|
32446
32726
|
}
|
|
@@ -32725,18 +33005,18 @@ function structured(content, data) {
|
|
|
32725
33005
|
function jsonStructured(value) {
|
|
32726
33006
|
return structured(JSON.stringify(value, null, 2), value);
|
|
32727
33007
|
}
|
|
32728
|
-
function renderChangeReport(
|
|
32729
|
-
const lines = [
|
|
32730
|
-
for (const change of
|
|
33008
|
+
function renderChangeReport(report3) {
|
|
33009
|
+
const lines = [report3.dryRun ? `DRY RUN \u2014 nothing was written. ${report3.summary}` : report3.summary];
|
|
33010
|
+
for (const change of report3.changes) {
|
|
32731
33011
|
const to = change.after === void 0 ? "" : `: ${JSON.stringify(change.after)}`;
|
|
32732
33012
|
const from = change.before === void 0 ? "" : ` (was ${JSON.stringify(change.before)})`;
|
|
32733
|
-
lines.push(`- ${change.path} ${
|
|
33013
|
+
lines.push(`- ${change.path} ${report3.dryRun ? `would be ${change.change}` : change.change}${to}${from}`);
|
|
32734
33014
|
}
|
|
32735
|
-
if (
|
|
32736
|
-
lines.push("", "NO EFFECT:", ...
|
|
33015
|
+
if (report3.ineffective.length) {
|
|
33016
|
+
lines.push("", "NO EFFECT:", ...report3.ineffective.map((i) => `- ${i}`));
|
|
32737
33017
|
}
|
|
32738
|
-
if (
|
|
32739
|
-
lines.push(...renderTestsToRevisit(
|
|
33018
|
+
if (report3.notices.length) lines.push("", "NOTICE:", ...report3.notices.map((n) => `- ${n}`));
|
|
33019
|
+
lines.push(...renderTestsToRevisit(report3.testsToRevisit));
|
|
32740
33020
|
return lines.join("\n");
|
|
32741
33021
|
}
|
|
32742
33022
|
function renderTestsToRevisit(entries) {
|
|
@@ -33251,11 +33531,11 @@ function createMcpServer(options = {}) {
|
|
|
33251
33531
|
if (!sub) return errText(`Subsystem "${subsystem}" does not exist.`);
|
|
33252
33532
|
const delta = publicInterfacesReplacement(subsystem, sub.publicInterfaces ?? [], publicInterfaces);
|
|
33253
33533
|
if (typeof delta === "string") return errText(delta);
|
|
33254
|
-
const
|
|
33534
|
+
const report3 = updateSpecGated("subsystem", subsystem, delta);
|
|
33255
33535
|
return structured(
|
|
33256
33536
|
`Updated public interfaces for subsystem "${subsystem}" (${publicInterfaces.length} ${publicInterfaces.length === 1 ? "entry" : "entries"}).
|
|
33257
|
-
${renderChangeReport(
|
|
33258
|
-
|
|
33537
|
+
${renderChangeReport(report3)}`,
|
|
33538
|
+
report3
|
|
33259
33539
|
);
|
|
33260
33540
|
} catch (e) {
|
|
33261
33541
|
return errMessage(e);
|
|
@@ -33276,11 +33556,11 @@ ${renderChangeReport(report2)}`,
|
|
|
33276
33556
|
({ subsystem, projectPath }) => {
|
|
33277
33557
|
try {
|
|
33278
33558
|
const delta = projectPath ? { projectPath } : { unset: ["projectPath"] };
|
|
33279
|
-
const
|
|
33559
|
+
const report3 = updateSpecGated("subsystem", subsystem, delta);
|
|
33280
33560
|
return structured(
|
|
33281
33561
|
`Updated projectPath for subsystem "${subsystem}" to: ${projectPath || "none (cleared)"}
|
|
33282
|
-
${renderChangeReport(
|
|
33283
|
-
|
|
33562
|
+
${renderChangeReport(report3)}`,
|
|
33563
|
+
report3
|
|
33284
33564
|
);
|
|
33285
33565
|
} catch (e) {
|
|
33286
33566
|
return errMessage(e);
|
|
@@ -33614,11 +33894,11 @@ ${renderChangeReport(report2)}`,
|
|
|
33614
33894
|
methods.push({ name: e.method, endpoint: parsed.data });
|
|
33615
33895
|
bound2.push(`${e.method}\u2192${e.transport}`);
|
|
33616
33896
|
}
|
|
33617
|
-
const
|
|
33897
|
+
const report3 = updateSpecGated("interface", interfaceId, { methods });
|
|
33618
33898
|
return structured(
|
|
33619
33899
|
`Bound ${bound2.length} endpoint(s) on "${interfaceId}": ${bound2.join(", ")}.
|
|
33620
|
-
${renderChangeReport(
|
|
33621
|
-
|
|
33900
|
+
${renderChangeReport(report3)}`,
|
|
33901
|
+
report3
|
|
33622
33902
|
);
|
|
33623
33903
|
} catch (e) {
|
|
33624
33904
|
return errMessage(e);
|
|
@@ -33960,8 +34240,8 @@ ${testsBlock}` : ""}`, deletion);
|
|
|
33960
34240
|
},
|
|
33961
34241
|
({ kind, id, delta, dryRun }) => {
|
|
33962
34242
|
try {
|
|
33963
|
-
const
|
|
33964
|
-
return structured(renderChangeReport(
|
|
34243
|
+
const report3 = updateSpecGated(kind, id, delta, dryRun);
|
|
34244
|
+
return structured(renderChangeReport(report3), report3);
|
|
33965
34245
|
} catch (e) {
|
|
33966
34246
|
return errText(String(e));
|
|
33967
34247
|
}
|
|
@@ -33979,13 +34259,13 @@ ${testsBlock}` : ""}`, deletion);
|
|
|
33979
34259
|
},
|
|
33980
34260
|
({ subsystem, recursive }) => {
|
|
33981
34261
|
try {
|
|
33982
|
-
const
|
|
34262
|
+
const report3 = getStatusReport({
|
|
33983
34263
|
subsystem,
|
|
33984
34264
|
recursive: recursive ?? true
|
|
33985
34265
|
});
|
|
33986
34266
|
const family = statusFamilyContext();
|
|
33987
34267
|
const verdict = approvalVerdict();
|
|
33988
|
-
return text(`${family}${
|
|
34268
|
+
return text(`${family}${report3.text}${verdict.text}`);
|
|
33989
34269
|
} catch (e) {
|
|
33990
34270
|
return errText(String(e));
|
|
33991
34271
|
}
|
|
@@ -34662,18 +34942,18 @@ async function runMcpStatus() {
|
|
|
34662
34942
|
{ label: "Antigravity (project)", filePath: geminiProject, fallbackName: "settings.json" },
|
|
34663
34943
|
{ label: "Antigravity (global)", filePath: geminiGlobal, fallbackName: "mcp_config.json" }
|
|
34664
34944
|
];
|
|
34665
|
-
for (const { label:
|
|
34945
|
+
for (const { label: label3, filePath, fallbackName } of checks) {
|
|
34666
34946
|
if (!fs24.existsSync(filePath)) {
|
|
34667
|
-
console.log(` ${
|
|
34947
|
+
console.log(` ${label3}: ${import_chalk3.default.gray(`${fallbackName} not found`)}`);
|
|
34668
34948
|
continue;
|
|
34669
34949
|
}
|
|
34670
34950
|
try {
|
|
34671
34951
|
const s = JSON.parse(fs24.readFileSync(filePath, "utf8"));
|
|
34672
34952
|
const registered = !!s["mcpServers"]?.["wairon"];
|
|
34673
34953
|
const mark = registered ? import_chalk3.default.green("\u2713 registered") : import_chalk3.default.gray("not registered");
|
|
34674
|
-
console.log(` ${
|
|
34954
|
+
console.log(` ${label3}: ${mark} ${import_chalk3.default.gray(filePath)}`);
|
|
34675
34955
|
} catch {
|
|
34676
|
-
console.log(` ${
|
|
34956
|
+
console.log(` ${label3}: ${import_chalk3.default.red("parse error")} ${import_chalk3.default.gray(filePath)}`);
|
|
34677
34957
|
}
|
|
34678
34958
|
}
|
|
34679
34959
|
logger.blank();
|
|
@@ -34732,7 +35012,7 @@ var init_mcp = __esm({
|
|
|
34732
35012
|
});
|
|
34733
35013
|
|
|
34734
35014
|
// src/cli/index.ts
|
|
34735
|
-
var
|
|
35015
|
+
var path76 = __toESM(require("path"));
|
|
34736
35016
|
var import_commander = require("commander");
|
|
34737
35017
|
init_defaults();
|
|
34738
35018
|
init_logger();
|
|
@@ -36015,14 +36295,14 @@ var http = __toESM(require("http"));
|
|
|
36015
36295
|
var https = __toESM(require("https"));
|
|
36016
36296
|
init_defaults();
|
|
36017
36297
|
function downloadFile(url, dest) {
|
|
36018
|
-
return new Promise((
|
|
36298
|
+
return new Promise((resolve37, reject) => {
|
|
36019
36299
|
const file = fs26.createWriteStream(dest);
|
|
36020
36300
|
const get4 = url.startsWith("https://") ? https.get : http.get;
|
|
36021
36301
|
get4(url, { headers: { "User-Agent": `wairon/${WAIRON_VERSION}` }, agent: false }, (res) => {
|
|
36022
36302
|
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
36023
36303
|
file.close();
|
|
36024
36304
|
res.destroy();
|
|
36025
|
-
downloadFile(res.headers.location, dest).then(
|
|
36305
|
+
downloadFile(res.headers.location, dest).then(resolve37).catch(reject);
|
|
36026
36306
|
return;
|
|
36027
36307
|
}
|
|
36028
36308
|
if (res.statusCode !== 200) {
|
|
@@ -36034,7 +36314,7 @@ function downloadFile(url, dest) {
|
|
|
36034
36314
|
res.pipe(file);
|
|
36035
36315
|
file.on("finish", () => {
|
|
36036
36316
|
res.destroy();
|
|
36037
|
-
file.close(() =>
|
|
36317
|
+
file.close(() => resolve37());
|
|
36038
36318
|
});
|
|
36039
36319
|
file.on("error", (err) => {
|
|
36040
36320
|
res.destroy();
|
|
@@ -36086,8 +36366,8 @@ async function runUpdate(options = {}) {
|
|
|
36086
36366
|
return;
|
|
36087
36367
|
}
|
|
36088
36368
|
const latestVersion = release.tag_name.replace(/^v/, "");
|
|
36089
|
-
const
|
|
36090
|
-
const channelLabel =
|
|
36369
|
+
const label3 = releaseChannelLabel(release.tag_name);
|
|
36370
|
+
const channelLabel = label3 === "stable" ? "" : ` [${label3}]`;
|
|
36091
36371
|
logger.info(`New version available: ${release.tag_name}${channelLabel} (current: ${WAIRON_VERSION})`);
|
|
36092
36372
|
if (release.body) {
|
|
36093
36373
|
logger.blank();
|
|
@@ -36176,19 +36456,19 @@ function releaseTier(tag, githubPrerelease = false) {
|
|
|
36176
36456
|
if (dash === -1) {
|
|
36177
36457
|
return githubPrerelease ? CHANNEL_RANK.dev : CHANNEL_RANK.stable;
|
|
36178
36458
|
}
|
|
36179
|
-
const
|
|
36180
|
-
const rank = CHANNEL_RANK[
|
|
36459
|
+
const label3 = version.slice(dash + 1).replace(/\.\d+$/, "");
|
|
36460
|
+
const rank = CHANNEL_RANK[label3];
|
|
36181
36461
|
return rank === void 0 || rank === CHANNEL_RANK.stable ? CHANNEL_RANK.dev : rank;
|
|
36182
36462
|
}
|
|
36183
36463
|
function reportOffChannelBuild(channel, currentVersion, newestOnChannel) {
|
|
36184
36464
|
const tier = releaseTier(currentVersion);
|
|
36185
36465
|
if (tier <= (CHANNEL_RANK[channel] ?? CHANNEL_RANK.stable)) return;
|
|
36186
|
-
const
|
|
36466
|
+
const label3 = releaseChannelLabel(currentVersion);
|
|
36187
36467
|
logger.warn(
|
|
36188
|
-
`This is a ${
|
|
36468
|
+
`This is a ${label3} build (${WAIRON_VERSION}) but the update channel is ${channel}.`
|
|
36189
36469
|
);
|
|
36190
36470
|
const target = newestOnChannel ? ` The newest ${channel} release is ${newestOnChannel}.` : "";
|
|
36191
|
-
const track = isUpdateChannel(
|
|
36471
|
+
const track = isUpdateChannel(label3) ? `Track this build with \`wairon update --channel ${label3}\`, or reinstall` : "Reinstall";
|
|
36192
36472
|
logger.info(`It will not update until ${channel} passes it.${target} ${track} to return to ${channel}.`);
|
|
36193
36473
|
logger.blank();
|
|
36194
36474
|
}
|
|
@@ -36197,9 +36477,9 @@ function reportWiderChannel(releases, channel, currentVersion) {
|
|
|
36197
36477
|
(r) => !isEligibleForChannel(r.tag_name, channel, r.prerelease) && isNewer(currentVersion, r.tag_name.replace(/^v/, ""))
|
|
36198
36478
|
);
|
|
36199
36479
|
if (!wider) return;
|
|
36200
|
-
const
|
|
36201
|
-
const hint = isUpdateChannel(
|
|
36202
|
-
logger.info(`A newer pre-release exists: ${wider.tag_name} [${
|
|
36480
|
+
const label3 = releaseChannelLabel(wider.tag_name);
|
|
36481
|
+
const hint = isUpdateChannel(label3) ? ` \u2014 install it with \`wairon update --channel ${label3}\`.` : ".";
|
|
36482
|
+
logger.info(`A newer pre-release exists: ${wider.tag_name} [${label3}]${hint}`);
|
|
36203
36483
|
}
|
|
36204
36484
|
function isEligibleForChannel(tag, channel, githubPrerelease = false) {
|
|
36205
36485
|
return releaseTier(tag, githubPrerelease) <= (CHANNEL_RANK[channel] ?? CHANNEL_RANK.stable);
|
|
@@ -36211,7 +36491,7 @@ function releaseChannelLabel(tag) {
|
|
|
36211
36491
|
return version.slice(dash + 1).replace(/\.\d+$/, "") || "stable";
|
|
36212
36492
|
}
|
|
36213
36493
|
function fetchReleases(repo) {
|
|
36214
|
-
return new Promise((
|
|
36494
|
+
return new Promise((resolve37, reject) => {
|
|
36215
36495
|
const url = `https://api.github.com/repos/${repo}/releases?per_page=100`;
|
|
36216
36496
|
const options = {
|
|
36217
36497
|
headers: {
|
|
@@ -36231,7 +36511,7 @@ function fetchReleases(repo) {
|
|
|
36231
36511
|
return;
|
|
36232
36512
|
}
|
|
36233
36513
|
try {
|
|
36234
|
-
|
|
36514
|
+
resolve37(JSON.parse(data));
|
|
36235
36515
|
} catch {
|
|
36236
36516
|
reject(new Error("Failed to parse GitHub API response"));
|
|
36237
36517
|
}
|
|
@@ -36375,13 +36655,13 @@ function withoutTrailingNewline(text2) {
|
|
|
36375
36655
|
}
|
|
36376
36656
|
async function runStatus(options = {}) {
|
|
36377
36657
|
assertProjectInitialized();
|
|
36378
|
-
const
|
|
36379
|
-
if (
|
|
36380
|
-
refuseUnreadableTree(
|
|
36658
|
+
const report3 = getStatusReport(options, TERMINAL_DECOR);
|
|
36659
|
+
if (report3.failed) {
|
|
36660
|
+
refuseUnreadableTree(report3.text);
|
|
36381
36661
|
}
|
|
36382
36662
|
logger.header("Architecture Status Dashboard");
|
|
36383
36663
|
logger.blank();
|
|
36384
|
-
console.log(withoutTrailingNewline(
|
|
36664
|
+
console.log(withoutTrailingNewline(report3.text));
|
|
36385
36665
|
const lock = approvalVerdict();
|
|
36386
36666
|
if (lock.text.trim()) {
|
|
36387
36667
|
logger.blank();
|
|
@@ -36458,7 +36738,7 @@ async function filteredCheckbox(config) {
|
|
|
36458
36738
|
32,
|
|
36459
36739
|
Math.max(...items.map((i) => i.label.length))
|
|
36460
36740
|
);
|
|
36461
|
-
return new Promise((
|
|
36741
|
+
return new Promise((resolve37) => {
|
|
36462
36742
|
const checked = /* @__PURE__ */ new Set();
|
|
36463
36743
|
let cursor = 0;
|
|
36464
36744
|
let filterIdx = 0;
|
|
@@ -36525,7 +36805,7 @@ async function filteredCheckbox(config) {
|
|
|
36525
36805
|
);
|
|
36526
36806
|
teardown();
|
|
36527
36807
|
const result = items.filter((_, idx) => checked.has(idx)).map((i) => i.value);
|
|
36528
|
-
|
|
36808
|
+
resolve37(result);
|
|
36529
36809
|
}
|
|
36530
36810
|
function abort() {
|
|
36531
36811
|
process.stdout.write("\n");
|
|
@@ -36797,8 +37077,9 @@ async function runSkillsInstall() {
|
|
|
36797
37077
|
// src/commands/doctor.ts
|
|
36798
37078
|
var fs28 = __toESM(require("fs"));
|
|
36799
37079
|
var os9 = __toESM(require("os"));
|
|
36800
|
-
var
|
|
37080
|
+
var path43 = __toESM(require("path"));
|
|
36801
37081
|
var import_chalk12 = __toESM(require("chalk"));
|
|
37082
|
+
var import_inquirer4 = __toESM(require("inquirer"));
|
|
36802
37083
|
init_logger();
|
|
36803
37084
|
init_defaults();
|
|
36804
37085
|
init_paths();
|
|
@@ -36807,6 +37088,356 @@ init_fs();
|
|
|
36807
37088
|
init_project();
|
|
36808
37089
|
init_lock();
|
|
36809
37090
|
init_mcp();
|
|
37091
|
+
|
|
37092
|
+
// src/commands/chaining-migration.ts
|
|
37093
|
+
var path42 = __toESM(require("path"));
|
|
37094
|
+
|
|
37095
|
+
// src/commands/adapters/surfaces.ts
|
|
37096
|
+
init_surface_portal();
|
|
37097
|
+
|
|
37098
|
+
// src/commands/chaining-migration.ts
|
|
37099
|
+
init_fs();
|
|
37100
|
+
init_paths();
|
|
37101
|
+
init_errors();
|
|
37102
|
+
init_project();
|
|
37103
|
+
init_project_family();
|
|
37104
|
+
init_exports();
|
|
37105
|
+
function isEmpty(migration) {
|
|
37106
|
+
return migration.projects.every((p) => !hasWrites(p));
|
|
37107
|
+
}
|
|
37108
|
+
function blocked(migration) {
|
|
37109
|
+
return migration.findings.some((f) => f.blocking);
|
|
37110
|
+
}
|
|
37111
|
+
function hasWrites(p) {
|
|
37112
|
+
return p.idToWrite !== void 0 || p.exports.length > 0 || p.externals.length > 0 || p.pins.length > 0;
|
|
37113
|
+
}
|
|
37114
|
+
function plan() {
|
|
37115
|
+
const bound2 = getProjectRoot();
|
|
37116
|
+
const climbed = climb2(bound2);
|
|
37117
|
+
return runWithProjectRoot(climbed.top, () => planFamily(climbed.top, climbed.whole));
|
|
37118
|
+
}
|
|
37119
|
+
function climb2(start2) {
|
|
37120
|
+
let current2 = start2;
|
|
37121
|
+
let parent;
|
|
37122
|
+
do {
|
|
37123
|
+
parent = runWithProjectRoot(current2, () => resolveChainingParent());
|
|
37124
|
+
if (parent) current2 = parent.parentRoot;
|
|
37125
|
+
} while (parent);
|
|
37126
|
+
return { top: current2, whole: !parentWithheld() };
|
|
37127
|
+
}
|
|
37128
|
+
function parentWithheld() {
|
|
37129
|
+
const reach2 = getRequestParentReach();
|
|
37130
|
+
return reach2 !== null && !reach2.parentReach;
|
|
37131
|
+
}
|
|
37132
|
+
function planFamily(top, whole) {
|
|
37133
|
+
const ctx = { family: graph(), projects: /* @__PURE__ */ new Map(), findings: [], absent: /* @__PURE__ */ new Map() };
|
|
37134
|
+
if (!whole) {
|
|
37135
|
+
ctx.findings.push({
|
|
37136
|
+
kind: "family-partial",
|
|
37137
|
+
project: "",
|
|
37138
|
+
blocking: true,
|
|
37139
|
+
detail: "the climb stopped at a hop out of reach, so a producer above it could need writes this plan cannot see \u2014 run the migration from the family's top root"
|
|
37140
|
+
});
|
|
37141
|
+
}
|
|
37142
|
+
decideIds(ctx);
|
|
37143
|
+
planCrossings(ctx);
|
|
37144
|
+
convertLegacyPins(ctx);
|
|
37145
|
+
return settle2(ctx, top, whole);
|
|
37146
|
+
}
|
|
37147
|
+
function entryOf(ctx, node) {
|
|
37148
|
+
let entry = ctx.projects.get(node.namespace);
|
|
37149
|
+
if (!entry) {
|
|
37150
|
+
entry = { project: node.namespace, directory: node.directory, exports: [], externals: [], pins: [], supersededPins: [] };
|
|
37151
|
+
ctx.projects.set(node.namespace, entry);
|
|
37152
|
+
}
|
|
37153
|
+
return entry;
|
|
37154
|
+
}
|
|
37155
|
+
function idOf(ctx, namespace) {
|
|
37156
|
+
return ctx.projects.get(namespace)?.id;
|
|
37157
|
+
}
|
|
37158
|
+
var label2 = (namespace) => namespace === "" ? "the top root" : `"${namespace}"`;
|
|
37159
|
+
function decideIds(ctx) {
|
|
37160
|
+
for (const node of ctx.family.nodes) {
|
|
37161
|
+
const approved = approvalRecord(node.directory)?.projectId;
|
|
37162
|
+
decideId(ctx, node, approved);
|
|
37163
|
+
}
|
|
37164
|
+
checkPlannedIds(ctx);
|
|
37165
|
+
}
|
|
37166
|
+
function decideId(ctx, node, approved) {
|
|
37167
|
+
const entry = entryOf(ctx, node);
|
|
37168
|
+
const member = node.parent !== void 0;
|
|
37169
|
+
if (node.idSource === "declared") {
|
|
37170
|
+
entry.id = node.id;
|
|
37171
|
+
return;
|
|
37172
|
+
}
|
|
37173
|
+
const planned = approved ?? (member ? node.mountAlias : node.id);
|
|
37174
|
+
if (node.name === void 0) absentProject(ctx, node);
|
|
37175
|
+
if (planned === void 0) {
|
|
37176
|
+
ctx.findings.push({ kind: "id-ambiguous", project: node.namespace, blocking: false, detail: `${label2(node.namespace)} declares no id and its name yields none \u2014 declare one in its project.yaml` });
|
|
37177
|
+
return;
|
|
37178
|
+
}
|
|
37179
|
+
entry.id = planned;
|
|
37180
|
+
entry.idToWrite = planned;
|
|
37181
|
+
if (approved !== void 0 && member && approved !== node.mountAlias) {
|
|
37182
|
+
ctx.findings.push({
|
|
37183
|
+
kind: "id-locked",
|
|
37184
|
+
project: node.namespace,
|
|
37185
|
+
blocking: false,
|
|
37186
|
+
detail: `${label2(node.namespace)} keeps "${approved}", the id its lock approved, rather than its mount's subsystem id "${node.mountAlias}" \u2014 moving it is the rename migration`
|
|
37187
|
+
});
|
|
37188
|
+
}
|
|
37189
|
+
}
|
|
37190
|
+
function absentProject(ctx, node) {
|
|
37191
|
+
const finding = {
|
|
37192
|
+
kind: "project-absent",
|
|
37193
|
+
project: node.namespace,
|
|
37194
|
+
blocking: false,
|
|
37195
|
+
detail: `${label2(node.namespace)} (${node.directory}) has no readable project.yaml \u2014 \`wairon doctor --fix\` writes one for a chained child first`
|
|
37196
|
+
};
|
|
37197
|
+
ctx.findings.push(finding);
|
|
37198
|
+
ctx.absent.set(node.namespace, finding);
|
|
37199
|
+
}
|
|
37200
|
+
function checkPlannedIds(ctx) {
|
|
37201
|
+
const holders = /* @__PURE__ */ new Map();
|
|
37202
|
+
for (const entry of ctx.projects.values()) {
|
|
37203
|
+
if (entry.id !== void 0) holders.set(entry.id, [...holders.get(entry.id) ?? [], entry.project]);
|
|
37204
|
+
}
|
|
37205
|
+
for (const entry of ctx.projects.values()) {
|
|
37206
|
+
if (entry.idToWrite === void 0) continue;
|
|
37207
|
+
const others = (holders.get(entry.idToWrite) ?? []).filter((ns) => ns !== entry.project);
|
|
37208
|
+
const why = !PROJECT_ID_RE.test(entry.idToWrite) ? "breaks the project-id grammar" : others.length > 0 ? `is also the id of ${others.map(label2).join(", ")}` : void 0;
|
|
37209
|
+
if (why === void 0) continue;
|
|
37210
|
+
ctx.findings.push({ kind: "id-ambiguous", project: entry.project, blocking: false, detail: `the id planned for ${label2(entry.project)}, "${entry.idToWrite}", ${why} \u2014 declare one by hand` });
|
|
37211
|
+
delete entry.id;
|
|
37212
|
+
delete entry.idToWrite;
|
|
37213
|
+
}
|
|
37214
|
+
reportOrphanedDeclarations(ctx);
|
|
37215
|
+
}
|
|
37216
|
+
function reportOrphanedDeclarations(ctx) {
|
|
37217
|
+
for (const node of ctx.family.nodes) {
|
|
37218
|
+
for (const external of node.externals) {
|
|
37219
|
+
if (external.sourceKind !== "family" || external.producer === void 0) continue;
|
|
37220
|
+
const next = ctx.projects.get(external.producer)?.idToWrite;
|
|
37221
|
+
if (next === void 0 || next === external.project) continue;
|
|
37222
|
+
ctx.findings.push({
|
|
37223
|
+
kind: "declaration-orphaned",
|
|
37224
|
+
project: node.namespace,
|
|
37225
|
+
blocking: false,
|
|
37226
|
+
detail: `the external "${external.alias}" finds ${label2(external.producer)} by "${external.project}", which it leaves for "${next}" \u2014 re-point the declaration after the migration`
|
|
37227
|
+
});
|
|
37228
|
+
}
|
|
37229
|
+
}
|
|
37230
|
+
}
|
|
37231
|
+
function planCrossings(ctx) {
|
|
37232
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
37233
|
+
for (const ref of ctx.family.references) pairs.set(`${ref.consumer}\0${ref.producer}`, { consumer: ref.consumer, producer: ref.producer });
|
|
37234
|
+
for (const { consumer, producer } of pairs.values()) planPair(ctx, consumer, producer);
|
|
37235
|
+
}
|
|
37236
|
+
function planPair(ctx, consumer, producer) {
|
|
37237
|
+
const consumerNode2 = familyNode(ctx.family, consumer);
|
|
37238
|
+
const producerNode = familyNode(ctx.family, producer);
|
|
37239
|
+
if (!consumerNode2 || !producerNode) return;
|
|
37240
|
+
const usage = exportUsage(consumer, producer);
|
|
37241
|
+
const table = resolveProjectExports(producer || void 0);
|
|
37242
|
+
let entries = false;
|
|
37243
|
+
for (const ref of usage.unexported) entries = planEntry(ctx, producerNode, ref, table) || entries;
|
|
37244
|
+
const alias = declares(ctx.family, consumer, producer) ? declaredAlias(consumerNode2, producer) : planExternal(ctx, consumerNode2, producer, "reference");
|
|
37245
|
+
if (alias !== void 0 && (entries || alias.planned)) addPin(ctx, consumerNode2, alias.alias);
|
|
37246
|
+
}
|
|
37247
|
+
function declaredAlias(consumer, producer) {
|
|
37248
|
+
const external = consumer.externals.find((e) => e.sourceKind === "family" && e.producer === producer);
|
|
37249
|
+
return external ? { alias: external.alias, planned: false } : void 0;
|
|
37250
|
+
}
|
|
37251
|
+
function addPin(ctx, consumer, alias) {
|
|
37252
|
+
const entry = entryOf(ctx, consumer);
|
|
37253
|
+
if (!entry.pins.includes(alias)) entry.pins.push(alias);
|
|
37254
|
+
}
|
|
37255
|
+
function planEntry(ctx, producer, ref, table) {
|
|
37256
|
+
const target = targetOf(ref);
|
|
37257
|
+
if (!target) return report(ctx, "target-unpublished", ref, `${ref.specId} names "${ref.target}", which ${label2(producer.namespace)} does not hold`);
|
|
37258
|
+
if (target.kind === "subsystem") {
|
|
37259
|
+
return report(ctx, "subsystem-reference", ref, `${ref.specId} re-exports ${label2(producer.namespace)}'s subsystem "${target.id}" wholesale \u2014 no L0 entry short of exporting it expresses that; stage 3 rewrites the reference`);
|
|
37260
|
+
}
|
|
37261
|
+
const published = resolveSubsystemExports(target.source);
|
|
37262
|
+
return decideEntry(ctx, producer, ref, target, table, published);
|
|
37263
|
+
}
|
|
37264
|
+
function targetOf(ref) {
|
|
37265
|
+
const component = loadSpec("component", ref.target);
|
|
37266
|
+
if (component) return { kind: "component", id: component.id, source: component.subsystem };
|
|
37267
|
+
const last = ref.target.split("::").pop();
|
|
37268
|
+
for (const candidate of [ref.target, ref.producer ? `${ref.producer}::${last}` : last]) {
|
|
37269
|
+
const type = loadSpec("type", candidate);
|
|
37270
|
+
if (type) return type.subsystem ? { kind: "type", id: type.id, source: type.subsystem } : null;
|
|
37271
|
+
}
|
|
37272
|
+
const subsystem = loadSpec("subsystem", ref.target);
|
|
37273
|
+
return subsystem ? { kind: "subsystem", id: subsystem.id, source: subsystem.id } : null;
|
|
37274
|
+
}
|
|
37275
|
+
function decideEntry(ctx, producer, ref, target, table, published) {
|
|
37276
|
+
const key = targetKey(target);
|
|
37277
|
+
const at = published.entries.filter((e) => exportTargetKey({ ...e, interface: void 0 }) === key);
|
|
37278
|
+
if (at.length === 0) {
|
|
37279
|
+
return report(ctx, "target-unpublished", ref, `"${target.id}" is not in its subsystem's L1 table, so no L0 re-export can follow it \u2014 publish it at L1 first, or the reference is wrong`);
|
|
37280
|
+
}
|
|
37281
|
+
if (table.entries.some((e) => exportTargetKey({ ...e, interface: void 0 }) === key) || !reachableThrough(at, ref)) {
|
|
37282
|
+
return report(ctx, "narrowed", ref, `"${target.id}" is exported under a narrowing that does not declare "${ref.member ?? "what the reference reaches"}" \u2014 widen the narrowing or reach another member`);
|
|
37283
|
+
}
|
|
37284
|
+
const local = localIn(producer.namespace, target.id);
|
|
37285
|
+
const publicName = local.split("::").pop();
|
|
37286
|
+
const taken = table.entries.find((e) => e.publicName === publicName && exportTargetKey({ ...e, interface: void 0 }) !== key) ?? entryOf(ctx, producer).exports.find((e) => e.publicName === publicName && (e.component ?? e.typeDef) !== local);
|
|
37287
|
+
if (taken) {
|
|
37288
|
+
return report(ctx, "name-taken", ref, `"${publicName}" already names another item in ${label2(producer.namespace)} \u2014 export "${target.id}" under a name a person chooses`);
|
|
37289
|
+
}
|
|
37290
|
+
mergeEntry(entryOf(ctx, producer), target, localIn(producer.namespace, target.source), local, publicName, ref);
|
|
37291
|
+
return true;
|
|
37292
|
+
}
|
|
37293
|
+
function reachableThrough(entries, ref) {
|
|
37294
|
+
if (ref.member === void 0 || ref.member.startsWith("capability:")) return true;
|
|
37295
|
+
return entries.some((e) => {
|
|
37296
|
+
if (e.kind !== "component" || e.interface === void 0) return true;
|
|
37297
|
+
const narrowing = loadSpec("interface", e.interface);
|
|
37298
|
+
return narrowing?.methods.some((m) => m.name === ref.member) ?? false;
|
|
37299
|
+
});
|
|
37300
|
+
}
|
|
37301
|
+
var targetKey = (t) => t.kind === "type" ? `type:${t.id}` : `component:${t.id}`;
|
|
37302
|
+
function localIn(namespace, id) {
|
|
37303
|
+
return namespace && id.startsWith(`${namespace}::`) ? id.slice(namespace.length + 2) : id;
|
|
37304
|
+
}
|
|
37305
|
+
function mergeEntry(entry, target, from, item, publicName, ref) {
|
|
37306
|
+
let planned = entry.exports.find((e) => e.from === from && (target.kind === "type" ? e.typeDef : e.component) === item);
|
|
37307
|
+
if (!planned) {
|
|
37308
|
+
planned = { from, ...target.kind === "type" ? { typeDef: item } : { component: item }, publicName, audience: "project", consumers: [], members: [] };
|
|
37309
|
+
entry.exports.push(planned);
|
|
37310
|
+
}
|
|
37311
|
+
addSorted(planned.consumers, ref.consumer);
|
|
37312
|
+
const member = target.kind === "type" ? "type" : ref.member;
|
|
37313
|
+
if (member !== void 0) addSorted(planned.members, member);
|
|
37314
|
+
}
|
|
37315
|
+
function addSorted(list2, value) {
|
|
37316
|
+
if (!list2.includes(value)) {
|
|
37317
|
+
list2.push(value);
|
|
37318
|
+
list2.sort();
|
|
37319
|
+
}
|
|
37320
|
+
}
|
|
37321
|
+
function report(ctx, kind, ref, detail) {
|
|
37322
|
+
ctx.findings.push({ kind, project: ref.producer, detail, reference: ref, blocking: false });
|
|
37323
|
+
return false;
|
|
37324
|
+
}
|
|
37325
|
+
function planExternal(ctx, consumer, producer, reason) {
|
|
37326
|
+
const alias = idOf(ctx, producer);
|
|
37327
|
+
const refuse = (kind, detail) => {
|
|
37328
|
+
ctx.findings.push({ kind, project: consumer.namespace, blocking: false, detail });
|
|
37329
|
+
return void 0;
|
|
37330
|
+
};
|
|
37331
|
+
if (alias === void 0) return refuse("alias-invalid", `${label2(producer)} has no id to declare it under \u2014 declare its id first`);
|
|
37332
|
+
if (!EXTERNAL_ALIAS_RE.test(alias)) return refuse("alias-invalid", `"${alias}" is not an alias ([a-z0-9-_]+) \u2014 declare ${label2(producer)} under an alias a person chooses`);
|
|
37333
|
+
const existing = consumer.externals.find((e) => e.alias === alias);
|
|
37334
|
+
if (existing && existing.project === alias) return { alias, planned: true };
|
|
37335
|
+
const mounted = consumer.members.some((m) => familyNode(ctx.family, m)?.mountAlias === alias);
|
|
37336
|
+
const entry = entryOf(ctx, consumer);
|
|
37337
|
+
const planned = entry.externals.find((e) => e.alias === alias);
|
|
37338
|
+
if (existing || mounted || planned && planned.producer !== producer) {
|
|
37339
|
+
return refuse("alias-taken", `${label2(consumer.namespace)} already uses the alias "${alias}" for something else \u2014 declare ${label2(producer)} under another`);
|
|
37340
|
+
}
|
|
37341
|
+
if (!planned) entry.externals.push({ alias, project: alias, producer, reason });
|
|
37342
|
+
return { alias, planned: true };
|
|
37343
|
+
}
|
|
37344
|
+
function convertLegacyPins(ctx) {
|
|
37345
|
+
for (const node of ctx.family.nodes) {
|
|
37346
|
+
if (node.parent === void 0) continue;
|
|
37347
|
+
const vendored = runWithProjectRoot(node.directory, () => listExternalInterfaces2());
|
|
37348
|
+
for (const surface of vendored) {
|
|
37349
|
+
if (surface.sourceKind === "sibling") addSorted(entryOf(ctx, node).supersededPins, surface.projectName);
|
|
37350
|
+
else if (surface.sourceKind === "parent") convertParentPin(ctx, node, node.parent);
|
|
37351
|
+
}
|
|
37352
|
+
}
|
|
37353
|
+
}
|
|
37354
|
+
function convertParentPin(ctx, member, parent) {
|
|
37355
|
+
if (declares(ctx.family, member.namespace, parent)) return;
|
|
37356
|
+
if (entryOf(ctx, member).externals.some((e) => e.producer === parent)) return;
|
|
37357
|
+
const alias = planExternal(ctx, member, parent, "legacy-pin");
|
|
37358
|
+
if (alias !== void 0) addPin(ctx, member, alias.alias);
|
|
37359
|
+
}
|
|
37360
|
+
function settle2(ctx, top, whole) {
|
|
37361
|
+
const projects = [];
|
|
37362
|
+
for (const node of ctx.family.nodes) {
|
|
37363
|
+
const entry = ctx.projects.get(node.namespace);
|
|
37364
|
+
if (!entry || !hasWrites(entry)) continue;
|
|
37365
|
+
entry.exports.sort((a, b) => compare(a.from, b.from) || compare(a.component ?? a.typeDef ?? "", b.component ?? b.typeDef ?? ""));
|
|
37366
|
+
entry.externals.sort((a, b) => compare(a.alias, b.alias));
|
|
37367
|
+
entry.pins.sort();
|
|
37368
|
+
projects.push(entry);
|
|
37369
|
+
}
|
|
37370
|
+
for (const [namespace, finding] of ctx.absent) finding.blocking = projects.some((p) => p.project === namespace);
|
|
37371
|
+
return { familyRoot: top, whole, projects, findings: ctx.findings };
|
|
37372
|
+
}
|
|
37373
|
+
var compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
37374
|
+
var WriteLog = class {
|
|
37375
|
+
constructor() {
|
|
37376
|
+
this.written = [];
|
|
37377
|
+
this.relock = [];
|
|
37378
|
+
}
|
|
37379
|
+
file(file) {
|
|
37380
|
+
if (!this.written.includes(file)) this.written.push(file);
|
|
37381
|
+
}
|
|
37382
|
+
stale(directory) {
|
|
37383
|
+
if (!this.relock.includes(directory)) this.relock.push(directory);
|
|
37384
|
+
}
|
|
37385
|
+
};
|
|
37386
|
+
function apply(plan2) {
|
|
37387
|
+
if (isEmpty(plan2)) return { plan: plan2, applied: false, written: [], relock: [] };
|
|
37388
|
+
if (blocked(plan2)) {
|
|
37389
|
+
throw new ChainingMigrationRefusedError(plan2.findings.filter((f) => f.blocking).map((f) => `${f.kind} (${label2(f.project)}): ${f.detail}`));
|
|
37390
|
+
}
|
|
37391
|
+
const projects = plan2.projects.filter(hasWrites);
|
|
37392
|
+
for (const p of projects) runWithProjectRoot(p.directory, () => preflight(p));
|
|
37393
|
+
const log = new WriteLog();
|
|
37394
|
+
for (const p of projects.filter((q2) => q2.idToWrite !== void 0)) runWithProjectRoot(p.directory, () => declareId(p, log));
|
|
37395
|
+
for (const p of projects.filter((q2) => q2.exports.length > 0)) runWithProjectRoot(p.directory, () => addEntries(p, log));
|
|
37396
|
+
for (const p of projects.filter((q2) => q2.externals.length > 0)) runWithProjectRoot(p.directory, () => declareExternals(p, log));
|
|
37397
|
+
for (const p of projects.filter((q2) => q2.pins.length > 0)) runWithProjectRoot(p.directory, () => pin(p, log));
|
|
37398
|
+
return { plan: plan2, applied: true, written: log.written, relock: log.relock };
|
|
37399
|
+
}
|
|
37400
|
+
function preflight(p) {
|
|
37401
|
+
if (!projectConfigExists()) {
|
|
37402
|
+
throw new ChainingMigrationRefusedError([`project-absent (${label2(p.project)}): ${p.directory} has no project.yaml any more`]);
|
|
37403
|
+
}
|
|
37404
|
+
if (p.exports.length > 0) updateSpecGated("system", "system", exportDelta(p), true);
|
|
37405
|
+
}
|
|
37406
|
+
function exportDelta(p) {
|
|
37407
|
+
return {
|
|
37408
|
+
publicInterfaces: p.exports.map((e) => ({
|
|
37409
|
+
from: e.from,
|
|
37410
|
+
...e.typeDef !== void 0 ? { typeDef: e.typeDef } : { component: e.component },
|
|
37411
|
+
audience: e.audience
|
|
37412
|
+
}))
|
|
37413
|
+
};
|
|
37414
|
+
}
|
|
37415
|
+
function declareId(p, log) {
|
|
37416
|
+
if (setProjectId(p.idToWrite)) log.file(AI_PATHS.projectConfig());
|
|
37417
|
+
}
|
|
37418
|
+
function addEntries(p, log) {
|
|
37419
|
+
const change = updateSpecGated("system", "system", exportDelta(p));
|
|
37420
|
+
if (!change.written) return;
|
|
37421
|
+
log.file(AI_PATHS.specsSystem());
|
|
37422
|
+
log.stale(p.directory);
|
|
37423
|
+
}
|
|
37424
|
+
function declareExternals(p, log) {
|
|
37425
|
+
for (const external of p.externals) {
|
|
37426
|
+
if (!declareExternal(external.alias, {})) continue;
|
|
37427
|
+
log.file(AI_PATHS.projectConfig());
|
|
37428
|
+
log.stale(p.directory);
|
|
37429
|
+
}
|
|
37430
|
+
}
|
|
37431
|
+
function pin(p, log) {
|
|
37432
|
+
for (const pinned of pinExternals2(p.pins)) {
|
|
37433
|
+
if (pinned.outcome !== "pinned") continue;
|
|
37434
|
+
if (pinned.snapshot) log.file(path42.resolve(p.directory, pinned.snapshot));
|
|
37435
|
+
log.file(path42.join(p.directory, ".wai", "externals.lock.yaml"));
|
|
37436
|
+
log.stale(p.directory);
|
|
37437
|
+
}
|
|
37438
|
+
}
|
|
37439
|
+
|
|
37440
|
+
// src/commands/doctor.ts
|
|
36810
37441
|
function enabledTargets() {
|
|
36811
37442
|
const config = loadProjectConfig();
|
|
36812
37443
|
return config ? activeTargetTypes(config) : [];
|
|
@@ -36848,11 +37479,15 @@ function mcpEntryHealth(settingsPath) {
|
|
|
36848
37479
|
}
|
|
36849
37480
|
async function runDoctor(options = {}) {
|
|
36850
37481
|
const tally = { warn: 0, error: 0 };
|
|
37482
|
+
if (options.report !== void 0) {
|
|
37483
|
+
reportOnly(options);
|
|
37484
|
+
return;
|
|
37485
|
+
}
|
|
36851
37486
|
logger.blank();
|
|
36852
37487
|
console.log(`${import_chalk12.default.bold("wairon doctor")} ${import_chalk12.default.gray(`\u2014 installed v${WAIRON_VERSION}`)}`);
|
|
36853
37488
|
logger.blank();
|
|
36854
37489
|
if (options.fix) {
|
|
36855
|
-
await applyFixes();
|
|
37490
|
+
await applyFixes(options, tally);
|
|
36856
37491
|
}
|
|
36857
37492
|
console.log(import_chalk12.default.bold("Project"));
|
|
36858
37493
|
if (!projectConfigExists()) {
|
|
@@ -36891,7 +37526,7 @@ async function runDoctor(options = {}) {
|
|
|
36891
37526
|
try {
|
|
36892
37527
|
const missing = findChainingSubprojectsMissingConfig(getProjectRoot());
|
|
36893
37528
|
if (missing.length > 0) {
|
|
36894
|
-
line(tally, "warn", `${missing.length} chained subproject(s) have specs but no project.yaml (un-runnable standalone): ${missing.map((d) =>
|
|
37529
|
+
line(tally, "warn", `${missing.length} chained subproject(s) have specs but no project.yaml (un-runnable standalone): ${missing.map((d) => path43.relative(getProjectRoot(), d) || ".").join(", ")}. Run \`wairon doctor --fix\` to initialize them.`);
|
|
36895
37530
|
}
|
|
36896
37531
|
} catch {
|
|
36897
37532
|
}
|
|
@@ -36915,15 +37550,15 @@ async function runDoctor(options = {}) {
|
|
|
36915
37550
|
}
|
|
36916
37551
|
logger.blank();
|
|
36917
37552
|
try {
|
|
36918
|
-
const
|
|
36919
|
-
if (
|
|
37553
|
+
const plan2 = retireSpecialists(false);
|
|
37554
|
+
if (plan2.retyped.length > 0) {
|
|
36920
37555
|
console.log(import_chalk12.default.bold("Stereotypes"));
|
|
36921
|
-
for (const retype of
|
|
37556
|
+
for (const retype of plan2.retyped) {
|
|
36922
37557
|
const cls = retype.dependencyClass ?? "workflow";
|
|
36923
37558
|
line(tally, "warn", `${retype.component}: Specialist \u2192 Orchestrator (${cls}) \u2014 ${retype.reason}`);
|
|
36924
37559
|
}
|
|
36925
|
-
if (
|
|
36926
|
-
line(tally, "warn", `${
|
|
37560
|
+
if (plan2.rebasedVariants.length > 0) {
|
|
37561
|
+
line(tally, "warn", `${plan2.rebasedVariants.length} project variant(s) to rebase from Specialist to Orchestrator: ${plan2.rebasedVariants.join(", ")}`);
|
|
36927
37562
|
}
|
|
36928
37563
|
line(tally, "warn", "Run `wairon doctor --fix` to retire the Specialist stereotype.");
|
|
36929
37564
|
logger.blank();
|
|
@@ -36948,23 +37583,33 @@ async function runDoctor(options = {}) {
|
|
|
36948
37583
|
} catch (e) {
|
|
36949
37584
|
line(tally, "warn", `Could not plan the narrative-step repair: ${e instanceof Error ? e.message : String(e)}`);
|
|
36950
37585
|
}
|
|
37586
|
+
try {
|
|
37587
|
+
const pending = plan();
|
|
37588
|
+
if (!isEmpty(pending) || pending.findings.length > 0) {
|
|
37589
|
+
console.log(import_chalk12.default.bold("Chaining"));
|
|
37590
|
+
line(tally, "warn", `Chaining: ${pendingCount(pending)} pending (${chainingTotals(pending)}) \u2014 see \`wairon doctor --report chaining\`, apply with \`wairon doctor --fix\``);
|
|
37591
|
+
logger.blank();
|
|
37592
|
+
}
|
|
37593
|
+
} catch (e) {
|
|
37594
|
+
line(tally, "warn", `Could not plan the chaining migration: ${e instanceof Error ? e.message : String(e)}`);
|
|
37595
|
+
}
|
|
36951
37596
|
}
|
|
36952
37597
|
console.log(import_chalk12.default.bold(`Generated files ${import_chalk12.default.gray("(stale = older than installed)")}`));
|
|
36953
37598
|
for (const p of derivedDocPaths()) {
|
|
36954
|
-
const
|
|
37599
|
+
const label3 = path43.relative(getProjectRoot(), p).replace(/\\/g, "/");
|
|
36955
37600
|
if (!pathExists(p)) {
|
|
36956
|
-
line(tally, "warn", `${
|
|
37601
|
+
line(tally, "warn", `${label3} \u2014 not generated yet (run \`wairon generate\`)`);
|
|
36957
37602
|
continue;
|
|
36958
37603
|
}
|
|
36959
37604
|
const { mark, note } = stampVerdict(readFileOrNull(p));
|
|
36960
|
-
line(tally, mark, `${
|
|
37605
|
+
line(tally, mark, `${label3} (${note})`);
|
|
36961
37606
|
}
|
|
36962
37607
|
const seenGuides = /* @__PURE__ */ new Set();
|
|
36963
37608
|
for (const t of targets) {
|
|
36964
37609
|
const gp = localGuideFilePath(process.cwd(), t);
|
|
36965
37610
|
if (!gp || seenGuides.has(gp)) continue;
|
|
36966
37611
|
seenGuides.add(gp);
|
|
36967
|
-
const rel2 =
|
|
37612
|
+
const rel2 = path43.relative(process.cwd(), gp).replace(/\\/g, "/");
|
|
36968
37613
|
if (!pathExists(gp)) {
|
|
36969
37614
|
line(tally, "warn", `${rel2} guide \u2014 not injected (run \`wairon generate\`)`);
|
|
36970
37615
|
continue;
|
|
@@ -37013,7 +37658,7 @@ async function runDoctor(options = {}) {
|
|
|
37013
37658
|
}
|
|
37014
37659
|
}
|
|
37015
37660
|
try {
|
|
37016
|
-
const legacy =
|
|
37661
|
+
const legacy = path43.join(os9.homedir(), ".wairon", "baselines");
|
|
37017
37662
|
const leftovers = fs28.existsSync(legacy) ? fs28.readdirSync(legacy).filter((f) => f.endsWith(".json")) : [];
|
|
37018
37663
|
if (leftovers.length) {
|
|
37019
37664
|
console.log(import_chalk12.default.bold("Approvals"));
|
|
@@ -37063,7 +37708,7 @@ async function runDoctor(options = {}) {
|
|
|
37063
37708
|
line(tally, h.mark, `Claude (project .mcp.json): ${h.note}${h.mark === "ok" ? "" : " \u2014 run `wairon mcp install --backend claude`"}`);
|
|
37064
37709
|
}
|
|
37065
37710
|
if (wantGemini) {
|
|
37066
|
-
const globalCfg =
|
|
37711
|
+
const globalCfg = path43.join(os9.homedir(), ".gemini", "antigravity-cli", "mcp_config.json");
|
|
37067
37712
|
const hg = mcpEntryHealth(globalCfg);
|
|
37068
37713
|
line(tally, hg.mark, `Antigravity (global mcp_config.json): ${hg.note}${hg.mark === "ok" ? "" : " \u2014 run `wairon mcp install --backend gemini --global`"}`);
|
|
37069
37714
|
const projPath = fromProjectRoot(".gemini", "settings.json");
|
|
@@ -37072,7 +37717,7 @@ async function runDoctor(options = {}) {
|
|
|
37072
37717
|
line(tally, hp.mark === "error" ? "error" : "ok", `Gemini CLI (project): ${hp.note} ${import_chalk12.default.gray("(Antigravity ignores this file)")}`);
|
|
37073
37718
|
}
|
|
37074
37719
|
}
|
|
37075
|
-
const pluginDir =
|
|
37720
|
+
const pluginDir = path43.join(os9.homedir(), ".gemini", "config", "plugins", "wairon");
|
|
37076
37721
|
if (fs28.existsSync(pluginDir)) {
|
|
37077
37722
|
line(tally, "warn", `Legacy Antigravity plugin present (${pluginDir}) \u2014 it collides with the wairon MCP server. Remove it with \`wairon doctor --fix\`.`);
|
|
37078
37723
|
}
|
|
@@ -37080,7 +37725,7 @@ async function runDoctor(options = {}) {
|
|
|
37080
37725
|
printSummary(tally);
|
|
37081
37726
|
if (tally.error > 0) process.exit(1);
|
|
37082
37727
|
}
|
|
37083
|
-
async function applyFixes() {
|
|
37728
|
+
async function applyFixes(options, tally) {
|
|
37084
37729
|
if (!projectConfigExists()) return;
|
|
37085
37730
|
let targets;
|
|
37086
37731
|
try {
|
|
@@ -37149,6 +37794,7 @@ async function applyFixes() {
|
|
|
37149
37794
|
} catch (e) {
|
|
37150
37795
|
console.log(` ${icon("error")} Narrative-step repair failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
37151
37796
|
}
|
|
37797
|
+
await migrateChaining(options, tally);
|
|
37152
37798
|
const { runMcpInstall: runMcpInstall2 } = (init_mcp(), __toCommonJS(mcp_exports));
|
|
37153
37799
|
if (targets.includes("claude")) {
|
|
37154
37800
|
try {
|
|
@@ -37172,6 +37818,106 @@ async function applyFixes() {
|
|
|
37172
37818
|
}
|
|
37173
37819
|
logger.blank();
|
|
37174
37820
|
}
|
|
37821
|
+
function reportOnly(options) {
|
|
37822
|
+
if (options.fix) {
|
|
37823
|
+
throw new DoctorOptionsError("--report prints a plan and writes nothing, so it never combines with --fix.");
|
|
37824
|
+
}
|
|
37825
|
+
if (options.report !== "chaining") {
|
|
37826
|
+
throw new DoctorOptionsError(`--report knows one section, \`chaining\`; "${options.report}" is not one.`);
|
|
37827
|
+
}
|
|
37828
|
+
const migration = plan();
|
|
37829
|
+
logger.blank();
|
|
37830
|
+
console.log(`${import_chalk12.default.bold("wairon doctor --report chaining")} ${import_chalk12.default.gray(`\u2014 installed v${WAIRON_VERSION}`)}`);
|
|
37831
|
+
logger.blank();
|
|
37832
|
+
printChainingPlan(migration);
|
|
37833
|
+
console.log(import_chalk12.default.gray("Nothing was written."));
|
|
37834
|
+
logger.blank();
|
|
37835
|
+
}
|
|
37836
|
+
async function migrateChaining(options, tally) {
|
|
37837
|
+
let migration;
|
|
37838
|
+
try {
|
|
37839
|
+
migration = plan();
|
|
37840
|
+
} catch (e) {
|
|
37841
|
+
console.log(` ${icon("error")} Could not plan the chaining migration: ${e instanceof Error ? e.message : String(e)}`);
|
|
37842
|
+
tally.error++;
|
|
37843
|
+
return;
|
|
37844
|
+
}
|
|
37845
|
+
if (isEmpty(migration)) return;
|
|
37846
|
+
printChainingPlan(migration);
|
|
37847
|
+
if (!await confirmChaining(options)) return;
|
|
37848
|
+
try {
|
|
37849
|
+
const applied = apply(migration);
|
|
37850
|
+
printApplied(applied.written, applied.relock);
|
|
37851
|
+
} catch (e) {
|
|
37852
|
+
if (!(e instanceof ChainingMigrationRefusedError)) throw e;
|
|
37853
|
+
console.log(` ${icon("error")} ${e.message}`);
|
|
37854
|
+
tally.error++;
|
|
37855
|
+
}
|
|
37856
|
+
}
|
|
37857
|
+
async function confirmChaining(options) {
|
|
37858
|
+
if (options.yes) return true;
|
|
37859
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
37860
|
+
console.log(` ${icon("warn")} Chaining migration skipped: no terminal to confirm it \u2014 re-run with \`--fix --yes\` to apply it. Nothing of it was written.`);
|
|
37861
|
+
return false;
|
|
37862
|
+
}
|
|
37863
|
+
const { confirmed } = await import_inquirer4.default.prompt([
|
|
37864
|
+
{ type: "confirm", name: "confirmed", message: "Apply the chaining migration above?", default: false }
|
|
37865
|
+
]);
|
|
37866
|
+
if (!confirmed) console.log(` ${icon("warn")} Chaining migration skipped. Nothing of it was written.`);
|
|
37867
|
+
return confirmed;
|
|
37868
|
+
}
|
|
37869
|
+
function printApplied(written, relock) {
|
|
37870
|
+
console.log(` ${icon("ok")} Applied the chaining migration: ${written.length} file(s) written.`);
|
|
37871
|
+
for (const file of written) console.log(` ${file}`);
|
|
37872
|
+
if (relock.length === 0) return;
|
|
37873
|
+
console.log(` ${icon("warn")} The writes staled the approval of ${relock.length} project(s); nothing was locked here. Re-lock each with \`wairon lock\`:`);
|
|
37874
|
+
for (const dir of relock) console.log(` ${dir}`);
|
|
37875
|
+
}
|
|
37876
|
+
function pendingCount(migration) {
|
|
37877
|
+
return migration.projects.reduce((n, p) => n + (p.idToWrite ? 1 : 0) + p.exports.length + p.externals.length + p.pins.length, 0);
|
|
37878
|
+
}
|
|
37879
|
+
function chainingTotals(migration) {
|
|
37880
|
+
const sum = (f) => migration.projects.reduce((n, p) => n + f(p), 0);
|
|
37881
|
+
const entries = sum((p) => p.exports.length);
|
|
37882
|
+
return [
|
|
37883
|
+
`${sum((p) => p.idToWrite ? 1 : 0)} id(s)`,
|
|
37884
|
+
`${entries} L0 entr${entries === 1 ? "y" : "ies"}`,
|
|
37885
|
+
`${sum((p) => p.externals.length)} external(s)`,
|
|
37886
|
+
`${sum((p) => p.pins.length)} pin(s)`,
|
|
37887
|
+
`${sum((p) => p.supersededPins.length)} superseded pin(s)`,
|
|
37888
|
+
`${migration.findings.length} finding(s)`
|
|
37889
|
+
].join(", ");
|
|
37890
|
+
}
|
|
37891
|
+
function printChainingPlan(migration) {
|
|
37892
|
+
console.log(import_chalk12.default.bold("Chaining migration"));
|
|
37893
|
+
console.log(import_chalk12.default.gray(` family root: ${migration.familyRoot}${migration.whole ? "" : " (partial: a hop above was out of reach)"}`));
|
|
37894
|
+
if (isEmpty(migration)) console.log(" Nothing to migrate.");
|
|
37895
|
+
for (const p of migration.projects) printProjectMigration(p);
|
|
37896
|
+
for (const f of migration.findings) {
|
|
37897
|
+
const where = f.project === "" ? "top root" : f.project;
|
|
37898
|
+
console.log(` ${icon(f.blocking ? "error" : "warn")} ${f.kind} [${where}]${f.blocking ? " (blocks apply)" : ""}: ${f.detail}`);
|
|
37899
|
+
}
|
|
37900
|
+
console.log(` Totals: ${chainingTotals(migration)}.`);
|
|
37901
|
+
logger.blank();
|
|
37902
|
+
}
|
|
37903
|
+
function printProjectMigration(p) {
|
|
37904
|
+
console.log(` ${import_chalk12.default.bold(p.project === "" ? "(top root)" : p.project)} ${import_chalk12.default.gray(p.directory)}`);
|
|
37905
|
+
if (p.idToWrite) console.log(` id: declare "${p.idToWrite}"`);
|
|
37906
|
+
for (const e of p.exports) {
|
|
37907
|
+
const item = e.component !== void 0 ? `component: ${e.component}` : `typeDef: ${e.typeDef}`;
|
|
37908
|
+
const members = e.members.length > 0 ? `, reaching ${e.members.join(", ")}` : "";
|
|
37909
|
+
const consumers = e.consumers.map((c) => c || "(top root)").join(", ");
|
|
37910
|
+
console.log(` L0 entry: { from: ${e.from}, ${item}, audience: ${e.audience} } as "${e.publicName}" \u2014 for ${consumers}${members}`);
|
|
37911
|
+
}
|
|
37912
|
+
for (const x of p.externals) {
|
|
37913
|
+
const why = x.reason === "legacy-pin" ? "replaces the stage-1 family pin of" : "its references cross into";
|
|
37914
|
+
console.log(` external: ${x.alias}: {} \u2014 ${why} ${x.producer || "(top root)"}`);
|
|
37915
|
+
}
|
|
37916
|
+
if (p.pins.length > 0) console.log(` pin: ${p.pins.join(", ")}`);
|
|
37917
|
+
for (const key of p.supersededPins) {
|
|
37918
|
+
console.log(` superseded sibling pin: ${key} \u2014 left on disk until stage 3 (stage-1 resolution still reads it; nothing deletes it)`);
|
|
37919
|
+
}
|
|
37920
|
+
}
|
|
37175
37921
|
function printSummary(tally) {
|
|
37176
37922
|
if (tally.error === 0 && tally.warn === 0) {
|
|
37177
37923
|
logger.success("All checks passed \u2014 everything is current.");
|
|
@@ -37189,13 +37935,13 @@ function printSummary(tally) {
|
|
|
37189
37935
|
|
|
37190
37936
|
// src/commands/diagram.ts
|
|
37191
37937
|
var fs29 = __toESM(require("fs"));
|
|
37192
|
-
var
|
|
37938
|
+
var path45 = __toESM(require("path"));
|
|
37193
37939
|
init_logger();
|
|
37194
37940
|
init_paths();
|
|
37195
37941
|
init_fs();
|
|
37196
37942
|
|
|
37197
37943
|
// src/commands/subsystem.ts
|
|
37198
|
-
var
|
|
37944
|
+
var path44 = __toESM(require("path"));
|
|
37199
37945
|
init_logger();
|
|
37200
37946
|
init_errors();
|
|
37201
37947
|
init_fs();
|
|
@@ -37230,10 +37976,10 @@ async function runSubsystemAdd(id, options = {}) {
|
|
|
37230
37976
|
const stored = loadSubsystemSpec(id);
|
|
37231
37977
|
const restatement = subsystemAddRestatement(id, options.projectPath, options.name, stored);
|
|
37232
37978
|
const receipt = writeSpec(restatement);
|
|
37233
|
-
const childDir =
|
|
37979
|
+
const childDir = path44.resolve(getProjectRoot(), options.projectPath);
|
|
37234
37980
|
logger.success(`${receipt.replacedExisting ? "Re-authored" : "Added"} external subsystem "${id}" \u2192 ${options.projectPath}`);
|
|
37235
37981
|
for (const notice of receipt.notices) logger.info(notice);
|
|
37236
|
-
logger.info(`Scaffolded child project at ${
|
|
37982
|
+
logger.info(`Scaffolded child project at ${path44.relative(process.cwd(), childDir) || "."}`);
|
|
37237
37983
|
logger.info(`Design its spec tree from this parent using namespaced ids (e.g. ${id}::<component>).`);
|
|
37238
37984
|
}
|
|
37239
37985
|
async function runSubsystemMove(id, options = {}) {
|
|
@@ -37256,9 +38002,9 @@ async function runSubsystemExternalize(id, options = {}) {
|
|
|
37256
38002
|
throw new WaironError("--project-path (the subproject destination) is required.");
|
|
37257
38003
|
}
|
|
37258
38004
|
externalizeSubsystem(id, options.projectPath);
|
|
37259
|
-
const childDir =
|
|
38005
|
+
const childDir = path44.resolve(getProjectRoot(), options.projectPath);
|
|
37260
38006
|
logger.success(`Externalized subsystem "${id}" \u2192 ${options.projectPath}`);
|
|
37261
|
-
logger.info(`Moved its specs into ${
|
|
38007
|
+
logger.info(`Moved its specs into ${path44.relative(process.cwd(), childDir) || "."} (now a standalone subproject).`);
|
|
37262
38008
|
logger.info("Move the source code there yourself, then run `wairon validate` to confirm the tree.");
|
|
37263
38009
|
}
|
|
37264
38010
|
async function runSubsystemInternalize(id) {
|
|
@@ -37289,7 +38035,7 @@ function applyFormat(options) {
|
|
|
37289
38035
|
};
|
|
37290
38036
|
}
|
|
37291
38037
|
function writeArtifact(dest, content) {
|
|
37292
|
-
ensureDir(
|
|
38038
|
+
ensureDir(path45.dirname(path45.resolve(dest)));
|
|
37293
38039
|
fs29.writeFileSync(dest, content, "utf-8");
|
|
37294
38040
|
}
|
|
37295
38041
|
function parseSequenceRef(ref) {
|
|
@@ -37305,21 +38051,21 @@ async function runDiagram(rawOptions = {}) {
|
|
|
37305
38051
|
assertProjectInitialized();
|
|
37306
38052
|
const options = applyFormat(rawOptions);
|
|
37307
38053
|
if (options.canvas && !options.all) {
|
|
37308
|
-
const dest2 = options.out ??
|
|
38054
|
+
const dest2 = options.out ?? path45.join(AI_PATHS.docsDir(), "diagrams", "canvas.html");
|
|
37309
38055
|
writeArtifact(dest2, renderDiagram("canvas"));
|
|
37310
38056
|
logger.success(`Interactive canvas written to ${dest2}`);
|
|
37311
38057
|
logger.info("Open it in a browser \u2014 fully self-contained (works offline).");
|
|
37312
38058
|
return;
|
|
37313
38059
|
}
|
|
37314
38060
|
if (options.drawio && !options.all) {
|
|
37315
|
-
const dest2 = options.out ??
|
|
38061
|
+
const dest2 = options.out ?? path45.join(AI_PATHS.docsDir(), "diagrams", "architecture.drawio");
|
|
37316
38062
|
writeArtifact(dest2, renderDiagram("drawio"));
|
|
37317
38063
|
logger.success(`draw.io diagram written to ${dest2}`);
|
|
37318
38064
|
logger.info("Open with draw.io / diagrams.net (or import into tools that accept the format).");
|
|
37319
38065
|
return;
|
|
37320
38066
|
}
|
|
37321
38067
|
if (options.excalidraw && !options.all) {
|
|
37322
|
-
const dest2 = options.out ??
|
|
38068
|
+
const dest2 = options.out ?? path45.join(AI_PATHS.docsDir(), "diagrams", "architecture.excalidraw");
|
|
37323
38069
|
writeArtifact(dest2, renderDiagram("excalidraw"));
|
|
37324
38070
|
logger.success(`Excalidraw scene written to ${dest2}`);
|
|
37325
38071
|
logger.info("Open with excalidraw.com or the VS Code extension.");
|
|
@@ -37327,27 +38073,27 @@ async function runDiagram(rawOptions = {}) {
|
|
|
37327
38073
|
}
|
|
37328
38074
|
const wantsMermaid = options.format?.toLowerCase().startsWith("mermaid") || !!options.subsystem || !!options.sequence;
|
|
37329
38075
|
if (!options.all && !options.sequence && !wantsMermaid) {
|
|
37330
|
-
const dest2 = options.out ??
|
|
38076
|
+
const dest2 = options.out ?? path45.join(AI_PATHS.docsDir(), "diagrams", "canvas.html");
|
|
37331
38077
|
writeArtifact(dest2, renderDiagram("canvas"));
|
|
37332
38078
|
logger.success(`Interactive canvas written to ${dest2}`);
|
|
37333
38079
|
logger.info("Open it in a browser \u2014 fully self-contained (works offline). Other formats: --format mermaid|drawio|excalidraw.");
|
|
37334
38080
|
return;
|
|
37335
38081
|
}
|
|
37336
38082
|
if (options.all) {
|
|
37337
|
-
const outDir = options.out ??
|
|
38083
|
+
const outDir = options.out ?? path45.join(AI_PATHS.docsDir(), "diagrams");
|
|
37338
38084
|
const files = generateDiagramSet();
|
|
37339
38085
|
if (files.length === 0) {
|
|
37340
38086
|
logger.warn("No diagrams to generate \u2014 the spec tree has no components yet.");
|
|
37341
38087
|
return;
|
|
37342
38088
|
}
|
|
37343
38089
|
for (const file of files) {
|
|
37344
|
-
writeArtifact(
|
|
38090
|
+
writeArtifact(path45.join(outDir, file.relPath), toMarkdown(file));
|
|
37345
38091
|
}
|
|
37346
|
-
writeArtifact(
|
|
37347
|
-
writeArtifact(
|
|
37348
|
-
writeArtifact(
|
|
38092
|
+
writeArtifact(path45.join(outDir, "canvas.html"), renderDiagram("canvas"));
|
|
38093
|
+
writeArtifact(path45.join(outDir, "architecture.drawio"), renderDiagram("drawio"));
|
|
38094
|
+
writeArtifact(path45.join(outDir, "architecture.excalidraw"), renderDiagram("excalidraw"));
|
|
37349
38095
|
const graph2 = loadSpecGraph();
|
|
37350
|
-
const indexPath =
|
|
38096
|
+
const indexPath = path45.join(outDir, "README.md");
|
|
37351
38097
|
writeArtifact(indexPath, diagramSetIndex(files, graph2.systemName));
|
|
37352
38098
|
logger.success(`Generated ${files.length} diagram(s) + interactive canvas.html + index into ${outDir}`);
|
|
37353
38099
|
for (const file of files.slice(0, 12)) {
|
|
@@ -37359,20 +38105,20 @@ async function runDiagram(rawOptions = {}) {
|
|
|
37359
38105
|
let mermaid;
|
|
37360
38106
|
let title;
|
|
37361
38107
|
let defaultDest;
|
|
37362
|
-
const diagramsDir =
|
|
38108
|
+
const diagramsDir = path45.join(AI_PATHS.docsDir(), "diagrams");
|
|
37363
38109
|
if (options.sequence) {
|
|
37364
38110
|
const { component, method: method2 } = parseSequenceRef(options.sequence);
|
|
37365
38111
|
mermaid = generateSequenceDiagram(component, method2, { depth: options.depth });
|
|
37366
38112
|
title = `${component}.${method2} \u2014 narrative sequence`;
|
|
37367
|
-
defaultDest =
|
|
38113
|
+
defaultDest = path45.join(diagramsDir, "sequences", `${component.replace(/::/g, "--")}.${method2}.md`);
|
|
37368
38114
|
} else if (options.subsystem) {
|
|
37369
38115
|
mermaid = generateComponentDiagram({ subsystem: options.subsystem });
|
|
37370
38116
|
title = `${options.subsystem} \u2014 components`;
|
|
37371
|
-
defaultDest =
|
|
38117
|
+
defaultDest = path45.join(diagramsDir, "subsystems", `${options.subsystem.replace(/::/g, "--")}.md`);
|
|
37372
38118
|
} else {
|
|
37373
38119
|
mermaid = renderDiagram("mermaid");
|
|
37374
38120
|
title = "Component architecture";
|
|
37375
|
-
defaultDest =
|
|
38121
|
+
defaultDest = path45.join(diagramsDir, "system.md");
|
|
37376
38122
|
}
|
|
37377
38123
|
const dest = options.out ?? defaultDest;
|
|
37378
38124
|
const content = dest.endsWith(".mmd") ? `${mermaid}
|
|
@@ -37488,7 +38234,7 @@ Component variants (${variants.length})
|
|
|
37488
38234
|
// src/commands/packs.ts
|
|
37489
38235
|
var fs30 = __toESM(require("fs"));
|
|
37490
38236
|
var os10 = __toESM(require("os"));
|
|
37491
|
-
var
|
|
38237
|
+
var path46 = __toESM(require("path"));
|
|
37492
38238
|
var import_chalk16 = __toESM(require("chalk"));
|
|
37493
38239
|
var import_sdk = __toESM(require_dist());
|
|
37494
38240
|
init_logger();
|
|
@@ -37515,7 +38261,7 @@ function describe2(probe2) {
|
|
|
37515
38261
|
return parts.join(", ");
|
|
37516
38262
|
}
|
|
37517
38263
|
function resolveSourceUnit(source) {
|
|
37518
|
-
const abs =
|
|
38264
|
+
const abs = path46.resolve(source);
|
|
37519
38265
|
if (!fs30.existsSync(abs)) {
|
|
37520
38266
|
throw new Error(`Pack source "${source}" does not exist.`);
|
|
37521
38267
|
}
|
|
@@ -37535,7 +38281,7 @@ async function addPack(source, options = {}) {
|
|
|
37535
38281
|
}
|
|
37536
38282
|
const { abs } = resolveSourceUnit(source);
|
|
37537
38283
|
const scope = options.global ? "global" : "project";
|
|
37538
|
-
const probe2 = probePack(abs,
|
|
38284
|
+
const probe2 = probePack(abs, path46.dirname(abs), scope);
|
|
37539
38285
|
if (probe2.error) {
|
|
37540
38286
|
logger.error(probe2.error);
|
|
37541
38287
|
process.exitCode = 1;
|
|
@@ -37543,8 +38289,8 @@ async function addPack(source, options = {}) {
|
|
|
37543
38289
|
}
|
|
37544
38290
|
if (options.global) {
|
|
37545
38291
|
const destDir = globalPacksDir();
|
|
37546
|
-
const dest2 =
|
|
37547
|
-
if (
|
|
38292
|
+
const dest2 = path46.join(destDir, path46.basename(abs));
|
|
38293
|
+
if (path46.resolve(dest2) !== abs) {
|
|
37548
38294
|
fs30.mkdirSync(destDir, { recursive: true });
|
|
37549
38295
|
fs30.cpSync(abs, dest2, { recursive: true, force: true });
|
|
37550
38296
|
}
|
|
@@ -37559,10 +38305,10 @@ async function addPack(source, options = {}) {
|
|
|
37559
38305
|
return;
|
|
37560
38306
|
}
|
|
37561
38307
|
const root = getProjectRoot();
|
|
37562
|
-
const relRef = `.wai/packs/${
|
|
37563
|
-
const dest =
|
|
37564
|
-
if (
|
|
37565
|
-
fs30.mkdirSync(
|
|
38308
|
+
const relRef = `.wai/packs/${path46.basename(abs)}`;
|
|
38309
|
+
const dest = path46.join(root, ".wai", "packs", path46.basename(abs));
|
|
38310
|
+
if (path46.resolve(dest) !== abs) {
|
|
38311
|
+
fs30.mkdirSync(path46.dirname(dest), { recursive: true });
|
|
37566
38312
|
fs30.cpSync(abs, dest, { recursive: true, force: true });
|
|
37567
38313
|
}
|
|
37568
38314
|
if (registerPackRef(relRef)) {
|
|
@@ -37574,7 +38320,7 @@ async function addPack(source, options = {}) {
|
|
|
37574
38320
|
logger.info(`${describe2(probe2)} \u2014 commit .wai/ so CI and every clone enforce it.`);
|
|
37575
38321
|
}
|
|
37576
38322
|
async function addPackFromArchive(source, options) {
|
|
37577
|
-
const abs =
|
|
38323
|
+
const abs = path46.resolve(source);
|
|
37578
38324
|
if (!fs30.existsSync(abs) || !fs30.statSync(abs).isFile()) {
|
|
37579
38325
|
logger.error(`Pack archive "${source}" does not exist.`);
|
|
37580
38326
|
process.exitCode = 1;
|
|
@@ -37590,25 +38336,25 @@ async function addPackFromArchive(source, options) {
|
|
|
37590
38336
|
process.exitCode = 1;
|
|
37591
38337
|
return;
|
|
37592
38338
|
}
|
|
37593
|
-
baseDir =
|
|
38339
|
+
baseDir = path46.join(getProjectRoot(), ".wai", "packs");
|
|
37594
38340
|
}
|
|
37595
38341
|
const bytes = fs30.readFileSync(abs);
|
|
37596
38342
|
fs30.mkdirSync(baseDir, { recursive: true });
|
|
37597
|
-
const staging = fs30.mkdtempSync(
|
|
38343
|
+
const staging = fs30.mkdtempSync(path46.join(baseDir, ".wpack-staging-"));
|
|
37598
38344
|
let result;
|
|
37599
38345
|
try {
|
|
37600
38346
|
result = (0, import_sdk.extractPack)(bytes, staging);
|
|
37601
38347
|
} catch (err) {
|
|
37602
38348
|
fs30.rmSync(staging, { recursive: true, force: true });
|
|
37603
|
-
logger.error(`Failed to extract pack archive "${
|
|
38349
|
+
logger.error(`Failed to extract pack archive "${path46.basename(abs)}": ${err instanceof Error ? err.message : String(err)}`);
|
|
37604
38350
|
process.exitCode = 1;
|
|
37605
38351
|
return;
|
|
37606
38352
|
}
|
|
37607
38353
|
const name = result.name;
|
|
37608
|
-
const destDir =
|
|
38354
|
+
const destDir = path46.join(baseDir, name);
|
|
37609
38355
|
if (fs30.existsSync(destDir)) fs30.rmSync(destDir, { recursive: true, force: true });
|
|
37610
38356
|
fs30.renameSync(staging, destDir);
|
|
37611
|
-
const probe2 = probePack(destDir,
|
|
38357
|
+
const probe2 = probePack(destDir, path46.dirname(destDir), scope);
|
|
37612
38358
|
if (probe2.error) {
|
|
37613
38359
|
fs30.rmSync(destDir, { recursive: true, force: true });
|
|
37614
38360
|
logger.error(probe2.error);
|
|
@@ -37624,7 +38370,7 @@ async function addPackFromArchive(source, options) {
|
|
|
37624
38370
|
if (registerPackRef(relRef)) {
|
|
37625
38371
|
logger.success(`Installed pack "${probe2.name ?? name}" into ${relRef} and registered it in .wai/project.yaml.`);
|
|
37626
38372
|
} else {
|
|
37627
|
-
logger.success(`Pack "${probe2.name ?? name}" already registered \u2014 refreshed ${relRef} from ${
|
|
38373
|
+
logger.success(`Pack "${probe2.name ?? name}" already registered \u2014 refreshed ${relRef} from ${path46.basename(abs)}.`);
|
|
37628
38374
|
}
|
|
37629
38375
|
logger.info(`${describe2(probe2)} \u2014 commit .wai/ so CI and every clone enforce it.`);
|
|
37630
38376
|
}
|
|
@@ -37656,8 +38402,8 @@ function expandSource(source, version) {
|
|
|
37656
38402
|
return source.replace(/\{version\}/g, version ?? "").replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_, name) => process.env[name] ?? "");
|
|
37657
38403
|
}
|
|
37658
38404
|
async function fetchArchive(url) {
|
|
37659
|
-
const dir = fs30.mkdtempSync(
|
|
37660
|
-
const dest =
|
|
38405
|
+
const dir = fs30.mkdtempSync(path46.join(os10.tmpdir(), "wairon-packdl-"));
|
|
38406
|
+
const dest = path46.join(dir, "pack.wpack");
|
|
37661
38407
|
await downloadFile(url, dest);
|
|
37662
38408
|
return dest;
|
|
37663
38409
|
}
|
|
@@ -37676,7 +38422,7 @@ async function installPack(source) {
|
|
|
37676
38422
|
}
|
|
37677
38423
|
const extracted = extractArchiveToTemp(archive);
|
|
37678
38424
|
try {
|
|
37679
|
-
fs30.rmSync(
|
|
38425
|
+
fs30.rmSync(path46.dirname(archive), { recursive: true, force: true });
|
|
37680
38426
|
} catch {
|
|
37681
38427
|
}
|
|
37682
38428
|
if (!extracted) return;
|
|
@@ -37699,7 +38445,7 @@ async function installPack(source) {
|
|
|
37699
38445
|
if (!extracted) return;
|
|
37700
38446
|
sourceDir = extracted.dir;
|
|
37701
38447
|
cleanup = extracted.dir;
|
|
37702
|
-
origin =
|
|
38448
|
+
origin = path46.resolve(source);
|
|
37703
38449
|
} else {
|
|
37704
38450
|
let unit;
|
|
37705
38451
|
try {
|
|
@@ -37742,13 +38488,13 @@ function reportInstalled(installed, origin) {
|
|
|
37742
38488
|
}
|
|
37743
38489
|
}
|
|
37744
38490
|
function extractArchiveToTemp(source) {
|
|
37745
|
-
const abs =
|
|
38491
|
+
const abs = path46.resolve(source);
|
|
37746
38492
|
if (!fs30.existsSync(abs)) {
|
|
37747
38493
|
logger.error(`Pack archive "${source}" does not exist.`);
|
|
37748
38494
|
process.exitCode = 1;
|
|
37749
38495
|
return null;
|
|
37750
38496
|
}
|
|
37751
|
-
const tempDir = fs30.mkdtempSync(
|
|
38497
|
+
const tempDir = fs30.mkdtempSync(path46.join(os10.tmpdir(), "wairon-packinstall-"));
|
|
37752
38498
|
try {
|
|
37753
38499
|
const result = (0, import_sdk.extractPack)(new Uint8Array(fs30.readFileSync(abs)), tempDir);
|
|
37754
38500
|
void result;
|
|
@@ -37857,10 +38603,10 @@ async function syncPacks() {
|
|
|
37857
38603
|
}
|
|
37858
38604
|
let installed = 0;
|
|
37859
38605
|
for (const selection of missing) {
|
|
37860
|
-
const
|
|
38606
|
+
const label3 = packEntryLabel(selection);
|
|
37861
38607
|
const blocker = syncBlocker(selection);
|
|
37862
38608
|
if (blocker) {
|
|
37863
|
-
logger.error(`"${
|
|
38609
|
+
logger.error(`"${label3}" ${blocker}`);
|
|
37864
38610
|
process.exitCode = 1;
|
|
37865
38611
|
continue;
|
|
37866
38612
|
}
|
|
@@ -37871,7 +38617,7 @@ async function syncPacks() {
|
|
|
37871
38617
|
console.log(` ${import_chalk16.default.green("+")} ${pack.name} v${pack.version} ${import_chalk16.default.dim(`\u2190 ${url}`)}`);
|
|
37872
38618
|
installed++;
|
|
37873
38619
|
} catch (e) {
|
|
37874
|
-
logger.error(`Could not sync "${
|
|
38620
|
+
logger.error(`Could not sync "${label3}" from ${url}: ${e instanceof Error ? e.message : String(e)}`);
|
|
37875
38621
|
process.exitCode = 1;
|
|
37876
38622
|
}
|
|
37877
38623
|
}
|
|
@@ -37892,7 +38638,7 @@ async function fetchAndInstall(selection, url) {
|
|
|
37892
38638
|
const archive = await fetchArchive(url);
|
|
37893
38639
|
const extracted = extractArchiveToTemp(archive);
|
|
37894
38640
|
try {
|
|
37895
|
-
fs30.rmSync(
|
|
38641
|
+
fs30.rmSync(path46.dirname(archive), { recursive: true, force: true });
|
|
37896
38642
|
} catch {
|
|
37897
38643
|
}
|
|
37898
38644
|
if (!extracted) return null;
|
|
@@ -37915,9 +38661,9 @@ function bundleTargets(selections, name, all) {
|
|
|
37915
38661
|
return selections.filter((s) => s.bundle === true);
|
|
37916
38662
|
}
|
|
37917
38663
|
function writeBundle(root, resolved) {
|
|
37918
|
-
const dest =
|
|
38664
|
+
const dest = path46.join(root, ".wai", "packs", resolved.name, resolved.version);
|
|
37919
38665
|
fs30.rmSync(dest, { recursive: true, force: true });
|
|
37920
|
-
fs30.mkdirSync(
|
|
38666
|
+
fs30.mkdirSync(path46.dirname(dest), { recursive: true });
|
|
37921
38667
|
fs30.cpSync(resolved.path, dest, { recursive: true });
|
|
37922
38668
|
return dest;
|
|
37923
38669
|
}
|
|
@@ -37949,7 +38695,7 @@ async function bundlePack(name, options = {}) {
|
|
|
37949
38695
|
const dest = writeBundle(root, resolved);
|
|
37950
38696
|
bundledSelections.push({ name: selection.name, version: resolved.version });
|
|
37951
38697
|
bundled.push(`${resolved.name}@${resolved.version}`);
|
|
37952
|
-
console.log(` ${import_chalk16.default.green("+")} ${import_chalk16.default.dim(
|
|
38698
|
+
console.log(` ${import_chalk16.default.green("+")} ${import_chalk16.default.dim(path46.relative(root, dest).replace(/\\/g, "/"))}`);
|
|
37953
38699
|
}
|
|
37954
38700
|
if (bundled.length === 0) return;
|
|
37955
38701
|
markSelectionsBundled(bundledSelections);
|
|
@@ -37986,9 +38732,9 @@ async function listPacks() {
|
|
|
37986
38732
|
console.log(import_chalk16.default.bold.cyan(`\u25A0 Global (${globalPacksDir()})${useGlobal ? "" : import_chalk16.default.yellow(" [disabled: extensions.useGlobalPacks: false]")}`));
|
|
37987
38733
|
if (globalRefs.length === 0) console.log(import_chalk16.default.dim(" (none)"));
|
|
37988
38734
|
for (const ref of globalRefs) {
|
|
37989
|
-
const probe2 = probePack(ref,
|
|
37990
|
-
if (probe2.error) console.log(` ${import_chalk16.default.red("\u2716")} ${
|
|
37991
|
-
else console.log(` ${import_chalk16.default.green("\u25CF")} ${import_chalk16.default.bold(probe2.name ??
|
|
38735
|
+
const probe2 = probePack(ref, path46.dirname(ref), "global");
|
|
38736
|
+
if (probe2.error) console.log(` ${import_chalk16.default.red("\u2716")} ${path46.basename(ref)} \u2014 ${import_chalk16.default.red(probe2.error)}`);
|
|
38737
|
+
else console.log(` ${import_chalk16.default.green("\u25CF")} ${import_chalk16.default.bold(probe2.name ?? path46.basename(ref))} ${import_chalk16.default.dim(describe2(probe2))}`);
|
|
37992
38738
|
}
|
|
37993
38739
|
console.log("");
|
|
37994
38740
|
if (!inProject) {
|
|
@@ -37999,16 +38745,16 @@ async function listPacks() {
|
|
|
37999
38745
|
const projectEntries = config?.extensions?.packs ?? [];
|
|
38000
38746
|
if (projectEntries.length === 0) console.log(import_chalk16.default.dim(" (none)"));
|
|
38001
38747
|
for (const entry of projectEntries) {
|
|
38002
|
-
const
|
|
38748
|
+
const label3 = packEntryLabel(entry);
|
|
38003
38749
|
const ref = packEntryRef(entry, root);
|
|
38004
38750
|
if (!ref) {
|
|
38005
|
-
console.log(` ${import_chalk16.default.red("\u2716")} ${
|
|
38751
|
+
console.log(` ${import_chalk16.default.red("\u2716")} ${label3} \u2014 ${import_chalk16.default.red("declared but not installed or bundled")}`);
|
|
38006
38752
|
continue;
|
|
38007
38753
|
}
|
|
38008
38754
|
const probe2 = probePack(ref, root, "project");
|
|
38009
38755
|
const origin = typeof entry === "string" ? ref : `selected \u2192 ${ref}`;
|
|
38010
|
-
if (probe2.error) console.log(` ${import_chalk16.default.red("\u2716")} ${
|
|
38011
|
-
else console.log(` ${import_chalk16.default.green("\u25CF")} ${import_chalk16.default.bold(probe2.name ??
|
|
38756
|
+
if (probe2.error) console.log(` ${import_chalk16.default.red("\u2716")} ${label3} \u2014 ${import_chalk16.default.red(probe2.error)}`);
|
|
38757
|
+
else console.log(` ${import_chalk16.default.green("\u25CF")} ${import_chalk16.default.bold(probe2.name ?? label3)} ${import_chalk16.default.dim(origin)} ${import_chalk16.default.dim(describe2(probe2))}`);
|
|
38012
38758
|
}
|
|
38013
38759
|
console.log("");
|
|
38014
38760
|
logger.info("Rules from packs show up in `wairon rules list`; add packs with `wairon pack add <source> [--global]`.");
|
|
@@ -38016,8 +38762,8 @@ async function listPacks() {
|
|
|
38016
38762
|
async function removePack(name, options = {}) {
|
|
38017
38763
|
if (options.global) {
|
|
38018
38764
|
for (const ref of discoverPacks(globalPacksDir())) {
|
|
38019
|
-
const probe2 = probePack(ref,
|
|
38020
|
-
if (probe2.name === name ||
|
|
38765
|
+
const probe2 = probePack(ref, path46.dirname(ref), "global");
|
|
38766
|
+
if (probe2.name === name || path46.basename(ref) === name) {
|
|
38021
38767
|
fs30.rmSync(ref, { recursive: true, force: true });
|
|
38022
38768
|
logger.success(`Removed global pack "${probe2.name ?? name}" (${ref}).`);
|
|
38023
38769
|
return;
|
|
@@ -38039,11 +38785,11 @@ async function removePack(name, options = {}) {
|
|
|
38039
38785
|
if (typeof entry !== "string") continue;
|
|
38040
38786
|
const ref = entry;
|
|
38041
38787
|
const probe2 = probePack(ref, root, "project");
|
|
38042
|
-
if (probe2.name === name || ref === name ||
|
|
38788
|
+
if (probe2.name === name || ref === name || path46.basename(ref) === name) {
|
|
38043
38789
|
deregisterPackRef(ref);
|
|
38044
|
-
const resolved =
|
|
38045
|
-
const vendorDir =
|
|
38046
|
-
if (resolved.startsWith(vendorDir +
|
|
38790
|
+
const resolved = path46.resolve(root, ref);
|
|
38791
|
+
const vendorDir = path46.resolve(root, ".wai", "packs");
|
|
38792
|
+
if (resolved.startsWith(vendorDir + path46.sep)) {
|
|
38047
38793
|
fs30.rmSync(resolved, { recursive: true, force: true });
|
|
38048
38794
|
logger.success(`Deregistered pack "${probe2.name ?? name}" and deleted ${ref}.`);
|
|
38049
38795
|
} else {
|
|
@@ -38058,7 +38804,7 @@ async function removePack(name, options = {}) {
|
|
|
38058
38804
|
|
|
38059
38805
|
// src/commands/host.ts
|
|
38060
38806
|
var fs57 = __toESM(require("fs"));
|
|
38061
|
-
var
|
|
38807
|
+
var path73 = __toESM(require("path"));
|
|
38062
38808
|
var os11 = __toESM(require("os"));
|
|
38063
38809
|
var crypto24 = __toESM(require("crypto"));
|
|
38064
38810
|
var import_child_process7 = require("child_process");
|
|
@@ -38087,14 +38833,14 @@ var WEB_SESSION_PREFIX = "ws_";
|
|
|
38087
38833
|
|
|
38088
38834
|
// src/server/credentials.ts
|
|
38089
38835
|
var fs31 = __toESM(require("fs"));
|
|
38090
|
-
var
|
|
38836
|
+
var path47 = __toESM(require("path"));
|
|
38091
38837
|
var crypto7 = __toESM(require("crypto"));
|
|
38092
38838
|
var HASH_NS = "wairon:token:v1";
|
|
38093
38839
|
function hashToken(token) {
|
|
38094
38840
|
return crypto7.createHash("sha256").update(`${HASH_NS}:${token}`).digest("hex");
|
|
38095
38841
|
}
|
|
38096
38842
|
function storePath(dataDir) {
|
|
38097
|
-
return
|
|
38843
|
+
return path47.join(dataDir, "auth", "credentials.json");
|
|
38098
38844
|
}
|
|
38099
38845
|
function load3(dataDir) {
|
|
38100
38846
|
try {
|
|
@@ -38105,7 +38851,7 @@ function load3(dataDir) {
|
|
|
38105
38851
|
}
|
|
38106
38852
|
function save(dataDir, records) {
|
|
38107
38853
|
const p = storePath(dataDir);
|
|
38108
|
-
fs31.mkdirSync(
|
|
38854
|
+
fs31.mkdirSync(path47.dirname(p), { recursive: true });
|
|
38109
38855
|
const tmp = `${p}.tmp`;
|
|
38110
38856
|
fs31.writeFileSync(tmp, JSON.stringify(records, null, 2) + "\n");
|
|
38111
38857
|
fs31.renameSync(tmp, p);
|
|
@@ -38154,10 +38900,10 @@ function listByOwner(dataDir, ownerUserId) {
|
|
|
38154
38900
|
|
|
38155
38901
|
// src/server/websessions.ts
|
|
38156
38902
|
var fs32 = __toESM(require("fs"));
|
|
38157
|
-
var
|
|
38903
|
+
var path48 = __toESM(require("path"));
|
|
38158
38904
|
var crypto8 = __toESM(require("crypto"));
|
|
38159
38905
|
function storePath2(dataDir) {
|
|
38160
|
-
return
|
|
38906
|
+
return path48.join(dataDir, "web-sessions.json");
|
|
38161
38907
|
}
|
|
38162
38908
|
function readSessions(dataDir) {
|
|
38163
38909
|
const p = storePath2(dataDir);
|
|
@@ -38178,7 +38924,7 @@ function readSessions(dataDir) {
|
|
|
38178
38924
|
}
|
|
38179
38925
|
function persistSessions(dataDir, sessions) {
|
|
38180
38926
|
const p = storePath2(dataDir);
|
|
38181
|
-
fs32.mkdirSync(
|
|
38927
|
+
fs32.mkdirSync(path48.dirname(p), { recursive: true });
|
|
38182
38928
|
const tmp = `${p}.tmp`;
|
|
38183
38929
|
fs32.writeFileSync(tmp, JSON.stringify(sessions, null, 2) + "\n");
|
|
38184
38930
|
fs32.renameSync(tmp, p);
|
|
@@ -38343,10 +39089,10 @@ function listWebSessionsBySubject(dataDir, userId) {
|
|
|
38343
39089
|
|
|
38344
39090
|
// src/server/users.ts
|
|
38345
39091
|
var fs33 = __toESM(require("fs"));
|
|
38346
|
-
var
|
|
39092
|
+
var path49 = __toESM(require("path"));
|
|
38347
39093
|
var VALID_STATUSES = ["active", "inactive", "suspended", "deactivated", "disabled"];
|
|
38348
39094
|
function storePath3(dataDir) {
|
|
38349
|
-
return
|
|
39095
|
+
return path49.join(dataDir, "users.json");
|
|
38350
39096
|
}
|
|
38351
39097
|
function loadStore(dataDir) {
|
|
38352
39098
|
const p = storePath3(dataDir);
|
|
@@ -38370,7 +39116,7 @@ function loadStore(dataDir) {
|
|
|
38370
39116
|
}
|
|
38371
39117
|
function replaceAll(dataDir, records) {
|
|
38372
39118
|
const p = storePath3(dataDir);
|
|
38373
|
-
fs33.mkdirSync(
|
|
39119
|
+
fs33.mkdirSync(path49.dirname(p), { recursive: true });
|
|
38374
39120
|
const tmp = `${p}.tmp`;
|
|
38375
39121
|
fs33.writeFileSync(tmp, JSON.stringify(records, null, 2) + "\n");
|
|
38376
39122
|
fs33.renameSync(tmp, p);
|
|
@@ -38476,10 +39222,10 @@ function remapUnitReferences(dataDir, remap, removedScopeIds) {
|
|
|
38476
39222
|
|
|
38477
39223
|
// src/server/instance.ts
|
|
38478
39224
|
var fs34 = __toESM(require("fs"));
|
|
38479
|
-
var
|
|
39225
|
+
var path50 = __toESM(require("path"));
|
|
38480
39226
|
var import_crypto2 = require("crypto");
|
|
38481
39227
|
function storePath4(dataDir) {
|
|
38482
|
-
return
|
|
39228
|
+
return path50.join(dataDir, "instance.json");
|
|
38483
39229
|
}
|
|
38484
39230
|
var InstanceIdentityStore = class {
|
|
38485
39231
|
constructor(dataDir) {
|
|
@@ -38519,7 +39265,7 @@ var InstanceIdentityStore = class {
|
|
|
38519
39265
|
* never truncates the file. Only called by the registry's create-once seed. */
|
|
38520
39266
|
replace(identity) {
|
|
38521
39267
|
const p = storePath4(this.dataDir);
|
|
38522
|
-
fs34.mkdirSync(
|
|
39268
|
+
fs34.mkdirSync(path50.dirname(p), { recursive: true });
|
|
38523
39269
|
const tmp = `${p}.tmp`;
|
|
38524
39270
|
fs34.writeFileSync(tmp, JSON.stringify(identity, null, 2) + "\n");
|
|
38525
39271
|
fs34.renameSync(tmp, p);
|
|
@@ -38579,7 +39325,7 @@ function getInstanceIdentity(dataDir) {
|
|
|
38579
39325
|
|
|
38580
39326
|
// src/utils/secrets.ts
|
|
38581
39327
|
var fs35 = __toESM(require("fs"));
|
|
38582
|
-
var
|
|
39328
|
+
var path51 = __toESM(require("path"));
|
|
38583
39329
|
var ENV_FALLBACK = {
|
|
38584
39330
|
"git-token": ["WAIRON_GIT_TOKEN"],
|
|
38585
39331
|
"notion-token": ["WAIRON_NOTION_TOKEN"],
|
|
@@ -38588,7 +39334,7 @@ var ENV_FALLBACK = {
|
|
|
38588
39334
|
};
|
|
38589
39335
|
function storePath5() {
|
|
38590
39336
|
const dataDir = process.env["WAIRON_DATA_DIR"];
|
|
38591
|
-
return dataDir ?
|
|
39337
|
+
return dataDir ? path51.join(dataDir, "auth", "secrets.json") : null;
|
|
38592
39338
|
}
|
|
38593
39339
|
function readStore() {
|
|
38594
39340
|
const p = storePath5();
|
|
@@ -38619,7 +39365,7 @@ function setSecret(key, value) {
|
|
|
38619
39365
|
if (!p) throw new Error("WAIRON_DATA_DIR is not set \u2014 a running server needs it to store secrets.");
|
|
38620
39366
|
const store = readStore();
|
|
38621
39367
|
store[key] = value;
|
|
38622
|
-
fs35.mkdirSync(
|
|
39368
|
+
fs35.mkdirSync(path51.dirname(p), { recursive: true });
|
|
38623
39369
|
const tmp = `${p}.tmp`;
|
|
38624
39370
|
fs35.writeFileSync(tmp, JSON.stringify(store, null, 2) + "\n");
|
|
38625
39371
|
fs35.renameSync(tmp, p);
|
|
@@ -38831,10 +39577,10 @@ function verifySsoState(state) {
|
|
|
38831
39577
|
|
|
38832
39578
|
// src/server/organization.ts
|
|
38833
39579
|
var fs36 = __toESM(require("fs"));
|
|
38834
|
-
var
|
|
39580
|
+
var path52 = __toESM(require("path"));
|
|
38835
39581
|
var crypto10 = __toESM(require("crypto"));
|
|
38836
39582
|
function storePath6(dataDir) {
|
|
38837
|
-
return
|
|
39583
|
+
return path52.join(dataDir, "organization.json");
|
|
38838
39584
|
}
|
|
38839
39585
|
function readState(dataDir) {
|
|
38840
39586
|
const p = storePath6(dataDir);
|
|
@@ -38857,7 +39603,7 @@ function readState(dataDir) {
|
|
|
38857
39603
|
}
|
|
38858
39604
|
function persistState(dataDir, state) {
|
|
38859
39605
|
const p = storePath6(dataDir);
|
|
38860
|
-
fs36.mkdirSync(
|
|
39606
|
+
fs36.mkdirSync(path52.dirname(p), { recursive: true });
|
|
38861
39607
|
const tmp = `${p}.tmp`;
|
|
38862
39608
|
fs36.writeFileSync(tmp, JSON.stringify(state, null, 2) + "\n");
|
|
38863
39609
|
fs36.renameSync(tmp, p);
|
|
@@ -39237,10 +39983,10 @@ function getOrganizationUnit(dataDir, id) {
|
|
|
39237
39983
|
|
|
39238
39984
|
// src/server/permissions.ts
|
|
39239
39985
|
var fs37 = __toESM(require("fs"));
|
|
39240
|
-
var
|
|
39986
|
+
var path53 = __toESM(require("path"));
|
|
39241
39987
|
var import_crypto3 = require("crypto");
|
|
39242
39988
|
function storePath7(dataDir) {
|
|
39243
|
-
return
|
|
39989
|
+
return path53.join(dataDir, "permissions.json");
|
|
39244
39990
|
}
|
|
39245
39991
|
function assignmentKey(a) {
|
|
39246
39992
|
return [a.subjectKind, a.subjectId ?? "", a.scopeKind, a.scopeId ?? "", a.capability].join("|");
|
|
@@ -39267,7 +40013,7 @@ function load4(dataDir) {
|
|
|
39267
40013
|
}
|
|
39268
40014
|
function replaceAll2(dataDir, assignments) {
|
|
39269
40015
|
const p = storePath7(dataDir);
|
|
39270
|
-
fs37.mkdirSync(
|
|
40016
|
+
fs37.mkdirSync(path53.dirname(p), { recursive: true });
|
|
39271
40017
|
const tmp = `${p}.tmp`;
|
|
39272
40018
|
fs37.writeFileSync(tmp, JSON.stringify(assignments, null, 2) + "\n");
|
|
39273
40019
|
fs37.renameSync(tmp, p);
|
|
@@ -39357,7 +40103,7 @@ function getAssignment(dataDir, assignmentId) {
|
|
|
39357
40103
|
|
|
39358
40104
|
// src/server/roles.ts
|
|
39359
40105
|
var fs38 = __toESM(require("fs"));
|
|
39360
|
-
var
|
|
40106
|
+
var path54 = __toESM(require("path"));
|
|
39361
40107
|
var BUILTIN_ROLES = [
|
|
39362
40108
|
{
|
|
39363
40109
|
id: SSO_ADMIN_ROLE_ID,
|
|
@@ -39375,7 +40121,7 @@ function isBuiltinRoleId(roleId) {
|
|
|
39375
40121
|
return BUILTIN_ROLE_IDS.has(roleId);
|
|
39376
40122
|
}
|
|
39377
40123
|
function storePath8(dataDir) {
|
|
39378
|
-
return
|
|
40124
|
+
return path54.join(dataDir, "roles.json");
|
|
39379
40125
|
}
|
|
39380
40126
|
function load5(dataDir) {
|
|
39381
40127
|
const p = storePath8(dataDir);
|
|
@@ -39399,7 +40145,7 @@ function load5(dataDir) {
|
|
|
39399
40145
|
}
|
|
39400
40146
|
function replaceAll3(dataDir, roles) {
|
|
39401
40147
|
const p = storePath8(dataDir);
|
|
39402
|
-
fs38.mkdirSync(
|
|
40148
|
+
fs38.mkdirSync(path54.dirname(p), { recursive: true });
|
|
39403
40149
|
const tmp = `${p}.tmp`;
|
|
39404
40150
|
fs38.writeFileSync(tmp, JSON.stringify(roles, null, 2) + "\n");
|
|
39405
40151
|
fs38.renameSync(tmp, p);
|
|
@@ -39637,7 +40383,7 @@ function actionableUnitIds(scopes) {
|
|
|
39637
40383
|
|
|
39638
40384
|
// src/server/projects.ts
|
|
39639
40385
|
var fs39 = __toESM(require("fs"));
|
|
39640
|
-
var
|
|
40386
|
+
var path55 = __toESM(require("path"));
|
|
39641
40387
|
init_paths();
|
|
39642
40388
|
init_yaml();
|
|
39643
40389
|
init_fs();
|
|
@@ -39651,7 +40397,7 @@ function isValidProjectId(id) {
|
|
|
39651
40397
|
return typeof id === "string" && ID_RE.test(id);
|
|
39652
40398
|
}
|
|
39653
40399
|
function registryPath(dataDir) {
|
|
39654
|
-
return
|
|
40400
|
+
return path55.join(dataDir, "projects.json");
|
|
39655
40401
|
}
|
|
39656
40402
|
function load6(dataDir) {
|
|
39657
40403
|
try {
|
|
@@ -39662,13 +40408,13 @@ function load6(dataDir) {
|
|
|
39662
40408
|
}
|
|
39663
40409
|
function save2(dataDir, records) {
|
|
39664
40410
|
const p = registryPath(dataDir);
|
|
39665
|
-
fs39.mkdirSync(
|
|
40411
|
+
fs39.mkdirSync(path55.dirname(p), { recursive: true });
|
|
39666
40412
|
const tmp = `${p}.tmp`;
|
|
39667
40413
|
fs39.writeFileSync(tmp, JSON.stringify(records, null, 2) + "\n");
|
|
39668
40414
|
fs39.renameSync(tmp, p);
|
|
39669
40415
|
}
|
|
39670
40416
|
function projectRoot(dataDir, id) {
|
|
39671
|
-
return
|
|
40417
|
+
return path55.join(dataDir, "projects", id);
|
|
39672
40418
|
}
|
|
39673
40419
|
function existingProjectRoot(dataDir, id) {
|
|
39674
40420
|
if (!isValidProjectId(id)) return null;
|
|
@@ -39821,7 +40567,7 @@ function resolveProjectRoot(dataDir, principal, selector) {
|
|
|
39821
40567
|
|
|
39822
40568
|
// src/git/config.ts
|
|
39823
40569
|
var fs40 = __toESM(require("fs"));
|
|
39824
|
-
var
|
|
40570
|
+
var path56 = __toESM(require("path"));
|
|
39825
40571
|
init_fs();
|
|
39826
40572
|
function configPath() {
|
|
39827
40573
|
return aiDir("git.json");
|
|
@@ -39835,7 +40581,7 @@ function readGitConfig() {
|
|
|
39835
40581
|
}
|
|
39836
40582
|
function writeGitConfig(config) {
|
|
39837
40583
|
const p = configPath();
|
|
39838
|
-
fs40.mkdirSync(
|
|
40584
|
+
fs40.mkdirSync(path56.dirname(p), { recursive: true });
|
|
39839
40585
|
const tmp = `${p}.tmp`;
|
|
39840
40586
|
fs40.writeFileSync(tmp, JSON.stringify(config, null, 2) + "\n");
|
|
39841
40587
|
fs40.renameSync(tmp, p);
|
|
@@ -39850,7 +40596,7 @@ function clearGitConfig() {
|
|
|
39850
40596
|
// src/git/adapter.ts
|
|
39851
40597
|
var import_child_process5 = require("child_process");
|
|
39852
40598
|
var fs41 = __toESM(require("fs"));
|
|
39853
|
-
var
|
|
40599
|
+
var path57 = __toESM(require("path"));
|
|
39854
40600
|
init_fs();
|
|
39855
40601
|
function git(args, cwd) {
|
|
39856
40602
|
return (0, import_child_process5.execFileSync)("git", args, {
|
|
@@ -39901,9 +40647,9 @@ function compareUrl(remote, defaultBranch, workingBranch) {
|
|
|
39901
40647
|
return `${web}/compare/${encodeURIComponent(defaultBranch)}...${encodeURIComponent(workingBranch)}`;
|
|
39902
40648
|
}
|
|
39903
40649
|
function excludeLocalFiles() {
|
|
39904
|
-
const excludePath =
|
|
40650
|
+
const excludePath = path57.join(getProjectRoot(), ".git", "info", "exclude");
|
|
39905
40651
|
try {
|
|
39906
|
-
fs41.mkdirSync(
|
|
40652
|
+
fs41.mkdirSync(path57.dirname(excludePath), { recursive: true });
|
|
39907
40653
|
const existing = fs41.existsSync(excludePath) ? fs41.readFileSync(excludePath, "utf8") : "";
|
|
39908
40654
|
const lines = existing.split(/\r?\n/).filter((line2) => line2.length > 0);
|
|
39909
40655
|
const hadLegacyLockExclusion = lines.some((line2) => line2.trim() === ".wai/lock.json");
|
|
@@ -39982,7 +40728,7 @@ function configureSync(periodicSyncMinutes, skipIfClean) {
|
|
|
39982
40728
|
|
|
39983
40729
|
// src/producers/config.ts
|
|
39984
40730
|
var fs42 = __toESM(require("fs"));
|
|
39985
|
-
var
|
|
40731
|
+
var path58 = __toESM(require("path"));
|
|
39986
40732
|
init_fs();
|
|
39987
40733
|
function configPath2() {
|
|
39988
40734
|
return aiDir("producers.json");
|
|
@@ -39996,7 +40742,7 @@ function load7() {
|
|
|
39996
40742
|
}
|
|
39997
40743
|
function save3(configs) {
|
|
39998
40744
|
const p = configPath2();
|
|
39999
|
-
fs42.mkdirSync(
|
|
40745
|
+
fs42.mkdirSync(path58.dirname(p), { recursive: true });
|
|
40000
40746
|
const tmp = `${p}.tmp`;
|
|
40001
40747
|
fs42.writeFileSync(tmp, JSON.stringify(configs, null, 2) + "\n");
|
|
40002
40748
|
fs42.renameSync(tmp, p);
|
|
@@ -40625,8 +41371,8 @@ async function produceProducer(cfg, credential, project2, target) {
|
|
|
40625
41371
|
const configured = runWithProjectRoot(root, () => list()).some((p) => p.target === target);
|
|
40626
41372
|
const token = configured ? resolveSecret(`${target}-token`) : null;
|
|
40627
41373
|
if (configured && !token) {
|
|
40628
|
-
const
|
|
40629
|
-
throw new Error(`No ${
|
|
41374
|
+
const label3 = target.charAt(0).toUpperCase() + target.slice(1);
|
|
41375
|
+
throw new Error(`No ${label3} token \u2014 set WAIRON_${target.toUpperCase()}_TOKEN or run \`wairon host secret set ${target}-token <secret>\`.`);
|
|
40630
41376
|
}
|
|
40631
41377
|
await runWithProjectRoot(root, () => produce(target, diagramUrl, token ?? ""));
|
|
40632
41378
|
}
|
|
@@ -40686,7 +41432,7 @@ function diagramViewLink(cfg, credential, project2) {
|
|
|
40686
41432
|
|
|
40687
41433
|
// src/server/packs.ts
|
|
40688
41434
|
var fs43 = __toESM(require("fs"));
|
|
40689
|
-
var
|
|
41435
|
+
var path59 = __toESM(require("path"));
|
|
40690
41436
|
init_fs();
|
|
40691
41437
|
init_yaml();
|
|
40692
41438
|
|
|
@@ -40742,7 +41488,7 @@ function assertNotCodeArchive(info) {
|
|
|
40742
41488
|
function extractDeclarativeArchive(archive, destDir) {
|
|
40743
41489
|
const result = extractArchive(archive, destDir, HOSTED_STRICT_LIMITS);
|
|
40744
41490
|
try {
|
|
40745
|
-
assertDeclarative(fs43.readFileSync(
|
|
41491
|
+
assertDeclarative(fs43.readFileSync(path59.join(result.directory, result.entryPath), "utf8"));
|
|
40746
41492
|
} catch (e) {
|
|
40747
41493
|
fs43.rmSync(destDir, { recursive: true, force: true });
|
|
40748
41494
|
throw e;
|
|
@@ -40751,10 +41497,10 @@ function extractDeclarativeArchive(archive, destDir) {
|
|
|
40751
41497
|
function probe(loadRef, baseRoot, scope, displayRef) {
|
|
40752
41498
|
const loaded = loadExtensionPacks([{ ref: loadRef, scope }], baseRoot);
|
|
40753
41499
|
if (loaded.errors.length) {
|
|
40754
|
-
return { name:
|
|
41500
|
+
return { name: path59.basename(displayRef), scope, ref: displayRef, profiles: 0, languages: 0, rules: 0, error: loaded.errors[0] };
|
|
40755
41501
|
}
|
|
40756
41502
|
return {
|
|
40757
|
-
name: loaded.packNames[0] ??
|
|
41503
|
+
name: loaded.packNames[0] ?? path59.basename(displayRef),
|
|
40758
41504
|
scope,
|
|
40759
41505
|
ref: displayRef,
|
|
40760
41506
|
profiles: Object.keys(loaded.profiles).length,
|
|
@@ -40768,20 +41514,20 @@ function probe(loadRef, baseRoot, scope, displayRef) {
|
|
|
40768
41514
|
};
|
|
40769
41515
|
}
|
|
40770
41516
|
function writeFileAtomic(file, content) {
|
|
40771
|
-
fs43.mkdirSync(
|
|
41517
|
+
fs43.mkdirSync(path59.dirname(file), { recursive: true });
|
|
40772
41518
|
const tmp = `${file}.tmp`;
|
|
40773
41519
|
fs43.writeFileSync(tmp, content);
|
|
40774
41520
|
fs43.renameSync(tmp, file);
|
|
40775
41521
|
}
|
|
40776
41522
|
function stem(ref) {
|
|
40777
|
-
return
|
|
41523
|
+
return path59.basename(ref).replace(PACK_EXT_RE2, "");
|
|
40778
41524
|
}
|
|
40779
41525
|
function imagePacksDir() {
|
|
40780
41526
|
return process.env.WAIRON_IMAGE_PACKS_DIR ?? "/opt/wairon/packs";
|
|
40781
41527
|
}
|
|
40782
41528
|
function probeTier(dir, tier) {
|
|
40783
41529
|
return discoverPacks(dir).map((full) => {
|
|
40784
|
-
const d = probe(full,
|
|
41530
|
+
const d = probe(full, path59.dirname(full), "global", path59.basename(full));
|
|
40785
41531
|
d.tier = tier;
|
|
40786
41532
|
return d;
|
|
40787
41533
|
});
|
|
@@ -40799,9 +41545,9 @@ function scanGlobalPackProfiles() {
|
|
|
40799
41545
|
for (const dir of [globalPacksDir(), imagePacksDir()]) {
|
|
40800
41546
|
for (const full of discoverPacks(dir)) {
|
|
40801
41547
|
try {
|
|
40802
|
-
const loaded = loadExtensionPacks([{ ref: full, scope: "global" }],
|
|
41548
|
+
const loaded = loadExtensionPacks([{ ref: full, scope: "global" }], path59.dirname(full));
|
|
40803
41549
|
if (loaded.errors.length) continue;
|
|
40804
|
-
const source = loaded.packNames[0] ??
|
|
41550
|
+
const source = loaded.packNames[0] ?? path59.basename(full);
|
|
40805
41551
|
for (const [id, def] of Object.entries(loaded.profiles)) out.push({ id, source, family: def.family });
|
|
40806
41552
|
} catch {
|
|
40807
41553
|
}
|
|
@@ -40857,7 +41603,7 @@ function readPackContent(full) {
|
|
|
40857
41603
|
if (st.isFile()) return fs43.readFileSync(full, "utf8");
|
|
40858
41604
|
if (st.isDirectory()) {
|
|
40859
41605
|
for (const entry of ["pack.yaml", "pack.yml"]) {
|
|
40860
|
-
const p =
|
|
41606
|
+
const p = path59.join(full, entry);
|
|
40861
41607
|
if (fs43.existsSync(p) && fs43.statSync(p).isFile()) return fs43.readFileSync(p, "utf8");
|
|
40862
41608
|
}
|
|
40863
41609
|
}
|
|
@@ -40867,9 +41613,9 @@ function storeResolveGlobalPacks(names) {
|
|
|
40867
41613
|
const index = /* @__PURE__ */ new Map();
|
|
40868
41614
|
const indexTier = (dir, tier) => {
|
|
40869
41615
|
for (const full of discoverPacks(dir)) {
|
|
40870
|
-
const manifestName = probe(full,
|
|
41616
|
+
const manifestName = probe(full, path59.dirname(full), "global", path59.basename(full)).name;
|
|
40871
41617
|
const candidate = { full, manifestName, tier };
|
|
40872
|
-
for (const key of [manifestName, stem(full),
|
|
41618
|
+
for (const key of [manifestName, stem(full), path59.basename(full)]) {
|
|
40873
41619
|
if (!index.has(key)) index.set(key, candidate);
|
|
40874
41620
|
}
|
|
40875
41621
|
}
|
|
@@ -40896,7 +41642,7 @@ function storeInstallGlobalPack(name, content) {
|
|
|
40896
41642
|
assertName(name);
|
|
40897
41643
|
assertDeclarative(content);
|
|
40898
41644
|
const dir = globalPacksDir();
|
|
40899
|
-
const file =
|
|
41645
|
+
const file = path59.join(dir, `${name}.yaml`);
|
|
40900
41646
|
writeFileAtomic(file, content);
|
|
40901
41647
|
const descriptor = probe(file, dir, "global", `${name}.yaml`);
|
|
40902
41648
|
descriptor.tier = "instance";
|
|
@@ -40907,7 +41653,7 @@ function storeInstallGlobalPackArchive(archive, name) {
|
|
|
40907
41653
|
assertNotCodeArchive(info);
|
|
40908
41654
|
const packName = name ?? info.name;
|
|
40909
41655
|
assertName(packName);
|
|
40910
|
-
const dir =
|
|
41656
|
+
const dir = path59.join(globalPacksDir(), packName);
|
|
40911
41657
|
extractDeclarativeArchive(archive, dir);
|
|
40912
41658
|
const descriptor = probe(dir, globalPacksDir(), "global", packName);
|
|
40913
41659
|
descriptor.tier = "instance";
|
|
@@ -40918,7 +41664,7 @@ function declaredName2(loadRef, baseRoot, scope) {
|
|
|
40918
41664
|
return d.error ? void 0 : d.name;
|
|
40919
41665
|
}
|
|
40920
41666
|
function pickByName(candidates, name, fileOf, manifestOf) {
|
|
40921
|
-
const byFile = candidates.find((c) => stem(fileOf(c)) === name ||
|
|
41667
|
+
const byFile = candidates.find((c) => stem(fileOf(c)) === name || path59.basename(fileOf(c)) === name);
|
|
40922
41668
|
if (byFile !== void 0) return byFile;
|
|
40923
41669
|
const byManifest = candidates.filter((c) => manifestOf(c) === name);
|
|
40924
41670
|
if (byManifest.length > 1) {
|
|
@@ -40931,11 +41677,11 @@ function pickByName(candidates, name, fileOf, manifestOf) {
|
|
|
40931
41677
|
function storeRemoveGlobalPack(name) {
|
|
40932
41678
|
assertName(name);
|
|
40933
41679
|
const dir = globalPacksDir();
|
|
40934
|
-
const manifestOf = (ref) => declaredName2(ref,
|
|
40935
|
-
const match = pickByName(discoverPacks(dir), name,
|
|
41680
|
+
const manifestOf = (ref) => declaredName2(ref, path59.dirname(ref), "global");
|
|
41681
|
+
const match = pickByName(discoverPacks(dir), name, path59.basename, manifestOf);
|
|
40936
41682
|
if (!match) {
|
|
40937
41683
|
const inImage = discoverPacks(imagePacksDir()).some(
|
|
40938
|
-
(ref) => stem(ref) === name ||
|
|
41684
|
+
(ref) => stem(ref) === name || path59.basename(ref) === name || manifestOf(ref) === name
|
|
40939
41685
|
);
|
|
40940
41686
|
throw new Error(
|
|
40941
41687
|
inImage ? `Pack "${name}" is an immutable image-layer pack (WAIRON_IMAGE_PACKS_DIR) and cannot be removed at runtime; rebuild the extension image without it.` : `No server-global instance pack named "${name}".`
|
|
@@ -40947,9 +41693,9 @@ function storeListProjectPacks(config) {
|
|
|
40947
41693
|
const root = getProjectRoot();
|
|
40948
41694
|
const entries = config?.extensions?.packs ?? [];
|
|
40949
41695
|
return entries.map((entry) => {
|
|
40950
|
-
const
|
|
41696
|
+
const label3 = packEntryLabel(entry);
|
|
40951
41697
|
const ref = packEntryRef(entry, root);
|
|
40952
|
-
return probe(ref ??
|
|
41698
|
+
return probe(ref ?? label3, root, "project", label3);
|
|
40953
41699
|
});
|
|
40954
41700
|
}
|
|
40955
41701
|
function storeInstallProjectPack(name, content) {
|
|
@@ -40957,7 +41703,7 @@ function storeInstallProjectPack(name, content) {
|
|
|
40957
41703
|
assertDeclarative(content);
|
|
40958
41704
|
const root = getProjectRoot();
|
|
40959
41705
|
const relRef = `.wai/packs/${name}.yaml`;
|
|
40960
|
-
writeFileAtomic(
|
|
41706
|
+
writeFileAtomic(path59.join(root, ".wai", "packs", `${name}.yaml`), content);
|
|
40961
41707
|
return probe(relRef, root, "project", relRef);
|
|
40962
41708
|
}
|
|
40963
41709
|
function storeInstallProjectPackArchive(archive, name) {
|
|
@@ -40967,15 +41713,15 @@ function storeInstallProjectPackArchive(archive, name) {
|
|
|
40967
41713
|
assertName(packName);
|
|
40968
41714
|
const root = getProjectRoot();
|
|
40969
41715
|
const relRef = `.wai/packs/${packName}`;
|
|
40970
|
-
extractDeclarativeArchive(archive,
|
|
41716
|
+
extractDeclarativeArchive(archive, path59.join(root, ".wai", "packs", packName));
|
|
40971
41717
|
return probe(relRef, root, "project", relRef);
|
|
40972
41718
|
}
|
|
40973
41719
|
function storeRemoveProjectPack(name, ref) {
|
|
40974
41720
|
assertName(name);
|
|
40975
41721
|
const root = getProjectRoot();
|
|
40976
|
-
const resolved =
|
|
40977
|
-
const vendorDir =
|
|
40978
|
-
if (resolved.startsWith(vendorDir +
|
|
41722
|
+
const resolved = path59.resolve(root, ref ?? path59.join(".wai", "packs", name));
|
|
41723
|
+
const vendorDir = path59.resolve(root, ".wai", "packs");
|
|
41724
|
+
if (resolved.startsWith(vendorDir + path59.sep)) {
|
|
40979
41725
|
fs43.rmSync(resolved, { recursive: true, force: true });
|
|
40980
41726
|
}
|
|
40981
41727
|
}
|
|
@@ -40998,7 +41744,7 @@ function boundProject2(cfg, project2) {
|
|
|
40998
41744
|
function findPackRegistration(config, name) {
|
|
40999
41745
|
const relRef = `.wai/packs/${name}.yaml`;
|
|
41000
41746
|
const entries = config?.extensions?.packs ?? [];
|
|
41001
|
-
const direct = entries.find((entry) => typeof entry === "string" ? entry === relRef || stem(entry) === name ||
|
|
41747
|
+
const direct = entries.find((entry) => typeof entry === "string" ? entry === relRef || stem(entry) === name || path59.basename(entry) === name : entry.name === name);
|
|
41002
41748
|
if (direct !== void 0) return direct;
|
|
41003
41749
|
const root = getProjectRoot();
|
|
41004
41750
|
const refs = entries.filter((entry) => typeof entry === "string");
|
|
@@ -41113,7 +41859,7 @@ function installProjectPackArchive(cfg, credential, project2, archive, name) {
|
|
|
41113
41859
|
|
|
41114
41860
|
// src/server/audit.ts
|
|
41115
41861
|
var fs44 = __toESM(require("fs"));
|
|
41116
|
-
var
|
|
41862
|
+
var path60 = __toESM(require("path"));
|
|
41117
41863
|
var crypto12 = __toESM(require("crypto"));
|
|
41118
41864
|
var LEVEL_ORDER = {
|
|
41119
41865
|
debug: 0,
|
|
@@ -41136,7 +41882,7 @@ var DEFAULT_AUDIT_POLICY = {
|
|
|
41136
41882
|
metadataMode: "redacted"
|
|
41137
41883
|
};
|
|
41138
41884
|
function storePath9(dataDir) {
|
|
41139
|
-
return
|
|
41885
|
+
return path60.join(dataDir, "audit-events.json");
|
|
41140
41886
|
}
|
|
41141
41887
|
function readEvents(dataDir) {
|
|
41142
41888
|
const p = storePath9(dataDir);
|
|
@@ -41157,7 +41903,7 @@ function readEvents(dataDir) {
|
|
|
41157
41903
|
}
|
|
41158
41904
|
function persistEvents(dataDir, events) {
|
|
41159
41905
|
const p = storePath9(dataDir);
|
|
41160
|
-
fs44.mkdirSync(
|
|
41906
|
+
fs44.mkdirSync(path60.dirname(p), { recursive: true });
|
|
41161
41907
|
const tmp = `${p}.tmp`;
|
|
41162
41908
|
fs44.writeFileSync(tmp, JSON.stringify(events, null, 2) + "\n");
|
|
41163
41909
|
fs44.renameSync(tmp, p);
|
|
@@ -41849,7 +42595,7 @@ function assertAllowedRedirectUri(provider, redirectUri) {
|
|
|
41849
42595
|
|
|
41850
42596
|
// src/server/policy.ts
|
|
41851
42597
|
var fs45 = __toESM(require("fs"));
|
|
41852
|
-
var
|
|
42598
|
+
var path61 = __toESM(require("path"));
|
|
41853
42599
|
init_fs();
|
|
41854
42600
|
|
|
41855
42601
|
// src/server/httpio.ts
|
|
@@ -41866,7 +42612,7 @@ function sendJson(res, status2, body) {
|
|
|
41866
42612
|
|
|
41867
42613
|
// src/server/policy.ts
|
|
41868
42614
|
function packPolicyPath(dataDir) {
|
|
41869
|
-
return
|
|
42615
|
+
return path61.join(dataDir, "pack-policy.json");
|
|
41870
42616
|
}
|
|
41871
42617
|
function getPackPolicyRecord(dataDir) {
|
|
41872
42618
|
const p = packPolicyPath(dataDir);
|
|
@@ -41886,14 +42632,14 @@ function getPackPolicyRecord(dataDir) {
|
|
|
41886
42632
|
function setPackPolicyRecord(dataDir, policy) {
|
|
41887
42633
|
const stored = { ...policy, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
41888
42634
|
const p = packPolicyPath(dataDir);
|
|
41889
|
-
fs45.mkdirSync(
|
|
42635
|
+
fs45.mkdirSync(path61.dirname(p), { recursive: true });
|
|
41890
42636
|
const tmp = `${p}.tmp`;
|
|
41891
42637
|
fs45.writeFileSync(tmp, JSON.stringify(stored, null, 2) + "\n");
|
|
41892
42638
|
fs45.renameSync(tmp, p);
|
|
41893
42639
|
return stored;
|
|
41894
42640
|
}
|
|
41895
42641
|
function exposurePolicyPath(dataDir) {
|
|
41896
|
-
return
|
|
42642
|
+
return path61.join(dataDir, "exposure-policy.json");
|
|
41897
42643
|
}
|
|
41898
42644
|
var COMPATIBLE_DEFAULT_EXPOSURE = {
|
|
41899
42645
|
adminApiMode: "local_only",
|
|
@@ -41923,7 +42669,7 @@ function getExposurePolicyRecord(dataDir) {
|
|
|
41923
42669
|
}
|
|
41924
42670
|
function setExposurePolicyRecord(dataDir, policy) {
|
|
41925
42671
|
const p = exposurePolicyPath(dataDir);
|
|
41926
|
-
fs45.mkdirSync(
|
|
42672
|
+
fs45.mkdirSync(path61.dirname(p), { recursive: true });
|
|
41927
42673
|
const tmp = `${p}.tmp`;
|
|
41928
42674
|
fs45.writeFileSync(tmp, JSON.stringify(policy, null, 2) + "\n");
|
|
41929
42675
|
fs45.renameSync(tmp, p);
|
|
@@ -41944,7 +42690,7 @@ function effectivePolicy(dataDir) {
|
|
|
41944
42690
|
return getPackPolicyRecord(dataDir) ?? PERMISSIVE_DEFAULT_POLICY;
|
|
41945
42691
|
}
|
|
41946
42692
|
function identityProvidersPath(dataDir) {
|
|
41947
|
-
return
|
|
42693
|
+
return path61.join(dataDir, "identity-providers.json");
|
|
41948
42694
|
}
|
|
41949
42695
|
function sanitizeIdentityProvider(config) {
|
|
41950
42696
|
const clean = {
|
|
@@ -41968,7 +42714,7 @@ function sanitizeIdentityProvider(config) {
|
|
|
41968
42714
|
}
|
|
41969
42715
|
function writeIdentityProviderRecords(dataDir, records) {
|
|
41970
42716
|
const p = identityProvidersPath(dataDir);
|
|
41971
|
-
fs45.mkdirSync(
|
|
42717
|
+
fs45.mkdirSync(path61.dirname(p), { recursive: true });
|
|
41972
42718
|
const tmp = `${p}.tmp`;
|
|
41973
42719
|
fs45.writeFileSync(tmp, JSON.stringify(records, null, 2) + "\n");
|
|
41974
42720
|
fs45.renameSync(tmp, p);
|
|
@@ -42171,8 +42917,8 @@ function buildEvaluation(input) {
|
|
|
42171
42917
|
missingPackNames = requiredDefaultNames(policy).filter((n) => !present.has(n));
|
|
42172
42918
|
unresolvedPacks = [];
|
|
42173
42919
|
}
|
|
42174
|
-
const
|
|
42175
|
-
const blockedPackNames = presentPackNames.filter((n) =>
|
|
42920
|
+
const blocked2 = new Set(policy.blockedPackNames ?? []);
|
|
42921
|
+
const blockedPackNames = presentPackNames.filter((n) => blocked2.has(n));
|
|
42176
42922
|
const requiredProfileIds = policy.requiredProfileIds ?? [];
|
|
42177
42923
|
const selected = new Set(selectedProfileIds);
|
|
42178
42924
|
const missingProfileIds = requiredProfileIds.filter((id) => !selected.has(id));
|
|
@@ -43014,10 +43760,10 @@ init_fs();
|
|
|
43014
43760
|
|
|
43015
43761
|
// src/server/relations.ts
|
|
43016
43762
|
var fs46 = __toESM(require("fs"));
|
|
43017
|
-
var
|
|
43763
|
+
var path62 = __toESM(require("path"));
|
|
43018
43764
|
var crypto15 = __toESM(require("crypto"));
|
|
43019
43765
|
function storePath10(dataDir) {
|
|
43020
|
-
return
|
|
43766
|
+
return path62.join(dataDir, "relations.json");
|
|
43021
43767
|
}
|
|
43022
43768
|
function readRelations(dataDir) {
|
|
43023
43769
|
const p = storePath10(dataDir);
|
|
@@ -43038,7 +43784,7 @@ function readRelations(dataDir) {
|
|
|
43038
43784
|
}
|
|
43039
43785
|
function persistRelations(dataDir, relations) {
|
|
43040
43786
|
const p = storePath10(dataDir);
|
|
43041
|
-
fs46.mkdirSync(
|
|
43787
|
+
fs46.mkdirSync(path62.dirname(p), { recursive: true });
|
|
43042
43788
|
const tmp = `${p}.tmp`;
|
|
43043
43789
|
fs46.writeFileSync(tmp, JSON.stringify(relations, null, 2) + "\n");
|
|
43044
43790
|
fs46.renameSync(tmp, p);
|
|
@@ -43152,9 +43898,9 @@ function listProjectRelations(dataDir, sourceProjectId, targetProjectId, status2
|
|
|
43152
43898
|
|
|
43153
43899
|
// src/server/surfaces.ts
|
|
43154
43900
|
var fs47 = __toESM(require("fs"));
|
|
43155
|
-
var
|
|
43901
|
+
var path63 = __toESM(require("path"));
|
|
43156
43902
|
function storePath11(dataDir) {
|
|
43157
|
-
return
|
|
43903
|
+
return path63.join(dataDir, "public-surfaces.json");
|
|
43158
43904
|
}
|
|
43159
43905
|
function readSnapshots(dataDir) {
|
|
43160
43906
|
const p = storePath11(dataDir);
|
|
@@ -43175,7 +43921,7 @@ function readSnapshots(dataDir) {
|
|
|
43175
43921
|
}
|
|
43176
43922
|
function persistSnapshots(dataDir, snapshots) {
|
|
43177
43923
|
const p = storePath11(dataDir);
|
|
43178
|
-
fs47.mkdirSync(
|
|
43924
|
+
fs47.mkdirSync(path63.dirname(p), { recursive: true });
|
|
43179
43925
|
const tmp = `${p}.tmp`;
|
|
43180
43926
|
fs47.writeFileSync(tmp, JSON.stringify(snapshots, null, 2) + "\n");
|
|
43181
43927
|
fs47.renameSync(tmp, p);
|
|
@@ -43321,12 +44067,12 @@ function resolveVisibility(observerProjectId, units, placements) {
|
|
|
43321
44067
|
const best = /* @__PURE__ */ new Map();
|
|
43322
44068
|
for (const placement of placements) {
|
|
43323
44069
|
if (placement.projectId === observerProjectId) continue;
|
|
43324
|
-
const
|
|
43325
|
-
if (!
|
|
43326
|
-
const closedOk =
|
|
44070
|
+
const path77 = chainOf(placement.unitId, unitById);
|
|
44071
|
+
if (!path77.length) continue;
|
|
44072
|
+
const closedOk = path77.every((u) => effectivePosture(u, unitById) !== "closed" || observerInside(u.id) || grantedTo(u));
|
|
43327
44073
|
if (!closedOk) continue;
|
|
43328
|
-
const crossTenant = !tenantRoots.has(
|
|
43329
|
-
if (crossTenant && !
|
|
44074
|
+
const crossTenant = !tenantRoots.has(path77[path77.length - 1].id);
|
|
44075
|
+
if (crossTenant && !path77.some(grantedTo)) continue;
|
|
43330
44076
|
if (crossTenant && directUnits.length === 0) continue;
|
|
43331
44077
|
const distance = crossTenant ? "partner" : sameBranch(placement.unitId) ? "department" : "instance";
|
|
43332
44078
|
const existing = best.get(placement.projectId);
|
|
@@ -43946,7 +44692,7 @@ function handleLandscapeRequest(cfg, credential, req, res, body, url) {
|
|
|
43946
44692
|
|
|
43947
44693
|
// src/server/migration.ts
|
|
43948
44694
|
var fs48 = __toESM(require("fs"));
|
|
43949
|
-
var
|
|
44695
|
+
var path64 = __toESM(require("path"));
|
|
43950
44696
|
var LEGACY_CAPABILITY_MAP = {
|
|
43951
44697
|
"mcp:read": "project:read",
|
|
43952
44698
|
"operations:read": "project:read",
|
|
@@ -43984,7 +44730,7 @@ function readRaw(file) {
|
|
|
43984
44730
|
}
|
|
43985
44731
|
}
|
|
43986
44732
|
function writeRaw(file, value) {
|
|
43987
|
-
fs48.mkdirSync(
|
|
44733
|
+
fs48.mkdirSync(path64.dirname(file), { recursive: true });
|
|
43988
44734
|
const tmp = `${file}.tmp`;
|
|
43989
44735
|
fs48.writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n");
|
|
43990
44736
|
fs48.renameSync(tmp, file);
|
|
@@ -44015,19 +44761,19 @@ function seedAssignment(dataDir, existing, subjectId, capability, scope) {
|
|
|
44015
44761
|
existing.push({ subjectId, scopeKind: scope.scopeKind, scopeId: scope.scopeId, capability });
|
|
44016
44762
|
return true;
|
|
44017
44763
|
}
|
|
44018
|
-
function migratePermissionModel(dataDir,
|
|
44764
|
+
function migratePermissionModel(dataDir, apply2) {
|
|
44019
44765
|
const findings = [];
|
|
44020
44766
|
const found = (area, detail) => {
|
|
44021
44767
|
findings.push({ area, detail });
|
|
44022
44768
|
};
|
|
44023
44769
|
const grid = readRaw(
|
|
44024
|
-
|
|
44770
|
+
path64.join(dataDir, "permissions.json")
|
|
44025
44771
|
) ?? [];
|
|
44026
44772
|
if (!getInstanceIdentity(dataDir)) {
|
|
44027
44773
|
found("instance", "instance identity is not seeded \u2014 the built-in admin/dev subjects have no persisted UUIDs");
|
|
44028
|
-
if (
|
|
44774
|
+
if (apply2) ensureInstanceIdentity(dataDir);
|
|
44029
44775
|
}
|
|
44030
|
-
const orgPath =
|
|
44776
|
+
const orgPath = path64.join(dataDir, "organization.json");
|
|
44031
44777
|
const org = readRaw(orgPath);
|
|
44032
44778
|
if (org?.units?.length) {
|
|
44033
44779
|
const units = org.units;
|
|
@@ -44055,14 +44801,14 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44055
44801
|
newIds.set(unit.id, candidate);
|
|
44056
44802
|
if (!unit.slug || unit.slug !== slug) {
|
|
44057
44803
|
found("units", `unit "${unit.id}" gets slug "${slug}"`);
|
|
44058
|
-
if (
|
|
44804
|
+
if (apply2) unit.slug = slug;
|
|
44059
44805
|
}
|
|
44060
44806
|
if (candidate !== unit.id) {
|
|
44061
44807
|
found("units", `unit id "${unit.id}" becomes the qualified path "${candidate}"`);
|
|
44062
44808
|
remap.push({ oldId: unit.id, newId: candidate });
|
|
44063
44809
|
}
|
|
44064
44810
|
}
|
|
44065
|
-
if (
|
|
44811
|
+
if (apply2) {
|
|
44066
44812
|
const lookup2 = new Map(remap.map((r) => [r.oldId, r.newId]));
|
|
44067
44813
|
for (const unit of units) {
|
|
44068
44814
|
unit.id = lookup2.get(unit.id) ?? unit.id;
|
|
@@ -44081,7 +44827,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44081
44827
|
found("units", `${remap.length} unit id(s) would be remapped across placements, exposeTo, assignments, and users`);
|
|
44082
44828
|
}
|
|
44083
44829
|
}
|
|
44084
|
-
const usersPath =
|
|
44830
|
+
const usersPath = path64.join(dataDir, "users.json");
|
|
44085
44831
|
const users = readRaw(usersPath);
|
|
44086
44832
|
if (users) {
|
|
44087
44833
|
let changed = false;
|
|
@@ -44095,7 +44841,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44095
44841
|
}
|
|
44096
44842
|
const subjectId = user.subject?.userId ?? user.id;
|
|
44097
44843
|
found("users", `user "${user.id}": ${user.grants.length} stored grant(s) become assignments for subject "${subjectId}"`);
|
|
44098
|
-
if (
|
|
44844
|
+
if (apply2) {
|
|
44099
44845
|
for (const grant of user.grants) {
|
|
44100
44846
|
const scope = scopeOf(grant);
|
|
44101
44847
|
for (const capability of capabilitiesOf(grant.permissions)) {
|
|
@@ -44106,9 +44852,9 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44106
44852
|
changed = true;
|
|
44107
44853
|
}
|
|
44108
44854
|
}
|
|
44109
|
-
if (
|
|
44855
|
+
if (apply2 && changed) writeRaw(usersPath, users);
|
|
44110
44856
|
}
|
|
44111
|
-
const keysPath =
|
|
44857
|
+
const keysPath = path64.join(dataDir, "auth", "credentials.json");
|
|
44112
44858
|
const keys = readRaw(keysPath);
|
|
44113
44859
|
if (keys) {
|
|
44114
44860
|
let changed = false;
|
|
@@ -44116,7 +44862,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44116
44862
|
if (key.revokedAt) continue;
|
|
44117
44863
|
if (isLegacyBuiltin(key.ownerSubject?.userId)) {
|
|
44118
44864
|
found("keys", `key "${key.id}" is owned by the retired literal "${key.ownerSubject?.userId}" \u2014 revoked; re-mint for the seeded UUID subject`);
|
|
44119
|
-
if (
|
|
44865
|
+
if (apply2) {
|
|
44120
44866
|
key.revokedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
44121
44867
|
changed = true;
|
|
44122
44868
|
}
|
|
@@ -44126,7 +44872,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44126
44872
|
if (legacyGrants?.length) {
|
|
44127
44873
|
const projects = [...new Set(legacyGrants.map((g) => g.orgUnitId || !g.projectId ? "*" : g.projectId))];
|
|
44128
44874
|
found("keys", `key "${key.id}": stored grants become the projects narrowing [${projects.join(", ")}]`);
|
|
44129
|
-
if (
|
|
44875
|
+
if (apply2) {
|
|
44130
44876
|
key.projects = projects.includes("*") ? ["*"] : projects;
|
|
44131
44877
|
delete key.grants;
|
|
44132
44878
|
changed = true;
|
|
@@ -44135,7 +44881,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44135
44881
|
if (!key.ownerSubject) {
|
|
44136
44882
|
const ownerId = `svc-key-${key.id}`;
|
|
44137
44883
|
found("keys", `key "${key.id}" has no owner \u2014 bound to the synthesized service subject "${ownerId}" carrying its legacy authority`);
|
|
44138
|
-
if (
|
|
44884
|
+
if (apply2) {
|
|
44139
44885
|
key.ownerSubject = { userId: ownerId, kind: "service", issuer: "local" };
|
|
44140
44886
|
const caps = [];
|
|
44141
44887
|
if (legacyGrants?.length) {
|
|
@@ -44156,9 +44902,9 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44156
44902
|
}
|
|
44157
44903
|
}
|
|
44158
44904
|
}
|
|
44159
|
-
if (
|
|
44905
|
+
if (apply2 && changed) writeRaw(keysPath, keys);
|
|
44160
44906
|
}
|
|
44161
|
-
const sessionsPath =
|
|
44907
|
+
const sessionsPath = path64.join(dataDir, "web-sessions.json");
|
|
44162
44908
|
const sessions = readRaw(sessionsPath);
|
|
44163
44909
|
if (sessions) {
|
|
44164
44910
|
let changed = false;
|
|
@@ -44166,7 +44912,7 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44166
44912
|
if (isLegacyBuiltin(s.subject?.userId)) {
|
|
44167
44913
|
found("sessions", `session "${s.id}" belongs to the retired literal "${s.subject?.userId}" \u2014 dropped (re-login mints the UUID subject)`);
|
|
44168
44914
|
changed = true;
|
|
44169
|
-
return !
|
|
44915
|
+
return !apply2;
|
|
44170
44916
|
}
|
|
44171
44917
|
return true;
|
|
44172
44918
|
});
|
|
@@ -44174,19 +44920,19 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44174
44920
|
if (!s.grants) continue;
|
|
44175
44921
|
const projects = [...new Set(s.grants.map((g) => g.orgUnitId || !g.projectId ? "*" : g.projectId))];
|
|
44176
44922
|
found("sessions", `session "${s.id}": stored grants become the projects narrowing [${projects.join(", ")}]`);
|
|
44177
|
-
if (
|
|
44923
|
+
if (apply2) {
|
|
44178
44924
|
s.projects = projects.length === 0 || projects.includes("*") ? ["*"] : projects;
|
|
44179
44925
|
delete s.grants;
|
|
44180
44926
|
changed = true;
|
|
44181
44927
|
}
|
|
44182
44928
|
}
|
|
44183
|
-
if (
|
|
44929
|
+
if (apply2 && changed) writeRaw(sessionsPath, kept);
|
|
44184
44930
|
}
|
|
44185
44931
|
const placedIds = new Set(listProjectPlacements(dataDir).map((p) => p.projectId));
|
|
44186
44932
|
const unplaced = listProjectRecords(dataDir).filter((r) => !placedIds.has(r.id));
|
|
44187
44933
|
if (unplaced.length > 0) {
|
|
44188
44934
|
found("projects", `${unplaced.length} project(s) are placed in no organization unit: ${unplaced.map((r) => r.id).join(", ")} \u2014 placed into the 'unassigned' root unit`);
|
|
44189
|
-
if (
|
|
44935
|
+
if (apply2) {
|
|
44190
44936
|
const system = { userId: "migration", kind: "service", issuer: "local" };
|
|
44191
44937
|
if (!getOrganizationUnit(dataDir, "unassigned")) {
|
|
44192
44938
|
createUnit(dataDir, {
|
|
@@ -44228,17 +44974,17 @@ function migratePermissionModel(dataDir, apply) {
|
|
|
44228
44974
|
"placements",
|
|
44229
44975
|
`project "${projectId}" carries ${rows.length} owner placements \u2014 keeping the newest (${sorted[0].unitId}), removing ${stale.map((p) => p.unitId).join(", ")}`
|
|
44230
44976
|
);
|
|
44231
|
-
if (
|
|
44977
|
+
if (apply2) {
|
|
44232
44978
|
for (const p of stale) deletePlacement(dataDir, p.id);
|
|
44233
44979
|
}
|
|
44234
44980
|
}
|
|
44235
|
-
return { findings, applied:
|
|
44981
|
+
return { findings, applied: apply2 };
|
|
44236
44982
|
}
|
|
44237
44983
|
|
|
44238
44984
|
// src/server/http.ts
|
|
44239
44985
|
var http2 = __toESM(require("http"));
|
|
44240
44986
|
var fs56 = __toESM(require("fs"));
|
|
44241
|
-
var
|
|
44987
|
+
var path72 = __toESM(require("path"));
|
|
44242
44988
|
|
|
44243
44989
|
// src/server/request.ts
|
|
44244
44990
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
@@ -44252,10 +44998,10 @@ function createScopedServer() {
|
|
|
44252
44998
|
|
|
44253
44999
|
// src/server/approvals.ts
|
|
44254
45000
|
var fs49 = __toESM(require("fs"));
|
|
44255
|
-
var
|
|
45001
|
+
var path65 = __toESM(require("path"));
|
|
44256
45002
|
var crypto16 = __toESM(require("crypto"));
|
|
44257
45003
|
function storePath12(dataDir) {
|
|
44258
|
-
return
|
|
45004
|
+
return path65.join(dataDir, "approvals.json");
|
|
44259
45005
|
}
|
|
44260
45006
|
function readRequests(dataDir) {
|
|
44261
45007
|
const p = storePath12(dataDir);
|
|
@@ -44276,7 +45022,7 @@ function readRequests(dataDir) {
|
|
|
44276
45022
|
}
|
|
44277
45023
|
function persistRequests(dataDir, requests) {
|
|
44278
45024
|
const p = storePath12(dataDir);
|
|
44279
|
-
fs49.mkdirSync(
|
|
45025
|
+
fs49.mkdirSync(path65.dirname(p), { recursive: true });
|
|
44280
45026
|
const tmp = `${p}.tmp`;
|
|
44281
45027
|
fs49.writeFileSync(tmp, JSON.stringify(requests, null, 2) + "\n");
|
|
44282
45028
|
fs49.renameSync(tmp, p);
|
|
@@ -44800,7 +45546,7 @@ async function awaitApproval(cfg, credential, requestId, timeoutSeconds) {
|
|
|
44800
45546
|
let current2 = req;
|
|
44801
45547
|
while (current2.status === "pending" && Date.now() < deadline) {
|
|
44802
45548
|
const remaining = deadline - Date.now();
|
|
44803
|
-
await new Promise((
|
|
45549
|
+
await new Promise((resolve37) => setTimeout(resolve37, Math.min(AWAIT_POLL_INTERVAL_MS, remaining)));
|
|
44804
45550
|
expirePendingApprovals(cfg.dataDir, (/* @__PURE__ */ new Date()).toISOString());
|
|
44805
45551
|
current2 = getApprovalRequestById(cfg.dataDir, requestId) ?? current2;
|
|
44806
45552
|
}
|
|
@@ -44954,24 +45700,24 @@ function collectUsage(projects, scope) {
|
|
|
44954
45700
|
}
|
|
44955
45701
|
function buildHealthReport(checks, usage) {
|
|
44956
45702
|
const status2 = checks.some((c) => c.status === "fail") ? "unhealthy" : checks.some((c) => c.status === "warn") ? "degraded" : "ok";
|
|
44957
|
-
const
|
|
44958
|
-
if (usage)
|
|
44959
|
-
return
|
|
45703
|
+
const report3 = { status: status2, generatedAt: (/* @__PURE__ */ new Date()).toISOString(), checks };
|
|
45704
|
+
if (usage) report3.usage = usage;
|
|
45705
|
+
return report3;
|
|
44960
45706
|
}
|
|
44961
45707
|
function evaluateUsage(snapshots, policy) {
|
|
44962
45708
|
if (!policy.enabled) return snapshots;
|
|
44963
45709
|
const advisory = policy.mode === "block" ? "observe" : policy.mode || "observe";
|
|
44964
45710
|
return snapshots.map((snapshot) => {
|
|
44965
45711
|
const messages = [];
|
|
44966
|
-
const
|
|
45712
|
+
const compare2 = (value, limit, label3) => {
|
|
44967
45713
|
if (typeof value === "number" && typeof limit === "number" && value > limit) {
|
|
44968
|
-
messages.push(`[${advisory}] ${
|
|
45714
|
+
messages.push(`[${advisory}] ${label3} ${value} exceeds limit ${limit}`);
|
|
44969
45715
|
}
|
|
44970
45716
|
};
|
|
44971
|
-
|
|
44972
|
-
|
|
44973
|
-
|
|
44974
|
-
|
|
45717
|
+
compare2(snapshot.projectCount, policy.maxProjectsPerUser, "projectCount");
|
|
45718
|
+
compare2(snapshot.projectBytes, policy.maxProjectBytes, "projectBytes");
|
|
45719
|
+
compare2(snapshot.mcpRequestsLastMinute, policy.maxMcpRequestsPerMinute, "mcpRequestsPerMinute");
|
|
45720
|
+
compare2(snapshot.auditEventsToday, policy.maxAuditEventsPerDay, "auditEventsPerDay");
|
|
44975
45721
|
if (messages.length === 0) return snapshot;
|
|
44976
45722
|
return { ...snapshot, quotaMessages: [...snapshot.quotaMessages, ...messages] };
|
|
44977
45723
|
});
|
|
@@ -45088,11 +45834,11 @@ function handleOperationsRequest(cfg, credential, req, res, url) {
|
|
|
45088
45834
|
|
|
45089
45835
|
// src/server/gitbacking.ts
|
|
45090
45836
|
var fs50 = __toESM(require("fs"));
|
|
45091
|
-
var
|
|
45837
|
+
var path66 = __toESM(require("path"));
|
|
45092
45838
|
var crypto17 = __toESM(require("crypto"));
|
|
45093
45839
|
var import_child_process6 = require("child_process");
|
|
45094
45840
|
function storePath13(dataDir) {
|
|
45095
|
-
return
|
|
45841
|
+
return path66.join(dataDir, "git-backing.json");
|
|
45096
45842
|
}
|
|
45097
45843
|
var GitBackingStore = class {
|
|
45098
45844
|
constructor(dataDir) {
|
|
@@ -45123,7 +45869,7 @@ var GitBackingStore = class {
|
|
|
45123
45869
|
/** Swap the persisted collection wholesale via write-temp-then-rename. */
|
|
45124
45870
|
replaceAll(bindings) {
|
|
45125
45871
|
const p = storePath13(this.dataDir);
|
|
45126
|
-
fs50.mkdirSync(
|
|
45872
|
+
fs50.mkdirSync(path66.dirname(p), { recursive: true });
|
|
45127
45873
|
const tmp = `${p}.tmp`;
|
|
45128
45874
|
fs50.writeFileSync(tmp, JSON.stringify(bindings, null, 2) + "\n");
|
|
45129
45875
|
fs50.renameSync(tmp, p);
|
|
@@ -45231,7 +45977,7 @@ function checkoutBranch(workdir, branch) {
|
|
|
45231
45977
|
}
|
|
45232
45978
|
}
|
|
45233
45979
|
function cloneOrOpen(remote, branch, workdir, credentialRef) {
|
|
45234
|
-
if (!fs50.existsSync(
|
|
45980
|
+
if (!fs50.existsSync(path66.join(workdir, ".git"))) {
|
|
45235
45981
|
fs50.mkdirSync(workdir, { recursive: true });
|
|
45236
45982
|
git2(["clone", authRemote2(remote, credentialRef), "."], workdir);
|
|
45237
45983
|
git2(["config", "user.name", process.env["WAIRON_GIT_NAME"] || "wairon-bot"], workdir);
|
|
@@ -45247,7 +45993,7 @@ function mirrorTree(sourceDir, targetDir) {
|
|
|
45247
45993
|
fs50.rmSync(targetDir, { recursive: true, force: true });
|
|
45248
45994
|
const stat = fs50.statSync(sourceDir, { throwIfNoEntry: false });
|
|
45249
45995
|
if (!stat) return;
|
|
45250
|
-
fs50.mkdirSync(
|
|
45996
|
+
fs50.mkdirSync(path66.dirname(targetDir), { recursive: true });
|
|
45251
45997
|
fs50.cpSync(sourceDir, targetDir, { recursive: true });
|
|
45252
45998
|
}
|
|
45253
45999
|
function commitAndPush(workdir, message) {
|
|
@@ -45370,7 +46116,7 @@ function unbindScope(cfg, credential, bindingId) {
|
|
|
45370
46116
|
tryAppendAudit7(cfg, buildAuditEvent6(principal, "git.backing.unbind", "security", bindingId));
|
|
45371
46117
|
}
|
|
45372
46118
|
function runMirrorSync(cfg, binding) {
|
|
45373
|
-
const workdir =
|
|
46119
|
+
const workdir = path66.join(cfg.dataDir, "git-backing", binding.id);
|
|
45374
46120
|
cloneOrOpen(binding.remote, binding.branch, workdir, binding.credentialRef);
|
|
45375
46121
|
if (binding.scopeKind === "unit") {
|
|
45376
46122
|
const units = listOrganizationUnits(cfg.dataDir);
|
|
@@ -45378,23 +46124,23 @@ function runMirrorSync(cfg, binding) {
|
|
|
45378
46124
|
const placedIds = new Set(
|
|
45379
46125
|
listProjectPlacements(cfg.dataDir).filter((p) => subtree.has(p.unitId)).map((p) => p.projectId)
|
|
45380
46126
|
);
|
|
45381
|
-
const projectsDir =
|
|
46127
|
+
const projectsDir = path66.join(workdir, "projects");
|
|
45382
46128
|
fs50.rmSync(projectsDir, { recursive: true, force: true });
|
|
45383
46129
|
for (const rec of listProjectRecords(cfg.dataDir)) {
|
|
45384
46130
|
if (!placedIds.has(rec.id)) continue;
|
|
45385
|
-
mirrorTree(
|
|
46131
|
+
mirrorTree(path66.join(rec.rootPath, ".wai"), path66.join(projectsDir, rec.id, ".wai"));
|
|
45386
46132
|
}
|
|
45387
46133
|
} else {
|
|
45388
|
-
const instanceDir =
|
|
46134
|
+
const instanceDir = path66.join(workdir, "instance");
|
|
45389
46135
|
fs50.rmSync(instanceDir, { recursive: true, force: true });
|
|
45390
46136
|
const files = binding.includeCredentials ? INSTANCE_STRUCTURE_FILES : INSTANCE_STRUCTURE_FILES.filter((rel2) => rel2 !== "auth/credentials.json");
|
|
45391
46137
|
for (const rel2 of files) {
|
|
45392
|
-
mirrorTree(
|
|
46138
|
+
mirrorTree(path66.join(cfg.dataDir, rel2), path66.join(instanceDir, rel2));
|
|
45393
46139
|
}
|
|
45394
|
-
const projectsDir =
|
|
46140
|
+
const projectsDir = path66.join(workdir, "projects");
|
|
45395
46141
|
fs50.rmSync(projectsDir, { recursive: true, force: true });
|
|
45396
46142
|
for (const rec of listProjectRecords(cfg.dataDir)) {
|
|
45397
|
-
mirrorTree(
|
|
46143
|
+
mirrorTree(path66.join(rec.rootPath, ".wai"), path66.join(projectsDir, rec.id, ".wai"));
|
|
45398
46144
|
}
|
|
45399
46145
|
}
|
|
45400
46146
|
const published = commitAndPush(
|
|
@@ -45712,7 +46458,7 @@ function encodeFrame(opcode, payload) {
|
|
|
45712
46458
|
// src/server/web.ts
|
|
45713
46459
|
var crypto23 = __toESM(require("crypto"));
|
|
45714
46460
|
var fs55 = __toESM(require("fs"));
|
|
45715
|
-
var
|
|
46461
|
+
var path71 = __toESM(require("path"));
|
|
45716
46462
|
|
|
45717
46463
|
// src/server/webadmin.ts
|
|
45718
46464
|
function listUsers3(cfg, sessionId, project2) {
|
|
@@ -45967,14 +46713,14 @@ var crypto22 = __toESM(require("crypto"));
|
|
|
45967
46713
|
|
|
45968
46714
|
// src/server/sharesnapshots.ts
|
|
45969
46715
|
var fs51 = __toESM(require("fs"));
|
|
45970
|
-
var
|
|
46716
|
+
var path67 = __toESM(require("path"));
|
|
45971
46717
|
var crypto19 = __toESM(require("crypto"));
|
|
45972
46718
|
init_fs();
|
|
45973
46719
|
function snapshotDir(dataDir) {
|
|
45974
|
-
return
|
|
46720
|
+
return path67.join(dataDir, "share-snapshots");
|
|
45975
46721
|
}
|
|
45976
46722
|
function snapshotPath2(dataDir, id) {
|
|
45977
|
-
return
|
|
46723
|
+
return path67.join(snapshotDir(dataDir), `${id}.json`);
|
|
45978
46724
|
}
|
|
45979
46725
|
var ShareSnapshotStore = class {
|
|
45980
46726
|
constructor(dataDir) {
|
|
@@ -45983,7 +46729,7 @@ var ShareSnapshotStore = class {
|
|
|
45983
46729
|
write(snapshot) {
|
|
45984
46730
|
const p = snapshotPath2(this.dataDir, snapshot.id);
|
|
45985
46731
|
if (fs51.existsSync(p)) return;
|
|
45986
|
-
fs51.mkdirSync(
|
|
46732
|
+
fs51.mkdirSync(path67.dirname(p), { recursive: true });
|
|
45987
46733
|
const tmp = `${p}.tmp`;
|
|
45988
46734
|
fs51.writeFileSync(tmp, JSON.stringify(snapshot, null, 2) + "\n");
|
|
45989
46735
|
fs51.renameSync(tmp, p);
|
|
@@ -46085,10 +46831,10 @@ function captureSnapshot(dataDir, principal, projectId, view, artifacts) {
|
|
|
46085
46831
|
|
|
46086
46832
|
// src/server/sharelinks.ts
|
|
46087
46833
|
var fs52 = __toESM(require("fs"));
|
|
46088
|
-
var
|
|
46834
|
+
var path68 = __toESM(require("path"));
|
|
46089
46835
|
var crypto20 = __toESM(require("crypto"));
|
|
46090
46836
|
function storePath14(dataDir) {
|
|
46091
|
-
return
|
|
46837
|
+
return path68.join(dataDir, "share-links.json");
|
|
46092
46838
|
}
|
|
46093
46839
|
var ShareLinkStore = class {
|
|
46094
46840
|
constructor(dataDir) {
|
|
@@ -46116,7 +46862,7 @@ var ShareLinkStore = class {
|
|
|
46116
46862
|
}
|
|
46117
46863
|
replaceAll(links) {
|
|
46118
46864
|
const p = storePath14(this.dataDir);
|
|
46119
|
-
fs52.mkdirSync(
|
|
46865
|
+
fs52.mkdirSync(path68.dirname(p), { recursive: true });
|
|
46120
46866
|
const tmp = `${p}.tmp`;
|
|
46121
46867
|
fs52.writeFileSync(tmp, JSON.stringify(links, null, 2) + "\n");
|
|
46122
46868
|
fs52.renameSync(tmp, p);
|
|
@@ -46188,10 +46934,10 @@ function listProjectLinks(dataDir, projectId) {
|
|
|
46188
46934
|
|
|
46189
46935
|
// src/server/shareaccesslog.ts
|
|
46190
46936
|
var fs53 = __toESM(require("fs"));
|
|
46191
|
-
var
|
|
46937
|
+
var path69 = __toESM(require("path"));
|
|
46192
46938
|
var crypto21 = __toESM(require("crypto"));
|
|
46193
46939
|
function storePath15(dataDir) {
|
|
46194
|
-
return
|
|
46940
|
+
return path69.join(dataDir, "share-access.json");
|
|
46195
46941
|
}
|
|
46196
46942
|
var ShareAccessStore = class {
|
|
46197
46943
|
constructor(dataDir) {
|
|
@@ -46219,7 +46965,7 @@ var ShareAccessStore = class {
|
|
|
46219
46965
|
}
|
|
46220
46966
|
append(entry) {
|
|
46221
46967
|
const p = storePath15(this.dataDir);
|
|
46222
|
-
fs53.mkdirSync(
|
|
46968
|
+
fs53.mkdirSync(path69.dirname(p), { recursive: true });
|
|
46223
46969
|
const next = [...this.load(), entry];
|
|
46224
46970
|
const tmp = `${p}.tmp`;
|
|
46225
46971
|
fs53.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n");
|
|
@@ -46375,15 +47121,15 @@ init_fs();
|
|
|
46375
47121
|
|
|
46376
47122
|
// src/server/swagger.ts
|
|
46377
47123
|
var fs54 = __toESM(require("fs"));
|
|
46378
|
-
var
|
|
47124
|
+
var path70 = __toESM(require("path"));
|
|
46379
47125
|
var cache;
|
|
46380
47126
|
function loadAssets() {
|
|
46381
47127
|
if (cache !== void 0) return cache;
|
|
46382
47128
|
try {
|
|
46383
|
-
const dir =
|
|
47129
|
+
const dir = path70.dirname(require.resolve("swagger-ui-dist/package.json"));
|
|
46384
47130
|
cache = {
|
|
46385
|
-
css: fs54.readFileSync(
|
|
46386
|
-
js: fs54.readFileSync(
|
|
47131
|
+
css: fs54.readFileSync(path70.join(dir, "swagger-ui.css"), "utf8"),
|
|
47132
|
+
js: fs54.readFileSync(path70.join(dir, "swagger-ui-bundle.js"), "utf8")
|
|
46387
47133
|
};
|
|
46388
47134
|
} catch {
|
|
46389
47135
|
cache = null;
|
|
@@ -46795,11 +47541,11 @@ function nonceMatches(a, b) {
|
|
|
46795
47541
|
}
|
|
46796
47542
|
function loadReactBundle() {
|
|
46797
47543
|
const candidates = [
|
|
46798
|
-
|
|
47544
|
+
path71.resolve(__dirname, "webapp.html"),
|
|
46799
47545
|
// dist/index.js -> dist/webapp.html
|
|
46800
|
-
|
|
47546
|
+
path71.resolve(__dirname, "..", "webapp.html"),
|
|
46801
47547
|
// dist/cli/index.js -> dist/webapp.html
|
|
46802
|
-
|
|
47548
|
+
path71.resolve(__dirname, "..", "..", "web", "dist", "index.html")
|
|
46803
47549
|
// tsx dev: src/server -> web/dist
|
|
46804
47550
|
];
|
|
46805
47551
|
for (const candidate of candidates) {
|
|
@@ -49383,8 +50129,8 @@ var RealtimeHub = class {
|
|
|
49383
50129
|
* complete the handshake, and register the connection. A bad path or session
|
|
49384
50130
|
* destroys the socket. */
|
|
49385
50131
|
handleUpgrade(cfg, req, socket) {
|
|
49386
|
-
const
|
|
49387
|
-
if (
|
|
50132
|
+
const path77 = (req.url ?? "/").split("?")[0];
|
|
50133
|
+
if (path77 !== REALTIME_PATH || !isWebSocketUpgrade(req)) {
|
|
49388
50134
|
socket.destroy();
|
|
49389
50135
|
return;
|
|
49390
50136
|
}
|
|
@@ -50381,7 +51127,7 @@ function routeData(cfg, req, res) {
|
|
|
50381
51127
|
}
|
|
50382
51128
|
function readExposurePolicyFile(dataDir) {
|
|
50383
51129
|
try {
|
|
50384
|
-
const raw = fs56.readFileSync(
|
|
51130
|
+
const raw = fs56.readFileSync(path72.join(dataDir, "exposure-policy.json"), "utf8");
|
|
50385
51131
|
const parsed = JSON.parse(raw);
|
|
50386
51132
|
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
50387
51133
|
} catch {
|
|
@@ -50568,17 +51314,17 @@ async function routeAdmin(cfg, req, res) {
|
|
|
50568
51314
|
}
|
|
50569
51315
|
function warnIfDataDirUnmigrated(cfg) {
|
|
50570
51316
|
try {
|
|
50571
|
-
const
|
|
50572
|
-
if (
|
|
51317
|
+
const report3 = migratePermissionModel(cfg.dataDir, false);
|
|
51318
|
+
if (report3.findings.length === 0) return;
|
|
50573
51319
|
console.error(
|
|
50574
|
-
`[wairon migrate] ${
|
|
51320
|
+
`[wairon migrate] ${report3.findings.length} legacy data shape(s) found in ${cfg.dataDir} \u2014 this instance has NOT been migrated to the permission model. Legacy users and tokens resolve to zero permissions until you run: wairon host doctor --fix (run it without --fix first for a dry run).`
|
|
50575
51321
|
);
|
|
50576
|
-
const shown =
|
|
51322
|
+
const shown = report3.findings.slice(0, 10);
|
|
50577
51323
|
for (const finding of shown) {
|
|
50578
51324
|
console.error(`[wairon migrate] ${finding.area}: ${finding.detail}`);
|
|
50579
51325
|
}
|
|
50580
|
-
if (
|
|
50581
|
-
console.error(`[wairon migrate] \u2026 and ${
|
|
51326
|
+
if (report3.findings.length > shown.length) {
|
|
51327
|
+
console.error(`[wairon migrate] \u2026 and ${report3.findings.length - shown.length} more (see \`wairon host doctor\`).`);
|
|
50582
51328
|
}
|
|
50583
51329
|
} catch (err) {
|
|
50584
51330
|
console.error(`[wairon migrate] migration check skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -51073,9 +51819,9 @@ function seedDemoTree() {
|
|
|
51073
51819
|
|
|
51074
51820
|
// src/commands/host.ts
|
|
51075
51821
|
function resolveHostConfig(options) {
|
|
51076
|
-
const dataDir = options.dataDir || process.env["WAIRON_DATA_DIR"] ||
|
|
51822
|
+
const dataDir = options.dataDir || process.env["WAIRON_DATA_DIR"] || path73.join(os11.homedir(), ".wairon", "data");
|
|
51077
51823
|
if (!process.env["WAIRON_PACKS_DIR"]) {
|
|
51078
|
-
process.env["WAIRON_PACKS_DIR"] =
|
|
51824
|
+
process.env["WAIRON_PACKS_DIR"] = path73.join(dataDir, "packs");
|
|
51079
51825
|
}
|
|
51080
51826
|
const cfg = {
|
|
51081
51827
|
host: options.host || "0.0.0.0",
|
|
@@ -51132,11 +51878,11 @@ async function runServe(options = {}) {
|
|
|
51132
51878
|
logger.info(` data dir: ${import_chalk17.default.gray(cfg.dataDir)}`);
|
|
51133
51879
|
logger.blank();
|
|
51134
51880
|
logger.info("Press Ctrl+C to stop.");
|
|
51135
|
-
await new Promise((
|
|
51881
|
+
await new Promise((resolve37) => {
|
|
51136
51882
|
const shutdown = () => {
|
|
51137
51883
|
logger.info("Shutting down\u2026");
|
|
51138
51884
|
handle.close();
|
|
51139
|
-
|
|
51885
|
+
resolve37();
|
|
51140
51886
|
};
|
|
51141
51887
|
process.on("SIGINT", shutdown);
|
|
51142
51888
|
process.on("SIGTERM", shutdown);
|
|
@@ -51156,13 +51902,13 @@ function openBrowser(url) {
|
|
|
51156
51902
|
}
|
|
51157
51903
|
async function runDev(options = {}) {
|
|
51158
51904
|
const cwd = process.cwd();
|
|
51159
|
-
if (!fs57.existsSync(
|
|
51905
|
+
if (!fs57.existsSync(path73.join(cwd, ".wai"))) {
|
|
51160
51906
|
throw new WaironError(
|
|
51161
51907
|
"No .wai/ found in the current directory. Run `wairon dev` from a wairon project root (or run `wairon init` first)."
|
|
51162
51908
|
);
|
|
51163
51909
|
}
|
|
51164
51910
|
const hash = crypto24.createHash("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
51165
|
-
const dataDir =
|
|
51911
|
+
const dataDir = path73.join(os11.tmpdir(), "wairon-dev", hash);
|
|
51166
51912
|
fs57.mkdirSync(dataDir, { recursive: true });
|
|
51167
51913
|
const port = options.port ? Number(options.port) : 8080;
|
|
51168
51914
|
const exposurePolicy = {
|
|
@@ -51201,11 +51947,11 @@ async function runDev(options = {}) {
|
|
|
51201
51947
|
logger.blank();
|
|
51202
51948
|
logger.info("An agent edits specs; refresh the page to see the live graph. Press Ctrl+C to stop.");
|
|
51203
51949
|
if (options.open) openBrowser(url);
|
|
51204
|
-
await new Promise((
|
|
51950
|
+
await new Promise((resolve37) => {
|
|
51205
51951
|
const shutdown = () => {
|
|
51206
51952
|
logger.info("Shutting down\u2026");
|
|
51207
51953
|
handle.close();
|
|
51208
|
-
|
|
51954
|
+
resolve37();
|
|
51209
51955
|
};
|
|
51210
51956
|
process.on("SIGINT", shutdown);
|
|
51211
51957
|
process.on("SIGTERM", shutdown);
|
|
@@ -51329,16 +52075,16 @@ async function runHostUnit(action, options = {}) {
|
|
|
51329
52075
|
}
|
|
51330
52076
|
async function runHostDoctor(options = {}) {
|
|
51331
52077
|
const cfg = resolveHostConfig(options);
|
|
51332
|
-
const
|
|
51333
|
-
if (
|
|
52078
|
+
const report3 = migratePermissionModel(cfg.dataDir, options.fix === true);
|
|
52079
|
+
if (report3.findings.length === 0) {
|
|
51334
52080
|
logger.success("Hosted data is on the permission model \u2014 nothing to migrate.");
|
|
51335
52081
|
return;
|
|
51336
52082
|
}
|
|
51337
|
-
logger.info(`${
|
|
51338
|
-
for (const f of
|
|
52083
|
+
logger.info(`${report3.findings.length} finding(s)${report3.applied ? " \u2014 applied" : " (dry run; re-run with --fix to apply)"}:`);
|
|
52084
|
+
for (const f of report3.findings) {
|
|
51339
52085
|
logger.info(` [${f.area.padEnd(8)}] ${f.detail}`);
|
|
51340
52086
|
}
|
|
51341
|
-
if (!
|
|
52087
|
+
if (!report3.applied) {
|
|
51342
52088
|
logger.warn("NOT applied. Without --fix, pre-permission-model users and tokens resolve to ZERO permissions.");
|
|
51343
52089
|
}
|
|
51344
52090
|
}
|
|
@@ -51559,8 +52305,8 @@ async function runHostPacks(action, options = {}) {
|
|
|
51559
52305
|
}
|
|
51560
52306
|
case "install": {
|
|
51561
52307
|
if (!options.file) throw new WaironError("`--file <path>` (a declarative pack YAML) is required for install.");
|
|
51562
|
-
const name = options.name ??
|
|
51563
|
-
const content = fs57.readFileSync(
|
|
52308
|
+
const name = options.name ?? path73.basename(options.file).replace(/\.(ya?ml)$/i, "");
|
|
52309
|
+
const content = fs57.readFileSync(path73.resolve(options.file), "utf8");
|
|
51564
52310
|
const desc = project2 ? installProjectPack(cfg, cred, project2, name, content) : installGlobalPack(cfg, cred, name, content);
|
|
51565
52311
|
logger.success(`Installed ${scope} pack "${desc.name}" (${desc.profiles} profile(s), ${desc.languages} language(s)).`);
|
|
51566
52312
|
if (project2) logger.info("Committed with the project \u2014 every clone and CI will enforce it.");
|
|
@@ -51647,7 +52393,7 @@ async function runHostGit(action, options = {}) {
|
|
|
51647
52393
|
}
|
|
51648
52394
|
|
|
51649
52395
|
// src/commands/produce.ts
|
|
51650
|
-
var
|
|
52396
|
+
var import_inquirer5 = __toESM(require("inquirer"));
|
|
51651
52397
|
var import_chalk18 = __toESM(require("chalk"));
|
|
51652
52398
|
init_logger();
|
|
51653
52399
|
init_errors();
|
|
@@ -51664,7 +52410,7 @@ async function runProduce(target, options = {}) {
|
|
|
51664
52410
|
let token = options.token || process.env[t.envKey] || null;
|
|
51665
52411
|
if (!token) {
|
|
51666
52412
|
if (!process.stdin.isTTY) throw new WaironError(`No ${t.label} token \u2014 pass --token or set ${t.envKey}.`);
|
|
51667
|
-
const ans = await
|
|
52413
|
+
const ans = await import_inquirer5.default.prompt([
|
|
51668
52414
|
{ type: "password", name: "token", message: `${t.label} token:`, mask: "*" }
|
|
51669
52415
|
]);
|
|
51670
52416
|
token = ans.token;
|
|
@@ -51685,11 +52431,6 @@ var import_chalk19 = __toESM(require("chalk"));
|
|
|
51685
52431
|
init_logger();
|
|
51686
52432
|
init_errors();
|
|
51687
52433
|
init_paths();
|
|
51688
|
-
|
|
51689
|
-
// src/commands/adapters/surfaces.ts
|
|
51690
|
-
init_surface_portal();
|
|
51691
|
-
|
|
51692
|
-
// src/commands/surface.ts
|
|
51693
52434
|
init_models();
|
|
51694
52435
|
async function runSurface(action, options = {}) {
|
|
51695
52436
|
assertProjectInitialized();
|
|
@@ -51815,10 +52556,10 @@ function printPins(pins) {
|
|
|
51815
52556
|
return;
|
|
51816
52557
|
}
|
|
51817
52558
|
const outcome = (o) => o === "pinned" ? import_chalk20.default.green(o) : o === "unchanged" ? import_chalk20.default.gray(o) : import_chalk20.default.yellow(o);
|
|
51818
|
-
for (const
|
|
51819
|
-
const what =
|
|
51820
|
-
logger.info(`${import_chalk20.default.cyan(
|
|
51821
|
-
for (const ref of
|
|
52559
|
+
for (const pin2 of pins) {
|
|
52560
|
+
const what = pin2.digest ? ` ${pin2.usedNames} used name(s), ${pin2.digest.slice(0, 19)}\u2026` : "";
|
|
52561
|
+
logger.info(`${import_chalk20.default.cyan(pin2.alias)} \u2192 ${pin2.project ?? "?"}: ${outcome(pin2.outcome)}${what}${pin2.detail ? ` \u2014 ${pin2.detail}` : ""}`);
|
|
52562
|
+
for (const ref of pin2.unexported) {
|
|
51822
52563
|
logger.info(` unexported: "${ref.specId}" reaches "${ref.target}"${ref.member ? ` (${ref.member})` : ""} \u2014 export it from the producer's L0 to pin it`);
|
|
51823
52564
|
}
|
|
51824
52565
|
}
|
|
@@ -51882,7 +52623,7 @@ async function runExternals(action, aliases, options = {}) {
|
|
|
51882
52623
|
|
|
51883
52624
|
// src/commands/remote.ts
|
|
51884
52625
|
var fs59 = __toESM(require("fs"));
|
|
51885
|
-
var
|
|
52626
|
+
var path75 = __toESM(require("path"));
|
|
51886
52627
|
var import_chalk21 = __toESM(require("chalk"));
|
|
51887
52628
|
init_logger();
|
|
51888
52629
|
init_errors();
|
|
@@ -51893,15 +52634,15 @@ init_mcp();
|
|
|
51893
52634
|
// src/commands/remotebinding.ts
|
|
51894
52635
|
var fs58 = __toESM(require("fs"));
|
|
51895
52636
|
var os12 = __toESM(require("os"));
|
|
51896
|
-
var
|
|
52637
|
+
var path74 = __toESM(require("path"));
|
|
51897
52638
|
init_paths();
|
|
51898
52639
|
var BINDING_FILE = "remote.json";
|
|
51899
52640
|
var CREDENTIALS_FILE = "credentials.json";
|
|
51900
52641
|
function bindingPath(root) {
|
|
51901
|
-
return
|
|
52642
|
+
return path74.join(aiPathsAt(root).root(), BINDING_FILE);
|
|
51902
52643
|
}
|
|
51903
52644
|
function credentialsPath() {
|
|
51904
|
-
return
|
|
52645
|
+
return path74.join(os12.homedir(), ".wairon", CREDENTIALS_FILE);
|
|
51905
52646
|
}
|
|
51906
52647
|
function normalizeInstanceUrl(url) {
|
|
51907
52648
|
return url.trim().replace(/\/+$/, "").toLowerCase();
|
|
@@ -51915,7 +52656,7 @@ function readJson(file) {
|
|
|
51915
52656
|
}
|
|
51916
52657
|
}
|
|
51917
52658
|
function writeJsonAtomic(file, value, mode) {
|
|
51918
|
-
fs58.mkdirSync(
|
|
52659
|
+
fs58.mkdirSync(path74.dirname(file), { recursive: true });
|
|
51919
52660
|
const tmp = `${file}.tmp`;
|
|
51920
52661
|
fs58.writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n", mode !== void 0 ? { mode } : void 0);
|
|
51921
52662
|
fs58.renameSync(tmp, file);
|
|
@@ -52248,7 +52989,7 @@ async function runRemote(action, options = {}) {
|
|
|
52248
52989
|
};
|
|
52249
52990
|
if (options.unit) transfer.createUnitId = options.unit;
|
|
52250
52991
|
if (options.archive) transfer.archivePath = options.archive;
|
|
52251
|
-
|
|
52992
|
+
report2(await pushTree(target, transfer));
|
|
52252
52993
|
return;
|
|
52253
52994
|
}
|
|
52254
52995
|
case "pull": {
|
|
@@ -52257,8 +52998,8 @@ async function runRemote(action, options = {}) {
|
|
|
52257
52998
|
allowPartial: options.allowPartial === true
|
|
52258
52999
|
};
|
|
52259
53000
|
if (options.archive) transfer.archivePath = options.archive;
|
|
52260
|
-
if (options.dir) transfer.destDir =
|
|
52261
|
-
|
|
53001
|
+
if (options.dir) transfer.destDir = path75.resolve(options.dir);
|
|
53002
|
+
report2(await pullTree(target, transfer));
|
|
52262
53003
|
return;
|
|
52263
53004
|
}
|
|
52264
53005
|
default:
|
|
@@ -52341,13 +53082,13 @@ function topProjectId2(selector) {
|
|
|
52341
53082
|
}
|
|
52342
53083
|
function writeArchiveIfAsked(archive, archivePath, suggestedFileName) {
|
|
52343
53084
|
if (!archivePath) return void 0;
|
|
52344
|
-
const resolved =
|
|
52345
|
-
const target = fs59.existsSync(resolved) && fs59.statSync(resolved).isDirectory() ?
|
|
52346
|
-
fs59.mkdirSync(
|
|
53085
|
+
const resolved = path75.resolve(archivePath);
|
|
53086
|
+
const target = fs59.existsSync(resolved) && fs59.statSync(resolved).isDirectory() ? path75.join(resolved, suggestedFileName) : resolved;
|
|
53087
|
+
fs59.mkdirSync(path75.dirname(target), { recursive: true });
|
|
52347
53088
|
fs59.writeFileSync(target, Buffer.from(archive));
|
|
52348
53089
|
return target;
|
|
52349
53090
|
}
|
|
52350
|
-
function
|
|
53091
|
+
function report2(outcome) {
|
|
52351
53092
|
const where = outcome.direction === "push" ? `${outcome.url} \u2192 ${outcome.projectId}` : `${outcome.projectId} \u2192 ${outcome.destDir ?? getProjectRoot()}`;
|
|
52352
53093
|
logger.success(
|
|
52353
53094
|
`${outcome.direction === "push" ? "Pushed" : "Pulled"} "${outcome.projectName}": ${outcome.fileCount} file(s) across ${outcome.roots.length} root(s) \u2014 ${where}`
|
|
@@ -52564,10 +53305,10 @@ async function lockCommand(opts) {
|
|
|
52564
53305
|
async function validateCommand(opts) {
|
|
52565
53306
|
const target = resolveTarget(getProjectRoot(), {});
|
|
52566
53307
|
if (target) {
|
|
52567
|
-
const
|
|
52568
|
-
const errors =
|
|
52569
|
-
const warnings =
|
|
52570
|
-
const notices =
|
|
53308
|
+
const report3 = await validateAttached(target, opts.subsystem);
|
|
53309
|
+
const errors = report3.errors ?? [];
|
|
53310
|
+
const warnings = report3.warnings ?? [];
|
|
53311
|
+
const notices = report3.notices ?? [];
|
|
52571
53312
|
logger.info(`Validated "${target.projectId}" on ${target.url} \u2014 ${errors.length} error(s), ${warnings.length} warning(s), ${notices.length} notice(s).`);
|
|
52572
53313
|
for (const e of errors) logger.error(` [${e.code}] ${e.specId ? `${e.specId}: ` : ""}${e.message}`);
|
|
52573
53314
|
for (const w of warnings) logger.warn(` [${w.code}] ${w.specId ? `${w.specId}: ` : ""}${w.message}`);
|
|
@@ -52607,8 +53348,8 @@ program.command("validate").description("Validate the project configuration and
|
|
|
52607
53348
|
program.command("status").description("Show a hierarchical completeness graph of the SDD Spec Tree").option("--subsystem <id>", "only show status for the specified subsystem").option("--no-recursive", "do not recursively show status for subprojects").action(async (opts) => {
|
|
52608
53349
|
await statusCommand(opts);
|
|
52609
53350
|
});
|
|
52610
|
-
program.command("doctor").description("Health check: flags stale generated guides/skills, an unregistered MCP server,
|
|
52611
|
-
await runDoctor({ fix: opts.fix });
|
|
53351
|
+
program.command("doctor").description("Health check: flags stale generated guides/skills, an unregistered MCP server, spec-tree issues and the chaining migration still pending").option("--fix", "regenerate stale in-project guides/context/skills, register the MCP server, then apply the chaining migration once confirmed").option("--report <section>", "print one section's plan and nothing else, writing nothing (the one section: chaining); never combines with --fix").option("-y, --yes", "answer the chaining migration's confirmation (for a non-interactive --fix)").action(async (opts) => {
|
|
53352
|
+
await runDoctor({ fix: opts.fix, report: opts.report, yes: opts.yes });
|
|
52612
53353
|
});
|
|
52613
53354
|
async function runRules() {
|
|
52614
53355
|
await listRules3();
|
|
@@ -52761,7 +53502,7 @@ async function runAgent(action, id) {
|
|
|
52761
53502
|
}
|
|
52762
53503
|
case "customize": {
|
|
52763
53504
|
const brief = composeAgentBrief(id);
|
|
52764
|
-
const guidancePath =
|
|
53505
|
+
const guidancePath = path76.join(AI_PATHS.root(), "agents", `${id}.md`);
|
|
52765
53506
|
const relPath = `.wai/agents/${id}.md`;
|
|
52766
53507
|
if (pathExists(guidancePath)) {
|
|
52767
53508
|
throw new GuidanceFileExistsError(relPath);
|