agentsys 5.0.3 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/.claude-plugin/marketplace.json +21 -14
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +2 -1
  4. package/CHANGELOG.md +18 -0
  5. package/README.md +7 -6
  6. package/adapters/codex/skills/agnix/SKILL.md +0 -1
  7. package/adapters/codex/skills/audit-project/SKILL.md +0 -1
  8. package/adapters/codex/skills/audit-project-agents/SKILL.md +0 -1
  9. package/adapters/codex/skills/audit-project-github/SKILL.md +0 -1
  10. package/adapters/codex/skills/consult/SKILL.md +132 -57
  11. package/adapters/codex/skills/debate/SKILL.md +214 -0
  12. package/adapters/codex/skills/delivery-approval/SKILL.md +0 -1
  13. package/adapters/codex/skills/deslop/SKILL.md +0 -1
  14. package/adapters/codex/skills/drift-detect/SKILL.md +0 -1
  15. package/adapters/codex/skills/enhance/SKILL.md +0 -1
  16. package/adapters/codex/skills/learn/SKILL.md +0 -1
  17. package/adapters/codex/skills/next-task/SKILL.md +0 -1
  18. package/adapters/codex/skills/perf/SKILL.md +0 -1
  19. package/adapters/codex/skills/repo-map/SKILL.md +0 -1
  20. package/adapters/codex/skills/ship/SKILL.md +0 -1
  21. package/adapters/codex/skills/ship-ci-review-loop/SKILL.md +0 -1
  22. package/adapters/codex/skills/ship-deployment/SKILL.md +0 -1
  23. package/adapters/codex/skills/ship-error-handling/SKILL.md +0 -1
  24. package/adapters/codex/skills/sync-docs/SKILL.md +0 -1
  25. package/adapters/opencode/agents/agent-enhancer.md +0 -1
  26. package/adapters/opencode/agents/agnix-agent.md +0 -1
  27. package/adapters/opencode/agents/ci-fixer.md +0 -1
  28. package/adapters/opencode/agents/ci-monitor.md +0 -1
  29. package/adapters/opencode/agents/claudemd-enhancer.md +0 -1
  30. package/adapters/opencode/agents/consult-agent.md +122 -30
  31. package/adapters/opencode/agents/cross-file-enhancer.md +0 -1
  32. package/adapters/opencode/agents/debate-orchestrator.md +169 -0
  33. package/adapters/opencode/agents/delivery-validator.md +0 -1
  34. package/adapters/opencode/agents/deslop-agent.md +0 -1
  35. package/adapters/opencode/agents/docs-enhancer.md +0 -1
  36. package/adapters/opencode/agents/exploration-agent.md +0 -1
  37. package/adapters/opencode/agents/hooks-enhancer.md +0 -1
  38. package/adapters/opencode/agents/implementation-agent.md +0 -1
  39. package/adapters/opencode/agents/learn-agent.md +0 -1
  40. package/adapters/opencode/agents/map-validator.md +0 -1
  41. package/adapters/opencode/agents/perf-analyzer.md +0 -1
  42. package/adapters/opencode/agents/perf-code-paths.md +0 -1
  43. package/adapters/opencode/agents/perf-investigation-logger.md +0 -1
  44. package/adapters/opencode/agents/perf-orchestrator.md +0 -1
  45. package/adapters/opencode/agents/perf-theory-gatherer.md +0 -1
  46. package/adapters/opencode/agents/perf-theory-tester.md +0 -1
  47. package/adapters/opencode/agents/plan-synthesizer.md +0 -1
  48. package/adapters/opencode/agents/planning-agent.md +0 -1
  49. package/adapters/opencode/agents/plugin-enhancer.md +0 -1
  50. package/adapters/opencode/agents/prompt-enhancer.md +0 -1
  51. package/adapters/opencode/agents/simple-fixer.md +0 -1
  52. package/adapters/opencode/agents/skills-enhancer.md +0 -1
  53. package/adapters/opencode/agents/sync-docs-agent.md +0 -1
  54. package/adapters/opencode/agents/task-discoverer.md +0 -1
  55. package/adapters/opencode/agents/test-coverage-checker.md +0 -1
  56. package/adapters/opencode/agents/worktree-manager.md +0 -1
  57. package/adapters/opencode/commands/agnix.md +0 -1
  58. package/adapters/opencode/commands/audit-project-agents.md +0 -1
  59. package/adapters/opencode/commands/audit-project-github.md +0 -1
  60. package/adapters/opencode/commands/audit-project.md +0 -1
  61. package/adapters/opencode/commands/consult.md +133 -57
  62. package/adapters/opencode/commands/debate.md +224 -0
  63. package/adapters/opencode/commands/delivery-approval.md +0 -1
  64. package/adapters/opencode/commands/deslop.md +0 -1
  65. package/adapters/opencode/commands/drift-detect.md +0 -1
  66. package/adapters/opencode/commands/enhance.md +0 -1
  67. package/adapters/opencode/commands/learn.md +0 -1
  68. package/adapters/opencode/commands/next-task.md +0 -1
  69. package/adapters/opencode/commands/perf.md +0 -1
  70. package/adapters/opencode/commands/repo-map.md +0 -1
  71. package/adapters/opencode/commands/ship-ci-review-loop.md +0 -1
  72. package/adapters/opencode/commands/ship-deployment.md +0 -1
  73. package/adapters/opencode/commands/ship-error-handling.md +0 -1
  74. package/adapters/opencode/commands/ship.md +0 -1
  75. package/adapters/opencode/commands/sync-docs.md +0 -1
  76. package/adapters/opencode/skills/agnix/SKILL.md +1 -2
  77. package/adapters/opencode/skills/consult/SKILL.md +33 -23
  78. package/adapters/opencode/skills/debate/SKILL.md +245 -0
  79. package/adapters/opencode/skills/deslop/SKILL.md +1 -2
  80. package/adapters/opencode/skills/discover-tasks/SKILL.md +1 -2
  81. package/adapters/opencode/skills/drift-analysis/SKILL.md +1 -2
  82. package/adapters/opencode/skills/enhance-agent-prompts/SKILL.md +1 -2
  83. package/adapters/opencode/skills/enhance-claude-memory/SKILL.md +1 -2
  84. package/adapters/opencode/skills/enhance-cross-file/SKILL.md +1 -2
  85. package/adapters/opencode/skills/enhance-docs/SKILL.md +1 -2
  86. package/adapters/opencode/skills/enhance-hooks/SKILL.md +1 -2
  87. package/adapters/opencode/skills/enhance-orchestrator/SKILL.md +1 -2
  88. package/adapters/opencode/skills/enhance-plugins/SKILL.md +1 -2
  89. package/adapters/opencode/skills/enhance-prompts/SKILL.md +1 -2
  90. package/adapters/opencode/skills/enhance-skills/SKILL.md +1 -2
  91. package/adapters/opencode/skills/learn/SKILL.md +1 -2
  92. package/adapters/opencode/skills/orchestrate-review/SKILL.md +0 -1
  93. package/adapters/opencode/skills/perf-analyzer/SKILL.md +1 -2
  94. package/adapters/opencode/skills/perf-baseline-manager/SKILL.md +1 -2
  95. package/adapters/opencode/skills/perf-benchmarker/SKILL.md +1 -2
  96. package/adapters/opencode/skills/perf-code-paths/SKILL.md +1 -2
  97. package/adapters/opencode/skills/perf-investigation-logger/SKILL.md +1 -2
  98. package/adapters/opencode/skills/perf-profiler/SKILL.md +1 -2
  99. package/adapters/opencode/skills/perf-theory-gatherer/SKILL.md +1 -2
  100. package/adapters/opencode/skills/perf-theory-tester/SKILL.md +1 -2
  101. package/adapters/opencode/skills/repo-mapping/SKILL.md +1 -2
  102. package/adapters/opencode/skills/sync-docs/SKILL.md +1 -2
  103. package/adapters/opencode/skills/validate-delivery/SKILL.md +1 -2
  104. package/lib/adapter-transforms.js +24 -4
  105. package/package.json +1 -1
  106. package/plugins/agnix/.claude-plugin/plugin.json +1 -1
  107. package/plugins/agnix/skills/agnix/SKILL.md +1 -1
  108. package/plugins/audit-project/.claude-plugin/plugin.json +1 -1
  109. package/plugins/audit-project/lib/adapter-transforms.js +24 -4
  110. package/plugins/consult/.claude-plugin/plugin.json +1 -1
  111. package/plugins/consult/agents/consult-agent.md +122 -29
  112. package/plugins/consult/commands/consult.md +135 -58
  113. package/plugins/consult/skills/consult/SKILL.md +31 -20
  114. package/plugins/debate/.claude-plugin/plugin.json +21 -0
  115. package/plugins/debate/agents/debate-orchestrator.md +175 -0
  116. package/plugins/debate/commands/debate.md +221 -0
  117. package/plugins/debate/lib/adapter-transforms.js +298 -0
  118. package/plugins/debate/lib/collectors/codebase.js +392 -0
  119. package/plugins/debate/lib/collectors/docs-patterns.js +713 -0
  120. package/plugins/debate/lib/collectors/documentation.js +219 -0
  121. package/plugins/debate/lib/collectors/github.js +330 -0
  122. package/plugins/debate/lib/collectors/index.js +126 -0
  123. package/plugins/debate/lib/config/index.js +14 -0
  124. package/plugins/debate/lib/cross-platform/index.js +539 -0
  125. package/plugins/debate/lib/discovery/index.js +352 -0
  126. package/plugins/debate/lib/drift-detect/collectors.js +37 -0
  127. package/plugins/debate/lib/enhance/agent-analyzer.js +421 -0
  128. package/plugins/debate/lib/enhance/agent-patterns.js +571 -0
  129. package/plugins/debate/lib/enhance/auto-suppression.js +622 -0
  130. package/plugins/debate/lib/enhance/benchmark.js +417 -0
  131. package/plugins/debate/lib/enhance/cross-file-analyzer.js +930 -0
  132. package/plugins/debate/lib/enhance/cross-file-patterns.js +370 -0
  133. package/plugins/debate/lib/enhance/docs-analyzer.js +325 -0
  134. package/plugins/debate/lib/enhance/docs-patterns.js +671 -0
  135. package/plugins/debate/lib/enhance/fixer.js +721 -0
  136. package/plugins/debate/lib/enhance/hook-analyzer.js +135 -0
  137. package/plugins/debate/lib/enhance/hook-patterns.js +40 -0
  138. package/plugins/debate/lib/enhance/index.js +127 -0
  139. package/plugins/debate/lib/enhance/plugin-analyzer.js +402 -0
  140. package/plugins/debate/lib/enhance/plugin-patterns.js +326 -0
  141. package/plugins/debate/lib/enhance/projectmemory-analyzer.js +551 -0
  142. package/plugins/debate/lib/enhance/projectmemory-patterns.js +617 -0
  143. package/plugins/debate/lib/enhance/prompt-analyzer.js +457 -0
  144. package/plugins/debate/lib/enhance/prompt-patterns.js +1484 -0
  145. package/plugins/debate/lib/enhance/reporter.js +1348 -0
  146. package/plugins/debate/lib/enhance/security-patterns.js +284 -0
  147. package/plugins/debate/lib/enhance/skill-analyzer.js +182 -0
  148. package/plugins/debate/lib/enhance/skill-patterns.js +147 -0
  149. package/plugins/debate/lib/enhance/suppression.js +352 -0
  150. package/plugins/debate/lib/enhance/tool-patterns.js +373 -0
  151. package/plugins/debate/lib/index.js +270 -0
  152. package/plugins/debate/lib/patterns/cli-enhancers.js +611 -0
  153. package/plugins/debate/lib/patterns/pipeline.js +948 -0
  154. package/plugins/debate/lib/patterns/review-patterns.js +558 -0
  155. package/plugins/debate/lib/patterns/slop-analyzers.js +2305 -0
  156. package/plugins/debate/lib/patterns/slop-patterns.js +1187 -0
  157. package/plugins/debate/lib/perf/analyzer/index.js +22 -0
  158. package/plugins/debate/lib/perf/argument-parser.js +105 -0
  159. package/plugins/debate/lib/perf/baseline-comparator.js +50 -0
  160. package/plugins/debate/lib/perf/baseline-store.js +127 -0
  161. package/plugins/debate/lib/perf/benchmark-runner.js +404 -0
  162. package/plugins/debate/lib/perf/breaking-point-finder.js +52 -0
  163. package/plugins/debate/lib/perf/breaking-point-runner.js +60 -0
  164. package/plugins/debate/lib/perf/checkpoint.js +123 -0
  165. package/plugins/debate/lib/perf/code-paths.js +86 -0
  166. package/plugins/debate/lib/perf/consolidation.js +37 -0
  167. package/plugins/debate/lib/perf/constraint-runner.js +71 -0
  168. package/plugins/debate/lib/perf/experiment-runner.js +32 -0
  169. package/plugins/debate/lib/perf/index.js +41 -0
  170. package/plugins/debate/lib/perf/investigation-state.js +874 -0
  171. package/plugins/debate/lib/perf/optimization-runner.js +79 -0
  172. package/plugins/debate/lib/perf/profilers/go.js +22 -0
  173. package/plugins/debate/lib/perf/profilers/index.js +46 -0
  174. package/plugins/debate/lib/perf/profilers/java.js +23 -0
  175. package/plugins/debate/lib/perf/profilers/node.js +27 -0
  176. package/plugins/debate/lib/perf/profilers/python.js +23 -0
  177. package/plugins/debate/lib/perf/profilers/rust.js +23 -0
  178. package/plugins/debate/lib/perf/profiling-runner.js +75 -0
  179. package/plugins/debate/lib/perf/schemas.js +140 -0
  180. package/plugins/debate/lib/platform/detect-platform.js +413 -0
  181. package/plugins/debate/lib/platform/detection-configs.js +93 -0
  182. package/plugins/debate/lib/platform/state-dir.js +132 -0
  183. package/plugins/debate/lib/platform/verify-tools.js +182 -0
  184. package/plugins/debate/lib/repo-map/cache.js +152 -0
  185. package/plugins/debate/lib/repo-map/concurrency.js +29 -0
  186. package/plugins/debate/lib/repo-map/index.js +222 -0
  187. package/plugins/debate/lib/repo-map/installer.js +212 -0
  188. package/plugins/debate/lib/repo-map/queries/go.js +27 -0
  189. package/plugins/debate/lib/repo-map/queries/index.js +100 -0
  190. package/plugins/debate/lib/repo-map/queries/java.js +38 -0
  191. package/plugins/debate/lib/repo-map/queries/javascript.js +55 -0
  192. package/plugins/debate/lib/repo-map/queries/python.js +24 -0
  193. package/plugins/debate/lib/repo-map/queries/rust.js +73 -0
  194. package/plugins/debate/lib/repo-map/queries/typescript.js +38 -0
  195. package/plugins/debate/lib/repo-map/runner.js +1364 -0
  196. package/plugins/debate/lib/repo-map/updater.js +562 -0
  197. package/plugins/debate/lib/repo-map/usage-analyzer.js +407 -0
  198. package/plugins/debate/lib/schemas/plugin-manifest.schema.json +57 -0
  199. package/plugins/debate/lib/schemas/validator.js +247 -0
  200. package/plugins/debate/lib/sources/custom-handler.js +199 -0
  201. package/plugins/debate/lib/sources/policy-questions.js +246 -0
  202. package/plugins/debate/lib/sources/source-cache.js +165 -0
  203. package/plugins/debate/lib/state/workflow-state.js +576 -0
  204. package/plugins/debate/lib/types/agent-frontmatter.d.ts +134 -0
  205. package/plugins/debate/lib/types/command-frontmatter.d.ts +107 -0
  206. package/plugins/debate/lib/types/hook-frontmatter.d.ts +115 -0
  207. package/plugins/debate/lib/types/index.d.ts +84 -0
  208. package/plugins/debate/lib/types/plugin-manifest.d.ts +102 -0
  209. package/plugins/debate/lib/types/skill-frontmatter.d.ts +89 -0
  210. package/plugins/debate/lib/utils/atomic-write.js +94 -0
  211. package/plugins/debate/lib/utils/cache-manager.js +159 -0
  212. package/plugins/debate/lib/utils/command-parser.js +0 -0
  213. package/plugins/debate/lib/utils/context-optimizer.js +300 -0
  214. package/plugins/debate/lib/utils/deprecation.js +37 -0
  215. package/plugins/debate/lib/utils/shell-escape.js +88 -0
  216. package/plugins/debate/lib/utils/state-helpers.js +61 -0
  217. package/plugins/debate/skills/debate/SKILL.md +264 -0
  218. package/plugins/deslop/.claude-plugin/plugin.json +1 -1
  219. package/plugins/deslop/lib/adapter-transforms.js +24 -4
  220. package/plugins/deslop/skills/deslop/SKILL.md +1 -1
  221. package/plugins/drift-detect/.claude-plugin/plugin.json +1 -1
  222. package/plugins/drift-detect/lib/adapter-transforms.js +24 -4
  223. package/plugins/drift-detect/skills/drift-analysis/SKILL.md +1 -1
  224. package/plugins/enhance/.claude-plugin/plugin.json +1 -1
  225. package/plugins/enhance/lib/adapter-transforms.js +24 -4
  226. package/plugins/enhance/skills/enhance-agent-prompts/SKILL.md +1 -1
  227. package/plugins/enhance/skills/enhance-claude-memory/SKILL.md +1 -1
  228. package/plugins/enhance/skills/enhance-cross-file/SKILL.md +1 -1
  229. package/plugins/enhance/skills/enhance-docs/SKILL.md +1 -1
  230. package/plugins/enhance/skills/enhance-hooks/SKILL.md +1 -1
  231. package/plugins/enhance/skills/enhance-orchestrator/SKILL.md +1 -1
  232. package/plugins/enhance/skills/enhance-plugins/SKILL.md +1 -1
  233. package/plugins/enhance/skills/enhance-prompts/SKILL.md +1 -1
  234. package/plugins/enhance/skills/enhance-skills/SKILL.md +1 -1
  235. package/plugins/learn/.claude-plugin/plugin.json +1 -1
  236. package/plugins/learn/agents/learn-agent.md +1 -1
  237. package/plugins/learn/lib/adapter-transforms.js +24 -4
  238. package/plugins/learn/skills/learn/SKILL.md +1 -1
  239. package/plugins/next-task/.claude-plugin/plugin.json +1 -1
  240. package/plugins/next-task/agents/exploration-agent.md +1 -1
  241. package/plugins/next-task/lib/adapter-transforms.js +24 -4
  242. package/plugins/next-task/skills/discover-tasks/SKILL.md +1 -1
  243. package/plugins/next-task/skills/validate-delivery/SKILL.md +1 -1
  244. package/plugins/perf/.claude-plugin/plugin.json +1 -1
  245. package/plugins/perf/lib/adapter-transforms.js +24 -4
  246. package/plugins/perf/skills/perf-analyzer/SKILL.md +1 -1
  247. package/plugins/perf/skills/perf-baseline-manager/SKILL.md +1 -1
  248. package/plugins/perf/skills/perf-benchmarker/SKILL.md +1 -1
  249. package/plugins/perf/skills/perf-code-paths/SKILL.md +1 -1
  250. package/plugins/perf/skills/perf-investigation-logger/SKILL.md +1 -1
  251. package/plugins/perf/skills/perf-profiler/SKILL.md +1 -1
  252. package/plugins/perf/skills/perf-theory-gatherer/SKILL.md +1 -1
  253. package/plugins/perf/skills/perf-theory-tester/SKILL.md +1 -1
  254. package/plugins/repo-map/.claude-plugin/plugin.json +1 -1
  255. package/plugins/repo-map/lib/adapter-transforms.js +24 -4
  256. package/plugins/ship/.claude-plugin/plugin.json +1 -1
  257. package/plugins/ship/lib/adapter-transforms.js +24 -4
  258. package/plugins/sync-docs/.claude-plugin/plugin.json +1 -1
  259. package/plugins/sync-docs/lib/adapter-transforms.js +24 -4
  260. package/plugins/sync-docs/skills/sync-docs/SKILL.md +1 -1
  261. package/scripts/gen-adapters.js +6 -7
  262. package/scripts/generate-docs.js +4 -2
  263. package/scripts/plugins.txt +1 -0
  264. package/site/content.json +6 -6
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Suppression System for /enhance
3
+ * Handles inline comments and config file suppressions
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ /**
10
+ * Default suppression config
11
+ */
12
+ const DEFAULT_CONFIG = {
13
+ ignore: {
14
+ patterns: [],
15
+ files: [],
16
+ rules: {}
17
+ },
18
+ severity: {}
19
+ };
20
+
21
+ // Maximum config file size (1MB) to prevent DoS via large files
22
+ const MAX_CONFIG_SIZE = 1024 * 1024;
23
+
24
+ /**
25
+ * Load suppression config from project root
26
+ * @param {string} projectRoot - Path to project root
27
+ * @returns {Object} Merged config
28
+ */
29
+ function loadConfig(projectRoot) {
30
+ const configPaths = [
31
+ path.join(projectRoot, '.enhancerc.json'),
32
+ path.join(projectRoot, '.enhancerc'),
33
+ path.join(projectRoot, 'enhance.config.json')
34
+ ];
35
+
36
+ for (const configPath of configPaths) {
37
+ if (fs.existsSync(configPath)) {
38
+ try {
39
+ // Check file size before reading to prevent DoS
40
+ const stats = fs.statSync(configPath);
41
+ if (stats.size > MAX_CONFIG_SIZE) {
42
+ console.error(`[WARN] Config file too large (${stats.size} bytes), using defaults`);
43
+ continue;
44
+ }
45
+ const content = fs.readFileSync(configPath, 'utf8');
46
+ const userConfig = JSON.parse(content);
47
+ return mergeConfig(DEFAULT_CONFIG, userConfig);
48
+ } catch (err) {
49
+ // Invalid config, use defaults
50
+ }
51
+ }
52
+ }
53
+
54
+ return DEFAULT_CONFIG;
55
+ }
56
+
57
+ /**
58
+ * Merge user config with defaults
59
+ * @param {Object} defaults - Default config
60
+ * @param {Object} user - User config
61
+ * @returns {Object} Merged config
62
+ */
63
+ function mergeConfig(defaults, user) {
64
+ return {
65
+ ignore: {
66
+ patterns: [...(defaults.ignore.patterns || []), ...(user.ignore?.patterns || [])],
67
+ files: [...(defaults.ignore.files || []), ...(user.ignore?.files || [])],
68
+ rules: { ...(defaults.ignore.rules || {}), ...(user.ignore?.rules || {}) }
69
+ },
70
+ severity: { ...(defaults.severity || {}), ...(user.severity || {}) }
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Extract inline suppressions from content
76
+ * Supports:
77
+ * - <!-- enhance:ignore pattern_id -->
78
+ * - // enhance:ignore pattern_id
79
+ * - # enhance:ignore pattern_id
80
+ *
81
+ * @param {string} content - File content
82
+ * @returns {Set<string>} Set of suppressed pattern IDs
83
+ */
84
+ function extractInlineSuppressions(content) {
85
+ if (!content || typeof content !== 'string') return new Set();
86
+
87
+ const suppressions = new Set();
88
+
89
+ // HTML/Markdown comments
90
+ const htmlPattern = /<!--\s*enhance:ignore\s+(\S+)\s*-->/gi;
91
+ let match;
92
+ while ((match = htmlPattern.exec(content)) !== null) {
93
+ suppressions.add(match[1].toLowerCase());
94
+ }
95
+
96
+ // JS/TS comments
97
+ const jsPattern = /\/\/\s*enhance:ignore\s+(\S+)/gi;
98
+ while ((match = jsPattern.exec(content)) !== null) {
99
+ suppressions.add(match[1].toLowerCase());
100
+ }
101
+
102
+ // Python/Shell comments
103
+ const pyPattern = /#\s*enhance:ignore\s+(\S+)/gi;
104
+ while ((match = pyPattern.exec(content)) !== null) {
105
+ suppressions.add(match[1].toLowerCase());
106
+ }
107
+
108
+ return suppressions;
109
+ }
110
+
111
+ /**
112
+ * Check if a finding should be suppressed
113
+ * @param {Object} finding - The finding to check
114
+ * @param {Object} config - Suppression config
115
+ * @param {Set<string>} inlineSuppressions - Inline suppressions for this file
116
+ * @param {string} filePath - Path to file being analyzed
117
+ * @param {string} projectRoot - Project root path
118
+ * @returns {Object|null} Suppression info if suppressed, null otherwise
119
+ */
120
+ function shouldSuppress(finding, config, inlineSuppressions, filePath, projectRoot) {
121
+ const patternId = (finding.patternId || finding.id || '').toLowerCase();
122
+
123
+ // Check inline suppressions
124
+ if (inlineSuppressions.has(patternId)) {
125
+ return {
126
+ reason: 'inline',
127
+ patternId,
128
+ source: 'inline comment'
129
+ };
130
+ }
131
+
132
+ // Check config pattern suppressions
133
+ if (config.ignore.patterns.includes(patternId)) {
134
+ return {
135
+ reason: 'config',
136
+ patternId,
137
+ source: 'config: ignore.patterns'
138
+ };
139
+ }
140
+
141
+ // Check config rule suppressions
142
+ const ruleConfig = config.ignore.rules[patternId];
143
+ if (ruleConfig) {
144
+ if (ruleConfig.severity === 'off' || ruleConfig === 'off') {
145
+ return {
146
+ reason: 'config',
147
+ patternId,
148
+ source: `config: ignore.rules.${patternId}`,
149
+ userReason: ruleConfig.reason
150
+ };
151
+ }
152
+ }
153
+
154
+ // Check file pattern suppressions
155
+ if (filePath && projectRoot) {
156
+ const relativePath = path.relative(projectRoot, filePath).replace(/\\/g, '/');
157
+ for (const filePattern of config.ignore.files) {
158
+ if (matchGlob(relativePath, filePattern)) {
159
+ return {
160
+ reason: 'config',
161
+ patternId,
162
+ source: `config: ignore.files (${filePattern})`
163
+ };
164
+ }
165
+ }
166
+ }
167
+
168
+ // Check auto-learned suppressions
169
+ if (config.auto_learned?.patterns?.[patternId]) {
170
+ const autoRule = config.auto_learned.patterns[patternId];
171
+ const relativePath = filePath && projectRoot
172
+ ? path.relative(projectRoot, filePath).replace(/\\/g, '/')
173
+ : filePath;
174
+
175
+ // Check if this file is in the auto-learned list
176
+ const fileMatch = autoRule.files?.some(f => {
177
+ // Support both exact match and glob patterns
178
+ if (f === relativePath || f === filePath) return true;
179
+ return matchGlob(relativePath || '', f);
180
+ });
181
+
182
+ if (fileMatch) {
183
+ return {
184
+ reason: 'auto_learned',
185
+ patternId,
186
+ source: 'auto-learned suppression',
187
+ confidence: autoRule.confidence,
188
+ note: autoRule.reason
189
+ };
190
+ }
191
+ }
192
+
193
+ return null;
194
+ }
195
+
196
+ /**
197
+ * Simple glob matching (supports * and **)
198
+ * @param {string} filePath - File path to match
199
+ * @param {string} pattern - Glob pattern
200
+ * @returns {boolean} True if matches
201
+ */
202
+ function matchGlob(filePath, pattern) {
203
+ // Convert glob to regex
204
+ // First escape backslashes, then other special regex chars, then convert glob patterns
205
+ const regexStr = pattern
206
+ .replace(/\\/g, '\\\\')
207
+ .replace(/\./g, '\\.')
208
+ .replace(/\*\*/g, '.*')
209
+ .replace(/\*/g, '[^/]*');
210
+
211
+ const regex = new RegExp(`^${regexStr}$`);
212
+ return regex.test(filePath);
213
+ }
214
+
215
+ /**
216
+ * Apply severity overrides from config
217
+ * @param {Object} finding - Finding to check
218
+ * @param {Object} config - Suppression config
219
+ * @returns {string} Adjusted certainty level
220
+ */
221
+ function applySeverityOverride(finding, config) {
222
+ const patternId = (finding.patternId || finding.id || '').toLowerCase();
223
+
224
+ // Check config severity overrides
225
+ if (config.severity[patternId]) {
226
+ const override = config.severity[patternId];
227
+ if (['HIGH', 'MEDIUM', 'LOW'].includes(override.toUpperCase())) {
228
+ return override.toUpperCase();
229
+ }
230
+ }
231
+
232
+ // Check rule-level severity
233
+ const ruleConfig = config.ignore.rules[patternId];
234
+ if (ruleConfig && ruleConfig.severity && ruleConfig.severity !== 'off') {
235
+ if (['HIGH', 'MEDIUM', 'LOW'].includes(ruleConfig.severity.toUpperCase())) {
236
+ return ruleConfig.severity.toUpperCase();
237
+ }
238
+ }
239
+
240
+ return finding.certainty;
241
+ }
242
+
243
+ /**
244
+ * Filter findings with suppression tracking
245
+ * @param {Array} findings - All findings
246
+ * @param {Object} config - Suppression config
247
+ * @param {string} projectRoot - Project root path
248
+ * @param {Map<string, string>} fileContents - Map of file path to content (for inline suppression extraction)
249
+ * @returns {Object} { active: [], suppressed: [] }
250
+ */
251
+ function filterFindings(findings, config, projectRoot, fileContents = new Map()) {
252
+ const active = [];
253
+ const suppressed = [];
254
+
255
+ // Cache inline suppressions per file
256
+ const inlineSuppressionsCache = new Map();
257
+
258
+ for (const finding of findings) {
259
+ const filePath = finding.file || finding.filePath;
260
+
261
+ // Get inline suppressions for this file
262
+ let inlineSuppressions;
263
+ if (inlineSuppressionsCache.has(filePath)) {
264
+ inlineSuppressions = inlineSuppressionsCache.get(filePath);
265
+ } else {
266
+ const content = fileContents.get(filePath);
267
+ inlineSuppressions = content ? extractInlineSuppressions(content) : new Set();
268
+ inlineSuppressionsCache.set(filePath, inlineSuppressions);
269
+ }
270
+
271
+ // Check if suppressed
272
+ const suppression = shouldSuppress(finding, config, inlineSuppressions, filePath, projectRoot);
273
+
274
+ if (suppression) {
275
+ suppressed.push({
276
+ ...finding,
277
+ reason: suppression.reason,
278
+ confidence: suppression.confidence,
279
+ note: suppression.note,
280
+ suppression
281
+ });
282
+ } else {
283
+ // Apply severity override
284
+ const adjustedCertainty = applySeverityOverride(finding, config);
285
+ active.push({
286
+ ...finding,
287
+ certainty: adjustedCertainty,
288
+ originalCertainty: finding.certainty !== adjustedCertainty ? finding.certainty : undefined
289
+ });
290
+ }
291
+ }
292
+
293
+ return { active, suppressed };
294
+ }
295
+
296
+ /**
297
+ * Generate suppression summary for report
298
+ * @param {Array} suppressed - Suppressed findings
299
+ * @returns {string} Summary markdown
300
+ */
301
+ function generateSuppressionSummary(suppressed) {
302
+ if (!suppressed || suppressed.length === 0) {
303
+ return '';
304
+ }
305
+
306
+ const lines = [];
307
+ lines.push('## Suppressed Findings');
308
+ lines.push('');
309
+ lines.push(`**${suppressed.length} findings suppressed**`);
310
+ lines.push('');
311
+
312
+ // Group by suppression source
313
+ const bySource = {};
314
+ for (const finding of suppressed) {
315
+ const source = finding.suppression?.source || 'unknown';
316
+ if (!bySource[source]) bySource[source] = [];
317
+ bySource[source].push(finding);
318
+ }
319
+
320
+ lines.push('| Source | Pattern | Count |');
321
+ lines.push('|--------|---------|-------|');
322
+
323
+ for (const [source, findings] of Object.entries(bySource)) {
324
+ // Group by pattern within source
325
+ const byPattern = {};
326
+ for (const f of findings) {
327
+ const pattern = f.suppression?.patternId || 'unknown';
328
+ byPattern[pattern] = (byPattern[pattern] || 0) + 1;
329
+ }
330
+
331
+ for (const [pattern, count] of Object.entries(byPattern)) {
332
+ lines.push(`| ${source} | ${pattern} | ${count} |`);
333
+ }
334
+ }
335
+
336
+ lines.push('');
337
+ lines.push('*Use `--show-suppressed` to see full details*');
338
+ lines.push('');
339
+
340
+ return lines.join('\n');
341
+ }
342
+
343
+ module.exports = {
344
+ loadConfig,
345
+ extractInlineSuppressions,
346
+ shouldSuppress,
347
+ applySeverityOverride,
348
+ filterFindings,
349
+ generateSuppressionSummary,
350
+ matchGlob,
351
+ DEFAULT_CONFIG
352
+ };