@mrciphersmith/keryx 0.3.52 → 0.3.53

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
@@ -7414,6 +7414,7 @@ async function worktreeFileIsClean(projectRoot, relativePath) {
7414
7414
  }
7415
7415
 
7416
7416
  // src/lib/git-worktrees.ts
7417
+ import { readdir as readdir8, readFile as readFile15, realpath as realpath7, stat as stat7 } from "fs/promises";
7417
7418
  import path32 from "path";
7418
7419
  async function resolveGitCommonDir(cwd) {
7419
7420
  try {
@@ -7422,7 +7423,12 @@ async function resolveGitCommonDir(cwd) {
7422
7423
  if (await proc.exited !== 0 || out.length === 0) {
7423
7424
  return;
7424
7425
  }
7425
- return path32.isAbsolute(out) ? out : path32.resolve(cwd, out);
7426
+ const absolute = path32.isAbsolute(out) ? out : path32.resolve(cwd, out);
7427
+ try {
7428
+ return path32.join(await realpath7(path32.dirname(absolute)), path32.basename(absolute));
7429
+ } catch {
7430
+ return absolute;
7431
+ }
7426
7432
  } catch {
7427
7433
  return;
7428
7434
  }
@@ -7605,7 +7611,7 @@ var init_entrypoint_targets = __esm(() => {
7605
7611
  });
7606
7612
 
7607
7613
  // src/rules/export-render.ts
7608
- import { readFile as readFile15, readdir as readdir8 } from "fs/promises";
7614
+ import { readFile as readFile16, readdir as readdir9 } from "fs/promises";
7609
7615
  import path33 from "path";
7610
7616
  function isUnsafeRulePath(relativePath) {
7611
7617
  return UNSAFE_RULE_PATH_PATTERN.test(relativePath) || relativePath.includes("<!--") || relativePath.includes("-->");
@@ -7670,7 +7676,7 @@ async function collectCanonicalRules(root) {
7670
7676
  async function walk(dirAbsolute, dirRelative) {
7671
7677
  let dirents;
7672
7678
  try {
7673
- dirents = await readdir8(dirAbsolute, { withFileTypes: true });
7679
+ dirents = await readdir9(dirAbsolute, { withFileTypes: true });
7674
7680
  } catch {
7675
7681
  return;
7676
7682
  }
@@ -7698,7 +7704,7 @@ async function collectCanonicalRules(root) {
7698
7704
  }
7699
7705
  let content;
7700
7706
  try {
7701
- content = await readFile15(childAbsolute, "utf8");
7707
+ content = await readFile16(childAbsolute, "utf8");
7702
7708
  } catch {
7703
7709
  continue;
7704
7710
  }
@@ -8384,7 +8390,7 @@ var init_surfaces = __esm(() => {
8384
8390
  });
8385
8391
 
8386
8392
  // src/integrations/markdown-block.ts
8387
- import { readFile as readFile16 } from "fs/promises";
8393
+ import { readFile as readFile17 } from "fs/promises";
8388
8394
  import path36 from "path";
8389
8395
  function dominantEol(content) {
8390
8396
  const crlf = (content.match(/\r\n/g) ?? []).length;
@@ -8538,7 +8544,7 @@ async function installMarkdownBlock(root, relativePath, frontMatter, spec = INST
8538
8544
  await writeContained(root, relativePath, `${frontMatter ?? ""}${spec.render()}`);
8539
8545
  return [];
8540
8546
  }
8541
- const raw = await readFile16(file, "utf8");
8547
+ const raw = await readFile17(file, "utf8");
8542
8548
  const eol = dominantEol(raw);
8543
8549
  let blocks;
8544
8550
  try {
@@ -8563,7 +8569,7 @@ async function uninstallMarkdownBlock(root, relativePath, frontMatter, spec = IN
8563
8569
  const file = fileFor(root, relativePath);
8564
8570
  if (!await pathExists(file))
8565
8571
  return false;
8566
- const raw = await readFile16(file, "utf8");
8572
+ const raw = await readFile17(file, "utf8");
8567
8573
  const blocks = parseBlocks(raw, relativePath, spec);
8568
8574
  if (blocks.length === 0)
8569
8575
  return false;
@@ -8585,7 +8591,7 @@ async function inspectMarkdownBlock(root, relativePath, spec = INSTRUCTIONS_BLOC
8585
8591
  const file = fileFor(root, relativePath);
8586
8592
  if (!await pathExists(file))
8587
8593
  return { state: "absent-file" };
8588
- const raw = await readFile16(file, "utf8");
8594
+ const raw = await readFile17(file, "utf8");
8589
8595
  let blocks;
8590
8596
  try {
8591
8597
  blocks = parseBlocks(raw, relativePath, spec);
@@ -9780,6 +9786,7 @@ function isModelTier(value) {
9780
9786
  var MODEL_TIERS, TIER_ALIASES, SKILL_TIER_KEY = "model_tier", TIER_DECLARATION;
9781
9787
  var init_model_tier = __esm(() => {
9782
9788
  init_model_version();
9789
+ init_skill_frontmatter();
9783
9790
  MODEL_TIERS = ["light", "standard", "deep"];
9784
9791
  TIER_ALIASES = new Map([["cheap", "light"]]);
9785
9792
  TIER_DECLARATION = new RegExp(`^\\s*(?:[-*]\\s*)?"?(?:${SKILL_TIER_KEY}|model-tier|modelTier)"?\\s*[:=]\\s*(.+?)\\s*,?\\s*$`, "i");
@@ -9789,7 +9796,7 @@ var init_model_tier = __esm(() => {
9789
9796
  var CEILINGS_BY_KEY, SKILL_LENGTH_CEILINGS;
9790
9797
  var init_skill_length_ceilings = __esm(() => {
9791
9798
  CEILINGS_BY_KEY = {
9792
- "core/reviewer-skill-creator": 280,
9799
+ "core/reviewer-skill-creator": 279,
9793
9800
  "orchestration/code-verifier": 339,
9794
9801
  "orchestration/context-collector": 671,
9795
9802
  "orchestration/feature-analyzer": 447,
@@ -11260,7 +11267,7 @@ var init_compile = __esm(() => {
11260
11267
  });
11261
11268
 
11262
11269
  // src/agents/export.ts
11263
- import { readFile as readFile17, readdir as readdir9, lstat as lstat6, realpath as realpath7 } from "fs/promises";
11270
+ import { readFile as readFile18, readdir as readdir10, lstat as lstat6, realpath as realpath8 } from "fs/promises";
11264
11271
  import path41 from "path";
11265
11272
  function matrixStateToExportLevel(state) {
11266
11273
  return state === "native" || state === "adapter" ? state : "instruction-only";
@@ -11275,7 +11282,7 @@ function proseExportRelativePath(runtime, name) {
11275
11282
  async function readExistingFileContent(projectRoot, relativePath) {
11276
11283
  const absolute = path41.join(projectRoot, ...relativePath.split("/"));
11277
11284
  try {
11278
- return await readFile17(absolute, "utf8");
11285
+ return await readFile18(absolute, "utf8");
11279
11286
  } catch (error) {
11280
11287
  if (isNotFound(error))
11281
11288
  return;
@@ -11307,7 +11314,7 @@ async function checkExportPathSafety(projectRoot, relativePath) {
11307
11314
  ancestor = parent;
11308
11315
  }
11309
11316
  try {
11310
- const [resolvedRoot, resolvedAncestor] = await Promise.all([realpath7(projectRoot), realpath7(ancestor)]);
11317
+ const [resolvedRoot, resolvedAncestor] = await Promise.all([realpath8(projectRoot), realpath8(ancestor)]);
11311
11318
  if (!isPathInside(resolvedRoot, resolvedAncestor)) {
11312
11319
  return `refusing to write ${relativePath} \u2014 its resolved directory is outside the project root`;
11313
11320
  }
@@ -11487,7 +11494,7 @@ async function scanManagedAgentExports(projectRoot, runtime) {
11487
11494
  return { verified: [], handEdited: [] };
11488
11495
  let entries;
11489
11496
  try {
11490
- entries = await readdir9(dirAbsolute, { withFileTypes: true });
11497
+ entries = await readdir10(dirAbsolute, { withFileTypes: true });
11491
11498
  } catch {
11492
11499
  return { verified: [], handEdited: [] };
11493
11500
  }
@@ -11508,7 +11515,7 @@ async function scanManagedAgentExports(projectRoot, runtime) {
11508
11515
  continue;
11509
11516
  let content;
11510
11517
  try {
11511
- content = await readFile17(absolute, "utf8");
11518
+ content = await readFile18(absolute, "utf8");
11512
11519
  } catch {
11513
11520
  continue;
11514
11521
  }
@@ -11681,7 +11688,7 @@ var init_surfaces_agents = __esm(() => {
11681
11688
  });
11682
11689
 
11683
11690
  // src/lib/git-local-ignore.ts
11684
- import { lstat as lstat7, mkdir as mkdir9, readFile as readFile18, realpath as realpath8, writeFile as writeFile6 } from "fs/promises";
11691
+ import { lstat as lstat7, mkdir as mkdir9, readFile as readFile19, realpath as realpath9, writeFile as writeFile6 } from "fs/promises";
11685
11692
  import path42 from "path";
11686
11693
  async function isPathIgnored(projectRoot, relativePath) {
11687
11694
  if (await resolveGitCommonDir(projectRoot) === undefined)
@@ -11768,7 +11775,7 @@ async function explainIgnoredPaths(projectRoot, relativePaths) {
11768
11775
  return [];
11769
11776
  const excludePath = path42.join(commonDir, "info", "exclude");
11770
11777
  const block = findManagedBlock(await readExcludeFile(excludePath).catch(() => ""), location.prefix);
11771
- const excludeReal = await realpath8(excludePath).catch(() => excludePath);
11778
+ const excludeReal = await realpath9(excludePath).catch(() => excludePath);
11772
11779
  let fields;
11773
11780
  try {
11774
11781
  const proc = Bun.spawn(["git", "check-ignore", "--verbose", "--non-matching", "--no-index", "-z", "--stdin"], {
@@ -11799,7 +11806,7 @@ async function explainIgnoredPaths(projectRoot, relativePaths) {
11799
11806
  let sourcePath = sourcePaths.get(source);
11800
11807
  if (sourcePath === undefined) {
11801
11808
  const resolved = path42.resolve(location.toplevel, source);
11802
- sourcePath = await realpath8(resolved).catch(() => resolved);
11809
+ sourcePath = await realpath9(resolved).catch(() => resolved);
11803
11810
  sourcePaths.set(source, sourcePath);
11804
11811
  }
11805
11812
  const ignored = !pattern.startsWith("!");
@@ -11848,7 +11855,7 @@ async function resolveWorktreeLocation(projectRoot) {
11848
11855
  }
11849
11856
  }
11850
11857
  async function readExcludeFile(excludePath) {
11851
- return readFile18(excludePath, "utf8").catch((error) => {
11858
+ return readFile19(excludePath, "utf8").catch((error) => {
11852
11859
  if (error.code === "ENOENT" || error.code === "ENOTDIR")
11853
11860
  return "";
11854
11861
  throw error;
@@ -11868,7 +11875,7 @@ function refuseUnsafeLines(lines) {
11868
11875
  return;
11869
11876
  }
11870
11877
  async function refuseUnsafeExcludePath(commonDir, infoDir, excludePath) {
11871
- const commonDirReal = await realpath8(commonDir).catch(() => commonDir);
11878
+ const commonDirReal = await realpath9(commonDir).catch(() => commonDir);
11872
11879
  for (const [target, label] of [
11873
11880
  [infoDir, "the git info directory"],
11874
11881
  [excludePath, "the git exclude file"]
@@ -11877,7 +11884,7 @@ async function refuseUnsafeExcludePath(commonDir, infoDir, excludePath) {
11877
11884
  if (stats === null)
11878
11885
  continue;
11879
11886
  if (stats.isSymbolicLink()) {
11880
- const real = await realpath8(target).catch(() => {
11887
+ const real = await realpath9(target).catch(() => {
11881
11888
  return;
11882
11889
  });
11883
11890
  if (real === undefined)
@@ -11904,7 +11911,7 @@ var init_git_local_ignore = __esm(() => {
11904
11911
  });
11905
11912
 
11906
11913
  // src/lib/metaproject-gitignore.ts
11907
- import { readFile as readFile19 } from "fs/promises";
11914
+ import { readFile as readFile20 } from "fs/promises";
11908
11915
  import path43 from "path";
11909
11916
  async function syncMetaprojectIgnoreRules(projectRoot, options = {}) {
11910
11917
  const notice = options.onNotice ?? (() => {});
@@ -11958,7 +11965,7 @@ async function moveBlockOutOfGitignore(projectRoot, notice) {
11958
11965
  const gitignorePath = path43.join(projectRoot, GITIGNORE);
11959
11966
  if (!await pathExists(gitignorePath))
11960
11967
  return false;
11961
- const content = await readFile19(gitignorePath, "utf8");
11968
+ const content = await readFile20(gitignorePath, "utf8");
11962
11969
  if (!managedBlockPattern().test(content))
11963
11970
  return false;
11964
11971
  const head = await readHeadBlob(projectRoot, GITIGNORE);
@@ -12261,7 +12268,7 @@ var init_rules_export_target = __esm(() => {
12261
12268
 
12262
12269
  // src/integrations/surfaces-rules.ts
12263
12270
  import { readFileSync as readFileSync7 } from "fs";
12264
- import { readFile as readFile20 } from "fs/promises";
12271
+ import { readFile as readFile21 } from "fs/promises";
12265
12272
  import path45 from "path";
12266
12273
  async function rulesSpec(root) {
12267
12274
  const { rules, skipped } = await collectCanonicalRules(root);
@@ -12389,7 +12396,7 @@ async function installIntoOverride(root, relativePath) {
12389
12396
  const refusal = await refuseEscapingSymlink(root, relativePath);
12390
12397
  if (refusal !== undefined)
12391
12398
  return { errors: [refusal], warnings };
12392
- const content = await readFile20(path45.join(root, ...relativePath.split("/")), "utf8");
12399
+ const content = await readFile21(path45.join(root, ...relativePath.split("/")), "utf8");
12393
12400
  let next;
12394
12401
  try {
12395
12402
  next = withOverrideRulesSlot(content, spec.render());
@@ -12447,7 +12454,7 @@ async function inspectOverrideSlot(root, relativePath) {
12447
12454
  }
12448
12455
  async function readTextIfPresent(root, relativePath) {
12449
12456
  try {
12450
- return await readFile20(path45.join(root, ...relativePath.split("/")), "utf8");
12457
+ return await readFile21(path45.join(root, ...relativePath.split("/")), "utf8");
12451
12458
  } catch (error) {
12452
12459
  if (error.code === "ENOENT")
12453
12460
  return;
@@ -13118,11 +13125,11 @@ var init_integrations = __esm(() => {
13118
13125
 
13119
13126
  // src/security/audit-harness/surfaces.ts
13120
13127
  import path47 from "path";
13121
- import { lstat as lstat8, readdir as readdir10, realpath as realpath9, stat as stat7 } from "fs/promises";
13128
+ import { lstat as lstat8, readdir as readdir11, realpath as realpath10, stat as stat8 } from "fs/promises";
13122
13129
  async function resolvesInsideRoot(root, absolute) {
13123
13130
  try {
13124
- const rootReal = await realpath9(root).catch(() => path47.resolve(root));
13125
- const real = await realpath9(absolute);
13131
+ const rootReal = await realpath10(root).catch(() => path47.resolve(root));
13132
+ const real = await realpath10(absolute);
13126
13133
  return isPathInside(rootReal, real);
13127
13134
  } catch {
13128
13135
  return false;
@@ -13160,7 +13167,7 @@ async function listFilesByExtensions(root, dirRelative, extensions) {
13160
13167
  }
13161
13168
  let entries;
13162
13169
  try {
13163
- entries = await readdir10(dirAbsolute, { withFileTypes: true });
13170
+ entries = await readdir11(dirAbsolute, { withFileTypes: true });
13164
13171
  } catch {
13165
13172
  return { found: [], unreadable: [toPosix(dirRelative)] };
13166
13173
  }
@@ -13222,7 +13229,7 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
13222
13229
  acc.unreadable.push(toPosix(dirRelative));
13223
13230
  return;
13224
13231
  }
13225
- const dirReal = await realpath9(dirAbsolute).catch(() => {
13232
+ const dirReal = await realpath10(dirAbsolute).catch(() => {
13226
13233
  return;
13227
13234
  });
13228
13235
  if (dirReal !== undefined) {
@@ -13232,7 +13239,7 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
13232
13239
  }
13233
13240
  let entries;
13234
13241
  try {
13235
- entries = await readdir10(dirAbsolute, { withFileTypes: true });
13242
+ entries = await readdir11(dirAbsolute, { withFileTypes: true });
13236
13243
  } catch {
13237
13244
  acc.unreadable.push(toPosix(dirRelative));
13238
13245
  return;
@@ -13253,7 +13260,7 @@ async function walkScripts(root, dirRelative, depth, visited, acc) {
13253
13260
  acc.unreadable.push(toPosix(childRelative));
13254
13261
  continue;
13255
13262
  }
13256
- const stats = await stat7(absolute).catch(() => {
13263
+ const stats = await stat8(absolute).catch(() => {
13257
13264
  return;
13258
13265
  });
13259
13266
  if (stats?.isDirectory()) {
@@ -14787,7 +14794,7 @@ var init_checks = __esm(() => {
14787
14794
 
14788
14795
  // src/security/audit-harness/baseline.ts
14789
14796
  import path48 from "path";
14790
- import { readFile as readFile21 } from "fs/promises";
14797
+ import { readFile as readFile22 } from "fs/promises";
14791
14798
  function defaultBaselinePath(root) {
14792
14799
  return path48.join(root, ".metaproject", "security-audit-baseline.json");
14793
14800
  }
@@ -14862,7 +14869,7 @@ function indefiniteSuppressionFindings(applicableEntries) {
14862
14869
  }
14863
14870
  async function readRawBaselineFindingIds(filePath) {
14864
14871
  try {
14865
- const text = await readFile21(filePath, "utf8");
14872
+ const text = await readFile22(filePath, "utf8");
14866
14873
  const parsed = JSON.parse(text);
14867
14874
  if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.entries)) {
14868
14875
  return [];
@@ -14887,7 +14894,7 @@ async function addBaselineEntry(root, entry, options = {}) {
14887
14894
  }
14888
14895
  const now = options.now ? options.now() : new Date;
14889
14896
  backupPath = `${filePath}.bak-${now.toISOString().replace(/[:.]/g, "-")}`;
14890
- const preResealBytes = await readFile21(filePath);
14897
+ const preResealBytes = await readFile22(filePath);
14891
14898
  await writeContained(root, path48.relative(root, backupPath), preResealBytes);
14892
14899
  entries = loaded.state.entries;
14893
14900
  const rawIds = await readRawBaselineFindingIds(filePath);
@@ -14994,12 +15001,12 @@ var init_types2 = __esm(() => {
14994
15001
 
14995
15002
  // src/security/audit-harness/proposals.ts
14996
15003
  import path49 from "path";
14997
- import { readFile as readFile22, realpath as realpath10 } from "fs/promises";
15004
+ import { readFile as readFile23, realpath as realpath11 } from "fs/promises";
14998
15005
  async function assertContained2(rootReal, absolute, label) {
14999
15006
  if (!isPathInside(rootReal, absolute)) {
15000
15007
  throw new Error(`Refusing to write ${label}: path escapes project root ${rootReal}.`);
15001
15008
  }
15002
- const real = await realpath10(absolute).catch(() => {
15009
+ const real = await realpath11(absolute).catch(() => {
15003
15010
  return;
15004
15011
  });
15005
15012
  if (real !== undefined) {
@@ -15010,7 +15017,7 @@ async function assertContained2(rootReal, absolute, label) {
15010
15017
  }
15011
15018
  let dir = path49.dirname(absolute);
15012
15019
  for (;; ) {
15013
- const dirReal = await realpath10(dir).catch(() => {
15020
+ const dirReal = await realpath11(dir).catch(() => {
15014
15021
  return;
15015
15022
  });
15016
15023
  if (dirReal !== undefined) {
@@ -15108,7 +15115,7 @@ function countOccurrences(haystack, needle) {
15108
15115
  async function applyTextEdit(rootReal, edit) {
15109
15116
  const absolute = path49.resolve(rootReal, edit.path);
15110
15117
  await assertContained2(rootReal, absolute, `target file "${edit.path}"`);
15111
- const content = await readFile22(absolute, "utf8");
15118
+ const content = await readFile23(absolute, "utf8");
15112
15119
  const occurrences = countOccurrences(content, edit.from);
15113
15120
  if (occurrences === 0) {
15114
15121
  throw new Error(`Cannot apply proposal: expected text not found in ${edit.path}.`);
@@ -15133,7 +15140,7 @@ async function applyAuditProposal(root, proposalId, options = {}) {
15133
15140
  if (!PROPOSAL_ID_RE.test(proposalId)) {
15134
15141
  throw new Error(`Invalid proposal id: ${proposalId}`);
15135
15142
  }
15136
- const rootReal = await realpath10(root).catch(() => {
15143
+ const rootReal = await realpath11(root).catch(() => {
15137
15144
  return;
15138
15145
  }) ?? path49.resolve(root);
15139
15146
  return withFileLock(lockPath2(rootReal), async () => {
@@ -15189,7 +15196,7 @@ var init_proposals = __esm(() => {
15189
15196
  // src/security/audit-harness/index.ts
15190
15197
  import { createHash as createHash7 } from "crypto";
15191
15198
  import path50 from "path";
15192
- import { readFile as readFile23 } from "fs/promises";
15199
+ import { readFile as readFile24 } from "fs/promises";
15193
15200
  function findingId(f) {
15194
15201
  const pointerOrLine = f.location?.pointer ?? (f.location?.line !== undefined ? `line:${f.location.line}` : "");
15195
15202
  const policyId = f.evidence.policyId ?? "";
@@ -15214,14 +15221,14 @@ function compareFindings(a, b) {
15214
15221
  }
15215
15222
  async function safeReadText(absolute) {
15216
15223
  try {
15217
- return await readFile23(absolute, "utf8");
15224
+ return await readFile24(absolute, "utf8");
15218
15225
  } catch {
15219
15226
  return;
15220
15227
  }
15221
15228
  }
15222
15229
  async function safeReadBuffer(absolute) {
15223
15230
  try {
15224
- return await readFile23(absolute);
15231
+ return await readFile24(absolute);
15225
15232
  } catch {
15226
15233
  return;
15227
15234
  }
@@ -15819,7 +15826,7 @@ __export(exports_service, {
15819
15826
  verifyConfigChecksum: () => verifyConfigChecksum
15820
15827
  });
15821
15828
  import path51 from "path";
15822
- import { readFile as readFile24 } from "fs/promises";
15829
+ import { readFile as readFile25 } from "fs/promises";
15823
15830
  import { randomBytes as randomBytes4 } from "crypto";
15824
15831
  function validateSerializedOutput(content, exemptExfil) {
15825
15832
  return validateSerializedContentForTransport(content, exemptExfil);
@@ -15952,7 +15959,7 @@ async function readLatestReport(cwd) {
15952
15959
  }
15953
15960
  let parsed;
15954
15961
  try {
15955
- parsed = JSON.parse(await readFile24(file, "utf8"));
15962
+ parsed = JSON.parse(await readFile25(file, "utf8"));
15956
15963
  } catch {
15957
15964
  return { kind: "unusable" };
15958
15965
  }
@@ -16072,9 +16079,9 @@ var init_service2 = __esm(() => {
16072
16079
  });
16073
16080
 
16074
16081
  // src/gdgraph/config.ts
16075
- import path56 from "path";
16082
+ import path57 from "path";
16076
16083
  function gdgraphConfigPath(cwd) {
16077
- return path56.join(cwd, ".metaproject", "gdgraph.config.json");
16084
+ return path57.join(cwd, ".metaproject", "gdgraph.config.json");
16078
16085
  }
16079
16086
  function mergeGdgraphConfig(parsed) {
16080
16087
  const base = DEFAULT_GDGRAPH_CONFIG;
@@ -16679,7 +16686,7 @@ var init_extract = __esm(() => {
16679
16686
  });
16680
16687
 
16681
16688
  // src/gdgraph/treesitter/grammars.ts
16682
- import path57 from "path";
16689
+ import path58 from "path";
16683
16690
  function grammarAssetId(language) {
16684
16691
  return `tree-sitter-${language}`;
16685
16692
  }
@@ -16695,7 +16702,7 @@ function symbolLanguage(language) {
16695
16702
  async function resolveGrammar(cwd, language, grammarsPath) {
16696
16703
  const id = grammarAssetId(language);
16697
16704
  const lock = await loadAssetsLock(cwd);
16698
- const overrides = grammarsPath ? { [id]: { path: path57.join(grammarsPath, `${id}.wasm`) } } : undefined;
16705
+ const overrides = grammarsPath ? { [id]: { path: path58.join(grammarsPath, `${id}.wasm`) } } : undefined;
16699
16706
  const registry = registryFromLock(lock, overrides);
16700
16707
  const resolved = await resolveAsset(registry, id);
16701
16708
  if (!resolved) {
@@ -16725,7 +16732,7 @@ function toGrammarLanguages(languages) {
16725
16732
  return out;
16726
16733
  }
16727
16734
  function grammarForFile(file, available) {
16728
- const ext = path57.extname(file);
16735
+ const ext = path58.extname(file);
16729
16736
  const preference = ext === ".tsx" ? ["tsx", "typescript"] : ext === ".ts" ? ["typescript"] : ext === ".jsx" || ext === ".js" || ext === ".mjs" || ext === ".cjs" ? ["javascript"] : ext === ".java" ? ["java"] : ext === ".py" ? ["python"] : [];
16730
16737
  for (const language of preference) {
16731
16738
  if (available.includes(language)) {
@@ -16987,7 +16994,7 @@ var init_adapter = __esm(() => {
16987
16994
 
16988
16995
  // src/gdgraph/enrich.ts
16989
16996
  import { mkdir as mkdir13, writeFile as writeFile7 } from "fs/promises";
16990
- import path58 from "path";
16997
+ import path59 from "path";
16991
16998
  async function enrichBuildWithSymbols(cwd, files, resolve) {
16992
16999
  const config = await loadGdgraphConfig(cwd);
16993
17000
  const treesitterConfig = {
@@ -17003,12 +17010,12 @@ async function enrichBuildWithSymbols(cwd, files, resolve) {
17003
17010
  return { enriched: true, symbols: layer.symbols.length, calls: layer.calls.length };
17004
17011
  }
17005
17012
  async function writeSymbolLayer(cwd, layer) {
17006
- const storageDir = path58.join(cwd, ".metaproject", "data", "gdgraph", "storage");
17013
+ const storageDir = path59.join(cwd, ".metaproject", "data", "gdgraph", "storage");
17007
17014
  await mkdir13(storageDir, { recursive: true });
17008
- await writeFile7(path58.join(storageDir, "symbols.jsonl"), layer.symbols.map((symbol) => JSON.stringify(symbol)).join(`
17015
+ await writeFile7(path59.join(storageDir, "symbols.jsonl"), layer.symbols.map((symbol) => JSON.stringify(symbol)).join(`
17009
17016
  `) + `
17010
17017
  `, "utf8");
17011
- await writeFile7(path58.join(storageDir, "calls.jsonl"), layer.calls.map((call) => JSON.stringify(call)).join(`
17018
+ await writeFile7(path59.join(storageDir, "calls.jsonl"), layer.calls.map((call) => JSON.stringify(call)).join(`
17012
17019
  `) + `
17013
17020
  `, "utf8");
17014
17021
  }
@@ -17200,11 +17207,11 @@ var NOT_CODE_SCOPED = "none";
17200
17207
  var init_describes = () => {};
17201
17208
 
17202
17209
  // src/sync/provenance.ts
17203
- import { mkdir as mkdir14, readFile as readFile28, writeFile as writeFile8 } from "fs/promises";
17204
- import path59 from "path";
17210
+ import { mkdir as mkdir14, readFile as readFile29, writeFile as writeFile8 } from "fs/promises";
17211
+ import path60 from "path";
17205
17212
  import { spawn } from "child_process";
17206
17213
  function provenancePath(cwd, module) {
17207
- return path59.join(cwd, ".metaproject", "data", module, ".provenance.json");
17214
+ return path60.join(cwd, ".metaproject", "data", module, ".provenance.json");
17208
17215
  }
17209
17216
  function gitCmdResult(cwd, args) {
17210
17217
  return new Promise((resolve) => {
@@ -17249,7 +17256,7 @@ async function recordProvenance(cwd, module, at) {
17249
17256
  if (!head)
17250
17257
  return;
17251
17258
  const file = provenancePath(cwd, module);
17252
- await mkdir14(path59.dirname(file), { recursive: true });
17259
+ await mkdir14(path60.dirname(file), { recursive: true });
17253
17260
  const provenance = { commit: head.commit, branch: head.branch, builtAt: at };
17254
17261
  await writeFile8(file, `${JSON.stringify(provenance, null, 2)}
17255
17262
  `, "utf8");
@@ -17260,7 +17267,7 @@ async function readProvenance(cwd, module) {
17260
17267
  return null;
17261
17268
  }
17262
17269
  try {
17263
- const parsed = JSON.parse(await readFile28(file, "utf8"));
17270
+ const parsed = JSON.parse(await readFile29(file, "utf8"));
17264
17271
  if (parsed && typeof parsed === "object" && typeof parsed.commit === "string") {
17265
17272
  return parsed;
17266
17273
  }
@@ -17273,8 +17280,8 @@ var init_provenance = __esm(() => {
17273
17280
 
17274
17281
  // src/gdgraph/staleness.ts
17275
17282
  import { spawn as spawn2 } from "child_process";
17276
- import { stat as stat8 } from "fs/promises";
17277
- import path60 from "path";
17283
+ import { stat as stat9 } from "fs/promises";
17284
+ import path61 from "path";
17278
17285
  function gitStatusPorcelain(cwd) {
17279
17286
  return new Promise((resolve) => {
17280
17287
  try {
@@ -17297,10 +17304,10 @@ function gitStatusPorcelain(cwd) {
17297
17304
  });
17298
17305
  }
17299
17306
  function nodesJsonlPath(cwd) {
17300
- return path60.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
17307
+ return path61.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
17301
17308
  }
17302
17309
  function gdgraphConfigPath2(cwd) {
17303
- return path60.join(cwd, ".metaproject", "gdgraph.config.json");
17310
+ return path61.join(cwd, ".metaproject", "gdgraph.config.json");
17304
17311
  }
17305
17312
  function categorizeStatusEntries(entries, rootPrefix) {
17306
17313
  const metaprojectPrefix = `${rootPrefix}.metaproject/`;
@@ -17360,7 +17367,7 @@ async function committedChangedFiles(cwd, fromCommit, toCommit, rootPrefix) {
17360
17367
  return diff.split("\x00").filter((entry) => entry.length > 0 && !entry.startsWith(metaprojectPrefix));
17361
17368
  }
17362
17369
  async function checkGraphStaleness(cwd) {
17363
- const nodesStat = await stat8(nodesJsonlPath(cwd)).catch(() => null);
17370
+ const nodesStat = await stat9(nodesJsonlPath(cwd)).catch(() => null);
17364
17371
  if (!nodesStat) {
17365
17372
  return { status: "stale", reasons: ["graph has not been built yet (no nodes.jsonl)"] };
17366
17373
  }
@@ -17381,7 +17388,7 @@ async function checkGraphStaleness(cwd) {
17381
17388
  }
17382
17389
  } else {
17383
17390
  provenanceMissing = true;
17384
- const logsHeadStat = await stat8(path60.join(cwd, ".git", "logs", "HEAD")).catch(() => null);
17391
+ const logsHeadStat = await stat9(path61.join(cwd, ".git", "logs", "HEAD")).catch(() => null);
17385
17392
  if (logsHeadStat && logsHeadStat.mtimeMs > nodesStat.mtimeMs) {
17386
17393
  reasons.push("repo HEAD moved since the graph was built (no build provenance recorded; inferred from .git/logs/HEAD)");
17387
17394
  }
@@ -17410,7 +17417,7 @@ async function checkGraphStaleness(cwd) {
17410
17417
  if (projectRelative === null) {
17411
17418
  continue;
17412
17419
  }
17413
- const fileStat = await stat8(path60.join(cwd, projectRelative)).catch(() => null);
17420
+ const fileStat = await stat9(path61.join(cwd, projectRelative)).catch(() => null);
17414
17421
  if (fileStat && fileStat.mtimeMs > nodesStat.mtimeMs) {
17415
17422
  postBuildEdits.push(displayPath);
17416
17423
  }
@@ -17420,7 +17427,7 @@ async function checkGraphStaleness(cwd) {
17420
17427
  }
17421
17428
  }
17422
17429
  }
17423
- const configStat = await stat8(gdgraphConfigPath2(cwd)).catch(() => null);
17430
+ const configStat = await stat9(gdgraphConfigPath2(cwd)).catch(() => null);
17424
17431
  if (configStat && configStat.mtimeMs > nodesStat.mtimeMs) {
17425
17432
  reasons.push("gdgraph.config.json changed since the graph was built");
17426
17433
  }
@@ -17545,19 +17552,19 @@ var init_types3 = __esm(() => {
17545
17552
  });
17546
17553
 
17547
17554
  // src/wiki/collect.ts
17548
- import { readFile as readFile29, readdir as readdir11 } from "fs/promises";
17549
- import path61 from "path";
17555
+ import { readFile as readFile30, readdir as readdir12 } from "fs/promises";
17556
+ import path62 from "path";
17550
17557
  function wikiRootPath(cwd) {
17551
- return path61.join(cwd, ".metaproject", "wiki");
17558
+ return path62.join(cwd, ".metaproject", "wiki");
17552
17559
  }
17553
17560
  async function collectPages(cwd) {
17554
17561
  const root = wikiRootPath(cwd);
17555
17562
  const pages = [];
17556
17563
  for (const { type, folder } of WIKI_PAGE_TYPES) {
17557
- const dir = path61.join(root, folder);
17564
+ const dir = path62.join(root, folder);
17558
17565
  let names;
17559
17566
  try {
17560
- names = await readdir11(dir);
17567
+ names = await readdir12(dir);
17561
17568
  } catch (error) {
17562
17569
  if (isNotFound(error)) {
17563
17570
  continue;
@@ -17569,10 +17576,10 @@ async function collectPages(cwd) {
17569
17576
  if (!entry.endsWith(".md")) {
17570
17577
  continue;
17571
17578
  }
17572
- const absolutePath = path61.join(dir, entry);
17579
+ const absolutePath = path62.join(dir, entry);
17573
17580
  let content;
17574
17581
  try {
17575
- content = await readFile29(absolutePath, "utf8");
17582
+ content = await readFile30(absolutePath, "utf8");
17576
17583
  } catch (error) {
17577
17584
  const message = error instanceof Error ? error.message : String(error);
17578
17585
  throw new WikiCollectionError(absolutePath, `the wiki store could not be read (${message}). This is not the same as "no pages": ` + `${absolutePath} exists but could not be read.`);
@@ -18379,7 +18386,7 @@ var init_section_index = __esm(() => {
18379
18386
  });
18380
18387
 
18381
18388
  // src/security/guard.ts
18382
- import path62 from "path";
18389
+ import path63 from "path";
18383
18390
  function prepareOutputForPersistence(guard, original) {
18384
18391
  if (!guard.allowed) {
18385
18392
  return { allowed: false, reason: guard.reason ?? "security gate blocked" };
@@ -18397,7 +18404,7 @@ function prepareOutputForPersistence(guard, original) {
18397
18404
  };
18398
18405
  }
18399
18406
  async function resolveManifestSecurityState(cwd) {
18400
- const manifestPath = path62.join(securityProjectRoot(cwd), ".metaproject", "metaproject.json");
18407
+ const manifestPath = path63.join(securityProjectRoot(cwd), ".metaproject", "metaproject.json");
18401
18408
  if (!await pathExists(manifestPath)) {
18402
18409
  return { enabled: false, manifestUnreadable: false };
18403
18410
  }
@@ -18603,10 +18610,10 @@ var MEMORY_EMBEDDING_ID = "memory.embedding", DEFAULT_EMBED_DIMS = 96;
18603
18610
 
18604
18611
  // src/memory/embedding/index.ts
18605
18612
  import { createHash as createHash10 } from "crypto";
18606
- import { mkdir as mkdir15, readFile as readFile30, writeFile as writeFile9 } from "fs/promises";
18607
- import path63 from "path";
18613
+ import { mkdir as mkdir15, readFile as readFile31, writeFile as writeFile9 } from "fs/promises";
18614
+ import path64 from "path";
18608
18615
  function embeddingsDir(cwd) {
18609
- return path63.join(cwd, ".metaproject", "data", "memory", "embeddings");
18616
+ return path64.join(cwd, ".metaproject", "data", "memory", "embeddings");
18610
18617
  }
18611
18618
  function entryText(entry) {
18612
18619
  return `${entry.title}
@@ -18635,24 +18642,24 @@ async function buildEmbeddingIndex(cwd, entries, embedder, model, now) {
18635
18642
  };
18636
18643
  const dir = embeddingsDir(cwd);
18637
18644
  await mkdir15(dir, { recursive: true });
18638
- await writeFile9(path63.join(dir, "index.meta.json"), `${JSON.stringify(meta, null, 2)}
18645
+ await writeFile9(path64.join(dir, "index.meta.json"), `${JSON.stringify(meta, null, 2)}
18639
18646
  `, "utf8");
18640
- await writeFile9(path63.join(dir, "vectors.jsonl"), records.map((record) => JSON.stringify(record)).join(`
18647
+ await writeFile9(path64.join(dir, "vectors.jsonl"), records.map((record) => JSON.stringify(record)).join(`
18641
18648
  `) + (records.length > 0 ? `
18642
18649
  ` : ""), "utf8");
18643
18650
  return toIndex(meta, records);
18644
18651
  }
18645
18652
  async function loadEmbeddingIndex(cwd) {
18646
18653
  const dir = embeddingsDir(cwd);
18647
- const metaPath = path63.join(dir, "index.meta.json");
18648
- const vectorsPath = path63.join(dir, "vectors.jsonl");
18654
+ const metaPath = path64.join(dir, "index.meta.json");
18655
+ const vectorsPath = path64.join(dir, "vectors.jsonl");
18649
18656
  if (!await pathExists(metaPath) || !await pathExists(vectorsPath)) {
18650
18657
  return null;
18651
18658
  }
18652
18659
  try {
18653
- const meta = JSON.parse(await readFile30(metaPath, "utf8"));
18660
+ const meta = JSON.parse(await readFile31(metaPath, "utf8"));
18654
18661
  const records = [];
18655
- for (const line of (await readFile30(vectorsPath, "utf8")).split(`
18662
+ for (const line of (await readFile31(vectorsPath, "utf8")).split(`
18656
18663
  `)) {
18657
18664
  if (line.trim().length === 0) {
18658
18665
  continue;
@@ -18726,10 +18733,10 @@ var init_embedding = __esm(() => {
18726
18733
  });
18727
18734
 
18728
18735
  // src/wiki/section-tombstone.ts
18729
- import path64 from "path";
18730
- import { stat as stat9 } from "fs/promises";
18736
+ import path65 from "path";
18737
+ import { stat as stat10 } from "fs/promises";
18731
18738
  function sectionRegistryPath(cwd) {
18732
- return path64.join(cwd, ".metaproject", "wiki", ".sections.json");
18739
+ return path65.join(cwd, ".metaproject", "wiki", ".sections.json");
18733
18740
  }
18734
18741
  function emptySectionRegistry() {
18735
18742
  return { version: SECTION_REGISTRY_VERSION, entries: [], tombstones: [], lifted: [] };
@@ -18810,7 +18817,7 @@ function parseLifted(value) {
18810
18817
  async function readSectionRegistryState(cwd) {
18811
18818
  const file = sectionRegistryPath(cwd);
18812
18819
  try {
18813
- await stat9(file);
18820
+ await stat10(file);
18814
18821
  } catch (error) {
18815
18822
  if (isNotFound(error)) {
18816
18823
  return { state: "absent", path: file };
@@ -19030,11 +19037,11 @@ var init_section_tombstone = __esm(() => {
19030
19037
  });
19031
19038
 
19032
19039
  // src/memory/cross-layer.ts
19033
- import { readFile as readFile31 } from "fs/promises";
19034
- import path65 from "path";
19040
+ import { readFile as readFile32 } from "fs/promises";
19041
+ import path66 from "path";
19035
19042
  function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wikiRoot) {
19036
19043
  const references = [];
19037
- const entryDir = path65.dirname(entryAbsolutePath);
19044
+ const entryDir = path66.dirname(entryAbsolutePath);
19038
19045
  const lines = content.split(`
19039
19046
  `);
19040
19047
  for (let index = 0;index < lines.length; index += 1) {
@@ -19049,16 +19056,16 @@ function extractWikiReferences(entryRelativePath, entryAbsolutePath, content, wi
19049
19056
  if (withoutAnchor.length === 0) {
19050
19057
  continue;
19051
19058
  }
19052
- const absolute = path65.resolve(entryDir, withoutAnchor);
19053
- const relativeToWiki = path65.relative(wikiRoot, absolute);
19054
- if (relativeToWiki.startsWith("..") || path65.isAbsolute(relativeToWiki)) {
19059
+ const absolute = path66.resolve(entryDir, withoutAnchor);
19060
+ const relativeToWiki = path66.relative(wikiRoot, absolute);
19061
+ if (relativeToWiki.startsWith("..") || path66.isAbsolute(relativeToWiki)) {
19055
19062
  continue;
19056
19063
  }
19057
19064
  references.push({
19058
19065
  entry: entryRelativePath,
19059
19066
  kind: "page-path",
19060
19067
  raw: href,
19061
- target: relativeToWiki.split(path65.sep).join("/"),
19068
+ target: relativeToWiki.split(path66.sep).join("/"),
19062
19069
  line
19063
19070
  });
19064
19071
  }
@@ -19078,11 +19085,11 @@ function isDangling(finding) {
19078
19085
  return finding.state !== "intact";
19079
19086
  }
19080
19087
  async function loadWikiKnowledgeView(cwd) {
19081
- const wikiRoot = path65.join(cwd, ".metaproject", "wiki");
19088
+ const wikiRoot = path66.join(cwd, ".metaproject", "wiki");
19082
19089
  const pages = await collectPages(cwd);
19083
19090
  const index = buildSectionIndex(await Promise.all(pages.map(async (page) => ({
19084
19091
  page,
19085
- content: await readFile31(page.absolutePath, "utf8").catch(() => "")
19092
+ content: await readFile32(page.absolutePath, "utf8").catch(() => "")
19086
19093
  }))));
19087
19094
  return {
19088
19095
  index,
@@ -19195,7 +19202,7 @@ async function checkMemoryCrossLayer(cwd, entries, view) {
19195
19202
  const resolved = view ?? await loadWikiKnowledgeView(cwd);
19196
19203
  const findings = [];
19197
19204
  for (const entry of entries) {
19198
- const content = await readFile31(entry.absolutePath, "utf8").catch(() => null);
19205
+ const content = await readFile32(entry.absolutePath, "utf8").catch(() => null);
19199
19206
  if (content === null) {
19200
19207
  findings.push({
19201
19208
  reference: {
@@ -19296,7 +19303,7 @@ function round2(value) {
19296
19303
  var init_dedup = () => {};
19297
19304
 
19298
19305
  // src/memory/check.ts
19299
- import path66 from "path";
19306
+ import path67 from "path";
19300
19307
  async function checkMemory(cwd, config) {
19301
19308
  const entries = await collectEntries(cwd);
19302
19309
  const issues = [];
@@ -19312,7 +19319,7 @@ async function checkMemory(cwd, config) {
19312
19319
  }
19313
19320
  for (const file of entry.scopes.files) {
19314
19321
  const clean = file.replace(/^`|`$/g, "");
19315
- if (!await pathExists(path66.resolve(cwd, clean))) {
19322
+ if (!await pathExists(path67.resolve(cwd, clean))) {
19316
19323
  issues.push({ path: entry.relativePath, kind: "link", message: `related file not found: ${clean}` });
19317
19324
  }
19318
19325
  }
@@ -19366,13 +19373,13 @@ var init_check = __esm(() => {
19366
19373
  });
19367
19374
 
19368
19375
  // src/memory/write.ts
19369
- import { mkdir as mkdir16, open as open2, readFile as readFile32, rename as rename5, rm as rm4, writeFile as writeFile10 } from "fs/promises";
19370
- import path67 from "path";
19376
+ import { mkdir as mkdir16, open as open2, readFile as readFile33, rename as rename5, rm as rm4, writeFile as writeFile10 } from "fs/promises";
19377
+ import path68 from "path";
19371
19378
  async function resolveCanonicalEntryPath(cwd, relativePath) {
19372
- const root = path67.resolve(memoryRoot(cwd));
19373
- const absolutePath = path67.resolve(root, relativePath);
19374
- const normalized = toPosix2(path67.relative(root, absolutePath));
19375
- if (!normalized || normalized.startsWith("../") || path67.isAbsolute(normalized) || !normalized.endsWith(".md")) {
19379
+ const root = path68.resolve(memoryRoot(cwd));
19380
+ const absolutePath = path68.resolve(root, relativePath);
19381
+ const normalized = toPosix2(path68.relative(root, absolutePath));
19382
+ if (!normalized || normalized.startsWith("../") || path68.isAbsolute(normalized) || !normalized.endsWith(".md")) {
19376
19383
  return null;
19377
19384
  }
19378
19385
  return { absolutePath, relativePath: normalized };
@@ -19407,7 +19414,7 @@ async function writeCanonicalPair(input) {
19407
19414
  return asPair(secondGuard.result, [first.value.relativePath]);
19408
19415
  const prepared = [firstGuard.value, secondGuard.value];
19409
19416
  const warnings = prepared.flatMap((entry) => entry.warnings);
19410
- const [originalFirst, originalSecond] = await Promise.all(prepared.map((entry) => readFile32(entry.absolutePath, "utf8")));
19417
+ const [originalFirst, originalSecond] = await Promise.all(prepared.map((entry) => readFile33(entry.absolutePath, "utf8")));
19411
19418
  try {
19412
19419
  await replaceAtomically(prepared[0].absolutePath, prepared[0].content);
19413
19420
  if (input.failReplaceAt === 2)
@@ -19468,9 +19475,9 @@ function validateNextEntry(relativePath, content) {
19468
19475
  return null;
19469
19476
  }
19470
19477
  async function replaceAtomically(target, content) {
19471
- const dir = path67.dirname(target);
19478
+ const dir = path68.dirname(target);
19472
19479
  await mkdir16(dir, { recursive: true });
19473
- const tmp = path67.join(dir, `.${path67.basename(target)}.keryx-tmp-${process.pid}-${Math.random().toString(16).slice(2)}`);
19480
+ const tmp = path68.join(dir, `.${path68.basename(target)}.keryx-tmp-${process.pid}-${Math.random().toString(16).slice(2)}`);
19474
19481
  try {
19475
19482
  await writeFile10(tmp, content, "utf8");
19476
19483
  const file = await open2(tmp, "r");
@@ -19506,7 +19513,7 @@ function header(content, name) {
19506
19513
  return content.match(new RegExp(`^${name}:\\s*(.+)$`, "mi"))?.[1]?.trim() ?? null;
19507
19514
  }
19508
19515
  function toPosix2(value) {
19509
- return value.split(path67.sep).join("/");
19516
+ return value.split(path68.sep).join("/");
19510
19517
  }
19511
19518
  function message(cause) {
19512
19519
  return cause instanceof Error ? cause.message : String(cause);
@@ -19519,14 +19526,14 @@ var init_write = __esm(() => {
19519
19526
 
19520
19527
  // src/memory/ingest.ts
19521
19528
  import { existsSync as existsSync6 } from "fs";
19522
- import { readFile as readFile33 } from "fs/promises";
19523
- import path68 from "path";
19529
+ import { readFile as readFile34 } from "fs/promises";
19530
+ import path69 from "path";
19524
19531
  async function ingestMemory(cwd, source, filePath, config, now) {
19525
- const absolute = path68.resolve(cwd, filePath);
19532
+ const absolute = path69.resolve(cwd, filePath);
19526
19533
  if (!await pathExists(absolute)) {
19527
19534
  throw new Error(`Ingest source not found: ${filePath}`);
19528
19535
  }
19529
- const content = await readFile33(absolute, "utf8");
19536
+ const content = await readFile34(absolute, "utf8");
19530
19537
  const candidates = extractCandidates2(content);
19531
19538
  const type = SOURCE_TYPE[source] ?? "lesson";
19532
19539
  const confidence = SOURCE_CONFIDENCE[source] ?? "low";
@@ -19539,8 +19546,8 @@ async function ingestMemory(cwd, source, filePath, config, now) {
19539
19546
  const securityWarnings = [];
19540
19547
  const securitySkipped = [];
19541
19548
  let skippedDuplicates = 0;
19542
- const dir = path68.join(memoryRoot(cwd), folder);
19543
- const link = path68.relative(cwd, absolute);
19549
+ const dir = path69.join(memoryRoot(cwd), folder);
19550
+ const link = path69.relative(cwd, absolute);
19544
19551
  const date = dateString(now);
19545
19552
  for (const text of candidates) {
19546
19553
  const title = toTitle(text);
@@ -19606,7 +19613,7 @@ async function ingestMemory(cwd, source, filePath, config, now) {
19606
19613
  return result;
19607
19614
  }
19608
19615
  async function reconcileEntry(cwd, relativePath, absolutePath, source, link, date) {
19609
- const content = await readFile33(absolutePath, "utf8");
19616
+ const content = await readFile34(absolutePath, "utf8");
19610
19617
  const note = `- Reconciled: ${source} ${date}${link ? ` (${link})` : ""}`;
19611
19618
  if (content.includes(note)) {
19612
19619
  return { changed: false };
@@ -19721,7 +19728,7 @@ function uniqueSlug(dir, title) {
19721
19728
  const base = slugify2(title) || "entry";
19722
19729
  let slug = base;
19723
19730
  let counter = 2;
19724
- while (existsSync6(path68.join(dir, `${slug}.md`))) {
19731
+ while (existsSync6(path69.join(dir, `${slug}.md`))) {
19725
19732
  slug = `${base}-${counter}`;
19726
19733
  counter += 1;
19727
19734
  }
@@ -19755,8 +19762,8 @@ var init_ingest = __esm(() => {
19755
19762
  });
19756
19763
 
19757
19764
  // src/memory/supersede.ts
19758
- import { readFile as readFile34 } from "fs/promises";
19759
- import path69 from "path";
19765
+ import { readFile as readFile35 } from "fs/promises";
19766
+ import path70 from "path";
19760
19767
  async function supersedeEntry(input, now) {
19761
19768
  const date = input.date ?? now.toISOString().slice(0, 10);
19762
19769
  const today = now.toISOString().slice(0, 10);
@@ -19768,8 +19775,8 @@ async function supersedeEntry(input, now) {
19768
19775
  if (!newResolved) {
19769
19776
  throw new Error(`Superseding entry not found: ${input.newPath}`);
19770
19777
  }
19771
- const oldContent = await readFile34(oldResolved.absolute, "utf8");
19772
- const newContent = await readFile34(newResolved.absolute, "utf8");
19778
+ const oldContent = await readFile35(oldResolved.absolute, "utf8");
19779
+ const newContent = await readFile35(newResolved.absolute, "utf8");
19773
19780
  if (headerValue(oldContent, "Superseded-By") === newResolved.relative && headerValue(newContent, "Supersedes") === oldResolved.relative) {
19774
19781
  return {
19775
19782
  superseded: oldResolved.relative,
@@ -19816,12 +19823,12 @@ async function supersedeEntry(input, now) {
19816
19823
  async function resolveEntryPath(cwd, raw) {
19817
19824
  const root = memoryRoot(cwd);
19818
19825
  const candidates = [
19819
- path69.resolve(cwd, raw),
19820
- path69.resolve(root, raw),
19821
- path69.isAbsolute(raw) ? raw : path69.join(cwd, raw)
19826
+ path70.resolve(cwd, raw),
19827
+ path70.resolve(root, raw),
19828
+ path70.isAbsolute(raw) ? raw : path70.join(cwd, raw)
19822
19829
  ];
19823
19830
  for (const absolute of candidates) {
19824
- const confined = await resolveCanonicalEntryPath(cwd, path69.relative(root, absolute));
19831
+ const confined = await resolveCanonicalEntryPath(cwd, path70.relative(root, absolute));
19825
19832
  if (confined && await pathExists(confined.absolutePath)) {
19826
19833
  return { absolute: confined.absolutePath, relative: confined.relativePath };
19827
19834
  }
@@ -20016,10 +20023,10 @@ __export(exports_service3, {
20016
20023
  selectHandoffEntries: () => selectHandoffEntries
20017
20024
  });
20018
20025
  import { createHash as createHash11 } from "crypto";
20019
- import { mkdir as mkdir17, readFile as readFile35, writeFile as writeFile11 } from "fs/promises";
20020
- import path70 from "path";
20026
+ import { mkdir as mkdir17, readFile as readFile36, writeFile as writeFile11 } from "fs/promises";
20027
+ import path71 from "path";
20021
20028
  function dataRoot2(cwd) {
20022
- return path70.join(cwd, ".metaproject", "data", "memory");
20029
+ return path71.join(cwd, ".metaproject", "data", "memory");
20023
20030
  }
20024
20031
  function createMemoryService() {
20025
20032
  const reportStore = createMemoryReportStore();
@@ -20034,9 +20041,9 @@ function createMemoryService() {
20034
20041
  if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) {
20035
20042
  throw new Error(`Invalid slug: ${slug}. Use lowercase letters, digits, and hyphens.`);
20036
20043
  }
20037
- const dir = path70.join(memoryRoot(input.cwd), typeConfig.folder);
20038
- const filePath = path70.join(dir, `${slug}.md`);
20039
- const relativePath = path70.relative(input.cwd, filePath);
20044
+ const dir = path71.join(memoryRoot(input.cwd), typeConfig.folder);
20045
+ const filePath = path71.join(dir, `${slug}.md`);
20046
+ const relativePath = path71.relative(input.cwd, filePath);
20040
20047
  if (await pathExists(filePath) && !input.force) {
20041
20048
  throw new Error(`Entry already exists: ${relativePath}. Use --force to overwrite.`);
20042
20049
  }
@@ -20067,9 +20074,9 @@ function createMemoryService() {
20067
20074
  async index(input) {
20068
20075
  const entries = await collectEntries(input.cwd);
20069
20076
  const generatedAt = new Date().toISOString();
20070
- const indexDir = path70.join(dataRoot2(input.cwd), "index");
20077
+ const indexDir = path71.join(dataRoot2(input.cwd), "index");
20071
20078
  await mkdir17(indexDir, { recursive: true });
20072
- const indexPath = path70.join(indexDir, "index.json");
20079
+ const indexPath = path71.join(indexDir, "index.json");
20073
20080
  await writeFile11(indexPath, `${JSON.stringify({
20074
20081
  catalogVersion: 1,
20075
20082
  sourceFingerprint: createHash11("sha256").update(JSON.stringify(entries.map((e) => ({
@@ -20090,7 +20097,7 @@ function createMemoryService() {
20090
20097
  }, null, 2)}
20091
20098
  `, "utf8");
20092
20099
  const result = {
20093
- path: path70.relative(input.cwd, indexPath),
20100
+ path: path71.relative(input.cwd, indexPath),
20094
20101
  entryCount: entries.length,
20095
20102
  generatedAt
20096
20103
  };
@@ -20103,7 +20110,7 @@ function createMemoryService() {
20103
20110
  const built = await buildEmbeddingIndex(input.cwd, entries, embedder.embed, embedder.model, new Date);
20104
20111
  result.embeddings = {
20105
20112
  built: true,
20106
- path: path70.relative(input.cwd, embeddingsDir(input.cwd)),
20113
+ path: path71.relative(input.cwd, embeddingsDir(input.cwd)),
20107
20114
  vectorCount: built.meta.entryCount,
20108
20115
  model: built.meta.model
20109
20116
  };
@@ -20143,7 +20150,7 @@ function createMemoryService() {
20143
20150
  }
20144
20151
  let content;
20145
20152
  try {
20146
- content = await readFile35(resolved.absolutePath, "utf8");
20153
+ content = await readFile36(resolved.absolutePath, "utf8");
20147
20154
  } catch {
20148
20155
  return { path: resolved.relativePath, from: "draft", to: input.to, changed: false, error: { code: "not-found", message: `Memory entry not found: ${resolved.relativePath}` } };
20149
20156
  }
@@ -20334,7 +20341,7 @@ var init_service3 = __esm(() => {
20334
20341
  });
20335
20342
 
20336
20343
  // src/wiki/ask.ts
20337
- import { readFile as readFile36 } from "fs/promises";
20344
+ import { readFile as readFile37 } from "fs/promises";
20338
20345
  async function wikiAsk(input) {
20339
20346
  const k = input.k && input.k > 0 ? input.k : DEFAULT_K;
20340
20347
  const asOf = input.asOf ? validateAsOf(input.asOf, new Date) : undefined;
@@ -20501,7 +20508,7 @@ async function wikiCandidates(cwd, observedAt, historicalMode, asOf) {
20501
20508
  }
20502
20509
  const index = buildSectionIndex(await Promise.all(admitted.map(async (page) => ({
20503
20510
  page,
20504
- content: await readFile36(page.absolutePath, "utf8").catch(() => "")
20511
+ content: await readFile37(page.absolutePath, "utf8").catch(() => "")
20505
20512
  }))));
20506
20513
  const result = [];
20507
20514
  for (const section of index.sections) {
@@ -20705,7 +20712,7 @@ var init_ask = __esm(() => {
20705
20712
  });
20706
20713
 
20707
20714
  // src/wiki/backlinks.ts
20708
- import path71 from "path";
20715
+ import path72 from "path";
20709
20716
  function extractCodePaths(content) {
20710
20717
  const out = [];
20711
20718
  let match;
@@ -20735,8 +20742,8 @@ function resolveLink(fromRepoPath, raw) {
20735
20742
  const clean = (raw.split("#")[0] ?? "").trim();
20736
20743
  if (!clean)
20737
20744
  return "";
20738
- const fromDir = path71.posix.dirname(fromRepoPath.split(path71.sep).join("/"));
20739
- return path71.posix.normalize(path71.posix.join(fromDir, clean));
20745
+ const fromDir = path72.posix.dirname(fromRepoPath.split(path72.sep).join("/"));
20746
+ return path72.posix.normalize(path72.posix.join(fromDir, clean));
20740
20747
  }
20741
20748
  function buildBacklinkIndex(pages) {
20742
20749
  const index = new Map;
@@ -20750,18 +20757,18 @@ function buildBacklinkIndex(pages) {
20750
20757
  }
20751
20758
  };
20752
20759
  for (const page of pages) {
20753
- const from = page.repoPath.split(path71.sep).join("/");
20760
+ const from = page.repoPath.split(path72.sep).join("/");
20754
20761
  for (const raw of extractLinks(page.content))
20755
20762
  add(resolveLink(from, raw), from);
20756
20763
  for (const raw of extractCodePaths(page.content))
20757
- add(path71.posix.normalize(raw), from);
20764
+ add(path72.posix.normalize(raw), from);
20758
20765
  }
20759
20766
  for (const list of index.values())
20760
20767
  list.sort();
20761
20768
  return index;
20762
20769
  }
20763
20770
  function backlinksFor(index, targetRepoPath) {
20764
- const key = path71.posix.normalize(targetRepoPath.split(path71.sep).join("/"));
20771
+ const key = path72.posix.normalize(targetRepoPath.split(path72.sep).join("/"));
20765
20772
  return index.get(key) ?? [];
20766
20773
  }
20767
20774
  var LINK, CODE_SPAN, FILE_LIKE;
@@ -20774,7 +20781,7 @@ var init_backlinks = __esm(() => {
20774
20781
  // src/ctx/assembly.ts
20775
20782
  import { createHash as createHash12 } from "crypto";
20776
20783
  import { mkdir as mkdir18, rename as rename6, writeFile as writeFile12 } from "fs/promises";
20777
- import path72 from "path";
20784
+ import path73 from "path";
20778
20785
  function assembleContext(input) {
20779
20786
  let items = 0;
20780
20787
  let tokens = 0;
@@ -20818,9 +20825,9 @@ async function recordNoContentContext(input) {
20818
20825
  return assembly;
20819
20826
  }
20820
20827
  async function recordContextAssembly(input) {
20821
- const directory = path72.join(input.workspaceRoot, ".metaproject", "context-operations", "traces");
20828
+ const directory = path73.join(input.workspaceRoot, ".metaproject", "context-operations", "traces");
20822
20829
  await mkdir18(directory, { recursive: true });
20823
- const target = path72.join(directory, path72.basename(input.assembly.traceRef));
20830
+ const target = path73.join(directory, path73.basename(input.assembly.traceRef));
20824
20831
  const temporary = `${target}.${process.pid}.tmp`;
20825
20832
  await writeFile12(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 })}
20826
20833
  `, { mode: 384 });
@@ -21670,16 +21677,16 @@ __export(exports_service4, {
21670
21677
  });
21671
21678
  import { spawn as spawn3 } from "child_process";
21672
21679
  import { createHash as createHash14 } from "crypto";
21673
- import { mkdir as mkdir19, readFile as readFile37, readdir as readdir12, rm as rm5, writeFile as writeFile13 } from "fs/promises";
21674
- import path73 from "path";
21680
+ import { mkdir as mkdir19, readFile as readFile38, readdir as readdir13, rm as rm5, writeFile as writeFile13 } from "fs/promises";
21681
+ import path74 from "path";
21675
21682
  function wikiRootPath2(cwd) {
21676
- return path73.join(cwd, ".metaproject", "wiki");
21683
+ return path74.join(cwd, ".metaproject", "wiki");
21677
21684
  }
21678
21685
  function dataRootPath(cwd) {
21679
- return path73.join(cwd, ".metaproject", "data", "gdwiki");
21686
+ return path74.join(cwd, ".metaproject", "data", "gdwiki");
21680
21687
  }
21681
21688
  function linkCheckReportPath(cwd) {
21682
- return path73.join(dataRootPath(cwd), "link-check", "latest.md");
21689
+ return path74.join(dataRootPath(cwd), "link-check", "latest.md");
21683
21690
  }
21684
21691
  async function wikiStatus(cwd) {
21685
21692
  const root = wikiRootPath2(cwd);
@@ -21687,7 +21694,7 @@ async function wikiStatus(cwd) {
21687
21694
  const pages = enabled ? await collectPages(cwd) : [];
21688
21695
  return {
21689
21696
  enabled,
21690
- wikiRoot: path73.relative(cwd, root),
21697
+ wikiRoot: path74.relative(cwd, root),
21691
21698
  totalPages: pages.length,
21692
21699
  countsByType: WIKI_PAGE_TYPES.map(({ type }) => ({
21693
21700
  type,
@@ -21702,7 +21709,7 @@ async function findPagesWithThinkTags(pages) {
21702
21709
  const flagged = [];
21703
21710
  for (const page of pages) {
21704
21711
  try {
21705
- const content = await readFile37(page.absolutePath, "utf8");
21712
+ const content = await readFile38(page.absolutePath, "utf8");
21706
21713
  if (containsThinkTags(content)) {
21707
21714
  flagged.push(page.relativePath);
21708
21715
  }
@@ -21718,9 +21725,9 @@ async function wikiCreatePage(input) {
21718
21725
  if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
21719
21726
  throw new Error(`Invalid slug: ${input.slug}. Use lowercase letters, digits, and hyphens.`);
21720
21727
  }
21721
- const dir = path73.join(wikiRootPath2(input.cwd), typeConfig.folder);
21722
- const filePath = path73.join(dir, `${input.slug}.md`);
21723
- const relativePath = path73.relative(input.cwd, filePath);
21728
+ const dir = path74.join(wikiRootPath2(input.cwd), typeConfig.folder);
21729
+ const filePath = path74.join(dir, `${input.slug}.md`);
21730
+ const relativePath = path74.relative(input.cwd, filePath);
21724
21731
  if (await pathExists(filePath) && !input.force) {
21725
21732
  throw new Error(`Page already exists: ${relativePath}. Use --force to overwrite.`);
21726
21733
  }
@@ -21731,13 +21738,13 @@ async function wikiCreatePage(input) {
21731
21738
  }
21732
21739
  async function wikiGenerateIndex(cwd) {
21733
21740
  const root = wikiRootPath2(cwd);
21734
- const indexPath = path73.join(root, "index.md");
21741
+ const indexPath = path74.join(root, "index.md");
21735
21742
  const pages = await collectPages(cwd);
21736
21743
  const generatedAt = new Date().toISOString();
21737
21744
  const managedBlock = `${WIKI_INDEX_BEGIN}
21738
21745
  ${renderIndexBody(pages, generatedAt)}
21739
21746
  ${WIKI_INDEX_END}`;
21740
- const existing = await pathExists(indexPath) ? await readFile37(indexPath, "utf8") : renderWikiIndexScaffold();
21747
+ const existing = await pathExists(indexPath) ? await readFile38(indexPath, "utf8") : renderWikiIndexScaffold();
21741
21748
  const pattern = new RegExp(`${escapeRegExp3(WIKI_INDEX_BEGIN)}[\\s\\S]*?${escapeRegExp3(WIKI_INDEX_END)}`);
21742
21749
  const replaced = pattern.test(existing) ? existing.replace(pattern, managedBlock) : `${existing.trimEnd()}
21743
21750
 
@@ -21749,7 +21756,7 @@ ${managedBlock}
21749
21756
  await mkdir19(root, { recursive: true });
21750
21757
  await writeFile13(indexPath, next, "utf8");
21751
21758
  return {
21752
- path: path73.relative(cwd, indexPath),
21759
+ path: path74.relative(cwd, indexPath),
21753
21760
  pageCount: pages.length,
21754
21761
  generatedAt
21755
21762
  };
@@ -21757,13 +21764,13 @@ ${managedBlock}
21757
21764
  async function wikiCheckLinks(cwd) {
21758
21765
  const root = wikiRootPath2(cwd);
21759
21766
  const allFiles = await pathExists(root) ? await walkMarkdown(root) : [];
21760
- const files = allFiles.filter((absolutePath) => !path73.relative(root, absolutePath).startsWith(`templates${path73.sep}`));
21767
+ const files = allFiles.filter((absolutePath) => !path74.relative(root, absolutePath).startsWith(`templates${path74.sep}`));
21761
21768
  const broken = [];
21762
21769
  let checkedLinks = 0;
21763
21770
  let skippedExternal = 0;
21764
21771
  for (const absolutePath of files) {
21765
- const content = await readFile37(absolutePath, "utf8");
21766
- const pageRelative = path73.relative(cwd, absolutePath);
21772
+ const content = await readFile38(absolutePath, "utf8");
21773
+ const pageRelative = path74.relative(cwd, absolutePath);
21767
21774
  for (const target of extractLinkTargets(content)) {
21768
21775
  if (EXTERNAL_LINK.test(target)) {
21769
21776
  skippedExternal += 1;
@@ -21774,7 +21781,7 @@ async function wikiCheckLinks(cwd) {
21774
21781
  continue;
21775
21782
  }
21776
21783
  checkedLinks += 1;
21777
- const resolved = path73.resolve(path73.dirname(absolutePath), filePart);
21784
+ const resolved = path74.resolve(path74.dirname(absolutePath), filePart);
21778
21785
  if (!await pathExists(resolved)) {
21779
21786
  broken.push({
21780
21787
  page: pageRelative,
@@ -21786,7 +21793,7 @@ async function wikiCheckLinks(cwd) {
21786
21793
  }
21787
21794
  const generatedAt = new Date().toISOString();
21788
21795
  const reportPath = linkCheckReportPath(cwd);
21789
- await mkdir19(path73.dirname(reportPath), { recursive: true });
21796
+ await mkdir19(path74.dirname(reportPath), { recursive: true });
21790
21797
  await writeFile13(reportPath, renderLinkCheckReport({
21791
21798
  generatedAt,
21792
21799
  checkedPages: files.length,
@@ -21795,7 +21802,7 @@ async function wikiCheckLinks(cwd) {
21795
21802
  broken
21796
21803
  }), "utf8");
21797
21804
  return {
21798
- reportPath: path73.relative(cwd, reportPath),
21805
+ reportPath: path74.relative(cwd, reportPath),
21799
21806
  checkedPages: files.length,
21800
21807
  checkedLinks,
21801
21808
  skippedExternal,
@@ -21845,7 +21852,7 @@ async function wikiValidate(cwd) {
21845
21852
  }
21846
21853
  if (await isIndexStale(cwd, pages)) {
21847
21854
  issues.push({
21848
- page: path73.join(path73.relative(cwd, wikiRootPath2(cwd)), "index.md"),
21855
+ page: path74.join(path74.relative(cwd, wikiRootPath2(cwd)), "index.md"),
21849
21856
  kind: "index",
21850
21857
  message: "index out of date, run `keryx wiki index`"
21851
21858
  });
@@ -21882,7 +21889,7 @@ async function wikiCollect(input) {
21882
21889
  };
21883
21890
  }
21884
21891
  async function wikiPruneOrphans(cwd) {
21885
- const componentsDir = path73.join(wikiRootPath2(cwd), "components");
21892
+ const componentsDir = path74.join(wikiRootPath2(cwd), "components");
21886
21893
  if (!await pathExists(componentsDir)) {
21887
21894
  return { pruned: [], orphanedAccepted: [] };
21888
21895
  }
@@ -21891,7 +21898,7 @@ async function wikiPruneOrphans(cwd) {
21891
21898
  const validSlugs = new Set(candidates.filter((candidate) => candidate.type === "component").map((candidate) => candidate.slug));
21892
21899
  const pruned = [];
21893
21900
  const orphanedAccepted = [];
21894
- for (const entry of await readdir12(componentsDir)) {
21901
+ for (const entry of await readdir13(componentsDir)) {
21895
21902
  if (!entry.endsWith(".md")) {
21896
21903
  continue;
21897
21904
  }
@@ -21899,25 +21906,25 @@ async function wikiPruneOrphans(cwd) {
21899
21906
  if (validSlugs.has(slug)) {
21900
21907
  continue;
21901
21908
  }
21902
- const filePath = path73.join(componentsDir, entry);
21903
- const current = await readFile37(filePath, "utf8");
21909
+ const filePath = path74.join(componentsDir, entry);
21910
+ const current = await readFile38(filePath, "utf8");
21904
21911
  const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
21905
21912
  if (isUnmodifiedDraft) {
21906
21913
  await rm5(filePath);
21907
- pruned.push(path73.relative(cwd, filePath));
21914
+ pruned.push(path74.relative(cwd, filePath));
21908
21915
  } else {
21909
- orphanedAccepted.push(path73.relative(cwd, filePath));
21916
+ orphanedAccepted.push(path74.relative(cwd, filePath));
21910
21917
  }
21911
21918
  }
21912
21919
  return { pruned, orphanedAccepted };
21913
21920
  }
21914
21921
  async function validModuleNames(cwd) {
21915
- const nodesPath = path73.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
21922
+ const nodesPath = path74.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
21916
21923
  if (!await pathExists(nodesPath)) {
21917
21924
  return;
21918
21925
  }
21919
21926
  const modules = new Set;
21920
- for (const node of parseJsonl(await readFile37(nodesPath, "utf8"))) {
21927
+ for (const node of parseJsonl(await readFile38(nodesPath, "utf8"))) {
21921
21928
  if (node.kind === "asset")
21922
21929
  continue;
21923
21930
  const nodePath = String(node.path ?? node.id ?? "unknown");
@@ -21948,7 +21955,7 @@ async function wikiEvidence(input) {
21948
21955
  const pages = await collectPages(input.cwd);
21949
21956
  const index = buildSectionIndex(await Promise.all(pages.map(async (page) => ({
21950
21957
  page,
21951
- content: await readFile37(page.absolutePath, "utf8").catch(() => "")
21958
+ content: await readFile38(page.absolutePath, "utf8").catch(() => "")
21952
21959
  }))));
21953
21960
  const registry = await readSectionRegistryState(input.cwd);
21954
21961
  const pageStatus = {};
@@ -21982,9 +21989,9 @@ async function wikiEvidence(input) {
21982
21989
  });
21983
21990
  }
21984
21991
  function resolveEvidenceScope(cwd, override) {
21985
- const absolute = path73.resolve(cwd);
21992
+ const absolute = path74.resolve(cwd);
21986
21993
  return {
21987
- projectId: override?.projectId ?? (path73.basename(absolute) || "project"),
21994
+ projectId: override?.projectId ?? (path74.basename(absolute) || "project"),
21988
21995
  checkoutId: override?.checkoutId ?? `checkout:${createHash14("sha256").update(absolute).digest("hex").slice(0, 16)}`,
21989
21996
  ...override?.workspaceId ? { workspaceId: override.workspaceId } : {},
21990
21997
  ...override?.taskId ? { taskId: override.taskId } : {}
@@ -21999,7 +22006,7 @@ function isMachineAuthoredPage(pageType, relativePath, content) {
21999
22006
  if (source === null) {
22000
22007
  return false;
22001
22008
  }
22002
- const normalised = relativePath.split(path73.sep).join("/").replace(/^wiki\//, "");
22009
+ const normalised = relativePath.split(path74.sep).join("/").replace(/^wiki\//, "");
22003
22010
  return WIKI_PAGE_PRODUCERS.some((producer) => producer.source === source && producer.pageType === pageType && producer.path.test(normalised) && /^-[ \t]+Link:.*\bsha256\b/m.test(content));
22004
22011
  }
22005
22012
  function createGdWikiService() {
@@ -22015,8 +22022,8 @@ function createGdWikiService() {
22015
22022
  };
22016
22023
  }
22017
22024
  async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules) {
22018
- const nodesPath = path73.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
22019
- const edgesPath = path73.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
22025
+ const nodesPath = path74.join(cwd, ".metaproject", "data", "gdgraph", "storage", "nodes.jsonl");
22026
+ const edgesPath = path74.join(cwd, ".metaproject", "data", "gdgraph", "storage", "edges.jsonl");
22020
22027
  if (!await pathExists(nodesPath) || !await pathExists(edgesPath)) {
22021
22028
  return [];
22022
22029
  }
@@ -22025,7 +22032,7 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
22025
22032
  let nodes = 0;
22026
22033
  let files = 0;
22027
22034
  let assets = 0;
22028
- for (const node of parseJsonl(await readFile37(nodesPath, "utf8"))) {
22035
+ for (const node of parseJsonl(await readFile38(nodesPath, "utf8"))) {
22029
22036
  nodes += 1;
22030
22037
  const nodePath = String(node.path ?? node.id ?? "unknown");
22031
22038
  if (node.kind === "asset") {
@@ -22047,7 +22054,7 @@ async function collectGraphWikiCandidates(cwd, generatedAt, limit, onlyModules)
22047
22054
  let edges = 0;
22048
22055
  let imports = 0;
22049
22056
  let unresolved = 0;
22050
- for (const edge of parseJsonl(await readFile37(edgesPath, "utf8"))) {
22057
+ for (const edge of parseJsonl(await readFile38(edgesPath, "utf8"))) {
22051
22058
  edges += 1;
22052
22059
  const kind = String(edge.kind ?? "");
22053
22060
  if (kind === "unresolved") {
@@ -22200,12 +22207,12 @@ function topCounts(bucket, limit) {
22200
22207
  return [...bucket.entries()].sort((a, b) => b[1] - a[1]).slice(0, limit);
22201
22208
  }
22202
22209
  async function readModuleReadme(cwd, moduleName) {
22203
- const readmePath = path73.join(cwd, ...moduleName.split("/"), "README.md");
22210
+ const readmePath = path74.join(cwd, ...moduleName.split("/"), "README.md");
22204
22211
  if (!await pathExists(readmePath)) {
22205
22212
  return null;
22206
22213
  }
22207
22214
  try {
22208
- const content = await readFile37(readmePath, "utf8");
22215
+ const content = await readFile38(readmePath, "utf8");
22209
22216
  const paragraph = content.split(/\n\s*\n/).map((block) => block.trim()).find((block) => block.length > 0 && !block.startsWith("#"));
22210
22217
  if (!paragraph) {
22211
22218
  return null;
@@ -22221,12 +22228,12 @@ async function extractModuleExports(cwd, files) {
22221
22228
  const declRe = /export\s+(?:async\s+)?(?:default\s+)?(?:const|let|var|function|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/g;
22222
22229
  const braceRe = /export\s*\{([^}]+)\}/g;
22223
22230
  for (const file of files.slice(0, 4)) {
22224
- const filePath = path73.join(cwd, ...file.split("/"));
22231
+ const filePath = path74.join(cwd, ...file.split("/"));
22225
22232
  if (!await pathExists(filePath)) {
22226
22233
  continue;
22227
22234
  }
22228
22235
  try {
22229
- const content = (await readFile37(filePath, "utf8")).slice(0, 40000);
22236
+ const content = (await readFile38(filePath, "utf8")).slice(0, 40000);
22230
22237
  let match;
22231
22238
  while ((match = declRe.exec(content)) !== null) {
22232
22239
  if (match[1]) {
@@ -22252,14 +22259,14 @@ async function extractModuleExports(cwd, files) {
22252
22259
  }
22253
22260
  async function extractModuleApi(cwd, files) {
22254
22261
  const names = await extractModuleExports(cwd, files);
22255
- const symbolsPath = path73.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
22262
+ const symbolsPath = path74.join(cwd, ".metaproject", "data", "gdgraph", "storage", "symbols.jsonl");
22256
22263
  if (names.length === 0 || !await pathExists(symbolsPath)) {
22257
22264
  return names.map((name) => "`" + name + "`");
22258
22265
  }
22259
22266
  const fileSet = new Set(files);
22260
22267
  const kindByName = new Map;
22261
22268
  try {
22262
- for (const raw of parseJsonl(await readFile37(symbolsPath, "utf8"))) {
22269
+ for (const raw of parseJsonl(await readFile38(symbolsPath, "utf8"))) {
22263
22270
  const symbol = raw;
22264
22271
  if (!symbol.name || !symbol.path || symbol.container != null)
22265
22272
  continue;
@@ -22278,11 +22285,11 @@ async function extractModuleApi(cwd, files) {
22278
22285
  });
22279
22286
  }
22280
22287
  async function collectHealthWikiCandidates(cwd, generatedAt) {
22281
- const healthPath = path73.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
22288
+ const healthPath = path74.join(cwd, ".metaproject", "data", "health", "artifacts", "latest.json");
22282
22289
  if (!await pathExists(healthPath)) {
22283
22290
  return [];
22284
22291
  }
22285
- const report = JSON.parse(await readFile37(healthPath, "utf8"));
22292
+ const report = JSON.parse(await readFile38(healthPath, "utf8"));
22286
22293
  const metrics = Array.isArray(report.metrics) ? report.metrics : [];
22287
22294
  const project = metrics.find((metric) => metric.key === "project") ?? {};
22288
22295
  const counts = project.findingCounts ?? {};
@@ -22320,11 +22327,11 @@ async function collectHealthWikiCandidates(cwd, generatedAt) {
22320
22327
  }];
22321
22328
  }
22322
22329
  async function collectTestingWikiCandidates(cwd, generatedAt) {
22323
- const contextPath = path73.join(cwd, ".metaproject", "data", "testing", "context.md");
22330
+ const contextPath = path74.join(cwd, ".metaproject", "data", "testing", "context.md");
22324
22331
  if (!await pathExists(contextPath)) {
22325
22332
  return [];
22326
22333
  }
22327
- const context = await readFile37(contextPath, "utf8");
22334
+ const context = await readFile38(contextPath, "utf8");
22328
22335
  const summary = firstMeaningfulLine(context) ?? "Generated from testing context.";
22329
22336
  return [{
22330
22337
  type: "architecture",
@@ -22351,14 +22358,14 @@ async function writeCollectedPage(cwd, candidate, force) {
22351
22358
  if (!folder) {
22352
22359
  throw new Error(`Unsupported collected wiki type: ${candidate.type}`);
22353
22360
  }
22354
- const filePath = path73.join(wikiRootPath2(cwd), folder, `${candidate.slug}.md`);
22355
- const relativePath = path73.relative(cwd, filePath);
22361
+ const filePath = path74.join(wikiRootPath2(cwd), folder, `${candidate.slug}.md`);
22362
+ const relativePath = path74.relative(cwd, filePath);
22356
22363
  const exists = await pathExists(filePath);
22357
22364
  if (exists && !force) {
22358
22365
  return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
22359
22366
  }
22360
22367
  if (exists && force) {
22361
- const current = await readFile37(filePath, "utf8");
22368
+ const current = await readFile38(filePath, "utf8");
22362
22369
  const isUnmodifiedDraft = /\nStatus:\s*draft\s*\n/.test(current) && current.includes("Generated by `keryx wiki collect`");
22363
22370
  if (!isUnmodifiedDraft) {
22364
22371
  return { path: relativePath, type: candidate.type, source: candidate.source, action: "skipped" };
@@ -22380,7 +22387,7 @@ async function writeCollectedPage(cwd, candidate, force) {
22380
22387
  securityReason: output.reason
22381
22388
  };
22382
22389
  }
22383
- await mkdir19(path73.dirname(filePath), { recursive: true });
22390
+ await mkdir19(path74.dirname(filePath), { recursive: true });
22384
22391
  await writeFile13(filePath, output.content, "utf8");
22385
22392
  return {
22386
22393
  path: relativePath,
@@ -22392,8 +22399,8 @@ async function writeCollectedPage(cwd, candidate, force) {
22392
22399
  async function wikiPagesForFile(cwd, targetRepoPath) {
22393
22400
  const pages = await collectPages(cwd);
22394
22401
  const refs = await Promise.all(pages.map(async (page) => ({
22395
- repoPath: path73.relative(cwd, page.absolutePath).split(path73.sep).join("/"),
22396
- content: await readFile37(page.absolutePath, "utf8")
22402
+ repoPath: path74.relative(cwd, page.absolutePath).split(path74.sep).join("/"),
22403
+ content: await readFile38(page.absolutePath, "utf8")
22397
22404
  })));
22398
22405
  return backlinksFor(buildBacklinkIndex(refs), targetRepoPath);
22399
22406
  }
@@ -22431,11 +22438,11 @@ function renderIndexBody(pages, generatedAt) {
22431
22438
  `).trimEnd();
22432
22439
  }
22433
22440
  async function isIndexStale(cwd, pages) {
22434
- const indexPath = path73.join(wikiRootPath2(cwd), "index.md");
22441
+ const indexPath = path74.join(wikiRootPath2(cwd), "index.md");
22435
22442
  if (!await pathExists(indexPath)) {
22436
22443
  return true;
22437
22444
  }
22438
- const content = await readFile37(indexPath, "utf8");
22445
+ const content = await readFile38(indexPath, "utf8");
22439
22446
  const managed = content.match(new RegExp(`${escapeRegExp3(WIKI_INDEX_BEGIN)}([\\s\\S]*?)${escapeRegExp3(WIKI_INDEX_END)}`));
22440
22447
  if (!managed?.[1]) {
22441
22448
  return true;
@@ -22447,9 +22454,9 @@ function stripStamp(body) {
22447
22454
  }
22448
22455
  async function walkMarkdown(root) {
22449
22456
  const results = [];
22450
- const entries = await readdir12(root, { withFileTypes: true });
22457
+ const entries = await readdir13(root, { withFileTypes: true });
22451
22458
  for (const entry of entries) {
22452
- const absolutePath = path73.join(root, entry.name);
22459
+ const absolutePath = path74.join(root, entry.name);
22453
22460
  if (entry.isDirectory()) {
22454
22461
  results.push(...await walkMarkdown(absolutePath));
22455
22462
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -22506,11 +22513,11 @@ ${JSON.stringify(state, null, 2)}
22506
22513
  `;
22507
22514
  }
22508
22515
  async function readIndexGeneratedAt(cwd) {
22509
- const indexPath = path73.join(wikiRootPath2(cwd), "index.md");
22516
+ const indexPath = path74.join(wikiRootPath2(cwd), "index.md");
22510
22517
  if (!await pathExists(indexPath)) {
22511
22518
  return null;
22512
22519
  }
22513
- const content = await readFile37(indexPath, "utf8");
22520
+ const content = await readFile38(indexPath, "utf8");
22514
22521
  const match = content.match(/<!--\s*generated:\s*([^|]+?)\s*\|/);
22515
22522
  const value = match?.[1]?.trim();
22516
22523
  return value && value !== "never" ? value : null;
@@ -22520,7 +22527,7 @@ async function readLinkCheckState(cwd) {
22520
22527
  if (!await pathExists(reportPath)) {
22521
22528
  return null;
22522
22529
  }
22523
- const content = await readFile37(reportPath, "utf8");
22530
+ const content = await readFile38(reportPath, "utf8");
22524
22531
  const matches = [...content.matchAll(/```json\n([\s\S]*?)```/g)];
22525
22532
  const last = matches.at(-1);
22526
22533
  if (!last?.[1]) {
@@ -22718,7 +22725,7 @@ async function validateStructure(cwd, pages, issues) {
22718
22725
  for (const page of pages) {
22719
22726
  let content;
22720
22727
  try {
22721
- content = await readFile37(page.absolutePath, "utf8");
22728
+ content = await readFile38(page.absolutePath, "utf8");
22722
22729
  } catch {
22723
22730
  continue;
22724
22731
  }
@@ -22743,7 +22750,7 @@ async function validateStructure(cwd, pages, issues) {
22743
22750
  if (pattern.includes("*")) {
22744
22751
  continue;
22745
22752
  }
22746
- if (!await pathExists(path73.join(cwd, pattern))) {
22753
+ if (!await pathExists(path74.join(cwd, pattern))) {
22747
22754
  issues.push({
22748
22755
  page: page.relativePath,
22749
22756
  kind: "describes",
@@ -22813,10 +22820,10 @@ var init_service4 = __esm(() => {
22813
22820
 
22814
22821
  // src/gdgraph/wiki-layer.ts
22815
22822
  import { createHash as createHash15 } from "crypto";
22816
- import { mkdir as mkdir20, stat as stat10, writeFile as writeFile14 } from "fs/promises";
22817
- import path74 from "path";
22823
+ import { mkdir as mkdir20, stat as stat11, writeFile as writeFile14 } from "fs/promises";
22824
+ import path75 from "path";
22818
22825
  function storageDir(projectRoot) {
22819
- return path74.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
22826
+ return path75.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
22820
22827
  }
22821
22828
  function wikiPageId(relativePath) {
22822
22829
  return `wiki:${relativePath}`;
@@ -22882,11 +22889,11 @@ async function enrichBuildWithWikiLayer(input) {
22882
22889
  const mtimes = new Map;
22883
22890
  for (const record of input.fileRecords) {
22884
22891
  try {
22885
- const info = await stat10(path74.join(input.projectRoot, record.path));
22892
+ const info = await stat11(path75.join(input.projectRoot, record.path));
22886
22893
  mtimes.set(record.path, info.mtimeMs);
22887
22894
  } catch {}
22888
22895
  }
22889
- await writeFile14(path74.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
22896
+ await writeFile14(path75.join(dir, BUILD_MANIFEST_FILE), `${JSON.stringify({ version: 1, files: computeFingerprints(input.fileRecords, mtimes) }, null, 2)}
22890
22897
  `, "utf8");
22891
22898
  const validModules = input.validModules !== undefined ? input.validModules : await (input.loadValidModules ?? defaultLoadValidModules)(input.projectRoot);
22892
22899
  const wikiPages = await collectPages(input.projectRoot);
@@ -22911,8 +22918,8 @@ async function enrichBuildWithWikiLayer(input) {
22911
22918
  version: page.version
22912
22919
  }))
22913
22920
  });
22914
- await writeJsonl(path74.join(dir, WIKI_PAGES_FILE), layer.pages);
22915
- await writeJsonl(path74.join(dir, DESCRIBES_FILE), layer.describes);
22921
+ await writeJsonl(path75.join(dir, WIKI_PAGES_FILE), layer.pages);
22922
+ await writeJsonl(path75.join(dir, DESCRIBES_FILE), layer.describes);
22916
22923
  return layer;
22917
22924
  }
22918
22925
  async function defaultLoadValidModules(projectRoot) {
@@ -22928,23 +22935,23 @@ var init_wiki_layer = __esm(() => {
22928
22935
  });
22929
22936
 
22930
22937
  // src/gdskills/contracts.ts
22931
- import { readFile as readFile49 } from "fs/promises";
22938
+ import { readFile as readFile50 } from "fs/promises";
22932
22939
  import { existsSync as existsSync15 } from "fs";
22933
- import path102 from "path";
22940
+ import path103 from "path";
22934
22941
  import { fileURLToPath as fileURLToPath2 } from "url";
22935
22942
  async function loadSchema(name) {
22936
22943
  const contract = CONTRACTS.find((entry) => entry.name === name);
22937
22944
  if (!contract) {
22938
22945
  throw new Error(`Unknown contract schema: ${name}`);
22939
22946
  }
22940
- const raw = await readFile49(contractPath(contract), "utf8");
22947
+ const raw = await readFile50(contractPath(contract), "utf8");
22941
22948
  return JSON.parse(raw);
22942
22949
  }
22943
22950
  function contractPath(contract) {
22944
- const here = path102.dirname(fileURLToPath2(import.meta.url));
22951
+ const here = path103.dirname(fileURLToPath2(import.meta.url));
22945
22952
  if (contract.sourcePath) {
22946
- for (const root of [path102.join(here, "..", ".."), path102.join(here, ".."), here]) {
22947
- const candidate = path102.resolve(root, contract.sourcePath);
22953
+ for (const root of [path103.join(here, "..", ".."), path103.join(here, ".."), here]) {
22954
+ const candidate = path103.resolve(root, contract.sourcePath);
22948
22955
  if (existsSync15(candidate)) {
22949
22956
  return candidate;
22950
22957
  }
@@ -22954,7 +22961,7 @@ function contractPath(contract) {
22954
22961
  if (existsSync15(directPath)) {
22955
22962
  return directPath;
22956
22963
  }
22957
- const packagedSourcePath = path102.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
22964
+ const packagedSourcePath = path103.join(here, "..", "src", "gdskills", "contracts", contract.fileName);
22958
22965
  if (existsSync15(packagedSourcePath)) {
22959
22966
  return packagedSourcePath;
22960
22967
  }
@@ -23185,8 +23192,8 @@ __export(exports_service2, {
23185
23192
  validateCriterionName: () => validateCriterionName,
23186
23193
  writeAcCheckCache: () => writeAcCheckCache
23187
23194
  });
23188
- import { mkdir as mkdir12, readFile as readFile27 } from "fs/promises";
23189
- import path55 from "path";
23195
+ import { mkdir as mkdir12, readFile as readFile28 } from "fs/promises";
23196
+ import path56 from "path";
23190
23197
 
23191
23198
  // src/flow/machine.ts
23192
23199
  var TRANSITIONS = {
@@ -24920,6 +24927,10 @@ function flowStateSchema() {
24920
24927
  type: "boolean",
24921
24928
  description: "Written by `flow init`. When true, `flow complete` fails the owner gate with a named reason while no owner is set, and passes it once one is. Absent on packages created before the gate existed, which report the gate `skipped` rather than `fail`."
24922
24929
  },
24930
+ folderCommitted: {
24931
+ type: "boolean",
24932
+ description: "flow 384: written by `flow init`. When true, `flow complete` fails the folder-committed gate while the flow folder's flow.json is not in HEAD, and passes it once it is. Absent on packages created before the gate existed, which report the gate `skipped` rather than `fail`."
24933
+ },
24923
24934
  confirmation: {
24924
24935
  type: "boolean",
24925
24936
  description: "flow 299: written by `flow init --require-confirmation`, or by `flow init` when `.metaproject/tasks.config.json` has `completion.require_confirmation: true`. When true, `flow complete` fails the confirmation gate unless `--confirm-token` carries a valid, unexpired, unspent token minted by `keryx flow confirm` for this flow and its current criteria checksum. Absent on every other flow, which reports the gate `skipped`."
@@ -25162,6 +25173,7 @@ function flowStateSchema() {
25162
25173
  "review",
25163
25174
  "base-branch",
25164
25175
  "owner",
25176
+ "folder-committed",
25165
25177
  "confirmation"
25166
25178
  ]
25167
25179
  },
@@ -25895,7 +25907,7 @@ async function intentNoteForNewFlow(cwd, dir) {
25895
25907
  }
25896
25908
  // src/flow/check-ac.ts
25897
25909
  import { createHash as createHash8 } from "crypto";
25898
- import { chmod as chmod4, mkdir as mkdir10, readFile as readFile25 } from "fs/promises";
25910
+ import { chmod as chmod4, mkdir as mkdir10, readFile as readFile26 } from "fs/promises";
25899
25911
  import path52 from "path";
25900
25912
 
25901
25913
  // src/review/cost.ts
@@ -26084,7 +26096,7 @@ function factsOnlyVerdict(item) {
26084
26096
  }
26085
26097
  async function readAcCheckEnabled(cwd) {
26086
26098
  try {
26087
- const parsed = JSON.parse(await readFile25(path52.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
26099
+ const parsed = JSON.parse(await readFile26(path52.join(cwd, REVIEW_GATE_CONFIG_PATH), "utf8"));
26088
26100
  if (typeof parsed !== "object" || parsed === null)
26089
26101
  return false;
26090
26102
  const review = parsed["review"];
@@ -26111,7 +26123,7 @@ async function readAcCheckCache(cachePath) {
26111
26123
  if (!await pathExists(cachePath))
26112
26124
  return;
26113
26125
  try {
26114
- return JSON.parse(await readFile25(cachePath, "utf8"));
26126
+ return JSON.parse(await readFile26(cachePath, "utf8"));
26115
26127
  } catch {
26116
26128
  return;
26117
26129
  }
@@ -26174,7 +26186,7 @@ function renderAcCheckAdvisoryNotice(verdicts) {
26174
26186
  return `acceptance-criteria check (advisory): ${counts.likelyMet} likely met, ${counts.notEvident} not evident, ${counts.notCheckable} not checkable` + (inDoubt.length > 0 ? ` \u2014 in doubt: ${inDoubt.join(", ")}` : "") + ` (\`keryx flow check-ac\` for detail)`;
26175
26187
  }
26176
26188
  // src/flow/allocation.ts
26177
- import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile26 } from "fs/promises";
26189
+ import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile27 } from "fs/promises";
26178
26190
  import path54 from "path";
26179
26191
 
26180
26192
  // src/lib/clone-scope.ts
@@ -26239,7 +26251,7 @@ async function readAllocationLedger(scope) {
26239
26251
  if (!scope.ledgerPath || !await pathExists(scope.ledgerPath)) {
26240
26252
  return [];
26241
26253
  }
26242
- const content = await readFile26(scope.ledgerPath, "utf8");
26254
+ const content = await readFile27(scope.ledgerPath, "utf8");
26243
26255
  const records = [];
26244
26256
  for (const line of content.split(`
26245
26257
  `)) {
@@ -26269,6 +26281,173 @@ async function recordAllocation(scope, record) {
26269
26281
  `, "utf8");
26270
26282
  }
26271
26283
 
26284
+ // src/flow/remote-flows.ts
26285
+ import path55 from "path";
26286
+ var MAX_REFS = 500;
26287
+ var CONCURRENCY = 8;
26288
+ async function runGit2(cwd, args) {
26289
+ try {
26290
+ const proc = Bun.spawn(["git", ...args], { cwd, stdout: "pipe", stderr: "ignore" });
26291
+ const stdout = await new Response(proc.stdout).text();
26292
+ return { code: await proc.exited, stdout };
26293
+ } catch {
26294
+ return;
26295
+ }
26296
+ }
26297
+ function lines(text) {
26298
+ return text.split(`
26299
+ `).map((line) => line.trim()).filter((line) => line.length > 0);
26300
+ }
26301
+ function nulSplit(text) {
26302
+ return text.split("\x00").filter((entry) => entry.length > 0);
26303
+ }
26304
+ function safeDirName(dir) {
26305
+ let out = "";
26306
+ for (const char of dir) {
26307
+ const code = char.codePointAt(0) ?? 0;
26308
+ if (code > 31 && (code < 127 || code > 159)) {
26309
+ out += char;
26310
+ }
26311
+ }
26312
+ return out;
26313
+ }
26314
+ async function showPrefix(cwd) {
26315
+ const result = await runGit2(cwd, ["rev-parse", "--show-prefix"]);
26316
+ if (result === undefined || result.code !== 0) {
26317
+ return null;
26318
+ }
26319
+ return result.stdout.trim();
26320
+ }
26321
+ function orderRemoteRefs(entries, max = MAX_REFS) {
26322
+ const headTargets = new Set(entries.map((entry) => entry.symref).filter((symref) => symref.length > 0));
26323
+ const rank = (ref) => {
26324
+ if (/^refs\/remotes\/[^/]+\/(main|master)$/.test(ref)) {
26325
+ return 0;
26326
+ }
26327
+ return headTargets.has(ref) ? 1 : 2;
26328
+ };
26329
+ const candidates = entries.filter((entry) => entry.ref.startsWith("refs/remotes/") && !entry.ref.endsWith("/HEAD") && entry.symref === "").sort((a, b) => rank(a.ref) - rank(b.ref) || (a.ref < b.ref ? -1 : a.ref > b.ref ? 1 : 0));
26330
+ const seenTips = new Set;
26331
+ const refs = [];
26332
+ for (const entry of candidates) {
26333
+ if (seenTips.has(entry.tip)) {
26334
+ continue;
26335
+ }
26336
+ seenTips.add(entry.tip);
26337
+ refs.push(entry.ref);
26338
+ if (refs.length >= max) {
26339
+ break;
26340
+ }
26341
+ }
26342
+ return refs;
26343
+ }
26344
+ async function remoteRefs(cwd) {
26345
+ const result = await runGit2(cwd, ["for-each-ref", "--format=%(objectname) %(refname) %(symref)", "refs/remotes/"]);
26346
+ if (result === undefined || result.code !== 0) {
26347
+ return [];
26348
+ }
26349
+ const entries = [];
26350
+ for (const line of lines(result.stdout)) {
26351
+ const [tip, ref, symref] = line.split(" ");
26352
+ if (tip === undefined || ref === undefined) {
26353
+ continue;
26354
+ }
26355
+ entries.push({ tip, ref, symref: symref ?? "" });
26356
+ }
26357
+ return orderRemoteRefs(entries);
26358
+ }
26359
+ async function flowDirsOnRef(cwd, ref, flowsPath) {
26360
+ const result = await runGit2(cwd, ["ls-tree", "-z", "-d", "--name-only", "--full-tree", ref, "--", `${flowsPath}/`]);
26361
+ if (result === undefined || result.code !== 0) {
26362
+ return [];
26363
+ }
26364
+ return nulSplit(result.stdout).map((entry) => path55.posix.basename(entry)).filter((name) => /^\d{3}-/.test(name));
26365
+ }
26366
+ async function knownRemoteFlowDirs(cwd) {
26367
+ try {
26368
+ const prefix = await showPrefix(cwd);
26369
+ if (prefix === null) {
26370
+ return [];
26371
+ }
26372
+ const refs = await remoteRefs(cwd);
26373
+ if (refs.length === 0) {
26374
+ return [];
26375
+ }
26376
+ const flowsPath = `${prefix}.metaproject/flows`;
26377
+ const found = new Array(refs.length).fill([]);
26378
+ let next = 0;
26379
+ const worker = async () => {
26380
+ while (next < refs.length) {
26381
+ const index = next;
26382
+ next += 1;
26383
+ const ref = refs[index];
26384
+ if (ref === undefined) {
26385
+ continue;
26386
+ }
26387
+ const short = ref.slice("refs/remotes/".length);
26388
+ found[index] = (await flowDirsOnRef(cwd, ref, flowsPath)).map((dir) => ({ ref: short, dir }));
26389
+ }
26390
+ };
26391
+ await Promise.all(Array.from({ length: Math.min(CONCURRENCY, refs.length) }, () => worker()));
26392
+ return found.flat();
26393
+ } catch {
26394
+ return [];
26395
+ }
26396
+ }
26397
+ function flowNumberOfDir(dir) {
26398
+ const dash = dir.indexOf("-");
26399
+ return dash > 0 ? Number(dir.slice(0, dash)) : Number.NaN;
26400
+ }
26401
+ async function remoteFlowNumbers(cwd) {
26402
+ const dirs = await knownRemoteFlowDirs(cwd);
26403
+ const numbers = new Set;
26404
+ for (const { dir } of dirs) {
26405
+ const value = flowNumberOfDir(dir);
26406
+ if (!Number.isNaN(value)) {
26407
+ numbers.add(value);
26408
+ }
26409
+ }
26410
+ return [...numbers].sort((a, b) => a - b);
26411
+ }
26412
+
26413
+ // src/flow/folder-committed.ts
26414
+ var BATCH = 100;
26415
+ async function flowFoldersInHead(cwd, dirs) {
26416
+ const prefix = await showPrefix(cwd);
26417
+ if (prefix === null) {
26418
+ return null;
26419
+ }
26420
+ const committed = new Set;
26421
+ if (dirs.length === 0) {
26422
+ return committed;
26423
+ }
26424
+ const head = await runGit2(cwd, ["rev-parse", "--verify", "-q", "HEAD"]);
26425
+ if (head === undefined) {
26426
+ return null;
26427
+ }
26428
+ if (head.code !== 0) {
26429
+ return committed;
26430
+ }
26431
+ for (let start = 0;start < dirs.length; start += BATCH) {
26432
+ const batch = dirs.slice(start, start + BATCH);
26433
+ const paths = batch.map((dir) => `${prefix}.metaproject/flows/${dir}/flow.json`);
26434
+ const result = await runGit2(cwd, ["ls-tree", "-z", "--name-only", "--full-tree", "HEAD", "--", ...paths]);
26435
+ if (result === undefined) {
26436
+ return null;
26437
+ }
26438
+ if (result.code !== 0) {
26439
+ throw new Error(`could not read HEAD tree (git ls-tree exited ${result.code}); not treating the flow folders as uncommitted`);
26440
+ }
26441
+ const found = new Set(nulSplit(result.stdout));
26442
+ for (const [index, dir] of batch.entries()) {
26443
+ if (found.has(paths[index] ?? "")) {
26444
+ committed.add(dir);
26445
+ }
26446
+ }
26447
+ }
26448
+ return committed;
26449
+ }
26450
+
26272
26451
  // src/flow/templates.ts
26273
26452
  function renderDescription(title, source) {
26274
26453
  return `# ${title}
@@ -26353,7 +26532,7 @@ function renderJournal(createdAt) {
26353
26532
 
26354
26533
  // src/flow/service.ts
26355
26534
  async function deriveAcKinds(cwd, dir, flowId) {
26356
- const { report } = buildAcKindReport(flowId, await readFile27(acPath(cwd, dir), "utf8"));
26535
+ const { report } = buildAcKindReport(flowId, await readFile28(acPath(cwd, dir), "utf8"));
26357
26536
  return { ...report.criteria };
26358
26537
  }
26359
26538
  function prMergeState(pr, gates) {
@@ -26384,6 +26563,7 @@ function prMergeState(pr, gates) {
26384
26563
  }
26385
26564
  var UNCONFIRMED_PREFIX = "unconfirmed: ";
26386
26565
  var NO_PR_DETAIL = "no PR recorded";
26566
+ var FOLDER_UNCOMMITTED_PREFIX = "flow folder ";
26387
26567
  function completionAdmitted(status, merged) {
26388
26568
  return canTransition(status, "completing") || merged && status === "in-progress";
26389
26569
  }
@@ -26409,6 +26589,10 @@ function completionFixHint(gate, flowId) {
26409
26589
  return "keryx health run";
26410
26590
  case "confirmation":
26411
26591
  return `keryx flow confirm ${flowId} (in a terminal)`;
26592
+ case "folder-committed": {
26593
+ const dir = gate.detail.startsWith(FOLDER_UNCOMMITTED_PREFIX) ? gate.detail.slice(FOLDER_UNCOMMITTED_PREFIX.length).split(" ")[0] : undefined;
26594
+ return dir ? `git add .metaproject/flows/${dir} && git commit` : undefined;
26595
+ }
26412
26596
  default:
26413
26597
  return;
26414
26598
  }
@@ -26541,6 +26725,11 @@ function createFlowService(deps) {
26541
26725
  }
26542
26726
  gates.push(taskGate(flow));
26543
26727
  gates.push(ownerGate(flow));
26728
+ try {
26729
+ gates.push(await folderCommittedGate(cwd, dir, flow));
26730
+ } catch {
26731
+ gates.push(unevaluableGate("folder-committed"));
26732
+ }
26544
26733
  try {
26545
26734
  gates.push(await reviewGate({
26546
26735
  cwd,
@@ -26612,11 +26801,14 @@ function createFlowService(deps) {
26612
26801
  const title = input.title ?? context.issueTitle ?? provisionalTitle;
26613
26802
  const scope = await resolveAllocationScope(input.cwd);
26614
26803
  return withFileLock(scope.lockPath, async () => {
26615
- const id = await nextFlowId(input.cwd, await reservedIds(scope));
26804
+ const id = await nextFlowId(input.cwd, [
26805
+ ...await reservedIds(scope),
26806
+ ...await remoteFlowNumbers(input.cwd)
26807
+ ]);
26616
26808
  const date = now().slice(0, 10);
26617
26809
  const slug = slugify(input.slug ?? title);
26618
26810
  const dir = `${id}-${date}-${slug}`;
26619
- const absolute = path55.join(flowsRoot(input.cwd), dir);
26811
+ const absolute = path56.join(flowsRoot(input.cwd), dir);
26620
26812
  if (await pathExists(absolute)) {
26621
26813
  throw new Error(`Flow directory already exists: ${dir}`);
26622
26814
  }
@@ -26628,6 +26820,7 @@ function createFlowService(deps) {
26628
26820
  tasks: true,
26629
26821
  review: true,
26630
26822
  owner: true,
26823
+ folderCommitted: true,
26631
26824
  ...input.requireConfirmation === true || await readRequireConfirmationDefault(input.cwd) ? { confirmation: true } : {}
26632
26825
  },
26633
26826
  id,
@@ -26650,15 +26843,15 @@ function createFlowService(deps) {
26650
26843
  history: [{ at: createdAt, event: "created" }]
26651
26844
  };
26652
26845
  const sourceLabel = input.issue ?? "user description";
26653
- await writeFileAtomic(path55.join(absolute, "description.md"), renderDescription(title, sourceLabel));
26654
- await writeFileAtomic(path55.join(absolute, "context.md"), context.markdown);
26655
- await writeFileAtomic(path55.join(absolute, "plan.md"), renderPlan());
26656
- await writeFileAtomic(path55.join(absolute, "tasks.md"), renderTasksDoc());
26657
- await writeFileAtomic(path55.join(absolute, "acceptance-criteria.md"), renderAcceptanceCriteria());
26658
- await writeFileAtomic(path55.join(absolute, "journal.md"), renderJournal(createdAt));
26846
+ await writeFileAtomic(path56.join(absolute, "description.md"), renderDescription(title, sourceLabel));
26847
+ await writeFileAtomic(path56.join(absolute, "context.md"), context.markdown);
26848
+ await writeFileAtomic(path56.join(absolute, "plan.md"), renderPlan());
26849
+ await writeFileAtomic(path56.join(absolute, "tasks.md"), renderTasksDoc());
26850
+ await writeFileAtomic(path56.join(absolute, "acceptance-criteria.md"), renderAcceptanceCriteria());
26851
+ await writeFileAtomic(path56.join(absolute, "journal.md"), renderJournal(createdAt));
26659
26852
  await writeFlow(input.cwd, dir, flow);
26660
26853
  await recordAllocation(scope, { id, dir, at: createdAt, project: scope.project });
26661
- return { flow, dir: path55.relative(input.cwd, absolute), contextNotes: context.notes };
26854
+ return { flow, dir: path56.relative(input.cwd, absolute), contextNotes: context.notes };
26662
26855
  });
26663
26856
  },
26664
26857
  async list({ cwd }) {
@@ -26883,7 +27076,7 @@ function createFlowService(deps) {
26883
27076
  },
26884
27077
  async acKinds({ cwd, id }) {
26885
27078
  const { dir, flow } = await load(cwd, id);
26886
- return buildAcKindReport(flow.id, await readFile27(acPath(cwd, dir), "utf8"));
27079
+ return buildAcKindReport(flow.id, await readFile28(acPath(cwd, dir), "utf8"));
26887
27080
  },
26888
27081
  async acReseal({ cwd, id, reason }) {
26889
27082
  if (!reason?.trim()) {
@@ -27141,6 +27334,10 @@ function createFlowService(deps) {
27141
27334
  if ((await reservedIds(scope)).includes(Number(to))) {
27142
27335
  throw new Error(`Flow id ${to} was already used in this repository and cannot be reused. ` + "Pick a fresh number (see .metaproject/flows/id-map.json).");
27143
27336
  }
27337
+ const remoteUse = (await knownRemoteFlowDirs(cwd)).find((entry) => flowNumberOfDir(entry.dir) === Number(to));
27338
+ if (remoteUse) {
27339
+ throw new Error(`Flow id ${to} is already used on ${remoteUse.ref} (${safeDirName(remoteUse.dir)}) and cannot be reused. ` + "Pick a fresh number.");
27340
+ }
27144
27341
  const toDir = `${to}${fromDir.slice(3)}`;
27145
27342
  const { flow, reviewRecords } = await withFileLock(flowLockPath(cwd, fromDir), async () => {
27146
27343
  const reviewRecords = await moveFlowDirWithReviewRecords({ cwd, from, to, fromDir, toDir });
@@ -27176,6 +27373,34 @@ function createFlowService(deps) {
27176
27373
  });
27177
27374
  }
27178
27375
  }
27376
+ const remoteDirs = await knownRemoteFlowDirs(cwd);
27377
+ if (remoteDirs.length > 0) {
27378
+ for (const dir of allDirs) {
27379
+ const clash = remoteDirs.find((entry) => entry.dir !== dir && flowNumberOfDir(entry.dir) === Number(flowIdOf(dir)));
27380
+ if (clash) {
27381
+ issues.push({
27382
+ flow: dir,
27383
+ kind: "duplicate-id",
27384
+ message: `flow id ${flowIdOf(dir)} is also used on ${clash.ref} by a different flow (${safeDirName(clash.dir)})` + ` \u2014 repair with: keryx flow renumber ${dir} --to <free id> --reason "<why>"`
27385
+ });
27386
+ }
27387
+ }
27388
+ }
27389
+ const warnings = [];
27390
+ const inHead = await flowFoldersInHead(cwd, allDirs).catch(() => {
27391
+ return null;
27392
+ });
27393
+ if (inHead !== null) {
27394
+ for (const dir of allDirs) {
27395
+ if (!inHead.has(dir)) {
27396
+ warnings.push({
27397
+ flow: dir,
27398
+ kind: "untracked",
27399
+ message: `flow folder ${dir} is not committed: commit it in the same PR as the code`
27400
+ });
27401
+ }
27402
+ }
27403
+ }
27179
27404
  for (const dir of allDirs) {
27180
27405
  let flow;
27181
27406
  try {
@@ -27192,7 +27417,7 @@ function createFlowService(deps) {
27192
27417
  issues.push({ flow: dir, kind: "schema", message: `unknown schemaVersion ${flow.schemaVersion}` });
27193
27418
  }
27194
27419
  try {
27195
- const raw = JSON.parse(await Bun.file(path55.join(flowsRoot(cwd), dir, "flow.json")).text());
27420
+ const raw = JSON.parse(await Bun.file(path56.join(flowsRoot(cwd), dir, "flow.json")).text());
27196
27421
  const validation = validateAgainstSchemaObject(flowStateSchema(), raw);
27197
27422
  if (!validation.valid) {
27198
27423
  issues.push({
@@ -27203,7 +27428,7 @@ function createFlowService(deps) {
27203
27428
  }
27204
27429
  } catch {}
27205
27430
  for (const file of ["description.md", "context.md", "plan.md", "tasks.md", "acceptance-criteria.md", "journal.md"]) {
27206
- if (!await pathExists(path55.join(flowsRoot(cwd), dir, file))) {
27431
+ if (!await pathExists(path56.join(flowsRoot(cwd), dir, file))) {
27207
27432
  issues.push({ flow: dir, kind: "structure", message: `missing ${file}` });
27208
27433
  }
27209
27434
  }
@@ -27237,15 +27462,15 @@ function createFlowService(deps) {
27237
27462
  });
27238
27463
  }
27239
27464
  }
27240
- return { ok: issues.length === 0, issues };
27465
+ return { ok: issues.length === 0, issues, warnings };
27241
27466
  }
27242
27467
  };
27243
27468
  }
27244
27469
  async function appendIdMap(cwd, entry) {
27245
- const file = path55.join(flowsRoot(cwd), "id-map.json");
27470
+ const file = path56.join(flowsRoot(cwd), "id-map.json");
27246
27471
  let entries = [];
27247
27472
  if (await pathExists(file)) {
27248
- const raw = await readFile27(file, "utf8");
27473
+ const raw = await readFile28(file, "utf8");
27249
27474
  try {
27250
27475
  const parsed = JSON.parse(raw);
27251
27476
  if (!Array.isArray(parsed)) {
@@ -27253,7 +27478,7 @@ async function appendIdMap(cwd, entry) {
27253
27478
  }
27254
27479
  entries = parsed;
27255
27480
  } catch (error) {
27256
- throw new Error(`Cannot read ${path55.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`);
27481
+ throw new Error(`Cannot read ${path56.relative(cwd, file)}: ${error instanceof Error ? error.message : String(error)}`);
27257
27482
  }
27258
27483
  }
27259
27484
  entries.push(entry);
@@ -27347,6 +27572,27 @@ function ownerGate(flow) {
27347
27572
  }
27348
27573
  return { name: "owner", status: "pass", detail: `owner: ${flow.owner.value}` };
27349
27574
  }
27575
+ async function folderCommittedGate(cwd, dir, flow) {
27576
+ if (!flow.gates?.folderCommitted) {
27577
+ return {
27578
+ name: "folder-committed",
27579
+ status: "skipped",
27580
+ detail: "folder-committed gate not enabled for this package (created before the gate); " + "flows created by this keryx version opt in automatically"
27581
+ };
27582
+ }
27583
+ const committed = await flowFoldersInHead(cwd, [dir]);
27584
+ if (committed === null) {
27585
+ return { name: "folder-committed", status: "skipped", detail: "not a git repository; nothing to compare the flow folder with" };
27586
+ }
27587
+ if (!committed.has(dir)) {
27588
+ return {
27589
+ name: "folder-committed",
27590
+ status: "fail",
27591
+ detail: `${FOLDER_UNCOMMITTED_PREFIX}${dir} is not committed. Commit it (git add .metaproject/flows/${dir} && git commit) ` + "in the PR that carries the code, then run flow complete again"
27592
+ };
27593
+ }
27594
+ return { name: "folder-committed", status: "pass", detail: `${dir} is committed in HEAD` };
27595
+ }
27350
27596
  function confirmPreconditionError(flow, merged) {
27351
27597
  const confirmable = flow.status === "implemented" || flow.status === "in-progress" && merged;
27352
27598
  if (!confirmable) {
@@ -27504,9 +27750,9 @@ __export(exports_service5, {
27504
27750
  });
27505
27751
 
27506
27752
  // src/gdgraph/build.ts
27507
- import { mkdir as mkdir21, readdir as readdir13, readFile as readFile38, writeFile as writeFile15 } from "fs/promises";
27753
+ import { mkdir as mkdir21, readdir as readdir14, readFile as readFile39, writeFile as writeFile15 } from "fs/promises";
27508
27754
  import { existsSync as existsSync7 } from "fs";
27509
- import path75 from "path";
27755
+ import path76 from "path";
27510
27756
 
27511
27757
  // src/gdgraph/types.ts
27512
27758
  var UNKNOWN_IMPORT_KIND = "unknown-static";
@@ -27571,8 +27817,8 @@ async function buildGraph(projectRoot) {
27571
27817
  const assetNodes = new Map;
27572
27818
  const fileRecords = [];
27573
27819
  for (const file of files) {
27574
- const absolutePath = path75.join(projectRoot, file);
27575
- const content = await readFile38(absolutePath, "utf8");
27820
+ const absolutePath = path76.join(projectRoot, file);
27821
+ const content = await readFile39(absolutePath, "utf8");
27576
27822
  fileRecords.push({ path: file, content });
27577
27823
  const language = getLanguage(file);
27578
27824
  const resolver = pickResolver(resolvers, language);
@@ -27624,24 +27870,24 @@ async function collectSourceFiles(projectRoot) {
27624
27870
  const result = [];
27625
27871
  const skippedDirectories = [];
27626
27872
  async function walk(relativeDir) {
27627
- const absoluteDir = path75.join(projectRoot, relativeDir);
27628
- const entries = await readdir13(absoluteDir, { withFileTypes: true });
27873
+ const absoluteDir = path76.join(projectRoot, relativeDir);
27874
+ const entries = await readdir14(absoluteDir, { withFileTypes: true });
27629
27875
  for (const entry of entries) {
27630
27876
  if (entry.isDirectory()) {
27631
27877
  if (IGNORE_DIRS.has(entry.name)) {
27632
- skippedDirectories.push(normalizePath2(path75.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
27878
+ skippedDirectories.push(normalizePath2(path76.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
27633
27879
  continue;
27634
27880
  }
27635
- await walk(normalizePath2(path75.posix.join(relativeDir, entry.name)));
27881
+ await walk(normalizePath2(path76.posix.join(relativeDir, entry.name)));
27636
27882
  continue;
27637
27883
  }
27638
27884
  if (!entry.isFile()) {
27639
27885
  continue;
27640
27886
  }
27641
- if (!SOURCE_EXTENSIONS.includes(path75.extname(entry.name))) {
27887
+ if (!SOURCE_EXTENSIONS.includes(path76.extname(entry.name))) {
27642
27888
  continue;
27643
27889
  }
27644
- result.push(normalizePath2(path75.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
27890
+ result.push(normalizePath2(path76.posix.join(relativeDir, entry.name)).replace(/^\.\//, ""));
27645
27891
  }
27646
27892
  }
27647
27893
  await walk(".");
@@ -27723,8 +27969,8 @@ function resolveImport(projectRoot, fromFile, specifier, fileSet, resolver) {
27723
27969
  }
27724
27970
  function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
27725
27971
  for (const candidate of importCandidateBases(projectRoot, fromFile, specifier, resolver)) {
27726
- const extension = path75.posix.extname(candidate);
27727
- if (ASSET_EXTENSIONS.includes(extension) && existsSync7(path75.join(projectRoot, candidate))) {
27972
+ const extension = path76.posix.extname(candidate);
27973
+ if (ASSET_EXTENSIONS.includes(extension) && existsSync7(path76.join(projectRoot, candidate))) {
27728
27974
  return candidate;
27729
27975
  }
27730
27976
  }
@@ -27733,17 +27979,17 @@ function resolveAssetImport(projectRoot, fromFile, specifier, resolver) {
27733
27979
  function importCandidateBases(projectRoot, fromFile, specifier, resolver) {
27734
27980
  const normalizedSpecifier = stripImportSuffix(specifier);
27735
27981
  if (normalizedSpecifier.startsWith(".") && getLanguage(fromFile) !== "python") {
27736
- const fromDir = path75.posix.dirname(fromFile);
27737
- return [normalizePath2(path75.posix.normalize(path75.posix.join(fromDir, normalizedSpecifier)))];
27982
+ const fromDir = path76.posix.dirname(fromFile);
27983
+ return [normalizePath2(path76.posix.normalize(path76.posix.join(fromDir, normalizedSpecifier)))];
27738
27984
  }
27739
- return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path75.relative(projectRoot, path75.join(projectRoot, candidate))));
27985
+ return resolver.candidateBases(normalizedSpecifier, fromFile).map((candidate) => normalizePath2(path76.relative(projectRoot, path76.join(projectRoot, candidate))));
27740
27986
  }
27741
27987
  function resolveSourceCandidate(base, fileSet) {
27742
27988
  const candidates = [
27743
27989
  base,
27744
27990
  ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => `${base}${extension}`),
27745
- ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path75.posix.join(base, `index${extension}`)),
27746
- path75.posix.join(base, "__init__.py")
27991
+ ...SOURCE_RESOLUTION_EXTENSIONS.map((extension) => path76.posix.join(base, `index${extension}`)),
27992
+ path76.posix.join(base, "__init__.py")
27747
27993
  ];
27748
27994
  return candidates.find((candidate) => fileSet.has(candidate)) ?? null;
27749
27995
  }
@@ -27773,20 +28019,20 @@ async function loadJavaResolver(projectRoot) {
27773
28019
  return createJavaResolver(roots);
27774
28020
  }
27775
28021
  async function discoverJavaSourceRoots(projectRoot) {
27776
- const pomPath = path75.join(projectRoot, "pom.xml");
28022
+ const pomPath = path76.join(projectRoot, "pom.xml");
27777
28023
  if (existsSync7(pomPath)) {
27778
28024
  try {
27779
- const roots = parseMavenSourceRoots(await readFile38(pomPath, "utf8"));
28025
+ const roots = parseMavenSourceRoots(await readFile39(pomPath, "utf8"));
27780
28026
  if (roots.length > 0) {
27781
28027
  return roots;
27782
28028
  }
27783
28029
  } catch {}
27784
28030
  }
27785
28031
  for (const gradleName of ["build.gradle", "build.gradle.kts"]) {
27786
- const gradlePath = path75.join(projectRoot, gradleName);
28032
+ const gradlePath = path76.join(projectRoot, gradleName);
27787
28033
  if (existsSync7(gradlePath)) {
27788
28034
  try {
27789
- const roots = parseGradleSourceRoots(await readFile38(gradlePath, "utf8"));
28035
+ const roots = parseGradleSourceRoots(await readFile39(gradlePath, "utf8"));
27790
28036
  if (roots.length > 0) {
27791
28037
  return roots;
27792
28038
  }
@@ -27805,12 +28051,12 @@ function createJavaResolver(sourceRoots) {
27805
28051
  return [];
27806
28052
  }
27807
28053
  const relative = specifier.split(".").join("/");
27808
- return sourceRoots.map((root) => normalizePath2(path75.posix.join(root, relative)));
28054
+ return sourceRoots.map((root) => normalizePath2(path76.posix.join(root, relative)));
27809
28055
  }
27810
28056
  };
27811
28057
  }
27812
28058
  function loadPythonResolver(projectRoot) {
27813
- const hasSrc = existsSync7(path75.join(projectRoot, "src"));
28059
+ const hasSrc = existsSync7(path76.join(projectRoot, "src"));
27814
28060
  return createPythonResolver(hasSrc);
27815
28061
  }
27816
28062
  function createPythonResolver(hasSrc) {
@@ -27823,16 +28069,16 @@ function createPythonResolver(hasSrc) {
27823
28069
  if (specifier.startsWith(".")) {
27824
28070
  const dots = /^\.+/.exec(specifier)?.[0].length ?? 0;
27825
28071
  const rest = specifier.slice(dots);
27826
- let baseDir = path75.posix.dirname(fromFile);
28072
+ let baseDir = path76.posix.dirname(fromFile);
27827
28073
  for (let level = 1;level < dots; level += 1) {
27828
- baseDir = path75.posix.dirname(baseDir);
28074
+ baseDir = path76.posix.dirname(baseDir);
27829
28075
  }
27830
28076
  const suffix = rest ? rest.split(".").join("/") : "";
27831
- const base = suffix ? path75.posix.join(baseDir, suffix) : baseDir;
28077
+ const base = suffix ? path76.posix.join(baseDir, suffix) : baseDir;
27832
28078
  return [normalizePath2(base)];
27833
28079
  }
27834
28080
  const relative = specifier.split(".").join("/");
27835
- return roots.map((root) => normalizePath2(root ? path75.posix.join(root, relative) : relative));
28081
+ return roots.map((root) => normalizePath2(root ? path76.posix.join(root, relative) : relative));
27836
28082
  }
27837
28083
  };
27838
28084
  }
@@ -27841,8 +28087,8 @@ function parseMavenSourceRoots(pomXml) {
27841
28087
  for (const match of pomXml.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
27842
28088
  const moduleDir = match[1]?.trim();
27843
28089
  if (moduleDir && !moduleDir.includes("${")) {
27844
- roots.add(normalizePath2(path75.posix.join(moduleDir, "src/main/java")));
27845
- roots.add(normalizePath2(path75.posix.join(moduleDir, "src/test/java")));
28090
+ roots.add(normalizePath2(path76.posix.join(moduleDir, "src/main/java")));
28091
+ roots.add(normalizePath2(path76.posix.join(moduleDir, "src/test/java")));
27846
28092
  }
27847
28093
  }
27848
28094
  for (const tag of ["sourceDirectory", "testSourceDirectory"]) {
@@ -27875,7 +28121,7 @@ function parseGradleSourceRoots(buildGradle) {
27875
28121
  var TSCONFIG_EXTENDS_MAX_DEPTH = 10;
27876
28122
  async function loadTsconfigResolver(projectRoot) {
27877
28123
  const empty = createTsconfigResolver(null, []);
27878
- const tsconfigPath = path75.join(projectRoot, "tsconfig.json");
28124
+ const tsconfigPath = path76.join(projectRoot, "tsconfig.json");
27879
28125
  if (!existsSync7(tsconfigPath)) {
27880
28126
  return empty;
27881
28127
  }
@@ -27888,12 +28134,12 @@ async function loadTsconfigResolver(projectRoot) {
27888
28134
  return createTsconfigResolver(resolved.baseUrl, paths);
27889
28135
  }
27890
28136
  function toProjectRelativeDir(projectRoot, absoluteDir) {
27891
- const relative = normalizePath2(path75.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
28137
+ const relative = normalizePath2(path76.relative(projectRoot, absoluteDir)).replace(/^\.\//, "");
27892
28138
  return relative === "." ? "" : relative;
27893
28139
  }
27894
28140
  async function readTsconfigJson(configPath) {
27895
28141
  try {
27896
- const raw = await readFile38(configPath, "utf8");
28142
+ const raw = await readFile39(configPath, "utf8");
27897
28143
  return JSON.parse(stripJsonComments(raw));
27898
28144
  } catch {
27899
28145
  return null;
@@ -27903,11 +28149,11 @@ function resolveTsconfigExtendsPath(configDir, extendsSpecifier) {
27903
28149
  if (!extendsSpecifier.startsWith(".") && !extendsSpecifier.startsWith("/")) {
27904
28150
  return null;
27905
28151
  }
27906
- const resolved = path75.resolve(configDir, extendsSpecifier);
28152
+ const resolved = path76.resolve(configDir, extendsSpecifier);
27907
28153
  return resolved.endsWith(".json") ? resolved : `${resolved}.json`;
27908
28154
  }
27909
28155
  async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
27910
- const resolvedPath = path75.resolve(configPath);
28156
+ const resolvedPath = path76.resolve(configPath);
27911
28157
  if (depth > TSCONFIG_EXTENDS_MAX_DEPTH || visited.has(resolvedPath)) {
27912
28158
  return null;
27913
28159
  }
@@ -27918,15 +28164,15 @@ async function resolveTsconfigOptions(configPath, visited, depth, projectRoot) {
27918
28164
  }
27919
28165
  let inherited = null;
27920
28166
  if (typeof parsed.extends === "string") {
27921
- const basePath = resolveTsconfigExtendsPath(path75.dirname(resolvedPath), parsed.extends);
28167
+ const basePath = resolveTsconfigExtendsPath(path76.dirname(resolvedPath), parsed.extends);
27922
28168
  if (basePath) {
27923
28169
  inherited = await resolveTsconfigOptions(basePath, visited, depth + 1, projectRoot);
27924
28170
  }
27925
28171
  }
27926
- const configDir = path75.dirname(resolvedPath);
28172
+ const configDir = path76.dirname(resolvedPath);
27927
28173
  const declaringDir = toProjectRelativeDir(projectRoot, configDir);
27928
28174
  const options = parsed.compilerOptions ?? {};
27929
- const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path75.resolve(configDir, options.baseUrl)) : null;
28175
+ const ownBaseUrl = typeof options.baseUrl === "string" ? toProjectRelativeDir(projectRoot, path76.resolve(configDir, options.baseUrl)) : null;
27930
28176
  const baseUrl = ownBaseUrl ?? inherited?.baseUrl ?? null;
27931
28177
  const ownPaths = isRecord4(options.paths) ? Object.entries(options.paths).filter((entry) => Array.isArray(entry[1])).map(([pattern, targets]) => ({
27932
28178
  pattern,
@@ -27955,7 +28201,7 @@ function createTsconfigResolver(baseUrl, mappings) {
27955
28201
  }
27956
28202
  }
27957
28203
  if (baseUrl !== null) {
27958
- candidates.push(normalizePath2(path75.posix.join(baseUrl, normalizedSpecifier)));
28204
+ candidates.push(normalizePath2(path76.posix.join(baseUrl, normalizedSpecifier)));
27959
28205
  }
27960
28206
  return [...new Set(candidates.map((candidate) => candidate.replace(/^\.\//, "")))];
27961
28207
  }
@@ -27975,7 +28221,7 @@ function matchPathPattern(pattern, specifier) {
27975
28221
  }
27976
28222
  function applyPathTarget(base, target, wildcard) {
27977
28223
  const replaced = target.includes("*") ? target.replace("*", wildcard) : target;
27978
- return normalizePath2(path75.posix.normalize(path75.posix.join(base, replaced)));
28224
+ return normalizePath2(path76.posix.normalize(path76.posix.join(base, replaced)));
27979
28225
  }
27980
28226
  function stripJsonComments(source) {
27981
28227
  let out = "";
@@ -28028,21 +28274,21 @@ function isRecord4(value) {
28028
28274
  return typeof value === "object" && value !== null && !Array.isArray(value);
28029
28275
  }
28030
28276
  async function writeGraph(projectRoot, graph) {
28031
- const storageDir = path75.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
28032
- const artifactsDir = path75.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
28277
+ const storageDir = path76.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
28278
+ const artifactsDir = path76.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
28033
28279
  await mkdir21(storageDir, { recursive: true });
28034
28280
  await mkdir21(artifactsDir, { recursive: true });
28035
- await writeFile15(path75.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
28281
+ await writeFile15(path76.join(storageDir, "nodes.jsonl"), graph.nodes.map((node) => JSON.stringify(node)).join(`
28036
28282
  `) + `
28037
28283
  `, "utf8");
28038
- await writeFile15(path75.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
28284
+ await writeFile15(path76.join(storageDir, "edges.jsonl"), graph.edges.map((edge) => JSON.stringify(edge)).join(`
28039
28285
  `) + `
28040
28286
  `, "utf8");
28041
- await writeFile15(path75.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
28287
+ await writeFile15(path76.join(artifactsDir, "module-map.json"), JSON.stringify(buildModuleMap(graph), null, 2) + `
28042
28288
  `, "utf8");
28043
28289
  }
28044
28290
  async function writeSummary(projectRoot, graph, collection) {
28045
- const artifactsDir = path75.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
28291
+ const artifactsDir = path76.join(projectRoot, ".metaproject", "data", "gdgraph", "artifacts");
28046
28292
  await mkdir21(artifactsDir, { recursive: true });
28047
28293
  const unresolved = graph.edges.filter((edge) => edge.kind === "unresolved");
28048
28294
  const imports = graph.edges.filter((edge) => edge.kind === "imports");
@@ -28057,7 +28303,7 @@ async function writeSummary(projectRoot, graph, collection) {
28057
28303
  `);
28058
28304
  const skippedList = collection.skippedDirectories.length > 0 ? collection.skippedDirectories.slice(0, 30).map((dir) => `- \`${dir}\``).join(`
28059
28305
  `) : "- none";
28060
- const summaryPath = path75.join(artifactsDir, "summary.md");
28306
+ const summaryPath = path76.join(artifactsDir, "summary.md");
28061
28307
  const content = `# gdgraph Summary
28062
28308
 
28063
28309
  ## Stats
@@ -28138,7 +28384,7 @@ function groupBy(items, getKey) {
28138
28384
  }
28139
28385
  function unresolvedType(specifier) {
28140
28386
  const stripped = stripImportSuffix(specifier);
28141
- const extension = path75.posix.extname(stripped);
28387
+ const extension = path76.posix.extname(stripped);
28142
28388
  if (extension) {
28143
28389
  return extension;
28144
28390
  }
@@ -28148,13 +28394,13 @@ function unresolvedType(specifier) {
28148
28394
  return "package";
28149
28395
  }
28150
28396
  function normalizePath2(value) {
28151
- return value.split(path75.sep).join("/");
28397
+ return value.split(path76.sep).join("/");
28152
28398
  }
28153
28399
 
28154
28400
  // src/gdgraph/target.ts
28155
- import path76 from "path";
28401
+ import path77 from "path";
28156
28402
  function normalizeTarget(target) {
28157
- return target.replace(/^\.\//, "").split(path76.sep).join("/");
28403
+ return target.replace(/^\.\//, "").split(path77.sep).join("/");
28158
28404
  }
28159
28405
  function resolveGraphTarget(graph, target) {
28160
28406
  const normalized = normalizeTarget(target);
@@ -28246,16 +28492,16 @@ function normalizeDepth(depth) {
28246
28492
  init_config3();
28247
28493
 
28248
28494
  // src/gdgraph/query.ts
28249
- import { readFile as readFile39 } from "fs/promises";
28250
- import path77 from "path";
28495
+ import { readFile as readFile40 } from "fs/promises";
28496
+ import path78 from "path";
28251
28497
  async function loadGraph(projectRoot) {
28252
- const storageDir = path77.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
28253
- const nodes = await readJsonl(path77.join(storageDir, "nodes.jsonl"));
28254
- const edges = await readJsonl(path77.join(storageDir, "edges.jsonl"));
28255
- const symbols = await readJsonl(path77.join(storageDir, "symbols.jsonl"));
28256
- const calls = await readJsonl(path77.join(storageDir, "calls.jsonl"));
28257
- const wikiPages = await readJsonl(path77.join(storageDir, "wiki-pages.jsonl"));
28258
- const describes = await readJsonl(path77.join(storageDir, "describes.jsonl"));
28498
+ const storageDir = path78.join(projectRoot, ".metaproject", "data", "gdgraph", "storage");
28499
+ const nodes = await readJsonl(path78.join(storageDir, "nodes.jsonl"));
28500
+ const edges = await readJsonl(path78.join(storageDir, "edges.jsonl"));
28501
+ const symbols = await readJsonl(path78.join(storageDir, "symbols.jsonl"));
28502
+ const calls = await readJsonl(path78.join(storageDir, "calls.jsonl"));
28503
+ const wikiPages = await readJsonl(path78.join(storageDir, "wiki-pages.jsonl"));
28504
+ const describes = await readJsonl(path78.join(storageDir, "describes.jsonl"));
28259
28505
  const graph = { nodes, edges };
28260
28506
  if (symbols.length > 0) {
28261
28507
  graph.symbols = symbols;
@@ -28315,7 +28561,7 @@ async function bunfigPreloadRoots(projectRoot) {
28315
28561
  const roots = new Set;
28316
28562
  let text;
28317
28563
  try {
28318
- text = await readFile39(path77.join(projectRoot, "bunfig.toml"), "utf8");
28564
+ text = await readFile40(path78.join(projectRoot, "bunfig.toml"), "utf8");
28319
28565
  } catch {
28320
28566
  return roots;
28321
28567
  }
@@ -28329,8 +28575,8 @@ async function bunfigPreloadRoots(projectRoot) {
28329
28575
  if (raw.length === 0) {
28330
28576
  continue;
28331
28577
  }
28332
- const absolute = path77.resolve(projectRoot, raw);
28333
- const relative = path77.relative(projectRoot, absolute).split(path77.sep).join("/");
28578
+ const absolute = path78.resolve(projectRoot, raw);
28579
+ const relative = path78.relative(projectRoot, absolute).split(path78.sep).join("/");
28334
28580
  roots.add(relative);
28335
28581
  }
28336
28582
  }
@@ -28379,7 +28625,7 @@ function getCycles(graph) {
28379
28625
  async function readJsonl(filePath) {
28380
28626
  let content;
28381
28627
  try {
28382
- content = await readFile39(filePath, "utf8");
28628
+ content = await readFile40(filePath, "utf8");
28383
28629
  } catch {
28384
28630
  return [];
28385
28631
  }
@@ -28403,7 +28649,7 @@ function canonicalCycle(cycle) {
28403
28649
 
28404
28650
  // src/gdgraph/repomap.ts
28405
28651
  import { mkdir as mkdir22, writeFile as writeFile16 } from "fs/promises";
28406
- import path78 from "path";
28652
+ import path79 from "path";
28407
28653
 
28408
28654
  // src/gdgraph/pagerank.ts
28409
28655
  function personalizedPageRank(nodes, edges, options) {
@@ -28514,7 +28760,7 @@ function overflowContent(required, missing, budget) {
28514
28760
  `);
28515
28761
  }
28516
28762
  function repomapArtifactPath(cwd) {
28517
- return path78.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
28763
+ return path79.join(cwd, ".metaproject", "data", "gdgraph", "artifacts", "repomap.md");
28518
28764
  }
28519
28765
  function buildRankEdges(graph, config) {
28520
28766
  const edges = [];
@@ -28659,7 +28905,7 @@ function computeRepomap(graph, config, options = {}) {
28659
28905
  async function writeRepomap(cwd, graph, config, options = {}) {
28660
28906
  const result = computeRepomap(graph, config, options);
28661
28907
  const artifactPath = repomapArtifactPath(cwd);
28662
- await mkdir22(path78.dirname(artifactPath), { recursive: true });
28908
+ await mkdir22(path79.dirname(artifactPath), { recursive: true });
28663
28909
  await writeFile16(artifactPath, result.content, "utf8");
28664
28910
  return { ...result, path: artifactPath };
28665
28911
  }
@@ -28741,18 +28987,18 @@ init_section_tombstone();
28741
28987
 
28742
28988
  // src/forgetting/journal.ts
28743
28989
  init_fs();
28744
- import { appendFile as appendFile4, mkdir as mkdir23, readFile as readFile40, stat as stat11 } from "fs/promises";
28745
- import path79 from "path";
28990
+ import { appendFile as appendFile4, mkdir as mkdir23, readFile as readFile41, stat as stat12 } from "fs/promises";
28991
+ import path80 from "path";
28746
28992
  function forgettingDataDir(cwd) {
28747
- return path79.join(cwd, ".metaproject", "data", "forgetting");
28993
+ return path80.join(cwd, ".metaproject", "data", "forgetting");
28748
28994
  }
28749
28995
  function deletionJournalPath(cwd) {
28750
- return path79.join(forgettingDataDir(cwd), "journal.jsonl");
28996
+ return path80.join(forgettingDataDir(cwd), "journal.jsonl");
28751
28997
  }
28752
28998
  async function readDeletionJournal(cwd) {
28753
28999
  const file = deletionJournalPath(cwd);
28754
29000
  try {
28755
- await stat11(file);
29001
+ await stat12(file);
28756
29002
  } catch (error) {
28757
29003
  if (isNotFound(error)) {
28758
29004
  return { state: "absent", path: file };
@@ -28766,7 +29012,7 @@ async function readDeletionJournal(cwd) {
28766
29012
  }
28767
29013
  let content;
28768
29014
  try {
28769
- content = await readFile40(file, "utf8");
29015
+ content = await readFile41(file, "utf8");
28770
29016
  } catch (error) {
28771
29017
  const message = error instanceof Error ? error.message : String(error);
28772
29018
  return {
@@ -29166,12 +29412,12 @@ __export(exports_service7, {
29166
29412
  gateExitCode: () => gateExitCode,
29167
29413
  readWikiFreshnessMetric: () => readWikiFreshnessMetric
29168
29414
  });
29169
- import path99 from "path";
29415
+ import path100 from "path";
29170
29416
 
29171
29417
  // src/health/config.ts
29172
29418
  init_fs();
29173
29419
  init_json();
29174
- import path80 from "path";
29420
+ import path81 from "path";
29175
29421
  var DEFAULT_HEALTH_CONFIG = {
29176
29422
  schemaVersion: 2,
29177
29423
  ignore: {
@@ -29227,7 +29473,7 @@ var DEFAULT_HEALTH_CONFIG = {
29227
29473
  }
29228
29474
  };
29229
29475
  function configPath2(cwd) {
29230
- return path80.join(cwd, ".metaproject", "health.config.json");
29476
+ return path81.join(cwd, ".metaproject", "health.config.json");
29231
29477
  }
29232
29478
  var STRICTEST_GATE = {
29233
29479
  failOnPriorities: ["P0", "P1", "P2", "P3"],
@@ -29278,7 +29524,7 @@ async function loadHealthConfig(cwd) {
29278
29524
  // src/health/run.ts
29279
29525
  init_fs();
29280
29526
  import { mkdir as mkdir27, writeFile as writeFile20 } from "fs/promises";
29281
- import path98 from "path";
29527
+ import path99 from "path";
29282
29528
 
29283
29529
  // src/metrics/provenance.ts
29284
29530
  async function collectGitProvenance(cwd) {
@@ -29378,12 +29624,12 @@ function computeGate2(input) {
29378
29624
  }
29379
29625
 
29380
29626
  // src/health/scopes.ts
29381
- import path83 from "path";
29627
+ import path84 from "path";
29382
29628
 
29383
29629
  // src/health/util.ts
29384
29630
  init_fs();
29385
- import { mkdir as mkdir24, readFile as readFile41, readdir as readdir14, writeFile as writeFile17 } from "fs/promises";
29386
- import path81 from "path";
29631
+ import { mkdir as mkdir24, readFile as readFile42, readdir as readdir15, writeFile as writeFile17 } from "fs/promises";
29632
+ import path82 from "path";
29387
29633
  var IGNORED_DIRS = new Set([
29388
29634
  "node_modules",
29389
29635
  ".git",
@@ -29427,14 +29673,14 @@ async function toolVersion(command, cwd) {
29427
29673
  }
29428
29674
  }
29429
29675
  function dataRoot3(cwd) {
29430
- return path81.join(cwd, ".metaproject", "data", "health");
29676
+ return path82.join(cwd, ".metaproject", "data", "health");
29431
29677
  }
29432
29678
  async function writeRaw(cwd, source, content, stamp) {
29433
- const dir = path81.join(dataRoot3(cwd), "raw", source);
29679
+ const dir = path82.join(dataRoot3(cwd), "raw", source);
29434
29680
  await mkdir24(dir, { recursive: true });
29435
- const file = path81.join(dir, `${stamp}.log`);
29681
+ const file = path82.join(dir, `${stamp}.log`);
29436
29682
  await writeFile17(file, content, "utf8");
29437
- return path81.relative(cwd, file);
29683
+ return path82.relative(cwd, file);
29438
29684
  }
29439
29685
  async function listSourceFiles(cwd, ignorePaths = []) {
29440
29686
  const { files } = await listSourceFilesWithReasons(cwd, ignorePaths);
@@ -29452,9 +29698,9 @@ async function listSourceFilesWithReasons(cwd, ignorePaths = []) {
29452
29698
  async function walk2(root, dir, out, incompleteReasons) {
29453
29699
  let entries;
29454
29700
  try {
29455
- entries = await readdir14(dir, { withFileTypes: true });
29701
+ entries = await readdir15(dir, { withFileTypes: true });
29456
29702
  } catch (error) {
29457
- incompleteReasons.push(`${path81.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
29703
+ incompleteReasons.push(`${path82.relative(root, dir) || "."}: ${error instanceof Error ? error.message : String(error)}`);
29458
29704
  return;
29459
29705
  }
29460
29706
  for (const entry of entries) {
@@ -29462,14 +29708,14 @@ async function walk2(root, dir, out, incompleteReasons) {
29462
29708
  if (entry.isDirectory() && !IGNORED_DIRS.has(entry.name)) {}
29463
29709
  continue;
29464
29710
  }
29465
- const abs = path81.join(dir, entry.name);
29711
+ const abs = path82.join(dir, entry.name);
29466
29712
  if (entry.isDirectory()) {
29467
29713
  if (IGNORED_DIRS.has(entry.name)) {
29468
29714
  continue;
29469
29715
  }
29470
29716
  await walk2(root, abs, out, incompleteReasons);
29471
- } else if (entry.isFile() && SOURCE_EXT.has(path81.extname(entry.name))) {
29472
- out.push(path81.relative(root, abs));
29717
+ } else if (entry.isFile() && SOURCE_EXT.has(path82.extname(entry.name))) {
29718
+ out.push(path82.relative(root, abs));
29473
29719
  }
29474
29720
  }
29475
29721
  }
@@ -29484,7 +29730,7 @@ function moduleOfFile(file) {
29484
29730
  return null;
29485
29731
  }
29486
29732
  function isSourceFile(file) {
29487
- return SOURCE_EXT.has(path81.extname(file));
29733
+ return SOURCE_EXT.has(path82.extname(file));
29488
29734
  }
29489
29735
  function matchesAnyPattern(file, patterns) {
29490
29736
  const normalized = file.replace(/\\/g, "/").replace(/^\.\//, "");
@@ -29583,8 +29829,8 @@ function rankHotspots(files, churn, sourceAnalysis) {
29583
29829
 
29584
29830
  // src/health/source-analysis.ts
29585
29831
  init_fs();
29586
- import { readFile as readFile42 } from "fs/promises";
29587
- import path82 from "path";
29832
+ import { readFile as readFile43 } from "fs/promises";
29833
+ import path83 from "path";
29588
29834
 
29589
29835
  // src/health/metrics/complexity.ts
29590
29836
  var CONTROL_KEYWORDS = new Set([
@@ -29818,11 +30064,11 @@ async function analyzeSourceFiles(cwd, sourceFiles) {
29818
30064
  return new Map(entries.filter((entry) => entry !== null));
29819
30065
  }
29820
30066
  async function analyzeSourceFile(cwd, file) {
29821
- const abs = path82.join(cwd, file);
30067
+ const abs = path83.join(cwd, file);
29822
30068
  if (!await pathExists(abs)) {
29823
30069
  return null;
29824
30070
  }
29825
- const content = await readFile42(abs, "utf8");
30071
+ const content = await readFile43(abs, "utf8");
29826
30072
  return [
29827
30073
  file,
29828
30074
  {
@@ -29891,14 +30137,14 @@ async function computeMetrics(input) {
29891
30137
  }
29892
30138
  const components = new Map;
29893
30139
  for (const file of sourceFiles) {
29894
- const dir = path83.posix.dirname(file);
30140
+ const dir = path84.posix.dirname(file);
29895
30141
  if (dir === "." || dir === moduleOfFile(file)) {
29896
30142
  continue;
29897
30143
  }
29898
30144
  components.set(dir, [...components.get(dir) ?? [], file]);
29899
30145
  }
29900
30146
  for (const [name, files] of [...components.entries()].sort()) {
29901
- const compFindings = findings.filter((f) => f.file && path83.posix.dirname(f.file) === name);
30147
+ const compFindings = findings.filter((f) => f.file && path84.posix.dirname(f.file) === name);
29902
30148
  scopes.push(build("component", `component:${name}`, name, files, compFindings, averageCoverage(files, coverage)));
29903
30149
  }
29904
30150
  const findingFiles = findings.map((f) => f.file).filter((f) => Boolean(f));
@@ -29942,10 +30188,10 @@ function tally2(values) {
29942
30188
 
29943
30189
  // src/health/baseline.ts
29944
30190
  init_fs();
29945
- import { mkdir as mkdir25, readFile as readFile43, writeFile as writeFile18 } from "fs/promises";
29946
- import path84 from "path";
30191
+ import { mkdir as mkdir25, readFile as readFile44, writeFile as writeFile18 } from "fs/promises";
30192
+ import path85 from "path";
29947
30193
  function baselinePath(cwd) {
29948
- return path84.join(cwd, ".metaproject", "health", "baselines", "scores.json");
30194
+ return path85.join(cwd, ".metaproject", "health", "baselines", "scores.json");
29949
30195
  }
29950
30196
  async function loadBaseline(cwd) {
29951
30197
  const file = baselinePath(cwd);
@@ -29953,7 +30199,7 @@ async function loadBaseline(cwd) {
29953
30199
  return new Map;
29954
30200
  }
29955
30201
  try {
29956
- const data = JSON.parse(await readFile43(file, "utf8"));
30202
+ const data = JSON.parse(await readFile44(file, "utf8"));
29957
30203
  return new Map(Object.entries(data.scopes ?? {}));
29958
30204
  } catch {
29959
30205
  return new Map;
@@ -29977,7 +30223,7 @@ async function writeBaseline(cwd, metrics, generatedAt, selector) {
29977
30223
  scopes[key] = value;
29978
30224
  }
29979
30225
  const file = baselinePath(cwd);
29980
- await mkdir25(path84.dirname(file), { recursive: true });
30226
+ await mkdir25(path85.dirname(file), { recursive: true });
29981
30227
  await writeFile18(file, `${JSON.stringify({ generatedAt, scopes }, null, 2)}
29982
30228
  `, "utf8");
29983
30229
  return updated;
@@ -30030,11 +30276,11 @@ async function getChurn(cwd, windowDays) {
30030
30276
  }
30031
30277
 
30032
30278
  // src/health/metrics/wiki-freshness.ts
30033
- import { readFile as readFile44, stat as stat12 } from "fs/promises";
30034
- import path85 from "path";
30279
+ import { readFile as readFile45, stat as stat13 } from "fs/promises";
30280
+ import path86 from "path";
30035
30281
  var DEFAULT_STALE_EVIDENCE_DAYS = 7;
30036
30282
  function freshnessReportPath(cwd) {
30037
- return path85.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
30283
+ return path86.join(cwd, ".metaproject", "data", "wiki", "freshness", "latest.json");
30038
30284
  }
30039
30285
  async function readWikiFreshnessMetric(cwd, options = {}) {
30040
30286
  const file = freshnessReportPath(cwd);
@@ -30042,7 +30288,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
30042
30288
  const now = (options.now ?? (() => new Date))();
30043
30289
  let raw;
30044
30290
  try {
30045
- raw = await readFile44(file, "utf8");
30291
+ raw = await readFile45(file, "utf8");
30046
30292
  } catch {
30047
30293
  return {
30048
30294
  status: "no-report",
@@ -30055,7 +30301,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
30055
30301
  } catch {
30056
30302
  return {
30057
30303
  status: "unreadable-report",
30058
- reason: `${path85.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
30304
+ reason: `${path86.relative(cwd, file)} is not valid JSON; re-run \`keryx wiki freshness\`.`
30059
30305
  };
30060
30306
  }
30061
30307
  const report = parsed;
@@ -30065,7 +30311,7 @@ async function readWikiFreshnessMetric(cwd, options = {}) {
30065
30311
  if (pagesTotal === null || pagesFresh === null) {
30066
30312
  return {
30067
30313
  status: "unreadable-report",
30068
- reason: `${path85.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
30314
+ reason: `${path86.relative(cwd, file)} is missing its totals; re-run \`keryx wiki freshness\`.`
30069
30315
  };
30070
30316
  }
30071
30317
  const pagesUndecidable = numberOr2(totals.pagesUndecidable) ?? 0;
@@ -30102,7 +30348,7 @@ async function reportAgeDays(file, generatedAt, now) {
30102
30348
  return Math.floor((now.getTime() - stamped) / 86400000);
30103
30349
  }
30104
30350
  try {
30105
- const info = await stat12(file);
30351
+ const info = await stat13(file);
30106
30352
  return Math.floor((now.getTime() - info.mtimeMs) / 86400000);
30107
30353
  } catch {
30108
30354
  return null;
@@ -30119,12 +30365,12 @@ function renderWikiFreshnessLine(metric) {
30119
30365
  }
30120
30366
 
30121
30367
  // src/health/sources/helpers.ts
30122
- import path86 from "path";
30368
+ import path87 from "path";
30123
30369
  import { existsSync as existsSync8 } from "fs";
30124
30370
  class NoImportError extends Error {
30125
30371
  }
30126
30372
  function resolveBin(cwd, name) {
30127
- const local = path86.join(cwd, "node_modules", ".bin", name);
30373
+ const local = path87.join(cwd, "node_modules", ".bin", name);
30128
30374
  if (existsSync8(local)) {
30129
30375
  return local;
30130
30376
  }
@@ -30205,13 +30451,13 @@ async function getComplexityFindings(cwd, sourceFiles, config, sourceAnalysis) {
30205
30451
 
30206
30452
  // src/health/metrics/coverage.ts
30207
30453
  import { existsSync as existsSync9 } from "fs";
30208
- import path87 from "path";
30454
+ import path88 from "path";
30209
30455
  var SUMMARY_PATHS = [
30210
30456
  "coverage/coverage-summary.json",
30211
30457
  "coverage/coverage-final.json"
30212
30458
  ];
30213
30459
  async function getCoverage(cwd) {
30214
- const summary = SUMMARY_PATHS.map((rel) => path87.join(cwd, rel)).find((abs) => existsSync9(abs));
30460
+ const summary = SUMMARY_PATHS.map((rel) => path88.join(cwd, rel)).find((abs) => existsSync9(abs));
30215
30461
  if (!summary) {
30216
30462
  return { status: "missing", total: null, byFile: new Map };
30217
30463
  }
@@ -30232,7 +30478,7 @@ async function getCoverage(cwd) {
30232
30478
  total = pct;
30233
30479
  continue;
30234
30480
  }
30235
- const relative = path87.isAbsolute(key) ? path87.relative(cwd, key) : key;
30481
+ const relative = path88.isAbsolute(key) ? path88.relative(cwd, key) : key;
30236
30482
  byFile.set(relative.replace(/\\/g, "/"), pct);
30237
30483
  }
30238
30484
  return { status: "available", total, byFile };
@@ -30364,17 +30610,17 @@ function renderWikiFreshness(metric) {
30364
30610
 
30365
30611
  // src/health/skills.ts
30366
30612
  init_fs();
30367
- import { readFile as readFile45 } from "fs/promises";
30368
- import path88 from "path";
30613
+ import { readFile as readFile46 } from "fs/promises";
30614
+ import path89 from "path";
30369
30615
  var EMPTY = { skills: [], skillForFile: () => null };
30370
30616
  async function loadSkillOwnership(cwd) {
30371
- const manifestPath = path88.join(cwd, ".metaproject", "metaproject.json");
30617
+ const manifestPath = path89.join(cwd, ".metaproject", "metaproject.json");
30372
30618
  if (!await pathExists(manifestPath)) {
30373
30619
  return EMPTY;
30374
30620
  }
30375
30621
  let registry;
30376
30622
  try {
30377
- const manifest = JSON.parse(await readFile45(manifestPath, "utf8"));
30623
+ const manifest = JSON.parse(await readFile46(manifestPath, "utf8"));
30378
30624
  registry = manifest.modules?.gdskills?.projectSkillRegistry ?? [];
30379
30625
  } catch {
30380
30626
  return EMPTY;
@@ -30406,7 +30652,7 @@ function normalize(value) {
30406
30652
 
30407
30653
  // src/health/sources/eslint.ts
30408
30654
  import { existsSync as existsSync10 } from "fs";
30409
- import path89 from "path";
30655
+ import path90 from "path";
30410
30656
  var CONFIG_FILES = [
30411
30657
  ".eslintrc",
30412
30658
  ".eslintrc.js",
@@ -30420,7 +30666,7 @@ var CONFIG_FILES = [
30420
30666
  "eslint.config.ts"
30421
30667
  ];
30422
30668
  function hasConfig(cwd) {
30423
- return CONFIG_FILES.some((file) => existsSync10(path89.join(cwd, file)));
30669
+ return CONFIG_FILES.some((file) => existsSync10(path90.join(cwd, file)));
30424
30670
  }
30425
30671
  var eslintAdapter = {
30426
30672
  id: "eslint",
@@ -30445,7 +30691,7 @@ var eslintAdapter = {
30445
30691
  };
30446
30692
  },
30447
30693
  async import(ctx) {
30448
- const report = path89.join(ctx.cwd, "eslint-report.json");
30694
+ const report = path90.join(ctx.cwd, "eslint-report.json");
30449
30695
  if (!existsSync10(report)) {
30450
30696
  throw new NoImportError("no eslint-report.json");
30451
30697
  }
@@ -30472,7 +30718,7 @@ var eslintAdapter = {
30472
30718
  }
30473
30719
  const findings = [];
30474
30720
  for (const file of data) {
30475
- const relative = path89.isAbsolute(file.filePath) ? path89.relative(ctx.cwd, file.filePath) : file.filePath;
30721
+ const relative = path90.isAbsolute(file.filePath) ? path90.relative(ctx.cwd, file.filePath) : file.filePath;
30476
30722
  for (const message of file.messages ?? []) {
30477
30723
  const isError = message.severity === 2;
30478
30724
  findings.push(makeFinding({
@@ -30504,9 +30750,9 @@ var eslintAdapter = {
30504
30750
 
30505
30751
  // src/health/sources/typescript.ts
30506
30752
  import { existsSync as existsSync11 } from "fs";
30507
- import path90 from "path";
30753
+ import path91 from "path";
30508
30754
  function hasTsconfig(cwd) {
30509
- return existsSync11(path90.join(cwd, "tsconfig.json"));
30755
+ return existsSync11(path91.join(cwd, "tsconfig.json"));
30510
30756
  }
30511
30757
  var typescriptAdapter = {
30512
30758
  id: "typescript",
@@ -30581,8 +30827,8 @@ __export(exports_service6, {
30581
30827
  testingDataRoot: () => testingDataRoot
30582
30828
  });
30583
30829
  import { existsSync as existsSync12 } from "fs";
30584
- import { readFile as readFile48, readdir as readdir15 } from "fs/promises";
30585
- import path95 from "path";
30830
+ import { readFile as readFile49, readdir as readdir16 } from "fs/promises";
30831
+ import path96 from "path";
30586
30832
 
30587
30833
  // src/lib/git-env.ts
30588
30834
  var GIT_DISCOVERY_OVERRIDE_VARS = [
@@ -30606,8 +30852,8 @@ function withoutGitDiscoveryOverrides(env) {
30606
30852
  // src/metrics/lifecycle.ts
30607
30853
  init_fs();
30608
30854
  init_guard();
30609
- import { readFile as readFile46 } from "fs/promises";
30610
- import path91 from "path";
30855
+ import { readFile as readFile47 } from "fs/promises";
30856
+ import path92 from "path";
30611
30857
 
30612
30858
  // src/metrics/record.ts
30613
30859
  var RELIABILITIES = new Set(["exact", "estimated", "unknown"]);
@@ -30622,16 +30868,16 @@ var RETRY_TYPES = new Set([
30622
30868
 
30623
30869
  // src/metrics/lifecycle.ts
30624
30870
  async function readArtifactPointer(root, expected) {
30625
- const pointerFile = path91.join(root, "latest.json");
30871
+ const pointerFile = path92.join(root, "latest.json");
30626
30872
  if (!await pathExists(pointerFile))
30627
30873
  return { status: "missing", pointer: null };
30628
30874
  let pointer;
30629
30875
  try {
30630
- pointer = JSON.parse(await readFile46(pointerFile, "utf8"));
30876
+ pointer = JSON.parse(await readFile47(pointerFile, "utf8"));
30631
30877
  } catch {
30632
30878
  return { status: "stale", pointer: null, reason: "latest pointer is invalid JSON" };
30633
30879
  }
30634
- const recordFile = pointer.record ? path91.join(root, pointer.record) : null;
30880
+ const recordFile = pointer.record ? path92.join(root, pointer.record) : null;
30635
30881
  if (!recordFile || !isPathInside(root, recordFile) || !await pathExists(recordFile)) {
30636
30882
  return { status: "stale", pointer, reason: "pointer record is missing" };
30637
30883
  }
@@ -30647,9 +30893,9 @@ init_guard();
30647
30893
  // src/testing/capability.ts
30648
30894
  init_fs();
30649
30895
  init_json();
30650
- import path92 from "path";
30896
+ import path93 from "path";
30651
30897
  async function isTestingCapabilityEnabled(cwd, capability) {
30652
- const manifestPath = path92.join(cwd, ".metaproject", "metaproject.json");
30898
+ const manifestPath = path93.join(cwd, ".metaproject", "metaproject.json");
30653
30899
  if (!await pathExists(manifestPath)) {
30654
30900
  return false;
30655
30901
  }
@@ -30674,11 +30920,11 @@ async function isTestingCapabilityEnabled(cwd, capability) {
30674
30920
  // src/testing/coverage-map.ts
30675
30921
  init_fs();
30676
30922
  init_guard();
30677
- import { readFile as readFile47, mkdir as mkdir26, writeFile as writeFile19 } from "fs/promises";
30678
- import path93 from "path";
30923
+ import { readFile as readFile48, mkdir as mkdir26, writeFile as writeFile19 } from "fs/promises";
30924
+ import path94 from "path";
30679
30925
  var COVERAGE_MAP_SCHEMA_VERSION = 1;
30680
30926
  function coverageMapPath(cwd, cfg) {
30681
- return path93.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path93.join(cwd, cfg.coverageMap.artifact);
30927
+ return path94.isAbsolute(cfg.coverageMap.artifact) ? cfg.coverageMap.artifact : path94.join(cwd, cfg.coverageMap.artifact);
30682
30928
  }
30683
30929
  async function loadCoverageMap(cwd, cfg) {
30684
30930
  const file = coverageMapPath(cwd, cfg);
@@ -30686,7 +30932,7 @@ async function loadCoverageMap(cwd, cfg) {
30686
30932
  return null;
30687
30933
  }
30688
30934
  try {
30689
- const parsed = JSON.parse(await readFile47(file, "utf8"));
30935
+ const parsed = JSON.parse(await readFile48(file, "utf8"));
30690
30936
  if (!parsed || typeof parsed !== "object" || typeof parsed.map !== "object") {
30691
30937
  return null;
30692
30938
  }
@@ -30752,20 +30998,20 @@ function normalizePath4(file) {
30752
30998
  }
30753
30999
 
30754
31000
  // src/testing/selection.ts
30755
- import path94 from "path";
31001
+ import path95 from "path";
30756
31002
  var TEST_FILE_RE = /(^|\/)(__tests__\/.*|.*\.(test|spec)\.[cm]?[tj]sx?$|e2e\/.*\.[cm]?[tj]sx?$|tests\/.*\.[cm]?[tj]sx?$)/;
30757
31003
  function normalizePath5(file) {
30758
31004
  return file.replace(/\\/g, "/").replace(/^\.\//, "");
30759
31005
  }
30760
31006
  function relatedByNamingAndDirectory(target, testFiles) {
30761
31007
  const normalized = normalizePath5(target);
30762
- const ext = path94.extname(normalized);
31008
+ const ext = path95.extname(normalized);
30763
31009
  const withoutExt = ext ? normalized.slice(0, -ext.length) : normalized;
30764
- const base = path94.basename(withoutExt);
30765
- const dir = path94.dirname(normalized);
31010
+ const base = path95.basename(withoutExt);
31011
+ const dir = path95.dirname(normalized);
30766
31012
  return testFiles.filter((file) => {
30767
- const fileDir = path94.dirname(file);
30768
- const fileBase = path94.basename(file);
31013
+ const fileDir = path95.dirname(file);
31014
+ const fileBase = path95.basename(file);
30769
31015
  return file.startsWith(`${withoutExt}.`) || file.includes(`${withoutExt}.`) || fileDir === dir && fileBase.startsWith(`${base}.`) || fileDir.startsWith(dir) && fileBase.includes(base);
30770
31016
  }).sort();
30771
31017
  }
@@ -30895,7 +31141,7 @@ var DEFAULT_TESTING_CONFIG = {
30895
31141
  }
30896
31142
  };
30897
31143
  function testingDataRoot(cwd) {
30898
- return path95.join(cwd, ".metaproject", "data", "testing");
31144
+ return path96.join(cwd, ".metaproject", "data", "testing");
30899
31145
  }
30900
31146
  async function computeTestingContext(cwd) {
30901
31147
  const { files, incompleteReasons } = await listProjectFiles(cwd);
@@ -31070,33 +31316,33 @@ async function runTesting(input) {
31070
31316
  return runResult;
31071
31317
  }
31072
31318
  async function loadTestingContext(cwd) {
31073
- const file = path95.join(testingDataRoot(cwd), "context.json");
31319
+ const file = path96.join(testingDataRoot(cwd), "context.json");
31074
31320
  if (!await pathExists(file)) {
31075
31321
  return null;
31076
31322
  }
31077
31323
  try {
31078
- return JSON.parse(await readFile48(file, "utf8"));
31324
+ return JSON.parse(await readFile49(file, "utf8"));
31079
31325
  } catch {
31080
31326
  return null;
31081
31327
  }
31082
31328
  }
31083
31329
  async function loadTestingReport(cwd) {
31084
- const file = path95.join(testingDataRoot(cwd), "artifacts", "latest.json");
31330
+ const file = path96.join(testingDataRoot(cwd), "artifacts", "latest.json");
31085
31331
  if (!await pathExists(file)) {
31086
31332
  return null;
31087
31333
  }
31088
31334
  try {
31089
- const latest = JSON.parse(await readFile48(file, "utf8"));
31335
+ const latest = JSON.parse(await readFile49(file, "utf8"));
31090
31336
  if (typeof latest.record === "string") {
31091
- const pointer = await readArtifactPointer(path95.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
31337
+ const pointer = await readArtifactPointer(path96.join(testingDataRoot(cwd), "artifacts"), await collectGitProvenance(cwd));
31092
31338
  if (pointer.status !== "fresh")
31093
31339
  return null;
31094
- const recordFile = path95.join(testingDataRoot(cwd), "artifacts", latest.record);
31095
- if (!isPathInside(path95.join(testingDataRoot(cwd), "artifacts"), recordFile))
31340
+ const recordFile = path96.join(testingDataRoot(cwd), "artifacts", latest.record);
31341
+ if (!isPathInside(path96.join(testingDataRoot(cwd), "artifacts"), recordFile))
31096
31342
  return null;
31097
31343
  if (!await pathExists(recordFile))
31098
31344
  return null;
31099
- return JSON.parse(await readFile48(recordFile, "utf8"));
31345
+ return JSON.parse(await readFile49(recordFile, "utf8"));
31100
31346
  }
31101
31347
  return latest;
31102
31348
  } catch {
@@ -31139,28 +31385,28 @@ async function ensureContext(cwd) {
31139
31385
  }
31140
31386
  async function writeContext(cwd, context) {
31141
31387
  const root = testingDataRoot(cwd);
31142
- const rel = (p) => path95.relative(cwd, p);
31388
+ const rel = (p) => path96.relative(cwd, p);
31143
31389
  await mkdirContained(cwd, rel(root));
31144
- await writeContained(cwd, rel(path95.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
31390
+ await writeContained(cwd, rel(path96.join(root, "context.json")), `${JSON.stringify(context, null, 2)}
31145
31391
  `);
31146
- await writeContained(cwd, rel(path95.join(root, "context.md")), renderContextMarkdown(context));
31147
- await writeContained(cwd, rel(path95.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
31392
+ await writeContained(cwd, rel(path96.join(root, "context.md")), renderContextMarkdown(context));
31393
+ await writeContained(cwd, rel(path96.join(root, "recommendations.md")), renderRecommendationsMarkdown(context));
31148
31394
  }
31149
31395
  async function writeReport(cwd, report) {
31150
31396
  const root = testingDataRoot(cwd);
31151
- const artifacts = path95.join(root, "artifacts");
31152
- const history = path95.join(root, "history");
31153
- const rel = (p) => path95.relative(cwd, p);
31397
+ const artifacts = path96.join(root, "artifacts");
31398
+ const history = path96.join(root, "history");
31399
+ const rel = (p) => path96.relative(cwd, p);
31154
31400
  await mkdirContained(cwd, rel(artifacts));
31155
31401
  await mkdirContained(cwd, rel(history));
31156
31402
  const stamp = report.generatedAt.replace(/[:.]/g, "-");
31157
- const json = path95.join(artifacts, "latest.json");
31158
- const markdown = path95.join(artifacts, "latest.md");
31403
+ const json = path96.join(artifacts, "latest.json");
31404
+ const markdown = path96.join(artifacts, "latest.md");
31159
31405
  const serialized = `${JSON.stringify(report, null, 2)}
31160
31406
  `;
31161
31407
  if (report.runId) {
31162
- const runJson = path95.join(artifacts, "runs", `${report.runId}.json`);
31163
- const runMarkdown = path95.join(artifacts, "runs", `${report.runId}.md`);
31408
+ const runJson = path96.join(artifacts, "runs", `${report.runId}.json`);
31409
+ const runMarkdown = path96.join(artifacts, "runs", `${report.runId}.md`);
31164
31410
  if (await pathExists(runJson))
31165
31411
  throw new Error(`immutable testing run already exists: ${report.runId}`);
31166
31412
  await writeContained(cwd, rel(runJson), serialized);
@@ -31171,26 +31417,26 @@ async function writeReport(cwd, report) {
31171
31417
  branch: report.provenance?.branch ?? null,
31172
31418
  worktree: report.provenance?.worktree ?? null,
31173
31419
  generated_at: report.generatedAt,
31174
- record: path95.posix.join("runs", `${report.runId}.json`)
31420
+ record: path96.posix.join("runs", `${report.runId}.json`)
31175
31421
  }, null, 2)}
31176
31422
  `);
31177
31423
  } else {
31178
31424
  await writeContained(cwd, rel(json), serialized);
31179
31425
  }
31180
31426
  await writeContained(cwd, rel(markdown), renderReportMarkdown3(report));
31181
- await writeContained(cwd, rel(path95.join(history, `${stamp}.json`)), serialized);
31427
+ await writeContained(cwd, rel(path96.join(history, `${stamp}.json`)), serialized);
31182
31428
  return {
31183
- markdownPath: path95.relative(cwd, markdown),
31184
- jsonPath: path95.relative(cwd, json)
31429
+ markdownPath: path96.relative(cwd, markdown),
31430
+ jsonPath: path96.relative(cwd, json)
31185
31431
  };
31186
31432
  }
31187
31433
  async function writeRawLog(cwd, raw) {
31188
- const logs = path95.join(testingDataRoot(cwd), "logs");
31189
- const rel = (p) => path95.relative(cwd, p);
31434
+ const logs = path96.join(testingDataRoot(cwd), "logs");
31435
+ const rel = (p) => path96.relative(cwd, p);
31190
31436
  await mkdirContained(cwd, rel(logs));
31191
- const latest = path95.join(logs, "latest.raw.log");
31437
+ const latest = path96.join(logs, "latest.raw.log");
31192
31438
  await writeContained(cwd, rel(latest), raw);
31193
- return path95.relative(cwd, latest);
31439
+ return path96.relative(cwd, latest);
31194
31440
  }
31195
31441
  async function listProjectFiles(cwd) {
31196
31442
  const out = [];
@@ -31201,13 +31447,13 @@ async function listProjectFiles(cwd) {
31201
31447
  async function walk3(root, dir, out, incompleteReasons) {
31202
31448
  let entries;
31203
31449
  try {
31204
- entries = await readdir15(dir, { withFileTypes: true });
31450
+ entries = await readdir16(dir, { withFileTypes: true });
31205
31451
  } catch (error) {
31206
- incompleteReasons.push(`${normalizePath6(path95.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
31452
+ incompleteReasons.push(`${normalizePath6(path96.relative(root, dir)) || "."}: ${error instanceof Error ? error.message : String(error)}`);
31207
31453
  return;
31208
31454
  }
31209
31455
  for (const entry of entries) {
31210
- const abs = path95.join(dir, entry.name);
31456
+ const abs = path96.join(dir, entry.name);
31211
31457
  if (entry.isDirectory()) {
31212
31458
  if (IGNORED_DIRS2.has(entry.name) || entry.name.startsWith(".tmp-")) {
31213
31459
  continue;
@@ -31216,28 +31462,28 @@ async function walk3(root, dir, out, incompleteReasons) {
31216
31462
  continue;
31217
31463
  }
31218
31464
  if (entry.isFile()) {
31219
- out.push(normalizePath6(path95.relative(root, abs)));
31465
+ out.push(normalizePath6(path96.relative(root, abs)));
31220
31466
  }
31221
31467
  }
31222
31468
  }
31223
31469
  async function readPackageJson(cwd) {
31224
- const file = path95.join(cwd, "package.json");
31470
+ const file = path96.join(cwd, "package.json");
31225
31471
  if (!await pathExists(file)) {
31226
31472
  return null;
31227
31473
  }
31228
31474
  try {
31229
- return JSON.parse(await readFile48(file, "utf8"));
31475
+ return JSON.parse(await readFile49(file, "utf8"));
31230
31476
  } catch {
31231
31477
  return null;
31232
31478
  }
31233
31479
  }
31234
31480
  async function loadTestingConfig(cwd) {
31235
- const file = path95.join(cwd, ".metaproject", "testing.config.json");
31481
+ const file = path96.join(cwd, ".metaproject", "testing.config.json");
31236
31482
  if (!await pathExists(file)) {
31237
31483
  return DEFAULT_TESTING_CONFIG;
31238
31484
  }
31239
31485
  try {
31240
- const parsed = JSON.parse(await readFile48(file, "utf8"));
31486
+ const parsed = JSON.parse(await readFile49(file, "utf8"));
31241
31487
  return {
31242
31488
  schemaVersion: parsed.schemaVersion ?? DEFAULT_TESTING_CONFIG.schemaVersion,
31243
31489
  enabled: parsed.enabled ?? DEFAULT_TESTING_CONFIG.enabled,
@@ -31297,11 +31543,11 @@ function detectFrameworks(input) {
31297
31543
  async function extractConventions(cwd, files) {
31298
31544
  const conventions = new Set;
31299
31545
  for (const file of files.slice(0, 40)) {
31300
- const abs = path95.join(cwd, file);
31546
+ const abs = path96.join(cwd, file);
31301
31547
  if (!await pathExists(abs)) {
31302
31548
  continue;
31303
31549
  }
31304
- const text = await readFile48(abs, "utf8");
31550
+ const text = await readFile49(abs, "utf8");
31305
31551
  for (const line of text.split(`
31306
31552
  `)) {
31307
31553
  if (/test|testing|spec|coverage|playwright|vitest|jest|bun:test/i.test(line)) {
@@ -31427,11 +31673,11 @@ async function findTestsByImportedTargets(cwd, targets, testFiles) {
31427
31673
  const targetKeys = new Set(targets.map((target) => modulePathKey(normalizePath6(target))));
31428
31674
  const selected = new Set;
31429
31675
  for (const testFile of testFiles) {
31430
- const absoluteTest = path95.join(cwd, testFile);
31676
+ const absoluteTest = path96.join(cwd, testFile);
31431
31677
  if (!await pathExists(absoluteTest)) {
31432
31678
  continue;
31433
31679
  }
31434
- const content = await readFile48(absoluteTest, "utf8");
31680
+ const content = await readFile49(absoluteTest, "utf8");
31435
31681
  const imports = extractImportPaths(content);
31436
31682
  if (imports.length === 0) {
31437
31683
  continue;
@@ -31461,10 +31707,10 @@ function resolveImportPath(cwd, testFile, importPath) {
31461
31707
  if (!importPath.startsWith(".")) {
31462
31708
  return null;
31463
31709
  }
31464
- const importerDir = path95.dirname(testFile);
31465
- const absoluteResolved = path95.resolve(path95.join(cwd, importerDir), importPath);
31466
- const relative = path95.relative(cwd, absoluteResolved);
31467
- if (relative.startsWith(`..${path95.sep}`) || relative === "..") {
31710
+ const importerDir = path96.dirname(testFile);
31711
+ const absoluteResolved = path96.resolve(path96.join(cwd, importerDir), importPath);
31712
+ const relative = path96.relative(cwd, absoluteResolved);
31713
+ if (relative.startsWith(`..${path96.sep}`) || relative === "..") {
31468
31714
  return null;
31469
31715
  }
31470
31716
  const relativeNormalized = normalizePath6(relative);
@@ -31516,13 +31762,13 @@ function resolveTestCommand(cwd, context, input) {
31516
31762
  }
31517
31763
  var BUN_LOCKFILES = ["bun.lock", "bun.lockb"];
31518
31764
  function detectPackageManager(cwd) {
31519
- if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path95.join(cwd, name)))) {
31765
+ if (resolveBunBin() && BUN_LOCKFILES.some((name) => pathExistsSync(path96.join(cwd, name)))) {
31520
31766
  return "bun";
31521
31767
  }
31522
- if (Bun.which("pnpm") && pathExistsSync(path95.join(cwd, "pnpm-lock.yaml"))) {
31768
+ if (Bun.which("pnpm") && pathExistsSync(path96.join(cwd, "pnpm-lock.yaml"))) {
31523
31769
  return "pnpm";
31524
31770
  }
31525
- if (Bun.which("yarn") && pathExistsSync(path95.join(cwd, "yarn.lock"))) {
31771
+ if (Bun.which("yarn") && pathExistsSync(path96.join(cwd, "yarn.lock"))) {
31526
31772
  return "yarn";
31527
31773
  }
31528
31774
  return "npm";
@@ -31862,7 +32108,7 @@ async function compatibleReportForHealth(ctx) {
31862
32108
 
31863
32109
  // src/health/sources/dependency-audit.ts
31864
32110
  import { existsSync as existsSync13 } from "fs";
31865
- import path96 from "path";
32111
+ import path97 from "path";
31866
32112
  function auditSeverityToPriority(severity) {
31867
32113
  if (severity === "critical" || severity === "high")
31868
32114
  return "P0";
@@ -31981,7 +32227,7 @@ var LOCKFILE_COMMANDS = [
31981
32227
  ];
31982
32228
  function auditCommand(cwd) {
31983
32229
  for (const entry of LOCKFILE_COMMANDS) {
31984
- if (!entry.lockfiles.some((name) => existsSync13(path96.join(cwd, name))))
32230
+ if (!entry.lockfiles.some((name) => existsSync13(path97.join(cwd, name))))
31985
32231
  continue;
31986
32232
  const bin = resolveBin(cwd, entry.bin);
31987
32233
  if (bin)
@@ -32040,13 +32286,13 @@ var dependencyAuditAdapter = {
32040
32286
 
32041
32287
  // src/health/sources/sonarqube.ts
32042
32288
  import { existsSync as existsSync14 } from "fs";
32043
- import path97 from "path";
32289
+ import path98 from "path";
32044
32290
  var REPORT_FILES = ["sonar-issues.json", ".metaproject/data/health/sonar-issues.json"];
32045
32291
  function reportPath(cwd) {
32046
32292
  const fromEnv = process.env.SONAR_ISSUES_FILE;
32047
32293
  const candidates = fromEnv ? [fromEnv, ...REPORT_FILES] : REPORT_FILES;
32048
32294
  for (const rel of candidates) {
32049
- const abs = path97.isAbsolute(rel) ? rel : path97.join(cwd, rel);
32295
+ const abs = path98.isAbsolute(rel) ? rel : path98.join(cwd, rel);
32050
32296
  if (existsSync14(abs)) {
32051
32297
  return abs;
32052
32298
  }
@@ -32130,7 +32376,7 @@ var sonarqubeAdapter = {
32130
32376
  function relativizeComponent(component, cwd) {
32131
32377
  const colon = component.indexOf(":");
32132
32378
  const value = colon >= 0 ? component.slice(colon + 1) : component;
32133
- return path97.isAbsolute(value) ? path97.relative(cwd, value) : value;
32379
+ return path98.isAbsolute(value) ? path98.relative(cwd, value) : value;
32134
32380
  }
32135
32381
 
32136
32382
  // src/health/sources/index.ts
@@ -32467,19 +32713,19 @@ function filteredInfo(source, cfg) {
32467
32713
  };
32468
32714
  }
32469
32715
  async function writeOutputs(cwd, report, config, stamp) {
32470
- const artifacts = path98.join(dataRoot3(cwd), "artifacts");
32471
- const history = path98.join(dataRoot3(cwd), "history");
32716
+ const artifacts = path99.join(dataRoot3(cwd), "artifacts");
32717
+ const history = path99.join(dataRoot3(cwd), "history");
32472
32718
  await mkdir27(artifacts, { recursive: true });
32473
32719
  await mkdir27(history, { recursive: true });
32474
- const markdown = path98.join(artifacts, "latest.md");
32475
- const json = path98.join(artifacts, "latest.json");
32476
- const historyJson = path98.join(history, `${stamp}.json`);
32720
+ const markdown = path99.join(artifacts, "latest.md");
32721
+ const json = path99.join(artifacts, "latest.json");
32722
+ const historyJson = path99.join(history, `${stamp}.json`);
32477
32723
  const serialized = `${JSON.stringify(report, null, 2)}
32478
32724
  `;
32479
32725
  await writeFile20(markdown, renderReportMarkdown2(report, config), "utf8");
32480
32726
  if (report.runId) {
32481
- const runJson = path98.join(artifacts, "runs", `${report.runId}.json`);
32482
- const runMarkdown = path98.join(artifacts, "runs", `${report.runId}.md`);
32727
+ const runJson = path99.join(artifacts, "runs", `${report.runId}.json`);
32728
+ const runMarkdown = path99.join(artifacts, "runs", `${report.runId}.md`);
32483
32729
  if (await pathExists(runJson))
32484
32730
  throw new Error(`immutable health run already exists: ${report.runId}`);
32485
32731
  await writeFileAtomic(runJson, serialized);
@@ -32490,7 +32736,7 @@ async function writeOutputs(cwd, report, config, stamp) {
32490
32736
  branch: report.provenance?.branch ?? null,
32491
32737
  worktree: report.provenance?.worktree ?? null,
32492
32738
  generated_at: report.generatedAt,
32493
- record: path98.posix.join("runs", `${report.runId}.json`)
32739
+ record: path99.posix.join("runs", `${report.runId}.json`)
32494
32740
  }, null, 2)}
32495
32741
  `);
32496
32742
  } else {
@@ -32498,8 +32744,8 @@ async function writeOutputs(cwd, report, config, stamp) {
32498
32744
  }
32499
32745
  await writeFile20(historyJson, serialized, "utf8");
32500
32746
  return {
32501
- markdownPath: path98.relative(cwd, markdown),
32502
- jsonPath: path98.relative(cwd, json)
32747
+ markdownPath: path99.relative(cwd, markdown),
32748
+ jsonPath: path99.relative(cwd, json)
32503
32749
  };
32504
32750
  }
32505
32751
  async function resolveChanged(cwd, selector) {
@@ -32552,7 +32798,7 @@ function hasGateShape(value) {
32552
32798
  return Array.isArray(report.metrics) && Array.isArray(report.sources) && Array.isArray(report.findings);
32553
32799
  }
32554
32800
  async function readLatest(cwd) {
32555
- const file = path99.join(dataRoot3(cwd), "artifacts", "latest.json");
32801
+ const file = path100.join(dataRoot3(cwd), "artifacts", "latest.json");
32556
32802
  if (!await pathExists(file)) {
32557
32803
  return null;
32558
32804
  }
@@ -32563,11 +32809,11 @@ async function readLatest(cwd) {
32563
32809
  const latest = read.value;
32564
32810
  const record = latest.record;
32565
32811
  if (typeof record === "string") {
32566
- const pointer = await readArtifactPointer(path99.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
32812
+ const pointer = await readArtifactPointer(path100.join(dataRoot3(cwd), "artifacts"), await collectGitProvenance(cwd));
32567
32813
  if (pointer.status !== "fresh")
32568
32814
  return null;
32569
- const recordFile = path99.join(dataRoot3(cwd), "artifacts", record);
32570
- if (!isPathInside(path99.join(dataRoot3(cwd), "artifacts"), recordFile))
32815
+ const recordFile = path100.join(dataRoot3(cwd), "artifacts", record);
32816
+ if (!isPathInside(path100.join(dataRoot3(cwd), "artifacts"), recordFile))
32571
32817
  return null;
32572
32818
  if (!await pathExists(recordFile))
32573
32819
  return null;
@@ -32640,7 +32886,7 @@ function createCodeHealthService() {
32640
32886
  return {
32641
32887
  run: (input) => runHealth(input),
32642
32888
  async status(input) {
32643
- const enabled = await pathExists(path99.join(input.cwd, ".metaproject", "health.config.json"));
32889
+ const enabled = await pathExists(path100.join(input.cwd, ".metaproject", "health.config.json"));
32644
32890
  const latest = await readLatest(input.cwd);
32645
32891
  const project = latest?.metrics.find((m) => m.key === "project") ?? null;
32646
32892
  const decliningScopes = latest ? latest.metrics.filter((m) => m.regression_score > 0).length : 0;
@@ -32798,10 +33044,10 @@ function renderEvidenceBlock(evidences, siblings) {
32798
33044
  init_fs();
32799
33045
  init_contained_write();
32800
33046
  init_json();
32801
- import path100 from "path";
33047
+ import path101 from "path";
32802
33048
  import { createHash as createHash16 } from "crypto";
32803
33049
  function impactEvidenceDataRoot(root) {
32804
- return path100.join(root, ".metaproject", "data", "security", "impact-evidence");
33050
+ return path101.join(root, ".metaproject", "data", "security", "impact-evidence");
32805
33051
  }
32806
33052
  function sanitizeSessionId(sessionId) {
32807
33053
  const cleaned = sessionId.replace(/[^A-Za-z0-9._-]/g, "_");
@@ -32813,7 +33059,7 @@ function sessionStateFilename(sessionId) {
32813
33059
  return `${sanitized}-${suffix}.json`;
32814
33060
  }
32815
33061
  function sessionStatePath(root, sessionId) {
32816
- return path100.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
33062
+ return path101.join(impactEvidenceDataRoot(root), "sessions", sessionStateFilename(sessionId));
32817
33063
  }
32818
33064
  async function loadSessionState(root, sessionId) {
32819
33065
  const file = sessionStatePath(root, sessionId);
@@ -32832,11 +33078,11 @@ async function loadSessionState(root, sessionId) {
32832
33078
  }
32833
33079
  async function saveSessionState(root, sessionId, state) {
32834
33080
  const file = sessionStatePath(root, sessionId);
32835
- await writeContained(root, path100.relative(root, file), `${JSON.stringify(state, null, 2)}
33081
+ await writeContained(root, path101.relative(root, file), `${JSON.stringify(state, null, 2)}
32836
33082
  `);
32837
33083
  }
32838
33084
  function logPath(root) {
32839
- return path100.join(impactEvidenceDataRoot(root), "log.jsonl");
33085
+ return path101.join(impactEvidenceDataRoot(root), "log.jsonl");
32840
33086
  }
32841
33087
  async function appendLogRecord(root, record) {
32842
33088
  const full = {
@@ -32847,7 +33093,7 @@ async function appendLogRecord(root, record) {
32847
33093
  ...record.detail !== undefined ? { detail: record.detail } : {}
32848
33094
  };
32849
33095
  const file = logPath(root);
32850
- await appendContained(root, path100.relative(root, file), `${JSON.stringify(full)}
33096
+ await appendContained(root, path101.relative(root, file), `${JSON.stringify(full)}
32851
33097
  `);
32852
33098
  return full;
32853
33099
  }
@@ -32874,7 +33120,7 @@ init_command_risk();
32874
33120
  init_shell_syntax();
32875
33121
  init_fs();
32876
33122
  init_service2();
32877
- import path101 from "path";
33123
+ import path102 from "path";
32878
33124
  import { createHash as createHash17 } from "crypto";
32879
33125
  import { realpathSync as realpathSync2 } from "fs";
32880
33126
  function impactEvidenceHookClass(strict) {
@@ -32890,29 +33136,29 @@ function realpathNearestExisting(p) {
32890
33136
  for (;; ) {
32891
33137
  try {
32892
33138
  const real = realpathSync2(current);
32893
- return tail.length > 0 ? path101.join(real, ...tail) : real;
33139
+ return tail.length > 0 ? path102.join(real, ...tail) : real;
32894
33140
  } catch {
32895
- const parent = path101.dirname(current);
33141
+ const parent = path102.dirname(current);
32896
33142
  if (parent === current) {
32897
- return tail.length > 0 ? path101.join(current, ...tail) : current;
33143
+ return tail.length > 0 ? path102.join(current, ...tail) : current;
32898
33144
  }
32899
- tail.unshift(path101.basename(current));
33145
+ tail.unshift(path102.basename(current));
32900
33146
  current = parent;
32901
33147
  }
32902
33148
  }
32903
33149
  }
32904
33150
  function normalizeRequestFiles(root, files) {
32905
- const rootReal = realpathNearestExisting(path101.resolve(root));
33151
+ const rootReal = realpathNearestExisting(path102.resolve(root));
32906
33152
  const normalized = [];
32907
33153
  const rejected = [];
32908
33154
  for (const file of files) {
32909
- const lexicalAbsolute = path101.isAbsolute(file) ? path101.resolve(file) : path101.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
33155
+ const lexicalAbsolute = path102.isAbsolute(file) ? path102.resolve(file) : path102.resolve(rootReal, toPosix(file).replace(/^\.\//, ""));
32910
33156
  const effective = realpathNearestExisting(lexicalAbsolute);
32911
33157
  if (!isPathInside(rootReal, effective)) {
32912
33158
  rejected.push(file);
32913
33159
  continue;
32914
33160
  }
32915
- normalized.push(toPosix(path101.relative(rootReal, effective)));
33161
+ normalized.push(toPosix(path102.relative(rootReal, effective)));
32916
33162
  }
32917
33163
  return { files: [...new Set(normalized)], rejected };
32918
33164
  }
@@ -33198,7 +33444,7 @@ __export(exports_service8, {
33198
33444
  createJobService: () => createJobService
33199
33445
  });
33200
33446
  import { copyFile, mkdir as mkdir29 } from "fs/promises";
33201
- import path104 from "path";
33447
+ import path105 from "path";
33202
33448
 
33203
33449
  // src/job/types.ts
33204
33450
  var JOB_INTENTS = ["implement", "analyze", "review", "custom"];
@@ -33338,16 +33584,16 @@ function defaultPlan(intent) {
33338
33584
  init_validator();
33339
33585
  init_contracts();
33340
33586
  init_fs();
33341
- import { appendFile as appendFile5, mkdir as mkdir28, readFile as readFile50, readdir as readdir16 } from "fs/promises";
33342
- import path103 from "path";
33587
+ import { appendFile as appendFile5, mkdir as mkdir28, readFile as readFile51, readdir as readdir17 } from "fs/promises";
33588
+ import path104 from "path";
33343
33589
  function jobsRoot(cwd) {
33344
- return path103.join(cwd, ".metaproject", "jobs");
33590
+ return path104.join(cwd, ".metaproject", "jobs");
33345
33591
  }
33346
33592
  function jobDir(cwd, name) {
33347
- return path103.join(jobsRoot(cwd), name);
33593
+ return path104.join(jobsRoot(cwd), name);
33348
33594
  }
33349
33595
  function jobStatePath(cwd, name) {
33350
- return path103.join(jobDir(cwd, name), "state.json");
33596
+ return path104.join(jobDir(cwd, name), "state.json");
33351
33597
  }
33352
33598
  var JOB_NAME_PATTERN = /^[a-z0-9-]+$/;
33353
33599
  function assertJobName(name) {
@@ -33364,7 +33610,7 @@ async function listJobNames(cwd) {
33364
33610
  if (!await pathExists(root)) {
33365
33611
  return [];
33366
33612
  }
33367
- const entries = await readdir16(root, { withFileTypes: true });
33613
+ const entries = await readdir17(root, { withFileTypes: true });
33368
33614
  return entries.filter((entry) => entry.isDirectory() && JOB_NAME_PATTERN.test(entry.name)).map((entry) => entry.name).sort();
33369
33615
  }
33370
33616
  async function readJob(cwd, name) {
@@ -33373,7 +33619,7 @@ async function readJob(cwd, name) {
33373
33619
  const known = await listJobNames(cwd);
33374
33620
  throw new Error(`Job not found: ${name}.` + (known.length > 0 ? ` Known: ${known.join(", ")}` : " Run: keryx job list"));
33375
33621
  }
33376
- return JSON.parse(await readFile50(file, "utf8"));
33622
+ return JSON.parse(await readFile51(file, "utf8"));
33377
33623
  }
33378
33624
  async function writeJob(cwd, name, state) {
33379
33625
  const schema = await loadSchema("job-orchestrator-state");
@@ -33384,12 +33630,12 @@ async function writeJob(cwd, name, state) {
33384
33630
  `));
33385
33631
  }
33386
33632
  const file = jobStatePath(cwd, name);
33387
- await mkdir28(path103.dirname(file), { recursive: true });
33633
+ await mkdir28(path104.dirname(file), { recursive: true });
33388
33634
  await writeFileAtomic(file, `${JSON.stringify(state, null, 2)}
33389
33635
  `);
33390
33636
  }
33391
33637
  async function appendJournal2(cwd, name, at, line) {
33392
- await appendFile5(path103.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
33638
+ await appendFile5(path104.join(jobDir(cwd, name), "journal.md"), `- ${at} - ${line}
33393
33639
  `, "utf8");
33394
33640
  }
33395
33641
  function renderJournal2(name, at) {
@@ -33410,7 +33656,7 @@ function assertDocumentType(raw) {
33410
33656
  return raw;
33411
33657
  }
33412
33658
  function documentFileName(type, sourcePath) {
33413
- const extension = path103.extname(sourcePath) || ".md";
33659
+ const extension = path104.extname(sourcePath) || ".md";
33414
33660
  return `${type}${extension}`;
33415
33661
  }
33416
33662
 
@@ -33418,7 +33664,7 @@ function documentFileName(type, sourcePath) {
33418
33664
  function createJobService(deps) {
33419
33665
  const now = () => deps.now().toISOString();
33420
33666
  function lockPath(cwd, name) {
33421
- return path104.join(jobsRoot(cwd), `.job-lock-${name}`);
33667
+ return path105.join(jobsRoot(cwd), `.job-lock-${name}`);
33422
33668
  }
33423
33669
  async function mutate(cwd, name, run) {
33424
33670
  assertJobName(name);
@@ -33467,20 +33713,20 @@ function createJobService(deps) {
33467
33713
  },
33468
33714
  plan: { steps: defaultPlan(intent) },
33469
33715
  documentation: {
33470
- job_path: path104.join(".metaproject", "jobs", name),
33716
+ job_path: path105.join(".metaproject", "jobs", name),
33471
33717
  documents_created: []
33472
33718
  },
33473
33719
  metrics: { steps: [] },
33474
- jobs_root: path104.join(".metaproject", "jobs"),
33720
+ jobs_root: path105.join(".metaproject", "jobs"),
33475
33721
  updated_at: createdAt
33476
33722
  };
33477
33723
  const first = firstOpenStep(state.plan.steps);
33478
33724
  if (first) {
33479
33725
  state.plan.current_step = first.id;
33480
33726
  }
33481
- await writeFileAtomic(path104.join(absolute, "journal.md"), renderJournal2(name, createdAt));
33727
+ await writeFileAtomic(path105.join(absolute, "journal.md"), renderJournal2(name, createdAt));
33482
33728
  await writeJob(input.cwd, name, state);
33483
- return { state, dir: path104.relative(input.cwd, absolute) };
33729
+ return { state, dir: path105.relative(input.cwd, absolute) };
33484
33730
  },
33485
33731
  async status({ cwd, name }) {
33486
33732
  assertJobName(name);
@@ -33492,7 +33738,7 @@ function createJobService(deps) {
33492
33738
  }
33493
33739
  return {
33494
33740
  state,
33495
- dir: path104.join(".metaproject", "jobs", name),
33741
+ dir: path105.join(".metaproject", "jobs", name),
33496
33742
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
33497
33743
  stepsTotal: state.plan.steps.length,
33498
33744
  nextStep: firstOpenStep(state.plan.steps),
@@ -33549,23 +33795,23 @@ function createJobService(deps) {
33549
33795
  if (!input.file) {
33550
33796
  throw new Error("Missing --file. Usage: keryx job document <name> --type <type> --file <path>");
33551
33797
  }
33552
- const source = path104.isAbsolute(input.file) ? input.file : path104.join(input.cwd, input.file);
33798
+ const source = path105.isAbsolute(input.file) ? input.file : path105.join(input.cwd, input.file);
33553
33799
  if (!await pathExists(source)) {
33554
33800
  throw new Error(`--file not found: ${input.file}. Write the document first, then record it.`);
33555
33801
  }
33556
33802
  let recorded;
33557
33803
  await mutate(input.cwd, input.name, async (state) => {
33558
33804
  const fileName = documentFileName(type, source);
33559
- const target = path104.join(jobDir(input.cwd, state.job_name), fileName);
33805
+ const target = path105.join(jobDir(input.cwd, state.job_name), fileName);
33560
33806
  await copyFile(source, target);
33561
33807
  state.documentation ??= {};
33562
- state.documentation.job_path ??= path104.join(".metaproject", "jobs", state.job_name);
33808
+ state.documentation.job_path ??= path105.join(".metaproject", "jobs", state.job_name);
33563
33809
  const created = state.documentation.documents_created ?? [];
33564
33810
  state.documentation.documents_created = created.includes(fileName) ? created : [...created, fileName];
33565
33811
  recorded = {
33566
33812
  state,
33567
33813
  document: fileName,
33568
- path: path104.join(".metaproject", "jobs", state.job_name, fileName)
33814
+ path: path105.join(".metaproject", "jobs", state.job_name, fileName)
33569
33815
  };
33570
33816
  return { state, event: "document", detail: `${type} -> ${fileName}` };
33571
33817
  });
@@ -33600,7 +33846,7 @@ function createJobService(deps) {
33600
33846
  name: state.job_name,
33601
33847
  phase: state.phase,
33602
33848
  intent: state.intent,
33603
- dir: path104.join(".metaproject", "jobs", name),
33849
+ dir: path105.join(".metaproject", "jobs", name),
33604
33850
  stepsDone: state.plan.steps.filter((step) => isTerminalStep(step.status)).length,
33605
33851
  stepsTotal: state.plan.steps.length,
33606
33852
  nextStep: firstOpenStep(state.plan.steps)?.id ?? null
@@ -33704,13 +33950,13 @@ function normalizeWorkspaceReference(raw) {
33704
33950
 
33705
33951
  // src/sac/fwk-service.ts
33706
33952
  init_assembly();
33707
- import { appendFile as appendFile6, mkdir as mkdir31, open as open3, readFile as readFile53, rename as rename7, rm as rm6, stat as stat13, writeFile as writeFile21 } from "fs/promises";
33708
- import path108 from "path";
33953
+ import { appendFile as appendFile6, mkdir as mkdir31, open as open3, readFile as readFile54, rename as rename7, rm as rm6, stat as stat14, writeFile as writeFile21 } from "fs/promises";
33954
+ import path109 from "path";
33709
33955
 
33710
33956
  // src/sac/index.ts
33711
- import { access as access3, readFile as readFile51, realpath as realpath11 } from "fs/promises";
33957
+ import { access as access3, readFile as readFile52, realpath as realpath12 } from "fs/promises";
33712
33958
  import { createHash as createHash18 } from "crypto";
33713
- import path105 from "path";
33959
+ import path106 from "path";
33714
33960
  import { fileURLToPath as fileURLToPath3 } from "url";
33715
33961
  var idPattern = /^[a-z][a-z0-9-]{2,63}$/;
33716
33962
  var subjectPattern = /^(?:user|team|service|agent):[a-z0-9][a-z0-9._-]{0,127}$/;
@@ -33728,21 +33974,21 @@ var normativeSchemaFiles = {
33728
33974
  "review-decision": "review-decision.schema.json"
33729
33975
  };
33730
33976
  var normativeSchemas = new Map;
33731
- var NORMATIVE_SCHEMA_DIR = path105.join("docs", "requirements", "shared-agent-context", "schemas");
33977
+ var NORMATIVE_SCHEMA_DIR = path106.join("docs", "requirements", "shared-agent-context", "schemas");
33732
33978
  async function resolveSacNormativeSchemaPath(fileName, searchFrom = [fileURLToPath3(new URL(".", import.meta.url)), process.cwd()]) {
33733
33979
  const seen = new Set;
33734
33980
  for (const start of searchFrom) {
33735
- let dir = path105.resolve(start);
33981
+ let dir = path106.resolve(start);
33736
33982
  for (let i = 0;i < 10; i++) {
33737
33983
  if (seen.has(dir))
33738
33984
  break;
33739
33985
  seen.add(dir);
33740
- const candidate = path105.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
33986
+ const candidate = path106.join(dir, NORMATIVE_SCHEMA_DIR, fileName);
33741
33987
  try {
33742
33988
  await access3(candidate);
33743
33989
  return candidate;
33744
33990
  } catch {}
33745
- const parent = path105.dirname(dir);
33991
+ const parent = path106.dirname(dir);
33746
33992
  if (parent === dir)
33747
33993
  break;
33748
33994
  dir = parent;
@@ -33788,7 +34034,7 @@ function isRecord5(value) {
33788
34034
  async function loadNormativeSchema(schema) {
33789
34035
  let pending = normativeSchemas.get(schema);
33790
34036
  if (!pending) {
33791
- pending = resolveSacNormativeSchemaPath(normativeSchemaFiles[schema]).then((file) => readFile51(file, "utf8")).then((source) => JSON.parse(source));
34037
+ pending = resolveSacNormativeSchemaPath(normativeSchemaFiles[schema]).then((file) => readFile52(file, "utf8")).then((source) => JSON.parse(source));
33792
34038
  normativeSchemas.set(schema, pending);
33793
34039
  }
33794
34040
  return pending;
@@ -34411,20 +34657,20 @@ class SacReferenceError extends Error {
34411
34657
  code = "unsafe_workspace_reference";
34412
34658
  }
34413
34659
  async function resolveWorkspaceReference(input) {
34414
- if (!workspacePathPattern.test(input.uri) || path105.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
34660
+ if (!workspacePathPattern.test(input.uri) || path106.isAbsolute(input.uri) || /^[a-z][a-z0-9+.-]*:/i.test(input.uri) || input.uri.includes("\\"))
34415
34661
  throw new SacReferenceError("unsafe workspace reference");
34416
- const lexicalRoot = path105.resolve(input.workspaceRoot);
34417
- const root = await realpath11(lexicalRoot);
34418
- const candidate = path105.resolve(lexicalRoot, input.uri.slice(2));
34419
- if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path105.sep}`))
34662
+ const lexicalRoot = path106.resolve(input.workspaceRoot);
34663
+ const root = await realpath12(lexicalRoot);
34664
+ const candidate = path106.resolve(lexicalRoot, input.uri.slice(2));
34665
+ if (candidate !== lexicalRoot && !candidate.startsWith(`${lexicalRoot}${path106.sep}`))
34420
34666
  throw new SacReferenceError("workspace reference escapes root");
34421
34667
  let resolved;
34422
34668
  try {
34423
- resolved = await realpath11(candidate);
34669
+ resolved = await realpath12(candidate);
34424
34670
  } catch {
34425
34671
  throw new SacReferenceError("workspace reference is not resolvable");
34426
34672
  }
34427
- if (resolved !== root && !resolved.startsWith(`${root}${path105.sep}`))
34673
+ if (resolved !== root && !resolved.startsWith(`${root}${path106.sep}`))
34428
34674
  throw new SacReferenceError("workspace reference escapes root after realpath");
34429
34675
  return candidate;
34430
34676
  }
@@ -34478,18 +34724,18 @@ async function evaluateStrictSacGuard(input) {
34478
34724
 
34479
34725
  // src/sac/workspace-service.ts
34480
34726
  init_fs();
34481
- import { mkdir as mkdir30, readdir as readdir17, readFile as readFile52 } from "fs/promises";
34727
+ import { mkdir as mkdir30, readdir as readdir18, readFile as readFile53 } from "fs/promises";
34482
34728
  import { createHash as createHash19, randomUUID as randomUUID3 } from "crypto";
34483
- import path107 from "path";
34729
+ import path108 from "path";
34484
34730
 
34485
34731
  // src/sac/secure-resource-read.ts
34486
34732
  init_contained_read();
34487
34733
  init_descriptor_read();
34488
- import path106 from "path";
34734
+ import path107 from "path";
34489
34735
  function readWorkspaceFileNoFollow(workspaceRoot, absolutePath) {
34490
- const relativePath = path106.relative(workspaceRoot, absolutePath);
34491
- const components = relativePath.split(path106.sep);
34492
- if (!relativePath || path106.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
34736
+ const relativePath = path107.relative(workspaceRoot, absolutePath);
34737
+ const components = relativePath.split(path107.sep);
34738
+ if (!relativePath || path107.isAbsolute(relativePath) || components.some((component) => !component || component === "." || component === "..")) {
34493
34739
  throw new Error("safe source path is not workspace-relative");
34494
34740
  }
34495
34741
  return readDescriptorChain(workspaceRoot, absolutePath, {
@@ -34516,8 +34762,8 @@ class WorkspaceService {
34516
34762
  now;
34517
34763
  constructor(options) {
34518
34764
  this.options = options;
34519
- this.root = path107.resolve(options.workspaceRoot);
34520
- this.storageRoot = path107.resolve(options.storageRoot ?? path107.join(this.root, ".metaproject", "workspaces"));
34765
+ this.root = path108.resolve(options.workspaceRoot);
34766
+ this.storageRoot = path108.resolve(options.storageRoot ?? path108.join(this.root, ".metaproject", "workspaces"));
34521
34767
  this.now = options.now ?? (() => new Date);
34522
34768
  }
34523
34769
  async create(input) {
@@ -34540,7 +34786,7 @@ class WorkspaceService {
34540
34786
  await mkdir30(this.storageRoot, { recursive: true, mode: 448 });
34541
34787
  await withFileLock(this.lockPath(manifest.id), async () => {
34542
34788
  try {
34543
- await readFile52(this.manifestPath(manifest.id), "utf8");
34789
+ await readFile53(this.manifestPath(manifest.id), "utf8");
34544
34790
  throw new WorkspaceServiceError("conflict", "workspace already exists");
34545
34791
  } catch (error) {
34546
34792
  if (error instanceof WorkspaceServiceError || !isNotFound(error))
@@ -34569,7 +34815,7 @@ class WorkspaceService {
34569
34815
  } catch {
34570
34816
  return [];
34571
34817
  }
34572
- const entries = await readdir17(this.storageRoot, { withFileTypes: true });
34818
+ const entries = await readdir18(this.storageRoot, { withFileTypes: true });
34573
34819
  const visible = [];
34574
34820
  for (const entry of entries) {
34575
34821
  if (!entry.isDirectory())
@@ -34830,7 +35076,7 @@ class WorkspaceService {
34830
35076
  throw new WorkspaceServiceError("not_found", "workspace not found");
34831
35077
  let parsed;
34832
35078
  try {
34833
- parsed = JSON.parse(await readFile52(this.manifestPath(id), "utf8"));
35079
+ parsed = JSON.parse(await readFile53(this.manifestPath(id), "utf8"));
34834
35080
  } catch (error) {
34835
35081
  if (isNotFound(error))
34836
35082
  throw new WorkspaceServiceError("not_found", "workspace not found");
@@ -34842,13 +35088,13 @@ class WorkspaceService {
34842
35088
  return parsed;
34843
35089
  }
34844
35090
  workspaceDir(id) {
34845
- return path107.join(this.storageRoot, id);
35091
+ return path108.join(this.storageRoot, id);
34846
35092
  }
34847
35093
  manifestPath(id) {
34848
- return path107.join(this.workspaceDir(id), "workspace.json");
35094
+ return path108.join(this.workspaceDir(id), "workspace.json");
34849
35095
  }
34850
35096
  lockPath(id) {
34851
- return path107.join(this.storageRoot, `.${id}.lock`);
35097
+ return path108.join(this.storageRoot, `.${id}.lock`);
34852
35098
  }
34853
35099
  timestamp() {
34854
35100
  return this.now().toISOString();
@@ -35457,7 +35703,7 @@ var ledgerDigestChunkBytes = 64 * 1024;
35457
35703
  var isMissing = (error) => error instanceof Error && error.code === "ENOENT";
35458
35704
  var checkpointHash = (body) => createHash22("sha256").update(JSON.stringify(body), "utf8").digest("hex");
35459
35705
  async function ledgerByteLength(ledger) {
35460
- const value = await stat13(ledger, { bigint: true });
35706
+ const value = await stat14(ledger, { bigint: true });
35461
35707
  if (value.size > BigInt(Number.MAX_SAFE_INTEGER))
35462
35708
  throw new Error("invalid access receipt ledger: ledger-too-large");
35463
35709
  return Number(value.size);
@@ -35503,7 +35749,7 @@ function parseCheckpoint(value) {
35503
35749
  }
35504
35750
  async function readCheckpoint(checkpointPath) {
35505
35751
  try {
35506
- const raw = await readFile53(checkpointPath, "utf8");
35752
+ const raw = await readFile54(checkpointPath, "utf8");
35507
35753
  try {
35508
35754
  const checkpoint = parseCheckpoint(JSON.parse(raw));
35509
35755
  return checkpoint ? { present: true, checkpoint } : { present: true };
@@ -35571,7 +35817,7 @@ async function fastCheckpointState(ledger, checkpoint, ledgerBytes) {
35571
35817
  }
35572
35818
  }
35573
35819
  async function auditLedger(ledger, checkpointPath, verifier) {
35574
- const bytes = await readFile53(ledger);
35820
+ const bytes = await readFile54(ledger);
35575
35821
  const raw = bytes.toString("utf8");
35576
35822
  if (raw.length > 0 && !raw.endsWith(`
35577
35823
  `))
@@ -35621,7 +35867,7 @@ var isEvaluationReport = (report) => report.schemaVersion === "1.0" && asString2
35621
35867
  var isConfigRecord = (value) => typeof value.enabled === "boolean" && typeof value.killSwitch === "boolean";
35622
35868
  async function readPinnedJson(input) {
35623
35869
  const ref = await resolveWorkspaceReference({ workspaceRoot: input.workspaceRoot, kind: "artifact", uri: input.uri });
35624
- const raw = await readFile53(ref, "utf8");
35870
+ const raw = await readFile54(ref, "utf8");
35625
35871
  const digest = createHash22("sha256").update(raw).digest("hex");
35626
35872
  if (digest !== input.digest)
35627
35873
  throw new Error("policy experiment pinned artifact digest mismatch");
@@ -35629,7 +35875,7 @@ async function readPinnedJson(input) {
35629
35875
  }
35630
35876
  async function readWorkspaceJson(input) {
35631
35877
  const ref = await resolveWorkspaceReference({ workspaceRoot: input.workspaceRoot, kind: "artifact", uri: input.uri });
35632
- const raw = await readFile53(ref, "utf8");
35878
+ const raw = await readFile54(ref, "utf8");
35633
35879
  return { artifact: JSON.parse(raw), raw };
35634
35880
  }
35635
35881
  function hasReportIntegrity(report) {
@@ -35637,10 +35883,10 @@ function hasReportIntegrity(report) {
35637
35883
  return reportHashPattern.test(reportDigest) && sha2564(body) === reportDigest;
35638
35884
  }
35639
35885
  async function resolvePolicySelection(workspaceRoot, canonicalFallback) {
35640
- const configPath = path108.join(workspaceRoot, ...policyExperimentConfigPath);
35886
+ const configPath = path109.join(workspaceRoot, ...policyExperimentConfigPath);
35641
35887
  let configJson;
35642
35888
  try {
35643
- const raw = await readFile53(configPath, "utf8").catch((error) => {
35889
+ const raw = await readFile54(configPath, "utf8").catch((error) => {
35644
35890
  if (isMissing(error))
35645
35891
  return;
35646
35892
  throw error;
@@ -35835,9 +36081,9 @@ class FwkReadService {
35835
36081
  const recordedAt = nowIso(now);
35836
36082
  const id = `receipt-${randomUUID4().replace(/-/g, "").slice(0, 16)}`;
35837
36083
  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"}` } : {} };
35838
- const ledger = path108.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
35839
- const checkpointPath = path108.join(path108.dirname(ledger), "access-receipts.checkpoint.json");
35840
- await mkdir31(path108.dirname(ledger), { recursive: true, mode: 448 });
36084
+ const ledger = path109.join(this.options.canonical.workspaceRoot, ".metaproject", "context-operations", "access-receipts.jsonl");
36085
+ const checkpointPath = path109.join(path109.dirname(ledger), "access-receipts.checkpoint.json");
36086
+ await mkdir31(path109.dirname(ledger), { recursive: true, mode: 448 });
35841
36087
  return withFileLock(`${ledger}.lock`, async () => {
35842
36088
  const state = await resolveLedgerState(ledger, checkpointPath, this.options.verifyReceiptLedger ?? verifyAccessReceiptLedger);
35843
36089
  const receipt = sealAccessReceipt(base, state.headHash);
@@ -35940,8 +36186,8 @@ function normalizeFwkResult(result) {
35940
36186
  // src/sac/proposal-lifecycle.ts
35941
36187
  init_fs();
35942
36188
  import { createHash as createHash29, randomUUID as randomUUID7 } from "crypto";
35943
- import { appendFile as appendFile7, mkdir as mkdir34, readdir as readdir19, readFile as readFile62 } from "fs/promises";
35944
- import path118 from "path";
36189
+ import { appendFile as appendFile7, mkdir as mkdir34, readdir as readdir20, readFile as readFile63 } from "fs/promises";
36190
+ import path119 from "path";
35945
36191
 
35946
36192
  // src/sac/trusted-wrap-up.ts
35947
36193
  import { createHash as createHash23, randomUUID as randomUUID5 } from "crypto";
@@ -36013,7 +36259,7 @@ function bindingHash(owner, intent) {
36013
36259
  // src/sac/session-wrap-up.ts
36014
36260
  import { createHash as createHash25 } from "crypto";
36015
36261
  import { mkdir as mkdir33, writeFile as writeFile22 } from "fs/promises";
36016
- import path112 from "path";
36262
+ import path113 from "path";
36017
36263
 
36018
36264
  // src/session/store.ts
36019
36265
  init_config_dir();
@@ -36025,12 +36271,12 @@ import {
36025
36271
  renameSync as renameSync2,
36026
36272
  writeFileSync as writeFileSync2
36027
36273
  } from "fs";
36028
- import path111 from "path";
36274
+ import path112 from "path";
36029
36275
 
36030
36276
  // src/session/paths.ts
36031
36277
  import { existsSync as existsSync16 } from "fs";
36032
36278
  import { homedir } from "os";
36033
- import path109 from "path";
36279
+ import path110 from "path";
36034
36280
  function keryxDataDir(override) {
36035
36281
  if (override !== undefined && override.length > 0) {
36036
36282
  return override;
@@ -36042,22 +36288,22 @@ function keryxDataDir(override) {
36042
36288
  const home = homedir();
36043
36289
  if (process.platform === "win32") {
36044
36290
  const appData = process.env.APPDATA;
36045
- const base = appData !== undefined && appData.length > 0 ? appData : path109.join(home, "AppData", "Roaming");
36046
- return path109.join(base, "keryx");
36291
+ const base = appData !== undefined && appData.length > 0 ? appData : path110.join(home, "AppData", "Roaming");
36292
+ return path110.join(base, "keryx");
36047
36293
  }
36048
36294
  const xdg = process.env.XDG_DATA_HOME;
36049
- const base = xdg !== undefined && xdg.length > 0 ? xdg : path109.join(home, ".local", "share");
36050
- return path109.join(base, "keryx");
36295
+ const base = xdg !== undefined && xdg.length > 0 ? xdg : path110.join(home, ".local", "share");
36296
+ return path110.join(base, "keryx");
36051
36297
  }
36052
36298
  function resolveProjectRoot2(cwd) {
36053
- const abs = path109.resolve(cwd);
36299
+ const abs = path110.resolve(cwd);
36054
36300
  let dir = abs;
36055
36301
  for (;; ) {
36056
- const gitPath = path109.join(dir, ".git");
36302
+ const gitPath = path110.join(dir, ".git");
36057
36303
  if (existsSync16(gitPath)) {
36058
36304
  return dir;
36059
36305
  }
36060
- const parent = path109.dirname(dir);
36306
+ const parent = path110.dirname(dir);
36061
36307
  if (parent === dir) {
36062
36308
  break;
36063
36309
  }
@@ -36066,12 +36312,12 @@ function resolveProjectRoot2(cwd) {
36066
36312
  return abs;
36067
36313
  }
36068
36314
  function projectKeyFromPath(projectPath) {
36069
- const abs = path109.resolve(projectPath);
36315
+ const abs = path110.resolve(projectPath);
36070
36316
  const encoded = encodeURIComponent(abs);
36071
36317
  if (encoded.length <= 200) {
36072
36318
  return encoded;
36073
36319
  }
36074
- const base = path109.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
36320
+ const base = path110.basename(abs).replace(/[^a-zA-Z0-9._-]+/g, "_").slice(0, 40);
36075
36321
  let h = 0;
36076
36322
  for (let i = 0;i < abs.length; i++) {
36077
36323
  h = Math.imul(31, h) + abs.charCodeAt(i) | 0;
@@ -36081,17 +36327,17 @@ function projectKeyFromPath(projectPath) {
36081
36327
  }
36082
36328
  function projectSessionsDir(projectPath, dataDir) {
36083
36329
  const key = projectKeyFromPath(resolveProjectRoot2(projectPath));
36084
- return path109.join(keryxDataDir(dataDir), "sessions", key);
36330
+ return path110.join(keryxDataDir(dataDir), "sessions", key);
36085
36331
  }
36086
36332
  function sessionDir(projectPath, sessionId, dataDir) {
36087
- return path109.join(projectSessionsDir(projectPath, dataDir), sessionId);
36333
+ return path110.join(projectSessionsDir(projectPath, dataDir), sessionId);
36088
36334
  }
36089
36335
 
36090
36336
  // src/session/slate.ts
36091
36337
  init_fs();
36092
36338
  init_assembly();
36093
- import { mkdir as mkdir32, readFile as readFile54, rm as rm7 } from "fs/promises";
36094
- import path110 from "path";
36339
+ import { mkdir as mkdir32, readFile as readFile55, rm as rm7 } from "fs/promises";
36340
+ import path111 from "path";
36095
36341
  init_redact();
36096
36342
  var SLATE_SEED_KINDS = [
36097
36343
  "decision",
@@ -36106,14 +36352,14 @@ function isSlateSeedKind(value) {
36106
36352
  }
36107
36353
  var SEED_TEXT_MAX_LENGTH = 4000;
36108
36354
  function slatePath(dir) {
36109
- return path110.join(dir, "slate.json");
36355
+ return path111.join(dir, "slate.json");
36110
36356
  }
36111
36357
  function slateLockPath(dir) {
36112
36358
  return `${slatePath(dir)}.lock`;
36113
36359
  }
36114
36360
  async function readSlate(dir) {
36115
36361
  try {
36116
- const raw = await readFile54(slatePath(dir), "utf8");
36362
+ const raw = await readFile55(slatePath(dir), "utf8");
36117
36363
  return JSON.parse(raw);
36118
36364
  } catch (error) {
36119
36365
  if (isNotFound(error))
@@ -36329,11 +36575,11 @@ function listSessions(cwd, dataDir) {
36329
36575
  if (name.startsWith(".")) {
36330
36576
  continue;
36331
36577
  }
36332
- const summary = readSummaryFile(path111.join(root, name, "summary.json"));
36578
+ const summary = readSummaryFile(path112.join(root, name, "summary.json"));
36333
36579
  if (summary === undefined) {
36334
36580
  continue;
36335
36581
  }
36336
- if (path111.resolve(summary.projectPath) !== path111.resolve(projectPath)) {
36582
+ if (path112.resolve(summary.projectPath) !== path112.resolve(projectPath)) {
36337
36583
  continue;
36338
36584
  }
36339
36585
  out.push(summary);
@@ -36366,15 +36612,15 @@ async function readSessionSlate(cwd, sessionId, dataDir) {
36366
36612
  }
36367
36613
  function loadContext(cwd, sessionId, dataDir) {
36368
36614
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
36369
- const contextPath = path111.join(dir, "context.jsonl");
36615
+ const contextPath = path112.join(dir, "context.jsonl");
36370
36616
  if (existsSync17(contextPath)) {
36371
36617
  return readJsonl2(contextPath);
36372
36618
  }
36373
- return readJsonl2(path111.join(dir, "transcript.jsonl"));
36619
+ return readJsonl2(path112.join(dir, "transcript.jsonl"));
36374
36620
  }
36375
36621
  function loadArchive(cwd, sessionId, dataDir, onDegraded) {
36376
36622
  const dir = sessionDir(resolveProjectRoot2(cwd), sessionId, dataDir);
36377
- const archivePath = path111.join(dir, "archive.jsonl");
36623
+ const archivePath = path112.join(dir, "archive.jsonl");
36378
36624
  if (existsSync17(archivePath)) {
36379
36625
  try {
36380
36626
  const archive = readJsonl2(archivePath);
@@ -36558,7 +36804,7 @@ function sessionEvidenceRef(workspaceId, sessionId) {
36558
36804
  }
36559
36805
  async function resolveSessionWrapUp(input) {
36560
36806
  const now = input.now ?? (() => new Date);
36561
- const sessionId = path112.posix.basename(input.sourceRef, ".md");
36807
+ const sessionId = path113.posix.basename(input.sourceRef, ".md");
36562
36808
  const summary = findSession(input.cwd, sessionId);
36563
36809
  if (summary === undefined || input.sourceRef !== sessionEvidenceRef(input.workspaceId, summary.id)) {
36564
36810
  throw new SessionWrapUpError("session_not_found", `no session matching "${input.sourceRef}" in this project \u2014 use \`keryx sessions list\``);
@@ -36575,7 +36821,7 @@ async function resolveSessionWrapUp(input) {
36575
36821
  throw new SessionWrapUpError("session_unreadable", `session "${summary.id}" could not be read: ${cause.message}`);
36576
36822
  }
36577
36823
  const relPath = sessionEvidenceRef(input.workspaceId, summary.id).slice(2);
36578
- const evidenceDir = path112.dirname(relPath);
36824
+ const evidenceDir = path113.dirname(relPath);
36579
36825
  const slate = await readSessionSlate(input.cwd, summary.id);
36580
36826
  const diff = await gitDiff(input.cwd);
36581
36827
  const diffBody = diff.kind === "measured" ? diff.text : unmeasurableDiffBody(diff.detail);
@@ -36597,23 +36843,23 @@ async function resolveSessionWrapUp(input) {
36597
36843
  ""
36598
36844
  ].join(`
36599
36845
  `);
36600
- const wrapUpRelPath = path112.join(evidenceDir, `${summary.id}.wrap-up.md`);
36601
- const diffRelPath = path112.join(evidenceDir, `${summary.id}.diff.txt`);
36602
- const noticeRelPath = path112.join(evidenceDir, `${summary.id}.redaction.md`);
36846
+ const wrapUpRelPath = path113.join(evidenceDir, `${summary.id}.wrap-up.md`);
36847
+ const diffRelPath = path113.join(evidenceDir, `${summary.id}.diff.txt`);
36848
+ const noticeRelPath = path113.join(evidenceDir, `${summary.id}.redaction.md`);
36603
36849
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
36604
- { name: path112.basename(relPath), content: markdown, path: relPath, source: "generated" },
36605
- { name: path112.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
36606
- { name: path112.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
36850
+ { name: path113.basename(relPath), content: markdown, path: relPath, source: "generated" },
36851
+ { name: path113.basename(wrapUpRelPath), content: wrapUpMarkdown, path: wrapUpRelPath, source: "generated" },
36852
+ { name: path113.basename(diffRelPath), content: diffBody, path: diffRelPath, source: "tool-output" }
36607
36853
  ]);
36608
36854
  if (!floor.ok)
36609
36855
  throw new SessionWrapUpError("security_denied", floor.reason);
36610
36856
  const [safeSession, safeWrapUp, safeDiff] = floor.bodies;
36611
- await mkdir33(path112.join(input.cwd, evidenceDir), { recursive: true });
36612
- await writeFile22(path112.join(input.cwd, relPath), safeSession.content, "utf8");
36613
- await writeFile22(path112.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
36614
- await writeFile22(path112.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
36857
+ await mkdir33(path113.join(input.cwd, evidenceDir), { recursive: true });
36858
+ await writeFile22(path113.join(input.cwd, relPath), safeSession.content, "utf8");
36859
+ await writeFile22(path113.join(input.cwd, wrapUpRelPath), safeWrapUp.content, "utf8");
36860
+ await writeFile22(path113.join(input.cwd, diffRelPath), safeDiff.content, "utf8");
36615
36861
  if (floor.notice !== undefined)
36616
- await writeFile22(path112.join(input.cwd, noticeRelPath), floor.notice, "utf8");
36862
+ await writeFile22(path113.join(input.cwd, noticeRelPath), floor.notice, "utf8");
36617
36863
  const observedAt = now().toISOString();
36618
36864
  const evidence = [
36619
36865
  { kind: "wrap-up", uri: `./${wrapUpRelPath}`, revision: createHash25("sha256").update(safeWrapUp.content).digest("hex"), observedAt },
@@ -36635,14 +36881,14 @@ async function resolveSessionWrapUp(input) {
36635
36881
  // src/sac/review-confirm-token.ts
36636
36882
  init_fs();
36637
36883
  import { createHash as createHash26, randomBytes as randomBytes5 } from "crypto";
36638
- import { readFile as readFile55 } from "fs/promises";
36639
- import path113 from "path";
36884
+ import { readFile as readFile56 } from "fs/promises";
36885
+ import path114 from "path";
36640
36886
  var CONFIRM_TOKEN_TTL_MS = 2 * 60000;
36641
36887
  function confirmTokenPath2(cwd, workspaceId, proposalId) {
36642
- return path113.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
36888
+ return path114.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.confirm-token.json`);
36643
36889
  }
36644
36890
  function confirmReceiptPath(cwd, workspaceId, proposalId, idempotencyKey) {
36645
- return path113.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2565(idempotencyKey)}.confirm-receipt.json`);
36891
+ return path114.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${sha2565(idempotencyKey)}.confirm-receipt.json`);
36646
36892
  }
36647
36893
  function sha2565(text) {
36648
36894
  return createHash26("sha256").update(text).digest("hex");
@@ -36658,7 +36904,7 @@ async function consumeConfirmToken(cwd, workspaceId, proposalId, idempotencyKey,
36658
36904
  return { ok: false, reason: "token_required" };
36659
36905
  let stored;
36660
36906
  try {
36661
- stored = JSON.parse(await readFile55(file, "utf8"));
36907
+ stored = JSON.parse(await readFile56(file, "utf8"));
36662
36908
  } catch (error) {
36663
36909
  return { ok: false, reason: isNotFound(error) ? "token_required" : "token_invalid" };
36664
36910
  }
@@ -36681,28 +36927,28 @@ async function consumeConfirmToken(cwd, workspaceId, proposalId, idempotencyKey,
36681
36927
  init_dedup();
36682
36928
  init_store();
36683
36929
  init_config();
36684
- import { readFile as readFile57, readdir as readdir18 } from "fs/promises";
36930
+ import { readFile as readFile58, readdir as readdir19 } from "fs/promises";
36685
36931
  import { randomUUID as randomUUID6 } from "crypto";
36686
- import path115 from "path";
36932
+ import path116 from "path";
36687
36933
 
36688
36934
  // src/sac/proposal-evidence.ts
36689
36935
  init_fs();
36690
36936
  import { createHash as createHash27 } from "crypto";
36691
- import { readFile as readFile56, rm as rm8 } from "fs/promises";
36692
- import path114 from "path";
36937
+ import { readFile as readFile57, rm as rm8 } from "fs/promises";
36938
+ import path115 from "path";
36693
36939
  function proposalPath(cwd, workspaceId, proposalId) {
36694
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
36940
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
36695
36941
  }
36696
36942
  function ownerReceiptPath(cwd, owner, workspaceId, idempotencyKey) {
36697
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
36943
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-receipts`, `${idempotencyKey}.json`);
36698
36944
  }
36699
36945
  function proposalNotePath(cwd, workspaceId, proposalId) {
36700
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
36946
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.note.txt`);
36701
36947
  }
36702
36948
  async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
36703
36949
  let proposal;
36704
36950
  try {
36705
- proposal = JSON.parse(await readFile56(proposalPath(cwd, workspaceId, proposalId), "utf8"));
36951
+ proposal = JSON.parse(await readFile57(proposalPath(cwd, workspaceId, proposalId), "utf8"));
36706
36952
  } catch {
36707
36953
  return { ok: false, code: "proposal_record_unreadable" };
36708
36954
  }
@@ -36711,7 +36957,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
36711
36957
  return { ok: false, code: "no_evidence_to_write" };
36712
36958
  let content;
36713
36959
  try {
36714
- content = await readFile56(path114.join(cwd, evidence.uri), "utf8");
36960
+ content = await readFile57(path115.join(cwd, evidence.uri), "utf8");
36715
36961
  } catch {
36716
36962
  return { ok: false, code: "evidence_file_unreadable" };
36717
36963
  }
@@ -36721,7 +36967,7 @@ async function readVerifiedProposalEvidence(cwd, workspaceId, proposalId) {
36721
36967
  return { proposal, evidence, content };
36722
36968
  }
36723
36969
  async function readSidecarNote(cwd, workspaceId, proposalId) {
36724
- return readFile56(proposalNotePath(cwd, workspaceId, proposalId), "utf8").catch(() => {
36970
+ return readFile57(proposalNotePath(cwd, workspaceId, proposalId), "utf8").catch(() => {
36725
36971
  return;
36726
36972
  });
36727
36973
  }
@@ -36730,7 +36976,7 @@ function digestOf2(content) {
36730
36976
  }
36731
36977
  async function readTargetVersion(absolutePath) {
36732
36978
  try {
36733
- return digestOf2(await readFile56(absolutePath, "utf8"));
36979
+ return digestOf2(await readFile57(absolutePath, "utf8"));
36734
36980
  } catch (error) {
36735
36981
  if (isNotFound(error))
36736
36982
  return null;
@@ -36741,26 +36987,26 @@ function targetRelPath(targetRef) {
36741
36987
  return targetRef.replace(/^\.\//, "");
36742
36988
  }
36743
36989
  function targetAbsolutePath(cwd, targetRef) {
36744
- return path114.join(cwd, ".metaproject", targetRelPath(targetRef));
36990
+ return path115.join(cwd, ".metaproject", targetRelPath(targetRef));
36745
36991
  }
36746
36992
  function targetKey(targetRef) {
36747
36993
  return digestOf2(targetRelPath(targetRef)).slice(0, 32);
36748
36994
  }
36749
36995
  function ownerTargetVersionPath(cwd, owner, workspaceId, targetRef) {
36750
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
36996
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-target-versions`, `${targetKey(targetRef)}.json`);
36751
36997
  }
36752
36998
  function ownerTargetLockPath(cwd, owner, targetRef) {
36753
- return path114.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
36999
+ return path115.join(cwd, ".metaproject", "data", "sac", "target-locks", owner, `${targetKey(targetRef)}.lock`);
36754
37000
  }
36755
37001
  function ownerStagingDir(cwd, owner, workspaceId, idempotencyKey) {
36756
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
37002
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-staging`, digestOf2(idempotencyKey).slice(0, 32));
36757
37003
  }
36758
37004
  function ownerConflictDir(cwd, owner, workspaceId, idempotencyKey) {
36759
- return path114.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
37005
+ return path115.join(cwd, ".metaproject", "workspaces", workspaceId, `${owner}-write-conflicts`, digestOf2(idempotencyKey).slice(0, 32));
36760
37006
  }
36761
37007
  async function readJson2(file) {
36762
37008
  try {
36763
- return JSON.parse(await readFile56(file, "utf8"));
37009
+ return JSON.parse(await readFile57(file, "utf8"));
36764
37010
  } catch {
36765
37011
  return;
36766
37012
  }
@@ -36827,7 +37073,7 @@ async function applyGuardedTargetWrite(input) {
36827
37073
  staged: input.staged,
36828
37074
  stagedAt: receipt.completedAt
36829
37075
  };
36830
- await writeFileAtomic(path114.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
37076
+ await writeFileAtomic(path115.join(ownerStagingDir(cwd, owner, intent.workspaceId, intent.idempotencyKey), "plan.json"), `${JSON.stringify(staged, null, 2)}
36831
37077
  `);
36832
37078
  const applied = await input.apply(input.staged);
36833
37079
  if (!applied.ok) {
@@ -36853,15 +37099,15 @@ async function recoverStagedOwnerWrite(input) {
36853
37099
  });
36854
37100
  }
36855
37101
  async function readStagedOwnerWrite(cwd, owner, workspaceId, idempotencyKey) {
36856
- return readJson2(path114.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
37102
+ return readJson2(path115.join(ownerStagingDir(cwd, owner, workspaceId, idempotencyKey), "plan.json"));
36857
37103
  }
36858
37104
  async function recordConflict(input) {
36859
37105
  const base = { targetRef: input.targetRef, expectedVersion: input.expectedVersion, currentVersion: input.currentVersion };
36860
37106
  if (input.proposedContent === undefined)
36861
37107
  return base;
36862
37108
  const dir = ownerConflictDir(input.cwd, input.owner, input.intent.workspaceId, input.intent.idempotencyKey);
36863
- await writeFileAtomic(path114.join(dir, "proposed"), input.proposedContent);
36864
- const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path114.basename(dir)}/proposed`;
37109
+ await writeFileAtomic(path115.join(dir, "proposed"), input.proposedContent);
37110
+ const diffRef = `./workspaces/${input.intent.workspaceId}/${input.owner}-write-conflicts/${path115.basename(dir)}/proposed`;
36865
37111
  return { ...base, diffRef };
36866
37112
  }
36867
37113
 
@@ -36911,21 +37157,21 @@ async function resolveWorkspaceModule(cwd, workspaceId) {
36911
37157
  }
36912
37158
  }
36913
37159
  async function collectWikiDecisionEntries(cwd) {
36914
- const dir = path115.join(cwd, ".metaproject", "wiki", "decisions");
37160
+ const dir = path116.join(cwd, ".metaproject", "wiki", "decisions");
36915
37161
  let files;
36916
37162
  try {
36917
- files = (await readdir18(dir)).filter((name) => name.endsWith(".md"));
37163
+ files = (await readdir19(dir)).filter((name) => name.endsWith(".md"));
36918
37164
  } catch {
36919
37165
  return [];
36920
37166
  }
36921
37167
  const entries = [];
36922
37168
  for (const file of files) {
36923
- const absolutePath = path115.join(dir, file);
37169
+ const absolutePath = path116.join(dir, file);
36924
37170
  try {
36925
- const content = await readFile57(absolutePath, "utf8");
37171
+ const content = await readFile58(absolutePath, "utf8");
36926
37172
  entries.push({
36927
37173
  absolutePath,
36928
- relativePath: path115.posix.join("decisions", file),
37174
+ relativePath: path116.posix.join("decisions", file),
36929
37175
  type: extractHeaderField(content, "Type") ?? "decision",
36930
37176
  title: extractTitle(content),
36931
37177
  version: extractHeaderField(content, "Version") ?? null,
@@ -37039,7 +37285,7 @@ ${candidates}`;
37039
37285
 
37040
37286
  // src/sac/memory-owner-writer.ts
37041
37287
  init_write();
37042
- import { readFile as readFile58 } from "fs/promises";
37288
+ import { readFile as readFile59 } from "fs/promises";
37043
37289
  function renderWrapUpMemoryEntry(input) {
37044
37290
  const note = input.note?.trim();
37045
37291
  return `# ${input.title}
@@ -37098,7 +37344,7 @@ function createRealMemoryOwnerWriter(cwd, opts) {
37098
37344
  },
37099
37345
  async recover(intent) {
37100
37346
  try {
37101
- const raw = await readFile58(ownerReceiptPath(cwd, "memory", intent.workspaceId, intent.idempotencyKey), "utf8");
37347
+ const raw = await readFile59(ownerReceiptPath(cwd, "memory", intent.workspaceId, intent.idempotencyKey), "utf8");
37102
37348
  return JSON.parse(raw);
37103
37349
  } catch {
37104
37350
  return;
@@ -37146,8 +37392,8 @@ function createRealMemoryOwnerWriter(cwd, opts) {
37146
37392
  // src/sac/wiki-owner-writer.ts
37147
37393
  init_fs();
37148
37394
  init_guard();
37149
- import { readFile as readFile59 } from "fs/promises";
37150
- import path116 from "path";
37395
+ import { readFile as readFile60 } from "fs/promises";
37396
+ import path117 from "path";
37151
37397
  function renderWrapUpDecisionPage(input) {
37152
37398
  const note = input.note?.trim();
37153
37399
  return `# ${input.title}
@@ -37188,14 +37434,14 @@ export is the source of truth for what actually happened.
37188
37434
  `;
37189
37435
  }
37190
37436
  function wikiPageRelativePath(proposalId) {
37191
- return path116.posix.join("decisions", `sac-${proposalId}.md`);
37437
+ return path117.posix.join("decisions", `sac-${proposalId}.md`);
37192
37438
  }
37193
37439
  function createRealWikiOwnerWriter(cwd, opts) {
37194
37440
  const now = opts?.now ?? (() => new Date);
37195
37441
  const applyStaged = async (staged) => {
37196
37442
  const relativePath = staged.relativePath;
37197
37443
  const content = staged.content;
37198
- await writeFileAtomic(path116.join(cwd, ".metaproject", "wiki", relativePath), content);
37444
+ await writeFileAtomic(path117.join(cwd, ".metaproject", "wiki", relativePath), content);
37199
37445
  return { ok: true };
37200
37446
  };
37201
37447
  return {
@@ -37204,7 +37450,7 @@ function createRealWikiOwnerWriter(cwd, opts) {
37204
37450
  },
37205
37451
  async recover(intent) {
37206
37452
  try {
37207
- const raw = await readFile59(ownerReceiptPath(cwd, "wiki", intent.workspaceId, intent.idempotencyKey), "utf8");
37453
+ const raw = await readFile60(ownerReceiptPath(cwd, "wiki", intent.workspaceId, intent.idempotencyKey), "utf8");
37208
37454
  return JSON.parse(raw);
37209
37455
  } catch {
37210
37456
  return;
@@ -37255,7 +37501,7 @@ function createRealWikiOwnerWriter(cwd, opts) {
37255
37501
  }
37256
37502
 
37257
37503
  // src/sac/skill-owner-writer.ts
37258
- import { readFile as readFile61 } from "fs/promises";
37504
+ import { readFile as readFile62 } from "fs/promises";
37259
37505
 
37260
37506
  // src/gdskills/project-skills.ts
37261
37507
  init_contained_write();
@@ -37264,8 +37510,8 @@ init_json();
37264
37510
  init_guard();
37265
37511
  import { createHash as createHash28 } from "crypto";
37266
37512
  import { homedir as homedir2 } from "os";
37267
- import { readFile as readFile60, stat as stat14 } from "fs/promises";
37268
- import path117 from "path";
37513
+ import { readFile as readFile61, stat as stat15 } from "fs/promises";
37514
+ import path118 from "path";
37269
37515
  var VERSION = "0.1.0";
37270
37516
  var PROJECT_SKILLS_DIR = ".metaproject/project-skills";
37271
37517
  var PROJECT_SKILLS_MANIFEST_PATH = ".metaproject/metaproject.json";
@@ -37295,7 +37541,7 @@ async function assertProjectWritesContained(projectRoot, paths) {
37295
37541
  }
37296
37542
  }
37297
37543
  async function createProjectSkill(projectRoot, options) {
37298
- const metaprojectRoot = path117.join(projectRoot, ".metaproject");
37544
+ const metaprojectRoot = path118.join(projectRoot, ".metaproject");
37299
37545
  if (!await pathExists(metaprojectRoot)) {
37300
37546
  throw new Error("Metaproject is not initialized. Run: keryx init");
37301
37547
  }
@@ -37306,7 +37552,7 @@ async function createProjectSkill(projectRoot, options) {
37306
37552
  const skillName = projectSkillSlug(options.name ?? inferSkillName(options.target));
37307
37553
  const format = options.format ?? "auto";
37308
37554
  const relativeSkillPath = projectSkillPackagePath(moduleName, skillName);
37309
- const packageRoot = path117.join(projectRoot, relativeSkillPath);
37555
+ const packageRoot = path118.join(projectRoot, relativeSkillPath);
37310
37556
  await assertProjectWritesContained(projectRoot, projectSkillWritePaths(moduleName, skillName, format));
37311
37557
  const origin = options.origin ? options.originContent !== undefined ? {
37312
37558
  ref: options.origin.trim(),
@@ -37317,7 +37563,7 @@ async function createProjectSkill(projectRoot, options) {
37317
37563
  const warnings = collectWarnings(evidence, format);
37318
37564
  const files = filesForPackage(packageRoot, format);
37319
37565
  if (!options.dryRun) {
37320
- await withFileLock(path117.join(projectRoot, PROJECT_SKILLS_LOCK_PATH), async () => {
37566
+ await withFileLock(path118.join(projectRoot, PROJECT_SKILLS_LOCK_PATH), async () => {
37321
37567
  await writeProjectSkillPackage({
37322
37568
  projectRoot,
37323
37569
  packageRoot,
@@ -37346,7 +37592,7 @@ async function createProjectSkill(projectRoot, options) {
37346
37592
  name: skillName,
37347
37593
  target: options.target,
37348
37594
  skillPath: relativeSkillPath,
37349
- files: files.map((filePath) => toPosix(path117.relative(projectRoot, filePath))),
37595
+ files: files.map((filePath) => toPosix(path118.relative(projectRoot, filePath))),
37350
37596
  warnings,
37351
37597
  dryRun: options.dryRun === true
37352
37598
  };
@@ -37355,9 +37601,9 @@ var MAX_SKILL_TARGET_LENGTH = 80;
37355
37601
  function resolveOriginPath(ref, projectRoot) {
37356
37602
  const trimmed = ref.trim();
37357
37603
  if (trimmed === "~" || trimmed.startsWith("~/")) {
37358
- return path117.join(homedir2(), trimmed.slice(1));
37604
+ return path118.join(homedir2(), trimmed.slice(1));
37359
37605
  }
37360
- return path117.resolve(projectRoot, trimmed);
37606
+ return path118.resolve(projectRoot, trimmed);
37361
37607
  }
37362
37608
  function hashOriginContent(content) {
37363
37609
  return `sha256:${createHash28("sha256").update(content).digest("hex")}`;
@@ -37366,7 +37612,7 @@ async function readSkillOrigin(projectRoot, ref, now = () => new Date) {
37366
37612
  const resolved = resolveOriginPath(ref, projectRoot);
37367
37613
  let content;
37368
37614
  try {
37369
- content = await readFile60(resolved, "utf8");
37615
+ content = await readFile61(resolved, "utf8");
37370
37616
  } catch (cause) {
37371
37617
  throw new Error(`Cannot read the origin file ${ref} (resolved to ${resolved}): ${cause instanceof Error ? cause.message : String(cause)}`);
37372
37618
  }
@@ -37395,16 +37641,16 @@ async function writeProjectSkillPackage({
37395
37641
  }) {
37396
37642
  const packageFormat = format === "single" ? "single" : "package";
37397
37643
  const skillContent = renderProjectSkill({ moduleName, skillName, target, note, origin, evidence, packageFormat });
37398
- const relativeSkillMdPath = toPosix(path117.join(path117.relative(projectRoot, packageRoot), "SKILL.md"));
37644
+ const relativeSkillMdPath = toPosix(path118.join(path118.relative(projectRoot, packageRoot), "SKILL.md"));
37399
37645
  const guard = await guardOutput({ cwd: projectRoot, content: skillContent, target: "skill", source: "generated", path: relativeSkillMdPath });
37400
37646
  const output = prepareOutputForPersistence(guard, skillContent);
37401
37647
  if (!output.allowed) {
37402
37648
  throw new Error(`Project skill blocked by the security gate: ${output.reason}`);
37403
37649
  }
37404
- const packageRel = toPosix(path117.relative(projectRoot, packageRoot));
37650
+ const packageRel = toPosix(path118.relative(projectRoot, packageRoot));
37405
37651
  const write = (file, content) => writeContained(projectRoot, `${packageRel}/${file}`, content);
37406
37652
  await write("SKILL.md", output.content);
37407
- if (!await pathExists(path117.join(packageRoot, "skill-changelog.md"))) {
37653
+ if (!await pathExists(path118.join(packageRoot, "skill-changelog.md"))) {
37408
37654
  await write("skill-changelog.md", renderSkillChangelog({ moduleName, skillName, target }));
37409
37655
  }
37410
37656
  if (packageFormat === "package") {
@@ -37414,10 +37660,10 @@ async function writeProjectSkillPackage({
37414
37660
  }
37415
37661
  }
37416
37662
  async function collectEvidence(projectRoot, target) {
37417
- const absoluteTarget = path117.resolve(projectRoot, target);
37663
+ const absoluteTarget = path118.resolve(projectRoot, target);
37418
37664
  const targetExists = await pathExists(absoluteTarget);
37419
37665
  const targetKind = await classifyTarget(absoluteTarget, targetExists);
37420
- const maybeRelativeTarget = targetExists ? toPosix(path117.relative(projectRoot, absoluteTarget)) : undefined;
37666
+ const maybeRelativeTarget = targetExists ? toPosix(path118.relative(projectRoot, absoluteTarget)) : undefined;
37421
37667
  const graphArtifacts = await existingRelativePaths(projectRoot, [
37422
37668
  ".metaproject/data/gdgraph/artifacts/summary.md",
37423
37669
  ".metaproject/data/gdgraph/artifacts/module-map.json"
@@ -37441,13 +37687,13 @@ async function classifyTarget(absoluteTarget, targetExists) {
37441
37687
  if (!targetExists) {
37442
37688
  return "symbol-or-concept";
37443
37689
  }
37444
- const stats = await stat14(absoluteTarget);
37690
+ const stats = await stat15(absoluteTarget);
37445
37691
  return stats.isDirectory() ? "directory" : "file";
37446
37692
  }
37447
37693
  async function existingRelativePaths(projectRoot, candidates) {
37448
37694
  const existing = [];
37449
37695
  for (const candidate of candidates) {
37450
- if (await pathExists(path117.join(projectRoot, candidate))) {
37696
+ if (await pathExists(path118.join(projectRoot, candidate))) {
37451
37697
  existing.push(candidate);
37452
37698
  }
37453
37699
  }
@@ -37474,17 +37720,17 @@ function collectWarnings(evidence, format) {
37474
37720
  }
37475
37721
  function filesForPackage(packageRoot, format) {
37476
37722
  const base = [
37477
- path117.join(packageRoot, "SKILL.md"),
37478
- path117.join(packageRoot, "skill-changelog.md")
37723
+ path118.join(packageRoot, "SKILL.md"),
37724
+ path118.join(packageRoot, "skill-changelog.md")
37479
37725
  ];
37480
37726
  if (format === "single") {
37481
37727
  return base;
37482
37728
  }
37483
37729
  return [
37484
37730
  ...base,
37485
- path117.join(packageRoot, "verification.md"),
37486
- path117.join(packageRoot, "references", "context.md"),
37487
- path117.join(packageRoot, "templates", "README.md")
37731
+ path118.join(packageRoot, "verification.md"),
37732
+ path118.join(packageRoot, "references", "context.md"),
37733
+ path118.join(packageRoot, "templates", "README.md")
37488
37734
  ];
37489
37735
  }
37490
37736
  function renderProjectSkill({
@@ -37712,7 +37958,7 @@ keryx skills verify ${moduleName}/${skillName}
37712
37958
  `;
37713
37959
  }
37714
37960
  async function updateManifest(projectRoot, entry) {
37715
- const manifestPath = path117.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
37961
+ const manifestPath = path118.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
37716
37962
  const manifest = await readJsonFileOr(manifestPath, {});
37717
37963
  manifest.modules ??= {};
37718
37964
  manifest.modules.gdskills ??= {};
@@ -37726,8 +37972,8 @@ async function updateManifest(projectRoot, entry) {
37726
37972
  `);
37727
37973
  }
37728
37974
  async function updateSkillsCatalog(projectRoot) {
37729
- const manifestPath = path117.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
37730
- const catalogPath = path117.join(projectRoot, PROJECT_SKILLS_CATALOG_PATH);
37975
+ const manifestPath = path118.join(projectRoot, PROJECT_SKILLS_MANIFEST_PATH);
37976
+ const catalogPath = path118.join(projectRoot, PROJECT_SKILLS_CATALOG_PATH);
37731
37977
  const manifest = await readJsonFileOr(manifestPath, {});
37732
37978
  const registry = manifest.modules?.gdskills?.projectSkillRegistry ?? [];
37733
37979
  const rows = registry.length > 0 ? registry.map(projectSkillCatalogRow).join(`
@@ -37739,7 +37985,7 @@ async function updateSkillsCatalog(projectRoot) {
37739
37985
  |---|---|---|---|
37740
37986
  ${rows}
37741
37987
  ${PROJECT_SKILLS_CATALOG_END}`;
37742
- const current = await pathExists(catalogPath) ? await readFile60(catalogPath, "utf8") : `# Metaproject Skills Catalog
37988
+ const current = await pathExists(catalogPath) ? await readFile61(catalogPath, "utf8") : `# Metaproject Skills Catalog
37743
37989
  `;
37744
37990
  const start = PROJECT_SKILLS_CATALOG_START;
37745
37991
  const end = PROJECT_SKILLS_CATALOG_END;
@@ -37767,7 +38013,7 @@ function inferModule(target) {
37767
38013
  }
37768
38014
  function inferSkillName(target) {
37769
38015
  const normalized = target.trim().replace(/[#:]+/g, "/");
37770
- const base = path117.basename(normalized).replace(/\.[^.]+$/, "");
38016
+ const base = path118.basename(normalized).replace(/\.[^.]+$/, "");
37771
38017
  return base || "entity";
37772
38018
  }
37773
38019
  function projectSkillSlug(value) {
@@ -37814,7 +38060,7 @@ function createRealSkillOwnerWriter(cwd, opts) {
37814
38060
  },
37815
38061
  async recover(intent) {
37816
38062
  try {
37817
- const raw = await readFile61(ownerReceiptPath(cwd, "skill", intent.workspaceId, intent.idempotencyKey), "utf8");
38063
+ const raw = await readFile62(ownerReceiptPath(cwd, "skill", intent.workspaceId, intent.idempotencyKey), "utf8");
37818
38064
  return JSON.parse(raw);
37819
38065
  } catch {
37820
38066
  return;
@@ -37872,7 +38118,7 @@ class ProposalLifecycleService {
37872
38118
  now;
37873
38119
  constructor(options) {
37874
38120
  this.options = options;
37875
- this.root = path118.resolve(options.workspaceRoot);
38121
+ this.root = path119.resolve(options.workspaceRoot);
37876
38122
  this.now = options.now ?? (() => new Date);
37877
38123
  }
37878
38124
  async create(input) {
@@ -37891,13 +38137,13 @@ class ProposalLifecycleService {
37891
38137
  if (manifest.status === "archived")
37892
38138
  throw new ProposalLifecycleError("guard_denied", "workspace is archived");
37893
38139
  const file = this.proposalPath(workspaceId, proposal.id);
37894
- await mkdir34(path118.dirname(file), { recursive: true, mode: 448 });
38140
+ await mkdir34(path119.dirname(file), { recursive: true, mode: 448 });
37895
38141
  return withFileLock(`${file}.lock`, async () => {
37896
38142
  const consume = this.options.wrapUpAuthority.consume(input.wrapUp, { actor, workspaceId });
37897
38143
  if (consume !== "ok")
37898
38144
  throw new ProposalLifecycleError("trusted_wrap_up_required", `trusted wrap-up ${consume}`);
37899
38145
  try {
37900
- await readFile62(file, "utf8");
38146
+ await readFile63(file, "utf8");
37901
38147
  throw new ProposalLifecycleError("conflict", "proposal already exists");
37902
38148
  } catch (error) {
37903
38149
  if (error instanceof ProposalLifecycleError)
@@ -37919,7 +38165,7 @@ class ProposalLifecycleService {
37919
38165
  return this.options.workspaces.withAuthorizedActor({ actorContext: actor, workspaceId: input.workspaceId, action: "review", execute: async (manifest) => {
37920
38166
  const proposal = await this.loadProposal(input.workspaceId, input.proposalId);
37921
38167
  const ledger = this.ledgerPath(input.workspaceId);
37922
- await mkdir34(path118.dirname(ledger), { recursive: true, mode: 448 });
38168
+ await mkdir34(path119.dirname(ledger), { recursive: true, mode: 448 });
37923
38169
  return withFileLock(`${ledger}.lock`, async () => {
37924
38170
  const records = (await this.records(ledger)).filter((record) => record.proposalId === proposal.id);
37925
38171
  const events = records.filter((record) => record.recordType === "proposal-transition");
@@ -37961,10 +38207,10 @@ class ProposalLifecycleService {
37961
38207
  } });
37962
38208
  }
37963
38209
  async listProposedProposals(workspaceId) {
37964
- const proposalsDir = path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
38210
+ const proposalsDir = path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals");
37965
38211
  let entries;
37966
38212
  try {
37967
- entries = (await readdir19(proposalsDir)).filter((name) => name.endsWith(".json"));
38213
+ entries = (await readdir20(proposalsDir)).filter((name) => name.endsWith(".json"));
37968
38214
  } catch (error) {
37969
38215
  if (isNotFound(error))
37970
38216
  return [];
@@ -37973,7 +38219,7 @@ class ProposalLifecycleService {
37973
38219
  const proposals = [];
37974
38220
  for (const entry of entries) {
37975
38221
  try {
37976
- const parsed = JSON.parse(await readFile62(path118.join(proposalsDir, entry), "utf8"));
38222
+ const parsed = JSON.parse(await readFile63(path119.join(proposalsDir, entry), "utf8"));
37977
38223
  if (parsed.recordType === "proposal-created")
37978
38224
  proposals.push(parsed);
37979
38225
  } catch {}
@@ -38058,7 +38304,7 @@ class ProposalLifecycleService {
38058
38304
  }
38059
38305
  async loadOwnerWriteAttempt(workspaceId, proposalId, key) {
38060
38306
  try {
38061
- return JSON.parse(await readFile62(this.attemptPath(workspaceId, proposalId, key), "utf8"));
38307
+ return JSON.parse(await readFile63(this.attemptPath(workspaceId, proposalId, key), "utf8"));
38062
38308
  } catch (error) {
38063
38309
  if (isNotFound(error))
38064
38310
  return;
@@ -38073,7 +38319,7 @@ class ProposalLifecycleService {
38073
38319
  async ensureReviewDecision(proposal, actor, reviewerAuthority, input, outcome, targetWrite, policyRevision) {
38074
38320
  const file = this.decisionPath(proposal.workspaceId, proposal.id, input.idempotencyKey);
38075
38321
  try {
38076
- const existing = JSON.parse(await readFile62(file, "utf8"));
38322
+ const existing = JSON.parse(await readFile63(file, "utf8"));
38077
38323
  const existingWrite = existing.targetWrite;
38078
38324
  if (existing.proposalId !== proposal.id || existing.proposalRevision !== proposal.proposalRevision || existing.workspaceId !== proposal.workspaceId || existing.correlationId !== input.requestCorrelationId || existing.idempotencyKey !== input.idempotencyKey || existing.decision !== outcome) {
38079
38325
  throw new ProposalLifecycleError("conflict", "review decision does not match the recovery request");
@@ -38106,7 +38352,7 @@ class ProposalLifecycleService {
38106
38352
  const approvalRef = this.approvalRef(proposal.id, input.idempotencyKey);
38107
38353
  const approvalPath = this.approvalPath(proposal.workspaceId, proposal.id, input.idempotencyKey);
38108
38354
  try {
38109
- const existing = JSON.parse(await readFile62(approvalPath, "utf8"));
38355
+ const existing = JSON.parse(await readFile63(approvalPath, "utf8"));
38110
38356
  if (existing.proposalId !== proposal.id || existing.proposalRevision !== proposal.proposalRevision || existing.workspaceId !== proposal.workspaceId || existing.correlationId !== input.requestCorrelationId || existing.idempotencyKey !== input.idempotencyKey || existing.policyRevision !== policyRevision || JSON.stringify(existing.reviewer) !== JSON.stringify({ subject: actor.subject, authority: reviewerAuthority }))
38111
38357
  throw new ProposalLifecycleError("conflict", "approval does not match the recovery request");
38112
38358
  return { approvalRef };
@@ -38126,7 +38372,7 @@ class ProposalLifecycleService {
38126
38372
  if (existing)
38127
38373
  return { intentRef };
38128
38374
  try {
38129
- const recovered = JSON.parse(await readFile62(this.intentPath(proposal.workspaceId, proposal.id, input.idempotencyKey), "utf8"));
38375
+ const recovered = JSON.parse(await readFile63(this.intentPath(proposal.workspaceId, proposal.id, input.idempotencyKey), "utf8"));
38130
38376
  await this.validateRecord(recovered);
38131
38377
  if (recovered.proposalId !== proposal.id || recovered.proposalRevision !== proposal.proposalRevision || recovered.correlationId !== input.requestCorrelationId || recovered.idempotencyKey !== input.idempotencyKey || recovered.workspaceId !== proposal.workspaceId)
38132
38378
  throw new ProposalLifecycleError("conflict", "write intent does not match the recovery request");
@@ -38219,7 +38465,7 @@ class ProposalLifecycleService {
38219
38465
  }
38220
38466
  async loadProposal(workspaceId, proposalId) {
38221
38467
  try {
38222
- const item = JSON.parse(await readFile62(this.proposalPath(workspaceId, proposalId), "utf8"));
38468
+ const item = JSON.parse(await readFile63(this.proposalPath(workspaceId, proposalId), "utf8"));
38223
38469
  await this.validateProposal(item);
38224
38470
  return item;
38225
38471
  } catch (error) {
@@ -38230,7 +38476,7 @@ class ProposalLifecycleService {
38230
38476
  }
38231
38477
  async records(ledger) {
38232
38478
  try {
38233
- return (await readFile62(ledger, "utf8")).trim().split(`
38479
+ return (await readFile63(ledger, "utf8")).trim().split(`
38234
38480
  `).filter(Boolean).map((line) => JSON.parse(line));
38235
38481
  } catch (error) {
38236
38482
  if (isNotFound(error))
@@ -38239,35 +38485,35 @@ class ProposalLifecycleService {
38239
38485
  }
38240
38486
  }
38241
38487
  proposalPath(workspaceId, proposalId) {
38242
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
38488
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.json`);
38243
38489
  }
38244
38490
  decisionRef(proposalId, key) {
38245
38491
  return `./proposals/${proposalId}.${hash(key)}.decision.json`;
38246
38492
  }
38247
38493
  decisionPath(workspaceId, proposalId, key) {
38248
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
38494
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.decision.json`);
38249
38495
  }
38250
38496
  approvalRef(proposalId, key) {
38251
38497
  return `./proposals/${proposalId}.${hash(key)}.approval.json`;
38252
38498
  }
38253
38499
  approvalPath(workspaceId, proposalId, key) {
38254
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
38500
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.approval.json`);
38255
38501
  }
38256
38502
  writeResultPath(workspaceId, proposalId, key) {
38257
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
38503
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-result.json`);
38258
38504
  }
38259
38505
  intentRef(proposalId, key) {
38260
38506
  return `./proposals/${proposalId}.${hash(key)}.write-intent.json`;
38261
38507
  }
38262
38508
  intentPath(workspaceId, proposalId, key) {
38263
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
38509
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.write-intent.json`);
38264
38510
  }
38265
38511
  attemptPath(workspaceId, proposalId, key) {
38266
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
38512
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "proposals", `${proposalId}.${hash(key)}.owner-write-attempt.json`);
38267
38513
  }
38268
38514
  async loadWriteResult(workspaceId, proposalId, key) {
38269
38515
  try {
38270
- return JSON.parse(await readFile62(this.writeResultPath(workspaceId, proposalId, key), "utf8"));
38516
+ return JSON.parse(await readFile63(this.writeResultPath(workspaceId, proposalId, key), "utf8"));
38271
38517
  } catch (error) {
38272
38518
  if (isNotFound(error))
38273
38519
  return;
@@ -38276,7 +38522,7 @@ class ProposalLifecycleService {
38276
38522
  }
38277
38523
  async writeImmutable(file, record) {
38278
38524
  try {
38279
- const existing = await readFile62(file, "utf8");
38525
+ const existing = await readFile63(file, "utf8");
38280
38526
  if (existing !== `${JSON.stringify(record)}
38281
38527
  `)
38282
38528
  throw new ProposalLifecycleError("conflict", "immutable lifecycle record already exists");
@@ -38290,7 +38536,7 @@ class ProposalLifecycleService {
38290
38536
  }
38291
38537
  }
38292
38538
  ledgerPath(workspaceId) {
38293
- return path118.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
38539
+ return path119.join(this.root, ".metaproject", "workspaces", workspaceId, "activity.jsonl");
38294
38540
  }
38295
38541
  timestamp() {
38296
38542
  return this.now().toISOString();
@@ -38371,9 +38617,9 @@ function normalizeProposalLifecycleResult(value) {
38371
38617
  return JSON.parse(JSON.stringify(value));
38372
38618
  }
38373
38619
  // src/sac/collaboration-service.ts
38374
- import { appendFile as appendFile8, mkdir as mkdir35, readFile as readFile63 } from "fs/promises";
38620
+ import { appendFile as appendFile8, mkdir as mkdir35, readFile as readFile64 } from "fs/promises";
38375
38621
  import { randomUUID as randomUUID8 } from "crypto";
38376
- import path119 from "path";
38622
+ import path120 from "path";
38377
38623
  class CollaborationServiceError extends Error {
38378
38624
  code;
38379
38625
  constructor(code, message) {
@@ -38388,7 +38634,7 @@ class CollaborationService {
38388
38634
  this.input = input;
38389
38635
  }
38390
38636
  file(id) {
38391
- return path119.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
38637
+ return path120.join(this.input.workspaceRoot, ".metaproject", "workspaces", id, "activity.jsonl");
38392
38638
  }
38393
38639
  async overview(input) {
38394
38640
  const manifest = await this.input.workspaces.show(input);
@@ -38397,7 +38643,7 @@ class CollaborationService {
38397
38643
  async activity(input) {
38398
38644
  await this.input.workspaces.show(input);
38399
38645
  try {
38400
- return (await readFile63(this.file(input.workspaceId), "utf8")).trim().split(`
38646
+ return (await readFile64(this.file(input.workspaceId), "utf8")).trim().split(`
38401
38647
  `).filter(Boolean).map((line) => this.validate(JSON.parse(line)));
38402
38648
  } catch (error) {
38403
38649
  if (typeof error === "object" && error && "code" in error && error.code === "ENOENT")
@@ -38425,7 +38671,7 @@ class CollaborationService {
38425
38671
  occurredAt: (this.input.now ?? (() => new Date))().toISOString(),
38426
38672
  ...suppliedHandoff ? { handoff: { ...suppliedHandoff, from: actor.subject } } : {}
38427
38673
  });
38428
- await mkdir35(path119.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
38674
+ await mkdir35(path120.dirname(this.file(manifest.id)), { recursive: true, mode: 448 });
38429
38675
  await appendFile8(this.file(manifest.id), `${JSON.stringify(activity)}
38430
38676
  `, { mode: 384 });
38431
38677
  return normalizeCollaborationResult(activity);
@@ -38474,14 +38720,14 @@ function normalizeCollaborationResult(value) {
38474
38720
  }
38475
38721
  // src/session/external-slate.ts
38476
38722
  init_fs();
38477
- import { mkdir as mkdir37, readdir as readdir20, readFile as readFile64 } from "fs/promises";
38478
- import path121 from "path";
38723
+ import { mkdir as mkdir37, readdir as readdir21, readFile as readFile65 } from "fs/promises";
38724
+ import path122 from "path";
38479
38725
 
38480
38726
  // src/sac/machine-wrap-up.ts
38481
38727
  init_fs();
38482
38728
  import { createHash as createHash30, randomUUID as randomUUID10 } from "crypto";
38483
38729
  import { mkdir as mkdir36 } from "fs/promises";
38484
- import path120 from "path";
38730
+ import path121 from "path";
38485
38731
 
38486
38732
  // src/sac/workspace-resolve.ts
38487
38733
  init_redact();
@@ -38622,11 +38868,11 @@ async function resolveMachineWrapUp(input) {
38622
38868
  `;
38623
38869
  const seedsJson = `${JSON.stringify(seedsForKind.map((seed) => ({ text: seed.text, source: describeSource(seed.source) })), null, 2)}
38624
38870
  `;
38625
- const evidenceRelBase = path120.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
38871
+ const evidenceRelBase = path121.posix.join(".metaproject", "workspaces", input.workspaceId, "machine-evidence");
38626
38872
  const floor = await applyEvidenceRedactionFloor(input.cwd, [
38627
- { name: `${input.kind}.diff.txt`, content: diffBody, path: path120.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
38628
- { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path120.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
38629
- { name: `${input.kind}.seeds.json`, content: seedsJson, path: path120.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
38873
+ { name: `${input.kind}.diff.txt`, content: diffBody, path: path121.posix.join(evidenceRelBase, `${input.kind}.diff.txt`), source: "tool-output" },
38874
+ { name: `${input.kind}.flow.json`, content: flowSnapshotJson, path: path121.posix.join(evidenceRelBase, `${input.kind}.flow.json`), source: "generated" },
38875
+ { name: `${input.kind}.seeds.json`, content: seedsJson, path: path121.posix.join(evidenceRelBase, `${input.kind}.seeds.json`), source: "generated" }
38630
38876
  ]);
38631
38877
  if (!floor.ok)
38632
38878
  return { ok: false, code: "security_denied", detail: floor.reason };
@@ -38680,14 +38926,14 @@ ${safeSeeds.content}`;
38680
38926
  }
38681
38927
  summary = result.text.trim().length > 0 ? result.text.trim() : mechanicalSummary(summaryDiff, course);
38682
38928
  }
38683
- const evidenceDir = path120.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
38929
+ const evidenceDir = path121.join(input.cwd, ".metaproject", "workspaces", input.workspaceId, "machine-evidence");
38684
38930
  await mkdir36(evidenceDir, { recursive: true });
38685
38931
  const diffFile = `${input.kind}.${shortHash}.diff.txt`;
38686
38932
  const flowFile = `${input.kind}.${shortHash}.flow.json`;
38687
38933
  const seedsFile = `${input.kind}.${shortHash}.seeds.json`;
38688
- await writeFileAtomic(path120.join(evidenceDir, diffFile), safeDiff.content);
38689
- await writeFileAtomic(path120.join(evidenceDir, flowFile), safeFlow.content);
38690
- await writeFileAtomic(path120.join(evidenceDir, seedsFile), safeSeeds.content);
38934
+ await writeFileAtomic(path121.join(evidenceDir, diffFile), safeDiff.content);
38935
+ await writeFileAtomic(path121.join(evidenceDir, flowFile), safeFlow.content);
38936
+ await writeFileAtomic(path121.join(evidenceDir, seedsFile), safeSeeds.content);
38691
38937
  const observedAt = now().toISOString();
38692
38938
  const relBase = `./.metaproject/workspaces/${input.workspaceId}/machine-evidence`;
38693
38939
  const evidence = [
@@ -38697,7 +38943,7 @@ ${safeSeeds.content}`;
38697
38943
  ];
38698
38944
  if (floor.notice !== undefined) {
38699
38945
  const noticeFile = `${input.kind}.${shortHash}.redaction.md`;
38700
- await writeFileAtomic(path120.join(evidenceDir, noticeFile), floor.notice);
38946
+ await writeFileAtomic(path121.join(evidenceDir, noticeFile), floor.notice);
38701
38947
  evidence.push({ kind: REDACTION_NOTICE_KIND, uri: `${relBase}/${noticeFile}`, revision: sha2566(floor.notice), observedAt });
38702
38948
  }
38703
38949
  return {
@@ -38716,18 +38962,18 @@ async function writeFlooredArchiveArtifact(params) {
38716
38962
  {
38717
38963
  name: params.filename,
38718
38964
  content: params.content,
38719
- path: path120.posix.join("slate-archive", params.filename),
38965
+ path: path121.posix.join("slate-archive", params.filename),
38720
38966
  source: "generated"
38721
38967
  }
38722
38968
  ]);
38723
38969
  if (!floor.ok)
38724
38970
  return { ok: false, code: "security_denied", detail: floor.reason };
38725
38971
  const body = floor.bodies[0];
38726
- const archiveDir = path120.join(params.dir, "slate-archive");
38972
+ const archiveDir = path121.join(params.dir, "slate-archive");
38727
38973
  await mkdir36(archiveDir, { recursive: true });
38728
- await writeFileAtomic(path120.join(archiveDir, params.filename), body.content);
38974
+ await writeFileAtomic(path121.join(archiveDir, params.filename), body.content);
38729
38975
  if (floor.notice !== undefined) {
38730
- await writeFileAtomic(path120.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
38976
+ await writeFileAtomic(path121.join(archiveDir, `${params.filename}${ARCHIVE_REDACTION_NOTICE_SUFFIX}`), floor.notice);
38731
38977
  }
38732
38978
  return { ok: true, altered: body.altered };
38733
38979
  }
@@ -38763,9 +39009,9 @@ async function writeWrapUpOutcomeArtifact(cwd, dir, trigger, now, groups) {
38763
39009
  return;
38764
39010
  const refusalIso = now().toISOString();
38765
39011
  const refusalFilename = `${refusalIso.replace(/[:.]/g, "-")}-wrap-up-outcome.json`;
38766
- const archiveDir = path120.join(dir, "slate-archive");
39012
+ const archiveDir = path121.join(dir, "slate-archive");
38767
39013
  await mkdir36(archiveDir, { recursive: true });
38768
- await writeFileAtomic(path120.join(archiveDir, refusalFilename), `${JSON.stringify({
39014
+ await writeFileAtomic(path121.join(archiveDir, refusalFilename), `${JSON.stringify({
38769
39015
  recordType: "wrap-up-outcome",
38770
39016
  trigger,
38771
39017
  generatedAt: refusalIso,
@@ -38901,7 +39147,7 @@ async function runWrapUp(input) {
38901
39147
 
38902
39148
  // src/session/external-slate.ts
38903
39149
  function externalSlatesDir(cwd) {
38904
- return path121.join(cwd, ".keryx", "external-slates");
39150
+ return path122.join(cwd, ".keryx", "external-slates");
38905
39151
  }
38906
39152
  var EXTERNAL_SESSION_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
38907
39153
  function assertValidExternalSessionId(externalSessionId) {
@@ -38911,18 +39157,18 @@ function assertValidExternalSessionId(externalSessionId) {
38911
39157
  }
38912
39158
  function externalSlatePath(cwd, externalSessionId) {
38913
39159
  assertValidExternalSessionId(externalSessionId);
38914
- return path121.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
39160
+ return path122.join(externalSlatesDir(cwd), `${externalSessionId}.json`);
38915
39161
  }
38916
39162
  function externalSlateLockPath(cwd, externalSessionId) {
38917
39163
  return `${externalSlatePath(cwd, externalSessionId)}.lock`;
38918
39164
  }
38919
39165
  function externalSlateEvidenceDir(cwd, externalSessionId) {
38920
39166
  assertValidExternalSessionId(externalSessionId);
38921
- return path121.join(externalSlatesDir(cwd), externalSessionId);
39167
+ return path122.join(externalSlatesDir(cwd), externalSessionId);
38922
39168
  }
38923
39169
  async function readExternalSlate(cwd, externalSessionId) {
38924
39170
  try {
38925
- const raw = await readFile64(externalSlatePath(cwd, externalSessionId), "utf8");
39171
+ const raw = await readFile65(externalSlatePath(cwd, externalSessionId), "utf8");
38926
39172
  return JSON.parse(raw);
38927
39173
  } catch (error) {
38928
39174
  if (isNotFound(error))
@@ -38942,7 +39188,7 @@ async function writeExternalSlate(cwd, externalSessionId, update) {
38942
39188
  }
38943
39189
  async function listExternalSlateIds(cwd) {
38944
39190
  try {
38945
- const entries = await readdir20(externalSlatesDir(cwd));
39191
+ const entries = await readdir21(externalSlatesDir(cwd));
38946
39192
  return entries.filter((name) => name.endsWith(".json")).map((name) => name.slice(0, -".json".length));
38947
39193
  } catch (error) {
38948
39194
  if (isNotFound(error))
@@ -39024,13 +39270,13 @@ __export(exports_service10, {
39024
39270
  runDoctor: () => runDoctor,
39025
39271
  runValidate: () => runValidate
39026
39272
  });
39027
- import path124 from "path";
39028
- import { readFile as readFile67 } from "fs/promises";
39273
+ import path125 from "path";
39274
+ import { readFile as readFile68 } from "fs/promises";
39029
39275
 
39030
39276
  // src/standard/validate.ts
39031
39277
  init_fs();
39032
- import path123 from "path";
39033
- import { readFile as readFile66 } from "fs/promises";
39278
+ import path124 from "path";
39279
+ import { readFile as readFile67 } from "fs/promises";
39034
39280
 
39035
39281
  // src/standard/schemas.ts
39036
39282
  var MODULE_SCHEMA = {
@@ -39159,8 +39405,8 @@ var SCHEMA_REGISTRY2 = {
39159
39405
  // src/standard/profiles.ts
39160
39406
  init_fs();
39161
39407
  init_entrypoint_targets();
39162
- import path122 from "path";
39163
- import { readFile as readFile65 } from "fs/promises";
39408
+ import path123 from "path";
39409
+ import { readFile as readFile66 } from "fs/promises";
39164
39410
  var AGENT_MODULES = ["gdgraph", "gdctx", "gdskills", "gdwiki", "memory"];
39165
39411
  var CI_MODULES = ["health", "testing"];
39166
39412
  var INDEX_LINK = ".metaproject/index.md";
@@ -39184,11 +39430,11 @@ function enabledModuleKeys(manifest) {
39184
39430
  }
39185
39431
  async function rootEntrypointLinksIndex(cwd, manifest) {
39186
39432
  for (const { path: name } of namedEntrypoints(manifest)) {
39187
- const filePath = path122.join(cwd, name);
39433
+ const filePath = path123.join(cwd, name);
39188
39434
  if (!await pathExists(filePath)) {
39189
39435
  continue;
39190
39436
  }
39191
- const content = await readFile65(filePath, "utf8");
39437
+ const content = await readFile66(filePath, "utf8");
39192
39438
  if (content.includes(INDEX_LINK)) {
39193
39439
  return true;
39194
39440
  }
@@ -39196,16 +39442,16 @@ async function rootEntrypointLinksIndex(cwd, manifest) {
39196
39442
  return false;
39197
39443
  }
39198
39444
  async function minimalSatisfied(cwd) {
39199
- const metaprojectRoot = path122.join(cwd, ".metaproject");
39445
+ const metaprojectRoot = path123.join(cwd, ".metaproject");
39200
39446
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
39201
39447
  const requiredDirs = ["modules", "rules", "skills", "data"];
39202
39448
  for (const file of requiredFiles) {
39203
- if (!await pathExists(path122.join(metaprojectRoot, file))) {
39449
+ if (!await pathExists(path123.join(metaprojectRoot, file))) {
39204
39450
  return false;
39205
39451
  }
39206
39452
  }
39207
39453
  for (const dir of requiredDirs) {
39208
- if (!await pathExists(path122.join(metaprojectRoot, dir))) {
39454
+ if (!await pathExists(path123.join(metaprojectRoot, dir))) {
39209
39455
  return false;
39210
39456
  }
39211
39457
  }
@@ -39218,7 +39464,7 @@ async function ciSatisfied(cwd, manifest) {
39218
39464
  return false;
39219
39465
  }
39220
39466
  for (const key of ciModules) {
39221
- if (await pathExists(path122.join(cwd, ".metaproject", "data", key, "artifacts"))) {
39467
+ if (await pathExists(path123.join(cwd, ".metaproject", "data", key, "artifacts"))) {
39222
39468
  return true;
39223
39469
  }
39224
39470
  }
@@ -39231,7 +39477,7 @@ async function evaluateProfiles(cwd, manifest) {
39231
39477
  satisfied.push("minimal");
39232
39478
  }
39233
39479
  const hasAgentModule = AGENT_MODULES.some((key) => new Set(enabledModuleKeys(manifest)).has(key));
39234
- const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path122.join(cwd, ".metaproject", "rules"));
39480
+ const agent = minimal && hasAgentModule && await rootEntrypointLinksIndex(cwd, manifest) && await pathExists(path123.join(cwd, ".metaproject", "rules"));
39235
39481
  if (agent) {
39236
39482
  satisfied.push("agent");
39237
39483
  }
@@ -39400,26 +39646,26 @@ var MANIFEST_TOP_LEVEL_SCHEMA = {
39400
39646
  async function validateWorkspace2(cwd) {
39401
39647
  const errors = [];
39402
39648
  const warnings = [];
39403
- const metaprojectRoot = path123.join(cwd, ".metaproject");
39649
+ const metaprojectRoot = path124.join(cwd, ".metaproject");
39404
39650
  const requiredFiles = ["index.md", "README.md", "metaproject.json"];
39405
39651
  for (const file of requiredFiles) {
39406
- if (!await pathExists(path123.join(metaprojectRoot, file))) {
39652
+ if (!await pathExists(path124.join(metaprojectRoot, file))) {
39407
39653
  errors.push(issue("missing-required-file", `Required file .metaproject/${file} is missing`, `Run \`keryx init\` to scaffold .metaproject/${file}.`));
39408
39654
  }
39409
39655
  }
39410
39656
  const requiredDirs = ["modules", "rules", "skills", "data"];
39411
39657
  for (const dir of requiredDirs) {
39412
- if (!await pathExists(path123.join(metaprojectRoot, dir))) {
39658
+ if (!await pathExists(path124.join(metaprojectRoot, dir))) {
39413
39659
  errors.push(issue("missing-required-dir", `Required directory .metaproject/${dir}/ is missing`, `Run \`keryx init\` to create .metaproject/${dir}/.`));
39414
39660
  }
39415
39661
  }
39416
- const manifestPath = path123.join(metaprojectRoot, "metaproject.json");
39662
+ const manifestPath = path124.join(metaprojectRoot, "metaproject.json");
39417
39663
  if (!await pathExists(manifestPath)) {
39418
39664
  return { ok: errors.length === 0, errors, warnings };
39419
39665
  }
39420
39666
  let manifest;
39421
39667
  try {
39422
- manifest = JSON.parse(await readFile66(manifestPath, "utf8"));
39668
+ manifest = JSON.parse(await readFile67(manifestPath, "utf8"));
39423
39669
  } catch (error) {
39424
39670
  const detail = error instanceof Error ? error.message : String(error);
39425
39671
  errors.push(issue("invalid-manifest-json", `.metaproject/metaproject.json is not valid JSON: ${detail}`, "Fix the JSON syntax or regenerate it with `keryx init`."));
@@ -39445,7 +39691,7 @@ async function validateWorkspace2(cwd) {
39445
39691
  if (typeof value !== "string") {
39446
39692
  continue;
39447
39693
  }
39448
- if (!await pathExists(path123.join(cwd, value))) {
39694
+ if (!await pathExists(path124.join(cwd, value))) {
39449
39695
  errors.push(issue("missing-declared-path", `Declared path paths.${key} -> ${value} does not exist`, `Create ${value} or remove paths.${key} from metaproject.json.`));
39450
39696
  }
39451
39697
  }
@@ -39455,7 +39701,7 @@ async function validateWorkspace2(cwd) {
39455
39701
  continue;
39456
39702
  }
39457
39703
  if (typeof entry.manifest === "string") {
39458
- if (!await pathExists(path123.join(cwd, entry.manifest))) {
39704
+ if (!await pathExists(path124.join(cwd, entry.manifest))) {
39459
39705
  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.`));
39460
39706
  }
39461
39707
  }
@@ -39464,18 +39710,18 @@ async function validateWorkspace2(cwd) {
39464
39710
  if (typeof value !== "string") {
39465
39711
  continue;
39466
39712
  }
39467
- if (!await pathExists(path123.join(cwd, value))) {
39713
+ if (!await pathExists(path124.join(cwd, value))) {
39468
39714
  const sink = field === "data" ? warnings : errors;
39469
39715
  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.`));
39470
39716
  }
39471
39717
  }
39472
39718
  }
39473
39719
  for (const { path: name, scope } of namedEntrypoints(manifest)) {
39474
- const filePath = path123.join(cwd, name);
39720
+ const filePath = path124.join(cwd, name);
39475
39721
  if (!await pathExists(filePath)) {
39476
39722
  continue;
39477
39723
  }
39478
- const content = await readFile66(filePath, "utf8");
39724
+ const content = await readFile67(filePath, "utf8");
39479
39725
  if (!content.includes(INDEX_LINK2)) {
39480
39726
  errors.push(issue("entrypoint-missing-index-link", `Root entrypoint ${name} does not link ${INDEX_LINK2}`, scope === "local" ? `Run \`keryx update\` to put the managed block back into ${name}.` : `Add a reference to ${INDEX_LINK2} in ${name} (\`keryx rules sync\` does this).`));
39481
39727
  }
@@ -40381,12 +40627,12 @@ async function runDoctor(cwd) {
40381
40627
  return validateWorkspace2(cwd);
40382
40628
  }
40383
40629
  async function readManifest(cwd) {
40384
- const manifestPath = path124.join(cwd, ".metaproject", "metaproject.json");
40630
+ const manifestPath = path125.join(cwd, ".metaproject", "metaproject.json");
40385
40631
  if (!await pathExists(manifestPath)) {
40386
40632
  throw new Error("Metaproject is not initialized (missing .metaproject/metaproject.json). Run `keryx init` first.");
40387
40633
  }
40388
40634
  try {
40389
- return JSON.parse(await readFile67(manifestPath, "utf8"));
40635
+ return JSON.parse(await readFile68(manifestPath, "utf8"));
40390
40636
  } catch (error) {
40391
40637
  const detail = error instanceof Error ? error.message : String(error);
40392
40638
  throw new Error(`Invalid .metaproject/metaproject.json: ${detail}`);