Check a single-if initialize body in FormatValidationRaisingInInitialize #1709

Closed
opened 2026-11-12 07:53:11 +00:00 by jared · 2 comments
Owner

Problem

Sdlc/Structural/FormatValidationRaisingInInitialize does not check an initialize whose whole body is one if statement. validated_if_node calls body.each_descendant(:if), and each_descendant does not yield the receiver node. When the body is a single if, the body node is that if, so the cop never sees it. The cop then misses a raising format check in the simplest form of the smell.

Observed

  • A survivor-loop agent found the gap on 2026-11-12 while it wrote tests for #1703.
  • To reach the code under test, it added a second statement after each if in its test inputs.
  • Location: plugins/os-sdlc/lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb:27, body.each_descendant(:if) do |if_node|.

Reproduce

class Port
  def initialize(value)
    raise ArgumentError, "bad" unless value.match?(/\A\d+\z/)
  end
end

Run the cop on this source. It reports no offense. Add a statement @value = value after the raise line and run it again. The cop now reports the offense.

Approach

Required work: none beyond the acceptance criteria.

Acceptance criteria

  1. Given an initialize whose only statement is a raising format check on a parameter, when the cop runs, then it reports the same offense it reports when a second statement follows the check.

Owner sketch

class RuboCop::Cop::Sdlc::Structural::FormatValidationRaisingInInitialize
  def validated_if_node(body, derived_params)
end

Origin

  • Trigger: #1703 survivor loop, group E-L, 2026-11-12
  • Improvised this session: the test inputs add a trailing statement after the if
  • Chain: a single-if initialize is not checked ← each_descendant(:if) skips the body node itself ← DESIGN (lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb:27)
  • Root candidate: none found; searched FormatValidationRaisingInInitialize, format_validation, each_descendant, single if
  • Where: lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb
  • Parent: #1703
  • Session: 2677aa00-1973-4df6-b9c5-e317088f3ea3
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1708/2677aa00-1973-4df6-b9c5-e317088f3ea3.jsonl

VERDICT: CREATE (ticket-skeptic, 2026-11-12): real false negative in a shipped cop; the two open tickets on this cop cover other faults.

## Problem `Sdlc/Structural/FormatValidationRaisingInInitialize` does not check an `initialize` whose whole body is one `if` statement. `validated_if_node` calls `body.each_descendant(:if)`, and `each_descendant` does not yield the receiver node. When the body is a single `if`, the body node is that `if`, so the cop never sees it. The cop then misses a raising format check in the simplest form of the smell. ## Observed - A survivor-loop agent found the gap on 2026-11-12 while it wrote tests for #1703. - To reach the code under test, it added a second statement after each `if` in its test inputs. - Location: `plugins/os-sdlc/lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb:27`, `body.each_descendant(:if) do |if_node|`. ## Reproduce ```ruby class Port def initialize(value) raise ArgumentError, "bad" unless value.match?(/\A\d+\z/) end end ``` Run the cop on this source. It reports no offense. Add a statement `@value = value` after the `raise` line and run it again. The cop now reports the offense. ## Approach Required work: none beyond the acceptance criteria. ## Acceptance criteria 1. Given an `initialize` whose only statement is a raising format check on a parameter, when the cop runs, then it reports the same offense it reports when a second statement follows the check. ## Owner sketch ```ruby class RuboCop::Cop::Sdlc::Structural::FormatValidationRaisingInInitialize def validated_if_node(body, derived_params) end ``` ## Origin - Trigger: #1703 survivor loop, group E-L, 2026-11-12 - Improvised this session: the test inputs add a trailing statement after the `if` - Chain: a single-`if` initialize is not checked ← `each_descendant(:if)` skips the body node itself ← DESIGN (`lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb:27`) - Root candidate: none found; searched FormatValidationRaisingInInitialize, format_validation, each_descendant, single if - Where: lib/os_sdlc/cops/structural/format_validation_raising_in_initialize.rb - Parent: #1703 - Session: 2677aa00-1973-4df6-b9c5-e317088f3ea3 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1708/2677aa00-1973-4df6-b9c5-e317088f3ea3.jsonl VERDICT: CREATE (ticket-skeptic, 2026-11-12): real false negative in a shipped cop; the two open tickets on this cop cover other faults.
Author
Owner

Work started: os-sdlc pipeline on branch ticket-1709 (session 01fe836c).

Work started: os-sdlc pipeline on branch ticket-1709 (session 01fe836c).
Author
Owner

Resolution

Done: FormatValidationRaisingInInitialize now checks an initialize whose whole body is one raising if: validated_if_node uses body.each_node(:if), which visits the body node itself.

Evidence: Implementation 284 (9 dispatches, all pass, 4 min 54 s): d28458004 (lib) and c9691f64a (test + History row) on branch ticket-1709. Cop test file 18 runs, 0 failures; suite gate and survivor gate green.

Follow-ups: none

## Resolution **Done:** FormatValidationRaisingInInitialize now checks an initialize whose whole body is one raising if: validated_if_node uses body.each_node(:if), which visits the body node itself. **Evidence:** Implementation 284 (9 dispatches, all pass, 4 min 54 s): d28458004 (lib) and c9691f64a (test + History row) on branch ticket-1709. Cop test file 18 runs, 0 failures; suite gate and survivor gate green. **Follow-ups:** none <!-- os-backlog kind: resolution -->
jared closed this issue 2026-11-12 19:25:50 +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#1709
No description provided.