crc-records reads an applied split row as stale when a part keeps the old last constant segment #1072

Open
opened 2026-10-17 02:24:06 +00:00 by jared · 3 comments
Owner

Problem

PathLookup#defined_in (plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb) falls back to the last constant segment. In the os-sdlc run, the applied split row command/residual_dispatch_report.rb (OsSdlc::ResidualDispatchReport, split in #1064, 720f911c) reads as stale. The new lint/residual_dispatch_report.rb defines OsSdlc::Lint::ResidualDispatchReport, so the fallback matches it. No ledger cell shape clears the row without recording the split as a deletion. A false stale row in the records step teaches the run to ignore stale rows.

Second symptom (CRC run 2 close-out, 2026-10-18): the same fallback makes crc-records exit 1 on 10 false ambiguous entries. Each is an unchanged keep row under cops/ (for example cops/inward_dependency/ledger.rb, constant RuboCop::Cop::Sdlc::Structural::InwardDependency::Ledger). The Zeitwerk path for a RuboCop:: constant does not exist, so defined_in globs for the last segment and finds two or more files. RowCheck#resolve (lib/os_sdlc/crc/records/row_check.rb:60-63) uses the recorded path only when the lookup is :missing. The close-out rule "crc-records exits 0" cannot be met. The 10 rows are listed in docs/crc/os-sdlc/records-report.json.

Reproduce

plugins/os-sdlc/bin/crc-records --target os-sdlc docs/crc/os-sdlc

The output lists the command/residual_dispatch_report.rb row as stale.

Approach

Scope of this pass: the second symptom only. An unchanged keep row (verdict keep, empty new_path) whose recorded path exists is current; RowCheck resolves it at the recorded path before any constant lookup, so it is never ambiguous.

Part 1 shipped in implementation 76 (RowCheck#unchanged_keep_in_place?, AC 1-3 below, green). Part 2: the same last-segment fallback makes an applied move row under cops/ ambiguous. cops/ constants (RuboCop::Cop::Sdlc::...) have no Zeitwerk path, so PathLookup#resolve_exact always misses them. After #1153 the ledger row cops/inward_dependency/ledger.rb records the applied move to cops/layer_ledger/ledger.rb (RuboCop::Cop::Sdlc::Structural::LayerLedger::Ledger, commit 260d07de); that file exists and defines Ledger, yet the row reads ambiguous between it, crc/ledger.rb and lint/gated_run/ledger.rb.

Required work:

  1. In RowCheck#resolve, resolve an unchanged keep row whose recorded path exists at that path, before the constant lookup — check: present keep in plugins/os-sdlc/lib/os_sdlc/crc/records/row_check.rb
  2. A row that is not pending resolves at its recorded path when that file exists and defines the last segment of the row's constant, before the last-segment glob. A recorded file that no longer defines it falls through to the lookup as now.

Acceptance criteria

  1. Given an unchanged keep row whose recorded path exists and whose constant's last segment is defined in two files, when crc-records runs, then the row is current, not ambiguous.
  2. Given a rename or move row whose constant is defined in two files, when crc-records runs, then the row is still ambiguous and no path is guessed.
  3. Given docs/crc/os-sdlc and plugins/os-sdlc/lib/os_sdlc on this branch, when the Reproduce command runs, then no unchanged cops/ keep row is reported ambiguous.
  4. Given an applied move row (commit set) whose recorded new_path exists and defines the last segment of new_constant, and that last segment is defined in two other files, when crc-records runs, then the row is current, not ambiguous.

Owner sketch

class OsSdlc::Crc::Records::RowCheck
  def resolve   # not pending, recorded file exists and defines the constant's last segment -> Resolution(:found, [recorded])
end

Non-goals

The stale applied split row (first symptom) and the last-segment fallback in PathLookup#defined_in stay open on this ticket.

Origin

  • Trigger: crc-records run in the os-sdlc Phase 7 run (split #1064, 720f911c)
  • Improvised this session: none
  • Chain: false stale row in the records step ← PathLookup#defined_in falls back to the last constant segment ← DESIGN: plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb
  • Root candidate: none known
  • Where: plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb
  • Session: 2baa3b32-f47b-4c8b-9cdd-6270831fe640
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/2baa3b32-f47b-4c8b-9cdd-6270831fe640.jsonl

VERDICT: CREATE — real defect in crc-records seen in the Phase 7 run; no existing mechanism covers it; parent #835 is user-filed.

## Problem `PathLookup#defined_in` (plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb) falls back to the last constant segment. In the os-sdlc run, the applied split row `command/residual_dispatch_report.rb` (`OsSdlc::ResidualDispatchReport`, split in #1064, 720f911c) reads as stale. The new `lint/residual_dispatch_report.rb` defines `OsSdlc::Lint::ResidualDispatchReport`, so the fallback matches it. No ledger cell shape clears the row without recording the split as a deletion. A false stale row in the records step teaches the run to ignore stale rows. Second symptom (CRC run 2 close-out, 2026-10-18): the same fallback makes `crc-records` exit 1 on 10 false `ambiguous` entries. Each is an unchanged `keep` row under `cops/` (for example `cops/inward_dependency/ledger.rb`, constant `RuboCop::Cop::Sdlc::Structural::InwardDependency::Ledger`). The Zeitwerk path for a `RuboCop::` constant does not exist, so `defined_in` globs for the last segment and finds two or more files. `RowCheck#resolve` (lib/os_sdlc/crc/records/row_check.rb:60-63) uses the recorded path only when the lookup is `:missing`. The close-out rule "crc-records exits 0" cannot be met. The 10 rows are listed in docs/crc/os-sdlc/records-report.json. ## Reproduce ``` plugins/os-sdlc/bin/crc-records --target os-sdlc docs/crc/os-sdlc ``` The output lists the command/residual_dispatch_report.rb row as stale. ## Approach Scope of this pass: the second symptom only. An unchanged keep row (verdict `keep`, empty `new_path`) whose recorded path exists is current; `RowCheck` resolves it at the recorded path before any constant lookup, so it is never `ambiguous`. Part 1 shipped in implementation 76 (`RowCheck#unchanged_keep_in_place?`, AC 1-3 below, green). Part 2: the same last-segment fallback makes an applied move row under `cops/` ambiguous. `cops/` constants (`RuboCop::Cop::Sdlc::...`) have no Zeitwerk path, so `PathLookup#resolve_exact` always misses them. After #1153 the ledger row `cops/inward_dependency/ledger.rb` records the applied move to `cops/layer_ledger/ledger.rb` (`RuboCop::Cop::Sdlc::Structural::LayerLedger::Ledger`, commit 260d07de); that file exists and defines `Ledger`, yet the row reads ambiguous between it, `crc/ledger.rb` and `lint/gated_run/ledger.rb`. Required work: 1. In `RowCheck#resolve`, resolve an unchanged keep row whose recorded path exists at that path, before the constant lookup — check: present `keep` in `plugins/os-sdlc/lib/os_sdlc/crc/records/row_check.rb` 2. A row that is not pending resolves at its recorded path when that file exists and defines the last segment of the row's constant, before the last-segment glob. A recorded file that no longer defines it falls through to the lookup as now. ## Acceptance criteria 1. Given an unchanged keep row whose recorded path exists and whose constant's last segment is defined in two files, when crc-records runs, then the row is current, not ambiguous. 2. Given a rename or move row whose constant is defined in two files, when crc-records runs, then the row is still ambiguous and no path is guessed. 3. Given docs/crc/os-sdlc and plugins/os-sdlc/lib/os_sdlc on this branch, when the Reproduce command runs, then no unchanged `cops/` keep row is reported ambiguous. 4. Given an applied move row (commit set) whose recorded `new_path` exists and defines the last segment of `new_constant`, and that last segment is defined in two other files, when crc-records runs, then the row is current, not ambiguous. ## Owner sketch ```ruby class OsSdlc::Crc::Records::RowCheck def resolve # not pending, recorded file exists and defines the constant's last segment -> Resolution(:found, [recorded]) end ``` ## Non-goals The stale applied split row (first symptom) and the last-segment fallback in `PathLookup#defined_in` stay open on this ticket. ## Origin - Trigger: crc-records run in the os-sdlc Phase 7 run (split #1064, 720f911c) - Improvised this session: none - Chain: false stale row in the records step ← PathLookup#defined_in falls back to the last constant segment ← DESIGN: plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb - Root candidate: none known - Where: plugins/os-sdlc/lib/os_sdlc/crc_records/path_lookup.rb - Session: 2baa3b32-f47b-4c8b-9cdd-6270831fe640 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/2baa3b32-f47b-4c8b-9cdd-6270831fe640.jsonl VERDICT: CREATE — real defect in crc-records seen in the Phase 7 run; no existing mechanism covers it; parent #835 is user-filed.
Author
Owner

Occurrence: crc-records reports unchanged cops/ keep rows as ambiguous
Seen: plugins/os-sdlc/lib/os_sdlc/crc/records/path_lookup.rb (last-segment fallback); 10 keep rows under lib/os_sdlc/cops/ (feature_envy/site.rb, instance_variable_assumption/class_site.rb, inward_dependency/ledger.rb, lifecycle_ivar_behind_attr_reader/body_statements.rb, mutable_collection_leak_via_attr_reader/body_statements.rb, primitive_obsessed_ivar/class_site.rb, require_in_method/call.rb, unreachable_branch_after_guard/{branch,statements}.rb, unused_private_method/visibility_call.rb) listed under ambiguous with a target in another concept
Run: CRC refactor run 2, docs/crc/os-sdlc, session ca7a7686-22a8-4463-86d5-c542e7d9f215; records-report.json committed in the run dir
Adds: the cops/ case (RuboCop::Cop::Sdlc constants outside OsSdlc, file at the row path exists unchanged) makes crc-records exit 1 at close-out; a row whose path exists needs no lookup, and a cops constant maps to cops//.rb by path

Occurrence: crc-records reports unchanged cops/ keep rows as ambiguous Seen: plugins/os-sdlc/lib/os_sdlc/crc/records/path_lookup.rb (last-segment fallback); 10 keep rows under lib/os_sdlc/cops/ (feature_envy/site.rb, instance_variable_assumption/class_site.rb, inward_dependency/ledger.rb, lifecycle_ivar_behind_attr_reader/body_statements.rb, mutable_collection_leak_via_attr_reader/body_statements.rb, primitive_obsessed_ivar/class_site.rb, require_in_method/call.rb, unreachable_branch_after_guard/{branch,statements}.rb, unused_private_method/visibility_call.rb) listed under ambiguous with a target in another concept Run: CRC refactor run 2, docs/crc/os-sdlc, session ca7a7686-22a8-4463-86d5-c542e7d9f215; records-report.json committed in the run dir Adds: the cops/ case (RuboCop::Cop::Sdlc constants outside OsSdlc, file at the row path exists unchanged) makes crc-records exit 1 at close-out; a row whose path exists needs no lookup, and a cops constant maps to cops/<x>/<y>.rb by path
Author
Owner

Work started on branch ticket-1072 through /os-sdlc:implement, scoped to the ambiguous unchanged keep rows (see body Approach and Non-goals).

Work started on branch ticket-1072 through /os-sdlc:implement, scoped to the ambiguous unchanged keep rows (see body Approach and Non-goals).
Author
Owner

Occurrence (2026-10-19, ambiguous keep rows), not a close.
Done: an unchanged keep row whose recorded path exists is current, never ambiguous (implementation 76); any non-pending row resolves at its recorded path when that file exists and defines the constant's last segment (implementation 77). The ledger records the #1153 moves of InwardDependency::Ledger and ::LayerMap (e723d1b0).
Evidence: merged to main 6fe46aae. crc-records --target os-sdlc docs/crc/os-sdlc exits 0: 756 current, 0 stale, 0 ambiguous (was exit 1 with 9 ambiguous and 1 stale). Suite 2201 runs, 0 failures. The close-out exit 0 rule can now be met.
Follow-ups: the first symptom (stale applied split row through the last-segment fallback in PathLookup#defined_in) stays open on this ticket, per Non-goals.

Occurrence (2026-10-19, ambiguous keep rows), not a close. Done: an unchanged keep row whose recorded path exists is current, never ambiguous (implementation 76); any non-pending row resolves at its recorded path when that file exists and defines the constant's last segment (implementation 77). The ledger records the #1153 moves of InwardDependency::Ledger and ::LayerMap (e723d1b0). Evidence: merged to main 6fe46aae. `crc-records --target os-sdlc docs/crc/os-sdlc` exits 0: 756 current, 0 stale, 0 ambiguous (was exit 1 with 9 ambiguous and 1 stale). Suite 2201 runs, 0 failures. The close-out exit 0 rule can now be met. Follow-ups: the first symptom (stale applied split row through the last-segment fallback in PathLookup#defined_in) stays open on this ticket, per Non-goals.
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#1072
No description provided.