Split Sdlc/Structural/InwardDependency into one cop per offense kind #1153
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#1153
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/InwardDependencyreports two different offense kinds under one cop name.on_constreports an inward edge (%{constant} (layer %{outer}) is referenced from layer %{inner}. ...).on_new_investigationreports an unmapped ledger file (%{constant} has no ledger row with a layer role; add it to %{ledger}). One is design debt in the code. The other is a gap in the CRC ledger. A reader cannot count, enable, or route one kind without the other, and the cop name describes only the first kind.Reproduce
n/a: design ticket; both kinds are in plugins/os-sdlc/lib/os_sdlc/cops/inward_dependency.rb (
MESSAGEandUNMAPPED_MESSAGE).Approach
Sdlc/Structural/InwardDependencykeeps the inward-edge kind only. A new copSdlc/Structural/UnlayeredConstantreports the unmapped-ledger-file kind with the same message. Both cops read the sameLedgerPathparameter and the same layer map; the shared ledger reading (ROLE_LAYER,layer_map,ledger_path,Ledger,LayerMap) moves to one owner that both cops use, so neither cop depends on the other.OsSdlc::CollaboratorPass::InwardEdgesreads the layer map from that owner.Required work:
Sdlc/Structural/UnlayeredConstantcop with the unmapped message — check: presentUnlayeredConstantinplugins/os-sdlc/lib/os_sdlc/cops/unlayered_constant.rbInwardDependency— check: absentUNMAPPED_MESSAGEinplugins/os-sdlc/lib/os_sdlc/cops/inward_dependency.rbLedgerPath, in the sweep tier — check: presentSdlc/Structural/UnlayeredConstantinplugins/os-sdlc/.rubocop-sweep.ymllint-lessons/sdlc-structural-inward-dependency.yml— check: presentSdlc/Structural/UnlayeredConstantinplugins/os-sdlc/lint-lessons/*.ymlskills/fix-lints/SKILL.md,skills/crc-refactor/references/*.md) — check: presentUnlayeredConstantinplugins/os-sdlc/skills/fix-lints/SKILL.mdRejected: keep one cop with a per-kind config switch — two kinds under one name is the problem.
Acceptance criteria
Sdlc/Structural/UnlayeredConstantreports it with the unmapped message andSdlc/Structural/InwardDependencyreports nothing for it.Sdlc/Structural/InwardDependencyreports the edge andSdlc/Structural/UnlayeredConstantreports nothing for it.bin/lint-sweepruns from plugins/os-sdlc/, then theInwardDependencyoffense set equals the set before the split.bin/collaborator-pass measure, when it reads inward edges, then it reports the same edges as before the split.Owner sketch
Retired tests
plugins/os-sdlc/tests/cops/inward_dependency_test.rb#test_ledger_lacking_own_constant_reports_unmapped_offense_on_first_constant
Origin
VERDICT: CREATE (backlog search only; user-requested 2026-10-19)
Work started on branch ticket-1153 through /os-sdlc:implement.
Resolution
Done: Sdlc/Structural/InwardDependency now reports inward edges only; new cop Sdlc/Structural/UnlayeredConstant reports a lib constant with no ledger row with a layer role. Shared ledger reading moved to RuboCop::Cop::Sdlc::Structural::LayerLedger (Ledger, LayerMap), used by both cops and by CollaboratorPass::InwardEdges. Both cops in .rubocop-sweep.yml with LedgerPath; lint lesson sdlc-structural-unlayered-constant.yml; fix-lints and crc-refactor skill text name both cops.
Evidence: Merged to main (
3f9e2dd5; implementation 75 commit plusd3e0d4d3for the moved files' deletions). Suite 2115 runs, 0 failures. bin/lint-sweep from plugins/os-sdlc/ and repo root: InwardDependency 175 offenses (124 unique edges) each, identical, equal to the pre-split set on the same main (the 176->175 drop is FlayCheck deleted by #1141); UnlayeredConstant 0; 0 crash lines from either cop.Follow-ups: Runner commit omitted the moved files' deletions: occurrence posted on #916 (skeptic OCCURRENCE). No other follow-ups.