@wrongstack/plugins 0.293.0 → 0.295.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +7 -71
  2. package/dist/accessibility-auditor/index.d.ts +1 -1
  3. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  4. package/dist/accessibility-auditor.js +50 -33
  5. package/dist/agent-handoff/index.d.ts +1 -1
  6. package/dist/agent-handoff/index.d.ts.map +1 -1
  7. package/dist/agent-handoff.js +30 -1
  8. package/dist/api-compatibility-gate/index.d.ts +1 -1
  9. package/dist/api-compatibility-gate/index.d.ts.map +1 -1
  10. package/dist/api-compatibility-gate.js +21 -16
  11. package/dist/audit/index.d.ts +386 -0
  12. package/dist/audit/index.d.ts.map +1 -0
  13. package/dist/audit.d.ts +1 -0
  14. package/dist/audit.js +454 -0
  15. package/dist/auto-doc/index.d.ts +1 -1
  16. package/dist/auto-doc/index.d.ts.map +1 -1
  17. package/dist/auto-doc.js +3 -1
  18. package/dist/auto-escalate/index.d.ts +1 -1
  19. package/dist/auto-escalate/index.d.ts.map +1 -1
  20. package/dist/auto-i18n-extractor/index.d.ts +1 -1
  21. package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
  22. package/dist/auto-i18n-extractor.js +7 -1
  23. package/dist/branch-guard/index.d.ts +1 -1
  24. package/dist/branch-guard/index.d.ts.map +1 -1
  25. package/dist/branch-guard.js +111 -1
  26. package/dist/catalog.d.ts +5 -30
  27. package/dist/catalog.d.ts.map +1 -1
  28. package/dist/changelog-writer/index.d.ts +1 -1
  29. package/dist/changelog-writer/index.d.ts.map +1 -1
  30. package/dist/changelog-writer.js +137 -3
  31. package/dist/checkpoint/index.d.ts +3 -1
  32. package/dist/checkpoint/index.d.ts.map +1 -1
  33. package/dist/checkpoint.js +41 -16
  34. package/dist/code-metrics/index.d.ts +1 -1
  35. package/dist/code-metrics/index.d.ts.map +1 -1
  36. package/dist/code-metrics.js +34 -29
  37. package/dist/commit-validator/index.d.ts +1 -1
  38. package/dist/commit-validator/index.d.ts.map +1 -1
  39. package/dist/commit-validator.js +17 -7
  40. package/dist/config-validator/index.d.ts +1 -1
  41. package/dist/config-validator/index.d.ts.map +1 -1
  42. package/dist/context-pins/index.d.ts +1 -1
  43. package/dist/context-pins/index.d.ts.map +1 -1
  44. package/dist/context-pins.js +6 -5
  45. package/dist/cost-tracker/index.d.ts +1 -1
  46. package/dist/cost-tracker/index.d.ts.map +1 -1
  47. package/dist/cost-tracker.js +109 -2
  48. package/dist/cron/index.d.ts +1 -1
  49. package/dist/cron/index.d.ts.map +1 -1
  50. package/dist/cron.js +1 -0
  51. package/dist/dead-code-detector/index.d.ts +1 -1
  52. package/dist/dead-code-detector/index.d.ts.map +1 -1
  53. package/dist/dead-code-detector.js +31 -18
  54. package/dist/dep-guard/index.d.ts +1 -1
  55. package/dist/dep-guard/index.d.ts.map +1 -1
  56. package/dist/dependency-vulnerability-gate/index.d.ts +1 -1
  57. package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -1
  58. package/dist/dependency-vulnerability-gate.js +67 -20
  59. package/dist/diff-summary/index.d.ts +1 -1
  60. package/dist/diff-summary/index.d.ts.map +1 -1
  61. package/dist/diff-summary.js +128 -30
  62. package/dist/doc-sync-guard/index.d.ts +1 -1
  63. package/dist/doc-sync-guard/index.d.ts.map +1 -1
  64. package/dist/doc-sync-guard.js +7 -1
  65. package/dist/duplicate-code-detector/index.d.ts +26 -1
  66. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  67. package/dist/duplicate-code-detector.js +280 -69
  68. package/dist/error-lens/index.d.ts +1 -1
  69. package/dist/error-lens/index.d.ts.map +1 -1
  70. package/dist/factories/index.d.ts +4 -0
  71. package/dist/factories/index.d.ts.map +1 -0
  72. package/dist/factories.d.ts +1 -0
  73. package/dist/factories.js +74 -0
  74. package/dist/feature-flag-tracker/index.d.ts +1 -1
  75. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  76. package/dist/feature-flag-tracker.js +59 -33
  77. package/dist/file-watcher/index.d.ts +1 -1
  78. package/dist/file-watcher/index.d.ts.map +1 -1
  79. package/dist/file-watcher.js +6 -7
  80. package/dist/format-on-save/index.d.ts +3 -1
  81. package/dist/format-on-save/index.d.ts.map +1 -1
  82. package/dist/format-on-save.js +289 -59
  83. package/dist/generated-plugin-exports.d.ts +65 -0
  84. package/dist/generated-plugin-exports.d.ts.map +1 -0
  85. package/dist/git-autocommit/index.d.ts +1 -1
  86. package/dist/git-autocommit/index.d.ts.map +1 -1
  87. package/dist/import-organizer/index.d.ts +1 -1
  88. package/dist/import-organizer/index.d.ts.map +1 -1
  89. package/dist/import-organizer.js +141 -20
  90. package/dist/index.d.ts +4 -183
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +18298 -17279
  93. package/dist/injection-shield/index.d.ts +1 -1
  94. package/dist/injection-shield/index.d.ts.map +1 -1
  95. package/dist/interface-contract-guard/index.d.ts +1 -1
  96. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  97. package/dist/interface-contract-guard.js +87 -53
  98. package/dist/knowledge-graph/index.d.ts +1 -1
  99. package/dist/knowledge-graph/index.d.ts.map +1 -1
  100. package/dist/knowledge-graph.js +7 -6
  101. package/dist/license-audit-gate/index.d.ts +1 -1
  102. package/dist/license-audit-gate/index.d.ts.map +1 -1
  103. package/dist/lint-gate/index.d.ts +1 -1
  104. package/dist/lint-gate/index.d.ts.map +1 -1
  105. package/dist/lint-gate.js +112 -1
  106. package/dist/llm-cache/index.d.ts +5 -1
  107. package/dist/llm-cache/index.d.ts.map +1 -1
  108. package/dist/llm-cache.js +16 -8
  109. package/dist/loop-breaker/index.d.ts +1 -1
  110. package/dist/loop-breaker/index.d.ts.map +1 -1
  111. package/dist/loop-breaker.js +25 -9
  112. package/dist/manifest/index.d.ts +16 -0
  113. package/dist/manifest/index.d.ts.map +1 -0
  114. package/dist/manifest.d.ts +1 -0
  115. package/dist/manifest.js +152 -0
  116. package/dist/migration-planner/index.d.ts +1 -1
  117. package/dist/migration-planner/index.d.ts.map +1 -1
  118. package/dist/migration-planner.js +5 -1
  119. package/dist/model-router/index.d.ts +1 -1
  120. package/dist/model-router/index.d.ts.map +1 -1
  121. package/dist/notify-hub/index.d.ts +1 -1
  122. package/dist/notify-hub/index.d.ts.map +1 -1
  123. package/dist/notify-hub/webhook-channel.d.ts +1 -1
  124. package/dist/notify-hub/webhook-channel.d.ts.map +1 -1
  125. package/dist/notify-hub.js +41 -4
  126. package/dist/path-guard/index.d.ts +1 -1
  127. package/dist/path-guard/index.d.ts.map +1 -1
  128. package/dist/performance-regression-gate/index.d.ts +1 -1
  129. package/dist/performance-regression-gate/index.d.ts.map +1 -1
  130. package/dist/plugin-stack-observer/index.d.ts +1 -1
  131. package/dist/plugin-stack-observer/index.d.ts.map +1 -1
  132. package/dist/pr-drafter/index.d.ts +1 -1
  133. package/dist/pr-drafter/index.d.ts.map +1 -1
  134. package/dist/pr-drafter.js +28 -29
  135. package/dist/process-guard/index.d.ts +1 -1
  136. package/dist/process-guard/index.d.ts.map +1 -1
  137. package/dist/prompt-firewall/index.d.ts +1 -1
  138. package/dist/prompt-firewall/index.d.ts.map +1 -1
  139. package/dist/prompt-firewall.js +140 -11
  140. package/dist/refactor-suggester/index.d.ts +1 -1
  141. package/dist/refactor-suggester/index.d.ts.map +1 -1
  142. package/dist/refactor-suggester.js +148 -33
  143. package/dist/release-notes-generator/index.d.ts +1 -1
  144. package/dist/release-notes-generator/index.d.ts.map +1 -1
  145. package/dist/release-notes-generator.js +29 -22
  146. package/dist/runtime/bounded-map.d.ts +86 -0
  147. package/dist/runtime/bounded-map.d.ts.map +1 -0
  148. package/dist/runtime/credential-patterns.d.ts +42 -0
  149. package/dist/runtime/credential-patterns.d.ts.map +1 -0
  150. package/dist/runtime/index.d.ts +18 -0
  151. package/dist/runtime/index.d.ts.map +1 -1
  152. package/dist/runtime/llm.d.ts +1 -1
  153. package/dist/runtime/llm.d.ts.map +1 -1
  154. package/dist/runtime/local-bin.d.ts +120 -0
  155. package/dist/runtime/local-bin.d.ts.map +1 -0
  156. package/dist/runtime/safe-json.d.ts +25 -0
  157. package/dist/runtime/safe-json.d.ts.map +1 -0
  158. package/dist/runtime.js +332 -22
  159. package/dist/schema-evolution-guard/index.d.ts +1 -1
  160. package/dist/schema-evolution-guard/index.d.ts.map +1 -1
  161. package/dist/schema-evolution-guard.js +7 -1
  162. package/dist/secret-scanner/index.d.ts +1 -1
  163. package/dist/secret-scanner/index.d.ts.map +1 -1
  164. package/dist/secret-scanner.js +181 -48
  165. package/dist/security-hotspot-scanner/index.d.ts +1 -1
  166. package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
  167. package/dist/security-hotspot-scanner.js +158 -20
  168. package/dist/semantic-search-indexer/index.d.ts +1 -1
  169. package/dist/semantic-search-indexer/index.d.ts.map +1 -1
  170. package/dist/semantic-search-indexer.js +7 -1
  171. package/dist/semver-bump/index.d.ts +1 -1
  172. package/dist/semver-bump/index.d.ts.map +1 -1
  173. package/dist/semver-bump.js +97 -43
  174. package/dist/session-recap/index.d.ts +1 -1
  175. package/dist/session-recap/index.d.ts.map +1 -1
  176. package/dist/shell-check/index.d.ts +1 -1
  177. package/dist/shell-check/index.d.ts.map +1 -1
  178. package/dist/smart-rename/index.d.ts +1 -1
  179. package/dist/smart-rename/index.d.ts.map +1 -1
  180. package/dist/spec-linker/index.d.ts +1 -1
  181. package/dist/spec-linker/index.d.ts.map +1 -1
  182. package/dist/spec-linker.js +222 -20772
  183. package/dist/template-engine/index.d.ts +1 -1
  184. package/dist/template-engine/index.d.ts.map +1 -1
  185. package/dist/template-engine.js +34 -8
  186. package/dist/test-coverage-gate/index.d.ts +1 -1
  187. package/dist/test-coverage-gate/index.d.ts.map +1 -1
  188. package/dist/test-coverage-gate.js +34 -14
  189. package/dist/test-flake-detector/index.d.ts +1 -1
  190. package/dist/test-flake-detector/index.d.ts.map +1 -1
  191. package/dist/test-flake-detector.js +31 -20
  192. package/dist/test-generator/index.d.ts +1 -1
  193. package/dist/test-generator/index.d.ts.map +1 -1
  194. package/dist/test-runner-gate/index.d.ts +1 -1
  195. package/dist/test-runner-gate/index.d.ts.map +1 -1
  196. package/dist/test-runner-gate.js +132 -9
  197. package/dist/todo-listener/index.d.ts +1 -32
  198. package/dist/todo-listener/index.d.ts.map +1 -1
  199. package/dist/todo-listener.js +30 -1
  200. package/dist/todo-tracker/index.d.ts +1 -1
  201. package/dist/todo-tracker/index.d.ts.map +1 -1
  202. package/dist/todo-tracker.js +3 -4
  203. package/dist/token-budget/index.d.ts +1 -1
  204. package/dist/token-budget/index.d.ts.map +1 -1
  205. package/dist/token-throttle/index.d.ts +1 -1
  206. package/dist/token-throttle/index.d.ts.map +1 -1
  207. package/dist/token-throttle.js +17 -2
  208. package/dist/type-gate/index.d.ts +1 -1
  209. package/dist/type-gate/index.d.ts.map +1 -1
  210. package/dist/type-gate.js +106 -19
  211. package/package.json +80 -68
@@ -1,20 +1,44 @@
1
- // src/secret-scanner/index.ts
2
- var BASE_PATTERNS = [
1
+ // src/runtime/credential-patterns.ts
2
+ var CREDENTIAL_PATTERNS = [
3
3
  // LLM provider keys
4
4
  {
5
5
  type: "anthropic_key",
6
6
  regex: /(?<![A-Za-z0-9])sk-ant-api\d+-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g
7
7
  },
8
- { type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g },
9
- // GitHub
8
+ { type: "openai_key", regex: /(?<![A-Za-z0-9])sk-(?!ant)(?:proj-)?[A-Za-z0-9_-]{20,}(?![A-Za-z0-9])/g },
9
+ // GitHub. `ghp_` is only the personal-access-token prefix — the OAuth
10
+ // (`gho_`), user-to-server (`ghu_`), server-to-server (`ghs_`) and
11
+ // refresh (`ghr_`) tokens grant the same or broader access and were
12
+ // previously not detected at all.
10
13
  { type: "github_pat", regex: /(?<![A-Za-z0-9])ghp_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g },
14
+ {
15
+ type: "github_oauth_token",
16
+ regex: /(?<![A-Za-z0-9])gh[ousr]_[A-Za-z0-9]{36,}(?![A-Za-z0-9])/g
17
+ },
11
18
  { type: "github_pat_v2", regex: /(?<![A-Za-z0-9])github_pat_[A-Za-z0-9_]{50,}(?![A-Za-z0-9])/g },
19
+ // GitLab
20
+ { type: "gitlab_pat", regex: /(?<![A-Za-z0-9])glpat-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
21
+ {
22
+ type: "gitlab_runner_token",
23
+ regex: /(?<![A-Za-z0-9])glrt-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
24
+ },
25
+ // npm — a leaked publish token is a supply-chain compromise.
26
+ { type: "npm_token", regex: /(?<![A-Za-z0-9])npm_[A-Za-z0-9]{36}(?![A-Za-z0-9])/g },
12
27
  // AWS
13
28
  { type: "aws_access_key", regex: /(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])/g },
14
29
  // GCP
15
30
  { type: "gcp_key", regex: /(?<![A-Za-z0-9])AIza[0-9A-Za-z_-]{35}(?![A-Za-z0-9])/g },
16
- // Slack
17
- { type: "slack_token", regex: /(?<![A-Za-z0-9-])xox[abpos]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g },
31
+ // Slack. `xoxe` (token-rotation) and `xapp` (app-level) were missing;
32
+ // both are as sensitive as the bot/user tokens already covered.
33
+ {
34
+ type: "slack_token",
35
+ regex: /(?<![A-Za-z0-9-])xox[abposer]-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g
36
+ },
37
+ { type: "slack_app_token", regex: /(?<![A-Za-z0-9-])xapp-\d-[A-Za-z0-9-]{10,}(?![A-Za-z0-9-])/g },
38
+ {
39
+ type: "slack_webhook",
40
+ regex: /https:\/\/hooks\.slack\.com\/services\/T[A-Za-z0-9_-]+\/B[A-Za-z0-9_-]+\/[A-Za-z0-9]{16,}/g
41
+ },
18
42
  // Stripe
19
43
  {
20
44
  type: "stripe_key",
@@ -25,7 +49,7 @@ var BASE_PATTERNS = [
25
49
  // Telegram
26
50
  {
27
51
  type: "telegram_bot_token",
28
- regex: /\/bot\d+:[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
52
+ regex: /(?:(?<![A-Za-z0-9_])|(?<=(?:^|[^A-Za-z0-9_])bot))\d+:[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
29
53
  },
30
54
  // JWT
31
55
  {
@@ -35,29 +59,93 @@ var BASE_PATTERNS = [
35
59
  // Private keys
36
60
  {
37
61
  type: "private_key",
38
- regex: /(?:^|\n)-----BEGIN (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----[\s\S]*?-----END (?:RSA|EC|OPENSSH|DSA|PGP)? ?PRIVATE KEY-----(?!\S)/g
62
+ regex: /(?:^|\n)(?:-----BEGIN (?:RSA|EC|OPENSSH|DSA)? ?PRIVATE KEY-----[\s\S]*?-----END (?:RSA|EC|OPENSSH|DSA)? ?PRIVATE KEY-----|-----BEGIN PGP PRIVATE KEY BLOCK-----[\s\S]*?-----END PGP PRIVATE KEY BLOCK-----)(?!\S)/g
39
63
  },
40
64
  // AI/ML provider tokens
41
65
  { type: "huggingface_token", regex: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{34}(?![A-Za-z0-9])/g },
42
66
  { type: "replicate_token", regex: /(?<![A-Za-z0-9])r8_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
43
67
  { type: "perplexity_key", regex: /(?<![A-Za-z0-9])pplx-[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
44
68
  { type: "groq_key", regex: /(?<![A-Za-z0-9])gsk_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
69
+ // SaaS / infrastructure tokens — each grants API access on the user's
70
+ // account, and each was previously invisible to this gate.
71
+ { type: "sendgrid_key", regex: /(?<![A-Za-z0-9])SG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
72
+ { type: "digitalocean_token", regex: /(?<![A-Za-z0-9])dop_v1_[a-f0-9]{64}(?![A-Za-z0-9])/g },
73
+ { type: "doppler_token", regex: /(?<![A-Za-z0-9])dp\.(?:pt|st|sa|scim|audit)\.[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
74
+ { type: "shopify_token", regex: /(?<![A-Za-z0-9])shp(?:at|ca|pa|ss)_[a-fA-F0-9]{32}(?![A-Za-z0-9])/g },
75
+ { type: "docker_pat", regex: /(?<![A-Za-z0-9])dckr_pat_[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
76
+ { type: "linear_key", regex: /(?<![A-Za-z0-9])lin_api_[A-Za-z0-9]{40,}(?![A-Za-z0-9])/g },
77
+ { type: "atlassian_token", regex: /(?<![A-Za-z0-9])ATATT3[A-Za-z0-9_\-=]{40,}(?![A-Za-z0-9_\-=])/g },
78
+ { type: "square_token", regex: /(?<![A-Za-z0-9])(?:sq0(?:atp|csp)-|EAAA)[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g },
79
+ {
80
+ type: "azure_storage_key",
81
+ regex: /AccountKey=[A-Za-z0-9+/]{80,}={0,2}/g
82
+ },
83
+ {
84
+ type: "google_oauth_client_secret",
85
+ regex: /(?<![A-Za-z0-9_-])GOCSPX-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])/g
86
+ },
45
87
  // Bearer tokens
46
88
  {
47
89
  type: "bearer_token",
48
- regex: /(?:^|[^A-Za-z0-9_.~+/-])Bearer\s+[A-Za-z0-9._~+/-]{12,512}=*(?![A-Za-z0-9._~+/-])/g
90
+ regex: /(?<![A-Za-z0-9_.~+/-])Bearer\s+[A-Za-z0-9._~+/-]{12,512}=*(?![A-Za-z0-9._~+/-])/g
91
+ },
92
+ // Database URIs. Require password-bearing user-info; credential-free values stay scannable.
93
+ { type: "mongodb_uri", regex: /mongodb(?:\+srv)?:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g },
94
+ {
95
+ type: "postgres_uri",
96
+ // Query parsers decode percent-encoded parameter names. Recognize each
97
+ // encoded character in `password` so mixed forms such as `pass%77ord`
98
+ // cannot bypass detection while keeping the scan strictly bounded.
99
+ regex: /postgres(?:ql)?:\/\/(?:[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+|[^&\s?"'`#]{1,2048}\?(?:(?!(?:p|%70)(?:a|%61)(?:s|%73)(?:s|%73)(?:w|%77)(?:o|%6[fF])(?:r|%72)(?:d|%64)=)[^&\s#"'`]{1,256}&){0,32}(?:p|%70)(?:a|%61)(?:s|%73)(?:s|%73)(?:w|%77)(?:o|%6[fF])(?:r|%72)(?:d|%64)=[^&\s#"'`]{1,4096})/g
49
100
  },
50
- // Database URIs
51
- { type: "mongodb_uri", regex: /mongodb(?:\+srv)?:\/\/[^\s"'`]+/g },
52
- { type: "postgres_uri", regex: /postgres(?:ql)?:\/\/[^\s"'`]+/g },
53
- { type: "mysql_uri", regex: /mysql:\/\/[^\s"'`]+/g },
54
- { type: "redis_uri", regex: /redis:\/\/[^\s"'`]+/g }
101
+ { type: "mysql_uri", regex: /mysql:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g },
102
+ { type: "redis_uri", regex: /redis:\/\/[^\s:/@"'`]*:[^\s/@"'`]+@[^\s"'`]+/g }
55
103
  ];
104
+ function cloneCredentialPatterns() {
105
+ return CREDENTIAL_PATTERNS.map((p) => ({
106
+ type: p.type,
107
+ regex: new RegExp(p.regex.source, p.regex.flags)
108
+ }));
109
+ }
110
+
111
+ // src/secret-scanner/index.ts
112
+ var BASE_PATTERNS = cloneCredentialPatterns();
56
113
  var PATTERNS = [...BASE_PATTERNS];
114
+ var patternCacheKey = "";
115
+ var GROUP_INDEX_OF_PATTERN = [];
57
116
  var COMBINED_REGEX = buildCombinedRegex(PATTERNS);
58
- var RE_DOS_MAX_SCAN_LENGTH = 1e5;
117
+ var SCAN_WINDOW_LENGTH = 1e5;
118
+ var SCAN_WINDOW_OVERLAP = 4096;
119
+ var MAX_TOTAL_SCAN_LENGTH = 8 * 1024 * 1024;
120
+ var TOO_LARGE_MARKER = "unscannable_oversized_input";
59
121
  var RE_DOS_TIMEOUT_MS = 100;
122
+ function countCaptureGroups(source) {
123
+ try {
124
+ return new RegExp(`${source}|`).exec("").length - 1;
125
+ } catch {
126
+ return 0;
127
+ }
128
+ }
129
+ function patternTypeForGroups(groups) {
130
+ for (let i = 0; i < PATTERNS.length; i++) {
131
+ const at = GROUP_INDEX_OF_PATTERN[i];
132
+ if (at !== void 0 && groups[at] !== void 0) return PATTERNS[i].type;
133
+ }
134
+ return void 0;
135
+ }
60
136
  function buildCombinedRegex(patterns) {
137
+ const newCacheKey = JSON.stringify(patterns.map((p) => [p.type, p.regex.source]));
138
+ if (newCacheKey === patternCacheKey && COMBINED_REGEX) {
139
+ return COMBINED_REGEX;
140
+ }
141
+ patternCacheKey = newCacheKey;
142
+ const offsets = [];
143
+ let cursor = 0;
144
+ for (const p of patterns) {
145
+ offsets.push(cursor);
146
+ cursor += 1 + countCaptureGroups(p.regex.source);
147
+ }
148
+ GROUP_INDEX_OF_PATTERN = offsets;
61
149
  return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
62
150
  }
63
151
  var state = {
@@ -75,30 +163,38 @@ var state = {
75
163
  /** PostToolUse hook handle so teardown can unregister. */
76
164
  postHookUnregister: null
77
165
  };
78
- function findMatches(text) {
79
- if (!text) return [];
80
- if (text.length > RE_DOS_MAX_SCAN_LENGTH) return [];
81
- const found = /* @__PURE__ */ new Set();
166
+ function scanWindow(window, found, startTime) {
82
167
  COMBINED_REGEX.lastIndex = 0;
83
168
  let m;
84
- const startTime = performance.now();
85
- while ((m = COMBINED_REGEX.exec(text)) !== null) {
169
+ while ((m = COMBINED_REGEX.exec(window)) !== null) {
86
170
  if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
87
171
  throw new Error(
88
- `secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${text.length}-char input`
172
+ `secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${window.length}-char window`
89
173
  );
90
174
  }
91
- for (let i = 0; i < PATTERNS.length; i++) {
92
- if (m[i + 1] !== void 0) {
93
- found.add(PATTERNS[i].type);
94
- break;
95
- }
96
- }
175
+ const type = patternTypeForGroups(m.slice(1));
176
+ if (type !== void 0) found.add(type);
97
177
  if (m.index === COMBINED_REGEX.lastIndex) {
98
178
  COMBINED_REGEX.lastIndex += 1;
99
179
  }
100
180
  }
101
- return Array.from(found);
181
+ }
182
+ function findMatches(text) {
183
+ if (!text) return [];
184
+ const found = /* @__PURE__ */ new Set();
185
+ const startTime = performance.now();
186
+ if (text.length <= SCAN_WINDOW_LENGTH) {
187
+ scanWindow(text, found, startTime);
188
+ return Array.from(found).sort();
189
+ }
190
+ if (text.length > MAX_TOTAL_SCAN_LENGTH) {
191
+ return [TOO_LARGE_MARKER];
192
+ }
193
+ const stride = SCAN_WINDOW_LENGTH - SCAN_WINDOW_OVERLAP;
194
+ for (let offset = 0; offset < text.length; offset += stride) {
195
+ scanWindow(text.slice(offset, offset + SCAN_WINDOW_LENGTH), found, startTime);
196
+ }
197
+ return Array.from(found).sort();
102
198
  }
103
199
  function scanInput(input, depth = 0) {
104
200
  if (input === null || input === void 0) return null;
@@ -123,30 +219,55 @@ function scanInput(input, depth = 0) {
123
219
  }
124
220
  return null;
125
221
  }
222
+ function redactString(text) {
223
+ if (text.length > SCAN_WINDOW_LENGTH) {
224
+ return { ok: false, reason: "oversized_input" };
225
+ }
226
+ const startTime = performance.now();
227
+ let cursor = 0;
228
+ let output = "";
229
+ COMBINED_REGEX.lastIndex = 0;
230
+ let match;
231
+ while ((match = COMBINED_REGEX.exec(text)) !== null) {
232
+ if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
233
+ return { ok: false, reason: "oversized_input" };
234
+ }
235
+ const type = patternTypeForGroups(match.slice(1));
236
+ output += text.slice(cursor, match.index);
237
+ output += `[REDACTED:${type ?? "unknown"}]`;
238
+ cursor = COMBINED_REGEX.lastIndex;
239
+ if (match.index === COMBINED_REGEX.lastIndex) {
240
+ COMBINED_REGEX.lastIndex += 1;
241
+ }
242
+ }
243
+ if (cursor === 0) return { ok: true, value: text };
244
+ return { ok: true, value: output + text.slice(cursor) };
245
+ }
126
246
  function redactInput(input, depth = 0) {
127
- if (input === null || input === void 0) return input;
128
- if (depth > 50) return input;
247
+ if (input === null || input === void 0) return { ok: true, value: input };
248
+ if (depth > 50) return { ok: false, reason: "maximum_depth_exceeded" };
129
249
  if (typeof input === "string") {
130
- return input.replace(COMBINED_REGEX, (_match, ...groups) => {
131
- for (let i = 0; i < PATTERNS.length; i++) {
132
- if (groups[i] !== void 0) {
133
- return `[REDACTED:${PATTERNS[i].type}]`;
134
- }
135
- }
136
- return "[REDACTED:unknown]";
137
- });
250
+ return redactString(input);
138
251
  }
139
252
  if (Array.isArray(input)) {
140
- return input.map((item) => redactInput(item, depth + 1));
253
+ const out = [];
254
+ for (const item of input) {
255
+ const redacted = redactInput(item, depth + 1);
256
+ if (!redacted.ok) return redacted;
257
+ out.push(redacted.value);
258
+ }
259
+ return { ok: true, value: out };
141
260
  }
142
261
  if (typeof input === "object") {
143
262
  const out = {};
144
263
  for (const [k, v] of Object.entries(input)) {
145
- out[k] = redactInput(v, depth + 1);
264
+ const redacted = redactInput(v, depth + 1);
265
+ if (!redacted.ok) return redacted;
266
+ out[k] = redacted.value;
146
267
  }
147
- return out;
268
+ return { ok: true, value: out };
148
269
  }
149
- return input;
270
+ return { ok: true, value: input };
150
271
  }
151
272
  var DEFAULTS = {
152
273
  matcher: "bash|write|edit",
@@ -206,20 +327,21 @@ function buildHook(cfg, log) {
206
327
  }
207
328
  if (cfg.mode === "redact") {
208
329
  const redacted = redactInput(input.toolInput);
209
- if (redacted !== null && typeof redacted === "object" && !Array.isArray(redacted)) {
330
+ if (redacted.ok && redacted.value !== null && typeof redacted.value === "object" && !Array.isArray(redacted.value)) {
210
331
  state.redactCount += 1;
211
332
  log.info(`[secret-scanner] redacted ${toolName} \u2014 matched: ${summary}`);
212
333
  return {
213
334
  decision: "allow",
214
- modifiedInput: redacted,
335
+ modifiedInput: redacted.value,
215
336
  additionalContext: `secret-scanner: redacted ${matched.length} credential pattern(s) from the ${toolName} arguments before execution.`
216
337
  };
217
338
  }
218
339
  state.blockCount += 1;
219
340
  state.lastBlock = { toolName, matchedTypes: matched, when };
341
+ const detail = !redacted.ok ? redacted.reason === "oversized_input" ? "an input field exceeds the safe scan limit" : "the input exceeds the safe nesting depth" : "the input has a non-object shape";
220
342
  return {
221
343
  decision: "block",
222
- reason: `secret-scanner: cannot safely redact '${toolName}' input (non-object shape); refusing to run.`
344
+ reason: `secret-scanner: cannot safely redact '${toolName}' because ${detail}; refusing to run.`
223
345
  };
224
346
  }
225
347
  state.allowCount += 1;
@@ -237,10 +359,21 @@ function buildPostHook(cfg, log) {
237
359
  const matched = findMatches(result.content);
238
360
  if (matched.length === 0) return;
239
361
  const toolName = input.toolName ?? "unknown";
240
- const summary = matched.join(", ");
362
+ const oversized = matched.includes(TOO_LARGE_MARKER);
363
+ const credentialMatches = matched.filter((type) => type !== TOO_LARGE_MARKER);
364
+ if (oversized && credentialMatches.length === 0) {
365
+ log.warn(
366
+ `[secret-scanner] POST-TOOL UNSCANNABLE: ${toolName} output exceeds ${MAX_TOTAL_SCAN_LENGTH} characters`
367
+ );
368
+ return {
369
+ additionalContext: `
370
+ \u26A0\uFE0F secret-scanner: the output of '${toolName}' exceeds the safe scan limit and could not be inspected for plaintext credentials. Do not treat this output as verified clean; avoid echoing, storing, committing, or transmitting it until it can be reviewed in smaller bounded sections.`
371
+ };
372
+ }
373
+ const summary = credentialMatches.join(", ");
241
374
  const when = (/* @__PURE__ */ new Date()).toISOString();
242
375
  state.leakCount += 1;
243
- state.lastLeak = { toolName, matchedTypes: matched, when };
376
+ state.lastLeak = { toolName, matchedTypes: credentialMatches, when };
244
377
  log.warn(`[secret-scanner] POST-TOOL LEAK: ${toolName} output matched ${summary}`);
245
378
  return {
246
379
  additionalContext: `
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * @public
24
24
  */
25
- import type { Plugin } from '@wrongstack/core';
25
+ import type { Plugin } from '@wrongstack/core/types';
26
26
  declare const plugin: Plugin;
27
27
  export default plugin;
28
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security-hotspot-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAgQ/C,QAAA,MAAM,MAAM,EAAE,MAiQb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security-hotspot-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAkRrD,QAAA,MAAM,MAAM,EAAE,MAkQb,CAAC;eAEa,MAAM"}
@@ -1,9 +1,140 @@
1
1
  // src/security-hotspot-scanner/index.ts
2
- import { readdirSync, readFileSync, statSync } from "node:fs";
2
+ import { readdir, readFile, stat } from "node:fs/promises";
3
3
  import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
4
 
5
5
  // src/runtime/index.ts
6
6
  import { basename, extname, isAbsolute, relative, resolve } from "node:path";
7
+
8
+ // src/runtime/local-bin.ts
9
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
10
+
11
+ // src/runtime/bounded-map.ts
12
+ var BoundedMap = class {
13
+ map = /* @__PURE__ */ new Map();
14
+ max;
15
+ ttlMs;
16
+ now;
17
+ /** Entries dropped to stay under `max`. Surfaced by plugin health(). */
18
+ evictions = 0;
19
+ constructor(options) {
20
+ const normalizedMax = Math.floor(options.max);
21
+ this.max = Number.isSafeInteger(normalizedMax) ? Math.max(1, normalizedMax) : 1;
22
+ this.ttlMs = options.ttlMs;
23
+ this.now = options.now ?? Date.now;
24
+ }
25
+ expired(entry) {
26
+ return this.ttlMs !== void 0 && this.now() - entry.storedAt > this.ttlMs;
27
+ }
28
+ get(key) {
29
+ const entry = this.map.get(key);
30
+ if (entry === void 0) return void 0;
31
+ if (this.expired(entry)) {
32
+ this.map.delete(key);
33
+ return void 0;
34
+ }
35
+ this.map.delete(key);
36
+ this.map.set(key, entry);
37
+ return entry.value;
38
+ }
39
+ /**
40
+ * Read without promoting the key to most-recently-used. Use for
41
+ * diagnostics that must not perturb the eviction order.
42
+ */
43
+ peek(key) {
44
+ const entry = this.map.get(key);
45
+ if (entry === void 0 || this.expired(entry)) return void 0;
46
+ return entry.value;
47
+ }
48
+ has(key) {
49
+ const entry = this.map.get(key);
50
+ if (entry === void 0) return false;
51
+ if (this.expired(entry)) {
52
+ this.map.delete(key);
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ set(key, value) {
58
+ this.map.delete(key);
59
+ this.map.set(key, { value, storedAt: this.now() });
60
+ while (this.map.size > this.max) {
61
+ const coldest = this.map.keys().next().value;
62
+ if (coldest === void 0) break;
63
+ this.map.delete(coldest);
64
+ this.evictions += 1;
65
+ }
66
+ return this;
67
+ }
68
+ delete(key) {
69
+ return this.map.delete(key);
70
+ }
71
+ clear() {
72
+ this.map.clear();
73
+ this.evictions = 0;
74
+ }
75
+ get size() {
76
+ return this.map.size;
77
+ }
78
+ /** How many entries have been dropped to respect `max`, since the last clear. */
79
+ get evictionCount() {
80
+ return this.evictions;
81
+ }
82
+ /** Drop every expired entry. Cheap enough to call from a status tool. */
83
+ prune() {
84
+ if (this.ttlMs === void 0) return 0;
85
+ let removed = 0;
86
+ for (const [key, entry] of this.map) {
87
+ if (this.expired(entry)) {
88
+ this.map.delete(key);
89
+ removed += 1;
90
+ }
91
+ }
92
+ return removed;
93
+ }
94
+ /** Live (non-expired) entries, coldest first. */
95
+ *entries() {
96
+ for (const [key, entry] of this.map) {
97
+ if (!this.expired(entry)) yield [key, entry.value];
98
+ }
99
+ }
100
+ [Symbol.iterator]() {
101
+ return this.entries();
102
+ }
103
+ };
104
+ var BoundedSet = class {
105
+ inner;
106
+ constructor(options) {
107
+ this.inner = new BoundedMap(options);
108
+ }
109
+ has(value) {
110
+ return this.inner.has(value);
111
+ }
112
+ add(value) {
113
+ this.inner.set(value, true);
114
+ return this;
115
+ }
116
+ delete(value) {
117
+ return this.inner.delete(value);
118
+ }
119
+ clear() {
120
+ this.inner.clear();
121
+ }
122
+ get size() {
123
+ return this.inner.size;
124
+ }
125
+ /** How many entries have been dropped to respect `max`, since the last clear. */
126
+ get evictionCount() {
127
+ return this.inner.evictionCount;
128
+ }
129
+ *values() {
130
+ for (const [key] of this.inner) yield key;
131
+ }
132
+ [Symbol.iterator]() {
133
+ return this.values();
134
+ }
135
+ };
136
+
137
+ // src/runtime/index.ts
7
138
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
139
  function hasLeadingDash(arg) {
9
140
  return arg.length > 0 && arg.startsWith("-");
@@ -16,7 +147,8 @@ function withinProjectPath(projectRoot, candidate) {
16
147
  return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
17
148
  }
18
149
  function withinProject(p) {
19
- return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
150
+ const cwd = process.cwd();
151
+ return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
20
152
  }
21
153
 
22
154
  // src/security-hotspot-scanner/index.ts
@@ -29,7 +161,7 @@ var state = {
29
161
  skippedCount: 0,
30
162
  blockedCount: 0,
31
163
  lastResult: null,
32
- knownHotspots: /* @__PURE__ */ new Set(),
164
+ knownHotspots: new BoundedSet({ max: 5e3 }),
33
165
  hookUnregister: null
34
166
  };
35
167
  var DEFAULTS = {
@@ -38,14 +170,20 @@ var DEFAULTS = {
38
170
  maxFindings: 10,
39
171
  scanOnChange: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".py", ".java", ".go", ".rb", ".php"]
40
172
  };
173
+ var scanOnChangeSet = new Set(DEFAULTS.scanOnChange);
41
174
  function readConfig(raw) {
42
- if (!raw || typeof raw !== "object") return { ...DEFAULTS };
175
+ if (!raw || typeof raw !== "object") {
176
+ scanOnChangeSet = new Set(DEFAULTS.scanOnChange);
177
+ return { ...DEFAULTS };
178
+ }
43
179
  const r = raw;
180
+ const scanOnChange = Array.isArray(r["scanOnChange"]) ? r["scanOnChange"].filter((x) => typeof x === "string") : DEFAULTS.scanOnChange;
181
+ scanOnChangeSet = new Set(scanOnChange);
44
182
  return {
45
183
  enabled: r["enabled"] === true,
46
184
  severity: r["severity"] === "block" ? "block" : DEFAULTS.severity,
47
185
  maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 100 ? r["maxFindings"] : DEFAULTS.maxFindings,
48
- scanOnChange: Array.isArray(r["scanOnChange"]) ? r["scanOnChange"].filter((x) => typeof x === "string") : DEFAULTS.scanOnChange
186
+ scanOnChange
49
187
  };
50
188
  }
51
189
  var PATTERNS = [
@@ -101,7 +239,7 @@ function isSourceFile(filePath, extensions) {
101
239
  const lower = filePath.toLowerCase();
102
240
  return extensions.some((ext) => lower.endsWith(ext));
103
241
  }
104
- function scanPath(inputPath, cfg) {
242
+ async function scanPath(inputPath, cfg) {
105
243
  const start = Date.now();
106
244
  const root = process.cwd();
107
245
  const resolved = isAbsolute2(inputPath) ? resolve2(inputPath) : resolve2(root, inputPath);
@@ -118,10 +256,10 @@ function scanPath(inputPath, cfg) {
118
256
  let filesScanned = 0;
119
257
  const allFindings = [];
120
258
  const maxPerFile = Math.max(1, Math.floor(cfg.maxFindings / 2));
121
- const scanFile = (filePath) => {
259
+ const scanFile = async (filePath) => {
122
260
  if (!isSourceFile(filePath, cfg.scanOnChange)) return;
123
261
  try {
124
- const content = readFileSync(filePath, "utf-8");
262
+ const content = await readFile(filePath, "utf-8");
125
263
  filesScanned += 1;
126
264
  const findings = scanSource(content, maxPerFile);
127
265
  for (const f of findings) {
@@ -131,10 +269,10 @@ function scanPath(inputPath, cfg) {
131
269
  } catch {
132
270
  }
133
271
  };
134
- const walk = (dir) => {
272
+ const walk = async (dir) => {
135
273
  let entries;
136
274
  try {
137
- entries = readdirSync(dir);
275
+ entries = await readdir(dir);
138
276
  } catch {
139
277
  return;
140
278
  }
@@ -142,25 +280,25 @@ function scanPath(inputPath, cfg) {
142
280
  if (allFindings.length >= cfg.maxFindings) return;
143
281
  const full = resolve2(dir, entry);
144
282
  try {
145
- const st = statSync(full);
283
+ const st = await stat(full);
146
284
  if (st.isDirectory()) {
147
285
  if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "coverage") {
148
286
  continue;
149
287
  }
150
- walk(full);
288
+ await walk(full);
151
289
  } else if (st.isFile()) {
152
- scanFile(full);
290
+ await scanFile(full);
153
291
  }
154
292
  } catch {
155
293
  }
156
294
  }
157
295
  };
158
296
  try {
159
- const st = statSync(resolved);
297
+ const st = await stat(resolved);
160
298
  if (st.isDirectory()) {
161
- walk(resolved);
299
+ await walk(resolved);
162
300
  } else if (st.isFile()) {
163
- scanFile(resolved);
301
+ await scanFile(resolved);
164
302
  } else {
165
303
  return {
166
304
  path: inputPath,
@@ -238,7 +376,7 @@ var plugin = {
238
376
  state.hookUnregister = null;
239
377
  }
240
378
  const cfg = readConfig(api.config.extensions?.["security-hotspot-scanner"]);
241
- const hook = (input) => {
379
+ const hook = async (input) => {
242
380
  if (!cfg.enabled) return;
243
381
  if (input.toolResult?.isError) return;
244
382
  const inp = input.toolInput ?? {};
@@ -246,12 +384,12 @@ var plugin = {
246
384
  if (!sourcePath || typeof sourcePath !== "string") return;
247
385
  if (!withinProject(sourcePath)) return;
248
386
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
249
- if (!cfg.scanOnChange.includes(ext)) {
387
+ if (!scanOnChangeSet.has(ext)) {
250
388
  state.skippedCount += 1;
251
389
  return;
252
390
  }
253
391
  state.hookInvocationCount += 1;
254
- const result = scanPath(sourcePath, cfg);
392
+ const result = await scanPath(sourcePath, cfg);
255
393
  state.scanCount += 1;
256
394
  state.fileScanCount += result.filesScanned;
257
395
  if (!result.scanned) {
@@ -307,7 +445,7 @@ Review or remove the risky pattern(s).`;
307
445
  mutating: false,
308
446
  async execute(input) {
309
447
  if (!cfg.enabled) return { ok: false, error: "security-hotspot-scanner is disabled" };
310
- const result = scanPath(input.path, cfg);
448
+ const result = await scanPath(input.path, cfg);
311
449
  state.scanCount += 1;
312
450
  state.fileScanCount += result.filesScanned;
313
451
  state.findingCount += result.findings.length;
@@ -30,7 +30,7 @@
30
30
  *
31
31
  * @public
32
32
  */
33
- import type { Plugin } from '@wrongstack/core';
33
+ import type { Plugin } from '@wrongstack/core/types';
34
34
  declare const plugin: Plugin;
35
35
  export default plugin;
36
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic-search-indexer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA6b/C,QAAA,MAAM,MAAM,EAAE,MA6Nb,CAAC;eAEa,MAAM"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic-search-indexer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAqcrD,QAAA,MAAM,MAAM,EAAE,MA6Nb,CAAC;eAEa,MAAM"}
@@ -1,7 +1,9 @@
1
1
  // src/semantic-search-indexer/index.ts
2
2
  import * as fs from "node:fs/promises";
3
3
  import { isAbsolute, relative, resolve } from "node:path";
4
+ import { DEFAULT_WALK_IGNORE_DIRS } from "@wrongstack/core/utils";
4
5
  var API_VERSION = "^0.1.10";
6
+ var escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5
7
  var state = {
6
8
  index: null,
7
9
  cachedPath: null,
@@ -45,7 +47,11 @@ var DEFAULTS = {
45
47
  ".scss",
46
48
  ".html"
47
49
  ],
48
- excludePatterns: ["node_modules", "\\.git", "\\.wrongstack", "\\.temp_files", "coverage", "dist"],
50
+ excludePatterns: [
51
+ ...DEFAULT_WALK_IGNORE_DIRS.map(escapeRegex),
52
+ "\\.wrongstack",
53
+ "\\.temp_files"
54
+ ],
49
55
  maxFileBytes: 1e6,
50
56
  defaultLimit: 10,
51
57
  minTokenLength: 2,
@@ -6,7 +6,7 @@
6
6
  * - semver_current: Show the current version from package.json
7
7
  * - semver_changelog: Generate a changelog between two versions
8
8
  */
9
- import type { Plugin } from '@wrongstack/core';
9
+ import type { Plugin } from '@wrongstack/core/types';
10
10
  type BumpType = 'major' | 'minor' | 'patch' | 'auto';
11
11
  interface ConventionalCommit {
12
12
  hash: string;