@swarmvaultai/engine 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  uniqueBy,
22
22
  writeFileIfChanged,
23
23
  writeJsonFile
24
- } from "./chunk-B3FC4J3P.js";
24
+ } from "./chunk-FD3LJQ4T.js";
25
25
 
26
26
  // src/agents.ts
27
27
  import crypto from "crypto";
@@ -8502,8 +8502,8 @@ async function readExtractionArtifact(rootDir, manifest) {
8502
8502
  }
8503
8503
 
8504
8504
  // src/mcp.ts
8505
- import fs19 from "fs/promises";
8506
- import path23 from "path";
8505
+ import fs20 from "fs/promises";
8506
+ import path24 from "path";
8507
8507
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
8508
8508
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8509
8509
  import { z as z8 } from "zod";
@@ -8616,8 +8616,8 @@ function buildSchemaPrompt(schema, instruction) {
8616
8616
  }
8617
8617
 
8618
8618
  // src/vault.ts
8619
- import fs18 from "fs/promises";
8620
- import path22 from "path";
8619
+ import fs19 from "fs/promises";
8620
+ import path23 from "path";
8621
8621
  import matter9 from "gray-matter";
8622
8622
  import { z as z7 } from "zod";
8623
8623
 
@@ -11137,15 +11137,15 @@ function sourceTypeForNode(node, pagesById) {
11137
11137
  return pagesById.get(node.pageId)?.sourceType;
11138
11138
  }
11139
11139
  function supportingPathDetails(graph, edge) {
11140
- const path28 = shortestGraphPath(graph, edge.source, edge.target);
11140
+ const path29 = shortestGraphPath(graph, edge.source, edge.target);
11141
11141
  const edgesById = new Map(graph.edges.map((item) => [item.id, item]));
11142
- const pathEdges = path28.edgeIds.map((edgeId) => edgesById.get(edgeId)).filter((item) => Boolean(item));
11142
+ const pathEdges = path29.edgeIds.map((edgeId) => edgesById.get(edgeId)).filter((item) => Boolean(item));
11143
11143
  return {
11144
- pathNodeIds: path28.nodeIds,
11145
- pathEdgeIds: path28.edgeIds,
11144
+ pathNodeIds: path29.nodeIds,
11145
+ pathEdgeIds: path29.edgeIds,
11146
11146
  pathRelations: pathEdges.map((item) => item.relation),
11147
11147
  pathEvidenceClasses: pathEdges.map((item) => item.evidenceClass),
11148
- pathSummary: path28.summary
11148
+ pathSummary: path29.summary
11149
11149
  };
11150
11150
  }
11151
11151
  function surpriseScore(edge, graph, pagesById, hyperedgesByNodeId) {
@@ -11214,7 +11214,7 @@ function topSurprisingConnections(graph, pagesById) {
11214
11214
  }).map((edge) => {
11215
11215
  const source = nodesById.get(edge.source);
11216
11216
  const target = nodesById.get(edge.target);
11217
- const path28 = supportingPathDetails(graph, edge);
11217
+ const path29 = supportingPathDetails(graph, edge);
11218
11218
  const scored = surpriseScore(edge, graph, pagesById, hyperedgesByNodeId);
11219
11219
  return {
11220
11220
  id: edge.id,
@@ -11225,11 +11225,11 @@ function topSurprisingConnections(graph, pagesById) {
11225
11225
  relation: edge.relation,
11226
11226
  evidenceClass: edge.evidenceClass,
11227
11227
  confidence: edge.confidence,
11228
- pathNodeIds: path28.pathNodeIds,
11229
- pathEdgeIds: path28.pathEdgeIds,
11230
- pathRelations: path28.pathRelations,
11231
- pathEvidenceClasses: path28.pathEvidenceClasses,
11232
- pathSummary: path28.pathSummary,
11228
+ pathNodeIds: path29.pathNodeIds,
11229
+ pathEdgeIds: path29.pathEdgeIds,
11230
+ pathRelations: path29.pathRelations,
11231
+ pathEvidenceClasses: path29.pathEvidenceClasses,
11232
+ pathSummary: path29.pathSummary,
11233
11233
  why: scored.why,
11234
11234
  explanation: scored.explanation,
11235
11235
  surpriseScore: scored.score
@@ -12691,6 +12691,58 @@ function searchPages(dbPath, query, limitOrOptions = 5) {
12691
12691
  }));
12692
12692
  }
12693
12693
 
12694
+ // src/source-sessions.ts
12695
+ import fs18 from "fs/promises";
12696
+ import path22 from "path";
12697
+ function sessionStatePathFor(paths, sessionId) {
12698
+ return path22.join(paths.sourceSessionsDir, `${sessionId}.json`);
12699
+ }
12700
+ async function listGuidedSourceSessions(rootDir) {
12701
+ const { paths } = await loadVaultConfig(rootDir);
12702
+ const entries = await fs18.readdir(paths.sourceSessionsDir, { withFileTypes: true }).catch(() => []);
12703
+ const sessions = await Promise.all(
12704
+ entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map(async (entry) => await readJsonFile(path22.join(paths.sourceSessionsDir, entry.name)))
12705
+ );
12706
+ return sessions.filter((session) => Boolean(session)).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
12707
+ }
12708
+ async function readGuidedSourceSession(rootDir, sessionId) {
12709
+ const { paths } = await loadVaultConfig(rootDir);
12710
+ return await readJsonFile(sessionStatePathFor(paths, sessionId));
12711
+ }
12712
+ async function findLatestGuidedSourceSessionByScope(rootDir, scopeId) {
12713
+ const sessions = await listGuidedSourceSessions(rootDir);
12714
+ return sessions.find((session) => session.scopeId === scopeId) ?? null;
12715
+ }
12716
+ async function writeGuidedSourceSession(rootDir, session) {
12717
+ const { paths } = await loadVaultConfig(rootDir);
12718
+ await ensureDir(paths.sourceSessionsDir);
12719
+ const next = {
12720
+ ...session,
12721
+ updatedAt: session.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
12722
+ };
12723
+ const filePath = sessionStatePathFor(paths, session.sessionId);
12724
+ await fs18.writeFile(filePath, `${JSON.stringify(next, null, 2)}
12725
+ `, "utf8");
12726
+ return filePath;
12727
+ }
12728
+ async function updateGuidedSourceSessionStatus(rootDir, sessionId, status) {
12729
+ const existing = await readGuidedSourceSession(rootDir, sessionId);
12730
+ if (!existing) {
12731
+ return null;
12732
+ }
12733
+ const next = {
12734
+ ...existing,
12735
+ status,
12736
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
12737
+ };
12738
+ await writeGuidedSourceSession(rootDir, next);
12739
+ return next;
12740
+ }
12741
+ async function guidedSourceSessionStatePath(rootDir, sessionId) {
12742
+ const { paths } = await loadVaultConfig(rootDir);
12743
+ return sessionStatePathFor(paths, sessionId);
12744
+ }
12745
+
12694
12746
  // src/vault.ts
12695
12747
  var COMPILE_PROGRESS_THRESHOLD = 120;
12696
12748
  var COMPILE_PROGRESS_UPDATE_INTERVAL = 50;
@@ -12745,7 +12797,7 @@ function outputFormatInstruction(format) {
12745
12797
  }
12746
12798
  }
12747
12799
  function outputAssetPath(slug, fileName) {
12748
- return toPosix(path22.join("outputs", "assets", slug, fileName));
12800
+ return toPosix(path23.join("outputs", "assets", slug, fileName));
12749
12801
  }
12750
12802
  function outputAssetId(slug, role) {
12751
12803
  return `output:${slug}:asset:${role}`;
@@ -12885,7 +12937,7 @@ async function resolveImageGenerationProvider(rootDir) {
12885
12937
  if (!providerConfig) {
12886
12938
  throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
12887
12939
  }
12888
- const { createProvider: createProvider2 } = await import("./registry-KVJAO5DF.js");
12940
+ const { createProvider: createProvider2 } = await import("./registry-XOPLQNZY.js");
12889
12941
  return createProvider2(preferredProviderId, providerConfig, rootDir);
12890
12942
  }
12891
12943
  async function generateOutputArtifacts(rootDir, input) {
@@ -13083,7 +13135,7 @@ async function generateOutputArtifacts(rootDir, input) {
13083
13135
  };
13084
13136
  }
13085
13137
  function normalizeProjectRoot(root) {
13086
- const normalized = toPosix(path22.posix.normalize(root.replace(/\\/g, "/"))).replace(/^\.\/+/, "").replace(/\/+$/, "");
13138
+ const normalized = toPosix(path23.posix.normalize(root.replace(/\\/g, "/"))).replace(/^\.\/+/, "").replace(/\/+$/, "");
13087
13139
  return normalized;
13088
13140
  }
13089
13141
  function projectEntries(config) {
@@ -13109,10 +13161,10 @@ function manifestPathForProject(rootDir, manifest) {
13109
13161
  if (!rawPath) {
13110
13162
  return toPosix(manifest.storedPath);
13111
13163
  }
13112
- if (!path22.isAbsolute(rawPath)) {
13164
+ if (!path23.isAbsolute(rawPath)) {
13113
13165
  return normalizeProjectRoot(rawPath);
13114
13166
  }
13115
- const relative = toPosix(path22.relative(rootDir, rawPath));
13167
+ const relative = toPosix(path23.relative(rootDir, rawPath));
13116
13168
  return relative.startsWith("..") ? toPosix(rawPath) : normalizeProjectRoot(relative);
13117
13169
  }
13118
13170
  function prefixMatches(value, prefix) {
@@ -13265,6 +13317,7 @@ function approvalSummary(manifest) {
13265
13317
  createdAt: manifest.createdAt,
13266
13318
  bundleType: manifest.bundleType,
13267
13319
  title: manifest.title,
13320
+ sourceSessionId: manifest.sourceSessionId,
13268
13321
  entryCount: manifest.entries.length,
13269
13322
  pendingCount: manifest.entries.filter((entry) => entry.status === "pending").length,
13270
13323
  acceptedCount: manifest.entries.filter((entry) => entry.status === "accepted").length,
@@ -13288,7 +13341,7 @@ function pageHashes(pages) {
13288
13341
  return Object.fromEntries(pages.map((page) => [page.page.id, page.contentHash]));
13289
13342
  }
13290
13343
  async function buildManagedGraphPage(absolutePath, defaults, build) {
13291
- const existingContent = await fileExists(absolutePath) ? await fs18.readFile(absolutePath, "utf8") : null;
13344
+ const existingContent = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
13292
13345
  let existing = await loadExistingManagedPageState(absolutePath, {
13293
13346
  status: defaults.status ?? "active",
13294
13347
  managedBy: defaults.managedBy
@@ -13326,7 +13379,7 @@ async function buildManagedGraphPage(absolutePath, defaults, build) {
13326
13379
  return built;
13327
13380
  }
13328
13381
  async function buildManagedContent(absolutePath, defaults, build) {
13329
- const existingContent = await fileExists(absolutePath) ? await fs18.readFile(absolutePath, "utf8") : null;
13382
+ const existingContent = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
13330
13383
  let existing = await loadExistingManagedPageState(absolutePath, {
13331
13384
  status: defaults.status ?? "active",
13332
13385
  managedBy: defaults.managedBy
@@ -13368,7 +13421,7 @@ function manifestDetailValue(manifest, key) {
13368
13421
  }
13369
13422
  async function loadAnalysesBySourceIds(paths, sourceIds) {
13370
13423
  const analyses = await Promise.all(
13371
- sourceIds.map(async (sourceId) => await readJsonFile(path22.join(paths.analysesDir, `${sourceId}.json`)))
13424
+ sourceIds.map(async (sourceId) => await readJsonFile(path23.join(paths.analysesDir, `${sourceId}.json`)))
13372
13425
  );
13373
13426
  return analyses.filter((analysis) => Boolean(analysis?.sourceId));
13374
13427
  }
@@ -13377,6 +13430,7 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13377
13430
  const reviewPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-reviews/"));
13378
13431
  const briefPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-briefs/"));
13379
13432
  const guidePages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-guides/"));
13433
+ const sessionPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-sessions/"));
13380
13434
  const conceptPages = graph.pages.filter((page) => page.kind === "concept" && page.status !== "candidate").slice(0, 16);
13381
13435
  const entityPages = graph.pages.filter((page) => page.kind === "entity" && page.status !== "candidate").slice(0, 16);
13382
13436
  const manifests = graph.sources;
@@ -13387,9 +13441,10 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13387
13441
  const openQuestions = uniqueStrings3(
13388
13442
  analyses.flatMap((analysis) => analysis.questions.map((question) => `${analysis.title}: ${question}`))
13389
13443
  ).slice(0, 20);
13444
+ const sourceSessions = await listGuidedSourceSessions(paths.rootDir);
13390
13445
  const stagedGuideBundles = (await Promise.all(
13391
- (await fs18.readdir(paths.approvalsDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map(async (entry) => await readJsonFile(approvalManifestPath(paths, entry.name)))
13392
- )).filter((manifest) => Boolean(manifest)).filter((manifest) => manifest.bundleType === "guided_source").sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, 12);
13446
+ (await fs19.readdir(paths.approvalsDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map(async (entry) => await readJsonFile(approvalManifestPath(paths, entry.name)))
13447
+ )).filter((manifest) => Boolean(manifest)).filter((manifest) => manifest.bundleType === "guided_source" || manifest.bundleType === "guided_session").sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, 12);
13393
13448
  const dashboards = [
13394
13449
  {
13395
13450
  relativePath: "dashboards/index.md",
@@ -13401,6 +13456,7 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13401
13456
  "- [[dashboards/recent-sources|Recent Sources]]",
13402
13457
  "- [[dashboards/reading-log|Reading Log]]",
13403
13458
  "- [[dashboards/timeline|Timeline]]",
13459
+ "- [[dashboards/source-sessions|Source Sessions]]",
13404
13460
  "- [[dashboards/source-guides|Source Guides]]",
13405
13461
  "- [[dashboards/research-map|Research Map]]",
13406
13462
  "- [[dashboards/contradictions|Contradictions]]",
@@ -13487,6 +13543,14 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13487
13543
  const participants = manifestDetailValue(manifest, "participants");
13488
13544
  return `- ${occurredAt}: ${manifest.title}${participants ? ` (${participants})` : ""}`;
13489
13545
  }) : recentSourcePages.map((page) => `- ${page.updatedAt}: [[${page.path.replace(/\.md$/, "")}|${page.title}]]`),
13546
+ ...sourceSessions.length ? [
13547
+ "",
13548
+ "## Active Guided Sessions",
13549
+ "",
13550
+ ...sourceSessions.slice(0, 8).map(
13551
+ (session) => `- ${session.updatedAt}: \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`
13552
+ )
13553
+ ] : [],
13490
13554
  "",
13491
13555
  "```dataview",
13492
13556
  "TABLE occurred_at, source_type, participants, container_title",
@@ -13561,6 +13625,59 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13561
13625
  }
13562
13626
  )
13563
13627
  },
13628
+ {
13629
+ relativePath: "dashboards/source-sessions.md",
13630
+ title: "Source Sessions",
13631
+ content: (metadata) => matter9.stringify(
13632
+ [
13633
+ "# Source Sessions",
13634
+ "",
13635
+ "## Active Sessions",
13636
+ "",
13637
+ ...sourceSessions.length ? sourceSessions.slice(0, 16).map(
13638
+ (session) => `- ${session.updatedAt}: \`${session.status}\` \`${session.sessionId}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`
13639
+ ) : ["- No guided source sessions yet."],
13640
+ "",
13641
+ "## Pending Guided Bundles",
13642
+ "",
13643
+ ...stagedGuideBundles.length ? stagedGuideBundles.map(
13644
+ (bundle) => `- ${bundle.createdAt}: \`${bundle.approvalId}\`${bundle.title ? ` ${bundle.title}` : ""} (${bundle.entries.length} staged entr${bundle.entries.length === 1 ? "y" : "ies"})`
13645
+ ) : ["- No staged guided bundles right now."],
13646
+ "",
13647
+ "```dataview",
13648
+ 'LIST FROM "outputs/source-sessions"',
13649
+ "SORT file.mtime desc",
13650
+ "```",
13651
+ ""
13652
+ ].join("\n"),
13653
+ {
13654
+ page_id: "dashboards:source-sessions",
13655
+ kind: "index",
13656
+ title: "Source Sessions",
13657
+ tags: ["index", "dashboard", "source-sessions"],
13658
+ source_ids: uniqueStrings3([
13659
+ ...sessionPages.flatMap((page) => page.sourceIds),
13660
+ ...sourceSessions.flatMap((session) => session.sourceIds)
13661
+ ]),
13662
+ project_ids: [],
13663
+ node_ids: [],
13664
+ freshness: "fresh",
13665
+ status: metadata.status,
13666
+ confidence: 1,
13667
+ created_at: metadata.createdAt,
13668
+ updated_at: metadata.updatedAt,
13669
+ compiled_from: uniqueStrings3([
13670
+ ...sessionPages.flatMap((page) => page.sourceIds),
13671
+ ...sourceSessions.flatMap((session) => session.sourceIds)
13672
+ ]),
13673
+ managed_by: metadata.managedBy,
13674
+ backlinks: [],
13675
+ schema_hash: schemaHash,
13676
+ source_hashes: {},
13677
+ source_semantic_hashes: {}
13678
+ }
13679
+ )
13680
+ },
13564
13681
  {
13565
13682
  relativePath: "dashboards/source-guides.md",
13566
13683
  title: "Source Guides",
@@ -13628,6 +13745,10 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13628
13745
  "## Recently Guided Sources",
13629
13746
  "",
13630
13747
  ...guidePages.length ? guidePages.slice(0, 8).map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No accepted source guides yet."],
13748
+ "",
13749
+ "## Active Source Sessions",
13750
+ "",
13751
+ ...sourceSessions.length ? sourceSessions.slice(0, 8).map((session) => `- \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`) : ["- No active source sessions yet."],
13631
13752
  ...report?.suggestedQuestions?.length ? ["", "## Suggested Questions", "", ...report.suggestedQuestions.slice(0, 8).map((question) => `- ${question}`)] : [],
13632
13753
  "",
13633
13754
  "```dataview",
@@ -13722,9 +13843,15 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13722
13843
  "# Open Questions",
13723
13844
  "",
13724
13845
  ...openQuestions.length ? openQuestions.map((question) => `- ${question}`) : ["- No open questions are currently extracted."],
13846
+ ...sourceSessions.length ? [
13847
+ "",
13848
+ "## Active Guided Sessions",
13849
+ "",
13850
+ ...sourceSessions.filter((session) => session.status === "awaiting_input" || session.status === "staged").slice(0, 8).map((session) => `- \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`)
13851
+ ] : [],
13725
13852
  "",
13726
13853
  "```dataview",
13727
- 'LIST FROM "outputs/source-briefs" OR "outputs/source-reviews" OR "outputs/source-guides"',
13854
+ 'LIST FROM "outputs/source-briefs" OR "outputs/source-reviews" OR "outputs/source-guides" OR "outputs/source-sessions"',
13728
13855
  "SORT file.mtime desc",
13729
13856
  "```",
13730
13857
  ""
@@ -13754,7 +13881,7 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13754
13881
  ];
13755
13882
  const records = [];
13756
13883
  for (const dashboard of dashboards) {
13757
- const absolutePath = path22.join(paths.wikiDir, dashboard.relativePath);
13884
+ const absolutePath = path23.join(paths.wikiDir, dashboard.relativePath);
13758
13885
  const compiledFrom = dashboard.relativePath === "dashboards/recent-sources.md" ? recentSourcePages.flatMap((page) => page.sourceIds) : [];
13759
13886
  const content = await buildManagedContent(
13760
13887
  absolutePath,
@@ -13868,7 +13995,7 @@ function resetGraphNodeMetrics(nodes) {
13868
13995
  return nodes.map(({ communityId: _communityId, degree: _degree, bridgeScore: _bridgeScore, isGodNode: _isGodNode, ...node }) => node);
13869
13996
  }
13870
13997
  function manifestRepoPath(manifest) {
13871
- return toPosix(manifest.repoRelativePath ?? path22.basename(manifest.originalPath ?? manifest.storedPath));
13998
+ return toPosix(manifest.repoRelativePath ?? path23.basename(manifest.originalPath ?? manifest.storedPath));
13872
13999
  }
13873
14000
  function goPackageScopeKey(manifest, analysis) {
13874
14001
  if (analysis.code?.language !== "go") {
@@ -13878,7 +14005,7 @@ function goPackageScopeKey(manifest, analysis) {
13878
14005
  if (!packageName) {
13879
14006
  return null;
13880
14007
  }
13881
- return `${packageName}:${path22.posix.dirname(manifestRepoPath(manifest))}`;
14008
+ return `${packageName}:${path23.posix.dirname(manifestRepoPath(manifest))}`;
13882
14009
  }
13883
14010
  function buildGoPackageSymbolLookups(analyses, manifestsById) {
13884
14011
  const lookups = /* @__PURE__ */ new Map();
@@ -14347,7 +14474,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14347
14474
  const benchmark = await readJsonFile(paths.benchmarkPath);
14348
14475
  const communityRecords = [];
14349
14476
  for (const community of graph.communities ?? []) {
14350
- const absolutePath = path22.join(paths.wikiDir, "graph", "communities", `${community.id.replace(/^community:/, "")}.md`);
14477
+ const absolutePath = path23.join(paths.wikiDir, "graph", "communities", `${community.id.replace(/^community:/, "")}.md`);
14351
14478
  communityRecords.push(
14352
14479
  await buildManagedGraphPage(
14353
14480
  absolutePath,
@@ -14376,7 +14503,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14376
14503
  graphHash: graphHash(graph),
14377
14504
  contradictions
14378
14505
  });
14379
- const reportAbsolutePath = path22.join(paths.wikiDir, "graph", "report.md");
14506
+ const reportAbsolutePath = path23.join(paths.wikiDir, "graph", "report.md");
14380
14507
  const reportRecord = await buildManagedGraphPage(
14381
14508
  reportAbsolutePath,
14382
14509
  {
@@ -14397,7 +14524,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14397
14524
  };
14398
14525
  }
14399
14526
  async function writePage(wikiDir, relativePath, content, changedPages) {
14400
- const absolutePath = path22.resolve(wikiDir, relativePath);
14527
+ const absolutePath = path23.resolve(wikiDir, relativePath);
14401
14528
  const changed = await writeFileIfChanged(absolutePath, content);
14402
14529
  if (changed) {
14403
14530
  changedPages.push(relativePath);
@@ -14463,29 +14590,29 @@ async function requiredCompileArtifactsExist(paths) {
14463
14590
  paths.graphPath,
14464
14591
  paths.codeIndexPath,
14465
14592
  paths.searchDbPath,
14466
- path22.join(paths.wikiDir, "index.md"),
14467
- path22.join(paths.wikiDir, "sources", "index.md"),
14468
- path22.join(paths.wikiDir, "code", "index.md"),
14469
- path22.join(paths.wikiDir, "concepts", "index.md"),
14470
- path22.join(paths.wikiDir, "entities", "index.md"),
14471
- path22.join(paths.wikiDir, "outputs", "index.md"),
14472
- path22.join(paths.wikiDir, "projects", "index.md"),
14473
- path22.join(paths.wikiDir, "candidates", "index.md")
14593
+ path23.join(paths.wikiDir, "index.md"),
14594
+ path23.join(paths.wikiDir, "sources", "index.md"),
14595
+ path23.join(paths.wikiDir, "code", "index.md"),
14596
+ path23.join(paths.wikiDir, "concepts", "index.md"),
14597
+ path23.join(paths.wikiDir, "entities", "index.md"),
14598
+ path23.join(paths.wikiDir, "outputs", "index.md"),
14599
+ path23.join(paths.wikiDir, "projects", "index.md"),
14600
+ path23.join(paths.wikiDir, "candidates", "index.md")
14474
14601
  ];
14475
14602
  const checks = await Promise.all(requiredPaths.map((filePath) => fileExists(filePath)));
14476
14603
  return checks.every(Boolean);
14477
14604
  }
14478
14605
  async function loadAvailableCachedAnalyses(paths, manifests) {
14479
14606
  const analyses = await Promise.all(
14480
- manifests.map(async (manifest) => readJsonFile(path22.join(paths.analysesDir, `${manifest.sourceId}.json`)))
14607
+ manifests.map(async (manifest) => readJsonFile(path23.join(paths.analysesDir, `${manifest.sourceId}.json`)))
14481
14608
  );
14482
14609
  return analyses.filter((analysis) => Boolean(analysis));
14483
14610
  }
14484
14611
  function approvalManifestPath(paths, approvalId) {
14485
- return path22.join(paths.approvalsDir, approvalId, "manifest.json");
14612
+ return path23.join(paths.approvalsDir, approvalId, "manifest.json");
14486
14613
  }
14487
14614
  function approvalGraphPath(paths, approvalId) {
14488
- return path22.join(paths.approvalsDir, approvalId, "state", "graph.json");
14615
+ return path23.join(paths.approvalsDir, approvalId, "state", "graph.json");
14489
14616
  }
14490
14617
  async function readApprovalManifest(paths, approvalId) {
14491
14618
  const manifest = await readJsonFile(approvalManifestPath(paths, approvalId));
@@ -14495,7 +14622,7 @@ async function readApprovalManifest(paths, approvalId) {
14495
14622
  return manifest;
14496
14623
  }
14497
14624
  async function writeApprovalManifest(paths, manifest) {
14498
- await fs18.writeFile(approvalManifestPath(paths, manifest.approvalId), `${JSON.stringify(manifest, null, 2)}
14625
+ await fs19.writeFile(approvalManifestPath(paths, manifest.approvalId), `${JSON.stringify(manifest, null, 2)}
14499
14626
  `, "utf8");
14500
14627
  }
14501
14628
  async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousGraph, graph, labelsByPath = /* @__PURE__ */ new Map()) {
@@ -14510,7 +14637,7 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14510
14637
  continue;
14511
14638
  }
14512
14639
  const previousPage = previousPagesById.get(nextPage.id);
14513
- const currentExists = await fileExists(path22.join(paths.wikiDir, file.relativePath));
14640
+ const currentExists = await fileExists(path23.join(paths.wikiDir, file.relativePath));
14514
14641
  if (previousPage && previousPage.path !== nextPage.path) {
14515
14642
  entries.push({
14516
14643
  pageId: nextPage.id,
@@ -14545,7 +14672,7 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14545
14672
  const previousPage = previousPagesByPath.get(deletedPath);
14546
14673
  entries.push({
14547
14674
  pageId: previousPage?.id ?? `page:${slugify(deletedPath)}`,
14548
- title: previousPage?.title ?? path22.basename(deletedPath, ".md"),
14675
+ title: previousPage?.title ?? path23.basename(deletedPath, ".md"),
14549
14676
  kind: previousPage?.kind ?? "index",
14550
14677
  changeType: "delete",
14551
14678
  status: "pending",
@@ -14558,16 +14685,16 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14558
14685
  }
14559
14686
  async function stageApprovalBundle(paths, changedFiles, deletedPaths, previousGraph, graph) {
14560
14687
  const approvalId = `compile-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
14561
- const approvalDir = path22.join(paths.approvalsDir, approvalId);
14688
+ const approvalDir = path23.join(paths.approvalsDir, approvalId);
14562
14689
  await ensureDir(approvalDir);
14563
- await ensureDir(path22.join(approvalDir, "wiki"));
14564
- await ensureDir(path22.join(approvalDir, "state"));
14690
+ await ensureDir(path23.join(approvalDir, "wiki"));
14691
+ await ensureDir(path23.join(approvalDir, "state"));
14565
14692
  for (const file of changedFiles) {
14566
- const targetPath = path22.join(approvalDir, "wiki", file.relativePath);
14567
- await ensureDir(path22.dirname(targetPath));
14568
- await fs18.writeFile(targetPath, file.content, "utf8");
14693
+ const targetPath = path23.join(approvalDir, "wiki", file.relativePath);
14694
+ await ensureDir(path23.dirname(targetPath));
14695
+ await fs19.writeFile(targetPath, file.content, "utf8");
14569
14696
  }
14570
- await fs18.writeFile(path22.join(approvalDir, "state", "graph.json"), JSON.stringify(graph, null, 2), "utf8");
14697
+ await fs19.writeFile(path23.join(approvalDir, "state", "graph.json"), JSON.stringify(graph, null, 2), "utf8");
14571
14698
  await writeApprovalManifest(paths, {
14572
14699
  approvalId,
14573
14700
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -14633,7 +14760,7 @@ async function syncVaultArtifacts(rootDir, input) {
14633
14760
  confidence: 1
14634
14761
  });
14635
14762
  const sourceRecord = await buildManagedGraphPage(
14636
- path22.join(paths.wikiDir, preview.path),
14763
+ path23.join(paths.wikiDir, preview.path),
14637
14764
  {
14638
14765
  managedBy: "system",
14639
14766
  confidence: 1,
@@ -14679,7 +14806,7 @@ async function syncVaultArtifacts(rootDir, input) {
14679
14806
  );
14680
14807
  records.push(
14681
14808
  await buildManagedGraphPage(
14682
- path22.join(paths.wikiDir, modulePreview.path),
14809
+ path23.join(paths.wikiDir, modulePreview.path),
14683
14810
  {
14684
14811
  managedBy: "system",
14685
14812
  confidence: 1,
@@ -14713,8 +14840,8 @@ async function syncVaultArtifacts(rootDir, input) {
14713
14840
  const relativePath = promoted ? activeAggregatePath(itemKind, slug) : candidatePagePathFor(itemKind, slug);
14714
14841
  const aggregateSourceClass2 = aggregateManifestSourceClass(input.manifests, sourceIds);
14715
14842
  const fallbackPaths = [
14716
- path22.join(paths.wikiDir, activeAggregatePath(itemKind, slug)),
14717
- path22.join(paths.wikiDir, candidatePagePathFor(itemKind, slug))
14843
+ path23.join(paths.wikiDir, activeAggregatePath(itemKind, slug)),
14844
+ path23.join(paths.wikiDir, candidatePagePathFor(itemKind, slug))
14718
14845
  ];
14719
14846
  const confidence = nodeConfidence(aggregate.sourceAnalyses.length);
14720
14847
  const preview = emptyGraphPage({
@@ -14732,7 +14859,7 @@ async function syncVaultArtifacts(rootDir, input) {
14732
14859
  status: promoted ? "active" : "candidate"
14733
14860
  });
14734
14861
  const pageRecord = await buildManagedGraphPage(
14735
- path22.join(paths.wikiDir, relativePath),
14862
+ path23.join(paths.wikiDir, relativePath),
14736
14863
  {
14737
14864
  status: promoted ? "active" : "candidate",
14738
14865
  managedBy: "system",
@@ -14861,7 +14988,7 @@ async function syncVaultArtifacts(rootDir, input) {
14861
14988
  confidence: 1
14862
14989
  }),
14863
14990
  content: await buildManagedContent(
14864
- path22.join(paths.wikiDir, "projects", "index.md"),
14991
+ path23.join(paths.wikiDir, "projects", "index.md"),
14865
14992
  {
14866
14993
  managedBy: "system",
14867
14994
  compiledFrom: indexCompiledFrom(projectIndexRefs)
@@ -14885,7 +15012,7 @@ async function syncVaultArtifacts(rootDir, input) {
14885
15012
  records.push({
14886
15013
  page: projectIndexRef,
14887
15014
  content: await buildManagedContent(
14888
- path22.join(paths.wikiDir, projectIndexRef.path),
15015
+ path23.join(paths.wikiDir, projectIndexRef.path),
14889
15016
  {
14890
15017
  managedBy: "system",
14891
15018
  compiledFrom: indexCompiledFrom(Object.values(sections).flat())
@@ -14913,7 +15040,7 @@ async function syncVaultArtifacts(rootDir, input) {
14913
15040
  confidence: 1
14914
15041
  }),
14915
15042
  content: await buildManagedContent(
14916
- path22.join(paths.wikiDir, "index.md"),
15043
+ path23.join(paths.wikiDir, "index.md"),
14917
15044
  {
14918
15045
  managedBy: "system",
14919
15046
  compiledFrom: indexCompiledFrom(allPages)
@@ -14949,7 +15076,7 @@ async function syncVaultArtifacts(rootDir, input) {
14949
15076
  confidence: 1
14950
15077
  }),
14951
15078
  content: await buildManagedContent(
14952
- path22.join(paths.wikiDir, relativePath),
15079
+ path23.join(paths.wikiDir, relativePath),
14953
15080
  {
14954
15081
  managedBy: "system",
14955
15082
  compiledFrom: indexCompiledFrom(pages)
@@ -14960,12 +15087,12 @@ async function syncVaultArtifacts(rootDir, input) {
14960
15087
  }
14961
15088
  const nextPagePaths = new Set(records.map((record) => record.page.path));
14962
15089
  const obsoleteGraphPaths = (previousGraph?.pages ?? []).filter((page) => page.kind !== "output" && page.kind !== "insight").map((page) => page.path).filter((relativePath) => !nextPagePaths.has(relativePath));
14963
- const existingProjectIndexPaths = (await listFilesRecursive(paths.projectsDir)).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path22.relative(paths.wikiDir, absolutePath))).filter((relativePath) => !nextPagePaths.has(relativePath));
15090
+ const existingProjectIndexPaths = (await listFilesRecursive(paths.projectsDir)).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path23.relative(paths.wikiDir, absolutePath))).filter((relativePath) => !nextPagePaths.has(relativePath));
14964
15091
  const obsoletePaths = uniqueStrings3([...obsoleteGraphPaths, ...existingProjectIndexPaths]);
14965
15092
  const changedFiles = [];
14966
15093
  for (const record of records) {
14967
- const absolutePath = path22.join(paths.wikiDir, record.page.path);
14968
- const current = await fileExists(absolutePath) ? await fs18.readFile(absolutePath, "utf8") : null;
15094
+ const absolutePath = path23.join(paths.wikiDir, record.page.path);
15095
+ const current = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
14969
15096
  if (current !== record.content) {
14970
15097
  changedPages.push(record.page.path);
14971
15098
  changedFiles.push({ relativePath: record.page.path, content: record.content });
@@ -14990,10 +15117,10 @@ async function syncVaultArtifacts(rootDir, input) {
14990
15117
  await writePage(paths.wikiDir, record.page.path, record.content, writeChanges);
14991
15118
  }
14992
15119
  for (const relativePath of obsoletePaths) {
14993
- await fs18.rm(path22.join(paths.wikiDir, relativePath), { force: true });
15120
+ await fs19.rm(path23.join(paths.wikiDir, relativePath), { force: true });
14994
15121
  }
14995
15122
  await writeJsonFile(paths.graphPath, graph);
14996
- await writeJsonFile(path22.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15123
+ await writeJsonFile(path23.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
14997
15124
  await writeJsonFile(paths.codeIndexPath, input.codeIndex);
14998
15125
  await writeJsonFile(paths.compileStatePath, {
14999
15126
  generatedAt: graph.generatedAt,
@@ -15088,18 +15215,18 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15088
15215
  })
15089
15216
  );
15090
15217
  await Promise.all([
15091
- ensureDir(path22.join(paths.wikiDir, "sources")),
15092
- ensureDir(path22.join(paths.wikiDir, "code")),
15093
- ensureDir(path22.join(paths.wikiDir, "concepts")),
15094
- ensureDir(path22.join(paths.wikiDir, "entities")),
15095
- ensureDir(path22.join(paths.wikiDir, "outputs")),
15096
- ensureDir(path22.join(paths.wikiDir, "dashboards")),
15097
- ensureDir(path22.join(paths.wikiDir, "graph")),
15098
- ensureDir(path22.join(paths.wikiDir, "graph", "communities")),
15099
- ensureDir(path22.join(paths.wikiDir, "projects")),
15100
- ensureDir(path22.join(paths.wikiDir, "candidates"))
15218
+ ensureDir(path23.join(paths.wikiDir, "sources")),
15219
+ ensureDir(path23.join(paths.wikiDir, "code")),
15220
+ ensureDir(path23.join(paths.wikiDir, "concepts")),
15221
+ ensureDir(path23.join(paths.wikiDir, "entities")),
15222
+ ensureDir(path23.join(paths.wikiDir, "outputs")),
15223
+ ensureDir(path23.join(paths.wikiDir, "dashboards")),
15224
+ ensureDir(path23.join(paths.wikiDir, "graph")),
15225
+ ensureDir(path23.join(paths.wikiDir, "graph", "communities")),
15226
+ ensureDir(path23.join(paths.wikiDir, "projects")),
15227
+ ensureDir(path23.join(paths.wikiDir, "candidates"))
15101
15228
  ]);
15102
- const projectsIndexPath = path22.join(paths.wikiDir, "projects", "index.md");
15229
+ const projectsIndexPath = path23.join(paths.wikiDir, "projects", "index.md");
15103
15230
  await writeFileIfChanged(
15104
15231
  projectsIndexPath,
15105
15232
  await buildManagedContent(
@@ -15120,7 +15247,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15120
15247
  outputs: pages.filter((page) => page.kind === "output" && page.projectIds.includes(project.id)),
15121
15248
  candidates: pages.filter((page) => page.status === "candidate" && page.projectIds.includes(project.id))
15122
15249
  };
15123
- const absolutePath = path22.join(paths.wikiDir, "projects", project.id, "index.md");
15250
+ const absolutePath = path23.join(paths.wikiDir, "projects", project.id, "index.md");
15124
15251
  await writeFileIfChanged(
15125
15252
  absolutePath,
15126
15253
  await buildManagedContent(
@@ -15138,7 +15265,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15138
15265
  )
15139
15266
  );
15140
15267
  }
15141
- const rootIndexPath = path22.join(paths.wikiDir, "index.md");
15268
+ const rootIndexPath = path23.join(paths.wikiDir, "index.md");
15142
15269
  await writeFileIfChanged(
15143
15270
  rootIndexPath,
15144
15271
  await buildManagedContent(
@@ -15164,7 +15291,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15164
15291
  ["candidates/index.md", "candidates", pagesWithGraph.filter((page) => page.status === "candidate")],
15165
15292
  ["graph/index.md", "graph", pagesWithGraph.filter((page) => page.kind === "graph_report" || page.kind === "community_summary")]
15166
15293
  ]) {
15167
- const absolutePath = path22.join(paths.wikiDir, relativePath);
15294
+ const absolutePath = path23.join(paths.wikiDir, relativePath);
15168
15295
  await writeFileIfChanged(
15169
15296
  absolutePath,
15170
15297
  await buildManagedContent(
@@ -15178,31 +15305,31 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15178
15305
  );
15179
15306
  }
15180
15307
  for (const record of graphOrientation.records) {
15181
- await writeFileIfChanged(path22.join(paths.wikiDir, record.page.path), record.content);
15308
+ await writeFileIfChanged(path23.join(paths.wikiDir, record.page.path), record.content);
15182
15309
  }
15183
15310
  for (const record of dashboardRecords) {
15184
- await writeFileIfChanged(path22.join(paths.wikiDir, record.page.path), record.content);
15311
+ await writeFileIfChanged(path23.join(paths.wikiDir, record.page.path), record.content);
15185
15312
  }
15186
15313
  if (graphOrientation.report) {
15187
- await writeJsonFile(path22.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15314
+ await writeJsonFile(path23.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15188
15315
  }
15189
- const existingProjectIndexPaths = (await listFilesRecursive(paths.projectsDir)).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path22.relative(paths.wikiDir, absolutePath)));
15316
+ const existingProjectIndexPaths = (await listFilesRecursive(paths.projectsDir)).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path23.relative(paths.wikiDir, absolutePath)));
15190
15317
  const allowedProjectIndexPaths = /* @__PURE__ */ new Set([
15191
15318
  "projects/index.md",
15192
15319
  ...configuredProjects.map((project) => `projects/${project.id}/index.md`)
15193
15320
  ]);
15194
15321
  await Promise.all(
15195
- existingProjectIndexPaths.filter((relativePath) => !allowedProjectIndexPaths.has(relativePath)).map((relativePath) => fs18.rm(path22.join(paths.wikiDir, relativePath), { force: true }))
15322
+ existingProjectIndexPaths.filter((relativePath) => !allowedProjectIndexPaths.has(relativePath)).map((relativePath) => fs19.rm(path23.join(paths.wikiDir, relativePath), { force: true }))
15196
15323
  );
15197
- const existingGraphPages = (await listFilesRecursive(path22.join(paths.wikiDir, "graph").replace(/\/$/, "")).catch(() => [])).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path22.relative(paths.wikiDir, absolutePath)));
15324
+ const existingGraphPages = (await listFilesRecursive(path23.join(paths.wikiDir, "graph").replace(/\/$/, "")).catch(() => [])).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path23.relative(paths.wikiDir, absolutePath)));
15198
15325
  const allowedGraphPages = /* @__PURE__ */ new Set(["graph/index.md", ...graphOrientation.records.map((record) => record.page.path)]);
15199
15326
  await Promise.all(
15200
- existingGraphPages.filter((relativePath) => !allowedGraphPages.has(relativePath)).map((relativePath) => fs18.rm(path22.join(paths.wikiDir, relativePath), { force: true }))
15327
+ existingGraphPages.filter((relativePath) => !allowedGraphPages.has(relativePath)).map((relativePath) => fs19.rm(path23.join(paths.wikiDir, relativePath), { force: true }))
15201
15328
  );
15202
- const existingDashboardPages = (await listFilesRecursive(path22.join(paths.wikiDir, "dashboards")).catch(() => [])).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path22.relative(paths.wikiDir, absolutePath)));
15329
+ const existingDashboardPages = (await listFilesRecursive(path23.join(paths.wikiDir, "dashboards")).catch(() => [])).filter((absolutePath) => absolutePath.endsWith(".md")).map((absolutePath) => toPosix(path23.relative(paths.wikiDir, absolutePath)));
15203
15330
  const allowedDashboardPages = /* @__PURE__ */ new Set(["dashboards/index.md", ...dashboardRecords.map((record) => record.page.path)]);
15204
15331
  await Promise.all(
15205
- existingDashboardPages.filter((relativePath) => !allowedDashboardPages.has(relativePath)).map((relativePath) => fs18.rm(path22.join(paths.wikiDir, relativePath), { force: true }))
15332
+ existingDashboardPages.filter((relativePath) => !allowedDashboardPages.has(relativePath)).map((relativePath) => fs19.rm(path23.join(paths.wikiDir, relativePath), { force: true }))
15206
15333
  );
15207
15334
  await rebuildSearchIndex(paths.searchDbPath, pagesWithGraph, paths.wikiDir);
15208
15335
  }
@@ -15222,7 +15349,7 @@ async function prepareOutputPageSave(rootDir, input) {
15222
15349
  confidence: 0.74
15223
15350
  }
15224
15351
  });
15225
- const absolutePath = path22.join(paths.wikiDir, output.page.path);
15352
+ const absolutePath = path23.join(paths.wikiDir, output.page.path);
15226
15353
  return {
15227
15354
  page: output.page,
15228
15355
  savedPath: absolutePath,
@@ -15234,15 +15361,15 @@ async function prepareOutputPageSave(rootDir, input) {
15234
15361
  async function persistOutputPage(rootDir, input) {
15235
15362
  const { paths } = await loadVaultConfig(rootDir);
15236
15363
  const prepared = await prepareOutputPageSave(rootDir, input);
15237
- await ensureDir(path22.dirname(prepared.savedPath));
15238
- await fs18.writeFile(prepared.savedPath, prepared.content, "utf8");
15364
+ await ensureDir(path23.dirname(prepared.savedPath));
15365
+ await fs19.writeFile(prepared.savedPath, prepared.content, "utf8");
15239
15366
  for (const assetFile of prepared.assetFiles) {
15240
- const assetPath = path22.join(paths.wikiDir, assetFile.relativePath);
15241
- await ensureDir(path22.dirname(assetPath));
15367
+ const assetPath = path23.join(paths.wikiDir, assetFile.relativePath);
15368
+ await ensureDir(path23.dirname(assetPath));
15242
15369
  if (typeof assetFile.content === "string") {
15243
- await fs18.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15370
+ await fs19.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15244
15371
  } else {
15245
- await fs18.writeFile(assetPath, assetFile.content);
15372
+ await fs19.writeFile(assetPath, assetFile.content);
15246
15373
  }
15247
15374
  }
15248
15375
  return { page: prepared.page, savedPath: prepared.savedPath, outputAssets: prepared.outputAssets };
@@ -15263,7 +15390,7 @@ async function prepareExploreHubSave(rootDir, input) {
15263
15390
  confidence: 0.76
15264
15391
  }
15265
15392
  });
15266
- const absolutePath = path22.join(paths.wikiDir, hub.page.path);
15393
+ const absolutePath = path23.join(paths.wikiDir, hub.page.path);
15267
15394
  return {
15268
15395
  page: hub.page,
15269
15396
  savedPath: absolutePath,
@@ -15275,15 +15402,15 @@ async function prepareExploreHubSave(rootDir, input) {
15275
15402
  async function persistExploreHub(rootDir, input) {
15276
15403
  const { paths } = await loadVaultConfig(rootDir);
15277
15404
  const prepared = await prepareExploreHubSave(rootDir, input);
15278
- await ensureDir(path22.dirname(prepared.savedPath));
15279
- await fs18.writeFile(prepared.savedPath, prepared.content, "utf8");
15405
+ await ensureDir(path23.dirname(prepared.savedPath));
15406
+ await fs19.writeFile(prepared.savedPath, prepared.content, "utf8");
15280
15407
  for (const assetFile of prepared.assetFiles) {
15281
- const assetPath = path22.join(paths.wikiDir, assetFile.relativePath);
15282
- await ensureDir(path22.dirname(assetPath));
15408
+ const assetPath = path23.join(paths.wikiDir, assetFile.relativePath);
15409
+ await ensureDir(path23.dirname(assetPath));
15283
15410
  if (typeof assetFile.content === "string") {
15284
- await fs18.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15411
+ await fs19.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15285
15412
  } else {
15286
- await fs18.writeFile(assetPath, assetFile.content);
15413
+ await fs19.writeFile(assetPath, assetFile.content);
15287
15414
  }
15288
15415
  }
15289
15416
  return { page: prepared.page, savedPath: prepared.savedPath, outputAssets: prepared.outputAssets };
@@ -15301,17 +15428,17 @@ async function stageOutputApprovalBundle(rootDir, stagedPages, options = {}) {
15301
15428
  ]);
15302
15429
  const labelsByPath = new Map(stagedPages.filter((item) => item.label).map((item) => [item.page.path, item.label]));
15303
15430
  const approvalId = `schedule-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
15304
- const approvalDir = path22.join(paths.approvalsDir, approvalId);
15431
+ const approvalDir = path23.join(paths.approvalsDir, approvalId);
15305
15432
  await ensureDir(approvalDir);
15306
- await ensureDir(path22.join(approvalDir, "wiki"));
15307
- await ensureDir(path22.join(approvalDir, "state"));
15433
+ await ensureDir(path23.join(approvalDir, "wiki"));
15434
+ await ensureDir(path23.join(approvalDir, "state"));
15308
15435
  for (const file of changedFiles) {
15309
- const targetPath = path22.join(approvalDir, "wiki", file.relativePath);
15310
- await ensureDir(path22.dirname(targetPath));
15436
+ const targetPath = path23.join(approvalDir, "wiki", file.relativePath);
15437
+ await ensureDir(path23.dirname(targetPath));
15311
15438
  if ("binary" in file && file.binary) {
15312
- await fs18.writeFile(targetPath, Buffer.from(file.content, "base64"));
15439
+ await fs19.writeFile(targetPath, Buffer.from(file.content, "base64"));
15313
15440
  } else {
15314
- await fs18.writeFile(targetPath, file.content, "utf8");
15441
+ await fs19.writeFile(targetPath, file.content, "utf8");
15315
15442
  }
15316
15443
  }
15317
15444
  const nextPages = sortGraphPages([
@@ -15326,12 +15453,13 @@ async function stageOutputApprovalBundle(rootDir, stagedPages, options = {}) {
15326
15453
  sources: previousGraph?.sources ?? [],
15327
15454
  pages: nextPages
15328
15455
  };
15329
- await fs18.writeFile(path22.join(approvalDir, "state", "graph.json"), JSON.stringify(graph, null, 2), "utf8");
15456
+ await fs19.writeFile(path23.join(approvalDir, "state", "graph.json"), JSON.stringify(graph, null, 2), "utf8");
15330
15457
  await writeApprovalManifest(paths, {
15331
15458
  approvalId,
15332
15459
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
15333
15460
  bundleType: options.bundleType ?? "generated_output",
15334
15461
  title: options.title,
15462
+ sourceSessionId: options.sourceSessionId,
15335
15463
  entries: await buildApprovalEntries(
15336
15464
  paths,
15337
15465
  stagedPages.map((item) => ({ relativePath: item.page.path, content: item.content })),
@@ -15361,9 +15489,9 @@ async function executeQuery(rootDir, question, format) {
15361
15489
  const searchResults = searchPages(paths.searchDbPath, question, 5);
15362
15490
  const excerpts = await Promise.all(
15363
15491
  searchResults.map(async (result) => {
15364
- const absolutePath = path22.join(paths.wikiDir, result.path);
15492
+ const absolutePath = path23.join(paths.wikiDir, result.path);
15365
15493
  try {
15366
- const content = await fs18.readFile(absolutePath, "utf8");
15494
+ const content = await fs19.readFile(absolutePath, "utf8");
15367
15495
  const parsed = matter9(content);
15368
15496
  return `# ${result.title}
15369
15497
  ${truncate(normalizeWhitespace(parsed.content), 1200)}`;
@@ -15598,7 +15726,7 @@ function computeChangeSummary(current, staged, changeType) {
15598
15726
  async function listApprovals(rootDir) {
15599
15727
  const { paths } = await loadVaultConfig(rootDir);
15600
15728
  const manifests = await Promise.all(
15601
- (await fs18.readdir(paths.approvalsDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map(async (entry) => {
15729
+ (await fs19.readdir(paths.approvalsDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map(async (entry) => {
15602
15730
  try {
15603
15731
  return await readApprovalManifest(paths, entry.name);
15604
15732
  } catch {
@@ -15614,8 +15742,8 @@ async function readApproval(rootDir, approvalId, options) {
15614
15742
  const details = await Promise.all(
15615
15743
  manifest.entries.map(async (entry) => {
15616
15744
  const currentPath = entry.previousPath ?? entry.nextPath;
15617
- const currentContent = currentPath ? await fs18.readFile(path22.join(paths.wikiDir, currentPath), "utf8").catch(() => void 0) : void 0;
15618
- const stagedContent = entry.nextPath ? await fs18.readFile(path22.join(paths.approvalsDir, approvalId, "wiki", entry.nextPath), "utf8").catch(() => void 0) : void 0;
15745
+ const currentContent = currentPath ? await fs19.readFile(path23.join(paths.wikiDir, currentPath), "utf8").catch(() => void 0) : void 0;
15746
+ const stagedContent = entry.nextPath ? await fs19.readFile(path23.join(paths.approvalsDir, approvalId, "wiki", entry.nextPath), "utf8").catch(() => void 0) : void 0;
15619
15747
  const detail = {
15620
15748
  ...entry,
15621
15749
  currentContent,
@@ -15648,26 +15776,26 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15648
15776
  if (!entry.nextPath) {
15649
15777
  throw new Error(`Approval entry ${entry.pageId} is missing a staged path.`);
15650
15778
  }
15651
- const stagedAbsolutePath = path22.join(paths.approvalsDir, approvalId, "wiki", entry.nextPath);
15652
- const stagedContent = await fs18.readFile(stagedAbsolutePath, "utf8");
15653
- const targetAbsolutePath = path22.join(paths.wikiDir, entry.nextPath);
15654
- await ensureDir(path22.dirname(targetAbsolutePath));
15655
- await fs18.writeFile(targetAbsolutePath, stagedContent, "utf8");
15779
+ const stagedAbsolutePath = path23.join(paths.approvalsDir, approvalId, "wiki", entry.nextPath);
15780
+ const stagedContent = await fs19.readFile(stagedAbsolutePath, "utf8");
15781
+ const targetAbsolutePath = path23.join(paths.wikiDir, entry.nextPath);
15782
+ await ensureDir(path23.dirname(targetAbsolutePath));
15783
+ await fs19.writeFile(targetAbsolutePath, stagedContent, "utf8");
15656
15784
  if (entry.changeType === "promote" && entry.previousPath) {
15657
- await fs18.rm(path22.join(paths.wikiDir, entry.previousPath), { force: true });
15785
+ await fs19.rm(path23.join(paths.wikiDir, entry.previousPath), { force: true });
15658
15786
  }
15659
15787
  const nextPage = bundleGraph?.pages.find((page) => page.id === entry.pageId && page.path === entry.nextPath) ?? parseStoredPage(entry.nextPath, stagedContent);
15660
15788
  if (nextPage.kind === "output" && nextPage.outputAssets?.length) {
15661
- const outputAssetDir = path22.join(paths.wikiDir, "outputs", "assets", path22.basename(nextPage.path, ".md"));
15662
- await fs18.rm(outputAssetDir, { recursive: true, force: true });
15789
+ const outputAssetDir = path23.join(paths.wikiDir, "outputs", "assets", path23.basename(nextPage.path, ".md"));
15790
+ await fs19.rm(outputAssetDir, { recursive: true, force: true });
15663
15791
  for (const asset of nextPage.outputAssets) {
15664
- const stagedAssetPath = path22.join(paths.approvalsDir, approvalId, "wiki", asset.path);
15792
+ const stagedAssetPath = path23.join(paths.approvalsDir, approvalId, "wiki", asset.path);
15665
15793
  if (!await fileExists(stagedAssetPath)) {
15666
15794
  continue;
15667
15795
  }
15668
- const targetAssetPath = path22.join(paths.wikiDir, asset.path);
15669
- await ensureDir(path22.dirname(targetAssetPath));
15670
- await fs18.copyFile(stagedAssetPath, targetAssetPath);
15796
+ const targetAssetPath = path23.join(paths.wikiDir, asset.path);
15797
+ await ensureDir(path23.dirname(targetAssetPath));
15798
+ await fs19.copyFile(stagedAssetPath, targetAssetPath);
15671
15799
  }
15672
15800
  }
15673
15801
  nextPages = nextPages.filter(
@@ -15678,10 +15806,10 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15678
15806
  } else {
15679
15807
  const deletedPage = nextPages.find((page) => page.id === entry.pageId || page.path === entry.previousPath) ?? bundleGraph?.pages.find((page) => page.id === entry.pageId || page.path === entry.previousPath) ?? null;
15680
15808
  if (entry.previousPath) {
15681
- await fs18.rm(path22.join(paths.wikiDir, entry.previousPath), { force: true });
15809
+ await fs19.rm(path23.join(paths.wikiDir, entry.previousPath), { force: true });
15682
15810
  }
15683
15811
  if (deletedPage?.kind === "output") {
15684
- await fs18.rm(path22.join(paths.wikiDir, "outputs", "assets", path22.basename(deletedPage.path, ".md")), {
15812
+ await fs19.rm(path23.join(paths.wikiDir, "outputs", "assets", path23.basename(deletedPage.path, ".md")), {
15685
15813
  recursive: true,
15686
15814
  force: true
15687
15815
  });
@@ -15704,6 +15832,9 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15704
15832
  await writeJsonFile(paths.compileStatePath, compileState);
15705
15833
  await refreshIndexesAndSearch(rootDir, nextGraph.pages);
15706
15834
  await writeApprovalManifest(paths, manifest);
15835
+ if (manifest.sourceSessionId) {
15836
+ await updateGuidedSourceSessionStatus(rootDir, manifest.sourceSessionId, "accepted");
15837
+ }
15707
15838
  await recordSession(rootDir, {
15708
15839
  operation: "review",
15709
15840
  title: `Accepted review entries from ${approvalId}`,
@@ -15730,6 +15861,9 @@ async function rejectApproval(rootDir, approvalId, targets = []) {
15730
15861
  entry.status = "rejected";
15731
15862
  }
15732
15863
  await writeApprovalManifest(paths, manifest);
15864
+ if (manifest.sourceSessionId) {
15865
+ await updateGuidedSourceSessionStatus(rootDir, manifest.sourceSessionId, "rejected");
15866
+ }
15733
15867
  await recordSession(rootDir, {
15734
15868
  operation: "review",
15735
15869
  title: `Rejected review entries from ${approvalId}`,
@@ -15772,7 +15906,7 @@ async function promoteCandidate(rootDir, target) {
15772
15906
  const { paths } = await loadVaultConfig(rootDir);
15773
15907
  const graph = await readJsonFile(paths.graphPath);
15774
15908
  const candidate = resolveCandidateTarget(graph?.pages ?? [], target);
15775
- const raw = await fs18.readFile(path22.join(paths.wikiDir, candidate.path), "utf8");
15909
+ const raw = await fs19.readFile(path23.join(paths.wikiDir, candidate.path), "utf8");
15776
15910
  const parsed = matter9(raw);
15777
15911
  const nextUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
15778
15912
  const nextContent = matter9.stringify(parsed.content, {
@@ -15784,10 +15918,10 @@ async function promoteCandidate(rootDir, target) {
15784
15918
  )
15785
15919
  });
15786
15920
  const nextPath = candidateActivePath(candidate);
15787
- const nextAbsolutePath = path22.join(paths.wikiDir, nextPath);
15788
- await ensureDir(path22.dirname(nextAbsolutePath));
15789
- await fs18.writeFile(nextAbsolutePath, nextContent, "utf8");
15790
- await fs18.rm(path22.join(paths.wikiDir, candidate.path), { force: true });
15921
+ const nextAbsolutePath = path23.join(paths.wikiDir, nextPath);
15922
+ await ensureDir(path23.dirname(nextAbsolutePath));
15923
+ await fs19.writeFile(nextAbsolutePath, nextContent, "utf8");
15924
+ await fs19.rm(path23.join(paths.wikiDir, candidate.path), { force: true });
15791
15925
  const nextPage = parseStoredPage(nextPath, nextContent, { createdAt: candidate.createdAt, updatedAt: nextUpdatedAt });
15792
15926
  const nextPages = sortGraphPages(
15793
15927
  (graph?.pages ?? []).filter((page) => page.id !== candidate.id && page.path !== candidate.path).concat(nextPage)
@@ -15832,7 +15966,7 @@ async function archiveCandidate(rootDir, target) {
15832
15966
  const { paths } = await loadVaultConfig(rootDir);
15833
15967
  const graph = await readJsonFile(paths.graphPath);
15834
15968
  const candidate = resolveCandidateTarget(graph?.pages ?? [], target);
15835
- await fs18.rm(path22.join(paths.wikiDir, candidate.path), { force: true });
15969
+ await fs19.rm(path23.join(paths.wikiDir, candidate.path), { force: true });
15836
15970
  const nextPages = sortGraphPages((graph?.pages ?? []).filter((page) => page.id !== candidate.id && page.path !== candidate.path));
15837
15971
  const nextGraph = {
15838
15972
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -15871,18 +16005,18 @@ async function archiveCandidate(rootDir, target) {
15871
16005
  }
15872
16006
  async function ensureObsidianWorkspace(rootDir) {
15873
16007
  const { config } = await loadVaultConfig(rootDir);
15874
- const obsidianDir = path22.join(rootDir, ".obsidian");
16008
+ const obsidianDir = path23.join(rootDir, ".obsidian");
15875
16009
  const projectIds = projectEntries(config).map((project) => project.id);
15876
16010
  await ensureDir(obsidianDir);
15877
16011
  await Promise.all([
15878
- writeJsonFile(path22.join(obsidianDir, "app.json"), {
16012
+ writeJsonFile(path23.join(obsidianDir, "app.json"), {
15879
16013
  alwaysUpdateLinks: true,
15880
16014
  newFileLocation: "folder",
15881
16015
  newFileFolderPath: "wiki/insights",
15882
16016
  useMarkdownLinks: false,
15883
16017
  attachmentFolderPath: "raw/assets"
15884
16018
  }),
15885
- writeJsonFile(path22.join(obsidianDir, "core-plugins.json"), [
16019
+ writeJsonFile(path23.join(obsidianDir, "core-plugins.json"), [
15886
16020
  "file-explorer",
15887
16021
  "global-search",
15888
16022
  "switcher",
@@ -15892,7 +16026,7 @@ async function ensureObsidianWorkspace(rootDir) {
15892
16026
  "tag-pane",
15893
16027
  "page-preview"
15894
16028
  ]),
15895
- writeJsonFile(path22.join(obsidianDir, "graph.json"), {
16029
+ writeJsonFile(path23.join(obsidianDir, "graph.json"), {
15896
16030
  "collapse-filter": false,
15897
16031
  search: "",
15898
16032
  showTags: true,
@@ -15904,7 +16038,7 @@ async function ensureObsidianWorkspace(rootDir) {
15904
16038
  })),
15905
16039
  localJumps: false
15906
16040
  }),
15907
- writeJsonFile(path22.join(obsidianDir, "workspace.json"), {
16041
+ writeJsonFile(path23.join(obsidianDir, "workspace.json"), {
15908
16042
  active: "root",
15909
16043
  lastOpenFiles: ["wiki/index.md", "wiki/projects/index.md", "wiki/candidates/index.md", "wiki/insights/index.md"],
15910
16044
  left: {
@@ -15920,7 +16054,7 @@ async function initVault(rootDir, options = {}) {
15920
16054
  const profile = options.profile ?? "default";
15921
16055
  const { paths } = await initWorkspace(rootDir, { profile });
15922
16056
  await installConfiguredAgents(rootDir);
15923
- const insightsIndexPath = path22.join(paths.wikiDir, "insights", "index.md");
16057
+ const insightsIndexPath = path23.join(paths.wikiDir, "insights", "index.md");
15924
16058
  const now = (/* @__PURE__ */ new Date()).toISOString();
15925
16059
  await writeFileIfChanged(
15926
16060
  insightsIndexPath,
@@ -15931,7 +16065,7 @@ async function initVault(rootDir, options = {}) {
15931
16065
  "Human-authored research notes live here.",
15932
16066
  "",
15933
16067
  "- Use this folder for thesis notes, reading reflections, synthesis drafts, and decisions you want to keep explicitly human-authored.",
15934
- "- Guided ingest can propose updates elsewhere, but SwarmVault does not rewrite files inside `wiki/insights/` after initialization.",
16068
+ "- Guided sessions can stage `wiki/insights/` updates through the approval queue, but SwarmVault never applies them without review.",
15935
16069
  "- Treat these pages as the human judgment layer for your vault.",
15936
16070
  ""
15937
16071
  ] : [
@@ -15940,7 +16074,7 @@ async function initVault(rootDir, options = {}) {
15940
16074
  "Human-authored notes live here.",
15941
16075
  "",
15942
16076
  "- SwarmVault can read these pages during compile and query.",
15943
- "- SwarmVault does not rewrite files inside `wiki/insights/` after initialization.",
16077
+ "- SwarmVault can stage insight-page updates through guided sessions, but it never applies them without review.",
15944
16078
  ""
15945
16079
  ]).join("\n"),
15946
16080
  {
@@ -15966,7 +16100,7 @@ async function initVault(rootDir, options = {}) {
15966
16100
  )
15967
16101
  );
15968
16102
  await writeFileIfChanged(
15969
- path22.join(paths.wikiDir, "projects", "index.md"),
16103
+ path23.join(paths.wikiDir, "projects", "index.md"),
15970
16104
  matter9.stringify(["# Projects", "", "- Run `swarmvault compile` to build project rollups.", ""].join("\n"), {
15971
16105
  page_id: "projects:index",
15972
16106
  kind: "index",
@@ -15989,7 +16123,7 @@ async function initVault(rootDir, options = {}) {
15989
16123
  })
15990
16124
  );
15991
16125
  await writeFileIfChanged(
15992
- path22.join(paths.wikiDir, "candidates", "index.md"),
16126
+ path23.join(paths.wikiDir, "candidates", "index.md"),
15993
16127
  matter9.stringify(["# Candidates", "", "- Run `swarmvault compile` to stage candidate pages.", ""].join("\n"), {
15994
16128
  page_id: "candidates:index",
15995
16129
  kind: "index",
@@ -16016,13 +16150,14 @@ async function initVault(rootDir, options = {}) {
16016
16150
  }
16017
16151
  if (profile === "personal-research") {
16018
16152
  await writeFileIfChanged(
16019
- path22.join(paths.wikiDir, "insights", "research-playbook.md"),
16153
+ path23.join(paths.wikiDir, "insights", "research-playbook.md"),
16020
16154
  matter9.stringify(
16021
16155
  [
16022
16156
  "# Personal Research Playbook",
16023
16157
  "",
16024
16158
  "- Add one source at a time with `swarmvault ingest <input> --guide` or `swarmvault source add <input> --guide`.",
16025
- "- Review `wiki/outputs/source-briefs/`, `wiki/outputs/source-reviews/`, and `wiki/outputs/source-guides/` before accepting staged updates.",
16159
+ "- Resume a guided session with `swarmvault source session <source-id-or-session-id>` whenever you want to answer the session prompts directly.",
16160
+ "- Review `wiki/outputs/source-briefs/`, `wiki/outputs/source-reviews/`, `wiki/outputs/source-guides/`, and `wiki/outputs/source-sessions/` before accepting staged updates.",
16026
16161
  "- Keep unresolved questions visible in `wiki/dashboards/open-questions.md`.",
16027
16162
  "- Use `swarmvault review list` and `swarmvault review show --diff` to decide what becomes canonical.",
16028
16163
  ""
@@ -16165,7 +16300,7 @@ async function compileVault(rootDir, options = {}) {
16165
16300
  ),
16166
16301
  Promise.all(
16167
16302
  clean.map(async (manifest) => {
16168
- const cached = await readJsonFile(path22.join(paths.analysesDir, `${manifest.sourceId}.json`));
16303
+ const cached = await readJsonFile(path23.join(paths.analysesDir, `${manifest.sourceId}.json`));
16169
16304
  if (cached) {
16170
16305
  analysisProgress.tick(manifest.title);
16171
16306
  return cached;
@@ -16193,22 +16328,22 @@ async function compileVault(rootDir, options = {}) {
16193
16328
  }
16194
16329
  const enriched = enrichResolvedCodeImports(manifest, analysis, codeIndex);
16195
16330
  if (analysisSignature(enriched) !== analysisSignature(analysis)) {
16196
- await writeJsonFile(path22.join(paths.analysesDir, `${analysis.sourceId}.json`), enriched);
16331
+ await writeJsonFile(path23.join(paths.analysesDir, `${analysis.sourceId}.json`), enriched);
16197
16332
  }
16198
16333
  return enriched;
16199
16334
  })
16200
16335
  );
16201
16336
  await Promise.all([
16202
- ensureDir(path22.join(paths.wikiDir, "sources")),
16203
- ensureDir(path22.join(paths.wikiDir, "code")),
16204
- ensureDir(path22.join(paths.wikiDir, "concepts")),
16205
- ensureDir(path22.join(paths.wikiDir, "entities")),
16206
- ensureDir(path22.join(paths.wikiDir, "outputs")),
16207
- ensureDir(path22.join(paths.wikiDir, "projects")),
16208
- ensureDir(path22.join(paths.wikiDir, "insights")),
16209
- ensureDir(path22.join(paths.wikiDir, "candidates")),
16210
- ensureDir(path22.join(paths.wikiDir, "candidates", "concepts")),
16211
- ensureDir(path22.join(paths.wikiDir, "candidates", "entities"))
16337
+ ensureDir(path23.join(paths.wikiDir, "sources")),
16338
+ ensureDir(path23.join(paths.wikiDir, "code")),
16339
+ ensureDir(path23.join(paths.wikiDir, "concepts")),
16340
+ ensureDir(path23.join(paths.wikiDir, "entities")),
16341
+ ensureDir(path23.join(paths.wikiDir, "outputs")),
16342
+ ensureDir(path23.join(paths.wikiDir, "projects")),
16343
+ ensureDir(path23.join(paths.wikiDir, "insights")),
16344
+ ensureDir(path23.join(paths.wikiDir, "candidates")),
16345
+ ensureDir(path23.join(paths.wikiDir, "candidates", "concepts")),
16346
+ ensureDir(path23.join(paths.wikiDir, "candidates", "entities"))
16212
16347
  ]);
16213
16348
  const sync = await syncVaultArtifacts(rootDir, {
16214
16349
  schemas,
@@ -16355,7 +16490,7 @@ async function queryVault(rootDir, options) {
16355
16490
  assetFiles: staged.assetFiles
16356
16491
  }
16357
16492
  ]);
16358
- stagedPath = path22.join(approval.approvalDir, "wiki", staged.page.path);
16493
+ stagedPath = path23.join(approval.approvalDir, "wiki", staged.page.path);
16359
16494
  savedPageId = staged.page.id;
16360
16495
  approvalId = approval.approvalId;
16361
16496
  approvalDir = approval.approvalDir;
@@ -16611,9 +16746,9 @@ ${orchestrationNotes.join("\n")}
16611
16746
  approvalId = approval.approvalId;
16612
16747
  approvalDir = approval.approvalDir;
16613
16748
  stepResults.forEach((result, index) => {
16614
- result.stagedPath = path22.join(approval.approvalDir, "wiki", stagedStepPages[index]?.page.path ?? "");
16749
+ result.stagedPath = path23.join(approval.approvalDir, "wiki", stagedStepPages[index]?.page.path ?? "");
16615
16750
  });
16616
- stagedHubPath = path22.join(approval.approvalDir, "wiki", hubPage.path);
16751
+ stagedHubPath = path23.join(approval.approvalDir, "wiki", hubPage.path);
16617
16752
  } else {
16618
16753
  await refreshVaultAfterOutputSave(rootDir);
16619
16754
  }
@@ -16700,11 +16835,11 @@ async function benchmarkVault(rootDir, options = {}) {
16700
16835
  }
16701
16836
  }
16702
16837
  for (const page of graph.pages) {
16703
- const absolutePath = path22.join(paths.wikiDir, page.path);
16838
+ const absolutePath = path23.join(paths.wikiDir, page.path);
16704
16839
  if (!await fileExists(absolutePath)) {
16705
16840
  continue;
16706
16841
  }
16707
- const parsed = matter9(await fs18.readFile(absolutePath, "utf8"));
16842
+ const parsed = matter9(await fs19.readFile(absolutePath, "utf8"));
16708
16843
  pageContentsById.set(page.id, parsed.content);
16709
16844
  }
16710
16845
  const configuredQuestions = (config.benchmark?.questions ?? []).map((question) => normalizeWhitespace(question)).filter(Boolean);
@@ -16759,7 +16894,7 @@ async function listGraphHyperedges(rootDir, target, limit = 25) {
16759
16894
  }
16760
16895
  async function readGraphReport(rootDir) {
16761
16896
  const { paths } = await loadVaultConfig(rootDir);
16762
- return readJsonFile(path22.join(paths.wikiDir, "graph", "report.json"));
16897
+ return readJsonFile(path23.join(paths.wikiDir, "graph", "report.json"));
16763
16898
  }
16764
16899
  async function listGodNodes(rootDir, limit = 10) {
16765
16900
  const graph = await ensureCompiledGraph(rootDir);
@@ -16772,15 +16907,15 @@ async function listPages(rootDir) {
16772
16907
  }
16773
16908
  async function readPage(rootDir, relativePath) {
16774
16909
  const { paths } = await loadVaultConfig(rootDir);
16775
- const absolutePath = path22.resolve(paths.wikiDir, relativePath);
16910
+ const absolutePath = path23.resolve(paths.wikiDir, relativePath);
16776
16911
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
16777
16912
  return null;
16778
16913
  }
16779
- const raw = await fs18.readFile(absolutePath, "utf8");
16914
+ const raw = await fs19.readFile(absolutePath, "utf8");
16780
16915
  const parsed = matter9(raw);
16781
16916
  return {
16782
16917
  path: relativePath,
16783
- title: typeof parsed.data.title === "string" ? parsed.data.title : path22.basename(relativePath, path22.extname(relativePath)),
16918
+ title: typeof parsed.data.title === "string" ? parsed.data.title : path23.basename(relativePath, path23.extname(relativePath)),
16784
16919
  frontmatter: parsed.data,
16785
16920
  content: parsed.content
16786
16921
  };
@@ -16816,7 +16951,7 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16816
16951
  severity: "warning",
16817
16952
  code: "stale_page",
16818
16953
  message: `Page ${page.title} is stale because the vault schema changed.`,
16819
- pagePath: path22.join(paths.wikiDir, page.path),
16954
+ pagePath: path23.join(paths.wikiDir, page.path),
16820
16955
  relatedPageIds: [page.id]
16821
16956
  });
16822
16957
  }
@@ -16829,7 +16964,7 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16829
16964
  severity: "warning",
16830
16965
  code: "stale_page",
16831
16966
  message: `Page ${page.title} is stale because source ${sourceId} changed.`,
16832
- pagePath: path22.join(paths.wikiDir, page.path),
16967
+ pagePath: path23.join(paths.wikiDir, page.path),
16833
16968
  relatedSourceIds: [sourceId],
16834
16969
  relatedPageIds: [page.id]
16835
16970
  });
@@ -16840,13 +16975,13 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16840
16975
  severity: "info",
16841
16976
  code: "orphan_page",
16842
16977
  message: `Page ${page.title} has no backlinks.`,
16843
- pagePath: path22.join(paths.wikiDir, page.path),
16978
+ pagePath: path23.join(paths.wikiDir, page.path),
16844
16979
  relatedPageIds: [page.id]
16845
16980
  });
16846
16981
  }
16847
- const absolutePath = path22.join(paths.wikiDir, page.path);
16982
+ const absolutePath = path23.join(paths.wikiDir, page.path);
16848
16983
  if (await fileExists(absolutePath)) {
16849
- const content = await fs18.readFile(absolutePath, "utf8");
16984
+ const content = await fs19.readFile(absolutePath, "utf8");
16850
16985
  if (content.includes("## Claims")) {
16851
16986
  const uncited = content.split("\n").filter((line) => line.startsWith("- ") && !line.includes("[source:"));
16852
16987
  if (uncited.length) {
@@ -16963,7 +17098,7 @@ async function bootstrapDemo(rootDir, input) {
16963
17098
  }
16964
17099
 
16965
17100
  // src/mcp.ts
16966
- var SERVER_VERSION = "0.5.0";
17101
+ var SERVER_VERSION = "0.6.0";
16967
17102
  async function createMcpServer(rootDir) {
16968
17103
  const server = new McpServer({
16969
17104
  name: "swarmvault",
@@ -17234,7 +17369,7 @@ async function createMcpServer(rootDir) {
17234
17369
  },
17235
17370
  async () => {
17236
17371
  const { paths } = await loadVaultConfig(rootDir);
17237
- const files = (await listFilesRecursive(paths.sessionsDir)).filter((filePath) => filePath.endsWith(".md")).map((filePath) => toPosix(path23.relative(paths.sessionsDir, filePath))).sort();
17372
+ const files = (await listFilesRecursive(paths.sessionsDir)).filter((filePath) => filePath.endsWith(".md")).map((filePath) => toPosix(path24.relative(paths.sessionsDir, filePath))).sort();
17238
17373
  return asTextResource("swarmvault://sessions", JSON.stringify(files, null, 2));
17239
17374
  }
17240
17375
  );
@@ -17267,8 +17402,8 @@ async function createMcpServer(rootDir) {
17267
17402
  return asTextResource(`swarmvault://pages/${encodedPath}`, `Page not found: ${relativePath}`);
17268
17403
  }
17269
17404
  const { paths } = await loadVaultConfig(rootDir);
17270
- const absolutePath = path23.resolve(paths.wikiDir, relativePath);
17271
- return asTextResource(`swarmvault://pages/${encodedPath}`, await fs19.readFile(absolutePath, "utf8"));
17405
+ const absolutePath = path24.resolve(paths.wikiDir, relativePath);
17406
+ return asTextResource(`swarmvault://pages/${encodedPath}`, await fs20.readFile(absolutePath, "utf8"));
17272
17407
  }
17273
17408
  );
17274
17409
  server.registerResource(
@@ -17276,11 +17411,11 @@ async function createMcpServer(rootDir) {
17276
17411
  new ResourceTemplate("swarmvault://sessions/{path}", {
17277
17412
  list: async () => {
17278
17413
  const { paths } = await loadVaultConfig(rootDir);
17279
- const files = (await listFilesRecursive(paths.sessionsDir)).filter((filePath) => filePath.endsWith(".md")).map((filePath) => toPosix(path23.relative(paths.sessionsDir, filePath))).sort();
17414
+ const files = (await listFilesRecursive(paths.sessionsDir)).filter((filePath) => filePath.endsWith(".md")).map((filePath) => toPosix(path24.relative(paths.sessionsDir, filePath))).sort();
17280
17415
  return {
17281
17416
  resources: files.map((relativePath) => ({
17282
17417
  uri: `swarmvault://sessions/${encodeURIComponent(relativePath)}`,
17283
- name: path23.basename(relativePath, ".md"),
17418
+ name: path24.basename(relativePath, ".md"),
17284
17419
  title: relativePath,
17285
17420
  description: "SwarmVault session artifact",
17286
17421
  mimeType: "text/markdown"
@@ -17297,11 +17432,11 @@ async function createMcpServer(rootDir) {
17297
17432
  const { paths } = await loadVaultConfig(rootDir);
17298
17433
  const encodedPath = typeof variables.path === "string" ? variables.path : "";
17299
17434
  const relativePath = decodeURIComponent(encodedPath);
17300
- const absolutePath = path23.resolve(paths.sessionsDir, relativePath);
17435
+ const absolutePath = path24.resolve(paths.sessionsDir, relativePath);
17301
17436
  if (!absolutePath.startsWith(paths.sessionsDir) || !await fileExists(absolutePath)) {
17302
17437
  return asTextResource(`swarmvault://sessions/${encodedPath}`, `Session not found: ${relativePath}`);
17303
17438
  }
17304
- return asTextResource(`swarmvault://sessions/${encodedPath}`, await fs19.readFile(absolutePath, "utf8"));
17439
+ return asTextResource(`swarmvault://sessions/${encodedPath}`, await fs20.readFile(absolutePath, "utf8"));
17305
17440
  }
17306
17441
  );
17307
17442
  return server;
@@ -17349,13 +17484,13 @@ function asTextResource(uri, text) {
17349
17484
  }
17350
17485
 
17351
17486
  // src/schedule.ts
17352
- import fs20 from "fs/promises";
17353
- import path24 from "path";
17487
+ import fs21 from "fs/promises";
17488
+ import path25 from "path";
17354
17489
  function scheduleStatePath(schedulesDir, jobId) {
17355
- return path24.join(schedulesDir, `${encodeURIComponent(jobId)}.json`);
17490
+ return path25.join(schedulesDir, `${encodeURIComponent(jobId)}.json`);
17356
17491
  }
17357
17492
  function scheduleLockPath(schedulesDir, jobId) {
17358
- return path24.join(schedulesDir, `${encodeURIComponent(jobId)}.lock`);
17493
+ return path25.join(schedulesDir, `${encodeURIComponent(jobId)}.lock`);
17359
17494
  }
17360
17495
  function parseEveryDuration(value) {
17361
17496
  const match = value.trim().match(/^(\d+)(m|h|d)$/i);
@@ -17458,13 +17593,13 @@ async function acquireJobLease(rootDir, jobId) {
17458
17593
  const { paths } = await loadVaultConfig(rootDir);
17459
17594
  const leasePath = scheduleLockPath(paths.schedulesDir, jobId);
17460
17595
  await ensureDir(paths.schedulesDir);
17461
- const handle = await fs20.open(leasePath, "wx");
17596
+ const handle = await fs21.open(leasePath, "wx");
17462
17597
  await handle.writeFile(`${process.pid}
17463
17598
  ${(/* @__PURE__ */ new Date()).toISOString()}
17464
17599
  `);
17465
17600
  await handle.close();
17466
17601
  return async () => {
17467
- await fs20.rm(leasePath, { force: true });
17602
+ await fs21.rm(leasePath, { force: true });
17468
17603
  };
17469
17604
  }
17470
17605
  async function listSchedules(rootDir) {
@@ -17612,8 +17747,9 @@ async function serveSchedules(rootDir, pollMs = 3e4) {
17612
17747
 
17613
17748
  // src/sources.ts
17614
17749
  import { spawn as spawn2 } from "child_process";
17615
- import fs21 from "fs/promises";
17616
- import path25 from "path";
17750
+ import fs22 from "fs/promises";
17751
+ import path26 from "path";
17752
+ import matter10 from "gray-matter";
17617
17753
  import { JSDOM as JSDOM3 } from "jsdom";
17618
17754
  var DEFAULT_CRAWL_MAX_PAGES = 12;
17619
17755
  var DEFAULT_CRAWL_MAX_DEPTH = 2;
@@ -17640,24 +17776,24 @@ function normalizeManagedStatus(value) {
17640
17776
  return value === "missing" || value === "error" ? value : "ready";
17641
17777
  }
17642
17778
  function withinRoot2(rootPath, targetPath) {
17643
- const relative = path25.relative(rootPath, targetPath);
17644
- return relative === "" || !relative.startsWith("..") && !path25.isAbsolute(relative);
17779
+ const relative = path26.relative(rootPath, targetPath);
17780
+ return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
17645
17781
  }
17646
17782
  async function findNearestGitRoot3(startPath) {
17647
- let current = path25.resolve(startPath);
17783
+ let current = path26.resolve(startPath);
17648
17784
  try {
17649
- const stat = await fs21.stat(current);
17785
+ const stat = await fs22.stat(current);
17650
17786
  if (!stat.isDirectory()) {
17651
- current = path25.dirname(current);
17787
+ current = path26.dirname(current);
17652
17788
  }
17653
17789
  } catch {
17654
- current = path25.dirname(current);
17790
+ current = path26.dirname(current);
17655
17791
  }
17656
17792
  while (true) {
17657
- if (await fileExists(path25.join(current, ".git"))) {
17793
+ if (await fileExists(path26.join(current, ".git"))) {
17658
17794
  return current;
17659
17795
  }
17660
- const parent = path25.dirname(current);
17796
+ const parent = path26.dirname(current);
17661
17797
  if (parent === current) {
17662
17798
  return null;
17663
17799
  }
@@ -17731,7 +17867,7 @@ function isAllowedDocsCandidate(candidate, startUrl) {
17731
17867
  if (candidate.origin !== startUrl.origin) {
17732
17868
  return false;
17733
17869
  }
17734
- const extension = path25.extname(candidate.pathname).toLowerCase();
17870
+ const extension = path26.extname(candidate.pathname).toLowerCase();
17735
17871
  if (extension && extension !== ".html" && extension !== ".htm" && extension !== ".md") {
17736
17872
  return false;
17737
17873
  }
@@ -17820,14 +17956,14 @@ function matchesManagedSourceSpec(existing, input) {
17820
17956
  return false;
17821
17957
  }
17822
17958
  if (input.kind === "directory" || input.kind === "file") {
17823
- return path25.resolve(existing.path ?? "") === path25.resolve(input.path);
17959
+ return path26.resolve(existing.path ?? "") === path26.resolve(input.path);
17824
17960
  }
17825
17961
  return (existing.url ?? "") === input.url;
17826
17962
  }
17827
17963
  async function resolveManagedSourceInput(rootDir, input) {
17828
- const absoluteInput = path25.resolve(rootDir, input);
17964
+ const absoluteInput = path26.resolve(rootDir, input);
17829
17965
  if (!(input.startsWith("http://") || input.startsWith("https://"))) {
17830
- const stat = await fs21.stat(absoluteInput).catch(() => null);
17966
+ const stat = await fs22.stat(absoluteInput).catch(() => null);
17831
17967
  if (!stat) {
17832
17968
  throw new Error(`Source not found: ${input}`);
17833
17969
  }
@@ -17835,7 +17971,7 @@ async function resolveManagedSourceInput(rootDir, input) {
17835
17971
  return {
17836
17972
  kind: "file",
17837
17973
  path: absoluteInput,
17838
- title: path25.basename(absoluteInput, path25.extname(absoluteInput)) || absoluteInput
17974
+ title: path26.basename(absoluteInput, path26.extname(absoluteInput)) || absoluteInput
17839
17975
  };
17840
17976
  }
17841
17977
  if (!stat.isDirectory()) {
@@ -17847,7 +17983,7 @@ async function resolveManagedSourceInput(rootDir, input) {
17847
17983
  kind: "directory",
17848
17984
  path: absoluteInput,
17849
17985
  repoRoot,
17850
- title: path25.basename(absoluteInput) || absoluteInput
17986
+ title: path26.basename(absoluteInput) || absoluteInput
17851
17987
  };
17852
17988
  }
17853
17989
  const github = normalizeGitHubRepoRootUrl(input);
@@ -17870,16 +18006,16 @@ async function resolveManagedSourceInput(rootDir, input) {
17870
18006
  };
17871
18007
  }
17872
18008
  function directorySourceIdsFor(manifests, inputPath) {
17873
- return manifests.filter((manifest) => manifest.originalPath && withinRoot2(path25.resolve(inputPath), path25.resolve(manifest.originalPath))).map((manifest) => manifest.sourceId).sort((left, right) => left.localeCompare(right));
18009
+ return manifests.filter((manifest) => manifest.originalPath && withinRoot2(path26.resolve(inputPath), path26.resolve(manifest.originalPath))).map((manifest) => manifest.sourceId).sort((left, right) => left.localeCompare(right));
17874
18010
  }
17875
18011
  function fileSourceIdsFor(manifests, inputPath) {
17876
- const absoluteInput = path25.resolve(inputPath);
17877
- return manifests.filter((manifest) => manifest.originalPath && path25.resolve(manifest.originalPath) === absoluteInput).map((manifest) => manifest.sourceId).sort((left, right) => left.localeCompare(right));
18012
+ const absoluteInput = path26.resolve(inputPath);
18013
+ return manifests.filter((manifest) => manifest.originalPath && path26.resolve(manifest.originalPath) === absoluteInput).map((manifest) => manifest.sourceId).sort((left, right) => left.localeCompare(right));
17878
18014
  }
17879
18015
  async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17880
18016
  const manifestsBefore = await listManifests(rootDir);
17881
18017
  const previousInScope = manifestsBefore.filter(
17882
- (manifest) => manifest.originalPath && withinRoot2(path25.resolve(inputPath), path25.resolve(manifest.originalPath))
18018
+ (manifest) => manifest.originalPath && withinRoot2(path26.resolve(inputPath), path26.resolve(manifest.originalPath))
17883
18019
  );
17884
18020
  const result = await ingestDirectory(rootDir, inputPath, { repoRoot });
17885
18021
  const removed = [];
@@ -17887,7 +18023,7 @@ async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17887
18023
  if (!manifest.originalPath) {
17888
18024
  continue;
17889
18025
  }
17890
- if (await fileExists(path25.resolve(manifest.originalPath))) {
18026
+ if (await fileExists(path26.resolve(manifest.originalPath))) {
17891
18027
  continue;
17892
18028
  }
17893
18029
  const removedManifest = await removeManifestBySourceId(rootDir, manifest.sourceId);
@@ -17897,7 +18033,7 @@ async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17897
18033
  }
17898
18034
  const manifestsAfter = await listManifests(rootDir);
17899
18035
  return {
17900
- title: path25.basename(inputPath) || inputPath,
18036
+ title: path26.basename(inputPath) || inputPath,
17901
18037
  sourceIds: directorySourceIdsFor(manifestsAfter, inputPath),
17902
18038
  counts: {
17903
18039
  scannedCount: result.scannedCount,
@@ -17913,7 +18049,7 @@ async function syncFileSource(rootDir, inputPath) {
17913
18049
  const result = await ingestInputDetailed(rootDir, inputPath);
17914
18050
  const manifestsAfter = await listManifests(rootDir);
17915
18051
  return {
17916
- title: path25.basename(inputPath, path25.extname(inputPath)) || inputPath,
18052
+ title: path26.basename(inputPath, path26.extname(inputPath)) || inputPath,
17917
18053
  sourceIds: fileSourceIdsFor(manifestsAfter, inputPath),
17918
18054
  counts: {
17919
18055
  scannedCount: result.scannedCount,
@@ -17947,8 +18083,8 @@ async function runGitCommand(cwd, args) {
17947
18083
  }
17948
18084
  async function syncGitHubRepoSource(rootDir, entry) {
17949
18085
  const workingDir = await managedSourceWorkingDir(rootDir, entry.id);
17950
- const checkoutDir = path25.join(workingDir, "checkout");
17951
- await fs21.rm(checkoutDir, { recursive: true, force: true });
18086
+ const checkoutDir = path26.join(workingDir, "checkout");
18087
+ await fs22.rm(checkoutDir, { recursive: true, force: true });
17952
18088
  await ensureDir(workingDir);
17953
18089
  if (!entry.url) {
17954
18090
  throw new Error(`Managed source ${entry.id} is missing its repository URL.`);
@@ -18075,7 +18211,7 @@ function scopedNodeIds(graph, sourceIds) {
18075
18211
  async function loadSourceAnalyses(rootDir, sourceIds) {
18076
18212
  const { paths } = await loadVaultConfig(rootDir);
18077
18213
  const analyses = await Promise.all(
18078
- sourceIds.map(async (sourceId) => await readJsonFile(path25.join(paths.analysesDir, `${sourceId}.json`)))
18214
+ sourceIds.map(async (sourceId) => await readJsonFile(path26.join(paths.analysesDir, `${sourceId}.json`)))
18079
18215
  );
18080
18216
  return analyses.filter((analysis) => Boolean(analysis?.sourceId));
18081
18217
  }
@@ -18235,9 +18371,9 @@ async function writeSourceBriefForScope(rootDir, source) {
18235
18371
  confidence: 0.82
18236
18372
  }
18237
18373
  });
18238
- const absolutePath = path25.join(paths.wikiDir, output.page.path);
18239
- await ensureDir(path25.dirname(absolutePath));
18240
- await fs21.writeFile(absolutePath, output.content, "utf8");
18374
+ const absolutePath = path26.join(paths.wikiDir, output.page.path);
18375
+ await ensureDir(path26.dirname(absolutePath));
18376
+ await fs22.writeFile(absolutePath, output.content, "utf8");
18241
18377
  return absolutePath;
18242
18378
  }
18243
18379
  async function writeSourceBrief(rootDir, source) {
@@ -18256,6 +18392,59 @@ async function generateBriefsForSources(rootDir, sources) {
18256
18392
  }
18257
18393
  return briefPaths;
18258
18394
  }
18395
+ var GUIDED_SESSION_QUESTIONS = [
18396
+ {
18397
+ id: "importance",
18398
+ prompt: "What matters most from this source for your wiki right now?"
18399
+ },
18400
+ {
18401
+ id: "exclude",
18402
+ prompt: "What should stay provisional, be ignored, or be kept out for now?"
18403
+ },
18404
+ {
18405
+ id: "targets",
18406
+ prompt: "Which canonical pages or topics should this source update?"
18407
+ },
18408
+ {
18409
+ id: "conflicts",
18410
+ prompt: "What feels new, reinforcing, or conflicting compared with what you already believe?"
18411
+ },
18412
+ {
18413
+ id: "followups",
18414
+ prompt: "What follow-up questions or next sources should stay open?"
18415
+ }
18416
+ ];
18417
+ function defaultGuidedSessionQuestions() {
18418
+ return GUIDED_SESSION_QUESTIONS.map((question) => ({ ...question }));
18419
+ }
18420
+ function normalizeGuidedAnswerValue(value) {
18421
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
18422
+ }
18423
+ function normalizeGuidedAnswers(input) {
18424
+ if (!input) {
18425
+ return {};
18426
+ }
18427
+ if (Array.isArray(input)) {
18428
+ return Object.fromEntries(
18429
+ GUIDED_SESSION_QUESTIONS.map((question, index) => [question.id, normalizeGuidedAnswerValue(input[index])]).filter(
18430
+ (entry) => Boolean(entry[1])
18431
+ )
18432
+ );
18433
+ }
18434
+ return Object.fromEntries(
18435
+ Object.entries(input).map(([key, value]) => [key, normalizeGuidedAnswerValue(value)]).filter((entry) => Boolean(entry[1]))
18436
+ );
18437
+ }
18438
+ function mergeGuidedSessionQuestions(questions, answers) {
18439
+ const normalizedAnswers = normalizeGuidedAnswers(answers);
18440
+ return questions.map((question) => ({
18441
+ ...question,
18442
+ answer: normalizedAnswers[question.id] ?? question.answer
18443
+ }));
18444
+ }
18445
+ function answeredGuidedSessionQuestions(questions) {
18446
+ return questions.filter((question) => typeof question.answer === "string" && question.answer.trim().length > 0);
18447
+ }
18259
18448
  function renderDeterministicSourceReview(input) {
18260
18449
  const canonicalPages = input.sourcePages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 10);
18261
18450
  const modulePages = input.sourcePages.filter((page) => page.kind === "module").slice(0, 8);
@@ -18399,6 +18588,75 @@ function classifySourceGuidePageBuckets(sourcePages, scopeSourceIds) {
18399
18588
  const reinforcingPages = canonicalPages.filter((page) => page.sourceIds.some((sourceId) => !scopeSet.has(sourceId))).slice(0, 6);
18400
18589
  return { canonicalPages, newPages, reinforcingPages };
18401
18590
  }
18591
+ function findContradictionsForScope(scope, report) {
18592
+ return report?.contradictions.filter(
18593
+ (contradiction) => scope.sourceIds.includes(contradiction.sourceIdA) || scope.sourceIds.includes(contradiction.sourceIdB)
18594
+ ) ?? [];
18595
+ }
18596
+ function selectGuidedTargetPages(scope, sourcePages, questions) {
18597
+ const { canonicalPages } = classifySourceGuidePageBuckets(sourcePages, scope.sourceIds);
18598
+ if (!canonicalPages.length) {
18599
+ return [];
18600
+ }
18601
+ const desiredTargets = normalizeWhitespace(
18602
+ questions.find((question) => question.id === "targets")?.answer ?? questions.find((question) => question.id === "importance")?.answer ?? ""
18603
+ ).toLowerCase();
18604
+ const matchedTargets = desiredTargets ? canonicalPages.filter((page) => {
18605
+ const title = page.title.toLowerCase();
18606
+ const relative = page.path.replace(/\.md$/, "").toLowerCase();
18607
+ return desiredTargets.includes(title) || desiredTargets.includes(relative) || title.includes(desiredTargets);
18608
+ }) : [];
18609
+ return (matchedTargets.length ? matchedTargets : canonicalPages).slice(0, 6);
18610
+ }
18611
+ function insightRelativePathForTarget(page, scope) {
18612
+ const basename = path26.basename(page.path);
18613
+ if (page.kind === "concept") {
18614
+ return `insights/concepts/${basename}`;
18615
+ }
18616
+ if (page.kind === "entity") {
18617
+ return `insights/entities/${basename}`;
18618
+ }
18619
+ if (page.kind === "source") {
18620
+ return `insights/sources/${slugify(page.title || scope.title)}.md`;
18621
+ }
18622
+ return `insights/topics/${slugify(page.title || scope.title)}.md`;
18623
+ }
18624
+ function insightTitleForTarget(page, scope) {
18625
+ if (page.kind === "concept" || page.kind === "entity") {
18626
+ return page.title;
18627
+ }
18628
+ if (page.kind === "source") {
18629
+ return `Source Notes: ${page.title}`;
18630
+ }
18631
+ return `${scope.title} Notes`;
18632
+ }
18633
+ function insightTagsForTarget(page) {
18634
+ return uniqueStrings4(["insight", "guided-session", `guided/${page?.kind ?? "topic"}`]);
18635
+ }
18636
+ function guidedUpdateMarker(scopeId) {
18637
+ return {
18638
+ start: `<!-- swarmvault-guided-source:${scopeId}:start -->`,
18639
+ end: `<!-- swarmvault-guided-source:${scopeId}:end -->`
18640
+ };
18641
+ }
18642
+ function replaceMarkedSection(content, scopeId, replacement) {
18643
+ const marker = guidedUpdateMarker(scopeId);
18644
+ const block = `${marker.start}
18645
+ ${replacement.trim()}
18646
+ ${marker.end}`;
18647
+ const startIndex = content.indexOf(marker.start);
18648
+ const endIndex = content.indexOf(marker.end);
18649
+ if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) {
18650
+ return `${content.slice(0, startIndex).trimEnd()}
18651
+
18652
+ ${block}
18653
+ `;
18654
+ }
18655
+ return `${content.trimEnd()}
18656
+
18657
+ ${block}
18658
+ `;
18659
+ }
18402
18660
  function renderDeterministicSourceGuide(input) {
18403
18661
  const { canonicalPages, newPages, reinforcingPages } = classifySourceGuidePageBuckets(input.sourcePages, input.scope.sourceIds);
18404
18662
  const modulePages = input.sourcePages.filter((page) => page.kind === "module").slice(0, 6);
@@ -18563,40 +18821,338 @@ async function stageSourceReviewForScope(rootDir, scope) {
18563
18821
  return {
18564
18822
  sourceId: scope.id,
18565
18823
  pageId: output.page.id,
18566
- reviewPath: path25.join(approval.approvalDir, "wiki", output.page.path),
18824
+ reviewPath: path26.join(approval.approvalDir, "wiki", output.page.path),
18567
18825
  staged: true,
18568
18826
  approvalId: approval.approvalId,
18569
18827
  approvalDir: approval.approvalDir
18570
18828
  };
18571
18829
  }
18572
- async function stageSourceGuideForScope(rootDir, scope) {
18573
- const briefPath = scope.briefPath ?? await writeSourceBriefForScope(rootDir, scope) ?? void 0;
18830
+ function nextGuidedSourceSessionId(scope) {
18831
+ return `source-session-${slugify(scope.id)}-${sha256(`${scope.id}:${(/* @__PURE__ */ new Date()).toISOString()}`).slice(0, 8)}`;
18832
+ }
18833
+ function shouldReuseGuidedSourceSession(session) {
18834
+ return Boolean(session && session.status === "awaiting_input");
18835
+ }
18836
+ function questionAnswer(questions, id, fallback) {
18837
+ return normalizeGuidedAnswerValue(questions.find((question) => question.id === id)?.answer) ?? fallback;
18838
+ }
18839
+ async function prepareGuidedSourceSession(rootDir, scope, answers) {
18840
+ const existing = await findLatestGuidedSourceSessionByScope(rootDir, scope.id);
18841
+ const now = (/* @__PURE__ */ new Date()).toISOString();
18842
+ const session = shouldReuseGuidedSourceSession(existing) ? {
18843
+ ...existing,
18844
+ scopeTitle: scope.title,
18845
+ sourceIds: scope.sourceIds,
18846
+ kind: scope.kind,
18847
+ questions: mergeGuidedSessionQuestions(existing.questions, answers),
18848
+ updatedAt: now
18849
+ } : {
18850
+ sessionId: nextGuidedSourceSessionId(scope),
18851
+ scopeId: scope.id,
18852
+ scopeTitle: scope.title,
18853
+ sourceIds: scope.sourceIds,
18854
+ kind: scope.kind,
18855
+ status: "awaiting_input",
18856
+ createdAt: now,
18857
+ updatedAt: now,
18858
+ questions: mergeGuidedSessionQuestions(defaultGuidedSessionQuestions(), answers),
18859
+ briefPath: scope.briefPath,
18860
+ targetedPagePaths: [],
18861
+ stagedUpdatePaths: []
18862
+ };
18863
+ const statePath = await guidedSourceSessionStatePath(rootDir, session.sessionId);
18864
+ return { session, statePath };
18865
+ }
18866
+ async function buildSourceSessionSavedPage(rootDir, scope, session) {
18867
+ const { paths } = await loadVaultConfig(rootDir);
18868
+ let graph = await readJsonFile(paths.graphPath);
18869
+ if (!graph) {
18870
+ await compileVault(rootDir, {});
18871
+ graph = await readJsonFile(paths.graphPath);
18872
+ }
18873
+ const sourcePages = graph ? scopedSourcePages(graph, scope.sourceIds) : [];
18874
+ const analyses = await loadSourceAnalyses(rootDir, scope.sourceIds);
18875
+ const report = await readGraphReport(rootDir);
18876
+ const contradictions = findContradictionsForScope(scope, report);
18877
+ const relatedPageIds = uniqueStrings4([
18878
+ ...sourcePages.slice(0, 18).map((page) => page.id),
18879
+ ...session.targetedPagePaths.map((relativePath) => {
18880
+ const page = graph?.pages.find((candidate) => candidate.path === relativePath);
18881
+ return page?.id ?? "";
18882
+ })
18883
+ ]);
18884
+ const relatedNodeIds = graph ? scopedNodeIds(graph, scope.sourceIds).slice(0, 28) : [];
18885
+ const projectIds = uniqueStrings4(sourcePages.flatMap((page) => page.projectIds));
18886
+ const relativeBriefPath = session.briefPath && path26.isAbsolute(session.briefPath) ? path26.relative(paths.wikiDir, session.briefPath) : session.briefPath;
18887
+ const sessionMarkdown = [
18888
+ `# Guided Session: ${scope.title}`,
18889
+ "",
18890
+ `Status: \`${session.status}\``,
18891
+ `Session ID: \`${session.sessionId}\``,
18892
+ ...session.approvalId ? [`Approval Bundle: \`${session.approvalId}\``] : [],
18893
+ ...relativeBriefPath ? [`Brief: \`${relativeBriefPath}\``] : [],
18894
+ "",
18895
+ "## What This Source Is",
18896
+ "",
18897
+ ...analyses.length ? analyses.slice(0, 6).map((analysis) => `- ${analysis.title}: ${analysis.summary}`) : ["- Awaiting compile context."],
18898
+ "",
18899
+ "## Guided Questions",
18900
+ "",
18901
+ ...session.questions.flatMap((question) => [`### ${question.prompt}`, "", question.answer ?? "_Awaiting input._", ""]),
18902
+ "## Proposed Wiki Targets",
18903
+ "",
18904
+ ...session.targetedPagePaths.length ? session.targetedPagePaths.map((targetPath) => `- [[${targetPath.replace(/\.md$/, "")}]]`) : ["- No canonical update targets selected yet."],
18905
+ "",
18906
+ "## Conflicts And Judgment Calls",
18907
+ "",
18908
+ ...contradictions.length ? contradictions.map((contradiction) => `- ${contradiction.claimA} / ${contradiction.claimB}`) : ["- No contradictions are currently flagged for this source scope."],
18909
+ "",
18910
+ "## Follow-up Questions",
18911
+ "",
18912
+ ...(() => {
18913
+ const followups = questionAnswer(session.questions, "followups", "");
18914
+ if (followups) {
18915
+ return followups.split(/\n+/).map((line) => line.trim()).filter(Boolean).map((line) => `- ${line.replace(/^-+\s*/, "")}`);
18916
+ }
18917
+ const analysisQuestions = uniqueStrings4(analyses.flatMap((analysis) => analysis.questions)).slice(0, 6);
18918
+ return analysisQuestions.length ? analysisQuestions.map((question) => `- ${question}`) : ["- No follow-up questions recorded yet."];
18919
+ })(),
18920
+ "",
18921
+ "## Related Artifacts",
18922
+ "",
18923
+ `- [[outputs/source-briefs/${scope.id}|Source Brief]]`,
18924
+ `- [[outputs/source-reviews/${scope.id}|Source Review]]`,
18925
+ `- [[outputs/source-guides/${scope.id}|Source Guide]]`,
18926
+ ""
18927
+ ].join("\n");
18928
+ const now = (/* @__PURE__ */ new Date()).toISOString();
18929
+ const output = buildOutputPage({
18930
+ title: `Guided Session: ${scope.title}`,
18931
+ question: `Guided Session ${scope.title}`,
18932
+ answer: sessionMarkdown,
18933
+ citations: scope.sourceIds,
18934
+ schemaHash: graph?.generatedAt ?? "",
18935
+ outputFormat: "report",
18936
+ relatedPageIds,
18937
+ relatedNodeIds,
18938
+ relatedSourceIds: scope.sourceIds,
18939
+ projectIds,
18940
+ extraTags: ["source-session", "guided-session"],
18941
+ origin: "query",
18942
+ slug: `source-sessions/${scope.id}`,
18943
+ metadata: {
18944
+ status: "active",
18945
+ createdAt: now,
18946
+ updatedAt: now,
18947
+ compiledFrom: scope.sourceIds,
18948
+ managedBy: "system",
18949
+ confidence: 0.81
18950
+ }
18951
+ });
18952
+ return { page: output.page, content: output.content };
18953
+ }
18954
+ async function persistSourceSessionPage(rootDir, scope, session) {
18955
+ const { paths } = await loadVaultConfig(rootDir);
18956
+ const output = await buildSourceSessionSavedPage(rootDir, scope, session);
18957
+ const absolutePath = path26.join(paths.wikiDir, output.page.path);
18958
+ await ensureDir(path26.dirname(absolutePath));
18959
+ await fs22.writeFile(absolutePath, output.content, "utf8");
18960
+ return { pageId: output.page.id, sessionPath: absolutePath };
18961
+ }
18962
+ async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
18963
+ const { paths } = await loadVaultConfig(rootDir);
18964
+ let graph = await readJsonFile(paths.graphPath);
18965
+ if (!graph) {
18966
+ await compileVault(rootDir, {});
18967
+ graph = await readJsonFile(paths.graphPath);
18968
+ }
18969
+ if (!graph) {
18970
+ return [];
18971
+ }
18972
+ const sourcePages = scopedSourcePages(graph, scope.sourceIds);
18973
+ const analyses = await loadSourceAnalyses(rootDir, scope.sourceIds);
18974
+ const report = await readGraphReport(rootDir);
18975
+ const contradictions = findContradictionsForScope(scope, report);
18976
+ const selectedTargets = selectGuidedTargetPages(scope, sourcePages, session.questions);
18977
+ const targetPages = selectedTargets.length ? selectedTargets : [null];
18978
+ return await Promise.all(
18979
+ targetPages.map(async (targetPage, index) => {
18980
+ const relativePath = targetPage ? insightRelativePathForTarget(targetPage, scope) : `insights/topics/${slugify(scope.title)}.md`;
18981
+ const absolutePath = path26.join(paths.wikiDir, relativePath);
18982
+ const existingContent = await fileExists(absolutePath) ? await fs22.readFile(absolutePath, "utf8") : "";
18983
+ const parsed = existingContent ? matter10(existingContent) : { data: {}, content: "" };
18984
+ const existingData = parsed.data;
18985
+ const existingSourceIds = Array.isArray(existingData.source_ids) ? existingData.source_ids.filter((value) => typeof value === "string") : [];
18986
+ const existingProjectIds = Array.isArray(existingData.project_ids) ? existingData.project_ids.filter((value) => typeof value === "string") : [];
18987
+ const existingNodeIds = Array.isArray(existingData.node_ids) ? existingData.node_ids.filter((value) => typeof value === "string") : [];
18988
+ const existingBacklinks = Array.isArray(existingData.backlinks) ? existingData.backlinks.filter((value) => typeof value === "string") : [];
18989
+ const createdAt = typeof existingData.created_at === "string" && existingData.created_at.trim() ? existingData.created_at : (/* @__PURE__ */ new Date()).toISOString();
18990
+ const title = typeof existingData.title === "string" && existingData.title.trim() || (targetPage ? insightTitleForTarget(targetPage, scope) : `${scope.title} Notes`);
18991
+ const baseBody = parsed.content.trim() ? parsed.content.trim() : [`# ${title}`, "", "Human-curated insight page. Guided sessions stage replaceable update blocks here.", ""].join("\n");
18992
+ const importance = questionAnswer(
18993
+ session.questions,
18994
+ "importance",
18995
+ "Capture the most important new ideas from this source before treating them as canonical."
18996
+ );
18997
+ const exclude = questionAnswer(
18998
+ session.questions,
18999
+ "exclude",
19000
+ "Keep uncertain or incidental details provisional until they matter to the research thread."
19001
+ );
19002
+ const conflictNotes = questionAnswer(
19003
+ session.questions,
19004
+ "conflicts",
19005
+ contradictions.length ? "Review the conflicting evidence before accepting any canonical summary changes." : "No explicit conflicts were called out."
19006
+ );
19007
+ const followups = questionAnswer(session.questions, "followups", "Track follow-up questions on the source session page.");
19008
+ const updateBlock = [
19009
+ `## Guided Session Update: ${scope.title}`,
19010
+ "",
19011
+ `Session: [[outputs/source-sessions/${scope.id}|Guided Session]]`,
19012
+ `Source Guide: [[outputs/source-guides/${scope.id}|Source Guide]]`,
19013
+ "",
19014
+ "### What Matters Now",
19015
+ "",
19016
+ importance,
19017
+ "",
19018
+ "### Proposed Integration",
19019
+ "",
19020
+ targetPage ? `- Fold the strongest source-backed takeaways into [[${targetPage.path.replace(/\.md$/, "")}|${targetPage.title}]].` : `- Start a durable topic note for ${scope.title}.`,
19021
+ ...analyses.slice(0, 5).map((analysis) => `- ${truncate(normalizeWhitespace(analysis.summary), 180)}`),
19022
+ "",
19023
+ "### Keep Provisional Or Out",
19024
+ "",
19025
+ exclude,
19026
+ "",
19027
+ "### Reinforcing Or Conflicting Notes",
19028
+ "",
19029
+ conflictNotes,
19030
+ ...contradictions.length ? ["", ...contradictions.slice(0, 4).map((contradiction) => `- ${contradiction.claimA} / ${contradiction.claimB}`)] : [],
19031
+ "",
19032
+ "### Follow-up Questions",
19033
+ "",
19034
+ followups,
19035
+ ""
19036
+ ].join("\n");
19037
+ const nextBody = replaceMarkedSection(baseBody, scope.id, updateBlock);
19038
+ const content = matter10.stringify(`${nextBody.trimEnd()}
19039
+ `, {
19040
+ ...existingData,
19041
+ page_id: typeof existingData.page_id === "string" && existingData.page_id.trim() || `insight:${slugify(relativePath.replace(/\.md$/, ""))}`,
19042
+ kind: "insight",
19043
+ title,
19044
+ tags: uniqueStrings4([
19045
+ ...Array.isArray(existingData.tags) ? existingData.tags.filter((value) => typeof value === "string") : [],
19046
+ ...insightTagsForTarget(targetPage)
19047
+ ]),
19048
+ source_ids: uniqueStrings4([...existingSourceIds, ...scope.sourceIds]),
19049
+ project_ids: uniqueStrings4([...existingProjectIds, ...targetPage?.projectIds ?? []]),
19050
+ node_ids: uniqueStrings4([...existingNodeIds, ...targetPage?.nodeIds ?? []]),
19051
+ freshness: "fresh",
19052
+ status: existingData.status === "archived" ? "archived" : "active",
19053
+ confidence: 0.83,
19054
+ created_at: createdAt,
19055
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
19056
+ compiled_from: uniqueStrings4([
19057
+ ...Array.isArray(existingData.compiled_from) ? existingData.compiled_from.filter((value) => typeof value === "string") : [],
19058
+ ...scope.sourceIds
19059
+ ]),
19060
+ managed_by: "human",
19061
+ backlinks: uniqueStrings4([
19062
+ ...existingBacklinks,
19063
+ ...targetPage ? [targetPage.id] : [],
19064
+ `output:source-sessions/${scope.id}`,
19065
+ `output:source-guides/${scope.id}`
19066
+ ]),
19067
+ schema_hash: typeof existingData.schema_hash === "string" ? existingData.schema_hash : "",
19068
+ source_hashes: existingData.source_hashes && typeof existingData.source_hashes === "object" ? existingData.source_hashes : {},
19069
+ source_semantic_hashes: existingData.source_semantic_hashes && typeof existingData.source_semantic_hashes === "object" ? existingData.source_semantic_hashes : {}
19070
+ });
19071
+ const page = parseStoredPage(relativePath, content, {
19072
+ createdAt,
19073
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
19074
+ });
19075
+ if (index === 0) {
19076
+ session.targetedPagePaths = uniqueStrings4([
19077
+ ...session.targetedPagePaths,
19078
+ ...selectedTargets.length ? selectedTargets.map((page2) => page2.path) : [relativePath]
19079
+ ]);
19080
+ }
19081
+ return { page, content, label: "guided-update" };
19082
+ })
19083
+ );
19084
+ }
19085
+ async function stageSourceGuideForScope(rootDir, scope, options = {}) {
19086
+ const { session, statePath } = await prepareGuidedSourceSession(rootDir, scope, options.answers);
19087
+ const briefPath = scope.briefPath ?? session.briefPath ?? await writeSourceBriefForScope(rootDir, scope) ?? void 0;
19088
+ session.briefPath = briefPath;
18574
19089
  if (briefPath) {
18575
19090
  await refreshVaultAfterOutputSave(rootDir);
18576
19091
  }
19092
+ if (answeredGuidedSessionQuestions(session.questions).length === 0) {
19093
+ session.status = "awaiting_input";
19094
+ const persisted2 = await persistSourceSessionPage(rootDir, scope, session);
19095
+ session.sessionPath = persisted2.sessionPath;
19096
+ await writeGuidedSourceSession(rootDir, session);
19097
+ await refreshVaultAfterOutputSave(rootDir);
19098
+ return {
19099
+ sourceId: scope.id,
19100
+ sessionId: session.sessionId,
19101
+ sessionPath: persisted2.sessionPath,
19102
+ sessionStatePath: statePath,
19103
+ status: session.status,
19104
+ questions: session.questions,
19105
+ awaitingInput: true,
19106
+ targetedPagePaths: session.targetedPagePaths,
19107
+ stagedUpdatePaths: session.stagedUpdatePaths,
19108
+ briefPath,
19109
+ staged: false
19110
+ };
19111
+ }
19112
+ session.status = "ready_to_stage";
19113
+ await writeGuidedSourceSession(rootDir, session);
18577
19114
  const reviewOutput = await buildSourceReviewStagedPage(rootDir, scope);
18578
19115
  const guideOutput = await buildSourceGuideStagedPage(rootDir, {
18579
19116
  ...scope,
18580
19117
  briefPath
18581
19118
  });
19119
+ const guidedUpdates = await buildGuidedInsightUpdatePages(rootDir, scope, session);
19120
+ session.stagedUpdatePaths = guidedUpdates.map((item) => item.page.path);
18582
19121
  const approval = await stageGeneratedOutputPages(
18583
19122
  rootDir,
18584
19123
  [
18585
19124
  { page: reviewOutput.page, content: reviewOutput.content, label: "source-review" },
18586
- { page: guideOutput.page, content: guideOutput.content, label: "source-guide" }
19125
+ { page: guideOutput.page, content: guideOutput.content, label: "source-guide" },
19126
+ ...guidedUpdates
18587
19127
  ],
18588
19128
  {
18589
- bundleType: "guided_source",
18590
- title: `Guided Source: ${scope.title}`
19129
+ bundleType: "guided_session",
19130
+ title: `Guided Session: ${scope.title}`,
19131
+ sourceSessionId: session.sessionId
18591
19132
  }
18592
19133
  );
19134
+ session.status = "staged";
19135
+ session.reviewPath = path26.join(approval.approvalDir, "wiki", reviewOutput.page.path);
19136
+ session.guidePath = path26.join(approval.approvalDir, "wiki", guideOutput.page.path);
19137
+ session.approvalId = approval.approvalId;
19138
+ session.approvalDir = approval.approvalDir;
19139
+ const persisted = await persistSourceSessionPage(rootDir, scope, session);
19140
+ session.sessionPath = persisted.sessionPath;
19141
+ await writeGuidedSourceSession(rootDir, session);
18593
19142
  await refreshVaultAfterOutputSave(rootDir);
18594
19143
  return {
18595
19144
  sourceId: scope.id,
18596
19145
  pageId: guideOutput.page.id,
18597
- guidePath: path25.join(approval.approvalDir, "wiki", guideOutput.page.path),
19146
+ guidePath: session.guidePath,
18598
19147
  reviewPageId: reviewOutput.page.id,
18599
- reviewPath: path25.join(approval.approvalDir, "wiki", reviewOutput.page.path),
19148
+ reviewPath: session.reviewPath,
19149
+ sessionId: session.sessionId,
19150
+ sessionPath: persisted.sessionPath,
19151
+ sessionStatePath: statePath,
19152
+ status: session.status,
19153
+ questions: session.questions,
19154
+ targetedPagePaths: session.targetedPagePaths,
19155
+ stagedUpdatePaths: session.stagedUpdatePaths,
18600
19156
  briefPath,
18601
19157
  staged: true,
18602
19158
  approvalId: approval.approvalId,
@@ -18612,53 +19168,82 @@ function scopeFromManagedSource(source) {
18612
19168
  briefPath: source.briefPath
18613
19169
  };
18614
19170
  }
18615
- async function reviewSourceScope(rootDir, scope) {
18616
- return await stageSourceReviewForScope(rootDir, scope);
18617
- }
18618
- async function guideSourceScope(rootDir, scope) {
18619
- return await stageSourceGuideForScope(rootDir, scope);
18620
- }
18621
- async function reviewManagedSource(rootDir, id) {
18622
- const managedSources = await loadManagedSources(rootDir);
18623
- const managedSource = managedSources.find((source) => source.id === id);
18624
- if (managedSource) {
18625
- if (!await loadVaultConfig(rootDir).then(({ paths }) => fileExists(paths.graphPath))) {
18626
- await compileVault(rootDir, {});
18627
- }
18628
- return await stageSourceReviewForScope(rootDir, scopeFromManagedSource(managedSource));
18629
- }
18630
- const manifests = await listManifests(rootDir);
18631
- const manifest = manifests.find((candidate) => candidate.sourceId === id);
18632
- if (!manifest) {
18633
- throw new Error(`Managed source or source id not found: ${id}`);
18634
- }
18635
- return await stageSourceReviewForScope(rootDir, {
18636
- id: manifest.sourceGroupId ?? manifest.sourceId,
19171
+ function scopeFromManifest(manifest, manifests) {
19172
+ const groupId = manifest.sourceGroupId ?? manifest.sourceId;
19173
+ return {
19174
+ id: groupId,
18637
19175
  title: manifest.sourceGroupTitle ?? manifest.title,
18638
19176
  sourceIds: manifest.sourceGroupId ? manifests.filter((candidate) => candidate.sourceGroupId === manifest.sourceGroupId).map((candidate) => candidate.sourceId) : [manifest.sourceId],
18639
19177
  kind: manifest.sourceKind
18640
- });
19178
+ };
18641
19179
  }
18642
- async function guideManagedSource(rootDir, id) {
19180
+ async function resolveSourceScope(rootDir, id) {
18643
19181
  const managedSources = await loadManagedSources(rootDir);
18644
19182
  const managedSource = managedSources.find((source) => source.id === id);
18645
19183
  if (managedSource) {
18646
- if (!await loadVaultConfig(rootDir).then(({ paths }) => fileExists(paths.graphPath))) {
18647
- await compileVault(rootDir, {});
18648
- }
18649
- return await stageSourceGuideForScope(rootDir, scopeFromManagedSource(managedSource));
19184
+ return scopeFromManagedSource(managedSource);
19185
+ }
19186
+ const latestSession = await findLatestGuidedSourceSessionByScope(rootDir, id);
19187
+ if (latestSession) {
19188
+ return {
19189
+ id: latestSession.scopeId,
19190
+ title: latestSession.scopeTitle,
19191
+ sourceIds: latestSession.sourceIds
19192
+ };
18650
19193
  }
18651
19194
  const manifests = await listManifests(rootDir);
18652
- const manifest = manifests.find((candidate) => candidate.sourceId === id);
19195
+ const manifest = manifests.find((candidate) => candidate.sourceId === id) ?? manifests.find((candidate) => candidate.sourceGroupId === id);
18653
19196
  if (!manifest) {
19197
+ return null;
19198
+ }
19199
+ return scopeFromManifest(manifest, manifests);
19200
+ }
19201
+ async function reviewSourceScope(rootDir, scope) {
19202
+ return await stageSourceReviewForScope(rootDir, scope);
19203
+ }
19204
+ async function guideSourceScope(rootDir, scope, options = {}) {
19205
+ return await stageSourceGuideForScope(rootDir, scope, options);
19206
+ }
19207
+ async function reviewManagedSource(rootDir, id) {
19208
+ const scope = await resolveSourceScope(rootDir, id);
19209
+ if (!scope) {
18654
19210
  throw new Error(`Managed source or source id not found: ${id}`);
18655
19211
  }
18656
- return await stageSourceGuideForScope(rootDir, {
18657
- id: manifest.sourceGroupId ?? manifest.sourceId,
18658
- title: manifest.sourceGroupTitle ?? manifest.title,
18659
- sourceIds: manifest.sourceGroupId ? manifests.filter((candidate) => candidate.sourceGroupId === manifest.sourceGroupId).map((candidate) => candidate.sourceId) : [manifest.sourceId],
18660
- kind: manifest.sourceKind
18661
- });
19212
+ if (!await loadVaultConfig(rootDir).then(({ paths }) => fileExists(paths.graphPath))) {
19213
+ await compileVault(rootDir, {});
19214
+ }
19215
+ return await stageSourceReviewForScope(rootDir, scope);
19216
+ }
19217
+ async function guideManagedSource(rootDir, id, options = {}) {
19218
+ const scope = await resolveSourceScope(rootDir, id);
19219
+ if (!scope) {
19220
+ throw new Error(`Managed source or source id not found: ${id}`);
19221
+ }
19222
+ if (!await loadVaultConfig(rootDir).then(({ paths }) => fileExists(paths.graphPath))) {
19223
+ await compileVault(rootDir, {});
19224
+ }
19225
+ return await stageSourceGuideForScope(rootDir, scope, options);
19226
+ }
19227
+ async function resumeSourceSession(rootDir, id, options = {}) {
19228
+ const existingSession = await readGuidedSourceSession(rootDir, id);
19229
+ if (existingSession) {
19230
+ return await stageSourceGuideForScope(
19231
+ rootDir,
19232
+ {
19233
+ id: existingSession.scopeId,
19234
+ title: existingSession.scopeTitle,
19235
+ sourceIds: existingSession.sourceIds,
19236
+ kind: existingSession.kind,
19237
+ briefPath: existingSession.briefPath
19238
+ },
19239
+ options
19240
+ );
19241
+ }
19242
+ const scope = await resolveSourceScope(rootDir, id);
19243
+ if (!scope) {
19244
+ throw new Error(`Managed source, source scope, or guided session not found: ${id}`);
19245
+ }
19246
+ return await stageSourceGuideForScope(rootDir, scope, options);
18662
19247
  }
18663
19248
  function shouldCompile(changedSources, graphExists, compileRequested) {
18664
19249
  return compileRequested && (!graphExists || changedSources.length > 0);
@@ -18677,7 +19262,7 @@ async function addManagedSource(rootDir, input, options = {}) {
18677
19262
  const existing = sources.find((candidate) => matchesManagedSourceSpec(candidate, resolved));
18678
19263
  const now = (/* @__PURE__ */ new Date()).toISOString();
18679
19264
  const source = existing ?? {
18680
- id: resolved.kind === "directory" || resolved.kind === "file" ? stableManagedSourceId(resolved.kind, path25.resolve(resolved.path), resolved.title) : stableManagedSourceId(resolved.kind, resolved.url, resolved.title),
19265
+ id: resolved.kind === "directory" || resolved.kind === "file" ? stableManagedSourceId(resolved.kind, path26.resolve(resolved.path), resolved.title) : stableManagedSourceId(resolved.kind, resolved.url, resolved.title),
18681
19266
  kind: resolved.kind,
18682
19267
  title: resolved.title,
18683
19268
  path: resolved.kind === "directory" || resolved.kind === "file" ? resolved.path : void 0,
@@ -18712,10 +19297,14 @@ async function addManagedSource(rootDir, input, options = {}) {
18712
19297
  const nextSources = existing ? sources.map((candidate) => candidate.id === nextSource.id ? nextSource : candidate) : [...sources, nextSource];
18713
19298
  await saveManagedSources(rootDir, nextSources);
18714
19299
  const review = reviewRequested && nextSource.status === "ready" ? await stageSourceReviewForScope(rootDir, scopeFromManagedSource(nextSource)) : void 0;
18715
- const guide = guideRequested && nextSource.status === "ready" ? await stageSourceGuideForScope(rootDir, {
18716
- ...scopeFromManagedSource(nextSource),
18717
- briefPath: nextSource.briefPath
18718
- }) : void 0;
19300
+ const guide = guideRequested && nextSource.status === "ready" ? await stageSourceGuideForScope(
19301
+ rootDir,
19302
+ {
19303
+ ...scopeFromManagedSource(nextSource),
19304
+ briefPath: nextSource.briefPath
19305
+ },
19306
+ { answers: options.guideAnswers }
19307
+ ) : void 0;
18719
19308
  return {
18720
19309
  source: nextSource,
18721
19310
  compile,
@@ -18769,10 +19358,14 @@ async function reloadManagedSources(rootDir, options = {}) {
18769
19358
  ) : [];
18770
19359
  const guides = guideRequested ? await Promise.all(
18771
19360
  nextSources.filter((source) => selected.some((candidate) => candidate.id === source.id)).filter((source) => source.status === "ready").map(
18772
- async (source) => await stageSourceGuideForScope(rootDir, {
18773
- ...scopeFromManagedSource(source),
18774
- briefPath: source.briefPath
18775
- })
19361
+ async (source) => await stageSourceGuideForScope(
19362
+ rootDir,
19363
+ {
19364
+ ...scopeFromManagedSource(source),
19365
+ briefPath: source.briefPath
19366
+ },
19367
+ { answers: options.guideAnswers }
19368
+ )
18776
19369
  )
18777
19370
  ) : [];
18778
19371
  return {
@@ -18794,17 +19387,17 @@ async function deleteManagedSource(rootDir, id) {
18794
19387
  sources.filter((source) => source.id !== id)
18795
19388
  );
18796
19389
  const workingDir = await managedSourceWorkingDir(rootDir, id);
18797
- await fs21.rm(workingDir, { recursive: true, force: true });
19390
+ await fs22.rm(workingDir, { recursive: true, force: true });
18798
19391
  return { removed: target };
18799
19392
  }
18800
19393
 
18801
19394
  // src/viewer.ts
18802
19395
  import { execFile } from "child_process";
18803
- import fs22 from "fs/promises";
19396
+ import fs23 from "fs/promises";
18804
19397
  import http from "http";
18805
- import path27 from "path";
19398
+ import path28 from "path";
18806
19399
  import { promisify } from "util";
18807
- import matter10 from "gray-matter";
19400
+ import matter11 from "gray-matter";
18808
19401
  import mime2 from "mime-types";
18809
19402
 
18810
19403
  // src/graph-presentation.ts
@@ -18926,7 +19519,7 @@ function buildViewerGraphArtifact(graph, options = {}) {
18926
19519
  }
18927
19520
 
18928
19521
  // src/watch.ts
18929
- import path26 from "path";
19522
+ import path27 from "path";
18930
19523
  import process3 from "process";
18931
19524
  import chokidar from "chokidar";
18932
19525
  var MAX_BACKOFF_MS = 3e4;
@@ -18934,15 +19527,15 @@ var BACKOFF_THRESHOLD = 3;
18934
19527
  var CRITICAL_THRESHOLD = 10;
18935
19528
  var REPO_WATCH_IGNORES = /* @__PURE__ */ new Set([".git", ".venv"]);
18936
19529
  function withinRoot3(rootPath, targetPath) {
18937
- const relative = path26.relative(rootPath, targetPath);
18938
- return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
19530
+ const relative = path27.relative(rootPath, targetPath);
19531
+ return relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative);
18939
19532
  }
18940
19533
  function hasIgnoredRepoSegment(baseDir, targetPath) {
18941
- const relativePath = path26.relative(baseDir, targetPath);
19534
+ const relativePath = path27.relative(baseDir, targetPath);
18942
19535
  if (!relativePath || relativePath.startsWith("..")) {
18943
19536
  return false;
18944
19537
  }
18945
- return relativePath.split(path26.sep).some((segment) => REPO_WATCH_IGNORES.has(segment));
19538
+ return relativePath.split(path27.sep).some((segment) => REPO_WATCH_IGNORES.has(segment));
18946
19539
  }
18947
19540
  function workspaceIgnoreRoots(rootDir, paths) {
18948
19541
  return [
@@ -18951,16 +19544,16 @@ function workspaceIgnoreRoots(rootDir, paths) {
18951
19544
  paths.stateDir,
18952
19545
  paths.agentDir,
18953
19546
  paths.inboxDir,
18954
- path26.join(rootDir, ".claude"),
18955
- path26.join(rootDir, ".cursor"),
18956
- path26.join(rootDir, ".obsidian")
18957
- ].map((candidate) => path26.resolve(candidate));
19547
+ path27.join(rootDir, ".claude"),
19548
+ path27.join(rootDir, ".cursor"),
19549
+ path27.join(rootDir, ".obsidian")
19550
+ ].map((candidate) => path27.resolve(candidate));
18958
19551
  }
18959
19552
  async function resolveWatchTargets(rootDir, paths, options) {
18960
- const targets = /* @__PURE__ */ new Set([path26.resolve(paths.inboxDir)]);
19553
+ const targets = /* @__PURE__ */ new Set([path27.resolve(paths.inboxDir)]);
18961
19554
  if (options.repo) {
18962
19555
  for (const repoRoot of await listTrackedRepoRoots(rootDir)) {
18963
- targets.add(path26.resolve(repoRoot));
19556
+ targets.add(path27.resolve(repoRoot));
18964
19557
  }
18965
19558
  }
18966
19559
  return [...targets].sort((left, right) => left.localeCompare(right));
@@ -19090,7 +19683,7 @@ async function watchVault(rootDir, options = {}) {
19090
19683
  const { paths } = await initWorkspace(rootDir);
19091
19684
  const baseDebounceMs = options.debounceMs ?? 900;
19092
19685
  const ignoredRoots = workspaceIgnoreRoots(rootDir, paths);
19093
- const inboxWatchRoot = path26.resolve(paths.inboxDir);
19686
+ const inboxWatchRoot = path27.resolve(paths.inboxDir);
19094
19687
  let watchTargets = await resolveWatchTargets(rootDir, paths, options);
19095
19688
  let timer;
19096
19689
  let running = false;
@@ -19105,7 +19698,7 @@ async function watchVault(rootDir, options = {}) {
19105
19698
  usePolling: true,
19106
19699
  interval: 100,
19107
19700
  ignored: (targetPath) => {
19108
- const absolutePath = path26.resolve(targetPath);
19701
+ const absolutePath = path27.resolve(targetPath);
19109
19702
  const primaryTarget = watchTargets.filter((watchTarget) => withinRoot3(watchTarget, absolutePath)).sort((left, right) => right.length - left.length)[0] ?? null;
19110
19703
  if (!primaryTarget) {
19111
19704
  return false;
@@ -19294,8 +19887,8 @@ async function watchVault(rootDir, options = {}) {
19294
19887
  }
19295
19888
  };
19296
19889
  const reasonForPath = (targetPath) => {
19297
- const baseDir = watchTargets.filter((watchTarget) => withinRoot3(watchTarget, path26.resolve(targetPath))).sort((left, right) => right.length - left.length)[0] ?? paths.inboxDir;
19298
- return path26.relative(baseDir, targetPath) || ".";
19890
+ const baseDir = watchTargets.filter((watchTarget) => withinRoot3(watchTarget, path27.resolve(targetPath))).sort((left, right) => right.length - left.length)[0] ?? paths.inboxDir;
19891
+ return path27.relative(baseDir, targetPath) || ".";
19299
19892
  };
19300
19893
  watcher.on("add", (filePath) => schedule(`add:${reasonForPath(filePath)}`)).on("change", (filePath) => schedule(`change:${reasonForPath(filePath)}`)).on("unlink", (filePath) => schedule(`unlink:${reasonForPath(filePath)}`)).on("addDir", (dirPath) => schedule(`addDir:${reasonForPath(dirPath)}`)).on("unlinkDir", (dirPath) => schedule(`unlinkDir:${reasonForPath(dirPath)}`)).on("error", (caught) => schedule(`error:${caught instanceof Error ? caught.message : String(caught)}`));
19301
19894
  await new Promise((resolve, reject) => {
@@ -19337,15 +19930,15 @@ async function getWatchStatus(rootDir) {
19337
19930
  var execFileAsync = promisify(execFile);
19338
19931
  async function readViewerPage(rootDir, relativePath) {
19339
19932
  const { paths } = await loadVaultConfig(rootDir);
19340
- const absolutePath = path27.resolve(paths.wikiDir, relativePath);
19933
+ const absolutePath = path28.resolve(paths.wikiDir, relativePath);
19341
19934
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
19342
19935
  return null;
19343
19936
  }
19344
- const raw = await fs22.readFile(absolutePath, "utf8");
19345
- const parsed = matter10(raw);
19937
+ const raw = await fs23.readFile(absolutePath, "utf8");
19938
+ const parsed = matter11(raw);
19346
19939
  return {
19347
19940
  path: relativePath,
19348
- title: typeof parsed.data.title === "string" ? parsed.data.title : path27.basename(relativePath, path27.extname(relativePath)),
19941
+ title: typeof parsed.data.title === "string" ? parsed.data.title : path28.basename(relativePath, path28.extname(relativePath)),
19349
19942
  frontmatter: parsed.data,
19350
19943
  content: parsed.content,
19351
19944
  assets: normalizeOutputAssets(parsed.data.output_assets)
@@ -19353,12 +19946,12 @@ async function readViewerPage(rootDir, relativePath) {
19353
19946
  }
19354
19947
  async function readViewerAsset(rootDir, relativePath) {
19355
19948
  const { paths } = await loadVaultConfig(rootDir);
19356
- const absolutePath = path27.resolve(paths.wikiDir, relativePath);
19949
+ const absolutePath = path28.resolve(paths.wikiDir, relativePath);
19357
19950
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
19358
19951
  return null;
19359
19952
  }
19360
19953
  return {
19361
- buffer: await fs22.readFile(absolutePath),
19954
+ buffer: await fs23.readFile(absolutePath),
19362
19955
  mimeType: mime2.lookup(absolutePath) || "application/octet-stream"
19363
19956
  };
19364
19957
  }
@@ -19381,12 +19974,12 @@ async function readJsonBody(request) {
19381
19974
  return JSON.parse(raw);
19382
19975
  }
19383
19976
  async function ensureViewerDist(viewerDistDir) {
19384
- const indexPath = path27.join(viewerDistDir, "index.html");
19977
+ const indexPath = path28.join(viewerDistDir, "index.html");
19385
19978
  if (await fileExists(indexPath)) {
19386
19979
  return;
19387
19980
  }
19388
- const viewerProjectDir = path27.dirname(viewerDistDir);
19389
- if (await fileExists(path27.join(viewerProjectDir, "package.json"))) {
19981
+ const viewerProjectDir = path28.dirname(viewerDistDir);
19982
+ if (await fileExists(path28.join(viewerProjectDir, "package.json"))) {
19390
19983
  await execFileAsync("pnpm", ["build"], { cwd: viewerProjectDir });
19391
19984
  }
19392
19985
  }
@@ -19408,7 +20001,7 @@ async function startGraphServer(rootDir, port, options = {}) {
19408
20001
  response.end(JSON.stringify({ error: "Graph artifact not found. Run `swarmvault compile` first." }));
19409
20002
  return;
19410
20003
  }
19411
- const reportPath = path27.join(paths.wikiDir, "graph", "report.json");
20004
+ const reportPath = path28.join(paths.wikiDir, "graph", "report.json");
19412
20005
  const report = await readJsonFile(reportPath) ?? null;
19413
20006
  response.writeHead(200, { "content-type": "application/json" });
19414
20007
  response.end(JSON.stringify(buildViewerGraphArtifact(graph, { report, full: options.full ?? false })));
@@ -19468,14 +20061,14 @@ async function startGraphServer(rootDir, port, options = {}) {
19468
20061
  return;
19469
20062
  }
19470
20063
  if (url.pathname === "/api/graph-report") {
19471
- const reportPath = path27.join(paths.wikiDir, "graph", "report.json");
20064
+ const reportPath = path28.join(paths.wikiDir, "graph", "report.json");
19472
20065
  if (!await fileExists(reportPath)) {
19473
20066
  response.writeHead(404, { "content-type": "application/json" });
19474
20067
  response.end(JSON.stringify({ error: "Graph report artifact not found. Run `swarmvault compile` first." }));
19475
20068
  return;
19476
20069
  }
19477
20070
  response.writeHead(200, { "content-type": "application/json" });
19478
- response.end(await fs22.readFile(reportPath, "utf8"));
20071
+ response.end(await fs23.readFile(reportPath, "utf8"));
19479
20072
  return;
19480
20073
  }
19481
20074
  if (url.pathname === "/api/watch-status") {
@@ -19558,8 +20151,8 @@ async function startGraphServer(rootDir, port, options = {}) {
19558
20151
  return;
19559
20152
  }
19560
20153
  const relativePath = url.pathname === "/" ? "index.html" : url.pathname.slice(1);
19561
- const target = path27.join(paths.viewerDistDir, relativePath);
19562
- const fallback = path27.join(paths.viewerDistDir, "index.html");
20154
+ const target = path28.join(paths.viewerDistDir, relativePath);
20155
+ const fallback = path28.join(paths.viewerDistDir, "index.html");
19563
20156
  const filePath = await fileExists(target) ? target : fallback;
19564
20157
  if (!await fileExists(filePath)) {
19565
20158
  response.writeHead(503, { "content-type": "text/plain" });
@@ -19567,7 +20160,7 @@ async function startGraphServer(rootDir, port, options = {}) {
19567
20160
  return;
19568
20161
  }
19569
20162
  response.writeHead(200, { "content-type": mime2.lookup(filePath) || "text/plain" });
19570
- response.end(await fs22.readFile(filePath));
20163
+ response.end(await fs23.readFile(filePath));
19571
20164
  });
19572
20165
  await new Promise((resolve) => {
19573
20166
  server.listen(effectivePort, resolve);
@@ -19594,7 +20187,7 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19594
20187
  throw new Error("Graph artifact not found. Run `swarmvault compile` first.");
19595
20188
  }
19596
20189
  await ensureViewerDist(paths.viewerDistDir);
19597
- const indexPath = path27.join(paths.viewerDistDir, "index.html");
20190
+ const indexPath = path28.join(paths.viewerDistDir, "index.html");
19598
20191
  if (!await fileExists(indexPath)) {
19599
20192
  throw new Error("Viewer build not found. Run `pnpm build` first.");
19600
20193
  }
@@ -19620,17 +20213,17 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19620
20213
  } : null;
19621
20214
  })
19622
20215
  );
19623
- const rawHtml = await fs22.readFile(indexPath, "utf8");
20216
+ const rawHtml = await fs23.readFile(indexPath, "utf8");
19624
20217
  const scriptMatch = rawHtml.match(/<script type="module" crossorigin src="([^"]+)"><\/script>/);
19625
20218
  const styleMatch = rawHtml.match(/<link rel="stylesheet" crossorigin href="([^"]+)">/);
19626
- const scriptPath = scriptMatch?.[1] ? path27.join(paths.viewerDistDir, scriptMatch[1].replace(/^\//, "")) : null;
19627
- const stylePath = styleMatch?.[1] ? path27.join(paths.viewerDistDir, styleMatch[1].replace(/^\//, "")) : null;
20219
+ const scriptPath = scriptMatch?.[1] ? path28.join(paths.viewerDistDir, scriptMatch[1].replace(/^\//, "")) : null;
20220
+ const stylePath = styleMatch?.[1] ? path28.join(paths.viewerDistDir, styleMatch[1].replace(/^\//, "")) : null;
19628
20221
  if (!scriptPath || !await fileExists(scriptPath)) {
19629
20222
  throw new Error("Viewer script bundle not found. Run `pnpm build` first.");
19630
20223
  }
19631
- const script = await fs22.readFile(scriptPath, "utf8");
19632
- const style = stylePath && await fileExists(stylePath) ? await fs22.readFile(stylePath, "utf8") : "";
19633
- const report = await readJsonFile(path27.join(paths.wikiDir, "graph", "report.json"));
20224
+ const script = await fs23.readFile(scriptPath, "utf8");
20225
+ const style = stylePath && await fileExists(stylePath) ? await fs23.readFile(stylePath, "utf8") : "";
20226
+ const report = await readJsonFile(path28.join(paths.wikiDir, "graph", "report.json"));
19634
20227
  const embeddedData = JSON.stringify(
19635
20228
  { graph: buildViewerGraphArtifact(graph, { report, full: options.full ?? false }), pages: pages.filter(Boolean), report },
19636
20229
  null,
@@ -19653,9 +20246,9 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19653
20246
  "</html>",
19654
20247
  ""
19655
20248
  ].filter(Boolean).join("\n");
19656
- await fs22.mkdir(path27.dirname(outputPath), { recursive: true });
19657
- await fs22.writeFile(outputPath, html, "utf8");
19658
- return path27.resolve(outputPath);
20249
+ await fs23.mkdir(path28.dirname(outputPath), { recursive: true });
20250
+ await fs23.writeFile(outputPath, html, "utf8");
20251
+ return path28.resolve(outputPath);
19659
20252
  }
19660
20253
  export {
19661
20254
  acceptApproval,
@@ -19717,6 +20310,7 @@ export {
19717
20310
  rejectApproval,
19718
20311
  reloadManagedSources,
19719
20312
  resolvePaths,
20313
+ resumeSourceSession,
19720
20314
  reviewManagedSource,
19721
20315
  reviewSourceScope,
19722
20316
  runSchedule,