kirograph 0.16.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +227 -8
  2. package/dist/bin/commands/affected.js +40 -5
  3. package/dist/bin/commands/affected.js.map +2 -2
  4. package/dist/bin/commands/data.js +665 -0
  5. package/dist/bin/commands/data.js.map +7 -0
  6. package/dist/bin/commands/help.js +5 -0
  7. package/dist/bin/commands/help.js.map +2 -2
  8. package/dist/bin/installer/config-prompt.js +28 -1
  9. package/dist/bin/installer/config-prompt.js.map +2 -2
  10. package/dist/bin/installer/index.js +28 -1
  11. package/dist/bin/installer/index.js.map +2 -2
  12. package/dist/bin/installer/steering.js +33 -0
  13. package/dist/bin/installer/steering.js.map +2 -2
  14. package/dist/bin/installer/targets/index.js.map +1 -1
  15. package/dist/bin/installer/targets/kiro.js +2 -2
  16. package/dist/bin/installer/targets/kiro.js.map +2 -2
  17. package/dist/bin/kirograph.js +3 -1
  18. package/dist/bin/kirograph.js.map +3 -3
  19. package/dist/bin/progress.js +30 -0
  20. package/dist/bin/progress.js.map +2 -2
  21. package/dist/compression/naive-cost.js +25 -0
  22. package/dist/compression/naive-cost.js.map +2 -2
  23. package/dist/compression/tracker.js +11 -2
  24. package/dist/compression/tracker.js.map +2 -2
  25. package/dist/compression/types.js.map +1 -1
  26. package/dist/config.js +37 -1
  27. package/dist/config.js.map +2 -2
  28. package/dist/core/pipeline.js +56 -2
  29. package/dist/core/pipeline.js.map +2 -2
  30. package/dist/data/filters.js +105 -0
  31. package/dist/data/filters.js.map +7 -0
  32. package/dist/data/indexer.js +225 -0
  33. package/dist/data/indexer.js.map +7 -0
  34. package/dist/data/linker.js +150 -0
  35. package/dist/data/linker.js.map +7 -0
  36. package/dist/data/lint.js +109 -0
  37. package/dist/data/lint.js.map +7 -0
  38. package/dist/data/parsers/csv.js +132 -0
  39. package/dist/data/parsers/csv.js.map +7 -0
  40. package/dist/data/parsers/excel.js +88 -0
  41. package/dist/data/parsers/excel.js.map +7 -0
  42. package/dist/data/parsers/index.js +79 -0
  43. package/dist/data/parsers/index.js.map +7 -0
  44. package/dist/data/parsers/json-array.js +89 -0
  45. package/dist/data/parsers/json-array.js.map +7 -0
  46. package/dist/data/parsers/jsonl.js +84 -0
  47. package/dist/data/parsers/jsonl.js.map +7 -0
  48. package/dist/data/parsers/parquet.js +95 -0
  49. package/dist/data/parsers/parquet.js.map +7 -0
  50. package/dist/data/profiler.js +182 -0
  51. package/dist/data/profiler.js.map +7 -0
  52. package/dist/data/queries.js +512 -0
  53. package/dist/data/queries.js.map +7 -0
  54. package/dist/data/types.js +17 -0
  55. package/dist/data/types.js.map +7 -0
  56. package/dist/db/data-schema.sql +61 -0
  57. package/dist/db/database.js +11 -0
  58. package/dist/db/database.js.map +2 -2
  59. package/dist/mcp/tool-names.js +9 -1
  60. package/dist/mcp/tool-names.js.map +2 -2
  61. package/dist/mcp/tools.js +423 -0
  62. package/dist/mcp/tools.js.map +2 -2
  63. package/dist/types.js.map +1 -1
  64. package/package.json +4 -2
@@ -66,6 +66,10 @@ KiroGraph builds a semantic knowledge graph of your codebase. Use its MCP tools
66
66
  | What does package X depend on? | \`kirograph_package\` |
67
67
  | Run a command with token savings | \`kirograph_exec\` |
68
68
  | Check token savings stats | \`kirograph_gain\` |
69
+ | What data files are indexed? | \`kirograph_data_list\` |
70
+ | What columns does this dataset have? | \`kirograph_data_describe\` |
71
+ | Query rows with filters | \`kirograph_data_query\` |
72
+ | Aggregate data (sum, avg, count) | \`kirograph_data_aggregate\` |
69
73
 
70
74
  ---
71
75
 
@@ -382,6 +386,35 @@ and gives you structured navigation instead of raw file content.
382
386
  `;
383
387
  content = content.trimEnd() + "\n\n" + docsSection.trim() + "\n";
384
388
  }
389
+ if (opts?.enableData) {
390
+ const dataSection = `
391
+ ## Data
392
+
393
+ KiroGraph indexes tabular data files (CSV, TSV, JSONL, JSON, Excel, Parquet) for structured
394
+ querying. Use \`kirograph_data_describe\` to understand a dataset's schema without loading
395
+ the file. Use \`kirograph_data_query\` with filters to retrieve specific rows.
396
+
397
+ **Available tools:**
398
+ - \`kirograph_data_list\` \u2014 list all indexed datasets with row/column counts
399
+ - \`kirograph_data_describe\` \u2014 full schema profile: column names, types, cardinality, null%, samples
400
+ - \`kirograph_data_query\` \u2014 filtered row retrieval with structured operators (eq, gt, contains, in, between)
401
+ - \`kirograph_data_aggregate\` \u2014 server-side GROUP BY: count, sum, avg, min, max, count_distinct
402
+ - \`kirograph_data_search\` \u2014 search column names and sample values by keyword
403
+
404
+ **When to use:** Instead of reading a CSV/data file directly (which floods context with raw rows),
405
+ use \`kirograph_data_describe\` to understand the schema, then \`kirograph_data_query\` with
406
+ filters to get only the rows you need. For summary statistics, use \`kirograph_data_aggregate\`
407
+ to compute results server-side. This saves 95-99% of tokens compared to reading raw data files.
408
+
409
+ \`\`\`
410
+ kirograph_data_list()
411
+ kirograph_data_describe(dataset: "tests-fixtures-users")
412
+ kirograph_data_query(dataset: "tests-fixtures-users", filters: [{column: "role", op: "eq", value: "admin"}])
413
+ kirograph_data_aggregate(dataset: "data-orders", groupBy: ["region"], metrics: [{column: "amount", op: "sum"}])
414
+ \`\`\`
415
+ `;
416
+ content = content.trimEnd() + "\n\n" + dataSection.trim() + "\n";
417
+ }
385
418
  return content;
386
419
  }
387
420
  function writeSteering(kiroDir, opts) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/bin/installer/steering.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Installer: Kiro steering file\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { CAVEMAN_RULES, CavemanMode } from './caveman';\n\nconst STEERING_CONTENT = `---\ninclusion: always\n---\n\n# KiroGraph\n\nKiroGraph builds a semantic knowledge graph of your codebase. Use its MCP tools instead of grep/glob/file reads whenever \\`.kirograph/\\` exists in the project.\n\n## Quick decision guide\n\n| Question | Tool |\n|----------|------|\n| Where do I start on this task? | \\`kirograph_context\\` |\n| What is this symbol / show me its code | \\`kirograph_node\\` with \\`includeCode: true\\` |\n| Find a symbol by name | \\`kirograph_search\\` |\n| Who calls function X? | \\`kirograph_callers\\` |\n| What does function X call? | \\`kirograph_callees\\` |\n| What breaks if I change X? | \\`kirograph_impact\\` |\n| How are X and Y connected? | \\`kirograph_path\\` |\n| What extends / implements this type? | \\`kirograph_type_hierarchy\\` |\n| Which code is never called? | \\`kirograph_dead_code\\` |\n| Are there import cycles? | \\`kirograph_circular_deps\\` |\n| What files are indexed? | \\`kirograph_files\\` |\n| Is the index healthy? | \\`kirograph_status\\` |\n| What are the most critical symbols? | \\`kirograph_hotspots\\` |\n| Any unexpected cross-module coupling? | \\`kirograph_surprising\\` |\n| What changed since the last snapshot? | \\`kirograph_diff\\` |\n| What packages/layers exist? | \\`kirograph_architecture\\` |\n| How coupled is package X? | \\`kirograph_coupling\\` |\n| What does package X depend on? | \\`kirograph_package\\` |\n| Run a command with token savings | \\`kirograph_exec\\` |\n| Check token savings stats | \\`kirograph_gain\\` |\n\n---\n\n## Tool reference\n\n### \\`kirograph_context\\`: **start here for any code task**\n\nReturns entry points, related symbols, and code snippets for a natural-language task description. Usually enough to orient without any additional tool calls.\n\n\\`\\`\\`\nkirograph_context(task: \"fix the auth token expiry bug\")\nkirograph_context(task: \"add dark mode\", maxNodes: 30)\nkirograph_context(task: \"refactor payment service\", includeCode: false)\n\\`\\`\\`\n\n### \\`kirograph_search\\`: find symbols by name\n\nExact match \u2192 FTS \u2192 LIKE fallback \u2192 vector (last resort). Use instead of grep.\n\n\\`\\`\\`\nkirograph_search(query: \"signIn\")\nkirograph_search(query: \"UserService\", kind: \"class\")\nkirograph_search(query: \"auth\", limit: 20)\n\\`\\`\\`\n\nSupported kinds: \\`function\\`, \\`method\\`, \\`class\\`, \\`interface\\`, \\`type_alias\\`, \\`variable\\`, \\`route\\`, \\`component\\`\n\n### \\`kirograph_node\\`: inspect a symbol\n\nReturns kind, file, signature, docstring. Add \\`includeCode: true\\` to get the full source.\n\n\\`\\`\\`\nkirograph_node(symbol: \"validateToken\")\nkirograph_node(symbol: \"AuthService\", includeCode: true)\n\\`\\`\\`\n\n### \\`kirograph_callers\\`: who calls this?\n\nBFS over incoming \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callers(symbol: \"processPayment\", limit: 30)\n\\`\\`\\`\n\n### \\`kirograph_callees\\`: what does this call?\n\nBFS over outgoing \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callees(symbol: \"handleRequest\")\n\\`\\`\\`\n\n### \\`kirograph_impact\\`: blast radius before a change\n\nTraverses all incoming edges up to \\`depth\\` hops. Call this before editing a symbol.\n\n\\`\\`\\`\nkirograph_impact(symbol: \"UserRepository\", depth: 3)\n\\`\\`\\`\n\n### \\`kirograph_path\\`: how are two symbols connected?\n\nBFS shortest path across all edge types.\n\n\\`\\`\\`\nkirograph_path(from: \"LoginController\", to: \"DatabasePool\")\n\\`\\`\\`\n\n### \\`kirograph_type_hierarchy\\`: class/interface inheritance\n\n\\`\\`\\`\nkirograph_type_hierarchy(symbol: \"BaseRepository\", direction: \"down\") // derived types\nkirograph_type_hierarchy(symbol: \"PaymentService\", direction: \"up\") // base types\nkirograph_type_hierarchy(symbol: \"IUserStore\", direction: \"both\") // all\n\\`\\`\\`\n\n### \\`kirograph_dead_code\\`: unreferenced symbols\n\nReturns unexported symbols with zero incoming edges. Good first step when cleaning up.\n\n\\`\\`\\`\nkirograph_dead_code(limit: 50)\n\\`\\`\\`\n\n### \\`kirograph_circular_deps\\`: import cycles\n\nRuns Tarjan's SCC over import edges. No parameters needed.\n\n\\`\\`\\`\nkirograph_circular_deps()\n\\`\\`\\`\n\n### \\`kirograph_files\\`: indexed file structure\n\n\\`\\`\\`\nkirograph_files(format: \"tree\") // default\nkirograph_files(format: \"flat\") // one path per line\nkirograph_files(format: \"grouped\") // by directory\nkirograph_files(filterPath: \"src/auth\", maxDepth: 2)\nkirograph_files(pattern: \"**/*.test.ts\")\n\\`\\`\\`\n\n### \\`kirograph_status\\`: index health\n\nReturns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.\n\n### \\`kirograph_hotspots\\`: most-connected symbols\n\nReturns the top-N symbols by total edge degree (in + out, excluding structural \\`contains\\` edges). Use to find core abstractions, identify high blast-radius symbols before a refactor, or understand what the codebase revolves around.\n\n\\`\\`\\`\nkirograph_hotspots(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_surprising\\`: unexpected cross-module coupling\n\nFinds direct edges between symbols in structurally distant files, scored by path distance \u00D7 edge-kind weight. Use before a refactor to discover hidden dependencies that will break. High score = more unexpected.\n\n\\`\\`\\`\nkirograph_surprising(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_diff\\`: what changed since a snapshot?\n\nCompares the current graph against a saved snapshot. Shows added/removed symbols and edges. A snapshot must exist: the user saves one with \\`kirograph snapshot save <label>\\` before making changes.\n\n\\`\\`\\`\nkirograph_diff() // vs latest snapshot\nkirograph_diff(snapshot: \"pre-refactor\") // vs named snapshot\n\\`\\`\\`\n\n---\n\n## Architecture tools *(require \\`enableArchitecture: true\\` in config)*\n\n### \\`kirograph_architecture\\`: **start here for architectural questions**\n\nReturns the full package graph, detected layers (api/service/data/ui/shared), and their dependency edges.\n\n\\`\\`\\`\nkirograph_architecture() // packages + layers\nkirograph_architecture(level: \"packages\")\nkirograph_architecture(level: \"layers\")\nkirograph_architecture(includeFiles: true) // add file\u2192package assignments\n\\`\\`\\`\n\n### \\`kirograph_coupling\\`: stability metrics per package\n\nReturns Ca (afferent: depended on by), Ce (efferent: depends on), and instability (Ce/(Ca+Ce)).\n- High Ca + low instability = load-bearing, safe to depend on, risky to change interface.\n- High Ce + high instability = depends on many things, safe to refactor internals.\n\n\\`\\`\\`\nkirograph_coupling() // all packages, sorted by instability\nkirograph_coupling(sortBy: \"afferent\") // most depended-on first\nkirograph_coupling(sortBy: \"efferent\") // most outgoing deps first\n\\`\\`\\`\n\n### \\`kirograph_package\\`: drill into one package\n\nReturns metadata, coupling metrics, outgoing deps, incoming dependents, and file list.\n\n\\`\\`\\`\nkirograph_package(package: \"auth\")\nkirograph_package(package: \"src/services\", includeFiles: false)\n\\`\\`\\`\n\n---\n\n## Workflows\n\n**Bug fix or feature:**\n1. \\`kirograph_context\\`: orient, find entry points.\n2. \\`kirograph_node\\` with \\`includeCode: true\\`: read the relevant symbol.\n3. \\`kirograph_callers\\` / \\`kirograph_callees\\`: trace the call flow.\n4. \\`kirograph_impact\\`: check blast radius before editing.\n\n**Refactor planning:**\n1. \\`kirograph_hotspots\\`: identify the most-connected symbols; changing these is risky.\n2. \\`kirograph_surprising\\`: surface hidden coupling that will break.\n3. \\`kirograph_impact\\` on specific targets: confirm blast radius.\n4. \\`kirograph_diff\\` after the refactor: verify the structural change matches intent.\n\n**Architectural review:**\n1. \\`kirograph_architecture\\`: get the package and layer map.\n2. \\`kirograph_coupling\\`: find the most stable (high Ca) and most volatile (high instability) packages.\n3. \\`kirograph_package\\`: drill into any package of interest.\n4. \\`kirograph_circular_deps\\`: check for import cycles.\n\n**Code cleanup:**\n1. \\`kirograph_dead_code\\`: find unreferenced unexported symbols.\n2. \\`kirograph_circular_deps\\`: find import cycles to untangle.\n3. \\`kirograph_surprising\\`: find unexpected coupling to decouple.\n\n---\n\n## If \\`.kirograph/\\` does NOT exist\n\nAsk the user: \"This project doesn't have KiroGraph initialized. Run \\`kirograph init -i\\` to build a code knowledge graph for faster exploration?\"\n`;\n\n// \u2500\u2500 Compression section builder (level-aware) \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\nconst LEVEL_DESCRIPTIONS: Record<string, string> = {\n normal: 'Balanced: removes noise, keeps structure.',\n aggressive: 'Compact: groups by category, limits output.',\n ultra: 'Maximum compression: counts and summaries only.',\n};\n\nconst LEVEL_EXAMPLES: Record<string, string> = {\n normal: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\")\nkirograph_exec(command: \"npm test\")\nkirograph_exec(command: \"cargo build\")\nkirograph_exec(command: \"ls -la src/\")\n\\\\\\`\\\\\\`\\\\\\``,\n aggressive: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"aggressive\")\nkirograph_exec(command: \"npm test\", level: \"aggressive\")\nkirograph_exec(command: \"eslint .\", level: \"aggressive\")\nkirograph_exec(command: \"find . -name '*.ts'\", level: \"aggressive\")\n\\\\\\`\\\\\\`\\\\\\``,\n ultra: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"ultra\")\nkirograph_exec(command: \"npm test\", level: \"ultra\")\nkirograph_exec(command: \"docker ps\", level: \"ultra\")\nkirograph_exec(command: \"ls -la src/\", level: \"ultra\")\n\\\\\\`\\\\\\`\\\\\\``,\n};\n\nfunction buildCompressionSection(level: 'normal' | 'aggressive' | 'ultra'): string {\n return `\n---\n\n## Shell Compression (\\\\\\`kirograph_exec\\\\\\`)\n\nWhen running shell commands, prefer \\\\\\`kirograph_exec\\\\\\` over raw shell execution for:\n- **git** operations (status, log, diff, push, pull, commit, add, fetch, branch)\n- **GitHub CLI** (gh pr list/view, gh issue list, gh run list)\n- **test runners** (jest, vitest, pytest, cargo test, go test, rspec, minitest, playwright)\n- **linters/build** (eslint, tsc, ruff, clippy, cargo build, prettier, biome, golangci-lint, rubocop, next build)\n- **file listings** (ls, find, tree)\n- **search** (grep, rg/ripgrep: grouped by file)\n- **diff** (diff file1 file2: condensed context)\n- **docker/k8s** (docker ps, images, logs, compose ps, kubectl pods, logs, services)\n- **package managers** (npm/pnpm install/list, pip list/install, bundle install, prisma generate)\n- **AWS CLI** (sts, ec2, lambda, logs, cloudformation, dynamodb, iam, s3, ecs, sqs, sns)\n- **network** (curl, wget: strip progress bars and headers)\n\nThis saves 60-90% of tokens compared to raw output.\n\nCompression level: **${level}**: ${LEVEL_DESCRIPTIONS[level]}\n\n${LEVEL_EXAMPLES[level]}\n\n**Important:** Error details are always preserved. Failed commands show full diagnostic output regardless of level.\n\n**Do NOT re-run commands:** When \\\\\\`kirograph_exec\\\\\\` returns a result, treat it as the final answer. Never re-run the same command with raw shell execution to \"get more details.\" The compressed output preserves all essential information. If you genuinely need something missing from the output, explain what's missing before making a second call.\n\nUse \\\\\\`kirograph_gain\\\\\\` to check token savings statistics.`;\n}\n\nexport interface SteeringOptions {\n cavemanMode?: CavemanMode | 'off';\n enableCompression?: boolean;\n shellCompressionLevel?: 'off' | 'normal' | 'aggressive' | 'ultra';\n enableMemory?: boolean;\n enableDocs?: boolean;\n}\n\nfunction buildSteeringContent(opts?: SteeringOptions): string {\n const cavemanMode = opts?.cavemanMode;\n const enableCompression = opts?.enableCompression !== false && opts?.shellCompressionLevel !== 'off';\n const shellCompressionLevel = opts?.shellCompressionLevel ?? 'normal';\n\n let content = STEERING_CONTENT;\n\n // Insert compression section before the \"If .kirograph/ does NOT exist\" section\n if (enableCompression && shellCompressionLevel !== 'off') {\n const section = buildCompressionSection(shellCompressionLevel as 'normal' | 'aggressive' | 'ultra');\n content = content.replace(\n '---\\n\\n## If `.kirograph/` does NOT exist',\n section.trim() + '\\n\\n---\\n\\n## If `.kirograph/` does NOT exist',\n );\n }\n\n // Remove compression tools from decision guide if disabled\n if (!enableCompression) {\n content = content.replace('| Run a command with token savings | `kirograph_exec` |\\n', '');\n content = content.replace('| Check token savings stats | `kirograph_gain` |\\n', '');\n }\n\n const caveman = cavemanMode && cavemanMode !== 'off' ? CAVEMAN_RULES[cavemanMode] : null;\n if (caveman) {\n content = content.trimEnd() + '\\n\\n' + caveman + '\\n';\n }\n\n // Memory section\n if (opts?.enableMemory) {\n const memorySection = `\n## Memory\n\nKiroGraph has persistent memory. Use \\`kirograph_mem_search\\` to recall past decisions,\nerrors, and patterns before making changes. Use \\`kirograph_mem_store\\` to save important\nobservations (architecture decisions, bug root causes, patterns discovered).\n\nMemory is searchable via hybrid FTS + vector search. Observations are automatically\nlinked to code symbols in the graph and surface in \\`kirograph_context\\` and\n\\`kirograph_impact\\` results when relevant.\n\n**When to store:** After fixing a bug, making an architecture decision, discovering a pattern,\nencountering a non-obvious error, or learning something about the codebase that future sessions\nshould know. Keep observations concise \u2014 one fact per store call. A hook will also remind you\nat session end.\n`;\n content = content.trimEnd() + '\\n\\n' + memorySection.trim() + '\\n';\n }\n\n // Documentation section\n if (opts?.enableDocs) {\n const docsSection = `\n## Documentation\n\nKiroGraph indexes project documentation by heading structure. Use \\`kirograph_docs_search\\`\nto find relevant doc sections instead of reading entire files. Use \\`kirograph_docs_section\\`\nto retrieve the exact section you need by ID.\n\n**Available tools:**\n- \\`kirograph_docs_toc\\` \u2014 table of contents for a file or the whole project\n- \\`kirograph_docs_search\\` \u2014 search sections by query (independent from code search)\n- \\`kirograph_docs_section\\` \u2014 retrieve full content of a section by ID\n- \\`kirograph_docs_outline\\` \u2014 heading hierarchy for a single document\n- \\`kirograph_docs_refs\\` \u2014 find code symbols referenced by a doc section (or vice versa)\n\n**When to use:** Before reading a documentation file directly, check if \\`kirograph_docs_search\\`\nor \\`kirograph_docs_outline\\` can give you the specific section you need. This saves tokens\nand gives you structured navigation instead of raw file content.\n`;\n content = content.trimEnd() + '\\n\\n' + docsSection.trim() + '\\n';\n }\n\n return content;\n}\n\nexport function writeSteering(kiroDir: string, opts?: SteeringOptions | CavemanMode | 'off'): void {\n const steeringDir = path.join(kiroDir, 'steering');\n fs.mkdirSync(steeringDir, { recursive: true });\n const steeringPath = path.join(steeringDir, 'kirograph.md');\n\n // Support both old signature (cavemanMode string) and new signature (options object)\n const resolvedOpts: SteeringOptions = typeof opts === 'string'\n ? { cavemanMode: opts }\n : opts ?? {};\n\n fs.writeFileSync(steeringPath, buildSteeringContent(resolvedOpts));\n console.log(` \u2713 Steering file written to ${steeringPath}`);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph Installer: Kiro steering file\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { CAVEMAN_RULES, CavemanMode } from './caveman';\n\nconst STEERING_CONTENT = `---\ninclusion: always\n---\n\n# KiroGraph\n\nKiroGraph builds a semantic knowledge graph of your codebase. Use its MCP tools instead of grep/glob/file reads whenever \\`.kirograph/\\` exists in the project.\n\n## Quick decision guide\n\n| Question | Tool |\n|----------|------|\n| Where do I start on this task? | \\`kirograph_context\\` |\n| What is this symbol / show me its code | \\`kirograph_node\\` with \\`includeCode: true\\` |\n| Find a symbol by name | \\`kirograph_search\\` |\n| Who calls function X? | \\`kirograph_callers\\` |\n| What does function X call? | \\`kirograph_callees\\` |\n| What breaks if I change X? | \\`kirograph_impact\\` |\n| How are X and Y connected? | \\`kirograph_path\\` |\n| What extends / implements this type? | \\`kirograph_type_hierarchy\\` |\n| Which code is never called? | \\`kirograph_dead_code\\` |\n| Are there import cycles? | \\`kirograph_circular_deps\\` |\n| What files are indexed? | \\`kirograph_files\\` |\n| Is the index healthy? | \\`kirograph_status\\` |\n| What are the most critical symbols? | \\`kirograph_hotspots\\` |\n| Any unexpected cross-module coupling? | \\`kirograph_surprising\\` |\n| What changed since the last snapshot? | \\`kirograph_diff\\` |\n| What packages/layers exist? | \\`kirograph_architecture\\` |\n| How coupled is package X? | \\`kirograph_coupling\\` |\n| What does package X depend on? | \\`kirograph_package\\` |\n| Run a command with token savings | \\`kirograph_exec\\` |\n| Check token savings stats | \\`kirograph_gain\\` |\n| What data files are indexed? | \\`kirograph_data_list\\` |\n| What columns does this dataset have? | \\`kirograph_data_describe\\` |\n| Query rows with filters | \\`kirograph_data_query\\` |\n| Aggregate data (sum, avg, count) | \\`kirograph_data_aggregate\\` |\n\n---\n\n## Tool reference\n\n### \\`kirograph_context\\`: **start here for any code task**\n\nReturns entry points, related symbols, and code snippets for a natural-language task description. Usually enough to orient without any additional tool calls.\n\n\\`\\`\\`\nkirograph_context(task: \"fix the auth token expiry bug\")\nkirograph_context(task: \"add dark mode\", maxNodes: 30)\nkirograph_context(task: \"refactor payment service\", includeCode: false)\n\\`\\`\\`\n\n### \\`kirograph_search\\`: find symbols by name\n\nExact match \u2192 FTS \u2192 LIKE fallback \u2192 vector (last resort). Use instead of grep.\n\n\\`\\`\\`\nkirograph_search(query: \"signIn\")\nkirograph_search(query: \"UserService\", kind: \"class\")\nkirograph_search(query: \"auth\", limit: 20)\n\\`\\`\\`\n\nSupported kinds: \\`function\\`, \\`method\\`, \\`class\\`, \\`interface\\`, \\`type_alias\\`, \\`variable\\`, \\`route\\`, \\`component\\`\n\n### \\`kirograph_node\\`: inspect a symbol\n\nReturns kind, file, signature, docstring. Add \\`includeCode: true\\` to get the full source.\n\n\\`\\`\\`\nkirograph_node(symbol: \"validateToken\")\nkirograph_node(symbol: \"AuthService\", includeCode: true)\n\\`\\`\\`\n\n### \\`kirograph_callers\\`: who calls this?\n\nBFS over incoming \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callers(symbol: \"processPayment\", limit: 30)\n\\`\\`\\`\n\n### \\`kirograph_callees\\`: what does this call?\n\nBFS over outgoing \\`calls\\` edges (depth 1).\n\n\\`\\`\\`\nkirograph_callees(symbol: \"handleRequest\")\n\\`\\`\\`\n\n### \\`kirograph_impact\\`: blast radius before a change\n\nTraverses all incoming edges up to \\`depth\\` hops. Call this before editing a symbol.\n\n\\`\\`\\`\nkirograph_impact(symbol: \"UserRepository\", depth: 3)\n\\`\\`\\`\n\n### \\`kirograph_path\\`: how are two symbols connected?\n\nBFS shortest path across all edge types.\n\n\\`\\`\\`\nkirograph_path(from: \"LoginController\", to: \"DatabasePool\")\n\\`\\`\\`\n\n### \\`kirograph_type_hierarchy\\`: class/interface inheritance\n\n\\`\\`\\`\nkirograph_type_hierarchy(symbol: \"BaseRepository\", direction: \"down\") // derived types\nkirograph_type_hierarchy(symbol: \"PaymentService\", direction: \"up\") // base types\nkirograph_type_hierarchy(symbol: \"IUserStore\", direction: \"both\") // all\n\\`\\`\\`\n\n### \\`kirograph_dead_code\\`: unreferenced symbols\n\nReturns unexported symbols with zero incoming edges. Good first step when cleaning up.\n\n\\`\\`\\`\nkirograph_dead_code(limit: 50)\n\\`\\`\\`\n\n### \\`kirograph_circular_deps\\`: import cycles\n\nRuns Tarjan's SCC over import edges. No parameters needed.\n\n\\`\\`\\`\nkirograph_circular_deps()\n\\`\\`\\`\n\n### \\`kirograph_files\\`: indexed file structure\n\n\\`\\`\\`\nkirograph_files(format: \"tree\") // default\nkirograph_files(format: \"flat\") // one path per line\nkirograph_files(format: \"grouped\") // by directory\nkirograph_files(filterPath: \"src/auth\", maxDepth: 2)\nkirograph_files(pattern: \"**/*.test.ts\")\n\\`\\`\\`\n\n### \\`kirograph_status\\`: index health\n\nReturns file count, symbol count, edge count, embedding coverage, DB size. Call when something feels off.\n\n### \\`kirograph_hotspots\\`: most-connected symbols\n\nReturns the top-N symbols by total edge degree (in + out, excluding structural \\`contains\\` edges). Use to find core abstractions, identify high blast-radius symbols before a refactor, or understand what the codebase revolves around.\n\n\\`\\`\\`\nkirograph_hotspots(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_surprising\\`: unexpected cross-module coupling\n\nFinds direct edges between symbols in structurally distant files, scored by path distance \u00D7 edge-kind weight. Use before a refactor to discover hidden dependencies that will break. High score = more unexpected.\n\n\\`\\`\\`\nkirograph_surprising(limit: 20)\n\\`\\`\\`\n\n### \\`kirograph_diff\\`: what changed since a snapshot?\n\nCompares the current graph against a saved snapshot. Shows added/removed symbols and edges. A snapshot must exist: the user saves one with \\`kirograph snapshot save <label>\\` before making changes.\n\n\\`\\`\\`\nkirograph_diff() // vs latest snapshot\nkirograph_diff(snapshot: \"pre-refactor\") // vs named snapshot\n\\`\\`\\`\n\n---\n\n## Architecture tools *(require \\`enableArchitecture: true\\` in config)*\n\n### \\`kirograph_architecture\\`: **start here for architectural questions**\n\nReturns the full package graph, detected layers (api/service/data/ui/shared), and their dependency edges.\n\n\\`\\`\\`\nkirograph_architecture() // packages + layers\nkirograph_architecture(level: \"packages\")\nkirograph_architecture(level: \"layers\")\nkirograph_architecture(includeFiles: true) // add file\u2192package assignments\n\\`\\`\\`\n\n### \\`kirograph_coupling\\`: stability metrics per package\n\nReturns Ca (afferent: depended on by), Ce (efferent: depends on), and instability (Ce/(Ca+Ce)).\n- High Ca + low instability = load-bearing, safe to depend on, risky to change interface.\n- High Ce + high instability = depends on many things, safe to refactor internals.\n\n\\`\\`\\`\nkirograph_coupling() // all packages, sorted by instability\nkirograph_coupling(sortBy: \"afferent\") // most depended-on first\nkirograph_coupling(sortBy: \"efferent\") // most outgoing deps first\n\\`\\`\\`\n\n### \\`kirograph_package\\`: drill into one package\n\nReturns metadata, coupling metrics, outgoing deps, incoming dependents, and file list.\n\n\\`\\`\\`\nkirograph_package(package: \"auth\")\nkirograph_package(package: \"src/services\", includeFiles: false)\n\\`\\`\\`\n\n---\n\n## Workflows\n\n**Bug fix or feature:**\n1. \\`kirograph_context\\`: orient, find entry points.\n2. \\`kirograph_node\\` with \\`includeCode: true\\`: read the relevant symbol.\n3. \\`kirograph_callers\\` / \\`kirograph_callees\\`: trace the call flow.\n4. \\`kirograph_impact\\`: check blast radius before editing.\n\n**Refactor planning:**\n1. \\`kirograph_hotspots\\`: identify the most-connected symbols; changing these is risky.\n2. \\`kirograph_surprising\\`: surface hidden coupling that will break.\n3. \\`kirograph_impact\\` on specific targets: confirm blast radius.\n4. \\`kirograph_diff\\` after the refactor: verify the structural change matches intent.\n\n**Architectural review:**\n1. \\`kirograph_architecture\\`: get the package and layer map.\n2. \\`kirograph_coupling\\`: find the most stable (high Ca) and most volatile (high instability) packages.\n3. \\`kirograph_package\\`: drill into any package of interest.\n4. \\`kirograph_circular_deps\\`: check for import cycles.\n\n**Code cleanup:**\n1. \\`kirograph_dead_code\\`: find unreferenced unexported symbols.\n2. \\`kirograph_circular_deps\\`: find import cycles to untangle.\n3. \\`kirograph_surprising\\`: find unexpected coupling to decouple.\n\n---\n\n## If \\`.kirograph/\\` does NOT exist\n\nAsk the user: \"This project doesn't have KiroGraph initialized. Run \\`kirograph init -i\\` to build a code knowledge graph for faster exploration?\"\n`;\n\n// \u2500\u2500 Compression section builder (level-aware) \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\nconst LEVEL_DESCRIPTIONS: Record<string, string> = {\n normal: 'Balanced: removes noise, keeps structure.',\n aggressive: 'Compact: groups by category, limits output.',\n ultra: 'Maximum compression: counts and summaries only.',\n};\n\nconst LEVEL_EXAMPLES: Record<string, string> = {\n normal: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\")\nkirograph_exec(command: \"npm test\")\nkirograph_exec(command: \"cargo build\")\nkirograph_exec(command: \"ls -la src/\")\n\\\\\\`\\\\\\`\\\\\\``,\n aggressive: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"aggressive\")\nkirograph_exec(command: \"npm test\", level: \"aggressive\")\nkirograph_exec(command: \"eslint .\", level: \"aggressive\")\nkirograph_exec(command: \"find . -name '*.ts'\", level: \"aggressive\")\n\\\\\\`\\\\\\`\\\\\\``,\n ultra: `\\\\\\`\\\\\\`\\\\\\`\nkirograph_exec(command: \"git status\", level: \"ultra\")\nkirograph_exec(command: \"npm test\", level: \"ultra\")\nkirograph_exec(command: \"docker ps\", level: \"ultra\")\nkirograph_exec(command: \"ls -la src/\", level: \"ultra\")\n\\\\\\`\\\\\\`\\\\\\``,\n};\n\nfunction buildCompressionSection(level: 'normal' | 'aggressive' | 'ultra'): string {\n return `\n---\n\n## Shell Compression (\\\\\\`kirograph_exec\\\\\\`)\n\nWhen running shell commands, prefer \\\\\\`kirograph_exec\\\\\\` over raw shell execution for:\n- **git** operations (status, log, diff, push, pull, commit, add, fetch, branch)\n- **GitHub CLI** (gh pr list/view, gh issue list, gh run list)\n- **test runners** (jest, vitest, pytest, cargo test, go test, rspec, minitest, playwright)\n- **linters/build** (eslint, tsc, ruff, clippy, cargo build, prettier, biome, golangci-lint, rubocop, next build)\n- **file listings** (ls, find, tree)\n- **search** (grep, rg/ripgrep: grouped by file)\n- **diff** (diff file1 file2: condensed context)\n- **docker/k8s** (docker ps, images, logs, compose ps, kubectl pods, logs, services)\n- **package managers** (npm/pnpm install/list, pip list/install, bundle install, prisma generate)\n- **AWS CLI** (sts, ec2, lambda, logs, cloudformation, dynamodb, iam, s3, ecs, sqs, sns)\n- **network** (curl, wget: strip progress bars and headers)\n\nThis saves 60-90% of tokens compared to raw output.\n\nCompression level: **${level}**: ${LEVEL_DESCRIPTIONS[level]}\n\n${LEVEL_EXAMPLES[level]}\n\n**Important:** Error details are always preserved. Failed commands show full diagnostic output regardless of level.\n\n**Do NOT re-run commands:** When \\\\\\`kirograph_exec\\\\\\` returns a result, treat it as the final answer. Never re-run the same command with raw shell execution to \"get more details.\" The compressed output preserves all essential information. If you genuinely need something missing from the output, explain what's missing before making a second call.\n\nUse \\\\\\`kirograph_gain\\\\\\` to check token savings statistics.`;\n}\n\nexport interface SteeringOptions {\n cavemanMode?: CavemanMode | 'off';\n enableCompression?: boolean;\n shellCompressionLevel?: 'off' | 'normal' | 'aggressive' | 'ultra';\n enableMemory?: boolean;\n enableDocs?: boolean;\n enableData?: boolean;\n}\n\nfunction buildSteeringContent(opts?: SteeringOptions): string {\n const cavemanMode = opts?.cavemanMode;\n const enableCompression = opts?.enableCompression !== false && opts?.shellCompressionLevel !== 'off';\n const shellCompressionLevel = opts?.shellCompressionLevel ?? 'normal';\n\n let content = STEERING_CONTENT;\n\n // Insert compression section before the \"If .kirograph/ does NOT exist\" section\n if (enableCompression && shellCompressionLevel !== 'off') {\n const section = buildCompressionSection(shellCompressionLevel as 'normal' | 'aggressive' | 'ultra');\n content = content.replace(\n '---\\n\\n## If `.kirograph/` does NOT exist',\n section.trim() + '\\n\\n---\\n\\n## If `.kirograph/` does NOT exist',\n );\n }\n\n // Remove compression tools from decision guide if disabled\n if (!enableCompression) {\n content = content.replace('| Run a command with token savings | `kirograph_exec` |\\n', '');\n content = content.replace('| Check token savings stats | `kirograph_gain` |\\n', '');\n }\n\n const caveman = cavemanMode && cavemanMode !== 'off' ? CAVEMAN_RULES[cavemanMode] : null;\n if (caveman) {\n content = content.trimEnd() + '\\n\\n' + caveman + '\\n';\n }\n\n // Memory section\n if (opts?.enableMemory) {\n const memorySection = `\n## Memory\n\nKiroGraph has persistent memory. Use \\`kirograph_mem_search\\` to recall past decisions,\nerrors, and patterns before making changes. Use \\`kirograph_mem_store\\` to save important\nobservations (architecture decisions, bug root causes, patterns discovered).\n\nMemory is searchable via hybrid FTS + vector search. Observations are automatically\nlinked to code symbols in the graph and surface in \\`kirograph_context\\` and\n\\`kirograph_impact\\` results when relevant.\n\n**When to store:** After fixing a bug, making an architecture decision, discovering a pattern,\nencountering a non-obvious error, or learning something about the codebase that future sessions\nshould know. Keep observations concise \u2014 one fact per store call. A hook will also remind you\nat session end.\n`;\n content = content.trimEnd() + '\\n\\n' + memorySection.trim() + '\\n';\n }\n\n // Documentation section\n if (opts?.enableDocs) {\n const docsSection = `\n## Documentation\n\nKiroGraph indexes project documentation by heading structure. Use \\`kirograph_docs_search\\`\nto find relevant doc sections instead of reading entire files. Use \\`kirograph_docs_section\\`\nto retrieve the exact section you need by ID.\n\n**Available tools:**\n- \\`kirograph_docs_toc\\` \u2014 table of contents for a file or the whole project\n- \\`kirograph_docs_search\\` \u2014 search sections by query (independent from code search)\n- \\`kirograph_docs_section\\` \u2014 retrieve full content of a section by ID\n- \\`kirograph_docs_outline\\` \u2014 heading hierarchy for a single document\n- \\`kirograph_docs_refs\\` \u2014 find code symbols referenced by a doc section (or vice versa)\n\n**When to use:** Before reading a documentation file directly, check if \\`kirograph_docs_search\\`\nor \\`kirograph_docs_outline\\` can give you the specific section you need. This saves tokens\nand gives you structured navigation instead of raw file content.\n`;\n content = content.trimEnd() + '\\n\\n' + docsSection.trim() + '\\n';\n }\n\n // Data section\n if (opts?.enableData) {\n const dataSection = `\n## Data\n\nKiroGraph indexes tabular data files (CSV, TSV, JSONL, JSON, Excel, Parquet) for structured\nquerying. Use \\`kirograph_data_describe\\` to understand a dataset's schema without loading\nthe file. Use \\`kirograph_data_query\\` with filters to retrieve specific rows.\n\n**Available tools:**\n- \\`kirograph_data_list\\` \u2014 list all indexed datasets with row/column counts\n- \\`kirograph_data_describe\\` \u2014 full schema profile: column names, types, cardinality, null%, samples\n- \\`kirograph_data_query\\` \u2014 filtered row retrieval with structured operators (eq, gt, contains, in, between)\n- \\`kirograph_data_aggregate\\` \u2014 server-side GROUP BY: count, sum, avg, min, max, count_distinct\n- \\`kirograph_data_search\\` \u2014 search column names and sample values by keyword\n\n**When to use:** Instead of reading a CSV/data file directly (which floods context with raw rows),\nuse \\`kirograph_data_describe\\` to understand the schema, then \\`kirograph_data_query\\` with\nfilters to get only the rows you need. For summary statistics, use \\`kirograph_data_aggregate\\`\nto compute results server-side. This saves 95-99% of tokens compared to reading raw data files.\n\n\\`\\`\\`\nkirograph_data_list()\nkirograph_data_describe(dataset: \"tests-fixtures-users\")\nkirograph_data_query(dataset: \"tests-fixtures-users\", filters: [{column: \"role\", op: \"eq\", value: \"admin\"}])\nkirograph_data_aggregate(dataset: \"data-orders\", groupBy: [\"region\"], metrics: [{column: \"amount\", op: \"sum\"}])\n\\`\\`\\`\n`;\n content = content.trimEnd() + '\\n\\n' + dataSection.trim() + '\\n';\n }\n\n return content;\n}\n\nexport function writeSteering(kiroDir: string, opts?: SteeringOptions | CavemanMode | 'off'): void {\n const steeringDir = path.join(kiroDir, 'steering');\n fs.mkdirSync(steeringDir, { recursive: true });\n const steeringPath = path.join(steeringDir, 'kirograph.md');\n\n // Support both old signature (cavemanMode string) and new signature (options object)\n const resolvedOpts: SteeringOptions = typeof opts === 'string'\n ? { cavemanMode: opts }\n : opts ?? {};\n\n fs.writeFileSync(steeringPath, buildSteeringContent(resolvedOpts));\n console.log(` \u2713 Steering file written to ${steeringPath}`);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/bin/installer/targets/index.ts"],
4
- "sourcesContent": ["import type { CavemanMode } from '../caveman';\nimport type { InstallTarget } from '../common';\nimport { installKiroEarly, installKiroLate, printKiroNextSteps } from './kiro';\nimport { installClaudeEarly, installClaudeLate, printClaudeNextSteps, uninitClaude } from './claude';\nimport { installCodexEarly, installCodexLate, printCodexNextSteps, uninitCodex } from './codex';\n\nexport interface TargetInstaller {\n label: string;\n installEarly(projectRoot: string): void;\n installLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean): void;\n printNextSteps(projectRoot: string): void;\n uninit?(projectRoot: string): void;\n}\n\nexport function getTargetInstaller(target: InstallTarget): TargetInstaller {\n if (target === 'claude') {\n return {\n label: 'Claude Code',\n installEarly: installClaudeEarly,\n installLate: installClaudeLate,\n printNextSteps: printClaudeNextSteps,\n uninit: uninitClaude,\n };\n }\n\n if (target === 'codex') {\n return {\n label: 'Codex',\n installEarly: installCodexEarly,\n installLate: installCodexLate,\n printNextSteps: printCodexNextSteps,\n uninit: uninitCodex,\n };\n }\n\n return {\n label: 'Kiro',\n installEarly: installKiroEarly,\n installLate: installKiroLate,\n printNextSteps: printKiroNextSteps,\n };\n}\n\n"],
4
+ "sourcesContent": ["import type { CavemanMode } from '../caveman';\nimport type { InstallTarget } from '../common';\nimport { installKiroEarly, installKiroLate, printKiroNextSteps } from './kiro';\nimport { installClaudeEarly, installClaudeLate, printClaudeNextSteps, uninitClaude } from './claude';\nimport { installCodexEarly, installCodexLate, printCodexNextSteps, uninitCodex } from './codex';\n\nexport interface TargetInstaller {\n label: string;\n installEarly(projectRoot: string): void;\n installLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean, enableData?: boolean): void;\n printNextSteps(projectRoot: string): void;\n uninit?(projectRoot: string): void;\n}\n\nexport function getTargetInstaller(target: InstallTarget): TargetInstaller {\n if (target === 'claude') {\n return {\n label: 'Claude Code',\n installEarly: installClaudeEarly,\n installLate: installClaudeLate,\n printNextSteps: printClaudeNextSteps,\n uninit: uninitClaude,\n };\n }\n\n if (target === 'codex') {\n return {\n label: 'Codex',\n installEarly: installCodexEarly,\n installLate: installCodexLate,\n printNextSteps: printCodexNextSteps,\n uninit: uninitCodex,\n };\n }\n\n return {\n label: 'Kiro',\n installEarly: installKiroEarly,\n installLate: installKiroLate,\n printNextSteps: printKiroNextSteps,\n };\n}\n\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAsE;AACtE,oBAA0F;AAC1F,mBAAsF;AAU/E,SAAS,mBAAmB,QAAwC;AACzE,MAAI,WAAW,UAAU;AACvB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,cAAc;AAAA,MACd,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,WAAW,SAAS;AACtB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,cAAc;AAAA,MACd,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,cAAc;AAAA,IACd,aAAa;AAAA,IACb,gBAAgB;AAAA,EAClB;AACF;",
6
6
  "names": []
7
7
  }
@@ -43,11 +43,11 @@ function installKiroEarly(projectRoot) {
43
43
  (0, import_mcp.writeMcpConfig)(kiroDir);
44
44
  (0, import_hooks.writeHooks)(kiroDir);
45
45
  }
46
- function installKiroLate(projectRoot, cavemanMode, shellCompressionLevel, enableMemory, enableDocs) {
46
+ function installKiroLate(projectRoot, cavemanMode, shellCompressionLevel, enableMemory, enableDocs, enableData) {
47
47
  const kiroDir = path.join(projectRoot, ".kiro");
48
48
  const enableCompression = shellCompressionLevel !== "off";
49
49
  (0, import_hooks.writeHooks)(kiroDir, { enableCompression, enableMemory });
50
- (0, import_steering.writeSteering)(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel, enableMemory, enableDocs });
50
+ (0, import_steering.writeSteering)(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel, enableMemory, enableDocs, enableData });
51
51
  (0, import_cli_agent.writeCliAgent)(kiroDir);
52
52
  }
53
53
  function printKiroNextSteps() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/bin/installer/targets/kiro.ts"],
4
- "sourcesContent": ["import * as path from 'path';\nimport { CavemanMode } from '../caveman';\nimport { writeCliAgent } from '../cli-agent';\nimport { writeHooks } from '../hooks';\nimport { writeMcpConfig } from '../mcp';\nimport { writeSteering } from '../steering';\n\nexport function installKiroEarly(projectRoot: string): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n writeMcpConfig(kiroDir);\n writeHooks(kiroDir);\n}\n\nexport function installKiroLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n const enableCompression = shellCompressionLevel !== 'off';\n // Re-write hooks with compression and memory awareness\n writeHooks(kiroDir, { enableCompression, enableMemory });\n writeSteering(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel: shellCompressionLevel as any, enableMemory, enableDocs });\n writeCliAgent(kiroDir);\n}\n\nexport function printKiroNextSteps(): void {\n console.log('\\n Done! Restart Kiro IDE for the MCP server to load.');\n console.log(' For Kiro CLI, use the \"kirograph\" agent: kiro-cli --agent kirograph\\n');\n}\n\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAsB;AAEtB,uBAA8B;AAC9B,mBAA2B;AAC3B,iBAA+B;AAC/B,sBAA8B;AAEvB,SAAS,iBAAiB,aAA2B;AAC1D,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,iCAAe,OAAO;AACtB,+BAAW,OAAO;AACpB;AAEO,SAAS,gBAAgB,aAAqB,aAAmC,uBAAgC,cAAwB,YAA4B;AAC1K,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,QAAM,oBAAoB,0BAA0B;AAEpD,+BAAW,SAAS,EAAE,mBAAmB,aAAa,CAAC;AACvD,qCAAc,SAAS,EAAE,aAAa,mBAAmB,uBAAqD,cAAc,WAAW,CAAC;AACxI,sCAAc,OAAO;AACvB;AAEO,SAAS,qBAA2B;AACzC,UAAQ,IAAI,wDAAwD;AACpE,UAAQ,IAAI,yEAAyE;AACvF;",
4
+ "sourcesContent": ["import * as path from 'path';\nimport { CavemanMode } from '../caveman';\nimport { writeCliAgent } from '../cli-agent';\nimport { writeHooks } from '../hooks';\nimport { writeMcpConfig } from '../mcp';\nimport { writeSteering } from '../steering';\n\nexport function installKiroEarly(projectRoot: string): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n writeMcpConfig(kiroDir);\n writeHooks(kiroDir);\n}\n\nexport function installKiroLate(projectRoot: string, cavemanMode?: CavemanMode | 'off', shellCompressionLevel?: string, enableMemory?: boolean, enableDocs?: boolean, enableData?: boolean): void {\n const kiroDir = path.join(projectRoot, '.kiro');\n const enableCompression = shellCompressionLevel !== 'off';\n // Re-write hooks with compression and memory awareness\n writeHooks(kiroDir, { enableCompression, enableMemory });\n writeSteering(kiroDir, { cavemanMode, enableCompression, shellCompressionLevel: shellCompressionLevel as any, enableMemory, enableDocs, enableData });\n writeCliAgent(kiroDir);\n}\n\nexport function printKiroNextSteps(): void {\n console.log('\\n Done! Restart Kiro IDE for the MCP server to load.');\n console.log(' For Kiro CLI, use the \"kirograph\" agent: kiro-cli --agent kirograph\\n');\n}\n\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAsB;AAEtB,uBAA8B;AAC9B,mBAA2B;AAC3B,iBAA+B;AAC/B,sBAA8B;AAEvB,SAAS,iBAAiB,aAA2B;AAC1D,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,iCAAe,OAAO;AACtB,+BAAW,OAAO;AACpB;AAEO,SAAS,gBAAgB,aAAqB,aAAmC,uBAAgC,cAAwB,YAAsB,YAA4B;AAChM,QAAM,UAAU,KAAK,KAAK,aAAa,OAAO;AAC9C,QAAM,oBAAoB,0BAA0B;AAEpD,+BAAW,SAAS,EAAE,mBAAmB,aAAa,CAAC;AACvD,qCAAc,SAAS,EAAE,aAAa,mBAAmB,uBAAqD,cAAc,YAAY,WAAW,CAAC;AACpJ,sCAAc,OAAO;AACvB;AAEO,SAAS,qBAA2B;AACzC,UAAQ,IAAI,wDAAwD;AACpE,UAAQ,IAAI,yEAAyE;AACvF;",
6
6
  "names": []
7
7
  }
@@ -33,6 +33,7 @@ var import_compression = require("./commands/compression");
33
33
  var import_exec = require("./commands/exec");
34
34
  var import_memory = require("./commands/memory");
35
35
  var import_docs = require("./commands/docs");
36
+ var import_data = require("./commands/data");
36
37
  process.on("uncaughtException", (err) => {
37
38
  const msg = err?.message ?? String(err);
38
39
  const isWasmAbort = msg.includes("Aborted(") || msg.includes("RuntimeError") || err?.constructor?.name === "RuntimeError";
@@ -61,7 +62,7 @@ process.on("uncaughtException", (err) => {
61
62
  process.exit(1);
62
63
  });
63
64
  const program = new import_commander.Command();
64
- program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.16.0").addHelpCommand(true).hook("preAction", (thisCommand) => {
65
+ program.name("kirograph").description("Semantic code knowledge graph for Kiro").version("0.17.0").addHelpCommand(true).hook("preAction", (thisCommand) => {
65
66
  const name = thisCommand.name();
66
67
  if (name === "init") (0, import_banner.printBanner)();
67
68
  });
@@ -95,6 +96,7 @@ program.name("kirograph").description("Semantic code knowledge graph for Kiro").
95
96
  (0, import_exec.register)(program);
96
97
  (0, import_memory.register)(program);
97
98
  (0, import_docs.register)(program);
99
+ (0, import_data.register)(program);
98
100
  if (process.argv.length === 2) {
99
101
  (0, import_banner.printBanner)();
100
102
  (0, import_help.printColoredHelp)();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/bin/kirograph.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n/**\n * KiroGraph CLI\n */\n\nimport { Command } from 'commander';\nimport { printBanner } from './banner';\nimport { printColoredHelp, register as registerHelp } from './commands/help';\nimport { register as registerInit } from './commands/init';\nimport { register as registerUninit } from './commands/uninit';\nimport { register as registerIndex } from './commands/index';\nimport { register as registerSync } from './commands/sync';\nimport { register as registerStatus } from './commands/status';\nimport { register as registerQuery } from './commands/query';\nimport { register as registerFiles } from './commands/files';\nimport { register as registerContext } from './commands/context';\nimport { register as registerAffected } from './commands/affected';\nimport { register as registerMarkDirty } from './commands/mark-dirty';\nimport { register as registerSyncIfDirty } from './commands/sync-if-dirty';\nimport { register as registerUnlock } from './commands/unlock';\nimport { register as registerInstall } from './commands/install';\nimport { register as registerServe } from './commands/serve';\nimport { register as registerDashboard } from './commands/dashboard';\nimport { register as registerArchitecture } from './commands/architecture';\nimport { register as registerCoupling } from './commands/coupling';\nimport { register as registerPackage } from './commands/package';\nimport { register as registerCaveman } from './commands/caveman';\nimport { register as registerDeadCode } from './commands/dead-code';\nimport { register as registerHotspots } from './commands/hotspots';\nimport { register as registerSurprising } from './commands/surprising';\nimport { register as registerSnapshot } from './commands/snapshot';\nimport { register as registerPath } from './commands/path';\nimport { register as registerExport } from './commands/export';\nimport { register as registerGain } from './commands/gain';\nimport { register as registerCompression } from './commands/compression';\nimport { register as registerExec } from './commands/exec';\nimport { register as registerMemory } from './commands/memory';\nimport { register as registerDocs } from './commands/docs';\n\n// \u2500\u2500 Global error handler for WASM runtime crashes \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// node-sqlite3-wasm calls process.abort() when it hits a fatal error (e.g.\n// database is locked by another process). This produces a raw \"Aborted()\"\n// message with no context. We intercept it here to print a clear explanation\n// before the process exits.\nprocess.on('uncaughtException', (err: Error) => {\n const msg = err?.message ?? String(err);\n const isWasmAbort = msg.includes('Aborted(') || msg.includes('RuntimeError') || (err as any)?.constructor?.name === 'RuntimeError';\n\n if (isWasmAbort) {\n process.stderr.write([\n '',\n ' \u2716 KiroGraph crashed: SQLite WASM runtime aborted.',\n '',\n ' Most likely cause: another process (e.g. the Kiro MCP server) is',\n ' holding the database open while indexing is running.',\n '',\n ' How to fix:',\n ' 1. Close Kiro IDE (or disable the kirograph MCP server) before indexing',\n ' 2. Run: kirograph unlock',\n ' 3. Then retry: kirograph index',\n '',\n ' If the problem persists, delete the lock manually:',\n ' del .kirograph\\\\kirograph.db.lock (Windows)',\n ' rm -rf .kirograph/kirograph.db.lock (macOS/Linux)',\n '',\n ].join('\\n'));\n process.exit(1);\n }\n\n // Not a WASM crash \u2014 re-throw as normal\n process.stderr.write(`Uncaught error: ${msg}\\n`);\n process.exit(1);\n});\n\ndeclare const __CLI_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('kirograph')\n .description('Semantic code knowledge graph for Kiro')\n .version(__CLI_VERSION__)\n .addHelpCommand(true)\n .hook('preAction', (thisCommand) => {\n const name = thisCommand.name();\n if (name === 'init') printBanner();\n });\n\nregisterInstall(program);\nregisterInit(program);\nregisterUninit(program);\nregisterIndex(program);\nregisterSync(program);\nregisterSyncIfDirty(program);\nregisterMarkDirty(program);\nregisterStatus(program);\nregisterQuery(program);\nregisterContext(program);\nregisterFiles(program);\nregisterAffected(program);\nregisterUnlock(program);\nregisterServe(program);\nregisterDashboard(program);\nregisterArchitecture(program);\nregisterCoupling(program);\nregisterPackage(program);\nregisterCaveman(program);\nregisterDeadCode(program);\nregisterHotspots(program);\nregisterSurprising(program);\nregisterSnapshot(program);\nregisterPath(program);\nregisterExport(program);\nregisterGain(program);\nregisterCompression(program);\nregisterExec(program);\nregisterMemory(program);\nregisterDocs(program);\n\n// Show banner + help when called with no arguments, otherwise parse normally\nif (process.argv.length === 2) {\n printBanner();\n printColoredHelp();\n process.exit(0);\n}\n\nregisterHelp(program);\n\nprogram.parse(process.argv);\n"],
5
- "mappings": "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",
6
- "names": ["registerInstall", "registerInit", "registerUninit", "registerIndex", "registerSync", "registerSyncIfDirty", "registerMarkDirty", "registerStatus", "registerQuery", "registerContext", "registerFiles", "registerAffected", "registerUnlock", "registerServe", "registerDashboard", "registerArchitecture", "registerCoupling", "registerPackage", "registerCaveman", "registerDeadCode", "registerHotspots", "registerSurprising", "registerSnapshot", "registerPath", "registerExport", "registerGain", "registerCompression", "registerExec", "registerMemory", "registerDocs", "registerHelp"]
4
+ "sourcesContent": ["#!/usr/bin/env node\n/**\n * KiroGraph CLI\n */\n\nimport { Command } from 'commander';\nimport { printBanner } from './banner';\nimport { printColoredHelp, register as registerHelp } from './commands/help';\nimport { register as registerInit } from './commands/init';\nimport { register as registerUninit } from './commands/uninit';\nimport { register as registerIndex } from './commands/index';\nimport { register as registerSync } from './commands/sync';\nimport { register as registerStatus } from './commands/status';\nimport { register as registerQuery } from './commands/query';\nimport { register as registerFiles } from './commands/files';\nimport { register as registerContext } from './commands/context';\nimport { register as registerAffected } from './commands/affected';\nimport { register as registerMarkDirty } from './commands/mark-dirty';\nimport { register as registerSyncIfDirty } from './commands/sync-if-dirty';\nimport { register as registerUnlock } from './commands/unlock';\nimport { register as registerInstall } from './commands/install';\nimport { register as registerServe } from './commands/serve';\nimport { register as registerDashboard } from './commands/dashboard';\nimport { register as registerArchitecture } from './commands/architecture';\nimport { register as registerCoupling } from './commands/coupling';\nimport { register as registerPackage } from './commands/package';\nimport { register as registerCaveman } from './commands/caveman';\nimport { register as registerDeadCode } from './commands/dead-code';\nimport { register as registerHotspots } from './commands/hotspots';\nimport { register as registerSurprising } from './commands/surprising';\nimport { register as registerSnapshot } from './commands/snapshot';\nimport { register as registerPath } from './commands/path';\nimport { register as registerExport } from './commands/export';\nimport { register as registerGain } from './commands/gain';\nimport { register as registerCompression } from './commands/compression';\nimport { register as registerExec } from './commands/exec';\nimport { register as registerMemory } from './commands/memory';\nimport { register as registerDocs } from './commands/docs';\nimport { register as registerData } from './commands/data';\n\n// \u2500\u2500 Global error handler for WASM runtime crashes \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// node-sqlite3-wasm calls process.abort() when it hits a fatal error (e.g.\n// database is locked by another process). This produces a raw \"Aborted()\"\n// message with no context. We intercept it here to print a clear explanation\n// before the process exits.\nprocess.on('uncaughtException', (err: Error) => {\n const msg = err?.message ?? String(err);\n const isWasmAbort = msg.includes('Aborted(') || msg.includes('RuntimeError') || (err as any)?.constructor?.name === 'RuntimeError';\n\n if (isWasmAbort) {\n process.stderr.write([\n '',\n ' \u2716 KiroGraph crashed: SQLite WASM runtime aborted.',\n '',\n ' Most likely cause: another process (e.g. the Kiro MCP server) is',\n ' holding the database open while indexing is running.',\n '',\n ' How to fix:',\n ' 1. Close Kiro IDE (or disable the kirograph MCP server) before indexing',\n ' 2. Run: kirograph unlock',\n ' 3. Then retry: kirograph index',\n '',\n ' If the problem persists, delete the lock manually:',\n ' del .kirograph\\\\kirograph.db.lock (Windows)',\n ' rm -rf .kirograph/kirograph.db.lock (macOS/Linux)',\n '',\n ].join('\\n'));\n process.exit(1);\n }\n\n // Not a WASM crash \u2014 re-throw as normal\n process.stderr.write(`Uncaught error: ${msg}\\n`);\n process.exit(1);\n});\n\ndeclare const __CLI_VERSION__: string;\n\nconst program = new Command();\n\nprogram\n .name('kirograph')\n .description('Semantic code knowledge graph for Kiro')\n .version(__CLI_VERSION__)\n .addHelpCommand(true)\n .hook('preAction', (thisCommand) => {\n const name = thisCommand.name();\n if (name === 'init') printBanner();\n });\n\nregisterInstall(program);\nregisterInit(program);\nregisterUninit(program);\nregisterIndex(program);\nregisterSync(program);\nregisterSyncIfDirty(program);\nregisterMarkDirty(program);\nregisterStatus(program);\nregisterQuery(program);\nregisterContext(program);\nregisterFiles(program);\nregisterAffected(program);\nregisterUnlock(program);\nregisterServe(program);\nregisterDashboard(program);\nregisterArchitecture(program);\nregisterCoupling(program);\nregisterPackage(program);\nregisterCaveman(program);\nregisterDeadCode(program);\nregisterHotspots(program);\nregisterSurprising(program);\nregisterSnapshot(program);\nregisterPath(program);\nregisterExport(program);\nregisterGain(program);\nregisterCompression(program);\nregisterExec(program);\nregisterMemory(program);\nregisterDocs(program);\nregisterData(program);\n\n// Show banner + help when called with no arguments, otherwise parse normally\nif (process.argv.length === 2) {\n printBanner();\n printColoredHelp();\n process.exit(0);\n}\n\nregisterHelp(program);\n\nprogram.parse(process.argv);\n"],
5
+ "mappings": "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",
6
+ "names": ["registerInstall", "registerInit", "registerUninit", "registerIndex", "registerSync", "registerSyncIfDirty", "registerMarkDirty", "registerStatus", "registerQuery", "registerContext", "registerFiles", "registerAffected", "registerUnlock", "registerServe", "registerDashboard", "registerArchitecture", "registerCoupling", "registerPackage", "registerCaveman", "registerDeadCode", "registerHotspots", "registerSurprising", "registerSnapshot", "registerPath", "registerExport", "registerGain", "registerCompression", "registerExec", "registerMemory", "registerDocs", "registerData", "registerHelp"]
7
7
  }
@@ -78,6 +78,16 @@ function renderIndexProgress(p) {
78
78
  process.stdout.write(`\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${" ".repeat(10)}`);
79
79
  if (p.current === p.total && p.total > 0) process.stdout.write("\n");
80
80
  }
81
+ } else if (p.phase === "docs") {
82
+ if (p.meta?.msg) {
83
+ process.stdout.write(`\r ${_v}docs${_r} ${_d}${p.meta.msg}${_r}${" ".repeat(20)}`);
84
+ if (String(p.meta.msg).startsWith("docs:")) process.stdout.write("\n");
85
+ }
86
+ } else if (p.phase === "data") {
87
+ if (p.meta?.msg) {
88
+ process.stdout.write(`\r ${_v}data${_r} ${_d}${p.meta.msg}${_r}${" ".repeat(20)}`);
89
+ if (String(p.meta.msg).startsWith("data:")) process.stdout.write("\n");
90
+ }
81
91
  } else {
82
92
  process.stdout.write(`\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${" ".repeat(20)}`);
83
93
  }
@@ -118,6 +128,16 @@ function renderSyncProgress(p) {
118
128
  process.stdout.write(`\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${" ".repeat(10)}`);
119
129
  if (p.current === p.total && p.total > 0) process.stdout.write("\n");
120
130
  }
131
+ } else if (p.phase === "docs") {
132
+ if (p.meta?.msg) {
133
+ process.stdout.write(`\r ${_v}docs${_r} ${_d}${p.meta.msg}${_r}${" ".repeat(20)}`);
134
+ if (String(p.meta.msg).startsWith("docs:")) process.stdout.write("\n");
135
+ }
136
+ } else if (p.phase === "data") {
137
+ if (p.meta?.msg) {
138
+ process.stdout.write(`\r ${_v}data${_r} ${_d}${p.meta.msg}${_r}${" ".repeat(20)}`);
139
+ if (String(p.meta.msg).startsWith("data:")) process.stdout.write("\n");
140
+ }
121
141
  } else {
122
142
  process.stdout.write(`\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${" ".repeat(20)}`);
123
143
  }
@@ -169,6 +189,16 @@ function renderSyncProgressVerbose(p) {
169
189
  `);
170
190
  } else if (p.current === p.total && p.total > 0) {
171
191
  process.stdout.write(` ${_v}\u2713 architecture${_r}
192
+ `);
193
+ }
194
+ } else if (p.phase === "docs") {
195
+ if (p.meta?.msg) {
196
+ process.stdout.write(` ${_v}docs${_r} ${_d}${p.meta.msg}${_r}
197
+ `);
198
+ }
199
+ } else if (p.phase === "data") {
200
+ if (p.meta?.msg) {
201
+ process.stdout.write(` ${_v}data${_r} ${_d}${p.meta.msg}${_r}
172
202
  `);
173
203
  }
174
204
  } else {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/bin/progress.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph CLI Progress Renderer\n *\n * Renders indexAll/sync progress events to stdout.\n * Lives in src/bin/ because it is a display concern \u2014 not part of the core library.\n */\n\nimport type { IndexProgress, SyncResult } from '../types';\n\n// \u2500\u2500 ANSI 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\n\nconst _v = '\\x1b[38;5;99m'; // violet\nconst _r = '\\x1b[0m'; // reset\nconst _d = '\\x1b[2m'; // dim\nconst _g = '\\x1b[38;5;114m'; // green\n\nfunction _bar(pct: number, width = 20): string {\n const filled = Math.floor(pct / (100 / width));\n return '\u2588'.repeat(filled) + '\u2591'.repeat(width - filled);\n}\n\nfunction _num(n: number): string {\n return n.toLocaleString();\n}\n\n// \u2500\u2500 Renderer \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/**\n * Renders a single indexAll progress event to stdout.\n * Scanning and framework detection print a persistent line (with \\n).\n * Parsing, resolving, and embeddings overwrite the current line (\\r).\n */\nexport function renderIndexProgress(p: IndexProgress): void {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n\n if (p.phase === 'scanning') {\n process.stdout.write(` ${_v}\u2713 scanning${_r} ${_v}${p.current}${_r} ${_d}files found${_r}\\n`);\n\n } else if (p.phase === 'parsing') {\n process.stdout.write(`\\r ${_v}parsing${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(8)}`);\n if (p.current === p.total) process.stdout.write('\\n');\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(`\\r ${_v}resolving${_r} cross-file references\u2026${' '.repeat(20)}`);\n } else if (p.total > 0) {\n const bar = _bar(pct);\n const suffix = p.current === p.total\n ? `${_v}${p.current}${_r}${_d}/${p.total} refs${_r}\\n`\n : `${_v}${p.current}${_r}${_d}/${p.total}${_r}${' '.repeat(10)}`;\n const prefix = p.current === p.total ? `\\r ${_v}\u2713 resolving${_r}` : `\\r ${_v}resolving${_r} `;\n process.stdout.write(`${prefix} [${bar}] ${suffix}`);\n }\n\n } else if (p.phase === 'detecting frameworks') {\n if (p.current === 1) {\n const frameworks = (p.meta?.frameworks as string[]) ?? [];\n const languages = (p.meta?.languages as string[]) ?? [];\n const fwLabel = frameworks.length > 0 ? `${_v}${frameworks.join(', ')}${_r}` : `${_d}none${_r}`;\n const langLabel = languages.length > 0 ? `${_v}${languages.join(', ')}${_r}` : `${_d}none${_r}`;\n process.stdout.write(` ${_v}\u2713 languages${_r} detected: ${langLabel}\\n`);\n process.stdout.write(` ${_v}\u2713 frameworks${_r} detected: ${fwLabel}\\n`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n // Large-codebase pre-flight warning emitted by VectorManager\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else {\n process.stdout.write(`\\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${' '.repeat(20)}`);\n }\n}\n\n\n// \u2500\u2500 Sync Progress Renderer \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/**\n * Renders a single sync progress event to stdout.\n * Same visual style as renderIndexProgress but tailored for incremental sync.\n */\nexport function renderSyncProgress(p: IndexProgress): void {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n\n if (p.phase === 'scanning') {\n if (p.current > 0) {\n process.stdout.write(`\\r ${_v}\u2713 scanning${_r} ${_v}${_num(p.current)}${_r} ${_d}files found${_r}\\n`);\n } else {\n process.stdout.write(`\\r ${_v}scanning${_r} ${_d}detecting changes\u2026${_r}${' '.repeat(20)}`);\n }\n\n } else if (p.phase === 'parsing') {\n process.stdout.write(`\\r ${_v}parsing${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(8)}`);\n if (p.current === p.total) process.stdout.write('\\n');\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(`\\r ${_v}resolving${_r} cross-file references\u2026${' '.repeat(20)}`);\n } else if (p.total > 0) {\n const bar = _bar(pct);\n const suffix = p.current === p.total\n ? `${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)} refs${_r}\\n`\n : `${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)}${_r}${' '.repeat(10)}`;\n const prefix = p.current === p.total ? `\\r ${_v}\u2713 resolving${_r}` : `\\r ${_v}resolving${_r} `;\n process.stdout.write(`${prefix} [${bar}] ${suffix}`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else {\n process.stdout.write(`\\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${' '.repeat(20)}`);\n }\n}\n\n/**\n * Verbose sync progress renderer for `sync --progress`.\n * Prints each file as it is processed, errors inline, and a running count.\n * Exclude-cleanup removals are shown with a distinct prefix.\n */\nexport function renderSyncProgressVerbose(p: IndexProgress): void {\n if (p.phase === 'scanning') {\n if (p.meta?.excludeCleanup && p.meta.file) {\n // A file is being removed because it now matches an exclude pattern\n process.stdout.write(` ${_d}exclude${_r} ${_d}${p.meta.file}${_r}\\n`);\n } else if (p.current > 0) {\n process.stdout.write(` ${_v}\u2713 scanning${_r} ${_v}${_num(p.current)}${_r} ${_d}files found${_r}\\n`);\n } else {\n process.stdout.write(` ${_v}scanning${_r} ${_d}detecting changes\u2026${_r}\\n`);\n }\n\n } else if (p.phase === 'parsing') {\n if (p.currentFile) {\n const short = p.currentFile.length > 60\n ? '\u2026' + p.currentFile.slice(p.currentFile.length - 59)\n : p.currentFile;\n process.stdout.write(` ${_v}parse${_r} ${_d}[${_num(p.current)}/${_num(p.total)}]${_r} ${short}\\n`);\n }\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(` ${_v}resolving${_r} cross-file references\u2026\\n`);\n } else if (p.total > 0 && p.current === p.total) {\n process.stdout.write(` ${_v}\u2713 resolving${_r} ${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)} refs${_r}\\n`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'architecture') {\n if (p.meta?.msg) {\n process.stdout.write(` ${_v}architecture${_r} ${_d}${p.meta.msg}${_r}\\n`);\n } else if (p.current === p.total && p.total > 0) {\n process.stdout.write(` ${_v}\u2713 architecture${_r}\\n`);\n }\n\n } else {\n process.stdout.write(` ${_v}${p.phase}${_r} ${p.current}/${p.total}\\n`);\n }\n}\n\n/**\n * Renders the final sync summary with before/after counts.\n */\nexport function renderSyncSummary(result: SyncResult): void {\n const secs = (result.duration / 1000).toFixed(1);\n const filesChanged = result.added.length + result.modified.length;\n const filesDeleted = result.removed.length;\n\n console.log(`\\n ${_g}\u2713${_r} sync complete ${_d}(${secs}s)${_r}`);\n console.log(` ${_d}files scanned:${_r} ${_v}${_num(result.filesScanned)}${_r}`);\n console.log(` ${_d}files changed:${_r} ${_v}${_num(filesChanged)}${_r}`);\n console.log(` ${_d}files deleted:${_r} ${_v}${_num(filesDeleted)}${_r}`);\n console.log(` ${_d}nodes added:${_r} ${_v}${_num(result.nodesCreated)}${_r}`);\n console.log(` ${_d}nodes updated:${_r} ${_v}${_num(result.nodesUpdated)}${_r}`);\n console.log(` ${_d}nodes removed:${_r} ${_v}${_num(result.nodesRemoved)}${_r}`);\n console.log(` ${_d}edges added:${_r} ${_v}${_num(result.edgesCreated)}${_r}`);\n console.log(` ${_d}edges removed:${_r} ${_v}${_num(result.edgesRemoved)}${_r}`);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph CLI Progress Renderer\n *\n * Renders indexAll/sync progress events to stdout.\n * Lives in src/bin/ because it is a display concern \u2014 not part of the core library.\n */\n\nimport type { IndexProgress, SyncResult } from '../types';\n\n// \u2500\u2500 ANSI 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\n\nconst _v = '\\x1b[38;5;99m'; // violet\nconst _r = '\\x1b[0m'; // reset\nconst _d = '\\x1b[2m'; // dim\nconst _g = '\\x1b[38;5;114m'; // green\n\nfunction _bar(pct: number, width = 20): string {\n const filled = Math.floor(pct / (100 / width));\n return '\u2588'.repeat(filled) + '\u2591'.repeat(width - filled);\n}\n\nfunction _num(n: number): string {\n return n.toLocaleString();\n}\n\n// \u2500\u2500 Renderer \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/**\n * Renders a single indexAll progress event to stdout.\n * Scanning and framework detection print a persistent line (with \\n).\n * Parsing, resolving, and embeddings overwrite the current line (\\r).\n */\nexport function renderIndexProgress(p: IndexProgress): void {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n\n if (p.phase === 'scanning') {\n process.stdout.write(` ${_v}\u2713 scanning${_r} ${_v}${p.current}${_r} ${_d}files found${_r}\\n`);\n\n } else if (p.phase === 'parsing') {\n process.stdout.write(`\\r ${_v}parsing${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(8)}`);\n if (p.current === p.total) process.stdout.write('\\n');\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(`\\r ${_v}resolving${_r} cross-file references\u2026${' '.repeat(20)}`);\n } else if (p.total > 0) {\n const bar = _bar(pct);\n const suffix = p.current === p.total\n ? `${_v}${p.current}${_r}${_d}/${p.total} refs${_r}\\n`\n : `${_v}${p.current}${_r}${_d}/${p.total}${_r}${' '.repeat(10)}`;\n const prefix = p.current === p.total ? `\\r ${_v}\u2713 resolving${_r}` : `\\r ${_v}resolving${_r} `;\n process.stdout.write(`${prefix} [${bar}] ${suffix}`);\n }\n\n } else if (p.phase === 'detecting frameworks') {\n if (p.current === 1) {\n const frameworks = (p.meta?.frameworks as string[]) ?? [];\n const languages = (p.meta?.languages as string[]) ?? [];\n const fwLabel = frameworks.length > 0 ? `${_v}${frameworks.join(', ')}${_r}` : `${_d}none${_r}`;\n const langLabel = languages.length > 0 ? `${_v}${languages.join(', ')}${_r}` : `${_d}none${_r}`;\n process.stdout.write(` ${_v}\u2713 languages${_r} detected: ${langLabel}\\n`);\n process.stdout.write(` ${_v}\u2713 frameworks${_r} detected: ${fwLabel}\\n`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n // Large-codebase pre-flight warning emitted by VectorManager\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'docs') {\n if (p.meta?.msg) {\n process.stdout.write(`\\r ${_v}docs${_r} ${_d}${p.meta.msg}${_r}${' '.repeat(20)}`);\n if (String(p.meta.msg).startsWith('docs:')) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'data') {\n if (p.meta?.msg) {\n process.stdout.write(`\\r ${_v}data${_r} ${_d}${p.meta.msg}${_r}${' '.repeat(20)}`);\n if (String(p.meta.msg).startsWith('data:')) process.stdout.write('\\n');\n }\n\n } else {\n process.stdout.write(`\\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${' '.repeat(20)}`);\n }\n}\n\n\n// \u2500\u2500 Sync Progress Renderer \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/**\n * Renders a single sync progress event to stdout.\n * Same visual style as renderIndexProgress but tailored for incremental sync.\n */\nexport function renderSyncProgress(p: IndexProgress): void {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n\n if (p.phase === 'scanning') {\n if (p.current > 0) {\n process.stdout.write(`\\r ${_v}\u2713 scanning${_r} ${_v}${_num(p.current)}${_r} ${_d}files found${_r}\\n`);\n } else {\n process.stdout.write(`\\r ${_v}scanning${_r} ${_d}detecting changes\u2026${_r}${' '.repeat(20)}`);\n }\n\n } else if (p.phase === 'parsing') {\n process.stdout.write(`\\r ${_v}parsing${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(8)}`);\n if (p.current === p.total) process.stdout.write('\\n');\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(`\\r ${_v}resolving${_r} cross-file references\u2026${' '.repeat(20)}`);\n } else if (p.total > 0) {\n const bar = _bar(pct);\n const suffix = p.current === p.total\n ? `${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)} refs${_r}\\n`\n : `${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)}${_r}${' '.repeat(10)}`;\n const prefix = p.current === p.total ? `\\r ${_v}\u2713 resolving${_r}` : `\\r ${_v}resolving${_r} `;\n process.stdout.write(`${prefix} [${bar}] ${suffix}`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'docs') {\n if (p.meta?.msg) {\n process.stdout.write(`\\r ${_v}docs${_r} ${_d}${p.meta.msg}${_r}${' '.repeat(20)}`);\n if (String(p.meta.msg).startsWith('docs:')) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'data') {\n if (p.meta?.msg) {\n process.stdout.write(`\\r ${_v}data${_r} ${_d}${p.meta.msg}${_r}${' '.repeat(20)}`);\n if (String(p.meta.msg).startsWith('data:')) process.stdout.write('\\n');\n }\n\n } else {\n process.stdout.write(`\\r ${_v}${p.phase}${_r} ${p.current}/${p.total}${' '.repeat(20)}`);\n }\n}\n\n/**\n * Verbose sync progress renderer for `sync --progress`.\n * Prints each file as it is processed, errors inline, and a running count.\n * Exclude-cleanup removals are shown with a distinct prefix.\n */\nexport function renderSyncProgressVerbose(p: IndexProgress): void {\n if (p.phase === 'scanning') {\n if (p.meta?.excludeCleanup && p.meta.file) {\n // A file is being removed because it now matches an exclude pattern\n process.stdout.write(` ${_d}exclude${_r} ${_d}${p.meta.file}${_r}\\n`);\n } else if (p.current > 0) {\n process.stdout.write(` ${_v}\u2713 scanning${_r} ${_v}${_num(p.current)}${_r} ${_d}files found${_r}\\n`);\n } else {\n process.stdout.write(` ${_v}scanning${_r} ${_d}detecting changes\u2026${_r}\\n`);\n }\n\n } else if (p.phase === 'parsing') {\n if (p.currentFile) {\n const short = p.currentFile.length > 60\n ? '\u2026' + p.currentFile.slice(p.currentFile.length - 59)\n : p.currentFile;\n process.stdout.write(` ${_v}parse${_r} ${_d}[${_num(p.current)}/${_num(p.total)}]${_r} ${short}\\n`);\n }\n\n } else if (p.phase === 'resolving') {\n if (p.current === 0 && p.total <= 1) {\n process.stdout.write(` ${_v}resolving${_r} cross-file references\u2026\\n`);\n } else if (p.total > 0 && p.current === p.total) {\n process.stdout.write(` ${_v}\u2713 resolving${_r} ${_v}${_num(p.current)}${_r}${_d}/${_num(p.total)} refs${_r}\\n`);\n }\n\n } else if (p.phase === 'embeddings') {\n if (p.current === -1) {\n process.stdout.write(`\\n \\x1b[33m\u26A0 Large codebase: ${_num(p.total)} embeddable symbols detected.\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m Embedding may be slow or memory-intensive. Consider setting enableEmbeddings: false\\x1b[0m\\n`);\n process.stdout.write(` \\x1b[33m for codebases this large, or use a lighter model (e.g. Xenova/all-MiniLM-L6-v2).\\x1b[0m\\n\\n`);\n } else {\n const pct = p.total > 0 ? Math.round((p.current / p.total) * 100) : 0;\n process.stdout.write(`\\r ${_v}embeddings${_r} [${_bar(pct)}] ${_v}${pct}%${_r}${' '.repeat(10)}`);\n if (p.current === p.total && p.total > 0) process.stdout.write('\\n');\n }\n\n } else if (p.phase === 'architecture') {\n if (p.meta?.msg) {\n process.stdout.write(` ${_v}architecture${_r} ${_d}${p.meta.msg}${_r}\\n`);\n } else if (p.current === p.total && p.total > 0) {\n process.stdout.write(` ${_v}\u2713 architecture${_r}\\n`);\n }\n\n } else if (p.phase === 'docs') {\n if (p.meta?.msg) {\n process.stdout.write(` ${_v}docs${_r} ${_d}${p.meta.msg}${_r}\\n`);\n }\n\n } else if (p.phase === 'data') {\n if (p.meta?.msg) {\n process.stdout.write(` ${_v}data${_r} ${_d}${p.meta.msg}${_r}\\n`);\n }\n\n } else {\n process.stdout.write(` ${_v}${p.phase}${_r} ${p.current}/${p.total}\\n`);\n }\n}\n\n/**\n * Renders the final sync summary with before/after counts.\n */\nexport function renderSyncSummary(result: SyncResult): void {\n const secs = (result.duration / 1000).toFixed(1);\n const filesChanged = result.added.length + result.modified.length;\n const filesDeleted = result.removed.length;\n\n console.log(`\\n ${_g}\u2713${_r} sync complete ${_d}(${secs}s)${_r}`);\n console.log(` ${_d}files scanned:${_r} ${_v}${_num(result.filesScanned)}${_r}`);\n console.log(` ${_d}files changed:${_r} ${_v}${_num(filesChanged)}${_r}`);\n console.log(` ${_d}files deleted:${_r} ${_v}${_num(filesDeleted)}${_r}`);\n console.log(` ${_d}nodes added:${_r} ${_v}${_num(result.nodesCreated)}${_r}`);\n console.log(` ${_d}nodes updated:${_r} ${_v}${_num(result.nodesUpdated)}${_r}`);\n console.log(` ${_d}nodes removed:${_r} ${_v}${_num(result.nodesRemoved)}${_r}`);\n console.log(` ${_d}edges added:${_r} ${_v}${_num(result.edgesCreated)}${_r}`);\n console.log(` ${_d}edges removed:${_r} ${_v}${_num(result.edgesRemoved)}${_r}`);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -115,6 +115,31 @@ function estimateNaiveCost(toolName, outputTokens, args) {
115
115
  case "kirograph_docs_refs": {
116
116
  return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;
117
117
  }
118
+ // ── Data tools ────────────────────────────────────────────────────────────
119
+ case "kirograph_data_list": {
120
+ return AVG_FIND_TOKENS + AVG_FILE_TOKENS;
121
+ }
122
+ case "kirograph_data_describe": {
123
+ return AVG_FILE_TOKENS * 30;
124
+ }
125
+ case "kirograph_data_query": {
126
+ return AVG_FILE_TOKENS * 30;
127
+ }
128
+ case "kirograph_data_aggregate": {
129
+ return AVG_FILE_TOKENS * 35;
130
+ }
131
+ case "kirograph_data_search": {
132
+ return AVG_GREP_TOKENS * 2 + AVG_FILE_TOKENS * 5;
133
+ }
134
+ case "kirograph_data_join": {
135
+ return AVG_FILE_TOKENS * 60;
136
+ }
137
+ case "kirograph_data_correlations": {
138
+ return AVG_FILE_TOKENS * 40;
139
+ }
140
+ case "kirograph_data_quality": {
141
+ return AVG_FILE_TOKENS * 20;
142
+ }
118
143
  // kirograph_exec and kirograph_gain are tracked separately
119
144
  default:
120
145
  return null;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/compression/naive-cost.ts"],
4
- "sourcesContent": ["/**\n * Naive cost estimator for KiroGraph MCP tools.\n *\n * Estimates how many tokens the agent would have consumed doing the same\n * work without KiroGraph (reading files, running grep, etc.).\n *\n * These are conservative estimates based on typical agent behavior:\n * - kirograph_context: agent would read 5-10 files fully to orient\n * - kirograph_search: agent would run grep/ripgrep across the project\n * - kirograph_callers/callees: agent would grep for the symbol name + read each file\n * - kirograph_impact: agent would trace callers recursively (multiple grep + read cycles)\n * - kirograph_node: agent would read the full file containing the symbol\n * - kirograph_files: agent would run find/ls -R\n * - kirograph_status: agent would check file counts, run wc, etc.\n * - kirograph_hotspots/surprising/dead_code: not feasible manually (infinite cost \u2192 cap at 5x)\n */\n\nimport { estimateTokens } from './index';\n\n/** Average tokens per file read (medium-sized source file ~200 lines) */\nconst AVG_FILE_TOKENS = 1500;\n\n/** Average tokens for a grep result across a medium project */\nconst AVG_GREP_TOKENS = 800;\n\n/** Average tokens for ls -R or find output on a medium project */\nconst AVG_FIND_TOKENS = 2000;\n\n/**\n * Estimate the naive token cost (what the agent would have spent without KiroGraph).\n *\n * @param toolName - The MCP tool that was called\n * @param outputTokens - Actual tokens in the tool's response\n * @param args - The tool arguments (for context-aware estimation)\n * @returns Estimated naive cost in tokens, or null if not estimable\n */\nexport function estimateNaiveCost(toolName: string, outputTokens: number, args?: Record<string, unknown>): number | null {\n switch (toolName) {\n case 'kirograph_context': {\n // Agent would read ~5-10 files to understand a task area\n const maxNodes = (args?.maxNodes as number) || 20;\n const filesEstimate = Math.min(Math.ceil(maxNodes / 2), 10);\n return filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_search': {\n // Agent would run grep/ripgrep and read through results\n const limit = (args?.limit as number) || 10;\n // grep output + reading top matches\n return AVG_GREP_TOKENS + Math.min(limit, 5) * (AVG_FILE_TOKENS / 3);\n }\n\n case 'kirograph_callers': {\n // Agent would grep for the symbol, then read each calling file\n const limit = (args?.limit as number) || 20;\n const callersEstimate = Math.min(limit, 10);\n return AVG_GREP_TOKENS + callersEstimate * (AVG_FILE_TOKENS / 2);\n }\n\n case 'kirograph_callees': {\n // Agent would read the function body + grep for each called symbol\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS * 3;\n }\n\n case 'kirograph_impact': {\n // Agent would need multiple rounds of grep + read (recursive)\n const depth = (args?.depth as number) || 2;\n return (AVG_GREP_TOKENS + AVG_FILE_TOKENS * 3) * depth;\n }\n\n case 'kirograph_node': {\n // Agent would read the full file to find the symbol\n return AVG_FILE_TOKENS;\n }\n\n case 'kirograph_files': {\n // Agent would run find or ls -R\n return AVG_FIND_TOKENS;\n }\n\n case 'kirograph_status': {\n // Agent would run multiple commands (wc -l, find, du, etc.)\n return 500;\n }\n\n case 'kirograph_path': {\n // Agent would need to manually trace connections \u2014 multiple grep + read cycles\n return AVG_GREP_TOKENS * 4 + AVG_FILE_TOKENS * 3;\n }\n\n case 'kirograph_type_hierarchy': {\n // Agent would grep for extends/implements, read each file\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_dead_code': {\n // Not feasible manually \u2014 would require reading every file and cross-referencing\n // Cap at 5x the output (conservative)\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_circular_deps': {\n // Not feasible manually \u2014 would require building a full import graph\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 8);\n }\n\n case 'kirograph_hotspots': {\n // Not feasible manually \u2014 would require counting edges for every symbol\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_surprising': {\n // Not feasible manually\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_architecture':\n case 'kirograph_coupling':\n case 'kirograph_package': {\n // Architecture analysis is not feasible manually\n return Math.max(outputTokens * 4, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_diff': {\n // Agent would need to compare file lists and grep for symbols\n return Math.max(outputTokens * 3, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_mem_search': {\n // Without memory, agent would re-read files to rediscover past decisions.\n // Typically 3-5 files + grep for related context.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return filesEstimate * AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_store': {\n // Storing has no direct naive equivalent \u2014 the knowledge would simply be lost.\n // We don't count savings on store; savings are realized on future searches.\n return null;\n }\n\n case 'kirograph_mem_timeline': {\n // Agent would ask user or re-read previous session context.\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_status': {\n // Lightweight status check, minimal naive cost.\n return 500;\n }\n\n // \u2500\u2500 Docs tools \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 case 'kirograph_docs_toc': {\n // Agent would read all doc files to understand structure.\n // Conservative: 3-5 doc files fully read.\n return AVG_FILE_TOKENS * 4 + AVG_FILE_TOKENS; // docs are ~2500 tokens avg\n }\n\n case 'kirograph_docs_search': {\n // Agent would grep across all doc files + read top matches.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return AVG_GREP_TOKENS + filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_docs_section': {\n // Agent would read the full file to find the relevant section.\n // With context=true, agent would also read parent/child files.\n const withContext = args?.context as boolean;\n return withContext ? AVG_FILE_TOKENS * 3 : AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_outline': {\n // Agent would read the full file to understand its structure.\n return AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_refs': {\n // Agent would grep for symbol names across docs + read code files.\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n // kirograph_exec and kirograph_gain are tracked separately\n default:\n return null;\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Naive cost estimator for KiroGraph MCP tools.\n *\n * Estimates how many tokens the agent would have consumed doing the same\n * work without KiroGraph (reading files, running grep, etc.).\n *\n * These are conservative estimates based on typical agent behavior:\n * - kirograph_context: agent would read 5-10 files fully to orient\n * - kirograph_search: agent would run grep/ripgrep across the project\n * - kirograph_callers/callees: agent would grep for the symbol name + read each file\n * - kirograph_impact: agent would trace callers recursively (multiple grep + read cycles)\n * - kirograph_node: agent would read the full file containing the symbol\n * - kirograph_files: agent would run find/ls -R\n * - kirograph_status: agent would check file counts, run wc, etc.\n * - kirograph_hotspots/surprising/dead_code: not feasible manually (infinite cost \u2192 cap at 5x)\n */\n\nimport { estimateTokens } from './index';\n\n/** Average tokens per file read (medium-sized source file ~200 lines) */\nconst AVG_FILE_TOKENS = 1500;\n\n/** Average tokens for a grep result across a medium project */\nconst AVG_GREP_TOKENS = 800;\n\n/** Average tokens for ls -R or find output on a medium project */\nconst AVG_FIND_TOKENS = 2000;\n\n/**\n * Estimate the naive token cost (what the agent would have spent without KiroGraph).\n *\n * @param toolName - The MCP tool that was called\n * @param outputTokens - Actual tokens in the tool's response\n * @param args - The tool arguments (for context-aware estimation)\n * @returns Estimated naive cost in tokens, or null if not estimable\n */\nexport function estimateNaiveCost(toolName: string, outputTokens: number, args?: Record<string, unknown>): number | null {\n switch (toolName) {\n case 'kirograph_context': {\n // Agent would read ~5-10 files to understand a task area\n const maxNodes = (args?.maxNodes as number) || 20;\n const filesEstimate = Math.min(Math.ceil(maxNodes / 2), 10);\n return filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_search': {\n // Agent would run grep/ripgrep and read through results\n const limit = (args?.limit as number) || 10;\n // grep output + reading top matches\n return AVG_GREP_TOKENS + Math.min(limit, 5) * (AVG_FILE_TOKENS / 3);\n }\n\n case 'kirograph_callers': {\n // Agent would grep for the symbol, then read each calling file\n const limit = (args?.limit as number) || 20;\n const callersEstimate = Math.min(limit, 10);\n return AVG_GREP_TOKENS + callersEstimate * (AVG_FILE_TOKENS / 2);\n }\n\n case 'kirograph_callees': {\n // Agent would read the function body + grep for each called symbol\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS * 3;\n }\n\n case 'kirograph_impact': {\n // Agent would need multiple rounds of grep + read (recursive)\n const depth = (args?.depth as number) || 2;\n return (AVG_GREP_TOKENS + AVG_FILE_TOKENS * 3) * depth;\n }\n\n case 'kirograph_node': {\n // Agent would read the full file to find the symbol\n return AVG_FILE_TOKENS;\n }\n\n case 'kirograph_files': {\n // Agent would run find or ls -R\n return AVG_FIND_TOKENS;\n }\n\n case 'kirograph_status': {\n // Agent would run multiple commands (wc -l, find, du, etc.)\n return 500;\n }\n\n case 'kirograph_path': {\n // Agent would need to manually trace connections \u2014 multiple grep + read cycles\n return AVG_GREP_TOKENS * 4 + AVG_FILE_TOKENS * 3;\n }\n\n case 'kirograph_type_hierarchy': {\n // Agent would grep for extends/implements, read each file\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_dead_code': {\n // Not feasible manually \u2014 would require reading every file and cross-referencing\n // Cap at 5x the output (conservative)\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_circular_deps': {\n // Not feasible manually \u2014 would require building a full import graph\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 8);\n }\n\n case 'kirograph_hotspots': {\n // Not feasible manually \u2014 would require counting edges for every symbol\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_surprising': {\n // Not feasible manually\n return Math.max(outputTokens * 5, AVG_FILE_TOKENS * 10);\n }\n\n case 'kirograph_architecture':\n case 'kirograph_coupling':\n case 'kirograph_package': {\n // Architecture analysis is not feasible manually\n return Math.max(outputTokens * 4, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_diff': {\n // Agent would need to compare file lists and grep for symbols\n return Math.max(outputTokens * 3, AVG_FILE_TOKENS * 5);\n }\n\n case 'kirograph_mem_search': {\n // Without memory, agent would re-read files to rediscover past decisions.\n // Typically 3-5 files + grep for related context.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return filesEstimate * AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_store': {\n // Storing has no direct naive equivalent \u2014 the knowledge would simply be lost.\n // We don't count savings on store; savings are realized on future searches.\n return null;\n }\n\n case 'kirograph_mem_timeline': {\n // Agent would ask user or re-read previous session context.\n return AVG_FILE_TOKENS + AVG_GREP_TOKENS;\n }\n\n case 'kirograph_mem_status': {\n // Lightweight status check, minimal naive cost.\n return 500;\n }\n\n // \u2500\u2500 Docs tools \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 case 'kirograph_docs_toc': {\n // Agent would read all doc files to understand structure.\n // Conservative: 3-5 doc files fully read.\n return AVG_FILE_TOKENS * 4 + AVG_FILE_TOKENS; // docs are ~2500 tokens avg\n }\n\n case 'kirograph_docs_search': {\n // Agent would grep across all doc files + read top matches.\n const limit = (args?.limit as number) || 10;\n const filesEstimate = Math.min(Math.ceil(limit / 2), 5);\n return AVG_GREP_TOKENS + filesEstimate * AVG_FILE_TOKENS;\n }\n\n case 'kirograph_docs_section': {\n // Agent would read the full file to find the relevant section.\n // With context=true, agent would also read parent/child files.\n const withContext = args?.context as boolean;\n return withContext ? AVG_FILE_TOKENS * 3 : AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_outline': {\n // Agent would read the full file to understand its structure.\n return AVG_FILE_TOKENS * 2;\n }\n\n case 'kirograph_docs_refs': {\n // Agent would grep for symbol names across docs + read code files.\n return AVG_GREP_TOKENS * 3 + AVG_FILE_TOKENS * 2;\n }\n\n // \u2500\u2500 Data tools \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 case 'kirograph_data_list': {\n // Agent would run ls/find on data files + inspect each\n return AVG_FIND_TOKENS + AVG_FILE_TOKENS;\n }\n\n case 'kirograph_data_describe': {\n // Agent would read the full data file to understand its schema (~30x a code file)\n return AVG_FILE_TOKENS * 30;\n }\n\n case 'kirograph_data_query': {\n // Agent would read the full file and scan for matching rows\n return AVG_FILE_TOKENS * 30;\n }\n\n case 'kirograph_data_aggregate': {\n // Agent would read the full file, then reason about aggregation in context\n return AVG_FILE_TOKENS * 35;\n }\n\n case 'kirograph_data_search': {\n // Agent would read file headers + grep for values\n return AVG_GREP_TOKENS * 2 + AVG_FILE_TOKENS * 5;\n }\n\n case 'kirograph_data_join': {\n // Agent would read both files entirely\n return AVG_FILE_TOKENS * 60;\n }\n\n case 'kirograph_data_correlations': {\n // Not feasible manually \u2014 would require reading all numeric data\n return AVG_FILE_TOKENS * 40;\n }\n\n case 'kirograph_data_quality': {\n // Agent would read the file and manually inspect each column\n return AVG_FILE_TOKENS * 20;\n }\n\n // kirograph_exec and kirograph_gain are tracked separately\n default:\n return null;\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -105,6 +105,15 @@ class TokenTracker {
105
105
  recordDocsSaving(toolName, outputTokens, naiveCost) {
106
106
  this.record(toolName, naiveCost, outputTokens, `docs:${toolName}`, "docs");
107
107
  }
108
+ /**
109
+ * Record a data tool saving.
110
+ * @param toolName - The MCP tool that was called
111
+ * @param outputTokens - Actual tokens returned by the tool
112
+ * @param naiveCost - Estimated tokens the agent would have used without data indexing
113
+ */
114
+ recordDataSaving(toolName, outputTokens, naiveCost) {
115
+ this.record(toolName, naiveCost, outputTokens, `data:${toolName}`, "data");
116
+ }
108
117
  /**
109
118
  * Get aggregated statistics for a time period.
110
119
  */
@@ -119,13 +128,13 @@ class TokenTracker {
119
128
  savingsPercent: 0,
120
129
  byFamily: {},
121
130
  recentCommands: [],
122
- bySource: { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 } }
131
+ bySource: { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 }, data: { count: 0, saved: 0 } }
123
132
  };
124
133
  }
125
134
  let totalOriginal = 0;
126
135
  let totalCompressed = 0;
127
136
  const byFamily = /* @__PURE__ */ new Map();
128
- const bySource = { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 } };
137
+ const bySource = { exec: { count: 0, saved: 0 }, graph: { count: 0, saved: 0 }, memory: { count: 0, saved: 0 }, docs: { count: 0, saved: 0 }, data: { count: 0, saved: 0 } };
129
138
  for (const r of records) {
130
139
  totalOriginal += r.originalTokens;
131
140
  totalCompressed += r.compressedTokens;