branchproof 0.5.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5b31682254d1c9db4be1d61e11743be038c65f859c730be05d1acae138e673c
4
- data.tar.gz: 59a6f30a1586c0783283f32e16d1ed5626f702f3ec152ec15dfe271cfbc0c0b1
3
+ metadata.gz: c4c0c87db7babd3785baf2ea439a90ec852253e7ade2837becec235ee9ac7055
4
+ data.tar.gz: 29b5cd02d6ab9419343af3c9c1d49fd07a77c2487eaf2631aafbc90bafdf4296
5
5
  SHA512:
6
- metadata.gz: 061d18741787eaeb57f5f1ec90a5e68d658fa8d9344fee52ecfa54fd70a69fcc909affe4890785031403a46379c90e11ac8a63c01766bd8477e2d7963ca14172
7
- data.tar.gz: 144e5b02c3a380133015402e9ad2b47b52bc3a4d624c2f13728015159cd7ec6287fe7b3d1f167fb2ce745b3d953d5f271628a740c0912ae36af3fa7f72e13fb9
6
+ metadata.gz: bffba10f09dc43d851a79373b1e3ec8b2457179a2f69da8b8076d1f48c002f3a8f6a88e7a30f8c970c5f9960a73abbec4829dfcbee2581da61c5ff3cd1e233f4
7
+ data.tar.gz: c808687e23a8b27ed794d723d4a390f8296d5ade907fb6255660ac025e657530eff850d578d7d600b1177076dcf2376d577b15a4310e620cd618bf4598f626fc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.0] - 2026-09-10
4
+
5
+ - Discover Boolean loop predicates, subjectless case candidates, standalone
6
+ short-circuit expressions, and pattern predicates through Prism.
7
+ - Analyze unary NOT and keyword `and`/`or` with Ruby's parsed precedence.
8
+ - Attribute selected paths for ordinary case, unguarded case/in, safe navigation,
9
+ and conditional assignments without adding them to MC/DC denominators.
10
+ - Expose decision kinds, contexts, alternative evidence, and explicit unsupported
11
+ constructs in schema 1.2 reports while retaining older saved-report support.
12
+
13
+ ## [0.6.0] - 2026-09-10
14
+
15
+ - Report Decision, Condition, and Condition/Decision Coverage alongside
16
+ existing MC/DC evidence from one test execution.
17
+ - Show explicit coverage counts, supporting tests, and missing Boolean
18
+ observations in decision, condition, and test views and JSON reports.
19
+ - Calculate the same coverage criteria at every reporting level and retain
20
+ analysis in level-1 snapshots for offline inspection at higher detail.
21
+ Continue to support legacy snapshots without analysis at level 1.
22
+
3
23
  ## [0.5.0] - 2026-09-10
4
24
 
5
25
  - Show source filenames beside diagnostics in decision, condition, and test
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Branchproof
2
2
 
3
- Branchproof measures modified condition/decision coverage (MC/DC) from one
4
- serial Minitest run. It inventories supported `if`, `unless`, `elsif`,
5
- modifier, and ordinary ternary (`?:`) decisions, records observed vectors,
6
- and reports independence evidence, missing counterpart constraints, and
7
- smaller supporting test sets.
3
+ Branchproof measures decision, condition, and modified condition/decision
4
+ coverage (MC/DC) from one serial Minitest run. It discovers Ruby decisions
5
+ through Prism, records their runtime paths, and attributes evidence to tests.
6
+ Boolean decisions receive the coverage ladder; `case`, pattern alternatives,
7
+ safe navigation, and conditional assignments receive alternative coverage.
8
8
 
9
9
  The gem and primary command are named `branchproof`. The `mcdc` command and
10
10
  `MCDC` namespace remain compatibility aliases with the same behavior.
@@ -126,6 +126,50 @@ Additional tests outside this MC/DC evidence set may improve coverage.
126
126
  The test execution still runs once for the selected level. Use `--format
127
127
  json` when a consumer needs the complete identifiers and versioned schema.
128
128
 
129
+ ### Coverage ladder
130
+
131
+ Each successful `analyze` run calculates four criteria from the same completed
132
+ observations. The report shows their status for each supported decision and
133
+ aggregate counts with explicit denominators:
134
+
135
+ | Criterion | Requirement | Aggregate denominator |
136
+ | --- | --- | --- |
137
+ | Decision | The decision produced both true and false | Supported decisions |
138
+ | Condition | Every atomic condition evaluated both true and false | Two required truth values per supported condition |
139
+ | Condition/Decision | Both Decision and Condition Coverage hold for a decision | Supported decisions |
140
+ | MC/DC | Every condition has an independence witness pair | Supported conditions |
141
+
142
+ For `logged_in? && admin?`, observations `[F-] => F` and `[TT] => T` give:
143
+
144
+ ```text
145
+ Decision PASS
146
+ Condition FAIL (3/4 values observed)
147
+ Condition/Decision FAIL
148
+ MC/DC FAIL (1/2 conditions proven)
149
+ ```
150
+
151
+ The skipped `admin?` in `[F-]` counts as neither true nor false. Conditions
152
+ that did evaluate count toward Condition Coverage even when their value was
153
+ masked by another condition. Here, the two observations prove independence
154
+ for `logged_in?`; `admin?` still needs `[TF] => F`.
155
+
156
+ Decision and Condition Coverage are calculated independently from the captured
157
+ evidence. Condition/Decision requires both; MC/DC adds independence evidence.
158
+ Unsupported decisions are excluded from every denominator, while
159
+ unexecuted supported decisions remain in scope. Empty denominators are N/A.
160
+
161
+ Reports retain the observations and owning tests for each decision outcome
162
+ and condition value. Missing values describe required runtime observations,
163
+ not application inputs or a guarantee that the path is reachable. Unattributed
164
+ observations can provide truth-value evidence without identifying a test;
165
+ the report's completeness and diagnostics still apply.
166
+
167
+ JSON stores aggregate counts under `analysis.coverage`, per-decision results
168
+ under `analysis.decisions[].coverage`, and condition value evidence under
169
+ `analysis.decisions[].condition_results[].coverage`. Existing MC/DC witness
170
+ pairs, counterpart constraints, and raw vectors remain available. Statuses
171
+ distinguish `covered`, `partial`, `unexecuted`, and `unsupported` results.
172
+
129
173
  ### Find missing cases
130
174
 
131
175
  Use `--missing-only` to focus the terminal report on conditions that still
@@ -175,15 +219,17 @@ test inputs; they do not by themselves prove a bug in the application.
175
219
 
176
220
  The levels select how much of the one-run result is displayed:
177
221
 
178
- * Level 1 reports observed vectors grouped by their raw decision outcomes.
222
+ * Level 1 reports the coverage ladder and observed vectors grouped by their
223
+ raw decision outcomes.
179
224
  * Level 2 includes the smallest supporting sets found for vectors and tests.
180
225
  * Level 3 (the default) includes condition independence witnesses and
181
226
  counterpart constraints, as well as the Level 1 and 2 evidence.
182
227
 
183
- Level 2 and Level 3 compute from the same captured run. They do not rerun the
184
- test suite. A failed, unsupported, or incomplete run is reported with its
185
- status and diagnostics and cannot become a successful coverage result by
186
- changing the display level.
228
+ All levels calculate the same criteria from one captured run. The level
229
+ controls displayed evidence, not the coverage criterion; JSON retains the
230
+ analysis even at Level 1. A failed, unsupported, or incomplete run is reported
231
+ with its status and diagnostics and cannot become a successful coverage
232
+ result by changing the display level.
187
233
 
188
234
  ### Focused condition and test views
189
235
 
@@ -232,7 +278,8 @@ artifacts when you need to retain multiple runs.
232
278
  The `report` command reads the saved document without loading the application
233
279
  or running tests. It uses locations and metadata captured in the report, so
234
280
  rendering remains useful after the original checkout has moved or been
235
- removed. Level 1 reports observations; levels 2 and 3 require corresponding
281
+ removed. New snapshots retain the ladder at every level. Legacy snapshots
282
+ without analysis can still be rendered at Level 1; levels 2 and 3 require
236
283
  analysis in the saved report. The repository ignores `.branchproof/`; choose a
237
284
  different path and CI artifact policy when a project needs to retain reports.
238
285
  Saved JSON includes existing raw metadata such as test names and expressions;
@@ -274,26 +321,77 @@ short-circuited or masked rather than fixed to the same observed values. For exa
274
321
  short-circuits it once, but does not prove `right`; `[TF]` is also required.
275
322
  The condition and test views preserve that distinction.
276
323
 
277
- ### Supported conditional forms
278
-
279
- Ordinary Ruby ternaries use the same predicate instrumentation and `&&`/`||`
280
- condition trees as supported `if` decisions. For example:
281
-
282
- ```ruby
283
- value = ready ? false : true
284
- ```
285
-
286
- Branchproof records `ready` as the ternary predicate. The decision outcome is
287
- therefore the truth value of `ready`, even though the selected branch returns
288
- `false` or `true`; branch selection, returned values, object identity, and
289
- evaluation order are unchanged. Ternaries nested inside other predicates are
290
- also inventoried at their own level, including all executed nested levels.
291
- Expanding the supported syntax increases the eligible-condition denominator,
292
- so percentages should be compared with that changed scope in mind.
293
-
294
- The existing predicate exclusions and analysis limits still apply. Keyword
295
- `and`/`or` expressions, contextual syntax, unsafe or ambiguous predicates,
296
- and limit overflows remain diagnostics rather than eligible coverage.
324
+ ### Supported decision forms
325
+
326
+ Every decision has a stable `kind` and `context` in JSON. The Boolean ladder
327
+ applies to the following forms:
328
+
329
+ | Construct | Kind | Context |
330
+ | --- | --- | --- |
331
+ | `if`, modifier `if`, `elsif`, `unless`, ternary | `boolean` | `if`, `elsif`, `unless`, `ternary` |
332
+ | `while`, `until`, including modifier and post-test loops | `boolean` | `while`, `until` |
333
+ | Each subjectless `case` candidate | `boolean` | `case_when` |
334
+ | Standalone `value in pattern` | `boolean` | `pattern_in` |
335
+ | Evaluated pattern guard predicate | `boolean` | `pattern_guard` |
336
+ | Standalone `&&`, `||`, `and`, `or` | `boolean` | `short_circuit` |
337
+
338
+ Prism determines precedence. `!` and `not` appear as NOT nodes in the Boolean
339
+ tree; their operands remain the conditions. Short-circuited operands remain
340
+ not evaluated. A Boolean subtree already decomposed in a decision is not
341
+ inventoried again as a standalone decision.
342
+
343
+ Loop outcomes describe the predicate as written: an `until` predicate that
344
+ returns true ends the loop. Every predicate evaluation receives an execution
345
+ ID. Repeated equivalent executions aggregate into a vector's `count`, retaining
346
+ the supporting tests. Ternary outcomes likewise describe the predicate, not
347
+ the value returned by the chosen branch.
348
+
349
+ Other constructs use alternative coverage, separate from MC/DC:
350
+
351
+ | Construct | Kind | Context | Required alternatives |
352
+ | --- | --- | --- | --- |
353
+ | `case subject` | `multiway` | `case` | Each `when` candidate and `else` (or implicit no-match path) |
354
+ | `case/in` | `pattern` | `case_in` | Each pattern clause and explicit `else`, if present |
355
+ | `receiver&.method` | `implicit` | `safe_navigation` | Receiver nil / non-nil |
356
+ | `lhs ||= rhs` | `implicit` | `or_assignment` | RHS skipped / executed |
357
+ | `lhs &&= rhs` | `implicit` | `and_assignment` | RHS skipped / executed |
358
+
359
+ Each safe-navigation operation in a chain is a distinct decision. Assignment
360
+ instrumentation preserves Ruby's native local, instance, class, global,
361
+ constant, method, and indexed assignment operations, including receiver and
362
+ index evaluation order. Safe navigation distinguishes nil from false.
363
+
364
+ For multiway decisions, vector values mean selected (`true`), evaluated but
365
+ not selected (`false`), and skipped (`null`). Later alternatives remain skipped
366
+ when an earlier candidate matches. Implicit vectors record the selected path
367
+ and its unselected complement. Their `outcome` is a selection marker, not the
368
+ truthiness of the application's return value. Reports label these as paths,
369
+ not Boolean outcomes. Each alternative exposes selected, not-selected, and
370
+ skipped evidence with test and vector IDs. The alternative denominator is the
371
+ number of supported selectable alternatives; these decisions do not enter
372
+ Boolean-ladder or MC/DC denominators.
373
+
374
+ A `case/in` without `else` retains Ruby's native no-match exception. An execution
375
+ that fails before choosing a branch is aborted, not counted as a selected
376
+ alternative. Selected branches and assignment paths remain observed even when
377
+ their bodies or right-hand sides subsequently raise or return.
378
+
379
+ Unsupported syntax stays visible and outside coverage denominators. Current
380
+ exclusions include guarded `case/in` (`unsupported_pattern_guard`), dynamic
381
+ `when` splats (`unsupported_case_splat`), safe-navigation compound assignment
382
+ (`unsupported_assignment_target`), and rescue alternatives
383
+ (`unsupported_rescue_control_flow`). A guard predicate can still supply Boolean
384
+ evidence when Ruby evaluates it; an unsupported guarded case does not claim
385
+ pattern-match coverage from that evidence. Flip-flops remain
386
+ `unsupported_flip_flop`. Decisions inside `defined?`, contextual regular
387
+ expressions, heredocs, unsafe predicates, and limit overflows retain explicit
388
+ exclusions. Ruby-defined custom `!` methods keep their runtime behavior;
389
+ evidence that contradicts Boolean negation is rejected instead of proving
390
+ coverage with an invalid logical model.
391
+
392
+ New reports use schema `1.2`; saved schema `1.0` and `1.1` reports remain
393
+ readable. Expanded discovery changes coverage denominators, so compare reports
394
+ with their supported syntax scope in mind.
297
395
 
298
396
  ### Limits
299
397
 
@@ -8,6 +8,9 @@
8
8
  Derives condition- and test-oriented rows from one report document.
9
9
 
10
10
  ## Attributes
11
+ ### `alternatives` [R] <a id="attribute-i-alternatives"></a> <a id="alternatives-instance_method"></a>
12
+ Returns the value of attribute alternatives.
13
+
11
14
  ### `conditions` [R] <a id="attribute-i-conditions"></a> <a id="conditions-instance_method"></a>
12
15
  Returns the value of attribute conditions.
13
16
 
@@ -0,0 +1,20 @@
1
+ # Module Branchproof::DecisionSyntax <a id="module-Branchproof-DecisionSyntax"></a>
2
+
3
+ | | |
4
+ | --- | --- |
5
+ | **Defined in** | lib/branchproof/decision_syntax.rb |
6
+
7
+ Discovers control-flow expressions whose truth is not represented by an
8
+ ordinary Prism IfNode. The records intentionally contain byte ranges and
9
+ scalar metadata only; Prism nodes must not escape the source pass.
10
+
11
+ ## Constants
12
+ ### `AND_WRITE_NODE_NAMES` <a id="constant-AND_WRITE_NODE_NAMES"></a> <a id="AND_WRITE_NODE_NAMES-constant"></a>
13
+ Not documented.
14
+
15
+ ### `OR_WRITE_NODE_NAMES` <a id="constant-OR_WRITE_NODE_NAMES"></a> <a id="OR_WRITE_NODE_NAMES-constant"></a>
16
+ Not documented.
17
+
18
+ ## Public Instance Methods
19
+ ### `flow_decisions_for(program, bytes, source_id, file_reasons = [], encoding = "UTF-8")` <a id="method-i-flow_decisions_for"></a> <a id="flow_decisions_for-instance_method"></a>
20
+ Not documented.
@@ -0,0 +1,7 @@
1
+ # Module Branchproof::FlowInstrumentation <a id="module-Branchproof-FlowInstrumentation"></a>
2
+
3
+ | | |
4
+ | --- | --- |
5
+ | **Defined in** | lib/branchproof/flow_instrumentation.rb |
6
+
7
+ Source-location edits around Ruby's native matching and assignment operations.
@@ -3,6 +3,7 @@
3
3
  | | |
4
4
  | --- | --- |
5
5
  | **Inherits** | Object |
6
+ | **Includes** | [Branchproof::FlowInstrumentation](FlowInstrumentation.md) |
6
7
  | **Defined in** | lib/branchproof/instrumenter.rb |
7
8
 
8
9
  Applies the smallest possible source edits around inventoried expressions. The
@@ -19,9 +19,19 @@ Not documented.
19
19
  Not documented.
20
20
 
21
21
  ## Public Instance Methods
22
+ ### `condition_coverage_evidence(decision_id:, condition_id:)` <a id="method-i-condition_coverage_evidence"></a> <a id="condition_coverage_evidence-instance_method"></a>
23
+ Returns condition-value evidence for focused renderers without exposing the
24
+ report's internal document traversal or mutating saved records.
25
+
22
26
  ### `condition_explanation(decision_id:, condition_id:)` <a id="method-i-condition_explanation"></a> <a id="condition_explanation-instance_method"></a>
23
27
  Shares the existing missing-case wording with focused terminal views.
24
28
 
29
+ ### `coverage_ladder_lines()` <a id="method-i-coverage_ladder_lines"></a> <a id="coverage_ladder_lines-instance_method"></a>
30
+ Render the shared ladder in every terminal view.
31
+
32
+ ### `coverage_status_label(status)` <a id="method-i-coverage_status_label"></a> <a id="coverage_status_label-instance_method"></a>
33
+ Not documented.
34
+
25
35
  ### `diagnostic_message(diagnostic)` <a id="method-i-diagnostic_message"></a> <a id="diagnostic_message-instance_method"></a>
26
36
  Formats source context consistently in live and saved terminal views.
27
37
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  | | |
4
4
  | --- | --- |
5
+ | **Extended by** | [Branchproof::RuntimeFlow](RuntimeFlow.md) |
5
6
  | **Defined in** | lib/branchproof/runtime.rb |
6
7
 
7
8
  Process-local execution recorder. It deliberately never coerces or stores
@@ -27,6 +28,24 @@ Not documented.
27
28
  ### `finish(decision_id, value)` <a id="method-c-finish"></a> <a id="finish-class_method"></a>
28
29
  Not documented.
29
30
 
31
+ ### `flow_candidate(decision_id, index)` <a id="method-c-flow_candidate"></a> <a id="flow_candidate-class_method"></a>
32
+ Not documented.
33
+
34
+ ### `flow_finish(decision_id, value, default_path = nil)` <a id="method-c-flow_finish"></a> <a id="flow_finish-class_method"></a>
35
+ Not documented.
36
+
37
+ ### `flow_path(decision_id, index)` <a id="method-c-flow_path"></a> <a id="flow_path-class_method"></a>
38
+ Not documented.
39
+
40
+ ### `flow_receiver(decision_id, receiver)` <a id="method-c-flow_receiver"></a> <a id="flow_receiver-class_method"></a>
41
+ Not documented.
42
+
43
+ ### `flow_select(decision_id, index)` <a id="method-c-flow_select"></a> <a id="flow_select-class_method"></a>
44
+ Not documented.
45
+
46
+ ### `flow_selected(decision_id)` <a id="method-c-flow_selected"></a> <a id="flow_selected-class_method"></a>
47
+ Not documented.
48
+
30
49
  ### `leave(decision_id)` <a id="method-c-leave"></a> <a id="leave-class_method"></a>
31
50
  Not documented.
32
51
 
@@ -0,0 +1,27 @@
1
+ # Module Branchproof::RuntimeFlow <a id="module-Branchproof-RuntimeFlow"></a>
2
+
3
+ | | |
4
+ | --- | --- |
5
+ | **Defined in** | lib/branchproof/runtime_flow.rb |
6
+
7
+ Records native Ruby path selection without evaluating application values
8
+ twice.
9
+
10
+ ## Public Instance Methods
11
+ ### `flow_candidate(decision_id, index)` <a id="method-i-flow_candidate"></a> <a id="flow_candidate-instance_method"></a>
12
+ Not documented.
13
+
14
+ ### `flow_finish(decision_id, value, default_path = nil)` <a id="method-i-flow_finish"></a> <a id="flow_finish-instance_method"></a>
15
+ Not documented.
16
+
17
+ ### `flow_path(decision_id, index)` <a id="method-i-flow_path"></a> <a id="flow_path-instance_method"></a>
18
+ Not documented.
19
+
20
+ ### `flow_receiver(decision_id, receiver)` <a id="method-i-flow_receiver"></a> <a id="flow_receiver-instance_method"></a>
21
+ Not documented.
22
+
23
+ ### `flow_select(decision_id, index)` <a id="method-i-flow_select"></a> <a id="flow_select-instance_method"></a>
24
+ Not documented.
25
+
26
+ ### `flow_selected(decision_id)` <a id="method-i-flow_selected"></a> <a id="flow_selected-instance_method"></a>
27
+ Not documented.
@@ -14,6 +14,12 @@ Not documented.
14
14
  ### `CRITERION_VERSION` <a id="constant-CRITERION_VERSION"></a> <a id="CRITERION_VERSION-constant"></a>
15
15
  Not documented.
16
16
 
17
+ ### `DECISION_KINDS` <a id="constant-DECISION_KINDS"></a> <a id="DECISION_KINDS-constant"></a>
18
+ Not documented.
19
+
20
+ ### `NONBOOLEAN_KINDS` <a id="constant-NONBOOLEAN_KINDS"></a> <a id="NONBOOLEAN_KINDS-constant"></a>
21
+ Not documented.
22
+
17
23
  ### `REQUIRED_FIELDS` <a id="constant-REQUIRED_FIELDS"></a> <a id="REQUIRED_FIELDS-constant"></a>
18
24
  Not documented.
19
25
 
@@ -3,6 +3,7 @@
3
3
  | | |
4
4
  | --- | --- |
5
5
  | **Inherits** | Object |
6
+ | **Includes** | [Branchproof::DecisionSyntax](DecisionSyntax.md) |
6
7
  | **Defined in** | lib/branchproof/source.rb |
7
8
 
8
9
  Inventories supported condition and decision occurrences from Ruby files.
data/doc/Branchproof.md CHANGED
@@ -2,9 +2,10 @@
2
2
 
3
3
  | | |
4
4
  | --- | --- |
5
- | **Defined in** | lib/branchproof.rb, lib/branchproof/cli.rb, lib/branchproof/limits.rb, lib/branchproof/loader.rb, lib/branchproof/report.rb, lib/branchproof/source.rb, lib/branchproof/worker.rb, lib/branchproof/project.rb, lib/branchproof/records.rb, lib/branchproof/runtime.rb, lib/branchproof/version.rb, lib/branchproof/analyzer.rb, lib/branchproof/evidence.rb, lib/branchproof/minimizer.rb, lib/branchproof/comparison.rb, lib/branchproof/instrumenter.rb, lib/branchproof/saved_report.rb, lib/branchproof/rails_support.rb, lib/branchproof/coverage_index.rb, lib/branchproof/focused_report.rb, lib/branchproof/minitest_adapter.rb, lib/branchproof/comparison_report.rb |
5
+ | **Defined in** | lib/branchproof.rb, lib/branchproof/cli.rb, lib/branchproof/limits.rb, lib/branchproof/loader.rb, lib/branchproof/report.rb, lib/branchproof/source.rb, lib/branchproof/worker.rb, lib/branchproof/project.rb, lib/branchproof/records.rb, lib/branchproof/runtime.rb, lib/branchproof/version.rb, lib/branchproof/analyzer.rb, lib/branchproof/evidence.rb, lib/branchproof/minimizer.rb, lib/branchproof/comparison.rb, lib/branchproof/instrumenter.rb, lib/branchproof/runtime_flow.rb, lib/branchproof/saved_report.rb, lib/branchproof/rails_support.rb, lib/branchproof/coverage_index.rb, lib/branchproof/focused_report.rb, lib/branchproof/decision_syntax.rb, lib/branchproof/minitest_adapter.rb, lib/branchproof/comparison_report.rb, lib/branchproof/flow_instrumentation.rb |
6
6
 
7
- Public namespace for source inventory and one-run MC/DC reporting.
7
+ Keep each bounded source rewrite together so its evaluation order can be
8
+ audited. rubocop:disable Metrics/AbcSize, Metrics/MethodLength
8
9
 
9
10
  ## Constants
10
11
  ### `VERSION` <a id="constant-VERSION"></a> <a id="VERSION-constant"></a>
@@ -17,8 +18,10 @@ Not documented.
17
18
  - [Branchproof/Comparison.md](Branchproof/Comparison.md)
18
19
  - [Branchproof/ComparisonReport.md](Branchproof/ComparisonReport.md)
19
20
  - [Branchproof/CoverageIndex.md](Branchproof/CoverageIndex.md)
21
+ - [Branchproof/DecisionSyntax.md](Branchproof/DecisionSyntax.md)
20
22
  - [Branchproof/Error.md](Branchproof/Error.md)
21
23
  - [Branchproof/Evidence.md](Branchproof/Evidence.md)
24
+ - [Branchproof/FlowInstrumentation.md](Branchproof/FlowInstrumentation.md)
22
25
  - [Branchproof/FocusedReport.md](Branchproof/FocusedReport.md)
23
26
  - [Branchproof/Instrumenter.md](Branchproof/Instrumenter.md)
24
27
  - [Branchproof/Limits.md](Branchproof/Limits.md)
@@ -31,6 +34,7 @@ Not documented.
31
34
  - [Branchproof/Records.md](Branchproof/Records.md)
32
35
  - [Branchproof/Report.md](Branchproof/Report.md)
33
36
  - [Branchproof/Runtime.md](Branchproof/Runtime.md)
37
+ - [Branchproof/RuntimeFlow.md](Branchproof/RuntimeFlow.md)
34
38
  - [Branchproof/SavedReport.md](Branchproof/SavedReport.md)
35
39
  - [Branchproof/Source.md](Branchproof/Source.md)
36
40
  - [Branchproof/Worker.md](Branchproof/Worker.md)
data/doc/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.0] - 2026-09-10
4
+
5
+ - Discover Boolean loop predicates, subjectless case candidates, standalone
6
+ short-circuit expressions, and pattern predicates through Prism.
7
+ - Analyze unary NOT and keyword `and`/`or` with Ruby's parsed precedence.
8
+ - Attribute selected paths for ordinary case, unguarded case/in, safe navigation,
9
+ and conditional assignments without adding them to MC/DC denominators.
10
+ - Expose decision kinds, contexts, alternative evidence, and explicit unsupported
11
+ constructs in schema 1.2 reports while retaining older saved-report support.
12
+
13
+ ## [0.6.0] - 2026-09-10
14
+
15
+ - Report Decision, Condition, and Condition/Decision Coverage alongside
16
+ existing MC/DC evidence from one test execution.
17
+ - Show explicit coverage counts, supporting tests, and missing Boolean
18
+ observations in decision, condition, and test views and JSON reports.
19
+ - Calculate the same coverage criteria at every reporting level and retain
20
+ analysis in level-1 snapshots for offline inspection at higher detail.
21
+ Continue to support legacy snapshots without analysis at level 1.
22
+
3
23
  ## [0.5.0] - 2026-09-10
4
24
 
5
25
  - Show source filenames beside diagnostics in decision, condition, and test