Sdlc/Structural/UnderscoredParameter: report only a def that the same file calls #1370
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#1370
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Sdlc/Structural/UnderscoredParametertells the agent: "Delete it and stop passing it, or read it." That fix is correct only when the agent can change every caller. The cop sees one file. When the caller is in another file, the arity is often set by a framework, a protocol that sibling implementers read, or a dispatch table, and deletion breaks the caller. The cop runs only inplugins/os-sdlc/.rubocop-sweep.yml.Found by the #1325 zero-false-positive audit (docs/plans/class-length-family/sdlc-cop-audit.md). Shapes measured on main
4a0fc41d, 2026-10-26, with the sweep config over every file inplugins/(25 offenses):selfplugins/cc-architect/scripts/plugin_config/operations/audit.rb:121privatecheck_installed(_name, key), called only at:72; sweep hitplugins/os-backlog/tests/project_index_test.rb:54plugins/os-sdlc/lib/os_sdlc/boot/onboarding.rb:17def self.handle_no_command_error(command, _has_namespace = $thor_runner)plugins/os-sdlc/tests/daemon/lsp_session_reopen_test.rb:31def request(_method, params)plugins/os-sdlc/tests/gate_test.rb:62->(_outcome, classification:) { ... }method(:x), or lambda) called from another fileTakedown::StepList#steps(run, history)besideProbePlan#steps(_run, history)), and the fix needs new caller machinery that the cop cannot seeplugins/os-sdlc/lib/os_sdlc/crc/shares/run.rb:10"verdicts-merge" => ->(path, _run) { VerdictMerge.new(path) };plugins/os-sdlc/lib/os_sdlc/dispatch/rerouting.rb:10The #1317 sweep of os-backlog, os, os-adr, os-aidd-lint, and os-me finds 1 offense (
plugins/os-backlog/tests/project_index_test.rb:54). It is a true positive.Approach
Fix by shape in the cop matcher. Never use a config Exclude list or a test-path exclusion.
Rule: the cop checks a
defordefsonly when the same file holds a send of its method name with no receiver or with aselfreceiver. It no longer checks lambdas. The existing parameter test does not change: report an underscored parameter when the definition reads another parameter.Measured effect (scratch simulation that patches the cop, main
4a0fc41d): offenses overplugins/go from 25 to 4. The 4 kept are the true positives above (audit.rb:121,plugins/os-adr/eval-c/bin/check:226,project_index_test.rb:54,plugins/os-sdlc/lib/os_sdlc/implementation/lifecycle.rb:42). The 21 removed are all false positives. The #1317 sweep count stays 1.The lesson's dispatch-table example (from fast-batch-1, docs/crc/os-sdlc/fast-batch-1/finding-c-underscored-parameter.md) no longer fires. That shape has a correct fix only when the table's caller is in this codebase, and no AST shape in one file tells that case apart from a protocol-forced lambda. The cop gives up that recall to keep every offense true, as in ruling R2 (docs/plans/class-length-family/HANDOFF.md).
Required work:
plugins/os-sdlc/lib/os_sdlc/cops/structural/underscored_parameter.rb, check adefordefsonly whenprocessed_source.astholds asendorcsendof the same method name whose receiver is nil orself. Delete theon_blocklambda check.check: absent
def on_blockinplugins/os-sdlc/lib/os_sdlc/cops/structural/underscored_parameter.rbplugins/os-sdlc/tests/cops/underscored_parameter_test.rb, change the two lambda fixtures that expect an offense (test_reports_an_underscored_lambda_parameter_beside_read_ones,test_reports_an_underscored_parameter_inside_a_destructured_lambda_parameter) to tests that expect no offense, and add an in-file call to the fixtures oftest_reports_an_underscored_def_parameter_beside_read_onesandtest_reports_an_underscored_keyword_rest_parameterso that they still fire. Add must-pass fixtures: a Thor hookdef self.handle_no_command_error(command, _has_namespace = nil)with no caller in the file, a test doubledef call(_repo, target) = target, and a method that the file calls only on another receiver (obj.call(repo, target)). Add must-fire fixtures: a private helper called with no receiver, a method called throughself., a destructured def parameterdef show(io, (action, _id))called in the file, and a call that comes before thedef.check: present
handle_no_command_errorinplugins/os-sdlc/tests/cops/underscored_parameter_test.rbplugins/os-sdlc/lint-lessons/sdlc-structural-underscored-parameter.yml, state insignalthat the same file calls the method (today it says "A method or lambda"). Rewritedecisionandcorrectionfor that shape: the callers are in the file, so delete the parameter and the argument at each call; drop the "second constructor on the table entry" advice. Replace the dispatch-tableexamplewith a method that the same file calls (before:check_installed(_name, key)called ascheck_installed(name, key); after:check_installed(key)). Runbin/refresh-pluginsafter the edit.check: present
same file callsinplugins/os-sdlc/lint-lessons/sdlc-structural-underscored-parameter.ymldocs/plans/class-length-family/sdlc-cop-audit.md, update the UnderscoredParameter row (line 63) and line 15: the cop path isplugins/os-sdlc/lib/os_sdlc/cops/structural/underscored_parameter.rb, and the cop now checks only a def that the same file calls.check: absent
os_sdlc/cops/underscored_parameter.rbindocs/plans/class-length-family/sdlc-cop-audit.mddocs/implementation-status/os-sdlc.md.check: present
#1370indocs/implementation-status/os-sdlc.mdAcceptance criteria
def self.handle_no_command_error(command, _has_namespace = nil)that readscommandand that no line of the file calls, when the cop runs, then it reports no offense.->(path, _run) { VerdictMerge.new(path) }, as a hash value, a call argument, or a local variable, when the cop runs, then it reports no offense.def check_installed(_name, key)that readskey, andcheck_installed(name, key)in the same file, when the cop runs, then it reports_name.def record(_result, text)that readstext, andself.record(result, text)in the same file, when the cop runs, then it reports_result.bundle exec rubocop -c .rubocop-sweep.yml --only Sdlc/Structural/UnderscoredParameter ../../pluginsrun fromplugins/os-sdlc, when it runs after the change, then it reports exactly 4 offenses, ataudit.rb:121,check:226,project_index_test.rb:54, andlifecycle.rb:42.Owner sketch
RuboCop::Cop::Sdlc::Structural::UnderscoredParameter(existing) owns the decision. It already partitions parameters and checks reads; it adds one question, "does this file call the method by name?", before it reports. No new object.In scope / out of scope
lifecycle.rb:42needsplugins/os-sdlc/lib/os_sdlc/implementation/landing.rb:51to stop passingroot:..rubocop-sweep.ymlto.rubocop.yml. The tier change belongs to the sweep-promotion process (#1317), not to this false-positive fix.docs/crc/os-sdlc/fast-batch-1/finding-c-underscored-parameter.md. It is a dated record of fast batch 1; the History row of this ticket records that the two Boot lambdas it fixed are no longer in the cop's shape.plugins/): a lambda that its own file calls, and calls throughsend(:name)orpublic_send.Blocking edges
None. One implement run.
Origin
plugins/os-sdlc/lib/os_sdlc/cops/structural/underscored_parameter.rb)VERDICT: CREATE
Sdlc/Structural/UnderscoredParameter: carve out arity forced by a protocol or frameworkto Sdlc/Structural/UnderscoredParameter: report only a def that the same file callsDecomposed AFK on 2026-10-26 (ticket-decompose). Measured on main
4a0fc41dwith a scratch patch of the cop: 25 offenses overplugins/become 4, all true positives; the 21 removed are all false positives. #1317 sweep count stays 1 (true positive).AFK decisions:
self); stop checking lambdas", in place of the original carve-out list (hook names, callback lambdas, test doubles). Reason: one AST question covers every false-positive shape and keeps every true positive. Confidence 0.75.crc/shares/run.rb:9-11, whose fix needs new caller machinery)..rubocop.ymland the fixes of the 4 true positives are out of scope (sweep-promotion process, #1317). Confidence 0.8.Work started on branch ticket-1370 via /os-sdlc:implement.
Implementation 172 failed at the test-reviewer node (dispatch 1503, reason verdict:error). Cause: required work R2 and acceptance criteria 3-4 ask for 4 tests of behavior the cop already has (private helper, self receiver, destructured def, call before def). They are green before any production change, and the red-first round requires every new test to be red; the pipeline has no exemption for preservation tests. Reviewer 1501 objected (objection 161); test-writer 1502 could not fix it with a test-only edit; reviewer 1503 settled error. Worktree ticket-1370 is kept: 11 new tests in tests/cops/underscored_parameter_test.rb, 7 red as intended, 4 green; no production change. Recovery: hand-finish (production change makes all 11 pass) or move the 4 preservation tests out of the red round. Labeled waiting.