@agentskit/doc-bridge 1.11.1 → 1.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/README.md +3 -2
  3. package/action.yml +1 -1
  4. package/dist/cli/program.js +582 -471
  5. package/dist/cli/program.js.map +1 -1
  6. package/dist/index.d.ts +7 -2
  7. package/dist/index.js +500 -389
  8. package/dist/index.js.map +1 -1
  9. package/docs/DESIGN.md +71 -0
  10. package/docs/MARKETPLACE-ECOSYSTEM-PLAN.md +1 -1
  11. package/docs/PRD-enterprise-hardening.md +5 -5
  12. package/docs/PRD-knowledge-retrieval-and-enrichment.md +1 -1
  13. package/docs/knowledge-engine-runbook.md +1 -1
  14. package/docs/loop-workflow.md +15 -15
  15. package/docs/spec/config-v1.md +29 -7
  16. package/docs/spec/documentation-standard-v1.md +5 -0
  17. package/docs/spec/mcp-knowledge-tools-v1.md +1 -1
  18. package/docs/validation-cycle-plan.md +13 -13
  19. package/ecosystem-claims.json +17 -17
  20. package/ecosystem-upstream.json +2 -2
  21. package/ecosystem.json +300 -147
  22. package/mcpb/manifest.json +1 -1
  23. package/package.json +2 -1
  24. package/skills/doc-bridge-handoff/SKILL.md +1 -1
  25. package/skills/doc-bridge-handoff/scripts/resolve-handoff.mjs +1 -1
  26. package/src/conformance/ecosystem-contract.ts +10 -26
  27. package/src/discovery/repository.ts +7 -1
  28. package/src/findings/report.ts +1 -1
  29. package/src/fixes/proposals.ts +4 -2
  30. package/src/gates/run-gates.ts +1 -1
  31. package/src/index-builder/human-adapters/core.ts +10 -4
  32. package/src/lib/ignore-filter.ts +151 -0
  33. package/src/lib/walk.ts +10 -2
  34. package/src/memory/ingest.ts +1 -1
  35. package/src/report/html.ts +1 -1
  36. package/src/safety/repository.ts +9 -0
  37. package/src/version.ts +1 -1
  38. package/docs/DOGFOOD-ROUND2.md +0 -147
  39. package/docs/DOGFOOD-ROUND3.md +0 -79
  40. package/docs/DOGFOOD-V1.md +0 -89
  41. package/docs/DOGFOOD.md +0 -97
package/dist/index.js CHANGED
@@ -1716,8 +1716,8 @@ ${zodIssues(result.error).map((i) => ` - ${i.path}: ${i.message}`).join("\n")}`
1716
1716
  };
1717
1717
 
1718
1718
  // src/index-builder/build-index.ts
1719
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync2 } from "fs";
1720
- import { dirname as dirname4, join as join10 } from "path";
1719
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync12, writeFileSync as writeFileSync2 } from "fs";
1720
+ import { dirname as dirname5, join as join11 } from "path";
1721
1721
 
1722
1722
  // src/discovery/documentation.ts
1723
1723
  import { parseDocument } from "yaml";
@@ -1831,8 +1831,8 @@ var nodeStart = (node) => {
1831
1831
  var conventionalPackageReference = (path, agentRoot) => {
1832
1832
  const prefix = `${agentRoot.replace(/\/$/, "")}/`;
1833
1833
  if (!path.startsWith(prefix)) return void 0;
1834
- const relative12 = path.slice(prefix.length);
1835
- const [scope, file] = relative12.split("/");
1834
+ const relative13 = path.slice(prefix.length);
1835
+ const [scope, file] = relative13.split("/");
1836
1836
  if (scope !== "packages" && scope !== "apps" || !file) return void 0;
1837
1837
  return file.replace(/\.mdx?$/, "");
1838
1838
  };
@@ -2145,9 +2145,9 @@ var applyDocumentationDeclarations = (snapshot, documents, options = {}) => {
2145
2145
  };
2146
2146
 
2147
2147
  // src/discovery/repository.ts
2148
- import { execFileSync } from "child_process";
2149
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
2150
- import { basename as basename2, dirname as dirname2, extname as extname2, join as join5, relative as relative3, resolve as resolve4, sep as sep3 } from "path";
2148
+ import { execFileSync as execFileSync2 } from "child_process";
2149
+ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
2150
+ import { basename as basename2, dirname as dirname3, extname as extname2, join as join6, relative as relative4, resolve as resolve5, sep as sep4 } from "path";
2151
2151
  import * as ts2 from "typescript";
2152
2152
 
2153
2153
  // src/lib/glob-expand.ts
@@ -2163,9 +2163,9 @@ var containedProjectPath = (root, path) => {
2163
2163
  const unresolved = resolve2(projectRoot, path);
2164
2164
  const unresolvedRelative = relative(projectRoot, unresolved);
2165
2165
  if (isAbsolute(unresolvedRelative) || unresolvedRelative === ".." || unresolvedRelative.startsWith(`..${sep}`)) return void 0;
2166
- const canonical = existsSync2(unresolved) ? realpathSync.native(unresolved) : unresolved;
2167
- const canonicalRelative = relative(projectRoot, canonical);
2168
- return isAbsolute(canonicalRelative) || canonicalRelative === ".." || canonicalRelative.startsWith(`..${sep}`) ? void 0 : canonical;
2166
+ const canonical2 = existsSync2(unresolved) ? realpathSync.native(unresolved) : unresolved;
2167
+ const canonicalRelative = relative(projectRoot, canonical2);
2168
+ return isAbsolute(canonicalRelative) || canonicalRelative === ".." || canonicalRelative.startsWith(`..${sep}`) ? void 0 : canonical2;
2169
2169
  };
2170
2170
 
2171
2171
  // src/lib/glob-expand.ts
@@ -2257,25 +2257,140 @@ var defaultChecksForTarget = (root, opts) => {
2257
2257
  };
2258
2258
 
2259
2259
  // src/safety/repository.ts
2260
- import { lstatSync, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
2261
- import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
2260
+ import { lstatSync, readdirSync as readdirSync2, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
2261
+ import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve4, sep as sep3 } from "path";
2262
2262
  import { minimatch } from "minimatch";
2263
+
2264
+ // src/lib/ignore-filter.ts
2265
+ import { execFileSync } from "child_process";
2266
+ import { existsSync as existsSync5, readFileSync as readFileSync3, realpathSync as realpathSync2 } from "fs";
2267
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join4, relative as relative2, resolve as resolve3, sep as sep2 } from "path";
2268
+ import ignore from "ignore";
2269
+ var toPosix2 = (value) => value.split(sep2).join("/");
2270
+ var canonical = (path) => {
2271
+ try {
2272
+ return realpathSync2.native(resolve3(path));
2273
+ } catch {
2274
+ return resolve3(path);
2275
+ }
2276
+ };
2277
+ var below = (root, candidate) => {
2278
+ const rel = relative2(root, candidate);
2279
+ if (rel === "") return "";
2280
+ if (isAbsolute2(rel) || rel === ".." || rel.startsWith(`..${sep2}`)) return void 0;
2281
+ return toPosix2(rel);
2282
+ };
2283
+ var gitVisibleFiles = (root) => {
2284
+ try {
2285
+ const inside = execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
2286
+ cwd: root,
2287
+ encoding: "utf8",
2288
+ stdio: ["ignore", "pipe", "ignore"]
2289
+ }).trim();
2290
+ if (inside !== "true") return void 0;
2291
+ const output = execFileSync("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", "."], {
2292
+ cwd: root,
2293
+ encoding: "utf8",
2294
+ maxBuffer: 256 * 1024 * 1024,
2295
+ stdio: ["ignore", "pipe", "ignore"]
2296
+ });
2297
+ return output.split("\0").filter(Boolean);
2298
+ } catch {
2299
+ return void 0;
2300
+ }
2301
+ };
2302
+ var gitFilter = (root, canonicalRoot, visible) => {
2303
+ const files = new Set(visible.filter((path) => !path.endsWith("/")));
2304
+ const directories = /* @__PURE__ */ new Set([""]);
2305
+ for (const file of visible) {
2306
+ let parent = file;
2307
+ for (; ; ) {
2308
+ const slash = parent.lastIndexOf("/");
2309
+ if (slash === -1) break;
2310
+ parent = parent.slice(0, slash);
2311
+ if (directories.has(parent)) break;
2312
+ directories.add(parent);
2313
+ }
2314
+ }
2315
+ return {
2316
+ mode: "git",
2317
+ isIgnored: (absolutePath, isDirectory) => {
2318
+ const rel = below(root, resolve3(absolutePath)) ?? below(canonicalRoot, canonical(absolutePath));
2319
+ if (rel === void 0) return false;
2320
+ return isDirectory ? !directories.has(rel) : !files.has(rel);
2321
+ }
2322
+ };
2323
+ };
2324
+ var gitignoreFilter = (root) => {
2325
+ const rules = /* @__PURE__ */ new Map();
2326
+ const rulesFor = (directory) => {
2327
+ if (rules.has(directory)) return rules.get(directory);
2328
+ const file = join4(directory, ".gitignore");
2329
+ let matcher;
2330
+ if (existsSync5(file)) {
2331
+ try {
2332
+ matcher = ignore().add(readFileSync3(file, "utf8"));
2333
+ } catch {
2334
+ matcher = void 0;
2335
+ }
2336
+ }
2337
+ rules.set(directory, matcher);
2338
+ return matcher;
2339
+ };
2340
+ const ignoredCache = /* @__PURE__ */ new Map();
2341
+ const isIgnored = (absolutePath, isDirectory) => {
2342
+ const target2 = resolve3(absolutePath);
2343
+ const rel = below(root, target2);
2344
+ if (rel === void 0 || rel === "") return false;
2345
+ const key = `${isDirectory ? "d" : "f"}:${rel}`;
2346
+ const cached = ignoredCache.get(key);
2347
+ if (cached !== void 0) return cached;
2348
+ const parent = dirname2(target2);
2349
+ let result = parent !== root && below(root, parent) !== void 0 ? isIgnored(parent, true) : false;
2350
+ if (!result) {
2351
+ let decided;
2352
+ let directory = root;
2353
+ const segments = below(root, parent)?.split("/").filter(Boolean) ?? [];
2354
+ for (let index = 0; index <= segments.length; index += 1) {
2355
+ if (index > 0) directory = join4(directory, segments[index - 1]);
2356
+ const matcher = rulesFor(directory);
2357
+ if (!matcher) continue;
2358
+ const local = toPosix2(relative2(directory, target2)) + (isDirectory ? "/" : "");
2359
+ const verdict = matcher.test(local);
2360
+ if (verdict.ignored) decided = true;
2361
+ else if (verdict.unignored) decided = false;
2362
+ }
2363
+ result = decided ?? false;
2364
+ }
2365
+ ignoredCache.set(key, result);
2366
+ return result;
2367
+ };
2368
+ return { mode: "gitignore", isIgnored };
2369
+ };
2370
+ var createIgnoreFilter = (root) => {
2371
+ const base = resolve3(root);
2372
+ const canonicalRoot = canonical(root);
2373
+ const visible = gitVisibleFiles(canonicalRoot);
2374
+ return visible ? gitFilter(base, canonicalRoot, visible) : gitignoreFilter(base);
2375
+ };
2376
+
2377
+ // src/safety/repository.ts
2263
2378
  var DEFAULT_SAFETY_EXCLUDES = ["**/.git/**", "**/node_modules/**", "**/dist/**", "**/build/**", "**/coverage/**", "**/.doc-bridge/**", "**/.next/**", "**/out/**", "**/.turbo/**", "**/.svelte-kit/**", "**/.mcpb-build/**", "**/.mcpb-output/**", "**/.env", "**/.env.*", "**/*secret*", "**/*credential*", "**/*.pem", "**/*.key"];
2264
2379
  var containedPath = (root, candidate) => {
2265
- const projectRoot = realpathSync2.native(resolve3(root));
2266
- const unresolved = resolve3(projectRoot, candidate);
2267
- const unresolvedRelative = relative2(projectRoot, unresolved);
2268
- if (isAbsolute2(unresolvedRelative) || unresolvedRelative === ".." || unresolvedRelative.startsWith(`..${sep2}`)) return void 0;
2380
+ const projectRoot = realpathSync3.native(resolve4(root));
2381
+ const unresolved = resolve4(projectRoot, candidate);
2382
+ const unresolvedRelative = relative3(projectRoot, unresolved);
2383
+ if (isAbsolute3(unresolvedRelative) || unresolvedRelative === ".." || unresolvedRelative.startsWith(`..${sep3}`)) return void 0;
2269
2384
  try {
2270
- const canonical = realpathSync2.native(unresolved);
2271
- const canonicalRelative = relative2(projectRoot, canonical);
2272
- return isAbsolute2(canonicalRelative) || canonicalRelative === ".." || canonicalRelative.startsWith(`..${sep2}`) ? void 0 : canonical;
2385
+ const canonical2 = realpathSync3.native(unresolved);
2386
+ const canonicalRelative = relative3(projectRoot, canonical2);
2387
+ return isAbsolute3(canonicalRelative) || canonicalRelative === ".." || canonicalRelative.startsWith(`..${sep3}`) ? void 0 : canonical2;
2273
2388
  } catch {
2274
2389
  return unresolved;
2275
2390
  }
2276
2391
  };
2277
2392
  var safeWalkFiles = (root, options = {}) => {
2278
- const projectRoot = resolve3(root);
2393
+ const projectRoot = resolve4(root);
2279
2394
  const extensions = options.extensions ?? [];
2280
2395
  const excludes = options.exclude ?? DEFAULT_SAFETY_EXCLUDES;
2281
2396
  const files = [];
@@ -2283,6 +2398,7 @@ var safeWalkFiles = (root, options = {}) => {
2283
2398
  let reason;
2284
2399
  const started = Date.now();
2285
2400
  const matchesExclude = (path) => excludes.some((pattern) => minimatch(path, pattern, { dot: true }));
2401
+ const ignored = options.respectIgnore === false ? void 0 : createIgnoreFilter(projectRoot);
2286
2402
  const visit2 = (directory) => {
2287
2403
  if (reason) return;
2288
2404
  if (options.maxTimeMs !== void 0 && Date.now() - started >= options.maxTimeMs) {
@@ -2300,8 +2416,8 @@ var safeWalkFiles = (root, options = {}) => {
2300
2416
  return;
2301
2417
  }
2302
2418
  for (const name of entries.sort()) {
2303
- const absolute = resolve3(directory, name);
2304
- const relativePath3 = relative2(projectRoot, absolute).split(sep2).join("/");
2419
+ const absolute = resolve4(directory, name);
2420
+ const relativePath3 = relative3(projectRoot, absolute).split(sep3).join("/");
2305
2421
  if (matchesExclude(relativePath3) || name === ".git") continue;
2306
2422
  let stats;
2307
2423
  try {
@@ -2310,6 +2426,7 @@ var safeWalkFiles = (root, options = {}) => {
2310
2426
  continue;
2311
2427
  }
2312
2428
  if (stats.isSymbolicLink()) continue;
2429
+ if (ignored?.isIgnored(absolute, stats.isDirectory())) continue;
2313
2430
  if (stats.isDirectory()) {
2314
2431
  visit2(absolute);
2315
2432
  if (reason) return;
@@ -2546,11 +2663,11 @@ var relativeToPackage = (modulePath, packagePath) => {
2546
2663
  const prefix = `${packagePath}/`;
2547
2664
  return modulePath.startsWith(prefix) ? modulePath.slice(prefix.length) : void 0;
2548
2665
  };
2549
- var join4 = (...parts) => parts.filter(Boolean).join("/");
2666
+ var join5 = (...parts) => parts.filter(Boolean).join("/");
2550
2667
  var conventionalAreaPath = (module, depth = DEFAULT_AREA_DEPTH, roots = DEFAULT_AREA_ROOTS) => {
2551
- const relative12 = relativeToPackage(normalize(module.path), normalize(module.packagePath));
2552
- if (relative12 === void 0) return void 0;
2553
- const segments = relative12.split("/");
2668
+ const relative13 = relativeToPackage(normalize(module.path), normalize(module.packagePath));
2669
+ if (relative13 === void 0) return void 0;
2670
+ const segments = relative13.split("/");
2554
2671
  segments.pop();
2555
2672
  if (!segments.length) return void 0;
2556
2673
  const rootPrefix = [];
@@ -2562,7 +2679,7 @@ var conventionalAreaPath = (module, depth = DEFAULT_AREA_DEPTH, roots = DEFAULT_
2562
2679
  const taken = rest.slice(0, Math.max(1, depth));
2563
2680
  if (!taken.length) return void 0;
2564
2681
  const packagePath = normalize(module.packagePath);
2565
- return join4(packagePath === "." ? "" : packagePath, ...rootPrefix, ...taken);
2682
+ return join5(packagePath === "." ? "" : packagePath, ...rootPrefix, ...taken);
2566
2683
  };
2567
2684
  var encloses = (candidate, path) => path === candidate || path.startsWith(`${candidate}/`);
2568
2685
  var deriveAreas = (options) => {
@@ -3246,13 +3363,13 @@ var MAX_MARKDOWN_NOTES = 32;
3246
3363
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3247
3364
  var readJson = (path) => {
3248
3365
  try {
3249
- const value = JSON.parse(readFileSync3(path, "utf8"));
3366
+ const value = JSON.parse(readFileSync4(path, "utf8"));
3250
3367
  return isRecord(value) ? { value } : { error: "JSON root is not an object" };
3251
3368
  } catch (error) {
3252
3369
  return { error: error instanceof Error ? error.message : String(error) };
3253
3370
  }
3254
3371
  };
3255
- var relativePath = (root, path) => toPosix(relative3(root, path)) || ".";
3372
+ var relativePath = (root, path) => toPosix(relative4(root, path)) || ".";
3256
3373
  var lineEvidence = (source, root, path, lineStart, lineEnd) => ({
3257
3374
  source,
3258
3375
  path: relativePath(root, path),
@@ -3270,11 +3387,11 @@ var workspacePatterns = (root, rootManifest) => {
3270
3387
  if (isRecord(fromPackageJson) && Array.isArray(fromPackageJson.packages)) {
3271
3388
  return fromPackageJson.packages.filter((value) => typeof value === "string");
3272
3389
  }
3273
- const workspacePath = join5(root, "pnpm-workspace.yaml");
3274
- if (!existsSync5(workspacePath)) return [];
3390
+ const workspacePath = join6(root, "pnpm-workspace.yaml");
3391
+ if (!existsSync6(workspacePath)) return [];
3275
3392
  const patterns = [];
3276
3393
  let inPackages = false;
3277
- for (const line of readFileSync3(workspacePath, "utf8").split(/\r?\n/)) {
3394
+ for (const line of readFileSync4(workspacePath, "utf8").split(/\r?\n/)) {
3278
3395
  const trimmed = line.trim();
3279
3396
  if (trimmed === "packages:") {
3280
3397
  inPackages = true;
@@ -3292,7 +3409,7 @@ var workspacePatterns = (root, rootManifest) => {
3292
3409
  var discoverPackages = (root, rootManifest, config) => {
3293
3410
  const packages = [];
3294
3411
  const coverage = [];
3295
- const rootManifestPath = join5(root, "package.json");
3412
+ const rootManifestPath = join6(root, "package.json");
3296
3413
  if (rootManifest) {
3297
3414
  const name = packageName(rootManifest, "");
3298
3415
  packages.push({
@@ -3312,8 +3429,8 @@ var discoverPackages = (root, rootManifest, config) => {
3312
3429
  }
3313
3430
  const dirs = expandWorkspaceGlobs(root, patterns);
3314
3431
  for (const absPath of dirs) {
3315
- const manifestPath = join5(absPath, "package.json");
3316
- if (!existsSync5(manifestPath)) continue;
3432
+ const manifestPath = join6(absPath, "package.json");
3433
+ if (!existsSync6(manifestPath)) continue;
3317
3434
  const parsed = readJson(manifestPath);
3318
3435
  if (!parsed.value) {
3319
3436
  coverage.push({ status: "partial", reason: `${relativePath(root, manifestPath)}: ${parsed.error ?? "invalid package.json"}` });
@@ -3323,7 +3440,7 @@ var discoverPackages = (root, rootManifest, config) => {
3323
3440
  const name = packageName(parsed.value, path);
3324
3441
  const id = entityId("package", name ?? path);
3325
3442
  const duplicate = packages.find((pkg) => pkg.id === id);
3326
- if (duplicate && duplicate.absPath !== absPath) {
3443
+ if (duplicate && toPosix(duplicate.absPath) !== toPosix(absPath)) {
3327
3444
  throw new Error(`Package identity collision for "${id}": "${duplicate.path}" and "${path}".`);
3328
3445
  }
3329
3446
  if (!duplicate) packages.push({ id, ...name ? { name } : {}, path, absPath, manifestPath, manifest: parsed.value });
@@ -3331,13 +3448,13 @@ var discoverPackages = (root, rootManifest, config) => {
3331
3448
  coverage.push({ status: "complete" });
3332
3449
  return { packages: packages.sort((a, b) => a.id.localeCompare(b.id)), coverage };
3333
3450
  };
3334
- var packageForModule = (packages, absPath) => [...packages].filter((pkg) => absPath === pkg.absPath || absPath.startsWith(`${pkg.absPath}${sep3}`)).sort((a, b) => b.absPath.length - a.absPath.length)[0];
3451
+ var packageForModule = (packages, absPath) => [...packages].filter((pkg) => absPath === pkg.absPath || absPath.startsWith(`${pkg.absPath}${sep4}`)).sort((a, b) => b.absPath.length - a.absPath.length)[0];
3335
3452
  var readCompilerOptions = (root) => {
3336
3453
  const configPath = ts2.findConfigFile(root, ts2.sys.fileExists, "tsconfig.json");
3337
3454
  if (!configPath) return { options: {} };
3338
3455
  const parsed = ts2.readConfigFile(configPath, ts2.sys.readFile);
3339
3456
  if (parsed.error) return { options: {}, error: ts2.flattenDiagnosticMessageText(parsed.error.messageText, "\n") };
3340
- const config = ts2.parseJsonConfigFileContent(parsed.config, ts2.sys, dirname2(configPath));
3457
+ const config = ts2.parseJsonConfigFileContent(parsed.config, ts2.sys, dirname3(configPath));
3341
3458
  if (config.errors.length) {
3342
3459
  return {
3343
3460
  options: config.options,
@@ -3468,17 +3585,17 @@ var moduleReferences = (root, path, sourceFile, runtimeWiringMethods) => {
3468
3585
  };
3469
3586
  };
3470
3587
  var resolveRelativeModule = (specifier, containingFile, modulePaths) => {
3471
- const base = resolve4(dirname2(containingFile), specifier);
3588
+ const base = resolve5(dirname3(containingFile), specifier);
3472
3589
  const extension = extname2(base);
3473
3590
  const extensionlessBase = extension ? base.slice(0, -extension.length) : base;
3474
3591
  const candidates = [
3475
3592
  base,
3476
3593
  ...SOURCE_EXTENSIONS.map((extension2) => `${base}${extension2}`),
3477
- ...SOURCE_EXTENSIONS.map((extension2) => join5(base, `index${extension2}`)),
3594
+ ...SOURCE_EXTENSIONS.map((extension2) => join6(base, `index${extension2}`)),
3478
3595
  ...SOURCE_EXTENSIONS.map((extension2) => `${extensionlessBase}${extension2}`),
3479
- ...SOURCE_EXTENSIONS.map((extension2) => join5(extensionlessBase, `index${extension2}`))
3596
+ ...SOURCE_EXTENSIONS.map((extension2) => join6(extensionlessBase, `index${extension2}`))
3480
3597
  ];
3481
- return candidates.map((candidate) => modulePaths.get(resolve4(candidate))).find(Boolean);
3598
+ return candidates.map((candidate) => modulePaths.get(resolve5(candidate))).find(Boolean);
3482
3599
  };
3483
3600
  var resolveReference = (reference8, containingFile, modules, packages, compilerOptions) => {
3484
3601
  if (reference8.specifier.startsWith(".") || reference8.specifier.startsWith("/")) {
@@ -3488,7 +3605,7 @@ var resolveReference = (reference8, containingFile, modules, packages, compilerO
3488
3605
  const packageTarget = [...packages].filter((pkg) => pkg.name && (reference8.specifier === pkg.name || reference8.specifier.startsWith(`${pkg.name}/`))).sort((a, b) => (b.name?.length ?? 0) - (a.name?.length ?? 0))[0];
3489
3606
  if (packageTarget) return { targetId: packageTarget.id };
3490
3607
  const resolved = ts2.resolveModuleName(reference8.specifier, containingFile, compilerOptions, ts2.sys).resolvedModule?.resolvedFileName;
3491
- const resolvedTarget = resolved ? modules.get(resolve4(resolved)) : void 0;
3608
+ const resolvedTarget = resolved ? modules.get(resolve5(resolved)) : void 0;
3492
3609
  if (resolvedTarget) return { targetId: resolvedTarget.entityId };
3493
3610
  return { targetId: entityId("external", reference8.specifier) };
3494
3611
  };
@@ -3505,26 +3622,26 @@ var sourceRevision = (root, files) => {
3505
3622
  value: sha256NormalizedV1(
3506
3623
  files.map((path) => ({
3507
3624
  path: relativePath(root, path),
3508
- contentHash: sha256NormalizedV1(readFileSync3(path, "utf8"))
3625
+ contentHash: sha256NormalizedV1(readFileSync4(path, "utf8"))
3509
3626
  }))
3510
3627
  ),
3511
3628
  kind: "content"
3512
3629
  });
3513
3630
  try {
3514
- const status = execFileSync("git", ["status", "--porcelain", "--untracked-files=all"], {
3631
+ const status = execFileSync2("git", ["status", "--porcelain", "--untracked-files=all"], {
3515
3632
  cwd: root,
3516
3633
  encoding: "utf8",
3517
3634
  stdio: ["ignore", "pipe", "ignore"]
3518
3635
  }).trim();
3519
3636
  if (status) return contentRevision();
3520
- const value = execFileSync("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
3637
+ const value = execFileSync2("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
3521
3638
  if (value) return { value, kind: "git" };
3522
3639
  } catch {
3523
3640
  }
3524
3641
  return contentRevision();
3525
3642
  };
3526
3643
  var hasPackageManagerMetadata = (root, rootManifest) => Boolean(
3527
- rootManifest?.packageManager || existsSync5(join5(root, "pnpm-lock.yaml")) || existsSync5(join5(root, "pnpm-workspace.yaml")) || existsSync5(join5(root, "yarn.lock")) || existsSync5(join5(root, "bun.lock")) || existsSync5(join5(root, "bun.lockb")) || existsSync5(join5(root, "package-lock.json"))
3644
+ rootManifest?.packageManager || existsSync6(join6(root, "pnpm-lock.yaml")) || existsSync6(join6(root, "pnpm-workspace.yaml")) || existsSync6(join6(root, "yarn.lock")) || existsSync6(join6(root, "bun.lock")) || existsSync6(join6(root, "bun.lockb")) || existsSync6(join6(root, "package-lock.json"))
3528
3645
  );
3529
3646
  var PIPELINE_VERSION = "1.5.0";
3530
3647
  var ANALYZER_VERSIONS = { repository: "1.3.0", "js-ts": "1.3.5", markdown: MARKDOWN_ANALYZER_VERSION, graph: GRAPH_ANALYZER_VERSION };
@@ -3549,12 +3666,12 @@ var artifact = (root, config, files, entities, relations, coverage) => {
3549
3666
  return DiscoverySnapshotV1Schema.parse({ ...base, contentHash: contentHashForArtifactV1(base) });
3550
3667
  };
3551
3668
  var discoverRepository = (opts = {}) => {
3552
- const root = resolve4(opts.root ?? process.cwd());
3669
+ const root = resolve5(opts.root ?? process.cwd());
3553
3670
  const safeOptions = safeWalkOptions(opts.config, {
3554
3671
  maxFiles: opts.maxFiles ?? opts.config?.safety?.maxFiles ?? DEFAULT_MAX_FILES,
3555
3672
  ...opts.maxBytes !== void 0 ? { maxBytes: opts.maxBytes } : {}
3556
3673
  });
3557
- const rootManifestPath = join5(root, "package.json");
3674
+ const rootManifestPath = join6(root, "package.json");
3558
3675
  const rootManifest = readJson(rootManifestPath).value;
3559
3676
  const packageResult = discoverPackages(root, rootManifest, opts.config);
3560
3677
  const sourceWalk = safeWalkFiles(root, { extensions: SOURCE_EXTENSIONS, ...safeOptions });
@@ -3563,7 +3680,7 @@ var discoverRepository = (opts = {}) => {
3563
3680
  const sourcePaths = sourceWalk.files;
3564
3681
  const documentPaths = documentWalk.files;
3565
3682
  const configPaths = configWalk.files.filter((path) => /(?:^|\/)(?:tsconfig|jsconfig|vite\.config|webpack\.config|rollup\.config|next\.config|jest\.config|eslint\.config|vitest\.config)/.test(relativePath(root, path)));
3566
- const allFiles = [...new Set([rootManifestPath, ...sourcePaths, ...documentPaths, ...configPaths].filter(existsSync5))].sort();
3683
+ const allFiles = [...new Set([rootManifestPath, ...sourcePaths, ...documentPaths, ...configPaths].filter(existsSync6))].sort();
3567
3684
  const entities = /* @__PURE__ */ new Map();
3568
3685
  const relations = /* @__PURE__ */ new Map();
3569
3686
  const addEntity = (entity) => {
@@ -3586,7 +3703,7 @@ var discoverRepository = (opts = {}) => {
3586
3703
  relations.set(relation.id, { ...existing, evidence: [...evidence2.values()] });
3587
3704
  };
3588
3705
  for (const pkg of packageResult.packages) {
3589
- const text = readFileSync3(pkg.manifestPath, "utf8");
3706
+ const text = readFileSync4(pkg.manifestPath, "utf8");
3590
3707
  addEntity({
3591
3708
  id: pkg.id,
3592
3709
  kind: "package",
@@ -3634,9 +3751,9 @@ var discoverRepository = (opts = {}) => {
3634
3751
  const path = relativePath(root, absPath);
3635
3752
  const pkg = packageForModule(packageResult.packages, absPath);
3636
3753
  const id = entityId("module", path);
3637
- const text = readFileSync3(absPath, "utf8");
3754
+ const text = readFileSync4(absPath, "utf8");
3638
3755
  const contentHash = fileContentHash(text);
3639
- modules.set(resolve4(absPath), { absPath, path, entityId: id, ...pkg ? { packageId: pkg.id } : {} });
3756
+ modules.set(resolve5(absPath), { absPath, path, entityId: id, ...pkg ? { packageId: pkg.id } : {} });
3640
3757
  modulesByPath.set(path, id);
3641
3758
  if (pkg) areaModules.push({ moduleId: id, path, packageId: pkg.id, packagePath: pkg.path });
3642
3759
  const priorModule = reuseModuleRelations ? prior?.modules.get(path) : void 0;
@@ -3759,7 +3876,7 @@ var discoverRepository = (opts = {}) => {
3759
3876
  for (const [path, absPath] of documentFiles) {
3760
3877
  let text;
3761
3878
  try {
3762
- text = readFileSync3(absPath, "utf8");
3879
+ text = readFileSync4(absPath, "utf8");
3763
3880
  } catch {
3764
3881
  unreadableDocuments.push(path);
3765
3882
  ledger.parsedFiles.push(path);
@@ -3878,7 +3995,7 @@ var discoverRepository = (opts = {}) => {
3878
3995
  });
3879
3996
  }
3880
3997
  for (const pkg of packageResult.packages) {
3881
- const text = readFileSync3(pkg.manifestPath, "utf8");
3998
+ const text = readFileSync4(pkg.manifestPath, "utf8");
3882
3999
  for (const dependency of dependencyEntries(pkg.manifest)) {
3883
4000
  const target2 = packageResult.packages.find((candidate) => candidate.name === dependency.name)?.id ?? entityId("external", dependency.name);
3884
4001
  if (!entities.has(target2)) addEntity({ id: target2, kind: "external", name: dependency.name, provenance: "observed", evidence: [lineEvidence("configuration", root, pkg.manifestPath, firstLineContaining(text, `"${dependency.name}"`))] });
@@ -3917,7 +4034,7 @@ var discoverRepository = (opts = {}) => {
3917
4034
  ledger.skippedFiles.push(module.path);
3918
4035
  continue;
3919
4036
  }
3920
- const text = readFileSync3(module.absPath, "utf8");
4037
+ const text = readFileSync4(module.absPath, "utf8");
3921
4038
  const sourceFile = ts2.createSourceFile(module.absPath, text, ts2.ScriptTarget.Latest, true, scriptKind(module.absPath));
3922
4039
  const runtimeWiringMethods = includeTestRuntimeWiring || !TEST_MODULE_PATTERN.test(module.path) ? configuredRuntimeWiringMethods : /* @__PURE__ */ new Set();
3923
4040
  const references = moduleReferences(root, module.absPath, sourceFile, runtimeWiringMethods);
@@ -3950,7 +4067,7 @@ var discoverRepository = (opts = {}) => {
3950
4067
  };
3951
4068
 
3952
4069
  // src/lib/bounded-text.ts
3953
- import { closeSync, fstatSync, openSync, readFileSync as readFileSync4 } from "fs";
4070
+ import { closeSync, fstatSync, openSync, readFileSync as readFileSync5 } from "fs";
3954
4071
  var MAX_DOCUMENT_BYTES = 4 * 1024 * 1024;
3955
4072
  var MAX_CORPUS_BYTES = 64 * 1024 * 1024;
3956
4073
  var readBoundedText = (path, budget, limits) => {
@@ -3967,7 +4084,7 @@ var readBoundedText = (path, budget, limits) => {
3967
4084
  throw new Error(`Documentation corpus exceeds the ${maxCorpusBytes} byte read budget.`);
3968
4085
  }
3969
4086
  budget.used += stat.size;
3970
- return readFileSync4(fd, "utf8");
4087
+ return readFileSync5(fd, "utf8");
3971
4088
  } finally {
3972
4089
  closeSync(fd);
3973
4090
  }
@@ -4069,8 +4186,8 @@ var slugFromPath = (relPath) => {
4069
4186
  };
4070
4187
 
4071
4188
  // src/lib/walk.ts
4072
- import { lstatSync as lstatSync2, readdirSync as readdirSync3, realpathSync as realpathSync3 } from "fs";
4073
- import { join as join6 } from "path";
4189
+ import { lstatSync as lstatSync2, readdirSync as readdirSync3, realpathSync as realpathSync4 } from "fs";
4190
+ import { join as join7 } from "path";
4074
4191
  var DEFAULT_SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "coverage", ".doc-bridge"]);
4075
4192
  var DEFAULT_MAX_FILES2 = 1e4;
4076
4193
  var walkFiles = (root, opts) => {
@@ -4078,10 +4195,11 @@ var walkFiles = (root, opts) => {
4078
4195
  const skip = opts?.skipDirs ?? DEFAULT_SKIP;
4079
4196
  const out = [];
4080
4197
  const visited = /* @__PURE__ */ new Set();
4198
+ const ignored = opts?.respectIgnore === false ? void 0 : createIgnoreFilter(root);
4081
4199
  const visit2 = (dir) => {
4082
4200
  let canonicalDir;
4083
4201
  try {
4084
- canonicalDir = realpathSync3.native(dir);
4202
+ canonicalDir = realpathSync4.native(dir);
4085
4203
  } catch {
4086
4204
  return;
4087
4205
  }
@@ -4094,7 +4212,7 @@ var walkFiles = (root, opts) => {
4094
4212
  return;
4095
4213
  }
4096
4214
  for (const name of entries) {
4097
- const abs = join6(dir, name);
4215
+ const abs = join7(dir, name);
4098
4216
  let st;
4099
4217
  try {
4100
4218
  st = lstatSync2(abs);
@@ -4103,12 +4221,12 @@ var walkFiles = (root, opts) => {
4103
4221
  }
4104
4222
  if (st.isSymbolicLink()) continue;
4105
4223
  if (st.isDirectory()) {
4106
- if (skip.has(name)) continue;
4224
+ if (skip.has(name) || ignored?.isIgnored(abs, true)) continue;
4107
4225
  visit2(abs);
4108
4226
  continue;
4109
4227
  }
4110
4228
  if (!st.isFile()) continue;
4111
- if (extensions.some((ext) => name.endsWith(ext))) {
4229
+ if (extensions.some((ext) => name.endsWith(ext)) && !ignored?.isIgnored(abs, false)) {
4112
4230
  if (out.length >= (opts?.maxFiles ?? DEFAULT_MAX_FILES2)) {
4113
4231
  throw new Error(`Documentation corpus exceeds the ${opts?.maxFiles ?? DEFAULT_MAX_FILES2} file limit.`);
4114
4232
  }
@@ -4400,7 +4518,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
4400
4518
  };
4401
4519
 
4402
4520
  // src/version.ts
4403
- var PACKAGE_VERSION = "1.11.1";
4521
+ var PACKAGE_VERSION = "1.12.0";
4404
4522
 
4405
4523
  // src/index-builder/capabilities.ts
4406
4524
  var renderCapabilitiesJson = (config, index, paths) => {
@@ -4434,8 +4552,8 @@ var renderCapabilitiesJson = (config, index, paths) => {
4434
4552
  };
4435
4553
 
4436
4554
  // src/render/template-source.ts
4437
- import { readFileSync as readFileSync5 } from "fs";
4438
- import { resolve as resolve5 } from "path";
4555
+ import { readFileSync as readFileSync6 } from "fs";
4556
+ import { resolve as resolve6 } from "path";
4439
4557
 
4440
4558
  // src/render/engine.ts
4441
4559
  import {
@@ -4992,10 +5110,10 @@ var BUNDLED_TEMPLATES = {
4992
5110
  var resolveTemplateSource = (name, config, root) => {
4993
5111
  const override = config.render?.templates?.[name];
4994
5112
  if (!override) return { name, source: BUNDLED_TEMPLATES[name], origin: "bundled" };
4995
- const path = root ? resolve5(root, override) : resolve5(override);
5113
+ const path = root ? resolve6(root, override) : resolve6(override);
4996
5114
  let source;
4997
5115
  try {
4998
- source = readFileSync5(path, "utf8");
5116
+ source = readFileSync6(path, "utf8");
4999
5117
  } catch (error) {
5000
5118
  throw new Error(`render.templates["${name}"] points at ${toPosix(override)}, which could not be read: ${error instanceof Error ? error.message : String(error)}`);
5001
5119
  }
@@ -5014,8 +5132,8 @@ var compile = (template2) => {
5014
5132
  var renderNamedTemplate = (name, variables, config, root) => renderCompiledTemplate(compile(resolveTemplateSource(name, config, root)), variables);
5015
5133
 
5016
5134
  // src/index-builder/project-corpus.ts
5017
- import { basename as basename3, extname as extname3, relative as relative4, resolve as resolve6, sep as sep4 } from "path";
5018
- import { readFileSync as readFileSync6 } from "fs";
5135
+ import { basename as basename3, extname as extname3, relative as relative5, resolve as resolve7, sep as sep5 } from "path";
5136
+ import { readFileSync as readFileSync7 } from "fs";
5019
5137
  var CORPUS_PROJECTION_VERSION = 2;
5020
5138
  var PROJECTED_ENTRY_TYPES = ["document", "module"];
5021
5139
  var isProjectedEntry = (entry) => PROJECTED_ENTRY_TYPES.includes(entry.type);
@@ -5034,14 +5152,14 @@ var isInput = (path, name) => {
5034
5152
  return CONFIG_INPUT_PATTERN.test(path);
5035
5153
  };
5036
5154
  var repositoryInputs = (root, config) => {
5037
- const projectRoot = resolve6(root);
5155
+ const projectRoot = resolve7(root);
5038
5156
  const walk = safeWalkFiles(projectRoot, { extensions: INPUT_EXTENSIONS, ...safeWalkOptions(config) });
5039
5157
  const fingerprints = [];
5040
5158
  for (const absPath of walk.files) {
5041
- const path = toPosix(relative4(projectRoot, absPath).split(sep4).join("/"));
5159
+ const path = toPosix(relative5(projectRoot, absPath).split(sep5).join("/"));
5042
5160
  if (!isInput(path, basename3(absPath))) continue;
5043
5161
  try {
5044
- fingerprints.push([path, sha256NormalizedV1(readFileSync6(absPath, "utf8"))]);
5162
+ fingerprints.push([path, sha256NormalizedV1(readFileSync7(absPath, "utf8"))]);
5045
5163
  } catch {
5046
5164
  fingerprints.push([path, "unreadable"]);
5047
5165
  }
@@ -5086,15 +5204,15 @@ var llmsTxtVariables = (config, knowledge, projectName2) => {
5086
5204
  var renderLlmsTxt = (config, knowledge, projectName2, options = {}) => renderNamedTemplate("llms.txt", llmsTxtVariables(config, knowledge, projectName2), config, options.root);
5087
5205
 
5088
5206
  // src/index-builder/human-adapters/index.ts
5089
- import { realpathSync as realpathSync5 } from "fs";
5090
- import { resolve as resolve8, sep as sep6 } from "path";
5207
+ import { realpathSync as realpathSync6 } from "fs";
5208
+ import { resolve as resolve9, sep as sep7 } from "path";
5091
5209
 
5092
5210
  // src/index-builder/human-adapters/docusaurus.ts
5093
- import { existsSync as existsSync6 } from "fs";
5211
+ import { existsSync as existsSync7 } from "fs";
5094
5212
 
5095
5213
  // src/index-builder/human-adapters/core.ts
5096
- import { realpathSync as realpathSync4 } from "fs";
5097
- import { isAbsolute as isAbsolute3, relative as relative5, resolve as resolve7, sep as sep5 } from "path";
5214
+ import { realpathSync as realpathSync5 } from "fs";
5215
+ import { isAbsolute as isAbsolute4, relative as relative6, resolve as resolve8, sep as sep6 } from "path";
5098
5216
  var optionString = (options, keys) => {
5099
5217
  for (const key of keys) {
5100
5218
  const value = options?.[key];
@@ -5103,11 +5221,12 @@ var optionString = (options, keys) => {
5103
5221
  return void 0;
5104
5222
  };
5105
5223
  var parseFrontmatter2 = (raw) => {
5106
- if (!raw.startsWith("---\n")) return {};
5107
- const end = raw.indexOf("\n---", 4);
5224
+ const normalized = raw.includes("\r\n") ? raw.replace(/\r\n/g, "\n") : raw;
5225
+ if (!normalized.startsWith("---\n")) return {};
5226
+ const end = normalized.indexOf("\n---", 4);
5108
5227
  if (end === -1) return {};
5109
5228
  const out = {};
5110
- for (const line of raw.slice(4, end).split("\n")) {
5229
+ for (const line of normalized.slice(4, end).split("\n")) {
5111
5230
  const match = /^([A-Za-z0-9_-]+):\s*(.+?)\s*$/.exec(line);
5112
5231
  if (match?.[1] && match[2]) out[match[1]] = match[2].replace(/^['"]|['"]$/g, "");
5113
5232
  }
@@ -5125,15 +5244,15 @@ var humanUrl = (slug2, urlPrefix) => {
5125
5244
  };
5126
5245
  var scanMarkdownDocs = (root, humanRoot, options) => {
5127
5246
  const out = [];
5128
- const projectRoot = realpathSync4.native(resolve7(root));
5247
+ const projectRoot = realpathSync5.native(resolve8(root));
5129
5248
  const absRoot = containedProjectPath(root, humanRoot);
5130
5249
  if (!absRoot) return out;
5131
5250
  const budget = { used: 0 };
5132
5251
  for (const abs of walkFiles(absRoot, { extensions: [".md", ".mdx"] })) {
5133
- const canonical = realpathSync4.native(abs);
5134
- const fileRelative = relative5(projectRoot, canonical);
5135
- if (isAbsolute3(fileRelative) || fileRelative === ".." || fileRelative.startsWith(`..${sep5}`)) continue;
5136
- const relToHumanRoot = toPosix(abs.replace(`${toPosix(absRoot)}/`, ""));
5252
+ const canonical2 = realpathSync5.native(abs);
5253
+ const fileRelative = relative6(projectRoot, canonical2);
5254
+ if (isAbsolute4(fileRelative) || fileRelative === ".." || fileRelative.startsWith(`..${sep6}`)) continue;
5255
+ const relToHumanRoot = toPosix(abs).replace(`${toPosix(absRoot)}/`, "");
5137
5256
  const raw = readBoundedText(abs, budget);
5138
5257
  if (options?.includeRelPath && !options.includeRelPath(relToHumanRoot, raw)) continue;
5139
5258
  out.push({
@@ -5174,7 +5293,7 @@ var docusaurusRecordId = (relPath, raw) => {
5174
5293
  };
5175
5294
  var readSidebars = (sidebarsFile) => {
5176
5295
  if (!sidebarsFile) return { enabled: false, ids: /* @__PURE__ */ new Set(), autogenDirs: [] };
5177
- if (!existsSync6(sidebarsFile)) return { enabled: false, ids: /* @__PURE__ */ new Set(), autogenDirs: [] };
5296
+ if (!existsSync7(sidebarsFile)) return { enabled: false, ids: /* @__PURE__ */ new Set(), autogenDirs: [] };
5178
5297
  const raw = readBoundedText(sidebarsFile, { used: 0 }, { maxFileBytes: 1048576, maxCorpusBytes: 1048576 });
5179
5298
  const filter = { ids: /* @__PURE__ */ new Set(), autogenDirs: [] };
5180
5299
  const visit2 = (value) => {
@@ -5224,13 +5343,13 @@ var docusaurusAdapter = {
5224
5343
  };
5225
5344
 
5226
5345
  // src/index-builder/human-adapters/fumadocs.ts
5227
- import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
5228
- import { join as join7 } from "path";
5346
+ import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
5347
+ import { join as join8 } from "path";
5229
5348
  var readMetaPages = (dir) => {
5230
- const file = join7(dir, "meta.json");
5231
- if (!existsSync7(file)) return void 0;
5349
+ const file = join8(dir, "meta.json");
5350
+ if (!existsSync8(file)) return void 0;
5232
5351
  try {
5233
- const meta = JSON.parse(readFileSync7(file, "utf8"));
5352
+ const meta = JSON.parse(readFileSync8(file, "utf8"));
5234
5353
  return Array.isArray(meta.pages) ? meta.pages.filter((page) => typeof page === "string") : void 0;
5235
5354
  } catch {
5236
5355
  return void 0;
@@ -5245,7 +5364,7 @@ var isListedByMeta = (contentRoot, relPath) => {
5245
5364
  if (isDotFile(relPath)) return false;
5246
5365
  const parts = relPath.split("/");
5247
5366
  for (let i = 0; i < parts.length; i += 1) {
5248
- const dir = join7(contentRoot, ...parts.slice(0, i));
5367
+ const dir = join8(contentRoot, ...parts.slice(0, i));
5249
5368
  const pages = readMetaPages(dir);
5250
5369
  if (!pages?.length || pages.includes("...")) continue;
5251
5370
  const key = pageKey(parts[i] ?? "");
@@ -5258,7 +5377,7 @@ var fumadocsAdapter = {
5258
5377
  scan: ({ root, config }) => {
5259
5378
  const contentDir = optionString(config.options, ["contentDir", "root"]);
5260
5379
  if (!contentDir) return [];
5261
- const contentRoot = join7(root, contentDir);
5380
+ const contentRoot = join8(root, contentDir);
5262
5381
  const excludePrefixes = Array.isArray(config.options?.excludePrefixes) ? config.options.excludePrefixes.filter((v) => typeof v === "string") : typeof config.options?.excludePrefix === "string" ? [config.options.excludePrefix] : [];
5263
5382
  if (!excludePrefixes.includes("for-agents")) excludePrefixes.push("for-agents");
5264
5383
  return scanMarkdownDocs(root, contentDir, {
@@ -5402,21 +5521,21 @@ var humanConfigs = (config) => {
5402
5521
  };
5403
5522
  var canonicalPath = (path) => {
5404
5523
  try {
5405
- return realpathSync5.native(path);
5524
+ return realpathSync6.native(path);
5406
5525
  } catch {
5407
- return resolve8(path);
5526
+ return resolve9(path);
5408
5527
  }
5409
5528
  };
5410
5529
  var scanHumanDocRecords = (root, config) => {
5411
5530
  const out = [];
5412
5531
  const seen = /* @__PURE__ */ new Set();
5413
- const agentRoot = canonicalPath(resolve8(root, config.corpus.agent.root));
5532
+ const agentRoot = canonicalPath(resolve9(root, config.corpus.agent.root));
5414
5533
  for (const human of humanConfigs(config)) {
5415
5534
  const adapter = ADAPTERS.find((candidate) => candidate.plugin === human.plugin);
5416
5535
  if (!adapter) continue;
5417
5536
  for (const record of adapter.scan({ root, config: human })) {
5418
5537
  const recordPath = canonicalPath(record.path);
5419
- if (recordPath === agentRoot || recordPath.startsWith(`${agentRoot}${sep6}`) || record.path.includes("/for-agents/") || record.path.endsWith("/for-agents")) {
5538
+ if (recordPath === agentRoot || recordPath.startsWith(`${agentRoot}${sep7}`) || record.path.includes("/for-agents/") || record.path.endsWith("/for-agents")) {
5420
5539
  continue;
5421
5540
  }
5422
5541
  if (seen.has(record.id)) continue;
@@ -5429,8 +5548,8 @@ var scanHumanDocRecords = (root, config) => {
5429
5548
  var scanHumanDocs = (root, config) => Object.fromEntries(scanHumanDocRecords(root, config).map((doc) => [doc.id, doc.url]));
5430
5549
 
5431
5550
  // src/index-builder/plugins/nx.ts
5432
- import { existsSync as existsSync8, lstatSync as lstatSync3, readFileSync as readFileSync8, realpathSync as realpathSync6 } from "fs";
5433
- import { basename as basename4, dirname as dirname3, isAbsolute as isAbsolute4, relative as relative6, resolve as resolve9, sep as sep7 } from "path";
5551
+ import { existsSync as existsSync9, lstatSync as lstatSync3, readFileSync as readFileSync9, realpathSync as realpathSync7 } from "fs";
5552
+ import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute5, relative as relative7, resolve as resolve10, sep as sep8 } from "path";
5434
5553
  var NX_SCAN_SKIP = /* @__PURE__ */ new Set([
5435
5554
  "node_modules",
5436
5555
  ".git",
@@ -5443,22 +5562,22 @@ var NX_PROJECT_NAME = /^(?:@[A-Za-z0-9._-]+\/)?[A-Za-z0-9][A-Za-z0-9._-]*$/;
5443
5562
  var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5444
5563
  var readJsonRecord = (path) => {
5445
5564
  try {
5446
- const parsed = JSON.parse(readFileSync8(path, "utf8"));
5565
+ const parsed = JSON.parse(readFileSync9(path, "utf8"));
5447
5566
  return isRecord2(parsed) ? parsed : void 0;
5448
5567
  } catch {
5449
5568
  return void 0;
5450
5569
  }
5451
5570
  };
5452
5571
  var safeProjectPath = (root, manifestDir, declaredRoot) => {
5453
- const candidate = typeof declaredRoot === "string" ? resolve9(root, declaredRoot) : manifestDir;
5454
- const rel = toPosix(relative6(root, candidate)) || ".";
5455
- if (isAbsolute4(rel) || rel === ".." || rel.startsWith("../")) return void 0;
5572
+ const candidate = typeof declaredRoot === "string" ? resolve10(root, declaredRoot) : manifestDir;
5573
+ const rel = toPosix(relative7(root, candidate)) || ".";
5574
+ if (isAbsolute5(rel) || rel === ".." || rel.startsWith("../")) return void 0;
5456
5575
  try {
5457
5576
  if (!lstatSync3(candidate).isDirectory()) return void 0;
5458
- const canonicalRoot = realpathSync6.native(root);
5459
- const canonicalCandidate = realpathSync6.native(candidate);
5460
- const canonicalRel = relative6(canonicalRoot, canonicalCandidate);
5461
- if (isAbsolute4(canonicalRel) || canonicalRel === ".." || canonicalRel.startsWith(`..${sep7}`)) {
5577
+ const canonicalRoot = realpathSync7.native(root);
5578
+ const canonicalCandidate = realpathSync7.native(candidate);
5579
+ const canonicalRel = relative7(canonicalRoot, canonicalCandidate);
5580
+ if (isAbsolute5(canonicalRel) || canonicalRel === ".." || canonicalRel.startsWith(`..${sep8}`)) {
5462
5581
  return void 0;
5463
5582
  }
5464
5583
  } catch {
@@ -5484,7 +5603,7 @@ var inferredChecks = (root, config, projectName2, targets) => {
5484
5603
  return checks.length ? checks : void 0;
5485
5604
  };
5486
5605
  var discoverNxProjects = (root, config) => {
5487
- if (!existsSync8(resolve9(root, "nx.json"))) return [];
5606
+ if (!existsSync9(resolve10(root, "nx.json"))) return [];
5488
5607
  const manifests = walkFiles(root, {
5489
5608
  extensions: ["project.json", "package.json"],
5490
5609
  skipDirs: NX_SCAN_SKIP,
@@ -5494,7 +5613,7 @@ var discoverNxProjects = (root, config) => {
5494
5613
  for (const manifest of manifests) {
5495
5614
  const json = readJsonRecord(manifest);
5496
5615
  if (!json) continue;
5497
- const manifestDir = dirname3(manifest);
5616
+ const manifestDir = dirname4(manifest);
5498
5617
  const manifestName = basename4(manifest);
5499
5618
  const isProjectJson = manifestName === "project.json";
5500
5619
  if (!isProjectJson && manifestName !== "package.json") continue;
@@ -5502,7 +5621,7 @@ var discoverNxProjects = (root, config) => {
5502
5621
  if (!isProjectJson && !isRecord2(nx)) continue;
5503
5622
  const path = safeProjectPath(root, manifestDir, isProjectJson ? json.root : void 0);
5504
5623
  if (!path) continue;
5505
- const projectPackage = isProjectJson ? readJsonRecord(resolve9(root, path, "package.json")) : void 0;
5624
+ const projectPackage = isProjectJson ? readJsonRecord(resolve10(root, path, "package.json")) : void 0;
5506
5625
  const projectName2 = typeof json.name === "string" ? json.name : typeof projectPackage?.name === "string" ? projectPackage.name : basename4(path === "." ? root : path);
5507
5626
  if (!NX_PROJECT_NAME.test(projectName2)) continue;
5508
5627
  const targets = /* @__PURE__ */ new Set();
@@ -5538,8 +5657,8 @@ var discoverNxProjects = (root, config) => {
5538
5657
  };
5539
5658
 
5540
5659
  // src/index-builder/plugins/pnpm-monorepo.ts
5541
- import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
5542
- import { basename as basename5, join as join8 } from "path";
5660
+ import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
5661
+ import { basename as basename5, join as join9 } from "path";
5543
5662
  var parsePnpmWorkspace = (yaml) => {
5544
5663
  const lines = yaml.split("\n");
5545
5664
  const patterns = [];
@@ -5561,10 +5680,10 @@ var parsePnpmWorkspace = (yaml) => {
5561
5680
  return patterns;
5562
5681
  };
5563
5682
  var readPackageJson = (dir) => {
5564
- const file = join8(dir, "package.json");
5565
- if (!existsSync9(file)) return null;
5683
+ const file = join9(dir, "package.json");
5684
+ if (!existsSync10(file)) return null;
5566
5685
  try {
5567
- return JSON.parse(readFileSync9(file, "utf8"));
5686
+ return JSON.parse(readFileSync10(file, "utf8"));
5568
5687
  } catch {
5569
5688
  return null;
5570
5689
  }
@@ -5573,9 +5692,9 @@ var discoverPnpmPackages = (root, config) => {
5573
5692
  const explicit = config.routing?.options?.packages;
5574
5693
  let patterns = explicit;
5575
5694
  if (!patterns?.length) {
5576
- const workspaceFile = join8(root, "pnpm-workspace.yaml");
5577
- if (existsSync9(workspaceFile)) {
5578
- patterns = parsePnpmWorkspace(readFileSync9(workspaceFile, "utf8"));
5695
+ const workspaceFile = join9(root, "pnpm-workspace.yaml");
5696
+ if (existsSync10(workspaceFile)) {
5697
+ patterns = parsePnpmWorkspace(readFileSync10(workspaceFile, "utf8"));
5579
5698
  }
5580
5699
  }
5581
5700
  if (!patterns?.length) return [];
@@ -6276,8 +6395,8 @@ var toKnowledgeEntry = (entry) => ({
6276
6395
  });
6277
6396
 
6278
6397
  // src/enrich/overlay.ts
6279
- import { existsSync as existsSync10, mkdirSync, readFileSync as readFileSync10, renameSync, writeFileSync } from "fs";
6280
- import { join as join9, resolve as resolve10 } from "path";
6398
+ import { existsSync as existsSync11, mkdirSync, readFileSync as readFileSync11, renameSync, writeFileSync } from "fs";
6399
+ import { join as join10, resolve as resolve11 } from "path";
6281
6400
 
6282
6401
  // src/schemas/enrichment.ts
6283
6402
  import { z as z9 } from "zod";
@@ -6785,14 +6904,14 @@ var EnrichmentProposalListSchema = z10.array(z10.unknown()).max(1024);
6785
6904
  // src/enrich/overlay.ts
6786
6905
  var ENRICHMENT_DIR = ".doc-bridge/enrich";
6787
6906
  var ENRICHMENT_OVERLAY_FILE = "overlay.json";
6788
- var enrichmentDir = (root) => join9(resolve10(root), ENRICHMENT_DIR);
6789
- var enrichmentOverlayPath = (root) => join9(enrichmentDir(root), ENRICHMENT_OVERLAY_FILE);
6790
- var enrichmentCacheDir = (root) => join9(enrichmentDir(root), "cache");
6907
+ var enrichmentDir = (root) => join10(resolve11(root), ENRICHMENT_DIR);
6908
+ var enrichmentOverlayPath = (root) => join10(enrichmentDir(root), ENRICHMENT_OVERLAY_FILE);
6909
+ var enrichmentCacheDir = (root) => join10(enrichmentDir(root), "cache");
6791
6910
  var readEnrichmentOverlay = (root) => {
6792
6911
  const path = enrichmentOverlayPath(root);
6793
- if (!existsSync10(path)) return void 0;
6912
+ if (!existsSync11(path)) return void 0;
6794
6913
  try {
6795
- const parsed = EnrichmentOverlayV1Schema.parse(JSON.parse(readFileSync10(path, "utf8")));
6914
+ const parsed = EnrichmentOverlayV1Schema.parse(JSON.parse(readFileSync11(path, "utf8")));
6796
6915
  return parsed.contentHash === enrichmentOverlayContentHash(parsed) ? parsed : void 0;
6797
6916
  } catch {
6798
6917
  return void 0;
@@ -6870,7 +6989,7 @@ var projectEnrichmentOverlay = (overlay, snapshot) => {
6870
6989
  const signals = /* @__PURE__ */ new Map();
6871
6990
  const aliases = /* @__PURE__ */ new Map();
6872
6991
  const summaries = /* @__PURE__ */ new Map();
6873
- const canonical = /* @__PURE__ */ new Map();
6992
+ const canonical2 = /* @__PURE__ */ new Map();
6874
6993
  const intents = [];
6875
6994
  const relations = [];
6876
6995
  const paths = new Map(snapshot.entities.map((entity) => [entity.id, entity.path]));
@@ -6895,7 +7014,7 @@ var projectEnrichmentOverlay = (overlay, snapshot) => {
6895
7014
  });
6896
7015
  break;
6897
7016
  case "mark-canonical":
6898
- canonical.set(proposal.entity, proposal.payload.scope);
7017
+ canonical2.set(proposal.entity, proposal.payload.scope);
6899
7018
  bump(proposal.entity, SIGNAL_CANONICAL);
6900
7019
  break;
6901
7020
  case "rank-hint":
@@ -6916,7 +7035,7 @@ var projectEnrichmentOverlay = (overlay, snapshot) => {
6916
7035
  ...signals.size ? { signals } : {},
6917
7036
  ...aliases.size ? { aliases } : {},
6918
7037
  ...summaries.size ? { summaries } : {},
6919
- ...canonical.size ? { canonical } : {},
7038
+ ...canonical2.size ? { canonical: canonical2 } : {},
6920
7039
  ...intents.length ? { intents } : {},
6921
7040
  ...relations.length ? { relations } : {}
6922
7041
  };
@@ -6944,7 +7063,7 @@ var enrichmentFindings = (overlay) => overlay.accepted.filter((entry) => ENRICHM
6944
7063
  var projectName = (root, config) => {
6945
7064
  if (config.project?.name) return config.project.name;
6946
7065
  try {
6947
- const pkg = JSON.parse(readFileSync11(join10(root, "package.json"), "utf8"));
7066
+ const pkg = JSON.parse(readFileSync12(join11(root, "package.json"), "utf8"));
6948
7067
  if (pkg.name) return pkg.name;
6949
7068
  } catch {
6950
7069
  }
@@ -6957,7 +7076,7 @@ var projectFromSnapshot = (root, config, given, lookup, curated, requested) => {
6957
7076
  for (const entity of observed.entities) {
6958
7077
  if (entity.kind !== "document" || !entity.path) continue;
6959
7078
  try {
6960
- contents.set(entity.path, readBoundedText(join10(root, entity.path), budget));
7079
+ contents.set(entity.path, readBoundedText(join11(root, entity.path), budget));
6961
7080
  } catch {
6962
7081
  }
6963
7082
  }
@@ -6980,7 +7099,7 @@ var projectFromSnapshot = (root, config, given, lookup, curated, requested) => {
6980
7099
  };
6981
7100
  var existingGeneratedAt = (indexPath, contentHash) => {
6982
7101
  try {
6983
- const index = JSON.parse(readFileSync11(indexPath, "utf8"));
7102
+ const index = JSON.parse(readFileSync12(indexPath, "utf8"));
6984
7103
  return index.contentHash === contentHash && typeof index.generatedAt === "string" ? index.generatedAt : void 0;
6985
7104
  } catch {
6986
7105
  return void 0;
@@ -6991,7 +7110,7 @@ var buildDocBridgeIndex = (opts) => {
6991
7110
  const config = opts.config;
6992
7111
  const write = opts.write ?? true;
6993
7112
  const outFile = config.index?.outFile ?? ".doc-bridge/index.json";
6994
- const indexPath = join10(root, outFile);
7113
+ const indexPath = join11(root, outFile);
6995
7114
  const corpus = scanAgentCorpus(root, config);
6996
7115
  const curated = corpus.map(({ absPath: _a, relPath: _r, frontmatter: _f, ...entry }) => entry);
6997
7116
  const retrieval = {
@@ -7041,7 +7160,7 @@ var buildDocBridgeIndex = (opts) => {
7041
7160
  );
7042
7161
  }
7043
7162
  if (write) {
7044
- mkdirSync2(dirname4(indexPath), { recursive: true });
7163
+ mkdirSync2(dirname5(indexPath), { recursive: true });
7045
7164
  writeFileSync2(indexPath, `${JSON.stringify(index, null, 2)}
7046
7165
  `, "utf8");
7047
7166
  }
@@ -7050,7 +7169,7 @@ var buildDocBridgeIndex = (opts) => {
7050
7169
  if (config.index?.llmsTxt?.enabled !== false) {
7051
7170
  const llmsOut = config.index?.llmsTxt?.outFile ?? "llms.txt";
7052
7171
  llmsTxtRelPath = toPosix(llmsOut);
7053
- llmsTxtPath = join10(root, llmsOut);
7172
+ llmsTxtPath = join11(root, llmsOut);
7054
7173
  if (write) {
7055
7174
  writeFileSync2(
7056
7175
  llmsTxtPath,
@@ -7062,9 +7181,9 @@ var buildDocBridgeIndex = (opts) => {
7062
7181
  let capabilitiesPath;
7063
7182
  if (config.index?.capabilities?.enabled !== false) {
7064
7183
  const capabilitiesOut = config.index?.capabilities?.outFile ?? ".doc-bridge/capabilities.json";
7065
- capabilitiesPath = join10(root, capabilitiesOut);
7184
+ capabilitiesPath = join11(root, capabilitiesOut);
7066
7185
  if (write) {
7067
- mkdirSync2(dirname4(capabilitiesPath), { recursive: true });
7186
+ mkdirSync2(dirname5(capabilitiesPath), { recursive: true });
7068
7187
  writeFileSync2(
7069
7188
  capabilitiesPath,
7070
7189
  renderCapabilitiesJson(config, index, {
@@ -7084,7 +7203,7 @@ var buildDocBridgeIndex = (opts) => {
7084
7203
  };
7085
7204
 
7086
7205
  // src/discovery/reproducibility.ts
7087
- import { execFileSync as execFileSync2 } from "child_process";
7206
+ import { execFileSync as execFileSync3 } from "child_process";
7088
7207
  var NOT_CHECKED = (skipped) => ({
7089
7208
  checked: false,
7090
7209
  skipped,
@@ -7092,7 +7211,7 @@ var NOT_CHECKED = (skipped) => ({
7092
7211
  });
7093
7212
  var git = (root, args, options = {}) => {
7094
7213
  try {
7095
- return execFileSync2("git", args, {
7214
+ return execFileSync3("git", args, {
7096
7215
  cwd: root,
7097
7216
  encoding: "utf8",
7098
7217
  stdio: ["pipe", "pipe", "ignore"],
@@ -7441,9 +7560,9 @@ var createDocBridgeGraphMemory = (snapshot, overlay = {}) => {
7441
7560
  };
7442
7561
 
7443
7562
  // src/agents/registry-adapter.ts
7444
- import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
7563
+ import { existsSync as existsSync12, readFileSync as readFileSync13, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
7445
7564
  import { spawn } from "child_process";
7446
- import { join as join11, resolve as resolve11 } from "path";
7565
+ import { join as join12, resolve as resolve12 } from "path";
7447
7566
  import { pathToFileURL } from "url";
7448
7567
  import { z as z11 } from "zod";
7449
7568
  var DEFAULT_REGISTRY_AGENT_ID = "ecosystem-doc-bridge-corpus-scanner";
@@ -7478,7 +7597,7 @@ var validateGrounding = (proposal, snapshot, report, documentation) => {
7478
7597
  if (proposal.relatedDiagnosticIds.some((id) => !diagnosticIds.has(id))) throw new Error("Registry agent proposal references an unknown diagnostic.");
7479
7598
  if (proposal.evidence.some((item) => !evidenceKeys.has(evidenceKey2(item)))) throw new Error("Registry agent proposal contains evidence outside the supplied snapshot/report.");
7480
7599
  };
7481
- var runCli = (root, cli, context, timeoutMs, maxInputBytes, maxResponseBytes) => new Promise((resolve32, reject) => {
7600
+ var runCli = (root, cli, context, timeoutMs, maxInputBytes, maxResponseBytes) => new Promise((resolve33, reject) => {
7482
7601
  const v2 = "protocol" in context;
7483
7602
  const input = JSON.stringify(
7484
7603
  v2 ? { protocol: REGISTRY_AGENT_PROTOCOL_V2, response: 'Return exactly one JSON object { "proposals": [...] } on stdout. Do not emit markdown or logs on stdout.', context } : { protocol: "doc-bridge.registry-agent.v1", response: "Return exactly one AgentProposalV1 JSON object on stdout. Do not emit markdown or logs on stdout.", context }
@@ -7530,7 +7649,7 @@ var runCli = (root, cli, context, timeoutMs, maxInputBytes, maxResponseBytes) =>
7530
7649
  return;
7531
7650
  }
7532
7651
  try {
7533
- resolve32(JSON.parse(stdout));
7652
+ resolve33(JSON.parse(stdout));
7534
7653
  } catch (error) {
7535
7654
  reject(new Error(`Registry agent CLI must return one JSON object on stdout: ${error instanceof Error ? error.message : String(error)}`));
7536
7655
  }
@@ -7546,8 +7665,8 @@ var runCli = (root, cli, context, timeoutMs, maxInputBytes, maxResponseBytes) =>
7546
7665
  var loadRegistryAgentRunner = async (root, config) => {
7547
7666
  const metadata = loadRegistryAgentMetadata(root, config);
7548
7667
  const configured = registryConfig(config)?.runnerModule;
7549
- const modulePath = configured ? containedPath(root, configured) : containedPath(root, join11(metadata.root, "doc-bridge-adapter.js"));
7550
- if (!modulePath || !existsSync11(modulePath)) throw new Error(`Registry agent "${metadata.id}" has no local runner module. Configure intelligence.registry.runnerModule or add doc-bridge-adapter.js to the installed agent.`);
7668
+ const modulePath = configured ? containedPath(root, configured) : containedPath(root, join12(metadata.root, "doc-bridge-adapter.js"));
7669
+ if (!modulePath || !existsSync12(modulePath)) throw new Error(`Registry agent "${metadata.id}" has no local runner module. Configure intelligence.registry.runnerModule or add doc-bridge-adapter.js to the installed agent.`);
7551
7670
  const loaded = await import(pathToFileURL(modulePath).href);
7552
7671
  const runner = typeof loaded.run === "function" ? loaded.run : typeof loaded.default === "function" ? loaded.default : loaded.default && typeof loaded.default === "object" && "run" in loaded.default && typeof loaded.default.run === "function" ? loaded.default.run : void 0;
7553
7672
  if (!runner) throw new Error(`Registry agent runner at ${modulePath} must export a function or { run }. `);
@@ -7557,17 +7676,17 @@ var loadRegistryAgentMetadata = (root, config) => {
7557
7676
  const settings = registryConfig(config);
7558
7677
  const id = settings?.agentId ?? DEFAULT_REGISTRY_AGENT_ID;
7559
7678
  const agentRoot = settings?.agentRoot ?? "agents";
7560
- const agentPath = containedPath(root, join11(agentRoot, id));
7561
- if (!agentPath || !existsSync11(agentPath)) throw new Error(`AgentsKit Registry agent "${id}" is not installed at ${join11(agentRoot, id)}. Install it with: npx agentskit add ${id}`);
7562
- const metadataPath = [join11(agentPath, "agent.json"), join11(agentPath, "manifest.json")].find(existsSync11);
7679
+ const agentPath = containedPath(root, join12(agentRoot, id));
7680
+ if (!agentPath || !existsSync12(agentPath)) throw new Error(`AgentsKit Registry agent "${id}" is not installed at ${join12(agentRoot, id)}. Install it with: npx agentskit add ${id}`);
7681
+ const metadataPath = [join12(agentPath, "agent.json"), join12(agentPath, "manifest.json")].find(existsSync12);
7563
7682
  if (!metadataPath) throw new Error(`Registry agent "${id}" is installed but has no agent.json or manifest.json metadata.`);
7564
- const metadata = RegistryAgentMetadataSchema.parse(JSON.parse(readFileSync12(metadataPath, "utf8")));
7683
+ const metadata = RegistryAgentMetadataSchema.parse(JSON.parse(readFileSync13(metadataPath, "utf8")));
7565
7684
  if (metadata.id !== id) throw new Error(`Installed Registry agent metadata id "${metadata.id}" does not match configured id "${id}".`);
7566
7685
  return { ...metadata, root: agentPath };
7567
7686
  };
7568
7687
  var createRegistryAgentAdapter = (root, config, runner) => {
7569
7688
  if (!registryConfig(config)?.enabled) throw new Error("Registry agents are disabled. Set intelligence.registry.enabled: true to run an assisted workflow.");
7570
- const metadata = loadRegistryAgentMetadata(resolve11(root), config);
7689
+ const metadata = loadRegistryAgentMetadata(resolve12(root), config);
7571
7690
  const settings = registryConfig(config) ?? {};
7572
7691
  const timeoutMs = settings.timeoutMs ?? 12e4;
7573
7692
  const maxInputBytes = settings.maxInputBytes ?? 8e6;
@@ -7584,7 +7703,7 @@ var createRegistryAgentAdapter = (root, config, runner) => {
7584
7703
  try {
7585
7704
  let raw;
7586
7705
  if (settings.cli) {
7587
- raw = await runCli(resolve11(root), settings.cli, context, timeoutMs, maxInputBytes, maxResponseBytes);
7706
+ raw = await runCli(resolve12(root), settings.cli, context, timeoutMs, maxInputBytes, maxResponseBytes);
7588
7707
  } else {
7589
7708
  const localRunner = runner;
7590
7709
  const timeout = new Promise((_, reject) => {
@@ -7662,8 +7781,8 @@ var persistRegistryAgentProposal = (stateDir, proposal) => {
7662
7781
  AgentProposalV1Schema.parse(proposal);
7663
7782
  if (proposal.contentHash !== contentHashForArtifactV1(proposal)) throw new Error("Cannot persist a Registry agent proposal with an invalid contentHash.");
7664
7783
  const safeHash = contentHashForArtifactV1(proposal);
7665
- mkdirSync3(join11(resolve11(stateDir), "agents"), { recursive: true });
7666
- const path = join11(resolve11(stateDir), "agents", `${proposal.origin.id}-${safeHash}.json`);
7784
+ mkdirSync3(join12(resolve12(stateDir), "agents"), { recursive: true });
7785
+ const path = join12(resolve12(stateDir), "agents", `${proposal.origin.id}-${safeHash}.json`);
7667
7786
  writeFileSync3(path, `${JSON.stringify(proposal, null, 2)}
7668
7787
  `, "utf8");
7669
7788
  return path;
@@ -8040,15 +8159,15 @@ var reconcileKnowledge = (observed, declared, options = {}) => {
8040
8159
  };
8041
8160
 
8042
8161
  // src/audit/documentation.ts
8043
- import { readFileSync as readFileSync13 } from "fs";
8044
- import { resolve as resolve12 } from "path";
8162
+ import { readFileSync as readFileSync14 } from "fs";
8163
+ import { resolve as resolve13 } from "path";
8045
8164
  import { minimatch as minimatch6 } from "minimatch";
8046
8165
 
8047
8166
  // src/query/handoff.ts
8048
8167
  var MAX_RELATED = 3;
8049
8168
  var MAX_READ_BEFORE = 2;
8050
8169
  var MAX_RELATED_EVIDENCE = 3;
8051
- var dirname5 = (path) => path.split("/").slice(0, -1).join("/") || ".";
8170
+ var dirname6 = (path) => path.split("/").slice(0, -1).join("/") || ".";
8052
8171
  var isHttp = (value) => /^https?:\/\//.test(value);
8053
8172
  var bridgeFor = (config, id, humanDoc) => humanDoc ? { humanDoc: isHttp(humanDoc) ? "external" : "linked" } : config.corpus.human ? { humanDoc: "missing", action: "ak-docs bootstrap agent-docs", bootstrap: `docs/for-agents/human/${id}.md` } : void 0;
8054
8173
  var legacyHandoff = (index, id, config) => {
@@ -8184,7 +8303,7 @@ var handoffForEntity = (index, id, config, options = {}) => {
8184
8303
  const area = target2.graph.areaId ? byId.get(target2.graph.areaId) : void 0;
8185
8304
  const packageEntry = target2.graph.packageId ? byId.get(target2.graph.packageId) : target2.kind === "package" ? target2 : void 0;
8186
8305
  const explain = {};
8187
- const unit = target2.kind === "module" ? area ? { path: area.path, reason: `contained by area ${area.id}` } : packageEntry ? { path: packageEntry.path, reason: `contained by package ${packageEntry.id}` } : { path: dirname5(target2.path), reason: "the directory of the module; no area or package contains it" } : { path: ownership?.path ?? target2.path, reason: ownership ? `ownership ${ownership.id} path` : `the ${target2.kind} itself` };
8306
+ const unit = target2.kind === "module" ? area ? { path: area.path, reason: `contained by area ${area.id}` } : packageEntry ? { path: packageEntry.path, reason: `contained by package ${packageEntry.id}` } : { path: dirname6(target2.path), reason: "the directory of the module; no area or package contains it" } : { path: ownership?.path ?? target2.path, reason: ownership ? `ownership ${ownership.id} path` : `the ${target2.kind} itself` };
8188
8307
  explain.editRoots = [unit.reason];
8189
8308
  const documents = documentsFor(projection, byId, target2, ownership);
8190
8309
  const startHere = documents[0]?.path ?? config.corpus.agent.index ?? target2.path;
@@ -8652,7 +8771,7 @@ var auditDocumentation = (options) => {
8652
8771
  const generatedPaths = config.generatedPaths ?? [];
8653
8772
  const criticalPaths = config.criticalPaths ?? [];
8654
8773
  const requiredSections = config.requiredSections ?? [];
8655
- const documents = options.snapshot.entities.filter((entity) => entity.kind === "document" && entity.path).map((entity) => ({ path: normalizedPath2(entity.path), content: readFileSync13(resolve12(options.root, entity.path), "utf8") })).filter((document) => !matches(document.path, excluded)).sort((a, b) => a.path.localeCompare(b.path));
8774
+ const documents = options.snapshot.entities.filter((entity) => entity.kind === "document" && entity.path).map((entity) => ({ path: normalizedPath2(entity.path), content: readFileSync14(resolve13(options.root, entity.path), "utf8") })).filter((document) => !matches(document.path, excluded)).sort((a, b) => a.path.localeCompare(b.path));
8656
8775
  const findings = [];
8657
8776
  const generated = documents.filter((document) => matches(document.path, generatedPaths));
8658
8777
  const analyzed = documents.filter((document) => !matches(document.path, generatedPaths));
@@ -9220,7 +9339,7 @@ const findingMatches=(finding)=>{const query=state.query.toLowerCase();return(!q
9220
9339
  const findingScope=(finding)=>data.view?.diagnosticGroup?.[finding.id]?.[0]||(()=>{const ids=[...(finding.entityIds||[])];(finding.relationIds||[]).forEach((id)=>{const relation=relationById.get(id);if(relation)ids.push(relation.from,relation.to)});return ids.map(groupFor).sort()[0]||"repository"})();
9221
9340
  const findingGroups=(findings)=>{const groups=new Map();findings.forEach((finding)=>{const scope=findingScope(finding),key=[scope,finding.code,finding.status,finding.severity].join("|"),group=groups.get(key)||{key,scope,code:finding.code,status:finding.status,severity:finding.severity,findings:[]};group.findings.push(finding);groups.set(key,group)});return[...groups.values()].sort((left,right)=>right.findings.length-left.findings.length||left.code.localeCompare(right.code)||left.key.localeCompare(right.key))};
9222
9341
  const renderFinding=(finding)=>"<article class=\"finding\" id=\""+esc("diagnostic-"+finding.id.replace(/[^A-Za-z0-9_-]+/g,"-"))+"\"><div class=\"finding-head\"><h3>"+esc(finding.code)+"</h3><span><span class=\"tag "+esc(finding.severity)+"\">"+esc(finding.severity)+"</span> <span class=\"tag\">"+esc(finding.status)+"</span></span></div><p>"+esc(finding.message)+"</p>"+(finding.evidence.length?"<ul>"+finding.evidence.slice(0,4).map((item)=>"<li>"+esc(item.path+(item.lineStart?":"+item.lineStart:"")+(item.context?" — "+item.context:""))+"</li>").join("")+"</ul>":"")+(finding.remediation?"<p><strong>Next check:</strong> "+esc(finding.remediation)+"</p>":"")+"</article>";
9223
- const renderFindings=()=>{let findings=data.diagnostics.filter(findingMatches);if(state.lens==="risks")findings=findings.filter((finding)=>finding.severity==="error"||finding.severity==="warn");if(state.lens==="evidence")findings=findings.filter((finding)=>finding.evidence.length);if(state.lens==="drift")findings=findings.filter((finding)=>finding.status!=="confirmed");const itemLabel=state.lens==="evidence"?"evidence checks":"findings",groups=findingGroups(findings),active=groups.find((group)=>group.key===state.findingGroup);if(!active){state.findingGroup=null;state.findingPage=0}syncHash();const selected=active||null,pageSize=40,pageCount=selected?Math.ceil(selected.findings.length/pageSize):0,page=Math.max(0,Math.min(state.findingPage,Math.max(0,pageCount-1))),start=page*pageSize;document.querySelector("#finding-count").textContent=findings.length+" "+itemLabel+" · "+groups.length+" groups";document.querySelector("#findings").innerHTML=findings.length?"<div class=\"finding-groups\">"+groups.map((group)=>"<article class=\"finding-group\"><div class=\"finding-head\"><h3>"+esc(group.code)+"</h3><span><span class=\"tag "+esc(group.severity)+"\">"+esc(group.severity)+"</span> <span class=\"tag\">"+esc(group.status)+"</span></span></div><p><strong>"+group.findings.length+"</strong> "+itemLabel+" · "+esc(groupById.get(group.scope)?.name||group.scope)+"</p><p>"+esc(group.findings[0].message)+"</p><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(group.key)+"\" aria-expanded=\""+String(selected?.key===group.key)+"\">Inspect group</button></article>").join("")+"</div>"+(selected?"<div class=\"finding-detail\"><div class=\"finding-head\"><h3>"+esc(selected.code)+" · "+esc(groupById.get(selected.scope)?.name||selected.scope)+"</h3><span class=\"subtle\">"+selected.findings.length+" "+itemLabel+"</span></div>"+selected.findings.slice(start,start+pageSize).map(renderFinding).join("")+"<div class=\"finding-actions\"><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(selected.key)+"\" data-finding-page=\""+(page-1)+"\" "+(page===0?"disabled":"")+">Previous</button><span class=\"subtle\">Showing "+(start+1)+"–"+Math.min(start+pageSize,selected.findings.length)+" of "+selected.findings.length+" · page "+(page+1)+"/"+pageCount+"</span><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(selected.key)+"\" data-finding-page=\""+(page+1)+"\" "+(page+1>=pageCount?"disabled":"")+">Next</button></div></div>":""):"<p class=\"empty\">No "+itemLabel+" match the current lens and filters.</p>"};
9342
+ const renderFindings=()=>{let findings=data.diagnostics.filter(findingMatches);if(state.lens==="risks")findings=findings.filter((finding)=>finding.severity==="error"||finding.severity==="warn");if(state.lens==="evidence")findings=findings.filter((finding)=>finding.evidence.length);if(state.lens==="drift")findings=findings.filter((finding)=>finding.status!=="confirmed");const itemLabel=state.lens==="evidence"?"evidence checks":"findings",groups=findingGroups(findings),active=groups.find((group)=>group.key===state.findingGroup);if(!active){state.findingGroup=null;state.findingPage=0}syncHash();const selected=active||null,pageSize=40,pageCount=selected?Math.ceil(selected.findings.length/pageSize):0,page=Math.max(0,Math.min(state.findingPage,Math.max(0,pageCount-1))),start=page*pageSize;document.querySelector("#finding-count").textContent=findings.length+" "+itemLabel+" · "+groups.length+" groups";document.querySelector("#findings").innerHTML=findings.length?"<div class=\"finding-groups\">"+groups.map((group)=>"<article class=\"finding-group\"><div class=\"finding-head\"><h3>"+esc(group.code)+"</h3><span><span class=\"tag "+esc(group.severity)+"\">"+esc(group.severity)+"</span> <span class=\"tag\">"+esc(group.status)+"</span></span></div><p><strong>"+group.findings.length+"</strong> "+itemLabel+" · "+esc(groupById.get(group.scope)?.name||group.scope)+"</p><p>"+esc(group.findings[0].message)+"</p><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(group.key)+"\" aria-expanded=\""+String(selected?.key===group.key)+"\">Inspect group</button></article>").join("")+"</div>"+(selected?"<div class=\"finding-detail\"><div class=\"finding-head\"><h3>"+esc(selected.code)+" · "+esc(groupById.get(selected.scope)?.name||selected.scope)+"</h3><span class=\"subtle\">"+selected.findings.length+" "+itemLabel+"</span></div>"+selected.findings.slice(start,start+pageSize).map(renderFinding).join("")+"<div class=\"finding-actions\"><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(selected.key)+"\" data-finding-page=\""+(page - 1)+"\" "+(page===0?"disabled":"")+">Previous</button><span class=\"subtle\">Showing "+(start+1)+"–"+Math.min(start+pageSize,selected.findings.length)+" of "+selected.findings.length+" · page "+(page+1)+"/"+pageCount+"</span><button class=\"tab\" type=\"button\" data-finding-group=\""+esc(selected.key)+"\" data-finding-page=\""+(page+1)+"\" "+(page+1>=pageCount?"disabled":"")+">Next</button></div></div>":""):"<p class=\"empty\">No "+itemLabel+" match the current lens and filters.</p>"};
9224
9343
  const renderCoverage=()=>{document.querySelector("#coverage-list").innerHTML=(data.coverage||[]).map((entry)=>{const width=entry.status==="complete"?100:entry.status==="partial"?55:12;return"<div class=\"coverage-row\"><div><b>"+esc(entry.analyzer)+"</b><br><span class=\"subtle\">"+esc(entry.scope)+"</span></div><div class=\"bar\"><i class=\""+(entry.status==="complete"?"":entry.status==="partial"?"partial":"none")+"\" style=\"width:"+width+"%\"></i></div><div>"+esc(entry.status)+"</div></div>"}).join("")||"<p class=\"empty\">No coverage metadata.</p>"};
9225
9344
  const deferFindings=()=>{if(findingsLoaded())return;const actionable=data.actionableCount??data.diagnosticCount??0,confirmed=data.confirmedCount??0;document.querySelector("#finding-count").textContent=actionable+" actionable findings · "+confirmed+" confirmed checks available on demand";document.querySelector("#findings").innerHTML="<div class=\"empty\"><p>Findings stay out of the first paint so large repositories remain responsive. Confirmed checks are evidence, not issues.</p><button id=\"load-findings\" class=\"tab\" type=\"button\">Load findings</button></div>"};
9226
9345
  const scopePrompt=()=>{if((state.level==="module"||state.level==="file")&&!state.selected){document.querySelector("#map-note").textContent="Select an app or package to inspect this level.";document.querySelector("#graph").innerHTML="<text x=\"500\" y=\"270\" text-anchor=\"middle\" class=\"subtle\">Select an app or package to expand this view.</text>"}};
@@ -9389,14 +9508,14 @@ var renderOfflineReportArtifact = (input, options = {}) => {
9389
9508
  };
9390
9509
 
9391
9510
  // src/fixes/proposals.ts
9392
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync14, realpathSync as realpathSync7, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
9393
- import { basename as basename7, dirname as dirname6, extname as extname5, join as join12, relative as relative7, resolve as resolve13, sep as sep8 } from "path";
9511
+ import { existsSync as existsSync13, readdirSync as readdirSync4, readFileSync as readFileSync15, realpathSync as realpathSync8, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
9512
+ import { basename as basename7, dirname as dirname7, extname as extname5, join as join13, relative as relative8, resolve as resolve14, sep as sep9 } from "path";
9394
9513
  var hash4 = (value) => sha256NormalizedV1(value);
9395
9514
  var artifactMetadata = (root, options) => ({
9396
9515
  schemaVersion: 1,
9397
9516
  contentHash: "0".repeat(64),
9398
9517
  contentHashAlgo: "sha256-normalized-v1",
9399
- project: { name: options.projectName ?? basename7(resolve13(root)), root: "." },
9518
+ project: { name: options.projectName ?? basename7(resolve14(root)), root: "." },
9400
9519
  sourceRevision: options.baseRevision,
9401
9520
  sourceRevisionKind: options.baseRevision.length === 40 ? "git" : "content",
9402
9521
  configurationHash: options.configurationHash,
@@ -9427,31 +9546,32 @@ var makeProposal = (root, options, changes, preconditions, postconditions) => {
9427
9546
  };
9428
9547
  return FixProposalV1Schema.parse({ ...draft, contentHash: contentHashForArtifactV1(draft) });
9429
9548
  };
9430
- var walkMarkdown = (root, directory = root) => readdirSync4(directory, { withFileTypes: true }).flatMap((entry) => {
9549
+ var walkMarkdown = (root, directory = root, ignored = createIgnoreFilter(root)) => readdirSync4(directory, { withFileTypes: true }).flatMap((entry) => {
9431
9550
  if (entry.name === ".git" || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build") return [];
9432
- const path = join12(directory, entry.name);
9433
- if (entry.isDirectory()) return walkMarkdown(root, path);
9434
- return entry.isFile() && [".md", ".mdx"].includes(extname5(entry.name).toLowerCase()) ? [relative7(root, path).split(sep8).join("/")] : [];
9551
+ const path = join13(directory, entry.name);
9552
+ if (ignored.isIgnored(path, entry.isDirectory())) return [];
9553
+ if (entry.isDirectory()) return walkMarkdown(root, path, ignored);
9554
+ return entry.isFile() && [".md", ".mdx"].includes(extname5(entry.name).toLowerCase()) ? [relative8(root, path).split(sep9).join("/")] : [];
9435
9555
  });
9436
9556
  var localLink = /(!?)\[([^\]]*)\]\(([^)\s]+)(?:\s+["'][^)]*["'])?\)/g;
9437
9557
  var sortJson = (value) => Array.isArray(value) ? value.map(sortJson) : value && typeof value === "object" ? Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => [key, sortJson(item)])) : value;
9438
9558
  var createMarkdownLinkFixProposal = (root, options) => {
9439
- const projectRoot = realpathSync7.native(resolve13(root));
9559
+ const projectRoot = realpathSync8.native(resolve14(root));
9440
9560
  const paths = walkMarkdown(projectRoot);
9441
9561
  const changes = [];
9442
9562
  for (const path of paths) {
9443
- const content = readFileSync14(join12(projectRoot, path), "utf8");
9563
+ const content = readFileSync15(join13(projectRoot, path), "utf8");
9444
9564
  let next = content;
9445
9565
  for (const match of content.matchAll(localLink)) {
9446
9566
  const target2 = match[3];
9447
9567
  if (!target2 || match[1] === "!" || /^(?:[a-z]+:|\/|#)/i.test(target2)) continue;
9448
9568
  const targetPath = target2.split("#")[0]?.split("?")[0];
9449
- if (!targetPath || existsSync12(resolve13(projectRoot, dirname6(path), targetPath))) continue;
9569
+ if (!targetPath || existsSync13(resolve14(projectRoot, dirname7(path), targetPath))) continue;
9450
9570
  const targetStem = basename7(targetPath, extname5(targetPath)).toLowerCase();
9451
9571
  const labelStem = (match[2] ?? "").trim().toLowerCase().replace(/[^a-z0-9]+/g, "");
9452
9572
  const candidates = paths.filter((candidate) => basename7(candidate, extname5(candidate)).toLowerCase() === targetStem || basename7(candidate, extname5(candidate)).toLowerCase().replace(/[^a-z0-9]+/g, "") === labelStem);
9453
9573
  if (candidates.length !== 1) continue;
9454
- let replacement = relative7(dirname6(path), candidates[0]).split(sep8).join("/");
9574
+ let replacement = relative8(dirname7(path), candidates[0]).split(sep9).join("/");
9455
9575
  if (target2.startsWith("./") && !replacement.startsWith(".")) replacement = `./${replacement}`;
9456
9576
  next = next.replace(match[0], match[0].replace(target2, replacement));
9457
9577
  }
@@ -9460,13 +9580,13 @@ var createMarkdownLinkFixProposal = (root, options) => {
9460
9580
  return changes.length ? makeProposal(projectRoot, options, changes, ["Each replacement has exactly one Markdown target."], ["All corrected local Markdown links resolve."]) : void 0;
9461
9581
  };
9462
9582
  var createArtifactNormalizationProposal = (root, artifactPath, options) => {
9463
- const projectRoot = realpathSync7.native(resolve13(root));
9464
- const path = artifactPath.split(sep8).join("/");
9583
+ const projectRoot = realpathSync8.native(resolve14(root));
9584
+ const path = artifactPath.split(sep9).join("/");
9465
9585
  const absolute = containedPath(projectRoot, path);
9466
9586
  if (!absolute) return void 0;
9467
9587
  let before;
9468
9588
  try {
9469
- before = readFileSync14(absolute, "utf8");
9589
+ before = readFileSync15(absolute, "utf8");
9470
9590
  } catch {
9471
9591
  return void 0;
9472
9592
  }
@@ -9477,7 +9597,7 @@ var createArtifactNormalizationProposal = (root, artifactPath, options) => {
9477
9597
  } catch {
9478
9598
  return void 0;
9479
9599
  }
9480
- return after === before ? void 0 : makeProposal(projectRoot, options, [{ path: relative7(projectRoot, absolute).split(sep8).join("/"), before, after }], ["The artifact contains valid JSON."], ["The artifact is valid canonical JSON with one trailing newline."]);
9600
+ return after === before ? void 0 : makeProposal(projectRoot, options, [{ path: relative8(projectRoot, absolute).split(sep9).join("/"), before, after }], ["The artifact contains valid JSON."], ["The artifact is valid canonical JSON with one trailing newline."]);
9481
9601
  };
9482
9602
  var approveFixProposal = (proposalInput, approvedBy, approvedAt = (/* @__PURE__ */ new Date()).toISOString()) => {
9483
9603
  const proposal = FixProposalV1Schema.parse(proposalInput);
@@ -9495,7 +9615,7 @@ var applyFixProposal = (root, proposalInput, options = {}) => {
9495
9615
  if (proposal.approval.proposalHash !== bindingHash(proposal)) throw new Error("Approval is not bound to the exact proposal content.");
9496
9616
  if (options.currentRevision && options.currentRevision !== proposal.baseRevision) throw new Error("The repository revision changed since this proposal was created.");
9497
9617
  if (!proposal.changes?.length) throw new Error("This proposal has no executable changes.");
9498
- const projectRoot = realpathSync7.native(resolve13(root));
9618
+ const projectRoot = realpathSync8.native(resolve14(root));
9499
9619
  const originals = /* @__PURE__ */ new Map();
9500
9620
  const affected = new Map(proposal.affectedFiles.map((file) => [file.path, file]));
9501
9621
  if (proposal.changes.some((change) => !affected.has(change.path) || affected.get(change.path)?.contentHash !== sha256NormalizedV1(change.before)) || affected.size !== proposal.changes.length) {
@@ -9503,29 +9623,29 @@ var applyFixProposal = (root, proposalInput, options = {}) => {
9503
9623
  }
9504
9624
  for (const file of proposal.affectedFiles) {
9505
9625
  const absolute = containedPath(projectRoot, file.path);
9506
- if (!absolute || !existsSync12(absolute)) throw new Error(`Affected file is unavailable or escapes the repository root: ${file.path}`);
9507
- const current = readFileSync14(absolute, "utf8");
9626
+ if (!absolute || !existsSync13(absolute)) throw new Error(`Affected file is unavailable or escapes the repository root: ${file.path}`);
9627
+ const current = readFileSync15(absolute, "utf8");
9508
9628
  if (sha256NormalizedV1(current) !== file.contentHash) throw new Error(`Affected file changed since proposal creation: ${file.path}`);
9509
9629
  originals.set(absolute, current);
9510
9630
  }
9511
9631
  try {
9512
9632
  for (const change of proposal.changes) {
9513
- const absolute = resolve13(projectRoot, change.path);
9633
+ const absolute = resolve14(projectRoot, change.path);
9514
9634
  writeFileSync4(`${absolute}.docbridge-${process.pid}.tmp`, change.after, "utf8");
9515
9635
  }
9516
9636
  for (const change of proposal.changes) {
9517
- const absolute = resolve13(projectRoot, change.path);
9637
+ const absolute = resolve14(projectRoot, change.path);
9518
9638
  renameSync2(`${absolute}.docbridge-${process.pid}.tmp`, absolute);
9519
9639
  }
9520
9640
  for (const change of proposal.changes) {
9521
- if (readFileSync14(resolve13(projectRoot, change.path), "utf8") !== change.after) throw new Error(`Postcondition failed for ${change.path}`);
9641
+ if (readFileSync15(resolve14(projectRoot, change.path), "utf8") !== change.after) throw new Error(`Postcondition failed for ${change.path}`);
9522
9642
  }
9523
9643
  options.verify?.(proposal.changes.map((change) => change.path));
9524
9644
  } catch (error) {
9525
9645
  for (const [absolute, content] of originals) writeFileSync4(absolute, content, "utf8");
9526
9646
  for (const change of proposal.changes) {
9527
- const temp = `${resolve13(projectRoot, change.path)}.docbridge-${process.pid}.tmp`;
9528
- if (existsSync12(temp)) unlinkSync(temp);
9647
+ const temp = `${resolve14(projectRoot, change.path)}.docbridge-${process.pid}.tmp`;
9648
+ if (existsSync13(temp)) unlinkSync(temp);
9529
9649
  }
9530
9650
  throw error;
9531
9651
  }
@@ -9534,8 +9654,8 @@ var applyFixProposal = (root, proposalInput, options = {}) => {
9534
9654
  };
9535
9655
 
9536
9656
  // src/workflow/engine.ts
9537
- import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync15, renameSync as renameSync3, rmSync, writeFileSync as writeFileSync5 } from "fs";
9538
- import { join as join13, relative as relative8, resolve as resolve14 } from "path";
9657
+ import { appendFileSync, existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync16, renameSync as renameSync3, rmSync, writeFileSync as writeFileSync5 } from "fs";
9658
+ import { join as join14, relative as relative9, resolve as resolve15 } from "path";
9539
9659
  var WORKFLOW_STAGES = ["collect", "normalize", "reconcile", "enrich", "evaluate", "report"];
9540
9660
  var OPTIONAL_WORKFLOW_STAGES = ["enrich"];
9541
9661
  var stageState = {
@@ -9546,7 +9666,7 @@ var stageState = {
9546
9666
  evaluate: "proposed",
9547
9667
  report: "delivered"
9548
9668
  };
9549
- var defaultStateDir = (root) => join13(root, ".doc-bridge", "workflow");
9669
+ var defaultStateDir = (root) => join14(root, ".doc-bridge", "workflow");
9550
9670
  var atomicWrite = (path, value) => {
9551
9671
  const temp = `${path}.tmp-${process.pid}-${Date.now()}`;
9552
9672
  writeFileSync5(temp, `${JSON.stringify(value, null, 2)}
@@ -9554,10 +9674,10 @@ var atomicWrite = (path, value) => {
9554
9674
  renameSync3(temp, path);
9555
9675
  };
9556
9676
  var writeManifest = (stateDir, run2) => {
9557
- atomicWrite(join13(stateDir, "manifest.json"), run2);
9677
+ atomicWrite(join14(stateDir, "manifest.json"), run2);
9558
9678
  };
9559
9679
  var appendTransition = (stateDir, transition2) => {
9560
- appendFileSync(join13(stateDir, "transitions.jsonl"), `${JSON.stringify(transition2)}
9680
+ appendFileSync(join14(stateDir, "transitions.jsonl"), `${JSON.stringify(transition2)}
9561
9681
  `, "utf8");
9562
9682
  };
9563
9683
  var transition = (run2, to, reason) => {
@@ -9588,8 +9708,8 @@ var transition = (run2, to, reason) => {
9588
9708
  };
9589
9709
  var runId = () => `${Date.now()}-${process.pid}`;
9590
9710
  var stageInputHash = (options, stage, input) => sha256NormalizedV1({ stage, input, sourceRevision: options.sourceRevision, configurationHash: options.configurationHash, pipelineVersion: options.pipelineVersion ?? "1.0.0", analyzerVersions: options.analyzerVersions ?? {}, toolVersion: options.toolVersion ?? "1.0.0" });
9591
- var stageArtifactPath = (stateDir, stage, inputHash) => join13(stateDir, "artifacts", `${stage}-${inputHash}.json`);
9592
- var readArtifact = (path) => JSON.parse(readFileSync15(path, "utf8"));
9711
+ var stageArtifactPath = (stateDir, stage, inputHash) => join14(stateDir, "artifacts", `${stage}-${inputHash}.json`);
9712
+ var readArtifact = (path) => JSON.parse(readFileSync16(path, "utf8"));
9593
9713
  var readVerifiedArtifact = (path, stage, step) => {
9594
9714
  const artifact2 = readArtifact(path);
9595
9715
  if (artifact2.type !== "workflow-step-artifact" || artifact2.stage !== stage || artifact2.inputHash !== step.inputHash) throw new Error(`Invalid workflow artifact for stage "${stage}".`);
@@ -9597,8 +9717,8 @@ var readVerifiedArtifact = (path, stage, step) => {
9597
9717
  return artifact2;
9598
9718
  };
9599
9719
  var stepArtifactPath = (stateDir, step) => {
9600
- const path = resolve14(stateDir, step.artifactRefs?.[0] ?? "");
9601
- const pathRelativeToState = relative8(stateDir, path);
9720
+ const path = resolve15(stateDir, step.artifactRefs?.[0] ?? "");
9721
+ const pathRelativeToState = relative9(stateDir, path);
9602
9722
  if (pathRelativeToState.startsWith("..") || pathRelativeToState.startsWith("/")) throw new Error(`Workflow artifact escapes state directory for stage "${step.name}".`);
9603
9723
  return path;
9604
9724
  };
@@ -9608,13 +9728,13 @@ var stepOutput = (stateDir, run2, stage) => {
9608
9728
  return readVerifiedArtifact(stepArtifactPath(stateDir, step), stage, step).value;
9609
9729
  };
9610
9730
  var acquireLock = (stateDir) => {
9611
- const lock = join13(stateDir, ".lock");
9731
+ const lock = join14(stateDir, ".lock");
9612
9732
  try {
9613
9733
  mkdirSync4(lock);
9614
9734
  } catch {
9615
- const ownerPath = join13(lock, "owner.json");
9735
+ const ownerPath = join14(lock, "owner.json");
9616
9736
  try {
9617
- const owner = JSON.parse(readFileSync15(ownerPath, "utf8"));
9737
+ const owner = JSON.parse(readFileSync16(ownerPath, "utf8"));
9618
9738
  if (typeof owner.pid === "number") process.kill(owner.pid, 0);
9619
9739
  throw new Error(`Workflow is already running (pid ${owner.pid ?? "unknown"}).`);
9620
9740
  } catch (error) {
@@ -9623,13 +9743,13 @@ var acquireLock = (stateDir) => {
9623
9743
  mkdirSync4(lock);
9624
9744
  }
9625
9745
  }
9626
- writeFileSync5(join13(lock, "owner.json"), JSON.stringify({ pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
9746
+ writeFileSync5(join14(lock, "owner.json"), JSON.stringify({ pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
9627
9747
  return () => rmSync(lock, { recursive: true, force: true });
9628
9748
  };
9629
9749
  var loadManifest = (stateDir) => {
9630
- const path = join13(stateDir, "manifest.json");
9631
- if (!existsSync13(path)) return void 0;
9632
- return WorkflowRunV1Schema.parse(JSON.parse(readFileSync15(path, "utf8")));
9750
+ const path = join14(stateDir, "manifest.json");
9751
+ if (!existsSync14(path)) return void 0;
9752
+ return WorkflowRunV1Schema.parse(JSON.parse(readFileSync16(path, "utf8")));
9633
9753
  };
9634
9754
  var baseRun = (options, stateDir, supersedes) => {
9635
9755
  const inputHash = sha256NormalizedV1({ sourceRevision: options.sourceRevision, configurationHash: options.configurationHash, pipelineVersion: options.pipelineVersion ?? "1.0.0", analyzerVersions: options.analyzerVersions ?? {}, toolVersion: options.toolVersion ?? "1.0.0" });
@@ -9638,7 +9758,7 @@ var baseRun = (options, stateDir, supersedes) => {
9638
9758
  schemaVersion: 1,
9639
9759
  contentHash: "0".repeat(64),
9640
9760
  contentHashAlgo: "sha256-normalized-v1",
9641
- project: { name: resolve14(options.root).split("/").pop() ?? "project", root: "." },
9761
+ project: { name: resolve15(options.root).split("/").pop() ?? "project", root: "." },
9642
9762
  sourceRevision: options.sourceRevision,
9643
9763
  sourceRevisionKind: "content",
9644
9764
  configurationHash: options.configurationHash,
@@ -9649,16 +9769,16 @@ var baseRun = (options, stateDir, supersedes) => {
9649
9769
  state: "created",
9650
9770
  steps: WORKFLOW_STAGES.map((name) => ({ name, status: "pending", inputHash })),
9651
9771
  transitions: [{ from: null, to: "created", at: (/* @__PURE__ */ new Date()).toISOString() }],
9652
- artifactRefs: [relative8(resolve14(options.root), stateDir), ...supersedes ? [`supersedes:${supersedes}`] : []]
9772
+ artifactRefs: [relative9(resolve15(options.root), stateDir), ...supersedes ? [`supersedes:${supersedes}`] : []]
9653
9773
  });
9654
9774
  };
9655
9775
  var withHash = (run2) => WorkflowRunV1Schema.parse({ ...run2, contentHash: contentHashForArtifactV1(run2) });
9656
9776
  var sameInputs = (run2, options) => run2.sourceRevision === options.sourceRevision && run2.configurationHash === options.configurationHash && run2.pipelineVersion === (options.pipelineVersion ?? "1.0.0") && sha256NormalizedV1(run2.analyzerVersions) === sha256NormalizedV1({ ...options.analyzerVersions ?? {}, workflow: options.toolVersion ?? "1.0.0" });
9657
9777
  var selectedStages = (stage) => stage && stage !== "all" ? [stage] : WORKFLOW_STAGES;
9658
9778
  var runWorkflow = (options) => {
9659
- const root = resolve14(options.root);
9660
- const stateDir = resolve14(root, options.stateDir ?? defaultStateDir(root));
9661
- mkdirSync4(join13(stateDir, "artifacts"), { recursive: true });
9779
+ const root = resolve15(options.root);
9780
+ const stateDir = resolve15(root, options.stateDir ?? defaultStateDir(root));
9781
+ mkdirSync4(join14(stateDir, "artifacts"), { recursive: true });
9662
9782
  const release = acquireLock(stateDir);
9663
9783
  try {
9664
9784
  let run2 = loadManifest(stateDir);
@@ -9697,8 +9817,8 @@ var runWorkflow = (options) => {
9697
9817
  const input = options.inputs?.[stage] ?? previousOutput;
9698
9818
  const inputHash = stageInputHash(options, stage, input);
9699
9819
  const existing = run2.steps.find((step) => step.name === stage);
9700
- const artifactPath = existing?.artifactRefs?.[0] && existing.inputHash === inputHash ? resolve14(stateDir, existing.artifactRefs[0]) : stageArtifactPath(stateDir, stage, inputHash);
9701
- if (existing?.status === "completed" && existing.inputHash === inputHash && existing.outputHash && existsSync13(artifactPath)) {
9820
+ const artifactPath = existing?.artifactRefs?.[0] && existing.inputHash === inputHash ? resolve15(stateDir, existing.artifactRefs[0]) : stageArtifactPath(stateDir, stage, inputHash);
9821
+ if (existing?.status === "completed" && existing.inputHash === inputHash && existing.outputHash && existsSync14(artifactPath)) {
9702
9822
  try {
9703
9823
  previousOutput = readVerifiedArtifact(artifactPath, stage, existing).value;
9704
9824
  } catch (error) {
@@ -9728,14 +9848,14 @@ var runWorkflow = (options) => {
9728
9848
  const value = handler({ root, stage, input, previousOutput });
9729
9849
  const outputHash = sha256NormalizedV1(value);
9730
9850
  const artifact2 = { type: "workflow-step-artifact", stage, inputHash, outputHash, value };
9731
- mkdirSync4(join13(stateDir, "artifacts"), { recursive: true });
9732
- if (existsSync13(artifactPath)) {
9851
+ mkdirSync4(join14(stateDir, "artifacts"), { recursive: true });
9852
+ if (existsSync14(artifactPath)) {
9733
9853
  const existingArtifact = readArtifact(artifactPath);
9734
9854
  if (existingArtifact.outputHash !== outputHash) throw new Error(`Immutable workflow artifact collision for stage "${stage}".`);
9735
9855
  } else {
9736
9856
  atomicWrite(artifactPath, artifact2);
9737
9857
  }
9738
- const ref = relative8(stateDir, artifactPath);
9858
+ const ref = relative9(stateDir, artifactPath);
9739
9859
  const completedStep = { name: stage, status: "completed", inputHash, outputHash, artifactRefs: [ref] };
9740
9860
  run2 = withHash({ ...run2, steps: run2.steps.map((step) => step.name === stage ? completedStep : step) });
9741
9861
  writeManifest(stateDir, run2);
@@ -9755,15 +9875,15 @@ var runWorkflow = (options) => {
9755
9875
  run2 = complete;
9756
9876
  }
9757
9877
  writeManifest(stateDir, run2);
9758
- if (run2.state === "delivered") atomicWrite(join13(stateDir, "last-known-good.json"), { runId: run2.runId, manifestHash: run2.contentHash, report: run2.steps.find((step) => step.name === "report")?.artifactRefs?.[0] });
9878
+ if (run2.state === "delivered") atomicWrite(join14(stateDir, "last-known-good.json"), { runId: run2.runId, manifestHash: run2.contentHash, report: run2.steps.find((step) => step.name === "report")?.artifactRefs?.[0] });
9759
9879
  }
9760
9880
  return { run: run2, stateDir, reusedStages };
9761
9881
  } finally {
9762
9882
  release();
9763
9883
  }
9764
9884
  };
9765
- var loadWorkflowManifest = (stateDir) => WorkflowRunV1Schema.parse(JSON.parse(readFileSync15(join13(resolve14(stateDir), "manifest.json"), "utf8")));
9766
- var loadWorkflowStepOutput = (stateDir, stage) => stepOutput(resolve14(stateDir), loadWorkflowManifest(stateDir), stage);
9885
+ var loadWorkflowManifest = (stateDir) => WorkflowRunV1Schema.parse(JSON.parse(readFileSync16(join14(resolve15(stateDir), "manifest.json"), "utf8")));
9886
+ var loadWorkflowStepOutput = (stateDir, stage) => stepOutput(resolve15(stateDir), loadWorkflowManifest(stateDir), stage);
9767
9887
 
9768
9888
  // src/study/metrics.ts
9769
9889
  import { z as z13 } from "zod";
@@ -10367,11 +10487,11 @@ var resolvedOptions = (options) => {
10367
10487
  const config = RulesConfigSchema.parse(options.config ?? {});
10368
10488
  const mode = options.preset ?? config.mode ?? "default";
10369
10489
  const severity = { ...config.severity, ...options.severity };
10370
- const ignore = /* @__PURE__ */ new Set([...config.ignore ?? [], ...options.ignore ?? []]);
10490
+ const ignore2 = /* @__PURE__ */ new Set([...config.ignore ?? [], ...options.ignore ?? []]);
10371
10491
  return {
10372
10492
  mode,
10373
10493
  severity,
10374
- ignore,
10494
+ ignore: ignore2,
10375
10495
  criticalEntities: options.criticalEntities ?? config.criticalEntities ?? [],
10376
10496
  criticalPaths: options.criticalPaths ?? config.criticalPaths ?? [],
10377
10497
  warningThresholds: { ...config.warningThresholds, ...options.warningThresholds }
@@ -10486,11 +10606,11 @@ function formatEcosystemLlmsSection(options) {
10486
10606
  }
10487
10607
 
10488
10608
  // src/gates/run-gates.ts
10489
- import { readFileSync as readFileSync18 } from "fs";
10609
+ import { readFileSync as readFileSync19 } from "fs";
10490
10610
 
10491
10611
  // src/conformance/documentation-standard-v1.ts
10492
- import { closeSync as closeSync2, existsSync as existsSync14, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync16, realpathSync as realpathSync8 } from "fs";
10493
- import { isAbsolute as isAbsolute5, relative as relative9, resolve as resolve15, sep as sep9 } from "path";
10612
+ import { closeSync as closeSync2, existsSync as existsSync15, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync17, realpathSync as realpathSync9 } from "fs";
10613
+ import { isAbsolute as isAbsolute6, relative as relative10, resolve as resolve16, sep as sep10 } from "path";
10494
10614
 
10495
10615
  // src/conformance/ecosystem-contract.ts
10496
10616
  import { z as z15 } from "zod";
@@ -10540,10 +10660,9 @@ var ManifestSchema = z15.object({
10540
10660
  schemaVersion: z15.literal(2),
10541
10661
  parentBrand: z15.object({ id: NonEmptyStringSchema, name: NonEmptyStringSchema }).passthrough(),
10542
10662
  products: z15.array(ProductSchema).min(1),
10543
- // Historical four-product shim or full seven-product projection of products[].
10544
- properties: z15.array(LegacyPropertySchema).refine((value) => value.length === 4 || value.length === 7, {
10545
- message: "must project either the legacy four products or the full seven-product catalog"
10546
- }),
10663
+ // Deprecated compatibility shim: when present, every entry projects one products[] record.
10664
+ // Membership is whatever the canonical manifest lists; no product is required by name.
10665
+ properties: z15.array(LegacyPropertySchema).optional(),
10547
10666
  builder: z15.object({ id: NonEmptyStringSchema, name: NonEmptyStringSchema, url: HttpsUrlSchema }).passthrough().optional()
10548
10667
  }).passthrough();
10549
10668
  var EvidenceSchema2 = z15.discriminatedUnion("type", [
@@ -10577,16 +10696,6 @@ var ClaimsSchema = z15.object({
10577
10696
  manifestSchemaVersion: z15.literal(2),
10578
10697
  products: z15.array(ClaimProductSchema)
10579
10698
  }).passthrough();
10580
- var LEGACY_FOUR_PRODUCT_IDS = ["agentskit", "akos", "playbook", "registry"];
10581
- var FULL_SEVEN_PRODUCT_IDS = [
10582
- "agentskit",
10583
- "registry",
10584
- "agentskit-chat",
10585
- "playbook",
10586
- "doc-bridge",
10587
- "code-review",
10588
- "akos"
10589
- ];
10590
10699
  var parseCanonicalEcosystemContract = (manifestInput, claimsInput) => {
10591
10700
  const manifest = ManifestSchema.parse(manifestInput);
10592
10701
  const claims = ClaimsSchema.parse(claimsInput);
@@ -10612,12 +10721,14 @@ var parseCanonicalEcosystemContract = (manifestInput, claimsInput) => {
10612
10721
  if (!products.has(nextId)) throw new Error(`Product ${product.id} references unknown product ${nextId}.`);
10613
10722
  }
10614
10723
  }
10615
- const propertyIds = manifest.properties.length === 7 ? FULL_SEVEN_PRODUCT_IDS : LEGACY_FOUR_PRODUCT_IDS;
10616
- for (const [index, id] of propertyIds.entries()) {
10617
- const legacy = manifest.properties[index];
10724
+ const propertyIds = /* @__PURE__ */ new Set();
10725
+ for (const [index, legacy] of (manifest.properties ?? []).entries()) {
10726
+ const id = legacy.id;
10618
10727
  const product = products.get(id);
10619
- if (!legacy || !product || legacy.id !== id || !product.surfaces.home) {
10620
- throw new Error(`Legacy property ${index} must project product ${id}.`);
10728
+ if (propertyIds.has(id)) throw new Error(`Legacy property ${id} is listed more than once.`);
10729
+ propertyIds.add(id);
10730
+ if (!product || !product.surfaces.home) {
10731
+ throw new Error(`Legacy property ${index} (${id}) must project a manifest product with a home surface.`);
10621
10732
  }
10622
10733
  const expected = {
10623
10734
  name: product.name,
@@ -10672,15 +10783,15 @@ var DOCUMENTATION_STANDARD_V1_ID = "documentation-standard-v1";
10672
10783
  var DOCUMENTATION_STANDARD_V1_STATUS = "stable";
10673
10784
  var MAX_TEXT_EVIDENCE_BYTES = 4 * 1024 * 1024;
10674
10785
  var safePath = (root, path) => {
10675
- const rootAbs = realpathSync8.native(resolve15(root));
10676
- const unresolved = resolve15(rootAbs, path);
10677
- const unresolvedRel = relative9(rootAbs, unresolved);
10678
- if (isAbsolute5(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep9}`)) return void 0;
10679
- if (!existsSync14(unresolved)) return unresolved;
10786
+ const rootAbs = realpathSync9.native(resolve16(root));
10787
+ const unresolved = resolve16(rootAbs, path);
10788
+ const unresolvedRel = relative10(rootAbs, unresolved);
10789
+ if (isAbsolute6(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep10}`)) return void 0;
10790
+ if (!existsSync15(unresolved)) return unresolved;
10680
10791
  try {
10681
- const abs = realpathSync8.native(unresolved);
10682
- const rel = relative9(rootAbs, abs);
10683
- return !isAbsolute5(rel) && rel !== ".." && !rel.startsWith(`..${sep9}`) ? abs : void 0;
10792
+ const abs = realpathSync9.native(unresolved);
10793
+ const rel = relative10(rootAbs, abs);
10794
+ return !isAbsolute6(rel) && rel !== ".." && !rel.startsWith(`..${sep10}`) ? abs : void 0;
10684
10795
  } catch {
10685
10796
  return void 0;
10686
10797
  }
@@ -10708,7 +10819,7 @@ var fileEvidence = (root, path, options) => {
10708
10819
  return {
10709
10820
  exists: true,
10710
10821
  content: "",
10711
- evidence: { path: toPosix(relative9(resolve15(root), abs)) || ".", detail: "File exists and is non-empty." }
10822
+ evidence: { path: toPosix(relative10(resolve16(root), abs)) || ".", detail: "File exists and is non-empty." }
10712
10823
  };
10713
10824
  }
10714
10825
  if (stat.size > MAX_TEXT_EVIDENCE_BYTES) {
@@ -10718,12 +10829,12 @@ var fileEvidence = (root, path, options) => {
10718
10829
  evidence: { path, detail: `Text evidence exceeds ${MAX_TEXT_EVIDENCE_BYTES} bytes.` }
10719
10830
  };
10720
10831
  }
10721
- const content = readFileSync16(fd, "utf8");
10832
+ const content = readFileSync17(fd, "utf8");
10722
10833
  return {
10723
10834
  exists: content.trim().length > 0,
10724
10835
  content,
10725
10836
  evidence: {
10726
- path: toPosix(relative9(resolve15(root), abs)) || ".",
10837
+ path: toPosix(relative10(resolve16(root), abs)) || ".",
10727
10838
  detail: content.trim().length > 0 ? "File exists and is non-empty." : "File is empty."
10728
10839
  }
10729
10840
  };
@@ -10765,7 +10876,7 @@ var humanDocsRule = (root, config) => {
10765
10876
  passed: docs.length > 0,
10766
10877
  message: docs.length > 0 ? `Found ${docs.length} human document(s).` : "No human documentation was discovered.",
10767
10878
  evidence: docs.slice(0, 10).map((doc) => ({
10768
- path: toPosix(relative9(resolve15(root), doc.path)),
10879
+ path: toPosix(relative10(resolve16(root), doc.path)),
10769
10880
  detail: `Human route: ${doc.url}`
10770
10881
  })),
10771
10882
  remediation: {
@@ -10776,10 +10887,10 @@ var humanDocsRule = (root, config) => {
10776
10887
  };
10777
10888
  var llmsRule = (root, config, options, generated) => {
10778
10889
  const llmsPath = config.index?.llmsTxt?.outFile ?? "llms.txt";
10779
- const llmsKey = safePath(root, llmsPath) ?? resolve15(root, llmsPath);
10890
+ const llmsKey = safePath(root, llmsPath) ?? resolve16(root, llmsPath);
10780
10891
  const rawSources = /* @__PURE__ */ new Map();
10781
10892
  for (const path of options.rawSources ?? []) {
10782
- const key = safePath(root, path) ?? resolve15(root, path);
10893
+ const key = safePath(root, path) ?? resolve16(root, path);
10783
10894
  if (key !== llmsKey && !rawSources.has(key)) rawSources.set(key, path);
10784
10895
  }
10785
10896
  const paths = [llmsPath, ...rawSources.values()];
@@ -10918,11 +11029,11 @@ var linksRule = (root, options) => {
10918
11029
  for (const link of links) {
10919
11030
  const sources = link.paths.map((path) => ({ path, file: fileEvidence(root, path) }));
10920
11031
  const matches2 = sources.filter(({ file }) => file.exists && file.content.includes(link.url));
10921
- const canonical = contract.urls.has(normalizedUrl(link.url));
10922
- if (matches2.length === 0 || !canonical) passed = false;
11032
+ const canonical2 = contract.urls.has(normalizedUrl(link.url));
11033
+ if (matches2.length === 0 || !canonical2) passed = false;
10923
11034
  evidence2.push({
10924
11035
  path: sources.map((source) => source.path).join(", "),
10925
- detail: matches2.length === 0 ? `Missing ${link.url}` : canonical ? `Found canonical ecosystem URL ${link.url}` : `Found ${link.url}, but it is absent from the canonical ecosystem manifest.`
11036
+ detail: matches2.length === 0 ? `Missing ${link.url}` : canonical2 ? `Found canonical ecosystem URL ${link.url}` : `Found ${link.url}, but it is absent from the canonical ecosystem manifest.`
10926
11037
  });
10927
11038
  }
10928
11039
  return {
@@ -11030,8 +11141,8 @@ var formatDocumentationStandardText = (report) => [
11030
11141
  ];
11031
11142
 
11032
11143
  // src/query/load-index.ts
11033
- import { existsSync as existsSync15, readFileSync as readFileSync17 } from "fs";
11034
- import { join as join14, resolve as resolve16 } from "path";
11144
+ import { existsSync as existsSync16, readFileSync as readFileSync18 } from "fs";
11145
+ import { join as join15, resolve as resolve17 } from "path";
11035
11146
  var IndexNotFoundError = class extends Error {
11036
11147
  constructor(path) {
11037
11148
  super(`Missing index at ${path}. Run: ak-docs index`);
@@ -11052,11 +11163,11 @@ var IndexStaleError = class extends Error {
11052
11163
  actual;
11053
11164
  expected;
11054
11165
  };
11055
- var indexFilePath = (root, config) => join14(root, config.index?.outFile ?? ".doc-bridge/index.json");
11166
+ var indexFilePath = (root, config) => join15(root, config.index?.outFile ?? ".doc-bridge/index.json");
11056
11167
  var loadDocBridgeIndex = (root, config) => {
11057
11168
  const path = indexFilePath(root, config);
11058
- if (!existsSync15(path)) throw new IndexNotFoundError(path);
11059
- const raw = JSON.parse(readFileSync17(path, "utf8"));
11169
+ if (!existsSync16(path)) throw new IndexNotFoundError(path);
11170
+ const raw = JSON.parse(readFileSync18(path, "utf8"));
11060
11171
  return parseDocBridgeIndex(raw);
11061
11172
  };
11062
11173
  var loadFreshDocBridgeIndex = (root, config) => {
@@ -11074,7 +11185,7 @@ var loadFreshDocBridgeIndex = (root, config) => {
11074
11185
  }
11075
11186
  return index;
11076
11187
  };
11077
- var resolveRoot = (cwd) => resolve16(cwd ?? process.cwd());
11188
+ var resolveRoot = (cwd) => resolve17(cwd ?? process.cwd());
11078
11189
 
11079
11190
  // src/gates/run-gates.ts
11080
11191
  var RESERVED_GATE_IDS = /* @__PURE__ */ new Set(["link-rot", "routing-currency", "bootstrap-size"]);
@@ -11120,7 +11231,7 @@ var runGate = (root, config, id) => {
11120
11231
  return {
11121
11232
  id,
11122
11233
  ok: false,
11123
- message: `${result.ignored.length} indexed path(s) are ignored by Git, so a clean checkout builds a different index. Add them to safety.exclude.`,
11234
+ message: `${result.ignored.length} indexed path(s) are ignored by Git, so a clean checkout builds a different index. Rebuild the index (scans skip ignored paths) or add them to safety.exclude.`,
11124
11235
  expected: "every indexed path is committed",
11125
11236
  actual: sample.join(", ")
11126
11237
  };
@@ -11179,7 +11290,7 @@ var runOkfTypeGate = (root, config) => {
11179
11290
  const required = config.corpus.agent.okf?.requireType ?? config.gates?.preset === "strict";
11180
11291
  if (!required) return { id: "okf-type", ok: true, message: "OKF type frontmatter not required" };
11181
11292
  const allowed = config.corpus.agent.okf?.allowedTypes;
11182
- const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync18(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
11293
+ const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync19(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
11183
11294
  if (bad.length) {
11184
11295
  return {
11185
11296
  id: "okf-type",
@@ -11253,7 +11364,7 @@ var runDocsStyleGate = (root, config) => {
11253
11364
  }
11254
11365
  const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({
11255
11366
  path: doc.path,
11256
- missing: missingStyleRules(readFileSync18(doc.absPath, "utf8"), required)
11367
+ missing: missingStyleRules(readFileSync19(doc.absPath, "utf8"), required)
11257
11368
  })).filter((doc) => doc.missing.length > 0);
11258
11369
  if (bad.length) {
11259
11370
  return {
@@ -11298,8 +11409,8 @@ var resolveGateIds = (config) => {
11298
11409
  };
11299
11410
 
11300
11411
  // src/mcp/server.ts
11301
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync21, realpathSync as realpathSync9, writeFileSync as writeFileSync7 } from "fs";
11302
- import { join as join17, relative as relative10, resolve as resolve18 } from "path";
11412
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync22, realpathSync as realpathSync10, writeFileSync as writeFileSync7 } from "fs";
11413
+ import { join as join18, relative as relative11, resolve as resolve19 } from "path";
11303
11414
  import { z as z16, ZodError } from "zod";
11304
11415
 
11305
11416
  // src/query/search.ts
@@ -11570,15 +11681,15 @@ ${document.source ? `Source: ${document.source}
11570
11681
  ` : ""}${document.content}`).join("\n\n");
11571
11682
 
11572
11683
  // src/memory/ingest.ts
11573
- import { existsSync as existsSync16, readFileSync as readFileSync19 } from "fs";
11574
- import { join as join15 } from "path";
11684
+ import { existsSync as existsSync17, readFileSync as readFileSync20 } from "fs";
11685
+ import { join as join16 } from "path";
11575
11686
  var memoryFact = (raw, id) => firstParagraph(raw) ?? firstHeading(raw) ?? id;
11576
11687
  var relativePath2 = (root, abs) => toPosix(abs).replace(`${toPosix(root)}/`, "");
11577
11688
  var ingestMarkdownDir = (root, dir, source, confidence) => {
11578
- if (!existsSync16(dir)) return [];
11579
- return walkFiles(dir, { extensions: [".md", ".mdc"] }).map((abs) => {
11689
+ if (!existsSync17(dir)) return [];
11690
+ return walkFiles(dir, { extensions: [".md", ".mdc"], respectIgnore: false }).map((abs) => {
11580
11691
  const rel = relativePath2(root, abs);
11581
- const raw = readFileSync19(abs, "utf8");
11692
+ const raw = readFileSync20(abs, "utf8");
11582
11693
  const id = slugFromPath(rel);
11583
11694
  return {
11584
11695
  schemaVersion: 1,
@@ -11593,10 +11704,10 @@ var ingestMarkdownDir = (root, dir, source, confidence) => {
11593
11704
  });
11594
11705
  };
11595
11706
  var ingestCursorRules = (root) => {
11596
- const dir = join15(root, ".cursor", "rules");
11707
+ const dir = join16(root, ".cursor", "rules");
11597
11708
  return ingestMarkdownDir(root, dir, "cursor", 0.6);
11598
11709
  };
11599
- var ingestAgentMemory = (root) => ingestMarkdownDir(root, join15(root, ".agent-memory"), "agent-memory", 0.7);
11710
+ var ingestAgentMemory = (root) => ingestMarkdownDir(root, join16(root, ".agent-memory"), "agent-memory", 0.7);
11600
11711
  var ingestMemoryCandidates = (root) => [
11601
11712
  ...ingestAgentMemory(root),
11602
11713
  ...ingestCursorRules(root)
@@ -12234,8 +12345,8 @@ var formatKnowledgeLookupText = (response) => {
12234
12345
  };
12235
12346
 
12236
12347
  // src/enrich/approvals.ts
12237
- import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync20, readdirSync as readdirSync5, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "fs";
12238
- import { join as join16, resolve as resolve17 } from "path";
12348
+ import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync21, readdirSync as readdirSync5, renameSync as renameSync4, writeFileSync as writeFileSync6 } from "fs";
12349
+ import { join as join17, resolve as resolve18 } from "path";
12239
12350
 
12240
12351
  // src/intelligence/peers.ts
12241
12352
  var PeerMissingError = class extends Error {
@@ -12287,7 +12398,7 @@ var layer1InstallHint = () => LAYER1_INSTALL;
12287
12398
  var APPROVALS_DIR = ".doc-bridge/approvals";
12288
12399
  var ENRICHMENT_APPROVAL_GATE = "doc-bridge.enrichment";
12289
12400
  var FIX_APPROVAL_GATE = "doc-bridge.fix";
12290
- var approvalsDir = (root) => join16(resolve17(root), APPROVALS_DIR);
12401
+ var approvalsDir = (root) => join17(resolve18(root), APPROVALS_DIR);
12291
12402
  var safeId = (id) => {
12292
12403
  if (!/^[a-f0-9]{16,64}$/.test(id)) throw new Error(`Approval ids are content hashes; received "${id}".`);
12293
12404
  return id;
@@ -12295,7 +12406,7 @@ var safeId = (id) => {
12295
12406
  var enrichmentApprovalId = (proposalId, targetContentHash) => sha256NormalizedV1({ proposalId, targetContentHash });
12296
12407
  var fixApprovalId = (proposalId, proposalHash) => sha256NormalizedV1({ proposalId, proposalHash });
12297
12408
  var createFileApprovalStore = (dir) => {
12298
- const pathFor = (id) => join16(dir, `${safeId(id)}.json`);
12409
+ const pathFor = (id) => join17(dir, `${safeId(id)}.json`);
12299
12410
  const write = (approval) => {
12300
12411
  mkdirSync5(dir, { recursive: true });
12301
12412
  const path = pathFor(approval.id);
@@ -12306,9 +12417,9 @@ var createFileApprovalStore = (dir) => {
12306
12417
  };
12307
12418
  const read = (id) => {
12308
12419
  const path = pathFor(id);
12309
- if (!existsSync17(path)) return null;
12420
+ if (!existsSync18(path)) return null;
12310
12421
  try {
12311
- return JSON.parse(readFileSync20(path, "utf8"));
12422
+ return JSON.parse(readFileSync21(path, "utf8"));
12312
12423
  } catch {
12313
12424
  return null;
12314
12425
  }
@@ -12330,10 +12441,10 @@ var createFileApprovalStore = (dir) => {
12330
12441
  };
12331
12442
  };
12332
12443
  var listApprovals = (dir) => {
12333
- if (!existsSync17(dir)) return [];
12444
+ if (!existsSync18(dir)) return [];
12334
12445
  return readdirSync5(dir).filter((name) => /^[a-f0-9]{16,64}\.json$/.test(name)).sort().flatMap((name) => {
12335
12446
  try {
12336
- return [JSON.parse(readFileSync20(join16(dir, name), "utf8"))];
12447
+ return [JSON.parse(readFileSync21(join17(dir, name), "utf8"))];
12337
12448
  } catch {
12338
12449
  return [];
12339
12450
  }
@@ -12664,16 +12775,16 @@ var findDocPath = (index, args) => {
12664
12775
  return doc.path;
12665
12776
  };
12666
12777
  var resolveDocPath = (root, relPath) => {
12667
- const rootAbs = realpathSync9.native(root);
12668
- const unresolved = resolve18(rootAbs, relPath);
12669
- const unresolvedRel = relative10(rootAbs, unresolved);
12778
+ const rootAbs = realpathSync10.native(root);
12779
+ const unresolved = resolve19(rootAbs, relPath);
12780
+ const unresolvedRel = relative11(rootAbs, unresolved);
12670
12781
  if (unresolvedRel.startsWith("..")) throw new Error("doc.get path escapes project root");
12671
- const abs = realpathSync9.native(unresolved);
12672
- const rel = relative10(rootAbs, abs);
12782
+ const abs = realpathSync10.native(unresolved);
12783
+ const rel = relative11(rootAbs, abs);
12673
12784
  if (rel.startsWith("..")) throw new Error("doc.get path escapes project root");
12674
12785
  return abs;
12675
12786
  };
12676
- var workflowStateDir = (ctx) => resolve18(ctx.root, ctx.config.workflow?.stateDir ?? ".doc-bridge/workflow");
12787
+ var workflowStateDir = (ctx) => resolve19(ctx.root, ctx.config.workflow?.stateDir ?? ".doc-bridge/workflow");
12677
12788
  var workflowRun = (ctx) => loadWorkflowManifest(workflowStateDir(ctx));
12678
12789
  var ensureLatestRun = (ctx, runId2) => {
12679
12790
  const run2 = workflowRun(ctx);
@@ -12689,17 +12800,17 @@ var workflowReport = (ctx, runId2) => {
12689
12800
  ensureLatestRun(ctx, runId2);
12690
12801
  return parseReconciliationReport(loadWorkflowStepOutput(workflowStateDir(ctx), "reconcile"));
12691
12802
  };
12692
- var proposalPath = (ctx) => join17(ctx.root, ".doc-bridge", "proposal.json");
12803
+ var proposalPath = (ctx) => join18(ctx.root, ".doc-bridge", "proposal.json");
12693
12804
  var readSavedProposal = (ctx, input) => {
12694
12805
  if (input !== void 0) return FixProposalV1Schema.parse(input);
12695
12806
  try {
12696
- return FixProposalV1Schema.parse(JSON.parse(readFileSync21(proposalPath(ctx), "utf8")));
12807
+ return FixProposalV1Schema.parse(JSON.parse(readFileSync22(proposalPath(ctx), "utf8")));
12697
12808
  } catch {
12698
12809
  throw new Error(`No saved fix proposal at ${proposalPath(ctx)}.`);
12699
12810
  }
12700
12811
  };
12701
12812
  var saveProposal = (ctx, proposal) => {
12702
- mkdirSync6(join17(ctx.root, ".doc-bridge"), { recursive: true });
12813
+ mkdirSync6(join18(ctx.root, ".doc-bridge"), { recursive: true });
12703
12814
  writeFileSync7(proposalPath(ctx), `${JSON.stringify(proposal, null, 2)}
12704
12815
  `, "utf8");
12705
12816
  };
@@ -12762,7 +12873,7 @@ var handleMcpRequest = (ctx, request) => {
12762
12873
  }
12763
12874
  if (name === "doc.get") {
12764
12875
  const relPath = findDocPath(index(), parseToolArgs("doc.get", DocGetArgsSchema, args));
12765
- return textResult(readFileSync21(resolveDocPath(ctx.root, relPath), "utf8"));
12876
+ return textResult(readFileSync22(resolveDocPath(ctx.root, relPath), "utf8"));
12766
12877
  }
12767
12878
  if (name === "gate.status") return textResult(runGates(ctx.root, ctx.config));
12768
12879
  if (name === "retriever.query") {
@@ -12951,9 +13062,9 @@ var startMcpStdioServer = (ctx) => {
12951
13062
  };
12952
13063
 
12953
13064
  // src/mcp/install.ts
12954
- import { existsSync as existsSync18, mkdirSync as mkdirSync7, readFileSync as readFileSync22, writeFileSync as writeFileSync8 } from "fs";
13065
+ import { existsSync as existsSync19, mkdirSync as mkdirSync7, readFileSync as readFileSync23, writeFileSync as writeFileSync8 } from "fs";
12955
13066
  import { homedir } from "os";
12956
- import { dirname as dirname7, join as join18, resolve as resolve19 } from "path";
13067
+ import { dirname as dirname8, join as join19, resolve as resolve20 } from "path";
12957
13068
  var SERVER_NAME = "ak-docs";
12958
13069
  var mcpServerEntry = (root) => ({
12959
13070
  command: "npx",
@@ -12961,26 +13072,26 @@ var mcpServerEntry = (root) => ({
12961
13072
  cwd: root
12962
13073
  });
12963
13074
  var readJson2 = (path) => {
12964
- if (!existsSync18(path)) return {};
13075
+ if (!existsSync19(path)) return {};
12965
13076
  try {
12966
- const parsed = JSON.parse(readFileSync22(path, "utf8"));
13077
+ const parsed = JSON.parse(readFileSync23(path, "utf8"));
12967
13078
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
12968
13079
  } catch {
12969
13080
  return {};
12970
13081
  }
12971
13082
  };
12972
13083
  var writeJson = (path, value) => {
12973
- mkdirSync7(dirname7(path), { recursive: true });
13084
+ mkdirSync7(dirname8(path), { recursive: true });
12974
13085
  writeFileSync8(path, `${JSON.stringify(value, null, 2)}
12975
13086
  `, "utf8");
12976
13087
  };
12977
13088
  var resolveTargetPath = (target2, root) => {
12978
- if (target2 === "cursor") return resolve19(root, ".cursor", "mcp.json");
12979
- return join18(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
13089
+ if (target2 === "cursor") return resolve20(root, ".cursor", "mcp.json");
13090
+ return join19(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
12980
13091
  };
12981
13092
  var installMcpConfig = (root, target2) => {
12982
13093
  const configPath = resolveTargetPath(target2, root);
12983
- const created = !existsSync18(configPath);
13094
+ const created = !existsSync19(configPath);
12984
13095
  const existing = readJson2(configPath);
12985
13096
  const servers = existing.mcpServers && typeof existing.mcpServers === "object" && !Array.isArray(existing.mcpServers) ? { ...existing.mcpServers } : {};
12986
13097
  servers[SERVER_NAME] = mcpServerEntry(root);
@@ -13005,8 +13116,8 @@ var installMcpConfig = (root, target2) => {
13005
13116
  var mcpSnippet = (root) => JSON.stringify({ mcpServers: { [SERVER_NAME]: mcpServerEntry(root) } }, null, 2);
13006
13117
 
13007
13118
  // src/doctor/run-doctor.ts
13008
- import { existsSync as existsSync19, readFileSync as readFileSync23 } from "fs";
13009
- import { resolve as resolve20 } from "path";
13119
+ import { existsSync as existsSync20, readFileSync as readFileSync24 } from "fs";
13120
+ import { resolve as resolve21 } from "path";
13010
13121
 
13011
13122
  // src/bench/retrieval.ts
13012
13123
  import { z as z17 } from "zod";
@@ -13333,11 +13444,11 @@ var measureConnectivity = (index) => {
13333
13444
  };
13334
13445
  var measureBenchmark = (root, config, index) => {
13335
13446
  const suite = config.retrieval?.benchmark?.suite ?? DEFAULT_RETRIEVAL_SUITE;
13336
- const suitePath = resolve20(root, suite);
13337
- if (!existsSync19(suitePath)) return { status: "not-analyzed", suite, reason: `No retrieval suite at ${suite}` };
13447
+ const suitePath = resolve21(root, suite);
13448
+ if (!existsSync20(suitePath)) return { status: "not-analyzed", suite, reason: `No retrieval suite at ${suite}` };
13338
13449
  if (!index.projection) return { status: "not-analyzed", suite, reason: "The index carries no retrieval projection. Run: ak-docs index" };
13339
13450
  try {
13340
- const parsed = parseRetrievalSuite(JSON.parse(readFileSync23(suitePath, "utf8")));
13451
+ const parsed = parseRetrievalSuite(JSON.parse(readFileSync24(suitePath, "utf8")));
13341
13452
  const result = runRetrievalBench({ index, suite: parsed });
13342
13453
  return {
13343
13454
  status: "measured",
@@ -13585,23 +13696,23 @@ var formatDoctorText = (report) => {
13585
13696
  };
13586
13697
 
13587
13698
  // src/index-builder/watch-index.ts
13588
- import { existsSync as existsSync20, watch } from "fs";
13589
- import { dirname as dirname8, resolve as resolve21 } from "path";
13699
+ import { existsSync as existsSync21, watch } from "fs";
13700
+ import { dirname as dirname9, resolve as resolve22 } from "path";
13590
13701
  var WATCH_PATTERN = /\.(md|mdx|json|ya?ml|mdc)$/i;
13591
13702
  var NX_MANIFEST_PATTERN = /(^|[/\\])(project|package)\.json$/i;
13592
13703
  var collectWatchRoots = (root, config, configPath) => {
13593
13704
  const roots = /* @__PURE__ */ new Set();
13594
- roots.add(resolve21(root, config.corpus.agent.root));
13705
+ roots.add(resolve22(root, config.corpus.agent.root));
13595
13706
  const humanSources = config.corpus.human ? Array.isArray(config.corpus.human) ? config.corpus.human : [config.corpus.human] : [];
13596
13707
  for (const source of humanSources) {
13597
13708
  const humanOpts = source.options ?? {};
13598
13709
  for (const key of ["contentDir", "docsDir", "root", "srcDir"]) {
13599
13710
  const value = humanOpts[key];
13600
- if (typeof value === "string" && value.length) roots.add(resolve21(root, value));
13711
+ if (typeof value === "string" && value.length) roots.add(resolve22(root, value));
13601
13712
  }
13602
13713
  }
13603
- if (configPath) roots.add(dirname8(resolve21(configPath)));
13604
- return [...roots].filter((dir) => existsSync20(dir));
13714
+ if (configPath) roots.add(dirname9(resolve22(configPath)));
13715
+ return [...roots].filter((dir) => existsSync21(dir));
13605
13716
  };
13606
13717
  var watchDocBridgeIndex = (opts) => {
13607
13718
  const debounceMs = opts.debounceMs ?? 350;
@@ -13642,15 +13753,15 @@ var watchDocBridgeIndex = (opts) => {
13642
13753
  rebuild();
13643
13754
  });
13644
13755
  }
13645
- const nxRoot = resolve21(opts.root);
13646
- if (opts.config.routing?.plugin === "nx" && existsSync20(nxRoot)) {
13756
+ const nxRoot = resolve22(opts.root);
13757
+ if (opts.config.routing?.plugin === "nx" && existsSync21(nxRoot)) {
13647
13758
  watch(nxRoot, { recursive: true }, (_event, filename) => {
13648
13759
  if (!filename || !NX_MANIFEST_PATTERN.test(filename)) return;
13649
13760
  rebuild();
13650
13761
  });
13651
13762
  }
13652
- const configDir = resolve21(opts.root);
13653
- if (existsSync20(configDir)) {
13763
+ const configDir = resolve22(opts.root);
13764
+ if (existsSync21(configDir)) {
13654
13765
  watch(configDir, (_event, filename) => {
13655
13766
  if (!filename || !/doc-bridge\.config/.test(filename)) return;
13656
13767
  rebuild();
@@ -13717,9 +13828,9 @@ var evaluateQualityScorecard = (input) => {
13717
13828
  };
13718
13829
 
13719
13830
  // src/memory/github-pr.ts
13720
- import { execFileSync as execFileSync3, spawnSync } from "child_process";
13721
- import { existsSync as existsSync21, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9 } from "fs";
13722
- import { join as join19 } from "path";
13831
+ import { execFileSync as execFileSync4, spawnSync } from "child_process";
13832
+ import { existsSync as existsSync22, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9 } from "fs";
13833
+ import { join as join20 } from "path";
13723
13834
  var run = (cmd, args, cwd) => {
13724
13835
  const result = spawnSync(cmd, [...args], { cwd, encoding: "utf8" });
13725
13836
  const out = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
@@ -13727,10 +13838,10 @@ var run = (cmd, args, cwd) => {
13727
13838
  };
13728
13839
  var hasGh = () => run("gh", ["--version"], process.cwd()).ok;
13729
13840
  var slug = () => (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
13730
- var defaultPromotionDraftPath = (root) => join19(root, ".doc-bridge", "drafts", `memory-promotion-${slug()}.md`);
13841
+ var defaultPromotionDraftPath = (root) => join20(root, ".doc-bridge", "drafts", `memory-promotion-${slug()}.md`);
13731
13842
  var writePromotionDraft = (root, draft, path) => {
13732
13843
  const draftPath = path ?? defaultPromotionDraftPath(root);
13733
- mkdirSync8(join19(root, ".doc-bridge", "drafts"), { recursive: true });
13844
+ mkdirSync8(join20(root, ".doc-bridge", "drafts"), { recursive: true });
13734
13845
  writeFileSync9(draftPath, `${draft.body}
13735
13846
  `, "utf8");
13736
13847
  return draftPath;
@@ -13766,7 +13877,7 @@ var promoteMemoryToGithubPr = (root, draft, options = {}) => {
13766
13877
  message: `Wrote draft to ${relDraft}. Run the printed git/gh commands to open a draft PR.`
13767
13878
  };
13768
13879
  }
13769
- if (!existsSync21(join19(root, ".git"))) {
13880
+ if (!existsSync22(join20(root, ".git"))) {
13770
13881
  return {
13771
13882
  ok: false,
13772
13883
  dryRun: false,
@@ -13844,7 +13955,7 @@ ${auth.out}`
13844
13955
  ];
13845
13956
  let prUrl = "";
13846
13957
  try {
13847
- prUrl = execFileSync3("gh", prArgs, { cwd: root, encoding: "utf8" }).trim();
13958
+ prUrl = execFileSync4("gh", prArgs, { cwd: root, encoding: "utf8" }).trim();
13848
13959
  } catch (error) {
13849
13960
  const message = error instanceof Error ? error.message : String(error);
13850
13961
  return {
@@ -14634,12 +14745,12 @@ var formatStudyTaskSuiteText = (suite) => [
14634
14745
  import { spawn as spawn2 } from "child_process";
14635
14746
  import { createHash as createHash3 } from "crypto";
14636
14747
  import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
14637
- import { dirname as dirname9, resolve as resolve23 } from "path";
14748
+ import { dirname as dirname10, resolve as resolve24 } from "path";
14638
14749
  import { z as z24 } from "zod";
14639
14750
 
14640
14751
  // src/study/provider-cli.ts
14641
- import { accessSync, constants, existsSync as existsSync22, statSync as statSync3 } from "fs";
14642
- import { isAbsolute as isAbsolute6, resolve as resolve22 } from "path";
14752
+ import { accessSync, constants, existsSync as existsSync23, statSync as statSync3 } from "fs";
14753
+ import { isAbsolute as isAbsolute7, resolve as resolve23 } from "path";
14643
14754
  import { z as z23 } from "zod";
14644
14755
  var STUDY_PROVIDER_CLI_SCHEMA_VERSION = 1;
14645
14756
  var STUDY_PROVIDER_CLI_CONTENT_HASH_ALGO = "sha256-normalized-v1";
@@ -14714,9 +14825,9 @@ var calculateStudyCostUsd = (pricing2, usage) => {
14714
14825
  return Number(((uncachedInputTokens * pricing2.inputPerMillionUsd + cachedInputTokens * pricing2.cachedInputPerMillionUsd + usage.outputTokens * pricing2.outputPerMillionUsd) / 1e6).toFixed(8));
14715
14826
  };
14716
14827
  var validateStudyProviderCommand = (provider, cwd) => {
14717
- if (isAbsolute6(provider.command) || provider.command.includes("/")) {
14718
- const resolvedPath = isAbsolute6(provider.command) ? provider.command : resolve22(cwd, provider.command);
14719
- if (!existsSync22(resolvedPath) || !statSync3(resolvedPath).isFile()) throw new Error(`Provider CLI command is not executable at ${resolvedPath}.`);
14828
+ if (isAbsolute7(provider.command) || provider.command.includes("/")) {
14829
+ const resolvedPath = isAbsolute7(provider.command) ? provider.command : resolve23(cwd, provider.command);
14830
+ if (!existsSync23(resolvedPath) || !statSync3(resolvedPath).isFile()) throw new Error(`Provider CLI command is not executable at ${resolvedPath}.`);
14720
14831
  try {
14721
14832
  accessSync(resolvedPath, constants.X_OK);
14722
14833
  } catch {
@@ -14727,7 +14838,7 @@ var validateStudyProviderCommand = (provider, cwd) => {
14727
14838
  const pathEntries = (process.env.PATH ?? "").split(":").filter(Boolean);
14728
14839
  if (pathEntries.some((entry) => {
14729
14840
  try {
14730
- accessSync(resolve22(entry, provider.command), constants.X_OK);
14841
+ accessSync(resolve23(entry, provider.command), constants.X_OK);
14731
14842
  return true;
14732
14843
  } catch {
14733
14844
  return false;
@@ -14994,7 +15105,7 @@ var runAttempt = (request, sessionId) => new Promise((resolveAttempt) => {
14994
15105
  const maxRuntimeMs = request.maxRuntimeMs ?? request.plan.budget.maxRuntimeMs;
14995
15106
  const maxOutputBytes = request.maxOutputBytes ?? request.plan.budget.maxOutputBytes;
14996
15107
  const child = spawn2(request.command, [...request.args ?? []], {
14997
- cwd: resolve23(request.cwd),
15108
+ cwd: resolve24(request.cwd),
14998
15109
  shell: false,
14999
15110
  detached: true,
15000
15111
  env: { ...env, DOC_BRIDGE_STUDY_SESSION_ID: sessionId },
@@ -15122,10 +15233,10 @@ var runControlledCommand = async (request) => {
15122
15233
  };
15123
15234
  var persistControlledStudyLedger = (path, ledger) => {
15124
15235
  parseControlledStudyLedger(ledger);
15125
- mkdirSync9(dirname9(resolve23(path)), { recursive: true });
15126
- writeFileSync10(resolve23(path), `${JSON.stringify(ledger, null, 2)}
15236
+ mkdirSync9(dirname10(resolve24(path)), { recursive: true });
15237
+ writeFileSync10(resolve24(path), `${JSON.stringify(ledger, null, 2)}
15127
15238
  `, "utf8");
15128
- return resolve23(path);
15239
+ return resolve24(path);
15129
15240
  };
15130
15241
  var formatControlledStudyRunPlanText = (plan) => [
15131
15242
  `Run plan: ${plan.planVersion}`,
@@ -15141,7 +15252,7 @@ var formatControlledStudyRunPlanText = (plan) => [
15141
15252
  import { spawn as spawn3 } from "child_process";
15142
15253
  import { createHash as createHash4 } from "crypto";
15143
15254
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
15144
- import { dirname as dirname10, resolve as resolve24 } from "path";
15255
+ import { dirname as dirname11, resolve as resolve25 } from "path";
15145
15256
  import { z as z25 } from "zod";
15146
15257
  var STUDY_ADJUDICATION_METHOD = "independent-rubric-v1";
15147
15258
  var outcome2 = z25.enum(["success", "partial", "incorrect", "incomplete", "blocked"]);
@@ -15168,7 +15279,7 @@ var terminate = (child) => {
15168
15279
  var runAdjudicatorProcess = (config, cwd, input, maxRuntimeMs) => new Promise((resolveResult) => {
15169
15280
  const env = Object.fromEntries([.../* @__PURE__ */ new Set(["PATH", "HOME", "TMPDIR", ...config.envAllowlist])].flatMap((name) => process.env[name] === void 0 ? [] : [[name, process.env[name]]]));
15170
15281
  const started = Date.now();
15171
- const child = spawn3(config.command, [...config.args], { cwd: resolve24(cwd), shell: false, detached: true, env, stdio: ["pipe", "pipe", "pipe"] });
15282
+ const child = spawn3(config.command, [...config.args], { cwd: resolve25(cwd), shell: false, detached: true, env, stdio: ["pipe", "pipe", "pipe"] });
15172
15283
  let stdout = "";
15173
15284
  let stderrBytes = 0;
15174
15285
  let settled = false;
@@ -15306,10 +15417,10 @@ var independentlyAdjudicateStudyLedger = async (options) => {
15306
15417
  };
15307
15418
  var persistIndependentlyAdjudicatedLedger = (path, ledger) => {
15308
15419
  parseControlledStudyLedger(ledger);
15309
- mkdirSync10(dirname10(resolve24(path)), { recursive: true });
15310
- writeFileSync11(resolve24(path), `${JSON.stringify(ledger, null, 2)}
15420
+ mkdirSync10(dirname11(resolve25(path)), { recursive: true });
15421
+ writeFileSync11(resolve25(path), `${JSON.stringify(ledger, null, 2)}
15311
15422
  `, "utf8");
15312
- return resolve24(path);
15423
+ return resolve25(path);
15313
15424
  };
15314
15425
  var adjudicatedLedgerInputHash = (task, observation) => createHash4("sha256").update(adjudicatorInput(task, observation)).digest("hex");
15315
15426
 
@@ -15351,8 +15462,8 @@ var measureProviderToolTelemetry = (events) => {
15351
15462
  };
15352
15463
 
15353
15464
  // src/study/execution.ts
15354
- import { existsSync as existsSync23, readFileSync as readFileSync24, statSync as statSync4 } from "fs";
15355
- import { resolve as resolve25 } from "path";
15465
+ import { existsSync as existsSync24, readFileSync as readFileSync25, statSync as statSync4 } from "fs";
15466
+ import { resolve as resolve26 } from "path";
15356
15467
  import { z as z26 } from "zod";
15357
15468
  var PROVIDER_RESPONSE_CONTRACT = "Return one JSON object matching the output schema. Required keys: taskOutcome, evidenceQuality, safetyOutcome, evidenceIds, clarificationRequests, reworkCount, and measurements. Each measurement is {name:string,value:number>=0}. Run every available acceptance check and report observed acceptanceChecksPassed, acceptanceChecksTotal, and acceptanceChecksExecuted; include firstEvidenceLatencyMs only when observed. Use canonical names when observed: tokensToFirstEvidence (tokens consumed before correct grounded evidence was in hand), registryAgentInputTokens, registryAgentOutputTokens, registryAgentCostUsd, registryAgentRuns (the enrichment agent of the assisted arm, reported apart from your own cost), searchHitRate, acceptanceChecksPassed, acceptanceChecksTotal, acceptanceChecksExecuted, entrypointEvidenceCount, ownershipEvidenceCount, architectureRelationCount, documentationClaimEvidenceCount, sourceComparisonEvidenceCount, verificationEvidenceCount, errorRate, documentationFindingCount, documentationExampleRate, documentationFreshnessRate, documentationCorrectnessRate, documentationCompletenessRate, documentationClarityRate, documentationMaintainabilityRate, timeToFirstEvidenceMs, analysisCostUsd, and agentCostUsd. Omit unknown values; never invent. Output no markdown, prose, logs, token counts, or extra keys; stdout must contain only the JSON object.";
15358
15469
  var STUDY_REPOSITORY_CONFIG_SCHEMA_VERSION = 1;
@@ -15391,8 +15502,8 @@ var emptyLedger2 = () => createControlledStudyLedger({
15391
15502
  observations: []
15392
15503
  });
15393
15504
  var loadLedger = (path) => {
15394
- if (!existsSync23(path)) return emptyLedger2();
15395
- return parseControlledStudyLedger(JSON.parse(readFileSync24(path, "utf8")));
15505
+ if (!existsSync24(path)) return emptyLedger2();
15506
+ return parseControlledStudyLedger(JSON.parse(readFileSync25(path, "utf8")));
15396
15507
  };
15397
15508
  var executionKey = (execution) => sha256NormalizedV1({
15398
15509
  taskId: execution.taskId,
@@ -15473,8 +15584,8 @@ var assertRunInputs = (options) => {
15473
15584
  throw new Error("Study repository config must contain exactly one root for every task-suite population id.");
15474
15585
  }
15475
15586
  for (const repository of options.repositories.repositories) {
15476
- const root = resolve25(repository.root);
15477
- if (!existsSync23(root) || !statSync4(root).isDirectory()) throw new Error(`Study repository ${repository.id} is not available at the configured root.`);
15587
+ const root = resolve26(repository.root);
15588
+ if (!existsSync24(root) || !statSync4(root).isDirectory()) throw new Error(`Study repository ${repository.id} is not available at the configured root.`);
15478
15589
  }
15479
15590
  const executions = selectTaskExecutions(options.suite, options.plan.sampling.sampleSize, options.plan.sampling);
15480
15591
  const assisted = assistedArmReadiness(options.plan, options.providers, options.suite);
@@ -15520,7 +15631,7 @@ var runControlledStudy = async (options) => {
15520
15631
  repositoryConfigHash: repositories.contentHash,
15521
15632
  assistedArm: { ...assisted, recorded: 0 }
15522
15633
  };
15523
- let ledger = loadLedger(resolve25(options.ledgerPath));
15634
+ let ledger = loadLedger(resolve26(options.ledgerPath));
15524
15635
  if (ledger.observations.some((observation) => observation.runId === plan.runId && observation.planHash !== plan.contentHash)) throw new Error(`Ledger already contains run ${plan.runId} with a different plan hash.`);
15525
15636
  let executed = 0;
15526
15637
  let skipped = 0;
@@ -15579,7 +15690,7 @@ var runControlledStudy = async (options) => {
15579
15690
  planned: executions.length,
15580
15691
  executed,
15581
15692
  skipped,
15582
- ledgerPath: resolve25(options.ledgerPath),
15693
+ ledgerPath: resolve26(options.ledgerPath),
15583
15694
  ledgerHash: ledger.contentHash,
15584
15695
  providerConfigHash: providers.contentHash,
15585
15696
  repositoryConfigHash: repositories.contentHash,
@@ -15600,8 +15711,8 @@ var formatControlledStudyRunText = (summary) => [
15600
15711
  ];
15601
15712
 
15602
15713
  // src/federation/llms.ts
15603
- import { existsSync as existsSync24, readFileSync as readFileSync25 } from "fs";
15604
- import { resolve as resolve26 } from "path";
15714
+ import { existsSync as existsSync25, readFileSync as readFileSync26 } from "fs";
15715
+ import { resolve as resolve27 } from "path";
15605
15716
  var scoreText = (query, text) => {
15606
15717
  const hay = text.toLowerCase();
15607
15718
  return tokenizeSearchText(query).reduce((score, token) => score + (hasSearchToken(hay, token) ? token.length : 0), 0);
@@ -15626,9 +15737,9 @@ var sourceText = async (root, source, fetchText) => {
15626
15737
  try {
15627
15738
  const remote = httpUrl(source);
15628
15739
  if (remote) return await fetchText(remote);
15629
- const path = resolve26(root, source);
15630
- if (!existsSync24(path)) return null;
15631
- return readFileSync25(path, "utf8");
15740
+ const path = resolve27(root, source);
15741
+ if (!existsSync25(path)) return null;
15742
+ return readFileSync26(path, "utf8");
15632
15743
  } catch {
15633
15744
  return null;
15634
15745
  }
@@ -15755,11 +15866,11 @@ var retrieveHybridChunks = async (root, config, index, query, options = {}) => {
15755
15866
  };
15756
15867
 
15757
15868
  // src/intelligence/rag.ts
15758
- import { readFileSync as readFileSync26 } from "fs";
15759
- import { join as join21 } from "path";
15869
+ import { readFileSync as readFileSync27 } from "fs";
15870
+ import { join as join22 } from "path";
15760
15871
 
15761
15872
  // src/intelligence/adapter.ts
15762
- import { join as join20 } from "path";
15873
+ import { join as join21 } from "path";
15763
15874
  var readEnv = (name) => {
15764
15875
  if (!name) return void 0;
15765
15876
  const value = process.env[name];
@@ -15838,7 +15949,7 @@ var resolveIntelligenceRuntime = async (config) => {
15838
15949
  }
15839
15950
  return { adapter, embed, provider, ...model ? { model } : {} };
15840
15951
  };
15841
- var defaultVectorStorePath = (root) => join20(root, ".doc-bridge", "vectors");
15952
+ var defaultVectorStorePath = (root) => join21(root, ".doc-bridge", "vectors");
15842
15953
 
15843
15954
  // src/intelligence/rag.ts
15844
15955
  var loadDocuments = (root, index, sources) => {
@@ -15846,10 +15957,10 @@ var loadDocuments = (root, index, sources) => {
15846
15957
  const docs = [];
15847
15958
  if (includeAgent) {
15848
15959
  for (const entry of index.knowledge) {
15849
- const abs = join21(root, entry.path);
15960
+ const abs = join22(root, entry.path);
15850
15961
  let content = "";
15851
15962
  try {
15852
- content = readFileSync26(abs, "utf8");
15963
+ content = readFileSync27(abs, "utf8");
15853
15964
  } catch {
15854
15965
  content = [entry.title, entry.description].filter(Boolean).join("\n\n");
15855
15966
  }
@@ -15867,7 +15978,7 @@ var createDocBridgeRag = async (root, config, index) => {
15867
15978
  const { embed } = await resolveIntelligenceRuntime(config);
15868
15979
  const ragMod = await importPeer("@agentskit/rag");
15869
15980
  const memoryMod = await importPeer("@agentskit/memory");
15870
- const storePath = typeof config.intelligence?.retriever?.options?.storePath === "string" ? join21(root, config.intelligence.retriever.options.storePath) : defaultVectorStorePath(root);
15981
+ const storePath = typeof config.intelligence?.retriever?.options?.storePath === "string" ? join22(root, config.intelligence.retriever.options.storePath) : defaultVectorStorePath(root);
15871
15982
  const store = memoryMod.fileVectorMemory({ path: storePath });
15872
15983
  const rag = ragMod.createRAG({
15873
15984
  embed,
@@ -16122,8 +16233,8 @@ var docBridgePatternPayload = () => ({
16122
16233
  });
16123
16234
 
16124
16235
  // src/render/render.ts
16125
- import { existsSync as existsSync25, mkdirSync as mkdirSync11, readFileSync as readFileSync27, writeFileSync as writeFileSync12 } from "fs";
16126
- import { dirname as dirname11, join as join22, relative as relative11, resolve as resolve27 } from "path";
16236
+ import { existsSync as existsSync26, mkdirSync as mkdirSync11, readFileSync as readFileSync28, writeFileSync as writeFileSync12 } from "fs";
16237
+ import { dirname as dirname12, join as join23, relative as relative12, resolve as resolve28 } from "path";
16127
16238
  var OPEN_PLACEHOLDER = "@@doc-bridge:generated-open@@";
16128
16239
  var CLOSE_PLACEHOLDER = "@@doc-bridge:generated-close@@";
16129
16240
  var REGION_VARIABLES = { open: OPEN_PLACEHOLDER, close: CLOSE_PLACEHOLDER };
@@ -16156,8 +16267,8 @@ var renderPage = (name, variables, config, root) => {
16156
16267
  const output = renderNamedTemplate(name, { ...variables, region: REGION_VARIABLES }, config, root);
16157
16268
  return RENDER_TEMPLATES[name].generatedRegion ? applyGeneratedRegions(output, name) : output;
16158
16269
  };
16159
- var readJson3 = (root, path) => JSON.parse(readFileSync27(resolve27(root, path), "utf8"));
16160
- var stateDirOf = (root, config) => resolve27(root, config.workflow?.stateDir ?? ".doc-bridge/workflow");
16270
+ var readJson3 = (root, path) => JSON.parse(readFileSync28(resolve28(root, path), "utf8"));
16271
+ var stateDirOf = (root, config) => resolve28(root, config.workflow?.stateDir ?? ".doc-bridge/workflow");
16161
16272
  var loadIndex = (options) => options.dataPath ? parseDocBridgeIndex(readJson3(options.root, options.dataPath)) : buildDocBridgeIndex({ root: options.root, config: options.config, write: false }).index;
16162
16273
  var loadReconciliation = (root, config) => {
16163
16274
  try {
@@ -16180,7 +16291,7 @@ var loadPreviousSnapshot = (options) => {
16180
16291
  };
16181
16292
  var DEFAULT_OVERLAY_PATH = ".doc-bridge/enrich/overlay.json";
16182
16293
  var loadOverlay = (options) => {
16183
- const path = options.dataPath ?? (existsSync25(resolve27(options.root, DEFAULT_OVERLAY_PATH)) ? DEFAULT_OVERLAY_PATH : void 0);
16294
+ const path = options.dataPath ?? (existsSync26(resolve28(options.root, DEFAULT_OVERLAY_PATH)) ? DEFAULT_OVERLAY_PATH : void 0);
16184
16295
  if (!path) return { overlay: void 0 };
16185
16296
  const value = readJson3(options.root, path);
16186
16297
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${path} is not an overlay object.`);
@@ -16231,28 +16342,28 @@ var writeRenderedPages = (result, target2, root) => {
16231
16342
  const single = result.pages.length === 1 && !RENDER_TEMPLATES[result.template].multiPage;
16232
16343
  const written = [];
16233
16344
  const write = (path, content) => {
16234
- mkdirSync11(dirname11(path), { recursive: true });
16345
+ mkdirSync11(dirname12(path), { recursive: true });
16235
16346
  writeFileSync12(path, content, "utf8");
16236
- return toPosix(relative11(root, path));
16347
+ return toPosix(relative12(root, path));
16237
16348
  };
16238
16349
  for (const page of result.pages) {
16239
16350
  if (!single) {
16240
- written.push(write(join22(target2, page.path), page.content));
16351
+ written.push(write(join23(target2, page.path), page.content));
16241
16352
  continue;
16242
16353
  }
16243
16354
  try {
16244
16355
  written.push(write(target2, page.content));
16245
16356
  } catch (error) {
16246
16357
  if (error.code !== "EISDIR") throw error;
16247
- written.push(write(join22(target2, page.path), page.content));
16358
+ written.push(write(join23(target2, page.path), page.content));
16248
16359
  }
16249
16360
  }
16250
16361
  return written;
16251
16362
  };
16252
16363
 
16253
16364
  // src/enrich/context-pack.ts
16254
- import { readFileSync as readFileSync28 } from "fs";
16255
- import { join as join23, resolve as resolve28 } from "path";
16365
+ import { readFileSync as readFileSync29 } from "fs";
16366
+ import { join as join24, resolve as resolve29 } from "path";
16256
16367
  var CONTEXT_PACK_VERSION = 1;
16257
16368
  var DEFAULT_PACK_BYTES = 64 * 1024;
16258
16369
  var MAX_PACK_NEIGHBOURS = 32;
@@ -16276,7 +16387,7 @@ var boundedMetadata = (metadata) => {
16276
16387
  var defaultReader = (root) => (path) => {
16277
16388
  if (!root) return void 0;
16278
16389
  try {
16279
- return readFileSync28(join23(resolve28(root), path), "utf8");
16390
+ return readFileSync29(join24(resolve29(root), path), "utf8");
16280
16391
  } catch {
16281
16392
  return void 0;
16282
16393
  }
@@ -16400,8 +16511,8 @@ var batchContextPacks = (packs) => {
16400
16511
  };
16401
16512
 
16402
16513
  // src/enrich/cache.ts
16403
- import { existsSync as existsSync26, mkdirSync as mkdirSync12, readFileSync as readFileSync29, renameSync as renameSync5, writeFileSync as writeFileSync13 } from "fs";
16404
- import { join as join24 } from "path";
16514
+ import { existsSync as existsSync27, mkdirSync as mkdirSync12, readFileSync as readFileSync30, renameSync as renameSync5, writeFileSync as writeFileSync13 } from "fs";
16515
+ import { join as join25 } from "path";
16405
16516
  import { z as z27 } from "zod";
16406
16517
  var enrichmentCacheKey = (input) => sha256NormalizedV1({ task: input.task, agentId: input.agentId, agentVersion: input.agentVersion, promptVersion: input.promptVersion, packHash: input.packHash });
16407
16518
  var CacheEntrySchema = z27.object({
@@ -16416,14 +16527,14 @@ var CacheEntrySchema = z27.object({
16416
16527
  }).strict();
16417
16528
  var createEnrichmentCache = (root) => {
16418
16529
  const dir = enrichmentCacheDir(root);
16419
- const pathFor = (key) => join24(dir, `${key}.json`);
16530
+ const pathFor = (key) => join25(dir, `${key}.json`);
16420
16531
  return {
16421
16532
  read: (input) => {
16422
16533
  const key = enrichmentCacheKey(input);
16423
16534
  const path = pathFor(key);
16424
- if (!existsSync26(path)) return void 0;
16535
+ if (!existsSync27(path)) return void 0;
16425
16536
  try {
16426
- const entry = CacheEntrySchema.parse(JSON.parse(readFileSync29(path, "utf8")));
16537
+ const entry = CacheEntrySchema.parse(JSON.parse(readFileSync30(path, "utf8")));
16427
16538
  return entry.key === key && entry.packHash === input.packHash && entry.agentId === input.agentId ? entry.proposals : void 0;
16428
16539
  } catch {
16429
16540
  return void 0;
@@ -16455,7 +16566,7 @@ var createMemoryEnrichmentCache = () => {
16455
16566
  };
16456
16567
 
16457
16568
  // src/enrich/stage.ts
16458
- import { basename as basename8, resolve as resolve29 } from "path";
16569
+ import { basename as basename8, resolve as resolve30 } from "path";
16459
16570
 
16460
16571
  // src/enrich/stats.ts
16461
16572
  var inventedReferenceCount = (rejected) => rejected.filter((entry) => INVENTED_RELATION_REASONS.includes(entry.reason)).length;
@@ -16552,7 +16663,7 @@ var registryAgent = async (root, config) => {
16552
16663
  };
16553
16664
  return {
16554
16665
  call: async ({ role, task, packs }) => (await adapterFor(role.agentId)).enrich(task, packs, { role: role.role, promptVersion: role.promptVersion }),
16555
- version: (role) => loadRegistryAgentMetadata(resolve29(root), configWithAgent(config, role.agentId)).version
16666
+ version: (role) => loadRegistryAgentMetadata(resolve30(root), configWithAgent(config, role.agentId)).version
16556
16667
  };
16557
16668
  };
16558
16669
  var overlayBase = (options) => ({
@@ -16870,7 +16981,7 @@ var studyRetrievalSuite = (options) => {
16870
16981
  continue;
16871
16982
  }
16872
16983
  const targets = byRepository.get(task.repositoryId);
16873
- const resolve32 = (references, kind) => references.flatMap((item) => {
16984
+ const resolve33 = (references, kind) => references.flatMap((item) => {
16874
16985
  const resolved = targets?.[item];
16875
16986
  if (!resolved?.length) {
16876
16987
  unresolved.push({ taskId: task.id, repositoryId: task.repositoryId, reference: item, kind });
@@ -16879,7 +16990,7 @@ var studyRetrievalSuite = (options) => {
16879
16990
  return resolved;
16880
16991
  });
16881
16992
  const expectedTargets = [
16882
- .../* @__PURE__ */ new Set([...resolve32(task.expectedEntities ?? [], "entity"), ...resolve32(task.expectedDocuments ?? [], "document")])
16993
+ .../* @__PURE__ */ new Set([...resolve33(task.expectedEntities ?? [], "entity"), ...resolve33(task.expectedDocuments ?? [], "document")])
16883
16994
  ].sort();
16884
16995
  if (!expectedTargets.length) continue;
16885
16996
  const queries = taskRetrievalQueries(task);
@@ -17089,8 +17200,8 @@ var claimPattern = (claim, surface) => {
17089
17200
  var renderClaim = (claim, value, surface) => (surface === void 0 ? claim.template ?? "{value}" : templateFor(claim, surface)).replace("{value}", value);
17090
17201
 
17091
17202
  // src/parity/resolve.ts
17092
- import { existsSync as existsSync27, readFileSync as readFileSync30 } from "fs";
17093
- import { resolve as resolve30 } from "path";
17203
+ import { existsSync as existsSync28, readFileSync as readFileSync31 } from "fs";
17204
+ import { resolve as resolve31 } from "path";
17094
17205
 
17095
17206
  // src/cli/usage.ts
17096
17207
  var CLI_COMMAND_USAGE = `ak-docs \u2014 human\u2194agent documentation bridge (@agentskit/doc-bridge)
@@ -17159,7 +17270,7 @@ Global flags:
17159
17270
  `;
17160
17271
 
17161
17272
  // src/parity/resolve.ts
17162
- var readJson4 = (path) => JSON.parse(readFileSync30(path, "utf8"));
17273
+ var readJson4 = (path) => JSON.parse(readFileSync31(path, "utf8"));
17163
17274
  var dotted = (value, field) => field.split(".").reduce((current, key) => {
17164
17275
  if (current === null || typeof current !== "object") return void 0;
17165
17276
  return current[key];
@@ -17211,20 +17322,20 @@ var resolveClaim = (claim, context) => {
17211
17322
  const evidence2 = claim.evidence;
17212
17323
  switch (evidence2.kind) {
17213
17324
  case "package-field": {
17214
- const path = resolve30(context.root, "package.json");
17215
- if (!existsSync27(path)) return { status: "not-analyzed", reason: "package.json is not present." };
17325
+ const path = resolve31(context.root, "package.json");
17326
+ if (!existsSync28(path)) return { status: "not-analyzed", reason: "package.json is not present." };
17216
17327
  const value = scalar2(dotted(readJson4(path), evidence2.field), void 0);
17217
17328
  return value === void 0 ? { status: "not-analyzed", reason: `package.json has no scalar field "${evidence2.field}".` } : { status: "resolved", value };
17218
17329
  }
17219
17330
  case "artifact-field": {
17220
- const path = resolve30(context.root, evidence2.path);
17221
- if (!existsSync27(path)) return { status: "not-analyzed", reason: `${evidence2.path} is not present.` };
17331
+ const path = resolve31(context.root, evidence2.path);
17332
+ if (!existsSync28(path)) return { status: "not-analyzed", reason: `${evidence2.path} is not present.` };
17222
17333
  const value = scalar2(dotted(readJson4(path), evidence2.field), evidence2.transform);
17223
17334
  return value === void 0 ? { status: "not-analyzed", reason: `${evidence2.path} has no scalar field "${evidence2.field}" that renders under ${evidence2.transform ?? "identity"}.` } : { status: "resolved", value };
17224
17335
  }
17225
17336
  case "artifact-sum": {
17226
- const path = resolve30(context.root, evidence2.path);
17227
- if (!existsSync27(path)) return { status: "not-analyzed", reason: `${evidence2.path} is not present.` };
17337
+ const path = resolve31(context.root, evidence2.path);
17338
+ if (!existsSync28(path)) return { status: "not-analyzed", reason: `${evidence2.path} is not present.` };
17228
17339
  const array = dotted(readJson4(path), evidence2.arrayField);
17229
17340
  if (!Array.isArray(array) || array.length === 0) {
17230
17341
  return { status: "not-analyzed", reason: `${evidence2.path} has no non-empty array at "${evidence2.arrayField}".` };
@@ -17259,8 +17370,8 @@ var resolveClaim = (claim, context) => {
17259
17370
  };
17260
17371
 
17261
17372
  // src/parity/check.ts
17262
- import { existsSync as existsSync28, readFileSync as readFileSync31 } from "fs";
17263
- import { resolve as resolve31 } from "path";
17373
+ import { existsSync as existsSync29, readFileSync as readFileSync32 } from "fs";
17374
+ import { resolve as resolve32 } from "path";
17264
17375
  import { z as z30 } from "zod";
17265
17376
  var PUBLIC_PARITY_SCHEMA_VERSION = 1;
17266
17377
  var PARITY_EXCERPT_LIMIT = 160;
@@ -17336,8 +17447,8 @@ var occurrences = (claim, surface, content) => {
17336
17447
  var checkPublicParity = (options) => {
17337
17448
  const { registry } = options;
17338
17449
  const read = options.readSurface ?? ((path) => {
17339
- const absolute = resolve31(options.root, path);
17340
- return existsSync28(absolute) ? readFileSync31(absolute, "utf8") : void 0;
17450
+ const absolute = resolve32(options.root, path);
17451
+ return existsSync29(absolute) ? readFileSync32(absolute, "utf8") : void 0;
17341
17452
  });
17342
17453
  const surfaces2 = claimSurfaces(registry);
17343
17454
  const contents = new Map(surfaces2.map((surface) => [surface, read(surface)]));