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.
- checksums.yaml +4 -4
- data/AGENTS.md +230 -0
- data/CLAUDE.md +5 -0
- data/CODE_OF_CONDUCT.md +62 -0
- data/CONTRIBUTING.md +102 -0
- data/GEMINI.md +5 -0
- data/README.md +154 -51
- data/RELEASE_NOTES.md +452 -0
- data/dev/images/cov-loupe-icon-lores.png +0 -0
- data/dev/images/cov-loupe-icon-square.png +0 -0
- data/dev/images/cov-loupe-icon.png +0 -0
- data/dev/images/cov-loupe-logo.png +0 -0
- data/dev/prompts/README.md +74 -0
- data/dev/prompts/archive/architectural-review-and-actions-prompt.md +53 -0
- data/dev/prompts/archive/investigate-and-report-issues-prompt.md +33 -0
- data/dev/prompts/archive/produce-action-items-prompt.md +25 -0
- data/dev/prompts/guidelines/ai-code-evaluator-guidelines.md +337 -0
- data/dev/prompts/improve/refactor-test-suite.md +18 -0
- data/dev/prompts/improve/simplify-code-logic.md +133 -0
- data/dev/prompts/improve/update-documentation.md +21 -0
- data/dev/prompts/review/comprehensive-codebase-review.md +176 -0
- data/dev/prompts/review/identify-action-items.md +143 -0
- data/dev/prompts/review/verify-code-changes.md +54 -0
- data/dev/prompts/validate/create-screencast-outline.md +234 -0
- data/dev/prompts/validate/test-documentation-examples.md +180 -0
- data/docs/QUICKSTART.md +63 -0
- data/docs/assets/images/cov-loupe-logo-lores.png +0 -0
- data/docs/assets/images/cov-loupe-logo.png +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/stylesheets/branding.css +16 -0
- data/docs/assets/stylesheets/extra.css +15 -0
- data/docs/code_of_conduct.md +1 -0
- data/docs/contributing.md +1 -0
- data/docs/dev/ARCHITECTURE.md +56 -11
- data/docs/dev/DEVELOPMENT.md +116 -12
- data/docs/dev/FUTURE_ENHANCEMENTS.md +14 -0
- data/docs/dev/README.md +3 -2
- data/docs/dev/RELEASING.md +2 -0
- data/docs/dev/arch-decisions/README.md +10 -7
- data/docs/dev/arch-decisions/application-architecture.md +259 -0
- data/docs/dev/arch-decisions/coverage-data-quality.md +193 -0
- data/docs/dev/arch-decisions/output-character-mode.md +217 -0
- data/docs/dev/arch-decisions/path-resolution.md +90 -0
- data/docs/dev/arch-decisions/{004-x-arch-decision.md → policy-validation.md} +32 -28
- data/docs/dev/arch-decisions/{005-x-arch-decision.md → simplecov-integration.md} +47 -44
- data/docs/dev/presentations/cov-loupe-presentation.md +15 -13
- data/docs/examples/mcp-inputs.md +3 -0
- data/docs/examples/prompts.md +3 -0
- data/docs/examples/success_predicates.md +3 -0
- data/docs/fixtures/demo_project/.resultset.json +170 -0
- data/docs/fixtures/demo_project/README.md +6 -0
- data/docs/fixtures/demo_project/app/controllers/admin/audit_logs_controller.rb +19 -0
- data/docs/fixtures/demo_project/app/controllers/orders_controller.rb +26 -0
- data/docs/fixtures/demo_project/app/models/order.rb +20 -0
- data/docs/fixtures/demo_project/app/models/user.rb +19 -0
- data/docs/fixtures/demo_project/lib/api/client.rb +22 -0
- data/docs/fixtures/demo_project/lib/ops/jobs/cleanup_job.rb +16 -0
- data/docs/fixtures/demo_project/lib/ops/jobs/report_job.rb +17 -0
- data/docs/fixtures/demo_project/lib/payments/processor.rb +15 -0
- data/docs/fixtures/demo_project/lib/payments/refund_service.rb +15 -0
- data/docs/fixtures/demo_project/lib/payments/reporting/exporter.rb +16 -0
- data/docs/index.md +1 -0
- data/docs/license.md +3 -0
- data/docs/release_notes.md +3 -0
- data/docs/user/ADVANCED_USAGE.md +208 -115
- data/docs/user/CLI_FALLBACK_FOR_LLMS.md +2 -0
- data/docs/user/CLI_USAGE.md +276 -101
- data/docs/user/ERROR_HANDLING.md +4 -4
- data/docs/user/EXAMPLES.md +121 -128
- data/docs/user/INSTALLATION.md +9 -28
- data/docs/user/LIBRARY_API.md +227 -122
- data/docs/user/MCP_INTEGRATION.md +114 -203
- data/docs/user/README.md +5 -1
- data/docs/user/TROUBLESHOOTING.md +49 -27
- data/docs/user/installing-a-prelease-version-of-covloupe.md +43 -0
- data/docs/user/{V2-BREAKING-CHANGES.md → migrations/MIGRATING_TO_V2.md} +62 -72
- data/docs/user/migrations/MIGRATING_TO_V3.md +72 -0
- data/docs/user/migrations/MIGRATING_TO_V4.md +591 -0
- data/docs/user/migrations/README.md +22 -0
- data/docs/user/prompts/README.md +9 -0
- data/docs/user/prompts/non-web-coverage-analysis-prompt.md +103 -0
- data/docs/user/prompts/rails-coverage-analysis-prompt.md +94 -0
- data/docs/user/prompts/use-cli-not-mcp-prompt.md +53 -0
- data/examples/cli_demo.sh +77 -0
- data/examples/filter_and_table_demo-output.md +114 -0
- data/examples/filter_and_table_demo.rb +174 -0
- data/examples/fixtures/demo_project/coverage/.resultset.json +10 -0
- data/examples/mcp-inputs/README.md +66 -0
- data/examples/mcp-inputs/coverage_detailed.json +1 -0
- data/examples/mcp-inputs/coverage_raw.json +1 -0
- data/examples/mcp-inputs/coverage_summary.json +1 -0
- data/examples/mcp-inputs/list.json +1 -0
- data/examples/mcp-inputs/uncovered_lines.json +1 -0
- data/examples/prompts/README.md +27 -0
- data/examples/prompts/custom_resultset.txt +2 -0
- data/examples/prompts/detailed_with_source.txt +2 -0
- data/examples/prompts/list_lowest.txt +2 -0
- data/examples/prompts/summary.txt +2 -0
- data/examples/prompts/uncovered.txt +2 -0
- data/examples/success_predicates/README.md +198 -0
- data/examples/success_predicates/all_files_above_threshold_predicate.rb +21 -0
- data/examples/success_predicates/directory_specific_thresholds_predicate.rb +30 -0
- data/examples/success_predicates/project_coverage_minimum_predicate.rb +6 -0
- data/lib/cov_loupe/base_tool.rb +229 -20
- data/lib/cov_loupe/cli.rb +132 -23
- data/lib/cov_loupe/commands/base_command.rb +25 -6
- data/lib/cov_loupe/commands/command_factory.rb +0 -1
- data/lib/cov_loupe/commands/detailed_command.rb +10 -5
- data/lib/cov_loupe/commands/list_command.rb +2 -1
- data/lib/cov_loupe/commands/raw_command.rb +7 -5
- data/lib/cov_loupe/commands/summary_command.rb +12 -7
- data/lib/cov_loupe/commands/totals_command.rb +74 -10
- data/lib/cov_loupe/commands/uncovered_command.rb +7 -5
- data/lib/cov_loupe/commands/validate_command.rb +11 -3
- data/lib/cov_loupe/commands/version_command.rb +6 -4
- data/lib/cov_loupe/{app_config.rb → config/app_config.rb} +13 -5
- data/lib/cov_loupe/config/app_context.rb +43 -0
- data/lib/cov_loupe/config/boolean_type.rb +91 -0
- data/lib/cov_loupe/config/logger.rb +92 -0
- data/lib/cov_loupe/{option_normalizers.rb → config/option_normalizers.rb} +55 -24
- data/lib/cov_loupe/{option_parser_builder.rb → config/option_parser_builder.rb} +46 -24
- data/lib/cov_loupe/coverage/coverage_calculator.rb +53 -0
- data/lib/cov_loupe/coverage/coverage_reporter.rb +63 -0
- data/lib/cov_loupe/coverage/coverage_table_formatter.rb +133 -0
- data/lib/cov_loupe/{error_handler.rb → errors/error_handler.rb} +21 -33
- data/lib/cov_loupe/{errors.rb → errors/errors.rb} +48 -71
- data/lib/cov_loupe/formatters/formatters.rb +75 -0
- data/lib/cov_loupe/formatters/source_formatter.rb +18 -7
- data/lib/cov_loupe/formatters/table_formatter.rb +80 -0
- data/lib/cov_loupe/loaders/all.rb +15 -0
- data/lib/cov_loupe/loaders/all_cli.rb +10 -0
- data/lib/cov_loupe/loaders/all_mcp.rb +23 -0
- data/lib/cov_loupe/loaders/resultset_loader.rb +147 -0
- data/lib/cov_loupe/mcp_server.rb +3 -2
- data/lib/cov_loupe/model/model.rb +520 -0
- data/lib/cov_loupe/model/model_data.rb +13 -0
- data/lib/cov_loupe/model/model_data_cache.rb +116 -0
- data/lib/cov_loupe/option_parsers/env_options_parser.rb +17 -6
- data/lib/cov_loupe/option_parsers/error_helper.rb +16 -10
- data/lib/cov_loupe/output_chars.rb +192 -0
- data/lib/cov_loupe/paths/glob_utils.rb +100 -0
- data/lib/cov_loupe/{path_relativizer.rb → paths/path_relativizer.rb} +5 -13
- data/lib/cov_loupe/paths/path_utils.rb +265 -0
- data/lib/cov_loupe/paths/volume_case_sensitivity.rb +173 -0
- data/lib/cov_loupe/presenters/base_coverage_presenter.rb +9 -13
- data/lib/cov_loupe/presenters/coverage_payload_presenter.rb +21 -0
- data/lib/cov_loupe/presenters/payload_caching.rb +23 -0
- data/lib/cov_loupe/presenters/project_coverage_presenter.rb +73 -21
- data/lib/cov_loupe/presenters/project_totals_presenter.rb +16 -10
- data/lib/cov_loupe/repositories/coverage_repository.rb +149 -0
- data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +90 -76
- data/lib/cov_loupe/resolvers/{resolver_factory.rb → resolver_helpers.rb} +6 -5
- data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +40 -12
- data/lib/cov_loupe/scripts/command_execution.rb +113 -0
- data/lib/cov_loupe/scripts/latest_ci_status.rb +97 -0
- data/lib/cov_loupe/scripts/pre_release_check.rb +164 -0
- data/lib/cov_loupe/scripts/setup_doc_server.rb +23 -0
- data/lib/cov_loupe/scripts/start_doc_server.rb +24 -0
- data/lib/cov_loupe/staleness/stale_status.rb +23 -0
- data/lib/cov_loupe/staleness/staleness_checker.rb +328 -0
- data/lib/cov_loupe/staleness/staleness_message_formatter.rb +91 -0
- data/lib/cov_loupe/tools/coverage_detailed_tool.rb +14 -15
- data/lib/cov_loupe/tools/coverage_raw_tool.rb +14 -14
- data/lib/cov_loupe/tools/coverage_summary_tool.rb +16 -16
- data/lib/cov_loupe/tools/coverage_table_tool.rb +139 -21
- data/lib/cov_loupe/tools/coverage_totals_tool.rb +31 -13
- data/lib/cov_loupe/tools/help_tool.rb +16 -20
- data/lib/cov_loupe/tools/list_tool.rb +65 -0
- data/lib/cov_loupe/tools/uncovered_lines_tool.rb +14 -14
- data/lib/cov_loupe/tools/validate_tool.rb +18 -24
- data/lib/cov_loupe/tools/version_tool.rb +8 -3
- data/lib/cov_loupe/version.rb +1 -1
- data/lib/cov_loupe.rb +83 -55
- metadata +184 -154
- data/docs/dev/BRANCH_ONLY_COVERAGE.md +0 -158
- data/docs/dev/arch-decisions/001-x-arch-decision.md +0 -95
- data/docs/dev/arch-decisions/002-x-arch-decision.md +0 -159
- data/docs/dev/arch-decisions/003-x-arch-decision.md +0 -165
- data/lib/cov_loupe/app_context.rb +0 -26
- data/lib/cov_loupe/constants.rb +0 -22
- data/lib/cov_loupe/coverage_reporter.rb +0 -31
- data/lib/cov_loupe/formatters.rb +0 -51
- data/lib/cov_loupe/mode_detector.rb +0 -56
- data/lib/cov_loupe/model.rb +0 -339
- data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +0 -14
- data/lib/cov_loupe/resultset_loader.rb +0 -131
- data/lib/cov_loupe/staleness_checker.rb +0 -247
- data/lib/cov_loupe/table_formatter.rb +0 -64
- data/lib/cov_loupe/tools/all_files_coverage_tool.rb +0 -51
- data/lib/cov_loupe/util.rb +0 -88
- data/spec/MCP_INTEGRATION_TESTS_README.md +0 -111
- data/spec/TIMESTAMPS.md +0 -48
- data/spec/all_files_coverage_tool_spec.rb +0 -53
- data/spec/app_config_spec.rb +0 -142
- data/spec/base_tool_spec.rb +0 -62
- data/spec/cli/show_default_report_spec.rb +0 -33
- data/spec/cli_enumerated_options_spec.rb +0 -90
- data/spec/cli_error_spec.rb +0 -184
- data/spec/cli_format_spec.rb +0 -123
- data/spec/cli_json_options_spec.rb +0 -50
- data/spec/cli_source_spec.rb +0 -44
- data/spec/cli_spec.rb +0 -192
- data/spec/cli_table_spec.rb +0 -28
- data/spec/cli_usage_spec.rb +0 -42
- data/spec/commands/base_command_spec.rb +0 -107
- data/spec/commands/command_factory_spec.rb +0 -76
- data/spec/commands/detailed_command_spec.rb +0 -34
- data/spec/commands/list_command_spec.rb +0 -28
- data/spec/commands/raw_command_spec.rb +0 -69
- data/spec/commands/summary_command_spec.rb +0 -34
- data/spec/commands/totals_command_spec.rb +0 -34
- data/spec/commands/uncovered_command_spec.rb +0 -55
- data/spec/commands/validate_command_spec.rb +0 -213
- data/spec/commands/version_command_spec.rb +0 -38
- data/spec/constants_spec.rb +0 -61
- data/spec/cov_loupe/formatters/source_formatter_spec.rb +0 -267
- data/spec/cov_loupe/formatters_spec.rb +0 -76
- data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +0 -79
- data/spec/cov_loupe_model_spec.rb +0 -454
- data/spec/cov_loupe_module_spec.rb +0 -37
- data/spec/cov_loupe_opts_spec.rb +0 -185
- data/spec/coverage_reporter_spec.rb +0 -102
- data/spec/coverage_table_tool_spec.rb +0 -59
- data/spec/coverage_totals_tool_spec.rb +0 -37
- data/spec/error_handler_spec.rb +0 -197
- data/spec/error_mode_spec.rb +0 -139
- data/spec/errors_edge_cases_spec.rb +0 -312
- data/spec/errors_stale_spec.rb +0 -83
- data/spec/file_based_mcp_tools_spec.rb +0 -99
- data/spec/help_tool_spec.rb +0 -26
- data/spec/integration_spec.rb +0 -789
- data/spec/logging_fallback_spec.rb +0 -128
- data/spec/mcp_logging_spec.rb +0 -44
- data/spec/mcp_server_integration_spec.rb +0 -23
- data/spec/mcp_server_spec.rb +0 -106
- data/spec/mode_detector_spec.rb +0 -153
- data/spec/model_error_handling_spec.rb +0 -269
- data/spec/model_staleness_spec.rb +0 -79
- data/spec/option_normalizers_spec.rb +0 -203
- data/spec/option_parsers/env_options_parser_spec.rb +0 -221
- data/spec/option_parsers/error_helper_spec.rb +0 -222
- data/spec/path_relativizer_spec.rb +0 -98
- data/spec/presenters/coverage_detailed_presenter_spec.rb +0 -19
- data/spec/presenters/coverage_raw_presenter_spec.rb +0 -15
- data/spec/presenters/coverage_summary_presenter_spec.rb +0 -15
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +0 -16
- data/spec/presenters/project_coverage_presenter_spec.rb +0 -87
- data/spec/presenters/project_totals_presenter_spec.rb +0 -144
- data/spec/resolvers/coverage_line_resolver_spec.rb +0 -282
- data/spec/resolvers/resolver_factory_spec.rb +0 -61
- data/spec/resolvers/resultset_path_resolver_spec.rb +0 -60
- data/spec/resultset_loader_spec.rb +0 -167
- data/spec/shared_examples/README.md +0 -115
- data/spec/shared_examples/coverage_presenter_examples.rb +0 -66
- data/spec/shared_examples/file_based_mcp_tools.rb +0 -179
- data/spec/shared_examples/formatted_command_examples.rb +0 -64
- data/spec/shared_examples/mcp_tool_text_json_response.rb +0 -16
- data/spec/spec_helper.rb +0 -127
- data/spec/staleness_checker_spec.rb +0 -374
- data/spec/staleness_more_spec.rb +0 -42
- data/spec/support/cli_helpers.rb +0 -22
- data/spec/support/control_flow_helpers.rb +0 -20
- data/spec/support/fake_mcp.rb +0 -40
- data/spec/support/io_helpers.rb +0 -29
- data/spec/support/mcp_helpers.rb +0 -35
- data/spec/support/mcp_runner.rb +0 -66
- data/spec/support/mocking_helpers.rb +0 -30
- data/spec/table_format_spec.rb +0 -70
- data/spec/tools/validate_tool_spec.rb +0 -132
- data/spec/tools_error_handling_spec.rb +0 -130
- data/spec/util_spec.rb +0 -154
- data/spec/version_spec.rb +0 -123
- data/spec/version_tool_spec.rb +0 -141
- /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/bar.rb +0 -0
- /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/foo.rb +0 -0
- /data/lib/cov_loupe/{config_parser.rb → config/config_parser.rb} +0 -0
- /data/lib/cov_loupe/{predicate_evaluator.rb → config/predicate_evaluator.rb} +0 -0
- /data/lib/cov_loupe/{error_handler_factory.rb → errors/error_handler_factory.rb} +0 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
# V4.0 Breaking Changes Guide
|
|
2
|
+
|
|
3
|
+
[Back to main README](../../index.md)
|
|
4
|
+
|
|
5
|
+
This document describes the breaking changes introduced in version 4.0.0. These changes affect the CLI flags for mode selection and staleness checks, as well as a method rename in the Ruby API.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [CLI Changes](#cli-changes)
|
|
10
|
+
- [MCP Mode Now Requires Explicit `-m/--mode mcp` Flag](#mcp-mode-now-requires-explicit-m-mode-mcp-flag)
|
|
11
|
+
- [Unified Stale Coverage Enforcement](#unified-stale-coverage-enforcement)
|
|
12
|
+
- [`--raise-on-stale` / `-S` - Explicit Value Required](#raise-on-stale-s-explicit-value-required)
|
|
13
|
+
- [`--color` / `-C` - Explicit Value Required](#color-c-explicit-value-required)
|
|
14
|
+
- [`--tracked-globs` Default Changed to Empty Array](#tracked-globs-default-changed-to-empty-array)
|
|
15
|
+
- [Ruby API Changes](#ruby-api-changes)
|
|
16
|
+
- [CoverageLineResolver Now Requires `root:` and `volume_case_sensitive:`](#coveragelineresolver-now-requires-root-and-volume_case_sensitive)
|
|
17
|
+
- [Method Renamed](#method-renamed)
|
|
18
|
+
- [Return Type Changed: `list` Now Returns a Hash](#return-type-changed-list-now-returns-a-hash)
|
|
19
|
+
- [Return Type Changed: `project_totals` Schema Updated](#return-type-changed-project_totals-schema-updated)
|
|
20
|
+
- [Logger Initialization Changed](#logger-initialization-changed)
|
|
21
|
+
- [Deleted Files Now Raise `FileNotFoundError`](#deleted-files-now-raise-filenotfounderror)
|
|
22
|
+
- [Staleness Indicators Changed from Strings to Symbols](#staleness-indicators-changed-from-strings-to-symbols)
|
|
23
|
+
- [Removed Branch-Only Coverage Support](#removed-branch-only-coverage-support)
|
|
24
|
+
- [Getting Help](#getting-help)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## CLI Changes
|
|
29
|
+
|
|
30
|
+
### ⚠️ MCP Mode Now Requires Explicit `-m/--mode mcp` Flag
|
|
31
|
+
|
|
32
|
+
**BREAKING**: Automatic mode detection has been removed.
|
|
33
|
+
The `-m/--mode mcp` flag is now **required** to run cov-loupe as an MCP server.
|
|
34
|
+
|
|
35
|
+
#### Previous Behavior (v3.x)
|
|
36
|
+
- cov-loupe automatically detected MCP mode based on TTY/stdin status
|
|
37
|
+
- `--force-mode` could override detection (values: `cli`, `mcp`, `auto`)
|
|
38
|
+
|
|
39
|
+
#### New Behavior (v4.x)
|
|
40
|
+
- **No automatic detection** - mode defaults to `cli`
|
|
41
|
+
- `-m mcp` or `--mode mcp` is **required** for MCP server mode
|
|
42
|
+
- Accepted values: `cli` (default) or `mcp`
|
|
43
|
+
|
|
44
|
+
#### Migration for MCP Users
|
|
45
|
+
|
|
46
|
+
**If you use cov-loupe as an MCP server, you MUST update your configuration:**
|
|
47
|
+
|
|
48
|
+
1. **Remove the old entry** (see [MCP Integration Guide - Setup by Client](../MCP_INTEGRATION.md#setup-by-client)
|
|
49
|
+
for removal commands with proper `--scope` options)
|
|
50
|
+
2. **Add the new entry with `-m mcp` flag:**
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
# Claude Code
|
|
54
|
+
claude mcp add cov-loupe cov-loupe -- -m mcp
|
|
55
|
+
|
|
56
|
+
# Codex
|
|
57
|
+
codex mcp add cov-loupe cov-loupe -m mcp
|
|
58
|
+
|
|
59
|
+
# Gemini
|
|
60
|
+
gemini mcp add cov-loupe cov-loupe -- -m mcp
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Without `-m mcp` or `--mode mcp`, the server will run in CLI mode and hang waiting for subcommands.**
|
|
64
|
+
|
|
65
|
+
#### Migration for CLI Users
|
|
66
|
+
|
|
67
|
+
CLI users are unaffected. The default mode is `cli`, so no changes are needed. However:
|
|
68
|
+
- `--force-cli` removed → use `-m cli` or `--mode cli` if you need to be explicit (rare)
|
|
69
|
+
- `--force-mode` removed → use `-m/--mode` instead
|
|
70
|
+
|
|
71
|
+
### Unified Stale Coverage Enforcement
|
|
72
|
+
|
|
73
|
+
The staleness checking logic has been unified into a single flag that raises an error if *any* staleness is detected.
|
|
74
|
+
|
|
75
|
+
* **Old**: `--staleness` / `check_stale` (inconsistent behavior)
|
|
76
|
+
* **New**: `--raise-on-stale` (boolean)
|
|
77
|
+
|
|
78
|
+
#### Behavior
|
|
79
|
+
* **`--raise-on-stale true` (or `raise_on_stale: true`)**: The command will exit with an error code if any file in the result set is stale or if the project totals are stale.
|
|
80
|
+
* **Default (false)**: Staleness is reported in the output (e.g., status `M`, `T`, `L`), but the command returns success (unless other errors occur).
|
|
81
|
+
|
|
82
|
+
#### Migration
|
|
83
|
+
* If you relied on previous flags to enforce staleness checks, switch to `--raise-on-stale true` or `-S true`.
|
|
84
|
+
|
|
85
|
+
**IMPORTANT:** As of v4.0.0, boolean flags now require explicit values for consistency.
|
|
86
|
+
|
|
87
|
+
### `--raise-on-stale` / `-S` - Explicit Value Required {#raise-on-stale-s-explicit-value-required}
|
|
88
|
+
* **Old (no longer works)**: `--raise-on-stale`, `-S`
|
|
89
|
+
* **New (required)**: `--raise-on-stale true`, `-S true`, `--raise-on-stale=yes`, etc.
|
|
90
|
+
|
|
91
|
+
### `--color` / `-C` - Explicit Value Required {#color-c-explicit-value-required}
|
|
92
|
+
* **Old (no longer works)**: `--color`, `-C`
|
|
93
|
+
* **New (required)**: `--color true`, `-C true`, `--color=on`, etc.
|
|
94
|
+
|
|
95
|
+
These changes improve consistency between short and long flag forms and eliminate ambiguous behavior where long-form bare flags would fail but short-form bare flags would succeed.
|
|
96
|
+
|
|
97
|
+
### ⚠️ --tracked-globs Default Changed to Empty Array {#tracked-globs-default-changed-to-empty-array}
|
|
98
|
+
|
|
99
|
+
**BREAKING**: The `--tracked-globs` CLI option now defaults to `[]` (empty) instead of `lib/**/*.rb,app/**/*.rb,src/**/*.rb`. The Ruby API (`CoverageModel`) now also defaults `tracked_globs:` to `[]` (previously `nil`, which behaved the same).
|
|
100
|
+
|
|
101
|
+
This affects:
|
|
102
|
+
- **CLI**: `cov-loupe list` (without `--tracked-globs`)
|
|
103
|
+
- **Ruby API**: `CoverageModel.new` (for consistency, though behavior is unchanged)
|
|
104
|
+
|
|
105
|
+
#### Previous Behavior (v4.x early versions)
|
|
106
|
+
- `--tracked-globs` CLI option defaulted to `lib/**/*.rb,app/**/*.rb,src/**/*.rb`
|
|
107
|
+
- Files outside these patterns were silently excluded from CLI output
|
|
108
|
+
- `missing_tracked_files` (in `list`) included any tracked files not in coverage
|
|
109
|
+
|
|
110
|
+
#### New Behavior (v4.x current)
|
|
111
|
+
- `--tracked-globs` defaults to `[]` (empty)
|
|
112
|
+
- Shows all files in the resultset without filtering
|
|
113
|
+
- No files are flagged as missing unless you explicitly set globs
|
|
114
|
+
|
|
115
|
+
#### Rationale
|
|
116
|
+
|
|
117
|
+
The previous default caused three problems:
|
|
118
|
+
1. **Silent exclusions**: Coverage results for files not matching the default patterns (e.g., `config/`, custom directories) were hidden
|
|
119
|
+
2. **False positives**: Files like migrations, bin scripts, etc. were incorrectly flagged as "missing"
|
|
120
|
+
3. **Wrong assumptions**: Not all projects use `lib/` and `app/` - some use `src/`, others have custom structures
|
|
121
|
+
|
|
122
|
+
The new default shows all coverage data transparently without making assumptions about your project structure.
|
|
123
|
+
|
|
124
|
+
#### Migration Steps
|
|
125
|
+
|
|
126
|
+
**For CLI usage** (if you want the old filtering behavior with `lib/**/*.rb,app/**/*.rb,src/**/*.rb`):
|
|
127
|
+
|
|
128
|
+
Set `COV_LOUPE_OPTS` to match your SimpleCov `track_files` configuration:
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
# In spec_helper.rb or similar
|
|
132
|
+
SimpleCov.start do
|
|
133
|
+
add_filter '/spec/'
|
|
134
|
+
track_files 'lib/**/*.rb'
|
|
135
|
+
track_files 'app/**/*.rb'
|
|
136
|
+
end
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
# In your shell config (.bashrc, .zshrc, etc.)
|
|
141
|
+
export COV_LOUPE_OPTS="--tracked-globs lib/**/*.rb,app/**/*.rb"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**For Ruby API usage**:
|
|
145
|
+
|
|
146
|
+
No functional changes needed, but the default signature has changed for consistency. The Ruby API now defaults `tracked_globs: []` (previously `nil`). Both behave identically, so existing code works unchanged:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
# Default behavior (behavior unchanged, signature updated for consistency)
|
|
150
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
151
|
+
result = model.list # tracked_globs: [] → no filtering
|
|
152
|
+
|
|
153
|
+
# Explicit globs for filtering and tracking
|
|
154
|
+
model = CovLoupe::CoverageModel.new(
|
|
155
|
+
root: '.',
|
|
156
|
+
tracked_globs: ['lib/**/*.rb', 'app/**/*.rb']
|
|
157
|
+
)
|
|
158
|
+
result = model.list # Uses explicit globs
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**If you're fine with seeing all files in the resultset (and _only_ files in the resultset)** (no action needed for CLI or Ruby API):
|
|
162
|
+
- The new default shows all files that have coverage data
|
|
163
|
+
- No filtering applied, but also no detection of files lacking coverage data
|
|
164
|
+
|
|
165
|
+
#### Important Note
|
|
166
|
+
|
|
167
|
+
**Files lacking any coverage at all** (not loaded during tests) will not appear in the resultset and therefore won't be visible with the default empty array. To detect such files, you must set `--tracked-globs` to match the files you expect to have coverage.
|
|
168
|
+
|
|
169
|
+
[↑ Back to top](#table-of-contents)
|
|
170
|
+
|
|
171
|
+
## Ruby API Changes
|
|
172
|
+
|
|
173
|
+
### CoverageLineResolver Now Requires `root:` and `volume_case_sensitive:`
|
|
174
|
+
|
|
175
|
+
**Breaking Change**: `CovLoupe::Resolvers::CoverageLineResolver` now requires `root:` and `volume_case_sensitive:` keyword arguments, and `CovLoupe::Resolvers::ResolverHelpers.lookup_lines` / `create_coverage_resolver` now require these parameters as well.
|
|
176
|
+
|
|
177
|
+
#### Migration
|
|
178
|
+
```ruby
|
|
179
|
+
# Old
|
|
180
|
+
resolver = CovLoupe::Resolvers::CoverageLineResolver.new(cov_data)
|
|
181
|
+
lines = CovLoupe::Resolvers::ResolverHelpers.lookup_lines(cov_data, abs_path)
|
|
182
|
+
|
|
183
|
+
# New
|
|
184
|
+
root = '/path/to/project'
|
|
185
|
+
volume_case_sensitive = CovLoupe::PathUtils.volume_case_sensitive?(root)
|
|
186
|
+
resolver = CovLoupe::Resolvers::CoverageLineResolver.new(cov_data, root: root, volume_case_sensitive: volume_case_sensitive)
|
|
187
|
+
lines = CovLoupe::Resolvers::ResolverHelpers.lookup_lines(cov_data, abs_path, root: root, volume_case_sensitive: volume_case_sensitive)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Note**: If you're using `CoverageModel` (recommended), this is handled automatically - the model detects volume case-sensitivity during initialization based on the project root and passes it to resolvers internally.
|
|
191
|
+
|
|
192
|
+
### Method Renamed
|
|
193
|
+
|
|
194
|
+
* **Old**: `CoverageModel#all_files_coverage`
|
|
195
|
+
* **New**: `CoverageModel#list`
|
|
196
|
+
|
|
197
|
+
### Return Type Changed: `list` Now Returns a Hash
|
|
198
|
+
|
|
199
|
+
**Breaking Change**: `CoverageModel#list` now returns a **hash** containing comprehensive staleness information instead of just an array of file data.
|
|
200
|
+
|
|
201
|
+
#### Old Behavior (v3.x)
|
|
202
|
+
```ruby
|
|
203
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
204
|
+
files = model.list # Returns array directly
|
|
205
|
+
|
|
206
|
+
# Filter and use the array
|
|
207
|
+
low_coverage = files.select { |f| f['percentage'] < 80 }
|
|
208
|
+
model.format_table(files)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### New Behavior (v4.x)
|
|
212
|
+
```ruby
|
|
213
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
214
|
+
result = model.list # Returns hash with multiple keys
|
|
215
|
+
|
|
216
|
+
# Access the files array
|
|
217
|
+
files = result['files']
|
|
218
|
+
|
|
219
|
+
# Filter and use the array
|
|
220
|
+
low_coverage = files.select { |f| f['percentage'] < 80 }
|
|
221
|
+
model.format_table(files)
|
|
222
|
+
|
|
223
|
+
# Access new staleness information
|
|
224
|
+
result['skipped_files'] # Files that raised errors during processing
|
|
225
|
+
result['missing_tracked_files'] # Files from tracked_globs not in coverage
|
|
226
|
+
result['newer_files'] # Files modified after coverage was generated
|
|
227
|
+
result['deleted_files'] # Files in coverage that no longer exist
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Migration Steps
|
|
231
|
+
|
|
232
|
+
**Option 1: Quick Fix (Extract files array)**
|
|
233
|
+
```ruby
|
|
234
|
+
# Old
|
|
235
|
+
files = model.list
|
|
236
|
+
|
|
237
|
+
# New
|
|
238
|
+
files = model.list['files']
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Option 2: Leverage New Staleness Data**
|
|
242
|
+
```ruby
|
|
243
|
+
result = model.list
|
|
244
|
+
|
|
245
|
+
# Use the files array as before
|
|
246
|
+
files = result['files']
|
|
247
|
+
low_coverage = files.select { |f| f['percentage'] < 80 }
|
|
248
|
+
|
|
249
|
+
# Now you can also:
|
|
250
|
+
if result['skipped_files'].any?
|
|
251
|
+
warn "Warning: #{result['skipped_files'].size} files were skipped due to errors"
|
|
252
|
+
result['skipped_files'].each do |skip|
|
|
253
|
+
warn " #{skip['file']}: #{skip['error']}"
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
if result['newer_files'].any?
|
|
258
|
+
warn "Warning: #{result['newer_files'].size} files are newer than coverage data"
|
|
259
|
+
end
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Impact on `format_table`
|
|
263
|
+
|
|
264
|
+
The `format_table` method still accepts an array of file hashes (not the full hash from `list`):
|
|
265
|
+
|
|
266
|
+
```ruby
|
|
267
|
+
# Correct
|
|
268
|
+
files = model.list['files']
|
|
269
|
+
table = model.format_table(files)
|
|
270
|
+
|
|
271
|
+
# Also correct (passing nil gets all files)
|
|
272
|
+
table = model.format_table(nil)
|
|
273
|
+
|
|
274
|
+
# Incorrect - do not pass the full hash
|
|
275
|
+
result = model.list
|
|
276
|
+
table = model.format_table(result) # This will fail
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Return Type Changed: `project_totals` Schema Updated
|
|
280
|
+
|
|
281
|
+
**Breaking Change**: `CoverageModel#project_totals` now returns a structured hash with
|
|
282
|
+
explicit `lines`, `tracking`, and `files` sections. The top-level `percentage` and
|
|
283
|
+
`excluded_files` fields were removed.
|
|
284
|
+
|
|
285
|
+
#### Old Behavior (v3.x)
|
|
286
|
+
```ruby
|
|
287
|
+
totals = model.project_totals
|
|
288
|
+
# => {
|
|
289
|
+
# "lines" => { "total" => 123, "covered" => 100, "uncovered" => 23 },
|
|
290
|
+
# "percentage" => 81.3,
|
|
291
|
+
# "files" => { "total" => 4, "ok" => 4, "stale" => 0 },
|
|
292
|
+
# "excluded_files" => { ... }
|
|
293
|
+
# }
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### New Behavior (v4.x)
|
|
297
|
+
```ruby
|
|
298
|
+
totals = model.project_totals
|
|
299
|
+
# => {
|
|
300
|
+
# "lines" => { "total" => 123, "covered" => 100, "uncovered" => 23, "percent_covered" => 81.3 },
|
|
301
|
+
# "tracking" => { "enabled" => true, "globs" => ["lib/**/*.rb"] },
|
|
302
|
+
# "files" => {
|
|
303
|
+
# "total" => 4,
|
|
304
|
+
# "with_coverage" => { "total" => 4, "ok" => 4, "stale" => { "total" => 0, "by_type" => { ... } } }
|
|
305
|
+
# }
|
|
306
|
+
# }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
#### Migration Steps
|
|
310
|
+
- Replace `totals['percentage']` with `totals['lines']['percent_covered']`.
|
|
311
|
+
- Replace `totals['files']['ok']` and `totals['files']['stale']` with
|
|
312
|
+
`totals['files']['with_coverage']['ok']` and `totals['files']['with_coverage']['stale']['total']`.
|
|
313
|
+
- If you relied on `excluded_files`, use `files.with_coverage.stale.by_type` and
|
|
314
|
+
`files.without_coverage.by_type` (present only when tracking is enabled).
|
|
315
|
+
|
|
316
|
+
### Logger Initialization Changed
|
|
317
|
+
|
|
318
|
+
The `CovLoupe::Logger` class has updated its `initialize` signature.
|
|
319
|
+
|
|
320
|
+
* **Old**: `initialize(target:, mcp_mode: false)`
|
|
321
|
+
* **New**: `initialize(target:, mode: :library)` # or :cli or :mcp
|
|
322
|
+
|
|
323
|
+
#### Migration
|
|
324
|
+
|
|
325
|
+
If you are manually instantiating `CovLoupe::Logger`:
|
|
326
|
+
|
|
327
|
+
```ruby
|
|
328
|
+
# Old
|
|
329
|
+
logger = CovLoupe::Logger.new(target: 'cov_loupe.log', mcp_mode: true)
|
|
330
|
+
logger = CovLoupe::Logger.new(target: 'cov_loupe.log', mcp_mode: false)
|
|
331
|
+
|
|
332
|
+
# New
|
|
333
|
+
logger = CovLoupe::Logger.new(target: 'cov_loupe.log', mode: :mcp)
|
|
334
|
+
logger = CovLoupe::Logger.new(target: 'cov_loupe.log', mode: :cli) # or :library
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
[↑ Back to top](#table-of-contents)
|
|
338
|
+
|
|
339
|
+
## Deleted Files Now Raise `FileNotFoundError`
|
|
340
|
+
|
|
341
|
+
**Breaking Change**: Querying a file that has been deleted (but still exists in the coverage resultset) now raises `FileNotFoundError` instead of returning stale coverage data.
|
|
342
|
+
|
|
343
|
+
### Previous Behavior (v3.x)
|
|
344
|
+
```ruby
|
|
345
|
+
# File lib/foo.rb was deleted after running tests
|
|
346
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
347
|
+
result = model.summary_for('lib/foo.rb')
|
|
348
|
+
# => { 'file' => '/path/to/lib/foo.rb', 'summary' => { 'covered' => 4, 'total' => 6, 'percentage' => 66.67 } }
|
|
349
|
+
# Returns stale coverage data with no error
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```sh
|
|
353
|
+
# CLI would return coverage percentage and exit 0
|
|
354
|
+
$ cov-loupe summary lib/foo.rb
|
|
355
|
+
lib/foo.rb: 66.67% (4/6)
|
|
356
|
+
$ echo $?
|
|
357
|
+
0
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### New Behavior (v4.x)
|
|
361
|
+
```ruby
|
|
362
|
+
# File lib/foo.rb was deleted after running tests
|
|
363
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
364
|
+
result = model.summary_for('lib/foo.rb')
|
|
365
|
+
# => raises CovLoupe::FileNotFoundError: "File not found: lib/foo.rb"
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
```sh
|
|
369
|
+
# CLI raises error and exits 1
|
|
370
|
+
$ cov-loupe summary lib/foo.rb
|
|
371
|
+
Error: File not found: lib/foo.rb
|
|
372
|
+
$ echo $?
|
|
373
|
+
1
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Rationale
|
|
377
|
+
|
|
378
|
+
Deleted files represent **stale data** that:
|
|
379
|
+
1. Misleads coverage metrics and statistics
|
|
380
|
+
2. Violates the API contract (docstring already promised `FileNotFoundError`)
|
|
381
|
+
3. Should be treated the same as other staleness issues
|
|
382
|
+
|
|
383
|
+
If a file no longer exists, its coverage data is no longer meaningful. The new behavior ensures you don't accidentally include deleted file coverage in your metrics.
|
|
384
|
+
|
|
385
|
+
### Impact
|
|
386
|
+
|
|
387
|
+
This affects:
|
|
388
|
+
- `model.summary_for(path)` - All single-file query methods
|
|
389
|
+
- `model.raw_for(path)`
|
|
390
|
+
- `model.uncovered_for(path)`
|
|
391
|
+
- `model.detailed_for(path)`
|
|
392
|
+
- CLI commands: `summary`, `raw`, `uncovered`, `detailed`
|
|
393
|
+
- MCP tools: `coverage_summary_tool`, `coverage_raw_tool`, etc.
|
|
394
|
+
|
|
395
|
+
### Migration
|
|
396
|
+
|
|
397
|
+
**If you expect deleted files to raise errors** (recommended):
|
|
398
|
+
- No action needed. This is the correct behavior.
|
|
399
|
+
|
|
400
|
+
**If you relied on getting coverage for deleted files**:
|
|
401
|
+
- This was incorrect behavior. Update your workflow to:
|
|
402
|
+
1. Re-run tests after file deletions to get fresh coverage, OR
|
|
403
|
+
2. Use the `list` command to see deleted files in the `deleted_files` array without querying them directly
|
|
404
|
+
|
|
405
|
+
**Example: Checking for deleted files**
|
|
406
|
+
```ruby
|
|
407
|
+
model = CovLoupe::CoverageModel.new(root: '.')
|
|
408
|
+
result = model.list
|
|
409
|
+
|
|
410
|
+
if result['deleted_files'].any?
|
|
411
|
+
puts "Warning: Coverage data exists for deleted files:"
|
|
412
|
+
result['deleted_files'].each { |f| puts " - #{f}" }
|
|
413
|
+
end
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
[↑ Back to top](#table-of-contents)
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Staleness Indicators Changed from Strings to Symbols
|
|
421
|
+
|
|
422
|
+
**Breaking Change**: Staleness indicators in the `stale` field now use Ruby symbols instead of single-character strings.
|
|
423
|
+
|
|
424
|
+
### Previous Behavior (v3.x)
|
|
425
|
+
```ruby
|
|
426
|
+
result = model.list
|
|
427
|
+
# => { 'files' => [{ 'file' => 'lib/foo.rb', 'stale' => 'M', ... }], ... }
|
|
428
|
+
|
|
429
|
+
# Staleness was indicated by strings:
|
|
430
|
+
# 'M' - Missing file
|
|
431
|
+
# 'T' - Timestamp mismatch
|
|
432
|
+
# 'L' - Line count mismatch
|
|
433
|
+
# 'E' - Error during staleness check
|
|
434
|
+
# false - Fresh coverage data
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### New Behavior (v4.x)
|
|
438
|
+
```ruby
|
|
439
|
+
result = model.list
|
|
440
|
+
# => { 'files' => [{ 'file' => 'lib/foo.rb', 'stale' => "missing", ... }], ... }
|
|
441
|
+
|
|
442
|
+
# Staleness is now indicated by symbols:
|
|
443
|
+
# "missing" - Missing file
|
|
444
|
+
# "newer" - Timestamp mismatch
|
|
445
|
+
# "length_mismatch" - Line count mismatch
|
|
446
|
+
# "error" - Error during staleness check
|
|
447
|
+
# "ok" - Fresh coverage data
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Rationale
|
|
451
|
+
|
|
452
|
+
Symbols are more idiomatic in Ruby for enumerated values and provide:
|
|
453
|
+
- **Better performance**: Symbols are interned, so comparisons are faster
|
|
454
|
+
- **Clearer semantics**: Symbols represent categories/concepts, not text
|
|
455
|
+
- **Consistency**: Aligns with Ruby conventions for status indicators
|
|
456
|
+
- **Type safety**: Symbol vs String distinction catches bugs
|
|
457
|
+
|
|
458
|
+
### Impact
|
|
459
|
+
|
|
460
|
+
This affects code that:
|
|
461
|
+
- **Checks equality with string literals**: `stale == 'M'` will no longer match
|
|
462
|
+
- **Uses string pattern matching**: Case statements with string patterns need updating
|
|
463
|
+
- **Serializes to JSON**: Symbols are converted to strings in JSON output
|
|
464
|
+
- **Type checks**: `stale.is_a?(Symbol)` instead of `stale.is_a?(String)`
|
|
465
|
+
|
|
466
|
+
**Frequency**: High - affects any code that checks staleness status.
|
|
467
|
+
|
|
468
|
+
### Migration
|
|
469
|
+
|
|
470
|
+
**If you check equality with string literals**:
|
|
471
|
+
```ruby
|
|
472
|
+
# Old
|
|
473
|
+
if file['stale'] == 'M'
|
|
474
|
+
puts "File is missing"
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# New - use symbols
|
|
478
|
+
if file['stale'] == 'missing'
|
|
479
|
+
puts "File is missing"
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# Or use string comparison (less efficient but works with both versions)
|
|
483
|
+
if file['stale'].to_s == 'missing'
|
|
484
|
+
puts "File is missing"
|
|
485
|
+
end
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**If you use case statements with string patterns**:
|
|
489
|
+
```ruby
|
|
490
|
+
# Old
|
|
491
|
+
case file['stale']
|
|
492
|
+
when 'M' then handle_missing
|
|
493
|
+
when 'T' then handle_timestamp
|
|
494
|
+
when 'L' then handle_length
|
|
495
|
+
when 'E' then handle_error
|
|
496
|
+
when false then handle_fresh
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
# New - use symbols
|
|
500
|
+
case file['stale']
|
|
501
|
+
when 'missing' then handle_missing
|
|
502
|
+
when 'newer' then handle_timestamp
|
|
503
|
+
when 'length_mismatch' then handle_length
|
|
504
|
+
when 'error' then handle_error
|
|
505
|
+
when 'ok' then handle_fresh
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
# Or use to_s for backward compatibility
|
|
509
|
+
case file['stale'].to_s
|
|
510
|
+
when 'missing' then handle_missing
|
|
511
|
+
when 'newer' then handle_timestamp
|
|
512
|
+
when 'length_mismatch' then handle_length
|
|
513
|
+
when 'error' then handle_error
|
|
514
|
+
when 'ok' then handle_fresh
|
|
515
|
+
end
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**If you check for any staleness**:
|
|
519
|
+
```ruby
|
|
520
|
+
# Old (works for both versions)
|
|
521
|
+
if file['stale']
|
|
522
|
+
puts "Stale file (#{file['stale']})"
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# New - explicit type check
|
|
526
|
+
if file['stale'].is_a?(Symbol)
|
|
527
|
+
puts "Stale file (#{file['stale']})"
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
# Or use the same approach (works for both versions)
|
|
531
|
+
if file['stale']
|
|
532
|
+
puts "Stale file (#{file['stale']})"
|
|
533
|
+
end
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**JSON serialization note**: When serializing to JSON (CLI, MCP, etc.), symbols are automatically converted to strings:
|
|
537
|
+
```ruby
|
|
538
|
+
# In Ruby
|
|
539
|
+
file['stale'] # => "missing"
|
|
540
|
+
|
|
541
|
+
# In JSON output
|
|
542
|
+
{ "file": "lib/foo.rb", "stale": "missing" }
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
**Table output legend updated**:
|
|
546
|
+
```
|
|
547
|
+
Staleness: missing = Missing file, newer = Timestamp mismatch, length_mismatch = Line count mismatch, error = Check failed
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Complete Staleness Value Reference
|
|
551
|
+
|
|
552
|
+
| Status | v3.x (String) | v4.x (Symbol) | Description |
|
|
553
|
+
|--------|----------------|------------------|-------------|
|
|
554
|
+
| Fresh | `false` | `"ok"` | Coverage data is current |
|
|
555
|
+
| Missing file | `'M'` | `"missing"` | File no longer exists on disk |
|
|
556
|
+
| Timestamp mismatch | `'T'` | `"newer"` | File modified after coverage was generated |
|
|
557
|
+
| Line count mismatch | `'L'` | `"length_mismatch"` | Source file line count differs from coverage data |
|
|
558
|
+
| Check error | `'E'` | `"error"` | Staleness check failed (permissions, I/O errors, etc.) |
|
|
559
|
+
|
|
560
|
+
[↑ Back to top](#table-of-contents)
|
|
561
|
+
|
|
562
|
+
---
|
|
563
|
+
|
|
564
|
+
## Removed Branch-Only Coverage Support
|
|
565
|
+
|
|
566
|
+
**Breaking Change**: The automatic synthesis of line coverage data from SimpleCov branch-only coverage results has been removed.
|
|
567
|
+
|
|
568
|
+
### Rationale
|
|
569
|
+
The logic required to maintain this feature was complex and prone to edge cases, particularly regarding staleness detection and line-count mismatches. Additionally, branch-only coverage is a rarely used configuration in the SimpleCov ecosystem.
|
|
570
|
+
|
|
571
|
+
### Impact
|
|
572
|
+
If your project is configured to track **only** branch coverage in SimpleCov (e.g., `enable_coverage :branch` without also tracking lines), `cov-loupe` will no longer be able to process your coverage data and will raise a `CorruptCoverageDataError`.
|
|
573
|
+
|
|
574
|
+
### How to Migrate
|
|
575
|
+
Most users do not need to take any action. Line coverage is enabled by default in SimpleCov.
|
|
576
|
+
|
|
577
|
+
If you have `enable_coverage :branch` in your configuration, your `.resultset.json` contains both `lines` and `branches` data. **This is fully supported.** `cov-loupe` will read and report the `lines` coverage as usual.
|
|
578
|
+
|
|
579
|
+
The change in v4.0 is simply that `cov-loupe` no longer looks at the `branches` data at all. Previously, if `lines` data was missing (a rare edge case), `cov-loupe` would attempt to calculate line coverage by summing up branch hits. This fallback logic has been removed.
|
|
580
|
+
|
|
581
|
+
[↑ Back to top](#table-of-contents)
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## Getting Help
|
|
586
|
+
|
|
587
|
+
If you encounter issues migrating to v4.0:
|
|
588
|
+
|
|
589
|
+
1. Check the [TROUBLESHOOTING.md](../TROUBLESHOOTING.md) guide.
|
|
590
|
+
2. Review the [CLI_USAGE.md](../CLI_USAGE.md) for complete CLI reference.
|
|
591
|
+
3. Open an issue at https://github.com/keithrbennett/cov-loupe/issues.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Migration Guides
|
|
2
|
+
|
|
3
|
+
Upgrade guides for major version changes in cov-loupe.
|
|
4
|
+
|
|
5
|
+
## Available Guides
|
|
6
|
+
|
|
7
|
+
- [Migrating to v4](MIGRATING_TO_V4.md) - Upgrade from v3.x to v4.x
|
|
8
|
+
- [Migrating to v3](MIGRATING_TO_V3.md) - Upgrade from v2.x to v3.x
|
|
9
|
+
- [Migrating to v2](MIGRATING_TO_V2.md) - Upgrade from v1.x to v2.x
|
|
10
|
+
|
|
11
|
+
## General Migration Tips
|
|
12
|
+
|
|
13
|
+
1. Always review the [Release Notes](../../release_notes.md) for your target version
|
|
14
|
+
2. Run your test suite after upgrading to catch any breaking changes
|
|
15
|
+
3. Check the [Troubleshooting Guide](../TROUBLESHOOTING.md) if you encounter issues
|
|
16
|
+
|
|
17
|
+
## Need Help?
|
|
18
|
+
|
|
19
|
+
If you encounter issues during migration, please:
|
|
20
|
+
- Check the relevant migration guide above for your version
|
|
21
|
+
- Review the [Troubleshooting Guide](../TROUBLESHOOTING.md)
|
|
22
|
+
- Search or open an issue on [GitHub](https://github.com/keithrbennett/cov-loupe/issues)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Prompt Library
|
|
2
|
+
|
|
3
|
+
[Back to main README](../../index.md)
|
|
4
|
+
|
|
5
|
+
Starter prompts you can paste into MCP-compatible assistants when you need cov-loupe to run targeted reports or fall back to CLI execution.
|
|
6
|
+
|
|
7
|
+
- [Rails Coverage Analysis](rails-coverage-analysis-prompt.md) – Guide an assistant through triaging a Rails `.resultset.json`
|
|
8
|
+
- [Non-Web Coverage Analysis](non-web-coverage-analysis-prompt.md) – Prompts for service/library repos
|
|
9
|
+
- [Use CLI Instead of MCP](use-cli-not-mcp-prompt.md) – Scripted fallback when MCP transport is blocked
|