Lens proposal: lift cross-concept nested cop helpers to top level under Cops::Sdlc::Structural #1523

Closed
opened 2026-11-03 14:04:45 +00:00 by jared · 3 comments
Owner

Problem

Three helper objects are nested inside one cop but have callers in other cop concepts. Lens A2 says an object with callers in more than one concept is a top-level object. The nesting hides the shared role, and each new cop that needs a helper reaches into another cop's namespace. Structural::EdgeScope and Structural::EffectReach already show the correct top-level form.

Observed

The A2 lens challenge on #1511 (run 221) returned "code defect found". The contract-auditor had marked the break JUSTIFIED because the ticket asked for reuse of nested helpers; the challenge found that the ticket named SameFileDefs and EFFECT_CONSTANTS only, never Candidate, and that the other nested reuses are earlier A2 breaks, not a pattern to follow.

plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/condition.rb:35,42  PrecedenceInEdge::Candidate.unwrap
plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/facts.rb:15          QueryMethodReachesWrite::SameFileDefs
plugins/os-sdlc/lib/os_sdlc/cops/structural/precedence_in_edge.rb:17                   QueryMethodReachesWrite::SameFileDefs
plugins/os-sdlc/lib/os_sdlc/cops/structural/edge_scope.rb:14-15,65                     EffectInModel::EffectCall
plugins/os-sdlc/lib/os_sdlc/cops/structural/effect_reach/walk.rb:31                    EffectInModel::EffectCall

Reproduce

n/a: structure finding, the suite is the proof

Approach

Structure-only moves under RuboCop::Cop::Sdlc::Structural, one concept per commit, no behavior change, on the fast path.

Required work:

  1. Move QueryMethodReachesWrite::SameFileDefs to structural/same_file_defs.rb and update its callers (QueryMethodReachesWrite, PrecedenceInEdge, DomainEffectInEdge::Facts). — check: present class SameFileDefs in plugins/os-sdlc/lib/os_sdlc/cops/structural/same_file_defs.rb
  2. Move EffectInModel::EffectCall to structural/effect_call.rb and update its callers (EffectInModel, EdgeScope, EffectReach::Walk). — check: present class EffectCall in plugins/os-sdlc/lib/os_sdlc/cops/structural/effect_call.rb
  3. Extract the class methods PrecedenceInEdge::Candidate.unwrap and .slot_of into a top-level value (name to be ruled) and update the callers (PrecedenceInEdge Candidate, Presence, Guard; DomainEffectInEdge::Condition). Candidate itself stays nested. — check: absent PrecedenceInEdge::Candidate in plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/**/*.rb

Orchestrator work: rule the name of the unwrap value before item 3.

Acceptance criteria

  1. Given the os-sdlc suite at the current commit, when the three moves land, then the suite and rubocop stay green with no test change.
  2. Given any cop under cops/structural/, when it needs SameFileDefs, EffectCall, or the unwrap, then it references a top-level Structural:: constant, not another cop's nested constant.

Owner sketch

module RuboCop::Cop::Sdlc::Structural
  class SameFileDefs
  class EffectCall
  class UnwrappedNode  # name to be ruled
end

Origin

  • Trigger: /os-sdlc:implement 1511, run 221, contract-auditor LENS line on A2; challenged per references/lens-challenge-checklist.md
  • Improvised this session: none; signal line appended to plugins/os-sdlc/lens-signals/A2.jsonl (main ef991fc4)
  • Chain: DomainEffectInEdge::Condition calls PrecedenceInEdge::Candidate.unwrap ← the unwrap has no top-level home ← SameFileDefs and EffectCall were nested the same way when PrecedenceInEdge and EdgeScope reused them (DESIGN: lens-architecture A2; plugins/os-sdlc/lens-signals/A2.jsonl 2026-11-02 deferred row)
  • Root candidate: none found; searched SameFileDefs, EffectCall, Candidate.unwrap, nested helper, Lens proposal, top-level object, lift, Structural
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/
  • Session: a5c3e206-c44a-409e-8655-4a519fdaab84
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1510/a5c3e206-c44a-409e-8655-4a519fdaab84.jsonl

VERDICT: CREATE — the A2 challenge on #1511 found a real code defect; no open ticket covers lifting the nested Structural cop helpers.

## Problem Three helper objects are nested inside one cop but have callers in other cop concepts. Lens A2 says an object with callers in more than one concept is a top-level object. The nesting hides the shared role, and each new cop that needs a helper reaches into another cop's namespace. `Structural::EdgeScope` and `Structural::EffectReach` already show the correct top-level form. ## Observed The A2 lens challenge on #1511 (run 221) returned "code defect found". The contract-auditor had marked the break JUSTIFIED because the ticket asked for reuse of nested helpers; the challenge found that the ticket named `SameFileDefs` and `EFFECT_CONSTANTS` only, never `Candidate`, and that the other nested reuses are earlier A2 breaks, not a pattern to follow. ``` plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/condition.rb:35,42 PrecedenceInEdge::Candidate.unwrap plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/facts.rb:15 QueryMethodReachesWrite::SameFileDefs plugins/os-sdlc/lib/os_sdlc/cops/structural/precedence_in_edge.rb:17 QueryMethodReachesWrite::SameFileDefs plugins/os-sdlc/lib/os_sdlc/cops/structural/edge_scope.rb:14-15,65 EffectInModel::EffectCall plugins/os-sdlc/lib/os_sdlc/cops/structural/effect_reach/walk.rb:31 EffectInModel::EffectCall ``` ## Reproduce n/a: structure finding, the suite is the proof ## Approach Structure-only moves under `RuboCop::Cop::Sdlc::Structural`, one concept per commit, no behavior change, on the fast path. Required work: 1. Move `QueryMethodReachesWrite::SameFileDefs` to `structural/same_file_defs.rb` and update its callers (QueryMethodReachesWrite, PrecedenceInEdge, DomainEffectInEdge::Facts). — check: present `class SameFileDefs` in `plugins/os-sdlc/lib/os_sdlc/cops/structural/same_file_defs.rb` 2. Move `EffectInModel::EffectCall` to `structural/effect_call.rb` and update its callers (EffectInModel, EdgeScope, EffectReach::Walk). — check: present `class EffectCall` in `plugins/os-sdlc/lib/os_sdlc/cops/structural/effect_call.rb` 3. Extract the class methods `PrecedenceInEdge::Candidate.unwrap` and `.slot_of` into a top-level value (name to be ruled) and update the callers (PrecedenceInEdge Candidate, Presence, Guard; DomainEffectInEdge::Condition). `Candidate` itself stays nested. — check: absent `PrecedenceInEdge::Candidate` in `plugins/os-sdlc/lib/os_sdlc/cops/structural/domain_effect_in_edge/**/*.rb` Orchestrator work: rule the name of the unwrap value before item 3. ## Acceptance criteria 1. Given the os-sdlc suite at the current commit, when the three moves land, then the suite and rubocop stay green with no test change. 2. Given any cop under `cops/structural/`, when it needs `SameFileDefs`, `EffectCall`, or the unwrap, then it references a top-level `Structural::` constant, not another cop's nested constant. ## Owner sketch ```ruby module RuboCop::Cop::Sdlc::Structural class SameFileDefs class EffectCall class UnwrappedNode # name to be ruled end ``` ## Origin - Trigger: `/os-sdlc:implement 1511`, run 221, contract-auditor LENS line on A2; challenged per references/lens-challenge-checklist.md - Improvised this session: none; signal line appended to plugins/os-sdlc/lens-signals/A2.jsonl (main ef991fc4) - Chain: DomainEffectInEdge::Condition calls PrecedenceInEdge::Candidate.unwrap ← the unwrap has no top-level home ← SameFileDefs and EffectCall were nested the same way when PrecedenceInEdge and EdgeScope reused them (DESIGN: lens-architecture A2; plugins/os-sdlc/lens-signals/A2.jsonl 2026-11-02 deferred row) - Root candidate: none found; searched SameFileDefs, EffectCall, Candidate.unwrap, nested helper, Lens proposal, top-level object, lift, Structural - Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/ - Session: a5c3e206-c44a-409e-8655-4a519fdaab84 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-1510/a5c3e206-c44a-409e-8655-4a519fdaab84.jsonl VERDICT: CREATE — the A2 challenge on #1511 found a real code defect; no open ticket covers lifting the nested Structural cop helpers.
Author
Owner

Ruling (Jared, 2026-11-03): item 3 name is Structural::Operand. Follow-up question under investigation before item 3: does DomainOperandInEdge (#1510) model the same operand concept, so that Operand should own more than unwrap/slot_of? Work starting on main via fast-batch.

Ruling (Jared, 2026-11-03): item 3 name is `Structural::Operand`. Follow-up question under investigation before item 3: does DomainOperandInEdge (#1510) model the same operand concept, so that Operand should own more than unwrap/slot_of? Work starting on main via fast-batch.
Author
Owner

This is a design-only refactor with no observed failure, and its parent #1523 is itself an AI-created follow-up, so the depth-1 rule applies. If the Operand work in #1523 wants a third method for the test-call unwrap in Presence#subject_of and Condition#check_of, add it there. Note it on #1523 instead of filing a new ticket.

This is a design-only refactor with no observed failure, and its parent #1523 is itself an AI-created follow-up, so the depth-1 rule applies. If the Operand work in #1523 wants a third method for the test-call unwrap in Presence#subject_of and Condition#check_of, add it there. Note it on #1523 instead of filing a new ticket.
Author
Owner

Resolution

Done: All three ticket items shipped via fast-batch-23, plus three related fixes: SameFileDefs, EffectCall, and Operand (unwrap, slot_of; name ruled by Jared) are top-level under Structural. DefKey is top-level and CallKeys nests under SameFileDefs (same A2 defect, exposed by item 1). The duplicate leaves became Structural::ConditionLeaves.of. ForwardingClass::Operand was renamed to Argument so the bare name Operand stays unambiguous. No behavior change.

Evidence: main d538dd47 (merge), cfc7ed26 (pushed). Commits a3003a8f 682f5e05 1218d3ed 91db7ec0 d027d88b 83117301 69d884c4. Full suite after merging main: 3305 runs, 7016 assertions, 0 failures, 0 errors. Sdlc/Structural/InwardDependency sweep 93 -> 93. AC2 grep: no Candidate.unwrap/slot_of, QueryMethodReachesWrite::SameFileDefs/DefKey/CallKeys, EffectInModel::EffectCall, or ForwardingClass::Operand left in plugins/*.rb. Records: docs/crc/os-sdlc/fast-batch-23/.

Follow-ups: none. Presence#subject_of / Condition#check_of merge: ticket-skeptic DROP (depth-1, reason on this ticket). design/generated/ staleness: dropped, the periodic regeneration commit owns it. ConstantChain#operands method name and a nested-constant shadowing cop: dropped, speculative.

## Resolution **Done:** All three ticket items shipped via fast-batch-23, plus three related fixes: SameFileDefs, EffectCall, and Operand (unwrap, slot_of; name ruled by Jared) are top-level under Structural. DefKey is top-level and CallKeys nests under SameFileDefs (same A2 defect, exposed by item 1). The duplicate leaves became Structural::ConditionLeaves.of. ForwardingClass::Operand was renamed to Argument so the bare name Operand stays unambiguous. No behavior change. **Evidence:** main d538dd47 (merge), cfc7ed26 (pushed). Commits a3003a8f 682f5e05 1218d3ed 91db7ec0 d027d88b 83117301 69d884c4. Full suite after merging main: 3305 runs, 7016 assertions, 0 failures, 0 errors. Sdlc/Structural/InwardDependency sweep 93 -> 93. AC2 grep: no Candidate.unwrap/slot_of, QueryMethodReachesWrite::SameFileDefs/DefKey/CallKeys, EffectInModel::EffectCall, or ForwardingClass::Operand left in plugins/*.rb. Records: docs/crc/os-sdlc/fast-batch-23/. **Follow-ups:** none. Presence#subject_of / Condition#check_of merge: ticket-skeptic DROP (depth-1, reason on this ticket). design/generated/ staleness: dropped, the periodic regeneration commit owns it. ConstantChain#operands method name and a nested-constant shadowing cop: dropped, speculative.
jared closed this issue 2026-11-03 14:44:42 +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#1523
No description provided.