cov-loupe 3.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 (171) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +329 -0
  4. data/docs/dev/ARCHITECTURE.md +80 -0
  5. data/docs/dev/BRANCH_ONLY_COVERAGE.md +158 -0
  6. data/docs/dev/DEVELOPMENT.md +83 -0
  7. data/docs/dev/README.md +10 -0
  8. data/docs/dev/RELEASING.md +146 -0
  9. data/docs/dev/arch-decisions/001-x-arch-decision.md +95 -0
  10. data/docs/dev/arch-decisions/002-x-arch-decision.md +159 -0
  11. data/docs/dev/arch-decisions/003-x-arch-decision.md +165 -0
  12. data/docs/dev/arch-decisions/004-x-arch-decision.md +203 -0
  13. data/docs/dev/arch-decisions/005-x-arch-decision.md +189 -0
  14. data/docs/dev/arch-decisions/README.md +60 -0
  15. data/docs/dev/presentations/cov-loupe-presentation.md +255 -0
  16. data/docs/fixtures/demo_project/README.md +9 -0
  17. data/docs/user/ADVANCED_USAGE.md +777 -0
  18. data/docs/user/CLI_FALLBACK_FOR_LLMS.md +34 -0
  19. data/docs/user/CLI_USAGE.md +750 -0
  20. data/docs/user/ERROR_HANDLING.md +93 -0
  21. data/docs/user/EXAMPLES.md +588 -0
  22. data/docs/user/INSTALLATION.md +130 -0
  23. data/docs/user/LIBRARY_API.md +693 -0
  24. data/docs/user/MCP_INTEGRATION.md +490 -0
  25. data/docs/user/README.md +14 -0
  26. data/docs/user/TROUBLESHOOTING.md +197 -0
  27. data/docs/user/V2-BREAKING-CHANGES.md +472 -0
  28. data/exe/cov-loupe +23 -0
  29. data/lib/cov_loupe/app_config.rb +56 -0
  30. data/lib/cov_loupe/app_context.rb +26 -0
  31. data/lib/cov_loupe/base_tool.rb +102 -0
  32. data/lib/cov_loupe/cli.rb +178 -0
  33. data/lib/cov_loupe/commands/base_command.rb +67 -0
  34. data/lib/cov_loupe/commands/command_factory.rb +45 -0
  35. data/lib/cov_loupe/commands/detailed_command.rb +38 -0
  36. data/lib/cov_loupe/commands/list_command.rb +13 -0
  37. data/lib/cov_loupe/commands/raw_command.rb +38 -0
  38. data/lib/cov_loupe/commands/summary_command.rb +41 -0
  39. data/lib/cov_loupe/commands/totals_command.rb +53 -0
  40. data/lib/cov_loupe/commands/uncovered_command.rb +45 -0
  41. data/lib/cov_loupe/commands/validate_command.rb +60 -0
  42. data/lib/cov_loupe/commands/version_command.rb +33 -0
  43. data/lib/cov_loupe/config_parser.rb +32 -0
  44. data/lib/cov_loupe/constants.rb +22 -0
  45. data/lib/cov_loupe/coverage_reporter.rb +31 -0
  46. data/lib/cov_loupe/error_handler.rb +165 -0
  47. data/lib/cov_loupe/error_handler_factory.rb +31 -0
  48. data/lib/cov_loupe/errors.rb +191 -0
  49. data/lib/cov_loupe/formatters/source_formatter.rb +152 -0
  50. data/lib/cov_loupe/formatters.rb +51 -0
  51. data/lib/cov_loupe/mcp_server.rb +42 -0
  52. data/lib/cov_loupe/mode_detector.rb +56 -0
  53. data/lib/cov_loupe/model.rb +339 -0
  54. data/lib/cov_loupe/option_normalizers.rb +113 -0
  55. data/lib/cov_loupe/option_parser_builder.rb +147 -0
  56. data/lib/cov_loupe/option_parsers/env_options_parser.rb +48 -0
  57. data/lib/cov_loupe/option_parsers/error_helper.rb +110 -0
  58. data/lib/cov_loupe/path_relativizer.rb +64 -0
  59. data/lib/cov_loupe/predicate_evaluator.rb +72 -0
  60. data/lib/cov_loupe/presenters/base_coverage_presenter.rb +42 -0
  61. data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +14 -0
  62. data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +14 -0
  63. data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +14 -0
  64. data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +14 -0
  65. data/lib/cov_loupe/presenters/project_coverage_presenter.rb +50 -0
  66. data/lib/cov_loupe/presenters/project_totals_presenter.rb +27 -0
  67. data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +122 -0
  68. data/lib/cov_loupe/resolvers/resolver_factory.rb +28 -0
  69. data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +76 -0
  70. data/lib/cov_loupe/resultset_loader.rb +131 -0
  71. data/lib/cov_loupe/staleness_checker.rb +247 -0
  72. data/lib/cov_loupe/table_formatter.rb +64 -0
  73. data/lib/cov_loupe/tools/all_files_coverage_tool.rb +51 -0
  74. data/lib/cov_loupe/tools/coverage_detailed_tool.rb +35 -0
  75. data/lib/cov_loupe/tools/coverage_raw_tool.rb +34 -0
  76. data/lib/cov_loupe/tools/coverage_summary_tool.rb +34 -0
  77. data/lib/cov_loupe/tools/coverage_table_tool.rb +50 -0
  78. data/lib/cov_loupe/tools/coverage_totals_tool.rb +44 -0
  79. data/lib/cov_loupe/tools/help_tool.rb +115 -0
  80. data/lib/cov_loupe/tools/uncovered_lines_tool.rb +34 -0
  81. data/lib/cov_loupe/tools/validate_tool.rb +72 -0
  82. data/lib/cov_loupe/tools/version_tool.rb +32 -0
  83. data/lib/cov_loupe/util.rb +88 -0
  84. data/lib/cov_loupe/version.rb +5 -0
  85. data/lib/cov_loupe.rb +140 -0
  86. data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
  87. data/spec/TIMESTAMPS.md +48 -0
  88. data/spec/all_files_coverage_tool_spec.rb +53 -0
  89. data/spec/app_config_spec.rb +142 -0
  90. data/spec/base_tool_spec.rb +62 -0
  91. data/spec/cli/show_default_report_spec.rb +33 -0
  92. data/spec/cli_enumerated_options_spec.rb +90 -0
  93. data/spec/cli_error_spec.rb +184 -0
  94. data/spec/cli_format_spec.rb +123 -0
  95. data/spec/cli_json_options_spec.rb +50 -0
  96. data/spec/cli_source_spec.rb +44 -0
  97. data/spec/cli_spec.rb +192 -0
  98. data/spec/cli_table_spec.rb +28 -0
  99. data/spec/cli_usage_spec.rb +42 -0
  100. data/spec/commands/base_command_spec.rb +107 -0
  101. data/spec/commands/command_factory_spec.rb +76 -0
  102. data/spec/commands/detailed_command_spec.rb +34 -0
  103. data/spec/commands/list_command_spec.rb +28 -0
  104. data/spec/commands/raw_command_spec.rb +69 -0
  105. data/spec/commands/summary_command_spec.rb +34 -0
  106. data/spec/commands/totals_command_spec.rb +34 -0
  107. data/spec/commands/uncovered_command_spec.rb +55 -0
  108. data/spec/commands/validate_command_spec.rb +213 -0
  109. data/spec/commands/version_command_spec.rb +38 -0
  110. data/spec/constants_spec.rb +61 -0
  111. data/spec/cov_loupe/formatters/source_formatter_spec.rb +267 -0
  112. data/spec/cov_loupe/formatters_spec.rb +76 -0
  113. data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +79 -0
  114. data/spec/cov_loupe_model_spec.rb +454 -0
  115. data/spec/cov_loupe_module_spec.rb +37 -0
  116. data/spec/cov_loupe_opts_spec.rb +185 -0
  117. data/spec/coverage_reporter_spec.rb +102 -0
  118. data/spec/coverage_table_tool_spec.rb +59 -0
  119. data/spec/coverage_totals_tool_spec.rb +37 -0
  120. data/spec/error_handler_spec.rb +197 -0
  121. data/spec/error_mode_spec.rb +139 -0
  122. data/spec/errors_edge_cases_spec.rb +312 -0
  123. data/spec/errors_stale_spec.rb +83 -0
  124. data/spec/file_based_mcp_tools_spec.rb +99 -0
  125. data/spec/fixtures/project1/lib/bar.rb +5 -0
  126. data/spec/fixtures/project1/lib/foo.rb +6 -0
  127. data/spec/help_tool_spec.rb +26 -0
  128. data/spec/integration_spec.rb +789 -0
  129. data/spec/logging_fallback_spec.rb +128 -0
  130. data/spec/mcp_logging_spec.rb +44 -0
  131. data/spec/mcp_server_integration_spec.rb +23 -0
  132. data/spec/mcp_server_spec.rb +106 -0
  133. data/spec/mode_detector_spec.rb +153 -0
  134. data/spec/model_error_handling_spec.rb +269 -0
  135. data/spec/model_staleness_spec.rb +79 -0
  136. data/spec/option_normalizers_spec.rb +203 -0
  137. data/spec/option_parsers/env_options_parser_spec.rb +221 -0
  138. data/spec/option_parsers/error_helper_spec.rb +222 -0
  139. data/spec/path_relativizer_spec.rb +98 -0
  140. data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
  141. data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
  142. data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
  143. data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
  144. data/spec/presenters/project_coverage_presenter_spec.rb +87 -0
  145. data/spec/presenters/project_totals_presenter_spec.rb +144 -0
  146. data/spec/resolvers/coverage_line_resolver_spec.rb +282 -0
  147. data/spec/resolvers/resolver_factory_spec.rb +61 -0
  148. data/spec/resolvers/resultset_path_resolver_spec.rb +60 -0
  149. data/spec/resultset_loader_spec.rb +167 -0
  150. data/spec/shared_examples/README.md +115 -0
  151. data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
  152. data/spec/shared_examples/file_based_mcp_tools.rb +179 -0
  153. data/spec/shared_examples/formatted_command_examples.rb +64 -0
  154. data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
  155. data/spec/spec_helper.rb +127 -0
  156. data/spec/staleness_checker_spec.rb +374 -0
  157. data/spec/staleness_more_spec.rb +42 -0
  158. data/spec/support/cli_helpers.rb +22 -0
  159. data/spec/support/control_flow_helpers.rb +20 -0
  160. data/spec/support/fake_mcp.rb +40 -0
  161. data/spec/support/io_helpers.rb +29 -0
  162. data/spec/support/mcp_helpers.rb +35 -0
  163. data/spec/support/mcp_runner.rb +66 -0
  164. data/spec/support/mocking_helpers.rb +30 -0
  165. data/spec/table_format_spec.rb +70 -0
  166. data/spec/tools/validate_tool_spec.rb +132 -0
  167. data/spec/tools_error_handling_spec.rb +130 -0
  168. data/spec/util_spec.rb +154 -0
  169. data/spec/version_spec.rb +123 -0
  170. data/spec/version_tool_spec.rb +141 -0
  171. metadata +290 -0
@@ -0,0 +1,490 @@
1
+ # MCP Integration Guide
2
+
3
+ [Back to main README](../README.md)
4
+
5
+ ## Table of Contents
6
+
7
+ - [What is MCP?](#what-is-mcp)
8
+ - [Prerequisites](#prerequisites)
9
+ - [Quick Start](#quick-start)
10
+ - [Setup by Client](#setup-by-client)
11
+ - [Available MCP Tools](#available-mcp-tools)
12
+ - [Testing Your Setup](#testing-your-setup)
13
+ - [Troubleshooting](#troubleshooting)
14
+
15
+ ## What is MCP?
16
+
17
+ The Model Context Protocol (MCP) is a standard for integrating tools and data sources with AI assistants. By running cov-loupe as an MCP server, you enable AI coding assistants to:
18
+
19
+ - Query coverage data for files
20
+ - Identify uncovered code
21
+ - Analyze coverage gaps
22
+ - Suggest improvements based on coverage data
23
+
24
+ ### Why Use MCP with Coverage Tools?
25
+
26
+ AI assistants can help you:
27
+ - **Prioritize testing** - "Which files need coverage most urgently?"
28
+ - **Understand gaps** - "Why is this file's coverage low?"
29
+ - **Generate tests** - "Write tests for uncovered lines in this file"
30
+ - **Track progress** - "Has coverage improved since last commit?"
31
+
32
+ ## Prerequisites
33
+
34
+ - **Ruby >= 3.2** (required by MCP gem dependency)
35
+ - **cov-loupe installed** - See [Installation Guide](INSTALLATION.md)
36
+ - **simplecov gem >= 0.21** - Needed when a resultset contains multiple suites (loaded lazily)
37
+ - **Coverage data** - Run tests to generate `coverage/.resultset.json`
38
+ - **MCP-compatible client** - Claude Code, Cursor, Codex, etc.
39
+
40
+ ## Quick Start
41
+
42
+ ### 1. Install cov-loupe
43
+
44
+ ```sh
45
+ gem install cov-loupe
46
+ ```
47
+
48
+ ### 2. Verify Installation
49
+
50
+ ```sh
51
+ # Find the executable path (needed for MCP configuration)
52
+ which cov-loupe
53
+
54
+ # Test it works
55
+ cov-loupe version
56
+ ```
57
+
58
+ ### 3. Configure Your AI Assistant
59
+
60
+ See [Setup by Client](#setup-by-client) below for specific instructions.
61
+
62
+ ### 4. Generate Coverage Data
63
+
64
+ ```sh
65
+ # Run your test suite
66
+ bundle exec rspec # or your test command
67
+
68
+ # Verify coverage file exists
69
+ ls coverage/.resultset.json
70
+ ```
71
+
72
+ > **Multi-suite note:** If the resultset contains several suites (e.g., `RSpec` and `Cucumber`), cov-loupe lazily loads the `simplecov` gem and merges them before answering coverage queries. Staleness checks currently use the newest suite’s timestamp, so treat multi-suite freshness warnings as advisory until per-file timestamps are introduced.
73
+ >
74
+ > Only suites stored in a *single* `.resultset.json` are merged automatically. If your test runs produce multiple resultset files, merge them (e.g., via `SimpleCov::ResultMerger.merge_and_store`) and point cov-loupe at the combined file.
75
+
76
+ > Multifile support may be added in a future version (post an issue if you want this).
77
+
78
+ ### 5. Test the MCP Server
79
+
80
+ ```sh
81
+ # Test manually
82
+ echo '''{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}''' | cov-loupe
83
+ ```
84
+
85
+ You should see a JSON-RPC response with version information.
86
+
87
+ ## Setup by Client
88
+
89
+ ### Claude Code
90
+
91
+ **Current Status:** Claude Code has a bug in its MCP client that prevents it from working with spec-compliant MCP servers like cov-loupe. Claude Code will automatically fall back to using the CLI interface.
92
+
93
+ **Bug Report:** [Claude Code Issue #8239](https://github.com/anthropics/claude-code/issues/8239)
94
+
95
+ **Workaround:** Use the CLI interface, which provides the same functionality:
96
+ ```sh
97
+ # Instead of MCP tools, use CLI
98
+ cov-loupe list
99
+ cov-loupe summary lib/cov_loupe/cli.rb
100
+ ```
101
+
102
+ **Configuration (for when bug is fixed):**
103
+
104
+ Using the Claude CLI tool:
105
+
106
+ ```sh
107
+ # Basic setup (if cov-loupe is in default PATH)
108
+ claude mcp add cov-loupe cov-loupe
109
+
110
+ # With rbenv/asdf (use absolute path)
111
+ claude mcp add cov-loupe /Users/yourname/.rbenv/shims/cov-loupe
112
+
113
+ # With RVM wrapper (recommended for stability)
114
+ rvm wrapper ruby-3.3.8 cov-loupe cov-loupe
115
+ claude mcp add cov-loupe /Users/yourname/.rvm/wrappers/ruby-3.3.8/cov-loupe
116
+
117
+ # For user-wide configuration (default is local)
118
+ claude mcp add --scope user cov-loupe cov-loupe
119
+
120
+ # For project-specific configuration
121
+ claude mcp add --scope project cov-loupe cov-loupe
122
+ ```
123
+
124
+ **Verify configuration:**
125
+ ```sh
126
+ # List configured MCP servers
127
+ claude mcp list
128
+
129
+ # Get server details
130
+ claude mcp get cov-loupe
131
+
132
+ # Remove if needed
133
+ claude mcp remove cov-loupe
134
+ ```
135
+
136
+ **Important Notes:**
137
+ - Default scope is `local` (current project)
138
+ - Use `--scope user` for global config, `--scope project` for project-specific
139
+ - The executable path is tied to Ruby version with version managers
140
+ - If you change Ruby versions, remove and re-add the configuration
141
+
142
+ ### Cursor / Codex
143
+
144
+ Using the Codex CLI:
145
+
146
+ ```sh
147
+ # Basic setup (if cov-loupe is in default PATH)
148
+ codex mcp add cov-loupe --command cov-loupe
149
+
150
+ # With rbenv/asdf (use absolute path)
151
+ codex mcp add cov-loupe --command /Users/yourname/.rbenv/shims/cov-loupe
152
+
153
+ # With RVM wrapper (recommended for stability)
154
+ rvm wrapper ruby-3.3.8 cov-loupe cov-loupe
155
+ codex mcp add cov-loupe --command /Users/yourname/.rvm/wrappers/ruby-3.3.8/cov-loupe
156
+
157
+ # List configured servers
158
+ codex mcp list
159
+
160
+ # Show server details
161
+ codex mcp get cov-loupe
162
+
163
+ # Remove if needed
164
+ codex mcp remove cov-loupe
165
+ ```
166
+
167
+ **Find your executable path:**
168
+ ```sh
169
+ which cov-loupe
170
+ ```
171
+
172
+ ### Gemini
173
+
174
+ Using the Gemini CLI:
175
+
176
+ ```sh
177
+ # Add MCP server
178
+ gemini mcp add cov-loupe /Users/yourname/.rbenv/shims/cov-loupe
179
+
180
+ # Or with RVM
181
+ gemini mcp add cov-loupe /Users/yourname/.rvm/wrappers/ruby-3.3.8/cov-loupe
182
+
183
+ # List configured servers
184
+ gemini mcp list
185
+
186
+ # Remove if needed
187
+ gemini mcp remove cov-loupe
188
+ ```
189
+
190
+ ### Generic MCP Client
191
+
192
+ For any MCP client that uses JSON configuration:
193
+
194
+ ```json
195
+ {
196
+ "mcpServers": {
197
+ "cov-loupe": {
198
+ "command": "/path/to/cov-loupe",
199
+ "args": [],
200
+ "env": {
201
+ "COV_LOUPE_OPTS": "--resultset coverage"
202
+ }
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ **Environment variables you can set:**
209
+
210
+ - `COV_LOUPE_OPTS` - Default CLI options (though less useful for MCP mode)
211
+
212
+ ## Available MCP Tools
213
+
214
+ ### Tool Catalog
215
+
216
+ cov-loupe exposes 10 MCP tools:
217
+
218
+ | Tool | Purpose | Key Parameters |
219
+ |------|---------|----------------|
220
+ | `coverage_summary_tool` | File coverage summary | `path` |
221
+ | `coverage_detailed_tool` | Per-line coverage | `path` |
222
+ | `coverage_raw_tool` | Raw SimpleCov array | `path` |
223
+ | `uncovered_lines_tool` | List uncovered lines | `path` |
224
+ | `all_files_coverage_tool` | Project-wide coverage | `sort_order`, `tracked_globs` |
225
+ | `coverage_totals_tool` | Aggregated line totals | `tracked_globs` |
226
+ | `coverage_table_tool` | Formatted coverage table | `sort_order` |
227
+ | `validate_tool` | Validate coverage policies | `code` or `file` |
228
+ | `help_tool` | Tool discovery | (none) |
229
+ | `version_tool` | Version information | (none) |
230
+
231
+ ### JSON Response Format
232
+
233
+ For tools that return structured data, `cov-loupe` serializes the data as a JSON string and returns it inside a `text` part of the MCP response.
234
+
235
+ **Example:**
236
+ ```json
237
+ {
238
+ "type": "text",
239
+ "text": "{"coverage_summary":{"covered":10,"total":20,"percentage":50.0}}"
240
+ }
241
+ ```
242
+
243
+ **Reasoning:**
244
+ While returning JSON in a `resource` part with `mimeType: "application/json"` is more semantically correct, major MCP clients (including Google's Gemini and Anthropic's Claude) were found to not support this format, causing validation errors. They expect a `resource` part to contain a `uri`.
245
+
246
+ To ensure maximum compatibility, the decision was made to use a simple `text` part. This is a pragmatic compromise that has proven to be reliable across different clients.
247
+
248
+ **Further Reading:**
249
+ This decision was informed by discussions with multiple AI models. For more details, see these conversations:
250
+ - [Perplexity AI Discussion](https://www.perplexity.ai/search/title-resolving-a-model-contex-IfpFWU1FR5WQXQ8HcQctyg#0)
251
+ - [ChatGPT Discussion](https://chatgpt.com/share/68e4d7e1-cad4-800f-80c2-58b33bfc31cb)
252
+
253
+ ### Common Parameters
254
+
255
+ All file-specific tools accept these parameters:
256
+
257
+ - `path` (required for file tools) - File path (relative or absolute)
258
+ - `root` (optional) - Project root directory (default: `.`)
259
+ - `resultset` (optional) - Path to the `.resultset.json` file. See [Configuring the Resultset](../README.md#configuring-the-resultset) for details.
260
+ - `staleness` (optional) - Staleness mode: `"off"` (default) or `"error"`
261
+ - `error_mode` (optional) - Error handling: `"off"`, `"log"` (default), `"debug"`
262
+
263
+ ### Tool Details
264
+
265
+ #### Per-File Tools
266
+
267
+ These tools analyze individual files. All require `path` parameter.
268
+
269
+ **`coverage_summary_tool`** - Covered/total/percentage summary
270
+ ```json
271
+ {"file": "...", "summary": {"covered": 12, "total": 14, "percentage": 85.71}, "stale": false}
272
+ ```
273
+
274
+ **`uncovered_lines_tool`** - List uncovered line numbers
275
+ ```json
276
+ {"file": "...", "uncovered": [5, 9, 12], "summary": {...}, "stale": false}
277
+ ```
278
+
279
+ **`coverage_detailed_tool`** - Per-line hit counts
280
+ ```json
281
+ {"file": "...", "lines": [{"line": 1, "hits": 1, "covered": true}, ...], "summary": {...}, "stale": false}
282
+ ```
283
+
284
+ **`coverage_raw_tool`** - Raw SimpleCov lines array
285
+ ```json
286
+ {"file": "...", "lines": [1, 0, null, 5, 2, null, 1], "stale": false}
287
+ ```
288
+
289
+ #### Project-Wide Tools
290
+
291
+ **`all_files_coverage_tool`** - Coverage for all files
292
+ - Parameters: `sort_order` (`ascending`|`descending`), `tracked_globs` (array)
293
+ - Returns: `{"files": [...], "counts": {"total": N, "ok": N, "stale": N}}`
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
+
299
+ **`coverage_table_tool`** - Formatted ASCII table
300
+ - Parameters: `sort_order` (`ascending`|`descending`)
301
+ - Returns: Plain text table
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
+
313
+ #### Utility Tools
314
+
315
+ **`help_tool`** - Tool discovery
316
+ **`version_tool`** - Version information
317
+
318
+ ## Example Prompts for AI Assistants
319
+
320
+ ### Coverage Analysis
321
+
322
+ ```
323
+ Using cov-loupe, show me a table of all files and their coverage percentages.
324
+ ```
325
+
326
+ ```
327
+ Using cov-loupe, find files with less than 80% coverage and tell me which ones to prioritize.
328
+ ```
329
+
330
+ ```
331
+ Using cov-loupe, analyze the coverage for lib/cov_loupe/tools/ and suggest improvements.
332
+ ```
333
+
334
+ ### Finding Coverage Gaps
335
+
336
+ ```
337
+ Using cov-loupe, show me the uncovered lines in lib/cov_loupe/base_tool.rb and explain what they do.
338
+ ```
339
+
340
+ ```
341
+ Using cov-loupe, find the most important uncovered code in lib/cov_loupe/tools/coverage_detailed_tool.rb.
342
+ ```
343
+
344
+ ### Test Generation
345
+
346
+ ```
347
+ Using cov-loupe, find uncovered lines in lib/cov_loupe/staleness_checker.rb and write RSpec tests for them.
348
+ ```
349
+
350
+ ```
351
+ Using cov-loupe, analyze coverage gaps in lib/cov_loupe/tools/ and generate test cases.
352
+ ```
353
+
354
+ ### Coverage Reporting
355
+
356
+ ```
357
+ Using cov-loupe, create a markdown report of:
358
+ - Files with worst coverage
359
+ - Most critical coverage gaps
360
+ - Recommended action items
361
+ ```
362
+
363
+ ## Testing Your Setup
364
+
365
+ ### Manual Testing via Command Line
366
+
367
+ Test the MCP server responds to JSON-RPC:
368
+
369
+ ```sh
370
+ # Test version tool (simplest)
371
+ echo '''{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}''' | cov-loupe
372
+
373
+ # Test summary tool
374
+ echo '''{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"lib/cov_loupe/model.rb"}}}''' | cov-loupe
375
+
376
+ # Test help tool
377
+ echo '''{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"help_tool","arguments":{}}}''' | cov-loupe
378
+ ```
379
+
380
+ **Important:** JSON-RPC messages must be on a single line. Multi-line JSON will cause parse errors.
381
+
382
+ ### Testing in AI Assistant
383
+
384
+ Once configured, try these prompts in your AI assistant:
385
+
386
+ 1. **Basic connectivity:**
387
+ ```
388
+ Using cov-loupe, show me the version.
389
+ ```
390
+
391
+ 2. **List tools:**
392
+ ```
393
+ Using cov-loupe, what tools are available?
394
+ ```
395
+
396
+ 3. **Simple query:**
397
+ ```
398
+ Using cov-loupe, show me all files with coverage.
399
+ ```
400
+
401
+ If these work, your setup is correct!
402
+
403
+ ### Checking Logs
404
+
405
+ The MCP server logs to `cov_loupe.log` in the current directory by default.
406
+
407
+ ```sh
408
+ # Watch logs in real-time
409
+ tail -f cov_loupe.log
410
+
411
+ # View recent errors
412
+ grep ERROR cov_loupe.log | tail -20
413
+ ```
414
+
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`.
416
+
417
+ **Note:** Logging to `stdout` is not permitted in MCP mode.
418
+
419
+ ## Troubleshooting
420
+
421
+ ### CLI Fallback
422
+
423
+ **Important:** If the MCP server doesn't work, you can use the CLI directly with the `-fJ` flag.
424
+
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
430
+
431
+ ### Common Issues
432
+
433
+ **Server Won't Start**
434
+ ```sh
435
+ which cov-loupe # Verify executable exists
436
+ ruby -v # Check Ruby >= 3.2
437
+ cov-loupe version # Test basic functionality
438
+ ```
439
+
440
+ **Path Issues with Version Managers**
441
+ ```sh
442
+ which cov-loupe # Use this absolute path in MCP config
443
+ # RVM: Create wrapper for stability
444
+ rvm wrapper ruby-3.3.8 cov-loupe cov-loupe
445
+ ```
446
+
447
+ **Tools Not Appearing**
448
+ 1. Restart AI assistant after config changes
449
+ 2. Check logs: `tail -f cov_loupe.log`
450
+ 3. Try explicit tool names in prompts
451
+ 4. Verify MCP server status in assistant
452
+
453
+ **JSON-RPC Parse Errors**
454
+ - Ensure JSON is on a single line (no newlines)
455
+ - Test manually: `echo '{"jsonrpc":"2.0",...}' | cov-loupe`
456
+
457
+ ## Advanced Configuration
458
+
459
+ ### Enable Debug Logging
460
+
461
+ For troubleshooting, add error mode when configuring the server:
462
+
463
+ ```sh
464
+ # Claude Code
465
+ claude mcp add cov-loupe cov-loupe --error-mode debug
466
+
467
+ # Codex
468
+ codex mcp add cov-loupe --command cov-loupe --args "--error-mode" --args "debug"
469
+
470
+ # Gemini
471
+ gemini mcp add cov-loupe "$(which cov-loupe) --error-mode debug"
472
+ ```
473
+
474
+ ### Project-Specific vs. Global Configuration
475
+
476
+ **Global configuration** (all projects):
477
+ - Claude: `claude mcp add --scope user cov-loupe ...`
478
+ - Codex: `codex mcp add` (uses global config by default)
479
+ - Gemini: `gemini mcp add` (uses global config)
480
+
481
+ **Project-specific** (one project):
482
+ - Claude: `claude mcp add --scope project cov-loupe ...` (default is `local`)
483
+ - Codex/Gemini: Create `.codex/config.toml` or `.gemini/config.toml` in project root (manual)
484
+
485
+ ## Next Steps
486
+
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
489
+ - **[Examples](EXAMPLES.md)** - Example prompts and workflows
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
@@ -0,0 +1,197 @@
1
+ # Troubleshooting Guide
2
+
3
+ [Back to main README](../README.md)
4
+
5
+ ## Table of Contents
6
+
7
+ - [Running Issues](#running-issues)
8
+ - [Coverage Data Issues](#coverage-data-issues)
9
+ - [MCP Server Issues](#mcp-server-issues)
10
+ - [Development Issues](#development-issues)
11
+ - [Diagnostic Commands](#diagnostic-commands)
12
+
13
+ ## Running Issues
14
+
15
+ ### Running the Test Suite with RVM (Codex macOS)
16
+
17
+ Codex's macOS sandbox forbids `/bin/ps`; RVM shells need it. When you run `bundle exec rspec` there, the shell falls back to macOS Ruby 2.6 and Bundler dies with `Gem::Resolver::APISet::GemParser` errors.
18
+
19
+ **Workarounds:**
20
+
21
+ - Run outside the macOS sandbox (Codex on Ubuntu, Gemini, Claude Code, local shells) or use a version manager that does not invoke `ps`.
22
+ - Or execute RSpec with explicit RVM paths:
23
+ ```bash
24
+ PATH="$HOME/.rvm/gems/ruby-3.4.5@cov-loupe/bin:$HOME/.rvm/rubies/ruby-3.4.5/bin:$PATH" \
25
+ GEM_HOME="$HOME/.rvm/gems/ruby-3.4.5@cov-loupe" \
26
+ GEM_PATH="$HOME/.rvm/gems/ruby-3.4.5@cov-loupe:$HOME/.rvm/gems/ruby-3.4.5@global" \
27
+ $HOME/.rvm/rubies/ruby-3.4.5/bin/bundle exec rspec
28
+ ```
29
+ - Use a different AI coding agent and/or operating system.
30
+
31
+ ## Coverage Data Issues
32
+
33
+ ### Missing `coverage/.resultset.json`
34
+
35
+ `cov-loupe` only reads coverage data; it never generates it. If you see "Could not find .resultset.json":
36
+
37
+ 1. Run the test suite with SimpleCov enabled (default project setup already enables it).
38
+ ```bash
39
+ bundle exec rspec
40
+ ls coverage/.resultset.json
41
+ ```
42
+ 2. If your coverage lives elsewhere, point the tools at it:
43
+ ```bash
44
+ cov-loupe --resultset build/coverage/.resultset.json
45
+ # or
46
+ export COV_LOUPE_OPTS="--resultset build/coverage"
47
+ ```
48
+
49
+ ### Stale Coverage Errors
50
+
51
+ `--staleness error` (or `staleness: 'error'`) compares file mtimes and line counts to the coverage snapshot. When it fails:
52
+
53
+ - Regenerate coverage (`bundle exec rspec`) so the snapshot matches current sources.
54
+ - Or drop back to warning-only behaviour using `--staleness off` / `staleness: 'off'`.
55
+
56
+ If you only care about a subset of files, supply `--tracked-globs` (CLI) or `tracked_globs:` (API) so new files outside those globs do not trigger staleness.
57
+
58
+ ### "No coverage data found for file"
59
+
60
+ The model looks up files by absolute path, then cwd-relative path, then basename. If you still hit this error:
61
+
62
+ 1. Verify the file is listed in the coverage table (`cov-loupe list | grep model.rb`).
63
+ 2. Use the exact project-relative path that SimpleCov recorded (case-sensitive, no symlinks).
64
+ 3. If the file truly never executes under tests, add coverage or exclude it from your workflow.
65
+
66
+ ## MCP Server Issues
67
+
68
+ ### MCP Integration Not Working
69
+
70
+ **Symptoms:**
71
+ - AI assistant reports "Could not connect to MCP server"
72
+ - AI says "I don't have access to cov-loupe tools"
73
+
74
+ **Diagnostic steps:**
75
+
76
+ 1. **Verify executable exists and works:**
77
+ ```bash
78
+ which cov-loupe
79
+ cov-loupe version
80
+ ```
81
+
82
+ 2. **Test MCP server mode manually:**
83
+ ```bash
84
+ echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' | cov-loupe
85
+ ```
86
+ Should return JSON-RPC response.
87
+
88
+ 3. **Verify MCP server is configured:**
89
+ ```bash
90
+ claude mcp list # For Claude Code
91
+ codex mcp list # For Codex
92
+ tail -f cov_loupe.log # Check logs
93
+ ```
94
+
95
+ 4. **Restart AI assistant** - Config changes often require restart
96
+
97
+ 5. **Use absolute path in MCP config:**
98
+ ```bash
99
+ # Find absolute path
100
+ which cov-loupe
101
+
102
+ # Update your MCP client config to use this path
103
+ ```
104
+
105
+ 6. **Use CLI as fallback:**
106
+
107
+ If MCP still isn't working, you can use the CLI with `-fJ` flag instead.
108
+ See **[CLI Fallback for LLMs](CLI_FALLBACK_FOR_LLMS.md)** for complete guidance.
109
+
110
+ ### Path Issues with Version Managers
111
+
112
+ **Symptom:** Works in terminal but not in MCP client.
113
+
114
+ **Cause:** MCP client doesn't have your shell environment (PATH, RVM, etc.).
115
+
116
+ **Solution:** Use absolute paths in MCP configuration:
117
+
118
+ ```bash
119
+ # For rbenv/asdf
120
+ which cov-loupe
121
+ # Use this path in MCP config
122
+
123
+ # For RVM, create wrapper
124
+ rvm wrapper ruby-3.3.8 cov-loupe cov-loupe
125
+ # Use: ~/.rvm/wrappers/ruby-3.3.8/cov-loupe
126
+ ```
127
+
128
+ ## Development Issues
129
+
130
+ ### Test Suite Failures
131
+
132
+ **Symptom:** `bundle exec rspec` fails with coverage errors.
133
+
134
+ **Common causes:**
135
+
136
+ 1. **Stale coverage data** - Delete `coverage/` directory and re-run
137
+ 2. **SimpleCov not loaded** - Check `spec/spec_helper.rb` requires SimpleCov
138
+ 3. **Wrong Ruby version** - Verify Ruby >= 3.2
139
+
140
+ ## Diagnostic Commands
141
+
142
+ Before reporting an issue, run these diagnostic commands and include the output:
143
+
144
+ ```bash
145
+ # System info
146
+ ruby -v
147
+ gem -v
148
+ bundle -v
149
+
150
+ # cov-loupe info
151
+ gem list cov-loupe
152
+ which cov-loupe
153
+ cov-loupe version
154
+
155
+ # Test basic functionality
156
+ cov-loupe --help
157
+ cov-loupe list 2>&1
158
+
159
+ # Check coverage data
160
+ ls -la coverage/.resultset.json
161
+ head -20 coverage/.resultset.json
162
+
163
+ # Test MCP mode
164
+ echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' | cov-loupe 2>&1
165
+ ```
166
+
167
+ ## Getting More Help
168
+
169
+ If the above doesn't solve your problem:
170
+
171
+ 1. **Check error mode** - Run with `--error-mode debug` for full stack traces:
172
+ ```bash
173
+ cov-loupe --error-mode debug summary lib/cov_loupe/cli.rb
174
+ ```
175
+
176
+ 2. **Check logs:**
177
+ ```bash
178
+ # MCP server logs
179
+ tail -50 cov_loupe.log
180
+
181
+ # Or specify custom log location
182
+ cov-loupe --log-file /tmp/debug.log summary lib/cov_loupe/cli.rb
183
+ ```
184
+
185
+ 3. **Search existing issues:**
186
+ https://github.com/keithrbennett/cov-loupe/issues
187
+
188
+ 4. **Report a bug:**
189
+ Include output from [Diagnostic Commands](#diagnostic-commands) above
190
+
191
+ ## Related Documentation
192
+
193
+ - [Installation Guide](INSTALLATION.md) - Setup and PATH configuration
194
+ - [CLI Usage](CLI_USAGE.md) - Command-line options and examples
195
+ - [CLI Fallback for LLMs](CLI_FALLBACK_FOR_LLMS.md) - Using CLI when MCP isn't available
196
+ - [MCP Integration](MCP_INTEGRATION.md) - MCP server configuration
197
+ - [Error Handling](ERROR_HANDLING.md) - Understanding error modes