kirograph 0.28.1 → 1.1.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 (177) hide show
  1. package/README.md +3 -2
  2. package/dist/architecture/index.js +4 -1
  3. package/dist/architecture/index.js.map +2 -2
  4. package/dist/architecture/manifest/index.js +13 -2
  5. package/dist/architecture/manifest/index.js.map +2 -2
  6. package/dist/architecture/manifest/python.js +2 -2
  7. package/dist/architecture/manifest/python.js.map +2 -2
  8. package/dist/bin/commands/help.js +3 -1
  9. package/dist/bin/commands/help.js.map +2 -2
  10. package/dist/bin/commands/install.js +2 -1
  11. package/dist/bin/commands/install.js.map +2 -2
  12. package/dist/bin/commands/memory.js +18 -8
  13. package/dist/bin/commands/memory.js.map +2 -2
  14. package/dist/bin/commands/reachability.js +7 -2
  15. package/dist/bin/commands/reachability.js.map +2 -2
  16. package/dist/bin/commands/status.js +2 -1
  17. package/dist/bin/commands/status.js.map +2 -2
  18. package/dist/bin/commands/uninit.js +2 -1
  19. package/dist/bin/commands/uninit.js.map +2 -2
  20. package/dist/bin/commands/vulns.js +26 -6
  21. package/dist/bin/commands/vulns.js.map +2 -2
  22. package/dist/bin/commands/wiki.js +56 -0
  23. package/dist/bin/commands/wiki.js.map +2 -2
  24. package/dist/bin/installer/common.js +7 -1
  25. package/dist/bin/installer/common.js.map +2 -2
  26. package/dist/bin/installer/detect.js +10 -0
  27. package/dist/bin/installer/detect.js.map +2 -2
  28. package/dist/bin/installer/hooks.js +13 -8
  29. package/dist/bin/installer/hooks.js.map +2 -2
  30. package/dist/bin/installer/steering.js +9 -0
  31. package/dist/bin/installer/steering.js.map +2 -2
  32. package/dist/bin/installer/targets/antigravity.js +1 -1
  33. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  34. package/dist/bin/installer/targets/claude.js +1 -1
  35. package/dist/bin/installer/targets/claude.js.map +2 -2
  36. package/dist/bin/installer/targets/codex.js +1 -1
  37. package/dist/bin/installer/targets/codex.js.map +2 -2
  38. package/dist/bin/installer/targets/commandcode.js +84 -0
  39. package/dist/bin/installer/targets/commandcode.js.map +7 -0
  40. package/dist/bin/installer/targets/copilot.js +1 -1
  41. package/dist/bin/installer/targets/copilot.js.map +2 -2
  42. package/dist/bin/installer/targets/cursor.js +2 -2
  43. package/dist/bin/installer/targets/cursor.js.map +2 -2
  44. package/dist/bin/installer/targets/devin.js +1 -1
  45. package/dist/bin/installer/targets/devin.js.map +2 -2
  46. package/dist/bin/installer/targets/gemini-cli.js +1 -1
  47. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  48. package/dist/bin/installer/targets/index.js +10 -0
  49. package/dist/bin/installer/targets/index.js.map +2 -2
  50. package/dist/bin/installer/targets/opencode.js +1 -1
  51. package/dist/bin/installer/targets/opencode.js.map +2 -2
  52. package/dist/bin/installer/targets/windsurf.js +1 -1
  53. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  54. package/dist/bin/kirograph.js +1 -1
  55. package/dist/bin/kirograph.js.map +1 -1
  56. package/dist/config.js +25 -1
  57. package/dist/config.js.map +2 -2
  58. package/dist/core/pipeline.js +18 -6
  59. package/dist/core/pipeline.js.map +2 -2
  60. package/dist/extraction/extractor.js +88 -26
  61. package/dist/extraction/extractor.js.map +2 -2
  62. package/dist/extraction/grammars.js +38 -3
  63. package/dist/extraction/grammars.js.map +2 -2
  64. package/dist/extraction/notebook.js +15 -7
  65. package/dist/extraction/notebook.js.map +2 -2
  66. package/dist/extraction/wasm/tree-sitter-bash.wasm +0 -0
  67. package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
  68. package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  69. package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
  70. package/dist/extraction/wasm/tree-sitter-csharp.wasm +0 -0
  71. package/dist/extraction/wasm/tree-sitter-css.wasm +0 -0
  72. package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
  73. package/dist/extraction/wasm/tree-sitter-elisp.wasm +0 -0
  74. package/dist/extraction/wasm/tree-sitter-elixir.wasm +0 -0
  75. package/dist/extraction/wasm/tree-sitter-elm.wasm +0 -0
  76. package/dist/extraction/wasm/tree-sitter-embedded_template.wasm +0 -0
  77. package/dist/extraction/wasm/tree-sitter-embeddedtemplate.wasm +0 -0
  78. package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
  79. package/dist/extraction/wasm/tree-sitter-html.wasm +0 -0
  80. package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
  81. package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
  82. package/dist/extraction/wasm/tree-sitter-json.wasm +0 -0
  83. package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
  84. package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
  85. package/dist/extraction/wasm/tree-sitter-objc.wasm +0 -0
  86. package/dist/extraction/wasm/tree-sitter-ocaml.wasm +0 -0
  87. package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
  88. package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
  89. package/dist/extraction/wasm/tree-sitter-ql.wasm +0 -0
  90. package/dist/extraction/wasm/tree-sitter-rescript.wasm +0 -0
  91. package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
  92. package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
  93. package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
  94. package/dist/extraction/wasm/tree-sitter-solidity.wasm +0 -0
  95. package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
  96. package/dist/extraction/wasm/tree-sitter-systemrdl.wasm +0 -0
  97. package/dist/extraction/wasm/tree-sitter-tlaplus.wasm +0 -0
  98. package/dist/extraction/wasm/tree-sitter-toml.wasm +0 -0
  99. package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
  100. package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
  101. package/dist/extraction/wasm/tree-sitter-vue.wasm +0 -0
  102. package/dist/extraction/wasm/tree-sitter-yaml.wasm +0 -0
  103. package/dist/extraction/wasm/tree-sitter-zig.wasm +0 -0
  104. package/dist/frameworks/index.js +68 -7
  105. package/dist/frameworks/index.js.map +2 -2
  106. package/dist/jev/client.js +99 -0
  107. package/dist/jev/client.js.map +7 -0
  108. package/dist/jev/types.js +17 -0
  109. package/dist/jev/types.js.map +7 -0
  110. package/dist/mcp/handlers/memory.js +14 -8
  111. package/dist/mcp/handlers/memory.js.map +2 -2
  112. package/dist/mcp/handlers/security.js +5 -3
  113. package/dist/mcp/handlers/security.js.map +2 -2
  114. package/dist/mcp/tools.js +1 -1
  115. package/dist/mcp/tools.js.map +1 -1
  116. package/dist/memory/index.js +13 -1
  117. package/dist/memory/index.js.map +3 -3
  118. package/dist/memory/relation-jev.js +59 -0
  119. package/dist/memory/relation-jev.js.map +7 -0
  120. package/dist/memory/schema.js +57 -0
  121. package/dist/memory/schema.js.map +7 -0
  122. package/dist/security/auth-detection-jev.js +47 -0
  123. package/dist/security/auth-detection-jev.js.map +7 -0
  124. package/dist/security/manifest/adapter.js +34 -5
  125. package/dist/security/manifest/adapter.js.map +3 -3
  126. package/dist/security/manifest/parser.js +2 -2
  127. package/dist/security/manifest/parser.js.map +2 -2
  128. package/dist/security/manifest/plugins/cargo.js +23 -0
  129. package/dist/security/manifest/plugins/cargo.js.map +2 -2
  130. package/dist/security/manifest/plugins/composer.js +12 -0
  131. package/dist/security/manifest/plugins/composer.js.map +2 -2
  132. package/dist/security/manifest/plugins/gradle.js +12 -0
  133. package/dist/security/manifest/plugins/gradle.js.map +2 -2
  134. package/dist/security/manifest/plugins/hex.js +12 -0
  135. package/dist/security/manifest/plugins/hex.js.map +2 -2
  136. package/dist/security/manifest/plugins/maven.js +68 -1
  137. package/dist/security/manifest/plugins/maven.js.map +2 -2
  138. package/dist/security/manifest/plugins/npm.js +86 -0
  139. package/dist/security/manifest/plugins/npm.js.map +2 -2
  140. package/dist/security/manifest/plugins/nuget.js +13 -0
  141. package/dist/security/manifest/plugins/nuget.js.map +2 -2
  142. package/dist/security/manifest/plugins/pubspec.js +12 -0
  143. package/dist/security/manifest/plugins/pubspec.js.map +2 -2
  144. package/dist/security/manifest/plugins/pyproject.js +12 -0
  145. package/dist/security/manifest/plugins/pyproject.js.map +2 -2
  146. package/dist/security/manifest/plugins/rubygems.js +12 -0
  147. package/dist/security/manifest/plugins/rubygems.js.map +2 -2
  148. package/dist/security/pipeline.js +5 -2
  149. package/dist/security/pipeline.js.map +2 -2
  150. package/dist/security/reachability.js +115 -50
  151. package/dist/security/reachability.js.map +2 -2
  152. package/dist/security/types.js.map +1 -1
  153. package/dist/security/vuln/client.js +45 -1
  154. package/dist/security/vuln/client.js.map +2 -2
  155. package/dist/security/vuln/epss-client.js +1 -1
  156. package/dist/security/vuln/epss-client.js.map +1 -1
  157. package/dist/security/vuln/osv-adapter.js +144 -32
  158. package/dist/security/vuln/osv-adapter.js.map +2 -2
  159. package/dist/sync/index.js +9 -2
  160. package/dist/sync/index.js.map +2 -2
  161. package/dist/vectors/libsql-index.js +287 -0
  162. package/dist/vectors/libsql-index.js.map +7 -0
  163. package/dist/vectors/turso-index.js +307 -0
  164. package/dist/vectors/turso-index.js.map +7 -0
  165. package/dist/wiki/contradiction-jev.js +49 -0
  166. package/dist/wiki/contradiction-jev.js.map +7 -0
  167. package/dist/wiki/index.js +13 -0
  168. package/dist/wiki/index.js.map +2 -2
  169. package/dist/wiki/ingest.js +2 -0
  170. package/dist/wiki/ingest.js.map +2 -2
  171. package/dist/wiki/links.js +53 -0
  172. package/dist/wiki/links.js.map +7 -0
  173. package/dist/wiki/lint.js +3 -6
  174. package/dist/wiki/lint.js.map +2 -2
  175. package/dist/wiki/rename.js +103 -0
  176. package/dist/wiki/rename.js.map +7 -0
  177. package/package.json +3 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/commands/status.ts"],
4
- "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport { dim, reset, violet, bold, green, label, value, section, renderTable } from '../ui';\nimport { loadConfig } from '../../config';\nimport { readTurboQuantStats } from '../../vectors/turboquant-index';\n\nexport function register(program: Command): void {\n program\n .command('status [projectPath]')\n .description('Show index statistics')\n .option('--integrations', 'Show detected and configured platforms')\n .action(async (projectPath: string | undefined, opts: { integrations?: boolean }) => {\n const target = path.resolve(projectPath ?? process.cwd());\n\n if (opts.integrations) {\n await showIntegrations(target);\n return;\n }\n\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const cg = await KiroGraph.open(target);\n const stats = await cg.getStats();\n\n console.log();\n console.log(section(' Graph'));\n console.log(` ${label('Files')} ${value(String(stats.files))}`);\n console.log(` ${label('Symbols')} ${value(String(stats.nodes))}`);\n console.log(` ${label('Edges')} ${value(String(stats.edges))}`);\n\n if (stats.frameworks.length > 0) {\n console.log(` ${label('Frameworks')} ${value(stats.frameworks.join(', '))}`);\n }\n\n const kindEntries = Object.entries(stats.nodesByKind).sort((a, b) => b[1] - a[1]);\n if (kindEntries.length > 0) {\n console.log(`\\n ${label('By kind')}`);\n console.log(renderTable(kindEntries.map(([k, v]) => [k, String(v)])));\n }\n\n const langEntries = Object.entries(stats.filesByLanguage ?? {}).sort((a, b) => b[1] - a[1]);\n if (langEntries.length > 0) {\n console.log(`\\n ${label('By language')}`);\n console.log(renderTable(langEntries.map(([k, v]) => [k, String(v)])));\n }\n\n // Sync state\n const threshold = stats.syncWarningThreshold ?? 10;\n const pendingFiles: number = stats.pendingFiles ?? 0;\n const syncRunning: boolean = stats.syncRunning ?? false;\n console.log();\n console.log(section(' Sync'));\n if (syncRunning) {\n console.log(` ${'\\x1b[33m'}\u26A0 Sync is currently running in the background.${reset}`);\n } else {\n console.log(` ${label('Status')} ${dim}idle${reset}`);\n }\n if (pendingFiles > 0) {\n const warn = threshold > 0 && pendingFiles >= threshold;\n const pendingLabel = warn ? `${'\\x1b[33m'}${pendingFiles} files pending${reset}` : `${dim}${pendingFiles} files pending${reset}`;\n console.log(` ${label('Pending')} ${pendingLabel}`);\n if (warn) {\n console.log(` ${'\\x1b[33m'}\u26A0 Index may be stale. Run \\`kirograph sync\\` to update.${reset}`);\n }\n } else {\n console.log(` ${label('Pending')} ${green}up to date${reset}`);\n }\n\n console.log();\n console.log(section(' Semantic Search'));\n if (stats.embeddingsEnabled) {\n const tqStats = stats.semanticEngine === 'turboquant'\n ? readTurboQuantStats(path.join(target, '.kirograph'))\n : null;\n const engineLabel =\n stats.semanticEngine === 'turboquant' ? `turboquant ${dim}(${stats.vecIndexCount} entries \u00B7 ${tqStats ? `${tqStats.bits} bits \u00B7 ${tqStats.compressionRatio.toFixed(1)}\u00D7 compression` : 'not yet indexed'})${reset}` :\n stats.semanticEngine === 'sqlite-vec' ? `sqlite-vec ${dim}(${stats.vecIndexCount} entries in ANN index)${reset}` :\n stats.semanticEngine === 'orama' ? `orama ${dim}(hybrid \u2014 ${stats.vecIndexCount} docs in index)${reset}` :\n stats.semanticEngine === 'pglite' ? `pglite+pgvector ${dim}(hybrid \u2014 ${stats.vecIndexCount} rows in DB)${reset}` :\n stats.semanticEngine === 'lancedb' ? `lancedb ${dim}(${stats.vecIndexCount} entries in ANN index)${reset}` :\n stats.semanticEngine === 'qdrant' ? `qdrant ${dim}(${stats.vecIndexCount} points in collection)${reset}` :\n stats.semanticEngine === 'typesense' ? `typesense ${dim}(${stats.vecIndexCount} documents in collection)${reset}` :\n stats.semanticEngine === 'turbovec' ? `turbovec ${dim}(${stats.vecIndexCount} entries \u00B7 ${stats.turbovecBits ?? 4} bits \u00B7 Rust/SIMD)${reset}` :\n `in-process cosine`;\n const total = stats.embeddableNodeCount > 0 ? stats.embeddableNodeCount : stats.nodes;\n const displayed = Math.min(stats.embeddingCount, total);\n const coverage = total > 0 ? Math.min(100, Math.round((stats.embeddingCount / total) * 100)) : 0;\n console.log(` ${label('Status')} ${green}${bold}enabled${reset}`);\n console.log(` ${label('Model')} ${value(stats.embeddingModel)}`);\n console.log(` ${label('Engine')} ${violet}${engineLabel}${reset}`);\n if (stats.engineFallback) {\n console.log(` ${'\\x1b[33m'}\u26A0 engine fallback: ${stats.engineFallback}${reset}`);\n }\n console.log(` ${label('Indexed')} ${value(`${displayed} / ${total}`)} ${dim}(${coverage}%)${reset}`);\n if (tqStats) {\n const rawMB = (tqStats.rawBytes / 1_048_576).toFixed(1);\n const compMB = (tqStats.actualBytes / 1_048_576).toFixed(1);\n const savedMB = (tqStats.savedBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Raw size')} ${dim}${rawMB} MB \u2192 compressed ${compMB} MB (${savedMB} MB saved)${reset}`);\n if (tqStats.memEnabled && tqStats.memCount > 0) {\n const mRawMB = (tqStats.memRawBytes / 1_048_576).toFixed(1);\n const mCompMB = (tqStats.memActualBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Memory')} ${dim}${tqStats.memCount} observations \u2192 ${mRawMB} MB \u2192 ${mCompMB} MB${reset}`);\n }\n if (tqStats.docsEnabled && tqStats.docsCount > 0) {\n const dRawMB = (tqStats.docsRawBytes / 1_048_576).toFixed(1);\n const dCompMB = (tqStats.docsActualBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Docs')} ${dim}${tqStats.docsCount} sections \u2192 ${dRawMB} MB \u2192 ${dCompMB} MB${reset}`);\n }\n const totalSaved = tqStats.savedBytes + (tqStats.memRawBytes - tqStats.memActualBytes) + (tqStats.docsRawBytes - tqStats.docsActualBytes);\n if (totalSaved > 0) {\n console.log(` ${label('Total RAM')} ${green}${(totalSaved / 1_048_576).toFixed(1)} MB saved${reset} ${dim}(TurboQuant compression)${reset}`);\n }\n }\n } else {\n console.log(` ${label('Status')} ${dim}disabled${reset}`);\n }\n\n // Pattern SAST section\n try {\n const patConfig = await loadConfig(target);\n if (patConfig.enablePatterns) {\n const db2 = cg.getDatabase();\n (db2 as any).applyPatternsSchema?.();\n const rawDb2 = db2.getRawDb();\n const tableExists = rawDb2.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\");\n if (tableExists) {\n const matchCount = (rawDb2.get('SELECT COUNT(*) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n const fileCount = (rawDb2.get('SELECT COUNT(DISTINCT file_path) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n const ruleCount = (rawDb2.get('SELECT COUNT(DISTINCT pattern_id) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n console.log();\n console.log(section(' Patterns'));\n console.log(` ${label('Status')} ${green}${bold}enabled${reset}`);\n if (matchCount > 0) {\n console.log(` ${label('Matches')} ${value(String(matchCount))} ${dim}across ${fileCount} files, ${ruleCount} rules triggered${reset}`);\n } else {\n console.log(` ${label('Matches')} ${dim}none yet \u2014 run kirograph index${reset}`);\n }\n } else {\n console.log();\n console.log(section(' Patterns'));\n console.log(` ${label('Status')} ${green}${bold}enabled${reset} ${dim}(not yet indexed \u2014 run kirograph index)${reset}`);\n }\n }\n } catch { /* non-critical */ }\n\n // Security stats (conditional on enableSecurity)\n try {\n const config = await loadConfig(target);\n if (config.enableSecurity) {\n const db = cg.getDatabase();\n db.applySecuritySchema();\n const rawDb = db.getRawDb();\n\n const depCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_dependencies')?.cnt ?? 0;\n const vulnCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_vulnerabilities')?.cnt ?? 0;\n const affectedCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'affected'\")?.cnt ?? 0;\n const notAffectedCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'not_affected'\")?.cnt ?? 0;\n const investigatingCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'under_investigation'\")?.cnt ?? 0;\n const staleCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_dependencies WHERE vuln_data_stale = 1')?.cnt ?? 0;\n\n console.log();\n console.log(section(' \uD83D\uDD12 Security'));\n console.log(` ${label('Dependencies')} ${value(String(depCount))}`);\n console.log(` ${label('Vulnerabilities')} ${value(String(vulnCount))}`);\n\n if (vulnCount > 0) {\n const affectedLabel = affectedCount > 0\n ? `${'\\x1b[31m'}${affectedCount} affected${reset}`\n : `${dim}0 affected${reset}`;\n console.log(` ${label('Affected')} ${affectedLabel}`);\n console.log(` ${label('Not Affected')} ${dim}${notAffectedCount}${reset}`);\n console.log(` ${label('Investigating')} ${dim}${investigatingCount}${reset}`);\n }\n\n if (staleCount > 0) {\n console.log(` ${'\\x1b[33m'}\u26A0 ${staleCount} dependenc${staleCount === 1 ? 'y has' : 'ies have'} stale vulnerability data. Run \\`kirograph vulns --refresh\\` to update.${reset}`);\n }\n }\n } catch { /* non-critical */ }\n\n console.log();\n cg.close();\n });\n}\n\nasync function showIntegrations(projectRoot: string): Promise<void> {\n const fs = await import('fs');\n const { detectPlatforms } = await Promise.resolve().then(() => require('../installer/detect.js'));\n const { readJson, KIROGRAPH_SERVER_NAME } = await Promise.resolve().then(() => require('../installer/common.js'));\n\n const detected = detectPlatforms(projectRoot);\n const home = process.env.HOME || process.env.USERPROFILE || '';\n\n // Map of target \u2192 config path to check if kirograph is configured\n const configChecks: Record<string, { path: string; key: string }> = {\n 'kiro': { path: path.join(projectRoot, '.kiro', 'settings', 'mcp.json'), key: 'mcpServers' },\n 'claude': { path: path.join(projectRoot, '.mcp.json'), key: 'mcpServers' },\n 'cursor': { path: path.join(projectRoot, '.cursor', 'mcp.json'), key: 'mcpServers' },\n 'windsurf': { path: path.join(home, '.codeium', 'windsurf', 'mcp_config.json'), key: 'mcpServers' },\n 'codex': { path: path.join(projectRoot, '.codex', 'hooks.json'), key: 'hooks' },\n 'copilot': { path: path.join(projectRoot, '.vscode', 'mcp.json'), key: 'servers' },\n 'copilot-cli': { path: path.join(home, '.copilot', 'mcp-config.json'), key: 'servers' },\n 'gemini-cli': { path: path.join(projectRoot, '.gemini', 'settings.json'), key: 'mcpServers' },\n 'continue': { path: path.join(projectRoot, '.continue', 'mcpServers', 'kirograph.json'), key: 'mcpServers' },\n 'opencode': { path: path.join(projectRoot, '.opencode.json'), key: 'mcp' },\n 'antigravity': { path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'), key: 'mcpServers' },\n 'roo': { path: path.join(projectRoot, '.roo', 'mcp.json'), key: 'mcpServers' },\n 'warp': { path: path.join(projectRoot, '.warp', '.mcp.json'), key: 'mcpServers' },\n 'trae': { path: path.join(projectRoot, '.trae', 'mcp.json'), key: 'mcpServers' },\n 'amp': { path: path.join(projectRoot, '.amp', 'config.json'), key: 'mcpServers' },\n 'cline': { path: path.join(projectRoot, '.cline', 'mcp_settings.json'), key: 'mcpServers' },\n 'qoder': { path: path.join(projectRoot, '.qoder', 'mcp.json'), key: 'mcpServers' },\n 'qwen': { path: path.join(home, '.qwen', 'settings.json'), key: 'mcpServers' },\n };\n\n function isConfigured(target: string): boolean {\n const check = configChecks[target];\n if (!check) return false;\n if (!fs.existsSync(check.path)) return false;\n const config = readJson(check.path);\n const container = config[check.key];\n if (!container) return false;\n if (typeof container === 'object' && !Array.isArray(container)) {\n return KIROGRAPH_SERVER_NAME in container;\n }\n return false;\n }\n\n const configured = detected.filter(d => isConfigured(d.target));\n const notConfigured = detected.filter(d => !isConfigured(d.target));\n\n console.log();\n console.log(section(' Integrations'));\n console.log();\n\n if (configured.length > 0) {\n console.log(` ${label('Configured:')}`);\n for (const d of configured) {\n const check = configChecks[d.target];\n const configPath = check ? check.path.replace(projectRoot, '.').replace(home, '~') : '';\n console.log(` ${green}\u2713${reset} ${d.label.padEnd(20)} ${dim}${configPath}${reset}`);\n }\n }\n\n if (notConfigured.length > 0) {\n if (configured.length > 0) console.log();\n console.log(` ${label('Detected but not configured:')}`);\n for (const d of notConfigured) {\n const check = configChecks[d.target];\n const configPath = check ? check.path.replace(projectRoot, '.').replace(home, '~') : '';\n console.log(` ${dim}\u25CB${reset} ${d.label.padEnd(20)} ${dim}${configPath}${reset}`);\n }\n console.log();\n console.log(` ${dim}Run \\`kirograph install\\` to configure detected platforms.${reset}`);\n }\n\n if (detected.length === 0) {\n console.log(` ${dim}No AI coding platforms detected.${reset}`);\n }\n\n console.log();\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport { dim, reset, violet, bold, green, label, value, section, renderTable } from '../ui';\nimport { loadConfig } from '../../config';\nimport { readTurboQuantStats } from '../../vectors/turboquant-index';\n\nexport function register(program: Command): void {\n program\n .command('status [projectPath]')\n .description('Show index statistics')\n .option('--integrations', 'Show detected and configured platforms')\n .action(async (projectPath: string | undefined, opts: { integrations?: boolean }) => {\n const target = path.resolve(projectPath ?? process.cwd());\n\n if (opts.integrations) {\n await showIntegrations(target);\n return;\n }\n\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n const cg = await KiroGraph.open(target);\n const stats = await cg.getStats();\n\n console.log();\n console.log(section(' Graph'));\n console.log(` ${label('Files')} ${value(String(stats.files))}`);\n console.log(` ${label('Symbols')} ${value(String(stats.nodes))}`);\n console.log(` ${label('Edges')} ${value(String(stats.edges))}`);\n\n if (stats.frameworks.length > 0) {\n console.log(` ${label('Frameworks')} ${value(stats.frameworks.join(', '))}`);\n }\n\n const kindEntries = Object.entries(stats.nodesByKind).sort((a, b) => b[1] - a[1]);\n if (kindEntries.length > 0) {\n console.log(`\\n ${label('By kind')}`);\n console.log(renderTable(kindEntries.map(([k, v]) => [k, String(v)])));\n }\n\n const langEntries = Object.entries(stats.filesByLanguage ?? {}).sort((a, b) => b[1] - a[1]);\n if (langEntries.length > 0) {\n console.log(`\\n ${label('By language')}`);\n console.log(renderTable(langEntries.map(([k, v]) => [k, String(v)])));\n }\n\n // Sync state\n const threshold = stats.syncWarningThreshold ?? 10;\n const pendingFiles: number = stats.pendingFiles ?? 0;\n const syncRunning: boolean = stats.syncRunning ?? false;\n console.log();\n console.log(section(' Sync'));\n if (syncRunning) {\n console.log(` ${'\\x1b[33m'}\u26A0 Sync is currently running in the background.${reset}`);\n } else {\n console.log(` ${label('Status')} ${dim}idle${reset}`);\n }\n if (pendingFiles > 0) {\n const warn = threshold > 0 && pendingFiles >= threshold;\n const pendingLabel = warn ? `${'\\x1b[33m'}${pendingFiles} files pending${reset}` : `${dim}${pendingFiles} files pending${reset}`;\n console.log(` ${label('Pending')} ${pendingLabel}`);\n if (warn) {\n console.log(` ${'\\x1b[33m'}\u26A0 Index may be stale. Run \\`kirograph sync\\` to update.${reset}`);\n }\n } else {\n console.log(` ${label('Pending')} ${green}up to date${reset}`);\n }\n\n console.log();\n console.log(section(' Semantic Search'));\n if (stats.embeddingsEnabled) {\n const tqStats = stats.semanticEngine === 'turboquant'\n ? readTurboQuantStats(path.join(target, '.kirograph'))\n : null;\n const engineLabel =\n stats.semanticEngine === 'turboquant' ? `turboquant ${dim}(${stats.vecIndexCount} entries \u00B7 ${tqStats ? `${tqStats.bits} bits \u00B7 ${tqStats.compressionRatio.toFixed(1)}\u00D7 compression` : 'not yet indexed'})${reset}` :\n stats.semanticEngine === 'sqlite-vec' ? `sqlite-vec ${dim}(${stats.vecIndexCount} entries in ANN index)${reset}` :\n stats.semanticEngine === 'orama' ? `orama ${dim}(hybrid \u2014 ${stats.vecIndexCount} docs in index)${reset}` :\n stats.semanticEngine === 'pglite' ? `pglite+pgvector ${dim}(hybrid \u2014 ${stats.vecIndexCount} rows in DB)${reset}` :\n stats.semanticEngine === 'lancedb' ? `lancedb ${dim}(${stats.vecIndexCount} entries in ANN index)${reset}` :\n stats.semanticEngine === 'qdrant' ? `qdrant ${dim}(${stats.vecIndexCount} points in collection)${reset}` :\n stats.semanticEngine === 'typesense' ? `typesense ${dim}(${stats.vecIndexCount} documents in collection)${reset}` :\n stats.semanticEngine === 'turbovec' ? `turbovec ${dim}(${stats.vecIndexCount} entries \u00B7 ${stats.turbovecBits ?? 4} bits \u00B7 Rust/SIMD)${reset}` :\n `in-process cosine`;\n const total = stats.embeddableNodeCount > 0 ? stats.embeddableNodeCount : stats.nodes;\n const displayed = Math.min(stats.embeddingCount, total);\n const coverage = total > 0 ? Math.min(100, Math.round((stats.embeddingCount / total) * 100)) : 0;\n console.log(` ${label('Status')} ${green}${bold}enabled${reset}`);\n console.log(` ${label('Model')} ${value(stats.embeddingModel)}`);\n console.log(` ${label('Engine')} ${violet}${engineLabel}${reset}`);\n if (stats.engineFallback) {\n console.log(` ${'\\x1b[33m'}\u26A0 engine fallback: ${stats.engineFallback}${reset}`);\n }\n console.log(` ${label('Indexed')} ${value(`${displayed} / ${total}`)} ${dim}(${coverage}%)${reset}`);\n if (tqStats) {\n const rawMB = (tqStats.rawBytes / 1_048_576).toFixed(1);\n const compMB = (tqStats.actualBytes / 1_048_576).toFixed(1);\n const savedMB = (tqStats.savedBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Raw size')} ${dim}${rawMB} MB \u2192 compressed ${compMB} MB (${savedMB} MB saved)${reset}`);\n if (tqStats.memEnabled && tqStats.memCount > 0) {\n const mRawMB = (tqStats.memRawBytes / 1_048_576).toFixed(1);\n const mCompMB = (tqStats.memActualBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Memory')} ${dim}${tqStats.memCount} observations \u2192 ${mRawMB} MB \u2192 ${mCompMB} MB${reset}`);\n }\n if (tqStats.docsEnabled && tqStats.docsCount > 0) {\n const dRawMB = (tqStats.docsRawBytes / 1_048_576).toFixed(1);\n const dCompMB = (tqStats.docsActualBytes / 1_048_576).toFixed(1);\n console.log(` ${label('Docs')} ${dim}${tqStats.docsCount} sections \u2192 ${dRawMB} MB \u2192 ${dCompMB} MB${reset}`);\n }\n const totalSaved = tqStats.savedBytes + (tqStats.memRawBytes - tqStats.memActualBytes) + (tqStats.docsRawBytes - tqStats.docsActualBytes);\n if (totalSaved > 0) {\n console.log(` ${label('Total RAM')} ${green}${(totalSaved / 1_048_576).toFixed(1)} MB saved${reset} ${dim}(TurboQuant compression)${reset}`);\n }\n }\n } else {\n console.log(` ${label('Status')} ${dim}disabled${reset}`);\n }\n\n // Pattern SAST section\n try {\n const patConfig = await loadConfig(target);\n if (patConfig.enablePatterns) {\n const db2 = cg.getDatabase();\n (db2 as any).applyPatternsSchema?.();\n const rawDb2 = db2.getRawDb();\n const tableExists = rawDb2.get(\"SELECT name FROM sqlite_master WHERE type='table' AND name='pattern_matches'\");\n if (tableExists) {\n const matchCount = (rawDb2.get('SELECT COUNT(*) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n const fileCount = (rawDb2.get('SELECT COUNT(DISTINCT file_path) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n const ruleCount = (rawDb2.get('SELECT COUNT(DISTINCT pattern_id) as cnt FROM pattern_matches') as any)?.cnt ?? 0;\n console.log();\n console.log(section(' Patterns'));\n console.log(` ${label('Status')} ${green}${bold}enabled${reset}`);\n if (matchCount > 0) {\n console.log(` ${label('Matches')} ${value(String(matchCount))} ${dim}across ${fileCount} files, ${ruleCount} rules triggered${reset}`);\n } else {\n console.log(` ${label('Matches')} ${dim}none yet \u2014 run kirograph index${reset}`);\n }\n } else {\n console.log();\n console.log(section(' Patterns'));\n console.log(` ${label('Status')} ${green}${bold}enabled${reset} ${dim}(not yet indexed \u2014 run kirograph index)${reset}`);\n }\n }\n } catch { /* non-critical */ }\n\n // Security stats (conditional on enableSecurity)\n try {\n const config = await loadConfig(target);\n if (config.enableSecurity) {\n const db = cg.getDatabase();\n db.applySecuritySchema();\n const rawDb = db.getRawDb();\n\n const depCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_dependencies')?.cnt ?? 0;\n const vulnCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_vulnerabilities')?.cnt ?? 0;\n const affectedCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'affected'\")?.cnt ?? 0;\n const notAffectedCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'not_affected'\")?.cnt ?? 0;\n const investigatingCount: number = rawDb.get(\"SELECT COUNT(*) as cnt FROM sec_reachability WHERE verdict = 'under_investigation'\")?.cnt ?? 0;\n const staleCount: number = rawDb.get('SELECT COUNT(*) as cnt FROM sec_dependencies WHERE vuln_data_stale = 1')?.cnt ?? 0;\n\n console.log();\n console.log(section(' \uD83D\uDD12 Security'));\n console.log(` ${label('Dependencies')} ${value(String(depCount))}`);\n console.log(` ${label('Vulnerabilities')} ${value(String(vulnCount))}`);\n\n if (vulnCount > 0) {\n const affectedLabel = affectedCount > 0\n ? `${'\\x1b[31m'}${affectedCount} affected${reset}`\n : `${dim}0 affected${reset}`;\n console.log(` ${label('Affected')} ${affectedLabel}`);\n console.log(` ${label('Not Affected')} ${dim}${notAffectedCount}${reset}`);\n console.log(` ${label('Investigating')} ${dim}${investigatingCount}${reset}`);\n }\n\n if (staleCount > 0) {\n console.log(` ${'\\x1b[33m'}\u26A0 ${staleCount} dependenc${staleCount === 1 ? 'y has' : 'ies have'} stale vulnerability data. Run \\`kirograph vulns --refresh\\` to update.${reset}`);\n }\n }\n } catch { /* non-critical */ }\n\n console.log();\n cg.close();\n });\n}\n\nasync function showIntegrations(projectRoot: string): Promise<void> {\n const fs = await import('fs');\n const { detectPlatforms } = await Promise.resolve().then(() => require('../installer/detect.js'));\n const { readJson, KIROGRAPH_SERVER_NAME } = await Promise.resolve().then(() => require('../installer/common.js'));\n\n const detected = detectPlatforms(projectRoot);\n const home = process.env.HOME || process.env.USERPROFILE || '';\n\n // Map of target \u2192 config path to check if kirograph is configured\n const configChecks: Record<string, { path: string; key: string }> = {\n 'kiro': { path: path.join(projectRoot, '.kiro', 'settings', 'mcp.json'), key: 'mcpServers' },\n 'claude': { path: path.join(projectRoot, '.mcp.json'), key: 'mcpServers' },\n 'cursor': { path: path.join(projectRoot, '.cursor', 'mcp.json'), key: 'mcpServers' },\n 'windsurf': { path: path.join(home, '.codeium', 'windsurf', 'mcp_config.json'), key: 'mcpServers' },\n 'codex': { path: path.join(projectRoot, '.codex', 'hooks.json'), key: 'hooks' },\n 'copilot': { path: path.join(projectRoot, '.vscode', 'mcp.json'), key: 'servers' },\n 'copilot-cli': { path: path.join(home, '.copilot', 'mcp-config.json'), key: 'servers' },\n 'gemini-cli': { path: path.join(projectRoot, '.gemini', 'settings.json'), key: 'mcpServers' },\n 'continue': { path: path.join(projectRoot, '.continue', 'mcpServers', 'kirograph.json'), key: 'mcpServers' },\n 'opencode': { path: path.join(projectRoot, '.opencode.json'), key: 'mcp' },\n 'antigravity': { path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'), key: 'mcpServers' },\n 'roo': { path: path.join(projectRoot, '.roo', 'mcp.json'), key: 'mcpServers' },\n 'warp': { path: path.join(projectRoot, '.warp', '.mcp.json'), key: 'mcpServers' },\n 'trae': { path: path.join(projectRoot, '.trae', 'mcp.json'), key: 'mcpServers' },\n 'amp': { path: path.join(projectRoot, '.amp', 'config.json'), key: 'mcpServers' },\n 'cline': { path: path.join(projectRoot, '.cline', 'mcp_settings.json'), key: 'mcpServers' },\n 'qoder': { path: path.join(projectRoot, '.qoder', 'mcp.json'), key: 'mcpServers' },\n 'qwen': { path: path.join(home, '.qwen', 'settings.json'), key: 'mcpServers' },\n 'commandcode': { path: path.join(projectRoot, '.mcp.json'), key: 'mcpServers' },\n };\n\n function isConfigured(target: string): boolean {\n const check = configChecks[target];\n if (!check) return false;\n if (!fs.existsSync(check.path)) return false;\n const config = readJson(check.path);\n const container = config[check.key];\n if (!container) return false;\n if (typeof container === 'object' && !Array.isArray(container)) {\n return KIROGRAPH_SERVER_NAME in container;\n }\n return false;\n }\n\n const configured = detected.filter(d => isConfigured(d.target));\n const notConfigured = detected.filter(d => !isConfigured(d.target));\n\n console.log();\n console.log(section(' Integrations'));\n console.log();\n\n if (configured.length > 0) {\n console.log(` ${label('Configured:')}`);\n for (const d of configured) {\n const check = configChecks[d.target];\n const configPath = check ? check.path.replace(projectRoot, '.').replace(home, '~') : '';\n console.log(` ${green}\u2713${reset} ${d.label.padEnd(20)} ${dim}${configPath}${reset}`);\n }\n }\n\n if (notConfigured.length > 0) {\n if (configured.length > 0) console.log();\n console.log(` ${label('Detected but not configured:')}`);\n for (const d of notConfigured) {\n const check = configChecks[d.target];\n const configPath = check ? check.path.replace(projectRoot, '.').replace(home, '~') : '';\n console.log(` ${dim}\u25CB${reset} ${d.label.padEnd(20)} ${dim}${configPath}${reset}`);\n }\n console.log();\n console.log(` ${dim}Run \\`kirograph install\\` to configure detected platforms.${reset}`);\n }\n\n if (detected.length === 0) {\n console.log(` ${dim}No AI coding platforms detected.${reset}`);\n }\n\n console.log();\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -84,7 +84,8 @@ const ALL_TARGETS = [
84
84
  "iflow",
85
85
  "qwen",
86
86
  "rovo",
87
- "qoder"
87
+ "qoder",
88
+ "commandcode"
88
89
  ];
89
90
  function isValidTarget(t) {
90
91
  return t === "all" || ALL_TARGETS.includes(t);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/commands/uninit.ts"],
4
- "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as readline from 'readline';\nimport { printBanner } from '../banner';\nimport { dim, reset, violet, bold, green } from '../ui';\nimport { askToggle } from '../installer/prompts';\nimport type { InstallTarget } from '../installer/common';\nimport { getTargetInstaller } from '../installer/targets';\n\nexport const UNINIT_FAREWELLS = [\n \"Oh. So it's come to this.\",\n \"We're sorry to see you go. (Are we? Yes. We are.)\",\n \"Deleting months of carefully indexed knowledge. Bold move.\",\n \"Fine. We'll just sit here in the dark.\",\n \"You can always come back. We won't mention this.\",\n \"The graph remembers everything. Except, soon, anything.\",\n \"Somewhere a tree-sitter is crying.\",\n \"Uninstalling... and pretending it doesn't hurt.\",\n \"574 embeddings. Gone. Just like that.\",\n \"See you on the other side of `kirograph install`.\",\n];\n\nconst ALL_TARGETS: InstallTarget[] = [\n 'kiro', 'claude', 'codex', 'cursor', 'antigravity', 'opencode',\n 'windsurf', 'cline', 'copilot', 'junie', 'gemini-cli',\n 'continue', 'roo', 'warp', 'aider', 'trae',\n 'augment', 'kilo', 'amp', 'devin', 'replit', 'goose', 'openhands', 'tabnine',\n 'mistral-vibe', 'ibm-bob', 'crush', 'droid-factory', 'forgecode', 'iflow', 'qwen', 'rovo', 'qoder',\n];\n\nfunction isValidTarget(t: string): t is InstallTarget | 'all' {\n return t === 'all' || ALL_TARGETS.includes(t as InstallTarget);\n}\n\nfunction uninitKiro(projectRoot: string): void {\n // Remove .kiro hooks created by kirograph (v2 .json format)\n const kiroHooks = [\n 'kirograph-sync-if-dirty.json',\n 'kirograph-compress-hint.json',\n 'kirograph-mem-capture.json',\n 'kirograph-watchmen.json',\n 'kirograph-wiki-ingest.json',\n 'kirograph-wiki-lint.json',\n // Legacy v1 .kiro.hook filenames\n 'kirograph-mark-dirty-on-save.kiro.hook',\n 'kirograph-mark-dirty-on-create.kiro.hook',\n 'kirograph-sync-on-delete.kiro.hook',\n 'kirograph-sync-if-dirty.kiro.hook',\n 'kirograph-compress-hint.kiro.hook',\n 'kirograph-mem-capture.kiro.hook',\n 'kirograph-watchmen.kiro.hook',\n 'kirograph-wiki-ingest.kiro.hook',\n 'kirograph-wiki-lint.kiro.hook',\n // Legacy pre-v1 .json filenames (different schema)\n 'kirograph-mark-dirty-on-save.json',\n 'kirograph-mark-dirty-on-create.json',\n 'kirograph-sync-on-delete.json',\n 'kirograph-sync-on-save.json',\n 'kirograph-sync-on-create.json',\n ];\n const hooksDir = path.join(projectRoot, '.kiro', 'hooks');\n let removedHooks = 0;\n for (const hook of kiroHooks) {\n const p = path.join(hooksDir, hook);\n if (fs.existsSync(p)) { fs.unlinkSync(p); removedHooks++; }\n }\n if (removedHooks > 0) console.log(` ${green}\u2713${reset} Removed ${removedHooks} hook(s) from .kiro/hooks/`);\n\n // Remove .kiro/steering/kirograph*.md (main + all workflow files)\n const steeringDir = path.join(projectRoot, '.kiro', 'steering');\n let removedSteering = 0;\n if (fs.existsSync(steeringDir)) {\n for (const entry of fs.readdirSync(steeringDir)) {\n if (entry.startsWith('kirograph') && entry.endsWith('.md')) {\n fs.unlinkSync(path.join(steeringDir, entry));\n removedSteering++;\n }\n }\n }\n if (removedSteering > 0) {\n console.log(` ${green}\u2713${reset} Removed ${removedSteering} steering file(s) from .kiro/steering/`);\n }\n\n // Remove .kiro/agents/kirograph.json\n const agentPath = path.join(projectRoot, '.kiro', 'agents', 'kirograph.json');\n if (fs.existsSync(agentPath)) {\n fs.unlinkSync(agentPath);\n console.log(` ${green}\u2713${reset} Removed .kiro/agents/kirograph.json`);\n }\n\n // Remove kirograph server from .kiro/settings/mcp.json\n const { removeMcpServersConfig } = require('../installer/common');\n const mcpPath = path.join(projectRoot, '.kiro', 'settings', 'mcp.json');\n if (removeMcpServersConfig(mcpPath)) {\n console.log(` ${green}\u2713${reset} Removed kirograph from .kiro/settings/mcp.json`);\n }\n}\n\nasync function runUninit(projectPath: string | undefined, opts: { force?: boolean; target?: string }): Promise<void> {\n const projectRoot = path.resolve(projectPath ?? process.cwd());\n const targetName = (opts.target ?? 'kiro').toLowerCase();\n\n if (!isValidTarget(targetName)) {\n console.error(`Unknown uninit target: ${opts.target}. Choose from: ${ALL_TARGETS.join(', ')}, all`);\n process.exit(1);\n }\n\n const dir = path.join(projectRoot, '.kirograph');\n if (!fs.existsSync(dir)) { console.log('Not initialized.'); return; }\n\n let removeIntegration = true;\n let removeGraph = opts.force === true;\n\n if (!opts.force) {\n printBanner();\n const farewell = UNINIT_FAREWELLS[Math.floor(Math.random() * UNINIT_FAREWELLS.length)]!;\n console.log(` ${violet}${bold}${farewell}${reset}`);\n console.log(`\\n ${dim}This can remove ${targetName} integration files and, separately, the shared .kirograph/ data.${reset}`);\n console.log(` ${dim}Your source code is untouched.${reset}`);\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n removeIntegration = await askToggle(rl, `Remove ${targetName} integration files?`, 'Removes hooks, MCP config, rules, and agent instructions for this target.', false);\n removeGraph = await askToggle(rl, 'Remove shared .kirograph/ data too?', 'Deletes the graph database, snapshots, and all indexed data. Cannot be undone.', false);\n\n rl.close();\n\n if (!removeIntegration && !removeGraph) {\n console.log(`\\n ${dim}Cancelled. Nothing removed.${reset}\\n`);\n return;\n }\n console.log();\n }\n\n if (removeGraph) {\n fs.rmSync(dir, { recursive: true, force: true });\n console.log(` ${green}\u2713${reset} Removed .kirograph/`);\n }\n\n if (removeIntegration) {\n const targets: InstallTarget[] = targetName === 'all' ? [...ALL_TARGETS] : [targetName as InstallTarget];\n\n for (const t of targets) {\n if (t === 'kiro') {\n uninitKiro(projectRoot);\n } else {\n const installer = getTargetInstaller(t);\n installer.uninit?.(projectRoot);\n }\n }\n }\n\n console.log(`\\n ${dim}Done. Run ${violet}kirograph install --target ${targetName === 'all' ? 'kiro' : targetName}${reset}${dim} to come back anytime.${reset}\\n`);\n}\n\nexport function register(program: Command): void {\n program\n .command('uninit [projectPath]')\n .description('Remove KiroGraph from a project')\n .option('--force', 'Skip confirmation')\n .option('--target <target>', `Integration target to clean up (or \"all\"): ${ALL_TARGETS.slice(0, 6).join(', ')}, ...`, 'kiro')\n .action(runUninit);\n\n program\n .command('uninstall [projectPath]')\n .description('Alias for uninit. Remove KiroGraph from a project')\n .option('--force', 'Skip confirmation')\n .option('--target <target>', `Integration target to clean up (or \"all\"): ${ALL_TARGETS.slice(0, 6).join(', ')}, ...`, 'kiro')\n .action(runUninit);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as readline from 'readline';\nimport { printBanner } from '../banner';\nimport { dim, reset, violet, bold, green } from '../ui';\nimport { askToggle } from '../installer/prompts';\nimport type { InstallTarget } from '../installer/common';\nimport { getTargetInstaller } from '../installer/targets';\n\nexport const UNINIT_FAREWELLS = [\n \"Oh. So it's come to this.\",\n \"We're sorry to see you go. (Are we? Yes. We are.)\",\n \"Deleting months of carefully indexed knowledge. Bold move.\",\n \"Fine. We'll just sit here in the dark.\",\n \"You can always come back. We won't mention this.\",\n \"The graph remembers everything. Except, soon, anything.\",\n \"Somewhere a tree-sitter is crying.\",\n \"Uninstalling... and pretending it doesn't hurt.\",\n \"574 embeddings. Gone. Just like that.\",\n \"See you on the other side of `kirograph install`.\",\n];\n\nconst ALL_TARGETS: InstallTarget[] = [\n 'kiro', 'claude', 'codex', 'cursor', 'antigravity', 'opencode',\n 'windsurf', 'cline', 'copilot', 'junie', 'gemini-cli',\n 'continue', 'roo', 'warp', 'aider', 'trae',\n 'augment', 'kilo', 'amp', 'devin', 'replit', 'goose', 'openhands', 'tabnine',\n 'mistral-vibe', 'ibm-bob', 'crush', 'droid-factory', 'forgecode', 'iflow', 'qwen', 'rovo', 'qoder', 'commandcode',\n];\n\nfunction isValidTarget(t: string): t is InstallTarget | 'all' {\n return t === 'all' || ALL_TARGETS.includes(t as InstallTarget);\n}\n\nfunction uninitKiro(projectRoot: string): void {\n // Remove .kiro hooks created by kirograph (v2 .json format)\n const kiroHooks = [\n 'kirograph-sync-if-dirty.json',\n 'kirograph-compress-hint.json',\n 'kirograph-mem-capture.json',\n 'kirograph-watchmen.json',\n 'kirograph-wiki-ingest.json',\n 'kirograph-wiki-lint.json',\n // Legacy v1 .kiro.hook filenames\n 'kirograph-mark-dirty-on-save.kiro.hook',\n 'kirograph-mark-dirty-on-create.kiro.hook',\n 'kirograph-sync-on-delete.kiro.hook',\n 'kirograph-sync-if-dirty.kiro.hook',\n 'kirograph-compress-hint.kiro.hook',\n 'kirograph-mem-capture.kiro.hook',\n 'kirograph-watchmen.kiro.hook',\n 'kirograph-wiki-ingest.kiro.hook',\n 'kirograph-wiki-lint.kiro.hook',\n // Legacy pre-v1 .json filenames (different schema)\n 'kirograph-mark-dirty-on-save.json',\n 'kirograph-mark-dirty-on-create.json',\n 'kirograph-sync-on-delete.json',\n 'kirograph-sync-on-save.json',\n 'kirograph-sync-on-create.json',\n ];\n const hooksDir = path.join(projectRoot, '.kiro', 'hooks');\n let removedHooks = 0;\n for (const hook of kiroHooks) {\n const p = path.join(hooksDir, hook);\n if (fs.existsSync(p)) { fs.unlinkSync(p); removedHooks++; }\n }\n if (removedHooks > 0) console.log(` ${green}\u2713${reset} Removed ${removedHooks} hook(s) from .kiro/hooks/`);\n\n // Remove .kiro/steering/kirograph*.md (main + all workflow files)\n const steeringDir = path.join(projectRoot, '.kiro', 'steering');\n let removedSteering = 0;\n if (fs.existsSync(steeringDir)) {\n for (const entry of fs.readdirSync(steeringDir)) {\n if (entry.startsWith('kirograph') && entry.endsWith('.md')) {\n fs.unlinkSync(path.join(steeringDir, entry));\n removedSteering++;\n }\n }\n }\n if (removedSteering > 0) {\n console.log(` ${green}\u2713${reset} Removed ${removedSteering} steering file(s) from .kiro/steering/`);\n }\n\n // Remove .kiro/agents/kirograph.json\n const agentPath = path.join(projectRoot, '.kiro', 'agents', 'kirograph.json');\n if (fs.existsSync(agentPath)) {\n fs.unlinkSync(agentPath);\n console.log(` ${green}\u2713${reset} Removed .kiro/agents/kirograph.json`);\n }\n\n // Remove kirograph server from .kiro/settings/mcp.json\n const { removeMcpServersConfig } = require('../installer/common');\n const mcpPath = path.join(projectRoot, '.kiro', 'settings', 'mcp.json');\n if (removeMcpServersConfig(mcpPath)) {\n console.log(` ${green}\u2713${reset} Removed kirograph from .kiro/settings/mcp.json`);\n }\n}\n\nasync function runUninit(projectPath: string | undefined, opts: { force?: boolean; target?: string }): Promise<void> {\n const projectRoot = path.resolve(projectPath ?? process.cwd());\n const targetName = (opts.target ?? 'kiro').toLowerCase();\n\n if (!isValidTarget(targetName)) {\n console.error(`Unknown uninit target: ${opts.target}. Choose from: ${ALL_TARGETS.join(', ')}, all`);\n process.exit(1);\n }\n\n const dir = path.join(projectRoot, '.kirograph');\n if (!fs.existsSync(dir)) { console.log('Not initialized.'); return; }\n\n let removeIntegration = true;\n let removeGraph = opts.force === true;\n\n if (!opts.force) {\n printBanner();\n const farewell = UNINIT_FAREWELLS[Math.floor(Math.random() * UNINIT_FAREWELLS.length)]!;\n console.log(` ${violet}${bold}${farewell}${reset}`);\n console.log(`\\n ${dim}This can remove ${targetName} integration files and, separately, the shared .kirograph/ data.${reset}`);\n console.log(` ${dim}Your source code is untouched.${reset}`);\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n\n removeIntegration = await askToggle(rl, `Remove ${targetName} integration files?`, 'Removes hooks, MCP config, rules, and agent instructions for this target.', false);\n removeGraph = await askToggle(rl, 'Remove shared .kirograph/ data too?', 'Deletes the graph database, snapshots, and all indexed data. Cannot be undone.', false);\n\n rl.close();\n\n if (!removeIntegration && !removeGraph) {\n console.log(`\\n ${dim}Cancelled. Nothing removed.${reset}\\n`);\n return;\n }\n console.log();\n }\n\n if (removeGraph) {\n fs.rmSync(dir, { recursive: true, force: true });\n console.log(` ${green}\u2713${reset} Removed .kirograph/`);\n }\n\n if (removeIntegration) {\n const targets: InstallTarget[] = targetName === 'all' ? [...ALL_TARGETS] : [targetName as InstallTarget];\n\n for (const t of targets) {\n if (t === 'kiro') {\n uninitKiro(projectRoot);\n } else {\n const installer = getTargetInstaller(t);\n installer.uninit?.(projectRoot);\n }\n }\n }\n\n console.log(`\\n ${dim}Done. Run ${violet}kirograph install --target ${targetName === 'all' ? 'kiro' : targetName}${reset}${dim} to come back anytime.${reset}\\n`);\n}\n\nexport function register(program: Command): void {\n program\n .command('uninit [projectPath]')\n .description('Remove KiroGraph from a project')\n .option('--force', 'Skip confirmation')\n .option('--target <target>', `Integration target to clean up (or \"all\"): ${ALL_TARGETS.slice(0, 6).join(', ')}, ...`, 'kiro')\n .action(runUninit);\n\n program\n .command('uninstall [projectPath]')\n .description('Alias for uninit. Remove KiroGraph from a project')\n .option('--force', 'Skip confirmation')\n .option('--target <target>', `Integration target to clean up (or \"all\"): ${ALL_TARGETS.slice(0, 6).join(', ')}, ...`, 'kiro')\n .action(runUninit);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -139,7 +139,7 @@ function register(program) {
139
139
  if (dbName.toUpperCase() === "OSV") return new OsvAdapter();
140
140
  return null;
141
141
  }).filter(Boolean);
142
- const client = new VulnerabilityDatabaseClient(adapters, db);
142
+ const client = new VulnerabilityDatabaseClient(adapters, db, void 0, target);
143
143
  const result = await client.enrichAll();
144
144
  console.error(` ${import_ui.green}\u2713${import_ui.reset} Checked ${import_ui.bold}${result.dependenciesChecked}${import_ui.reset} dependencies, found ${import_ui.bold}${result.vulnerabilitiesFound}${import_ui.reset} vulnerabilities`);
145
145
  if (result.errors.length > 0) {
@@ -165,10 +165,10 @@ function register(program) {
165
165
  const params = [];
166
166
  if (opts.severity) {
167
167
  const severityRanges = {
168
- critical: [9, 10],
169
- high: [7, 8.9],
170
- medium: [4, 6.9],
171
- low: [0.1, 3.9]
168
+ critical: [9, 10.01],
169
+ high: [7, 9],
170
+ medium: [4, 7],
171
+ low: [0, 4]
172
172
  };
173
173
  const range = severityRanges[opts.severity.toLowerCase()];
174
174
  if (!range) {
@@ -176,7 +176,7 @@ function register(program) {
176
176
  cg.close();
177
177
  process.exit(1);
178
178
  }
179
- query += ` AND v.severity_score >= ? AND v.severity_score <= ?`;
179
+ query += ` AND v.severity_score IS NOT NULL AND v.severity_score >= ? AND v.severity_score < ?`;
180
180
  params.push(range[0], range[1]);
181
181
  }
182
182
  if (opts.verdict) {
@@ -222,6 +222,11 @@ function register(program) {
222
222
  const suppressions = new import_suppressions.SuppressionManager(target);
223
223
  const suppressedRows = dedupedRows.filter((row) => suppressions.isSuppressed(row.cve_id));
224
224
  const filteredRows = dedupedRows.filter((row) => !suppressions.isSuppressed(row.cve_id));
225
+ const unresolvedMavenCount = rawDb.get(
226
+ `SELECT COUNT(*) as count FROM sec_dependencies
227
+ WHERE ecosystem = 'maven' AND (resolved_version IS NULL OR resolved_version = '')
228
+ AND (declared_constraint IS NULL OR declared_constraint = '')`
229
+ )?.count ?? 0;
225
230
  if (filteredRows.length === 0) {
226
231
  const filterNote = opts.severity || opts.verdict ? ` matching filters` : "";
227
232
  console.log(`
@@ -229,6 +234,11 @@ function register(program) {
229
234
  `);
230
235
  if (suppressedRows.length > 0) {
231
236
  console.log(` ${import_ui.dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${import_ui.reset}
237
+ `);
238
+ }
239
+ if (unresolvedMavenCount > 0) {
240
+ console.log(` ${import_ui.dim}${unresolvedMavenCount} Maven dependenc${unresolvedMavenCount === 1 ? "y has" : "ies have"} no resolved version (BOM-managed, e.g. via spring-boot-starter-parent) and were skipped.${import_ui.reset}`);
241
+ console.log(` ${import_ui.dim}Run${import_ui.reset} ${import_ui.violet}${import_ui.bold}mvn dependency:tree -DoutputFile=dependency-tree.txt${import_ui.reset}${import_ui.dim} next to pom.xml, then${import_ui.reset} ${import_ui.violet}${import_ui.bold}kirograph index${import_ui.dim} again to resolve them.${import_ui.reset}
232
242
  `);
233
243
  }
234
244
  cg.close();
@@ -341,6 +351,16 @@ function register(program) {
341
351
  }
342
352
  if (suppressedRows.length > 0) {
343
353
  console.log(` ${import_ui.dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${import_ui.reset}
354
+ `);
355
+ }
356
+ const pendingCount = filteredRows.filter((r) => !r.verdict).length;
357
+ if (pendingCount > 0) {
358
+ console.log(` ${import_ui.dim}${pendingCount} vulnerabilit${pendingCount === 1 ? "y is" : "ies are"} [pending] reachability analysis \u2014 run ${import_ui.reset}kirograph index${import_ui.dim} to compute call-graph verdicts.${import_ui.reset}
359
+ `);
360
+ }
361
+ if (unresolvedMavenCount > 0) {
362
+ console.log(` ${import_ui.dim}${unresolvedMavenCount} Maven dependenc${unresolvedMavenCount === 1 ? "y has" : "ies have"} no resolved version (BOM-managed, e.g. via spring-boot-starter-parent) and were skipped.${import_ui.reset}`);
363
+ console.log(` ${import_ui.dim}Run${import_ui.reset} ${import_ui.violet}${import_ui.bold}mvn dependency:tree -DoutputFile=dependency-tree.txt${import_ui.reset}${import_ui.dim} next to pom.xml, then${import_ui.reset} ${import_ui.violet}${import_ui.bold}kirograph index${import_ui.dim} again to resolve them.${import_ui.reset}
344
364
  `);
345
365
  }
346
366
  if (opts.failOn !== void 0) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/commands/vulns.ts"],
4
- "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport { loadConfig } from '../../config';\nimport { dim, reset, violet, bold, green } from '../ui';\nimport { formatFixSuggestion } from '../../security/export/fix-suggestions';\nimport { SuppressionManager } from '../../security/suppressions';\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Parse an `epss=N` fail-on value and return the threshold, or null if not an epss condition. */\nfunction parseEpssFailOn(failOn: string): number | null {\n const m = failOn.match(/^epss=(.+)$/);\n if (!m) return null;\n const n = parseFloat(m[1]);\n return isNaN(n) ? null : n;\n}\n\n/** Extract workspace label from a source_manifests JSON string. */\nfunction workspaceFromManifests(sourceManifests: string | null): string {\n if (!sourceManifests) return 'root';\n try {\n const manifests: string[] = JSON.parse(sourceManifests);\n if (!manifests.length) return 'root';\n const dir = path.dirname(manifests[0]);\n return dir === '.' ? 'root' : dir;\n } catch {\n return 'root';\n }\n}\n\nexport function register(program: Command): void {\n program\n .command('vulns [projectPath]')\n .description('List vulnerabilities with reachability verdicts and severity')\n .option('--severity <level>', 'Filter by severity: critical, high, medium, low')\n .option('--verdict <verdict>', 'Filter by verdict: affected, not_affected, under_investigation')\n .option('--refresh', 'Trigger fresh vulnerability enrichment before listing')\n .option('--epss <threshold>', 'Filter by EPSS score (e.g. 0.5 shows only vulns with EPSS >= 0.5)')\n .option('--stale', 'Show staleness score of the affected dependency alongside each CVE')\n .option('--sort <key>', 'Sort results by: risk (default), cvss, epss, name')\n .option('--add <cveId>', 'Manually register a CVE')\n .option('--package <name>', 'Package name for --add')\n .option('--version <ver>', 'Package version for --add')\n .option('--fail-on <condition>', 'Exit 1 if condition is met: affected, any, critical, high, epss=N')\n .option('--group-by <key>', 'Group output by: workspace')\n .action(async (projectPath: string | undefined, opts: {\n severity?: string;\n verdict?: string;\n refresh?: boolean;\n epss?: string;\n stale?: boolean;\n sort?: string;\n add?: string;\n package?: string;\n version?: string;\n failOn?: string;\n groupBy?: string;\n }) => {\n const target = path.resolve(projectPath ?? process.cwd());\n const config = await loadConfig(target);\n\n if (!config.enableSecurity) {\n console.error(`\\n ${'\\x1b[33m'}\u26A0 Security analysis is disabled.${reset}`);\n console.error(` ${dim}Enable it in .kirograph/config.json:${reset} ${violet}${bold}\"enableSecurity\": true${reset}`);\n console.error(` ${dim}Then re-run:${reset} ${violet}${bold}kirograph index${reset}\\n`);\n process.exit(1);\n }\n\n // Validate --fail-on early\n if (opts.failOn !== undefined) {\n const validFailOns = ['affected', 'any', 'critical', 'high'];\n const isEpss = parseEpssFailOn(opts.failOn) !== null;\n if (!validFailOns.includes(opts.failOn) && !isEpss) {\n console.error(` \u2716 Invalid --fail-on value: ${opts.failOn}. Use: affected, any, critical, high, epss=N`);\n process.exit(1);\n }\n }\n\n // Validate --group-by early\n if (opts.groupBy !== undefined && opts.groupBy !== 'workspace') {\n console.error(` \u2716 Invalid --group-by value: ${opts.groupBy}. Supported: workspace`);\n process.exit(1);\n }\n\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n if (!KiroGraph.isInitialized(target)) {\n console.error(' \u2716 KiroGraph not initialized. Run: kirograph init');\n process.exit(1);\n }\n\n const cg = await KiroGraph.open(target);\n const db = cg.getDatabase();\n db.applySecuritySchema();\n const rawDb = db.getRawDb();\n\n // Handle --add: manually register a CVE\n if (opts.add) {\n if (!opts.package || !opts.version) {\n console.error(` \u2716 --add requires --package <name> and --version <ver>`);\n cg.close(); process.exit(1);\n }\n\n const cveId = opts.add;\n const pkgName = opts.package;\n const pkgVersion = opts.version;\n\n // Find the matching dependency node\n const depRow: { node_id: string; ecosystem: string } | undefined = rawDb.get(\n `SELECT node_id, ecosystem FROM sec_dependencies\n WHERE package_name = ? AND (resolved_version = ? OR declared_constraint = ?)`,\n [pkgName, pkgVersion, pkgVersion],\n );\n\n if (!depRow) {\n console.error(` \u2716 No dependency found matching ${violet}${pkgName}@${pkgVersion}${reset}`);\n console.error(` ${dim}Run${reset} ${violet}${bold}kirograph index${reset} ${dim}first to discover dependencies.${reset}`);\n cg.close(); process.exit(1);\n }\n\n // Create the vulnerability node\n const vulnNodeId = `vuln:${cveId}`;\n const now = Date.now();\n\n rawDb.run(\n `INSERT OR REPLACE INTO nodes\n (id, kind, name, qualified_name, file_path, language,\n start_line, end_line, start_column, end_column,\n is_exported, is_async, is_static, is_abstract, updated_at)\n VALUES (?, 'vulnerability', ?, ?, '', 'unknown', 0, 0, 0, 0, 0, 0, 0, 0, ?)`,\n [vulnNodeId, cveId, cveId, now],\n );\n\n rawDb.run(\n `INSERT OR REPLACE INTO sec_vulnerabilities\n (node_id, cve_id, severity_score, affected_ranges, fixed_version, summary, source_database)\n VALUES (?, ?, NULL, '[]', NULL, 'Manually registered', 'manual')`,\n [vulnNodeId, cveId],\n );\n\n // Create has_vulnerability edge\n rawDb.run(\n `INSERT OR IGNORE INTO edges (source, target, kind, confidence, confidence_score)\n VALUES (?, ?, 'has_vulnerability', 'extracted', 1.0)`,\n [depRow.node_id, vulnNodeId],\n );\n\n console.log(` ${green}\u2713${reset} Registered ${violet}${bold}${cveId}${reset} against ${violet}${pkgName}@${pkgVersion}${reset}`);\n cg.close();\n return;\n }\n\n // Handle --refresh: trigger fresh vulnerability enrichment\n if (opts.refresh) {\n console.error(` ${dim}Refreshing vulnerability data from configured databases...${reset}`);\n const { OsvAdapter } = await Promise.resolve().then(() => require('../../security/vuln/osv-adapter.js'));\n const { VulnerabilityDatabaseClient } = await Promise.resolve().then(() => require('../../security/vuln/client.js'));\n\n const adapters = config.securityDatabases.map((dbName: string) => {\n if (dbName.toUpperCase() === 'OSV') return new OsvAdapter();\n return null;\n }).filter(Boolean) as any[];\n\n const client = new VulnerabilityDatabaseClient(adapters, db);\n const result = await client.enrichAll();\n\n console.error(` ${green}\u2713${reset} Checked ${bold}${result.dependenciesChecked}${reset} dependencies, found ${bold}${result.vulnerabilitiesFound}${reset} vulnerabilities`);\n if (result.errors.length > 0) {\n console.error(` ${'\\x1b[33m'}\u26A0${reset} ${result.errors.length} error(s) during enrichment`);\n }\n console.error();\n }\n\n // Build query for listing vulnerabilities\n // Include source_manifests when group-by workspace is requested\n const selectSourceManifests = opts.groupBy === 'workspace' ? `,\\n d.source_manifests` : '';\n let query = `\n SELECT\n v.node_id, v.cve_id, v.severity_score, v.fixed_version, v.summary, v.source_database,\n v.epss_score, v.epss_percentile, v.risk_score,\n d.package_name, d.ecosystem, d.resolved_version, d.declared_constraint,\n d.staleness_score,\n r.verdict${selectSourceManifests}\n FROM sec_vulnerabilities v\n LEFT JOIN edges e ON e.target = v.node_id AND e.kind = 'has_vulnerability'\n LEFT JOIN sec_dependencies d ON d.node_id = e.source\n LEFT JOIN sec_reachability r ON r.vulnerability_node_id = v.node_id\n WHERE 1=1\n `;\n const params: any[] = [];\n\n // Apply severity filter\n if (opts.severity) {\n const severityRanges: Record<string, [number, number]> = {\n critical: [9.0, 10.0],\n high: [7.0, 8.9],\n medium: [4.0, 6.9],\n low: [0.1, 3.9],\n };\n const range = severityRanges[opts.severity.toLowerCase()];\n if (!range) {\n console.error(` \u2716 Invalid severity: ${opts.severity}. Use: critical, high, medium, low`);\n cg.close(); process.exit(1);\n }\n query += ` AND v.severity_score >= ? AND v.severity_score <= ?`;\n params.push(range[0], range[1]);\n }\n\n // Apply verdict filter\n if (opts.verdict) {\n const validVerdicts = ['affected', 'not_affected', 'under_investigation'];\n if (!validVerdicts.includes(opts.verdict)) {\n console.error(` \u2716 Invalid verdict: ${opts.verdict}. Use: affected, not_affected, under_investigation`);\n cg.close(); process.exit(1);\n }\n query += ` AND r.verdict = ?`;\n params.push(opts.verdict);\n }\n\n // Apply EPSS threshold filter\n if (opts.epss !== undefined) {\n const epssThreshold = parseFloat(opts.epss);\n if (isNaN(epssThreshold) || epssThreshold < 0 || epssThreshold > 1) {\n console.error(` \u2716 Invalid EPSS threshold: ${opts.epss}. Use a number between 0 and 1 (e.g. 0.5)`);\n cg.close(); process.exit(1);\n }\n query += ` AND v.epss_score >= ?`;\n params.push(epssThreshold);\n }\n\n // Resolve sort order\n const sortKey = opts.sort?.toLowerCase() ?? 'risk';\n const validSortKeys = ['risk', 'cvss', 'epss', 'name'];\n if (!validSortKeys.includes(sortKey)) {\n console.error(` \u2716 Invalid sort key: ${opts.sort}. Use: risk, cvss, epss, name`);\n cg.close(); process.exit(1);\n }\n const sortClause =\n sortKey === 'risk' ? `v.risk_score DESC NULLS LAST` :\n sortKey === 'cvss' ? `v.severity_score DESC NULLS LAST` :\n sortKey === 'epss' ? `v.epss_score DESC NULLS LAST` :\n `v.cve_id ASC`;\n query += ` ORDER BY ${sortClause}`;\n\n const rows: Array<{\n node_id: string;\n cve_id: string;\n severity_score: number | null;\n fixed_version: string | null;\n summary: string | null;\n source_database: string;\n epss_score: number | null;\n epss_percentile: number | null;\n risk_score: number | null;\n package_name: string | null;\n ecosystem: string | null;\n resolved_version: string | null;\n declared_constraint: string | null;\n staleness_score: number | null;\n verdict: string | null;\n source_manifests?: string | null;\n }> = rawDb.all(query, params);\n\n // Deduplicate by (cve_id, package_name, ecosystem) \u2014 same CVE can appear multiple\n // times if a package is declared in multiple manifests (monorepo) or has multiple\n // dep nodes. Keep the row with the worst verdict (affected > under_investigation > not_affected > null).\n const verdictRank = (v: string | null) =>\n v === 'affected' ? 3 : v === 'under_investigation' ? 2 : v === 'not_affected' ? 1 : 0;\n const deduped = new Map<string, typeof rows[0]>();\n for (const row of rows) {\n const key = `${row.cve_id}::${row.package_name ?? ''}::${row.ecosystem ?? ''}`;\n const existing = deduped.get(key);\n if (!existing || verdictRank(row.verdict) > verdictRank(existing.verdict)) {\n deduped.set(key, row);\n }\n }\n const dedupedRows = [...deduped.values()];\n\n // Filter out suppressed CVEs\n const suppressions = new SuppressionManager(target);\n const suppressedRows = dedupedRows.filter(row => suppressions.isSuppressed(row.cve_id));\n const filteredRows = dedupedRows.filter(row => !suppressions.isSuppressed(row.cve_id));\n\n if (filteredRows.length === 0) {\n const filterNote = (opts.severity || opts.verdict)\n ? ` matching filters`\n : '';\n console.log(`\\n ${dim}No vulnerabilities found${filterNote}.${reset}\\n`);\n if (suppressedRows.length > 0) {\n console.log(` ${dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${reset}\\n`);\n }\n cg.close();\n return;\n }\n\n // \u2500\u2500 Render a single vulnerability row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function printVulnRow(row: (typeof filteredRows)[0], indent = ' '): void {\n // Severity badge\n const score = row.severity_score;\n let severityLabel: string;\n let severityColor: string;\n if (score == null) {\n severityLabel = 'unknown';\n severityColor = dim;\n } else if (score >= 9.0) {\n severityLabel = 'CRITICAL';\n severityColor = '\\x1b[31m';\n } else if (score >= 7.0) {\n severityLabel = 'HIGH';\n severityColor = '\\x1b[31m';\n } else if (score >= 4.0) {\n severityLabel = 'MEDIUM';\n severityColor = '\\x1b[33m';\n } else {\n severityLabel = 'LOW';\n severityColor = dim;\n }\n\n // Verdict badge\n let verdictLabel: string;\n let verdictColor: string;\n if (!row.verdict) {\n verdictLabel = 'pending';\n verdictColor = dim;\n } else if (row.verdict === 'affected') {\n verdictLabel = 'affected';\n verdictColor = '\\x1b[31m';\n } else if (row.verdict === 'not_affected') {\n verdictLabel = 'not affected';\n verdictColor = green;\n } else {\n verdictLabel = 'investigating';\n verdictColor = '\\x1b[33m';\n }\n\n const pkg = row.package_name\n ? `${row.package_name}@${row.resolved_version || row.declared_constraint || '?'}`\n : 'unknown package';\n\n // EPSS badge\n let epssBadge = '';\n if (row.epss_score != null && row.epss_percentile != null) {\n const epssColor = row.epss_score >= 0.3 ? '\\x1b[33m' : dim;\n const scoreStr = row.epss_score.toFixed(2);\n const pctStr = `${Math.round(row.epss_percentile * 100)}th%`;\n epssBadge = ` ${epssColor}${dim}[EPSS: ${scoreStr} / ${pctStr}]${reset}`;\n }\n\n // Risk score badge\n let riskBadge = '';\n if (row.risk_score != null) {\n const riskColor = row.risk_score >= 7 ? '\\x1b[31m' : row.risk_score >= 4 ? '\\x1b[33m' : dim;\n riskBadge = ` ${riskColor}[Risk: ${row.risk_score.toFixed(1)}]${reset}`;\n }\n\n console.log(`${indent}${severityColor}${severityLabel}${reset} ${violet}${bold}${row.cve_id}${reset} ${dim}${pkg}${reset} [${verdictColor}${verdictLabel}${reset}]${epssBadge}${riskBadge}`);\n\n if (row.summary && row.summary !== 'Manually registered') {\n const truncated = row.summary.length > 100 ? row.summary.slice(0, 100) + '\u2026' : row.summary;\n console.log(`${indent} ${dim}${truncated}${reset}`);\n }\n\n // Staleness badge (when --stale flag is set)\n if (opts.stale && row.staleness_score != null) {\n const s = row.staleness_score;\n const staleColor = s >= 0.7 ? '\\x1b[31m' : s >= 0.4 ? '\\x1b[33m' : dim;\n console.log(`${indent} ${staleColor}${dim}[staleness: ${s.toFixed(2)}]${reset}`);\n }\n\n // Fix suggestion\n if (row.fixed_version && row.ecosystem && row.package_name) {\n const fix = formatFixSuggestion(row.ecosystem, row.package_name, row.fixed_version);\n if (fix) {\n console.log(`${indent} ${fix}`);\n }\n }\n\n console.log();\n }\n\n // \u2500\u2500 Output: grouped or flat \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (opts.groupBy === 'workspace') {\n // Group by workspace (directory of first source manifest)\n const groups = new Map<string, Array<(typeof filteredRows)[0]>>();\n for (const row of filteredRows) {\n const ws = workspaceFromManifests(row.source_manifests ?? null);\n if (!groups.has(ws)) groups.set(ws, []);\n groups.get(ws)!.push(row);\n }\n\n // Only apply workspace grouping when there are multiple distinct workspaces\n const workspaces = Array.from(groups.keys());\n if (workspaces.length <= 1) {\n // Single workspace \u2014 fall through to flat output\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const row of filteredRows) {\n printVulnRow(row);\n }\n } else {\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const ws of workspaces) {\n const wsRows = groups.get(ws)!;\n const count = wsRows.length;\n const header = `Workspace: ${ws} (${count} vulnerabilit${count === 1 ? 'y' : 'ies'})`;\n const line = '\u2500'.repeat(header.length);\n console.log(` ${bold}${header}${reset}`);\n console.log(` ${dim}${line}${reset}`);\n for (const row of wsRows) {\n printVulnRow(row);\n }\n }\n }\n } else {\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const row of filteredRows) {\n printVulnRow(row);\n }\n }\n\n if (suppressedRows.length > 0) {\n console.log(` ${dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${reset}\\n`);\n }\n\n // \u2500\u2500 CI exit codes: --fail-on \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (opts.failOn !== undefined) {\n const failOn = opts.failOn;\n\n let failCount = 0;\n let failReason = '';\n\n if (failOn === 'affected') {\n failCount = filteredRows.filter(r => r.verdict === 'affected').length;\n failReason = `affected`;\n } else if (failOn === 'any') {\n failCount = filteredRows.length;\n failReason = `any`;\n } else if (failOn === 'critical') {\n failCount = filteredRows.filter(r => r.severity_score != null && r.severity_score >= 9.0).length;\n failReason = `critical`;\n } else if (failOn === 'high') {\n failCount = filteredRows.filter(r => r.severity_score != null && r.severity_score >= 7.0).length;\n failReason = `high`;\n } else {\n const epssThreshold = parseEpssFailOn(failOn);\n if (epssThreshold !== null) {\n failCount = filteredRows.filter(r => r.epss_score != null && r.epss_score >= epssThreshold).length;\n failReason = `epss=${epssThreshold}`;\n }\n }\n\n if (failCount > 0) {\n console.log(` \\x1b[31m\u2716\\x1b[0m --fail-on ${failReason}: ${failCount} ${failReason === 'any' ? '' : `${failReason} `}vulnerabilit${failCount === 1 ? 'y' : 'ies'} found. Exiting with code 1.`);\n cg.close();\n process.exit(1);\n }\n }\n\n cg.close();\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Command } from 'commander';\nimport * as path from 'path';\nimport { loadConfig } from '../../config';\nimport { dim, reset, violet, bold, green } from '../ui';\nimport { formatFixSuggestion } from '../../security/export/fix-suggestions';\nimport { SuppressionManager } from '../../security/suppressions';\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Parse an `epss=N` fail-on value and return the threshold, or null if not an epss condition. */\nfunction parseEpssFailOn(failOn: string): number | null {\n const m = failOn.match(/^epss=(.+)$/);\n if (!m) return null;\n const n = parseFloat(m[1]);\n return isNaN(n) ? null : n;\n}\n\n/** Extract workspace label from a source_manifests JSON string. */\nfunction workspaceFromManifests(sourceManifests: string | null): string {\n if (!sourceManifests) return 'root';\n try {\n const manifests: string[] = JSON.parse(sourceManifests);\n if (!manifests.length) return 'root';\n const dir = path.dirname(manifests[0]);\n return dir === '.' ? 'root' : dir;\n } catch {\n return 'root';\n }\n}\n\nexport function register(program: Command): void {\n program\n .command('vulns [projectPath]')\n .description('List vulnerabilities with reachability verdicts and severity')\n .option('--severity <level>', 'Filter by severity: critical, high, medium, low')\n .option('--verdict <verdict>', 'Filter by verdict: affected, not_affected, under_investigation')\n .option('--refresh', 'Trigger fresh vulnerability enrichment before listing')\n .option('--epss <threshold>', 'Filter by EPSS score (e.g. 0.5 shows only vulns with EPSS >= 0.5)')\n .option('--stale', 'Show staleness score of the affected dependency alongside each CVE')\n .option('--sort <key>', 'Sort results by: risk (default), cvss, epss, name')\n .option('--add <cveId>', 'Manually register a CVE')\n .option('--package <name>', 'Package name for --add')\n .option('--version <ver>', 'Package version for --add')\n .option('--fail-on <condition>', 'Exit 1 if condition is met: affected, any, critical, high, epss=N')\n .option('--group-by <key>', 'Group output by: workspace')\n .action(async (projectPath: string | undefined, opts: {\n severity?: string;\n verdict?: string;\n refresh?: boolean;\n epss?: string;\n stale?: boolean;\n sort?: string;\n add?: string;\n package?: string;\n version?: string;\n failOn?: string;\n groupBy?: string;\n }) => {\n const target = path.resolve(projectPath ?? process.cwd());\n const config = await loadConfig(target);\n\n if (!config.enableSecurity) {\n console.error(`\\n ${'\\x1b[33m'}\u26A0 Security analysis is disabled.${reset}`);\n console.error(` ${dim}Enable it in .kirograph/config.json:${reset} ${violet}${bold}\"enableSecurity\": true${reset}`);\n console.error(` ${dim}Then re-run:${reset} ${violet}${bold}kirograph index${reset}\\n`);\n process.exit(1);\n }\n\n // Validate --fail-on early\n if (opts.failOn !== undefined) {\n const validFailOns = ['affected', 'any', 'critical', 'high'];\n const isEpss = parseEpssFailOn(opts.failOn) !== null;\n if (!validFailOns.includes(opts.failOn) && !isEpss) {\n console.error(` \u2716 Invalid --fail-on value: ${opts.failOn}. Use: affected, any, critical, high, epss=N`);\n process.exit(1);\n }\n }\n\n // Validate --group-by early\n if (opts.groupBy !== undefined && opts.groupBy !== 'workspace') {\n console.error(` \u2716 Invalid --group-by value: ${opts.groupBy}. Supported: workspace`);\n process.exit(1);\n }\n\n const KiroGraph = (await Promise.resolve().then(() => require('../../index.js'))).default;\n if (!KiroGraph.isInitialized(target)) {\n console.error(' \u2716 KiroGraph not initialized. Run: kirograph init');\n process.exit(1);\n }\n\n const cg = await KiroGraph.open(target);\n const db = cg.getDatabase();\n db.applySecuritySchema();\n const rawDb = db.getRawDb();\n\n // Handle --add: manually register a CVE\n if (opts.add) {\n if (!opts.package || !opts.version) {\n console.error(` \u2716 --add requires --package <name> and --version <ver>`);\n cg.close(); process.exit(1);\n }\n\n const cveId = opts.add;\n const pkgName = opts.package;\n const pkgVersion = opts.version;\n\n // Find the matching dependency node\n const depRow: { node_id: string; ecosystem: string } | undefined = rawDb.get(\n `SELECT node_id, ecosystem FROM sec_dependencies\n WHERE package_name = ? AND (resolved_version = ? OR declared_constraint = ?)`,\n [pkgName, pkgVersion, pkgVersion],\n );\n\n if (!depRow) {\n console.error(` \u2716 No dependency found matching ${violet}${pkgName}@${pkgVersion}${reset}`);\n console.error(` ${dim}Run${reset} ${violet}${bold}kirograph index${reset} ${dim}first to discover dependencies.${reset}`);\n cg.close(); process.exit(1);\n }\n\n // Create the vulnerability node\n const vulnNodeId = `vuln:${cveId}`;\n const now = Date.now();\n\n rawDb.run(\n `INSERT OR REPLACE INTO nodes\n (id, kind, name, qualified_name, file_path, language,\n start_line, end_line, start_column, end_column,\n is_exported, is_async, is_static, is_abstract, updated_at)\n VALUES (?, 'vulnerability', ?, ?, '', 'unknown', 0, 0, 0, 0, 0, 0, 0, 0, ?)`,\n [vulnNodeId, cveId, cveId, now],\n );\n\n rawDb.run(\n `INSERT OR REPLACE INTO sec_vulnerabilities\n (node_id, cve_id, severity_score, affected_ranges, fixed_version, summary, source_database)\n VALUES (?, ?, NULL, '[]', NULL, 'Manually registered', 'manual')`,\n [vulnNodeId, cveId],\n );\n\n // Create has_vulnerability edge\n rawDb.run(\n `INSERT OR IGNORE INTO edges (source, target, kind, confidence, confidence_score)\n VALUES (?, ?, 'has_vulnerability', 'extracted', 1.0)`,\n [depRow.node_id, vulnNodeId],\n );\n\n console.log(` ${green}\u2713${reset} Registered ${violet}${bold}${cveId}${reset} against ${violet}${pkgName}@${pkgVersion}${reset}`);\n cg.close();\n return;\n }\n\n // Handle --refresh: trigger fresh vulnerability enrichment\n if (opts.refresh) {\n console.error(` ${dim}Refreshing vulnerability data from configured databases...${reset}`);\n const { OsvAdapter } = await Promise.resolve().then(() => require('../../security/vuln/osv-adapter.js'));\n const { VulnerabilityDatabaseClient } = await Promise.resolve().then(() => require('../../security/vuln/client.js'));\n\n const adapters = config.securityDatabases.map((dbName: string) => {\n if (dbName.toUpperCase() === 'OSV') return new OsvAdapter();\n return null;\n }).filter(Boolean) as any[];\n\n const client = new VulnerabilityDatabaseClient(adapters, db, undefined, target);\n const result = await client.enrichAll();\n\n console.error(` ${green}\u2713${reset} Checked ${bold}${result.dependenciesChecked}${reset} dependencies, found ${bold}${result.vulnerabilitiesFound}${reset} vulnerabilities`);\n if (result.errors.length > 0) {\n console.error(` ${'\\x1b[33m'}\u26A0${reset} ${result.errors.length} error(s) during enrichment`);\n }\n console.error();\n }\n\n // Build query for listing vulnerabilities\n // Include source_manifests when group-by workspace is requested\n const selectSourceManifests = opts.groupBy === 'workspace' ? `,\\n d.source_manifests` : '';\n let query = `\n SELECT\n v.node_id, v.cve_id, v.severity_score, v.fixed_version, v.summary, v.source_database,\n v.epss_score, v.epss_percentile, v.risk_score,\n d.package_name, d.ecosystem, d.resolved_version, d.declared_constraint,\n d.staleness_score,\n r.verdict${selectSourceManifests}\n FROM sec_vulnerabilities v\n LEFT JOIN edges e ON e.target = v.node_id AND e.kind = 'has_vulnerability'\n LEFT JOIN sec_dependencies d ON d.node_id = e.source\n LEFT JOIN sec_reachability r ON r.vulnerability_node_id = v.node_id\n WHERE 1=1\n `;\n const params: any[] = [];\n\n // Apply severity filter.\n // Bounds are half-open [min, max) and MUST mirror the display buckets in\n // printVulnRow() so the filter and the rendered label never disagree:\n // CRITICAL >= 9.0, HIGH >= 7.0, MEDIUM >= 4.0, LOW < 4.0 (incl. 0.0).\n if (opts.severity) {\n const severityRanges: Record<string, [number, number]> = {\n critical: [9.0, 10.01],\n high: [7.0, 9.0],\n medium: [4.0, 7.0],\n low: [0.0, 4.0],\n };\n const range = severityRanges[opts.severity.toLowerCase()];\n if (!range) {\n console.error(` \u2716 Invalid severity: ${opts.severity}. Use: critical, high, medium, low`);\n cg.close(); process.exit(1);\n }\n // severity_score IS NULL means \"unknown\" \u2014 excluded from every band.\n query += ` AND v.severity_score IS NOT NULL AND v.severity_score >= ? AND v.severity_score < ?`;\n params.push(range[0], range[1]);\n }\n\n // Apply verdict filter\n if (opts.verdict) {\n const validVerdicts = ['affected', 'not_affected', 'under_investigation'];\n if (!validVerdicts.includes(opts.verdict)) {\n console.error(` \u2716 Invalid verdict: ${opts.verdict}. Use: affected, not_affected, under_investigation`);\n cg.close(); process.exit(1);\n }\n query += ` AND r.verdict = ?`;\n params.push(opts.verdict);\n }\n\n // Apply EPSS threshold filter\n if (opts.epss !== undefined) {\n const epssThreshold = parseFloat(opts.epss);\n if (isNaN(epssThreshold) || epssThreshold < 0 || epssThreshold > 1) {\n console.error(` \u2716 Invalid EPSS threshold: ${opts.epss}. Use a number between 0 and 1 (e.g. 0.5)`);\n cg.close(); process.exit(1);\n }\n query += ` AND v.epss_score >= ?`;\n params.push(epssThreshold);\n }\n\n // Resolve sort order\n const sortKey = opts.sort?.toLowerCase() ?? 'risk';\n const validSortKeys = ['risk', 'cvss', 'epss', 'name'];\n if (!validSortKeys.includes(sortKey)) {\n console.error(` \u2716 Invalid sort key: ${opts.sort}. Use: risk, cvss, epss, name`);\n cg.close(); process.exit(1);\n }\n const sortClause =\n sortKey === 'risk' ? `v.risk_score DESC NULLS LAST` :\n sortKey === 'cvss' ? `v.severity_score DESC NULLS LAST` :\n sortKey === 'epss' ? `v.epss_score DESC NULLS LAST` :\n `v.cve_id ASC`;\n query += ` ORDER BY ${sortClause}`;\n\n const rows: Array<{\n node_id: string;\n cve_id: string;\n severity_score: number | null;\n fixed_version: string | null;\n summary: string | null;\n source_database: string;\n epss_score: number | null;\n epss_percentile: number | null;\n risk_score: number | null;\n package_name: string | null;\n ecosystem: string | null;\n resolved_version: string | null;\n declared_constraint: string | null;\n staleness_score: number | null;\n verdict: string | null;\n source_manifests?: string | null;\n }> = rawDb.all(query, params);\n\n // Deduplicate by (cve_id, package_name, ecosystem) \u2014 same CVE can appear multiple\n // times if a package is declared in multiple manifests (monorepo) or has multiple\n // dep nodes. Keep the row with the worst verdict (affected > under_investigation > not_affected > null).\n const verdictRank = (v: string | null) =>\n v === 'affected' ? 3 : v === 'under_investigation' ? 2 : v === 'not_affected' ? 1 : 0;\n const deduped = new Map<string, typeof rows[0]>();\n for (const row of rows) {\n const key = `${row.cve_id}::${row.package_name ?? ''}::${row.ecosystem ?? ''}`;\n const existing = deduped.get(key);\n if (!existing || verdictRank(row.verdict) > verdictRank(existing.verdict)) {\n deduped.set(key, row);\n }\n }\n const dedupedRows = [...deduped.values()];\n\n // Filter out suppressed CVEs\n const suppressions = new SuppressionManager(target);\n const suppressedRows = dedupedRows.filter(row => suppressions.isSuppressed(row.cve_id));\n const filteredRows = dedupedRows.filter(row => !suppressions.isSuppressed(row.cve_id));\n\n // Maven has no lock file: a <dependency> with no explicit <version> (the\n // common case under a BOM parent like spring-boot-starter-parent) never\n // gets a resolved version, so it's silently skipped during vulnerability\n // enrichment. Hint at the fix when that's likely hiding results.\n const unresolvedMavenCount = (rawDb.get(\n `SELECT COUNT(*) as count FROM sec_dependencies\n WHERE ecosystem = 'maven' AND (resolved_version IS NULL OR resolved_version = '')\n AND (declared_constraint IS NULL OR declared_constraint = '')`,\n ) as { count: number } | undefined)?.count ?? 0;\n\n if (filteredRows.length === 0) {\n const filterNote = (opts.severity || opts.verdict)\n ? ` matching filters`\n : '';\n console.log(`\\n ${dim}No vulnerabilities found${filterNote}.${reset}\\n`);\n if (suppressedRows.length > 0) {\n console.log(` ${dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${reset}\\n`);\n }\n if (unresolvedMavenCount > 0) {\n console.log(` ${dim}${unresolvedMavenCount} Maven dependenc${unresolvedMavenCount === 1 ? 'y has' : 'ies have'} no resolved version (BOM-managed, e.g. via spring-boot-starter-parent) and were skipped.${reset}`);\n console.log(` ${dim}Run${reset} ${violet}${bold}mvn dependency:tree -DoutputFile=dependency-tree.txt${reset}${dim} next to pom.xml, then${reset} ${violet}${bold}kirograph index${dim} again to resolve them.${reset}\\n`);\n }\n cg.close();\n return;\n }\n\n // \u2500\u2500 Render a single vulnerability row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n function printVulnRow(row: (typeof filteredRows)[0], indent = ' '): void {\n // Severity badge\n const score = row.severity_score;\n let severityLabel: string;\n let severityColor: string;\n if (score == null) {\n severityLabel = 'unknown';\n severityColor = dim;\n } else if (score >= 9.0) {\n severityLabel = 'CRITICAL';\n severityColor = '\\x1b[31m';\n } else if (score >= 7.0) {\n severityLabel = 'HIGH';\n severityColor = '\\x1b[31m';\n } else if (score >= 4.0) {\n severityLabel = 'MEDIUM';\n severityColor = '\\x1b[33m';\n } else {\n severityLabel = 'LOW';\n severityColor = dim;\n }\n\n // Verdict badge\n let verdictLabel: string;\n let verdictColor: string;\n if (!row.verdict) {\n verdictLabel = 'pending';\n verdictColor = dim;\n } else if (row.verdict === 'affected') {\n verdictLabel = 'affected';\n verdictColor = '\\x1b[31m';\n } else if (row.verdict === 'not_affected') {\n verdictLabel = 'not affected';\n verdictColor = green;\n } else {\n verdictLabel = 'investigating';\n verdictColor = '\\x1b[33m';\n }\n\n const pkg = row.package_name\n ? `${row.package_name}@${row.resolved_version || row.declared_constraint || '?'}`\n : 'unknown package';\n\n // EPSS badge\n let epssBadge = '';\n if (row.epss_score != null && row.epss_percentile != null) {\n const epssColor = row.epss_score >= 0.3 ? '\\x1b[33m' : dim;\n const scoreStr = row.epss_score.toFixed(2);\n const pctStr = `${Math.round(row.epss_percentile * 100)}th%`;\n epssBadge = ` ${epssColor}${dim}[EPSS: ${scoreStr} / ${pctStr}]${reset}`;\n }\n\n // Risk score badge\n let riskBadge = '';\n if (row.risk_score != null) {\n const riskColor = row.risk_score >= 7 ? '\\x1b[31m' : row.risk_score >= 4 ? '\\x1b[33m' : dim;\n riskBadge = ` ${riskColor}[Risk: ${row.risk_score.toFixed(1)}]${reset}`;\n }\n\n console.log(`${indent}${severityColor}${severityLabel}${reset} ${violet}${bold}${row.cve_id}${reset} ${dim}${pkg}${reset} [${verdictColor}${verdictLabel}${reset}]${epssBadge}${riskBadge}`);\n\n if (row.summary && row.summary !== 'Manually registered') {\n const truncated = row.summary.length > 100 ? row.summary.slice(0, 100) + '\u2026' : row.summary;\n console.log(`${indent} ${dim}${truncated}${reset}`);\n }\n\n // Staleness badge (when --stale flag is set)\n if (opts.stale && row.staleness_score != null) {\n const s = row.staleness_score;\n const staleColor = s >= 0.7 ? '\\x1b[31m' : s >= 0.4 ? '\\x1b[33m' : dim;\n console.log(`${indent} ${staleColor}${dim}[staleness: ${s.toFixed(2)}]${reset}`);\n }\n\n // Fix suggestion\n if (row.fixed_version && row.ecosystem && row.package_name) {\n const fix = formatFixSuggestion(row.ecosystem, row.package_name, row.fixed_version);\n if (fix) {\n console.log(`${indent} ${fix}`);\n }\n }\n\n console.log();\n }\n\n // \u2500\u2500 Output: grouped or flat \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (opts.groupBy === 'workspace') {\n // Group by workspace (directory of first source manifest)\n const groups = new Map<string, Array<(typeof filteredRows)[0]>>();\n for (const row of filteredRows) {\n const ws = workspaceFromManifests(row.source_manifests ?? null);\n if (!groups.has(ws)) groups.set(ws, []);\n groups.get(ws)!.push(row);\n }\n\n // Only apply workspace grouping when there are multiple distinct workspaces\n const workspaces = Array.from(groups.keys());\n if (workspaces.length <= 1) {\n // Single workspace \u2014 fall through to flat output\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const row of filteredRows) {\n printVulnRow(row);\n }\n } else {\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const ws of workspaces) {\n const wsRows = groups.get(ws)!;\n const count = wsRows.length;\n const header = `Workspace: ${ws} (${count} vulnerabilit${count === 1 ? 'y' : 'ies'})`;\n const line = '\u2500'.repeat(header.length);\n console.log(` ${bold}${header}${reset}`);\n console.log(` ${dim}${line}${reset}`);\n for (const row of wsRows) {\n printVulnRow(row);\n }\n }\n }\n } else {\n console.log(`\\n ${bold}Vulnerabilities${reset} (${filteredRows.length})\\n`);\n for (const row of filteredRows) {\n printVulnRow(row);\n }\n }\n\n if (suppressedRows.length > 0) {\n console.log(` ${dim}${suppressedRows.length} CVE(s) suppressed \u2014 kirograph vuln suppressions to review${reset}\\n`);\n }\n\n // Hint when reachability hasn't been computed yet (verdict is pending).\n // vulns --refresh only re-queries vulnerability data; the call-graph\n // reachability analysis that resolves [pending] \u2192 [affected]/[not affected]\n // runs during `kirograph index`.\n const pendingCount = filteredRows.filter(r => !r.verdict).length;\n if (pendingCount > 0) {\n console.log(` ${dim}${pendingCount} vulnerabilit${pendingCount === 1 ? 'y is' : 'ies are'} [pending] reachability analysis \u2014 run ${reset}kirograph index${dim} to compute call-graph verdicts.${reset}\\n`);\n }\n\n if (unresolvedMavenCount > 0) {\n console.log(` ${dim}${unresolvedMavenCount} Maven dependenc${unresolvedMavenCount === 1 ? 'y has' : 'ies have'} no resolved version (BOM-managed, e.g. via spring-boot-starter-parent) and were skipped.${reset}`);\n console.log(` ${dim}Run${reset} ${violet}${bold}mvn dependency:tree -DoutputFile=dependency-tree.txt${reset}${dim} next to pom.xml, then${reset} ${violet}${bold}kirograph index${dim} again to resolve them.${reset}\\n`);\n }\n\n // \u2500\u2500 CI exit codes: --fail-on \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n if (opts.failOn !== undefined) {\n const failOn = opts.failOn;\n\n let failCount = 0;\n let failReason = '';\n\n if (failOn === 'affected') {\n failCount = filteredRows.filter(r => r.verdict === 'affected').length;\n failReason = `affected`;\n } else if (failOn === 'any') {\n failCount = filteredRows.length;\n failReason = `any`;\n } else if (failOn === 'critical') {\n failCount = filteredRows.filter(r => r.severity_score != null && r.severity_score >= 9.0).length;\n failReason = `critical`;\n } else if (failOn === 'high') {\n failCount = filteredRows.filter(r => r.severity_score != null && r.severity_score >= 7.0).length;\n failReason = `high`;\n } else {\n const epssThreshold = parseEpssFailOn(failOn);\n if (epssThreshold !== null) {\n failCount = filteredRows.filter(r => r.epss_score != null && r.epss_score >= epssThreshold).length;\n failReason = `epss=${epssThreshold}`;\n }\n }\n\n if (failCount > 0) {\n console.log(` \\x1b[31m\u2716\\x1b[0m --fail-on ${failReason}: ${failCount} ${failReason === 'any' ? '' : `${failReason} `}vulnerabilit${failCount === 1 ? 'y' : 'ies'} found. Exiting with code 1.`);\n cg.close();\n process.exit(1);\n }\n }\n\n cg.close();\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -227,6 +227,62 @@ function register(program) {
227
227
  console.log();
228
228
  }
229
229
  });
230
+ wiki.command("links <slug>").description("Show outgoing, broken, and incoming [[slug]] links for a page").option("--format <fmt>", "Output format: text, json", "text").action(async (slug, opts) => {
231
+ const cwd = process.cwd();
232
+ const w = await getWiki(cwd);
233
+ const links = w.getLinks(slug);
234
+ if (!links) {
235
+ console.error(` \u2716 Wiki page "${slug}" not found. Run \`kirograph wiki list\` to see available pages.`);
236
+ process.exit(1);
237
+ }
238
+ if (opts.format === "json") {
239
+ console.log(JSON.stringify(links, null, 2));
240
+ return;
241
+ }
242
+ console.log(`
243
+ ${(0, import_ui.section)("Wiki Links:")} ${import_ui.violet}${import_ui.bold}${slug}${import_ui.reset}
244
+ `);
245
+ console.log(` ${import_ui.bold}Outgoing${import_ui.reset} ${import_ui.dim}(${links.outgoing.length})${import_ui.reset}`);
246
+ if (links.outgoing.length === 0) {
247
+ console.log(` ${import_ui.dim}(none)${import_ui.reset}`);
248
+ } else {
249
+ for (const s of links.outgoing) console.log(` ${import_ui.violet}\u2192${import_ui.reset} [[${s}]]`);
250
+ }
251
+ if (links.broken.length > 0) {
252
+ console.log(`
253
+ ${yellow}Broken${import_ui.reset} ${import_ui.dim}(${links.broken.length})${import_ui.reset}`);
254
+ for (const s of links.broken) console.log(` ${yellow}\u26A0${import_ui.reset} [[${s}]] ${import_ui.dim}\u2014 page does not exist${import_ui.reset}`);
255
+ }
256
+ console.log(`
257
+ ${import_ui.bold}Incoming${import_ui.reset} ${import_ui.dim}(${links.incoming.length}) \u2014 pages that link here${import_ui.reset}`);
258
+ if (links.incoming.length === 0) {
259
+ console.log(` ${import_ui.dim}(none)${import_ui.reset}`);
260
+ } else {
261
+ for (const s of links.incoming) console.log(` ${import_ui.violet}\u2190${import_ui.reset} [[${s}]]`);
262
+ }
263
+ console.log();
264
+ });
265
+ wiki.command("rename <from> <to>").description("Rename a page slug, moving its file and updating every [[slug]] reference to it").action(async (from, to) => {
266
+ const cwd = process.cwd();
267
+ const w = await getWiki(cwd);
268
+ let result;
269
+ try {
270
+ result = w.rename(from, to);
271
+ } catch (err) {
272
+ console.error(` \u2716 ${err instanceof Error ? err.message : String(err)}`);
273
+ process.exit(1);
274
+ }
275
+ console.log(`
276
+ ${import_ui.green}\u2713${import_ui.reset} Renamed ${import_ui.violet}[[${result.from}]]${import_ui.reset} \u2192 ${import_ui.violet}[[${result.to}]]${import_ui.reset}
277
+ `);
278
+ if (result.linksUpdated.length > 0) {
279
+ console.log(` ${import_ui.bold}Links updated in ${result.linksUpdated.length} page(s):${import_ui.reset}`);
280
+ for (const s of result.linksUpdated) console.log(` ${import_ui.dim}\xB7${import_ui.reset} ${s}`);
281
+ } else {
282
+ console.log(` ${import_ui.dim}No other pages referenced [[${result.from}]].${import_ui.reset}`);
283
+ }
284
+ console.log();
285
+ });
230
286
  wiki.command("reindex").description("Rebuild SQLite index from .kirograph/wiki/*.md files").action(async () => {
231
287
  const cwd = process.cwd();
232
288
  const w = await getWiki(cwd);