Callers read the bound Target; Project loses target/test/lint/code/map, FlatAttrs, and ProjectTargets (coding map) #795

Closed
opened 2026-09-28 14:17:15 +00:00 by jared · 5 comments
Owner

Problem

After T2 and T3, a Project holds targets, and it also still holds the selected target's target, test, and lint. That is two sources for one fact. Project#code is an alias kept only for callers (ADR-0210 rule 2). map is set from the yaml but is never read (no project.map caller in lib) and is not persisted.

Reproduce

n/a: behavior-preserving. Run on maps/coding.yaml.

Approach

Files, lib (about 10): model/project.rb, model/project/flat_attrs.rb (delete), model/project_targets.rb (delete; its three TargetSelectionError checks move to Project#target(name), used by Config.load and Open), model/project/codebase.rb (built from a Target), model/diff_test_plan.rb, model/project/validation.rb, query/project/changes.rb, query/gate/commands.rb, command/autocorrect_prepass/pass.rb (shared lint config), parser/project/snapshot.rb. Tests: about 9 that read project.test, project.lint, or project.target.
If the file count is over 8, split: T7a moves Codebase, Changes, DiffTestPlan, and Gate::Commands to the Target. T7b deletes the members, FlatAttrs, and ProjectTargets.
ADRs: this completes the T3 ADR (ADR-0192 items 1/3/4, ADR-0210 rules 1-2). Cited: ADR-0088 (the three selection errors keep their text), ADR-0213.

Required work:

  1. Replace project.test, project.lint, project.target, and project.code with the bound Target. — check: ! grep -rnE "project\)?\.(test|lint|target|code)\b" plugins/os-sdlc/lib
  2. Delete FlatAttrs and ProjectTargets. Target.from_section(name, hash) is the one flat-hash constructor, for both the yaml and the snapshot. — check: ! grep -rn "FlatAttrs\|ProjectTargets" plugins/os-sdlc
  3. Project.members == [:name, :path, :tracker, :commit_on_complete, :targets] — check: ruby plugins/os-sdlc/tests/all.rb

Rejected: keep Project#test as a delegator to the bound target. A Project has no bound target. Only an implementation or a --target run has one.

Acceptance criteria

  1. Given the full suite, when it runs, then it passes and no lib code reads a selected target from Project.

Owner sketch

OsSdlc::Project = Data.define(:name, :path, :tracker, :commit_on_complete, :targets) do
  def target(name)   # TargetSelectionError: none selected / unknown / --target on flat
end
OsSdlc::Project::Target  # def self.from_section(name, flat); def codebase(root)

Non-goals

path to root (T8).

Blocking edges

Blocked by: T3

Origin

  • Trigger: user ruling R5 (FlatAttrs "may not be needed any more"; delete Project#code)
  • Improvised this session: none
  • Chain: DESIGN: ADR-0192 item 4, ADR-0210 rule 2
  • Where: plugins/os-sdlc/lib/os_sdlc/model/project.rb, model/project/flat_attrs.rb, model/project_targets.rb
  • Session: bb36e383-017d-486e-809f-7ce25d151e61
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-pass-os-sdlc/bb36e383-017d-486e-809f-7ce25d151e61.jsonl
## Problem After T2 and T3, a Project holds `targets`, and it also still holds the selected target's `target`, `test`, and `lint`. That is two sources for one fact. `Project#code` is an alias kept only for callers (ADR-0210 rule 2). `map` is set from the yaml but is never read (no `project.map` caller in lib) and is not persisted. ## Reproduce n/a: behavior-preserving. Run on `maps/coding.yaml`. ## Approach Files, lib (about 10): model/project.rb, model/project/flat_attrs.rb (delete), model/project_targets.rb (delete; its three TargetSelectionError checks move to `Project#target(name)`, used by Config.load and Open), model/project/codebase.rb (built from a Target), model/diff_test_plan.rb, model/project/validation.rb, query/project/changes.rb, query/gate/commands.rb, command/autocorrect_prepass/pass.rb (shared lint config), parser/project/snapshot.rb. Tests: about 9 that read `project.test`, `project.lint`, or `project.target`. If the file count is over 8, split: T7a moves Codebase, Changes, DiffTestPlan, and Gate::Commands to the Target. T7b deletes the members, FlatAttrs, and ProjectTargets. ADRs: this completes the T3 ADR (ADR-0192 items 1/3/4, ADR-0210 rules 1-2). Cited: ADR-0088 (the three selection errors keep their text), ADR-0213. Required work: 1. Replace `project.test`, `project.lint`, `project.target`, and `project.code` with the bound Target. — check: `! grep -rnE "project\)?\.(test|lint|target|code)\b" plugins/os-sdlc/lib` 2. Delete FlatAttrs and ProjectTargets. `Target.from_section(name, hash)` is the one flat-hash constructor, for both the yaml and the snapshot. — check: `! grep -rn "FlatAttrs\|ProjectTargets" plugins/os-sdlc` 3. `Project.members == [:name, :path, :tracker, :commit_on_complete, :targets]` — check: `ruby plugins/os-sdlc/tests/all.rb` Rejected: keep `Project#test` as a delegator to the bound target. A Project has no bound target. Only an implementation or a `--target` run has one. ## Acceptance criteria 1. Given the full suite, when it runs, then it passes and no lib code reads a selected target from Project. ## Owner sketch ```ruby OsSdlc::Project = Data.define(:name, :path, :tracker, :commit_on_complete, :targets) do def target(name) # TargetSelectionError: none selected / unknown / --target on flat end OsSdlc::Project::Target # def self.from_section(name, flat); def codebase(root) ``` ## Non-goals `path` to `root` (T8). ## Blocking edges Blocked by: T3 ## Origin - Trigger: user ruling R5 (FlatAttrs "may not be needed any more"; delete Project#code) - Improvised this session: none - Chain: DESIGN: ADR-0192 item 4, ADR-0210 rule 2 - Where: plugins/os-sdlc/lib/os_sdlc/model/project.rb, model/project/flat_attrs.rb, model/project_targets.rb - Session: bb36e383-017d-486e-809f-7ce25d151e61 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-pass-os-sdlc/bb36e383-017d-486e-809f-7ce25d151e61.jsonl
Author
Owner

Carried from #792 review (fresh opus read): (1) Target.from_blob belongs in Project::Snapshot (lens A1); (2) the blob's target_name and the row's target column duplicate the bound-target choice (A12), make Snapshot the one chooser; (3) Project#to_config_h and #to_flat_h have no lib callers, only project_path_test.rb:30 uses them as a legacy fixture; (4) Target#bound_as drops test and lint, rename or remove when project.target retires; (5) tighten snapshot_name_guard_test.rb to match the full message; (6) implementation_project_test.rb:17 has two pre-existing alignment offenses.

Carried from #792 review (fresh opus read): (1) Target.from_blob belongs in Project::Snapshot (lens A1); (2) the blob's target_name and the row's target column duplicate the bound-target choice (A12), make Snapshot the one chooser; (3) Project#to_config_h and #to_flat_h have no lib callers, only project_path_test.rb:30 uses them as a legacy fixture; (4) Target#bound_as drops test and lint, rename or remove when project.target retires; (5) tighten snapshot_name_guard_test.rb to match the full message; (6) implementation_project_test.rb:17 has two pre-existing alignment offenses.
Author
Owner

Carried from #794 review: Project#tracker_required_message (model/project.rb) renders a reader-facing error string inside the model (lens A1, presenter verb). Move it beside the setup presenter when T7 reshapes Project.

Carried from #794 review: Project#tracker_required_message (model/project.rb) renders a reader-facing error string inside the model (lens A1, presenter verb). Move it beside the setup presenter when T7 reshapes Project.
Author
Owner

Work started on branch ticket-795 via /os-sdlc:implement, coding map (session bb36e383). #794 merged to main.

Work started on branch ticket-795 via /os-sdlc:implement, coding map (session bb36e383). #794 merged to main.
Author
Owner

Session bb36e383 wrapped mid-run. Implementation 60 (coding map) programmer dispatch 625 did not return before wrap. Partial work (42 files, FlatAttrs deleted, callers moved to the bound Target) is preserved as a WIP commit on branch ticket-795 in worktree .claude/worktrees/ticket-795. It is NOT gated. Next session: run the suite there; either continue from that state with a new implementation-open, or discard the branch and rerun.

Session bb36e383 wrapped mid-run. Implementation 60 (coding map) programmer dispatch 625 did not return before wrap. Partial work (42 files, FlatAttrs deleted, callers moved to the bound Target) is preserved as a WIP commit on branch ticket-795 in worktree .claude/worktrees/ticket-795. It is NOT gated. Next session: run the suite there; either continue from that state with a new implementation-open, or discard the branch and rerun.
Author
Owner

Resolution

Done: Callers read the bound Target through Project#target(name); Project is Data(name, path, tracker, commit_on_complete, targets); FlatAttrs and ProjectTargets deleted; the three TargetSelectionError checks moved into Project private methods with byte-identical messages; Target.from_section is the sole flat-hash constructor; Target#codebase(root) replaces Project#codebase

Evidence: branch ticket-795 merged to main, head 150727e8; suite 1298 runs 0 failures 0 errors; rubocop 0 offenses on 16 changed lib files; 43 files changed +260 -572

Follow-ups: none

## Resolution **Done:** Callers read the bound Target through Project#target(name); Project is Data(name, path, tracker, commit_on_complete, targets); FlatAttrs and ProjectTargets deleted; the three TargetSelectionError checks moved into Project private methods with byte-identical messages; Target.from_section is the sole flat-hash constructor; Target#codebase(root) replaces Project#codebase **Evidence:** branch ticket-795 merged to main, head 150727e8; suite 1298 runs 0 failures 0 errors; rubocop 0 offenses on 16 changed lib files; 43 files changed +260 -572 **Follow-ups:** none
jared closed this issue 2026-09-28 16:48:23 +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#795
No description provided.