simplecov-mcp 0.3.0 → 1.0.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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -0
  3. data/README.md +173 -356
  4. data/docs/ADVANCED_USAGE.md +967 -0
  5. data/docs/ARCHITECTURE.md +79 -0
  6. data/docs/BRANCH_ONLY_COVERAGE.md +81 -0
  7. data/docs/CLI_USAGE.md +637 -0
  8. data/docs/DEVELOPMENT.md +82 -0
  9. data/docs/ERROR_HANDLING.md +93 -0
  10. data/docs/EXAMPLES.md +430 -0
  11. data/docs/INSTALLATION.md +352 -0
  12. data/docs/LIBRARY_API.md +635 -0
  13. data/docs/MCP_INTEGRATION.md +488 -0
  14. data/docs/TROUBLESHOOTING.md +276 -0
  15. data/docs/arch-decisions/001-x-arch-decision.md +93 -0
  16. data/docs/arch-decisions/002-x-arch-decision.md +157 -0
  17. data/docs/arch-decisions/003-x-arch-decision.md +163 -0
  18. data/docs/arch-decisions/004-x-arch-decision.md +199 -0
  19. data/docs/arch-decisions/005-x-arch-decision.md +187 -0
  20. data/docs/arch-decisions/README.md +60 -0
  21. data/docs/presentations/simplecov-mcp-presentation.md +249 -0
  22. data/exe/simplecov-mcp +4 -4
  23. data/lib/simplecov_mcp/app_context.rb +26 -0
  24. data/lib/simplecov_mcp/base_tool.rb +74 -0
  25. data/lib/simplecov_mcp/cli.rb +234 -0
  26. data/lib/simplecov_mcp/cli_config.rb +56 -0
  27. data/lib/simplecov_mcp/commands/base_command.rb +78 -0
  28. data/lib/simplecov_mcp/commands/command_factory.rb +39 -0
  29. data/lib/simplecov_mcp/commands/detailed_command.rb +24 -0
  30. data/lib/simplecov_mcp/commands/list_command.rb +13 -0
  31. data/lib/simplecov_mcp/commands/raw_command.rb +22 -0
  32. data/lib/simplecov_mcp/commands/summary_command.rb +24 -0
  33. data/lib/simplecov_mcp/commands/uncovered_command.rb +26 -0
  34. data/lib/simplecov_mcp/commands/version_command.rb +18 -0
  35. data/lib/simplecov_mcp/constants.rb +22 -0
  36. data/lib/simplecov_mcp/error_handler.rb +124 -0
  37. data/lib/simplecov_mcp/error_handler_factory.rb +31 -0
  38. data/lib/simplecov_mcp/errors.rb +179 -0
  39. data/lib/simplecov_mcp/formatters/source_formatter.rb +148 -0
  40. data/lib/simplecov_mcp/mcp_server.rb +40 -0
  41. data/lib/simplecov_mcp/mode_detector.rb +55 -0
  42. data/lib/simplecov_mcp/model.rb +300 -0
  43. data/lib/simplecov_mcp/option_normalizers.rb +92 -0
  44. data/lib/simplecov_mcp/option_parser_builder.rb +134 -0
  45. data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +50 -0
  46. data/lib/simplecov_mcp/option_parsers/error_helper.rb +109 -0
  47. data/lib/simplecov_mcp/path_relativizer.rb +61 -0
  48. data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +44 -0
  49. data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +16 -0
  50. data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +16 -0
  51. data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +16 -0
  52. data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +16 -0
  53. data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +52 -0
  54. data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +126 -0
  55. data/lib/simplecov_mcp/resolvers/resolver_factory.rb +28 -0
  56. data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +78 -0
  57. data/lib/simplecov_mcp/resultset_loader.rb +136 -0
  58. data/lib/simplecov_mcp/staleness_checker.rb +243 -0
  59. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/all_files_coverage_tool.rb +31 -13
  60. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_detailed_tool.rb +7 -7
  61. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_raw_tool.rb +7 -7
  62. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_summary_tool.rb +7 -7
  63. data/lib/simplecov_mcp/tools/coverage_table_tool.rb +90 -0
  64. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/help_tool.rb +13 -4
  65. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/uncovered_lines_tool.rb +7 -7
  66. data/lib/{simple_cov_mcp → simplecov_mcp}/tools/version_tool.rb +11 -3
  67. data/lib/simplecov_mcp/util.rb +82 -0
  68. data/lib/{simple_cov_mcp → simplecov_mcp}/version.rb +1 -1
  69. data/lib/simplecov_mcp.rb +144 -2
  70. data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
  71. data/spec/TIMESTAMPS.md +48 -0
  72. data/spec/all_files_coverage_tool_spec.rb +29 -25
  73. data/spec/base_tool_spec.rb +11 -10
  74. data/spec/cli/show_default_report_spec.rb +33 -0
  75. data/spec/cli_config_spec.rb +137 -0
  76. data/spec/cli_enumerated_options_spec.rb +68 -0
  77. data/spec/cli_error_spec.rb +105 -47
  78. data/spec/cli_source_spec.rb +82 -23
  79. data/spec/cli_spec.rb +140 -5
  80. data/spec/cli_success_predicate_spec.rb +141 -0
  81. data/spec/cli_table_spec.rb +1 -1
  82. data/spec/cli_usage_spec.rb +10 -26
  83. data/spec/commands/base_command_spec.rb +187 -0
  84. data/spec/commands/command_factory_spec.rb +72 -0
  85. data/spec/commands/detailed_command_spec.rb +48 -0
  86. data/spec/commands/raw_command_spec.rb +46 -0
  87. data/spec/commands/summary_command_spec.rb +47 -0
  88. data/spec/commands/uncovered_command_spec.rb +49 -0
  89. data/spec/constants_spec.rb +61 -0
  90. data/spec/coverage_table_tool_spec.rb +17 -33
  91. data/spec/error_handler_spec.rb +22 -13
  92. data/spec/error_mode_spec.rb +143 -0
  93. data/spec/errors_edge_cases_spec.rb +239 -0
  94. data/spec/errors_stale_spec.rb +2 -2
  95. data/spec/file_based_mcp_tools_spec.rb +99 -0
  96. data/spec/fixtures/project1/lib/bar.rb +0 -1
  97. data/spec/fixtures/project1/lib/foo.rb +0 -1
  98. data/spec/help_tool_spec.rb +11 -17
  99. data/spec/integration_spec.rb +845 -0
  100. data/spec/logging_fallback_spec.rb +128 -0
  101. data/spec/mcp_logging_spec.rb +44 -0
  102. data/spec/mcp_server_integration_spec.rb +23 -0
  103. data/spec/mcp_server_spec.rb +15 -4
  104. data/spec/mode_detector_spec.rb +148 -0
  105. data/spec/model_error_handling_spec.rb +210 -0
  106. data/spec/model_staleness_spec.rb +40 -10
  107. data/spec/option_normalizers_spec.rb +204 -0
  108. data/spec/option_parsers/env_options_parser_spec.rb +233 -0
  109. data/spec/option_parsers/error_helper_spec.rb +222 -0
  110. data/spec/path_relativizer_spec.rb +83 -0
  111. data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
  112. data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
  113. data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
  114. data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
  115. data/spec/presenters/project_coverage_presenter_spec.rb +86 -0
  116. data/spec/resolvers/coverage_line_resolver_spec.rb +57 -0
  117. data/spec/resolvers/resolver_factory_spec.rb +61 -0
  118. data/spec/resolvers/resultset_path_resolver_spec.rb +55 -0
  119. data/spec/resultset_loader_spec.rb +167 -0
  120. data/spec/shared_examples/README.md +115 -0
  121. data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
  122. data/spec/shared_examples/file_based_mcp_tools.rb +174 -0
  123. data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
  124. data/spec/simple_cov_mcp_module_spec.rb +16 -0
  125. data/spec/simplecov_mcp_model_spec.rb +340 -9
  126. data/spec/simplecov_mcp_opts_spec.rb +182 -0
  127. data/spec/spec_helper.rb +147 -4
  128. data/spec/staleness_checker_spec.rb +373 -0
  129. data/spec/staleness_more_spec.rb +16 -13
  130. data/spec/support/mcp_runner.rb +64 -0
  131. data/spec/tools_error_handling_spec.rb +144 -0
  132. data/spec/util_spec.rb +109 -34
  133. data/spec/version_spec.rb +117 -9
  134. data/spec/version_tool_spec.rb +131 -10
  135. metadata +120 -63
  136. data/lib/simple_cov/mcp.rb +0 -9
  137. data/lib/simple_cov_mcp/base_tool.rb +0 -70
  138. data/lib/simple_cov_mcp/cli.rb +0 -390
  139. data/lib/simple_cov_mcp/error_handler.rb +0 -131
  140. data/lib/simple_cov_mcp/error_handler_factory.rb +0 -38
  141. data/lib/simple_cov_mcp/errors.rb +0 -176
  142. data/lib/simple_cov_mcp/mcp_server.rb +0 -30
  143. data/lib/simple_cov_mcp/model.rb +0 -104
  144. data/lib/simple_cov_mcp/staleness_checker.rb +0 -125
  145. data/lib/simple_cov_mcp/tools/coverage_table_tool.rb +0 -61
  146. data/lib/simple_cov_mcp/util.rb +0 -122
  147. data/lib/simple_cov_mcp.rb +0 -102
  148. data/spec/coverage_detailed_tool_spec.rb +0 -36
  149. data/spec/coverage_raw_tool_spec.rb +0 -32
  150. data/spec/coverage_summary_tool_spec.rb +0 -39
  151. data/spec/legacy_shim_spec.rb +0 -13
  152. data/spec/uncovered_lines_tool_spec.rb +0 -33
@@ -0,0 +1,93 @@
1
+ # Error Handling Guide
2
+
3
+ This tool provides different error handling behavior depending on how it's used:
4
+
5
+ ## CLI Mode
6
+
7
+ When used as a command-line tool, errors are displayed as user-friendly messages without stack traces:
8
+
9
+ ```bash
10
+ $ simplecov-mcp summary nonexistent.rb
11
+ File error: No coverage data found for the specified file
12
+ ```
13
+
14
+ For debugging, use the `--error-mode trace` flag to see full stack traces:
15
+
16
+ ```bash
17
+ $ simplecov-mcp --error-mode trace summary nonexistent.rb
18
+ ```
19
+
20
+ ## Library Mode
21
+
22
+ When used as a Ruby library, callers work with `SimpleCovMcp::CoverageModel` directly. Errors raise custom exception classes that can be caught and handled:
23
+
24
+ ```ruby
25
+ handler = SimpleCovMcp::ErrorHandlerFactory.for_library # disables CLI-style logging
26
+ context = SimpleCovMcp.create_context(error_handler: handler)
27
+
28
+ SimpleCovMcp.with_context(context) do
29
+ model = SimpleCovMcp::CoverageModel.new
30
+ begin
31
+ model.summary_for('missing.rb')
32
+ rescue SimpleCovMcp::FileError => e
33
+ puts "Handled gracefully: #{e.user_friendly_message}"
34
+ end
35
+ end
36
+ ```
37
+
38
+ Available exception classes:
39
+ - `SimpleCovMcp::Error` - Base error class
40
+ - `SimpleCovMcp::FileError` - File not found or access issues
41
+ - `SimpleCovMcp::CoverageDataError` - Invalid or missing coverage data
42
+ - `SimpleCovMcp::ConfigurationError` - Configuration problems
43
+ - `SimpleCovMcp::UsageError` - Command usage errors
44
+
45
+ ## MCP Server Mode
46
+
47
+ When running as an MCP server, errors are handled internally and returned as structured responses to the MCP client. The MCP server uses:
48
+
49
+ - **Logging enabled** - Errors are logged to `simplecov_mcp.log` in the current directory for server debugging
50
+ - **Clean error messages** - User-friendly messages are returned to the client without stack traces by default
51
+ - **Structured responses** - Errors are returned as proper MCP tool responses, not exceptions
52
+
53
+ The MCP server automatically configures error handling appropriately for server usage.
54
+
55
+ ## Custom Error Handlers
56
+
57
+ Library usage can opt into different logging behavior by installing a custom handler on the active context:
58
+
59
+ ```ruby
60
+ handler = SimpleCovMcp::ErrorHandler.new(
61
+ log_errors: true, # Enable logging when embedding
62
+ show_stack_traces: false # Keep error messages clean
63
+ )
64
+
65
+ context = SimpleCovMcp.create_context(error_handler: handler)
66
+
67
+ SimpleCovMcp.with_context(context) do
68
+ model = SimpleCovMcp::CoverageModel.new
69
+ model.summary_for('lib/simplecov_mcp/model.rb')
70
+ end
71
+ ```
72
+
73
+ ## Stale Coverage Errors
74
+
75
+ When strict staleness checking is enabled (`--stale error`), the model (and CLI) raise a `CoverageDataStaleError` if a source file appears newer than the coverage data or the line counts differ.
76
+
77
+ - Enable per instance: `SimpleCovMcp::CoverageModel.new(staleness: 'error')`
78
+
79
+ The error message is detailed and includes:
80
+
81
+ - File and Coverage times (UTC and local) and line counts
82
+ - A delta indicating how much newer the file is than coverage
83
+ - The absolute path to the `.resultset.json` used
84
+
85
+ **Example excerpt:**
86
+
87
+ ```
88
+ Coverage data stale: Coverage data appears stale for lib/foo.rb
89
+ File - time: 2025-09-16T14:03:22Z (local 2025-09-16T07:03:22-07:00), lines: 226
90
+ Coverage - time: 2025-09-15T21:11:09Z (local 2025-09-15T14:11:09-07:00), lines: 220
91
+ Delta - file is +123s newer than coverage
92
+ Resultset - /path/to/your/project/coverage/.resultset.json
93
+ ```
data/docs/EXAMPLES.md ADDED
@@ -0,0 +1,430 @@
1
+ # Examples and Recipes
2
+
3
+ Practical examples for common tasks with simplecov-mcp. Examples are organized by skill level and use case.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Quick Start Examples](#quick-start-examples)
8
+ - [CLI Examples](#cli-examples)
9
+ - [Ruby Library Examples](#ruby-library-examples)
10
+ - [AI Assistant Prompts](#ai-assistant-prompts)
11
+ - [CI/CD Integration](#cicd-integration)
12
+ - [Advanced Usage](#advanced-usage)
13
+
14
+ ## Quick Start Examples
15
+
16
+ ### View All Coverage
17
+
18
+ ```bash
19
+ # Default: show all files, worst coverage first
20
+ simplecov-mcp
21
+
22
+ # Show files with best coverage first
23
+ simplecov-mcp list --sort-order descending
24
+
25
+ # Export to JSON for processing
26
+ simplecov-mcp list --json > coverage-report.json
27
+ ```
28
+
29
+ ### Check Specific File
30
+
31
+ ```bash
32
+ # Quick summary
33
+ simplecov-mcp summary lib/my_class.rb
34
+
35
+ # See which lines aren't covered
36
+ simplecov-mcp uncovered lib/my_class.rb
37
+
38
+ # View uncovered code with context
39
+ simplecov-mcp uncovered lib/my_class.rb --source=uncovered --source-context 3
40
+ ```
41
+
42
+ ### Find Coverage Gaps
43
+
44
+ ```bash
45
+ # Files with worst coverage
46
+ simplecov-mcp list | head -10
47
+
48
+ # Only show files below 80%
49
+ simplecov-mcp list --json | jq '.files[] | select(.percentage < 80)'
50
+
51
+ # Check specific directory
52
+ simplecov-mcp list --tracked-globs "lib/services/**/*.rb"
53
+ ```
54
+
55
+ ## CLI Examples
56
+
57
+ ### Coverage Analysis
58
+
59
+ **Find files needing attention:**
60
+ ```bash
61
+ # Show only lib/ files
62
+ simplecov-mcp list --tracked-globs "lib/**/*.rb"
63
+
64
+ # Get uncovered line counts
65
+ simplecov-mcp list --json | jq '.files[] | {file: .file, uncovered: (.total - .covered)}'
66
+ ```
67
+
68
+ **Detailed investigation:**
69
+ ```bash
70
+ # See detailed hit counts
71
+ simplecov-mcp detailed lib/auth_service.rb
72
+
73
+ # Show full source with coverage markers
74
+ simplecov-mcp summary lib/auth_service.rb --source=full
75
+
76
+ # Focus on uncovered areas only
77
+ simplecov-mcp uncovered lib/auth_service.rb --source=uncovered --source-context 5
78
+ ```
79
+
80
+ ### Working with JSON Output
81
+
82
+ **Parse and filter:**
83
+ ```bash
84
+ # Files below threshold
85
+ simplecov-mcp list --json | jq '.files[] | select(.percentage < 90) | {file, coverage: .percentage}'
86
+
87
+ # Count total uncovered lines
88
+ simplecov-mcp list --json | jq '[.files[] | (.total - .covered)] | add'
89
+
90
+ # Group by directory
91
+ simplecov-mcp list --json | jq 'group_by(.file | split("/")[0]) | map({dir: .[0].file | split("/")[0], avg: (map(.percentage) | add / length)})'
92
+ ```
93
+
94
+ **Generate reports:**
95
+ ```bash
96
+ # Create markdown table
97
+ echo "| File | Coverage |" > report.md
98
+ echo "|------|----------|" >> report.md
99
+ simplecov-mcp list --json | jq -r '.files[] | "| \(.file) | \(.percentage)% |"' >> report.md
100
+
101
+ # Export for spreadsheet
102
+ simplecov-mcp list --json | jq -r '.files[] | [.file, .percentage] | @csv' > coverage.csv
103
+ ```
104
+
105
+ ## Ruby Library Examples
106
+
107
+ ### Basic Usage
108
+
109
+ ```ruby
110
+ require "simplecov_mcp"
111
+
112
+ model = SimpleCovMcp::CoverageModel.new
113
+
114
+ # Get all files with coverage
115
+ files = model.all_files
116
+ puts "Total files: #{files.length}"
117
+ puts "Average coverage: #{files.sum { |f| f['percentage'] } / files.length}%"
118
+
119
+ # Check specific file
120
+ summary = model.summary_for("lib/auth_service.rb")
121
+ puts "Coverage: #{summary['summary']['pct']}%"
122
+
123
+ # Find uncovered lines
124
+ uncovered = model.uncovered_for("lib/auth_service.rb")
125
+ puts "Uncovered lines: #{uncovered['uncovered'].join(', ')}"
126
+ ```
127
+
128
+ ### Filtering and Analysis
129
+
130
+ ```ruby
131
+ require "simplecov_mcp"
132
+
133
+ model = SimpleCovMcp::CoverageModel.new
134
+ all_files = model.all_files
135
+
136
+ # Find files below threshold
137
+ THRESHOLD = 80.0
138
+ low_coverage = all_files.select { |f| f['percentage'] < THRESHOLD }
139
+
140
+ if low_coverage.any?
141
+ puts "Files below #{THRESHOLD}%:"
142
+ low_coverage.each do |file|
143
+ puts " #{file['file']}: #{file['percentage']}%"
144
+ end
145
+ end
146
+
147
+ # Group by directory
148
+ by_dir = all_files.group_by { |f| File.dirname(f['file']) }
149
+ by_dir.each do |dir, files|
150
+ avg = files.sum { |f| f['percentage'] } / files.length
151
+ puts "#{dir}: #{avg.round(2)}% (#{files.length} files)"
152
+ end
153
+ ```
154
+
155
+ ### Custom Formatting
156
+
157
+ ```ruby
158
+ require "simplecov_mcp"
159
+
160
+ model = SimpleCovMcp::CoverageModel.new
161
+ all_files = model.all_files
162
+
163
+ # Filter to specific directory
164
+ lib_files = all_files.select { |f| f['file'].start_with?('lib/') }
165
+
166
+ # Generate custom table
167
+ table = model.format_table(lib_files, sort_order: :ascending)
168
+ puts table
169
+
170
+ # Or create your own format
171
+ lib_files.each do |file|
172
+ status = file['percentage'] >= 90 ? '✓' : '⚠'
173
+ puts "#{status} #{file['file']}: #{file['percentage']}%"
174
+ end
175
+ ```
176
+
177
+ ## AI Assistant Prompts
178
+
179
+ ### Coverage Analysis
180
+
181
+ ```
182
+ Using simplecov-mcp, show me a table of all files sorted by coverage percentage.
183
+ ```
184
+
185
+ ```
186
+ Using simplecov-mcp, find the 10 files with the lowest coverage and create a markdown report with:
187
+ 1. File path
188
+ 2. Current coverage %
189
+ 3. Number of uncovered lines
190
+ ```
191
+
192
+ ```
193
+ Using simplecov-mcp, analyze the lib/services/ directory and identify which files should be prioritized for additional testing based on coverage gaps and file complexity.
194
+ ```
195
+
196
+ ### Finding Specific Issues
197
+
198
+ ```
199
+ Using simplecov-mcp, show me the uncovered lines in lib/auth_service.rb with 5 lines of context around each uncovered block.
200
+ ```
201
+
202
+ ```
203
+ Using simplecov-mcp, find all files in lib/models/ with less than 80% coverage and list the specific uncovered line numbers for each.
204
+ ```
205
+
206
+ ### Test Generation
207
+
208
+ ```
209
+ Using simplecov-mcp, identify the uncovered lines in lib/payment_processor.rb and write RSpec tests to cover them.
210
+ ```
211
+
212
+ ```
213
+ Using simplecov-mcp, analyze coverage gaps in the lib/api/ directory and generate a test plan prioritizing:
214
+ 1. Public API methods
215
+ 2. Error handling paths
216
+ 3. Edge cases
217
+ ```
218
+
219
+ ### Reporting
220
+
221
+ ```
222
+ Using simplecov-mcp, create a coverage report showing:
223
+ - Overall project coverage percentage
224
+ - Top 5 files with worst coverage
225
+ - Recommended next steps to improve coverage
226
+
227
+ Format as markdown.
228
+ ```
229
+
230
+ ## CI/CD Integration
231
+
232
+ ### GitHub Actions
233
+
234
+ **Fail on low coverage:**
235
+ ```yaml
236
+ name: Coverage Check
237
+
238
+ on: [push, pull_request]
239
+
240
+ jobs:
241
+ coverage:
242
+ runs-on: ubuntu-latest
243
+ steps:
244
+ - uses: actions/checkout@v3
245
+
246
+ - name: Setup Ruby
247
+ uses: ruby/setup-ruby@v1
248
+ with:
249
+ ruby-version: 3.3
250
+ bundler-cache: true
251
+
252
+ - name: Run tests
253
+ run: bundle exec rspec
254
+
255
+ - name: Install simplecov-mcp
256
+ run: gem install simplecov-mcp
257
+
258
+ - name: Check coverage threshold
259
+ run: |
260
+ simplecov-mcp list --json > coverage.json
261
+ BELOW_THRESHOLD=$(jq '[.files[] | select(.percentage < 80)] | length' coverage.json)
262
+ if [ "$BELOW_THRESHOLD" -gt 0 ]; then
263
+ echo "❌ $BELOW_THRESHOLD files below 80% coverage"
264
+ jq -r '.files[] | select(.percentage < 80) | "\(.file): \(.percentage)%"' coverage.json
265
+ exit 1
266
+ fi
267
+ echo "✓ All files meet coverage threshold"
268
+
269
+ - name: Upload coverage report
270
+ uses: actions/upload-artifact@v3
271
+ with:
272
+ name: coverage-report
273
+ path: coverage.json
274
+ ```
275
+
276
+ **Check for stale coverage:**
277
+ ```yaml
278
+ - name: Verify coverage is fresh
279
+ run: simplecov-mcp --stale error || exit 1
280
+ ```
281
+
282
+ ### GitLab CI
283
+
284
+ ```yaml
285
+ test:
286
+ image: ruby:3.3
287
+ before_script:
288
+ - gem install simplecov-mcp
289
+ script:
290
+ - bundle exec rspec
291
+ - simplecov-mcp --stale error
292
+ artifacts:
293
+ paths:
294
+ - coverage/
295
+ reports:
296
+ coverage_report:
297
+ coverage_format: simplecov
298
+ path: coverage/.resultset.json
299
+ ```
300
+
301
+ ### Custom Success Predicate
302
+
303
+ ```ruby
304
+ # coverage_policy.rb
305
+ ->(model) do
306
+ all_files = model.all_files
307
+
308
+ # Must have at least 80% average coverage
309
+ avg_coverage = all_files.sum { |f| f['percentage'] } / all_files.length
310
+ return false if avg_coverage < 80.0
311
+
312
+ # No files below 60%
313
+ return false if all_files.any? { |f| f['percentage'] < 60.0 }
314
+
315
+ # lib/ files must average 90%
316
+ lib_files = all_files.select { |f| f['file'].start_with?('lib/') }
317
+ lib_avg = lib_files.sum { |f| f['percentage'] } / lib_files.length
318
+ return false if lib_avg < 90.0
319
+
320
+ true
321
+ end
322
+ ```
323
+
324
+ ```bash
325
+ # Use in CI
326
+ simplecov-mcp --success-predicate coverage_policy.rb
327
+ ```
328
+
329
+ ## Advanced Usage
330
+
331
+ ### Directory-Level Analysis
332
+
333
+ ```ruby
334
+ require "simplecov_mcp"
335
+
336
+ model = SimpleCovMcp::CoverageModel.new
337
+ all_files = model.all_files
338
+
339
+ # Calculate coverage by directory
340
+ by_directory = all_files.group_by { |f| f['file'].split('/')[0..1].join('/') }
341
+
342
+ results = by_directory.map do |dir, files|
343
+ total_lines = files.sum { |f| f['total'] }
344
+ covered_lines = files.sum { |f| f['covered'] }
345
+ percentage = (covered_lines.to_f / total_lines * 100).round(2)
346
+
347
+ {
348
+ directory: dir,
349
+ files: files.length,
350
+ coverage: percentage,
351
+ covered: covered_lines,
352
+ total: total_lines
353
+ }
354
+ end
355
+
356
+ # Sort by coverage ascending
357
+ results.sort_by { |r| r[:coverage] }.each do |r|
358
+ puts "#{r[:directory]}: #{r[:coverage]}% (#{r[:files]} files)"
359
+ end
360
+ ```
361
+
362
+ ### Coverage Delta Tracking
363
+
364
+ ```ruby
365
+ require "simplecov_mcp"
366
+ require "json"
367
+
368
+ # Save current coverage
369
+ model = SimpleCovMcp::CoverageModel.new
370
+ current = model.all_files
371
+
372
+ File.write("coverage_baseline.json", JSON.pretty_generate(current))
373
+
374
+ # Later, compare with baseline
375
+ baseline = JSON.parse(File.read("coverage_baseline.json"))
376
+
377
+ current.each do |file|
378
+ baseline_file = baseline.find { |f| f['file'] == file['file'] }
379
+ next unless baseline_file
380
+
381
+ delta = file['percentage'] - baseline_file['percentage']
382
+ if delta.abs > 0.1 # Changed by more than 0.1%
383
+ symbol = delta > 0 ? '↑' : '↓'
384
+ puts "#{symbol} #{file['file']}: #{baseline_file['percentage']}% → #{file['percentage']}%"
385
+ end
386
+ end
387
+ ```
388
+
389
+ ### Integration with Code Review
390
+
391
+ ```ruby
392
+ # pr_coverage_check.rb
393
+ require "simplecov_mcp"
394
+ require "json"
395
+
396
+ model = SimpleCovMcp::CoverageModel.new
397
+
398
+ # Get changed files from PR (example using git)
399
+ changed_files = `git diff --name-only origin/main`.split("\n")
400
+ changed_files.select! { |f| f.end_with?('.rb') }
401
+
402
+ puts "## Coverage Report for Changed Files\n\n"
403
+ puts "| File | Coverage | Status |"
404
+ puts "|------|----------|--------|"
405
+
406
+ changed_files.each do |file|
407
+ begin
408
+ summary = model.summary_for(file)
409
+ pct = summary['summary']['pct']
410
+ status = pct >= 80 ? '✅' : '⚠️'
411
+ puts "| #{file} | #{pct}% | #{status} |"
412
+ rescue
413
+ puts "| #{file} | N/A | ❌ No coverage |"
414
+ end
415
+ end
416
+ ```
417
+
418
+ ## Example Scripts
419
+
420
+ The [`/examples`](/examples) directory contains runnable scripts:
421
+
422
+ - **[filter_and_table_demo.rb](/examples/filter_and_table_demo.rb)** - Filter and format coverage data
423
+ - **[success_predicates/](/examples/success_predicates/)** - Custom coverage policy examples
424
+
425
+ ## Related Documentation
426
+
427
+ - [CLI Usage Guide](CLI_USAGE.md) - Complete command reference
428
+ - [Library API Guide](LIBRARY_API.md) - Ruby API documentation
429
+ - [MCP Integration](MCP_INTEGRATION.md) - AI assistant setup
430
+ - [Troubleshooting](TROUBLESHOOTING.md) - Common issues