@vibgrate/cli 2026.825.2 → 2026.829.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/DOCS.md +204 -9
  2. package/README.md +2 -0
  3. package/dist/{agent-DHQYEHVW.js → agent-5GW7C7EB.js} +14 -14
  4. package/dist/{agent-DHQYEHVW.js.map → agent-5GW7C7EB.js.map} +1 -1
  5. package/dist/{approvals-KBM72NU2.js → approvals-ISJFILVK.js} +5 -5
  6. package/dist/{approvals-KBM72NU2.js.map → approvals-ISJFILVK.js.map} +1 -1
  7. package/dist/{attach-O74NL4M5.js → attach-JUSALQ75.js} +3 -3
  8. package/dist/{attach-O74NL4M5.js.map → attach-JUSALQ75.js.map} +1 -1
  9. package/dist/baseline-YL2IZZ4Y.js +9 -0
  10. package/dist/{baseline-4X6MQBDA.js.map → baseline-YL2IZZ4Y.js.map} +1 -1
  11. package/dist/{chunk-JAEHLTVX.js → chunk-5RW5PIBH.js} +3 -3
  12. package/dist/{chunk-JAEHLTVX.js.map → chunk-5RW5PIBH.js.map} +1 -1
  13. package/dist/{chunk-TT2J2TB6.js → chunk-65YN3BG3.js} +1207 -40
  14. package/dist/chunk-65YN3BG3.js.map +1 -0
  15. package/dist/{chunk-VMPKOMHG.js → chunk-B5VCPIKT.js} +7 -6
  16. package/dist/chunk-B5VCPIKT.js.map +1 -0
  17. package/dist/{chunk-FQHWPOTS.js → chunk-BA6YBVNT.js} +3 -3
  18. package/dist/{chunk-FQHWPOTS.js.map → chunk-BA6YBVNT.js.map} +1 -1
  19. package/dist/{chunk-3E7QT4NE.js → chunk-BODXEZEY.js} +9 -9
  20. package/dist/{chunk-3E7QT4NE.js.map → chunk-BODXEZEY.js.map} +1 -1
  21. package/dist/{chunk-BICZR6UJ.js → chunk-D3SV3JWB.js} +3 -3
  22. package/dist/{chunk-BICZR6UJ.js.map → chunk-D3SV3JWB.js.map} +1 -1
  23. package/dist/chunk-EGMBHPXV.js +127 -0
  24. package/dist/chunk-EGMBHPXV.js.map +1 -0
  25. package/dist/{chunk-DIZ5KI5Q.js → chunk-FHSEK64W.js} +7 -7
  26. package/dist/{chunk-DIZ5KI5Q.js.map → chunk-FHSEK64W.js.map} +1 -1
  27. package/dist/{chunk-E3XVIFSH.js → chunk-FKCN653F.js} +3 -3
  28. package/dist/{chunk-E3XVIFSH.js.map → chunk-FKCN653F.js.map} +1 -1
  29. package/dist/{chunk-OIUVWCKM.js → chunk-FPIMNVLI.js} +12 -4
  30. package/dist/chunk-FPIMNVLI.js.map +1 -0
  31. package/dist/{chunk-NS4DL3QR.js → chunk-HHMWE52J.js} +10 -135
  32. package/dist/chunk-HHMWE52J.js.map +1 -0
  33. package/dist/{chunk-5UG4UHKU.js → chunk-HUJZO4K5.js} +281 -106
  34. package/dist/chunk-HUJZO4K5.js.map +1 -0
  35. package/dist/{chunk-HFQIYM6E.js → chunk-JWQ2JCQS.js} +4 -4
  36. package/dist/{chunk-HFQIYM6E.js.map → chunk-JWQ2JCQS.js.map} +1 -1
  37. package/dist/{chunk-27TS2AUJ.js → chunk-K7QR7U3V.js} +12 -11
  38. package/dist/chunk-K7QR7U3V.js.map +1 -0
  39. package/dist/{chunk-IJVWKZRS.js → chunk-KCKG3EEJ.js} +3 -3
  40. package/dist/{chunk-IJVWKZRS.js.map → chunk-KCKG3EEJ.js.map} +1 -1
  41. package/dist/{chunk-GWSJYDK7.js → chunk-MMIIVRQC.js} +7 -7
  42. package/dist/chunk-MMIIVRQC.js.map +1 -0
  43. package/dist/chunk-N6R4XPLX.js +27 -0
  44. package/dist/chunk-N6R4XPLX.js.map +1 -0
  45. package/dist/{chunk-GR7SFCQJ.js → chunk-NQQT75AN.js} +77 -27
  46. package/dist/chunk-NQQT75AN.js.map +1 -0
  47. package/dist/{chunk-6MIJLO5B.js → chunk-NSC7ZK62.js} +3 -3
  48. package/dist/{chunk-6MIJLO5B.js.map → chunk-NSC7ZK62.js.map} +1 -1
  49. package/dist/{chunk-SYMJSRYF.js → chunk-OAYSRM7J.js} +12 -14
  50. package/dist/chunk-OAYSRM7J.js.map +1 -0
  51. package/dist/{chunk-L7GCJNDT.js → chunk-QMROD7MI.js} +15 -8
  52. package/dist/chunk-QMROD7MI.js.map +1 -0
  53. package/dist/{chunk-SHD5TCZ5.js → chunk-R2FX4USU.js} +7 -7
  54. package/dist/chunk-R2FX4USU.js.map +1 -0
  55. package/dist/{chunk-7M4E7UGX.js → chunk-RL7JYG3D.js} +3 -3
  56. package/dist/{chunk-7M4E7UGX.js.map → chunk-RL7JYG3D.js.map} +1 -1
  57. package/dist/{chunk-QLNJ3VWO.js → chunk-RRSUNTZI.js} +3 -3
  58. package/dist/{chunk-QLNJ3VWO.js.map → chunk-RRSUNTZI.js.map} +1 -1
  59. package/dist/{chunk-NZES47ST.js → chunk-TWFPHXPN.js} +3 -3
  60. package/dist/{chunk-NZES47ST.js.map → chunk-TWFPHXPN.js.map} +1 -1
  61. package/dist/chunk-UGRUG2FA.js +6 -0
  62. package/dist/{chunk-G3ACLBMG.js.map → chunk-UGRUG2FA.js.map} +1 -1
  63. package/dist/{chunk-KYM55VZX.js → chunk-VOEEYCR3.js} +6 -6
  64. package/dist/{chunk-KYM55VZX.js.map → chunk-VOEEYCR3.js.map} +1 -1
  65. package/dist/{chunk-SIXWWQ6S.js → chunk-WBDRBP22.js} +4 -4
  66. package/dist/{chunk-SIXWWQ6S.js.map → chunk-WBDRBP22.js.map} +1 -1
  67. package/dist/{chunk-K3SXWOTT.js → chunk-YL332BU2.js} +20 -15
  68. package/dist/chunk-YL332BU2.js.map +1 -0
  69. package/dist/{chunk-2NUS5BOR.js → chunk-ZQY5TWCB.js} +3 -3
  70. package/dist/{chunk-2NUS5BOR.js.map → chunk-ZQY5TWCB.js.map} +1 -1
  71. package/dist/cli.d.ts +16 -1
  72. package/dist/cli.js +2362 -342
  73. package/dist/cli.js.map +1 -1
  74. package/dist/{daemon-RZS5FPIW.js → daemon-NRIIDMX2.js} +10 -10
  75. package/dist/{daemon-RZS5FPIW.js.map → daemon-NRIIDMX2.js.map} +1 -1
  76. package/dist/embed-worker-main.js +3 -3
  77. package/dist/{ensure-map-DL2S774J.js → ensure-map-VAIYCCEJ.js} +17 -16
  78. package/dist/{ensure-map-DL2S774J.js.map → ensure-map-VAIYCCEJ.js.map} +1 -1
  79. package/dist/explain-EXPJTCB5.js +126 -0
  80. package/dist/explain-EXPJTCB5.js.map +1 -0
  81. package/dist/{graph-backend-JXARVT3R.js → graph-backend-V5A2H5ZB.js} +7 -7
  82. package/dist/{graph-backend-JXARVT3R.js.map → graph-backend-V5A2H5ZB.js.map} +1 -1
  83. package/dist/index.d.ts +217 -13
  84. package/dist/index.js +17 -16
  85. package/dist/index.js.map +1 -1
  86. package/dist/{interactive-2XRBRFRB.js → interactive-VQM2CTE2.js} +37 -32
  87. package/dist/interactive-VQM2CTE2.js.map +1 -0
  88. package/dist/load-UAVA732M.js +11 -0
  89. package/dist/{load-7C5VETRD.js.map → load-UAVA732M.js.map} +1 -1
  90. package/dist/parse-worker.js +2 -2
  91. package/dist/{rules-ASYEUNB5.js → rules-TLRGB5L4.js} +12 -4
  92. package/dist/rules-TLRGB5L4.js.map +1 -0
  93. package/dist/{run-outcome-TMB5TJNA.js → run-outcome-EATWIKLR.js} +5 -5
  94. package/dist/{run-outcome-TMB5TJNA.js.map → run-outcome-EATWIKLR.js.map} +1 -1
  95. package/dist/{runtime-session-Y23NVY7R.js → runtime-session-Y2BRBXUW.js} +9 -9
  96. package/dist/{runtime-session-Y23NVY7R.js.map → runtime-session-Y2BRBXUW.js.map} +1 -1
  97. package/dist/{session-KXT2ZTPE.js → session-N2FTYIHQ.js} +9 -9
  98. package/dist/{session-KXT2ZTPE.js.map → session-N2FTYIHQ.js.map} +1 -1
  99. package/dist/{stream-json-NW6AOE47.js → stream-json-GCZAHORX.js} +14 -14
  100. package/dist/{stream-json-NW6AOE47.js.map → stream-json-GCZAHORX.js.map} +1 -1
  101. package/dist/version-XNZ4GLMQ.js +4 -0
  102. package/dist/{version-7ABYXWOZ.js.map → version-XNZ4GLMQ.js.map} +1 -1
  103. package/dist/{vg-mcp-bridge-LXBHKEFR.js → vg-mcp-bridge-VDZWFEO2.js} +22 -11
  104. package/dist/vg-mcp-bridge-VDZWFEO2.js.map +1 -0
  105. package/dist/{vgd-RW7HCEIP.js → vgd-3A2TRNP5.js} +8 -8
  106. package/dist/vgd-3A2TRNP5.js.map +1 -0
  107. package/package.json +2 -2
  108. package/dist/baseline-4X6MQBDA.js +0 -9
  109. package/dist/chunk-27TS2AUJ.js.map +0 -1
  110. package/dist/chunk-5UG4UHKU.js.map +0 -1
  111. package/dist/chunk-G3ACLBMG.js +0 -6
  112. package/dist/chunk-GR7SFCQJ.js.map +0 -1
  113. package/dist/chunk-GWSJYDK7.js.map +0 -1
  114. package/dist/chunk-K3SXWOTT.js.map +0 -1
  115. package/dist/chunk-L7GCJNDT.js.map +0 -1
  116. package/dist/chunk-NS4DL3QR.js.map +0 -1
  117. package/dist/chunk-OIUVWCKM.js.map +0 -1
  118. package/dist/chunk-SHD5TCZ5.js.map +0 -1
  119. package/dist/chunk-SYMJSRYF.js.map +0 -1
  120. package/dist/chunk-TT2J2TB6.js.map +0 -1
  121. package/dist/chunk-VMPKOMHG.js.map +0 -1
  122. package/dist/chunk-YENM3HT7.js +0 -23
  123. package/dist/chunk-YENM3HT7.js.map +0 -1
  124. package/dist/interactive-2XRBRFRB.js.map +0 -1
  125. package/dist/load-7C5VETRD.js +0 -11
  126. package/dist/rules-ASYEUNB5.js.map +0 -1
  127. package/dist/version-7ABYXWOZ.js +0 -4
  128. package/dist/vg-mcp-bridge-LXBHKEFR.js.map +0 -1
  129. package/dist/vgd-RW7HCEIP.js.map +0 -1
@@ -1,7 +1,7 @@
1
- export { compareDaemonVersion, ensureVgd, ensureVgdSoft, registerDaemon, restartVgdIfRunning, retireWedgedVgd, startDetachedVgd, stopVgd, vgdCliVersion, vgdVersionSkew } from './chunk-DIZ5KI5Q.js';
2
- import './chunk-YENM3HT7.js';
1
+ export { compareDaemonVersion, ensureVgd, ensureVgdSoft, registerDaemon, restartVgdIfRunning, retireWedgedVgd, startDetachedVgd, stopVgd, vgdCliVersion, vgdVersionSkew } from './chunk-FHSEK64W.js';
2
+ import './chunk-N6R4XPLX.js';
3
3
  import './chunk-CT5BS56U.js';
4
- import './chunk-KYM55VZX.js';
4
+ import './chunk-VOEEYCR3.js';
5
5
  import './chunk-3LOWJSAF.js';
6
6
  import './chunk-5HYCB55P.js';
7
7
  import './chunk-IS7VTH2Q.js';
@@ -11,20 +11,20 @@ import './chunk-EZ7UC5Y5.js';
11
11
  import './chunk-DBX3DL27.js';
12
12
  import './chunk-6BEBJCK4.js';
13
13
  import './chunk-J7LKEB2R.js';
14
- import './chunk-K3SXWOTT.js';
15
- import './chunk-7M4E7UGX.js';
14
+ import './chunk-YL332BU2.js';
15
+ import './chunk-RL7JYG3D.js';
16
16
  import './chunk-VHRSG6CF.js';
17
17
  import './chunk-6H2QV5DR.js';
18
18
  import './chunk-RTURQXQL.js';
19
19
  import './chunk-6WRG7VDO.js';
20
- import './chunk-FQHWPOTS.js';
21
- import './chunk-OIUVWCKM.js';
20
+ import './chunk-BA6YBVNT.js';
21
+ import './chunk-FPIMNVLI.js';
22
22
  import './chunk-MVPRPSXU.js';
23
23
  import './chunk-O3LABX6I.js';
24
- import './chunk-G3ACLBMG.js';
24
+ import './chunk-UGRUG2FA.js';
25
25
  import './chunk-XP6UUCZZ.js';
26
26
  import './chunk-JFGYT6BI.js';
27
27
  import './chunk-XQNKCA2J.js';
28
28
  import './chunk-Z6ZWNWWR.js';
29
- //# sourceMappingURL=daemon-RZS5FPIW.js.map
30
- //# sourceMappingURL=daemon-RZS5FPIW.js.map
29
+ //# sourceMappingURL=daemon-NRIIDMX2.js.map
30
+ //# sourceMappingURL=daemon-NRIIDMX2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"daemon-RZS5FPIW.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"daemon-NRIIDMX2.js"}
@@ -1,8 +1,8 @@
1
- import { resolveEmbedModel, loadEmbedder } from './chunk-FQHWPOTS.js';
2
- import './chunk-OIUVWCKM.js';
1
+ import { resolveEmbedModel, loadEmbedder } from './chunk-BA6YBVNT.js';
2
+ import './chunk-FPIMNVLI.js';
3
3
  import './chunk-MVPRPSXU.js';
4
4
  import './chunk-O3LABX6I.js';
5
- import './chunk-G3ACLBMG.js';
5
+ import './chunk-UGRUG2FA.js';
6
6
  import './chunk-XP6UUCZZ.js';
7
7
  import './chunk-JFGYT6BI.js';
8
8
  import './chunk-XQNKCA2J.js';
@@ -1,40 +1,41 @@
1
- export { ensureCodeMap } from './chunk-HFQIYM6E.js';
2
- import './chunk-27TS2AUJ.js';
3
- import './chunk-YENM3HT7.js';
1
+ export { ensureCodeMap } from './chunk-JWQ2JCQS.js';
2
+ import './chunk-K7QR7U3V.js';
3
+ import './chunk-N6R4XPLX.js';
4
4
  import './chunk-H5Q4JUY4.js';
5
5
  import './chunk-CT5BS56U.js';
6
- import './chunk-NS4DL3QR.js';
7
- import './chunk-TT2J2TB6.js';
6
+ import './chunk-HHMWE52J.js';
7
+ import './chunk-EGMBHPXV.js';
8
+ import './chunk-65YN3BG3.js';
8
9
  import './chunk-HTLDXEHW.js';
9
- import './chunk-5UG4UHKU.js';
10
+ import './chunk-HUJZO4K5.js';
10
11
  import './chunk-VIWZ4QT7.js';
11
- import './chunk-NZES47ST.js';
12
+ import './chunk-TWFPHXPN.js';
12
13
  import './chunk-WNKGRXUA.js';
13
14
  import './chunk-57ZRSCHY.js';
14
15
  import './chunk-MS6V5XKB.js';
15
- import './chunk-IJVWKZRS.js';
16
+ import './chunk-KCKG3EEJ.js';
16
17
  import './chunk-PVNALGTG.js';
17
18
  import './chunk-CRAMOEBE.js';
18
19
  import './chunk-EZ7UC5Y5.js';
19
20
  import './chunk-A3WWRW7U.js';
20
21
  import './chunk-6BEBJCK4.js';
21
22
  import './chunk-J7LKEB2R.js';
22
- import './chunk-K3SXWOTT.js';
23
- import './chunk-7M4E7UGX.js';
23
+ import './chunk-YL332BU2.js';
24
+ import './chunk-RL7JYG3D.js';
24
25
  import './chunk-VHRSG6CF.js';
25
26
  import './chunk-6H2QV5DR.js';
26
27
  import './chunk-RTURQXQL.js';
27
- import './chunk-6MIJLO5B.js';
28
+ import './chunk-NSC7ZK62.js';
28
29
  import './chunk-T7RSQ5WD.js';
29
30
  import './chunk-6WRG7VDO.js';
30
- import './chunk-FQHWPOTS.js';
31
- import './chunk-OIUVWCKM.js';
31
+ import './chunk-BA6YBVNT.js';
32
+ import './chunk-FPIMNVLI.js';
32
33
  import './chunk-MVPRPSXU.js';
33
34
  import './chunk-O3LABX6I.js';
34
- import './chunk-G3ACLBMG.js';
35
+ import './chunk-UGRUG2FA.js';
35
36
  import './chunk-XP6UUCZZ.js';
36
37
  import './chunk-JFGYT6BI.js';
37
38
  import './chunk-XQNKCA2J.js';
38
39
  import './chunk-Z6ZWNWWR.js';
39
- //# sourceMappingURL=ensure-map-DL2S774J.js.map
40
- //# sourceMappingURL=ensure-map-DL2S774J.js.map
40
+ //# sourceMappingURL=ensure-map-VAIYCCEJ.js.map
41
+ //# sourceMappingURL=ensure-map-VAIYCCEJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"ensure-map-DL2S774J.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ensure-map-VAIYCCEJ.js"}
@@ -0,0 +1,126 @@
1
+ import { EmbeddedLlmHost } from './chunk-IASO2HCI.js';
2
+ import { ensurePackage } from './chunk-3HNPVXUK.js';
3
+ import './chunk-3LOWJSAF.js';
4
+ import './chunk-5HYCB55P.js';
5
+ import { discoverModels } from './chunk-WNKGRXUA.js';
6
+ import './chunk-57ZRSCHY.js';
7
+ import { CliError, ExitCode } from './chunk-MS6V5XKB.js';
8
+ import './chunk-EZ7UC5Y5.js';
9
+ import './chunk-XP6UUCZZ.js';
10
+ import './chunk-JFGYT6BI.js';
11
+ import './chunk-XQNKCA2J.js';
12
+ import './chunk-Z6ZWNWWR.js';
13
+
14
+ // src/review/explain.ts
15
+ var EXPLAIN_GRAMMAR = String.raw`
16
+ root ::= "{" ws "\"implications\"" ws ":" ws implications ws "," ws "\"unknowns\"" ws ":" ws strings ws "}"
17
+ implications ::= "[" ws (implication (ws "," ws implication)*)? ws "]"
18
+ implication ::= "{" ws "\"finding_id\"" ws ":" ws string ws "," ws "\"implication\"" ws ":" ws string ws "," ws "\"remediation_intent\"" ws ":" ws string ws "}"
19
+ strings ::= "[" ws (string (ws "," ws string)*)? ws "]"
20
+ string ::= "\"" ([^"\\] | "\\" ["\\/bfnrt])* "\""
21
+ ws ::= [ \t\n]*
22
+ `;
23
+ function pickExplainModel(models = discoverModels()) {
24
+ const preferred = [/qwen.*coder/i, /granite/i, /coder/i, /instruct/i];
25
+ for (const pattern of preferred) {
26
+ const hit = models.find((m) => pattern.test(m.name));
27
+ if (hit) return hit;
28
+ }
29
+ return models[0] ?? null;
30
+ }
31
+ function quantizationOf(name) {
32
+ const m = name.match(/\b(Q\d(?:_K)?(?:_[SML])?|F16|BF16|Q\d)\b/i);
33
+ return m ? m[1].toUpperCase() : null;
34
+ }
35
+ function buildPrompt(capsule, findings) {
36
+ const findingLines = [...findings.architecture_findings, ...findings.security_findings].map(
37
+ (f) => `- ${f.id} (${f.kind}, ${f.severity}): ${f.claim}`
38
+ );
39
+ return [
40
+ "Analysis capsule (facts only \u2014 every fact below was produced by a deterministic analyzer):",
41
+ JSON.stringify(capsule),
42
+ "",
43
+ "Deterministic findings:",
44
+ findingLines.join("\n") || "(none)",
45
+ "",
46
+ "For each finding, state the implication the author may not have accounted for, and the",
47
+ "intent behind a fix. Add any unknown that the facts above do not settle.",
48
+ "You are not deciding whether this change merges. Do not claim anything is secure, safe,",
49
+ "approved, or free of vulnerabilities. Cite only finding ids listed above."
50
+ ].join("\n");
51
+ }
52
+ async function explainFindings(capsule, findings, opts = {}) {
53
+ const model = opts.model ?? pickExplainModel();
54
+ if (!model) {
55
+ throw new CliError(
56
+ "`--explain` needs a local model and none was found \u2014 install one (`vg models install`) or drop `--explain` to run the deterministic review",
57
+ ExitCode.ENGINE_UNAVAILABLE
58
+ );
59
+ }
60
+ const ensured = await ensurePackage("node-llama-cpp@^3", {
61
+ consent: false,
62
+ local: opts.offline === true,
63
+ interactive: false
64
+ });
65
+ if (!ensured.module) {
66
+ throw new CliError(
67
+ "`--explain` needs the local inference binding (node-llama-cpp) and it is not installed \u2014 run `vg models install`, or drop `--explain`",
68
+ ExitCode.ENGINE_UNAVAILABLE
69
+ );
70
+ }
71
+ const host = new EmbeddedLlmHost();
72
+ host.setBinding(ensured.module);
73
+ host.setPreferGrammar(true);
74
+ await host.load(model.path);
75
+ let raw;
76
+ try {
77
+ const result = await host.generate(
78
+ [
79
+ {
80
+ role: "system",
81
+ content: "You are the explanation layer of an architecture review. You annotate deterministic findings. You never decide, never invent evidence, and never assert that code is secure."
82
+ },
83
+ { role: "user", content: buildPrompt(capsule, findings) }
84
+ ],
85
+ { grammar: EXPLAIN_GRAMMAR, requireGrammar: true, temperature: 0, maxTokens: 1024 }
86
+ );
87
+ raw = result.text;
88
+ } finally {
89
+ await host.unload();
90
+ }
91
+ return {
92
+ model: model.name,
93
+ quantization: quantizationOf(model.name),
94
+ findings: mergeExplanations(findings, raw)
95
+ };
96
+ }
97
+ function mergeExplanations(findings, raw) {
98
+ let parsed;
99
+ try {
100
+ parsed = JSON.parse(raw);
101
+ } catch {
102
+ return findings;
103
+ }
104
+ const byId = new Map((parsed.implications ?? []).map((i) => [i.finding_id, i]));
105
+ const annotate = (f) => {
106
+ const hit = byId.get(f.id);
107
+ if (!hit) return f;
108
+ return {
109
+ ...f,
110
+ claim: `${f.claim} ${hit.implication}`.trim(),
111
+ remediation: hit.remediation_intent?.trim() ? hit.remediation_intent.trim() : f.remediation,
112
+ source: "model"
113
+ };
114
+ };
115
+ const modelUnknowns = (parsed.unknowns ?? []).filter((u) => typeof u === "string" && u.trim());
116
+ return {
117
+ ...findings,
118
+ architecture_findings: findings.architecture_findings.map(annotate),
119
+ security_findings: findings.security_findings.map(annotate),
120
+ unknowns: [.../* @__PURE__ */ new Set([...findings.unknowns, ...modelUnknowns])]
121
+ };
122
+ }
123
+
124
+ export { EXPLAIN_GRAMMAR, explainFindings, mergeExplanations, pickExplainModel };
125
+ //# sourceMappingURL=explain-EXPJTCB5.js.map
126
+ //# sourceMappingURL=explain-EXPJTCB5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/review/explain.ts"],"names":[],"mappings":"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","file":"explain-EXPJTCB5.js","sourcesContent":["/**\n * `vg review --explain` — the optional local model layer (spec §1, §7).\n *\n * The model may add **implications, purpose, unsure-band judgement, and\n * remediation intent**. It may not:\n * - write a `decision` (there is nowhere to put one; the verifier rejects it)\n * - invent evidence (every citation is checked against the capsule)\n * - claim something is secure, safe, approved, or vulnerability-free\n *\n * Output is constrained at sample time by a GBNF grammar and then re-checked by\n * {@link verifyFindings}. Constrained decoding is a convenience; the verifier is\n * the contract.\n *\n * Slice 0 ships no custom weights. `--explain` runs on an already-installed\n * local coder GGUF and records that id in `versions.model`. With no local model\n * — or with the binding missing — it **fails closed** (exit 6). It never\n * silently degrades to deterministic-only while the receipt claims a model ran.\n */\n\nimport { ensurePackage } from '../code/ensure.js';\nimport { discoverModels, type LocalModel } from '../engine/models.js';\nimport { EmbeddedLlmHost } from '../runtime/llm-host/index.js';\nimport { CliError, ExitCode } from '../util/exit.js';\nimport type { AnalysisCapsule, ReviewFinding, ReviewFindings } from './schemas.js';\n\n/**\n * GBNF for the model's contribution. Note what is *absent*: no `decision`, no\n * `severity` escalation, no new evidence ids — the model annotates findings the\n * scanners already produced and adds unknowns.\n */\nexport const EXPLAIN_GRAMMAR = String.raw`\nroot ::= \"{\" ws \"\\\"implications\\\"\" ws \":\" ws implications ws \",\" ws \"\\\"unknowns\\\"\" ws \":\" ws strings ws \"}\"\nimplications ::= \"[\" ws (implication (ws \",\" ws implication)*)? ws \"]\"\nimplication ::= \"{\" ws \"\\\"finding_id\\\"\" ws \":\" ws string ws \",\" ws \"\\\"implication\\\"\" ws \":\" ws string ws \",\" ws \"\\\"remediation_intent\\\"\" ws \":\" ws string ws \"}\"\nstrings ::= \"[\" ws (string (ws \",\" ws string)*)? ws \"]\"\nstring ::= \"\\\"\" ([^\"\\\\] | \"\\\\\" [\"\\\\/bfnrt])* \"\\\"\"\nws ::= [ \\t\\n]*\n`;\n\nexport interface ExplainResult {\n /** The model id recorded in `versions.model`. */\n model: string;\n quantization: string | null;\n findings: ReviewFindings;\n}\n\n/** A local coder model suitable for `task: analysis`. */\nexport function pickExplainModel(models: LocalModel[] = discoverModels()): LocalModel | null {\n // Prefer a coder-tuned GGUF; the spec's bake-off candidates first.\n const preferred = [/qwen.*coder/i, /granite/i, /coder/i, /instruct/i];\n for (const pattern of preferred) {\n const hit = models.find((m) => pattern.test(m.name));\n if (hit) return hit;\n }\n return models[0] ?? null;\n}\n\nfunction quantizationOf(name: string): string | null {\n const m = name.match(/\\b(Q\\d(?:_K)?(?:_[SML])?|F16|BF16|Q\\d)\\b/i);\n return m ? m[1].toUpperCase() : null;\n}\n\n/**\n * The capsule as a prompt. Bounded by construction — the capsule compiler has\n * already enforced the token budget, so this is a serialization, not a packer.\n */\nfunction buildPrompt(capsule: AnalysisCapsule, findings: ReviewFindings): string {\n const findingLines = [...findings.architecture_findings, ...findings.security_findings].map(\n (f) => `- ${f.id} (${f.kind}, ${f.severity}): ${f.claim}`,\n );\n return [\n 'Analysis capsule (facts only — every fact below was produced by a deterministic analyzer):',\n JSON.stringify(capsule),\n '',\n 'Deterministic findings:',\n findingLines.join('\\n') || '(none)',\n '',\n 'For each finding, state the implication the author may not have accounted for, and the',\n 'intent behind a fix. Add any unknown that the facts above do not settle.',\n 'You are not deciding whether this change merges. Do not claim anything is secure, safe,',\n 'approved, or free of vulnerabilities. Cite only finding ids listed above.',\n ].join('\\n');\n}\n\n/**\n * Run the explain pass. Throws {@link CliError} with exit 6 when a model or the\n * inference binding is unavailable — never returns un-explained findings while\n * claiming otherwise.\n */\nexport async function explainFindings(\n capsule: AnalysisCapsule,\n findings: ReviewFindings,\n opts: { offline?: boolean; model?: LocalModel | null } = {},\n): Promise<ExplainResult> {\n const model = opts.model ?? pickExplainModel();\n if (!model) {\n throw new CliError(\n '`--explain` needs a local model and none was found — install one (`vg models install`) or drop `--explain` to run the deterministic review',\n ExitCode.ENGINE_UNAVAILABLE,\n );\n }\n\n const ensured = await ensurePackage('node-llama-cpp@^3', {\n consent: false,\n local: opts.offline === true,\n interactive: false,\n });\n if (!ensured.module) {\n throw new CliError(\n '`--explain` needs the local inference binding (node-llama-cpp) and it is not installed — run `vg models install`, or drop `--explain`',\n ExitCode.ENGINE_UNAVAILABLE,\n );\n }\n\n const host = new EmbeddedLlmHost();\n host.setBinding(ensured.module);\n host.setPreferGrammar(true);\n await host.load(model.path);\n\n let raw: string;\n try {\n const result = await host.generate(\n [\n {\n role: 'system',\n content:\n 'You are the explanation layer of an architecture review. You annotate deterministic findings. You never decide, never invent evidence, and never assert that code is secure.',\n },\n { role: 'user', content: buildPrompt(capsule, findings) },\n ],\n { grammar: EXPLAIN_GRAMMAR, requireGrammar: true, temperature: 0, maxTokens: 1024 },\n );\n raw = result.text;\n } finally {\n await host.unload();\n }\n\n return {\n model: model.name,\n quantization: quantizationOf(model.name),\n findings: mergeExplanations(findings, raw),\n };\n}\n\n/**\n * Fold the model's annotations into the findings document. Unparseable output\n * is dropped, not guessed at — the deterministic findings stand on their own,\n * and the receipt still records which model was consulted.\n */\nexport function mergeExplanations(findings: ReviewFindings, raw: string): ReviewFindings {\n let parsed: { implications?: { finding_id: string; implication: string; remediation_intent: string }[]; unknowns?: string[] };\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n return findings;\n }\n const byId = new Map((parsed.implications ?? []).map((i) => [i.finding_id, i]));\n const annotate = (f: ReviewFinding): ReviewFinding => {\n const hit = byId.get(f.id);\n if (!hit) return f;\n return {\n ...f,\n claim: `${f.claim} ${hit.implication}`.trim(),\n remediation: hit.remediation_intent?.trim() ? hit.remediation_intent.trim() : f.remediation,\n source: 'model',\n };\n };\n const modelUnknowns = (parsed.unknowns ?? []).filter((u) => typeof u === 'string' && u.trim());\n return {\n ...findings,\n architecture_findings: findings.architecture_findings.map(annotate),\n security_findings: findings.security_findings.map(annotate),\n unknowns: [...new Set([...findings.unknowns, ...modelUnknowns])],\n };\n}\n"]}
@@ -1,16 +1,16 @@
1
- export { localGraphBackend, resolveGraphBackend, vgdGraphBackend } from './chunk-JAEHLTVX.js';
1
+ export { localGraphBackend, resolveGraphBackend, vgdGraphBackend } from './chunk-5RW5PIBH.js';
2
2
  import './chunk-J7LKEB2R.js';
3
- import './chunk-K3SXWOTT.js';
3
+ import './chunk-YL332BU2.js';
4
4
  import './chunk-VHRSG6CF.js';
5
5
  import './chunk-6H2QV5DR.js';
6
- import './chunk-FQHWPOTS.js';
7
- import './chunk-OIUVWCKM.js';
6
+ import './chunk-BA6YBVNT.js';
7
+ import './chunk-FPIMNVLI.js';
8
8
  import './chunk-MVPRPSXU.js';
9
9
  import './chunk-O3LABX6I.js';
10
- import './chunk-G3ACLBMG.js';
10
+ import './chunk-UGRUG2FA.js';
11
11
  import './chunk-XP6UUCZZ.js';
12
12
  import './chunk-JFGYT6BI.js';
13
13
  import './chunk-XQNKCA2J.js';
14
14
  import './chunk-Z6ZWNWWR.js';
15
- //# sourceMappingURL=graph-backend-JXARVT3R.js.map
16
- //# sourceMappingURL=graph-backend-JXARVT3R.js.map
15
+ //# sourceMappingURL=graph-backend-V5A2H5ZB.js.map
16
+ //# sourceMappingURL=graph-backend-V5A2H5ZB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"graph-backend-JXARVT3R.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"graph-backend-V5A2H5ZB.js"}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { G as GraphNode, a as GraphEdge, A as Area, R as ResolverKind, V as VgGr
2
2
  export { e as AnalysisTier, C as Centrality, D as DerivedBy, f as EpistemicTier, g as FactConfidence, h as FactKind, i as GraphMeta, j as GraphSummaries, H as HubBlastSummary, N as NodeKind, P as Provenance, k as SUPPORTED_SCHEMA_VERSIONS, l as Span, m as SupportedSchemaVersion, T as Toolchain, U as Unknown } from './types-DHqH0XIE.js';
3
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
4
 
5
- declare const VERSION = "2026.825.2";
5
+ declare const VERSION = "2026.829.1";
6
6
 
7
7
  /**
8
8
  * Analysis stage: importance, centrality, hubs, communities, and surprise.
@@ -343,16 +343,6 @@ declare function preferInRepoGraph(env?: NodeJS.ProcessEnv): boolean;
343
343
  * overwrite another ref's on-disk map.
344
344
  */
345
345
  declare function defaultGraphPath(root: string, env?: NodeJS.ProcessEnv): string;
346
- /**
347
- * Resolve where to **read** the map from.
348
- * Order: explicit override → legacy in-repo when `VIBGRATE_GRAPH_IN_REPO` is set
349
- * → branch-keyed global (if on a git ref) → `current` global snapshot →
350
- * legacy in-repo → default write path.
351
- *
352
- * The in-repo env short-circuit matters for CI and the release benchmark: they
353
- * force portable `.vibgrate/graph.json` artifacts and must not pay a synchronous
354
- * `git rev-parse` (or prefer a leftover global snapshot) on every resolve.
355
- */
356
346
  declare function resolveGraphPath(root: string, override?: string, env?: NodeJS.ProcessEnv): string;
357
347
  declare function writeArtifacts(graph: VgGraph, options: WriteOptions): WrittenArtifacts;
358
348
 
@@ -572,11 +562,135 @@ type EmbedProgress = (done: number, total: number) => void;
572
562
  */
573
563
  declare function getNodeEmbeddings(graph: VgGraph, embedder: Embedder, root: string, onProgress?: EmbedProgress): Promise<Map<string, number[]>>;
574
564
 
565
+ interface RelevanceExpansion {
566
+ /** Single lowercase word, ready for identifier-part matching. */
567
+ term: string;
568
+ /** The question token/phrase (or topic id) that produced it. */
569
+ from: string;
570
+ /** 0..1 relative confidence; scales the expansion's scoring contribution. */
571
+ weight: number;
572
+ }
573
+ interface RelevanceTopic {
574
+ id: string;
575
+ /** 0..1, normalized within one analysis. */
576
+ score: number;
577
+ }
578
+ /** One level of a matched taxonomy path, root-first. */
579
+ interface RelevanceTaxonomyLevel {
580
+ id: string;
581
+ path: string;
582
+ /** 0..1 — never lower than the levels beneath it. */
583
+ score: number;
584
+ /** This level's own vocabulary. */
585
+ terms: string[];
586
+ }
587
+ /** A hierarchical match: the most specific node plus its ancestor chain. */
588
+ interface RelevanceTaxonomyMatch {
589
+ /** "infrastructure/networking/dns/cname" */
590
+ path: string;
591
+ levels: RelevanceTaxonomyLevel[];
592
+ score: number;
593
+ /** Absolute evidence behind the match, not relative to other matches. */
594
+ evidence: number;
595
+ /** What matched — "~" prefixes a fuzzy repair. */
596
+ via: string[];
597
+ /** The matched node's OWN vocabulary, for explaining the domain. */
598
+ terms: string[];
599
+ /** Filenames and extensions this node's work lives in, nearest first. */
600
+ files: string[];
601
+ /** Standards governing this node, current revision first. */
602
+ standards: RelevanceStandard[];
603
+ }
604
+ /** A product the ask names, including through a misspelling. */
605
+ interface RelevanceVendorMatch {
606
+ name: string;
607
+ from: string;
608
+ node?: string;
609
+ topic: string;
610
+ score: number;
611
+ /** Filenames and extensions this vendor's configuration lives in. */
612
+ files: string[];
613
+ }
614
+ /** A standard governing the matched area, at the revision the pack tracks. */
615
+ interface RelevanceStandard {
616
+ name: string;
617
+ publisher: string;
618
+ node: string;
619
+ /** "standard" or "regulation". */
620
+ kind: string;
621
+ /** Lowercase category slugs from the website's own vocabulary. */
622
+ categories: string[];
623
+ }
624
+ /** A misspelling the provider resolved. */
625
+ interface RelevanceCorrection {
626
+ from: string;
627
+ to: string;
628
+ distance: number;
629
+ }
630
+ interface RelevanceAnalysis {
631
+ version: string;
632
+ topics: RelevanceTopic[];
633
+ expansions: RelevanceExpansion[];
634
+ /** Hierarchical matches, most specific first. Absent from older providers. */
635
+ taxonomy?: RelevanceTaxonomyMatch[];
636
+ vendors?: RelevanceVendorMatch[];
637
+ corrections?: RelevanceCorrection[];
638
+ /** Every file hint the analysis implies, most specific first. */
639
+ files?: string[];
640
+ /** Standards governing what the ask is about, most specific node first. */
641
+ standards?: RelevanceStandard[];
642
+ /** Deduped lowercase category slugs across those standards. */
643
+ categories?: string[];
644
+ }
645
+ /** One graph symbol, as handed to the provider's ranker: identity and name
646
+ * material only — never source contents. */
647
+ interface RankableSymbol {
648
+ id: string;
649
+ name: string;
650
+ qualifiedName: string;
651
+ file: string;
652
+ importance: number;
653
+ }
654
+ interface RankOptions {
655
+ limit?: number;
656
+ priorQuestion?: string | null;
657
+ topicTags?: Record<string, readonly string[]> | null;
658
+ }
575
659
  interface RankedSeed {
576
660
  id: string;
577
661
  score: number;
578
662
  why: string;
579
663
  }
664
+ /** The provider's full ranking answer (schema 5), pre-sanitization. */
665
+ interface RankResult {
666
+ version: string;
667
+ hasContent: boolean;
668
+ seeds: RankedSeed[];
669
+ conceptMap: string[];
670
+ }
671
+ interface RelevanceProvider {
672
+ version(): string;
673
+ analyzeQuery(question: string): RelevanceAnalysis;
674
+ /** Optional build-time enrichment: deterministic topic tags for one node
675
+ * (path + identifier evidence). Providers without it still work. */
676
+ tagNode?(input: {
677
+ qualifiedName: string;
678
+ file: string;
679
+ }): string[];
680
+ /**
681
+ * Schema-5: rank the given symbols for one ask. When present, the module
682
+ * IS the relevance engine — the host delegates seed selection here and
683
+ * keeps only mechanical name matching as its module-less fallback. A
684
+ * provider without it is treated as no ranking engine at all.
685
+ */
686
+ rankSymbols?(question: string, symbols: RankableSymbol[], opts?: RankOptions): RankResult;
687
+ }
688
+ /**
689
+ * Load the optional relevance provider. Memoized per process; returns `null`
690
+ * when disabled, not installed, or the module fails to load or violates the
691
+ * contract — callers treat `null` as "no analysis" and proceed unchanged.
692
+ */
693
+ declare function loadRelevanceProvider(): Promise<RelevanceProvider | null>;
580
694
  /** Sanitized module ranking, ready for `queryGraph({ ranked })`. */
581
695
  interface SanitizedRank {
582
696
  version: string;
@@ -584,6 +698,27 @@ interface SanitizedRank {
584
698
  seeds: RankedSeed[];
585
699
  conceptMap: string[];
586
700
  }
701
+ /**
702
+ * Rank a question over a graph's symbols via the installed module. Returns
703
+ * `null` when no module is installed, the installed module predates the
704
+ * ranking API, or its output fails sanitization — callers fall back to the
705
+ * host's mechanical matcher and proceed unchanged. Every failure path is a
706
+ * degrade, never an error.
707
+ */
708
+ declare function rankQuestion(graph: {
709
+ nodes: Array<{
710
+ id: string;
711
+ name: string;
712
+ qualifiedName: string;
713
+ file: string;
714
+ kind: string;
715
+ importance: number;
716
+ }>;
717
+ }, question: string, opts?: {
718
+ limit?: number;
719
+ priorQuestion?: string | null;
720
+ topicTags?: Map<string, readonly string[]> | null;
721
+ }): Promise<SanitizedRank | null>;
587
722
 
588
723
  /**
589
724
  * Retrieval front-end for `vg ask` / `vg code` capsule seeds (VG-CLI-SPEC
@@ -1472,6 +1607,12 @@ interface RefreshOptions {
1472
1607
  * exists (falls back to a fresh `defaultGraphPath` resolution).
1473
1608
  */
1474
1609
  graphPath?: string;
1610
+ /**
1611
+ * Live progress during the parse phase. A refresh is silent by default —
1612
+ * callers own their surface — but `vg review`'s auto-prep needs to show a
1613
+ * bar, because there the rebuild is the thing the user is waiting on.
1614
+ */
1615
+ onParseProgress?: (done: number, total: number) => void;
1475
1616
  }
1476
1617
  type RefreshOutcome =
1477
1618
  /** Map already matches the working tree. */
@@ -2101,6 +2242,39 @@ declare function moduleInstalled(): {
2101
2242
  version?: string;
2102
2243
  };
2103
2244
 
2245
+ /**
2246
+ * Topic tags for every scorable node of THIS graph, computed through the
2247
+ * provider and cached in the graph's own sidecar. Returns `null` when no
2248
+ * provider (or none with `tagNode`) is active — callers treat that as "no
2249
+ * enrichment" and proceed unchanged.
2250
+ *
2251
+ * `graphPath` should be the path the graph was actually loaded from (the MCP
2252
+ * server and `vg ask` pass it); when omitted it is re-resolved from the root
2253
+ * with the same branch-keyed rules `loadGraph` uses, so the sidecar always
2254
+ * sits beside the graph the current workspace state resolves to.
2255
+ */
2256
+ declare function loadTopicTags(graph: VgGraph, root: string, graphPath?: string): Promise<Map<string, readonly string[]> | null>;
2257
+
2258
+ /**
2259
+ * Return only the user-authored portion of an instruction, dropping trailing
2260
+ * host appendixes (attachments, @-mention / active-editor context). Unchanged
2261
+ * when no appendix.
2262
+ */
2263
+ declare function userAskFromInstruction(instruction: string): string;
2264
+ /**
2265
+ * The ask the RANKER sees. Same as {@link userAskFromInstruction}: host
2266
+ * appendixes stripped, user text otherwise intact.
2267
+ *
2268
+ * An earlier revision also deleted scope-fence sentences ("do not change the
2269
+ * tax helper", "leave X alone") before ranking. That recovered 0 of the −5 pt
2270
+ * fenced-ask penalty it targeted (docs/graph/VG-ASK-LENGTH-CAPSULE-ANALYSIS.md
2271
+ * §7.3) and is sentence-level deletion — a negation can be a fence or the
2272
+ * defect itself. It is not shipped. The alias stays so every caller
2273
+ * (`vg code`, `vg ask`, MCP, token-bench) keeps one name for "the ranking
2274
+ * input" without a second transformation.
2275
+ */
2276
+ declare function rankingAskFrom(instruction: string): string;
2277
+
2104
2278
  /** The graph-grounded context handed to the model, plus what fed it. */
2105
2279
  interface CodeContext {
2106
2280
  instruction: string;
@@ -2354,9 +2528,36 @@ declare function sourceTokenMass(contents: Iterable<string>): number;
2354
2528
  * names (F0/F1). Does not use the relevance module.
2355
2529
  */
2356
2530
  declare function askNamesSymbol(graph: VgGraph, instruction: string): boolean;
2531
+ /**
2532
+ * @deprecated Not a shipped threshold — a compatibility shim. An earlier
2533
+ * revision used 150 as an absolute ranking-score gate; it suppressed 3 of 114
2534
+ * real measurements, all terse one-line symptom asks, two of which retrieve
2535
+ * their target. Stand-down is now `rankConfidence === 0` only. Exported at 1
2536
+ * so a harness comparing `confidence < MIN_RANK_CONFIDENCE` keeps compiling
2537
+ * and matches the shipped rule (only honest-empty is suppressed).
2538
+ */
2539
+ declare const MIN_RANK_CONFIDENCE = 1;
2540
+ /**
2541
+ * Top ranking score from a module ranking, or null when there is nothing
2542
+ * comparable to threshold — no module answered, or it returned no scored seed.
2543
+ *
2544
+ * **Zero means the module's honest-empty verdict** (`hasContent === false`):
2545
+ * the ask named nothing this repo knows. Null means "no signal at all" and
2546
+ * never suppresses. A weak but nonzero score is a real, if faint, match and
2547
+ * compiles — a terse "invoice total is wrong" scoring 113 is the most common
2548
+ * field shape there is, and silencing it is `vg code` feeling dumber.
2549
+ */
2550
+ declare function rankConfidenceOf(ranked: {
2551
+ hasContent?: boolean;
2552
+ seeds?: Array<{
2553
+ score?: number;
2554
+ }>;
2555
+ } | null | undefined): number | null;
2357
2556
  declare function capsuleMode(input: {
2358
2557
  sourceTokens: number;
2359
2558
  askNamesSymbol: boolean;
2559
+ /** Top module ranking score; 0 is the honest-empty verdict, null no signal. */
2560
+ rankConfidence?: number | null;
2360
2561
  }): CapsuleMode;
2361
2562
  interface WholeRepoFile {
2362
2563
  path: string;
@@ -2372,8 +2573,11 @@ interface WholeRepoPacket {
2372
2573
  * First-turn packet = the mapped files, not a ranked dump. Files are sorted
2373
2574
  * by path. `budget` caps the paste (default {@link WHOLE_REPO_MAX_SOURCE_TOKENS});
2374
2575
  * at least one file is always included when any exist.
2576
+ *
2577
+ * The instruction is NOT echoed into the packet — the caller sends the ask as
2578
+ * its own trailing turn, so echoing it here billed it twice per step.
2375
2579
  */
2376
- declare function buildWholeRepoPacket(instruction: string, files: WholeRepoFile[], budget?: number): WholeRepoPacket;
2580
+ declare function buildWholeRepoPacket(files: WholeRepoFile[], budget?: number): WholeRepoPacket;
2377
2581
 
2378
2582
  /**
2379
2583
  * `search_symbols` — the hybrid flashlight next to the map
@@ -2424,4 +2628,4 @@ interface SearchResult {
2424
2628
  }
2425
2629
  declare function searchSymbols(graph: VgGraph, root: string, query: string, limit: number): Promise<SearchResult>;
2426
2630
 
2427
- export { ASSISTANTS, type AnalyzeOptions, type AnalyzeResult, Area, type Assistant, type BuildCapsuleOptions, type BuildContextOptions, type BuildOptions, type BuildResult, type BuildScope, CAPSULE_COMPILER_ID, CAPSULE_RANKING_VERSION, COMPILE_MIN_SOURCE_TOKENS, type CapsuleMode, type CapsuleSummary, type CapsuleSymbolRef, type ClusterMode, type DepRecord, type DiscoverOptions, type DiscoveredFile, type Drift, type DriftInventory, type DriftNote, EdgeKind, type Embedder, type ExportContext, type ExportFormat, FREE_PACK, Fact, FileParse, GraphEdge, GraphIndex, GraphNode, GraphSource, type GraphUploadEnvelope, GroundingEdge, GroundingKind, type ImpactItem, type ImpactResult, type KnowledgePack, LANGUAGES, type LanguageDef, type LibCatalog, type LibEntry, type LibSource, type LoadEmbedderOptions, type LocalModel, type ModuleResolver, type PackEntry, type PathResult, type ProbeResult, type QueryMatch, type QueryOptions, type QueryResult, type RefreshOptions, type RefreshOutcome, ResolverKind, ResourceLimitError, type ResourceLimits, SCHEMA_VERSION, SKIP_DIRS, SKIP_FILES, type SavingsReport, type ScipDocument, type ScipIndex, type ScipOccurrence, type SearchResult, type SemanticQueryOptions, type ServeOptions, type SourceSlice, type SymbolHit, TASK_CAPSULE_SCHEMA_VERSION, TOOLS, type TaskCapsule, type TextHit, UsageError, VERSION, type VerifyResult, VgGraph, type VgTool, WHOLE_REPO_MAX_SOURCE_TOKENS, type WholeRepoFile, type WholeRepoPacket, type WriteOptions, type WrittenArtifacts, addLibrary, allLanguageIds, analyze, applyCoverage, applyStaticTestLinkage, askNamesSymbol, assistantById, buildCodeContext, buildEnvelope, buildFacts, buildGraph, buildModuleResolver, buildTaskCapsule, buildWholeRepoPacket, capsuleMode, capsuleToCodeContext, cosine, coveringTests, createServer, decodeScipIndex, defaultGraphPath, inventory as dependencyInventory, detectRunner, discover, discoverModels, driftCount, driftFor, embeddingsCached, embeddingsPath, embeddingsPathFor, enrichOnline, exportGraph, findNodes, formatForExt, getNodeEmbeddings, grammarsSourceDir, groundGraph, hasDrift, identifierParts, impactOf, installAssistant, isTestFile, langById, langForExtension, legacyGraphPath, libId, loadCatalog, loadCoverage, loadEmbedder, loadGraph, loadSnapshot, mappedFilePaths, nodeById, nodeEmbedText, parseGraph, parseJsonc, parseSource, preferInRepoGraph, probeFreshness, queryGraph, queryGraphSemantic, readDoc, readSavings, recordSaving, redactGraph, refreshIfStale, relativeResolver, moduleInstalled as relevanceModuleInstalled, renderHtml, renderReport, resolveGraphPath, resolveLib, resolveLimits, resolveOne, saveCatalog, savingsRecorded, scipEdges, searchSymbols, serializeGraph, serveStdio, shortestPath, sourceTokenMass, stableStringify, summarizeCapsule, testsToRun, uninstallAssistant, verifyDeterminism, vibgrateDir, writeArtifacts, writeSnapshot };
2631
+ export { ASSISTANTS, type AnalyzeOptions, type AnalyzeResult, Area, type Assistant, type BuildCapsuleOptions, type BuildContextOptions, type BuildOptions, type BuildResult, type BuildScope, CAPSULE_COMPILER_ID, CAPSULE_RANKING_VERSION, COMPILE_MIN_SOURCE_TOKENS, type CapsuleMode, type CapsuleSummary, type CapsuleSymbolRef, type ClusterMode, type DepRecord, type DiscoverOptions, type DiscoveredFile, type Drift, type DriftInventory, type DriftNote, EdgeKind, type Embedder, type ExportContext, type ExportFormat, FREE_PACK, Fact, FileParse, GraphEdge, GraphIndex, GraphNode, GraphSource, type GraphUploadEnvelope, GroundingEdge, GroundingKind, type ImpactItem, type ImpactResult, type KnowledgePack, LANGUAGES, type LanguageDef, type LibCatalog, type LibEntry, type LibSource, type LoadEmbedderOptions, type LocalModel, MIN_RANK_CONFIDENCE, type ModuleResolver, type PackEntry, type PathResult, type ProbeResult, type QueryMatch, type QueryOptions, type QueryResult, type RankedSeed, type RefreshOptions, type RefreshOutcome, type RelevanceProvider, ResolverKind, ResourceLimitError, type ResourceLimits, SCHEMA_VERSION, SKIP_DIRS, SKIP_FILES, type SanitizedRank, type SavingsReport, type ScipDocument, type ScipIndex, type ScipOccurrence, type SearchResult, type SemanticQueryOptions, type ServeOptions, type SourceSlice, type SymbolHit, TASK_CAPSULE_SCHEMA_VERSION, TOOLS, type TaskCapsule, type TextHit, UsageError, VERSION, type VerifyResult, VgGraph, type VgTool, WHOLE_REPO_MAX_SOURCE_TOKENS, type WholeRepoFile, type WholeRepoPacket, type WriteOptions, type WrittenArtifacts, addLibrary, allLanguageIds, analyze, applyCoverage, applyStaticTestLinkage, askNamesSymbol, assistantById, buildCodeContext, buildEnvelope, buildFacts, buildGraph, buildModuleResolver, buildTaskCapsule, buildWholeRepoPacket, capsuleMode, capsuleToCodeContext, cosine, coveringTests, createServer, decodeScipIndex, defaultGraphPath, inventory as dependencyInventory, detectRunner, discover, discoverModels, driftCount, driftFor, embeddingsCached, embeddingsPath, embeddingsPathFor, enrichOnline, exportGraph, findNodes, formatForExt, getNodeEmbeddings, grammarsSourceDir, groundGraph, hasDrift, identifierParts, impactOf, installAssistant, isTestFile, langById, langForExtension, legacyGraphPath, libId, loadCatalog, loadCoverage, loadEmbedder, loadGraph, loadRelevanceProvider, loadSnapshot, loadTopicTags, mappedFilePaths, nodeById, nodeEmbedText, parseGraph, parseJsonc, parseSource, preferInRepoGraph, probeFreshness, queryGraph, queryGraphSemantic, rankConfidenceOf, rankQuestion, rankingAskFrom, readDoc, readSavings, recordSaving, redactGraph, refreshIfStale, relativeResolver, moduleInstalled as relevanceModuleInstalled, renderHtml, renderReport, resolveGraphPath, resolveLib, resolveLimits, resolveOne, saveCatalog, savingsRecorded, scipEdges, searchSymbols, serializeGraph, serveStdio, shortestPath, sourceTokenMass, stableStringify, summarizeCapsule, testsToRun, uninstallAssistant, userAskFromInstruction, verifyDeterminism, vibgrateDir, writeArtifacts, writeSnapshot };