@mrciphersmith/keryx 0.3.132 → 0.3.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.js CHANGED
@@ -16164,7 +16164,7 @@ var init_guard = __esm(() => {
16164
16164
 
16165
16165
  // src/lib/keryx-home.ts
16166
16166
  import os2 from "os";
16167
- import path58 from "path";
16167
+ import path59 from "path";
16168
16168
  function resolveKeryxHomeDir(env, homeDir) {
16169
16169
  if (homeDir !== undefined)
16170
16170
  return homeDir;
@@ -16173,24 +16173,24 @@ function resolveKeryxHomeDir(env, homeDir) {
16173
16173
  }
16174
16174
  function userStoreRoot(env = process.env, homeDir) {
16175
16175
  const home = resolveKeryxHomeDir(env, homeDir);
16176
- return path58.join(home, USER_STORE_DIRNAME);
16176
+ return path59.join(home, USER_STORE_DIRNAME);
16177
16177
  }
16178
16178
  function userStorePaths(env = process.env, homeDir) {
16179
16179
  const root = userStoreRoot(env, homeDir);
16180
- const state = path58.join(root, "state");
16180
+ const state = path59.join(root, "state");
16181
16181
  return {
16182
16182
  root,
16183
- skills: path58.join(root, "skills"),
16184
- agents: path58.join(root, "agents"),
16185
- memory: path58.join(root, "memory"),
16186
- learning: path58.join(root, "learning"),
16187
- learningPatterns: path58.join(root, "learning", "patterns"),
16188
- bundles: path58.join(root, "bundles"),
16189
- appliedState: path58.join(root, "bundles", "applied-state.json"),
16190
- hooksJson: path58.join(root, "hooks.json"),
16191
- externalSkillImports: path58.join(root, "skills", "external-imports.json"),
16183
+ skills: path59.join(root, "skills"),
16184
+ agents: path59.join(root, "agents"),
16185
+ memory: path59.join(root, "memory"),
16186
+ learning: path59.join(root, "learning"),
16187
+ learningPatterns: path59.join(root, "learning", "patterns"),
16188
+ bundles: path59.join(root, "bundles"),
16189
+ appliedState: path59.join(root, "bundles", "applied-state.json"),
16190
+ hooksJson: path59.join(root, "hooks.json"),
16191
+ externalSkillImports: path59.join(root, "skills", "external-imports.json"),
16192
16192
  state,
16193
- externalImportsKey: path58.join(state, "external-imports.key")
16193
+ externalImportsKey: path59.join(state, "external-imports.key")
16194
16194
  };
16195
16195
  }
16196
16196
  var USER_STORE_DIRNAME = ".keryx";
@@ -16297,12 +16297,12 @@ var init_types2 = __esm(() => {
16297
16297
 
16298
16298
  // src/memory/store.ts
16299
16299
  import { lstat as lstat8, readdir as readdir13, readFile as readFile28 } from "fs/promises";
16300
- import path59 from "path";
16300
+ import path60 from "path";
16301
16301
  function decodeStrictUtf8(bytes) {
16302
16302
  return STRICT_UTF8_DECODER.decode(bytes);
16303
16303
  }
16304
16304
  function memoryRoot(cwd) {
16305
- return path59.join(cwd, ".metaproject", "memory");
16305
+ return path60.join(cwd, ".metaproject", "memory");
16306
16306
  }
16307
16307
  function memoryRootFor(scope, cwd, env = process.env, homeDir) {
16308
16308
  return scope === "user" ? userStorePaths(env, homeDir).memory : memoryRoot(cwd);
@@ -16311,7 +16311,7 @@ async function collectEntries(cwd) {
16311
16311
  const root = memoryRoot(cwd);
16312
16312
  const entries = [];
16313
16313
  for (const { type, folder } of MEMORY_TYPES) {
16314
- const dir = path59.join(root, folder);
16314
+ const dir = path60.join(root, folder);
16315
16315
  let dirStats;
16316
16316
  try {
16317
16317
  dirStats = await lstat8(dir);
@@ -16325,7 +16325,7 @@ async function collectEntries(cwd) {
16325
16325
  if (!name.endsWith(".md")) {
16326
16326
  continue;
16327
16327
  }
16328
- const abs = path59.join(dir, name);
16328
+ const abs = path60.join(dir, name);
16329
16329
  let stats;
16330
16330
  try {
16331
16331
  stats = await lstat8(abs);
@@ -16360,7 +16360,7 @@ async function collectEntriesStrict(root) {
16360
16360
  return { status: "incomplete", entries: [], problems: [{ path: ".", reason: "not-a-regular-file" }] };
16361
16361
  }
16362
16362
  for (const { type, folder } of MEMORY_TYPES) {
16363
- const dir = path59.join(root, folder);
16363
+ const dir = path60.join(root, folder);
16364
16364
  let dirStats;
16365
16365
  try {
16366
16366
  dirStats = await lstat8(dir);
@@ -16384,7 +16384,7 @@ async function collectEntriesStrict(root) {
16384
16384
  }
16385
16385
  for (const name of names) {
16386
16386
  const relativePath = `${folder}/${name}`;
16387
- const abs = path59.join(dir, name);
16387
+ const abs = path60.join(dir, name);
16388
16388
  let entryStats;
16389
16389
  try {
16390
16390
  entryStats = await lstat8(abs);
@@ -16476,7 +16476,7 @@ async function collectUnexpectedMarkdown(dir, relativeDir, problems) {
16476
16476
  return;
16477
16477
  }
16478
16478
  for (const name of names) {
16479
- const abs = path59.join(dir, name);
16479
+ const abs = path60.join(dir, name);
16480
16480
  const relativePath = `${relativeDir}/${name}`;
16481
16481
  let stats;
16482
16482
  try {
@@ -16510,7 +16510,7 @@ async function collectUnexpectedTopLevel(root, problems) {
16510
16510
  if (MEMORY_TYPE_FOLDERS.has(name)) {
16511
16511
  continue;
16512
16512
  }
16513
- const abs = path59.join(root, name);
16513
+ const abs = path60.join(root, name);
16514
16514
  let stats;
16515
16515
  try {
16516
16516
  stats = await lstat8(abs);
@@ -16879,9 +16879,9 @@ var init_validation = __esm(() => {
16879
16879
  });
16880
16880
 
16881
16881
  // src/memory/config.ts
16882
- import path63 from "path";
16882
+ import path64 from "path";
16883
16883
  function memoryConfigPath(cwd) {
16884
- return path63.join(cwd, ".metaproject", "memory.config.json");
16884
+ return path64.join(cwd, ".metaproject", "memory.config.json");
16885
16885
  }
16886
16886
  async function loadMemoryConfig(cwd) {
16887
16887
  const file = memoryConfigPath(cwd);
@@ -17009,9 +17009,9 @@ function titleSimilarity(a, b) {
17009
17009
  // src/memory/report.ts
17010
17010
  import { randomUUID as randomUUID2 } from "crypto";
17011
17011
  import { access as access2, mkdir as mkdir10, readdir as readdir15, rename as rename4, rm as rm4, stat as stat10, writeFile as writeFile7 } from "fs/promises";
17012
- import path64 from "path";
17012
+ import path65 from "path";
17013
17013
  function runtimeRoot(cwd) {
17014
- return path64.join(cwd, ".metaproject", "runtime", "memory");
17014
+ return path65.join(cwd, ".metaproject", "runtime", "memory");
17015
17015
  }
17016
17016
  function bounded(value, maximum) {
17017
17017
  if (Buffer.byteLength(value, "utf8") <= maximum)
@@ -17048,8 +17048,8 @@ function formatScope(scopes) {
17048
17048
  return parts.length > 0 ? parts.join(", ") : null;
17049
17049
  }
17050
17050
  function relativeMemoryPath(value) {
17051
- const normalized = value.split(path64.sep).join("/");
17052
- if (!normalized || path64.isAbsolute(value) || normalized.startsWith("../") || normalized.includes("/../")) {
17051
+ const normalized = value.split(path65.sep).join("/");
17052
+ if (!normalized || path65.isAbsolute(value) || normalized.startsWith("../") || normalized.includes("/../")) {
17053
17053
  throw new Error("Memory report paths must be memory-root-relative");
17054
17054
  }
17055
17055
  return bounded(normalized, MAX_PATH_LENGTH);
@@ -17156,7 +17156,7 @@ function validateMemorySearchReport(value) {
17156
17156
  for (const key of Object.keys(item))
17157
17157
  if (!allowedResult.has(key))
17158
17158
  errors.push(`unexpected result property: ${key}`);
17159
- if (typeof item.path !== "string" || !item.path || item.path.length > MAX_PATH_LENGTH || path64.isAbsolute(item.path) || item.path.includes(".."))
17159
+ if (typeof item.path !== "string" || !item.path || item.path.length > MAX_PATH_LENGTH || path65.isAbsolute(item.path) || item.path.includes(".."))
17160
17160
  errors.push("result path is invalid");
17161
17161
  if (typeof item.title !== "string" || item.title.length > MAX_TITLE_LENGTH)
17162
17162
  errors.push("result title is invalid");
@@ -17243,26 +17243,26 @@ class MemoryReportStore {
17243
17243
  throw new Error("Invalid memory report run ID");
17244
17244
  const report = renderMemorySearchReport({ runId, generatedAt: this.clock(), search: input.search, filters: input.filters ?? {} });
17245
17245
  const root = runtimeRoot(input.cwd);
17246
- const searchRoot = path64.join(root, "search");
17247
- const tempRoot = path64.join(root, "tmp");
17248
- const destination = path64.join(searchRoot, runId);
17246
+ const searchRoot = path65.join(root, "search");
17247
+ const tempRoot = path65.join(root, "tmp");
17248
+ const destination = path65.join(searchRoot, runId);
17249
17249
  if (await exists(destination))
17250
17250
  throw new Error(`Memory report run already exists: ${runId}`);
17251
17251
  await mkdir10(searchRoot, { recursive: true });
17252
17252
  await mkdir10(tempRoot, { recursive: true });
17253
17253
  const staleBefore = this.clock().getTime() - STALE_STAGING_MS;
17254
17254
  for (const name of await readdir15(tempRoot)) {
17255
- const candidate = path64.join(tempRoot, name);
17255
+ const candidate = path65.join(tempRoot, name);
17256
17256
  if ((await stat10(candidate)).mtimeMs <= staleBefore)
17257
17257
  await rm4(candidate, { recursive: true, force: true });
17258
17258
  }
17259
- const staging = path64.join(tempRoot, `${runId}.${randomUUID2()}`);
17259
+ const staging = path65.join(tempRoot, `${runId}.${randomUUID2()}`);
17260
17260
  try {
17261
17261
  await mkdir10(staging);
17262
17262
  await Promise.all([
17263
- writeFile7(path64.join(staging, "report.json"), `${JSON.stringify(report, null, 2)}
17263
+ writeFile7(path65.join(staging, "report.json"), `${JSON.stringify(report, null, 2)}
17264
17264
  `, "utf8"),
17265
- writeFile7(path64.join(staging, "report.md"), renderMemorySearchReportMarkdown(report), "utf8")
17265
+ writeFile7(path65.join(staging, "report.md"), renderMemorySearchReportMarkdown(report), "utf8")
17266
17266
  ]);
17267
17267
  if (await exists(destination))
17268
17268
  throw new Error(`Memory report run already exists: ${runId}`);
@@ -17273,8 +17273,8 @@ class MemoryReportStore {
17273
17273
  }
17274
17274
  return {
17275
17275
  runId,
17276
- markdownPath: path64.relative(input.cwd, path64.join(destination, "report.md")),
17277
- jsonPath: path64.relative(input.cwd, path64.join(destination, "report.json"))
17276
+ markdownPath: path65.relative(input.cwd, path65.join(destination, "report.md")),
17277
+ jsonPath: path65.relative(input.cwd, path65.join(destination, "report.json"))
17278
17278
  };
17279
17279
  }
17280
17280
  }
@@ -17531,22 +17531,22 @@ var init_search = __esm(() => {
17531
17531
  });
17532
17532
 
17533
17533
  // src/gdgraph/data-dir.ts
17534
- import path78 from "path";
17534
+ import path79 from "path";
17535
17535
  function gdgraphDataDir(projectRoot, dataDir) {
17536
- return dataDir ?? path78.join(projectRoot, ".metaproject", "data", "gdgraph");
17536
+ return dataDir ?? path79.join(projectRoot, ".metaproject", "data", "gdgraph");
17537
17537
  }
17538
17538
  function gdgraphStorageDir(projectRoot, dataDir) {
17539
- return path78.join(gdgraphDataDir(projectRoot, dataDir), "storage");
17539
+ return path79.join(gdgraphDataDir(projectRoot, dataDir), "storage");
17540
17540
  }
17541
17541
  function gdgraphArtifactsDir(projectRoot, dataDir) {
17542
- return path78.join(gdgraphDataDir(projectRoot, dataDir), "artifacts");
17542
+ return path79.join(gdgraphDataDir(projectRoot, dataDir), "artifacts");
17543
17543
  }
17544
17544
  var init_data_dir = () => {};
17545
17545
 
17546
17546
  // src/gdgraph/config.ts
17547
- import path79 from "path";
17547
+ import path80 from "path";
17548
17548
  function gdgraphConfigPath(cwd) {
17549
- return path79.join(cwd, ".metaproject", "gdgraph.config.json");
17549
+ return path80.join(cwd, ".metaproject", "gdgraph.config.json");
17550
17550
  }
17551
17551
  function mergeGdgraphConfig(parsed) {
17552
17552
  const base = DEFAULT_GDGRAPH_CONFIG;
@@ -18151,7 +18151,7 @@ var init_extract = __esm(() => {
18151
18151
  });
18152
18152
 
18153
18153
  // src/gdgraph/treesitter/grammars.ts
18154
- import path80 from "path";
18154
+ import path81 from "path";
18155
18155
  function grammarAssetId(language) {
18156
18156
  return `tree-sitter-${language}`;
18157
18157
  }
@@ -18167,7 +18167,7 @@ function symbolLanguage(language) {
18167
18167
  async function resolveGrammar(cwd, language, grammarsPath) {
18168
18168
  const id = grammarAssetId(language);
18169
18169
  const lock = await loadAssetsLock(cwd);
18170
- const overrides = grammarsPath ? { [id]: { path: path80.join(grammarsPath, `${id}.wasm`) } } : undefined;
18170
+ const overrides = grammarsPath ? { [id]: { path: path81.join(grammarsPath, `${id}.wasm`) } } : undefined;
18171
18171
  const registry = registryFromLock(lock, overrides);
18172
18172
  const resolved = await resolveAsset(registry, id);
18173
18173
  if (!resolved) {
@@ -18197,7 +18197,7 @@ function toGrammarLanguages(languages) {
18197
18197
  return out;
18198
18198
  }
18199
18199
  function grammarForFile(file, available) {
18200
- const ext = path80.extname(file);
18200
+ const ext = path81.extname(file);
18201
18201
  const preference = ext === ".tsx" ? ["tsx", "typescript"] : ext === ".ts" ? ["typescript"] : ext === ".jsx" || ext === ".js" || ext === ".mjs" || ext === ".cjs" ? ["javascript"] : ext === ".java" ? ["java"] : ext === ".py" ? ["python"] : [];
18202
18202
  for (const language of preference) {
18203
18203
  if (available.includes(language)) {
@@ -18459,7 +18459,7 @@ var init_adapter = __esm(() => {
18459
18459
 
18460
18460
  // src/gdgraph/enrich.ts
18461
18461
  import { mkdir as mkdir14, writeFile as writeFile8 } from "fs/promises";
18462
- import path81 from "path";
18462
+ import path82 from "path";
18463
18463
  async function enrichBuildWithSymbols(cwd, files, resolve, dataDir) {
18464
18464
  const config = await loadGdgraphConfig(cwd);
18465
18465
  const treesitterConfig = {
@@ -18477,10 +18477,10 @@ async function enrichBuildWithSymbols(cwd, files, resolve, dataDir) {
18477
18477
  async function writeSymbolLayer(cwd, layer, dataDir) {
18478
18478
  const storageDir = gdgraphStorageDir(cwd, dataDir);
18479
18479
  await mkdir14(storageDir, { recursive: true });
18480
- await writeFile8(path81.join(storageDir, "symbols.jsonl"), layer.symbols.map((symbol) => JSON.stringify(symbol)).join(`
18480
+ await writeFile8(path82.join(storageDir, "symbols.jsonl"), layer.symbols.map((symbol) => JSON.stringify(symbol)).join(`
18481
18481
  `) + `
18482
18482
  `, "utf8");
18483
- await writeFile8(path81.join(storageDir, "calls.jsonl"), layer.calls.map((call) => JSON.stringify(call)).join(`
18483
+ await writeFile8(path82.join(storageDir, "calls.jsonl"), layer.calls.map((call) => JSON.stringify(call)).join(`
18484
18484
  `) + `
18485
18485
  `, "utf8");
18486
18486
  }
@@ -18674,10 +18674,10 @@ var init_describes = () => {};
18674
18674
 
18675
18675
  // src/sync/provenance.ts
18676
18676
  import { mkdir as mkdir15, readFile as readFile40, writeFile as writeFile9 } from "fs/promises";
18677
- import path82 from "path";
18677
+ import path83 from "path";
18678
18678
  import { spawn } from "child_process";
18679
18679
  function provenancePath(cwd, module) {
18680
- return path82.join(cwd, ".metaproject", "data", module, ".provenance.json");
18680
+ return path83.join(cwd, ".metaproject", "data", module, ".provenance.json");
18681
18681
  }
18682
18682
  function gitCmdResult(cwd, args) {
18683
18683
  return new Promise((resolve) => {
@@ -18722,7 +18722,7 @@ async function recordProvenance(cwd, module, at) {
18722
18722
  if (!head)
18723
18723
  return;
18724
18724
  const file = provenancePath(cwd, module);
18725
- await mkdir15(path82.dirname(file), { recursive: true });
18725
+ await mkdir15(path83.dirname(file), { recursive: true });
18726
18726
  const provenance = { commit: head.commit, branch: head.branch, builtAt: at };
18727
18727
  await writeFile9(file, `${JSON.stringify(provenance, null, 2)}
18728
18728
  `, "utf8");
@@ -18748,7 +18748,7 @@ var init_provenance = __esm(() => {
18748
18748
  // src/gdgraph/staleness.ts
18749
18749
  import { spawn as spawn2 } from "child_process";
18750
18750
  import { stat as stat11 } from "fs/promises";
18751
- import path83 from "path";
18751
+ import path84 from "path";
18752
18752
  function gitStatusPorcelain(cwd) {
18753
18753
  return new Promise((resolve) => {
18754
18754
  try {
@@ -18771,10 +18771,10 @@ function gitStatusPorcelain(cwd) {
18771
18771
  });
18772
18772
  }
18773
18773
  function nodesJsonlPath(cwd) {
18774
- return path83.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
18774
+ return path84.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
18775
18775
  }
18776
18776
  function gdgraphConfigPath2(cwd) {
18777
- return path83.join(cwd, ".metaproject", "gdgraph.config.json");
18777
+ return path84.join(cwd, ".metaproject", "gdgraph.config.json");
18778
18778
  }
18779
18779
  function categorizeStatusEntries(entries, rootPrefix) {
18780
18780
  const metaprojectPrefix = `${rootPrefix}.metaproject/`;
@@ -18869,7 +18869,7 @@ async function checkGraphStaleness(cwd, statusObservation) {
18869
18869
  }
18870
18870
  } else {
18871
18871
  provenanceMissing = true;
18872
- const logsHeadStat = await stat11(path83.join(cwd, ".git", "logs", "HEAD")).catch(() => null);
18872
+ const logsHeadStat = await stat11(path84.join(cwd, ".git", "logs", "HEAD")).catch(() => null);
18873
18873
  if (logsHeadStat && logsHeadStat.mtimeMs > nodesStat.mtimeMs) {
18874
18874
  reasons.push("repo HEAD moved since the graph was built (no build provenance recorded; inferred from .git/logs/HEAD)");
18875
18875
  }
@@ -18897,7 +18897,7 @@ async function checkGraphStaleness(cwd, statusObservation) {
18897
18897
  if (projectRelative === null) {
18898
18898
  continue;
18899
18899
  }
18900
- const fileStat = await stat11(path83.join(cwd, projectRelative)).catch(() => null);
18900
+ const fileStat = await stat11(path84.join(cwd, projectRelative)).catch(() => null);
18901
18901
  if (fileStat && fileStat.mtimeMs > nodesStat.mtimeMs) {
18902
18902
  postBuildEdits.push(displayPath);
18903
18903
  }
@@ -19033,15 +19033,15 @@ var init_types3 = __esm(() => {
19033
19033
 
19034
19034
  // src/wiki/collect.ts
19035
19035
  import { readFile as readFile41, readdir as readdir16 } from "fs/promises";
19036
- import path84 from "path";
19036
+ import path85 from "path";
19037
19037
  function wikiRootPath(cwd) {
19038
- return path84.join(cwd, ".metaproject", "wiki");
19038
+ return path85.join(cwd, ".metaproject", "wiki");
19039
19039
  }
19040
19040
  async function collectPages(cwd) {
19041
19041
  const root = wikiRootPath(cwd);
19042
19042
  const pages = [];
19043
19043
  for (const { type, folder } of WIKI_PAGE_TYPES) {
19044
- const dir = path84.join(root, folder);
19044
+ const dir = path85.join(root, folder);
19045
19045
  let names;
19046
19046
  try {
19047
19047
  names = await readdir16(dir);
@@ -19056,7 +19056,7 @@ async function collectPages(cwd) {
19056
19056
  if (!entry.endsWith(".md")) {
19057
19057
  continue;
19058
19058
  }
19059
- const absolutePath = path84.join(dir, entry);
19059
+ const absolutePath = path85.join(dir, entry);
19060
19060
  let content;
19061
19061
  try {
19062
19062
  content = await readFile41(absolutePath, "utf8");
@@ -19917,9 +19917,9 @@ var MEMORY_EMBEDDING_ID = "memory.embedding", DEFAULT_EMBED_DIMS = 96;
19917
19917
  // src/memory/embedding/index.ts
19918
19918
  import { createHash as createHash14 } from "crypto";
19919
19919
  import { mkdir as mkdir16, readFile as readFile42, writeFile as writeFile10 } from "fs/promises";
19920
- import path85 from "path";
19920
+ import path86 from "path";
19921
19921
  function embeddingsDir(cwd) {
19922
- return path85.join(cwd, ".metaproject", "data", "memory", "embeddings");
19922
+ return path86.join(cwd, ".metaproject", "data", "memory", "embeddings");
19923
19923
  }
19924
19924
  function entryText(entry) {
19925
19925
  return `${entry.title}
@@ -19948,17 +19948,17 @@ async function buildEmbeddingIndex(cwd, entries, embedder, model, now) {
19948
19948
  };
19949
19949
  const dir = embeddingsDir(cwd);
19950
19950
  await mkdir16(dir, { recursive: true });
19951
- await writeFile10(path85.join(dir, "index.meta.json"), `${JSON.stringify(meta, null, 2)}
19951
+ await writeFile10(path86.join(dir, "index.meta.json"), `${JSON.stringify(meta, null, 2)}
19952
19952
  `, "utf8");
19953
- await writeFile10(path85.join(dir, "vectors.jsonl"), records.map((record) => JSON.stringify(record)).join(`
19953
+ await writeFile10(path86.join(dir, "vectors.jsonl"), records.map((record) => JSON.stringify(record)).join(`
19954
19954
  `) + (records.length > 0 ? `
19955
19955
  ` : ""), "utf8");
19956
19956
  return toIndex(meta, records);
19957
19957
  }
19958
19958
  async function loadEmbeddingIndex(cwd) {
19959
19959
  const dir = embeddingsDir(cwd);
19960
- const metaPath = path85.join(dir, "index.meta.json");
19961
- const vectorsPath = path85.join(dir, "vectors.jsonl");
19960
+ const metaPath = path86.join(dir, "index.meta.json");
19961
+ const vectorsPath = path86.join(dir, "vectors.jsonl");
19962
19962
  if (!await pathExists(metaPath) || !await pathExists(vectorsPath)) {
19963
19963
  return null;
19964
19964
  }
@@ -20039,10 +20039,10 @@ var init_embedding = __esm(() => {
20039
20039
  });
20040
20040
 
20041
20041
  // src/wiki/section-tombstone.ts
20042
- import path86 from "path";
20042
+ import path87 from "path";
20043
20043
  import { stat as stat12 } from "fs/promises";
20044
20044
  function sectionRegistryPath(cwd) {
20045
- return path86.join(cwd, ".metaproject", "wiki", ".sections.json");
20045
+ return path87.join(cwd, ".metaproject", "wiki", ".sections.json");
20046
20046
  }
20047
20047
  function emptySectionRegistry() {
20048
20048
  return { version: SECTION_REGISTRY_VERSION, entries: [], tombstones: [], lifted: [] };
@@ -20344,10 +20344,10 @@ var init_section_tombstone = __esm(() => {
20344
20344
 
20345
20345
  // src/memory/cross-layer.ts
20346
20346
  import { readFile as readFile43 } from "fs/promises";
20347
- import path87 from "path";
20347
+ import path88 from "path";
20348
20348
  function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wikiRoot) {
20349
20349
  const references = [];
20350
- const entryDir = path87.dirname(entryAbsolutePath);
20350
+ const entryDir = path88.dirname(entryAbsolutePath);
20351
20351
  const lines = content.split(`
20352
20352
  `);
20353
20353
  for (let index = 0;index < lines.length; index += 1) {
@@ -20362,16 +20362,16 @@ function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wi
20362
20362
  if (withoutAnchor.length === 0) {
20363
20363
  continue;
20364
20364
  }
20365
- const absolute = path87.resolve(entryDir, withoutAnchor);
20366
- const relativeToWiki = path87.relative(wikiRoot, absolute);
20367
- if (relativeToWiki.startsWith("..") || path87.isAbsolute(relativeToWiki)) {
20365
+ const absolute = path88.resolve(entryDir, withoutAnchor);
20366
+ const relativeToWiki = path88.relative(wikiRoot, absolute);
20367
+ if (relativeToWiki.startsWith("..") || path88.isAbsolute(relativeToWiki)) {
20368
20368
  continue;
20369
20369
  }
20370
20370
  references.push({
20371
20371
  entry: entryRelativePath,
20372
20372
  kind: "page-path",
20373
20373
  raw: href,
20374
- target: relativeToWiki.split(path87.sep).join("/"),
20374
+ target: relativeToWiki.split(path88.sep).join("/"),
20375
20375
  line
20376
20376
  });
20377
20377
  }
@@ -20391,7 +20391,7 @@ function isDangling(finding) {
20391
20391
  return finding.state !== "intact";
20392
20392
  }
20393
20393
  async function loadWikiKnowledgeView(cwd) {
20394
- const wikiRoot = path87.join(cwd, ".metaproject", "wiki");
20394
+ const wikiRoot = path88.join(cwd, ".metaproject", "wiki");
20395
20395
  const pages = await collectPages(cwd);
20396
20396
  const index = buildSectionIndex(await Promise.all(pages.map(async (page) => ({
20397
20397
  page,
@@ -20609,7 +20609,7 @@ function round2(value) {
20609
20609
  var init_dedup = () => {};
20610
20610
 
20611
20611
  // src/memory/check.ts
20612
- import path88 from "path";
20612
+ import path89 from "path";
20613
20613
  async function checkMemory(cwd, config) {
20614
20614
  const entries = await collectEntries(cwd);
20615
20615
  const issues = [];
@@ -20625,7 +20625,7 @@ async function checkMemory(cwd, config) {
20625
20625
  }
20626
20626
  for (const file of entry.scopes.files) {
20627
20627
  const clean = file.replace(/^`|`$/g, "");
20628
- if (!await pathExists(path88.resolve(cwd, clean))) {
20628
+ if (!await pathExists(path89.resolve(cwd, clean))) {
20629
20629
  issues.push({ path: entry.relativePath, kind: "link", message: `related file not found: ${clean}` });
20630
20630
  }
20631
20631
  }
@@ -20680,12 +20680,12 @@ var init_check = __esm(() => {
20680
20680
 
20681
20681
  // src/memory/write.ts
20682
20682
  import { mkdir as mkdir17, open as open2, readFile as readFile44, rename as rename5, rm as rm5, writeFile as writeFile11 } from "fs/promises";
20683
- import path89 from "path";
20683
+ import path90 from "path";
20684
20684
  async function resolveCanonicalEntryPath(cwd, relativePath) {
20685
- const root = path89.resolve(memoryRoot(cwd));
20686
- const absolutePath = path89.resolve(root, relativePath);
20687
- const normalized = toPosix2(path89.relative(root, absolutePath));
20688
- if (!normalized || normalized.startsWith("../") || path89.isAbsolute(normalized) || !normalized.endsWith(".md")) {
20685
+ const root = path90.resolve(memoryRoot(cwd));
20686
+ const absolutePath = path90.resolve(root, relativePath);
20687
+ const normalized = toPosix2(path90.relative(root, absolutePath));
20688
+ if (!normalized || normalized.startsWith("../") || path90.isAbsolute(normalized) || !normalized.endsWith(".md")) {
20689
20689
  return null;
20690
20690
  }
20691
20691
  return { absolutePath, relativePath: normalized };
@@ -20781,9 +20781,9 @@ function validateNextEntry(relativePath, content) {
20781
20781
  return null;
20782
20782
  }
20783
20783
  async function replaceAtomically(target, content) {
20784
- const dir = path89.dirname(target);
20784
+ const dir = path90.dirname(target);
20785
20785
  await mkdir17(dir, { recursive: true });
20786
- const tmp = path89.join(dir, `.${path89.basename(target)}.keryx-tmp-${process.pid}-${Math.random().toString(16).slice(2)}`);
20786
+ const tmp = path90.join(dir, `.${path90.basename(target)}.keryx-tmp-${process.pid}-${Math.random().toString(16).slice(2)}`);
20787
20787
  try {
20788
20788
  await writeFile11(tmp, content, "utf8");
20789
20789
  const file = await open2(tmp, "r");
@@ -20819,7 +20819,7 @@ function header(content, name) {
20819
20819
  return content.match(new RegExp(`^${name}:\\s*(.+)$`, "mi"))?.[1]?.trim() ?? null;
20820
20820
  }
20821
20821
  function toPosix2(value) {
20822
- return value.split(path89.sep).join("/");
20822
+ return value.split(path90.sep).join("/");
20823
20823
  }
20824
20824
  function message(cause) {
20825
20825
  return cause instanceof Error ? cause.message : String(cause);
@@ -20833,9 +20833,9 @@ var init_write = __esm(() => {
20833
20833
  // src/memory/ingest.ts
20834
20834
  import { existsSync as existsSync10 } from "fs";
20835
20835
  import { readFile as readFile45 } from "fs/promises";
20836
- import path90 from "path";
20836
+ import path91 from "path";
20837
20837
  async function ingestMemory(cwd, source, filePath, config, now) {
20838
- const absolute = path90.resolve(cwd, filePath);
20838
+ const absolute = path91.resolve(cwd, filePath);
20839
20839
  if (!await pathExists(absolute)) {
20840
20840
  throw new Error(`Ingest source not found: ${filePath}`);
20841
20841
  }
@@ -20852,8 +20852,8 @@ async function ingestMemory(cwd, source, filePath, config, now) {
20852
20852
  const securityWarnings = [];
20853
20853
  const securitySkipped = [];
20854
20854
  let skippedDuplicates = 0;
20855
- const dir = path90.join(memoryRoot(cwd), folder);
20856
- const link = path90.relative(cwd, absolute);
20855
+ const dir = path91.join(memoryRoot(cwd), folder);
20856
+ const link = path91.relative(cwd, absolute);
20857
20857
  const date = dateString(now);
20858
20858
  for (const text of candidates) {
20859
20859
  const title = toTitle(text);
@@ -21034,7 +21034,7 @@ function uniqueSlug(dir, title) {
21034
21034
  const base = slugify2(title) || "entry";
21035
21035
  let slug = base;
21036
21036
  let counter = 2;
21037
- while (existsSync10(path90.join(dir, `${slug}.md`))) {
21037
+ while (existsSync10(path91.join(dir, `${slug}.md`))) {
21038
21038
  slug = `${base}-${counter}`;
21039
21039
  counter += 1;
21040
21040
  }
@@ -21069,7 +21069,7 @@ var init_ingest = __esm(() => {
21069
21069
 
21070
21070
  // src/memory/supersede.ts
21071
21071
  import { readFile as readFile46 } from "fs/promises";
21072
- import path91 from "path";
21072
+ import path92 from "path";
21073
21073
  async function supersedeEntry(input, now) {
21074
21074
  const date = input.date ?? now.toISOString().slice(0, 10);
21075
21075
  const today = now.toISOString().slice(0, 10);
@@ -21129,12 +21129,12 @@ async function supersedeEntry(input, now) {
21129
21129
  async function resolveEntryPath(cwd, raw) {
21130
21130
  const root = memoryRoot(cwd);
21131
21131
  const candidates = [
21132
- path91.resolve(cwd, raw),
21133
- path91.resolve(root, raw),
21134
- path91.isAbsolute(raw) ? raw : path91.join(cwd, raw)
21132
+ path92.resolve(cwd, raw),
21133
+ path92.resolve(root, raw),
21134
+ path92.isAbsolute(raw) ? raw : path92.join(cwd, raw)
21135
21135
  ];
21136
21136
  for (const absolute of candidates) {
21137
- const confined = await resolveCanonicalEntryPath(cwd, path91.relative(root, absolute));
21137
+ const confined = await resolveCanonicalEntryPath(cwd, path92.relative(root, absolute));
21138
21138
  if (confined && await pathExists(confined.absolutePath)) {
21139
21139
  return { absolute: confined.absolutePath, relative: confined.relativePath };
21140
21140
  }
@@ -21330,9 +21330,9 @@ __export(exports_service3, {
21330
21330
  });
21331
21331
  import { createHash as createHash15 } from "crypto";
21332
21332
  import { mkdir as mkdir18, readFile as readFile47, writeFile as writeFile12 } from "fs/promises";
21333
- import path92 from "path";
21333
+ import path93 from "path";
21334
21334
  function dataRoot2(cwd) {
21335
- return path92.join(cwd, ".metaproject", "data", "memory");
21335
+ return path93.join(cwd, ".metaproject", "data", "memory");
21336
21336
  }
21337
21337
  function createMemoryService() {
21338
21338
  const reportStore = createMemoryReportStore();
@@ -21347,9 +21347,9 @@ function createMemoryService() {
21347
21347
  if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) {
21348
21348
  throw new Error(`Invalid slug: ${slug}. Use lowercase letters, digits, and hyphens.`);
21349
21349
  }
21350
- const dir = path92.join(memoryRoot(input.cwd), typeConfig.folder);
21351
- const filePath = path92.join(dir, `${slug}.md`);
21352
- const relativePath = path92.relative(input.cwd, filePath);
21350
+ const dir = path93.join(memoryRoot(input.cwd), typeConfig.folder);
21351
+ const filePath = path93.join(dir, `${slug}.md`);
21352
+ const relativePath = path93.relative(input.cwd, filePath);
21353
21353
  if (await pathExists(filePath) && !input.force) {
21354
21354
  throw new Error(`Entry already exists: ${relativePath}. Use --force to overwrite.`);
21355
21355
  }
@@ -21380,9 +21380,9 @@ function createMemoryService() {
21380
21380
  async index(input) {
21381
21381
  const entries = await collectEntries(input.cwd);
21382
21382
  const generatedAt = new Date().toISOString();
21383
- const indexDir = input.indexDir ?? path92.join(dataRoot2(input.cwd), "index");
21383
+ const indexDir = input.indexDir ?? path93.join(dataRoot2(input.cwd), "index");
21384
21384
  await mkdir18(indexDir, { recursive: true });
21385
- const indexPath = path92.join(indexDir, "index.json");
21385
+ const indexPath = path93.join(indexDir, "index.json");
21386
21386
  await writeFile12(indexPath, `${JSON.stringify({
21387
21387
  catalogVersion: 1,
21388
21388
  sourceFingerprint: createHash15("sha256").update(JSON.stringify(entries.map((e) => ({
@@ -21403,7 +21403,7 @@ function createMemoryService() {
21403
21403
  }, null, 2)}
21404
21404
  `, "utf8");
21405
21405
  const result = {
21406
- path: path92.relative(input.cwd, indexPath),
21406
+ path: path93.relative(input.cwd, indexPath),
21407
21407
  entryCount: entries.length,
21408
21408
  generatedAt
21409
21409
  };
@@ -21416,7 +21416,7 @@ function createMemoryService() {
21416
21416
  const built = await buildEmbeddingIndex(input.cwd, entries, embedder.embed, embedder.model, new Date);
21417
21417
  result.embeddings = {
21418
21418
  built: true,
21419
- path: path92.relative(input.cwd, embeddingsDir(input.cwd)),
21419
+ path: path93.relative(input.cwd, embeddingsDir(input.cwd)),
21420
21420
  vectorCount: built.meta.entryCount,
21421
21421
  model: built.meta.model
21422
21422
  };
@@ -22018,7 +22018,7 @@ var init_ask = __esm(() => {
22018
22018
  });
22019
22019
 
22020
22020
  // src/wiki/backlinks.ts
22021
- import path93 from "path";
22021
+ import path94 from "path";
22022
22022
  function extractCodePaths(content) {
22023
22023
  const out = [];
22024
22024
  let match;
@@ -22048,8 +22048,8 @@ function resolveLink(fromRepoPath, raw) {
22048
22048
  const clean = (raw.split("#")[0] ?? "").trim();
22049
22049
  if (!clean)
22050
22050
  return "";
22051
- const fromDir = path93.posix.dirname(fromRepoPath.split(path93.sep).join("/"));
22052
- return path93.posix.normalize(path93.posix.join(fromDir, clean));
22051
+ const fromDir = path94.posix.dirname(fromRepoPath.split(path94.sep).join("/"));
22052
+ return path94.posix.normalize(path94.posix.join(fromDir, clean));
22053
22053
  }
22054
22054
  function buildBacklinkIndex(pages) {
22055
22055
  const index = new Map;
@@ -22063,18 +22063,18 @@ function buildBacklinkIndex(pages) {
22063
22063
  }
22064
22064
  };
22065
22065
  for (const page of pages) {
22066
- const from = page.repoPath.split(path93.sep).join("/");
22066
+ const from = page.repoPath.split(path94.sep).join("/");
22067
22067
  for (const raw of extractLinks(page.content))
22068
22068
  add(resolveLink(from, raw), from);
22069
22069
  for (const raw of extractCodePaths(page.content))
22070
- add(path93.posix.normalize(raw), from);
22070
+ add(path94.posix.normalize(raw), from);
22071
22071
  }
22072
22072
  for (const list of index.values())
22073
22073
  list.sort();
22074
22074
  return index;
22075
22075
  }
22076
22076
  function backlinksFor(index, targetRepoPath) {
22077
- const key = path93.posix.normalize(targetRepoPath.split(path93.sep).join("/"));
22077
+ const key = path94.posix.normalize(targetRepoPath.split(path94.sep).join("/"));
22078
22078
  return index.get(key) ?? [];
22079
22079
  }
22080
22080
  var LINK, CODE_SPAN, FILE_LIKE;
@@ -22087,7 +22087,7 @@ var init_backlinks = __esm(() => {
22087
22087
  // src/ctx/assembly.ts
22088
22088
  import { createHash as createHash16 } from "crypto";
22089
22089
  import { mkdir as mkdir19, rename as rename6, writeFile as writeFile13 } from "fs/promises";
22090
- import path94 from "path";
22090
+ import path95 from "path";
22091
22091
  function assembleContext(input) {
22092
22092
  let items = 0;
22093
22093
  let tokens = 0;
@@ -22131,9 +22131,9 @@ async function recordNoContentContext(input) {
22131
22131
  return assembly;
22132
22132
  }
22133
22133
  async function recordContextAssembly(input) {
22134
- const directory = path94.join(input.workspaceRoot, ".metaproject", "context-operations", "traces");
22134
+ const directory = path95.join(input.workspaceRoot, ".metaproject", "context-operations", "traces");
22135
22135
  await mkdir19(directory, { recursive: true });
22136
- const target = path94.join(directory, path94.basename(input.assembly.traceRef));
22136
+ const target = path95.join(directory, path95.basename(input.assembly.traceRef));
22137
22137
  const temporary = `${target}.${process.pid}.tmp`;
22138
22138
  await writeFile13(temporary, `${JSON.stringify({ schemaVersion: "1.0", correlationId: input.correlationId, outcome: input.outcome, configurationRevision: input.assembly.configurationRevision, policy: { ref: input.assembly.policyRef, revision: input.assembly.policyRevision }, selected: input.assembly.selected, omittedOptional: input.assembly.omittedOptional, partial: input.assembly.partial })}
22139
22139
  `, { mode: 384 });
@@ -22533,9 +22533,9 @@ var init_evidence = __esm(() => {
22533
22533
  });
22534
22534
 
22535
22535
  // src/wiki/config.ts
22536
- import path95 from "path";
22536
+ import path96 from "path";
22537
22537
  function wikiConfigPath(cwd) {
22538
- return path95.join(cwd, ".metaproject", "wiki.config.json");
22538
+ return path96.join(cwd, ".metaproject", "wiki.config.json");
22539
22539
  }
22540
22540
  function mergeWikiConfig(parsed) {
22541
22541
  const base = DEFAULT_WIKI_CONFIG;
@@ -22613,12 +22613,12 @@ var init_config4 = __esm(() => {
22613
22613
  // src/wiki/history.ts
22614
22614
  import { createHash as createHash17, randomBytes as randomBytes5 } from "crypto";
22615
22615
  import { appendFile as appendFile4, mkdir as mkdir20, open as open3, readFile as readFile49, rm as rm6, stat as stat13, writeFile as writeFile14 } from "fs/promises";
22616
- import path96 from "path";
22616
+ import path97 from "path";
22617
22617
  function wikiRootPath2(cwd) {
22618
- return path96.join(cwd, ".metaproject", "wiki");
22618
+ return path97.join(cwd, ".metaproject", "wiki");
22619
22619
  }
22620
22620
  function wikiHistoryRoot(cwd) {
22621
- return path96.join(cwd, ".metaproject", "data", "gdwiki", "history");
22621
+ return path97.join(cwd, ".metaproject", "data", "gdwiki", "history");
22622
22622
  }
22623
22623
  function newWikiRunId(now = new Date) {
22624
22624
  const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
@@ -22639,29 +22639,29 @@ async function openWikiWriteContext(cwd, command) {
22639
22639
  return createWikiWriteContext(cwd, command, { keep: (await loadWikiConfig(cwd)).history.keep });
22640
22640
  }
22641
22641
  function wikiPageKey(cwd, absolutePath) {
22642
- const relative = path96.relative(wikiRootPath2(cwd), path96.resolve(absolutePath));
22643
- if (relative === "" || relative.startsWith("..") || path96.isAbsolute(relative)) {
22642
+ const relative = path97.relative(wikiRootPath2(cwd), path97.resolve(absolutePath));
22643
+ if (relative === "" || relative.startsWith("..") || path97.isAbsolute(relative)) {
22644
22644
  throw new Error(`not a wiki page: ${absolutePath}`);
22645
22645
  }
22646
22646
  return toPosix(relative);
22647
22647
  }
22648
22648
  function assertPageKey(page) {
22649
22649
  const segments = page.split("/");
22650
- if (page.length === 0 || page.includes("\\") || path96.isAbsolute(page) || segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
22650
+ if (page.length === 0 || page.includes("\\") || path97.isAbsolute(page) || segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
22651
22651
  throw new Error(`not a wiki page path: ${page}`);
22652
22652
  }
22653
22653
  return page;
22654
22654
  }
22655
22655
  function pageHistoryDir(cwd, page) {
22656
- return path96.join(wikiHistoryRoot(cwd), ...assertPageKey(page).replace(/\.md$/i, "").split("/"));
22656
+ return path97.join(wikiHistoryRoot(cwd), ...assertPageKey(page).replace(/\.md$/i, "").split("/"));
22657
22657
  }
22658
22658
  function pagePath(cwd, page) {
22659
- return path96.join(wikiRootPath2(cwd), ...assertPageKey(page).split("/"));
22659
+ return path97.join(wikiRootPath2(cwd), ...assertPageKey(page).split("/"));
22660
22660
  }
22661
22661
  function versionFilePath(cwd, page, file) {
22662
22662
  const dir = pageHistoryDir(cwd, page);
22663
- const target = path96.join(dir, file);
22664
- if (!VERSION_FILE.test(file) || path96.dirname(target) !== dir) {
22663
+ const target = path97.join(dir, file);
22664
+ if (!VERSION_FILE.test(file) || path97.dirname(target) !== dir) {
22665
22665
  throw new Error(`history index names an invalid version file for ${page}: ${file}`);
22666
22666
  }
22667
22667
  return target;
@@ -22734,7 +22734,7 @@ function parsePageHistoryIndex(markdown, page) {
22734
22734
  return { page, rows };
22735
22735
  }
22736
22736
  async function readPageHistory(cwd, page) {
22737
- const indexPath = path96.join(pageHistoryDir(cwd, page), INDEX_FILE);
22737
+ const indexPath = path97.join(pageHistoryDir(cwd, page), INDEX_FILE);
22738
22738
  const raw = await readBufferOrNull(indexPath);
22739
22739
  if (raw === null)
22740
22740
  return null;
@@ -22746,8 +22746,8 @@ async function readPageHistory(cwd, page) {
22746
22746
  }
22747
22747
  async function storeVersion(cwd, page, version, at, content) {
22748
22748
  const fileName = `${versionLabel(version)}-${at.replace(/[:.]/g, "-")}.md`;
22749
- const target = path96.join(pageHistoryDir(cwd, page), fileName);
22750
- await mkdir20(path96.dirname(target), { recursive: true });
22749
+ const target = path97.join(pageHistoryDir(cwd, page), fileName);
22750
+ await mkdir20(path97.dirname(target), { recursive: true });
22751
22751
  await writeFile14(target, content);
22752
22752
  if (sha2562(await readFile49(target)) !== sha2562(content)) {
22753
22753
  throw new Error(`history: stored version does not match the page bytes: ${target}`);
@@ -22785,7 +22785,7 @@ function planPrune(history, keep, maxRows = MAX_INDEX_ROWS) {
22785
22785
  }
22786
22786
  async function ensureHistoryRoot(cwd) {
22787
22787
  const root = wikiHistoryRoot(cwd);
22788
- const ignore = path96.join(root, ".gitignore");
22788
+ const ignore = path97.join(root, ".gitignore");
22789
22789
  if (await readBufferOrNull(ignore))
22790
22790
  return;
22791
22791
  await mkdir20(root, { recursive: true });
@@ -22815,14 +22815,14 @@ async function endsWithoutNewline(file) {
22815
22815
  }
22816
22816
  async function appendRun(cwd, entry) {
22817
22817
  const root = wikiHistoryRoot(cwd);
22818
- const file = path96.join(root, RUNS_FILE);
22818
+ const file = path97.join(root, RUNS_FILE);
22819
22819
  const lead = await endsWithoutNewline(file) ? `
22820
22820
  ` : "";
22821
22821
  await appendFile4(file, `${lead}${JSON.stringify(entry)}
22822
22822
  `, "utf8");
22823
22823
  if ((await stat13(file)).size <= MAX_RUNS_BYTES)
22824
22824
  return;
22825
- await withFileLock(path96.join(root, ".runs.lock"), async () => {
22825
+ await withFileLock(path97.join(root, ".runs.lock"), async () => {
22826
22826
  if ((await stat13(file)).size <= MAX_RUNS_BYTES)
22827
22827
  return;
22828
22828
  const lines = (await readFile49(file, "utf8")).split(`
@@ -22836,7 +22836,7 @@ async function mutatePage(ctx, absolutePath, next) {
22836
22836
  const page = wikiPageKey(ctx.cwd, absolutePath);
22837
22837
  const dir = pageHistoryDir(ctx.cwd, page);
22838
22838
  await ensureHistoryRoot(ctx.cwd);
22839
- return withFileLock(path96.join(path96.dirname(dir), `.${path96.basename(dir)}.lock`), async () => {
22839
+ return withFileLock(path97.join(path97.dirname(dir), `.${path97.basename(dir)}.lock`), async () => {
22840
22840
  const live = await readBufferOrNull(absolutePath);
22841
22841
  if (next === null ? live === null : live !== null && live.equals(next)) {
22842
22842
  return { changed: false };
@@ -22860,7 +22860,7 @@ async function mutatePage(ctx, absolutePath, next) {
22860
22860
  if (next === null) {
22861
22861
  await rm6(absolutePath, { force: true });
22862
22862
  } else {
22863
- await mkdir20(path96.dirname(absolutePath), { recursive: true });
22863
+ await mkdir20(path97.dirname(absolutePath), { recursive: true });
22864
22864
  await writeFile14(absolutePath, next);
22865
22865
  }
22866
22866
  } catch (error) {
@@ -22868,7 +22868,7 @@ async function mutatePage(ctx, absolutePath, next) {
22868
22868
  await rm6(versionFilePath(ctx.cwd, page, row.file), { force: true });
22869
22869
  throw error;
22870
22870
  }
22871
- await writeFileAtomic(path96.join(dir, INDEX_FILE), renderPageHistoryIndex(history));
22871
+ await writeFileAtomic(path97.join(dir, INDEX_FILE), renderPageHistoryIndex(history));
22872
22872
  for (const file of pruned)
22873
22873
  await rm6(versionFilePath(ctx.cwd, page, file), { force: true });
22874
22874
  return { changed: true, action };
@@ -22881,7 +22881,7 @@ async function deleteWikiPage(ctx, absolutePath) {
22881
22881
  return mutatePage(ctx, absolutePath, null);
22882
22882
  }
22883
22883
  async function readWikiRuns(cwd) {
22884
- const raw = await readBufferOrNull(path96.join(wikiHistoryRoot(cwd), RUNS_FILE));
22884
+ const raw = await readBufferOrNull(path97.join(wikiHistoryRoot(cwd), RUNS_FILE));
22885
22885
  if (raw === null)
22886
22886
  return [];
22887
22887
  const entries = [];
@@ -23573,7 +23573,7 @@ var init_page_invariants = __esm(() => {
23573
23573
  });
23574
23574
 
23575
23575
  // src/wiki/readme-links.ts
23576
- import path97 from "path";
23576
+ import path98 from "path";
23577
23577
  function rewriteReadmeLinks(text, readmeDir, pageLink) {
23578
23578
  return text.replace(MARKDOWN_LINK, (whole, bang, label, target) => {
23579
23579
  if (target === "" || HAS_SCHEME.test(target)) {
@@ -23583,7 +23583,7 @@ function rewriteReadmeLinks(text, readmeDir, pageLink) {
23583
23583
  if (filePart === "") {
23584
23584
  return label;
23585
23585
  }
23586
- const resolved = path97.posix.normalize(filePart.startsWith("/") ? filePart.replace(/^\/+/, "") : path97.posix.join(readmeDir, filePart));
23586
+ const resolved = path98.posix.normalize(filePart.startsWith("/") ? filePart.replace(/^\/+/, "") : path98.posix.join(readmeDir, filePart));
23587
23587
  const codePath = resolved.replace(/\/+$/, "");
23588
23588
  if (codePath === "" || codePath === "." || codePath === ".." || codePath.startsWith("../")) {
23589
23589
  return label;
@@ -23598,12 +23598,12 @@ function rewriteReadmeLinks(text, readmeDir, pageLink) {
23598
23598
  });
23599
23599
  }
23600
23600
  function moduleOfTarget(filePart, codePath) {
23601
- const base = path97.posix.basename(codePath);
23601
+ const base = path98.posix.basename(codePath);
23602
23602
  if (filePart.endsWith("/") || !/\.[A-Za-z0-9]+$/.test(base)) {
23603
23603
  return codePath;
23604
23604
  }
23605
23605
  if (DOC_ENTRY.test(base)) {
23606
- const dir = path97.posix.dirname(codePath);
23606
+ const dir = path98.posix.dirname(codePath);
23607
23607
  return dir === "." ? null : dir;
23608
23608
  }
23609
23609
  return null;
@@ -24009,15 +24009,15 @@ __export(exports_service4, {
24009
24009
  import { spawn as spawn3 } from "child_process";
24010
24010
  import { createHash as createHash19 } from "crypto";
24011
24011
  import { mkdir as mkdir21, readFile as readFile50, readdir as readdir17, writeFile as writeFile15 } from "fs/promises";
24012
- import path98 from "path";
24012
+ import path99 from "path";
24013
24013
  function wikiRootPath3(cwd) {
24014
- return path98.join(cwd, ".metaproject", "wiki");
24014
+ return path99.join(cwd, ".metaproject", "wiki");
24015
24015
  }
24016
24016
  function dataRootPath(cwd) {
24017
- return path98.join(cwd, ".metaproject", "data", "gdwiki");
24017
+ return path99.join(cwd, ".metaproject", "data", "gdwiki");
24018
24018
  }
24019
24019
  function linkCheckReportPath(cwd) {
24020
- return path98.join(dataRootPath(cwd), "link-check", "latest.md");
24020
+ return path99.join(dataRootPath(cwd), "link-check", "latest.md");
24021
24021
  }
24022
24022
  async function wikiStatus(cwd) {
24023
24023
  const root = wikiRootPath3(cwd);
@@ -24025,7 +24025,7 @@ async function wikiStatus(cwd) {
24025
24025
  const pages = enabled ? await collectPages(cwd) : [];
24026
24026
  return {
24027
24027
  enabled,
24028
- wikiRoot: path98.relative(cwd, root),
24028
+ wikiRoot: path99.relative(cwd, root),
24029
24029
  totalPages: pages.length,
24030
24030
  countsByType: WIKI_PAGE_TYPES.map(({ type }) => ({
24031
24031
  type,
@@ -24056,9 +24056,9 @@ async function wikiCreatePage(input) {
24056
24056
  if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
24057
24057
  throw new Error(`Invalid slug: ${input.slug}. Use lowercase letters, digits, and hyphens.`);
24058
24058
  }
24059
- const dir = path98.join(wikiRootPath3(input.cwd), typeConfig.folder);
24060
- const filePath = path98.join(dir, `${input.slug}.md`);
24061
- const relativePath = path98.relative(input.cwd, filePath);
24059
+ const dir = path99.join(wikiRootPath3(input.cwd), typeConfig.folder);
24060
+ const filePath = path99.join(dir, `${input.slug}.md`);
24061
+ const relativePath = path99.relative(input.cwd, filePath);
24062
24062
  if (await pathExists(filePath) && !input.force) {
24063
24063
  throw new Error(`Page already exists: ${relativePath}. Use --force to overwrite.`);
24064
24064
  }
@@ -24070,7 +24070,7 @@ async function wikiCreatePage(input) {
24070
24070
  }
24071
24071
  async function wikiGenerateIndex(cwd, history) {
24072
24072
  const root = wikiRootPath3(cwd);
24073
- const indexPath = path98.join(root, "index.md");
24073
+ const indexPath = path99.join(root, "index.md");
24074
24074
  const pages = await collectPages(cwd);
24075
24075
  const generatedAt = new Date().toISOString();
24076
24076
  const managedBlock = `${WIKI_INDEX_BEGIN}
@@ -24087,7 +24087,7 @@ ${managedBlock}
24087
24087
  `;
24088
24088
  await writeWikiPage(history ?? await openWikiWriteContext(cwd, "wiki index"), indexPath, next);
24089
24089
  return {
24090
- path: path98.relative(cwd, indexPath),
24090
+ path: path99.relative(cwd, indexPath),
24091
24091
  pageCount: pages.length,
24092
24092
  generatedAt
24093
24093
  };
@@ -24095,13 +24095,13 @@ ${managedBlock}
24095
24095
  async function wikiCheckLinks(cwd) {
24096
24096
  const root = wikiRootPath3(cwd);
24097
24097
  const allFiles = await pathExists(root) ? await walkMarkdown(root) : [];
24098
- const files = allFiles.filter((absolutePath) => !path98.relative(root, absolutePath).startsWith(`templates${path98.sep}`));
24098
+ const files = allFiles.filter((absolutePath) => !path99.relative(root, absolutePath).startsWith(`templates${path99.sep}`));
24099
24099
  const broken = [];
24100
24100
  let checkedLinks = 0;
24101
24101
  let skippedExternal = 0;
24102
24102
  for (const absolutePath of files) {
24103
24103
  const content = await readFile50(absolutePath, "utf8");
24104
- const pageRelative = path98.relative(cwd, absolutePath);
24104
+ const pageRelative = path99.relative(cwd, absolutePath);
24105
24105
  for (const target of extractLinkTargets(content)) {
24106
24106
  if (EXTERNAL_LINK.test(target)) {
24107
24107
  skippedExternal += 1;
@@ -24112,7 +24112,7 @@ async function wikiCheckLinks(cwd) {
24112
24112
  continue;
24113
24113
  }
24114
24114
  checkedLinks += 1;
24115
- const resolved = path98.resolve(path98.dirname(absolutePath), filePart);
24115
+ const resolved = path99.resolve(path99.dirname(absolutePath), filePart);
24116
24116
  if (!await pathExists(resolved)) {
24117
24117
  broken.push({
24118
24118
  page: pageRelative,
@@ -24124,7 +24124,7 @@ async function wikiCheckLinks(cwd) {
24124
24124
  }
24125
24125
  const generatedAt = new Date().toISOString();
24126
24126
  const reportPath = linkCheckReportPath(cwd);
24127
- await mkdir21(path98.dirname(reportPath), { recursive: true });
24127
+ await mkdir21(path99.dirname(reportPath), { recursive: true });
24128
24128
  await writeFile15(reportPath, renderLinkCheckReport({
24129
24129
  generatedAt,
24130
24130
  checkedPages: files.length,
@@ -24133,7 +24133,7 @@ async function wikiCheckLinks(cwd) {
24133
24133
  broken
24134
24134
  }), "utf8");
24135
24135
  return {
24136
- reportPath: path98.relative(cwd, reportPath),
24136
+ reportPath: path99.relative(cwd, reportPath),
24137
24137
  checkedPages: files.length,
24138
24138
  checkedLinks,
24139
24139
  skippedExternal,
@@ -24184,7 +24184,7 @@ async function wikiValidate(cwd) {
24184
24184
  }
24185
24185
  if (await isIndexStale(cwd, pages)) {
24186
24186
  issues.push({
24187
- page: path98.join(path98.relative(cwd, wikiRootPath3(cwd)), "index.md"),
24187
+ page: path99.join(path99.relative(cwd, wikiRootPath3(cwd)), "index.md"),
24188
24188
  kind: "index",
24189
24189
  message: "index out of date, run `keryx wiki index`"
24190
24190
  });
@@ -24230,7 +24230,7 @@ function collectCommandLabel(input) {
24230
24230
  return ["wiki collect", ...flags].join(" ");
24231
24231
  }
24232
24232
  async function wikiPruneOrphans(cwd, history) {
24233
- const componentsDir = path98.join(wikiRootPath3(cwd), "components");
24233
+ const componentsDir = path99.join(wikiRootPath3(cwd), "components");
24234
24234
  if (!await pathExists(componentsDir)) {
24235
24235
  return { pruned: [], orphanedAccepted: [] };
24236
24236
  }
@@ -24250,15 +24250,15 @@ async function wikiPruneOrphans(cwd, history) {
24250
24250
  if (validSlugs.has(slug)) {
24251
24251
  continue;
24252
24252
  }
24253
- const filePath = path98.join(componentsDir, entry);
24253
+ const filePath = path99.join(componentsDir, entry);
24254
24254
  const current = await readFile50(filePath, "utf8");
24255
24255
  const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
24256
24256
  if (isUnmodifiedDraft) {
24257
24257
  run ??= history ?? await openWikiWriteContext(cwd, "wiki prune");
24258
24258
  await deleteWikiPage(run, filePath);
24259
- pruned.push(path98.relative(cwd, filePath));
24259
+ pruned.push(path99.relative(cwd, filePath));
24260
24260
  } else {
24261
- orphanedAccepted.push(path98.relative(cwd, filePath));
24261
+ orphanedAccepted.push(path99.relative(cwd, filePath));
24262
24262
  }
24263
24263
  }
24264
24264
  return { pruned, orphanedAccepted };
@@ -24268,7 +24268,7 @@ async function validModuleNames(cwd, dataDir) {
24268
24268
  return counts === undefined ? undefined : new Set(counts.keys());
24269
24269
  }
24270
24270
  async function moduleFileCounts(cwd, dataDir) {
24271
- const nodesPath = path98.join(gdgraphStorageDir(cwd, dataDir), "nodes.jsonl");
24271
+ const nodesPath = path99.join(gdgraphStorageDir(cwd, dataDir), "nodes.jsonl");
24272
24272
  if (!await pathExists(nodesPath)) {
24273
24273
  return;
24274
24274
  }
@@ -24339,9 +24339,9 @@ async function wikiEvidence(input) {
24339
24339
  });
24340
24340
  }
24341
24341
  function resolveEvidenceScope(cwd, override) {
24342
- const absolute = path98.resolve(cwd);
24342
+ const absolute = path99.resolve(cwd);
24343
24343
  return {
24344
- projectId: override?.projectId ?? (path98.basename(absolute) || "project"),
24344
+ projectId: override?.projectId ?? (path99.basename(absolute) || "project"),
24345
24345
  checkoutId: override?.checkoutId ?? `checkout:${createHash19("sha256").update(absolute).digest("hex").slice(0, 16)}`,
24346
24346
  ...override?.workspaceId ? { workspaceId: override.workspaceId } : {},
24347
24347
  ...override?.taskId ? { taskId: override.taskId } : {}
@@ -24356,7 +24356,7 @@ function isMachineAuthoredPage(pageType, relativePath, content) {
24356
24356
  if (source === null) {
24357
24357
  return false;
24358
24358
  }
24359
- const normalised = relativePath.split(path98.sep).join("/").replace(/^wiki\//, "");
24359
+ const normalised = relativePath.split(path99.sep).join("/").replace(/^wiki\//, "");
24360
24360
  return WIKI_PAGE_PRODUCERS.some((producer) => producer.source === source && producer.pageType === pageType && producer.path.test(normalised) && /^-[ \t]+Link:.*\bsha256\b/m.test(content));
24361
24361
  }
24362
24362
  function createGdWikiService() {
@@ -24372,8 +24372,8 @@ function createGdWikiService() {
24372
24372
  };
24373
24373
  }
24374
24374
  async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules, dataDir) {
24375
- const nodesPath = path98.join(gdgraphStorageDir(cwd, dataDir), "nodes.jsonl");
24376
- const edgesPath = path98.join(gdgraphStorageDir(cwd, dataDir), "edges.jsonl");
24375
+ const nodesPath = path99.join(gdgraphStorageDir(cwd, dataDir), "nodes.jsonl");
24376
+ const edgesPath = path99.join(gdgraphStorageDir(cwd, dataDir), "edges.jsonl");
24377
24377
  if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
24378
24378
  return [];
24379
24379
  }
@@ -24460,7 +24460,7 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules,
24460
24460
  };
24461
24461
  const moduleCandidates = [];
24462
24462
  const pageModules = new Set(topModules.map((entry) => entry.name));
24463
- const componentsDir = path98.join(wikiRootPath3(cwd), "components");
24463
+ const componentsDir = path99.join(wikiRootPath3(cwd), "components");
24464
24464
  const existingSlugs = new Set((await pathExists(componentsDir) ? await readdir17(componentsDir) : []).filter((entry) => entry.endsWith(".md")).map((entry) => entry.slice(0, -3)));
24465
24465
  const pageLink = (name) => {
24466
24466
  const slug = slugifyPath(name);
@@ -24568,7 +24568,7 @@ function topCounts(bucket, limit) {
24568
24568
  return [...bucket.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit);
24569
24569
  }
24570
24570
  async function readModuleReadme(cwd, moduleName, pageLink) {
24571
- const readmePath = path98.join(cwd, ...moduleName.split("/"), "README.md");
24571
+ const readmePath = path99.join(cwd, ...moduleName.split("/"), "README.md");
24572
24572
  if (!await pathExists(readmePath)) {
24573
24573
  return null;
24574
24574
  }
@@ -24589,7 +24589,7 @@ async function extractModuleExports(cwd, files) {
24589
24589
  const declRe = /export\s+(?:async\s+)?(?:default\s+)?(?:const|let|var|function|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/g;
24590
24590
  const braceRe = /export\s*\{([^}]+)\}/g;
24591
24591
  for (const file of files.slice(0, 4)) {
24592
- const filePath = path98.join(cwd, ...file.split("/"));
24592
+ const filePath = path99.join(cwd, ...file.split("/"));
24593
24593
  if (!await pathExists(filePath)) {
24594
24594
  continue;
24595
24595
  }
@@ -24620,7 +24620,7 @@ async function extractModuleExports(cwd, files) {
24620
24620
  }
24621
24621
  async function extractModuleApi(cwd, files, dataDir) {
24622
24622
  const names = await extractModuleExports(cwd, files);
24623
- const symbolsPath = path98.join(gdgraphStorageDir(cwd, dataDir), "symbols.jsonl");
24623
+ const symbolsPath = path99.join(gdgraphStorageDir(cwd, dataDir), "symbols.jsonl");
24624
24624
  if (names.length === 0 || !await pathExists(symbolsPath)) {
24625
24625
  return names.map((name) => "`" + name + "`");
24626
24626
  }
@@ -24646,7 +24646,7 @@ async function extractModuleApi(cwd, files, dataDir) {
24646
24646
  });
24647
24647
  }
24648
24648
  async function collectHealthWikiCandidates(cwd, generatedAt) {
24649
- const healthPath = path98.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
24649
+ const healthPath = path99.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
24650
24650
  if (!await pathExists(healthPath)) {
24651
24651
  return [];
24652
24652
  }
@@ -24688,7 +24688,7 @@ async function collectHealthWikiCandidates(cwd, generatedAt) {
24688
24688
  }];
24689
24689
  }
24690
24690
  async function collectTestingWikiCandidates(cwd, generatedAt) {
24691
- const contextPath = path98.join(cwd, ".metaproject", "data", "testing", "context.md");
24691
+ const contextPath = path99.join(cwd, ".metaproject", "data", "testing", "context.md");
24692
24692
  if (!await pathExists(contextPath)) {
24693
24693
  return [];
24694
24694
  }
@@ -24719,8 +24719,8 @@ async function writeCollectedPage(cwd, candidate, force, history) {
24719
24719
  if (!folder) {
24720
24720
  throw new Error(`Unsupported collected wiki type: ${candidate.type}`);
24721
24721
  }
24722
- const filePath = path98.join(wikiRootPath3(cwd), folder, `${candidate.slug}.md`);
24723
- const relativePath = path98.relative(cwd, filePath);
24722
+ const filePath = path99.join(wikiRootPath3(cwd), folder, `${candidate.slug}.md`);
24723
+ const relativePath = path99.relative(cwd, filePath);
24724
24724
  const exists = await pathExists(filePath);
24725
24725
  if (exists && !force) {
24726
24726
  return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
@@ -24771,7 +24771,7 @@ async function writeCollectedPage(cwd, candidate, force, history) {
24771
24771
  async function wikiPagesForFile(cwd, targetRepoPath) {
24772
24772
  const pages = await collectPages(cwd);
24773
24773
  const refs = await Promise.all(pages.map(async (page) => ({
24774
- repoPath: path98.relative(cwd, page.absolutePath).split(path98.sep).join("/"),
24774
+ repoPath: path99.relative(cwd, page.absolutePath).split(path99.sep).join("/"),
24775
24775
  content: await readFile50(page.absolutePath, "utf8")
24776
24776
  })));
24777
24777
  return backlinksFor(buildBacklinkIndex(refs), targetRepoPath);
@@ -24810,7 +24810,7 @@ function renderIndexBody(pages, generatedAt) {
24810
24810
  `).trimEnd();
24811
24811
  }
24812
24812
  async function isIndexStale(cwd, pages) {
24813
- const indexPath = path98.join(wikiRootPath3(cwd), "index.md");
24813
+ const indexPath = path99.join(wikiRootPath3(cwd), "index.md");
24814
24814
  if (!await pathExists(indexPath)) {
24815
24815
  return true;
24816
24816
  }
@@ -24828,7 +24828,7 @@ async function walkMarkdown(root) {
24828
24828
  const results = [];
24829
24829
  const entries = await readdir17(root, { withFileTypes: true });
24830
24830
  for (const entry of entries) {
24831
- const absolutePath = path98.join(root, entry.name);
24831
+ const absolutePath = path99.join(root, entry.name);
24832
24832
  if (entry.isDirectory()) {
24833
24833
  results.push(...await walkMarkdown(absolutePath));
24834
24834
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -24885,7 +24885,7 @@ ${JSON.stringify(state, null, 2)}
24885
24885
  `;
24886
24886
  }
24887
24887
  async function readIndexGeneratedAt(cwd) {
24888
- const indexPath = path98.join(wikiRootPath3(cwd), "index.md");
24888
+ const indexPath = path99.join(wikiRootPath3(cwd), "index.md");
24889
24889
  if (!await pathExists(indexPath)) {
24890
24890
  return null;
24891
24891
  }
@@ -25125,7 +25125,7 @@ async function validateStructure(cwd, pages, issues) {
25125
25125
  if (pattern.includes("*")) {
25126
25126
  continue;
25127
25127
  }
25128
- if (!await pathExists(path98.join(cwd, pattern))) {
25128
+ if (!await pathExists(path99.join(cwd, pattern))) {
25129
25129
  issues.push({
25130
25130
  page: page.relativePath,
25131
25131
  kind: "describes",
@@ -25195,7 +25195,7 @@ async function validatePageInvariants(cwd, pages, issues) {
25195
25195
  }
25196
25196
  }
25197
25197
  function toPosixPath(value) {
25198
- return value.split(path98.sep).join("/");
25198
+ return value.split(path99.sep).join("/");
25199
25199
  }
25200
25200
  function compareSemver(a, b) {
25201
25201
  const pa = a.split(".").map(Number);
@@ -25240,7 +25240,7 @@ var init_service4 = __esm(() => {
25240
25240
  // src/gdgraph/wiki-layer.ts
25241
25241
  import { createHash as createHash20 } from "crypto";
25242
25242
  import { mkdir as mkdir22, stat as stat14, writeFile as writeFile16 } from "fs/promises";
25243
- import path99 from "path";
25243
+ import path100 from "path";
25244
25244
  function storageDir(projectRoot, dataDir) {
25245
25245
  return gdgraphStorageDir(projectRoot, dataDir);
25246
25246
  }
@@ -25308,11 +25308,11 @@ async function enrichBuildWithWikiLayer(input) {
25308
25308
  const mtimes = new Map;
25309
25309
  for (const record of input.fileRecords) {
25310
25310
  try {
25311
- const info = await stat14(path99.join(input.projectRoot, record.path));
25311
+ const info = await stat14(path100.join(input.projectRoot, record.path));
25312
25312
  mtimes.set(record.path, info.mtimeMs);
25313
25313
  } catch {}
25314
25314
  }
25315
- await writeFile16(path99.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
25315
+ await writeFile16(path100.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
25316
25316
  `, "utf8");
25317
25317
  const validModules = input.validModules !== undefined ? input.validModules : await (input.loadValidModules ?? ((root) => defaultLoadValidModules(root, input.dataDir)))(input.projectRoot);
25318
25318
  const wikiPages = await collectPages(input.projectRoot);
@@ -25337,8 +25337,8 @@ async function enrichBuildWithWikiLayer(input) {
25337
25337
  version: page.version
25338
25338
  }))
25339
25339
  });
25340
- await writeJsonl(path99.join(dir, WIKI_PAGES_FILE), layer.pages);
25341
- await writeJsonl(path99.join(dir, DESCRIBES_FILE), layer.describes);
25340
+ await writeJsonl(path100.join(dir, WIKI_PAGES_FILE), layer.pages);
25341
+ await writeJsonl(path100.join(dir, DESCRIBES_FILE), layer.describes);
25342
25342
  return layer;
25343
25343
  }
25344
25344
  async function defaultLoadValidModules(projectRoot, dataDir) {
@@ -25434,7 +25434,7 @@ function personalizedPageRank(nodes, edges, options) {
25434
25434
 
25435
25435
  // src/gdgraph/repomap.ts
25436
25436
  import { mkdir as mkdir24, writeFile as writeFile18 } from "fs/promises";
25437
- import path102 from "path";
25437
+ import path103 from "path";
25438
25438
  function estimateTokens2(text) {
25439
25439
  return Math.ceil(text.length / 4);
25440
25440
  }
@@ -25465,7 +25465,7 @@ function overflowContent(required, missing, budget) {
25465
25465
  `);
25466
25466
  }
25467
25467
  function repomapArtifactPath(cwd) {
25468
- return path102.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
25468
+ return path103.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
25469
25469
  }
25470
25470
  function buildRankEdges(graph, config) {
25471
25471
  const edges = [];
@@ -25602,7 +25602,7 @@ function computeRepomap(graph, config, options = {}) {
25602
25602
  async function writeRepomap(cwd, graph, config, options = {}) {
25603
25603
  const result = computeRepomap(graph, config, options);
25604
25604
  const artifactPath = repomapArtifactPath(cwd);
25605
- await mkdir24(path102.dirname(artifactPath), { recursive: true });
25605
+ await mkdir24(path103.dirname(artifactPath), { recursive: true });
25606
25606
  await writeFile18(artifactPath, result.content, "utf8");
25607
25607
  return { ...result, path: artifactPath };
25608
25608
  }
@@ -25622,7 +25622,7 @@ var init_repomap = __esm(() => {
25622
25622
  // src/gdskills/contracts.ts
25623
25623
  import { readFile as readFile62 } from "fs/promises";
25624
25624
  import { existsSync as existsSync20 } from "fs";
25625
- import path126 from "path";
25625
+ import path127 from "path";
25626
25626
  import { fileURLToPath as fileURLToPath2 } from "url";
25627
25627
  async function loadSchema(name) {
25628
25628
  const contract = CONTRACTS.find((entry) => entry.name === name);
@@ -25633,10 +25633,10 @@ async function loadSchema(name) {
25633
25633
  return JSON.parse(raw);
25634
25634
  }
25635
25635
  function contractPath(contract) {
25636
- const here = path126.dirname(fileURLToPath2(import.meta.url));
25636
+ const here = path127.dirname(fileURLToPath2(import.meta.url));
25637
25637
  if (contract.sourcePath) {
25638
- for (const root of [path126.join(here, "..", ".."), path126.join(here, ".."), here]) {
25639
- const candidate = path126.resolve(root, contract.sourcePath);
25638
+ for (const root of [path127.join(here, "..", ".."), path127.join(here, ".."), here]) {
25639
+ const candidate = path127.resolve(root, contract.sourcePath);
25640
25640
  if (existsSync20(candidate)) {
25641
25641
  return candidate;
25642
25642
  }
@@ -25646,7 +25646,7 @@ function contractPath(contract) {
25646
25646
  if (existsSync20(directPath)) {
25647
25647
  return directPath;
25648
25648
  }
25649
- const packagedSourcePath = path126.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
25649
+ const packagedSourcePath = path127.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
25650
25650
  if (existsSync20(packagedSourcePath)) {
25651
25651
  return packagedSourcePath;
25652
25652
  }
@@ -25829,7 +25829,7 @@ var init_config_dir = __esm(() => {
25829
25829
  // src/session/preservation.ts
25830
25830
  import { createHash as createHash23, randomUUID as randomUUID3 } from "crypto";
25831
25831
  import { closeSync, fsyncSync, mkdirSync as mkdirSync3, openSync, readdirSync as readdirSync3, readFileSync as readFileSync13, renameSync as renameSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
25832
- import path129 from "path";
25832
+ import path130 from "path";
25833
25833
  function syncDir(dir) {
25834
25834
  if (process.platform === "win32")
25835
25835
  return;
@@ -25841,7 +25841,7 @@ function syncDir(dir) {
25841
25841
  }
25842
25842
  }
25843
25843
  function writePreservationFile(file, body) {
25844
- const dir = path129.dirname(file);
25844
+ const dir = path130.dirname(file);
25845
25845
  mkdirSync3(dir, { recursive: true, mode: 448 });
25846
25846
  const tmp = `${file}.${randomUUID3()}.tmp`;
25847
25847
  const fd = openSync(tmp, "wx", 384);
@@ -25866,11 +25866,11 @@ function writePreservationFile(file, body) {
25866
25866
  }
25867
25867
  }
25868
25868
  function readPreservation(dir, snapshotId) {
25869
- const base = path129.join(dir, "preservation");
25869
+ const base = path130.join(dir, "preservation");
25870
25870
  let id = snapshotId;
25871
25871
  if (id === undefined) {
25872
25872
  try {
25873
- id = readFileSync13(path129.join(base, "CURRENT"), "utf8");
25873
+ id = readFileSync13(path130.join(base, "CURRENT"), "utf8");
25874
25874
  } catch (e) {
25875
25875
  if (e.code === "ENOENT")
25876
25876
  return;
@@ -25879,7 +25879,7 @@ function readPreservation(dir, snapshotId) {
25879
25879
  }
25880
25880
  if (!/^[a-f0-9]{64}$/.test(id))
25881
25881
  throw new Error("invalid preservation identity");
25882
- const read = readTranscriptFile(path129.join(base, "generations", `${id}.json`));
25882
+ const read = readTranscriptFile(path130.join(base, "generations", `${id}.json`));
25883
25883
  if (!read.ok)
25884
25884
  throw new Error(`snapshot unreadable: ${read.reason}`);
25885
25885
  if (hash(read.text) !== id)
@@ -25897,9 +25897,9 @@ function readPreservation(dir, snapshotId) {
25897
25897
  return parsed;
25898
25898
  }
25899
25899
  function readPendingHistory(dir) {
25900
- let read = readConfigFile(path129.join(dir, "preservation", "HISTORY"));
25900
+ let read = readConfigFile(path130.join(dir, "preservation", "HISTORY"));
25901
25901
  if (!read.ok && read.reason === "absent") {
25902
- read = readConfigFile(path129.join(dir, "preservation", "MIRRORING"));
25902
+ read = readConfigFile(path130.join(dir, "preservation", "MIRRORING"));
25903
25903
  }
25904
25904
  if (!read.ok) {
25905
25905
  if (read.reason === "absent")
@@ -25923,12 +25923,12 @@ var init_preservation = __esm(() => {
25923
25923
 
25924
25924
  // src/session/slate.ts
25925
25925
  import { mkdir as mkdir33, readFile as readFile66, readdir as readdir23, stat as stat17 } from "fs/promises";
25926
- import path134 from "path";
25926
+ import path135 from "path";
25927
25927
  function isSlateSeedKind(value) {
25928
25928
  return typeof value === "string" && SLATE_SEED_KINDS.includes(value);
25929
25929
  }
25930
25930
  function slatePath(dir) {
25931
- return path134.join(dir, "slate.json");
25931
+ return path135.join(dir, "slate.json");
25932
25932
  }
25933
25933
  function slateLockPath(dir) {
25934
25934
  return `${slatePath(dir)}.lock`;
@@ -26394,7 +26394,7 @@ __export(exports_service10, {
26394
26394
  init_fs();
26395
26395
  init_validator();
26396
26396
  import { mkdir as mkdir13, readFile as readFile39 } from "fs/promises";
26397
- import path77 from "path";
26397
+ import path78 from "path";
26398
26398
 
26399
26399
  // src/flow/machine.ts
26400
26400
  var TRANSITIONS = {
@@ -26593,7 +26593,7 @@ function evaluateTaskGate(tasks) {
26593
26593
  }
26594
26594
 
26595
26595
  // src/review/coverage-complete.ts
26596
- import path53 from "path";
26596
+ import path54 from "path";
26597
26597
 
26598
26598
  // src/lib/shell-quote.ts
26599
26599
  function shellQuote(value) {
@@ -26611,7 +26611,7 @@ init_fs();
26611
26611
  import { createHash as createHash8 } from "crypto";
26612
26612
  import { existsSync as existsSync9 } from "fs";
26613
26613
  init_fs();
26614
- import path52 from "path";
26614
+ import path53 from "path";
26615
26615
 
26616
26616
  // src/review/blast-radius.ts
26617
26617
  init_affected();
@@ -27552,7 +27552,7 @@ var encoder = new TextEncoder;
27552
27552
  // src/review/coverage.ts
27553
27553
  import { existsSync as existsSync8 } from "fs";
27554
27554
  import { readFile as readFile23, realpath as realpath13 } from "fs/promises";
27555
- import path51 from "path";
27555
+ import path52 from "path";
27556
27556
 
27557
27557
  // src/review/git-base.ts
27558
27558
  var SHA = /^[0-9a-f]{7,64}$/i;
@@ -29321,6 +29321,85 @@ async function pendingMutants(packageDir) {
29321
29321
  }
29322
29322
  return unjudgedMutants(packageDir, specs);
29323
29323
  }
29324
+ // src/review/role-switches.ts
29325
+ init_fs();
29326
+ init_json();
29327
+ import path51 from "path";
29328
+ var OPTIONAL_BY_DEFAULT = ["review-clean-code", "review-style"];
29329
+ var ROUND_ROLES_FILE = "round-roles.json";
29330
+ var ROLE_LINE_PREFIX = "\u043E\u043F\u0446\u0438\u043E\u043D\u0430\u043B\u044C\u043D\u044B\u0435 \u0440\u043E\u043B\u0438 \u043D\u0435 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u043B\u0438\u0441\u044C:";
29331
+ var names = (value, field, warnings) => {
29332
+ if (value === undefined)
29333
+ return [];
29334
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
29335
+ warnings.push(`routing.config.json reviewRoles.${field} must be a list of role names; it is ignored`);
29336
+ return [];
29337
+ }
29338
+ return [...new Set(value.map((item) => item.trim()).filter(Boolean))];
29339
+ };
29340
+ async function readRoleConfig(projectRoot) {
29341
+ const none = { disabled: [], enabled: [], warnings: [] };
29342
+ const file = path51.join(projectRoot, "routing.config.json");
29343
+ if (!await pathExists(file))
29344
+ return none;
29345
+ const read = await readJsonObjectFile(file);
29346
+ if (read.state !== "object")
29347
+ return { ...none, warnings: [`${file} could not be read as a JSON object (${read.state}); reviewRoles is ignored`] };
29348
+ const own = read.value.reviewRoles;
29349
+ if (own === undefined)
29350
+ return none;
29351
+ if (own === null || typeof own !== "object" || Array.isArray(own))
29352
+ return { ...none, warnings: ["routing.config.json reviewRoles must be an object with disabled and enabled lists; it is ignored"] };
29353
+ const fields = own;
29354
+ const warnings = [];
29355
+ return { disabled: names(fields.disabled, "disabled", warnings), enabled: names(fields.enabled, "enabled", warnings), warnings };
29356
+ }
29357
+ function decideRoleSwitches(input) {
29358
+ const { roster, config, optIn, protectedRoles } = input;
29359
+ const known = new Set(roster);
29360
+ const warnings = [...config.warnings];
29361
+ const off = new Map;
29362
+ for (const name of OPTIONAL_BY_DEFAULT)
29363
+ off.set(name, `optional role, off by default (--style turns it on)`);
29364
+ if (input.configIgnored !== undefined && config.disabled.length > 0)
29365
+ warnings.push(`reviewRoles.disabled not applied: ${input.configIgnored}`);
29366
+ else {
29367
+ for (const name of config.disabled) {
29368
+ if (protectedRoles.has(name))
29369
+ warnings.push(`reviewRoles.disabled: ${name} is a core role that always runs; it stays on`);
29370
+ else if (!known.has(name))
29371
+ warnings.push(`reviewRoles.disabled: unknown role "${name}"; ignored`);
29372
+ else
29373
+ off.set(name, `disabled by routing.config.json reviewRoles.disabled (--with-role ${name} turns it on)`);
29374
+ }
29375
+ }
29376
+ for (const name of config.enabled) {
29377
+ if (!known.has(name) && !OPTIONAL_BY_DEFAULT.includes(name))
29378
+ warnings.push(`reviewRoles.enabled: unknown role "${name}"; ignored`);
29379
+ else
29380
+ off.delete(name);
29381
+ }
29382
+ for (const name of optIn) {
29383
+ if (!known.has(name) && !OPTIONAL_BY_DEFAULT.includes(name))
29384
+ warnings.push(`--with-role: unknown role "${name}"; ignored`);
29385
+ else
29386
+ off.delete(name);
29387
+ }
29388
+ for (const name of [...off.keys()])
29389
+ if (!known.has(name))
29390
+ off.delete(name);
29391
+ return { off, warnings };
29392
+ }
29393
+ async function packageEnabledRoles(packageDir) {
29394
+ const read = await readJsonObjectFile(path51.join(packageDir, ROUND_ROLES_FILE)).catch(() => {
29395
+ return;
29396
+ });
29397
+ if (read?.state !== "object" || !Array.isArray(read.value.enabled))
29398
+ return [];
29399
+ return read.value.enabled.filter((item) => typeof item === "string" && item.trim() !== "");
29400
+ }
29401
+ var LINE = new RegExp(`^${ROLE_LINE_PREFIX}.*$`, "m");
29402
+
29324
29403
  // src/review/coverage.ts
29325
29404
  var LIGHT_MAX_FILES = 5;
29326
29405
  var LIGHT_MAX_CHANGED_LINES = 300;
@@ -29332,8 +29411,8 @@ function overlayChangedByRound(reviewer, context) {
29332
29411
  return;
29333
29412
  if (context.files === undefined)
29334
29413
  return `${reviewer.name} is a project overlay and the round's changed files are not recorded, so it cannot be ruled out that this branch wrote it`;
29335
- const absolute = path51.isAbsolute(reviewer.path) ? reviewer.path : path51.resolve(context.root ?? process.cwd(), reviewer.path);
29336
- const dir = path51.relative(context.root ?? process.cwd(), path51.dirname(absolute)).split(path51.sep).join("/");
29414
+ const absolute = path52.isAbsolute(reviewer.path) ? reviewer.path : path52.resolve(context.root ?? process.cwd(), reviewer.path);
29415
+ const dir = path52.relative(context.root ?? process.cwd(), path52.dirname(absolute)).split(path52.sep).join("/");
29337
29416
  const changed = context.files.find((file) => file === dir || file.startsWith(`${dir}/`));
29338
29417
  return changed === undefined ? undefined : `${reviewer.name} is a project overlay this round changes (${changed})`;
29339
29418
  }
@@ -29398,7 +29477,7 @@ async function autoDepth(root, input) {
29398
29477
  }
29399
29478
  var ROUND_DEPTH_FILE = "round-depth.json";
29400
29479
  async function packageDepthBasis(packageDir) {
29401
- const manifest = await readFile23(path51.join(packageDir, "manifest.json"), "utf8").then((t) => JSON.parse(t)).catch(() => {
29480
+ const manifest = await readFile23(path52.join(packageDir, "manifest.json"), "utf8").then((t) => JSON.parse(t)).catch(() => {
29402
29481
  return;
29403
29482
  });
29404
29483
  const head = manifest?.target?.head;
@@ -29407,7 +29486,7 @@ async function packageDepthBasis(packageDir) {
29407
29486
  }
29408
29487
  async function packageChangedLines(packageDir) {
29409
29488
  try {
29410
- const parsed = JSON.parse(await readFile23(path51.join(packageDir, "scope-files.json"), "utf8"));
29489
+ const parsed = JSON.parse(await readFile23(path52.join(packageDir, "scope-files.json"), "utf8"));
29411
29490
  return typeof parsed?.changedLines === "number" && Number.isFinite(parsed.changedLines) && parsed.changedLines >= 0 ? parsed.changedLines : undefined;
29412
29491
  } catch {
29413
29492
  return;
@@ -29416,7 +29495,7 @@ async function packageChangedLines(packageDir) {
29416
29495
  async function packageRoundDepth(packageDir) {
29417
29496
  let parsed;
29418
29497
  try {
29419
- parsed = JSON.parse(await readFile23(path51.join(packageDir, ROUND_DEPTH_FILE), "utf8"));
29498
+ parsed = JSON.parse(await readFile23(path52.join(packageDir, ROUND_DEPTH_FILE), "utf8"));
29420
29499
  } catch {
29421
29500
  return;
29422
29501
  }
@@ -29469,7 +29548,7 @@ function derivedFromFiles(files) {
29469
29548
  return picked;
29470
29549
  }
29471
29550
  async function readSkill(root, relativePath) {
29472
- const file = path51.join(root, relativePath, "SKILL.md");
29551
+ const file = path52.join(root, relativePath, "SKILL.md");
29473
29552
  return existsSync8(file) ? readFile23(file, "utf8").catch(() => {
29474
29553
  return;
29475
29554
  }) : undefined;
@@ -29579,6 +29658,21 @@ async function requiredReviewers(root, mode, files, options = {}) {
29579
29658
  projectGates.set(reviewer.name, reviewer.paths.map(globToRegExp2));
29580
29659
  }
29581
29660
  const filesKnown = files !== undefined;
29661
+ const switches = decideRoleSwitches({
29662
+ roster,
29663
+ config: await readRoleConfig(root),
29664
+ optIn: options.enabledRoles ?? [],
29665
+ protectedRoles: NEVER_SUPERSEDED,
29666
+ configIgnored: files?.some((file) => file === "routing.config.json") ? "this round changes routing.config.json, so a branch cannot switch roles off for its own review" : undefined
29667
+ });
29668
+ const rolesOff = [...switches.off.keys()].sort();
29669
+ const warnings = switches.warnings;
29670
+ const switchedOff = (name) => switches.off.has(name);
29671
+ for (const name of roster)
29672
+ if (switchedOff(name))
29673
+ excluded.push({ reviewer: name, reason: switches.off.get(name) });
29674
+ roster.splice(0, roster.length, ...roster.filter((name) => !switchedOff(name)));
29675
+ const switchFields = { ...warnings.length === 0 ? {} : { warnings }, ...rolesOff.length === 0 ? {} : { rolesOff } };
29582
29676
  if (options.depth === "light") {
29583
29677
  const conventions = lightConventionsReviewer(roster, inventory);
29584
29678
  const keep = new Set([...LIGHT_FIXED_REVIEWERS, ...conventions === undefined ? [] : [conventions]]);
@@ -29591,7 +29685,7 @@ async function requiredReviewers(root, mode, files, options = {}) {
29591
29685
  excluded.push({ reviewer: name, reason: "light round: not part of the light set" });
29592
29686
  const notes = [];
29593
29687
  const kept = applySupersedes(light, inventory, excluded, { root, files }, notes).sort();
29594
- return { mode, depth: "light", required: kept, excluded, filesKnown, ...notes.length === 0 ? {} : { notes } };
29688
+ return { mode, depth: "light", required: kept, excluded, filesKnown, ...notes.length === 0 ? {} : { notes }, ...switchFields };
29595
29689
  }
29596
29690
  const gated = (name) => {
29597
29691
  if (!filesKnown)
@@ -29633,7 +29727,7 @@ async function requiredReviewers(root, mode, files, options = {}) {
29633
29727
  }
29634
29728
  const notes = [];
29635
29729
  const collapsed = applyOverlapGroups(applySupersedes(required, inventory, excluded, { root, files }, notes), inventory, files, excluded, { root }, notes).sort();
29636
- return { mode, depth: "full", required: collapsed, excluded, filesKnown, ...notes.length === 0 ? {} : { notes } };
29730
+ return { mode, depth: "full", required: collapsed, excluded, filesKnown, ...notes.length === 0 ? {} : { notes }, ...switchFields };
29637
29731
  }
29638
29732
  async function gitDiffAt(cwd, base, head, pathspec) {
29639
29733
  try {
@@ -29698,7 +29792,7 @@ async function packageDiffStats(options) {
29698
29792
  return packageDiffStatsCached({ packageDir: options.packageDir, root: options.root, target: { ...target, head: target.head } });
29699
29793
  }
29700
29794
  async function readPackageTarget(packageDir) {
29701
- const manifest = await readFile23(path51.join(packageDir, "manifest.json"), "utf8").then((t) => JSON.parse(t)).catch(() => {
29795
+ const manifest = await readFile23(path52.join(packageDir, "manifest.json"), "utf8").then((t) => JSON.parse(t)).catch(() => {
29702
29796
  return;
29703
29797
  });
29704
29798
  const target = asRecord(asRecord(manifest)?.target) ?? {};
@@ -29737,8 +29831,8 @@ async function diffOfTarget({ packageDir, root, target }) {
29737
29831
  const resolved = await resolveDiffBases(cwd, target);
29738
29832
  if ("error" in resolved)
29739
29833
  return { error: `${UNRESOLVED}: ${resolved.error} (${where(target.recordedBase)})` };
29740
- const realRoot = await realpath13(path51.resolve(root)).catch(() => path51.resolve(root));
29741
- const pathspec = notReviewPackagesAt(path51.relative(cwd, realRoot));
29834
+ const realRoot = await realpath13(path52.resolve(root)).catch(() => path52.resolve(root));
29835
+ const pathspec = notReviewPackagesAt(path52.relative(cwd, realRoot));
29742
29836
  const results = await Promise.all(resolved.bases.map((base) => gitDiffAt(cwd, base, target.head, pathspec)));
29743
29837
  const diffs = [];
29744
29838
  for (const [index, result] of results.entries()) {
@@ -29770,7 +29864,7 @@ async function effectiveDepth(record, options) {
29770
29864
  }
29771
29865
  async function packageHead(packageDir) {
29772
29866
  try {
29773
- const manifest = JSON.parse(await readFile23(path51.join(packageDir, "manifest.json"), "utf8"));
29867
+ const manifest = JSON.parse(await readFile23(path52.join(packageDir, "manifest.json"), "utf8"));
29774
29868
  return typeof manifest.target?.head === "string" && manifest.target.head.trim() !== "" ? manifest.target.head.trim() : undefined;
29775
29869
  } catch {
29776
29870
  return;
@@ -29779,7 +29873,8 @@ async function packageHead(packageDir) {
29779
29873
  async function reviewersLeftOut(packageDir, selected) {
29780
29874
  const need = await requiredReviewers(projectRootOfPackage(packageDir), "all", await packageScopeFiles(packageDir), {
29781
29875
  blastRadius: await packageHasBlastRadius(packageDir),
29782
- prContext: packageHasPrContext(packageDir)
29876
+ prContext: packageHasPrContext(packageDir),
29877
+ enabledRoles: await packageEnabledRoles(packageDir)
29783
29878
  });
29784
29879
  return { required: need.required, missing: selected === undefined ? need.required : need.required.filter((role) => !selected.includes(role)) };
29785
29880
  }
@@ -29800,7 +29895,7 @@ async function unconfirmedDecision(options, kind, selected) {
29800
29895
  return `${stale}${writersFor(kind, dir)}`;
29801
29896
  }
29802
29897
  function writersFor(kind, packageDir) {
29803
- return decisionWriters(kind, packageDir === undefined ? "<review-dir>" : path51.relative(process.cwd(), packageDir) || ".");
29898
+ return decisionWriters(kind, packageDir === undefined ? "<review-dir>" : path52.relative(process.cwd(), packageDir) || ".");
29804
29899
  }
29805
29900
  async function mutationErrors(record, options, depth) {
29806
29901
  const pending = options.pendingMutants ?? 0;
@@ -29826,14 +29921,14 @@ async function mutationErrors(record, options, depth) {
29826
29921
  }
29827
29922
  async function packageHasBlastRadius(packageDir, name = "blast-radius.json") {
29828
29923
  try {
29829
- const parsed = JSON.parse(await readFile23(path51.join(packageDir, name), "utf8"));
29924
+ const parsed = JSON.parse(await readFile23(path52.join(packageDir, name), "utf8"));
29830
29925
  return Array.isArray(parsed?.files) && Array.isArray(parsed?.changedFiles);
29831
29926
  } catch {
29832
29927
  return false;
29833
29928
  }
29834
29929
  }
29835
29930
  function packageHasPrContext(packageDir, name = "pr-context.md") {
29836
- return existsSync8(path51.join(packageDir, name));
29931
+ return existsSync8(path52.join(packageDir, name));
29837
29932
  }
29838
29933
  async function coverageErrors(dispatch, options) {
29839
29934
  const record = asRecord(dispatch);
@@ -29865,7 +29960,8 @@ async function reviewerSetErrors(dispatch, options, effective) {
29865
29960
  const need = await requiredReviewers(options.root, record.mode, options.files, {
29866
29961
  blastRadius: options.blastRadius,
29867
29962
  prContext: options.prContext === true && dispatchKnowsRole(record, PR_CONTRACT),
29868
- depth: effective?.depth ?? "full"
29963
+ depth: effective?.depth ?? "full",
29964
+ enabledRoles: options.packageDir === undefined ? [] : await packageEnabledRoles(options.packageDir)
29869
29965
  });
29870
29966
  const selected = new Set(Array.isArray(record.selected) ? record.selected.filter(text) : []);
29871
29967
  const skips = dispatchSkips(record).filter((skip) => need.required.includes(skip.reviewer) && !selected.has(skip.reviewer));
@@ -29925,20 +30021,20 @@ function dispatchSkips(dispatch) {
29925
30021
  }
29926
30022
  async function packageScopeFiles(packageDir) {
29927
30023
  try {
29928
- const parsed = JSON.parse(await readFile23(path51.join(packageDir, "scope-files.json"), "utf8"));
30024
+ const parsed = JSON.parse(await readFile23(path52.join(packageDir, "scope-files.json"), "utf8"));
29929
30025
  return Array.isArray(parsed?.files) && parsed.files.every((f) => typeof f === "string") ? parsed.files : undefined;
29930
30026
  } catch {
29931
30027
  return;
29932
30028
  }
29933
30029
  }
29934
30030
  function projectRootOfPackage(packageDir) {
29935
- const resolved = path51.resolve(packageDir);
29936
- const parts = resolved.split(path51.sep);
30031
+ const resolved = path52.resolve(packageDir);
30032
+ const parts = resolved.split(path52.sep);
29937
30033
  const at = parts.lastIndexOf(".metaproject");
29938
30034
  if (at > 0)
29939
- return parts.slice(0, at).join(path51.sep) || path51.sep;
30035
+ return parts.slice(0, at).join(path52.sep) || path52.sep;
29940
30036
  const found = resolveProjectRoot(resolved);
29941
- return found !== resolved ? found : path51.resolve(resolved, "..", "..", "..");
30037
+ return found !== resolved ? found : path52.resolve(resolved, "..", "..", "..");
29942
30038
  }
29943
30039
 
29944
30040
  // src/review/conform-state.ts
@@ -30093,14 +30189,14 @@ var CHUNK_STATE_FILE = "chunk-state.json";
30093
30189
  var CHUNK_REVIEWER = BLAST_RADIUS_SCOPE_REVIEWER;
30094
30190
  var readJson = (file) => readJsonFileOr(file, undefined);
30095
30191
  async function readChunkPlan(packageDir) {
30096
- const plan = await readJson(path52.join(packageDir, CHUNKS_FILE));
30192
+ const plan = await readJson(path53.join(packageDir, CHUNKS_FILE));
30097
30193
  return plan !== undefined && Array.isArray(plan.chunks) ? plan : undefined;
30098
30194
  }
30099
30195
  function emptyChunkState() {
30100
30196
  return { schemaVersion: 1, retry: emptyRetryState(), derived: [], outcomes: {} };
30101
30197
  }
30102
30198
  async function readChunkState(packageDir) {
30103
- const state = await readJson(path52.join(packageDir, CHUNK_STATE_FILE));
30199
+ const state = await readJson(path53.join(packageDir, CHUNK_STATE_FILE));
30104
30200
  return state !== undefined && state.retry !== undefined && Array.isArray(state.derived) && state.outcomes !== undefined ? state : emptyChunkState();
30105
30201
  }
30106
30202
  var textOf = (entry) => `${entry.files.join(`
@@ -30197,7 +30293,7 @@ async function computeChunkPass(packageDir) {
30197
30293
  return pass;
30198
30294
  }
30199
30295
  function hasChunkPlan(packageDir) {
30200
- return existsSync9(path52.join(packageDir, CHUNKS_FILE));
30296
+ return existsSync9(path53.join(packageDir, CHUNKS_FILE));
30201
30297
  }
30202
30298
 
30203
30299
  // src/review/coverage-complete.ts
@@ -30207,7 +30303,7 @@ var SLICE_MANIFEST_COPY = "slice-manifest.json";
30207
30303
  var readJson2 = (file) => readJsonFileOr(file, undefined);
30208
30304
  var text2 = (value) => typeof value === "string" && value.trim().length > 0;
30209
30305
  async function readManifest(packageDir) {
30210
- for (const candidate of [path53.join(packageDir, "slices", "manifest.json"), path53.join(packageDir, SLICE_MANIFEST_COPY)]) {
30306
+ for (const candidate of [path54.join(packageDir, "slices", "manifest.json"), path54.join(packageDir, SLICE_MANIFEST_COPY)]) {
30211
30307
  const found = await readJson2(candidate);
30212
30308
  if (found !== undefined && Array.isArray(found.slices))
30213
30309
  return found;
@@ -30245,9 +30341,9 @@ function scopeBRunComplete(dispatch) {
30245
30341
  async function packageRecordsCoverage(packageDir, research) {
30246
30342
  if (hasChunkPlan(packageDir))
30247
30343
  return true;
30248
- if (await readJson2(path53.join(packageDir, COVERAGE_FILE)) !== undefined)
30344
+ if (await readJson2(path54.join(packageDir, COVERAGE_FILE)) !== undefined)
30249
30345
  return true;
30250
- const ledger = research ?? await readJson2(path53.join(packageDir, "research.json"));
30346
+ const ledger = research ?? await readJson2(path54.join(packageDir, "research.json"));
30251
30347
  return dispatchRunRecords(asRecord(ledger)?.dispatch).some((run) => Array.isArray(run.coveredSlices));
30252
30348
  }
30253
30349
  function readCoverageWaiver(dispatch) {
@@ -30261,11 +30357,11 @@ function readCoverageWaiver(dispatch) {
30261
30357
  return { operatorQuote: waiver.operatorQuote, time: waiver.time, files, ...via === undefined ? {} : { confirmedVia: via }, ...cardPressFields({ pressedBy, pressedAt }) };
30262
30358
  }
30263
30359
  async function computeCoverage(packageDir, options = {}) {
30264
- const research = options.research ?? await readJson2(path53.join(packageDir, "research.json"));
30360
+ const research = options.research ?? await readJson2(path54.join(packageDir, "research.json"));
30265
30361
  const dispatch = asRecord(asRecord(research)?.dispatch);
30266
- const radius = await readJson2(path53.join(packageDir, "blast-radius.json"));
30362
+ const radius = await readJson2(path54.join(packageDir, "blast-radius.json"));
30267
30363
  const manifest = await readManifest(packageDir);
30268
- const retry = await readJson2(path53.join(packageDir, "retry-state.json"));
30364
+ const retry = await readJson2(path54.join(packageDir, "retry-state.json"));
30269
30365
  const scopeA = await packageScopeFiles(packageDir) ?? [];
30270
30366
  const chunkPass = hasChunkPlan(packageDir) ? await computeChunkPass(packageDir) : null;
30271
30367
  const radiusFiles = (radius?.files ?? []).map((entry) => entry.file).filter(text2);
@@ -30353,7 +30449,7 @@ async function coverageGateErrors(packageDir, research) {
30353
30449
  const uncovered = report.files.filter((entry) => entry.status === "uncovered");
30354
30450
  const first = uncovered.slice(0, FIRST_FILES).map((entry) => entry.file);
30355
30451
  const more = uncovered.length > FIRST_FILES ? `, \u2026 (+${uncovered.length - FIRST_FILES})` : "";
30356
- const dir = shellWord(path53.relative(process.cwd(), packageDir) || ".");
30452
+ const dir = shellWord(path54.relative(process.cwd(), packageDir) || ".");
30357
30453
  const chunkWork = uncovered.some((entry) => entry.scope === "B");
30358
30454
  const sliceWork = uncovered.some((entry) => entry.scope === "A");
30359
30455
  const commands = [
@@ -30422,7 +30518,7 @@ function dispatchErrors(value) {
30422
30518
 
30423
30519
  // src/review/research.ts
30424
30520
  import { readFile as readFile24 } from "fs/promises";
30425
- import path54 from "path";
30521
+ import path55 from "path";
30426
30522
  function researchErrors(value, findings) {
30427
30523
  const ledger = asRecord(value);
30428
30524
  if (ledger === undefined)
@@ -30486,7 +30582,7 @@ async function packageResearchErrors(packageDir, artifacts, findings, options =
30486
30582
  if (a.research !== "research.json")
30487
30583
  return ["invalid research artifact locator"];
30488
30584
  try {
30489
- const ledger = JSON.parse(await readFile24(path54.join(packageDir, "research.json"), "utf8"));
30585
+ const ledger = JSON.parse(await readFile24(path55.join(packageDir, "research.json"), "utf8"));
30490
30586
  const recorded = ledger?.dispatch !== undefined;
30491
30587
  const checked = a.reviewerDispatch !== undefined || recorded;
30492
30588
  const mismatch = recorded && a.reviewerDispatch === undefined ? ['research.json records a reviewer dispatch but manifest.json does not declare it: restore artifacts.reviewerDispatch "research.json"'] : [];
@@ -30549,11 +30645,11 @@ var CARRIED_PREMISE_CONTEXT = new Set(["judge", "model", "operator"]);
30549
30645
  // src/flow/review-gate.ts
30550
30646
  init_fs();
30551
30647
  import { readFile as readFile27 } from "fs/promises";
30552
- import path57 from "path";
30648
+ import path58 from "path";
30553
30649
 
30554
30650
  // src/review/package-location.ts
30555
30651
  import { readdir as readdir12, readFile as readFile25 } from "fs/promises";
30556
- import path55 from "path";
30652
+ import path56 from "path";
30557
30653
 
30558
30654
  // src/lib/map-bounded.ts
30559
30655
  async function mapBounded(items, limit, map) {
@@ -30569,15 +30665,15 @@ async function mapBounded(items, limit, map) {
30569
30665
 
30570
30666
  // src/review/package-location.ts
30571
30667
  function reviewsRoot(cwd) {
30572
- return path55.join(cwd, ".metaproject", "reviews");
30668
+ return path56.join(cwd, ".metaproject", "reviews");
30573
30669
  }
30574
30670
  function flowReviewsRoot(cwd, flowDir) {
30575
- return path55.join(flowsRoot(cwd), flowDir, "reviews");
30671
+ return path56.join(flowsRoot(cwd), flowDir, "reviews");
30576
30672
  }
30577
30673
  async function readManifestHead(packageDir) {
30578
30674
  let manifest;
30579
30675
  try {
30580
- manifest = JSON.parse(await readFile25(path55.join(packageDir, "manifest.json"), "utf8"));
30676
+ manifest = JSON.parse(await readFile25(path56.join(packageDir, "manifest.json"), "utf8"));
30581
30677
  } catch {
30582
30678
  return;
30583
30679
  }
@@ -30589,13 +30685,13 @@ async function readManifestHead(packageDir) {
30589
30685
  return { reviewId: str(fields.reviewId), mode: str(fields.mode), status: str(fields.status), flowId: str(flow.id), flowPath: str(flow.path) };
30590
30686
  }
30591
30687
  function boundToFlow(head, flowDir) {
30592
- if (head.flowPath !== undefined && path55.posix.normalize(head.flowPath.split(path55.sep).join("/")) === path55.posix.join(".metaproject", "flows", flowDir))
30688
+ if (head.flowPath !== undefined && path56.posix.normalize(head.flowPath.split(path56.sep).join("/")) === path56.posix.join(".metaproject", "flows", flowDir))
30593
30689
  return true;
30594
30690
  return head.flowId !== undefined && head.flowId !== "" && (flowDir === head.flowId || flowDir.startsWith(`${head.flowId}-`));
30595
30691
  }
30596
30692
  async function dirsUnder(root) {
30597
30693
  try {
30598
- return (await readdir12(root, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => path55.join(root, entry.name));
30694
+ return (await readdir12(root, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => path56.join(root, entry.name));
30599
30695
  } catch {
30600
30696
  return [];
30601
30697
  }
@@ -30615,8 +30711,8 @@ async function flowPackageDirs(cwd, flowDir, standalone) {
30615
30711
  return [...own, ...heads.filter(({ head }) => boundToFlow(head, flowDir)).map(({ dir }) => dir)];
30616
30712
  }
30617
30713
  var REVIEW_PACKAGE_MANIFEST_GLOBS = [
30618
- path55.posix.join(".metaproject", "reviews", "*", "manifest.json"),
30619
- path55.posix.join(".metaproject", "flows", "*", "reviews", "*", "manifest.json")
30714
+ path56.posix.join(".metaproject", "reviews", "*", "manifest.json"),
30715
+ path56.posix.join(".metaproject", "flows", "*", "reviews", "*", "manifest.json")
30620
30716
  ];
30621
30717
 
30622
30718
  // src/review/loop.ts
@@ -30660,12 +30756,12 @@ function normalizeText(value) {
30660
30756
  // src/review/pr-comments.ts
30661
30757
  init_fs();
30662
30758
  import { readFile as readFile26 } from "fs/promises";
30663
- import path56 from "path";
30759
+ import path57 from "path";
30664
30760
  var SEVERITY_SET = new Set(["blocker", "major", "minor", "info"]);
30665
30761
  var KNOWN_REVIEW_STATES = new Set(["APPROVED", "CHANGES_REQUESTED", "COMMENTED", "DISMISSED", "PENDING"]);
30666
30762
  var PR_COMMENT_STATE_VERSION = 1;
30667
30763
  function prCommentsStatePath(cwd, repo, number) {
30668
- return path56.join(cwd, ".metaproject", "reviews", "pr-comments", `${repo.replace(/\//g, "__")}__${number}.json`);
30764
+ return path57.join(cwd, ".metaproject", "reviews", "pr-comments", `${repo.replace(/\//g, "__")}__${number}.json`);
30669
30765
  }
30670
30766
  function emptyPrCommentState(repo, number) {
30671
30767
  return {
@@ -30724,7 +30820,7 @@ function safeFsErrorCode(error) {
30724
30820
  return typeof code === "string" && /^[A-Z][A-Z0-9]{2,15}$/.test(code) ? code : undefined;
30725
30821
  }
30726
30822
  async function readReviewGateConfig(cwd) {
30727
- const file = path57.join(cwd, REVIEW_GATE_CONFIG_PATH);
30823
+ const file = path58.join(cwd, REVIEW_GATE_CONFIG_PATH);
30728
30824
  if (!await pathExists(file)) {
30729
30825
  return { ...DEFAULT_REVIEW_GATE_CONFIG, notes: [] };
30730
30826
  }
@@ -30876,13 +30972,13 @@ function matchNumber(text, key) {
30876
30972
  async function readReviewRounds(cwd, flowDir) {
30877
30973
  const rounds = [];
30878
30974
  for (const packageDir of await flowPackageDirs(cwd, flowDir)) {
30879
- const name = path57.basename(packageDir);
30975
+ const name = path58.basename(packageDir);
30880
30976
  const problems = [];
30881
- const manifest = readRecord(await readJson3(path57.join(packageDir, "manifest.json")));
30977
+ const manifest = readRecord(await readJson3(path58.join(packageDir, "manifest.json")));
30882
30978
  if (manifest === null) {
30883
30979
  problems.push("manifest.json is missing or unreadable");
30884
30980
  }
30885
- const rawFindings = await readJson3(path57.join(packageDir, "findings.json"));
30981
+ const rawFindings = await readJson3(path58.join(packageDir, "findings.json"));
30886
30982
  if (!Array.isArray(rawFindings)) {
30887
30983
  problems.push("findings.json is missing, unreadable, or not an array");
30888
30984
  }
@@ -30900,14 +30996,14 @@ async function readReviewRounds(cwd, flowDir) {
30900
30996
  }
30901
30997
  ];
30902
30998
  }) : [];
30903
- const scopePath = path57.join(packageDir, "scope.md");
30999
+ const scopePath = path58.join(packageDir, "scope.md");
30904
31000
  const scope = await pathExists(scopePath) ? await readScopeMarkdown(scopePath) : null;
30905
31001
  const completeness = readString(manifest?.["status"]) !== "closed" && await packageRecordsCoverage(packageDir);
30906
31002
  problems.push(...await packageResearchErrors(packageDir, manifest?.["artifacts"], rawFindings, { completeness }));
30907
31003
  const findings = Array.isArray(rawFindings) ? await findingsWithHolds(rawFindings.map((item, index) => toGateFinding(item, reviewId, index)), packageDir, problems) : [];
30908
31004
  rounds.push({
30909
31005
  reviewId,
30910
- dir: path57.relative(cwd, packageDir),
31006
+ dir: path58.relative(cwd, packageDir),
30911
31007
  sortKey: readString(manifest?.["createdAt"]) ?? name,
30912
31008
  ingested: problems.length === 0,
30913
31009
  problems,
@@ -31194,7 +31290,7 @@ var durableExternalCommentsGate = async (input) => {
31194
31290
  return {
31195
31291
  collected: false,
31196
31292
  unanswered: [],
31197
- detail: `nothing records whether anyone commented on ${ref.repo}#${ref.number} ` + `(\`${path57.relative(input.cwd, file)}\` does not exist). Zero collected comments and no collection at ` + "all are different facts, and only one of them is clean. Run " + `\`keryx review comments collect --repo ${ref.repo} --pr ${ref.number} --sha <pr-head>\`, or inject ` + "`FlowServiceDeps.externalCommentsGate` with a collector of your own."
31293
+ detail: `nothing records whether anyone commented on ${ref.repo}#${ref.number} ` + `(\`${path58.relative(input.cwd, file)}\` does not exist). Zero collected comments and no collection at ` + "all are different facts, and only one of them is clean. Run " + `\`keryx review comments collect --repo ${ref.repo} --pr ${ref.number} --sha <pr-head>\`, or inject ` + "`FlowServiceDeps.externalCommentsGate` with a collector of your own."
31198
31294
  };
31199
31295
  }
31200
31296
  const state = await readPrCommentState(input.cwd, ref.repo, ref.number);
@@ -31783,14 +31879,14 @@ function describeIdentity(identity) {
31783
31879
  // src/review/flow-move.ts
31784
31880
  init_fs();
31785
31881
  import { readdir as readdir14, readFile as readFile29, rename as rename3 } from "fs/promises";
31786
- import path61 from "path";
31882
+ import path62 from "path";
31787
31883
 
31788
31884
  // src/review/review-notes.ts
31789
31885
  init_fs();
31790
31886
  init_store();
31791
- import path60 from "path";
31887
+ import path61 from "path";
31792
31888
  function reviewNotesDir(cwd) {
31793
- return path60.join(memoryRoot(cwd), "review-notes");
31889
+ return path61.join(memoryRoot(cwd), "review-notes");
31794
31890
  }
31795
31891
 
31796
31892
  // src/review/flow-move.ts
@@ -31798,16 +31894,16 @@ var RECORDED_FLOWS_ROOT = ".metaproject/flows";
31798
31894
  var SCOPE_FLOW_LINE = /^flow: (\d{3})\b/m;
31799
31895
  var NOTE_PATH_LINE = /^(- (?:Link|Location): `?)([^`\s]+)/gm;
31800
31896
  async function moveFlowDirWithReviewRecords(move) {
31801
- const fromRoot = path61.join(flowsRoot(move.cwd), move.fromDir);
31802
- const toRoot = path61.join(flowsRoot(move.cwd), move.toDir);
31803
- const plan = await planReviewRecordRewrites(move, fromRoot, (file) => path61.relative(move.cwd, file.startsWith(`${fromRoot}${path61.sep}`) ? path61.join(toRoot, path61.relative(fromRoot, file)) : file));
31897
+ const fromRoot = path62.join(flowsRoot(move.cwd), move.fromDir);
31898
+ const toRoot = path62.join(flowsRoot(move.cwd), move.toDir);
31899
+ const plan = await planReviewRecordRewrites(move, fromRoot, (file) => path62.relative(move.cwd, file.startsWith(`${fromRoot}${path62.sep}`) ? path62.join(toRoot, path62.relative(fromRoot, file)) : file));
31804
31900
  const written = [];
31805
31901
  try {
31806
31902
  for (const rewrite of plan.rewrites) {
31807
31903
  await writeFileAtomic(rewrite.current, rewrite.after);
31808
31904
  written.push(rewrite);
31809
31905
  }
31810
- await rename3(path61.join(flowsRoot(move.cwd), move.fromDir), path61.join(flowsRoot(move.cwd), move.toDir));
31906
+ await rename3(path62.join(flowsRoot(move.cwd), move.fromDir), path62.join(flowsRoot(move.cwd), move.toDir));
31811
31907
  } catch (error) {
31812
31908
  const unrestored = await restore(written);
31813
31909
  if (unrestored.length > 0) {
@@ -31833,14 +31929,14 @@ async function planReviewRecordRewrites(move, packagesRoot, finalOf) {
31833
31929
  const newPrefix = `${RECORDED_FLOWS_ROOT}/${move.toDir}`;
31834
31930
  const movePath = (value) => value === oldPrefix || value.startsWith(`${oldPrefix}/`) ? `${newPrefix}${value.slice(oldPrefix.length)}` : value;
31835
31931
  const plan = { rewrites: [], unreadable: [] };
31836
- const reviewsDir = path61.join(packagesRoot, "reviews");
31932
+ const reviewsDir = path62.join(packagesRoot, "reviews");
31837
31933
  if (await pathExists(reviewsDir)) {
31838
31934
  for (const entry of await readdir14(reviewsDir, { withFileTypes: true })) {
31839
31935
  if (!entry.isDirectory()) {
31840
31936
  continue;
31841
31937
  }
31842
- const packageDir = path61.join(reviewsDir, entry.name);
31843
- await planJson(plan, path61.join(packageDir, "manifest.json"), finalOf, (value) => {
31938
+ const packageDir = path62.join(reviewsDir, entry.name);
31939
+ await planJson(plan, path62.join(packageDir, "manifest.json"), finalOf, (value) => {
31844
31940
  const moved = mapStrings(value, movePath);
31845
31941
  const flow = asRecord3(asRecord3(moved)?.["flow"]);
31846
31942
  if (flow !== null && flow["id"] === move.from) {
@@ -31848,8 +31944,8 @@ async function planReviewRecordRewrites(move, packagesRoot, finalOf) {
31848
31944
  }
31849
31945
  return moved;
31850
31946
  });
31851
- await planJson(plan, path61.join(packageDir, "findings.json"), finalOf, (value) => mapStrings(value, movePath));
31852
- await planText(plan, path61.join(packageDir, "scope.md"), finalOf, (text) => text.replace(SCOPE_FLOW_LINE, (line, id) => id === move.from ? `flow: ${move.to}` : line));
31947
+ await planJson(plan, path62.join(packageDir, "findings.json"), finalOf, (value) => mapStrings(value, movePath));
31948
+ await planText(plan, path62.join(packageDir, "scope.md"), finalOf, (text) => text.replace(SCOPE_FLOW_LINE, (line, id) => id === move.from ? `flow: ${move.to}` : line));
31853
31949
  }
31854
31950
  }
31855
31951
  const notesDir = reviewNotesDir(move.cwd);
@@ -31858,7 +31954,7 @@ async function planReviewRecordRewrites(move, packagesRoot, finalOf) {
31858
31954
  if (!entry.isFile() || !entry.name.endsWith(".md")) {
31859
31955
  continue;
31860
31956
  }
31861
- await planText(plan, path61.join(notesDir, entry.name), finalOf, (text) => text.replace(NOTE_PATH_LINE, (_line, lead, value) => `${lead}${movePath(value)}`));
31957
+ await planText(plan, path62.join(notesDir, entry.name), finalOf, (text) => text.replace(NOTE_PATH_LINE, (_line, lead, value) => `${lead}${movePath(value)}`));
31862
31958
  }
31863
31959
  }
31864
31960
  return plan;
@@ -31909,7 +32005,7 @@ function asRecord3(value) {
31909
32005
  }
31910
32006
 
31911
32007
  // src/flow/ac-reseal.ts
31912
- import path62 from "path";
32008
+ import path63 from "path";
31913
32009
  async function acFileUnchangedSinceHead(cwd, acRelativePath) {
31914
32010
  if (!Bun.which("git")) {
31915
32011
  return { clean: false, reason: "git is not on PATH, so the file's state cannot be established" };
@@ -31960,7 +32056,7 @@ async function acFileUnchangedSinceHead(cwd, acRelativePath) {
31960
32056
  return { clean: true };
31961
32057
  }
31962
32058
  function acRelativePathFor(flowsRootRelative, dir) {
31963
- return path62.posix.join(flowsRootRelative, dir, "acceptance-criteria.md");
32059
+ return path63.posix.join(flowsRootRelative, dir, "acceptance-criteria.md");
31964
32060
  }
31965
32061
 
31966
32062
  // src/flow/schema.ts
@@ -32306,7 +32402,7 @@ function flowStateSchema() {
32306
32402
  init_fs();
32307
32403
  init_config2();
32308
32404
  import { readFile as readFile30 } from "fs/promises";
32309
- import path65 from "path";
32405
+ import path66 from "path";
32310
32406
 
32311
32407
  // src/memory/inject.ts
32312
32408
  init_config2();
@@ -32463,7 +32559,7 @@ ${renderMemorySearchReportMarkdown(report, { includeHeader: false }).trimEnd()}`
32463
32559
  ".metaproject/data/gdgraph/artifacts/summary.md",
32464
32560
  ".metaproject/data/gdgraph/artifacts/module-map.json"
32465
32561
  ]) {
32466
- if (await pathExists(path65.join(cwd, rel))) {
32562
+ if (await pathExists(path66.join(cwd, rel))) {
32467
32563
  graphRefs.push(`- \`${rel}\``);
32468
32564
  }
32469
32565
  }
@@ -32475,7 +32571,7 @@ ${graphRefs.join(`
32475
32571
 
32476
32572
  Use \`keryx gdgraph affected <file>\` for blast radius.`);
32477
32573
  }
32478
- const healthLatest = path65.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
32574
+ const healthLatest = path66.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
32479
32575
  if (await pathExists(healthLatest)) {
32480
32576
  try {
32481
32577
  const report = JSON.parse(await readFile30(healthLatest, "utf8"));
@@ -32485,7 +32581,7 @@ Use \`keryx gdgraph affected <file>\` for blast radius.`);
32485
32581
  - refresh: \`keryx health run\``);
32486
32582
  } catch {}
32487
32583
  }
32488
- const manifestPath = path65.join(cwd, ".metaproject", "metaproject.json");
32584
+ const manifestPath = path66.join(cwd, ".metaproject", "metaproject.json");
32489
32585
  if (await pathExists(manifestPath)) {
32490
32586
  try {
32491
32587
  const manifest = JSON.parse(await readFile30(manifestPath, "utf8"));
@@ -32527,13 +32623,13 @@ var DEFAULT_TASKS = [
32527
32623
  init_fs();
32528
32624
  import { createHash as createHash10, randomBytes as randomBytes4 } from "crypto";
32529
32625
  import { readFile as readFile31 } from "fs/promises";
32530
- import path66 from "path";
32626
+ import path67 from "path";
32531
32627
  var CONFIRMATION_TOKEN_TTL_MS = 10 * 60000;
32532
32628
  var CONFIRMATION_CAVEAT = "The token proves an interactive confirmation step ran outside the agent's tool roster, within its TTL, " + "for this criteria checksum \u2014 not that a human ran it, and not who.";
32533
32629
  var CONFIRM_TOKEN_FILE = "confirm-token.json";
32534
32630
  var TOKEN_REF_LENGTH = 12;
32535
32631
  function confirmTokenPath(cwd, dir) {
32536
- return path66.join(flowsRoot(cwd), dir, CONFIRM_TOKEN_FILE);
32632
+ return path67.join(flowsRoot(cwd), dir, CONFIRM_TOKEN_FILE);
32537
32633
  }
32538
32634
  function completionTarget(input) {
32539
32635
  return input.merged ? "merged" : `pr:${input.prUrl ?? "none"}`;
@@ -32648,7 +32744,7 @@ function describeConfirmationFailure(reason, flowId) {
32648
32744
  }
32649
32745
  async function readRequireConfirmationDefault(cwd) {
32650
32746
  try {
32651
- const parsed = JSON.parse(await readFile31(path66.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
32747
+ const parsed = JSON.parse(await readFile31(path67.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
32652
32748
  if (typeof parsed !== "object" || parsed === null)
32653
32749
  return false;
32654
32750
  const completion = parsed["completion"];
@@ -32772,7 +32868,7 @@ async function githubPostReview(url, event, body) {
32772
32868
  }
32773
32869
  }
32774
32870
  // src/flow/uncommitted-state.ts
32775
- import path67 from "path";
32871
+ import path68 from "path";
32776
32872
  var UNCOMMITTED_LIST_CAP = 5;
32777
32873
  var READ_ONLY_GIT_FLAGS = ["--no-optional-locks"];
32778
32874
  var GIT_TIMEOUT_MS2 = 5000;
@@ -32849,7 +32945,7 @@ async function readGit(cwd, scope, git) {
32849
32945
  }
32850
32946
  async function uncommittedFlowStateNote(cwd, flowId, dir, git = spawnGit) {
32851
32947
  try {
32852
- const read = await readGit(cwd, path67.join(flowsRoot(cwd), dir), git);
32948
+ const read = await readGit(cwd, path68.join(flowsRoot(cwd), dir), git);
32853
32949
  return read === null ? null : noteFor(flowId, dir, read);
32854
32950
  } catch {
32855
32951
  return null;
@@ -33055,7 +33151,7 @@ function readAcKindRecords(value) {
33055
33151
  }
33056
33152
  // src/flow/description-intent.ts
33057
33153
  import { readFile as readFile32 } from "fs/promises";
33058
- import path68 from "path";
33154
+ import path69 from "path";
33059
33155
  var OUTCOME_HINT = 'State an outcome criterion: what you would look at afterwards to see this helped, as a bullet. Or write "- not measured \u2014 <reason>".';
33060
33156
  var PLACEHOLDERS = ["Describe the problem precisely", "What must be true when this flow is done"];
33061
33157
  var FLOW_STATEMENT_HEADINGS = [/^problem$/i, /^expected outcome$/i];
@@ -33168,7 +33264,7 @@ function initIntentNote(description) {
33168
33264
  }
33169
33265
  async function intentNoteForNewFlow(cwd, dir) {
33170
33266
  try {
33171
- return initIntentNote(await readFile32(path68.join(cwd, dir, "description.md"), "utf8"));
33267
+ return initIntentNote(await readFile32(path69.join(cwd, dir, "description.md"), "utf8"));
33172
33268
  } catch {
33173
33269
  return null;
33174
33270
  }
@@ -33176,7 +33272,7 @@ async function intentNoteForNewFlow(cwd, dir) {
33176
33272
  // src/flow/check-ac.ts
33177
33273
  import { createHash as createHash11 } from "crypto";
33178
33274
  import { chmod as chmod4, mkdir as mkdir11, readFile as readFile33 } from "fs/promises";
33179
- import path69 from "path";
33275
+ import path70 from "path";
33180
33276
  init_service2();
33181
33277
  init_fs();
33182
33278
  var AC_LINE2 = /^\s*[-*]\s*(AC\d+)\s*:\s?(.*)$/i;
@@ -33357,7 +33453,7 @@ function factsOnlyVerdict(item) {
33357
33453
  }
33358
33454
  async function readAcCheckEnabled(cwd) {
33359
33455
  try {
33360
- const parsed = JSON.parse(await readFile33(path69.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
33456
+ const parsed = JSON.parse(await readFile33(path70.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
33361
33457
  if (typeof parsed !== "object" || parsed === null)
33362
33458
  return false;
33363
33459
  const review = parsed["review"];
@@ -33378,7 +33474,7 @@ function acCheckCacheKey(criteriaChecksum, diffText) {
33378
33474
  return `${criteriaChecksum}:${hashDiff(diffText)}`;
33379
33475
  }
33380
33476
  function acCheckCachePath(cwd, flowDir) {
33381
- return path69.join(cwd, ".metaproject", "data", "ac-check", `${flowDir}.json`);
33477
+ return path70.join(cwd, ".metaproject", "data", "ac-check", `${flowDir}.json`);
33382
33478
  }
33383
33479
  async function readAcCheckCache(cachePath) {
33384
33480
  if (!await pathExists(cachePath))
@@ -33390,7 +33486,7 @@ async function readAcCheckCache(cachePath) {
33390
33486
  }
33391
33487
  }
33392
33488
  async function writeAcCheckCache(cachePath, record) {
33393
- await mkdir11(path69.dirname(cachePath), { recursive: true });
33489
+ await mkdir11(path70.dirname(cachePath), { recursive: true });
33394
33490
  await writeFileAtomic(cachePath, `${JSON.stringify(record, null, 2)}
33395
33491
  `, { mode: 384 });
33396
33492
  if (process.platform !== "win32") {
@@ -33448,10 +33544,10 @@ function renderAcCheckAdvisoryNotice(verdicts) {
33448
33544
  }
33449
33545
  // src/flow/allocation.ts
33450
33546
  import { appendFile as appendFile3, mkdir as mkdir12, readFile as readFile34 } from "fs/promises";
33451
- import path71 from "path";
33547
+ import path72 from "path";
33452
33548
 
33453
33549
  // src/lib/clone-scope.ts
33454
- import path70 from "path";
33550
+ import path71 from "path";
33455
33551
  async function gitCommonDir(cwd) {
33456
33552
  try {
33457
33553
  const proc = Bun.spawn(["git", "rev-parse", "--git-common-dir"], {
@@ -33463,7 +33559,7 @@ async function gitCommonDir(cwd) {
33463
33559
  if (await proc.exited !== 0 || output.length === 0) {
33464
33560
  return null;
33465
33561
  }
33466
- return path70.isAbsolute(output) ? output : path70.resolve(cwd, output);
33562
+ return path71.isAbsolute(output) ? output : path71.resolve(cwd, output);
33467
33563
  } catch {
33468
33564
  return null;
33469
33565
  }
@@ -33488,23 +33584,23 @@ function projectKey(toplevel, cwd) {
33488
33584
  if (!toplevel) {
33489
33585
  return "root";
33490
33586
  }
33491
- const relative = path71.relative(toplevel, cwd);
33587
+ const relative = path72.relative(toplevel, cwd);
33492
33588
  return relative === "" ? "root" : slugify(relative);
33493
33589
  }
33494
33590
  async function resolveAllocationScope(cwd) {
33495
33591
  const commonDir = await gitCommonDir(cwd);
33496
33592
  if (!commonDir) {
33497
33593
  return {
33498
- lockPath: path71.join(flowsRoot(cwd), ".flow-init.lock"),
33594
+ lockPath: path72.join(flowsRoot(cwd), ".flow-init.lock"),
33499
33595
  ledgerPath: null,
33500
33596
  project: "root"
33501
33597
  };
33502
33598
  }
33503
33599
  const key = projectKey(await gitToplevel(cwd), cwd);
33504
- const dir = path71.join(commonDir, "keryx", "flow-ids");
33600
+ const dir = path72.join(commonDir, "keryx", "flow-ids");
33505
33601
  return {
33506
- lockPath: path71.join(dir, `${key}.lock`),
33507
- ledgerPath: path71.join(dir, `${key}.jsonl`),
33602
+ lockPath: path72.join(dir, `${key}.lock`),
33603
+ ledgerPath: path72.join(dir, `${key}.jsonl`),
33508
33604
  project: key
33509
33605
  };
33510
33606
  }
@@ -33537,13 +33633,13 @@ async function recordAllocation(scope, record) {
33537
33633
  if (!scope.ledgerPath) {
33538
33634
  return;
33539
33635
  }
33540
- await mkdir12(path71.dirname(scope.ledgerPath), { recursive: true });
33636
+ await mkdir12(path72.dirname(scope.ledgerPath), { recursive: true });
33541
33637
  await appendFile3(scope.ledgerPath, `${JSON.stringify(record)}
33542
33638
  `, "utf8");
33543
33639
  }
33544
33640
 
33545
33641
  // src/flow/remote-flows.ts
33546
- import path72 from "path";
33642
+ import path73 from "path";
33547
33643
  var MAX_REFS = 500;
33548
33644
  var CONCURRENCY = 8;
33549
33645
  async function runGit2(cwd, args) {
@@ -33624,7 +33720,7 @@ async function flowDirsOnRef(cwd, ref, flowsPath) {
33624
33720
  if (result === undefined || result.code !== 0) {
33625
33721
  return [];
33626
33722
  }
33627
- return nulSplit(result.stdout).map((entry) => path72.posix.basename(entry)).filter((name) => /^\d{3}-/.test(name));
33723
+ return nulSplit(result.stdout).map((entry) => path73.posix.basename(entry)).filter((name) => /^\d{3}-/.test(name));
33628
33724
  }
33629
33725
  async function knownRemoteFlowDirs(cwd) {
33630
33726
  try {
@@ -33804,12 +33900,12 @@ function renderJournal(createdAt) {
33804
33900
 
33805
33901
  // src/flow/task-project-context.ts
33806
33902
  import { readFile as readFile38 } from "fs/promises";
33807
- import path76 from "path";
33903
+ import path77 from "path";
33808
33904
 
33809
33905
  // src/gdskills/project-context-config.ts
33810
33906
  init_fs();
33811
33907
  import { readFile as readFile35 } from "fs/promises";
33812
- import path73 from "path";
33908
+ import path74 from "path";
33813
33909
  var PROJECT_CONTEXT_CONFIG_PATH = ".metaproject/tasks.config.json";
33814
33910
  var DEFAULT_MAX_BYTES = 131072;
33815
33911
  var MAX_BYTES_FLOOR = 4096;
@@ -33819,7 +33915,7 @@ function isValidMaxBytes(value) {
33819
33915
  }
33820
33916
  async function readRoot(projectRoot) {
33821
33917
  try {
33822
- const parsed = JSON.parse(await readFile35(path73.join(projectRoot, PROJECT_CONTEXT_CONFIG_PATH), "utf8"));
33918
+ const parsed = JSON.parse(await readFile35(path74.join(projectRoot, PROJECT_CONTEXT_CONFIG_PATH), "utf8"));
33823
33919
  return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
33824
33920
  } catch {
33825
33921
  return;
@@ -33863,7 +33959,7 @@ async function readProjectContextConfig(projectRoot) {
33863
33959
 
33864
33960
  // src/gdskills/resolved-context-check.ts
33865
33961
  import { readFile as readFile37 } from "fs/promises";
33866
- import path75 from "path";
33962
+ import path76 from "path";
33867
33963
 
33868
33964
  // src/gdskills/project-rules.ts
33869
33965
  import { createHash as createHash12 } from "crypto";
@@ -33876,7 +33972,7 @@ function sha256Hex(content) {
33876
33972
 
33877
33973
  // src/gdskills/reference-proof.ts
33878
33974
  import { readFile as readFile36 } from "fs/promises";
33879
- import path74 from "path";
33975
+ import path75 from "path";
33880
33976
 
33881
33977
  // src/gdskills/references-section.ts
33882
33978
  var FENCE = /^ {0,3}(`{3,}|~{3,})/;
@@ -33982,7 +34078,7 @@ function pickProofItem(items, pinned) {
33982
34078
  return items.find((item) => item.sha256 === pinned && item.how !== "n/a") ?? items.find((item) => item.how !== "n/a") ?? items[0];
33983
34079
  }
33984
34080
  async function currentSection(projectRoot, entry) {
33985
- const file = path74.isAbsolute(entry.path) ? entry.path : path74.join(projectRoot, entry.path);
34081
+ const file = path75.isAbsolute(entry.path) ? entry.path : path75.join(projectRoot, entry.path);
33986
34082
  let text;
33987
34083
  try {
33988
34084
  text = await readFile36(file, "utf8");
@@ -34074,7 +34170,7 @@ function appliedOf(result) {
34074
34170
  }
34075
34171
  async function currentSha(projectRoot, entryPath) {
34076
34172
  try {
34077
- return sha256Hex(await readFile37(path75.isAbsolute(entryPath) ? entryPath : path75.join(projectRoot, entryPath), "utf8"));
34173
+ return sha256Hex(await readFile37(path76.isAbsolute(entryPath) ? entryPath : path76.join(projectRoot, entryPath), "utf8"));
34078
34174
  } catch {
34079
34175
  return;
34080
34176
  }
@@ -34153,8 +34249,8 @@ async function checkTaskProjectContext(input) {
34153
34249
  }
34154
34250
  const report = await checkResolvedContext({
34155
34251
  projectRoot: input.projectRoot,
34156
- resolved: await readResolvedFile(path76.resolve(input.projectRoot, input.resolvedFile)),
34157
- result: await readResultFile(path76.resolve(input.projectRoot, input.resultFile))
34252
+ resolved: await readResolvedFile(path77.resolve(input.projectRoot, input.resolvedFile)),
34253
+ result: await readResultFile(path77.resolve(input.projectRoot, input.resultFile))
34158
34254
  });
34159
34255
  const lines = formatResolvedReport(report);
34160
34256
  if (lines.length === 0)
@@ -34468,7 +34564,7 @@ function createFlowService(deps) {
34468
34564
  const date = now().slice(0, 10);
34469
34565
  const slug = slugify(input.slug ?? title);
34470
34566
  const dir = `${id}-${date}-${slug}`;
34471
- const absolute = path77.join(flowsRoot(input.cwd), dir);
34567
+ const absolute = path78.join(flowsRoot(input.cwd), dir);
34472
34568
  if (await pathExists(absolute)) {
34473
34569
  throw new Error(`Flow directory already exists: ${dir}`);
34474
34570
  }
@@ -34504,17 +34600,17 @@ function createFlowService(deps) {
34504
34600
  history: [{ at: createdAt, event: "created" }]
34505
34601
  };
34506
34602
  const sourceLabel = input.issue ?? "user description";
34507
- await writeFileAtomic(path77.join(absolute, "description.md"), renderDescription(title, originDraft === undefined ? sourceLabel : `${sourceLabel} (origin: ${originDraft.kind})`, originDraft));
34508
- await writeFileAtomic(path77.join(absolute, "context.md"), context.markdown);
34509
- await writeFileAtomic(path77.join(absolute, "plan.md"), renderPlan());
34510
- await writeFileAtomic(path77.join(absolute, "tasks.md"), renderTasksDoc());
34511
- await writeFileAtomic(path77.join(absolute, "acceptance-criteria.md"), renderAcceptanceCriteria());
34512
- await writeFileAtomic(path77.join(absolute, "journal.md"), renderJournal(createdAt));
34603
+ await writeFileAtomic(path78.join(absolute, "description.md"), renderDescription(title, originDraft === undefined ? sourceLabel : `${sourceLabel} (origin: ${originDraft.kind})`, originDraft));
34604
+ await writeFileAtomic(path78.join(absolute, "context.md"), context.markdown);
34605
+ await writeFileAtomic(path78.join(absolute, "plan.md"), renderPlan());
34606
+ await writeFileAtomic(path78.join(absolute, "tasks.md"), renderTasksDoc());
34607
+ await writeFileAtomic(path78.join(absolute, "acceptance-criteria.md"), renderAcceptanceCriteria());
34608
+ await writeFileAtomic(path78.join(absolute, "journal.md"), renderJournal(createdAt));
34513
34609
  await writeFlow(input.cwd, dir, flow);
34514
34610
  await recordAllocation(scope, { id, dir, at: createdAt, project: scope.project });
34515
34611
  return {
34516
34612
  flow,
34517
- dir: path77.relative(input.cwd, absolute),
34613
+ dir: path78.relative(input.cwd, absolute),
34518
34614
  contextNotes: context.notes,
34519
34615
  ...originNote === undefined ? {} : { originNote }
34520
34616
  };
@@ -35155,7 +35251,7 @@ function createFlowService(deps) {
35155
35251
  issues.push({ flow: dir, kind: "schema", message: `unknown schemaVersion ${flow.schemaVersion}` });
35156
35252
  }
35157
35253
  try {
35158
- const raw = JSON.parse(await Bun.file(path77.join(flowsRoot(cwd), dir, "flow.json")).text());
35254
+ const raw = JSON.parse(await Bun.file(path78.join(flowsRoot(cwd), dir, "flow.json")).text());
35159
35255
  const validation = validateAgainstSchemaObject(flowStateSchema(), raw);
35160
35256
  if (!validation.valid) {
35161
35257
  issues.push({
@@ -35166,7 +35262,7 @@ function createFlowService(deps) {
35166
35262
  }
35167
35263
  } catch {}
35168
35264
  for (const file of ["description.md", "context.md", "plan.md", "tasks.md", "acceptance-criteria.md", "journal.md"]) {
35169
- if (!await pathExists(path77.join(flowsRoot(cwd), dir, file))) {
35265
+ if (!await pathExists(path78.join(flowsRoot(cwd), dir, file))) {
35170
35266
  issues.push({ flow: dir, kind: "structure", message: `missing ${file}` });
35171
35267
  }
35172
35268
  }
@@ -35205,7 +35301,7 @@ function createFlowService(deps) {
35205
35301
  };
35206
35302
  }
35207
35303
  async function appendIdMap(cwd, entry) {
35208
- const file = path77.join(flowsRoot(cwd), "id-map.json");
35304
+ const file = path78.join(flowsRoot(cwd), "id-map.json");
35209
35305
  let entries = [];
35210
35306
  if (await pathExists(file)) {
35211
35307
  const raw = await readFile39(file, "utf8");
@@ -35216,7 +35312,7 @@ async function appendIdMap(cwd, entry) {
35216
35312
  }
35217
35313
  entries = parsed;
35218
35314
  } catch (error) {
35219
- throw new Error(`Cannot read ${path77.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`);
35315
+ throw new Error(`Cannot read ${path78.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`);
35220
35316
  }
35221
35317
  }
35222
35318
  entries.push(entry);
@@ -35504,7 +35600,7 @@ async function acCriterionKnown(input) {
35504
35600
  init_data_dir();
35505
35601
  import { mkdir as mkdir23, readdir as readdir18, readFile as readFile51, writeFile as writeFile17 } from "fs/promises";
35506
35602
  import { existsSync as existsSync11 } from "fs";
35507
- import path100 from "path";
35603
+ import path101 from "path";
35508
35604
 
35509
35605
  // src/gdgraph/types.ts
35510
35606
  var UNKNOWN_IMPORT_KIND = "unknown-static";
@@ -35571,7 +35667,7 @@ async function buildGraph(projectRoot, options = {}) {
35571
35667
  const assetNodes = new Map;
35572
35668
  const fileRecords = [];
35573
35669
  for (const file of files) {
35574
- const absolutePath = path100.join(projectRoot, file);
35670
+ const absolutePath = path101.join(projectRoot, file);
35575
35671
  const content = await readFile51(absolutePath, "utf8");
35576
35672
  fileRecords.push({ path: file, content });
35577
35673
  const language = getLanguage(file);
@@ -35624,24 +35720,24 @@ async function collectSourceFiles(projectRoot) {
35624
35720
  const result = [];
35625
35721
  const skippedDirectories = [];
35626
35722
  async function walk(relativeDir) {
35627
- const absoluteDir = path100.join(projectRoot, relativeDir);
35723
+ const absoluteDir = path101.join(projectRoot, relativeDir);
35628
35724
  const entries = await readdir18(absoluteDir, { withFileTypes: true });
35629
35725
  for (const entry of entries) {
35630
35726
  if (entry.isDirectory()) {
35631
35727
  if (IGNORE_DIRS.has(entry.name)) {
35632
- skippedDirectories.push(normalizePath3(path100.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
35728
+ skippedDirectories.push(normalizePath3(path101.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
35633
35729
  continue;
35634
35730
  }
35635
- await walk(normalizePath3(path100.posix.join(relativeDir, entry.name)));
35731
+ await walk(normalizePath3(path101.posix.join(relativeDir, entry.name)));
35636
35732
  continue;
35637
35733
  }
35638
35734
  if (!entry.isFile()) {
35639
35735
  continue;
35640
35736
  }
35641
- if (!SOURCE_EXTENSIONS.includes(path100.extname(entry.name))) {
35737
+ if (!SOURCE_EXTENSIONS.includes(path101.extname(entry.name))) {
35642
35738
  continue;
35643
35739
  }
35644
- result.push(normalizePath3(path100.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
35740
+ result.push(normalizePath3(path101.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
35645
35741
  }
35646
35742
  }
35647
35743
  await walk(".");
@@ -35723,8 +35819,8 @@ function resolveImport(projectRoot, fromFile, specifier, fileSet, resolver) {
35723
35819
  }
35724
35820
  function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
35725
35821
  for (const candidate of importCandidateBases(projectRoot, fromFile, specifier, resolver)) {
35726
- const extension = path100.posix.extname(candidate);
35727
- if (ASSET_EXTENSIONS.includes(extension) && existsSync11(path100.join(projectRoot, candidate))) {
35822
+ const extension = path101.posix.extname(candidate);
35823
+ if (ASSET_EXTENSIONS.includes(extension) && existsSync11(path101.join(projectRoot, candidate))) {
35728
35824
  return candidate;
35729
35825
  }
35730
35826
  }
@@ -35733,17 +35829,17 @@ function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
35733
35829
  function importCandidateBases(projectRoot, fromFile, specifier, resolver) {
35734
35830
  const normalizedSpecifier = stripImportSuffix(specifier);
35735
35831
  if (normalizedSpecifier.startsWith(".") && getLanguage(fromFile) !== "python") {
35736
- const fromDir = path100.posix.dirname(fromFile);
35737
- return [normalizePath3(path100.posix.normalize(path100.posix.join(fromDir, normalizedSpecifier)))];
35832
+ const fromDir = path101.posix.dirname(fromFile);
35833
+ return [normalizePath3(path101.posix.normalize(path101.posix.join(fromDir, normalizedSpecifier)))];
35738
35834
  }
35739
- return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath3(path100.relative(projectRoot, path100.join(projectRoot, candidate))));
35835
+ return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath3(path101.relative(projectRoot, path101.join(projectRoot, candidate))));
35740
35836
  }
35741
35837
  function resolveSourceCandidate(base, fileSet) {
35742
35838
  const candidates = [
35743
35839
  base,
35744
35840
  ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => `${base}${extension}`),
35745
- ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path100.posix.join(base, `index${extension}`)),
35746
- path100.posix.join(base, "__init__.py")
35841
+ ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path101.posix.join(base, `index${extension}`)),
35842
+ path101.posix.join(base, "__init__.py")
35747
35843
  ];
35748
35844
  return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
35749
35845
  }
@@ -35773,7 +35869,7 @@ async function loadJavaResolver(projectRoot) {
35773
35869
  return createJavaResolver(roots);
35774
35870
  }
35775
35871
  async function discoverJavaSourceRoots(projectRoot) {
35776
- const pomPath = path100.join(projectRoot, "pom.xml");
35872
+ const pomPath = path101.join(projectRoot, "pom.xml");
35777
35873
  if (existsSync11(pomPath)) {
35778
35874
  try {
35779
35875
  const roots = parseMavenSourceRoots(await readFile51(pomPath, "utf8"));
@@ -35783,7 +35879,7 @@ async function discoverJavaSourceRoots(projectRoot) {
35783
35879
  } catch {}
35784
35880
  }
35785
35881
  for (const gradleName of ["build.gradle", "build.gradle.kts"]) {
35786
- const gradlePath = path100.join(projectRoot, gradleName);
35882
+ const gradlePath = path101.join(projectRoot, gradleName);
35787
35883
  if (existsSync11(gradlePath)) {
35788
35884
  try {
35789
35885
  const roots = parseGradleSourceRoots(await readFile51(gradlePath, "utf8"));
@@ -35805,12 +35901,12 @@ function createJavaResolver(sourceRoots) {
35805
35901
  return [];
35806
35902
  }
35807
35903
  const relative = specifier.split(".").join("/");
35808
- return sourceRoots.map((root) => normalizePath3(path100.posix.join(root, relative)));
35904
+ return sourceRoots.map((root) => normalizePath3(path101.posix.join(root, relative)));
35809
35905
  }
35810
35906
  };
35811
35907
  }
35812
35908
  function loadPythonResolver(projectRoot) {
35813
- const hasSrc = existsSync11(path100.join(projectRoot, "src"));
35909
+ const hasSrc = existsSync11(path101.join(projectRoot, "src"));
35814
35910
  return createPythonResolver(hasSrc);
35815
35911
  }
35816
35912
  function createPythonResolver(hasSrc) {
@@ -35823,16 +35919,16 @@ function createPythonResolver(hasSrc) {
35823
35919
  if (specifier.startsWith(".")) {
35824
35920
  const dots = /^\.+/.exec(specifier)?.[0].length ?? 0;
35825
35921
  const rest = specifier.slice(dots);
35826
- let baseDir = path100.posix.dirname(fromFile);
35922
+ let baseDir = path101.posix.dirname(fromFile);
35827
35923
  for (let level = 1;level < dots; level += 1) {
35828
- baseDir = path100.posix.dirname(baseDir);
35924
+ baseDir = path101.posix.dirname(baseDir);
35829
35925
  }
35830
35926
  const suffix = rest ? rest.split(".").join("/") : "";
35831
- const base = suffix ? path100.posix.join(baseDir, suffix) : baseDir;
35927
+ const base = suffix ? path101.posix.join(baseDir, suffix) : baseDir;
35832
35928
  return [normalizePath3(base)];
35833
35929
  }
35834
35930
  const relative = specifier.split(".").join("/");
35835
- return roots.map((root) => normalizePath3(root ? path100.posix.join(root, relative) : relative));
35931
+ return roots.map((root) => normalizePath3(root ? path101.posix.join(root, relative) : relative));
35836
35932
  }
35837
35933
  };
35838
35934
  }
@@ -35841,8 +35937,8 @@ function parseMavenSourceRoots(pomXml) {
35841
35937
  for (const match of pomXml.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
35842
35938
  const moduleDir = match[1]?.trim();
35843
35939
  if (moduleDir && !moduleDir.includes("${")) {
35844
- roots.add(normalizePath3(path100.posix.join(moduleDir, "src/main/java")));
35845
- roots.add(normalizePath3(path100.posix.join(moduleDir, "src/test/java")));
35940
+ roots.add(normalizePath3(path101.posix.join(moduleDir, "src/main/java")));
35941
+ roots.add(normalizePath3(path101.posix.join(moduleDir, "src/test/java")));
35846
35942
  }
35847
35943
  }
35848
35944
  for (const tag of ["sourceDirectory", "testSourceDirectory"]) {
@@ -35875,7 +35971,7 @@ function parseGradleSourceRoots(buildGradle) {
35875
35971
  var TSCONFIG_EXTENDS_MAX_DEPTH = 10;
35876
35972
  async function loadTsconfigResolver(projectRoot) {
35877
35973
  const empty = createTsconfigResolver(null, []);
35878
- const tsconfigPath = path100.join(projectRoot, "tsconfig.json");
35974
+ const tsconfigPath = path101.join(projectRoot, "tsconfig.json");
35879
35975
  if (!existsSync11(tsconfigPath)) {
35880
35976
  return empty;
35881
35977
  }
@@ -35888,7 +35984,7 @@ async function loadTsconfigResolver(projectRoot) {
35888
35984
  return createTsconfigResolver(resolved.baseUrl, paths);
35889
35985
  }
35890
35986
  function toProjectRelativeDir(projectRoot, absoluteDir) {
35891
- const relative = normalizePath3(path100.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
35987
+ const relative = normalizePath3(path101.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
35892
35988
  return relative === "." ? "" : relative;
35893
35989
  }
35894
35990
  async function readTsconfigJson(configPath) {
@@ -35903,11 +35999,11 @@ function resolveTsconfigExtendsPath(configDir, extendsSpecifier) {
35903
35999
  if (!extendsSpecifier.startsWith(".") && !extendsSpecifier.startsWith("/")) {
35904
36000
  return null;
35905
36001
  }
35906
- const resolved = path100.resolve(configDir, extendsSpecifier);
36002
+ const resolved = path101.resolve(configDir, extendsSpecifier);
35907
36003
  return resolved.endsWith(".json") ? resolved : `${resolved}.json`;
35908
36004
  }
35909
36005
  async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
35910
- const resolvedPath = path100.resolve(configPath);
36006
+ const resolvedPath = path101.resolve(configPath);
35911
36007
  if (depth > TSCONFIG_EXTENDS_MAX_DEPTH || visited.has(resolvedPath)) {
35912
36008
  return null;
35913
36009
  }
@@ -35918,15 +36014,15 @@ async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
35918
36014
  }
35919
36015
  let inherited = null;
35920
36016
  if (typeof parsed.extends === "string") {
35921
- const basePath = resolveTsconfigExtendsPath(path100.dirname(resolvedPath), parsed.extends);
36017
+ const basePath = resolveTsconfigExtendsPath(path101.dirname(resolvedPath), parsed.extends);
35922
36018
  if (basePath) {
35923
36019
  inherited = await resolveTsconfigOptions(basePath, visited, depth + 1, projectRoot);
35924
36020
  }
35925
36021
  }
35926
- const configDir = path100.dirname(resolvedPath);
36022
+ const configDir = path101.dirname(resolvedPath);
35927
36023
  const declaringDir = toProjectRelativeDir(projectRoot, configDir);
35928
36024
  const options = parsed.compilerOptions ?? {};
35929
- const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path100.resolve(configDir, options.baseUrl)) : null;
36025
+ const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path101.resolve(configDir, options.baseUrl)) : null;
35930
36026
  const baseUrl = ownBaseUrl ?? inherited?.baseUrl ?? null;
35931
36027
  const ownPaths = isRecord5(options.paths) ? Object.entries(options.paths).filter((entry) => Array.isArray(entry[1])).map(([pattern, targets]) => ({
35932
36028
  pattern,
@@ -35955,7 +36051,7 @@ function createTsconfigResolver(baseUrl, mappings) {
35955
36051
  }
35956
36052
  }
35957
36053
  if (baseUrl !== null) {
35958
- candidates.push(normalizePath3(path100.posix.join(baseUrl, normalizedSpecifier)));
36054
+ candidates.push(normalizePath3(path101.posix.join(baseUrl, normalizedSpecifier)));
35959
36055
  }
35960
36056
  return [...new Set(candidates.map((candidate) => candidate.replace(/^\.\//, "")))];
35961
36057
  }
@@ -35975,7 +36071,7 @@ function matchPathPattern(pattern, specifier) {
35975
36071
  }
35976
36072
  function applyPathTarget(base, target, wildcard) {
35977
36073
  const replaced = target.includes("*") ? target.replace("*", wildcard) : target;
35978
- return normalizePath3(path100.posix.normalize(path100.posix.join(base, replaced)));
36074
+ return normalizePath3(path101.posix.normalize(path101.posix.join(base, replaced)));
35979
36075
  }
35980
36076
  function stripJsonComments(source) {
35981
36077
  let out = "";
@@ -36032,13 +36128,13 @@ async function writeGraph(projectRoot, graph, dataDir) {
36032
36128
  const artifactsDir = gdgraphArtifactsDir(projectRoot, dataDir);
36033
36129
  await mkdir23(storageDir, { recursive: true });
36034
36130
  await mkdir23(artifactsDir, { recursive: true });
36035
- await writeFile17(path100.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
36131
+ await writeFile17(path101.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
36036
36132
  `) + `
36037
36133
  `, "utf8");
36038
- await writeFile17(path100.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
36134
+ await writeFile17(path101.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
36039
36135
  `) + `
36040
36136
  `, "utf8");
36041
- await writeFile17(path100.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
36137
+ await writeFile17(path101.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
36042
36138
  `, "utf8");
36043
36139
  }
36044
36140
  async function writeSummary(projectRoot, graph, collection, dataDir) {
@@ -36057,7 +36153,7 @@ async function writeSummary(projectRoot, graph, collection, dataDir) {
36057
36153
  `);
36058
36154
  const skippedList = collection.skippedDirectories.length > 0 ? collection.skippedDirectories.slice(0, 30).map((dir) => `- \`${dir}\``).join(`
36059
36155
  `) : "- none";
36060
- const summaryPath = path100.join(artifactsDir, "summary.md");
36156
+ const summaryPath = path101.join(artifactsDir, "summary.md");
36061
36157
  const content = `# gdgraph Summary
36062
36158
 
36063
36159
  ## Stats
@@ -36138,7 +36234,7 @@ function groupBy(items, getKey) {
36138
36234
  }
36139
36235
  function unresolvedType(specifier) {
36140
36236
  const stripped = stripImportSuffix(specifier);
36141
- const extension = path100.posix.extname(stripped);
36237
+ const extension = path101.posix.extname(stripped);
36142
36238
  if (extension) {
36143
36239
  return extension;
36144
36240
  }
@@ -36148,7 +36244,7 @@ function unresolvedType(specifier) {
36148
36244
  return "package";
36149
36245
  }
36150
36246
  function normalizePath3(value) {
36151
- return value.split(path100.sep).join("/");
36247
+ return value.split(path101.sep).join("/");
36152
36248
  }
36153
36249
 
36154
36250
  // src/gdgraph/service.ts
@@ -36157,17 +36253,17 @@ init_config3();
36157
36253
 
36158
36254
  // src/gdgraph/query.ts
36159
36255
  import { readFile as readFile52 } from "fs/promises";
36160
- import path101 from "path";
36256
+ import path102 from "path";
36161
36257
  init_data_dir();
36162
36258
  init_target();
36163
36259
  async function loadGraph(projectRoot, dataDir) {
36164
36260
  const storageDir = gdgraphStorageDir(projectRoot, dataDir);
36165
- const nodes = await readJsonl(path101.join(storageDir, "nodes.jsonl"));
36166
- const edges = await readJsonl(path101.join(storageDir, "edges.jsonl"));
36167
- const symbols = await readJsonl(path101.join(storageDir, "symbols.jsonl"));
36168
- const calls = await readJsonl(path101.join(storageDir, "calls.jsonl"));
36169
- const wikiPages = await readJsonl(path101.join(storageDir, "wiki-pages.jsonl"));
36170
- const describes = await readJsonl(path101.join(storageDir, "describes.jsonl"));
36261
+ const nodes = await readJsonl(path102.join(storageDir, "nodes.jsonl"));
36262
+ const edges = await readJsonl(path102.join(storageDir, "edges.jsonl"));
36263
+ const symbols = await readJsonl(path102.join(storageDir, "symbols.jsonl"));
36264
+ const calls = await readJsonl(path102.join(storageDir, "calls.jsonl"));
36265
+ const wikiPages = await readJsonl(path102.join(storageDir, "wiki-pages.jsonl"));
36266
+ const describes = await readJsonl(path102.join(storageDir, "describes.jsonl"));
36171
36267
  const graph = { nodes, edges };
36172
36268
  if (symbols.length > 0) {
36173
36269
  graph.symbols = symbols;
@@ -36227,7 +36323,7 @@ async function bunfigPreloadRoots(projectRoot) {
36227
36323
  const roots = new Set;
36228
36324
  let text;
36229
36325
  try {
36230
- text = await readFile52(path101.join(projectRoot, "bunfig.toml"), "utf8");
36326
+ text = await readFile52(path102.join(projectRoot, "bunfig.toml"), "utf8");
36231
36327
  } catch {
36232
36328
  return roots;
36233
36329
  }
@@ -36241,8 +36337,8 @@ async function bunfigPreloadRoots(projectRoot) {
36241
36337
  if (raw.length === 0) {
36242
36338
  continue;
36243
36339
  }
36244
- const absolute = path101.resolve(projectRoot, raw);
36245
- const relative = path101.relative(projectRoot, absolute).split(path101.sep).join("/");
36340
+ const absolute = path102.resolve(projectRoot, raw);
36341
+ const relative = path102.relative(projectRoot, absolute).split(path102.sep).join("/");
36246
36342
  roots.add(relative);
36247
36343
  }
36248
36344
  }
@@ -36397,12 +36493,12 @@ init_section_tombstone();
36397
36493
  // src/forgetting/journal.ts
36398
36494
  init_fs();
36399
36495
  import { appendFile as appendFile5, mkdir as mkdir25, readFile as readFile53, stat as stat15 } from "fs/promises";
36400
- import path103 from "path";
36496
+ import path104 from "path";
36401
36497
  function forgettingDataDir(cwd) {
36402
- return path103.join(cwd, ".metaproject", "data", "forgetting");
36498
+ return path104.join(cwd, ".metaproject", "data", "forgetting");
36403
36499
  }
36404
36500
  function deletionJournalPath(cwd) {
36405
- return path103.join(forgettingDataDir(cwd), "journal.jsonl");
36501
+ return path104.join(forgettingDataDir(cwd), "journal.jsonl");
36406
36502
  }
36407
36503
  async function readDeletionJournal(cwd) {
36408
36504
  const file = deletionJournalPath(cwd);
@@ -36817,12 +36913,12 @@ function createGdgraphService() {
36817
36913
  // src/health/service.ts
36818
36914
  init_fs();
36819
36915
  init_json();
36820
- import path123 from "path";
36916
+ import path124 from "path";
36821
36917
 
36822
36918
  // src/health/config.ts
36823
36919
  init_fs();
36824
36920
  init_json();
36825
- import path104 from "path";
36921
+ import path105 from "path";
36826
36922
  var DEFAULT_HEALTH_CONFIG = {
36827
36923
  schemaVersion: 2,
36828
36924
  ignore: {
@@ -36879,7 +36975,7 @@ var DEFAULT_HEALTH_CONFIG = {
36879
36975
  }
36880
36976
  };
36881
36977
  function configPath2(cwd) {
36882
- return path104.join(cwd, ".metaproject", "health.config.json");
36978
+ return path105.join(cwd, ".metaproject", "health.config.json");
36883
36979
  }
36884
36980
  var STRICTEST_GATE = {
36885
36981
  failOnPriorities: ["P0", "P1", "P2", "P3"],
@@ -36930,7 +37026,7 @@ async function loadHealthConfig(cwd) {
36930
37026
  // src/health/run.ts
36931
37027
  init_fs();
36932
37028
  import { mkdir as mkdir29, writeFile as writeFile22 } from "fs/promises";
36933
- import path122 from "path";
37029
+ import path123 from "path";
36934
37030
 
36935
37031
  // src/metrics/provenance.ts
36936
37032
  async function collectGitProvenance(cwd) {
@@ -37043,12 +37139,12 @@ function computeGate2(input) {
37043
37139
  }
37044
37140
 
37045
37141
  // src/health/scopes.ts
37046
- import path107 from "path";
37142
+ import path108 from "path";
37047
37143
 
37048
37144
  // src/health/util.ts
37049
37145
  init_fs();
37050
37146
  import { mkdir as mkdir26, readFile as readFile54, readdir as readdir19, writeFile as writeFile19 } from "fs/promises";
37051
- import path105 from "path";
37147
+ import path106 from "path";
37052
37148
  var IGNORED_DIRS = new Set([
37053
37149
  "node_modules",
37054
37150
  ".git",
@@ -37092,14 +37188,14 @@ async function toolVersion(command, cwd) {
37092
37188
  }
37093
37189
  }
37094
37190
  function dataRoot3(cwd) {
37095
- return path105.join(cwd, ".metaproject", "data", "health");
37191
+ return path106.join(cwd, ".metaproject", "data", "health");
37096
37192
  }
37097
37193
  async function writeRaw(cwd, source, content, stamp) {
37098
- const dir = path105.join(dataRoot3(cwd), "raw", source);
37194
+ const dir = path106.join(dataRoot3(cwd), "raw", source);
37099
37195
  await mkdir26(dir, { recursive: true });
37100
- const file = path105.join(dir, `${stamp}.log`);
37196
+ const file = path106.join(dir, `${stamp}.log`);
37101
37197
  await writeFile19(file, content, "utf8");
37102
- return path105.relative(cwd, file);
37198
+ return path106.relative(cwd, file);
37103
37199
  }
37104
37200
  async function listSourceFiles(cwd, ignorePaths = []) {
37105
37201
  const { files } = await listSourceFilesWithReasons(cwd, ignorePaths);
@@ -37119,7 +37215,7 @@ async function walk2(root, dir, out, incompleteReasons) {
37119
37215
  try {
37120
37216
  entries = await readdir19(dir, { withFileTypes: true });
37121
37217
  } catch (error) {
37122
- incompleteReasons.push(`${path105.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
37218
+ incompleteReasons.push(`${path106.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
37123
37219
  return;
37124
37220
  }
37125
37221
  for (const entry of entries) {
@@ -37127,14 +37223,14 @@ async function walk2(root, dir, out, incompleteReasons) {
37127
37223
  if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name)) {}
37128
37224
  continue;
37129
37225
  }
37130
- const abs = path105.join(dir, entry.name);
37226
+ const abs = path106.join(dir, entry.name);
37131
37227
  if (entry.isDirectory()) {
37132
37228
  if (IGNORED_DIRS.has(entry.name)) {
37133
37229
  continue;
37134
37230
  }
37135
37231
  await walk2(root, abs, out, incompleteReasons);
37136
- } else if (entry.isFile() && SOURCE_EXT.has(path105.extname(entry.name))) {
37137
- out.push(path105.relative(root, abs));
37232
+ } else if (entry.isFile() && SOURCE_EXT.has(path106.extname(entry.name))) {
37233
+ out.push(path106.relative(root, abs));
37138
37234
  }
37139
37235
  }
37140
37236
  }
@@ -37149,7 +37245,7 @@ function moduleOfFile(file) {
37149
37245
  return null;
37150
37246
  }
37151
37247
  function isSourceFile(file) {
37152
- return SOURCE_EXT.has(path105.extname(file));
37248
+ return SOURCE_EXT.has(path106.extname(file));
37153
37249
  }
37154
37250
  function matchesAnyPattern(file, patterns) {
37155
37251
  const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
@@ -37251,7 +37347,7 @@ function rankHotspots(files, churn, sourceAnalysis) {
37251
37347
  // src/health/source-analysis.ts
37252
37348
  init_fs();
37253
37349
  import { readFile as readFile55 } from "fs/promises";
37254
- import path106 from "path";
37350
+ import path107 from "path";
37255
37351
 
37256
37352
  // src/health/metrics/complexity.ts
37257
37353
  var CONTROL_KEYWORDS = new Set([
@@ -37485,7 +37581,7 @@ async function analyzeSourceFiles(cwd, sourceFiles) {
37485
37581
  return new Map(entries.filter((entry) => entry !== null));
37486
37582
  }
37487
37583
  async function analyzeSourceFile(cwd, file) {
37488
- const abs = path106.join(cwd, file);
37584
+ const abs = path107.join(cwd, file);
37489
37585
  if (!await pathExists(abs)) {
37490
37586
  return null;
37491
37587
  }
@@ -37562,14 +37658,14 @@ async function computeMetrics(input) {
37562
37658
  }
37563
37659
  const components = new Map;
37564
37660
  for (const file of sourceFiles) {
37565
- const dir = path107.posix.dirname(file);
37661
+ const dir = path108.posix.dirname(file);
37566
37662
  if (dir === "." || dir === moduleOfFile(file)) {
37567
37663
  continue;
37568
37664
  }
37569
37665
  components.set(dir, [...components.get(dir) ?? [], file]);
37570
37666
  }
37571
37667
  for (const [name, files] of [...components.entries()].sort()) {
37572
- const compFindings = findings.filter((f) => f.file && path107.posix.dirname(f.file) === name);
37668
+ const compFindings = findings.filter((f) => f.file && path108.posix.dirname(f.file) === name);
37573
37669
  scopes.push(build("component", `component:${name}`, name, files, compFindings, averageCoverage(files, coverage)));
37574
37670
  }
37575
37671
  const findingFiles = findings.map((f) => f.file).filter((f) => Boolean(f));
@@ -37614,7 +37710,7 @@ function tally2(values) {
37614
37710
  // src/health/baseline.ts
37615
37711
  init_fs();
37616
37712
  import { mkdir as mkdir27, readFile as readFile56, writeFile as writeFile20 } from "fs/promises";
37617
- import path108 from "path";
37713
+ import path109 from "path";
37618
37714
  var LEGACY_BASELINE_SOURCES = Object.freeze([
37619
37715
  "complexity",
37620
37716
  "coverage",
@@ -37639,7 +37735,7 @@ function measuredSources(sources) {
37639
37735
  return sources.filter((s) => s !== null && typeof s === "object").filter((s) => !didNotProduceResult(s)).map((s) => s.source).sort();
37640
37736
  }
37641
37737
  function baselinePath(cwd) {
37642
- return path108.join(cwd, ".metaproject", "health", "baselines", "scores.json");
37738
+ return path109.join(cwd, ".metaproject", "health", "baselines", "scores.json");
37643
37739
  }
37644
37740
  async function readBaselineFile(cwd) {
37645
37741
  const file = baselinePath(cwd);
@@ -37660,7 +37756,7 @@ async function loadBaselineSources(cwd) {
37660
37756
  }
37661
37757
  async function writeBaselineFile(cwd, data) {
37662
37758
  const file = baselinePath(cwd);
37663
- await mkdir27(path108.dirname(file), { recursive: true });
37759
+ await mkdir27(path109.dirname(file), { recursive: true });
37664
37760
  await writeFile20(file, `${JSON.stringify(data, null, 2)}
37665
37761
  `, "utf8");
37666
37762
  }
@@ -37742,10 +37838,10 @@ async function getChurn(cwd, windowDays) {
37742
37838
 
37743
37839
  // src/health/metrics/wiki-freshness.ts
37744
37840
  import { readFile as readFile57, stat as stat16 } from "fs/promises";
37745
- import path109 from "path";
37841
+ import path110 from "path";
37746
37842
  var DEFAULT_STALE_EVIDENCE_DAYS = 7;
37747
37843
  function freshnessReportPath(cwd) {
37748
- return path109.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
37844
+ return path110.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
37749
37845
  }
37750
37846
  async function readWikiFreshnessMetric(cwd, options = {}) {
37751
37847
  const file = freshnessReportPath(cwd);
@@ -37766,7 +37862,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
37766
37862
  } catch {
37767
37863
  return {
37768
37864
  status: "unreadable-report",
37769
- reason: `${path109.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
37865
+ reason: `${path110.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
37770
37866
  };
37771
37867
  }
37772
37868
  const report = parsed;
@@ -37776,7 +37872,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
37776
37872
  if (pagesTotal === null || pagesFresh === null) {
37777
37873
  return {
37778
37874
  status: "unreadable-report",
37779
- reason: `${path109.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
37875
+ reason: `${path110.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
37780
37876
  };
37781
37877
  }
37782
37878
  const pagesUndecidable = numberOr3(totals.pagesUndecidable) ?? 0;
@@ -37830,12 +37926,12 @@ function renderWikiFreshnessLine(metric) {
37830
37926
  }
37831
37927
 
37832
37928
  // src/health/sources/helpers.ts
37833
- import path110 from "path";
37929
+ import path111 from "path";
37834
37930
  import { existsSync as existsSync12 } from "fs";
37835
37931
  class NoImportError extends Error {
37836
37932
  }
37837
37933
  function resolveBin(cwd, name) {
37838
- const local = path110.join(cwd, "node_modules", ".bin", name);
37934
+ const local = path111.join(cwd, "node_modules", ".bin", name);
37839
37935
  if (existsSync12(local)) {
37840
37936
  return local;
37841
37937
  }
@@ -37916,13 +38012,13 @@ async function getComplexityFindings(cwd, sourceFiles, config, sourceAnalysis) {
37916
38012
 
37917
38013
  // src/health/metrics/coverage.ts
37918
38014
  import { existsSync as existsSync13 } from "fs";
37919
- import path111 from "path";
38015
+ import path112 from "path";
37920
38016
  var SUMMARY_PATHS = [
37921
38017
  "coverage/coverage-summary.json",
37922
38018
  "coverage/coverage-final.json"
37923
38019
  ];
37924
38020
  async function getCoverage(cwd) {
37925
- const summary = SUMMARY_PATHS.map((rel) => path111.join(cwd, rel)).find((abs) => existsSync13(abs));
38021
+ const summary = SUMMARY_PATHS.map((rel) => path112.join(cwd, rel)).find((abs) => existsSync13(abs));
37926
38022
  if (!summary) {
37927
38023
  return { status: "missing", total: null, byFile: new Map };
37928
38024
  }
@@ -37943,7 +38039,7 @@ async function getCoverage(cwd) {
37943
38039
  total = pct;
37944
38040
  continue;
37945
38041
  }
37946
- const relative = path111.isAbsolute(key) ? path111.relative(cwd, key) : key;
38042
+ const relative = path112.isAbsolute(key) ? path112.relative(cwd, key) : key;
37947
38043
  byFile.set(relative.replace(/\\/g, "/"), pct);
37948
38044
  }
37949
38045
  return { status: "available", total, byFile };
@@ -38076,10 +38172,10 @@ function renderWikiFreshness(metric) {
38076
38172
  // src/health/skills.ts
38077
38173
  init_fs();
38078
38174
  import { readFile as readFile58 } from "fs/promises";
38079
- import path112 from "path";
38175
+ import path113 from "path";
38080
38176
  var EMPTY = { skills: [], skillForFile: () => null };
38081
38177
  async function loadSkillOwnership(cwd) {
38082
- const manifestPath = path112.join(cwd, ".metaproject", "metaproject.json");
38178
+ const manifestPath = path113.join(cwd, ".metaproject", "metaproject.json");
38083
38179
  if (!await pathExists(manifestPath)) {
38084
38180
  return EMPTY;
38085
38181
  }
@@ -38117,7 +38213,7 @@ function normalize(value) {
38117
38213
 
38118
38214
  // src/health/sources/eslint.ts
38119
38215
  import { existsSync as existsSync14 } from "fs";
38120
- import path113 from "path";
38216
+ import path114 from "path";
38121
38217
  var CONFIG_FILES = [
38122
38218
  ".eslintrc",
38123
38219
  ".eslintrc.js",
@@ -38131,7 +38227,7 @@ var CONFIG_FILES = [
38131
38227
  "eslint.config.ts"
38132
38228
  ];
38133
38229
  function hasConfig(cwd) {
38134
- return CONFIG_FILES.some((file) => existsSync14(path113.join(cwd, file)));
38230
+ return CONFIG_FILES.some((file) => existsSync14(path114.join(cwd, file)));
38135
38231
  }
38136
38232
  var eslintAdapter = {
38137
38233
  id: "eslint",
@@ -38157,7 +38253,7 @@ var eslintAdapter = {
38157
38253
  };
38158
38254
  },
38159
38255
  async import(ctx) {
38160
- const report = path113.join(ctx.cwd, "eslint-report.json");
38256
+ const report = path114.join(ctx.cwd, "eslint-report.json");
38161
38257
  if (!existsSync14(report)) {
38162
38258
  throw new NoImportError("no eslint-report.json");
38163
38259
  }
@@ -38184,7 +38280,7 @@ var eslintAdapter = {
38184
38280
  }
38185
38281
  const findings = [];
38186
38282
  for (const file of data) {
38187
- const relative = path113.isAbsolute(file.filePath) ? path113.relative(ctx.cwd, file.filePath) : file.filePath;
38283
+ const relative = path114.isAbsolute(file.filePath) ? path114.relative(ctx.cwd, file.filePath) : file.filePath;
38188
38284
  for (const message of file.messages ?? []) {
38189
38285
  const isError = message.severity === 2;
38190
38286
  findings.push(makeFinding({
@@ -38216,19 +38312,19 @@ var eslintAdapter = {
38216
38312
 
38217
38313
  // src/health/sources/oxlint.ts
38218
38314
  import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
38219
- import path114 from "path";
38315
+ import path115 from "path";
38220
38316
  var CONFIG_FILES2 = [".oxlintrc.json", ".oxlintrc.jsonc"];
38221
38317
  var OXLINT_FORMAT = "json";
38222
38318
  var OXLINT_PARSE_ERROR = "oxlint JSON format was not recognized";
38223
38319
  var OXLINT_NO_FILES = "oxlint found no files to lint (check its paths and ignore patterns)";
38224
38320
  var NO_FILES_PREAMBLE = "No files found to lint";
38225
38321
  function hasConfigFile(cwd) {
38226
- if (CONFIG_FILES2.some((file) => existsSync15(path114.join(cwd, file))))
38322
+ if (CONFIG_FILES2.some((file) => existsSync15(path115.join(cwd, file))))
38227
38323
  return true;
38228
- return [".oxlintrc.js", ".oxlintrc.cjs", ".oxlintrc.mjs", ".oxlintrc.ts"].some((file) => existsSync15(path114.join(cwd, file)));
38324
+ return [".oxlintrc.js", ".oxlintrc.cjs", ".oxlintrc.mjs", ".oxlintrc.ts"].some((file) => existsSync15(path115.join(cwd, file)));
38229
38325
  }
38230
38326
  function packageNamesOxlint(cwd) {
38231
- const file = path114.join(cwd, "package.json");
38327
+ const file = path115.join(cwd, "package.json");
38232
38328
  if (!existsSync15(file))
38233
38329
  return false;
38234
38330
  try {
@@ -38286,7 +38382,7 @@ var oxlintAdapter = {
38286
38382
  return [];
38287
38383
  return data.map((diagnostic) => {
38288
38384
  const filePath = diagnostic.filename ?? "";
38289
- const relative = filePath && path114.isAbsolute(filePath) ? path114.relative(ctx.cwd, filePath) : filePath;
38385
+ const relative = filePath && path115.isAbsolute(filePath) ? path115.relative(ctx.cwd, filePath) : filePath;
38290
38386
  const isError = diagnostic.severity === "error";
38291
38387
  return makeFinding({
38292
38388
  source: "oxlint",
@@ -38312,9 +38408,9 @@ var oxlintAdapter = {
38312
38408
 
38313
38409
  // src/health/sources/typescript.ts
38314
38410
  import { existsSync as existsSync16 } from "fs";
38315
- import path115 from "path";
38411
+ import path116 from "path";
38316
38412
  function hasTsconfig(cwd) {
38317
- return existsSync16(path115.join(cwd, "tsconfig.json"));
38413
+ return existsSync16(path116.join(cwd, "tsconfig.json"));
38318
38414
  }
38319
38415
  var typescriptAdapter = {
38320
38416
  id: "typescript",
@@ -38375,12 +38471,12 @@ init_fs();
38375
38471
  init_contained_write();
38376
38472
  import { existsSync as existsSync17 } from "fs";
38377
38473
  import { readFile as readFile61, readdir as readdir20 } from "fs/promises";
38378
- import path119 from "path";
38474
+ import path120 from "path";
38379
38475
  // src/metrics/lifecycle.ts
38380
38476
  init_fs();
38381
38477
  init_guard();
38382
38478
  import { readFile as readFile59 } from "fs/promises";
38383
- import path116 from "path";
38479
+ import path117 from "path";
38384
38480
 
38385
38481
  // src/metrics/record.ts
38386
38482
  var RELIABILITIES = new Set(["exact", "estimated", "unknown"]);
@@ -38395,7 +38491,7 @@ var RETRY_TYPES = new Set([
38395
38491
 
38396
38492
  // src/metrics/lifecycle.ts
38397
38493
  async function readArtifactPointer(root, expected) {
38398
- const pointerFile = path116.join(root, "latest.json");
38494
+ const pointerFile = path117.join(root, "latest.json");
38399
38495
  if (!await pathExists(pointerFile))
38400
38496
  return { status: "missing", pointer: null };
38401
38497
  let pointer;
@@ -38404,7 +38500,7 @@ async function readArtifactPointer(root, expected) {
38404
38500
  } catch {
38405
38501
  return { status: "stale", pointer: null, reason: "latest pointer is invalid JSON" };
38406
38502
  }
38407
- const recordFile = pointer.record ? path116.join(root, pointer.record) : null;
38503
+ const recordFile = pointer.record ? path117.join(root, pointer.record) : null;
38408
38504
  if (!recordFile || !isPathInside(root, recordFile) || !await pathExists(recordFile)) {
38409
38505
  return { status: "stale", pointer, reason: "pointer record is missing" };
38410
38506
  }
@@ -38420,9 +38516,9 @@ init_guard();
38420
38516
  // src/testing/capability.ts
38421
38517
  init_fs();
38422
38518
  init_json();
38423
- import path117 from "path";
38519
+ import path118 from "path";
38424
38520
  async function isTestingCapabilityEnabled(cwd, capability) {
38425
- const manifestPath = path117.join(cwd, ".metaproject", "metaproject.json");
38521
+ const manifestPath = path118.join(cwd, ".metaproject", "metaproject.json");
38426
38522
  if (!await pathExists(manifestPath)) {
38427
38523
  return false;
38428
38524
  }
@@ -38448,10 +38544,10 @@ async function isTestingCapabilityEnabled(cwd, capability) {
38448
38544
  init_fs();
38449
38545
  init_guard();
38450
38546
  import { readFile as readFile60, mkdir as mkdir28, writeFile as writeFile21 } from "fs/promises";
38451
- import path118 from "path";
38547
+ import path119 from "path";
38452
38548
  var COVERAGE_MAP_SCHEMA_VERSION = 1;
38453
38549
  function coverageMapPath(cwd, cfg) {
38454
- return path118.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path118.join(cwd, cfg.coverageMap.artifact);
38550
+ return path119.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path119.join(cwd, cfg.coverageMap.artifact);
38455
38551
  }
38456
38552
  async function loadCoverageMap(cwd, cfg) {
38457
38553
  const file = coverageMapPath(cwd, cfg);
@@ -38586,7 +38682,7 @@ var DEFAULT_TESTING_CONFIG = {
38586
38682
  }
38587
38683
  };
38588
38684
  function testingDataRoot(cwd) {
38589
- return path119.join(cwd, ".metaproject", "data", "testing");
38685
+ return path120.join(cwd, ".metaproject", "data", "testing");
38590
38686
  }
38591
38687
  async function computeTestingContext(cwd) {
38592
38688
  const { files, incompleteReasons } = await listProjectFiles(cwd);
@@ -38761,7 +38857,7 @@ async function runTesting(input) {
38761
38857
  return runResult;
38762
38858
  }
38763
38859
  async function loadTestingContext(cwd) {
38764
- const file = path119.join(testingDataRoot(cwd), "context.json");
38860
+ const file = path120.join(testingDataRoot(cwd), "context.json");
38765
38861
  if (!await pathExists(file)) {
38766
38862
  return null;
38767
38863
  }
@@ -38772,18 +38868,18 @@ async function loadTestingContext(cwd) {
38772
38868
  }
38773
38869
  }
38774
38870
  async function loadTestingReport(cwd) {
38775
- const file = path119.join(testingDataRoot(cwd), "artifacts", "latest.json");
38871
+ const file = path120.join(testingDataRoot(cwd), "artifacts", "latest.json");
38776
38872
  if (!await pathExists(file)) {
38777
38873
  return null;
38778
38874
  }
38779
38875
  try {
38780
38876
  const latest = JSON.parse(await readFile61(file, "utf8"));
38781
38877
  if (typeof latest.record === "string") {
38782
- const pointer = await readArtifactPointer(path119.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
38878
+ const pointer = await readArtifactPointer(path120.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
38783
38879
  if (pointer.status !== "fresh")
38784
38880
  return null;
38785
- const recordFile = path119.join(testingDataRoot(cwd), "artifacts", latest.record);
38786
- if (!isPathInside(path119.join(testingDataRoot(cwd), "artifacts"), recordFile))
38881
+ const recordFile = path120.join(testingDataRoot(cwd), "artifacts", latest.record);
38882
+ if (!isPathInside(path120.join(testingDataRoot(cwd), "artifacts"), recordFile))
38787
38883
  return null;
38788
38884
  if (!await pathExists(recordFile))
38789
38885
  return null;
@@ -38830,28 +38926,28 @@ async function ensureContext(cwd) {
38830
38926
  }
38831
38927
  async function writeContext(cwd, context) {
38832
38928
  const root = testingDataRoot(cwd);
38833
- const rel = (p) => path119.relative(cwd, p);
38929
+ const rel = (p) => path120.relative(cwd, p);
38834
38930
  await mkdirContained(cwd, rel(root));
38835
- await writeContained(cwd, rel(path119.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
38931
+ await writeContained(cwd, rel(path120.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
38836
38932
  `);
38837
- await writeContained(cwd, rel(path119.join(root, "context.md")), renderContextMarkdown(context));
38838
- await writeContained(cwd, rel(path119.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
38933
+ await writeContained(cwd, rel(path120.join(root, "context.md")), renderContextMarkdown(context));
38934
+ await writeContained(cwd, rel(path120.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
38839
38935
  }
38840
38936
  async function writeReport(cwd, report) {
38841
38937
  const root = testingDataRoot(cwd);
38842
- const artifacts = path119.join(root, "artifacts");
38843
- const history = path119.join(root, "history");
38844
- const rel = (p) => path119.relative(cwd, p);
38938
+ const artifacts = path120.join(root, "artifacts");
38939
+ const history = path120.join(root, "history");
38940
+ const rel = (p) => path120.relative(cwd, p);
38845
38941
  await mkdirContained(cwd, rel(artifacts));
38846
38942
  await mkdirContained(cwd, rel(history));
38847
38943
  const stamp = report.generatedAt.replace(/[:.]/g, "-");
38848
- const json = path119.join(artifacts, "latest.json");
38849
- const markdown = path119.join(artifacts, "latest.md");
38944
+ const json = path120.join(artifacts, "latest.json");
38945
+ const markdown = path120.join(artifacts, "latest.md");
38850
38946
  const serialized = `${JSON.stringify(report, null, 2)}
38851
38947
  `;
38852
38948
  if (report.runId) {
38853
- const runJson = path119.join(artifacts, "runs", `${report.runId}.json`);
38854
- const runMarkdown = path119.join(artifacts, "runs", `${report.runId}.md`);
38949
+ const runJson = path120.join(artifacts, "runs", `${report.runId}.json`);
38950
+ const runMarkdown = path120.join(artifacts, "runs", `${report.runId}.md`);
38855
38951
  if (await pathExists(runJson))
38856
38952
  throw new Error(`immutable testing run already exists: ${report.runId}`);
38857
38953
  await writeContained(cwd, rel(runJson), serialized);
@@ -38862,26 +38958,26 @@ async function writeReport(cwd, report) {
38862
38958
  branch: report.provenance?.branch ?? null,
38863
38959
  worktree: report.provenance?.worktree ?? null,
38864
38960
  generated_at: report.generatedAt,
38865
- record: path119.posix.join("runs", `${report.runId}.json`)
38961
+ record: path120.posix.join("runs", `${report.runId}.json`)
38866
38962
  }, null, 2)}
38867
38963
  `);
38868
38964
  } else {
38869
38965
  await writeContained(cwd, rel(json), serialized);
38870
38966
  }
38871
38967
  await writeContained(cwd, rel(markdown), renderReportMarkdown3(report));
38872
- await writeContained(cwd, rel(path119.join(history, `${stamp}.json`)), serialized);
38968
+ await writeContained(cwd, rel(path120.join(history, `${stamp}.json`)), serialized);
38873
38969
  return {
38874
- markdownPath: path119.relative(cwd, markdown),
38875
- jsonPath: path119.relative(cwd, json)
38970
+ markdownPath: path120.relative(cwd, markdown),
38971
+ jsonPath: path120.relative(cwd, json)
38876
38972
  };
38877
38973
  }
38878
38974
  async function writeRawLog(cwd, raw) {
38879
- const logs = path119.join(testingDataRoot(cwd), "logs");
38880
- const rel = (p) => path119.relative(cwd, p);
38975
+ const logs = path120.join(testingDataRoot(cwd), "logs");
38976
+ const rel = (p) => path120.relative(cwd, p);
38881
38977
  await mkdirContained(cwd, rel(logs));
38882
- const latest = path119.join(logs, "latest.raw.log");
38978
+ const latest = path120.join(logs, "latest.raw.log");
38883
38979
  await writeContained(cwd, rel(latest), raw);
38884
- return path119.relative(cwd, latest);
38980
+ return path120.relative(cwd, latest);
38885
38981
  }
38886
38982
  async function listProjectFiles(cwd) {
38887
38983
  const out = [];
@@ -38894,11 +38990,11 @@ async function walk3(root, dir, out, incompleteReasons) {
38894
38990
  try {
38895
38991
  entries = await readdir20(dir, { withFileTypes: true });
38896
38992
  } catch (error) {
38897
- incompleteReasons.push(`${normalizePath6(path119.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
38993
+ incompleteReasons.push(`${normalizePath6(path120.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
38898
38994
  return;
38899
38995
  }
38900
38996
  for (const entry of entries) {
38901
- const abs = path119.join(dir, entry.name);
38997
+ const abs = path120.join(dir, entry.name);
38902
38998
  if (entry.isDirectory()) {
38903
38999
  if (IGNORED_DIRS2.has(entry.name) || entry.name.startsWith(".tmp-")) {
38904
39000
  continue;
@@ -38907,12 +39003,12 @@ async function walk3(root, dir, out, incompleteReasons) {
38907
39003
  continue;
38908
39004
  }
38909
39005
  if (entry.isFile()) {
38910
- out.push(normalizePath6(path119.relative(root, abs)));
39006
+ out.push(normalizePath6(path120.relative(root, abs)));
38911
39007
  }
38912
39008
  }
38913
39009
  }
38914
39010
  async function readPackageJson(cwd) {
38915
- const file = path119.join(cwd, "package.json");
39011
+ const file = path120.join(cwd, "package.json");
38916
39012
  if (!await pathExists(file)) {
38917
39013
  return null;
38918
39014
  }
@@ -38923,7 +39019,7 @@ async function readPackageJson(cwd) {
38923
39019
  }
38924
39020
  }
38925
39021
  async function loadTestingConfig(cwd) {
38926
- const file = path119.join(cwd, ".metaproject", "testing.config.json");
39022
+ const file = path120.join(cwd, ".metaproject", "testing.config.json");
38927
39023
  if (!await pathExists(file)) {
38928
39024
  return DEFAULT_TESTING_CONFIG;
38929
39025
  }
@@ -38988,7 +39084,7 @@ function detectFrameworks(input) {
38988
39084
  async function extractConventions(cwd, files) {
38989
39085
  const conventions = new Set;
38990
39086
  for (const file of files.slice(0, 40)) {
38991
- const abs = path119.join(cwd, file);
39087
+ const abs = path120.join(cwd, file);
38992
39088
  if (!await pathExists(abs)) {
38993
39089
  continue;
38994
39090
  }
@@ -39118,7 +39214,7 @@ async function findTestsByImportedTargets(cwd, targets, testFiles) {
39118
39214
  const targetKeys = new Set(targets.map((target) => modulePathKey(normalizePath6(target))));
39119
39215
  const selected = new Set;
39120
39216
  for (const testFile of testFiles) {
39121
- const absoluteTest = path119.join(cwd, testFile);
39217
+ const absoluteTest = path120.join(cwd, testFile);
39122
39218
  if (!await pathExists(absoluteTest)) {
39123
39219
  continue;
39124
39220
  }
@@ -39152,10 +39248,10 @@ function resolveImportPath(cwd, testFile, importPath) {
39152
39248
  if (!importPath.startsWith(".")) {
39153
39249
  return null;
39154
39250
  }
39155
- const importerDir = path119.dirname(testFile);
39156
- const absoluteResolved = path119.resolve(path119.join(cwd, importerDir), importPath);
39157
- const relative = path119.relative(cwd, absoluteResolved);
39158
- if (relative.startsWith(`..${path119.sep}`) || relative === "..") {
39251
+ const importerDir = path120.dirname(testFile);
39252
+ const absoluteResolved = path120.resolve(path120.join(cwd, importerDir), importPath);
39253
+ const relative = path120.relative(cwd, absoluteResolved);
39254
+ if (relative.startsWith(`..${path120.sep}`) || relative === "..") {
39159
39255
  return null;
39160
39256
  }
39161
39257
  const relativeNormalized = normalizePath6(relative);
@@ -39207,13 +39303,13 @@ function resolveTestCommand(cwd, context, input) {
39207
39303
  }
39208
39304
  var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
39209
39305
  function detectPackageManager(cwd) {
39210
- if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path119.join(cwd, name)))) {
39306
+ if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path120.join(cwd, name)))) {
39211
39307
  return "bun";
39212
39308
  }
39213
- if (Bun.which("pnpm") && pathExistsSync(path119.join(cwd, "pnpm-lock.yaml"))) {
39309
+ if (Bun.which("pnpm") && pathExistsSync(path120.join(cwd, "pnpm-lock.yaml"))) {
39214
39310
  return "pnpm";
39215
39311
  }
39216
- if (Bun.which("yarn") && pathExistsSync(path119.join(cwd, "yarn.lock"))) {
39312
+ if (Bun.which("yarn") && pathExistsSync(path120.join(cwd, "yarn.lock"))) {
39217
39313
  return "yarn";
39218
39314
  }
39219
39315
  return "npm";
@@ -39553,7 +39649,7 @@ async function compatibleReportForHealth(ctx) {
39553
39649
 
39554
39650
  // src/health/sources/dependency-audit.ts
39555
39651
  import { existsSync as existsSync18 } from "fs";
39556
- import path120 from "path";
39652
+ import path121 from "path";
39557
39653
  function auditSeverityToPriority(severity) {
39558
39654
  if (severity === "critical" || severity === "high")
39559
39655
  return "P0";
@@ -39672,7 +39768,7 @@ var LOCKFILE_COMMANDS = [
39672
39768
  ];
39673
39769
  function auditCommand(cwd) {
39674
39770
  for (const entry of LOCKFILE_COMMANDS) {
39675
- if (!entry.lockfiles.some((name) => existsSync18(path120.join(cwd, name))))
39771
+ if (!entry.lockfiles.some((name) => existsSync18(path121.join(cwd, name))))
39676
39772
  continue;
39677
39773
  const bin = resolveBin(cwd, entry.bin);
39678
39774
  if (bin)
@@ -39731,13 +39827,13 @@ var dependencyAuditAdapter = {
39731
39827
 
39732
39828
  // src/health/sources/sonarqube.ts
39733
39829
  import { existsSync as existsSync19 } from "fs";
39734
- import path121 from "path";
39830
+ import path122 from "path";
39735
39831
  var REPORT_FILES = ["sonar-issues.json", ".metaproject/data/health/sonar-issues.json"];
39736
39832
  function reportPath(cwd) {
39737
39833
  const fromEnv = process.env.SONAR_ISSUES_FILE;
39738
39834
  const candidates = fromEnv ? [fromEnv, ...REPORT_FILES] : REPORT_FILES;
39739
39835
  for (const rel of candidates) {
39740
- const abs = path121.isAbsolute(rel) ? rel : path121.join(cwd, rel);
39836
+ const abs = path122.isAbsolute(rel) ? rel : path122.join(cwd, rel);
39741
39837
  if (existsSync19(abs)) {
39742
39838
  return abs;
39743
39839
  }
@@ -39821,7 +39917,7 @@ var sonarqubeAdapter = {
39821
39917
  function relativizeComponent(component, cwd) {
39822
39918
  const colon = component.indexOf(":");
39823
39919
  const value = colon >= 0 ? component.slice(colon + 1) : component;
39824
- return path121.isAbsolute(value) ? path121.relative(cwd, value) : value;
39920
+ return path122.isAbsolute(value) ? path122.relative(cwd, value) : value;
39825
39921
  }
39826
39922
 
39827
39923
  // src/health/sources/index.ts
@@ -40182,19 +40278,19 @@ function filteredInfo(source, cfg) {
40182
40278
  };
40183
40279
  }
40184
40280
  async function writeOutputs(cwd, report, config, stamp) {
40185
- const artifacts = path122.join(dataRoot3(cwd), "artifacts");
40186
- const history = path122.join(dataRoot3(cwd), "history");
40281
+ const artifacts = path123.join(dataRoot3(cwd), "artifacts");
40282
+ const history = path123.join(dataRoot3(cwd), "history");
40187
40283
  await mkdir29(artifacts, { recursive: true });
40188
40284
  await mkdir29(history, { recursive: true });
40189
- const markdown = path122.join(artifacts, "latest.md");
40190
- const json = path122.join(artifacts, "latest.json");
40191
- const historyJson = path122.join(history, `${stamp}.json`);
40285
+ const markdown = path123.join(artifacts, "latest.md");
40286
+ const json = path123.join(artifacts, "latest.json");
40287
+ const historyJson = path123.join(history, `${stamp}.json`);
40192
40288
  const serialized = `${JSON.stringify(report, null, 2)}
40193
40289
  `;
40194
40290
  await writeFile22(markdown, renderReportMarkdown2(report, config), "utf8");
40195
40291
  if (report.runId) {
40196
- const runJson = path122.join(artifacts, "runs", `${report.runId}.json`);
40197
- const runMarkdown = path122.join(artifacts, "runs", `${report.runId}.md`);
40292
+ const runJson = path123.join(artifacts, "runs", `${report.runId}.json`);
40293
+ const runMarkdown = path123.join(artifacts, "runs", `${report.runId}.md`);
40198
40294
  if (await pathExists(runJson))
40199
40295
  throw new Error(`immutable health run already exists: ${report.runId}`);
40200
40296
  await writeFileAtomic(runJson, serialized);
@@ -40205,7 +40301,7 @@ async function writeOutputs(cwd, report, config, stamp) {
40205
40301
  branch: report.provenance?.branch ?? null,
40206
40302
  worktree: report.provenance?.worktree ?? null,
40207
40303
  generated_at: report.generatedAt,
40208
- record: path122.posix.join("runs", `${report.runId}.json`)
40304
+ record: path123.posix.join("runs", `${report.runId}.json`)
40209
40305
  }, null, 2)}
40210
40306
  `);
40211
40307
  } else {
@@ -40213,8 +40309,8 @@ async function writeOutputs(cwd, report, config, stamp) {
40213
40309
  }
40214
40310
  await writeFile22(historyJson, serialized, "utf8");
40215
40311
  return {
40216
- markdownPath: path122.relative(cwd, markdown),
40217
- jsonPath: path122.relative(cwd, json)
40312
+ markdownPath: path123.relative(cwd, markdown),
40313
+ jsonPath: path123.relative(cwd, json)
40218
40314
  };
40219
40315
  }
40220
40316
  async function resolveChanged(cwd, selector) {
@@ -40267,7 +40363,7 @@ function hasGateShape(value) {
40267
40363
  return Array.isArray(report.metrics) && Array.isArray(report.sources) && Array.isArray(report.findings);
40268
40364
  }
40269
40365
  async function readLatest(cwd) {
40270
- const file = path123.join(dataRoot3(cwd), "artifacts", "latest.json");
40366
+ const file = path124.join(dataRoot3(cwd), "artifacts", "latest.json");
40271
40367
  if (!await pathExists(file)) {
40272
40368
  return null;
40273
40369
  }
@@ -40278,11 +40374,11 @@ async function readLatest(cwd) {
40278
40374
  const latest = read.value;
40279
40375
  const record = latest.record;
40280
40376
  if (typeof record === "string") {
40281
- const pointer = await readArtifactPointer(path123.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
40377
+ const pointer = await readArtifactPointer(path124.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
40282
40378
  if (pointer.status !== "fresh")
40283
40379
  return null;
40284
- const recordFile = path123.join(dataRoot3(cwd), "artifacts", record);
40285
- if (!isPathInside(path123.join(dataRoot3(cwd), "artifacts"), recordFile))
40380
+ const recordFile = path124.join(dataRoot3(cwd), "artifacts", record);
40381
+ if (!isPathInside(path124.join(dataRoot3(cwd), "artifacts"), recordFile))
40286
40382
  return null;
40287
40383
  if (!await pathExists(recordFile))
40288
40384
  return null;
@@ -40355,7 +40451,7 @@ function createCodeHealthService() {
40355
40451
  return {
40356
40452
  run: (input) => runHealth(input),
40357
40453
  async status(input) {
40358
- const enabled = await pathExists(path123.join(input.cwd, ".metaproject", "health.config.json"));
40454
+ const enabled = await pathExists(path124.join(input.cwd, ".metaproject", "health.config.json"));
40359
40455
  const latest = await readLatest(input.cwd);
40360
40456
  const project = latest?.metrics.find((m) => m.key === "project") ?? null;
40361
40457
  const decliningScopes = latest ? latest.metrics.filter((m) => m.regression_score > 0).length : 0;
@@ -40512,10 +40608,10 @@ function renderEvidenceBlock(evidences, siblings) {
40512
40608
  init_fs();
40513
40609
  init_contained_write();
40514
40610
  init_json();
40515
- import path124 from "path";
40611
+ import path125 from "path";
40516
40612
  import { createHash as createHash21 } from "crypto";
40517
40613
  function impactEvidenceDataRoot(root) {
40518
- return path124.join(root, ".metaproject", "data", "security", "impact-evidence");
40614
+ return path125.join(root, ".metaproject", "data", "security", "impact-evidence");
40519
40615
  }
40520
40616
  function sanitizeSessionId(sessionId) {
40521
40617
  const cleaned = sessionId.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -40527,7 +40623,7 @@ function sessionStateFilename(sessionId) {
40527
40623
  return `${sanitized}-${suffix}.json`;
40528
40624
  }
40529
40625
  function sessionStatePath(root, sessionId) {
40530
- return path124.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
40626
+ return path125.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
40531
40627
  }
40532
40628
  async function loadSessionState(root, sessionId) {
40533
40629
  const file = sessionStatePath(root, sessionId);
@@ -40546,11 +40642,11 @@ async function loadSessionState(root, sessionId) {
40546
40642
  }
40547
40643
  async function saveSessionState(root, sessionId, state) {
40548
40644
  const file = sessionStatePath(root, sessionId);
40549
- await writeContained(root, path124.relative(root, file), `${JSON.stringify(state, null, 2)}
40645
+ await writeContained(root, path125.relative(root, file), `${JSON.stringify(state, null, 2)}
40550
40646
  `);
40551
40647
  }
40552
40648
  function logPath(root) {
40553
- return path124.join(impactEvidenceDataRoot(root), "log.jsonl");
40649
+ return path125.join(impactEvidenceDataRoot(root), "log.jsonl");
40554
40650
  }
40555
40651
  async function appendLogRecord(root, record) {
40556
40652
  const full = {
@@ -40561,7 +40657,7 @@ async function appendLogRecord(root, record) {
40561
40657
  ...record.detail !== undefined ? { detail: record.detail } : {}
40562
40658
  };
40563
40659
  const file = logPath(root);
40564
- await appendContained(root, path124.relative(root, file), `${JSON.stringify(full)}
40660
+ await appendContained(root, path125.relative(root, file), `${JSON.stringify(full)}
40565
40661
  `);
40566
40662
  return full;
40567
40663
  }
@@ -40588,7 +40684,7 @@ init_command_risk();
40588
40684
  init_shell_syntax();
40589
40685
  init_fs();
40590
40686
  init_service2();
40591
- import path125 from "path";
40687
+ import path126 from "path";
40592
40688
  import { createHash as createHash22 } from "crypto";
40593
40689
  import { realpathSync as realpathSync2 } from "fs";
40594
40690
  function impactEvidenceHookClass(strict) {
@@ -40604,29 +40700,29 @@ function realpathNearestExisting(p) {
40604
40700
  for (;; ) {
40605
40701
  try {
40606
40702
  const real = realpathSync2(current);
40607
- return tail.length > 0 ? path125.join(real, ...tail) : real;
40703
+ return tail.length > 0 ? path126.join(real, ...tail) : real;
40608
40704
  } catch {
40609
- const parent = path125.dirname(current);
40705
+ const parent = path126.dirname(current);
40610
40706
  if (parent === current) {
40611
- return tail.length > 0 ? path125.join(current, ...tail) : current;
40707
+ return tail.length > 0 ? path126.join(current, ...tail) : current;
40612
40708
  }
40613
- tail.unshift(path125.basename(current));
40709
+ tail.unshift(path126.basename(current));
40614
40710
  current = parent;
40615
40711
  }
40616
40712
  }
40617
40713
  }
40618
40714
  function normalizeRequestFiles(root, files) {
40619
- const rootReal = realpathNearestExisting(path125.resolve(root));
40715
+ const rootReal = realpathNearestExisting(path126.resolve(root));
40620
40716
  const normalized = [];
40621
40717
  const rejected = [];
40622
40718
  for (const file of files) {
40623
- const lexicalAbsolute = path125.isAbsolute(file) ? path125.resolve(file) : path125.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
40719
+ const lexicalAbsolute = path126.isAbsolute(file) ? path126.resolve(file) : path126.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
40624
40720
  const effective = realpathNearestExisting(lexicalAbsolute);
40625
40721
  if (!isPathInside(rootReal, effective)) {
40626
40722
  rejected.push(file);
40627
40723
  continue;
40628
40724
  }
40629
- normalized.push(toPosix(path125.relative(rootReal, effective)));
40725
+ normalized.push(toPosix(path126.relative(rootReal, effective)));
40630
40726
  }
40631
40727
  return { files: [...new Set(normalized)], rejected };
40632
40728
  }
@@ -40908,7 +41004,7 @@ function hostDeliveryStatus() {
40908
41004
  // src/job/service.ts
40909
41005
  init_fs();
40910
41006
  import { copyFile, mkdir as mkdir31 } from "fs/promises";
40911
- import path128 from "path";
41007
+ import path129 from "path";
40912
41008
 
40913
41009
  // src/job/types.ts
40914
41010
  var JOB_INTENTS = ["implement", "analyze", "review", "custom"];
@@ -41049,15 +41145,15 @@ init_validator();
41049
41145
  init_contracts();
41050
41146
  init_fs();
41051
41147
  import { appendFile as appendFile6, mkdir as mkdir30, readFile as readFile63, readdir as readdir21 } from "fs/promises";
41052
- import path127 from "path";
41148
+ import path128 from "path";
41053
41149
  function jobsRoot(cwd) {
41054
- return path127.join(cwd, ".metaproject", "jobs");
41150
+ return path128.join(cwd, ".metaproject", "jobs");
41055
41151
  }
41056
41152
  function jobDir(cwd, name) {
41057
- return path127.join(jobsRoot(cwd), name);
41153
+ return path128.join(jobsRoot(cwd), name);
41058
41154
  }
41059
41155
  function jobStatePath(cwd, name) {
41060
- return path127.join(jobDir(cwd, name), "state.json");
41156
+ return path128.join(jobDir(cwd, name), "state.json");
41061
41157
  }
41062
41158
  var JOB_NAME_PATTERN = /^[a-z0-9-]+$/;
41063
41159
  function assertJobName(name) {
@@ -41094,12 +41190,12 @@ async function writeJob(cwd, name, state) {
41094
41190
  `));
41095
41191
  }
41096
41192
  const file = jobStatePath(cwd, name);
41097
- await mkdir30(path127.dirname(file), { recursive: true });
41193
+ await mkdir30(path128.dirname(file), { recursive: true });
41098
41194
  await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
41099
41195
  `);
41100
41196
  }
41101
41197
  async function appendJournal2(cwd, name, at, line) {
41102
- await appendFile6(path127.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
41198
+ await appendFile6(path128.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
41103
41199
  `, "utf8");
41104
41200
  }
41105
41201
  function renderJournal2(name, at) {
@@ -41120,7 +41216,7 @@ function assertDocumentType(raw) {
41120
41216
  return raw;
41121
41217
  }
41122
41218
  function documentFileName(type, sourcePath) {
41123
- const extension = path127.extname(sourcePath) || ".md";
41219
+ const extension = path128.extname(sourcePath) || ".md";
41124
41220
  return `${type}${extension}`;
41125
41221
  }
41126
41222
 
@@ -41128,7 +41224,7 @@ function documentFileName(type, sourcePath) {
41128
41224
  function createJobService(deps) {
41129
41225
  const now = () => deps.now().toISOString();
41130
41226
  function lockPath(cwd, name) {
41131
- return path128.join(jobsRoot(cwd), `.job-lock-${name}`);
41227
+ return path129.join(jobsRoot(cwd), `.job-lock-${name}`);
41132
41228
  }
41133
41229
  async function mutate(cwd, name, run) {
41134
41230
  assertJobName(name);
@@ -41177,20 +41273,20 @@ function createJobService(deps) {
41177
41273
  },
41178
41274
  plan: { steps: defaultPlan(intent) },
41179
41275
  documentation: {
41180
- job_path: path128.join(".metaproject", "jobs", name),
41276
+ job_path: path129.join(".metaproject", "jobs", name),
41181
41277
  documents_created: []
41182
41278
  },
41183
41279
  metrics: { steps: [] },
41184
- jobs_root: path128.join(".metaproject", "jobs"),
41280
+ jobs_root: path129.join(".metaproject", "jobs"),
41185
41281
  updated_at: createdAt
41186
41282
  };
41187
41283
  const first = firstOpenStep(state.plan.steps);
41188
41284
  if (first) {
41189
41285
  state.plan.current_step = first.id;
41190
41286
  }
41191
- await writeFileAtomic(path128.join(absolute, "journal.md"), renderJournal2(name, createdAt));
41287
+ await writeFileAtomic(path129.join(absolute, "journal.md"), renderJournal2(name, createdAt));
41192
41288
  await writeJob(input.cwd, name, state);
41193
- return { state, dir: path128.relative(input.cwd, absolute) };
41289
+ return { state, dir: path129.relative(input.cwd, absolute) };
41194
41290
  },
41195
41291
  async status({ cwd, name }) {
41196
41292
  assertJobName(name);
@@ -41202,7 +41298,7 @@ function createJobService(deps) {
41202
41298
  }
41203
41299
  return {
41204
41300
  state,
41205
- dir: path128.join(".metaproject", "jobs", name),
41301
+ dir: path129.join(".metaproject", "jobs", name),
41206
41302
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
41207
41303
  stepsTotal: state.plan.steps.length,
41208
41304
  nextStep: firstOpenStep(state.plan.steps),
@@ -41259,23 +41355,23 @@ function createJobService(deps) {
41259
41355
  if (!input.file) {
41260
41356
  throw new Error("Missing --file. Usage: keryx job document <name> --type <type> --file <path>");
41261
41357
  }
41262
- const source = path128.isAbsolute(input.file) ? input.file : path128.join(input.cwd, input.file);
41358
+ const source = path129.isAbsolute(input.file) ? input.file : path129.join(input.cwd, input.file);
41263
41359
  if (!await pathExists(source)) {
41264
41360
  throw new Error(`--file not found: ${input.file}. Write the document first, then record it.`);
41265
41361
  }
41266
41362
  let recorded;
41267
41363
  await mutate(input.cwd, input.name, async (state) => {
41268
41364
  const fileName = documentFileName(type, source);
41269
- const target = path128.join(jobDir(input.cwd, state.job_name), fileName);
41365
+ const target = path129.join(jobDir(input.cwd, state.job_name), fileName);
41270
41366
  await copyFile(source, target);
41271
41367
  state.documentation ??= {};
41272
- state.documentation.job_path ??= path128.join(".metaproject", "jobs", state.job_name);
41368
+ state.documentation.job_path ??= path129.join(".metaproject", "jobs", state.job_name);
41273
41369
  const created = state.documentation.documents_created ?? [];
41274
41370
  state.documentation.documents_created = created.includes(fileName) ? created : [...created, fileName];
41275
41371
  recorded = {
41276
41372
  state,
41277
41373
  document: fileName,
41278
- path: path128.join(".metaproject", "jobs", state.job_name, fileName)
41374
+ path: path129.join(".metaproject", "jobs", state.job_name, fileName)
41279
41375
  };
41280
41376
  return { state, event: "document", detail: `${type} -> ${fileName}` };
41281
41377
  });
@@ -41310,7 +41406,7 @@ function createJobService(deps) {
41310
41406
  name: state.job_name,
41311
41407
  phase: state.phase,
41312
41408
  intent: state.intent,
41313
- dir: path128.join(".metaproject", "jobs", name),
41409
+ dir: path129.join(".metaproject", "jobs", name),
41314
41410
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
41315
41411
  stepsTotal: state.plan.steps.length,
41316
41412
  nextStep: firstOpenStep(state.plan.steps)?.id ?? null
@@ -41331,12 +41427,12 @@ init_fs();
41331
41427
  init_preservation();
41332
41428
  import { randomUUID as randomUUID8 } from "crypto";
41333
41429
  import { lstat as lstat9, readdir as readdir26 } from "fs/promises";
41334
- import path142 from "path";
41430
+ import path143 from "path";
41335
41431
 
41336
41432
  // src/session/paths.ts
41337
41433
  import { existsSync as existsSync21 } from "fs";
41338
41434
  import { homedir as homedir2 } from "os";
41339
- import path130 from "path";
41435
+ import path131 from "path";
41340
41436
  function keryxDataDir(override) {
41341
41437
  if (override !== undefined && override.length > 0) {
41342
41438
  return override;
@@ -41348,22 +41444,22 @@ function keryxDataDir(override) {
41348
41444
  const home = homedir2();
41349
41445
  if (process.platform === "win32") {
41350
41446
  const appData = process.env.APPDATA;
41351
- const base = appData !== undefined && appData.length > 0 ? appData : path130.join(home, "AppData", "Roaming");
41352
- return path130.join(base, "keryx");
41447
+ const base = appData !== undefined && appData.length > 0 ? appData : path131.join(home, "AppData", "Roaming");
41448
+ return path131.join(base, "keryx");
41353
41449
  }
41354
41450
  const xdg = process.env.XDG_DATA_HOME;
41355
- const base = xdg !== undefined && xdg.length > 0 ? xdg : path130.join(home, ".local", "share");
41356
- return path130.join(base, "keryx");
41451
+ const base = xdg !== undefined && xdg.length > 0 ? xdg : path131.join(home, ".local", "share");
41452
+ return path131.join(base, "keryx");
41357
41453
  }
41358
41454
  function resolveProjectRoot2(cwd) {
41359
- const abs = path130.resolve(cwd);
41455
+ const abs = path131.resolve(cwd);
41360
41456
  let dir = abs;
41361
41457
  for (;; ) {
41362
- const gitPath = path130.join(dir, ".git");
41458
+ const gitPath = path131.join(dir, ".git");
41363
41459
  if (existsSync21(gitPath)) {
41364
41460
  return dir;
41365
41461
  }
41366
- const parent = path130.dirname(dir);
41462
+ const parent = path131.dirname(dir);
41367
41463
  if (parent === dir) {
41368
41464
  break;
41369
41465
  }
@@ -41372,12 +41468,12 @@ function resolveProjectRoot2(cwd) {
41372
41468
  return abs;
41373
41469
  }
41374
41470
  function projectKeyFromPath(projectPath) {
41375
- const abs = path130.resolve(projectPath);
41471
+ const abs = path131.resolve(projectPath);
41376
41472
  const encoded = encodeURIComponent(abs);
41377
41473
  if (encoded.length <= 200) {
41378
41474
  return encoded;
41379
41475
  }
41380
- const base = path130.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
41476
+ const base = path131.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
41381
41477
  let h = 0;
41382
41478
  for (let i = 0;i < abs.length; i++) {
41383
41479
  h = Math.imul(31, h) + abs.charCodeAt(i) | 0;
@@ -41387,22 +41483,22 @@ function projectKeyFromPath(projectPath) {
41387
41483
  }
41388
41484
  function projectSessionsDir(projectPath, dataDir) {
41389
41485
  const key = projectKeyFromPath(resolveProjectRoot2(projectPath));
41390
- return path130.join(keryxDataDir(dataDir), "sessions", key);
41486
+ return path131.join(keryxDataDir(dataDir), "sessions", key);
41391
41487
  }
41392
41488
  function sessionDir(projectPath, sessionId, dataDir) {
41393
- return path130.join(projectSessionsDir(projectPath, dataDir), sessionId);
41489
+ return path131.join(projectSessionsDir(projectPath, dataDir), sessionId);
41394
41490
  }
41395
41491
 
41396
41492
  // src/sac/proposal-lifecycle.ts
41397
41493
  init_fs();
41398
41494
  import { createHash as createHash32, randomUUID as randomUUID7 } from "crypto";
41399
41495
  import { appendFile as appendFile7, mkdir as mkdir35, readdir as readdir25, readFile as readFile73 } from "fs/promises";
41400
- import path141 from "path";
41496
+ import path142 from "path";
41401
41497
 
41402
41498
  // src/sac/index.ts
41403
41499
  import { access as access3, readFile as readFile64, realpath as realpath14 } from "fs/promises";
41404
41500
  import { createHash as createHash24 } from "crypto";
41405
- import path131 from "path";
41501
+ import path132 from "path";
41406
41502
  import { fileURLToPath as fileURLToPath3 } from "url";
41407
41503
 
41408
41504
  // src/sac/workspace-reference.ts
@@ -41462,21 +41558,21 @@ var normativeSchemaFiles = {
41462
41558
  "review-decision": "review-decision.schema.json"
41463
41559
  };
41464
41560
  var normativeSchemas = new Map;
41465
- var NORMATIVE_SCHEMA_DIR = path131.join("docs", "requirements", "shared-agent-context", "schemas");
41561
+ var NORMATIVE_SCHEMA_DIR = path132.join("docs", "requirements", "shared-agent-context", "schemas");
41466
41562
  async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath3(new URL(".", import.meta.url)), process.cwd()]) {
41467
41563
  const seen = new Set;
41468
41564
  for (const start of searchFrom) {
41469
- let dir = path131.resolve(start);
41565
+ let dir = path132.resolve(start);
41470
41566
  for (let i = 0;i < 10; i++) {
41471
41567
  if (seen.has(dir))
41472
41568
  break;
41473
41569
  seen.add(dir);
41474
- const candidate = path131.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
41570
+ const candidate = path132.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
41475
41571
  try {
41476
41572
  await access3(candidate);
41477
41573
  return candidate;
41478
41574
  } catch {}
41479
- const parent = path131.dirname(dir);
41575
+ const parent = path132.dirname(dir);
41480
41576
  if (parent === dir)
41481
41577
  break;
41482
41578
  dir = parent;
@@ -42145,12 +42241,12 @@ class SacReferenceError extends Error {
42145
42241
  code = "unsafe_workspace_reference";
42146
42242
  }
42147
42243
  async function resolveWorkspaceReference(input) {
42148
- if (!workspacePathPattern.test(input.uri) || path131.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
42244
+ if (!workspacePathPattern.test(input.uri) || path132.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
42149
42245
  throw new SacReferenceError("unsafe workspace reference");
42150
- const lexicalRoot = path131.resolve(input.workspaceRoot);
42246
+ const lexicalRoot = path132.resolve(input.workspaceRoot);
42151
42247
  const root = await realpath14(lexicalRoot);
42152
- const candidate = path131.resolve(lexicalRoot, input.uri.slice(2));
42153
- if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path131.sep}`))
42248
+ const candidate = path132.resolve(lexicalRoot, input.uri.slice(2));
42249
+ if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path132.sep}`))
42154
42250
  throw new SacReferenceError("workspace reference escapes root");
42155
42251
  let resolved;
42156
42252
  try {
@@ -42158,7 +42254,7 @@ async function resolveWorkspaceReference(input) {
42158
42254
  } catch {
42159
42255
  throw new SacReferenceError("workspace reference is not resolvable");
42160
42256
  }
42161
- if (resolved !== root && !resolved.startsWith(`${root}${path131.sep}`))
42257
+ if (resolved !== root && !resolved.startsWith(`${root}${path132.sep}`))
42162
42258
  throw new SacReferenceError("workspace reference escapes root after realpath");
42163
42259
  return candidate;
42164
42260
  }
@@ -42214,16 +42310,16 @@ async function evaluateStrictSacGuard(input) {
42214
42310
  init_fs();
42215
42311
  import { mkdir as mkdir32, readdir as readdir22, readFile as readFile65 } from "fs/promises";
42216
42312
  import { createHash as createHash25, randomUUID as randomUUID4 } from "crypto";
42217
- import path133 from "path";
42313
+ import path134 from "path";
42218
42314
 
42219
42315
  // src/sac/secure-resource-read.ts
42220
42316
  init_contained_read();
42221
42317
  init_descriptor_read();
42222
- import path132 from "path";
42318
+ import path133 from "path";
42223
42319
  function readWorkspaceFileNoFollow(workspaceRoot, absolutePath) {
42224
- const relativePath = path132.relative(workspaceRoot, absolutePath);
42225
- const components = relativePath.split(path132.sep);
42226
- if (!relativePath || path132.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
42320
+ const relativePath = path133.relative(workspaceRoot, absolutePath);
42321
+ const components = relativePath.split(path133.sep);
42322
+ if (!relativePath || path133.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
42227
42323
  throw new Error("safe source path is not workspace-relative");
42228
42324
  }
42229
42325
  return readDescriptorChain(workspaceRoot, absolutePath, {
@@ -42250,8 +42346,8 @@ class WorkspaceService {
42250
42346
  now;
42251
42347
  constructor(options) {
42252
42348
  this.options = options;
42253
- this.root = path133.resolve(options.workspaceRoot);
42254
- this.storageRoot = path133.resolve(options.storageRoot ?? path133.join(this.root, ".metaproject", "workspaces"));
42349
+ this.root = path134.resolve(options.workspaceRoot);
42350
+ this.storageRoot = path134.resolve(options.storageRoot ?? path134.join(this.root, ".metaproject", "workspaces"));
42255
42351
  this.now = options.now ?? (() => new Date);
42256
42352
  }
42257
42353
  async create(input) {
@@ -42577,13 +42673,13 @@ class WorkspaceService {
42577
42673
  return parsed;
42578
42674
  }
42579
42675
  workspaceDir(id) {
42580
- return path133.join(this.storageRoot, id);
42676
+ return path134.join(this.storageRoot, id);
42581
42677
  }
42582
42678
  manifestPath(id) {
42583
- return path133.join(this.workspaceDir(id), "workspace.json");
42679
+ return path134.join(this.workspaceDir(id), "workspace.json");
42584
42680
  }
42585
42681
  lockPath(id) {
42586
- return path133.join(this.storageRoot, `.${id}.lock`);
42682
+ return path134.join(this.storageRoot, `.${id}.lock`);
42587
42683
  }
42588
42684
  timestamp() {
42589
42685
  return this.now().toISOString();
@@ -42699,7 +42795,7 @@ function bindingHash(owner, intent) {
42699
42795
  // src/sac/session-wrap-up.ts
42700
42796
  import { createHash as createHash28 } from "crypto";
42701
42797
  import { mkdir as mkdir34, writeFile as writeFile23 } from "fs/promises";
42702
- import path136 from "path";
42798
+ import path137 from "path";
42703
42799
 
42704
42800
  // src/session/store.ts
42705
42801
  init_preservation();
@@ -42712,7 +42808,7 @@ import {
42712
42808
  renameSync as renameSync5,
42713
42809
  writeFileSync as writeFileSync4
42714
42810
  } from "fs";
42715
- import path135 from "path";
42811
+ import path136 from "path";
42716
42812
  init_slate();
42717
42813
  init_redact();
42718
42814
  var SESSION_SCHEMA_VERSION = 1;
@@ -42805,7 +42901,7 @@ function parseRemote(value) {
42805
42901
  function readSummaryFile(file) {
42806
42902
  let pending;
42807
42903
  try {
42808
- pending = readPendingHistory(path135.dirname(file));
42904
+ pending = readPendingHistory(path136.dirname(file));
42809
42905
  } catch {
42810
42906
  pending = undefined;
42811
42907
  }
@@ -42857,11 +42953,11 @@ class TranscriptUnreadableError extends Error {
42857
42953
  }
42858
42954
  }
42859
42955
  function readJsonl2(file) {
42860
- const pending = readPendingHistory(path135.dirname(file));
42956
+ const pending = readPendingHistory(path136.dirname(file));
42861
42957
  if (pending === undefined && !existsSync22(file)) {
42862
42958
  return [];
42863
42959
  }
42864
- const read = pending !== undefined ? { ok: true, text: pending.files[path135.basename(file)] } : readTranscriptFile(file);
42960
+ const read = pending !== undefined ? { ok: true, text: pending.files[path136.basename(file)] } : readTranscriptFile(file);
42865
42961
  if (!read.ok) {
42866
42962
  throw new TranscriptUnreadableError(file, read.reason);
42867
42963
  }
@@ -42912,11 +43008,11 @@ function listSessions(cwd, dataDir) {
42912
43008
  if (name.startsWith(".")) {
42913
43009
  continue;
42914
43010
  }
42915
- const summary = readSummaryFile(path135.join(root, name, "summary.json"));
43011
+ const summary = readSummaryFile(path136.join(root, name, "summary.json"));
42916
43012
  if (summary === undefined) {
42917
43013
  continue;
42918
43014
  }
42919
- if (path135.resolve(summary.projectPath) !== path135.resolve(projectPath)) {
43015
+ if (path136.resolve(summary.projectPath) !== path136.resolve(projectPath)) {
42920
43016
  continue;
42921
43017
  }
42922
43018
  out.push(summary);
@@ -42949,15 +43045,15 @@ async function readSessionSlate(cwd, sessionId, dataDir) {
42949
43045
  }
42950
43046
  function loadContext(cwd, sessionId, dataDir) {
42951
43047
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
42952
- const contextPath = path135.join(dir, "context.jsonl");
43048
+ const contextPath = path136.join(dir, "context.jsonl");
42953
43049
  if (readPendingHistory(dir) !== undefined || existsSync22(contextPath)) {
42954
43050
  return readJsonl2(contextPath);
42955
43051
  }
42956
- return readJsonl2(path135.join(dir, "transcript.jsonl"));
43052
+ return readJsonl2(path136.join(dir, "transcript.jsonl"));
42957
43053
  }
42958
43054
  function loadArchive(cwd, sessionId, dataDir, onDegraded) {
42959
43055
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
42960
- const archivePath = path135.join(dir, "archive.jsonl");
43056
+ const archivePath = path136.join(dir, "archive.jsonl");
42961
43057
  if (readPendingHistory(dir) !== undefined || existsSync22(archivePath)) {
42962
43058
  try {
42963
43059
  const archive = readJsonl2(archivePath);
@@ -43032,7 +43128,7 @@ function sessionEvidenceRef(workspaceId, sessionId) {
43032
43128
  }
43033
43129
  async function resolveSessionWrapUp(input) {
43034
43130
  const now = input.now ?? (() => new Date);
43035
- const sessionId = path136.posix.basename(input.sourceRef, ".md");
43131
+ const sessionId = path137.posix.basename(input.sourceRef, ".md");
43036
43132
  const summary = findSession(input.cwd, sessionId);
43037
43133
  if (summary === undefined || input.sourceRef !== sessionEvidenceRef(input.workspaceId, summary.id)) {
43038
43134
  throw new SessionWrapUpError("session_not_found", `no session matching "${input.sourceRef}" in this project \u2014 use \`keryx sessions list\``);
@@ -43049,7 +43145,7 @@ async function resolveSessionWrapUp(input) {
43049
43145
  throw new SessionWrapUpError("session_unreadable", `session "${summary.id}" could not be read: ${cause.message}`);
43050
43146
  }
43051
43147
  const relPath = sessionEvidenceRef(input.workspaceId, summary.id).slice(2);
43052
- const evidenceDir = path136.dirname(relPath);
43148
+ const evidenceDir = path137.dirname(relPath);
43053
43149
  const slate = await readSessionSlate(input.cwd, summary.id);
43054
43150
  const diff = await gitDiff(input.cwd);
43055
43151
  const diffBody = diff.kind === "measured" ? diff.text : unmeasurableDiffBody(diff.detail);
@@ -43071,23 +43167,23 @@ async function resolveSessionWrapUp(input) {
43071
43167
  ""
43072
43168
  ].join(`
43073
43169
  `);
43074
- const wrapUpRelPath = path136.join(evidenceDir, `${summary.id}.wrap-up.md`);
43075
- const diffRelPath = path136.join(evidenceDir, `${summary.id}.diff.txt`);
43076
- const noticeRelPath = path136.join(evidenceDir, `${summary.id}.redaction.md`);
43170
+ const wrapUpRelPath = path137.join(evidenceDir, `${summary.id}.wrap-up.md`);
43171
+ const diffRelPath = path137.join(evidenceDir, `${summary.id}.diff.txt`);
43172
+ const noticeRelPath = path137.join(evidenceDir, `${summary.id}.redaction.md`);
43077
43173
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
43078
- { name: path136.basename(relPath), content: markdown, path: relPath, source: "generated" },
43079
- { name: path136.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
43080
- { name: path136.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
43174
+ { name: path137.basename(relPath), content: markdown, path: relPath, source: "generated" },
43175
+ { name: path137.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
43176
+ { name: path137.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
43081
43177
  ]);
43082
43178
  if (!floor.ok)
43083
43179
  throw new SessionWrapUpError("security_denied", floor.reason);
43084
43180
  const [safeSession, safeWrapUp, safeDiff] = floor.bodies;
43085
- await mkdir34(path136.join(input.cwd, evidenceDir), { recursive: true });
43086
- await writeFile23(path136.join(input.cwd, relPath), safeSession.content, "utf8");
43087
- await writeFile23(path136.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
43088
- await writeFile23(path136.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
43181
+ await mkdir34(path137.join(input.cwd, evidenceDir), { recursive: true });
43182
+ await writeFile23(path137.join(input.cwd, relPath), safeSession.content, "utf8");
43183
+ await writeFile23(path137.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
43184
+ await writeFile23(path137.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
43089
43185
  if (floor.notice !== undefined)
43090
- await writeFile23(path136.join(input.cwd, noticeRelPath), floor.notice, "utf8");
43186
+ await writeFile23(path137.join(input.cwd, noticeRelPath), floor.notice, "utf8");
43091
43187
  const observedAt = now().toISOString();
43092
43188
  const evidence = [
43093
43189
  { kind: "wrap-up", uri: `./${wrapUpRelPath}`, revision: createHash28("sha256").update(safeWrapUp.content).digest("hex"), observedAt },
@@ -43110,13 +43206,13 @@ async function resolveSessionWrapUp(input) {
43110
43206
  init_fs();
43111
43207
  import { createHash as createHash29, randomBytes as randomBytes6 } from "crypto";
43112
43208
  import { readFile as readFile67 } from "fs/promises";
43113
- import path137 from "path";
43209
+ import path138 from "path";
43114
43210
  var CONFIRM_TOKEN_TTL_MS = 2 * 60000;
43115
43211
  function confirmTokenPath2(cwd, workspaceId, proposalId) {
43116
- return path137.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
43212
+ return path138.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
43117
43213
  }
43118
43214
  function confirmReceiptPath(cwd, workspaceId, proposalId, idempotencyKey) {
43119
- return path137.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2563(idempotencyKey)}.confirm-receipt.json`);
43215
+ return path138.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2563(idempotencyKey)}.confirm-receipt.json`);
43120
43216
  }
43121
43217
  function sha2563(text) {
43122
43218
  return createHash29("sha256").update(text).digest("hex");
@@ -43157,21 +43253,21 @@ init_store();
43157
43253
  init_config2();
43158
43254
  import { readFile as readFile69, readdir as readdir24 } from "fs/promises";
43159
43255
  import { randomUUID as randomUUID6 } from "crypto";
43160
- import path139 from "path";
43256
+ import path140 from "path";
43161
43257
 
43162
43258
  // src/sac/proposal-evidence.ts
43163
43259
  init_fs();
43164
43260
  import { createHash as createHash30 } from "crypto";
43165
43261
  import { readFile as readFile68, rm as rm7 } from "fs/promises";
43166
- import path138 from "path";
43262
+ import path139 from "path";
43167
43263
  function proposalPath(cwd, workspaceId, proposalId) {
43168
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
43264
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
43169
43265
  }
43170
43266
  function ownerReceiptPath(cwd, owner, workspaceId, idempotencyKey) {
43171
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
43267
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
43172
43268
  }
43173
43269
  function proposalNotePath(cwd, workspaceId, proposalId) {
43174
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
43270
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
43175
43271
  }
43176
43272
  async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
43177
43273
  let proposal;
@@ -43185,7 +43281,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
43185
43281
  return { ok: false, code: "no_evidence_to_write" };
43186
43282
  let content;
43187
43283
  try {
43188
- content = await readFile68(path138.join(cwd, evidence.uri), "utf8");
43284
+ content = await readFile68(path139.join(cwd, evidence.uri), "utf8");
43189
43285
  } catch {
43190
43286
  return { ok: false, code: "evidence_file_unreadable" };
43191
43287
  }
@@ -43215,22 +43311,22 @@ function targetRelPath(targetRef) {
43215
43311
  return targetRef.replace(/^\.\//, "");
43216
43312
  }
43217
43313
  function targetAbsolutePath(cwd, targetRef) {
43218
- return path138.join(cwd, ".metaproject", targetRelPath(targetRef));
43314
+ return path139.join(cwd, ".metaproject", targetRelPath(targetRef));
43219
43315
  }
43220
43316
  function targetKey(targetRef) {
43221
43317
  return digestOf2(targetRelPath(targetRef)).slice(0, 32);
43222
43318
  }
43223
43319
  function ownerTargetVersionPath(cwd, owner, workspaceId, targetRef) {
43224
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
43320
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
43225
43321
  }
43226
43322
  function ownerTargetLockPath(cwd, owner, targetRef) {
43227
- return path138.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
43323
+ return path139.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
43228
43324
  }
43229
43325
  function ownerStagingDir(cwd, owner, workspaceId, idempotencyKey) {
43230
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
43326
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
43231
43327
  }
43232
43328
  function ownerConflictDir(cwd, owner, workspaceId, idempotencyKey) {
43233
- return path138.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
43329
+ return path139.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
43234
43330
  }
43235
43331
  async function readJson4(file) {
43236
43332
  try {
@@ -43301,7 +43397,7 @@ async function applyGuardedTargetWrite(input) {
43301
43397
  staged: input.staged,
43302
43398
  stagedAt: receipt.completedAt
43303
43399
  };
43304
- await writeFileAtomic(path138.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
43400
+ await writeFileAtomic(path139.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
43305
43401
  `);
43306
43402
  const applied = await input.apply(input.staged);
43307
43403
  if (!applied.ok) {
@@ -43327,15 +43423,15 @@ async function recoverStagedOwnerWrite(input) {
43327
43423
  });
43328
43424
  }
43329
43425
  async function readStagedOwnerWrite(cwd, owner, workspaceId, idempotencyKey) {
43330
- return readJson4(path138.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
43426
+ return readJson4(path139.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
43331
43427
  }
43332
43428
  async function recordConflict(input) {
43333
43429
  const base = { targetRef: input.targetRef, expectedVersion: input.expectedVersion, currentVersion: input.currentVersion };
43334
43430
  if (input.proposedContent === undefined)
43335
43431
  return base;
43336
43432
  const dir = ownerConflictDir(input.cwd, input.owner, input.intent.workspaceId, input.intent.idempotencyKey);
43337
- await writeFileAtomic(path138.join(dir, "proposed"), input.proposedContent);
43338
- const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path138.basename(dir)}/proposed`;
43433
+ await writeFileAtomic(path139.join(dir, "proposed"), input.proposedContent);
43434
+ const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path139.basename(dir)}/proposed`;
43339
43435
  return { ...base, diffRef };
43340
43436
  }
43341
43437
 
@@ -43385,7 +43481,7 @@ async function resolveWorkspaceModule(cwd, workspaceId) {
43385
43481
  }
43386
43482
  }
43387
43483
  async function collectWikiDecisionEntries(cwd) {
43388
- const dir = path139.join(cwd, ".metaproject", "wiki", "decisions");
43484
+ const dir = path140.join(cwd, ".metaproject", "wiki", "decisions");
43389
43485
  let files;
43390
43486
  try {
43391
43487
  files = (await readdir24(dir)).filter((name) => name.endsWith(".md"));
@@ -43394,12 +43490,12 @@ async function collectWikiDecisionEntries(cwd) {
43394
43490
  }
43395
43491
  const entries = [];
43396
43492
  for (const file of files) {
43397
- const absolutePath = path139.join(dir, file);
43493
+ const absolutePath = path140.join(dir, file);
43398
43494
  try {
43399
43495
  const content = await readFile69(absolutePath, "utf8");
43400
43496
  entries.push({
43401
43497
  absolutePath,
43402
- relativePath: path139.posix.join("decisions", file),
43498
+ relativePath: path140.posix.join("decisions", file),
43403
43499
  type: extractHeaderField(content, "Type") ?? "decision",
43404
43500
  title: extractTitle(content),
43405
43501
  version: extractHeaderField(content, "Version") ?? null,
@@ -43621,7 +43717,7 @@ function createRealMemoryOwnerWriter(cwd, opts) {
43621
43717
  init_service4();
43622
43718
  init_guard();
43623
43719
  import { readFile as readFile71 } from "fs/promises";
43624
- import path140 from "path";
43720
+ import path141 from "path";
43625
43721
  function renderWrapUpDecisionPage(input) {
43626
43722
  const note = input.note?.trim();
43627
43723
  return `# ${input.title}
@@ -43662,7 +43758,7 @@ export is the source of truth for what actually happened.
43662
43758
  `;
43663
43759
  }
43664
43760
  function wikiPageRelativePath(proposalId) {
43665
- return path140.posix.join("decisions", `sac-${proposalId}.md`);
43761
+ return path141.posix.join("decisions", `sac-${proposalId}.md`);
43666
43762
  }
43667
43763
  function createRealWikiOwnerWriter(cwd, opts) {
43668
43764
  const now = opts?.now ?? (() => new Date);
@@ -43670,7 +43766,7 @@ function createRealWikiOwnerWriter(cwd, opts) {
43670
43766
  const relativePath = staged.relativePath;
43671
43767
  const content = staged.content;
43672
43768
  const history = await openWikiWriteContext(cwd, "sac proposal accept");
43673
- await writeWikiPage(history, path140.join(cwd, ".metaproject", "wiki", relativePath), content);
43769
+ await writeWikiPage(history, path141.join(cwd, ".metaproject", "wiki", relativePath), content);
43674
43770
  return { ok: true };
43675
43771
  };
43676
43772
  return {
@@ -43819,7 +43915,7 @@ class ProposalLifecycleService {
43819
43915
  now;
43820
43916
  constructor(options) {
43821
43917
  this.options = options;
43822
- this.root = path141.resolve(options.workspaceRoot);
43918
+ this.root = path142.resolve(options.workspaceRoot);
43823
43919
  this.now = options.now ?? (() => new Date);
43824
43920
  }
43825
43921
  async create(input) {
@@ -43839,7 +43935,7 @@ class ProposalLifecycleService {
43839
43935
  if (manifest.status === "archived")
43840
43936
  throw new ProposalLifecycleError("guard_denied", "workspace is archived");
43841
43937
  const file = this.proposalPath(workspaceId, proposal.id);
43842
- await mkdir35(path141.dirname(file), { recursive: true, mode: 448 });
43938
+ await mkdir35(path142.dirname(file), { recursive: true, mode: 448 });
43843
43939
  return withFileLock(`${file}.lock`, async () => {
43844
43940
  const consume = this.options.wrapUpAuthority.consume(input.wrapUp, { actor, workspaceId });
43845
43941
  if (consume !== "ok")
@@ -43867,7 +43963,7 @@ class ProposalLifecycleService {
43867
43963
  return this.options.workspaces.withAuthorizedActor({ actorContext: actor, workspaceId: input.workspaceId, action: "review", execute: async (manifest) => {
43868
43964
  const proposal = await this.loadProposal(input.workspaceId, input.proposalId);
43869
43965
  const ledger = this.ledgerPath(input.workspaceId);
43870
- await mkdir35(path141.dirname(ledger), { recursive: true, mode: 448 });
43966
+ await mkdir35(path142.dirname(ledger), { recursive: true, mode: 448 });
43871
43967
  return withFileLock(`${ledger}.lock`, async () => {
43872
43968
  const records = (await this.records(ledger)).filter((record) => record.proposalId === proposal.id);
43873
43969
  const events = records.filter((record) => record.recordType === "proposal-transition");
@@ -43909,7 +44005,7 @@ class ProposalLifecycleService {
43909
44005
  } });
43910
44006
  }
43911
44007
  async listProposedProposals(workspaceId) {
43912
- const proposalsDir = path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
44008
+ const proposalsDir = path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
43913
44009
  let entries;
43914
44010
  try {
43915
44011
  entries = (await readdir25(proposalsDir)).filter((name) => name.endsWith(".json"));
@@ -43921,7 +44017,7 @@ class ProposalLifecycleService {
43921
44017
  const proposals = [];
43922
44018
  for (const entry of entries) {
43923
44019
  try {
43924
- const parsed = JSON.parse(await readFile73(path141.join(proposalsDir, entry), "utf8"));
44020
+ const parsed = JSON.parse(await readFile73(path142.join(proposalsDir, entry), "utf8"));
43925
44021
  if (parsed.recordType === "proposal-created")
43926
44022
  proposals.push(parsed);
43927
44023
  } catch {}
@@ -44187,31 +44283,31 @@ class ProposalLifecycleService {
44187
44283
  }
44188
44284
  }
44189
44285
  proposalPath(workspaceId, proposalId) {
44190
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
44286
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
44191
44287
  }
44192
44288
  decisionRef(proposalId, key) {
44193
44289
  return `./proposals/${proposalId}.${hash2(key)}.decision.json`;
44194
44290
  }
44195
44291
  decisionPath(workspaceId, proposalId, key) {
44196
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.decision.json`);
44292
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.decision.json`);
44197
44293
  }
44198
44294
  approvalRef(proposalId, key) {
44199
44295
  return `./proposals/${proposalId}.${hash2(key)}.approval.json`;
44200
44296
  }
44201
44297
  approvalPath(workspaceId, proposalId, key) {
44202
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.approval.json`);
44298
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.approval.json`);
44203
44299
  }
44204
44300
  writeResultPath(workspaceId, proposalId, key) {
44205
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.write-result.json`);
44301
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.write-result.json`);
44206
44302
  }
44207
44303
  intentRef(proposalId, key) {
44208
44304
  return `./proposals/${proposalId}.${hash2(key)}.write-intent.json`;
44209
44305
  }
44210
44306
  intentPath(workspaceId, proposalId, key) {
44211
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.write-intent.json`);
44307
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.write-intent.json`);
44212
44308
  }
44213
44309
  attemptPath(workspaceId, proposalId, key) {
44214
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.owner-write-attempt.json`);
44310
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash2(key)}.owner-write-attempt.json`);
44215
44311
  }
44216
44312
  async loadWriteResult(workspaceId, proposalId, key) {
44217
44313
  try {
@@ -44238,7 +44334,7 @@ class ProposalLifecycleService {
44238
44334
  }
44239
44335
  }
44240
44336
  ledgerPath(workspaceId) {
44241
- return path141.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
44337
+ return path142.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
44242
44338
  }
44243
44339
  timestamp() {
44244
44340
  return this.now().toISOString();
@@ -44357,11 +44453,11 @@ async function replayPreservation(input) {
44357
44453
  if (typeof slate.workspaceId !== "string" || !/^[a-z][a-z0-9-]{2,63}$/.test(slate.workspaceId))
44358
44454
  throw new Error("invalid workspace identity");
44359
44455
  const workspaceId = slate.workspaceId;
44360
- const outbox = path142.join(input.dir, "preservation", "outbox");
44361
- const receipt = await readReplayJson(path142.join(outbox, `${input.snapshot}.json`));
44456
+ const outbox = path143.join(input.dir, "preservation", "outbox");
44457
+ const receipt = await readReplayJson(path143.join(outbox, `${input.snapshot}.json`));
44362
44458
  if (receipt.version !== 1 || receipt.snapshot !== input.snapshot || receipt.state !== "pending-review")
44363
44459
  throw new Error("invalid outbox receipt");
44364
- return withFileLock(path142.join(outbox, `${input.snapshot}.delivery.lock`), async () => {
44460
+ return withFileLock(path143.join(outbox, `${input.snapshot}.delivery.lock`), async () => {
44365
44461
  input.signal?.throwIfAborted();
44366
44462
  const { service, wrapUpAuthority, authorizationServer } = createHarnessProposalLifecycleService(input.cwd, {
44367
44463
  workspaceId,
@@ -44388,12 +44484,12 @@ async function replayPreservation(input) {
44388
44484
  } catch (error) {
44389
44485
  if (!(error instanceof ProposalLifecycleError) || error.code !== "conflict")
44390
44486
  throw error;
44391
- const existing = await readReplayJson(path142.join(input.cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${id}.json`));
44487
+ const existing = await readReplayJson(path143.join(input.cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${id}.json`));
44392
44488
  const refs = (evidence) => evidence.map((e) => [e.uri, e.revision]);
44393
44489
  if (existing.workspaceId !== workspaceId || existing.author !== actor.subject || existing.kind !== "follow-up" || existing.proposalRevision !== input.snapshot || existing.wrapUp?.sourceRef !== sourceRef || existing.wrapUp?.sourceRevision !== wrapUp.sourceRevision || JSON.stringify(refs(existing.evidence)) !== JSON.stringify(refs(wrapUp.evidence)))
44394
44490
  throw new Error("delivery conflict mismatch", { cause: error });
44395
44491
  }
44396
- const delivered = path142.join(outbox, `${input.snapshot}.delivered`);
44492
+ const delivered = path143.join(outbox, `${input.snapshot}.delivered`);
44397
44493
  try {
44398
44494
  const marker = await readReplayJson(delivered);
44399
44495
  if (marker.version !== 1 || marker.workspaceId !== workspaceId || marker.proposalId !== id || marker.snapshot !== input.snapshot) {
@@ -44406,7 +44502,7 @@ async function replayPreservation(input) {
44406
44502
  }
44407
44503
  input.afterCreate?.();
44408
44504
  input.signal?.throwIfAborted();
44409
- writePreservationFile(path142.join(outbox, `${input.snapshot}.delivered`), JSON.stringify({ version: 1, workspaceId, proposalId: id, snapshot: input.snapshot }));
44505
+ writePreservationFile(path143.join(outbox, `${input.snapshot}.delivered`), JSON.stringify({ version: 1, workspaceId, proposalId: id, snapshot: input.snapshot }));
44410
44506
  return "proposed";
44411
44507
  }, input.signal ? { signal: input.signal } : {});
44412
44508
  }
@@ -44429,14 +44525,14 @@ async function scanPreservationOutbox(input) {
44429
44525
  const result = { proposed: 0, deferred: 0, unbound: 0 };
44430
44526
  let entries;
44431
44527
  try {
44432
- entries = await readdir26(path142.join(input.dir, "preservation", "outbox"));
44528
+ entries = await readdir26(path143.join(input.dir, "preservation", "outbox"));
44433
44529
  } catch (error) {
44434
44530
  if (error.code === "ENOENT")
44435
44531
  return result;
44436
44532
  throw error;
44437
44533
  }
44438
44534
  let attempted = 0;
44439
- const cursorFile = path142.join(input.dir, "preservation", "outbox", "SCAN_CURSOR");
44535
+ const cursorFile = path143.join(input.dir, "preservation", "outbox", "SCAN_CURSOR");
44440
44536
  for (const entry of resumeScan(entries.filter((name) => /^[a-f0-9]{64}\.json$/.test(name)), cursorFile)) {
44441
44537
  if (input.signal?.aborted || Date.now() >= (input.deadline ?? Infinity) || attempted >= (input.maxItems ?? 8))
44442
44538
  break;
@@ -44461,11 +44557,11 @@ async function replayProjectPreservationOutboxes(input) {
44461
44557
  return boundedReplay(input, scanProjectPreservationOutboxes);
44462
44558
  }
44463
44559
  async function retryProjectPreservation(cwd) {
44464
- return replayProjectPreservationOutboxes({ cwd, dir: path142.join(projectSessionsDir(cwd), ".explicit-retry") });
44560
+ return replayProjectPreservationOutboxes({ cwd, dir: path143.join(projectSessionsDir(cwd), ".explicit-retry") });
44465
44561
  }
44466
44562
  async function scanProjectPreservationOutboxes(input) {
44467
44563
  const result = { proposed: 0, deferred: 0, unbound: 0 };
44468
- const root = path142.dirname(input.dir);
44564
+ const root = path143.dirname(input.dir);
44469
44565
  let entries;
44470
44566
  try {
44471
44567
  entries = await readdir26(root, { withFileTypes: true });
@@ -44476,7 +44572,7 @@ async function scanProjectPreservationOutboxes(input) {
44476
44572
  }
44477
44573
  const deadline = input.deadline ?? Date.now() + 2000;
44478
44574
  let scanned = 0;
44479
- const cursorFile = path142.join(root, ".preservation-replay-cursor");
44575
+ const cursorFile = path143.join(root, ".preservation-replay-cursor");
44480
44576
  const candidates = entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
44481
44577
  for (const name of resumeScan(candidates, cursorFile)) {
44482
44578
  if (input.signal?.aborted || Date.now() >= deadline || scanned >= 32)
@@ -44485,7 +44581,7 @@ async function scanProjectPreservationOutboxes(input) {
44485
44581
  recordScanCursor(cursorFile, name);
44486
44582
  scanned++;
44487
44583
  try {
44488
- const replay = await replayPreservationOutbox({ ...input, deadline, maxItems: 1, dir: path142.join(root, name) });
44584
+ const replay = await replayPreservationOutbox({ ...input, deadline, maxItems: 1, dir: path143.join(root, name) });
44489
44585
  result.proposed += replay.proposed;
44490
44586
  result.deferred += replay.deferred;
44491
44587
  result.unbound += replay.unbound;
@@ -44524,7 +44620,7 @@ async function boundedReplay(input, scan) {
44524
44620
  import { createHash as createHash35, randomUUID as randomUUID9 } from "crypto";
44525
44621
  init_assembly();
44526
44622
  import { appendFile as appendFile8, mkdir as mkdir36, open as open4, readFile as readFile74, rename as rename7, rm as rm8, stat as stat18, writeFile as writeFile24 } from "fs/promises";
44527
- import path143 from "path";
44623
+ import path144 from "path";
44528
44624
  init_fs();
44529
44625
 
44530
44626
  // src/sac/policy-experiment.ts
@@ -45267,7 +45363,7 @@ function hasReportIntegrity(report) {
45267
45363
  return reportHashPattern.test(reportDigest) && sha2566(body) === reportDigest;
45268
45364
  }
45269
45365
  async function resolvePolicySelection(workspaceRoot, canonicalFallback) {
45270
- const configPath = path143.join(workspaceRoot, ...policyExperimentConfigPath);
45366
+ const configPath = path144.join(workspaceRoot, ...policyExperimentConfigPath);
45271
45367
  let configJson;
45272
45368
  try {
45273
45369
  const raw = await readFile74(configPath, "utf8").catch((error) => {
@@ -45465,9 +45561,9 @@ class FwkReadService {
45465
45561
  const recordedAt = nowIso2(now);
45466
45562
  const id = `receipt-${randomUUID9().replace(/-/g, "").slice(0, 16)}`;
45467
45563
  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"}` } : {} };
45468
- const ledger = path143.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
45469
- const checkpointPath = path143.join(path143.dirname(ledger), "access-receipts.checkpoint.json");
45470
- await mkdir36(path143.dirname(ledger), { recursive: true, mode: 448 });
45564
+ const ledger = path144.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
45565
+ const checkpointPath = path144.join(path144.dirname(ledger), "access-receipts.checkpoint.json");
45566
+ await mkdir36(path144.dirname(ledger), { recursive: true, mode: 448 });
45471
45567
  return withFileLock(`${ledger}.lock`, async () => {
45472
45568
  const state = await resolveLedgerState(ledger, checkpointPath, this.options.verifyReceiptLedger ?? verifyAccessReceiptLedger);
45473
45569
  const receipt = sealAccessReceipt(base, state.headHash);
@@ -45570,7 +45666,7 @@ function normalizeFwkResult(result) {
45570
45666
  // src/sac/collaboration-service.ts
45571
45667
  import { appendFile as appendFile9, mkdir as mkdir37, readFile as readFile75 } from "fs/promises";
45572
45668
  import { randomUUID as randomUUID10 } from "crypto";
45573
- import path144 from "path";
45669
+ import path145 from "path";
45574
45670
  class CollaborationServiceError extends Error {
45575
45671
  code;
45576
45672
  constructor(code, message) {
@@ -45585,7 +45681,7 @@ class CollaborationService {
45585
45681
  this.input = input;
45586
45682
  }
45587
45683
  file(id) {
45588
- return path144.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
45684
+ return path145.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
45589
45685
  }
45590
45686
  async overview(input) {
45591
45687
  const manifest = await this.input.workspaces.show(input);
@@ -45622,7 +45718,7 @@ class CollaborationService {
45622
45718
  occurredAt: (this.input.now ?? (() => new Date))().toISOString(),
45623
45719
  ...suppliedHandoff ? { handoff: { ...suppliedHandoff, from: actor.subject } } : {}
45624
45720
  });
45625
- await mkdir37(path144.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
45721
+ await mkdir37(path145.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
45626
45722
  await appendFile9(this.file(manifest.id), `${JSON.stringify(activity)}
45627
45723
  `, { mode: 384 });
45628
45724
  return normalizeCollaborationResult(activity);
@@ -45672,14 +45768,14 @@ function normalizeCollaborationResult(value) {
45672
45768
  // src/session/external-slate.ts
45673
45769
  init_fs();
45674
45770
  import { mkdir as mkdir39, readdir as readdir27, readFile as readFile76 } from "fs/promises";
45675
- import path146 from "path";
45771
+ import path147 from "path";
45676
45772
 
45677
45773
  // src/sac/machine-wrap-up.ts
45678
45774
  init_fs();
45679
45775
  init_slate();
45680
45776
  import { createHash as createHash36, randomUUID as randomUUID12 } from "crypto";
45681
45777
  import { mkdir as mkdir38 } from "fs/promises";
45682
- import path145 from "path";
45778
+ import path146 from "path";
45683
45779
 
45684
45780
  // src/sac/workspace-resolve.ts
45685
45781
  init_redact();
@@ -45822,11 +45918,11 @@ async function resolveMachineWrapUp(input) {
45822
45918
  `;
45823
45919
  const seedsJson = `${JSON.stringify(seedsForKind.map((seed) => ({ text: seed.text, source: describeSource(seed.source) })), null, 2)}
45824
45920
  `;
45825
- const evidenceRelBase = path145.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
45921
+ const evidenceRelBase = path146.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
45826
45922
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
45827
- { name: `${input.kind}.diff.txt`, content: diffBody, path: path145.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
45828
- { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path145.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
45829
- { name: `${input.kind}.seeds.json`, content: seedsJson, path: path145.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
45923
+ { name: `${input.kind}.diff.txt`, content: diffBody, path: path146.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
45924
+ { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path146.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
45925
+ { name: `${input.kind}.seeds.json`, content: seedsJson, path: path146.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
45830
45926
  ]);
45831
45927
  if (!floor.ok)
45832
45928
  return { ok: false, code: "security_denied", detail: floor.reason };
@@ -45880,14 +45976,14 @@ ${safeSeeds.content}`;
45880
45976
  }
45881
45977
  summary = result.text.trim().length > 0 ? result.text.trim() : mechanicalSummary(summaryDiff, course);
45882
45978
  }
45883
- const evidenceDir = path145.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
45979
+ const evidenceDir = path146.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
45884
45980
  await mkdir38(evidenceDir, { recursive: true });
45885
45981
  const diffFile = `${input.kind}.${shortHash}.diff.txt`;
45886
45982
  const flowFile = `${input.kind}.${shortHash}.flow.json`;
45887
45983
  const seedsFile = `${input.kind}.${shortHash}.seeds.json`;
45888
- await writeFileAtomic(path145.join(evidenceDir, diffFile), safeDiff.content);
45889
- await writeFileAtomic(path145.join(evidenceDir, flowFile), safeFlow.content);
45890
- await writeFileAtomic(path145.join(evidenceDir, seedsFile), safeSeeds.content);
45984
+ await writeFileAtomic(path146.join(evidenceDir, diffFile), safeDiff.content);
45985
+ await writeFileAtomic(path146.join(evidenceDir, flowFile), safeFlow.content);
45986
+ await writeFileAtomic(path146.join(evidenceDir, seedsFile), safeSeeds.content);
45891
45987
  const observedAt = now().toISOString();
45892
45988
  const relBase = `./.metaproject/workspaces/${input.workspaceId}/machine-evidence`;
45893
45989
  const evidence = [
@@ -45897,7 +45993,7 @@ ${safeSeeds.content}`;
45897
45993
  ];
45898
45994
  if (floor.notice !== undefined) {
45899
45995
  const noticeFile = `${input.kind}.${shortHash}.redaction.md`;
45900
- await writeFileAtomic(path145.join(evidenceDir, noticeFile), floor.notice);
45996
+ await writeFileAtomic(path146.join(evidenceDir, noticeFile), floor.notice);
45901
45997
  evidence.push({ kind: REDACTION_NOTICE_KIND, uri: `${relBase}/${noticeFile}`, revision: sha2567(floor.notice), observedAt });
45902
45998
  }
45903
45999
  return {
@@ -45916,18 +46012,18 @@ async function writeFlooredArchiveArtifact(params) {
45916
46012
  {
45917
46013
  name: params.filename,
45918
46014
  content: params.content,
45919
- path: path145.posix.join("slate-archive", params.filename),
46015
+ path: path146.posix.join("slate-archive", params.filename),
45920
46016
  source: "generated"
45921
46017
  }
45922
46018
  ]);
45923
46019
  if (!floor.ok)
45924
46020
  return { ok: false, code: "security_denied", detail: floor.reason };
45925
46021
  const body = floor.bodies[0];
45926
- const archiveDir = path145.join(params.dir, "slate-archive");
46022
+ const archiveDir = path146.join(params.dir, "slate-archive");
45927
46023
  await mkdir38(archiveDir, { recursive: true });
45928
- await writeFileAtomic(path145.join(archiveDir, params.filename), body.content);
46024
+ await writeFileAtomic(path146.join(archiveDir, params.filename), body.content);
45929
46025
  if (floor.notice !== undefined) {
45930
- await writeFileAtomic(path145.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
46026
+ await writeFileAtomic(path146.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
45931
46027
  }
45932
46028
  return { ok: true, altered: body.altered };
45933
46029
  }
@@ -45963,9 +46059,9 @@ async function writeWrapUpOutcomeArtifact(cwd, dir, trigger, now, groups) {
45963
46059
  return;
45964
46060
  const refusalIso = now().toISOString();
45965
46061
  const refusalFilename = `${refusalIso.replace(/[:.]/g, "-")}-wrap-up-outcome.json`;
45966
- const archiveDir = path145.join(dir, "slate-archive");
46062
+ const archiveDir = path146.join(dir, "slate-archive");
45967
46063
  await mkdir38(archiveDir, { recursive: true });
45968
- await writeFileAtomic(path145.join(archiveDir, refusalFilename), `${JSON.stringify({
46064
+ await writeFileAtomic(path146.join(archiveDir, refusalFilename), `${JSON.stringify({
45969
46065
  recordType: "wrap-up-outcome",
45970
46066
  trigger,
45971
46067
  generatedAt: refusalIso,
@@ -46102,7 +46198,7 @@ async function runWrapUp(input) {
46102
46198
 
46103
46199
  // src/session/external-slate.ts
46104
46200
  function externalSlatesDir(cwd) {
46105
- return path146.join(cwd, ".keryx", "external-slates");
46201
+ return path147.join(cwd, ".keryx", "external-slates");
46106
46202
  }
46107
46203
  var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
46108
46204
  function assertValidExternalSessionId(externalSessionId) {
@@ -46112,14 +46208,14 @@ function assertValidExternalSessionId(externalSessionId) {
46112
46208
  }
46113
46209
  function externalSlatePath(cwd, externalSessionId) {
46114
46210
  assertValidExternalSessionId(externalSessionId);
46115
- return path146.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
46211
+ return path147.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
46116
46212
  }
46117
46213
  function externalSlateLockPath(cwd, externalSessionId) {
46118
46214
  return `${externalSlatePath(cwd, externalSessionId)}.lock`;
46119
46215
  }
46120
46216
  function externalSlateEvidenceDir(cwd, externalSessionId) {
46121
46217
  assertValidExternalSessionId(externalSessionId);
46122
- return path146.join(externalSlatesDir(cwd), externalSessionId);
46218
+ return path147.join(externalSlatesDir(cwd), externalSessionId);
46123
46219
  }
46124
46220
  async function readExternalSlate(cwd, externalSessionId) {
46125
46221
  try {
@@ -46203,12 +46299,12 @@ init_service2();
46203
46299
 
46204
46300
  // src/standard/service.ts
46205
46301
  init_fs();
46206
- import path149 from "path";
46302
+ import path150 from "path";
46207
46303
  import { readFile as readFile79 } from "fs/promises";
46208
46304
 
46209
46305
  // src/standard/validate.ts
46210
46306
  init_fs();
46211
- import path148 from "path";
46307
+ import path149 from "path";
46212
46308
  import { readFile as readFile78 } from "fs/promises";
46213
46309
 
46214
46310
  // src/standard/schemas.ts
@@ -46338,7 +46434,7 @@ var SCHEMA_REGISTRY2 = {
46338
46434
  // src/standard/profiles.ts
46339
46435
  init_fs();
46340
46436
  init_entrypoint_targets();
46341
- import path147 from "path";
46437
+ import path148 from "path";
46342
46438
  import { readFile as readFile77 } from "fs/promises";
46343
46439
  var AGENT_MODULES = ["gdgraph", "gdctx", "gdskills", "gdwiki", "memory"];
46344
46440
  var CI_MODULES = ["health", "testing"];
@@ -46363,7 +46459,7 @@ function enabledModuleKeys(manifest) {
46363
46459
  }
46364
46460
  async function rootEntrypointLinksIndex(cwd, manifest) {
46365
46461
  for (const { path: name } of namedEntrypoints(manifest)) {
46366
- const filePath = path147.join(cwd, name);
46462
+ const filePath = path148.join(cwd, name);
46367
46463
  if (!await pathExists(filePath)) {
46368
46464
  continue;
46369
46465
  }
@@ -46375,16 +46471,16 @@ async function rootEntrypointLinksIndex(cwd, manifest) {
46375
46471
  return false;
46376
46472
  }
46377
46473
  async function minimalSatisfied(cwd) {
46378
- const metaprojectRoot = path147.join(cwd, ".metaproject");
46474
+ const metaprojectRoot = path148.join(cwd, ".metaproject");
46379
46475
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
46380
46476
  const requiredDirs = ["modules", "rules", "skills", "data"];
46381
46477
  for (const file of requiredFiles) {
46382
- if (!await pathExists(path147.join(metaprojectRoot, file))) {
46478
+ if (!await pathExists(path148.join(metaprojectRoot, file))) {
46383
46479
  return false;
46384
46480
  }
46385
46481
  }
46386
46482
  for (const dir of requiredDirs) {
46387
- if (!await pathExists(path147.join(metaprojectRoot, dir))) {
46483
+ if (!await pathExists(path148.join(metaprojectRoot, dir))) {
46388
46484
  return false;
46389
46485
  }
46390
46486
  }
@@ -46397,7 +46493,7 @@ async function ciSatisfied(cwd, manifest) {
46397
46493
  return false;
46398
46494
  }
46399
46495
  for (const key of ciModules) {
46400
- if (await pathExists(path147.join(cwd, ".metaproject", "data", key, "artifacts"))) {
46496
+ if (await pathExists(path148.join(cwd, ".metaproject", "data", key, "artifacts"))) {
46401
46497
  return true;
46402
46498
  }
46403
46499
  }
@@ -46410,7 +46506,7 @@ async function evaluateProfiles(cwd, manifest) {
46410
46506
  satisfied.push("minimal");
46411
46507
  }
46412
46508
  const hasAgentModule = AGENT_MODULES.some((key) => new Set(enabledModuleKeys(manifest)).has(key));
46413
- const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path147.join(cwd, ".metaproject", "rules"));
46509
+ const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path148.join(cwd, ".metaproject", "rules"));
46414
46510
  if (agent) {
46415
46511
  satisfied.push("agent");
46416
46512
  }
@@ -46579,20 +46675,20 @@ var MANIFEST_TOP_LEVEL_SCHEMA = {
46579
46675
  async function validateWorkspace2(cwd) {
46580
46676
  const errors = [];
46581
46677
  const warnings = [];
46582
- const metaprojectRoot = path148.join(cwd, ".metaproject");
46678
+ const metaprojectRoot = path149.join(cwd, ".metaproject");
46583
46679
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
46584
46680
  for (const file of requiredFiles) {
46585
- if (!await pathExists(path148.join(metaprojectRoot, file))) {
46681
+ if (!await pathExists(path149.join(metaprojectRoot, file))) {
46586
46682
  errors.push(issue("missing-required-file", `Required file .metaproject/${file} is missing`, `Run \`keryx init\` to scaffold .metaproject/${file}.`));
46587
46683
  }
46588
46684
  }
46589
46685
  const requiredDirs = ["modules", "rules", "skills", "data"];
46590
46686
  for (const dir of requiredDirs) {
46591
- if (!await pathExists(path148.join(metaprojectRoot, dir))) {
46687
+ if (!await pathExists(path149.join(metaprojectRoot, dir))) {
46592
46688
  errors.push(issue("missing-required-dir", `Required directory .metaproject/${dir}/ is missing`, `Run \`keryx init\` to create .metaproject/${dir}/.`));
46593
46689
  }
46594
46690
  }
46595
- const manifestPath = path148.join(metaprojectRoot, "metaproject.json");
46691
+ const manifestPath = path149.join(metaprojectRoot, "metaproject.json");
46596
46692
  if (!await pathExists(manifestPath)) {
46597
46693
  return { ok: errors.length === 0, errors, warnings };
46598
46694
  }
@@ -46624,7 +46720,7 @@ async function validateWorkspace2(cwd) {
46624
46720
  if (typeof value !== "string") {
46625
46721
  continue;
46626
46722
  }
46627
- if (!await pathExists(path148.join(cwd, value))) {
46723
+ if (!await pathExists(path149.join(cwd, value))) {
46628
46724
  errors.push(issue("missing-declared-path", `Declared path paths.${key} -> ${value} does not exist`, `Create ${value} or remove paths.${key} from metaproject.json.`));
46629
46725
  }
46630
46726
  }
@@ -46634,7 +46730,7 @@ async function validateWorkspace2(cwd) {
46634
46730
  continue;
46635
46731
  }
46636
46732
  if (typeof entry.manifest === "string") {
46637
- if (!await pathExists(path148.join(cwd, entry.manifest))) {
46733
+ if (!await pathExists(path149.join(cwd, entry.manifest))) {
46638
46734
  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.`));
46639
46735
  }
46640
46736
  }
@@ -46643,14 +46739,14 @@ async function validateWorkspace2(cwd) {
46643
46739
  if (typeof value !== "string") {
46644
46740
  continue;
46645
46741
  }
46646
- if (!await pathExists(path148.join(cwd, value))) {
46742
+ if (!await pathExists(path149.join(cwd, value))) {
46647
46743
  const sink = field === "data" ? warnings : errors;
46648
46744
  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.`));
46649
46745
  }
46650
46746
  }
46651
46747
  }
46652
46748
  for (const { path: name, scope } of namedEntrypoints(manifest)) {
46653
- const filePath = path148.join(cwd, name);
46749
+ const filePath = path149.join(cwd, name);
46654
46750
  if (!await pathExists(filePath)) {
46655
46751
  continue;
46656
46752
  }
@@ -47656,7 +47752,7 @@ async function runDoctor(cwd) {
47656
47752
  return validateWorkspace2(cwd);
47657
47753
  }
47658
47754
  async function readManifest2(cwd) {
47659
- const manifestPath = path149.join(cwd, ".metaproject", "metaproject.json");
47755
+ const manifestPath = path150.join(cwd, ".metaproject", "metaproject.json");
47660
47756
  if (!await pathExists(manifestPath)) {
47661
47757
  throw new Error("Metaproject is not initialized (missing .metaproject/metaproject.json). Run `keryx init` first.");
47662
47758
  }