@swarmvaultai/engine 0.7.25 → 0.7.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  uniqueBy,
23
23
  writeFileIfChanged,
24
24
  writeJsonFile
25
- } from "./chunk-MB7HPUTR.js";
25
+ } from "./chunk-N56FAH4N.js";
26
26
  import {
27
27
  estimatePageTokens,
28
28
  estimateTokens,
@@ -493,8 +493,11 @@ async function autoCommitWikiChanges(rootDir, operation, detail, options) {
493
493
  }
494
494
 
495
495
  // src/graph-export.ts
496
+ import { readFileSync } from "fs";
496
497
  import fs2 from "fs/promises";
498
+ import { createRequire } from "module";
497
499
  import path2 from "path";
500
+ import matter from "gray-matter";
498
501
 
499
502
  // src/graph-interchange.ts
500
503
  function exportHyperedgeNodeId(hyperedge) {
@@ -940,6 +943,15 @@ document.getElementById("page-filter").addEventListener("input", function(e) {
940
943
  }
941
944
 
942
945
  // src/graph-export.ts
946
+ var _visNetworkJs;
947
+ function loadVisNetworkJs() {
948
+ if (!_visNetworkJs) {
949
+ const require3 = createRequire(import.meta.url);
950
+ const pkgDir = path2.dirname(require3.resolve("vis-network/package.json"));
951
+ _visNetworkJs = readFileSync(path2.join(pkgDir, "standalone/umd/vis-network.min.js"), "utf8");
952
+ }
953
+ return _visNetworkJs;
954
+ }
943
955
  var NODE_COLORS = {
944
956
  source: "#f59e0b",
945
957
  module: "#fb7185",
@@ -1340,7 +1352,7 @@ function renderHtmlStandalone(graph) {
1340
1352
  <head>
1341
1353
  <meta charset="utf-8">
1342
1354
  <title>SwarmVault Graph</title>
1343
- <script src="https://unpkg.com/vis-network@9/standalone/umd/vis-network.min.js"></script>
1355
+ <script>${loadVisNetworkJs()}</script>
1344
1356
  <style>
1345
1357
  * { margin: 0; padding: 0; box-sizing: border-box; }
1346
1358
  body { font-family: system-ui, sans-serif; display: flex; height: 100vh; background: #0f172a; color: #e2e8f0; }
@@ -1593,14 +1605,27 @@ function deduplicateFileName(baseName, used) {
1593
1605
  used.add(name);
1594
1606
  return name;
1595
1607
  }
1596
- async function exportObsidianVault(rootDir, outputDir) {
1597
- const graph = await loadGraph(rootDir);
1598
- const resolvedOutputDir = path2.resolve(outputDir);
1599
- await ensureDir(resolvedOutputDir);
1600
- const nodesById = graphNodeById(graph);
1601
- const communities = sortedCommunities(graph);
1608
+ function typePluralDir(nodeType) {
1609
+ const map = {
1610
+ source: "sources",
1611
+ module: "modules",
1612
+ symbol: "symbols",
1613
+ concept: "concepts",
1614
+ entity: "entities",
1615
+ rationale: "rationales"
1616
+ };
1617
+ return map[nodeType] ?? "other";
1618
+ }
1619
+ function obsidianNodeSlug(node, pageById2) {
1620
+ if (node.pageId) {
1621
+ const page = pageById2.get(node.pageId);
1622
+ if (page) return path2.basename(page.path, ".md");
1623
+ }
1624
+ return slugify(node.label);
1625
+ }
1626
+ function buildAdjacency(edges) {
1602
1627
  const adjacency = /* @__PURE__ */ new Map();
1603
- for (const edge of graph.edges) {
1628
+ for (const edge of edges) {
1604
1629
  if (!adjacency.has(edge.source)) adjacency.set(edge.source, []);
1605
1630
  if (!adjacency.has(edge.target)) adjacency.set(edge.target, []);
1606
1631
  adjacency.get(edge.source).push({
@@ -1618,44 +1643,164 @@ async function exportObsidianVault(rootDir, outputDir) {
1618
1643
  direction: "in"
1619
1644
  });
1620
1645
  }
1621
- const usedFileNames = /* @__PURE__ */ new Set();
1622
- const nodeFileName = /* @__PURE__ */ new Map();
1623
- for (const node of [...graph.nodes].sort((a, b) => a.label.localeCompare(b.label) || a.id.localeCompare(b.id))) {
1624
- const name = deduplicateFileName(safeFileName(node.label), usedFileNames);
1625
- nodeFileName.set(node.id, name);
1646
+ return adjacency;
1647
+ }
1648
+ async function listFilesRecursive2(dir, base = "") {
1649
+ const results = [];
1650
+ let entries;
1651
+ try {
1652
+ entries = await fs2.readdir(dir, { withFileTypes: true });
1653
+ } catch {
1654
+ return results;
1626
1655
  }
1627
- let fileCount = 0;
1656
+ for (const entry of entries) {
1657
+ const rel = base ? `${base}/${entry.name}` : entry.name;
1658
+ if (entry.isDirectory()) {
1659
+ results.push(...await listFilesRecursive2(path2.join(dir, entry.name), rel));
1660
+ } else {
1661
+ results.push(rel);
1662
+ }
1663
+ }
1664
+ return results;
1665
+ }
1666
+ function connectionsSection(nodeIds, adjacency, nodesById, wikilinkTarget) {
1667
+ const seen = /* @__PURE__ */ new Set();
1668
+ const lines = [];
1669
+ for (const nodeId of nodeIds) {
1670
+ for (const entry of adjacency.get(nodeId) ?? []) {
1671
+ const key = `${entry.neighborId}:${entry.relation}`;
1672
+ if (seen.has(key)) continue;
1673
+ seen.add(key);
1674
+ const neighbor = nodesById.get(entry.neighborId);
1675
+ if (!neighbor) continue;
1676
+ const target = wikilinkTarget.get(entry.neighborId);
1677
+ if (!target) continue;
1678
+ lines.push(`- [[${target}|${neighbor.label}]] \u2014 ${entry.relation} (${entry.evidenceClass}, ${entry.confidence.toFixed(2)})`);
1679
+ }
1680
+ }
1681
+ return lines;
1682
+ }
1683
+ async function exportObsidianVault(rootDir, outputDir) {
1684
+ const graph = await loadGraph(rootDir);
1685
+ const { paths } = await loadVaultConfig(rootDir);
1686
+ const resolvedOutputDir = path2.resolve(outputDir);
1687
+ await ensureDir(resolvedOutputDir);
1688
+ const nodesById = graphNodeById(graph);
1689
+ const pageById2 = graphPageById(graph);
1690
+ const communities = sortedCommunities(graph);
1691
+ const adjacency = buildAdjacency(graph.edges);
1692
+ const nodesByPageId = /* @__PURE__ */ new Map();
1628
1693
  for (const node of graph.nodes) {
1629
- const fileName = nodeFileName.get(node.id);
1630
- const lines = [
1631
- "---",
1632
- `id: ${JSON.stringify(node.id)}`,
1633
- `type: ${JSON.stringify(node.type)}`,
1634
- `community: ${JSON.stringify(node.communityId ?? null)}`,
1635
- `confidence: ${node.confidence ?? null}`,
1636
- `source_class: ${JSON.stringify(node.sourceClass ?? null)}`,
1637
- `tags: ${JSON.stringify(node.tags ?? [])}`,
1638
- "---",
1639
- "",
1640
- `# ${node.label}`,
1641
- ""
1642
- ];
1643
- const neighbors = adjacency.get(node.id) ?? [];
1644
- if (neighbors.length > 0) {
1645
- lines.push("## Connections", "");
1646
- for (const neighbor of neighbors) {
1647
- const neighborNode = nodesById.get(neighbor.neighborId);
1648
- if (!neighborNode) continue;
1649
- const neighborFile = nodeFileName.get(neighbor.neighborId) ?? safeFileName(neighborNode.label);
1650
- lines.push(`- [[${neighborFile}]] \u2014 ${neighbor.relation} (${neighbor.evidenceClass}, ${neighbor.confidence.toFixed(2)})`);
1694
+ if (node.pageId && pageById2.has(node.pageId)) {
1695
+ const list = nodesByPageId.get(node.pageId) ?? [];
1696
+ list.push(node);
1697
+ nodesByPageId.set(node.pageId, list);
1698
+ }
1699
+ }
1700
+ const orphanNodes = graph.nodes.filter((node) => !node.pageId || !pageById2.has(node.pageId));
1701
+ const usedOrphanSlugs = /* @__PURE__ */ new Set();
1702
+ const orphanFilePath = /* @__PURE__ */ new Map();
1703
+ for (const node of [...orphanNodes].sort((a, b) => a.label.localeCompare(b.label) || a.id.localeCompare(b.id))) {
1704
+ const slug = deduplicateFileName(obsidianNodeSlug(node, pageById2), usedOrphanSlugs);
1705
+ orphanFilePath.set(node.id, `graph/nodes/${typePluralDir(node.type)}/${slug}.md`);
1706
+ }
1707
+ const wikilinkTarget = /* @__PURE__ */ new Map();
1708
+ for (const node of graph.nodes) {
1709
+ if (node.pageId) {
1710
+ const page = pageById2.get(node.pageId);
1711
+ if (page) {
1712
+ wikilinkTarget.set(node.id, page.path.replace(/\.md$/, ""));
1713
+ continue;
1651
1714
  }
1652
- lines.push("");
1653
1715
  }
1654
- await fs2.writeFile(path2.join(resolvedOutputDir, `${fileName}.md`), lines.join("\n"), "utf8");
1716
+ const orphanPath = orphanFilePath.get(node.id);
1717
+ if (orphanPath) {
1718
+ wikilinkTarget.set(node.id, orphanPath.replace(/\.md$/, ""));
1719
+ }
1720
+ }
1721
+ let fileCount = 0;
1722
+ const wikiFiles = await listFilesRecursive2(paths.wikiDir);
1723
+ const pageByPath = new Map(graph.pages.map((p) => [p.path, p]));
1724
+ for (const relPath of wikiFiles) {
1725
+ if (!relPath.endsWith(".md")) continue;
1726
+ const srcFile = path2.join(paths.wikiDir, relPath);
1727
+ const destFile = path2.join(resolvedOutputDir, relPath);
1728
+ await ensureDir(path2.dirname(destFile));
1729
+ let rawContent;
1730
+ try {
1731
+ rawContent = await fs2.readFile(srcFile, "utf8");
1732
+ } catch {
1733
+ continue;
1734
+ }
1735
+ const matchingPage = pageByPath.get(relPath);
1736
+ const pageNodes = matchingPage ? nodesByPageId.get(matchingPage.id) ?? [] : [];
1737
+ const parsed = matter(rawContent);
1738
+ const data = parsed.data;
1739
+ if (pageNodes.length > 0) {
1740
+ const primaryNode = pageNodes[0];
1741
+ if (primaryNode.communityId) {
1742
+ data.graph_community = primaryNode.communityId;
1743
+ }
1744
+ const title = data.title ?? "";
1745
+ const nodeAliases = pageNodes.map((n) => n.label).filter((label) => label.toLowerCase() !== title.toLowerCase());
1746
+ const existingAliases = Array.isArray(data.aliases) ? data.aliases : [];
1747
+ const mergedAliases = [.../* @__PURE__ */ new Set([...existingAliases, ...nodeAliases])];
1748
+ if (mergedAliases.length > 0) {
1749
+ data.aliases = mergedAliases;
1750
+ }
1751
+ }
1752
+ let outputContent = matter.stringify(parsed.content, data);
1753
+ if (pageNodes.length > 0) {
1754
+ const connLines = connectionsSection(
1755
+ pageNodes.map((n) => n.id),
1756
+ adjacency,
1757
+ nodesById,
1758
+ wikilinkTarget
1759
+ );
1760
+ if (connLines.length > 0) {
1761
+ outputContent = `${outputContent.trimEnd()}
1762
+
1763
+ ## Graph Connections
1764
+
1765
+ ${connLines.join("\n")}
1766
+ `;
1767
+ }
1768
+ }
1769
+ await fs2.writeFile(destFile, outputContent, "utf8");
1770
+ fileCount++;
1771
+ }
1772
+ for (const node of orphanNodes) {
1773
+ const relPath = orphanFilePath.get(node.id);
1774
+ const destFile = path2.join(resolvedOutputDir, relPath);
1775
+ await ensureDir(path2.dirname(destFile));
1776
+ const slug = path2.basename(relPath, ".md");
1777
+ const aliases = node.label !== slug ? [node.label] : [];
1778
+ const frontmatter = {
1779
+ id: node.id,
1780
+ type: node.type,
1781
+ community: node.communityId ?? null,
1782
+ confidence: node.confidence ?? null,
1783
+ source_class: node.sourceClass ?? null,
1784
+ tags: node.tags ?? []
1785
+ };
1786
+ if (aliases.length > 0) {
1787
+ frontmatter.aliases = aliases;
1788
+ }
1789
+ const lines = [`# ${node.label}`, ""];
1790
+ const connLines = connectionsSection([node.id], adjacency, nodesById, wikilinkTarget);
1791
+ if (connLines.length > 0) {
1792
+ lines.push("## Connections", "", ...connLines, "");
1793
+ }
1794
+ const content = matter.stringify(lines.join("\n"), frontmatter);
1795
+ await fs2.writeFile(destFile, content, "utf8");
1655
1796
  fileCount++;
1656
1797
  }
1657
1798
  const usedCommunityFileNames = /* @__PURE__ */ new Set();
1658
1799
  for (const community of communities) {
1800
+ const wikiCommunityPage = graph.pages.find(
1801
+ (p) => p.kind === "community_summary" && p.nodeIds.some((nid) => community.nodeIds.includes(nid))
1802
+ );
1803
+ if (wikiCommunityPage) continue;
1659
1804
  const memberNodes = community.nodeIds.map((id) => nodesById.get(id)).filter((n2) => Boolean(n2));
1660
1805
  const memberIdSet = new Set(community.nodeIds);
1661
1806
  let internalEdges = 0;
@@ -1674,35 +1819,102 @@ async function exportObsidianVault(rootDir, outputDir) {
1674
1819
  return nbNode && nbNode.communityId !== community.id;
1675
1820
  });
1676
1821
  });
1677
- const communityFileName = deduplicateFileName(`_Community_${safeFileName(community.label)}`, usedCommunityFileNames);
1678
- const lines = [
1679
- "---",
1680
- `id: ${JSON.stringify(community.id)}`,
1681
- `node_count: ${memberNodes.length}`,
1682
- `cohesion: ${cohesion.toFixed(4)}`,
1683
- "---",
1684
- "",
1685
- `# ${community.label}`,
1686
- "",
1687
- "## Members",
1688
- ""
1689
- ];
1822
+ const communitySlug = deduplicateFileName(safeFileName(community.label), usedCommunityFileNames);
1823
+ const destFile = path2.join(resolvedOutputDir, "graph", "communities", `${communitySlug}.md`);
1824
+ await ensureDir(path2.dirname(destFile));
1825
+ const lines = [`# ${community.label}`, "", "## Members", ""];
1690
1826
  for (const member of memberNodes) {
1691
- const memberFile = nodeFileName.get(member.id) ?? safeFileName(member.label);
1692
- lines.push(`- [[${memberFile}]]`);
1827
+ const target = wikilinkTarget.get(member.id);
1828
+ if (target) {
1829
+ lines.push(`- [[${target}|${member.label}]]`);
1830
+ } else {
1831
+ lines.push(`- ${member.label}`);
1832
+ }
1693
1833
  }
1694
1834
  lines.push("");
1695
1835
  if (bridgeNodes.length > 0) {
1696
1836
  lines.push("## Bridge Nodes", "");
1697
1837
  for (const bridge of bridgeNodes) {
1698
- const bridgeFile = nodeFileName.get(bridge.id) ?? safeFileName(bridge.label);
1699
- lines.push(`- [[${bridgeFile}]]`);
1838
+ const target = wikilinkTarget.get(bridge.id);
1839
+ if (target) {
1840
+ lines.push(`- [[${target}|${bridge.label}]]`);
1841
+ } else {
1842
+ lines.push(`- ${bridge.label}`);
1843
+ }
1700
1844
  }
1701
1845
  lines.push("");
1702
1846
  }
1703
- await fs2.writeFile(path2.join(resolvedOutputDir, `${communityFileName}.md`), lines.join("\n"), "utf8");
1847
+ const frontmatter = {
1848
+ id: community.id,
1849
+ node_count: memberNodes.length,
1850
+ cohesion: Number(cohesion.toFixed(4))
1851
+ };
1852
+ const content = matter.stringify(lines.join("\n"), frontmatter);
1853
+ await fs2.writeFile(destFile, content, "utf8");
1704
1854
  fileCount++;
1705
1855
  }
1856
+ const outputsAssetsDir = path2.join(paths.wikiDir, "outputs", "assets");
1857
+ try {
1858
+ const assetFiles = await listFilesRecursive2(outputsAssetsDir);
1859
+ for (const relAsset of assetFiles) {
1860
+ const src = path2.join(outputsAssetsDir, relAsset);
1861
+ const dest = path2.join(resolvedOutputDir, "outputs", "assets", relAsset);
1862
+ await ensureDir(path2.dirname(dest));
1863
+ await fs2.copyFile(src, dest);
1864
+ fileCount++;
1865
+ }
1866
+ } catch {
1867
+ }
1868
+ try {
1869
+ const rawAssetFiles = await listFilesRecursive2(paths.rawAssetsDir);
1870
+ for (const relAsset of rawAssetFiles) {
1871
+ const src = path2.join(paths.rawAssetsDir, relAsset);
1872
+ const dest = path2.join(resolvedOutputDir, "raw", "assets", relAsset);
1873
+ await ensureDir(path2.dirname(dest));
1874
+ await fs2.copyFile(src, dest);
1875
+ fileCount++;
1876
+ }
1877
+ } catch {
1878
+ }
1879
+ const obsidianDir = path2.join(resolvedOutputDir, ".obsidian");
1880
+ await ensureDir(obsidianDir);
1881
+ const projectIds = Object.keys(
1882
+ graph.pages.reduce(
1883
+ (acc, page) => {
1884
+ for (const pid of page.projectIds) acc[pid] = true;
1885
+ return acc;
1886
+ },
1887
+ {}
1888
+ )
1889
+ );
1890
+ const colorGroups = projectIds.map((pid, index) => ({
1891
+ query: `tag:#project/${pid}`,
1892
+ color: ["#0ea5e9", "#22c55e", "#f59e0b", "#8b5cf6", "#fb7185", "#14b8a6"][index % 6]
1893
+ }));
1894
+ await fs2.writeFile(
1895
+ path2.join(obsidianDir, "app.json"),
1896
+ JSON.stringify(
1897
+ { newFileLocation: "folder", newFileFolderPath: "outputs", attachmentFolderPath: "raw/assets", useMarkdownLinks: false },
1898
+ null,
1899
+ 2
1900
+ ),
1901
+ "utf8"
1902
+ );
1903
+ await fs2.writeFile(
1904
+ path2.join(obsidianDir, "core-plugins.json"),
1905
+ JSON.stringify(["file-explorer", "global-search", "graph", "backlink", "tag-pane", "page-preview", "outline"], null, 2),
1906
+ "utf8"
1907
+ );
1908
+ await fs2.writeFile(
1909
+ path2.join(obsidianDir, "graph.json"),
1910
+ JSON.stringify(
1911
+ { colorGroups, "collapse-filter": false, search: "", showTags: true, showAttachments: false, showOrphans: true },
1912
+ null,
1913
+ 2
1914
+ ),
1915
+ "utf8"
1916
+ );
1917
+ fileCount += 3;
1706
1918
  return { format: "obsidian", outputPath: resolvedOutputDir, fileCount };
1707
1919
  }
1708
1920
  async function exportObsidianCanvas(rootDir, outputPath) {
@@ -2782,7 +2994,7 @@ import fs11 from "fs/promises";
2782
2994
  import path12 from "path";
2783
2995
  import { pathToFileURL } from "url";
2784
2996
  import { Readability } from "@mozilla/readability";
2785
- import matter3 from "gray-matter";
2997
+ import matter4 from "gray-matter";
2786
2998
  import ignore from "ignore";
2787
2999
  import { isText } from "istextorbinary";
2788
3000
  import { JSDOM as JSDOM2 } from "jsdom";
@@ -2797,9 +3009,9 @@ import YAML2 from "yaml";
2797
3009
 
2798
3010
  // src/code-tree-sitter.ts
2799
3011
  import fs5 from "fs/promises";
2800
- import { createRequire } from "module";
3012
+ import { createRequire as createRequire2 } from "module";
2801
3013
  import path5 from "path";
2802
- var require2 = createRequire(import.meta.url);
3014
+ var require2 = createRequire2(import.meta.url);
2803
3015
  var TREE_SITTER_RUNTIME_PACKAGE = "@vscode/tree-sitter-wasm";
2804
3016
  var TREE_SITTER_EXTRA_GRAMMARS_PACKAGE = "tree-sitter-wasms";
2805
3017
  var SWIFT_TREE_SITTER_OPT_IN_ENV = "SWARMVAULT_ENABLE_SWIFT_TREE_SITTER";
@@ -2926,8 +3138,8 @@ function singleLineSignature(value) {
2926
3138
  180
2927
3139
  );
2928
3140
  }
2929
- function makeSymbolId(sourceId, name, seen) {
2930
- const base = slugify(name);
3141
+ function makeSymbolId(sourceId, name, kind, seen) {
3142
+ const base = `${slugify(name)}.${kind}`;
2931
3143
  const count = (seen.get(base) ?? 0) + 1;
2932
3144
  seen.set(base, count);
2933
3145
  return `symbol:${sourceId}:${count === 1 ? base : `${base}-${count}`}`;
@@ -3009,7 +3221,7 @@ function finalizeCodeAnalysis(manifest, language, imports, draftSymbols, exportL
3009
3221
  }
3010
3222
  const seenSymbolIds = /* @__PURE__ */ new Map();
3011
3223
  const symbols = draftSymbols.map((symbol) => ({
3012
- id: makeSymbolId(manifest.sourceId, symbol.name, seenSymbolIds),
3224
+ id: makeSymbolId(manifest.sourceId, symbol.name, symbol.kind, seenSymbolIds),
3013
3225
  name: symbol.name,
3014
3226
  kind: symbol.kind,
3015
3227
  signature: symbol.signature,
@@ -6272,7 +6484,7 @@ function htmlCodeAnalysis(manifest, rootNode, diagnostics) {
6272
6484
  }
6273
6485
  continue;
6274
6486
  }
6275
- if (tagName && tagName.includes("-")) {
6487
+ if (tagName?.includes("-")) {
6276
6488
  if (!seenSymbolNames.has(tagName)) {
6277
6489
  seenSymbolNames.add(tagName);
6278
6490
  draftSymbols.push({
@@ -6818,8 +7030,8 @@ function isNodeExported(node) {
6818
7030
  )
6819
7031
  );
6820
7032
  }
6821
- function makeSymbolId2(scope, name, seen) {
6822
- const base = slugify(name);
7033
+ function makeSymbolId2(scope, name, kind, seen) {
7034
+ const base = `${slugify(name)}.${kind}`;
6823
7035
  const count = (seen.get(base) ?? 0) + 1;
6824
7036
  seen.set(base, count);
6825
7037
  return `symbol:${scope}:${count === 1 ? base : `${base}-${count}`}`;
@@ -6986,7 +7198,7 @@ function finalizeCodeAnalysis2(manifest, language, imports, draftSymbols, export
6986
7198
  const seenSymbolIds = /* @__PURE__ */ new Map();
6987
7199
  const symbolScope = metadata?.namespace ? `ns:${slugify(metadata.namespace)}` : manifest.sourceId;
6988
7200
  const symbols = draftSymbols.map((symbol) => ({
6989
- id: makeSymbolId2(symbolScope, symbol.name, seenSymbolIds),
7201
+ id: makeSymbolId2(symbolScope, symbol.name, symbol.kind, seenSymbolIds),
6990
7202
  name: symbol.name,
6991
7203
  kind: symbol.kind,
6992
7204
  signature: symbol.signature,
@@ -7400,6 +7612,81 @@ function manifestBasenameWithoutExtension(manifest) {
7400
7612
  const target = manifest.repoRelativePath ?? manifest.originalPath ?? manifest.storedPath;
7401
7613
  return path6.posix.basename(stripCodeExtension2(normalizeAlias(target)));
7402
7614
  }
7615
+ async function readNearestTsconfigPaths(startPath, cache) {
7616
+ let current = path6.resolve(startPath);
7617
+ try {
7618
+ const stat = await fs6.stat(current);
7619
+ if (!stat.isDirectory()) {
7620
+ current = path6.dirname(current);
7621
+ }
7622
+ } catch {
7623
+ current = path6.dirname(current);
7624
+ }
7625
+ while (true) {
7626
+ if (cache.has(current)) {
7627
+ const cached = cache.get(current);
7628
+ return cached === null ? void 0 : cached;
7629
+ }
7630
+ const tsconfigPath = path6.join(current, "tsconfig.json");
7631
+ const exists = await fs6.access(tsconfigPath).then(() => true).catch(() => false);
7632
+ if (exists) {
7633
+ const configFile = ts.readConfigFile(tsconfigPath, (p) => ts.sys.readFile(p));
7634
+ if (!configFile.error && configFile.config) {
7635
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, current);
7636
+ const rawPaths = parsed.options.paths;
7637
+ if (rawPaths && Object.keys(rawPaths).length > 0) {
7638
+ const baseUrl = parsed.options.baseUrl ? toPosix(path6.relative(current, parsed.options.baseUrl)) : ".";
7639
+ const config = { baseUrl, paths: rawPaths };
7640
+ cache.set(current, config);
7641
+ return config;
7642
+ }
7643
+ }
7644
+ cache.set(current, null);
7645
+ return void 0;
7646
+ }
7647
+ const parent = path6.dirname(current);
7648
+ if (parent === current) {
7649
+ cache.set(current, null);
7650
+ return void 0;
7651
+ }
7652
+ current = parent;
7653
+ }
7654
+ }
7655
+ function tsconfigPathAliasesForFile(repoRelativePath, config) {
7656
+ const aliases = [];
7657
+ const stripped = stripCodeExtension2(normalizeAlias(repoRelativePath));
7658
+ const indexStripped = stripped.endsWith("/index") ? stripped.slice(0, -"/index".length) : void 0;
7659
+ for (const [pattern, targets] of Object.entries(config.paths)) {
7660
+ for (const target of targets) {
7661
+ if (pattern.includes("*") && target.includes("*")) {
7662
+ const targetPrefix = normalizeAlias(
7663
+ config.baseUrl === "." ? target.replace("*", "") : path6.posix.join(config.baseUrl, target.replace("*", ""))
7664
+ );
7665
+ const patternBase = pattern.replace("*", "");
7666
+ for (const candidate of [stripped, indexStripped]) {
7667
+ if (candidate && candidate.startsWith(targetPrefix)) {
7668
+ aliases.push(patternBase + candidate.slice(targetPrefix.length));
7669
+ }
7670
+ }
7671
+ } else if (!pattern.includes("*") && !target.includes("*")) {
7672
+ const targetNorm = normalizeAlias(config.baseUrl === "." ? target : path6.posix.join(config.baseUrl, target));
7673
+ if (stripped === stripCodeExtension2(targetNorm) || indexStripped === stripCodeExtension2(targetNorm)) {
7674
+ aliases.push(pattern);
7675
+ }
7676
+ }
7677
+ }
7678
+ }
7679
+ if (config.baseUrl !== ".") {
7680
+ const basePrefix = normalizeAlias(config.baseUrl) + "/";
7681
+ if (stripped.startsWith(basePrefix)) {
7682
+ aliases.push(stripped.slice(basePrefix.length));
7683
+ }
7684
+ if (indexStripped && indexStripped.startsWith(basePrefix)) {
7685
+ aliases.push(indexStripped.slice(basePrefix.length));
7686
+ }
7687
+ }
7688
+ return aliases;
7689
+ }
7403
7690
  async function readNearestDartPackageInfo(startPath, cache) {
7404
7691
  let current = path6.resolve(startPath);
7405
7692
  try {
@@ -7562,6 +7849,7 @@ async function buildCodeIndex(rootDir, manifests, analyses) {
7562
7849
  const analysesBySourceId = new Map(analyses.map((analysis) => [analysis.sourceId, analysis]));
7563
7850
  const goModuleCache = /* @__PURE__ */ new Map();
7564
7851
  const dartPackageCache = /* @__PURE__ */ new Map();
7852
+ const tsconfigCache = /* @__PURE__ */ new Map();
7565
7853
  const entries = [];
7566
7854
  for (const manifest of manifests) {
7567
7855
  const analysis = analysesBySourceId.get(manifest.sourceId);
@@ -7583,6 +7871,20 @@ async function buildCodeIndex(rootDir, manifests, analyses) {
7583
7871
  recordAlias(aliases, normalizedModuleName);
7584
7872
  recordAlias(aliases, normalizedNamespace);
7585
7873
  switch (analysis.code.language) {
7874
+ case "javascript":
7875
+ case "jsx":
7876
+ case "typescript":
7877
+ case "tsx": {
7878
+ if (repoRelativePath && manifest.originalPath) {
7879
+ const tsconfigPaths = await readNearestTsconfigPaths(manifest.originalPath, tsconfigCache);
7880
+ if (tsconfigPaths) {
7881
+ for (const alias of tsconfigPathAliasesForFile(repoRelativePath, tsconfigPaths)) {
7882
+ recordAlias(aliases, alias);
7883
+ }
7884
+ }
7885
+ }
7886
+ break;
7887
+ }
7586
7888
  case "python":
7587
7889
  recordAlias(aliases, normalizedModuleName?.replace(/\//g, "."));
7588
7890
  break;
@@ -8039,6 +8341,7 @@ import { parse as parseCsvSync } from "csv-parse/sync";
8039
8341
  import { strFromU8, unzipSync } from "fflate";
8040
8342
  import { JSDOM } from "jsdom";
8041
8343
  import TurndownService from "turndown";
8344
+ import { fetchTranscript } from "youtube-transcript-plus";
8042
8345
  import { z } from "zod";
8043
8346
 
8044
8347
  // src/markdown-ast.ts
@@ -8237,6 +8540,107 @@ async function extractImageWithVision(rootDir, input) {
8237
8540
  await attachment.cleanup();
8238
8541
  }
8239
8542
  }
8543
+ async function extractAudioTranscription(rootDir, input) {
8544
+ let provider;
8545
+ try {
8546
+ provider = await getProviderForTask(rootDir, "audioProvider");
8547
+ } catch (error) {
8548
+ return {
8549
+ artifact: {
8550
+ ...extractionMetadata("audio", input.mimeType, "audio_transcription"),
8551
+ warnings: [`Audio transcription unavailable: ${error instanceof Error ? error.message : "provider not configured"}`]
8552
+ }
8553
+ };
8554
+ }
8555
+ if (!provider.capabilities.has("audio") || !provider.transcribeAudio) {
8556
+ return {
8557
+ artifact: {
8558
+ ...extractionMetadata("audio", input.mimeType, "audio_transcription"),
8559
+ warnings: [`Audio transcription unavailable for provider ${provider.id}. Configure a provider with audio capability.`]
8560
+ }
8561
+ };
8562
+ }
8563
+ try {
8564
+ const result = await provider.transcribeAudio({
8565
+ mimeType: input.mimeType,
8566
+ bytes: input.bytes,
8567
+ fileName: input.fileName
8568
+ });
8569
+ const metadata = {};
8570
+ if (result.duration !== void 0) {
8571
+ metadata.duration = String(result.duration);
8572
+ }
8573
+ if (result.language) {
8574
+ metadata.language = result.language;
8575
+ }
8576
+ return {
8577
+ extractedText: result.text || void 0,
8578
+ artifact: {
8579
+ ...extractionMetadata("audio", input.mimeType, "audio_transcription"),
8580
+ providerId: provider.id,
8581
+ providerModel: provider.model,
8582
+ metadata: Object.keys(metadata).length ? metadata : void 0
8583
+ }
8584
+ };
8585
+ } catch (error) {
8586
+ return {
8587
+ artifact: {
8588
+ ...extractionMetadata("audio", input.mimeType, "audio_transcription"),
8589
+ providerId: provider.id,
8590
+ providerModel: provider.model,
8591
+ warnings: [`Audio transcription failed: ${error instanceof Error ? truncate(error.message, 240) : "unknown error"}`]
8592
+ }
8593
+ };
8594
+ }
8595
+ }
8596
+ async function extractYoutubeTranscript(input) {
8597
+ try {
8598
+ const result = await fetchTranscript(input.videoId, { videoDetails: true });
8599
+ const details = result.videoDetails;
8600
+ const title = details?.title ?? `YouTube ${input.videoId}`;
8601
+ const transcriptText = result.segments?.map((part) => part.text).join(" ") ?? "";
8602
+ const sections = [`# ${title}`];
8603
+ const metaLines = [];
8604
+ if (details?.author) metaLines.push(`**Author:** ${details.author}`);
8605
+ if (details?.lengthSeconds) {
8606
+ const seconds = details.lengthSeconds;
8607
+ const minutes = Math.floor(seconds / 60);
8608
+ const secs = seconds % 60;
8609
+ metaLines.push(`**Duration:** ${minutes}:${String(secs).padStart(2, "0")}`);
8610
+ }
8611
+ if (details?.viewCount) metaLines.push(`**Views:** ${Number(details.viewCount).toLocaleString()}`);
8612
+ metaLines.push(`**URL:** ${input.url}`);
8613
+ if (metaLines.length) {
8614
+ sections.push(metaLines.join("\n"));
8615
+ }
8616
+ if (transcriptText.trim()) {
8617
+ sections.push(`## Transcript
8618
+
8619
+ ${transcriptText.trim()}`);
8620
+ }
8621
+ const extractedText = sections.join("\n\n");
8622
+ const metadata = {};
8623
+ if (details?.title) metadata.title = details.title;
8624
+ if (details?.author) metadata.author = details.author;
8625
+ if (details?.lengthSeconds) metadata.duration = String(details.lengthSeconds);
8626
+ if (details?.viewCount) metadata.viewCount = String(details.viewCount);
8627
+ return {
8628
+ title,
8629
+ extractedText: extractedText || void 0,
8630
+ artifact: {
8631
+ ...extractionMetadata("youtube", "text/html", "youtube_transcript"),
8632
+ metadata: Object.keys(metadata).length ? metadata : void 0
8633
+ }
8634
+ };
8635
+ } catch (error) {
8636
+ return {
8637
+ artifact: {
8638
+ ...extractionMetadata("youtube", "text/html", "youtube_transcript"),
8639
+ warnings: [`YouTube transcript extraction failed: ${error instanceof Error ? truncate(error.message, 240) : "unknown error"}`]
8640
+ }
8641
+ };
8642
+ }
8643
+ }
8240
8644
  function normalizePdfMetadata(raw) {
8241
8645
  if (!raw || typeof raw !== "object") {
8242
8646
  return void 0;
@@ -10034,7 +10438,7 @@ async function extractSlackExportDirectory(directoryPath) {
10034
10438
  // src/logs.ts
10035
10439
  import fs8 from "fs/promises";
10036
10440
  import path8 from "path";
10037
- import matter from "gray-matter";
10441
+ import matter2 from "gray-matter";
10038
10442
  async function resolveUniqueSessionPath(rootDir, operation, title, startedAt) {
10039
10443
  const { paths } = await initWorkspace(rootDir);
10040
10444
  await ensureDir(paths.sessionsDir);
@@ -10087,7 +10491,7 @@ async function recordSession(rootDir, input) {
10087
10491
  token_usage: input.tokenUsage
10088
10492
  }).filter(([, value]) => value !== void 0)
10089
10493
  );
10090
- const content = matter.stringify(
10494
+ const content = matter2.stringify(
10091
10495
  [
10092
10496
  `# ${input.operation[0]?.toUpperCase() ?? ""}${input.operation.slice(1)} Session`,
10093
10497
  "",
@@ -10308,7 +10712,7 @@ async function managedSourceWorkingDir(rootDir, sourceId) {
10308
10712
  // src/watch-state.ts
10309
10713
  import fs10 from "fs/promises";
10310
10714
  import path11 from "path";
10311
- import matter2 from "gray-matter";
10715
+ import matter3 from "gray-matter";
10312
10716
  function pendingEntryKey(entry) {
10313
10717
  return entry.path;
10314
10718
  }
@@ -10420,13 +10824,13 @@ async function markPagesStaleForSources(rootDir, sourceIds) {
10420
10824
  continue;
10421
10825
  }
10422
10826
  const raw = await fs10.readFile(absolutePath, "utf8");
10423
- const parsed = matter2(raw);
10827
+ const parsed = matter3(raw);
10424
10828
  if (parsed.data.freshness === "stale") {
10425
10829
  continue;
10426
10830
  }
10427
10831
  parsed.data.freshness = "stale";
10428
10832
  parsed.data.updated_at = now;
10429
- await writeFileIfChanged(absolutePath, matter2.stringify(parsed.content, parsed.data));
10833
+ await writeFileIfChanged(absolutePath, matter3.stringify(parsed.content, parsed.data));
10430
10834
  }
10431
10835
  return affectedPagePaths;
10432
10836
  }
@@ -10522,6 +10926,9 @@ function inferKind(mimeType, filePath, detectionOptions = {}) {
10522
10926
  if (mimeType === "application/vnd.openxmlformats-officedocument.presentationml.presentation" || mimeType === "application/vnd.ms-powerpoint.presentation.macroenabled.12" || mimeType === "application/vnd.ms-powerpoint.template.macroenabled.12" || mimeType === "application/vnd.openxmlformats-officedocument.presentationml.template" || filePath.toLowerCase().endsWith(".pptx") || filePath.toLowerCase().endsWith(".pptm") || filePath.toLowerCase().endsWith(".potx") || filePath.toLowerCase().endsWith(".potm")) {
10523
10927
  return "pptx";
10524
10928
  }
10929
+ if (mimeType.startsWith("audio/") || /\.(mp3|wav|m4a|ogg|flac|webm|aac|wma)$/i.test(filePath)) {
10930
+ return "audio";
10931
+ }
10525
10932
  if (mimeType.startsWith("image/") || isImagePath(filePath)) {
10526
10933
  return "image";
10527
10934
  }
@@ -10546,6 +10953,10 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
10546
10953
  function isImagePath(filePath) {
10547
10954
  return IMAGE_EXTENSIONS.has(path12.extname(filePath).toLowerCase());
10548
10955
  }
10956
+ var YOUTUBE_URL_PATTERN = /(?:youtube\.com\/watch\?.*v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/shorts\/)([\w-]{11})/i;
10957
+ function parseYoutubeVideoId(url) {
10958
+ return url.match(YOUTUBE_URL_PATTERN)?.[1];
10959
+ }
10549
10960
  function isStructuredTextMime(mimeType) {
10550
10961
  switch (mimeType) {
10551
10962
  case "application/json":
@@ -10813,7 +11224,7 @@ function normalizeSemanticMarkdownList(value) {
10813
11224
  return items.length ? items : void 0;
10814
11225
  }
10815
11226
  function semanticMarkdownTitle(fallback, content, filePath) {
10816
- const parsed = matter3(content);
11227
+ const parsed = matter4(content);
10817
11228
  const frontmatterTitle = normalizeSemanticMarkdownScalar(parsed.data.title);
10818
11229
  if (frontmatterTitle) {
10819
11230
  return frontmatterTitle;
@@ -10821,7 +11232,7 @@ function semanticMarkdownTitle(fallback, content, filePath) {
10821
11232
  return titleFromText(fallback, parsed.content, filePath);
10822
11233
  }
10823
11234
  function semanticMarkdownContent(content) {
10824
- const parsed = matter3(content);
11235
+ const parsed = matter4(content);
10825
11236
  const body = parsed.content.replace(/\r\n?/g, "\n").trim();
10826
11237
  const semanticFrontmatter = Object.fromEntries(
10827
11238
  MARKDOWN_SEMANTIC_FRONTMATTER_KEYS.flatMap((key) => {
@@ -11025,7 +11436,7 @@ function markdownFrontmatter(value) {
11025
11436
  ([, rawValue]) => Array.isArray(rawValue) ? rawValue.length > 0 : Boolean(typeof rawValue === "string" ? rawValue.trim() : rawValue)
11026
11437
  )
11027
11438
  );
11028
- return matter3.stringify("", normalized).trimEnd().split("\n").concat([""]);
11439
+ return matter4.stringify("", normalized).trimEnd().split("\n").concat([""]);
11029
11440
  }
11030
11441
  function prepareCapturedMarkdownInput(input) {
11031
11442
  return finalizePreparedInput({
@@ -11843,7 +12254,7 @@ function preparedMatchesManifest(manifest, prepared, contentHash) {
11843
12254
  return manifest.contentHash === contentHash && manifest.extractionHash === (prepared.extractionHash ?? buildExtractionHash(prepared.extractedText, prepared.extractionArtifact)) && manifest.semanticHash === (prepared.semanticHash ?? contentHash) && manifest.title === prepared.title && manifest.sourceKind === prepared.sourceKind && manifest.sourceType === prepared.sourceType && manifest.sourceClass === prepared.sourceClass && manifest.language === prepared.language && manifest.mimeType === prepared.mimeType && manifest.repoRelativePath === prepared.repoRelativePath && manifest.sourceGroupId === prepared.sourceGroupId && manifest.sourceGroupTitle === prepared.sourceGroupTitle && manifest.sourcePartKey === prepared.sourcePartKey && manifest.partIndex === prepared.partIndex && manifest.partCount === prepared.partCount && manifest.partTitle === prepared.partTitle && JSON.stringify(manifest.details ?? {}) === JSON.stringify(prepared.details ?? {});
11844
12255
  }
11845
12256
  function shouldDeferWatchSemanticRefresh(sourceKind) {
11846
- return sourceKind === "markdown" || sourceKind === "text" || sourceKind === "html" || sourceKind === "pdf" || sourceKind === "docx" || sourceKind === "epub" || sourceKind === "csv" || sourceKind === "xlsx" || sourceKind === "pptx" || sourceKind === "transcript" || sourceKind === "chat_export" || sourceKind === "email" || sourceKind === "calendar" || sourceKind === "image";
12257
+ return sourceKind === "markdown" || sourceKind === "text" || sourceKind === "html" || sourceKind === "pdf" || sourceKind === "docx" || sourceKind === "epub" || sourceKind === "csv" || sourceKind === "xlsx" || sourceKind === "pptx" || sourceKind === "transcript" || sourceKind === "chat_export" || sourceKind === "email" || sourceKind === "calendar" || sourceKind === "image" || sourceKind === "audio";
11847
12258
  }
11848
12259
  function pendingSemanticRefreshId(changeType, repoRoot, relativePath) {
11849
12260
  return `pending:${changeType}:${sha256(`${toPosix(repoRoot)}:${relativePath}`).slice(0, 12)}`;
@@ -12334,6 +12745,15 @@ async function prepareFileInputs(rootDir, absoluteInput, repoRoot, sourceClass)
12334
12745
  title = extracted.title?.trim() || title;
12335
12746
  extractedText = extracted.extractedText;
12336
12747
  extractionArtifact = extracted.artifact;
12748
+ } else if (sourceKind === "audio") {
12749
+ title = path12.basename(absoluteInput, path12.extname(absoluteInput));
12750
+ const extracted = await extractAudioTranscription(rootDir, {
12751
+ mimeType,
12752
+ bytes: payloadBytes,
12753
+ fileName: absoluteInput
12754
+ });
12755
+ extractedText = extracted.extractedText;
12756
+ extractionArtifact = extracted.artifact;
12337
12757
  } else {
12338
12758
  title = path12.basename(absoluteInput, path12.extname(absoluteInput));
12339
12759
  }
@@ -12365,6 +12785,28 @@ async function prepareFileInput(rootDir, absoluteInput, repoRoot, sourceClass) {
12365
12785
  }
12366
12786
  async function prepareUrlInputs(rootDir, input, options) {
12367
12787
  await validateUrlSafety(input);
12788
+ const youtubeVideoId = parseYoutubeVideoId(input);
12789
+ if (youtubeVideoId) {
12790
+ const extracted = await extractYoutubeTranscript({ videoId: youtubeVideoId, url: input });
12791
+ const title2 = extracted.title ?? `YouTube ${youtubeVideoId}`;
12792
+ const extractedText2 = extracted.extractedText;
12793
+ const payloadBytes2 = Buffer.from(extractedText2 ?? "", "utf8");
12794
+ return [
12795
+ finalizePreparedInput({
12796
+ title: title2,
12797
+ originType: "url",
12798
+ sourceKind: "youtube",
12799
+ url: normalizeOriginUrl(input),
12800
+ mimeType: "text/html",
12801
+ storedExtension: ".md",
12802
+ payloadBytes: payloadBytes2,
12803
+ extractedText: extractedText2,
12804
+ extractionArtifact: extracted.artifact,
12805
+ extractionHash: buildExtractionHash(extractedText2, extracted.artifact),
12806
+ details: extracted.artifact.metadata
12807
+ })
12808
+ ];
12809
+ }
12368
12810
  const response = await fetch(input);
12369
12811
  if (!response.ok) {
12370
12812
  throw new Error(`Failed to fetch ${input}: ${response.status} ${response.statusText}`);
@@ -12584,6 +13026,14 @@ async function prepareUrlInputs(rootDir, input, options) {
12584
13026
  title = extracted.title?.trim() || title;
12585
13027
  extractedText = extracted.extractedText;
12586
13028
  extractionArtifact = extracted.artifact;
13029
+ } else if (sourceKind === "audio") {
13030
+ const extracted = await extractAudioTranscription(rootDir, {
13031
+ mimeType,
13032
+ bytes: payloadBytes,
13033
+ fileName: inputUrl.pathname
13034
+ });
13035
+ extractedText = extracted.extractedText;
13036
+ extractionArtifact = extracted.artifact;
12587
13037
  }
12588
13038
  }
12589
13039
  return [
@@ -13171,7 +13621,7 @@ import fs19 from "fs/promises";
13171
13621
  import path23 from "path";
13172
13622
  import Graph from "graphology";
13173
13623
  import louvain from "graphology-communities-louvain";
13174
- import matter9 from "gray-matter";
13624
+ import matter10 from "gray-matter";
13175
13625
  import { z as z7 } from "zod";
13176
13626
 
13177
13627
  // src/analysis.ts
@@ -13607,7 +14057,7 @@ function conflictConfidence(claimA, claimB) {
13607
14057
  // src/deep-lint.ts
13608
14058
  import fs13 from "fs/promises";
13609
14059
  import path17 from "path";
13610
- import matter4 from "gray-matter";
14060
+ import matter5 from "gray-matter";
13611
14061
  import { z as z5 } from "zod";
13612
14062
 
13613
14063
  // src/findings.ts
@@ -13981,7 +14431,7 @@ async function loadContextPages(rootDir, graph) {
13981
14431
  contextPages.slice(0, 18).map(async (page) => {
13982
14432
  const absolutePath = path17.join(paths.wikiDir, page.path);
13983
14433
  const raw = await fs13.readFile(absolutePath, "utf8").catch(() => "");
13984
- const parsed = matter4(raw);
14434
+ const parsed = matter5(raw);
13985
14435
  return {
13986
14436
  id: page.id,
13987
14437
  title: page.title,
@@ -14917,7 +15367,7 @@ function enrichGraph(graph, manifests, analyses, extraSimilarityEdges = []) {
14917
15367
  }
14918
15368
 
14919
15369
  // src/markdown.ts
14920
- import matter5 from "gray-matter";
15370
+ import matter6 from "gray-matter";
14921
15371
  function uniqueStrings2(values) {
14922
15372
  return uniqueBy(values.filter(Boolean), (value) => value);
14923
15373
  }
@@ -15172,7 +15622,7 @@ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutput
15172
15622
  compiledFrom: metadata.compiledFrom,
15173
15623
  managedBy: metadata.managedBy
15174
15624
  },
15175
- content: matter5.stringify(body, safeFrontmatter(frontmatter))
15625
+ content: matter6.stringify(body, safeFrontmatter(frontmatter))
15176
15626
  };
15177
15627
  }
15178
15628
  function buildModulePage(input) {
@@ -15322,7 +15772,7 @@ function buildModulePage(input) {
15322
15772
  compiledFrom: metadata.compiledFrom,
15323
15773
  managedBy: metadata.managedBy
15324
15774
  },
15325
- content: matter5.stringify(body, frontmatter)
15775
+ content: matter6.stringify(body, frontmatter)
15326
15776
  };
15327
15777
  }
15328
15778
  function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHashes, sourceSemanticHashes, schemaHash, metadata, relativePath, relatedOutputs = [], decorations, existingContent) {
@@ -15399,7 +15849,7 @@ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHash
15399
15849
  compiledFrom: metadata.compiledFrom,
15400
15850
  managedBy: metadata.managedBy
15401
15851
  },
15402
- content: matter5.stringify(body, frontmatter)
15852
+ content: matter6.stringify(body, frontmatter)
15403
15853
  };
15404
15854
  }
15405
15855
  function buildIndexPage(pages, schemaHash, metadata, projectPages = []) {
@@ -15483,7 +15933,7 @@ function buildIndexPage(pages, schemaHash, metadata, projectPages = []) {
15483
15933
  }
15484
15934
  function buildSectionIndex(kind, pages, schemaHash, metadata, projectIds = []) {
15485
15935
  const title = kind.charAt(0).toUpperCase() + kind.slice(1);
15486
- return matter5.stringify(
15936
+ return matter6.stringify(
15487
15937
  [`# ${title}`, "", ...pages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`), ""].join("\n"),
15488
15938
  {
15489
15939
  page_id: `${kind}:index`,
@@ -15995,7 +16445,7 @@ function buildGraphReportPage(input) {
15995
16445
  compiledFrom: input.metadata.compiledFrom,
15996
16446
  managedBy: input.metadata.managedBy
15997
16447
  },
15998
- content: matter5.stringify(body, frontmatter)
16448
+ content: matter6.stringify(body, frontmatter)
15999
16449
  };
16000
16450
  }
16001
16451
  function buildCommunitySummaryPage(input) {
@@ -16079,11 +16529,11 @@ function buildCommunitySummaryPage(input) {
16079
16529
  compiledFrom: input.metadata.compiledFrom,
16080
16530
  managedBy: input.metadata.managedBy
16081
16531
  },
16082
- content: matter5.stringify(body, frontmatter)
16532
+ content: matter6.stringify(body, frontmatter)
16083
16533
  };
16084
16534
  }
16085
16535
  function buildProjectsIndex(projectPages, schemaHash, metadata) {
16086
- return matter5.stringify(
16536
+ return matter6.stringify(
16087
16537
  [
16088
16538
  "# Projects",
16089
16539
  "",
@@ -16114,7 +16564,7 @@ function buildProjectsIndex(projectPages, schemaHash, metadata) {
16114
16564
  }
16115
16565
  function buildProjectIndex(input) {
16116
16566
  const title = `Project: ${input.projectId}`;
16117
- return matter5.stringify(
16567
+ return matter6.stringify(
16118
16568
  [
16119
16569
  `# ${title}`,
16120
16570
  "",
@@ -16231,7 +16681,7 @@ function buildOutputPage(input) {
16231
16681
  outputFormat: input.outputFormat,
16232
16682
  outputAssets
16233
16683
  },
16234
- content: matter5.stringify(
16684
+ content: matter6.stringify(
16235
16685
  (input.outputFormat === "slides" ? [
16236
16686
  input.answer,
16237
16687
  "",
@@ -16359,7 +16809,7 @@ function buildExploreHubPage(input) {
16359
16809
  outputFormat: input.outputFormat,
16360
16810
  outputAssets
16361
16811
  },
16362
- content: matter5.stringify(
16812
+ content: matter6.stringify(
16363
16813
  (input.outputFormat === "slides" ? [
16364
16814
  `# ${title}`,
16365
16815
  "",
@@ -16625,12 +17075,12 @@ function buildOutputAssetManifest(input) {
16625
17075
  // src/outputs.ts
16626
17076
  import fs16 from "fs/promises";
16627
17077
  import path20 from "path";
16628
- import matter7 from "gray-matter";
17078
+ import matter8 from "gray-matter";
16629
17079
 
16630
17080
  // src/pages.ts
16631
17081
  import fs15 from "fs/promises";
16632
17082
  import path19 from "path";
16633
- import matter6 from "gray-matter";
17083
+ import matter7 from "gray-matter";
16634
17084
  function normalizeStringArray(value) {
16635
17085
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
16636
17086
  }
@@ -16711,7 +17161,7 @@ async function loadExistingManagedPageState(absolutePath, defaults = {}) {
16711
17161
  };
16712
17162
  }
16713
17163
  const content = await fs15.readFile(absolutePath, "utf8");
16714
- const parsed = matter6(content);
17164
+ const parsed = matter7(content);
16715
17165
  return {
16716
17166
  status: normalizePageStatus(parsed.data.status, defaults.status ?? "active"),
16717
17167
  managedBy: normalizePageManager(parsed.data.managed_by, defaults.managedBy ?? "system"),
@@ -16745,7 +17195,7 @@ function inferPageKind(relativePath, explicitKind = void 0) {
16745
17195
  return "index";
16746
17196
  }
16747
17197
  function parseStoredPage(relativePath, content, defaults = {}) {
16748
- const parsed = matter6(content);
17198
+ const parsed = matter7(content);
16749
17199
  const now = (/* @__PURE__ */ new Date()).toISOString();
16750
17200
  const fallbackCreatedAt = defaults.createdAt ?? now;
16751
17201
  const fallbackUpdatedAt = defaults.updatedAt ?? fallbackCreatedAt;
@@ -16800,7 +17250,7 @@ async function loadInsightPages(wikiDir) {
16800
17250
  for (const absolutePath of files) {
16801
17251
  const relativePath = toPosix(path19.relative(wikiDir, absolutePath));
16802
17252
  const content = await fs15.readFile(absolutePath, "utf8");
16803
- const parsed = matter6(content);
17253
+ const parsed = matter7(content);
16804
17254
  const stats = await fs15.stat(absolutePath);
16805
17255
  const title = typeof parsed.data.title === "string" ? parsed.data.title : path19.basename(absolutePath, ".md");
16806
17256
  const sourceIds = normalizeStringArray(parsed.data.source_ids);
@@ -16901,7 +17351,7 @@ async function loadSavedOutputPages(wikiDir) {
16901
17351
  const relativePath = path20.posix.join(current.relativeDir, entry.name);
16902
17352
  const absolutePath = path20.join(current.absoluteDir, entry.name);
16903
17353
  const content = await fs16.readFile(absolutePath, "utf8");
16904
- const parsed = matter7(content);
17354
+ const parsed = matter8(content);
16905
17355
  const slug = relativePath.replace(/^outputs\//, "").replace(/\.md$/, "");
16906
17356
  const title = typeof parsed.data.title === "string" ? parsed.data.title : path20.basename(slug);
16907
17357
  const pageId = typeof parsed.data.page_id === "string" ? parsed.data.page_id : `output:${slug}`;
@@ -16955,7 +17405,7 @@ async function loadSavedOutputPages(wikiDir) {
16955
17405
  // src/search.ts
16956
17406
  import fs17 from "fs/promises";
16957
17407
  import path21 from "path";
16958
- import matter8 from "gray-matter";
17408
+ import matter9 from "gray-matter";
16959
17409
  function warningMessage(warning) {
16960
17410
  return warning instanceof Error ? warning.message : String(warning);
16961
17411
  }
@@ -17043,7 +17493,7 @@ async function rebuildSearchIndex(dbPath, pages, wikiDir) {
17043
17493
  for (const page of pages) {
17044
17494
  const absolutePath = path21.join(wikiDir, page.path);
17045
17495
  const content = await fs17.readFile(absolutePath, "utf8");
17046
- const parsed = matter8(content);
17496
+ const parsed = matter9(content);
17047
17497
  let body = parsed.content;
17048
17498
  const primarySourceId = Array.isArray(parsed.data.source_ids) && typeof parsed.data.source_ids[0] === "string" ? parsed.data.source_ids[0] : page.sourceIds[0];
17049
17499
  if ((page.kind === "source" || page.kind === "module") && primarySourceId) {
@@ -17454,7 +17904,7 @@ async function resolveImageGenerationProvider(rootDir) {
17454
17904
  if (!providerConfig) {
17455
17905
  throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
17456
17906
  }
17457
- const { createProvider: createProvider2 } = await import("./registry-UA42LQUQ.js");
17907
+ const { createProvider: createProvider2 } = await import("./registry-SYCRRA65.js");
17458
17908
  return createProvider2(preferredProviderId, providerConfig, rootDir);
17459
17909
  }
17460
17910
  async function generateOutputArtifacts(rootDir, input) {
@@ -17973,7 +18423,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
17973
18423
  {
17974
18424
  relativePath: "dashboards/index.md",
17975
18425
  title: "Dashboards",
17976
- content: (metadata) => matter9.stringify(
18426
+ content: (metadata) => matter10.stringify(
17977
18427
  [
17978
18428
  "# Dashboards",
17979
18429
  "",
@@ -18025,7 +18475,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18025
18475
  {
18026
18476
  relativePath: "dashboards/recent-sources.md",
18027
18477
  title: "Recent Sources",
18028
- content: (metadata) => matter9.stringify(
18478
+ content: (metadata) => matter10.stringify(
18029
18479
  [
18030
18480
  "# Recent Sources",
18031
18481
  "",
@@ -18068,7 +18518,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18068
18518
  {
18069
18519
  relativePath: "dashboards/reading-log.md",
18070
18520
  title: "Reading Log",
18071
- content: (metadata) => matter9.stringify(
18521
+ content: (metadata) => matter10.stringify(
18072
18522
  [
18073
18523
  "# Reading Log",
18074
18524
  "",
@@ -18128,7 +18578,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18128
18578
  {
18129
18579
  relativePath: "dashboards/timeline.md",
18130
18580
  title: "Timeline",
18131
- content: (metadata) => matter9.stringify(
18581
+ content: (metadata) => matter10.stringify(
18132
18582
  [
18133
18583
  "# Timeline",
18134
18584
  "",
@@ -18174,7 +18624,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18174
18624
  {
18175
18625
  relativePath: "dashboards/source-sessions.md",
18176
18626
  title: "Source Sessions",
18177
- content: (metadata) => matter9.stringify(
18627
+ content: (metadata) => matter10.stringify(
18178
18628
  [
18179
18629
  "# Source Sessions",
18180
18630
  "",
@@ -18231,7 +18681,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18231
18681
  {
18232
18682
  relativePath: "dashboards/source-guides.md",
18233
18683
  title: "Source Guides",
18234
- content: (metadata) => matter9.stringify(
18684
+ content: (metadata) => matter10.stringify(
18235
18685
  [
18236
18686
  "# Source Guides",
18237
18687
  "",
@@ -18284,7 +18734,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18284
18734
  {
18285
18735
  relativePath: "dashboards/research-map.md",
18286
18736
  title: "Research Map",
18287
- content: (metadata) => matter9.stringify(
18737
+ content: (metadata) => matter10.stringify(
18288
18738
  [
18289
18739
  "# Research Map",
18290
18740
  "",
@@ -18348,7 +18798,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18348
18798
  {
18349
18799
  relativePath: "dashboards/contradictions.md",
18350
18800
  title: "Contradictions",
18351
- content: (metadata) => matter9.stringify(
18801
+ content: (metadata) => matter10.stringify(
18352
18802
  [
18353
18803
  "# Contradictions",
18354
18804
  "",
@@ -18407,7 +18857,7 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18407
18857
  {
18408
18858
  relativePath: "dashboards/open-questions.md",
18409
18859
  title: "Open Questions",
18410
- content: (metadata) => matter9.stringify(
18860
+ content: (metadata) => matter10.stringify(
18411
18861
  [
18412
18862
  "# Open Questions",
18413
18863
  "",
@@ -18483,7 +18933,12 @@ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
18483
18933
  function indexCompiledFrom(pages) {
18484
18934
  return uniqueStrings3(pages.flatMap((page) => page.sourceIds));
18485
18935
  }
18486
- function deriveGraphMetrics(nodes, edges) {
18936
+ function autoResolution(nodeCount, edgeCount) {
18937
+ if (nodeCount <= 20) return 0.5;
18938
+ if (edgeCount / Math.max(1, nodeCount) < 2) return 0.8;
18939
+ return 1;
18940
+ }
18941
+ function deriveGraphMetrics(nodes, edges, options) {
18487
18942
  const adjacency = /* @__PURE__ */ new Map();
18488
18943
  const connect = (left, right) => {
18489
18944
  if (!adjacency.has(left)) {
@@ -18520,7 +18975,8 @@ function deriveGraphMetrics(nodes, edges) {
18520
18975
  }
18521
18976
  }
18522
18977
  }
18523
- const louvainMapping = louvainGraph.size > 0 ? louvain(louvainGraph, { resolution: 1 }) : {};
18978
+ const effectiveResolution = options?.resolution ?? autoResolution(louvainGraph.order, louvainGraph.size);
18979
+ const louvainMapping = louvainGraph.size > 0 ? louvain(louvainGraph, { resolution: effectiveResolution }) : {};
18524
18980
  const groupByCommunity = /* @__PURE__ */ new Map();
18525
18981
  let nextIsolated = -1;
18526
18982
  for (const node of nonSourceNodes) {
@@ -18666,7 +19122,7 @@ function detectContradictions(analyses) {
18666
19122
  }
18667
19123
  return contradictions;
18668
19124
  }
18669
- function buildGraph(manifests, analyses, pages, sourceProjects, _codeIndex) {
19125
+ function buildGraph(manifests, analyses, pages, sourceProjects, _codeIndex, options) {
18670
19126
  const manifestsById = new Map(manifests.map((manifest) => [manifest.sourceId, manifest]));
18671
19127
  const goPackageSymbolLookups = buildGoPackageSymbolLookups(analyses, manifestsById);
18672
19128
  const analysesBySourceId = new Map(analyses.map((analysis) => [analysis.sourceId, analysis]));
@@ -19026,7 +19482,7 @@ function buildGraph(manifests, analyses, pages, sourceProjects, _codeIndex) {
19026
19482
  manifests,
19027
19483
  analyses
19028
19484
  );
19029
- const metrics = deriveGraphMetrics(graphNodes, enriched.edges);
19485
+ const metrics = deriveGraphMetrics(graphNodes, enriched.edges, { resolution: options?.communityResolution });
19030
19486
  return {
19031
19487
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
19032
19488
  nodes: metrics.nodes,
@@ -19493,7 +19949,9 @@ async function syncVaultArtifacts(rootDir, input) {
19493
19949
  }
19494
19950
  const compiledPages = records.map((record) => record.page);
19495
19951
  const basePages = [...compiledPages, ...input.outputPages, ...input.insightPages];
19496
- const structuralGraph = buildGraph(input.manifests, input.analyses, basePages, input.sourceProjects, input.codeIndex);
19952
+ const structuralGraph = buildGraph(input.manifests, input.analyses, basePages, input.sourceProjects, input.codeIndex, {
19953
+ communityResolution: config.graph?.communityResolution
19954
+ });
19497
19955
  const contradictions = detectContradictions(input.analyses);
19498
19956
  for (const contradiction of contradictions) {
19499
19957
  const edgeId = `contradiction:${contradiction.sourceIdA}->${contradiction.sourceIdB}`;
@@ -19515,7 +19973,9 @@ async function syncVaultArtifacts(rootDir, input) {
19515
19973
  const edges = uniqueBy([...structuralGraph.edges, ...embeddingEdges], (edge) => edge.id).sort(
19516
19974
  (left, right) => left.id.localeCompare(right.id)
19517
19975
  );
19518
- const metrics = deriveGraphMetrics(resetGraphNodeMetrics(structuralGraph.nodes), edges);
19976
+ const metrics = deriveGraphMetrics(resetGraphNodeMetrics(structuralGraph.nodes), edges, {
19977
+ resolution: config.graph?.communityResolution
19978
+ });
19519
19979
  return {
19520
19980
  ...structuralGraph,
19521
19981
  nodes: metrics.nodes,
@@ -20086,7 +20546,7 @@ async function executeQuery(rootDir, question, format) {
20086
20546
  const absolutePath = path23.join(paths.wikiDir, result.path);
20087
20547
  try {
20088
20548
  const content = await fs19.readFile(absolutePath, "utf8");
20089
- const parsed = matter9(content);
20549
+ const parsed = matter10(content);
20090
20550
  return `# ${result.title}
20091
20551
  ${truncate(normalizeWhitespace(parsed.content), 1200)}`;
20092
20552
  } catch {
@@ -20299,8 +20759,8 @@ function computeChangeSummary(current, staged, changeType) {
20299
20759
  if (changeType === "delete") return "Removed page";
20300
20760
  if (changeType === "promote") return "Promoted from candidate";
20301
20761
  if (!current || !staged) return "Updated page";
20302
- const currentParsed = matter9(current);
20303
- const stagedParsed = matter9(staged);
20762
+ const currentParsed = matter10(current);
20763
+ const stagedParsed = matter10(staged);
20304
20764
  const changes = [];
20305
20765
  const currentTags = currentParsed.data.tags ?? [];
20306
20766
  const stagedTags = stagedParsed.data.tags ?? [];
@@ -20501,9 +20961,9 @@ async function promoteCandidate(rootDir, target) {
20501
20961
  const graph = await readJsonFile(paths.graphPath);
20502
20962
  const candidate = resolveCandidateTarget(graph?.pages ?? [], target);
20503
20963
  const raw = await fs19.readFile(path23.join(paths.wikiDir, candidate.path), "utf8");
20504
- const parsed = matter9(raw);
20964
+ const parsed = matter10(raw);
20505
20965
  const nextUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
20506
- const nextContent = matter9.stringify(parsed.content, {
20966
+ const nextContent = matter10.stringify(parsed.content, {
20507
20967
  ...parsed.data,
20508
20968
  status: "active",
20509
20969
  updated_at: nextUpdatedAt,
@@ -20654,7 +21114,7 @@ async function initVault(rootDir, options = {}) {
20654
21114
  const now = (/* @__PURE__ */ new Date()).toISOString();
20655
21115
  await writeFileIfChanged(
20656
21116
  insightsIndexPath,
20657
- matter9.stringify(
21117
+ matter10.stringify(
20658
21118
  (isResearchProfile ? [
20659
21119
  "# Insights",
20660
21120
  "",
@@ -20701,7 +21161,7 @@ async function initVault(rootDir, options = {}) {
20701
21161
  );
20702
21162
  await writeFileIfChanged(
20703
21163
  path23.join(paths.wikiDir, "projects", "index.md"),
20704
- matter9.stringify(["# Projects", "", "- Run `swarmvault compile` to build project rollups.", ""].join("\n"), {
21164
+ matter10.stringify(["# Projects", "", "- Run `swarmvault compile` to build project rollups.", ""].join("\n"), {
20705
21165
  page_id: "projects:index",
20706
21166
  kind: "index",
20707
21167
  title: "Projects",
@@ -20724,7 +21184,7 @@ async function initVault(rootDir, options = {}) {
20724
21184
  );
20725
21185
  await writeFileIfChanged(
20726
21186
  path23.join(paths.wikiDir, "candidates", "index.md"),
20727
- matter9.stringify(["# Candidates", "", "- Run `swarmvault compile` to stage candidate pages.", ""].join("\n"), {
21187
+ matter10.stringify(["# Candidates", "", "- Run `swarmvault compile` to stage candidate pages.", ""].join("\n"), {
20728
21188
  page_id: "candidates:index",
20729
21189
  kind: "index",
20730
21190
  title: "Candidates",
@@ -20751,7 +21211,7 @@ async function initVault(rootDir, options = {}) {
20751
21211
  if (isResearchProfile) {
20752
21212
  await writeFileIfChanged(
20753
21213
  path23.join(paths.wikiDir, "insights", "research-playbook.md"),
20754
- matter9.stringify(
21214
+ matter10.stringify(
20755
21215
  [
20756
21216
  `# ${requestedProfile === "personal-research" ? "Personal Research Playbook" : "Research Playbook"}`,
20757
21217
  "",
@@ -21536,7 +21996,7 @@ async function benchmarkVault(rootDir, options = {}) {
21536
21996
  if (!await fileExists(absolutePath)) {
21537
21997
  continue;
21538
21998
  }
21539
- const parsed = matter9(await fs19.readFile(absolutePath, "utf8"));
21999
+ const parsed = matter10(await fs19.readFile(absolutePath, "utf8"));
21540
22000
  pageContentsById.set(page.id, parsed.content);
21541
22001
  }
21542
22002
  const configuredQuestions = (config.benchmark?.questions ?? []).map((question) => normalizeWhitespace(question)).filter(Boolean);
@@ -21620,7 +22080,7 @@ async function readPage(rootDir, relativePath) {
21620
22080
  return null;
21621
22081
  }
21622
22082
  const raw = await fs19.readFile(absolutePath, "utf8");
21623
- const parsed = matter9(raw);
22083
+ const parsed = matter10(raw);
21624
22084
  return {
21625
22085
  path: relativePath,
21626
22086
  title: typeof parsed.data.title === "string" ? parsed.data.title : path23.basename(relativePath, path23.extname(relativePath)),
@@ -21835,7 +22295,7 @@ async function bootstrapDemo(rootDir, input) {
21835
22295
  }
21836
22296
 
21837
22297
  // src/mcp.ts
21838
- var SERVER_VERSION = "0.7.25";
22298
+ var SERVER_VERSION = "0.7.27";
21839
22299
  async function createMcpServer(rootDir) {
21840
22300
  const server = new McpServer({
21841
22301
  name: "swarmvault",
@@ -22520,7 +22980,7 @@ async function serveSchedules(rootDir, pollMs = 3e4) {
22520
22980
  import { spawn as spawn2 } from "child_process";
22521
22981
  import fs22 from "fs/promises";
22522
22982
  import path26 from "path";
22523
- import matter10 from "gray-matter";
22983
+ import matter11 from "gray-matter";
22524
22984
  import { JSDOM as JSDOM3 } from "jsdom";
22525
22985
  var DEFAULT_CRAWL_MAX_PAGES = 12;
22526
22986
  var DEFAULT_CRAWL_MAX_DEPTH = 2;
@@ -23863,7 +24323,7 @@ async function buildGuidedUpdatePages(rootDir, scope, session) {
23863
24323
  const relativePath = useCanonicalTargets && targetPage ? targetPage.path : targetPage ? insightRelativePathForTarget(targetPage, scope) : `insights/topics/${slugify(scope.title)}.md`;
23864
24324
  const absolutePath = path26.join(paths.wikiDir, relativePath);
23865
24325
  const existingContent = await fileExists(absolutePath) ? await fs22.readFile(absolutePath, "utf8") : "";
23866
- const parsed = existingContent ? matter10(existingContent) : { data: {}, content: "" };
24326
+ const parsed = existingContent ? matter11(existingContent) : { data: {}, content: "" };
23867
24327
  const existingData = parsed.data;
23868
24328
  const existingSourceIds = Array.isArray(existingData.source_ids) ? existingData.source_ids.filter((value) => typeof value === "string") : [];
23869
24329
  const existingProjectIds = Array.isArray(existingData.project_ids) ? existingData.project_ids.filter((value) => typeof value === "string") : [];
@@ -23924,7 +24384,7 @@ async function buildGuidedUpdatePages(rootDir, scope, session) {
23924
24384
  ""
23925
24385
  ].join("\n");
23926
24386
  const nextBody = replaceMarkedSection(baseBody, scope.id, updateBlock);
23927
- const content = matter10.stringify(
24387
+ const content = matter11.stringify(
23928
24388
  `${nextBody.trimEnd()}
23929
24389
  `,
23930
24390
  JSON.parse(
@@ -24310,7 +24770,7 @@ import fs23 from "fs/promises";
24310
24770
  import http from "http";
24311
24771
  import path28 from "path";
24312
24772
  import { promisify as promisify2 } from "util";
24313
- import matter11 from "gray-matter";
24773
+ import matter12 from "gray-matter";
24314
24774
  import mime2 from "mime-types";
24315
24775
 
24316
24776
  // src/graph-presentation.ts
@@ -24942,7 +25402,7 @@ async function readViewerPage(rootDir, relativePath) {
24942
25402
  return null;
24943
25403
  }
24944
25404
  const raw = await fs23.readFile(absolutePath, "utf8");
24945
- const parsed = matter11(raw);
25405
+ const parsed = matter12(raw);
24946
25406
  return {
24947
25407
  path: relativePath,
24948
25408
  title: typeof parsed.data.title === "string" ? parsed.data.title : path28.basename(relativePath, path28.extname(relativePath)),