kibi-runtime 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6737,19 +6737,56 @@ var init_engine_limits = __esm(() => {
6737
6737
  };
6738
6738
  });
6739
6739
 
6740
+ // ../cli/dist/package-versions.js
6741
+ import { readFileSync as readFileSync2 } from "node:fs";
6742
+ import { createRequire as createRequire2 } from "node:module";
6743
+ import path2 from "node:path";
6744
+ import { fileURLToPath } from "node:url";
6745
+ function manifestVersion(manifestPath, expectedName) {
6746
+ try {
6747
+ const manifest = JSON.parse(readFileSync2(manifestPath, "utf8"));
6748
+ return manifest.name === expectedName && typeof manifest.version === "string" ? manifest.version : undefined;
6749
+ } catch {
6750
+ return;
6751
+ }
6752
+ }
6753
+ function cliVersion() {
6754
+ if (true)
6755
+ return "2.14.0";
6756
+ return manifestVersion(path2.join(moduleDirectory, "..", "package.json"), "kibi-cli") ?? "unknown";
6757
+ }
6758
+ function coreVersion() {
6759
+ try {
6760
+ const resolved = manifestVersion(require2.resolve("kibi-core/package.json"), "kibi-core");
6761
+ if (resolved)
6762
+ return resolved;
6763
+ } catch {}
6764
+ return manifestVersion(path2.join(moduleDirectory, "..", "..", "core", "package.json"), "kibi-core") ?? "unknown";
6765
+ }
6766
+ function kibiPackageVersions() {
6767
+ const override = process.env.KIBI_PACKAGE_VERSIONS;
6768
+ return override !== undefined && override.length > 0 ? override : KIBI_BUILT_PACKAGE_VERSIONS;
6769
+ }
6770
+ var require2, moduleDirectory, KIBI_BUILT_PACKAGE_VERSIONS;
6771
+ var init_package_versions = __esm(() => {
6772
+ require2 = createRequire2(import.meta.url);
6773
+ moduleDirectory = path2.dirname(fileURLToPath(import.meta.url));
6774
+ KIBI_BUILT_PACKAGE_VERSIONS = `kibi-cli@${cliVersion()},kibi-core@${coreVersion()}`;
6775
+ });
6776
+
6740
6777
  // ../cli/dist/performance-trace.js
6741
6778
  import { constants } from "node:fs";
6742
6779
  import { closeSync, existsSync as existsSync2, lstatSync, openSync, realpathSync, statSync, writeSync } from "node:fs";
6743
- import path2 from "node:path";
6780
+ import path3 from "node:path";
6744
6781
  function isWithin(parent, candidate) {
6745
- const relative = path2.relative(parent, candidate);
6746
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path2.sep}`) && !path2.isAbsolute(relative);
6782
+ const relative = path3.relative(parent, candidate);
6783
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path3.sep}`) && !path3.isAbsolute(relative);
6747
6784
  }
6748
6785
  function privateTraceFile() {
6749
6786
  if (process.env[KIBI_PERF_TIMINGS_ENV] !== "1")
6750
6787
  return null;
6751
6788
  const configuredDirectory = process.env[KIBI_PERF_TRACE_DIR_ENV];
6752
- if (!configuredDirectory || !path2.isAbsolute(configuredDirectory))
6789
+ if (!configuredDirectory || !path3.isAbsolute(configuredDirectory))
6753
6790
  return null;
6754
6791
  try {
6755
6792
  const directoryInfo = lstatSync(configuredDirectory);
@@ -6757,7 +6794,7 @@ function privateTraceFile() {
6757
6794
  return null;
6758
6795
  }
6759
6796
  const directory = realpathSync(configuredDirectory);
6760
- if (path2.resolve(configuredDirectory) !== directory)
6797
+ if (path3.resolve(configuredDirectory) !== directory)
6761
6798
  return null;
6762
6799
  const directoryStats = statSync(directory);
6763
6800
  if (typeof process.getuid !== "function" || directoryStats.uid !== process.getuid()) {
@@ -6769,7 +6806,7 @@ function privateTraceFile() {
6769
6806
  const currentDirectory = realpathSync(process.cwd());
6770
6807
  if (isWithin(currentDirectory, directory))
6771
6808
  return null;
6772
- const file = path2.join(directory, `kibi-performance-${process.pid}.jsonl`);
6809
+ const file = path3.join(directory, `kibi-performance-${process.pid}.jsonl`);
6773
6810
  let state = states.get(file);
6774
6811
  if (!state) {
6775
6812
  if (existsSync2(file))
@@ -7138,8 +7175,8 @@ var init_error_terms = () => {};
7138
7175
 
7139
7176
  // ../cli/dist/prolog/swipl-resolver.js
7140
7177
  import { execFileSync, spawnSync } from "node:child_process";
7141
- import { constants as constants2, accessSync, existsSync as existsSync3, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
7142
- import path3 from "node:path";
7178
+ import { constants as constants2, accessSync, existsSync as existsSync3, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
7179
+ import path4 from "node:path";
7143
7180
  import { BUNDLED_BINARY_PATH, MANIFEST_FILE, PLATFORM_PACKAGES, locatePlatformPackage, platformKey, sha256File, validateBuildManifest } from "kibi-swipl";
7144
7181
  function detectGlibc() {
7145
7182
  if (process.platform !== "linux")
@@ -7212,8 +7249,8 @@ function inspectBundle(deps) {
7212
7249
  const packageDir = deps.locatePackage(packageName);
7213
7250
  if (packageDir === undefined)
7214
7251
  return { kind: "missing", key, packageName };
7215
- const manifestPath = path3.join(packageDir, MANIFEST_FILE);
7216
- const binary = path3.join(packageDir, BUNDLED_BINARY_PATH);
7252
+ const manifestPath = path4.join(packageDir, MANIFEST_FILE);
7253
+ const binary = path4.join(packageDir, BUNDLED_BINARY_PATH);
7217
7254
  if (!existsSync3(manifestPath)) {
7218
7255
  if (!existsSync3(binary))
7219
7256
  return { kind: "empty", key, packageName };
@@ -7233,12 +7270,12 @@ function inspectBundle(deps) {
7233
7270
  let manifest;
7234
7271
  let packageJson;
7235
7272
  try {
7236
- manifest = JSON.parse(readFileSync2(manifestPath, "utf8"));
7273
+ manifest = JSON.parse(readFileSync3(manifestPath, "utf8"));
7237
7274
  } catch (error) {
7238
7275
  return corrupt(`${MANIFEST_FILE} is not valid JSON (${error instanceof Error ? error.message : String(error)})`);
7239
7276
  }
7240
7277
  try {
7241
- packageJson = JSON.parse(readFileSync2(path3.join(packageDir, "package.json"), "utf8"));
7278
+ packageJson = JSON.parse(readFileSync3(path4.join(packageDir, "package.json"), "utf8"));
7242
7279
  } catch (error) {
7243
7280
  return corrupt(`package.json is unreadable (${error instanceof Error ? error.message : String(error)})`);
7244
7281
  }
@@ -7261,7 +7298,7 @@ function inspectBundle(deps) {
7261
7298
  if (actual !== checked.binarySha256) {
7262
7299
  return corrupt(`${BUNDLED_BINARY_PATH} SHA-256 ${actual} does not match the manifest (${checked.binarySha256})`);
7263
7300
  }
7264
- const home = path3.join(packageDir, checked.home);
7301
+ const home = path4.join(packageDir, checked.home);
7265
7302
  let homeIsDirectory = false;
7266
7303
  try {
7267
7304
  homeIsDirectory = statSync2(home).isDirectory();
@@ -7303,10 +7340,10 @@ function probeVersion(bin, deps) {
7303
7340
  return { kind: "ok", version: parsed.version };
7304
7341
  }
7305
7342
  function findOnPath(env, deps) {
7306
- for (const directory of (env.PATH ?? "").split(path3.delimiter)) {
7307
- if (directory === "" || !path3.isAbsolute(directory))
7343
+ for (const directory of (env.PATH ?? "").split(path4.delimiter)) {
7344
+ if (directory === "" || !path4.isAbsolute(directory))
7308
7345
  continue;
7309
- const candidate = path3.join(directory, "swipl");
7346
+ const candidate = path4.join(directory, "swipl");
7310
7347
  if (!isExecutableFile(candidate))
7311
7348
  continue;
7312
7349
  const probe = probeVersion(candidate, deps);
@@ -7329,7 +7366,7 @@ function resolveFromEnv(override, deps) {
7329
7366
  });
7330
7367
  const packageName = key === undefined ? undefined : PLATFORM_PACKAGES[key].package;
7331
7368
  const invalid = (detail) => new SwiplResolutionError("swipl_env_invalid", `KIBI_SWIPL=${override} ${detail}. Set KIBI_SWIPL to the absolute path of a SWI-Prolog ${MINIMUM_SWIPL_MAJOR}.0+ executable, to "system" to use swipl from PATH, or unset it to use the bundled runtime.`, platform, packageName);
7332
- if (!path3.isAbsolute(override))
7369
+ if (!path4.isAbsolute(override))
7333
7370
  return fail(invalid("is not an absolute path"));
7334
7371
  if (!isExecutableFile(override)) {
7335
7372
  return fail(invalid("is not an executable file"));
@@ -7454,18 +7491,10 @@ var init_swipl_resolver = __esm(() => {
7454
7491
  // ../cli/dist/prolog.js
7455
7492
  import { spawn } from "node:child_process";
7456
7493
  import { existsSync as existsSync4 } from "node:fs";
7457
- import { createRequire as createRequire2 } from "node:module";
7458
- import path4 from "node:path";
7494
+ import { createRequire as createRequire3 } from "node:module";
7495
+ import path5 from "node:path";
7459
7496
  import { performance } from "node:perf_hooks";
7460
- import { fileURLToPath } from "node:url";
7461
- function packageVersion(packagePath) {
7462
- try {
7463
- const packageJson = require2(packagePath);
7464
- return typeof packageJson.version === "string" ? packageJson.version : "unknown";
7465
- } catch {
7466
- return "unknown";
7467
- }
7468
- }
7497
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
7469
7498
  function resolveKbPlPath() {
7470
7499
  const overrideKbPath = getKbPlPathOverride();
7471
7500
  if (overrideKbPath) {
@@ -7473,20 +7502,20 @@ function resolveKbPlPath() {
7473
7502
  }
7474
7503
  try {
7475
7504
  try {
7476
- return require2.resolve("kibi-core/src/kb.pl");
7505
+ return require3.resolve("kibi-core/src/kb.pl");
7477
7506
  } catch {
7478
- const coreMain = require2.resolve("kibi-core");
7479
- const coreDir = path4.dirname(coreMain);
7480
- return path4.join(coreDir, "src", "kb.pl");
7507
+ const coreMain = require3.resolve("kibi-core");
7508
+ const coreDir = path5.dirname(coreMain);
7509
+ return path5.join(coreDir, "src", "kb.pl");
7481
7510
  }
7482
7511
  } catch {}
7483
7512
  let currentDir = importMetaDir;
7484
- while (currentDir !== path4.dirname(currentDir)) {
7485
- const candidate = path4.join(currentDir, "packages", "core", "src", "kb.pl");
7513
+ while (currentDir !== path5.dirname(currentDir)) {
7514
+ const candidate = path5.join(currentDir, "packages", "core", "src", "kb.pl");
7486
7515
  if (existsSync4(candidate)) {
7487
7516
  return candidate;
7488
7517
  }
7489
- currentDir = path4.dirname(currentDir);
7518
+ currentDir = path5.dirname(currentDir);
7490
7519
  }
7491
7520
  throw new Error("Unable to resolve kb.pl. Expected kibi-core to be installed (node_modules) " + "or to be running inside the monorepo checkout.");
7492
7521
  }
@@ -7568,7 +7597,7 @@ class PrologProcess {
7568
7597
  ...launch.env,
7569
7598
  KIBI_RUNTIME_NAME: process.versions.bun !== undefined ? "bun" : "node",
7570
7599
  KIBI_RUNTIME_VERSION: process.versions.bun ?? process.versions.node ?? "unknown",
7571
- KIBI_PACKAGE_VERSIONS: process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS
7600
+ KIBI_PACKAGE_VERSIONS: kibiPackageVersions()
7572
7601
  }
7573
7602
  });
7574
7603
  this.clearQueryBuffers();
@@ -7689,7 +7718,7 @@ writeln('${INTERACTIVE_QUERY_FRAME_END}').
7689
7718
  console.error(`[prolog debug] timeout: ${msg}`);
7690
7719
  const runtime = this.errorBuffer.split(`
7691
7720
  `).find((line) => line.includes("__KIBI_RUNTIME__"));
7692
- console.error(`[prolog debug] runtime=${runtime ?? "unknown"} packages=${process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS}`);
7721
+ console.error(`[prolog debug] runtime=${runtime ?? "unknown"} packages=${kibiPackageVersions()}`);
7693
7722
  }
7694
7723
  settle();
7695
7724
  this.terminationReason = `query timeout: ${goalLabel}`;
@@ -7888,7 +7917,7 @@ writeln('${INTERACTIVE_QUERY_FRAME_END}').
7888
7917
  ].join(", ");
7889
7918
  const runtimeName = process.versions.bun !== undefined ? "bun" : "node";
7890
7919
  const runtimeVersion = process.versions.bun ?? process.versions.node ?? "unknown";
7891
- const packageVersions = process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS;
7920
+ const packageVersions = kibiPackageVersions();
7892
7921
  let child;
7893
7922
  try {
7894
7923
  const launch = this.launchTarget();
@@ -8264,19 +8293,15 @@ writeln('${INTERACTIVE_QUERY_FRAME_END}').
8264
8293
  }
8265
8294
  }
8266
8295
  }
8267
- var importMetaDir, DEFAULT_PROLOG_OUTPUT_MAX_BUFFER_BYTES, PROLOG_OUTPUT_OVERFLOW_ERROR = "Query exceeded bounded Prolog output capacity (ENOBUFS); narrow the operation or reduce stored entity size", INTERACTIVE_QUERY_FRAME_END = "__KIBI_QUERY_FRAME_END__", require2, KIBI_PACKAGE_VERSIONS, PrologProcessTerminatedError;
8296
+ var importMetaDir, DEFAULT_PROLOG_OUTPUT_MAX_BUFFER_BYTES, PROLOG_OUTPUT_OVERFLOW_ERROR = "Query exceeded bounded Prolog output capacity (ENOBUFS); narrow the operation or reduce stored entity size", INTERACTIVE_QUERY_FRAME_END = "__KIBI_QUERY_FRAME_END__", require3, PrologProcessTerminatedError;
8268
8297
  var init_prolog = __esm(() => {
8298
+ init_package_versions();
8269
8299
  init_performance_trace();
8270
8300
  init_error_terms();
8271
8301
  init_swipl_resolver();
8272
- importMetaDir = path4.dirname(fileURLToPath(import.meta.url));
8302
+ importMetaDir = path5.dirname(fileURLToPath2(import.meta.url));
8273
8303
  DEFAULT_PROLOG_OUTPUT_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
8274
- require2 = createRequire2(import.meta.url);
8275
- KIBI_PACKAGE_VERSIONS = [
8276
- `kibi-cli@${packageVersion(path4.join(importMetaDir, "..", "package.json"))}`,
8277
- `kibi-core@${packageVersion(path4.join(importMetaDir, "..", "..", "core", "package.json"))}`,
8278
- `kibi-mcp@${packageVersion(path4.join(importMetaDir, "..", "..", "mcp", "package.json"))}`
8279
- ].join(",");
8304
+ require3 = createRequire3(import.meta.url);
8280
8305
  PrologProcessTerminatedError = class PrologProcessTerminatedError extends Error {
8281
8306
  code = "prolog_process_terminated";
8282
8307
  reason;
@@ -8290,7 +8315,7 @@ var init_prolog = __esm(() => {
8290
8315
 
8291
8316
  // ../cli/dist/prolog/store-lock.js
8292
8317
  import { existsSync as existsSync5, rmSync } from "node:fs";
8293
- import { readFileSync as readFileSync3 } from "node:fs";
8318
+ import { readFileSync as readFileSync4 } from "node:fs";
8294
8319
  import { dirname as dirname2, join as join2 } from "node:path";
8295
8320
  function currentBootId() {
8296
8321
  if (cachedBootId !== undefined)
@@ -8300,7 +8325,7 @@ function currentBootId() {
8300
8325
  return cachedBootId;
8301
8326
  }
8302
8327
  try {
8303
- const raw = readFileSync3("/proc/sys/kernel/random/boot_id", "utf8");
8328
+ const raw = readFileSync4("/proc/sys/kernel/random/boot_id", "utf8");
8304
8329
  cachedBootId = raw.trim();
8305
8330
  } catch {
8306
8331
  cachedBootId = null;
@@ -8342,7 +8367,7 @@ function readStoreLockOwner(storePath) {
8342
8367
  continue;
8343
8368
  let parsed;
8344
8369
  try {
8345
- parsed = JSON.parse(readFileSync3(journalPath, "utf8"));
8370
+ parsed = JSON.parse(readFileSync4(journalPath, "utf8"));
8346
8371
  } catch {
8347
8372
  continue;
8348
8373
  }
@@ -8419,19 +8444,19 @@ var init_store_lock = () => {};
8419
8444
 
8420
8445
  // ../cli/dist/utils/branch-store-locator.js
8421
8446
  import { createHash as createHash2 } from "node:crypto";
8422
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, readdirSync, statSync as statSync3, writeFileSync as writeFileSync2 } from "node:fs";
8423
- import path5 from "node:path";
8447
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync, statSync as statSync3, writeFileSync as writeFileSync2 } from "node:fs";
8448
+ import path6 from "node:path";
8424
8449
  function branchStoreKey(branch) {
8425
8450
  return createHash2("sha256").update(branch, "utf8").digest("hex");
8426
8451
  }
8427
8452
  function branchStoresRoot(workspaceRoot) {
8428
- return path5.join(path5.resolve(workspaceRoot), ".kb", "branches");
8453
+ return path6.join(path6.resolve(workspaceRoot), ".kb", "branches");
8429
8454
  }
8430
8455
  function branchStorePath(workspaceRoot, branch) {
8431
- return path5.join(branchStoresRoot(workspaceRoot), branchStoreKey(branch));
8456
+ return path6.join(branchStoresRoot(workspaceRoot), branchStoreKey(branch));
8432
8457
  }
8433
8458
  function branchStoreManifestPath(storePath) {
8434
- return path5.join(storePath, "branch.json");
8459
+ return path6.join(storePath, "branch.json");
8435
8460
  }
8436
8461
  function expectedBranchStoreManifest(branch) {
8437
8462
  return {
@@ -8445,7 +8470,7 @@ function readBranchStoreManifest(storePath) {
8445
8470
  if (!existsSync6(manifestPath))
8446
8471
  return null;
8447
8472
  try {
8448
- const parsed = JSON.parse(readFileSync4(manifestPath, "utf8"));
8473
+ const parsed = JSON.parse(readFileSync5(manifestPath, "utf8"));
8449
8474
  if (parsed.version !== BRANCH_STORE_MANIFEST_VERSION || typeof parsed.branch !== "string" || typeof parsed.key !== "string") {
8450
8475
  return null;
8451
8476
  }
@@ -8461,7 +8486,7 @@ function readBranchStoreManifest(storePath) {
8461
8486
  function branchStoreManifestMatches(storePath, branch) {
8462
8487
  const manifest = readBranchStoreManifest(storePath);
8463
8488
  const expected = expectedBranchStoreManifest(branch);
8464
- return manifest !== null && manifest.version === expected.version && manifest.branch === expected.branch && manifest.key === expected.key && path5.basename(storePath) === expected.key;
8489
+ return manifest !== null && manifest.version === expected.version && manifest.branch === expected.branch && manifest.key === expected.key && path6.basename(storePath) === expected.key;
8465
8490
  }
8466
8491
  function ensureBranchStoreManifest(workspaceRoot, branch) {
8467
8492
  const storePath = branchStorePath(workspaceRoot, branch);
@@ -8485,7 +8510,7 @@ function ensureBranchStoreManifest(workspaceRoot, branch) {
8485
8510
  return storePath;
8486
8511
  }
8487
8512
  function legacyBranchStorePath(workspaceRoot, branch) {
8488
- return path5.join(branchStoresRoot(workspaceRoot), branch);
8513
+ return path6.join(branchStoresRoot(workspaceRoot), branch);
8489
8514
  }
8490
8515
  function isDirectory(pathname) {
8491
8516
  try {
@@ -8499,8 +8524,8 @@ var init_branch_store_locator = () => {};
8499
8524
 
8500
8525
  // ../cli/dist/utils/branch-resolver.js
8501
8526
  import { execFileSync as rawExecFileSync, execSync as rawExecSync } from "node:child_process";
8502
- import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
8503
- import * as path6 from "node:path";
8527
+ import { copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync4 } from "node:fs";
8528
+ import * as path7 from "node:path";
8504
8529
  function unreadableMigrationJournalError(journalName) {
8505
8530
  return {
8506
8531
  error: `Unreadable branch migration journal '${journalName}' blocks attachment; recover it explicitly before continuing.`,
@@ -8514,7 +8539,7 @@ function _setBranchResolverDepsForTests(deps) {
8514
8539
  function isVolatileArtifact(fileName) {
8515
8540
  if (VOLATILE_ARTIFACTS.has(fileName))
8516
8541
  return true;
8517
- const ext = path6.extname(fileName).toLowerCase();
8542
+ const ext = path7.extname(fileName).toLowerCase();
8518
8543
  if (VOLATILE_EXTENSIONS.has(ext))
8519
8544
  return true;
8520
8545
  if (fileName.startsWith("journal-") && fileName.endsWith(".log"))
@@ -8683,13 +8708,13 @@ function resolveBranchAttachment(workspaceRoot = process.cwd()) {
8683
8708
  if ("error" in active)
8684
8709
  return active;
8685
8710
  const explicit = Boolean(getBranchOverride());
8686
- const migrationRoot = path6.join(path6.resolve(workspaceRoot), ".kb", "recovery", "branch-migrations");
8711
+ const migrationRoot = path7.join(path7.resolve(workspaceRoot), ".kb", "recovery", "branch-migrations");
8687
8712
  if (existsSync7(migrationRoot)) {
8688
8713
  for (const journalName of readdirSync2(migrationRoot)) {
8689
8714
  if (!journalName.endsWith(".json"))
8690
8715
  continue;
8691
8716
  try {
8692
- const journal = JSON.parse(readFileSync5(path6.join(migrationRoot, journalName), "utf8"));
8717
+ const journal = JSON.parse(readFileSync6(path7.join(migrationRoot, journalName), "utf8"));
8693
8718
  if (journal.state !== "committed" && journal.state !== "rolled_back") {
8694
8719
  const id = journalName.slice(0, -5);
8695
8720
  return {
@@ -8762,7 +8787,7 @@ function isValidBranchName(name) {
8762
8787
  const codePoint = character.codePointAt(0) ?? 0;
8763
8788
  return codePoint <= 32 || codePoint === 127;
8764
8789
  });
8765
- if (name.includes("..") || path6.isAbsolute(name) || name.startsWith("/")) {
8790
+ if (name.includes("..") || path7.isAbsolute(name) || name.startsWith("/")) {
8766
8791
  return false;
8767
8792
  }
8768
8793
  if (name.includes("//") || name.endsWith("/") || name.endsWith(".") || name.includes("\\") || name.startsWith("-") || name.includes("@{") || name.includes("..") || hasControlCharacter || /[~^:?*\[\]]/.test(name)) {
@@ -8795,8 +8820,8 @@ function copyDirectoryClean(sourceDir, targetDir) {
8795
8820
  if (isVolatileArtifact(entry)) {
8796
8821
  continue;
8797
8822
  }
8798
- const sourcePath = path6.join(sourceDir, entry);
8799
- const targetPath = path6.join(targetDir, entry);
8823
+ const sourcePath = path7.join(sourceDir, entry);
8824
+ const targetPath = path7.join(targetDir, entry);
8800
8825
  const stat = statSync4(sourcePath);
8801
8826
  if (stat.isDirectory()) {
8802
8827
  mkdirSync3(targetPath, { recursive: true });
@@ -8854,13 +8879,13 @@ var init_branch_resolver = __esm(() => {
8854
8879
 
8855
8880
  // ../cli/dist/utils/canonical-path.js
8856
8881
  import { lstatSync as lstatSync2, realpathSync as realpathSync2 } from "node:fs";
8857
- import path7 from "node:path";
8882
+ import path8 from "node:path";
8858
8883
  function canonicalFilesystemPath(candidate) {
8859
- let existing = path7.resolve(candidate);
8884
+ let existing = path8.resolve(candidate);
8860
8885
  const missing = [];
8861
8886
  for (;; ) {
8862
8887
  try {
8863
- return path7.resolve(realpathSync2.native(existing), ...missing);
8888
+ return path8.resolve(realpathSync2.native(existing), ...missing);
8864
8889
  } catch (error) {
8865
8890
  if (error.code !== "ENOENT")
8866
8891
  throw error;
@@ -8873,10 +8898,10 @@ function canonicalFilesystemPath(candidate) {
8873
8898
  }
8874
8899
  if (entry !== undefined)
8875
8900
  throw error;
8876
- const parent = path7.dirname(existing);
8901
+ const parent = path8.dirname(existing);
8877
8902
  if (parent === existing)
8878
8903
  throw error;
8879
- missing.unshift(path7.basename(existing));
8904
+ missing.unshift(path8.basename(existing));
8880
8905
  existing = parent;
8881
8906
  }
8882
8907
  }
@@ -8886,25 +8911,28 @@ var init_canonical_path = () => {};
8886
8911
  // ../cli/dist/engine.js
8887
8912
  import { spawn as spawn2 } from "node:child_process";
8888
8913
  import { createHash as createHash3, randomUUID } from "node:crypto";
8889
- import { chmodSync, closeSync as closeSync2, existsSync as existsSync8, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync6, readdirSync as readdirSync3, realpathSync as realpathSync3, renameSync, rmSync as rmSync2, statSync as statSync5, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
8914
+ import { chmodSync, closeSync as closeSync2, existsSync as existsSync8, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync as openSync2, readFileSync as readFileSync7, readdirSync as readdirSync3, realpathSync as realpathSync3, renameSync, rmSync as rmSync2, statSync as statSync5, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
8890
8915
  import * as net from "node:net";
8891
8916
  import * as os from "node:os";
8892
- import * as path8 from "node:path";
8893
- import { fileURLToPath as fileURLToPath2 } from "node:url";
8917
+ import * as path9 from "node:path";
8918
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
8919
+ function enginePackageVersions() {
8920
+ return kibiPackageVersions();
8921
+ }
8894
8922
  function engineSwiplIdentity() {
8895
8923
  return swiplIdentity(resolveSwipl());
8896
8924
  }
8897
8925
  function readJournalGeneration(branchPath) {
8898
- const currentPath = path8.join(branchPath, "CURRENT");
8926
+ const currentPath = path9.join(branchPath, "CURRENT");
8899
8927
  if (!existsSync8(currentPath))
8900
8928
  return "";
8901
- return readFileSync6(currentPath, "utf8").trim();
8929
+ return readFileSync7(currentPath, "utf8").trim();
8902
8930
  }
8903
8931
  function readEngineAttachmentIdentity(branchPath) {
8904
8932
  if (!existsSync8(branchPath))
8905
8933
  return null;
8906
8934
  const stats = statSync5(branchPath);
8907
- let resolved = path8.resolve(branchPath);
8935
+ let resolved = path9.resolve(branchPath);
8908
8936
  try {
8909
8937
  resolved = realpathSync3(branchPath);
8910
8938
  } catch {}
@@ -8978,15 +9006,15 @@ function parseFrames(buffer, onFrame) {
8978
9006
  return buffer.subarray(cursor);
8979
9007
  }
8980
9008
  function runtimeDirectory() {
8981
- const configured = process.env.KIBI_RUNTIME_DIR ?? process.env.XDG_RUNTIME_DIR ?? path8.join(os.tmpdir(), "kibi-runtime");
9009
+ const configured = process.env.KIBI_RUNTIME_DIR ?? process.env.XDG_RUNTIME_DIR ?? path9.join(os.tmpdir(), "kibi-runtime");
8982
9010
  if (process.platform === "win32") {
8983
9011
  for (const candidate of [
8984
9012
  configured,
8985
- path8.join(os.tmpdir(), "kibi-runtime")
9013
+ path9.join(os.tmpdir(), "kibi-runtime")
8986
9014
  ]) {
8987
9015
  try {
8988
9016
  mkdirSync4(candidate, { recursive: true, mode: 448 });
8989
- const probe = path8.join(candidate, `.kibi-write-${process.pid}`);
9017
+ const probe = path9.join(candidate, `.kibi-write-${process.pid}`);
8990
9018
  writeFileSync3(probe, "", { mode: 384 });
8991
9019
  unlinkSync(probe);
8992
9020
  return candidate;
@@ -9001,12 +9029,12 @@ function runtimeDirectory() {
9001
9029
  try {
9002
9030
  configuredIdentity = canonicalFilesystemPath(configured);
9003
9031
  } catch {
9004
- configuredIdentity = path8.resolve(configured);
9032
+ configuredIdentity = path9.resolve(configured);
9005
9033
  }
9006
9034
  const configuredKey = createHash3("sha256").update(configuredIdentity).digest("hex").slice(0, 32);
9007
9035
  const candidates = [
9008
9036
  configured,
9009
- path8.join("/tmp", `kb-${euid}-${configuredKey}`)
9037
+ path9.join("/tmp", `kb-${euid}-${configuredKey}`)
9010
9038
  ];
9011
9039
  const maximumBytes = process.platform === "linux" ? 107 : 103;
9012
9040
  const socketName = `kibi-${"0".repeat(32)}.sock`;
@@ -9024,9 +9052,9 @@ function runtimeDirectory() {
9024
9052
  if (!directory.isDirectory() || directory.uid !== euid || (directory.mode & 63) !== 0)
9025
9053
  continue;
9026
9054
  const canonical = canonicalFilesystemPath(candidate);
9027
- if (Buffer.byteLength(path8.join(canonical, socketName), "utf8") > maximumBytes)
9055
+ if (Buffer.byteLength(path9.join(canonical, socketName), "utf8") > maximumBytes)
9028
9056
  continue;
9029
- const probe = path8.join(canonical, `.kibi-write-${randomUUID()}`);
9057
+ const probe = path9.join(canonical, `.kibi-write-${randomUUID()}`);
9030
9058
  writeFileSync3(probe, "", { mode: 384, flag: "wx" });
9031
9059
  unlinkSync(probe);
9032
9060
  return canonical;
@@ -9047,7 +9075,7 @@ function fsyncPath(filePath) {
9047
9075
  }
9048
9076
  }
9049
9077
  function fsyncJournaledBranchStore(branchPath) {
9050
- const rdfRoot = path8.join(branchPath, "rdf");
9078
+ const rdfRoot = path9.join(branchPath, "rdf");
9051
9079
  const directories = [];
9052
9080
  const pending = existsSync8(rdfRoot) ? [rdfRoot] : [];
9053
9081
  while (pending.length > 0) {
@@ -9056,7 +9084,7 @@ function fsyncJournaledBranchStore(branchPath) {
9056
9084
  break;
9057
9085
  directories.push(directory);
9058
9086
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
9059
- const entryPath = path8.join(directory, entry.name);
9087
+ const entryPath = path9.join(directory, entry.name);
9060
9088
  if (entry.isDirectory())
9061
9089
  pending.push(entryPath);
9062
9090
  else if (entry.isFile() && entry.name !== "lock")
@@ -9064,7 +9092,7 @@ function fsyncJournaledBranchStore(branchPath) {
9064
9092
  }
9065
9093
  }
9066
9094
  for (const metadata of ["CURRENT", "storage.json", "kb.rdf"]) {
9067
- fsyncPath(path8.join(branchPath, metadata));
9095
+ fsyncPath(path9.join(branchPath, metadata));
9068
9096
  }
9069
9097
  if (process.platform !== "win32") {
9070
9098
  for (const directory of directories.reverse())
@@ -9078,18 +9106,18 @@ function engineSocketPath(workspaceRoot, branch) {
9078
9106
  if (process.platform === "win32") {
9079
9107
  return `\\\\.\\pipe\\kibi-${key}`;
9080
9108
  }
9081
- return path8.join(runtimeDirectory(), `kibi-${key}.sock`);
9109
+ return path9.join(runtimeDirectory(), `kibi-${key}.sock`);
9082
9110
  }
9083
9111
  function enginePidPath(workspaceRoot, branch) {
9084
9112
  const socket = engineSocketPath(workspaceRoot, branch);
9085
9113
  if (process.platform === "win32") {
9086
- return path8.join(runtimeDirectory(), `kibi-${createHash3("sha256").update(`${path8.resolve(workspaceRoot)}\x00${branch}`).digest("hex")}.pid`);
9114
+ return path9.join(runtimeDirectory(), `kibi-${createHash3("sha256").update(`${path9.resolve(workspaceRoot)}\x00${branch}`).digest("hex")}.pid`);
9087
9115
  }
9088
9116
  return `${socket}.pid`;
9089
9117
  }
9090
9118
  function engineStartLockPath(workspaceRoot, branch) {
9091
9119
  if (process.platform === "win32") {
9092
- return path8.join(runtimeDirectory(), `kibi-${createHash3("sha256").update(`${path8.resolve(workspaceRoot)}\x00${branch}`).digest("hex")}.start.lock`);
9120
+ return path9.join(runtimeDirectory(), `kibi-${createHash3("sha256").update(`${path9.resolve(workspaceRoot)}\x00${branch}`).digest("hex")}.start.lock`);
9093
9121
  }
9094
9122
  return `${engineSocketPath(workspaceRoot, branch)}.start.lock`;
9095
9123
  }
@@ -9098,7 +9126,7 @@ function enginePublicationLockPath(workspaceRoot, branch) {
9098
9126
  }
9099
9127
  function publicationLockOwner(lockPath) {
9100
9128
  try {
9101
- const [pidText, createdText] = readFileSync6(lockPath, "utf8").trim().split(":");
9129
+ const [pidText, createdText] = readFileSync7(lockPath, "utf8").trim().split(":");
9102
9130
  const pid = Number.parseInt(pidText ?? "", 10);
9103
9131
  const createdAt = Number.parseInt(createdText ?? "", 10);
9104
9132
  if (!Number.isInteger(pid) || pid <= 1 || !Number.isFinite(createdAt)) {
@@ -9146,7 +9174,7 @@ function publicationLockIsActive(lockPath) {
9146
9174
  }
9147
9175
  function acquireEnginePublicationLease(workspaceRoot, branch) {
9148
9176
  const lockPath = enginePublicationLockPath(workspaceRoot, branch);
9149
- mkdirSync4(path8.dirname(lockPath), { recursive: true, mode: 448 });
9177
+ mkdirSync4(path9.dirname(lockPath), { recursive: true, mode: 448 });
9150
9178
  let descriptor = null;
9151
9179
  try {
9152
9180
  descriptor = openSync2(lockPath, "wx", 384);
@@ -9200,7 +9228,7 @@ function tryAcquireStartLock(lockPath) {
9200
9228
  return descriptor;
9201
9229
  } catch {
9202
9230
  try {
9203
- const stamp = readFileSync6(lockPath, "utf8").trim().split(":");
9231
+ const stamp = readFileSync7(lockPath, "utf8").trim().split(":");
9204
9232
  const pid = Number.parseInt(stamp[0] ?? "", 10);
9205
9233
  const created = Number.parseInt(stamp[1] ?? "", 10);
9206
9234
  let age = 0;
@@ -9238,12 +9266,12 @@ function releaseStartLock(lockPath, descriptor) {
9238
9266
  } catch {}
9239
9267
  }
9240
9268
  function recoverStaleJournalLock(branchPath) {
9241
- const lockPath = path8.join(branchPath, "rdf", "lock");
9269
+ const lockPath = path9.join(branchPath, "rdf", "lock");
9242
9270
  if (!existsSync8(lockPath))
9243
9271
  return;
9244
9272
  let contents = "";
9245
9273
  try {
9246
- contents = readFileSync6(lockPath, "utf8");
9274
+ contents = readFileSync7(lockPath, "utf8");
9247
9275
  } catch {
9248
9276
  return;
9249
9277
  }
@@ -9263,11 +9291,11 @@ function recoverStaleJournalLock(branchPath) {
9263
9291
  }
9264
9292
  }
9265
9293
  function daemonEntry() {
9266
- const moduleDirectory = path8.dirname(fileURLToPath2(import.meta.url));
9294
+ const moduleDirectory = path9.dirname(fileURLToPath3(import.meta.url));
9267
9295
  const candidates = [
9268
- path8.join(moduleDirectory, "engine-daemon.js"),
9269
- path8.join(moduleDirectory, "..", "dist", "engine-daemon.js"),
9270
- path8.join(moduleDirectory, "..", "node_modules", "kibi-cli", "dist", "engine-daemon.js")
9296
+ path9.join(moduleDirectory, "engine-daemon.js"),
9297
+ path9.join(moduleDirectory, "..", "dist", "engine-daemon.js"),
9298
+ path9.join(moduleDirectory, "..", "node_modules", "kibi-cli", "dist", "engine-daemon.js")
9271
9299
  ];
9272
9300
  for (const candidate of candidates) {
9273
9301
  if (existsSync8(candidate))
@@ -9309,7 +9337,7 @@ async function connectWithRetry(socketPath, timeoutMs) {
9309
9337
  const errorPath = `${socketPath}.error`;
9310
9338
  if (existsSync8(errorPath)) {
9311
9339
  try {
9312
- const diagnostic = readFileSync6(errorPath, "utf8").trim();
9340
+ const diagnostic = readFileSync7(errorPath, "utf8").trim();
9313
9341
  if (diagnostic)
9314
9342
  throw new Error(diagnostic);
9315
9343
  } catch (error) {
@@ -9440,7 +9468,8 @@ class EngineClient {
9440
9468
  stdio: "ignore",
9441
9469
  env: {
9442
9470
  ...process.env,
9443
- KIBI_ENGINE_PROTOCOL: String(ENGINE_PROTOCOL_VERSION)
9471
+ KIBI_ENGINE_PROTOCOL: String(ENGINE_PROTOCOL_VERSION),
9472
+ KIBI_PACKAGE_VERSIONS: enginePackageVersions()
9444
9473
  }
9445
9474
  });
9446
9475
  await new Promise((resolve, reject) => {
@@ -9542,7 +9571,7 @@ class EngineClient {
9542
9571
  ...limits,
9543
9572
  id,
9544
9573
  protocolVersion: ENGINE_PROTOCOL_VERSION,
9545
- packageVersions: ENGINE_PACKAGE_VERSIONS,
9574
+ packageVersions: enginePackageVersions(),
9546
9575
  prologIdentity: engineSwiplIdentity(),
9547
9576
  workspaceRoot: this.workspaceRoot,
9548
9577
  branch: this.branch
@@ -9641,7 +9670,7 @@ class EngineClient {
9641
9670
  method: "cancel",
9642
9671
  cancelOf: requestId,
9643
9672
  protocolVersion: ENGINE_PROTOCOL_VERSION,
9644
- packageVersions: ENGINE_PACKAGE_VERSIONS,
9673
+ packageVersions: enginePackageVersions(),
9645
9674
  prologIdentity: engineSwiplIdentity(),
9646
9675
  workspaceRoot: this.workspaceRoot,
9647
9676
  branch: this.branch
@@ -9685,23 +9714,49 @@ class EngineClient {
9685
9714
  return null;
9686
9715
  return parseEngineAttachmentIdentity(status.bindings.JsonString);
9687
9716
  }
9688
- async daemonRuntimeMatches() {
9717
+ async daemonHandshake() {
9689
9718
  const reply = await this.request({
9690
9719
  method: "handshake"
9691
9720
  });
9692
- return reply?.prologIdentity === engineSwiplIdentity();
9721
+ return {
9722
+ prologIdentity: typeof reply?.prologIdentity === "string" ? reply.prologIdentity : null,
9723
+ packageVersions: typeof reply?.packageVersions === "string" ? reply.packageVersions : null
9724
+ };
9725
+ }
9726
+ async inspectLiveDaemon() {
9727
+ const wasConnected = this.isRunning();
9728
+ if (!wasConnected)
9729
+ await this.connect(false);
9730
+ if (!this.isRunning())
9731
+ return null;
9732
+ try {
9733
+ return await this.daemonHandshake();
9734
+ } finally {
9735
+ if (!wasConnected)
9736
+ await this.terminate();
9737
+ }
9738
+ }
9739
+ async daemonRuntimeMismatch() {
9740
+ const daemon = await this.daemonHandshake();
9741
+ const packageVersions = enginePackageVersions();
9742
+ if (daemon.packageVersions !== packageVersions)
9743
+ return `Kibi engine is running other package versions (${daemon.packageVersions ?? "not reported"}) than this client (${packageVersions})`;
9744
+ if (daemon.prologIdentity !== engineSwiplIdentity())
9745
+ return `Kibi engine is running a different SWI-Prolog than this client resolved (${engineSwiplIdentity()})`;
9746
+ return null;
9693
9747
  }
9694
9748
  async reconcileRuntime() {
9695
9749
  if (this.replacingStaleDaemon || this.socket === null)
9696
9750
  return;
9697
- if (await this.daemonRuntimeMatches())
9751
+ if (await this.daemonRuntimeMismatch() === null)
9698
9752
  return;
9699
9753
  this.replacingStaleDaemon = true;
9700
9754
  try {
9701
9755
  await this.shutdownConnectedDaemon();
9702
9756
  await this.connect(true);
9703
- if (!await this.daemonRuntimeMatches()) {
9704
- throw new Error(`Kibi engine is running a different SWI-Prolog than this client resolved (${engineSwiplIdentity()}); run 'kibi engine stop' and retry`);
9757
+ const mismatch = await this.daemonRuntimeMismatch();
9758
+ if (mismatch !== null) {
9759
+ throw new Error(`${mismatch} after replacing it; run 'kibi engine stop' and retry`);
9705
9760
  }
9706
9761
  } finally {
9707
9762
  this.replacingStaleDaemon = false;
@@ -9765,7 +9820,7 @@ class EngineClient {
9765
9820
  getPid() {
9766
9821
  const pidPath = enginePidPath(this.workspaceRoot, this.branch);
9767
9822
  try {
9768
- return Number.parseInt(readFileSync6(pidPath, "utf8").trim(), 10) || 0;
9823
+ return Number.parseInt(readFileSync7(pidPath, "utf8").trim(), 10) || 0;
9769
9824
  } catch {
9770
9825
  return 0;
9771
9826
  }
@@ -9796,12 +9851,12 @@ class EngineClient {
9796
9851
  }
9797
9852
  async function ensureJournaledBranchStoreAsync(branchPath) {
9798
9853
  mkdirSync4(branchPath, { recursive: true });
9799
- const markerPath = path8.join(branchPath, "storage.json");
9800
- const marker = existsSync8(markerPath) ? readFileSync6(markerPath, "utf8") : "";
9854
+ const markerPath = path9.join(branchPath, "storage.json");
9855
+ const marker = existsSync8(markerPath) ? readFileSync7(markerPath, "utf8") : "";
9801
9856
  if (marker.includes("kibi.rdf-journal.v1")) {
9802
- const rdfDirectory = path8.join(branchPath, "rdf");
9803
- const currentPath = path8.join(branchPath, "CURRENT");
9804
- const sentinelPath = path8.join(branchPath, "kb.rdf");
9857
+ const rdfDirectory = path9.join(branchPath, "rdf");
9858
+ const currentPath = path9.join(branchPath, "CURRENT");
9859
+ const sentinelPath = path9.join(branchPath, "kb.rdf");
9805
9860
  if (!existsSync8(rdfDirectory) || !existsSync8(currentPath)) {
9806
9861
  recoverInterruptedGeneration(branchPath);
9807
9862
  if (existsSync8(rdfDirectory) && existsSync8(currentPath)) {
@@ -9813,9 +9868,9 @@ async function ensureJournaledBranchStoreAsync(branchPath) {
9813
9868
  }
9814
9869
  return;
9815
9870
  }
9816
- const legacyRdf = path8.join(branchPath, "kb.rdf");
9817
- const legacyAudit = path8.join(branchPath, "audit.log");
9818
- const legacyContents = existsSync8(legacyRdf) ? readFileSync6(legacyRdf, "utf8") : "";
9871
+ const legacyRdf = path9.join(branchPath, "kb.rdf");
9872
+ const legacyAudit = path9.join(branchPath, "audit.log");
9873
+ const legacyContents = existsSync8(legacyRdf) ? readFileSync7(legacyRdf, "utf8") : "";
9819
9874
  if (existsSync8(legacyAudit) || existsSync8(legacyRdf) && !legacyContents.includes("kibi.rdf-journal.v1")) {
9820
9875
  rmSync2(rdfDirectory, { recursive: true, force: true });
9821
9876
  rmSync2(currentPath, { force: true });
@@ -9833,29 +9888,29 @@ async function ensureJournaledBranchStoreAsync(branchPath) {
9833
9888
  return;
9834
9889
  }
9835
9890
  }
9836
- const legacyRdf = path8.join(branchPath, "kb.rdf");
9837
- const legacyAudit = path8.join(branchPath, "audit.log");
9891
+ const legacyRdf = path9.join(branchPath, "kb.rdf");
9892
+ const legacyAudit = path9.join(branchPath, "audit.log");
9838
9893
  if (!existsSync8(legacyRdf) && !existsSync8(legacyAudit)) {
9839
- mkdirSync4(path8.join(branchPath, "rdf"), { recursive: true });
9894
+ mkdirSync4(path9.join(branchPath, "rdf"), { recursive: true });
9840
9895
  writeFileSync3(markerPath, `{"format":"kibi.rdf-journal.v1","schemaVersion":1}
9841
9896
  `, { mode: 384 });
9842
- writeFileSync3(path8.join(branchPath, "CURRENT"), `generation-1:0
9897
+ writeFileSync3(path9.join(branchPath, "CURRENT"), `generation-1:0
9843
9898
  `, {
9844
9899
  mode: 384
9845
9900
  });
9846
- writeFileSync3(path8.join(branchPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
9901
+ writeFileSync3(path9.join(branchPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
9847
9902
  `, { mode: 384 });
9848
9903
  return;
9849
9904
  }
9850
9905
  if (existsSync8(legacyRdf)) {
9851
- const legacyContents = readFileSync6(legacyRdf, "utf8");
9906
+ const legacyContents = readFileSync7(legacyRdf, "utf8");
9852
9907
  if (!/<rdf:RDF(?:\s|>)/.test(legacyContents)) {
9853
9908
  throw new Error(`Legacy Kibi store is corrupt at ${legacyRdf}: expected RDF/XML root`);
9854
9909
  }
9855
9910
  }
9856
- const parent = path8.dirname(branchPath);
9857
- const migrationKey = createHash3("sha256").update(path8.resolve(branchPath)).digest("hex").slice(0, 16);
9858
- const staging = path8.join(parent, `.${migrationKey}.migration.${process.pid}.${Date.now()}`);
9911
+ const parent = path9.dirname(branchPath);
9912
+ const migrationKey = createHash3("sha256").update(path9.resolve(branchPath)).digest("hex").slice(0, 16);
9913
+ const staging = path9.join(parent, `.${migrationKey}.migration.${process.pid}.${Date.now()}`);
9859
9914
  mkdirSync4(staging, { recursive: true, mode: 448 });
9860
9915
  const testOneShot = false;
9861
9916
  const migrator = new PrologProcess({
@@ -9883,35 +9938,35 @@ async function ensureJournaledBranchStoreAsync(branchPath) {
9883
9938
  await migrator.terminate();
9884
9939
  }
9885
9940
  for (const file of ["rdf", "storage.json", "CURRENT"]) {
9886
- const source = path8.join(staging, file);
9941
+ const source = path9.join(staging, file);
9887
9942
  if (!existsSync8(source))
9888
9943
  continue;
9889
- const target = path8.join(branchPath, file);
9944
+ const target = path9.join(branchPath, file);
9890
9945
  if (existsSync8(target))
9891
9946
  rmSync2(target, { recursive: true, force: true });
9892
9947
  renameSync(source, target);
9893
9948
  }
9894
9949
  archiveLegacyFiles(branchPath);
9895
- writeFileSync3(path8.join(branchPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
9950
+ writeFileSync3(path9.join(branchPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
9896
9951
  `, { mode: 384 });
9897
9952
  fsyncJournaledBranchStore(branchPath);
9898
9953
  rmSync2(staging, { recursive: true, force: true });
9899
9954
  }
9900
9955
  function archiveLegacyFiles(branchPath) {
9901
- const legacyDir = path8.join(branchPath, "legacy");
9956
+ const legacyDir = path9.join(branchPath, "legacy");
9902
9957
  mkdirSync4(legacyDir, { recursive: true, mode: 448 });
9903
9958
  for (const file of ["kb.rdf", "audit.log"]) {
9904
- const source = path8.join(branchPath, file);
9959
+ const source = path9.join(branchPath, file);
9905
9960
  if (!existsSync8(source))
9906
9961
  continue;
9907
9962
  if (file === "kb.rdf") {
9908
- const contents = readFileSync6(source, "utf8");
9963
+ const contents = readFileSync7(source, "utf8");
9909
9964
  if (contents.includes("kibi.rdf-journal.v1"))
9910
9965
  continue;
9911
9966
  }
9912
- const destination = path8.join(legacyDir, file);
9967
+ const destination = path9.join(legacyDir, file);
9913
9968
  if (existsSync8(destination)) {
9914
- renameSync(source, path8.join(legacyDir, `${file}.recovery.${Date.now()}`));
9969
+ renameSync(source, path9.join(legacyDir, `${file}.recovery.${Date.now()}`));
9915
9970
  } else {
9916
9971
  renameSync(source, destination);
9917
9972
  }
@@ -9927,12 +9982,12 @@ function recoverInterruptedGeneration(branchPath) {
9927
9982
  const newest = (prefix) => {
9928
9983
  const candidates = entries.filter((entry) => entry.startsWith(prefix)).sort().reverse();
9929
9984
  const candidate = candidates[0];
9930
- return candidate === undefined ? null : path8.join(branchPath, candidate);
9985
+ return candidate === undefined ? null : path9.join(branchPath, candidate);
9931
9986
  };
9932
9987
  const oldRdf = newest("rdf.old.");
9933
9988
  const oldCurrent = newest("CURRENT.old.");
9934
- const rdfPath = path8.join(branchPath, "rdf");
9935
- const currentPath = path8.join(branchPath, "CURRENT");
9989
+ const rdfPath = path9.join(branchPath, "rdf");
9990
+ const currentPath = path9.join(branchPath, "CURRENT");
9936
9991
  if ((!existsSync8(rdfPath) || !existsSync8(currentPath)) && oldRdf && oldCurrent) {
9937
9992
  try {
9938
9993
  if (existsSync8(rdfPath))
@@ -9958,6 +10013,7 @@ function recoverInterruptedGeneration(branchPath) {
9958
10013
  var READ_LIMITED_METHODS, ENGINE_PROTOCOL_VERSION = 1, ENGINE_IDLE_TIMEOUT_MS, ENGINE_PACKAGE_VERSIONS, ENGINE_QUERY_CACHE_MAX_RESULT_BYTES, ENGINE_PUBLICATION_LOCK_STALE_MS = 5000;
9959
10014
  var init_engine = __esm(() => {
9960
10015
  init_engine_limits();
10016
+ init_package_versions();
9961
10017
  init_performance_trace();
9962
10018
  init_prolog();
9963
10019
  init_store_lock();
@@ -9974,7 +10030,7 @@ var init_engine = __esm(() => {
9974
10030
  "search"
9975
10031
  ]);
9976
10032
  ENGINE_IDLE_TIMEOUT_MS = 10 * 60 * 1000;
9977
- ENGINE_PACKAGE_VERSIONS = process.env.KIBI_PACKAGE_VERSIONS ?? "unknown";
10033
+ ENGINE_PACKAGE_VERSIONS = kibiPackageVersions();
9978
10034
  ENGINE_QUERY_CACHE_MAX_RESULT_BYTES = 8 * 1024 * 1024;
9979
10035
  });
9980
10036
 
@@ -10235,9 +10291,25 @@ var init_entity_body_context = __esm(() => {
10235
10291
  };
10236
10292
  });
10237
10293
 
10294
+ // ../cli/dist/provenance-stub.js
10295
+ function tagList(value) {
10296
+ if (typeof value === "string")
10297
+ return [value];
10298
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
10299
+ }
10300
+ function isProvenanceStub(entity) {
10301
+ if (!entity)
10302
+ return false;
10303
+ const type = String(entity.type ?? "");
10304
+ if (type !== "" && type !== "fact")
10305
+ return false;
10306
+ return tagList(entity.tags).includes(PROVENANCE_STUB_TAG);
10307
+ }
10308
+ var PROVENANCE_STUB_TAG = "bootstrap:provenance-stub";
10309
+
10238
10310
  // ../cli/dist/search-ranking.js
10239
10311
  import fs from "node:fs/promises";
10240
- import path9 from "node:path";
10312
+ import path10 from "node:path";
10241
10313
  async function rankEntities(entities, query, workspaceRoot) {
10242
10314
  const queryContext = buildSearchQueryContext(query);
10243
10315
  if (!queryContext.rawTrimmedQuery || queryContext.signalTokens.length === 0) {
@@ -10247,10 +10319,15 @@ async function rankEntities(entities, query, workspaceRoot) {
10247
10319
  for (const entity of entities) {
10248
10320
  const match = await rankEntity(entity, queryContext, workspaceRoot);
10249
10321
  if (match) {
10322
+ if (isProvenanceStub(entity))
10323
+ match.reasons.push("demoted: provenance stub");
10250
10324
  matches.push(match);
10251
10325
  }
10252
10326
  }
10253
10327
  matches.sort((left, right) => {
10328
+ const stubOrder = Number(isProvenanceStub(left.entity)) - Number(isProvenanceStub(right.entity));
10329
+ if (stubOrder !== 0)
10330
+ return stubOrder;
10254
10331
  if (right.score !== left.score) {
10255
10332
  return right.score - left.score;
10256
10333
  }
@@ -10341,9 +10418,9 @@ async function loadMarkdownBody(source, workspaceRoot) {
10341
10418
  if (!normalizedSource.endsWith(".md")) {
10342
10419
  return null;
10343
10420
  }
10344
- const resolved = path9.resolve(path9.isAbsolute(normalizedSource) ? normalizedSource : path9.join(workspaceRoot, normalizedSource));
10345
- const normalizedRoot = path9.resolve(workspaceRoot);
10346
- if (!resolved.startsWith(normalizedRoot + path9.sep)) {
10421
+ const resolved = path10.resolve(path10.isAbsolute(normalizedSource) ? normalizedSource : path10.join(workspaceRoot, normalizedSource));
10422
+ const normalizedRoot = path10.resolve(workspaceRoot);
10423
+ if (!resolved.startsWith(normalizedRoot + path10.sep)) {
10347
10424
  return null;
10348
10425
  }
10349
10426
  try {
@@ -10469,7 +10546,7 @@ var init_search_ranking = __esm(() => {
10469
10546
  });
10470
10547
 
10471
10548
  // ../cli/dist/intent-search.js
10472
- import path10 from "node:path";
10549
+ import path11 from "node:path";
10473
10550
  function normalize(value) {
10474
10551
  return value.trim().toLowerCase().replace(/[-_]+/g, " ").replace(/[^a-z0-9\s]+/g, " ").split(/\s+/).filter(Boolean).map((token) => token.length > 4 && token.endsWith("s") && !token.endsWith("ss") ? token.slice(0, -1) : token).map(stem).join(" ");
10475
10552
  }
@@ -10598,7 +10675,7 @@ function entityTokens(entity, body) {
10598
10675
  ENTITY_TOKENS.set(entity, computed);
10599
10676
  return computed;
10600
10677
  }
10601
- function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence, documentFrequency, documentCount, body, superseded = false) {
10678
+ function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence, documentFrequency, documentCount, body, superseded = false, provenanceStub = false) {
10602
10679
  const { title: titleTokens, metadata: metadataTokens, bodyTokens } = entityTokens(entity, body);
10603
10680
  const allSignalTokens = Array.from(new Set(queryTokens));
10604
10681
  let placed = 0;
@@ -10631,10 +10708,12 @@ function scoreEntity(entity, queryTokens, facets, sourceEvidence, graphEvidence,
10631
10708
  const graphScore = graphEvidence.length > 0 ? Math.min(1, graphEvidence.length / 2) : 0;
10632
10709
  const status = String(entity.status ?? "").trim().toLowerCase();
10633
10710
  const nonGoverning = NON_GOVERNING_STATUSES.has(status) || superseded;
10634
- const score = Math.min(1, lexicalScore * 0.58 + facetScore * 0.17 + sourceScore * 0.2 + graphScore * 0.05) * (nonGoverning ? NON_GOVERNING_FACTOR : 1);
10711
+ const score = Math.min(1, lexicalScore * 0.58 + facetScore * 0.17 + sourceScore * 0.2 + graphScore * 0.05) * (nonGoverning ? NON_GOVERNING_FACTOR : 1) * (provenanceStub ? PROVENANCE_STUB_FACTOR : 1);
10635
10712
  const reasons = [];
10636
10713
  if (nonGoverning)
10637
10714
  reasons.push(superseded ? "demoted: superseded" : `demoted: ${status}`);
10715
+ if (provenanceStub)
10716
+ reasons.push("demoted: provenance stub");
10638
10717
  if (lexicalScore > 0)
10639
10718
  reasons.push("intent token match");
10640
10719
  if (matchedFacets.length > 0)
@@ -10702,7 +10781,7 @@ async function rankIntentEntities(entities, options2, workspaceRoot, graphEdges
10702
10781
  const entityId = String(entity.id ?? "");
10703
10782
  const graphEvidence = (graphByEntity.get(entityId) ?? []).slice(0, 8);
10704
10783
  const body = bodies.get(entity) ?? null;
10705
- const scored = scoreEntity(entity, allTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId));
10784
+ const scored = scoreEntity(entity, allTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId), isProvenanceStub(entity));
10706
10785
  if (scored.score < minScore)
10707
10786
  continue;
10708
10787
  const snippet = body === null ? undefined : bodySnippetLine(String(entity.type ?? ""), body, entity);
@@ -10721,6 +10800,9 @@ async function rankIntentEntities(entities, options2, workspaceRoot, graphEdges
10721
10800
  });
10722
10801
  }
10723
10802
  ranked.sort((left, right) => {
10803
+ const stubOrder = Number(isProvenanceStub(left.entity)) - Number(isProvenanceStub(right.entity));
10804
+ if (stubOrder !== 0)
10805
+ return stubOrder;
10724
10806
  if (right.score !== left.score)
10725
10807
  return right.score - left.score;
10726
10808
  const typeOrder = String(left.entity.type ?? "").localeCompare(String(right.entity.type ?? ""));
@@ -10841,7 +10923,7 @@ function validateIntentSearchInput(input) {
10841
10923
  throw new Error("Search execution failed: minScore must be between 0 and 1");
10842
10924
  }
10843
10925
  for (const location of input.sourceLocations ?? []) {
10844
- if (!location.path.trim() || path10.isAbsolute(location.path) || location.path.split("/").includes("..")) {
10926
+ if (!location.path.trim() || path11.isAbsolute(location.path) || location.path.split("/").includes("..")) {
10845
10927
  throw new Error("Search execution failed: sourceLocations.path must be workspace-relative");
10846
10928
  }
10847
10929
  if (location.line !== undefined && (!Number.isInteger(location.line) || location.line < 1)) {
@@ -10852,7 +10934,7 @@ function validateIntentSearchInput(input) {
10852
10934
  }
10853
10935
  }
10854
10936
  }
10855
- var GRAPH_RELATIONSHIPS, FACET_NAMES, STOP_WORDS, NON_GOVERNING_STATUSES, NON_GOVERNING_FACTOR = 0.5, AMBIGUOUS_MARGIN = 0.05, MAX_CANDIDATES = 1e4, MAX_GRAPH_SEEDS = 5, MAX_GRAPH_EDGES = 2000, STEM_SUFFIXES, ENTITY_TOKENS, BODY_READ_CONCURRENCY = 32;
10937
+ var GRAPH_RELATIONSHIPS, FACET_NAMES, STOP_WORDS, NON_GOVERNING_STATUSES, NON_GOVERNING_FACTOR = 0.5, PROVENANCE_STUB_FACTOR = 0.25, AMBIGUOUS_MARGIN = 0.05, MAX_CANDIDATES = 1e4, MAX_GRAPH_SEEDS = 5, MAX_GRAPH_EDGES = 2000, STEM_SUFFIXES, ENTITY_TOKENS, BODY_READ_CONCURRENCY = 32;
10856
10938
  var init_intent_search = __esm(() => {
10857
10939
  init_entity_body_context();
10858
10940
  init_discovery_entities();
@@ -11089,8 +11171,8 @@ var LATEST_KB_SCHEMA_VERSION = 8;
11089
11171
 
11090
11172
  // ../cli/dist/utils/kb-manifest.js
11091
11173
  import { createHash as createHash4 } from "node:crypto";
11092
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync7, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
11093
- import * as path11 from "node:path";
11174
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync8, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "node:fs";
11175
+ import * as path12 from "node:path";
11094
11176
  function defaultKbManifest() {
11095
11177
  return {
11096
11178
  manifestVersion: KB_MANIFEST_VERSION,
@@ -11099,7 +11181,7 @@ function defaultKbManifest() {
11099
11181
  };
11100
11182
  }
11101
11183
  function manifestPathFor(workspaceRoot) {
11102
- return path11.join(workspaceRoot, KB_PATHS.manifest);
11184
+ return path12.join(workspaceRoot, KB_PATHS.manifest);
11103
11185
  }
11104
11186
  function isRecord(value) {
11105
11187
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -11143,7 +11225,7 @@ function readKbManifestStatus(workspaceRoot) {
11143
11225
  }
11144
11226
  let contents;
11145
11227
  try {
11146
- contents = readFileSync7(manifestPath, "utf8");
11228
+ contents = readFileSync8(manifestPath, "utf8");
11147
11229
  } catch {
11148
11230
  return {
11149
11231
  state: "invalid",
@@ -11189,7 +11271,7 @@ function readKbManifest(workspaceRoot) {
11189
11271
  return status.state === "ok" ? status.manifest : null;
11190
11272
  }
11191
11273
  function writeAtomically(filePath, content) {
11192
- mkdirSync5(path11.dirname(filePath), { recursive: true });
11274
+ mkdirSync5(path12.dirname(filePath), { recursive: true });
11193
11275
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
11194
11276
  writeFileSync4(tempPath, content, "utf8");
11195
11277
  renameSync2(tempPath, filePath);
@@ -11206,7 +11288,7 @@ var init_kb_manifest = __esm(() => {
11206
11288
  });
11207
11289
 
11208
11290
  // ../cli/dist/operations/bootstrap/activation.js
11209
- import path12 from "node:path";
11291
+ import path13 from "node:path";
11210
11292
  function missingManifestActivation(vendored, projectSignal) {
11211
11293
  return activationFor(vendored && !projectSignal ? "vendored_only" : "root_uninitialized");
11212
11294
  }
@@ -11294,21 +11376,21 @@ function sourceCoverageState(files) {
11294
11376
  async function classifyActivation(context, files = []) {
11295
11377
  const sourceFiles = Array.isArray(files) ? files : [];
11296
11378
  const normalizedFiles = sourceFiles.map((file) => {
11297
- const relative = path12.isAbsolute(file) ? path12.relative(context.workspaceRoot, file) : file;
11379
+ const relative = path13.isAbsolute(file) ? path13.relative(context.workspaceRoot, file) : file;
11298
11380
  return relative.replaceAll("\\", "/");
11299
11381
  });
11300
11382
  const manifestStatus = readKbManifestStatus(context.workspaceRoot);
11301
11383
  if (manifestStatus.state === "missing") {
11302
11384
  const vendored = normalizedFiles.some((file) => file.startsWith("kibi/"));
11303
11385
  const projectSignalFromFiles = normalizedFiles.some((file) => !file.startsWith("kibi/") && /^(README\.md|package\.json|src\/|app\/|packages\/|tests\/)/.test(file));
11304
- const projectSignalFromDirectories = await Promise.all(["README.md", "package.json", "src", "app", "packages", "tests"].map((target) => exists(context, path12.resolve(context.workspaceRoot, target))));
11386
+ const projectSignalFromDirectories = await Promise.all(["README.md", "package.json", "src", "app", "packages", "tests"].map((target) => exists(context, path13.resolve(context.workspaceRoot, target))));
11305
11387
  const projectSignal = projectSignalFromFiles || projectSignalFromDirectories.some(Boolean);
11306
11388
  return missingManifestActivation(vendored, projectSignal);
11307
11389
  }
11308
11390
  if (manifestStatus.state !== "ok")
11309
11391
  return activationFor("root_partial");
11310
11392
  const targets = [...Object.values(KB_PATHS.lanes), KB_PATHS.symbolsManifest];
11311
- const resolved = await Promise.all(targets.map((target) => exists(context, path12.resolve(context.workspaceRoot, target))));
11393
+ const resolved = await Promise.all(targets.map((target) => exists(context, path13.resolve(context.workspaceRoot, target))));
11312
11394
  if (resolved.some((value) => !value))
11313
11395
  return activationFor("root_partial");
11314
11396
  if (!context.prolog)
@@ -11328,10 +11410,10 @@ var init_activation = __esm(() => {
11328
11410
  });
11329
11411
 
11330
11412
  // ../cli/dist/public/operations/prolog-json.js
11331
- import path13 from "node:path";
11413
+ import path14 from "node:path";
11332
11414
  function resolveCoreModulePath(fileName) {
11333
11415
  const genericOverride = getKbPlPathOverride();
11334
- return path13.join(path13.dirname(genericOverride ?? resolveKbPlPath()), fileName);
11416
+ return path14.join(path14.dirname(genericOverride ?? resolveKbPlPath()), fileName);
11335
11417
  }
11336
11418
  async function runOperationJsonQuery(prolog, fileName, goal, errorLabel, signal) {
11337
11419
  const modulePath = escapeAtom(resolveCoreModulePath(fileName).replaceAll("\\", "/"));
@@ -11741,6 +11823,8 @@ async function buildSearchAnswer(prolog, matches, options2 = {}) {
11741
11823
  continue;
11742
11824
  }
11743
11825
  if (type === "fact") {
11826
+ if (isProvenanceStub(match.entity))
11827
+ continue;
11744
11828
  const kind = text(entity.fact_kind);
11745
11829
  if (kind === "observation" || kind === "meta") {
11746
11830
  observations.push(brief(entity));
@@ -12128,8 +12212,8 @@ var init_search_answer = __esm(() => {
12128
12212
  });
12129
12213
 
12130
12214
  // ../cli/dist/utils/branch-store.js
12131
- import { existsSync as existsSync10, readFileSync as readFileSync8, statSync as statSync6 } from "node:fs";
12132
- import * as path14 from "node:path";
12215
+ import { existsSync as existsSync10, readFileSync as readFileSync9, statSync as statSync6 } from "node:fs";
12216
+ import * as path15 from "node:path";
12133
12217
  function inspectBranchStore(workspaceRoot, branch) {
12134
12218
  const storePath = branchStorePath(workspaceRoot, branch);
12135
12219
  if (!existsSync10(storePath)) {
@@ -12170,10 +12254,10 @@ function inspectBranchStore(workspaceRoot, branch) {
12170
12254
  recoveryRequired: true
12171
12255
  };
12172
12256
  }
12173
- const markerPath = path14.join(storePath, "storage.json");
12174
- const rdfPath = path14.join(storePath, "rdf");
12175
- const currentPath = path14.join(storePath, "CURRENT");
12176
- const legacyPath = path14.join(storePath, "kb.rdf");
12257
+ const markerPath = path15.join(storePath, "storage.json");
12258
+ const rdfPath = path15.join(storePath, "rdf");
12259
+ const currentPath = path15.join(storePath, "CURRENT");
12260
+ const legacyPath = path15.join(storePath, "kb.rdf");
12177
12261
  if (existsSync10(markerPath)) {
12178
12262
  if (!existsSync10(rdfPath) || !statSync6(rdfPath).isDirectory()) {
12179
12263
  return {
@@ -12193,7 +12277,7 @@ function inspectBranchStore(workspaceRoot, branch) {
12193
12277
  recoveryRequired: true
12194
12278
  };
12195
12279
  }
12196
- const current = readFileSync8(currentPath, "utf8").trim();
12280
+ const current = readFileSync9(currentPath, "utf8").trim();
12197
12281
  if (!/^generation-[^:\s]+:\d+$/.test(current)) {
12198
12282
  return {
12199
12283
  state: "unreadable",
@@ -12206,7 +12290,7 @@ function inspectBranchStore(workspaceRoot, branch) {
12206
12290
  return { state: "healthy", path: storePath, recoveryRequired: false };
12207
12291
  }
12208
12292
  if (existsSync10(legacyPath)) {
12209
- const legacy = readFileSync8(legacyPath, "utf8");
12293
+ const legacy = readFileSync9(legacyPath, "utf8");
12210
12294
  if (!/<rdf:RDF(?:\s|>)/.test(legacy)) {
12211
12295
  return {
12212
12296
  state: "unreadable",
@@ -12270,8 +12354,8 @@ var init_branch_store = __esm(() => {
12270
12354
  });
12271
12355
 
12272
12356
  // ../cli/dist/utils/config.js
12273
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
12274
- import * as path15 from "node:path";
12357
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "node:fs";
12358
+ import * as path16 from "node:path";
12275
12359
  function loadEntityPaths(_cwd = process.cwd()) {
12276
12360
  return CANONICAL_ENTITY_PATHS;
12277
12361
  }
@@ -12283,15 +12367,15 @@ function pickLegacyPathValue(paths, key) {
12283
12367
  return typeof value === "string" ? value : undefined;
12284
12368
  }
12285
12369
  function legacyConfigExists(cwd) {
12286
- return existsSync11(path15.join(cwd, ".kb", "config.json"));
12370
+ return existsSync11(path16.join(cwd, ".kb", "config.json"));
12287
12371
  }
12288
12372
  function readLegacyKbConfig(cwd) {
12289
- const configPath = path15.join(cwd, ".kb", "config.json");
12373
+ const configPath = path16.join(cwd, ".kb", "config.json");
12290
12374
  if (!existsSync11(configPath))
12291
12375
  return { kind: "none" };
12292
12376
  let raw;
12293
12377
  try {
12294
- raw = readFileSync9(configPath, "utf8");
12378
+ raw = readFileSync10(configPath, "utf8");
12295
12379
  } catch (error) {
12296
12380
  return {
12297
12381
  kind: "malformed",
@@ -12852,8 +12936,8 @@ __export(exports_migration_plan, {
12852
12936
  withoutActionCodes: () => withoutActionCodes
12853
12937
  });
12854
12938
  import { createHash as createHash5 } from "node:crypto";
12855
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
12856
- import * as path16 from "node:path";
12939
+ import { existsSync as existsSync12, readFileSync as readFileSync11 } from "node:fs";
12940
+ import * as path17 from "node:path";
12857
12941
  function isRecord4(value) {
12858
12942
  return value !== null && typeof value === "object" && !Array.isArray(value);
12859
12943
  }
@@ -13192,11 +13276,11 @@ function readMigrationConfigStatus(workspaceRoot) {
13192
13276
  };
13193
13277
  }
13194
13278
  function readLegacySchemaVersion(workspaceRoot) {
13195
- const legacyPath = path16.join(workspaceRoot, ".kb", "config.json");
13279
+ const legacyPath = path17.join(workspaceRoot, ".kb", "config.json");
13196
13280
  if (!existsSync12(legacyPath))
13197
13281
  return null;
13198
13282
  try {
13199
- const parsed = JSON.parse(readFileSync10(legacyPath, "utf8"));
13283
+ const parsed = JSON.parse(readFileSync11(legacyPath, "utf8"));
13200
13284
  return parsed.schemaVersion ?? null;
13201
13285
  } catch {
13202
13286
  return "";
@@ -13385,7 +13469,7 @@ async function readWorkspaceSnapshot(context) {
13385
13469
  }
13386
13470
 
13387
13471
  // ../cli/dist/public/operations/discovery-executors.js
13388
- import path17 from "node:path";
13472
+ import path18 from "node:path";
13389
13473
  function requireProlog(context) {
13390
13474
  if (!context.prolog) {
13391
13475
  throw new Error("Discovery operation requires a Prolog context");
@@ -13635,16 +13719,16 @@ async function executeStatus(_input, context) {
13635
13719
  const bootstrapActivation = await classifyActivation(context, bootstrapSourceFiles);
13636
13720
  const incompleteApplications = [];
13637
13721
  if (context.fs?.glob) {
13638
- const recoveryRoot = path17.join(context.workspaceRoot, ".kb", "recovery");
13722
+ const recoveryRoot = path18.join(context.workspaceRoot, ".kb", "recovery");
13639
13723
  const journals = await context.fs.glob(["bootstrap-*.json"], {
13640
13724
  cwd: recoveryRoot
13641
13725
  });
13642
13726
  for (const journalPath of journals) {
13643
13727
  try {
13644
- const journal = JSON.parse(await context.fs.readFile(path17.resolve(recoveryRoot, journalPath)));
13728
+ const journal = JSON.parse(await context.fs.readFile(path18.resolve(recoveryRoot, journalPath)));
13645
13729
  if (journal.kind === "bootstrap" && ["rejected", "repair_required", "applying"].includes(journal.state))
13646
13730
  incompleteApplications.push({
13647
- journalId: path17.basename(journalPath, ".json"),
13731
+ journalId: path18.basename(journalPath, ".json"),
13648
13732
  state: journal.state,
13649
13733
  appliedActions: (journal.results ?? []).filter((row) => row.outcome === "applied").length,
13650
13734
  failedActions: (journal.results ?? []).filter((row) => row.outcome === "failed"),
@@ -13652,7 +13736,7 @@ async function executeStatus(_input, context) {
13652
13736
  });
13653
13737
  } catch (error) {
13654
13738
  incompleteApplications.push({
13655
- journalId: path17.basename(journalPath, ".json"),
13739
+ journalId: path18.basename(journalPath, ".json"),
13656
13740
  state: "unreadable",
13657
13741
  detail: error instanceof Error ? error.message : String(error)
13658
13742
  });
@@ -14317,12 +14401,12 @@ var init_entity_origin = __esm(() => {
14317
14401
  });
14318
14402
 
14319
14403
  // ../cli/dist/utils/manifest-paths.js
14320
- import * as path18 from "node:path";
14404
+ import * as path19 from "node:path";
14321
14405
  function resolveSymbolsManifestPaths(workspaceRoot) {
14322
- const symbolsPath = path18.join(workspaceRoot, CANONICAL_ENTITY_PATHS.symbols);
14406
+ const symbolsPath = path19.join(workspaceRoot, CANONICAL_ENTITY_PATHS.symbols);
14323
14407
  return {
14324
14408
  symbolsPath,
14325
- coordinatesPath: path18.join(workspaceRoot, DEFAULT_COORDINATES_PATH)
14409
+ coordinatesPath: path19.join(workspaceRoot, DEFAULT_COORDINATES_PATH)
14326
14410
  };
14327
14411
  }
14328
14412
  var DEFAULT_SYMBOLS_PATH, DEFAULT_COORDINATES_PATH;
@@ -14333,22 +14417,22 @@ var init_manifest_paths = __esm(() => {
14333
14417
  });
14334
14418
 
14335
14419
  // ../cli/dist/utils/repo-relative-path.js
14336
- import path19 from "node:path";
14420
+ import path20 from "node:path";
14337
14421
  function normalizeRepoRelativePath(workspaceRoot, candidate) {
14338
14422
  if (candidate.trim() === "")
14339
14423
  return null;
14340
14424
  let slashed = candidate.replaceAll("\\", "/");
14341
14425
  const foreignAbsolute = /^[A-Za-z]:\//.test(slashed) || slashed.startsWith("//");
14342
14426
  if (slashed.startsWith("/") || foreignAbsolute) {
14343
- if (foreignAbsolute && path19.sep === "/")
14427
+ if (foreignAbsolute && path20.sep === "/")
14344
14428
  return null;
14345
- const root = path19.resolve(workspaceRoot);
14346
- const relative = path19.relative(root, path19.resolve(candidate));
14347
- if (relative === "" || path19.isAbsolute(relative))
14429
+ const root = path20.resolve(workspaceRoot);
14430
+ const relative = path20.relative(root, path20.resolve(candidate));
14431
+ if (relative === "" || path20.isAbsolute(relative))
14348
14432
  return null;
14349
14433
  slashed = relative.replaceAll("\\", "/");
14350
14434
  }
14351
- const normalized = path19.posix.normalize(slashed).replace(/\/+$/, "");
14435
+ const normalized = path20.posix.normalize(slashed).replace(/\/+$/, "");
14352
14436
  if (normalized === "" || normalized === "." || normalized === ".." || normalized.startsWith("../")) {
14353
14437
  return null;
14354
14438
  }
@@ -14358,8 +14442,8 @@ var init_repo_relative_path = () => {};
14358
14442
 
14359
14443
  // ../cli/dist/extractors/symbol-coordinates.js
14360
14444
  import { createHash as createHash8 } from "node:crypto";
14361
- import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
14362
- import * as path20 from "node:path";
14445
+ import { existsSync as existsSync13, readFileSync as readFileSync12 } from "node:fs";
14446
+ import * as path21 from "node:path";
14363
14447
  function isRecord7(value) {
14364
14448
  return typeof value === "object" && value !== null && !Array.isArray(value);
14365
14449
  }
@@ -14570,11 +14654,11 @@ function manifestSourceFile(record) {
14570
14654
  return;
14571
14655
  }
14572
14656
  function defaultResolveSourceText(sourceFile) {
14573
- const absolute = path20.isAbsolute(sourceFile) ? sourceFile : path20.resolve(process.cwd(), sourceFile);
14657
+ const absolute = path21.isAbsolute(sourceFile) ? sourceFile : path21.resolve(process.cwd(), sourceFile);
14574
14658
  if (!existsSync13(absolute))
14575
14659
  return null;
14576
14660
  try {
14577
- const content = readFileSync11(absolute, "utf8");
14661
+ const content = readFileSync12(absolute, "utf8");
14578
14662
  return typeof content === "string" ? content : null;
14579
14663
  } catch {
14580
14664
  return null;
@@ -14685,8 +14769,8 @@ var init_symbol_coordinates = __esm(() => {
14685
14769
 
14686
14770
  // ../cli/dist/extractors/manifest.js
14687
14771
  import { createHash as createHash9 } from "node:crypto";
14688
- import { existsSync as existsSync14, readFileSync as readFileSync12, statSync as statSync7 } from "node:fs";
14689
- import * as path21 from "node:path";
14772
+ import { existsSync as existsSync14, readFileSync as readFileSync13, statSync as statSync7 } from "node:fs";
14773
+ import * as path22 from "node:path";
14690
14774
  function inferEntityTypeFromId(id) {
14691
14775
  const upper = id.toUpperCase();
14692
14776
  if (upper.startsWith("REQ-"))
@@ -14859,14 +14943,14 @@ function resolveCoordinatesPath(manifestPath, coordinatesPath) {
14859
14943
  if (coordinatesPath) {
14860
14944
  return coordinatesPath;
14861
14945
  }
14862
- return path21.join(path21.dirname(manifestPath), path21.basename(DEFAULT_COORDINATES_PATH));
14946
+ return path22.join(path22.dirname(manifestPath), path22.basename(DEFAULT_COORDINATES_PATH));
14863
14947
  }
14864
14948
  function readCoordinateArtifactFromFile(coordinatesPath) {
14865
14949
  if (!existsSync14(coordinatesPath)) {
14866
14950
  return null;
14867
14951
  }
14868
14952
  try {
14869
- const parsed = parseCoordinateArtifact(readFileSync12(coordinatesPath, "utf8"));
14953
+ const parsed = parseCoordinateArtifact(readFileSync13(coordinatesPath, "utf8"));
14870
14954
  if (parsed.status === "invalid") {
14871
14955
  throw new ManifestError(parsed.reason, coordinatesPath, "coordinate-artifact");
14872
14956
  }
@@ -14880,17 +14964,17 @@ function readCoordinateArtifactFromFile(coordinatesPath) {
14880
14964
  }
14881
14965
  function sourceTextResolver(manifestPath) {
14882
14966
  const bases = [process.cwd()];
14883
- const grandparent = path21.resolve(path21.dirname(path21.dirname(manifestPath)));
14967
+ const grandparent = path22.resolve(path22.dirname(path22.dirname(manifestPath)));
14884
14968
  if (!bases.includes(grandparent))
14885
14969
  bases.push(grandparent);
14886
14970
  return (sourceFile) => {
14887
14971
  let resolved = null;
14888
14972
  for (const base of bases) {
14889
- const absolute = path21.isAbsolute(sourceFile) ? sourceFile : path21.resolve(base, sourceFile);
14973
+ const absolute = path22.isAbsolute(sourceFile) ? sourceFile : path22.resolve(base, sourceFile);
14890
14974
  if (!existsSync14(absolute))
14891
14975
  continue;
14892
14976
  try {
14893
- const content = readFileSync12(absolute, "utf8");
14977
+ const content = readFileSync13(absolute, "utf8");
14894
14978
  if (typeof content === "string") {
14895
14979
  resolved = content;
14896
14980
  break;
@@ -14901,7 +14985,7 @@ function sourceTextResolver(manifestPath) {
14901
14985
  };
14902
14986
  }
14903
14987
  function readManifestWithCoordinateOverlay(manifestPath, coordinatesPath) {
14904
- const manifestContent = readFileSync12(manifestPath, "utf8");
14988
+ const manifestContent = readFileSync13(manifestPath, "utf8");
14905
14989
  const manifestRecords = extractManifestSymbolRecordsString(manifestContent, manifestPath);
14906
14990
  const coordinateArtifact = readCoordinateArtifactFromFile(resolveCoordinatesPath(manifestPath, coordinatesPath));
14907
14991
  return mergeCoordinatesWithManifest(manifestRecords, coordinateArtifact, {
@@ -14923,7 +15007,7 @@ function scopeSourceFiles(manifestPath) {
14923
15007
  return hit.sourceFiles;
14924
15008
  const sourceFiles = new Map;
14925
15009
  if (stamp !== "missing") {
14926
- const records = extractManifestSymbolRecordsString(readFileSync12(manifestPath, "utf8"), manifestPath);
15010
+ const records = extractManifestSymbolRecordsString(readFileSync13(manifestPath, "utf8"), manifestPath);
14927
15011
  for (const record of records) {
14928
15012
  const sourceFile = typeof record.sourceFile === "string" && record.sourceFile !== "" ? record.sourceFile : typeof record.source === "string" && record.source !== "" ? record.source : undefined;
14929
15013
  if (typeof record.id === "string" && sourceFile !== undefined) {
@@ -14941,7 +15025,7 @@ function scopeFileHash(absolutePath) {
14941
15025
  const hit = scopeFileHashCache.get(absolutePath);
14942
15026
  if (hit && hit.stamp === stamp)
14943
15027
  return hit.hash;
14944
- const hash = createHash9("sha256").update(readFileSync12(absolutePath)).digest("hex");
15028
+ const hash = createHash9("sha256").update(readFileSync13(absolutePath)).digest("hex");
14945
15029
  scopeFileHashCache.set(absolutePath, { stamp, hash });
14946
15030
  return hash;
14947
15031
  }
@@ -14950,7 +15034,7 @@ function resolveBoundSymbolScope(manifestPath, symbolIds) {
14950
15034
  if (wanted.length === 0)
14951
15035
  return [];
14952
15036
  const sourceFiles = scopeSourceFiles(manifestPath);
14953
- const workspaceRoot = path21.dirname(path21.dirname(path21.resolve(manifestPath)));
15037
+ const workspaceRoot = path22.dirname(path22.dirname(path22.resolve(manifestPath)));
14954
15038
  const scope = [];
14955
15039
  for (const symbolId of wanted) {
14956
15040
  const sourceFile = sourceFiles.get(symbolId);
@@ -14959,7 +15043,7 @@ function resolveBoundSymbolScope(manifestPath, symbolIds) {
14959
15043
  const relative = normalizeRepoRelativePath(workspaceRoot, sourceFile);
14960
15044
  scope.push({
14961
15045
  symbolId,
14962
- sourceHash: relative === null ? OUTSIDE_WORKSPACE_SCOPE_HASH : scopeFileHash(path21.join(workspaceRoot, relative))
15046
+ sourceHash: relative === null ? OUTSIDE_WORKSPACE_SCOPE_HASH : scopeFileHash(path22.join(workspaceRoot, relative))
14963
15047
  });
14964
15048
  }
14965
15049
  scope.sort((left, right) => left.symbolId.localeCompare(right.symbolId));
@@ -22477,7 +22561,7 @@ var init_proof_receipt = __esm(() => {
22477
22561
 
22478
22562
  // ../cli/dist/extractors/markdown.js
22479
22563
  import { createHash as createHash11 } from "node:crypto";
22480
- import { readFileSync as readFileSync13 } from "node:fs";
22564
+ import { readFileSync as readFileSync14 } from "node:fs";
22481
22565
  function validateExtractedEntity() {
22482
22566
  extractedEntityValidator ??= ajv.compile(entity_schema_default);
22483
22567
  return extractedEntityValidator;
@@ -22956,7 +23040,7 @@ function extractFromMarkdownString(content, filePath) {
22956
23040
  function extractFromMarkdown(filePath) {
22957
23041
  let content;
22958
23042
  try {
22959
- content = readFileSync13(filePath, "utf8");
23043
+ content = readFileSync14(filePath, "utf8");
22960
23044
  } catch (error) {
22961
23045
  throw new FrontmatterError(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`, filePath, { classification: "File Read Error" });
22962
23046
  }
@@ -23461,7 +23545,7 @@ var init_rule_registry = __esm(() => {
23461
23545
 
23462
23546
  // ../cli/dist/utils/strict-modeling.js
23463
23547
  import { createHash as createHash12 } from "node:crypto";
23464
- import * as path22 from "node:path";
23548
+ import * as path23 from "node:path";
23465
23549
  function normalizeSubjectKey2(value) {
23466
23550
  const normalized = value.trim().toLowerCase().replace(/[\\/]+/g, ".").replace(/[^a-z0-9.]+/g, "_").replace(/_+/g, "_").replace(/\.+/g, ".").replace(/(^[._]+|[._]+$)/g, "");
23467
23551
  if (!normalized) {
@@ -23791,7 +23875,7 @@ function resolveEntitySourcePaths() {
23791
23875
  };
23792
23876
  }
23793
23877
  function normalizeEntityDirectory(directory) {
23794
- return directory.split(path22.sep).join("/").replace(/\/+$/g, "");
23878
+ return directory.split(path23.sep).join("/").replace(/\/+$/g, "");
23795
23879
  }
23796
23880
  function buildEntitySourcePath(directory, entityId) {
23797
23881
  return `${directory}/${entityId}.md`;
@@ -24903,9 +24987,9 @@ function cleanPredicate(value) {
24903
24987
  }
24904
24988
 
24905
24989
  // ../cli/dist/operations/modeling/requirement-heuristics.js
24906
- import path23 from "node:path";
24990
+ import path24 from "node:path";
24907
24991
  function fallbackSubjectFromSource(source) {
24908
- const basename = path23.basename(source, path23.extname(source)).replace(/[-_]+/g, " ").trim();
24992
+ const basename = path24.basename(source, path24.extname(source)).replace(/[-_]+/g, " ").trim();
24909
24993
  return basename || "Requirement";
24910
24994
  }
24911
24995
  function buildFallbackClaim(statement, source, confidence, provenance) {
@@ -26205,7 +26289,7 @@ var init_project_config = __esm(() => {
26205
26289
 
26206
26290
  // ../cli/dist/plugins/resolve-package.js
26207
26291
  import * as fs3 from "node:fs";
26208
- import { createRequire as createRequire3 } from "node:module";
26292
+ import { createRequire as createRequire4 } from "node:module";
26209
26293
  import { dirname as dirname6, isAbsolute as isAbsolute5, join as join12, relative as relative2, resolve as resolve6 } from "node:path";
26210
26294
  import { pathToFileURL } from "node:url";
26211
26295
  function readJson(path) {
@@ -26361,7 +26445,7 @@ function resolveProjectLocalPackage(workspaceRoot, packageName) {
26361
26445
  if (!hasDeclaredProjectDependency(root, packageName, manifest)) {
26362
26446
  throw new PluginResolutionError("UNDECLARED_DEPENDENCY", `Plugin package '${packageName}' must be listed in dependencies, devDependencies, or optionalDependencies of ${join12(root, "package.json")}`);
26363
26447
  }
26364
- const consumerRequire = createRequire3(join12(root, "package.json"));
26448
+ const consumerRequire = createRequire4(join12(root, "package.json"));
26365
26449
  let packageInfo = null;
26366
26450
  try {
26367
26451
  packageInfo = packageJsonForResolvedFile(consumerRequire.resolve(`${packageName}/package.json`), packageName);
@@ -26754,10 +26838,10 @@ var init_registry = __esm(() => {
26754
26838
  });
26755
26839
 
26756
26840
  // ../cli/dist/operations/modeling/vocabulary-alignment.js
26757
- import path24 from "node:path";
26841
+ import path25 from "node:path";
26758
26842
  import { rankSubjectCandidates } from "kibi-plugin-builtin";
26759
26843
  function semanticQualityModulePath() {
26760
- return path24.join(path24.dirname(resolveKbPlPath()), "semantic_quality.pl");
26844
+ return path25.join(path25.dirname(resolveKbPlPath()), "semantic_quality.pl");
26761
26845
  }
26762
26846
  function parseJsonBinding(raw) {
26763
26847
  if (raw === undefined || raw === "")
@@ -27390,6 +27474,12 @@ function provenanceBody(title, provenance) {
27390
27474
  ${provenance}
27391
27475
  `;
27392
27476
  }
27477
+ function provenanceStubBody(title, provenance) {
27478
+ return `${title.trim()}
27479
+
27480
+ ${provenance} This entry is a provenance stub: the provider found the source but no claim about it, so it is tagged bootstrap:provenance-stub, ranked after every other search match and not counted as knowledge by gap or coverage reports.
27481
+ `;
27482
+ }
27393
27483
  function provenanceRequirementBody(statement, provenance, reference) {
27394
27484
  return renderRequirementBody({
27395
27485
  statement,
@@ -27730,7 +27820,7 @@ var init_requirement_claims = __esm(() => {
27730
27820
  });
27731
27821
 
27732
27822
  // ../cli/dist/operations/bootstrap/markdown-candidates.js
27733
- import path25 from "node:path";
27823
+ import path26 from "node:path";
27734
27824
  function headingSignals(heading, sourcePath, textRef, minConfidence) {
27735
27825
  const result = [];
27736
27826
  for (const [kind, pattern, confidence] of [
@@ -27756,7 +27846,7 @@ function genericHeadingCandidate(item, heading, line, existingIds, minConfidence
27756
27846
  const confidence = type === "adr" ? 0.9 : type === "fact" ? 0.8 : 0;
27757
27847
  if (!type || confidence < minConfidence)
27758
27848
  return null;
27759
- const id = `${type === "adr" ? "ADR" : "FACT"}-GEN-${slug(heading, 60) || slug(path25.basename(relativePath))}`.toUpperCase();
27849
+ const id = `${type === "adr" ? "ADR" : "FACT"}-GEN-${slug(heading, 60) || slug(path26.basename(relativePath))}`.toUpperCase();
27760
27850
  if (existingIds.has(id))
27761
27851
  return null;
27762
27852
  const entity = {
@@ -27922,7 +28012,7 @@ var init_markdown_candidates = __esm(() => {
27922
28012
  });
27923
28013
 
27924
28014
  // ../cli/dist/operations/bootstrap/candidates.js
27925
- import path26 from "node:path";
28015
+ import path27 from "node:path";
27926
28016
  function typedCandidates(item, existingIds) {
27927
28017
  const results = item.kind === "symbol_manifest" ? extractFromManifestString(item.content ?? "", item.relativePath ?? item.label) : [
27928
28018
  extractFromMarkdownString(item.content ?? "", item.relativePath ?? item.label)
@@ -27954,6 +28044,19 @@ function typedCandidates(item, existingIds) {
27954
28044
  ];
27955
28045
  });
27956
28046
  }
28047
+ function providerClaim(item) {
28048
+ const claim = typeof item.data.claim === "string" ? item.data.claim.trim() : "";
28049
+ return claim.length > 0 ? claim : undefined;
28050
+ }
28051
+ function isProvenanceStubCandidate(candidate) {
28052
+ return candidate.applyPlan.some((payload) => {
28053
+ const properties = payload.properties;
28054
+ if (properties === null || typeof properties !== "object")
28055
+ return false;
28056
+ const tags = properties.tags;
28057
+ return Array.isArray(tags) && tags.includes(PROVENANCE_STUB_TAG);
28058
+ });
28059
+ }
27957
28060
  function providerCandidate(item, existingIds, minConfidence) {
27958
28061
  if (!new Set([
27959
28062
  "repo_metadata",
@@ -27967,18 +28070,22 @@ function providerCandidate(item, existingIds, minConfidence) {
27967
28070
  const id = `FACT-GEN-${slug(`${item.kind}-${relativePath}`, 64) || "evidence"}`.toUpperCase();
27968
28071
  if (confidence < minConfidence || existingIds.has(id))
27969
28072
  return [];
27970
- const symbolTitle = item.kind === "source_symbols" && /\.(?:[cm]?[jt]sx?)$/i.test(relativePath) ? `Source symbols: ${path26.basename(relativePath, path26.extname(relativePath))}` : undefined;
28073
+ const symbolTitle = item.kind === "source_symbols" && /\.(?:[cm]?[jt]sx?)$/i.test(relativePath) ? `Source symbols: ${path27.basename(relativePath, path27.extname(relativePath))}` : undefined;
27971
28074
  const title = (typeof item.data.title === "string" ? item.data.title : undefined) ?? symbolTitle ?? `Bootstrap evidence from ${relativePath}`;
28075
+ const claim = providerClaim(item);
28076
+ const stub = claim === undefined;
27972
28077
  const entity = {
27973
28078
  type: "fact",
27974
28079
  id,
27975
28080
  title,
27976
28081
  status: "active",
27977
- fact_kind: typeof item.data.factKind === "string" ? item.data.factKind : item.kind === "repo_metadata" ? "meta" : "observation",
28082
+ fact_kind: stub ? "meta" : typeof item.data.factKind === "string" ? item.data.factKind : item.kind === "repo_metadata" ? "meta" : "observation",
27978
28083
  source: `bootstrap:${item.provider}:${relativePath}`,
27979
- text_ref: relativePath
28084
+ text_ref: relativePath,
28085
+ ...stub ? { tags: [PROVENANCE_STUB_TAG] } : {}
27980
28086
  };
27981
28087
  const evidence = Array.isArray(item.data.evidence) ? item.data.evidence.filter((value) => typeof value === "string") : [`provider:${item.provider}`, `${item.provider}:${relativePath}`];
28088
+ const provenance = `${bootstrapProvenance(item.provider, relativePath, confidence)}${evidence.length > 0 ? ` Evidence: ${evidence.join("; ")}.` : ""}`;
27982
28089
  return [
27983
28090
  {
27984
28091
  candidateId: `prov:${item.kind}:${slug(relativePath, 96) || "evidence"}`,
@@ -27991,7 +28098,9 @@ function providerCandidate(item, existingIds, minConfidence) {
27991
28098
  evidence,
27992
28099
  relationships: [],
27993
28100
  applyPlan: [
27994
- withDocumentBody(upsert(entity), provenanceBody(title, `${bootstrapProvenance(item.provider, relativePath, confidence)}${evidence.length > 0 ? ` Evidence: ${evidence.join("; ")}.` : ""}`))
28101
+ withDocumentBody(upsert(entity), stub ? provenanceStubBody(title, provenance) : provenanceBody(`${title.trim()}
28102
+
28103
+ ${claim}`, provenance))
27995
28104
  ]
27996
28105
  }
27997
28106
  ];
@@ -28084,7 +28193,7 @@ var init_cli_errors = __esm(() => {
28084
28193
  });
28085
28194
 
28086
28195
  // ../cli/dist/operations/bootstrap/discovery-evidence.js
28087
- import path27 from "node:path";
28196
+ import path28 from "node:path";
28088
28197
  function isScanFilesystem(value) {
28089
28198
  return Boolean(value && "glob" in value && typeof value.glob === "function");
28090
28199
  }
@@ -28114,7 +28223,7 @@ function classifyFile(relativePath, content) {
28114
28223
  function evidenceData(provider, relativePath, content) {
28115
28224
  if (provider === "repo_metadata") {
28116
28225
  const languages = new Set;
28117
- if (/^package\.json$/i.test(path27.basename(relativePath))) {
28226
+ if (/^package\.json$/i.test(path28.basename(relativePath))) {
28118
28227
  try {
28119
28228
  const parsed = JSON.parse(content);
28120
28229
  const text = JSON.stringify(parsed);
@@ -28131,7 +28240,7 @@ function evidenceData(provider, relativePath, content) {
28131
28240
  if (/pyproject\.toml$/i.test(relativePath))
28132
28241
  languages.add("python");
28133
28242
  return {
28134
- title: `Repository metadata: ${path27.basename(relativePath)}`,
28243
+ title: `Repository metadata: ${path28.basename(relativePath)}`,
28135
28244
  factKind: "meta",
28136
28245
  confidence: relativePath.includes("tsconfig") ? 0.9 : 0.86,
28137
28246
  evidence: [`repo_metadata:${relativePath}`],
@@ -28152,13 +28261,16 @@ function evidenceData(provider, relativePath, content) {
28152
28261
  `test_topology:${relativePath}`,
28153
28262
  ...frameworks.map((item) => `framework:${item}`)
28154
28263
  ],
28155
- frameworks
28264
+ frameworks,
28265
+ ...frameworks.length > 0 ? {
28266
+ claim: `${relativePath} is a test file that runs under ${frameworks.join(", ")}.`
28267
+ } : {}
28156
28268
  };
28157
28269
  }
28158
28270
  if (provider === "source_symbols") {
28159
28271
  const symbolCount = Array.from(content.matchAll(/\b(?:export\s+)?(?:function|class|const|let|var|interface|type)\s+([A-Za-z_$][\w$]*)/g)).length;
28160
28272
  return {
28161
- title: `Source module: ${path27.basename(relativePath, path27.extname(relativePath))}`,
28273
+ title: `Source module: ${path28.basename(relativePath, path28.extname(relativePath))}`,
28162
28274
  factKind: "observation",
28163
28275
  confidence: 0.82,
28164
28276
  evidence: [`source_symbols:${relativePath}`],
@@ -28177,7 +28289,7 @@ function layoutEvidence(workspaceRoot, files, ignored) {
28177
28289
  kind: "repo_layout",
28178
28290
  label: root,
28179
28291
  relativePath: root,
28180
- absolutePath: path27.join(workspaceRoot, root),
28292
+ absolutePath: path28.join(workspaceRoot, root),
28181
28293
  data: {
28182
28294
  title: `Repository layout: ${root} directory`,
28183
28295
  factKind: "observation",
@@ -28206,14 +28318,14 @@ async function scanEvidence(context) {
28206
28318
  for (const relativePath of files) {
28207
28319
  if (ignored.has(relativePath))
28208
28320
  continue;
28209
- const absolutePath = path27.resolve(context.workspaceRoot, relativePath);
28321
+ const absolutePath = path28.resolve(context.workspaceRoot, relativePath);
28210
28322
  try {
28211
28323
  const content = await fs.readFile(absolutePath);
28212
28324
  const classification = classifyFile(relativePath, content);
28213
28325
  if (!classification)
28214
28326
  continue;
28215
28327
  const [provider, kind] = classification;
28216
- if (provider === "repo_metadata" && path27.basename(relativePath) === "package.json") {
28328
+ if (provider === "repo_metadata" && path28.basename(relativePath) === "package.json") {
28217
28329
  try {
28218
28330
  JSON.parse(content);
28219
28331
  } catch {
@@ -28315,7 +28427,7 @@ var init_types = __esm(() => {
28315
28427
  });
28316
28428
 
28317
28429
  // ../cli/dist/operations/bootstrap/discovery.js
28318
- import path28 from "node:path";
28430
+ import path29 from "node:path";
28319
28431
  async function migrationWarning(context) {
28320
28432
  try {
28321
28433
  const status = readKbManifestStatus(context.workspaceRoot);
@@ -28329,7 +28441,7 @@ async function migrationWarning(context) {
28329
28441
  function languages(evidence) {
28330
28442
  return [
28331
28443
  ...new Set(evidence.flatMap((item) => {
28332
- const extension = path28.extname(item.label).slice(1);
28444
+ const extension = path29.extname(item.label).slice(1);
28333
28445
  const fromExtension = item.kind === "source_symbols" ? [LANGUAGE_NAMES[extension] ?? extension] : [];
28334
28446
  const fromMetadata = Array.isArray(item.data.languages) ? item.data.languages.filter((value) => typeof value === "string") : [];
28335
28447
  return [...fromExtension, ...fromMetadata];
@@ -28697,12 +28809,12 @@ var init_intent_claims = __esm(() => {
28697
28809
  });
28698
28810
 
28699
28811
  // ../cli/dist/operations/bootstrap/guidance-actions.js
28700
- import path29 from "node:path";
28812
+ import path30 from "node:path";
28701
28813
  function relative3(root, target) {
28702
- if (!path29.isAbsolute(target))
28814
+ if (!path30.isAbsolute(target))
28703
28815
  return target;
28704
- const value = path29.relative(root, target);
28705
- return value.startsWith("..") || path29.isAbsolute(value) ? target.split(path29.sep).join("/") : value.split(path29.sep).join("/");
28816
+ const value = path30.relative(root, target);
28817
+ return value.startsWith("..") || path30.isAbsolute(value) ? target.split(path30.sep).join("/") : value.split(path30.sep).join("/");
28706
28818
  }
28707
28819
  function summary(values, limit = 3) {
28708
28820
  if (values.length === 0)
@@ -28770,12 +28882,12 @@ function buildActions(root, activation, declared, candidates, signals) {
28770
28882
  var init_guidance_actions = () => {};
28771
28883
 
28772
28884
  // ../cli/dist/operations/bootstrap/guidance.js
28773
- import path30 from "node:path";
28885
+ import path31 from "node:path";
28774
28886
  function relative4(root, target) {
28775
- if (!path30.isAbsolute(target))
28887
+ if (!path31.isAbsolute(target))
28776
28888
  return target;
28777
- const value = path30.relative(root, target);
28778
- return value.startsWith("..") || path30.isAbsolute(value) ? target.split(path30.sep).join("/") : value.split(path30.sep).join("/");
28889
+ const value = path31.relative(root, target);
28890
+ return value.startsWith("..") || path31.isAbsolute(value) ? target.split(path31.sep).join("/") : value.split(path31.sep).join("/");
28779
28891
  }
28780
28892
  function summary2(values, limit = 3) {
28781
28893
  if (values.length === 0)
@@ -29030,7 +29142,16 @@ function presentBootstrap(input) {
29030
29142
  const suppression = suppressionCounts(input.suppressedCandidates);
29031
29143
  const suppressedTotal = suppression.reduce((sum, row) => sum + row.count, 0);
29032
29144
  const suppressionSummary = suppressedTotal > 0 ? ` Suppressed ${suppressedTotal} candidate(s) by reason: ${suppression.map((row) => `${row.reason} ${row.count}`).join(", ")}.` : "";
29033
- const limitSummary = suppression.some((row) => row.reason === "over_limit") ? " Discovered candidates over maxCandidates are over_limit; raise the limit or narrow entityTypes. Declared intent claims do not count against it." : "";
29145
+ const provenanceStubs = input.candidates.filter(isProvenanceStubCandidate);
29146
+ const overLimitRows = input.suppressedCandidates.filter((row) => row.reason === "over_limit");
29147
+ const overLimitStubs = overLimitRows.filter((row) => row.provenanceStub === true).length;
29148
+ const limitSummary = overLimitRows.length > 0 ? ` Discovered candidates over maxCandidates are over_limit (${overLimitStubs} of ${overLimitRows.length} are provenance stubs that state no claim); raise the limit only for the ${overLimitRows.length - overLimitStubs} with a claim, or narrow entityTypes. Declared intent claims do not count against it.` : "";
29149
+ const discoverySummary = {
29150
+ ...input.discoverySummary,
29151
+ candidatesWithClaims: input.candidates.length - provenanceStubs.length,
29152
+ provenanceStubs: provenanceStubs.length,
29153
+ suppressedProvenanceStubs: overLimitStubs
29154
+ };
29034
29155
  const tldr = (confidenceLevel === "low" && !input.activation.applyBlocked ? `Low-confidence bootstrap (${String(guidance.confidence.score)}): review diagnostics before proceeding. ${baseTldr}` : baseTldr) + suppressionSummary + limitSummary;
29035
29156
  const rawActions = input.candidates.flatMap((candidate) => candidate.applyPlan.map((payload) => ({ candidate, payload })));
29036
29157
  const actionIds = new Map;
@@ -29093,7 +29214,7 @@ function presentBootstrap(input) {
29093
29214
  declaredContext,
29094
29215
  contextQuestions: contextQuestions.slice(0, 4),
29095
29216
  confidence: guidance.confidence,
29096
- discoverySummary: input.discoverySummary,
29217
+ discoverySummary,
29097
29218
  candidates: input.candidates,
29098
29219
  actions,
29099
29220
  sourceWrites: [],
@@ -29124,7 +29245,7 @@ function presentBootstrap(input) {
29124
29245
  promptBlock: guidance.promptBlock,
29125
29246
  recommendedActions: guidance.actions,
29126
29247
  declaredContext,
29127
- discoverySummary: input.discoverySummary,
29248
+ discoverySummary,
29128
29249
  candidates: input.candidates,
29129
29250
  actions,
29130
29251
  sourceWrites: [],
@@ -29139,6 +29260,7 @@ function presentBootstrap(input) {
29139
29260
  };
29140
29261
  }
29141
29262
  var init_presentation = __esm(() => {
29263
+ init_candidates();
29142
29264
  init_guidance();
29143
29265
  init_types();
29144
29266
  });
@@ -31262,7 +31384,7 @@ var init_validation2 = __esm(() => {
31262
31384
 
31263
31385
  // ../cli/dist/operations/bootstrap/generate.js
31264
31386
  import { createHash as createHash18 } from "node:crypto";
31265
- import path31 from "node:path";
31387
+ import path32 from "node:path";
31266
31388
  function filterSourceOnlySignals(signals, entityTypes) {
31267
31389
  return entityTypes && entityTypes.length > 0 ? signals.filter((signal) => entityTypes.includes(signal.kind)) : signals;
31268
31390
  }
@@ -31289,7 +31411,7 @@ function selectBootstrapCandidates(input, existingIds, entityTypes, maximum) {
31289
31411
  return 0;
31290
31412
  if (candidate.entityType === "req" && ["typed_markdown", "generic_markdown"].includes(candidate.sourceKind))
31291
31413
  return 1;
31292
- return 2;
31414
+ return isProvenanceStubCandidate(candidate) ? 3 : 2;
31293
31415
  };
31294
31416
  const suppressed = [];
31295
31417
  const sourceOnlySignals = [];
@@ -31349,11 +31471,21 @@ function selectBootstrapCandidates(input, existingIds, entityTypes, maximum) {
31349
31471
  const candidates = [];
31350
31472
  let discoveredCount = 0;
31351
31473
  let overLimit = 0;
31474
+ let overLimitStubs = 0;
31352
31475
  for (const candidate of selected.values()) {
31353
31476
  const discovered = candidate.sourceKind !== "intent_claim";
31354
31477
  if (discovered && discoveredCount >= maximum) {
31355
- suppress(candidate, "over_limit");
31478
+ const stub = isProvenanceStubCandidate(candidate);
31479
+ suppressed.push({
31480
+ candidateId: candidate.candidateId,
31481
+ reason: "over_limit",
31482
+ sourcePath: candidate.sourcePath,
31483
+ entityType: candidate.entityType,
31484
+ provenanceStub: stub
31485
+ });
31356
31486
  overLimit += 1;
31487
+ if (stub)
31488
+ overLimitStubs += 1;
31357
31489
  continue;
31358
31490
  }
31359
31491
  const conflict = candidate.applyPlan.find((payload) => {
@@ -31383,7 +31515,7 @@ function selectBootstrapCandidates(input, existingIds, entityTypes, maximum) {
31383
31515
  candidates.push(candidate);
31384
31516
  }
31385
31517
  if (overLimit > 0)
31386
- diagnostics.push(`${overLimit} discovered candidate(s) exceeded maxCandidates ${maximum} and are suppressed as over_limit; declared intent claims do not count against it.`);
31518
+ diagnostics.push(`${overLimit} discovered candidate(s) exceeded maxCandidates ${maximum} and are suppressed as over_limit, ${overLimitStubs} of them provenance stubs that state no claim (raise the limit only for the ${overLimit - overLimitStubs} with a claim); declared intent claims do not count against it.`);
31387
31519
  return {
31388
31520
  candidates,
31389
31521
  suppressed,
@@ -31437,7 +31569,7 @@ async function expectedSnapshots(context, evidencePaths) {
31437
31569
  } else {
31438
31570
  for (const relative of new Set(evidencePaths)) {
31439
31571
  try {
31440
- const resolved = path31.resolve(context.workspaceRoot, relative);
31572
+ const resolved = path32.resolve(context.workspaceRoot, relative);
31441
31573
  if (!(await context.fs.stat(resolved)).isFile())
31442
31574
  continue;
31443
31575
  sourceHashes[relative] = sha2562(await context.fs.readFile(resolved));
@@ -31761,7 +31893,7 @@ var init_bootstrap = __esm(() => {
31761
31893
  });
31762
31894
 
31763
31895
  // ../cli/dist/commands/aggregated-checks.js
31764
- import path32 from "node:path";
31896
+ import path33 from "node:path";
31765
31897
  function ontologyQualitySetting(raw) {
31766
31898
  if (raw === undefined || raw.trim() === "")
31767
31899
  return "default";
@@ -31778,7 +31910,7 @@ function ontologyQualityOverridesGoal(env = process.env) {
31778
31910
  }
31779
31911
  async function runAggregatedChecks(prolog, rulesAllowlist) {
31780
31912
  const violations = [];
31781
- const checksPlPath = path32.join(path32.dirname(resolveKbPlPath()), "checks.pl");
31913
+ const checksPlPath = path33.join(path33.dirname(resolveKbPlPath()), "checks.pl");
31782
31914
  const checksPlPathEscaped = escapeAtom(checksPlPath);
31783
31915
  const fallbackQuery = `( predicate_property(checks:check_all_json_with_options(_, _), _)
31784
31916
  -> call(checks:check_all_json_with_options(JsonString, false))
@@ -32497,7 +32629,7 @@ var init_source_classification = __esm(() => {
32497
32629
 
32498
32630
  // ../cli/dist/plugins/source-analysis-service.js
32499
32631
  import { createHash as createHash20 } from "node:crypto";
32500
- import * as path33 from "node:path";
32632
+ import * as path34 from "node:path";
32501
32633
  function detectSourceLanguage(filePath) {
32502
32634
  return extensionLanguage(filePath);
32503
32635
  }
@@ -32544,9 +32676,9 @@ function providerBudgetMs(hostTimeoutMs) {
32544
32676
  return Math.max(1, hostTimeoutMs - grace);
32545
32677
  }
32546
32678
  function inferModuleTitle(filePath) {
32547
- const extension = path33.extname(filePath);
32548
- const basename = path33.basename(filePath, extension);
32549
- return basename.length > 0 ? basename : path33.basename(filePath);
32679
+ const extension = path34.extname(filePath);
32680
+ const basename = path34.basename(filePath, extension);
32681
+ return basename.length > 0 ? basename : path34.basename(filePath);
32550
32682
  }
32551
32683
  function createConservativeFallbackAnalysis(filePath, fallbackReason) {
32552
32684
  const language = detectSourceLanguage(filePath);
@@ -32787,8 +32919,8 @@ var init_source_analysis_service = __esm(() => {
32787
32919
 
32788
32920
  // ../cli/dist/plugins/maintenance-source-analysis.js
32789
32921
  import { createHash as createHash21 } from "node:crypto";
32790
- import { readFileSync as readFileSync16, realpathSync as realpathSync5 } from "node:fs";
32791
- import { createRequire as createRequire4 } from "node:module";
32922
+ import { readFileSync as readFileSync17, realpathSync as realpathSync5 } from "node:fs";
32923
+ import { createRequire as createRequire5 } from "node:module";
32792
32924
  import { dirname as dirname7, isAbsolute as isAbsolute6, join as join13, relative as relative5, resolve as resolve7 } from "node:path";
32793
32925
  function digestFile(root, file) {
32794
32926
  const candidate = resolve7(root, file);
@@ -32799,7 +32931,7 @@ function digestFile(root, file) {
32799
32931
  const actualRel = relative5(realpathSync5(root), actual);
32800
32932
  if (actualRel.startsWith("..") || isAbsolute6(actualRel))
32801
32933
  throw new Error(`Approved asset escapes its package: ${file}`);
32802
- return createHash21("sha256").update(readFileSync16(actual)).digest("hex");
32934
+ return createHash21("sha256").update(readFileSync17(actual)).digest("hex");
32803
32935
  }
32804
32936
  function verifyFiles(root, files) {
32805
32937
  if (Object.keys(files).length === 0)
@@ -32810,11 +32942,11 @@ function verifyFiles(root, files) {
32810
32942
  }
32811
32943
  }
32812
32944
  function dependencyRoot(importer, packageName) {
32813
- const require2 = createRequire4(join13(importer, "package.json"));
32945
+ const require2 = createRequire5(join13(importer, "package.json"));
32814
32946
  let current = dirname7(require2.resolve(packageName));
32815
32947
  for (;; ) {
32816
32948
  try {
32817
- const json = JSON.parse(readFileSync16(join13(current, "package.json"), "utf8"));
32949
+ const json = JSON.parse(readFileSync17(join13(current, "package.json"), "utf8"));
32818
32950
  if (json.name === packageName)
32819
32951
  return current;
32820
32952
  } catch {}
@@ -32825,7 +32957,7 @@ function dependencyRoot(importer, packageName) {
32825
32957
  }
32826
32958
  }
32827
32959
  function builtinRuntimeIdentity() {
32828
- const manifest = createRequire4(import.meta.url)("kibi-plugin-builtin/package.json");
32960
+ const manifest = createRequire5(import.meta.url)("kibi-plugin-builtin/package.json");
32829
32961
  if (manifest.name !== "kibi-plugin-builtin" || typeof manifest.version !== "string")
32830
32962
  throw new Error("Builtin source analyzer identity is invalid");
32831
32963
  return { name: manifest.name, version: manifest.version };
@@ -32858,13 +32990,13 @@ function fingerprintMaintenanceSourceSet(workspaceRoot, projectConfig) {
32858
32990
  }
32859
32991
  function verifyApprovedSourceAnalyzer(root, approval) {
32860
32992
  verifyFiles(root, approval.files);
32861
- const manifest = JSON.parse(readFileSync16(join13(root, "package.json"), "utf8"));
32993
+ const manifest = JSON.parse(readFileSync17(join13(root, "package.json"), "utf8"));
32862
32994
  if (manifest.name !== approval.packageName || manifest.version !== approval.version)
32863
32995
  throw new Error("Source analyzer package identity does not match host approval");
32864
32996
  for (const dependency of approval.dependencies) {
32865
32997
  const depRoot = dependencyRoot(root, dependency.packageName);
32866
32998
  verifyFiles(depRoot, dependency.files);
32867
- const metadata = JSON.parse(readFileSync16(join13(depRoot, "package.json"), "utf8"));
32999
+ const metadata = JSON.parse(readFileSync17(join13(depRoot, "package.json"), "utf8"));
32868
33000
  if (metadata.version !== dependency.version)
32869
33001
  throw new Error(`Unapproved source runtime version: ${dependency.packageName}`);
32870
33002
  }
@@ -40403,9 +40535,9 @@ var init_dist2 = __esm(() => {
40403
40535
  // ../cli/dist/relationships/shards.js
40404
40536
  import * as crypto from "node:crypto";
40405
40537
  import * as fs4 from "node:fs";
40406
- import * as path34 from "node:path";
40538
+ import * as path35 from "node:path";
40407
40539
  function getRelationshipsDir(kbRoot) {
40408
- return path34.join(kbRoot, "relationships");
40540
+ return path35.join(kbRoot, "relationships");
40409
40541
  }
40410
40542
  function shardForFromId(fromId) {
40411
40543
  const hash = crypto.createHash("sha256").update(fromId).digest("hex");
@@ -40413,7 +40545,7 @@ function shardForFromId(fromId) {
40413
40545
  }
40414
40546
  function computeShardPath(kbRoot, entityId) {
40415
40547
  const shardName = shardForFromId(entityId);
40416
- return path34.join(getRelationshipsDir(kbRoot), `${shardName}.yaml`);
40548
+ return path35.join(getRelationshipsDir(kbRoot), `${shardName}.yaml`);
40417
40549
  }
40418
40550
  function readShard(shardPath) {
40419
40551
  if (!fs4.existsSync(shardPath)) {
@@ -40585,7 +40717,7 @@ function appendRelationship(kbRoot, relationship) {
40585
40717
  const next = renderShardWithRelationship(shardPath, existing, relationship);
40586
40718
  if (next !== null) {
40587
40719
  if (existing === null) {
40588
- fs4.mkdirSync(path34.dirname(shardPath), { recursive: true });
40720
+ fs4.mkdirSync(path35.dirname(shardPath), { recursive: true });
40589
40721
  }
40590
40722
  atomicWriteText(shardPath, next);
40591
40723
  }
@@ -40618,7 +40750,7 @@ function listShards(kbRoot) {
40618
40750
  if (!fs4.existsSync(relationshipsDir)) {
40619
40751
  return [];
40620
40752
  }
40621
- return fs4.readdirSync(relationshipsDir).filter((f) => f.endsWith(".yaml")).map((f) => path34.join(relationshipsDir, f));
40753
+ return fs4.readdirSync(relationshipsDir).filter((f) => f.endsWith(".yaml")).map((f) => path35.join(relationshipsDir, f));
40622
40754
  }
40623
40755
  function readAllShards(kbRoot) {
40624
40756
  const shards = listShards(kbRoot);
@@ -40639,7 +40771,7 @@ var init_shards = __esm(() => {
40639
40771
  });
40640
40772
 
40641
40773
  // ../cli/dist/extractors/relationships.js
40642
- import * as path35 from "node:path";
40774
+ import * as path36 from "node:path";
40643
40775
  function extractRelationshipShard(shardPath) {
40644
40776
  try {
40645
40777
  const records = readShard(shardPath);
@@ -40672,7 +40804,7 @@ function convertRecordToRelationship(record) {
40672
40804
  return relationship;
40673
40805
  }
40674
40806
  function getRelationshipsDir2(kbRoot) {
40675
- return path35.join(kbRoot, "relationships");
40807
+ return path36.join(kbRoot, "relationships");
40676
40808
  }
40677
40809
  function validateRelationships(relationships, validEntityIds) {
40678
40810
  const errors = [];
@@ -41079,8 +41211,8 @@ var init_symbol_extract = __esm(() => {
41079
41211
  });
41080
41212
 
41081
41213
  // ../cli/dist/public/impact/diagnostics.js
41082
- import { existsSync as existsSync18, readFileSync as readFileSync18 } from "node:fs";
41083
- import * as path36 from "node:path";
41214
+ import { existsSync as existsSync18, readFileSync as readFileSync19 } from "node:fs";
41215
+ import * as path37 from "node:path";
41084
41216
  function isNarrowerSymbol(manifestSymbolName, candidate, sourceSymbols) {
41085
41217
  if (candidate.name === manifestSymbolName)
41086
41218
  return false;
@@ -41104,14 +41236,14 @@ function readSourceSymbols(sourceFile, sourceContentByFile, workspaceRoot) {
41104
41236
  content: stagedContent
41105
41237
  });
41106
41238
  }
41107
- const absolutePath = path36.isAbsolute(sourceFile) ? sourceFile : path36.resolve(workspaceRoot, sourceFile);
41239
+ const absolutePath = path37.isAbsolute(sourceFile) ? sourceFile : path37.resolve(workspaceRoot, sourceFile);
41108
41240
  if (!existsSync18(absolutePath))
41109
41241
  return [];
41110
41242
  return extractSymbolsFromStagedFile({
41111
41243
  path: sourceFile,
41112
41244
  status: "M",
41113
41245
  hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
41114
- content: readFileSync18(absolutePath, "utf8")
41246
+ content: readFileSync19(absolutePath, "utf8")
41115
41247
  });
41116
41248
  }
41117
41249
  function getGranularSymbolsForSourceFile(sourceFile, options2) {
@@ -41477,14 +41609,14 @@ function hasMeaningfulSourceDiff(diffText) {
41477
41609
 
41478
41610
  // ../cli/dist/public/impact/source-changes.js
41479
41611
  import { execFileSync as execFileSync3, execSync as execSync2 } from "node:child_process";
41480
- import { existsSync as existsSync19, lstatSync as lstatSync4, readFileSync as readFileSync19, realpathSync as realpathSync6 } from "node:fs";
41481
- import * as path37 from "node:path";
41612
+ import { existsSync as existsSync19, lstatSync as lstatSync4, readFileSync as readFileSync20, realpathSync as realpathSync6 } from "node:fs";
41613
+ import * as path38 from "node:path";
41482
41614
  function isSupportedSourcePath(filePath) {
41483
41615
  return isQualifiedSourcePath(filePath);
41484
41616
  }
41485
41617
  function normalizeSourceFile(workspaceRoot, sourceFile) {
41486
- const relativePath = path37.isAbsolute(sourceFile) ? path37.relative(workspaceRoot, sourceFile) : sourceFile;
41487
- return relativePath.split(path37.sep).join("/");
41618
+ const relativePath = path38.isAbsolute(sourceFile) ? path38.relative(workspaceRoot, sourceFile) : sourceFile;
41619
+ return relativePath.split(path38.sep).join("/");
41488
41620
  }
41489
41621
  function uniqueSorted2(values) {
41490
41622
  return [...new Set(values)].sort();
@@ -41497,16 +41629,16 @@ function runGit3(workspaceRoot, args) {
41497
41629
  });
41498
41630
  }
41499
41631
  function readWorkingTreeSource(workspaceRoot, sourceFile) {
41500
- const absolutePath = path37.resolve(workspaceRoot, sourceFile);
41501
- const relative = path37.relative(workspaceRoot, absolutePath);
41502
- if (!relative || relative.startsWith("..") || path37.isAbsolute(relative))
41632
+ const absolutePath = path38.resolve(workspaceRoot, sourceFile);
41633
+ const relative = path38.relative(workspaceRoot, absolutePath);
41634
+ if (!relative || relative.startsWith("..") || path38.isAbsolute(relative))
41503
41635
  throw new Error("Source path must remain inside the workspace");
41504
41636
  if (!existsSync19(absolutePath) || !lstatSync4(absolutePath).isFile())
41505
41637
  return null;
41506
- const actualRelative = path37.relative(realpathSync6(workspaceRoot), realpathSync6(absolutePath));
41507
- if (actualRelative.startsWith("..") || path37.isAbsolute(actualRelative))
41638
+ const actualRelative = path38.relative(realpathSync6(workspaceRoot), realpathSync6(absolutePath));
41639
+ if (actualRelative.startsWith("..") || path38.isAbsolute(actualRelative))
41508
41640
  throw new Error("Source path escapes the workspace");
41509
- const bytes = readFileSync19(absolutePath);
41641
+ const bytes = readFileSync20(absolutePath);
41510
41642
  if (bytes.includes(0))
41511
41643
  return null;
41512
41644
  try {
@@ -41582,7 +41714,7 @@ function getExplicitSourceChanges(workspaceRoot, sourceFileFilter) {
41582
41714
  });
41583
41715
  }
41584
41716
  function collectSourceChanges(options2) {
41585
- const workspaceRoot = path37.resolve(options2.workspaceRoot);
41717
+ const workspaceRoot = path38.resolve(options2.workspaceRoot);
41586
41718
  const sourceFileFilter = new Set((options2.sourceFiles ?? []).map((sourceFile) => normalizeSourceFile(workspaceRoot, sourceFile)).filter(isSupportedSourcePath));
41587
41719
  if (options2.staged)
41588
41720
  return getStagedSourceChanges(workspaceRoot, sourceFileFilter);
@@ -41598,13 +41730,13 @@ var init_source_changes = __esm(() => {
41598
41730
 
41599
41731
  // ../cli/dist/public/impact/manifest.js
41600
41732
  import { existsSync as existsSync20 } from "node:fs";
41601
- import * as path38 from "node:path";
41733
+ import * as path39 from "node:path";
41602
41734
  function toTraceabilityRelationships(relationships) {
41603
41735
  return relationships.filter((relationship) => isTraceabilityRelationshipType(relationship.type)).map((relationship) => ({ type: relationship.type, to: relationship.to }));
41604
41736
  }
41605
41737
  function readImpactManifestResults(workspaceRoot) {
41606
41738
  const symbolsPath = CANONICAL_ENTITY_PATHS.symbols;
41607
- const absolutePath = path38.isAbsolute(symbolsPath) ? symbolsPath : path38.resolve(workspaceRoot, symbolsPath);
41739
+ const absolutePath = path39.isAbsolute(symbolsPath) ? symbolsPath : path39.resolve(workspaceRoot, symbolsPath);
41608
41740
  if (!existsSync20(absolutePath))
41609
41741
  return [];
41610
41742
  return extractFromManifest(absolutePath).map((result) => ({
@@ -41965,9 +42097,9 @@ var init_symbol_quality = __esm(() => {
41965
42097
  });
41966
42098
 
41967
42099
  // ../cli/dist/public/impact/analyzer.js
41968
- import * as path39 from "node:path";
42100
+ import * as path40 from "node:path";
41969
42101
  async function analyzeChangedFileImpact(options2) {
41970
- const workspaceRoot = path39.resolve(options2.workspaceRoot);
42102
+ const workspaceRoot = path40.resolve(options2.workspaceRoot);
41971
42103
  const snapshot = options2.staged ? captureStagedSnapshot(workspaceRoot) : undefined;
41972
42104
  const filter = new Set((options2.sourceFiles ?? []).map((file) => normalizeSourceFile(workspaceRoot, file)));
41973
42105
  const snapshotAnalysisInventory = snapshot ? snapshot.inventory.filter((file) => filter.size === 0 || filter.has(file.path)) : undefined;
@@ -43055,7 +43187,7 @@ var init_requirement_quality = __esm(() => {
43055
43187
 
43056
43188
  // ../cli/dist/public/impact/full-kb-quality.js
43057
43189
  import { readFile } from "node:fs/promises";
43058
- import path40 from "node:path";
43190
+ import path41 from "node:path";
43059
43191
  function stringField(entity, key) {
43060
43192
  const value = entity[key];
43061
43193
  return typeof value === "string" ? value : "";
@@ -43485,7 +43617,7 @@ function telemetryReadDiagnostic(message) {
43485
43617
  async function collectTelemetryDiagnostics(workspaceRoot, now) {
43486
43618
  if (workspaceRoot === undefined)
43487
43619
  return [];
43488
- const usageLogPath = path40.join(workspaceRoot, ".kb", "usage.log");
43620
+ const usageLogPath = path41.join(workspaceRoot, ".kb", "usage.log");
43489
43621
  let contents;
43490
43622
  try {
43491
43623
  contents = await readFile(usageLogPath, "utf8");
@@ -43661,7 +43793,7 @@ function buildSummary(input) {
43661
43793
  }
43662
43794
 
43663
43795
  // ../cli/dist/utils/entity-id-style.js
43664
- import * as path41 from "node:path";
43796
+ import * as path42 from "node:path";
43665
43797
  function isNumericEntityId(id) {
43666
43798
  return NUMERIC_ENTITY_ID_PATTERN.test(id.trim());
43667
43799
  }
@@ -43672,7 +43804,7 @@ function markdownSourceStem(sourcePath) {
43672
43804
  if (!normalized.endsWith(".md") || normalized.includes("://")) {
43673
43805
  return;
43674
43806
  }
43675
- return path41.posix.basename(normalized, ".md");
43807
+ return path42.posix.basename(normalized, ".md");
43676
43808
  }
43677
43809
  function entityIdStyleIssues(input) {
43678
43810
  const id = input.id.trim();
@@ -43798,8 +43930,8 @@ var init_prolog_query_plan_safety = __esm(() => {
43798
43930
 
43799
43931
  // ../cli/dist/public/operations/check-helpers.js
43800
43932
  import { execSync as execSync3 } from "node:child_process";
43801
- import { readFileSync as readFileSync20 } from "node:fs";
43802
- import path42 from "node:path";
43933
+ import { readFileSync as readFileSync21 } from "node:fs";
43934
+ import path43 from "node:path";
43803
43935
  function partitionCheckFindings(findings) {
43804
43936
  const violations = [];
43805
43937
  const qualityDiagnostics = [];
@@ -43826,11 +43958,11 @@ function partitionCheckFindings(findings) {
43826
43958
  }
43827
43959
  function resolveChecksPlPath() {
43828
43960
  const override = getKbPlPathOverride();
43829
- return path42.join(path42.dirname(override ?? resolveKbPlPath()), "checks.pl");
43961
+ return path43.join(path43.dirname(override ?? resolveKbPlPath()), "checks.pl");
43830
43962
  }
43831
43963
  function collectQueryPlanSafetyViolations() {
43832
43964
  const checksPlPath = resolveChecksPlPath();
43833
- const source = readFileSync20(checksPlPath, "utf8");
43965
+ const source = readFileSync21(checksPlPath, "utf8");
43834
43966
  return analyzePrologQueryPlanSafety(source).map((v) => ({
43835
43967
  rule: "query-plan-safety",
43836
43968
  entityId: v.predicate,
@@ -43888,8 +44020,8 @@ var init_check_helpers = __esm(() => {
43888
44020
  });
43889
44021
 
43890
44022
  // ../cli/dist/operations/migration/kb-sources.js
43891
- import { existsSync as existsSync21, mkdirSync as mkdirSync7, readFileSync as readFileSync21, readdirSync as readdirSync5, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
43892
- import path43 from "node:path";
44023
+ import { existsSync as existsSync21, mkdirSync as mkdirSync7, readFileSync as readFileSync22, readdirSync as readdirSync5, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "node:fs";
44024
+ import path44 from "node:path";
43893
44025
  import { isDeepStrictEqual } from "node:util";
43894
44026
  function walkMarkdown(directory, files) {
43895
44027
  let entries;
@@ -43899,7 +44031,7 @@ function walkMarkdown(directory, files) {
43899
44031
  return;
43900
44032
  }
43901
44033
  for (const entry of entries) {
43902
- const absolute = path43.join(directory, entry.name);
44034
+ const absolute = path44.join(directory, entry.name);
43903
44035
  if (entry.isDirectory()) {
43904
44036
  walkMarkdown(absolute, files);
43905
44037
  } else if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
@@ -43911,7 +44043,7 @@ function listLaneMarkdownFiles(workspaceRoot, lanes = ENTITY_LANES) {
43911
44043
  const result = [];
43912
44044
  for (const lane of lanes) {
43913
44045
  const files = [];
43914
- const laneRoot = path43.join(workspaceRoot, KB_PATHS.lanes[lane]);
44046
+ const laneRoot = path44.join(workspaceRoot, KB_PATHS.lanes[lane]);
43915
44047
  if (!existsSync21(laneRoot))
43916
44048
  continue;
43917
44049
  walkMarkdown(laneRoot, files);
@@ -43919,7 +44051,7 @@ function listLaneMarkdownFiles(workspaceRoot, lanes = ENTITY_LANES) {
43919
44051
  result.push({
43920
44052
  lane,
43921
44053
  absolutePath,
43922
- relativePath: path43.relative(workspaceRoot, absolutePath).replaceAll(path43.sep, "/")
44054
+ relativePath: path44.relative(workspaceRoot, absolutePath).replaceAll(path44.sep, "/")
43923
44055
  });
43924
44056
  }
43925
44057
  }
@@ -44047,14 +44179,14 @@ function withoutTopLevelField(content, key) {
44047
44179
  return match === null ? content : `${slice.prefix}${text}${slice.suffix}`;
44048
44180
  }
44049
44181
  function writeFileAtomically(filePath, content) {
44050
- mkdirSync7(path43.dirname(filePath), { recursive: true });
44182
+ mkdirSync7(path44.dirname(filePath), { recursive: true });
44051
44183
  const tempPath = `${filePath}.kibi-migrate-${process.pid}-${Date.now()}`;
44052
44184
  writeFileSync6(tempPath, content, "utf8");
44053
44185
  renameSync4(tempPath, filePath);
44054
44186
  }
44055
44187
  function readText(filePath) {
44056
44188
  try {
44057
- return readFileSync21(filePath, "utf8");
44189
+ return readFileSync22(filePath, "utf8");
44058
44190
  } catch {
44059
44191
  return null;
44060
44192
  }
@@ -44065,7 +44197,7 @@ var init_kb_sources = __esm(() => {
44065
44197
  });
44066
44198
 
44067
44199
  // ../cli/dist/public/operations/entity-context.js
44068
- import path44 from "node:path";
44200
+ import path45 from "node:path";
44069
44201
  function readAuthoredEntity(content, relativePath) {
44070
44202
  const slice = sliceFrontmatter(content);
44071
44203
  if (slice === null)
@@ -44081,7 +44213,7 @@ function readAuthoredEntity(content, relativePath) {
44081
44213
  }
44082
44214
  const record = data;
44083
44215
  const type = typeof record.type === "string" ? record.type : inferTypeFromPath(relativePath) ?? "";
44084
- const id = typeof record.id === "string" && record.id.trim() !== "" ? record.id.trim() : path44.basename(relativePath, ".md");
44216
+ const id = typeof record.id === "string" && record.id.trim() !== "" ? record.id.trim() : path45.basename(relativePath, ".md");
44085
44217
  const newline = slice.suffix.indexOf(`
44086
44218
  `);
44087
44219
  return {
@@ -44139,7 +44271,7 @@ function authoredSupersededIds(workspaceRoot, entities) {
44139
44271
  }
44140
44272
  }
44141
44273
  try {
44142
- for (const relationship of readAllShards(path44.join(workspaceRoot, ".kb"))) {
44274
+ for (const relationship of readAllShards(path45.join(workspaceRoot, ".kb"))) {
44143
44275
  if (relationship.type === "supersedes")
44144
44276
  superseded.add(relationship.to);
44145
44277
  }
@@ -44228,8 +44360,8 @@ var init_entity_context = __esm(() => {
44228
44360
  });
44229
44361
 
44230
44362
  // ../cli/dist/public/operations/origin-review.js
44231
- import { readFileSync as readFileSync22 } from "node:fs";
44232
- import path45 from "node:path";
44363
+ import { readFileSync as readFileSync23 } from "node:fs";
44364
+ import path46 from "node:path";
44233
44365
  function markdownHasRationaleSection(content) {
44234
44366
  const body = content.startsWith("---") ? content.replace(/^---\r?\n[\s\S]*?\r?\n---[ \t]*(?:\r?\n|$)/, "") : content;
44235
44367
  return RATIONALE_HEADING.test(body);
@@ -44240,13 +44372,13 @@ function rationaleSectionReader(workspaceRoot) {
44240
44372
  const source = text3(entity.source);
44241
44373
  if (source === undefined || !source.endsWith(".md"))
44242
44374
  return false;
44243
- const file = path45.resolve(workspaceRoot, source);
44375
+ const file = path46.resolve(workspaceRoot, source);
44244
44376
  const cached = cache.get(file);
44245
44377
  if (cached !== undefined)
44246
44378
  return cached;
44247
44379
  let found = false;
44248
44380
  try {
44249
- found = markdownHasRationaleSection(readFileSync22(file, "utf8"));
44381
+ found = markdownHasRationaleSection(readFileSync23(file, "utf8"));
44250
44382
  } catch {
44251
44383
  found = false;
44252
44384
  }
@@ -46585,7 +46717,7 @@ var init_predicate_schema_conformance = __esm(() => {
46585
46717
 
46586
46718
  // ../cli/dist/operations/migration/source-paths.js
46587
46719
  import { existsSync as existsSync22 } from "node:fs";
46588
- import path46 from "node:path";
46720
+ import path47 from "node:path";
46589
46721
  function scalarText(value) {
46590
46722
  if (typeof value === "string")
46591
46723
  return value.trim();
@@ -46609,7 +46741,7 @@ function scanAuthoredSources(workspaceRoot) {
46609
46741
  const slice = sliceFrontmatter(content);
46610
46742
  if (slice === null)
46611
46743
  continue;
46612
- const id = scalarText(readTopLevelField(slice.text, "id")) || path46.basename(file.relativePath, ".md");
46744
+ const id = scalarText(readTopLevelField(slice.text, "id")) || path47.basename(file.relativePath, ".md");
46613
46745
  entityIds.add(id);
46614
46746
  const value = readTopLevelField(slice.text, "source");
46615
46747
  if (value === undefined || value === null)
@@ -46618,7 +46750,7 @@ function scanAuthoredSources(workspaceRoot) {
46618
46750
  continue;
46619
46751
  refs.push({ entityId: id, file: file.relativePath, value });
46620
46752
  }
46621
- const symbols = readText(path46.join(workspaceRoot, KB_PATHS.symbolsManifest));
46753
+ const symbols = readText(path47.join(workspaceRoot, KB_PATHS.symbolsManifest));
46622
46754
  if (symbols !== null) {
46623
46755
  for (const match of symbols.matchAll(SYMBOL_ID_LINE)) {
46624
46756
  const id = unquote(match[1] ?? "");
@@ -46664,15 +46796,15 @@ function resolveAuthoredSource(value, context) {
46664
46796
  return { kind: "dangling" };
46665
46797
  }
46666
46798
  function workspacePathExists(workspaceRoot) {
46667
- const root = path46.resolve(workspaceRoot);
46799
+ const root = path47.resolve(workspaceRoot);
46668
46800
  const cache = new Map;
46669
46801
  return (relativePath) => {
46670
46802
  const cached = cache.get(relativePath);
46671
46803
  if (cached !== undefined)
46672
46804
  return cached;
46673
- const absolute = path46.resolve(root, relativePath);
46674
- const fromRoot = path46.relative(root, absolute);
46675
- const exists = !fromRoot.startsWith("..") && !path46.isAbsolute(fromRoot) && existsSync22(absolute);
46805
+ const absolute = path47.resolve(root, relativePath);
46806
+ const fromRoot = path47.relative(root, absolute);
46807
+ const exists = !fromRoot.startsWith("..") && !path47.isAbsolute(fromRoot) && existsSync22(absolute);
46676
46808
  cache.set(relativePath, exists);
46677
46809
  return exists;
46678
46810
  };
@@ -46714,7 +46846,7 @@ function classifySources(workspaceRoot) {
46714
46846
  }
46715
46847
  function withEditability(workspaceRoot, repairs) {
46716
46848
  return repairs.map((repair) => {
46717
- const content = readText(path46.join(workspaceRoot, repair.file));
46849
+ const content = readText(path47.join(workspaceRoot, repair.file));
46718
46850
  if (content !== null && editedContent(content, repair.fix) !== null) {
46719
46851
  return repair;
46720
46852
  }
@@ -46782,7 +46914,7 @@ function applySourcePathRepairs(workspaceRoot, planned) {
46782
46914
  continue;
46783
46915
  }
46784
46916
  }
46785
- const absolute = path46.join(workspaceRoot, repair.file);
46917
+ const absolute = path47.join(workspaceRoot, repair.file);
46786
46918
  const content = readText(absolute);
46787
46919
  const next = content === null ? null : editedContent(content, repair.fix);
46788
46920
  if (next === null) {
@@ -52345,15 +52477,15 @@ var require_out4 = __commonJS(function(exports2, module2) {
52345
52477
  import { execFile } from "node:child_process";
52346
52478
  import { createHash as createHash24 } from "node:crypto";
52347
52479
  import * as fs5 from "node:fs";
52348
- import { existsSync as existsSync23, readFileSync as readFileSync24, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
52349
- import * as path47 from "node:path";
52480
+ import { existsSync as existsSync23, readFileSync as readFileSync25, readdirSync as readdirSync6, unlinkSync as unlinkSync4 } from "node:fs";
52481
+ import * as path48 from "node:path";
52350
52482
  import { promisify } from "node:util";
52351
52483
  async function gitTrackedPaths(cwd) {
52352
52484
  const result = await execFileAsync("git", ["-C", cwd, "ls-files", "--cached", "-z", "--"], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 });
52353
52485
  return new Set(result.stdout.toString("utf8").split("\x00").filter(Boolean).map((value) => value.replaceAll("\\", "/")));
52354
52486
  }
52355
52487
  function pendingSourcePaths(cwd, recoverMissing) {
52356
- const root = path47.join(cwd, ".kb", "recovery", "pending-sources");
52488
+ const root = path48.join(cwd, ".kb", "recovery", "pending-sources");
52357
52489
  if (!existsSync23(root)) {
52358
52490
  return { paths: new Map, recoveredReceipts: [] };
52359
52491
  }
@@ -52362,14 +52494,14 @@ function pendingSourcePaths(cwd, recoverMissing) {
52362
52494
  for (const name of readdirSync6(root)) {
52363
52495
  if (!name.endsWith(".json"))
52364
52496
  continue;
52365
- const receiptPath = path47.join(root, name);
52497
+ const receiptPath = path48.join(root, name);
52366
52498
  try {
52367
- const raw = readFileSync24(receiptPath, "utf8");
52499
+ const raw = readFileSync25(receiptPath, "utf8");
52368
52500
  const receipt = JSON.parse(raw);
52369
52501
  if (typeof receipt.path === "string" && receipt.path.length > 0 && typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash)) {
52370
52502
  const relative = receipt.path.replaceAll("\\", "/");
52371
- const absolute = path47.resolve(cwd, relative);
52372
- if (!absolute.startsWith(`${path47.resolve(cwd)}${path47.sep}`)) {
52503
+ const absolute = path48.resolve(cwd, relative);
52504
+ if (!absolute.startsWith(`${path48.resolve(cwd)}${path48.sep}`)) {
52373
52505
  throw new Error(`Pending source receipt escapes workspace: ${relative}`);
52374
52506
  }
52375
52507
  if (!existsSync23(absolute)) {
@@ -52384,7 +52516,7 @@ function pendingSourcePaths(cwd, recoverMissing) {
52384
52516
  }
52385
52517
  throw new Error(`Pending source is missing: ${relative}. If the file was deleted on purpose, run 'kibi branch recover --apply' to rebuild the branch KB from the sources that remain.`);
52386
52518
  }
52387
- const actual = createHash24("sha256").update(readFileSync24(absolute)).digest("hex");
52519
+ const actual = createHash24("sha256").update(readFileSync25(absolute)).digest("hex");
52388
52520
  if (actual !== receipt.afterHash) {
52389
52521
  throw new Error(`Pending source hash drift blocks sync for ${relative}; expected ${receipt.afterHash}, found ${actual}`);
52390
52522
  }
@@ -52421,10 +52553,10 @@ function unlinkOrEnoent(absolute) {
52421
52553
  }
52422
52554
  }
52423
52555
  function clearRecoveredPendingSourceReceipts(cwd, receipts) {
52424
- const root = path47.resolve(cwd, ".kb", "recovery", "pending-sources");
52556
+ const root = path48.resolve(cwd, ".kb", "recovery", "pending-sources");
52425
52557
  for (const receipt of receipts) {
52426
- const absolute = path47.resolve(receipt.receiptPath);
52427
- if (!absolute.startsWith(`${root}${path47.sep}`)) {
52558
+ const absolute = path48.resolve(receipt.receiptPath);
52559
+ if (!absolute.startsWith(`${root}${path48.sep}`)) {
52428
52560
  throw new Error(`Pending source receipt escapes recovery root: ${absolute}`);
52429
52561
  }
52430
52562
  if (!existsSync23(absolute))
@@ -52451,7 +52583,7 @@ function clearRecoveredPendingSourceReceipts(cwd, receipts) {
52451
52583
  function filterTracked(cwd, files, tracked, pending) {
52452
52584
  const retained = [];
52453
52585
  for (const file of files) {
52454
- const relative = path47.relative(cwd, file).replaceAll(path47.sep, "/");
52586
+ const relative = path48.relative(cwd, file).replaceAll(path48.sep, "/");
52455
52587
  if (tracked.has(relative)) {
52456
52588
  retained.push(file);
52457
52589
  continue;
@@ -52500,7 +52632,7 @@ async function discoverSourceFiles(cwd, options2 = {}) {
52500
52632
  entityMarkdownFiles = filterTracked(cwd, entityMarkdownFiles, tracked, new Set(pending.paths.keys()));
52501
52633
  manifestFiles = filterTracked(cwd, manifestFiles, tracked, new Set(pending.paths.keys()));
52502
52634
  for (const relative of pending.paths.keys()) {
52503
- const absolute = path47.resolve(cwd, relative);
52635
+ const absolute = path48.resolve(cwd, relative);
52504
52636
  if (!existsSync23(absolute))
52505
52637
  continue;
52506
52638
  if (relative.endsWith(".md") && !entityMarkdownFiles.includes(absolute)) {
@@ -52510,21 +52642,21 @@ async function discoverSourceFiles(cwd, options2 = {}) {
52510
52642
  manifestFiles.push(absolute);
52511
52643
  }
52512
52644
  }
52513
- const pendingRoot = path47.join(cwd, ".kb", "recovery", "pending-sources");
52645
+ const pendingRoot = path48.join(cwd, ".kb", "recovery", "pending-sources");
52514
52646
  if (options2.consumeTrackedPendingReceipts !== false && existsSync23(pendingRoot)) {
52515
52647
  for (const name of readdirSync6(pendingRoot)) {
52516
52648
  if (!name.endsWith(".json"))
52517
52649
  continue;
52518
52650
  try {
52519
- const receipt = JSON.parse(readFileSync24(path47.join(pendingRoot, name), "utf8"));
52651
+ const receipt = JSON.parse(readFileSync25(path48.join(pendingRoot, name), "utf8"));
52520
52652
  if (typeof receipt.path === "string" && tracked.has(receipt.path.replaceAll("\\", "/"))) {
52521
- unlinkSync4(path47.join(pendingRoot, name));
52653
+ unlinkSync4(path48.join(pendingRoot, name));
52522
52654
  }
52523
52655
  } catch {}
52524
52656
  }
52525
52657
  }
52526
52658
  }
52527
- const relationshipsDir = getRelationshipsDir2(path47.join(cwd, ".kb"));
52659
+ const relationshipsDir = getRelationshipsDir2(path48.join(cwd, ".kb"));
52528
52660
  return {
52529
52661
  markdownFiles: entityMarkdownFiles,
52530
52662
  manifestFiles,
@@ -52542,15 +52674,15 @@ var init_discovery2 = __esm(() => {
52542
52674
  });
52543
52675
 
52544
52676
  // ../cli/dist/commands/sync/extraction.js
52545
- import * as path48 from "node:path";
52677
+ import * as path49 from "node:path";
52546
52678
  function normalizeExtractionSources(results, workspaceRoot) {
52547
- const root = path48.resolve(workspaceRoot);
52679
+ const root = path49.resolve(workspaceRoot);
52548
52680
  const normalize = (value) => {
52549
52681
  if (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(value))
52550
52682
  return value;
52551
- const absolute = path48.isAbsolute(value) ? path48.resolve(value) : undefined;
52552
- if (absolute?.startsWith(`${root}${path48.sep}`)) {
52553
- return path48.relative(root, absolute).replaceAll(path48.sep, "/");
52683
+ const absolute = path49.isAbsolute(value) ? path49.resolve(value) : undefined;
52684
+ if (absolute?.startsWith(`${root}${path49.sep}`)) {
52685
+ return path49.relative(root, absolute).replaceAll(path49.sep, "/");
52554
52686
  }
52555
52687
  return value.replaceAll("\\", "/");
52556
52688
  };
@@ -52903,7 +53035,7 @@ var init_relationships2 = __esm(() => {
52903
53035
 
52904
53036
  // ../cli/dist/public/operations/source-relationship-parity.js
52905
53037
  import { execFileSync as execFileSync4 } from "node:child_process";
52906
- import path49 from "node:path";
53038
+ import path50 from "node:path";
52907
53039
  function relationshipKey(relationship) {
52908
53040
  return `${relationship.type}\x00${relationship.from}\x00${relationship.to}`;
52909
53041
  }
@@ -53034,14 +53166,14 @@ async function collectSourceRelationshipParityViolations(workspaceRoot, prolog)
53034
53166
  if (extraction.errors.length > 0) {
53035
53167
  return extraction.errors.map(({ file, message }) => ({
53036
53168
  rule: "source-relationship-parity",
53037
- entityId: path49.relative(workspaceRoot, file).replaceAll(path49.sep, "/"),
53038
- source: path49.relative(workspaceRoot, file).replaceAll(path49.sep, "/"),
53169
+ entityId: path50.relative(workspaceRoot, file).replaceAll(path50.sep, "/"),
53170
+ source: path50.relative(workspaceRoot, file).replaceAll(path50.sep, "/"),
53039
53171
  description: `Authored relationship parity could not inspect source: ${message}`,
53040
53172
  suggestion: "Repair the authored source, then rerun kb_check."
53041
53173
  }));
53042
53174
  }
53043
53175
  const authored = extraction.results.flatMap(({ entity, relationships }) => relationships.map((relationship) => authoredRelationship(relationship, entity.source)));
53044
- for (const relationship of readAllShards(path49.join(workspaceRoot, ".kb"))) {
53176
+ for (const relationship of readAllShards(path50.join(workspaceRoot, ".kb"))) {
53045
53177
  authored.push({
53046
53178
  type: relationship.type,
53047
53179
  from: relationship.from,
@@ -54946,10 +55078,39 @@ function nameOrStopWordReason(value, context = {}) {
54946
55078
  return `it repeats the argument name ${token} and the claim does not name it`;
54947
55079
  return null;
54948
55080
  }
55081
+ function isParticipantArgumentType(type) {
55082
+ return PARTICIPANT_ARGUMENT_TYPES.has(type ? bindingToken(type) : "");
55083
+ }
55084
+ function subjectKeyParticipantReason(value, context = {}) {
55085
+ if (!isParticipantArgumentType(context.argumentType))
55086
+ return null;
55087
+ if (matchesConstant(value, context))
55088
+ return null;
55089
+ const token = bindingToken(value);
55090
+ if (token === "")
55091
+ return null;
55092
+ const subject = (context.constrainedSubjects ?? []).find((key) => bindingToken(key) === token);
55093
+ if (subject === undefined)
55094
+ return null;
55095
+ return `"${value}" is the requirement's subject key ${subject}, which the predicate fact already carries as its subject_key, so it names no ${bindingToken(context.argumentType ?? "")}`;
55096
+ }
55097
+ function clauseBindingReason(value, context = {}) {
55098
+ const type = context.argumentType ? bindingToken(context.argumentType) : "";
55099
+ if (!NAMING_ARGUMENT_TYPES.has(type))
55100
+ return null;
55101
+ if (matchesConstant(value, context))
55102
+ return null;
55103
+ const words = bindingToken(value).split("_").filter(Boolean);
55104
+ if (words.length <= MAX_NAMING_BINDING_WORDS)
55105
+ return null;
55106
+ return `it is a ${words.length}-word clause of the claim, not a short name for this ${type}`;
55107
+ }
54949
55108
  function classifyBinding(value, text, explicit, canonical = false, context = {}) {
54950
55109
  const normalized = value.trim();
54951
55110
  if (nameOrStopWordReason(normalized, { ...context, text }) !== null)
54952
55111
  return "placeholder";
55112
+ if (subjectKeyParticipantReason(normalized, context) !== null)
55113
+ return "placeholder";
54953
55114
  const constant = matchesConstant(normalized, context);
54954
55115
  if (canonical && (constant || !isGenericPlaceholder(normalized)))
54955
55116
  return "extracted";
@@ -54957,6 +55118,8 @@ function classifyBinding(value, text, explicit, canonical = false, context = {})
54957
55118
  return "explicit";
54958
55119
  if (!normalized || isGenericPlaceholder(normalized))
54959
55120
  return "placeholder";
55121
+ if (clauseBindingReason(normalized, context) !== null)
55122
+ return "placeholder";
54960
55123
  if (textContainsValue(text, normalized))
54961
55124
  return "extracted";
54962
55125
  return "inferred";
@@ -54967,7 +55130,7 @@ function aggregateBindingProvenance(values) {
54967
55130
  function bindingCanBeApplied(value) {
54968
55131
  return value === "explicit" || value === "requirement" || value === "extracted";
54969
55132
  }
54970
- var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, STOP_WORD_BINDINGS, PROVENANCE_ORDER;
55133
+ var PLACEHOLDER_VALUES, DERIVED_CUE_ALIASES, STOP_WORD_BINDINGS, NAMING_ARGUMENT_TYPES, PARTICIPANT_ARGUMENT_TYPES, MAX_NAMING_BINDING_WORDS = 3, PROVENANCE_ORDER;
54971
55134
  var init_predicate_bindings = __esm(() => {
54972
55135
  PLACEHOLDER_VALUES = new Set([
54973
55136
  "unknown",
@@ -55108,6 +55271,21 @@ var init_predicate_bindings = __esm(() => {
55108
55271
  "example",
55109
55272
  "placeholder"
55110
55273
  ]);
55274
+ NAMING_ARGUMENT_TYPES = new Set([
55275
+ "entity",
55276
+ "actor",
55277
+ "actor_scope",
55278
+ "resource",
55279
+ "owner",
55280
+ "role",
55281
+ "component"
55282
+ ]);
55283
+ PARTICIPANT_ARGUMENT_TYPES = new Set([
55284
+ "actor",
55285
+ "actor_scope",
55286
+ "role",
55287
+ "owner"
55288
+ ]);
55111
55289
  PROVENANCE_ORDER = [
55112
55290
  "explicit",
55113
55291
  "requirement",
@@ -55813,11 +55991,14 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
55813
55991
  const inferredArgs = inferArgs(schema, text, subject);
55814
55992
  const canonicalLauncherArgs = exactLauncherPredicateArgs(schema.predicate_name, text);
55815
55993
  const hasExactBinding = (name) => typeof argumentBindings[name] === "string" && argumentBindings[name].trim().length > 0;
55816
- const requirementSubjectArgument = diagnostics?.requirementSubject && diagnostics.explicitSubject !== true && !hasExactBinding("subject") ? schema.argument_names.indexOf("subject") : -1;
55994
+ const subjectArgument = schema.argument_names.indexOf("subject");
55995
+ const explicitSubject = diagnostics?.explicitSubject === true;
55996
+ const reviewedSubject = explicitSubject ? subject : diagnostics?.requirementSubject;
55997
+ const reviewedSubjectArgument = reviewedSubject !== undefined && !hasExactBinding("subject") ? subjectArgument : -1;
55817
55998
  const boundArgs = schema.argument_names.map((name, index) => {
55818
55999
  const exactBinding = argumentBindings[name];
55819
- if (index === requirementSubjectArgument)
55820
- return diagnostics?.requirementSubject ?? "unknown";
56000
+ if (index === reviewedSubjectArgument)
56001
+ return reviewedSubject ?? "unknown";
55821
56002
  return typeof exactBinding === "string" && exactBinding.trim().length > 0 ? exactBinding.trim() : inferredArgs[index] ?? "unknown";
55822
56003
  });
55823
56004
  const vocabulary = {
@@ -55827,16 +56008,27 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
55827
56008
  const conformance = predicateArgumentConformance(schema.argument_names, boundArgs, vocabulary);
55828
56009
  const predicateArgs = applyArgumentRewrites(boundArgs, conformance.rewrites);
55829
56010
  const undeclaredArguments = new Set(conformance.undeclared.map((value) => value.argumentName));
56011
+ const hintedFirstArgument = explicitSubject && subjectArgument < 0 && !hasExactBinding(schema.argument_names[0] ?? "") && predicateArgs[0] === subject && !isParticipantArgumentType(schema.argument_types[0]) ? 0 : -1;
56012
+ const constrainedSubjects = diagnostics?.constrainedSubjects ?? [];
55830
56013
  const bindingProvenanceByArgument = Object.fromEntries(schema.argument_names.map((name, index) => [
55831
56014
  name,
55832
- index === requirementSubjectArgument && !undeclaredArguments.has(name) ? "requirement" : classifyBinding(predicateArgs[index] ?? "unknown", text, typeof argumentBindings[name] === "string" && argumentBindings[name].trim().length > 0 || diagnostics?.explicitSubject === true && index === 0, canonicalLauncherArgs?.[index] === predicateArgs[index] && !(index === 0 && predicateArgs[index] === "launcher" && diagnostics?.explicitSubject !== true && typeof argumentBindings[name] !== "string"), index === 0 && diagnostics?.explicitSubject === true && typeof argumentBindings[name] !== "string" ? { constants: schema.argument_constants?.[name] } : {
56015
+ index === reviewedSubjectArgument && !undeclaredArguments.has(name) ? explicitSubject ? classifyBinding(predicateArgs[index] ?? "unknown", text, true) : "requirement" : classifyBinding(predicateArgs[index] ?? "unknown", text, hasExactBinding(name) || index === hintedFirstArgument, canonicalLauncherArgs?.[index] === predicateArgs[index] && !(index === 0 && predicateArgs[index] === "launcher" && !explicitSubject && typeof argumentBindings[name] !== "string"), index === hintedFirstArgument ? { constants: schema.argument_constants?.[name] } : {
55833
56016
  argumentName: name,
55834
56017
  argumentNames: schema.argument_names,
55835
- constants: schema.argument_constants?.[name]
56018
+ argumentType: schema.argument_types[index],
56019
+ constants: schema.argument_constants?.[name],
56020
+ constrainedSubjects
55836
56021
  })
55837
56022
  ]));
56023
+ const subjectKey = constrainedSubjects.length === 0 ? null : subjectArgument >= 0 ? predicateArgs[subjectArgument] ?? null : reviewedSubject ?? null;
56024
+ const subjectPairing = constrainedSubjects.length === 0 ? "not_required" : subjectKey !== null && constrainedSubjects.includes(subjectKey) ? "paired" : "unpaired";
55838
56025
  const bindingProvenance = aggregateBindingProvenance(Object.values(bindingProvenanceByArgument));
55839
56026
  const unboundArguments = schema.argument_names.filter((name) => undeclaredArguments.has(name) || !bindingCanBeApplied(bindingProvenanceByArgument[name] ?? "placeholder"));
56027
+ if (subjectPairing === "unpaired") {
56028
+ const missing = subjectArgument >= 0 ? "subject" : "subject_key";
56029
+ if (!unboundArguments.includes(missing))
56030
+ unboundArguments.push(missing);
56031
+ }
55840
56032
  const canonicalKey = `${schema.predicate_name}(${predicateArgs.join(",")})`;
55841
56033
  const polarity = polarityHint ?? (predicateArgs.at(-1) === "deny" || /\b(?:must\s+not|shall\s+not|never|cannot|can't|forbidden|prohibited)\b/i.test(text) ? "deny" : "assert");
55842
56034
  return {
@@ -55849,6 +56041,8 @@ function buildSuggestion(schema, text, subject, score, argumentBindings = {}, po
55849
56041
  unbound_arguments: unboundArguments,
55850
56042
  binding_provenance: bindingProvenance,
55851
56043
  binding_provenance_by_argument: bindingProvenanceByArgument,
56044
+ subject_key: subjectKey,
56045
+ subject_pairing: subjectPairing,
55852
56046
  eligibility: diagnostics?.eligibility ?? "eligible",
55853
56047
  rejection_reasons: [...diagnostics?.rejectionReasons ?? []],
55854
56048
  applicability_score: diagnostics?.applicabilityScore ?? score,
@@ -55891,6 +56085,7 @@ function buildPredicateApplyPlan(suggestion, args) {
55891
56085
  ...suggestion.schema.tags.map((tag) => `predicate:${tag}`)
55892
56086
  ],
55893
56087
  fact_kind: "predicate",
56088
+ ...suggestion.subject_key ? { subject_key: suggestion.subject_key } : {},
55894
56089
  predicate_name: suggestion.predicate_name,
55895
56090
  predicate_args: suggestion.predicate_args,
55896
56091
  canonical_key: suggestion.canonical_key,
@@ -56046,9 +56241,14 @@ function exampleArguments(example) {
56046
56241
  args.push(current.trim());
56047
56242
  return args.filter(Boolean);
56048
56243
  }
56049
- function unboundReason(candidate, name, value, text) {
56244
+ function noParticipantGuidance(type) {
56245
+ return `The claim names no ${type}. Bind the participant the claim names (a noun of at most 3 words), never the requirement's subject key; if the claim names no ${type}, this schema does not fit the claim: record_ontology_gap instead.`;
56246
+ }
56247
+ function unboundReason(candidate, name, value, text, requirementSubjects) {
56050
56248
  const schema = candidate.schema;
56051
56249
  const provenance = candidate.binding_provenance_by_argument[name];
56250
+ const type = schema.argument_types[schema.argument_names.indexOf(name)];
56251
+ const participant = isParticipantArgumentType(type);
56052
56252
  const nameReason = nameOrStopWordReason(value, {
56053
56253
  argumentName: name,
56054
56254
  argumentNames: schema.argument_names,
@@ -56057,8 +56257,21 @@ function unboundReason(candidate, name, value, text) {
56057
56257
  });
56058
56258
  if (nameReason !== null)
56059
56259
  return `The value "${value}" is not a binding: ${nameReason}.`;
56260
+ const subjectReason = subjectKeyParticipantReason(value, {
56261
+ argumentType: type,
56262
+ constants: schema.argument_constants?.[name],
56263
+ constrainedSubjects: requirementSubjects
56264
+ });
56265
+ if (subjectReason !== null)
56266
+ return `The value "${value}" is not a binding: ${subjectReason}. ${noParticipantGuidance(String(type))}`;
56267
+ const clauseReason = clauseBindingReason(value, {
56268
+ argumentType: type,
56269
+ constants: schema.argument_constants?.[name]
56270
+ });
56271
+ if (clauseReason !== null)
56272
+ return participant ? `The value "${value}" is not a binding: ${clauseReason}. Bind a noun of at most 3 words. ${noParticipantGuidance(String(type))}` : `The value "${value}" is not a binding: ${clauseReason}. Bind a noun of at most 3 words, or the requirement's subject key.`;
56060
56273
  if (!value.trim() || isGenericPlaceholder(value))
56061
- return "The claim text names no value for this argument.";
56274
+ return participant ? noParticipantGuidance(String(type)) : "The claim text names no value for this argument.";
56062
56275
  if (provenance === "inferred")
56063
56276
  return `The value "${value}" was inferred and does not appear in the claim text; confirm it or pass the exact value.`;
56064
56277
  if (schema.argument_constants?.[name])
@@ -56068,12 +56281,25 @@ function unboundReason(candidate, name, value, text) {
56068
56281
  function buildBindingHints(candidate, text, requirementSubjects = []) {
56069
56282
  const schema = candidate.schema;
56070
56283
  const parsedExamples = schema.examples.map(exampleArguments);
56284
+ const namesSubject = schema.argument_names.includes("subject");
56071
56285
  return candidate.unbound_arguments.map((name) => {
56286
+ if (name === "subject_key" && !namesSubject)
56287
+ return {
56288
+ argument: name,
56289
+ position: -1,
56290
+ type: "subject_key",
56291
+ description: "The subject the predicate fact is about; recorded as its subject_key because the schema names no subject argument.",
56292
+ examples: requirementSubjects.slice(0, MAX_EXAMPLES),
56293
+ currentValue: candidate.subject_key ?? "",
56294
+ provenance: "placeholder",
56295
+ reason: `The ${schema.predicate_name} schema does not name the requirement's subject, so kb_check pairs the predicate with the subject fact only through subject_key. Pass subjectHint with one of the subjects the requirement constrains.`
56296
+ };
56072
56297
  const position = schema.argument_names.indexOf(name);
56073
56298
  const constants = schema.argument_constants?.[name];
56074
56299
  const exampleValues = parsedExamples.map((args) => args[position]).filter((value) => typeof value === "string");
56300
+ const offersSubjects = name === "subject" || !namesSubject && schema.argument_types[position] === "entity";
56075
56301
  const examples = Array.from(new Set([
56076
- ...name === "subject" ? requirementSubjects : [],
56302
+ ...offersSubjects ? requirementSubjects : [],
56077
56303
  ...constants ?? [],
56078
56304
  ...exampleValues
56079
56305
  ])).slice(0, MAX_EXAMPLES);
@@ -56088,7 +56314,7 @@ function buildBindingHints(candidate, text, requirementSubjects = []) {
56088
56314
  examples,
56089
56315
  currentValue: current,
56090
56316
  provenance: candidate.binding_provenance_by_argument[name] ?? "placeholder",
56091
- reason: unboundReason(candidate, name, current, text)
56317
+ reason: name === "subject" && candidate.subject_pairing === "unpaired" && bindingCanBeApplied(candidate.binding_provenance_by_argument[name] ?? "placeholder") ? `The value "${current}" is not a subject the requirement constrains (${requirementSubjects.join(", ")}), so kb_check would not pair the predicate with the subject fact. Bind one of them.` : unboundReason(candidate, name, current, text, requirementSubjects)
56092
56318
  };
56093
56319
  });
56094
56320
  }
@@ -56275,8 +56501,8 @@ async function constrainedSubjectKeys(prolog, requirementId, warnings) {
56275
56501
  async function handleKbSuggestPredicates(prolog, args, context) {
56276
56502
  const text = normalizeText2(args.text);
56277
56503
  const warnings = [];
56278
- const requirementSubjects = hasSubjectHint(args.subjectHint) ? [] : await constrainedSubjectKeys(prolog, args.requirementId, warnings);
56279
- const requirementSubject = requirementSubjects.length === 1 ? requirementSubjects[0] : undefined;
56504
+ const requirementSubjects = await constrainedSubjectKeys(prolog, args.requirementId, warnings);
56505
+ const requirementSubject = !hasSubjectHint(args.subjectHint) && requirementSubjects.length === 1 ? requirementSubjects[0] : undefined;
56280
56506
  const subject = inferSubject(text, args.subjectHint, {
56281
56507
  requirementId: args.requirementId,
56282
56508
  subjectKey: requirementSubject
@@ -56322,7 +56548,8 @@ async function handleKbSuggestPredicates(prolog, args, context) {
56322
56548
  applicabilityScore: applicability.applicabilityScore,
56323
56549
  scoreComponents: ranked.components,
56324
56550
  explicitSubject: Boolean(args.subjectHint?.trim()),
56325
- ...requirementSubject ? { requirementSubject } : {}
56551
+ ...requirementSubject ? { requirementSubject } : {},
56552
+ constrainedSubjects: requirementSubjects
56326
56553
  });
56327
56554
  });
56328
56555
  const evaluatedCandidates = withMarginRejection(initialCandidates).sort((left, right) => {
@@ -56358,6 +56585,9 @@ async function handleKbSuggestPredicates(prolog, args, context) {
56358
56585
  warnings.push(`${args.requirementId} already grounds this claim (${claimKey}) through ${groundingSummary}. A modeled claim takes exactly one logical grounding relationship, so adding requires_predicate beside it fails the proposition-complete rule. ${replacementPlan ? "Keep the existing grounding, or follow replacementPlan to swap it for the predicate." : "Keep the existing grounding; no predicate replacement is available yet."}`);
56359
56586
  }
56360
56587
  const bindingHints = recommendedAction === "provide_argument_bindings" && recommendedCandidate ? buildBindingHints(recommendedCandidate, text, requirementSubjects) : [];
56588
+ if (recommendedCandidate?.subject_pairing === "unpaired") {
56589
+ warnings.push(unpairedSubjectWarning(recommendedCandidate, args, requirementSubjects));
56590
+ }
56361
56591
  const recommendedPredicateSchema = !recommendedCandidate && !unavailableSchema ? buildPredicateSchemaDraft(text, subject) : null;
56362
56592
  const groundedPrefix = alreadyGrounded ? `${args.requirementId} already grounds this claim through ${groundingSummary}. ` : "";
56363
56593
  const textSummary = groundedPrefix + (replacementPlan ? `To use ${completeCandidate?.predicate_name} instead, follow replacementPlan and link requires_predicate to ${plannedFactId}; otherwise keep the existing grounding.` : completeCandidate ? `Suggested ${candidates.length} predicate candidate(s). Top applicable match: ${completeCandidate.predicate_name}. Apply the predicate fact ${plannedFactId}, then link requires_predicate to that fact id (not a candidate id).` : recommendedCandidate ? `Matched ${recommendedCandidate.predicate_name}, but exact reviewed values are still required for: ${recommendedCandidate.unbound_arguments.join(", ")}. Bind them from the claim text: ${describeBindingHints(bindingHints)}. A value that repeats an argument name or a stop word stays unbound. No apply plan was generated.` : unavailableSchema ? `Requested predicate schema ${args.schemaId} is unavailable or semantically inapplicable. No apply plan was generated.` : alreadyGrounded ? "No predicate candidate passed the semantic applicability gate; keep the existing grounding and record the ontology-gap observation in applyPlan so the missing schema stays visible." : "No predicate candidate passed the semantic applicability gate; record an ontology gap and review the generated schema draft instead of silently writing prose.");
@@ -56385,6 +56615,12 @@ async function handleKbSuggestPredicates(prolog, args, context) {
56385
56615
  applyPlan
56386
56616
  };
56387
56617
  }
56618
+ function unpairedSubjectWarning(candidate, args, constrainedSubjects) {
56619
+ const subjects = constrainedSubjects.join(", ");
56620
+ const schemaNamesSubject = candidate.schema.argument_names.includes("subject");
56621
+ const cause = schemaNamesSubject ? `its subject argument is ${candidate.subject_key ?? "unbound"}, not a subject ${args.requirementId} constrains (${subjects})` : `the ${candidate.predicate_name} schema does not name the requirement's subject (its arguments are ${candidate.schema.argument_names.join(", ")}) and its subject_key ${candidate.subject_key === null ? "cannot be chosen" : `${candidate.subject_key} is not`} one of the subjects ${args.requirementId} constrains (${subjects})`;
56622
+ return `${candidate.predicate_name} is not offered for grounding because ${cause}, so kb_check would report strict-req-fact-pairing after the link. Pass subjectHint with one of ${subjects} and retry.`;
56623
+ }
56388
56624
  async function storedRequirementProperties(prolog, requirementId, warnings) {
56389
56625
  if (prolog === null)
56390
56626
  return null;
@@ -56413,8 +56649,14 @@ function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, exi
56413
56649
  relationships
56414
56650
  });
56415
56651
  const restate = stored === null ? `add the requirement's stored title and status as properties (they could not be read), keep this relationship only` : "the properties restate the stored title, status and metadata; kb_upsert keeps the stored proposition ledger";
56652
+ const transientRules = ["logic-coverage", "strict-req-fact-pairing"];
56416
56653
  return {
56417
56654
  relationshipTarget: factId,
56655
+ expected: {
56656
+ kbCheckAfterStep: [[], transientRules, []],
56657
+ kbCheckAfterLastStep: [],
56658
+ rollbackWhen: "kb_check after the last step is not clean"
56659
+ },
56418
56660
  steps: [
56419
56661
  {
56420
56662
  operation: "kb_upsert",
@@ -56439,9 +56681,9 @@ function buildGroundingReplacementPlan(requirementId, factId, predicatePlan, exi
56439
56681
  rollback: {
56440
56682
  operation: "kb_upsert",
56441
56683
  input: requirementUpsert(existing.map((row) => row.relationship)),
56442
- reason: "Only if the last step fails: restore the retracted grounding link so the claim is grounded again."
56684
+ reason: `Only if kb_check after the last step is not clean (it still reports ${transientRules.join(" or ")} for ${requirementId}, or the step failed): restore the retracted grounding link so the claim is grounded again.`
56443
56685
  },
56444
- instructions: `Only replace the grounding when the predicate states the claim at least as precisely as ${existing.map((row) => row.factId).join(", ")}. Apply the steps unchanged, in order and back to back: linking requires_predicate before the retraction is rejected because the claim would have two groundings, and between the retraction and the link the claim is ungrounded, so kb_check reports logic-coverage for ${requirementId} until the last step lands. If the last step fails, apply rollback. Run kb_check after the last step.`
56686
+ instructions: `Only replace the grounding when the predicate states the claim at least as precisely as ${existing.map((row) => row.factId).join(", ")}. Apply the steps unchanged, in order and back to back: linking requires_predicate before the retraction is rejected because the claim would have two groundings, and between the retraction and the link the claim is ungrounded and its subject unpaired, so kb_check reports both ${transientRules.join(" and ")} for ${requirementId} until the last step lands (see expected.kbCheckAfterStep). Run kb_check after the last step; if it is not clean, apply rollback.`
56445
56687
  };
56446
56688
  }
56447
56689
  async function executeSuggestPredicates(args, context) {
@@ -60351,7 +60593,7 @@ var require_gray_matter = __commonJS(function(exports2, module2) {
60351
60593
  });
60352
60594
 
60353
60595
  // ../cli/dist/public/skill-system/validation.js
60354
- import { existsSync as existsSync24, readFileSync as readFileSync25, realpathSync as realpathSync7, statSync as statSync9 } from "node:fs";
60596
+ import { existsSync as existsSync24, readFileSync as readFileSync26, realpathSync as realpathSync7, statSync as statSync9 } from "node:fs";
60355
60597
  import { dirname as dirname9, resolve as resolve15 } from "node:path";
60356
60598
  function assertMaxBytes(pathLike, maxBytes) {
60357
60599
  const size = statSync9(pathLike).size;
@@ -60361,7 +60603,7 @@ function assertMaxBytes(pathLike, maxBytes) {
60361
60603
  function parseSkillBundle(rootDir) {
60362
60604
  const path = resolve15(rootDir, SKILL_FILE_NAME);
60363
60605
  assertMaxBytes(path, SKILL_MARKDOWN_MAX_BYTES);
60364
- const parsed = import_gray_matter.default(readFileSync25(path, "utf8"));
60606
+ const parsed = import_gray_matter.default(readFileSync26(path, "utf8"));
60365
60607
  const [error] = validateManifestData(parsed.data);
60366
60608
  if (error)
60367
60609
  throw error;
@@ -60425,9 +60667,9 @@ var init_validation3 = __esm(() => {
60425
60667
  });
60426
60668
 
60427
60669
  // ../cli/dist/public/skill-system/loader.js
60428
- import { existsSync as existsSync25, readFileSync as readFileSync26, readdirSync as readdirSync7, realpathSync as realpathSync8 } from "node:fs";
60670
+ import { existsSync as existsSync25, readFileSync as readFileSync27, readdirSync as readdirSync7, realpathSync as realpathSync8 } from "node:fs";
60429
60671
  import { dirname as dirname10, join as join18, resolve as resolve16 } from "node:path";
60430
- import { fileURLToPath as fileURLToPath3 } from "node:url";
60672
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
60431
60673
  function listBundledSkills() {
60432
60674
  return listFrom(bundledSkillsDir);
60433
60675
  }
@@ -60472,14 +60714,14 @@ function readBundle(bundle, id, resourcePath) {
60472
60714
  throw new SkillResourceNotFoundError(id, resourcePath);
60473
60715
  }
60474
60716
  assertMaxBytes(candidate, RESOURCE_MAX_BYTES);
60475
- return readFileSync26(candidate, "utf8");
60717
+ return readFileSync27(candidate, "utf8");
60476
60718
  }
60477
60719
  var defaultBundledSkillsDir, bundledSkillsDir;
60478
60720
  var init_loader = __esm(() => {
60479
60721
  init_errors();
60480
60722
  init_paths();
60481
60723
  init_validation3();
60482
- defaultBundledSkillsDir = resolve16(dirname10(fileURLToPath3(import.meta.url)), "../skills");
60724
+ defaultBundledSkillsDir = resolve16(dirname10(fileURLToPath4(import.meta.url)), "../skills");
60483
60725
  bundledSkillsDir = defaultBundledSkillsDir;
60484
60726
  });
60485
60727
 
@@ -62272,17 +62514,17 @@ var init_audit = __esm(() => {
62272
62514
  import { createHash as createHash27 } from "node:crypto";
62273
62515
  import { randomUUID as randomUUID2 } from "node:crypto";
62274
62516
  import fs6 from "node:fs";
62275
- import path50 from "node:path";
62517
+ import path51 from "node:path";
62276
62518
  import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
62277
62519
  function digest3(value) {
62278
62520
  return createHash27("sha256").update(value).digest("hex");
62279
62521
  }
62280
62522
  function pendingReceiptPath(workspaceRoot, relativePath) {
62281
- return path50.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${digest3(relativePath)}.json`);
62523
+ return path51.join(workspaceRoot, ".kb", "recovery", "pending-sources", `${digest3(relativePath)}.json`);
62282
62524
  }
62283
62525
  function writePendingSourceReceipt(workspaceRoot, relativePath, afterHash) {
62284
62526
  const receiptPath = pendingReceiptPath(workspaceRoot, relativePath);
62285
- fs6.mkdirSync(path50.dirname(receiptPath), { recursive: true, mode: 448 });
62527
+ fs6.mkdirSync(path51.dirname(receiptPath), { recursive: true, mode: 448 });
62286
62528
  fs6.writeFileSync(receiptPath, `${JSON.stringify({
62287
62529
  version: 1,
62288
62530
  path: relativePath,
@@ -62310,34 +62552,34 @@ function authoredPath(value) {
62310
62552
  return normalized;
62311
62553
  }
62312
62554
  function resolveContainedSourcePath(workspaceRoot, relative) {
62313
- if (path50.isAbsolute(relative) || relative.split(/[\\/]/).some((part) => part === ".." || part === "")) {
62555
+ if (path51.isAbsolute(relative) || relative.split(/[\\/]/).some((part) => part === ".." || part === "")) {
62314
62556
  throw new OperationError("SOURCE_PATH_INVALID", `document.path must be a workspace-relative path without traversal: ${relative}`);
62315
62557
  }
62316
- const absolute = path50.resolve(workspaceRoot, relative);
62317
- const root = path50.resolve(workspaceRoot);
62318
- if (absolute !== root && !absolute.startsWith(`${root}${path50.sep}`)) {
62558
+ const absolute = path51.resolve(workspaceRoot, relative);
62559
+ const root = path51.resolve(workspaceRoot);
62560
+ if (absolute !== root && !absolute.startsWith(`${root}${path51.sep}`)) {
62319
62561
  throw new OperationError("SOURCE_PATH_INVALID", `document.path escapes the workspace: ${relative}`);
62320
62562
  }
62321
- const workspaceRelative = path50.relative(root, absolute).replaceAll(path50.sep, "/");
62563
+ const workspaceRelative = path51.relative(root, absolute).replaceAll(path51.sep, "/");
62322
62564
  if (isDerivedKbPath(workspaceRelative)) {
62323
62565
  throw new OperationError("SOURCE_PATH_INVALID", `document.path cannot target Kibi's derived state under ${workspaceRelative}: ${relative}`);
62324
62566
  }
62325
62567
  const realRoot = canonicalFilesystemPath(root);
62326
62568
  const real = canonicalFilesystemPath(absolute);
62327
- if (real !== realRoot && !real.startsWith(`${realRoot}${path50.sep}`)) {
62569
+ if (real !== realRoot && !real.startsWith(`${realRoot}${path51.sep}`)) {
62328
62570
  throw new OperationError("SOURCE_PATH_INVALID", `document.path resolves outside the workspace: ${relative}`);
62329
62571
  }
62330
62572
  return absolute;
62331
62573
  }
62332
62574
  function normalizeAuthoredSourcePath(workspaceRoot, source) {
62333
62575
  const normalized = source.replaceAll("\\", "/");
62334
- const root = path50.resolve(workspaceRoot);
62576
+ const root = path51.resolve(workspaceRoot);
62335
62577
  let relative = normalized;
62336
- if (path50.isAbsolute(normalized)) {
62337
- const absolute = path50.resolve(normalized);
62338
- relative = absolute === root || absolute.startsWith(`${root}${path50.sep}`) ? path50.relative(root, absolute) : path50.relative(canonicalFilesystemPath(root), canonicalFilesystemPath(absolute));
62578
+ if (path51.isAbsolute(normalized)) {
62579
+ const absolute = path51.resolve(normalized);
62580
+ relative = absolute === root || absolute.startsWith(`${root}${path51.sep}`) ? path51.relative(root, absolute) : path51.relative(canonicalFilesystemPath(root), canonicalFilesystemPath(absolute));
62339
62581
  }
62340
- return path50.relative(path50.resolve(workspaceRoot), resolveContainedSourcePath(workspaceRoot, relative)).replaceAll(path50.sep, "/");
62582
+ return path51.relative(path51.resolve(workspaceRoot), resolveContainedSourcePath(workspaceRoot, relative)).replaceAll(path51.sep, "/");
62341
62583
  }
62342
62584
  function bodyAndFrontmatter(content) {
62343
62585
  if (!content.startsWith("---"))
@@ -62383,13 +62625,13 @@ function sourcePath(context, input, entity, existing) {
62383
62625
  if (!relative) {
62384
62626
  throw new OperationError("DOCUMENT_PATH_REQUIRED", `No writable source target is available for ${input.type}; provide document.path explicitly`);
62385
62627
  }
62386
- if (path50.isAbsolute(relative)) {
62387
- const root = path50.resolve(context.workspaceRoot);
62388
- const absolute = path50.resolve(relative);
62389
- if (absolute !== root && !absolute.startsWith(`${root}${path50.sep}`)) {
62628
+ if (path51.isAbsolute(relative)) {
62629
+ const root = path51.resolve(context.workspaceRoot);
62630
+ const absolute = path51.resolve(relative);
62631
+ if (absolute !== root && !absolute.startsWith(`${root}${path51.sep}`)) {
62390
62632
  throw new OperationError("SOURCE_PATH_INVALID", `document.path resolves outside the workspace: ${relative}`);
62391
62633
  }
62392
- relative = path50.relative(root, absolute).replaceAll(path50.sep, "/");
62634
+ relative = path51.relative(root, absolute).replaceAll(path51.sep, "/");
62393
62635
  }
62394
62636
  return resolveContainedSourcePath(context.workspaceRoot, relative);
62395
62637
  }
@@ -62608,7 +62850,7 @@ function renderSymbolManifest(entity, relationships, existingContent) {
62608
62850
  return doc.toString(AUTHORED_YAML_OPTIONS);
62609
62851
  }
62610
62852
  function renderSourceDeletion(sourcePathValue, entityId, entityType, existingContent) {
62611
- const extension = path50.extname(sourcePathValue).toLowerCase();
62853
+ const extension = path51.extname(sourcePathValue).toLowerCase();
62612
62854
  if (extension === ".md" || extension === ".mdx") {
62613
62855
  const parsed = bodyAndFrontmatter(existingContent);
62614
62856
  if (String(parsed.frontmatter.id ?? "") !== entityId) {
@@ -62638,7 +62880,7 @@ function renderSourceDeletion(sourcePathValue, entityId, entityType, existingCon
62638
62880
  throw new OperationError("SOURCE_FORMAT_UNSUPPORTED", `Unsupported authored source format: ${extension || "unknown"}`);
62639
62881
  }
62640
62882
  function renderMarkdownRelationshipDeletion(sourcePathValue, existingContent, selector) {
62641
- const extension = path50.extname(sourcePathValue).toLowerCase();
62883
+ const extension = path51.extname(sourcePathValue).toLowerCase();
62642
62884
  if (extension !== ".md" && extension !== ".mdx") {
62643
62885
  throw new OperationError("SOURCE_FORMAT_UNSUPPORTED", `Relationship declarations can only be patched in Markdown documents: ${sourcePathValue}`);
62644
62886
  }
@@ -62697,7 +62939,7 @@ ${frontmatter.toString(AUTHORED_YAML_OPTIONS)}---${body.startsWith(`
62697
62939
  };
62698
62940
  }
62699
62941
  function renderYamlRelationshipDeletion(sourcePathValue, existingContent, selector) {
62700
- const extension = path50.extname(sourcePathValue).toLowerCase();
62942
+ const extension = path51.extname(sourcePathValue).toLowerCase();
62701
62943
  if (extension !== ".yaml" && extension !== ".yml") {
62702
62944
  throw new OperationError("SOURCE_FORMAT_UNSUPPORTED", `Relationship declarations can only be patched in YAML symbol manifests: ${sourcePathValue}`);
62703
62945
  }
@@ -62740,7 +62982,7 @@ function renderYamlRelationshipDeletion(sourcePathValue, existingContent, select
62740
62982
  return removed ? { body: doc.toString(AUTHORED_YAML_OPTIONS), removed: true } : { body: existingContent, removed: false };
62741
62983
  }
62742
62984
  function renderSourceDocument(input, entity, existingContent, relativePath) {
62743
- const extension = path50.extname(relativePath).toLowerCase();
62985
+ const extension = path51.extname(relativePath).toLowerCase();
62744
62986
  if (extension === ".yaml" || extension === ".yml") {
62745
62987
  if (input.type !== "symbol") {
62746
62988
  throw new OperationError("SOURCE_FORMAT_UNSUPPORTED", `YAML source authoring is supported only for symbol manifests, not ${input.type}`);
@@ -62756,7 +62998,7 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
62756
62998
  if (!context?.fs)
62757
62999
  return null;
62758
63000
  const absolute = sourcePath(context, input, entity, existing);
62759
- const relative = path50.relative(context.workspaceRoot, absolute).replaceAll("\\", "/");
63001
+ const relative = path51.relative(context.workspaceRoot, absolute).replaceAll("\\", "/");
62760
63002
  let before;
62761
63003
  try {
62762
63004
  before = await context.fs.readFile(absolute);
@@ -62764,7 +63006,7 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
62764
63006
  before = undefined;
62765
63007
  }
62766
63008
  const after = before !== undefined && sourceDocumentOverride !== undefined ? sourceDocumentOverride : renderSourceDocument(input, entity, before, relative);
62767
- await context.fs.mkdir(path50.dirname(absolute));
63009
+ await context.fs.mkdir(path51.dirname(absolute));
62768
63010
  const temporary = `${absolute}.kibi-source-${process.pid}-${randomUUID2()}`;
62769
63011
  try {
62770
63012
  await context.fs.writeFile(temporary, after);
@@ -62848,7 +63090,7 @@ async function writeSourceForUpsert(input, entity, existing, context, sourceDocu
62848
63090
  return { receipt, rollback };
62849
63091
  }
62850
63092
  function canonicalSourcePath(context, input, entity, existing) {
62851
- return path50.relative(context.workspaceRoot, sourcePath(context, input, entity, existing)).replaceAll(path50.sep, "/");
63093
+ return path51.relative(context.workspaceRoot, sourcePath(context, input, entity, existing)).replaceAll(path51.sep, "/");
62852
63094
  }
62853
63095
  var AUTHORED_YAML_OPTIONS, GENERATED_SYMBOL_FIELDS;
62854
63096
  var init_source_authoring = __esm(() => {
@@ -62870,8 +63112,8 @@ var init_source_authoring = __esm(() => {
62870
63112
 
62871
63113
  // ../cli/dist/operations/mutation/plan-apply-journal.js
62872
63114
  import { createHash as createHash28, randomUUID as randomUUID3 } from "node:crypto";
62873
- import { closeSync as closeSync3, existsSync as existsSync26, fsyncSync as fsyncSync2, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync27, readdirSync as readdirSync8, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "node:fs";
62874
- import path51 from "node:path";
63115
+ import { closeSync as closeSync3, existsSync as existsSync26, fsyncSync as fsyncSync2, mkdirSync as mkdirSync8, openSync as openSync3, readFileSync as readFileSync28, readdirSync as readdirSync8, renameSync as renameSync5, statSync as statSync10, unlinkSync as unlinkSync5, writeSync as writeSync2 } from "node:fs";
63116
+ import path52 from "node:path";
62875
63117
  function planApplyJournalId(planHash) {
62876
63118
  return `plan-apply-${planHash.slice(0, 16).toLowerCase()}`;
62877
63119
  }
@@ -62888,8 +63130,8 @@ function journalLocation(context) {
62888
63130
  const attachment = context.branchAttachment ?? resolveBranchAttachment(context.workspaceRoot);
62889
63131
  if ("error" in attachment)
62890
63132
  return null;
62891
- const storeDirectory = path51.join(attachment.storePath, JOURNAL_DIRECTORY);
62892
- const fallback = path51.join(path51.resolve(context.workspaceRoot), ".kb", "recovery", JOURNAL_DIRECTORY, branchStoreKey(attachment.kbBranch));
63133
+ const storeDirectory = path52.join(attachment.storePath, JOURNAL_DIRECTORY);
63134
+ const fallback = path52.join(path52.resolve(context.workspaceRoot), ".kb", "recovery", JOURNAL_DIRECTORY, branchStoreKey(attachment.kbBranch));
62893
63135
  let storeReady = false;
62894
63136
  try {
62895
63137
  storeReady = statSync10(attachment.storePath).isDirectory() && existsSync26(branchStoreManifestPath(attachment.storePath));
@@ -62915,7 +63157,7 @@ function fsyncDirectory(directory) {
62915
63157
  } catch {}
62916
63158
  }
62917
63159
  function writeJournal(journalPath, journal) {
62918
- const directory = path51.dirname(journalPath);
63160
+ const directory = path52.dirname(journalPath);
62919
63161
  mkdirSync8(directory, { recursive: true, mode: 448 });
62920
63162
  const temporary = `${journalPath}.tmp-${process.pid}-${randomUUID3()}`;
62921
63163
  try {
@@ -62945,7 +63187,7 @@ function isFileWrite(value) {
62945
63187
  const entry = value;
62946
63188
  const before = entry.before;
62947
63189
  const after = entry.after;
62948
- return typeof entry.path === "string" && entry.path !== "" && !path51.isAbsolute(entry.path) && !entry.path.split(/[\\/]/).includes("..") && (entry.origin === "plan" || entry.origin === "entity-document" || entry.origin === "relationship-shard") && (entry.mode === "write" || entry.mode === "delete") && (before === null ? entry.beforeHash === null : typeof before === "string" && entry.beforeHash === contentHash(before)) && (after === null ? entry.afterHash === null : typeof after === "string" && entry.afterHash === contentHash(after)) && entry.mode === "delete" === (after === null);
63190
+ return typeof entry.path === "string" && entry.path !== "" && !path52.isAbsolute(entry.path) && !entry.path.split(/[\\/]/).includes("..") && (entry.origin === "plan" || entry.origin === "entity-document" || entry.origin === "relationship-shard") && (entry.mode === "write" || entry.mode === "delete") && (before === null ? entry.beforeHash === null : typeof before === "string" && entry.beforeHash === contentHash(before)) && (after === null ? entry.afterHash === null : typeof after === "string" && entry.afterHash === contentHash(after)) && entry.mode === "delete" === (after === null);
62949
63191
  }
62950
63192
  function parseJournal(journalId, text) {
62951
63193
  const parsed = JSON.parse(text);
@@ -62965,10 +63207,10 @@ function unrecoverableJournal(journalPath, detail) {
62965
63207
  throw new OperationError("PARTIAL_COMMIT_REPAIR_REQUIRED", `Plan application journal ${journalPath} cannot be recovered automatically: ${detail}. Kibi will not apply or recover plans on this branch until it is resolved: restore each listed file to its journaled before or after bytes and retry, or reconcile the workspace and branch store by hand (kibi sync) and remove the journal`, false);
62966
63208
  }
62967
63209
  function readJournalFile(journalPath) {
62968
- const journalId = path51.basename(journalPath, ".json");
63210
+ const journalId = path52.basename(journalPath, ".json");
62969
63211
  let text;
62970
63212
  try {
62971
- text = readFileSync27(journalPath, "utf8");
63213
+ text = readFileSync28(journalPath, "utf8");
62972
63214
  } catch (error) {
62973
63215
  unrecoverableJournal(journalPath, `unreadable (${errorText(error)})`);
62974
63216
  }
@@ -62985,9 +63227,9 @@ function openPlanApplyJournal(context, planHash) {
62985
63227
  }
62986
63228
  const journalId = planApplyJournalId(planHash);
62987
63229
  let existing = null;
62988
- let journalPath = path51.join(location.primary, `${journalId}.json`);
63230
+ let journalPath = path52.join(location.primary, `${journalId}.json`);
62989
63231
  for (const directory of location.all) {
62990
- const candidate = path51.join(directory, `${journalId}.json`);
63232
+ const candidate = path52.join(directory, `${journalId}.json`);
62991
63233
  if (existsSync26(candidate)) {
62992
63234
  existing = readJournalFile(candidate);
62993
63235
  journalPath = candidate;
@@ -63028,7 +63270,7 @@ async function currentHash(fsPort, absolute) {
63028
63270
  }
63029
63271
  }
63030
63272
  async function publishWorkspaceFile(fsPort, absolute, content) {
63031
- await fsPort.mkdir(path51.dirname(absolute));
63273
+ await fsPort.mkdir(path52.dirname(absolute));
63032
63274
  if (fsPort.rename) {
63033
63275
  const staged = `${absolute}.kibi-stage-${process.pid}-${randomUUID3()}`;
63034
63276
  try {
@@ -63049,7 +63291,7 @@ async function publishWorkspaceFile(fsPort, absolute, content) {
63049
63291
  await fsPort.fsync(absolute);
63050
63292
  }
63051
63293
  if (fsPort.fsync)
63052
- await fsPort.fsync(path51.dirname(absolute)).catch(() => {
63294
+ await fsPort.fsync(path52.dirname(absolute)).catch(() => {
63053
63295
  return;
63054
63296
  });
63055
63297
  }
@@ -63064,12 +63306,12 @@ async function removeWorkspaceFile(fsPort, absolute, relative) {
63064
63306
  throw error;
63065
63307
  }
63066
63308
  if (fsPort.fsync)
63067
- await fsPort.fsync(path51.dirname(absolute)).catch(() => {
63309
+ await fsPort.fsync(path52.dirname(absolute)).catch(() => {
63068
63310
  return;
63069
63311
  });
63070
63312
  }
63071
63313
  async function setFile(fsPort, workspaceRoot, relative, content) {
63072
- const absolute = path51.resolve(workspaceRoot, relative);
63314
+ const absolute = path52.resolve(workspaceRoot, relative);
63073
63315
  if (content === null)
63074
63316
  await removeWorkspaceFile(fsPort, absolute, relative);
63075
63317
  else
@@ -63084,7 +63326,7 @@ async function moveJournaledFiles(fsPort, workspaceRoot, journalPath, files, sid
63084
63326
  const pending = [];
63085
63327
  const conflicts = [];
63086
63328
  for (const file of files) {
63087
- const actual = await currentHash(fsPort, path51.resolve(workspaceRoot, file.path));
63329
+ const actual = await currentHash(fsPort, path52.resolve(workspaceRoot, file.path));
63088
63330
  const wanted = side === "before" ? file.beforeHash : file.afterHash;
63089
63331
  if (actual === wanted)
63090
63332
  continue;
@@ -63106,11 +63348,11 @@ async function moveJournaledFiles(fsPort, workspaceRoot, journalPath, files, sid
63106
63348
  }
63107
63349
  function removeOrphanedStagedFiles(workspaceRoot, files) {
63108
63350
  for (const file of files) {
63109
- const absolute = path51.resolve(workspaceRoot, file.path);
63110
- const prefix = `${path51.basename(absolute)}.kibi-stage-`;
63351
+ const absolute = path52.resolve(workspaceRoot, file.path);
63352
+ const prefix = `${path52.basename(absolute)}.kibi-stage-`;
63111
63353
  let names;
63112
63354
  try {
63113
- names = readdirSync8(path51.dirname(absolute));
63355
+ names = readdirSync8(path52.dirname(absolute));
63114
63356
  } catch {
63115
63357
  continue;
63116
63358
  }
@@ -63118,7 +63360,7 @@ function removeOrphanedStagedFiles(workspaceRoot, files) {
63118
63360
  if (!name.startsWith(prefix))
63119
63361
  continue;
63120
63362
  try {
63121
- unlinkSync5(path51.join(path51.dirname(absolute), name));
63363
+ unlinkSync5(path52.join(path52.dirname(absolute), name));
63122
63364
  } catch {}
63123
63365
  }
63124
63366
  }
@@ -63232,7 +63474,7 @@ function openPlanApplyJournalById(context, journalId) {
63232
63474
  throw new Error("Plan journal recovery failed: the KB branch could not be resolved");
63233
63475
  }
63234
63476
  for (const directory of location.all) {
63235
- const candidate = path51.join(directory, `${journalId}.json`);
63477
+ const candidate = path52.join(directory, `${journalId}.json`);
63236
63478
  if (existsSync26(candidate)) {
63237
63479
  return { journalPath: candidate, journal: readJournalFile(candidate) };
63238
63480
  }
@@ -63255,7 +63497,7 @@ async function recoverPendingPlanApplyJournals(context, options2) {
63255
63497
  }
63256
63498
  for (const name of names) {
63257
63499
  if (name.endsWith(".json") && isPlanApplyJournalId(name.slice(0, -5))) {
63258
- candidates.push(path51.join(directory, name));
63500
+ candidates.push(path52.join(directory, name));
63259
63501
  }
63260
63502
  }
63261
63503
  }
@@ -63322,10 +63564,10 @@ async function saveAtomicMutation(prolog, goals, operation) {
63322
63564
  }
63323
63565
 
63324
63566
  // ../cli/dist/operations/mutation/workspace-mutation-lock.js
63325
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync28, renameSync as renameSync6, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync8 } from "node:fs";
63326
- import * as path52 from "node:path";
63567
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync29, renameSync as renameSync6, rmdirSync, unlinkSync as unlinkSync6, writeFileSync as writeFileSync8 } from "node:fs";
63568
+ import * as path53 from "node:path";
63327
63569
  function lockPath(workspaceRoot, lockFileRelative) {
63328
- return path52.join(workspaceRoot, lockFileRelative);
63570
+ return path53.join(workspaceRoot, lockFileRelative);
63329
63571
  }
63330
63572
  function randomToken() {
63331
63573
  return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
@@ -63379,7 +63621,7 @@ function removeLockDirectory(fileSystem, target) {
63379
63621
  const result = retryTransientFilesystemOperation(() => fileSystem.rmdirSync(target));
63380
63622
  if (result.ok)
63381
63623
  return;
63382
- const ownerPath = path52.join(target, OWNER_FILE);
63624
+ const ownerPath = path53.join(target, OWNER_FILE);
63383
63625
  throw new WorkspaceMutationLockError(`failed to remove workspace mutation lock directory at ${target} after ${result.attempts} attempt(s): ${errorDetail(result.error)}; lock remains fail-closed. ${manualCleanupGuidance(target, ownerPath)}`);
63384
63626
  }
63385
63627
  function removeLockOwner(fileSystem, target, ownerPath, ignoreMissing) {
@@ -63450,7 +63692,7 @@ function reclaimDeadLock(fileSystem, target, holder, token) {
63450
63692
  return "changed";
63451
63693
  throw new WorkspaceMutationLockError(`failed to reclaim workspace mutation lock at ${target} from dead pid ${holder.pid}: ${errorDetail(error)}`);
63452
63694
  }
63453
- const tombstoneOwner = path52.join(tombstone, OWNER_FILE);
63695
+ const tombstoneOwner = path53.join(tombstone, OWNER_FILE);
63454
63696
  let moved = null;
63455
63697
  try {
63456
63698
  moved = readLockRecord(fileSystem.readFileSync(tombstoneOwner));
@@ -63511,10 +63753,10 @@ async function acquireWorkspaceMutationLock(workspaceRoot, options2 = {}) {
63511
63753
  const fileSystem = options2.fileSystem ?? NODE_FILE_SYSTEM;
63512
63754
  const isProcessAlive = options2.isProcessAlive ?? defaultIsProcessAlive;
63513
63755
  const target = lockPath(workspaceRoot, options2.lockFileRelative ?? DEFAULT_LOCK_FILE_RELATIVE);
63514
- const ownerPath = path52.join(target, OWNER_FILE);
63756
+ const ownerPath = path53.join(target, OWNER_FILE);
63515
63757
  const token = randomToken();
63516
63758
  const deadline = now() + timeoutMs;
63517
- const parentPath = path52.dirname(target);
63759
+ const parentPath = path53.dirname(target);
63518
63760
  const parentResult = retryTransientFilesystemOperation(() => fileSystem.mkdirSync(parentPath, { recursive: true }));
63519
63761
  if (!parentResult.ok) {
63520
63762
  throw new WorkspaceMutationLockError(`failed to create workspace mutation lock parent at ${parentPath} after ${parentResult.attempts} attempt(s): ${errorDetail(parentResult.error)}`);
@@ -63637,12 +63879,12 @@ async function acquireWorkspaceMutationLock(workspaceRoot, options2 = {}) {
63637
63879
  var DEFAULT_LOCK_FILE_RELATIVE, OWNER_FILE = "owner.json", DEFAULT_TIMEOUT_MS = 15000, RETRY_INTERVAL_MS = 25, MAX_RELEASE_FILESYSTEM_ATTEMPTS = 3, MAX_MISSING_OWNER_REREADS = 4, NODE_FILE_SYSTEM, WorkspaceMutationLockError;
63638
63880
  var init_workspace_mutation_lock = __esm(() => {
63639
63881
  init_cli_errors();
63640
- DEFAULT_LOCK_FILE_RELATIVE = path52.join(".kb", "recovery", "source-authoring.lock");
63882
+ DEFAULT_LOCK_FILE_RELATIVE = path53.join(".kb", "recovery", "source-authoring.lock");
63641
63883
  NODE_FILE_SYSTEM = {
63642
63884
  mkdirSync: (target, options2) => {
63643
63885
  mkdirSync9(target, options2);
63644
63886
  },
63645
- readFileSync: (target) => readFileSync28(target, "utf8"),
63887
+ readFileSync: (target) => readFileSync29(target, "utf8"),
63646
63888
  writeFileSync: (target, data, options2) => {
63647
63889
  writeFileSync8(target, data, options2);
63648
63890
  },
@@ -63657,8 +63899,8 @@ var init_workspace_mutation_lock = __esm(() => {
63657
63899
 
63658
63900
  // ../cli/dist/operations/mutation/delete.js
63659
63901
  import { createHash as createHash29, randomUUID as randomUUID4 } from "node:crypto";
63660
- import { existsSync as existsSync27, readFileSync as readFileSync29, writeFileSync as writeFileSync9 } from "node:fs";
63661
- import path53 from "node:path";
63902
+ import { existsSync as existsSync27, readFileSync as readFileSync30, writeFileSync as writeFileSync9 } from "node:fs";
63903
+ import path54 from "node:path";
63662
63904
  function requireProlog3(context) {
63663
63905
  if (context.prolog === undefined)
63664
63906
  throw new Error("Delete operation requires a Prolog runtime");
@@ -63694,7 +63936,7 @@ function sourceIsAuthored(source) {
63694
63936
  function fileHash(pathname) {
63695
63937
  if (!existsSync27(pathname))
63696
63938
  return null;
63697
- return createHash29("sha256").update(readFileSync29(pathname)).digest("hex");
63939
+ return createHash29("sha256").update(readFileSync30(pathname)).digest("hex");
63698
63940
  }
63699
63941
  async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted = () => {
63700
63942
  return;
@@ -63710,7 +63952,7 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
63710
63952
  if (attachment.migrationRequired && (context.branchAttachment !== undefined || context.fs !== undefined)) {
63711
63953
  throw new Error(`Delete blocked: migrate legacy branch storage first with 'kibi branch migrate --from ${attachment.kbBranch} --to ${attachment.gitBranch} --apply'`);
63712
63954
  }
63713
- const shardRoot = path53.join(context.workspaceRoot, ".kb");
63955
+ const shardRoot = path54.join(context.workspaceRoot, ".kb");
63714
63956
  let shardRecords = [];
63715
63957
  try {
63716
63958
  shardRecords = readAllShards(shardRoot);
@@ -63789,7 +64031,7 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
63789
64031
  };
63790
64032
  const originalShardBytes = new Map(listShards(shardRoot).map((shardPath) => [
63791
64033
  shardPath,
63792
- readFileSync29(shardPath, "utf8")
64034
+ readFileSync30(shardPath, "utf8")
63793
64035
  ]));
63794
64036
  const originalShardHashes = new Map(listShards(shardRoot).map((shardPath) => [shardPath, fileHash(shardPath)]));
63795
64037
  let shardRemovals;
@@ -63808,7 +64050,7 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
63808
64050
  const writeSourcePatch = async (relative, body) => {
63809
64051
  assertFilesystemCapableRuntime(context.fs);
63810
64052
  const absolute = resolveContainedSourcePath(context.workspaceRoot, relative);
63811
- await context.fs.mkdir(path53.dirname(absolute));
64053
+ await context.fs.mkdir(path54.dirname(absolute));
63812
64054
  const temporary = `${absolute}.kibi-relationship-${process.pid}-${randomUUID4()}`;
63813
64055
  try {
63814
64056
  await context.fs.writeFile(temporary, body);
@@ -63873,7 +64115,7 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
63873
64115
  const after = fileHash(shardPath);
63874
64116
  if (before === after)
63875
64117
  return [];
63876
- const relative = path53.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
64118
+ const relative = path54.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
63877
64119
  if (after !== null) {
63878
64120
  writePendingSourceReceipt(context.workspaceRoot, relative, after);
63879
64121
  }
@@ -64009,7 +64251,7 @@ async function executeDelete(input, context) {
64009
64251
  authoredRequirementIds.push(id);
64010
64252
  if (context.fs) {
64011
64253
  const relativeSource = normalizeAuthoredSourcePath(context.workspaceRoot, source);
64012
- const sourcePath = path53.join(context.workspaceRoot, relativeSource);
64254
+ const sourcePath = path54.join(context.workspaceRoot, relativeSource);
64013
64255
  try {
64014
64256
  const original = sourceBodies.get(relativeSource) ?? await context.fs.readFile(sourcePath);
64015
64257
  if (!sourceBodies.has(relativeSource)) {
@@ -64041,12 +64283,12 @@ async function executeDelete(input, context) {
64041
64283
  if (authoredIds.length > 0 && context.sourcePlanApplication !== true) {
64042
64284
  if (context.fs) {
64043
64285
  const deleted = new Set(authoredIds);
64044
- for (const shardPath of listShards(path53.join(context.workspaceRoot, ".kb"))) {
64286
+ for (const shardPath of listShards(path54.join(context.workspaceRoot, ".kb"))) {
64045
64287
  const selectors = readShard(shardPath).filter((record) => deleted.has(record.from)).map(({ type, from, to }) => ({ type, from, to }));
64046
64288
  if (selectors.length === 0)
64047
64289
  continue;
64048
- const relativeShard = path53.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
64049
- const original = readFileSync29(shardPath, "utf8");
64290
+ const relativeShard = path54.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
64291
+ const original = readFileSync30(shardPath, "utf8");
64050
64292
  const body = renderShardWithout(original, selectors, shardPath);
64051
64293
  const beforeHash = createHash29("sha256").update(original).digest("hex");
64052
64294
  sourceHashes[relativeShard] = beforeHash;
@@ -64144,13 +64386,13 @@ var init_delete = __esm(() => {
64144
64386
  });
64145
64387
 
64146
64388
  // ../cli/dist/operations/mutation/context-warning.js
64147
- import { readFileSync as readFileSync30 } from "node:fs";
64148
- import path54 from "node:path";
64389
+ import { readFileSync as readFileSync31 } from "node:fs";
64390
+ import path55 from "node:path";
64149
64391
  function readBody(workspaceRoot, source) {
64150
64392
  if (typeof source !== "string" || !source.endsWith(".md"))
64151
64393
  return;
64152
64394
  try {
64153
- return readAuthoredEntity(readFileSync30(path54.resolve(workspaceRoot, source), "utf8"), source)?.body ?? undefined;
64395
+ return readAuthoredEntity(readFileSync31(path55.resolve(workspaceRoot, source), "utf8"), source)?.body ?? undefined;
64154
64396
  } catch {
64155
64397
  return;
64156
64398
  }
@@ -64190,7 +64432,7 @@ var init_context_warning = __esm(() => {
64190
64432
  });
64191
64433
 
64192
64434
  // ../cli/dist/operations/mutation/symbol-granularity.js
64193
- import path55 from "node:path";
64435
+ import path56 from "node:path";
64194
64436
  import { collectGranularityCandidates } from "kibi-plugin-builtin";
64195
64437
  function candidate(name, kind) {
64196
64438
  return { name, kind, role: inferSymbolRole(kind) };
@@ -64215,7 +64457,7 @@ async function validateSymbolGranularity(entity, relationships, context) {
64215
64457
  const fs = context.fs;
64216
64458
  if (fs === undefined)
64217
64459
  return;
64218
- const sourcePath = path55.isAbsolute(entity.sourceFile) ? entity.sourceFile : path55.resolve(context.workspaceRoot, entity.sourceFile);
64460
+ const sourcePath = path56.isAbsolute(entity.sourceFile) ? entity.sourceFile : path56.resolve(context.workspaceRoot, entity.sourceFile);
64219
64461
  let content;
64220
64462
  try {
64221
64463
  const stat = await fs.stat(sourcePath);
@@ -64547,10 +64789,10 @@ var init_saga = __esm(() => {
64547
64789
  });
64548
64790
 
64549
64791
  // ../cli/dist/operations/mutation/symbol-compiler-lock.js
64550
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync31, rmdirSync as rmdirSync2, unlinkSync as unlinkSync7, writeFileSync as writeFileSync10 } from "node:fs";
64551
- import * as path56 from "node:path";
64792
+ import { mkdirSync as mkdirSync10, readFileSync as readFileSync32, rmdirSync as rmdirSync2, unlinkSync as unlinkSync7, writeFileSync as writeFileSync10 } from "node:fs";
64793
+ import * as path57 from "node:path";
64552
64794
  function lockPath2(workspaceRoot) {
64553
- return path56.join(workspaceRoot, LOCK_FILE_RELATIVE);
64795
+ return path57.join(workspaceRoot, LOCK_FILE_RELATIVE);
64554
64796
  }
64555
64797
  function randomToken2() {
64556
64798
  return `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
@@ -64604,7 +64846,7 @@ function removeLockDirectory2(fileSystem, target) {
64604
64846
  const result = retryTransientFilesystemOperation2(() => fileSystem.rmdirSync(target));
64605
64847
  if (result.ok)
64606
64848
  return;
64607
- const ownerPath = path56.join(target, OWNER_FILE2);
64849
+ const ownerPath = path57.join(target, OWNER_FILE2);
64608
64850
  throw new SymbolCompilerLockError(`failed to remove symbol compiler lock directory at ${target} after ${result.attempts} attempt(s): ${errorDetail2(result.error)}; lock remains fail-closed. ${manualCleanupGuidance2(target, ownerPath)}`);
64609
64851
  }
64610
64852
  function removeLockOwner2(fileSystem, target, ownerPath, ignoreMissing) {
@@ -64693,10 +64935,10 @@ async function acquireSymbolCompilerLock(workspaceRoot, options2 = {}) {
64693
64935
  const fileSystem = options2.fileSystem ?? NODE_FILE_SYSTEM2;
64694
64936
  const isProcessAlive = options2.isProcessAlive ?? defaultIsProcessAlive2;
64695
64937
  const target = lockPath2(workspaceRoot);
64696
- const ownerPath = path56.join(target, OWNER_FILE2);
64938
+ const ownerPath = path57.join(target, OWNER_FILE2);
64697
64939
  const token = randomToken2();
64698
64940
  const deadline = now() + timeoutMs;
64699
- const parentPath = path56.dirname(target);
64941
+ const parentPath = path57.dirname(target);
64700
64942
  const parentResult = retryTransientFilesystemOperation2(() => fileSystem.mkdirSync(parentPath, { recursive: true }));
64701
64943
  if (!parentResult.ok) {
64702
64944
  throw new SymbolCompilerLockError(`failed to create symbol compiler lock parent at ${parentPath} after ${parentResult.attempts} attempt(s): ${errorDetail2(parentResult.error)}`);
@@ -64799,12 +65041,12 @@ async function withSymbolCompilerLock(workspaceRoot, operation, options2 = {}) {
64799
65041
  var LOCK_FILE_RELATIVE, OWNER_FILE2 = "owner.json", DEFAULT_TIMEOUT_MS2 = 15000, RETRY_INTERVAL_MS2 = 25, MAX_RELEASE_FILESYSTEM_ATTEMPTS2 = 3, NODE_FILE_SYSTEM2, SymbolCompilerLockError;
64800
65042
  var init_symbol_compiler_lock = __esm(() => {
64801
65043
  init_cli_errors();
64802
- LOCK_FILE_RELATIVE = path56.join(".kb", ".symbol-compiler.lock");
65044
+ LOCK_FILE_RELATIVE = path57.join(".kb", ".symbol-compiler.lock");
64803
65045
  NODE_FILE_SYSTEM2 = {
64804
65046
  mkdirSync: (target, options2) => {
64805
65047
  mkdirSync10(target, options2);
64806
65048
  },
64807
- readFileSync: (target) => readFileSync31(target, "utf8"),
65049
+ readFileSync: (target) => readFileSync32(target, "utf8"),
64808
65050
  writeFileSync: (target, data, options2) => {
64809
65051
  writeFileSync10(target, data, options2);
64810
65052
  },
@@ -64818,7 +65060,7 @@ var init_symbol_compiler_lock = __esm(() => {
64818
65060
 
64819
65061
  // ../cli/dist/extractors/symbols-coordinator.js
64820
65062
  import * as fs7 from "node:fs";
64821
- import * as path57 from "node:path";
65063
+ import * as path58 from "node:path";
64822
65064
  function analyzeSourceText(filePathOrEntries, contentOrWorkspaceRoot, optionsOrDeps) {
64823
65065
  if (Array.isArray(filePathOrEntries)) {
64824
65066
  return enrichSymbolCoordinates(filePathOrEntries, contentOrWorkspaceRoot, optionsOrDeps);
@@ -64859,13 +65101,13 @@ async function enrichSymbolCoordinates(entries, workspaceRoot, deps) {
64859
65101
  const resolved = resolveSourcePath(entry.sourceFile, workspaceRoot);
64860
65102
  if (!resolved || !fs7.statSync(resolved.absolutePath).isFile())
64861
65103
  continue;
64862
- const ext = path57.extname(resolved.absolutePath).toLowerCase();
65104
+ const ext = path58.extname(resolved.absolutePath).toLowerCase();
64863
65105
  if (isTsJsSourcePath(resolved.absolutePath)) {
64864
65106
  tsIndices.push(index);
64865
65107
  tsEntries.push(entry);
64866
65108
  continue;
64867
65109
  }
64868
- const logicalPath = path57.relative(workspaceRoot, resolved.absolutePath).replaceAll("\\", "/");
65110
+ const logicalPath = path58.relative(workspaceRoot, resolved.absolutePath).replaceAll("\\", "/");
64869
65111
  let analysis = analyses.get(logicalPath);
64870
65112
  const firstAnalysis = analysis === undefined;
64871
65113
  if (!analysis) {
@@ -64954,7 +65196,7 @@ function enrichWithRegexHeuristic(entry, absolutePath) {
64954
65196
  function resolveSourcePath(sourceFile, workspaceRoot) {
64955
65197
  if (!sourceFile)
64956
65198
  return null;
64957
- const absolutePath = path57.isAbsolute(sourceFile) ? sourceFile : path57.resolve(workspaceRoot, sourceFile);
65199
+ const absolutePath = path58.isAbsolute(sourceFile) ? sourceFile : path58.resolve(workspaceRoot, sourceFile);
64958
65200
  if (!fs7.existsSync(absolutePath))
64959
65201
  return null;
64960
65202
  return { absolutePath };
@@ -64981,9 +65223,9 @@ function detectSourceLanguage2(filePath) {
64981
65223
  return extensionLanguage(filePath);
64982
65224
  }
64983
65225
  function inferModuleTitle2(filePath) {
64984
- const extension = path57.extname(filePath);
64985
- const basename = path57.basename(filePath, extension);
64986
- return basename.length > 0 ? basename : path57.basename(filePath);
65226
+ const extension = path58.extname(filePath);
65227
+ const basename = path58.basename(filePath, extension);
65228
+ return basename.length > 0 ? basename : path58.basename(filePath);
64987
65229
  }
64988
65230
  var DEFAULT_SOURCE_ANALYSIS_PROVIDERS;
64989
65231
  var init_symbols_coordinator = __esm(() => {
@@ -65003,8 +65245,8 @@ var init_symbols_coordinator2 = __esm(() => {
65003
65245
 
65004
65246
  // ../cli/dist/operations/mutation/symbol-refresh.js
65005
65247
  import { createHash as createHash30, randomUUID as randomUUID5 } from "node:crypto";
65006
- import { existsSync as existsSync29, readFileSync as readFileSync33, renameSync as renameSync7, unlinkSync as unlinkSync8, writeFileSync as writeFileSync11 } from "node:fs";
65007
- import * as path58 from "node:path";
65248
+ import { existsSync as existsSync29, readFileSync as readFileSync34, renameSync as renameSync7, unlinkSync as unlinkSync8, writeFileSync as writeFileSync11 } from "node:fs";
65249
+ import * as path59 from "node:path";
65008
65250
  function record2(value) {
65009
65251
  return typeof value === "object" && value !== null && !Array.isArray(value);
65010
65252
  }
@@ -65015,15 +65257,15 @@ function coordinate(value) {
65015
65257
  return typeof sourceFile === "string" && typeof sourceLine === "number" && typeof sourceColumn === "number" && typeof sourceEndLine === "number" && typeof sourceEndColumn === "number" ? { sourceFile, sourceLine, sourceColumn, sourceEndLine, sourceEndColumn } : null;
65016
65258
  }
65017
65259
  async function manifestPath(context) {
65018
- return path58.join(context.workspaceRoot, CANONICAL_ENTITY_PATHS.symbols);
65260
+ return path59.join(context.workspaceRoot, CANONICAL_ENTITY_PATHS.symbols);
65019
65261
  }
65020
65262
  function artifactPathFor(manifest) {
65021
- return path58.join(path58.dirname(manifest), "symbol-coordinates.yaml");
65263
+ return path59.join(path59.dirname(manifest), "symbol-coordinates.yaml");
65022
65264
  }
65023
65265
  function sourceTextFor(sourceFile, workspaceRoot) {
65024
- const absolute = path58.isAbsolute(sourceFile) ? sourceFile : path58.resolve(workspaceRoot, sourceFile);
65266
+ const absolute = path59.isAbsolute(sourceFile) ? sourceFile : path59.resolve(workspaceRoot, sourceFile);
65025
65267
  try {
65026
- return readFileSync33(absolute, "utf8");
65268
+ return readFileSync34(absolute, "utf8");
65027
65269
  } catch {
65028
65270
  return null;
65029
65271
  }
@@ -65051,7 +65293,7 @@ function replaceArtifactAtomically(targetPath, content) {
65051
65293
  }
65052
65294
  }
65053
65295
  function publishArtifact(targetPath, content) {
65054
- const before = existsSync29(targetPath) ? readFileSync33(targetPath, "utf8") : null;
65296
+ const before = existsSync29(targetPath) ? readFileSync34(targetPath, "utf8") : null;
65055
65297
  const beforeHash = before === null ? null : contentHash2(before);
65056
65298
  const afterHash = contentHash2(content);
65057
65299
  replaceArtifactAtomically(targetPath, content);
@@ -65063,7 +65305,7 @@ function publishArtifact(targetPath, content) {
65063
65305
  if (!existsSync29(targetPath)) {
65064
65306
  throw new CoordinateArtifactError(`coordinate artifact disappeared before rollback: ${targetPath}`);
65065
65307
  }
65066
- const current = readFileSync33(targetPath, "utf8");
65308
+ const current = readFileSync34(targetPath, "utf8");
65067
65309
  if (contentHash2(current) !== afterHash) {
65068
65310
  throw new CoordinateArtifactError(`coordinate artifact changed after publication; refusing rollback: ${targetPath}`);
65069
65311
  }
@@ -65230,8 +65472,8 @@ var init_warnings = () => {};
65230
65472
 
65231
65473
  // ../cli/dist/operations/mutation/upsert.js
65232
65474
  import { createHash as createHash31 } from "node:crypto";
65233
- import { existsSync as existsSync30, readFileSync as readFileSync34, unlinkSync as unlinkSync9, writeFileSync as writeFileSync12 } from "node:fs";
65234
- import path59 from "node:path";
65475
+ import { existsSync as existsSync30, readFileSync as readFileSync35, unlinkSync as unlinkSync9, writeFileSync as writeFileSync12 } from "node:fs";
65476
+ import path60 from "node:path";
65235
65477
  function requireProlog4(context) {
65236
65478
  if (context.prolog === undefined) {
65237
65479
  throw new Error("Upsert operation requires a Prolog runtime");
@@ -65250,21 +65492,21 @@ function parseChangeKind(value) {
65250
65492
  function fileHash2(pathname) {
65251
65493
  if (!existsSync30(pathname))
65252
65494
  return null;
65253
- return createHash31("sha256").update(readFileSync34(pathname)).digest("hex");
65495
+ return createHash31("sha256").update(readFileSync35(pathname)).digest("hex");
65254
65496
  }
65255
65497
  function textHash(value) {
65256
65498
  return createHash31("sha256").update(value).digest("hex");
65257
65499
  }
65258
65500
  function assertRelationshipShardContained(workspaceRoot, shardPath) {
65259
- const root = path59.resolve(workspaceRoot);
65260
- const relationshipRoot = path59.resolve(root, ".kb", "relationships");
65261
- const absolute = path59.resolve(shardPath);
65262
- if (!absolute.startsWith(`${relationshipRoot}${path59.sep}`)) {
65501
+ const root = path60.resolve(workspaceRoot);
65502
+ const relationshipRoot = path60.resolve(root, ".kb", "relationships");
65503
+ const absolute = path60.resolve(shardPath);
65504
+ if (!absolute.startsWith(`${relationshipRoot}${path60.sep}`)) {
65263
65505
  throw new OperationError("SOURCE_PATH_INVALID", `Relationship shard escapes the canonical workspace lane: ${shardPath}`);
65264
65506
  }
65265
65507
  const realRoot = canonicalFilesystemPath(root);
65266
65508
  const real = canonicalFilesystemPath(absolute);
65267
- if (real !== realRoot && !real.startsWith(`${realRoot}${path59.sep}`)) {
65509
+ if (real !== realRoot && !real.startsWith(`${realRoot}${path60.sep}`)) {
65268
65510
  throw new OperationError("SOURCE_PATH_INVALID", `Relationship shard follows a symlink outside the workspace: ${shardPath}`);
65269
65511
  }
65270
65512
  }
@@ -65277,7 +65519,7 @@ function restoreRelationshipShard(shardPath, before, expectedAfterHash) {
65277
65519
  currentHash = null;
65278
65520
  }
65279
65521
  if (currentHash !== expectedAfterHash) {
65280
- console.warn(`Skipped relationship shard rollback for ${path59.relative(process.cwd(), shardPath)}: shard changed after the Kibi write.`);
65522
+ console.warn(`Skipped relationship shard rollback for ${path60.relative(process.cwd(), shardPath)}: shard changed after the Kibi write.`);
65281
65523
  return;
65282
65524
  }
65283
65525
  }
@@ -65327,7 +65569,7 @@ async function effectiveRelationships(input, entity, relationships, context, sta
65327
65569
  }
65328
65570
  }
65329
65571
  function reextractCanonicalSymbolEntity(symbolId, authoredRelativePath, workspaceRoot) {
65330
- const absoluteManifest = path59.resolve(workspaceRoot, authoredRelativePath);
65572
+ const absoluteManifest = path60.resolve(workspaceRoot, authoredRelativePath);
65331
65573
  let records;
65332
65574
  try {
65333
65575
  records = readManifestWithCoordinateOverlay(absoluteManifest);
@@ -65463,12 +65705,12 @@ async function executeUpsert(input, context, options2 = {}) {
65463
65705
  const to = typeof relationship.to === "string" ? relationship.to : "";
65464
65706
  if (!type || !from || !to)
65465
65707
  continue;
65466
- const shardPath = computeShardPath(path59.join(context.workspaceRoot, ".kb"), from);
65708
+ const shardPath = computeShardPath(path60.join(context.workspaceRoot, ".kb"), from);
65467
65709
  assertRelationshipShardContained(context.workspaceRoot, shardPath);
65468
65710
  if (!relationshipShardBefore.has(shardPath)) {
65469
- relationshipShardBefore.set(shardPath, existsSync30(shardPath) ? readFileSync34(shardPath, "utf8") : null);
65711
+ relationshipShardBefore.set(shardPath, existsSync30(shardPath) ? readFileSync35(shardPath, "utf8") : null);
65470
65712
  }
65471
- appendRelationship(path59.join(context.workspaceRoot, ".kb"), {
65713
+ appendRelationship(path60.join(context.workspaceRoot, ".kb"), {
65472
65714
  type,
65473
65715
  from,
65474
65716
  to,
@@ -65480,7 +65722,7 @@ async function executeUpsert(input, context, options2 = {}) {
65480
65722
  }
65481
65723
  }
65482
65724
  if (input.type === "symbol" && context.fs !== undefined && context.sourceFirst !== false && sourceWrite !== null) {
65483
- const refresh = await refreshSymbolCoordinatesForManifest(input.id, path59.resolve(context.workspaceRoot, sourceWrite.receipt.path), context);
65725
+ const refresh = await refreshSymbolCoordinatesForManifest(input.id, path60.resolve(context.workspaceRoot, sourceWrite.receipt.path), context);
65484
65726
  const coordinatePublication = refresh.publication;
65485
65727
  if (coordinatePublication !== undefined) {
65486
65728
  saga.add({
@@ -65581,14 +65823,14 @@ async function executeUpsert(input, context, options2 = {}) {
65581
65823
  const expectedAfterHash = relationshipShardAfterHash.get(shardPath) ?? null;
65582
65824
  if (afterHash === null) {
65583
65825
  if (expectedAfterHash !== null) {
65584
- const relative = path59.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
65826
+ const relative = path60.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
65585
65827
  shardWarnings.push(`Relationship shard vanished after write: ${relative}`);
65586
65828
  }
65587
65829
  continue;
65588
65830
  }
65589
65831
  if (afterHash === beforeHash)
65590
65832
  continue;
65591
- const relative = path59.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
65833
+ const relative = path60.relative(context.workspaceRoot, shardPath).replaceAll("\\", "/");
65592
65834
  writePendingSourceReceipt(context.workspaceRoot, relative, afterHash);
65593
65835
  relationshipSourceWrites.push({
65594
65836
  path: relative,
@@ -66433,15 +66675,15 @@ function formatSyncSummary(summary) {
66433
66675
  }
66434
66676
 
66435
66677
  // ../cli/dist/commands/sync/manifest.js
66436
- import { existsSync as existsSync31, readFileSync as readFileSync35, renameSync as renameSync8, unlinkSync as unlinkSync10, writeFileSync as writeFileSync13 } from "node:fs";
66437
- import * as path60 from "node:path";
66678
+ import { existsSync as existsSync31, readFileSync as readFileSync36, renameSync as renameSync8, unlinkSync as unlinkSync10, writeFileSync as writeFileSync13 } from "node:fs";
66679
+ import * as path61 from "node:path";
66438
66680
  function resolveDeps2(overrides) {
66439
66681
  return {
66440
66682
  dumpYAML: dump,
66441
66683
  enrichSymbolCoordinates,
66442
66684
  existsSync: existsSync31,
66443
66685
  parseYAML: load,
66444
- readFileSync: readFileSync35,
66686
+ readFileSync: readFileSync36,
66445
66687
  renameSync: renameSync8,
66446
66688
  unlinkSync: unlinkSync10,
66447
66689
  writeFileSync: writeFileSync13,
@@ -66465,7 +66707,7 @@ function extractedCoordinates(entry) {
66465
66707
  } : null;
66466
66708
  }
66467
66709
  function readSourceText(sourceFile, workspaceRoot, deps) {
66468
- const absolute = path60.isAbsolute(sourceFile) ? sourceFile : path60.resolve(workspaceRoot, sourceFile);
66710
+ const absolute = path61.isAbsolute(sourceFile) ? sourceFile : path61.resolve(workspaceRoot, sourceFile);
66469
66711
  if (!deps.existsSync(absolute))
66470
66712
  return null;
66471
66713
  try {
@@ -66618,9 +66860,9 @@ async function refreshManifestCoordinates(manifestPath, workspaceRoot, deps) {
66618
66860
  if (!deps?.quiet) {
66619
66861
  const counts = `(refreshed=${refreshed}, unchanged=${unchanged}, failed=${failures.length})`;
66620
66862
  if (coordinatesPath !== null) {
66621
- console.log(`✓ Refreshed symbol coordinates in ${path60.relative(workspaceRoot, coordinatesPath)} ${counts}`);
66863
+ console.log(`✓ Refreshed symbol coordinates in ${path61.relative(workspaceRoot, coordinatesPath)} ${counts}`);
66622
66864
  } else {
66623
- console.log(`✓ Normalized symbol manifest ${path60.relative(workspaceRoot, manifestPath)} ${counts}`);
66865
+ console.log(`✓ Normalized symbol manifest ${path61.relative(workspaceRoot, manifestPath)} ${counts}`);
66624
66866
  }
66625
66867
  const maxReportedFailures = 10;
66626
66868
  for (const failure of failures.slice(0, maxReportedFailures)) {
@@ -66641,7 +66883,7 @@ function isEligibleForCoordinateRefresh(sourceFile, workspaceRoot, deps) {
66641
66883
  const resolved = resolveDeps2(deps);
66642
66884
  if (!sourceFile)
66643
66885
  return false;
66644
- const absolute = path60.isAbsolute(sourceFile) ? sourceFile : path60.resolve(workspaceRoot, sourceFile);
66886
+ const absolute = path61.isAbsolute(sourceFile) ? sourceFile : path61.resolve(workspaceRoot, sourceFile);
66645
66887
  return resolved.existsSync(absolute);
66646
66888
  }
66647
66889
  function isRecord16(value) {
@@ -66683,8 +66925,8 @@ var init_manifest3 = __esm(() => {
66683
66925
 
66684
66926
  // ../cli/dist/commands/sync/untracked-targets.js
66685
66927
  import { execFileSync as execFileSync7 } from "node:child_process";
66686
- import { existsSync as existsSync32, readFileSync as readFileSync36 } from "node:fs";
66687
- import * as path61 from "node:path";
66928
+ import { existsSync as existsSync32, readFileSync as readFileSync37 } from "node:fs";
66929
+ import * as path62 from "node:path";
66688
66930
  function findUntrackedDocumentMatches(workspaceRoot, missingIds, deps = {}) {
66689
66931
  const resolved = { ...defaultDeps3, ...deps };
66690
66932
  const matches = new Map;
@@ -66712,7 +66954,7 @@ function findUntrackedDocumentMatches(workspaceRoot, missingIds, deps = {}) {
66712
66954
  break;
66713
66955
  if (!relative.endsWith(".md"))
66714
66956
  continue;
66715
- const absolute = path61.resolve(workspaceRoot, relative.replaceAll("\\", "/"));
66957
+ const absolute = path62.resolve(workspaceRoot, relative.replaceAll("\\", "/"));
66716
66958
  if (!resolved.existsSync(absolute))
66717
66959
  continue;
66718
66960
  let content;
@@ -66723,7 +66965,7 @@ function findUntrackedDocumentMatches(workspaceRoot, missingIds, deps = {}) {
66723
66965
  }
66724
66966
  const id = frontmatterId(content);
66725
66967
  if (id !== null && remaining.has(id)) {
66726
- const workspaceRelative = path61.relative(workspaceRoot, absolute).replaceAll("\\", "/");
66968
+ const workspaceRelative = path62.relative(workspaceRoot, absolute).replaceAll("\\", "/");
66727
66969
  matches.set(id, workspaceRelative);
66728
66970
  remaining.delete(id);
66729
66971
  }
@@ -66751,12 +66993,12 @@ var init_untracked_targets = __esm(() => {
66751
66993
  defaultDeps3 = {
66752
66994
  execFileSync: (file, args, options2) => execFileSync7(file, args, options2),
66753
66995
  existsSync: existsSync32,
66754
- readFileSync: readFileSync36
66996
+ readFileSync: readFileSync37
66755
66997
  };
66756
66998
  });
66757
66999
 
66758
67000
  // ../cli/dist/commands/sync/persistence.js
66759
- import * as path62 from "node:path";
67001
+ import * as path63 from "node:path";
66760
67002
  function getEntityField(entity, field) {
66761
67003
  return entity[field];
66762
67004
  }
@@ -66834,8 +67076,8 @@ function sourceLookupCandidates(sourceFile) {
66834
67076
  return [
66835
67077
  ...new Set([
66836
67078
  sourceFile,
66837
- path62.relative(process.cwd(), sourceFile),
66838
- path62.basename(sourceFile)
67079
+ path63.relative(process.cwd(), sourceFile),
67080
+ path63.basename(sourceFile)
66839
67081
  ])
66840
67082
  ];
66841
67083
  }
@@ -67123,7 +67365,7 @@ async function persistEntities(prolog, results, entityIds, options2 = {}) {
67123
67365
  return { entityCount, kbModified };
67124
67366
  }
67125
67367
  function semanticEntityContext(entity, sourceFile) {
67126
- const displaySource = path62.isAbsolute(sourceFile) ? path62.relative(process.cwd(), sourceFile) : sourceFile;
67368
+ const displaySource = path63.isAbsolute(sourceFile) ? path63.relative(process.cwd(), sourceFile) : sourceFile;
67127
67369
  const details = [`source=${displaySource}`];
67128
67370
  if (entity.type === "fact") {
67129
67371
  const factKind = getEntityField(entity, "fact_kind");
@@ -67144,7 +67386,7 @@ async function persistRelationships(prolog, results, shardRelationships, options
67144
67386
  let kbModified = false;
67145
67387
  const idLookup = new Map;
67146
67388
  for (const { entity } of results) {
67147
- const filename = path62.basename(entity.source, ".md");
67389
+ const filename = path63.basename(entity.source, ".md");
67148
67390
  idLookup.set(filename, entity.id);
67149
67391
  idLookup.set(entity.id, entity.id);
67150
67392
  }
@@ -67342,7 +67584,7 @@ var init_persistence = __esm(() => {
67342
67584
  // ../cli/dist/commands/sync/staging.js
67343
67585
  import { existsSync as existsSync33, mkdirSync as mkdirSync11, renameSync as renameSync9, rmSync as rmSync4, writeFileSync as writeFileSync14 } from "node:fs";
67344
67586
  import { copyFileSync as copyFileSync2 } from "node:fs";
67345
- import * as path63 from "node:path";
67587
+ import * as path64 from "node:path";
67346
67588
  function resolveDeps3(overrides) {
67347
67589
  return {
67348
67590
  copyCleanSnapshot,
@@ -67367,15 +67609,15 @@ function resolveDeps3(overrides) {
67367
67609
  };
67368
67610
  }
67369
67611
  function createUniqueStagingPath(currentBranch, rootDir, pid = process.pid, now = Date.now()) {
67370
- return path63.join(rootDir, ".kb", "branches", `${currentBranch}.staging.${pid}.${now}`);
67612
+ return path64.join(rootDir, ".kb", "branches", `${currentBranch}.staging.${pid}.${now}`);
67371
67613
  }
67372
67614
  function abandonedStagingBranch(branch) {
67373
67615
  return branch ? branch : undefined;
67374
67616
  }
67375
67617
  async function cleanupAbandonedStagingDirectories(stagingPath, deps) {
67376
67618
  const resolved = resolveDeps3(deps);
67377
- const stagingDir = path63.dirname(stagingPath);
67378
- const stagingBase = path63.basename(stagingPath);
67619
+ const stagingDir = path64.dirname(stagingPath);
67620
+ const stagingBase = path64.basename(stagingPath);
67379
67621
  const match = /^(?<branch>.*)\.staging\.(?<pid>\d+)\.(?<timestamp>\d+)$/.exec(stagingBase);
67380
67622
  if (!match?.groups) {
67381
67623
  return;
@@ -67394,7 +67636,7 @@ async function cleanupAbandonedStagingDirectories(stagingPath, deps) {
67394
67636
  if (candidate === stagingPath) {
67395
67637
  continue;
67396
67638
  }
67397
- const candidateBase = path63.basename(candidate);
67639
+ const candidateBase = path64.basename(candidate);
67398
67640
  const candidateMatch = new RegExp(`^${escapeRegex2(branch)}\\.staging\\.(\\d+)\\.(\\d+)$`).exec(candidateBase);
67399
67641
  if (!candidateMatch) {
67400
67642
  continue;
@@ -67420,25 +67662,25 @@ async function prepareStagingEnvironment(stagingPath, livePath, rebuild, deps) {
67420
67662
  } else {
67421
67663
  await copySchemaToStaging(stagingPath, resolved);
67422
67664
  }
67423
- const markerPath = path63.join(stagingPath, "storage.json");
67665
+ const markerPath = path64.join(stagingPath, "storage.json");
67424
67666
  const canWriteMetadata = deps === undefined || deps.writeFileSync !== undefined;
67425
67667
  if (canWriteMetadata && resolved.existsSync(stagingPath) && !resolved.existsSync(markerPath)) {
67426
- resolved.mkdirSync(path63.join(stagingPath, "rdf"), { recursive: true });
67668
+ resolved.mkdirSync(path64.join(stagingPath, "rdf"), { recursive: true });
67427
67669
  resolved.writeFileSync(markerPath, `{"format":"kibi.rdf-journal.v1","schemaVersion":1}
67428
67670
  `, { mode: 384 });
67429
67671
  const generation = rebuild ? `generation-${process.pid}-${Date.now()}` : "generation-1";
67430
- resolved.writeFileSync(path63.join(stagingPath, "CURRENT"), `${generation}:0
67672
+ resolved.writeFileSync(path64.join(stagingPath, "CURRENT"), `${generation}:0
67431
67673
  `, { mode: 384 });
67432
- resolved.writeFileSync(path63.join(stagingPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
67674
+ resolved.writeFileSync(path64.join(stagingPath, "kb.rdf"), `KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1
67433
67675
  `, { mode: 384 });
67434
67676
  }
67435
67677
  }
67436
67678
  async function copySchemaToStaging(stagingPath, deps) {
67437
67679
  const possibleSchemaPaths = [
67438
- path63.resolve(deps.cwd(), "node_modules", "kibi-cli", "schema"),
67439
- path63.resolve(deps.cwd(), "..", "..", "schema"),
67440
- path63.resolve(deps.moduleDir, "..", "..", "schema"),
67441
- path63.resolve(deps.cwd(), "packages", "cli", "schema")
67680
+ path64.resolve(deps.cwd(), "node_modules", "kibi-cli", "schema"),
67681
+ path64.resolve(deps.cwd(), "..", "..", "schema"),
67682
+ path64.resolve(deps.moduleDir, "..", "..", "schema"),
67683
+ path64.resolve(deps.cwd(), "packages", "cli", "schema")
67442
67684
  ];
67443
67685
  let schemaSourceDir = null;
67444
67686
  for (const p of possibleSchemaPaths) {
@@ -67454,19 +67696,19 @@ async function copySchemaToStaging(stagingPath, deps) {
67454
67696
  cwd: schemaSourceDir,
67455
67697
  absolute: false
67456
67698
  });
67457
- const schemaDestDir = path63.join(stagingPath, "schema");
67699
+ const schemaDestDir = path64.join(stagingPath, "schema");
67458
67700
  if (!deps.existsSync(schemaDestDir)) {
67459
67701
  deps.mkdirSync(schemaDestDir, { recursive: true });
67460
67702
  }
67461
67703
  for (const file of schemaFiles) {
67462
- const sourcePath = path63.join(schemaSourceDir, file);
67463
- const destPath = path63.join(schemaDestDir, file);
67704
+ const sourcePath = path64.join(schemaSourceDir, file);
67705
+ const destPath = path64.join(schemaDestDir, file);
67464
67706
  deps.copyFileSync(sourcePath, destPath);
67465
67707
  }
67466
67708
  }
67467
67709
  function atomicPublish(stagingPath, livePath, deps) {
67468
67710
  const resolved = resolveDeps3(deps);
67469
- const liveParent = path63.dirname(livePath);
67711
+ const liveParent = path64.dirname(livePath);
67470
67712
  if (!resolved.existsSync(liveParent)) {
67471
67713
  resolved.mkdirSync(liveParent, { recursive: true });
67472
67714
  }
@@ -67481,7 +67723,7 @@ function atomicPublish(stagingPath, livePath, deps) {
67481
67723
  }
67482
67724
  function atomicPublishGeneration(stagingPath, livePath, deps) {
67483
67725
  const resolved = resolveDeps3(deps);
67484
- const liveParent = path63.dirname(livePath);
67726
+ const liveParent = path64.dirname(livePath);
67485
67727
  if (!resolved.existsSync(liveParent)) {
67486
67728
  resolved.mkdirSync(liveParent, { recursive: true });
67487
67729
  }
@@ -67490,11 +67732,11 @@ function atomicPublishGeneration(stagingPath, livePath, deps) {
67490
67732
  return;
67491
67733
  }
67492
67734
  const generationStamp = `${Date.now()}.${process.pid}`;
67493
- const liveRdf = path63.join(livePath, "rdf");
67494
- const stagedRdf = path63.join(stagingPath, "rdf");
67735
+ const liveRdf = path64.join(livePath, "rdf");
67736
+ const stagedRdf = path64.join(stagingPath, "rdf");
67495
67737
  const oldRdf = `${liveRdf}.old.${generationStamp}`;
67496
- const liveCurrent = path63.join(livePath, "CURRENT");
67497
- const stagedCurrent = path63.join(stagingPath, "CURRENT");
67738
+ const liveCurrent = path64.join(livePath, "CURRENT");
67739
+ const stagedCurrent = path64.join(stagingPath, "CURRENT");
67498
67740
  const oldCurrent = `${liveCurrent}.old.${generationStamp}`;
67499
67741
  if (!resolved.existsSync(stagedRdf) || !resolved.existsSync(stagedCurrent)) {
67500
67742
  throw new Error("Rebuilt journal generation is missing rdf or CURRENT");
@@ -67548,8 +67790,8 @@ var init_staging = __esm(() => {
67548
67790
  // ../cli/dist/commands/sync.js
67549
67791
  import { execSync as execSync4 } from "node:child_process";
67550
67792
  import { createHash as createHash32 } from "node:crypto";
67551
- import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync37, readdirSync as readdirSync9, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
67552
- import * as path64 from "node:path";
67793
+ import { existsSync as existsSync34, mkdirSync as mkdirSync12, readFileSync as readFileSync38, readdirSync as readdirSync9, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
67794
+ import * as path65 from "node:path";
67553
67795
  function relationshipKey2(relationship) {
67554
67796
  return `${relationship.type}\x00${relationship.from}\x00${relationship.to}`;
67555
67797
  }
@@ -67591,14 +67833,14 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
67591
67833
  return [];
67592
67834
  }
67593
67835
  const pending = new Set;
67594
- const pendingRoot = path64.join(workspaceRoot, ".kb", "recovery", "pending-sources");
67836
+ const pendingRoot = path65.join(workspaceRoot, ".kb", "recovery", "pending-sources");
67595
67837
  if (existsSync34(pendingRoot)) {
67596
67838
  for (const receiptName of readdirSync9(pendingRoot)) {
67597
67839
  if (!receiptName.endsWith(".json"))
67598
67840
  continue;
67599
67841
  let receipt;
67600
67842
  try {
67601
- receipt = JSON.parse(readFileSync37(path64.join(pendingRoot, receiptName), "utf8"));
67843
+ receipt = JSON.parse(readFileSync38(path65.join(pendingRoot, receiptName), "utf8"));
67602
67844
  } catch {
67603
67845
  continue;
67604
67846
  }
@@ -67608,26 +67850,26 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
67608
67850
  const relative = receipt.path.replaceAll("\\", "/");
67609
67851
  if (!relative.startsWith(".kb/relationships/"))
67610
67852
  continue;
67611
- const absolute = path64.resolve(workspaceRoot, relative);
67612
- if (!absolute.startsWith(`${path64.resolve(workspaceRoot)}${path64.sep}`)) {
67853
+ const absolute = path65.resolve(workspaceRoot, relative);
67854
+ if (!absolute.startsWith(`${path65.resolve(workspaceRoot)}${path65.sep}`)) {
67613
67855
  throw new SyncError(`Pending source path escapes workspace: ${relative}`);
67614
67856
  }
67615
67857
  if (!existsSync34(absolute)) {
67616
67858
  if (recoverMissingPendingSources) {
67617
- const receiptPath = path64.join(pendingRoot, receiptName);
67859
+ const receiptPath = path65.join(pendingRoot, receiptName);
67618
67860
  if (!recoveredPendingReceiptPaths.some((candidate) => candidate.receiptPath === receiptPath)) {
67619
67861
  recoveredPendingReceiptPaths.push({
67620
67862
  receiptPath,
67621
67863
  path: relative,
67622
67864
  afterHash: receipt.afterHash,
67623
- rawHash: createHash32("sha256").update(readFileSync37(receiptPath)).digest("hex")
67865
+ rawHash: createHash32("sha256").update(readFileSync38(receiptPath)).digest("hex")
67624
67866
  });
67625
67867
  }
67626
67868
  continue;
67627
67869
  }
67628
67870
  throw new SyncError(`Pending source is missing: ${relative}.${PENDING_SOURCE_RECOVERY_HINT}`);
67629
67871
  }
67630
- const actual = createHash32("sha256").update(readFileSync37(absolute)).digest("hex");
67872
+ const actual = createHash32("sha256").update(readFileSync38(absolute)).digest("hex");
67631
67873
  if (actual !== receipt.afterHash) {
67632
67874
  throw new SyncError(`Pending source hash drift blocks sync for ${relative}`);
67633
67875
  }
@@ -67635,8 +67877,8 @@ function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissin
67635
67877
  }
67636
67878
  }
67637
67879
  try {
67638
- return readdirSync9(relationshipsDir).filter((file) => file.endsWith(".yaml") || file.endsWith(".yml")).map((file) => path64.join(relationshipsDir, file)).filter((file) => {
67639
- const relative = path64.relative(workspaceRoot, file).replaceAll(path64.sep, "/");
67880
+ return readdirSync9(relationshipsDir).filter((file) => file.endsWith(".yaml") || file.endsWith(".yml")).map((file) => path65.join(relationshipsDir, file)).filter((file) => {
67881
+ const relative = path65.relative(workspaceRoot, file).replaceAll(path65.sep, "/");
67640
67882
  return tracked.has(relative) || pending.has(relative);
67641
67883
  }).sort();
67642
67884
  } catch {
@@ -67740,7 +67982,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
67740
67982
  } : (...args) => console.log(...args);
67741
67983
  const rebuild = options2.rebuild ?? false;
67742
67984
  const recoveryBackupPath = options2.recoveryBackupPath;
67743
- const workspaceRoot = path64.resolve(options2.workspaceRoot ?? process.cwd());
67985
+ const workspaceRoot = path65.resolve(options2.workspaceRoot ?? process.cwd());
67744
67986
  const startTime = Date.now();
67745
67987
  const diagnostics = [];
67746
67988
  const entityCounts = {};
@@ -67824,7 +68066,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
67824
68066
  console.log("[kibi-debug] manifestFiles:", manifestFiles.length);
67825
68067
  }
67826
68068
  const sourceFiles = [...markdownFiles, ...manifestFiles].sort();
67827
- const cachePath = path64.join(livePathForEngine, "sync-cache.json");
68069
+ const cachePath = path65.join(livePathForEngine, "sync-cache.json");
67828
68070
  const syncCache = readSyncCache(cachePath, undefined, {
67829
68071
  compilerFingerprint: SYNC_COMPILER_FINGERPRINT
67830
68072
  });
@@ -67832,7 +68074,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
67832
68074
  const nowMs = Date.now();
67833
68075
  const currentSourceKeys = new Set(sourceFiles.map((file) => toCacheKey(workspaceRoot, file)));
67834
68076
  const relationshipShardFiles = existsSync34(relationshipsDir) ? trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoveryBackupPath !== undefined, recoveredPendingReceiptPaths) : [];
67835
- const fastPathSourceHashOf = (file) => manifestFiles.includes(file) ? hashManifestWithCoordinates(workspaceRoot, file, path64.join(path64.dirname(file), "symbol-coordinates.yaml")) : hashFile(workspaceRoot, file);
68077
+ const fastPathSourceHashOf = (file) => manifestFiles.includes(file) ? hashManifestWithCoordinates(workspaceRoot, file, path65.join(path65.dirname(file), "symbol-coordinates.yaml")) : hashFile(workspaceRoot, file);
67836
68078
  if (!validateOnly && !rebuild && !options2.refreshSymbolCoordinates && runtime.createProlog === undefined && compilerCacheHasEntityDelta(syncCache) && compilerCacheIsFresh(syncCache, workspaceRoot, sourceFiles, nowMs) && compilerCacheFilesMatch(syncCache, workspaceRoot, sourceFiles, relationshipShardFiles, fastPathSourceHashOf)) {
67837
68079
  await checkpointNoopSync(workspaceRoot, currentBranch);
67838
68080
  info("✓ Imported 0 entities, 0 relationships (no changes)");
@@ -67857,7 +68099,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
67857
68099
  refreshedManifestKeys.add(toCacheKey(workspaceRoot, file));
67858
68100
  }
67859
68101
  }
67860
- const coordinatesPathForManifest = (manifestFile) => path64.join(path64.dirname(manifestFile), "symbol-coordinates.yaml");
68102
+ const coordinatesPathForManifest = (manifestFile) => path65.join(path65.dirname(manifestFile), "symbol-coordinates.yaml");
67861
68103
  const effectiveSourceHash = (file) => manifestFiles.includes(file) ? hashManifestWithCoordinates(workspaceRoot, file, coordinatesPathForManifest(file)) : hashFile(workspaceRoot, file);
67862
68104
  const changedSourceHashes = new Map;
67863
68105
  for (const file of sourceFiles) {
@@ -67882,7 +68124,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
67882
68124
  const changedMarkdownFiles = [];
67883
68125
  const changedManifestFiles = [];
67884
68126
  const forceEntitySourceKeys = new Set;
67885
- const deletedSourceFiles = Object.keys(syncCache.hashes).filter((key) => !currentSourceKeys.has(key)).map((key) => path64.resolve(workspaceRoot, key));
68127
+ const deletedSourceFiles = Object.keys(syncCache.hashes).filter((key) => !currentSourceKeys.has(key)).map((key) => path65.resolve(workspaceRoot, key));
67886
68128
  const currentRelationshipKeys = new Set;
67887
68129
  for (const shardPath of relationshipShardFiles) {
67888
68130
  const key = toCacheKey(workspaceRoot, shardPath);
@@ -68226,7 +68468,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
68226
68468
  evictedSemanticContracts[key] = nextSemanticContracts[key] === true;
68227
68469
  }
68228
68470
  }
68229
- writeSyncCache(path64.join(livePath, "sync-cache.json"), {
68471
+ writeSyncCache(path65.join(livePath, "sync-cache.json"), {
68230
68472
  version: SYNC_CACHE_VERSION,
68231
68473
  hashes: evictedHashes,
68232
68474
  relationshipHashes: nextRelationshipHashes,
@@ -68353,7 +68595,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
68353
68595
  }
68354
68596
  await prolog.query("kb_detach");
68355
68597
  await prolog.terminate();
68356
- const journaledLive = existsSync34(path64.join(livePath, "storage.json"));
68598
+ const journaledLive = existsSync34(path65.join(livePath, "storage.json"));
68357
68599
  if (recoveryBackupPath !== undefined) {
68358
68600
  if (!existsSync34(livePath)) {
68359
68601
  throw new SyncError(`Recovery target disappeared before publication: ${livePath}`);
@@ -68361,7 +68603,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
68361
68603
  if (existsSync34(recoveryBackupPath)) {
68362
68604
  throw new SyncError(`Recovery backup path already exists: ${recoveryBackupPath}`);
68363
68605
  }
68364
- mkdirSync12(path64.dirname(recoveryBackupPath), { recursive: true });
68606
+ mkdirSync12(path65.dirname(recoveryBackupPath), { recursive: true });
68365
68607
  renameSync10(livePath, recoveryBackupPath);
68366
68608
  try {
68367
68609
  renameSync10(stagingPath, livePath);
@@ -68397,7 +68639,7 @@ async function syncCommand(options2 = {}, runtime = {}) {
68397
68639
  evictedSemanticContracts[key] = nextSemanticContracts[key] === true;
68398
68640
  }
68399
68641
  }
68400
- const liveCachePath = path64.join(livePath, "sync-cache.json");
68642
+ const liveCachePath = path65.join(livePath, "sync-cache.json");
68401
68643
  writeSyncCache(liveCachePath, {
68402
68644
  version: SYNC_CACHE_VERSION,
68403
68645
  hashes: evictedHashes,
@@ -68490,7 +68732,7 @@ var init_sync = __esm(() => {
68490
68732
  // ../cli/dist/commands/branch.js
68491
68733
  import { createHash as createHash33 } from "node:crypto";
68492
68734
  import * as fs8 from "node:fs";
68493
- import * as path65 from "node:path";
68735
+ import * as path66 from "node:path";
68494
68736
  function isSupportedLegacyBranchMigration(from, to) {
68495
68737
  return from === to;
68496
68738
  }
@@ -68498,12 +68740,12 @@ function hashLegacyStore(sourcePath) {
68498
68740
  const hash = createHash33("sha256");
68499
68741
  const visit = (directory, relative = "") => {
68500
68742
  for (const entry of fs8.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
68501
- const absolute = path65.join(directory, entry.name);
68502
- const child = relative ? path65.join(relative, entry.name) : entry.name;
68743
+ const absolute = path66.join(directory, entry.name);
68744
+ const child = relative ? path66.join(relative, entry.name) : entry.name;
68503
68745
  if (entry.isDirectory())
68504
68746
  visit(absolute, child);
68505
68747
  else if (entry.isFile()) {
68506
- hash.update(child.replaceAll(path65.sep, "/"));
68748
+ hash.update(child.replaceAll(path66.sep, "/"));
68507
68749
  hash.update("\x00");
68508
68750
  hash.update(fs8.readFileSync(absolute));
68509
68751
  hash.update("\x00");
@@ -68529,7 +68771,7 @@ function migrationJournalPath(workspaceRoot, id) {
68529
68771
  if (!/^[A-Za-z0-9._-]+$/.test(id)) {
68530
68772
  throw new Error("branch migration journal ID is invalid");
68531
68773
  }
68532
- return path65.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${id}.json`);
68774
+ return path66.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${id}.json`);
68533
68775
  }
68534
68776
  function writeMigrationJournal(journalPath, journal) {
68535
68777
  fs8.writeFileSync(journalPath, `${JSON.stringify(journal, null, 2)}
@@ -68549,9 +68791,9 @@ function recoverBranchMigration(workspaceRoot, id, apply) {
68549
68791
  const journal = JSON.parse(fs8.readFileSync(journalPath, "utf8"));
68550
68792
  if (journal.version !== 2)
68551
68793
  throw new Error("Unsupported branch migration journal version");
68552
- const root = path65.resolve(workspaceRoot);
68553
- const paths = ["sourcePath", "targetPath", "stagingPath", "backupPath"].map((key) => path65.resolve(root, String(journal[key])));
68554
- if (paths.some((candidate) => !candidate.startsWith(`${root}${path65.sep}`))) {
68794
+ const root = path66.resolve(workspaceRoot);
68795
+ const paths = ["sourcePath", "targetPath", "stagingPath", "backupPath"].map((key) => path66.resolve(root, String(journal[key])));
68796
+ if (paths.some((candidate) => !candidate.startsWith(`${root}${path66.sep}`))) {
68555
68797
  throw new Error("Branch migration journal path escapes workspace");
68556
68798
  }
68557
68799
  const [sourcePath, targetPath, stagingPath, backupPath] = completeBranchJournalPaths(paths);
@@ -68604,7 +68846,7 @@ function createEmptyBranchKb(branch, workspaceRoot) {
68604
68846
  console.log(`Created branch KB: ${branch} (${kbPath})`);
68605
68847
  }
68606
68848
  async function branchEnsureCommand(options2) {
68607
- const workspaceRoot = path65.resolve(options2?.workspaceRoot ?? process.cwd());
68849
+ const workspaceRoot = path66.resolve(options2?.workspaceRoot ?? process.cwd());
68608
68850
  const branchResult = resolveBranchAttachment(workspaceRoot);
68609
68851
  if ("error" in branchResult) {
68610
68852
  console.error(getBranchDiagnostic(undefined, branchResult.error));
@@ -68625,7 +68867,7 @@ async function branchEnsureCommand(options2) {
68625
68867
  createEmptyBranchKb(currentBranch, workspaceRoot);
68626
68868
  }
68627
68869
  async function branchMigrateCommand(options2 = {}) {
68628
- const workspaceRoot = path65.resolve(options2.workspaceRoot ?? process.cwd());
68870
+ const workspaceRoot = path66.resolve(options2.workspaceRoot ?? process.cwd());
68629
68871
  if (options2.recoverJournal !== undefined) {
68630
68872
  recoverBranchMigration(workspaceRoot, options2.recoverJournal, options2.apply === true);
68631
68873
  return;
@@ -68699,18 +68941,18 @@ async function branchMigrateCommand(options2 = {}) {
68699
68941
  }
68700
68942
  fs8.mkdirSync(root, { recursive: true });
68701
68943
  const migrationId = `${Date.now()}-${from.replaceAll("/", "__")}-${to.replaceAll("/", "__")}`;
68702
- const journalPath = path65.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${migrationId}.json`);
68944
+ const journalPath = path66.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${migrationId}.json`);
68703
68945
  const stagingPath = `${targetPath}.staging-${process.pid}-${Date.now()}`;
68704
- const backupPath = path65.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${migrationId}-legacy`);
68705
- fs8.mkdirSync(path65.dirname(backupPath), { recursive: true });
68946
+ const backupPath = path66.join(workspaceRoot, ".kb", "recovery", "branch-migrations", `${migrationId}-legacy`);
68947
+ fs8.mkdirSync(path66.dirname(backupPath), { recursive: true });
68706
68948
  const journal = {
68707
68949
  version: 2,
68708
68950
  from,
68709
68951
  to,
68710
- sourcePath: path65.relative(workspaceRoot, sourcePath),
68711
- targetPath: path65.relative(workspaceRoot, targetPath),
68712
- stagingPath: path65.relative(workspaceRoot, stagingPath),
68713
- backupPath: path65.relative(workspaceRoot, backupPath),
68952
+ sourcePath: path66.relative(workspaceRoot, sourcePath),
68953
+ targetPath: path66.relative(workspaceRoot, targetPath),
68954
+ stagingPath: path66.relative(workspaceRoot, stagingPath),
68955
+ backupPath: path66.relative(workspaceRoot, backupPath),
68714
68956
  approvalHash,
68715
68957
  state: "prepared"
68716
68958
  };
@@ -68747,7 +68989,7 @@ async function branchMigrateCommand(options2 = {}) {
68747
68989
  }
68748
68990
  }
68749
68991
  async function branchRecoverCommand(options2 = {}) {
68750
- const workspaceRoot = path65.resolve(options2.workspaceRoot ?? process.cwd());
68992
+ const workspaceRoot = path66.resolve(options2.workspaceRoot ?? process.cwd());
68751
68993
  const attachment = resolveBranchAttachment(workspaceRoot);
68752
68994
  if ("error" in attachment) {
68753
68995
  throw new Error(`Failed to resolve active branch: ${attachment.error}`);
@@ -68760,7 +69002,7 @@ async function branchRecoverCommand(options2 = {}) {
68760
69002
  throw new Error(`Branch KB is missing at ${inspection.path}; run 'kibi branch ensure' instead.`);
68761
69003
  }
68762
69004
  const stamp = new Date().toISOString().replaceAll(":", "-");
68763
- const backupPath = path65.join(workspaceRoot, ".kb", "recovery", attachment.kbBranch, stamp);
69005
+ const backupPath = path66.join(workspaceRoot, ".kb", "recovery", attachment.kbBranch, stamp);
68764
69006
  console.log(`Branch KB recovery preview: ${attachment.kbBranch}`);
68765
69007
  console.log(`Store: ${inspection.path}`);
68766
69008
  console.log(`State: ${inspection.state}${inspection.errorCode ? ` (${inspection.errorCode})` : ""}`);
@@ -68784,15 +69026,15 @@ async function branchRecoverCommand(options2 = {}) {
68784
69026
  if (!checkpoint.success) {
68785
69027
  throw new Error("Recovered branch KB could not establish a fresh checkpoint.");
68786
69028
  }
68787
- const auditPath = path65.join(workspaceRoot, ".kb", "migrations", `${attachment.kbBranch.replaceAll("/", "__")}.recovery.json`);
68788
- fs8.mkdirSync(path65.dirname(auditPath), { recursive: true });
69029
+ const auditPath = path66.join(workspaceRoot, ".kb", "migrations", `${attachment.kbBranch.replaceAll("/", "__")}.recovery.json`);
69030
+ fs8.mkdirSync(path66.dirname(auditPath), { recursive: true });
68789
69031
  fs8.writeFileSync(auditPath, `${JSON.stringify({
68790
69032
  version: 1,
68791
69033
  branch: attachment.kbBranch,
68792
69034
  recoveredAt: new Date().toISOString(),
68793
69035
  priorState: inspection.state,
68794
69036
  priorErrorCode: inspection.errorCode ?? null,
68795
- backupPath: path65.relative(workspaceRoot, backupPath),
69037
+ backupPath: path66.relative(workspaceRoot, backupPath),
68796
69038
  strategy: "rebuild_from_authored_sources"
68797
69039
  }, null, 2)}
68798
69040
  `, "utf8");
@@ -68809,7 +69051,7 @@ var init_branch = __esm(() => {
68809
69051
 
68810
69052
  // ../cli/dist/operations/migration/inventory-rederive.js
68811
69053
  import { createHash as createHash34 } from "node:crypto";
68812
- import path66 from "node:path";
69054
+ import path67 from "node:path";
68813
69055
  import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
68814
69056
  function isRecord17(value) {
68815
69057
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -68856,7 +69098,7 @@ class FactClaimIndex {
68856
69098
  this.workspaceRoot = workspaceRoot;
68857
69099
  }
68858
69100
  claimKey(factId) {
68859
- const direct = path66.join(this.workspaceRoot, KB_PATHS.lanes.facts, `${factId}.md`);
69101
+ const direct = path67.join(this.workspaceRoot, KB_PATHS.lanes.facts, `${factId}.md`);
68860
69102
  try {
68861
69103
  const result = extractFromMarkdown(direct);
68862
69104
  if (result.entity.id === factId)
@@ -69030,7 +69272,7 @@ function planOne(workspaceRoot, relativePath, entity, extracted, shards, facts)
69030
69272
  }
69031
69273
  function readShardRelationships(workspaceRoot) {
69032
69274
  try {
69033
- return readAllShards(path66.join(workspaceRoot, ".kb")).map(({ type, from, to }) => ({ type, from, to }));
69275
+ return readAllShards(path67.join(workspaceRoot, ".kb")).map(({ type, from, to }) => ({ type, from, to }));
69034
69276
  } catch {
69035
69277
  return [];
69036
69278
  }
@@ -69040,7 +69282,7 @@ function planInventoryRederivation(workspaceRoot, onlyId) {
69040
69282
  const facts = new FactClaimIndex(workspaceRoot);
69041
69283
  const plans = [];
69042
69284
  const files = listLaneMarkdownFiles(workspaceRoot, ["requirements"]);
69043
- const preferred = onlyId === undefined ? files : files.filter((file) => path66.basename(file.relativePath, ".md") === onlyId);
69285
+ const preferred = onlyId === undefined ? files : files.filter((file) => path67.basename(file.relativePath, ".md") === onlyId);
69044
69286
  for (const file of preferred.length > 0 ? preferred : files) {
69045
69287
  let result;
69046
69288
  try {
@@ -69137,7 +69379,7 @@ function applyInventoryRederivation(workspaceRoot, requirementId, expectedContra
69137
69379
  if (expectedContractHash !== undefined && plan.contractHash !== expectedContractHash) {
69138
69380
  throw new Error(`Requirement ${requirementId} changed since planning; rerun kibi migrate and approve the new plan.`);
69139
69381
  }
69140
- const absolute = path66.join(workspaceRoot, plan.path);
69382
+ const absolute = path67.join(workspaceRoot, plan.path);
69141
69383
  const content = readText(absolute);
69142
69384
  const next = content === null ? null : rewriteContract(content, plan.contract);
69143
69385
  if (next === null) {
@@ -69183,7 +69425,7 @@ var init_inventory_rederive = __esm(() => {
69183
69425
  });
69184
69426
 
69185
69427
  // ../cli/dist/operations/migration/origin-backfill.js
69186
- import path67 from "node:path";
69428
+ import path68 from "node:path";
69187
69429
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
69188
69430
  function isRecord18(value) {
69189
69431
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -69225,8 +69467,8 @@ function inspect(workspaceRoot, absolutePath, relativePath) {
69225
69467
  migrated: "origin" in origin && origin.origin.kind === "migration" && origin.origin.ref === SCHEMA6_MIGRATION_ORIGIN_REF
69226
69468
  };
69227
69469
  }
69228
- const id = typeof data.id === "string" && data.id.trim() !== "" ? data.id.trim() : path67.basename(relativePath, ".md");
69229
- const type = typeof data.type === "string" ? data.type : inferTypeFromPath(path67.join(workspaceRoot, relativePath)) ?? "";
69470
+ const id = typeof data.id === "string" && data.id.trim() !== "" ? data.id.trim() : path68.basename(relativePath, ".md");
69471
+ const type = typeof data.type === "string" ? data.type : inferTypeFromPath(path68.join(workspaceRoot, relativePath)) ?? "";
69230
69472
  return { kind: "target", target: { id, type, path: relativePath }, content };
69231
69473
  }
69232
69474
  function planOriginBackfill(workspaceRoot) {
@@ -69307,7 +69549,7 @@ var init_origin_backfill = __esm(() => {
69307
69549
  });
69308
69550
 
69309
69551
  // ../cli/dist/operations/migration/superseded-closure.js
69310
- import path68 from "node:path";
69552
+ import path69 from "node:path";
69311
69553
  function reachable(adjacency, start) {
69312
69554
  const seen = new Set;
69313
69555
  const queue = [...adjacency.get(start) ?? []];
@@ -69359,7 +69601,7 @@ function readRequirementsAndEdges(workspaceRoot) {
69359
69601
  } catch {}
69360
69602
  }
69361
69603
  try {
69362
- relationships.push(...readAllShards(path68.join(workspaceRoot, ".kb")));
69604
+ relationships.push(...readAllShards(path69.join(workspaceRoot, ".kb")));
69363
69605
  } catch {}
69364
69606
  const edges = new Map;
69365
69607
  for (const relationship of relationships) {
@@ -69415,7 +69657,7 @@ function applySupersededClosures(workspaceRoot, planned) {
69415
69657
  for (const closure of planSupersededClosures(workspaceRoot).closures) {
69416
69658
  if (planned !== undefined && !planned.has(closure.id))
69417
69659
  continue;
69418
- const absolute = path68.join(workspaceRoot, closure.path);
69660
+ const absolute = path69.join(workspaceRoot, closure.path);
69419
69661
  const content = readText(absolute);
69420
69662
  const next = content === null ? null : withTopLevelField(content, "status", CLOSED_REQUIREMENT_STATUS);
69421
69663
  if (next === null) {
@@ -69438,11 +69680,11 @@ var init_superseded_closure = __esm(() => {
69438
69680
  });
69439
69681
 
69440
69682
  // ../cli/dist/commands/init-helpers.js
69441
- import { constants as constants3, chmodSync as chmodSync2, copyFileSync as copyFileSync3, existsSync as existsSync36, lstatSync as lstatSync5, mkdirSync as mkdirSync14, readFileSync as readFileSync39, writeFileSync as writeFileSync17 } from "node:fs";
69442
- import * as path69 from "node:path";
69683
+ import { constants as constants3, chmodSync as chmodSync2, copyFileSync as copyFileSync3, existsSync as existsSync36, lstatSync as lstatSync5, mkdirSync as mkdirSync14, readFileSync as readFileSync40, writeFileSync as writeFileSync17 } from "node:fs";
69684
+ import * as path70 from "node:path";
69443
69685
  function updateGitIgnore(cwd) {
69444
- const gitignorePath = path69.join(cwd, ".gitignore");
69445
- const gitignoreContent = existsSync36(gitignorePath) ? readFileSync39(gitignorePath, "utf8") : "";
69686
+ const gitignorePath = path70.join(cwd, ".gitignore");
69687
+ const gitignoreContent = existsSync36(gitignorePath) ? readFileSync40(gitignorePath, "utf8") : "";
69446
69688
  const ensureEntry = (current, entry) => {
69447
69689
  const lines = current.split(/\r?\n/).map((line) => line.trim());
69448
69690
  if (lines.includes(entry)) {
@@ -69599,8 +69841,8 @@ ${KIBI_BIN_RESOLVER}
69599
69841
 
69600
69842
  // ../cli/dist/commands/legacy-storage-migration.js
69601
69843
  import { createHash as createHash35 } from "node:crypto";
69602
- import { existsSync as existsSync37, mkdirSync as mkdirSync15, readFileSync as readFileSync40, readdirSync as readdirSync11, renameSync as renameSync12, rmSync as rmSync5, statSync as statSync12, writeFileSync as writeFileSync18 } from "node:fs";
69603
- import * as path70 from "node:path";
69844
+ import { existsSync as existsSync37, mkdirSync as mkdirSync15, readFileSync as readFileSync41, readdirSync as readdirSync11, renameSync as renameSync12, rmSync as rmSync5, statSync as statSync12, writeFileSync as writeFileSync18 } from "node:fs";
69845
+ import * as path71 from "node:path";
69604
69846
  function stripGlobToRoot(pattern) {
69605
69847
  const normalized = pattern.replaceAll("\\", "/").replace(/\/+$/, "");
69606
69848
  if (!normalized.includes("*"))
@@ -69638,8 +69880,8 @@ function planLegacyStorageMigration(cwd) {
69638
69880
  if (typeof legacy !== "string" || legacy.trim().length === 0)
69639
69881
  continue;
69640
69882
  const { root, glob } = normalizeLegacySource(legacy);
69641
- const legacyRoot = path70.resolve(cwd, root);
69642
- if (legacyRoot === path70.resolve(cwd, KB_PATHS.lanes[lane]))
69883
+ const legacyRoot = path71.resolve(cwd, root);
69884
+ if (legacyRoot === path71.resolve(cwd, KB_PATHS.lanes[lane]))
69643
69885
  continue;
69644
69886
  if (!existsSync37(legacyRoot))
69645
69887
  continue;
@@ -69650,37 +69892,37 @@ function planLegacyStorageMigration(cwd) {
69650
69892
  onlyFiles: true
69651
69893
  });
69652
69894
  for (const file of files.sort()) {
69653
- const relativeUnderRoot = path70.relative(legacyRoot, file);
69654
- const destination = path70.join(cwd, KB_PATHS.lanes[lane], relativeUnderRoot);
69895
+ const relativeUnderRoot = path71.relative(legacyRoot, file);
69896
+ const destination = path71.join(cwd, KB_PATHS.lanes[lane], relativeUnderRoot);
69655
69897
  moves.push({
69656
- from: path70.relative(cwd, file).replaceAll(path70.sep, "/"),
69657
- to: path70.relative(cwd, destination).replaceAll(path70.sep, "/"),
69898
+ from: path71.relative(cwd, file).replaceAll(path71.sep, "/"),
69899
+ to: path71.relative(cwd, destination).replaceAll(path71.sep, "/"),
69658
69900
  lane
69659
69901
  });
69660
69902
  }
69661
69903
  }
69662
69904
  const legacySymbols = legacyPaths.symbols;
69663
69905
  if (typeof legacySymbols === "string" && legacySymbols.trim().length > 0) {
69664
- const legacyManifest = path70.resolve(cwd, legacySymbols);
69665
- if (existsSync37(legacyManifest) && legacyManifest !== path70.resolve(cwd, CANONICAL_ENTITY_PATHS.symbols)) {
69906
+ const legacyManifest = path71.resolve(cwd, legacySymbols);
69907
+ if (existsSync37(legacyManifest) && legacyManifest !== path71.resolve(cwd, CANONICAL_ENTITY_PATHS.symbols)) {
69666
69908
  moves.push({
69667
- from: path70.relative(cwd, legacyManifest).replaceAll(path70.sep, "/"),
69909
+ from: path71.relative(cwd, legacyManifest).replaceAll(path71.sep, "/"),
69668
69910
  to: CANONICAL_ENTITY_PATHS.symbols,
69669
69911
  lane: "symbols"
69670
69912
  });
69671
69913
  }
69672
69914
  const legacyCoordinates = legacySymbols.replace(/\.ya?ml$/, ".yaml").replace(/symbols\.yaml$/, "symbol-coordinates.yaml");
69673
- const legacyCoordinatesPath = path70.resolve(cwd, legacyCoordinates);
69674
- if (existsSync37(legacyCoordinatesPath) && legacyCoordinatesPath !== path70.resolve(cwd, KB_PATHS.symbolCoordinates)) {
69915
+ const legacyCoordinatesPath = path71.resolve(cwd, legacyCoordinates);
69916
+ if (existsSync37(legacyCoordinatesPath) && legacyCoordinatesPath !== path71.resolve(cwd, KB_PATHS.symbolCoordinates)) {
69675
69917
  moves.push({
69676
- from: path70.relative(cwd, legacyCoordinatesPath).replaceAll(path70.sep, "/"),
69918
+ from: path71.relative(cwd, legacyCoordinatesPath).replaceAll(path71.sep, "/"),
69677
69919
  to: KB_PATHS.symbolCoordinates,
69678
69920
  lane: "symbols"
69679
69921
  });
69680
69922
  }
69681
69923
  }
69682
69924
  for (const move of moves) {
69683
- const destinationAbsolute = path70.resolve(cwd, move.to);
69925
+ const destinationAbsolute = path71.resolve(cwd, move.to);
69684
69926
  if (!existsSync37(destinationAbsolute))
69685
69927
  continue;
69686
69928
  blockers.push(`Destination ${move.to} already exists; resolve the conflict manually before migrating ${move.from}.`);
@@ -69708,12 +69950,12 @@ function applyLegacyStorageMigration(cwd, plan) {
69708
69950
  }
69709
69951
  const movedFiles = [];
69710
69952
  for (const move of plan.moves) {
69711
- const sourceAbsolute = path70.resolve(cwd, move.from);
69712
- const destinationAbsolute = path70.resolve(cwd, move.to);
69953
+ const sourceAbsolute = path71.resolve(cwd, move.from);
69954
+ const destinationAbsolute = path71.resolve(cwd, move.to);
69713
69955
  if (!existsSync37(sourceAbsolute)) {
69714
69956
  continue;
69715
69957
  }
69716
- mkdirSync15(path70.dirname(destinationAbsolute), { recursive: true });
69958
+ mkdirSync15(path71.dirname(destinationAbsolute), { recursive: true });
69717
69959
  renameSync12(sourceAbsolute, destinationAbsolute);
69718
69960
  movedFiles.push(move.to);
69719
69961
  }
@@ -69727,7 +69969,7 @@ function applyLegacyStorageMigration(cwd, plan) {
69727
69969
  };
69728
69970
  const manifestPath = writeKbManifest(cwd, manifest);
69729
69971
  let retiredLegacyConfig = false;
69730
- const legacyConfigPath = path70.join(cwd, ".kb", "config.json");
69972
+ const legacyConfigPath = path71.join(cwd, ".kb", "config.json");
69731
69973
  if (existsSync37(legacyConfigPath)) {
69732
69974
  rmSync5(legacyConfigPath);
69733
69975
  retiredLegacyConfig = true;
@@ -69738,7 +69980,7 @@ function applyLegacyStorageMigration(cwd, plan) {
69738
69980
  return {
69739
69981
  movedFiles,
69740
69982
  retiredLegacyConfig,
69741
- manifestPath: path70.relative(cwd, manifestPath).replaceAll(path70.sep, "/"),
69983
+ manifestPath: path71.relative(cwd, manifestPath).replaceAll(path71.sep, "/"),
69742
69984
  schemaVersion: manifest.schemaVersion,
69743
69985
  semanticAdvisorBackfill: backfill
69744
69986
  };
@@ -69746,11 +69988,11 @@ function applyLegacyStorageMigration(cwd, plan) {
69746
69988
  function pruneEmptyLegacyDirs(cwd, plan) {
69747
69989
  const roots = new Set;
69748
69990
  for (const move of plan.moves) {
69749
- const absolute = path70.resolve(cwd, move.from);
69750
- let dir = path70.dirname(absolute);
69751
- while (dir.startsWith(path70.resolve(cwd)) && dir !== path70.resolve(cwd) && !dir.startsWith(path70.resolve(cwd, KB_ROOT2))) {
69991
+ const absolute = path71.resolve(cwd, move.from);
69992
+ let dir = path71.dirname(absolute);
69993
+ while (dir.startsWith(path71.resolve(cwd)) && dir !== path71.resolve(cwd) && !dir.startsWith(path71.resolve(cwd, KB_ROOT2))) {
69752
69994
  roots.add(dir);
69753
- dir = path70.dirname(dir);
69995
+ dir = path71.dirname(dir);
69754
69996
  }
69755
69997
  }
69756
69998
  const ordered = [...roots].sort((a, b) => b.length - a.length);
@@ -69763,7 +70005,7 @@ function pruneEmptyLegacyDirs(cwd, plan) {
69763
70005
  }
69764
70006
  }
69765
70007
  function rewritePendingSourceReceiptPaths(cwd, moves) {
69766
- const pendingRoot = path70.join(cwd, ".kb", "recovery", "pending-sources");
70008
+ const pendingRoot = path71.join(cwd, ".kb", "recovery", "pending-sources");
69767
70009
  if (!existsSync37(pendingRoot))
69768
70010
  return 0;
69769
70011
  const moveByFrom = new Map(moves.map((move) => [move.from, move.to]));
@@ -69771,9 +70013,9 @@ function rewritePendingSourceReceiptPaths(cwd, moves) {
69771
70013
  for (const name of readdirSync11(pendingRoot)) {
69772
70014
  if (!name.endsWith(".json"))
69773
70015
  continue;
69774
- const receiptPath = path70.join(pendingRoot, name);
70016
+ const receiptPath = path71.join(pendingRoot, name);
69775
70017
  try {
69776
- const raw = readFileSync40(receiptPath, "utf8");
70018
+ const raw = readFileSync41(receiptPath, "utf8");
69777
70019
  const receipt = JSON.parse(raw);
69778
70020
  if (typeof receipt.path !== "string")
69779
70021
  continue;
@@ -69781,10 +70023,10 @@ function rewritePendingSourceReceiptPaths(cwd, moves) {
69781
70023
  const destination = moveByFrom.get(normalized) ?? (normalized.startsWith("documentation/") ? normalized.replace(/^documentation\//, ".kb/") : undefined);
69782
70024
  if (destination === undefined || destination === normalized)
69783
70025
  continue;
69784
- const absolute = path70.resolve(cwd, destination);
70026
+ const absolute = path71.resolve(cwd, destination);
69785
70027
  if (!existsSync37(absolute))
69786
70028
  continue;
69787
- const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash : createHash35("sha256").update(readFileSync40(absolute)).digest("hex");
70029
+ const afterHash = typeof receipt.afterHash === "string" && /^[a-f0-9]{64}$/i.test(receipt.afterHash) ? receipt.afterHash : createHash35("sha256").update(readFileSync41(absolute)).digest("hex");
69788
70030
  writeFileSync18(receiptPath, `${JSON.stringify({ ...receipt, path: destination, afterHash }, null, 2)}
69789
70031
  `, "utf8");
69790
70032
  rewritten += 1;
@@ -70325,26 +70567,26 @@ var require_ignore = __commonJS(function(exports2, module2) {
70325
70567
  });
70326
70568
 
70327
70569
  // ../cli/dist/public/ignore-policy.js
70328
- import { existsSync as existsSync38, readFileSync as readFileSync41, readdirSync as readdirSync12 } from "node:fs";
70329
- import * as path71 from "node:path";
70570
+ import { existsSync as existsSync38, readFileSync as readFileSync42, readdirSync as readdirSync12 } from "node:fs";
70571
+ import * as path72 from "node:path";
70330
70572
  function readIgnoreFileLines(filePath) {
70331
70573
  if (!existsSync38(filePath))
70332
70574
  return [];
70333
70575
  try {
70334
- const content = readFileSync41(filePath, "utf8");
70576
+ const content = readFileSync42(filePath, "utf8");
70335
70577
  return content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#"));
70336
70578
  } catch {
70337
70579
  return [];
70338
70580
  }
70339
70581
  }
70340
70582
  function toPosix(p) {
70341
- return p.split(path71.sep).join("/");
70583
+ return p.split(path72.sep).join("/");
70342
70584
  }
70343
70585
  function createRepoIgnorePolicy(workspaceRoot) {
70344
- const root = path71.resolve(workspaceRoot);
70345
- const rootGitignorePath = path71.join(root, ".gitignore");
70586
+ const root = path72.resolve(workspaceRoot);
70587
+ const rootGitignorePath = path72.join(root, ".gitignore");
70346
70588
  const rootGitPatterns = readIgnoreFileLines(rootGitignorePath);
70347
- const gitInfoExcludePath = path71.join(root, ".git", "info", "exclude");
70589
+ const gitInfoExcludePath = path72.join(root, ".git", "info", "exclude");
70348
70590
  const gitInfoPatterns = readIgnoreFileLines(gitInfoExcludePath);
70349
70591
  const nestedPatterns = new Map;
70350
70592
  function walk(dirAbs) {
@@ -70356,7 +70598,7 @@ function createRepoIgnorePolicy(workspaceRoot) {
70356
70598
  }
70357
70599
  for (const ent of entries) {
70358
70600
  const name = String(ent.name);
70359
- const abs = path71.join(dirAbs, name);
70601
+ const abs = path72.join(dirAbs, name);
70360
70602
  if (ent.isDirectory()) {
70361
70603
  if (HARD_DENYLIST.includes(name))
70362
70604
  continue;
@@ -70367,10 +70609,10 @@ function createRepoIgnorePolicy(workspaceRoot) {
70367
70609
  walk(abs);
70368
70610
  } else if (ent.isFile()) {
70369
70611
  if (name === ".gitignore") {
70370
- if (path71.resolve(dirAbs) === root)
70612
+ if (path72.resolve(dirAbs) === root)
70371
70613
  continue;
70372
70614
  const patterns = readIgnoreFileLines(abs);
70373
- const relDir = path71.relative(root, dirAbs) || ".";
70615
+ const relDir = path72.relative(root, dirAbs) || ".";
70374
70616
  nestedPatterns.set(toPosix(relDir), patterns);
70375
70617
  }
70376
70618
  }
@@ -70392,8 +70634,8 @@ function createRepoIgnorePolicy(workspaceRoot) {
70392
70634
  }
70393
70635
  const nestedDirsSorted = Array.from(nestedIgnoreMap.keys()).sort((a, b) => b.length - a.length);
70394
70636
  function isPathOutsideWorkspace(absPath) {
70395
- const rel = path71.relative(root, absPath);
70396
- return rel === "" ? false : rel.split(path71.sep)[0] === "..";
70637
+ const rel = path72.relative(root, absPath);
70638
+ return rel === "" ? false : rel.split(path72.sep)[0] === "..";
70397
70639
  }
70398
70640
  function matchesHardDeny(relPosix) {
70399
70641
  const segments = relPosix.split("/").filter(Boolean);
@@ -70409,11 +70651,11 @@ function createRepoIgnorePolicy(workspaceRoot) {
70409
70651
  return false;
70410
70652
  }
70411
70653
  function isIgnoredInternal(inputPath) {
70412
- const abs = path71.isAbsolute(inputPath) ? path71.resolve(inputPath) : path71.resolve(root, inputPath);
70413
- if (path71.isAbsolute(inputPath) && isPathOutsideWorkspace(abs)) {
70654
+ const abs = path72.isAbsolute(inputPath) ? path72.resolve(inputPath) : path72.resolve(root, inputPath);
70655
+ if (path72.isAbsolute(inputPath) && isPathOutsideWorkspace(abs)) {
70414
70656
  return { ignored: true, reason: "outside_workspace" };
70415
70657
  }
70416
- const rel = path71.relative(root, abs) || ".";
70658
+ const rel = path72.relative(root, abs) || ".";
70417
70659
  const relPosix = toPosix(rel);
70418
70660
  if (matchesHardDeny(relPosix))
70419
70661
  return { ignored: true, reason: "hard_deny" };
@@ -70524,7 +70766,7 @@ import { execFile as execFile2, execFileSync as execFileSync8 } from "node:child
70524
70766
  import { createHash as createHash36 } from "node:crypto";
70525
70767
  import * as fsSync from "node:fs";
70526
70768
  import * as fs9 from "node:fs/promises";
70527
- import path72 from "node:path";
70769
+ import path73 from "node:path";
70528
70770
  import { promisify as promisify2 } from "node:util";
70529
70771
  function includedSnapshotPath(relativePath) {
70530
70772
  return !SNAPSHOT_EXCLUDED_PREFIXES.some((prefix) => relativePath === prefix.slice(0, -1) || relativePath.startsWith(prefix));
@@ -70533,7 +70775,7 @@ function isReceiptOnlyMarkdownChange(workspaceRoot, relativePath) {
70533
70775
  if (!relativePath.endsWith(".md"))
70534
70776
  return false;
70535
70777
  try {
70536
- const working = snapshotFileContent(relativePath, fsSync.readFileSync(path72.join(workspaceRoot, relativePath)));
70778
+ const working = snapshotFileContent(relativePath, fsSync.readFileSync(path73.join(workspaceRoot, relativePath)));
70537
70779
  const committed = execFileSync8("git", ["-C", workspaceRoot, "show", `HEAD:${relativePath}`], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 });
70538
70780
  return working.equals(snapshotFileContent(relativePath, committed));
70539
70781
  } catch {
@@ -70557,7 +70799,7 @@ async function workspaceSnapshot(workspaceRoot) {
70557
70799
  digest.update(relativePath);
70558
70800
  digest.update("\x00");
70559
70801
  try {
70560
- const content = await fs9.readFile(path72.join(workspaceRoot, raw));
70802
+ const content = await fs9.readFile(path73.join(workspaceRoot, raw));
70561
70803
  digest.update(snapshotFileContent(relativePath, content));
70562
70804
  } catch (error) {
70563
70805
  const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "unreadable";
@@ -70751,7 +70993,7 @@ var exports_cli_runtime = {};
70751
70993
  __export(exports_cli_runtime, {
70752
70994
  createCliRuntime: () => createCliRuntime
70753
70995
  });
70754
- import path73 from "node:path";
70996
+ import path74 from "node:path";
70755
70997
  function attachmentFailureMessage(attachment) {
70756
70998
  const isNonGitContext = attachment.code === "NOT_A_GIT_REPO" || attachment.code === "GIT_NOT_AVAILABLE";
70757
70999
  return isNonGitContext ? "Kibi requires an active Git branch outside a repository; set KIBI_BRANCH explicitly for a standalone workspace." : `Failed to resolve active branch: ${attachment.error}`;
@@ -70766,7 +71008,7 @@ function createDefaultProlog(root, branch) {
70766
71008
  }
70767
71009
  function workspaceRoot(options2) {
70768
71010
  const envRoot = process.env.KIBI_WORKSPACE ?? process.env.KIBI_PROJECT_ROOT ?? process.env.KIBI_ROOT;
70769
- return path73.resolve(options2.workspaceRoot ?? envRoot ?? process.cwd());
71011
+ return path74.resolve(options2.workspaceRoot ?? envRoot ?? process.cwd());
70770
71012
  }
70771
71013
  function quoteProlog2(value) {
70772
71014
  return value.replaceAll("'", "''");
@@ -71698,8 +71940,8 @@ var init_repair_plan = __esm(() => {
71698
71940
  });
71699
71941
 
71700
71942
  // ../cli/dist/public/operations/symbol-repair-plan.js
71701
- import { existsSync as existsSync39, readFileSync as readFileSync43 } from "node:fs";
71702
- import path74 from "node:path";
71943
+ import { existsSync as existsSync39, readFileSync as readFileSync44 } from "node:fs";
71944
+ import path75 from "node:path";
71703
71945
  function sourceFileOf(entity) {
71704
71946
  const value = entity.sourceFile ?? entity.source;
71705
71947
  return typeof value === "string" && value.trim() ? value.trim() : null;
@@ -71730,7 +71972,7 @@ async function inspectCoordinateRepairs(symbols, workspaceRoot) {
71730
71972
  let source = null;
71731
71973
  if (sourceFile) {
71732
71974
  try {
71733
- source = readFileSync43(path74.resolve(workspaceRoot, sourceFile), "utf8");
71975
+ source = readFileSync44(path75.resolve(workspaceRoot, sourceFile), "utf8");
71734
71976
  } catch {}
71735
71977
  }
71736
71978
  const extracted = entry.title.length > 0 && coordinatesPresent(enriched[index] ?? {});
@@ -71819,11 +72061,11 @@ async function buildSymbolRepairPlan(rows, context) {
71819
72061
  const source = sourceFileOf(symbol);
71820
72062
  if (!source || extractedByPath.has(source))
71821
72063
  continue;
71822
- const absolute = path74.isAbsolute(source) ? source : path74.resolve(context.workspaceRoot, source);
72064
+ const absolute = path75.isAbsolute(source) ? source : path75.resolve(context.workspaceRoot, source);
71823
72065
  if (!existsSync39(absolute))
71824
72066
  continue;
71825
72067
  try {
71826
- const content = readFileSync43(absolute, "utf8");
72068
+ const content = readFileSync44(absolute, "utf8");
71827
72069
  const analysis = analyzeSourceText(absolute, content);
71828
72070
  if (analysis.providerId === null)
71829
72071
  continue;
@@ -71841,7 +72083,7 @@ async function buildSymbolRepairPlan(rows, context) {
71841
72083
  if (!entity)
71842
72084
  return [];
71843
72085
  const source = sourceFileOf(entity);
71844
- const absolute = source ? path74.isAbsolute(source) ? source : path74.resolve(context.workspaceRoot, source) : null;
72086
+ const absolute = source ? path75.isAbsolute(source) ? source : path75.resolve(context.workspaceRoot, source) : null;
71845
72087
  const exists = absolute !== null && existsSync39(absolute);
71846
72088
  const candidates = currentCandidates(entity, symbols, extractedByPath);
71847
72089
  const extraction = source ? extractedByPath.get(source) : undefined;
@@ -72383,7 +72625,7 @@ __export(exports_schema6, {
72383
72625
  buildSchema6MigrationFragment: () => buildSchema6MigrationFragment,
72384
72626
  migrationSyncAction: () => migrationSyncAction
72385
72627
  });
72386
- import path75 from "node:path";
72628
+ import path76 from "node:path";
72387
72629
  function rederiveAction(plan) {
72388
72630
  const changed = plan.changes.filter((change) => change.change !== "kept");
72389
72631
  return migrationAction({
@@ -72450,7 +72692,7 @@ function unapprovedExceptionsFromSources(workspaceRoot) {
72450
72692
  } catch {}
72451
72693
  }
72452
72694
  try {
72453
- relationships.push(...readAllShards(path75.join(workspaceRoot, ".kb")));
72695
+ relationships.push(...readAllShards(path76.join(workspaceRoot, ".kb")));
72454
72696
  } catch {}
72455
72697
  const superseded = new Set(relationships.filter((relationship) => relationship.type === "supersedes").map((relationship) => relationship.to));
72456
72698
  const exempts = new Map;
@@ -73854,8 +74096,8 @@ var init_cli_json_command = __esm(() => {
73854
74096
  });
73855
74097
 
73856
74098
  // ../cli/dist/commands/migrate.js
73857
- import { existsSync as existsSync40, mkdirSync as mkdirSync16, readFileSync as readFileSync44, renameSync as renameSync13, writeFileSync as writeFileSync19 } from "node:fs";
73858
- import * as path76 from "node:path";
74099
+ import { existsSync as existsSync40, mkdirSync as mkdirSync16, readFileSync as readFileSync45, renameSync as renameSync13, writeFileSync as writeFileSync19 } from "node:fs";
74100
+ import * as path77 from "node:path";
73859
74101
  function migrationStepsFor(fromVersion) {
73860
74102
  const start = Math.max(0, fromVersion ?? 0);
73861
74103
  return SCHEMA_MIGRATION_STEPS.filter((step) => step.from >= start);
@@ -73864,8 +74106,8 @@ function printWarning(message) {
73864
74106
  console.log(`Warning: ${message}`);
73865
74107
  }
73866
74108
  function toRelativePath(cwd, filePath) {
73867
- const relativePath = path76.relative(cwd, filePath);
73868
- return relativePath.length > 0 ? relativePath : path76.basename(filePath);
74109
+ const relativePath = path77.relative(cwd, filePath);
74110
+ return relativePath.length > 0 ? relativePath : path77.basename(filePath);
73869
74111
  }
73870
74112
  function resolveMigrationBranch(cwd) {
73871
74113
  const result = resolveBranchAttachment(cwd);
@@ -73892,7 +74134,7 @@ function writeJsonAtomically(filePath, value) {
73892
74134
  `);
73893
74135
  }
73894
74136
  function writeTextAtomically(filePath, content) {
73895
- mkdirSync16(path76.dirname(filePath), { recursive: true });
74137
+ mkdirSync16(path77.dirname(filePath), { recursive: true });
73896
74138
  const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
73897
74139
  writeFileSync19(tempPath, content, "utf8");
73898
74140
  renameSync13(tempPath, filePath);
@@ -73944,7 +74186,7 @@ function hasTraceabilityRelationship2(symbol) {
73944
74186
  });
73945
74187
  }
73946
74188
  function getGranularNames(cwd, sourceFile) {
73947
- const absolutePath = path76.isAbsolute(sourceFile) ? sourceFile : path76.join(cwd, sourceFile);
74189
+ const absolutePath = path77.isAbsolute(sourceFile) ? sourceFile : path77.join(cwd, sourceFile);
73948
74190
  if (!existsSync40(absolutePath)) {
73949
74191
  return new Set;
73950
74192
  }
@@ -73952,7 +74194,7 @@ function getGranularNames(cwd, sourceFile) {
73952
74194
  path: sourceFile,
73953
74195
  status: "M",
73954
74196
  hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
73955
- content: readFileSync44(absolutePath, "utf8")
74197
+ content: readFileSync45(absolutePath, "utf8")
73956
74198
  });
73957
74199
  return new Set(symbols.map((symbol) => symbol.name));
73958
74200
  }
@@ -73994,11 +74236,11 @@ function addLegacyReasonsToManifestText(content, symbolIds) {
73994
74236
  `);
73995
74237
  }
73996
74238
  function migrateSymbolGranularity(options2) {
73997
- const manifestPath = options2.manifestPath ?? path76.join(options2.cwd, CANONICAL_ENTITY_PATHS.symbols);
74239
+ const manifestPath = options2.manifestPath ?? path77.join(options2.cwd, CANONICAL_ENTITY_PATHS.symbols);
73998
74240
  if (!existsSync40(manifestPath)) {
73999
74241
  return { count: 0, manifestPath };
74000
74242
  }
74001
- const manifestContent = readFileSync44(manifestPath, "utf8");
74243
+ const manifestContent = readFileSync45(manifestPath, "utf8");
74002
74244
  const parsed = load(manifestContent);
74003
74245
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
74004
74246
  return { count: 0, manifestPath };
@@ -74138,7 +74380,7 @@ async function migrateCommand(options2 = {}) {
74138
74380
  if (options2.applySafe === true || options2.format === "json" || options2.yes !== true && options2.dryRun !== true) {
74139
74381
  return migratePlanCommand(options2);
74140
74382
  }
74141
- const cwd = path76.resolve(options2.workspaceRoot ?? process.cwd());
74383
+ const cwd = path77.resolve(options2.workspaceRoot ?? process.cwd());
74142
74384
  const branchResult = resolveMigrationBranch(cwd);
74143
74385
  if ("error" in branchResult) {
74144
74386
  console.error(branchResult.error);
@@ -74166,7 +74408,7 @@ async function migrateCommand(options2 = {}) {
74166
74408
  ...branchWarnings,
74167
74409
  ...migrationWarning ? [migrationWarning] : []
74168
74410
  ];
74169
- const auditPath = path76.join(cwd, ".kb", "migrations", `${branch}.json`);
74411
+ const auditPath = path77.join(cwd, ".kb", "migrations", `${branch}.json`);
74170
74412
  for (const warning of warnings) {
74171
74413
  printWarning(warning);
74172
74414
  }
@@ -74240,7 +74482,7 @@ async function migrateCommand(options2 = {}) {
74240
74482
  const preview = migrateSymbolGranularity({
74241
74483
  cwd,
74242
74484
  dryRun: true,
74243
- manifestPath: path76.join(cwd, symbolsSource)
74485
+ manifestPath: path77.join(cwd, symbolsSource)
74244
74486
  });
74245
74487
  if (preview.count > 0) {
74246
74488
  console.log(`dry run: would mark ${preview.count} legacy coarse symbol link(s) as legacy-link.`);
@@ -74422,7 +74664,7 @@ async function buildWorkspaceMigrationPlan(workspaceRoot = process.cwd()) {
74422
74664
  return mergeMigrationPlans(plans);
74423
74665
  }
74424
74666
  async function migratePlanCommand(options2) {
74425
- const workspaceRoot = path76.resolve(options2.workspaceRoot ?? process.cwd());
74667
+ const workspaceRoot = path77.resolve(options2.workspaceRoot ?? process.cwd());
74426
74668
  const plan = await buildWorkspaceMigrationPlan(workspaceRoot);
74427
74669
  if (options2.applySafe === true) {
74428
74670
  if (!options2.approvedPlanHash) {
@@ -74545,7 +74787,7 @@ var init_migrate = __esm(() => {
74545
74787
 
74546
74788
  // ../cli/dist/operations/planning/compile-intent.js
74547
74789
  import { createHash as createHash39 } from "node:crypto";
74548
- import path77 from "node:path";
74790
+ import path78 from "node:path";
74549
74791
  function compilePlanHash(plan) {
74550
74792
  const { planHash: _ignored, ...body } = plan;
74551
74793
  return hash2(body);
@@ -74582,7 +74824,7 @@ function requiredIntent(args) {
74582
74824
  return intent;
74583
74825
  }
74584
74826
  function validateLocation(location) {
74585
- if (!text7(location.path) || path77.isAbsolute(location.path) || location.path.split(/[\\/]/).includes("..")) {
74827
+ if (!text7(location.path) || path78.isAbsolute(location.path) || location.path.split(/[\\/]/).includes("..")) {
74586
74828
  throw new Error("Compile intent failed: sourceLocations.path must be workspace-relative");
74587
74829
  }
74588
74830
  }
@@ -74700,7 +74942,7 @@ async function sourceHashes(context, locations) {
74700
74942
  const hashes = {};
74701
74943
  for (const relative of sourceFilesFor(locations)) {
74702
74944
  try {
74703
- const contents = context.fs ? await context.fs.readFile(path77.join(context.workspaceRoot, relative)) : null;
74945
+ const contents = context.fs ? await context.fs.readFile(path78.join(context.workspaceRoot, relative)) : null;
74704
74946
  hashes[relative] = contents === null ? null : createHash39("sha256").update(contents).digest("hex");
74705
74947
  } catch {
74706
74948
  hashes[relative] = null;
@@ -74757,7 +74999,7 @@ async function existingRequirementBody(context, source) {
74757
74999
  if (!context.fs || !source.endsWith(".md"))
74758
75000
  return;
74759
75001
  try {
74760
- const raw = await context.fs.readFile(path77.join(context.workspaceRoot, source));
75002
+ const raw = await context.fs.readFile(path78.join(context.workspaceRoot, source));
74761
75003
  return readAuthoredEntity(String(raw), source)?.body ?? undefined;
74762
75004
  } catch {
74763
75005
  return;
@@ -75287,7 +75529,7 @@ var init_compile_intent = __esm(() => {
75287
75529
 
75288
75530
  // ../cli/dist/operations/planning/apply-plan.js
75289
75531
  import { createHash as createHash40, randomUUID as randomUUID6 } from "node:crypto";
75290
- import path78 from "node:path";
75532
+ import path79 from "node:path";
75291
75533
  function text8(value) {
75292
75534
  return typeof value === "string" ? value.trim() : "";
75293
75535
  }
@@ -75352,7 +75594,7 @@ function isBootstrapApplyArgs(args) {
75352
75594
  return "plan" in args && args.plan.version === "kibi.bootstrap-plan.v1";
75353
75595
  }
75354
75596
  function assertSourceWriteStaysInWorkspace(root, absolute, writePath) {
75355
- if (absolute !== root && !absolute.startsWith(`${root}${path78.sep}`)) {
75597
+ if (absolute !== root && !absolute.startsWith(`${root}${path79.sep}`)) {
75356
75598
  throw new Error(`Apply plan failed: sourceWrites.path escapes workspace: ${writePath}`);
75357
75599
  }
75358
75600
  }
@@ -75532,13 +75774,13 @@ function topologicalActions(actions) {
75532
75774
  async function validateSources(context, sourceHashes) {
75533
75775
  let checked = 0;
75534
75776
  for (const [relative, expected] of Object.entries(sourceHashes)) {
75535
- if (!relative || path78.isAbsolute(relative) || relative.split(/[\\/]/).includes(".."))
75777
+ if (!relative || path79.isAbsolute(relative) || relative.split(/[\\/]/).includes(".."))
75536
75778
  throw new Error("Apply plan failed: source hash paths must be workspace-relative");
75537
75779
  if (!context.fs)
75538
75780
  throw new Error("Apply plan failed: source hashes require a filesystem-capable runtime");
75539
75781
  let actual;
75540
75782
  try {
75541
- actual = digest4(await context.fs.readFile(path78.join(context.workspaceRoot, relative)));
75783
+ actual = digest4(await context.fs.readFile(path79.join(context.workspaceRoot, relative)));
75542
75784
  } catch {
75543
75785
  actual = null;
75544
75786
  }
@@ -75549,19 +75791,19 @@ async function validateSources(context, sourceHashes) {
75549
75791
  return checked;
75550
75792
  }
75551
75793
  async function resolveSourceWriteTarget(workspaceRoot, fsPort, write) {
75552
- if (!write.path || path78.isAbsolute(write.path) || write.path.split(/[\\/]/).includes("..")) {
75794
+ if (!write.path || path79.isAbsolute(write.path) || write.path.split(/[\\/]/).includes("..")) {
75553
75795
  throw new Error(`Apply plan failed: sourceWrites.path must be workspace-relative: ${write.path}`);
75554
75796
  }
75555
- const absolute = path78.resolve(workspaceRoot, write.path);
75556
- const root = path78.resolve(workspaceRoot);
75797
+ const absolute = path79.resolve(workspaceRoot, write.path);
75798
+ const root = path79.resolve(workspaceRoot);
75557
75799
  assertSourceWriteStaysInWorkspace(root, absolute, write.path);
75558
- const relative = path78.relative(root, absolute).split(path78.sep).join("/");
75800
+ const relative = path79.relative(root, absolute).split(path79.sep).join("/");
75559
75801
  if (relative === ".kb" || isDerivedKbPath(relative)) {
75560
75802
  throw new Error("Apply plan failed: sourceWrites.path cannot target Kibi's derived .kb runtime trees");
75561
75803
  }
75562
75804
  const realRoot = canonicalFilesystemPath(root);
75563
75805
  const realExisting = canonicalFilesystemPath(absolute);
75564
- if (realExisting !== realRoot && !realExisting.startsWith(`${realRoot}${path78.sep}`)) {
75806
+ if (realExisting !== realRoot && !realExisting.startsWith(`${realRoot}${path79.sep}`)) {
75565
75807
  throw new Error(`Apply plan failed: sourceWrites.path follows a symlink outside the workspace: ${write.path}`);
75566
75808
  }
75567
75809
  const existing = await fsPort.readFile(absolute).catch(() => {
@@ -75592,7 +75834,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75592
75834
  throw new Error("Apply plan failed: sourceWrites require a filesystem-capable runtime");
75593
75835
  }
75594
75836
  const fsPort = context.fs;
75595
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `source-writes-${planHash.slice(0, 16)}.json`);
75837
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `source-writes-${planHash.slice(0, 16)}.json`);
75596
75838
  const journalId = `source-writes-${planHash.slice(0, 16)}`;
75597
75839
  const sameEntries = (entries) => entries.length === writes.length && entries.every((entry) => writes.some((write) => write.path === entry.path && (write.mode ?? "write") === entry.mode && write.beforeHash === entry.beforeHash && write.afterHash === entry.afterHash));
75598
75840
  const readJournal = async () => {
@@ -75615,7 +75857,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75615
75857
  let allAfter = true;
75616
75858
  for (const entry of prior.entries) {
75617
75859
  try {
75618
- const current = await context.fs.readFile(path78.resolve(context.workspaceRoot, entry.path));
75860
+ const current = await context.fs.readFile(path79.resolve(context.workspaceRoot, entry.path));
75619
75861
  if (entry.afterHash === null || digest4(current) !== entry.afterHash) {
75620
75862
  allAfter = false;
75621
75863
  }
@@ -75637,7 +75879,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75637
75879
  }
75638
75880
  if (prior && (prior.state === "prepared" || prior.state === "publishing_sources")) {
75639
75881
  for (const entry of prior.entries) {
75640
- const absolute = path78.resolve(context.workspaceRoot, entry.path);
75882
+ const absolute = path79.resolve(context.workspaceRoot, entry.path);
75641
75883
  let current;
75642
75884
  try {
75643
75885
  current = await context.fs.readFile(absolute);
@@ -75670,7 +75912,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75670
75912
  const { absolute, existing, mode } = await resolveSourceWriteTarget(context.workspaceRoot, fsPort, write);
75671
75913
  originals.push({ absolute, body: existing });
75672
75914
  paths.push(write.path);
75673
- const stageBase = path78.join(context.workspaceRoot, ".kb", "recovery", `${journalId}-${entries.length}`);
75915
+ const stageBase = path79.join(context.workspaceRoot, ".kb", "recovery", `${journalId}-${entries.length}`);
75674
75916
  entries.push({
75675
75917
  path: write.path,
75676
75918
  mode,
@@ -75681,7 +75923,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75681
75923
  afterStage: `${stageBase}.after`
75682
75924
  });
75683
75925
  }
75684
- await context.fs.mkdir(path78.dirname(journalPath));
75926
+ await context.fs.mkdir(path79.dirname(journalPath));
75685
75927
  for (let index = 0;index < writes.length; index += 1) {
75686
75928
  const original = originals[index];
75687
75929
  const entry = entries[index];
@@ -75702,7 +75944,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75702
75944
  const write = writes[index];
75703
75945
  if (!absolute || !write)
75704
75946
  continue;
75705
- await context.fs.mkdir(path78.dirname(absolute));
75947
+ await context.fs.mkdir(path79.dirname(absolute));
75706
75948
  await context.fs.writeFile(journalPath, `${JSON.stringify({ version: 1, planHash, state: "publishing_sources", entries }, null, 2)}
75707
75949
  `);
75708
75950
  if ((write.mode ?? "write") === "delete") {
@@ -75754,7 +75996,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75754
75996
  } catch {}
75755
75997
  }
75756
75998
  try {
75757
- await context.fs.mkdir(path78.dirname(journalPath));
75999
+ await context.fs.mkdir(path79.dirname(journalPath));
75758
76000
  await context.fs.writeFile(journalPath, `${JSON.stringify({ version: 1, planHash, state: "rolled_back", entries }, null, 2)}
75759
76001
  `);
75760
76002
  } catch {}
@@ -75771,7 +76013,7 @@ async function applySourceWrites(context, writes, planHash, allowReplay = false,
75771
76013
  async function markSourceJournal(context, journalId, state) {
75772
76014
  if (!journalId || !context.fs)
75773
76015
  return;
75774
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
76016
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
75775
76017
  try {
75776
76018
  const current = JSON.parse(await context.fs.readFile(journalPath));
75777
76019
  await context.fs.writeFile(journalPath, `${JSON.stringify({ ...current, state }, null, 2)}
@@ -75786,7 +76028,7 @@ async function executeSourceRecovery(args, context, onCommitted = () => {
75786
76028
  if (!/^[A-Za-z0-9._-]+$/.test(args.recoveryJournalId)) {
75787
76029
  throw new Error("Source recovery journal ID is invalid");
75788
76030
  }
75789
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
76031
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
75790
76032
  const journal = JSON.parse(await context.fs.readFile(journalPath));
75791
76033
  if (journal.version !== 1 || typeof journal.planHash !== "string" || !Array.isArray(journal.entries) || !["sources_committed", "compiled_published", "repair_required"].includes(journal.state ?? "")) {
75792
76034
  throw new Error("Source recovery requires a committed or repair_required journal");
@@ -75902,7 +76144,7 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
75902
76144
  if (!status)
75903
76145
  throw new Error("Bootstrap apply failed: status returned no payload");
75904
76146
  const journalId = `bootstrap-${args.plan.planHash.slice(0, 16)}`;
75905
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
76147
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `${journalId}.json`);
75906
76148
  if (!recovery && context.fs) {
75907
76149
  try {
75908
76150
  await context.fs.readFile(journalPath);
@@ -75935,7 +76177,7 @@ async function executeBootstrapPlan(args, context, recovery = false, remainingAc
75935
76177
  const writeJournal = async (state, activeActionId, currentCheckpoint = lastCheckpoint) => {
75936
76178
  if (!context.fs)
75937
76179
  return;
75938
- await context.fs.mkdir(path78.dirname(journalPath));
76180
+ await context.fs.mkdir(path79.dirname(journalPath));
75939
76181
  await context.fs.writeFile(journalPath, `${JSON.stringify({
75940
76182
  version: 2,
75941
76183
  kind: "bootstrap",
@@ -76205,7 +76447,7 @@ async function dispatchApplyPlan(args, context, onCommitted, recovered) {
76205
76447
  throw new Error("Bootstrap recovery requires a filesystem-capable runtime");
76206
76448
  if (!/^bootstrap-[a-f0-9]{16}$/.test(args.recoveryJournalId))
76207
76449
  throw new Error("Bootstrap recovery journal ID is invalid");
76208
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
76450
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
76209
76451
  const journal = JSON.parse(await context.fs.readFile(journalPath));
76210
76452
  if (journal.version !== 2 || journal.kind !== "bootstrap" || !journal.plan)
76211
76453
  throw new Error("Bootstrap recovery journal is invalid");
@@ -76389,7 +76631,7 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
76389
76631
  const relative = canonicalSourcePath(context, step.input, step.entity, existing);
76390
76632
  let file = files.get(relative);
76391
76633
  if (file === undefined) {
76392
- const existingBytes = await fsPort.readFile(path78.join(workspaceRoot, relative)).catch(() => {
76634
+ const existingBytes = await fsPort.readFile(path79.join(workspaceRoot, relative)).catch(() => {
76393
76635
  return;
76394
76636
  });
76395
76637
  const before = existingBytes ?? null;
@@ -76414,8 +76656,8 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
76414
76656
  file.after = after;
76415
76657
  file.afterHash = contentHash(after);
76416
76658
  }
76417
- const root = path78.resolve(workspaceRoot);
76418
- const kbRoot = path78.join(workspaceRoot, ".kb");
76659
+ const root = path79.resolve(workspaceRoot);
76660
+ const kbRoot = path79.join(workspaceRoot, ".kb");
76419
76661
  const createdAt = now.toISOString();
76420
76662
  for (const step of steps) {
76421
76663
  for (const relationship of step.relationships) {
@@ -76426,7 +76668,7 @@ async function planFileWrites(context, prolog, fsPort, sourceWrites, steps, now)
76426
76668
  continue;
76427
76669
  const shardPath = computeShardPath(kbRoot, from);
76428
76670
  assertRelationshipShardContained(workspaceRoot, shardPath);
76429
- const relative = path78.relative(root, path78.resolve(shardPath)).split(path78.sep).join("/");
76671
+ const relative = path79.relative(root, path79.resolve(shardPath)).split(path79.sep).join("/");
76430
76672
  let file = files.get(relative);
76431
76673
  if (file === undefined) {
76432
76674
  const existing = await fsPort.readFile(shardPath).catch(() => null);
@@ -76911,7 +77153,7 @@ async function applyingBootstrapJournal(args, context) {
76911
77153
  return;
76912
77154
  if (!/^bootstrap-[a-f0-9]{16}$/.test(args.recoveryJournalId))
76913
77155
  return;
76914
- const journalPath = path78.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
77156
+ const journalPath = path79.join(context.workspaceRoot, ".kb", "recovery", `${args.recoveryJournalId}.json`);
76915
77157
  try {
76916
77158
  const journal = JSON.parse(await context.fs.readFile(journalPath));
76917
77159
  return journal.kind === "bootstrap" && journal.state === "applying" ? journalPath : undefined;
@@ -77631,10 +77873,10 @@ function evaluateContractAgainstRun(artifact, contract) {
77631
77873
  var MAX_ATTRIBUTED_MEMBERS = 5;
77632
77874
 
77633
77875
  // ../cli/dist/proof/integrations.js
77634
- import { existsSync as existsSync41, readFileSync as readFileSync45 } from "node:fs";
77635
- import path79 from "node:path";
77876
+ import { existsSync as existsSync41, readFileSync as readFileSync46 } from "node:fs";
77877
+ import path80 from "node:path";
77636
77878
  function integrationsPath(workspaceRoot) {
77637
- return path79.join(workspaceRoot, PROOF_INTEGRATIONS_PATH);
77879
+ return path80.join(workspaceRoot, PROOF_INTEGRATIONS_PATH);
77638
77880
  }
77639
77881
  function proofIntegrationErrors(value) {
77640
77882
  const file = record5(value);
@@ -77691,7 +77933,7 @@ function loadProofIntegrations(workspaceRoot) {
77691
77933
  }
77692
77934
  let parsed;
77693
77935
  try {
77694
- parsed = JSON.parse(readFileSync45(filePath, "utf8"));
77936
+ parsed = JSON.parse(readFileSync46(filePath, "utf8"));
77695
77937
  } catch (error) {
77696
77938
  return {
77697
77939
  available: false,
@@ -78539,9 +78781,9 @@ init_ir();
78539
78781
  import { createHash as createHash41 } from "node:crypto";
78540
78782
 
78541
78783
  // src/skill-system/loader.ts
78542
- import { existsSync as existsSync44, readFileSync as readFileSync47, readdirSync as readdirSync13, realpathSync as realpathSync10 } from "node:fs";
78784
+ import { existsSync as existsSync44, readFileSync as readFileSync48, readdirSync as readdirSync13, realpathSync as realpathSync10 } from "node:fs";
78543
78785
  import { dirname as dirname21, join as join32, resolve as resolve29 } from "node:path";
78544
- import { fileURLToPath as fileURLToPath4 } from "node:url";
78786
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
78545
78787
 
78546
78788
  // src/skill-system/errors.ts
78547
78789
  class SkillNotFoundError2 extends Error {
@@ -78724,7 +78966,7 @@ function isStringArray2(value) {
78724
78966
  }
78725
78967
 
78726
78968
  // src/skill-system/loader.ts
78727
- var moduleDir = dirname21(fileURLToPath4(import.meta.url));
78969
+ var moduleDir = dirname21(fileURLToPath5(import.meta.url));
78728
78970
  var overrideSkillsDir;
78729
78971
  function defaultBundledSkillsDir2() {
78730
78972
  return existsSync44(resolve29(moduleDir, "skills")) ? resolve29(moduleDir, "skills") : resolve29(moduleDir, "../skills");
@@ -78785,7 +79027,7 @@ function readBundle2(bundle, id, resourcePath) {
78785
79027
  throw new SkillResourceNotFoundError2(id, resourcePath);
78786
79028
  }
78787
79029
  assertMaxBytes2(candidate, RESOURCE_MAX_BYTES2);
78788
- return readFileSync47(candidate, "utf8");
79030
+ return readFileSync48(candidate, "utf8");
78789
79031
  }
78790
79032
  // src/skill-operations.ts
78791
79033
  function assertNonEmptyString2(value, field) {
@@ -78942,7 +79184,7 @@ init_symbols_coordinator2();
78942
79184
  // ../cli/dist/env/bootstrap.js
78943
79185
  import fs11 from "node:fs";
78944
79186
  import os2 from "node:os";
78945
- import path80 from "node:path";
79187
+ import path81 from "node:path";
78946
79188
  var WORKSPACE_ENV_KEYS = [
78947
79189
  "KIBI_WORKSPACE",
78948
79190
  "KIBI_PROJECT_ROOT",
@@ -78968,13 +79210,13 @@ function readFirstEnv(env, keys) {
78968
79210
  return null;
78969
79211
  }
78970
79212
  function nextAncestorDirectory2(current) {
78971
- const parent = path80.dirname(current);
79213
+ const parent = path81.dirname(current);
78972
79214
  return parent === current ? undefined : parent;
78973
79215
  }
78974
79216
  function findUpwards(startDir, marker) {
78975
- let current = path80.resolve(startDir);
79217
+ let current = path81.resolve(startDir);
78976
79218
  while (current !== undefined) {
78977
- if (fs11.existsSync(path80.join(current, marker))) {
79219
+ if (fs11.existsSync(path81.join(current, marker))) {
78978
79220
  return current;
78979
79221
  }
78980
79222
  current = nextAncestorDirectory2(current);
@@ -78984,24 +79226,24 @@ function findUpwards(startDir, marker) {
78984
79226
  function resolveKibiWorkspaceRoot(startDir = process.cwd(), env = process.env) {
78985
79227
  const envRoot = readFirstEnv(env, WORKSPACE_ENV_KEYS);
78986
79228
  if (envRoot)
78987
- return path80.resolve(envRoot);
79229
+ return path81.resolve(envRoot);
78988
79230
  const kbRoot = findUpwards(startDir, ".kb");
78989
79231
  if (kbRoot)
78990
79232
  return kbRoot;
78991
79233
  const gitRoot = findUpwards(startDir, ".git");
78992
79234
  if (gitRoot)
78993
79235
  return gitRoot;
78994
- return path80.resolve(startDir);
79236
+ return path81.resolve(startDir);
78995
79237
  }
78996
79238
  function resolveEnvFilePath(envFileName, workspaceRoot) {
78997
- if (path80.isAbsolute(envFileName))
79239
+ if (path81.isAbsolute(envFileName))
78998
79240
  return envFileName;
78999
- return path80.resolve(workspaceRoot, envFileName);
79241
+ return path81.resolve(workspaceRoot, envFileName);
79000
79242
  }
79001
79243
  function resolveKibiUserEnvPath(options2 = {}) {
79002
79244
  const env = options2.env ?? process.env;
79003
- const xdg = options2.xdgConfigHome?.trim() || env.XDG_CONFIG_HOME?.trim() || path80.join(options2.homedir ?? os2.homedir(), ".config");
79004
- return path80.join(xdg, "kibi", "env");
79245
+ const xdg = options2.xdgConfigHome?.trim() || env.XDG_CONFIG_HOME?.trim() || path81.join(options2.homedir ?? os2.homedir(), ".config");
79246
+ return path81.join(xdg, "kibi", "env");
79005
79247
  }
79006
79248
  function resolveKibiProjectEnvPath(workspaceRoot, env = process.env) {
79007
79249
  const override = env.KIBI_ENV_FILE?.trim();