Widen ParameterListSignalsMissingObject to count keys read from **opts #1448

Closed
opened 2026-10-27 21:57:24 +00:00 by jared · 4 comments
Owner

Problem

The cop Sdlc/Structural/ParameterListSignalsMissingObject counts **opts as one parameter.
A method can read many keys from **opts and never fire.
The real site that motivated the cop used this dodge for one commit's worth of growth.

Observed

Analysis: docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md, option B.
A probe of the widened rule over plugins/ (gate config plugins/os-sdlc/.rubocop.yml) on 2026-10-28 found 3 new hits, all true positives. They are fixed on main before this ticket runs: plugins/os-backlog/lib/backlog/issues.rb (Issues#create now takes a Backlog::IssueDraft), plugins/os-backlog/tests/support/file_tracker_sandbox.rb, and plugins/os-sdlc/eval/ticket-takedown/test/run_support.rb (RunSupport::CritiqueReply).
Three hits in plugins/os-context extensionless scripts exist on main before the widening; they are not part of this ticket.

Reproduce

n/a: this is a widening of a cop; the matcher is plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb.

Approach

For a def/defs whose args hold a named **rest parameter, collect the distinct symbol keys read from it in the method body as rest[:key] or rest.fetch(:key, ...). The **rest parameter then counts as the number of distinct keys read, minimum one (a **rest that only passes through still counts one).
Rule from Jared: every new hit must be a true positive, and no Exclude lists. Carve-outs go in the matcher.
The cop message does not change. Update the lesson signal in plugins/os-sdlc/lint-lessons/sdlc-structural-parameter-list-signals-missing-object.yml to say a **rest parameter counts as the keys the body reads from it.

Required work:

  1. Count keys read from a **rest parameter in the matcher — check: present kwrestarg in plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb

Acceptance criteria

  1. Given a def with 3 keyword parameters and **opts whose body reads opts[:d] and opts[:e], when the cop runs, then it reports one offense that says 5 parameters.
  2. Given a def with 3 keyword parameters and **opts whose body reads opts.fetch(:d) and opts.fetch(:e, nil), when the cop runs, then it reports one offense.

Owner sketch

class RuboCop::Cop::Sdlc::Structural::ParameterListSignalsMissingObject < RuboCop::Cop::Metrics::ParameterLists
  def on_args(node)        # count = args_count(node) + extra keys hidden behind **rest
  def hidden_rest_keys(node) # distinct rest[:key] / rest.fetch(:key) reads in the def body, minus the one slot
end

Origin

  • Trigger: Jared ruled "B for four cops" on the inc 7 widenings of the lint-cops track (handoff .cc-os/os/handoffs/2026-10-27-1542-lint-cops-track.md).
  • Improvised this session: none
  • Chain: cop misses the **opts dodge ← cop counts **opts as one parameter ← DESIGN (docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md)
  • Root candidate: none found; searched ParameterListSignalsMissingObject, opts, **opts, parameter_list_signals_missing_object
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb
  • Session: 9f415790-a6bd-4850-8d70-3dd45004ce2b
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9f415790-a6bd-4850-8d70-3dd45004ce2b.jsonl
## Problem The cop `Sdlc/Structural/ParameterListSignalsMissingObject` counts `**opts` as one parameter. A method can read many keys from `**opts` and never fire. The real site that motivated the cop used this dodge for one commit's worth of growth. ## Observed Analysis: `docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md`, option B. A probe of the widened rule over `plugins/` (gate config `plugins/os-sdlc/.rubocop.yml`) on 2026-10-28 found 3 new hits, all true positives. They are fixed on main before this ticket runs: `plugins/os-backlog/lib/backlog/issues.rb` (`Issues#create` now takes a `Backlog::IssueDraft`), `plugins/os-backlog/tests/support/file_tracker_sandbox.rb`, and `plugins/os-sdlc/eval/ticket-takedown/test/run_support.rb` (`RunSupport::CritiqueReply`). Three hits in `plugins/os-context` extensionless scripts exist on main before the widening; they are not part of this ticket. ## Reproduce n/a: this is a widening of a cop; the matcher is `plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb`. ## Approach For a `def`/`defs` whose args hold a named `**rest` parameter, collect the distinct symbol keys read from it in the method body as `rest[:key]` or `rest.fetch(:key, ...)`. The `**rest` parameter then counts as the number of distinct keys read, minimum one (a `**rest` that only passes through still counts one). Rule from Jared: every new hit must be a true positive, and no Exclude lists. Carve-outs go in the matcher. The cop message does not change. Update the lesson `signal` in `plugins/os-sdlc/lint-lessons/sdlc-structural-parameter-list-signals-missing-object.yml` to say a `**rest` parameter counts as the keys the body reads from it. Required work: 1. Count keys read from a `**rest` parameter in the matcher — check: present `kwrestarg` in `plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb` ## Acceptance criteria 1. Given a def with 3 keyword parameters and `**opts` whose body reads `opts[:d]` and `opts[:e]`, when the cop runs, then it reports one offense that says 5 parameters. 2. Given a def with 3 keyword parameters and `**opts` whose body reads `opts.fetch(:d)` and `opts.fetch(:e, nil)`, when the cop runs, then it reports one offense. ## Owner sketch ```ruby class RuboCop::Cop::Sdlc::Structural::ParameterListSignalsMissingObject < RuboCop::Cop::Metrics::ParameterLists def on_args(node) # count = args_count(node) + extra keys hidden behind **rest def hidden_rest_keys(node) # distinct rest[:key] / rest.fetch(:key) reads in the def body, minus the one slot end ``` ## Origin - Trigger: Jared ruled "B for four cops" on the inc 7 widenings of the lint-cops track (handoff `.cc-os/os/handoffs/2026-10-27-1542-lint-cops-track.md`). - Improvised this session: none - Chain: cop misses the `**opts` dodge ← cop counts `**opts` as one parameter ← DESIGN (docs/lint-lessons/analyses/sdlc-structural-parameter-list-signals-missing-object.md) - Root candidate: none found; searched ParameterListSignalsMissingObject, opts, **opts, parameter_list_signals_missing_object - Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb - Session: 9f415790-a6bd-4850-8d70-3dd45004ce2b - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9f415790-a6bd-4850-8d70-3dd45004ce2b.jsonl
Author
Owner

Blocked by #1363 (FP carve-out on the same cop). Remove waiting when #1363 closes.

Blocked by #1363 (FP carve-out on the same cop). Remove `waiting` when #1363 closes.
Author
Owner

#1363 is closed (invalid: the two named hits were true positives, fixed on main by extraction in 51a91034 and 9914036d; the cop matcher did not change). #1448 is unblocked. The baseline sweep of Sdlc/Structural/ParameterListSignalsMissingObject over plugins/ on 2026-10-28 is 0 hits. The cop is at plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb (not cops/ as some older text says).

#1363 is closed (invalid: the two named hits were true positives, fixed on main by extraction in 51a91034 and 9914036d; the cop matcher did not change). #1448 is unblocked. The baseline sweep of Sdlc/Structural/ParameterListSignalsMissingObject over plugins/ on 2026-10-28 is 0 hits. The cop is at plugins/os-sdlc/lib/os_sdlc/cops/structural/parameter_list_signals_missing_object.rb (not cops/ as some older text says).
Author
Owner

Work started on branch ticket-1448 (worktree .claude/worktrees/ticket-1448). Three new hits of the widened rule were fixed on main first in 36b80f97 (IssueDraft, sandbox helper, RunSupport::CritiqueReply).

Work started on branch ticket-1448 (worktree .claude/worktrees/ticket-1448). Three new hits of the widened rule were fixed on main first in 36b80f97 (IssueDraft, sandbox helper, RunSupport::CritiqueReply).
Author
Owner

Resolution

Done: Widened ParameterListSignalsMissingObject: a **rest parameter counts as the distinct keys the body reads with rest[:key] or rest.fetch(:key), at least one (8ecedb1f). Fixed the 3 new true-positive hits first by passing built value objects: Backlog::IssueDraft for Issues#create and the FileTrackerSandbox helper, RunSupport::CritiqueReply for the takedown critique fixture (36b80f97). Added must-not-fire cases (one distinct key; forward-only) and reflowed the lesson signal (5b80a126). Pipeline implementation 207 complete in 4 min 18 s, no retries.

Evidence: Main 5b80a126 pushed. os-sdlc suite 2869 runs 0 failures; os-backlog 344 runs 0 failures; takedown eval tests green. Cop over plugins/ with plugins/os-sdlc/.rubocop.yml: no new hits; only the 3 os-context hits that exist before the widening remain.

Follow-ups: #1455 fix the 3 pre-existing os-context hits

## Resolution **Done:** Widened ParameterListSignalsMissingObject: a **rest parameter counts as the distinct keys the body reads with rest[:key] or rest.fetch(:key), at least one (8ecedb1f). Fixed the 3 new true-positive hits first by passing built value objects: Backlog::IssueDraft for Issues#create and the FileTrackerSandbox helper, RunSupport::CritiqueReply for the takedown critique fixture (36b80f97). Added must-not-fire cases (one distinct key; forward-only) and reflowed the lesson signal (5b80a126). Pipeline implementation 207 complete in 4 min 18 s, no retries. **Evidence:** Main 5b80a126 pushed. os-sdlc suite 2869 runs 0 failures; os-backlog 344 runs 0 failures; takedown eval tests green. Cop over plugins/ with plugins/os-sdlc/.rubocop.yml: no new hits; only the 3 os-context hits that exist before the widening remain. **Follow-ups:** #1455 fix the 3 pre-existing os-context hits
jared closed this issue 2026-10-28 06:39:13 +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#1448
No description provided.