crc os-adr wave 5: split Detector: file reads leave the classifying model #929

Closed
opened 2026-10-04 16:37:10 +00:00 by jared · 2 comments
Owner

Problem

Split Detector: extract classification rules into a model; keep file reading in a query. Detector currently does two jobs: classifying legacy decision file structure and reading files from disk. Separate data and vocabulary split this cleanly per R6 and R7.

Reproduce

n/a: structure-only refactor, no behavior change

Approach

Required work:

  1. Extract classification rules from plugins/os-adr/lib/adr/detector.rb into plugins/os-adr/lib/adr/model/migration/unit.rb, constant Adr::Migration::Unit, with UNIT_HEADING, PROSE_DECISION, DECISION_MARKERS. Public methods: classify_file, split_units, unit_title, single_title, relative. Its public message takes the source text and its relative path and returns Units; it reads no file.
  2. Keep file-reading in plugins/os-adr/lib/adr/query/migration/ as a query whose name the wave 2 re-run assigns, with CANDIDATE_DIRS, GENERATED_BASENAMES. Public methods: new(root:), units, candidate_files, generated?, already_migrated?. units reads each candidate file and passes the text to the model. The model never calls the query.
  3. Rename detector.rb to reflect query responsibility after split, with the name from the wave 2 re-run. The test keeps its path.
  4. Update callers: bin/adr-detect, bin/adr-migrate, migrator.rb, migration_report.rb change only the constant name.

Recipe from R7:
The classification leaves to a model under model/migration/: Unit, UNIT_HEADING, PROSE_DECISION, DECISION_MARKERS, classify_file, split_units, unit_title, single_title, relative. Its public message takes the source text and its relative path and returns Units; it reads no file. What stays becomes a query under query/migration/: CANDIDATE_DIRS, GENERATED_BASENAMES, candidate_files, generated?, already_migrated?, and units, which reads each candidate file and passes the text to the model. The query keeps the public new(root:) and units, so bin/adr-detect:11, bin/adr-migrate:18, migrator.rb:38, and migration_report.rb:34 change only the constant name.

Governed by rulings: R1, R6, R7
Rejected: none (R7 governs the split)

Acceptance criteria

  • Detector split into two files: model/migration/unit.rb and query/migration/ (name per wave 2 re-run)
  • Model Unit reads no files; all public methods return Unit-based results
  • Query reads files and passes the text to the model
  • tests/detector_test.rb remains green with new(root:).units seam unchanged
  • ruby plugins/os-adr/tests/all.rb passes with 0 failures
  • ruby -e 'require "./plugins/os-adr/lib/adr"; Adr.loader.eager_load' runs silently
  • Loader plugins/os-adr/lib/adr.rb collapses the six role directories (model/migration/ and query/migration/ load through model/ and query/)
  • All callers updated (bin/adr-detect, bin/adr-migrate, migrator.rb, migration_report.rb)
  • No inward rule violations: model does not call query

Owner sketch

Familiar with Ruby, Zeitwerk, os-adr architecture, and the Migration/Detection workflow. Understand the two jobs: classifying legacy file structure (model responsibility) and discovering candidate files (query responsibility). The model is stateless; the query holds root and discovers files.

Non-goals

No behavior change; no new tests; no deletion of code that has callers.

Origin

Session: a20defa9-036a-415a-9dde-2ed833c727cb
Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-refactor-docs/a20defa9-036a-415a-9dde-2ed833c727cb.jsonl
Where: crc-refactor run on plugins/os-adr, worktree crc-os-adr-2026-10-04, ledger docs/crc/os-adr/ledger.tsv

## Problem Split Detector: extract classification rules into a model; keep file reading in a query. Detector currently does two jobs: classifying legacy decision file structure and reading files from disk. Separate data and vocabulary split this cleanly per R6 and R7. ## Reproduce n/a: structure-only refactor, no behavior change ## Approach Required work: 1. Extract classification rules from plugins/os-adr/lib/adr/detector.rb into plugins/os-adr/lib/adr/model/migration/unit.rb, constant Adr::Migration::Unit, with UNIT_HEADING, PROSE_DECISION, DECISION_MARKERS. Public methods: classify_file, split_units, unit_title, single_title, relative. Its public message takes the source text and its relative path and returns Units; it reads no file. 2. Keep file-reading in plugins/os-adr/lib/adr/query/migration/ as a query whose name the wave 2 re-run assigns, with CANDIDATE_DIRS, GENERATED_BASENAMES. Public methods: new(root:), units, candidate_files, generated?, already_migrated?. units reads each candidate file and passes the text to the model. The model never calls the query. 3. Rename detector.rb to reflect query responsibility after split, with the name from the wave 2 re-run. The test keeps its path. 4. Update callers: bin/adr-detect, bin/adr-migrate, migrator.rb, migration_report.rb change only the constant name. Recipe from R7: The classification leaves to a model under `model/migration/`: `Unit`, `UNIT_HEADING`, `PROSE_DECISION`, `DECISION_MARKERS`, `classify_file`, `split_units`, `unit_title`, `single_title`, `relative`. Its public message takes the source text and its relative path and returns `Unit`s; it reads no file. What stays becomes a query under `query/migration/`: `CANDIDATE_DIRS`, `GENERATED_BASENAMES`, `candidate_files`, `generated?`, `already_migrated?`, and `units`, which reads each candidate file and passes the text to the model. The query keeps the public `new(root:)` and `units`, so `bin/adr-detect:11`, `bin/adr-migrate:18`, `migrator.rb:38`, and `migration_report.rb:34` change only the constant name. Governed by rulings: R1, R6, R7 Rejected: none (R7 governs the split) ## Acceptance criteria - Detector split into two files: model/migration/unit.rb and query/migration/ (name per wave 2 re-run) - Model Unit reads no files; all public methods return Unit-based results - Query reads files and passes the text to the model - tests/detector_test.rb remains green with new(root:).units seam unchanged - ruby plugins/os-adr/tests/all.rb passes with 0 failures - ruby -e 'require "./plugins/os-adr/lib/adr"; Adr.loader.eager_load' runs silently - Loader plugins/os-adr/lib/adr.rb collapses the six role directories (model/migration/ and query/migration/ load through model/ and query/) - All callers updated (bin/adr-detect, bin/adr-migrate, migrator.rb, migration_report.rb) - No inward rule violations: model does not call query ## Owner sketch Familiar with Ruby, Zeitwerk, os-adr architecture, and the Migration/Detection workflow. Understand the two jobs: classifying legacy file structure (model responsibility) and discovering candidate files (query responsibility). The model is stateless; the query holds root and discovers files. ## Non-goals No behavior change; no new tests; no deletion of code that has callers. ## Origin Session: a20defa9-036a-415a-9dde-2ed833c727cb Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-refactor-docs/a20defa9-036a-415a-9dde-2ed833c727cb.jsonl Where: crc-refactor run on plugins/os-adr, worktree crc-os-adr-2026-10-04, ledger docs/crc/os-adr/ledger.tsv
Author
Owner

Commit 12acff91 (Detector split into Migration::Classification, Migration::Unit, Migration::Inventory); rows applied 1/1; rows deviated 1 (relative stays in query); rows blocked 0

Commit 12acff91 (Detector split into Migration::Classification, Migration::Unit, Migration::Inventory); rows applied 1/1; rows deviated 1 (relative stays in query); rows blocked 0
Author
Owner

Resolution

Done: Detector split per R7: Migration::Inventory (query), classification model (later Migration::LegacyFile by #932), Migration::Unit

Evidence: 12acff91 on branch crc-os-adr-2026-10-04 (not merged; user review pending); suite: 51 runs, 168 assertions, 0 failures, 0 errors, 0 skips; eager load silent; inward lint: none (os-adr has none)

Follow-ups: none for this ticket; run-level follow-ups filed as #934 and #935; dropped items listed in docs/crc/os-adr/HANDOFF.md Review

## Resolution **Done:** Detector split per R7: Migration::Inventory (query), classification model (later Migration::LegacyFile by #932), Migration::Unit **Evidence:** 12acff91 on branch crc-os-adr-2026-10-04 (not merged; user review pending); suite: 51 runs, 168 assertions, 0 failures, 0 errors, 0 skips; eager load silent; inward lint: none (os-adr has none) **Follow-ups:** none for this ticket; run-level follow-ups filed as #934 and #935; dropped items listed in docs/crc/os-adr/HANDOFF.md Review
jared closed this issue 2026-10-04 17:15:05 +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#929
No description provided.