Add cop Sdlc/Sequel/DatasetResultCompared #909

Closed
opened 2026-10-02 16:57:05 +00:00 by jared · 2 comments
Owner

Problem

A decision about one model's rows is made outside that model, by comparing or testing the result of a dataset chain.
Signal: a decision about one model's rows is made outside that model.

Approach

Add the cop Sdlc/Sequel/DatasetResultCompared under plugins/os-sdlc/lib/os_sdlc/cops/.
Templates: registry_outside_entry_point.rb, row_index_on_model.rb, and the shared sequel_allowed_paths.rb.
Authoring guide: plugins/os-sdlc/skills/mine-lints/references/implement-cop.md.
RuboCop runs with DisabledByDefault: true, so every enabled cop blocks at the gate and every hit must always need a correction.
Do not widen the match lists below.
Receiver test: the chain starts from a *_dataset call.
Direct model queries (Model.where) are out of scope.

Flagged: *_dataset chain used as an operand of >= > < <= == !=, or as the receiver of zero? positive? empty? any? none?.

Not flagged: between? eql? <=> equal?, case/===, a bare chain as an if condition.

Known hits: plugins/os-sdlc/lib/os_sdlc/model/implementation.rb:74-75 (reroutes_dataset.applied.count >= Reroute::CAP).
Correct the existing hits in plugins/os-sdlc/lib/ in the same change.
Intended correction: move the query or decision into a named dataset_module method on the model that owns the rows, and delegate from the caller.

Lesson (ADR-0265): the lesson file is a required part of the cop.
Path: plugins/os-sdlc/lint-lessons/<kebab-cop-name>.md in the plugin (ADR-0266).
Sections in order: The signal; What it is a sign of; Why it matters; Your decision; Correction; Example.
Lesson text uses generic names (for example orders_dataset, Order), never names from this codebase.
Lesson example: before orders_dataset.shipped.count >= Order::LIMIT, after orders_dataset.limit_reached?.
Depends on #908 (Lesson concept move; Lesson::Library reads the plugin lesson directory).

Required work:

  1. Add the cop file — check: present DatasetResultCompared in plugins/os-sdlc/lib/os_sdlc/cops/*.rb
  2. Add the lesson file — check: present The signal in plugins/os-sdlc/lint-lessons/sdlc-sequel-dataset-result-compared.md

Acceptance criteria

  1. Given a call in the flagged list on a *_dataset chain, when the cop runs, then it flags it.
  2. Given a call in the not-flagged list, when the cop runs, then it does not flag it.
  3. Given the existing hits in plugins/os-sdlc/lib, when the gate runs, then none remain.
  4. Given a gate reply for a flagged offense, when the gate renders, then the lesson file text appears.

Owner sketch

class RuboCop::Cop::Sdlc::Sequel::DatasetResultCompared < RuboCop::Cop::Base
  def on_send(node)
end

Origin

  • Trigger: user request this session, from a review of Sequel dataset use.
  • Improvised this session: none
  • Chain: query or decision outside owning model ← no cop covers it (DESIGN: ADR-0265)
  • Root candidate: none
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/
  • Session: 9ee7805f-a4e4-470e-af50-5020e5c524a4
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9ee7805f-a4e4-470e-af50-5020e5c524a4.jsonl
## Problem A decision about one model's rows is made outside that model, by comparing or testing the result of a dataset chain. Signal: a decision about one model's rows is made outside that model. ## Approach Add the cop `Sdlc/Sequel/DatasetResultCompared` under `plugins/os-sdlc/lib/os_sdlc/cops/`. Templates: `registry_outside_entry_point.rb`, `row_index_on_model.rb`, and the shared `sequel_allowed_paths.rb`. Authoring guide: `plugins/os-sdlc/skills/mine-lints/references/implement-cop.md`. RuboCop runs with `DisabledByDefault: true`, so every enabled cop blocks at the gate and every hit must always need a correction. Do not widen the match lists below. Receiver test: the chain starts from a `*_dataset` call. Direct model queries (`Model.where`) are out of scope. Flagged: `*_dataset` chain used as an operand of `>= > < <= == !=`, or as the receiver of `zero? positive? empty? any? none?`. Not flagged: `between? eql? <=> equal?`, `case`/`===`, a bare chain as an `if` condition. Known hits: `plugins/os-sdlc/lib/os_sdlc/model/implementation.rb:74-75` (`reroutes_dataset.applied.count >= Reroute::CAP`). Correct the existing hits in `plugins/os-sdlc/lib/` in the same change. Intended correction: move the query or decision into a named `dataset_module` method on the model that owns the rows, and delegate from the caller. Lesson (ADR-0265): the lesson file is a required part of the cop. Path: `plugins/os-sdlc/lint-lessons/<kebab-cop-name>.md` in the plugin (ADR-0266). Sections in order: The signal; What it is a sign of; Why it matters; Your decision; Correction; Example. Lesson text uses generic names (for example `orders_dataset`, `Order`), never names from this codebase. Lesson example: before `orders_dataset.shipped.count >= Order::LIMIT`, after `orders_dataset.limit_reached?`. Depends on #908 (Lesson concept move; `Lesson::Library` reads the plugin lesson directory). Required work: 1. Add the cop file — check: present `DatasetResultCompared` in `plugins/os-sdlc/lib/os_sdlc/cops/*.rb` 2. Add the lesson file — check: present `The signal` in `plugins/os-sdlc/lint-lessons/sdlc-sequel-dataset-result-compared.md` ## Acceptance criteria 1. Given a call in the flagged list on a `*_dataset` chain, when the cop runs, then it flags it. 2. Given a call in the not-flagged list, when the cop runs, then it does not flag it. 3. Given the existing hits in `plugins/os-sdlc/lib`, when the gate runs, then none remain. 4. Given a gate reply for a flagged offense, when the gate renders, then the lesson file text appears. ## Owner sketch ```ruby class RuboCop::Cop::Sdlc::Sequel::DatasetResultCompared < RuboCop::Cop::Base def on_send(node) end ``` ## Origin - Trigger: user request this session, from a review of Sequel dataset use. - Improvised this session: none - Chain: query or decision outside owning model ← no cop covers it (DESIGN: ADR-0265) - Root candidate: none - Where: plugins/os-sdlc/lib/os_sdlc/cops/ - Session: 9ee7805f-a4e4-470e-af50-5020e5c524a4 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/9ee7805f-a4e4-470e-af50-5020e5c524a4.jsonl
Author
Owner

Work started on branch ticket-909 through the os-sdlc pipeline.

Work started on branch ticket-909 through the os-sdlc pipeline.
Author
Owner

Resolution

Done: Cop Sdlc/Sequel/DatasetResultCompared added and enabled in plugins/os-sdlc/.rubocop.yml, with its lesson file plugins/os-sdlc/lint-lessons/sdlc-sequel-dataset-result-compared.md (ADR-0265 sections, generic names). The existing hit is corrected: the cap decision moved to a Reroute dataset_module method and Implementation delegates.

Evidence: Branch ticket-909, commit 39cfda08; os-sdlc implementation 13: 8 dispatches, 0 retries, required-work gate and full suite green, contract-auditor pass.

Follow-ups: none; History row for the os-sdlc leaf added after merge.

## Resolution **Done:** Cop Sdlc/Sequel/DatasetResultCompared added and enabled in plugins/os-sdlc/.rubocop.yml, with its lesson file plugins/os-sdlc/lint-lessons/sdlc-sequel-dataset-result-compared.md (ADR-0265 sections, generic names). The existing hit is corrected: the cap decision moved to a Reroute dataset_module method and Implementation delegates. **Evidence:** Branch ticket-909, commit 39cfda08; os-sdlc implementation 13: 8 dispatches, 0 retries, required-work gate and full suite green, contract-auditor pass. **Follow-ups:** none; History row for the os-sdlc leaf added after merge.
jared closed this issue 2026-10-02 17:20:13 +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#909
No description provided.