Sdlc/Structural/ParameterListSignalsMissingObject: exempt value-object initializers and fixture builders by shape #1363

Closed
opened 2026-10-25 21:23:20 +00:00 by jared · 1 comment
Owner

Problem

The cop Sdlc/Structural/ParameterListSignalsMissingObject flags any def or block with more than 4 parameters.
It exempts only Struct/Data initialize and lambda/proc args.
The prescribed fix (extract a value object) is not always correct: a plain-class value-object initialize already is the object.

Found by the #1325 zero-false-positive audit (docs/plans/class-length-family/sdlc-cop-audit.md).

Observed

Counterexample 1: plugins/os-sdlc/lib/os_sdlc/map/edge.rb:19. Edge#initialize(verdict:, to:, bound:, note:, progress_reset:) only assigns ivars. The fix would wrap a value object in a value object.
Counterexample 2: plugins/os-me/test/candidate_fakes.rb:24, a fixture-row builder whose body is one hash built from its parameters.
The MSG hedge ("stop when no concept exists") admits the false positives. 22 hits.

Reproduce

n/a: the cop matcher is at plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb:28-36; run the cop on plugins/os-sdlc/lib/os_sdlc/map/edge.rb.

Approach

Carve-outs go in the cop matcher, never in a config Exclude list or a test-path exclusion.
Skip an initialize whose body is only @x = x assignments of its own parameters.
Skip a def whose body is one hash or new literal built from its parameters.
Remove the "stop and say so" hedge from the MSG once the carve-outs exist.

Required work:

  1. Add the two carve-outs to the cop matcher and drop the hedge — check: absent stop in plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb

Acceptance criteria

  1. Given an initialize whose body only assigns its parameters to ivars, when the cop runs, then it reports no offense.
  2. Given a def whose body is one hash literal built from its parameters, when the cop runs, then it reports no offense.
  3. Given a def with 5 parameters and any other body, when the cop runs, then it reports an offense.

Origin

  • Trigger: #1325 zero-false-positive audit of the Sdlc cops
  • Improvised this session: none
  • Chain: false positive ← matcher has no value-object or builder carve-out ← DESIGN (plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb)
  • Root candidate: none found; searched ParameterListSignalsMissingObject
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb
  • Session: eb98cdcd-6783-46a0-b7df-cf18a8fe2a56
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1325/eb98cdcd-6783-46a0-b7df-cf18a8fe2a56.jsonl
    VERDICT: CREATE
## Problem The cop `Sdlc/Structural/ParameterListSignalsMissingObject` flags any def or block with more than 4 parameters. It exempts only Struct/Data `initialize` and lambda/proc args. The prescribed fix (extract a value object) is not always correct: a plain-class value-object `initialize` already is the object. Found by the #1325 zero-false-positive audit (docs/plans/class-length-family/sdlc-cop-audit.md). ## Observed Counterexample 1: `plugins/os-sdlc/lib/os_sdlc/map/edge.rb:19`. `Edge#initialize(verdict:, to:, bound:, note:, progress_reset:)` only assigns ivars. The fix would wrap a value object in a value object. Counterexample 2: `plugins/os-me/test/candidate_fakes.rb:24`, a fixture-row builder whose body is one hash built from its parameters. The MSG hedge ("stop when no concept exists") admits the false positives. 22 hits. ## Reproduce n/a: the cop matcher is at `plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb:28-36`; run the cop on `plugins/os-sdlc/lib/os_sdlc/map/edge.rb`. ## Approach Carve-outs go in the cop matcher, never in a config Exclude list or a test-path exclusion. Skip an `initialize` whose body is only `@x = x` assignments of its own parameters. Skip a def whose body is one hash or `new` literal built from its parameters. Remove the "stop and say so" hedge from the MSG once the carve-outs exist. Required work: 1. Add the two carve-outs to the cop matcher and drop the hedge — check: absent `stop` in `plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb` ## Acceptance criteria 1. Given an `initialize` whose body only assigns its parameters to ivars, when the cop runs, then it reports no offense. 2. Given a def whose body is one hash literal built from its parameters, when the cop runs, then it reports no offense. 3. Given a def with 5 parameters and any other body, when the cop runs, then it reports an offense. ## Origin - Trigger: #1325 zero-false-positive audit of the Sdlc cops - Improvised this session: none - Chain: false positive ← matcher has no value-object or builder carve-out ← DESIGN (plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb) - Root candidate: none found; searched ParameterListSignalsMissingObject - Where: plugins/os-sdlc/lib/os_sdlc/cops/parameter_list_signals_missing_object.rb - Session: eb98cdcd-6783-46a0-b7df-cf18a8fe2a56 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1325/eb98cdcd-6783-46a0-b7df-cf18a8fe2a56.jsonl VERDICT: CREATE
Author
Owner

Resolution

Done: Closed as invalid, not implemented. The two hits the ticket names were true positives, not false positives. The cop's prescription (extract a value object) found a real object at each site. Ruling: predicted (os-me predict, band 80, confidence 75), judgment tier, AFK.

Evidence: edge.rb: commit 51a91034 extracted LoopBound (bound and progress_reset travel together); Edge#initialize now takes 4 keywords. candidate_fakes.rb: commit 9914036d made RulingRow a Data.define (already exempt). Sweep of the cop over all 2664 .rb files under plugins/ on main 2026-10-28 with plugins/os-sdlc/.rubocop.yml: 0 hits. A synthetic probe (ivar-only initialize, hash-literal builder, call body, 5 params each) gives 3 offenses, so the cop is active. Carve-out 1 (ivar-only initialize) would also pass a service constructor that stores 5 collaborators, and it would have hidden the Edge clump; the smell analysis docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md step 8 warned about this. The ticket's cop path was also stale (now cops/structural/).

Follow-ups: #1448 (count **opts keys) is unblocked. The MSG hedge ('stop and say so') stays; it has no effect on matching.

## Resolution **Done:** Closed as invalid, not implemented. The two hits the ticket names were true positives, not false positives. The cop's prescription (extract a value object) found a real object at each site. Ruling: predicted (os-me predict, band 80, confidence 75), judgment tier, AFK. **Evidence:** edge.rb: commit 51a91034 extracted LoopBound (bound and progress_reset travel together); Edge#initialize now takes 4 keywords. candidate_fakes.rb: commit 9914036d made RulingRow a Data.define (already exempt). Sweep of the cop over all 2664 .rb files under plugins/ on main 2026-10-28 with plugins/os-sdlc/.rubocop.yml: 0 hits. A synthetic probe (ivar-only initialize, hash-literal builder, call body, 5 params each) gives 3 offenses, so the cop is active. Carve-out 1 (ivar-only initialize) would also pass a service constructor that stores 5 collaborators, and it would have hidden the Edge clump; the smell analysis docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md step 8 warned about this. The ticket's cop path was also stale (now cops/structural/). **Follow-ups:** #1448 (count **opts keys) is unblocked. The MSG hedge ('stop and say so') stays; it has no effect on matching.
jared closed this issue 2026-10-28 06:10:09 +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#1363
No description provided.