kirograph 0.27.0 → 0.27.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +27 -1
  2. package/dist/bin/commands/callees.js +76 -0
  3. package/dist/bin/commands/callees.js.map +7 -0
  4. package/dist/bin/commands/callers.js +76 -0
  5. package/dist/bin/commands/callers.js.map +7 -0
  6. package/dist/bin/commands/circular-deps.js +68 -0
  7. package/dist/bin/commands/circular-deps.js.map +7 -0
  8. package/dist/bin/commands/help.js +8 -3
  9. package/dist/bin/commands/help.js.map +2 -2
  10. package/dist/bin/commands/hook.js +242 -0
  11. package/dist/bin/commands/hook.js.map +7 -0
  12. package/dist/bin/commands/impact.js +76 -0
  13. package/dist/bin/commands/impact.js.map +7 -0
  14. package/dist/bin/commands/init.js.map +2 -2
  15. package/dist/bin/commands/type-hierarchy.js +76 -0
  16. package/dist/bin/commands/type-hierarchy.js.map +7 -0
  17. package/dist/bin/installer/common.js +15 -9
  18. package/dist/bin/installer/common.js.map +2 -2
  19. package/dist/bin/installer/config-prompt.js +16 -4
  20. package/dist/bin/installer/config-prompt.js.map +2 -2
  21. package/dist/bin/installer/index.js +37 -5
  22. package/dist/bin/installer/index.js.map +2 -2
  23. package/dist/bin/installer/instructions.js +14 -21
  24. package/dist/bin/installer/instructions.js.map +2 -2
  25. package/dist/bin/installer/mcp.js.map +2 -2
  26. package/dist/bin/installer/steering.js +38 -0
  27. package/dist/bin/installer/steering.js.map +2 -2
  28. package/dist/bin/installer/targets/aider.js +3 -3
  29. package/dist/bin/installer/targets/aider.js.map +2 -2
  30. package/dist/bin/installer/targets/amp.js +3 -3
  31. package/dist/bin/installer/targets/amp.js.map +2 -2
  32. package/dist/bin/installer/targets/antigravity.js +4 -4
  33. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  34. package/dist/bin/installer/targets/augment.js +3 -3
  35. package/dist/bin/installer/targets/augment.js.map +2 -2
  36. package/dist/bin/installer/targets/claude.js +3 -3
  37. package/dist/bin/installer/targets/claude.js.map +2 -2
  38. package/dist/bin/installer/targets/cline.js +4 -4
  39. package/dist/bin/installer/targets/cline.js.map +2 -2
  40. package/dist/bin/installer/targets/codex.js +4 -4
  41. package/dist/bin/installer/targets/codex.js.map +2 -2
  42. package/dist/bin/installer/targets/continue.js +4 -4
  43. package/dist/bin/installer/targets/continue.js.map +2 -2
  44. package/dist/bin/installer/targets/copilot-cli.js +4 -4
  45. package/dist/bin/installer/targets/copilot-cli.js.map +2 -2
  46. package/dist/bin/installer/targets/copilot.js +4 -4
  47. package/dist/bin/installer/targets/copilot.js.map +2 -2
  48. package/dist/bin/installer/targets/cursor.js +5 -5
  49. package/dist/bin/installer/targets/cursor.js.map +2 -2
  50. package/dist/bin/installer/targets/devin.js +4 -4
  51. package/dist/bin/installer/targets/devin.js.map +2 -2
  52. package/dist/bin/installer/targets/gemini-cli.js +4 -4
  53. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  54. package/dist/bin/installer/targets/generic.js +2 -2
  55. package/dist/bin/installer/targets/generic.js.map +2 -2
  56. package/dist/bin/installer/targets/goose.js +3 -4
  57. package/dist/bin/installer/targets/goose.js.map +3 -3
  58. package/dist/bin/installer/targets/index.js.map +1 -1
  59. package/dist/bin/installer/targets/junie.js +4 -4
  60. package/dist/bin/installer/targets/junie.js.map +2 -2
  61. package/dist/bin/installer/targets/kilo.js +4 -4
  62. package/dist/bin/installer/targets/kilo.js.map +2 -2
  63. package/dist/bin/installer/targets/kiro.js +23 -3
  64. package/dist/bin/installer/targets/kiro.js.map +2 -2
  65. package/dist/bin/installer/targets/opencode.js +3 -3
  66. package/dist/bin/installer/targets/opencode.js.map +2 -2
  67. package/dist/bin/installer/targets/openhands.js +3 -3
  68. package/dist/bin/installer/targets/openhands.js.map +2 -2
  69. package/dist/bin/installer/targets/qoder.js +2 -2
  70. package/dist/bin/installer/targets/qoder.js.map +2 -2
  71. package/dist/bin/installer/targets/qwen.js +2 -2
  72. package/dist/bin/installer/targets/qwen.js.map +2 -2
  73. package/dist/bin/installer/targets/replit.js +3 -3
  74. package/dist/bin/installer/targets/replit.js.map +2 -2
  75. package/dist/bin/installer/targets/roo.js +4 -4
  76. package/dist/bin/installer/targets/roo.js.map +2 -2
  77. package/dist/bin/installer/targets/tabnine.js +3 -3
  78. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  79. package/dist/bin/installer/targets/trae.js +3 -3
  80. package/dist/bin/installer/targets/trae.js.map +2 -2
  81. package/dist/bin/installer/targets/warp.js +4 -4
  82. package/dist/bin/installer/targets/warp.js.map +2 -2
  83. package/dist/bin/installer/targets/windsurf.js +4 -4
  84. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  85. package/dist/bin/kirograph.js +13 -1
  86. package/dist/bin/kirograph.js.map +3 -3
  87. package/dist/config.js +4 -0
  88. package/dist/config.js.map +2 -2
  89. package/dist/hooks/import-prompt.js +75 -0
  90. package/dist/hooks/import-prompt.js.map +7 -0
  91. package/dist/hooks/manager.js +124 -0
  92. package/dist/hooks/manager.js.map +7 -0
  93. package/dist/hooks/prompt.js +296 -0
  94. package/dist/hooks/prompt.js.map +7 -0
  95. package/dist/mcp/cache.js +1 -1
  96. package/dist/mcp/cache.js.map +2 -2
  97. package/dist/mcp/tool-names.js +43 -4
  98. package/dist/mcp/tool-names.js.map +2 -2
  99. package/dist/mcp/tools.js +774 -182
  100. package/dist/mcp/tools.js.map +3 -3
  101. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/config.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Config System\n *\n * Mirrors CodeGraph src/config.ts \u2014 load, save, validate, and provide defaults\n * for KiroGraph configuration.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport picomatch from 'picomatch';\nimport { logWarn, logError } from './errors';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport interface KiroGraphConfig {\n version: number;\n languages: string[];\n include: string[];\n exclude: string[];\n maxFileSize: number;\n extractDocstrings: boolean;\n trackCallSites: boolean;\n // Parity fields:\n enableEmbeddings: boolean;\n embeddingModel: string;\n embeddingDim: number;\n /** @deprecated Use semanticEngine instead. Kept for backwards compatibility. */\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'turboquant' | 'turbovec' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n /** Apply TurboQuant ANN index to memory observations and doc sections. Default: false. */\n turboquantMemDocs: boolean;\n /** TurboQuant bits per coordinate (1\u20138). Controls compression/quality tradeoff. Default: 3 (\u224825\u00D7). */\n turboquantBits: number;\n /** Apply TurboVec ANN index to memory observations and doc sections. Default: false. */\n turbovecMemDocs: boolean;\n /** TurboVec bits per coordinate (2, 3, or 4). Controls compression/quality tradeoff. Default: 4. */\n turbovecBits: number;\n typesenseDashboard: boolean;\n qdrantDashboard: boolean;\n minLogLevel: 'debug' | 'info' | 'warn' | 'error';\n frameworkHints: string[];\n fuzzyResolutionThreshold: number; // 0.0\u20131.0\n /** Enable architecture analysis (package graph + layer detection). Default: false. */\n enableArchitecture: boolean;\n /**\n * User-defined layer \u2192 glob pattern overrides.\n * When set, config-defined layers win over auto-detected ones.\n * Example: { \"api\": [\"src/routes/**\", \"src/controllers/**\"] }\n */\n architectureLayers?: Record<string, string[]>;\n /** Agent communication style injected at agentSpawn. Default: 'off'. */\n cavemanMode: 'off' | 'lite' | 'full' | 'ultra';\n /** Shell compression level for kirograph_exec. 'off' disables the hook/steering. Default: 'normal'. */\n shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra';\n /**\n * Number of pending (unindexed) files above which kirograph_status warns the agent.\n * Set to 0 to disable the warning. Default: 10.\n */\n syncWarningThreshold: number;\n /** Enable persistent cross-session memory. Default: false. */\n enableMemory: boolean;\n /** FTS/vector blend for memory search: 0 = FTS only, 1 = vector only. Default: 0.5. */\n memorySearchAlpha: number;\n /** Store uncompressed originals when caveman is on. Default: false. */\n memoryKeepRaw: boolean;\n /** Auto-prune threshold (max observations). 0 = no limit. Default: 10000. */\n memoryMaxObservations: number;\n /** Seconds of inactivity before auto-closing a session. Default: 7200. */\n memorySessionTimeout: number;\n /** Max observations shown in kirograph_context. Default: 3. */\n memoryContextLimit: number;\n /** Min relevance score to include memory in context. Default: 0.3. */\n memoryContextThreshold: number;\n /** Glob patterns for paths to never capture in memory. Default: []. */\n memoryExcludePatterns: string[];\n /** Enable watchmen \u2014 auto-synthesize workspace briefs from memory observations. Requires enableMemory. Default: false. */\n enableWatchmen: boolean;\n /** Minimum new observations since last synthesis before watchmenReady fires. Default: 5. */\n watchmenThreshold: number;\n /**\n * How synthesis is performed.\n * 'local' \u2014 runs a local HuggingFace model via @huggingface/transformers (no API cost, works for all tools).\n * 'agent' \u2014 delegates to the active AI agent via askAgent hook (Kiro only, consumes agent tokens).\n * Default: 'local'.\n */\n watchmenSynthesisMode: 'local' | 'agent';\n /** HuggingFace model ID for local synthesis. Only used when watchmenSynthesisMode is 'local'. Default: 'onnx-community/gemma-4-E4B-it-ONNX'. */\n watchmenLocalModel: string;\n /** Enable documentation indexing and navigation. Default: false. */\n enableDocs: boolean;\n /** Glob patterns for documentation files to include. */\n docsInclude: string[];\n /** Glob patterns for documentation files to exclude. */\n docsExclude: string[];\n /** Enable auto-linking of doc sections to code symbols. Default: true. */\n docsLinkCode: boolean;\n /** Max doc sections to include in kirograph_context. 0 = disabled. Default: 0. */\n docsContextLimit: number;\n /** Min relevance score to include a doc section in context. Default: 0.3. */\n docsContextThreshold: number;\n /** Max file size for doc files (bytes). Default: 1MB. */\n docsMaxFileSize: number;\n /** Summarization strategy. Default: 'first-sentence'. */\n docsSummarization: 'embedding' | 'first-sentence' | 'off';\n /** Enable LLM-maintained wiki (entity pages in .kirograph/wiki/). Default: false. */\n enableWiki: boolean;\n /** Wiki synthesis mode. Default: 'agent'. */\n wikiSynthesisMode: 'agent' | 'local';\n /** HuggingFace model for local wiki synthesis. */\n wikiLocalModel: string;\n /** Glob patterns for auto-ingest wiki sources. Default: ['docs/']. */\n wikiSources: string[];\n /** Auto-resolve wiki conflicts by source date. Default: false. */\n wikiAutoResolveConflicts: boolean;\n /** Lint frequency: 'weekly' (every ~20 sessions) or 'off'. Default: 'off'. */\n wikiLintFrequency: 'weekly' | 'off';\n /** Max wiki pages to include in kirograph_context. Default: 3. */\n wikiContextLimit: number;\n /** Min FTS score to include wiki page in context. Default: 0.4. */\n wikiContextThreshold: number;\n /** Enable tabular data indexing and querying. Default: false. */\n enableData: boolean;\n /** Glob patterns for data files to include. */\n dataInclude: string[];\n /** Glob patterns for data files to exclude. */\n dataExclude: string[];\n /** Enable auto-linking of data files to code symbols. Default: true. */\n dataLinkCode: boolean;\n /** Max datasets to include in kirograph_context. 0 = disabled. Default: 0. */\n dataContextLimit: number;\n /** Max file size for data files (bytes). Default: 50MB. */\n dataMaxFileSize: number;\n /** Max rows to index per file. Default: 1,000,000. */\n dataMaxRows: number;\n /** Max rows returned per query. Default: 500. */\n dataQueryLimit: number;\n /** Max token budget per response. Default: 8000. */\n dataMaxResponseTokens: number;\n /** Enable security analysis (dependency scanning + vulnerability detection). Default: false. */\n enableSecurity: boolean;\n /** Vulnerability databases to query. Default: ['OSV']. */\n securityDatabases: string[];\n /** Enable AST-level structural pattern matching (SAST) during indexing. Default: false. */\n enablePatterns: boolean;\n /** Enable code health tools (hotspots, dead code, change tracking). Default: true. */\n enableCodeHealth: boolean;\n /** Enable advanced analysis tools (type hierarchies, flows, communities, refactor). Default: true. */\n enableAdvancedAnalysis: boolean;\n /** Enable agent utility tools (file caching, budget tracking). Default: true. */\n enableAgentUtils: boolean;\n /** Derived from shellCompressionLevel \u2014 true when compression is enabled. Controls kirograph_exec. */\n enableShellExec: boolean;\n /** Path to a directory of user-supplied YAML rule files. Merged with bundled library (user rules win on id conflict). Default: undefined. */\n patternLibraryPath: string | undefined;\n /** Minimum severity level for storing pattern matches during index-time analysis. Default: 'low'. */\n patternSeverityThreshold: 'critical' | 'high' | 'medium' | 'low';\n /** Auto-run vulnerability enrichment after manifest parsing. Default: true. */\n securityAutoEnrich: boolean;\n /** Max age in days for vulnerability data before showing a staleness warning. Default: 7. */\n securityEnrichMaxAgeDays: number;\n /**\n * License policy for dependency compliance.\n * deny: licenses to block (build fails / command exits non-zero).\n * warn: licenses to flag as warnings.\n * Patterns support wildcards: GPL-* matches GPL-2.0, GPL-3.0, etc.\n * Default: { deny: [], warn: [] }.\n */\n securityLicensePolicy: {\n deny: string[];\n warn: string[];\n };\n /** Context budget governance settings. */\n contextBudget?: {\n maxTokensPerSession: number;\n warnAt: number;\n throttleAt: number;\n };\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 KIROGRAPH_DIR = '.kirograph';\nconst CONFIG_FILE = 'config.json';\n\nconst KNOWN_FIELDS = new Set<string>([\n 'version', 'languages', 'include', 'exclude', 'maxFileSize',\n 'extractDocstrings', 'trackCallSites', 'enableEmbeddings', 'embeddingModel', 'embeddingDim',\n 'useVecIndex', 'semanticEngine', 'turboquantMemDocs', 'turboquantBits', 'turbovecMemDocs', 'turbovecBits', 'typesenseDashboard', 'qdrantDashboard',\n 'minLogLevel', 'frameworkHints', 'fuzzyResolutionThreshold',\n 'enableArchitecture', 'architectureLayers', 'cavemanMode', 'shellCompressionLevel', 'syncWarningThreshold',\n 'enableMemory', 'memorySearchAlpha', 'memoryKeepRaw', 'memoryMaxObservations',\n 'memorySessionTimeout', 'memoryContextLimit', 'memoryContextThreshold', 'memoryExcludePatterns',\n 'enableWatchmen', 'watchmenThreshold', 'watchmenSynthesisMode', 'watchmenLocalModel',\n 'enableWiki', 'wikiSynthesisMode', 'wikiLocalModel', 'wikiSources',\n 'wikiAutoResolveConflicts', 'wikiLintFrequency', 'wikiContextLimit', 'wikiContextThreshold',\n 'enableDocs', 'docsInclude', 'docsExclude', 'docsLinkCode',\n 'docsContextLimit', 'docsContextThreshold', 'docsMaxFileSize', 'docsSummarization',\n 'enableData', 'dataInclude', 'dataExclude', 'dataLinkCode',\n 'dataContextLimit', 'dataMaxFileSize', 'dataMaxRows', 'dataQueryLimit', 'dataMaxResponseTokens',\n 'enableSecurity', 'securityDatabases', 'securityAutoEnrich', 'securityEnrichMaxAgeDays', 'securityLicensePolicy',\n 'enablePatterns', 'patternLibraryPath', 'patternSeverityThreshold',\n 'enableCodeHealth', 'enableAdvancedAnalysis', 'enableAgentUtils',\n 'contextBudget',\n // Legacy aliases / derived fields (accepted but ignored or recomputed)\n 'enableCompression', 'compressionLevel', 'enableShellExec',\n]);\n\nconst LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);\n\n// \u2500\u2500 ReDoS-safe regex check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Returns false if the pattern is potentially dangerous (ReDoS risk) or too long.\n * Checks for catastrophic backtracking patterns like (a+)+ or (a|a)+.\n */\nexport function isSafeRegex(pattern: string): boolean {\n if (pattern.length > 100) return false;\n // Detect nested quantifiers: (x+)+ or (x*)+ or (x+)* etc.\n if (/\\([^)]*[+*][^)]*\\)[+*?]/.test(pattern)) return false;\n // Detect alternation with overlap: (a|a)+ style\n if (/\\([^)]*\\|[^)]*\\)[+*]/.test(pattern)) return false;\n return true;\n}\n\n// \u2500\u2500 Default config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function createDefaultConfig(_projectRoot?: string): KiroGraphConfig {\n return {\n version: 2,\n languages: [],\n include: [],\n exclude: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '*.min.js', '**/.kirograph/**'],\n maxFileSize: 1_048_576,\n extractDocstrings: false,\n trackCallSites: false,\n enableEmbeddings: false,\n embeddingModel: 'nomic-ai/nomic-embed-text-v1.5',\n embeddingDim: 768,\n useVecIndex: false,\n semanticEngine: 'cosine',\n turboquantMemDocs: false,\n turboquantBits: 3,\n turbovecMemDocs: false,\n turbovecBits: 4,\n typesenseDashboard: false,\n qdrantDashboard: false,\n minLogLevel: 'warn',\n frameworkHints: [],\n fuzzyResolutionThreshold: 0.5,\n enableArchitecture: false,\n cavemanMode: 'off',\n shellCompressionLevel: 'normal',\n syncWarningThreshold: 10,\n enableMemory: false,\n memorySearchAlpha: 0.5,\n memoryKeepRaw: false,\n memoryMaxObservations: 10000,\n memorySessionTimeout: 7200,\n memoryContextLimit: 3,\n memoryContextThreshold: 0.3,\n memoryExcludePatterns: [],\n enableWatchmen: false,\n watchmenThreshold: 5,\n watchmenSynthesisMode: 'local',\n watchmenLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n enableWiki: false,\n wikiSynthesisMode: 'agent' as const,\n wikiLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n wikiSources: ['docs/'],\n wikiAutoResolveConflicts: false,\n wikiLintFrequency: 'off' as const,\n wikiContextLimit: 3,\n wikiContextThreshold: 0.4,\n enableDocs: false,\n docsInclude: ['**/*.md', '**/*.mdx', '**/*.rst', '**/*.adoc', '**/*.asciidoc', '**/*.rdoc', '**/*.org', '**/*.cheatmd', 'docs/**/*.txt', 'docs/**/*.html'],\n docsExclude: ['node_modules/**', '**/CHANGELOG*', '**/LICENSE*', '**/CHANGES*', 'dist/**', 'build/**', 'coverage/**', '.git/**', '**/generated/**', '**/auto-generated/**', '**/vendor/**', '_build/**'],\n docsLinkCode: true,\n docsContextLimit: 0,\n docsContextThreshold: 0.3,\n docsMaxFileSize: 1_048_576,\n docsSummarization: 'first-sentence',\n enableData: false,\n dataInclude: ['**/*.csv', '**/*.tsv', '**/*.jsonl', '**/*.ndjson', '**/*.xlsx', '**/*.xls', '**/*.parquet', 'data/**/*.json', '**/*.pdf'],\n dataExclude: ['node_modules/**', 'dist/**', 'build/**', '.git/**', '**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml', '**/tsconfig.json', '**/jsconfig.json', 'coverage/**', '**/generated/**'],\n dataLinkCode: true,\n dataContextLimit: 0,\n dataMaxFileSize: 52_428_800,\n dataMaxRows: 1_000_000,\n dataQueryLimit: 500,\n dataMaxResponseTokens: 8000,\n enableSecurity: false,\n securityDatabases: ['OSV'],\n securityAutoEnrich: true,\n securityEnrichMaxAgeDays: 7,\n securityLicensePolicy: { deny: [], warn: [] },\n enablePatterns: false,\n patternLibraryPath: undefined,\n patternSeverityThreshold: 'low',\n enableCodeHealth: true,\n enableAdvancedAnalysis: true,\n enableAgentUtils: true,\n enableShellExec: true,\n };\n}\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function validateConfig(config: unknown): KiroGraphConfig {\n const defaults = createDefaultConfig();\n\n if (typeof config !== 'object' || config === null) {\n return defaults;\n }\n\n const raw = config as Record<string, unknown>;\n\n // Warn about unknown fields\n for (const key of Object.keys(raw)) {\n if (!KNOWN_FIELDS.has(key)) {\n logWarn(`Unknown config field: ${key}`);\n }\n }\n\n // Validate and coerce each field\n const version = typeof raw.version === 'number' ? raw.version : defaults.version;\n const languages = Array.isArray(raw.languages) && raw.languages.every(l => typeof l === 'string')\n ? (raw.languages as string[])\n : defaults.languages;\n const maxFileSize = typeof raw.maxFileSize === 'number' && raw.maxFileSize > 0\n ? raw.maxFileSize\n : defaults.maxFileSize;\n const extractDocstrings = typeof raw.extractDocstrings === 'boolean'\n ? raw.extractDocstrings\n : defaults.extractDocstrings;\n const trackCallSites = typeof raw.trackCallSites === 'boolean'\n ? raw.trackCallSites\n : defaults.trackCallSites;\n const enableEmbeddings = typeof raw.enableEmbeddings === 'boolean'\n ? raw.enableEmbeddings\n : defaults.enableEmbeddings;\n const embeddingModel = typeof raw.embeddingModel === 'string' && raw.embeddingModel.length > 0\n ? raw.embeddingModel\n : defaults.embeddingModel;\n const embeddingDim = typeof raw.embeddingDim === 'number' && raw.embeddingDim > 0\n ? raw.embeddingDim\n : defaults.embeddingDim;\n const useVecIndex = typeof raw.useVecIndex === 'boolean'\n ? raw.useVecIndex\n : defaults.useVecIndex;\n const SEMANTIC_ENGINES = new Set(['cosine', 'turboquant', 'turbovec', 'sqlite-vec', 'orama', 'pglite', 'lancedb', 'qdrant', 'typesense']);\n // useVecIndex is a legacy alias: if set and no explicit semanticEngine, map it\n const semanticEngine = typeof raw.semanticEngine === 'string' && SEMANTIC_ENGINES.has(raw.semanticEngine)\n ? (raw.semanticEngine as KiroGraphConfig['semanticEngine'])\n : useVecIndex ? 'sqlite-vec' : defaults.semanticEngine;\n const turboquantMemDocs = typeof raw.turboquantMemDocs === 'boolean'\n ? raw.turboquantMemDocs\n : defaults.turboquantMemDocs;\n const turboquantBits = typeof raw.turboquantBits === 'number'\n && raw.turboquantBits >= 1 && raw.turboquantBits <= 8\n ? Math.round(raw.turboquantBits)\n : defaults.turboquantBits;\n const turbovecMemDocs = typeof raw.turbovecMemDocs === 'boolean'\n ? raw.turbovecMemDocs\n : defaults.turbovecMemDocs;\n const TURBOVEC_BIT_WIDTHS = new Set([2, 3, 4]);\n const turbovecBits = typeof raw.turbovecBits === 'number' && TURBOVEC_BIT_WIDTHS.has(Math.round(raw.turbovecBits))\n ? Math.round(raw.turbovecBits)\n : defaults.turbovecBits;\n const typesenseDashboard = typeof raw.typesenseDashboard === 'boolean'\n ? raw.typesenseDashboard\n : defaults.typesenseDashboard;\n const qdrantDashboard = typeof raw.qdrantDashboard === 'boolean'\n ? raw.qdrantDashboard\n : defaults.qdrantDashboard;\n const minLogLevel = typeof raw.minLogLevel === 'string' && LOG_LEVELS.has(raw.minLogLevel)\n ? (raw.minLogLevel as KiroGraphConfig['minLogLevel'])\n : defaults.minLogLevel;\n const frameworkHints = Array.isArray(raw.frameworkHints) && raw.frameworkHints.every(h => typeof h === 'string')\n ? (raw.frameworkHints as string[])\n : defaults.frameworkHints;\n const fuzzyResolutionThreshold = typeof raw.fuzzyResolutionThreshold === 'number'\n && raw.fuzzyResolutionThreshold >= 0\n && raw.fuzzyResolutionThreshold <= 1\n ? raw.fuzzyResolutionThreshold\n : defaults.fuzzyResolutionThreshold;\n const enableArchitecture = typeof raw.enableArchitecture === 'boolean'\n ? raw.enableArchitecture\n : defaults.enableArchitecture;\n const architectureLayers = _validateArchitectureLayers(raw.architectureLayers);\n const CAVEMAN_MODES = new Set(['off', 'lite', 'full', 'ultra']);\n const cavemanMode = typeof raw.cavemanMode === 'string' && CAVEMAN_MODES.has(raw.cavemanMode)\n ? (raw.cavemanMode as KiroGraphConfig['cavemanMode'])\n : defaults.cavemanMode;\n const COMPRESSION_LEVELS = new Set(['off', 'normal', 'aggressive', 'ultra']);\n // Support legacy field names: enableCompression (boolean) and compressionLevel (string)\n let shellCompressionLevel: KiroGraphConfig['shellCompressionLevel'];\n if (typeof raw.shellCompressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.shellCompressionLevel)) {\n shellCompressionLevel = raw.shellCompressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.compressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.compressionLevel)) {\n shellCompressionLevel = raw.compressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.enableCompression === 'boolean') {\n shellCompressionLevel = raw.enableCompression ? 'normal' : 'off';\n } else {\n shellCompressionLevel = defaults.shellCompressionLevel;\n }\n const syncWarningThreshold = typeof raw.syncWarningThreshold === 'number' && raw.syncWarningThreshold >= 0\n ? Math.round(raw.syncWarningThreshold)\n : defaults.syncWarningThreshold;\n\n // \u2500\u2500 Memory config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableMemory = typeof raw.enableMemory === 'boolean'\n ? raw.enableMemory\n : defaults.enableMemory;\n const memorySearchAlpha = typeof raw.memorySearchAlpha === 'number'\n && raw.memorySearchAlpha >= 0 && raw.memorySearchAlpha <= 1\n ? raw.memorySearchAlpha\n : defaults.memorySearchAlpha;\n const memoryKeepRaw = typeof raw.memoryKeepRaw === 'boolean'\n ? raw.memoryKeepRaw\n : defaults.memoryKeepRaw;\n const memoryMaxObservations = typeof raw.memoryMaxObservations === 'number' && raw.memoryMaxObservations >= 0\n ? Math.round(raw.memoryMaxObservations)\n : defaults.memoryMaxObservations;\n const memorySessionTimeout = typeof raw.memorySessionTimeout === 'number' && raw.memorySessionTimeout > 0\n ? Math.round(raw.memorySessionTimeout)\n : defaults.memorySessionTimeout;\n const memoryContextLimit = typeof raw.memoryContextLimit === 'number' && raw.memoryContextLimit >= 0\n ? Math.round(raw.memoryContextLimit)\n : defaults.memoryContextLimit;\n const memoryContextThreshold = typeof raw.memoryContextThreshold === 'number'\n && raw.memoryContextThreshold >= 0 && raw.memoryContextThreshold <= 1\n ? raw.memoryContextThreshold\n : defaults.memoryContextThreshold;\n const memoryExcludePatterns = Array.isArray(raw.memoryExcludePatterns)\n && raw.memoryExcludePatterns.every((p: unknown) => typeof p === 'string')\n ? (raw.memoryExcludePatterns as string[])\n : defaults.memoryExcludePatterns;\n\n // \u2500\u2500 Watchmen config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableWatchmen = typeof raw.enableWatchmen === 'boolean'\n ? raw.enableWatchmen\n : defaults.enableWatchmen;\n const watchmenThreshold = typeof raw.watchmenThreshold === 'number' && raw.watchmenThreshold > 0\n ? Math.round(raw.watchmenThreshold)\n : defaults.watchmenThreshold;\n const WATCHMEN_SYNTHESIS_MODES = new Set(['local', 'agent']);\n const watchmenSynthesisMode = typeof raw.watchmenSynthesisMode === 'string' && WATCHMEN_SYNTHESIS_MODES.has(raw.watchmenSynthesisMode)\n ? (raw.watchmenSynthesisMode as KiroGraphConfig['watchmenSynthesisMode'])\n : defaults.watchmenSynthesisMode;\n const watchmenLocalModel = typeof raw.watchmenLocalModel === 'string' && raw.watchmenLocalModel.length > 0\n ? raw.watchmenLocalModel\n : defaults.watchmenLocalModel;\n\n // \u2500\u2500 Wiki config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableWiki = typeof raw.enableWiki === 'boolean' ? raw.enableWiki : defaults.enableWiki;\n const wikiSynthesisMode = raw.wikiSynthesisMode === 'local' ? 'local' as const : 'agent' as const;\n const wikiLocalModel = typeof raw.wikiLocalModel === 'string' ? raw.wikiLocalModel : defaults.wikiLocalModel;\n const wikiSources = Array.isArray(raw.wikiSources) ? raw.wikiSources : defaults.wikiSources;\n const wikiAutoResolveConflicts = typeof raw.wikiAutoResolveConflicts === 'boolean' ? raw.wikiAutoResolveConflicts : defaults.wikiAutoResolveConflicts;\n const wikiLintFrequency = raw.wikiLintFrequency === 'weekly' ? 'weekly' as const : 'off' as const;\n const wikiContextLimit = typeof raw.wikiContextLimit === 'number' ? raw.wikiContextLimit : defaults.wikiContextLimit;\n const wikiContextThreshold = typeof raw.wikiContextThreshold === 'number' ? raw.wikiContextThreshold : defaults.wikiContextThreshold;\n\n // \u2500\u2500 Docs config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableDocs = typeof raw.enableDocs === 'boolean'\n ? raw.enableDocs\n : defaults.enableDocs;\n const docsInclude = Array.isArray(raw.docsInclude)\n && raw.docsInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsInclude as string[])\n : defaults.docsInclude;\n const docsExclude = Array.isArray(raw.docsExclude)\n && raw.docsExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsExclude as string[])\n : defaults.docsExclude;\n const docsLinkCode = typeof raw.docsLinkCode === 'boolean'\n ? raw.docsLinkCode\n : defaults.docsLinkCode;\n const docsContextLimit = typeof raw.docsContextLimit === 'number' && raw.docsContextLimit >= 0\n ? Math.round(raw.docsContextLimit)\n : defaults.docsContextLimit;\n const docsContextThreshold = typeof raw.docsContextThreshold === 'number'\n && raw.docsContextThreshold >= 0 && raw.docsContextThreshold <= 1\n ? raw.docsContextThreshold\n : defaults.docsContextThreshold;\n const docsMaxFileSize = typeof raw.docsMaxFileSize === 'number' && raw.docsMaxFileSize > 0\n ? raw.docsMaxFileSize\n : defaults.docsMaxFileSize;\n const DOCS_SUMMARIZATION_MODES = new Set(['embedding', 'first-sentence', 'off']);\n const docsSummarization = typeof raw.docsSummarization === 'string' && DOCS_SUMMARIZATION_MODES.has(raw.docsSummarization)\n ? (raw.docsSummarization as KiroGraphConfig['docsSummarization'])\n : defaults.docsSummarization;\n\n // \u2500\u2500 Data config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableData = typeof raw.enableData === 'boolean' ? raw.enableData : defaults.enableData;\n const dataInclude = Array.isArray(raw.dataInclude) && raw.dataInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataInclude as string[]) : defaults.dataInclude;\n const dataExclude = Array.isArray(raw.dataExclude) && raw.dataExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataExclude as string[]) : defaults.dataExclude;\n const dataLinkCode = typeof raw.dataLinkCode === 'boolean' ? raw.dataLinkCode : defaults.dataLinkCode;\n const dataContextLimit = typeof raw.dataContextLimit === 'number' && raw.dataContextLimit >= 0\n ? Math.round(raw.dataContextLimit) : defaults.dataContextLimit;\n const dataMaxFileSize = typeof raw.dataMaxFileSize === 'number' && raw.dataMaxFileSize > 0\n ? raw.dataMaxFileSize : defaults.dataMaxFileSize;\n const dataMaxRows = typeof raw.dataMaxRows === 'number' && raw.dataMaxRows > 0\n ? Math.round(raw.dataMaxRows) : defaults.dataMaxRows;\n const dataQueryLimit = typeof raw.dataQueryLimit === 'number' && raw.dataQueryLimit > 0\n ? Math.min(Math.round(raw.dataQueryLimit), 500) : defaults.dataQueryLimit;\n const dataMaxResponseTokens = typeof raw.dataMaxResponseTokens === 'number' && raw.dataMaxResponseTokens > 0\n ? Math.round(raw.dataMaxResponseTokens) : defaults.dataMaxResponseTokens;\n\n // \u2500\u2500 Security config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let enableSecurity: boolean;\n if (typeof raw.enableSecurity === 'boolean') {\n enableSecurity = raw.enableSecurity;\n } else {\n if (raw.enableSecurity !== undefined) {\n logWarn('Invalid config field enableSecurity: expected boolean, applying default (false)');\n }\n enableSecurity = defaults.enableSecurity;\n }\n\n let securityAutoEnrich: boolean;\n if (typeof raw.securityAutoEnrich === 'boolean') {\n securityAutoEnrich = raw.securityAutoEnrich;\n } else {\n if (raw.securityAutoEnrich !== undefined) {\n logWarn('Invalid config field securityAutoEnrich: expected boolean, applying default (true)');\n }\n securityAutoEnrich = defaults.securityAutoEnrich;\n }\n\n let securityEnrichMaxAgeDays: number;\n if (typeof raw.securityEnrichMaxAgeDays === 'number' && raw.securityEnrichMaxAgeDays > 0) {\n securityEnrichMaxAgeDays = raw.securityEnrichMaxAgeDays;\n } else {\n if (raw.securityEnrichMaxAgeDays !== undefined) {\n logWarn('Invalid config field securityEnrichMaxAgeDays: expected positive number, applying default (7)');\n }\n securityEnrichMaxAgeDays = defaults.securityEnrichMaxAgeDays;\n }\n\n const SUPPORTED_SECURITY_DATABASES = new Set(['OSV']);\n let securityDatabases: string[];\n if (Array.isArray(raw.securityDatabases) && raw.securityDatabases.every((d: unknown) => typeof d === 'string')) {\n const valid = (raw.securityDatabases as string[]).filter(d => {\n if (!SUPPORTED_SECURITY_DATABASES.has(d)) {\n logWarn(`Unsupported security database \"${d}\" in securityDatabases, ignoring`);\n return false;\n }\n return true;\n });\n securityDatabases = valid.length > 0 ? valid : defaults.securityDatabases;\n } else {\n if (raw.securityDatabases !== undefined) {\n logWarn('Invalid config field securityDatabases: expected array of strings, applying default ([\"OSV\"])');\n }\n securityDatabases = defaults.securityDatabases;\n }\n\n let securityLicensePolicy: KiroGraphConfig['securityLicensePolicy'];\n if (raw.securityLicensePolicy && typeof raw.securityLicensePolicy === 'object' && !Array.isArray(raw.securityLicensePolicy)) {\n const rawPolicy = raw.securityLicensePolicy as Record<string, unknown>;\n const deny = Array.isArray(rawPolicy.deny) && rawPolicy.deny.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.deny as string[])\n : defaults.securityLicensePolicy.deny;\n const warn = Array.isArray(rawPolicy.warn) && rawPolicy.warn.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.warn as string[])\n : defaults.securityLicensePolicy.warn;\n securityLicensePolicy = { deny, warn };\n } else {\n if (raw.securityLicensePolicy !== undefined) {\n logWarn('Invalid config field securityLicensePolicy: expected object with deny/warn arrays, applying default');\n }\n securityLicensePolicy = defaults.securityLicensePolicy;\n }\n\n // \u2500\u2500 Patterns config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let enablePatterns: boolean;\n if (typeof raw.enablePatterns === 'boolean') {\n enablePatterns = raw.enablePatterns;\n } else {\n if (raw.enablePatterns !== undefined) {\n logWarn('Invalid config field enablePatterns: expected boolean, applying default (false)');\n }\n enablePatterns = defaults.enablePatterns;\n }\n\n let patternLibraryPath: string | undefined;\n if (raw.patternLibraryPath === undefined || raw.patternLibraryPath === null) {\n patternLibraryPath = undefined;\n } else if (typeof raw.patternLibraryPath === 'string') {\n patternLibraryPath = raw.patternLibraryPath;\n } else {\n logWarn('Invalid config field patternLibraryPath: expected string or undefined, applying default (undefined)');\n patternLibraryPath = defaults.patternLibraryPath;\n }\n\n const PATTERN_SEVERITY_LEVELS = new Set(['critical', 'high', 'medium', 'low']);\n let patternSeverityThreshold: KiroGraphConfig['patternSeverityThreshold'];\n if (typeof raw.patternSeverityThreshold === 'string' && PATTERN_SEVERITY_LEVELS.has(raw.patternSeverityThreshold)) {\n patternSeverityThreshold = raw.patternSeverityThreshold as KiroGraphConfig['patternSeverityThreshold'];\n } else {\n if (raw.patternSeverityThreshold !== undefined) {\n logWarn('Invalid config field patternSeverityThreshold: expected critical|high|medium|low, applying default (low)');\n }\n patternSeverityThreshold = defaults.patternSeverityThreshold;\n }\n\n // \u2500\u2500 Tool group flags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableCodeHealth = typeof raw.enableCodeHealth === 'boolean'\n ? raw.enableCodeHealth\n : defaults.enableCodeHealth;\n const enableAdvancedAnalysis = typeof raw.enableAdvancedAnalysis === 'boolean'\n ? raw.enableAdvancedAnalysis\n : defaults.enableAdvancedAnalysis;\n const enableAgentUtils = typeof raw.enableAgentUtils === 'boolean'\n ? raw.enableAgentUtils\n : defaults.enableAgentUtils;\n\n // Dependency constraint: enableSecurity requires enableArchitecture\n let finalEnableArchitecture = enableArchitecture;\n if (enableSecurity && !enableArchitecture) {\n logWarn('enableSecurity requires enableArchitecture \\u2014 auto-enabling architecture analysis');\n finalEnableArchitecture = true;\n }\n\n // \u2500\u2500 Context budget config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let contextBudget: KiroGraphConfig['contextBudget'] | undefined;\n if (raw.contextBudget && typeof raw.contextBudget === 'object' && !Array.isArray(raw.contextBudget)) {\n const cb = raw.contextBudget as Record<string, unknown>;\n contextBudget = {\n maxTokensPerSession: typeof cb.maxTokensPerSession === 'number' && cb.maxTokensPerSession > 0\n ? Math.round(cb.maxTokensPerSession) : 100_000,\n warnAt: typeof cb.warnAt === 'number' && cb.warnAt > 0\n ? Math.round(cb.warnAt) : 80_000,\n throttleAt: typeof cb.throttleAt === 'number' && cb.throttleAt > 0\n ? Math.round(cb.throttleAt) : 95_000,\n };\n }\n\n // Validate glob patterns \u2014 exclude unsafe regex patterns\n const include = _validatePatterns(raw.include, defaults.include);\n const exclude = _validatePatterns(raw.exclude, defaults.exclude);\n\n return {\n version,\n languages,\n include,\n exclude,\n maxFileSize,\n extractDocstrings,\n trackCallSites,\n enableEmbeddings,\n embeddingModel,\n embeddingDim,\n useVecIndex,\n semanticEngine,\n turboquantMemDocs,\n turboquantBits,\n turbovecMemDocs,\n turbovecBits,\n typesenseDashboard,\n qdrantDashboard,\n minLogLevel,\n frameworkHints,\n fuzzyResolutionThreshold,\n enableArchitecture: finalEnableArchitecture,\n cavemanMode,\n shellCompressionLevel,\n syncWarningThreshold,\n enableMemory,\n memorySearchAlpha,\n memoryKeepRaw,\n memoryMaxObservations,\n memorySessionTimeout,\n memoryContextLimit,\n memoryContextThreshold,\n memoryExcludePatterns,\n enableWatchmen: enableWatchmen && enableMemory,\n watchmenThreshold,\n watchmenSynthesisMode,\n watchmenLocalModel,\n enableWiki,\n wikiSynthesisMode,\n wikiLocalModel,\n wikiSources,\n wikiAutoResolveConflicts,\n wikiLintFrequency,\n wikiContextLimit,\n wikiContextThreshold,\n enableDocs,\n docsInclude,\n docsExclude,\n docsLinkCode,\n docsContextLimit,\n docsContextThreshold,\n docsMaxFileSize,\n docsSummarization,\n enableData,\n dataInclude,\n dataExclude,\n dataLinkCode,\n dataContextLimit,\n dataMaxFileSize,\n dataMaxRows,\n dataQueryLimit,\n dataMaxResponseTokens,\n enableSecurity,\n securityDatabases,\n securityAutoEnrich,\n securityEnrichMaxAgeDays,\n securityLicensePolicy,\n enablePatterns,\n patternLibraryPath,\n patternSeverityThreshold,\n enableCodeHealth,\n enableAdvancedAnalysis,\n enableAgentUtils,\n enableShellExec: shellCompressionLevel !== 'off',\n ...(architectureLayers !== undefined ? { architectureLayers } : {}),\n ...(contextBudget !== undefined ? { contextBudget } : {}),\n };\n}\n\nfunction _validateArchitectureLayers(raw: unknown): Record<string, string[]> | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const result: Record<string, string[]> = {};\n for (const [key, val] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof key !== 'string') continue;\n if (!Array.isArray(val)) continue;\n const patterns = val.filter((p): p is string => typeof p === 'string' && isSafeRegex(p));\n if (patterns.length > 0) result[key] = patterns;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction _validatePatterns(raw: unknown, fallback: string[]): string[] {\n if (!Array.isArray(raw)) return fallback;\n const valid: string[] = [];\n for (const p of raw) {\n if (typeof p !== 'string') continue;\n if (!isSafeRegex(p)) {\n logWarn(`Unsafe regex pattern skipped: ${p}`);\n continue;\n }\n valid.push(p);\n }\n return valid;\n}\n\n// \u2500\u2500 Migration 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\n\n/**\n * Upgrades shallow exclude patterns (e.g. \"node_modules/**\") to recursive ones\n * (e.g. \"** /node_modules/**\") so nested directories are excluded at any depth.\n */\nconst SHALLOW_TO_RECURSIVE: Record<string, string> = {\n 'node_modules/**': '**/node_modules/**',\n 'dist/**': '**/dist/**',\n 'build/**': '**/build/**',\n '.git/**': '**/.git/**',\n '.kirograph/**': '**/.kirograph/**',\n};\n\nfunction migrateExcludePatterns(patterns: string[]): string[] {\n return patterns.map(p => SHALLOW_TO_RECURSIVE[p] ?? p);\n}\n\n// \u2500\u2500 Load / Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport async function loadConfig(projectRoot: string): Promise<KiroGraphConfig> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n\n if (!fs.existsSync(cfgPath)) {\n // Create default config file\n const defaults = createDefaultConfig(projectRoot);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, defaults);\n return defaults;\n }\n\n let raw: unknown;\n try {\n const text = await fs.promises.readFile(cfgPath, 'utf8');\n raw = JSON.parse(text);\n } catch (err) {\n logError('Config parse error', { path: cfgPath, error: err instanceof Error ? err.message : String(err) });\n return createDefaultConfig(projectRoot);\n }\n\n const config = validateConfig(raw);\n\n // Migrate v1 \u2192 v2: upgrade shallow exclude patterns to recursive\n if (config.version < 2) {\n config.version = 2;\n config.exclude = migrateExcludePatterns(config.exclude);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n }\n\n return config;\n}\n\nexport async function saveConfig(projectRoot: string, config: KiroGraphConfig): Promise<void> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n}\n\nasync function _writeAtomic(cfgPath: string, config: KiroGraphConfig): Promise<void> {\n const tmp = cfgPath + '.tmp';\n await fs.promises.writeFile(tmp, JSON.stringify(config, null, 2), 'utf8');\n await fs.promises.rename(tmp, cfgPath);\n}\n\n// \u2500\u2500 Update 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\n\nexport async function updateConfig(\n projectRoot: string,\n patch: Partial<KiroGraphConfig>\n): Promise<KiroGraphConfig> {\n const current = await loadConfig(projectRoot);\n const updated = validateConfig({ ...current, ...patch });\n await saveConfig(projectRoot, updated);\n return updated;\n}\n\nexport async function addIncludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.include);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, include: [...config.include, ...toAdd] });\n}\n\nexport async function addExcludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.exclude);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, exclude: [...config.exclude, ...toAdd] });\n}\n\n// \u2500\u2500 File inclusion check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function shouldIncludeFile(config: KiroGraphConfig, relPath: string): boolean {\n // Check exclude patterns first\n for (const pattern of config.exclude) {\n if (picomatch(pattern)(relPath)) return false;\n }\n // If include patterns are specified, file must match at least one\n if (config.include.length > 0) {\n return config.include.some(pattern => picomatch(pattern)(relPath));\n }\n return true;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph Config System\n *\n * Mirrors CodeGraph src/config.ts \u2014 load, save, validate, and provide defaults\n * for KiroGraph configuration.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport picomatch from 'picomatch';\nimport { logWarn, logError } from './errors';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport interface KiroGraphConfig {\n version: number;\n languages: string[];\n include: string[];\n exclude: string[];\n maxFileSize: number;\n extractDocstrings: boolean;\n trackCallSites: boolean;\n // Parity fields:\n enableEmbeddings: boolean;\n embeddingModel: string;\n embeddingDim: number;\n /** @deprecated Use semanticEngine instead. Kept for backwards compatibility. */\n useVecIndex: boolean;\n semanticEngine: 'cosine' | 'turboquant' | 'turbovec' | 'sqlite-vec' | 'orama' | 'pglite' | 'lancedb' | 'qdrant' | 'typesense';\n /** Apply TurboQuant ANN index to memory observations and doc sections. Default: false. */\n turboquantMemDocs: boolean;\n /** TurboQuant bits per coordinate (1\u20138). Controls compression/quality tradeoff. Default: 3 (\u224825\u00D7). */\n turboquantBits: number;\n /** Apply TurboVec ANN index to memory observations and doc sections. Default: false. */\n turbovecMemDocs: boolean;\n /** TurboVec bits per coordinate (2, 3, or 4). Controls compression/quality tradeoff. Default: 4. */\n turbovecBits: number;\n typesenseDashboard: boolean;\n qdrantDashboard: boolean;\n minLogLevel: 'debug' | 'info' | 'warn' | 'error';\n frameworkHints: string[];\n fuzzyResolutionThreshold: number; // 0.0\u20131.0\n /** Enable architecture analysis (package graph + layer detection). Default: false. */\n enableArchitecture: boolean;\n /**\n * User-defined layer \u2192 glob pattern overrides.\n * When set, config-defined layers win over auto-detected ones.\n * Example: { \"api\": [\"src/routes/**\", \"src/controllers/**\"] }\n */\n architectureLayers?: Record<string, string[]>;\n /** Agent communication style injected at agentSpawn. Default: 'off'. */\n cavemanMode: 'off' | 'lite' | 'full' | 'ultra';\n /** Shell compression level for kirograph_exec. 'off' disables the hook/steering. Default: 'normal'. */\n shellCompressionLevel: 'off' | 'normal' | 'aggressive' | 'ultra';\n /**\n * Number of pending (unindexed) files above which kirograph_status warns the agent.\n * Set to 0 to disable the warning. Default: 10.\n */\n syncWarningThreshold: number;\n /** Enable persistent cross-session memory. Default: false. */\n enableMemory: boolean;\n /** FTS/vector blend for memory search: 0 = FTS only, 1 = vector only. Default: 0.5. */\n memorySearchAlpha: number;\n /** Store uncompressed originals when caveman is on. Default: false. */\n memoryKeepRaw: boolean;\n /** Auto-prune threshold (max observations). 0 = no limit. Default: 10000. */\n memoryMaxObservations: number;\n /** Seconds of inactivity before auto-closing a session. Default: 7200. */\n memorySessionTimeout: number;\n /** Max observations shown in kirograph_context. Default: 3. */\n memoryContextLimit: number;\n /** Min relevance score to include memory in context. Default: 0.3. */\n memoryContextThreshold: number;\n /** Glob patterns for paths to never capture in memory. Default: []. */\n memoryExcludePatterns: string[];\n /** Enable watchmen \u2014 auto-synthesize workspace briefs from memory observations. Requires enableMemory. Default: false. */\n enableWatchmen: boolean;\n /** Minimum new observations since last synthesis before watchmenReady fires. Default: 5. */\n watchmenThreshold: number;\n /**\n * How synthesis is performed.\n * 'local' \u2014 runs a local HuggingFace model via @huggingface/transformers (no API cost, works for all tools).\n * 'agent' \u2014 delegates to the active AI agent via askAgent hook (Kiro only, consumes agent tokens).\n * Default: 'local'.\n */\n watchmenSynthesisMode: 'local' | 'agent';\n /** HuggingFace model ID for local synthesis. Only used when watchmenSynthesisMode is 'local'. Default: 'onnx-community/gemma-4-E4B-it-ONNX'. */\n watchmenLocalModel: string;\n /** Enable documentation indexing and navigation. Default: false. */\n enableDocs: boolean;\n /** Glob patterns for documentation files to include. */\n docsInclude: string[];\n /** Glob patterns for documentation files to exclude. */\n docsExclude: string[];\n /** Enable auto-linking of doc sections to code symbols. Default: true. */\n docsLinkCode: boolean;\n /** Max doc sections to include in kirograph_context. 0 = disabled. Default: 0. */\n docsContextLimit: number;\n /** Min relevance score to include a doc section in context. Default: 0.3. */\n docsContextThreshold: number;\n /** Max file size for doc files (bytes). Default: 1MB. */\n docsMaxFileSize: number;\n /** Summarization strategy. Default: 'first-sentence'. */\n docsSummarization: 'embedding' | 'first-sentence' | 'off';\n /** Enable LLM-maintained wiki (entity pages in .kirograph/wiki/). Default: false. */\n enableWiki: boolean;\n /** Wiki synthesis mode. Default: 'agent'. */\n wikiSynthesisMode: 'agent' | 'local';\n /** HuggingFace model for local wiki synthesis. */\n wikiLocalModel: string;\n /** Glob patterns for auto-ingest wiki sources. Default: ['docs/']. */\n wikiSources: string[];\n /** Auto-resolve wiki conflicts by source date. Default: false. */\n wikiAutoResolveConflicts: boolean;\n /** Lint frequency: 'weekly' (every ~20 sessions) or 'off'. Default: 'off'. */\n wikiLintFrequency: 'weekly' | 'off';\n /** Max wiki pages to include in kirograph_context. Default: 3. */\n wikiContextLimit: number;\n /** Min FTS score to include wiki page in context. Default: 0.4. */\n wikiContextThreshold: number;\n /** Enable tabular data indexing and querying. Default: false. */\n enableData: boolean;\n /** Glob patterns for data files to include. */\n dataInclude: string[];\n /** Glob patterns for data files to exclude. */\n dataExclude: string[];\n /** Enable auto-linking of data files to code symbols. Default: true. */\n dataLinkCode: boolean;\n /** Max datasets to include in kirograph_context. 0 = disabled. Default: 0. */\n dataContextLimit: number;\n /** Max file size for data files (bytes). Default: 50MB. */\n dataMaxFileSize: number;\n /** Max rows to index per file. Default: 1,000,000. */\n dataMaxRows: number;\n /** Max rows returned per query. Default: 500. */\n dataQueryLimit: number;\n /** Max token budget per response. Default: 8000. */\n dataMaxResponseTokens: number;\n /** Enable security analysis (dependency scanning + vulnerability detection). Default: false. */\n enableSecurity: boolean;\n /** Vulnerability databases to query. Default: ['OSV']. */\n securityDatabases: string[];\n /** Enable AST-level structural pattern matching (SAST) during indexing. Default: false. */\n enablePatterns: boolean;\n /** Enable code health tools (hotspots, dead code, change tracking). Default: true. */\n enableCodeHealth: boolean;\n /** Enable advanced analysis tools (type hierarchies, flows, communities, refactor). Default: true. */\n enableAdvancedAnalysis: boolean;\n /** Enable agent utility tools (file caching, budget tracking). Default: true. */\n enableAgentUtils: boolean;\n /** Enable general-purpose compression tool (kirograph_compress). Default: false. */\n enableGeneralCompression: boolean;\n /** Derived from shellCompressionLevel \u2014 true when compression is enabled. Controls kirograph_exec. */\n enableShellExec: boolean;\n /** Path to a directory of user-supplied YAML rule files. Merged with bundled library (user rules win on id conflict). Default: undefined. */\n patternLibraryPath: string | undefined;\n /** Minimum severity level for storing pattern matches during index-time analysis. Default: 'low'. */\n patternSeverityThreshold: 'critical' | 'high' | 'medium' | 'low';\n /** Auto-run vulnerability enrichment after manifest parsing. Default: true. */\n securityAutoEnrich: boolean;\n /** Max age in days for vulnerability data before showing a staleness warning. Default: 7. */\n securityEnrichMaxAgeDays: number;\n /**\n * License policy for dependency compliance.\n * deny: licenses to block (build fails / command exits non-zero).\n * warn: licenses to flag as warnings.\n * Patterns support wildcards: GPL-* matches GPL-2.0, GPL-3.0, etc.\n * Default: { deny: [], warn: [] }.\n */\n securityLicensePolicy: {\n deny: string[];\n warn: string[];\n };\n /** Context budget governance settings. */\n contextBudget?: {\n maxTokensPerSession: number;\n warnAt: number;\n throttleAt: number;\n };\n}\n\n// \u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 KIROGRAPH_DIR = '.kirograph';\nconst CONFIG_FILE = 'config.json';\n\nconst KNOWN_FIELDS = new Set<string>([\n 'version', 'languages', 'include', 'exclude', 'maxFileSize',\n 'extractDocstrings', 'trackCallSites', 'enableEmbeddings', 'embeddingModel', 'embeddingDim',\n 'useVecIndex', 'semanticEngine', 'turboquantMemDocs', 'turboquantBits', 'turbovecMemDocs', 'turbovecBits', 'typesenseDashboard', 'qdrantDashboard',\n 'minLogLevel', 'frameworkHints', 'fuzzyResolutionThreshold',\n 'enableArchitecture', 'architectureLayers', 'cavemanMode', 'shellCompressionLevel', 'syncWarningThreshold',\n 'enableMemory', 'memorySearchAlpha', 'memoryKeepRaw', 'memoryMaxObservations',\n 'memorySessionTimeout', 'memoryContextLimit', 'memoryContextThreshold', 'memoryExcludePatterns',\n 'enableWatchmen', 'watchmenThreshold', 'watchmenSynthesisMode', 'watchmenLocalModel',\n 'enableWiki', 'wikiSynthesisMode', 'wikiLocalModel', 'wikiSources',\n 'wikiAutoResolveConflicts', 'wikiLintFrequency', 'wikiContextLimit', 'wikiContextThreshold',\n 'enableDocs', 'docsInclude', 'docsExclude', 'docsLinkCode',\n 'docsContextLimit', 'docsContextThreshold', 'docsMaxFileSize', 'docsSummarization',\n 'enableData', 'dataInclude', 'dataExclude', 'dataLinkCode',\n 'dataContextLimit', 'dataMaxFileSize', 'dataMaxRows', 'dataQueryLimit', 'dataMaxResponseTokens',\n 'enableSecurity', 'securityDatabases', 'securityAutoEnrich', 'securityEnrichMaxAgeDays', 'securityLicensePolicy',\n 'enablePatterns', 'patternLibraryPath', 'patternSeverityThreshold',\n 'enableCodeHealth', 'enableAdvancedAnalysis', 'enableAgentUtils', 'enableGeneralCompression',\n 'contextBudget',\n // Legacy aliases / derived fields (accepted but ignored or recomputed)\n 'enableCompression', 'compressionLevel', 'enableShellExec',\n]);\n\nconst LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);\n\n// \u2500\u2500 ReDoS-safe regex check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Returns false if the pattern is potentially dangerous (ReDoS risk) or too long.\n * Checks for catastrophic backtracking patterns like (a+)+ or (a|a)+.\n */\nexport function isSafeRegex(pattern: string): boolean {\n if (pattern.length > 100) return false;\n // Detect nested quantifiers: (x+)+ or (x*)+ or (x+)* etc.\n if (/\\([^)]*[+*][^)]*\\)[+*?]/.test(pattern)) return false;\n // Detect alternation with overlap: (a|a)+ style\n if (/\\([^)]*\\|[^)]*\\)[+*]/.test(pattern)) return false;\n return true;\n}\n\n// \u2500\u2500 Default config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function createDefaultConfig(_projectRoot?: string): KiroGraphConfig {\n return {\n version: 2,\n languages: [],\n include: [],\n exclude: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '*.min.js', '**/.kirograph/**'],\n maxFileSize: 1_048_576,\n extractDocstrings: false,\n trackCallSites: false,\n enableEmbeddings: false,\n embeddingModel: 'nomic-ai/nomic-embed-text-v1.5',\n embeddingDim: 768,\n useVecIndex: false,\n semanticEngine: 'cosine',\n turboquantMemDocs: false,\n turboquantBits: 3,\n turbovecMemDocs: false,\n turbovecBits: 4,\n typesenseDashboard: false,\n qdrantDashboard: false,\n minLogLevel: 'warn',\n frameworkHints: [],\n fuzzyResolutionThreshold: 0.5,\n enableArchitecture: false,\n cavemanMode: 'off',\n shellCompressionLevel: 'normal',\n syncWarningThreshold: 10,\n enableMemory: false,\n memorySearchAlpha: 0.5,\n memoryKeepRaw: false,\n memoryMaxObservations: 10000,\n memorySessionTimeout: 7200,\n memoryContextLimit: 3,\n memoryContextThreshold: 0.3,\n memoryExcludePatterns: [],\n enableWatchmen: false,\n watchmenThreshold: 5,\n watchmenSynthesisMode: 'local',\n watchmenLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n enableWiki: false,\n wikiSynthesisMode: 'agent' as const,\n wikiLocalModel: 'onnx-community/gemma-4-E4B-it-ONNX',\n wikiSources: ['docs/'],\n wikiAutoResolveConflicts: false,\n wikiLintFrequency: 'off' as const,\n wikiContextLimit: 3,\n wikiContextThreshold: 0.4,\n enableDocs: false,\n docsInclude: ['**/*.md', '**/*.mdx', '**/*.rst', '**/*.adoc', '**/*.asciidoc', '**/*.rdoc', '**/*.org', '**/*.cheatmd', 'docs/**/*.txt', 'docs/**/*.html'],\n docsExclude: ['node_modules/**', '**/CHANGELOG*', '**/LICENSE*', '**/CHANGES*', 'dist/**', 'build/**', 'coverage/**', '.git/**', '**/generated/**', '**/auto-generated/**', '**/vendor/**', '_build/**'],\n docsLinkCode: true,\n docsContextLimit: 0,\n docsContextThreshold: 0.3,\n docsMaxFileSize: 1_048_576,\n docsSummarization: 'first-sentence',\n enableData: false,\n dataInclude: ['**/*.csv', '**/*.tsv', '**/*.jsonl', '**/*.ndjson', '**/*.xlsx', '**/*.xls', '**/*.parquet', 'data/**/*.json', '**/*.pdf'],\n dataExclude: ['node_modules/**', 'dist/**', 'build/**', '.git/**', '**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml', '**/tsconfig.json', '**/jsconfig.json', 'coverage/**', '**/generated/**'],\n dataLinkCode: true,\n dataContextLimit: 0,\n dataMaxFileSize: 52_428_800,\n dataMaxRows: 1_000_000,\n dataQueryLimit: 500,\n dataMaxResponseTokens: 8000,\n enableSecurity: false,\n securityDatabases: ['OSV'],\n securityAutoEnrich: true,\n securityEnrichMaxAgeDays: 7,\n securityLicensePolicy: { deny: [], warn: [] },\n enablePatterns: false,\n patternLibraryPath: undefined,\n patternSeverityThreshold: 'low',\n enableCodeHealth: true,\n enableAdvancedAnalysis: true,\n enableAgentUtils: true,\n enableGeneralCompression: false,\n enableShellExec: true,\n };\n}\n\n// \u2500\u2500 Validation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function validateConfig(config: unknown): KiroGraphConfig {\n const defaults = createDefaultConfig();\n\n if (typeof config !== 'object' || config === null) {\n return defaults;\n }\n\n const raw = config as Record<string, unknown>;\n\n // Warn about unknown fields\n for (const key of Object.keys(raw)) {\n if (!KNOWN_FIELDS.has(key)) {\n logWarn(`Unknown config field: ${key}`);\n }\n }\n\n // Validate and coerce each field\n const version = typeof raw.version === 'number' ? raw.version : defaults.version;\n const languages = Array.isArray(raw.languages) && raw.languages.every(l => typeof l === 'string')\n ? (raw.languages as string[])\n : defaults.languages;\n const maxFileSize = typeof raw.maxFileSize === 'number' && raw.maxFileSize > 0\n ? raw.maxFileSize\n : defaults.maxFileSize;\n const extractDocstrings = typeof raw.extractDocstrings === 'boolean'\n ? raw.extractDocstrings\n : defaults.extractDocstrings;\n const trackCallSites = typeof raw.trackCallSites === 'boolean'\n ? raw.trackCallSites\n : defaults.trackCallSites;\n const enableEmbeddings = typeof raw.enableEmbeddings === 'boolean'\n ? raw.enableEmbeddings\n : defaults.enableEmbeddings;\n const embeddingModel = typeof raw.embeddingModel === 'string' && raw.embeddingModel.length > 0\n ? raw.embeddingModel\n : defaults.embeddingModel;\n const embeddingDim = typeof raw.embeddingDim === 'number' && raw.embeddingDim > 0\n ? raw.embeddingDim\n : defaults.embeddingDim;\n const useVecIndex = typeof raw.useVecIndex === 'boolean'\n ? raw.useVecIndex\n : defaults.useVecIndex;\n const SEMANTIC_ENGINES = new Set(['cosine', 'turboquant', 'turbovec', 'sqlite-vec', 'orama', 'pglite', 'lancedb', 'qdrant', 'typesense']);\n // useVecIndex is a legacy alias: if set and no explicit semanticEngine, map it\n const semanticEngine = typeof raw.semanticEngine === 'string' && SEMANTIC_ENGINES.has(raw.semanticEngine)\n ? (raw.semanticEngine as KiroGraphConfig['semanticEngine'])\n : useVecIndex ? 'sqlite-vec' : defaults.semanticEngine;\n const turboquantMemDocs = typeof raw.turboquantMemDocs === 'boolean'\n ? raw.turboquantMemDocs\n : defaults.turboquantMemDocs;\n const turboquantBits = typeof raw.turboquantBits === 'number'\n && raw.turboquantBits >= 1 && raw.turboquantBits <= 8\n ? Math.round(raw.turboquantBits)\n : defaults.turboquantBits;\n const turbovecMemDocs = typeof raw.turbovecMemDocs === 'boolean'\n ? raw.turbovecMemDocs\n : defaults.turbovecMemDocs;\n const TURBOVEC_BIT_WIDTHS = new Set([2, 3, 4]);\n const turbovecBits = typeof raw.turbovecBits === 'number' && TURBOVEC_BIT_WIDTHS.has(Math.round(raw.turbovecBits))\n ? Math.round(raw.turbovecBits)\n : defaults.turbovecBits;\n const typesenseDashboard = typeof raw.typesenseDashboard === 'boolean'\n ? raw.typesenseDashboard\n : defaults.typesenseDashboard;\n const qdrantDashboard = typeof raw.qdrantDashboard === 'boolean'\n ? raw.qdrantDashboard\n : defaults.qdrantDashboard;\n const minLogLevel = typeof raw.minLogLevel === 'string' && LOG_LEVELS.has(raw.minLogLevel)\n ? (raw.minLogLevel as KiroGraphConfig['minLogLevel'])\n : defaults.minLogLevel;\n const frameworkHints = Array.isArray(raw.frameworkHints) && raw.frameworkHints.every(h => typeof h === 'string')\n ? (raw.frameworkHints as string[])\n : defaults.frameworkHints;\n const fuzzyResolutionThreshold = typeof raw.fuzzyResolutionThreshold === 'number'\n && raw.fuzzyResolutionThreshold >= 0\n && raw.fuzzyResolutionThreshold <= 1\n ? raw.fuzzyResolutionThreshold\n : defaults.fuzzyResolutionThreshold;\n const enableArchitecture = typeof raw.enableArchitecture === 'boolean'\n ? raw.enableArchitecture\n : defaults.enableArchitecture;\n const architectureLayers = _validateArchitectureLayers(raw.architectureLayers);\n const CAVEMAN_MODES = new Set(['off', 'lite', 'full', 'ultra']);\n const cavemanMode = typeof raw.cavemanMode === 'string' && CAVEMAN_MODES.has(raw.cavemanMode)\n ? (raw.cavemanMode as KiroGraphConfig['cavemanMode'])\n : defaults.cavemanMode;\n const COMPRESSION_LEVELS = new Set(['off', 'normal', 'aggressive', 'ultra']);\n // Support legacy field names: enableCompression (boolean) and compressionLevel (string)\n let shellCompressionLevel: KiroGraphConfig['shellCompressionLevel'];\n if (typeof raw.shellCompressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.shellCompressionLevel)) {\n shellCompressionLevel = raw.shellCompressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.compressionLevel === 'string' && COMPRESSION_LEVELS.has(raw.compressionLevel)) {\n shellCompressionLevel = raw.compressionLevel as KiroGraphConfig['shellCompressionLevel'];\n } else if (typeof raw.enableCompression === 'boolean') {\n shellCompressionLevel = raw.enableCompression ? 'normal' : 'off';\n } else {\n shellCompressionLevel = defaults.shellCompressionLevel;\n }\n const syncWarningThreshold = typeof raw.syncWarningThreshold === 'number' && raw.syncWarningThreshold >= 0\n ? Math.round(raw.syncWarningThreshold)\n : defaults.syncWarningThreshold;\n\n // \u2500\u2500 Memory config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableMemory = typeof raw.enableMemory === 'boolean'\n ? raw.enableMemory\n : defaults.enableMemory;\n const memorySearchAlpha = typeof raw.memorySearchAlpha === 'number'\n && raw.memorySearchAlpha >= 0 && raw.memorySearchAlpha <= 1\n ? raw.memorySearchAlpha\n : defaults.memorySearchAlpha;\n const memoryKeepRaw = typeof raw.memoryKeepRaw === 'boolean'\n ? raw.memoryKeepRaw\n : defaults.memoryKeepRaw;\n const memoryMaxObservations = typeof raw.memoryMaxObservations === 'number' && raw.memoryMaxObservations >= 0\n ? Math.round(raw.memoryMaxObservations)\n : defaults.memoryMaxObservations;\n const memorySessionTimeout = typeof raw.memorySessionTimeout === 'number' && raw.memorySessionTimeout > 0\n ? Math.round(raw.memorySessionTimeout)\n : defaults.memorySessionTimeout;\n const memoryContextLimit = typeof raw.memoryContextLimit === 'number' && raw.memoryContextLimit >= 0\n ? Math.round(raw.memoryContextLimit)\n : defaults.memoryContextLimit;\n const memoryContextThreshold = typeof raw.memoryContextThreshold === 'number'\n && raw.memoryContextThreshold >= 0 && raw.memoryContextThreshold <= 1\n ? raw.memoryContextThreshold\n : defaults.memoryContextThreshold;\n const memoryExcludePatterns = Array.isArray(raw.memoryExcludePatterns)\n && raw.memoryExcludePatterns.every((p: unknown) => typeof p === 'string')\n ? (raw.memoryExcludePatterns as string[])\n : defaults.memoryExcludePatterns;\n\n // \u2500\u2500 Watchmen config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableWatchmen = typeof raw.enableWatchmen === 'boolean'\n ? raw.enableWatchmen\n : defaults.enableWatchmen;\n const watchmenThreshold = typeof raw.watchmenThreshold === 'number' && raw.watchmenThreshold > 0\n ? Math.round(raw.watchmenThreshold)\n : defaults.watchmenThreshold;\n const WATCHMEN_SYNTHESIS_MODES = new Set(['local', 'agent']);\n const watchmenSynthesisMode = typeof raw.watchmenSynthesisMode === 'string' && WATCHMEN_SYNTHESIS_MODES.has(raw.watchmenSynthesisMode)\n ? (raw.watchmenSynthesisMode as KiroGraphConfig['watchmenSynthesisMode'])\n : defaults.watchmenSynthesisMode;\n const watchmenLocalModel = typeof raw.watchmenLocalModel === 'string' && raw.watchmenLocalModel.length > 0\n ? raw.watchmenLocalModel\n : defaults.watchmenLocalModel;\n\n // \u2500\u2500 Wiki config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableWiki = typeof raw.enableWiki === 'boolean' ? raw.enableWiki : defaults.enableWiki;\n const wikiSynthesisMode = raw.wikiSynthesisMode === 'local' ? 'local' as const : 'agent' as const;\n const wikiLocalModel = typeof raw.wikiLocalModel === 'string' ? raw.wikiLocalModel : defaults.wikiLocalModel;\n const wikiSources = Array.isArray(raw.wikiSources) ? raw.wikiSources : defaults.wikiSources;\n const wikiAutoResolveConflicts = typeof raw.wikiAutoResolveConflicts === 'boolean' ? raw.wikiAutoResolveConflicts : defaults.wikiAutoResolveConflicts;\n const wikiLintFrequency = raw.wikiLintFrequency === 'weekly' ? 'weekly' as const : 'off' as const;\n const wikiContextLimit = typeof raw.wikiContextLimit === 'number' ? raw.wikiContextLimit : defaults.wikiContextLimit;\n const wikiContextThreshold = typeof raw.wikiContextThreshold === 'number' ? raw.wikiContextThreshold : defaults.wikiContextThreshold;\n\n // \u2500\u2500 Docs config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableDocs = typeof raw.enableDocs === 'boolean'\n ? raw.enableDocs\n : defaults.enableDocs;\n const docsInclude = Array.isArray(raw.docsInclude)\n && raw.docsInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsInclude as string[])\n : defaults.docsInclude;\n const docsExclude = Array.isArray(raw.docsExclude)\n && raw.docsExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.docsExclude as string[])\n : defaults.docsExclude;\n const docsLinkCode = typeof raw.docsLinkCode === 'boolean'\n ? raw.docsLinkCode\n : defaults.docsLinkCode;\n const docsContextLimit = typeof raw.docsContextLimit === 'number' && raw.docsContextLimit >= 0\n ? Math.round(raw.docsContextLimit)\n : defaults.docsContextLimit;\n const docsContextThreshold = typeof raw.docsContextThreshold === 'number'\n && raw.docsContextThreshold >= 0 && raw.docsContextThreshold <= 1\n ? raw.docsContextThreshold\n : defaults.docsContextThreshold;\n const docsMaxFileSize = typeof raw.docsMaxFileSize === 'number' && raw.docsMaxFileSize > 0\n ? raw.docsMaxFileSize\n : defaults.docsMaxFileSize;\n const DOCS_SUMMARIZATION_MODES = new Set(['embedding', 'first-sentence', 'off']);\n const docsSummarization = typeof raw.docsSummarization === 'string' && DOCS_SUMMARIZATION_MODES.has(raw.docsSummarization)\n ? (raw.docsSummarization as KiroGraphConfig['docsSummarization'])\n : defaults.docsSummarization;\n\n // \u2500\u2500 Data config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableData = typeof raw.enableData === 'boolean' ? raw.enableData : defaults.enableData;\n const dataInclude = Array.isArray(raw.dataInclude) && raw.dataInclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataInclude as string[]) : defaults.dataInclude;\n const dataExclude = Array.isArray(raw.dataExclude) && raw.dataExclude.every((p: unknown) => typeof p === 'string')\n ? (raw.dataExclude as string[]) : defaults.dataExclude;\n const dataLinkCode = typeof raw.dataLinkCode === 'boolean' ? raw.dataLinkCode : defaults.dataLinkCode;\n const dataContextLimit = typeof raw.dataContextLimit === 'number' && raw.dataContextLimit >= 0\n ? Math.round(raw.dataContextLimit) : defaults.dataContextLimit;\n const dataMaxFileSize = typeof raw.dataMaxFileSize === 'number' && raw.dataMaxFileSize > 0\n ? raw.dataMaxFileSize : defaults.dataMaxFileSize;\n const dataMaxRows = typeof raw.dataMaxRows === 'number' && raw.dataMaxRows > 0\n ? Math.round(raw.dataMaxRows) : defaults.dataMaxRows;\n const dataQueryLimit = typeof raw.dataQueryLimit === 'number' && raw.dataQueryLimit > 0\n ? Math.min(Math.round(raw.dataQueryLimit), 500) : defaults.dataQueryLimit;\n const dataMaxResponseTokens = typeof raw.dataMaxResponseTokens === 'number' && raw.dataMaxResponseTokens > 0\n ? Math.round(raw.dataMaxResponseTokens) : defaults.dataMaxResponseTokens;\n\n // \u2500\u2500 Security config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let enableSecurity: boolean;\n if (typeof raw.enableSecurity === 'boolean') {\n enableSecurity = raw.enableSecurity;\n } else {\n if (raw.enableSecurity !== undefined) {\n logWarn('Invalid config field enableSecurity: expected boolean, applying default (false)');\n }\n enableSecurity = defaults.enableSecurity;\n }\n\n let securityAutoEnrich: boolean;\n if (typeof raw.securityAutoEnrich === 'boolean') {\n securityAutoEnrich = raw.securityAutoEnrich;\n } else {\n if (raw.securityAutoEnrich !== undefined) {\n logWarn('Invalid config field securityAutoEnrich: expected boolean, applying default (true)');\n }\n securityAutoEnrich = defaults.securityAutoEnrich;\n }\n\n let securityEnrichMaxAgeDays: number;\n if (typeof raw.securityEnrichMaxAgeDays === 'number' && raw.securityEnrichMaxAgeDays > 0) {\n securityEnrichMaxAgeDays = raw.securityEnrichMaxAgeDays;\n } else {\n if (raw.securityEnrichMaxAgeDays !== undefined) {\n logWarn('Invalid config field securityEnrichMaxAgeDays: expected positive number, applying default (7)');\n }\n securityEnrichMaxAgeDays = defaults.securityEnrichMaxAgeDays;\n }\n\n const SUPPORTED_SECURITY_DATABASES = new Set(['OSV']);\n let securityDatabases: string[];\n if (Array.isArray(raw.securityDatabases) && raw.securityDatabases.every((d: unknown) => typeof d === 'string')) {\n const valid = (raw.securityDatabases as string[]).filter(d => {\n if (!SUPPORTED_SECURITY_DATABASES.has(d)) {\n logWarn(`Unsupported security database \"${d}\" in securityDatabases, ignoring`);\n return false;\n }\n return true;\n });\n securityDatabases = valid.length > 0 ? valid : defaults.securityDatabases;\n } else {\n if (raw.securityDatabases !== undefined) {\n logWarn('Invalid config field securityDatabases: expected array of strings, applying default ([\"OSV\"])');\n }\n securityDatabases = defaults.securityDatabases;\n }\n\n let securityLicensePolicy: KiroGraphConfig['securityLicensePolicy'];\n if (raw.securityLicensePolicy && typeof raw.securityLicensePolicy === 'object' && !Array.isArray(raw.securityLicensePolicy)) {\n const rawPolicy = raw.securityLicensePolicy as Record<string, unknown>;\n const deny = Array.isArray(rawPolicy.deny) && rawPolicy.deny.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.deny as string[])\n : defaults.securityLicensePolicy.deny;\n const warn = Array.isArray(rawPolicy.warn) && rawPolicy.warn.every((p: unknown) => typeof p === 'string')\n ? (rawPolicy.warn as string[])\n : defaults.securityLicensePolicy.warn;\n securityLicensePolicy = { deny, warn };\n } else {\n if (raw.securityLicensePolicy !== undefined) {\n logWarn('Invalid config field securityLicensePolicy: expected object with deny/warn arrays, applying default');\n }\n securityLicensePolicy = defaults.securityLicensePolicy;\n }\n\n // \u2500\u2500 Patterns config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let enablePatterns: boolean;\n if (typeof raw.enablePatterns === 'boolean') {\n enablePatterns = raw.enablePatterns;\n } else {\n if (raw.enablePatterns !== undefined) {\n logWarn('Invalid config field enablePatterns: expected boolean, applying default (false)');\n }\n enablePatterns = defaults.enablePatterns;\n }\n\n let patternLibraryPath: string | undefined;\n if (raw.patternLibraryPath === undefined || raw.patternLibraryPath === null) {\n patternLibraryPath = undefined;\n } else if (typeof raw.patternLibraryPath === 'string') {\n patternLibraryPath = raw.patternLibraryPath;\n } else {\n logWarn('Invalid config field patternLibraryPath: expected string or undefined, applying default (undefined)');\n patternLibraryPath = defaults.patternLibraryPath;\n }\n\n const PATTERN_SEVERITY_LEVELS = new Set(['critical', 'high', 'medium', 'low']);\n let patternSeverityThreshold: KiroGraphConfig['patternSeverityThreshold'];\n if (typeof raw.patternSeverityThreshold === 'string' && PATTERN_SEVERITY_LEVELS.has(raw.patternSeverityThreshold)) {\n patternSeverityThreshold = raw.patternSeverityThreshold as KiroGraphConfig['patternSeverityThreshold'];\n } else {\n if (raw.patternSeverityThreshold !== undefined) {\n logWarn('Invalid config field patternSeverityThreshold: expected critical|high|medium|low, applying default (low)');\n }\n patternSeverityThreshold = defaults.patternSeverityThreshold;\n }\n\n // \u2500\u2500 Tool group flags \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const enableCodeHealth = typeof raw.enableCodeHealth === 'boolean'\n ? raw.enableCodeHealth\n : defaults.enableCodeHealth;\n const enableAdvancedAnalysis = typeof raw.enableAdvancedAnalysis === 'boolean'\n ? raw.enableAdvancedAnalysis\n : defaults.enableAdvancedAnalysis;\n const enableAgentUtils = typeof raw.enableAgentUtils === 'boolean'\n ? raw.enableAgentUtils\n : defaults.enableAgentUtils;\n const enableGeneralCompression = typeof raw.enableGeneralCompression === 'boolean'\n ? raw.enableGeneralCompression\n : defaults.enableGeneralCompression;\n\n // Dependency constraint: enableSecurity requires enableArchitecture\n let finalEnableArchitecture = enableArchitecture;\n if (enableSecurity && !enableArchitecture) {\n logWarn('enableSecurity requires enableArchitecture \\u2014 auto-enabling architecture analysis');\n finalEnableArchitecture = true;\n }\n\n // \u2500\u2500 Context budget config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let contextBudget: KiroGraphConfig['contextBudget'] | undefined;\n if (raw.contextBudget && typeof raw.contextBudget === 'object' && !Array.isArray(raw.contextBudget)) {\n const cb = raw.contextBudget as Record<string, unknown>;\n contextBudget = {\n maxTokensPerSession: typeof cb.maxTokensPerSession === 'number' && cb.maxTokensPerSession > 0\n ? Math.round(cb.maxTokensPerSession) : 100_000,\n warnAt: typeof cb.warnAt === 'number' && cb.warnAt > 0\n ? Math.round(cb.warnAt) : 80_000,\n throttleAt: typeof cb.throttleAt === 'number' && cb.throttleAt > 0\n ? Math.round(cb.throttleAt) : 95_000,\n };\n }\n\n // Validate glob patterns \u2014 exclude unsafe regex patterns\n const include = _validatePatterns(raw.include, defaults.include);\n const exclude = _validatePatterns(raw.exclude, defaults.exclude);\n\n return {\n version,\n languages,\n include,\n exclude,\n maxFileSize,\n extractDocstrings,\n trackCallSites,\n enableEmbeddings,\n embeddingModel,\n embeddingDim,\n useVecIndex,\n semanticEngine,\n turboquantMemDocs,\n turboquantBits,\n turbovecMemDocs,\n turbovecBits,\n typesenseDashboard,\n qdrantDashboard,\n minLogLevel,\n frameworkHints,\n fuzzyResolutionThreshold,\n enableArchitecture: finalEnableArchitecture,\n cavemanMode,\n shellCompressionLevel,\n syncWarningThreshold,\n enableMemory,\n memorySearchAlpha,\n memoryKeepRaw,\n memoryMaxObservations,\n memorySessionTimeout,\n memoryContextLimit,\n memoryContextThreshold,\n memoryExcludePatterns,\n enableWatchmen: enableWatchmen && enableMemory,\n watchmenThreshold,\n watchmenSynthesisMode,\n watchmenLocalModel,\n enableWiki,\n wikiSynthesisMode,\n wikiLocalModel,\n wikiSources,\n wikiAutoResolveConflicts,\n wikiLintFrequency,\n wikiContextLimit,\n wikiContextThreshold,\n enableDocs,\n docsInclude,\n docsExclude,\n docsLinkCode,\n docsContextLimit,\n docsContextThreshold,\n docsMaxFileSize,\n docsSummarization,\n enableData,\n dataInclude,\n dataExclude,\n dataLinkCode,\n dataContextLimit,\n dataMaxFileSize,\n dataMaxRows,\n dataQueryLimit,\n dataMaxResponseTokens,\n enableSecurity,\n securityDatabases,\n securityAutoEnrich,\n securityEnrichMaxAgeDays,\n securityLicensePolicy,\n enablePatterns,\n patternLibraryPath,\n patternSeverityThreshold,\n enableCodeHealth,\n enableAdvancedAnalysis,\n enableAgentUtils,\n enableGeneralCompression,\n enableShellExec: shellCompressionLevel !== 'off',\n ...(architectureLayers !== undefined ? { architectureLayers } : {}),\n ...(contextBudget !== undefined ? { contextBudget } : {}),\n };\n}\n\nfunction _validateArchitectureLayers(raw: unknown): Record<string, string[]> | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (typeof raw !== 'object' || Array.isArray(raw)) return undefined;\n const result: Record<string, string[]> = {};\n for (const [key, val] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof key !== 'string') continue;\n if (!Array.isArray(val)) continue;\n const patterns = val.filter((p): p is string => typeof p === 'string' && isSafeRegex(p));\n if (patterns.length > 0) result[key] = patterns;\n }\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction _validatePatterns(raw: unknown, fallback: string[]): string[] {\n if (!Array.isArray(raw)) return fallback;\n const valid: string[] = [];\n for (const p of raw) {\n if (typeof p !== 'string') continue;\n if (!isSafeRegex(p)) {\n logWarn(`Unsafe regex pattern skipped: ${p}`);\n continue;\n }\n valid.push(p);\n }\n return valid;\n}\n\n// \u2500\u2500 Migration 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\n\n/**\n * Upgrades shallow exclude patterns (e.g. \"node_modules/**\") to recursive ones\n * (e.g. \"** /node_modules/**\") so nested directories are excluded at any depth.\n */\nconst SHALLOW_TO_RECURSIVE: Record<string, string> = {\n 'node_modules/**': '**/node_modules/**',\n 'dist/**': '**/dist/**',\n 'build/**': '**/build/**',\n '.git/**': '**/.git/**',\n '.kirograph/**': '**/.kirograph/**',\n};\n\nfunction migrateExcludePatterns(patterns: string[]): string[] {\n return patterns.map(p => SHALLOW_TO_RECURSIVE[p] ?? p);\n}\n\n// \u2500\u2500 Load / Save \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport async function loadConfig(projectRoot: string): Promise<KiroGraphConfig> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n\n if (!fs.existsSync(cfgPath)) {\n // Create default config file\n const defaults = createDefaultConfig(projectRoot);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, defaults);\n return defaults;\n }\n\n let raw: unknown;\n try {\n const text = await fs.promises.readFile(cfgPath, 'utf8');\n raw = JSON.parse(text);\n } catch (err) {\n logError('Config parse error', { path: cfgPath, error: err instanceof Error ? err.message : String(err) });\n return createDefaultConfig(projectRoot);\n }\n\n const config = validateConfig(raw);\n\n // Migrate v1 \u2192 v2: upgrade shallow exclude patterns to recursive\n if (config.version < 2) {\n config.version = 2;\n config.exclude = migrateExcludePatterns(config.exclude);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n }\n\n return config;\n}\n\nexport async function saveConfig(projectRoot: string, config: KiroGraphConfig): Promise<void> {\n const dir = path.join(projectRoot, KIROGRAPH_DIR);\n const cfgPath = path.join(dir, CONFIG_FILE);\n await fs.promises.mkdir(dir, { recursive: true });\n await _writeAtomic(cfgPath, config);\n}\n\nasync function _writeAtomic(cfgPath: string, config: KiroGraphConfig): Promise<void> {\n const tmp = cfgPath + '.tmp';\n await fs.promises.writeFile(tmp, JSON.stringify(config, null, 2), 'utf8');\n await fs.promises.rename(tmp, cfgPath);\n}\n\n// \u2500\u2500 Update 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\n\nexport async function updateConfig(\n projectRoot: string,\n patch: Partial<KiroGraphConfig>\n): Promise<KiroGraphConfig> {\n const current = await loadConfig(projectRoot);\n const updated = validateConfig({ ...current, ...patch });\n await saveConfig(projectRoot, updated);\n return updated;\n}\n\nexport async function addIncludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.include);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, include: [...config.include, ...toAdd] });\n}\n\nexport async function addExcludePatterns(projectRoot: string, patterns: string[]): Promise<void> {\n const config = await loadConfig(projectRoot);\n const existing = new Set(config.exclude);\n const toAdd = patterns.filter(p => isSafeRegex(p) && !existing.has(p));\n if (toAdd.length === 0) return;\n await saveConfig(projectRoot, { ...config, exclude: [...config.exclude, ...toAdd] });\n}\n\n// \u2500\u2500 File inclusion check \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport function shouldIncludeFile(config: KiroGraphConfig, relPath: string): boolean {\n // Check exclude patterns first\n for (const pattern of config.exclude) {\n if (picomatch(pattern)(relPath)) return false;\n }\n // If include patterns are specified, file must match at least one\n if (config.include.length > 0) {\n return config.include.some(pattern => picomatch(pattern)(relPath));\n }\n return true;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["picomatch"]
7
7
  }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var import_prompt_exports = {};
20
+ __export(import_prompt_exports, {
21
+ applyImportedGlobalHooks: () => applyImportedGlobalHooks,
22
+ promptImportGlobalHookSelection: () => promptImportGlobalHookSelection
23
+ });
24
+ module.exports = __toCommonJS(import_prompt_exports);
25
+ var import_manager = require("./manager");
26
+ var import_prompt = require("./prompt");
27
+ const green = "\x1B[32m";
28
+ const reset = "\x1B[0m";
29
+ async function promptImportGlobalHookSelection() {
30
+ let globalDir;
31
+ try {
32
+ globalDir = (0, import_manager.getGlobalHooksDir)();
33
+ } catch {
34
+ return null;
35
+ }
36
+ const globalHooks = (0, import_manager.listHooks)(globalDir);
37
+ if (globalHooks.length === 0) return null;
38
+ const choice = await (0, import_prompt.singleChoice)("Import global hooks?", [
39
+ { label: "None", value: "none" },
40
+ { label: "All", value: "all" },
41
+ { label: "Select specific hooks", value: "select" }
42
+ ]);
43
+ if (choice === "all") {
44
+ return globalHooks.map((h) => h.filename);
45
+ }
46
+ if (choice === "select") {
47
+ const options = globalHooks.map((h) => ({
48
+ label: h.displayName,
49
+ value: h.filename,
50
+ description: h.description
51
+ }));
52
+ const selected = await (0, import_prompt.multiSelect)("Select hooks to import:", options);
53
+ return selected.length > 0 ? selected : null;
54
+ }
55
+ return null;
56
+ }
57
+ function applyImportedGlobalHooks(projectRoot, filenames) {
58
+ if (filenames.length === 0) return;
59
+ const globalDir = (0, import_manager.getGlobalHooksDir)();
60
+ const globalHooks = (0, import_manager.listHooks)(globalDir);
61
+ const workspaceHooksDir = (0, import_manager.getWorkspaceHooksDir)(projectRoot);
62
+ (0, import_manager.ensureDir)(workspaceHooksDir);
63
+ const copied = (0, import_manager.copyHooks)(globalDir, workspaceHooksDir, filenames);
64
+ console.log(` ${green}\u2713${reset} Imported ${copied.length} hook${copied.length === 1 ? "" : "s"}:`);
65
+ for (const f of copied) {
66
+ const hook = globalHooks.find((h) => h.filename === f);
67
+ console.log(` ${hook?.displayName ?? f}`);
68
+ }
69
+ }
70
+ // Annotate the CommonJS export names for ESM import in node:
71
+ 0 && (module.exports = {
72
+ applyImportedGlobalHooks,
73
+ promptImportGlobalHookSelection
74
+ });
75
+ //# sourceMappingURL=import-prompt.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/hooks/import-prompt.ts"],
4
+ "sourcesContent": ["import {\n getGlobalHooksDir,\n listHooks,\n copyHooks,\n getWorkspaceHooksDir,\n ensureDir,\n} from './manager';\nimport { singleChoice, multiSelect } from './prompt';\n\nconst green = '\\x1b[32m';\nconst reset = '\\x1b[0m';\n\n/**\n * Ask which global hooks to import. Returns filenames to copy, or null to skip.\n */\nexport async function promptImportGlobalHookSelection(): Promise<string[] | null> {\n let globalDir: string;\n try {\n globalDir = getGlobalHooksDir();\n } catch {\n return null;\n }\n\n const globalHooks = listHooks(globalDir);\n if (globalHooks.length === 0) return null;\n\n const choice = await singleChoice('Import global hooks?', [\n { label: 'None', value: 'none' },\n { label: 'All', value: 'all' },\n { label: 'Select specific hooks', value: 'select' },\n ]);\n\n if (choice === 'all') {\n return globalHooks.map((h) => h.filename);\n }\n\n if (choice === 'select') {\n const options = globalHooks.map((h) => ({\n label: h.displayName,\n value: h.filename,\n description: h.description,\n }));\n const selected = await multiSelect('Select hooks to import:', options);\n return selected.length > 0 ? selected : null;\n }\n\n return null;\n}\n\n/** Copy selected global hooks into the workspace and print a summary. */\nexport function applyImportedGlobalHooks(\n projectRoot: string,\n filenames: string[]\n): void {\n if (filenames.length === 0) return;\n\n const globalDir = getGlobalHooksDir();\n const globalHooks = listHooks(globalDir);\n const workspaceHooksDir = getWorkspaceHooksDir(projectRoot);\n ensureDir(workspaceHooksDir);\n const copied = copyHooks(globalDir, workspaceHooksDir, filenames);\n console.log(` ${green}\u2713${reset} Imported ${copied.length} hook${copied.length === 1 ? '' : 's'}:`);\n for (const f of copied) {\n const hook = globalHooks.find((h) => h.filename === f);\n console.log(` ${hook?.displayName ?? f}`);\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMO;AACP,oBAA0C;AAE1C,MAAM,QAAQ;AACd,MAAM,QAAQ;AAKd,eAAsB,kCAA4D;AAChF,MAAI;AACJ,MAAI;AACF,oBAAY,kCAAkB;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,kBAAc,0BAAU,SAAS;AACvC,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,QAAM,SAAS,UAAM,4BAAa,wBAAwB;AAAA,IACxD,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,IAC/B,EAAE,OAAO,OAAO,OAAO,MAAM;AAAA,IAC7B,EAAE,OAAO,yBAAyB,OAAO,SAAS;AAAA,EACpD,CAAC;AAED,MAAI,WAAW,OAAO;AACpB,WAAO,YAAY,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,EAC1C;AAEA,MAAI,WAAW,UAAU;AACvB,UAAM,UAAU,YAAY,IAAI,CAAC,OAAO;AAAA,MACtC,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,aAAa,EAAE;AAAA,IACjB,EAAE;AACF,UAAM,WAAW,UAAM,2BAAY,2BAA2B,OAAO;AACrE,WAAO,SAAS,SAAS,IAAI,WAAW;AAAA,EAC1C;AAEA,SAAO;AACT;AAGO,SAAS,yBACd,aACA,WACM;AACN,MAAI,UAAU,WAAW,EAAG;AAE5B,QAAM,gBAAY,kCAAkB;AACpC,QAAM,kBAAc,0BAAU,SAAS;AACvC,QAAM,wBAAoB,qCAAqB,WAAW;AAC1D,gCAAU,iBAAiB;AAC3B,QAAM,aAAS,0BAAU,WAAW,mBAAmB,SAAS;AAChE,UAAQ,IAAI,KAAK,KAAK,SAAI,KAAK,aAAa,OAAO,MAAM,QAAQ,OAAO,WAAW,IAAI,KAAK,GAAG,GAAG;AAClG,aAAW,KAAK,QAAQ;AACtB,UAAM,OAAO,YAAY,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC;AACrD,YAAQ,IAAI,OAAO,MAAM,eAAe,CAAC,EAAE;AAAA,EAC7C;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var manager_exports = {};
30
+ __export(manager_exports, {
31
+ copyHooks: () => copyHooks,
32
+ ensureDir: () => ensureDir,
33
+ getGlobalHooksDir: () => getGlobalHooksDir,
34
+ getGlobalKirographDir: () => getGlobalKirographDir,
35
+ getWorkspaceHooksDir: () => getWorkspaceHooksDir,
36
+ listHooks: () => listHooks,
37
+ parseHookMetadata: () => parseHookMetadata,
38
+ parseHookName: () => parseHookName,
39
+ removeHooks: () => removeHooks
40
+ });
41
+ module.exports = __toCommonJS(manager_exports);
42
+ var fs = __toESM(require("fs"));
43
+ var path = __toESM(require("path"));
44
+ function getGlobalKirographDir() {
45
+ const home = process.env.HOME || process.env.USERPROFILE;
46
+ if (!home) {
47
+ throw new Error("Cannot determine home directory");
48
+ }
49
+ return path.join(home, ".kirograph");
50
+ }
51
+ function getGlobalHooksDir() {
52
+ return path.join(getGlobalKirographDir(), "hooks");
53
+ }
54
+ function getWorkspaceHooksDir(projectRoot) {
55
+ return path.join(projectRoot, ".kiro", "hooks");
56
+ }
57
+ function ensureDir(dirPath) {
58
+ fs.mkdirSync(dirPath, { recursive: true });
59
+ }
60
+ function listHooks(dirPath) {
61
+ let entries;
62
+ try {
63
+ entries = fs.readdirSync(dirPath);
64
+ } catch (err) {
65
+ if (err.code === "ENOENT") {
66
+ return [];
67
+ }
68
+ throw err;
69
+ }
70
+ return entries.filter((name) => name.endsWith(".kiro.hook") || name.endsWith(".json")).map((filename) => {
71
+ const fullPath = path.join(dirPath, filename);
72
+ const { displayName, description } = parseHookMetadata(fullPath);
73
+ return { filename, displayName, description, fullPath };
74
+ });
75
+ }
76
+ function copyHooks(sourceDir, destDir, filenames) {
77
+ const copied = [];
78
+ for (const filename of filenames) {
79
+ const src = path.join(sourceDir, filename);
80
+ const dest = path.join(destDir, filename);
81
+ const content = fs.readFileSync(src);
82
+ fs.writeFileSync(dest, content);
83
+ copied.push(filename);
84
+ }
85
+ return copied;
86
+ }
87
+ function removeHooks(dirPath, filenames) {
88
+ const removed = [];
89
+ for (const filename of filenames) {
90
+ fs.unlinkSync(path.join(dirPath, filename));
91
+ removed.push(filename);
92
+ }
93
+ return removed;
94
+ }
95
+ function parseHookMetadata(filePath) {
96
+ const fallback = path.basename(filePath);
97
+ try {
98
+ const content = fs.readFileSync(filePath, "utf-8");
99
+ const json = JSON.parse(content);
100
+ const isV2 = Array.isArray(json.hooks) && json.hooks.length > 0;
101
+ const rawName = isV2 ? json.hooks[0].name : json.name;
102
+ const displayName = typeof rawName === "string" && rawName.length > 0 ? rawName : fallback;
103
+ const description = !isV2 && typeof json.description === "string" && json.description.length > 0 ? json.description : void 0;
104
+ return { displayName, description };
105
+ } catch {
106
+ return { displayName: fallback };
107
+ }
108
+ }
109
+ function parseHookName(filePath) {
110
+ return parseHookMetadata(filePath).displayName;
111
+ }
112
+ // Annotate the CommonJS export names for ESM import in node:
113
+ 0 && (module.exports = {
114
+ copyHooks,
115
+ ensureDir,
116
+ getGlobalHooksDir,
117
+ getGlobalKirographDir,
118
+ getWorkspaceHooksDir,
119
+ listHooks,
120
+ parseHookMetadata,
121
+ parseHookName,
122
+ removeHooks
123
+ });
124
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/hooks/manager.ts"],
4
+ "sourcesContent": ["import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Information about a hook file found in a directory.\n */\nexport interface HookFileInfo {\n /** Filename (e.g. \"my-lint-hook.kiro.hook\") */\n filename: string;\n /** Display name parsed from hook JSON `name` field, or filename if unparseable */\n displayName: string;\n /** Description parsed from hook JSON `description` field, if present */\n description?: string;\n /** Full absolute path to the file */\n fullPath: string;\n}\n\n/**\n * Resolve the global KiroGraph directory path (~/.kirograph/).\n * Throws if home directory cannot be determined.\n */\nexport function getGlobalKirographDir(): string {\n const home = process.env.HOME || process.env.USERPROFILE;\n if (!home) {\n throw new Error('Cannot determine home directory');\n }\n return path.join(home, '.kirograph');\n}\n\n/**\n * Resolve the global hooks directory path (~/.kirograph/hooks/).\n * Throws if home directory cannot be determined.\n */\nexport function getGlobalHooksDir(): string {\n return path.join(getGlobalKirographDir(), 'hooks');\n}\n\n/**\n * Resolve the workspace hooks directory path (.kiro/hooks/ relative to project root).\n */\nexport function getWorkspaceHooksDir(projectRoot: string): string {\n return path.join(projectRoot, '.kiro', 'hooks');\n}\n\n/**\n * Ensure the target directory exists, creating it recursively.\n * Throws on permission or filesystem errors.\n */\nexport function ensureDir(dirPath: string): void {\n fs.mkdirSync(dirPath, { recursive: true });\n}\n\n/**\n * List all .kiro.hook files in a directory.\n * Returns empty array if directory does not exist.\n */\nexport function listHooks(dirPath: string): HookFileInfo[] {\n let entries: string[];\n try {\n entries = fs.readdirSync(dirPath);\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return [];\n }\n throw err;\n }\n\n return entries\n .filter((name) => name.endsWith('.kiro.hook') || name.endsWith('.json'))\n .map((filename) => {\n const fullPath = path.join(dirPath, filename);\n const { displayName, description } = parseHookMetadata(fullPath);\n return { filename, displayName, description, fullPath };\n });\n}\n\n/**\n * Copy hook files from source dir to destination dir.\n * Always overwrites existing files with the same filename.\n * Uses fail-fast semantics: throws immediately on first copy error.\n * Returns the list of copied filenames.\n */\nexport function copyHooks(\n sourceDir: string,\n destDir: string,\n filenames: string[]\n): string[] {\n const copied: string[] = [];\n for (const filename of filenames) {\n const src = path.join(sourceDir, filename);\n const dest = path.join(destDir, filename);\n const content = fs.readFileSync(src);\n fs.writeFileSync(dest, content);\n copied.push(filename);\n }\n return copied;\n}\n\n/**\n * Remove hook files from a directory.\n * Uses fail-fast semantics: throws immediately on first removal error.\n * Returns the list of removed filenames.\n */\nexport function removeHooks(dirPath: string, filenames: string[]): string[] {\n const removed: string[] = [];\n for (const filename of filenames) {\n fs.unlinkSync(path.join(dirPath, filename));\n removed.push(filename);\n }\n return removed;\n}\n\n/**\n * Parse a hook file's JSON metadata (`name`, `description`).\n * Falls back to the filename when `name` is absent or unparseable.\n */\nexport function parseHookMetadata(filePath: string): {\n displayName: string;\n description?: string;\n} {\n const fallback = path.basename(filePath);\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const json = JSON.parse(content);\n // v2 format: { version: 'v1', hooks: [{ name, ... }] }\n // v1 format: { name, description, ... }\n const isV2 = Array.isArray(json.hooks) && json.hooks.length > 0;\n const rawName = isV2 ? json.hooks[0].name : json.name;\n const displayName =\n typeof rawName === 'string' && rawName.length > 0 ? rawName : fallback;\n const description =\n !isV2 && typeof json.description === 'string' && json.description.length > 0\n ? json.description\n : undefined;\n return { displayName, description };\n } catch {\n return { displayName: fallback };\n }\n}\n\n/**\n * Parse a hook file's JSON to extract the `name` field.\n * Returns the basename of the file path if parsing fails or `name` is absent/empty.\n */\nexport function parseHookName(filePath: string): string {\n return parseHookMetadata(filePath).displayName;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AAoBf,SAAS,wBAAgC;AAC9C,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI;AAC7C,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AACA,SAAO,KAAK,KAAK,MAAM,YAAY;AACrC;AAMO,SAAS,oBAA4B;AAC1C,SAAO,KAAK,KAAK,sBAAsB,GAAG,OAAO;AACnD;AAKO,SAAS,qBAAqB,aAA6B;AAChE,SAAO,KAAK,KAAK,aAAa,SAAS,OAAO;AAChD;AAMO,SAAS,UAAU,SAAuB;AAC/C,KAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAC3C;AAMO,SAAS,UAAU,SAAiC;AACzD,MAAI;AACJ,MAAI;AACF,cAAU,GAAG,YAAY,OAAO;AAAA,EAClC,SAAS,KAAc;AACrB,QAAK,IAA8B,SAAS,UAAU;AACpD,aAAO,CAAC;AAAA,IACV;AACA,UAAM;AAAA,EACR;AAEA,SAAO,QACJ,OAAO,CAAC,SAAS,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,OAAO,CAAC,EACtE,IAAI,CAAC,aAAa;AACjB,UAAM,WAAW,KAAK,KAAK,SAAS,QAAQ;AAC5C,UAAM,EAAE,aAAa,YAAY,IAAI,kBAAkB,QAAQ;AAC/D,WAAO,EAAE,UAAU,aAAa,aAAa,SAAS;AAAA,EACxD,CAAC;AACL;AAQO,SAAS,UACd,WACA,SACA,WACU;AACV,QAAM,SAAmB,CAAC;AAC1B,aAAW,YAAY,WAAW;AAChC,UAAM,MAAM,KAAK,KAAK,WAAW,QAAQ;AACzC,UAAM,OAAO,KAAK,KAAK,SAAS,QAAQ;AACxC,UAAM,UAAU,GAAG,aAAa,GAAG;AACnC,OAAG,cAAc,MAAM,OAAO;AAC9B,WAAO,KAAK,QAAQ;AAAA,EACtB;AACA,SAAO;AACT;AAOO,SAAS,YAAY,SAAiB,WAA+B;AAC1E,QAAM,UAAoB,CAAC;AAC3B,aAAW,YAAY,WAAW;AAChC,OAAG,WAAW,KAAK,KAAK,SAAS,QAAQ,CAAC;AAC1C,YAAQ,KAAK,QAAQ;AAAA,EACvB;AACA,SAAO;AACT;AAMO,SAAS,kBAAkB,UAGhC;AACA,QAAM,WAAW,KAAK,SAAS,QAAQ;AACvC,MAAI;AACF,UAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AACjD,UAAM,OAAO,KAAK,MAAM,OAAO;AAG/B,UAAM,OAAO,MAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,MAAM,SAAS;AAC9D,UAAM,UAAU,OAAO,KAAK,MAAM,CAAC,EAAE,OAAO,KAAK;AACjD,UAAM,cACJ,OAAO,YAAY,YAAY,QAAQ,SAAS,IAAI,UAAU;AAChE,UAAM,cACJ,CAAC,QAAQ,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,SAAS,IACvE,KAAK,cACL;AACN,WAAO,EAAE,aAAa,YAAY;AAAA,EACpC,QAAQ;AACN,WAAO,EAAE,aAAa,SAAS;AAAA,EACjC;AACF;AAMO,SAAS,cAAc,UAA0B;AACtD,SAAO,kBAAkB,QAAQ,EAAE;AACrC;",
6
+ "names": []
7
+ }