@wairon/cli 5.1.1-dev.6 → 5.1.1-dev.7

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/index.js CHANGED
@@ -1211,7 +1211,7 @@ var init_defaults = __esm({
1211
1211
  copilot: ".github/prompts",
1212
1212
  codex: ".codex/agents"
1213
1213
  };
1214
- WAIRON_VERSION = "5.1.1-dev.6";
1214
+ WAIRON_VERSION = "5.1.1-dev.7";
1215
1215
  GITHUB_REPO = "SYW-Apps/Waffle-AIron";
1216
1216
  ARCHITECT_AGENT_ID = "agent-architect";
1217
1217
  ARCHITECT_TEMPLATE_ID = "architect";
@@ -3361,9 +3361,9 @@ var init_surfaces = __esm({
3361
3361
  // src/core/rules/namespace.ts
3362
3362
  function isExternalNamespaceRef(ctx, ref) {
3363
3363
  if (ref.startsWith("::") || ref.startsWith("super::")) return true;
3364
- const sep4 = ref.indexOf("::");
3365
- if (sep4 === -1) return false;
3366
- return !ctx.subsystemIds.has(ref.slice(0, sep4));
3364
+ const sep6 = ref.indexOf("::");
3365
+ if (sep6 === -1) return false;
3366
+ return !ctx.subsystemIds.has(ref.slice(0, sep6));
3367
3367
  }
3368
3368
  function resolveSurfaceRef(ctx, ref) {
3369
3369
  const local = ref.split("::").filter((seg) => seg && seg !== "super").pop();
@@ -3700,10 +3700,10 @@ function stepGraph(steps) {
3700
3700
  const s = byNum.get(n);
3701
3701
  if (s.type !== "parallel" || s.endStep === void 0 || !s.branches?.length) continue;
3702
3702
  const entries = s.branches.map((b) => b.step).sort((a, b) => a - b);
3703
- const join15 = fallNext(s.endStep);
3703
+ const join16 = fallNext(s.endStep);
3704
3704
  for (let i = 0; i < entries.length; i++) {
3705
3705
  const armEnd = i + 1 < entries.length ? prevOf(entries[i + 1]) : s.endStep;
3706
- if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join15);
3706
+ if (armEnd !== void 0 && armEnd >= entries[i]) armEndJoin.set(armEnd, join16);
3707
3707
  }
3708
3708
  }
3709
3709
  const successorsOf = (n) => {
@@ -3777,7 +3777,8 @@ var init_narrative_flow = __esm({
3777
3777
  { code: "REGION_OVERLAP", defaultSeverity: "error", summary: "loop/try regions interleave \u2014 regions must nest or be disjoint to map onto structured code" },
3778
3778
  { code: "JUMP_INTO_REGION", defaultSeverity: "warning", summary: "Jump lands in the middle of a loop/try body from outside \u2014 regions are entered through their header" },
3779
3779
  { code: "FALLTHROUGH_INTO_HANDLER", defaultSeverity: "warning", summary: "try body falls through into its own catch/finally region on the success path" },
3780
- { code: "BACKWARD_JUMP", defaultSeverity: "warning", summary: "Backward jump that is not a continue to an enclosing loop header \u2014 model repetition with a loop step" }
3780
+ { code: "BACKWARD_JUMP", defaultSeverity: "warning", summary: "Backward jump that is not a continue to an enclosing loop header \u2014 model repetition with a loop step" },
3781
+ { code: "DUPLICATE_STEP_LABEL", defaultSeverity: "error", summary: "Two steps in one narrative share a label \u2014 the symbolic anchor later deltas address by" }
3781
3782
  ],
3782
3783
  check(ctx) {
3783
3784
  for (const impl of ctx.implementations) {
@@ -3786,6 +3787,23 @@ var init_narrative_flow = __esm({
3786
3787
  const steps = implMethod.narrative;
3787
3788
  if (!steps.length) continue;
3788
3789
  const where = `Method "${implMethod.name}" in implementation "${impl.id}": `;
3790
+ const labelled = /* @__PURE__ */ new Map();
3791
+ for (const step of steps) {
3792
+ const label = step.label;
3793
+ if (!label) continue;
3794
+ const first = labelled.get(label);
3795
+ if (first !== void 0) {
3796
+ ctx.addIssue(
3797
+ "error",
3798
+ "DUPLICATE_STEP_LABEL",
3799
+ `${where}steps ${first} and ${step.stepNumber} share the label "${label}". A label anchors one step for later deltas to address; two steps holding it makes every symbolic reference ambiguous and blocks all further edits to this implementation. Rename one.`,
3800
+ impl.id,
3801
+ isDraftCtx
3802
+ );
3803
+ } else {
3804
+ labelled.set(label, step.stepNumber);
3805
+ }
3806
+ }
3789
3807
  let sound = true;
3790
3808
  const malformed = (msg) => {
3791
3809
  sound = false;
@@ -7011,11 +7029,11 @@ var init_narrative_antipatterns = __esm({
7011
7029
  const memberEdges = keys.flatMap((k) => (adjacency.get(k) ?? []).filter((e) => inScc.has(e.toKey)));
7012
7030
  if (memberEdges.length === 0) continue;
7013
7031
  const anchor = [...memberEdges].sort((a, b) => a.fromKey.localeCompare(b.fromKey))[0];
7014
- const path24 = [...keys].sort().join(" \u2192 ");
7032
+ const path26 = [...keys].sort().join(" \u2192 ");
7015
7033
  ctx.addIssue(
7016
7034
  "warning",
7017
7035
  "UNCONDITIONAL_CALL_CYCLE",
7018
- `Call cycle with no guard: ${path24} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
7036
+ `Call cycle with no guard: ${path26} \u2014 every call edge in this cycle is unavoidable on all paths of its narrative (e.g. step ${anchor.stepNumber} of "${anchor.methodName}" in "${anchor.impl.id}" always calls ${anchor.toLabel}). This recurses without a base case, by construction. Guard at least one edge with a branch/return before the call, or lint.allow with the termination argument.`,
7019
7037
  anchor.impl.id,
7020
7038
  memberEdges.some((e) => ctx.isImplementationDraft(e.impl))
7021
7039
  );
@@ -13881,6 +13899,77 @@ var init_variants = __esm({
13881
13899
  }
13882
13900
  });
13883
13901
 
13902
+ // src/core/baseline.ts
13903
+ function baselineDir() {
13904
+ return process.env["WAIRON_BASELINE_DIR"] || path13.join(os4.homedir(), ".wairon", "baselines");
13905
+ }
13906
+ function keyFor(root) {
13907
+ const normalized = path13.resolve(root).replace(/\\/g, "/").toLowerCase();
13908
+ return crypto3.createHash("sha256").update(normalized).digest("hex").slice(0, 16);
13909
+ }
13910
+ function baselinePath(root) {
13911
+ return path13.join(baselineDir(), `${keyFor(root)}.json`);
13912
+ }
13913
+ function readBaseline(root = getProjectRoot()) {
13914
+ const p = baselinePath(root);
13915
+ if (!pathExists(p)) return null;
13916
+ try {
13917
+ return JSON.parse(fs9.readFileSync(p, "utf8"));
13918
+ } catch {
13919
+ return null;
13920
+ }
13921
+ }
13922
+ function currentSpecs(root) {
13923
+ const mountDirs = loadSubsystemSpecs().filter((s) => s.projectPath && !s.id.includes("::")).map((s) => `${path13.resolve(root, s.projectPath).split(path13.sep).join("/")}/`);
13924
+ const out = {};
13925
+ for (const [abs, content] of snapshotSpecFiles()) {
13926
+ const normalized = path13.resolve(abs).split(path13.sep).join("/");
13927
+ if (mountDirs.some((dir) => normalized.startsWith(dir))) continue;
13928
+ out[path13.relative(root, abs).split(path13.sep).join("/")] = content;
13929
+ }
13930
+ return out;
13931
+ }
13932
+ function diffAgainstBaseline(root = getProjectRoot()) {
13933
+ const baseline = readBaseline(root);
13934
+ if (!baseline) return null;
13935
+ const current2 = currentSpecs(root);
13936
+ const added = [];
13937
+ const changed = [];
13938
+ const removed = [];
13939
+ const unchangedPaths = [];
13940
+ for (const [rel2, content] of Object.entries(current2)) {
13941
+ const before = baseline.specs[rel2];
13942
+ if (before === void 0) added.push(rel2);
13943
+ else if (before !== content) changed.push(rel2);
13944
+ else unchangedPaths.push(rel2);
13945
+ }
13946
+ for (const rel2 of Object.keys(baseline.specs)) {
13947
+ if (current2[rel2] === void 0) removed.push(rel2);
13948
+ }
13949
+ return {
13950
+ added: added.sort(),
13951
+ changed: changed.sort(),
13952
+ removed: removed.sort(),
13953
+ unchangedPaths: unchangedPaths.sort()
13954
+ };
13955
+ }
13956
+ function settledSpecPaths(root = getProjectRoot()) {
13957
+ const diff = diffAgainstBaseline(root);
13958
+ return diff ? new Set(diff.unchangedPaths) : null;
13959
+ }
13960
+ var fs9, os4, path13, crypto3;
13961
+ var init_baseline = __esm({
13962
+ "src/core/baseline.ts"() {
13963
+ "use strict";
13964
+ fs9 = __toESM(require("fs"));
13965
+ os4 = __toESM(require("os"));
13966
+ path13 = __toESM(require("path"));
13967
+ crypto3 = __toESM(require("crypto"));
13968
+ init_fs();
13969
+ init_specs2();
13970
+ }
13971
+ });
13972
+
13884
13973
  // src/core/validation.ts
13885
13974
  function projectPackSelections() {
13886
13975
  try {
@@ -14003,7 +14092,7 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
14003
14092
  const types = loadTypeSpecs();
14004
14093
  const surfaceSnapshots = loadSurfaceSnapshots();
14005
14094
  const codeModel = buildCodeModel(implementations, getProjectRoot());
14006
- const statusBearing = treatAllAsComplete ? [...subsystems, ...components, ...interfaces, ...implementations] : [];
14095
+ const statusBearing = treatAllAsComplete ? [...subsystems, ...components, ...interfaces, ...implementations] : settledStatusBearing({ subsystems, components, interfaces, implementations });
14007
14096
  const statusSnapshot = statusBearing.map((s) => s.status);
14008
14097
  for (const s of statusBearing) s.status = "complete";
14009
14098
  try {
@@ -14125,10 +14214,34 @@ function validateSddTree(rulesOrOptions, projectType = "backend") {
14125
14214
  });
14126
14215
  }
14127
14216
  }
14217
+ function settledStatusBearing(loaded) {
14218
+ let settled;
14219
+ try {
14220
+ settled = settledSpecPaths();
14221
+ } catch {
14222
+ return [];
14223
+ }
14224
+ if (!settled || settled.size === 0) return [];
14225
+ const root = getProjectRoot();
14226
+ const index = scanAllSpecs();
14227
+ const rel2 = (abs) => path14.relative(root, abs).split(path14.sep).join("/");
14228
+ const out = [];
14229
+ const take = (specs, paths) => {
14230
+ for (const spec of specs) {
14231
+ const p = paths[spec.id];
14232
+ if (p && settled.has(rel2(p))) out.push(spec);
14233
+ }
14234
+ };
14235
+ take(loaded.subsystems, index.paths.subsystem);
14236
+ take(loaded.components, index.paths.component);
14237
+ take(loaded.interfaces, index.paths.interface);
14238
+ take(loaded.implementations, index.paths.implementation);
14239
+ return out;
14240
+ }
14128
14241
  function validateAsComplete(options) {
14129
14242
  return validateSddTree({ ...options ?? {}, treatAllAsComplete: true });
14130
14243
  }
14131
- var SUBPROJECT_REFERENCE_CODES, SUBPROJECT_CONFORMANCE_CODES;
14244
+ var path14, SUBPROJECT_REFERENCE_CODES, SUBPROJECT_CONFORMANCE_CODES;
14132
14245
  var init_validation = __esm({
14133
14246
  "src/core/validation.ts"() {
14134
14247
  "use strict";
@@ -14142,6 +14255,8 @@ var init_validation = __esm({
14142
14255
  init_source_analysis();
14143
14256
  init_specs2();
14144
14257
  init_fs();
14258
+ path14 = __toESM(require("path"));
14259
+ init_baseline();
14145
14260
  SUBPROJECT_REFERENCE_CODES = /* @__PURE__ */ new Set([
14146
14261
  "UNDEFINED_TYPE_REFERENCE",
14147
14262
  "INVALID_DEPENDENCY_REFERENCE",
@@ -14471,8 +14586,8 @@ function generateSequenceDiagram(componentId, methodName, options) {
14471
14586
  const steps = [...methodImpl.narrative].sort((a, b) => a.stepNumber - b.stepNumber);
14472
14587
  for (const step of steps) {
14473
14588
  for (const par of parallelArms) {
14474
- const sep4 = par.sepByStep.get(step.stepNumber);
14475
- if (sep4 !== void 0) lines.push(` and ${escapeLabel(sep4)}`);
14589
+ const sep6 = par.sepByStep.get(step.stepNumber);
14590
+ if (sep6 !== void 0) lines.push(` and ${escapeLabel(sep6)}`);
14476
14591
  }
14477
14592
  switch (step.type) {
14478
14593
  case "local":
@@ -14766,16 +14881,16 @@ function relativizeId(id, prefix) {
14766
14881
  return `${"super::".repeat(prefixParts.length - common)}${idParts.slice(common).join("::")}`;
14767
14882
  }
14768
14883
  function isWithin(dir, file) {
14769
- const d = path13.resolve(dir);
14770
- const f = path13.resolve(file);
14771
- return f === d || f.startsWith(d + path13.sep);
14884
+ const d = path15.resolve(dir);
14885
+ const f = path15.resolve(file);
14886
+ return f === d || f.startsWith(d + path15.sep);
14772
14887
  }
14773
14888
  function projectPathEscapesRoot(projectRoot, projectPath, resolvedChildDir) {
14774
- return path13.isAbsolute(projectPath) || !isWithin(projectRoot, resolvedChildDir);
14889
+ return path15.isAbsolute(projectPath) || !isWithin(projectRoot, resolvedChildDir);
14775
14890
  }
14776
14891
  function assertContainedProjectPath(projectRoot, projectPath) {
14777
- const root = path13.resolve(projectRoot);
14778
- const resolved = path13.resolve(root, projectPath);
14892
+ const root = path15.resolve(projectRoot);
14893
+ const resolved = path15.resolve(root, projectPath);
14779
14894
  if (projectPathEscapesRoot(root, projectPath, resolved)) {
14780
14895
  throw new Error(
14781
14896
  `projectPath "${projectPath}" must resolve within the project root "${root}", but resolves to "${resolved}"; absolute paths and ../-escaping paths are rejected so a chained subproject is always contained by its parent.`
@@ -14786,11 +14901,11 @@ function assertContainedProjectPath(projectRoot, projectPath) {
14786
14901
  function findChainingParent(childRoot) {
14787
14902
  let childResolved;
14788
14903
  try {
14789
- childResolved = path13.resolve(childRoot);
14904
+ childResolved = path15.resolve(childRoot);
14790
14905
  } catch {
14791
14906
  return null;
14792
14907
  }
14793
- let dir = path13.dirname(childResolved);
14908
+ let dir = path15.dirname(childResolved);
14794
14909
  for (let hops = 0; hops < 32; hops++) {
14795
14910
  const specsDir = aiPathsAt(dir).specsDir();
14796
14911
  if (pathExists(specsDir)) {
@@ -14805,7 +14920,7 @@ function findChainingParent(childRoot) {
14805
14920
  const projectPath = raw.projectPath;
14806
14921
  if (typeof projectPath === "string" && projectPath.trim() !== "") {
14807
14922
  try {
14808
- if (path13.resolve(dir, projectPath) === childResolved) {
14923
+ if (path15.resolve(dir, projectPath) === childResolved) {
14809
14924
  const id = raw.id;
14810
14925
  return { parentRoot: dir, subsystemId: typeof id === "string" ? id : "?" };
14811
14926
  }
@@ -14815,7 +14930,7 @@ function findChainingParent(childRoot) {
14815
14930
  }
14816
14931
  }
14817
14932
  }
14818
- const up = path13.dirname(dir);
14933
+ const up = path15.dirname(dir);
14819
14934
  if (up === dir) break;
14820
14935
  dir = up;
14821
14936
  }
@@ -14920,18 +15035,18 @@ function findOwner(id, components) {
14920
15035
  }) ?? null;
14921
15036
  }
14922
15037
  function moveComponentFolder(fromDir, toDir) {
14923
- if (path13.normalize(fromDir) === path13.normalize(toDir)) return false;
14924
- if (!fs9.existsSync(fromDir) || fs9.existsSync(toDir)) return false;
14925
- ensureDir(path13.dirname(toDir));
14926
- fs9.renameSync(fromDir, toDir);
15038
+ if (path15.normalize(fromDir) === path15.normalize(toDir)) return false;
15039
+ if (!fs10.existsSync(fromDir) || fs10.existsSync(toDir)) return false;
15040
+ ensureDir(path15.dirname(toDir));
15041
+ fs10.renameSync(fromDir, toDir);
14927
15042
  return true;
14928
15043
  }
14929
15044
  function cleanEmptyDirs(filePath, specsRoot) {
14930
- let dir = path13.dirname(filePath);
15045
+ let dir = path15.dirname(filePath);
14931
15046
  while (dir !== specsRoot && dir.startsWith(specsRoot)) {
14932
- if (fs9.existsSync(dir) && fs9.readdirSync(dir).length === 0) {
14933
- fs9.rmdirSync(dir);
14934
- dir = path13.dirname(dir);
15047
+ if (fs10.existsSync(dir) && fs10.readdirSync(dir).length === 0) {
15048
+ fs10.rmdirSync(dir);
15049
+ dir = path15.dirname(dir);
14935
15050
  } else {
14936
15051
  break;
14937
15052
  }
@@ -14950,13 +15065,13 @@ function parseOrThrow(schema, value, kind, id) {
14950
15065
  function computeSpecTreeSignature(dirs) {
14951
15066
  const parts = [];
14952
15067
  for (const dir of dirs) {
14953
- if (!fs9.existsSync(dir)) {
15068
+ if (!fs10.existsSync(dir)) {
14954
15069
  parts.push(`${dir}:missing`);
14955
15070
  continue;
14956
15071
  }
14957
15072
  for (const f of listFilesRecursive(dir, ".yaml")) {
14958
15073
  try {
14959
- const st = fs9.statSync(f);
15074
+ const st = fs10.statSync(f);
14960
15075
  parts.push(`${f}:${st.mtimeMs}:${st.size}`);
14961
15076
  } catch {
14962
15077
  parts.push(`${f}:gone`);
@@ -14966,7 +15081,7 @@ function computeSpecTreeSignature(dirs) {
14966
15081
  return parts.join("|");
14967
15082
  }
14968
15083
  function workspaceFor(rootDir) {
14969
- const key = path13.resolve(rootDir);
15084
+ const key = path15.resolve(rootDir);
14970
15085
  let ws = workspaces.get(key);
14971
15086
  if (!ws) {
14972
15087
  ws = new SpecWorkspace(key);
@@ -15105,7 +15220,7 @@ function readLockState() {
15105
15220
  return { state: stateIdEquals(record.stateId, current2) ? "locked" : "stale", record, current: current2 };
15106
15221
  }
15107
15222
  function computeStateIdAt(root) {
15108
- const resolved = path13.resolve(root);
15223
+ const resolved = path15.resolve(root);
15109
15224
  return runWithProjectRoot(resolved, () => {
15110
15225
  workspaceFor(resolved).invalidate();
15111
15226
  const system = loadSystemSpec();
@@ -15135,12 +15250,15 @@ function collectPromotableSpecs(scopeSubsystem) {
15135
15250
  function applySpecStatus(kind, id, status) {
15136
15251
  current().applySpecStatus(kind, id, status);
15137
15252
  }
15253
+ function specPathsInScope(scopeSubsystem) {
15254
+ return current().specPathsInScope(scopeSubsystem);
15255
+ }
15138
15256
  function snapshotSpecFiles() {
15139
15257
  return current().snapshotSpecFiles();
15140
15258
  }
15141
15259
  function restoreSpecFiles(snapshot) {
15142
15260
  for (const [file, content] of snapshot) {
15143
- fs9.writeFileSync(file, content);
15261
+ fs10.writeFileSync(file, content);
15144
15262
  }
15145
15263
  }
15146
15264
  function findLegacySpecFiles() {
@@ -15149,12 +15267,12 @@ function findLegacySpecFiles() {
15149
15267
  function updateSpec(kind, id, delta, hooks) {
15150
15268
  return current().updateSpec(kind, id, delta, hooks);
15151
15269
  }
15152
- var fs9, path13, SIGNATURE_TTL_MS, SpecWorkspace, workspaces;
15270
+ var fs10, path15, SIGNATURE_TTL_MS, SpecWorkspace, workspaces;
15153
15271
  var init_specs2 = __esm({
15154
15272
  "src/core/specs.ts"() {
15155
15273
  "use strict";
15156
- fs9 = __toESM(require("fs"));
15157
- path13 = __toESM(require("path"));
15274
+ fs10 = __toESM(require("fs"));
15275
+ path15 = __toESM(require("path"));
15158
15276
  init_loader();
15159
15277
  init_fs();
15160
15278
  init_statehash();
@@ -15175,7 +15293,7 @@ var init_specs2 = __esm({
15175
15293
  this.rootSubsystems = /* @__PURE__ */ new Set();
15176
15294
  this.scanVisitedSpecDirs = [];
15177
15295
  this.loaderIssues = [];
15178
- this.rootDir = path13.resolve(rootDir);
15296
+ this.rootDir = path15.resolve(rootDir);
15179
15297
  this.paths = aiPathsAt(this.rootDir);
15180
15298
  }
15181
15299
  invalidate() {
@@ -15202,7 +15320,7 @@ var init_specs2 = __esm({
15202
15320
  this.rootSubsystems.clear();
15203
15321
  this.cachedRecursive = recursive;
15204
15322
  this.scanVisitedSpecDirs = [];
15205
- const visited = /* @__PURE__ */ new Set([path13.resolve(this.rootDir)]);
15323
+ const visited = /* @__PURE__ */ new Set([path15.resolve(this.rootDir)]);
15206
15324
  const maxDepth = typeof recursive === "number" ? recursive : recursive ? Infinity : 0;
15207
15325
  this.cachedIndex = this.scanSpecsForProject(this.rootDir, "", visited, maxDepth, 0);
15208
15326
  this.cachedSpecDirs = this.scanVisitedSpecDirs;
@@ -15217,10 +15335,10 @@ var init_specs2 = __esm({
15217
15335
  this.scanVisitedSpecDirs.push(specsDir);
15218
15336
  if (!pathExists(specsDir)) return index;
15219
15337
  const files = listFilesRecursive(specsDir, ".yaml");
15220
- const systemYaml = path13.normalize(projectPaths.specsSystem());
15338
+ const systemYaml = path15.normalize(projectPaths.specsSystem());
15221
15339
  const localSubprojects = [];
15222
15340
  for (const file of files) {
15223
- const normFile = path13.normalize(file);
15341
+ const normFile = path15.normalize(file);
15224
15342
  if (normFile === systemYaml) continue;
15225
15343
  let detectedType = "spec";
15226
15344
  try {
@@ -15230,7 +15348,7 @@ var init_specs2 = __esm({
15230
15348
  severity: "error",
15231
15349
  code: "INVALID_YAML",
15232
15350
  message: `Spec file "${file}" is not a valid YAML object or is empty.`,
15233
- specId: path13.basename(file, ".yaml")
15351
+ specId: path15.basename(file, ".yaml")
15234
15352
  });
15235
15353
  continue;
15236
15354
  }
@@ -15262,8 +15380,8 @@ var init_specs2 = __esm({
15262
15380
  detectedType = "implementation";
15263
15381
  const parsed = ImplementationSpecSchema.parse(raw);
15264
15382
  if (parsed.sourcePath) {
15265
- const absSourcePath = path13.resolve(projectDir, parsed.sourcePath);
15266
- parsed.sourcePath = path13.relative(projectDir, absSourcePath).replace(/\\/g, "/");
15383
+ const absSourcePath = path15.resolve(projectDir, parsed.sourcePath);
15384
+ parsed.sourcePath = path15.relative(projectDir, absSourcePath).replace(/\\/g, "/");
15267
15385
  }
15268
15386
  index.implementations.push(parsed);
15269
15387
  index.paths.implementation[parsed.id] = file;
@@ -15285,11 +15403,11 @@ var init_specs2 = __esm({
15285
15403
  severity: "error",
15286
15404
  code: "UNKNOWN_SPEC_TYPE",
15287
15405
  message: `Spec file "${file}" does not match any recognized L1-L4 schema structure.`,
15288
- specId: path13.basename(file, ".yaml")
15406
+ specId: path15.basename(file, ".yaml")
15289
15407
  });
15290
15408
  }
15291
15409
  } catch (e) {
15292
- const filename = path13.basename(file, ".yaml");
15410
+ const filename = path15.basename(file, ".yaml");
15293
15411
  this.loaderIssues.push({
15294
15412
  severity: "error",
15295
15413
  code: "SCHEMA_VALIDATION_ERROR",
@@ -15387,7 +15505,7 @@ var init_specs2 = __esm({
15387
15505
  }
15388
15506
  if (currentDepth < maxDepth) {
15389
15507
  for (const subproj of localSubprojects) {
15390
- const childDir = path13.resolve(projectDir, subproj.projectPath);
15508
+ const childDir = path15.resolve(projectDir, subproj.projectPath);
15391
15509
  if (projectPathEscapesRoot(this.rootDir, subproj.projectPath, childDir)) {
15392
15510
  this.loaderIssues.push({
15393
15511
  severity: "error",
@@ -15406,7 +15524,7 @@ var init_specs2 = __esm({
15406
15524
  });
15407
15525
  continue;
15408
15526
  }
15409
- if (!fs9.existsSync(childDir)) {
15527
+ if (!fs10.existsSync(childDir)) {
15410
15528
  this.loaderIssues.push({
15411
15529
  severity: "error",
15412
15530
  code: "SUBPROJECT_NOT_FOUND",
@@ -15449,7 +15567,7 @@ var init_specs2 = __esm({
15449
15567
  const index = this.scanAll();
15450
15568
  const sub = index.subsystems.find((s) => s.id === currentPrefix);
15451
15569
  if (sub && sub.projectPath) {
15452
- const nextDir = path13.resolve(currentDir, sub.projectPath);
15570
+ const nextDir = path15.resolve(currentDir, sub.projectPath);
15453
15571
  if (projectPathEscapesRoot(this.rootDir, sub.projectPath, nextDir)) {
15454
15572
  this.loaderIssues.push({
15455
15573
  severity: "error",
@@ -15501,9 +15619,9 @@ var init_specs2 = __esm({
15501
15619
  return index.paths.subsystem[matches2[0]];
15502
15620
  }
15503
15621
  if (pathExists(this.paths.specsSubsystemsDir()) && listFiles(this.paths.specsSubsystemsDir(), ".yaml").length > 0) {
15504
- return path13.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
15622
+ return path15.join(this.paths.specsSubsystemsDir(), `${id}.yaml`);
15505
15623
  }
15506
- return path13.join(this.paths.specsDir(), id, ".index.yaml");
15624
+ return path15.join(this.paths.specsDir(), id, ".index.yaml");
15507
15625
  }
15508
15626
  getComponentPath(id, subsystemId) {
15509
15627
  const index = this.scanAll();
@@ -15523,21 +15641,21 @@ var init_specs2 = __esm({
15523
15641
  if (owner) {
15524
15642
  const ownerPath = index.paths.component[owner.id];
15525
15643
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
15526
- return path13.join(path13.dirname(ownerPath), id, ".index.yaml");
15644
+ return path15.join(path15.dirname(ownerPath), id, ".index.yaml");
15527
15645
  }
15528
15646
  }
15529
15647
  if (subsystemId) {
15530
15648
  const subPath = this.getSubsystemPath(subsystemId);
15531
- const subDir = path13.dirname(subPath);
15649
+ const subDir = path15.dirname(subPath);
15532
15650
  if (subPath.endsWith(".index.yaml")) {
15533
- return path13.join(subDir, id, ".index.yaml");
15651
+ return path15.join(subDir, id, ".index.yaml");
15534
15652
  }
15535
15653
  }
15536
15654
  if (pathExists(this.paths.specsComponentsDir()) && listFiles(this.paths.specsComponentsDir(), ".yaml").length > 0) {
15537
- return path13.join(this.paths.specsComponentsDir(), `${id}.yaml`);
15655
+ return path15.join(this.paths.specsComponentsDir(), `${id}.yaml`);
15538
15656
  }
15539
15657
  const targetSubsystem = subsystemId || "default";
15540
- return path13.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
15658
+ return path15.join(this.paths.specsDir(), targetSubsystem, id, ".index.yaml");
15541
15659
  }
15542
15660
  getInterfacePath(id, componentId) {
15543
15661
  const index = this.scanAll();
@@ -15563,16 +15681,16 @@ var init_specs2 = __esm({
15563
15681
  }
15564
15682
  if (componentId) {
15565
15683
  const compPath = this.getComponentPath(componentId);
15566
- const compDir = path13.dirname(compPath);
15684
+ const compDir = path15.dirname(compPath);
15567
15685
  if (compPath.endsWith(".index.yaml")) {
15568
- return path13.join(compDir, ".interface.yaml");
15686
+ return path15.join(compDir, ".interface.yaml");
15569
15687
  }
15570
15688
  }
15571
15689
  if (pathExists(this.paths.specsInterfacesDir()) && listFiles(this.paths.specsInterfacesDir(), ".yaml").length > 0) {
15572
- return path13.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
15690
+ return path15.join(this.paths.specsInterfacesDir(), `${id}.yaml`);
15573
15691
  }
15574
15692
  const targetComponent = componentId || "default";
15575
- return path13.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
15693
+ return path15.join(this.paths.specsDir(), "default", targetComponent, ".interface.yaml");
15576
15694
  }
15577
15695
  getImplementationPath(id, contractId) {
15578
15696
  const index = this.scanAll();
@@ -15598,16 +15716,16 @@ var init_specs2 = __esm({
15598
15716
  }
15599
15717
  if (contractId) {
15600
15718
  const intfPath = this.getInterfacePath(contractId);
15601
- const intfDir = path13.dirname(intfPath);
15719
+ const intfDir = path15.dirname(intfPath);
15602
15720
  if (intfPath.endsWith(".interface.yaml")) {
15603
- return path13.join(intfDir, ".implementation.yaml");
15721
+ return path15.join(intfDir, ".implementation.yaml");
15604
15722
  }
15605
15723
  }
15606
15724
  if (pathExists(this.paths.specsImplementationsDir()) && listFiles(this.paths.specsImplementationsDir(), ".yaml").length > 0) {
15607
- return path13.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
15725
+ return path15.join(this.paths.specsImplementationsDir(), `${id}.yaml`);
15608
15726
  }
15609
15727
  const targetContract = contractId ? contractId.replace(/^i/, "") : "default";
15610
- return path13.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
15728
+ return path15.join(this.paths.specsDir(), "default", targetContract, ".implementation.yaml");
15611
15729
  }
15612
15730
  getTypePath(id, subsystemId, group) {
15613
15731
  const index = this.scanAll();
@@ -15638,7 +15756,7 @@ var init_specs2 = __esm({
15638
15756
  const groupPath = index.paths.group[targetGroup] || index.paths.group[plainGroup];
15639
15757
  if (groupPath) {
15640
15758
  const localId2 = id.split("::").pop();
15641
- return path13.join(path13.dirname(groupPath), `${localId2}.yaml`);
15759
+ return path15.join(path15.dirname(groupPath), `${localId2}.yaml`);
15642
15760
  }
15643
15761
  }
15644
15762
  let localId = id;
@@ -15651,12 +15769,12 @@ var init_specs2 = __esm({
15651
15769
  }
15652
15770
  if (subsystemId) {
15653
15771
  const subPath = this.getSubsystemPath(subsystemId);
15654
- const subDir = path13.dirname(subPath);
15772
+ const subDir = path15.dirname(subPath);
15655
15773
  if (subPath.endsWith(".index.yaml")) {
15656
- return path13.join(subDir, "types", `${localId}.yaml`);
15774
+ return path15.join(subDir, "types", `${localId}.yaml`);
15657
15775
  }
15658
15776
  }
15659
- return path13.join(this.paths.specsTypesDir(), `${localId}.yaml`);
15777
+ return path15.join(this.paths.specsTypesDir(), `${localId}.yaml`);
15660
15778
  }
15661
15779
  getGroupPath(id, subsystemId) {
15662
15780
  const index = this.scanAll();
@@ -15690,12 +15808,12 @@ var init_specs2 = __esm({
15690
15808
  }
15691
15809
  if (subsystemId) {
15692
15810
  const subPath = this.getSubsystemPath(subsystemId);
15693
- const subDir = path13.dirname(subPath);
15811
+ const subDir = path15.dirname(subPath);
15694
15812
  if (subPath.endsWith(".index.yaml")) {
15695
- return path13.join(subDir, "types", localId, ".index.yaml");
15813
+ return path15.join(subDir, "types", localId, ".index.yaml");
15696
15814
  }
15697
15815
  }
15698
- return path13.join(this.paths.specsTypesDir(), localId, ".index.yaml");
15816
+ return path15.join(this.paths.specsTypesDir(), localId, ".index.yaml");
15699
15817
  }
15700
15818
  // -------------------------------------------------------------------------
15701
15819
  // Level 0: System
@@ -15718,7 +15836,7 @@ var init_specs2 = __esm({
15718
15836
  }
15719
15837
  saveSystemSpec(spec) {
15720
15838
  const p = this.paths.specsSystem();
15721
- ensureDir(path13.dirname(p));
15839
+ ensureDir(path15.dirname(p));
15722
15840
  writeYamlFile(p, parseOrThrow(SystemSpecSchema, spec, "system", spec.name));
15723
15841
  invalidateSpecCache();
15724
15842
  }
@@ -15836,7 +15954,7 @@ var init_specs2 = __esm({
15836
15954
  }
15837
15955
  saveSubsystemSpec(spec) {
15838
15956
  const p = this.getSubsystemPath(spec.id);
15839
- ensureDir(path13.dirname(p));
15957
+ ensureDir(path15.dirname(p));
15840
15958
  const { prefix } = splitNamespace(spec.id);
15841
15959
  if (!prefix && spec.projectPath && spec.projectPath.trim() !== "") {
15842
15960
  assertContainedProjectPath(this.rootDir, spec.projectPath);
@@ -15867,9 +15985,9 @@ var init_specs2 = __esm({
15867
15985
  }
15868
15986
  deleteSubsystemSpec(id) {
15869
15987
  const p = this.getSubsystemPath(id);
15870
- if (!fs9.existsSync(p)) return false;
15871
- fs9.unlinkSync(p);
15872
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
15988
+ if (!fs10.existsSync(p)) return false;
15989
+ fs10.unlinkSync(p);
15990
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
15873
15991
  invalidateSpecCache();
15874
15992
  return true;
15875
15993
  }
@@ -15902,7 +16020,7 @@ var init_specs2 = __esm({
15902
16020
  saveComponentSpec(spec, opts) {
15903
16021
  const notices = [];
15904
16022
  const p = this.getComponentPath(spec.id, spec.subsystem);
15905
- ensureDir(path13.dirname(p));
16023
+ ensureDir(path15.dirname(p));
15906
16024
  const specToWrite = this.prepareComponentForWrite(spec);
15907
16025
  const existing = this.loadComponentSpec(spec.id);
15908
16026
  if (existing) {
@@ -15919,7 +16037,7 @@ var init_specs2 = __esm({
15919
16037
  const subsystemChanged = existing && existing.subsystem !== spec.subsystem && splitNamespace(existing.subsystem).localId !== splitNamespace(spec.subsystem).localId;
15920
16038
  if (subsystemChanged && !p.endsWith(".index.yaml")) {
15921
16039
  notices.push(
15922
- `component "${spec.id}" already exists at ${path13.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}").`
16040
+ `component "${spec.id}" already exists at ${path15.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}").`
15923
16041
  );
15924
16042
  }
15925
16043
  specToWrite.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -15930,9 +16048,9 @@ var init_specs2 = __esm({
15930
16048
  }
15931
16049
  deleteComponentSpec(id) {
15932
16050
  const p = this.getComponentPath(id);
15933
- if (!fs9.existsSync(p)) return false;
15934
- fs9.unlinkSync(p);
15935
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
16051
+ if (!fs10.existsSync(p)) return false;
16052
+ fs10.unlinkSync(p);
16053
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
15936
16054
  invalidateSpecCache();
15937
16055
  return true;
15938
16056
  }
@@ -15945,12 +16063,12 @@ var init_specs2 = __esm({
15945
16063
  if (owner) {
15946
16064
  const ownerPath = index.paths.component[owner.id];
15947
16065
  if (ownerPath && ownerPath.endsWith(".index.yaml")) {
15948
- const ownerSubDir = path13.dirname(this.getSubsystemPath(owner.subsystem));
15949
- return path13.join(ownerSubDir, owner.id, comp.id);
16066
+ const ownerSubDir = path15.dirname(this.getSubsystemPath(owner.subsystem));
16067
+ return path15.join(ownerSubDir, owner.id, comp.id);
15950
16068
  }
15951
16069
  }
15952
- const subDir = path13.dirname(this.getSubsystemPath(comp.subsystem));
15953
- return path13.join(subDir, comp.id);
16070
+ const subDir = path15.dirname(this.getSubsystemPath(comp.subsystem));
16071
+ return path15.join(subDir, comp.id);
15954
16072
  }
15955
16073
  /**
15956
16074
  * Move component folders so the physical tree mirrors ownership: each owned
@@ -15966,7 +16084,7 @@ var init_specs2 = __esm({
15966
16084
  if (!currentPath) continue;
15967
16085
  const desiredDir = this.desiredComponentDir(comp, index);
15968
16086
  if (!desiredDir) continue;
15969
- if (moveComponentFolder(path13.dirname(currentPath), desiredDir)) moved.push(comp.id);
16087
+ if (moveComponentFolder(path15.dirname(currentPath), desiredDir)) moved.push(comp.id);
15970
16088
  }
15971
16089
  if (moved.length) invalidateSpecCache();
15972
16090
  return moved;
@@ -16022,7 +16140,7 @@ var init_specs2 = __esm({
16022
16140
  if (!occupantId) return;
16023
16141
  if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
16024
16142
  throw new Error(
16025
- `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path13.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.`
16143
+ `Cannot write ${kind} "${id}": ${parentLabel} is already ${kind === "interface" ? "served by" : "implemented by"} "${occupantId}" at ${path15.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.`
16026
16144
  );
16027
16145
  }
16028
16146
  /** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
@@ -16030,12 +16148,12 @@ var init_specs2 = __esm({
16030
16148
  const notices = [];
16031
16149
  const p = this.getInterfacePath(spec.id, spec.component);
16032
16150
  this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
16033
- ensureDir(path13.dirname(p));
16151
+ ensureDir(path15.dirname(p));
16034
16152
  const specToWrite = this.prepareInterfaceForWrite(spec);
16035
16153
  const existing = this.loadInterfaceSpec(spec.id);
16036
16154
  if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
16037
16155
  notices.push(
16038
- `interface "${spec.id}" already exists at ${path13.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.`
16156
+ `interface "${spec.id}" already exists at ${path15.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.`
16039
16157
  );
16040
16158
  }
16041
16159
  if (existing) {
@@ -16058,9 +16176,9 @@ var init_specs2 = __esm({
16058
16176
  }
16059
16177
  deleteInterfaceSpec(id) {
16060
16178
  const p = this.getInterfacePath(id);
16061
- if (!fs9.existsSync(p)) return false;
16062
- fs9.unlinkSync(p);
16063
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
16179
+ if (!fs10.existsSync(p)) return false;
16180
+ fs10.unlinkSync(p);
16181
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
16064
16182
  invalidateSpecCache();
16065
16183
  return true;
16066
16184
  }
@@ -16094,12 +16212,12 @@ var init_specs2 = __esm({
16094
16212
  const notices = [];
16095
16213
  const p = this.getImplementationPath(spec.id, spec.contract);
16096
16214
  this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
16097
- ensureDir(path13.dirname(p));
16215
+ ensureDir(path15.dirname(p));
16098
16216
  const specToWrite = this.prepareImplementationForWrite(spec);
16099
16217
  const existing = this.loadImplementationSpec(spec.id);
16100
16218
  if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
16101
16219
  notices.push(
16102
- `implementation "${spec.id}" already exists at ${path13.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.`
16220
+ `implementation "${spec.id}" already exists at ${path15.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.`
16103
16221
  );
16104
16222
  }
16105
16223
  if (existing) {
@@ -16115,9 +16233,9 @@ var init_specs2 = __esm({
16115
16233
  }
16116
16234
  deleteImplementationSpec(id) {
16117
16235
  const p = this.getImplementationPath(id);
16118
- if (!fs9.existsSync(p)) return false;
16119
- fs9.unlinkSync(p);
16120
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
16236
+ if (!fs10.existsSync(p)) return false;
16237
+ fs10.unlinkSync(p);
16238
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
16121
16239
  invalidateSpecCache();
16122
16240
  return true;
16123
16241
  }
@@ -16142,11 +16260,11 @@ var init_specs2 = __esm({
16142
16260
  const existing = this.loadTypeSpec(spec.id);
16143
16261
  const group = spec.group || (existing ? existing.group : void 0);
16144
16262
  const p = this.getTypePath(spec.id, spec.subsystem, group);
16145
- ensureDir(path13.dirname(p));
16263
+ ensureDir(path15.dirname(p));
16146
16264
  const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
16147
16265
  if (subsystemChanged) {
16148
16266
  notices.push(
16149
- `type "${spec.id}" already exists at ${path13.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)"}").`
16267
+ `type "${spec.id}" already exists at ${path15.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)"}").`
16150
16268
  );
16151
16269
  }
16152
16270
  if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
@@ -16169,9 +16287,9 @@ var init_specs2 = __esm({
16169
16287
  deleteTypeSpec(id) {
16170
16288
  const spec = this.loadTypeSpec(id);
16171
16289
  const p = this.getTypePath(id, spec?.subsystem, spec?.group);
16172
- if (!fs9.existsSync(p)) return false;
16173
- fs9.unlinkSync(p);
16174
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
16290
+ if (!fs10.existsSync(p)) return false;
16291
+ fs10.unlinkSync(p);
16292
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
16175
16293
  invalidateSpecCache();
16176
16294
  return true;
16177
16295
  }
@@ -16186,7 +16304,7 @@ var init_specs2 = __esm({
16186
16304
  }
16187
16305
  saveGroupSpec(spec) {
16188
16306
  const p = this.getGroupPath(spec.id);
16189
- ensureDir(path13.dirname(p));
16307
+ ensureDir(path15.dirname(p));
16190
16308
  const specToWrite = this.prepareGroupForWrite(spec);
16191
16309
  const existing = this.loadGroupSpec(spec.id);
16192
16310
  if (existing) {
@@ -16198,9 +16316,9 @@ var init_specs2 = __esm({
16198
16316
  }
16199
16317
  deleteGroupSpec(id) {
16200
16318
  const p = this.getGroupPath(id);
16201
- if (!fs9.existsSync(p)) return false;
16202
- fs9.unlinkSync(p);
16203
- cleanEmptyDirs(p, path13.resolve(this.paths.specsDir()));
16319
+ if (!fs10.existsSync(p)) return false;
16320
+ fs10.unlinkSync(p);
16321
+ cleanEmptyDirs(p, path15.resolve(this.paths.specsDir()));
16204
16322
  invalidateSpecCache();
16205
16323
  return true;
16206
16324
  }
@@ -16248,6 +16366,50 @@ var init_specs2 = __esm({
16248
16366
  }
16249
16367
  return out;
16250
16368
  }
16369
+ /**
16370
+ * Every spec FILE inside a subsystem scope (absolute paths), regardless of
16371
+ * status. `collectPromotableSpecs` answers a different question — which specs
16372
+ * are not yet complete — so it cannot stand in for this: a scoped approval
16373
+ * must cover the specs it approves whether or not they were already settled.
16374
+ */
16375
+ specPathsInScope(scopeSubsystem) {
16376
+ const index = this.scanAll();
16377
+ const components = this.loadComponentSpecs();
16378
+ const interfaces = this.loadInterfaceSpecs();
16379
+ const implementations = this.loadImplementationSpecs();
16380
+ const inScope = (specSubsystem) => {
16381
+ if (!scopeSubsystem) return true;
16382
+ if (!specSubsystem) return false;
16383
+ return specSubsystem === scopeSubsystem || specSubsystem.startsWith(`${scopeSubsystem}::`);
16384
+ };
16385
+ const out = /* @__PURE__ */ new Set();
16386
+ const add = (p) => {
16387
+ if (p) out.add(path15.resolve(p));
16388
+ };
16389
+ for (const s of this.loadSubsystemSpecs()) {
16390
+ if (!scopeSubsystem || s.id === scopeSubsystem || s.id.startsWith(`${scopeSubsystem}::`)) {
16391
+ add(index.paths.subsystem[s.id]);
16392
+ }
16393
+ }
16394
+ for (const c of components) {
16395
+ if (inScope(c.subsystem)) add(index.paths.component[c.id]);
16396
+ }
16397
+ for (const i of interfaces) {
16398
+ const comp = components.find((c) => c.id === i.component);
16399
+ if (comp && inScope(comp.subsystem)) add(index.paths.interface[i.id]);
16400
+ }
16401
+ for (const m of implementations) {
16402
+ const intf = interfaces.find((i) => i.id === m.contract);
16403
+ const comp = intf ? components.find((c) => c.id === intf.component) : null;
16404
+ if (comp && inScope(comp.subsystem)) add(index.paths.implementation[m.id]);
16405
+ }
16406
+ if (!scopeSubsystem) {
16407
+ add(this.paths.specsSystem());
16408
+ for (const p of Object.values(index.paths.type)) add(p);
16409
+ for (const p of Object.values(index.paths.group)) add(p);
16410
+ }
16411
+ return [...out];
16412
+ }
16251
16413
  /** Set a single spec's status (bumps updatedAt). Caller invalidates the cache. */
16252
16414
  applySpecStatus(kind, id, status) {
16253
16415
  switch (kind) {
@@ -16285,16 +16447,16 @@ var init_specs2 = __esm({
16285
16447
  const files = /* @__PURE__ */ new Set();
16286
16448
  const sysPath = this.paths.specsSystem();
16287
16449
  if (pathExists(sysPath)) {
16288
- files.add(path13.resolve(sysPath));
16450
+ files.add(path15.resolve(sysPath));
16289
16451
  }
16290
16452
  for (const group of Object.values(index.paths)) {
16291
16453
  for (const file of Object.values(group)) {
16292
- files.add(path13.resolve(file));
16454
+ files.add(path15.resolve(file));
16293
16455
  }
16294
16456
  }
16295
16457
  for (const file of files) {
16296
- if (fs9.existsSync(file)) {
16297
- snapshot.set(file, fs9.readFileSync(file, "utf8"));
16458
+ if (fs10.existsSync(file)) {
16459
+ snapshot.set(file, fs10.readFileSync(file, "utf8"));
16298
16460
  }
16299
16461
  }
16300
16462
  return snapshot;
@@ -16308,20 +16470,20 @@ var init_specs2 = __esm({
16308
16470
  const files = listFilesRecursive(specsDir, ".yaml");
16309
16471
  const legacy = [];
16310
16472
  for (const f of files) {
16311
- const base = path13.basename(f);
16312
- const dir = path13.dirname(f);
16473
+ const base = path15.basename(f);
16474
+ const dir = path15.dirname(f);
16313
16475
  if (base === "system.yaml") {
16314
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16476
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16315
16477
  } else if (base === "subsystem.yaml") {
16316
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16478
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16317
16479
  } else if (base === "component.yaml") {
16318
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16480
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16319
16481
  } else if (base === "group.yaml") {
16320
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16482
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16321
16483
  } else if (base === "interface.yaml") {
16322
- legacy.push({ path: f, expected: path13.join(dir, ".interface.yaml") });
16484
+ legacy.push({ path: f, expected: path15.join(dir, ".interface.yaml") });
16323
16485
  } else if (base === "implementation.yaml") {
16324
- legacy.push({ path: f, expected: path13.join(dir, ".implementation.yaml") });
16486
+ legacy.push({ path: f, expected: path15.join(dir, ".implementation.yaml") });
16325
16487
  }
16326
16488
  }
16327
16489
  return legacy;
@@ -16768,8 +16930,8 @@ __export(agent_resolver_exports, {
16768
16930
  resolveAgentTopology: () => resolveAgentTopology
16769
16931
  });
16770
16932
  function listFilesRecursiveSafe(dirPath, ext) {
16771
- if (!fs10.existsSync(dirPath)) return [];
16772
- const nameLower = path14.basename(dirPath).toLowerCase();
16933
+ if (!fs11.existsSync(dirPath)) return [];
16934
+ const nameLower = path16.basename(dirPath).toLowerCase();
16773
16935
  const IGNORED_DIRS = /* @__PURE__ */ new Set([
16774
16936
  "node_modules",
16775
16937
  "target",
@@ -16784,10 +16946,10 @@ function listFilesRecursiveSafe(dirPath, ext) {
16784
16946
  ".vscode"
16785
16947
  ]);
16786
16948
  if (IGNORED_DIRS.has(nameLower)) return [];
16787
- const entries = fs10.readdirSync(dirPath, { withFileTypes: true });
16949
+ const entries = fs11.readdirSync(dirPath, { withFileTypes: true });
16788
16950
  const files = [];
16789
16951
  for (const entry of entries) {
16790
- const fullPath = path14.join(dirPath, entry.name);
16952
+ const fullPath = path16.join(dirPath, entry.name);
16791
16953
  if (entry.isDirectory()) {
16792
16954
  files.push(...listFilesRecursiveSafe(fullPath, ext));
16793
16955
  } else if (entry.isFile() && entry.name.endsWith(ext)) {
@@ -16800,8 +16962,8 @@ function getProjectFiles(projectDir) {
16800
16962
  let files = projectFilesCache.get(projectDir);
16801
16963
  if (!files) {
16802
16964
  files = [];
16803
- const srcDir = path14.join(projectDir, "src");
16804
- const legacySrcDir = path14.join(projectDir, "legacy-src");
16965
+ const srcDir = path16.join(projectDir, "src");
16966
+ const legacySrcDir = path16.join(projectDir, "legacy-src");
16805
16967
  let searchDir = projectDir;
16806
16968
  if (pathExists(srcDir)) {
16807
16969
  searchDir = srcDir;
@@ -16816,7 +16978,7 @@ function getProjectFiles(projectDir) {
16816
16978
  files.push(...listFilesRecursiveSafe(searchDir, ext));
16817
16979
  }
16818
16980
  const rootDir = getProjectRoot();
16819
- files = files.map((f) => path14.relative(rootDir, f).replace(/\\/g, "/"));
16981
+ files = files.map((f) => path16.relative(rootDir, f).replace(/\\/g, "/"));
16820
16982
  projectFilesCache.set(projectDir, files);
16821
16983
  }
16822
16984
  return files;
@@ -16841,8 +17003,8 @@ function inferSourcePathForComponent(comp, subsystems) {
16841
17003
  let bestFile = null;
16842
17004
  let bestScore = -1;
16843
17005
  for (const f of files) {
16844
- const ext = path14.extname(f);
16845
- const base = path14.basename(f, ext).toLowerCase();
17006
+ const ext = path16.extname(f);
17007
+ const base = path16.basename(f, ext).toLowerCase();
16846
17008
  if (candidates.has(base)) {
16847
17009
  let score = 0;
16848
17010
  const normalizedPath = f.toLowerCase();
@@ -16938,7 +17100,7 @@ function resolveAgentTopology() {
16938
17100
  });
16939
17101
  for (const sub of subsystems) {
16940
17102
  if (sub.projectPath) {
16941
- const mountSpecPath = path14.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
17103
+ const mountSpecPath = path16.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
16942
17104
  agents.push({
16943
17105
  id: `${sub.id}-owner`,
16944
17106
  name: `${sub.name} (chained subproject)`,
@@ -16960,9 +17122,9 @@ function resolveAgentTopology() {
16960
17122
  }
16961
17123
  const subComponents = components.filter((c) => c.subsystem === sub.id);
16962
17124
  const ownedPaths = [];
16963
- ownedPaths.push(path14.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
17125
+ ownedPaths.push(path16.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
16964
17126
  for (const c of subComponents) {
16965
- ownedPaths.push(path14.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
17127
+ ownedPaths.push(path16.relative(getProjectRoot(), getComponentPath(c.id, sub.id)).replace(/\\/g, "/"));
16966
17128
  }
16967
17129
  if (!config.rules.generateComponentImplementers) {
16968
17130
  for (const comp of subComponents) {
@@ -17035,10 +17197,10 @@ function resolveAgentTopology() {
17035
17197
  }
17036
17198
  const dependencies = comp.dependsOn.map((depId) => `${depId}-implementer`);
17037
17199
  const readPaths = [
17038
- path14.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
17039
- path14.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
17040
- ...compInterfaces.map((i) => path14.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
17041
- ...compImpls.map((impl) => path14.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
17200
+ path16.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
17201
+ path16.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
17202
+ ...compInterfaces.map((i) => path16.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
17203
+ ...compImpls.map((impl) => path16.relative(getProjectRoot(), getImplementationPath(impl.id, impl.contract)).replace(/\\/g, "/"))
17042
17204
  ];
17043
17205
  agents.push({
17044
17206
  id: `${comp.id}-implementer`,
@@ -17121,12 +17283,12 @@ ${guidance.trim()}
17121
17283
  variantGuidance: record.variantGuidance || void 0
17122
17284
  };
17123
17285
  }
17124
- var path14, fs10, projectFilesCache, UnknownAgentError;
17286
+ var path16, fs11, projectFilesCache, UnknownAgentError;
17125
17287
  var init_agent_resolver = __esm({
17126
17288
  "src/core/agent_resolver.ts"() {
17127
17289
  "use strict";
17128
- path14 = __toESM(require("path"));
17129
- fs10 = __toESM(require("fs"));
17290
+ path16 = __toESM(require("path"));
17291
+ fs11 = __toESM(require("fs"));
17130
17292
  init_loader();
17131
17293
  init_fs();
17132
17294
  init_errors();
@@ -17157,12 +17319,12 @@ __export(loader_exports, {
17157
17319
  saveTopologyConfig: () => saveTopologyConfig
17158
17320
  });
17159
17321
  function aiPathsAt(rootDir) {
17160
- const resolvedRoot = path15.resolve(rootDir);
17322
+ const resolvedRoot = path17.resolve(rootDir);
17161
17323
  const aiDirAt = (...segments) => {
17162
- const waiPath = path15.join(resolvedRoot, ".wai");
17163
- const waironPath = path15.join(resolvedRoot, ".wairon");
17164
- const base = !fs11.existsSync(waiPath) && fs11.existsSync(waironPath) ? waironPath : waiPath;
17165
- return path15.join(base, ...segments);
17324
+ const waiPath = path17.join(resolvedRoot, ".wai");
17325
+ const waironPath = path17.join(resolvedRoot, ".wairon");
17326
+ const base = !fs12.existsSync(waiPath) && fs12.existsSync(waironPath) ? waironPath : waiPath;
17327
+ return path17.join(base, ...segments);
17166
17328
  };
17167
17329
  const specsDir = () => {
17168
17330
  try {
@@ -17170,7 +17332,7 @@ function aiPathsAt(rootDir) {
17170
17332
  if (pathExists(projConfig)) {
17171
17333
  const raw = readYamlFile(projConfig);
17172
17334
  if (raw && raw.paths && raw.paths.specsDir) {
17173
- return path15.resolve(resolvedRoot, raw.paths.specsDir);
17335
+ return path17.resolve(resolvedRoot, raw.paths.specsDir);
17174
17336
  }
17175
17337
  }
17176
17338
  } catch {
@@ -17191,12 +17353,12 @@ function aiPathsAt(rootDir) {
17191
17353
  contextDomainsMd: () => aiDirAt("context", "domains.md"),
17192
17354
  contextWaironGuideMd: () => aiDirAt("context", "wairon-guide.md"),
17193
17355
  specsDir,
17194
- specsSystem: () => path15.join(specsDir(), ".index.yaml"),
17195
- specsSubsystemsDir: () => path15.join(specsDir(), "subsystems"),
17196
- specsComponentsDir: () => path15.join(specsDir(), "components"),
17197
- specsInterfacesDir: () => path15.join(specsDir(), "interfaces"),
17198
- specsImplementationsDir: () => path15.join(specsDir(), "implementations"),
17199
- specsTypesDir: () => path15.join(specsDir(), "types")
17356
+ specsSystem: () => path17.join(specsDir(), ".index.yaml"),
17357
+ specsSubsystemsDir: () => path17.join(specsDir(), "subsystems"),
17358
+ specsComponentsDir: () => path17.join(specsDir(), "components"),
17359
+ specsInterfacesDir: () => path17.join(specsDir(), "interfaces"),
17360
+ specsImplementationsDir: () => path17.join(specsDir(), "implementations"),
17361
+ specsTypesDir: () => path17.join(specsDir(), "types")
17200
17362
  };
17201
17363
  }
17202
17364
  function isProjectInitialized() {
@@ -17239,12 +17401,12 @@ function loadTopologyConfig() {
17239
17401
  function saveTopologyConfig(config) {
17240
17402
  writeYamlFile(AI_PATHS.topologyConfig(), config);
17241
17403
  }
17242
- var fs11, path15, AI_PATHS;
17404
+ var fs12, path17, AI_PATHS;
17243
17405
  var init_loader = __esm({
17244
17406
  "src/config/loader.ts"() {
17245
17407
  "use strict";
17246
- fs11 = __toESM(require("fs"));
17247
- path15 = __toESM(require("path"));
17408
+ fs12 = __toESM(require("fs"));
17409
+ path17 = __toESM(require("path"));
17248
17410
  init_fs();
17249
17411
  init_yaml();
17250
17412
  init_errors();
@@ -17284,7 +17446,7 @@ __export(domains_exports, {
17284
17446
  resolveDomains: () => resolveDomains
17285
17447
  });
17286
17448
  function rel(p) {
17287
- return path17.relative(process.cwd(), p).replace(/\\/g, "/");
17449
+ return path19.relative(process.cwd(), p).replace(/\\/g, "/");
17288
17450
  }
17289
17451
  function deriveSubsystemDomains() {
17290
17452
  const subsystems = loadSubsystemSpecs();
@@ -17334,11 +17496,11 @@ function removeFreeStandingDomain(id) {
17334
17496
  config.domains.splice(idx, 1);
17335
17497
  saveTopologyConfig(config);
17336
17498
  }
17337
- var path17;
17499
+ var path19;
17338
17500
  var init_domains = __esm({
17339
17501
  "src/core/domains.ts"() {
17340
17502
  "use strict";
17341
- path17 = __toESM(require("path"));
17503
+ path19 = __toESM(require("path"));
17342
17504
  init_loader();
17343
17505
  init_specs2();
17344
17506
  init_errors();
@@ -17669,6 +17831,7 @@ __export(src_exports, {
17669
17831
  skillExtendErrors: () => skillExtendErrors,
17670
17832
  skillsDirForTarget: () => skillsDirForTarget,
17671
17833
  snapshotSpecFiles: () => snapshotSpecFiles,
17834
+ specPathsInScope: () => specPathsInScope,
17672
17835
  splitNamespace: () => splitNamespace,
17673
17836
  stateIdEquals: () => stateIdEquals,
17674
17837
  stateIdString: () => stateIdString,
@@ -17699,8 +17862,8 @@ init_defaults();
17699
17862
  init_loader();
17700
17863
 
17701
17864
  // src/core/detection.ts
17702
- var fs12 = __toESM(require("fs"));
17703
- var path16 = __toESM(require("path"));
17865
+ var fs13 = __toESM(require("fs"));
17866
+ var path18 = __toESM(require("path"));
17704
17867
  init_defaults();
17705
17868
  var PACKAGE_MARKERS = [
17706
17869
  "package.json",
@@ -17752,7 +17915,7 @@ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
17752
17915
  });
17753
17916
  }
17754
17917
  function parseGitmodules(filePath) {
17755
- const content = fs12.readFileSync(filePath, "utf-8");
17918
+ const content = fs13.readFileSync(filePath, "utf-8");
17756
17919
  const entries = [];
17757
17920
  let current2 = {};
17758
17921
  for (const line of content.split("\n")) {
@@ -17774,8 +17937,8 @@ function parseGitmodules(filePath) {
17774
17937
  return entries;
17775
17938
  }
17776
17939
  function detectGitSubmodules(projectRoot) {
17777
- const gitmodulesPath = path16.join(projectRoot, ".gitmodules");
17778
- if (!fs12.existsSync(gitmodulesPath)) return [];
17940
+ const gitmodulesPath = path18.join(projectRoot, ".gitmodules");
17941
+ if (!fs13.existsSync(gitmodulesPath)) return [];
17779
17942
  return parseGitmodules(gitmodulesPath).map((entry) => ({
17780
17943
  suggestedId: pathToId(entry.path),
17781
17944
  suggestedName: pathToName(entry.path),
@@ -17793,18 +17956,18 @@ function walkForGit(projectRoot, currentDir, depth, results) {
17793
17956
  if (depth > MAX_SCAN_DEPTH) return;
17794
17957
  let entries;
17795
17958
  try {
17796
- entries = fs12.readdirSync(currentDir, { withFileTypes: true });
17959
+ entries = fs13.readdirSync(currentDir, { withFileTypes: true });
17797
17960
  } catch {
17798
17961
  return;
17799
17962
  }
17800
17963
  for (const entry of entries) {
17801
17964
  if (!entry.isDirectory()) continue;
17802
17965
  if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
17803
- const fullPath = path16.join(currentDir, entry.name);
17804
- const relPath = normalizePath3(path16.relative(projectRoot, fullPath));
17966
+ const fullPath = path18.join(currentDir, entry.name);
17967
+ const relPath = normalizePath3(path18.relative(projectRoot, fullPath));
17805
17968
  if (relPath === "" || relPath === ".") continue;
17806
- const gitPath = path16.join(fullPath, ".git");
17807
- if (fs12.existsSync(gitPath)) {
17969
+ const gitPath = path18.join(fullPath, ".git");
17970
+ if (fs13.existsSync(gitPath)) {
17808
17971
  results.push({
17809
17972
  suggestedId: pathToId(relPath),
17810
17973
  suggestedName: pathToName(relPath),
@@ -17826,17 +17989,17 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
17826
17989
  if (depth > MAX_SCAN_DEPTH) return;
17827
17990
  let entries;
17828
17991
  try {
17829
- entries = fs12.readdirSync(currentDir, { withFileTypes: true });
17992
+ entries = fs13.readdirSync(currentDir, { withFileTypes: true });
17830
17993
  } catch {
17831
17994
  return;
17832
17995
  }
17833
17996
  for (const entry of entries) {
17834
17997
  if (!entry.isDirectory()) continue;
17835
17998
  if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
17836
- const fullPath = path16.join(currentDir, entry.name);
17837
- const relPath = normalizePath3(path16.relative(projectRoot, fullPath));
17999
+ const fullPath = path18.join(currentDir, entry.name);
18000
+ const relPath = normalizePath3(path18.relative(projectRoot, fullPath));
17838
18001
  if (relPath === "" || relPath === ".") continue;
17839
- const hasMarker = PACKAGE_MARKERS.some((m) => fs12.existsSync(path16.join(fullPath, m)));
18002
+ const hasMarker = PACKAGE_MARKERS.some((m) => fs13.existsSync(path18.join(fullPath, m)));
17840
18003
  if (hasMarker) {
17841
18004
  results.push({
17842
18005
  suggestedId: pathToId(relPath),
@@ -17850,8 +18013,8 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
17850
18013
  }
17851
18014
  }
17852
18015
  function pathToId(relPath) {
17853
- const basename9 = path16.basename(relPath);
17854
- return basename9.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
18016
+ const basename10 = path18.basename(relPath);
18017
+ return basename10.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
17855
18018
  }
17856
18019
  function pathToName(relPath) {
17857
18020
  const id = pathToId(relPath);
@@ -17871,8 +18034,8 @@ init_rules();
17871
18034
  init_specs2();
17872
18035
 
17873
18036
  // src/core/provision.ts
17874
- var fs13 = __toESM(require("fs"));
17875
- var path18 = __toESM(require("path"));
18037
+ var fs14 = __toESM(require("fs"));
18038
+ var path20 = __toESM(require("path"));
17876
18039
  init_specs2();
17877
18040
  init_loader();
17878
18041
  init_fs();
@@ -17920,7 +18083,7 @@ function provisionProject(name) {
17920
18083
  function ensureProjectInitialized(fallbackName) {
17921
18084
  const now = (/* @__PURE__ */ new Date()).toISOString();
17922
18085
  const paths = aiPathsAt(getProjectRoot());
17923
- const hasSystem = fs13.existsSync(paths.specsSystem());
18086
+ const hasSystem = fs14.existsSync(paths.specsSystem());
17924
18087
  let name = fallbackName;
17925
18088
  if (hasSystem) {
17926
18089
  const existing = loadSystemSpec();
@@ -17928,7 +18091,7 @@ function ensureProjectInitialized(fallbackName) {
17928
18091
  }
17929
18092
  let wroteConfig = false;
17930
18093
  let wroteSystem = false;
17931
- if (!fs13.existsSync(paths.projectConfig())) {
18094
+ if (!fs14.existsSync(paths.projectConfig())) {
17932
18095
  saveProjectConfig(defaultProjectConfig(name, now));
17933
18096
  wroteConfig = true;
17934
18097
  }
@@ -17957,11 +18120,11 @@ function promoteAllComplete() {
17957
18120
  function walkChainedSubprojects(projectRoot, onChild) {
17958
18121
  const visited = /* @__PURE__ */ new Set();
17959
18122
  const walk = (dir) => {
17960
- const resolved = path18.resolve(dir);
18123
+ const resolved = path20.resolve(dir);
17961
18124
  if (visited.has(resolved)) return;
17962
18125
  visited.add(resolved);
17963
18126
  const specsDir = aiPathsAt(dir).specsDir();
17964
- if (!fs13.existsSync(specsDir)) return;
18127
+ if (!fs14.existsSync(specsDir)) return;
17965
18128
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
17966
18129
  let raw;
17967
18130
  try {
@@ -17979,7 +18142,7 @@ function walkChainedSubprojects(projectRoot, onChild) {
17979
18142
  continue;
17980
18143
  }
17981
18144
  const id = raw.id;
17982
- onChild(childDir, typeof id === "string" ? id : path18.basename(childDir));
18145
+ onChild(childDir, typeof id === "string" ? id : path20.basename(childDir));
17983
18146
  walk(childDir);
17984
18147
  }
17985
18148
  };
@@ -17988,7 +18151,7 @@ function walkChainedSubprojects(projectRoot, onChild) {
17988
18151
  function listDirectChainedSubprojects(projectRoot) {
17989
18152
  const out = [];
17990
18153
  const specsDir = aiPathsAt(projectRoot).specsDir();
17991
- if (!fs13.existsSync(specsDir)) return out;
18154
+ if (!fs14.existsSync(specsDir)) return out;
17992
18155
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
17993
18156
  let raw;
17994
18157
  try {
@@ -18006,12 +18169,12 @@ function listDirectChainedSubprojects(projectRoot) {
18006
18169
  continue;
18007
18170
  }
18008
18171
  const id = raw.id;
18009
- out.push({ dir, subsystemId: typeof id === "string" ? id : path18.basename(dir) });
18172
+ out.push({ dir, subsystemId: typeof id === "string" ? id : path20.basename(dir) });
18010
18173
  }
18011
18174
  return out;
18012
18175
  }
18013
18176
  function childHasSpecsButNoConfig(childDir) {
18014
- return fs13.existsSync(aiPathsAt(childDir).specsDir()) && !fs13.existsSync(aiPathsAt(childDir).projectConfig());
18177
+ return fs14.existsSync(aiPathsAt(childDir).specsDir()) && !fs14.existsSync(aiPathsAt(childDir).projectConfig());
18015
18178
  }
18016
18179
  function findChainingSubprojectsMissingConfig(projectRoot) {
18017
18180
  const missing = [];
@@ -18060,14 +18223,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
18060
18223
  const oldDir = assertContainedProjectPath(root, sub.projectPath);
18061
18224
  const newDir = assertContainedProjectPath(root, nextPath);
18062
18225
  if (oldDir !== newDir) {
18063
- if (!fs13.existsSync(oldDir)) {
18226
+ if (!fs14.existsSync(oldDir)) {
18064
18227
  throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
18065
18228
  }
18066
- if (fs13.existsSync(newDir)) {
18229
+ if (fs14.existsSync(newDir)) {
18067
18230
  throw new WaironError(`Target directory already exists: ${newDir}`);
18068
18231
  }
18069
- ensureDir(path18.dirname(newDir));
18070
- fs13.renameSync(oldDir, newDir);
18232
+ ensureDir(path20.dirname(newDir));
18233
+ fs14.renameSync(oldDir, newDir);
18071
18234
  }
18072
18235
  saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
18073
18236
  invalidateSpecCache();
@@ -18076,9 +18239,9 @@ function toPosixPath(p) {
18076
18239
  return p.replace(/\\/g, "/");
18077
18240
  }
18078
18241
  function isWithinDir(dir, file) {
18079
- const d = path18.resolve(dir);
18080
- const f = path18.resolve(file);
18081
- return f === d || f.startsWith(d + path18.sep);
18242
+ const d = path20.resolve(dir);
18243
+ const f = path20.resolve(file);
18244
+ return f === d || f.startsWith(d + path20.sep);
18082
18245
  }
18083
18246
  function externalizeSubsystem(subsystemId, projectPath) {
18084
18247
  if (subsystemId.includes("::")) {
@@ -18090,14 +18253,14 @@ function externalizeSubsystem(subsystemId, projectPath) {
18090
18253
  }
18091
18254
  const parentRoot = getProjectRoot();
18092
18255
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
18093
- const fooDir = path18.join(parentSpecsDir, subsystemId);
18094
- if (!fs13.existsSync(fooDir)) {
18256
+ const fooDir = path20.join(parentSpecsDir, subsystemId);
18257
+ if (!fs14.existsSync(fooDir)) {
18095
18258
  throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
18096
18259
  }
18097
18260
  const relPath = toPosixPath(projectPath);
18098
18261
  const childDir = assertContainedProjectPath(parentRoot, relPath);
18099
- const childFooDir = path18.join(childDir, ".wai", "specs", subsystemId);
18100
- if (fs13.existsSync(childFooDir)) {
18262
+ const childFooDir = path20.join(childDir, ".wai", "specs", subsystemId);
18263
+ if (fs14.existsSync(childFooDir)) {
18101
18264
  throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
18102
18265
  }
18103
18266
  const renameMap = buildRenameMap(
@@ -18107,17 +18270,17 @@ function externalizeSubsystem(subsystemId, projectPath) {
18107
18270
  );
18108
18271
  const childSystemName = foo.name || subsystemId;
18109
18272
  runWithProjectRoot(childDir, () => {
18110
- ensureDir(path18.join(childDir, ".wai", "specs"));
18273
+ ensureDir(path20.join(childDir, ".wai", "specs"));
18111
18274
  provisionProject(childSystemName);
18112
18275
  });
18113
- ensureDir(path18.dirname(childFooDir));
18114
- fs13.renameSync(fooDir, childFooDir);
18115
- patchSubsystemIndex(path18.join(childFooDir, ".index.yaml"), (s) => {
18276
+ ensureDir(path20.dirname(childFooDir));
18277
+ fs14.renameSync(fooDir, childFooDir);
18278
+ patchSubsystemIndex(path20.join(childFooDir, ".index.yaml"), (s) => {
18116
18279
  s.parentSystem = childSystemName;
18117
18280
  delete s.projectPath;
18118
18281
  });
18119
18282
  ensureDir(fooDir);
18120
- writeYamlFile(path18.join(fooDir, ".index.yaml"), {
18283
+ writeYamlFile(path20.join(fooDir, ".index.yaml"), {
18121
18284
  id: subsystemId,
18122
18285
  name: foo.name,
18123
18286
  description: foo.description,
@@ -18143,9 +18306,9 @@ function internalizeSubsystem(subsystemId) {
18143
18306
  const parentRoot = getProjectRoot();
18144
18307
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
18145
18308
  const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
18146
- const childWai = path18.join(childDir, ".wai");
18147
- const childFooDir = path18.join(childDir, ".wai", "specs", subsystemId);
18148
- if (!fs13.existsSync(childFooDir)) {
18309
+ const childWai = path20.join(childDir, ".wai");
18310
+ const childFooDir = path20.join(childDir, ".wai", "specs", subsystemId);
18311
+ if (!fs14.existsSync(childFooDir)) {
18149
18312
  throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
18150
18313
  }
18151
18314
  const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
@@ -18158,15 +18321,15 @@ function internalizeSubsystem(subsystemId) {
18158
18321
  false
18159
18322
  );
18160
18323
  const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
18161
- const fooDir = path18.join(parentSpecsDir, subsystemId);
18162
- fs13.rmSync(fooDir, { recursive: true, force: true });
18163
- ensureDir(path18.dirname(fooDir));
18164
- fs13.renameSync(childFooDir, fooDir);
18165
- patchSubsystemIndex(path18.join(fooDir, ".index.yaml"), (s) => {
18324
+ const fooDir = path20.join(parentSpecsDir, subsystemId);
18325
+ fs14.rmSync(fooDir, { recursive: true, force: true });
18326
+ ensureDir(path20.dirname(fooDir));
18327
+ fs14.renameSync(childFooDir, fooDir);
18328
+ patchSubsystemIndex(path20.join(fooDir, ".index.yaml"), (s) => {
18166
18329
  s.parentSystem = parentSystemName;
18167
18330
  delete s.projectPath;
18168
18331
  });
18169
- fs13.rmSync(childWai, { recursive: true, force: true });
18332
+ fs14.rmSync(childWai, { recursive: true, force: true });
18170
18333
  rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
18171
18334
  invalidateSpecCache();
18172
18335
  }
@@ -18263,7 +18426,7 @@ function rewriteRefsInDir(specsDir, renameMap, excludeDir) {
18263
18426
  }
18264
18427
  }
18265
18428
  function patchSubsystemIndex(indexPath, mutate) {
18266
- if (!fs13.existsSync(indexPath)) return;
18429
+ if (!fs14.existsSync(indexPath)) return;
18267
18430
  const raw = readYamlFile(indexPath);
18268
18431
  mutate(raw);
18269
18432
  raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -18277,8 +18440,8 @@ init_statehash();
18277
18440
  init_agent_resolver();
18278
18441
 
18279
18442
  // src/core/skills.ts
18280
- var path19 = __toESM(require("path"));
18281
- var fs14 = __toESM(require("fs"));
18443
+ var path21 = __toESM(require("path"));
18444
+ var fs15 = __toESM(require("fs"));
18282
18445
  init_fs();
18283
18446
  init_defaults();
18284
18447
  init_extensions();
@@ -18412,16 +18575,16 @@ function packNamespace(pack) {
18412
18575
  return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
18413
18576
  }
18414
18577
  function extensionsFor(builtin, packSkills) {
18415
- return packSkills.filter((s) => s.extends === builtin && fs14.existsSync(s.sourcePath));
18578
+ return packSkills.filter((s) => s.extends === builtin && fs15.existsSync(s.sourcePath));
18416
18579
  }
18417
18580
  function composeBuiltinSkill(name, packSkills) {
18418
18581
  const srcPath = skillTemplatePath(name);
18419
- const base = fs14.existsSync(srcPath) ? fs14.readFileSync(srcPath, "utf-8") : "";
18582
+ const base = fs15.existsSync(srcPath) ? fs15.readFileSync(srcPath, "utf-8") : "";
18420
18583
  const sections = extensionsFor(name, packSkills);
18421
18584
  if (sections.length === 0) return base;
18422
18585
  const parts = [base.trimEnd()];
18423
18586
  for (const section of sections) {
18424
- const body = fs14.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
18587
+ const body = fs15.readFileSync(section.sourcePath, "utf-8").replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "");
18425
18588
  parts.push(`## Platform: ${section.pack}`, body.trim());
18426
18589
  }
18427
18590
  return `${parts.join("\n\n")}
@@ -18437,16 +18600,16 @@ function readFrontmatter(raw, fallbackName) {
18437
18600
  return { name: field("name") || fallbackName, description: field("description") };
18438
18601
  }
18439
18602
  function builtinSkillsDir() {
18440
- return path19.resolve(__dirname, "..", "templates", "skills");
18603
+ return path21.resolve(__dirname, "..", "templates", "skills");
18441
18604
  }
18442
18605
  function skillTemplatePath(name) {
18443
- return path19.join(builtinSkillsDir(), `${name}.md`);
18606
+ return path21.join(builtinSkillsDir(), `${name}.md`);
18444
18607
  }
18445
18608
  function skillDestPath(type, destDir, name) {
18446
18609
  if (type === "claude" || type === "codex" || type === "gemini" || type === "agy") {
18447
- return path19.join(destDir, name, "SKILL.md");
18610
+ return path21.join(destDir, name, "SKILL.md");
18448
18611
  }
18449
- return path19.join(destDir, `${name}.md`);
18612
+ return path21.join(destDir, `${name}.md`);
18450
18613
  }
18451
18614
  function skillsDirForTarget(type) {
18452
18615
  switch (type) {
@@ -18481,22 +18644,22 @@ function exportSddSkills(targetTypes) {
18481
18644
  ensureDir(destDir);
18482
18645
  destinations.push(destDir);
18483
18646
  for (const name of SKILL_NAMES) {
18484
- if (!fs14.existsSync(skillTemplatePath(name))) continue;
18647
+ if (!fs15.existsSync(skillTemplatePath(name))) continue;
18485
18648
  const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
18486
18649
  const destPath = skillDestPath(type, destDir, name);
18487
- ensureDir(path19.dirname(destPath));
18488
- fs14.writeFileSync(destPath, content, "utf-8");
18650
+ ensureDir(path21.dirname(destPath));
18651
+ fs15.writeFileSync(destPath, content, "utf-8");
18489
18652
  fileCount++;
18490
18653
  }
18491
18654
  for (const skill of packSkills) {
18492
18655
  if (skill.extends !== void 0) continue;
18493
18656
  if (!skill.targets.includes(type)) continue;
18494
- if (!fs14.existsSync(skill.sourcePath)) continue;
18657
+ if (!fs15.existsSync(skill.sourcePath)) continue;
18495
18658
  const id = packSkillId(skill);
18496
- const content = fs14.readFileSync(skill.sourcePath, "utf-8");
18659
+ const content = fs15.readFileSync(skill.sourcePath, "utf-8");
18497
18660
  const destPath = skillDestPath(type, destDir, id);
18498
- ensureDir(path19.dirname(destPath));
18499
- fs14.writeFileSync(destPath, content, "utf-8");
18661
+ ensureDir(path21.dirname(destPath));
18662
+ fs15.writeFileSync(destPath, content, "utf-8");
18500
18663
  fileCount++;
18501
18664
  }
18502
18665
  }
@@ -18509,12 +18672,12 @@ function checkSkillFreshness(type) {
18509
18672
  const packSkills = loadProjectExtensions2().skills.filter((s) => s.targets.includes(type));
18510
18673
  for (const name of SKILL_NAMES) {
18511
18674
  const destPath = skillDestPath(type, dir, name);
18512
- if (!fs14.existsSync(destPath)) {
18675
+ if (!fs15.existsSync(destPath)) {
18513
18676
  result.missing.push(name);
18514
18677
  continue;
18515
18678
  }
18516
18679
  const want = composeBuiltinSkill(name, packSkills);
18517
- const have = fs14.readFileSync(destPath, "utf-8");
18680
+ const have = fs15.readFileSync(destPath, "utf-8");
18518
18681
  if (have === want) result.ok.push(name);
18519
18682
  else result.stale.push(name);
18520
18683
  }
@@ -18534,7 +18697,7 @@ var SkillResourceNotFoundError = class extends Error {
18534
18697
  }
18535
18698
  };
18536
18699
  function readSkillFrontmatter(name) {
18537
- return readFrontmatter(fs14.readFileSync(skillTemplatePath(name), "utf-8"), name);
18700
+ return readFrontmatter(fs15.readFileSync(skillTemplatePath(name), "utf-8"), name);
18538
18701
  }
18539
18702
  function listSkillResources() {
18540
18703
  const builtin = RESOURCE_SKILL_IDS.map((id) => {
@@ -18548,9 +18711,9 @@ function listSkillResources() {
18548
18711
  defaultForHostedMcp: true
18549
18712
  };
18550
18713
  });
18551
- const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs14.existsSync(s.sourcePath)).map((skill) => {
18714
+ const pack = loadProjectExtensions2().skills.filter((s) => s.extends === void 0 && fs15.existsSync(s.sourcePath)).map((skill) => {
18552
18715
  const id = packSkillId(skill);
18553
- const fm = readFrontmatter(fs14.readFileSync(skill.sourcePath, "utf-8"), id);
18716
+ const fm = readFrontmatter(fs15.readFileSync(skill.sourcePath, "utf-8"), id);
18554
18717
  return {
18555
18718
  id,
18556
18719
  name: fm.name,
@@ -18566,8 +18729,8 @@ function readSkillResource(resourceId) {
18566
18729
  const packSkills = loadProjectExtensions2().skills;
18567
18730
  if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
18568
18731
  const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
18569
- if (packSkill) return fs14.readFileSync(packSkill.sourcePath, "utf-8");
18570
- return fs14.readFileSync(skillTemplatePath(resourceId), "utf-8");
18732
+ if (packSkill) return fs15.readFileSync(packSkill.sourcePath, "utf-8");
18733
+ return fs15.readFileSync(skillTemplatePath(resourceId), "utf-8");
18571
18734
  }
18572
18735
  function listResources() {
18573
18736
  return listSkillResources();
@@ -18756,7 +18919,7 @@ var WAIRON_MANAGED_MARKER = "wairon:managed";
18756
18919
  var WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
18757
18920
 
18758
18921
  // src/exporters/claude.ts
18759
- var path20 = __toESM(require("path"));
18922
+ var path22 = __toESM(require("path"));
18760
18923
  init_fs();
18761
18924
  var ClaudeExporter = class {
18762
18925
  constructor() {
@@ -18765,7 +18928,7 @@ var ClaudeExporter = class {
18765
18928
  outputPath(ctx) {
18766
18929
  const { agent, target, projectRoot } = ctx;
18767
18930
  const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
18768
- return path20.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18931
+ return path22.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18769
18932
  }
18770
18933
  export(ctx) {
18771
18934
  const { agent, renderedInstructions } = ctx;
@@ -18786,7 +18949,7 @@ var ClaudeExporter = class {
18786
18949
  };
18787
18950
 
18788
18951
  // src/exporters/custom.ts
18789
- var path21 = __toESM(require("path"));
18952
+ var path23 = __toESM(require("path"));
18790
18953
  init_fs();
18791
18954
  var CustomExporter = class {
18792
18955
  constructor() {
@@ -18797,7 +18960,7 @@ var CustomExporter = class {
18797
18960
  if (!("outputDir" in target)) {
18798
18961
  throw new Error("CustomExporter requires target.outputDir");
18799
18962
  }
18800
- return path21.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18963
+ return path23.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18801
18964
  }
18802
18965
  export(ctx) {
18803
18966
  const { agent, target, renderedInstructions } = ctx;
@@ -18820,7 +18983,7 @@ var CustomExporter = class {
18820
18983
  };
18821
18984
 
18822
18985
  // src/exporters/gemini.ts
18823
- var path22 = __toESM(require("path"));
18986
+ var path24 = __toESM(require("path"));
18824
18987
  init_fs();
18825
18988
  var GeminiExporter = class {
18826
18989
  constructor() {
@@ -18829,7 +18992,7 @@ var GeminiExporter = class {
18829
18992
  outputPath(ctx) {
18830
18993
  const { agent, target, projectRoot } = ctx;
18831
18994
  const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
18832
- return path22.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
18995
+ return path24.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
18833
18996
  }
18834
18997
  export(ctx) {
18835
18998
  const { agent, renderedInstructions } = ctx;
@@ -18854,7 +19017,7 @@ function yamlString(value) {
18854
19017
  }
18855
19018
 
18856
19019
  // src/exporters/generate.ts
18857
- var path23 = __toESM(require("path"));
19020
+ var path25 = __toESM(require("path"));
18858
19021
  init_fs();
18859
19022
 
18860
19023
  // src/exporters/registry.ts
@@ -18921,7 +19084,7 @@ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProj
18921
19084
  const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
18922
19085
  if (!targetConfig) continue;
18923
19086
  const ctx = { agent, projectRoot, target: targetConfig };
18924
- expected.add(path23.resolve(getExporter(targetConfig).outputPath(ctx)));
19087
+ expected.add(path25.resolve(getExporter(targetConfig).outputPath(ctx)));
18925
19088
  }
18926
19089
  }
18927
19090
  return expected;
@@ -19316,6 +19479,7 @@ init_yaml();
19316
19479
  skillExtendErrors,
19317
19480
  skillsDirForTarget,
19318
19481
  snapshotSpecFiles,
19482
+ specPathsInScope,
19319
19483
  splitNamespace,
19320
19484
  stateIdEquals,
19321
19485
  stateIdString,