@agentskit/doc-bridge 1.2.6 → 1.4.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 (47) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +32 -6
  3. package/action.yml +1 -1
  4. package/dist/cli/program.js +344 -130
  5. package/dist/cli/program.js.map +1 -1
  6. package/dist/config/index.d.ts +1 -1
  7. package/dist/config/index.js +3 -1
  8. package/dist/config/index.js.map +1 -1
  9. package/dist/{index-DGI9TBLE.d.ts → index-DAeq_OIi.d.ts} +22 -22
  10. package/dist/index.d.ts +7 -4
  11. package/dist/index.js +320 -105
  12. package/dist/index.js.map +1 -1
  13. package/docs/MARKETPLACE.md +1 -1
  14. package/docs/POSITIONING.md +1 -1
  15. package/docs/examples.md +4 -0
  16. package/docs/getting-started.md +1 -1
  17. package/docs/guides/choose-context-layer.md +129 -0
  18. package/docs/guides/gate-ci.md +1 -1
  19. package/docs/guides/meta.json +1 -0
  20. package/docs/landing/index.html +2 -2
  21. package/docs/playbook/doc-bridge-pattern.md +1 -1
  22. package/docs/qa/vitepress-starlight-adapters.md +19 -0
  23. package/docs/recipes/index-pipeline.md +1 -1
  24. package/docs/spec/config-v1.md +33 -2
  25. package/examples/nextra-only.config.ts +17 -0
  26. package/examples/nx-monorepo.config.ts +11 -0
  27. package/examples/starlight-only.config.ts +17 -0
  28. package/examples/vitepress-only.config.ts +19 -0
  29. package/mcpb/manifest.json +1 -1
  30. package/package.json +15 -4
  31. package/skills/doc-bridge-handoff/SKILL.md +38 -0
  32. package/skills/doc-bridge-handoff/fixtures/synthetic-repo/doc-bridge.config.json +23 -0
  33. package/skills/doc-bridge-handoff/fixtures/synthetic-repo/docs/for-agents/packages/payments.md +5 -0
  34. package/skills/doc-bridge-handoff/fixtures/synthetic-repo/packages/payments/package.json +4 -0
  35. package/skills/doc-bridge-handoff/scripts/resolve-handoff.mjs +70 -0
  36. package/src/config/schema.ts +3 -1
  37. package/src/index-builder/build-handoffs.ts +2 -0
  38. package/src/index-builder/build-index.ts +7 -1
  39. package/src/index-builder/human-adapters/index.ts +6 -0
  40. package/src/index-builder/human-adapters/nextra.ts +43 -0
  41. package/src/index-builder/human-adapters/starlight.ts +40 -0
  42. package/src/index-builder/human-adapters/vitepress.ts +43 -0
  43. package/src/index-builder/plugins/nx.ts +161 -0
  44. package/src/index-builder/plugins/pnpm-monorepo.ts +1 -0
  45. package/src/index-builder/watch-index.ts +11 -2
  46. package/src/index.ts +1 -0
  47. package/src/version.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  // src/cli/program.ts
2
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync16, writeFileSync as writeFileSync4 } from "fs";
3
- import { dirname as dirname7, resolve as resolve12 } from "path";
2
+ import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync4 } from "fs";
3
+ import { dirname as dirname8, resolve as resolve13 } from "path";
4
4
  import { createInterface } from "readline/promises";
5
5
 
6
6
  // src/config/load-config.ts
@@ -333,6 +333,8 @@ var HumanCorpusPluginIdSchema = z.enum([
333
333
  "docusaurus",
334
334
  "mkdocs",
335
335
  "vitepress",
336
+ "starlight",
337
+ "nextra",
336
338
  "custom"
337
339
  ]);
338
340
  var AgentCorpusConfigSchema = z.object({
@@ -372,7 +374,7 @@ var OwnershipEntrySchema = z.object({
372
374
  humanDoc: z.string().min(1).max(512).optional()
373
375
  }).strict();
374
376
  var RoutingConfigSchema = z.object({
375
- plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "pattern-files", "custom"]).optional(),
377
+ plugin: z.enum(["pnpm-monorepo", "npm-workspaces", "yarn-workspaces", "nx", "pattern-files", "custom"]).optional(),
376
378
  options: z.object({
377
379
  packages: z.array(z.string().min(1).max(256)).max(128).optional(),
378
380
  /** Infer ownership from corpus paths/frontmatter (default true). */
@@ -665,8 +667,8 @@ var projectRootFromConfigPath = (configFilePath, projectRootField) => {
665
667
  };
666
668
 
667
669
  // src/conformance/documentation-standard-v1.ts
668
- import { existsSync as existsSync8, readFileSync as readFileSync7, realpathSync as realpathSync5, statSync as statSync3 } from "fs";
669
- import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve5, sep as sep4 } from "path";
670
+ import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync as realpathSync6, statSync as statSync3 } from "fs";
671
+ import { isAbsolute as isAbsolute4, relative as relative4, resolve as resolve6, sep as sep5 } from "path";
670
672
 
671
673
  // src/conformance/ecosystem-contract.ts
672
674
  import { z as z2 } from "zod";
@@ -841,8 +843,8 @@ var parseCanonicalEcosystemContract = (manifestInput, claimsInput) => {
841
843
  };
842
844
 
843
845
  // src/index-builder/build-index.ts
844
- import { mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
845
- import { dirname as dirname3, join as join7 } from "path";
846
+ import { mkdirSync, readFileSync as readFileSync7, writeFileSync } from "fs";
847
+ import { dirname as dirname4, join as join7 } from "path";
846
848
 
847
849
  // src/lib/paths.ts
848
850
  import { existsSync as existsSync2, realpathSync } from "fs";
@@ -1111,17 +1113,17 @@ var scanAgentCorpus = (root, config) => {
1111
1113
  };
1112
1114
  });
1113
1115
  };
1114
- var guessAgentDocForPackage = (corpus, packageId) => {
1116
+ var guessAgentDocForPackage = (corpus, packageId2) => {
1115
1117
  const candidates = [
1116
- (doc) => frontmatterString(doc.frontmatter, "package") === packageId,
1117
- (doc) => doc.id === packageId,
1118
- (doc) => doc.relPath.endsWith(`/packages/${packageId}.md`),
1119
- (doc) => doc.relPath.endsWith(`/packages/${packageId}.mdx`),
1120
- (doc) => doc.relPath.endsWith(`/packages/${packageId}/index.md`),
1121
- (doc) => doc.relPath.endsWith(`/packages/${packageId}/index.mdx`),
1122
- (doc) => doc.relPath.endsWith(`/${packageId}.md`),
1123
- (doc) => doc.relPath.endsWith(`/${packageId}.mdx`),
1124
- (doc) => doc.relPath.includes(`/packages/${packageId}/`)
1118
+ (doc) => frontmatterString(doc.frontmatter, "package") === packageId2,
1119
+ (doc) => doc.id === packageId2,
1120
+ (doc) => doc.relPath.endsWith(`/packages/${packageId2}.md`),
1121
+ (doc) => doc.relPath.endsWith(`/packages/${packageId2}.mdx`),
1122
+ (doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.md`),
1123
+ (doc) => doc.relPath.endsWith(`/packages/${packageId2}/index.mdx`),
1124
+ (doc) => doc.relPath.endsWith(`/${packageId2}.md`),
1125
+ (doc) => doc.relPath.endsWith(`/${packageId2}.mdx`),
1126
+ (doc) => doc.relPath.includes(`/packages/${packageId2}/`)
1125
1127
  ];
1126
1128
  for (const match of candidates) {
1127
1129
  const hit = corpus.find(match);
@@ -1213,7 +1215,8 @@ var collectPackages = (config, discovered, corpus) => {
1213
1215
  byId.set(pkg.id, {
1214
1216
  id: pkg.id,
1215
1217
  path: existing.path || pkg.path,
1216
- ...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {}
1218
+ ...pkg.name ? { name: pkg.name } : existing.name ? { name: existing.name } : {},
1219
+ ...pkg.checks ? { checks: pkg.checks } : existing.checks ? { checks: existing.checks } : {}
1217
1220
  });
1218
1221
  }
1219
1222
  const seeds = [
@@ -1232,24 +1235,24 @@ var collectPackages = (config, discovered, corpus) => {
1232
1235
  }
1233
1236
  return [...byId.values()].sort((a, b) => a.id.localeCompare(b.id));
1234
1237
  };
1235
- var resolveHumanDoc = (packageId, override, fmHuman, humanDocs = {}) => {
1238
+ var resolveHumanDoc = (packageId2, override, fmHuman, humanDocs = {}) => {
1236
1239
  if (override) return override;
1237
1240
  if (fmHuman) return fmHuman;
1238
- if (humanDocs[packageId]) return humanDocs[packageId];
1241
+ if (humanDocs[packageId2]) return humanDocs[packageId2];
1239
1242
  const aliases = [
1240
- packageId,
1241
- packageId.replace(/^@[^/]+\//, ""),
1242
- packageId.replace(/^os-/, ""),
1243
- packageId.replace(/-pattern$/, ""),
1244
- `packages/${packageId}`,
1245
- `reference/packages/${packageId}`,
1246
- `packages/${packageId}/index`
1243
+ packageId2,
1244
+ packageId2.replace(/^@[^/]+\//, ""),
1245
+ packageId2.replace(/^os-/, ""),
1246
+ packageId2.replace(/-pattern$/, ""),
1247
+ `packages/${packageId2}`,
1248
+ `reference/packages/${packageId2}`,
1249
+ `packages/${packageId2}/index`
1247
1250
  ];
1248
1251
  for (const alias of aliases) {
1249
1252
  if (humanDocs[alias]) return humanDocs[alias];
1250
1253
  }
1251
1254
  for (const [key, url] of Object.entries(humanDocs)) {
1252
- if (key === packageId || key.endsWith(`/${packageId}`) || key.endsWith(`/${packageId}/index`) || key.endsWith(`-${packageId}`)) {
1255
+ if (key === packageId2 || key.endsWith(`/${packageId2}`) || key.endsWith(`/${packageId2}/index`) || key.endsWith(`-${packageId2}`)) {
1253
1256
  return url;
1254
1257
  }
1255
1258
  }
@@ -1273,7 +1276,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
1273
1276
  const purpose = override?.purpose ?? fm?.purpose;
1274
1277
  const path = override?.path ?? fm?.path ?? pkg.path;
1275
1278
  const checks = [
1276
- ...override?.checks ?? fm?.checks ?? defaultChecksForTarget(root, {
1279
+ ...override?.checks ?? fm?.checks ?? pkg.checks ?? defaultChecksForTarget(root, {
1277
1280
  packageId: pkg.id,
1278
1281
  packagePath: path,
1279
1282
  ...pkg.name ? { packageName: pkg.name } : {},
@@ -1347,7 +1350,7 @@ var buildLookup = (config, packages, corpus, indexOutFile, humanDocs = {}, root
1347
1350
  };
1348
1351
 
1349
1352
  // src/version.ts
1350
- var PACKAGE_VERSION = "1.2.6";
1353
+ var PACKAGE_VERSION = "1.4.0";
1351
1354
 
1352
1355
  // src/index-builder/capabilities.ts
1353
1356
  var renderCapabilitiesJson = (config, index, paths) => {
@@ -1604,6 +1607,38 @@ var fumadocsAdapter = {
1604
1607
  }
1605
1608
  };
1606
1609
 
1610
+ // src/index-builder/human-adapters/nextra.ts
1611
+ var nextraRecordId = (relPath, raw) => {
1612
+ const frontmatter = parseFrontmatter2(raw);
1613
+ return frontmatter.package ?? frontmatter.module ?? frontmatter.id ?? (routeSlug(relPath) || "index");
1614
+ };
1615
+ var isIndexPage = (path) => /(^|[/\\])index\.mdx?$/i.test(path);
1616
+ var resolveRouteCollisions = (records) => {
1617
+ const byUrl = /* @__PURE__ */ new Map();
1618
+ for (const record of records) {
1619
+ const normalized = { ...record, url: record.url || "/" };
1620
+ const indexPage = isIndexPage(record.path);
1621
+ const existing = byUrl.get(normalized.url);
1622
+ if (!existing || indexPage || !existing.indexPage) {
1623
+ byUrl.set(normalized.url, { record: normalized, indexPage });
1624
+ }
1625
+ }
1626
+ return [...byUrl.values()].map(({ record }) => record);
1627
+ };
1628
+ var nextraAdapter = {
1629
+ plugin: "nextra",
1630
+ scan: ({ root, config }) => {
1631
+ const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
1632
+ if (!contentDir) return [];
1633
+ return resolveRouteCollisions(
1634
+ scanMarkdownDocs(root, contentDir, {
1635
+ idForDoc: nextraRecordId,
1636
+ urlPrefix: optionString(config.options, ["urlPrefix", "contentDirBasePath"]) ?? "/"
1637
+ })
1638
+ );
1639
+ }
1640
+ };
1641
+
1607
1642
  // src/index-builder/human-adapters/plain-markdown.ts
1608
1643
  var plainMarkdownAdapter = {
1609
1644
  plugin: "plain-markdown",
@@ -1613,11 +1648,73 @@ var plainMarkdownAdapter = {
1613
1648
  }
1614
1649
  };
1615
1650
 
1651
+ // src/index-builder/human-adapters/starlight.ts
1652
+ import { slug as githubSlug } from "github-slugger";
1653
+ var isStarlightPage = (relPath, raw) => {
1654
+ if (relPath.split("/").some((part) => part.startsWith(".") || part.startsWith("_"))) return false;
1655
+ return parseFrontmatter2(raw).draft !== "true";
1656
+ };
1657
+ var starlightFileSlug = (relPath) => routeSlug(relPath).split("/").map((part) => githubSlug(part)).filter(Boolean).join("/");
1658
+ var starlightSlug = (relPath, raw) => {
1659
+ const slug2 = parseFrontmatter2(raw).slug;
1660
+ return slug2 ? slug2.replace(/^\/+|\/+$/g, "") : starlightFileSlug(relPath);
1661
+ };
1662
+ var starlightAdapter = {
1663
+ plugin: "starlight",
1664
+ scan: ({ root, config }) => {
1665
+ const contentDir = optionString(config.options, ["contentDir", "docsDir", "root"]);
1666
+ if (!contentDir) return [];
1667
+ return scanMarkdownDocs(root, contentDir, {
1668
+ includeRelPath: isStarlightPage,
1669
+ slugForDoc: starlightSlug,
1670
+ urlPrefix: config.options?.urlPrefix
1671
+ });
1672
+ }
1673
+ };
1674
+
1675
+ // src/index-builder/human-adapters/vitepress.ts
1676
+ import { minimatch } from "minimatch";
1677
+ var isVitePressPage = (relPath) => !relPath.split("/").some((part) => part === ".vitepress" || part.startsWith("."));
1678
+ var srcExcludePatterns = (value) => {
1679
+ if (value === void 0) return [];
1680
+ if (!Array.isArray(value) || value.length > 64) {
1681
+ throw new Error("VitePress srcExclude must be an array of at most 64 glob patterns.");
1682
+ }
1683
+ return value.map((pattern) => {
1684
+ if (typeof pattern !== "string" || !pattern || pattern.length > 256 || pattern.includes("\0")) {
1685
+ throw new Error("Each VitePress srcExclude pattern must be a non-empty string up to 256 characters.");
1686
+ }
1687
+ return pattern;
1688
+ });
1689
+ };
1690
+ var isExcluded = (relPath, patterns) => patterns.some((pattern) => minimatch(relPath, pattern, { dot: true }));
1691
+ var vitepressSlug = (relPath, cleanUrls) => {
1692
+ const slug2 = routeSlug(relPath);
1693
+ if (cleanUrls || /(?:^|\/)index\.mdx?$/.test(relPath)) return slug2;
1694
+ return `${slug2}.html`;
1695
+ };
1696
+ var vitepressAdapter = {
1697
+ plugin: "vitepress",
1698
+ scan: ({ root, config }) => {
1699
+ const docsDir = optionString(config.options, ["docsDir", "root", "srcDir"]);
1700
+ if (!docsDir) return [];
1701
+ const srcExclude = srcExcludePatterns(config.options?.srcExclude);
1702
+ return scanMarkdownDocs(root, docsDir, {
1703
+ includeRelPath: (relPath) => isVitePressPage(relPath) && !isExcluded(relPath, srcExclude),
1704
+ slugForDoc: (relPath) => vitepressSlug(relPath, config.options?.cleanUrls === true),
1705
+ urlPrefix: config.options?.urlPrefix
1706
+ });
1707
+ }
1708
+ };
1709
+
1616
1710
  // src/index-builder/human-adapters/index.ts
1617
1711
  var ADAPTERS = [
1618
1712
  plainMarkdownAdapter,
1619
1713
  fumadocsAdapter,
1620
- docusaurusAdapter
1714
+ docusaurusAdapter,
1715
+ vitepressAdapter,
1716
+ starlightAdapter,
1717
+ nextraAdapter
1621
1718
  ];
1622
1719
  var humanConfigs = (config) => {
1623
1720
  const human = config.corpus.human;
@@ -1652,12 +1749,121 @@ var scanHumanDocRecords = (root, config) => {
1652
1749
  };
1653
1750
  var scanHumanDocs = (root, config) => Object.fromEntries(scanHumanDocRecords(root, config).map((doc) => [doc.id, doc.url]));
1654
1751
 
1752
+ // src/index-builder/plugins/nx.ts
1753
+ import { existsSync as existsSync6, lstatSync as lstatSync2, readFileSync as readFileSync5, realpathSync as realpathSync5 } from "fs";
1754
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve5, sep as sep4 } from "path";
1755
+ var NX_SCAN_SKIP = /* @__PURE__ */ new Set([
1756
+ "node_modules",
1757
+ ".git",
1758
+ ".nx",
1759
+ "dist",
1760
+ "coverage",
1761
+ ".doc-bridge"
1762
+ ]);
1763
+ var NX_PROJECT_NAME = /^(?:@[A-Za-z0-9._-]+\/)?[A-Za-z0-9][A-Za-z0-9._-]*$/;
1764
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1765
+ var readJsonRecord = (path) => {
1766
+ try {
1767
+ const parsed = JSON.parse(readFileSync5(path, "utf8"));
1768
+ return isRecord(parsed) ? parsed : void 0;
1769
+ } catch {
1770
+ return void 0;
1771
+ }
1772
+ };
1773
+ var safeProjectPath = (root, manifestDir, declaredRoot) => {
1774
+ const candidate = typeof declaredRoot === "string" ? resolve5(root, declaredRoot) : manifestDir;
1775
+ const rel = toPosix(relative3(root, candidate)) || ".";
1776
+ if (isAbsolute3(rel) || rel === ".." || rel.startsWith("../")) return void 0;
1777
+ try {
1778
+ if (!lstatSync2(candidate).isDirectory()) return void 0;
1779
+ const canonicalRoot = realpathSync5.native(root);
1780
+ const canonicalCandidate = realpathSync5.native(candidate);
1781
+ const canonicalRel = relative3(canonicalRoot, canonicalCandidate);
1782
+ if (isAbsolute3(canonicalRel) || canonicalRel === ".." || canonicalRel.startsWith(`..${sep4}`)) {
1783
+ return void 0;
1784
+ }
1785
+ } catch {
1786
+ return void 0;
1787
+ }
1788
+ return rel;
1789
+ };
1790
+ var packageId = (name) => name.startsWith("@") ? name.split("/").at(-1) ?? name : name;
1791
+ var commandPrefix = (root) => {
1792
+ const manager = detectPackageManager(root);
1793
+ if (manager === "pnpm") return "pnpm exec nx run";
1794
+ if (manager === "yarn") return "yarn nx run";
1795
+ if (manager === "bun") return "bunx nx run";
1796
+ return "npx nx run";
1797
+ };
1798
+ var inferredChecks = (root, config, projectName2, targets) => {
1799
+ const prefix = commandPrefix(root);
1800
+ const strict = (config.gates?.preset ?? "minimal") !== "minimal";
1801
+ const checks = [
1802
+ ...targets.has("test") ? [`${prefix} ${projectName2}:test`] : [],
1803
+ ...strict && targets.has("lint") ? [`${prefix} ${projectName2}:lint`] : []
1804
+ ];
1805
+ return checks.length ? checks : void 0;
1806
+ };
1807
+ var discoverNxProjects = (root, config) => {
1808
+ if (!existsSync6(resolve5(root, "nx.json"))) return [];
1809
+ const manifests = walkFiles(root, {
1810
+ extensions: ["project.json", "package.json"],
1811
+ skipDirs: NX_SCAN_SKIP,
1812
+ maxFiles: 1e4
1813
+ });
1814
+ const projects = /* @__PURE__ */ new Map();
1815
+ for (const manifest of manifests) {
1816
+ const json = readJsonRecord(manifest);
1817
+ if (!json) continue;
1818
+ const manifestDir = dirname3(manifest);
1819
+ const manifestName = basename2(manifest);
1820
+ const isProjectJson = manifestName === "project.json";
1821
+ if (!isProjectJson && manifestName !== "package.json") continue;
1822
+ const nx = json.nx;
1823
+ if (!isProjectJson && !isRecord(nx)) continue;
1824
+ const path = safeProjectPath(root, manifestDir, isProjectJson ? json.root : void 0);
1825
+ if (!path) continue;
1826
+ const projectPackage = isProjectJson ? readJsonRecord(resolve5(root, path, "package.json")) : void 0;
1827
+ const projectName2 = typeof json.name === "string" ? json.name : typeof projectPackage?.name === "string" ? projectPackage.name : basename2(path === "." ? root : path);
1828
+ if (!NX_PROJECT_NAME.test(projectName2)) continue;
1829
+ const targets = /* @__PURE__ */ new Set();
1830
+ const targetRecord = isProjectJson ? json.targets : isRecord(nx) ? nx.targets : void 0;
1831
+ if (isRecord(targetRecord)) {
1832
+ for (const target of Object.keys(targetRecord)) targets.add(target);
1833
+ }
1834
+ if (!isProjectJson && isRecord(json.scripts)) {
1835
+ for (const script of Object.keys(json.scripts)) targets.add(script);
1836
+ }
1837
+ const id = packageId(projectName2);
1838
+ const rank = isProjectJson ? 2 : 1;
1839
+ const existing = projects.get(id);
1840
+ if (existing && existing.path !== path) {
1841
+ throw new Error(
1842
+ `Nx project identity collision for "${id}": "${existing.name ?? id}" at "${existing.path}" and "${projectName2}" at "${path}". Use unique Nx project names.`
1843
+ );
1844
+ }
1845
+ const mergedTargets = [.../* @__PURE__ */ new Set([...existing?.targets ?? [], ...targets])];
1846
+ const projectJsonWins = rank >= (existing?.rank ?? 0);
1847
+ const resolvedName = projectJsonWins ? projectName2 : existing?.name ?? projectName2;
1848
+ const checks = inferredChecks(root, config, resolvedName, new Set(mergedTargets));
1849
+ projects.set(id, {
1850
+ id,
1851
+ path,
1852
+ name: resolvedName,
1853
+ ...checks ? { checks } : {},
1854
+ rank: projectJsonWins ? rank : existing?.rank ?? rank,
1855
+ targets: mergedTargets
1856
+ });
1857
+ }
1858
+ return [...projects.values()].sort((a, b) => a.id.localeCompare(b.id)).map(({ rank: _rank, targets: _targets, ...project }) => project);
1859
+ };
1860
+
1655
1861
  // src/index-builder/plugins/pnpm-monorepo.ts
1656
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
1657
- import { basename as basename2, join as join6 } from "path";
1862
+ import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
1863
+ import { basename as basename3, join as join6 } from "path";
1658
1864
 
1659
1865
  // src/lib/glob-expand.ts
1660
- import { existsSync as existsSync6, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
1866
+ import { existsSync as existsSync7, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
1661
1867
  import { join as join5 } from "path";
1662
1868
  var expandWorkspaceGlobs = (root, patterns) => {
1663
1869
  const dirs = /* @__PURE__ */ new Set();
@@ -1665,12 +1871,12 @@ var expandWorkspaceGlobs = (root, patterns) => {
1665
1871
  const normalized = toPosix(pattern).replace(/\/$/, "");
1666
1872
  if (!normalized.includes("*")) {
1667
1873
  const abs = join5(root, normalized);
1668
- if (existsSync6(abs)) dirs.add(toPosix(abs));
1874
+ if (existsSync7(abs)) dirs.add(toPosix(abs));
1669
1875
  continue;
1670
1876
  }
1671
1877
  const star = normalized.indexOf("*");
1672
1878
  const base = join5(root, normalized.slice(0, star).replace(/\/$/, ""));
1673
- if (!existsSync6(base)) continue;
1879
+ if (!existsSync7(base)) continue;
1674
1880
  for (const name of readdirSync2(base)) {
1675
1881
  const abs = join5(base, name);
1676
1882
  try {
@@ -1705,9 +1911,9 @@ var parsePnpmWorkspace = (yaml) => {
1705
1911
  };
1706
1912
  var readPackageJson = (dir) => {
1707
1913
  const file = join6(dir, "package.json");
1708
- if (!existsSync7(file)) return null;
1914
+ if (!existsSync8(file)) return null;
1709
1915
  try {
1710
- return JSON.parse(readFileSync5(file, "utf8"));
1916
+ return JSON.parse(readFileSync6(file, "utf8"));
1711
1917
  } catch {
1712
1918
  return null;
1713
1919
  }
@@ -1717,8 +1923,8 @@ var discoverPnpmPackages = (root, config) => {
1717
1923
  let patterns = explicit;
1718
1924
  if (!patterns?.length) {
1719
1925
  const workspaceFile = join6(root, "pnpm-workspace.yaml");
1720
- if (existsSync7(workspaceFile)) {
1721
- patterns = parsePnpmWorkspace(readFileSync5(workspaceFile, "utf8"));
1926
+ if (existsSync8(workspaceFile)) {
1927
+ patterns = parsePnpmWorkspace(readFileSync6(workspaceFile, "utf8"));
1722
1928
  }
1723
1929
  }
1724
1930
  if (!patterns?.length) return [];
@@ -1728,7 +1934,7 @@ var discoverPnpmPackages = (root, config) => {
1728
1934
  const pkg = readPackageJson(abs);
1729
1935
  if (!pkg) continue;
1730
1936
  const rel = toPosix(abs.replace(`${toPosix(root)}/`, ""));
1731
- const folderId = basename2(abs);
1937
+ const folderId = basename3(abs);
1732
1938
  const id = pkg.name?.startsWith("@") ? pkg.name.split("/").pop() ?? folderId : pkg.name ?? folderId;
1733
1939
  out.push({ id, path: rel, ...pkg.name ? { name: pkg.name } : {} });
1734
1940
  }
@@ -1739,7 +1945,7 @@ var discoverPnpmPackages = (root, config) => {
1739
1945
  var projectName = (root, config) => {
1740
1946
  if (config.project?.name) return config.project.name;
1741
1947
  try {
1742
- const pkg = JSON.parse(readFileSync6(join7(root, "package.json"), "utf8"));
1948
+ const pkg = JSON.parse(readFileSync7(join7(root, "package.json"), "utf8"));
1743
1949
  if (pkg.name) return pkg.name;
1744
1950
  } catch {
1745
1951
  }
@@ -1747,7 +1953,7 @@ var projectName = (root, config) => {
1747
1953
  };
1748
1954
  var existingGeneratedAt = (indexPath, contentHash) => {
1749
1955
  try {
1750
- const index = JSON.parse(readFileSync6(indexPath, "utf8"));
1956
+ const index = JSON.parse(readFileSync7(indexPath, "utf8"));
1751
1957
  return index.contentHash === contentHash && typeof index.generatedAt === "string" ? index.generatedAt : void 0;
1752
1958
  } catch {
1753
1959
  return void 0;
@@ -1762,7 +1968,7 @@ var buildDocBridgeIndex = (opts) => {
1762
1968
  const corpus = scanAgentCorpus(root, config);
1763
1969
  const knowledge = corpus.map(({ absPath: _a, relPath: _r, frontmatter: _f, ...entry }) => entry);
1764
1970
  const shouldDiscover = config.routing?.plugin === "pnpm-monorepo" || Boolean(config.routing?.options?.packages?.length) || config.routing?.plugin === "npm-workspaces" || config.routing?.plugin === "yarn-workspaces";
1765
- const discovered = shouldDiscover ? discoverPnpmPackages(root, config) : [];
1971
+ const discovered = config.routing?.plugin === "nx" ? discoverNxProjects(root, config) : shouldDiscover ? discoverPnpmPackages(root, config) : [];
1766
1972
  const packages = collectPackages(config, discovered, corpus);
1767
1973
  const humanDocs = scanHumanDocs(root, config);
1768
1974
  const { lookup, handoffs } = buildLookup(config, packages, corpus, outFile, humanDocs, root);
@@ -1784,7 +1990,7 @@ var buildDocBridgeIndex = (opts) => {
1784
1990
  lookup
1785
1991
  };
1786
1992
  if (write) {
1787
- mkdirSync(dirname3(indexPath), { recursive: true });
1993
+ mkdirSync(dirname4(indexPath), { recursive: true });
1788
1994
  writeFileSync(indexPath, `${JSON.stringify(index, null, 2)}
1789
1995
  `, "utf8");
1790
1996
  }
@@ -1807,7 +2013,7 @@ var buildDocBridgeIndex = (opts) => {
1807
2013
  const capabilitiesOut = config.index?.capabilities?.outFile ?? ".doc-bridge/capabilities.json";
1808
2014
  capabilitiesPath = join7(root, capabilitiesOut);
1809
2015
  if (write) {
1810
- mkdirSync(dirname3(capabilitiesPath), { recursive: true });
2016
+ mkdirSync(dirname4(capabilitiesPath), { recursive: true });
1811
2017
  writeFileSync(
1812
2018
  capabilitiesPath,
1813
2019
  renderCapabilitiesJson(config, index, {
@@ -1831,15 +2037,15 @@ var DOCUMENTATION_STANDARD_V1_ID = "documentation-standard-v1";
1831
2037
  var DOCUMENTATION_STANDARD_V1_STATUS = "stable";
1832
2038
  var MAX_TEXT_EVIDENCE_BYTES = 4 * 1024 * 1024;
1833
2039
  var safePath = (root, path) => {
1834
- const rootAbs = realpathSync5.native(resolve5(root));
1835
- const unresolved = resolve5(rootAbs, path);
1836
- const unresolvedRel = relative3(rootAbs, unresolved);
1837
- if (isAbsolute3(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep4}`)) return void 0;
1838
- if (!existsSync8(unresolved)) return unresolved;
2040
+ const rootAbs = realpathSync6.native(resolve6(root));
2041
+ const unresolved = resolve6(rootAbs, path);
2042
+ const unresolvedRel = relative4(rootAbs, unresolved);
2043
+ if (isAbsolute4(unresolvedRel) || unresolvedRel === ".." || unresolvedRel.startsWith(`..${sep5}`)) return void 0;
2044
+ if (!existsSync9(unresolved)) return unresolved;
1839
2045
  try {
1840
- const abs = realpathSync5.native(unresolved);
1841
- const rel = relative3(rootAbs, abs);
1842
- return !isAbsolute3(rel) && rel !== ".." && !rel.startsWith(`..${sep4}`) ? abs : void 0;
2046
+ const abs = realpathSync6.native(unresolved);
2047
+ const rel = relative4(rootAbs, abs);
2048
+ return !isAbsolute4(rel) && rel !== ".." && !rel.startsWith(`..${sep5}`) ? abs : void 0;
1843
2049
  } catch {
1844
2050
  return void 0;
1845
2051
  }
@@ -1853,7 +2059,7 @@ var fileEvidence = (root, path, options) => {
1853
2059
  evidence: { path, detail: "Path escapes the project root." }
1854
2060
  };
1855
2061
  }
1856
- if (!existsSync8(abs)) {
2062
+ if (!existsSync9(abs)) {
1857
2063
  return { exists: false, content: "", evidence: { path, detail: "File does not exist." } };
1858
2064
  }
1859
2065
  try {
@@ -1868,7 +2074,7 @@ var fileEvidence = (root, path, options) => {
1868
2074
  return {
1869
2075
  exists: true,
1870
2076
  content: "",
1871
- evidence: { path: toPosix(relative3(resolve5(root), abs)) || ".", detail: "File exists and is non-empty." }
2077
+ evidence: { path: toPosix(relative4(resolve6(root), abs)) || ".", detail: "File exists and is non-empty." }
1872
2078
  };
1873
2079
  }
1874
2080
  if (stat.size > MAX_TEXT_EVIDENCE_BYTES) {
@@ -1878,12 +2084,12 @@ var fileEvidence = (root, path, options) => {
1878
2084
  evidence: { path, detail: `Text evidence exceeds ${MAX_TEXT_EVIDENCE_BYTES} bytes.` }
1879
2085
  };
1880
2086
  }
1881
- const content = readFileSync7(abs, "utf8");
2087
+ const content = readFileSync8(abs, "utf8");
1882
2088
  return {
1883
2089
  exists: content.trim().length > 0,
1884
2090
  content,
1885
2091
  evidence: {
1886
- path: toPosix(relative3(resolve5(root), abs)) || ".",
2092
+ path: toPosix(relative4(resolve6(root), abs)) || ".",
1887
2093
  detail: content.trim().length > 0 ? "File exists and is non-empty." : "File is empty."
1888
2094
  }
1889
2095
  };
@@ -1918,7 +2124,7 @@ var humanDocsRule = (root, config) => {
1918
2124
  passed: docs.length > 0,
1919
2125
  message: docs.length > 0 ? `Found ${docs.length} human document(s).` : "No human documentation was discovered.",
1920
2126
  evidence: docs.slice(0, 10).map((doc) => ({
1921
- path: toPosix(relative3(resolve5(root), doc.path)),
2127
+ path: toPosix(relative4(resolve6(root), doc.path)),
1922
2128
  detail: `Human route: ${doc.url}`
1923
2129
  })),
1924
2130
  remediation: {
@@ -1929,10 +2135,10 @@ var humanDocsRule = (root, config) => {
1929
2135
  };
1930
2136
  var llmsRule = (root, config, options) => {
1931
2137
  const llmsPath = config.index?.llmsTxt?.outFile ?? "llms.txt";
1932
- const llmsKey = safePath(root, llmsPath) ?? resolve5(root, llmsPath);
2138
+ const llmsKey = safePath(root, llmsPath) ?? resolve6(root, llmsPath);
1933
2139
  const rawSources = /* @__PURE__ */ new Map();
1934
2140
  for (const path of options.rawSources ?? []) {
1935
- const key = safePath(root, path) ?? resolve5(root, path);
2141
+ const key = safePath(root, path) ?? resolve6(root, path);
1936
2142
  if (key !== llmsKey && !rawSources.has(key)) rawSources.set(key, path);
1937
2143
  }
1938
2144
  const paths = [llmsPath, ...rawSources.values()];
@@ -2184,8 +2390,8 @@ var formatDocumentationStandardText = (report) => [
2184
2390
  ];
2185
2391
 
2186
2392
  // src/federation/llms.ts
2187
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
2188
- import { resolve as resolve6 } from "path";
2393
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
2394
+ import { resolve as resolve7 } from "path";
2189
2395
 
2190
2396
  // src/query/search.ts
2191
2397
  var tokenize = (value) => value.toLowerCase().split(/[^a-z0-9@/_-]+/).filter((t) => t.length >= 2);
@@ -2314,9 +2520,9 @@ var defaultFetchText = async (url) => {
2314
2520
  var sourceText = async (root, source, fetchText) => {
2315
2521
  try {
2316
2522
  if (/^https?:\/\//.test(source)) return await fetchText(source);
2317
- const path = resolve6(root, source);
2318
- if (!existsSync9(path)) return null;
2319
- return readFileSync8(path, "utf8");
2523
+ const path = resolve7(root, source);
2524
+ if (!existsSync10(path)) return null;
2525
+ return readFileSync9(path, "utf8");
2320
2526
  } catch {
2321
2527
  return null;
2322
2528
  }
@@ -2401,11 +2607,11 @@ var retrieveHybridChunks = async (root, config, index, query, options = {}) => {
2401
2607
  };
2402
2608
 
2403
2609
  // src/gates/run-gates.ts
2404
- import { readFileSync as readFileSync10 } from "fs";
2610
+ import { readFileSync as readFileSync11 } from "fs";
2405
2611
 
2406
2612
  // src/query/load-index.ts
2407
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
2408
- import { join as join8, resolve as resolve7 } from "path";
2613
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
2614
+ import { join as join8, resolve as resolve8 } from "path";
2409
2615
 
2410
2616
  // src/schemas/agent-handoff.ts
2411
2617
  import { z as z3 } from "zod";
@@ -2621,8 +2827,8 @@ var IndexNotFoundError = class extends Error {
2621
2827
  var indexFilePath = (root, config) => join8(root, config.index?.outFile ?? ".doc-bridge/index.json");
2622
2828
  var loadDocBridgeIndex = (root, config) => {
2623
2829
  const path = indexFilePath(root, config);
2624
- if (!existsSync10(path)) throw new IndexNotFoundError(path);
2625
- const raw = JSON.parse(readFileSync9(path, "utf8"));
2830
+ if (!existsSync11(path)) throw new IndexNotFoundError(path);
2831
+ const raw = JSON.parse(readFileSync10(path, "utf8"));
2626
2832
  return parseDocBridgeIndex(raw);
2627
2833
  };
2628
2834
 
@@ -2697,7 +2903,7 @@ var runOkfTypeGate = (root, config) => {
2697
2903
  const required = config.corpus.agent.okf?.requireType ?? config.gates?.preset === "strict";
2698
2904
  if (!required) return { id: "okf-type", ok: true, message: "OKF type frontmatter not required" };
2699
2905
  const allowed = config.corpus.agent.okf?.allowedTypes;
2700
- const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync10(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
2906
+ const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({ path: doc.path, type: frontmatterType(readFileSync11(doc.absPath, "utf8")) })).filter((doc) => !doc.type || allowed && !allowed.includes(doc.type));
2701
2907
  if (bad.length) {
2702
2908
  return {
2703
2909
  id: "okf-type",
@@ -2724,10 +2930,10 @@ var DOCS_STYLE_RULES = {
2724
2930
  "playbook-okf-soft": ["title", "no-stale-wording"],
2725
2931
  "title-only": ["title"]
2726
2932
  };
2727
- var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2933
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2728
2934
  var docsStyleOptions = (config) => {
2729
2935
  const raw = config.gates?.options?.["docs-style"];
2730
- if (!isRecord(raw)) {
2936
+ if (!isRecord2(raw)) {
2731
2937
  if (config.gates?.preset === "playbook") {
2732
2938
  return { profile: "playbook-okf-soft", required: DOCS_STYLE_RULES["playbook-okf-soft"] };
2733
2939
  }
@@ -2771,7 +2977,7 @@ var runDocsStyleGate = (root, config) => {
2771
2977
  }
2772
2978
  const bad = scanAgentCorpus(root, config).filter((doc) => doc.path !== config.corpus.agent.index).map((doc) => ({
2773
2979
  path: doc.path,
2774
- missing: missingStyleRules(readFileSync10(doc.absPath, "utf8"), required)
2980
+ missing: missingStyleRules(readFileSync11(doc.absPath, "utf8"), required)
2775
2981
  })).filter((doc) => doc.missing.length > 0);
2776
2982
  if (bad.length) {
2777
2983
  return {
@@ -3056,7 +3262,7 @@ var resolveIntelligenceRuntime = async (config) => {
3056
3262
  var defaultVectorStorePath = (root) => join9(root, ".doc-bridge", "vectors");
3057
3263
 
3058
3264
  // src/intelligence/rag.ts
3059
- import { readFileSync as readFileSync11 } from "fs";
3265
+ import { readFileSync as readFileSync12 } from "fs";
3060
3266
  import { join as join10 } from "path";
3061
3267
  var loadDocuments = (root, index, sources) => {
3062
3268
  const includeAgent = sources.includes("agent") || sources.length === 0;
@@ -3066,7 +3272,7 @@ var loadDocuments = (root, index, sources) => {
3066
3272
  const abs = join10(root, entry.path);
3067
3273
  let content = "";
3068
3274
  try {
3069
- content = readFileSync11(abs, "utf8");
3275
+ content = readFileSync12(abs, "utf8");
3070
3276
  } catch {
3071
3277
  content = [entry.title, entry.description].filter(Boolean).join("\n\n");
3072
3278
  }
@@ -3219,15 +3425,15 @@ var startInkChat = async (root, config, index) => {
3219
3425
  };
3220
3426
 
3221
3427
  // src/memory/ingest.ts
3222
- import { existsSync as existsSync11, readFileSync as readFileSync12 } from "fs";
3428
+ import { existsSync as existsSync12, readFileSync as readFileSync13 } from "fs";
3223
3429
  import { join as join11 } from "path";
3224
3430
  var memoryFact = (raw, id) => firstParagraph(raw) ?? firstHeading(raw) ?? id;
3225
3431
  var relativePath = (root, abs) => toPosix(abs).replace(`${toPosix(root)}/`, "");
3226
3432
  var ingestMarkdownDir = (root, dir, source, confidence) => {
3227
- if (!existsSync11(dir)) return [];
3433
+ if (!existsSync12(dir)) return [];
3228
3434
  return walkFiles(dir, { extensions: [".md", ".mdc"] }).map((abs) => {
3229
3435
  const rel = relativePath(root, abs);
3230
- const raw = readFileSync12(abs, "utf8");
3436
+ const raw = readFileSync13(abs, "utf8");
3231
3437
  const id = slugFromPath(rel);
3232
3438
  return {
3233
3439
  schemaVersion: 1,
@@ -3332,7 +3538,7 @@ var draftMemoryPromotion = (classifications) => {
3332
3538
 
3333
3539
  // src/memory/github-pr.ts
3334
3540
  import { execFileSync, spawnSync } from "child_process";
3335
- import { existsSync as existsSync12, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
3541
+ import { existsSync as existsSync13, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
3336
3542
  import { join as join12 } from "path";
3337
3543
  var run = (cmd, args, cwd) => {
3338
3544
  const result = spawnSync(cmd, [...args], { cwd, encoding: "utf8" });
@@ -3380,7 +3586,7 @@ var promoteMemoryToGithubPr = (root, draft, options = {}) => {
3380
3586
  message: `Wrote draft to ${relDraft}. Run the printed git/gh commands to open a draft PR.`
3381
3587
  };
3382
3588
  }
3383
- if (!existsSync12(join12(root, ".git"))) {
3589
+ if (!existsSync13(join12(root, ".git"))) {
3384
3590
  return {
3385
3591
  ok: false,
3386
3592
  dryRun: false,
@@ -3483,22 +3689,23 @@ ${auth.out}`
3483
3689
  };
3484
3690
 
3485
3691
  // src/index-builder/watch-index.ts
3486
- import { existsSync as existsSync13, watch } from "fs";
3487
- import { dirname as dirname4, resolve as resolve8 } from "path";
3692
+ import { existsSync as existsSync14, watch } from "fs";
3693
+ import { dirname as dirname5, resolve as resolve9 } from "path";
3488
3694
  var WATCH_PATTERN = /\.(md|mdx|json|ya?ml|mdc)$/i;
3695
+ var NX_MANIFEST_PATTERN = /(^|[/\\])(project|package)\.json$/i;
3489
3696
  var collectWatchRoots = (root, config, configPath) => {
3490
3697
  const roots = /* @__PURE__ */ new Set();
3491
- roots.add(resolve8(root, config.corpus.agent.root));
3698
+ roots.add(resolve9(root, config.corpus.agent.root));
3492
3699
  const humanSources = config.corpus.human ? Array.isArray(config.corpus.human) ? config.corpus.human : [config.corpus.human] : [];
3493
3700
  for (const source of humanSources) {
3494
3701
  const humanOpts = source.options ?? {};
3495
- for (const key of ["contentDir", "docsDir", "root"]) {
3702
+ for (const key of ["contentDir", "docsDir", "root", "srcDir"]) {
3496
3703
  const value = humanOpts[key];
3497
- if (typeof value === "string" && value.length) roots.add(resolve8(root, value));
3704
+ if (typeof value === "string" && value.length) roots.add(resolve9(root, value));
3498
3705
  }
3499
3706
  }
3500
- if (configPath) roots.add(dirname4(resolve8(configPath)));
3501
- return [...roots].filter((dir) => existsSync13(dir));
3707
+ if (configPath) roots.add(dirname5(resolve9(configPath)));
3708
+ return [...roots].filter((dir) => existsSync14(dir));
3502
3709
  };
3503
3710
  var watchDocBridgeIndex = (opts) => {
3504
3711
  const debounceMs = opts.debounceMs ?? 350;
@@ -3539,8 +3746,15 @@ var watchDocBridgeIndex = (opts) => {
3539
3746
  rebuild();
3540
3747
  });
3541
3748
  }
3542
- const configDir = resolve8(opts.root);
3543
- if (existsSync13(configDir)) {
3749
+ const nxRoot = resolve9(opts.root);
3750
+ if (opts.config.routing?.plugin === "nx" && existsSync14(nxRoot)) {
3751
+ watch(nxRoot, { recursive: true }, (_event, filename) => {
3752
+ if (!filename || !NX_MANIFEST_PATTERN.test(filename)) return;
3753
+ rebuild();
3754
+ });
3755
+ }
3756
+ const configDir = resolve9(opts.root);
3757
+ if (existsSync14(configDir)) {
3544
3758
  watch(configDir, (_event, filename) => {
3545
3759
  if (!filename || !/doc-bridge\.config/.test(filename)) return;
3546
3760
  rebuild();
@@ -3716,15 +3930,15 @@ var docBridgePatternPayload = () => ({
3716
3930
  });
3717
3931
 
3718
3932
  // src/cli/demo.ts
3719
- import { cpSync, existsSync as existsSync15, mkdtempSync, readFileSync as readFileSync14, rmSync } from "fs";
3933
+ import { cpSync, existsSync as existsSync16, mkdtempSync, readFileSync as readFileSync15, rmSync } from "fs";
3720
3934
  import { tmpdir } from "os";
3721
- import { dirname as dirname6, join as join15, resolve as resolve10 } from "path";
3935
+ import { dirname as dirname7, join as join15, resolve as resolve11 } from "path";
3722
3936
  import { fileURLToPath } from "url";
3723
3937
 
3724
3938
  // src/mcp/install.ts
3725
- import { existsSync as existsSync14, mkdirSync as mkdirSync3, readFileSync as readFileSync13, writeFileSync as writeFileSync3 } from "fs";
3939
+ import { existsSync as existsSync15, mkdirSync as mkdirSync3, readFileSync as readFileSync14, writeFileSync as writeFileSync3 } from "fs";
3726
3940
  import { homedir } from "os";
3727
- import { dirname as dirname5, join as join14, resolve as resolve9 } from "path";
3941
+ import { dirname as dirname6, join as join14, resolve as resolve10 } from "path";
3728
3942
  var SERVER_NAME = "ak-docs";
3729
3943
  var mcpServerEntry = (root) => ({
3730
3944
  command: "npx",
@@ -3732,26 +3946,26 @@ var mcpServerEntry = (root) => ({
3732
3946
  cwd: root
3733
3947
  });
3734
3948
  var readJson = (path) => {
3735
- if (!existsSync14(path)) return {};
3949
+ if (!existsSync15(path)) return {};
3736
3950
  try {
3737
- const parsed = JSON.parse(readFileSync13(path, "utf8"));
3951
+ const parsed = JSON.parse(readFileSync14(path, "utf8"));
3738
3952
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
3739
3953
  } catch {
3740
3954
  return {};
3741
3955
  }
3742
3956
  };
3743
3957
  var writeJson = (path, value) => {
3744
- mkdirSync3(dirname5(path), { recursive: true });
3958
+ mkdirSync3(dirname6(path), { recursive: true });
3745
3959
  writeFileSync3(path, `${JSON.stringify(value, null, 2)}
3746
3960
  `, "utf8");
3747
3961
  };
3748
3962
  var resolveTargetPath = (target, root) => {
3749
- if (target === "cursor") return resolve9(root, ".cursor", "mcp.json");
3963
+ if (target === "cursor") return resolve10(root, ".cursor", "mcp.json");
3750
3964
  return join14(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
3751
3965
  };
3752
3966
  var installMcpConfig = (root, target) => {
3753
3967
  const configPath = resolveTargetPath(target, root);
3754
- const created = !existsSync14(configPath);
3968
+ const created = !existsSync15(configPath);
3755
3969
  const existing = readJson(configPath);
3756
3970
  const servers = existing.mcpServers && typeof existing.mcpServers === "object" && !Array.isArray(existing.mcpServers) ? { ...existing.mcpServers } : {};
3757
3971
  servers[SERVER_NAME] = mcpServerEntry(root);
@@ -3776,7 +3990,7 @@ var installMcpConfig = (root, target) => {
3776
3990
  var mcpSnippet = (root) => JSON.stringify({ mcpServers: { [SERVER_NAME]: mcpServerEntry(root) } }, null, 2);
3777
3991
 
3778
3992
  // src/cli/demo.ts
3779
- var packageRoot = resolve10(dirname6(fileURLToPath(import.meta.url)), "..", "..");
3993
+ var packageRoot = resolve11(dirname7(fileURLToPath(import.meta.url)), "..", "..");
3780
3994
  var fixturePath = (fixture) => {
3781
3995
  if (fixture === "monorepo") {
3782
3996
  return join15(packageRoot, "examples", "demo-monorepo");
@@ -3797,10 +4011,10 @@ var formatHandoffText = (handoff) => {
3797
4011
  var runDemo = (root, config, fixture = "example", options = {}) => {
3798
4012
  const targetPackage = fixture === "monorepo" ? "auth" : "example";
3799
4013
  const fixtureDir = fixturePath(fixture);
3800
- if (options.copyFixture && existsSync15(fixtureDir)) {
4014
+ if (options.copyFixture && existsSync16(fixtureDir)) {
3801
4015
  for (const rel of ["doc-bridge.config.json", "docs", "packages", "pnpm-workspace.yaml", "package.json"]) {
3802
4016
  const src = join15(fixtureDir, rel);
3803
- if (!existsSync15(src)) continue;
4017
+ if (!existsSync16(src)) continue;
3804
4018
  const dest = join15(root, rel);
3805
4019
  cpSync(src, dest, { recursive: true });
3806
4020
  }
@@ -3859,11 +4073,11 @@ var withDemoWorkspace = (fixture, fn) => {
3859
4073
  const dir = mkdtempSync(join15(tmpdir(), "ak-docs-demo-"));
3860
4074
  try {
3861
4075
  const fixtureDir = fixturePath(fixture);
3862
- if (!existsSync15(fixtureDir)) {
4076
+ if (!existsSync16(fixtureDir)) {
3863
4077
  throw new Error(`Demo fixture "${fixture}" not found at ${fixtureDir}`);
3864
4078
  }
3865
4079
  cpSync(fixtureDir, dir, { recursive: true });
3866
- const config = JSON.parse(readFileSync14(join15(dir, "doc-bridge.config.json"), "utf8"));
4080
+ const config = JSON.parse(readFileSync15(join15(dir, "doc-bridge.config.json"), "utf8"));
3867
4081
  return fn(dir, config);
3868
4082
  } finally {
3869
4083
  rmSync(dir, { recursive: true, force: true });
@@ -4074,8 +4288,8 @@ var formatDoctorText = (report) => {
4074
4288
  };
4075
4289
 
4076
4290
  // src/mcp/server.ts
4077
- import { readFileSync as readFileSync15, realpathSync as realpathSync6 } from "fs";
4078
- import { relative as relative4, resolve as resolve11 } from "path";
4291
+ import { readFileSync as readFileSync16, realpathSync as realpathSync7 } from "fs";
4292
+ import { relative as relative5, resolve as resolve12 } from "path";
4079
4293
  import { z as z6, ZodError } from "zod";
4080
4294
  var MCP_TOOLS = [
4081
4295
  {
@@ -4197,12 +4411,12 @@ var findDocPath = (index, args) => {
4197
4411
  return doc.path;
4198
4412
  };
4199
4413
  var resolveDocPath = (root, relPath) => {
4200
- const rootAbs = realpathSync6.native(root);
4201
- const unresolved = resolve11(rootAbs, relPath);
4202
- const unresolvedRel = relative4(rootAbs, unresolved);
4414
+ const rootAbs = realpathSync7.native(root);
4415
+ const unresolved = resolve12(rootAbs, relPath);
4416
+ const unresolvedRel = relative5(rootAbs, unresolved);
4203
4417
  if (unresolvedRel.startsWith("..")) throw new Error("doc.get path escapes project root");
4204
- const abs = realpathSync6.native(unresolved);
4205
- const rel = relative4(rootAbs, abs);
4418
+ const abs = realpathSync7.native(unresolved);
4419
+ const rel = relative5(rootAbs, abs);
4206
4420
  if (rel.startsWith("..")) throw new Error("doc.get path escapes project root");
4207
4421
  return abs;
4208
4422
  };
@@ -4236,7 +4450,7 @@ var handleMcpRequest = (ctx, request) => {
4236
4450
  }
4237
4451
  if (name === "doc.get") {
4238
4452
  const relPath = findDocPath(index(), parseToolArgs("doc.get", DocGetArgsSchema, args));
4239
- return textResult(readFileSync15(resolveDocPath(ctx.root, relPath), "utf8"));
4453
+ return textResult(readFileSync16(resolveDocPath(ctx.root, relPath), "utf8"));
4240
4454
  }
4241
4455
  if (name === "gate.status") return textResult(runGates(ctx.root, ctx.config));
4242
4456
  if (name === "retriever.query") {
@@ -4505,12 +4719,12 @@ var readIndexedDoc = (root, config, idOrPath) => {
4505
4719
  const index = loadDocBridgeIndex(root, config);
4506
4720
  const entry = index.knowledge.find((doc) => doc.id === idOrPath || doc.path === idOrPath);
4507
4721
  if (!entry) throw new Error(`Unknown indexed doc "${idOrPath}". Try: search ${idOrPath}`);
4508
- const abs = resolve12(root, entry.path);
4509
- const rootAbs = resolve12(root);
4722
+ const abs = resolve13(root, entry.path);
4723
+ const rootAbs = resolve13(root);
4510
4724
  if (abs !== rootAbs && !abs.startsWith(`${rootAbs}/`)) {
4511
4725
  throw new Error(`Indexed doc escapes project root: ${entry.path}`);
4512
4726
  }
4513
- return readFileSync16(abs, "utf8");
4727
+ return readFileSync17(abs, "utf8");
4514
4728
  };
4515
4729
  var runAskRepl = async (root, config) => {
4516
4730
  const index = loadDocBridgeIndex(root, config);
@@ -4586,8 +4800,8 @@ var diagnosticNextCommands = (config, result) => {
4586
4800
  ];
4587
4801
  };
4588
4802
  var writeIfMissing = (path, contents) => {
4589
- if (existsSync16(path)) return false;
4590
- mkdirSync5(dirname7(path), { recursive: true });
4803
+ if (existsSync17(path)) return false;
4804
+ mkdirSync5(dirname8(path), { recursive: true });
4591
4805
  writeFileSync4(path, contents, "utf8");
4592
4806
  return true;
4593
4807
  };
@@ -4691,7 +4905,7 @@ var scaffoldWorkspaceDocs = (root, config) => {
4691
4905
  const created = [];
4692
4906
  const skipped = [];
4693
4907
  for (const pkg of discoverPnpmPackages(root, config)) {
4694
- const path = resolve12(root, config.corpus.agent.root, "packages", `${pkg.id}.md`);
4908
+ const path = resolve13(root, config.corpus.agent.root, "packages", `${pkg.id}.md`);
4695
4909
  if (writeIfMissing(path, workspaceDocDraft(pkg.id, pkg.path))) created.push(path);
4696
4910
  else skipped.push(path);
4697
4911
  }
@@ -4701,11 +4915,11 @@ var bootstrapAgentDocs = (root, config) => {
4701
4915
  const created = [];
4702
4916
  const skipped = [];
4703
4917
  for (const doc of scanHumanDocRecords(root, config)) {
4704
- const raw = readFileSync16(doc.path, "utf8");
4918
+ const raw = readFileSync17(doc.path, "utf8");
4705
4919
  const body = raw.replace(/^---\n[\s\S]*?\n---\n?/, "");
4706
4920
  const title = firstHeading(body) ?? doc.id;
4707
4921
  const description = firstParagraph(body);
4708
- const draftPath = resolve12(root, config.corpus.agent.root, "human", `${doc.id}.md`);
4922
+ const draftPath = resolve13(root, config.corpus.agent.root, "human", `${doc.id}.md`);
4709
4923
  const draft = [
4710
4924
  "---",
4711
4925
  "type: knowledge",
@@ -4769,8 +4983,8 @@ var runCli = (argv) => {
4769
4983
  return 1;
4770
4984
  }
4771
4985
  try {
4772
- const abs = resolve12(file);
4773
- const raw = readFileSync16(abs, "utf8");
4986
+ const abs = resolve13(file);
4987
+ const raw = readFileSync17(abs, "utf8");
4774
4988
  const handoff = parseAgentHandoff(JSON.parse(raw));
4775
4989
  writeJson2({ ok: true, handoff });
4776
4990
  return 0;
@@ -4783,10 +4997,10 @@ var runCli = (argv) => {
4783
4997
  if (command === "init") {
4784
4998
  const root = process.cwd();
4785
4999
  const withDemo = flags.has("--demo") || !flags.has("--no-demo");
4786
- const configFile = resolve12(root, configPath ?? "doc-bridge.config.json");
4787
- const docsIndex = resolve12(root, "docs/for-agents/INDEX.md");
4788
- const exampleDoc = resolve12(root, "docs/for-agents/packages/example.md");
4789
- const agentsMd = resolve12(root, "AGENTS.md");
5000
+ const configFile = resolve13(root, configPath ?? "doc-bridge.config.json");
5001
+ const docsIndex = resolve13(root, "docs/for-agents/INDEX.md");
5002
+ const exampleDoc = resolve13(root, "docs/for-agents/packages/example.md");
5003
+ const agentsMd = resolve13(root, "AGENTS.md");
4790
5004
  const configWritten = writeIfMissing(configFile, initConfigContents(configFile, withDemo));
4791
5005
  const indexWritten = writeIfMissing(
4792
5006
  docsIndex,
@@ -4794,7 +5008,7 @@ var runCli = (argv) => {
4794
5008
  );
4795
5009
  const exampleWritten = withDemo ? writeIfMissing(exampleDoc, exampleAgentDoc) : false;
4796
5010
  const agentsWritten = writeIfMissing(agentsMd, agentsMdSnippet);
4797
- if (withDemo) writeIfMissing(resolve12(root, "src/.gitkeep"), "");
5011
+ if (withDemo) writeIfMissing(resolve13(root, "src/.gitkeep"), "");
4798
5012
  const scaffold = flags.has("--scaffold-workspaces") ? scaffoldWorkspaceDocs(root, loadProject(configFile).config) : void 0;
4799
5013
  writeJson2({
4800
5014
  ok: true,
@@ -5037,8 +5251,8 @@ var runCli = (argv) => {
5037
5251
  const { config, root } = loadProject(configPath);
5038
5252
  const report = runDoctor(root, config);
5039
5253
  if (flags.has("--write-badge")) {
5040
- const badgePath = resolve12(root, ".doc-bridge", "coverage-badge.json");
5041
- mkdirSync5(dirname7(badgePath), { recursive: true });
5254
+ const badgePath = resolve13(root, ".doc-bridge", "coverage-badge.json");
5255
+ mkdirSync5(dirname8(badgePath), { recursive: true });
5042
5256
  writeFileSync4(badgePath, `${formatDoctorBadgeJson(report.badge)}
5043
5257
  `, "utf8");
5044
5258
  }