cov-loupe 3.0.0 → 4.0.0.pre

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 (281) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +230 -0
  3. data/CLAUDE.md +5 -0
  4. data/CODE_OF_CONDUCT.md +62 -0
  5. data/CONTRIBUTING.md +102 -0
  6. data/GEMINI.md +5 -0
  7. data/README.md +154 -51
  8. data/RELEASE_NOTES.md +452 -0
  9. data/dev/images/cov-loupe-icon-lores.png +0 -0
  10. data/dev/images/cov-loupe-icon-square.png +0 -0
  11. data/dev/images/cov-loupe-icon.png +0 -0
  12. data/dev/images/cov-loupe-logo.png +0 -0
  13. data/dev/prompts/README.md +74 -0
  14. data/dev/prompts/archive/architectural-review-and-actions-prompt.md +53 -0
  15. data/dev/prompts/archive/investigate-and-report-issues-prompt.md +33 -0
  16. data/dev/prompts/archive/produce-action-items-prompt.md +25 -0
  17. data/dev/prompts/guidelines/ai-code-evaluator-guidelines.md +337 -0
  18. data/dev/prompts/improve/refactor-test-suite.md +18 -0
  19. data/dev/prompts/improve/simplify-code-logic.md +133 -0
  20. data/dev/prompts/improve/update-documentation.md +21 -0
  21. data/dev/prompts/review/comprehensive-codebase-review.md +176 -0
  22. data/dev/prompts/review/identify-action-items.md +143 -0
  23. data/dev/prompts/review/verify-code-changes.md +54 -0
  24. data/dev/prompts/validate/create-screencast-outline.md +234 -0
  25. data/dev/prompts/validate/test-documentation-examples.md +180 -0
  26. data/docs/QUICKSTART.md +63 -0
  27. data/docs/assets/images/cov-loupe-logo-lores.png +0 -0
  28. data/docs/assets/images/cov-loupe-logo.png +0 -0
  29. data/docs/assets/images/favicon.png +0 -0
  30. data/docs/assets/stylesheets/branding.css +16 -0
  31. data/docs/assets/stylesheets/extra.css +15 -0
  32. data/docs/code_of_conduct.md +1 -0
  33. data/docs/contributing.md +1 -0
  34. data/docs/dev/ARCHITECTURE.md +56 -11
  35. data/docs/dev/DEVELOPMENT.md +116 -12
  36. data/docs/dev/FUTURE_ENHANCEMENTS.md +14 -0
  37. data/docs/dev/README.md +3 -2
  38. data/docs/dev/RELEASING.md +2 -0
  39. data/docs/dev/arch-decisions/README.md +10 -7
  40. data/docs/dev/arch-decisions/application-architecture.md +259 -0
  41. data/docs/dev/arch-decisions/coverage-data-quality.md +193 -0
  42. data/docs/dev/arch-decisions/output-character-mode.md +217 -0
  43. data/docs/dev/arch-decisions/path-resolution.md +90 -0
  44. data/docs/dev/arch-decisions/{004-x-arch-decision.md → policy-validation.md} +32 -28
  45. data/docs/dev/arch-decisions/{005-x-arch-decision.md → simplecov-integration.md} +47 -44
  46. data/docs/dev/presentations/cov-loupe-presentation.md +15 -13
  47. data/docs/examples/mcp-inputs.md +3 -0
  48. data/docs/examples/prompts.md +3 -0
  49. data/docs/examples/success_predicates.md +3 -0
  50. data/docs/fixtures/demo_project/.resultset.json +170 -0
  51. data/docs/fixtures/demo_project/README.md +6 -0
  52. data/docs/fixtures/demo_project/app/controllers/admin/audit_logs_controller.rb +19 -0
  53. data/docs/fixtures/demo_project/app/controllers/orders_controller.rb +26 -0
  54. data/docs/fixtures/demo_project/app/models/order.rb +20 -0
  55. data/docs/fixtures/demo_project/app/models/user.rb +19 -0
  56. data/docs/fixtures/demo_project/lib/api/client.rb +22 -0
  57. data/docs/fixtures/demo_project/lib/ops/jobs/cleanup_job.rb +16 -0
  58. data/docs/fixtures/demo_project/lib/ops/jobs/report_job.rb +17 -0
  59. data/docs/fixtures/demo_project/lib/payments/processor.rb +15 -0
  60. data/docs/fixtures/demo_project/lib/payments/refund_service.rb +15 -0
  61. data/docs/fixtures/demo_project/lib/payments/reporting/exporter.rb +16 -0
  62. data/docs/index.md +1 -0
  63. data/docs/license.md +3 -0
  64. data/docs/release_notes.md +3 -0
  65. data/docs/user/ADVANCED_USAGE.md +208 -115
  66. data/docs/user/CLI_FALLBACK_FOR_LLMS.md +2 -0
  67. data/docs/user/CLI_USAGE.md +276 -101
  68. data/docs/user/ERROR_HANDLING.md +4 -4
  69. data/docs/user/EXAMPLES.md +121 -128
  70. data/docs/user/INSTALLATION.md +9 -28
  71. data/docs/user/LIBRARY_API.md +227 -122
  72. data/docs/user/MCP_INTEGRATION.md +114 -203
  73. data/docs/user/README.md +5 -1
  74. data/docs/user/TROUBLESHOOTING.md +49 -27
  75. data/docs/user/installing-a-prelease-version-of-covloupe.md +43 -0
  76. data/docs/user/{V2-BREAKING-CHANGES.md → migrations/MIGRATING_TO_V2.md} +62 -72
  77. data/docs/user/migrations/MIGRATING_TO_V3.md +72 -0
  78. data/docs/user/migrations/MIGRATING_TO_V4.md +591 -0
  79. data/docs/user/migrations/README.md +22 -0
  80. data/docs/user/prompts/README.md +9 -0
  81. data/docs/user/prompts/non-web-coverage-analysis-prompt.md +103 -0
  82. data/docs/user/prompts/rails-coverage-analysis-prompt.md +94 -0
  83. data/docs/user/prompts/use-cli-not-mcp-prompt.md +53 -0
  84. data/examples/cli_demo.sh +77 -0
  85. data/examples/filter_and_table_demo-output.md +114 -0
  86. data/examples/filter_and_table_demo.rb +174 -0
  87. data/examples/fixtures/demo_project/coverage/.resultset.json +10 -0
  88. data/examples/mcp-inputs/README.md +66 -0
  89. data/examples/mcp-inputs/coverage_detailed.json +1 -0
  90. data/examples/mcp-inputs/coverage_raw.json +1 -0
  91. data/examples/mcp-inputs/coverage_summary.json +1 -0
  92. data/examples/mcp-inputs/list.json +1 -0
  93. data/examples/mcp-inputs/uncovered_lines.json +1 -0
  94. data/examples/prompts/README.md +27 -0
  95. data/examples/prompts/custom_resultset.txt +2 -0
  96. data/examples/prompts/detailed_with_source.txt +2 -0
  97. data/examples/prompts/list_lowest.txt +2 -0
  98. data/examples/prompts/summary.txt +2 -0
  99. data/examples/prompts/uncovered.txt +2 -0
  100. data/examples/success_predicates/README.md +198 -0
  101. data/examples/success_predicates/all_files_above_threshold_predicate.rb +21 -0
  102. data/examples/success_predicates/directory_specific_thresholds_predicate.rb +30 -0
  103. data/examples/success_predicates/project_coverage_minimum_predicate.rb +6 -0
  104. data/lib/cov_loupe/base_tool.rb +229 -20
  105. data/lib/cov_loupe/cli.rb +132 -23
  106. data/lib/cov_loupe/commands/base_command.rb +25 -6
  107. data/lib/cov_loupe/commands/command_factory.rb +0 -1
  108. data/lib/cov_loupe/commands/detailed_command.rb +10 -5
  109. data/lib/cov_loupe/commands/list_command.rb +2 -1
  110. data/lib/cov_loupe/commands/raw_command.rb +7 -5
  111. data/lib/cov_loupe/commands/summary_command.rb +12 -7
  112. data/lib/cov_loupe/commands/totals_command.rb +74 -10
  113. data/lib/cov_loupe/commands/uncovered_command.rb +7 -5
  114. data/lib/cov_loupe/commands/validate_command.rb +11 -3
  115. data/lib/cov_loupe/commands/version_command.rb +6 -4
  116. data/lib/cov_loupe/{app_config.rb → config/app_config.rb} +13 -5
  117. data/lib/cov_loupe/config/app_context.rb +43 -0
  118. data/lib/cov_loupe/config/boolean_type.rb +91 -0
  119. data/lib/cov_loupe/config/logger.rb +92 -0
  120. data/lib/cov_loupe/{option_normalizers.rb → config/option_normalizers.rb} +55 -24
  121. data/lib/cov_loupe/{option_parser_builder.rb → config/option_parser_builder.rb} +46 -24
  122. data/lib/cov_loupe/coverage/coverage_calculator.rb +53 -0
  123. data/lib/cov_loupe/coverage/coverage_reporter.rb +63 -0
  124. data/lib/cov_loupe/coverage/coverage_table_formatter.rb +133 -0
  125. data/lib/cov_loupe/{error_handler.rb → errors/error_handler.rb} +21 -33
  126. data/lib/cov_loupe/{errors.rb → errors/errors.rb} +48 -71
  127. data/lib/cov_loupe/formatters/formatters.rb +75 -0
  128. data/lib/cov_loupe/formatters/source_formatter.rb +18 -7
  129. data/lib/cov_loupe/formatters/table_formatter.rb +80 -0
  130. data/lib/cov_loupe/loaders/all.rb +15 -0
  131. data/lib/cov_loupe/loaders/all_cli.rb +10 -0
  132. data/lib/cov_loupe/loaders/all_mcp.rb +23 -0
  133. data/lib/cov_loupe/loaders/resultset_loader.rb +147 -0
  134. data/lib/cov_loupe/mcp_server.rb +3 -2
  135. data/lib/cov_loupe/model/model.rb +520 -0
  136. data/lib/cov_loupe/model/model_data.rb +13 -0
  137. data/lib/cov_loupe/model/model_data_cache.rb +116 -0
  138. data/lib/cov_loupe/option_parsers/env_options_parser.rb +17 -6
  139. data/lib/cov_loupe/option_parsers/error_helper.rb +16 -10
  140. data/lib/cov_loupe/output_chars.rb +192 -0
  141. data/lib/cov_loupe/paths/glob_utils.rb +100 -0
  142. data/lib/cov_loupe/{path_relativizer.rb → paths/path_relativizer.rb} +5 -13
  143. data/lib/cov_loupe/paths/path_utils.rb +265 -0
  144. data/lib/cov_loupe/paths/volume_case_sensitivity.rb +173 -0
  145. data/lib/cov_loupe/presenters/base_coverage_presenter.rb +9 -13
  146. data/lib/cov_loupe/presenters/coverage_payload_presenter.rb +21 -0
  147. data/lib/cov_loupe/presenters/payload_caching.rb +23 -0
  148. data/lib/cov_loupe/presenters/project_coverage_presenter.rb +73 -21
  149. data/lib/cov_loupe/presenters/project_totals_presenter.rb +16 -10
  150. data/lib/cov_loupe/repositories/coverage_repository.rb +149 -0
  151. data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +90 -76
  152. data/lib/cov_loupe/resolvers/{resolver_factory.rb → resolver_helpers.rb} +6 -5
  153. data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +40 -12
  154. data/lib/cov_loupe/scripts/command_execution.rb +113 -0
  155. data/lib/cov_loupe/scripts/latest_ci_status.rb +97 -0
  156. data/lib/cov_loupe/scripts/pre_release_check.rb +164 -0
  157. data/lib/cov_loupe/scripts/setup_doc_server.rb +23 -0
  158. data/lib/cov_loupe/scripts/start_doc_server.rb +24 -0
  159. data/lib/cov_loupe/staleness/stale_status.rb +23 -0
  160. data/lib/cov_loupe/staleness/staleness_checker.rb +328 -0
  161. data/lib/cov_loupe/staleness/staleness_message_formatter.rb +91 -0
  162. data/lib/cov_loupe/tools/coverage_detailed_tool.rb +14 -15
  163. data/lib/cov_loupe/tools/coverage_raw_tool.rb +14 -14
  164. data/lib/cov_loupe/tools/coverage_summary_tool.rb +16 -16
  165. data/lib/cov_loupe/tools/coverage_table_tool.rb +139 -21
  166. data/lib/cov_loupe/tools/coverage_totals_tool.rb +31 -13
  167. data/lib/cov_loupe/tools/help_tool.rb +16 -20
  168. data/lib/cov_loupe/tools/list_tool.rb +65 -0
  169. data/lib/cov_loupe/tools/uncovered_lines_tool.rb +14 -14
  170. data/lib/cov_loupe/tools/validate_tool.rb +18 -24
  171. data/lib/cov_loupe/tools/version_tool.rb +8 -3
  172. data/lib/cov_loupe/version.rb +1 -1
  173. data/lib/cov_loupe.rb +83 -55
  174. metadata +184 -154
  175. data/docs/dev/BRANCH_ONLY_COVERAGE.md +0 -158
  176. data/docs/dev/arch-decisions/001-x-arch-decision.md +0 -95
  177. data/docs/dev/arch-decisions/002-x-arch-decision.md +0 -159
  178. data/docs/dev/arch-decisions/003-x-arch-decision.md +0 -165
  179. data/lib/cov_loupe/app_context.rb +0 -26
  180. data/lib/cov_loupe/constants.rb +0 -22
  181. data/lib/cov_loupe/coverage_reporter.rb +0 -31
  182. data/lib/cov_loupe/formatters.rb +0 -51
  183. data/lib/cov_loupe/mode_detector.rb +0 -56
  184. data/lib/cov_loupe/model.rb +0 -339
  185. data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +0 -14
  186. data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +0 -14
  187. data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +0 -14
  188. data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +0 -14
  189. data/lib/cov_loupe/resultset_loader.rb +0 -131
  190. data/lib/cov_loupe/staleness_checker.rb +0 -247
  191. data/lib/cov_loupe/table_formatter.rb +0 -64
  192. data/lib/cov_loupe/tools/all_files_coverage_tool.rb +0 -51
  193. data/lib/cov_loupe/util.rb +0 -88
  194. data/spec/MCP_INTEGRATION_TESTS_README.md +0 -111
  195. data/spec/TIMESTAMPS.md +0 -48
  196. data/spec/all_files_coverage_tool_spec.rb +0 -53
  197. data/spec/app_config_spec.rb +0 -142
  198. data/spec/base_tool_spec.rb +0 -62
  199. data/spec/cli/show_default_report_spec.rb +0 -33
  200. data/spec/cli_enumerated_options_spec.rb +0 -90
  201. data/spec/cli_error_spec.rb +0 -184
  202. data/spec/cli_format_spec.rb +0 -123
  203. data/spec/cli_json_options_spec.rb +0 -50
  204. data/spec/cli_source_spec.rb +0 -44
  205. data/spec/cli_spec.rb +0 -192
  206. data/spec/cli_table_spec.rb +0 -28
  207. data/spec/cli_usage_spec.rb +0 -42
  208. data/spec/commands/base_command_spec.rb +0 -107
  209. data/spec/commands/command_factory_spec.rb +0 -76
  210. data/spec/commands/detailed_command_spec.rb +0 -34
  211. data/spec/commands/list_command_spec.rb +0 -28
  212. data/spec/commands/raw_command_spec.rb +0 -69
  213. data/spec/commands/summary_command_spec.rb +0 -34
  214. data/spec/commands/totals_command_spec.rb +0 -34
  215. data/spec/commands/uncovered_command_spec.rb +0 -55
  216. data/spec/commands/validate_command_spec.rb +0 -213
  217. data/spec/commands/version_command_spec.rb +0 -38
  218. data/spec/constants_spec.rb +0 -61
  219. data/spec/cov_loupe/formatters/source_formatter_spec.rb +0 -267
  220. data/spec/cov_loupe/formatters_spec.rb +0 -76
  221. data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +0 -79
  222. data/spec/cov_loupe_model_spec.rb +0 -454
  223. data/spec/cov_loupe_module_spec.rb +0 -37
  224. data/spec/cov_loupe_opts_spec.rb +0 -185
  225. data/spec/coverage_reporter_spec.rb +0 -102
  226. data/spec/coverage_table_tool_spec.rb +0 -59
  227. data/spec/coverage_totals_tool_spec.rb +0 -37
  228. data/spec/error_handler_spec.rb +0 -197
  229. data/spec/error_mode_spec.rb +0 -139
  230. data/spec/errors_edge_cases_spec.rb +0 -312
  231. data/spec/errors_stale_spec.rb +0 -83
  232. data/spec/file_based_mcp_tools_spec.rb +0 -99
  233. data/spec/help_tool_spec.rb +0 -26
  234. data/spec/integration_spec.rb +0 -789
  235. data/spec/logging_fallback_spec.rb +0 -128
  236. data/spec/mcp_logging_spec.rb +0 -44
  237. data/spec/mcp_server_integration_spec.rb +0 -23
  238. data/spec/mcp_server_spec.rb +0 -106
  239. data/spec/mode_detector_spec.rb +0 -153
  240. data/spec/model_error_handling_spec.rb +0 -269
  241. data/spec/model_staleness_spec.rb +0 -79
  242. data/spec/option_normalizers_spec.rb +0 -203
  243. data/spec/option_parsers/env_options_parser_spec.rb +0 -221
  244. data/spec/option_parsers/error_helper_spec.rb +0 -222
  245. data/spec/path_relativizer_spec.rb +0 -98
  246. data/spec/presenters/coverage_detailed_presenter_spec.rb +0 -19
  247. data/spec/presenters/coverage_raw_presenter_spec.rb +0 -15
  248. data/spec/presenters/coverage_summary_presenter_spec.rb +0 -15
  249. data/spec/presenters/coverage_uncovered_presenter_spec.rb +0 -16
  250. data/spec/presenters/project_coverage_presenter_spec.rb +0 -87
  251. data/spec/presenters/project_totals_presenter_spec.rb +0 -144
  252. data/spec/resolvers/coverage_line_resolver_spec.rb +0 -282
  253. data/spec/resolvers/resolver_factory_spec.rb +0 -61
  254. data/spec/resolvers/resultset_path_resolver_spec.rb +0 -60
  255. data/spec/resultset_loader_spec.rb +0 -167
  256. data/spec/shared_examples/README.md +0 -115
  257. data/spec/shared_examples/coverage_presenter_examples.rb +0 -66
  258. data/spec/shared_examples/file_based_mcp_tools.rb +0 -179
  259. data/spec/shared_examples/formatted_command_examples.rb +0 -64
  260. data/spec/shared_examples/mcp_tool_text_json_response.rb +0 -16
  261. data/spec/spec_helper.rb +0 -127
  262. data/spec/staleness_checker_spec.rb +0 -374
  263. data/spec/staleness_more_spec.rb +0 -42
  264. data/spec/support/cli_helpers.rb +0 -22
  265. data/spec/support/control_flow_helpers.rb +0 -20
  266. data/spec/support/fake_mcp.rb +0 -40
  267. data/spec/support/io_helpers.rb +0 -29
  268. data/spec/support/mcp_helpers.rb +0 -35
  269. data/spec/support/mcp_runner.rb +0 -66
  270. data/spec/support/mocking_helpers.rb +0 -30
  271. data/spec/table_format_spec.rb +0 -70
  272. data/spec/tools/validate_tool_spec.rb +0 -132
  273. data/spec/tools_error_handling_spec.rb +0 -130
  274. data/spec/util_spec.rb +0 -154
  275. data/spec/version_spec.rb +0 -123
  276. data/spec/version_tool_spec.rb +0 -141
  277. /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/bar.rb +0 -0
  278. /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/foo.rb +0 -0
  279. /data/lib/cov_loupe/{config_parser.rb → config/config_parser.rb} +0 -0
  280. /data/lib/cov_loupe/{predicate_evaluator.rb → config/predicate_evaluator.rb} +0 -0
  281. /data/lib/cov_loupe/{error_handler_factory.rb → errors/error_handler_factory.rb} +0 -0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cov-loupe
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 4.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith R. Bennett
@@ -10,33 +10,47 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: awesome_print
13
+ name: amazing_print
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '1.9'
18
+ version: '2.0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '1.9'
25
+ version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: logger
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: mcp
28
42
  requirement: !ruby/object:Gem::Requirement
29
43
  requirements:
30
44
  - - "~>"
31
45
  - !ruby/object:Gem::Version
32
- version: '0.3'
46
+ version: '0.4'
33
47
  type: :runtime
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
51
  - - "~>"
38
52
  - !ruby/object:Gem::Version
39
- version: '0.3'
53
+ version: '0.4'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: simplecov
42
56
  requirement: !ruby/object:Gem::Requirement
@@ -66,21 +80,70 @@ executables:
66
80
  extensions: []
67
81
  extra_rdoc_files: []
68
82
  files:
83
+ - AGENTS.md
84
+ - CLAUDE.md
85
+ - CODE_OF_CONDUCT.md
86
+ - CONTRIBUTING.md
87
+ - GEMINI.md
69
88
  - LICENSE
70
89
  - README.md
90
+ - RELEASE_NOTES.md
91
+ - dev/images/cov-loupe-icon-lores.png
92
+ - dev/images/cov-loupe-icon-square.png
93
+ - dev/images/cov-loupe-icon.png
94
+ - dev/images/cov-loupe-logo.png
95
+ - dev/prompts/README.md
96
+ - dev/prompts/archive/architectural-review-and-actions-prompt.md
97
+ - dev/prompts/archive/investigate-and-report-issues-prompt.md
98
+ - dev/prompts/archive/produce-action-items-prompt.md
99
+ - dev/prompts/guidelines/ai-code-evaluator-guidelines.md
100
+ - dev/prompts/improve/refactor-test-suite.md
101
+ - dev/prompts/improve/simplify-code-logic.md
102
+ - dev/prompts/improve/update-documentation.md
103
+ - dev/prompts/review/comprehensive-codebase-review.md
104
+ - dev/prompts/review/identify-action-items.md
105
+ - dev/prompts/review/verify-code-changes.md
106
+ - dev/prompts/validate/create-screencast-outline.md
107
+ - dev/prompts/validate/test-documentation-examples.md
108
+ - docs/QUICKSTART.md
109
+ - docs/assets/images/cov-loupe-logo-lores.png
110
+ - docs/assets/images/cov-loupe-logo.png
111
+ - docs/assets/images/favicon.png
112
+ - docs/assets/stylesheets/branding.css
113
+ - docs/assets/stylesheets/extra.css
114
+ - docs/code_of_conduct.md
115
+ - docs/contributing.md
71
116
  - docs/dev/ARCHITECTURE.md
72
- - docs/dev/BRANCH_ONLY_COVERAGE.md
73
117
  - docs/dev/DEVELOPMENT.md
118
+ - docs/dev/FUTURE_ENHANCEMENTS.md
74
119
  - docs/dev/README.md
75
120
  - docs/dev/RELEASING.md
76
- - docs/dev/arch-decisions/001-x-arch-decision.md
77
- - docs/dev/arch-decisions/002-x-arch-decision.md
78
- - docs/dev/arch-decisions/003-x-arch-decision.md
79
- - docs/dev/arch-decisions/004-x-arch-decision.md
80
- - docs/dev/arch-decisions/005-x-arch-decision.md
81
121
  - docs/dev/arch-decisions/README.md
122
+ - docs/dev/arch-decisions/application-architecture.md
123
+ - docs/dev/arch-decisions/coverage-data-quality.md
124
+ - docs/dev/arch-decisions/output-character-mode.md
125
+ - docs/dev/arch-decisions/path-resolution.md
126
+ - docs/dev/arch-decisions/policy-validation.md
127
+ - docs/dev/arch-decisions/simplecov-integration.md
82
128
  - docs/dev/presentations/cov-loupe-presentation.md
129
+ - docs/examples/mcp-inputs.md
130
+ - docs/examples/prompts.md
131
+ - docs/examples/success_predicates.md
132
+ - docs/fixtures/demo_project/.resultset.json
83
133
  - docs/fixtures/demo_project/README.md
134
+ - docs/fixtures/demo_project/app/controllers/admin/audit_logs_controller.rb
135
+ - docs/fixtures/demo_project/app/controllers/orders_controller.rb
136
+ - docs/fixtures/demo_project/app/models/order.rb
137
+ - docs/fixtures/demo_project/app/models/user.rb
138
+ - docs/fixtures/demo_project/lib/api/client.rb
139
+ - docs/fixtures/demo_project/lib/ops/jobs/cleanup_job.rb
140
+ - docs/fixtures/demo_project/lib/ops/jobs/report_job.rb
141
+ - docs/fixtures/demo_project/lib/payments/processor.rb
142
+ - docs/fixtures/demo_project/lib/payments/refund_service.rb
143
+ - docs/fixtures/demo_project/lib/payments/reporting/exporter.rb
144
+ - docs/index.md
145
+ - docs/license.md
146
+ - docs/release_notes.md
84
147
  - docs/user/ADVANCED_USAGE.md
85
148
  - docs/user/CLI_FALLBACK_FOR_LLMS.md
86
149
  - docs/user/CLI_USAGE.md
@@ -91,11 +154,39 @@ files:
91
154
  - docs/user/MCP_INTEGRATION.md
92
155
  - docs/user/README.md
93
156
  - docs/user/TROUBLESHOOTING.md
94
- - docs/user/V2-BREAKING-CHANGES.md
157
+ - docs/user/installing-a-prelease-version-of-covloupe.md
158
+ - docs/user/migrations/MIGRATING_TO_V2.md
159
+ - docs/user/migrations/MIGRATING_TO_V3.md
160
+ - docs/user/migrations/MIGRATING_TO_V4.md
161
+ - docs/user/migrations/README.md
162
+ - docs/user/prompts/README.md
163
+ - docs/user/prompts/non-web-coverage-analysis-prompt.md
164
+ - docs/user/prompts/rails-coverage-analysis-prompt.md
165
+ - docs/user/prompts/use-cli-not-mcp-prompt.md
166
+ - examples/cli_demo.sh
167
+ - examples/filter_and_table_demo-output.md
168
+ - examples/filter_and_table_demo.rb
169
+ - examples/fixtures/demo_project/coverage/.resultset.json
170
+ - examples/fixtures/demo_project/lib/bar.rb
171
+ - examples/fixtures/demo_project/lib/foo.rb
172
+ - examples/mcp-inputs/README.md
173
+ - examples/mcp-inputs/coverage_detailed.json
174
+ - examples/mcp-inputs/coverage_raw.json
175
+ - examples/mcp-inputs/coverage_summary.json
176
+ - examples/mcp-inputs/list.json
177
+ - examples/mcp-inputs/uncovered_lines.json
178
+ - examples/prompts/README.md
179
+ - examples/prompts/custom_resultset.txt
180
+ - examples/prompts/detailed_with_source.txt
181
+ - examples/prompts/list_lowest.txt
182
+ - examples/prompts/summary.txt
183
+ - examples/prompts/uncovered.txt
184
+ - examples/success_predicates/README.md
185
+ - examples/success_predicates/all_files_above_threshold_predicate.rb
186
+ - examples/success_predicates/directory_specific_thresholds_predicate.rb
187
+ - examples/success_predicates/project_coverage_minimum_predicate.rb
95
188
  - exe/cov-loupe
96
189
  - lib/cov_loupe.rb
97
- - lib/cov_loupe/app_config.rb
98
- - lib/cov_loupe/app_context.rb
99
190
  - lib/cov_loupe/base_tool.rb
100
191
  - lib/cov_loupe/cli.rb
101
192
  - lib/cov_loupe/commands/base_command.rb
@@ -108,168 +199,107 @@ files:
108
199
  - lib/cov_loupe/commands/uncovered_command.rb
109
200
  - lib/cov_loupe/commands/validate_command.rb
110
201
  - lib/cov_loupe/commands/version_command.rb
111
- - lib/cov_loupe/config_parser.rb
112
- - lib/cov_loupe/constants.rb
113
- - lib/cov_loupe/coverage_reporter.rb
114
- - lib/cov_loupe/error_handler.rb
115
- - lib/cov_loupe/error_handler_factory.rb
116
- - lib/cov_loupe/errors.rb
117
- - lib/cov_loupe/formatters.rb
202
+ - lib/cov_loupe/config/app_config.rb
203
+ - lib/cov_loupe/config/app_context.rb
204
+ - lib/cov_loupe/config/boolean_type.rb
205
+ - lib/cov_loupe/config/config_parser.rb
206
+ - lib/cov_loupe/config/logger.rb
207
+ - lib/cov_loupe/config/option_normalizers.rb
208
+ - lib/cov_loupe/config/option_parser_builder.rb
209
+ - lib/cov_loupe/config/predicate_evaluator.rb
210
+ - lib/cov_loupe/coverage/coverage_calculator.rb
211
+ - lib/cov_loupe/coverage/coverage_reporter.rb
212
+ - lib/cov_loupe/coverage/coverage_table_formatter.rb
213
+ - lib/cov_loupe/errors/error_handler.rb
214
+ - lib/cov_loupe/errors/error_handler_factory.rb
215
+ - lib/cov_loupe/errors/errors.rb
216
+ - lib/cov_loupe/formatters/formatters.rb
118
217
  - lib/cov_loupe/formatters/source_formatter.rb
218
+ - lib/cov_loupe/formatters/table_formatter.rb
219
+ - lib/cov_loupe/loaders/all.rb
220
+ - lib/cov_loupe/loaders/all_cli.rb
221
+ - lib/cov_loupe/loaders/all_mcp.rb
222
+ - lib/cov_loupe/loaders/resultset_loader.rb
119
223
  - lib/cov_loupe/mcp_server.rb
120
- - lib/cov_loupe/mode_detector.rb
121
- - lib/cov_loupe/model.rb
122
- - lib/cov_loupe/option_normalizers.rb
123
- - lib/cov_loupe/option_parser_builder.rb
224
+ - lib/cov_loupe/model/model.rb
225
+ - lib/cov_loupe/model/model_data.rb
226
+ - lib/cov_loupe/model/model_data_cache.rb
124
227
  - lib/cov_loupe/option_parsers/env_options_parser.rb
125
228
  - lib/cov_loupe/option_parsers/error_helper.rb
126
- - lib/cov_loupe/path_relativizer.rb
127
- - lib/cov_loupe/predicate_evaluator.rb
229
+ - lib/cov_loupe/output_chars.rb
230
+ - lib/cov_loupe/paths/glob_utils.rb
231
+ - lib/cov_loupe/paths/path_relativizer.rb
232
+ - lib/cov_loupe/paths/path_utils.rb
233
+ - lib/cov_loupe/paths/volume_case_sensitivity.rb
128
234
  - lib/cov_loupe/presenters/base_coverage_presenter.rb
129
- - lib/cov_loupe/presenters/coverage_detailed_presenter.rb
130
- - lib/cov_loupe/presenters/coverage_raw_presenter.rb
131
- - lib/cov_loupe/presenters/coverage_summary_presenter.rb
132
- - lib/cov_loupe/presenters/coverage_uncovered_presenter.rb
235
+ - lib/cov_loupe/presenters/coverage_payload_presenter.rb
236
+ - lib/cov_loupe/presenters/payload_caching.rb
133
237
  - lib/cov_loupe/presenters/project_coverage_presenter.rb
134
238
  - lib/cov_loupe/presenters/project_totals_presenter.rb
239
+ - lib/cov_loupe/repositories/coverage_repository.rb
135
240
  - lib/cov_loupe/resolvers/coverage_line_resolver.rb
136
- - lib/cov_loupe/resolvers/resolver_factory.rb
241
+ - lib/cov_loupe/resolvers/resolver_helpers.rb
137
242
  - lib/cov_loupe/resolvers/resultset_path_resolver.rb
138
- - lib/cov_loupe/resultset_loader.rb
139
- - lib/cov_loupe/staleness_checker.rb
140
- - lib/cov_loupe/table_formatter.rb
141
- - lib/cov_loupe/tools/all_files_coverage_tool.rb
243
+ - lib/cov_loupe/scripts/command_execution.rb
244
+ - lib/cov_loupe/scripts/latest_ci_status.rb
245
+ - lib/cov_loupe/scripts/pre_release_check.rb
246
+ - lib/cov_loupe/scripts/setup_doc_server.rb
247
+ - lib/cov_loupe/scripts/start_doc_server.rb
248
+ - lib/cov_loupe/staleness/stale_status.rb
249
+ - lib/cov_loupe/staleness/staleness_checker.rb
250
+ - lib/cov_loupe/staleness/staleness_message_formatter.rb
142
251
  - lib/cov_loupe/tools/coverage_detailed_tool.rb
143
252
  - lib/cov_loupe/tools/coverage_raw_tool.rb
144
253
  - lib/cov_loupe/tools/coverage_summary_tool.rb
145
254
  - lib/cov_loupe/tools/coverage_table_tool.rb
146
255
  - lib/cov_loupe/tools/coverage_totals_tool.rb
147
256
  - lib/cov_loupe/tools/help_tool.rb
257
+ - lib/cov_loupe/tools/list_tool.rb
148
258
  - lib/cov_loupe/tools/uncovered_lines_tool.rb
149
259
  - lib/cov_loupe/tools/validate_tool.rb
150
260
  - lib/cov_loupe/tools/version_tool.rb
151
- - lib/cov_loupe/util.rb
152
261
  - lib/cov_loupe/version.rb
153
- - spec/MCP_INTEGRATION_TESTS_README.md
154
- - spec/TIMESTAMPS.md
155
- - spec/all_files_coverage_tool_spec.rb
156
- - spec/app_config_spec.rb
157
- - spec/base_tool_spec.rb
158
- - spec/cli/show_default_report_spec.rb
159
- - spec/cli_enumerated_options_spec.rb
160
- - spec/cli_error_spec.rb
161
- - spec/cli_format_spec.rb
162
- - spec/cli_json_options_spec.rb
163
- - spec/cli_source_spec.rb
164
- - spec/cli_spec.rb
165
- - spec/cli_table_spec.rb
166
- - spec/cli_usage_spec.rb
167
- - spec/commands/base_command_spec.rb
168
- - spec/commands/command_factory_spec.rb
169
- - spec/commands/detailed_command_spec.rb
170
- - spec/commands/list_command_spec.rb
171
- - spec/commands/raw_command_spec.rb
172
- - spec/commands/summary_command_spec.rb
173
- - spec/commands/totals_command_spec.rb
174
- - spec/commands/uncovered_command_spec.rb
175
- - spec/commands/validate_command_spec.rb
176
- - spec/commands/version_command_spec.rb
177
- - spec/constants_spec.rb
178
- - spec/cov_loupe/formatters/source_formatter_spec.rb
179
- - spec/cov_loupe/formatters_spec.rb
180
- - spec/cov_loupe/presenters/base_coverage_presenter_spec.rb
181
- - spec/cov_loupe_model_spec.rb
182
- - spec/cov_loupe_module_spec.rb
183
- - spec/cov_loupe_opts_spec.rb
184
- - spec/coverage_reporter_spec.rb
185
- - spec/coverage_table_tool_spec.rb
186
- - spec/coverage_totals_tool_spec.rb
187
- - spec/error_handler_spec.rb
188
- - spec/error_mode_spec.rb
189
- - spec/errors_edge_cases_spec.rb
190
- - spec/errors_stale_spec.rb
191
- - spec/file_based_mcp_tools_spec.rb
192
- - spec/fixtures/project1/lib/bar.rb
193
- - spec/fixtures/project1/lib/foo.rb
194
- - spec/help_tool_spec.rb
195
- - spec/integration_spec.rb
196
- - spec/logging_fallback_spec.rb
197
- - spec/mcp_logging_spec.rb
198
- - spec/mcp_server_integration_spec.rb
199
- - spec/mcp_server_spec.rb
200
- - spec/mode_detector_spec.rb
201
- - spec/model_error_handling_spec.rb
202
- - spec/model_staleness_spec.rb
203
- - spec/option_normalizers_spec.rb
204
- - spec/option_parsers/env_options_parser_spec.rb
205
- - spec/option_parsers/error_helper_spec.rb
206
- - spec/path_relativizer_spec.rb
207
- - spec/presenters/coverage_detailed_presenter_spec.rb
208
- - spec/presenters/coverage_raw_presenter_spec.rb
209
- - spec/presenters/coverage_summary_presenter_spec.rb
210
- - spec/presenters/coverage_uncovered_presenter_spec.rb
211
- - spec/presenters/project_coverage_presenter_spec.rb
212
- - spec/presenters/project_totals_presenter_spec.rb
213
- - spec/resolvers/coverage_line_resolver_spec.rb
214
- - spec/resolvers/resolver_factory_spec.rb
215
- - spec/resolvers/resultset_path_resolver_spec.rb
216
- - spec/resultset_loader_spec.rb
217
- - spec/shared_examples/README.md
218
- - spec/shared_examples/coverage_presenter_examples.rb
219
- - spec/shared_examples/file_based_mcp_tools.rb
220
- - spec/shared_examples/formatted_command_examples.rb
221
- - spec/shared_examples/mcp_tool_text_json_response.rb
222
- - spec/spec_helper.rb
223
- - spec/staleness_checker_spec.rb
224
- - spec/staleness_more_spec.rb
225
- - spec/support/cli_helpers.rb
226
- - spec/support/control_flow_helpers.rb
227
- - spec/support/fake_mcp.rb
228
- - spec/support/io_helpers.rb
229
- - spec/support/mcp_helpers.rb
230
- - spec/support/mcp_runner.rb
231
- - spec/support/mocking_helpers.rb
232
- - spec/table_format_spec.rb
233
- - spec/tools/validate_tool_spec.rb
234
- - spec/tools_error_handling_spec.rb
235
- - spec/util_spec.rb
236
- - spec/version_spec.rb
237
- - spec/version_tool_spec.rb
238
262
  homepage: https://github.com/keithrbennett/cov-loupe
239
263
  licenses:
240
264
  - MIT
241
265
  metadata:
242
266
  rubygems_mfa_required: 'true'
243
- post_install_message: |
244
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
245
- V3.0.0 - GEM RENAMED: simplecov-mcp → cov-loupe ┃
246
- ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
247
-
248
- This gem has been renamed! If upgrading from simplecov-mcp:
249
-
250
- • Executable: simplecov-mcp → cov-loupe ┃
251
- ┃ • Environment: SIMPLECOV_MCP_OPTS COV_LOUPE_OPTS
252
- • Log file: simplecov_mcp.log → cov_loupe.log ┃
253
- ┃ • Alias: smcp → clp (in documentation) ┃
254
-
255
- Module name (CovLoupe) and require path (cov_loupe) unchanged. ┃
256
-
257
- Uninstall old gem: gem uninstall simplecov-mcp
258
-
259
- ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
260
- V2.0.0 BREAKING CHANGES (if upgrading from v1.x) ┃
261
- ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
262
-
263
- Options must now come BEFORE subcommands
264
- --stale renamed to --staleness (-S still works)
265
- --json replaced with --format json
266
- • Error modes renamed: 'on' → 'log', 'trace' → 'debug' ┃
267
- ┃ • --success-predicate moved to 'validate' subcommand
268
- ┃ • Default sort order changed from ascending to descending
269
-
270
- See docs/user/V2-BREAKING-CHANGES.md for complete migration guide. ┃
271
-
272
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
267
+ post_install_message: "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n┃
268
+ V4.0.0 BREAKING CHANGES ┃\n┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n┃
269
+ \ ┃\n
270
+ \ ⚠️ MCP MODE NOW REQUIRES -m/--mode mcp FLAG (AUTO-DETECTION REMOVED) ┃\n┃
271
+ \ ┃\n
272
+ \ If you use cov-loupe as an MCP server, you MUST update your config. ┃\n
273
+ \ Without -m mcp, the server will run in CLI mode and hang. ┃\n
274
+ \ ┃\n
275
+ \ \U0001F4D6 Migration instructions: docs/user/migrations/MIGRATING_TO_V4.md ┃\n
276
+ \ ┃\n
277
+ Other breaking changes: ┃\n┃ •
278
+ --force-mode removed → use -m/--mode cli|mcp instead ┃\n • --staleness
279
+ removed use --raise-on-stale (boolean) instead ┃\n┃ • Ruby API: check_stale
280
+ removed → use raise_on_stale (boolean) instead ┃\n • Model #all_files_coverage
281
+ method renamed to #list ┃\n ┃\n┃
282
+ See RELEASE_NOTES.md for full migration details. ┃\n ┃\n┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n
283
+ V3.0.0 - GEM RENAMED: simplecov-mcp → cov-loupe ┃\n┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n┃
284
+ \ ┃\n
285
+ This gem has been renamed! If upgrading from simplecov-mcp: ┃\n┃ ┃\n┃
286
+ \ • Executable: simplecov-mcp → cov-loupe ┃\n
287
+ \ Environment: SIMPLECOV_MCP_OPTS COV_LOUPE_OPTS ┃\n
288
+ \ Log file: simplecov_mcp.log cov_loupe.log ┃\n
289
+ \ Alias: smcp clp (in documentation) ┃\n
290
+ \ ┃\n
291
+ Module name (CovLoupe) and require path (cov_loupe) unchanged. ┃\n ┃\n┃
292
+ Uninstall old gem: gem uninstall simplecov-mcp ┃\n ┃\n┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n┃
293
+ V2.0.0 BREAKING CHANGES (if upgrading from v1.x) ┃\n┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n
294
+ \ ┃\n
295
+ \ • Options must now come BEFORE subcommands ┃\n
296
+ \ • --stale renamed to --staleness (-S still works) ┃\n┃
297
+ \ • --json replaced with --format json ┃\n┃
298
+ \ • Error modes renamed: 'on' → 'log', 'trace' → 'debug' ┃\n┃
299
+ \ • --success-predicate moved to 'validate' subcommand ┃\n┃
300
+ \ • Default sort order changed from ascending to descending ┃\n┃
301
+ \ ┃\n┃
302
+ See docs/user/migrations/MIGRATING_TO_V2.md for complete migration guide. ┃\n┃ ┃\n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n"
273
303
  rdoc_options: []
274
304
  require_paths:
275
305
  - lib
@@ -284,7 +314,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
314
  - !ruby/object:Gem::Version
285
315
  version: '0'
286
316
  requirements: []
287
- rubygems_version: 3.7.2
317
+ rubygems_version: 4.0.4
288
318
  specification_version: 4
289
319
  summary: MCP server + CLI for SimpleCov coverage data
290
320
  test_files: []
@@ -1,158 +0,0 @@
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/cov_loupe/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/cov_loupe_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.