simplecov-mcp 1.0.0 → 2.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 (164) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -50
  3. data/docs/{ARCHITECTURE.md → dev/ARCHITECTURE.md} +11 -10
  4. data/docs/dev/BRANCH_ONLY_COVERAGE.md +158 -0
  5. data/docs/{DEVELOPMENT.md → dev/DEVELOPMENT.md} +2 -1
  6. data/docs/dev/README.md +10 -0
  7. data/docs/dev/RELEASING.md +146 -0
  8. data/docs/{arch-decisions → dev/arch-decisions}/001-x-arch-decision.md +3 -1
  9. data/docs/{arch-decisions → dev/arch-decisions}/002-x-arch-decision.md +7 -5
  10. data/docs/{arch-decisions → dev/arch-decisions}/003-x-arch-decision.md +2 -0
  11. data/docs/{arch-decisions → dev/arch-decisions}/004-x-arch-decision.md +6 -2
  12. data/docs/{arch-decisions → dev/arch-decisions}/005-x-arch-decision.md +4 -2
  13. data/docs/{arch-decisions → dev/arch-decisions}/README.md +3 -3
  14. data/docs/{presentations → dev/presentations}/simplecov-mcp-presentation.md +28 -22
  15. data/docs/fixtures/demo_project/README.md +9 -0
  16. data/docs/{ADVANCED_USAGE.md → user/ADVANCED_USAGE.md} +129 -319
  17. data/docs/user/CLI_FALLBACK_FOR_LLMS.md +34 -0
  18. data/docs/user/CLI_USAGE.md +750 -0
  19. data/docs/{ERROR_HANDLING.md → user/ERROR_HANDLING.md} +12 -12
  20. data/docs/user/EXAMPLES.md +588 -0
  21. data/docs/user/INSTALLATION.md +130 -0
  22. data/docs/{LIBRARY_API.md → user/LIBRARY_API.md} +90 -32
  23. data/docs/{MCP_INTEGRATION.md → user/MCP_INTEGRATION.md} +36 -34
  24. data/docs/user/README.md +14 -0
  25. data/docs/{TROUBLESHOOTING.md → user/TROUBLESHOOTING.md} +21 -100
  26. data/docs/user/V2-BREAKING-CHANGES.md +472 -0
  27. data/exe/simplecov-mcp +1 -1
  28. data/lib/simplecov_mcp/{cli_config.rb → app_config.rb} +12 -12
  29. data/lib/simplecov_mcp/app_context.rb +1 -1
  30. data/lib/simplecov_mcp/base_tool.rb +66 -38
  31. data/lib/simplecov_mcp/cli.rb +67 -123
  32. data/lib/simplecov_mcp/commands/base_command.rb +16 -27
  33. data/lib/simplecov_mcp/commands/command_factory.rb +8 -2
  34. data/lib/simplecov_mcp/commands/detailed_command.rb +16 -2
  35. data/lib/simplecov_mcp/commands/list_command.rb +1 -1
  36. data/lib/simplecov_mcp/commands/raw_command.rb +18 -2
  37. data/lib/simplecov_mcp/commands/summary_command.rb +20 -3
  38. data/lib/simplecov_mcp/commands/totals_command.rb +53 -0
  39. data/lib/simplecov_mcp/commands/uncovered_command.rb +24 -5
  40. data/lib/simplecov_mcp/commands/validate_command.rb +60 -0
  41. data/lib/simplecov_mcp/commands/version_command.rb +19 -4
  42. data/lib/simplecov_mcp/config_parser.rb +32 -0
  43. data/lib/simplecov_mcp/constants.rb +3 -3
  44. data/lib/simplecov_mcp/coverage_reporter.rb +31 -0
  45. data/lib/simplecov_mcp/error_handler.rb +81 -40
  46. data/lib/simplecov_mcp/error_handler_factory.rb +2 -2
  47. data/lib/simplecov_mcp/errors.rb +32 -20
  48. data/lib/simplecov_mcp/formatters/source_formatter.rb +23 -19
  49. data/lib/simplecov_mcp/formatters.rb +51 -0
  50. data/lib/simplecov_mcp/mcp_server.rb +9 -7
  51. data/lib/simplecov_mcp/mode_detector.rb +6 -5
  52. data/lib/simplecov_mcp/model.rb +122 -83
  53. data/lib/simplecov_mcp/option_normalizers.rb +39 -18
  54. data/lib/simplecov_mcp/option_parser_builder.rb +82 -65
  55. data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +3 -5
  56. data/lib/simplecov_mcp/option_parsers/error_helper.rb +18 -17
  57. data/lib/simplecov_mcp/path_relativizer.rb +17 -14
  58. data/lib/simplecov_mcp/predicate_evaluator.rb +72 -0
  59. data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +1 -3
  60. data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +1 -3
  61. data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +1 -3
  62. data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +1 -3
  63. data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +1 -3
  64. data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +1 -3
  65. data/lib/simplecov_mcp/presenters/project_totals_presenter.rb +27 -0
  66. data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +14 -18
  67. data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +7 -9
  68. data/lib/simplecov_mcp/resultset_loader.rb +20 -25
  69. data/lib/simplecov_mcp/staleness_checker.rb +50 -46
  70. data/lib/simplecov_mcp/table_formatter.rb +64 -0
  71. data/lib/simplecov_mcp/tools/all_files_coverage_tool.rb +20 -50
  72. data/lib/simplecov_mcp/tools/coverage_detailed_tool.rb +13 -7
  73. data/lib/simplecov_mcp/tools/coverage_raw_tool.rb +12 -7
  74. data/lib/simplecov_mcp/tools/coverage_summary_tool.rb +13 -8
  75. data/lib/simplecov_mcp/tools/coverage_table_tool.rb +20 -60
  76. data/lib/simplecov_mcp/tools/coverage_totals_tool.rb +44 -0
  77. data/lib/simplecov_mcp/tools/help_tool.rb +38 -66
  78. data/lib/simplecov_mcp/tools/uncovered_lines_tool.rb +13 -8
  79. data/lib/simplecov_mcp/tools/validate_tool.rb +72 -0
  80. data/lib/simplecov_mcp/tools/version_tool.rb +7 -14
  81. data/lib/simplecov_mcp/util.rb +18 -12
  82. data/lib/simplecov_mcp/version.rb +1 -1
  83. data/lib/simplecov_mcp.rb +23 -29
  84. data/spec/all_files_coverage_tool_spec.rb +4 -3
  85. data/spec/{cli_config_spec.rb → app_config_spec.rb} +31 -26
  86. data/spec/base_tool_spec.rb +17 -14
  87. data/spec/cli/show_default_report_spec.rb +2 -2
  88. data/spec/cli_enumerated_options_spec.rb +31 -9
  89. data/spec/cli_error_spec.rb +46 -23
  90. data/spec/cli_format_spec.rb +123 -0
  91. data/spec/cli_json_options_spec.rb +50 -0
  92. data/spec/cli_source_spec.rb +11 -63
  93. data/spec/cli_spec.rb +82 -97
  94. data/spec/cli_usage_spec.rb +15 -15
  95. data/spec/commands/base_command_spec.rb +12 -92
  96. data/spec/commands/command_factory_spec.rb +7 -3
  97. data/spec/commands/detailed_command_spec.rb +10 -24
  98. data/spec/commands/list_command_spec.rb +28 -0
  99. data/spec/commands/raw_command_spec.rb +43 -20
  100. data/spec/commands/summary_command_spec.rb +10 -23
  101. data/spec/commands/totals_command_spec.rb +34 -0
  102. data/spec/commands/uncovered_command_spec.rb +29 -23
  103. data/spec/commands/validate_command_spec.rb +213 -0
  104. data/spec/commands/version_command_spec.rb +38 -0
  105. data/spec/constants_spec.rb +3 -3
  106. data/spec/coverage_reporter_spec.rb +102 -0
  107. data/spec/coverage_table_tool_spec.rb +21 -10
  108. data/spec/coverage_totals_tool_spec.rb +37 -0
  109. data/spec/error_handler_spec.rb +120 -4
  110. data/spec/error_mode_spec.rb +18 -22
  111. data/spec/errors_edge_cases_spec.rb +101 -28
  112. data/spec/errors_stale_spec.rb +34 -0
  113. data/spec/file_based_mcp_tools_spec.rb +6 -6
  114. data/spec/fixtures/project1/lib/bar.rb +2 -0
  115. data/spec/fixtures/project1/lib/foo.rb +2 -0
  116. data/spec/help_tool_spec.rb +2 -18
  117. data/spec/integration_spec.rb +114 -170
  118. data/spec/logging_fallback_spec.rb +3 -3
  119. data/spec/mcp_server_integration_spec.rb +1 -1
  120. data/spec/mcp_server_spec.rb +70 -53
  121. data/spec/mode_detector_spec.rb +46 -41
  122. data/spec/model_error_handling_spec.rb +141 -82
  123. data/spec/model_staleness_spec.rb +13 -13
  124. data/spec/option_normalizers_spec.rb +111 -112
  125. data/spec/option_parsers/env_options_parser_spec.rb +25 -37
  126. data/spec/option_parsers/error_helper_spec.rb +56 -56
  127. data/spec/path_relativizer_spec.rb +15 -0
  128. data/spec/presenters/coverage_detailed_presenter_spec.rb +1 -1
  129. data/spec/presenters/coverage_summary_presenter_spec.rb +1 -1
  130. data/spec/presenters/coverage_uncovered_presenter_spec.rb +1 -1
  131. data/spec/presenters/project_coverage_presenter_spec.rb +9 -8
  132. data/spec/presenters/project_totals_presenter_spec.rb +144 -0
  133. data/spec/resolvers/coverage_line_resolver_spec.rb +261 -36
  134. data/spec/resolvers/resultset_path_resolver_spec.rb +13 -8
  135. data/spec/shared_examples/file_based_mcp_tools.rb +23 -18
  136. data/spec/shared_examples/formatted_command_examples.rb +64 -0
  137. data/spec/simple_cov_mcp_module_spec.rb +24 -3
  138. data/spec/simplecov_mcp/formatters/source_formatter_spec.rb +267 -0
  139. data/spec/simplecov_mcp/formatters_spec.rb +76 -0
  140. data/spec/simplecov_mcp/presenters/base_coverage_presenter_spec.rb +79 -0
  141. data/spec/simplecov_mcp_model_spec.rb +99 -49
  142. data/spec/simplecov_mcp_opts_spec.rb +42 -39
  143. data/spec/spec_helper.rb +27 -92
  144. data/spec/staleness_checker_spec.rb +10 -9
  145. data/spec/staleness_more_spec.rb +4 -4
  146. data/spec/support/cli_helpers.rb +22 -0
  147. data/spec/support/control_flow_helpers.rb +20 -0
  148. data/spec/support/fake_mcp.rb +40 -0
  149. data/spec/support/io_helpers.rb +29 -0
  150. data/spec/support/mcp_helpers.rb +35 -0
  151. data/spec/support/mcp_runner.rb +10 -8
  152. data/spec/support/mocking_helpers.rb +30 -0
  153. data/spec/table_format_spec.rb +70 -0
  154. data/spec/tools/validate_tool_spec.rb +132 -0
  155. data/spec/tools_error_handling_spec.rb +34 -48
  156. data/spec/util_spec.rb +5 -4
  157. data/spec/version_spec.rb +7 -7
  158. data/spec/version_tool_spec.rb +20 -22
  159. metadata +90 -23
  160. data/docs/BRANCH_ONLY_COVERAGE.md +0 -81
  161. data/docs/CLI_USAGE.md +0 -637
  162. data/docs/EXAMPLES.md +0 -430
  163. data/docs/INSTALLATION.md +0 -352
  164. data/spec/cli_success_predicate_spec.rb +0 -141
@@ -0,0 +1,130 @@
1
+ # Installation Guide
2
+
3
+ [Back to main README](../README.md)
4
+
5
+ ## Prerequisites
6
+
7
+ - **Ruby >= 3.2** (required by the `mcp` dependency)
8
+ - SimpleCov-generated `.resultset.json` file in your project
9
+
10
+ ## Quick Install
11
+
12
+ ### Via RubyGems
13
+
14
+ ```sh
15
+ gem install simplecov-mcp
16
+ ```
17
+
18
+ ### Via Bundler
19
+
20
+ Add to your `Gemfile`:
21
+
22
+ ```ruby
23
+ gem 'simplecov-mcp'
24
+ ```
25
+
26
+ Then run:
27
+
28
+ ```sh
29
+ bundle install
30
+ ```
31
+
32
+ ### From Source
33
+
34
+ ```sh
35
+ git clone https://github.com/keithrbennett/simplecov-mcp.git
36
+ cd simplecov-mcp
37
+ bundle install
38
+ gem build simplecov-mcp.gemspec
39
+ gem install simplecov-mcp-*.gem
40
+ ```
41
+
42
+ ## Require Path
43
+
44
+ The gem uses a single require path:
45
+
46
+ ```ruby
47
+ require "simplecov_mcp"
48
+ ```
49
+
50
+ The executable is `simplecov-mcp` (with hyphen).
51
+
52
+ ## PATH Configuration
53
+
54
+ ### With Version Managers
55
+
56
+ Most version managers (rbenv, asdf, RVM, chruby) automatically configure PATH. After installation:
57
+
58
+ ```sh
59
+ # Refresh shims if needed
60
+ rbenv rehash # rbenv
61
+ asdf reshim ruby # asdf
62
+
63
+ # Verify executable is accessible
64
+ which simplecov-mcp
65
+ ```
66
+
67
+ **Important:** When changing Ruby versions, reinstall the gem and update any MCP configurations that use absolute paths.
68
+
69
+ ### Bundler Execution
70
+
71
+ If PATH setup is problematic, use bundler:
72
+
73
+ ```sh
74
+ bundle exec simplecov-mcp
75
+ ```
76
+
77
+ This works from any project directory that has simplecov-mcp in its Gemfile.
78
+
79
+ ## Verification
80
+
81
+ ### Test Installation
82
+
83
+ ```sh
84
+ # Check version
85
+ simplecov-mcp version
86
+
87
+ # Show help
88
+ simplecov-mcp --help
89
+
90
+ # Run on current project (requires coverage data)
91
+ simplecov-mcp
92
+ ```
93
+
94
+ ### Generate Test Coverage
95
+
96
+ If you don't have coverage data yet:
97
+
98
+ ```sh
99
+ # Run your tests with SimpleCov enabled
100
+ bundle exec rspec # or your test command
101
+
102
+ # Verify coverage file exists
103
+ ls -l coverage/.resultset.json
104
+
105
+ # Now test simplecov-mcp
106
+ simplecov-mcp
107
+ ```
108
+
109
+ ## Platform-Specific Notes
110
+
111
+ ### macOS
112
+
113
+ Works with system Ruby or any version manager. Recommended: use rbenv or asdf, not rvm (see note below).
114
+
115
+ **Note:** RVM may not work in sandboxed environments (e.g., AI coding assistants) because it requires `/bin/ps`, which sandbox restrictions often block. Use rbenv or chruby instead for sandboxed environments.
116
+
117
+ ### Linux
118
+
119
+ Works with system Ruby or any version manager.
120
+
121
+ ### Windows
122
+
123
+ Should work with Ruby installed via RubyInstaller. PATH configuration may differ.
124
+
125
+ ## Next Steps
126
+
127
+ - **[CLI Usage](CLI_USAGE.md)** - Learn command-line options
128
+ - **[Library API](LIBRARY_API.md)** - Use in Ruby code
129
+ - **[MCP Integration](MCP_INTEGRATION.md)** - Connect to AI assistants
130
+ - **[Troubleshooting](TROUBLESHOOTING.md)** - More detailed troubleshooting
@@ -1,5 +1,7 @@
1
1
  # Library API Guide
2
2
 
3
+ [Back to main README](../README.md)
4
+
3
5
  Use this gem programmatically to inspect coverage without running the CLI or MCP server. The primary entry point is `SimpleCovMcp::CoverageModel`.
4
6
 
5
7
  ## Table of Contents
@@ -42,12 +44,12 @@ raw = model.raw_for("lib/foo.rb")
42
44
 
43
45
  ## Method Reference
44
46
 
45
- ### `all_files(sort_order: :ascending)`
47
+ ### `all_files(sort_order: :descending)`
46
48
 
47
49
  Returns coverage summary for all files in the resultset.
48
50
 
49
51
  **Parameters:**
50
- - `sort_order` (Symbol, optional): `:ascending` (default) or `:descending` by coverage percentage
52
+ - `sort_order` (Symbol, optional): `:descending` (default) or `:ascending` by coverage percentage
51
53
 
52
54
  **Returns:** `Array<Hash>` - See [all_files return type](#all_files)
53
55
 
@@ -74,7 +76,7 @@ Returns coverage summary for a specific file.
74
76
  **Example:**
75
77
  ```ruby
76
78
  summary = model.summary_for("lib/foo.rb")
77
- # => { 'file' => '/abs/.../lib/foo.rb', 'summary' => {'covered'=>12, 'total'=>14, 'pct'=>85.71}, 'stale' => false }
79
+ # => { 'file' => '/abs/.../lib/foo.rb', 'summary' => {'covered'=>12, 'total'=>14, 'percentage'=>85.71}, 'stale' => false }
78
80
  ```
79
81
 
80
82
  ### `uncovered_for(path)`
@@ -128,13 +130,13 @@ raw = model.raw_for("lib/foo.rb")
128
130
  # => { 'file' => '/abs/.../lib/foo.rb', 'lines' => [nil, 1, 0, 3, ...], 'stale' => false }
129
131
  ```
130
132
 
131
- ### `format_table(rows = nil, sort_order: :ascending)`
133
+ ### `format_table(rows = nil, sort_order: :descending)`
132
134
 
133
135
  Generates formatted ASCII table string.
134
136
 
135
137
  **Parameters:**
136
138
  - `rows` (Array<Hash>, optional): Custom row data; defaults to `all_files`
137
- - `sort_order` (Symbol, optional): `:ascending` (default) or `:descending`
139
+ - `sort_order` (Symbol, optional): `:descending` (default) or `:ascending`
138
140
 
139
141
  **Returns:** `String` - Formatted table with Unicode borders
140
142
 
@@ -150,6 +152,46 @@ lib_table = model.format_table(lib_files, sort_order: :descending)
150
152
  puts lib_table
151
153
  ```
152
154
 
155
+ ### `project_totals(tracked_globs: nil)`
156
+
157
+ Returns aggregated coverage totals across all files.
158
+
159
+ **Parameters:**
160
+ - `tracked_globs` (Array<String> or String, optional): Glob patterns to filter files
161
+
162
+ **Returns:** `Hash` - See [project_totals return type](#project_totals)
163
+
164
+ **Example:**
165
+ ```ruby
166
+ totals = model.project_totals
167
+ # => { 'lines' => { 'total' => 123, 'covered' => 100, 'uncovered' => 23 }, 'percentage' => 81.3, 'files' => { 'total' => 5, 'ok' => 4, 'stale' => 1 } }
168
+
169
+ # Filter to specific directory
170
+ lib_totals = model.project_totals(tracked_globs: 'lib/**/*.rb')
171
+ ```
172
+
173
+ ### `relativize(data)`
174
+
175
+ Converts absolute file paths in coverage data to relative paths from project root.
176
+
177
+ **Parameters:**
178
+ - `data` (Hash or Array<Hash>): Coverage data with absolute file paths
179
+
180
+ **Returns:** `Hash` or `Array<Hash>` - Same structure with relative paths
181
+
182
+ **Example:**
183
+ ```ruby
184
+ summary = model.summary_for('lib/simplecov_mcp/model.rb')
185
+ # => { 'file' => '/home/user/project/lib/simplecov_mcp/model.rb', ... }
186
+
187
+ relative_summary = model.relativize(summary)
188
+ # => { 'file' => 'lib/simplecov_mcp/model.rb', ... }
189
+
190
+ # Works with arrays too
191
+ files = model.all_files
192
+ relative_files = model.relativize(files)
193
+ ```
194
+
153
195
  ## Return Types
154
196
 
155
197
  ### `all_files`
@@ -176,7 +218,7 @@ Returns `Hash`:
176
218
  'summary' => {
177
219
  'covered' => Integer, # Number of covered lines
178
220
  'total' => Integer, # Total relevant lines
179
- 'pct' => Float # Coverage percentage (0.00-100.00)
221
+ 'percentage' => Float # Coverage percentage (0.00-100.00)
180
222
  }
181
223
  }
182
224
  ```
@@ -192,7 +234,7 @@ Returns `Hash`:
192
234
  'summary' => {
193
235
  'covered' => Integer,
194
236
  'total' => Integer,
195
- 'pct' => Float
237
+ 'percentage' => Float
196
238
  }
197
239
  }
198
240
  ```
@@ -208,7 +250,7 @@ Returns `Hash`:
208
250
  'summary' => {
209
251
  'covered' => Integer,
210
252
  'total' => Integer,
211
- 'pct' => Float
253
+ 'percentage' => Float
212
254
  }
213
255
  }
214
256
  ```
@@ -233,6 +275,26 @@ Returns `Hash`:
233
275
  }
234
276
  ```
235
277
 
278
+ ### `project_totals`
279
+
280
+ Returns `Hash`:
281
+
282
+ ```ruby
283
+ {
284
+ 'lines' => {
285
+ 'total' => Integer, # Total relevant lines across all files
286
+ 'covered' => Integer, # Total covered lines
287
+ 'uncovered' => Integer # Total uncovered lines
288
+ },
289
+ 'percentage' => Float, # Overall coverage percentage
290
+ 'files' => {
291
+ 'total' => Integer, # Total number of files
292
+ 'ok' => Integer, # Files with fresh coverage
293
+ 'stale' => Integer # Files with stale coverage
294
+ }
295
+ }
296
+ ```
297
+
236
298
  ## Error Handling
237
299
 
238
300
  ### Exception Types
@@ -254,7 +316,7 @@ require "simplecov_mcp"
254
316
  begin
255
317
  model = SimpleCovMcp::CoverageModel.new
256
318
  summary = model.summary_for("lib/foo.rb")
257
- puts "Coverage: #{summary['summary']['pct']}%"
319
+ puts "Coverage: #{summary['summary']['percentage']}%"
258
320
  rescue SimpleCovMcp::FileError => e
259
321
  puts "File not in coverage data: #{e.message}"
260
322
  rescue SimpleCovMcp::ResultsetNotFoundError => e
@@ -313,7 +375,7 @@ summary = find_coverage(model, [
313
375
  ])
314
376
 
315
377
  if summary
316
- puts "Coverage: #{summary['summary']['pct']}%"
378
+ puts "Coverage: #{summary['summary']['percentage']}%"
317
379
  else
318
380
  puts "File not found in coverage data"
319
381
  end
@@ -340,8 +402,8 @@ results = files_to_check.map do |path|
340
402
  summary = model.summary_for(path)
341
403
  {
342
404
  file: path,
343
- coverage: summary['summary']['pct'],
344
- status: summary['summary']['pct'] >= 80 ? :ok : :low
405
+ coverage: summary['summary']['percentage'],
406
+ status: summary['summary']['percentage'] >= 80 ? :ok : :low
345
407
  }
346
408
  rescue SimpleCovMcp::FileError
347
409
  {
@@ -425,25 +487,19 @@ validator.validate!
425
487
  require "simplecov_mcp"
426
488
 
427
489
  model = SimpleCovMcp::CoverageModel.new
428
- files = model.all_files
429
490
 
430
- # Calculate coverage by directory
431
- by_directory = files.group_by do |file|
432
- # Get first two path components (e.g., "lib/services")
433
- file['file'].split('/')[0..1].join('/')
434
- end
491
+ # Calculate coverage by directory using the totals API
492
+ patterns = %w[lib/simplecov_mcp/tools/**/*.rb lib/simplecov_mcp/commands/**/*.rb lib/simplecov_mcp/presenters/**/*.rb]
435
493
 
436
- directory_stats = by_directory.map do |dir, dir_files|
437
- total_lines = dir_files.sum { |f| f['total'] }
438
- covered_lines = dir_files.sum { |f| f['covered'] }
439
- percentage = (covered_lines.to_f / total_lines * 100).round(2)
494
+ directory_stats = patterns.map do |pattern|
495
+ totals = model.project_totals(tracked_globs: pattern)
440
496
 
441
497
  {
442
- directory: dir,
443
- files: dir_files.length,
444
- coverage: percentage,
445
- covered: covered_lines,
446
- total: total_lines
498
+ directory: pattern,
499
+ files: totals['files']['total'],
500
+ coverage: totals['percentage'].round(2),
501
+ covered: totals['lines']['covered'],
502
+ total: totals['lines']['total']
447
503
  }
448
504
  end
449
505
 
@@ -545,6 +601,7 @@ class CoverageReporter
545
601
 
546
602
  def generate_markdown_report(output_path)
547
603
  files = @model.all_files
604
+ totals = @model.project_totals
548
605
 
549
606
  File.open(output_path, 'w') do |f|
550
607
  f.puts "# Coverage Report"
@@ -553,13 +610,14 @@ class CoverageReporter
553
610
  f.puts
554
611
 
555
612
  # Overall stats
556
- total_lines = files.sum { |file| file['total'] }
557
- covered_lines = files.sum { |file| file['covered'] }
558
- overall_pct = (covered_lines.to_f / total_lines * 100).round(2)
613
+ overall_percentage = totals['percentage']
614
+ total_lines = totals['lines']['total']
615
+ covered_lines = totals['lines']['covered']
616
+ total_files = totals['files']['total']
559
617
 
560
- f.puts "## Overall Coverage: #{overall_pct}%"
618
+ f.puts "## Overall Coverage: #{overall_percentage}%"
561
619
  f.puts
562
- f.puts "- Total Files: #{files.length}"
620
+ f.puts "- Total Files: #{total_files}"
563
621
  f.puts "- Total Lines: #{total_lines}"
564
622
  f.puts "- Covered Lines: #{covered_lines}"
565
623
  f.puts
@@ -1,6 +1,6 @@
1
1
  # MCP Integration Guide
2
2
 
3
- This guide covers setting up simplecov-mcp as an MCP (Model Context Protocol) server for AI coding assistants.
3
+ [Back to main README](../README.md)
4
4
 
5
5
  ## Table of Contents
6
6
 
@@ -213,7 +213,7 @@ For any MCP client that uses JSON configuration:
213
213
 
214
214
  ### Tool Catalog
215
215
 
216
- simplecov-mcp exposes 8 MCP tools:
216
+ simplecov-mcp exposes 10 MCP tools:
217
217
 
218
218
  | Tool | Purpose | Key Parameters |
219
219
  |------|---------|----------------|
@@ -222,8 +222,10 @@ simplecov-mcp exposes 8 MCP tools:
222
222
  | `coverage_raw_tool` | Raw SimpleCov array | `path` |
223
223
  | `uncovered_lines_tool` | List uncovered lines | `path` |
224
224
  | `all_files_coverage_tool` | Project-wide coverage | `sort_order`, `tracked_globs` |
225
+ | `coverage_totals_tool` | Aggregated line totals | `tracked_globs` |
225
226
  | `coverage_table_tool` | Formatted coverage table | `sort_order` |
226
- | `help_tool` | Tool discovery | `query` (optional) |
227
+ | `validate_tool` | Validate coverage policies | `code` or `file` |
228
+ | `help_tool` | Tool discovery | (none) |
227
229
  | `version_tool` | Version information | (none) |
228
230
 
229
231
  ### JSON Response Format
@@ -234,7 +236,7 @@ For tools that return structured data, `simplecov-mcp` serializes the data as a
234
236
  ```json
235
237
  {
236
238
  "type": "text",
237
- "text": "{"coverage_summary":{"covered":10,"total":20,"pct":50.0}}"
239
+ "text": "{"coverage_summary":{"covered":10,"total":20,"percentage":50.0}}"
238
240
  }
239
241
  ```
240
242
 
@@ -255,8 +257,8 @@ All file-specific tools accept these parameters:
255
257
  - `path` (required for file tools) - File path (relative or absolute)
256
258
  - `root` (optional) - Project root directory (default: `.`)
257
259
  - `resultset` (optional) - Path to the `.resultset.json` file. See [Configuring the Resultset](../README.md#configuring-the-resultset) for details.
258
- - `stale` (optional) - Staleness mode: `"off"` (default) or `"error"`
259
- - `error_mode` (optional) - Error handling: `"off"`, `"on"` (default), `"trace"`
260
+ - `staleness` (optional) - Staleness mode: `"off"` (default) or `"error"`
261
+ - `error_mode` (optional) - Error handling: `"off"`, `"log"` (default), `"debug"`
260
262
 
261
263
  ### Tool Details
262
264
 
@@ -266,7 +268,7 @@ These tools analyze individual files. All require `path` parameter.
266
268
 
267
269
  **`coverage_summary_tool`** - Covered/total/percentage summary
268
270
  ```json
269
- {"file": "...", "summary": {"covered": 12, "total": 14, "pct": 85.71}, "stale": false}
271
+ {"file": "...", "summary": {"covered": 12, "total": 14, "percentage": 85.71}, "stale": false}
270
272
  ```
271
273
 
272
274
  **`uncovered_lines_tool`** - List uncovered line numbers
@@ -290,13 +292,27 @@ These tools analyze individual files. All require `path` parameter.
290
292
  - Parameters: `sort_order` (`ascending`|`descending`), `tracked_globs` (array)
291
293
  - Returns: `{"files": [...], "counts": {"total": N, "ok": N, "stale": N}}`
292
294
 
295
+ **`coverage_totals_tool`** - Aggregated line totals
296
+ - Parameters: `tracked_globs` (array), `staleness`
297
+ - Returns: `{"lines":{"total":N,"covered":N,"uncovered":N},"percentage":Float,"files":{"total":N,"ok":N,"stale":N}}`
298
+
293
299
  **`coverage_table_tool`** - Formatted ASCII table
294
300
  - Parameters: `sort_order` (`ascending`|`descending`)
295
301
  - Returns: Plain text table
296
302
 
303
+ #### Policy Validation Tools
304
+
305
+ **`validate_tool`** - Validate coverage against custom policies
306
+ - Parameters: Either `code` (Ruby string) OR `file` (path to Ruby file), plus optional `root`, `resultset`, `staleness`, `error_mode`
307
+ - Returns: `{"result": Boolean}` where `true` means policy passed, `false` means failed
308
+ - Security Warning: Predicates execute as arbitrary Ruby code with full system privileges. Only use predicate files from trusted sources.
309
+ - Examples:
310
+ - Check if all files have at least 80% coverage: `{"code": "->(m) { m.all_files.all? { |f| f['percentage'] >= 80 } }"}`
311
+ - Run coverage policy from file: `{"file": "coverage_policy.rb"}`
312
+
297
313
  #### Utility Tools
298
314
 
299
- **`help_tool`** - Tool discovery (optional `query` parameter)
315
+ **`help_tool`** - Tool discovery
300
316
  **`version_tool`** - Version information
301
317
 
302
318
  ## Example Prompts for AI Assistants
@@ -396,18 +412,7 @@ tail -f simplecov_mcp.log
396
412
  grep ERROR simplecov_mcp.log | tail -20
397
413
  ```
398
414
 
399
- **Configure custom log location** when adding the server:
400
-
401
- ```sh
402
- # Claude Code
403
- claude mcp add simplecov-mcp simplecov-mcp --log-file /var/log/simplecov.log
404
-
405
- # Codex
406
- codex mcp add simplecov-mcp --command simplecov-mcp --args "--log-file" --args "/var/log/simplecov.log"
407
-
408
- # Log to stderr (Claude)
409
- claude mcp add simplecov-mcp simplecov-mcp --log-file stderr
410
- ```
415
+ To override the default log file location, specify the `--log-file` argument wherever and however you configure your MCP server. For example, to log to a different file path, include `--log-file /path/to/logfile.log` in your server configuration. To log to standard error, use `--log-file stderr`.
411
416
 
412
417
  **Note:** Logging to `stdout` is not permitted in MCP mode.
413
418
 
@@ -415,17 +420,13 @@ claude mcp add simplecov-mcp simplecov-mcp --log-file stderr
415
420
 
416
421
  ### CLI Fallback
417
422
 
418
- **Important:** If the MCP server doesn't work, use CLI commands with `--json` for structured output:
419
-
420
- ```sh
421
- simplecov-mcp summary lib/file.rb --json # coverage_summary_tool
422
- simplecov-mcp uncovered lib/file.rb --json # uncovered_lines_tool
423
- simplecov-mcp detailed lib/file.rb --json # coverage_detailed_tool
424
- simplecov-mcp list --json # all_files_coverage_tool
425
- simplecov-mcp version --json # version_tool
426
- ```
423
+ **Important:** If the MCP server doesn't work, you can use the CLI directly with the `-fJ` flag.
427
424
 
428
- See [CLI Usage](CLI_USAGE.md) for complete documentation.
425
+ See the **[CLI Fallback for LLMs Guide](CLI_FALLBACK_FOR_LLMS.md)** for:
426
+ - Complete command reference and MCP tool mappings
427
+ - Sample prompt to give your LLM
428
+ - JSON output examples
429
+ - Tips for using CLI as an MCP alternative
429
430
 
430
431
  ### Common Issues
431
432
 
@@ -461,13 +462,13 @@ For troubleshooting, add error mode when configuring the server:
461
462
 
462
463
  ```sh
463
464
  # Claude Code
464
- claude mcp add simplecov-mcp simplecov-mcp --error-mode trace
465
+ claude mcp add simplecov-mcp simplecov-mcp --error-mode debug
465
466
 
466
467
  # Codex
467
- codex mcp add simplecov-mcp --command simplecov-mcp --args "--error-mode" --args "trace"
468
+ codex mcp add simplecov-mcp --command simplecov-mcp --args "--error-mode" --args "debug"
468
469
 
469
470
  # Gemini
470
- gemini mcp add simplecov-mcp "$(which simplecov-mcp) --error-mode trace"
471
+ gemini mcp add simplecov-mcp "$(which simplecov-mcp) --error-mode debug"
471
472
  ```
472
473
 
473
474
  ### Project-Specific vs. Global Configuration
@@ -483,6 +484,7 @@ gemini mcp add simplecov-mcp "$(which simplecov-mcp) --error-mode trace"
483
484
 
484
485
  ## Next Steps
485
486
 
486
- - **[CLI Usage](CLI_USAGE.md)** - Alternative to MCP for direct queries
487
+ - **[CLI Fallback for LLMs](CLI_FALLBACK_FOR_LLMS.md)** - Using CLI when MCP isn't available
488
+ - **[CLI Usage](CLI_USAGE.md)** - Complete CLI reference
487
489
  - **[Examples](EXAMPLES.md)** - Example prompts and workflows
488
490
  - **[Troubleshooting](TROUBLESHOOTING.md)** - Detailed troubleshooting guide
@@ -0,0 +1,14 @@
1
+ # User Documentation
2
+
3
+ Guides for installing, configuring, and using SimpleCov MCP in day-to-day
4
+ workflows.
5
+
6
+ - [Installation](INSTALLATION.md) – environment setup across platforms
7
+ - [CLI Usage](CLI_USAGE.md) – command reference with examples
8
+ - [Examples](EXAMPLES.md) – common coverage workflows
9
+ - [Advanced Usage](ADVANCED_USAGE.md) – resultset paths, staleness, predicates
10
+ - [Error Handling](ERROR_HANDLING.md) – modes, exceptions, logging
11
+ - [MCP Integration](MCP_INTEGRATION.md) – configuring AI assistants
12
+ - [CLI Fallback for LLMs](CLI_FALLBACK_FOR_LLMS.md) – when MCP isn't available
13
+ - [Library API](LIBRARY_API.md) – embedding the gem in Ruby code
14
+ - [Troubleshooting](TROUBLESHOOTING.md) – diagnostics for common issues