os-sdlc lint rule: parameter threading through private methods (wants instance state) #87
Labels
No labels
P0
P1
P2
P3
bug
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
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#87
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?
Context
Sandi Metz review of
plugins/os_sdlc/lib/os_sdlc/issue_source.rbfoundrunnerthreadedthrough a chain of private class methods as a plain parameter — a smell for state that wants
an object of its own.
Problem
plugins/os-sdlc/lib/os_sdlc/issue_source.rb—runnerappears in the signature of everymethod in this call chain:
resolve_and_persist,tracker_from_git_remote, andforgejo_host?are allprivate_class_methods (line 97) that exist solely to keep passingrunnerone leveldeeper so
forgejo_host?can eventually callrunner.capture(...).runneris de factoinstance state being smuggled through parameter lists instead of being held by an object.
Detection
private_class_method(orprivate) method definitions in aclass/module body, and their parameter lists.
parameter of that exact name.
more private methods.
"runner is passed through 3+ private methods (resolve_and_persist, tracker_from_git_remote, forgejo_host?) -- extract an object that holds runner as instance state (e.g. a GitRemoteTracker initialized with runner:) instead of threading it through every private method's parameter list."Correction
Pass/fail examples
runner(or any other single parameter name) appearsin the signatures of
resolve_and_persist,tracker_from_git_remote, andforgejo_host?(3 private methods) as in the current file.GitRemoteTracker#initializetakesrunner:; every other method in the chain reads it from@runner.Provenance
Sandi Metz review of
issue_source.rb, cc-os session 2026-07-22 (organic finding — not acouncil/run finding).
Implementation plan
Custom RuboCop cop (batch-2 custom-cop slot; no stock cop counts repeated parameter names
across a class's private methods). Implemented directly by a Fable agent, with a Codex
review/audit before merge.
Implementation note (2026-07-22): the detection algorithm as specified correctly fires on MORE than the prose enumerates. On issue_source.rb it also flags
project(threaded through resolve_and_persist, tracker_from_config, tracker_from_git_remote), andrunner's chain includesbuild(4 methods, not 3). The rule is correct; the ticket narrative undercounted its own hits. Cop implemented as Sdlc/ParameterThreadedThroughPrivateMethods.Covered: Sdlc/Structural/ParameterThreadedThroughPrivateMethods shipped and enabled in .rubocop.yml with tests. ADR-0061 finalizes the os-sdlc lint program; closing per commit
8e88bbe.