@triedotdev/mcp 1.0.168 → 1.0.170

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 (149) hide show
  1. package/README.md +54 -500
  2. package/dist/chunk-2YXOBNKW.js +619 -0
  3. package/dist/chunk-2YXOBNKW.js.map +1 -0
  4. package/dist/chunk-QR64Y5TI.js +363 -0
  5. package/dist/chunk-QR64Y5TI.js.map +1 -0
  6. package/dist/cli/main.d.ts +0 -15
  7. package/dist/cli/main.js +356 -3100
  8. package/dist/cli/main.js.map +1 -1
  9. package/dist/index.js +2 -36
  10. package/dist/index.js.map +1 -1
  11. package/dist/server/mcp-server.js +2 -36
  12. package/package.json +8 -31
  13. package/dist/autonomy-config-FSERX3O3.js +0 -30
  14. package/dist/autonomy-config-FSERX3O3.js.map +0 -1
  15. package/dist/chat-store-JNGNTDSN.js +0 -15
  16. package/dist/chat-store-JNGNTDSN.js.map +0 -1
  17. package/dist/chunk-2HF65EHQ.js +0 -311
  18. package/dist/chunk-2HF65EHQ.js.map +0 -1
  19. package/dist/chunk-43X6JBEM.js +0 -36
  20. package/dist/chunk-43X6JBEM.js.map +0 -1
  21. package/dist/chunk-4MXH2ZPT.js +0 -1827
  22. package/dist/chunk-4MXH2ZPT.js.map +0 -1
  23. package/dist/chunk-575YT2SD.js +0 -737
  24. package/dist/chunk-575YT2SD.js.map +0 -1
  25. package/dist/chunk-5BRRRTN6.js +0 -354
  26. package/dist/chunk-5BRRRTN6.js.map +0 -1
  27. package/dist/chunk-6NLHFIYA.js +0 -344
  28. package/dist/chunk-6NLHFIYA.js.map +0 -1
  29. package/dist/chunk-7WITSO22.js +0 -824
  30. package/dist/chunk-7WITSO22.js.map +0 -1
  31. package/dist/chunk-DGUM43GV.js +0 -11
  32. package/dist/chunk-DGUM43GV.js.map +0 -1
  33. package/dist/chunk-EFWVF6TI.js +0 -267
  34. package/dist/chunk-EFWVF6TI.js.map +0 -1
  35. package/dist/chunk-F6WFNUAY.js +0 -216
  36. package/dist/chunk-F6WFNUAY.js.map +0 -1
  37. package/dist/chunk-FQ45QP5A.js +0 -361
  38. package/dist/chunk-FQ45QP5A.js.map +0 -1
  39. package/dist/chunk-G2TGF6TR.js +0 -573
  40. package/dist/chunk-G2TGF6TR.js.map +0 -1
  41. package/dist/chunk-GTKYBOXL.js +0 -700
  42. package/dist/chunk-GTKYBOXL.js.map +0 -1
  43. package/dist/chunk-HVCDY3AK.js +0 -850
  44. package/dist/chunk-HVCDY3AK.js.map +0 -1
  45. package/dist/chunk-JVMBCWKS.js +0 -348
  46. package/dist/chunk-JVMBCWKS.js.map +0 -1
  47. package/dist/chunk-KDHN2ZQE.js +0 -313
  48. package/dist/chunk-KDHN2ZQE.js.map +0 -1
  49. package/dist/chunk-LQIMKE3P.js +0 -12524
  50. package/dist/chunk-LQIMKE3P.js.map +0 -1
  51. package/dist/chunk-ME2OERF5.js +0 -345
  52. package/dist/chunk-ME2OERF5.js.map +0 -1
  53. package/dist/chunk-MRHKX5M5.js +0 -662
  54. package/dist/chunk-MRHKX5M5.js.map +0 -1
  55. package/dist/chunk-OBQ74FOU.js +0 -27
  56. package/dist/chunk-OBQ74FOU.js.map +0 -1
  57. package/dist/chunk-OMR4YCBS.js +0 -987
  58. package/dist/chunk-OMR4YCBS.js.map +0 -1
  59. package/dist/chunk-Q5EKA5YA.js +0 -254
  60. package/dist/chunk-Q5EKA5YA.js.map +0 -1
  61. package/dist/chunk-Q63FFI6D.js +0 -132
  62. package/dist/chunk-Q63FFI6D.js.map +0 -1
  63. package/dist/chunk-SY6KQG44.js +0 -983
  64. package/dist/chunk-SY6KQG44.js.map +0 -1
  65. package/dist/chunk-T63OHG4Q.js +0 -440
  66. package/dist/chunk-T63OHG4Q.js.map +0 -1
  67. package/dist/chunk-TN5WEKWI.js +0 -173
  68. package/dist/chunk-TN5WEKWI.js.map +0 -1
  69. package/dist/chunk-VUL52BQL.js +0 -402
  70. package/dist/chunk-VUL52BQL.js.map +0 -1
  71. package/dist/chunk-VVITXIHN.js +0 -189
  72. package/dist/chunk-VVITXIHN.js.map +0 -1
  73. package/dist/chunk-WCN7S3EI.js +0 -14
  74. package/dist/chunk-WCN7S3EI.js.map +0 -1
  75. package/dist/chunk-XE6KQRKZ.js +0 -816
  76. package/dist/chunk-XE6KQRKZ.js.map +0 -1
  77. package/dist/chunk-XPZZFPBZ.js +0 -491
  78. package/dist/chunk-XPZZFPBZ.js.map +0 -1
  79. package/dist/chunk-XTFWT2XM.js +0 -727
  80. package/dist/chunk-XTFWT2XM.js.map +0 -1
  81. package/dist/chunk-YDHUCDHM.js +0 -4011
  82. package/dist/chunk-YDHUCDHM.js.map +0 -1
  83. package/dist/chunk-YZ6Y2H3P.js +0 -1289
  84. package/dist/chunk-YZ6Y2H3P.js.map +0 -1
  85. package/dist/chunk-ZJF5FTBX.js +0 -1396
  86. package/dist/chunk-ZJF5FTBX.js.map +0 -1
  87. package/dist/chunk-ZV2K6M7T.js +0 -74
  88. package/dist/chunk-ZV2K6M7T.js.map +0 -1
  89. package/dist/cli/create-agent.d.ts +0 -1
  90. package/dist/cli/create-agent.js +0 -1050
  91. package/dist/cli/create-agent.js.map +0 -1
  92. package/dist/cli/yolo-daemon.d.ts +0 -1
  93. package/dist/cli/yolo-daemon.js +0 -423
  94. package/dist/cli/yolo-daemon.js.map +0 -1
  95. package/dist/client-NJPZE5JT.js +0 -28
  96. package/dist/client-NJPZE5JT.js.map +0 -1
  97. package/dist/codebase-index-VAPF32XX.js +0 -12
  98. package/dist/codebase-index-VAPF32XX.js.map +0 -1
  99. package/dist/fast-analyzer-XXYMOXRK.js +0 -216
  100. package/dist/fast-analyzer-XXYMOXRK.js.map +0 -1
  101. package/dist/git-EO5SRFMN.js +0 -28
  102. package/dist/git-EO5SRFMN.js.map +0 -1
  103. package/dist/github-ingester-ZOKK6GRS.js +0 -11
  104. package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
  105. package/dist/goal-manager-YOB7VWK7.js +0 -25
  106. package/dist/goal-manager-YOB7VWK7.js.map +0 -1
  107. package/dist/goal-validator-ULKIBDPX.js +0 -24
  108. package/dist/goal-validator-ULKIBDPX.js.map +0 -1
  109. package/dist/graph-B3NA4S7I.js +0 -10
  110. package/dist/graph-B3NA4S7I.js.map +0 -1
  111. package/dist/hypothesis-7BFFT5JY.js +0 -23
  112. package/dist/hypothesis-7BFFT5JY.js.map +0 -1
  113. package/dist/incident-index-EFNUSGWL.js +0 -11
  114. package/dist/incident-index-EFNUSGWL.js.map +0 -1
  115. package/dist/insight-store-EC4PLSAW.js +0 -22
  116. package/dist/insight-store-EC4PLSAW.js.map +0 -1
  117. package/dist/issue-store-ZIRP23EP.js +0 -36
  118. package/dist/issue-store-ZIRP23EP.js.map +0 -1
  119. package/dist/ledger-TWZTGDFA.js +0 -58
  120. package/dist/ledger-TWZTGDFA.js.map +0 -1
  121. package/dist/linear-ingester-XXPAZZRW.js +0 -11
  122. package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
  123. package/dist/output-manager-RVJ37XKA.js +0 -13
  124. package/dist/output-manager-RVJ37XKA.js.map +0 -1
  125. package/dist/parse-goal-violation-SACGFG3C.js +0 -8
  126. package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
  127. package/dist/pattern-discovery-F7LU5K6E.js +0 -8
  128. package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
  129. package/dist/progress-SRQ2V3BP.js +0 -18
  130. package/dist/progress-SRQ2V3BP.js.map +0 -1
  131. package/dist/project-state-AHPA77SM.js +0 -28
  132. package/dist/project-state-AHPA77SM.js.map +0 -1
  133. package/dist/sync-M2FSWPBC.js +0 -12
  134. package/dist/sync-M2FSWPBC.js.map +0 -1
  135. package/dist/terminal-spawn-5YXDMUCF.js +0 -157
  136. package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
  137. package/dist/tiered-storage-Z3YCR465.js +0 -12
  138. package/dist/tiered-storage-Z3YCR465.js.map +0 -1
  139. package/dist/trie-agent-3YDPEGHJ.js +0 -28
  140. package/dist/trie-agent-3YDPEGHJ.js.map +0 -1
  141. package/dist/ui/chat.html +0 -1014
  142. package/dist/ui/goals.html +0 -967
  143. package/dist/ui/hypotheses.html +0 -1011
  144. package/dist/ui/ledger.html +0 -954
  145. package/dist/ui/nudges.html +0 -995
  146. package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
  147. package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
  148. package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
  149. package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/trie/vulnerability-signatures.ts"],"sourcesContent":["/**\n * Vulnerability Signature Database\n * \n * Pre-indexed security patterns using Aho-Corasick for O(n + z) scanning\n * where n = file size, z = number of matches.\n * \n * This is MUCH faster than running 100+ regex patterns on every file.\n * \n * IMPROVEMENTS (v2):\n * - Context-aware pattern matching to reduce false positives\n * - File path exclusions for test/lock files\n * - SQL injection detection only in SQL contexts\n * - Better secret detection avoiding package names/URLs\n */\n\nimport { AhoCorasick, PatternMetadata } from './trie.js';\nimport { isInteractiveMode } from '../utils/progress.js';\n\nexport interface VulnerabilityMatch {\n pattern: string;\n line: number;\n column: number;\n severity: 'critical' | 'serious' | 'moderate' | 'low';\n category: string;\n description: string;\n cwe?: string;\n fix: string;\n}\n\n/**\n * Files/patterns to ALWAYS exclude from scanning (never any false positives from these)\n */\nconst ALWAYS_EXCLUDED_FILES = [\n /vulnerability-signatures\\.[jt]s$/, // CRITICAL: Never scan ourselves!\n /vibe-code-signatures\\.[jt]s$/, // Never scan signature files\n /legal\\.[jt]s$/, // Legal skill contains detection patterns\n /security-scanner\\.[jt]s$/, // Security scanner contains patterns\n /agent-smith\\.[jt]s$/, // Agent Smith contains patterns\n /security\\.[jt]s$/, // Security skill\n /privacy\\.[jt]s$/, // Privacy skill\n /soc2\\.[jt]s$/, // SOC2 skill\n /skills[\\/\\\\]built-in[\\/\\\\]/, // Never scan Trie's own skill implementations\n /skills[\\/\\\\].*\\.[jt]s$/, // Never scan any skills directory\n /trie-agents?[\\/\\\\]src[\\/\\\\]/, // Never scan Trie's source when installed as dependency\n /trie-agents?[\\/\\\\]dist[\\/\\\\]/, // Never scan Trie's dist when installed\n /package-lock\\.json$/, // Lock files\n /yarn\\.lock$/,\n /pnpm-lock\\.yaml$/,\n /node_modules[\\/\\\\]/, // Dependencies\n /\\.d\\.ts$/, // Type definitions\n /\\.min\\.[jt]s$/, // Minified files\n /dist[\\/\\\\]/, // Build output\n /build[\\/\\\\]/,\n];\n\n/**\n * Files to exclude from non-critical checks (test files, examples, etc.)\n */\nconst EXCLUDED_FILE_PATTERNS = [\n /\\.test\\.[jt]sx?$/, // Test files\n /\\.spec\\.[jt]sx?$/, // Spec files\n /__tests__\\//, // Test directories\n /\\/test\\//, // test/ directory\n /\\/tests\\//, // tests/ directory\n /\\.stories\\.[jt]sx?$/, // Storybook files\n /\\.config\\.[jt]s$/, // Config files\n /example/i, // Example files\n /demo/i, // Demo files\n /fixture/i, // Test fixtures\n /mock/i, // Mock files\n];\n\n/**\n * Check if a file should be completely excluded from scanning\n */\nexport function shouldAlwaysExcludeFile(filePath: string): boolean {\n // Normalize path to use forward slashes for consistent matching\n const normalizedPath = filePath.replace(/\\\\/g, '/');\n \n // Check against exclusion patterns\n if (ALWAYS_EXCLUDED_FILES.some(pattern => pattern.test(normalizedPath))) {\n return true;\n }\n \n // Also exclude files in Trie's source directories (handles both installed and development)\n if (normalizedPath.includes('trie') && normalizedPath.includes('/src/')) {\n return true;\n }\n \n // Exclude specific Trie scanner/skill files by filename (regardless of path)\n const fileName = normalizedPath.split('/').pop() || '';\n const TRIE_SCANNER_FILES = [\n 'vulnerability-signatures.ts', 'vulnerability-signatures.js',\n 'vibe-code-signatures.ts', 'vibe-code-signatures.js',\n 'legal.ts', 'legal.js',\n 'security-scanner.ts', 'security-scanner.js',\n 'agent-smith.ts', 'agent-smith.js',\n 'security.ts', 'security.js',\n 'privacy.ts', 'privacy.js',\n 'soc2.ts', 'soc2.js',\n ];\n if (TRIE_SCANNER_FILES.includes(fileName)) {\n // Only exclude if it looks like it's in a skills/trie directory\n if (normalizedPath.includes('/skills/') || normalizedPath.includes('/trie/')) {\n return true;\n }\n }\n \n return false;\n}\n\n/**\n * Check if a file should be excluded from certain checks\n */\nexport function shouldExcludeFile(filePath: string, patternCategory: string): boolean {\n // CRITICAL: Always exclude signature files - never flag ourselves!\n if (shouldAlwaysExcludeFile(filePath)) {\n return true;\n }\n \n // For secrets in test files, we need extra context checking (done elsewhere)\n // Don't auto-exclude test files for secrets here, let isFalsePositive handle it\n if (patternCategory === 'secrets' || patternCategory === 'exposed-secrets') {\n return false;\n }\n \n // Exclude certain file types from non-critical checks\n return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));\n}\n\n/**\n * SQL-related keywords that indicate a SQL context\n */\nconst SQL_CONTEXT_KEYWORDS = [\n 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'FROM', 'WHERE', 'JOIN',\n 'query', 'execute', 'sql', 'prisma', 'knex', 'sequelize',\n 'createQueryBuilder', 'rawQuery', '.raw('\n];\n\n/**\n * Check if a line is in a SQL context\n */\nfunction isInSQLContext(line: string, surroundingLines: string[]): boolean {\n const allContent = [line, ...surroundingLines].join(' ').toLowerCase();\n return SQL_CONTEXT_KEYWORDS.some(keyword => \n allContent.includes(keyword.toLowerCase())\n );\n}\n\n/**\n * Security vulnerability patterns organized by category\n */\nconst VULNERABILITY_PATTERNS: Array<{\n pattern: string;\n metadata: PatternMetadata;\n}> = [\n // ============================================\n // CRITICAL: Injection vulnerabilities\n // ============================================\n {\n pattern: 'eval(',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'injection',\n description: 'eval() can execute arbitrary code - potential RCE',\n cwe: 'CWE-95',\n fix: 'Use safer alternatives like JSON.parse() or a sandboxed interpreter',\n },\n },\n {\n pattern: 'new Function(',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'injection',\n description: 'new Function() can execute arbitrary code',\n cwe: 'CWE-95',\n fix: 'Avoid dynamic function creation from user input',\n },\n },\n {\n pattern: 'exec(',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'injection',\n description: 'Command execution - potential command injection',\n cwe: 'CWE-78',\n fix: 'Use parameterized commands and validate/sanitize all inputs',\n },\n },\n {\n pattern: 'execSync(',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'injection',\n description: 'Synchronous command execution - potential injection',\n cwe: 'CWE-78',\n fix: 'Use spawn with argument arrays instead of shell strings',\n },\n },\n {\n pattern: 'spawn(',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'injection',\n description: 'Process spawn - verify inputs are sanitized',\n cwe: 'CWE-78',\n fix: 'Use shell: false and pass arguments as array',\n },\n },\n {\n pattern: 'child_process',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'injection',\n description: 'Child process module - review for command injection',\n cwe: 'CWE-78',\n fix: 'Validate all inputs passed to child processes',\n },\n },\n\n // ============================================\n // CRITICAL: SQL Injection patterns\n // NOTE: ${} is NOT flagged here - we check SQL context in isFalsePositive\n // ============================================\n {\n pattern: 'SELECT * FROM',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'sql-injection',\n description: 'Raw SQL query detected - verify parameterization',\n cwe: 'CWE-89',\n fix: 'Use ORM or parameterized queries',\n },\n },\n {\n pattern: 'INSERT INTO',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'sql-injection',\n description: 'Raw SQL INSERT - verify parameterization',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries',\n },\n },\n {\n pattern: 'DELETE FROM',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'sql-injection',\n description: 'Raw SQL DELETE - verify parameterization',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries',\n },\n },\n {\n pattern: '.raw(`',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'sql-injection',\n description: 'Raw query with template literal - high injection risk',\n cwe: 'CWE-89',\n fix: 'Avoid raw queries with interpolation or use proper escaping',\n },\n },\n {\n pattern: \".raw('\",\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'sql-injection',\n description: 'Raw query method - verify for injection risk',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries instead of raw SQL',\n },\n },\n {\n pattern: '.raw(\"',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'sql-injection',\n description: 'Raw query method - verify for injection risk',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries instead of raw SQL',\n },\n },\n {\n pattern: '`SELECT',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'sql-injection',\n description: 'SQL in template literal - check for injection',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries with placeholders',\n },\n },\n {\n pattern: '`INSERT',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'sql-injection',\n description: 'SQL INSERT in template literal - check for injection',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries with placeholders',\n },\n },\n {\n pattern: '`UPDATE',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'sql-injection',\n description: 'SQL UPDATE in template literal - check for injection',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries with placeholders',\n },\n },\n {\n pattern: '`DELETE',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'sql-injection',\n description: 'SQL DELETE in template literal - check for injection',\n cwe: 'CWE-89',\n fix: 'Use parameterized queries with placeholders',\n },\n },\n\n // ============================================\n // CRITICAL: XSS vulnerabilities\n // ============================================\n {\n pattern: 'innerHTML',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'innerHTML can inject malicious scripts',\n cwe: 'CWE-79',\n fix: 'Use textContent or sanitize HTML with DOMPurify',\n },\n },\n {\n pattern: 'outerHTML',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'outerHTML can inject malicious scripts',\n cwe: 'CWE-79',\n fix: 'Avoid outerHTML with user input',\n },\n },\n {\n pattern: 'document.write',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'document.write can inject malicious content',\n cwe: 'CWE-79',\n fix: 'Use DOM methods like createElement instead',\n },\n },\n {\n pattern: 'dangerouslySetInnerHTML',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'React dangerouslySetInnerHTML - XSS risk',\n cwe: 'CWE-79',\n fix: 'Sanitize with DOMPurify before using',\n },\n },\n {\n pattern: 'v-html',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'Vue v-html directive - XSS risk',\n cwe: 'CWE-79',\n fix: 'Sanitize content or use v-text',\n },\n },\n {\n pattern: '[innerHTML]',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'xss',\n description: 'Angular innerHTML binding - XSS risk',\n cwe: 'CWE-79',\n fix: 'Use Angular DomSanitizer',\n },\n },\n\n // ============================================\n // CRITICAL: Hardcoded secrets\n // More specific patterns to reduce false positives\n // ============================================\n {\n pattern: \"password = '\",\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded password in string',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: 'password = \"',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded password in string',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: \"password: '\",\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded password in config',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: 'password: \"',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded password in config',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: \"api_key = '\",\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded API key',\n cwe: 'CWE-798',\n fix: 'Use environment variables',\n },\n },\n {\n pattern: 'api_key = \"',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded API key',\n cwe: 'CWE-798',\n fix: 'Use environment variables',\n },\n },\n {\n pattern: \"apiKey: '\",\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded API key in config',\n cwe: 'CWE-798',\n fix: 'Use environment variables',\n },\n },\n {\n pattern: 'apiKey: \"',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded API key in config',\n cwe: 'CWE-798',\n fix: 'Use environment variables',\n },\n },\n {\n pattern: \"secret = '\",\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded secret',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: 'secret = \"',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'Hardcoded secret',\n cwe: 'CWE-798',\n fix: 'Use environment variables or secret management',\n },\n },\n {\n pattern: 'AWS_SECRET_ACCESS_KEY=',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'secrets',\n description: 'AWS secret key assignment',\n cwe: 'CWE-798',\n fix: 'Use IAM roles or AWS Secrets Manager',\n },\n },\n {\n pattern: \"'Bearer \",\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'secrets',\n description: 'Hardcoded bearer token in string',\n cwe: 'CWE-798',\n fix: 'Use environment variables for tokens',\n },\n },\n {\n pattern: '\"Bearer ',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'secrets',\n description: 'Hardcoded bearer token in string',\n cwe: 'CWE-798',\n fix: 'Use environment variables for tokens',\n },\n },\n\n // ============================================\n // SERIOUS: Authentication issues\n // ============================================\n {\n pattern: 'password ==',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'auth',\n description: 'Plain text password comparison',\n cwe: 'CWE-256',\n fix: 'Use bcrypt.compare() or similar secure comparison',\n },\n },\n {\n pattern: 'password ===',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'auth',\n description: 'Plain text password comparison',\n cwe: 'CWE-256',\n fix: 'Use bcrypt.compare() or similar secure comparison',\n },\n },\n {\n pattern: 'MD5(',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'crypto',\n description: 'MD5 is cryptographically broken',\n cwe: 'CWE-328',\n fix: 'Use SHA-256 or bcrypt for passwords',\n },\n },\n {\n pattern: 'md5(',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'crypto',\n description: 'MD5 is cryptographically broken',\n cwe: 'CWE-328',\n fix: 'Use SHA-256 or bcrypt for passwords',\n },\n },\n {\n pattern: 'SHA1(',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'crypto',\n description: 'SHA1 is deprecated for security use',\n cwe: 'CWE-328',\n fix: 'Use SHA-256 or stronger',\n },\n },\n {\n pattern: 'sha1(',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'crypto',\n description: 'SHA1 is deprecated for security use',\n cwe: 'CWE-328',\n fix: 'Use SHA-256 or stronger',\n },\n },\n {\n pattern: 'Math.random()',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'crypto',\n description: 'Math.random() is not cryptographically secure',\n cwe: 'CWE-338',\n fix: 'Use crypto.randomBytes() or crypto.getRandomValues()',\n },\n },\n\n // ============================================\n // SERIOUS: Insecure configurations\n // ============================================\n {\n pattern: 'cors: true',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'config',\n description: 'CORS enabled - verify origin restrictions',\n cwe: 'CWE-942',\n fix: 'Specify allowed origins explicitly',\n },\n },\n {\n pattern: \"origin: '*'\",\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'config',\n description: 'CORS allows all origins',\n cwe: 'CWE-942',\n fix: 'Restrict to specific trusted origins',\n },\n },\n {\n pattern: 'origin: \"*\"',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'config',\n description: 'CORS allows all origins',\n cwe: 'CWE-942',\n fix: 'Restrict to specific trusted origins',\n },\n },\n {\n pattern: 'secure: false',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'config',\n description: 'Insecure cookie/connection setting',\n cwe: 'CWE-614',\n fix: 'Set secure: true in production',\n },\n },\n {\n pattern: 'httpOnly: false',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'config',\n description: 'Cookie accessible to JavaScript',\n cwe: 'CWE-1004',\n fix: 'Set httpOnly: true to prevent XSS cookie theft',\n },\n },\n {\n pattern: 'rejectUnauthorized: false',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'config',\n description: 'TLS certificate validation disabled',\n cwe: 'CWE-295',\n fix: 'Enable certificate validation in production',\n },\n },\n {\n pattern: 'NODE_TLS_REJECT_UNAUTHORIZED',\n metadata: {\n type: 'vulnerability',\n severity: 'critical',\n category: 'config',\n description: 'TLS validation may be disabled',\n cwe: 'CWE-295',\n fix: 'Never disable TLS validation in production',\n },\n },\n\n // ============================================\n // MODERATE: Common bugs and issues\n // ============================================\n {\n pattern: '.forEach(async',\n metadata: {\n type: 'vulnerability',\n severity: 'serious',\n category: 'async',\n description: 'async forEach does not await - unexpected behavior',\n cwe: 'CWE-703',\n fix: 'Use for...of loop or Promise.all(arr.map())',\n },\n },\n {\n pattern: 'JSON.parse(',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'error-handling',\n description: 'JSON.parse can throw - needs try/catch',\n cwe: 'CWE-755',\n fix: 'Wrap in try/catch block',\n },\n },\n {\n pattern: 'atob(',\n metadata: {\n type: 'vulnerability',\n severity: 'low',\n category: 'encoding',\n description: 'atob can throw on invalid input',\n cwe: 'CWE-755',\n fix: 'Wrap in try/catch and validate input',\n },\n },\n\n // ============================================\n // Privacy & Compliance patterns\n // ============================================\n {\n pattern: 'console.log(',\n metadata: {\n type: 'vulnerability',\n severity: 'low',\n category: 'logging',\n description: 'Console logging - may leak sensitive data',\n cwe: 'CWE-532',\n fix: 'Remove or replace with proper logging in production',\n },\n },\n {\n pattern: 'localStorage.setItem',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'storage',\n description: 'localStorage is accessible to XSS attacks',\n cwe: 'CWE-922',\n fix: 'Avoid storing sensitive data in localStorage',\n },\n },\n {\n pattern: 'sessionStorage.setItem',\n metadata: {\n type: 'vulnerability',\n severity: 'moderate',\n category: 'storage',\n description: 'sessionStorage is accessible to XSS attacks',\n cwe: 'CWE-922',\n fix: 'Avoid storing sensitive data in sessionStorage',\n },\n },\n];\n\n/**\n * Build the vulnerability signature trie\n * Called once at startup, then O(1) access\n */\nlet vulnerabilityTrie: AhoCorasick<PatternMetadata> | null = null;\n\nexport function getVulnerabilityTrie(): AhoCorasick<PatternMetadata> {\n if (!vulnerabilityTrie) {\n vulnerabilityTrie = new AhoCorasick<PatternMetadata>();\n \n for (const { pattern, metadata } of VULNERABILITY_PATTERNS) {\n vulnerabilityTrie.addPattern(pattern, metadata, metadata);\n }\n \n vulnerabilityTrie.build();\n if (!isInteractiveMode()) {\n console.error(` Loaded ${VULNERABILITY_PATTERNS.length} vulnerability signatures into trie`);\n }\n }\n \n return vulnerabilityTrie;\n}\n\n/**\n * Scan code for vulnerabilities using the trie\n * O(n + z) where n = code length, z = number of matches\n */\nexport function scanForVulnerabilities(code: string, filePath: string): VulnerabilityMatch[] {\n // CRITICAL: Skip files that should never be scanned\n if (shouldAlwaysExcludeFile(filePath)) {\n return [];\n }\n \n const trie = getVulnerabilityTrie();\n const rawMatches = trie.search(code);\n const lines = code.split('\\n');\n \n // Deduplicate and filter false positives\n const matches: VulnerabilityMatch[] = [];\n const seen = new Set<string>();\n \n for (const match of rawMatches) {\n // Create unique key for deduplication\n const key = `${match.line}:${match.pattern}`;\n if (seen.has(key)) continue;\n seen.add(key);\n \n const meta = match.metadata!;\n \n // Check file exclusions\n if (shouldExcludeFile(filePath, meta.category || '')) continue;\n \n // Filter out false positives\n if (isFalsePositive(code, match, filePath, lines)) continue;\n \n const vulnMatch: VulnerabilityMatch = {\n pattern: match.pattern,\n line: match.line,\n column: match.column,\n severity: meta.severity as any,\n category: meta.category || 'unknown',\n description: meta.description || '',\n fix: meta.fix || '',\n };\n if (meta.cwe !== undefined) {\n vulnMatch.cwe = meta.cwe;\n }\n matches.push(vulnMatch);\n }\n \n return matches;\n}\n\n/**\n * Get surrounding lines for context analysis\n */\nfunction getSurroundingLines(lines: string[], lineNum: number, range: number = 3): string[] {\n const start = Math.max(0, lineNum - range - 1);\n const end = Math.min(lines.length, lineNum + range);\n return lines.slice(start, end);\n}\n\n/**\n * Filter out common false positives with enhanced context awareness\n */\nfunction isFalsePositive(_code: string, match: any, filePath: string, lines: string[]): boolean {\n const line = lines[match.line - 1] || '';\n const trimmedLine = line.trim();\n const pattern = match.pattern;\n const category = match.metadata?.category || '';\n \n // ============================================\n // CRITICAL: Skip signature/pattern definition files\n // ============================================\n if (filePath.includes('signature') || \n filePath.includes('patterns') ||\n filePath.includes('rules')) {\n // If the line contains 'pattern:' or 'pattern =' it's a definition, not a vulnerability\n if (/pattern\\s*[:=]/.test(line)) {\n return true;\n }\n }\n \n // Skip if line is a pattern string definition (in any file)\n // e.g., pattern: \"password = '\", or { pattern: 'secret' }\n if (/^\\s*(pattern|regex|rule|signature)\\s*[:=]/.test(trimmedLine)) {\n return true;\n }\n \n // ============================================\n // CRITICAL: Skip test files entirely for most patterns\n // ============================================\n if (isTestFile(filePath)) {\n // Test files can have intentional bad code for testing detection\n // Only flag REAL secrets (actual API keys that look real)\n if (category === 'secrets') {\n // Skip if it's clearly test/mock data\n if (/test|mock|fake|dummy|example|fixture|sample|placeholder/i.test(line)) {\n return true;\n }\n // Skip generic fake values like \"password123\", \"secret_test\", etc.\n if (/'[a-z_]*password[a-z_0-9]*'|\"[a-z_]*password[a-z_0-9]*\"|'[a-z_]*secret[a-z_0-9]*'|\"[a-z_]*secret[a-z_0-9]*\"/i.test(line)) {\n return true;\n }\n // Skip obviously fake API keys (short or with placeholder patterns)\n if (/sk-[a-z0-9]{10,20}\"|'sk-[a-z0-9]{10,20}'|api[_-]?key.*['\"][a-z0-9_-]{5,30}['\"]/i.test(line)) {\n return true;\n }\n }\n // For non-secrets, skip all test file findings\n return true;\n }\n \n // ============================================\n // SKIP: Comments and documentation\n // ============================================\n if (trimmedLine.startsWith('//') || \n trimmedLine.startsWith('*') || \n trimmedLine.startsWith('/*') ||\n trimmedLine.startsWith('#') ||\n trimmedLine.startsWith('<!--')) {\n return true;\n }\n \n // Skip JSDoc and documentation blocks\n if (/^\\s*\\*\\s/.test(line) || /@(param|returns|example|description|see|link)/i.test(line)) {\n return true;\n }\n \n // Skip description/fix/metadata strings (common in config objects)\n if (/^\\s*(description|fix|message|help|hint|reason|why)\\s*[:=]/.test(trimmedLine)) {\n return true;\n }\n \n // ============================================\n // SKIP: Type definitions and interfaces\n // ============================================\n if (/^\\s*(interface|type|export\\s+interface|export\\s+type)\\s/.test(line)) {\n return true;\n }\n \n // Skip TypeScript type annotations (e.g., password: string)\n if (/:\\s*(string|number|boolean|any|unknown|null|undefined|void)\\s*(;|,|\\)|$)/.test(line)) {\n return true;\n }\n \n // Skip interface/type property definitions\n if (/^\\s*\\w+\\s*\\??\\s*:\\s*(string|number|boolean|any)/.test(trimmedLine)) {\n return true;\n }\n \n // ============================================\n // SKIP: Environment variable reads (not hardcoded)\n // ============================================\n if (/process\\.env|import\\.meta\\.env|getenv|os\\.environ|Deno\\.env|\\.env\\.|config\\.\\w+|settings\\.\\w+/.test(line)) {\n return true;\n }\n \n // ============================================\n // SKIP: Lock files and package metadata\n // ============================================\n if (filePath.endsWith('package-lock.json') || \n filePath.endsWith('yarn.lock') ||\n filePath.endsWith('pnpm-lock.yaml') ||\n filePath.includes('node_modules/')) {\n return true;\n }\n \n // ============================================\n // SKIP: String in object definition (metadata, not code)\n // ============================================\n // Lines like: severity: 'critical', or category: 'secrets'\n if (/^\\s*(severity|category|type|level|priority|cwe|owasp)\\s*:\\s*['\"]/.test(trimmedLine)) {\n return true;\n }\n \n // ============================================\n // Category-specific false positive detection\n // ============================================\n \n // SQL Injection: Only flag in SQL contexts\n if (category === 'sql-injection') {\n const surroundingLines = getSurroundingLines(lines, match.line);\n if (!isInSQLContext(line, surroundingLines)) {\n return true;\n }\n }\n \n // Secrets: Very strict detection to avoid false positives\n if (category === 'secrets' || category === 'auth') {\n // Skip function parameters (function foo(password: string))\n if (/\\(\\s*[^)]*\\w+\\s*:\\s*(string|any)/.test(line)) {\n return true;\n }\n // Skip object destructuring ({ password })\n if (/\\{\\s*\\w*password\\w*\\s*(,|\\}|:)/.test(line) && !/'|\"|`/.test(line.split(/password/i)[1] || '')) {\n return true;\n }\n // Skip when reading from env or config\n if (/=\\s*(process\\.env|config\\.|options\\.|settings\\.|env\\.)/.test(line)) {\n return true;\n }\n // Skip variable declarations without string literals\n if (/password\\s*[=:](?!\\s*['\"`])/.test(line)) {\n return true;\n }\n // Skip if it's reading from another variable\n if (/password\\s*=\\s*\\w+(\\.|$)/.test(line) && !/'|\"|`/.test(line)) {\n return true;\n }\n // Skip error messages and logging about passwords\n if (/error|message|log|warn|info|debug|throw|new Error/i.test(line)) {\n return true;\n }\n // Skip regex patterns for password validation\n if (/regex|RegExp|\\/.*password.*\\//i.test(line)) {\n return true;\n }\n }\n \n // Logging: Skip in development/debug contexts\n if (category === 'logging') {\n // console.error is often intentional\n if (pattern === 'console.error(' || pattern === 'console.warn(') {\n return true;\n }\n // Skip if in catch block (error logging)\n if (/catch|error|err\\b/.test(line)) {\n return true;\n }\n }\n \n // Config patterns: Skip legitimate security config\n if (category === 'config') {\n // Skip when setting secure values\n if (/secure:\\s*true/.test(line) || /httpOnly:\\s*true/.test(line)) {\n return true;\n }\n // Skip environment-based config\n if (/NODE_ENV|process\\.env|production|development/.test(line)) {\n return true;\n }\n // Skip conditional configs\n if (/if\\s*\\(|ternary|\\?.*:/.test(line)) {\n return true;\n }\n }\n \n // Crypto: Skip in contexts where weak crypto is acceptable\n if (category === 'crypto') {\n // MD5/SHA1 for non-security purposes (checksums, cache keys)\n if (/checksum|hash.*file|etag|cache.*key|fingerprint|integrity|content.*hash/i.test(line)) {\n return true;\n }\n // Math.random for non-crypto purposes (UI, games, etc.)\n if (pattern === 'Math.random()') {\n // Only flag if in security context\n if (!/token|secret|password|key|auth|session|csrf|nonce/i.test(line)) {\n return true;\n }\n }\n }\n \n // Async: forEach async is sometimes intentional\n if (category === 'async') {\n // Skip if there's a comment indicating it's intentional\n if (/\\/\\/.*intentional|\\/\\/.*fire.?and.?forget|\\/\\/.*parallel/i.test(line)) {\n return true;\n }\n }\n \n // ============================================\n // SKIP: Validation/check patterns (not vulnerabilities)\n // ============================================\n // Skip password validation logic\n if (/password.*length|validate.*password|check.*password|verify.*password|is.*valid/i.test(line)) {\n return true;\n }\n \n // Skip comparison against hashed values\n if (/bcrypt|argon|scrypt|pbkdf|compare.*hash|hash.*compare|verify.*hash/i.test(line)) {\n return true;\n }\n \n // Skip schema definitions (Zod, Yup, etc.)\n if (/z\\.|yup\\.|joi\\.|schema|validation|validator/i.test(line)) {\n return true;\n }\n \n // ============================================\n // SKIP: Imports and requires\n // ============================================\n if (/^\\s*(import|require|from)\\s/.test(trimmedLine)) {\n return true;\n }\n \n // ============================================\n // SKIP: Example/Demo files\n // ============================================\n if (/example|demo|sample|tutorial|readme/i.test(filePath)) {\n return true;\n }\n \n return false;\n}\n\n/**\n * Check if file is a test file\n */\nfunction isTestFile(filePath: string): boolean {\n return /\\.(test|spec)\\.[jt]sx?$/.test(filePath) ||\n /__tests__\\//.test(filePath) ||\n /test\\//.test(filePath) ||\n /tests\\//.test(filePath) ||\n /\\.stories\\.[jt]sx?$/.test(filePath);\n}\n\n/**\n * Get vulnerability statistics\n */\nexport function getVulnerabilityStats(): { total: number; byCategory: Record<string, number>; bySeverity: Record<string, number> } {\n const byCategory: Record<string, number> = {};\n const bySeverity: Record<string, number> = {};\n \n for (const { metadata } of VULNERABILITY_PATTERNS) {\n const cat = metadata.category || 'unknown';\n const sev = metadata.severity || 'unknown';\n byCategory[cat] = (byCategory[cat] || 0) + 1;\n bySeverity[sev] = (bySeverity[sev] || 0) + 1;\n }\n \n return {\n total: VULNERABILITY_PATTERNS.length,\n byCategory,\n bySeverity,\n };\n}\n\n"],"mappings":"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","names":[]}
@@ -1,440 +0,0 @@
1
- import {
2
- BackupManager,
3
- safeParseAndValidate
4
- } from "./chunk-EFWVF6TI.js";
5
- import {
6
- atomicWriteJSON
7
- } from "./chunk-43X6JBEM.js";
8
- import {
9
- getTrieDirectory
10
- } from "./chunk-VVITXIHN.js";
11
-
12
- // src/agent/insight-store.ts
13
- import { mkdir, readFile } from "fs/promises";
14
- import { existsSync } from "fs";
15
- import { join } from "path";
16
- import { z } from "zod";
17
- var InsightDetailsSchema = z.object({
18
- affectedFiles: z.array(z.string()).optional(),
19
- issueBreakdown: z.record(z.string(), z.number()).optional(),
20
- examples: z.array(z.string()).optional(),
21
- trend: z.enum(["improving", "stable", "worsening"]).optional(),
22
- comparison: z.string().optional(),
23
- resolvedCount: z.number().optional(),
24
- resolvedIssues: z.array(z.object({
25
- file: z.string(),
26
- line: z.number().optional(),
27
- issue: z.string(),
28
- agent: z.string(),
29
- resolvedAt: z.string().optional()
30
- })).optional(),
31
- summary: z.string().optional(),
32
- // Hypothesis-related fields
33
- hypothesis: z.string().optional(),
34
- testCriteria: z.string().optional(),
35
- confidence: z.number().optional(),
36
- // Pattern-related fields
37
- patternsCount: z.number().optional(),
38
- topPattern: z.string().optional()
39
- });
40
- var InsightSchema = z.object({
41
- id: z.string(),
42
- type: z.enum(["observation", "warning", "suggestion", "celebration", "question"]),
43
- message: z.string(),
44
- context: z.string().optional(),
45
- suggestedAction: z.string().optional(),
46
- actionCommand: z.string().optional(),
47
- relatedIssues: z.array(z.string()),
48
- priority: z.number().min(1).max(10),
49
- timestamp: z.number(),
50
- dismissed: z.boolean(),
51
- category: z.enum(["security", "quality", "performance", "pattern", "progress", "general"]),
52
- details: InsightDetailsSchema.optional()
53
- });
54
- var InsightStoreDataSchema = z.object({
55
- version: z.literal(1),
56
- insights: z.array(InsightSchema),
57
- cooldowns: z.record(z.string(), z.number()),
58
- // insightKey -> timestamp
59
- dismissedIds: z.array(z.string()),
60
- // Track dismissed insight IDs permanently
61
- lastUpdated: z.string()
62
- });
63
- var InsightStore = class _InsightStore {
64
- projectPath;
65
- data;
66
- loaded = false;
67
- dirty = false;
68
- // Default cooldown periods (in ms)
69
- static COOLDOWNS = {
70
- "pre-push-warning": 6e4,
71
- // 1 min between pre-push warnings
72
- "security-warning": 3e4,
73
- // 30s between security warnings
74
- "new-issues": 3e4,
75
- // 30s between new issue observations
76
- "celebration": 6e4,
77
- // 1 min between celebrations
78
- "pattern-suggestion": 12e4,
79
- // 2 min between pattern suggestions
80
- "accessibility-visual-qa": 3e5,
81
- // 5 min between visual QA suggestions
82
- "goal-suggestion": 3e5,
83
- // 5 min between goal suggestions
84
- "risk-prediction": 18e4,
85
- // 3 min between risk predictions
86
- "hypothesis-update": 6e5,
87
- // 10 min between hypothesis updates
88
- "auto-escalation": 3e5
89
- // 5 min between auto-escalations
90
- };
91
- constructor(projectPath) {
92
- this.projectPath = projectPath;
93
- this.data = this.createEmptyData();
94
- }
95
- /**
96
- * Get the storage file path
97
- */
98
- getStorePath() {
99
- return join(getTrieDirectory(this.projectPath), "memory", "insights.json");
100
- }
101
- /**
102
- * Create empty data structure
103
- */
104
- createEmptyData() {
105
- return {
106
- version: 1,
107
- insights: [],
108
- cooldowns: {},
109
- dismissedIds: [],
110
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
111
- };
112
- }
113
- /**
114
- * Load insights from disk
115
- *
116
- * If the file is corrupted, attempts recovery from backup.
117
- * Returns empty data if no valid file/backup exists.
118
- */
119
- async load() {
120
- if (this.loaded) {
121
- return this.data;
122
- }
123
- const storePath = this.getStorePath();
124
- try {
125
- if (existsSync(storePath)) {
126
- const content = await readFile(storePath, "utf-8");
127
- const result = safeParseAndValidate(content, InsightStoreDataSchema);
128
- if (result.success) {
129
- this.data = result.data;
130
- this.loaded = true;
131
- this.deduplicateInsights();
132
- return this.data;
133
- }
134
- console.error(` Insight store corrupted: ${result.error}`);
135
- const backupManager = new BackupManager(storePath);
136
- if (await backupManager.recoverFromBackup()) {
137
- console.error(" Recovered from backup");
138
- const recovered = await readFile(storePath, "utf-8");
139
- const recoveredResult = safeParseAndValidate(recovered, InsightStoreDataSchema);
140
- if (recoveredResult.success) {
141
- this.data = recoveredResult.data;
142
- this.loaded = true;
143
- this.deduplicateInsights();
144
- return this.data;
145
- }
146
- }
147
- console.error(" No valid backup found, starting fresh");
148
- }
149
- } catch (error) {
150
- console.error(` Could not load insight store: ${error}`);
151
- }
152
- this.data = this.createEmptyData();
153
- this.loaded = true;
154
- return this.data;
155
- }
156
- /**
157
- * Deduplicate existing insights on load
158
- * Keeps the most recent instance of each unique insight
159
- */
160
- deduplicateInsights() {
161
- const seen = /* @__PURE__ */ new Map();
162
- const toRemove = [];
163
- for (let i = 0; i < this.data.insights.length; i++) {
164
- const insight = this.data.insights[i];
165
- if (!insight) continue;
166
- const contentKey = this.getContentKey(insight);
167
- if (seen.has(contentKey)) {
168
- toRemove.push(i);
169
- } else {
170
- seen.set(contentKey, i);
171
- }
172
- }
173
- if (toRemove.length > 0) {
174
- for (let i = toRemove.length - 1; i >= 0; i--) {
175
- const idx = toRemove[i];
176
- if (idx !== void 0) {
177
- this.data.insights.splice(idx, 1);
178
- }
179
- }
180
- this.dirty = true;
181
- }
182
- }
183
- /**
184
- * Save insights to disk
185
- *
186
- * Creates backup before writing, uses atomic write.
187
- */
188
- async save() {
189
- if (!this.dirty && this.loaded) {
190
- return;
191
- }
192
- const storePath = this.getStorePath();
193
- const memoryDir = join(getTrieDirectory(this.projectPath), "memory");
194
- await mkdir(memoryDir, { recursive: true });
195
- const backupManager = new BackupManager(storePath);
196
- await backupManager.createBackup();
197
- this.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
198
- await atomicWriteJSON(storePath, this.data);
199
- this.dirty = false;
200
- }
201
- /**
202
- * Generate a content-based key for deduplication
203
- * Insights with the same content key are considered duplicates
204
- */
205
- getContentKey(insight) {
206
- const normalizedMessage = insight.message.replace(/\d+/g, "N").toLowerCase().trim();
207
- return `${insight.type}:${insight.category}:${normalizedMessage}`;
208
- }
209
- /**
210
- * Add an insight to the store
211
- *
212
- * Checks for duplicates using both insight ID and content similarity.
213
- * If a similar insight already exists (same type, category, and normalized message),
214
- * updates its timestamp instead of creating a duplicate.
215
- * Respects cooldowns to prevent insight spam.
216
- */
217
- async addInsight(insight) {
218
- await this.load();
219
- if (this.data.insights.some((i) => i.id === insight.id)) {
220
- return false;
221
- }
222
- if (this.data.dismissedIds.includes(insight.id)) {
223
- return false;
224
- }
225
- const contentKey = this.getContentKey(insight);
226
- const existingIndex = this.data.insights.findIndex(
227
- (i) => !i.dismissed && this.getContentKey(i) === contentKey
228
- );
229
- if (existingIndex >= 0) {
230
- const existing = this.data.insights[existingIndex];
231
- if (existing) {
232
- existing.timestamp = insight.timestamp;
233
- existing.message = insight.message;
234
- existing.details = insight.details;
235
- existing.relatedIssues = insight.relatedIssues;
236
- existing.suggestedAction = insight.suggestedAction;
237
- this.data.insights.splice(existingIndex, 1);
238
- this.data.insights.unshift(existing);
239
- this.dirty = true;
240
- await this.save();
241
- }
242
- return false;
243
- }
244
- this.data.insights.unshift(insight);
245
- if (this.data.insights.length > 100) {
246
- this.data.insights = this.data.insights.slice(0, 100);
247
- }
248
- this.dirty = true;
249
- await this.save();
250
- return true;
251
- }
252
- /**
253
- * Check if a cooldown has expired for an insight type
254
- */
255
- canCreateInsight(insightKey) {
256
- const lastTime = this.data.cooldowns[insightKey];
257
- const cooldown = _InsightStore.COOLDOWNS[insightKey] || 3e4;
258
- if (!lastTime) return true;
259
- return Date.now() - lastTime > cooldown;
260
- }
261
- /**
262
- * Mark that an insight type was created (set cooldown)
263
- */
264
- async markInsightCreated(insightKey) {
265
- await this.load();
266
- this.data.cooldowns[insightKey] = Date.now();
267
- this.dirty = true;
268
- await this.save();
269
- }
270
- /**
271
- * Get active (non-dismissed) insights
272
- *
273
- * Returns insights sorted by priority (highest first),
274
- * limited to the specified count.
275
- */
276
- getActiveInsights(limit = 5) {
277
- return this.data.insights.filter((i) => !i.dismissed).sort((a, b) => b.priority - a.priority).slice(0, limit);
278
- }
279
- /**
280
- * Get all insights (including dismissed)
281
- */
282
- getAllInsights() {
283
- return [...this.data.insights];
284
- }
285
- /**
286
- * Dismiss an insight by ID
287
- */
288
- async dismissInsight(insightId) {
289
- await this.load();
290
- const insight = this.data.insights.find((i) => i.id === insightId);
291
- if (!insight) {
292
- return false;
293
- }
294
- insight.dismissed = true;
295
- if (!this.data.dismissedIds.includes(insightId)) {
296
- this.data.dismissedIds.push(insightId);
297
- if (this.data.dismissedIds.length > 500) {
298
- this.data.dismissedIds = this.data.dismissedIds.slice(-500);
299
- }
300
- }
301
- this.dirty = true;
302
- await this.save();
303
- return true;
304
- }
305
- /**
306
- * Remove an insight entirely
307
- */
308
- async removeInsight(insightId) {
309
- await this.load();
310
- const index = this.data.insights.findIndex((i) => i.id === insightId);
311
- if (index === -1) {
312
- return false;
313
- }
314
- this.data.insights.splice(index, 1);
315
- this.dirty = true;
316
- await this.save();
317
- return true;
318
- }
319
- /**
320
- * Clear all cooldowns
321
- */
322
- async clearCooldowns() {
323
- await this.load();
324
- this.data.cooldowns = {};
325
- this.dirty = true;
326
- await this.save();
327
- }
328
- /**
329
- * Get insight by ID
330
- */
331
- getInsight(insightId) {
332
- return this.data.insights.find((i) => i.id === insightId);
333
- }
334
- /**
335
- * Update an existing insight
336
- */
337
- async updateInsight(insightId, updates) {
338
- await this.load();
339
- const insight = this.data.insights.find((i) => i.id === insightId);
340
- if (!insight) {
341
- return false;
342
- }
343
- Object.assign(insight, updates);
344
- this.dirty = true;
345
- await this.save();
346
- return true;
347
- }
348
- /**
349
- * Get insights by category
350
- */
351
- getInsightsByCategory(category) {
352
- return this.data.insights.filter((i) => i.category === category && !i.dismissed);
353
- }
354
- /**
355
- * Get insights by type
356
- */
357
- getInsightsByType(type) {
358
- return this.data.insights.filter((i) => i.type === type && !i.dismissed);
359
- }
360
- /**
361
- * Get insights from the last N hours
362
- */
363
- getRecentInsights(hours = 24) {
364
- const cutoff = Date.now() - hours * 60 * 60 * 1e3;
365
- return this.data.insights.filter((i) => i.timestamp >= cutoff);
366
- }
367
- /**
368
- * Get statistics about insights
369
- */
370
- getStats() {
371
- const stats = {
372
- total: this.data.insights.length,
373
- active: 0,
374
- dismissed: 0,
375
- byCategory: {},
376
- byType: {}
377
- };
378
- for (const insight of this.data.insights) {
379
- if (insight.dismissed) {
380
- stats.dismissed++;
381
- } else {
382
- stats.active++;
383
- }
384
- stats.byCategory[insight.category] = (stats.byCategory[insight.category] || 0) + 1;
385
- stats.byType[insight.type] = (stats.byType[insight.type] || 0) + 1;
386
- }
387
- return stats;
388
- }
389
- /**
390
- * Prune old insights (older than N days)
391
- */
392
- async pruneOldInsights(daysToKeep = 30) {
393
- await this.load();
394
- const cutoff = Date.now() - daysToKeep * 24 * 60 * 60 * 1e3;
395
- const originalCount = this.data.insights.length;
396
- this.data.insights = this.data.insights.filter((i) => i.timestamp >= cutoff);
397
- const pruned = originalCount - this.data.insights.length;
398
- if (pruned > 0) {
399
- this.dirty = true;
400
- await this.save();
401
- }
402
- return pruned;
403
- }
404
- /**
405
- * Check if the store has been loaded
406
- */
407
- isLoaded() {
408
- return this.loaded;
409
- }
410
- /**
411
- * Force reload from disk
412
- */
413
- async reload() {
414
- this.loaded = false;
415
- this.dirty = false;
416
- return this.load();
417
- }
418
- };
419
- var insightStores = /* @__PURE__ */ new Map();
420
- function getInsightStore(projectPath) {
421
- let store = insightStores.get(projectPath);
422
- if (!store) {
423
- store = new InsightStore(projectPath);
424
- insightStores.set(projectPath, store);
425
- }
426
- return store;
427
- }
428
- function clearInsightStores() {
429
- insightStores.clear();
430
- }
431
-
432
- export {
433
- InsightDetailsSchema,
434
- InsightSchema,
435
- InsightStoreDataSchema,
436
- InsightStore,
437
- getInsightStore,
438
- clearInsightStores
439
- };
440
- //# sourceMappingURL=chunk-T63OHG4Q.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agent/insight-store.ts"],"sourcesContent":["/**\n * Insight Store - Persistent storage for insights\n * \n * Persists to: .trie/memory/insights.json\n * \n * Features:\n * - Insight persistence across restarts\n * - Cooldown state persistence (prevents duplicate insights)\n * - Dismissed insight tracking\n * - Atomic writes with backup rotation\n * - Zod validation for data integrity\n */\n\nimport { mkdir, readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getTrieDirectory } from '../utils/workspace.js';\nimport { z } from 'zod';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { safeParseAndValidate } from '../memory/validation.js';\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\n/**\n * Schema for insight details\n */\nexport const InsightDetailsSchema = z.object({\n affectedFiles: z.array(z.string()).optional(),\n issueBreakdown: z.record(z.string(), z.number()).optional(),\n examples: z.array(z.string()).optional(),\n trend: z.enum(['improving', 'stable', 'worsening']).optional(),\n comparison: z.string().optional(),\n resolvedCount: z.number().optional(),\n resolvedIssues: z.array(z.object({\n file: z.string(),\n line: z.number().optional(),\n issue: z.string(),\n agent: z.string(),\n resolvedAt: z.string().optional(),\n })).optional(),\n summary: z.string().optional(),\n // Hypothesis-related fields\n hypothesis: z.string().optional(),\n testCriteria: z.string().optional(),\n confidence: z.number().optional(),\n // Pattern-related fields\n patternsCount: z.number().optional(),\n topPattern: z.string().optional(),\n});\n\n/**\n * Schema for an insight\n */\nexport const InsightSchema = z.object({\n id: z.string(),\n type: z.enum(['observation', 'warning', 'suggestion', 'celebration', 'question']),\n message: z.string(),\n context: z.string().optional(),\n suggestedAction: z.string().optional(),\n actionCommand: z.string().optional(),\n relatedIssues: z.array(z.string()),\n priority: z.number().min(1).max(10),\n timestamp: z.number(),\n dismissed: z.boolean(),\n category: z.enum(['security', 'quality', 'performance', 'pattern', 'progress', 'general']),\n details: InsightDetailsSchema.optional(),\n});\n\nexport type Insight = z.infer<typeof InsightSchema>;\n\n/**\n * Schema for the entire insight store file\n */\nexport const InsightStoreDataSchema = z.object({\n version: z.literal(1),\n insights: z.array(InsightSchema),\n cooldowns: z.record(z.string(), z.number()), // insightKey -> timestamp\n dismissedIds: z.array(z.string()), // Track dismissed insight IDs permanently\n lastUpdated: z.string(),\n});\n\nexport type InsightStoreData = z.infer<typeof InsightStoreDataSchema>;\n\n// ============================================================================\n// InsightStore Class\n// ============================================================================\n\n/**\n * Persistent store for insights\n * \n * Usage:\n * ```typescript\n * const store = new InsightStore(projectPath);\n * await store.load();\n * \n * await store.addInsight(insight);\n * const active = store.getActiveInsights();\n * await store.dismissInsight(insightId);\n * ```\n */\nexport class InsightStore {\n private projectPath: string;\n private data: InsightStoreData;\n private loaded: boolean = false;\n private dirty: boolean = false;\n \n // Default cooldown periods (in ms)\n static readonly COOLDOWNS: Record<string, number> = {\n 'pre-push-warning': 60000, // 1 min between pre-push warnings\n 'security-warning': 30000, // 30s between security warnings\n 'new-issues': 30000, // 30s between new issue observations\n 'celebration': 60000, // 1 min between celebrations\n 'pattern-suggestion': 120000, // 2 min between pattern suggestions\n 'accessibility-visual-qa': 300000, // 5 min between visual QA suggestions\n 'goal-suggestion': 300000, // 5 min between goal suggestions\n 'risk-prediction': 180000, // 3 min between risk predictions\n 'hypothesis-update': 600000, // 10 min between hypothesis updates\n 'auto-escalation': 300000, // 5 min between auto-escalations\n };\n \n constructor(projectPath: string) {\n this.projectPath = projectPath;\n this.data = this.createEmptyData();\n }\n \n /**\n * Get the storage file path\n */\n private getStorePath(): string {\n return join(getTrieDirectory(this.projectPath), 'memory', 'insights.json');\n }\n \n /**\n * Create empty data structure\n */\n private createEmptyData(): InsightStoreData {\n return {\n version: 1,\n insights: [],\n cooldowns: {},\n dismissedIds: [],\n lastUpdated: new Date().toISOString(),\n };\n }\n \n /**\n * Load insights from disk\n * \n * If the file is corrupted, attempts recovery from backup.\n * Returns empty data if no valid file/backup exists.\n */\n async load(): Promise<InsightStoreData> {\n if (this.loaded) {\n return this.data;\n }\n \n const storePath = this.getStorePath();\n \n try {\n if (existsSync(storePath)) {\n const content = await readFile(storePath, 'utf-8');\n const result = safeParseAndValidate(content, InsightStoreDataSchema);\n \n if (result.success) {\n this.data = result.data;\n this.loaded = true;\n // Deduplicate any existing duplicate insights\n this.deduplicateInsights();\n return this.data;\n }\n \n // Validation failed - attempt recovery from backup\n console.error(` Insight store corrupted: ${result.error}`);\n const backupManager = new BackupManager(storePath);\n \n if (await backupManager.recoverFromBackup()) {\n console.error(' Recovered from backup');\n const recovered = await readFile(storePath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, InsightStoreDataSchema);\n if (recoveredResult.success) {\n this.data = recoveredResult.data;\n this.loaded = true;\n // Deduplicate any existing duplicate insights\n this.deduplicateInsights();\n return this.data;\n }\n }\n \n console.error(' No valid backup found, starting fresh');\n }\n } catch (error) {\n // File doesn't exist or recovery failed - start fresh\n console.error(` Could not load insight store: ${error}`);\n }\n \n this.data = this.createEmptyData();\n this.loaded = true;\n return this.data;\n }\n \n /**\n * Deduplicate existing insights on load\n * Keeps the most recent instance of each unique insight\n */\n private deduplicateInsights(): void {\n const seen = new Map<string, number>(); // contentKey -> index of first occurrence\n const toRemove: number[] = [];\n \n // Process from newest to oldest (insights are sorted by recency)\n for (let i = 0; i < this.data.insights.length; i++) {\n const insight = this.data.insights[i];\n if (!insight) continue;\n \n const contentKey = this.getContentKey(insight);\n \n if (seen.has(contentKey)) {\n // This is a duplicate - mark for removal\n toRemove.push(i);\n } else {\n seen.set(contentKey, i);\n }\n }\n \n // Remove duplicates (reverse order to preserve indices)\n if (toRemove.length > 0) {\n for (let i = toRemove.length - 1; i >= 0; i--) {\n const idx = toRemove[i];\n if (idx !== undefined) {\n this.data.insights.splice(idx, 1);\n }\n }\n this.dirty = true;\n }\n }\n \n /**\n * Save insights to disk\n * \n * Creates backup before writing, uses atomic write.\n */\n async save(): Promise<void> {\n if (!this.dirty && this.loaded) {\n return; // No changes to save\n }\n \n const storePath = this.getStorePath();\n const memoryDir = join(getTrieDirectory(this.projectPath), 'memory');\n \n // Ensure directory exists\n await mkdir(memoryDir, { recursive: true });\n \n // Create backup before writing\n const backupManager = new BackupManager(storePath);\n await backupManager.createBackup();\n \n // Update timestamp\n this.data.lastUpdated = new Date().toISOString();\n \n // Atomic write\n await atomicWriteJSON(storePath, this.data);\n \n this.dirty = false;\n }\n \n /**\n * Generate a content-based key for deduplication\n * Insights with the same content key are considered duplicates\n */\n private getContentKey(insight: Insight): string {\n // Normalize the message by removing specific numbers/counts that might vary slightly\n // e.g., \"Found 30 security issues\" and \"Found 31 security issues\" are the same insight\n const normalizedMessage = insight.message\n .replace(/\\d+/g, 'N') // Replace all numbers with N\n .toLowerCase()\n .trim();\n \n return `${insight.type}:${insight.category}:${normalizedMessage}`;\n }\n \n /**\n * Add an insight to the store\n * \n * Checks for duplicates using both insight ID and content similarity.\n * If a similar insight already exists (same type, category, and normalized message),\n * updates its timestamp instead of creating a duplicate.\n * Respects cooldowns to prevent insight spam.\n */\n async addInsight(insight: Insight): Promise<boolean> {\n await this.load();\n \n // Check if already exists by ID\n if (this.data.insights.some(i => i.id === insight.id)) {\n return false;\n }\n \n // Check if ID was previously dismissed (don't re-add)\n if (this.data.dismissedIds.includes(insight.id)) {\n return false;\n }\n \n // Check for content-based duplicates (same type, category, similar message)\n const contentKey = this.getContentKey(insight);\n const existingIndex = this.data.insights.findIndex(i => \n !i.dismissed && this.getContentKey(i) === contentKey\n );\n \n if (existingIndex >= 0) {\n // Update existing insight instead of adding duplicate\n const existing = this.data.insights[existingIndex];\n if (existing) {\n // Update with new data but keep the original ID\n existing.timestamp = insight.timestamp;\n existing.message = insight.message; // Update with current counts\n existing.details = insight.details; // Update details\n existing.relatedIssues = insight.relatedIssues;\n existing.suggestedAction = insight.suggestedAction;\n \n // Move to front of list\n this.data.insights.splice(existingIndex, 1);\n this.data.insights.unshift(existing);\n \n this.dirty = true;\n await this.save();\n }\n return false; // Return false to indicate no new insight was created\n }\n \n // Add to front of list\n this.data.insights.unshift(insight);\n \n // Keep only last 100 insights\n if (this.data.insights.length > 100) {\n this.data.insights = this.data.insights.slice(0, 100);\n }\n \n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Check if a cooldown has expired for an insight type\n */\n canCreateInsight(insightKey: string): boolean {\n const lastTime = this.data.cooldowns[insightKey];\n const cooldown = InsightStore.COOLDOWNS[insightKey] || 30000;\n \n if (!lastTime) return true;\n return Date.now() - lastTime > cooldown;\n }\n \n /**\n * Mark that an insight type was created (set cooldown)\n */\n async markInsightCreated(insightKey: string): Promise<void> {\n await this.load();\n this.data.cooldowns[insightKey] = Date.now();\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Get active (non-dismissed) insights\n * \n * Returns insights sorted by priority (highest first),\n * limited to the specified count.\n */\n getActiveInsights(limit: number = 5): Insight[] {\n return this.data.insights\n .filter(i => !i.dismissed)\n .sort((a, b) => b.priority - a.priority)\n .slice(0, limit);\n }\n \n /**\n * Get all insights (including dismissed)\n */\n getAllInsights(): Insight[] {\n return [...this.data.insights];\n }\n \n /**\n * Dismiss an insight by ID\n */\n async dismissInsight(insightId: string): Promise<boolean> {\n await this.load();\n \n const insight = this.data.insights.find(i => i.id === insightId);\n if (!insight) {\n return false;\n }\n \n insight.dismissed = true;\n \n // Track permanently dismissed IDs\n if (!this.data.dismissedIds.includes(insightId)) {\n this.data.dismissedIds.push(insightId);\n \n // Keep only last 500 dismissed IDs\n if (this.data.dismissedIds.length > 500) {\n this.data.dismissedIds = this.data.dismissedIds.slice(-500);\n }\n }\n \n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Remove an insight entirely\n */\n async removeInsight(insightId: string): Promise<boolean> {\n await this.load();\n \n const index = this.data.insights.findIndex(i => i.id === insightId);\n if (index === -1) {\n return false;\n }\n \n this.data.insights.splice(index, 1);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Clear all cooldowns\n */\n async clearCooldowns(): Promise<void> {\n await this.load();\n this.data.cooldowns = {};\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Get insight by ID\n */\n getInsight(insightId: string): Insight | undefined {\n return this.data.insights.find(i => i.id === insightId);\n }\n \n /**\n * Update an existing insight\n */\n async updateInsight(insightId: string, updates: Partial<Insight>): Promise<boolean> {\n await this.load();\n \n const insight = this.data.insights.find(i => i.id === insightId);\n if (!insight) {\n return false;\n }\n \n Object.assign(insight, updates);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Get insights by category\n */\n getInsightsByCategory(category: Insight['category']): Insight[] {\n return this.data.insights.filter(i => i.category === category && !i.dismissed);\n }\n \n /**\n * Get insights by type\n */\n getInsightsByType(type: Insight['type']): Insight[] {\n return this.data.insights.filter(i => i.type === type && !i.dismissed);\n }\n \n /**\n * Get insights from the last N hours\n */\n getRecentInsights(hours: number = 24): Insight[] {\n const cutoff = Date.now() - (hours * 60 * 60 * 1000);\n return this.data.insights.filter(i => i.timestamp >= cutoff);\n }\n \n /**\n * Get statistics about insights\n */\n getStats(): {\n total: number;\n active: number;\n dismissed: number;\n byCategory: Record<string, number>;\n byType: Record<string, number>;\n } {\n const stats = {\n total: this.data.insights.length,\n active: 0,\n dismissed: 0,\n byCategory: {} as Record<string, number>,\n byType: {} as Record<string, number>,\n };\n \n for (const insight of this.data.insights) {\n if (insight.dismissed) {\n stats.dismissed++;\n } else {\n stats.active++;\n }\n \n stats.byCategory[insight.category] = (stats.byCategory[insight.category] || 0) + 1;\n stats.byType[insight.type] = (stats.byType[insight.type] || 0) + 1;\n }\n \n return stats;\n }\n \n /**\n * Prune old insights (older than N days)\n */\n async pruneOldInsights(daysToKeep: number = 30): Promise<number> {\n await this.load();\n \n const cutoff = Date.now() - (daysToKeep * 24 * 60 * 60 * 1000);\n const originalCount = this.data.insights.length;\n \n this.data.insights = this.data.insights.filter(i => i.timestamp >= cutoff);\n \n const pruned = originalCount - this.data.insights.length;\n if (pruned > 0) {\n this.dirty = true;\n await this.save();\n }\n \n return pruned;\n }\n \n /**\n * Check if the store has been loaded\n */\n isLoaded(): boolean {\n return this.loaded;\n }\n \n /**\n * Force reload from disk\n */\n async reload(): Promise<InsightStoreData> {\n this.loaded = false;\n this.dirty = false;\n return this.load();\n }\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst insightStores: Map<string, InsightStore> = new Map();\n\n/**\n * Get the InsightStore for a project (singleton per project)\n */\nexport function getInsightStore(projectPath: string): InsightStore {\n let store = insightStores.get(projectPath);\n if (!store) {\n store = new InsightStore(projectPath);\n insightStores.set(projectPath, store);\n }\n return store;\n}\n\n/**\n * Clear all InsightStore instances (for testing)\n */\nexport function clearInsightStores(): void {\n insightStores.clear();\n}\n"],"mappings":"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","names":[]}