@swarmvaultai/engine 0.6.0 → 0.6.2

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-FD3LJQ4T.js";
24
+ } from "./chunk-OK5752AP.js";
25
25
 
26
26
  // src/agents.ts
27
27
  import crypto from "crypto";
@@ -1735,6 +1735,7 @@ import TurndownService2 from "turndown";
1735
1735
  import fs6 from "fs/promises";
1736
1736
  import path6 from "path";
1737
1737
  import ts from "typescript";
1738
+ import YAML2 from "yaml";
1738
1739
 
1739
1740
  // src/code-tree-sitter.ts
1740
1741
  import fs5 from "fs/promises";
@@ -1758,12 +1759,14 @@ var treeSitterModulePromise;
1758
1759
  var treeSitterInitPromise;
1759
1760
  var languageCache = /* @__PURE__ */ new Map();
1760
1761
  var grammarAssetByLanguage = {
1762
+ bash: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-bash.wasm" },
1761
1763
  python: { packageName: TREE_SITTER_RUNTIME_PACKAGE, relativePath: "wasm/tree-sitter-python.wasm" },
1762
1764
  go: { packageName: TREE_SITTER_RUNTIME_PACKAGE, relativePath: "wasm/tree-sitter-go.wasm" },
1763
1765
  rust: { packageName: TREE_SITTER_RUNTIME_PACKAGE, relativePath: "wasm/tree-sitter-rust.wasm" },
1764
1766
  java: { packageName: TREE_SITTER_RUNTIME_PACKAGE, relativePath: "wasm/tree-sitter-java.wasm" },
1765
1767
  kotlin: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-kotlin.wasm" },
1766
1768
  scala: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-scala.wasm" },
1769
+ dart: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-dart.wasm" },
1767
1770
  lua: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-lua.wasm" },
1768
1771
  zig: { packageName: TREE_SITTER_EXTRA_GRAMMARS_PACKAGE, relativePath: "out/tree-sitter-zig.wasm" },
1769
1772
  csharp: { packageName: TREE_SITTER_RUNTIME_PACKAGE, relativePath: "wasm/tree-sitter-c-sharp.wasm" },
@@ -1830,7 +1833,10 @@ function normalizeSymbolReference(value) {
1830
1833
  return lastSegment.replace(/[,:;]+$/g, "").trim();
1831
1834
  }
1832
1835
  function stripCodeExtension(filePath) {
1833
- return filePath.replace(/\.(?:[cm]?jsx?|tsx?|mts|cts|py|go|rs|java|kt|kts|scala|sc|lua|zig|cs|php|c|cc|cpp|cxx|h|hh|hpp|hxx)$/i, "");
1836
+ return filePath.replace(
1837
+ /\.(?:[cm]?jsx?|tsx?|mts|cts|sh|bash|zsh|py|go|rs|java|kt|kts|scala|sc|dart|lua|zig|cs|php|c|cc|cpp|cxx|h|hh|hpp|hxx)$/i,
1838
+ ""
1839
+ );
1834
1840
  }
1835
1841
  function manifestModuleName(manifest, language) {
1836
1842
  const repoPath = manifest.repoRelativePath ?? path5.basename(manifest.originalPath ?? manifest.storedPath);
@@ -2264,6 +2270,89 @@ function parseScalaImport(text) {
2264
2270
  reExport: false
2265
2271
  }));
2266
2272
  }
2273
+ function bashCommandName(commandNode) {
2274
+ if (!commandNode) {
2275
+ return void 0;
2276
+ }
2277
+ const nameNode = commandNode.childForFieldName("name") ?? findNamedChild(commandNode, "command_name") ?? commandNode.namedChildren.at(0) ?? null;
2278
+ if (!nameNode) {
2279
+ return void 0;
2280
+ }
2281
+ return nodeText(findNamedChild(nameNode, "word") ?? nameNode.namedChildren.at(0) ?? nameNode).trim() || void 0;
2282
+ }
2283
+ function bashSpecifierLooksLocal(specifier) {
2284
+ return specifier.startsWith(".") || specifier.startsWith("/") || specifier.includes("/") || /\.(?:sh|bash|zsh)$/i.test(specifier);
2285
+ }
2286
+ function parseBashImport(commandNode) {
2287
+ const commandName = bashCommandName(commandNode);
2288
+ if (commandName !== "source" && commandName !== ".") {
2289
+ return void 0;
2290
+ }
2291
+ const argumentNode = commandNode.childForFieldName("argument") ?? commandNode.namedChildren.find((child) => child && child !== (commandNode.childForFieldName("name") ?? null)) ?? null;
2292
+ const specifier = quotedPath(nodeText(argumentNode));
2293
+ if (!specifier) {
2294
+ return void 0;
2295
+ }
2296
+ return {
2297
+ specifier,
2298
+ importedSymbols: [],
2299
+ isExternal: !bashSpecifierLooksLocal(specifier),
2300
+ reExport: false
2301
+ };
2302
+ }
2303
+ function parseDartUri(node) {
2304
+ const stringNode = node?.descendantsOfType("string_literal").find((item) => item !== null) ?? null;
2305
+ return stringNode ? quotedPath(stringNode.text) : void 0;
2306
+ }
2307
+ function dartSpecifierLooksLocal(specifier) {
2308
+ return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || !specifier.startsWith("package:") && !specifier.includes(":") && specifier.endsWith(".dart");
2309
+ }
2310
+ function parseDartDirective(node) {
2311
+ if (node.type === "import_or_export") {
2312
+ const importNode = findNamedChild(node, "library_import");
2313
+ if (importNode) {
2314
+ const specifier2 = parseDartUri(
2315
+ findNamedChild(importNode, "configurable_uri") ?? findNamedChild(findNamedChild(importNode, "import_specification"), "configurable_uri") ?? importNode
2316
+ );
2317
+ if (!specifier2) {
2318
+ return void 0;
2319
+ }
2320
+ return {
2321
+ specifier: specifier2,
2322
+ importedSymbols: [],
2323
+ isExternal: !dartSpecifierLooksLocal(specifier2) && !specifier2.startsWith("package:"),
2324
+ reExport: false
2325
+ };
2326
+ }
2327
+ const exportNode = findNamedChild(node, "library_export");
2328
+ if (exportNode) {
2329
+ const specifier2 = parseDartUri(findNamedChild(exportNode, "configurable_uri") ?? exportNode);
2330
+ if (!specifier2) {
2331
+ return void 0;
2332
+ }
2333
+ return {
2334
+ specifier: specifier2,
2335
+ importedSymbols: [],
2336
+ isExternal: !dartSpecifierLooksLocal(specifier2) && !specifier2.startsWith("package:"),
2337
+ reExport: true
2338
+ };
2339
+ }
2340
+ return void 0;
2341
+ }
2342
+ if (node.type !== "part_directive") {
2343
+ return void 0;
2344
+ }
2345
+ const specifier = parseDartUri(findNamedChild(node, "uri") ?? node);
2346
+ if (!specifier) {
2347
+ return void 0;
2348
+ }
2349
+ return {
2350
+ specifier,
2351
+ importedSymbols: [],
2352
+ isExternal: false,
2353
+ reExport: false
2354
+ };
2355
+ }
2267
2356
  function parseLuaRequire(node) {
2268
2357
  const stringNode = node.descendantsOfType("string").find((item) => item !== null);
2269
2358
  const identifiers = node.descendantsOfType("identifier").filter((item) => item !== null).map((item) => item.text.trim());
@@ -2425,6 +2514,29 @@ function scalaDefinitionKind(node) {
2425
2514
  }
2426
2515
  return void 0;
2427
2516
  }
2517
+ function bashCallNamesFromBody(bodyNode, selfName) {
2518
+ if (!bodyNode) {
2519
+ return [];
2520
+ }
2521
+ return uniqueBy(
2522
+ bodyNode.descendantsOfType("command").filter((item) => item !== null).map((item) => bashCommandName(item)).filter((name) => Boolean(name)).filter((name) => name !== "source" && name !== "." && name !== selfName),
2523
+ (name) => name
2524
+ );
2525
+ }
2526
+ function dartCallableName(node) {
2527
+ if (!node) {
2528
+ return void 0;
2529
+ }
2530
+ if (node.type === "function_signature") {
2531
+ return extractIdentifier(node.childForFieldName("name") ?? findNamedChild(node, "identifier"));
2532
+ }
2533
+ if (node.type === "constructor_signature") {
2534
+ return extractIdentifier(node.childForFieldName("name") ?? findNamedChild(node, "identifier"));
2535
+ }
2536
+ return extractIdentifier(
2537
+ node.childForFieldName("name") ?? findNamedChild(node, "function_signature") ?? findNamedChild(node, "identifier")
2538
+ );
2539
+ }
2428
2540
  function luaFunctionName(node) {
2429
2541
  if (!node) {
2430
2542
  return void 0;
@@ -2447,6 +2559,237 @@ function zigDeclarationKind(node) {
2447
2559
  }
2448
2560
  return void 0;
2449
2561
  }
2562
+ function bashCodeAnalysis(manifest, rootNode, diagnostics) {
2563
+ const imports = [];
2564
+ const draftSymbols = [];
2565
+ const exportLabels = [];
2566
+ for (const child of rootNode.namedChildren) {
2567
+ if (!child) {
2568
+ continue;
2569
+ }
2570
+ if (child.type === "command") {
2571
+ const parsed = parseBashImport(child);
2572
+ if (parsed) {
2573
+ imports.push(parsed);
2574
+ }
2575
+ continue;
2576
+ }
2577
+ if (child.type !== "function_definition") {
2578
+ continue;
2579
+ }
2580
+ const name = nodeText(child.childForFieldName("name") ?? child.namedChildren.at(0) ?? null).trim();
2581
+ if (!name) {
2582
+ continue;
2583
+ }
2584
+ draftSymbols.push({
2585
+ name,
2586
+ kind: "function",
2587
+ signature: singleLineSignature(child.text),
2588
+ exported: true,
2589
+ callNames: [],
2590
+ extendsNames: [],
2591
+ implementsNames: [],
2592
+ bodyText: nodeText(child.childForFieldName("body") ?? findNamedChild(child, "compound_statement"))
2593
+ });
2594
+ exportLabels.push(name);
2595
+ }
2596
+ for (let index = 0; index < draftSymbols.length; index += 1) {
2597
+ const functionNode = rootNode.namedChildren.find(
2598
+ (child) => child?.type === "function_definition" && nodeText(child.childForFieldName("name") ?? child.namedChildren.at(0) ?? null).trim() === draftSymbols[index]?.name
2599
+ );
2600
+ draftSymbols[index].callNames = bashCallNamesFromBody(
2601
+ functionNode?.childForFieldName("body") ?? findNamedChild(functionNode, "compound_statement"),
2602
+ draftSymbols[index].name
2603
+ );
2604
+ }
2605
+ return finalizeCodeAnalysis(manifest, "bash", imports, draftSymbols, exportLabels, diagnostics);
2606
+ }
2607
+ function dartCodeAnalysis(manifest, rootNode, diagnostics) {
2608
+ const imports = [];
2609
+ const draftSymbols = [];
2610
+ const exportLabels = [];
2611
+ let libraryName;
2612
+ const pushScopedFunctions = (bodyNode, scopeName) => {
2613
+ if (!bodyNode) {
2614
+ return;
2615
+ }
2616
+ const children = bodyNode.namedChildren.filter((item) => item !== null);
2617
+ for (let index = 0; index < children.length; index += 1) {
2618
+ const child = children[index];
2619
+ if (!child) {
2620
+ continue;
2621
+ }
2622
+ if (child.type === "method_signature") {
2623
+ const signatureNode = findNamedChild(child, "function_signature") ?? child;
2624
+ const methodName = dartCallableName(signatureNode);
2625
+ if (!methodName) {
2626
+ continue;
2627
+ }
2628
+ const bodyNode2 = children[index + 1]?.type === "function_body" ? children[index + 1] : null;
2629
+ const symbolName2 = `${scopeName}.${methodName}`;
2630
+ const exported2 = !scopeName.startsWith("_") && !methodName.startsWith("_");
2631
+ draftSymbols.push({
2632
+ name: symbolName2,
2633
+ kind: "function",
2634
+ signature: singleLineSignature(`${child.text} ${nodeText(bodyNode2)}`),
2635
+ exported: exported2,
2636
+ callNames: [],
2637
+ extendsNames: [],
2638
+ implementsNames: [],
2639
+ bodyText: nodeText(bodyNode2)
2640
+ });
2641
+ if (exported2) {
2642
+ exportLabels.push(symbolName2);
2643
+ }
2644
+ continue;
2645
+ }
2646
+ if (child.type !== "declaration") {
2647
+ continue;
2648
+ }
2649
+ const constructorNode = findNamedChild(child, "constructor_signature");
2650
+ const constructorName = dartCallableName(constructorNode);
2651
+ if (!constructorName) {
2652
+ continue;
2653
+ }
2654
+ const symbolName = `${scopeName}.${constructorName}`;
2655
+ const exported = !scopeName.startsWith("_") && !constructorName.startsWith("_");
2656
+ draftSymbols.push({
2657
+ name: symbolName,
2658
+ kind: "function",
2659
+ signature: singleLineSignature(child.text),
2660
+ exported,
2661
+ callNames: [],
2662
+ extendsNames: [],
2663
+ implementsNames: [],
2664
+ bodyText: child.text
2665
+ });
2666
+ if (exported) {
2667
+ exportLabels.push(symbolName);
2668
+ }
2669
+ }
2670
+ };
2671
+ const topLevelChildren = rootNode.namedChildren.filter((item) => item !== null);
2672
+ for (let index = 0; index < topLevelChildren.length; index += 1) {
2673
+ const child = topLevelChildren[index];
2674
+ if (!child) {
2675
+ continue;
2676
+ }
2677
+ if (child.type === "library_name") {
2678
+ libraryName = nodeText(findNamedChild(child, "dotted_identifier_list") ?? child.namedChildren.at(-1) ?? null) || libraryName;
2679
+ continue;
2680
+ }
2681
+ if (child.type === "import_or_export" || child.type === "part_directive") {
2682
+ const parsed = parseDartDirective(child);
2683
+ if (parsed) {
2684
+ imports.push(parsed);
2685
+ }
2686
+ continue;
2687
+ }
2688
+ if (child.type === "function_signature") {
2689
+ const functionName = dartCallableName(child);
2690
+ if (!functionName) {
2691
+ continue;
2692
+ }
2693
+ const bodyNode2 = topLevelChildren[index + 1]?.type === "function_body" ? topLevelChildren[index + 1] : null;
2694
+ const exported2 = !functionName.startsWith("_");
2695
+ draftSymbols.push({
2696
+ name: functionName,
2697
+ kind: "function",
2698
+ signature: singleLineSignature(`${child.text} ${nodeText(bodyNode2)}`),
2699
+ exported: exported2,
2700
+ callNames: [],
2701
+ extendsNames: [],
2702
+ implementsNames: [],
2703
+ bodyText: nodeText(bodyNode2)
2704
+ });
2705
+ if (exported2) {
2706
+ exportLabels.push(functionName);
2707
+ }
2708
+ continue;
2709
+ }
2710
+ if (child.type === "mixin_declaration") {
2711
+ const mixinName = extractIdentifier(child.childForFieldName("name") ?? findNamedChild(child, "identifier"));
2712
+ if (!mixinName) {
2713
+ continue;
2714
+ }
2715
+ const bodyNode2 = child.childForFieldName("body") ?? findNamedChild(child, "class_body");
2716
+ const exported2 = !mixinName.startsWith("_");
2717
+ draftSymbols.push({
2718
+ name: mixinName,
2719
+ kind: "trait",
2720
+ signature: singleLineSignature(child.text),
2721
+ exported: exported2,
2722
+ callNames: [],
2723
+ extendsNames: [],
2724
+ implementsNames: [],
2725
+ bodyText: nodeText(bodyNode2) || child.text
2726
+ });
2727
+ if (exported2) {
2728
+ exportLabels.push(mixinName);
2729
+ }
2730
+ pushScopedFunctions(bodyNode2, mixinName);
2731
+ continue;
2732
+ }
2733
+ if (child.type === "enum_declaration") {
2734
+ const enumName = extractIdentifier(child.childForFieldName("name") ?? findNamedChild(child, "identifier"));
2735
+ if (!enumName) {
2736
+ continue;
2737
+ }
2738
+ const exported2 = !enumName.startsWith("_");
2739
+ draftSymbols.push({
2740
+ name: enumName,
2741
+ kind: "enum",
2742
+ signature: singleLineSignature(child.text),
2743
+ exported: exported2,
2744
+ callNames: [],
2745
+ extendsNames: [],
2746
+ implementsNames: [],
2747
+ bodyText: nodeText(child.childForFieldName("body") ?? findNamedChild(child, "enum_body")) || child.text
2748
+ });
2749
+ if (exported2) {
2750
+ exportLabels.push(enumName);
2751
+ }
2752
+ continue;
2753
+ }
2754
+ if (child.type === "extension_declaration") {
2755
+ const extensionName = extractIdentifier(child.childForFieldName("name") ?? findNamedChild(child, "identifier"));
2756
+ const targetType = extractIdentifier(child.childForFieldName("type") ?? findNamedChild(child, "type_identifier")) ?? extensionName;
2757
+ const bodyNode2 = child.childForFieldName("body") ?? findNamedChild(child, "extension_body");
2758
+ if (targetType) {
2759
+ pushScopedFunctions(bodyNode2, targetType);
2760
+ }
2761
+ continue;
2762
+ }
2763
+ if (child.type !== "class_definition") {
2764
+ continue;
2765
+ }
2766
+ const className = extractIdentifier(child.childForFieldName("name") ?? findNamedChild(child, "identifier"));
2767
+ if (!className) {
2768
+ continue;
2769
+ }
2770
+ const superTypes = descendantTypeNames(child.childForFieldName("superclass"));
2771
+ const interfaceTypes = descendantTypeNames(child.childForFieldName("interfaces"));
2772
+ const bodyNode = child.childForFieldName("body") ?? findNamedChild(child, "class_body");
2773
+ const exported = !className.startsWith("_");
2774
+ draftSymbols.push({
2775
+ name: className,
2776
+ kind: "class",
2777
+ signature: singleLineSignature(child.text),
2778
+ exported,
2779
+ callNames: [],
2780
+ extendsNames: superTypes.slice(0, 1),
2781
+ implementsNames: [...superTypes.slice(1), ...interfaceTypes],
2782
+ bodyText: nodeText(bodyNode) || child.text
2783
+ });
2784
+ if (exported) {
2785
+ exportLabels.push(className);
2786
+ }
2787
+ pushScopedFunctions(bodyNode, className);
2788
+ }
2789
+ return finalizeCodeAnalysis(manifest, "dart", imports, draftSymbols, exportLabels, diagnostics, {
2790
+ namespace: libraryName
2791
+ });
2792
+ }
2450
2793
  function pythonCodeAnalysis(manifest, rootNode, diagnostics) {
2451
2794
  const imports = [];
2452
2795
  const draftSymbols = [];
@@ -3425,6 +3768,8 @@ async function analyzeTreeSitterCode(manifest, content, language) {
3425
3768
  const diagnostics = diagnosticsFromTree(tree.rootNode);
3426
3769
  const rationales = extractTreeSitterRationales(manifest, language, tree.rootNode);
3427
3770
  switch (language) {
3771
+ case "bash":
3772
+ return { code: bashCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3428
3773
  case "python":
3429
3774
  return { code: pythonCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3430
3775
  case "go":
@@ -3437,6 +3782,8 @@ async function analyzeTreeSitterCode(manifest, content, language) {
3437
3782
  return { code: kotlinCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3438
3783
  case "scala":
3439
3784
  return { code: scalaCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3785
+ case "dart":
3786
+ return { code: dartCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3440
3787
  case "lua":
3441
3788
  return { code: luaCodeAnalysis(manifest, tree.rootNode, diagnostics), rationales };
3442
3789
  case "zig":
@@ -3497,6 +3844,34 @@ function isRelativeSpecifier(specifier) {
3497
3844
  function isLocalIncludeSpecifier(specifier) {
3498
3845
  return specifier.startsWith(".") || specifier.startsWith("/") || specifier.includes("/");
3499
3846
  }
3847
+ function bashSpecifierLooksLocal2(specifier) {
3848
+ return isLocalIncludeSpecifier(specifier) || /\.(?:sh|bash|zsh)$/i.test(specifier);
3849
+ }
3850
+ function dartSpecifierLooksLocal2(specifier) {
3851
+ return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || !specifier.startsWith("package:") && !specifier.includes(":") && specifier.endsWith(".dart");
3852
+ }
3853
+ function interpreterFromShebang(content) {
3854
+ if (!content?.startsWith("#!")) {
3855
+ return void 0;
3856
+ }
3857
+ const firstLine = content.split(/\r?\n/, 1)[0]?.slice(2).trim() ?? "";
3858
+ if (!firstLine) {
3859
+ return void 0;
3860
+ }
3861
+ const parts = firstLine.split(/\s+/).filter(Boolean);
3862
+ if (parts.length === 0) {
3863
+ return void 0;
3864
+ }
3865
+ const basename = (value) => path6.posix.basename(value.trim());
3866
+ if (basename(parts[0] ?? "") === "env") {
3867
+ const interpreter = parts.slice(1).find((part) => !part.startsWith("-"));
3868
+ return interpreter ? basename(interpreter) : void 0;
3869
+ }
3870
+ return basename(parts[0] ?? "");
3871
+ }
3872
+ function isShellInterpreter(value) {
3873
+ return value === "sh" || value === "bash" || value === "zsh";
3874
+ }
3500
3875
  function formatDiagnosticCategory(category) {
3501
3876
  switch (category) {
3502
3877
  case ts.DiagnosticCategory.Error:
@@ -3727,7 +4102,10 @@ function makeRationale2(manifest, index, text, kind, symbolName) {
3727
4102
  };
3728
4103
  }
3729
4104
  function stripCodeExtension2(filePath) {
3730
- return filePath.replace(/\.(?:[cm]?jsx?|tsx?|mts|cts|py|go|rs|java|kt|kts|scala|sc|lua|zig|cs|php|c|cc|cpp|cxx|h|hh|hpp|hxx)$/i, "");
4105
+ return filePath.replace(
4106
+ /\.(?:[cm]?jsx?|tsx?|mts|cts|sh|bash|zsh|py|go|rs|java|kt|kts|scala|sc|dart|lua|zig|cs|php|c|cc|cpp|cxx|h|hh|hpp|hxx)$/i,
4107
+ ""
4108
+ );
3731
4109
  }
3732
4110
  function manifestModuleName2(manifest, language) {
3733
4111
  const repoPath = manifest.repoRelativePath ?? path6.basename(manifest.originalPath ?? manifest.storedPath);
@@ -4032,7 +4410,7 @@ function analyzeTypeScriptLikeCode(manifest, content) {
4032
4410
  rationales: extractTypeScriptRationales(manifest, content, sourceFile)
4033
4411
  };
4034
4412
  }
4035
- function inferCodeLanguage(filePath, mimeType = "") {
4413
+ function inferCodeLanguage(filePath, mimeType = "", options = {}) {
4036
4414
  const extension = path6.extname(filePath).toLowerCase();
4037
4415
  if (extension === ".ts" || extension === ".mts" || extension === ".cts") {
4038
4416
  return "typescript";
@@ -4046,6 +4424,9 @@ function inferCodeLanguage(filePath, mimeType = "") {
4046
4424
  if (extension === ".js" || extension === ".mjs" || extension === ".cjs" || mimeType.includes("javascript")) {
4047
4425
  return "javascript";
4048
4426
  }
4427
+ if (extension === ".sh" || extension === ".bash" || extension === ".zsh" || mimeType === "application/x-sh") {
4428
+ return "bash";
4429
+ }
4049
4430
  if (extension === ".py") {
4050
4431
  return "python";
4051
4432
  }
@@ -4064,6 +4445,9 @@ function inferCodeLanguage(filePath, mimeType = "") {
4064
4445
  if (extension === ".scala" || extension === ".sc") {
4065
4446
  return "scala";
4066
4447
  }
4448
+ if (extension === ".dart") {
4449
+ return "dart";
4450
+ }
4067
4451
  if (extension === ".lua") {
4068
4452
  return "lua";
4069
4453
  }
@@ -4088,6 +4472,9 @@ function inferCodeLanguage(filePath, mimeType = "") {
4088
4472
  if ([".cc", ".cpp", ".cxx", ".h", ".hh", ".hpp", ".hxx"].includes(extension)) {
4089
4473
  return "cpp";
4090
4474
  }
4475
+ if (!extension && options.executable && isShellInterpreter(interpreterFromShebang(options.content))) {
4476
+ return "bash";
4477
+ }
4091
4478
  return void 0;
4092
4479
  }
4093
4480
  function modulePageTitle(manifest) {
@@ -4120,6 +4507,43 @@ function manifestBasenameWithoutExtension(manifest) {
4120
4507
  const target = manifest.repoRelativePath ?? manifest.originalPath ?? manifest.storedPath;
4121
4508
  return path6.posix.basename(stripCodeExtension2(normalizeAlias(target)));
4122
4509
  }
4510
+ async function readNearestDartPackageInfo(startPath, cache) {
4511
+ let current = path6.resolve(startPath);
4512
+ try {
4513
+ const stat = await fs6.stat(current);
4514
+ if (!stat.isDirectory()) {
4515
+ current = path6.dirname(current);
4516
+ }
4517
+ } catch {
4518
+ current = path6.dirname(current);
4519
+ }
4520
+ while (true) {
4521
+ if (cache.has(current)) {
4522
+ const cached = cache.get(current);
4523
+ return cached === null ? void 0 : cached;
4524
+ }
4525
+ const pubspecPath = path6.join(current, "pubspec.yaml");
4526
+ if (await fs6.access(pubspecPath).then(() => true).catch(() => false)) {
4527
+ try {
4528
+ const content = await fs6.readFile(pubspecPath, "utf8");
4529
+ const parsed = YAML2.parse(content);
4530
+ const packageName = typeof parsed?.name === "string" ? parsed.name.trim() : "";
4531
+ const info = packageName ? { rootDir: current, name: packageName } : null;
4532
+ cache.set(current, info);
4533
+ return info ?? void 0;
4534
+ } catch {
4535
+ cache.set(current, null);
4536
+ return void 0;
4537
+ }
4538
+ }
4539
+ const parent = path6.dirname(current);
4540
+ if (parent === current) {
4541
+ cache.set(current, null);
4542
+ return void 0;
4543
+ }
4544
+ current = parent;
4545
+ }
4546
+ }
4123
4547
  async function readNearestGoModulePath(startPath, cache) {
4124
4548
  let current = path6.resolve(startPath);
4125
4549
  try {
@@ -4166,6 +4590,8 @@ function candidateExtensionsFor(language) {
4166
4590
  case "typescript":
4167
4591
  case "tsx":
4168
4592
  return [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"];
4593
+ case "bash":
4594
+ return [".sh", ".bash", ".zsh"];
4169
4595
  case "python":
4170
4596
  return [".py"];
4171
4597
  case "go":
@@ -4178,6 +4604,8 @@ function candidateExtensionsFor(language) {
4178
4604
  return [".kt", ".kts"];
4179
4605
  case "scala":
4180
4606
  return [".scala", ".sc"];
4607
+ case "dart":
4608
+ return [".dart"];
4181
4609
  case "lua":
4182
4610
  return [".lua"];
4183
4611
  case "zig":
@@ -4199,6 +4627,7 @@ function candidateExtensionsFor(language) {
4199
4627
  async function buildCodeIndex(rootDir, manifests, analyses) {
4200
4628
  const analysesBySourceId = new Map(analyses.map((analysis) => [analysis.sourceId, analysis]));
4201
4629
  const goModuleCache = /* @__PURE__ */ new Map();
4630
+ const dartPackageCache = /* @__PURE__ */ new Map();
4202
4631
  const entries = [];
4203
4632
  for (const manifest of manifests) {
4204
4633
  const analysis = analysesBySourceId.get(manifest.sourceId);
@@ -4223,6 +4652,9 @@ async function buildCodeIndex(rootDir, manifests, analyses) {
4223
4652
  case "python":
4224
4653
  recordAlias(aliases, normalizedModuleName?.replace(/\//g, "."));
4225
4654
  break;
4655
+ case "bash":
4656
+ recordAlias(aliases, basename);
4657
+ break;
4226
4658
  case "rust":
4227
4659
  if (repoRelativePath) {
4228
4660
  recordAlias(aliases, rustModuleAlias(repoRelativePath));
@@ -4244,6 +4676,7 @@ async function buildCodeIndex(rootDir, manifests, analyses) {
4244
4676
  case "java":
4245
4677
  case "kotlin":
4246
4678
  case "scala":
4679
+ case "dart":
4247
4680
  case "csharp":
4248
4681
  if (normalizedNamespace) {
4249
4682
  recordAlias(aliases, `${normalizedNamespace}.${basename}`);
@@ -4253,6 +4686,19 @@ async function buildCodeIndex(rootDir, manifests, analyses) {
4253
4686
  recordAlias(aliases, `${normalizedNamespace}.${symbol.name}`);
4254
4687
  }
4255
4688
  }
4689
+ if (analysis.code.language === "dart" && repoRelativePath) {
4690
+ recordAlias(aliases, basename);
4691
+ const originalPath = manifest.originalPath ? path6.resolve(manifest.originalPath) : path6.resolve(rootDir, manifest.storedPath);
4692
+ const packageInfo = await readNearestDartPackageInfo(originalPath, dartPackageCache);
4693
+ if (packageInfo) {
4694
+ const packageRelativePath = toPosix(path6.relative(packageInfo.rootDir, originalPath));
4695
+ if (packageRelativePath.startsWith("lib/")) {
4696
+ const packagePath = packageRelativePath.slice("lib/".length);
4697
+ recordAlias(aliases, `package:${packageInfo.name}/${packagePath}`);
4698
+ recordAlias(aliases, `package:${packageInfo.name}/${stripCodeExtension2(packagePath)}`);
4699
+ }
4700
+ }
4701
+ }
4256
4702
  break;
4257
4703
  case "lua":
4258
4704
  recordAlias(aliases, basename);
@@ -4387,14 +4833,17 @@ function findImportCandidates(manifest, codeImport, lookup) {
4387
4833
  case "scala":
4388
4834
  case "csharp":
4389
4835
  return aliasMatches(lookup, codeImport.specifier);
4836
+ case "dart":
4837
+ return repoRelativePath && dartSpecifierLooksLocal2(codeImport.specifier) ? repoPathMatches(lookup, ...importResolutionCandidates(repoRelativePath, codeImport.specifier, candidateExtensionsFor(language))) : aliasMatches(lookup, codeImport.specifier);
4390
4838
  case "lua":
4391
4839
  return luaSpecifierLooksLocal(codeImport.specifier) ? repoPathMatches(lookup, ...resolveLuaModuleCandidates(codeImport.specifier)) : aliasMatches(lookup, codeImport.specifier, codeImport.specifier.replace(/\./g, "/"));
4392
4840
  case "zig":
4393
4841
  return repoRelativePath && (!codeImport.isExternal || codeImport.specifier.endsWith(".zig")) ? repoPathMatches(lookup, ...importResolutionCandidates(repoRelativePath, codeImport.specifier, candidateExtensionsFor(language))) : aliasMatches(lookup, codeImport.specifier);
4394
4842
  case "php":
4395
4843
  case "ruby":
4844
+ case "bash":
4396
4845
  case "powershell":
4397
- if (repoRelativePath && isLocalIncludeSpecifier(codeImport.specifier)) {
4846
+ if (repoRelativePath && (language === "bash" ? bashSpecifierLooksLocal2(codeImport.specifier) : isLocalIncludeSpecifier(codeImport.specifier))) {
4398
4847
  return repoPathMatches(
4399
4848
  lookup,
4400
4849
  ...importResolutionCandidates(repoRelativePath, codeImport.specifier, candidateExtensionsFor(language))
@@ -4438,6 +4887,10 @@ function importLooksLocal(manifest, codeImport, candidates) {
4438
4887
  case "kotlin":
4439
4888
  case "scala":
4440
4889
  return !codeImport.isExternal;
4890
+ case "bash":
4891
+ return bashSpecifierLooksLocal2(codeImport.specifier);
4892
+ case "dart":
4893
+ return dartSpecifierLooksLocal2(codeImport.specifier);
4441
4894
  case "lua":
4442
4895
  return luaSpecifierLooksLocal(codeImport.specifier);
4443
4896
  case "zig":
@@ -6096,8 +6549,8 @@ var MARKDOWN_SEMANTIC_FRONTMATTER_KEYS = [
6096
6549
  function uniqueStrings(values) {
6097
6550
  return [...new Set(values.filter(Boolean))];
6098
6551
  }
6099
- function inferKind(mimeType, filePath) {
6100
- if (inferCodeLanguage(filePath, mimeType)) {
6552
+ function inferKind(mimeType, filePath, detectionOptions = {}) {
6553
+ if (inferCodeLanguage(filePath, mimeType, detectionOptions)) {
6101
6554
  return "code";
6102
6555
  }
6103
6556
  if (isRstFilePath(filePath)) {
@@ -6144,6 +6597,25 @@ function inferKind(mimeType, filePath) {
6144
6597
  }
6145
6598
  return "binary";
6146
6599
  }
6600
+ async function localCodeDetectionOptions(absolutePath, payloadBytes) {
6601
+ if (path12.extname(absolutePath)) {
6602
+ return {};
6603
+ }
6604
+ try {
6605
+ const stat = await fs11.stat(absolutePath);
6606
+ const executable = Boolean(stat.mode & 73);
6607
+ if (!executable) {
6608
+ return { executable: false };
6609
+ }
6610
+ const bytes = payloadBytes ?? await fs11.readFile(absolutePath);
6611
+ return {
6612
+ executable,
6613
+ content: bytes.subarray(0, 256).toString("utf8")
6614
+ };
6615
+ } catch {
6616
+ return {};
6617
+ }
6618
+ }
6147
6619
  function isRstFilePath(filePath) {
6148
6620
  const extension = path12.extname(filePath).toLowerCase();
6149
6621
  return extension === ".rst" || extension === ".rest";
@@ -7017,7 +7489,8 @@ async function collectDirectoryFiles(rootDir, inputDir, repoRoot, options) {
7017
7489
  continue;
7018
7490
  }
7019
7491
  const mimeType = guessMimeType(absolutePath);
7020
- let sourceKind = inferKind(mimeType, absolutePath);
7492
+ const detectionOptions = await localCodeDetectionOptions(absolutePath);
7493
+ let sourceKind = inferKind(mimeType, absolutePath, detectionOptions);
7021
7494
  if (sourceKind === "binary" && path12.extname(absolutePath).toLowerCase() === ".zip") {
7022
7495
  const bytes = await fs11.readFile(absolutePath);
7023
7496
  if (isSlackExportArchive(bytes)) {
@@ -7644,8 +8117,9 @@ async function prepareFileInputs(rootDir, absoluteInput, repoRoot, sourceClass)
7644
8117
  }
7645
8118
  }
7646
8119
  const mimeType = guessMimeType(absoluteInput);
7647
- const sourceKind = inferKind(mimeType, absoluteInput);
7648
- const language = inferCodeLanguage(absoluteInput, mimeType);
8120
+ const detectionOptions = await localCodeDetectionOptions(absoluteInput, payloadBytes);
8121
+ const sourceKind = inferKind(mimeType, absoluteInput, detectionOptions);
8122
+ const language = inferCodeLanguage(absoluteInput, mimeType, detectionOptions);
7649
8123
  const storedExtension = path12.extname(absoluteInput) || `.${mime.extension(mimeType) || "bin"}`;
7650
8124
  let title;
7651
8125
  let extractedText;
@@ -8077,7 +8551,8 @@ async function collectInboxAttachmentRefs(inputDir, files) {
8077
8551
  const refsBySource = /* @__PURE__ */ new Map();
8078
8552
  for (const absolutePath of files) {
8079
8553
  const mimeType = guessMimeType(absolutePath);
8080
- const sourceKind = inferKind(mimeType, absolutePath);
8554
+ const detectionOptions = await localCodeDetectionOptions(absolutePath);
8555
+ const sourceKind = inferKind(mimeType, absolutePath, detectionOptions);
8081
8556
  if (sourceKind !== "markdown" && sourceKind !== "html") {
8082
8557
  continue;
8083
8558
  }
@@ -8419,7 +8894,8 @@ async function importInbox(rootDir, inputDir) {
8419
8894
  continue;
8420
8895
  }
8421
8896
  const mimeType = guessMimeType(absolutePath);
8422
- let sourceKind = inferKind(mimeType, absolutePath);
8897
+ const detectionOptions = await localCodeDetectionOptions(absolutePath);
8898
+ let sourceKind = inferKind(mimeType, absolutePath, detectionOptions);
8423
8899
  if (sourceKind === "binary" && path12.extname(absolutePath).toLowerCase() === ".zip") {
8424
8900
  const bytes = await fs11.readFile(absolutePath);
8425
8901
  if (isSlackExportArchive(bytes)) {
@@ -10579,6 +11055,43 @@ import matter5 from "gray-matter";
10579
11055
  function uniqueStrings2(values) {
10580
11056
  return uniqueBy(values.filter(Boolean), (value) => value);
10581
11057
  }
11058
+ var GUIDED_SOURCE_MARKER_PREFIX = "<!-- swarmvault-guided-source:";
11059
+ var GUIDED_SOURCE_START_SUFFIX = ":start -->";
11060
+ var GUIDED_SOURCE_END_SUFFIX = ":end -->";
11061
+ function extractGuidedSourceBlocks(content) {
11062
+ if (!content) {
11063
+ return [];
11064
+ }
11065
+ const blocks = [];
11066
+ let cursor = 0;
11067
+ while (cursor < content.length) {
11068
+ const startIndex = content.indexOf(GUIDED_SOURCE_MARKER_PREFIX, cursor);
11069
+ if (startIndex === -1) {
11070
+ break;
11071
+ }
11072
+ const scopeEndIndex = content.indexOf(GUIDED_SOURCE_START_SUFFIX, startIndex);
11073
+ if (scopeEndIndex === -1) {
11074
+ break;
11075
+ }
11076
+ const scopeId = content.slice(startIndex + GUIDED_SOURCE_MARKER_PREFIX.length, scopeEndIndex);
11077
+ const endMarker = `${GUIDED_SOURCE_MARKER_PREFIX}${scopeId}${GUIDED_SOURCE_END_SUFFIX}`;
11078
+ const endIndex = content.indexOf(endMarker, scopeEndIndex);
11079
+ if (endIndex === -1) {
11080
+ break;
11081
+ }
11082
+ const blockEnd = endIndex + endMarker.length;
11083
+ blocks.push(content.slice(startIndex, blockEnd).trim());
11084
+ cursor = blockEnd;
11085
+ }
11086
+ return uniqueStrings2(blocks);
11087
+ }
11088
+ function appendGuidedSourceBlocks(body, existingContent) {
11089
+ const blocks = extractGuidedSourceBlocks(existingContent);
11090
+ if (!blocks.length) {
11091
+ return body;
11092
+ }
11093
+ return [body.trimEnd(), "", "## Guided Session Notes", "", ...blocks, ""].join("\n");
11094
+ }
10582
11095
  function safeFrontmatter(value) {
10583
11096
  return JSON.parse(JSON.stringify(value));
10584
11097
  }
@@ -10667,7 +11180,7 @@ function detailList(manifest, key) {
10667
11180
  const items = value.split(",").map((item) => item.trim()).filter(Boolean);
10668
11181
  return items.length ? items : void 0;
10669
11182
  }
10670
- function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutputs = [], modulePage, decorations) {
11183
+ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutputs = [], modulePage, decorations, existingContent) {
10671
11184
  const relativePath = pagePathFor("source", manifest.sourceId);
10672
11185
  const pageId = `source:${manifest.sourceId}`;
10673
11186
  const { sourceHashes, sourceSemanticHashes } = sourceHashesForManifest(manifest);
@@ -10709,61 +11222,64 @@ function buildSourcePage(manifest, analysis, schemaHash, metadata, relatedOutput
10709
11222
  schema_hash: schemaHash,
10710
11223
  ...sourceHashFrontmatter(sourceHashes, sourceSemanticHashes)
10711
11224
  };
10712
- const body = [
10713
- `# ${analysis.title}`,
10714
- "",
10715
- `Source ID: \`${manifest.sourceId}\``,
10716
- `Source Kind: \`${manifest.sourceKind}\``,
10717
- manifest.url ? `Source URL: ${manifest.url}` : `Source Path: \`${manifest.originalPath ?? manifest.storedPath}\``,
10718
- ...manifest.sourceType ? [`Source Type: \`${manifest.sourceType}\``, ""] : [""],
10719
- ...manifest.sourceClass ? [`Source Class: \`${manifest.sourceClass}\``, ""] : [],
10720
- ...manifest.sourceGroupTitle ? [`Source Group: ${manifest.sourceGroupTitle}`] : [],
10721
- ...manifest.partTitle ? [`Part: ${manifest.partIndex ?? "?"}/${manifest.partCount ?? "?"} - ${manifest.partTitle}`] : [],
10722
- ...manifest.details && Object.keys(manifest.details).length ? [
11225
+ const body = appendGuidedSourceBlocks(
11226
+ [
11227
+ `# ${analysis.title}`,
10723
11228
  "",
10724
- "## Source Details",
11229
+ `Source ID: \`${manifest.sourceId}\``,
11230
+ `Source Kind: \`${manifest.sourceKind}\``,
11231
+ manifest.url ? `Source URL: ${manifest.url}` : `Source Path: \`${manifest.originalPath ?? manifest.storedPath}\``,
11232
+ ...manifest.sourceType ? [`Source Type: \`${manifest.sourceType}\``, ""] : [""],
11233
+ ...manifest.sourceClass ? [`Source Class: \`${manifest.sourceClass}\``, ""] : [],
11234
+ ...manifest.sourceGroupTitle ? [`Source Group: ${manifest.sourceGroupTitle}`] : [],
11235
+ ...manifest.partTitle ? [`Part: ${manifest.partIndex ?? "?"}/${manifest.partCount ?? "?"} - ${manifest.partTitle}`] : [],
11236
+ ...manifest.details && Object.keys(manifest.details).length ? [
11237
+ "",
11238
+ "## Source Details",
11239
+ "",
11240
+ ...Object.entries(manifest.details).map(([key, value]) => `- ${key.replace(/_/g, " ")}: ${value}`),
11241
+ ""
11242
+ ] : [],
10725
11243
  "",
10726
- ...Object.entries(manifest.details).map(([key, value]) => `- ${key.replace(/_/g, " ")}: ${value}`),
10727
- ""
10728
- ] : [],
10729
- "",
10730
- "## Summary",
10731
- "",
10732
- analysis.summary,
10733
- "",
10734
- ...analysis.code ? [
10735
- "## Code Module",
11244
+ "## Summary",
11245
+ "",
11246
+ analysis.summary,
11247
+ "",
11248
+ ...analysis.code ? [
11249
+ "## Code Module",
11250
+ "",
11251
+ `- Language: \`${analysis.code.language}\``,
11252
+ modulePage ? `- Module Page: [[${modulePage.path.replace(/\.md$/, "")}|${modulePage.title}]]` : "- Module Page: Not generated.",
11253
+ `- Exports: ${analysis.code.exports.length ? analysis.code.exports.join(", ") : "None detected."}`,
11254
+ `- Symbols: ${analysis.code.symbols.length ? analysis.code.symbols.map((symbol) => symbol.name).join(", ") : "None detected."}`,
11255
+ analysis.code.diagnostics.length ? `- Diagnostics: ${analysis.code.diagnostics.length}` : "- Diagnostics: None.",
11256
+ ""
11257
+ ] : [],
11258
+ "## Concepts",
11259
+ "",
11260
+ ...analysis.concepts.length ? analysis.concepts.map(
11261
+ (item) => `- [[${pagePathFor("concept", slugify(item.name)).replace(/\.md$/, "")}|${item.name}]]: ${item.description}`
11262
+ ) : ["- None detected."],
11263
+ "",
11264
+ "## Entities",
11265
+ "",
11266
+ ...analysis.entities.length ? analysis.entities.map(
11267
+ (item) => `- [[${pagePathFor("entity", slugify(item.name)).replace(/\.md$/, "")}|${item.name}]]: ${item.description}`
11268
+ ) : ["- None detected."],
10736
11269
  "",
10737
- `- Language: \`${analysis.code.language}\``,
10738
- modulePage ? `- Module Page: [[${modulePage.path.replace(/\.md$/, "")}|${modulePage.title}]]` : "- Module Page: Not generated.",
10739
- `- Exports: ${analysis.code.exports.length ? analysis.code.exports.join(", ") : "None detected."}`,
10740
- `- Symbols: ${analysis.code.symbols.length ? analysis.code.symbols.map((symbol) => symbol.name).join(", ") : "None detected."}`,
10741
- analysis.code.diagnostics.length ? `- Diagnostics: ${analysis.code.diagnostics.length}` : "- Diagnostics: None.",
11270
+ "## Claims",
11271
+ "",
11272
+ ...analysis.claims.length ? analysis.claims.map((claim) => `- ${claim.text} [source:${claim.citation}]`) : ["- No claims extracted."],
11273
+ "",
11274
+ "## Questions",
11275
+ "",
11276
+ ...analysis.questions.length ? analysis.questions.map((question) => `- ${question}`) : ["- No follow-up questions yet."],
11277
+ "",
11278
+ ...relatedOutputsSection(relatedOutputs),
10742
11279
  ""
10743
- ] : [],
10744
- "## Concepts",
10745
- "",
10746
- ...analysis.concepts.length ? analysis.concepts.map(
10747
- (item) => `- [[${pagePathFor("concept", slugify(item.name)).replace(/\.md$/, "")}|${item.name}]]: ${item.description}`
10748
- ) : ["- None detected."],
10749
- "",
10750
- "## Entities",
10751
- "",
10752
- ...analysis.entities.length ? analysis.entities.map(
10753
- (item) => `- [[${pagePathFor("entity", slugify(item.name)).replace(/\.md$/, "")}|${item.name}]]: ${item.description}`
10754
- ) : ["- None detected."],
10755
- "",
10756
- "## Claims",
10757
- "",
10758
- ...analysis.claims.length ? analysis.claims.map((claim) => `- ${claim.text} [source:${claim.citation}]`) : ["- No claims extracted."],
10759
- "",
10760
- "## Questions",
10761
- "",
10762
- ...analysis.questions.length ? analysis.questions.map((question) => `- ${question}`) : ["- No follow-up questions yet."],
10763
- "",
10764
- ...relatedOutputsSection(relatedOutputs),
10765
- ""
10766
- ].join("\n");
11280
+ ].join("\n"),
11281
+ existingContent
11282
+ );
10767
11283
  return {
10768
11284
  page: {
10769
11285
  id: pageId,
@@ -10943,7 +11459,7 @@ function buildModulePage(input) {
10943
11459
  content: matter5.stringify(body, frontmatter)
10944
11460
  };
10945
11461
  }
10946
- function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHashes, sourceSemanticHashes, schemaHash, metadata, relativePath, relatedOutputs = [], decorations) {
11462
+ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHashes, sourceSemanticHashes, schemaHash, metadata, relativePath, relatedOutputs = [], decorations, existingContent) {
10947
11463
  const slug = slugify(name);
10948
11464
  const pageId = `${kind}:${slug}`;
10949
11465
  const sourceIds = sourceAnalyses.map((item) => item.sourceId);
@@ -10969,26 +11485,29 @@ function buildAggregatePage(kind, name, descriptions, sourceAnalyses, sourceHash
10969
11485
  schema_hash: schemaHash,
10970
11486
  ...sourceHashFrontmatter(sourceHashes, sourceSemanticHashes)
10971
11487
  };
10972
- const body = [
10973
- `# ${name}`,
10974
- "",
10975
- "## Summary",
10976
- "",
10977
- summary,
10978
- "",
10979
- "## Seen In",
10980
- "",
10981
- ...sourceAnalyses.map((item) => `- [[${pagePathFor("source", item.sourceId).replace(/\.md$/, "")}|${item.title}]]`),
10982
- "",
10983
- "## Source Claims",
10984
- "",
10985
- ...sourceAnalyses.flatMap(
10986
- (item) => item.claims.filter((claim) => claim.text.toLowerCase().includes(name.toLowerCase())).map((claim) => `- ${claim.text} [source:${claim.citation}]`)
10987
- ),
10988
- "",
10989
- ...relatedOutputsSection(relatedOutputs),
10990
- ""
10991
- ].join("\n");
11488
+ const body = appendGuidedSourceBlocks(
11489
+ [
11490
+ `# ${name}`,
11491
+ "",
11492
+ "## Summary",
11493
+ "",
11494
+ summary,
11495
+ "",
11496
+ "## Seen In",
11497
+ "",
11498
+ ...sourceAnalyses.map((item) => `- [[${pagePathFor("source", item.sourceId).replace(/\.md$/, "")}|${item.title}]]`),
11499
+ "",
11500
+ "## Source Claims",
11501
+ "",
11502
+ ...sourceAnalyses.flatMap(
11503
+ (item) => item.claims.filter((claim) => claim.text.toLowerCase().includes(name.toLowerCase())).map((claim) => `- ${claim.text} [source:${claim.citation}]`)
11504
+ ),
11505
+ "",
11506
+ ...relatedOutputsSection(relatedOutputs),
11507
+ ""
11508
+ ].join("\n"),
11509
+ existingContent
11510
+ );
10992
11511
  return {
10993
11512
  page: {
10994
11513
  id: pageId,
@@ -11744,7 +12263,8 @@ function buildOutputPage(input) {
11744
12263
  question: input.question,
11745
12264
  output_format: input.outputFormat,
11746
12265
  output_assets: outputAssets,
11747
- ...input.outputFormat === "slides" ? { marp: true } : {}
12266
+ ...input.outputFormat === "slides" ? { marp: true } : {},
12267
+ ...input.frontmatter ?? {}
11748
12268
  };
11749
12269
  return {
11750
12270
  page: {
@@ -11832,7 +12352,7 @@ function buildOutputPage(input) {
11832
12352
  ...input.citations.map((citation) => `- [source:${citation}]`),
11833
12353
  ""
11834
12354
  ]).join("\n"),
11835
- frontmatter
12355
+ safeFrontmatter(frontmatter)
11836
12356
  )
11837
12357
  };
11838
12358
  }
@@ -12937,7 +13457,7 @@ async function resolveImageGenerationProvider(rootDir) {
12937
13457
  if (!providerConfig) {
12938
13458
  throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
12939
13459
  }
12940
- const { createProvider: createProvider2 } = await import("./registry-XOPLQNZY.js");
13460
+ const { createProvider: createProvider2 } = await import("./registry-TYROWPR5.js");
12941
13461
  return createProvider2(preferredProviderId, providerConfig, rootDir);
12942
13462
  }
12943
13463
  async function generateOutputArtifacts(rootDir, input) {
@@ -13342,6 +13862,7 @@ function pageHashes(pages) {
13342
13862
  }
13343
13863
  async function buildManagedGraphPage(absolutePath, defaults, build) {
13344
13864
  const existingContent = await fileExists(absolutePath) ? await fs19.readFile(absolutePath, "utf8") : null;
13865
+ let carriedContent = existingContent;
13345
13866
  let existing = await loadExistingManagedPageState(absolutePath, {
13346
13867
  status: defaults.status ?? "active",
13347
13868
  managedBy: defaults.managedBy
@@ -13356,6 +13877,7 @@ async function buildManagedGraphPage(absolutePath, defaults, build) {
13356
13877
  status: defaults.status ?? "active",
13357
13878
  managedBy: defaults.managedBy
13358
13879
  });
13880
+ carriedContent = await fs19.readFile(candidatePath, "utf8");
13359
13881
  usedFallbackState = true;
13360
13882
  break;
13361
13883
  }
@@ -13368,13 +13890,13 @@ async function buildManagedGraphPage(absolutePath, defaults, build) {
13368
13890
  managedBy: defaults.managedBy,
13369
13891
  confidence: defaults.confidence
13370
13892
  };
13371
- let built = build(metadata);
13372
- if (existingContent && existingContent !== built.content) {
13893
+ let built = build(metadata, carriedContent);
13894
+ if (carriedContent && carriedContent !== built.content) {
13373
13895
  metadata = {
13374
13896
  ...metadata,
13375
13897
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
13376
13898
  };
13377
- built = build(metadata);
13899
+ built = build(metadata, carriedContent);
13378
13900
  }
13379
13901
  return built;
13380
13902
  }
@@ -13425,7 +13947,10 @@ async function loadAnalysesBySourceIds(paths, sourceIds) {
13425
13947
  );
13426
13948
  return analyses.filter((analysis) => Boolean(analysis?.sourceId));
13427
13949
  }
13428
- async function buildDashboardRecords(paths, graph, schemaHash, report) {
13950
+ async function buildDashboardRecords(config, paths, graph, schemaHash, report) {
13951
+ const dataviewEnabled = config.profile.dataviewBlocks;
13952
+ const profilePresets = config.profile.presets;
13953
+ const dashboardPack = config.profile.dashboardPack;
13429
13954
  const sourcePages = graph.pages.filter((page) => page.kind === "source");
13430
13955
  const reviewPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-reviews/"));
13431
13956
  const briefPages = graph.pages.filter((page) => page.kind === "output" && page.path.startsWith("outputs/source-briefs/"));
@@ -13445,6 +13970,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13445
13970
  const stagedGuideBundles = (await Promise.all(
13446
13971
  (await fs19.readdir(paths.approvalsDir, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map(async (entry) => await readJsonFile(approvalManifestPath(paths, entry.name)))
13447
13972
  )).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);
13973
+ const readerFocusPages = uniqueBy([...guidePages, ...briefPages, ...conceptPages, ...entityPages], (page) => page.id).slice(0, 8);
13974
+ const diligenceSessions = sourceSessions.filter((session) => session.status === "staged" || session.status === "awaiting_input").slice(0, 8);
13448
13975
  const dashboards = [
13449
13976
  {
13450
13977
  relativePath: "dashboards/index.md",
@@ -13462,12 +13989,17 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13462
13989
  "- [[dashboards/contradictions|Contradictions]]",
13463
13990
  "- [[dashboards/open-questions|Open Questions]]",
13464
13991
  "",
13465
- "```dataview",
13466
- "TABLE file.mtime AS updated",
13467
- 'FROM "dashboards"',
13468
- 'WHERE file.name != "index"',
13469
- "SORT file.mtime desc",
13470
- "```",
13992
+ `Profile Presets: ${profilePresets.length ? profilePresets.map((preset) => `\`${preset}\``).join(", ") : "_default_"}`,
13993
+ `Dashboard Pack: \`${dashboardPack}\``,
13994
+ ...dataviewEnabled ? [
13995
+ "",
13996
+ "```dataview",
13997
+ "TABLE file.mtime AS updated",
13998
+ 'FROM "dashboards"',
13999
+ 'WHERE file.name != "index"',
14000
+ "SORT file.mtime desc",
14001
+ "```"
14002
+ ] : [],
13471
14003
  ""
13472
14004
  ].join("\n"),
13473
14005
  {
@@ -13488,7 +14020,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13488
14020
  backlinks: [],
13489
14021
  schema_hash: schemaHash,
13490
14022
  source_hashes: {},
13491
- source_semantic_hashes: {}
14023
+ source_semantic_hashes: {},
14024
+ profile_presets: profilePresets
13492
14025
  }
13493
14026
  )
13494
14027
  },
@@ -13500,13 +14033,16 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13500
14033
  "# Recent Sources",
13501
14034
  "",
13502
14035
  ...recentSourcePages.length ? recentSourcePages.map((page) => `- ${page.updatedAt}: [[${page.path.replace(/\.md$/, "")}|${page.title}]]`) : ["- No source pages yet."],
13503
- "",
13504
- "```dataview",
13505
- "TABLE source_type, occurred_at, participants",
13506
- 'FROM "sources"',
13507
- "SORT updated_at desc",
13508
- "LIMIT 25",
13509
- "```",
14036
+ ...dashboardPack === "reader" && readerFocusPages.length ? ["", "## Reader Focus", "", ...readerFocusPages.map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`)] : [],
14037
+ ...dataviewEnabled ? [
14038
+ "",
14039
+ "```dataview",
14040
+ "TABLE source_type, occurred_at, participants",
14041
+ 'FROM "sources"',
14042
+ "SORT updated_at desc",
14043
+ "LIMIT 25",
14044
+ "```"
14045
+ ] : [],
13510
14046
  ""
13511
14047
  ].join("\n"),
13512
14048
  {
@@ -13527,7 +14063,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13527
14063
  backlinks: [],
13528
14064
  schema_hash: schemaHash,
13529
14065
  source_hashes: {},
13530
- source_semantic_hashes: {}
14066
+ source_semantic_hashes: {},
14067
+ profile_presets: profilePresets
13531
14068
  }
13532
14069
  )
13533
14070
  },
@@ -13551,13 +14088,21 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13551
14088
  (session) => `- ${session.updatedAt}: \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`
13552
14089
  )
13553
14090
  ] : [],
13554
- "",
13555
- "```dataview",
13556
- "TABLE occurred_at, source_type, participants, container_title",
13557
- 'FROM "sources"',
13558
- "SORT occurred_at desc",
13559
- "LIMIT 25",
13560
- "```",
14091
+ ...dashboardPack === "reader" && conceptPages.length ? [
14092
+ "",
14093
+ "## Thesis And Hub Pages",
14094
+ "",
14095
+ ...conceptPages.slice(0, 6).map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`)
14096
+ ] : [],
14097
+ ...dataviewEnabled ? [
14098
+ "",
14099
+ "```dataview",
14100
+ "TABLE occurred_at, source_type, participants, container_title",
14101
+ 'FROM "sources"',
14102
+ "SORT occurred_at desc",
14103
+ "LIMIT 25",
14104
+ "```"
14105
+ ] : [],
13561
14106
  ""
13562
14107
  ].join("\n"),
13563
14108
  {
@@ -13578,7 +14123,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13578
14123
  backlinks: [],
13579
14124
  schema_hash: schemaHash,
13580
14125
  source_hashes: {},
13581
- source_semantic_hashes: {}
14126
+ source_semantic_hashes: {},
14127
+ profile_presets: profilePresets
13582
14128
  }
13583
14129
  )
13584
14130
  },
@@ -13594,13 +14140,15 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13594
14140
  const sourcePage = sourcePages.find((page) => page.sourceIds.includes(manifest.sourceId));
13595
14141
  return `- ${occurredAt}: ${sourcePage ? `[[${sourcePage.path.replace(/\.md$/, "")}|${sourcePage.title}]]` : manifest.title}`;
13596
14142
  }) : ["- No timeline-aware sources yet."],
13597
- "",
13598
- "```dataview",
13599
- "TABLE occurred_at, participants, container_title",
13600
- 'FROM "sources"',
13601
- "WHERE occurred_at",
13602
- "SORT occurred_at desc",
13603
- "```",
14143
+ ...dataviewEnabled ? [
14144
+ "",
14145
+ "```dataview",
14146
+ "TABLE occurred_at, participants, container_title",
14147
+ 'FROM "sources"',
14148
+ "WHERE occurred_at",
14149
+ "SORT occurred_at desc",
14150
+ "```"
14151
+ ] : [],
13604
14152
  ""
13605
14153
  ].join("\n"),
13606
14154
  {
@@ -13621,7 +14169,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13621
14169
  backlinks: [],
13622
14170
  schema_hash: schemaHash,
13623
14171
  source_hashes: {},
13624
- source_semantic_hashes: {}
14172
+ source_semantic_hashes: {},
14173
+ profile_presets: profilePresets
13625
14174
  }
13626
14175
  )
13627
14176
  },
@@ -13643,11 +14192,14 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13643
14192
  ...stagedGuideBundles.length ? stagedGuideBundles.map(
13644
14193
  (bundle) => `- ${bundle.createdAt}: \`${bundle.approvalId}\`${bundle.title ? ` ${bundle.title}` : ""} (${bundle.entries.length} staged entr${bundle.entries.length === 1 ? "y" : "ies"})`
13645
14194
  ) : ["- No staged guided bundles right now."],
13646
- "",
13647
- "```dataview",
13648
- 'LIST FROM "outputs/source-sessions"',
13649
- "SORT file.mtime desc",
13650
- "```",
14195
+ ...dataviewEnabled ? [
14196
+ "",
14197
+ "```dataview",
14198
+ "TABLE session_status, evidence_state, canonical_targets",
14199
+ 'FROM "outputs/source-sessions"',
14200
+ "SORT file.mtime desc",
14201
+ "```"
14202
+ ] : [],
13651
14203
  ""
13652
14204
  ].join("\n"),
13653
14205
  {
@@ -13674,7 +14226,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13674
14226
  backlinks: [],
13675
14227
  schema_hash: schemaHash,
13676
14228
  source_hashes: {},
13677
- source_semantic_hashes: {}
14229
+ source_semantic_hashes: {},
14230
+ profile_presets: profilePresets
13678
14231
  }
13679
14232
  )
13680
14233
  },
@@ -13692,11 +14245,14 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13692
14245
  ...stagedGuideBundles.length ? stagedGuideBundles.map(
13693
14246
  (bundle) => `- ${bundle.createdAt}: \`${bundle.approvalId}\`${bundle.title ? ` ${bundle.title}` : ""} (${bundle.entries.length} staged entr${bundle.entries.length === 1 ? "y" : "ies"})`
13694
14247
  ) : ["- No staged guided bundles right now."],
13695
- "",
13696
- "```dataview",
13697
- 'LIST FROM "outputs/source-guides"',
13698
- "SORT file.mtime desc",
13699
- "```",
14248
+ ...dataviewEnabled ? [
14249
+ "",
14250
+ "```dataview",
14251
+ "TABLE evidence_state, canonical_targets, file.mtime AS updated",
14252
+ 'FROM "outputs/source-guides"',
14253
+ "SORT file.mtime desc",
14254
+ "```"
14255
+ ] : [],
13700
14256
  ""
13701
14257
  ].join("\n"),
13702
14258
  {
@@ -13723,7 +14279,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13723
14279
  backlinks: [],
13724
14280
  schema_hash: schemaHash,
13725
14281
  source_hashes: {},
13726
- source_semantic_hashes: {}
14282
+ source_semantic_hashes: {},
14283
+ profile_presets: profilePresets
13727
14284
  }
13728
14285
  )
13729
14286
  },
@@ -13750,12 +14307,14 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13750
14307
  "",
13751
14308
  ...sourceSessions.length ? sourceSessions.slice(0, 8).map((session) => `- \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`) : ["- No active source sessions yet."],
13752
14309
  ...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
- "```",
14310
+ ...dataviewEnabled ? [
14311
+ "",
14312
+ "```dataview",
14313
+ 'TABLE file.folder, file.mtime FROM "concepts" OR "entities"',
14314
+ "SORT file.mtime desc",
14315
+ "LIMIT 30",
14316
+ "```"
14317
+ ] : [],
13759
14318
  ""
13760
14319
  ].join("\n"),
13761
14320
  {
@@ -13784,7 +14343,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13784
14343
  backlinks: [],
13785
14344
  schema_hash: schemaHash,
13786
14345
  source_hashes: {},
13787
- source_semantic_hashes: {}
14346
+ source_semantic_hashes: {},
14347
+ profile_presets: profilePresets
13788
14348
  }
13789
14349
  )
13790
14350
  },
@@ -13807,10 +14367,21 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13807
14367
  ...[...guidePages, ...reviewPages, ...briefPages].slice(0, 12).map((page) => `- [[${page.path.replace(/\.md$/, "")}|${page.title}]]`),
13808
14368
  ""
13809
14369
  ] : [],
13810
- "```dataview",
13811
- 'LIST FROM "outputs/source-reviews" OR "outputs/source-guides"',
13812
- "SORT file.mtime desc",
13813
- "```",
14370
+ ...dashboardPack === "diligence" && diligenceSessions.length ? [
14371
+ "## Active Evidence Review Sessions",
14372
+ "",
14373
+ ...diligenceSessions.map(
14374
+ (session) => `- \`${session.status}\` [[outputs/source-sessions/${session.scopeId}|${session.scopeTitle}]]`
14375
+ ),
14376
+ ""
14377
+ ] : [],
14378
+ ...dataviewEnabled ? [
14379
+ "```dataview",
14380
+ 'TABLE evidence_state, session_status, canonical_targets FROM "outputs/source-reviews" OR "outputs/source-guides" OR "outputs/source-sessions"',
14381
+ 'WHERE evidence_state = "conflicting"',
14382
+ "SORT file.mtime desc",
14383
+ "```"
14384
+ ] : [],
13814
14385
  ""
13815
14386
  ].join("\n"),
13816
14387
  {
@@ -13831,7 +14402,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13831
14402
  backlinks: [],
13832
14403
  schema_hash: schemaHash,
13833
14404
  source_hashes: {},
13834
- source_semantic_hashes: {}
14405
+ source_semantic_hashes: {},
14406
+ profile_presets: profilePresets
13835
14407
  }
13836
14408
  )
13837
14409
  },
@@ -13849,11 +14421,13 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13849
14421
  "",
13850
14422
  ...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
14423
  ] : [],
13852
- "",
13853
- "```dataview",
13854
- 'LIST FROM "outputs/source-briefs" OR "outputs/source-reviews" OR "outputs/source-guides" OR "outputs/source-sessions"',
13855
- "SORT file.mtime desc",
13856
- "```",
14424
+ ...dataviewEnabled ? [
14425
+ "",
14426
+ "```dataview",
14427
+ 'TABLE question_state, session_status, evidence_state FROM "outputs/source-briefs" OR "outputs/source-reviews" OR "outputs/source-guides" OR "outputs/source-sessions"',
14428
+ "SORT file.mtime desc",
14429
+ "```"
14430
+ ] : [],
13857
14431
  ""
13858
14432
  ].join("\n"),
13859
14433
  {
@@ -13874,7 +14448,8 @@ async function buildDashboardRecords(paths, graph, schemaHash, report) {
13874
14448
  backlinks: [],
13875
14449
  schema_hash: schemaHash,
13876
14450
  source_hashes: {},
13877
- source_semantic_hashes: {}
14451
+ source_semantic_hashes: {},
14452
+ profile_presets: profilePresets
13878
14453
  }
13879
14454
  )
13880
14455
  }
@@ -14766,7 +15341,7 @@ async function syncVaultArtifacts(rootDir, input) {
14766
15341
  confidence: 1,
14767
15342
  compiledFrom: [manifest.sourceId]
14768
15343
  },
14769
- (metadata) => buildSourcePage(
15344
+ (metadata, existingContent) => buildSourcePage(
14770
15345
  manifest,
14771
15346
  analysis,
14772
15347
  sourceSchemaHash,
@@ -14777,7 +15352,8 @@ async function syncVaultArtifacts(rootDir, input) {
14777
15352
  projectIds: sourceProjectIds,
14778
15353
  extraTags: [...sourceCategoryTags, ...analysis.tags ?? []],
14779
15354
  sourceClass: manifest.sourceClass
14780
- }
15355
+ },
15356
+ existingContent
14781
15357
  )
14782
15358
  );
14783
15359
  records.push(sourceRecord);
@@ -14867,7 +15443,7 @@ async function syncVaultArtifacts(rootDir, input) {
14867
15443
  compiledFrom: sourceIds,
14868
15444
  statePathCandidates: fallbackPaths
14869
15445
  },
14870
- (metadata) => buildAggregatePage(
15446
+ (metadata, existingContent) => buildAggregatePage(
14871
15447
  itemKind,
14872
15448
  aggregate.name,
14873
15449
  aggregate.descriptions,
@@ -14886,7 +15462,8 @@ async function syncVaultArtifacts(rootDir, input) {
14886
15462
  ...aggregate.sourceAnalyses.map((item) => item.summary)
14887
15463
  ]),
14888
15464
  sourceClass: aggregateSourceClass2
14889
- }
15465
+ },
15466
+ existingContent
14890
15467
  )
14891
15468
  );
14892
15469
  if (promoted && previousEntry?.status === "candidate") {
@@ -14940,6 +15517,7 @@ async function syncVaultArtifacts(rootDir, input) {
14940
15517
  );
14941
15518
  const preliminaryPages = [...basePages, ...graphOrientation.records.map((record) => record.page)];
14942
15519
  const dashboardRecords = await buildDashboardRecords(
15520
+ config,
14943
15521
  paths,
14944
15522
  {
14945
15523
  ...baseGraph,
@@ -15179,6 +15757,7 @@ async function refreshIndexesAndSearch(rootDir, pages) {
15179
15757
  compileState?.generatedAt
15180
15758
  ) : { records: [], report: null };
15181
15759
  const dashboardRecords = currentGraph ? await buildDashboardRecords(
15760
+ config,
15182
15761
  paths,
15183
15762
  {
15184
15763
  ...currentGraph,
@@ -16051,21 +16630,27 @@ async function ensureObsidianWorkspace(rootDir) {
16051
16630
  ]);
16052
16631
  }
16053
16632
  async function initVault(rootDir, options = {}) {
16054
- const profile = options.profile ?? "default";
16055
- const { paths } = await initWorkspace(rootDir, { profile });
16633
+ const requestedProfile = options.profile ?? "default";
16634
+ const { config, paths } = await initWorkspace(rootDir, { profile: requestedProfile });
16635
+ const profile = config.profile;
16636
+ const isResearchProfile = profile.presets.length > 0 || profile.guidedSessionMode === "canonical_review" || profile.dataviewBlocks;
16056
16637
  await installConfiguredAgents(rootDir);
16057
16638
  const insightsIndexPath = path23.join(paths.wikiDir, "insights", "index.md");
16058
16639
  const now = (/* @__PURE__ */ new Date()).toISOString();
16059
16640
  await writeFileIfChanged(
16060
16641
  insightsIndexPath,
16061
16642
  matter9.stringify(
16062
- (profile === "personal-research" ? [
16643
+ (isResearchProfile ? [
16063
16644
  "# Insights",
16064
16645
  "",
16065
16646
  "Human-authored research notes live here.",
16066
16647
  "",
16067
16648
  "- 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.",
16649
+ ...profile.guidedSessionMode === "canonical_review" ? [
16650
+ "- Guided sessions can stage approval-queued updates for canonical pages and fall back to `wiki/insights/` when a claim still needs judgment."
16651
+ ] : [
16652
+ "- Guided sessions fall back to `wiki/insights/` for exploratory synthesis until you decide what should become canonical."
16653
+ ],
16069
16654
  "- Treat these pages as the human judgment layer for your vault.",
16070
16655
  ""
16071
16656
  ] : [
@@ -16148,16 +16733,21 @@ async function initVault(rootDir, options = {}) {
16148
16733
  if (options.obsidian) {
16149
16734
  await ensureObsidianWorkspace(rootDir);
16150
16735
  }
16151
- if (profile === "personal-research") {
16736
+ if (isResearchProfile) {
16152
16737
  await writeFileIfChanged(
16153
16738
  path23.join(paths.wikiDir, "insights", "research-playbook.md"),
16154
16739
  matter9.stringify(
16155
16740
  [
16156
- "# Personal Research Playbook",
16741
+ `# ${requestedProfile === "personal-research" ? "Personal Research Playbook" : "Research Playbook"}`,
16157
16742
  "",
16158
16743
  "- Add one source at a time with `swarmvault ingest <input> --guide` or `swarmvault source add <input> --guide`.",
16159
16744
  "- Resume a guided session with `swarmvault source session <source-id-or-session-id>` whenever you want to answer the session prompts directly.",
16160
16745
  "- Review `wiki/outputs/source-briefs/`, `wiki/outputs/source-reviews/`, `wiki/outputs/source-guides/`, and `wiki/outputs/source-sessions/` before accepting staged updates.",
16746
+ ...profile.guidedSessionMode === "canonical_review" ? ["- Use `swarmvault review show --diff` to inspect staged canonical page edits before accepting them."] : ["- Keep exploratory synthesis in `wiki/insights/` until you are ready to promote it into canonical pages."],
16747
+ ...profile.dataviewBlocks ? [
16748
+ "- Dataview-friendly fields are enabled in the dashboards, but every generated page should still read cleanly as plain markdown."
16749
+ ] : [],
16750
+ ...profile.presets.length ? [`- Active profile presets: ${profile.presets.map((preset) => `\`${preset}\``).join(", ")}.`] : [],
16161
16751
  "- Keep unresolved questions visible in `wiki/dashboards/open-questions.md`.",
16162
16752
  "- Use `swarmvault review list` and `swarmvault review show --diff` to decide what becomes canonical.",
16163
16753
  ""
@@ -16165,7 +16755,7 @@ async function initVault(rootDir, options = {}) {
16165
16755
  {
16166
16756
  page_id: "insights:research-playbook",
16167
16757
  kind: "insight",
16168
- title: "Personal Research Playbook",
16758
+ title: requestedProfile === "personal-research" ? "Personal Research Playbook" : "Research Playbook",
16169
16759
  tags: ["insight", "research", "playbook"],
16170
16760
  source_ids: [],
16171
16761
  project_ids: [],
@@ -17098,7 +17688,7 @@ async function bootstrapDemo(rootDir, input) {
17098
17688
  }
17099
17689
 
17100
17690
  // src/mcp.ts
17101
- var SERVER_VERSION = "0.6.0";
17691
+ var SERVER_VERSION = "0.6.2";
17102
17692
  async function createMcpServer(rootDir) {
17103
17693
  const server = new McpServer({
17104
17694
  name: "swarmvault",
@@ -18417,6 +19007,9 @@ var GUIDED_SESSION_QUESTIONS = [
18417
19007
  function defaultGuidedSessionQuestions() {
18418
19008
  return GUIDED_SESSION_QUESTIONS.map((question) => ({ ...question }));
18419
19009
  }
19010
+ function splitDelimitedDetail(value) {
19011
+ return value ? value.split(",").map((item) => item.trim()).filter(Boolean) : [];
19012
+ }
18420
19013
  function normalizeGuidedAnswerValue(value) {
18421
19014
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
18422
19015
  }
@@ -18445,6 +19038,40 @@ function mergeGuidedSessionQuestions(questions, answers) {
18445
19038
  function answeredGuidedSessionQuestions(questions) {
18446
19039
  return questions.filter((question) => typeof question.answer === "string" && question.answer.trim().length > 0);
18447
19040
  }
19041
+ function questionStateForSession(session) {
19042
+ return answeredGuidedSessionQuestions(session.questions).length === session.questions.length ? "answered" : "awaiting_input";
19043
+ }
19044
+ function manifestsForScope(graph, scope) {
19045
+ if (!graph) {
19046
+ return [];
19047
+ }
19048
+ const scopeSet = new Set(scope.sourceIds);
19049
+ return graph.sources.filter((manifest) => scopeSet.has(manifest.sourceId));
19050
+ }
19051
+ function scopeSourceType(scope, manifests) {
19052
+ return scope.kind ?? manifests[0]?.sourceKind ?? manifests[0]?.sourceType;
19053
+ }
19054
+ function scopeOccurredAt(manifests) {
19055
+ return manifests.map((manifest) => manifest.details?.occurred_at).filter((value) => typeof value === "string" && value.trim().length > 0).sort((left, right) => right.localeCompare(left))[0];
19056
+ }
19057
+ function scopeParticipants(manifests) {
19058
+ return uniqueStrings4(manifests.flatMap((manifest) => splitDelimitedDetail(manifest.details?.participants)));
19059
+ }
19060
+ function scopeContainerTitle(manifests) {
19061
+ return manifests.find((manifest) => manifest.details?.container_title)?.details?.container_title ?? manifests[0]?.sourceGroupTitle;
19062
+ }
19063
+ function scopeConversationId(manifests) {
19064
+ return manifests.find((manifest) => manifest.details?.conversation_id)?.details?.conversation_id;
19065
+ }
19066
+ function classifyGuidedEvidenceState(scope, targetPage, contradictions) {
19067
+ if (contradictions.length) {
19068
+ return "conflicting";
19069
+ }
19070
+ if (!targetPage) {
19071
+ return "needs_judgment";
19072
+ }
19073
+ return targetPage.sourceIds.some((sourceId) => !scope.sourceIds.includes(sourceId)) ? "reinforcing" : "new";
19074
+ }
18448
19075
  function renderDeterministicSourceReview(input) {
18449
19076
  const canonicalPages = input.sourcePages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 10);
18450
19077
  const modulePages = input.sourcePages.filter((page) => page.kind === "module").slice(0, 8);
@@ -18545,12 +19172,13 @@ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}
18545
19172
  }
18546
19173
  }
18547
19174
  async function buildSourceReviewStagedPage(rootDir, scope) {
18548
- const { paths } = await loadVaultConfig(rootDir);
19175
+ const { config, paths } = await loadVaultConfig(rootDir);
18549
19176
  const markdown = await generateSourceReviewMarkdown(rootDir, scope);
18550
19177
  if (!markdown) {
18551
19178
  throw new Error(`Could not generate a source review for ${scope.id}.`);
18552
19179
  }
18553
19180
  const graph = await readJsonFile(paths.graphPath);
19181
+ const scopeManifests = manifestsForScope(graph, scope);
18554
19182
  const relatedPages = graph ? scopedSourcePages(graph, scope.sourceIds) : [];
18555
19183
  const relatedPageIds = relatedPages.slice(0, 16).map((page) => page.id);
18556
19184
  const relatedNodeIds = graph ? scopedNodeIds(graph, scope.sourceIds).slice(0, 24) : [];
@@ -18577,13 +19205,26 @@ async function buildSourceReviewStagedPage(rootDir, scope) {
18577
19205
  compiledFrom: scope.sourceIds,
18578
19206
  managedBy: "system",
18579
19207
  confidence: 0.79
19208
+ },
19209
+ frontmatter: {
19210
+ profile_presets: config.profile.presets,
19211
+ source_type: scopeSourceType(scope, scopeManifests),
19212
+ occurred_at: scopeOccurredAt(scopeManifests),
19213
+ participants: scopeParticipants(scopeManifests),
19214
+ container_title: scopeContainerTitle(scopeManifests),
19215
+ conversation_id: scopeConversationId(scopeManifests),
19216
+ question_state: "answered",
19217
+ canonical_targets: relatedPages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 8).map((page) => page.path),
19218
+ evidence_state: findContradictionsForScope(scope, await readGraphReport(rootDir)).length ? "conflicting" : "needs_judgment"
18580
19219
  }
18581
19220
  });
18582
19221
  return { page: output.page, content: output.content };
18583
19222
  }
18584
19223
  function classifySourceGuidePageBuckets(sourcePages, scopeSourceIds) {
18585
19224
  const scopeSet = new Set(scopeSourceIds);
18586
- const canonicalPages = sourcePages.filter((page) => page.kind === "source" || page.kind === "concept" || page.kind === "entity").slice(0, 12);
19225
+ const canonicalPages = sourcePages.filter(
19226
+ (page) => (page.kind === "source" || page.kind === "concept" || page.kind === "entity") && (page.kind === "source" || page.status !== "candidate")
19227
+ ).slice(0, 12);
18587
19228
  const newPages = canonicalPages.filter((page) => page.sourceIds.every((sourceId) => scopeSet.has(sourceId))).slice(0, 6);
18588
19229
  const reinforcingPages = canonicalPages.filter((page) => page.sourceIds.some((sourceId) => !scopeSet.has(sourceId))).slice(0, 6);
18589
19230
  return { canonicalPages, newPages, reinforcingPages };
@@ -18776,13 +19417,16 @@ Entities: ${analysis.entities.map((entity) => entity.name).join(", ") || "none"}
18776
19417
  }
18777
19418
  }
18778
19419
  async function buildSourceGuideStagedPage(rootDir, scope) {
18779
- const { paths } = await loadVaultConfig(rootDir);
19420
+ const { config, paths } = await loadVaultConfig(rootDir);
18780
19421
  const markdown = await generateSourceGuideMarkdown(rootDir, scope);
18781
19422
  if (!markdown) {
18782
19423
  throw new Error(`Could not generate a source guide for ${scope.id}.`);
18783
19424
  }
18784
19425
  const graph = await readJsonFile(paths.graphPath);
19426
+ const scopeManifests = manifestsForScope(graph, scope);
18785
19427
  const relatedPages = graph ? scopedSourcePages(graph, scope.sourceIds) : [];
19428
+ const contradictions = findContradictionsForScope(scope, await readGraphReport(rootDir));
19429
+ const selectedTargets = selectGuidedTargetPages(scope, relatedPages, defaultGuidedSessionQuestions());
18786
19430
  const relatedPageIds = relatedPages.slice(0, 18).map((page) => page.id);
18787
19431
  const relatedNodeIds = graph ? scopedNodeIds(graph, scope.sourceIds).slice(0, 28) : [];
18788
19432
  const projectIds = uniqueStrings4(relatedPages.flatMap((page) => page.projectIds));
@@ -18808,6 +19452,17 @@ async function buildSourceGuideStagedPage(rootDir, scope) {
18808
19452
  compiledFrom: scope.sourceIds,
18809
19453
  managedBy: "system",
18810
19454
  confidence: 0.8
19455
+ },
19456
+ frontmatter: {
19457
+ profile_presets: config.profile.presets,
19458
+ source_type: scopeSourceType(scope, scopeManifests),
19459
+ occurred_at: scopeOccurredAt(scopeManifests),
19460
+ participants: scopeParticipants(scopeManifests),
19461
+ container_title: scopeContainerTitle(scopeManifests),
19462
+ conversation_id: scopeConversationId(scopeManifests),
19463
+ question_state: "answered",
19464
+ canonical_targets: selectedTargets.map((page) => page.path),
19465
+ evidence_state: contradictions.length ? "conflicting" : selectedTargets.some((page) => page.sourceIds.some((sourceId) => !scope.sourceIds.includes(sourceId))) ? "reinforcing" : selectedTargets.length ? "new" : "needs_judgment"
18811
19466
  }
18812
19467
  });
18813
19468
  return { page: output.page, content: output.content };
@@ -18864,12 +19519,13 @@ async function prepareGuidedSourceSession(rootDir, scope, answers) {
18864
19519
  return { session, statePath };
18865
19520
  }
18866
19521
  async function buildSourceSessionSavedPage(rootDir, scope, session) {
18867
- const { paths } = await loadVaultConfig(rootDir);
19522
+ const { config, paths } = await loadVaultConfig(rootDir);
18868
19523
  let graph = await readJsonFile(paths.graphPath);
18869
19524
  if (!graph) {
18870
19525
  await compileVault(rootDir, {});
18871
19526
  graph = await readJsonFile(paths.graphPath);
18872
19527
  }
19528
+ const scopeManifests = manifestsForScope(graph, scope);
18873
19529
  const sourcePages = graph ? scopedSourcePages(graph, scope.sourceIds) : [];
18874
19530
  const analyses = await loadSourceAnalyses(rootDir, scope.sourceIds);
18875
19531
  const report = await readGraphReport(rootDir);
@@ -18883,6 +19539,9 @@ async function buildSourceSessionSavedPage(rootDir, scope, session) {
18883
19539
  ]);
18884
19540
  const relatedNodeIds = graph ? scopedNodeIds(graph, scope.sourceIds).slice(0, 28) : [];
18885
19541
  const projectIds = uniqueStrings4(sourcePages.flatMap((page) => page.projectIds));
19542
+ const evidenceState = contradictions.length > 0 ? "conflicting" : session.targetedPagePaths.some(
19543
+ (targetPath) => sourcePages.some((page) => page.path === targetPath && page.sourceIds.some((sourceId) => !scope.sourceIds.includes(sourceId)))
19544
+ ) ? "reinforcing" : session.targetedPagePaths.length ? "new" : "needs_judgment";
18886
19545
  const relativeBriefPath = session.briefPath && path26.isAbsolute(session.briefPath) ? path26.relative(paths.wikiDir, session.briefPath) : session.briefPath;
18887
19546
  const sessionMarkdown = [
18888
19547
  `# Guided Session: ${scope.title}`,
@@ -18947,6 +19606,18 @@ async function buildSourceSessionSavedPage(rootDir, scope, session) {
18947
19606
  compiledFrom: scope.sourceIds,
18948
19607
  managedBy: "system",
18949
19608
  confidence: 0.81
19609
+ },
19610
+ frontmatter: {
19611
+ profile_presets: config.profile.presets,
19612
+ source_type: scopeSourceType(scope, scopeManifests),
19613
+ occurred_at: scopeOccurredAt(scopeManifests),
19614
+ participants: scopeParticipants(scopeManifests),
19615
+ container_title: scopeContainerTitle(scopeManifests),
19616
+ conversation_id: scopeConversationId(scopeManifests),
19617
+ session_status: session.status,
19618
+ question_state: questionStateForSession(session),
19619
+ canonical_targets: session.targetedPagePaths,
19620
+ evidence_state: evidenceState
18950
19621
  }
18951
19622
  });
18952
19623
  return { page: output.page, content: output.content };
@@ -18959,8 +19630,8 @@ async function persistSourceSessionPage(rootDir, scope, session) {
18959
19630
  await fs22.writeFile(absolutePath, output.content, "utf8");
18960
19631
  return { pageId: output.page.id, sessionPath: absolutePath };
18961
19632
  }
18962
- async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
18963
- const { paths } = await loadVaultConfig(rootDir);
19633
+ async function buildGuidedUpdatePages(rootDir, scope, session) {
19634
+ const { config, paths } = await loadVaultConfig(rootDir);
18964
19635
  let graph = await readJsonFile(paths.graphPath);
18965
19636
  if (!graph) {
18966
19637
  await compileVault(rootDir, {});
@@ -18970,14 +19641,20 @@ async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
18970
19641
  return [];
18971
19642
  }
18972
19643
  const sourcePages = scopedSourcePages(graph, scope.sourceIds);
19644
+ const scopeManifests = manifestsForScope(graph, scope);
18973
19645
  const analyses = await loadSourceAnalyses(rootDir, scope.sourceIds);
18974
19646
  const report = await readGraphReport(rootDir);
18975
19647
  const contradictions = findContradictionsForScope(scope, report);
18976
19648
  const selectedTargets = selectGuidedTargetPages(scope, sourcePages, session.questions);
18977
- const targetPages = selectedTargets.length ? selectedTargets : [null];
19649
+ const useCanonicalTargets = config.profile.guidedSessionMode === "canonical_review" && selectedTargets.length > 0;
19650
+ const targetPages = useCanonicalTargets ? selectedTargets : [selectedTargets[0] ?? null];
19651
+ session.targetedPagePaths = uniqueStrings4(
19652
+ useCanonicalTargets ? selectedTargets.map((page) => page.path) : selectedTargets.length ? selectedTargets.map((page) => page.path) : session.targetedPagePaths
19653
+ );
18978
19654
  return await Promise.all(
18979
- targetPages.map(async (targetPage, index) => {
18980
- const relativePath = targetPage ? insightRelativePathForTarget(targetPage, scope) : `insights/topics/${slugify(scope.title)}.md`;
19655
+ targetPages.map(async (targetPage) => {
19656
+ const evidenceState = classifyGuidedEvidenceState(scope, targetPage, contradictions);
19657
+ const relativePath = useCanonicalTargets && targetPage ? targetPage.path : targetPage ? insightRelativePathForTarget(targetPage, scope) : `insights/topics/${slugify(scope.title)}.md`;
18981
19658
  const absolutePath = path26.join(paths.wikiDir, relativePath);
18982
19659
  const existingContent = await fileExists(absolutePath) ? await fs22.readFile(absolutePath, "utf8") : "";
18983
19660
  const parsed = existingContent ? matter10(existingContent) : { data: {}, content: "" };
@@ -18987,8 +19664,13 @@ async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
18987
19664
  const existingNodeIds = Array.isArray(existingData.node_ids) ? existingData.node_ids.filter((value) => typeof value === "string") : [];
18988
19665
  const existingBacklinks = Array.isArray(existingData.backlinks) ? existingData.backlinks.filter((value) => typeof value === "string") : [];
18989
19666
  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");
19667
+ const title = typeof existingData.title === "string" && existingData.title.trim() || (useCanonicalTargets && targetPage ? targetPage.title : targetPage ? insightTitleForTarget(targetPage, scope) : `${scope.title} Notes`);
19668
+ const baseBody = parsed.content.trim() ? parsed.content.trim() : [
19669
+ `# ${title}`,
19670
+ "",
19671
+ useCanonicalTargets ? "Canonical page maintained by SwarmVault. Guided sessions stage replaceable update blocks here for approval." : "Human-curated insight page. Guided sessions stage replaceable update blocks here.",
19672
+ ""
19673
+ ].join("\n");
18992
19674
  const importance = questionAnswer(
18993
19675
  session.questions,
18994
19676
  "importance",
@@ -19008,6 +19690,7 @@ async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
19008
19690
  const updateBlock = [
19009
19691
  `## Guided Session Update: ${scope.title}`,
19010
19692
  "",
19693
+ `Evidence State: \`${evidenceState}\``,
19011
19694
  `Session: [[outputs/source-sessions/${scope.id}|Guided Session]]`,
19012
19695
  `Source Guide: [[outputs/source-guides/${scope.id}|Source Guide]]`,
19013
19696
  "",
@@ -19035,48 +19718,60 @@ async function buildGuidedInsightUpdatePages(rootDir, scope, session) {
19035
19718
  ""
19036
19719
  ].join("\n");
19037
19720
  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
- });
19721
+ const content = matter10.stringify(
19722
+ `${nextBody.trimEnd()}
19723
+ `,
19724
+ JSON.parse(
19725
+ JSON.stringify({
19726
+ ...existingData,
19727
+ page_id: typeof existingData.page_id === "string" && existingData.page_id.trim() || (useCanonicalTargets && targetPage ? targetPage.id : `insight:${slugify(relativePath.replace(/\.md$/, ""))}`),
19728
+ kind: useCanonicalTargets && targetPage ? targetPage.kind : "insight",
19729
+ title,
19730
+ tags: uniqueStrings4([
19731
+ ...Array.isArray(existingData.tags) ? existingData.tags.filter((value) => typeof value === "string") : [],
19732
+ ...useCanonicalTargets ? ["guided-session", `guided/${targetPage?.kind ?? "page"}`] : insightTagsForTarget(targetPage)
19733
+ ]),
19734
+ source_ids: uniqueStrings4([...existingSourceIds, ...scope.sourceIds]),
19735
+ project_ids: uniqueStrings4([...existingProjectIds, ...targetPage?.projectIds ?? []]),
19736
+ node_ids: uniqueStrings4([...existingNodeIds, ...targetPage?.nodeIds ?? []]),
19737
+ freshness: "fresh",
19738
+ status: existingData.status === "archived" ? "archived" : "active",
19739
+ confidence: 0.83,
19740
+ created_at: createdAt,
19741
+ updated_at: (/* @__PURE__ */ new Date()).toISOString(),
19742
+ compiled_from: uniqueStrings4([
19743
+ ...Array.isArray(existingData.compiled_from) ? existingData.compiled_from.filter((value) => typeof value === "string") : [],
19744
+ ...scope.sourceIds
19745
+ ]),
19746
+ managed_by: typeof existingData.managed_by === "string" && (existingData.managed_by === "human" || existingData.managed_by === "system") ? existingData.managed_by : useCanonicalTargets ? "system" : "human",
19747
+ backlinks: uniqueStrings4([
19748
+ ...existingBacklinks,
19749
+ ...targetPage ? [targetPage.id] : [],
19750
+ `output:source-sessions/${scope.id}`,
19751
+ `output:source-guides/${scope.id}`
19752
+ ]),
19753
+ schema_hash: typeof existingData.schema_hash === "string" ? existingData.schema_hash : "",
19754
+ source_hashes: existingData.source_hashes && typeof existingData.source_hashes === "object" ? existingData.source_hashes : {},
19755
+ source_semantic_hashes: existingData.source_semantic_hashes && typeof existingData.source_semantic_hashes === "object" ? existingData.source_semantic_hashes : {},
19756
+ profile_presets: config.profile.presets,
19757
+ source_type: scopeSourceType(scope, scopeManifests),
19758
+ occurred_at: scopeOccurredAt(scopeManifests),
19759
+ participants: scopeParticipants(scopeManifests),
19760
+ container_title: scopeContainerTitle(scopeManifests),
19761
+ conversation_id: scopeConversationId(scopeManifests),
19762
+ session_status: session.status,
19763
+ question_state: questionStateForSession(session),
19764
+ canonical_targets: useCanonicalTargets ? selectedTargets.map((page2) => page2.path) : [],
19765
+ evidence_state: evidenceState
19766
+ })
19767
+ )
19768
+ );
19071
19769
  const page = parseStoredPage(relativePath, content, {
19072
19770
  createdAt,
19073
19771
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
19074
19772
  });
19075
- if (index === 0) {
19076
- session.targetedPagePaths = uniqueStrings4([
19077
- ...session.targetedPagePaths,
19078
- ...selectedTargets.length ? selectedTargets.map((page2) => page2.path) : [relativePath]
19079
- ]);
19773
+ if (!useCanonicalTargets && !selectedTargets.length) {
19774
+ session.targetedPagePaths = uniqueStrings4([...session.targetedPagePaths, relativePath]);
19080
19775
  }
19081
19776
  return { page, content, label: "guided-update" };
19082
19777
  })
@@ -19116,7 +19811,7 @@ async function stageSourceGuideForScope(rootDir, scope, options = {}) {
19116
19811
  ...scope,
19117
19812
  briefPath
19118
19813
  });
19119
- const guidedUpdates = await buildGuidedInsightUpdatePages(rootDir, scope, session);
19814
+ const guidedUpdates = await buildGuidedUpdatePages(rootDir, scope, session);
19120
19815
  session.stagedUpdatePaths = guidedUpdates.map((item) => item.page.path);
19121
19816
  const approval = await stageGeneratedOutputPages(
19122
19817
  rootDir,