@wairon/cli 5.1.1-dev.59 → 5.1.1-dev.60
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 +595 -596
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +265 -114
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var init_defaults = __esm({
|
|
|
65
65
|
copilot: ".github/prompts",
|
|
66
66
|
codex: ".codex/agents"
|
|
67
67
|
};
|
|
68
|
-
WAIRON_VERSION = "5.1.1-dev.
|
|
68
|
+
WAIRON_VERSION = "5.1.1-dev.60";
|
|
69
69
|
GITHUB_REPO = "SYW-Apps/Waffle-AIron";
|
|
70
70
|
SUPPORTED_ALIASES = ["wai"];
|
|
71
71
|
SCAN_EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
@@ -321,196 +321,6 @@ var init_fs = __esm({
|
|
|
321
321
|
}
|
|
322
322
|
});
|
|
323
323
|
|
|
324
|
-
// src/core/stamp.ts
|
|
325
|
-
function versionStamp() {
|
|
326
|
-
return `<!-- wairon-version: ${WAIRON_VERSION} -->`;
|
|
327
|
-
}
|
|
328
|
-
function readStampVersion(content) {
|
|
329
|
-
const m = content.match(STAMP_RE);
|
|
330
|
-
return m ? m[1] : null;
|
|
331
|
-
}
|
|
332
|
-
var STAMP_RE;
|
|
333
|
-
var init_stamp = __esm({
|
|
334
|
-
"src/core/stamp.ts"() {
|
|
335
|
-
"use strict";
|
|
336
|
-
init_defaults();
|
|
337
|
-
STAMP_RE = /<!--\s*wairon-version:\s*([^\s]+)\s*-->/;
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
// src/utils/ai-guide.ts
|
|
342
|
-
var ai_guide_exports = {};
|
|
343
|
-
__export(ai_guide_exports, {
|
|
344
|
-
GLOBAL_GUIDE_BODY: () => GLOBAL_GUIDE_BODY,
|
|
345
|
-
GUIDE_MARKER_END: () => GUIDE_MARKER_END,
|
|
346
|
-
GUIDE_MARKER_START: () => GUIDE_MARKER_START,
|
|
347
|
-
globalGuideFilePath: () => globalGuideFilePath,
|
|
348
|
-
hasWaironGuide: () => hasWaironGuide,
|
|
349
|
-
injectGuide: () => injectGuide,
|
|
350
|
-
localGuideFilePath: () => localGuideFilePath,
|
|
351
|
-
reinjectLocalGuides: () => reinjectLocalGuides,
|
|
352
|
-
stripGuideSection: () => stripGuideSection,
|
|
353
|
-
writeRootGuideDelegator: () => writeRootGuideDelegator
|
|
354
|
-
});
|
|
355
|
-
function globalGuideFilePath(targetType) {
|
|
356
|
-
if (targetType === "claude") return path5.join(process.env["CLAUDE_CONFIG_DIR"] || path5.join(os3.homedir(), ".claude"), "CLAUDE.md");
|
|
357
|
-
if (targetType === "gemini") return path5.join(process.env["GEMINI_CONFIG_DIR"] || path5.join(os3.homedir(), ".gemini"), "GEMINI.md");
|
|
358
|
-
return null;
|
|
359
|
-
}
|
|
360
|
-
function localGuideFilePath(projectRoot2, targetType) {
|
|
361
|
-
if (targetType === "claude") return path5.join(projectRoot2, ".claude", "CLAUDE.md");
|
|
362
|
-
if (targetType === "gemini" || targetType === "agy") return path5.join(projectRoot2, ".gemini", "GEMINI.md");
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
function hasWaironGuide(filePath) {
|
|
366
|
-
if (!fs4.existsSync(filePath)) return false;
|
|
367
|
-
return fs4.readFileSync(filePath, "utf-8").includes(GUIDE_MARKER_START);
|
|
368
|
-
}
|
|
369
|
-
function injectGuide(filePath, scope) {
|
|
370
|
-
const body = scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
|
|
371
|
-
const section = `
|
|
372
|
-
|
|
373
|
-
${GUIDE_MARKER_START}
|
|
374
|
-
${versionStamp()}
|
|
375
|
-
${body}
|
|
376
|
-
${GUIDE_MARKER_END}
|
|
377
|
-
`;
|
|
378
|
-
const existing = fs4.existsSync(filePath) ? fs4.readFileSync(filePath, "utf-8") : "";
|
|
379
|
-
const stripped = stripGuideSection(existing);
|
|
380
|
-
const newContent = stripped.trimEnd() + section;
|
|
381
|
-
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
382
|
-
fs4.writeFileSync(filePath, newContent, "utf-8");
|
|
383
|
-
}
|
|
384
|
-
function stripGuideSection(content) {
|
|
385
|
-
const start2 = content.indexOf(GUIDE_MARKER_START);
|
|
386
|
-
const end = content.indexOf(GUIDE_MARKER_END);
|
|
387
|
-
if (start2 === -1 || end === -1) return content;
|
|
388
|
-
return content.slice(0, start2) + content.slice(end + GUIDE_MARKER_END.length);
|
|
389
|
-
}
|
|
390
|
-
function writeRootGuideDelegator(projectRoot2, targetType) {
|
|
391
|
-
if (targetType === "claude") {
|
|
392
|
-
const filePath = path5.join(projectRoot2, "CLAUDE.md");
|
|
393
|
-
const content = `@.claude/CLAUDE.md
|
|
394
|
-
|
|
395
|
-
# Wairon SDD Project
|
|
396
|
-
|
|
397
|
-
This project uses the Wairon Spec-Driven Development (SDD) framework. The imported
|
|
398
|
-
\`.claude/CLAUDE.md\` above is your complete operating guide \u2014 you already have the
|
|
399
|
-
full context, so don't search the project to learn how wairon or SDD works.
|
|
400
|
-
|
|
401
|
-
To design or modify the system, invoke the **\`sdd-architect\`** skill
|
|
402
|
-
(in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
|
|
403
|
-
the \`wairon\` CLI is the human developer's tool, not yours.
|
|
404
|
-
`;
|
|
405
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
406
|
-
} else if (targetType === "gemini" || targetType === "agy") {
|
|
407
|
-
const filePath = path5.join(projectRoot2, "GEMINI.md");
|
|
408
|
-
const content = `# Wairon SDD Project
|
|
409
|
-
${GUIDE_MARKER_START}
|
|
410
|
-
${versionStamp()}
|
|
411
|
-
${LOCAL_GUIDE_BODY}
|
|
412
|
-
${GUIDE_MARKER_END}
|
|
413
|
-
`;
|
|
414
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
415
|
-
} else if (targetType === "cursor") {
|
|
416
|
-
const filePath = path5.join(projectRoot2, ".cursorrules");
|
|
417
|
-
const content = `# Wairon SDD Project
|
|
418
|
-
|
|
419
|
-
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
420
|
-
|
|
421
|
-
Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
|
|
422
|
-
`;
|
|
423
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
424
|
-
} else if (targetType === "copilot") {
|
|
425
|
-
const filePath = path5.join(projectRoot2, ".github", "copilot-instructions.md");
|
|
426
|
-
fs4.mkdirSync(path5.dirname(filePath), { recursive: true });
|
|
427
|
-
const content = `# Wairon SDD Project
|
|
428
|
-
|
|
429
|
-
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
430
|
-
|
|
431
|
-
Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
|
|
432
|
-
`;
|
|
433
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
434
|
-
} else if (targetType === "codex") {
|
|
435
|
-
const filePath = path5.join(projectRoot2, ".codexrules");
|
|
436
|
-
const content = `# Wairon SDD Project
|
|
437
|
-
|
|
438
|
-
Refer to [.codex/agents/](.codex/agents/) for full instructions.
|
|
439
|
-
`;
|
|
440
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
function reinjectLocalGuides(projectRoot2, targetTypes) {
|
|
444
|
-
const written = [];
|
|
445
|
-
for (const type of targetTypes) {
|
|
446
|
-
if (!GUIDE_TARGETS.includes(type)) continue;
|
|
447
|
-
const guidePath = localGuideFilePath(projectRoot2, type);
|
|
448
|
-
if (guidePath) {
|
|
449
|
-
injectGuide(guidePath, "local");
|
|
450
|
-
if (!written.includes(guidePath)) written.push(guidePath);
|
|
451
|
-
}
|
|
452
|
-
writeRootGuideDelegator(projectRoot2, type);
|
|
453
|
-
}
|
|
454
|
-
return written;
|
|
455
|
-
}
|
|
456
|
-
var fs4, os3, path5, GUIDE_MARKER_START, GUIDE_MARKER_END, GLOBAL_GUIDE_BODY, LOCAL_GUIDE_BODY, GUIDE_TARGETS;
|
|
457
|
-
var init_ai_guide = __esm({
|
|
458
|
-
"src/utils/ai-guide.ts"() {
|
|
459
|
-
"use strict";
|
|
460
|
-
fs4 = __toESM(require("fs"));
|
|
461
|
-
os3 = __toESM(require("os"));
|
|
462
|
-
path5 = __toESM(require("path"));
|
|
463
|
-
init_stamp();
|
|
464
|
-
GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
|
|
465
|
-
GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
|
|
466
|
-
GLOBAL_GUIDE_BODY = `## wairon \u2014 Spec-Driven Development (optional)
|
|
467
|
-
|
|
468
|
-
If \`.wai/specs/\` exists, the wairon SDD workflow is active; otherwise ignore it. wairon does not orchestrate sessions \u2014 it equips yours.
|
|
469
|
-
|
|
470
|
-
### In SDD Projects:
|
|
471
|
-
- **Source of Truth**: All architecture lives in the spec tree under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 L5 Narrative). Do not edit generated agent config files under \`.claude/agents/\` (rebuilt via \`wairon generate\`).
|
|
472
|
-
- **Validation**: Conformance checks (stereotype rules, cycle checks, reference integrity) are run via the \`sdd_validate_tree\` MCP tool.
|
|
473
|
-
- **Operating Rules**:
|
|
474
|
-
1. **Skills**: Use \`sdd-architect\` to design (and \`sdd-implement\`, \`sdd-narrative\`, \`sdd-auditor\`). Refer to project's local guide file for detailed constraints.
|
|
475
|
-
2. **MCP Tools Only**: Author/validate specs *only* via \`sdd_*\` tools (e.g. \`sdd_initialize_system\`, \`sdd_validate_tree\`).
|
|
476
|
-
3. **No CLI Exec**: Do not run the \`wairon\` CLI (human tool). Use MCP tools \`sdd_validate_tree\` and \`sdd_get_status\` instead.
|
|
477
|
-
4. **Delegation**: Delegate implementation via the \`sdd-delegate\` skill \u2014 live agent briefs (\`sdd_get_agent_brief\` MCP tool / \`wairon-agent://\` resource) are composed per call and always current; no session restart. Generated agent files are an optional materialized view of the same topology. User-owned per-agent guidance may live in \`.wai/agents/<agent-id>.md\` (folded into every brief; scaffold via \`wairon agent customize <id>\`).
|
|
478
|
-
5. **Design First**: Complete spec and pass \`sdd_validate_tree\` before writing code.
|
|
479
|
-
6. **Consistency**: Code must match L3 interfaces and L5 narratives exactly. If the spec is wrong, stop and update the spec.
|
|
480
|
-
7. **Subprojects & Namespacing**: If a subsystem uses \`projectPath\` delegation, target its specs using namespaced IDs (e.g. \`subsystem::component\`). Use leading \`::\` to target root (e.g. \`::shared::type\`) and \`super::\` to go up a level (e.g. \`super::sibling\`). wairon automatically resolves the path and strips the prefix on writes.`;
|
|
481
|
-
LOCAL_GUIDE_BODY = `## Wairon \u2014 Spec-Driven Development (you are operating inside it)
|
|
482
|
-
|
|
483
|
-
This project uses **wairon**. System specs live under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 Narrative); agent topology and code are derived from it.
|
|
484
|
-
|
|
485
|
-
**Do NOT search files or read agent configs to learn about wairon or SDD. Use the context here and the \`sdd-architect\` skill to start.**
|
|
486
|
-
|
|
487
|
-
**Your first move: call the \`sdd_get_status\` MCP tool** (or \`wairon/sdd_get_status\`) to see the spec tree. Do not parse files or run CLI commands manually.
|
|
488
|
-
|
|
489
|
-
### How you operate
|
|
490
|
-
- **To design/modify specs**: Use **\`sdd-architect\`** skill (in \`.claude/skills/\` or \`.gemini/skills/\`).
|
|
491
|
-
- **Manage specs via MCP tools only**: Use \`sdd_initialize_system\`, \`sdd_add_subsystem\`, \`sdd_add_component\`, \`sdd_define_interface\`, \`sdd_write_narrative\`, \`sdd_add_type\`, \`sdd_get_spec\`, \`sdd_delete_spec\`, \`sdd_validate_tree\`, and \`sdd_get_status\` (namespaced if needed). Do not edit specs manually.
|
|
492
|
-
- **Subprojects & Namespacing (Chaining)**: If a subsystem defines a \`projectPath\`, its entire \`.wai/\` spec tree is recursively loaded and namespaced with the subsystem ID as a prefix (using \`::\`, e.g. \`billing::invoice::invoice_portal\`). Use the qualified namespaced ID with the parent MCP tools; wairon will resolve the path and strip the prefix automatically.
|
|
493
|
-
- **Leading \`::\`**: Bypasses the local subsystem prefix to resolve absolute from the system root (e.g. \`::shared::error-type\`).
|
|
494
|
-
- **\`super::\`**: Goes up one parent subsystem level (e.g. \`super::sibling_comp\`, \`super::super::parent_sibling\`).
|
|
495
|
-
- **Do not run the \`wairon\` CLI**: Use \`sdd_validate_tree\` and \`sdd_get_status\` instead of CLI commands.
|
|
496
|
-
- **Handoff to implementation**: Once design is complete and validates cleanly, tell the human: *"The specs are complete and validate. Please run \`wairon lock\` to confirm and freeze them."* No session restart is needed after the lock \u2014 delegate implementation right away via the \`sdd-delegate\` skill.
|
|
497
|
-
- **To implement code**: Delegate via the \`sdd-delegate\` skill: fetch the component's live brief with the \`sdd_get_agent_brief\` MCP tool (or the \`wairon-agent://\` resource) and spawn a subagent from it. Briefs are composed per call from the current spec tree, so they are always current \u2014 never wait for a restart. Implementations must match L3 interfaces and L5 narratives exactly. Generated agent files under \`.claude/agents/\` are an optional materialized view of the same topology \u2014 the live briefs are canonical.
|
|
498
|
-
|
|
499
|
-
### Rules (enforced by \`sdd_validate_tree\`)
|
|
500
|
-
1. **Design before code**: Complete spec and pass validator before writing source code.
|
|
501
|
-
2. **Human-in-the-loop**: Ask user approval for each spec layer before proceeding.
|
|
502
|
-
3. **Spec consistency**: If a 1:1 narrative match is incorrect or conflicts with L0 requirements, escalate a spec revision first. Never ship mismatched code.
|
|
503
|
-
4. **No persistence shortcuts & strict layers**: A Portal must never depend directly on a Store, Registry, or Adapter. Portal reads MAY go through a Repository/Index facade (passthrough reads need no per-entity Orchestrator ceremony), but a Portal narrative call or dispatch-table binding that reaches a write-effect facade method is an error (\`PORTAL_WRITE_SHORTCUT\`) \u2014 writes always route through an Orchestrator. Held domain state always lives in a dedicated data component, never as fields inside an Orchestrator. Two sanctioned shapes: the RECOMMENDED Repository pattern (owns Store + Registry + Index; consumers depend on the facade), or \u2014 for genuinely simple state \u2014 a deliberately standalone Store (workflow-layer consumers only, acknowledged with a lint.allow reason on the UNOWNED_STORE warning). Never combine Store/Registry/Index roles into one component, and never fold state into a consuming component because a link was refused.
|
|
504
|
-
|
|
505
|
-
### Component Vocabulary
|
|
506
|
-
* **Blocks**: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer.
|
|
507
|
-
* **Patterns**: Repository \u2014 the composable pattern that \`owns\` its member blocks: one Store with its Registry, Indexes and Queries, and optionally an Adapter.
|
|
508
|
-
* **Variants**: \`gateway\`, a Portal that authenticates, authorizes, validates or rate-limits before it dispatches. Logic is an Orchestrator, and \`dependencyClass: pure | read\` bounds what it may depend on (unset = a workflow). Specialist and Gateway are retired stereotypes.
|
|
509
|
-
* Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
|
|
510
|
-
GUIDE_TARGETS = ["claude", "gemini", "agy", "cursor", "copilot", "codex"];
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
|
|
514
324
|
// src/utils/yaml.ts
|
|
515
325
|
function parseYaml(content, sourcePath) {
|
|
516
326
|
try {
|
|
@@ -1159,13 +969,13 @@ var init_project = __esm({
|
|
|
1159
969
|
|
|
1160
970
|
// src/config/project-config.ts
|
|
1161
971
|
function waiDirAt(root) {
|
|
1162
|
-
const wai =
|
|
1163
|
-
const legacy =
|
|
1164
|
-
return !
|
|
972
|
+
const wai = path5.join(root, ".wai");
|
|
973
|
+
const legacy = path5.join(root, ".wairon");
|
|
974
|
+
return !fs4.existsSync(wai) && fs4.existsSync(legacy) ? legacy : wai;
|
|
1165
975
|
}
|
|
1166
976
|
function projectConfigFsAdapterAt(rootDir) {
|
|
1167
|
-
const root =
|
|
1168
|
-
const file = () =>
|
|
977
|
+
const root = path5.resolve(rootDir);
|
|
978
|
+
const file = () => path5.join(waiDirAt(root), "project.yaml");
|
|
1169
979
|
return {
|
|
1170
980
|
readDocument() {
|
|
1171
981
|
return readYamlFile(file());
|
|
@@ -1174,7 +984,7 @@ function projectConfigFsAdapterAt(rootDir) {
|
|
|
1174
984
|
writeYamlFile(file(), document);
|
|
1175
985
|
},
|
|
1176
986
|
documentExists() {
|
|
1177
|
-
return
|
|
987
|
+
return fs4.existsSync(file());
|
|
1178
988
|
}
|
|
1179
989
|
};
|
|
1180
990
|
}
|
|
@@ -1373,15 +1183,15 @@ function indexOver(store, root) {
|
|
|
1373
1183
|
specsDir() {
|
|
1374
1184
|
try {
|
|
1375
1185
|
const declared = store.readField("paths.specsDir");
|
|
1376
|
-
if (declared) return
|
|
1186
|
+
if (declared) return path5.resolve(root, declared);
|
|
1377
1187
|
} catch {
|
|
1378
1188
|
}
|
|
1379
|
-
return
|
|
1189
|
+
return path5.join(waiDirAt(root), "specs");
|
|
1380
1190
|
}
|
|
1381
1191
|
};
|
|
1382
1192
|
}
|
|
1383
1193
|
function projectConfigRepositoryOver(adapter, rootDir) {
|
|
1384
|
-
const root =
|
|
1194
|
+
const root = path5.resolve(rootDir);
|
|
1385
1195
|
const store = storeOver(adapter, root);
|
|
1386
1196
|
const index = indexOver(store, root);
|
|
1387
1197
|
const registry = registryOver(store, root);
|
|
@@ -1436,7 +1246,7 @@ function projectConfigRepositoryAt(rootDir) {
|
|
|
1436
1246
|
function declaredPackNames(config) {
|
|
1437
1247
|
const selection = config.profileSelection;
|
|
1438
1248
|
return [.../* @__PURE__ */ new Set([
|
|
1439
|
-
...(config.extensions?.packs ?? []).map((entry) => typeof entry === "string" ?
|
|
1249
|
+
...(config.extensions?.packs ?? []).map((entry) => typeof entry === "string" ? path5.basename(entry).replace(PACK_EXT_RE, "") : entry.name),
|
|
1440
1250
|
...selection?.requiredPackNames ?? [],
|
|
1441
1251
|
...selection?.defaultPackNames ?? []
|
|
1442
1252
|
])];
|
|
@@ -1444,12 +1254,12 @@ function declaredPackNames(config) {
|
|
|
1444
1254
|
function declaredProfileIds(config) {
|
|
1445
1255
|
return [...new Set(config.profileSelection?.profileIds ?? [])];
|
|
1446
1256
|
}
|
|
1447
|
-
var
|
|
1257
|
+
var fs4, path5, import_zod4, USE_GLOBAL_PACKS_DEFAULT, bound, projectConfigRepository, PACK_EXT_RE;
|
|
1448
1258
|
var init_project_config = __esm({
|
|
1449
1259
|
"src/config/project-config.ts"() {
|
|
1450
1260
|
"use strict";
|
|
1451
|
-
|
|
1452
|
-
|
|
1261
|
+
fs4 = __toESM(require("fs"));
|
|
1262
|
+
path5 = __toESM(require("path"));
|
|
1453
1263
|
import_zod4 = require("zod");
|
|
1454
1264
|
init_fs();
|
|
1455
1265
|
init_yaml();
|
|
@@ -1514,12 +1324,12 @@ __export(paths_exports, {
|
|
|
1514
1324
|
isProjectInitialized: () => isProjectInitialized
|
|
1515
1325
|
});
|
|
1516
1326
|
function aiPathsAt(rootDir) {
|
|
1517
|
-
const resolvedRoot =
|
|
1327
|
+
const resolvedRoot = path6.resolve(rootDir);
|
|
1518
1328
|
const aiDirAt2 = (...segments) => {
|
|
1519
|
-
const waiPath =
|
|
1520
|
-
const waironPath =
|
|
1521
|
-
const base = !
|
|
1522
|
-
return
|
|
1329
|
+
const waiPath = path6.join(resolvedRoot, ".wai");
|
|
1330
|
+
const waironPath = path6.join(resolvedRoot, ".wairon");
|
|
1331
|
+
const base = !fs5.existsSync(waiPath) && fs5.existsSync(waironPath) ? waironPath : waiPath;
|
|
1332
|
+
return path6.join(base, ...segments);
|
|
1523
1333
|
};
|
|
1524
1334
|
const specsDir = () => projectConfigRepositoryAt(resolvedRoot).specsDir();
|
|
1525
1335
|
return {
|
|
@@ -1536,12 +1346,12 @@ function aiPathsAt(rootDir) {
|
|
|
1536
1346
|
contextDomainsMd: () => aiDirAt2("context", "domains.md"),
|
|
1537
1347
|
contextWaironGuideMd: () => aiDirAt2("context", "wairon-guide.md"),
|
|
1538
1348
|
specsDir,
|
|
1539
|
-
specsSystem: () =>
|
|
1540
|
-
specsSubsystemsDir: () =>
|
|
1541
|
-
specsComponentsDir: () =>
|
|
1542
|
-
specsInterfacesDir: () =>
|
|
1543
|
-
specsImplementationsDir: () =>
|
|
1544
|
-
specsTypesDir: () =>
|
|
1349
|
+
specsSystem: () => path6.join(specsDir(), ".index.yaml"),
|
|
1350
|
+
specsSubsystemsDir: () => path6.join(specsDir(), "subsystems"),
|
|
1351
|
+
specsComponentsDir: () => path6.join(specsDir(), "components"),
|
|
1352
|
+
specsInterfacesDir: () => path6.join(specsDir(), "interfaces"),
|
|
1353
|
+
specsImplementationsDir: () => path6.join(specsDir(), "implementations"),
|
|
1354
|
+
specsTypesDir: () => path6.join(specsDir(), "types")
|
|
1545
1355
|
};
|
|
1546
1356
|
}
|
|
1547
1357
|
function isProjectInitialized() {
|
|
@@ -1552,12 +1362,12 @@ function assertProjectInitialized() {
|
|
|
1552
1362
|
throw new ProjectNotInitializedError();
|
|
1553
1363
|
}
|
|
1554
1364
|
}
|
|
1555
|
-
var
|
|
1365
|
+
var fs5, path6, AI_PATHS;
|
|
1556
1366
|
var init_paths = __esm({
|
|
1557
1367
|
"src/config/paths.ts"() {
|
|
1558
1368
|
"use strict";
|
|
1559
|
-
|
|
1560
|
-
|
|
1369
|
+
fs5 = __toESM(require("fs"));
|
|
1370
|
+
path6 = __toESM(require("path"));
|
|
1561
1371
|
init_fs();
|
|
1562
1372
|
init_errors();
|
|
1563
1373
|
init_project_config();
|
|
@@ -1660,14 +1470,14 @@ function describeApprover(who) {
|
|
|
1660
1470
|
}
|
|
1661
1471
|
function readLockRecord() {
|
|
1662
1472
|
try {
|
|
1663
|
-
return normalizeRecord(JSON.parse(
|
|
1473
|
+
return normalizeRecord(JSON.parse(fs6.readFileSync(lockPath(), "utf8")));
|
|
1664
1474
|
} catch {
|
|
1665
1475
|
return null;
|
|
1666
1476
|
}
|
|
1667
1477
|
}
|
|
1668
1478
|
function readLockRecordAt(root) {
|
|
1669
1479
|
try {
|
|
1670
|
-
return normalizeRecord(JSON.parse(
|
|
1480
|
+
return normalizeRecord(JSON.parse(fs6.readFileSync(aiDirAt(root, "lock.json"), "utf8")));
|
|
1671
1481
|
} catch {
|
|
1672
1482
|
return null;
|
|
1673
1483
|
}
|
|
@@ -1678,10 +1488,10 @@ function normalizeRecord(raw) {
|
|
|
1678
1488
|
}
|
|
1679
1489
|
function writeLockRecord(record2) {
|
|
1680
1490
|
const p = lockPath();
|
|
1681
|
-
|
|
1491
|
+
fs6.mkdirSync(path7.dirname(p), { recursive: true });
|
|
1682
1492
|
const tmp = `${p}.tmp`;
|
|
1683
|
-
|
|
1684
|
-
|
|
1493
|
+
fs6.writeFileSync(tmp, JSON.stringify(withSortedMaps(record2), null, 2) + "\n");
|
|
1494
|
+
fs6.renameSync(tmp, p);
|
|
1685
1495
|
}
|
|
1686
1496
|
function withSortedMaps(record2) {
|
|
1687
1497
|
const sorted = (m) => {
|
|
@@ -1698,12 +1508,12 @@ function withSortedMaps(record2) {
|
|
|
1698
1508
|
...children ? { children } : {}
|
|
1699
1509
|
};
|
|
1700
1510
|
}
|
|
1701
|
-
var
|
|
1511
|
+
var fs6, path7;
|
|
1702
1512
|
var init_lockfile = __esm({
|
|
1703
1513
|
"src/core/lockfile.ts"() {
|
|
1704
1514
|
"use strict";
|
|
1705
|
-
|
|
1706
|
-
|
|
1515
|
+
fs6 = __toESM(require("fs"));
|
|
1516
|
+
path7 = __toESM(require("path"));
|
|
1707
1517
|
init_fs();
|
|
1708
1518
|
}
|
|
1709
1519
|
});
|
|
@@ -1719,25 +1529,25 @@ function listSpecFiles(specsDir) {
|
|
|
1719
1529
|
return listFilesRecursive(specsDir, SPEC_FILE_EXTENSION);
|
|
1720
1530
|
}
|
|
1721
1531
|
function removeSpecFile(filePath, specsRoot) {
|
|
1722
|
-
if (!
|
|
1723
|
-
|
|
1724
|
-
pruneEmptyDirs(
|
|
1532
|
+
if (!fs7.existsSync(filePath)) return false;
|
|
1533
|
+
fs7.unlinkSync(filePath);
|
|
1534
|
+
pruneEmptyDirs(path8.dirname(filePath), path8.resolve(specsRoot));
|
|
1725
1535
|
return true;
|
|
1726
1536
|
}
|
|
1727
1537
|
function pruneEmptyDirs(dir, specsRoot) {
|
|
1728
1538
|
let at = dir;
|
|
1729
1539
|
while (at !== specsRoot && at.startsWith(specsRoot)) {
|
|
1730
|
-
if (!
|
|
1731
|
-
|
|
1732
|
-
at =
|
|
1540
|
+
if (!fs7.existsSync(at) || fs7.readdirSync(at).length > 0) return;
|
|
1541
|
+
fs7.rmdirSync(at);
|
|
1542
|
+
at = path8.dirname(at);
|
|
1733
1543
|
}
|
|
1734
1544
|
}
|
|
1735
|
-
var
|
|
1545
|
+
var fs7, path8, SPEC_FILE_EXTENSION;
|
|
1736
1546
|
var init_spec_files = __esm({
|
|
1737
1547
|
"src/core/spec-files.ts"() {
|
|
1738
1548
|
"use strict";
|
|
1739
|
-
|
|
1740
|
-
|
|
1549
|
+
fs7 = __toESM(require("fs"));
|
|
1550
|
+
path8 = __toESM(require("path"));
|
|
1741
1551
|
init_fs();
|
|
1742
1552
|
init_yaml();
|
|
1743
1553
|
SPEC_FILE_EXTENSION = ".yaml";
|
|
@@ -3300,7 +3110,7 @@ function hasFunctionBody(facts, symbol) {
|
|
|
3300
3110
|
}
|
|
3301
3111
|
function resolveImport(fromFile, specifier, knownPaths) {
|
|
3302
3112
|
if (!specifier.startsWith(".")) return void 0;
|
|
3303
|
-
const joined = pathKey(
|
|
3113
|
+
const joined = pathKey(path9.posix.normalize(path9.posix.join(path9.posix.dirname(fromFile), specifier)));
|
|
3304
3114
|
const candidates = [
|
|
3305
3115
|
joined,
|
|
3306
3116
|
joined.replace(/\.js$/, ".ts"),
|
|
@@ -3316,11 +3126,11 @@ function resolveImport(fromFile, specifier, knownPaths) {
|
|
|
3316
3126
|
}
|
|
3317
3127
|
return void 0;
|
|
3318
3128
|
}
|
|
3319
|
-
var
|
|
3129
|
+
var path9, NO_DECLARED_TYPES;
|
|
3320
3130
|
var init_code_model = __esm({
|
|
3321
3131
|
"src/models/code-model.ts"() {
|
|
3322
3132
|
"use strict";
|
|
3323
|
-
|
|
3133
|
+
path9 = __toESM(require("path"));
|
|
3324
3134
|
NO_DECLARED_TYPES = [];
|
|
3325
3135
|
}
|
|
3326
3136
|
});
|
|
@@ -4099,14 +3909,14 @@ function embedJson(value) {
|
|
|
4099
3909
|
}
|
|
4100
3910
|
function loadCytoscapeLib() {
|
|
4101
3911
|
const candidates = [
|
|
4102
|
-
|
|
3912
|
+
path10.resolve(__dirname, "..", "templates", "canvas", "cytoscape.min.js"),
|
|
4103
3913
|
// src/core & dist/cli
|
|
4104
|
-
|
|
3914
|
+
path10.resolve(__dirname, "templates", "canvas", "cytoscape.min.js")
|
|
4105
3915
|
// dist (library entry)
|
|
4106
3916
|
];
|
|
4107
3917
|
for (const p of candidates) {
|
|
4108
|
-
if (
|
|
4109
|
-
return
|
|
3918
|
+
if (fs8.existsSync(p)) {
|
|
3919
|
+
return fs8.readFileSync(p, "utf-8").replace(/<\/script/gi, "<\\/script");
|
|
4110
3920
|
}
|
|
4111
3921
|
}
|
|
4112
3922
|
throw new Error("Vendored cytoscape bundle not found (templates/canvas/cytoscape.min.js) \u2014 the wairon installation is incomplete.");
|
|
@@ -4118,12 +3928,12 @@ function renderCanvasHtml(model) {
|
|
|
4118
3928
|
function escapeHtml(s) {
|
|
4119
3929
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4120
3930
|
}
|
|
4121
|
-
var
|
|
3931
|
+
var fs8, path10, CANVAS_TEMPLATE;
|
|
4122
3932
|
var init_canvas = __esm({
|
|
4123
3933
|
"src/core/canvas.ts"() {
|
|
4124
3934
|
"use strict";
|
|
4125
|
-
|
|
4126
|
-
|
|
3935
|
+
fs8 = __toESM(require("fs"));
|
|
3936
|
+
path10 = __toESM(require("path"));
|
|
4127
3937
|
init_specs2();
|
|
4128
3938
|
init_models();
|
|
4129
3939
|
init_diagram_export();
|
|
@@ -8318,7 +8128,7 @@ function packStoreDir() {
|
|
|
8318
8128
|
function packFiles(dir, prefix = "") {
|
|
8319
8129
|
let entries;
|
|
8320
8130
|
try {
|
|
8321
|
-
entries =
|
|
8131
|
+
entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
8322
8132
|
} catch {
|
|
8323
8133
|
return [];
|
|
8324
8134
|
}
|
|
@@ -8326,25 +8136,25 @@ function packFiles(dir, prefix = "") {
|
|
|
8326
8136
|
for (const e of entries) {
|
|
8327
8137
|
if (DIGEST_EXCLUDED.has(e.name)) continue;
|
|
8328
8138
|
const rel2 = prefix ? `${prefix}/${e.name}` : e.name;
|
|
8329
|
-
if (e.isDirectory()) out.push(...packFiles(
|
|
8139
|
+
if (e.isDirectory()) out.push(...packFiles(path11.join(dir, e.name), rel2));
|
|
8330
8140
|
else if (e.isFile()) out.push(rel2);
|
|
8331
8141
|
}
|
|
8332
8142
|
return out.sort();
|
|
8333
8143
|
}
|
|
8334
8144
|
function computePackDigest(packDir) {
|
|
8335
8145
|
const hash = crypto2.createHash("sha256");
|
|
8336
|
-
const abs =
|
|
8146
|
+
const abs = path11.resolve(packDir);
|
|
8337
8147
|
let isFile = false;
|
|
8338
8148
|
try {
|
|
8339
|
-
isFile =
|
|
8149
|
+
isFile = fs9.statSync(abs).isFile();
|
|
8340
8150
|
} catch {
|
|
8341
8151
|
}
|
|
8342
|
-
const entries = isFile ? [[
|
|
8152
|
+
const entries = isFile ? [[path11.basename(abs), abs]] : packFiles(abs).map((rel2) => [rel2, path11.join(abs, rel2)]);
|
|
8343
8153
|
for (const [rel2, full] of entries) {
|
|
8344
8154
|
hash.update(rel2);
|
|
8345
8155
|
hash.update("\0");
|
|
8346
8156
|
try {
|
|
8347
|
-
hash.update(
|
|
8157
|
+
hash.update(fs9.readFileSync(full));
|
|
8348
8158
|
} catch {
|
|
8349
8159
|
}
|
|
8350
8160
|
hash.update("\0");
|
|
@@ -8353,7 +8163,7 @@ function computePackDigest(packDir) {
|
|
|
8353
8163
|
}
|
|
8354
8164
|
function readInstallRecord(packPath) {
|
|
8355
8165
|
try {
|
|
8356
|
-
const raw = readYamlFile(
|
|
8166
|
+
const raw = readYamlFile(path11.join(packPath, INSTALL_RECORD));
|
|
8357
8167
|
return raw && typeof raw === "object" ? raw : {};
|
|
8358
8168
|
} catch {
|
|
8359
8169
|
return {};
|
|
@@ -8383,14 +8193,14 @@ function installedFrom(location, name, version) {
|
|
|
8383
8193
|
function versionedEntries(nameDir, fallbackName) {
|
|
8384
8194
|
let versions;
|
|
8385
8195
|
try {
|
|
8386
|
-
versions =
|
|
8196
|
+
versions = fs9.readdirSync(nameDir, { withFileTypes: true });
|
|
8387
8197
|
} catch {
|
|
8388
8198
|
return [];
|
|
8389
8199
|
}
|
|
8390
8200
|
const out = [];
|
|
8391
8201
|
for (const v of versions) {
|
|
8392
8202
|
if (!v.isDirectory()) continue;
|
|
8393
|
-
const versionDir =
|
|
8203
|
+
const versionDir = path11.join(nameDir, v.name);
|
|
8394
8204
|
const entryFile = packDirEntry(versionDir);
|
|
8395
8205
|
if (!entryFile) continue;
|
|
8396
8206
|
out.push(installedFrom(versionDir, declaredName(entryFile) ?? fallbackName, v.name));
|
|
@@ -8398,7 +8208,7 @@ function versionedEntries(nameDir, fallbackName) {
|
|
|
8398
8208
|
return out;
|
|
8399
8209
|
}
|
|
8400
8210
|
function storeEntryPacks(store, entry) {
|
|
8401
|
-
const full =
|
|
8211
|
+
const full = path11.join(store, entry.name);
|
|
8402
8212
|
if (entry.isFile()) {
|
|
8403
8213
|
if (!PACK_FILE_RE.test(entry.name)) return [];
|
|
8404
8214
|
const name = declaredName(full) ?? entry.name.replace(PACK_FILE_RE, "");
|
|
@@ -8413,7 +8223,7 @@ function listInstalledPacks() {
|
|
|
8413
8223
|
const store = packStoreDir();
|
|
8414
8224
|
let entries;
|
|
8415
8225
|
try {
|
|
8416
|
-
entries =
|
|
8226
|
+
entries = fs9.readdirSync(store, { withFileTypes: true });
|
|
8417
8227
|
} catch {
|
|
8418
8228
|
return [];
|
|
8419
8229
|
}
|
|
@@ -8430,17 +8240,17 @@ function resolveInstalledPack(name, version) {
|
|
|
8430
8240
|
return candidates[0];
|
|
8431
8241
|
}
|
|
8432
8242
|
function installPackFromDirectory(sourceDir, origin) {
|
|
8433
|
-
const abs =
|
|
8243
|
+
const abs = path11.resolve(sourceDir);
|
|
8434
8244
|
const entryFile = packDirEntry(abs);
|
|
8435
8245
|
if (!entryFile) {
|
|
8436
8246
|
throw new Error(`"${sourceDir}" is not a pack directory (no pack.yaml | pack.cjs | index.cjs | \u2026).`);
|
|
8437
8247
|
}
|
|
8438
|
-
const manifest = readManifest(entryFile,
|
|
8248
|
+
const manifest = readManifest(entryFile, path11.dirname(entryFile));
|
|
8439
8249
|
const version = manifest.version && manifest.version.length > 0 ? manifest.version : UNVERSIONED;
|
|
8440
|
-
const dest =
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8250
|
+
const dest = path11.join(packStoreDir(), manifest.name, version);
|
|
8251
|
+
fs9.rmSync(dest, { recursive: true, force: true });
|
|
8252
|
+
fs9.mkdirSync(path11.dirname(dest), { recursive: true });
|
|
8253
|
+
fs9.cpSync(abs, dest, { recursive: true });
|
|
8444
8254
|
const digest2 = computePackDigest(dest);
|
|
8445
8255
|
const record2 = {
|
|
8446
8256
|
origin,
|
|
@@ -8448,7 +8258,7 @@ function installPackFromDirectory(sourceDir, origin) {
|
|
|
8448
8258
|
waironVersion: WAIRON_VERSION,
|
|
8449
8259
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8450
8260
|
};
|
|
8451
|
-
writeYamlFile(
|
|
8261
|
+
writeYamlFile(path11.join(dest, INSTALL_RECORD), record2);
|
|
8452
8262
|
return {
|
|
8453
8263
|
name: manifest.name,
|
|
8454
8264
|
version,
|
|
@@ -8463,23 +8273,23 @@ function uninstallPack(name, version) {
|
|
|
8463
8273
|
const targets = listInstalledPacks().filter((p) => p.name === name && (!version || p.version === version));
|
|
8464
8274
|
if (targets.length === 0) return false;
|
|
8465
8275
|
for (const target of targets) {
|
|
8466
|
-
|
|
8467
|
-
const parent =
|
|
8468
|
-
if (
|
|
8276
|
+
fs9.rmSync(target.path, { recursive: true, force: true });
|
|
8277
|
+
const parent = path11.dirname(target.path);
|
|
8278
|
+
if (path11.resolve(parent) === path11.resolve(packStoreDir())) continue;
|
|
8469
8279
|
try {
|
|
8470
|
-
if (
|
|
8280
|
+
if (fs9.readdirSync(parent).length === 0) fs9.rmdirSync(parent);
|
|
8471
8281
|
} catch {
|
|
8472
8282
|
}
|
|
8473
8283
|
}
|
|
8474
8284
|
return true;
|
|
8475
8285
|
}
|
|
8476
|
-
var crypto2,
|
|
8286
|
+
var crypto2, fs9, path11, UNVERSIONED, INSTALL_RECORD, DIGEST_EXCLUDED, PACK_FILE_RE;
|
|
8477
8287
|
var init_packstore = __esm({
|
|
8478
8288
|
"src/core/packstore.ts"() {
|
|
8479
8289
|
"use strict";
|
|
8480
8290
|
crypto2 = __toESM(require("crypto"));
|
|
8481
|
-
|
|
8482
|
-
|
|
8291
|
+
fs9 = __toESM(require("fs"));
|
|
8292
|
+
path11 = __toESM(require("path"));
|
|
8483
8293
|
init_yaml();
|
|
8484
8294
|
init_defaults();
|
|
8485
8295
|
init_version();
|
|
@@ -8506,26 +8316,26 @@ function emptyExtensions() {
|
|
|
8506
8316
|
return { packNames: [], packs: [], rules: [], profiles: {}, languages: {}, skills: [], patterns: [], guarantees: [], assertions: [], instructions: [], errors: [], selectionFailures: [] };
|
|
8507
8317
|
}
|
|
8508
8318
|
function globalPacksDir() {
|
|
8509
|
-
return process.env.WAIRON_PACKS_DIR ??
|
|
8319
|
+
return process.env.WAIRON_PACKS_DIR ?? path12.join(os3.homedir(), ".wairon", "packs");
|
|
8510
8320
|
}
|
|
8511
8321
|
function packDirEntry(dir) {
|
|
8512
8322
|
for (const name of PACK_DIR_ENTRIES) {
|
|
8513
|
-
const p =
|
|
8514
|
-
if (
|
|
8323
|
+
const p = path12.join(dir, name);
|
|
8324
|
+
if (fs10.existsSync(p)) return p;
|
|
8515
8325
|
}
|
|
8516
8326
|
return null;
|
|
8517
8327
|
}
|
|
8518
8328
|
function latestVersionDir(nameDir) {
|
|
8519
8329
|
let versions;
|
|
8520
8330
|
try {
|
|
8521
|
-
versions =
|
|
8331
|
+
versions = fs10.readdirSync(nameDir, { withFileTypes: true });
|
|
8522
8332
|
} catch {
|
|
8523
8333
|
return null;
|
|
8524
8334
|
}
|
|
8525
8335
|
let best = null;
|
|
8526
8336
|
for (const v of versions) {
|
|
8527
8337
|
if (!v.isDirectory()) continue;
|
|
8528
|
-
const dir =
|
|
8338
|
+
const dir = path12.join(nameDir, v.name);
|
|
8529
8339
|
if (!packDirEntry(dir)) continue;
|
|
8530
8340
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
8531
8341
|
}
|
|
@@ -8534,13 +8344,13 @@ function latestVersionDir(nameDir) {
|
|
|
8534
8344
|
function discoverPacks(dir) {
|
|
8535
8345
|
let entries;
|
|
8536
8346
|
try {
|
|
8537
|
-
entries =
|
|
8347
|
+
entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
8538
8348
|
} catch {
|
|
8539
8349
|
return [];
|
|
8540
8350
|
}
|
|
8541
8351
|
const refs = [];
|
|
8542
8352
|
for (const e of entries.sort((a, b) => compareOrdinal(a.name, b.name))) {
|
|
8543
|
-
const full =
|
|
8353
|
+
const full = path12.join(dir, e.name);
|
|
8544
8354
|
if (e.isDirectory()) {
|
|
8545
8355
|
if (packDirEntry(full)) refs.push(full);
|
|
8546
8356
|
else {
|
|
@@ -8570,17 +8380,17 @@ function mergePack(out, pack, ref, scope, packDir) {
|
|
|
8570
8380
|
foreignBuiltins: [.../* @__PURE__ */ new Set([...existing.foreignBuiltins, ...def.foreignBuiltins])]
|
|
8571
8381
|
} : def;
|
|
8572
8382
|
}
|
|
8573
|
-
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath:
|
|
8383
|
+
for (const s of pack.skills) out.skills.push({ ...s, pack: pack.name, packVersion: pack.version, sourcePath: path12.resolve(packDir, s.source) });
|
|
8574
8384
|
for (const p of pack.patterns) out.patterns.push({ ...p, pack: pack.name });
|
|
8575
8385
|
out.guarantees = [.../* @__PURE__ */ new Set([...out.guarantees, ...pack.guarantees])];
|
|
8576
8386
|
for (const a of pack.assertions) out.assertions.push({ ...a, pack: pack.name, fullCode: assertionFullCode(pack.name, a.code) });
|
|
8577
8387
|
for (const b of pack.instructions) out.instructions.push({ ...b, pack: pack.name });
|
|
8578
8388
|
}
|
|
8579
8389
|
function resolvePackRef(ref, projectRoot2) {
|
|
8580
|
-
const pathLike = ref.startsWith(".") ||
|
|
8390
|
+
const pathLike = ref.startsWith(".") || path12.isAbsolute(ref) || isYamlPath(ref);
|
|
8581
8391
|
if (!pathLike) return ref;
|
|
8582
|
-
const resolved =
|
|
8583
|
-
if (
|
|
8392
|
+
const resolved = path12.resolve(projectRoot2, ref);
|
|
8393
|
+
if (fs10.existsSync(resolved) && fs10.statSync(resolved).isDirectory()) {
|
|
8584
8394
|
const entry = packDirEntry(resolved);
|
|
8585
8395
|
if (!entry) throw new Error(`directory pack has no entry file (${PACK_DIR_ENTRIES.join(" | ")})`);
|
|
8586
8396
|
return entry;
|
|
@@ -8593,7 +8403,7 @@ function readManifest(target, projectRoot2) {
|
|
|
8593
8403
|
if (raw == null) throw new Error("file not found or empty");
|
|
8594
8404
|
return { ...DeclarativePackSchema.parse(raw), rules: [] };
|
|
8595
8405
|
}
|
|
8596
|
-
const req = (0, import_module.createRequire)(
|
|
8406
|
+
const req = (0, import_module.createRequire)(path12.join(projectRoot2, "package.json"));
|
|
8597
8407
|
const modRaw = req(target);
|
|
8598
8408
|
const mod = modRaw?.default ?? modRaw;
|
|
8599
8409
|
const parsed = DeclarativePackSchema.parse({
|
|
@@ -8621,7 +8431,7 @@ function loadExtensionPacks(refs, projectRoot2) {
|
|
|
8621
8431
|
try {
|
|
8622
8432
|
const target = resolvePackRef(ref, projectRoot2);
|
|
8623
8433
|
const manifest = readManifest(target, projectRoot2);
|
|
8624
|
-
mergePack(out, manifest, ref, scope,
|
|
8434
|
+
mergePack(out, manifest, ref, scope, path12.dirname(target));
|
|
8625
8435
|
for (const r of manifest.rules) out.rules.push(r);
|
|
8626
8436
|
} catch (e) {
|
|
8627
8437
|
out.errors.push(`Extension pack "${ref}" failed to load: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -8664,7 +8474,7 @@ function defaultPackSelections() {
|
|
|
8664
8474
|
const entry = packDirEntry(pack.path) ?? pack.path;
|
|
8665
8475
|
let manifest;
|
|
8666
8476
|
try {
|
|
8667
|
-
manifest = readManifest(entry,
|
|
8477
|
+
manifest = readManifest(entry, path12.dirname(entry));
|
|
8668
8478
|
} catch {
|
|
8669
8479
|
continue;
|
|
8670
8480
|
}
|
|
@@ -8703,7 +8513,7 @@ function diagnoseProjectPacks() {
|
|
|
8703
8513
|
const globalsApplied = [];
|
|
8704
8514
|
if (globalsOn) {
|
|
8705
8515
|
for (const ref of discoverPacks(globalPacksDir())) {
|
|
8706
|
-
const match = installed.find((p) =>
|
|
8516
|
+
const match = installed.find((p) => path12.resolve(p.path) === path12.resolve(ref));
|
|
8707
8517
|
if (match) globalsApplied.push({ name: match.name, version: match.version });
|
|
8708
8518
|
}
|
|
8709
8519
|
}
|
|
@@ -8781,7 +8591,7 @@ function verifyIntegrity(selection, packDir, where) {
|
|
|
8781
8591
|
};
|
|
8782
8592
|
}
|
|
8783
8593
|
function detectBundleStoreDrift(selection, bundleDir) {
|
|
8784
|
-
const bundledVersion =
|
|
8594
|
+
const bundledVersion = path12.basename(bundleDir);
|
|
8785
8595
|
const installed = resolveInstalledPack(selection.name, bundledVersion);
|
|
8786
8596
|
if (!installed) return void 0;
|
|
8787
8597
|
const bundleDigest = computePackDigest(bundleDir);
|
|
@@ -8795,34 +8605,34 @@ function detectBundleStoreDrift(selection, bundleDir) {
|
|
|
8795
8605
|
};
|
|
8796
8606
|
}
|
|
8797
8607
|
function findBundledPack(projectRoot2, selection) {
|
|
8798
|
-
const base =
|
|
8608
|
+
const base = path12.join(projectRoot2, ".wai", "packs", selection.name);
|
|
8799
8609
|
if (selection.version) {
|
|
8800
|
-
const pinned =
|
|
8610
|
+
const pinned = path12.join(base, selection.version);
|
|
8801
8611
|
return packDirEntry(pinned) ? pinned : null;
|
|
8802
8612
|
}
|
|
8803
8613
|
if (packDirEntry(base)) return base;
|
|
8804
8614
|
let versions;
|
|
8805
8615
|
try {
|
|
8806
|
-
versions =
|
|
8616
|
+
versions = fs10.readdirSync(base, { withFileTypes: true });
|
|
8807
8617
|
} catch {
|
|
8808
8618
|
return null;
|
|
8809
8619
|
}
|
|
8810
8620
|
let best = null;
|
|
8811
8621
|
for (const v of versions) {
|
|
8812
8622
|
if (!v.isDirectory()) continue;
|
|
8813
|
-
const dir =
|
|
8623
|
+
const dir = path12.join(base, v.name);
|
|
8814
8624
|
if (!packDirEntry(dir)) continue;
|
|
8815
8625
|
if (!best || isNewerVersion(best.version, v.name)) best = { version: v.name, dir };
|
|
8816
8626
|
}
|
|
8817
8627
|
return best?.dir ?? null;
|
|
8818
8628
|
}
|
|
8819
|
-
var
|
|
8629
|
+
var fs10, os3, path12, import_module, import_zod9, ProfileDefSchema, LanguagePackDefSchema, PackSkillSchema, PackInstructionBlockSchema, PackInstructionsSchema, PatternDefSchema, AssertionSelectorSchema, assertionBase, PackAssertionSchema, DeclarativePackSchema, EXTENDABLE_BUILTIN_SKILLS, GLOBAL_PACKS_DEFAULT, PACK_DIR_ENTRIES, isYamlPath;
|
|
8820
8630
|
var init_extensions = __esm({
|
|
8821
8631
|
"src/core/extensions.ts"() {
|
|
8822
8632
|
"use strict";
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8633
|
+
fs10 = __toESM(require("fs"));
|
|
8634
|
+
os3 = __toESM(require("os"));
|
|
8635
|
+
path12 = __toESM(require("path"));
|
|
8826
8636
|
import_module = require("module");
|
|
8827
8637
|
import_zod9 = require("zod");
|
|
8828
8638
|
init_yaml();
|
|
@@ -15834,7 +15644,7 @@ function resolveTypeScript(projectRoot2) {
|
|
|
15834
15644
|
return cached.ts;
|
|
15835
15645
|
}
|
|
15836
15646
|
let ts = null;
|
|
15837
|
-
const bases = [
|
|
15647
|
+
const bases = [path13.join(projectRoot2, "package.json"), __filename];
|
|
15838
15648
|
for (const base of bases) {
|
|
15839
15649
|
try {
|
|
15840
15650
|
const req = (0, import_module2.createRequire)(base);
|
|
@@ -16049,7 +15859,7 @@ function walkExact(ts, sourceText, fileName) {
|
|
|
16049
15859
|
}
|
|
16050
15860
|
function resolveRelativeModule(fromFile, specifier) {
|
|
16051
15861
|
if (!specifier.startsWith(".")) return null;
|
|
16052
|
-
const base =
|
|
15862
|
+
const base = path13.resolve(path13.dirname(fromFile), specifier);
|
|
16053
15863
|
const candidates = [
|
|
16054
15864
|
base,
|
|
16055
15865
|
base.replace(/\.js$/, ".ts"),
|
|
@@ -16057,12 +15867,12 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
16057
15867
|
`${base}.ts`,
|
|
16058
15868
|
`${base}.tsx`,
|
|
16059
15869
|
`${base}.js`,
|
|
16060
|
-
|
|
16061
|
-
|
|
15870
|
+
path13.join(base, "index.ts"),
|
|
15871
|
+
path13.join(base, "index.js")
|
|
16062
15872
|
];
|
|
16063
15873
|
for (const c of candidates) {
|
|
16064
15874
|
try {
|
|
16065
|
-
if (
|
|
15875
|
+
if (fs11.statSync(c).isFile()) return c;
|
|
16066
15876
|
} catch {
|
|
16067
15877
|
}
|
|
16068
15878
|
}
|
|
@@ -16070,11 +15880,11 @@ function resolveRelativeModule(fromFile, specifier) {
|
|
|
16070
15880
|
}
|
|
16071
15881
|
function reexportTarget(ts, filePath, specifier, projectRoot2, visited, exactCache) {
|
|
16072
15882
|
const target = resolveRelativeModule(filePath, specifier);
|
|
16073
|
-
if (!target ||
|
|
15883
|
+
if (!target || path13.relative(projectRoot2, target).startsWith("..")) return null;
|
|
16074
15884
|
let targetFacts = exactCache.get(target);
|
|
16075
15885
|
if (targetFacts === void 0) {
|
|
16076
15886
|
try {
|
|
16077
|
-
targetFacts = walkExact(ts,
|
|
15887
|
+
targetFacts = walkExact(ts, fs11.readFileSync(target, "utf8"), target);
|
|
16078
15888
|
} catch {
|
|
16079
15889
|
targetFacts = null;
|
|
16080
15890
|
}
|
|
@@ -16092,7 +15902,7 @@ function carryBody(facts, target, targetPath, local, exported, projectRoot2) {
|
|
|
16092
15902
|
if (score !== void 0) facts.complexity.set(exported, Math.max(facts.complexity.get(exported) ?? 0, score));
|
|
16093
15903
|
const targetCalls = target.calls.get(local);
|
|
16094
15904
|
if (!targetCalls) return;
|
|
16095
|
-
const carriedFrom = pathKey(
|
|
15905
|
+
const carriedFrom = pathKey(path13.relative(projectRoot2, targetPath));
|
|
16096
15906
|
const sites = facts.calls.get(exported) ?? /* @__PURE__ */ new Map();
|
|
16097
15907
|
for (const [key, site] of targetCalls) sites.set(carriedFrom + "|" + key, { ...site, from: site.from ?? carriedFrom });
|
|
16098
15908
|
facts.calls.set(exported, sites);
|
|
@@ -16122,24 +15932,24 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
|
|
|
16122
15932
|
const excluded = exclude.map(pathKey);
|
|
16123
15933
|
const isExcluded = (key) => excluded.some((e) => key === e || key.startsWith(`${e}/`));
|
|
16124
15934
|
const record2 = (absolute) => {
|
|
16125
|
-
const key = pathKey(
|
|
15935
|
+
const key = pathKey(path13.relative(projectRoot2, absolute));
|
|
16126
15936
|
if (seen.has(key) || isExcluded(key)) return;
|
|
16127
|
-
if (!EXTENSION_LANGUAGE[
|
|
15937
|
+
if (!EXTENSION_LANGUAGE[path13.extname(key).toLowerCase()]) return;
|
|
16128
15938
|
seen.add(key);
|
|
16129
15939
|
found.push(key);
|
|
16130
15940
|
};
|
|
16131
15941
|
const descend = (dir) => {
|
|
16132
15942
|
let entries;
|
|
16133
15943
|
try {
|
|
16134
|
-
entries =
|
|
15944
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
16135
15945
|
} catch {
|
|
16136
15946
|
return;
|
|
16137
15947
|
}
|
|
16138
15948
|
for (const entry of entries.slice().sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
|
|
16139
|
-
const child =
|
|
15949
|
+
const child = path13.join(dir, entry.name);
|
|
16140
15950
|
if (entry.isDirectory()) {
|
|
16141
15951
|
if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
|
|
16142
|
-
if (isExcluded(pathKey(
|
|
15952
|
+
if (isExcluded(pathKey(path13.relative(projectRoot2, child)))) continue;
|
|
16143
15953
|
descend(child);
|
|
16144
15954
|
} else if (entry.isFile()) {
|
|
16145
15955
|
record2(child);
|
|
@@ -16148,13 +15958,13 @@ function walkDeclaredRoots(roots, exclude, projectRoot2) {
|
|
|
16148
15958
|
};
|
|
16149
15959
|
for (const root of roots) {
|
|
16150
15960
|
const key = pathKey(root);
|
|
16151
|
-
if (
|
|
16152
|
-
const absolute =
|
|
16153
|
-
if (
|
|
15961
|
+
if (path13.isAbsolute(key) || path13.normalize(key).split(path13.sep)[0] === "..") continue;
|
|
15962
|
+
const absolute = path13.resolve(projectRoot2, key);
|
|
15963
|
+
if (path13.relative(projectRoot2, absolute).startsWith("..")) continue;
|
|
16154
15964
|
if (isExcluded(key)) continue;
|
|
16155
15965
|
let stat;
|
|
16156
15966
|
try {
|
|
16157
|
-
stat =
|
|
15967
|
+
stat = fs11.statSync(absolute);
|
|
16158
15968
|
} catch {
|
|
16159
15969
|
continue;
|
|
16160
15970
|
}
|
|
@@ -16180,23 +15990,23 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16180
15990
|
if (seen.has(sourcePath)) continue;
|
|
16181
15991
|
seen.add(sourcePath);
|
|
16182
15992
|
const empty = { declaredNames: [], anchoredNames: [], exportedNames: [], imports: [], reexports: [] };
|
|
16183
|
-
if (
|
|
15993
|
+
if (path13.isAbsolute(sourcePath) || path13.normalize(sourcePath).split(path13.sep)[0] === "..") {
|
|
16184
15994
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
16185
15995
|
continue;
|
|
16186
15996
|
}
|
|
16187
|
-
const absolute =
|
|
16188
|
-
if (
|
|
15997
|
+
const absolute = path13.resolve(projectRoot2, sourcePath);
|
|
15998
|
+
if (path13.relative(projectRoot2, absolute).startsWith("..")) {
|
|
16189
15999
|
files.push({ path: sourcePath, status: "escaped", ...empty });
|
|
16190
16000
|
continue;
|
|
16191
16001
|
}
|
|
16192
16002
|
let buffer;
|
|
16193
16003
|
try {
|
|
16194
|
-
const stat =
|
|
16004
|
+
const stat = fs11.statSync(absolute);
|
|
16195
16005
|
if (!stat.isFile()) {
|
|
16196
16006
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
16197
16007
|
continue;
|
|
16198
16008
|
}
|
|
16199
|
-
buffer =
|
|
16009
|
+
buffer = fs11.readFileSync(absolute);
|
|
16200
16010
|
} catch {
|
|
16201
16011
|
files.push({ path: sourcePath, status: "missing", ...empty });
|
|
16202
16012
|
continue;
|
|
@@ -16206,7 +16016,7 @@ function buildCodeModel(implementations, types, projectRoot2, sourceRoots = [],
|
|
|
16206
16016
|
continue;
|
|
16207
16017
|
}
|
|
16208
16018
|
const text2 = buffer.toString("utf8");
|
|
16209
|
-
const language = EXTENSION_LANGUAGE[
|
|
16019
|
+
const language = EXTENSION_LANGUAGE[path13.extname(sourcePath).toLowerCase()];
|
|
16210
16020
|
let analyzed;
|
|
16211
16021
|
if (language === "typescript" || language === "javascript") {
|
|
16212
16022
|
const ts = resolveTypeScript(projectRoot2);
|
|
@@ -16250,7 +16060,7 @@ function readTestFiles(testRoots, projectRoot2) {
|
|
|
16250
16060
|
for (const key of walkDeclaredRoots(testRoots, [], projectRoot2)) {
|
|
16251
16061
|
let text2;
|
|
16252
16062
|
try {
|
|
16253
|
-
const buffer =
|
|
16063
|
+
const buffer = fs11.readFileSync(path13.resolve(projectRoot2, key));
|
|
16254
16064
|
if (looksBinary(buffer)) continue;
|
|
16255
16065
|
text2 = buffer.toString("utf8");
|
|
16256
16066
|
} catch {
|
|
@@ -16287,12 +16097,12 @@ function findTestsReferencing(methods, projectRoot2, testRoots = []) {
|
|
|
16287
16097
|
}
|
|
16288
16098
|
return found;
|
|
16289
16099
|
}
|
|
16290
|
-
var
|
|
16100
|
+
var fs11, path13, import_module2, EXTENSION_LANGUAGE, C_FAMILY_COMMENTS, NAMED_IMPORT_BINDINGS_RE, JS_PATTERNS, LANGUAGE_PATTERNS, PATTERN_ANALYSIS_MAX_BYTES, IDENTIFIER_RE, STRING_RE, tsResolutionCache, TS_RESOLUTION_RETRY_MS;
|
|
16291
16101
|
var init_source_analysis = __esm({
|
|
16292
16102
|
"src/core/source-analysis.ts"() {
|
|
16293
16103
|
"use strict";
|
|
16294
|
-
|
|
16295
|
-
|
|
16104
|
+
fs11 = __toESM(require("fs"));
|
|
16105
|
+
path13 = __toESM(require("path"));
|
|
16296
16106
|
import_module2 = require("module");
|
|
16297
16107
|
init_models();
|
|
16298
16108
|
EXTENSION_LANGUAGE = {
|
|
@@ -17062,28 +16872,28 @@ var init_gate_identity = __esm({
|
|
|
17062
16872
|
|
|
17063
16873
|
// src/core/variants.ts
|
|
17064
16874
|
function globalVariantsDir() {
|
|
17065
|
-
return process.env.WAIRON_VARIANTS_DIR ??
|
|
16875
|
+
return process.env.WAIRON_VARIANTS_DIR ?? path14.join(os4.homedir(), ".wairon", "variants");
|
|
17066
16876
|
}
|
|
17067
16877
|
function builtinVariantsDir() {
|
|
17068
16878
|
const candidates = [
|
|
17069
|
-
|
|
16879
|
+
path14.resolve(__dirname, "..", "templates", "variants"),
|
|
17070
16880
|
// src/core & dist/cli
|
|
17071
|
-
|
|
16881
|
+
path14.resolve(__dirname, "templates", "variants")
|
|
17072
16882
|
// dist (library entry)
|
|
17073
16883
|
];
|
|
17074
|
-
return candidates.find((dir) =>
|
|
16884
|
+
return candidates.find((dir) => fs12.existsSync(dir)) ?? candidates[0];
|
|
17075
16885
|
}
|
|
17076
16886
|
function projectVariantsDir() {
|
|
17077
|
-
return
|
|
16887
|
+
return path14.join(getProjectRoot(), ".wai", "variants");
|
|
17078
16888
|
}
|
|
17079
16889
|
function variantFiles(dir) {
|
|
17080
16890
|
let entries;
|
|
17081
16891
|
try {
|
|
17082
|
-
entries =
|
|
16892
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
17083
16893
|
} catch {
|
|
17084
16894
|
return [];
|
|
17085
16895
|
}
|
|
17086
|
-
return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) =>
|
|
16896
|
+
return entries.filter((e) => e.isFile() && /\.ya?ml$/i.test(e.name)).sort((a, b) => a.name.localeCompare(b.name)).map((e) => path14.join(dir, e.name));
|
|
17087
16897
|
}
|
|
17088
16898
|
function parseVariants(raw) {
|
|
17089
16899
|
if (raw == null) return [];
|
|
@@ -17192,13 +17002,13 @@ function rebasedText(content, fromBase, toBase, rebasedContent) {
|
|
|
17192
17002
|
}
|
|
17193
17003
|
return serializeYaml(rebasedContent);
|
|
17194
17004
|
}
|
|
17195
|
-
var
|
|
17005
|
+
var fs12, os4, path14, import_zod10, VariantDefSchema;
|
|
17196
17006
|
var init_variants = __esm({
|
|
17197
17007
|
"src/core/variants.ts"() {
|
|
17198
17008
|
"use strict";
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
|
|
17009
|
+
fs12 = __toESM(require("fs"));
|
|
17010
|
+
os4 = __toESM(require("os"));
|
|
17011
|
+
path14 = __toESM(require("path"));
|
|
17202
17012
|
import_zod10 = require("zod");
|
|
17203
17013
|
init_yaml();
|
|
17204
17014
|
init_fs();
|
|
@@ -17584,7 +17394,7 @@ var init_openapi = __esm({
|
|
|
17584
17394
|
|
|
17585
17395
|
// src/core/surfaces.ts
|
|
17586
17396
|
function surfacesDir(rootDir) {
|
|
17587
|
-
return
|
|
17397
|
+
return path15.join(rootDir, ".wai", SURFACES_DIRNAME);
|
|
17588
17398
|
}
|
|
17589
17399
|
function audienceRank(audience) {
|
|
17590
17400
|
const idx = SURFACE_AUDIENCES.indexOf(audience ?? "instance");
|
|
@@ -17742,12 +17552,12 @@ function projectSubsystemSurface(subsystemId) {
|
|
|
17742
17552
|
}
|
|
17743
17553
|
function listSnapshots(rootDir = getProjectRoot()) {
|
|
17744
17554
|
const dir = surfacesDir(rootDir);
|
|
17745
|
-
if (!
|
|
17555
|
+
if (!fs13.existsSync(dir)) return [];
|
|
17746
17556
|
const out = [];
|
|
17747
|
-
for (const file of
|
|
17557
|
+
for (const file of fs13.readdirSync(dir)) {
|
|
17748
17558
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
17749
17559
|
try {
|
|
17750
|
-
out.push(SurfaceSnapshotSchema.parse(readYamlFile(
|
|
17560
|
+
out.push(SurfaceSnapshotSchema.parse(readYamlFile(path15.join(dir, file))));
|
|
17751
17561
|
} catch {
|
|
17752
17562
|
}
|
|
17753
17563
|
}
|
|
@@ -17758,10 +17568,10 @@ function snapshotFilename(projectName) {
|
|
|
17758
17568
|
}
|
|
17759
17569
|
function writeSnapshotIfChanged(snapshot, rootDir) {
|
|
17760
17570
|
const dir = surfacesDir(rootDir);
|
|
17761
|
-
|
|
17762
|
-
const p =
|
|
17571
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
17572
|
+
const p = path15.join(dir, snapshotFilename(snapshot.projectName));
|
|
17763
17573
|
const next = SurfaceSnapshotSchema.parse(snapshot);
|
|
17764
|
-
if (
|
|
17574
|
+
if (fs13.existsSync(p)) {
|
|
17765
17575
|
try {
|
|
17766
17576
|
const existing = SurfaceSnapshotSchema.parse(readYamlFile(p));
|
|
17767
17577
|
if (surfaceContentKey(existing) === surfaceContentKey(next)) {
|
|
@@ -17780,11 +17590,11 @@ function loadSurfaceSnapshots() {
|
|
|
17780
17590
|
return listSnapshots();
|
|
17781
17591
|
}
|
|
17782
17592
|
function listMountSnapshots(mounts) {
|
|
17783
|
-
const bound2 =
|
|
17593
|
+
const bound2 = path15.resolve(getProjectRoot());
|
|
17784
17594
|
const out = [];
|
|
17785
17595
|
for (const namespace of mounts) {
|
|
17786
17596
|
const dir = resolveSubprojectForNamespace(namespace);
|
|
17787
|
-
if (!dir ||
|
|
17597
|
+
if (!dir || path15.resolve(dir) === bound2) continue;
|
|
17788
17598
|
const snapshots = listSnapshots(dir);
|
|
17789
17599
|
if (snapshots.length > 0) out.push({ namespace, snapshots });
|
|
17790
17600
|
}
|
|
@@ -17802,24 +17612,24 @@ function selectPortalSpec(renderedSet, portalId) {
|
|
|
17802
17612
|
return [hit];
|
|
17803
17613
|
}
|
|
17804
17614
|
function perPortalPath(resolvedOut, portalId) {
|
|
17805
|
-
const ext =
|
|
17615
|
+
const ext = path15.extname(resolvedOut);
|
|
17806
17616
|
const stem2 = ext ? resolvedOut.slice(0, -ext.length) : resolvedOut;
|
|
17807
17617
|
return `${stem2}.${safeFilenamePart(portalId)}${ext}`;
|
|
17808
17618
|
}
|
|
17809
17619
|
function writeSurfaceFile(outPath, snapshot, renderedSet) {
|
|
17810
|
-
const resolved =
|
|
17811
|
-
|
|
17620
|
+
const resolved = path15.resolve(outPath);
|
|
17621
|
+
fs13.mkdirSync(path15.dirname(resolved), { recursive: true });
|
|
17812
17622
|
if (!renderedSet || renderedSet.length === 0) {
|
|
17813
17623
|
writeYamlFile(resolved, snapshot);
|
|
17814
17624
|
return [resolved];
|
|
17815
17625
|
}
|
|
17816
17626
|
if (renderedSet.length === 1) {
|
|
17817
|
-
|
|
17627
|
+
fs13.writeFileSync(resolved, renderedSet[0].document);
|
|
17818
17628
|
return [resolved];
|
|
17819
17629
|
}
|
|
17820
17630
|
return renderedSet.map((spec) => {
|
|
17821
17631
|
const target = perPortalPath(resolved, spec.portalId);
|
|
17822
|
-
|
|
17632
|
+
fs13.writeFileSync(target, spec.document);
|
|
17823
17633
|
return target;
|
|
17824
17634
|
});
|
|
17825
17635
|
}
|
|
@@ -17841,14 +17651,14 @@ function exportSurface(maxAudience, format, outPath, portalId) {
|
|
|
17841
17651
|
return exportResult(snapshot, renderedSet, writtenPaths);
|
|
17842
17652
|
}
|
|
17843
17653
|
function importSurface(sourcePath, origin) {
|
|
17844
|
-
const resolved =
|
|
17845
|
-
if (!
|
|
17654
|
+
const resolved = path15.resolve(sourcePath);
|
|
17655
|
+
if (!fs13.existsSync(resolved)) {
|
|
17846
17656
|
throw new Error(`Surface document not found: ${resolved}`);
|
|
17847
17657
|
}
|
|
17848
|
-
const body =
|
|
17658
|
+
const body = fs13.readFileSync(resolved, "utf8");
|
|
17849
17659
|
let snapshot;
|
|
17850
17660
|
if (isOpenApiDocument(body)) {
|
|
17851
|
-
const projectName =
|
|
17661
|
+
const projectName = path15.basename(resolved).replace(/\.(json|ya?ml)$/i, "");
|
|
17852
17662
|
snapshot = fromOpenApi(body, projectName);
|
|
17853
17663
|
snapshot = { ...snapshot, origin };
|
|
17854
17664
|
} else {
|
|
@@ -17911,12 +17721,12 @@ function surfaceContentKey(snapshot) {
|
|
|
17911
17721
|
const { stateId, generatedAt, origin, ...content } = snapshot;
|
|
17912
17722
|
return JSON.stringify(content);
|
|
17913
17723
|
}
|
|
17914
|
-
var
|
|
17724
|
+
var fs13, path15, SURFACES_DIRNAME, CROSS_BOUNDARY_TARGETS;
|
|
17915
17725
|
var init_surfaces = __esm({
|
|
17916
17726
|
"src/core/surfaces.ts"() {
|
|
17917
17727
|
"use strict";
|
|
17918
|
-
|
|
17919
|
-
|
|
17728
|
+
fs13 = __toESM(require("fs"));
|
|
17729
|
+
path15 = __toESM(require("path"));
|
|
17920
17730
|
init_fs();
|
|
17921
17731
|
init_yaml();
|
|
17922
17732
|
init_filenames();
|
|
@@ -18222,13 +18032,13 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
|
|
|
18222
18032
|
function resolveThroughParent(boundRoot, treatAllAsComplete, childRules) {
|
|
18223
18033
|
const reach = getRequestParentReach();
|
|
18224
18034
|
if (reach && !reach.parentReach) return null;
|
|
18225
|
-
const ceiling = reach?.topRoot ?
|
|
18035
|
+
const ceiling = reach?.topRoot ? path16.resolve(reach.topRoot) : void 0;
|
|
18226
18036
|
const chain = [];
|
|
18227
|
-
let top =
|
|
18037
|
+
let top = path16.resolve(boundRoot);
|
|
18228
18038
|
while (top !== ceiling) {
|
|
18229
18039
|
const hop = findChainingParent(top, ceiling);
|
|
18230
18040
|
if (!hop) break;
|
|
18231
|
-
const next =
|
|
18041
|
+
const next = path16.resolve(hop.parentRoot);
|
|
18232
18042
|
if (ceiling && !isWithinOrEqual(ceiling, next)) break;
|
|
18233
18043
|
chain.unshift(hop.subsystemId);
|
|
18234
18044
|
top = next;
|
|
@@ -18275,8 +18085,8 @@ function isIdChar(ch) {
|
|
|
18275
18085
|
return ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "_" || ch === "-" || ch === "." || ch === ":";
|
|
18276
18086
|
}
|
|
18277
18087
|
function isWithinOrEqual(dir, target) {
|
|
18278
|
-
const rel2 =
|
|
18279
|
-
return rel2 === "" || !rel2.startsWith("..") && !
|
|
18088
|
+
const rel2 = path16.relative(dir, target);
|
|
18089
|
+
return rel2 === "" || !rel2.startsWith("..") && !path16.isAbsolute(rel2);
|
|
18280
18090
|
}
|
|
18281
18091
|
function dedupeIssues(list2) {
|
|
18282
18092
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -18297,7 +18107,7 @@ function settledStatusBearing(loaded) {
|
|
|
18297
18107
|
if (!settled || settled.size === 0) return [];
|
|
18298
18108
|
const root = getProjectRoot();
|
|
18299
18109
|
const index = scanAllSpecs();
|
|
18300
|
-
const rel2 = (abs) =>
|
|
18110
|
+
const rel2 = (abs) => path16.relative(root, abs).split(path16.sep).join("/");
|
|
18301
18111
|
const out = [];
|
|
18302
18112
|
const take = (specs, paths) => {
|
|
18303
18113
|
for (const spec of specs) {
|
|
@@ -18327,7 +18137,7 @@ function computeGateStateId() {
|
|
|
18327
18137
|
registerBuiltinRules();
|
|
18328
18138
|
return computeGateIdentity(content, extensions, ruleSequence(), inputs, gate);
|
|
18329
18139
|
}
|
|
18330
|
-
var
|
|
18140
|
+
var path16, RESOLUTION_FAILURE_CODES, SEVERITY_RANK;
|
|
18331
18141
|
var init_validation = __esm({
|
|
18332
18142
|
"src/core/validation.ts"() {
|
|
18333
18143
|
"use strict";
|
|
@@ -18343,7 +18153,7 @@ var init_validation = __esm({
|
|
|
18343
18153
|
init_source_analysis();
|
|
18344
18154
|
init_specs2();
|
|
18345
18155
|
init_fs();
|
|
18346
|
-
|
|
18156
|
+
path16 = __toESM(require("path"));
|
|
18347
18157
|
init_core();
|
|
18348
18158
|
RESOLUTION_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
18349
18159
|
"UNDEFINED_TYPE_REFERENCE",
|
|
@@ -19063,42 +18873,42 @@ function rebaseReference(ref, mount, direction, isMoved = () => false) {
|
|
|
19063
18873
|
return relativizeId(travels ? qualifyId(left, to, NO_ROOT_SUBSYSTEMS) : target, to);
|
|
19064
18874
|
}
|
|
19065
18875
|
function isWithin(dir, file) {
|
|
19066
|
-
const d =
|
|
19067
|
-
const f =
|
|
19068
|
-
return f === d || f.startsWith(d +
|
|
18876
|
+
const d = path17.resolve(dir);
|
|
18877
|
+
const f = path17.resolve(file);
|
|
18878
|
+
return f === d || f.startsWith(d + path17.sep);
|
|
19069
18879
|
}
|
|
19070
18880
|
function canonicalPath(target) {
|
|
19071
|
-
let existing =
|
|
18881
|
+
let existing = path17.resolve(target);
|
|
19072
18882
|
const rest = [];
|
|
19073
18883
|
for (; ; ) {
|
|
19074
18884
|
try {
|
|
19075
|
-
|
|
18885
|
+
fs14.lstatSync(existing);
|
|
19076
18886
|
break;
|
|
19077
18887
|
} catch {
|
|
19078
|
-
const up =
|
|
19079
|
-
if (up === existing) return
|
|
19080
|
-
rest.unshift(
|
|
18888
|
+
const up = path17.dirname(existing);
|
|
18889
|
+
if (up === existing) return path17.resolve(target);
|
|
18890
|
+
rest.unshift(path17.basename(existing));
|
|
19081
18891
|
existing = up;
|
|
19082
18892
|
}
|
|
19083
18893
|
}
|
|
19084
18894
|
try {
|
|
19085
|
-
return
|
|
18895
|
+
return path17.join(fs14.realpathSync.native(existing), ...rest);
|
|
19086
18896
|
} catch {
|
|
19087
18897
|
return null;
|
|
19088
18898
|
}
|
|
19089
18899
|
}
|
|
19090
18900
|
function chainDirKey(dir) {
|
|
19091
|
-
return canonicalPath(dir) ??
|
|
18901
|
+
return canonicalPath(dir) ?? path17.resolve(dir);
|
|
19092
18902
|
}
|
|
19093
18903
|
function projectPathEscapesRoot(projectRoot2, projectPath, resolvedChildDir) {
|
|
19094
|
-
if (
|
|
18904
|
+
if (path17.isAbsolute(projectPath) || !isWithin(projectRoot2, resolvedChildDir)) return true;
|
|
19095
18905
|
const root = canonicalPath(projectRoot2);
|
|
19096
18906
|
const child = canonicalPath(resolvedChildDir);
|
|
19097
18907
|
return root === null || child === null || !isWithin(root, child);
|
|
19098
18908
|
}
|
|
19099
18909
|
function assertContainedProjectPath(projectRoot2, projectPath) {
|
|
19100
|
-
const root =
|
|
19101
|
-
const resolved =
|
|
18910
|
+
const root = path17.resolve(projectRoot2);
|
|
18911
|
+
const resolved = path17.resolve(root, projectPath);
|
|
19102
18912
|
if (projectPathEscapesRoot(root, projectPath, resolved)) {
|
|
19103
18913
|
throw new Error(
|
|
19104
18914
|
`projectPath "${projectPath}" must resolve within the project root "${root}", but resolves to "${resolved}"; absolute, ../-escaping and link-escaping paths are rejected so a chained subproject is always contained by its parent.`
|
|
@@ -19109,12 +18919,12 @@ function assertContainedProjectPath(projectRoot2, projectPath) {
|
|
|
19109
18919
|
function findChainingParent(childRoot, ceiling) {
|
|
19110
18920
|
let childResolved;
|
|
19111
18921
|
try {
|
|
19112
|
-
childResolved =
|
|
18922
|
+
childResolved = path17.resolve(childRoot);
|
|
19113
18923
|
} catch {
|
|
19114
18924
|
return null;
|
|
19115
18925
|
}
|
|
19116
|
-
const bound2 = ceiling ?
|
|
19117
|
-
let dir =
|
|
18926
|
+
const bound2 = ceiling ? path17.resolve(ceiling) : void 0;
|
|
18927
|
+
let dir = path17.dirname(childResolved);
|
|
19118
18928
|
for (let hops = 0; hops < 32; hops++) {
|
|
19119
18929
|
if (bound2 && !isWithin(bound2, dir)) break;
|
|
19120
18930
|
const specsDir = aiPathsAt(dir).specsDir();
|
|
@@ -19130,7 +18940,7 @@ function findChainingParent(childRoot, ceiling) {
|
|
|
19130
18940
|
const projectPath = raw.projectPath;
|
|
19131
18941
|
if (typeof projectPath === "string" && projectPath.trim() !== "") {
|
|
19132
18942
|
try {
|
|
19133
|
-
const mountDir =
|
|
18943
|
+
const mountDir = path17.resolve(dir, projectPath);
|
|
19134
18944
|
if (mountDir === childResolved && !projectPathEscapesRoot(dir, projectPath, mountDir)) {
|
|
19135
18945
|
const id = raw.id;
|
|
19136
18946
|
return { parentRoot: dir, subsystemId: typeof id === "string" ? id : "?" };
|
|
@@ -19141,14 +18951,14 @@ function findChainingParent(childRoot, ceiling) {
|
|
|
19141
18951
|
}
|
|
19142
18952
|
}
|
|
19143
18953
|
}
|
|
19144
|
-
const up =
|
|
18954
|
+
const up = path17.dirname(dir);
|
|
19145
18955
|
if (up === dir) break;
|
|
19146
18956
|
dir = up;
|
|
19147
18957
|
}
|
|
19148
18958
|
return null;
|
|
19149
18959
|
}
|
|
19150
18960
|
function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
19151
|
-
const root =
|
|
18961
|
+
const root = path17.resolve(rootDir);
|
|
19152
18962
|
const inspection = { roots: [], skipped: [] };
|
|
19153
18963
|
const listed = /* @__PURE__ */ new Set();
|
|
19154
18964
|
const walk2 = (projectDir, prefix, ancestors, depth) => {
|
|
@@ -19167,14 +18977,14 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
19167
18977
|
const localId = typeof id === "string" ? id : "?";
|
|
19168
18978
|
let childDir;
|
|
19169
18979
|
try {
|
|
19170
|
-
childDir =
|
|
18980
|
+
childDir = path17.resolve(projectDir, projectPath);
|
|
19171
18981
|
} catch {
|
|
19172
18982
|
continue;
|
|
19173
18983
|
}
|
|
19174
18984
|
let reason;
|
|
19175
18985
|
if (projectPathEscapesRoot(projectDir, projectPath, childDir)) reason = "escapes";
|
|
19176
18986
|
else if (ancestors.has(chainDirKey(childDir))) reason = "cyclic";
|
|
19177
|
-
else if (!
|
|
18987
|
+
else if (!fs14.existsSync(childDir)) reason = "missing";
|
|
19178
18988
|
else if (depth >= 32) reason = "too-deep";
|
|
19179
18989
|
if (reason) {
|
|
19180
18990
|
const mount = prefix ? qualifyDeclaredId(localId, prefix, true) : localId;
|
|
@@ -19184,7 +18994,7 @@ function inspectChainedRoots(rootDir = getProjectRoot()) {
|
|
|
19184
18994
|
const key = chainDirKey(childDir);
|
|
19185
18995
|
if (listed.has(key)) continue;
|
|
19186
18996
|
listed.add(key);
|
|
19187
|
-
inspection.roots.push(
|
|
18997
|
+
inspection.roots.push(path17.relative(root, childDir).split(path17.sep).join("/"));
|
|
19188
18998
|
walk2(childDir, prefix ? `${prefix}::${localId}` : localId, /* @__PURE__ */ new Set([...ancestors, key]), depth + 1);
|
|
19189
18999
|
}
|
|
19190
19000
|
};
|
|
@@ -19270,9 +19080,9 @@ function stripNamespaceFromImplementation(spec, prefix) {
|
|
|
19270
19080
|
}
|
|
19271
19081
|
function childRelativeFilePaths(spec, authoringRoot, childRoot) {
|
|
19272
19082
|
const reexpress = (p) => {
|
|
19273
|
-
if (
|
|
19274
|
-
const rel2 =
|
|
19275
|
-
const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${
|
|
19083
|
+
if (path17.isAbsolute(p)) return p;
|
|
19084
|
+
const rel2 = path17.relative(childRoot, path17.resolve(authoringRoot, p));
|
|
19085
|
+
const inside = rel2 !== "" && rel2 !== ".." && !rel2.startsWith(`..${path17.sep}`) && !path17.isAbsolute(rel2);
|
|
19276
19086
|
return inside ? rel2.replace(/\\/g, "/") : p;
|
|
19277
19087
|
};
|
|
19278
19088
|
return {
|
|
@@ -19307,10 +19117,10 @@ function findOwner(id, components) {
|
|
|
19307
19117
|
}) ?? null;
|
|
19308
19118
|
}
|
|
19309
19119
|
function moveComponentFolder(fromDir, toDir) {
|
|
19310
|
-
if (
|
|
19311
|
-
if (!
|
|
19312
|
-
ensureDir(
|
|
19313
|
-
|
|
19120
|
+
if (path17.normalize(fromDir) === path17.normalize(toDir)) return false;
|
|
19121
|
+
if (!fs14.existsSync(fromDir) || fs14.existsSync(toDir)) return false;
|
|
19122
|
+
ensureDir(path17.dirname(toDir));
|
|
19123
|
+
fs14.renameSync(fromDir, toDir);
|
|
19314
19124
|
return true;
|
|
19315
19125
|
}
|
|
19316
19126
|
function formatZodIssues(error) {
|
|
@@ -19326,13 +19136,13 @@ function parseOrThrow(schema, value, kind, id) {
|
|
|
19326
19136
|
function computeSpecTreeSignature(dirs) {
|
|
19327
19137
|
const parts = [];
|
|
19328
19138
|
for (const dir of dirs) {
|
|
19329
|
-
if (!
|
|
19139
|
+
if (!fs14.existsSync(dir)) {
|
|
19330
19140
|
parts.push(`${dir}:missing`);
|
|
19331
19141
|
continue;
|
|
19332
19142
|
}
|
|
19333
19143
|
for (const f of listSpecFiles(dir)) {
|
|
19334
19144
|
try {
|
|
19335
|
-
const st =
|
|
19145
|
+
const st = fs14.statSync(f);
|
|
19336
19146
|
parts.push(`${f}:${st.mtimeMs}:${st.size}`);
|
|
19337
19147
|
} catch {
|
|
19338
19148
|
parts.push(`${f}:gone`);
|
|
@@ -19725,7 +19535,7 @@ function refusedMoveSummary(from, to, methods, refusals, alternatives) {
|
|
|
19725
19535
|
return `Refused: moving ${namedMethods(methods)} from "${from}" to "${to}" is refused by ${refusals.join(", ")}. Nothing was written. ` + (cheapest ? `The cheapest legal home is "${cheapest.component}" (${cheapest.newDependencies.length} new dependenc${cheapest.newDependencies.length === 1 ? "y" : "ies"}, ${cheapest.dependencyCount} of ${cheapest.dependencyLimit}).` : `No component of this subsystem can take them as they stand \u2014 ${alternatives.length} were weighed.`);
|
|
19726
19536
|
}
|
|
19727
19537
|
function workspaceFor(rootDir) {
|
|
19728
|
-
const key =
|
|
19538
|
+
const key = path17.resolve(rootDir);
|
|
19729
19539
|
let ws = workspaces.get(key);
|
|
19730
19540
|
if (!ws) {
|
|
19731
19541
|
ws = new SpecWorkspace(key);
|
|
@@ -19855,13 +19665,13 @@ function snapshotInputKey(snapshot) {
|
|
|
19855
19665
|
return canonicalize(content);
|
|
19856
19666
|
}
|
|
19857
19667
|
function consumedSurfaceInputsAt(rootDir) {
|
|
19858
|
-
const dir =
|
|
19668
|
+
const dir = path17.join(rootDir, ".wai", "surfaces");
|
|
19859
19669
|
if (!pathExists(dir)) return [];
|
|
19860
19670
|
const keys = [];
|
|
19861
|
-
for (const file of
|
|
19671
|
+
for (const file of fs14.readdirSync(dir)) {
|
|
19862
19672
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) continue;
|
|
19863
19673
|
try {
|
|
19864
|
-
keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(
|
|
19674
|
+
keys.push(snapshotInputKey(SurfaceSnapshotSchema.parse(readYamlFile(path17.join(dir, file)))));
|
|
19865
19675
|
} catch {
|
|
19866
19676
|
}
|
|
19867
19677
|
}
|
|
@@ -19869,7 +19679,7 @@ function consumedSurfaceInputsAt(rootDir) {
|
|
|
19869
19679
|
}
|
|
19870
19680
|
function consumedContractInputs() {
|
|
19871
19681
|
const root = getProjectRoot();
|
|
19872
|
-
const roots = [root, ...listChainedRoots(root).map((rel2) =>
|
|
19682
|
+
const roots = [root, ...listChainedRoots(root).map((rel2) => path17.join(root, rel2))];
|
|
19873
19683
|
return roots.flatMap(consumedSurfaceInputsAt);
|
|
19874
19684
|
}
|
|
19875
19685
|
function readLockState(current2) {
|
|
@@ -19905,7 +19715,7 @@ function markSelectionsBundled(bundled) {
|
|
|
19905
19715
|
projectConfigRepository.markSelectionsBundled(bundled);
|
|
19906
19716
|
}
|
|
19907
19717
|
function computeStateIdAt(root) {
|
|
19908
|
-
const resolved =
|
|
19718
|
+
const resolved = path17.resolve(root);
|
|
19909
19719
|
return runWithProjectRoot(resolved, () => {
|
|
19910
19720
|
workspaceFor(resolved).invalidate();
|
|
19911
19721
|
const system = loadSystemSpec();
|
|
@@ -19943,7 +19753,7 @@ function snapshotSpecFiles() {
|
|
|
19943
19753
|
}
|
|
19944
19754
|
function restoreSpecFiles(snapshot) {
|
|
19945
19755
|
for (const [file, content] of snapshot) {
|
|
19946
|
-
|
|
19756
|
+
fs14.writeFileSync(file, content);
|
|
19947
19757
|
}
|
|
19948
19758
|
}
|
|
19949
19759
|
function findLegacySpecFiles() {
|
|
@@ -19955,12 +19765,12 @@ function updateSpec(kind, id, delta, hooks, dryRun) {
|
|
|
19955
19765
|
function moveMethods(from, to, methods, hooks, dryRun) {
|
|
19956
19766
|
return current().moveMethods(from, to, methods, hooks, dryRun);
|
|
19957
19767
|
}
|
|
19958
|
-
var
|
|
19768
|
+
var fs14, path17, NO_ROOT_SUBSYSTEMS, SIGNATURE_TTL_MS, COMPONENT_AUTH_SOURCE, DELTA_VERBS, JUMP_LABEL_TWINS, LABEL_TWIN_CONTAINERS, SpecWorkspace, DEFAULT_DEPENDENCY_LIMIT, PROSE_FIELDS, workspaces;
|
|
19959
19769
|
var init_specs2 = __esm({
|
|
19960
19770
|
"src/core/specs.ts"() {
|
|
19961
19771
|
"use strict";
|
|
19962
|
-
|
|
19963
|
-
|
|
19772
|
+
fs14 = __toESM(require("fs"));
|
|
19773
|
+
path17 = __toESM(require("path"));
|
|
19964
19774
|
init_paths();
|
|
19965
19775
|
init_project_config();
|
|
19966
19776
|
init_fs();
|
|
@@ -19995,7 +19805,7 @@ var init_specs2 = __esm({
|
|
|
19995
19805
|
this.rootSubsystems = /* @__PURE__ */ new Set();
|
|
19996
19806
|
this.scanVisitedSpecDirs = [];
|
|
19997
19807
|
this.loaderIssues = [];
|
|
19998
|
-
this.rootDir =
|
|
19808
|
+
this.rootDir = path17.resolve(rootDir);
|
|
19999
19809
|
this.paths = aiPathsAt(this.rootDir);
|
|
20000
19810
|
}
|
|
20001
19811
|
invalidate() {
|
|
@@ -20038,8 +19848,8 @@ var init_specs2 = __esm({
|
|
|
20038
19848
|
* qualifies the spec itself — so scoping a validate to a mount keeps it.
|
|
20039
19849
|
*/
|
|
20040
19850
|
loaderIssueSpecId(file, rawId, namespacePrefix) {
|
|
20041
|
-
const stem2 =
|
|
20042
|
-
const local = rawId ?? (stem2.startsWith(".") ?
|
|
19851
|
+
const stem2 = path17.basename(file, ".yaml");
|
|
19852
|
+
const local = rawId ?? (stem2.startsWith(".") ? path17.basename(path17.dirname(file)) : stem2);
|
|
20043
19853
|
return namespacePrefix ? qualifyId(local, namespacePrefix, this.rootSubsystems) : local;
|
|
20044
19854
|
}
|
|
20045
19855
|
scanSpecsForProject(projectDir, namespacePrefix, visitedDirs, maxDepth, currentDepth) {
|
|
@@ -20049,10 +19859,10 @@ var init_specs2 = __esm({
|
|
|
20049
19859
|
this.scanVisitedSpecDirs.push(specsDir);
|
|
20050
19860
|
if (!pathExists(specsDir)) return index;
|
|
20051
19861
|
const files = listSpecFiles(specsDir);
|
|
20052
|
-
const systemYaml =
|
|
19862
|
+
const systemYaml = path17.normalize(projectPaths.specsSystem());
|
|
20053
19863
|
const localSubprojects = [];
|
|
20054
19864
|
for (const file of files) {
|
|
20055
|
-
const normFile =
|
|
19865
|
+
const normFile = path17.normalize(file);
|
|
20056
19866
|
if (normFile === systemYaml) continue;
|
|
20057
19867
|
let detectedType = "spec";
|
|
20058
19868
|
let rawId;
|
|
@@ -20096,7 +19906,7 @@ var init_specs2 = __esm({
|
|
|
20096
19906
|
} else if ("contract" in raw) {
|
|
20097
19907
|
detectedType = "implementation";
|
|
20098
19908
|
const parsed = ImplementationSpecSchema.parse(raw);
|
|
20099
|
-
const normalizeSourcePath = (p) =>
|
|
19909
|
+
const normalizeSourcePath = (p) => path17.relative(projectDir, path17.resolve(projectDir, p)).replace(/\\/g, "/");
|
|
20100
19910
|
if (parsed.sourcePath) parsed.sourcePath = normalizeSourcePath(parsed.sourcePath);
|
|
20101
19911
|
for (const method2 of parsed.methods) {
|
|
20102
19912
|
if (method2.sourcePath) method2.sourcePath = normalizeSourcePath(method2.sourcePath);
|
|
@@ -20222,7 +20032,7 @@ var init_specs2 = __esm({
|
|
|
20222
20032
|
}
|
|
20223
20033
|
if (currentDepth < maxDepth) {
|
|
20224
20034
|
for (const subproj of localSubprojects) {
|
|
20225
|
-
const childDir =
|
|
20035
|
+
const childDir = path17.resolve(projectDir, subproj.projectPath);
|
|
20226
20036
|
const mountId = namespacePrefix ? qualifyDeclaredId(subproj.subsystemId, namespacePrefix, true) : subproj.subsystemId;
|
|
20227
20037
|
if (projectPathEscapesRoot(projectDir, subproj.projectPath, childDir)) {
|
|
20228
20038
|
this.loaderIssues.push({
|
|
@@ -20242,7 +20052,7 @@ var init_specs2 = __esm({
|
|
|
20242
20052
|
});
|
|
20243
20053
|
continue;
|
|
20244
20054
|
}
|
|
20245
|
-
if (!
|
|
20055
|
+
if (!fs14.existsSync(childDir)) {
|
|
20246
20056
|
this.loaderIssues.push({
|
|
20247
20057
|
severity: "error",
|
|
20248
20058
|
code: "SUBPROJECT_NOT_FOUND",
|
|
@@ -20285,7 +20095,7 @@ var init_specs2 = __esm({
|
|
|
20285
20095
|
const index = this.scanAll();
|
|
20286
20096
|
const sub = index.subsystems.find((s) => s.id === currentPrefix);
|
|
20287
20097
|
if (sub && sub.projectPath) {
|
|
20288
|
-
const nextDir =
|
|
20098
|
+
const nextDir = path17.resolve(currentDir, sub.projectPath);
|
|
20289
20099
|
if (projectPathEscapesRoot(currentDir, sub.projectPath, nextDir)) {
|
|
20290
20100
|
this.loaderIssues.push({
|
|
20291
20101
|
severity: "error",
|
|
@@ -20337,9 +20147,9 @@ var init_specs2 = __esm({
|
|
|
20337
20147
|
return index.paths.subsystem[matches[0]];
|
|
20338
20148
|
}
|
|
20339
20149
|
if (pathExists(this.paths.specsSubsystemsDir()) && listFiles(this.paths.specsSubsystemsDir(), ".yaml").length > 0) {
|
|
20340
|
-
return
|
|
20150
|
+
return path17.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
|
|
20341
20151
|
}
|
|
20342
|
-
return
|
|
20152
|
+
return path17.join(this.paths.specsDir(), id, ".index.yaml");
|
|
20343
20153
|
}
|
|
20344
20154
|
getComponentPath(id, subsystemId) {
|
|
20345
20155
|
const index = this.scanAll();
|
|
@@ -20359,21 +20169,21 @@ var init_specs2 = __esm({
|
|
|
20359
20169
|
if (owner) {
|
|
20360
20170
|
const ownerPath = index.paths.component[owner.id];
|
|
20361
20171
|
if (ownerPath && ownerPath.endsWith(".index.yaml")) {
|
|
20362
|
-
return
|
|
20172
|
+
return path17.join(path17.dirname(ownerPath), id, ".index.yaml");
|
|
20363
20173
|
}
|
|
20364
20174
|
}
|
|
20365
20175
|
if (subsystemId) {
|
|
20366
20176
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20367
|
-
const subDir =
|
|
20177
|
+
const subDir = path17.dirname(subPath);
|
|
20368
20178
|
if (subPath.endsWith(".index.yaml")) {
|
|
20369
|
-
return
|
|
20179
|
+
return path17.join(subDir, id, ".index.yaml");
|
|
20370
20180
|
}
|
|
20371
20181
|
}
|
|
20372
20182
|
if (pathExists(this.paths.specsComponentsDir()) && listFiles(this.paths.specsComponentsDir(), ".yaml").length > 0) {
|
|
20373
|
-
return
|
|
20183
|
+
return path17.join(this.paths.specsComponentsDir(), `${id}.yaml`);
|
|
20374
20184
|
}
|
|
20375
20185
|
const targetSubsystem = subsystemId || "default";
|
|
20376
|
-
return
|
|
20186
|
+
return path17.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
|
|
20377
20187
|
}
|
|
20378
20188
|
getInterfacePath(id, componentId) {
|
|
20379
20189
|
const index = this.scanAll();
|
|
@@ -20399,16 +20209,16 @@ var init_specs2 = __esm({
|
|
|
20399
20209
|
}
|
|
20400
20210
|
if (componentId) {
|
|
20401
20211
|
const compPath = this.getComponentPath(componentId);
|
|
20402
|
-
const compDir =
|
|
20212
|
+
const compDir = path17.dirname(compPath);
|
|
20403
20213
|
if (compPath.endsWith(".index.yaml")) {
|
|
20404
|
-
return
|
|
20214
|
+
return path17.join(compDir, ".interface.yaml");
|
|
20405
20215
|
}
|
|
20406
20216
|
}
|
|
20407
20217
|
if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
|
|
20408
|
-
return
|
|
20218
|
+
return path17.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
|
|
20409
20219
|
}
|
|
20410
20220
|
const targetComponent = componentId || "default";
|
|
20411
|
-
return
|
|
20221
|
+
return path17.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
|
|
20412
20222
|
}
|
|
20413
20223
|
getImplementationPath(id, contractId) {
|
|
20414
20224
|
const index = this.scanAll();
|
|
@@ -20434,16 +20244,16 @@ var init_specs2 = __esm({
|
|
|
20434
20244
|
}
|
|
20435
20245
|
if (contractId) {
|
|
20436
20246
|
const intfPath = this.getInterfacePath(contractId);
|
|
20437
|
-
const intfDir =
|
|
20247
|
+
const intfDir = path17.dirname(intfPath);
|
|
20438
20248
|
if (intfPath.endsWith(".interface.yaml")) {
|
|
20439
|
-
return
|
|
20249
|
+
return path17.join(intfDir, ".implementation.yaml");
|
|
20440
20250
|
}
|
|
20441
20251
|
}
|
|
20442
20252
|
if (pathExists(this.paths.specsImplementationsDir()) && listFiles(this.paths.specsImplementationsDir(), ".yaml").length > 0) {
|
|
20443
|
-
return
|
|
20253
|
+
return path17.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
|
|
20444
20254
|
}
|
|
20445
20255
|
const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
|
|
20446
|
-
return
|
|
20256
|
+
return path17.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
|
|
20447
20257
|
}
|
|
20448
20258
|
getTypePath(id, subsystemId, group) {
|
|
20449
20259
|
const index = this.scanAll();
|
|
@@ -20474,7 +20284,7 @@ var init_specs2 = __esm({
|
|
|
20474
20284
|
const groupPath = index.paths.group[targetGroup] || index.paths.group[plainGroup];
|
|
20475
20285
|
if (groupPath) {
|
|
20476
20286
|
const localId2 = id.split("::").pop();
|
|
20477
|
-
return
|
|
20287
|
+
return path17.join(path17.dirname(groupPath), `${localId2}.yaml`);
|
|
20478
20288
|
}
|
|
20479
20289
|
}
|
|
20480
20290
|
let localId = id;
|
|
@@ -20487,12 +20297,12 @@ var init_specs2 = __esm({
|
|
|
20487
20297
|
}
|
|
20488
20298
|
if (subsystemId) {
|
|
20489
20299
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20490
|
-
const subDir =
|
|
20300
|
+
const subDir = path17.dirname(subPath);
|
|
20491
20301
|
if (subPath.endsWith(".index.yaml")) {
|
|
20492
|
-
return
|
|
20302
|
+
return path17.join(subDir, "types", `${localId}.yaml`);
|
|
20493
20303
|
}
|
|
20494
20304
|
}
|
|
20495
|
-
return
|
|
20305
|
+
return path17.join(this.paths.specsTypesDir(), `${localId}.yaml`);
|
|
20496
20306
|
}
|
|
20497
20307
|
getGroupPath(id, subsystemId) {
|
|
20498
20308
|
const index = this.scanAll();
|
|
@@ -20526,12 +20336,12 @@ var init_specs2 = __esm({
|
|
|
20526
20336
|
}
|
|
20527
20337
|
if (subsystemId) {
|
|
20528
20338
|
const subPath = this.getSubsystemPath(subsystemId);
|
|
20529
|
-
const subDir =
|
|
20339
|
+
const subDir = path17.dirname(subPath);
|
|
20530
20340
|
if (subPath.endsWith(".index.yaml")) {
|
|
20531
|
-
return
|
|
20341
|
+
return path17.join(subDir, "types", localId, ".index.yaml");
|
|
20532
20342
|
}
|
|
20533
20343
|
}
|
|
20534
|
-
return
|
|
20344
|
+
return path17.join(this.paths.specsTypesDir(), localId, ".index.yaml");
|
|
20535
20345
|
}
|
|
20536
20346
|
// -------------------------------------------------------------------------
|
|
20537
20347
|
// Level 0: System
|
|
@@ -20554,7 +20364,7 @@ var init_specs2 = __esm({
|
|
|
20554
20364
|
}
|
|
20555
20365
|
saveSystemSpec(spec) {
|
|
20556
20366
|
const p = this.paths.specsSystem();
|
|
20557
|
-
ensureDir(
|
|
20367
|
+
ensureDir(path17.dirname(p));
|
|
20558
20368
|
writeSpecFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
|
|
20559
20369
|
invalidateSpecCache();
|
|
20560
20370
|
}
|
|
@@ -20676,7 +20486,7 @@ var init_specs2 = __esm({
|
|
|
20676
20486
|
}
|
|
20677
20487
|
saveSubsystemSpec(spec, opts) {
|
|
20678
20488
|
const p = this.getSubsystemPath(spec.id);
|
|
20679
|
-
ensureDir(
|
|
20489
|
+
ensureDir(path17.dirname(p));
|
|
20680
20490
|
const { prefix } = splitNamespace(spec.id);
|
|
20681
20491
|
if (!prefix && spec.projectPath && spec.projectPath.trim() !== "") {
|
|
20682
20492
|
assertContainedProjectPath(this.rootDir, spec.projectPath);
|
|
@@ -20743,7 +20553,7 @@ var init_specs2 = __esm({
|
|
|
20743
20553
|
saveComponentSpec(spec, opts) {
|
|
20744
20554
|
const notices = [];
|
|
20745
20555
|
const p = this.getComponentPath(spec.id, spec.subsystem);
|
|
20746
|
-
ensureDir(
|
|
20556
|
+
ensureDir(path17.dirname(p));
|
|
20747
20557
|
const specToWrite = this.prepareComponentForWrite(spec);
|
|
20748
20558
|
const existing = this.loadComponentSpec(spec.id);
|
|
20749
20559
|
if (existing) {
|
|
@@ -20760,7 +20570,7 @@ var init_specs2 = __esm({
|
|
|
20760
20570
|
const subsystemChanged = existing && existing.subsystem !== spec.subsystem && splitNamespace(existing.subsystem).localId !== splitNamespace(spec.subsystem).localId;
|
|
20761
20571
|
if (subsystemChanged && !p.endsWith(".index.yaml")) {
|
|
20762
20572
|
notices.push(
|
|
20763
|
-
`component "${spec.id}" already exists at ${
|
|
20573
|
+
`component "${spec.id}" already exists at ${path17.relative(this.rootDir, p)} \u2014 the flat layout re-saves in place and never relocates the file. The subsystem field is now "${spec.subsystem}" (was "${existing.subsystem}").`
|
|
20764
20574
|
);
|
|
20765
20575
|
}
|
|
20766
20576
|
specToWrite.updatedAt = opts?.preserveUpdatedAt && existing?.updatedAt ? existing.updatedAt : (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -20784,12 +20594,12 @@ var init_specs2 = __esm({
|
|
|
20784
20594
|
if (owner) {
|
|
20785
20595
|
const ownerPath = index.paths.component[owner.id];
|
|
20786
20596
|
if (ownerPath && ownerPath.endsWith(".index.yaml")) {
|
|
20787
|
-
const ownerSubDir =
|
|
20788
|
-
return
|
|
20597
|
+
const ownerSubDir = path17.dirname(this.getSubsystemPath(owner.subsystem));
|
|
20598
|
+
return path17.join(ownerSubDir, owner.id, comp.id);
|
|
20789
20599
|
}
|
|
20790
20600
|
}
|
|
20791
|
-
const subDir =
|
|
20792
|
-
return
|
|
20601
|
+
const subDir = path17.dirname(this.getSubsystemPath(comp.subsystem));
|
|
20602
|
+
return path17.join(subDir, comp.id);
|
|
20793
20603
|
}
|
|
20794
20604
|
/**
|
|
20795
20605
|
* Move component folders so the physical tree mirrors ownership: each owned
|
|
@@ -20805,7 +20615,7 @@ var init_specs2 = __esm({
|
|
|
20805
20615
|
if (!currentPath) continue;
|
|
20806
20616
|
const desiredDir = this.desiredComponentDir(comp, index);
|
|
20807
20617
|
if (!desiredDir) continue;
|
|
20808
|
-
if (moveComponentFolder(
|
|
20618
|
+
if (moveComponentFolder(path17.dirname(currentPath), desiredDir)) moved.push(comp.id);
|
|
20809
20619
|
}
|
|
20810
20620
|
if (moved.length) invalidateSpecCache();
|
|
20811
20621
|
return moved;
|
|
@@ -20861,7 +20671,7 @@ var init_specs2 = __esm({
|
|
|
20861
20671
|
if (!occupantId) return;
|
|
20862
20672
|
if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
|
|
20863
20673
|
throw new Error(
|
|
20864
|
-
`Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${
|
|
20674
|
+
`Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path17.relative(this.rootDir, p)}, and both ids resolve to that one file. Re-author "${occupantId}" instead, or delete it first if you meant to replace it.`
|
|
20865
20675
|
);
|
|
20866
20676
|
}
|
|
20867
20677
|
/** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
|
|
@@ -20869,12 +20679,12 @@ var init_specs2 = __esm({
|
|
|
20869
20679
|
const notices = [];
|
|
20870
20680
|
const p = this.getInterfacePath(spec.id, spec.component);
|
|
20871
20681
|
this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
|
|
20872
|
-
ensureDir(
|
|
20682
|
+
ensureDir(path17.dirname(p));
|
|
20873
20683
|
const specToWrite = this.prepareInterfaceForWrite(spec);
|
|
20874
20684
|
const existing = this.loadInterfaceSpec(spec.id);
|
|
20875
20685
|
if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
|
|
20876
20686
|
notices.push(
|
|
20877
|
-
`interface "${spec.id}" already exists at ${
|
|
20687
|
+
`interface "${spec.id}" already exists at ${path17.relative(this.rootDir, p)} \u2014 re-saving updates the component binding field in place (now "${spec.component}", was "${existing.component}") and never moves the file.`
|
|
20878
20688
|
);
|
|
20879
20689
|
}
|
|
20880
20690
|
if (existing) {
|
|
@@ -20931,12 +20741,12 @@ var init_specs2 = __esm({
|
|
|
20931
20741
|
const notices = [];
|
|
20932
20742
|
const p = this.getImplementationPath(spec.id, spec.contract);
|
|
20933
20743
|
this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
|
|
20934
|
-
ensureDir(
|
|
20744
|
+
ensureDir(path17.dirname(p));
|
|
20935
20745
|
const specToWrite = this.prepareImplementationForWrite(spec);
|
|
20936
20746
|
const existing = this.loadImplementationSpec(spec.id);
|
|
20937
20747
|
if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
|
|
20938
20748
|
notices.push(
|
|
20939
|
-
`implementation "${spec.id}" already exists at ${
|
|
20749
|
+
`implementation "${spec.id}" already exists at ${path17.relative(this.rootDir, p)} \u2014 re-saving updates the contract binding field in place (now "${spec.contract}", was "${existing.contract}") and never moves the file.`
|
|
20940
20750
|
);
|
|
20941
20751
|
}
|
|
20942
20752
|
if (existing) {
|
|
@@ -20977,11 +20787,11 @@ var init_specs2 = __esm({
|
|
|
20977
20787
|
const existing = this.loadTypeSpec(spec.id);
|
|
20978
20788
|
const group = spec.group || (existing ? existing.group : void 0);
|
|
20979
20789
|
const p = this.getTypePath(spec.id, spec.subsystem, group);
|
|
20980
|
-
ensureDir(
|
|
20790
|
+
ensureDir(path17.dirname(p));
|
|
20981
20791
|
const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
|
|
20982
20792
|
if (subsystemChanged) {
|
|
20983
20793
|
notices.push(
|
|
20984
|
-
`type "${spec.id}" already exists at ${
|
|
20794
|
+
`type "${spec.id}" already exists at ${path17.relative(this.rootDir, p)} \u2014 re-saving updates fields in place and never relocates the file. The subsystem field is now "${spec.subsystem ?? "(none)"}" (was "${existing.subsystem ?? "(none)"}").`
|
|
20985
20795
|
);
|
|
20986
20796
|
}
|
|
20987
20797
|
if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
|
|
@@ -21019,7 +20829,7 @@ var init_specs2 = __esm({
|
|
|
21019
20829
|
}
|
|
21020
20830
|
saveGroupSpec(spec, opts) {
|
|
21021
20831
|
const p = this.getGroupPath(spec.id);
|
|
21022
|
-
ensureDir(
|
|
20832
|
+
ensureDir(path17.dirname(p));
|
|
21023
20833
|
const specToWrite = this.prepareGroupForWrite(spec);
|
|
21024
20834
|
const existing = this.loadGroupSpec(spec.id);
|
|
21025
20835
|
if (existing) {
|
|
@@ -21097,7 +20907,7 @@ var init_specs2 = __esm({
|
|
|
21097
20907
|
};
|
|
21098
20908
|
const out = /* @__PURE__ */ new Set();
|
|
21099
20909
|
const add = (p) => {
|
|
21100
|
-
if (p) out.add(
|
|
20910
|
+
if (p) out.add(path17.resolve(p));
|
|
21101
20911
|
};
|
|
21102
20912
|
for (const s of this.loadSubsystemSpecs()) {
|
|
21103
20913
|
if (!scopeSubsystem || s.id === scopeSubsystem || s.id.startsWith(`${scopeSubsystem}::`)) {
|
|
@@ -21168,16 +20978,16 @@ var init_specs2 = __esm({
|
|
|
21168
20978
|
const files = /* @__PURE__ */ new Set();
|
|
21169
20979
|
const sysPath = this.paths.specsSystem();
|
|
21170
20980
|
if (pathExists(sysPath)) {
|
|
21171
|
-
files.add(
|
|
20981
|
+
files.add(path17.resolve(sysPath));
|
|
21172
20982
|
}
|
|
21173
20983
|
for (const group of Object.values(index.paths)) {
|
|
21174
20984
|
for (const file of Object.values(group)) {
|
|
21175
|
-
files.add(
|
|
20985
|
+
files.add(path17.resolve(file));
|
|
21176
20986
|
}
|
|
21177
20987
|
}
|
|
21178
20988
|
for (const file of files) {
|
|
21179
|
-
if (
|
|
21180
|
-
snapshot.set(file,
|
|
20989
|
+
if (fs14.existsSync(file)) {
|
|
20990
|
+
snapshot.set(file, fs14.readFileSync(file, "utf8"));
|
|
21181
20991
|
}
|
|
21182
20992
|
}
|
|
21183
20993
|
return snapshot;
|
|
@@ -21191,20 +21001,20 @@ var init_specs2 = __esm({
|
|
|
21191
21001
|
const files = listSpecFiles(specsDir);
|
|
21192
21002
|
const legacy = [];
|
|
21193
21003
|
for (const f of files) {
|
|
21194
|
-
const base =
|
|
21195
|
-
const dir =
|
|
21004
|
+
const base = path17.basename(f);
|
|
21005
|
+
const dir = path17.dirname(f);
|
|
21196
21006
|
if (base === "system.yaml") {
|
|
21197
|
-
legacy.push({ path: f, expected:
|
|
21007
|
+
legacy.push({ path: f, expected: path17.join(dir, ".index.yaml") });
|
|
21198
21008
|
} else if (base === "subsystem.yaml") {
|
|
21199
|
-
legacy.push({ path: f, expected:
|
|
21009
|
+
legacy.push({ path: f, expected: path17.join(dir, ".index.yaml") });
|
|
21200
21010
|
} else if (base === "component.yaml") {
|
|
21201
|
-
legacy.push({ path: f, expected:
|
|
21011
|
+
legacy.push({ path: f, expected: path17.join(dir, ".index.yaml") });
|
|
21202
21012
|
} else if (base === "group.yaml") {
|
|
21203
|
-
legacy.push({ path: f, expected:
|
|
21013
|
+
legacy.push({ path: f, expected: path17.join(dir, ".index.yaml") });
|
|
21204
21014
|
} else if (base === "interface.yaml") {
|
|
21205
|
-
legacy.push({ path: f, expected:
|
|
21015
|
+
legacy.push({ path: f, expected: path17.join(dir, ".interface.yaml") });
|
|
21206
21016
|
} else if (base === "implementation.yaml") {
|
|
21207
|
-
legacy.push({ path: f, expected:
|
|
21017
|
+
legacy.push({ path: f, expected: path17.join(dir, ".implementation.yaml") });
|
|
21208
21018
|
}
|
|
21209
21019
|
}
|
|
21210
21020
|
return legacy;
|
|
@@ -22276,7 +22086,7 @@ var init_topology = __esm({
|
|
|
22276
22086
|
|
|
22277
22087
|
// src/core/domain_projector.ts
|
|
22278
22088
|
function rel(p) {
|
|
22279
|
-
return
|
|
22089
|
+
return path18.relative(process.cwd(), p).replace(/\\/g, "/");
|
|
22280
22090
|
}
|
|
22281
22091
|
function deriveSubsystemDomains() {
|
|
22282
22092
|
const subsystems = loadSubsystemSpecs();
|
|
@@ -22300,11 +22110,11 @@ function resolveDomains() {
|
|
|
22300
22110
|
const registered = loadConfig().domains;
|
|
22301
22111
|
return [...derived, ...registered];
|
|
22302
22112
|
}
|
|
22303
|
-
var
|
|
22113
|
+
var path18;
|
|
22304
22114
|
var init_domain_projector = __esm({
|
|
22305
22115
|
"src/core/domain_projector.ts"() {
|
|
22306
22116
|
"use strict";
|
|
22307
|
-
|
|
22117
|
+
path18 = __toESM(require("path"));
|
|
22308
22118
|
init_specs2();
|
|
22309
22119
|
init_topology();
|
|
22310
22120
|
}
|
|
@@ -22374,7 +22184,7 @@ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
|
|
|
22374
22184
|
});
|
|
22375
22185
|
}
|
|
22376
22186
|
function parseGitmodules(filePath) {
|
|
22377
|
-
const content =
|
|
22187
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
22378
22188
|
const entries = [];
|
|
22379
22189
|
let current2 = {};
|
|
22380
22190
|
for (const line2 of content.split("\n")) {
|
|
@@ -22396,8 +22206,8 @@ function parseGitmodules(filePath) {
|
|
|
22396
22206
|
return entries;
|
|
22397
22207
|
}
|
|
22398
22208
|
function detectGitSubmodules(projectRoot2) {
|
|
22399
|
-
const gitmodulesPath =
|
|
22400
|
-
if (!
|
|
22209
|
+
const gitmodulesPath = path19.join(projectRoot2, ".gitmodules");
|
|
22210
|
+
if (!fs15.existsSync(gitmodulesPath)) return [];
|
|
22401
22211
|
return parseGitmodules(gitmodulesPath).map((entry) => ({
|
|
22402
22212
|
suggestedId: pathToId(entry.path),
|
|
22403
22213
|
suggestedName: pathToName(entry.path),
|
|
@@ -22415,18 +22225,18 @@ function walkForGit(projectRoot2, currentDir, depth, results) {
|
|
|
22415
22225
|
if (depth > MAX_SCAN_DEPTH) return;
|
|
22416
22226
|
let entries;
|
|
22417
22227
|
try {
|
|
22418
|
-
entries =
|
|
22228
|
+
entries = fs15.readdirSync(currentDir, { withFileTypes: true });
|
|
22419
22229
|
} catch {
|
|
22420
22230
|
return;
|
|
22421
22231
|
}
|
|
22422
22232
|
for (const entry of entries) {
|
|
22423
22233
|
if (!entry.isDirectory()) continue;
|
|
22424
22234
|
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22425
|
-
const fullPath =
|
|
22426
|
-
const relPath = normalizePath(
|
|
22235
|
+
const fullPath = path19.join(currentDir, entry.name);
|
|
22236
|
+
const relPath = normalizePath(path19.relative(projectRoot2, fullPath));
|
|
22427
22237
|
if (relPath === "" || relPath === ".") continue;
|
|
22428
|
-
const gitPath =
|
|
22429
|
-
if (
|
|
22238
|
+
const gitPath = path19.join(fullPath, ".git");
|
|
22239
|
+
if (fs15.existsSync(gitPath)) {
|
|
22430
22240
|
results.push({
|
|
22431
22241
|
suggestedId: pathToId(relPath),
|
|
22432
22242
|
suggestedName: pathToName(relPath),
|
|
@@ -22448,17 +22258,17 @@ function walkForPackages(projectRoot2, currentDir, depth, results) {
|
|
|
22448
22258
|
if (depth > MAX_SCAN_DEPTH) return;
|
|
22449
22259
|
let entries;
|
|
22450
22260
|
try {
|
|
22451
|
-
entries =
|
|
22261
|
+
entries = fs15.readdirSync(currentDir, { withFileTypes: true });
|
|
22452
22262
|
} catch {
|
|
22453
22263
|
return;
|
|
22454
22264
|
}
|
|
22455
22265
|
for (const entry of entries) {
|
|
22456
22266
|
if (!entry.isDirectory()) continue;
|
|
22457
22267
|
if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
|
|
22458
|
-
const fullPath =
|
|
22459
|
-
const relPath = normalizePath(
|
|
22268
|
+
const fullPath = path19.join(currentDir, entry.name);
|
|
22269
|
+
const relPath = normalizePath(path19.relative(projectRoot2, fullPath));
|
|
22460
22270
|
if (relPath === "" || relPath === ".") continue;
|
|
22461
|
-
const hasMarker = PACKAGE_MARKERS.some((m) =>
|
|
22271
|
+
const hasMarker = PACKAGE_MARKERS.some((m) => fs15.existsSync(path19.join(fullPath, m)));
|
|
22462
22272
|
if (hasMarker) {
|
|
22463
22273
|
results.push({
|
|
22464
22274
|
suggestedId: pathToId(relPath),
|
|
@@ -22472,7 +22282,7 @@ function walkForPackages(projectRoot2, currentDir, depth, results) {
|
|
|
22472
22282
|
}
|
|
22473
22283
|
}
|
|
22474
22284
|
function pathToId(relPath) {
|
|
22475
|
-
const basename15 =
|
|
22285
|
+
const basename15 = path19.basename(relPath);
|
|
22476
22286
|
return basename15.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
22477
22287
|
}
|
|
22478
22288
|
function pathToName(relPath) {
|
|
@@ -22482,12 +22292,12 @@ function pathToName(relPath) {
|
|
|
22482
22292
|
function normalizePath(p) {
|
|
22483
22293
|
return p.replace(/\\/g, "/");
|
|
22484
22294
|
}
|
|
22485
|
-
var
|
|
22295
|
+
var fs15, path19, PACKAGE_MARKERS, MAX_SCAN_DEPTH;
|
|
22486
22296
|
var init_detection = __esm({
|
|
22487
22297
|
"src/core/detection.ts"() {
|
|
22488
22298
|
"use strict";
|
|
22489
|
-
|
|
22490
|
-
|
|
22299
|
+
fs15 = __toESM(require("fs"));
|
|
22300
|
+
path19 = __toESM(require("path"));
|
|
22491
22301
|
init_defaults();
|
|
22492
22302
|
PACKAGE_MARKERS = [
|
|
22493
22303
|
"package.json",
|
|
@@ -22504,12 +22314,12 @@ var init_detection = __esm({
|
|
|
22504
22314
|
|
|
22505
22315
|
// src/core/templates.ts
|
|
22506
22316
|
function builtinTemplatesDir() {
|
|
22507
|
-
return
|
|
22317
|
+
return path20.resolve(__dirname, "..", "templates");
|
|
22508
22318
|
}
|
|
22509
22319
|
function loadTemplate(id, globalOverride) {
|
|
22510
22320
|
const dirs = templateSearchDirs(globalOverride);
|
|
22511
22321
|
for (const dir of dirs) {
|
|
22512
|
-
const filePath =
|
|
22322
|
+
const filePath = path20.join(dir, `${id}.yaml`);
|
|
22513
22323
|
if (pathExists(filePath)) {
|
|
22514
22324
|
const raw = readYamlFile(filePath);
|
|
22515
22325
|
return { ...TemplateSchema.parse(raw), templateName: id };
|
|
@@ -22518,7 +22328,7 @@ function loadTemplate(id, globalOverride) {
|
|
|
22518
22328
|
throw new TemplateNotFoundError(id);
|
|
22519
22329
|
}
|
|
22520
22330
|
function loadAgentOverride(agentId) {
|
|
22521
|
-
const filePath =
|
|
22331
|
+
const filePath = path20.join(AI_PATHS.root(), "agents", `${agentId}.md`);
|
|
22522
22332
|
return readFileOrNull(filePath);
|
|
22523
22333
|
}
|
|
22524
22334
|
function templateSearchDirs(globalOverride) {
|
|
@@ -22536,11 +22346,11 @@ function renderTemplateInstructions(template, vars) {
|
|
|
22536
22346
|
return key in vars ? vars[key] : `{{${key}}}`;
|
|
22537
22347
|
});
|
|
22538
22348
|
}
|
|
22539
|
-
var
|
|
22349
|
+
var path20;
|
|
22540
22350
|
var init_templates = __esm({
|
|
22541
22351
|
"src/core/templates.ts"() {
|
|
22542
22352
|
"use strict";
|
|
22543
|
-
|
|
22353
|
+
path20 = __toESM(require("path"));
|
|
22544
22354
|
init_fs();
|
|
22545
22355
|
init_yaml();
|
|
22546
22356
|
init_errors();
|
|
@@ -22612,7 +22422,7 @@ function provisionProject(name) {
|
|
|
22612
22422
|
function ensureProjectInitialized(fallbackName) {
|
|
22613
22423
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22614
22424
|
const paths = aiPathsAt(getProjectRoot());
|
|
22615
|
-
const hasSystem =
|
|
22425
|
+
const hasSystem = fs16.existsSync(paths.specsSystem());
|
|
22616
22426
|
let name = fallbackName;
|
|
22617
22427
|
if (hasSystem) {
|
|
22618
22428
|
const existing = loadSystemSpec();
|
|
@@ -22634,11 +22444,11 @@ function ensureProjectInitialized(fallbackName) {
|
|
|
22634
22444
|
function walkChainedSubprojects(projectRoot2, onChild) {
|
|
22635
22445
|
const visited = /* @__PURE__ */ new Set();
|
|
22636
22446
|
const walk2 = (dir) => {
|
|
22637
|
-
const resolved =
|
|
22447
|
+
const resolved = path21.resolve(dir);
|
|
22638
22448
|
if (visited.has(resolved)) return;
|
|
22639
22449
|
visited.add(resolved);
|
|
22640
22450
|
const specsDir = aiPathsAt(dir).specsDir();
|
|
22641
|
-
if (!
|
|
22451
|
+
if (!fs16.existsSync(specsDir)) return;
|
|
22642
22452
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
22643
22453
|
let raw;
|
|
22644
22454
|
try {
|
|
@@ -22656,7 +22466,7 @@ function walkChainedSubprojects(projectRoot2, onChild) {
|
|
|
22656
22466
|
continue;
|
|
22657
22467
|
}
|
|
22658
22468
|
const id = raw.id;
|
|
22659
|
-
onChild(childDir, typeof id === "string" ? id :
|
|
22469
|
+
onChild(childDir, typeof id === "string" ? id : path21.basename(childDir));
|
|
22660
22470
|
walk2(childDir);
|
|
22661
22471
|
}
|
|
22662
22472
|
};
|
|
@@ -22665,7 +22475,7 @@ function walkChainedSubprojects(projectRoot2, onChild) {
|
|
|
22665
22475
|
function listDirectChainedSubprojects(projectRoot2) {
|
|
22666
22476
|
const out = [];
|
|
22667
22477
|
const specsDir = aiPathsAt(projectRoot2).specsDir();
|
|
22668
|
-
if (!
|
|
22478
|
+
if (!fs16.existsSync(specsDir)) return out;
|
|
22669
22479
|
for (const file of listFilesRecursive(specsDir, ".yaml")) {
|
|
22670
22480
|
let raw;
|
|
22671
22481
|
try {
|
|
@@ -22683,12 +22493,12 @@ function listDirectChainedSubprojects(projectRoot2) {
|
|
|
22683
22493
|
continue;
|
|
22684
22494
|
}
|
|
22685
22495
|
const id = raw.id;
|
|
22686
|
-
out.push({ dir, subsystemId: typeof id === "string" ? id :
|
|
22496
|
+
out.push({ dir, subsystemId: typeof id === "string" ? id : path21.basename(dir) });
|
|
22687
22497
|
}
|
|
22688
22498
|
return out;
|
|
22689
22499
|
}
|
|
22690
22500
|
function childHasSpecsButNoConfig(childDir) {
|
|
22691
|
-
return
|
|
22501
|
+
return fs16.existsSync(aiPathsAt(childDir).specsDir()) && !projectConfigRepositoryAt(childDir).exists();
|
|
22692
22502
|
}
|
|
22693
22503
|
function findChainingSubprojectsMissingConfig(projectRoot2) {
|
|
22694
22504
|
const missing = [];
|
|
@@ -22737,14 +22547,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
|
|
|
22737
22547
|
const oldDir = assertContainedProjectPath(root, sub.projectPath);
|
|
22738
22548
|
const newDir = assertContainedProjectPath(root, nextPath);
|
|
22739
22549
|
if (oldDir !== newDir) {
|
|
22740
|
-
if (!
|
|
22550
|
+
if (!fs16.existsSync(oldDir)) {
|
|
22741
22551
|
throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
|
|
22742
22552
|
}
|
|
22743
|
-
if (
|
|
22553
|
+
if (fs16.existsSync(newDir)) {
|
|
22744
22554
|
throw new WaironError(`Target directory already exists: ${newDir}`);
|
|
22745
22555
|
}
|
|
22746
|
-
ensureDir(
|
|
22747
|
-
|
|
22556
|
+
ensureDir(path21.dirname(newDir));
|
|
22557
|
+
fs16.renameSync(oldDir, newDir);
|
|
22748
22558
|
}
|
|
22749
22559
|
saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
22750
22560
|
invalidateSpecCache();
|
|
@@ -22753,9 +22563,9 @@ function toPosixPath(p) {
|
|
|
22753
22563
|
return p.replace(/\\/g, "/");
|
|
22754
22564
|
}
|
|
22755
22565
|
function isWithinDir(dir, file) {
|
|
22756
|
-
const d =
|
|
22757
|
-
const f =
|
|
22758
|
-
return f === d || f.startsWith(d +
|
|
22566
|
+
const d = path21.resolve(dir);
|
|
22567
|
+
const f = path21.resolve(file);
|
|
22568
|
+
return f === d || f.startsWith(d + path21.sep);
|
|
22759
22569
|
}
|
|
22760
22570
|
function externalizeSubsystem(subsystemId, projectPath) {
|
|
22761
22571
|
if (subsystemId.includes("::")) {
|
|
@@ -22767,14 +22577,14 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
22767
22577
|
}
|
|
22768
22578
|
const parentRoot = getProjectRoot();
|
|
22769
22579
|
const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
|
|
22770
|
-
const fooDir =
|
|
22771
|
-
if (!
|
|
22580
|
+
const fooDir = path21.join(parentSpecsDir, subsystemId);
|
|
22581
|
+
if (!fs16.existsSync(fooDir)) {
|
|
22772
22582
|
throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
|
|
22773
22583
|
}
|
|
22774
22584
|
const relPath = toPosixPath(projectPath);
|
|
22775
22585
|
const childDir = assertContainedProjectPath(parentRoot, relPath);
|
|
22776
|
-
const childFooDir =
|
|
22777
|
-
if (
|
|
22586
|
+
const childFooDir = path21.join(childDir, ".wai", "specs", subsystemId);
|
|
22587
|
+
if (fs16.existsSync(childFooDir)) {
|
|
22778
22588
|
throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
|
|
22779
22589
|
}
|
|
22780
22590
|
const renameMap = buildRenameMap(
|
|
@@ -22786,18 +22596,18 @@ function externalizeSubsystem(subsystemId, projectPath) {
|
|
|
22786
22596
|
runWithProjectRoot(childDir, () => {
|
|
22787
22597
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22788
22598
|
projectConfigRepository.create(defaultProjectConfig(childSystemName, now));
|
|
22789
|
-
ensureDir(
|
|
22599
|
+
ensureDir(path21.join(childDir, ".wai", "specs"));
|
|
22790
22600
|
saveSystemSpec(bootstrapSystemSpec(childSystemName, now));
|
|
22791
22601
|
});
|
|
22792
|
-
ensureDir(
|
|
22793
|
-
|
|
22602
|
+
ensureDir(path21.dirname(childFooDir));
|
|
22603
|
+
fs16.renameSync(fooDir, childFooDir);
|
|
22794
22604
|
rebaseImplementationPaths(childFooDir, parentRoot, childDir);
|
|
22795
|
-
patchSubsystemIndex(
|
|
22605
|
+
patchSubsystemIndex(path21.join(childFooDir, ".index.yaml"), (s) => {
|
|
22796
22606
|
s.parentSystem = childSystemName;
|
|
22797
22607
|
delete s.projectPath;
|
|
22798
22608
|
});
|
|
22799
22609
|
ensureDir(fooDir);
|
|
22800
|
-
writeYamlFile(
|
|
22610
|
+
writeYamlFile(path21.join(fooDir, ".index.yaml"), {
|
|
22801
22611
|
id: subsystemId,
|
|
22802
22612
|
name: foo.name,
|
|
22803
22613
|
description: foo.description,
|
|
@@ -22824,9 +22634,9 @@ function internalizeSubsystem(subsystemId) {
|
|
|
22824
22634
|
const parentRoot = getProjectRoot();
|
|
22825
22635
|
const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
|
|
22826
22636
|
const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
|
|
22827
|
-
const childWai =
|
|
22828
|
-
const childFooDir =
|
|
22829
|
-
if (!
|
|
22637
|
+
const childWai = path21.join(childDir, ".wai");
|
|
22638
|
+
const childFooDir = path21.join(childDir, ".wai", "specs", subsystemId);
|
|
22639
|
+
if (!fs16.existsSync(childFooDir)) {
|
|
22830
22640
|
throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
|
|
22831
22641
|
}
|
|
22832
22642
|
const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
|
|
@@ -22839,16 +22649,16 @@ function internalizeSubsystem(subsystemId) {
|
|
|
22839
22649
|
false
|
|
22840
22650
|
);
|
|
22841
22651
|
const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
|
|
22842
|
-
const fooDir =
|
|
22843
|
-
|
|
22844
|
-
ensureDir(
|
|
22845
|
-
|
|
22652
|
+
const fooDir = path21.join(parentSpecsDir, subsystemId);
|
|
22653
|
+
fs16.rmSync(fooDir, { recursive: true, force: true });
|
|
22654
|
+
ensureDir(path21.dirname(fooDir));
|
|
22655
|
+
fs16.renameSync(childFooDir, fooDir);
|
|
22846
22656
|
rebaseImplementationPaths(fooDir, childDir, parentRoot);
|
|
22847
|
-
patchSubsystemIndex(
|
|
22657
|
+
patchSubsystemIndex(path21.join(fooDir, ".index.yaml"), (s) => {
|
|
22848
22658
|
s.parentSystem = parentSystemName;
|
|
22849
22659
|
delete s.projectPath;
|
|
22850
22660
|
});
|
|
22851
|
-
|
|
22661
|
+
fs16.rmSync(childWai, { recursive: true, force: true });
|
|
22852
22662
|
rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
|
|
22853
22663
|
rebaseMovedRefs(fooDir, subsystemId, "outOf");
|
|
22854
22664
|
invalidateSpecCache();
|
|
@@ -22926,8 +22736,8 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
|
|
|
22926
22736
|
let changed = false;
|
|
22927
22737
|
const rebase = (holder, key) => {
|
|
22928
22738
|
const p = holder[key];
|
|
22929
|
-
if (typeof p !== "string" || p === "" ||
|
|
22930
|
-
const next = toPosixPath(
|
|
22739
|
+
if (typeof p !== "string" || p === "" || path21.isAbsolute(p)) return;
|
|
22740
|
+
const next = toPosixPath(path21.relative(toRoot, path21.resolve(fromRoot, p)));
|
|
22931
22741
|
if (next !== p) {
|
|
22932
22742
|
holder[key] = next;
|
|
22933
22743
|
changed = true;
|
|
@@ -22943,7 +22753,7 @@ function rebaseImplementationPaths(specsDir, fromRoot, toRoot) {
|
|
|
22943
22753
|
}
|
|
22944
22754
|
}
|
|
22945
22755
|
function patchSubsystemIndex(indexPath, mutate) {
|
|
22946
|
-
if (!
|
|
22756
|
+
if (!fs16.existsSync(indexPath)) return;
|
|
22947
22757
|
const raw = readYamlFile(indexPath);
|
|
22948
22758
|
mutate(raw);
|
|
22949
22759
|
raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -23004,8 +22814,8 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
23004
22814
|
if (movedInterface) saveInterfaceSpec({ ...movedInterface, id: interfaceId, component: newId });
|
|
23005
22815
|
if (movedImplementation) {
|
|
23006
22816
|
const oldFile = getImplementationPath(movedImplementation.id);
|
|
23007
|
-
if (
|
|
23008
|
-
|
|
22817
|
+
if (path21.resolve(getImplementationPath(implementationId, movedImplementation.contract)) === path21.resolve(oldFile)) {
|
|
22818
|
+
fs16.unlinkSync(oldFile);
|
|
23009
22819
|
}
|
|
23010
22820
|
saveImplementationSpec({ ...movedImplementation, id: implementationId });
|
|
23011
22821
|
}
|
|
@@ -23015,17 +22825,17 @@ function moveRenamedSpecs(componentId, newId, component, movingInterface, moving
|
|
|
23015
22825
|
invalidateSpecCache();
|
|
23016
22826
|
}
|
|
23017
22827
|
function removeSpecFile2(file, id) {
|
|
23018
|
-
if (!
|
|
22828
|
+
if (!fs16.existsSync(file)) return;
|
|
23019
22829
|
try {
|
|
23020
22830
|
if (readYamlFile(file)?.id !== id) return;
|
|
23021
22831
|
} catch {
|
|
23022
22832
|
return;
|
|
23023
22833
|
}
|
|
23024
|
-
|
|
23025
|
-
const specsRoot =
|
|
23026
|
-
for (let dir =
|
|
23027
|
-
if (
|
|
23028
|
-
|
|
22834
|
+
fs16.unlinkSync(file);
|
|
22835
|
+
const specsRoot = path21.resolve(aiPathsAt(getProjectRoot()).specsDir());
|
|
22836
|
+
for (let dir = path21.dirname(path21.resolve(file)); dir !== specsRoot && isWithinDir(specsRoot, dir); dir = path21.dirname(dir)) {
|
|
22837
|
+
if (fs16.readdirSync(dir).length > 0) break;
|
|
22838
|
+
fs16.rmdirSync(dir);
|
|
23029
22839
|
}
|
|
23030
22840
|
}
|
|
23031
22841
|
function renameMethod(componentId, methodName, newName, pinSymbol) {
|
|
@@ -23122,12 +22932,12 @@ function collectMentions(specsDir, methodName, moved) {
|
|
|
23122
22932
|
function identifierPattern(methodName) {
|
|
23123
22933
|
return new RegExp(`(?<![A-Za-z0-9_])${methodName}(?![A-Za-z0-9_])`);
|
|
23124
22934
|
}
|
|
23125
|
-
var
|
|
22935
|
+
var fs16, path21, METHOD_NAME, PROSE_FIELDS2;
|
|
23126
22936
|
var init_provision = __esm({
|
|
23127
22937
|
"src/core/provision.ts"() {
|
|
23128
22938
|
"use strict";
|
|
23129
|
-
|
|
23130
|
-
|
|
22939
|
+
fs16 = __toESM(require("fs"));
|
|
22940
|
+
path21 = __toESM(require("path"));
|
|
23131
22941
|
init_specs2();
|
|
23132
22942
|
init_paths();
|
|
23133
22943
|
init_project_config();
|
|
@@ -23293,8 +23103,8 @@ var init_budget_policy = __esm({
|
|
|
23293
23103
|
|
|
23294
23104
|
// src/core/agent_resolver.ts
|
|
23295
23105
|
function listFilesRecursiveSafe(dirPath, ext) {
|
|
23296
|
-
if (!
|
|
23297
|
-
const nameLower =
|
|
23106
|
+
if (!fs17.existsSync(dirPath)) return [];
|
|
23107
|
+
const nameLower = path22.basename(dirPath).toLowerCase();
|
|
23298
23108
|
const IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
23299
23109
|
"node_modules",
|
|
23300
23110
|
"target",
|
|
@@ -23309,10 +23119,10 @@ function listFilesRecursiveSafe(dirPath, ext) {
|
|
|
23309
23119
|
".vscode"
|
|
23310
23120
|
]);
|
|
23311
23121
|
if (IGNORED_DIRS.has(nameLower)) return [];
|
|
23312
|
-
const entries =
|
|
23122
|
+
const entries = fs17.readdirSync(dirPath, { withFileTypes: true });
|
|
23313
23123
|
const files = [];
|
|
23314
23124
|
for (const entry of entries) {
|
|
23315
|
-
const fullPath =
|
|
23125
|
+
const fullPath = path22.join(dirPath, entry.name);
|
|
23316
23126
|
if (entry.isDirectory()) {
|
|
23317
23127
|
files.push(...listFilesRecursiveSafe(fullPath, ext));
|
|
23318
23128
|
} else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
@@ -23325,8 +23135,8 @@ function getProjectFiles(projectDir) {
|
|
|
23325
23135
|
let files = projectFilesCache.get(projectDir);
|
|
23326
23136
|
if (!files) {
|
|
23327
23137
|
files = [];
|
|
23328
|
-
const srcDir =
|
|
23329
|
-
const legacySrcDir =
|
|
23138
|
+
const srcDir = path22.join(projectDir, "src");
|
|
23139
|
+
const legacySrcDir = path22.join(projectDir, "legacy-src");
|
|
23330
23140
|
let searchDir = projectDir;
|
|
23331
23141
|
if (pathExists(srcDir)) {
|
|
23332
23142
|
searchDir = srcDir;
|
|
@@ -23341,7 +23151,7 @@ function getProjectFiles(projectDir) {
|
|
|
23341
23151
|
files.push(...listFilesRecursiveSafe(searchDir, ext));
|
|
23342
23152
|
}
|
|
23343
23153
|
const rootDir = getProjectRoot();
|
|
23344
|
-
files = files.map((f) =>
|
|
23154
|
+
files = files.map((f) => path22.relative(rootDir, f).replace(/\\/g, "/"));
|
|
23345
23155
|
projectFilesCache.set(projectDir, files);
|
|
23346
23156
|
}
|
|
23347
23157
|
return files;
|
|
@@ -23366,8 +23176,8 @@ function inferSourcePathForComponent(comp, subsystems) {
|
|
|
23366
23176
|
let bestFile = null;
|
|
23367
23177
|
let bestScore = -1;
|
|
23368
23178
|
for (const f of files) {
|
|
23369
|
-
const ext =
|
|
23370
|
-
const base =
|
|
23179
|
+
const ext = path22.extname(f);
|
|
23180
|
+
const base = path22.basename(f, ext).toLowerCase();
|
|
23371
23181
|
if (candidates.has(base)) {
|
|
23372
23182
|
let score = 0;
|
|
23373
23183
|
const normalizedPath = f.toLowerCase();
|
|
@@ -23464,7 +23274,7 @@ function resolveAgentTopology() {
|
|
|
23464
23274
|
});
|
|
23465
23275
|
for (const sub of subsystems) {
|
|
23466
23276
|
if (sub.projectPath) {
|
|
23467
|
-
const mountSpecPath =
|
|
23277
|
+
const mountSpecPath = path22.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
|
|
23468
23278
|
agents.push({
|
|
23469
23279
|
id: `${sub.id}-owner`,
|
|
23470
23280
|
name: `${sub.name} (chained subproject)`,
|
|
@@ -23486,9 +23296,9 @@ function resolveAgentTopology() {
|
|
|
23486
23296
|
}
|
|
23487
23297
|
const subComponents = components.filter((c) => c.subsystem === sub.id);
|
|
23488
23298
|
const ownedPaths = [];
|
|
23489
|
-
ownedPaths.push(
|
|
23299
|
+
ownedPaths.push(path22.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
|
|
23490
23300
|
for (const c of subComponents) {
|
|
23491
|
-
ownedPaths.push(
|
|
23301
|
+
ownedPaths.push(path22.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
|
|
23492
23302
|
}
|
|
23493
23303
|
if (!config.rules.generateComponentImplementers) {
|
|
23494
23304
|
for (const comp of subComponents) {
|
|
@@ -23564,10 +23374,10 @@ function resolveAgentTopology() {
|
|
|
23564
23374
|
}
|
|
23565
23375
|
const dependencies = comp.dependsOn.map((depId) => `${depId}-implementer`);
|
|
23566
23376
|
const readPaths = [
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
...compInterfaces.map((i) =>
|
|
23570
|
-
...compImpls.map((impl) =>
|
|
23377
|
+
path22.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
|
|
23378
|
+
path22.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
|
|
23379
|
+
...compInterfaces.map((i) => path22.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
|
|
23380
|
+
...compImpls.map((impl) => path22.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
|
|
23571
23381
|
];
|
|
23572
23382
|
agents.push({
|
|
23573
23383
|
id: `${comp.id}-implementer`,
|
|
@@ -23665,12 +23475,12 @@ function loadRegistry() {
|
|
|
23665
23475
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
23666
23476
|
};
|
|
23667
23477
|
}
|
|
23668
|
-
var
|
|
23478
|
+
var path22, fs17, projectFilesCache, UnknownAgentError;
|
|
23669
23479
|
var init_agent_resolver = __esm({
|
|
23670
23480
|
"src/core/agent_resolver.ts"() {
|
|
23671
23481
|
"use strict";
|
|
23672
|
-
|
|
23673
|
-
|
|
23482
|
+
path22 = __toESM(require("path"));
|
|
23483
|
+
fs17 = __toESM(require("fs"));
|
|
23674
23484
|
init_topology();
|
|
23675
23485
|
init_paths();
|
|
23676
23486
|
init_registry();
|
|
@@ -23832,16 +23642,16 @@ function packNamespace(pack) {
|
|
|
23832
23642
|
return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
23833
23643
|
}
|
|
23834
23644
|
function extensionsFor(builtin, packSkills) {
|
|
23835
|
-
return packSkills.filter((s) => s.extends === builtin &&
|
|
23645
|
+
return packSkills.filter((s) => s.extends === builtin && fs18.existsSync(s.sourcePath));
|
|
23836
23646
|
}
|
|
23837
23647
|
function composeBuiltinSkill(name, packSkills) {
|
|
23838
23648
|
const srcPath = skillTemplatePath(name);
|
|
23839
|
-
const base =
|
|
23649
|
+
const base = fs18.existsSync(srcPath) ? fs18.readFileSync(srcPath, "utf-8") : "";
|
|
23840
23650
|
const sections = extensionsFor(name, packSkills);
|
|
23841
23651
|
if (sections.length === 0) return base;
|
|
23842
23652
|
const parts = [base.trimEnd()];
|
|
23843
23653
|
for (const section of sections) {
|
|
23844
|
-
const body =
|
|
23654
|
+
const body = fs18.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
|
|
23845
23655
|
parts.push(`## Platform: ${section.pack}`, body.trim());
|
|
23846
23656
|
}
|
|
23847
23657
|
return `${parts.join("\n\n")}
|
|
@@ -23857,16 +23667,16 @@ function readFrontmatter(raw, fallbackName) {
|
|
|
23857
23667
|
return { name: field("name") || fallbackName, description: field("description") };
|
|
23858
23668
|
}
|
|
23859
23669
|
function builtinSkillsDir() {
|
|
23860
|
-
return
|
|
23670
|
+
return path23.resolve(__dirname, "..", "templates", "skills");
|
|
23861
23671
|
}
|
|
23862
23672
|
function skillTemplatePath(name) {
|
|
23863
|
-
return
|
|
23673
|
+
return path23.join(builtinSkillsDir(), `${name}.md`);
|
|
23864
23674
|
}
|
|
23865
23675
|
function skillDestPath(type, destDir, name) {
|
|
23866
23676
|
if (type === "claude" || type === "codex" || type === "gemini" || type === "agy") {
|
|
23867
|
-
return
|
|
23677
|
+
return path23.join(destDir, name, "SKILL.md");
|
|
23868
23678
|
}
|
|
23869
|
-
return
|
|
23679
|
+
return path23.join(destDir, `${name}.md`);
|
|
23870
23680
|
}
|
|
23871
23681
|
function skillsDirForTarget(type) {
|
|
23872
23682
|
switch (type) {
|
|
@@ -23901,22 +23711,22 @@ function exportSddSkills(targetTypes) {
|
|
|
23901
23711
|
ensureDir(destDir);
|
|
23902
23712
|
destinations.push(destDir);
|
|
23903
23713
|
for (const name of SKILL_NAMES) {
|
|
23904
|
-
if (!
|
|
23714
|
+
if (!fs18.existsSync(skillTemplatePath(name))) continue;
|
|
23905
23715
|
const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
|
|
23906
23716
|
const destPath = skillDestPath(type, destDir, name);
|
|
23907
|
-
ensureDir(
|
|
23908
|
-
|
|
23717
|
+
ensureDir(path23.dirname(destPath));
|
|
23718
|
+
fs18.writeFileSync(destPath, content, "utf-8");
|
|
23909
23719
|
fileCount++;
|
|
23910
23720
|
}
|
|
23911
23721
|
for (const skill of packSkills) {
|
|
23912
23722
|
if (skill.extends !== void 0) continue;
|
|
23913
23723
|
if (!skill.targets.includes(type)) continue;
|
|
23914
|
-
if (!
|
|
23724
|
+
if (!fs18.existsSync(skill.sourcePath)) continue;
|
|
23915
23725
|
const id = packSkillId(skill);
|
|
23916
|
-
const content =
|
|
23726
|
+
const content = fs18.readFileSync(skill.sourcePath, "utf-8");
|
|
23917
23727
|
const destPath = skillDestPath(type, destDir, id);
|
|
23918
|
-
ensureDir(
|
|
23919
|
-
|
|
23728
|
+
ensureDir(path23.dirname(destPath));
|
|
23729
|
+
fs18.writeFileSync(destPath, content, "utf-8");
|
|
23920
23730
|
fileCount++;
|
|
23921
23731
|
}
|
|
23922
23732
|
}
|
|
@@ -23929,12 +23739,12 @@ function checkSkillFreshness(type) {
|
|
|
23929
23739
|
const packSkills = loadProjectExtensions2().skills.filter((s) => s.targets.includes(type));
|
|
23930
23740
|
for (const name of SKILL_NAMES) {
|
|
23931
23741
|
const destPath = skillDestPath(type, dir, name);
|
|
23932
|
-
if (!
|
|
23742
|
+
if (!fs18.existsSync(destPath)) {
|
|
23933
23743
|
result.missing.push(name);
|
|
23934
23744
|
continue;
|
|
23935
23745
|
}
|
|
23936
23746
|
const want = composeBuiltinSkill(name, packSkills);
|
|
23937
|
-
const have =
|
|
23747
|
+
const have = fs18.readFileSync(destPath, "utf-8");
|
|
23938
23748
|
if (have === want) result.ok.push(name);
|
|
23939
23749
|
else result.stale.push(name);
|
|
23940
23750
|
}
|
|
@@ -23946,7 +23756,7 @@ function activeTargetTypes2() {
|
|
|
23946
23756
|
return activeTargetTypes(config);
|
|
23947
23757
|
}
|
|
23948
23758
|
function readSkillFrontmatter(name) {
|
|
23949
|
-
return readFrontmatter(
|
|
23759
|
+
return readFrontmatter(fs18.readFileSync(skillTemplatePath(name), "utf-8"), name);
|
|
23950
23760
|
}
|
|
23951
23761
|
function listSkillResources() {
|
|
23952
23762
|
const builtin = RESOURCE_SKILL_IDS.map((id) => {
|
|
@@ -23960,9 +23770,9 @@ function listSkillResources() {
|
|
|
23960
23770
|
defaultForHostedMcp: true
|
|
23961
23771
|
};
|
|
23962
23772
|
});
|
|
23963
|
-
const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 &&
|
|
23773
|
+
const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs18.existsSync(s.sourcePath)).map((skill) => {
|
|
23964
23774
|
const id = packSkillId(skill);
|
|
23965
|
-
const fm = readFrontmatter(
|
|
23775
|
+
const fm = readFrontmatter(fs18.readFileSync(skill.sourcePath, "utf-8"), id);
|
|
23966
23776
|
return {
|
|
23967
23777
|
id,
|
|
23968
23778
|
name: fm.name,
|
|
@@ -23978,8 +23788,8 @@ function readSkillResource(resourceId) {
|
|
|
23978
23788
|
const packSkills = loadProjectExtensions2().skills;
|
|
23979
23789
|
if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
|
|
23980
23790
|
const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
|
|
23981
|
-
if (packSkill) return
|
|
23982
|
-
return
|
|
23791
|
+
if (packSkill) return fs18.readFileSync(packSkill.sourcePath, "utf-8");
|
|
23792
|
+
return fs18.readFileSync(skillTemplatePath(resourceId), "utf-8");
|
|
23983
23793
|
}
|
|
23984
23794
|
function listResources() {
|
|
23985
23795
|
return listSkillResources();
|
|
@@ -23992,12 +23802,12 @@ function readResource(resourceId) {
|
|
|
23992
23802
|
if (!known) throw new SkillResourceNotFoundError(resourceId);
|
|
23993
23803
|
return readSkillResource(resourceId);
|
|
23994
23804
|
}
|
|
23995
|
-
var
|
|
23805
|
+
var path23, fs18, SKILL_NAMES, SKILL_RESOURCE_SCHEME, RESOURCE_SKILL_IDS, SkillResourceNotFoundError;
|
|
23996
23806
|
var init_skills = __esm({
|
|
23997
23807
|
"src/core/skills.ts"() {
|
|
23998
23808
|
"use strict";
|
|
23999
|
-
|
|
24000
|
-
|
|
23809
|
+
path23 = __toESM(require("path"));
|
|
23810
|
+
fs18 = __toESM(require("fs"));
|
|
24001
23811
|
init_fs();
|
|
24002
23812
|
init_defaults();
|
|
24003
23813
|
init_project();
|
|
@@ -24016,6 +23826,179 @@ var init_skills = __esm({
|
|
|
24016
23826
|
}
|
|
24017
23827
|
});
|
|
24018
23828
|
|
|
23829
|
+
// src/core/stamp.ts
|
|
23830
|
+
function versionStamp() {
|
|
23831
|
+
return `<!-- wairon-version: ${WAIRON_VERSION} -->`;
|
|
23832
|
+
}
|
|
23833
|
+
function readStampVersion(content) {
|
|
23834
|
+
const m = content.match(STAMP_RE);
|
|
23835
|
+
return m ? m[1] : null;
|
|
23836
|
+
}
|
|
23837
|
+
var STAMP_RE;
|
|
23838
|
+
var init_stamp = __esm({
|
|
23839
|
+
"src/core/stamp.ts"() {
|
|
23840
|
+
"use strict";
|
|
23841
|
+
init_defaults();
|
|
23842
|
+
STAMP_RE = /<!--\s*wairon-version:\s*([^\s]+)\s*-->/;
|
|
23843
|
+
}
|
|
23844
|
+
});
|
|
23845
|
+
|
|
23846
|
+
// src/utils/ai-guide.ts
|
|
23847
|
+
function globalGuideFilePath(targetType) {
|
|
23848
|
+
if (targetType === "claude") return path24.join(process.env["CLAUDE_CONFIG_DIR"] || path24.join(os5.homedir(), ".claude"), "CLAUDE.md");
|
|
23849
|
+
if (targetType === "gemini") return path24.join(process.env["GEMINI_CONFIG_DIR"] || path24.join(os5.homedir(), ".gemini"), "GEMINI.md");
|
|
23850
|
+
return null;
|
|
23851
|
+
}
|
|
23852
|
+
function localGuideFilePath(projectRoot2, targetType) {
|
|
23853
|
+
if (targetType === "claude") return path24.join(projectRoot2, ".claude", "CLAUDE.md");
|
|
23854
|
+
if (targetType === "gemini" || targetType === "agy") return path24.join(projectRoot2, ".gemini", "GEMINI.md");
|
|
23855
|
+
return null;
|
|
23856
|
+
}
|
|
23857
|
+
function injectGuide(filePath, scope) {
|
|
23858
|
+
const body = scope === "global" ? GLOBAL_GUIDE_BODY : LOCAL_GUIDE_BODY;
|
|
23859
|
+
const section = `
|
|
23860
|
+
|
|
23861
|
+
${GUIDE_MARKER_START}
|
|
23862
|
+
${versionStamp()}
|
|
23863
|
+
${body}
|
|
23864
|
+
${GUIDE_MARKER_END}
|
|
23865
|
+
`;
|
|
23866
|
+
const existing = fs19.existsSync(filePath) ? fs19.readFileSync(filePath, "utf-8") : "";
|
|
23867
|
+
const stripped = stripGuideSection(existing);
|
|
23868
|
+
const newContent = stripped.trimEnd() + section;
|
|
23869
|
+
fs19.mkdirSync(path24.dirname(filePath), { recursive: true });
|
|
23870
|
+
fs19.writeFileSync(filePath, newContent, "utf-8");
|
|
23871
|
+
}
|
|
23872
|
+
function stripGuideSection(content) {
|
|
23873
|
+
const start2 = content.indexOf(GUIDE_MARKER_START);
|
|
23874
|
+
const end = content.indexOf(GUIDE_MARKER_END);
|
|
23875
|
+
if (start2 === -1 || end === -1) return content;
|
|
23876
|
+
return content.slice(0, start2) + content.slice(end + GUIDE_MARKER_END.length);
|
|
23877
|
+
}
|
|
23878
|
+
function writeRootGuideDelegator(projectRoot2, targetType) {
|
|
23879
|
+
if (targetType === "claude") {
|
|
23880
|
+
const filePath = path24.join(projectRoot2, "CLAUDE.md");
|
|
23881
|
+
const content = `@.claude/CLAUDE.md
|
|
23882
|
+
|
|
23883
|
+
# Wairon SDD Project
|
|
23884
|
+
|
|
23885
|
+
This project uses the Wairon Spec-Driven Development (SDD) framework. The imported
|
|
23886
|
+
\`.claude/CLAUDE.md\` above is your complete operating guide \u2014 you already have the
|
|
23887
|
+
full context, so don't search the project to learn how wairon or SDD works.
|
|
23888
|
+
|
|
23889
|
+
To design or modify the system, invoke the **\`sdd-architect\`** skill
|
|
23890
|
+
(in \`.claude/skills/\`). Author and validate specs with the \`sdd_*\` MCP tools;
|
|
23891
|
+
the \`wairon\` CLI is the human developer's tool, not yours.
|
|
23892
|
+
`;
|
|
23893
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
23894
|
+
} else if (targetType === "gemini" || targetType === "agy") {
|
|
23895
|
+
const filePath = path24.join(projectRoot2, "GEMINI.md");
|
|
23896
|
+
const content = `# Wairon SDD Project
|
|
23897
|
+
${GUIDE_MARKER_START}
|
|
23898
|
+
${versionStamp()}
|
|
23899
|
+
${LOCAL_GUIDE_BODY}
|
|
23900
|
+
${GUIDE_MARKER_END}
|
|
23901
|
+
`;
|
|
23902
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
23903
|
+
} else if (targetType === "cursor") {
|
|
23904
|
+
const filePath = path24.join(projectRoot2, ".cursorrules");
|
|
23905
|
+
const content = `# Wairon SDD Project
|
|
23906
|
+
|
|
23907
|
+
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
23908
|
+
|
|
23909
|
+
Refer to the rules in [.cursor/rules/](.cursor/rules/) for full instructions.
|
|
23910
|
+
`;
|
|
23911
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
23912
|
+
} else if (targetType === "copilot") {
|
|
23913
|
+
const filePath = path24.join(projectRoot2, ".github", "copilot-instructions.md");
|
|
23914
|
+
fs19.mkdirSync(path24.dirname(filePath), { recursive: true });
|
|
23915
|
+
const content = `# Wairon SDD Project
|
|
23916
|
+
|
|
23917
|
+
This project uses the Wairon Spec-Driven Development (SDD) framework.
|
|
23918
|
+
|
|
23919
|
+
Refer to the prompts in [.github/prompts/](.github/prompts/) for instructions.
|
|
23920
|
+
`;
|
|
23921
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
23922
|
+
} else if (targetType === "codex") {
|
|
23923
|
+
const filePath = path24.join(projectRoot2, ".codexrules");
|
|
23924
|
+
const content = `# Wairon SDD Project
|
|
23925
|
+
|
|
23926
|
+
Refer to [.codex/agents/](.codex/agents/) for full instructions.
|
|
23927
|
+
`;
|
|
23928
|
+
fs19.writeFileSync(filePath, content, "utf-8");
|
|
23929
|
+
}
|
|
23930
|
+
}
|
|
23931
|
+
function reinjectLocalGuides(projectRoot2, targetTypes) {
|
|
23932
|
+
const written = [];
|
|
23933
|
+
for (const type of targetTypes) {
|
|
23934
|
+
if (!GUIDE_TARGETS.includes(type)) continue;
|
|
23935
|
+
const guidePath = localGuideFilePath(projectRoot2, type);
|
|
23936
|
+
if (guidePath) {
|
|
23937
|
+
injectGuide(guidePath, "local");
|
|
23938
|
+
if (!written.includes(guidePath)) written.push(guidePath);
|
|
23939
|
+
}
|
|
23940
|
+
writeRootGuideDelegator(projectRoot2, type);
|
|
23941
|
+
}
|
|
23942
|
+
return written;
|
|
23943
|
+
}
|
|
23944
|
+
var fs19, os5, path24, GUIDE_MARKER_START, GUIDE_MARKER_END, GLOBAL_GUIDE_BODY, LOCAL_GUIDE_BODY, GUIDE_TARGETS;
|
|
23945
|
+
var init_ai_guide = __esm({
|
|
23946
|
+
"src/utils/ai-guide.ts"() {
|
|
23947
|
+
"use strict";
|
|
23948
|
+
fs19 = __toESM(require("fs"));
|
|
23949
|
+
os5 = __toESM(require("os"));
|
|
23950
|
+
path24 = __toESM(require("path"));
|
|
23951
|
+
init_stamp();
|
|
23952
|
+
GUIDE_MARKER_START = "<!-- wairon-guide-start -->";
|
|
23953
|
+
GUIDE_MARKER_END = "<!-- wairon-guide-end -->";
|
|
23954
|
+
GLOBAL_GUIDE_BODY = `## wairon \u2014 Spec-Driven Development (optional)
|
|
23955
|
+
|
|
23956
|
+
If \`.wai/specs/\` exists, the wairon SDD workflow is active; otherwise ignore it. wairon does not orchestrate sessions \u2014 it equips yours.
|
|
23957
|
+
|
|
23958
|
+
### In SDD Projects:
|
|
23959
|
+
- **Source of Truth**: All architecture lives in the spec tree under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 L5 Narrative). Do not edit generated agent config files under \`.claude/agents/\` (rebuilt via \`wairon generate\`).
|
|
23960
|
+
- **Validation**: Conformance checks (stereotype rules, cycle checks, reference integrity) are run via the \`sdd_validate_tree\` MCP tool.
|
|
23961
|
+
- **Operating Rules**:
|
|
23962
|
+
1. **Skills**: Use \`sdd-architect\` to design (and \`sdd-implement\`, \`sdd-narrative\`, \`sdd-auditor\`). Refer to project's local guide file for detailed constraints.
|
|
23963
|
+
2. **MCP Tools Only**: Author/validate specs *only* via \`sdd_*\` tools (e.g. \`sdd_initialize_system\`, \`sdd_validate_tree\`).
|
|
23964
|
+
3. **No CLI Exec**: Do not run the \`wairon\` CLI (human tool). Use MCP tools \`sdd_validate_tree\` and \`sdd_get_status\` instead.
|
|
23965
|
+
4. **Delegation**: Delegate implementation via the \`sdd-delegate\` skill \u2014 live agent briefs (\`sdd_get_agent_brief\` MCP tool / \`wairon-agent://\` resource) are composed per call and always current; no session restart. Generated agent files are an optional materialized view of the same topology. User-owned per-agent guidance may live in \`.wai/agents/<agent-id>.md\` (folded into every brief; scaffold via \`wairon agent customize <id>\`).
|
|
23966
|
+
5. **Design First**: Complete spec and pass \`sdd_validate_tree\` before writing code.
|
|
23967
|
+
6. **Consistency**: Code must match L3 interfaces and L5 narratives exactly. If the spec is wrong, stop and update the spec.
|
|
23968
|
+
7. **Subprojects & Namespacing**: If a subsystem uses \`projectPath\` delegation, target its specs using namespaced IDs (e.g. \`subsystem::component\`). Use leading \`::\` to target root (e.g. \`::shared::type\`) and \`super::\` to go up a level (e.g. \`super::sibling\`). wairon automatically resolves the path and strips the prefix on writes.`;
|
|
23969
|
+
LOCAL_GUIDE_BODY = `## Wairon \u2014 Spec-Driven Development (you are operating inside it)
|
|
23970
|
+
|
|
23971
|
+
This project uses **wairon**. System specs live under \`.wai/specs/\` (L0 System \u2192 L1 Subsystem \u2192 L2 Component \u2192 L3 Interface \u2192 L4 Implementation \u2192 Narrative); agent topology and code are derived from it.
|
|
23972
|
+
|
|
23973
|
+
**Do NOT search files or read agent configs to learn about wairon or SDD. Use the context here and the \`sdd-architect\` skill to start.**
|
|
23974
|
+
|
|
23975
|
+
**Your first move: call the \`sdd_get_status\` MCP tool** (or \`wairon/sdd_get_status\`) to see the spec tree. Do not parse files or run CLI commands manually.
|
|
23976
|
+
|
|
23977
|
+
### How you operate
|
|
23978
|
+
- **To design/modify specs**: Use **\`sdd-architect\`** skill (in \`.claude/skills/\` or \`.gemini/skills/\`).
|
|
23979
|
+
- **Manage specs via MCP tools only**: Use \`sdd_initialize_system\`, \`sdd_add_subsystem\`, \`sdd_add_component\`, \`sdd_define_interface\`, \`sdd_write_narrative\`, \`sdd_add_type\`, \`sdd_get_spec\`, \`sdd_delete_spec\`, \`sdd_validate_tree\`, and \`sdd_get_status\` (namespaced if needed). Do not edit specs manually.
|
|
23980
|
+
- **Subprojects & Namespacing (Chaining)**: If a subsystem defines a \`projectPath\`, its entire \`.wai/\` spec tree is recursively loaded and namespaced with the subsystem ID as a prefix (using \`::\`, e.g. \`billing::invoice::invoice_portal\`). Use the qualified namespaced ID with the parent MCP tools; wairon will resolve the path and strip the prefix automatically.
|
|
23981
|
+
- **Leading \`::\`**: Bypasses the local subsystem prefix to resolve absolute from the system root (e.g. \`::shared::error-type\`).
|
|
23982
|
+
- **\`super::\`**: Goes up one parent subsystem level (e.g. \`super::sibling_comp\`, \`super::super::parent_sibling\`).
|
|
23983
|
+
- **Do not run the \`wairon\` CLI**: Use \`sdd_validate_tree\` and \`sdd_get_status\` instead of CLI commands.
|
|
23984
|
+
- **Handoff to implementation**: Once design is complete and validates cleanly, tell the human: *"The specs are complete and validate. Please run \`wairon lock\` to confirm and freeze them."* No session restart is needed after the lock \u2014 delegate implementation right away via the \`sdd-delegate\` skill.
|
|
23985
|
+
- **To implement code**: Delegate via the \`sdd-delegate\` skill: fetch the component's live brief with the \`sdd_get_agent_brief\` MCP tool (or the \`wairon-agent://\` resource) and spawn a subagent from it. Briefs are composed per call from the current spec tree, so they are always current \u2014 never wait for a restart. Implementations must match L3 interfaces and L5 narratives exactly. Generated agent files under \`.claude/agents/\` are an optional materialized view of the same topology \u2014 the live briefs are canonical.
|
|
23986
|
+
|
|
23987
|
+
### Rules (enforced by \`sdd_validate_tree\`)
|
|
23988
|
+
1. **Design before code**: Complete spec and pass validator before writing source code.
|
|
23989
|
+
2. **Human-in-the-loop**: Ask user approval for each spec layer before proceeding.
|
|
23990
|
+
3. **Spec consistency**: If a 1:1 narrative match is incorrect or conflicts with L0 requirements, escalate a spec revision first. Never ship mismatched code.
|
|
23991
|
+
4. **No persistence shortcuts & strict layers**: A Portal must never depend directly on a Store, Registry, or Adapter. Portal reads MAY go through a Repository/Index facade (passthrough reads need no per-entity Orchestrator ceremony), but a Portal narrative call or dispatch-table binding that reaches a write-effect facade method is an error (\`PORTAL_WRITE_SHORTCUT\`) \u2014 writes always route through an Orchestrator. Held domain state always lives in a dedicated data component, never as fields inside an Orchestrator. Two sanctioned shapes: the RECOMMENDED Repository pattern (owns Store + Registry + Index; consumers depend on the facade), or \u2014 for genuinely simple state \u2014 a deliberately standalone Store (workflow-layer consumers only, acknowledged with a lint.allow reason on the UNOWNED_STORE warning). Never combine Store/Registry/Index roles into one component, and never fold state into a consuming component because a link was refused.
|
|
23992
|
+
|
|
23993
|
+
### Component Vocabulary
|
|
23994
|
+
* **Blocks**: Portal, Orchestrator, Supervisor, Actor, Store, Index, Query, Registry, Adapter, Observer.
|
|
23995
|
+
* **Patterns**: Repository \u2014 the composable pattern that \`owns\` its member blocks: one Store with its Registry, Indexes and Queries, and optionally an Adapter.
|
|
23996
|
+
* **Variants**: \`gateway\`, a Portal that authenticates, authorizes, validates or rate-limits before it dispatches. Logic is an Orchestrator, and \`dependencyClass: pure | read\` bounds what it may depend on (unset = a workflow). Specialist and Gateway are retired stereotypes.
|
|
23997
|
+
* Use \`owns\` for private member containment (exactly one hop) and \`dependsOn\` for collaborators. Never use generic suffixes like "Manager", "Helper", or "Utils".`;
|
|
23998
|
+
GUIDE_TARGETS = ["claude", "gemini", "agy", "cursor", "copilot", "codex"];
|
|
23999
|
+
}
|
|
24000
|
+
});
|
|
24001
|
+
|
|
24019
24002
|
// src/core/context.ts
|
|
24020
24003
|
function contextDir(...segments) {
|
|
24021
24004
|
return aiDir("context", ...segments);
|
|
@@ -28275,6 +28258,8 @@ var init_core = __esm({
|
|
|
28275
28258
|
init_project_config();
|
|
28276
28259
|
init_execution_profile();
|
|
28277
28260
|
init_budget_policy();
|
|
28261
|
+
init_ai_guide();
|
|
28262
|
+
init_stamp();
|
|
28278
28263
|
}
|
|
28279
28264
|
});
|
|
28280
28265
|
|
|
@@ -31043,7 +31028,6 @@ var import_inquirer = __toESM(require("inquirer"));
|
|
|
31043
31028
|
init_logger();
|
|
31044
31029
|
init_errors();
|
|
31045
31030
|
init_fs();
|
|
31046
|
-
init_ai_guide();
|
|
31047
31031
|
init_yaml();
|
|
31048
31032
|
init_paths();
|
|
31049
31033
|
|
|
@@ -31130,6 +31114,24 @@ function deriveExecutionProfile2(agent) {
|
|
|
31130
31114
|
function resolveBudget2(profile, config, agentId) {
|
|
31131
31115
|
return resolveBudget(profile, config, agentId);
|
|
31132
31116
|
}
|
|
31117
|
+
function globalGuideFilePath2(target) {
|
|
31118
|
+
return globalGuideFilePath(target);
|
|
31119
|
+
}
|
|
31120
|
+
function localGuideFilePath2(projectRoot2, target) {
|
|
31121
|
+
return localGuideFilePath(projectRoot2, target);
|
|
31122
|
+
}
|
|
31123
|
+
function injectGuide2(filePath, scope) {
|
|
31124
|
+
injectGuide(filePath, scope);
|
|
31125
|
+
}
|
|
31126
|
+
function writeRootGuideDelegator2(projectRoot2, target) {
|
|
31127
|
+
writeRootGuideDelegator(projectRoot2, target);
|
|
31128
|
+
}
|
|
31129
|
+
function reinjectLocalGuides2(projectRoot2, targets) {
|
|
31130
|
+
return reinjectLocalGuides(projectRoot2, targets);
|
|
31131
|
+
}
|
|
31132
|
+
function readStampVersion2(content) {
|
|
31133
|
+
return readStampVersion(content);
|
|
31134
|
+
}
|
|
31133
31135
|
async function runSubsystemAdd(id, options = {}) {
|
|
31134
31136
|
logger.header("wairon subsystem add");
|
|
31135
31137
|
if (!projectConfigExists2()) {
|
|
@@ -31478,39 +31480,39 @@ async function executeInit(projectName, projectConfig, guidePlan) {
|
|
|
31478
31480
|
writeStarterDesignGuide(projectName);
|
|
31479
31481
|
writeStarterProjectContext(projectName);
|
|
31480
31482
|
if (guidePlan.claudeGlobal) {
|
|
31481
|
-
const p =
|
|
31482
|
-
|
|
31483
|
+
const p = globalGuideFilePath2("claude");
|
|
31484
|
+
injectGuide2(p, "global");
|
|
31483
31485
|
logger.success(`Injected wairon guide into ${p}`);
|
|
31484
31486
|
}
|
|
31485
31487
|
if (guidePlan.claudeLocal) {
|
|
31486
|
-
const p =
|
|
31487
|
-
|
|
31488
|
+
const p = localGuideFilePath2(projectRoot2, "claude");
|
|
31489
|
+
injectGuide2(p, "local");
|
|
31488
31490
|
logger.success(`Injected wairon guide into ${path34.relative(cwd, p)}`);
|
|
31489
|
-
|
|
31491
|
+
writeRootGuideDelegator2(projectRoot2, "claude");
|
|
31490
31492
|
logger.success(`Created root CLAUDE.md delegator pointing to .claude/CLAUDE.md`);
|
|
31491
31493
|
}
|
|
31492
31494
|
if (guidePlan.geminiGlobal) {
|
|
31493
|
-
const p =
|
|
31494
|
-
|
|
31495
|
+
const p = globalGuideFilePath2("gemini");
|
|
31496
|
+
injectGuide2(p, "global");
|
|
31495
31497
|
logger.success(`Injected wairon guide into ${p}`);
|
|
31496
31498
|
}
|
|
31497
31499
|
if (guidePlan.geminiLocal) {
|
|
31498
|
-
const p =
|
|
31499
|
-
|
|
31500
|
+
const p = localGuideFilePath2(projectRoot2, "gemini");
|
|
31501
|
+
injectGuide2(p, "local");
|
|
31500
31502
|
logger.success(`Injected wairon guide into ${path34.relative(cwd, p)}`);
|
|
31501
|
-
|
|
31503
|
+
writeRootGuideDelegator2(projectRoot2, "gemini");
|
|
31502
31504
|
logger.success(`Created root GEMINI.md delegator pointing to .gemini/GEMINI.md`);
|
|
31503
31505
|
}
|
|
31504
31506
|
if (targetTypes.includes("cursor")) {
|
|
31505
|
-
|
|
31507
|
+
writeRootGuideDelegator2(projectRoot2, "cursor");
|
|
31506
31508
|
logger.success(`Created root .cursorrules pointing to .cursor/rules/`);
|
|
31507
31509
|
}
|
|
31508
31510
|
if (targetTypes.includes("copilot")) {
|
|
31509
|
-
|
|
31511
|
+
writeRootGuideDelegator2(projectRoot2, "copilot");
|
|
31510
31512
|
logger.success(`Created root .github/copilot-instructions.md pointing to .github/prompts/`);
|
|
31511
31513
|
}
|
|
31512
31514
|
if (targetTypes.includes("codex")) {
|
|
31513
|
-
|
|
31515
|
+
writeRootGuideDelegator2(projectRoot2, "codex");
|
|
31514
31516
|
logger.success(`Created root .codexrules pointing to .codex/agents/`);
|
|
31515
31517
|
}
|
|
31516
31518
|
if (targetTypes.includes("claude")) {
|
|
@@ -31800,7 +31802,6 @@ async function generateLayer(options = {}) {
|
|
|
31800
31802
|
}
|
|
31801
31803
|
}
|
|
31802
31804
|
try {
|
|
31803
|
-
const { reinjectLocalGuides: reinjectLocalGuides2 } = (init_ai_guide(), __toCommonJS(ai_guide_exports));
|
|
31804
31805
|
reinjectLocalGuides2(getProjectRoot(), activeTargetTypes(projectConfig));
|
|
31805
31806
|
logger.verbose("Local AI guides re-injected.");
|
|
31806
31807
|
} catch (err) {
|
|
@@ -32964,8 +32965,6 @@ init_errors();
|
|
|
32964
32965
|
init_fs();
|
|
32965
32966
|
init_provision();
|
|
32966
32967
|
init_context();
|
|
32967
|
-
init_stamp();
|
|
32968
|
-
init_ai_guide();
|
|
32969
32968
|
init_skills();
|
|
32970
32969
|
init_specs2();
|
|
32971
32970
|
init_lockfile();
|
|
@@ -32983,7 +32982,7 @@ function line(tally, mark, msg) {
|
|
|
32983
32982
|
}
|
|
32984
32983
|
function stampVerdict(content) {
|
|
32985
32984
|
if (content === null) return { mark: "error", note: "missing" };
|
|
32986
|
-
const v =
|
|
32985
|
+
const v = readStampVersion2(content);
|
|
32987
32986
|
if (v === null) return { mark: "warn", note: "unstamped (older wairon)" };
|
|
32988
32987
|
if (v === WAIRON_VERSION) return { mark: "ok", note: `v${v}` };
|
|
32989
32988
|
return { mark: "warn", note: `v${v} \u2014 stale, installed is v${WAIRON_VERSION}` };
|
|
@@ -33121,7 +33120,7 @@ async function runDoctor(options = {}) {
|
|
|
33121
33120
|
}
|
|
33122
33121
|
const seenGuides = /* @__PURE__ */ new Set();
|
|
33123
33122
|
for (const t of targets) {
|
|
33124
|
-
const gp =
|
|
33123
|
+
const gp = localGuideFilePath2(process.cwd(), t);
|
|
33125
33124
|
if (!gp || seenGuides.has(gp)) continue;
|
|
33126
33125
|
seenGuides.add(gp);
|
|
33127
33126
|
const rel2 = path38.relative(process.cwd(), gp).replace(/\\/g, "/");
|
|
@@ -33255,7 +33254,7 @@ async function applyFixes() {
|
|
|
33255
33254
|
try {
|
|
33256
33255
|
syncContextFiles();
|
|
33257
33256
|
exportSddSkills(targets);
|
|
33258
|
-
const guides =
|
|
33257
|
+
const guides = reinjectLocalGuides2(process.cwd(), targets);
|
|
33259
33258
|
console.log(` ${icon("ok")} Regenerated context files, skills, and ${guides.length} local guide(s).`);
|
|
33260
33259
|
} catch (e) {
|
|
33261
33260
|
console.log(` ${icon("error")} Regeneration failed: ${e instanceof Error ? e.message : String(e)}`);
|