simplecov-mcp 1.0.1 → 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 +12 -19
  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 -88
  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 +103 -161
  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 +139 -78
  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 +97 -47
  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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 95c9d9edb894cafc89610f2d171e7452ec092a484666cfb15eac0314a1189963
4
- data.tar.gz: bdb9d23aa1a53adfde9abe953fbeb21e1c998435a9fa63e7150f8ab7d26c8184
3
+ metadata.gz: f35432a5fa155b21702ea533b8ab875a14bf520881e8a40e348aa15d597cdd66
4
+ data.tar.gz: 34deaac536651232ed05a606af80b07ebdba9ef945e4fc454efd4aecf0631251
5
5
  SHA512:
6
- metadata.gz: 5f2c42c2f48e5fecf6c7e7392dd384b7255a2b3b48ccb5fcc89fb423918ff9f5028b57f6ce68b4c03f288c23665a23d08d7cf48f9e36eaebab753cd4f2aa7ec6
7
- data.tar.gz: 4a96af4e01a259d194a902e9ea45c98058ffc06c5ed4313cf6785e7fc40929b3a186b6ccd9bbb078b9907f84173223096eafb278bbb696c3df414495b1e672d4
6
+ metadata.gz: 9adcc5e0b9f70ac5f6e9501194aa891fa93756e91513c470a11028072f7a7a260e36d25d0337a4bade9889dfc7f1a9d28d429148320560697b1ac465335bb820
7
+ data.tar.gz: '095a9e06c5b45d635d03e84aeb35a39ecbe49ff2b5fef4cbac27913794e822a7d28b3997d68e047f67ea4215500c2fe8931978c81440cdafbc0d28d6830899a8'
data/README.md CHANGED
@@ -8,20 +8,23 @@
8
8
 
9
9
  **simplecov-mcp** makes SimpleCov coverage data queryable and actionable through three interfaces:
10
10
 
11
- - **MCP server** - Let AI assistants analyze your coverage
11
+ - **MCP server** - Lets AI assistants analyze your coverage
12
12
  - **CLI** - Fast command-line coverage reports and queries
13
13
  - **Ruby library** - Programmatic API for custom tooling
14
14
 
15
15
  Works with any SimpleCov-generated `.resultset.json` file—no runtime dependency on your test suite.
16
16
 
17
- ### Key capabilities
17
+ ### Key Features
18
18
 
19
- - Flexible path resolution (absolute or relative paths)
20
- - Staleness detection (identifies outdated coverage files)
21
- - Multi-suite resultset merging when needed
22
- - Multiple useful output formats (tables, JSON, annotated source)
19
+ - **Multiple interfaces** - MCP server, CLI, and Ruby API
20
+ - **Annotated source code** - `--source full|uncovered` with `--context-lines N` for context lines
21
+ - ✅ **Staleness detection** - Identify outdated coverage (missing files, timestamp mismatches, line count changes)
22
+ - **Multi-suite support** - Automatic merging of multiple test suites (RSpec + Cucumber, etc.)
23
+ - ✅ **Flexible path resolution** - Works with absolute or relative paths
24
+ - ✅ **Comprehensive error handling** - Context-aware messages for each mode
25
+ - ⚠️ **Branch coverage limitation** - Branch-level metrics are collapsed to per-line totals. Use native SimpleCov reports for branch-by-branch analysis.
23
26
 
24
- ### Practical use cases
27
+ ### Practical Use Cases
25
28
 
26
29
  - Query coverage data from AI assistants, e.g.:
27
30
  - "Using simplecov-mcp, analyze test coverage data and write a report to a markdown file containing a free text analysis of each issue and then two tables, one sorted in descending order of urgency, the other in ascending order of level of effort."
@@ -29,6 +32,7 @@ Works with any SimpleCov-generated `.resultset.json` file—no runtime dependenc
29
32
  - Find files with the lowest coverage
30
33
  - Investigate specific files or directories
31
34
  - Generate CI/CD coverage reports
35
+ - Create custom pass/fail predicates for scripts and CI - use the library API or CLI JSON output to implement arbitrarily complex coverage rules beyond simple thresholds (e.g., require higher coverage for critical paths, exempt test utilities, track coverage trends)
32
36
 
33
37
  ## Quick Start
34
38
 
@@ -45,7 +49,7 @@ gem install simplecov-mcp
45
49
  bundle exec rspec # or your test command
46
50
 
47
51
  # Verify coverage was generated
48
- ls coverage/.resultset.json
52
+ ls -l coverage/.resultset.json
49
53
  ```
50
54
 
51
55
  ### Basic Usage
@@ -61,6 +65,13 @@ simplecov-mcp summary lib/simplecov_mcp/model.rb
61
65
  simplecov-mcp uncovered lib/simplecov_mcp/cli.rb
62
66
  ```
63
67
 
68
+ **CLI - Find the Project Homepage Fast:**
69
+ Run `simplecov-mcp -h` and the banner's second line shows the repository URL. Some terminal applications (e.g. iTerm2) will enable direct clicking the link using modifier keys such as `Cmd` or `Alt`.
70
+ ```
71
+ Usage: simplecov-mcp [options] [subcommand] [args]
72
+ Repository: https://github.com/keithrbennett/simplecov-mcp # <--- Project URL ---
73
+ ```
74
+
64
75
  **Ruby Library:**
65
76
  ```ruby
66
77
  require "simplecov_mcp"
@@ -70,21 +81,11 @@ files = model.all_files
70
81
  # => [{ "file" => "lib/simplecov_mcp/model.rb", "covered" => 114, "total" => 118, "percentage" => 96.61, "stale" => false }, ...]
71
82
 
72
83
  summary = model.summary_for("lib/simplecov_mcp/model.rb")
73
- # => { "file" => "lib/simplecov_mcp/model.rb", "summary" => { "covered" => 114, "total" => 118, "pct" => 96.61 }, "stale" => false }
84
+ # => { "file" => "lib/simplecov_mcp/model.rb", "summary" => { "covered" => 114, "total" => 118, "percentage" => 96.61 }, "stale" => false }
74
85
  ```
75
86
 
76
87
  **MCP Server:**
77
- See [MCP Integration Guide](docs/MCP_INTEGRATION.md) for AI assistant setup.
78
-
79
- ## Key Features
80
-
81
- - ✅ **Multiple interfaces** - MCP server, CLI, and Ruby API
82
- - ✅ **Rich output formats** - Tables, JSON, annotated source code
83
- - ✅ **Staleness detection** - Identify outdated coverage (missing files, timestamp mismatches, line count changes)
84
- - ✅ **Multi-suite support** - Automatic merging of multiple test suites (RSpec + Cucumber, etc.)
85
- - ✅ **Flexible path resolution** - Works with absolute or relative paths
86
- - ✅ **Comprehensive error handling** - Context-aware messages for each mode
87
- - ⚠️ **Branch coverage limitation** - Branch-level metrics are collapsed to per-line totals. Use native SimpleCov reports for branch-by-branch analysis.
88
+ See [MCP Integration Guide](docs/user/MCP_INTEGRATION.md) for AI assistant setup.
88
89
 
89
90
  ## Multi-Suite Coverage Merging
90
91
 
@@ -103,25 +104,28 @@ When a `.resultset.json` file contains multiple test suites (e.g., RSpec + Cucum
103
104
  ## Documentation
104
105
 
105
106
  **Getting Started:**
106
- - [Installation](docs/INSTALLATION.md) - Setup for different environments
107
- - [CLI Usage](docs/CLI_USAGE.md) - Command-line reference
108
- - [Examples](docs/EXAMPLES.md) - Common use cases
107
+ - [Installation](docs/user/INSTALLATION.md) - Setup for different environments
108
+ - [CLI Usage](docs/user/CLI_USAGE.md) - Command-line reference
109
+ - [Examples](docs/user/EXAMPLES.md) - Common use cases
109
110
 
110
111
  **Advanced Usage:**
111
- - [MCP Integration](docs/MCP_INTEGRATION.md) - AI assistant configuration
112
- - [Library API](docs/LIBRARY_API.md) - Ruby API documentation
113
- - [Error Handling](docs/ERROR_HANDLING.md) - Error modes and exceptions
112
+ - [MCP Integration](docs/user/MCP_INTEGRATION.md) - AI assistant configuration
113
+ - [CLI Fallback for LLMs](docs/user/CLI_FALLBACK_FOR_LLMS.md) - Using CLI when MCP isn't available
114
+ - [Library API](docs/user/LIBRARY_API.md) - Ruby API documentation
115
+ - [Advanced Usage](docs/user/ADVANCED_USAGE.md) - Staleness detection, error modes, path resolution
116
+ - [Error Handling](docs/user/ERROR_HANDLING.md) - Error modes and exceptions
114
117
 
115
118
  **Reference:**
116
- - [Troubleshooting](docs/TROUBLESHOOTING.md) - Common issues
117
- - [Development](docs/DEVELOPMENT.md) - Contributing guide
119
+ - [Architecture](docs/dev/ARCHITECTURE.md) - Design and internals
120
+ - [Branch Coverage](docs/dev/BRANCH_ONLY_COVERAGE.md) - Branch coverage limitations
121
+ - [Troubleshooting](docs/user/TROUBLESHOOTING.md) - Common issues
122
+ - [Development](docs/dev/DEVELOPMENT.md) - Contributing guide
118
123
 
119
124
  ## Requirements
120
125
 
121
126
  - **Ruby >= 3.2** (required by `mcp` gem dependency)
122
127
  - SimpleCov-generated `.resultset.json` file
123
128
  - `simplecov` gem >= 0.21
124
- - RVM users: export your preferred ruby/gemset *before* running commands (e.g. `rvm use 3.4.5@simplecov-mcp`)
125
129
 
126
130
  ## Configuring the Resultset
127
131
 
@@ -139,7 +143,7 @@ export SIMPLECOV_MCP_OPTS="--resultset /path/to/your/coverage"
139
143
  # "args": ["--resultset", "/path/to/your/coverage"]
140
144
  ```
141
145
 
142
- See [CLI Usage Guide](docs/CLI_USAGE.md#-r---resultset-path) for complete details.
146
+ See [CLI Usage Guide](docs/user/CLI_USAGE.md#-r---resultset-path) for complete details.
143
147
 
144
148
 
145
149
 
@@ -149,26 +153,66 @@ See [CLI Usage Guide](docs/CLI_USAGE.md#-r---resultset-path) for complete detail
149
153
 
150
154
  ```sh
151
155
  # Files with worst coverage
152
- simplecov-mcp list --sort-order d # display table in descending order, worst will be at end of output
153
- simplecov-mcp list -o d # same as above, short form option
156
+ simplecov-mcp -o d list # -o = --sort-order, d = descending (worst at end)
154
157
  simplecov-mcp list | less # display table in pager, worst files first
155
158
  simplecov-mcp list | head -10 # truncate the table
156
159
 
157
160
  # Specific directory
158
- simplecov-mcp list --tracked-globs "lib/simplecov_mcp/tools/**/*.rb"
161
+ simplecov-mcp -g "lib/simplecov_mcp/tools/**/*.rb" list # -g = --tracked-globs
159
162
 
160
163
  # Export for analysis
161
- simplecov-mcp list --json > coverage-report.json
164
+ simplecov-mcp -fJ list > coverage-report.json
162
165
  ```
163
166
 
167
+ ### Working with JSON Output
168
+
169
+ The `-fJ` flag enables programmatic processing of coverage data using command-line JSON tools.
170
+
171
+ **Using jq:**
172
+ ```sh
173
+ # Filter files below 80% coverage
174
+ simplecov-mcp -fJ list | jq '.files[] | select(.percentage < 80)'
175
+ ```
176
+
177
+ **Using Ruby one-liners:**
178
+ ```sh
179
+ # Count files below threshold
180
+ simplecov-mcp -fJ list | ruby -r json -e '
181
+ puts JSON.parse($stdin.read)["files"].count { |f| f["percentage"] < 80 }
182
+ '
183
+ ```
184
+
185
+ **Using rexe:**
186
+
187
+ [rexe](https://github.com/keithrbennett/rexe) is a Ruby gem that enables shorter Ruby command lines by providing command-line options for input and output formats, plus other conveniences. It eliminates the need for explicit JSON parsing and formatting code.
188
+
189
+ Install: `gem install rexe`
190
+
191
+ ```sh
192
+ # Filter files below 80% coverage with pretty-printed JSON output
193
+ simplecov-mcp -fJ list | rexe -ij -mb -oJ 'self["files"].select { |f| f["percentage"] < 80 }'
194
+
195
+ # Count files below threshold
196
+ simplecov-mcp -fJ list | rexe -ij -mb -op 'self["files"].count { |f| f["percentage"] < 80 }'
197
+
198
+ # Human-readable output with AwesomePrint
199
+ simplecov-mcp -fJ list | rexe -ij -mb -oa 'self["files"].first(3)'
200
+ ```
201
+
202
+ With rexe's `-ij -mb` options, `self` automatically becomes the parsed JSON object. The same holds true for JSON output -- using `-oJ` produces pretty-printed JSON without explicit formatting calls. Rexe also supports YAML input/output (`-iy`, `-oy`) and AwesomePrint output (`-oa`) for human consumption.
203
+
204
+ Run `rexe -h` to see all available options, or visit the [rexe project page](https://github.com/keithrbennett/rexe) for more examples.
205
+
206
+ For comprehensive JSON processing examples, see [docs/user/EXAMPLES.md](docs/user/EXAMPLES.md).
207
+
164
208
  ### CI/CD Integration
165
209
 
166
210
  ```sh
167
211
  # Fail build if coverage is stale
168
- simplecov-mcp --stale error || exit 1
212
+ simplecov-mcp --staleness error || exit 1
169
213
 
170
214
  # Generate coverage report artifact
171
- simplecov-mcp list --json > artifacts/coverage.json
215
+ simplecov-mcp -fJ list > artifacts/coverage.json
172
216
  ```
173
217
 
174
218
  ### Investigate Specific Files
@@ -181,31 +225,35 @@ simplecov-mcp summary lib/simplecov_mcp/model.rb
181
225
  simplecov-mcp uncovered lib/simplecov_mcp/cli.rb
182
226
 
183
227
  # View in context
184
- simplecov-mcp uncovered lib/simplecov_mcp/cli.rb --source=uncovered --source-context 3
228
+ simplecov-mcp -s u -c 3 uncovered lib/simplecov_mcp/cli.rb # -s = --source (u = uncovered), -c = --context-lines
185
229
 
186
230
  # Detailed hit counts
187
231
  simplecov-mcp detailed lib/simplecov_mcp/util.rb
232
+
233
+ # Project totals
234
+ simplecov-mcp totals
235
+ simplecov-mcp -fJ totals
188
236
  ```
189
237
 
190
238
  ## Commands and Tools
191
239
 
192
- **CLI Subcommands:** `list`, `summary`, `uncovered`, `detailed`, `raw`, `version`
240
+ **CLI Subcommands:** `list`, `summary`, `uncovered`, `detailed`, `raw`, `totals`, `validate`, `version`
193
241
 
194
- **MCP Tools:** `coverage_summary_tool`, `coverage_detailed_tool`, `coverage_raw_tool`, `uncovered_lines_tool`, `all_files_coverage_tool`, `coverage_table_tool`, `help_tool`, `version_tool`
242
+ **MCP Tools:** `coverage_summary_tool`, `coverage_detailed_tool`, `coverage_raw_tool`, `uncovered_lines_tool`, `all_files_coverage_tool`, `coverage_totals_tool`, `coverage_table_tool`, `validate_tool`, `help_tool`, `version_tool`
195
243
 
196
244
  📖 **See also:**
197
- - [CLI Usage Guide](docs/CLI_USAGE.md) - Complete command-line reference
198
- - [MCP Integration Guide](docs/MCP_INTEGRATION.md#available-mcp-tools) - MCP tools documentation
245
+ - [CLI Usage Guide](docs/user/CLI_USAGE.md) - Complete command-line reference
246
+ - [MCP Integration Guide](docs/user/MCP_INTEGRATION.md#available-mcp-tools) - MCP tools documentation
199
247
 
200
248
  ## Troubleshooting
201
249
 
202
- - **"command not found"** - See [Installation Guide](docs/INSTALLATION.md#path-configuration)
203
- - **"cannot load such file -- mcp"** - Upgrade to Ruby >= 3.2
204
- - **"Could not find .resultset.json"** - Run tests to generate coverage. See the [Configuring the Resultset](#configuring-the-resultset) section for more details.
205
- - **MCP server won't connect** - Check PATH and Ruby version in [MCP Troubleshooting](docs/MCP_INTEGRATION.md#troubleshooting)
206
- - **Codex on macOS with RVM** - Codex's macOS sandbox disallows `/bin/ps`, which RVM needs. Use a different version manager (rbenv, chruby) or run outside the Codex environment.
250
+ - **"command not found"** - See [Installation Guide](docs/user/INSTALLATION.md#path-configuration)
251
+ - **"cannot load such file -- mcp"** - Requires Ruby >= 3.2. Verify: `ruby -v`
252
+ - **"Could not find .resultset.json"** - Ensure SimpleCov is configured in your test suite, then run tests to generate coverage. See the [Configuring the Resultset](#configuring-the-resultset) section for more details.
253
+ - **MCP server won't connect** - Check PATH and Ruby version in [MCP Troubleshooting](docs/user/MCP_INTEGRATION.md#troubleshooting)
254
+ - **RVM in sandboxed environments (macOS)** - RVM requires `/bin/ps` which may be blocked by sandbox restrictions. Use rbenv or chruby instead.
207
255
 
208
- For more detailed help, see the full [Troubleshooting Guide](docs/TROUBLESHOOTING.md).
256
+ For more detailed help, see the full [Troubleshooting Guide](docs/user/TROUBLESHOOTING.md).
209
257
 
210
258
  ## Development
211
259
 
@@ -219,14 +267,14 @@ bundle install
219
267
  bundle exec rspec
220
268
 
221
269
  # Test locally
222
- ruby -Ilib exe/simplecov-mcp
270
+ bundle exec exe/simplecov-mcp
223
271
 
224
272
  # Build and install
225
273
  gem build simplecov-mcp.gemspec
226
274
  gem install simplecov-mcp-*.gem
227
275
  ```
228
276
 
229
- See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for more *(coming soon)*.
277
+ See [docs/dev/DEVELOPMENT.md](docs/dev/DEVELOPMENT.md) for more.
230
278
 
231
279
  ## SimpleCov Dependency
232
280
 
@@ -265,7 +313,7 @@ MIT License - see [LICENSE](LICENSE) file for details.
265
313
 
266
314
  📦 **Install:** `gem install simplecov-mcp`
267
315
 
268
- 📖 **Read:** [CLI Usage Guide](docs/CLI_USAGE.md) | [MCP Integration](docs/MCP_INTEGRATION.md)
316
+ 📖 **Read:** [CLI Usage Guide](docs/user/CLI_USAGE.md) | [MCP Integration](docs/user/MCP_INTEGRATION.md)
269
317
 
270
318
  🐛 **Report issues:** [GitHub Issues](https://github.com/keithrbennett/simplecov-mcp/issues)
271
319
 
@@ -1,5 +1,7 @@
1
1
  # Architecture
2
2
 
3
+ [Back to main README](../README.md)
4
+
3
5
  simplecov-mcp is organized around a single coverage data model that feeds three delivery channels: a command-line interface, an MCP server for LLM agents, and a light-weight Ruby API. The codebase is intentionally modular—shared logic for loading, normalizing, and validating SimpleCov data lives in `lib/simplecov_mcp/`, while adapters wrap that core for each runtime mode.
4
6
 
5
7
  ## Runtime Entry Points
@@ -11,16 +13,16 @@ simplecov-mcp is organized around a single coverage data model that feeds three
11
13
  ## Coverage Data Pipeline
12
14
 
13
15
  1. **Resultset discovery** – The tool locates the `.resultset.json` file by checking a series of default paths or by using a path specified by the user. For a detailed explanation of the configuration options, see the [Configuring the Resultset](../README.md#configuring-the-resultset) section in the main README.
14
- 2. **Parsing and normalization** – `CoverageModel` loads the chosen resultset once, selects the first suite that exposes `coverage`, and maps all file keys to absolute paths anchored at the configured project root. Timestamps are cached for staleness checks.
16
+ 2. **Parsing and normalization** – `CoverageModel` loads the chosen resultset once, extracts all test suites that expose `coverage` data (e.g., "RSpec", "Minitest"), merges them if multiple suites exist, and maps all file keys to absolute paths anchored at the configured project root. Timestamps are cached for staleness checks.
15
17
  3. **Path relativizing** – `PathRelativizer` produces relative paths for user-facing payloads without mutating the canonical data. Tool responses pass through `CoverageModel#relativize` before leaving the process.
16
18
  4. **Derived metrics** – `CovUtil.summary`, `CovUtil.uncovered`, and `CovUtil.detailed` compute coverage stats from the raw `lines` arrays. `CoverageModel` exposes `summary_for`, `uncovered_for`, `detailed_for`, and `raw_for` helpers that wrap these utilities.
17
- 5. **Staleness detection** – `StalenessChecker` compares source mtimes/line counts to coverage metadata. CLI flags and MCP arguments can promote warnings to hard failures (`--stale error`) or simply mark rows as stale for display.
19
+ 5. **Staleness detection** – `StalenessChecker` compares source mtimes/line counts to coverage metadata. CLI flags and MCP arguments can promote warnings to hard failures (`--staleness error`) or simply mark rows as stale for display.
18
20
 
19
21
  ## Interfaces
20
22
 
21
23
  ### CLI (`SimpleCovMcp::CoverageCLI`)
22
24
 
23
- - Builds on Ruby’s `OptionParser`, with global options such as `--resultset`, `--stale`, `--json`, and `--source` modes.
25
+ - Builds on Ruby’s `OptionParser`, with global options such as `--resultset`, `--staleness`, `-fJ`, and `--source` modes.
24
26
  - Subcommands (`list`, `summary`, `raw`, `uncovered`, `detailed`, `version`) translate to calls on `CoverageModel`.
25
27
  - Uses `ErrorHandlerFactory.for_cli` to convert unexpected exceptions into friendly user messages while honoring `--error-mode`.
26
28
  - Formatting logic (tables, JSON) lives in the model to keep presentation consistent with MCP responses.
@@ -45,7 +47,7 @@ simplecov-mcp is organized around a single coverage data model that feeds three
45
47
  ## Error Handling & Logging
46
48
 
47
49
  - Custom exceptions under `lib/simplecov_mcp/errors.rb` capture context for configuration issues, missing files, stale coverage, and general runtime errors. Each implements `#user_friendly_message` for consistent UX.
48
- - `SimpleCovMcp::ErrorHandler` encapsulates logging and severity decisions. Modes (`:off`, `:on`, `:trace`) control whether errors are recorded and whether stack traces are included.
50
+ - `SimpleCovMcp::ErrorHandler` encapsulates logging and severity decisions. Modes (`:off`, `:log`, `:debug`) control whether errors are recorded and whether stack traces are included.
49
51
  - Runtime configuration (error handlers, log destinations) flows through `SimpleCovMcp::AppContext`. Entry points push a context with `SimpleCovMcp.with_context`, which stores the active configuration in a thread-local slot (`SimpleCovMcp.context`). Nested calls automatically restore the previous context when the block exits, ensuring isolation even when multiple callers share a process or thread.
50
52
  - Two helper accessors clarify intent:
51
53
  - `SimpleCovMcp.default_log_file` / `default_log_file=` adjust the baseline log sink that future contexts inherit.
@@ -57,22 +59,21 @@ simplecov-mcp is organized around a single coverage data model that feeds three
57
59
 
58
60
  - **Environment defaults** – `SIMPLECOV_MCP_OPTS` applies baseline CLI flags before parsing the actual command line.
59
61
  - **Resultset overrides** – The location of the `.resultset.json` file can be specified via CLI options or in the MCP configuration. See [Configuring the Resultset](../README.md#configuring-the-resultset) for details.
60
- - **Tracked globs** – For project staleness checks, `tracked_globs` ensures new files raise alerts when absent from coverage.
62
+ - **Tracked globs** – Glob patterns (e.g., `lib/**/*.rb`) that specify which files should have coverage. When provided, SimpleCov MCP alerts you if any matching files are missing from the coverage data, helping catch untested files that were added to the project but never executed during test runs.
61
63
  - **Colorized source** – CLI-only flags (`--source`, `--source-context`, `--color`) enhance human-readable reports when working locally.
62
64
 
63
65
  ## Repository Layout Highlights
64
66
 
65
67
  - `lib/simplecov_mcp/` – Core runtime (model, utilities, error handling, CLI, MCP server, tools).
66
68
  - `lib/simplecov_mcp.rb` – Primary public entry point required by gem consumers.
67
- - `docs/` – User-facing guides (usage, installation, troubleshooting, architecture).
69
+ - `docs/` – Audience-specific guides (`docs/user` for usage, `docs/dev` for contributors).
68
70
  - `spec/` – RSpec suite with fixtures under `spec/fixtures/` for deterministic coverage data.
69
- - `scripts/` – Helper scripts (e.g., `scripts/setup_codex_cloud.sh`).
70
71
 
71
- ## Extending the System
72
+ ## Extending the System With a New Tool or Metric
72
73
 
73
74
  1. Add or update data processing inside `CoverageModel` or `CovUtil` when a new metric is needed.
74
- 2. Surface that metric through the desired interface: CLI option/subcommand, new MCP tool, or library helper.
75
- 3. Register the new tool in `MCPServer`, or update CLI option parsing in `CoverageCLI`.
75
+ 2. Surface that metric through all interfaces: add a CLI option/subcommand, create an MCP tool, and expose a library helper method.
76
+ 3. Register the new tool in `MCPServer` and update CLI option parsing in `CoverageCLI`.
76
77
  4. Provide tests under `spec/` mirroring the lib path (`spec/lib/simplecov_mcp/..._spec.rb`).
77
78
  5. Update documentation to reflect the new capability.
78
79
 
@@ -0,0 +1,158 @@
1
+ # Branch-Only Coverage Handling
2
+
3
+ [Back to main README](../README.md)
4
+
5
+ > **Note:** This document is for **developers working on SimpleCov MCP**, not for users of the gem.
6
+ > If you're a user, you don't need to read this - branch-only coverage "just works" automatically.
7
+ > This explains the internal implementation for contributors who need to maintain or modify the code.
8
+
9
+ ## The Problem This Solves for SimpleCov MCP
10
+
11
+ SimpleCov can be configured to track different types of coverage:
12
+ - **Line coverage**: Which lines of code were executed
13
+ - **Branch coverage**: Which paths through if/else, case/when, etc. were taken
14
+ - **Both**: Track both lines and branches together
15
+
16
+ When users configure SimpleCov to track **only branch coverage** (without line coverage),
17
+ the `.resultset.json` file has a different structure: the `lines` array is `null`,
18
+ and only the `branches` data exists.
19
+
20
+ **This breaks SimpleCov MCP** because our entire tool is designed around the `lines` array:
21
+ - Our MCP tools (`coverage_summary_tool`, `uncovered_lines_tool`, etc.) expect line data
22
+ - Our CLI commands expect line data
23
+ - Our `CoverageModel` API expects line data
24
+
25
+ Rather than failing with "no coverage data found" errors, SimpleCov MCP **automatically
26
+ converts branch coverage into line coverage** so all our tools continue to work seamlessly
27
+ for projects using branch-only configuration.
28
+
29
+ ## What Branch-Only Coverage Data Looks Like
30
+
31
+ When SimpleCov writes branch-only coverage, the `.resultset.json` file looks different
32
+ from the normal line coverage format. Here's an example:
33
+
34
+ ```json
35
+ {
36
+ "lib/example.rb": {
37
+ "lines": null,
38
+ "branches": {
39
+ "[:if, 0, 12, 4, 20, 29]": {
40
+ "[:then, 1, 13, 6, 13, 18]": 4,
41
+ "[:else, 2, 15, 6, 15, 16]": 0
42
+ }
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### Understanding the Branch Data Structure
49
+
50
+ The `branches` hash uses a nested structure:
51
+
52
+ **Outer key** (e.g., `"[:if, 0, 12, 4, 20, 29]"`):
53
+ - This is either a Ruby array or its stringified version
54
+ - It describes where the branch decision happens (the `if` statement itself)
55
+ - Format: `[type, id, start_line, start_col, end_line, end_col]`
56
+ - Position 0: Branch type (`:if`, `:case`, `:unless`, etc.)
57
+ - Position 1: SimpleCov's internal ID for this branch
58
+ - **Position 2: The line number** ← This is what we need for line coverage!
59
+ - Position 3: Starting column
60
+ - Position 4: Ending line
61
+ - Position 5: Ending column
62
+
63
+ **Nested hash** (the value of the outer key):
64
+ - Contains each possible path through the branch
65
+ - Keys are branch targets like `"[:then, 1, 13, 6, 13, 18]"` or `"[:else, 2, 15, 6, 15, 16]"`
66
+ - Each target has the same array format as the outer key
67
+ - Values are integers showing how many times that path was executed
68
+ - `4` means the `then` branch ran 4 times
69
+ - `0` means the `else` branch never ran
70
+
71
+ **Why this matters for our conversion:**
72
+ - We extract the line number (position 2) from each branch target
73
+ - We sum up all the execution counts for branches on the same line
74
+ - This gives us enough information to build a line coverage array
75
+
76
+ ## How SimpleCov MCP Converts Branch Coverage to Line Coverage
77
+
78
+ Since all of SimpleCov MCP's tools expect a `lines` array, we need to build one from
79
+ the `branches` data. This happens automatically in the `CoverageLineResolver` whenever
80
+ it detects that `lines` is `null` but `branches` exists.
81
+
82
+ ### The Conversion Algorithm
83
+
84
+ Here's how we transform branch data into line data:
85
+
86
+ **Step 1: Parse the branch keys**
87
+ - Branch keys can be either raw Ruby arrays or stringified (e.g., `"[:if, 0, 12, 4, 20, 29]"`)
88
+ - We handle both formats by parsing the string format when needed
89
+
90
+ **Step 2: Extract line numbers**
91
+ - From each branch target tuple, we pull out position 2 (the line number)
92
+ - Invalid or malformed tuples are silently skipped
93
+
94
+ **Step 3: Sum hits per line**
95
+ - Multiple branches can exist on the same line (e.g., nested ifs, ternaries)
96
+ - We add up all the execution counts for branches on the same line
97
+ - Example: if line 15 has a `then` branch hit 4 times and an `else` branch hit 2 times,
98
+ that line gets a total of 6 hits
99
+
100
+ **Step 4: Build the line array**
101
+ - We create an array with length equal to the highest line number found
102
+ - Each array position represents a line: `array[0]` = line 1, `array[1]` = line 2, etc.
103
+ - Positions get the summed hit count for that line, or `nil` if no branches appeared there
104
+
105
+ **Result:** We now have a `lines` array that looks exactly like SimpleCov's normal
106
+ format, so all our tools (`summary`, `uncovered`, staleness checks, etc.) work without
107
+ knowing branch coverage was involved.
108
+
109
+ ## Where to Find the Code
110
+
111
+ If you need to modify or debug the branch coverage conversion, here's where everything lives:
112
+
113
+ ### Implementation
114
+ **`lib/simplecov_mcp/resolvers/coverage_line_resolver.rb`**
115
+ - Line 59-66: `lines_from_entry` - Detects when to synthesize line data
116
+ - Line 68-103: `synthesize_lines_from_branches` - The main conversion logic
117
+ - Line 105-123: `extract_line_number` - Parses line numbers from branch tuples
118
+
119
+ This file is referenced in the code comments at line 79.
120
+
121
+ ### Tests
122
+ **`spec/resolvers/coverage_line_resolver_spec.rb`**
123
+ - Contains tests specifically for the resolver and branch synthesis
124
+
125
+ **`spec/simplecov_mcp_model_spec.rb`**
126
+ - Integration tests showing how the model uses synthesized line data
127
+
128
+ ### Test Data
129
+ **`spec/fixtures/branch_only_project/coverage/.resultset.json`**
130
+ - Example of real branch-only coverage data used in tests
131
+ - Useful reference when debugging issues or adding new test cases
132
+
133
+ ## Important Implementation Notes
134
+
135
+ ### Why the resolver returns `nil` for missing files
136
+
137
+ When `CoverageLineResolver.lookup_lines` can't find a file, it returns `nil` rather
138
+ than immediately raising an error. This is deliberate:
139
+
140
+ - The lookup tries multiple strategies: exact path match, relative path, path without
141
+ working directory prefix
142
+ - Each strategy calls `lines_from_entry` which may return `nil`
143
+ - Only after **all strategies fail** does the resolver raise a `FileError`
144
+ - This ensures we try every possible way to find the file before giving up
145
+
146
+ If you change `lines_from_entry` to raise an error immediately, the multi-strategy
147
+ lookup will break!
148
+
149
+ ### Future-proofing for SimpleCov changes
150
+
151
+ SimpleCov's branch tuple format could change in future versions. If that happens:
152
+
153
+ 1. Update `extract_line_number` to recognize the new tuple format
154
+ 2. Add test fixtures with the new format
155
+ 3. Update this documentation with the new structure
156
+ 4. Keep backward compatibility with the old format if possible
157
+
158
+ This way, SimpleCov MCP continues working even when SimpleCov evolves.
@@ -1,5 +1,7 @@
1
1
  # Development Guide
2
2
 
3
+ [Back to main README](../README.md)
4
+
3
5
  > **Note:** Commands like `simplecov-mcp` assume the gem is installed globally. If not, substitute `bundle exec exe/simplecov-mcp`.
4
6
 
5
7
  ## Setup
@@ -79,4 +81,3 @@ before { setup_mcp_response_stub }
79
81
  ```sh
80
82
  echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' | simplecov-mcp
81
83
  ```
82
-
@@ -0,0 +1,10 @@
1
+ # Developer Documentation
2
+
3
+ Resources for contributors working on SimpleCov MCP internals and release
4
+ engineering.
5
+
6
+ - [Architecture Overview](ARCHITECTURE.md) – subsystem layout and data flow
7
+ - [Development Guide](DEVELOPMENT.md) – setup, testing, release workflow
8
+ - [Branch Coverage Support](BRANCH_ONLY_COVERAGE.md) – implementation notes and limitations
9
+ - [Architecture Decision Records](arch-decisions/README.md) – design history
10
+ - [Presentations](presentations/simplecov-mcp-presentation.md) – slide deck for talks/demos