Add cop Sdlc/Structural/ClassInWrongConcept with lesson #1749

Closed
opened 2026-11-13 20:06:42 +00:00 by jared · 2 comments
Owner

Problem

The one message of Sdlc/Structural/ConceptCycle does not tell an agent the correct fix for a class that is in one concept and that only another concept uses.
A separate cop with its own message and lesson gives the correct fix.
Ticket 1 supplies the facts. This ticket is blocked by ticket 1.

The base branch is ticket-1742. It is not merged. Its worktree is /home/jared/dev/cc-os/.claude/worktrees/ticket-1742. It holds the cop Sdlc/Structural/ConceptCycle and the class OsSdlc::Lint::ConceptCycleCheck. main does not have them.

The research source is docs/research/lint-lessons/2026-11-13-concept-cycle-kinds/ on main (commits 5465548a7, 9bb6a9845, 58ee53c). It holds simulation/kinds.rb, simulation/facts-os-sdlc.yml, simulation/package/ (lessons, message forms, render.rb), and simulation/round-1/grades/*.yml.

A "loop reference" is a reference from one concept to another concept when the two concepts are in a dependency loop. A "concept" is a top-level namespace of the library with its directory. The cop reports 93 loop references in 58 files of os-sdlc.

Work: add the cop Sdlc/Structural/ClassInWrongConcept and its lesson. The cop reports a class that is in one concept and is used only by another concept.
The cop gives one finding for each unit.
The source text is simulation/package/sdlc-structural-class-in-wrong-concept.yml.
Put the cop file under plugins/os-sdlc/lib/os_sdlc/cops/structural/. Put the lesson under plugins/os-sdlc/lint-lessons/.
Write a must-fire fixture and a must-pass fixture.

Constraints:

  • Register cops in plugins/os-sdlc/.rubocop.yml only (ADR-0298).
  • Each cop file name under lib/os_sdlc/cops/structural/ agrees with its constant (ADR-0090).
  • Use no Exclude list and no allowlist.
  • Write no repository name in lesson or message-form text.
  • Put pass/fail logic in tested Ruby, not in prompt text.

Observed

In round 1 (round-1/grades/known-A.yml), 3 of 3 runs made the correct fix.
All three runs named the same gaps in the lesson and message:

  • The list "other users" reads as a list of sites to edit.
  • The lesson does not say what to do with generated files and frozen fixtures.
  • The message does not say if the user writes the short name or the qualified name.

The new lesson and message must close these three gaps.

Reproduce

n/a: feature ticket.

Origin

  • Trigger: round 1 of the concept-cycle kinds research (docs/research/lint-lessons/2026-11-13-concept-cycle-kinds/ on main)
  • Improvised this session: none
  • Chain: the agent edits the wrong site ← the one message does not name this kind ← no cop for this kind exists (DESIGN: ticket 1 of this set and simulation/package/sdlc-structural-class-in-wrong-concept.yml)
  • Root candidate: none found; searched ClassInWrongConcept, WrongConcept, ConceptCycle, concept-cycle, class in wrong concept, kinds
  • Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/ and plugins/os-sdlc/lint-lessons/ (branch ticket-1742)
  • Session: fdf2ac7d-9590-47d4-97e8-ebff9711ce46
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os-plugins-os-sdlc/fdf2ac7d-9590-47d4-97e8-ebff9711ce46.jsonl
  • VERDICT: CREATE - handoff step 5 states the requirement; round 1 grades give provenance; no open ticket for this cop.
## Problem The one message of `Sdlc/Structural/ConceptCycle` does not tell an agent the correct fix for a class that is in one concept and that only another concept uses. A separate cop with its own message and lesson gives the correct fix. Ticket 1 supplies the facts. This ticket is blocked by ticket 1. The base branch is `ticket-1742`. It is not merged. Its worktree is `/home/jared/dev/cc-os/.claude/worktrees/ticket-1742`. It holds the cop `Sdlc/Structural/ConceptCycle` and the class `OsSdlc::Lint::ConceptCycleCheck`. `main` does not have them. The research source is `docs/research/lint-lessons/2026-11-13-concept-cycle-kinds/` on `main` (commits `5465548a7`, `9bb6a9845`, `58ee53c`). It holds `simulation/kinds.rb`, `simulation/facts-os-sdlc.yml`, `simulation/package/` (lessons, message forms, `render.rb`), and `simulation/round-1/grades/*.yml`. A "loop reference" is a reference from one concept to another concept when the two concepts are in a dependency loop. A "concept" is a top-level namespace of the library with its directory. The cop reports 93 loop references in 58 files of os-sdlc. Work: add the cop `Sdlc/Structural/ClassInWrongConcept` and its lesson. The cop reports a class that is in one concept and is used only by another concept. The cop gives one finding for each unit. The source text is `simulation/package/sdlc-structural-class-in-wrong-concept.yml`. Put the cop file under `plugins/os-sdlc/lib/os_sdlc/cops/structural/`. Put the lesson under `plugins/os-sdlc/lint-lessons/`. Write a must-fire fixture and a must-pass fixture. Constraints: - Register cops in `plugins/os-sdlc/.rubocop.yml` only (ADR-0298). - Each cop file name under `lib/os_sdlc/cops/structural/` agrees with its constant (ADR-0090). - Use no `Exclude` list and no allowlist. - Write no repository name in lesson or message-form text. - Put pass/fail logic in tested Ruby, not in prompt text. ## Observed In round 1 (`round-1/grades/known-A.yml`), 3 of 3 runs made the correct fix. All three runs named the same gaps in the lesson and message: - The list "other users" reads as a list of sites to edit. - The lesson does not say what to do with generated files and frozen fixtures. - The message does not say if the user writes the short name or the qualified name. The new lesson and message must close these three gaps. ## Reproduce n/a: feature ticket. ## Origin - Trigger: round 1 of the concept-cycle kinds research (`docs/research/lint-lessons/2026-11-13-concept-cycle-kinds/` on `main`) - Improvised this session: none - Chain: the agent edits the wrong site ← the one message does not name this kind ← no cop for this kind exists (DESIGN: ticket 1 of this set and `simulation/package/sdlc-structural-class-in-wrong-concept.yml`) - Root candidate: none found; searched ClassInWrongConcept, WrongConcept, ConceptCycle, concept-cycle, class in wrong concept, kinds - Where: plugins/os-sdlc/lib/os_sdlc/cops/structural/ and plugins/os-sdlc/lint-lessons/ (branch `ticket-1742`) - Session: fdf2ac7d-9590-47d4-97e8-ebff9711ce46 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os-plugins-os-sdlc/fdf2ac7d-9590-47d4-97e8-ebff9711ce46.jsonl - VERDICT: CREATE - handoff step 5 states the requirement; round 1 grades give provenance; no open ticket for this cop.
Author
Owner

Blocked by #1748: this ticket uses the classification that it builds.

Blocked by #1748: this ticket uses the classification that it builds.
Author
Owner

Resolution

Done: Cop Sdlc/Structural/ClassInWrongConcept reports each class that only another concept uses, one time, at its declaration. The message comes from the Facts of Kinds::Report. The lesson is lint-lessons/sdlc-structural-class-in-wrong-concept.yml. ConceptCycle no longer reports a reference of this kind. ConceptCycle::LoopFacts is the shared facts owner for the cops of #1750 and #1751.

Evidence: Branch ticket-1742, commit 73608ed39 (11 files, +500/-12). Suite: 5439 runs, 0 failures, 0 errors. Rubocop on the 9 changed Ruby files: no offenses. On os-sdlc lib with .rubocop-sweep.yml: ConceptCycle 91 offenses in 56 files, ClassInWrongConcept 1 offense that stands for 2 loop references; 91 + 2 = 93. Must-fire and must-pass fixtures in test/cops/class_in_wrong_concept_test.rb (13 tests).

Follow-ups: Two defects found in Kinds::Report: move_to_path is wrong when the new concept has no file of its own; this is corrected in the build of #1750. When two classes in two concepts use only each other, each is a proven unit; dropped as a ticket, the lesson stop condition covers it and no codebase shows it. The cop is registered in .rubocop-sweep.yml only, the same as ConceptCycle on this branch.

## Resolution **Done:** Cop Sdlc/Structural/ClassInWrongConcept reports each class that only another concept uses, one time, at its declaration. The message comes from the Facts of Kinds::Report. The lesson is lint-lessons/sdlc-structural-class-in-wrong-concept.yml. ConceptCycle no longer reports a reference of this kind. ConceptCycle::LoopFacts is the shared facts owner for the cops of #1750 and #1751. **Evidence:** Branch ticket-1742, commit 73608ed39 (11 files, +500/-12). Suite: 5439 runs, 0 failures, 0 errors. Rubocop on the 9 changed Ruby files: no offenses. On os-sdlc lib with .rubocop-sweep.yml: ConceptCycle 91 offenses in 56 files, ClassInWrongConcept 1 offense that stands for 2 loop references; 91 + 2 = 93. Must-fire and must-pass fixtures in test/cops/class_in_wrong_concept_test.rb (13 tests). **Follow-ups:** Two defects found in Kinds::Report: move_to_path is wrong when the new concept has no file of its own; this is corrected in the build of #1750. When two classes in two concepts use only each other, each is a proven unit; dropped as a ticket, the lesson stop condition covers it and no codebase shows it. The cop is registered in .rubocop-sweep.yml only, the same as ConceptCycle on this branch. <!-- os-backlog kind: resolution -->
jared closed this issue 2026-11-13 21:04:40 +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#1749
No description provided.