ConceptCycleCheck: classify each loop reference by kind #1748

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

Problem

The one message of Sdlc/Structural/ConceptCycle fails on the most common kind of loop fault.
The facts that a correct message needs exist only in a research script, simulation/kinds.rb.
Tickets 2 to 5 of this set need those facts in tested Ruby. This ticket blocks tickets 2, 3, 4, and 5.

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: port the three value rules of simulation/kinds.rb into tested Ruby under plugins/os-sdlc/lib/os_sdlc/lint/, next to OsSdlc::Lint::ConceptCycleCheck.
For each loop reference, the check gives these facts:

  • The kind, or none.
  • The unit.
  • The fault site.
  • The move target path.
  • The other users of the named constant, and the other users of the source constant.
  • The count of reports that one fix removes.
  • Each proven fault on any return route, not only when one fix alone removes the report.
  • The count of return routes, with file and line for each edge.

A rule that cannot prove its kind stays quiet.

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

At 2f58591f4, simulation/kinds.rb gives these counts on os-sdlc: 2 misplaced-unit, 2 one-edge-back, 18 starting-code, 71 none.
At 2f58591f4, the script gives 0 proven and 10 none on os-backlog.
The ported code must give the same counts.
Two reject clauses, the superclass clause and the starter-file clause, rejected nothing in the two codebases.
Each of the two clauses needs a must-pass fixture, because the data does not exercise them.

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: a correct message needs facts ← the facts exist only in simulation/kinds.rb ← the check OsSdlc::Lint::ConceptCycleCheck has not got them (DESIGN: plugins/os-sdlc/lib/os_sdlc/lint/concept_cycle_check.rb on ticket-1742)
  • Root candidate: none found; searched ConceptCycle, ConceptCycleCheck, concept-cycle, kinds.rb, loop reference, classify
  • Where: plugins/os-sdlc/lib/os_sdlc/lint/concept_cycle_check.rb (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 - user-directed build step 5 of the handoff; no open ticket covers the same fault.
## Problem The one message of `Sdlc/Structural/ConceptCycle` fails on the most common kind of loop fault. The facts that a correct message needs exist only in a research script, `simulation/kinds.rb`. Tickets 2 to 5 of this set need those facts in tested Ruby. This ticket blocks tickets 2, 3, 4, and 5. 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: port the three value rules of `simulation/kinds.rb` into tested Ruby under `plugins/os-sdlc/lib/os_sdlc/lint/`, next to `OsSdlc::Lint::ConceptCycleCheck`. For each loop reference, the check gives these facts: - The kind, or none. - The unit. - The fault site. - The move target path. - The other users of the named constant, and the other users of the source constant. - The count of reports that one fix removes. - Each proven fault on any return route, not only when one fix alone removes the report. - The count of return routes, with file and line for each edge. A rule that cannot prove its kind stays quiet. 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 At `2f58591f4`, `simulation/kinds.rb` gives these counts on os-sdlc: 2 misplaced-unit, 2 one-edge-back, 18 starting-code, 71 none. At `2f58591f4`, the script gives 0 proven and 10 none on os-backlog. The ported code must give the same counts. Two reject clauses, the superclass clause and the starter-file clause, rejected nothing in the two codebases. Each of the two clauses needs a must-pass fixture, because the data does not exercise them. ## 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: a correct message needs facts ← the facts exist only in `simulation/kinds.rb` ← the check `OsSdlc::Lint::ConceptCycleCheck` has not got them (DESIGN: `plugins/os-sdlc/lib/os_sdlc/lint/concept_cycle_check.rb` on `ticket-1742`) - Root candidate: none found; searched ConceptCycle, ConceptCycleCheck, concept-cycle, kinds.rb, loop reference, classify - Where: plugins/os-sdlc/lib/os_sdlc/lint/concept_cycle_check.rb (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 - user-directed build step 5 of the handoff; no open ticket covers the same fault.
Author
Owner

Scope addition from the merge of main into ticket-1742 (commit c25f8259e).
The merge changed the cop's Reference to build a CodeShape::LexicalScope. A compact declaration such as class A::B is now one lookup frame in the cop, as it is in References#located. Before the merge, the cop also searched A:: from inside that declaration.
No test covers this case. Add a fixture for a reference inside a compact declaration, in test/cops/concept_cycle_test.rb.
Base for this ticket: branch ticket-1742 at c25f8259e. The full suite is green there (5396 runs), and the cop reports 93 loop references in 58 files.

Scope addition from the merge of `main` into `ticket-1742` (commit `c25f8259e`). The merge changed the cop's `Reference` to build a `CodeShape::LexicalScope`. A compact declaration such as `class A::B` is now one lookup frame in the cop, as it is in `References#located`. Before the merge, the cop also searched `A::` from inside that declaration. No test covers this case. Add a fixture for a reference inside a compact declaration, in `test/cops/concept_cycle_test.rb`. Base for this ticket: branch `ticket-1742` at `c25f8259e`. The full suite is green there (5396 runs), and the cop reports 93 loop references in 58 files.
Author
Owner

The takedown run docs/takedown/1748-20261113-150953/ failed at final-check: evidence timed out after 600s. Cause: #1760. The design of that run (09-revise-1) is built test-first on branch ticket-1742, outside the pipeline.

The takedown run docs/takedown/1748-20261113-150953/ failed at final-check: evidence timed out after 600s. Cause: #1760. The design of that run (09-revise-1) is built test-first on branch ticket-1742, outside the pipeline.
Author
Owner

Resolution

Done: OsSdlc::Lint::ConceptCycleCheck::Kinds::Report gives, for each loop reference, the kind (or none), the unit, the fault site, the move target, the other users of both constants, the reports that one fix removes, each proven fault on a return route, and each return route with file:line for each edge. ConceptCycleCheck::Graph owns the concept graph. The rule code holds no repository names.

Evidence: Branch ticket-1742, commits 2aa90b65c ccce31fb5 1f370d111 (28 files, +1047/-25). Suite: 5418 runs, 0 failures, 0 errors, 0 skips. Rubocop on the 28 changed files: no offenses. Sdlc/Structural/ConceptCycle still reports 93 offenses in 58 files. Kinds on os-sdlc: 2 / 2 / 18 / 71; on os-backlog: 0 / 10; zero differences from simulation/kinds.rb. Built test-first outside the takedown pipeline because bin/evidence timed out (#1760).

Follow-ups: #1760 filed for the bin/evidence timeout. The cops of #1749 to #1752 supply tracked_files and call Kinds::Report; no other follow-up.

## Resolution **Done:** OsSdlc::Lint::ConceptCycleCheck::Kinds::Report gives, for each loop reference, the kind (or none), the unit, the fault site, the move target, the other users of both constants, the reports that one fix removes, each proven fault on a return route, and each return route with file:line for each edge. ConceptCycleCheck::Graph owns the concept graph. The rule code holds no repository names. **Evidence:** Branch ticket-1742, commits 2aa90b65c ccce31fb5 1f370d111 (28 files, +1047/-25). Suite: 5418 runs, 0 failures, 0 errors, 0 skips. Rubocop on the 28 changed files: no offenses. Sdlc/Structural/ConceptCycle still reports 93 offenses in 58 files. Kinds on os-sdlc: 2 / 2 / 18 / 71; on os-backlog: 0 / 10; zero differences from simulation/kinds.rb. Built test-first outside the takedown pipeline because bin/evidence timed out (#1760). **Follow-ups:** #1760 filed for the bin/evidence timeout. The cops of #1749 to #1752 supply tracked_files and call Kinds::Report; no other follow-up. <!-- os-backlog kind: resolution -->
jared closed this issue 2026-11-13 20:54: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#1748
No description provided.