lint rule: unreachable branch given a prior guard clause #201

Closed
opened 2026-08-01 14:16:50 +00:00 by jared · 2 comments
Owner

Migrated from jared/os-sdlc#26 (repo retired).

lint rule: unreachable branch given a prior guard clause

Problem

General pattern (originally found in the retired eval-sandbox's
decision-dice.rb, no longer relevant as a specific file): a conditional
branch whose condition can never be true given an earlier guard clause in
the same method, e.g. a guard that raises when some value is empty, followed
later by a branch that only fires when that same value is empty. The branch
is dead code and never test-coverable.

Detection

  • Inputs: lib/ Ruby source + test suite.
  • Algorithm: not fully specified. Candidates: (a) a mutation-testing gate
    (e.g. mutant) that would surface this branch as an unkillable mutant
    because no test exercises it; (b) a narrow, mechanical rubocop cop that
    only flags the specific shape "guard clause raises when x.empty?, later
    branch condition includes x.empty? with no intervening reassignment of
    x" -- this narrower version is AST-checkable but only catches this one
    shape, not general unreachability.
  • Failure message: name the unreachable condition and the guard clause
    that makes it unreachable.

Correction

Delete the branch, or add a test proving it's reachable via a path not yet
considered.

Pass/fail examples

  • Must fail: a method with an early raising guard on x.empty? and a
    later branch also conditioned on x.empty? with no test exercising it.
  • Must pass: branch removed, or a passing test that reaches it.

Provenance

Fable + Codex dual review, run 18 (ticket #18, decision-dice), 2026-07-21.
Reassessed 2026-08-01 during os-sdlc sandbox retirement triage: general
unreachability analysis is likely too broad for a rubocop cop; the narrower
guard-clause-shape version (candidate b above) is the only variant that's
concretely implementable as a cop. Needs a decision on which variant to
pursue before implementation.

Implementation plan

Not decided -- general mutation-testing gate vs. narrow AST cop is an open
call.

Migrated from jared/os-sdlc#26 (repo retired). # lint rule: unreachable branch given a prior guard clause ## Problem General pattern (originally found in the retired eval-sandbox's decision-dice.rb, no longer relevant as a specific file): a conditional branch whose condition can never be true given an earlier guard clause in the same method, e.g. a guard that raises when some value is empty, followed later by a branch that only fires when that same value is empty. The branch is dead code and never test-coverable. ## Detection * **Inputs:** lib/ Ruby source + test suite. * **Algorithm:** not fully specified. Candidates: (a) a mutation-testing gate (e.g. `mutant`) that would surface this branch as an unkillable mutant because no test exercises it; (b) a narrow, mechanical rubocop cop that only flags the specific shape "guard clause raises when `x.empty?`, later branch condition includes `x.empty?` with no intervening reassignment of x" -- this narrower version is AST-checkable but only catches this one shape, not general unreachability. * **Failure message:** name the unreachable condition and the guard clause that makes it unreachable. ## Correction Delete the branch, or add a test proving it's reachable via a path not yet considered. ## Pass/fail examples * **Must fail:** a method with an early raising guard on `x.empty?` and a later branch also conditioned on `x.empty?` with no test exercising it. * **Must pass:** branch removed, or a passing test that reaches it. ## Provenance Fable + Codex dual review, run 18 (ticket #18, decision-dice), 2026-07-21. Reassessed 2026-08-01 during os-sdlc sandbox retirement triage: general unreachability analysis is likely too broad for a rubocop cop; the narrower guard-clause-shape version (candidate b above) is the only variant that's concretely implementable as a cop. Needs a decision on which variant to pursue before implementation. ## Implementation plan Not decided -- general mutation-testing gate vs. narrow AST cop is an open call.
Author
Owner

This was generated by AI during triage.

Recommendation for maintainer: pursue option (b), the narrow AST cop, not mutation testing. Mutant is slow and flaky against this repo's minitest suite, and general unreachability-given-a-guard is undecidable — scope creep for a cop. The narrow shape (raise-on-empty? guard, later branch re-testing the same predicate with no intervening reassignment) is a small, mechanical Sdlc::UnreachableGuardedBranch cop, consistent with this repo's existing single-file cops. This resolves the open call; ready to implement as scoped.

> *This was generated by AI during triage.* Recommendation for maintainer: pursue option (b), the narrow AST cop, not mutation testing. Mutant is slow and flaky against this repo's minitest suite, and general unreachability-given-a-guard is undecidable — scope creep for a cop. The narrow shape (raise-on-empty? guard, later branch re-testing the same predicate with no intervening reassignment) is a small, mechanical Sdlc::UnreachableGuardedBranch cop, consistent with this repo's existing single-file cops. This resolves the open call; ready to implement as scoped.
Author
Owner

This was generated by AI during triage.

Implemented via os-sdlc pipeline (APPROVE). Narrow AST cop variant (candidate b per triage): Sdlc/Structural/UnreachableBranchAfterGuard. Merged to main in b7c2b66.

> *This was generated by AI during triage.* Implemented via os-sdlc pipeline (APPROVE). Narrow AST cop variant (candidate b per triage): Sdlc/Structural/UnreachableBranchAfterGuard. Merged to main in b7c2b66.
jared 2026-08-01 20:22:30 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#201
No description provided.