Give os-sdlc cops/ a Zeitwerk loader so tests and .rubocop.yml stop naming each cop file #1393
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#1393
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
plugins/os-sdlc/lib/os_sdlc_loader.rb:16runsloader.ignore(File.join(os_sdlc_dir, "cops")). No loader autoloadsRuboCop::Cop::Sdlc::*. Each file that needs a cop must name it withrequire_relative.Today:
plugins/os-sdlc/tests/cops/carriesrequire_relative "../../lib/os_sdlc/cops/<cop>". 19 of them wrap it inbegin ... rescue LoadError; nil; end, which hides a missing file.plugins/os-sdlc/.rubocop.ymlhas arequire:list of 39 per-cop entries.cops/carry about 130 top-levelrequire_relativecalls to their helpers.detector/files require cop files:detector/reach_through.rb:3,holders.rb:3-4,inward_edges.rb:3-4,error_lineage/rescue_index.rb:3,effect_sites.rb:3.detector/cop_sites.rb:4requirescops/cop_source.Reproduce
n/a: design change. Count with
grep -rc 'require_relative.*cops/' plugins/os-sdlc/tests/cops.Approach
Investigation, then change. Untested sketch: add a second Zeitwerk loader for
cops/withnamespace: RuboCop::Cop::Sdlc. Require it once fromtest_helperand as the single.rubocop.ymlrequireentry.Decided 2026-10-26: the cop namespaces are mixed (Structural 128 files, Dry 18, Minitest 7, Sequel 6, plain
Sdlc5) and the flatcops/paths do not name them. #1397 moves the files into department folders (cops/structural/,cops/dry/, ...) so each path names its constant; this ticket starts after #1397. The loader lives in a newlib/os_sdlc_cops_loader.rbbesidelib/os_sdlc_loader.rb, outside theOsSdlcloader's root. Cops register on class definition, so the loader callseager_loadunder rubocop.Required work:
rubocop --show-cops | grep Sdlc/count unchanged).require_relativelines from cop tests, including the 19rescue LoadErrorblocks..rubocop.ymlrequire:list to one entry.cops/anddetector/require_relativecalls that the loader makes redundant. Adetector/file that needs a cop requiresos_sdlc_cops_loaderonce in place of its per-cop lines..rubocop.ymlrequires 40 today, and the 8 others are the sweep-tier cops that only.rubocop-sweep.ymlrequires:Sdlc/Dry/RepeatedPathLiteral,Sdlc/Structural/EffectInModel,ForwardingClass,InwardDependency,ReachThroughChain,RescueSite,UnderscoredParameter,UnlayeredConstant. SetEnabled: falsefor each in.rubocop.yml, with no*Pathparameter (lint/worklist_rubocop_config.rbrewrites*Pathparameters per layer). Collapse the.rubocop-sweep.ymlrequire:list to the loader entry and keep itsEnabled: trueentries;lint/sweeping.rblayers the sweep config after.rubocop.yml, so itsEnabled: truemust win.Acceptance criteria
require_relative ".../cops/..."lines underplugins/os-sdlc/tests/cops/.rubocop --show-copswith.rubocop.yml, when the Sdlc cops whoseEnabledis not false are listed, then the list equals the list before the change (38 cops on 2026-10-26;--show-copsalso lists disabled cops, so count enabled ones)..rubocop-sweep.ymllayered after.rubocop.yml, aslint/sweeping.rbruns it, when the enabled Sdlc cops are listed, then each of the 8 sweep-tier cops is enabled. (Corrected 2026-10-26 during implementation 169:lint/sweeping.rbis the only code consumer of the sweep config, and it layers the file and passesonly:; the standalone-c .rubocop-sweep.ymlcount is not an interface.)Owner sketch
Blocking edges
Blocked by #1397.
Origin
require_relativein every test ←loader.ignoreofcops/inplugins/os-sdlc/lib/os_sdlc_loader.rb:16← DESIGN (loader file, line 16)VERDICT: CREATE
Related: #1367 (being rewritten into Sdlc/RequireInsideCode).
Work started on branch ticket-1393 through /os-sdlc:implement (poodr-ticket-implementation).
Blocked by #1397. The flat cops/ layout cannot map to RuboCop::Cop::Sdlc under Zeitwerk; Jared chose to move cop files into department folders first (#1397, fast-batch). Owner sketch and blocking edge added to the body. Implement run not opened; branch ticket-1393 removed with no changes.
Fact for the loader (measured 2026-10-26 in fast-batch-16): rubocop --show-cops lists 40 Sdlc cops today, but a Zeitwerk eager_load of all of cops/ registers 48. .rubocop.yml does not require 8 cop files. A loader that eager-loads every file registers those 8, and RuboCop enables a cop that has no config, so lint results change. Acceptance criterion 2 (count unchanged) catches this. The run must either disable the 8 in .rubocop.yml or make a decision to enable them.
Work resumed on branch ticket-1393 through /os-sdlc:implement (poodr-ticket-implementation), after #1397 merged.
Resolution
Done: OsSdlc.cops_loader (lib/os_sdlc_cops_loader.rb) eager-loads cops/ under RuboCop::Cop::Sdlc. .rubocop.yml and .rubocop-sweep.yml each require only the loader; the 8 sweep-tier cops are disabled in .rubocop.yml. test_helper and detector.rb require the loader once. Per-cop require_relative lines and 19 rescue LoadError blocks removed from tests/cops, tests/support, tests/detector, cops/ and detector/.
Evidence: main
2248b680(implementation 169, hand-finished after escalations 77 and 78). Full suite 2675 runs 0 failures; rubocop offenses identical to main (22 pre-existing, 0 new); --show-cops: 38 Sdlc cops enabled before and after; 0 require_relative to cops/ under tests/cops; new test fails when eager_load is removed; design audit: 8 findings fixed, 3 answered.Follow-ups: jared/decision-model#10 (copied cop require: list; replace with the loader entry). Suite wall time is over its 60 s budget on main and on this branch; measurements on a loaded machine were inconclusive (main 66-78 s, branch 85-87 s); none filed. Redundant require "rubocop" lines in about 15 cop files: dropped (harmless).