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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +329 -0
- data/docs/dev/ARCHITECTURE.md +80 -0
- data/docs/dev/BRANCH_ONLY_COVERAGE.md +158 -0
- data/docs/dev/DEVELOPMENT.md +83 -0
- data/docs/dev/README.md +10 -0
- data/docs/dev/RELEASING.md +146 -0
- data/docs/dev/arch-decisions/001-x-arch-decision.md +95 -0
- data/docs/dev/arch-decisions/002-x-arch-decision.md +159 -0
- data/docs/dev/arch-decisions/003-x-arch-decision.md +165 -0
- data/docs/dev/arch-decisions/004-x-arch-decision.md +203 -0
- data/docs/dev/arch-decisions/005-x-arch-decision.md +189 -0
- data/docs/dev/arch-decisions/README.md +60 -0
- data/docs/dev/presentations/cov-loupe-presentation.md +255 -0
- data/docs/fixtures/demo_project/README.md +9 -0
- data/docs/user/ADVANCED_USAGE.md +777 -0
- data/docs/user/CLI_FALLBACK_FOR_LLMS.md +34 -0
- data/docs/user/CLI_USAGE.md +750 -0
- data/docs/user/ERROR_HANDLING.md +93 -0
- data/docs/user/EXAMPLES.md +588 -0
- data/docs/user/INSTALLATION.md +130 -0
- data/docs/user/LIBRARY_API.md +693 -0
- data/docs/user/MCP_INTEGRATION.md +490 -0
- data/docs/user/README.md +14 -0
- data/docs/user/TROUBLESHOOTING.md +197 -0
- data/docs/user/V2-BREAKING-CHANGES.md +472 -0
- data/exe/cov-loupe +23 -0
- data/lib/cov_loupe/app_config.rb +56 -0
- data/lib/cov_loupe/app_context.rb +26 -0
- data/lib/cov_loupe/base_tool.rb +102 -0
- data/lib/cov_loupe/cli.rb +178 -0
- data/lib/cov_loupe/commands/base_command.rb +67 -0
- data/lib/cov_loupe/commands/command_factory.rb +45 -0
- data/lib/cov_loupe/commands/detailed_command.rb +38 -0
- data/lib/cov_loupe/commands/list_command.rb +13 -0
- data/lib/cov_loupe/commands/raw_command.rb +38 -0
- data/lib/cov_loupe/commands/summary_command.rb +41 -0
- data/lib/cov_loupe/commands/totals_command.rb +53 -0
- data/lib/cov_loupe/commands/uncovered_command.rb +45 -0
- data/lib/cov_loupe/commands/validate_command.rb +60 -0
- data/lib/cov_loupe/commands/version_command.rb +33 -0
- data/lib/cov_loupe/config_parser.rb +32 -0
- data/lib/cov_loupe/constants.rb +22 -0
- data/lib/cov_loupe/coverage_reporter.rb +31 -0
- data/lib/cov_loupe/error_handler.rb +165 -0
- data/lib/cov_loupe/error_handler_factory.rb +31 -0
- data/lib/cov_loupe/errors.rb +191 -0
- data/lib/cov_loupe/formatters/source_formatter.rb +152 -0
- data/lib/cov_loupe/formatters.rb +51 -0
- data/lib/cov_loupe/mcp_server.rb +42 -0
- data/lib/cov_loupe/mode_detector.rb +56 -0
- data/lib/cov_loupe/model.rb +339 -0
- data/lib/cov_loupe/option_normalizers.rb +113 -0
- data/lib/cov_loupe/option_parser_builder.rb +147 -0
- data/lib/cov_loupe/option_parsers/env_options_parser.rb +48 -0
- data/lib/cov_loupe/option_parsers/error_helper.rb +110 -0
- data/lib/cov_loupe/path_relativizer.rb +64 -0
- data/lib/cov_loupe/predicate_evaluator.rb +72 -0
- data/lib/cov_loupe/presenters/base_coverage_presenter.rb +42 -0
- data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +14 -0
- data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +14 -0
- data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +14 -0
- data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +14 -0
- data/lib/cov_loupe/presenters/project_coverage_presenter.rb +50 -0
- data/lib/cov_loupe/presenters/project_totals_presenter.rb +27 -0
- data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +122 -0
- data/lib/cov_loupe/resolvers/resolver_factory.rb +28 -0
- data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +76 -0
- data/lib/cov_loupe/resultset_loader.rb +131 -0
- data/lib/cov_loupe/staleness_checker.rb +247 -0
- data/lib/cov_loupe/table_formatter.rb +64 -0
- data/lib/cov_loupe/tools/all_files_coverage_tool.rb +51 -0
- data/lib/cov_loupe/tools/coverage_detailed_tool.rb +35 -0
- data/lib/cov_loupe/tools/coverage_raw_tool.rb +34 -0
- data/lib/cov_loupe/tools/coverage_summary_tool.rb +34 -0
- data/lib/cov_loupe/tools/coverage_table_tool.rb +50 -0
- data/lib/cov_loupe/tools/coverage_totals_tool.rb +44 -0
- data/lib/cov_loupe/tools/help_tool.rb +115 -0
- data/lib/cov_loupe/tools/uncovered_lines_tool.rb +34 -0
- data/lib/cov_loupe/tools/validate_tool.rb +72 -0
- data/lib/cov_loupe/tools/version_tool.rb +32 -0
- data/lib/cov_loupe/util.rb +88 -0
- data/lib/cov_loupe/version.rb +5 -0
- data/lib/cov_loupe.rb +140 -0
- data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
- data/spec/TIMESTAMPS.md +48 -0
- data/spec/all_files_coverage_tool_spec.rb +53 -0
- data/spec/app_config_spec.rb +142 -0
- data/spec/base_tool_spec.rb +62 -0
- data/spec/cli/show_default_report_spec.rb +33 -0
- data/spec/cli_enumerated_options_spec.rb +90 -0
- data/spec/cli_error_spec.rb +184 -0
- data/spec/cli_format_spec.rb +123 -0
- data/spec/cli_json_options_spec.rb +50 -0
- data/spec/cli_source_spec.rb +44 -0
- data/spec/cli_spec.rb +192 -0
- data/spec/cli_table_spec.rb +28 -0
- data/spec/cli_usage_spec.rb +42 -0
- data/spec/commands/base_command_spec.rb +107 -0
- data/spec/commands/command_factory_spec.rb +76 -0
- data/spec/commands/detailed_command_spec.rb +34 -0
- data/spec/commands/list_command_spec.rb +28 -0
- data/spec/commands/raw_command_spec.rb +69 -0
- data/spec/commands/summary_command_spec.rb +34 -0
- data/spec/commands/totals_command_spec.rb +34 -0
- data/spec/commands/uncovered_command_spec.rb +55 -0
- data/spec/commands/validate_command_spec.rb +213 -0
- data/spec/commands/version_command_spec.rb +38 -0
- data/spec/constants_spec.rb +61 -0
- data/spec/cov_loupe/formatters/source_formatter_spec.rb +267 -0
- data/spec/cov_loupe/formatters_spec.rb +76 -0
- data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +79 -0
- data/spec/cov_loupe_model_spec.rb +454 -0
- data/spec/cov_loupe_module_spec.rb +37 -0
- data/spec/cov_loupe_opts_spec.rb +185 -0
- data/spec/coverage_reporter_spec.rb +102 -0
- data/spec/coverage_table_tool_spec.rb +59 -0
- data/spec/coverage_totals_tool_spec.rb +37 -0
- data/spec/error_handler_spec.rb +197 -0
- data/spec/error_mode_spec.rb +139 -0
- data/spec/errors_edge_cases_spec.rb +312 -0
- data/spec/errors_stale_spec.rb +83 -0
- data/spec/file_based_mcp_tools_spec.rb +99 -0
- data/spec/fixtures/project1/lib/bar.rb +5 -0
- data/spec/fixtures/project1/lib/foo.rb +6 -0
- data/spec/help_tool_spec.rb +26 -0
- data/spec/integration_spec.rb +789 -0
- data/spec/logging_fallback_spec.rb +128 -0
- data/spec/mcp_logging_spec.rb +44 -0
- data/spec/mcp_server_integration_spec.rb +23 -0
- data/spec/mcp_server_spec.rb +106 -0
- data/spec/mode_detector_spec.rb +153 -0
- data/spec/model_error_handling_spec.rb +269 -0
- data/spec/model_staleness_spec.rb +79 -0
- data/spec/option_normalizers_spec.rb +203 -0
- data/spec/option_parsers/env_options_parser_spec.rb +221 -0
- data/spec/option_parsers/error_helper_spec.rb +222 -0
- data/spec/path_relativizer_spec.rb +98 -0
- data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
- data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
- data/spec/presenters/project_coverage_presenter_spec.rb +87 -0
- data/spec/presenters/project_totals_presenter_spec.rb +144 -0
- data/spec/resolvers/coverage_line_resolver_spec.rb +282 -0
- data/spec/resolvers/resolver_factory_spec.rb +61 -0
- data/spec/resolvers/resultset_path_resolver_spec.rb +60 -0
- data/spec/resultset_loader_spec.rb +167 -0
- data/spec/shared_examples/README.md +115 -0
- data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
- data/spec/shared_examples/file_based_mcp_tools.rb +179 -0
- data/spec/shared_examples/formatted_command_examples.rb +64 -0
- data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
- data/spec/spec_helper.rb +127 -0
- data/spec/staleness_checker_spec.rb +374 -0
- data/spec/staleness_more_spec.rb +42 -0
- data/spec/support/cli_helpers.rb +22 -0
- data/spec/support/control_flow_helpers.rb +20 -0
- data/spec/support/fake_mcp.rb +40 -0
- data/spec/support/io_helpers.rb +29 -0
- data/spec/support/mcp_helpers.rb +35 -0
- data/spec/support/mcp_runner.rb +66 -0
- data/spec/support/mocking_helpers.rb +30 -0
- data/spec/table_format_spec.rb +70 -0
- data/spec/tools/validate_tool_spec.rb +132 -0
- data/spec/tools_error_handling_spec.rb +130 -0
- data/spec/util_spec.rb +154 -0
- data/spec/version_spec.rb +123 -0
- data/spec/version_tool_spec.rb +141 -0
- metadata +290 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# V2.0 Breaking Changes Guide
|
|
2
|
+
|
|
3
|
+
This document describes all breaking changes introduced in version 2.0.0 of cov-loupe. These changes improve consistency, clarity, and alignment with Ruby conventions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Command Line Interface Changes](#command-line-interface-changes)
|
|
10
|
+
- [Options Must Precede Subcommands](#options-must-precede-subcommands)
|
|
11
|
+
- [--stale Renamed to --staleness](#--stale-renamed-to---staleness)
|
|
12
|
+
- [--source-context Renamed to --context-lines](#--source-context-renamed-to---context-lines)
|
|
13
|
+
- [--source Now Requires Explicit Mode](#--source-now-requires-explicit-mode)
|
|
14
|
+
- [--json Replaced with --format](#--json-replaced-with---format)
|
|
15
|
+
- [Error Mode Values Changed](#error-mode-values-changed)
|
|
16
|
+
- [--success-predicate Replaced with validate Subcommand](#--success-predicate-replaced-with-validate-subcommand)
|
|
17
|
+
- [Default Sort Order Changed](#default-sort-order-changed)
|
|
18
|
+
- [MCP Tool Changes](#mcp-tool-changes)
|
|
19
|
+
- [stale Parameter Renamed to staleness](#stale-parameter-renamed-to-staleness)
|
|
20
|
+
- [Error Mode Values Changed](#error-mode-values-changed-1)
|
|
21
|
+
- [MCP Tool Arguments Use Symbols](#mcp-tool-arguments-use-symbols)
|
|
22
|
+
- [Ruby API Changes](#ruby-api-changes)
|
|
23
|
+
- [CLIConfig Renamed to AppConfig](#cliconfig-renamed-to-appconfig)
|
|
24
|
+
- [AppConfig Field Changes](#appconfig-field-changes)
|
|
25
|
+
- [Behavioral Changes](#behavioral-changes)
|
|
26
|
+
- [Context Lines Validation](#context-lines-validation)
|
|
27
|
+
- [Migration Guide](#migration-guide)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Command Line Interface Changes
|
|
32
|
+
|
|
33
|
+
### Options Must Precede Subcommands
|
|
34
|
+
|
|
35
|
+
**Change:** Global options must now appear *before* the subcommand, not after.
|
|
36
|
+
|
|
37
|
+
**Rationale:** This aligns with standard Unix command conventions (e.g., `git`, `docker`) and simplifies argument parsing.
|
|
38
|
+
|
|
39
|
+
**Before (v1.x):**
|
|
40
|
+
```bash
|
|
41
|
+
cov-loupe list --resultset coverage --format json
|
|
42
|
+
cov-loupe summary lib/foo.rb --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**After (v2.x):**
|
|
46
|
+
```bash
|
|
47
|
+
cov-loupe --resultset coverage --format json list
|
|
48
|
+
cov-loupe --format json summary lib/foo.rb
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Migration:** Move all global options (flags like `-r`, `-f`, `-S`, etc.) before the subcommand name.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
### --stale Renamed to --staleness
|
|
56
|
+
|
|
57
|
+
**Change:** The `--stale` option has been renamed to `--staleness`. The short form `-S` is preserved.
|
|
58
|
+
|
|
59
|
+
**Rationale:** Better describes what the option controls (staleness detection mode) and aligns with internal naming conventions.
|
|
60
|
+
|
|
61
|
+
**Before (v1.x):**
|
|
62
|
+
```bash
|
|
63
|
+
cov-loupe --stale error list
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**After (v2.x):**
|
|
67
|
+
```bash
|
|
68
|
+
cov-loupe --staleness error list
|
|
69
|
+
# OR use the short form:
|
|
70
|
+
cov-loupe -S error list
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Migration:** Replace `--stale` with `--staleness` (or continue using `-S`).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### --source-context Renamed to --context-lines
|
|
78
|
+
|
|
79
|
+
**Change:** The `--source-context` option has been renamed to `--context-lines`.
|
|
80
|
+
|
|
81
|
+
**Rationale:** More concise and clearer about what the option controls.
|
|
82
|
+
|
|
83
|
+
**Before (v1.x):**
|
|
84
|
+
```bash
|
|
85
|
+
cov-loupe --source uncovered --source-context 3 uncovered lib/foo.rb
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**After (v2.x):**
|
|
89
|
+
```bash
|
|
90
|
+
cov-loupe --source uncovered --context-lines 3 uncovered lib/foo.rb
|
|
91
|
+
# OR use the short form:
|
|
92
|
+
cov-loupe -s uncovered -c 3 uncovered lib/foo.rb
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Migration:** Replace `--source-context` with `--context-lines` (or use `-c`).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### --source Now Requires Explicit Mode
|
|
100
|
+
|
|
101
|
+
**Change:** The `--source` option now requires an explicit mode argument (`full` or `uncovered`).
|
|
102
|
+
|
|
103
|
+
**Rationale:** Eliminates ambiguity about what source display mode is being used.
|
|
104
|
+
|
|
105
|
+
**Before (v1.x):**
|
|
106
|
+
```bash
|
|
107
|
+
# Implied 'full' mode
|
|
108
|
+
cov-loupe --source summary lib/foo.rb
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**After (v2.x):**
|
|
112
|
+
```bash
|
|
113
|
+
# Must specify mode explicitly
|
|
114
|
+
cov-loupe --source full summary lib/foo.rb
|
|
115
|
+
# OR
|
|
116
|
+
cov-loupe --source uncovered summary lib/foo.rb
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Migration:** Add an explicit mode (`full` or `uncovered`) after `--source`.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### --json Replaced with --format
|
|
124
|
+
|
|
125
|
+
**Change:** The `--json` flag (and related `-j`, `-J`, `--pretty-json` flags) have been removed. Use `--format` instead.
|
|
126
|
+
|
|
127
|
+
**Rationale:** Supports multiple output formats beyond JSON (YAML, awesome_print, etc.) with a consistent interface.
|
|
128
|
+
|
|
129
|
+
**Before (v1.x):**
|
|
130
|
+
```bash
|
|
131
|
+
cov-loupe --json list
|
|
132
|
+
cov-loupe -j summary lib/foo.rb
|
|
133
|
+
cov-loupe --pretty-json list
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**After (v2.x):**
|
|
137
|
+
```bash
|
|
138
|
+
cov-loupe --format json list
|
|
139
|
+
cov-loupe -f j summary lib/foo.rb # Short form
|
|
140
|
+
cov-loupe --format pretty-json list
|
|
141
|
+
cov-loupe -f J list # Short form for pretty-json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Available formats:**
|
|
145
|
+
- `table` (default) - Human-readable table format
|
|
146
|
+
- `json` or `j` - Single-line JSON
|
|
147
|
+
- `pretty-json` or `J` - Pretty-printed JSON
|
|
148
|
+
- `yaml` or `y` - YAML format
|
|
149
|
+
- `awesome-print` or `ap` - Colored awesome_print format (requires `awesome_print` gem)
|
|
150
|
+
|
|
151
|
+
**Migration:** Replace `--json` with `--format json` (or `-f j`). Replace `--pretty-json` with `--format pretty-json` (or `-f J`).
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### Error Mode Values Changed
|
|
156
|
+
|
|
157
|
+
**Change:** Error mode enum values have been renamed for clarity:
|
|
158
|
+
- `on` → `log`
|
|
159
|
+
- `trace` → `debug`
|
|
160
|
+
|
|
161
|
+
The old values are **no longer supported**.
|
|
162
|
+
|
|
163
|
+
**Rationale:** More descriptive names that better communicate what each mode does.
|
|
164
|
+
|
|
165
|
+
**Before (v1.x):**
|
|
166
|
+
```bash
|
|
167
|
+
cov-loupe --error-mode on list
|
|
168
|
+
cov-loupe --error-mode trace list
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**After (v2.x):**
|
|
172
|
+
```bash
|
|
173
|
+
cov-loupe --error-mode log list
|
|
174
|
+
cov-loupe --error-mode debug list
|
|
175
|
+
# OR use short forms:
|
|
176
|
+
cov-loupe --error-mode l list
|
|
177
|
+
cov-loupe --error-mode d list
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Error modes:**
|
|
181
|
+
- `off` (or `o`) - Silent, no error logging
|
|
182
|
+
- `log` (or `l`) - Log errors to file (default)
|
|
183
|
+
- `debug` (or `d`) - Verbose logging with backtraces
|
|
184
|
+
|
|
185
|
+
**Migration:** Replace `--error-mode on` with `--error-mode log`. Replace `--error-mode trace` with `--error-mode debug`.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### --success-predicate Replaced with validate Subcommand
|
|
190
|
+
|
|
191
|
+
**Change:** The `--success-predicate` flag has been removed. Use the `validate` subcommand instead.
|
|
192
|
+
|
|
193
|
+
**Rationale:** Better fits the subcommand paradigm and provides a clearer interface for policy validation.
|
|
194
|
+
|
|
195
|
+
**Before (v1.x):**
|
|
196
|
+
```bash
|
|
197
|
+
cov-loupe --success-predicate policy.rb
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**After (v2.x):**
|
|
201
|
+
```bash
|
|
202
|
+
# File-based policy
|
|
203
|
+
cov-loupe validate policy.rb
|
|
204
|
+
|
|
205
|
+
# Inline policy (new feature)
|
|
206
|
+
cov-loupe validate -i '->(m) { m.all_files.all? { |f| f["percentage"] >= 80 } }'
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Migration:** Replace `--success-predicate FILE` with `validate FILE`.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### Default Sort Order Changed
|
|
214
|
+
|
|
215
|
+
**Change:** The default sort order for the `list` command changed from `ascending` to `descending`.
|
|
216
|
+
|
|
217
|
+
**Rationale:** Most users want to see best-covered files first, not worst-covered files first.
|
|
218
|
+
|
|
219
|
+
**Before (v1.x):**
|
|
220
|
+
```bash
|
|
221
|
+
# Shows worst coverage first by default
|
|
222
|
+
cov-loupe list
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**After (v2.x):**
|
|
226
|
+
```bash
|
|
227
|
+
# Shows best coverage first by default
|
|
228
|
+
cov-loupe list
|
|
229
|
+
|
|
230
|
+
# To get old behavior (worst first):
|
|
231
|
+
cov-loupe --sort-order ascending list
|
|
232
|
+
cov-loupe -o a list # Short form
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Migration:** If you relied on ascending order (worst coverage first), explicitly specify `--sort-order ascending` or `-o a`.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## MCP Tool Changes
|
|
240
|
+
|
|
241
|
+
### stale Parameter Renamed to staleness
|
|
242
|
+
|
|
243
|
+
**Change:** All MCP tools that accepted a `stale` parameter now use `staleness` instead.
|
|
244
|
+
|
|
245
|
+
**Rationale:** Aligns with the `CoverageModel` API and CLI option naming.
|
|
246
|
+
|
|
247
|
+
**Before (v1.x):**
|
|
248
|
+
```json
|
|
249
|
+
{
|
|
250
|
+
"jsonrpc": "2.0",
|
|
251
|
+
"method": "tools/call",
|
|
252
|
+
"params": {
|
|
253
|
+
"name": "coverage_summary_tool",
|
|
254
|
+
"arguments": {
|
|
255
|
+
"path": "lib/foo.rb",
|
|
256
|
+
"stale": "error"
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**After (v2.x):**
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"jsonrpc": "2.0",
|
|
266
|
+
"method": "tools/call",
|
|
267
|
+
"params": {
|
|
268
|
+
"name": "coverage_summary_tool",
|
|
269
|
+
"arguments": {
|
|
270
|
+
"path": "lib/foo.rb",
|
|
271
|
+
"staleness": "error"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Affected tools:** All file-based tools (`coverage_summary_tool`, `coverage_detailed_tool`, `coverage_raw_tool`, `uncovered_lines_tool`) and aggregate tools (`all_files_coverage_tool`, `coverage_totals_tool`).
|
|
278
|
+
|
|
279
|
+
**Migration:** Replace `"stale"` with `"staleness"` in all MCP tool calls.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### Error Mode Values Changed
|
|
284
|
+
|
|
285
|
+
**Change:** Error mode enum values changed from `['off', 'on', 'trace']` to `['off', 'log', 'debug']`.
|
|
286
|
+
|
|
287
|
+
**Rationale:** More descriptive names matching CLI changes.
|
|
288
|
+
|
|
289
|
+
**Before (v1.x):**
|
|
290
|
+
```json
|
|
291
|
+
{
|
|
292
|
+
"error_mode": "on"
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**After (v2.x):**
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"error_mode": "log"
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Migration:** Replace `"on"` with `"log"`, replace `"trace"` with `"debug"`.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### MCP Tool Arguments Use Symbols
|
|
308
|
+
|
|
309
|
+
**Change:** Internally, MCP tools now normalize enum arguments to symbols (`:off`, `:error`, `:log`, `:debug`) for consistency with the Ruby API.
|
|
310
|
+
|
|
311
|
+
**Impact:** This is mostly an internal change. MCP clients still send strings in JSON, but if you're using the tools programmatically in Ruby, be aware of the symbol usage.
|
|
312
|
+
|
|
313
|
+
**Migration:** No action needed for MCP clients. For Ruby API users, see [Ruby API Changes](#ruby-api-changes).
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Ruby API Changes
|
|
318
|
+
|
|
319
|
+
### CLIConfig Renamed to AppConfig
|
|
320
|
+
|
|
321
|
+
**Change:** The `CLIConfig` class has been renamed to `AppConfig`.
|
|
322
|
+
|
|
323
|
+
**Rationale:** The configuration is now used by both CLI and MCP modes, not just CLI.
|
|
324
|
+
|
|
325
|
+
**Before (v1.x):**
|
|
326
|
+
```ruby
|
|
327
|
+
require 'cov_loupe/cli_config'
|
|
328
|
+
config = CovLoupe::CLIConfig.new(root: '.', json: true)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**After (v2.x):**
|
|
332
|
+
```ruby
|
|
333
|
+
require 'cov_loupe/app_config'
|
|
334
|
+
config = CovLoupe::AppConfig.new(root: '.', format: :json)
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Migration:** Replace `CLIConfig` with `AppConfig` in your code. Update require statements from `'cov_loupe/cli_config'` to `'cov_loupe/app_config'`.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
### AppConfig Field Changes
|
|
342
|
+
|
|
343
|
+
**Change:** Several `AppConfig` fields have been renamed or changed:
|
|
344
|
+
|
|
345
|
+
| Old Field (v1.x) | New Field (v2.x) | Type Change |
|
|
346
|
+
|-----------------------|------------------|--------------------------------------|
|
|
347
|
+
| `json` | `format` | `Boolean` → `Symbol` (`:json`, `:table`, etc.) |
|
|
348
|
+
| `stale_mode` | `staleness` | Name change only |
|
|
349
|
+
| `success_predicate` | (removed) | Moved to `validate` subcommand |
|
|
350
|
+
| (new) | `show_version` | New field for `-v`/`--version` |
|
|
351
|
+
|
|
352
|
+
**Default value changes:**
|
|
353
|
+
- `sort_order`: Changed from `:ascending` to `:descending`
|
|
354
|
+
- `error_mode`: Changed from `:on` to `:log`
|
|
355
|
+
|
|
356
|
+
**Before (v1.x):**
|
|
357
|
+
```ruby
|
|
358
|
+
config = CovLoupe::CLIConfig.new(
|
|
359
|
+
json: true,
|
|
360
|
+
stale_mode: :error,
|
|
361
|
+
error_mode: :on,
|
|
362
|
+
sort_order: :ascending
|
|
363
|
+
)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**After (v2.x):**
|
|
367
|
+
```ruby
|
|
368
|
+
config = CovLoupe::AppConfig.new(
|
|
369
|
+
format: :json,
|
|
370
|
+
staleness: :error,
|
|
371
|
+
error_mode: :log,
|
|
372
|
+
sort_order: :descending # New default
|
|
373
|
+
)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Migration:** Update field names when constructing `AppConfig`. Note the new defaults.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Behavioral Changes
|
|
381
|
+
|
|
382
|
+
### Context Lines Validation
|
|
383
|
+
|
|
384
|
+
**Change:** The `--context-lines` option (formerly `--source-context`) now raises an `ArgumentError` if given a negative value. Previously, negative values were silently clamped to zero.
|
|
385
|
+
|
|
386
|
+
**Rationale:** Fail fast and provide clear feedback for invalid input.
|
|
387
|
+
|
|
388
|
+
**Before (v1.x):**
|
|
389
|
+
```bash
|
|
390
|
+
# Silently clamped to 0
|
|
391
|
+
cov-loupe --source-context -5 uncovered lib/foo.rb
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
**After (v2.x):**
|
|
395
|
+
```bash
|
|
396
|
+
# Raises ArgumentError
|
|
397
|
+
cov-loupe --context-lines -5 uncovered lib/foo.rb
|
|
398
|
+
# Error: Context lines must be non-negative (got: -5)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Migration:** Ensure `--context-lines` values are non-negative (>= 0).
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## Migration Guide
|
|
406
|
+
|
|
407
|
+
### Quick Checklist
|
|
408
|
+
|
|
409
|
+
- [ ] Move all global options before subcommands in CLI invocations
|
|
410
|
+
- [ ] Replace `--stale` with `--staleness` (or continue using `-S`)
|
|
411
|
+
- [ ] Replace `--source-context` with `--context-lines` (or use `-c`)
|
|
412
|
+
- [ ] Add explicit mode to `--source` (either `full` or `uncovered`)
|
|
413
|
+
- [ ] Replace `--json` with `--format json` (or `-f j`)
|
|
414
|
+
- [ ] Replace `--error-mode on` with `--error-mode log`
|
|
415
|
+
- [ ] Replace `--error-mode trace` with `--error-mode debug`
|
|
416
|
+
- [ ] Replace `--success-predicate FILE` with `validate FILE`
|
|
417
|
+
- [ ] Update MCP tool calls: rename `stale` to `staleness`
|
|
418
|
+
- [ ] Update MCP tool calls: replace error mode `"on"` with `"log"`, `"trace"` with `"debug"`
|
|
419
|
+
- [ ] Update Ruby code: rename `CLIConfig` to `AppConfig`
|
|
420
|
+
- [ ] Update Ruby code: rename `json` field to `format`, `stale_mode` to `staleness`
|
|
421
|
+
- [ ] Explicitly set `--sort-order ascending` if you need worst-coverage-first sorting
|
|
422
|
+
- [ ] Ensure `--context-lines` values are non-negative
|
|
423
|
+
|
|
424
|
+
### Script Migration Example
|
|
425
|
+
|
|
426
|
+
**Before (v1.x):**
|
|
427
|
+
```bash
|
|
428
|
+
#!/bin/bash
|
|
429
|
+
cov-loupe list --json --stale error --sort-order ascending
|
|
430
|
+
cov-loupe summary lib/foo.rb --json
|
|
431
|
+
cov-loupe uncovered lib/bar.rb --source=uncovered --source-context 3
|
|
432
|
+
cov-loupe --success-predicate policy.rb
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**After (v2.x):**
|
|
436
|
+
```bash
|
|
437
|
+
#!/bin/bash
|
|
438
|
+
cov-loupe --format json --staleness error --sort-order ascending list
|
|
439
|
+
cov-loupe --format json summary lib/foo.rb
|
|
440
|
+
cov-loupe --source uncovered --context-lines 3 uncovered lib/bar.rb
|
|
441
|
+
cov-loupe validate policy.rb
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Environment Variable Migration
|
|
445
|
+
|
|
446
|
+
**Before (v1.x):**
|
|
447
|
+
```bash
|
|
448
|
+
export COV_LOUPE_OPTS="--stale error --json"
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**After (v2.x):**
|
|
452
|
+
```bash
|
|
453
|
+
export COV_LOUPE_OPTS="--staleness error --format json"
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## Getting Help
|
|
459
|
+
|
|
460
|
+
If you encounter issues migrating to v2.0:
|
|
461
|
+
|
|
462
|
+
1. Check the [TROUBLESHOOTING.md](TROUBLESHOOTING.md) guide
|
|
463
|
+
2. Review the [CLI_USAGE.md](CLI_USAGE.md) for complete CLI reference
|
|
464
|
+
3. See [MCP_INTEGRATION.md](MCP_INTEGRATION.md) for MCP tool documentation
|
|
465
|
+
4. Open an issue at https://github.com/keithrbennett/cov-loupe/issues
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
**See also:**
|
|
470
|
+
- [RELEASE_NOTES.md](../../RELEASE_NOTES.md) - Full release notes with new features
|
|
471
|
+
- [CLI_USAGE.md](CLI_USAGE.md) - Complete CLI reference
|
|
472
|
+
- [MCP_INTEGRATION.md](MCP_INTEGRATION.md) - MCP tool reference
|
data/exe/cov-loupe
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Make it safe to run via symlink by resolving the real path
|
|
5
|
+
root = File.expand_path('..', File.realpath(__FILE__))
|
|
6
|
+
lib = File.join(root, 'lib')
|
|
7
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
8
|
+
|
|
9
|
+
# Fail fast with a helpful message if Ruby is too old for this gem
|
|
10
|
+
begin
|
|
11
|
+
require 'rubygems'
|
|
12
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.2')
|
|
13
|
+
$stderr.puts "cov-loupe requires Ruby >= 3.2 (current: #{RUBY_VERSION})."
|
|
14
|
+
$stderr.puts 'Please run with a supported Ruby version (e.g., via rbenv, rvm, asdf).'
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
rescue
|
|
18
|
+
# If anything goes wrong, let the app load and potentially fail with a more specific error.
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require 'cov_loupe'
|
|
22
|
+
|
|
23
|
+
CovLoupe.run(ARGV)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CovLoupe
|
|
4
|
+
# Configuration container for application options (used by both CLI and MCP modes)
|
|
5
|
+
# Uses Struct for simplicity and built-in functionality
|
|
6
|
+
AppConfig = Struct.new(
|
|
7
|
+
:root,
|
|
8
|
+
:resultset,
|
|
9
|
+
:format,
|
|
10
|
+
:sort_order,
|
|
11
|
+
:source_mode,
|
|
12
|
+
:source_context,
|
|
13
|
+
:color,
|
|
14
|
+
:error_mode,
|
|
15
|
+
:staleness,
|
|
16
|
+
:tracked_globs,
|
|
17
|
+
:log_file,
|
|
18
|
+
:show_version,
|
|
19
|
+
keyword_init: true
|
|
20
|
+
) do
|
|
21
|
+
# Set sensible defaults - ALL SYMBOLS FOR ENUMS
|
|
22
|
+
def initialize(
|
|
23
|
+
root: '.',
|
|
24
|
+
resultset: nil,
|
|
25
|
+
format: :table,
|
|
26
|
+
sort_order: :descending,
|
|
27
|
+
source_mode: nil,
|
|
28
|
+
source_context: 2,
|
|
29
|
+
color: $stdout.tty?,
|
|
30
|
+
error_mode: :log,
|
|
31
|
+
staleness: :off,
|
|
32
|
+
tracked_globs: nil,
|
|
33
|
+
log_file: nil,
|
|
34
|
+
show_version: false
|
|
35
|
+
)
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Convenience method for CoverageModel initialization
|
|
40
|
+
def model_options
|
|
41
|
+
{
|
|
42
|
+
root: root,
|
|
43
|
+
resultset: resultset,
|
|
44
|
+
staleness: staleness,
|
|
45
|
+
tracked_globs: tracked_globs
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Convenience method for SourceFormatter initialization
|
|
50
|
+
def formatter_options
|
|
51
|
+
{
|
|
52
|
+
color_enabled: color
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CovLoupe
|
|
4
|
+
# Encapsulates per-request configuration such as error handling and logging.
|
|
5
|
+
class AppContext
|
|
6
|
+
attr_reader :error_handler, :log_target, :mode
|
|
7
|
+
|
|
8
|
+
def initialize(error_handler:, log_target: nil, mode: :library)
|
|
9
|
+
@error_handler = error_handler
|
|
10
|
+
@log_target = log_target
|
|
11
|
+
@mode = mode
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def with_error_handler(handler)
|
|
15
|
+
self.class.new(error_handler: handler, log_target: log_target, mode: mode)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def with_log_target(target)
|
|
19
|
+
self.class.new(error_handler: error_handler, log_target: target, mode: mode)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mcp_mode? = mode == :mcp
|
|
23
|
+
def cli_mode? = mode == :cli
|
|
24
|
+
def library_mode? = mode == :library
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'mcp'
|
|
4
|
+
require 'json'
|
|
5
|
+
require_relative 'errors'
|
|
6
|
+
require_relative 'error_handler'
|
|
7
|
+
|
|
8
|
+
module CovLoupe
|
|
9
|
+
class BaseTool < ::MCP::Tool
|
|
10
|
+
COMMON_PROPERTIES = {
|
|
11
|
+
root: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
description: 'Project root used to resolve relative paths ' \
|
|
14
|
+
'(defaults to current workspace).',
|
|
15
|
+
default: '.'
|
|
16
|
+
},
|
|
17
|
+
resultset: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
description: 'Path to the SimpleCov .resultset.json file (absolute or relative to root).'
|
|
20
|
+
},
|
|
21
|
+
staleness: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
description: 'How to handle missing/outdated coverage data. ' \
|
|
24
|
+
"'off' skips checks; 'error' raises.",
|
|
25
|
+
enum: [:off, :error],
|
|
26
|
+
default: :off
|
|
27
|
+
},
|
|
28
|
+
error_mode: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: "Error handling mode: 'off' (silent), 'log' (log errors), " \
|
|
31
|
+
"'debug' (verbose with backtraces).",
|
|
32
|
+
enum: %w[off log debug],
|
|
33
|
+
default: 'log'
|
|
34
|
+
}
|
|
35
|
+
}.freeze
|
|
36
|
+
|
|
37
|
+
ERROR_MODE_PROPERTY = COMMON_PROPERTIES[:error_mode].freeze
|
|
38
|
+
|
|
39
|
+
TRACKED_GLOBS_PROPERTY = {
|
|
40
|
+
type: 'array',
|
|
41
|
+
description: 'Glob patterns for files that should exist in the coverage report' \
|
|
42
|
+
'(helps flag new files).',
|
|
43
|
+
items: { type: 'string' }
|
|
44
|
+
}.freeze
|
|
45
|
+
|
|
46
|
+
PATH_PROPERTY = {
|
|
47
|
+
type: 'string',
|
|
48
|
+
description: 'Repo-relative or absolute path to the file whose coverage data you need.',
|
|
49
|
+
examples: ['lib/cov_loupe/model.rb']
|
|
50
|
+
}.freeze
|
|
51
|
+
|
|
52
|
+
def self.coverage_schema(additional_properties: {}, required: [])
|
|
53
|
+
{
|
|
54
|
+
type: 'object',
|
|
55
|
+
additionalProperties: false,
|
|
56
|
+
properties: COMMON_PROPERTIES.merge(additional_properties),
|
|
57
|
+
required: required
|
|
58
|
+
}.freeze
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
FILE_INPUT_SCHEMA = coverage_schema(
|
|
62
|
+
additional_properties: { path: PATH_PROPERTY },
|
|
63
|
+
required: ['path']
|
|
64
|
+
)
|
|
65
|
+
def self.input_schema_def = FILE_INPUT_SCHEMA
|
|
66
|
+
|
|
67
|
+
# Wrap tool execution with consistent error handling.
|
|
68
|
+
# Yields to the block and rescues any error, delegating to handle_mcp_error.
|
|
69
|
+
# This eliminates duplicate rescue blocks across all tools.
|
|
70
|
+
def self.with_error_handling(tool_name, error_mode:)
|
|
71
|
+
yield
|
|
72
|
+
rescue => e
|
|
73
|
+
handle_mcp_error(e, tool_name, error_mode: error_mode)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Handle errors consistently across all MCP tools
|
|
77
|
+
# Returns an MCP::Tool::Response with appropriate error message
|
|
78
|
+
def self.handle_mcp_error(error, tool_name, error_mode: :log)
|
|
79
|
+
# Create error handler with the specified mode
|
|
80
|
+
error_handler = ErrorHandlerFactory.for_mcp_server(error_mode: error_mode.to_sym)
|
|
81
|
+
|
|
82
|
+
# Normalize to a CovLoupe::Error so we can handle/log uniformly
|
|
83
|
+
normalized = error.is_a?(CovLoupe::Error) \
|
|
84
|
+
? error : error_handler.convert_standard_error(error)
|
|
85
|
+
log_mcp_error(normalized, tool_name, error_handler)
|
|
86
|
+
::MCP::Tool::Response.new([{ 'type' => 'text', 'text' => "Error: #{normalized.user_friendly_message}" }])
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Respond with JSON as a resource to avoid clients mutating content types.
|
|
90
|
+
# The resource embeds the JSON string with a clear MIME type.
|
|
91
|
+
def self.respond_json(payload, name: 'data.json', pretty: false)
|
|
92
|
+
json = pretty ? JSON.pretty_generate(payload) : JSON.generate(payload)
|
|
93
|
+
::MCP::Tool::Response.new([{ 'type' => 'text', 'text' => json }])
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.log_mcp_error(error, tool_name, error_handler)
|
|
97
|
+
# Use the provided error handler for logging
|
|
98
|
+
error_handler.send(:log_error, error, tool_name)
|
|
99
|
+
end
|
|
100
|
+
private_class_method :log_mcp_error
|
|
101
|
+
end
|
|
102
|
+
end
|