@swarmvaultai/engine 0.4.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-CWLDFLH2.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-2REAPKPO.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) {
@@ -13263,6 +13315,9 @@ function approvalSummary(manifest) {
13263
13315
  return {
13264
13316
  approvalId: manifest.approvalId,
13265
13317
  createdAt: manifest.createdAt,
13318
+ bundleType: manifest.bundleType,
13319
+ title: manifest.title,
13320
+ sourceSessionId: manifest.sourceSessionId,
13266
13321
  entryCount: manifest.entries.length,
13267
13322
  pendingCount: manifest.entries.filter((entry) => entry.status === "pending").length,
13268
13323
  acceptedCount: manifest.entries.filter((entry) => entry.status === "accepted").length,
@@ -13286,7 +13341,7 @@ function pageHashes(pages) {
13286
13341
  return Object.fromEntries(pages.map((page) => [page.page.id, page.contentHash]));
13287
13342
  }
13288
13343
  async function buildManagedGraphPage(absolutePath, defaults, build) {
13289
- const existingContent = await fileExists(absolutePath) ? await fs18.readFile(absolutePath, "utf8") : null;
13344
+ const existingContent = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
13290
13345
  let existing = await loadExistingManagedPageState(absolutePath, {
13291
13346
  status: defaults.status ?? "active",
13292
13347
  managedBy: defaults.managedBy
@@ -13324,7 +13379,7 @@ async function buildManagedGraphPage(absolutePath, defaults, build) {
13324
13379
  return built;
13325
13380
  }
13326
13381
  async function buildManagedContent(absolutePath, defaults, build) {
13327
- const existingContent = await fileExists(absolutePath) ? await fs18.readFile(absolutePath, "utf8") : null;
13382
+ const existingContent = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
13328
13383
  let existing = await loadExistingManagedPageState(absolutePath, {
13329
13384
  status: defaults.status ?? "active",
13330
13385
  managedBy: defaults.managedBy
@@ -13366,7 +13421,7 @@ function manifestDetailValue(manifest, key) {
13366
13421
  }
13367
13422
  async function loadAnalysesBySourceIds(paths, sourceIds) {
13368
13423
  const analyses = await Promise.all(
13369
- 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`)))
13370
13425
  );
13371
13426
  return analyses.filter((analysis) => Boolean(analysis?.sourceId));
13372
13427
  }
@@ -13374,6 +13429,10 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13374
13429
  const sourcePages = graph.pages.filter((page) => page.kind === "source");
13375
13430
  const reviewPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-reviews/"));
13376
13431
  const briefPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-briefs/"));
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/"));
13434
+ const conceptPages = graph.pages.filter((page) => page.kind === "concept" && page.status !== "candidate").slice(0, 16);
13435
+ const entityPages = graph.pages.filter((page) => page.kind === "entity" && page.status !== "candidate").slice(0, 16);
13377
13436
  const manifests = graph.sources;
13378
13437
  const manifestBySourceId = new Map(manifests.map((manifest) => [manifest.sourceId, manifest]));
13379
13438
  const timelineManifests = manifests.filter((manifest) => manifestDetailValue(manifest, "occurred_at")).sort((left, right) => (manifestDetailValue(right, "occurred_at") ?? "").localeCompare(manifestDetailValue(left, "occurred_at") ?? "")).slice(0, 25);
@@ -13382,6 +13441,10 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13382
13441
  const openQuestions = uniqueStrings3(
13383
13442
  analyses.flatMap((analysis) => analysis.questions.map((question) => `${analysis.title}: ${question}`))
13384
13443
  ).slice(0, 20);
13444
+ const sourceSessions = await listGuidedSourceSessions(paths.rootDir);
13445
+ const stagedGuideBundles = (await Promise.all(
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);
13385
13448
  const dashboards = [
13386
13449
  {
13387
13450
  relativePath: "dashboards/index.md",
@@ -13391,7 +13454,11 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13391
13454
  "# Dashboards",
13392
13455
  "",
13393
13456
  "- [[dashboards/recent-sources|Recent Sources]]",
13457
+ "- [[dashboards/reading-log|Reading Log]]",
13394
13458
  "- [[dashboards/timeline|Timeline]]",
13459
+ "- [[dashboards/source-sessions|Source Sessions]]",
13460
+ "- [[dashboards/source-guides|Source Guides]]",
13461
+ "- [[dashboards/research-map|Research Map]]",
13395
13462
  "- [[dashboards/contradictions|Contradictions]]",
13396
13463
  "- [[dashboards/open-questions|Open Questions]]",
13397
13464
  "",
@@ -13464,6 +13531,57 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13464
13531
  }
13465
13532
  )
13466
13533
  },
13534
+ {
13535
+ relativePath: "dashboards/reading-log.md",
13536
+ title: "Reading Log",
13537
+ content: (metadata) => matter9.stringify(
13538
+ [
13539
+ "# Reading Log",
13540
+ "",
13541
+ ...timelineManifests.length ? timelineManifests.map((manifest) => {
13542
+ const occurredAt = manifestDetailValue(manifest, "occurred_at") ?? manifest.updatedAt;
13543
+ const participants = manifestDetailValue(manifest, "participants");
13544
+ return `- ${occurredAt}: ${manifest.title}${participants ? ` (${participants})` : ""}`;
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
+ ] : [],
13554
+ "",
13555
+ "```dataview",
13556
+ "TABLE occurred_at, source_type, participants, container_title",
13557
+ 'FROM "sources"',
13558
+ "SORT occurred_at desc",
13559
+ "LIMIT 25",
13560
+ "```",
13561
+ ""
13562
+ ].join("\n"),
13563
+ {
13564
+ page_id: "dashboards:reading-log",
13565
+ kind: "index",
13566
+ title: "Reading Log",
13567
+ tags: ["index", "dashboard", "reading-log"],
13568
+ source_ids: timelineManifests.map((manifest) => manifest.sourceId),
13569
+ project_ids: [],
13570
+ node_ids: [],
13571
+ freshness: "fresh",
13572
+ status: metadata.status,
13573
+ confidence: 1,
13574
+ created_at: metadata.createdAt,
13575
+ updated_at: metadata.updatedAt,
13576
+ compiled_from: timelineManifests.map((manifest) => manifest.sourceId),
13577
+ managed_by: metadata.managedBy,
13578
+ backlinks: [],
13579
+ schema_hash: schemaHash,
13580
+ source_hashes: {},
13581
+ source_semantic_hashes: {}
13582
+ }
13583
+ )
13584
+ },
13467
13585
  {
13468
13586
  relativePath: "dashboards/timeline.md",
13469
13587
  title: "Timeline",
@@ -13507,6 +13625,169 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13507
13625
  }
13508
13626
  )
13509
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
+ },
13681
+ {
13682
+ relativePath: "dashboards/source-guides.md",
13683
+ title: "Source Guides",
13684
+ content: (metadata) => matter9.stringify(
13685
+ [
13686
+ "# Source Guides",
13687
+ "",
13688
+ ...guidePages.length ? guidePages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No accepted source guides yet."],
13689
+ "",
13690
+ "## Pending Guided Bundles",
13691
+ "",
13692
+ ...stagedGuideBundles.length ? stagedGuideBundles.map(
13693
+ (bundle) => `- ${bundle.createdAt}: \`${bundle.approvalId}\`${bundle.title ? ` ${bundle.title}` : ""} (${bundle.entries.length} staged entr${bundle.entries.length === 1 ? "y" : "ies"})`
13694
+ ) : ["- No staged guided bundles right now."],
13695
+ "",
13696
+ "```dataview",
13697
+ 'LIST FROM "outputs/source-guides"',
13698
+ "SORT file.mtime desc",
13699
+ "```",
13700
+ ""
13701
+ ].join("\n"),
13702
+ {
13703
+ page_id: "dashboards:source-guides",
13704
+ kind: "index",
13705
+ title: "Source Guides",
13706
+ tags: ["index", "dashboard", "source-guides"],
13707
+ source_ids: uniqueStrings3([
13708
+ ...guidePages.flatMap((page) => page.sourceIds),
13709
+ ...stagedGuideBundles.flatMap((bundle) => bundle.entries.flatMap((entry) => entry.sourceIds))
13710
+ ]),
13711
+ project_ids: [],
13712
+ node_ids: [],
13713
+ freshness: "fresh",
13714
+ status: metadata.status,
13715
+ confidence: 1,
13716
+ created_at: metadata.createdAt,
13717
+ updated_at: metadata.updatedAt,
13718
+ compiled_from: uniqueStrings3([
13719
+ ...guidePages.flatMap((page) => page.sourceIds),
13720
+ ...stagedGuideBundles.flatMap((bundle) => bundle.entries.flatMap((entry) => entry.sourceIds))
13721
+ ]),
13722
+ managed_by: metadata.managedBy,
13723
+ backlinks: [],
13724
+ schema_hash: schemaHash,
13725
+ source_hashes: {},
13726
+ source_semantic_hashes: {}
13727
+ }
13728
+ )
13729
+ },
13730
+ {
13731
+ relativePath: "dashboards/research-map.md",
13732
+ title: "Research Map",
13733
+ content: (metadata) => matter9.stringify(
13734
+ [
13735
+ "# Research Map",
13736
+ "",
13737
+ "## Canonical Concept Pages",
13738
+ "",
13739
+ ...conceptPages.length ? conceptPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No concept pages yet."],
13740
+ "",
13741
+ "## Canonical Entity Pages",
13742
+ "",
13743
+ ...entityPages.length ? entityPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No entity pages yet."],
13744
+ "",
13745
+ "## Recently Guided Sources",
13746
+ "",
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."],
13752
+ ...report?.suggestedQuestions?.length ? ["", "## Suggested Questions", "", ...report.suggestedQuestions.slice(0, 8).map((question) => `- ${question}`)] : [],
13753
+ "",
13754
+ "```dataview",
13755
+ 'TABLE file.folder, file.mtime FROM "concepts" OR "entities"',
13756
+ "SORT file.mtime desc",
13757
+ "LIMIT 30",
13758
+ "```",
13759
+ ""
13760
+ ].join("\n"),
13761
+ {
13762
+ page_id: "dashboards:research-map",
13763
+ kind: "index",
13764
+ title: "Research Map",
13765
+ tags: ["index", "dashboard", "research-map"],
13766
+ source_ids: uniqueStrings3([
13767
+ ...conceptPages.flatMap((page) => page.sourceIds),
13768
+ ...entityPages.flatMap((page) => page.sourceIds),
13769
+ ...guidePages.flatMap((page) => page.sourceIds)
13770
+ ]),
13771
+ project_ids: [],
13772
+ node_ids: [],
13773
+ freshness: "fresh",
13774
+ status: metadata.status,
13775
+ confidence: 1,
13776
+ created_at: metadata.createdAt,
13777
+ updated_at: metadata.updatedAt,
13778
+ compiled_from: uniqueStrings3([
13779
+ ...conceptPages.flatMap((page) => page.sourceIds),
13780
+ ...entityPages.flatMap((page) => page.sourceIds),
13781
+ ...guidePages.flatMap((page) => page.sourceIds)
13782
+ ]),
13783
+ managed_by: metadata.managedBy,
13784
+ backlinks: [],
13785
+ schema_hash: schemaHash,
13786
+ source_hashes: {},
13787
+ source_semantic_hashes: {}
13788
+ }
13789
+ )
13790
+ },
13510
13791
  {
13511
13792
  relativePath: "dashboards/contradictions.md",
13512
13793
  title: "Contradictions",
@@ -13520,14 +13801,14 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13520
13801
  return `- ${left} / ${right}: ${contradiction.claimA} <> ${contradiction.claimB}`;
13521
13802
  }) : ["- No contradictions are currently flagged."],
13522
13803
  "",
13523
- ...reviewPages.length || briefPages.length ? [
13804
+ ...reviewPages.length || briefPages.length || guidePages.length ? [
13524
13805
  "## Related Reviews",
13525
13806
  "",
13526
- ...[...reviewPages, ...briefPages].slice(0, 12).map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`),
13807
+ ...[...guidePages, ...reviewPages, ...briefPages].slice(0, 12).map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`),
13527
13808
  ""
13528
13809
  ] : [],
13529
13810
  "```dataview",
13530
- 'LIST FROM "outputs/source-reviews"',
13811
+ 'LIST FROM "outputs/source-reviews" OR "outputs/source-guides"',
13531
13812
  "SORT file.mtime desc",
13532
13813
  "```",
13533
13814
  ""
@@ -13562,9 +13843,15 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13562
13843
  "# Open Questions",
13563
13844
  "",
13564
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
+ ] : [],
13565
13852
  "",
13566
13853
  "```dataview",
13567
- 'LIST FROM "outputs/source-briefs" OR "outputs/source-reviews"',
13854
+ 'LIST FROM "outputs/source-briefs" OR "outputs/source-reviews" OR "outputs/source-guides" OR "outputs/source-sessions"',
13568
13855
  "SORT file.mtime desc",
13569
13856
  "```",
13570
13857
  ""
@@ -13594,7 +13881,7 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13594
13881
  ];
13595
13882
  const records = [];
13596
13883
  for (const dashboard of dashboards) {
13597
- const absolutePath = path22.join(paths.wikiDir, dashboard.relativePath);
13884
+ const absolutePath = path23.join(paths.wikiDir, dashboard.relativePath);
13598
13885
  const compiledFrom = dashboard.relativePath === "dashboards/recent-sources.md" ? recentSourcePages.flatMap((page) => page.sourceIds) : [];
13599
13886
  const content = await buildManagedContent(
13600
13887
  absolutePath,
@@ -13708,7 +13995,7 @@ function resetGraphNodeMetrics(nodes) {
13708
13995
  return nodes.map(({ communityId: _communityId, degree: _degree, bridgeScore: _bridgeScore, isGodNode: _isGodNode, ...node }) => node);
13709
13996
  }
13710
13997
  function manifestRepoPath(manifest) {
13711
- return toPosix(manifest.repoRelativePath ?? path22.basename(manifest.originalPath ?? manifest.storedPath));
13998
+ return toPosix(manifest.repoRelativePath ?? path23.basename(manifest.originalPath ?? manifest.storedPath));
13712
13999
  }
13713
14000
  function goPackageScopeKey(manifest, analysis) {
13714
14001
  if (analysis.code?.language !== "go") {
@@ -13718,7 +14005,7 @@ function goPackageScopeKey(manifest, analysis) {
13718
14005
  if (!packageName) {
13719
14006
  return null;
13720
14007
  }
13721
- return `${packageName}:${path22.posix.dirname(manifestRepoPath(manifest))}`;
14008
+ return `${packageName}:${path23.posix.dirname(manifestRepoPath(manifest))}`;
13722
14009
  }
13723
14010
  function buildGoPackageSymbolLookups(analyses, manifestsById) {
13724
14011
  const lookups = /* @__PURE__ */ new Map();
@@ -14187,7 +14474,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14187
14474
  const benchmark = await readJsonFile(paths.benchmarkPath);
14188
14475
  const communityRecords = [];
14189
14476
  for (const community of graph.communities ?? []) {
14190
- 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`);
14191
14478
  communityRecords.push(
14192
14479
  await buildManagedGraphPage(
14193
14480
  absolutePath,
@@ -14216,7 +14503,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14216
14503
  graphHash: graphHash(graph),
14217
14504
  contradictions
14218
14505
  });
14219
- const reportAbsolutePath = path22.join(paths.wikiDir, "graph", "report.md");
14506
+ const reportAbsolutePath = path23.join(paths.wikiDir, "graph", "report.md");
14220
14507
  const reportRecord = await buildManagedGraphPage(
14221
14508
  reportAbsolutePath,
14222
14509
  {
@@ -14237,7 +14524,7 @@ async function buildGraphOrientationPages(graph, paths, schemaHash, previousComp
14237
14524
  };
14238
14525
  }
14239
14526
  async function writePage(wikiDir, relativePath, content, changedPages) {
14240
- const absolutePath = path22.resolve(wikiDir, relativePath);
14527
+ const absolutePath = path23.resolve(wikiDir, relativePath);
14241
14528
  const changed = await writeFileIfChanged(absolutePath, content);
14242
14529
  if (changed) {
14243
14530
  changedPages.push(relativePath);
@@ -14303,29 +14590,29 @@ async function requiredCompileArtifactsExist(paths) {
14303
14590
  paths.graphPath,
14304
14591
  paths.codeIndexPath,
14305
14592
  paths.searchDbPath,
14306
- path22.join(paths.wikiDir, "index.md"),
14307
- path22.join(paths.wikiDir, "sources", "index.md"),
14308
- path22.join(paths.wikiDir, "code", "index.md"),
14309
- path22.join(paths.wikiDir, "concepts", "index.md"),
14310
- path22.join(paths.wikiDir, "entities", "index.md"),
14311
- path22.join(paths.wikiDir, "outputs", "index.md"),
14312
- path22.join(paths.wikiDir, "projects", "index.md"),
14313
- 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")
14314
14601
  ];
14315
14602
  const checks = await Promise.all(requiredPaths.map((filePath) => fileExists(filePath)));
14316
14603
  return checks.every(Boolean);
14317
14604
  }
14318
14605
  async function loadAvailableCachedAnalyses(paths, manifests) {
14319
14606
  const analyses = await Promise.all(
14320
- 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`)))
14321
14608
  );
14322
14609
  return analyses.filter((analysis) => Boolean(analysis));
14323
14610
  }
14324
14611
  function approvalManifestPath(paths, approvalId) {
14325
- return path22.join(paths.approvalsDir, approvalId, "manifest.json");
14612
+ return path23.join(paths.approvalsDir, approvalId, "manifest.json");
14326
14613
  }
14327
14614
  function approvalGraphPath(paths, approvalId) {
14328
- return path22.join(paths.approvalsDir, approvalId, "state", "graph.json");
14615
+ return path23.join(paths.approvalsDir, approvalId, "state", "graph.json");
14329
14616
  }
14330
14617
  async function readApprovalManifest(paths, approvalId) {
14331
14618
  const manifest = await readJsonFile(approvalManifestPath(paths, approvalId));
@@ -14335,10 +14622,10 @@ async function readApprovalManifest(paths, approvalId) {
14335
14622
  return manifest;
14336
14623
  }
14337
14624
  async function writeApprovalManifest(paths, manifest) {
14338
- 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)}
14339
14626
  `, "utf8");
14340
14627
  }
14341
- async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousGraph, graph) {
14628
+ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousGraph, graph, labelsByPath = /* @__PURE__ */ new Map()) {
14342
14629
  const previousPagesById = new Map((previousGraph?.pages ?? []).map((page) => [page.id, page]));
14343
14630
  const previousPagesByPath = new Map((previousGraph?.pages ?? []).map((page) => [page.path, page]));
14344
14631
  const nextPagesByPath = new Map(graph.pages.map((page) => [page.path, page]));
@@ -14350,7 +14637,7 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14350
14637
  continue;
14351
14638
  }
14352
14639
  const previousPage = previousPagesById.get(nextPage.id);
14353
- const currentExists = await fileExists(path22.join(paths.wikiDir, file.relativePath));
14640
+ const currentExists = await fileExists(path23.join(paths.wikiDir, file.relativePath));
14354
14641
  if (previousPage && previousPage.path !== nextPage.path) {
14355
14642
  entries.push({
14356
14643
  pageId: nextPage.id,
@@ -14360,7 +14647,8 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14360
14647
  status: "pending",
14361
14648
  sourceIds: nextPage.sourceIds,
14362
14649
  nextPath: nextPage.path,
14363
- previousPath: previousPage.path
14650
+ previousPath: previousPage.path,
14651
+ label: labelsByPath.get(nextPage.path) ?? labelsByPath.get(previousPage.path)
14364
14652
  });
14365
14653
  handledDeletedPaths.add(previousPage.path);
14366
14654
  continue;
@@ -14373,7 +14661,8 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14373
14661
  status: "pending",
14374
14662
  sourceIds: nextPage.sourceIds,
14375
14663
  nextPath: nextPage.path,
14376
- previousPath: previousPage?.path
14664
+ previousPath: previousPage?.path,
14665
+ label: labelsByPath.get(nextPage.path) ?? (previousPage?.path ? labelsByPath.get(previousPage.path) : void 0)
14377
14666
  });
14378
14667
  }
14379
14668
  for (const deletedPath of deletedPaths.sort((left, right) => left.localeCompare(right))) {
@@ -14383,31 +14672,34 @@ async function buildApprovalEntries(paths, changedFiles, deletedPaths, previousG
14383
14672
  const previousPage = previousPagesByPath.get(deletedPath);
14384
14673
  entries.push({
14385
14674
  pageId: previousPage?.id ?? `page:${slugify(deletedPath)}`,
14386
- title: previousPage?.title ?? path22.basename(deletedPath, ".md"),
14675
+ title: previousPage?.title ?? path23.basename(deletedPath, ".md"),
14387
14676
  kind: previousPage?.kind ?? "index",
14388
14677
  changeType: "delete",
14389
14678
  status: "pending",
14390
14679
  sourceIds: previousPage?.sourceIds ?? [],
14391
- previousPath: deletedPath
14680
+ previousPath: deletedPath,
14681
+ label: labelsByPath.get(deletedPath)
14392
14682
  });
14393
14683
  }
14394
14684
  return uniqueBy(entries, (entry) => `${entry.pageId}:${entry.changeType}:${entry.nextPath ?? ""}:${entry.previousPath ?? ""}`);
14395
14685
  }
14396
14686
  async function stageApprovalBundle(paths, changedFiles, deletedPaths, previousGraph, graph) {
14397
14687
  const approvalId = `compile-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
14398
- const approvalDir = path22.join(paths.approvalsDir, approvalId);
14688
+ const approvalDir = path23.join(paths.approvalsDir, approvalId);
14399
14689
  await ensureDir(approvalDir);
14400
- await ensureDir(path22.join(approvalDir, "wiki"));
14401
- await ensureDir(path22.join(approvalDir, "state"));
14690
+ await ensureDir(path23.join(approvalDir, "wiki"));
14691
+ await ensureDir(path23.join(approvalDir, "state"));
14402
14692
  for (const file of changedFiles) {
14403
- const targetPath = path22.join(approvalDir, "wiki", file.relativePath);
14404
- await ensureDir(path22.dirname(targetPath));
14405
- 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");
14406
14696
  }
14407
- 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");
14408
14698
  await writeApprovalManifest(paths, {
14409
14699
  approvalId,
14410
14700
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
14701
+ bundleType: "compile",
14702
+ title: "Compile Approval",
14411
14703
  entries: await buildApprovalEntries(paths, changedFiles, deletedPaths, previousGraph, graph)
14412
14704
  });
14413
14705
  return { approvalId, approvalDir };
@@ -14468,7 +14760,7 @@ async function syncVaultArtifacts(rootDir, input) {
14468
14760
  confidence: 1
14469
14761
  });
14470
14762
  const sourceRecord = await buildManagedGraphPage(
14471
- path22.join(paths.wikiDir, preview.path),
14763
+ path23.join(paths.wikiDir, preview.path),
14472
14764
  {
14473
14765
  managedBy: "system",
14474
14766
  confidence: 1,
@@ -14514,7 +14806,7 @@ async function syncVaultArtifacts(rootDir, input) {
14514
14806
  );
14515
14807
  records.push(
14516
14808
  await buildManagedGraphPage(
14517
- path22.join(paths.wikiDir, modulePreview.path),
14809
+ path23.join(paths.wikiDir, modulePreview.path),
14518
14810
  {
14519
14811
  managedBy: "system",
14520
14812
  confidence: 1,
@@ -14548,8 +14840,8 @@ async function syncVaultArtifacts(rootDir, input) {
14548
14840
  const relativePath = promoted ? activeAggregatePath(itemKind, slug) : candidatePagePathFor(itemKind, slug);
14549
14841
  const aggregateSourceClass2 = aggregateManifestSourceClass(input.manifests, sourceIds);
14550
14842
  const fallbackPaths = [
14551
- path22.join(paths.wikiDir, activeAggregatePath(itemKind, slug)),
14552
- path22.join(paths.wikiDir, candidatePagePathFor(itemKind, slug))
14843
+ path23.join(paths.wikiDir, activeAggregatePath(itemKind, slug)),
14844
+ path23.join(paths.wikiDir, candidatePagePathFor(itemKind, slug))
14553
14845
  ];
14554
14846
  const confidence = nodeConfidence(aggregate.sourceAnalyses.length);
14555
14847
  const preview = emptyGraphPage({
@@ -14567,7 +14859,7 @@ async function syncVaultArtifacts(rootDir, input) {
14567
14859
  status: promoted ? "active" : "candidate"
14568
14860
  });
14569
14861
  const pageRecord = await buildManagedGraphPage(
14570
- path22.join(paths.wikiDir, relativePath),
14862
+ path23.join(paths.wikiDir, relativePath),
14571
14863
  {
14572
14864
  status: promoted ? "active" : "candidate",
14573
14865
  managedBy: "system",
@@ -14696,7 +14988,7 @@ async function syncVaultArtifacts(rootDir, input) {
14696
14988
  confidence: 1
14697
14989
  }),
14698
14990
  content: await buildManagedContent(
14699
- path22.join(paths.wikiDir, "projects", "index.md"),
14991
+ path23.join(paths.wikiDir, "projects", "index.md"),
14700
14992
  {
14701
14993
  managedBy: "system",
14702
14994
  compiledFrom: indexCompiledFrom(projectIndexRefs)
@@ -14720,7 +15012,7 @@ async function syncVaultArtifacts(rootDir, input) {
14720
15012
  records.push({
14721
15013
  page: projectIndexRef,
14722
15014
  content: await buildManagedContent(
14723
- path22.join(paths.wikiDir, projectIndexRef.path),
15015
+ path23.join(paths.wikiDir, projectIndexRef.path),
14724
15016
  {
14725
15017
  managedBy: "system",
14726
15018
  compiledFrom: indexCompiledFrom(Object.values(sections).flat())
@@ -14748,7 +15040,7 @@ async function syncVaultArtifacts(rootDir, input) {
14748
15040
  confidence: 1
14749
15041
  }),
14750
15042
  content: await buildManagedContent(
14751
- path22.join(paths.wikiDir, "index.md"),
15043
+ path23.join(paths.wikiDir, "index.md"),
14752
15044
  {
14753
15045
  managedBy: "system",
14754
15046
  compiledFrom: indexCompiledFrom(allPages)
@@ -14784,7 +15076,7 @@ async function syncVaultArtifacts(rootDir, input) {
14784
15076
  confidence: 1
14785
15077
  }),
14786
15078
  content: await buildManagedContent(
14787
- path22.join(paths.wikiDir, relativePath),
15079
+ path23.join(paths.wikiDir, relativePath),
14788
15080
  {
14789
15081
  managedBy: "system",
14790
15082
  compiledFrom: indexCompiledFrom(pages)
@@ -14795,12 +15087,12 @@ async function syncVaultArtifacts(rootDir, input) {
14795
15087
  }
14796
15088
  const nextPagePaths = new Set(records.map((record) => record.page.path));
14797
15089
  const obsoleteGraphPaths = (previousGraph?.pages ?? []).filter((page) => page.kind !== "output" && page.kind !== "insight").map((page) => page.path).filter((relativePath) => !nextPagePaths.has(relativePath));
14798
- 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));
14799
15091
  const obsoletePaths = uniqueStrings3([...obsoleteGraphPaths, ...existingProjectIndexPaths]);
14800
15092
  const changedFiles = [];
14801
15093
  for (const record of records) {
14802
- const absolutePath = path22.join(paths.wikiDir, record.page.path);
14803
- 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;
14804
15096
  if (current !== record.content) {
14805
15097
  changedPages.push(record.page.path);
14806
15098
  changedFiles.push({ relativePath: record.page.path, content: record.content });
@@ -14825,10 +15117,10 @@ async function syncVaultArtifacts(rootDir, input) {
14825
15117
  await writePage(paths.wikiDir, record.page.path, record.content, writeChanges);
14826
15118
  }
14827
15119
  for (const relativePath of obsoletePaths) {
14828
- await fs18.rm(path22.join(paths.wikiDir, relativePath), { force: true });
15120
+ await fs19.rm(path23.join(paths.wikiDir, relativePath), { force: true });
14829
15121
  }
14830
15122
  await writeJsonFile(paths.graphPath, graph);
14831
- await writeJsonFile(path22.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15123
+ await writeJsonFile(path23.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
14832
15124
  await writeJsonFile(paths.codeIndexPath, input.codeIndex);
14833
15125
  await writeJsonFile(paths.compileStatePath, {
14834
15126
  generatedAt: graph.generatedAt,
@@ -14923,18 +15215,18 @@ async function refreshIndexesAndSearch(rootDir, pages) {
14923
15215
  })
14924
15216
  );
14925
15217
  await Promise.all([
14926
- ensureDir(path22.join(paths.wikiDir, "sources")),
14927
- ensureDir(path22.join(paths.wikiDir, "code")),
14928
- ensureDir(path22.join(paths.wikiDir, "concepts")),
14929
- ensureDir(path22.join(paths.wikiDir, "entities")),
14930
- ensureDir(path22.join(paths.wikiDir, "outputs")),
14931
- ensureDir(path22.join(paths.wikiDir, "dashboards")),
14932
- ensureDir(path22.join(paths.wikiDir, "graph")),
14933
- ensureDir(path22.join(paths.wikiDir, "graph", "communities")),
14934
- ensureDir(path22.join(paths.wikiDir, "projects")),
14935
- 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"))
14936
15228
  ]);
14937
- const projectsIndexPath = path22.join(paths.wikiDir, "projects", "index.md");
15229
+ const projectsIndexPath = path23.join(paths.wikiDir, "projects", "index.md");
14938
15230
  await writeFileIfChanged(
14939
15231
  projectsIndexPath,
14940
15232
  await buildManagedContent(
@@ -14955,7 +15247,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
14955
15247
  outputs: pages.filter((page) => page.kind === "output" && page.projectIds.includes(project.id)),
14956
15248
  candidates: pages.filter((page) => page.status === "candidate" && page.projectIds.includes(project.id))
14957
15249
  };
14958
- const absolutePath = path22.join(paths.wikiDir, "projects", project.id, "index.md");
15250
+ const absolutePath = path23.join(paths.wikiDir, "projects", project.id, "index.md");
14959
15251
  await writeFileIfChanged(
14960
15252
  absolutePath,
14961
15253
  await buildManagedContent(
@@ -14973,7 +15265,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
14973
15265
  )
14974
15266
  );
14975
15267
  }
14976
- const rootIndexPath = path22.join(paths.wikiDir, "index.md");
15268
+ const rootIndexPath = path23.join(paths.wikiDir, "index.md");
14977
15269
  await writeFileIfChanged(
14978
15270
  rootIndexPath,
14979
15271
  await buildManagedContent(
@@ -14999,7 +15291,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
14999
15291
  ["candidates/index.md", "candidates", pagesWithGraph.filter((page) => page.status === "candidate")],
15000
15292
  ["graph/index.md", "graph", pagesWithGraph.filter((page) => page.kind === "graph_report" || page.kind === "community_summary")]
15001
15293
  ]) {
15002
- const absolutePath = path22.join(paths.wikiDir, relativePath);
15294
+ const absolutePath = path23.join(paths.wikiDir, relativePath);
15003
15295
  await writeFileIfChanged(
15004
15296
  absolutePath,
15005
15297
  await buildManagedContent(
@@ -15013,31 +15305,31 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15013
15305
  );
15014
15306
  }
15015
15307
  for (const record of graphOrientation.records) {
15016
- await writeFileIfChanged(path22.join(paths.wikiDir, record.page.path), record.content);
15308
+ await writeFileIfChanged(path23.join(paths.wikiDir, record.page.path), record.content);
15017
15309
  }
15018
15310
  for (const record of dashboardRecords) {
15019
- await writeFileIfChanged(path22.join(paths.wikiDir, record.page.path), record.content);
15311
+ await writeFileIfChanged(path23.join(paths.wikiDir, record.page.path), record.content);
15020
15312
  }
15021
15313
  if (graphOrientation.report) {
15022
- await writeJsonFile(path22.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15314
+ await writeJsonFile(path23.join(paths.wikiDir, "graph", "report.json"), graphOrientation.report);
15023
15315
  }
15024
- 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)));
15025
15317
  const allowedProjectIndexPaths = /* @__PURE__ */ new Set([
15026
15318
  "projects/index.md",
15027
15319
  ...configuredProjects.map((project) => `projects/${project.id}/index.md`)
15028
15320
  ]);
15029
15321
  await Promise.all(
15030
- 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 }))
15031
15323
  );
15032
- 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)));
15033
15325
  const allowedGraphPages = /* @__PURE__ */ new Set(["graph/index.md", ...graphOrientation.records.map((record) => record.page.path)]);
15034
15326
  await Promise.all(
15035
- 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 }))
15036
15328
  );
15037
- 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)));
15038
15330
  const allowedDashboardPages = /* @__PURE__ */ new Set(["dashboards/index.md", ...dashboardRecords.map((record) => record.page.path)]);
15039
15331
  await Promise.all(
15040
- 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 }))
15041
15333
  );
15042
15334
  await rebuildSearchIndex(paths.searchDbPath, pagesWithGraph, paths.wikiDir);
15043
15335
  }
@@ -15057,7 +15349,7 @@ async function prepareOutputPageSave(rootDir, input) {
15057
15349
  confidence: 0.74
15058
15350
  }
15059
15351
  });
15060
- const absolutePath = path22.join(paths.wikiDir, output.page.path);
15352
+ const absolutePath = path23.join(paths.wikiDir, output.page.path);
15061
15353
  return {
15062
15354
  page: output.page,
15063
15355
  savedPath: absolutePath,
@@ -15069,15 +15361,15 @@ async function prepareOutputPageSave(rootDir, input) {
15069
15361
  async function persistOutputPage(rootDir, input) {
15070
15362
  const { paths } = await loadVaultConfig(rootDir);
15071
15363
  const prepared = await prepareOutputPageSave(rootDir, input);
15072
- await ensureDir(path22.dirname(prepared.savedPath));
15073
- await fs18.writeFile(prepared.savedPath, prepared.content, "utf8");
15364
+ await ensureDir(path23.dirname(prepared.savedPath));
15365
+ await fs19.writeFile(prepared.savedPath, prepared.content, "utf8");
15074
15366
  for (const assetFile of prepared.assetFiles) {
15075
- const assetPath = path22.join(paths.wikiDir, assetFile.relativePath);
15076
- await ensureDir(path22.dirname(assetPath));
15367
+ const assetPath = path23.join(paths.wikiDir, assetFile.relativePath);
15368
+ await ensureDir(path23.dirname(assetPath));
15077
15369
  if (typeof assetFile.content === "string") {
15078
- await fs18.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15370
+ await fs19.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15079
15371
  } else {
15080
- await fs18.writeFile(assetPath, assetFile.content);
15372
+ await fs19.writeFile(assetPath, assetFile.content);
15081
15373
  }
15082
15374
  }
15083
15375
  return { page: prepared.page, savedPath: prepared.savedPath, outputAssets: prepared.outputAssets };
@@ -15098,7 +15390,7 @@ async function prepareExploreHubSave(rootDir, input) {
15098
15390
  confidence: 0.76
15099
15391
  }
15100
15392
  });
15101
- const absolutePath = path22.join(paths.wikiDir, hub.page.path);
15393
+ const absolutePath = path23.join(paths.wikiDir, hub.page.path);
15102
15394
  return {
15103
15395
  page: hub.page,
15104
15396
  savedPath: absolutePath,
@@ -15110,20 +15402,20 @@ async function prepareExploreHubSave(rootDir, input) {
15110
15402
  async function persistExploreHub(rootDir, input) {
15111
15403
  const { paths } = await loadVaultConfig(rootDir);
15112
15404
  const prepared = await prepareExploreHubSave(rootDir, input);
15113
- await ensureDir(path22.dirname(prepared.savedPath));
15114
- await fs18.writeFile(prepared.savedPath, prepared.content, "utf8");
15405
+ await ensureDir(path23.dirname(prepared.savedPath));
15406
+ await fs19.writeFile(prepared.savedPath, prepared.content, "utf8");
15115
15407
  for (const assetFile of prepared.assetFiles) {
15116
- const assetPath = path22.join(paths.wikiDir, assetFile.relativePath);
15117
- await ensureDir(path22.dirname(assetPath));
15408
+ const assetPath = path23.join(paths.wikiDir, assetFile.relativePath);
15409
+ await ensureDir(path23.dirname(assetPath));
15118
15410
  if (typeof assetFile.content === "string") {
15119
- await fs18.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15411
+ await fs19.writeFile(assetPath, assetFile.content, assetFile.encoding ?? "utf8");
15120
15412
  } else {
15121
- await fs18.writeFile(assetPath, assetFile.content);
15413
+ await fs19.writeFile(assetPath, assetFile.content);
15122
15414
  }
15123
15415
  }
15124
15416
  return { page: prepared.page, savedPath: prepared.savedPath, outputAssets: prepared.outputAssets };
15125
15417
  }
15126
- async function stageOutputApprovalBundle(rootDir, stagedPages) {
15418
+ async function stageOutputApprovalBundle(rootDir, stagedPages, options = {}) {
15127
15419
  const { paths } = await loadVaultConfig(rootDir);
15128
15420
  const previousGraph = await readJsonFile(paths.graphPath);
15129
15421
  const changedFiles = stagedPages.flatMap((item) => [
@@ -15134,18 +15426,19 @@ async function stageOutputApprovalBundle(rootDir, stagedPages) {
15134
15426
  binary: typeof assetFile.content !== "string"
15135
15427
  }))
15136
15428
  ]);
15429
+ const labelsByPath = new Map(stagedPages.filter((item) => item.label).map((item) => [item.page.path, item.label]));
15137
15430
  const approvalId = `schedule-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
15138
- const approvalDir = path22.join(paths.approvalsDir, approvalId);
15431
+ const approvalDir = path23.join(paths.approvalsDir, approvalId);
15139
15432
  await ensureDir(approvalDir);
15140
- await ensureDir(path22.join(approvalDir, "wiki"));
15141
- await ensureDir(path22.join(approvalDir, "state"));
15433
+ await ensureDir(path23.join(approvalDir, "wiki"));
15434
+ await ensureDir(path23.join(approvalDir, "state"));
15142
15435
  for (const file of changedFiles) {
15143
- const targetPath = path22.join(approvalDir, "wiki", file.relativePath);
15144
- await ensureDir(path22.dirname(targetPath));
15436
+ const targetPath = path23.join(approvalDir, "wiki", file.relativePath);
15437
+ await ensureDir(path23.dirname(targetPath));
15145
15438
  if ("binary" in file && file.binary) {
15146
- await fs18.writeFile(targetPath, Buffer.from(file.content, "base64"));
15439
+ await fs19.writeFile(targetPath, Buffer.from(file.content, "base64"));
15147
15440
  } else {
15148
- await fs18.writeFile(targetPath, file.content, "utf8");
15441
+ await fs19.writeFile(targetPath, file.content, "utf8");
15149
15442
  }
15150
15443
  }
15151
15444
  const nextPages = sortGraphPages([
@@ -15160,22 +15453,26 @@ async function stageOutputApprovalBundle(rootDir, stagedPages) {
15160
15453
  sources: previousGraph?.sources ?? [],
15161
15454
  pages: nextPages
15162
15455
  };
15163
- 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");
15164
15457
  await writeApprovalManifest(paths, {
15165
15458
  approvalId,
15166
15459
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
15460
+ bundleType: options.bundleType ?? "generated_output",
15461
+ title: options.title,
15462
+ sourceSessionId: options.sourceSessionId,
15167
15463
  entries: await buildApprovalEntries(
15168
15464
  paths,
15169
15465
  stagedPages.map((item) => ({ relativePath: item.page.path, content: item.content })),
15170
15466
  [],
15171
15467
  previousGraph ?? null,
15172
- graph
15468
+ graph,
15469
+ labelsByPath
15173
15470
  )
15174
15471
  });
15175
15472
  return { approvalId, approvalDir };
15176
15473
  }
15177
- async function stageGeneratedOutputPages(rootDir, stagedPages) {
15178
- return await stageOutputApprovalBundle(rootDir, stagedPages);
15474
+ async function stageGeneratedOutputPages(rootDir, stagedPages, options = {}) {
15475
+ return await stageOutputApprovalBundle(rootDir, stagedPages, options);
15179
15476
  }
15180
15477
  async function executeQuery(rootDir, question, format) {
15181
15478
  const { paths } = await loadVaultConfig(rootDir);
@@ -15192,9 +15489,9 @@ async function executeQuery(rootDir, question, format) {
15192
15489
  const searchResults = searchPages(paths.searchDbPath, question, 5);
15193
15490
  const excerpts = await Promise.all(
15194
15491
  searchResults.map(async (result) => {
15195
- const absolutePath = path22.join(paths.wikiDir, result.path);
15492
+ const absolutePath = path23.join(paths.wikiDir, result.path);
15196
15493
  try {
15197
- const content = await fs18.readFile(absolutePath, "utf8");
15494
+ const content = await fs19.readFile(absolutePath, "utf8");
15198
15495
  const parsed = matter9(content);
15199
15496
  return `# ${result.title}
15200
15497
  ${truncate(normalizeWhitespace(parsed.content), 1200)}`;
@@ -15429,7 +15726,7 @@ function computeChangeSummary(current, staged, changeType) {
15429
15726
  async function listApprovals(rootDir) {
15430
15727
  const { paths } = await loadVaultConfig(rootDir);
15431
15728
  const manifests = await Promise.all(
15432
- (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) => {
15433
15730
  try {
15434
15731
  return await readApprovalManifest(paths, entry.name);
15435
15732
  } catch {
@@ -15445,8 +15742,8 @@ async function readApproval(rootDir, approvalId, options) {
15445
15742
  const details = await Promise.all(
15446
15743
  manifest.entries.map(async (entry) => {
15447
15744
  const currentPath = entry.previousPath ?? entry.nextPath;
15448
- const currentContent = currentPath ? await fs18.readFile(path22.join(paths.wikiDir, currentPath), "utf8").catch(() => void 0) : void 0;
15449
- 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;
15450
15747
  const detail = {
15451
15748
  ...entry,
15452
15749
  currentContent,
@@ -15479,26 +15776,26 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15479
15776
  if (!entry.nextPath) {
15480
15777
  throw new Error(`Approval entry ${entry.pageId} is missing a staged path.`);
15481
15778
  }
15482
- const stagedAbsolutePath = path22.join(paths.approvalsDir, approvalId, "wiki", entry.nextPath);
15483
- const stagedContent = await fs18.readFile(stagedAbsolutePath, "utf8");
15484
- const targetAbsolutePath = path22.join(paths.wikiDir, entry.nextPath);
15485
- await ensureDir(path22.dirname(targetAbsolutePath));
15486
- 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");
15487
15784
  if (entry.changeType === "promote" && entry.previousPath) {
15488
- await fs18.rm(path22.join(paths.wikiDir, entry.previousPath), { force: true });
15785
+ await fs19.rm(path23.join(paths.wikiDir, entry.previousPath), { force: true });
15489
15786
  }
15490
15787
  const nextPage = bundleGraph?.pages.find((page) => page.id === entry.pageId && page.path === entry.nextPath) ?? parseStoredPage(entry.nextPath, stagedContent);
15491
15788
  if (nextPage.kind === "output" && nextPage.outputAssets?.length) {
15492
- const outputAssetDir = path22.join(paths.wikiDir, "outputs", "assets", path22.basename(nextPage.path, ".md"));
15493
- 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 });
15494
15791
  for (const asset of nextPage.outputAssets) {
15495
- const stagedAssetPath = path22.join(paths.approvalsDir, approvalId, "wiki", asset.path);
15792
+ const stagedAssetPath = path23.join(paths.approvalsDir, approvalId, "wiki", asset.path);
15496
15793
  if (!await fileExists(stagedAssetPath)) {
15497
15794
  continue;
15498
15795
  }
15499
- const targetAssetPath = path22.join(paths.wikiDir, asset.path);
15500
- await ensureDir(path22.dirname(targetAssetPath));
15501
- 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);
15502
15799
  }
15503
15800
  }
15504
15801
  nextPages = nextPages.filter(
@@ -15509,10 +15806,10 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15509
15806
  } else {
15510
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;
15511
15808
  if (entry.previousPath) {
15512
- await fs18.rm(path22.join(paths.wikiDir, entry.previousPath), { force: true });
15809
+ await fs19.rm(path23.join(paths.wikiDir, entry.previousPath), { force: true });
15513
15810
  }
15514
15811
  if (deletedPage?.kind === "output") {
15515
- 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")), {
15516
15813
  recursive: true,
15517
15814
  force: true
15518
15815
  });
@@ -15535,6 +15832,9 @@ async function acceptApproval(rootDir, approvalId, targets = []) {
15535
15832
  await writeJsonFile(paths.compileStatePath, compileState);
15536
15833
  await refreshIndexesAndSearch(rootDir, nextGraph.pages);
15537
15834
  await writeApprovalManifest(paths, manifest);
15835
+ if (manifest.sourceSessionId) {
15836
+ await updateGuidedSourceSessionStatus(rootDir, manifest.sourceSessionId, "accepted");
15837
+ }
15538
15838
  await recordSession(rootDir, {
15539
15839
  operation: "review",
15540
15840
  title: `Accepted review entries from ${approvalId}`,
@@ -15561,6 +15861,9 @@ async function rejectApproval(rootDir, approvalId, targets = []) {
15561
15861
  entry.status = "rejected";
15562
15862
  }
15563
15863
  await writeApprovalManifest(paths, manifest);
15864
+ if (manifest.sourceSessionId) {
15865
+ await updateGuidedSourceSessionStatus(rootDir, manifest.sourceSessionId, "rejected");
15866
+ }
15564
15867
  await recordSession(rootDir, {
15565
15868
  operation: "review",
15566
15869
  title: `Rejected review entries from ${approvalId}`,
@@ -15603,7 +15906,7 @@ async function promoteCandidate(rootDir, target) {
15603
15906
  const { paths } = await loadVaultConfig(rootDir);
15604
15907
  const graph = await readJsonFile(paths.graphPath);
15605
15908
  const candidate = resolveCandidateTarget(graph?.pages ?? [], target);
15606
- 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");
15607
15910
  const parsed = matter9(raw);
15608
15911
  const nextUpdatedAt = (/* @__PURE__ */ new Date()).toISOString();
15609
15912
  const nextContent = matter9.stringify(parsed.content, {
@@ -15615,10 +15918,10 @@ async function promoteCandidate(rootDir, target) {
15615
15918
  )
15616
15919
  });
15617
15920
  const nextPath = candidateActivePath(candidate);
15618
- const nextAbsolutePath = path22.join(paths.wikiDir, nextPath);
15619
- await ensureDir(path22.dirname(nextAbsolutePath));
15620
- await fs18.writeFile(nextAbsolutePath, nextContent, "utf8");
15621
- 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 });
15622
15925
  const nextPage = parseStoredPage(nextPath, nextContent, { createdAt: candidate.createdAt, updatedAt: nextUpdatedAt });
15623
15926
  const nextPages = sortGraphPages(
15624
15927
  (graph?.pages ?? []).filter((page) => page.id !== candidate.id && page.path !== candidate.path).concat(nextPage)
@@ -15663,7 +15966,7 @@ async function archiveCandidate(rootDir, target) {
15663
15966
  const { paths } = await loadVaultConfig(rootDir);
15664
15967
  const graph = await readJsonFile(paths.graphPath);
15665
15968
  const candidate = resolveCandidateTarget(graph?.pages ?? [], target);
15666
- await fs18.rm(path22.join(paths.wikiDir, candidate.path), { force: true });
15969
+ await fs19.rm(path23.join(paths.wikiDir, candidate.path), { force: true });
15667
15970
  const nextPages = sortGraphPages((graph?.pages ?? []).filter((page) => page.id !== candidate.id && page.path !== candidate.path));
15668
15971
  const nextGraph = {
15669
15972
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -15702,18 +16005,18 @@ async function archiveCandidate(rootDir, target) {
15702
16005
  }
15703
16006
  async function ensureObsidianWorkspace(rootDir) {
15704
16007
  const { config } = await loadVaultConfig(rootDir);
15705
- const obsidianDir = path22.join(rootDir, ".obsidian");
16008
+ const obsidianDir = path23.join(rootDir, ".obsidian");
15706
16009
  const projectIds = projectEntries(config).map((project) => project.id);
15707
16010
  await ensureDir(obsidianDir);
15708
16011
  await Promise.all([
15709
- writeJsonFile(path22.join(obsidianDir, "app.json"), {
16012
+ writeJsonFile(path23.join(obsidianDir, "app.json"), {
15710
16013
  alwaysUpdateLinks: true,
15711
16014
  newFileLocation: "folder",
15712
16015
  newFileFolderPath: "wiki/insights",
15713
16016
  useMarkdownLinks: false,
15714
16017
  attachmentFolderPath: "raw/assets"
15715
16018
  }),
15716
- writeJsonFile(path22.join(obsidianDir, "core-plugins.json"), [
16019
+ writeJsonFile(path23.join(obsidianDir, "core-plugins.json"), [
15717
16020
  "file-explorer",
15718
16021
  "global-search",
15719
16022
  "switcher",
@@ -15723,7 +16026,7 @@ async function ensureObsidianWorkspace(rootDir) {
15723
16026
  "tag-pane",
15724
16027
  "page-preview"
15725
16028
  ]),
15726
- writeJsonFile(path22.join(obsidianDir, "graph.json"), {
16029
+ writeJsonFile(path23.join(obsidianDir, "graph.json"), {
15727
16030
  "collapse-filter": false,
15728
16031
  search: "",
15729
16032
  showTags: true,
@@ -15735,7 +16038,7 @@ async function ensureObsidianWorkspace(rootDir) {
15735
16038
  })),
15736
16039
  localJumps: false
15737
16040
  }),
15738
- writeJsonFile(path22.join(obsidianDir, "workspace.json"), {
16041
+ writeJsonFile(path23.join(obsidianDir, "workspace.json"), {
15739
16042
  active: "root",
15740
16043
  lastOpenFiles: ["wiki/index.md", "wiki/projects/index.md", "wiki/candidates/index.md", "wiki/insights/index.md"],
15741
16044
  left: {
@@ -15748,22 +16051,32 @@ async function ensureObsidianWorkspace(rootDir) {
15748
16051
  ]);
15749
16052
  }
15750
16053
  async function initVault(rootDir, options = {}) {
15751
- const { paths } = await initWorkspace(rootDir);
16054
+ const profile = options.profile ?? "default";
16055
+ const { paths } = await initWorkspace(rootDir, { profile });
15752
16056
  await installConfiguredAgents(rootDir);
15753
- const insightsIndexPath = path22.join(paths.wikiDir, "insights", "index.md");
16057
+ const insightsIndexPath = path23.join(paths.wikiDir, "insights", "index.md");
15754
16058
  const now = (/* @__PURE__ */ new Date()).toISOString();
15755
16059
  await writeFileIfChanged(
15756
16060
  insightsIndexPath,
15757
16061
  matter9.stringify(
15758
- [
16062
+ (profile === "personal-research" ? [
16063
+ "# Insights",
16064
+ "",
16065
+ "Human-authored research notes live here.",
16066
+ "",
16067
+ "- Use this folder for thesis notes, reading reflections, synthesis drafts, and decisions you want to keep explicitly human-authored.",
16068
+ "- Guided sessions can stage `wiki/insights/` updates through the approval queue, but SwarmVault never applies them without review.",
16069
+ "- Treat these pages as the human judgment layer for your vault.",
16070
+ ""
16071
+ ] : [
15759
16072
  "# Insights",
15760
16073
  "",
15761
16074
  "Human-authored notes live here.",
15762
16075
  "",
15763
16076
  "- SwarmVault can read these pages during compile and query.",
15764
- "- 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.",
15765
16078
  ""
15766
- ].join("\n"),
16079
+ ]).join("\n"),
15767
16080
  {
15768
16081
  page_id: "insights:index",
15769
16082
  kind: "index",
@@ -15787,7 +16100,7 @@ async function initVault(rootDir, options = {}) {
15787
16100
  )
15788
16101
  );
15789
16102
  await writeFileIfChanged(
15790
- path22.join(paths.wikiDir, "projects", "index.md"),
16103
+ path23.join(paths.wikiDir, "projects", "index.md"),
15791
16104
  matter9.stringify(["# Projects", "", "- Run `swarmvault compile` to build project rollups.", ""].join("\n"), {
15792
16105
  page_id: "projects:index",
15793
16106
  kind: "index",
@@ -15810,7 +16123,7 @@ async function initVault(rootDir, options = {}) {
15810
16123
  })
15811
16124
  );
15812
16125
  await writeFileIfChanged(
15813
- path22.join(paths.wikiDir, "candidates", "index.md"),
16126
+ path23.join(paths.wikiDir, "candidates", "index.md"),
15814
16127
  matter9.stringify(["# Candidates", "", "- Run `swarmvault compile` to stage candidate pages.", ""].join("\n"), {
15815
16128
  page_id: "candidates:index",
15816
16129
  kind: "index",
@@ -15835,6 +16148,43 @@ async function initVault(rootDir, options = {}) {
15835
16148
  if (options.obsidian) {
15836
16149
  await ensureObsidianWorkspace(rootDir);
15837
16150
  }
16151
+ if (profile === "personal-research") {
16152
+ await writeFileIfChanged(
16153
+ path23.join(paths.wikiDir, "insights", "research-playbook.md"),
16154
+ matter9.stringify(
16155
+ [
16156
+ "# Personal Research Playbook",
16157
+ "",
16158
+ "- Add one source at a time with `swarmvault ingest <input> --guide` or `swarmvault source add <input> --guide`.",
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.",
16161
+ "- Keep unresolved questions visible in `wiki/dashboards/open-questions.md`.",
16162
+ "- Use `swarmvault review list` and `swarmvault review show --diff` to decide what becomes canonical.",
16163
+ ""
16164
+ ].join("\n"),
16165
+ {
16166
+ page_id: "insights:research-playbook",
16167
+ kind: "insight",
16168
+ title: "Personal Research Playbook",
16169
+ tags: ["insight", "research", "playbook"],
16170
+ source_ids: [],
16171
+ project_ids: [],
16172
+ node_ids: [],
16173
+ freshness: "fresh",
16174
+ status: "active",
16175
+ confidence: 1,
16176
+ created_at: now,
16177
+ updated_at: now,
16178
+ compiled_from: [],
16179
+ managed_by: "human",
16180
+ backlinks: [],
16181
+ schema_hash: "",
16182
+ source_hashes: {},
16183
+ source_semantic_hashes: {}
16184
+ }
16185
+ )
16186
+ );
16187
+ }
15838
16188
  }
15839
16189
  async function runConfiguredBenchmark(rootDir, config) {
15840
16190
  if (config.benchmark?.enabled === false) {
@@ -15950,7 +16300,7 @@ async function compileVault(rootDir, options = {}) {
15950
16300
  ),
15951
16301
  Promise.all(
15952
16302
  clean.map(async (manifest) => {
15953
- const cached = await readJsonFile(path22.join(paths.analysesDir, `${manifest.sourceId}.json`));
16303
+ const cached = await readJsonFile(path23.join(paths.analysesDir, `${manifest.sourceId}.json`));
15954
16304
  if (cached) {
15955
16305
  analysisProgress.tick(manifest.title);
15956
16306
  return cached;
@@ -15978,22 +16328,22 @@ async function compileVault(rootDir, options = {}) {
15978
16328
  }
15979
16329
  const enriched = enrichResolvedCodeImports(manifest, analysis, codeIndex);
15980
16330
  if (analysisSignature(enriched) !== analysisSignature(analysis)) {
15981
- await writeJsonFile(path22.join(paths.analysesDir, `${analysis.sourceId}.json`), enriched);
16331
+ await writeJsonFile(path23.join(paths.analysesDir, `${analysis.sourceId}.json`), enriched);
15982
16332
  }
15983
16333
  return enriched;
15984
16334
  })
15985
16335
  );
15986
16336
  await Promise.all([
15987
- ensureDir(path22.join(paths.wikiDir, "sources")),
15988
- ensureDir(path22.join(paths.wikiDir, "code")),
15989
- ensureDir(path22.join(paths.wikiDir, "concepts")),
15990
- ensureDir(path22.join(paths.wikiDir, "entities")),
15991
- ensureDir(path22.join(paths.wikiDir, "outputs")),
15992
- ensureDir(path22.join(paths.wikiDir, "projects")),
15993
- ensureDir(path22.join(paths.wikiDir, "insights")),
15994
- ensureDir(path22.join(paths.wikiDir, "candidates")),
15995
- ensureDir(path22.join(paths.wikiDir, "candidates", "concepts")),
15996
- 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"))
15997
16347
  ]);
15998
16348
  const sync = await syncVaultArtifacts(rootDir, {
15999
16349
  schemas,
@@ -16140,7 +16490,7 @@ async function queryVault(rootDir, options) {
16140
16490
  assetFiles: staged.assetFiles
16141
16491
  }
16142
16492
  ]);
16143
- stagedPath = path22.join(approval.approvalDir, "wiki", staged.page.path);
16493
+ stagedPath = path23.join(approval.approvalDir, "wiki", staged.page.path);
16144
16494
  savedPageId = staged.page.id;
16145
16495
  approvalId = approval.approvalId;
16146
16496
  approvalDir = approval.approvalDir;
@@ -16396,9 +16746,9 @@ ${orchestrationNotes.join("\n")}
16396
16746
  approvalId = approval.approvalId;
16397
16747
  approvalDir = approval.approvalDir;
16398
16748
  stepResults.forEach((result, index) => {
16399
- result.stagedPath = path22.join(approval.approvalDir, "wiki", stagedStepPages[index]?.page.path ?? "");
16749
+ result.stagedPath = path23.join(approval.approvalDir, "wiki", stagedStepPages[index]?.page.path ?? "");
16400
16750
  });
16401
- stagedHubPath = path22.join(approval.approvalDir, "wiki", hubPage.path);
16751
+ stagedHubPath = path23.join(approval.approvalDir, "wiki", hubPage.path);
16402
16752
  } else {
16403
16753
  await refreshVaultAfterOutputSave(rootDir);
16404
16754
  }
@@ -16485,11 +16835,11 @@ async function benchmarkVault(rootDir, options = {}) {
16485
16835
  }
16486
16836
  }
16487
16837
  for (const page of graph.pages) {
16488
- const absolutePath = path22.join(paths.wikiDir, page.path);
16838
+ const absolutePath = path23.join(paths.wikiDir, page.path);
16489
16839
  if (!await fileExists(absolutePath)) {
16490
16840
  continue;
16491
16841
  }
16492
- const parsed = matter9(await fs18.readFile(absolutePath, "utf8"));
16842
+ const parsed = matter9(await fs19.readFile(absolutePath, "utf8"));
16493
16843
  pageContentsById.set(page.id, parsed.content);
16494
16844
  }
16495
16845
  const configuredQuestions = (config.benchmark?.questions ?? []).map((question) => normalizeWhitespace(question)).filter(Boolean);
@@ -16544,7 +16894,7 @@ async function listGraphHyperedges(rootDir, target, limit = 25) {
16544
16894
  }
16545
16895
  async function readGraphReport(rootDir) {
16546
16896
  const { paths } = await loadVaultConfig(rootDir);
16547
- return readJsonFile(path22.join(paths.wikiDir, "graph", "report.json"));
16897
+ return readJsonFile(path23.join(paths.wikiDir, "graph", "report.json"));
16548
16898
  }
16549
16899
  async function listGodNodes(rootDir, limit = 10) {
16550
16900
  const graph = await ensureCompiledGraph(rootDir);
@@ -16557,15 +16907,15 @@ async function listPages(rootDir) {
16557
16907
  }
16558
16908
  async function readPage(rootDir, relativePath) {
16559
16909
  const { paths } = await loadVaultConfig(rootDir);
16560
- const absolutePath = path22.resolve(paths.wikiDir, relativePath);
16910
+ const absolutePath = path23.resolve(paths.wikiDir, relativePath);
16561
16911
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
16562
16912
  return null;
16563
16913
  }
16564
- const raw = await fs18.readFile(absolutePath, "utf8");
16914
+ const raw = await fs19.readFile(absolutePath, "utf8");
16565
16915
  const parsed = matter9(raw);
16566
16916
  return {
16567
16917
  path: relativePath,
16568
- 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)),
16569
16919
  frontmatter: parsed.data,
16570
16920
  content: parsed.content
16571
16921
  };
@@ -16601,7 +16951,7 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16601
16951
  severity: "warning",
16602
16952
  code: "stale_page",
16603
16953
  message: `Page ${page.title} is stale because the vault schema changed.`,
16604
- pagePath: path22.join(paths.wikiDir, page.path),
16954
+ pagePath: path23.join(paths.wikiDir, page.path),
16605
16955
  relatedPageIds: [page.id]
16606
16956
  });
16607
16957
  }
@@ -16614,7 +16964,7 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16614
16964
  severity: "warning",
16615
16965
  code: "stale_page",
16616
16966
  message: `Page ${page.title} is stale because source ${sourceId} changed.`,
16617
- pagePath: path22.join(paths.wikiDir, page.path),
16967
+ pagePath: path23.join(paths.wikiDir, page.path),
16618
16968
  relatedSourceIds: [sourceId],
16619
16969
  relatedPageIds: [page.id]
16620
16970
  });
@@ -16625,13 +16975,13 @@ function structuralLintFindings(_rootDir, paths, graph, schemas, manifests, sour
16625
16975
  severity: "info",
16626
16976
  code: "orphan_page",
16627
16977
  message: `Page ${page.title} has no backlinks.`,
16628
- pagePath: path22.join(paths.wikiDir, page.path),
16978
+ pagePath: path23.join(paths.wikiDir, page.path),
16629
16979
  relatedPageIds: [page.id]
16630
16980
  });
16631
16981
  }
16632
- const absolutePath = path22.join(paths.wikiDir, page.path);
16982
+ const absolutePath = path23.join(paths.wikiDir, page.path);
16633
16983
  if (await fileExists(absolutePath)) {
16634
- const content = await fs18.readFile(absolutePath, "utf8");
16984
+ const content = await fs19.readFile(absolutePath, "utf8");
16635
16985
  if (content.includes("## Claims")) {
16636
16986
  const uncited = content.split("\n").filter((line) => line.startsWith("- ") && !line.includes("[source:"));
16637
16987
  if (uncited.length) {
@@ -16748,7 +17098,7 @@ async function bootstrapDemo(rootDir, input) {
16748
17098
  }
16749
17099
 
16750
17100
  // src/mcp.ts
16751
- var SERVER_VERSION = "0.4.0";
17101
+ var SERVER_VERSION = "0.6.0";
16752
17102
  async function createMcpServer(rootDir) {
16753
17103
  const server = new McpServer({
16754
17104
  name: "swarmvault",
@@ -17019,7 +17369,7 @@ async function createMcpServer(rootDir) {
17019
17369
  },
17020
17370
  async () => {
17021
17371
  const { paths } = await loadVaultConfig(rootDir);
17022
- 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();
17023
17373
  return asTextResource("swarmvault://sessions", JSON.stringify(files, null, 2));
17024
17374
  }
17025
17375
  );
@@ -17052,8 +17402,8 @@ async function createMcpServer(rootDir) {
17052
17402
  return asTextResource(`swarmvault://pages/${encodedPath}`, `Page not found: ${relativePath}`);
17053
17403
  }
17054
17404
  const { paths } = await loadVaultConfig(rootDir);
17055
- const absolutePath = path23.resolve(paths.wikiDir, relativePath);
17056
- 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"));
17057
17407
  }
17058
17408
  );
17059
17409
  server.registerResource(
@@ -17061,11 +17411,11 @@ async function createMcpServer(rootDir) {
17061
17411
  new ResourceTemplate("swarmvault://sessions/{path}", {
17062
17412
  list: async () => {
17063
17413
  const { paths } = await loadVaultConfig(rootDir);
17064
- 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();
17065
17415
  return {
17066
17416
  resources: files.map((relativePath) => ({
17067
17417
  uri: `swarmvault://sessions/${encodeURIComponent(relativePath)}`,
17068
- name: path23.basename(relativePath, ".md"),
17418
+ name: path24.basename(relativePath, ".md"),
17069
17419
  title: relativePath,
17070
17420
  description: "SwarmVault session artifact",
17071
17421
  mimeType: "text/markdown"
@@ -17082,11 +17432,11 @@ async function createMcpServer(rootDir) {
17082
17432
  const { paths } = await loadVaultConfig(rootDir);
17083
17433
  const encodedPath = typeof variables.path === "string" ? variables.path : "";
17084
17434
  const relativePath = decodeURIComponent(encodedPath);
17085
- const absolutePath = path23.resolve(paths.sessionsDir, relativePath);
17435
+ const absolutePath = path24.resolve(paths.sessionsDir, relativePath);
17086
17436
  if (!absolutePath.startsWith(paths.sessionsDir) || !await fileExists(absolutePath)) {
17087
17437
  return asTextResource(`swarmvault://sessions/${encodedPath}`, `Session not found: ${relativePath}`);
17088
17438
  }
17089
- return asTextResource(`swarmvault://sessions/${encodedPath}`, await fs19.readFile(absolutePath, "utf8"));
17439
+ return asTextResource(`swarmvault://sessions/${encodedPath}`, await fs20.readFile(absolutePath, "utf8"));
17090
17440
  }
17091
17441
  );
17092
17442
  return server;
@@ -17134,13 +17484,13 @@ function asTextResource(uri, text) {
17134
17484
  }
17135
17485
 
17136
17486
  // src/schedule.ts
17137
- import fs20 from "fs/promises";
17138
- import path24 from "path";
17487
+ import fs21 from "fs/promises";
17488
+ import path25 from "path";
17139
17489
  function scheduleStatePath(schedulesDir, jobId) {
17140
- return path24.join(schedulesDir, `${encodeURIComponent(jobId)}.json`);
17490
+ return path25.join(schedulesDir, `${encodeURIComponent(jobId)}.json`);
17141
17491
  }
17142
17492
  function scheduleLockPath(schedulesDir, jobId) {
17143
- return path24.join(schedulesDir, `${encodeURIComponent(jobId)}.lock`);
17493
+ return path25.join(schedulesDir, `${encodeURIComponent(jobId)}.lock`);
17144
17494
  }
17145
17495
  function parseEveryDuration(value) {
17146
17496
  const match = value.trim().match(/^(\d+)(m|h|d)$/i);
@@ -17243,13 +17593,13 @@ async function acquireJobLease(rootDir, jobId) {
17243
17593
  const { paths } = await loadVaultConfig(rootDir);
17244
17594
  const leasePath = scheduleLockPath(paths.schedulesDir, jobId);
17245
17595
  await ensureDir(paths.schedulesDir);
17246
- const handle = await fs20.open(leasePath, "wx");
17596
+ const handle = await fs21.open(leasePath, "wx");
17247
17597
  await handle.writeFile(`${process.pid}
17248
17598
  ${(/* @__PURE__ */ new Date()).toISOString()}
17249
17599
  `);
17250
17600
  await handle.close();
17251
17601
  return async () => {
17252
- await fs20.rm(leasePath, { force: true });
17602
+ await fs21.rm(leasePath, { force: true });
17253
17603
  };
17254
17604
  }
17255
17605
  async function listSchedules(rootDir) {
@@ -17397,8 +17747,9 @@ async function serveSchedules(rootDir, pollMs = 3e4) {
17397
17747
 
17398
17748
  // src/sources.ts
17399
17749
  import { spawn as spawn2 } from "child_process";
17400
- import fs21 from "fs/promises";
17401
- import path25 from "path";
17750
+ import fs22 from "fs/promises";
17751
+ import path26 from "path";
17752
+ import matter10 from "gray-matter";
17402
17753
  import { JSDOM as JSDOM3 } from "jsdom";
17403
17754
  var DEFAULT_CRAWL_MAX_PAGES = 12;
17404
17755
  var DEFAULT_CRAWL_MAX_DEPTH = 2;
@@ -17425,24 +17776,24 @@ function normalizeManagedStatus(value) {
17425
17776
  return value === "missing" || value === "error" ? value : "ready";
17426
17777
  }
17427
17778
  function withinRoot2(rootPath, targetPath) {
17428
- const relative = path25.relative(rootPath, targetPath);
17429
- return relative === "" || !relative.startsWith("..") && !path25.isAbsolute(relative);
17779
+ const relative = path26.relative(rootPath, targetPath);
17780
+ return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
17430
17781
  }
17431
17782
  async function findNearestGitRoot3(startPath) {
17432
- let current = path25.resolve(startPath);
17783
+ let current = path26.resolve(startPath);
17433
17784
  try {
17434
- const stat = await fs21.stat(current);
17785
+ const stat = await fs22.stat(current);
17435
17786
  if (!stat.isDirectory()) {
17436
- current = path25.dirname(current);
17787
+ current = path26.dirname(current);
17437
17788
  }
17438
17789
  } catch {
17439
- current = path25.dirname(current);
17790
+ current = path26.dirname(current);
17440
17791
  }
17441
17792
  while (true) {
17442
- if (await fileExists(path25.join(current, ".git"))) {
17793
+ if (await fileExists(path26.join(current, ".git"))) {
17443
17794
  return current;
17444
17795
  }
17445
- const parent = path25.dirname(current);
17796
+ const parent = path26.dirname(current);
17446
17797
  if (parent === current) {
17447
17798
  return null;
17448
17799
  }
@@ -17516,7 +17867,7 @@ function isAllowedDocsCandidate(candidate, startUrl) {
17516
17867
  if (candidate.origin !== startUrl.origin) {
17517
17868
  return false;
17518
17869
  }
17519
- const extension = path25.extname(candidate.pathname).toLowerCase();
17870
+ const extension = path26.extname(candidate.pathname).toLowerCase();
17520
17871
  if (extension && extension !== ".html" && extension !== ".htm" && extension !== ".md") {
17521
17872
  return false;
17522
17873
  }
@@ -17605,14 +17956,14 @@ function matchesManagedSourceSpec(existing, input) {
17605
17956
  return false;
17606
17957
  }
17607
17958
  if (input.kind === "directory" || input.kind === "file") {
17608
- return path25.resolve(existing.path ?? "") === path25.resolve(input.path);
17959
+ return path26.resolve(existing.path ?? "") === path26.resolve(input.path);
17609
17960
  }
17610
17961
  return (existing.url ?? "") === input.url;
17611
17962
  }
17612
17963
  async function resolveManagedSourceInput(rootDir, input) {
17613
- const absoluteInput = path25.resolve(rootDir, input);
17964
+ const absoluteInput = path26.resolve(rootDir, input);
17614
17965
  if (!(input.startsWith("http://") || input.startsWith("https://"))) {
17615
- const stat = await fs21.stat(absoluteInput).catch(() => null);
17966
+ const stat = await fs22.stat(absoluteInput).catch(() => null);
17616
17967
  if (!stat) {
17617
17968
  throw new Error(`Source not found: ${input}`);
17618
17969
  }
@@ -17620,7 +17971,7 @@ async function resolveManagedSourceInput(rootDir, input) {
17620
17971
  return {
17621
17972
  kind: "file",
17622
17973
  path: absoluteInput,
17623
- title: path25.basename(absoluteInput, path25.extname(absoluteInput)) || absoluteInput
17974
+ title: path26.basename(absoluteInput, path26.extname(absoluteInput)) || absoluteInput
17624
17975
  };
17625
17976
  }
17626
17977
  if (!stat.isDirectory()) {
@@ -17632,7 +17983,7 @@ async function resolveManagedSourceInput(rootDir, input) {
17632
17983
  kind: "directory",
17633
17984
  path: absoluteInput,
17634
17985
  repoRoot,
17635
- title: path25.basename(absoluteInput) || absoluteInput
17986
+ title: path26.basename(absoluteInput) || absoluteInput
17636
17987
  };
17637
17988
  }
17638
17989
  const github = normalizeGitHubRepoRootUrl(input);
@@ -17655,16 +18006,16 @@ async function resolveManagedSourceInput(rootDir, input) {
17655
18006
  };
17656
18007
  }
17657
18008
  function directorySourceIdsFor(manifests, inputPath) {
17658
- 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));
17659
18010
  }
17660
18011
  function fileSourceIdsFor(manifests, inputPath) {
17661
- const absoluteInput = path25.resolve(inputPath);
17662
- 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));
17663
18014
  }
17664
18015
  async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17665
18016
  const manifestsBefore = await listManifests(rootDir);
17666
18017
  const previousInScope = manifestsBefore.filter(
17667
- (manifest) => manifest.originalPath && withinRoot2(path25.resolve(inputPath), path25.resolve(manifest.originalPath))
18018
+ (manifest) => manifest.originalPath && withinRoot2(path26.resolve(inputPath), path26.resolve(manifest.originalPath))
17668
18019
  );
17669
18020
  const result = await ingestDirectory(rootDir, inputPath, { repoRoot });
17670
18021
  const removed = [];
@@ -17672,7 +18023,7 @@ async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17672
18023
  if (!manifest.originalPath) {
17673
18024
  continue;
17674
18025
  }
17675
- if (await fileExists(path25.resolve(manifest.originalPath))) {
18026
+ if (await fileExists(path26.resolve(manifest.originalPath))) {
17676
18027
  continue;
17677
18028
  }
17678
18029
  const removedManifest = await removeManifestBySourceId(rootDir, manifest.sourceId);
@@ -17682,7 +18033,7 @@ async function syncDirectorySource(rootDir, inputPath, repoRoot) {
17682
18033
  }
17683
18034
  const manifestsAfter = await listManifests(rootDir);
17684
18035
  return {
17685
- title: path25.basename(inputPath) || inputPath,
18036
+ title: path26.basename(inputPath) || inputPath,
17686
18037
  sourceIds: directorySourceIdsFor(manifestsAfter, inputPath),
17687
18038
  counts: {
17688
18039
  scannedCount: result.scannedCount,
@@ -17698,7 +18049,7 @@ async function syncFileSource(rootDir, inputPath) {
17698
18049
  const result = await ingestInputDetailed(rootDir, inputPath);
17699
18050
  const manifestsAfter = await listManifests(rootDir);
17700
18051
  return {
17701
- title: path25.basename(inputPath, path25.extname(inputPath)) || inputPath,
18052
+ title: path26.basename(inputPath, path26.extname(inputPath)) || inputPath,
17702
18053
  sourceIds: fileSourceIdsFor(manifestsAfter, inputPath),
17703
18054
  counts: {
17704
18055
  scannedCount: result.scannedCount,
@@ -17732,8 +18083,8 @@ async function runGitCommand(cwd, args) {
17732
18083
  }
17733
18084
  async function syncGitHubRepoSource(rootDir, entry) {
17734
18085
  const workingDir = await managedSourceWorkingDir(rootDir, entry.id);
17735
- const checkoutDir = path25.join(workingDir, "checkout");
17736
- await fs21.rm(checkoutDir, { recursive: true, force: true });
18086
+ const checkoutDir = path26.join(workingDir, "checkout");
18087
+ await fs22.rm(checkoutDir, { recursive: true, force: true });
17737
18088
  await ensureDir(workingDir);
17738
18089
  if (!entry.url) {
17739
18090
  throw new Error(`Managed source ${entry.id} is missing its repository URL.`);
@@ -17860,7 +18211,7 @@ function scopedNodeIds(graph, sourceIds) {
17860
18211
  async function loadSourceAnalyses(rootDir, sourceIds) {
17861
18212
  const { paths } = await loadVaultConfig(rootDir);
17862
18213
  const analyses = await Promise.all(
17863
- 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`)))
17864
18215
  );
17865
18216
  return analyses.filter((analysis) => Boolean(analysis?.sourceId));
17866
18217
  }
@@ -17927,7 +18278,7 @@ function renderDeterministicSourceBrief(input) {
17927
18278
  ""
17928
18279
  ].join("\n");
17929
18280
  }
17930
- async function generateSourceBriefMarkdown(rootDir, source) {
18281
+ async function generateSourceBriefMarkdownForScope(rootDir, source) {
17931
18282
  const { paths } = await loadVaultConfig(rootDir);
17932
18283
  const graph = await readJsonFile(paths.graphPath);
17933
18284
  if (!graph) {
@@ -17964,7 +18315,7 @@ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}
17964
18315
  ),
17965
18316
  prompt: [
17966
18317
  `Source title: ${source.title}`,
17967
- `Source kind: ${source.kind}`,
18318
+ `Source kind: ${source.kind ?? "source"}`,
17968
18319
  `Tracked source ids: ${source.sourceIds.join(", ") || "none"}`,
17969
18320
  "",
17970
18321
  "Pages:",
@@ -17982,12 +18333,12 @@ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}
17982
18333
  return fallback;
17983
18334
  }
17984
18335
  }
17985
- async function writeSourceBrief(rootDir, source) {
18336
+ async function writeSourceBriefForScope(rootDir, source) {
17986
18337
  if (!source.sourceIds.length) {
17987
18338
  return null;
17988
18339
  }
17989
18340
  const { paths } = await loadVaultConfig(rootDir);
17990
- const markdown = await generateSourceBriefMarkdown(rootDir, source);
18341
+ const markdown = await generateSourceBriefMarkdownForScope(rootDir, source);
17991
18342
  if (!markdown) {
17992
18343
  return null;
17993
18344
  }
@@ -18020,11 +18371,14 @@ async function writeSourceBrief(rootDir, source) {
18020
18371
  confidence: 0.82
18021
18372
  }
18022
18373
  });
18023
- const absolutePath = path25.join(paths.wikiDir, output.page.path);
18024
- await ensureDir(path25.dirname(absolutePath));
18025
- 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");
18026
18377
  return absolutePath;
18027
18378
  }
18379
+ async function writeSourceBrief(rootDir, source) {
18380
+ return await writeSourceBriefForScope(rootDir, scopeFromManagedSource(source));
18381
+ }
18028
18382
  async function generateBriefsForSources(rootDir, sources) {
18029
18383
  const briefPaths = /* @__PURE__ */ new Map();
18030
18384
  for (const source of sources) {
@@ -18038,6 +18392,59 @@ async function generateBriefsForSources(rootDir, sources) {
18038
18392
  }
18039
18393
  return briefPaths;
18040
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
+ }
18041
18448
  function renderDeterministicSourceReview(input) {
18042
18449
  const canonicalPages = input.sourcePages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 10);
18043
18450
  const modulePages = input.sourcePages.filter((page) => page.kind === "module").slice(0, 8);
@@ -18137,7 +18544,7 @@ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}
18137
18544
  return fallback;
18138
18545
  }
18139
18546
  }
18140
- async function stageSourceReviewForScope(rootDir, scope) {
18547
+ async function buildSourceReviewStagedPage(rootDir, scope) {
18141
18548
  const { paths } = await loadVaultConfig(rootDir);
18142
18549
  const markdown = await generateSourceReviewMarkdown(rootDir, scope);
18143
18550
  if (!markdown) {
@@ -18172,44 +18579,671 @@ async function stageSourceReviewForScope(rootDir, scope) {
18172
18579
  confidence: 0.79
18173
18580
  }
18174
18581
  });
18175
- const approval = await stageGeneratedOutputPages(rootDir, [{ page: output.page, content: output.content }]);
18176
- return {
18177
- sourceId: scope.id,
18178
- pageId: output.page.id,
18179
- reviewPath: path25.join(approval.approvalDir, "wiki", output.page.path),
18180
- staged: true,
18181
- approvalId: approval.approvalId,
18182
- approvalDir: approval.approvalDir
18183
- };
18582
+ return { page: output.page, content: output.content };
18583
+ }
18584
+ function classifySourceGuidePageBuckets(sourcePages, scopeSourceIds) {
18585
+ const scopeSet = new Set(scopeSourceIds);
18586
+ const canonicalPages = sourcePages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 12);
18587
+ const newPages = canonicalPages.filter((page) => page.sourceIds.every((sourceId) => scopeSet.has(sourceId))).slice(0, 6);
18588
+ const reinforcingPages = canonicalPages.filter((page) => page.sourceIds.some((sourceId) => !scopeSet.has(sourceId))).slice(0, 6);
18589
+ return { canonicalPages, newPages, reinforcingPages };
18590
+ }
18591
+ function findContradictionsForScope(scope, report) {
18592
+ return report?.contradictions.filter(
18593
+ (contradiction) => scope.sourceIds.includes(contradiction.sourceIdA) || scope.sourceIds.includes(contradiction.sourceIdB)
18594
+ ) ?? [];
18184
18595
  }
18185
- function scopeFromManagedSource(source) {
18186
- return {
18187
- id: source.id,
18188
- title: source.title,
18189
- sourceIds: source.sourceIds
18190
- };
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);
18191
18610
  }
18192
- async function reviewSourceScope(rootDir, scope) {
18193
- return await stageSourceReviewForScope(rootDir, scope);
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`;
18194
18623
  }
18195
- async function reviewManagedSource(rootDir, id) {
18196
- const managedSources = await loadManagedSources(rootDir);
18197
- const managedSource = managedSources.find((source) => source.id === id);
18198
- if (managedSource) {
18199
- if (!await loadVaultConfig(rootDir).then(({ paths }) => fileExists(paths.graphPath))) {
18200
- await compileVault(rootDir, {});
18201
- }
18202
- return await stageSourceReviewForScope(rootDir, scopeFromManagedSource(managedSource));
18624
+ function insightTitleForTarget(page, scope) {
18625
+ if (page.kind === "concept" || page.kind === "entity") {
18626
+ return page.title;
18203
18627
  }
18204
- const manifest = (await listManifests(rootDir)).find((candidate) => candidate.sourceId === id);
18205
- if (!manifest) {
18206
- throw new Error(`Managed source or source id not found: ${id}`);
18628
+ if (page.kind === "source") {
18629
+ return `Source Notes: ${page.title}`;
18207
18630
  }
18208
- return await stageSourceReviewForScope(rootDir, {
18209
- id: manifest.sourceId,
18210
- title: manifest.title,
18211
- sourceIds: [manifest.sourceId]
18212
- });
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
+ }
18660
+ function renderDeterministicSourceGuide(input) {
18661
+ const { canonicalPages, newPages, reinforcingPages } = classifySourceGuidePageBuckets(input.sourcePages, input.scope.sourceIds);
18662
+ const modulePages = input.sourcePages.filter((page) => page.kind === "module").slice(0, 6);
18663
+ const takeaways = uniqueStrings4(
18664
+ input.analyses.flatMap((analysis) => [
18665
+ analysis.summary,
18666
+ ...analysis.concepts.map((concept) => concept.description),
18667
+ ...analysis.entities.map((entity) => entity.description)
18668
+ ]).filter(Boolean).map((value) => normalizeWhitespace(value))
18669
+ ).slice(0, 7).map((value) => truncate(value, 180));
18670
+ const questions = uniqueStrings4(input.analyses.flatMap((analysis) => analysis.questions)).slice(0, 6);
18671
+ const contradictions = input.report?.contradictions.filter(
18672
+ (contradiction) => input.scope.sourceIds.includes(contradiction.sourceIdA) || input.scope.sourceIds.includes(contradiction.sourceIdB)
18673
+ ) ?? [];
18674
+ return [
18675
+ `# Source Guide: ${input.scope.title}`,
18676
+ "",
18677
+ "## What This Source Is",
18678
+ "",
18679
+ takeaways.length ? takeaways[0] : `${input.scope.title} has been compiled into the vault and is ready for guided review.`,
18680
+ "",
18681
+ "## Key Takeaways",
18682
+ "",
18683
+ ...takeaways.length ? takeaways.map((takeaway) => `- ${takeaway}`) : ["- No takeaways are available until the source is compiled."],
18684
+ "",
18685
+ "## Proposed Canonical Pages To Update",
18686
+ "",
18687
+ ...canonicalPages.length ? canonicalPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No likely canonical pages were identified yet."],
18688
+ "",
18689
+ "## New, Reinforcing, And Conflicting Claims",
18690
+ "",
18691
+ ...newPages.length ? ["New or source-local pages:", ...newPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`), ""] : [],
18692
+ ...reinforcingPages.length ? ["Reinforcing existing pages:", ...reinforcingPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`), ""] : [],
18693
+ ...contradictions.length ? ["Conflicts to judge:", ...contradictions.map((contradiction) => `- ${contradiction.claimA} / ${contradiction.claimB}`), ""] : ["Conflicts to judge:", "- No contradictions are currently flagged for this source scope.", ""],
18694
+ "## What Should Probably Stay Out For Now",
18695
+ "",
18696
+ ...modulePages.length ? ["- Avoid promoting narrow implementation details unless they matter to your thesis or recurring questions."] : ["- Avoid promoting incidental details that are not yet supported by multiple sources or clear research goals."],
18697
+ ...contradictions.length ? ["- Keep contested claims provisional until you review the conflicting evidence side by side."] : [],
18698
+ "",
18699
+ "## Needs Human Judgment",
18700
+ "",
18701
+ ...questions.length ? questions.map((question) => `- ${question}`) : ["- Decide which proposed canonical pages deserve durable summary updates."],
18702
+ "",
18703
+ "## Suggested Follow-up Questions",
18704
+ "",
18705
+ ...questions.length ? questions.map((question) => `- ${question}`) : ["- What changed in your understanding after reading this source?"],
18706
+ ""
18707
+ ].join("\n");
18708
+ }
18709
+ async function generateSourceGuideMarkdown(rootDir, scope) {
18710
+ const { paths } = await loadVaultConfig(rootDir);
18711
+ let graph = await readJsonFile(paths.graphPath);
18712
+ if (!graph) {
18713
+ await compileVault(rootDir, {});
18714
+ graph = await readJsonFile(paths.graphPath);
18715
+ }
18716
+ if (!graph) {
18717
+ return null;
18718
+ }
18719
+ const sourcePages = scopedSourcePages(graph, scope.sourceIds);
18720
+ const analyses = await loadSourceAnalyses(rootDir, scope.sourceIds);
18721
+ const report = await readGraphReport(rootDir);
18722
+ const fallback = renderDeterministicSourceGuide({
18723
+ scope,
18724
+ sourcePages,
18725
+ analyses,
18726
+ report
18727
+ });
18728
+ const provider = await getProviderForTask(rootDir, "queryProvider");
18729
+ if (provider.type === "heuristic") {
18730
+ return fallback;
18731
+ }
18732
+ try {
18733
+ const schemas = await loadVaultSchemas(rootDir);
18734
+ const { canonicalPages, newPages, reinforcingPages } = classifySourceGuidePageBuckets(sourcePages, scope.sourceIds);
18735
+ const pageContext = sourcePages.slice(0, 12).map((page) => `- ${page.title} (${page.kind}) -> ${page.path}`).join("\n");
18736
+ const analysisContext = analyses.slice(0, 8).map(
18737
+ (analysis) => `# ${analysis.title}
18738
+ Summary: ${analysis.summary}
18739
+ Questions: ${analysis.questions.join(" | ") || "none"}
18740
+ Concepts: ${analysis.concepts.map((concept) => concept.name).join(", ") || "none"}
18741
+ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}`
18742
+ ).join("\n\n---\n\n");
18743
+ const response = await provider.generateText({
18744
+ system: buildSchemaPrompt(
18745
+ schemas.effective.global,
18746
+ "Write a concise markdown source guide with sections: What This Source Is, Key Takeaways, Proposed Canonical Pages To Update, New Reinforcing And Conflicting Claims, What Should Probably Stay Out For Now, Needs Human Judgment, Suggested Follow-up Questions. Focus on helping a human integrate one source into an evolving research wiki."
18747
+ ),
18748
+ prompt: [
18749
+ `Source scope: ${scope.title}`,
18750
+ `Scope id: ${scope.id}`,
18751
+ `Tracked source ids: ${scope.sourceIds.join(", ") || "none"}`,
18752
+ `Current brief path: ${scope.briefPath ?? "none"}`,
18753
+ "",
18754
+ "Likely canonical pages:",
18755
+ canonicalPages.length ? canonicalPages.map((page) => `- ${page.title} -> ${page.path}`).join("\n") : "- none",
18756
+ "",
18757
+ "Likely source-local pages:",
18758
+ newPages.length ? newPages.map((page) => `- ${page.title} -> ${page.path}`).join("\n") : "- none",
18759
+ "",
18760
+ "Likely reinforcing pages:",
18761
+ reinforcingPages.length ? reinforcingPages.map((page) => `- ${page.title} -> ${page.path}`).join("\n") : "- none",
18762
+ "",
18763
+ "Pages:",
18764
+ pageContext || "- none",
18765
+ "",
18766
+ "Analyses:",
18767
+ analysisContext || "No analysis context available.",
18768
+ "",
18769
+ "Deterministic fallback draft:",
18770
+ fallback
18771
+ ].join("\n")
18772
+ });
18773
+ return response.text?.trim() ? response.text.trim() : fallback;
18774
+ } catch {
18775
+ return fallback;
18776
+ }
18777
+ }
18778
+ async function buildSourceGuideStagedPage(rootDir, scope) {
18779
+ const { paths } = await loadVaultConfig(rootDir);
18780
+ const markdown = await generateSourceGuideMarkdown(rootDir, scope);
18781
+ if (!markdown) {
18782
+ throw new Error(`Could not generate a source guide for ${scope.id}.`);
18783
+ }
18784
+ const graph = await readJsonFile(paths.graphPath);
18785
+ const relatedPages = graph ? scopedSourcePages(graph, scope.sourceIds) : [];
18786
+ const relatedPageIds = relatedPages.slice(0, 18).map((page) => page.id);
18787
+ const relatedNodeIds = graph ? scopedNodeIds(graph, scope.sourceIds).slice(0, 28) : [];
18788
+ const projectIds = uniqueStrings4(relatedPages.flatMap((page) => page.projectIds));
18789
+ const now = (/* @__PURE__ */ new Date()).toISOString();
18790
+ const output = buildOutputPage({
18791
+ title: `Source Guide: ${scope.title}`,
18792
+ question: `Guide ${scope.title}`,
18793
+ answer: markdown,
18794
+ citations: scope.sourceIds,
18795
+ schemaHash: graph?.generatedAt ?? "",
18796
+ outputFormat: "report",
18797
+ relatedPageIds,
18798
+ relatedNodeIds,
18799
+ relatedSourceIds: scope.sourceIds,
18800
+ projectIds,
18801
+ extraTags: ["source-guide", "guided-ingest"],
18802
+ origin: "query",
18803
+ slug: `source-guides/${scope.id}`,
18804
+ metadata: {
18805
+ status: "draft",
18806
+ createdAt: now,
18807
+ updatedAt: now,
18808
+ compiledFrom: scope.sourceIds,
18809
+ managedBy: "system",
18810
+ confidence: 0.8
18811
+ }
18812
+ });
18813
+ return { page: output.page, content: output.content };
18814
+ }
18815
+ async function stageSourceReviewForScope(rootDir, scope) {
18816
+ const output = await buildSourceReviewStagedPage(rootDir, scope);
18817
+ const approval = await stageGeneratedOutputPages(rootDir, [{ page: output.page, content: output.content, label: "source-review" }], {
18818
+ bundleType: "source_review",
18819
+ title: `Source Review: ${scope.title}`
18820
+ });
18821
+ return {
18822
+ sourceId: scope.id,
18823
+ pageId: output.page.id,
18824
+ reviewPath: path26.join(approval.approvalDir, "wiki", output.page.path),
18825
+ staged: true,
18826
+ approvalId: approval.approvalId,
18827
+ approvalDir: approval.approvalDir
18828
+ };
18829
+ }
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;
19089
+ if (briefPath) {
19090
+ await refreshVaultAfterOutputSave(rootDir);
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);
19114
+ const reviewOutput = await buildSourceReviewStagedPage(rootDir, scope);
19115
+ const guideOutput = await buildSourceGuideStagedPage(rootDir, {
19116
+ ...scope,
19117
+ briefPath
19118
+ });
19119
+ const guidedUpdates = await buildGuidedInsightUpdatePages(rootDir, scope, session);
19120
+ session.stagedUpdatePaths = guidedUpdates.map((item) => item.page.path);
19121
+ const approval = await stageGeneratedOutputPages(
19122
+ rootDir,
19123
+ [
19124
+ { page: reviewOutput.page, content: reviewOutput.content, label: "source-review" },
19125
+ { page: guideOutput.page, content: guideOutput.content, label: "source-guide" },
19126
+ ...guidedUpdates
19127
+ ],
19128
+ {
19129
+ bundleType: "guided_session",
19130
+ title: `Guided Session: ${scope.title}`,
19131
+ sourceSessionId: session.sessionId
19132
+ }
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);
19142
+ await refreshVaultAfterOutputSave(rootDir);
19143
+ return {
19144
+ sourceId: scope.id,
19145
+ pageId: guideOutput.page.id,
19146
+ guidePath: session.guidePath,
19147
+ reviewPageId: reviewOutput.page.id,
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,
19156
+ briefPath,
19157
+ staged: true,
19158
+ approvalId: approval.approvalId,
19159
+ approvalDir: approval.approvalDir
19160
+ };
19161
+ }
19162
+ function scopeFromManagedSource(source) {
19163
+ return {
19164
+ id: source.id,
19165
+ title: source.title,
19166
+ sourceIds: source.sourceIds,
19167
+ kind: source.kind,
19168
+ briefPath: source.briefPath
19169
+ };
19170
+ }
19171
+ function scopeFromManifest(manifest, manifests) {
19172
+ const groupId = manifest.sourceGroupId ?? manifest.sourceId;
19173
+ return {
19174
+ id: groupId,
19175
+ title: manifest.sourceGroupTitle ?? manifest.title,
19176
+ sourceIds: manifest.sourceGroupId ? manifests.filter((candidate) => candidate.sourceGroupId === manifest.sourceGroupId).map((candidate) => candidate.sourceId) : [manifest.sourceId],
19177
+ kind: manifest.sourceKind
19178
+ };
19179
+ }
19180
+ async function resolveSourceScope(rootDir, id) {
19181
+ const managedSources = await loadManagedSources(rootDir);
19182
+ const managedSource = managedSources.find((source) => source.id === id);
19183
+ if (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
+ };
19193
+ }
19194
+ const manifests = await listManifests(rootDir);
19195
+ const manifest = manifests.find((candidate) => candidate.sourceId === id) ?? manifests.find((candidate) => candidate.sourceGroupId === id);
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) {
19210
+ throw new Error(`Managed source or source id not found: ${id}`);
19211
+ }
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);
18213
19247
  }
18214
19248
  function shouldCompile(changedSources, graphExists, compileRequested) {
18215
19249
  return compileRequested && (!graphExists || changedSources.length > 0);
@@ -18220,14 +19254,15 @@ async function listManagedSourceRecords(rootDir) {
18220
19254
  }
18221
19255
  async function addManagedSource(rootDir, input, options = {}) {
18222
19256
  const compileRequested = options.compile ?? true;
18223
- const briefRequested = options.brief ?? true;
18224
- const reviewRequested = options.review ?? false;
19257
+ const guideRequested = options.guide ?? false;
19258
+ const briefRequested = guideRequested ? true : options.brief ?? true;
19259
+ const reviewRequested = guideRequested ? false : options.review ?? false;
18225
19260
  const sources = await loadManagedSources(rootDir);
18226
19261
  const resolved = await resolveManagedSourceInput(rootDir, input);
18227
19262
  const existing = sources.find((candidate) => matchesManagedSourceSpec(candidate, resolved));
18228
19263
  const now = (/* @__PURE__ */ new Date()).toISOString();
18229
19264
  const source = existing ?? {
18230
- 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),
18231
19266
  kind: resolved.kind,
18232
19267
  title: resolved.title,
18233
19268
  path: resolved.kind === "directory" || resolved.kind === "file" ? resolved.path : void 0,
@@ -18262,17 +19297,27 @@ async function addManagedSource(rootDir, input, options = {}) {
18262
19297
  const nextSources = existing ? sources.map((candidate) => candidate.id === nextSource.id ? nextSource : candidate) : [...sources, nextSource];
18263
19298
  await saveManagedSources(rootDir, nextSources);
18264
19299
  const review = reviewRequested && nextSource.status === "ready" ? await stageSourceReviewForScope(rootDir, scopeFromManagedSource(nextSource)) : 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;
18265
19308
  return {
18266
19309
  source: nextSource,
18267
19310
  compile,
18268
19311
  briefGenerated,
18269
- review
19312
+ review,
19313
+ guide
18270
19314
  };
18271
19315
  }
18272
19316
  async function reloadManagedSources(rootDir, options = {}) {
18273
19317
  const compileRequested = options.compile ?? true;
18274
- const briefRequested = options.brief ?? true;
18275
- const reviewRequested = options.review ?? false;
19318
+ const guideRequested = options.guide ?? false;
19319
+ const briefRequested = guideRequested ? true : options.brief ?? true;
19320
+ const reviewRequested = guideRequested ? false : options.review ?? false;
18276
19321
  const sources = await loadManagedSources(rootDir);
18277
19322
  const selected = options.all || !options.id ? sources : sources.filter((source) => source.id === options.id);
18278
19323
  if (!selected.length) {
@@ -18311,11 +19356,24 @@ async function reloadManagedSources(rootDir, options = {}) {
18311
19356
  const reviews = reviewRequested ? await Promise.all(
18312
19357
  nextSources.filter((source) => selected.some((candidate) => candidate.id === source.id)).filter((source) => source.status === "ready").map(async (source) => await stageSourceReviewForScope(rootDir, scopeFromManagedSource(source)))
18313
19358
  ) : [];
19359
+ const guides = guideRequested ? await Promise.all(
19360
+ nextSources.filter((source) => selected.some((candidate) => candidate.id === source.id)).filter((source) => source.status === "ready").map(
19361
+ async (source) => await stageSourceGuideForScope(
19362
+ rootDir,
19363
+ {
19364
+ ...scopeFromManagedSource(source),
19365
+ briefPath: source.briefPath
19366
+ },
19367
+ { answers: options.guideAnswers }
19368
+ )
19369
+ )
19370
+ ) : [];
18314
19371
  return {
18315
19372
  sources: nextSources.filter((source) => selected.some((candidate) => candidate.id === source.id)),
18316
19373
  compile,
18317
19374
  briefPaths: [...briefPaths.values()],
18318
- reviews
19375
+ reviews,
19376
+ guides
18319
19377
  };
18320
19378
  }
18321
19379
  async function deleteManagedSource(rootDir, id) {
@@ -18329,17 +19387,17 @@ async function deleteManagedSource(rootDir, id) {
18329
19387
  sources.filter((source) => source.id !== id)
18330
19388
  );
18331
19389
  const workingDir = await managedSourceWorkingDir(rootDir, id);
18332
- await fs21.rm(workingDir, { recursive: true, force: true });
19390
+ await fs22.rm(workingDir, { recursive: true, force: true });
18333
19391
  return { removed: target };
18334
19392
  }
18335
19393
 
18336
19394
  // src/viewer.ts
18337
19395
  import { execFile } from "child_process";
18338
- import fs22 from "fs/promises";
19396
+ import fs23 from "fs/promises";
18339
19397
  import http from "http";
18340
- import path27 from "path";
19398
+ import path28 from "path";
18341
19399
  import { promisify } from "util";
18342
- import matter10 from "gray-matter";
19400
+ import matter11 from "gray-matter";
18343
19401
  import mime2 from "mime-types";
18344
19402
 
18345
19403
  // src/graph-presentation.ts
@@ -18461,7 +19519,7 @@ function buildViewerGraphArtifact(graph, options = {}) {
18461
19519
  }
18462
19520
 
18463
19521
  // src/watch.ts
18464
- import path26 from "path";
19522
+ import path27 from "path";
18465
19523
  import process3 from "process";
18466
19524
  import chokidar from "chokidar";
18467
19525
  var MAX_BACKOFF_MS = 3e4;
@@ -18469,15 +19527,15 @@ var BACKOFF_THRESHOLD = 3;
18469
19527
  var CRITICAL_THRESHOLD = 10;
18470
19528
  var REPO_WATCH_IGNORES = /* @__PURE__ */ new Set([".git", ".venv"]);
18471
19529
  function withinRoot3(rootPath, targetPath) {
18472
- const relative = path26.relative(rootPath, targetPath);
18473
- return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
19530
+ const relative = path27.relative(rootPath, targetPath);
19531
+ return relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative);
18474
19532
  }
18475
19533
  function hasIgnoredRepoSegment(baseDir, targetPath) {
18476
- const relativePath = path26.relative(baseDir, targetPath);
19534
+ const relativePath = path27.relative(baseDir, targetPath);
18477
19535
  if (!relativePath || relativePath.startsWith("..")) {
18478
19536
  return false;
18479
19537
  }
18480
- 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));
18481
19539
  }
18482
19540
  function workspaceIgnoreRoots(rootDir, paths) {
18483
19541
  return [
@@ -18486,16 +19544,16 @@ function workspaceIgnoreRoots(rootDir, paths) {
18486
19544
  paths.stateDir,
18487
19545
  paths.agentDir,
18488
19546
  paths.inboxDir,
18489
- path26.join(rootDir, ".claude"),
18490
- path26.join(rootDir, ".cursor"),
18491
- path26.join(rootDir, ".obsidian")
18492
- ].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));
18493
19551
  }
18494
19552
  async function resolveWatchTargets(rootDir, paths, options) {
18495
- const targets = /* @__PURE__ */ new Set([path26.resolve(paths.inboxDir)]);
19553
+ const targets = /* @__PURE__ */ new Set([path27.resolve(paths.inboxDir)]);
18496
19554
  if (options.repo) {
18497
19555
  for (const repoRoot of await listTrackedRepoRoots(rootDir)) {
18498
- targets.add(path26.resolve(repoRoot));
19556
+ targets.add(path27.resolve(repoRoot));
18499
19557
  }
18500
19558
  }
18501
19559
  return [...targets].sort((left, right) => left.localeCompare(right));
@@ -18625,7 +19683,7 @@ async function watchVault(rootDir, options = {}) {
18625
19683
  const { paths } = await initWorkspace(rootDir);
18626
19684
  const baseDebounceMs = options.debounceMs ?? 900;
18627
19685
  const ignoredRoots = workspaceIgnoreRoots(rootDir, paths);
18628
- const inboxWatchRoot = path26.resolve(paths.inboxDir);
19686
+ const inboxWatchRoot = path27.resolve(paths.inboxDir);
18629
19687
  let watchTargets = await resolveWatchTargets(rootDir, paths, options);
18630
19688
  let timer;
18631
19689
  let running = false;
@@ -18640,7 +19698,7 @@ async function watchVault(rootDir, options = {}) {
18640
19698
  usePolling: true,
18641
19699
  interval: 100,
18642
19700
  ignored: (targetPath) => {
18643
- const absolutePath = path26.resolve(targetPath);
19701
+ const absolutePath = path27.resolve(targetPath);
18644
19702
  const primaryTarget = watchTargets.filter((watchTarget) => withinRoot3(watchTarget, absolutePath)).sort((left, right) => right.length - left.length)[0] ?? null;
18645
19703
  if (!primaryTarget) {
18646
19704
  return false;
@@ -18829,8 +19887,8 @@ async function watchVault(rootDir, options = {}) {
18829
19887
  }
18830
19888
  };
18831
19889
  const reasonForPath = (targetPath) => {
18832
- const baseDir = watchTargets.filter((watchTarget) => withinRoot3(watchTarget, path26.resolve(targetPath))).sort((left, right) => right.length - left.length)[0] ?? paths.inboxDir;
18833
- 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) || ".";
18834
19892
  };
18835
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)}`));
18836
19894
  await new Promise((resolve, reject) => {
@@ -18872,15 +19930,15 @@ async function getWatchStatus(rootDir) {
18872
19930
  var execFileAsync = promisify(execFile);
18873
19931
  async function readViewerPage(rootDir, relativePath) {
18874
19932
  const { paths } = await loadVaultConfig(rootDir);
18875
- const absolutePath = path27.resolve(paths.wikiDir, relativePath);
19933
+ const absolutePath = path28.resolve(paths.wikiDir, relativePath);
18876
19934
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
18877
19935
  return null;
18878
19936
  }
18879
- const raw = await fs22.readFile(absolutePath, "utf8");
18880
- const parsed = matter10(raw);
19937
+ const raw = await fs23.readFile(absolutePath, "utf8");
19938
+ const parsed = matter11(raw);
18881
19939
  return {
18882
19940
  path: relativePath,
18883
- 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)),
18884
19942
  frontmatter: parsed.data,
18885
19943
  content: parsed.content,
18886
19944
  assets: normalizeOutputAssets(parsed.data.output_assets)
@@ -18888,12 +19946,12 @@ async function readViewerPage(rootDir, relativePath) {
18888
19946
  }
18889
19947
  async function readViewerAsset(rootDir, relativePath) {
18890
19948
  const { paths } = await loadVaultConfig(rootDir);
18891
- const absolutePath = path27.resolve(paths.wikiDir, relativePath);
19949
+ const absolutePath = path28.resolve(paths.wikiDir, relativePath);
18892
19950
  if (!absolutePath.startsWith(paths.wikiDir) || !await fileExists(absolutePath)) {
18893
19951
  return null;
18894
19952
  }
18895
19953
  return {
18896
- buffer: await fs22.readFile(absolutePath),
19954
+ buffer: await fs23.readFile(absolutePath),
18897
19955
  mimeType: mime2.lookup(absolutePath) || "application/octet-stream"
18898
19956
  };
18899
19957
  }
@@ -18916,12 +19974,12 @@ async function readJsonBody(request) {
18916
19974
  return JSON.parse(raw);
18917
19975
  }
18918
19976
  async function ensureViewerDist(viewerDistDir) {
18919
- const indexPath = path27.join(viewerDistDir, "index.html");
19977
+ const indexPath = path28.join(viewerDistDir, "index.html");
18920
19978
  if (await fileExists(indexPath)) {
18921
19979
  return;
18922
19980
  }
18923
- const viewerProjectDir = path27.dirname(viewerDistDir);
18924
- if (await fileExists(path27.join(viewerProjectDir, "package.json"))) {
19981
+ const viewerProjectDir = path28.dirname(viewerDistDir);
19982
+ if (await fileExists(path28.join(viewerProjectDir, "package.json"))) {
18925
19983
  await execFileAsync("pnpm", ["build"], { cwd: viewerProjectDir });
18926
19984
  }
18927
19985
  }
@@ -18943,7 +20001,7 @@ async function startGraphServer(rootDir, port, options = {}) {
18943
20001
  response.end(JSON.stringify({ error: "Graph artifact not found. Run `swarmvault compile` first." }));
18944
20002
  return;
18945
20003
  }
18946
- const reportPath = path27.join(paths.wikiDir, "graph", "report.json");
20004
+ const reportPath = path28.join(paths.wikiDir, "graph", "report.json");
18947
20005
  const report = await readJsonFile(reportPath) ?? null;
18948
20006
  response.writeHead(200, { "content-type": "application/json" });
18949
20007
  response.end(JSON.stringify(buildViewerGraphArtifact(graph, { report, full: options.full ?? false })));
@@ -19003,14 +20061,14 @@ async function startGraphServer(rootDir, port, options = {}) {
19003
20061
  return;
19004
20062
  }
19005
20063
  if (url.pathname === "/api/graph-report") {
19006
- const reportPath = path27.join(paths.wikiDir, "graph", "report.json");
20064
+ const reportPath = path28.join(paths.wikiDir, "graph", "report.json");
19007
20065
  if (!await fileExists(reportPath)) {
19008
20066
  response.writeHead(404, { "content-type": "application/json" });
19009
20067
  response.end(JSON.stringify({ error: "Graph report artifact not found. Run `swarmvault compile` first." }));
19010
20068
  return;
19011
20069
  }
19012
20070
  response.writeHead(200, { "content-type": "application/json" });
19013
- response.end(await fs22.readFile(reportPath, "utf8"));
20071
+ response.end(await fs23.readFile(reportPath, "utf8"));
19014
20072
  return;
19015
20073
  }
19016
20074
  if (url.pathname === "/api/watch-status") {
@@ -19093,8 +20151,8 @@ async function startGraphServer(rootDir, port, options = {}) {
19093
20151
  return;
19094
20152
  }
19095
20153
  const relativePath = url.pathname === "/" ? "index.html" : url.pathname.slice(1);
19096
- const target = path27.join(paths.viewerDistDir, relativePath);
19097
- 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");
19098
20156
  const filePath = await fileExists(target) ? target : fallback;
19099
20157
  if (!await fileExists(filePath)) {
19100
20158
  response.writeHead(503, { "content-type": "text/plain" });
@@ -19102,7 +20160,7 @@ async function startGraphServer(rootDir, port, options = {}) {
19102
20160
  return;
19103
20161
  }
19104
20162
  response.writeHead(200, { "content-type": mime2.lookup(filePath) || "text/plain" });
19105
- response.end(await fs22.readFile(filePath));
20163
+ response.end(await fs23.readFile(filePath));
19106
20164
  });
19107
20165
  await new Promise((resolve) => {
19108
20166
  server.listen(effectivePort, resolve);
@@ -19129,7 +20187,7 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19129
20187
  throw new Error("Graph artifact not found. Run `swarmvault compile` first.");
19130
20188
  }
19131
20189
  await ensureViewerDist(paths.viewerDistDir);
19132
- const indexPath = path27.join(paths.viewerDistDir, "index.html");
20190
+ const indexPath = path28.join(paths.viewerDistDir, "index.html");
19133
20191
  if (!await fileExists(indexPath)) {
19134
20192
  throw new Error("Viewer build not found. Run `pnpm build` first.");
19135
20193
  }
@@ -19155,17 +20213,17 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19155
20213
  } : null;
19156
20214
  })
19157
20215
  );
19158
- const rawHtml = await fs22.readFile(indexPath, "utf8");
20216
+ const rawHtml = await fs23.readFile(indexPath, "utf8");
19159
20217
  const scriptMatch = rawHtml.match(/<script type="module" crossorigin src="([^"]+)"><\/script>/);
19160
20218
  const styleMatch = rawHtml.match(/<link rel="stylesheet" crossorigin href="([^"]+)">/);
19161
- const scriptPath = scriptMatch?.[1] ? path27.join(paths.viewerDistDir, scriptMatch[1].replace(/^\//, "")) : null;
19162
- 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;
19163
20221
  if (!scriptPath || !await fileExists(scriptPath)) {
19164
20222
  throw new Error("Viewer script bundle not found. Run `pnpm build` first.");
19165
20223
  }
19166
- const script = await fs22.readFile(scriptPath, "utf8");
19167
- const style = stylePath && await fileExists(stylePath) ? await fs22.readFile(stylePath, "utf8") : "";
19168
- 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"));
19169
20227
  const embeddedData = JSON.stringify(
19170
20228
  { graph: buildViewerGraphArtifact(graph, { report, full: options.full ?? false }), pages: pages.filter(Boolean), report },
19171
20229
  null,
@@ -19188,9 +20246,9 @@ async function exportGraphHtml(rootDir, outputPath, options = {}) {
19188
20246
  "</html>",
19189
20247
  ""
19190
20248
  ].filter(Boolean).join("\n");
19191
- await fs22.mkdir(path27.dirname(outputPath), { recursive: true });
19192
- await fs22.writeFile(outputPath, html, "utf8");
19193
- 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);
19194
20252
  }
19195
20253
  export {
19196
20254
  acceptApproval,
@@ -19216,6 +20274,8 @@ export {
19216
20274
  getWatchStatus,
19217
20275
  getWebSearchAdapterForTask,
19218
20276
  getWorkspaceInfo,
20277
+ guideManagedSource,
20278
+ guideSourceScope,
19219
20279
  importInbox,
19220
20280
  ingestDirectory,
19221
20281
  ingestInput,
@@ -19250,6 +20310,7 @@ export {
19250
20310
  rejectApproval,
19251
20311
  reloadManagedSources,
19252
20312
  resolvePaths,
20313
+ resumeSourceSession,
19253
20314
  reviewManagedSource,
19254
20315
  reviewSourceScope,
19255
20316
  runSchedule,