@mrciphersmith/keryx 0.3.80 → 0.3.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +2248 -2114
  2. package/dist/core.js +550 -435
  3. package/package.json +1 -1
package/dist/core.js CHANGED
@@ -22803,7 +22803,7 @@ var MARKER_VERSION = 1, BEGIN, END, REFERENCE_HEADING;
22803
22803
  var init_managed_block = __esm(() => {
22804
22804
  BEGIN = /^<!--\s*keryx:reference:begin\s+v=(\d+)(?:\s+hash=([0-9a-f]{64}))?\s*-->$/;
22805
22805
  END = /^<!--\s*keryx:reference:end\s*-->$/;
22806
- REFERENCE_HEADING = /^##\s+Reference\b/i;
22806
+ REFERENCE_HEADING = /^##\s+Reference(?:\s*\([^)]*\))?\s*$/i;
22807
22807
  });
22808
22808
 
22809
22809
  // src/wiki/page-invariants.ts
@@ -23010,6 +23010,49 @@ ${entry}
23010
23010
  return all.join(`
23011
23011
  `);
23012
23012
  }
23013
+ function repairVersionAndOrder(markdown) {
23014
+ let next = markdown;
23015
+ const all = next.split(`
23016
+ `);
23017
+ const range = changelogRange(all);
23018
+ if (range !== null) {
23019
+ const mask = fencedLines2(all);
23020
+ const starts = [];
23021
+ for (let index = range.heading + 1;index < range.end; index += 1) {
23022
+ if (!mask[index] && ENTRY_START.test(all[index]))
23023
+ starts.push(index);
23024
+ }
23025
+ const chunks = starts.map((start, position) => {
23026
+ const end = position + 1 < starts.length ? starts[position + 1] : range.end;
23027
+ const body = all.slice(start, end);
23028
+ while (body.length > 1 && body[body.length - 1].trim() === "")
23029
+ body.pop();
23030
+ return { body, version: ENTRY_VERSION.exec(body[0])?.[1] ?? null };
23031
+ });
23032
+ const ordered = chunks.every((chunk) => chunk.version !== null) ? [...chunks].sort((left, right) => compareVersions(right.version, left.version)) : chunks;
23033
+ if (ordered.some((chunk, index) => chunk !== chunks[index])) {
23034
+ const spaced = starts.length > 1 && all[starts[1] - 1].trim() === "";
23035
+ const rebuilt = [];
23036
+ ordered.forEach((chunk, index) => {
23037
+ if (index > 0 && spaced)
23038
+ rebuilt.push("");
23039
+ rebuilt.push(...chunk.body);
23040
+ });
23041
+ let tail = range.end;
23042
+ while (tail > starts[0] && all[tail - 1].trim() === "")
23043
+ tail -= 1;
23044
+ all.splice(starts[0], tail - starts[0], ...rebuilt);
23045
+ next = all.join(`
23046
+ `);
23047
+ }
23048
+ }
23049
+ const version = pageVersion(next);
23050
+ const newest = newestChangelogVersion(parseChangelog(next));
23051
+ if (version !== null && newest !== null && compareVersions(version, newest) < 0) {
23052
+ next = setPageVersion(next, newest);
23053
+ }
23054
+ return next;
23055
+ }
23013
23056
  function sectionsOf(markdown) {
23014
23057
  const all = lines2(markdown);
23015
23058
  const mask = fencedLines2(all);
@@ -23095,6 +23138,8 @@ function withAddedLines(fresh, existingBody) {
23095
23138
  return false;
23096
23139
  if (/^[-*]\s+\[Module [^\]]+\]\([^)]+\.md\)$/.test(text))
23097
23140
  return false;
23141
+ if (/^[-*]\s+`[^`]+`\s+\(no wiki page\)$/.test(text))
23142
+ return false;
23098
23143
  if (/^graph-derived\b/i.test(text))
23099
23144
  return false;
23100
23145
  return !freshText.includes(text);
@@ -23155,10 +23200,11 @@ ${replacement.lines.join(`
23155
23200
  `);
23156
23201
  }
23157
23202
  }
23203
+ const repaired = repairVersionAndOrder(next);
23158
23204
  if (next === source)
23159
- return existing;
23160
- const version = nextPageVersion(source);
23161
- return inEolOf(existing, prependChangelogEntry(setPageVersion(next, version), `- ${version} - ${entryNote}`));
23205
+ return repaired === source ? existing : inEolOf(existing, repaired);
23206
+ const version = nextPageVersion(repaired);
23207
+ return inEolOf(existing, prependChangelogEntry(setPageVersion(repaired, version), `- ${version} - ${entryNote}`));
23162
23208
  }
23163
23209
  var CHANGELOG_HEADING, SECTION_HEADING, H2, ENTRY_START, ENTRY_VERSION, LEGACY_META_KEYS;
23164
23210
  var init_page_invariants = __esm(() => {
@@ -23182,6 +23228,55 @@ var init_page_invariants = __esm(() => {
23182
23228
  ]);
23183
23229
  });
23184
23230
 
23231
+ // src/wiki/readme-links.ts
23232
+ import path76 from "path";
23233
+ function rewriteReadmeLinks(text, readmeDir, pageLink) {
23234
+ return text.replace(MARKDOWN_LINK, (whole, bang, label, target) => {
23235
+ if (target === "" || HAS_SCHEME.test(target)) {
23236
+ return whole;
23237
+ }
23238
+ const filePart = target.split(/[#?]/)[0] ?? "";
23239
+ if (filePart === "") {
23240
+ return label;
23241
+ }
23242
+ const resolved = path76.posix.normalize(filePart.startsWith("/") ? filePart.replace(/^\/+/, "") : path76.posix.join(readmeDir, filePart));
23243
+ const codePath = resolved.replace(/\/+$/, "");
23244
+ if (codePath === "" || codePath === "." || codePath === ".." || codePath.startsWith("../")) {
23245
+ return label;
23246
+ }
23247
+ const named = label.length > 0 ? `${label} (\`${codePath}\`)` : `\`${codePath}\``;
23248
+ if (bang === "!") {
23249
+ return named;
23250
+ }
23251
+ const moduleName = moduleOfTarget(filePart, codePath);
23252
+ const page = moduleName === null ? null : pageLink(moduleName);
23253
+ return page === null ? named : `[${label.length > 0 ? label : moduleName}](${page})`;
23254
+ });
23255
+ }
23256
+ function moduleOfTarget(filePart, codePath) {
23257
+ const base = path76.posix.basename(codePath);
23258
+ if (filePart.endsWith("/") || !/\.[A-Za-z0-9]+$/.test(base)) {
23259
+ return codePath;
23260
+ }
23261
+ if (DOC_ENTRY.test(base)) {
23262
+ const dir = path76.posix.dirname(codePath);
23263
+ return dir === "." ? null : dir;
23264
+ }
23265
+ return null;
23266
+ }
23267
+ function truncateMarkdown(text, max) {
23268
+ if (text.length <= max) {
23269
+ return text;
23270
+ }
23271
+ return text.slice(0, max).replace(/\s*!?\[[^\]]*$|\s*!?\[[^\]]*\]\([^)]*$/, "").trimEnd();
23272
+ }
23273
+ var MARKDOWN_LINK, HAS_SCHEME, DOC_ENTRY;
23274
+ var init_readme_links = __esm(() => {
23275
+ MARKDOWN_LINK = /(!?)\[([^[\]]*)\]\(\s*<?([^)\s>]*)>?(?:\s+(?:"[^"]*"|'[^']*'))?\s*\)/g;
23276
+ HAS_SCHEME = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
23277
+ DOC_ENTRY = /^(?:readme|index)\.(?:md|mdx)$/i;
23278
+ });
23279
+
23185
23280
  // src/wiki/think-tags.ts
23186
23281
  function maskCodeRegions(text) {
23187
23282
  const maskMatch = (m) => "\x00".repeat(m.length);
@@ -23570,15 +23665,15 @@ __export(exports_service4, {
23570
23665
  import { spawn as spawn3 } from "child_process";
23571
23666
  import { createHash as createHash15 } from "crypto";
23572
23667
  import { mkdir as mkdir20, readFile as readFile39, readdir as readdir13, writeFile as writeFile14 } from "fs/promises";
23573
- import path76 from "path";
23668
+ import path77 from "path";
23574
23669
  function wikiRootPath3(cwd) {
23575
- return path76.join(cwd, ".metaproject", "wiki");
23670
+ return path77.join(cwd, ".metaproject", "wiki");
23576
23671
  }
23577
23672
  function dataRootPath(cwd) {
23578
- return path76.join(cwd, ".metaproject", "data", "gdwiki");
23673
+ return path77.join(cwd, ".metaproject", "data", "gdwiki");
23579
23674
  }
23580
23675
  function linkCheckReportPath(cwd) {
23581
- return path76.join(dataRootPath(cwd), "link-check", "latest.md");
23676
+ return path77.join(dataRootPath(cwd), "link-check", "latest.md");
23582
23677
  }
23583
23678
  async function wikiStatus(cwd) {
23584
23679
  const root = wikiRootPath3(cwd);
@@ -23586,7 +23681,7 @@ async function wikiStatus(cwd) {
23586
23681
  const pages = enabled ? await collectPages(cwd) : [];
23587
23682
  return {
23588
23683
  enabled,
23589
- wikiRoot: path76.relative(cwd, root),
23684
+ wikiRoot: path77.relative(cwd, root),
23590
23685
  totalPages: pages.length,
23591
23686
  countsByType: WIKI_PAGE_TYPES.map(({ type }) => ({
23592
23687
  type,
@@ -23617,9 +23712,9 @@ async function wikiCreatePage(input) {
23617
23712
  if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
23618
23713
  throw new Error(`Invalid slug: ${input.slug}. Use lowercase letters, digits, and hyphens.`);
23619
23714
  }
23620
- const dir = path76.join(wikiRootPath3(input.cwd), typeConfig.folder);
23621
- const filePath = path76.join(dir, `${input.slug}.md`);
23622
- const relativePath = path76.relative(input.cwd, filePath);
23715
+ const dir = path77.join(wikiRootPath3(input.cwd), typeConfig.folder);
23716
+ const filePath = path77.join(dir, `${input.slug}.md`);
23717
+ const relativePath = path77.relative(input.cwd, filePath);
23623
23718
  if (await pathExists(filePath) && !input.force) {
23624
23719
  throw new Error(`Page already exists: ${relativePath}. Use --force to overwrite.`);
23625
23720
  }
@@ -23631,7 +23726,7 @@ async function wikiCreatePage(input) {
23631
23726
  }
23632
23727
  async function wikiGenerateIndex(cwd, history) {
23633
23728
  const root = wikiRootPath3(cwd);
23634
- const indexPath = path76.join(root, "index.md");
23729
+ const indexPath = path77.join(root, "index.md");
23635
23730
  const pages = await collectPages(cwd);
23636
23731
  const generatedAt = new Date().toISOString();
23637
23732
  const managedBlock = `${WIKI_INDEX_BEGIN}
@@ -23648,7 +23743,7 @@ ${managedBlock}
23648
23743
  `;
23649
23744
  await writeWikiPage(history ?? await openWikiWriteContext(cwd, "wiki index"), indexPath, next);
23650
23745
  return {
23651
- path: path76.relative(cwd, indexPath),
23746
+ path: path77.relative(cwd, indexPath),
23652
23747
  pageCount: pages.length,
23653
23748
  generatedAt
23654
23749
  };
@@ -23656,13 +23751,13 @@ ${managedBlock}
23656
23751
  async function wikiCheckLinks(cwd) {
23657
23752
  const root = wikiRootPath3(cwd);
23658
23753
  const allFiles = await pathExists(root) ? await walkMarkdown(root) : [];
23659
- const files = allFiles.filter((absolutePath) => !path76.relative(root, absolutePath).startsWith(`templates${path76.sep}`));
23754
+ const files = allFiles.filter((absolutePath) => !path77.relative(root, absolutePath).startsWith(`templates${path77.sep}`));
23660
23755
  const broken = [];
23661
23756
  let checkedLinks = 0;
23662
23757
  let skippedExternal = 0;
23663
23758
  for (const absolutePath of files) {
23664
23759
  const content = await readFile39(absolutePath, "utf8");
23665
- const pageRelative = path76.relative(cwd, absolutePath);
23760
+ const pageRelative = path77.relative(cwd, absolutePath);
23666
23761
  for (const target of extractLinkTargets(content)) {
23667
23762
  if (EXTERNAL_LINK.test(target)) {
23668
23763
  skippedExternal += 1;
@@ -23673,7 +23768,7 @@ async function wikiCheckLinks(cwd) {
23673
23768
  continue;
23674
23769
  }
23675
23770
  checkedLinks += 1;
23676
- const resolved = path76.resolve(path76.dirname(absolutePath), filePart);
23771
+ const resolved = path77.resolve(path77.dirname(absolutePath), filePart);
23677
23772
  if (!await pathExists(resolved)) {
23678
23773
  broken.push({
23679
23774
  page: pageRelative,
@@ -23685,7 +23780,7 @@ async function wikiCheckLinks(cwd) {
23685
23780
  }
23686
23781
  const generatedAt = new Date().toISOString();
23687
23782
  const reportPath = linkCheckReportPath(cwd);
23688
- await mkdir20(path76.dirname(reportPath), { recursive: true });
23783
+ await mkdir20(path77.dirname(reportPath), { recursive: true });
23689
23784
  await writeFile14(reportPath, renderLinkCheckReport({
23690
23785
  generatedAt,
23691
23786
  checkedPages: files.length,
@@ -23694,7 +23789,7 @@ async function wikiCheckLinks(cwd) {
23694
23789
  broken
23695
23790
  }), "utf8");
23696
23791
  return {
23697
- reportPath: path76.relative(cwd, reportPath),
23792
+ reportPath: path77.relative(cwd, reportPath),
23698
23793
  checkedPages: files.length,
23699
23794
  checkedLinks,
23700
23795
  skippedExternal,
@@ -23745,7 +23840,7 @@ async function wikiValidate(cwd) {
23745
23840
  }
23746
23841
  if (await isIndexStale(cwd, pages)) {
23747
23842
  issues.push({
23748
- page: path76.join(path76.relative(cwd, wikiRootPath3(cwd)), "index.md"),
23843
+ page: path77.join(path77.relative(cwd, wikiRootPath3(cwd)), "index.md"),
23749
23844
  kind: "index",
23750
23845
  message: "index out of date, run `keryx wiki index`"
23751
23846
  });
@@ -23791,13 +23886,15 @@ function collectCommandLabel(input) {
23791
23886
  return ["wiki collect", ...flags].join(" ");
23792
23887
  }
23793
23888
  async function wikiPruneOrphans(cwd, history) {
23794
- const componentsDir = path76.join(wikiRootPath3(cwd), "components");
23889
+ const componentsDir = path77.join(wikiRootPath3(cwd), "components");
23795
23890
  if (!await pathExists(componentsDir)) {
23796
23891
  return { pruned: [], orphanedAccepted: [] };
23797
23892
  }
23798
- const at = new Date().toISOString();
23799
- const candidates = await collectGraphWikiCandidates(cwd, at, DEFAULT_COLLECT_LIMIT, null);
23800
- const validSlugs = new Set(candidates.filter((candidate) => candidate.type === "component").map((candidate) => candidate.slug));
23893
+ const counts = await moduleFileCounts(cwd);
23894
+ if (counts === undefined || counts.size === 0) {
23895
+ return { pruned: [], orphanedAccepted: [] };
23896
+ }
23897
+ const validSlugs = new Set([...counts].filter(([, files]) => files >= MIN_MODULE_FILES).map(([name]) => slugifyPath(name)));
23801
23898
  const pruned = [];
23802
23899
  const orphanedAccepted = [];
23803
23900
  let run;
@@ -23809,32 +23906,37 @@ async function wikiPruneOrphans(cwd, history) {
23809
23906
  if (validSlugs.has(slug)) {
23810
23907
  continue;
23811
23908
  }
23812
- const filePath = path76.join(componentsDir, entry);
23909
+ const filePath = path77.join(componentsDir, entry);
23813
23910
  const current = await readFile39(filePath, "utf8");
23814
23911
  const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
23815
23912
  if (isUnmodifiedDraft) {
23816
23913
  run ??= history ?? await openWikiWriteContext(cwd, "wiki prune");
23817
23914
  await deleteWikiPage(run, filePath);
23818
- pruned.push(path76.relative(cwd, filePath));
23915
+ pruned.push(path77.relative(cwd, filePath));
23819
23916
  } else {
23820
- orphanedAccepted.push(path76.relative(cwd, filePath));
23917
+ orphanedAccepted.push(path77.relative(cwd, filePath));
23821
23918
  }
23822
23919
  }
23823
23920
  return { pruned, orphanedAccepted };
23824
23921
  }
23825
23922
  async function validModuleNames(cwd) {
23826
- const nodesPath = path76.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
23923
+ const counts = await moduleFileCounts(cwd);
23924
+ return counts === undefined ? undefined : new Set(counts.keys());
23925
+ }
23926
+ async function moduleFileCounts(cwd) {
23927
+ const nodesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
23827
23928
  if (!await pathExists(nodesPath)) {
23828
23929
  return;
23829
23930
  }
23830
- const modules = new Set;
23931
+ const counts = new Map;
23831
23932
  for (const node of parseJsonl(await readFile39(nodesPath, "utf8"))) {
23832
23933
  if (node.kind === "asset")
23833
23934
  continue;
23834
23935
  const nodePath = String(node.path ?? node.id ?? "unknown");
23835
- modules.add(moduleNameFromProjectPath(nodePath));
23936
+ const moduleName = moduleNameFromProjectPath(nodePath);
23937
+ counts.set(moduleName, (counts.get(moduleName) ?? 0) + 1);
23836
23938
  }
23837
- return modules;
23939
+ return counts;
23838
23940
  }
23839
23941
  async function wikiEvidence(input) {
23840
23942
  const ask = await wikiAsk({
@@ -23893,9 +23995,9 @@ async function wikiEvidence(input) {
23893
23995
  });
23894
23996
  }
23895
23997
  function resolveEvidenceScope(cwd, override) {
23896
- const absolute = path76.resolve(cwd);
23998
+ const absolute = path77.resolve(cwd);
23897
23999
  return {
23898
- projectId: override?.projectId ?? (path76.basename(absolute) || "project"),
24000
+ projectId: override?.projectId ?? (path77.basename(absolute) || "project"),
23899
24001
  checkoutId: override?.checkoutId ?? `checkout:${createHash15("sha256").update(absolute).digest("hex").slice(0, 16)}`,
23900
24002
  ...override?.workspaceId ? { workspaceId: override.workspaceId } : {},
23901
24003
  ...override?.taskId ? { taskId: override.taskId } : {}
@@ -23910,7 +24012,7 @@ function isMachineAuthoredPage(pageType, relativePath, content) {
23910
24012
  if (source === null) {
23911
24013
  return false;
23912
24014
  }
23913
- const normalised = relativePath.split(path76.sep).join("/").replace(/^wiki\//, "");
24015
+ const normalised = relativePath.split(path77.sep).join("/").replace(/^wiki\//, "");
23914
24016
  return WIKI_PAGE_PRODUCERS.some((producer) => producer.source === source && producer.pageType === pageType && producer.path.test(normalised) && /^-[ \t]+Link:.*\bsha256\b/m.test(content));
23915
24017
  }
23916
24018
  function createGdWikiService() {
@@ -23926,8 +24028,8 @@ function createGdWikiService() {
23926
24028
  };
23927
24029
  }
23928
24030
  async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules) {
23929
- const nodesPath = path76.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
23930
- const edgesPath = path76.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
24031
+ const nodesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
24032
+ const edgesPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
23931
24033
  if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
23932
24034
  return [];
23933
24035
  }
@@ -24014,6 +24116,12 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
24014
24116
  };
24015
24117
  const moduleCandidates = [];
24016
24118
  const pageModules = new Set(topModules.map((entry) => entry.name));
24119
+ const componentsDir = path77.join(wikiRootPath3(cwd), "components");
24120
+ const existingSlugs = new Set((await pathExists(componentsDir) ? await readdir13(componentsDir) : []).filter((entry) => entry.endsWith(".md")).map((entry) => entry.slice(0, -3)));
24121
+ const pageLink = (name) => {
24122
+ const slug = slugifyPath(name);
24123
+ return pageModules.has(name) || existingSlugs.has(slug) ? `${slug}.md` : null;
24124
+ };
24017
24125
  for (const item of topModules) {
24018
24126
  const moduleName = item.name;
24019
24127
  const moduleFileList = moduleFiles.get(moduleName) ?? [];
@@ -24025,7 +24133,7 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
24025
24133
  const entryFiles = moduleFileList.filter((file) => /(^|\/)index\.[jt]sx?$/.test(file)).slice(0, 4);
24026
24134
  const deps = topCounts(moduleDeps.get(moduleName), 6);
24027
24135
  const dependents = topCounts(moduleDependents.get(moduleName), 6);
24028
- const readme = await readModuleReadme(cwd, moduleName);
24136
+ const readme = await readModuleReadme(cwd, moduleName, pageLink);
24029
24137
  const exportsFrom = entryFiles.length > 0 ? entryFiles : keyFiles.slice(0, 2).map((entry) => entry.file);
24030
24138
  const exportApi = await extractModuleApi(cwd, exportsFrom);
24031
24139
  const reference = [];
@@ -24057,15 +24165,20 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
24057
24165
  if (exportApi.length > 0) {
24058
24166
  summaryParts.push("Exposes " + exportApi.length + " public symbol(s).");
24059
24167
  }
24060
- const relatedNames = [];
24168
+ const linkedNames = [];
24169
+ const unlinkedNames = [];
24061
24170
  const seenRelated = new Set([moduleName]);
24062
24171
  for (const [name] of [...deps, ...dependents]) {
24063
- if (!seenRelated.has(name) && pageModules.has(name)) {
24064
- seenRelated.add(name);
24065
- relatedNames.push(name);
24172
+ if (seenRelated.has(name)) {
24173
+ continue;
24066
24174
  }
24175
+ seenRelated.add(name);
24176
+ (pageLink(name) === null ? unlinkedNames : linkedNames).push(name);
24067
24177
  }
24068
- const related = relatedNames.slice(0, 8).map((name) => ({ name, slug: slugifyPath(name) }));
24178
+ const related = [
24179
+ ...linkedNames.slice(0, 8).map((name) => ({ name, page: pageLink(name) })),
24180
+ ...unlinkedNames.slice(0, 8).map((name) => ({ name, page: null }))
24181
+ ];
24069
24182
  moduleCandidates.push({
24070
24183
  type: "component",
24071
24184
  slug: slugifyPath(moduleName),
@@ -24110,8 +24223,8 @@ function topCounts(bucket, limit) {
24110
24223
  }
24111
24224
  return [...bucket.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit);
24112
24225
  }
24113
- async function readModuleReadme(cwd, moduleName) {
24114
- const readmePath = path76.join(cwd, ...moduleName.split("/"), "README.md");
24226
+ async function readModuleReadme(cwd, moduleName, pageLink) {
24227
+ const readmePath = path77.join(cwd, ...moduleName.split("/"), "README.md");
24115
24228
  if (!await pathExists(readmePath)) {
24116
24229
  return null;
24117
24230
  }
@@ -24121,7 +24234,7 @@ async function readModuleReadme(cwd, moduleName) {
24121
24234
  if (!paragraph) {
24122
24235
  return null;
24123
24236
  }
24124
- const normalized = paragraph.replace(/\s+/g, " ").slice(0, 400);
24237
+ const normalized = truncateMarkdown(rewriteReadmeLinks(paragraph.replace(/\s+/g, " "), moduleName, pageLink), 400);
24125
24238
  return "- " + normalized + " (from module README)";
24126
24239
  } catch {
24127
24240
  return null;
@@ -24132,7 +24245,7 @@ async function extractModuleExports(cwd, files) {
24132
24245
  const declRe = /export\s+(?:async\s+)?(?:default\s+)?(?:const|let|var|function|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/g;
24133
24246
  const braceRe = /export\s*\{([^}]+)\}/g;
24134
24247
  for (const file of files.slice(0, 4)) {
24135
- const filePath = path76.join(cwd, ...file.split("/"));
24248
+ const filePath = path77.join(cwd, ...file.split("/"));
24136
24249
  if (!await pathExists(filePath)) {
24137
24250
  continue;
24138
24251
  }
@@ -24163,7 +24276,7 @@ async function extractModuleExports(cwd, files) {
24163
24276
  }
24164
24277
  async function extractModuleApi(cwd, files) {
24165
24278
  const names = await extractModuleExports(cwd, files);
24166
- const symbolsPath = path76.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
24279
+ const symbolsPath = path77.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
24167
24280
  if (names.length === 0 || !await pathExists(symbolsPath)) {
24168
24281
  return names.map((name) => "`" + name + "`");
24169
24282
  }
@@ -24189,7 +24302,7 @@ async function extractModuleApi(cwd, files) {
24189
24302
  });
24190
24303
  }
24191
24304
  async function collectHealthWikiCandidates(cwd, generatedAt) {
24192
- const healthPath = path76.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
24305
+ const healthPath = path77.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
24193
24306
  if (!await pathExists(healthPath)) {
24194
24307
  return [];
24195
24308
  }
@@ -24231,7 +24344,7 @@ async function collectHealthWikiCandidates(cwd, generatedAt) {
24231
24344
  }];
24232
24345
  }
24233
24346
  async function collectTestingWikiCandidates(cwd, generatedAt) {
24234
- const contextPath = path76.join(cwd, ".metaproject", "data", "testing", "context.md");
24347
+ const contextPath = path77.join(cwd, ".metaproject", "data", "testing", "context.md");
24235
24348
  if (!await pathExists(contextPath)) {
24236
24349
  return [];
24237
24350
  }
@@ -24262,8 +24375,8 @@ async function writeCollectedPage(cwd, candidate, force, history) {
24262
24375
  if (!folder) {
24263
24376
  throw new Error(`Unsupported collected wiki type: ${candidate.type}`);
24264
24377
  }
24265
- const filePath = path76.join(wikiRootPath3(cwd), folder, `${candidate.slug}.md`);
24266
- const relativePath = path76.relative(cwd, filePath);
24378
+ const filePath = path77.join(wikiRootPath3(cwd), folder, `${candidate.slug}.md`);
24379
+ const relativePath = path77.relative(cwd, filePath);
24267
24380
  const exists = await pathExists(filePath);
24268
24381
  if (exists && !force) {
24269
24382
  return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
@@ -24314,7 +24427,7 @@ async function writeCollectedPage(cwd, candidate, force, history) {
24314
24427
  async function wikiPagesForFile(cwd, targetRepoPath) {
24315
24428
  const pages = await collectPages(cwd);
24316
24429
  const refs = await Promise.all(pages.map(async (page) => ({
24317
- repoPath: path76.relative(cwd, page.absolutePath).split(path76.sep).join("/"),
24430
+ repoPath: path77.relative(cwd, page.absolutePath).split(path77.sep).join("/"),
24318
24431
  content: await readFile39(page.absolutePath, "utf8")
24319
24432
  })));
24320
24433
  return backlinksFor(buildBacklinkIndex(refs), targetRepoPath);
@@ -24353,7 +24466,7 @@ function renderIndexBody(pages, generatedAt) {
24353
24466
  `).trimEnd();
24354
24467
  }
24355
24468
  async function isIndexStale(cwd, pages) {
24356
- const indexPath = path76.join(wikiRootPath3(cwd), "index.md");
24469
+ const indexPath = path77.join(wikiRootPath3(cwd), "index.md");
24357
24470
  if (!await pathExists(indexPath)) {
24358
24471
  return true;
24359
24472
  }
@@ -24371,7 +24484,7 @@ async function walkMarkdown(root) {
24371
24484
  const results = [];
24372
24485
  const entries = await readdir13(root, { withFileTypes: true });
24373
24486
  for (const entry of entries) {
24374
- const absolutePath = path76.join(root, entry.name);
24487
+ const absolutePath = path77.join(root, entry.name);
24375
24488
  if (entry.isDirectory()) {
24376
24489
  results.push(...await walkMarkdown(absolutePath));
24377
24490
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -24428,7 +24541,7 @@ ${JSON.stringify(state, null, 2)}
24428
24541
  `;
24429
24542
  }
24430
24543
  async function readIndexGeneratedAt(cwd) {
24431
- const indexPath = path76.join(wikiRootPath3(cwd), "index.md");
24544
+ const indexPath = path77.join(wikiRootPath3(cwd), "index.md");
24432
24545
  if (!await pathExists(indexPath)) {
24433
24546
  return null;
24434
24547
  }
@@ -24511,10 +24624,11 @@ ${reference.join(`
24511
24624
  ## Related Wiki
24512
24625
 
24513
24626
  Graph-derived - regenerated by \`keryx wiki collect --force\`. Only pages that
24514
- exist are linked; when enriching, add new links only to pages you have verified.
24627
+ exist are linked, other modules are named as code paths; when enriching, add
24628
+ new links only to pages you have verified.
24515
24629
 
24516
24630
  - [Wiki Index](../index.md)
24517
- ${related.map((entry) => "- [Module " + entry.name + "](" + entry.slug + ".md)").join(`
24631
+ ${related.map((entry) => entry.page === null ? "- `" + entry.name + "` (no wiki page)" : "- [Module " + entry.name + "](" + entry.page + ")").join(`
24518
24632
  `)}
24519
24633
 
24520
24634
  ## Changelog
@@ -24665,7 +24779,7 @@ async function validateStructure(cwd, pages, issues) {
24665
24779
  if (pattern.includes("*")) {
24666
24780
  continue;
24667
24781
  }
24668
- if (!await pathExists(path76.join(cwd, pattern))) {
24782
+ if (!await pathExists(path77.join(cwd, pattern))) {
24669
24783
  issues.push({
24670
24784
  page: page.relativePath,
24671
24785
  kind: "describes",
@@ -24735,7 +24849,7 @@ async function validatePageInvariants(cwd, pages, issues) {
24735
24849
  }
24736
24850
  }
24737
24851
  function toPosixPath(value) {
24738
- return value.split(path76.sep).join("/");
24852
+ return value.split(path77.sep).join("/");
24739
24853
  }
24740
24854
  function compareSemver(a, b) {
24741
24855
  const pa = a.split(".").map(Number);
@@ -24757,6 +24871,7 @@ var init_service4 = __esm(() => {
24757
24871
  init_evidence();
24758
24872
  init_history();
24759
24873
  init_page_invariants();
24874
+ init_readme_links();
24760
24875
  init_section_index();
24761
24876
  init_section_tombstone();
24762
24877
  init_staleness2();
@@ -24778,9 +24893,9 @@ var init_service4 = __esm(() => {
24778
24893
  // src/gdgraph/wiki-layer.ts
24779
24894
  import { createHash as createHash16 } from "crypto";
24780
24895
  import { mkdir as mkdir21, stat as stat12, writeFile as writeFile15 } from "fs/promises";
24781
- import path77 from "path";
24896
+ import path78 from "path";
24782
24897
  function storageDir(projectRoot) {
24783
- return path77.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
24898
+ return path78.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
24784
24899
  }
24785
24900
  function wikiPageId(relativePath) {
24786
24901
  return `wiki:${relativePath}`;
@@ -24846,11 +24961,11 @@ async function enrichBuildWithWikiLayer(input) {
24846
24961
  const mtimes = new Map;
24847
24962
  for (const record of input.fileRecords) {
24848
24963
  try {
24849
- const info = await stat12(path77.join(input.projectRoot, record.path));
24964
+ const info = await stat12(path78.join(input.projectRoot, record.path));
24850
24965
  mtimes.set(record.path, info.mtimeMs);
24851
24966
  } catch {}
24852
24967
  }
24853
- await writeFile15(path77.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
24968
+ await writeFile15(path78.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
24854
24969
  `, "utf8");
24855
24970
  const validModules = input.validModules !== undefined ? input.validModules : await (input.loadValidModules ?? defaultLoadValidModules)(input.projectRoot);
24856
24971
  const wikiPages = await collectPages(input.projectRoot);
@@ -24875,8 +24990,8 @@ async function enrichBuildWithWikiLayer(input) {
24875
24990
  version: page.version
24876
24991
  }))
24877
24992
  });
24878
- await writeJsonl(path77.join(dir, WIKI_PAGES_FILE), layer.pages);
24879
- await writeJsonl(path77.join(dir, DESCRIBES_FILE), layer.describes);
24993
+ await writeJsonl(path78.join(dir, WIKI_PAGES_FILE), layer.pages);
24994
+ await writeJsonl(path78.join(dir, DESCRIBES_FILE), layer.describes);
24880
24995
  return layer;
24881
24996
  }
24882
24997
  async function defaultLoadValidModules(projectRoot) {
@@ -24894,7 +25009,7 @@ var init_wiki_layer = __esm(() => {
24894
25009
  // src/gdskills/contracts.ts
24895
25010
  import { readFile as readFile51 } from "fs/promises";
24896
25011
  import { existsSync as existsSync15 } from "fs";
24897
- import path105 from "path";
25012
+ import path106 from "path";
24898
25013
  import { fileURLToPath as fileURLToPath2 } from "url";
24899
25014
  async function loadSchema(name) {
24900
25015
  const contract = CONTRACTS.find((entry) => entry.name === name);
@@ -24905,10 +25020,10 @@ async function loadSchema(name) {
24905
25020
  return JSON.parse(raw);
24906
25021
  }
24907
25022
  function contractPath(contract) {
24908
- const here = path105.dirname(fileURLToPath2(import.meta.url));
25023
+ const here = path106.dirname(fileURLToPath2(import.meta.url));
24909
25024
  if (contract.sourcePath) {
24910
- for (const root of [path105.join(here, "..", ".."), path105.join(here, ".."), here]) {
24911
- const candidate = path105.resolve(root, contract.sourcePath);
25025
+ for (const root of [path106.join(here, "..", ".."), path106.join(here, ".."), here]) {
25026
+ const candidate = path106.resolve(root, contract.sourcePath);
24912
25027
  if (existsSync15(candidate)) {
24913
25028
  return candidate;
24914
25029
  }
@@ -24918,7 +25033,7 @@ function contractPath(contract) {
24918
25033
  if (existsSync15(directPath)) {
24919
25034
  return directPath;
24920
25035
  }
24921
- const packagedSourcePath = path105.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
25036
+ const packagedSourcePath = path106.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
24922
25037
  if (existsSync15(packagedSourcePath)) {
24923
25038
  return packagedSourcePath;
24924
25039
  }
@@ -29952,7 +30067,7 @@ __export(exports_service5, {
29952
30067
  // src/gdgraph/build.ts
29953
30068
  import { mkdir as mkdir22, readdir as readdir14, readFile as readFile40, writeFile as writeFile16 } from "fs/promises";
29954
30069
  import { existsSync as existsSync7 } from "fs";
29955
- import path78 from "path";
30070
+ import path79 from "path";
29956
30071
 
29957
30072
  // src/gdgraph/types.ts
29958
30073
  var UNKNOWN_IMPORT_KIND = "unknown-static";
@@ -30017,7 +30132,7 @@ async function buildGraph(projectRoot) {
30017
30132
  const assetNodes = new Map;
30018
30133
  const fileRecords = [];
30019
30134
  for (const file of files) {
30020
- const absolutePath = path78.join(projectRoot, file);
30135
+ const absolutePath = path79.join(projectRoot, file);
30021
30136
  const content = await readFile40(absolutePath, "utf8");
30022
30137
  fileRecords.push({ path: file, content });
30023
30138
  const language = getLanguage(file);
@@ -30070,24 +30185,24 @@ async function collectSourceFiles(projectRoot) {
30070
30185
  const result = [];
30071
30186
  const skippedDirectories = [];
30072
30187
  async function walk(relativeDir) {
30073
- const absoluteDir = path78.join(projectRoot, relativeDir);
30188
+ const absoluteDir = path79.join(projectRoot, relativeDir);
30074
30189
  const entries = await readdir14(absoluteDir, { withFileTypes: true });
30075
30190
  for (const entry of entries) {
30076
30191
  if (entry.isDirectory()) {
30077
30192
  if (IGNORE_DIRS.has(entry.name)) {
30078
- skippedDirectories.push(normalizePath2(path78.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
30193
+ skippedDirectories.push(normalizePath2(path79.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
30079
30194
  continue;
30080
30195
  }
30081
- await walk(normalizePath2(path78.posix.join(relativeDir, entry.name)));
30196
+ await walk(normalizePath2(path79.posix.join(relativeDir, entry.name)));
30082
30197
  continue;
30083
30198
  }
30084
30199
  if (!entry.isFile()) {
30085
30200
  continue;
30086
30201
  }
30087
- if (!SOURCE_EXTENSIONS.includes(path78.extname(entry.name))) {
30202
+ if (!SOURCE_EXTENSIONS.includes(path79.extname(entry.name))) {
30088
30203
  continue;
30089
30204
  }
30090
- result.push(normalizePath2(path78.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
30205
+ result.push(normalizePath2(path79.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
30091
30206
  }
30092
30207
  }
30093
30208
  await walk(".");
@@ -30169,8 +30284,8 @@ function resolveImport(projectRoot, fromFile, specifier, fileSet, resolver) {
30169
30284
  }
30170
30285
  function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
30171
30286
  for (const candidate of importCandidateBases(projectRoot, fromFile, specifier, resolver)) {
30172
- const extension = path78.posix.extname(candidate);
30173
- if (ASSET_EXTENSIONS.includes(extension) && existsSync7(path78.join(projectRoot, candidate))) {
30287
+ const extension = path79.posix.extname(candidate);
30288
+ if (ASSET_EXTENSIONS.includes(extension) && existsSync7(path79.join(projectRoot, candidate))) {
30174
30289
  return candidate;
30175
30290
  }
30176
30291
  }
@@ -30179,17 +30294,17 @@ function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
30179
30294
  function importCandidateBases(projectRoot, fromFile, specifier, resolver) {
30180
30295
  const normalizedSpecifier = stripImportSuffix(specifier);
30181
30296
  if (normalizedSpecifier.startsWith(".") && getLanguage(fromFile) !== "python") {
30182
- const fromDir = path78.posix.dirname(fromFile);
30183
- return [normalizePath2(path78.posix.normalize(path78.posix.join(fromDir, normalizedSpecifier)))];
30297
+ const fromDir = path79.posix.dirname(fromFile);
30298
+ return [normalizePath2(path79.posix.normalize(path79.posix.join(fromDir, normalizedSpecifier)))];
30184
30299
  }
30185
- return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path78.relative(projectRoot, path78.join(projectRoot, candidate))));
30300
+ return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path79.relative(projectRoot, path79.join(projectRoot, candidate))));
30186
30301
  }
30187
30302
  function resolveSourceCandidate(base, fileSet) {
30188
30303
  const candidates = [
30189
30304
  base,
30190
30305
  ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => `${base}${extension}`),
30191
- ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path78.posix.join(base, `index${extension}`)),
30192
- path78.posix.join(base, "__init__.py")
30306
+ ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path79.posix.join(base, `index${extension}`)),
30307
+ path79.posix.join(base, "__init__.py")
30193
30308
  ];
30194
30309
  return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
30195
30310
  }
@@ -30219,7 +30334,7 @@ async function loadJavaResolver(projectRoot) {
30219
30334
  return createJavaResolver(roots);
30220
30335
  }
30221
30336
  async function discoverJavaSourceRoots(projectRoot) {
30222
- const pomPath = path78.join(projectRoot, "pom.xml");
30337
+ const pomPath = path79.join(projectRoot, "pom.xml");
30223
30338
  if (existsSync7(pomPath)) {
30224
30339
  try {
30225
30340
  const roots = parseMavenSourceRoots(await readFile40(pomPath, "utf8"));
@@ -30229,7 +30344,7 @@ async function discoverJavaSourceRoots(projectRoot) {
30229
30344
  } catch {}
30230
30345
  }
30231
30346
  for (const gradleName of ["build.gradle", "build.gradle.kts"]) {
30232
- const gradlePath = path78.join(projectRoot, gradleName);
30347
+ const gradlePath = path79.join(projectRoot, gradleName);
30233
30348
  if (existsSync7(gradlePath)) {
30234
30349
  try {
30235
30350
  const roots = parseGradleSourceRoots(await readFile40(gradlePath, "utf8"));
@@ -30251,12 +30366,12 @@ function createJavaResolver(sourceRoots) {
30251
30366
  return [];
30252
30367
  }
30253
30368
  const relative = specifier.split(".").join("/");
30254
- return sourceRoots.map((root) => normalizePath2(path78.posix.join(root, relative)));
30369
+ return sourceRoots.map((root) => normalizePath2(path79.posix.join(root, relative)));
30255
30370
  }
30256
30371
  };
30257
30372
  }
30258
30373
  function loadPythonResolver(projectRoot) {
30259
- const hasSrc = existsSync7(path78.join(projectRoot, "src"));
30374
+ const hasSrc = existsSync7(path79.join(projectRoot, "src"));
30260
30375
  return createPythonResolver(hasSrc);
30261
30376
  }
30262
30377
  function createPythonResolver(hasSrc) {
@@ -30269,16 +30384,16 @@ function createPythonResolver(hasSrc) {
30269
30384
  if (specifier.startsWith(".")) {
30270
30385
  const dots = /^\.+/.exec(specifier)?.[0].length ?? 0;
30271
30386
  const rest = specifier.slice(dots);
30272
- let baseDir = path78.posix.dirname(fromFile);
30387
+ let baseDir = path79.posix.dirname(fromFile);
30273
30388
  for (let level = 1;level < dots; level += 1) {
30274
- baseDir = path78.posix.dirname(baseDir);
30389
+ baseDir = path79.posix.dirname(baseDir);
30275
30390
  }
30276
30391
  const suffix = rest ? rest.split(".").join("/") : "";
30277
- const base = suffix ? path78.posix.join(baseDir, suffix) : baseDir;
30392
+ const base = suffix ? path79.posix.join(baseDir, suffix) : baseDir;
30278
30393
  return [normalizePath2(base)];
30279
30394
  }
30280
30395
  const relative = specifier.split(".").join("/");
30281
- return roots.map((root) => normalizePath2(root ? path78.posix.join(root, relative) : relative));
30396
+ return roots.map((root) => normalizePath2(root ? path79.posix.join(root, relative) : relative));
30282
30397
  }
30283
30398
  };
30284
30399
  }
@@ -30287,8 +30402,8 @@ function parseMavenSourceRoots(pomXml) {
30287
30402
  for (const match of pomXml.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
30288
30403
  const moduleDir = match[1]?.trim();
30289
30404
  if (moduleDir && !moduleDir.includes("${")) {
30290
- roots.add(normalizePath2(path78.posix.join(moduleDir, "src/main/java")));
30291
- roots.add(normalizePath2(path78.posix.join(moduleDir, "src/test/java")));
30405
+ roots.add(normalizePath2(path79.posix.join(moduleDir, "src/main/java")));
30406
+ roots.add(normalizePath2(path79.posix.join(moduleDir, "src/test/java")));
30292
30407
  }
30293
30408
  }
30294
30409
  for (const tag of ["sourceDirectory", "testSourceDirectory"]) {
@@ -30321,7 +30436,7 @@ function parseGradleSourceRoots(buildGradle) {
30321
30436
  var TSCONFIG_EXTENDS_MAX_DEPTH = 10;
30322
30437
  async function loadTsconfigResolver(projectRoot) {
30323
30438
  const empty = createTsconfigResolver(null, []);
30324
- const tsconfigPath = path78.join(projectRoot, "tsconfig.json");
30439
+ const tsconfigPath = path79.join(projectRoot, "tsconfig.json");
30325
30440
  if (!existsSync7(tsconfigPath)) {
30326
30441
  return empty;
30327
30442
  }
@@ -30334,7 +30449,7 @@ async function loadTsconfigResolver(projectRoot) {
30334
30449
  return createTsconfigResolver(resolved.baseUrl, paths);
30335
30450
  }
30336
30451
  function toProjectRelativeDir(projectRoot, absoluteDir) {
30337
- const relative = normalizePath2(path78.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
30452
+ const relative = normalizePath2(path79.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
30338
30453
  return relative === "." ? "" : relative;
30339
30454
  }
30340
30455
  async function readTsconfigJson(configPath) {
@@ -30349,11 +30464,11 @@ function resolveTsconfigExtendsPath(configDir, extendsSpecifier) {
30349
30464
  if (!extendsSpecifier.startsWith(".") && !extendsSpecifier.startsWith("/")) {
30350
30465
  return null;
30351
30466
  }
30352
- const resolved = path78.resolve(configDir, extendsSpecifier);
30467
+ const resolved = path79.resolve(configDir, extendsSpecifier);
30353
30468
  return resolved.endsWith(".json") ? resolved : `${resolved}.json`;
30354
30469
  }
30355
30470
  async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
30356
- const resolvedPath = path78.resolve(configPath);
30471
+ const resolvedPath = path79.resolve(configPath);
30357
30472
  if (depth > TSCONFIG_EXTENDS_MAX_DEPTH || visited.has(resolvedPath)) {
30358
30473
  return null;
30359
30474
  }
@@ -30364,15 +30479,15 @@ async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
30364
30479
  }
30365
30480
  let inherited = null;
30366
30481
  if (typeof parsed.extends === "string") {
30367
- const basePath = resolveTsconfigExtendsPath(path78.dirname(resolvedPath), parsed.extends);
30482
+ const basePath = resolveTsconfigExtendsPath(path79.dirname(resolvedPath), parsed.extends);
30368
30483
  if (basePath) {
30369
30484
  inherited = await resolveTsconfigOptions(basePath, visited, depth + 1, projectRoot);
30370
30485
  }
30371
30486
  }
30372
- const configDir = path78.dirname(resolvedPath);
30487
+ const configDir = path79.dirname(resolvedPath);
30373
30488
  const declaringDir = toProjectRelativeDir(projectRoot, configDir);
30374
30489
  const options = parsed.compilerOptions ?? {};
30375
- const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path78.resolve(configDir, options.baseUrl)) : null;
30490
+ const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path79.resolve(configDir, options.baseUrl)) : null;
30376
30491
  const baseUrl = ownBaseUrl ?? inherited?.baseUrl ?? null;
30377
30492
  const ownPaths = isRecord4(options.paths) ? Object.entries(options.paths).filter((entry) => Array.isArray(entry[1])).map(([pattern, targets]) => ({
30378
30493
  pattern,
@@ -30401,7 +30516,7 @@ function createTsconfigResolver(baseUrl, mappings) {
30401
30516
  }
30402
30517
  }
30403
30518
  if (baseUrl !== null) {
30404
- candidates.push(normalizePath2(path78.posix.join(baseUrl, normalizedSpecifier)));
30519
+ candidates.push(normalizePath2(path79.posix.join(baseUrl, normalizedSpecifier)));
30405
30520
  }
30406
30521
  return [...new Set(candidates.map((candidate) => candidate.replace(/^\.\//, "")))];
30407
30522
  }
@@ -30421,7 +30536,7 @@ function matchPathPattern(pattern, specifier) {
30421
30536
  }
30422
30537
  function applyPathTarget(base, target, wildcard) {
30423
30538
  const replaced = target.includes("*") ? target.replace("*", wildcard) : target;
30424
- return normalizePath2(path78.posix.normalize(path78.posix.join(base, replaced)));
30539
+ return normalizePath2(path79.posix.normalize(path79.posix.join(base, replaced)));
30425
30540
  }
30426
30541
  function stripJsonComments(source) {
30427
30542
  let out = "";
@@ -30474,21 +30589,21 @@ function isRecord4(value) {
30474
30589
  return typeof value === "object" && value !== null && !Array.isArray(value);
30475
30590
  }
30476
30591
  async function writeGraph(projectRoot, graph) {
30477
- const storageDir = path78.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
30478
- const artifactsDir = path78.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
30592
+ const storageDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
30593
+ const artifactsDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
30479
30594
  await mkdir22(storageDir, { recursive: true });
30480
30595
  await mkdir22(artifactsDir, { recursive: true });
30481
- await writeFile16(path78.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
30596
+ await writeFile16(path79.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
30482
30597
  `) + `
30483
30598
  `, "utf8");
30484
- await writeFile16(path78.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
30599
+ await writeFile16(path79.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
30485
30600
  `) + `
30486
30601
  `, "utf8");
30487
- await writeFile16(path78.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
30602
+ await writeFile16(path79.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
30488
30603
  `, "utf8");
30489
30604
  }
30490
30605
  async function writeSummary(projectRoot, graph, collection) {
30491
- const artifactsDir = path78.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
30606
+ const artifactsDir = path79.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
30492
30607
  await mkdir22(artifactsDir, { recursive: true });
30493
30608
  const unresolved = graph.edges.filter((edge) => edge.kind === "unresolved");
30494
30609
  const imports = graph.edges.filter((edge) => edge.kind === "imports");
@@ -30503,7 +30618,7 @@ async function writeSummary(projectRoot, graph, collection) {
30503
30618
  `);
30504
30619
  const skippedList = collection.skippedDirectories.length > 0 ? collection.skippedDirectories.slice(0, 30).map((dir) => `- \`${dir}\``).join(`
30505
30620
  `) : "- none";
30506
- const summaryPath = path78.join(artifactsDir, "summary.md");
30621
+ const summaryPath = path79.join(artifactsDir, "summary.md");
30507
30622
  const content = `# gdgraph Summary
30508
30623
 
30509
30624
  ## Stats
@@ -30584,7 +30699,7 @@ function groupBy(items, getKey) {
30584
30699
  }
30585
30700
  function unresolvedType(specifier) {
30586
30701
  const stripped = stripImportSuffix(specifier);
30587
- const extension = path78.posix.extname(stripped);
30702
+ const extension = path79.posix.extname(stripped);
30588
30703
  if (extension) {
30589
30704
  return extension;
30590
30705
  }
@@ -30594,13 +30709,13 @@ function unresolvedType(specifier) {
30594
30709
  return "package";
30595
30710
  }
30596
30711
  function normalizePath2(value) {
30597
- return value.split(path78.sep).join("/");
30712
+ return value.split(path79.sep).join("/");
30598
30713
  }
30599
30714
 
30600
30715
  // src/gdgraph/target.ts
30601
- import path79 from "path";
30716
+ import path80 from "path";
30602
30717
  function normalizeTarget(target) {
30603
- return target.replace(/^\.\//, "").split(path79.sep).join("/");
30718
+ return target.replace(/^\.\//, "").split(path80.sep).join("/");
30604
30719
  }
30605
30720
  function resolveGraphTarget(graph, target) {
30606
30721
  const normalized = normalizeTarget(target);
@@ -30693,15 +30808,15 @@ init_config3();
30693
30808
 
30694
30809
  // src/gdgraph/query.ts
30695
30810
  import { readFile as readFile41 } from "fs/promises";
30696
- import path80 from "path";
30811
+ import path81 from "path";
30697
30812
  async function loadGraph(projectRoot) {
30698
- const storageDir = path80.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
30699
- const nodes = await readJsonl(path80.join(storageDir, "nodes.jsonl"));
30700
- const edges = await readJsonl(path80.join(storageDir, "edges.jsonl"));
30701
- const symbols = await readJsonl(path80.join(storageDir, "symbols.jsonl"));
30702
- const calls = await readJsonl(path80.join(storageDir, "calls.jsonl"));
30703
- const wikiPages = await readJsonl(path80.join(storageDir, "wiki-pages.jsonl"));
30704
- const describes = await readJsonl(path80.join(storageDir, "describes.jsonl"));
30813
+ const storageDir = path81.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
30814
+ const nodes = await readJsonl(path81.join(storageDir, "nodes.jsonl"));
30815
+ const edges = await readJsonl(path81.join(storageDir, "edges.jsonl"));
30816
+ const symbols = await readJsonl(path81.join(storageDir, "symbols.jsonl"));
30817
+ const calls = await readJsonl(path81.join(storageDir, "calls.jsonl"));
30818
+ const wikiPages = await readJsonl(path81.join(storageDir, "wiki-pages.jsonl"));
30819
+ const describes = await readJsonl(path81.join(storageDir, "describes.jsonl"));
30705
30820
  const graph = { nodes, edges };
30706
30821
  if (symbols.length > 0) {
30707
30822
  graph.symbols = symbols;
@@ -30761,7 +30876,7 @@ async function bunfigPreloadRoots(projectRoot) {
30761
30876
  const roots = new Set;
30762
30877
  let text;
30763
30878
  try {
30764
- text = await readFile41(path80.join(projectRoot, "bunfig.toml"), "utf8");
30879
+ text = await readFile41(path81.join(projectRoot, "bunfig.toml"), "utf8");
30765
30880
  } catch {
30766
30881
  return roots;
30767
30882
  }
@@ -30775,8 +30890,8 @@ async function bunfigPreloadRoots(projectRoot) {
30775
30890
  if (raw.length === 0) {
30776
30891
  continue;
30777
30892
  }
30778
- const absolute = path80.resolve(projectRoot, raw);
30779
- const relative = path80.relative(projectRoot, absolute).split(path80.sep).join("/");
30893
+ const absolute = path81.resolve(projectRoot, raw);
30894
+ const relative = path81.relative(projectRoot, absolute).split(path81.sep).join("/");
30780
30895
  roots.add(relative);
30781
30896
  }
30782
30897
  }
@@ -30849,7 +30964,7 @@ function canonicalCycle(cycle) {
30849
30964
 
30850
30965
  // src/gdgraph/repomap.ts
30851
30966
  import { mkdir as mkdir23, writeFile as writeFile17 } from "fs/promises";
30852
- import path81 from "path";
30967
+ import path82 from "path";
30853
30968
 
30854
30969
  // src/gdgraph/pagerank.ts
30855
30970
  function personalizedPageRank(nodes, edges, options) {
@@ -30960,7 +31075,7 @@ function overflowContent(required, missing, budget) {
30960
31075
  `);
30961
31076
  }
30962
31077
  function repomapArtifactPath(cwd) {
30963
- return path81.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
31078
+ return path82.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
30964
31079
  }
30965
31080
  function buildRankEdges(graph, config) {
30966
31081
  const edges = [];
@@ -31105,7 +31220,7 @@ function computeRepomap(graph, config, options = {}) {
31105
31220
  async function writeRepomap(cwd, graph, config, options = {}) {
31106
31221
  const result = computeRepomap(graph, config, options);
31107
31222
  const artifactPath = repomapArtifactPath(cwd);
31108
- await mkdir23(path81.dirname(artifactPath), { recursive: true });
31223
+ await mkdir23(path82.dirname(artifactPath), { recursive: true });
31109
31224
  await writeFile17(artifactPath, result.content, "utf8");
31110
31225
  return { ...result, path: artifactPath };
31111
31226
  }
@@ -31188,12 +31303,12 @@ init_section_tombstone();
31188
31303
  // src/forgetting/journal.ts
31189
31304
  init_fs();
31190
31305
  import { appendFile as appendFile5, mkdir as mkdir24, readFile as readFile42, stat as stat13 } from "fs/promises";
31191
- import path82 from "path";
31306
+ import path83 from "path";
31192
31307
  function forgettingDataDir(cwd) {
31193
- return path82.join(cwd, ".metaproject", "data", "forgetting");
31308
+ return path83.join(cwd, ".metaproject", "data", "forgetting");
31194
31309
  }
31195
31310
  function deletionJournalPath(cwd) {
31196
- return path82.join(forgettingDataDir(cwd), "journal.jsonl");
31311
+ return path83.join(forgettingDataDir(cwd), "journal.jsonl");
31197
31312
  }
31198
31313
  async function readDeletionJournal(cwd) {
31199
31314
  const file = deletionJournalPath(cwd);
@@ -31612,12 +31727,12 @@ __export(exports_service7, {
31612
31727
  gateExitCode: () => gateExitCode,
31613
31728
  readWikiFreshnessMetric: () => readWikiFreshnessMetric
31614
31729
  });
31615
- import path102 from "path";
31730
+ import path103 from "path";
31616
31731
 
31617
31732
  // src/health/config.ts
31618
31733
  init_fs();
31619
31734
  init_json();
31620
- import path83 from "path";
31735
+ import path84 from "path";
31621
31736
  var DEFAULT_HEALTH_CONFIG = {
31622
31737
  schemaVersion: 2,
31623
31738
  ignore: {
@@ -31673,7 +31788,7 @@ var DEFAULT_HEALTH_CONFIG = {
31673
31788
  }
31674
31789
  };
31675
31790
  function configPath2(cwd) {
31676
- return path83.join(cwd, ".metaproject", "health.config.json");
31791
+ return path84.join(cwd, ".metaproject", "health.config.json");
31677
31792
  }
31678
31793
  var STRICTEST_GATE = {
31679
31794
  failOnPriorities: ["P0", "P1", "P2", "P3"],
@@ -31724,7 +31839,7 @@ async function loadHealthConfig(cwd) {
31724
31839
  // src/health/run.ts
31725
31840
  init_fs();
31726
31841
  import { mkdir as mkdir28, writeFile as writeFile21 } from "fs/promises";
31727
- import path101 from "path";
31842
+ import path102 from "path";
31728
31843
 
31729
31844
  // src/metrics/provenance.ts
31730
31845
  async function collectGitProvenance(cwd) {
@@ -31824,12 +31939,12 @@ function computeGate2(input) {
31824
31939
  }
31825
31940
 
31826
31941
  // src/health/scopes.ts
31827
- import path86 from "path";
31942
+ import path87 from "path";
31828
31943
 
31829
31944
  // src/health/util.ts
31830
31945
  init_fs();
31831
31946
  import { mkdir as mkdir25, readFile as readFile43, readdir as readdir15, writeFile as writeFile18 } from "fs/promises";
31832
- import path84 from "path";
31947
+ import path85 from "path";
31833
31948
  var IGNORED_DIRS = new Set([
31834
31949
  "node_modules",
31835
31950
  ".git",
@@ -31873,14 +31988,14 @@ async function toolVersion(command, cwd) {
31873
31988
  }
31874
31989
  }
31875
31990
  function dataRoot3(cwd) {
31876
- return path84.join(cwd, ".metaproject", "data", "health");
31991
+ return path85.join(cwd, ".metaproject", "data", "health");
31877
31992
  }
31878
31993
  async function writeRaw(cwd, source, content, stamp) {
31879
- const dir = path84.join(dataRoot3(cwd), "raw", source);
31994
+ const dir = path85.join(dataRoot3(cwd), "raw", source);
31880
31995
  await mkdir25(dir, { recursive: true });
31881
- const file = path84.join(dir, `${stamp}.log`);
31996
+ const file = path85.join(dir, `${stamp}.log`);
31882
31997
  await writeFile18(file, content, "utf8");
31883
- return path84.relative(cwd, file);
31998
+ return path85.relative(cwd, file);
31884
31999
  }
31885
32000
  async function listSourceFiles(cwd, ignorePaths = []) {
31886
32001
  const { files } = await listSourceFilesWithReasons(cwd, ignorePaths);
@@ -31900,7 +32015,7 @@ async function walk2(root, dir, out, incompleteReasons) {
31900
32015
  try {
31901
32016
  entries = await readdir15(dir, { withFileTypes: true });
31902
32017
  } catch (error) {
31903
- incompleteReasons.push(`${path84.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
32018
+ incompleteReasons.push(`${path85.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
31904
32019
  return;
31905
32020
  }
31906
32021
  for (const entry of entries) {
@@ -31908,14 +32023,14 @@ async function walk2(root, dir, out, incompleteReasons) {
31908
32023
  if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name)) {}
31909
32024
  continue;
31910
32025
  }
31911
- const abs = path84.join(dir, entry.name);
32026
+ const abs = path85.join(dir, entry.name);
31912
32027
  if (entry.isDirectory()) {
31913
32028
  if (IGNORED_DIRS.has(entry.name)) {
31914
32029
  continue;
31915
32030
  }
31916
32031
  await walk2(root, abs, out, incompleteReasons);
31917
- } else if (entry.isFile() && SOURCE_EXT.has(path84.extname(entry.name))) {
31918
- out.push(path84.relative(root, abs));
32032
+ } else if (entry.isFile() && SOURCE_EXT.has(path85.extname(entry.name))) {
32033
+ out.push(path85.relative(root, abs));
31919
32034
  }
31920
32035
  }
31921
32036
  }
@@ -31930,7 +32045,7 @@ function moduleOfFile(file) {
31930
32045
  return null;
31931
32046
  }
31932
32047
  function isSourceFile(file) {
31933
- return SOURCE_EXT.has(path84.extname(file));
32048
+ return SOURCE_EXT.has(path85.extname(file));
31934
32049
  }
31935
32050
  function matchesAnyPattern(file, patterns) {
31936
32051
  const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
@@ -32030,7 +32145,7 @@ function rankHotspots(files, churn, sourceAnalysis) {
32030
32145
  // src/health/source-analysis.ts
32031
32146
  init_fs();
32032
32147
  import { readFile as readFile44 } from "fs/promises";
32033
- import path85 from "path";
32148
+ import path86 from "path";
32034
32149
 
32035
32150
  // src/health/metrics/complexity.ts
32036
32151
  var CONTROL_KEYWORDS = new Set([
@@ -32264,7 +32379,7 @@ async function analyzeSourceFiles(cwd, sourceFiles) {
32264
32379
  return new Map(entries.filter((entry) => entry !== null));
32265
32380
  }
32266
32381
  async function analyzeSourceFile(cwd, file) {
32267
- const abs = path85.join(cwd, file);
32382
+ const abs = path86.join(cwd, file);
32268
32383
  if (!await pathExists(abs)) {
32269
32384
  return null;
32270
32385
  }
@@ -32337,14 +32452,14 @@ async function computeMetrics(input) {
32337
32452
  }
32338
32453
  const components = new Map;
32339
32454
  for (const file of sourceFiles) {
32340
- const dir = path86.posix.dirname(file);
32455
+ const dir = path87.posix.dirname(file);
32341
32456
  if (dir === "." || dir === moduleOfFile(file)) {
32342
32457
  continue;
32343
32458
  }
32344
32459
  components.set(dir, [...components.get(dir) ?? [], file]);
32345
32460
  }
32346
32461
  for (const [name, files] of [...components.entries()].sort()) {
32347
- const compFindings = findings.filter((f) => f.file && path86.posix.dirname(f.file) === name);
32462
+ const compFindings = findings.filter((f) => f.file && path87.posix.dirname(f.file) === name);
32348
32463
  scopes.push(build("component", `component:${name}`, name, files, compFindings, averageCoverage(files, coverage)));
32349
32464
  }
32350
32465
  const findingFiles = findings.map((f) => f.file).filter((f) => Boolean(f));
@@ -32389,9 +32504,9 @@ function tally2(values) {
32389
32504
  // src/health/baseline.ts
32390
32505
  init_fs();
32391
32506
  import { mkdir as mkdir26, readFile as readFile45, writeFile as writeFile19 } from "fs/promises";
32392
- import path87 from "path";
32507
+ import path88 from "path";
32393
32508
  function baselinePath(cwd) {
32394
- return path87.join(cwd, ".metaproject", "health", "baselines", "scores.json");
32509
+ return path88.join(cwd, ".metaproject", "health", "baselines", "scores.json");
32395
32510
  }
32396
32511
  async function loadBaseline(cwd) {
32397
32512
  const file = baselinePath(cwd);
@@ -32423,7 +32538,7 @@ async function writeBaseline(cwd, metrics, generatedAt, selector) {
32423
32538
  scopes[key] = value;
32424
32539
  }
32425
32540
  const file = baselinePath(cwd);
32426
- await mkdir26(path87.dirname(file), { recursive: true });
32541
+ await mkdir26(path88.dirname(file), { recursive: true });
32427
32542
  await writeFile19(file, `${JSON.stringify({ generatedAt, scopes }, null, 2)}
32428
32543
  `, "utf8");
32429
32544
  return updated;
@@ -32477,10 +32592,10 @@ async function getChurn(cwd, windowDays) {
32477
32592
 
32478
32593
  // src/health/metrics/wiki-freshness.ts
32479
32594
  import { readFile as readFile46, stat as stat14 } from "fs/promises";
32480
- import path88 from "path";
32595
+ import path89 from "path";
32481
32596
  var DEFAULT_STALE_EVIDENCE_DAYS = 7;
32482
32597
  function freshnessReportPath(cwd) {
32483
- return path88.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
32598
+ return path89.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
32484
32599
  }
32485
32600
  async function readWikiFreshnessMetric(cwd, options = {}) {
32486
32601
  const file = freshnessReportPath(cwd);
@@ -32501,7 +32616,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
32501
32616
  } catch {
32502
32617
  return {
32503
32618
  status: "unreadable-report",
32504
- reason: `${path88.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
32619
+ reason: `${path89.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
32505
32620
  };
32506
32621
  }
32507
32622
  const report = parsed;
@@ -32511,7 +32626,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
32511
32626
  if (pagesTotal === null || pagesFresh === null) {
32512
32627
  return {
32513
32628
  status: "unreadable-report",
32514
- reason: `${path88.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
32629
+ reason: `${path89.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
32515
32630
  };
32516
32631
  }
32517
32632
  const pagesUndecidable = numberOr3(totals.pagesUndecidable) ?? 0;
@@ -32565,12 +32680,12 @@ function renderWikiFreshnessLine(metric) {
32565
32680
  }
32566
32681
 
32567
32682
  // src/health/sources/helpers.ts
32568
- import path89 from "path";
32683
+ import path90 from "path";
32569
32684
  import { existsSync as existsSync8 } from "fs";
32570
32685
  class NoImportError extends Error {
32571
32686
  }
32572
32687
  function resolveBin(cwd, name) {
32573
- const local = path89.join(cwd, "node_modules", ".bin", name);
32688
+ const local = path90.join(cwd, "node_modules", ".bin", name);
32574
32689
  if (existsSync8(local)) {
32575
32690
  return local;
32576
32691
  }
@@ -32651,13 +32766,13 @@ async function getComplexityFindings(cwd, sourceFiles, config, sourceAnalysis) {
32651
32766
 
32652
32767
  // src/health/metrics/coverage.ts
32653
32768
  import { existsSync as existsSync9 } from "fs";
32654
- import path90 from "path";
32769
+ import path91 from "path";
32655
32770
  var SUMMARY_PATHS = [
32656
32771
  "coverage/coverage-summary.json",
32657
32772
  "coverage/coverage-final.json"
32658
32773
  ];
32659
32774
  async function getCoverage(cwd) {
32660
- const summary = SUMMARY_PATHS.map((rel) => path90.join(cwd, rel)).find((abs) => existsSync9(abs));
32775
+ const summary = SUMMARY_PATHS.map((rel) => path91.join(cwd, rel)).find((abs) => existsSync9(abs));
32661
32776
  if (!summary) {
32662
32777
  return { status: "missing", total: null, byFile: new Map };
32663
32778
  }
@@ -32678,7 +32793,7 @@ async function getCoverage(cwd) {
32678
32793
  total = pct;
32679
32794
  continue;
32680
32795
  }
32681
- const relative = path90.isAbsolute(key) ? path90.relative(cwd, key) : key;
32796
+ const relative = path91.isAbsolute(key) ? path91.relative(cwd, key) : key;
32682
32797
  byFile.set(relative.replace(/\\/g, "/"), pct);
32683
32798
  }
32684
32799
  return { status: "available", total, byFile };
@@ -32811,10 +32926,10 @@ function renderWikiFreshness(metric) {
32811
32926
  // src/health/skills.ts
32812
32927
  init_fs();
32813
32928
  import { readFile as readFile47 } from "fs/promises";
32814
- import path91 from "path";
32929
+ import path92 from "path";
32815
32930
  var EMPTY = { skills: [], skillForFile: () => null };
32816
32931
  async function loadSkillOwnership(cwd) {
32817
- const manifestPath = path91.join(cwd, ".metaproject", "metaproject.json");
32932
+ const manifestPath = path92.join(cwd, ".metaproject", "metaproject.json");
32818
32933
  if (!await pathExists(manifestPath)) {
32819
32934
  return EMPTY;
32820
32935
  }
@@ -32852,7 +32967,7 @@ function normalize(value) {
32852
32967
 
32853
32968
  // src/health/sources/eslint.ts
32854
32969
  import { existsSync as existsSync10 } from "fs";
32855
- import path92 from "path";
32970
+ import path93 from "path";
32856
32971
  var CONFIG_FILES = [
32857
32972
  ".eslintrc",
32858
32973
  ".eslintrc.js",
@@ -32866,7 +32981,7 @@ var CONFIG_FILES = [
32866
32981
  "eslint.config.ts"
32867
32982
  ];
32868
32983
  function hasConfig(cwd) {
32869
- return CONFIG_FILES.some((file) => existsSync10(path92.join(cwd, file)));
32984
+ return CONFIG_FILES.some((file) => existsSync10(path93.join(cwd, file)));
32870
32985
  }
32871
32986
  var eslintAdapter = {
32872
32987
  id: "eslint",
@@ -32891,7 +33006,7 @@ var eslintAdapter = {
32891
33006
  };
32892
33007
  },
32893
33008
  async import(ctx) {
32894
- const report = path92.join(ctx.cwd, "eslint-report.json");
33009
+ const report = path93.join(ctx.cwd, "eslint-report.json");
32895
33010
  if (!existsSync10(report)) {
32896
33011
  throw new NoImportError("no eslint-report.json");
32897
33012
  }
@@ -32918,7 +33033,7 @@ var eslintAdapter = {
32918
33033
  }
32919
33034
  const findings = [];
32920
33035
  for (const file of data) {
32921
- const relative = path92.isAbsolute(file.filePath) ? path92.relative(ctx.cwd, file.filePath) : file.filePath;
33036
+ const relative = path93.isAbsolute(file.filePath) ? path93.relative(ctx.cwd, file.filePath) : file.filePath;
32922
33037
  for (const message of file.messages ?? []) {
32923
33038
  const isError = message.severity === 2;
32924
33039
  findings.push(makeFinding({
@@ -32950,9 +33065,9 @@ var eslintAdapter = {
32950
33065
 
32951
33066
  // src/health/sources/typescript.ts
32952
33067
  import { existsSync as existsSync11 } from "fs";
32953
- import path93 from "path";
33068
+ import path94 from "path";
32954
33069
  function hasTsconfig(cwd) {
32955
- return existsSync11(path93.join(cwd, "tsconfig.json"));
33070
+ return existsSync11(path94.join(cwd, "tsconfig.json"));
32956
33071
  }
32957
33072
  var typescriptAdapter = {
32958
33073
  id: "typescript",
@@ -33028,7 +33143,7 @@ __export(exports_service6, {
33028
33143
  });
33029
33144
  import { existsSync as existsSync12 } from "fs";
33030
33145
  import { readFile as readFile50, readdir as readdir16 } from "fs/promises";
33031
- import path98 from "path";
33146
+ import path99 from "path";
33032
33147
 
33033
33148
  // src/lib/git-env.ts
33034
33149
  var GIT_DISCOVERY_OVERRIDE_VARS = [
@@ -33053,7 +33168,7 @@ function withoutGitDiscoveryOverrides(env) {
33053
33168
  init_fs();
33054
33169
  init_guard();
33055
33170
  import { readFile as readFile48 } from "fs/promises";
33056
- import path94 from "path";
33171
+ import path95 from "path";
33057
33172
 
33058
33173
  // src/metrics/record.ts
33059
33174
  var RELIABILITIES = new Set(["exact", "estimated", "unknown"]);
@@ -33068,7 +33183,7 @@ var RETRY_TYPES = new Set([
33068
33183
 
33069
33184
  // src/metrics/lifecycle.ts
33070
33185
  async function readArtifactPointer(root, expected) {
33071
- const pointerFile = path94.join(root, "latest.json");
33186
+ const pointerFile = path95.join(root, "latest.json");
33072
33187
  if (!await pathExists(pointerFile))
33073
33188
  return { status: "missing", pointer: null };
33074
33189
  let pointer;
@@ -33077,7 +33192,7 @@ async function readArtifactPointer(root, expected) {
33077
33192
  } catch {
33078
33193
  return { status: "stale", pointer: null, reason: "latest pointer is invalid JSON" };
33079
33194
  }
33080
- const recordFile = pointer.record ? path94.join(root, pointer.record) : null;
33195
+ const recordFile = pointer.record ? path95.join(root, pointer.record) : null;
33081
33196
  if (!recordFile || !isPathInside(root, recordFile) || !await pathExists(recordFile)) {
33082
33197
  return { status: "stale", pointer, reason: "pointer record is missing" };
33083
33198
  }
@@ -33093,9 +33208,9 @@ init_guard();
33093
33208
  // src/testing/capability.ts
33094
33209
  init_fs();
33095
33210
  init_json();
33096
- import path95 from "path";
33211
+ import path96 from "path";
33097
33212
  async function isTestingCapabilityEnabled(cwd, capability) {
33098
- const manifestPath = path95.join(cwd, ".metaproject", "metaproject.json");
33213
+ const manifestPath = path96.join(cwd, ".metaproject", "metaproject.json");
33099
33214
  if (!await pathExists(manifestPath)) {
33100
33215
  return false;
33101
33216
  }
@@ -33121,10 +33236,10 @@ async function isTestingCapabilityEnabled(cwd, capability) {
33121
33236
  init_fs();
33122
33237
  init_guard();
33123
33238
  import { readFile as readFile49, mkdir as mkdir27, writeFile as writeFile20 } from "fs/promises";
33124
- import path96 from "path";
33239
+ import path97 from "path";
33125
33240
  var COVERAGE_MAP_SCHEMA_VERSION = 1;
33126
33241
  function coverageMapPath(cwd, cfg) {
33127
- return path96.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path96.join(cwd, cfg.coverageMap.artifact);
33242
+ return path97.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path97.join(cwd, cfg.coverageMap.artifact);
33128
33243
  }
33129
33244
  async function loadCoverageMap(cwd, cfg) {
33130
33245
  const file = coverageMapPath(cwd, cfg);
@@ -33198,20 +33313,20 @@ function normalizePath4(file) {
33198
33313
  }
33199
33314
 
33200
33315
  // src/testing/selection.ts
33201
- import path97 from "path";
33316
+ import path98 from "path";
33202
33317
  var TEST_FILE_RE = /(^|\/)(__tests__\/.*|.*\.(test|spec)\.[cm]?[tj]sx?$|e2e\/.*\.[cm]?[tj]sx?$|tests\/.*\.[cm]?[tj]sx?$)/;
33203
33318
  function normalizePath5(file) {
33204
33319
  return file.replace(/\\/g, "/").replace(/^\.\//, "");
33205
33320
  }
33206
33321
  function relatedByNamingAndDirectory(target, testFiles) {
33207
33322
  const normalized = normalizePath5(target);
33208
- const ext = path97.extname(normalized);
33323
+ const ext = path98.extname(normalized);
33209
33324
  const withoutExt = ext ? normalized.slice(0, -ext.length) : normalized;
33210
- const base = path97.basename(withoutExt);
33211
- const dir = path97.dirname(normalized);
33325
+ const base = path98.basename(withoutExt);
33326
+ const dir = path98.dirname(normalized);
33212
33327
  return testFiles.filter((file) => {
33213
- const fileDir = path97.dirname(file);
33214
- const fileBase = path97.basename(file);
33328
+ const fileDir = path98.dirname(file);
33329
+ const fileBase = path98.basename(file);
33215
33330
  return file.startsWith(`${withoutExt}.`) || file.includes(`${withoutExt}.`) || fileDir === dir && fileBase.startsWith(`${base}.`) || fileDir.startsWith(dir) && fileBase.includes(base);
33216
33331
  }).sort();
33217
33332
  }
@@ -33341,7 +33456,7 @@ var DEFAULT_TESTING_CONFIG = {
33341
33456
  }
33342
33457
  };
33343
33458
  function testingDataRoot(cwd) {
33344
- return path98.join(cwd, ".metaproject", "data", "testing");
33459
+ return path99.join(cwd, ".metaproject", "data", "testing");
33345
33460
  }
33346
33461
  async function computeTestingContext(cwd) {
33347
33462
  const { files, incompleteReasons } = await listProjectFiles(cwd);
@@ -33516,7 +33631,7 @@ async function runTesting(input) {
33516
33631
  return runResult;
33517
33632
  }
33518
33633
  async function loadTestingContext(cwd) {
33519
- const file = path98.join(testingDataRoot(cwd), "context.json");
33634
+ const file = path99.join(testingDataRoot(cwd), "context.json");
33520
33635
  if (!await pathExists(file)) {
33521
33636
  return null;
33522
33637
  }
@@ -33527,18 +33642,18 @@ async function loadTestingContext(cwd) {
33527
33642
  }
33528
33643
  }
33529
33644
  async function loadTestingReport(cwd) {
33530
- const file = path98.join(testingDataRoot(cwd), "artifacts", "latest.json");
33645
+ const file = path99.join(testingDataRoot(cwd), "artifacts", "latest.json");
33531
33646
  if (!await pathExists(file)) {
33532
33647
  return null;
33533
33648
  }
33534
33649
  try {
33535
33650
  const latest = JSON.parse(await readFile50(file, "utf8"));
33536
33651
  if (typeof latest.record === "string") {
33537
- const pointer = await readArtifactPointer(path98.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
33652
+ const pointer = await readArtifactPointer(path99.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
33538
33653
  if (pointer.status !== "fresh")
33539
33654
  return null;
33540
- const recordFile = path98.join(testingDataRoot(cwd), "artifacts", latest.record);
33541
- if (!isPathInside(path98.join(testingDataRoot(cwd), "artifacts"), recordFile))
33655
+ const recordFile = path99.join(testingDataRoot(cwd), "artifacts", latest.record);
33656
+ if (!isPathInside(path99.join(testingDataRoot(cwd), "artifacts"), recordFile))
33542
33657
  return null;
33543
33658
  if (!await pathExists(recordFile))
33544
33659
  return null;
@@ -33585,28 +33700,28 @@ async function ensureContext(cwd) {
33585
33700
  }
33586
33701
  async function writeContext(cwd, context) {
33587
33702
  const root = testingDataRoot(cwd);
33588
- const rel = (p) => path98.relative(cwd, p);
33703
+ const rel = (p) => path99.relative(cwd, p);
33589
33704
  await mkdirContained(cwd, rel(root));
33590
- await writeContained(cwd, rel(path98.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
33705
+ await writeContained(cwd, rel(path99.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
33591
33706
  `);
33592
- await writeContained(cwd, rel(path98.join(root, "context.md")), renderContextMarkdown(context));
33593
- await writeContained(cwd, rel(path98.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
33707
+ await writeContained(cwd, rel(path99.join(root, "context.md")), renderContextMarkdown(context));
33708
+ await writeContained(cwd, rel(path99.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
33594
33709
  }
33595
33710
  async function writeReport(cwd, report) {
33596
33711
  const root = testingDataRoot(cwd);
33597
- const artifacts = path98.join(root, "artifacts");
33598
- const history = path98.join(root, "history");
33599
- const rel = (p) => path98.relative(cwd, p);
33712
+ const artifacts = path99.join(root, "artifacts");
33713
+ const history = path99.join(root, "history");
33714
+ const rel = (p) => path99.relative(cwd, p);
33600
33715
  await mkdirContained(cwd, rel(artifacts));
33601
33716
  await mkdirContained(cwd, rel(history));
33602
33717
  const stamp = report.generatedAt.replace(/[:.]/g, "-");
33603
- const json = path98.join(artifacts, "latest.json");
33604
- const markdown = path98.join(artifacts, "latest.md");
33718
+ const json = path99.join(artifacts, "latest.json");
33719
+ const markdown = path99.join(artifacts, "latest.md");
33605
33720
  const serialized = `${JSON.stringify(report, null, 2)}
33606
33721
  `;
33607
33722
  if (report.runId) {
33608
- const runJson = path98.join(artifacts, "runs", `${report.runId}.json`);
33609
- const runMarkdown = path98.join(artifacts, "runs", `${report.runId}.md`);
33723
+ const runJson = path99.join(artifacts, "runs", `${report.runId}.json`);
33724
+ const runMarkdown = path99.join(artifacts, "runs", `${report.runId}.md`);
33610
33725
  if (await pathExists(runJson))
33611
33726
  throw new Error(`immutable testing run already exists: ${report.runId}`);
33612
33727
  await writeContained(cwd, rel(runJson), serialized);
@@ -33617,26 +33732,26 @@ async function writeReport(cwd, report) {
33617
33732
  branch: report.provenance?.branch ?? null,
33618
33733
  worktree: report.provenance?.worktree ?? null,
33619
33734
  generated_at: report.generatedAt,
33620
- record: path98.posix.join("runs", `${report.runId}.json`)
33735
+ record: path99.posix.join("runs", `${report.runId}.json`)
33621
33736
  }, null, 2)}
33622
33737
  `);
33623
33738
  } else {
33624
33739
  await writeContained(cwd, rel(json), serialized);
33625
33740
  }
33626
33741
  await writeContained(cwd, rel(markdown), renderReportMarkdown3(report));
33627
- await writeContained(cwd, rel(path98.join(history, `${stamp}.json`)), serialized);
33742
+ await writeContained(cwd, rel(path99.join(history, `${stamp}.json`)), serialized);
33628
33743
  return {
33629
- markdownPath: path98.relative(cwd, markdown),
33630
- jsonPath: path98.relative(cwd, json)
33744
+ markdownPath: path99.relative(cwd, markdown),
33745
+ jsonPath: path99.relative(cwd, json)
33631
33746
  };
33632
33747
  }
33633
33748
  async function writeRawLog(cwd, raw) {
33634
- const logs = path98.join(testingDataRoot(cwd), "logs");
33635
- const rel = (p) => path98.relative(cwd, p);
33749
+ const logs = path99.join(testingDataRoot(cwd), "logs");
33750
+ const rel = (p) => path99.relative(cwd, p);
33636
33751
  await mkdirContained(cwd, rel(logs));
33637
- const latest = path98.join(logs, "latest.raw.log");
33752
+ const latest = path99.join(logs, "latest.raw.log");
33638
33753
  await writeContained(cwd, rel(latest), raw);
33639
- return path98.relative(cwd, latest);
33754
+ return path99.relative(cwd, latest);
33640
33755
  }
33641
33756
  async function listProjectFiles(cwd) {
33642
33757
  const out = [];
@@ -33649,11 +33764,11 @@ async function walk3(root, dir, out, incompleteReasons) {
33649
33764
  try {
33650
33765
  entries = await readdir16(dir, { withFileTypes: true });
33651
33766
  } catch (error) {
33652
- incompleteReasons.push(`${normalizePath6(path98.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
33767
+ incompleteReasons.push(`${normalizePath6(path99.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
33653
33768
  return;
33654
33769
  }
33655
33770
  for (const entry of entries) {
33656
- const abs = path98.join(dir, entry.name);
33771
+ const abs = path99.join(dir, entry.name);
33657
33772
  if (entry.isDirectory()) {
33658
33773
  if (IGNORED_DIRS2.has(entry.name) || entry.name.startsWith(".tmp-")) {
33659
33774
  continue;
@@ -33662,12 +33777,12 @@ async function walk3(root, dir, out, incompleteReasons) {
33662
33777
  continue;
33663
33778
  }
33664
33779
  if (entry.isFile()) {
33665
- out.push(normalizePath6(path98.relative(root, abs)));
33780
+ out.push(normalizePath6(path99.relative(root, abs)));
33666
33781
  }
33667
33782
  }
33668
33783
  }
33669
33784
  async function readPackageJson(cwd) {
33670
- const file = path98.join(cwd, "package.json");
33785
+ const file = path99.join(cwd, "package.json");
33671
33786
  if (!await pathExists(file)) {
33672
33787
  return null;
33673
33788
  }
@@ -33678,7 +33793,7 @@ async function readPackageJson(cwd) {
33678
33793
  }
33679
33794
  }
33680
33795
  async function loadTestingConfig(cwd) {
33681
- const file = path98.join(cwd, ".metaproject", "testing.config.json");
33796
+ const file = path99.join(cwd, ".metaproject", "testing.config.json");
33682
33797
  if (!await pathExists(file)) {
33683
33798
  return DEFAULT_TESTING_CONFIG;
33684
33799
  }
@@ -33743,7 +33858,7 @@ function detectFrameworks(input) {
33743
33858
  async function extractConventions(cwd, files) {
33744
33859
  const conventions = new Set;
33745
33860
  for (const file of files.slice(0, 40)) {
33746
- const abs = path98.join(cwd, file);
33861
+ const abs = path99.join(cwd, file);
33747
33862
  if (!await pathExists(abs)) {
33748
33863
  continue;
33749
33864
  }
@@ -33873,7 +33988,7 @@ async function findTestsByImportedTargets(cwd, targets, testFiles) {
33873
33988
  const targetKeys = new Set(targets.map((target) => modulePathKey(normalizePath6(target))));
33874
33989
  const selected = new Set;
33875
33990
  for (const testFile of testFiles) {
33876
- const absoluteTest = path98.join(cwd, testFile);
33991
+ const absoluteTest = path99.join(cwd, testFile);
33877
33992
  if (!await pathExists(absoluteTest)) {
33878
33993
  continue;
33879
33994
  }
@@ -33907,10 +34022,10 @@ function resolveImportPath(cwd, testFile, importPath) {
33907
34022
  if (!importPath.startsWith(".")) {
33908
34023
  return null;
33909
34024
  }
33910
- const importerDir = path98.dirname(testFile);
33911
- const absoluteResolved = path98.resolve(path98.join(cwd, importerDir), importPath);
33912
- const relative = path98.relative(cwd, absoluteResolved);
33913
- if (relative.startsWith(`..${path98.sep}`) || relative === "..") {
34025
+ const importerDir = path99.dirname(testFile);
34026
+ const absoluteResolved = path99.resolve(path99.join(cwd, importerDir), importPath);
34027
+ const relative = path99.relative(cwd, absoluteResolved);
34028
+ if (relative.startsWith(`..${path99.sep}`) || relative === "..") {
33914
34029
  return null;
33915
34030
  }
33916
34031
  const relativeNormalized = normalizePath6(relative);
@@ -33962,13 +34077,13 @@ function resolveTestCommand(cwd, context, input) {
33962
34077
  }
33963
34078
  var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
33964
34079
  function detectPackageManager(cwd) {
33965
- if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path98.join(cwd, name)))) {
34080
+ if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path99.join(cwd, name)))) {
33966
34081
  return "bun";
33967
34082
  }
33968
- if (Bun.which("pnpm") && pathExistsSync(path98.join(cwd, "pnpm-lock.yaml"))) {
34083
+ if (Bun.which("pnpm") && pathExistsSync(path99.join(cwd, "pnpm-lock.yaml"))) {
33969
34084
  return "pnpm";
33970
34085
  }
33971
- if (Bun.which("yarn") && pathExistsSync(path98.join(cwd, "yarn.lock"))) {
34086
+ if (Bun.which("yarn") && pathExistsSync(path99.join(cwd, "yarn.lock"))) {
33972
34087
  return "yarn";
33973
34088
  }
33974
34089
  return "npm";
@@ -34308,7 +34423,7 @@ async function compatibleReportForHealth(ctx) {
34308
34423
 
34309
34424
  // src/health/sources/dependency-audit.ts
34310
34425
  import { existsSync as existsSync13 } from "fs";
34311
- import path99 from "path";
34426
+ import path100 from "path";
34312
34427
  function auditSeverityToPriority(severity) {
34313
34428
  if (severity === "critical" || severity === "high")
34314
34429
  return "P0";
@@ -34427,7 +34542,7 @@ var LOCKFILE_COMMANDS = [
34427
34542
  ];
34428
34543
  function auditCommand(cwd) {
34429
34544
  for (const entry of LOCKFILE_COMMANDS) {
34430
- if (!entry.lockfiles.some((name) => existsSync13(path99.join(cwd, name))))
34545
+ if (!entry.lockfiles.some((name) => existsSync13(path100.join(cwd, name))))
34431
34546
  continue;
34432
34547
  const bin = resolveBin(cwd, entry.bin);
34433
34548
  if (bin)
@@ -34486,13 +34601,13 @@ var dependencyAuditAdapter = {
34486
34601
 
34487
34602
  // src/health/sources/sonarqube.ts
34488
34603
  import { existsSync as existsSync14 } from "fs";
34489
- import path100 from "path";
34604
+ import path101 from "path";
34490
34605
  var REPORT_FILES = ["sonar-issues.json", ".metaproject/data/health/sonar-issues.json"];
34491
34606
  function reportPath(cwd) {
34492
34607
  const fromEnv = process.env.SONAR_ISSUES_FILE;
34493
34608
  const candidates = fromEnv ? [fromEnv, ...REPORT_FILES] : REPORT_FILES;
34494
34609
  for (const rel of candidates) {
34495
- const abs = path100.isAbsolute(rel) ? rel : path100.join(cwd, rel);
34610
+ const abs = path101.isAbsolute(rel) ? rel : path101.join(cwd, rel);
34496
34611
  if (existsSync14(abs)) {
34497
34612
  return abs;
34498
34613
  }
@@ -34576,7 +34691,7 @@ var sonarqubeAdapter = {
34576
34691
  function relativizeComponent(component, cwd) {
34577
34692
  const colon = component.indexOf(":");
34578
34693
  const value = colon >= 0 ? component.slice(colon + 1) : component;
34579
- return path100.isAbsolute(value) ? path100.relative(cwd, value) : value;
34694
+ return path101.isAbsolute(value) ? path101.relative(cwd, value) : value;
34580
34695
  }
34581
34696
 
34582
34697
  // src/health/sources/index.ts
@@ -34913,19 +35028,19 @@ function filteredInfo(source, cfg) {
34913
35028
  };
34914
35029
  }
34915
35030
  async function writeOutputs(cwd, report, config, stamp) {
34916
- const artifacts = path101.join(dataRoot3(cwd), "artifacts");
34917
- const history = path101.join(dataRoot3(cwd), "history");
35031
+ const artifacts = path102.join(dataRoot3(cwd), "artifacts");
35032
+ const history = path102.join(dataRoot3(cwd), "history");
34918
35033
  await mkdir28(artifacts, { recursive: true });
34919
35034
  await mkdir28(history, { recursive: true });
34920
- const markdown = path101.join(artifacts, "latest.md");
34921
- const json = path101.join(artifacts, "latest.json");
34922
- const historyJson = path101.join(history, `${stamp}.json`);
35035
+ const markdown = path102.join(artifacts, "latest.md");
35036
+ const json = path102.join(artifacts, "latest.json");
35037
+ const historyJson = path102.join(history, `${stamp}.json`);
34923
35038
  const serialized = `${JSON.stringify(report, null, 2)}
34924
35039
  `;
34925
35040
  await writeFile21(markdown, renderReportMarkdown2(report, config), "utf8");
34926
35041
  if (report.runId) {
34927
- const runJson = path101.join(artifacts, "runs", `${report.runId}.json`);
34928
- const runMarkdown = path101.join(artifacts, "runs", `${report.runId}.md`);
35042
+ const runJson = path102.join(artifacts, "runs", `${report.runId}.json`);
35043
+ const runMarkdown = path102.join(artifacts, "runs", `${report.runId}.md`);
34929
35044
  if (await pathExists(runJson))
34930
35045
  throw new Error(`immutable health run already exists: ${report.runId}`);
34931
35046
  await writeFileAtomic(runJson, serialized);
@@ -34936,7 +35051,7 @@ async function writeOutputs(cwd, report, config, stamp) {
34936
35051
  branch: report.provenance?.branch ?? null,
34937
35052
  worktree: report.provenance?.worktree ?? null,
34938
35053
  generated_at: report.generatedAt,
34939
- record: path101.posix.join("runs", `${report.runId}.json`)
35054
+ record: path102.posix.join("runs", `${report.runId}.json`)
34940
35055
  }, null, 2)}
34941
35056
  `);
34942
35057
  } else {
@@ -34944,8 +35059,8 @@ async function writeOutputs(cwd, report, config, stamp) {
34944
35059
  }
34945
35060
  await writeFile21(historyJson, serialized, "utf8");
34946
35061
  return {
34947
- markdownPath: path101.relative(cwd, markdown),
34948
- jsonPath: path101.relative(cwd, json)
35062
+ markdownPath: path102.relative(cwd, markdown),
35063
+ jsonPath: path102.relative(cwd, json)
34949
35064
  };
34950
35065
  }
34951
35066
  async function resolveChanged(cwd, selector) {
@@ -34998,7 +35113,7 @@ function hasGateShape(value) {
34998
35113
  return Array.isArray(report.metrics) && Array.isArray(report.sources) && Array.isArray(report.findings);
34999
35114
  }
35000
35115
  async function readLatest(cwd) {
35001
- const file = path102.join(dataRoot3(cwd), "artifacts", "latest.json");
35116
+ const file = path103.join(dataRoot3(cwd), "artifacts", "latest.json");
35002
35117
  if (!await pathExists(file)) {
35003
35118
  return null;
35004
35119
  }
@@ -35009,11 +35124,11 @@ async function readLatest(cwd) {
35009
35124
  const latest = read.value;
35010
35125
  const record = latest.record;
35011
35126
  if (typeof record === "string") {
35012
- const pointer = await readArtifactPointer(path102.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
35127
+ const pointer = await readArtifactPointer(path103.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
35013
35128
  if (pointer.status !== "fresh")
35014
35129
  return null;
35015
- const recordFile = path102.join(dataRoot3(cwd), "artifacts", record);
35016
- if (!isPathInside(path102.join(dataRoot3(cwd), "artifacts"), recordFile))
35130
+ const recordFile = path103.join(dataRoot3(cwd), "artifacts", record);
35131
+ if (!isPathInside(path103.join(dataRoot3(cwd), "artifacts"), recordFile))
35017
35132
  return null;
35018
35133
  if (!await pathExists(recordFile))
35019
35134
  return null;
@@ -35086,7 +35201,7 @@ function createCodeHealthService() {
35086
35201
  return {
35087
35202
  run: (input) => runHealth(input),
35088
35203
  async status(input) {
35089
- const enabled = await pathExists(path102.join(input.cwd, ".metaproject", "health.config.json"));
35204
+ const enabled = await pathExists(path103.join(input.cwd, ".metaproject", "health.config.json"));
35090
35205
  const latest = await readLatest(input.cwd);
35091
35206
  const project = latest?.metrics.find((m) => m.key === "project") ?? null;
35092
35207
  const decliningScopes = latest ? latest.metrics.filter((m) => m.regression_score > 0).length : 0;
@@ -35244,10 +35359,10 @@ function renderEvidenceBlock(evidences, siblings) {
35244
35359
  init_fs();
35245
35360
  init_contained_write();
35246
35361
  init_json();
35247
- import path103 from "path";
35362
+ import path104 from "path";
35248
35363
  import { createHash as createHash17 } from "crypto";
35249
35364
  function impactEvidenceDataRoot(root) {
35250
- return path103.join(root, ".metaproject", "data", "security", "impact-evidence");
35365
+ return path104.join(root, ".metaproject", "data", "security", "impact-evidence");
35251
35366
  }
35252
35367
  function sanitizeSessionId(sessionId) {
35253
35368
  const cleaned = sessionId.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -35259,7 +35374,7 @@ function sessionStateFilename(sessionId) {
35259
35374
  return `${sanitized}-${suffix}.json`;
35260
35375
  }
35261
35376
  function sessionStatePath(root, sessionId) {
35262
- return path103.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
35377
+ return path104.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
35263
35378
  }
35264
35379
  async function loadSessionState(root, sessionId) {
35265
35380
  const file = sessionStatePath(root, sessionId);
@@ -35278,11 +35393,11 @@ async function loadSessionState(root, sessionId) {
35278
35393
  }
35279
35394
  async function saveSessionState(root, sessionId, state) {
35280
35395
  const file = sessionStatePath(root, sessionId);
35281
- await writeContained(root, path103.relative(root, file), `${JSON.stringify(state, null, 2)}
35396
+ await writeContained(root, path104.relative(root, file), `${JSON.stringify(state, null, 2)}
35282
35397
  `);
35283
35398
  }
35284
35399
  function logPath(root) {
35285
- return path103.join(impactEvidenceDataRoot(root), "log.jsonl");
35400
+ return path104.join(impactEvidenceDataRoot(root), "log.jsonl");
35286
35401
  }
35287
35402
  async function appendLogRecord(root, record) {
35288
35403
  const full = {
@@ -35293,7 +35408,7 @@ async function appendLogRecord(root, record) {
35293
35408
  ...record.detail !== undefined ? { detail: record.detail } : {}
35294
35409
  };
35295
35410
  const file = logPath(root);
35296
- await appendContained(root, path103.relative(root, file), `${JSON.stringify(full)}
35411
+ await appendContained(root, path104.relative(root, file), `${JSON.stringify(full)}
35297
35412
  `);
35298
35413
  return full;
35299
35414
  }
@@ -35320,7 +35435,7 @@ init_command_risk();
35320
35435
  init_shell_syntax();
35321
35436
  init_fs();
35322
35437
  init_service2();
35323
- import path104 from "path";
35438
+ import path105 from "path";
35324
35439
  import { createHash as createHash18 } from "crypto";
35325
35440
  import { realpathSync as realpathSync2 } from "fs";
35326
35441
  function impactEvidenceHookClass(strict) {
@@ -35336,29 +35451,29 @@ function realpathNearestExisting(p) {
35336
35451
  for (;; ) {
35337
35452
  try {
35338
35453
  const real = realpathSync2(current);
35339
- return tail.length > 0 ? path104.join(real, ...tail) : real;
35454
+ return tail.length > 0 ? path105.join(real, ...tail) : real;
35340
35455
  } catch {
35341
- const parent = path104.dirname(current);
35456
+ const parent = path105.dirname(current);
35342
35457
  if (parent === current) {
35343
- return tail.length > 0 ? path104.join(current, ...tail) : current;
35458
+ return tail.length > 0 ? path105.join(current, ...tail) : current;
35344
35459
  }
35345
- tail.unshift(path104.basename(current));
35460
+ tail.unshift(path105.basename(current));
35346
35461
  current = parent;
35347
35462
  }
35348
35463
  }
35349
35464
  }
35350
35465
  function normalizeRequestFiles(root, files) {
35351
- const rootReal = realpathNearestExisting(path104.resolve(root));
35466
+ const rootReal = realpathNearestExisting(path105.resolve(root));
35352
35467
  const normalized = [];
35353
35468
  const rejected = [];
35354
35469
  for (const file of files) {
35355
- const lexicalAbsolute = path104.isAbsolute(file) ? path104.resolve(file) : path104.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
35470
+ const lexicalAbsolute = path105.isAbsolute(file) ? path105.resolve(file) : path105.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
35356
35471
  const effective = realpathNearestExisting(lexicalAbsolute);
35357
35472
  if (!isPathInside(rootReal, effective)) {
35358
35473
  rejected.push(file);
35359
35474
  continue;
35360
35475
  }
35361
- normalized.push(toPosix(path104.relative(rootReal, effective)));
35476
+ normalized.push(toPosix(path105.relative(rootReal, effective)));
35362
35477
  }
35363
35478
  return { files: [...new Set(normalized)], rejected };
35364
35479
  }
@@ -35644,7 +35759,7 @@ __export(exports_service8, {
35644
35759
  createJobService: () => createJobService
35645
35760
  });
35646
35761
  import { copyFile, mkdir as mkdir30 } from "fs/promises";
35647
- import path107 from "path";
35762
+ import path108 from "path";
35648
35763
 
35649
35764
  // src/job/types.ts
35650
35765
  var JOB_INTENTS = ["implement", "analyze", "review", "custom"];
@@ -35785,15 +35900,15 @@ init_validator();
35785
35900
  init_contracts();
35786
35901
  init_fs();
35787
35902
  import { appendFile as appendFile6, mkdir as mkdir29, readFile as readFile52, readdir as readdir17 } from "fs/promises";
35788
- import path106 from "path";
35903
+ import path107 from "path";
35789
35904
  function jobsRoot(cwd) {
35790
- return path106.join(cwd, ".metaproject", "jobs");
35905
+ return path107.join(cwd, ".metaproject", "jobs");
35791
35906
  }
35792
35907
  function jobDir(cwd, name) {
35793
- return path106.join(jobsRoot(cwd), name);
35908
+ return path107.join(jobsRoot(cwd), name);
35794
35909
  }
35795
35910
  function jobStatePath(cwd, name) {
35796
- return path106.join(jobDir(cwd, name), "state.json");
35911
+ return path107.join(jobDir(cwd, name), "state.json");
35797
35912
  }
35798
35913
  var JOB_NAME_PATTERN = /^[a-z0-9-]+$/;
35799
35914
  function assertJobName(name) {
@@ -35830,12 +35945,12 @@ async function writeJob(cwd, name, state) {
35830
35945
  `));
35831
35946
  }
35832
35947
  const file = jobStatePath(cwd, name);
35833
- await mkdir29(path106.dirname(file), { recursive: true });
35948
+ await mkdir29(path107.dirname(file), { recursive: true });
35834
35949
  await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
35835
35950
  `);
35836
35951
  }
35837
35952
  async function appendJournal2(cwd, name, at, line) {
35838
- await appendFile6(path106.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
35953
+ await appendFile6(path107.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
35839
35954
  `, "utf8");
35840
35955
  }
35841
35956
  function renderJournal2(name, at) {
@@ -35856,7 +35971,7 @@ function assertDocumentType(raw) {
35856
35971
  return raw;
35857
35972
  }
35858
35973
  function documentFileName(type, sourcePath) {
35859
- const extension = path106.extname(sourcePath) || ".md";
35974
+ const extension = path107.extname(sourcePath) || ".md";
35860
35975
  return `${type}${extension}`;
35861
35976
  }
35862
35977
 
@@ -35864,7 +35979,7 @@ function documentFileName(type, sourcePath) {
35864
35979
  function createJobService(deps) {
35865
35980
  const now = () => deps.now().toISOString();
35866
35981
  function lockPath(cwd, name) {
35867
- return path107.join(jobsRoot(cwd), `.job-lock-${name}`);
35982
+ return path108.join(jobsRoot(cwd), `.job-lock-${name}`);
35868
35983
  }
35869
35984
  async function mutate(cwd, name, run) {
35870
35985
  assertJobName(name);
@@ -35913,20 +36028,20 @@ function createJobService(deps) {
35913
36028
  },
35914
36029
  plan: { steps: defaultPlan(intent) },
35915
36030
  documentation: {
35916
- job_path: path107.join(".metaproject", "jobs", name),
36031
+ job_path: path108.join(".metaproject", "jobs", name),
35917
36032
  documents_created: []
35918
36033
  },
35919
36034
  metrics: { steps: [] },
35920
- jobs_root: path107.join(".metaproject", "jobs"),
36035
+ jobs_root: path108.join(".metaproject", "jobs"),
35921
36036
  updated_at: createdAt
35922
36037
  };
35923
36038
  const first = firstOpenStep(state.plan.steps);
35924
36039
  if (first) {
35925
36040
  state.plan.current_step = first.id;
35926
36041
  }
35927
- await writeFileAtomic(path107.join(absolute, "journal.md"), renderJournal2(name, createdAt));
36042
+ await writeFileAtomic(path108.join(absolute, "journal.md"), renderJournal2(name, createdAt));
35928
36043
  await writeJob(input.cwd, name, state);
35929
- return { state, dir: path107.relative(input.cwd, absolute) };
36044
+ return { state, dir: path108.relative(input.cwd, absolute) };
35930
36045
  },
35931
36046
  async status({ cwd, name }) {
35932
36047
  assertJobName(name);
@@ -35938,7 +36053,7 @@ function createJobService(deps) {
35938
36053
  }
35939
36054
  return {
35940
36055
  state,
35941
- dir: path107.join(".metaproject", "jobs", name),
36056
+ dir: path108.join(".metaproject", "jobs", name),
35942
36057
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
35943
36058
  stepsTotal: state.plan.steps.length,
35944
36059
  nextStep: firstOpenStep(state.plan.steps),
@@ -35995,23 +36110,23 @@ function createJobService(deps) {
35995
36110
  if (!input.file) {
35996
36111
  throw new Error("Missing --file. Usage: keryx job document <name> --type <type> --file <path>");
35997
36112
  }
35998
- const source = path107.isAbsolute(input.file) ? input.file : path107.join(input.cwd, input.file);
36113
+ const source = path108.isAbsolute(input.file) ? input.file : path108.join(input.cwd, input.file);
35999
36114
  if (!await pathExists(source)) {
36000
36115
  throw new Error(`--file not found: ${input.file}. Write the document first, then record it.`);
36001
36116
  }
36002
36117
  let recorded;
36003
36118
  await mutate(input.cwd, input.name, async (state) => {
36004
36119
  const fileName = documentFileName(type, source);
36005
- const target = path107.join(jobDir(input.cwd, state.job_name), fileName);
36120
+ const target = path108.join(jobDir(input.cwd, state.job_name), fileName);
36006
36121
  await copyFile(source, target);
36007
36122
  state.documentation ??= {};
36008
- state.documentation.job_path ??= path107.join(".metaproject", "jobs", state.job_name);
36123
+ state.documentation.job_path ??= path108.join(".metaproject", "jobs", state.job_name);
36009
36124
  const created = state.documentation.documents_created ?? [];
36010
36125
  state.documentation.documents_created = created.includes(fileName) ? created : [...created, fileName];
36011
36126
  recorded = {
36012
36127
  state,
36013
36128
  document: fileName,
36014
- path: path107.join(".metaproject", "jobs", state.job_name, fileName)
36129
+ path: path108.join(".metaproject", "jobs", state.job_name, fileName)
36015
36130
  };
36016
36131
  return { state, event: "document", detail: `${type} -> ${fileName}` };
36017
36132
  });
@@ -36046,7 +36161,7 @@ function createJobService(deps) {
36046
36161
  name: state.job_name,
36047
36162
  phase: state.phase,
36048
36163
  intent: state.intent,
36049
- dir: path107.join(".metaproject", "jobs", name),
36164
+ dir: path108.join(".metaproject", "jobs", name),
36050
36165
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
36051
36166
  stepsTotal: state.plan.steps.length,
36052
36167
  nextStep: firstOpenStep(state.plan.steps)?.id ?? null
@@ -36151,12 +36266,12 @@ function normalizeWorkspaceReference(raw) {
36151
36266
  // src/sac/fwk-service.ts
36152
36267
  init_assembly();
36153
36268
  import { appendFile as appendFile7, mkdir as mkdir32, open as open4, readFile as readFile55, rename as rename7, rm as rm6, stat as stat15, writeFile as writeFile22 } from "fs/promises";
36154
- import path111 from "path";
36269
+ import path112 from "path";
36155
36270
 
36156
36271
  // src/sac/index.ts
36157
36272
  import { access as access3, readFile as readFile53, realpath as realpath12 } from "fs/promises";
36158
36273
  import { createHash as createHash19 } from "crypto";
36159
- import path108 from "path";
36274
+ import path109 from "path";
36160
36275
  import { fileURLToPath as fileURLToPath3 } from "url";
36161
36276
  var idPattern = /^[a-z][a-z0-9-]{2,63}$/;
36162
36277
  var subjectPattern = /^(?:user|team|service|agent):[a-z0-9][a-z0-9._-]{0,127}$/;
@@ -36174,21 +36289,21 @@ var normativeSchemaFiles = {
36174
36289
  "review-decision": "review-decision.schema.json"
36175
36290
  };
36176
36291
  var normativeSchemas = new Map;
36177
- var NORMATIVE_SCHEMA_DIR = path108.join("docs", "requirements", "shared-agent-context", "schemas");
36292
+ var NORMATIVE_SCHEMA_DIR = path109.join("docs", "requirements", "shared-agent-context", "schemas");
36178
36293
  async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath3(new URL(".", import.meta.url)), process.cwd()]) {
36179
36294
  const seen = new Set;
36180
36295
  for (const start of searchFrom) {
36181
- let dir = path108.resolve(start);
36296
+ let dir = path109.resolve(start);
36182
36297
  for (let i = 0;i < 10; i++) {
36183
36298
  if (seen.has(dir))
36184
36299
  break;
36185
36300
  seen.add(dir);
36186
- const candidate = path108.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
36301
+ const candidate = path109.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
36187
36302
  try {
36188
36303
  await access3(candidate);
36189
36304
  return candidate;
36190
36305
  } catch {}
36191
- const parent = path108.dirname(dir);
36306
+ const parent = path109.dirname(dir);
36192
36307
  if (parent === dir)
36193
36308
  break;
36194
36309
  dir = parent;
@@ -36857,12 +36972,12 @@ class SacReferenceError extends Error {
36857
36972
  code = "unsafe_workspace_reference";
36858
36973
  }
36859
36974
  async function resolveWorkspaceReference(input) {
36860
- if (!workspacePathPattern.test(input.uri) || path108.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
36975
+ if (!workspacePathPattern.test(input.uri) || path109.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
36861
36976
  throw new SacReferenceError("unsafe workspace reference");
36862
- const lexicalRoot = path108.resolve(input.workspaceRoot);
36977
+ const lexicalRoot = path109.resolve(input.workspaceRoot);
36863
36978
  const root = await realpath12(lexicalRoot);
36864
- const candidate = path108.resolve(lexicalRoot, input.uri.slice(2));
36865
- if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path108.sep}`))
36979
+ const candidate = path109.resolve(lexicalRoot, input.uri.slice(2));
36980
+ if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path109.sep}`))
36866
36981
  throw new SacReferenceError("workspace reference escapes root");
36867
36982
  let resolved;
36868
36983
  try {
@@ -36870,7 +36985,7 @@ async function resolveWorkspaceReference(input) {
36870
36985
  } catch {
36871
36986
  throw new SacReferenceError("workspace reference is not resolvable");
36872
36987
  }
36873
- if (resolved !== root && !resolved.startsWith(`${root}${path108.sep}`))
36988
+ if (resolved !== root && !resolved.startsWith(`${root}${path109.sep}`))
36874
36989
  throw new SacReferenceError("workspace reference escapes root after realpath");
36875
36990
  return candidate;
36876
36991
  }
@@ -36926,16 +37041,16 @@ async function evaluateStrictSacGuard(input) {
36926
37041
  init_fs();
36927
37042
  import { mkdir as mkdir31, readdir as readdir18, readFile as readFile54 } from "fs/promises";
36928
37043
  import { createHash as createHash20, randomUUID as randomUUID3 } from "crypto";
36929
- import path110 from "path";
37044
+ import path111 from "path";
36930
37045
 
36931
37046
  // src/sac/secure-resource-read.ts
36932
37047
  init_contained_read();
36933
37048
  init_descriptor_read();
36934
- import path109 from "path";
37049
+ import path110 from "path";
36935
37050
  function readWorkspaceFileNoFollow(workspaceRoot, absolutePath) {
36936
- const relativePath = path109.relative(workspaceRoot, absolutePath);
36937
- const components = relativePath.split(path109.sep);
36938
- if (!relativePath || path109.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
37051
+ const relativePath = path110.relative(workspaceRoot, absolutePath);
37052
+ const components = relativePath.split(path110.sep);
37053
+ if (!relativePath || path110.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
36939
37054
  throw new Error("safe source path is not workspace-relative");
36940
37055
  }
36941
37056
  return readDescriptorChain(workspaceRoot, absolutePath, {
@@ -36962,8 +37077,8 @@ class WorkspaceService {
36962
37077
  now;
36963
37078
  constructor(options) {
36964
37079
  this.options = options;
36965
- this.root = path110.resolve(options.workspaceRoot);
36966
- this.storageRoot = path110.resolve(options.storageRoot ?? path110.join(this.root, ".metaproject", "workspaces"));
37080
+ this.root = path111.resolve(options.workspaceRoot);
37081
+ this.storageRoot = path111.resolve(options.storageRoot ?? path111.join(this.root, ".metaproject", "workspaces"));
36967
37082
  this.now = options.now ?? (() => new Date);
36968
37083
  }
36969
37084
  async create(input) {
@@ -37288,13 +37403,13 @@ class WorkspaceService {
37288
37403
  return parsed;
37289
37404
  }
37290
37405
  workspaceDir(id) {
37291
- return path110.join(this.storageRoot, id);
37406
+ return path111.join(this.storageRoot, id);
37292
37407
  }
37293
37408
  manifestPath(id) {
37294
- return path110.join(this.workspaceDir(id), "workspace.json");
37409
+ return path111.join(this.workspaceDir(id), "workspace.json");
37295
37410
  }
37296
37411
  lockPath(id) {
37297
- return path110.join(this.storageRoot, `.${id}.lock`);
37412
+ return path111.join(this.storageRoot, `.${id}.lock`);
37298
37413
  }
37299
37414
  timestamp() {
37300
37415
  return this.now().toISOString();
@@ -38083,7 +38198,7 @@ function hasReportIntegrity(report) {
38083
38198
  return reportHashPattern.test(reportDigest) && sha2565(body) === reportDigest;
38084
38199
  }
38085
38200
  async function resolvePolicySelection(workspaceRoot, canonicalFallback) {
38086
- const configPath = path111.join(workspaceRoot, ...policyExperimentConfigPath);
38201
+ const configPath = path112.join(workspaceRoot, ...policyExperimentConfigPath);
38087
38202
  let configJson;
38088
38203
  try {
38089
38204
  const raw = await readFile55(configPath, "utf8").catch((error) => {
@@ -38281,9 +38396,9 @@ class FwkReadService {
38281
38396
  const recordedAt = nowIso(now);
38282
38397
  const id = `receipt-${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
38283
38398
  const base = { schemaVersion: "1.0", id, workspaceId, actor, action, decision, recordedAt, cost: { tokens: 0, toolCalls: 1, elapsedMs: 0 }, contextAssembly: { traceRef: assembly.traceRef, configurationRevision: assembly.configurationRevision, selected: assembly.selected.map((id) => `./ids/${id}`), omittedOptional: assembly.omittedOptional.map((id) => `./ids/${id}`) }, policy: { ref: assembly.policyRef, revision: assembly.policyRevision }, ...action === "resource" ? { resourceRef: `./ids/${resourceId ?? "unknown"}` } : {} };
38284
- const ledger = path111.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
38285
- const checkpointPath = path111.join(path111.dirname(ledger), "access-receipts.checkpoint.json");
38286
- await mkdir32(path111.dirname(ledger), { recursive: true, mode: 448 });
38399
+ const ledger = path112.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
38400
+ const checkpointPath = path112.join(path112.dirname(ledger), "access-receipts.checkpoint.json");
38401
+ await mkdir32(path112.dirname(ledger), { recursive: true, mode: 448 });
38287
38402
  return withFileLock(`${ledger}.lock`, async () => {
38288
38403
  const state = await resolveLedgerState(ledger, checkpointPath, this.options.verifyReceiptLedger ?? verifyAccessReceiptLedger);
38289
38404
  const receipt = sealAccessReceipt(base, state.headHash);
@@ -38387,7 +38502,7 @@ function normalizeFwkResult(result) {
38387
38502
  init_fs();
38388
38503
  import { createHash as createHash30, randomUUID as randomUUID7 } from "crypto";
38389
38504
  import { appendFile as appendFile8, mkdir as mkdir35, readdir as readdir21, readFile as readFile64 } from "fs/promises";
38390
- import path121 from "path";
38505
+ import path122 from "path";
38391
38506
 
38392
38507
  // src/sac/trusted-wrap-up.ts
38393
38508
  import { createHash as createHash24, randomUUID as randomUUID5 } from "crypto";
@@ -38459,7 +38574,7 @@ function bindingHash(owner, intent) {
38459
38574
  // src/sac/session-wrap-up.ts
38460
38575
  import { createHash as createHash26 } from "crypto";
38461
38576
  import { mkdir as mkdir34, writeFile as writeFile23 } from "fs/promises";
38462
- import path115 from "path";
38577
+ import path116 from "path";
38463
38578
 
38464
38579
  // src/session/store.ts
38465
38580
  init_config_dir();
@@ -38471,12 +38586,12 @@ import {
38471
38586
  renameSync as renameSync2,
38472
38587
  writeFileSync as writeFileSync2
38473
38588
  } from "fs";
38474
- import path114 from "path";
38589
+ import path115 from "path";
38475
38590
 
38476
38591
  // src/session/paths.ts
38477
38592
  import { existsSync as existsSync16 } from "fs";
38478
38593
  import { homedir } from "os";
38479
- import path112 from "path";
38594
+ import path113 from "path";
38480
38595
  function keryxDataDir(override) {
38481
38596
  if (override !== undefined && override.length > 0) {
38482
38597
  return override;
@@ -38488,22 +38603,22 @@ function keryxDataDir(override) {
38488
38603
  const home = homedir();
38489
38604
  if (process.platform === "win32") {
38490
38605
  const appData = process.env.APPDATA;
38491
- const base = appData !== undefined && appData.length > 0 ? appData : path112.join(home, "AppData", "Roaming");
38492
- return path112.join(base, "keryx");
38606
+ const base = appData !== undefined && appData.length > 0 ? appData : path113.join(home, "AppData", "Roaming");
38607
+ return path113.join(base, "keryx");
38493
38608
  }
38494
38609
  const xdg = process.env.XDG_DATA_HOME;
38495
- const base = xdg !== undefined && xdg.length > 0 ? xdg : path112.join(home, ".local", "share");
38496
- return path112.join(base, "keryx");
38610
+ const base = xdg !== undefined && xdg.length > 0 ? xdg : path113.join(home, ".local", "share");
38611
+ return path113.join(base, "keryx");
38497
38612
  }
38498
38613
  function resolveProjectRoot2(cwd) {
38499
- const abs = path112.resolve(cwd);
38614
+ const abs = path113.resolve(cwd);
38500
38615
  let dir = abs;
38501
38616
  for (;; ) {
38502
- const gitPath = path112.join(dir, ".git");
38617
+ const gitPath = path113.join(dir, ".git");
38503
38618
  if (existsSync16(gitPath)) {
38504
38619
  return dir;
38505
38620
  }
38506
- const parent = path112.dirname(dir);
38621
+ const parent = path113.dirname(dir);
38507
38622
  if (parent === dir) {
38508
38623
  break;
38509
38624
  }
@@ -38512,12 +38627,12 @@ function resolveProjectRoot2(cwd) {
38512
38627
  return abs;
38513
38628
  }
38514
38629
  function projectKeyFromPath(projectPath) {
38515
- const abs = path112.resolve(projectPath);
38630
+ const abs = path113.resolve(projectPath);
38516
38631
  const encoded = encodeURIComponent(abs);
38517
38632
  if (encoded.length <= 200) {
38518
38633
  return encoded;
38519
38634
  }
38520
- const base = path112.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
38635
+ const base = path113.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
38521
38636
  let h = 0;
38522
38637
  for (let i = 0;i < abs.length; i++) {
38523
38638
  h = Math.imul(31, h) + abs.charCodeAt(i) | 0;
@@ -38527,17 +38642,17 @@ function projectKeyFromPath(projectPath) {
38527
38642
  }
38528
38643
  function projectSessionsDir(projectPath, dataDir) {
38529
38644
  const key = projectKeyFromPath(resolveProjectRoot2(projectPath));
38530
- return path112.join(keryxDataDir(dataDir), "sessions", key);
38645
+ return path113.join(keryxDataDir(dataDir), "sessions", key);
38531
38646
  }
38532
38647
  function sessionDir(projectPath, sessionId, dataDir) {
38533
- return path112.join(projectSessionsDir(projectPath, dataDir), sessionId);
38648
+ return path113.join(projectSessionsDir(projectPath, dataDir), sessionId);
38534
38649
  }
38535
38650
 
38536
38651
  // src/session/slate.ts
38537
38652
  init_fs();
38538
38653
  init_assembly();
38539
38654
  import { mkdir as mkdir33, readFile as readFile56, readdir as readdir19, rm as rm7, stat as stat16 } from "fs/promises";
38540
- import path113 from "path";
38655
+ import path114 from "path";
38541
38656
  init_redact();
38542
38657
  var SLATE_SEED_KINDS = [
38543
38658
  "decision",
@@ -38552,7 +38667,7 @@ function isSlateSeedKind(value) {
38552
38667
  }
38553
38668
  var SEED_TEXT_MAX_LENGTH = 4000;
38554
38669
  function slatePath(dir) {
38555
- return path113.join(dir, "slate.json");
38670
+ return path114.join(dir, "slate.json");
38556
38671
  }
38557
38672
  function slateLockPath(dir) {
38558
38673
  return `${slatePath(dir)}.lock`;
@@ -38782,11 +38897,11 @@ function listSessions(cwd, dataDir) {
38782
38897
  if (name.startsWith(".")) {
38783
38898
  continue;
38784
38899
  }
38785
- const summary = readSummaryFile(path114.join(root, name, "summary.json"));
38900
+ const summary = readSummaryFile(path115.join(root, name, "summary.json"));
38786
38901
  if (summary === undefined) {
38787
38902
  continue;
38788
38903
  }
38789
- if (path114.resolve(summary.projectPath) !== path114.resolve(projectPath)) {
38904
+ if (path115.resolve(summary.projectPath) !== path115.resolve(projectPath)) {
38790
38905
  continue;
38791
38906
  }
38792
38907
  out.push(summary);
@@ -38819,15 +38934,15 @@ async function readSessionSlate(cwd, sessionId, dataDir) {
38819
38934
  }
38820
38935
  function loadContext(cwd, sessionId, dataDir) {
38821
38936
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
38822
- const contextPath = path114.join(dir, "context.jsonl");
38937
+ const contextPath = path115.join(dir, "context.jsonl");
38823
38938
  if (existsSync17(contextPath)) {
38824
38939
  return readJsonl2(contextPath);
38825
38940
  }
38826
- return readJsonl2(path114.join(dir, "transcript.jsonl"));
38941
+ return readJsonl2(path115.join(dir, "transcript.jsonl"));
38827
38942
  }
38828
38943
  function loadArchive(cwd, sessionId, dataDir, onDegraded) {
38829
38944
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
38830
- const archivePath = path114.join(dir, "archive.jsonl");
38945
+ const archivePath = path115.join(dir, "archive.jsonl");
38831
38946
  if (existsSync17(archivePath)) {
38832
38947
  try {
38833
38948
  const archive = readJsonl2(archivePath);
@@ -39011,7 +39126,7 @@ function sessionEvidenceRef(workspaceId, sessionId) {
39011
39126
  }
39012
39127
  async function resolveSessionWrapUp(input) {
39013
39128
  const now = input.now ?? (() => new Date);
39014
- const sessionId = path115.posix.basename(input.sourceRef, ".md");
39129
+ const sessionId = path116.posix.basename(input.sourceRef, ".md");
39015
39130
  const summary = findSession(input.cwd, sessionId);
39016
39131
  if (summary === undefined || input.sourceRef !== sessionEvidenceRef(input.workspaceId, summary.id)) {
39017
39132
  throw new SessionWrapUpError("session_not_found", `no session matching "${input.sourceRef}" in this project \u2014 use \`keryx sessions list\``);
@@ -39028,7 +39143,7 @@ async function resolveSessionWrapUp(input) {
39028
39143
  throw new SessionWrapUpError("session_unreadable", `session "${summary.id}" could not be read: ${cause.message}`);
39029
39144
  }
39030
39145
  const relPath = sessionEvidenceRef(input.workspaceId, summary.id).slice(2);
39031
- const evidenceDir = path115.dirname(relPath);
39146
+ const evidenceDir = path116.dirname(relPath);
39032
39147
  const slate = await readSessionSlate(input.cwd, summary.id);
39033
39148
  const diff = await gitDiff(input.cwd);
39034
39149
  const diffBody = diff.kind === "measured" ? diff.text : unmeasurableDiffBody(diff.detail);
@@ -39050,23 +39165,23 @@ async function resolveSessionWrapUp(input) {
39050
39165
  ""
39051
39166
  ].join(`
39052
39167
  `);
39053
- const wrapUpRelPath = path115.join(evidenceDir, `${summary.id}.wrap-up.md`);
39054
- const diffRelPath = path115.join(evidenceDir, `${summary.id}.diff.txt`);
39055
- const noticeRelPath = path115.join(evidenceDir, `${summary.id}.redaction.md`);
39168
+ const wrapUpRelPath = path116.join(evidenceDir, `${summary.id}.wrap-up.md`);
39169
+ const diffRelPath = path116.join(evidenceDir, `${summary.id}.diff.txt`);
39170
+ const noticeRelPath = path116.join(evidenceDir, `${summary.id}.redaction.md`);
39056
39171
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
39057
- { name: path115.basename(relPath), content: markdown, path: relPath, source: "generated" },
39058
- { name: path115.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
39059
- { name: path115.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
39172
+ { name: path116.basename(relPath), content: markdown, path: relPath, source: "generated" },
39173
+ { name: path116.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
39174
+ { name: path116.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
39060
39175
  ]);
39061
39176
  if (!floor.ok)
39062
39177
  throw new SessionWrapUpError("security_denied", floor.reason);
39063
39178
  const [safeSession, safeWrapUp, safeDiff] = floor.bodies;
39064
- await mkdir34(path115.join(input.cwd, evidenceDir), { recursive: true });
39065
- await writeFile23(path115.join(input.cwd, relPath), safeSession.content, "utf8");
39066
- await writeFile23(path115.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
39067
- await writeFile23(path115.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
39179
+ await mkdir34(path116.join(input.cwd, evidenceDir), { recursive: true });
39180
+ await writeFile23(path116.join(input.cwd, relPath), safeSession.content, "utf8");
39181
+ await writeFile23(path116.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
39182
+ await writeFile23(path116.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
39068
39183
  if (floor.notice !== undefined)
39069
- await writeFile23(path115.join(input.cwd, noticeRelPath), floor.notice, "utf8");
39184
+ await writeFile23(path116.join(input.cwd, noticeRelPath), floor.notice, "utf8");
39070
39185
  const observedAt = now().toISOString();
39071
39186
  const evidence = [
39072
39187
  { kind: "wrap-up", uri: `./${wrapUpRelPath}`, revision: createHash26("sha256").update(safeWrapUp.content).digest("hex"), observedAt },
@@ -39089,13 +39204,13 @@ async function resolveSessionWrapUp(input) {
39089
39204
  init_fs();
39090
39205
  import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
39091
39206
  import { readFile as readFile57 } from "fs/promises";
39092
- import path116 from "path";
39207
+ import path117 from "path";
39093
39208
  var CONFIRM_TOKEN_TTL_MS = 2 * 60000;
39094
39209
  function confirmTokenPath2(cwd, workspaceId, proposalId) {
39095
- return path116.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
39210
+ return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
39096
39211
  }
39097
39212
  function confirmReceiptPath(cwd, workspaceId, proposalId, idempotencyKey) {
39098
- return path116.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2566(idempotencyKey)}.confirm-receipt.json`);
39213
+ return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2566(idempotencyKey)}.confirm-receipt.json`);
39099
39214
  }
39100
39215
  function sha2566(text) {
39101
39216
  return createHash27("sha256").update(text).digest("hex");
@@ -39136,21 +39251,21 @@ init_store();
39136
39251
  init_config();
39137
39252
  import { readFile as readFile59, readdir as readdir20 } from "fs/promises";
39138
39253
  import { randomUUID as randomUUID6 } from "crypto";
39139
- import path118 from "path";
39254
+ import path119 from "path";
39140
39255
 
39141
39256
  // src/sac/proposal-evidence.ts
39142
39257
  init_fs();
39143
39258
  import { createHash as createHash28 } from "crypto";
39144
39259
  import { readFile as readFile58, rm as rm8 } from "fs/promises";
39145
- import path117 from "path";
39260
+ import path118 from "path";
39146
39261
  function proposalPath(cwd, workspaceId, proposalId) {
39147
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
39262
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
39148
39263
  }
39149
39264
  function ownerReceiptPath(cwd, owner, workspaceId, idempotencyKey) {
39150
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
39265
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
39151
39266
  }
39152
39267
  function proposalNotePath(cwd, workspaceId, proposalId) {
39153
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
39268
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
39154
39269
  }
39155
39270
  async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
39156
39271
  let proposal;
@@ -39164,7 +39279,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
39164
39279
  return { ok: false, code: "no_evidence_to_write" };
39165
39280
  let content;
39166
39281
  try {
39167
- content = await readFile58(path117.join(cwd, evidence.uri), "utf8");
39282
+ content = await readFile58(path118.join(cwd, evidence.uri), "utf8");
39168
39283
  } catch {
39169
39284
  return { ok: false, code: "evidence_file_unreadable" };
39170
39285
  }
@@ -39194,22 +39309,22 @@ function targetRelPath(targetRef) {
39194
39309
  return targetRef.replace(/^\.\//, "");
39195
39310
  }
39196
39311
  function targetAbsolutePath(cwd, targetRef) {
39197
- return path117.join(cwd, ".metaproject", targetRelPath(targetRef));
39312
+ return path118.join(cwd, ".metaproject", targetRelPath(targetRef));
39198
39313
  }
39199
39314
  function targetKey(targetRef) {
39200
39315
  return digestOf2(targetRelPath(targetRef)).slice(0, 32);
39201
39316
  }
39202
39317
  function ownerTargetVersionPath(cwd, owner, workspaceId, targetRef) {
39203
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
39318
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
39204
39319
  }
39205
39320
  function ownerTargetLockPath(cwd, owner, targetRef) {
39206
- return path117.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
39321
+ return path118.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
39207
39322
  }
39208
39323
  function ownerStagingDir(cwd, owner, workspaceId, idempotencyKey) {
39209
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
39324
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
39210
39325
  }
39211
39326
  function ownerConflictDir(cwd, owner, workspaceId, idempotencyKey) {
39212
- return path117.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
39327
+ return path118.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
39213
39328
  }
39214
39329
  async function readJson2(file) {
39215
39330
  try {
@@ -39280,7 +39395,7 @@ async function applyGuardedTargetWrite(input) {
39280
39395
  staged: input.staged,
39281
39396
  stagedAt: receipt.completedAt
39282
39397
  };
39283
- await writeFileAtomic(path117.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
39398
+ await writeFileAtomic(path118.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
39284
39399
  `);
39285
39400
  const applied = await input.apply(input.staged);
39286
39401
  if (!applied.ok) {
@@ -39306,15 +39421,15 @@ async function recoverStagedOwnerWrite(input) {
39306
39421
  });
39307
39422
  }
39308
39423
  async function readStagedOwnerWrite(cwd, owner, workspaceId, idempotencyKey) {
39309
- return readJson2(path117.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
39424
+ return readJson2(path118.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
39310
39425
  }
39311
39426
  async function recordConflict(input) {
39312
39427
  const base = { targetRef: input.targetRef, expectedVersion: input.expectedVersion, currentVersion: input.currentVersion };
39313
39428
  if (input.proposedContent === undefined)
39314
39429
  return base;
39315
39430
  const dir = ownerConflictDir(input.cwd, input.owner, input.intent.workspaceId, input.intent.idempotencyKey);
39316
- await writeFileAtomic(path117.join(dir, "proposed"), input.proposedContent);
39317
- const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path117.basename(dir)}/proposed`;
39431
+ await writeFileAtomic(path118.join(dir, "proposed"), input.proposedContent);
39432
+ const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path118.basename(dir)}/proposed`;
39318
39433
  return { ...base, diffRef };
39319
39434
  }
39320
39435
 
@@ -39364,7 +39479,7 @@ async function resolveWorkspaceModule(cwd, workspaceId) {
39364
39479
  }
39365
39480
  }
39366
39481
  async function collectWikiDecisionEntries(cwd) {
39367
- const dir = path118.join(cwd, ".metaproject", "wiki", "decisions");
39482
+ const dir = path119.join(cwd, ".metaproject", "wiki", "decisions");
39368
39483
  let files;
39369
39484
  try {
39370
39485
  files = (await readdir20(dir)).filter((name) => name.endsWith(".md"));
@@ -39373,12 +39488,12 @@ async function collectWikiDecisionEntries(cwd) {
39373
39488
  }
39374
39489
  const entries = [];
39375
39490
  for (const file of files) {
39376
- const absolutePath = path118.join(dir, file);
39491
+ const absolutePath = path119.join(dir, file);
39377
39492
  try {
39378
39493
  const content = await readFile59(absolutePath, "utf8");
39379
39494
  entries.push({
39380
39495
  absolutePath,
39381
- relativePath: path118.posix.join("decisions", file),
39496
+ relativePath: path119.posix.join("decisions", file),
39382
39497
  type: extractHeaderField(content, "Type") ?? "decision",
39383
39498
  title: extractTitle(content),
39384
39499
  version: extractHeaderField(content, "Version") ?? null,
@@ -39600,7 +39715,7 @@ function createRealMemoryOwnerWriter(cwd, opts) {
39600
39715
  init_service4();
39601
39716
  init_guard();
39602
39717
  import { readFile as readFile61 } from "fs/promises";
39603
- import path119 from "path";
39718
+ import path120 from "path";
39604
39719
  function renderWrapUpDecisionPage(input) {
39605
39720
  const note = input.note?.trim();
39606
39721
  return `# ${input.title}
@@ -39641,7 +39756,7 @@ export is the source of truth for what actually happened.
39641
39756
  `;
39642
39757
  }
39643
39758
  function wikiPageRelativePath(proposalId) {
39644
- return path119.posix.join("decisions", `sac-${proposalId}.md`);
39759
+ return path120.posix.join("decisions", `sac-${proposalId}.md`);
39645
39760
  }
39646
39761
  function createRealWikiOwnerWriter(cwd, opts) {
39647
39762
  const now = opts?.now ?? (() => new Date);
@@ -39649,7 +39764,7 @@ function createRealWikiOwnerWriter(cwd, opts) {
39649
39764
  const relativePath = staged.relativePath;
39650
39765
  const content = staged.content;
39651
39766
  const history = await openWikiWriteContext(cwd, "sac proposal accept");
39652
- await writeWikiPage(history, path119.join(cwd, ".metaproject", "wiki", relativePath), content);
39767
+ await writeWikiPage(history, path120.join(cwd, ".metaproject", "wiki", relativePath), content);
39653
39768
  return { ok: true };
39654
39769
  };
39655
39770
  return {
@@ -39719,7 +39834,7 @@ init_guard();
39719
39834
  import { createHash as createHash29 } from "crypto";
39720
39835
  import { homedir as homedir2 } from "os";
39721
39836
  import { readFile as readFile62, stat as stat17 } from "fs/promises";
39722
- import path120 from "path";
39837
+ import path121 from "path";
39723
39838
  var VERSION = "0.1.0";
39724
39839
  var PROJECT_SKILLS_DIR = ".metaproject/project-skills";
39725
39840
  var PROJECT_SKILLS_MANIFEST_PATH = ".metaproject/metaproject.json";
@@ -39749,7 +39864,7 @@ async function assertProjectWritesContained(projectRoot, paths) {
39749
39864
  }
39750
39865
  }
39751
39866
  async function createProjectSkill(projectRoot, options) {
39752
- const metaprojectRoot = path120.join(projectRoot, ".metaproject");
39867
+ const metaprojectRoot = path121.join(projectRoot, ".metaproject");
39753
39868
  if (!await pathExists(metaprojectRoot)) {
39754
39869
  throw new Error("Metaproject is not initialized. Run: keryx init");
39755
39870
  }
@@ -39760,7 +39875,7 @@ async function createProjectSkill(projectRoot, options) {
39760
39875
  const skillName = projectSkillSlug(options.name ?? inferSkillName(options.target));
39761
39876
  const format = options.format ?? "auto";
39762
39877
  const relativeSkillPath = projectSkillPackagePath(moduleName, skillName);
39763
- const packageRoot = path120.join(projectRoot, relativeSkillPath);
39878
+ const packageRoot = path121.join(projectRoot, relativeSkillPath);
39764
39879
  await assertProjectWritesContained(projectRoot, projectSkillWritePaths(moduleName, skillName, format));
39765
39880
  const origin = options.origin ? options.originContent !== undefined ? {
39766
39881
  ref: options.origin.trim(),
@@ -39771,7 +39886,7 @@ async function createProjectSkill(projectRoot, options) {
39771
39886
  const warnings = collectWarnings(evidence, format);
39772
39887
  const files = filesForPackage(packageRoot, format);
39773
39888
  if (!options.dryRun) {
39774
- await withFileLock(path120.join(projectRoot, PROJECT_SKILLS_LOCK_PATH), async () => {
39889
+ await withFileLock(path121.join(projectRoot, PROJECT_SKILLS_LOCK_PATH), async () => {
39775
39890
  await writeProjectSkillPackage({
39776
39891
  projectRoot,
39777
39892
  packageRoot,
@@ -39800,7 +39915,7 @@ async function createProjectSkill(projectRoot, options) {
39800
39915
  name: skillName,
39801
39916
  target: options.target,
39802
39917
  skillPath: relativeSkillPath,
39803
- files: files.map((filePath) => toPosix(path120.relative(projectRoot, filePath))),
39918
+ files: files.map((filePath) => toPosix(path121.relative(projectRoot, filePath))),
39804
39919
  warnings,
39805
39920
  dryRun: options.dryRun === true
39806
39921
  };
@@ -39809,9 +39924,9 @@ var MAX_SKILL_TARGET_LENGTH = 80;
39809
39924
  function resolveOriginPath(ref, projectRoot) {
39810
39925
  const trimmed = ref.trim();
39811
39926
  if (trimmed === "~" || trimmed.startsWith("~/")) {
39812
- return path120.join(homedir2(), trimmed.slice(1));
39927
+ return path121.join(homedir2(), trimmed.slice(1));
39813
39928
  }
39814
- return path120.resolve(projectRoot, trimmed);
39929
+ return path121.resolve(projectRoot, trimmed);
39815
39930
  }
39816
39931
  function hashOriginContent(content) {
39817
39932
  return `sha256:${createHash29("sha256").update(content).digest("hex")}`;
@@ -39849,16 +39964,16 @@ async function writeProjectSkillPackage({
39849
39964
  }) {
39850
39965
  const packageFormat = format === "single" ? "single" : "package";
39851
39966
  const skillContent = renderProjectSkill({ moduleName, skillName, target, note, origin, evidence, packageFormat });
39852
- const relativeSkillMdPath = toPosix(path120.join(path120.relative(projectRoot, packageRoot), "SKILL.md"));
39967
+ const relativeSkillMdPath = toPosix(path121.join(path121.relative(projectRoot, packageRoot), "SKILL.md"));
39853
39968
  const guard = await guardOutput({ cwd: projectRoot, content: skillContent, target: "skill", source: "generated", path: relativeSkillMdPath });
39854
39969
  const output = prepareOutputForPersistence(guard, skillContent);
39855
39970
  if (!output.allowed) {
39856
39971
  throw new Error(`Project skill blocked by the security gate: ${output.reason}`);
39857
39972
  }
39858
- const packageRel = toPosix(path120.relative(projectRoot, packageRoot));
39973
+ const packageRel = toPosix(path121.relative(projectRoot, packageRoot));
39859
39974
  const write = (file, content) => writeContained(projectRoot, `${packageRel}/${file}`, content);
39860
39975
  await write("SKILL.md", output.content);
39861
- if (!await pathExists(path120.join(packageRoot, "skill-changelog.md"))) {
39976
+ if (!await pathExists(path121.join(packageRoot, "skill-changelog.md"))) {
39862
39977
  await write("skill-changelog.md", renderSkillChangelog({ moduleName, skillName, target }));
39863
39978
  }
39864
39979
  if (packageFormat === "package") {
@@ -39868,10 +39983,10 @@ async function writeProjectSkillPackage({
39868
39983
  }
39869
39984
  }
39870
39985
  async function collectEvidence(projectRoot, target) {
39871
- const absoluteTarget = path120.resolve(projectRoot, target);
39986
+ const absoluteTarget = path121.resolve(projectRoot, target);
39872
39987
  const targetExists = await pathExists(absoluteTarget);
39873
39988
  const targetKind = await classifyTarget(absoluteTarget, targetExists);
39874
- const maybeRelativeTarget = targetExists ? toPosix(path120.relative(projectRoot, absoluteTarget)) : undefined;
39989
+ const maybeRelativeTarget = targetExists ? toPosix(path121.relative(projectRoot, absoluteTarget)) : undefined;
39875
39990
  const graphArtifacts = await existingRelativePaths(projectRoot, [
39876
39991
  ".metaproject/data/gdgraph/artifacts/summary.md",
39877
39992
  ".metaproject/data/gdgraph/artifacts/module-map.json"
@@ -39901,7 +40016,7 @@ async function classifyTarget(absoluteTarget, targetExists) {
39901
40016
  async function existingRelativePaths(projectRoot, candidates) {
39902
40017
  const existing = [];
39903
40018
  for (const candidate of candidates) {
39904
- if (await pathExists(path120.join(projectRoot, candidate))) {
40019
+ if (await pathExists(path121.join(projectRoot, candidate))) {
39905
40020
  existing.push(candidate);
39906
40021
  }
39907
40022
  }
@@ -39928,17 +40043,17 @@ function collectWarnings(evidence, format) {
39928
40043
  }
39929
40044
  function filesForPackage(packageRoot, format) {
39930
40045
  const base = [
39931
- path120.join(packageRoot, "SKILL.md"),
39932
- path120.join(packageRoot, "skill-changelog.md")
40046
+ path121.join(packageRoot, "SKILL.md"),
40047
+ path121.join(packageRoot, "skill-changelog.md")
39933
40048
  ];
39934
40049
  if (format === "single") {
39935
40050
  return base;
39936
40051
  }
39937
40052
  return [
39938
40053
  ...base,
39939
- path120.join(packageRoot, "verification.md"),
39940
- path120.join(packageRoot, "references", "context.md"),
39941
- path120.join(packageRoot, "templates", "README.md")
40054
+ path121.join(packageRoot, "verification.md"),
40055
+ path121.join(packageRoot, "references", "context.md"),
40056
+ path121.join(packageRoot, "templates", "README.md")
39942
40057
  ];
39943
40058
  }
39944
40059
  function renderProjectSkill({
@@ -40166,7 +40281,7 @@ keryx skills verify ${moduleName}/${skillName}
40166
40281
  `;
40167
40282
  }
40168
40283
  async function updateManifest(projectRoot, entry) {
40169
- const manifestPath = path120.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
40284
+ const manifestPath = path121.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
40170
40285
  const manifest = await readJsonFileOr(manifestPath, {});
40171
40286
  manifest.modules ??= {};
40172
40287
  manifest.modules.gdskills ??= {};
@@ -40180,8 +40295,8 @@ async function updateManifest(projectRoot, entry) {
40180
40295
  `);
40181
40296
  }
40182
40297
  async function updateSkillsCatalog(projectRoot) {
40183
- const manifestPath = path120.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
40184
- const catalogPath = path120.join(projectRoot, PROJECT_SKILLS_CATALOG_PATH);
40298
+ const manifestPath = path121.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
40299
+ const catalogPath = path121.join(projectRoot, PROJECT_SKILLS_CATALOG_PATH);
40185
40300
  const manifest = await readJsonFileOr(manifestPath, {});
40186
40301
  const registry = manifest.modules?.gdskills?.projectSkillRegistry ?? [];
40187
40302
  const rows = registry.length > 0 ? registry.map(projectSkillCatalogRow).join(`
@@ -40221,7 +40336,7 @@ function inferModule(target) {
40221
40336
  }
40222
40337
  function inferSkillName(target) {
40223
40338
  const normalized = target.trim().replace(/[#:]+/g, "/");
40224
- const base = path120.basename(normalized).replace(/\.[^.]+$/, "");
40339
+ const base = path121.basename(normalized).replace(/\.[^.]+$/, "");
40225
40340
  return base || "entity";
40226
40341
  }
40227
40342
  function projectSkillSlug(value) {
@@ -40326,7 +40441,7 @@ class ProposalLifecycleService {
40326
40441
  now;
40327
40442
  constructor(options) {
40328
40443
  this.options = options;
40329
- this.root = path121.resolve(options.workspaceRoot);
40444
+ this.root = path122.resolve(options.workspaceRoot);
40330
40445
  this.now = options.now ?? (() => new Date);
40331
40446
  }
40332
40447
  async create(input) {
@@ -40345,7 +40460,7 @@ class ProposalLifecycleService {
40345
40460
  if (manifest.status === "archived")
40346
40461
  throw new ProposalLifecycleError("guard_denied", "workspace is archived");
40347
40462
  const file = this.proposalPath(workspaceId, proposal.id);
40348
- await mkdir35(path121.dirname(file), { recursive: true, mode: 448 });
40463
+ await mkdir35(path122.dirname(file), { recursive: true, mode: 448 });
40349
40464
  return withFileLock(`${file}.lock`, async () => {
40350
40465
  const consume = this.options.wrapUpAuthority.consume(input.wrapUp, { actor, workspaceId });
40351
40466
  if (consume !== "ok")
@@ -40373,7 +40488,7 @@ class ProposalLifecycleService {
40373
40488
  return this.options.workspaces.withAuthorizedActor({ actorContext: actor, workspaceId: input.workspaceId, action: "review", execute: async (manifest) => {
40374
40489
  const proposal = await this.loadProposal(input.workspaceId, input.proposalId);
40375
40490
  const ledger = this.ledgerPath(input.workspaceId);
40376
- await mkdir35(path121.dirname(ledger), { recursive: true, mode: 448 });
40491
+ await mkdir35(path122.dirname(ledger), { recursive: true, mode: 448 });
40377
40492
  return withFileLock(`${ledger}.lock`, async () => {
40378
40493
  const records = (await this.records(ledger)).filter((record) => record.proposalId === proposal.id);
40379
40494
  const events = records.filter((record) => record.recordType === "proposal-transition");
@@ -40415,7 +40530,7 @@ class ProposalLifecycleService {
40415
40530
  } });
40416
40531
  }
40417
40532
  async listProposedProposals(workspaceId) {
40418
- const proposalsDir = path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
40533
+ const proposalsDir = path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
40419
40534
  let entries;
40420
40535
  try {
40421
40536
  entries = (await readdir21(proposalsDir)).filter((name) => name.endsWith(".json"));
@@ -40427,7 +40542,7 @@ class ProposalLifecycleService {
40427
40542
  const proposals = [];
40428
40543
  for (const entry of entries) {
40429
40544
  try {
40430
- const parsed = JSON.parse(await readFile64(path121.join(proposalsDir, entry), "utf8"));
40545
+ const parsed = JSON.parse(await readFile64(path122.join(proposalsDir, entry), "utf8"));
40431
40546
  if (parsed.recordType === "proposal-created")
40432
40547
  proposals.push(parsed);
40433
40548
  } catch {}
@@ -40693,31 +40808,31 @@ class ProposalLifecycleService {
40693
40808
  }
40694
40809
  }
40695
40810
  proposalPath(workspaceId, proposalId) {
40696
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
40811
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
40697
40812
  }
40698
40813
  decisionRef(proposalId, key) {
40699
40814
  return `./proposals/${proposalId}.${hash(key)}.decision.json`;
40700
40815
  }
40701
40816
  decisionPath(workspaceId, proposalId, key) {
40702
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
40817
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
40703
40818
  }
40704
40819
  approvalRef(proposalId, key) {
40705
40820
  return `./proposals/${proposalId}.${hash(key)}.approval.json`;
40706
40821
  }
40707
40822
  approvalPath(workspaceId, proposalId, key) {
40708
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
40823
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
40709
40824
  }
40710
40825
  writeResultPath(workspaceId, proposalId, key) {
40711
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
40826
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
40712
40827
  }
40713
40828
  intentRef(proposalId, key) {
40714
40829
  return `./proposals/${proposalId}.${hash(key)}.write-intent.json`;
40715
40830
  }
40716
40831
  intentPath(workspaceId, proposalId, key) {
40717
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
40832
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
40718
40833
  }
40719
40834
  attemptPath(workspaceId, proposalId, key) {
40720
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
40835
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
40721
40836
  }
40722
40837
  async loadWriteResult(workspaceId, proposalId, key) {
40723
40838
  try {
@@ -40744,7 +40859,7 @@ class ProposalLifecycleService {
40744
40859
  }
40745
40860
  }
40746
40861
  ledgerPath(workspaceId) {
40747
- return path121.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
40862
+ return path122.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
40748
40863
  }
40749
40864
  timestamp() {
40750
40865
  return this.now().toISOString();
@@ -40827,7 +40942,7 @@ function normalizeProposalLifecycleResult(value) {
40827
40942
  // src/sac/collaboration-service.ts
40828
40943
  import { appendFile as appendFile9, mkdir as mkdir36, readFile as readFile65 } from "fs/promises";
40829
40944
  import { randomUUID as randomUUID8 } from "crypto";
40830
- import path122 from "path";
40945
+ import path123 from "path";
40831
40946
  class CollaborationServiceError extends Error {
40832
40947
  code;
40833
40948
  constructor(code, message) {
@@ -40842,7 +40957,7 @@ class CollaborationService {
40842
40957
  this.input = input;
40843
40958
  }
40844
40959
  file(id) {
40845
- return path122.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
40960
+ return path123.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
40846
40961
  }
40847
40962
  async overview(input) {
40848
40963
  const manifest = await this.input.workspaces.show(input);
@@ -40879,7 +40994,7 @@ class CollaborationService {
40879
40994
  occurredAt: (this.input.now ?? (() => new Date))().toISOString(),
40880
40995
  ...suppliedHandoff ? { handoff: { ...suppliedHandoff, from: actor.subject } } : {}
40881
40996
  });
40882
- await mkdir36(path122.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
40997
+ await mkdir36(path123.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
40883
40998
  await appendFile9(this.file(manifest.id), `${JSON.stringify(activity)}
40884
40999
  `, { mode: 384 });
40885
41000
  return normalizeCollaborationResult(activity);
@@ -40929,13 +41044,13 @@ function normalizeCollaborationResult(value) {
40929
41044
  // src/session/external-slate.ts
40930
41045
  init_fs();
40931
41046
  import { mkdir as mkdir38, readdir as readdir22, readFile as readFile66 } from "fs/promises";
40932
- import path124 from "path";
41047
+ import path125 from "path";
40933
41048
 
40934
41049
  // src/sac/machine-wrap-up.ts
40935
41050
  init_fs();
40936
41051
  import { createHash as createHash31, randomUUID as randomUUID10 } from "crypto";
40937
41052
  import { mkdir as mkdir37 } from "fs/promises";
40938
- import path123 from "path";
41053
+ import path124 from "path";
40939
41054
 
40940
41055
  // src/sac/workspace-resolve.ts
40941
41056
  init_redact();
@@ -41076,11 +41191,11 @@ async function resolveMachineWrapUp(input) {
41076
41191
  `;
41077
41192
  const seedsJson = `${JSON.stringify(seedsForKind.map((seed) => ({ text: seed.text, source: describeSource(seed.source) })), null, 2)}
41078
41193
  `;
41079
- const evidenceRelBase = path123.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
41194
+ const evidenceRelBase = path124.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
41080
41195
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
41081
- { name: `${input.kind}.diff.txt`, content: diffBody, path: path123.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
41082
- { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path123.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
41083
- { name: `${input.kind}.seeds.json`, content: seedsJson, path: path123.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
41196
+ { name: `${input.kind}.diff.txt`, content: diffBody, path: path124.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
41197
+ { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path124.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
41198
+ { name: `${input.kind}.seeds.json`, content: seedsJson, path: path124.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
41084
41199
  ]);
41085
41200
  if (!floor.ok)
41086
41201
  return { ok: false, code: "security_denied", detail: floor.reason };
@@ -41134,14 +41249,14 @@ ${safeSeeds.content}`;
41134
41249
  }
41135
41250
  summary = result.text.trim().length > 0 ? result.text.trim() : mechanicalSummary(summaryDiff, course);
41136
41251
  }
41137
- const evidenceDir = path123.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
41252
+ const evidenceDir = path124.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
41138
41253
  await mkdir37(evidenceDir, { recursive: true });
41139
41254
  const diffFile = `${input.kind}.${shortHash}.diff.txt`;
41140
41255
  const flowFile = `${input.kind}.${shortHash}.flow.json`;
41141
41256
  const seedsFile = `${input.kind}.${shortHash}.seeds.json`;
41142
- await writeFileAtomic(path123.join(evidenceDir, diffFile), safeDiff.content);
41143
- await writeFileAtomic(path123.join(evidenceDir, flowFile), safeFlow.content);
41144
- await writeFileAtomic(path123.join(evidenceDir, seedsFile), safeSeeds.content);
41257
+ await writeFileAtomic(path124.join(evidenceDir, diffFile), safeDiff.content);
41258
+ await writeFileAtomic(path124.join(evidenceDir, flowFile), safeFlow.content);
41259
+ await writeFileAtomic(path124.join(evidenceDir, seedsFile), safeSeeds.content);
41145
41260
  const observedAt = now().toISOString();
41146
41261
  const relBase = `./.metaproject/workspaces/${input.workspaceId}/machine-evidence`;
41147
41262
  const evidence = [
@@ -41151,7 +41266,7 @@ ${safeSeeds.content}`;
41151
41266
  ];
41152
41267
  if (floor.notice !== undefined) {
41153
41268
  const noticeFile = `${input.kind}.${shortHash}.redaction.md`;
41154
- await writeFileAtomic(path123.join(evidenceDir, noticeFile), floor.notice);
41269
+ await writeFileAtomic(path124.join(evidenceDir, noticeFile), floor.notice);
41155
41270
  evidence.push({ kind: REDACTION_NOTICE_KIND, uri: `${relBase}/${noticeFile}`, revision: sha2567(floor.notice), observedAt });
41156
41271
  }
41157
41272
  return {
@@ -41170,18 +41285,18 @@ async function writeFlooredArchiveArtifact(params) {
41170
41285
  {
41171
41286
  name: params.filename,
41172
41287
  content: params.content,
41173
- path: path123.posix.join("slate-archive", params.filename),
41288
+ path: path124.posix.join("slate-archive", params.filename),
41174
41289
  source: "generated"
41175
41290
  }
41176
41291
  ]);
41177
41292
  if (!floor.ok)
41178
41293
  return { ok: false, code: "security_denied", detail: floor.reason };
41179
41294
  const body = floor.bodies[0];
41180
- const archiveDir = path123.join(params.dir, "slate-archive");
41295
+ const archiveDir = path124.join(params.dir, "slate-archive");
41181
41296
  await mkdir37(archiveDir, { recursive: true });
41182
- await writeFileAtomic(path123.join(archiveDir, params.filename), body.content);
41297
+ await writeFileAtomic(path124.join(archiveDir, params.filename), body.content);
41183
41298
  if (floor.notice !== undefined) {
41184
- await writeFileAtomic(path123.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
41299
+ await writeFileAtomic(path124.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
41185
41300
  }
41186
41301
  return { ok: true, altered: body.altered };
41187
41302
  }
@@ -41217,9 +41332,9 @@ async function writeWrapUpOutcomeArtifact(cwd, dir, trigger, now, groups) {
41217
41332
  return;
41218
41333
  const refusalIso = now().toISOString();
41219
41334
  const refusalFilename = `${refusalIso.replace(/[:.]/g, "-")}-wrap-up-outcome.json`;
41220
- const archiveDir = path123.join(dir, "slate-archive");
41335
+ const archiveDir = path124.join(dir, "slate-archive");
41221
41336
  await mkdir37(archiveDir, { recursive: true });
41222
- await writeFileAtomic(path123.join(archiveDir, refusalFilename), `${JSON.stringify({
41337
+ await writeFileAtomic(path124.join(archiveDir, refusalFilename), `${JSON.stringify({
41223
41338
  recordType: "wrap-up-outcome",
41224
41339
  trigger,
41225
41340
  generatedAt: refusalIso,
@@ -41355,7 +41470,7 @@ async function runWrapUp(input) {
41355
41470
 
41356
41471
  // src/session/external-slate.ts
41357
41472
  function externalSlatesDir(cwd) {
41358
- return path124.join(cwd, ".keryx", "external-slates");
41473
+ return path125.join(cwd, ".keryx", "external-slates");
41359
41474
  }
41360
41475
  var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
41361
41476
  function assertValidExternalSessionId(externalSessionId) {
@@ -41365,14 +41480,14 @@ function assertValidExternalSessionId(externalSessionId) {
41365
41480
  }
41366
41481
  function externalSlatePath(cwd, externalSessionId) {
41367
41482
  assertValidExternalSessionId(externalSessionId);
41368
- return path124.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
41483
+ return path125.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
41369
41484
  }
41370
41485
  function externalSlateLockPath(cwd, externalSessionId) {
41371
41486
  return `${externalSlatePath(cwd, externalSessionId)}.lock`;
41372
41487
  }
41373
41488
  function externalSlateEvidenceDir(cwd, externalSessionId) {
41374
41489
  assertValidExternalSessionId(externalSessionId);
41375
- return path124.join(externalSlatesDir(cwd), externalSessionId);
41490
+ return path125.join(externalSlatesDir(cwd), externalSessionId);
41376
41491
  }
41377
41492
  async function readExternalSlate(cwd, externalSessionId) {
41378
41493
  try {
@@ -41478,12 +41593,12 @@ __export(exports_service10, {
41478
41593
  runDoctor: () => runDoctor,
41479
41594
  runValidate: () => runValidate
41480
41595
  });
41481
- import path127 from "path";
41596
+ import path128 from "path";
41482
41597
  import { readFile as readFile69 } from "fs/promises";
41483
41598
 
41484
41599
  // src/standard/validate.ts
41485
41600
  init_fs();
41486
- import path126 from "path";
41601
+ import path127 from "path";
41487
41602
  import { readFile as readFile68 } from "fs/promises";
41488
41603
 
41489
41604
  // src/standard/schemas.ts
@@ -41613,7 +41728,7 @@ var SCHEMA_REGISTRY2 = {
41613
41728
  // src/standard/profiles.ts
41614
41729
  init_fs();
41615
41730
  init_entrypoint_targets();
41616
- import path125 from "path";
41731
+ import path126 from "path";
41617
41732
  import { readFile as readFile67 } from "fs/promises";
41618
41733
  var AGENT_MODULES = ["gdgraph", "gdctx", "gdskills", "gdwiki", "memory"];
41619
41734
  var CI_MODULES = ["health", "testing"];
@@ -41638,7 +41753,7 @@ function enabledModuleKeys(manifest) {
41638
41753
  }
41639
41754
  async function rootEntrypointLinksIndex(cwd, manifest) {
41640
41755
  for (const { path: name } of namedEntrypoints(manifest)) {
41641
- const filePath = path125.join(cwd, name);
41756
+ const filePath = path126.join(cwd, name);
41642
41757
  if (!await pathExists(filePath)) {
41643
41758
  continue;
41644
41759
  }
@@ -41650,16 +41765,16 @@ async function rootEntrypointLinksIndex(cwd, manifest) {
41650
41765
  return false;
41651
41766
  }
41652
41767
  async function minimalSatisfied(cwd) {
41653
- const metaprojectRoot = path125.join(cwd, ".metaproject");
41768
+ const metaprojectRoot = path126.join(cwd, ".metaproject");
41654
41769
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
41655
41770
  const requiredDirs = ["modules", "rules", "skills", "data"];
41656
41771
  for (const file of requiredFiles) {
41657
- if (!await pathExists(path125.join(metaprojectRoot, file))) {
41772
+ if (!await pathExists(path126.join(metaprojectRoot, file))) {
41658
41773
  return false;
41659
41774
  }
41660
41775
  }
41661
41776
  for (const dir of requiredDirs) {
41662
- if (!await pathExists(path125.join(metaprojectRoot, dir))) {
41777
+ if (!await pathExists(path126.join(metaprojectRoot, dir))) {
41663
41778
  return false;
41664
41779
  }
41665
41780
  }
@@ -41672,7 +41787,7 @@ async function ciSatisfied(cwd, manifest) {
41672
41787
  return false;
41673
41788
  }
41674
41789
  for (const key of ciModules) {
41675
- if (await pathExists(path125.join(cwd, ".metaproject", "data", key, "artifacts"))) {
41790
+ if (await pathExists(path126.join(cwd, ".metaproject", "data", key, "artifacts"))) {
41676
41791
  return true;
41677
41792
  }
41678
41793
  }
@@ -41685,7 +41800,7 @@ async function evaluateProfiles(cwd, manifest) {
41685
41800
  satisfied.push("minimal");
41686
41801
  }
41687
41802
  const hasAgentModule = AGENT_MODULES.some((key) => new Set(enabledModuleKeys(manifest)).has(key));
41688
- const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path125.join(cwd, ".metaproject", "rules"));
41803
+ const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path126.join(cwd, ".metaproject", "rules"));
41689
41804
  if (agent) {
41690
41805
  satisfied.push("agent");
41691
41806
  }
@@ -41854,20 +41969,20 @@ var MANIFEST_TOP_LEVEL_SCHEMA = {
41854
41969
  async function validateWorkspace2(cwd) {
41855
41970
  const errors = [];
41856
41971
  const warnings = [];
41857
- const metaprojectRoot = path126.join(cwd, ".metaproject");
41972
+ const metaprojectRoot = path127.join(cwd, ".metaproject");
41858
41973
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
41859
41974
  for (const file of requiredFiles) {
41860
- if (!await pathExists(path126.join(metaprojectRoot, file))) {
41975
+ if (!await pathExists(path127.join(metaprojectRoot, file))) {
41861
41976
  errors.push(issue("missing-required-file", `Required file .metaproject/${file} is missing`, `Run \`keryx init\` to scaffold .metaproject/${file}.`));
41862
41977
  }
41863
41978
  }
41864
41979
  const requiredDirs = ["modules", "rules", "skills", "data"];
41865
41980
  for (const dir of requiredDirs) {
41866
- if (!await pathExists(path126.join(metaprojectRoot, dir))) {
41981
+ if (!await pathExists(path127.join(metaprojectRoot, dir))) {
41867
41982
  errors.push(issue("missing-required-dir", `Required directory .metaproject/${dir}/ is missing`, `Run \`keryx init\` to create .metaproject/${dir}/.`));
41868
41983
  }
41869
41984
  }
41870
- const manifestPath = path126.join(metaprojectRoot, "metaproject.json");
41985
+ const manifestPath = path127.join(metaprojectRoot, "metaproject.json");
41871
41986
  if (!await pathExists(manifestPath)) {
41872
41987
  return { ok: errors.length === 0, errors, warnings };
41873
41988
  }
@@ -41899,7 +42014,7 @@ async function validateWorkspace2(cwd) {
41899
42014
  if (typeof value !== "string") {
41900
42015
  continue;
41901
42016
  }
41902
- if (!await pathExists(path126.join(cwd, value))) {
42017
+ if (!await pathExists(path127.join(cwd, value))) {
41903
42018
  errors.push(issue("missing-declared-path", `Declared path paths.${key} -> ${value} does not exist`, `Create ${value} or remove paths.${key} from metaproject.json.`));
41904
42019
  }
41905
42020
  }
@@ -41909,7 +42024,7 @@ async function validateWorkspace2(cwd) {
41909
42024
  continue;
41910
42025
  }
41911
42026
  if (typeof entry.manifest === "string") {
41912
- if (!await pathExists(path126.join(cwd, entry.manifest))) {
42027
+ if (!await pathExists(path127.join(cwd, entry.manifest))) {
41913
42028
  errors.push(issue("missing-module-manifest", `Enabled module "${key}" manifest ${entry.manifest} is missing`, `Create ${entry.manifest} or run \`keryx update\` to regenerate module manifests.`));
41914
42029
  }
41915
42030
  }
@@ -41918,14 +42033,14 @@ async function validateWorkspace2(cwd) {
41918
42033
  if (typeof value !== "string") {
41919
42034
  continue;
41920
42035
  }
41921
- if (!await pathExists(path126.join(cwd, value))) {
42036
+ if (!await pathExists(path127.join(cwd, value))) {
41922
42037
  const sink = field === "data" ? warnings : errors;
41923
42038
  sink.push(issue("missing-module-path", `Module "${key}" declares ${String(field)} ${value}, which does not exist`, field === "data" ? `Run the module (e.g. \`keryx ${key} ...\`) to generate ${value}, or update modules.${key}.data in metaproject.json.` : `Create ${value} or update modules.${key}.${String(field)} in metaproject.json.`));
41924
42039
  }
41925
42040
  }
41926
42041
  }
41927
42042
  for (const { path: name, scope } of namedEntrypoints(manifest)) {
41928
- const filePath = path126.join(cwd, name);
42043
+ const filePath = path127.join(cwd, name);
41929
42044
  if (!await pathExists(filePath)) {
41930
42045
  continue;
41931
42046
  }
@@ -42925,7 +43040,7 @@ async function runDoctor(cwd) {
42925
43040
  return validateWorkspace2(cwd);
42926
43041
  }
42927
43042
  async function readManifest(cwd) {
42928
- const manifestPath = path127.join(cwd, ".metaproject", "metaproject.json");
43043
+ const manifestPath = path128.join(cwd, ".metaproject", "metaproject.json");
42929
43044
  if (!await pathExists(manifestPath)) {
42930
43045
  throw new Error("Metaproject is not initialized (missing .metaproject/metaproject.json). Run `keryx init` first.");
42931
43046
  }