Rewrite EffectCall on Prism nodes so the collaborator pass parses without rubocop #1220

Closed
opened 2026-10-21 19:12:26 +00:00 by jared · 1 comment
Owner

Problem

OsSdlc::EffectCall is a library owner at plugins/os-sdlc/lib/os_sdlc/effect_call.rb, but it is written against rubocop AST node types (xstr_type?, NodePattern). That forces collaborator_pass/effect_sites.rb and collaborator_pass/inward_edges.rb to parse through CopSource and rubocop's parser, which needs a grammar version. The library already walks Prism in 17 files, and Prism needs no version. Only crc/holders/site_offenses.rb needs rubocop, because it runs cops.

Reproduce

n/a: design ticket; the dependency is visible in effect_sites.rb (require "rubocop", CopSource.from_file).

Approach

EffectCall takes a Prism node. The EffectInModel cop adapts at its boundary, or both share one Prism-walking core. effect_sites.rb and inward_edges.rb parse with Prism.parse_file and no longer require rubocop. CopSource keeps only the site_offenses.rb caller.

Required work:

  1. EffectCall classifies a Prism call or xstring node — check: absent xstr_type? in plugins/os-sdlc/lib/os_sdlc/effect_call.rb
  2. effect_sites.rb and inward_edges.rb parse with Prism — check: absent CopSource in plugins/os-sdlc/lib/os_sdlc/collaborator_pass/*.rb
  3. The EffectInModel cop keeps its offenses through an adapter or a shared core — check: present EffectCall in plugins/os-sdlc/lib/os_sdlc/cops/effect_in_model.rb

Rejected: keep rubocop AST and resolve the version per file — the version dependency is the thing this ticket removes.

Acceptance criteria

  1. Given the plugin on main, when bin/lint-sweep runs, then EffectInModel reports 22 offenses, the same set as before.
  2. Given collaborator-pass measure --sources effects,inward, when it runs, then signals.tsv equals the pre-change output for both sources.
  3. Given effect_sites.rb and inward_edges.rb, when loaded, then neither requires rubocop.
  4. Given the suite, when it runs, then it is green.

Owner sketch

class OsSdlc::EffectCall
  def initialize(node, constants:, pure_methods:)
  def label
end

Origin

  • Trigger: fast-batch-1 stranger review and ruling 4 discussion, 2026-10-21
  • Improvised this session: none
  • Chain: three sites hand a grammar version to rubocop ← EffectCall is rubocop-AST shaped ← DESIGN (plugins/os-sdlc/lib/os_sdlc/effect_call.rb)
  • Root candidate: none found; searched EffectCall, EffectInModel, CopSource, ProcessedSource, effect_sites, inward_edges, prism, rubocop, collaborator, parser, grammar
  • Where: plugins/os-sdlc/lib/os_sdlc/effect_call.rb
  • Session: 017840c1-178f-4be2-bbb8-c548c9e70349
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/017840c1-178f-4be2-bbb8-c548c9e70349.jsonl

VERDICT: CREATE

## Problem `OsSdlc::EffectCall` is a library owner at `plugins/os-sdlc/lib/os_sdlc/effect_call.rb`, but it is written against rubocop AST node types (`xstr_type?`, `NodePattern`). That forces `collaborator_pass/effect_sites.rb` and `collaborator_pass/inward_edges.rb` to parse through `CopSource` and rubocop's parser, which needs a grammar version. The library already walks Prism in 17 files, and Prism needs no version. Only `crc/holders/site_offenses.rb` needs rubocop, because it runs cops. ## Reproduce n/a: design ticket; the dependency is visible in `effect_sites.rb` (`require "rubocop"`, `CopSource.from_file`). ## Approach `EffectCall` takes a Prism node. The `EffectInModel` cop adapts at its boundary, or both share one Prism-walking core. `effect_sites.rb` and `inward_edges.rb` parse with `Prism.parse_file` and no longer require rubocop. `CopSource` keeps only the `site_offenses.rb` caller. Required work: 1. `EffectCall` classifies a Prism call or xstring node — check: absent `xstr_type?` in `plugins/os-sdlc/lib/os_sdlc/effect_call.rb` 2. `effect_sites.rb` and `inward_edges.rb` parse with Prism — check: absent `CopSource` in `plugins/os-sdlc/lib/os_sdlc/collaborator_pass/*.rb` 3. The `EffectInModel` cop keeps its offenses through an adapter or a shared core — check: present `EffectCall` in `plugins/os-sdlc/lib/os_sdlc/cops/effect_in_model.rb` Rejected: keep rubocop AST and resolve the version per file — the version dependency is the thing this ticket removes. ## Acceptance criteria 1. Given the plugin on main, when `bin/lint-sweep` runs, then `EffectInModel` reports 22 offenses, the same set as before. 2. Given `collaborator-pass measure --sources effects,inward`, when it runs, then `signals.tsv` equals the pre-change output for both sources. 3. Given `effect_sites.rb` and `inward_edges.rb`, when loaded, then neither requires rubocop. 4. Given the suite, when it runs, then it is green. ## Owner sketch ```ruby class OsSdlc::EffectCall def initialize(node, constants:, pure_methods:) def label end ``` ## Origin - Trigger: fast-batch-1 stranger review and ruling 4 discussion, 2026-10-21 - Improvised this session: none - Chain: three sites hand a grammar version to rubocop ← `EffectCall` is rubocop-AST shaped ← DESIGN (`plugins/os-sdlc/lib/os_sdlc/effect_call.rb`) - Root candidate: none found; searched EffectCall, EffectInModel, CopSource, ProcessedSource, effect_sites, inward_edges, prism, rubocop, collaborator, parser, grammar - Where: plugins/os-sdlc/lib/os_sdlc/effect_call.rb - Session: 017840c1-178f-4be2-bbb8-c548c9e70349 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/017840c1-178f-4be2-bbb8-c548c9e70349.jsonl VERDICT: CREATE
Author
Owner

Resolution

Done: Closed as wrong by Jared's ruling 2026-10-22: EffectCall is shared by the EffectInModel cop and the effect_sites detector, so it stays on RuboCop AST. The detector runs the cop through Detector::CopSites instead.

Evidence: docs/crc/os-sdlc/detector-plan.md Phase 1 steps 3 and 4; ticket #1230

Follow-ups: none

## Resolution **Done:** Closed as wrong by Jared's ruling 2026-10-22: EffectCall is shared by the EffectInModel cop and the effect_sites detector, so it stays on RuboCop AST. The detector runs the cop through Detector::CopSites instead. **Evidence:** docs/crc/os-sdlc/detector-plan.md Phase 1 steps 3 and 4; ticket #1230 **Follow-ups:** none
jared closed this issue 2026-10-22 12:28:11 +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#1220
No description provided.