@wairon/cli 5.1.1-dev.5 → 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.5";
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;
@@ -15996,16 +16114,46 @@ var init_specs2 = __esm({
15996
16114
  return null;
15997
16115
  }
15998
16116
  }
16117
+ /**
16118
+ * Refuse a write that would land on a file already holding a DIFFERENT spec.
16119
+ *
16120
+ * In the nested layout a spec's path is derived from its parent — a component
16121
+ * for an interface, a contract for an implementation — and the spec's own id
16122
+ * is not part of it (see getInterfacePath / getImplementationPath, which take
16123
+ * the id but ignore it once the parent resolves). So a second id bound to the
16124
+ * same parent resolves to the SAME file.
16125
+ *
16126
+ * Left unguarded that is silent data loss, and doubly invisible: the caller's
16127
+ * `existing` lookup is by the NEW id, finds nothing, and every re-author
16128
+ * notice ("REMOVED …", the carry-forward seam) stays quiet. An agent renaming
16129
+ * an interface by defining a new one destroys the old contract, its
16130
+ * narratives and its lint.allows, and is told "Successfully defined".
16131
+ */
16132
+ assertPathHoldsNoOtherSpec(p, id, kind, parentLabel) {
16133
+ if (!pathExists(p)) return;
16134
+ let occupantId;
16135
+ try {
16136
+ occupantId = readYamlFile(p)?.id;
16137
+ } catch {
16138
+ return;
16139
+ }
16140
+ if (!occupantId) return;
16141
+ if (occupantId === id || splitNamespace(occupantId).localId === splitNamespace(id).localId) return;
16142
+ throw new Error(
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.`
16144
+ );
16145
+ }
15999
16146
  /** Returns non-fatal placement notices (see saveTypeSpec) — empty when there is nothing to clarify. */
16000
16147
  saveInterfaceSpec(spec, opts) {
16001
16148
  const notices = [];
16002
16149
  const p = this.getInterfacePath(spec.id, spec.component);
16003
- ensureDir(path13.dirname(p));
16150
+ this.assertPathHoldsNoOtherSpec(p, spec.id, "interface", `component "${spec.component}"`);
16151
+ ensureDir(path15.dirname(p));
16004
16152
  const specToWrite = this.prepareInterfaceForWrite(spec);
16005
16153
  const existing = this.loadInterfaceSpec(spec.id);
16006
16154
  if (existing && existing.component !== spec.component && splitNamespace(existing.component).localId !== splitNamespace(spec.component).localId) {
16007
16155
  notices.push(
16008
- `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.`
16009
16157
  );
16010
16158
  }
16011
16159
  if (existing) {
@@ -16028,9 +16176,9 @@ var init_specs2 = __esm({
16028
16176
  }
16029
16177
  deleteInterfaceSpec(id) {
16030
16178
  const p = this.getInterfacePath(id);
16031
- if (!fs9.existsSync(p)) return false;
16032
- fs9.unlinkSync(p);
16033
- 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()));
16034
16182
  invalidateSpecCache();
16035
16183
  return true;
16036
16184
  }
@@ -16063,12 +16211,13 @@ var init_specs2 = __esm({
16063
16211
  saveImplementationSpec(spec, opts) {
16064
16212
  const notices = [];
16065
16213
  const p = this.getImplementationPath(spec.id, spec.contract);
16066
- ensureDir(path13.dirname(p));
16214
+ this.assertPathHoldsNoOtherSpec(p, spec.id, "implementation", `contract "${spec.contract}"`);
16215
+ ensureDir(path15.dirname(p));
16067
16216
  const specToWrite = this.prepareImplementationForWrite(spec);
16068
16217
  const existing = this.loadImplementationSpec(spec.id);
16069
16218
  if (existing && existing.contract !== spec.contract && splitNamespace(existing.contract).localId !== splitNamespace(spec.contract).localId) {
16070
16219
  notices.push(
16071
- `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.`
16072
16221
  );
16073
16222
  }
16074
16223
  if (existing) {
@@ -16084,9 +16233,9 @@ var init_specs2 = __esm({
16084
16233
  }
16085
16234
  deleteImplementationSpec(id) {
16086
16235
  const p = this.getImplementationPath(id);
16087
- if (!fs9.existsSync(p)) return false;
16088
- fs9.unlinkSync(p);
16089
- 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()));
16090
16239
  invalidateSpecCache();
16091
16240
  return true;
16092
16241
  }
@@ -16111,11 +16260,11 @@ var init_specs2 = __esm({
16111
16260
  const existing = this.loadTypeSpec(spec.id);
16112
16261
  const group = spec.group || (existing ? existing.group : void 0);
16113
16262
  const p = this.getTypePath(spec.id, spec.subsystem, group);
16114
- ensureDir(path13.dirname(p));
16263
+ ensureDir(path15.dirname(p));
16115
16264
  const subsystemChanged = existing && (existing.subsystem ?? "") !== (spec.subsystem ?? "") && splitNamespace(existing.subsystem ?? "").localId !== splitNamespace(spec.subsystem ?? "").localId;
16116
16265
  if (subsystemChanged) {
16117
16266
  notices.push(
16118
- `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)"}").`
16119
16268
  );
16120
16269
  }
16121
16270
  if (spec.subsystem && (!existing || subsystemChanged) && !this.getSubsystemPath(spec.subsystem).endsWith(".index.yaml")) {
@@ -16138,9 +16287,9 @@ var init_specs2 = __esm({
16138
16287
  deleteTypeSpec(id) {
16139
16288
  const spec = this.loadTypeSpec(id);
16140
16289
  const p = this.getTypePath(id, spec?.subsystem, spec?.group);
16141
- if (!fs9.existsSync(p)) return false;
16142
- fs9.unlinkSync(p);
16143
- 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()));
16144
16293
  invalidateSpecCache();
16145
16294
  return true;
16146
16295
  }
@@ -16155,7 +16304,7 @@ var init_specs2 = __esm({
16155
16304
  }
16156
16305
  saveGroupSpec(spec) {
16157
16306
  const p = this.getGroupPath(spec.id);
16158
- ensureDir(path13.dirname(p));
16307
+ ensureDir(path15.dirname(p));
16159
16308
  const specToWrite = this.prepareGroupForWrite(spec);
16160
16309
  const existing = this.loadGroupSpec(spec.id);
16161
16310
  if (existing) {
@@ -16167,9 +16316,9 @@ var init_specs2 = __esm({
16167
16316
  }
16168
16317
  deleteGroupSpec(id) {
16169
16318
  const p = this.getGroupPath(id);
16170
- if (!fs9.existsSync(p)) return false;
16171
- fs9.unlinkSync(p);
16172
- 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()));
16173
16322
  invalidateSpecCache();
16174
16323
  return true;
16175
16324
  }
@@ -16217,6 +16366,50 @@ var init_specs2 = __esm({
16217
16366
  }
16218
16367
  return out;
16219
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
+ }
16220
16413
  /** Set a single spec's status (bumps updatedAt). Caller invalidates the cache. */
16221
16414
  applySpecStatus(kind, id, status) {
16222
16415
  switch (kind) {
@@ -16254,16 +16447,16 @@ var init_specs2 = __esm({
16254
16447
  const files = /* @__PURE__ */ new Set();
16255
16448
  const sysPath = this.paths.specsSystem();
16256
16449
  if (pathExists(sysPath)) {
16257
- files.add(path13.resolve(sysPath));
16450
+ files.add(path15.resolve(sysPath));
16258
16451
  }
16259
16452
  for (const group of Object.values(index.paths)) {
16260
16453
  for (const file of Object.values(group)) {
16261
- files.add(path13.resolve(file));
16454
+ files.add(path15.resolve(file));
16262
16455
  }
16263
16456
  }
16264
16457
  for (const file of files) {
16265
- if (fs9.existsSync(file)) {
16266
- snapshot.set(file, fs9.readFileSync(file, "utf8"));
16458
+ if (fs10.existsSync(file)) {
16459
+ snapshot.set(file, fs10.readFileSync(file, "utf8"));
16267
16460
  }
16268
16461
  }
16269
16462
  return snapshot;
@@ -16277,20 +16470,20 @@ var init_specs2 = __esm({
16277
16470
  const files = listFilesRecursive(specsDir, ".yaml");
16278
16471
  const legacy = [];
16279
16472
  for (const f of files) {
16280
- const base = path13.basename(f);
16281
- const dir = path13.dirname(f);
16473
+ const base = path15.basename(f);
16474
+ const dir = path15.dirname(f);
16282
16475
  if (base === "system.yaml") {
16283
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16476
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16284
16477
  } else if (base === "subsystem.yaml") {
16285
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16478
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16286
16479
  } else if (base === "component.yaml") {
16287
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16480
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16288
16481
  } else if (base === "group.yaml") {
16289
- legacy.push({ path: f, expected: path13.join(dir, ".index.yaml") });
16482
+ legacy.push({ path: f, expected: path15.join(dir, ".index.yaml") });
16290
16483
  } else if (base === "interface.yaml") {
16291
- legacy.push({ path: f, expected: path13.join(dir, ".interface.yaml") });
16484
+ legacy.push({ path: f, expected: path15.join(dir, ".interface.yaml") });
16292
16485
  } else if (base === "implementation.yaml") {
16293
- legacy.push({ path: f, expected: path13.join(dir, ".implementation.yaml") });
16486
+ legacy.push({ path: f, expected: path15.join(dir, ".implementation.yaml") });
16294
16487
  }
16295
16488
  }
16296
16489
  return legacy;
@@ -16357,6 +16550,35 @@ var init_specs2 = __esm({
16357
16550
  }
16358
16551
  return refs;
16359
16552
  };
16553
+ const normalizeIdentity = (k) => String(k ?? "").toLowerCase().replace(/[_\-\s]/g, "");
16554
+ const assertDeltaMarkers = (item, label) => {
16555
+ if (!item || typeof item !== "object") return;
16556
+ if ("remove" in item && typeof item.remove !== "boolean") {
16557
+ throw new Error(
16558
+ `Refusing to update ${label}: "remove" must be the boolean true, got ${JSON.stringify(item.remove)}. A non-boolean is ignored, which would leave the element in place while reporting success.`
16559
+ );
16560
+ }
16561
+ if ("action" in item && item.action !== "add" && item.action !== "delete") {
16562
+ throw new Error(
16563
+ `Refusing to update ${label}: unknown action ${JSON.stringify(item.action)} \u2014 expected "add" or "delete". An unknown verb is ignored, which would leave the element in place while reporting success.`
16564
+ );
16565
+ }
16566
+ };
16567
+ const assertUnmatchedIsAnAddition = (deltaItem, key, existingKeys, label) => {
16568
+ if (deltaItem?.remove === true || deltaItem?.action === "delete") {
16569
+ throw new Error(
16570
+ `Refusing to delete ${label} "${String(key)}": nothing with that identity exists. ` + (existingKeys.length ? `Present: ${existingKeys.map(String).join(", ")}.` : "The collection is empty.")
16571
+ );
16572
+ }
16573
+ const near = existingKeys.find(
16574
+ (k) => String(k) !== String(key) && normalizeIdentity(k) === normalizeIdentity(key)
16575
+ );
16576
+ if (near !== void 0) {
16577
+ throw new Error(
16578
+ `Refusing to add ${label} "${String(key)}": "${String(near)}" already exists and differs only in case or separators. Use the existing identity to edit it, or pick a name that is not a near-duplicate.`
16579
+ );
16580
+ }
16581
+ };
16360
16582
  const mergeNarrative = (existingSteps, deltaSteps) => {
16361
16583
  let steps = [...existingSteps];
16362
16584
  const sortedDeltas = [...deltaSteps].sort((a, b) => a.stepNumber - b.stepNumber);
@@ -16425,6 +16647,7 @@ var init_specs2 = __esm({
16425
16647
  const mergeMethods = (existingMethods, deltaMethods) => {
16426
16648
  const merged = [...existingMethods];
16427
16649
  for (const deltaMethod of deltaMethods) {
16650
+ assertDeltaMarkers(deltaMethod, `method "${deltaMethod?.name}"`);
16428
16651
  const idx = merged.findIndex((m) => m.name === deltaMethod.name);
16429
16652
  if (idx !== -1) {
16430
16653
  if (deltaMethod.remove === true || deltaMethod.action === "delete") {
@@ -16444,9 +16667,8 @@ var init_specs2 = __esm({
16444
16667
  };
16445
16668
  }
16446
16669
  } else {
16447
- if (deltaMethod.remove !== true && deltaMethod.action !== "delete") {
16448
- merged.push(deltaMethod);
16449
- }
16670
+ assertUnmatchedIsAnAddition(deltaMethod, deltaMethod.name, merged.map((m) => m.name), "method");
16671
+ merged.push(deltaMethod);
16450
16672
  }
16451
16673
  }
16452
16674
  return merged;
@@ -16454,6 +16676,7 @@ var init_specs2 = __esm({
16454
16676
  const mergeNamedArray = (existing, delta2) => {
16455
16677
  const merged = [...existing];
16456
16678
  for (const deltaItem of delta2) {
16679
+ assertDeltaMarkers(deltaItem, `entry "${deltaItem?.name}"`);
16457
16680
  const idx = merged.findIndex((item) => item.name === deltaItem.name);
16458
16681
  if (idx !== -1) {
16459
16682
  if (deltaItem.remove === true || deltaItem.action === "delete") {
@@ -16466,9 +16689,8 @@ var init_specs2 = __esm({
16466
16689
  };
16467
16690
  }
16468
16691
  } else {
16469
- if (deltaItem.remove !== true && deltaItem.action !== "delete") {
16470
- merged.push(deltaItem);
16471
- }
16692
+ assertUnmatchedIsAnAddition(deltaItem, deltaItem.name, merged.map((i) => i.name), "entry");
16693
+ merged.push(deltaItem);
16472
16694
  }
16473
16695
  }
16474
16696
  return merged;
@@ -16476,6 +16698,7 @@ var init_specs2 = __esm({
16476
16698
  const mergeKeyedArray = (existing, delta2, keyOf) => {
16477
16699
  const merged = [...existing];
16478
16700
  for (const deltaItem of delta2) {
16701
+ assertDeltaMarkers(deltaItem, `entry "${keyOf(deltaItem)}"`);
16479
16702
  const idx = merged.findIndex((item) => keyOf(item) === keyOf(deltaItem));
16480
16703
  if (idx !== -1) {
16481
16704
  if (deltaItem.remove === true || deltaItem.action === "delete") {
@@ -16483,7 +16706,8 @@ var init_specs2 = __esm({
16483
16706
  } else {
16484
16707
  merged[idx] = { ...merged[idx], ...deltaItem };
16485
16708
  }
16486
- } else if (deltaItem.remove !== true && deltaItem.action !== "delete") {
16709
+ } else {
16710
+ assertUnmatchedIsAnAddition(deltaItem, keyOf(deltaItem), merged.map(keyOf), "entry");
16487
16711
  merged.push(deltaItem);
16488
16712
  }
16489
16713
  }
@@ -16492,6 +16716,8 @@ var init_specs2 = __esm({
16492
16716
  const mergePublicInterfaces = (existing, delta2) => {
16493
16717
  const merged = [...existing];
16494
16718
  for (const deltaItem of delta2) {
16719
+ const piKey = (i) => `${i?.component}.${i?.interface}`;
16720
+ assertDeltaMarkers(deltaItem, `publicInterface "${piKey(deltaItem)}"`);
16495
16721
  const idx = merged.findIndex((item) => item.component === deltaItem.component && item.interface === deltaItem.interface);
16496
16722
  if (idx !== -1) {
16497
16723
  if (deltaItem.remove === true || deltaItem.action === "delete") {
@@ -16503,9 +16729,8 @@ var init_specs2 = __esm({
16503
16729
  };
16504
16730
  }
16505
16731
  } else {
16506
- if (deltaItem.remove !== true && deltaItem.action !== "delete") {
16507
- merged.push(deltaItem);
16508
- }
16732
+ assertUnmatchedIsAnAddition(deltaItem, piKey(deltaItem), merged.map(piKey), "publicInterface");
16733
+ merged.push(deltaItem);
16509
16734
  }
16510
16735
  }
16511
16736
  return merged;
@@ -16546,11 +16771,22 @@ var init_specs2 = __esm({
16546
16771
  for (const deltaItem of delta2) {
16547
16772
  const key = identityKeyOf(field, deltaItem);
16548
16773
  const idx = key === null ? -1 : merged.findIndex((item) => identityKeyOf(field, item) === key);
16774
+ assertDeltaMarkers(deltaItem, `${field} entry "${String(key)}"`);
16549
16775
  const isDelete = deltaItem?.remove === true || deltaItem?.action === "delete";
16550
16776
  if (idx !== -1) {
16551
16777
  if (isDelete) merged.splice(idx, 1);
16552
16778
  else merged[idx] = { ...merged[idx], ...deltaItem };
16553
- } else if (!isDelete) {
16779
+ } else {
16780
+ if (key !== null) {
16781
+ assertUnmatchedIsAnAddition(
16782
+ deltaItem,
16783
+ key,
16784
+ merged.map((i) => identityKeyOf(field, i)).filter((k) => k !== null),
16785
+ field
16786
+ );
16787
+ } else if (isDelete) {
16788
+ throw new Error(`Refusing to delete a ${field} entry with no resolvable identity.`);
16789
+ }
16554
16790
  merged.push(deltaItem);
16555
16791
  }
16556
16792
  }
@@ -16694,8 +16930,8 @@ __export(agent_resolver_exports, {
16694
16930
  resolveAgentTopology: () => resolveAgentTopology
16695
16931
  });
16696
16932
  function listFilesRecursiveSafe(dirPath, ext) {
16697
- if (!fs10.existsSync(dirPath)) return [];
16698
- const nameLower = path14.basename(dirPath).toLowerCase();
16933
+ if (!fs11.existsSync(dirPath)) return [];
16934
+ const nameLower = path16.basename(dirPath).toLowerCase();
16699
16935
  const IGNORED_DIRS = /* @__PURE__ */ new Set([
16700
16936
  "node_modules",
16701
16937
  "target",
@@ -16710,10 +16946,10 @@ function listFilesRecursiveSafe(dirPath, ext) {
16710
16946
  ".vscode"
16711
16947
  ]);
16712
16948
  if (IGNORED_DIRS.has(nameLower)) return [];
16713
- const entries = fs10.readdirSync(dirPath, { withFileTypes: true });
16949
+ const entries = fs11.readdirSync(dirPath, { withFileTypes: true });
16714
16950
  const files = [];
16715
16951
  for (const entry of entries) {
16716
- const fullPath = path14.join(dirPath, entry.name);
16952
+ const fullPath = path16.join(dirPath, entry.name);
16717
16953
  if (entry.isDirectory()) {
16718
16954
  files.push(...listFilesRecursiveSafe(fullPath, ext));
16719
16955
  } else if (entry.isFile() && entry.name.endsWith(ext)) {
@@ -16726,8 +16962,8 @@ function getProjectFiles(projectDir) {
16726
16962
  let files = projectFilesCache.get(projectDir);
16727
16963
  if (!files) {
16728
16964
  files = [];
16729
- const srcDir = path14.join(projectDir, "src");
16730
- const legacySrcDir = path14.join(projectDir, "legacy-src");
16965
+ const srcDir = path16.join(projectDir, "src");
16966
+ const legacySrcDir = path16.join(projectDir, "legacy-src");
16731
16967
  let searchDir = projectDir;
16732
16968
  if (pathExists(srcDir)) {
16733
16969
  searchDir = srcDir;
@@ -16742,7 +16978,7 @@ function getProjectFiles(projectDir) {
16742
16978
  files.push(...listFilesRecursiveSafe(searchDir, ext));
16743
16979
  }
16744
16980
  const rootDir = getProjectRoot();
16745
- files = files.map((f) => path14.relative(rootDir, f).replace(/\\/g, "/"));
16981
+ files = files.map((f) => path16.relative(rootDir, f).replace(/\\/g, "/"));
16746
16982
  projectFilesCache.set(projectDir, files);
16747
16983
  }
16748
16984
  return files;
@@ -16767,8 +17003,8 @@ function inferSourcePathForComponent(comp, subsystems) {
16767
17003
  let bestFile = null;
16768
17004
  let bestScore = -1;
16769
17005
  for (const f of files) {
16770
- const ext = path14.extname(f);
16771
- const base = path14.basename(f, ext).toLowerCase();
17006
+ const ext = path16.extname(f);
17007
+ const base = path16.basename(f, ext).toLowerCase();
16772
17008
  if (candidates.has(base)) {
16773
17009
  let score = 0;
16774
17010
  const normalizedPath = f.toLowerCase();
@@ -16864,7 +17100,7 @@ function resolveAgentTopology() {
16864
17100
  });
16865
17101
  for (const sub of subsystems) {
16866
17102
  if (sub.projectPath) {
16867
- const mountSpecPath = path14.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
17103
+ const mountSpecPath = path16.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/");
16868
17104
  agents.push({
16869
17105
  id: `${sub.id}-owner`,
16870
17106
  name: `${sub.name} (chained subproject)`,
@@ -16886,9 +17122,9 @@ function resolveAgentTopology() {
16886
17122
  }
16887
17123
  const subComponents = components.filter((c) => c.subsystem === sub.id);
16888
17124
  const ownedPaths = [];
16889
- ownedPaths.push(path14.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
17125
+ ownedPaths.push(path16.relative(getProjectRoot(), getSubsystemPath(sub.id)).replace(/\\/g, "/"));
16890
17126
  for (const c of subComponents) {
16891
- 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, "/"));
16892
17128
  }
16893
17129
  if (!config.rules.generateComponentImplementers) {
16894
17130
  for (const comp of subComponents) {
@@ -16961,10 +17197,10 @@ function resolveAgentTopology() {
16961
17197
  }
16962
17198
  const dependencies = comp.dependsOn.map((depId) => `${depId}-implementer`);
16963
17199
  const readPaths = [
16964
- path14.relative(getProjectRoot(), AI_PATHS.specsSystem()).replace(/\\/g, "/"),
16965
- path14.relative(getProjectRoot(), getComponentPath(comp.id, comp.subsystem)).replace(/\\/g, "/"),
16966
- ...compInterfaces.map((i) => path14.relative(getProjectRoot(), getInterfacePath(i.id, comp.id)).replace(/\\/g, "/")),
16967
- ...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, "/"))
16968
17204
  ];
16969
17205
  agents.push({
16970
17206
  id: `${comp.id}-implementer`,
@@ -17047,12 +17283,12 @@ ${guidance.trim()}
17047
17283
  variantGuidance: record.variantGuidance || void 0
17048
17284
  };
17049
17285
  }
17050
- var path14, fs10, projectFilesCache, UnknownAgentError;
17286
+ var path16, fs11, projectFilesCache, UnknownAgentError;
17051
17287
  var init_agent_resolver = __esm({
17052
17288
  "src/core/agent_resolver.ts"() {
17053
17289
  "use strict";
17054
- path14 = __toESM(require("path"));
17055
- fs10 = __toESM(require("fs"));
17290
+ path16 = __toESM(require("path"));
17291
+ fs11 = __toESM(require("fs"));
17056
17292
  init_loader();
17057
17293
  init_fs();
17058
17294
  init_errors();
@@ -17083,12 +17319,12 @@ __export(loader_exports, {
17083
17319
  saveTopologyConfig: () => saveTopologyConfig
17084
17320
  });
17085
17321
  function aiPathsAt(rootDir) {
17086
- const resolvedRoot = path15.resolve(rootDir);
17322
+ const resolvedRoot = path17.resolve(rootDir);
17087
17323
  const aiDirAt = (...segments) => {
17088
- const waiPath = path15.join(resolvedRoot, ".wai");
17089
- const waironPath = path15.join(resolvedRoot, ".wairon");
17090
- const base = !fs11.existsSync(waiPath) && fs11.existsSync(waironPath) ? waironPath : waiPath;
17091
- 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);
17092
17328
  };
17093
17329
  const specsDir = () => {
17094
17330
  try {
@@ -17096,7 +17332,7 @@ function aiPathsAt(rootDir) {
17096
17332
  if (pathExists(projConfig)) {
17097
17333
  const raw = readYamlFile(projConfig);
17098
17334
  if (raw && raw.paths && raw.paths.specsDir) {
17099
- return path15.resolve(resolvedRoot, raw.paths.specsDir);
17335
+ return path17.resolve(resolvedRoot, raw.paths.specsDir);
17100
17336
  }
17101
17337
  }
17102
17338
  } catch {
@@ -17117,12 +17353,12 @@ function aiPathsAt(rootDir) {
17117
17353
  contextDomainsMd: () => aiDirAt("context", "domains.md"),
17118
17354
  contextWaironGuideMd: () => aiDirAt("context", "wairon-guide.md"),
17119
17355
  specsDir,
17120
- specsSystem: () => path15.join(specsDir(), ".index.yaml"),
17121
- specsSubsystemsDir: () => path15.join(specsDir(), "subsystems"),
17122
- specsComponentsDir: () => path15.join(specsDir(), "components"),
17123
- specsInterfacesDir: () => path15.join(specsDir(), "interfaces"),
17124
- specsImplementationsDir: () => path15.join(specsDir(), "implementations"),
17125
- 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")
17126
17362
  };
17127
17363
  }
17128
17364
  function isProjectInitialized() {
@@ -17165,12 +17401,12 @@ function loadTopologyConfig() {
17165
17401
  function saveTopologyConfig(config) {
17166
17402
  writeYamlFile(AI_PATHS.topologyConfig(), config);
17167
17403
  }
17168
- var fs11, path15, AI_PATHS;
17404
+ var fs12, path17, AI_PATHS;
17169
17405
  var init_loader = __esm({
17170
17406
  "src/config/loader.ts"() {
17171
17407
  "use strict";
17172
- fs11 = __toESM(require("fs"));
17173
- path15 = __toESM(require("path"));
17408
+ fs12 = __toESM(require("fs"));
17409
+ path17 = __toESM(require("path"));
17174
17410
  init_fs();
17175
17411
  init_yaml();
17176
17412
  init_errors();
@@ -17210,7 +17446,7 @@ __export(domains_exports, {
17210
17446
  resolveDomains: () => resolveDomains
17211
17447
  });
17212
17448
  function rel(p) {
17213
- return path17.relative(process.cwd(), p).replace(/\\/g, "/");
17449
+ return path19.relative(process.cwd(), p).replace(/\\/g, "/");
17214
17450
  }
17215
17451
  function deriveSubsystemDomains() {
17216
17452
  const subsystems = loadSubsystemSpecs();
@@ -17260,11 +17496,11 @@ function removeFreeStandingDomain(id) {
17260
17496
  config.domains.splice(idx, 1);
17261
17497
  saveTopologyConfig(config);
17262
17498
  }
17263
- var path17;
17499
+ var path19;
17264
17500
  var init_domains = __esm({
17265
17501
  "src/core/domains.ts"() {
17266
17502
  "use strict";
17267
- path17 = __toESM(require("path"));
17503
+ path19 = __toESM(require("path"));
17268
17504
  init_loader();
17269
17505
  init_specs2();
17270
17506
  init_errors();
@@ -17595,6 +17831,7 @@ __export(src_exports, {
17595
17831
  skillExtendErrors: () => skillExtendErrors,
17596
17832
  skillsDirForTarget: () => skillsDirForTarget,
17597
17833
  snapshotSpecFiles: () => snapshotSpecFiles,
17834
+ specPathsInScope: () => specPathsInScope,
17598
17835
  splitNamespace: () => splitNamespace,
17599
17836
  stateIdEquals: () => stateIdEquals,
17600
17837
  stateIdString: () => stateIdString,
@@ -17625,8 +17862,8 @@ init_defaults();
17625
17862
  init_loader();
17626
17863
 
17627
17864
  // src/core/detection.ts
17628
- var fs12 = __toESM(require("fs"));
17629
- var path16 = __toESM(require("path"));
17865
+ var fs13 = __toESM(require("fs"));
17866
+ var path18 = __toESM(require("path"));
17630
17867
  init_defaults();
17631
17868
  var PACKAGE_MARKERS = [
17632
17869
  "package.json",
@@ -17678,7 +17915,7 @@ function deduplicateIds(candidates, existingIds = /* @__PURE__ */ new Set()) {
17678
17915
  });
17679
17916
  }
17680
17917
  function parseGitmodules(filePath) {
17681
- const content = fs12.readFileSync(filePath, "utf-8");
17918
+ const content = fs13.readFileSync(filePath, "utf-8");
17682
17919
  const entries = [];
17683
17920
  let current2 = {};
17684
17921
  for (const line of content.split("\n")) {
@@ -17700,8 +17937,8 @@ function parseGitmodules(filePath) {
17700
17937
  return entries;
17701
17938
  }
17702
17939
  function detectGitSubmodules(projectRoot) {
17703
- const gitmodulesPath = path16.join(projectRoot, ".gitmodules");
17704
- if (!fs12.existsSync(gitmodulesPath)) return [];
17940
+ const gitmodulesPath = path18.join(projectRoot, ".gitmodules");
17941
+ if (!fs13.existsSync(gitmodulesPath)) return [];
17705
17942
  return parseGitmodules(gitmodulesPath).map((entry) => ({
17706
17943
  suggestedId: pathToId(entry.path),
17707
17944
  suggestedName: pathToName(entry.path),
@@ -17719,18 +17956,18 @@ function walkForGit(projectRoot, currentDir, depth, results) {
17719
17956
  if (depth > MAX_SCAN_DEPTH) return;
17720
17957
  let entries;
17721
17958
  try {
17722
- entries = fs12.readdirSync(currentDir, { withFileTypes: true });
17959
+ entries = fs13.readdirSync(currentDir, { withFileTypes: true });
17723
17960
  } catch {
17724
17961
  return;
17725
17962
  }
17726
17963
  for (const entry of entries) {
17727
17964
  if (!entry.isDirectory()) continue;
17728
17965
  if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
17729
- const fullPath = path16.join(currentDir, entry.name);
17730
- const relPath = normalizePath3(path16.relative(projectRoot, fullPath));
17966
+ const fullPath = path18.join(currentDir, entry.name);
17967
+ const relPath = normalizePath3(path18.relative(projectRoot, fullPath));
17731
17968
  if (relPath === "" || relPath === ".") continue;
17732
- const gitPath = path16.join(fullPath, ".git");
17733
- if (fs12.existsSync(gitPath)) {
17969
+ const gitPath = path18.join(fullPath, ".git");
17970
+ if (fs13.existsSync(gitPath)) {
17734
17971
  results.push({
17735
17972
  suggestedId: pathToId(relPath),
17736
17973
  suggestedName: pathToName(relPath),
@@ -17752,17 +17989,17 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
17752
17989
  if (depth > MAX_SCAN_DEPTH) return;
17753
17990
  let entries;
17754
17991
  try {
17755
- entries = fs12.readdirSync(currentDir, { withFileTypes: true });
17992
+ entries = fs13.readdirSync(currentDir, { withFileTypes: true });
17756
17993
  } catch {
17757
17994
  return;
17758
17995
  }
17759
17996
  for (const entry of entries) {
17760
17997
  if (!entry.isDirectory()) continue;
17761
17998
  if (SCAN_EXCLUDE_DIRS.has(entry.name)) continue;
17762
- const fullPath = path16.join(currentDir, entry.name);
17763
- const relPath = normalizePath3(path16.relative(projectRoot, fullPath));
17999
+ const fullPath = path18.join(currentDir, entry.name);
18000
+ const relPath = normalizePath3(path18.relative(projectRoot, fullPath));
17764
18001
  if (relPath === "" || relPath === ".") continue;
17765
- 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)));
17766
18003
  if (hasMarker) {
17767
18004
  results.push({
17768
18005
  suggestedId: pathToId(relPath),
@@ -17776,8 +18013,8 @@ function walkForPackages(projectRoot, currentDir, depth, results) {
17776
18013
  }
17777
18014
  }
17778
18015
  function pathToId(relPath) {
17779
- const basename9 = path16.basename(relPath);
17780
- 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, "");
17781
18018
  }
17782
18019
  function pathToName(relPath) {
17783
18020
  const id = pathToId(relPath);
@@ -17797,8 +18034,8 @@ init_rules();
17797
18034
  init_specs2();
17798
18035
 
17799
18036
  // src/core/provision.ts
17800
- var fs13 = __toESM(require("fs"));
17801
- var path18 = __toESM(require("path"));
18037
+ var fs14 = __toESM(require("fs"));
18038
+ var path20 = __toESM(require("path"));
17802
18039
  init_specs2();
17803
18040
  init_loader();
17804
18041
  init_fs();
@@ -17846,7 +18083,7 @@ function provisionProject(name) {
17846
18083
  function ensureProjectInitialized(fallbackName) {
17847
18084
  const now = (/* @__PURE__ */ new Date()).toISOString();
17848
18085
  const paths = aiPathsAt(getProjectRoot());
17849
- const hasSystem = fs13.existsSync(paths.specsSystem());
18086
+ const hasSystem = fs14.existsSync(paths.specsSystem());
17850
18087
  let name = fallbackName;
17851
18088
  if (hasSystem) {
17852
18089
  const existing = loadSystemSpec();
@@ -17854,7 +18091,7 @@ function ensureProjectInitialized(fallbackName) {
17854
18091
  }
17855
18092
  let wroteConfig = false;
17856
18093
  let wroteSystem = false;
17857
- if (!fs13.existsSync(paths.projectConfig())) {
18094
+ if (!fs14.existsSync(paths.projectConfig())) {
17858
18095
  saveProjectConfig(defaultProjectConfig(name, now));
17859
18096
  wroteConfig = true;
17860
18097
  }
@@ -17883,11 +18120,11 @@ function promoteAllComplete() {
17883
18120
  function walkChainedSubprojects(projectRoot, onChild) {
17884
18121
  const visited = /* @__PURE__ */ new Set();
17885
18122
  const walk = (dir) => {
17886
- const resolved = path18.resolve(dir);
18123
+ const resolved = path20.resolve(dir);
17887
18124
  if (visited.has(resolved)) return;
17888
18125
  visited.add(resolved);
17889
18126
  const specsDir = aiPathsAt(dir).specsDir();
17890
- if (!fs13.existsSync(specsDir)) return;
18127
+ if (!fs14.existsSync(specsDir)) return;
17891
18128
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
17892
18129
  let raw;
17893
18130
  try {
@@ -17905,7 +18142,7 @@ function walkChainedSubprojects(projectRoot, onChild) {
17905
18142
  continue;
17906
18143
  }
17907
18144
  const id = raw.id;
17908
- onChild(childDir, typeof id === "string" ? id : path18.basename(childDir));
18145
+ onChild(childDir, typeof id === "string" ? id : path20.basename(childDir));
17909
18146
  walk(childDir);
17910
18147
  }
17911
18148
  };
@@ -17914,7 +18151,7 @@ function walkChainedSubprojects(projectRoot, onChild) {
17914
18151
  function listDirectChainedSubprojects(projectRoot) {
17915
18152
  const out = [];
17916
18153
  const specsDir = aiPathsAt(projectRoot).specsDir();
17917
- if (!fs13.existsSync(specsDir)) return out;
18154
+ if (!fs14.existsSync(specsDir)) return out;
17918
18155
  for (const file of listFilesRecursive(specsDir, ".yaml")) {
17919
18156
  let raw;
17920
18157
  try {
@@ -17932,12 +18169,12 @@ function listDirectChainedSubprojects(projectRoot) {
17932
18169
  continue;
17933
18170
  }
17934
18171
  const id = raw.id;
17935
- out.push({ dir, subsystemId: typeof id === "string" ? id : path18.basename(dir) });
18172
+ out.push({ dir, subsystemId: typeof id === "string" ? id : path20.basename(dir) });
17936
18173
  }
17937
18174
  return out;
17938
18175
  }
17939
18176
  function childHasSpecsButNoConfig(childDir) {
17940
- return fs13.existsSync(aiPathsAt(childDir).specsDir()) && !fs13.existsSync(aiPathsAt(childDir).projectConfig());
18177
+ return fs14.existsSync(aiPathsAt(childDir).specsDir()) && !fs14.existsSync(aiPathsAt(childDir).projectConfig());
17941
18178
  }
17942
18179
  function findChainingSubprojectsMissingConfig(projectRoot) {
17943
18180
  const missing = [];
@@ -17986,14 +18223,14 @@ function moveSubsystemProject(subsystemId, newProjectPath) {
17986
18223
  const oldDir = assertContainedProjectPath(root, sub.projectPath);
17987
18224
  const newDir = assertContainedProjectPath(root, nextPath);
17988
18225
  if (oldDir !== newDir) {
17989
- if (!fs13.existsSync(oldDir)) {
18226
+ if (!fs14.existsSync(oldDir)) {
17990
18227
  throw new WaironError(`Subproject directory not found at its current path: ${oldDir}`);
17991
18228
  }
17992
- if (fs13.existsSync(newDir)) {
18229
+ if (fs14.existsSync(newDir)) {
17993
18230
  throw new WaironError(`Target directory already exists: ${newDir}`);
17994
18231
  }
17995
- ensureDir(path18.dirname(newDir));
17996
- fs13.renameSync(oldDir, newDir);
18232
+ ensureDir(path20.dirname(newDir));
18233
+ fs14.renameSync(oldDir, newDir);
17997
18234
  }
17998
18235
  saveSubsystemSpec({ ...sub, projectPath: nextPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
17999
18236
  invalidateSpecCache();
@@ -18002,9 +18239,9 @@ function toPosixPath(p) {
18002
18239
  return p.replace(/\\/g, "/");
18003
18240
  }
18004
18241
  function isWithinDir(dir, file) {
18005
- const d = path18.resolve(dir);
18006
- const f = path18.resolve(file);
18007
- 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);
18008
18245
  }
18009
18246
  function externalizeSubsystem(subsystemId, projectPath) {
18010
18247
  if (subsystemId.includes("::")) {
@@ -18016,14 +18253,14 @@ function externalizeSubsystem(subsystemId, projectPath) {
18016
18253
  }
18017
18254
  const parentRoot = getProjectRoot();
18018
18255
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
18019
- const fooDir = path18.join(parentSpecsDir, subsystemId);
18020
- if (!fs13.existsSync(fooDir)) {
18256
+ const fooDir = path20.join(parentSpecsDir, subsystemId);
18257
+ if (!fs14.existsSync(fooDir)) {
18021
18258
  throw new WaironError(`subsystem specs directory not found: ${fooDir}`);
18022
18259
  }
18023
18260
  const relPath = toPosixPath(projectPath);
18024
18261
  const childDir = assertContainedProjectPath(parentRoot, relPath);
18025
- const childFooDir = path18.join(childDir, ".wai", "specs", subsystemId);
18026
- if (fs13.existsSync(childFooDir)) {
18262
+ const childFooDir = path20.join(childDir, ".wai", "specs", subsystemId);
18263
+ if (fs14.existsSync(childFooDir)) {
18027
18264
  throw new WaironError(`target already contains a "${subsystemId}" subsystem: ${childFooDir}`);
18028
18265
  }
18029
18266
  const renameMap = buildRenameMap(
@@ -18033,17 +18270,17 @@ function externalizeSubsystem(subsystemId, projectPath) {
18033
18270
  );
18034
18271
  const childSystemName = foo.name || subsystemId;
18035
18272
  runWithProjectRoot(childDir, () => {
18036
- ensureDir(path18.join(childDir, ".wai", "specs"));
18273
+ ensureDir(path20.join(childDir, ".wai", "specs"));
18037
18274
  provisionProject(childSystemName);
18038
18275
  });
18039
- ensureDir(path18.dirname(childFooDir));
18040
- fs13.renameSync(fooDir, childFooDir);
18041
- 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) => {
18042
18279
  s.parentSystem = childSystemName;
18043
18280
  delete s.projectPath;
18044
18281
  });
18045
18282
  ensureDir(fooDir);
18046
- writeYamlFile(path18.join(fooDir, ".index.yaml"), {
18283
+ writeYamlFile(path20.join(fooDir, ".index.yaml"), {
18047
18284
  id: subsystemId,
18048
18285
  name: foo.name,
18049
18286
  description: foo.description,
@@ -18069,9 +18306,9 @@ function internalizeSubsystem(subsystemId) {
18069
18306
  const parentRoot = getProjectRoot();
18070
18307
  const parentSpecsDir = aiPathsAt(parentRoot).specsDir();
18071
18308
  const childDir = assertContainedProjectPath(parentRoot, foo.projectPath);
18072
- const childWai = path18.join(childDir, ".wai");
18073
- const childFooDir = path18.join(childDir, ".wai", "specs", subsystemId);
18074
- 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)) {
18075
18312
  throw new WaironError(`external subproject missing subsystem "${subsystemId}": ${childFooDir}`);
18076
18313
  }
18077
18314
  const childOwnSubs = runWithProjectRoot(childDir, () => loadSubsystemSpecs()).filter((s) => !s.id.includes("::"));
@@ -18084,15 +18321,15 @@ function internalizeSubsystem(subsystemId) {
18084
18321
  false
18085
18322
  );
18086
18323
  const parentSystemName = loadSystemSpec()?.name ?? foo.parentSystem;
18087
- const fooDir = path18.join(parentSpecsDir, subsystemId);
18088
- fs13.rmSync(fooDir, { recursive: true, force: true });
18089
- ensureDir(path18.dirname(fooDir));
18090
- fs13.renameSync(childFooDir, fooDir);
18091
- 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) => {
18092
18329
  s.parentSystem = parentSystemName;
18093
18330
  delete s.projectPath;
18094
18331
  });
18095
- fs13.rmSync(childWai, { recursive: true, force: true });
18332
+ fs14.rmSync(childWai, { recursive: true, force: true });
18096
18333
  rewriteRefsInDir(parentSpecsDir, renameMap, fooDir);
18097
18334
  invalidateSpecCache();
18098
18335
  }
@@ -18189,7 +18426,7 @@ function rewriteRefsInDir(specsDir, renameMap, excludeDir) {
18189
18426
  }
18190
18427
  }
18191
18428
  function patchSubsystemIndex(indexPath, mutate) {
18192
- if (!fs13.existsSync(indexPath)) return;
18429
+ if (!fs14.existsSync(indexPath)) return;
18193
18430
  const raw = readYamlFile(indexPath);
18194
18431
  mutate(raw);
18195
18432
  raw.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -18203,8 +18440,8 @@ init_statehash();
18203
18440
  init_agent_resolver();
18204
18441
 
18205
18442
  // src/core/skills.ts
18206
- var path19 = __toESM(require("path"));
18207
- var fs14 = __toESM(require("fs"));
18443
+ var path21 = __toESM(require("path"));
18444
+ var fs15 = __toESM(require("fs"));
18208
18445
  init_fs();
18209
18446
  init_defaults();
18210
18447
  init_extensions();
@@ -18338,16 +18575,16 @@ function packNamespace(pack) {
18338
18575
  return pack.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
18339
18576
  }
18340
18577
  function extensionsFor(builtin, packSkills) {
18341
- return packSkills.filter((s) => s.extends === builtin && fs14.existsSync(s.sourcePath));
18578
+ return packSkills.filter((s) => s.extends === builtin && fs15.existsSync(s.sourcePath));
18342
18579
  }
18343
18580
  function composeBuiltinSkill(name, packSkills) {
18344
18581
  const srcPath = skillTemplatePath(name);
18345
- const base = fs14.existsSync(srcPath) ? fs14.readFileSync(srcPath, "utf-8") : "";
18582
+ const base = fs15.existsSync(srcPath) ? fs15.readFileSync(srcPath, "utf-8") : "";
18346
18583
  const sections = extensionsFor(name, packSkills);
18347
18584
  if (sections.length === 0) return base;
18348
18585
  const parts = [base.trimEnd()];
18349
18586
  for (const section of sections) {
18350
- 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?/, "");
18351
18588
  parts.push(`## Platform: ${section.pack}`, body.trim());
18352
18589
  }
18353
18590
  return `${parts.join("\n\n")}
@@ -18363,16 +18600,16 @@ function readFrontmatter(raw, fallbackName) {
18363
18600
  return { name: field("name") || fallbackName, description: field("description") };
18364
18601
  }
18365
18602
  function builtinSkillsDir() {
18366
- return path19.resolve(__dirname, "..", "templates", "skills");
18603
+ return path21.resolve(__dirname, "..", "templates", "skills");
18367
18604
  }
18368
18605
  function skillTemplatePath(name) {
18369
- return path19.join(builtinSkillsDir(), `${name}.md`);
18606
+ return path21.join(builtinSkillsDir(), `${name}.md`);
18370
18607
  }
18371
18608
  function skillDestPath(type, destDir, name) {
18372
18609
  if (type === "claude" || type === "codex" || type === "gemini" || type === "agy") {
18373
- return path19.join(destDir, name, "SKILL.md");
18610
+ return path21.join(destDir, name, "SKILL.md");
18374
18611
  }
18375
- return path19.join(destDir, `${name}.md`);
18612
+ return path21.join(destDir, `${name}.md`);
18376
18613
  }
18377
18614
  function skillsDirForTarget(type) {
18378
18615
  switch (type) {
@@ -18407,22 +18644,22 @@ function exportSddSkills(targetTypes) {
18407
18644
  ensureDir(destDir);
18408
18645
  destinations.push(destDir);
18409
18646
  for (const name of SKILL_NAMES) {
18410
- if (!fs14.existsSync(skillTemplatePath(name))) continue;
18647
+ if (!fs15.existsSync(skillTemplatePath(name))) continue;
18411
18648
  const content = composeBuiltinSkill(name, packSkills.filter((s) => s.targets.includes(type)));
18412
18649
  const destPath = skillDestPath(type, destDir, name);
18413
- ensureDir(path19.dirname(destPath));
18414
- fs14.writeFileSync(destPath, content, "utf-8");
18650
+ ensureDir(path21.dirname(destPath));
18651
+ fs15.writeFileSync(destPath, content, "utf-8");
18415
18652
  fileCount++;
18416
18653
  }
18417
18654
  for (const skill of packSkills) {
18418
18655
  if (skill.extends !== void 0) continue;
18419
18656
  if (!skill.targets.includes(type)) continue;
18420
- if (!fs14.existsSync(skill.sourcePath)) continue;
18657
+ if (!fs15.existsSync(skill.sourcePath)) continue;
18421
18658
  const id = packSkillId(skill);
18422
- const content = fs14.readFileSync(skill.sourcePath, "utf-8");
18659
+ const content = fs15.readFileSync(skill.sourcePath, "utf-8");
18423
18660
  const destPath = skillDestPath(type, destDir, id);
18424
- ensureDir(path19.dirname(destPath));
18425
- fs14.writeFileSync(destPath, content, "utf-8");
18661
+ ensureDir(path21.dirname(destPath));
18662
+ fs15.writeFileSync(destPath, content, "utf-8");
18426
18663
  fileCount++;
18427
18664
  }
18428
18665
  }
@@ -18435,12 +18672,12 @@ function checkSkillFreshness(type) {
18435
18672
  const packSkills = loadProjectExtensions2().skills.filter((s) => s.targets.includes(type));
18436
18673
  for (const name of SKILL_NAMES) {
18437
18674
  const destPath = skillDestPath(type, dir, name);
18438
- if (!fs14.existsSync(destPath)) {
18675
+ if (!fs15.existsSync(destPath)) {
18439
18676
  result.missing.push(name);
18440
18677
  continue;
18441
18678
  }
18442
18679
  const want = composeBuiltinSkill(name, packSkills);
18443
- const have = fs14.readFileSync(destPath, "utf-8");
18680
+ const have = fs15.readFileSync(destPath, "utf-8");
18444
18681
  if (have === want) result.ok.push(name);
18445
18682
  else result.stale.push(name);
18446
18683
  }
@@ -18460,7 +18697,7 @@ var SkillResourceNotFoundError = class extends Error {
18460
18697
  }
18461
18698
  };
18462
18699
  function readSkillFrontmatter(name) {
18463
- return readFrontmatter(fs14.readFileSync(skillTemplatePath(name), "utf-8"), name);
18700
+ return readFrontmatter(fs15.readFileSync(skillTemplatePath(name), "utf-8"), name);
18464
18701
  }
18465
18702
  function listSkillResources() {
18466
18703
  const builtin = RESOURCE_SKILL_IDS.map((id) => {
@@ -18474,9 +18711,9 @@ function listSkillResources() {
18474
18711
  defaultForHostedMcp: true
18475
18712
  };
18476
18713
  });
18477
- 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) => {
18478
18715
  const id = packSkillId(skill);
18479
- const fm = readFrontmatter(fs14.readFileSync(skill.sourcePath, "utf-8"), id);
18716
+ const fm = readFrontmatter(fs15.readFileSync(skill.sourcePath, "utf-8"), id);
18480
18717
  return {
18481
18718
  id,
18482
18719
  name: fm.name,
@@ -18492,8 +18729,8 @@ function readSkillResource(resourceId) {
18492
18729
  const packSkills = loadProjectExtensions2().skills;
18493
18730
  if (SKILL_NAMES.includes(resourceId)) return composeBuiltinSkill(resourceId, packSkills);
18494
18731
  const packSkill = packSkills.find((s) => s.extends === void 0 && packSkillId(s) === resourceId);
18495
- if (packSkill) return fs14.readFileSync(packSkill.sourcePath, "utf-8");
18496
- 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");
18497
18734
  }
18498
18735
  function listResources() {
18499
18736
  return listSkillResources();
@@ -18682,7 +18919,7 @@ var WAIRON_MANAGED_MARKER = "wairon:managed";
18682
18919
  var WAIRON_MANAGED_BANNER = `<!-- ${WAIRON_MANAGED_MARKER} \u2014 generated by \`wairon generate\`; do not edit, changes are overwritten -->`;
18683
18920
 
18684
18921
  // src/exporters/claude.ts
18685
- var path20 = __toESM(require("path"));
18922
+ var path22 = __toESM(require("path"));
18686
18923
  init_fs();
18687
18924
  var ClaudeExporter = class {
18688
18925
  constructor() {
@@ -18691,7 +18928,7 @@ var ClaudeExporter = class {
18691
18928
  outputPath(ctx) {
18692
18929
  const { agent, target, projectRoot } = ctx;
18693
18930
  const outputDir = "outputDir" in target ? target.outputDir : ".claude/agents";
18694
- return path20.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18931
+ return path22.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18695
18932
  }
18696
18933
  export(ctx) {
18697
18934
  const { agent, renderedInstructions } = ctx;
@@ -18712,7 +18949,7 @@ var ClaudeExporter = class {
18712
18949
  };
18713
18950
 
18714
18951
  // src/exporters/custom.ts
18715
- var path21 = __toESM(require("path"));
18952
+ var path23 = __toESM(require("path"));
18716
18953
  init_fs();
18717
18954
  var CustomExporter = class {
18718
18955
  constructor() {
@@ -18723,7 +18960,7 @@ var CustomExporter = class {
18723
18960
  if (!("outputDir" in target)) {
18724
18961
  throw new Error("CustomExporter requires target.outputDir");
18725
18962
  }
18726
- return path21.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18963
+ return path23.resolve(projectRoot, target.outputDir, `${agent.id.replace(/::/g, "--")}.md`);
18727
18964
  }
18728
18965
  export(ctx) {
18729
18966
  const { agent, target, renderedInstructions } = ctx;
@@ -18746,7 +18983,7 @@ var CustomExporter = class {
18746
18983
  };
18747
18984
 
18748
18985
  // src/exporters/gemini.ts
18749
- var path22 = __toESM(require("path"));
18986
+ var path24 = __toESM(require("path"));
18750
18987
  init_fs();
18751
18988
  var GeminiExporter = class {
18752
18989
  constructor() {
@@ -18755,7 +18992,7 @@ var GeminiExporter = class {
18755
18992
  outputPath(ctx) {
18756
18993
  const { agent, target, projectRoot } = ctx;
18757
18994
  const outputDir = "outputDir" in target ? target.outputDir : ".gemini/agents";
18758
- return path22.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
18995
+ return path24.resolve(projectRoot, outputDir, `${agent.id.replace(/::/g, "--")}.yaml`);
18759
18996
  }
18760
18997
  export(ctx) {
18761
18998
  const { agent, renderedInstructions } = ctx;
@@ -18780,7 +19017,7 @@ function yamlString(value) {
18780
19017
  }
18781
19018
 
18782
19019
  // src/exporters/generate.ts
18783
- var path23 = __toESM(require("path"));
19020
+ var path25 = __toESM(require("path"));
18784
19021
  init_fs();
18785
19022
 
18786
19023
  // src/exporters/registry.ts
@@ -18847,7 +19084,7 @@ function resolveExpectedOutputPaths(agents, projectConfig, projectRoot = getProj
18847
19084
  const targetConfig = resolveTargetConfig(agentTarget, projectConfig);
18848
19085
  if (!targetConfig) continue;
18849
19086
  const ctx = { agent, projectRoot, target: targetConfig };
18850
- expected.add(path23.resolve(getExporter(targetConfig).outputPath(ctx)));
19087
+ expected.add(path25.resolve(getExporter(targetConfig).outputPath(ctx)));
18851
19088
  }
18852
19089
  }
18853
19090
  return expected;
@@ -19242,6 +19479,7 @@ init_yaml();
19242
19479
  skillExtendErrors,
19243
19480
  skillsDirForTarget,
19244
19481
  snapshotSpecFiles,
19482
+ specPathsInScope,
19245
19483
  splitNamespace,
19246
19484
  stateIdEquals,
19247
19485
  stateIdString,