os-sdlc: Git namespace owns every git call; Project::Changes maps the change set; delete the five Runner diff classes #558

Closed
opened 2026-09-11 16:04:51 +00:00 by jared · 1 comment
Owner

Context

Four production classes run the git binary through their own Open3 calls instead of the existing adapter OsSdlc::Git (lib/os_sdlc/git.rb): Runner::PathDiff, Runner::DiffedRubyFiles, Project.git_repo? (project.rb:186), and test-support helpers. Five Runner classes answer diff questions with overlapping code: PathDiff, CodeDiff, TestDiff, DiffedRubyFiles, DiffedTestPaths. Git-shaped knowledge also hides in Implementation::Commit (changed/staged path math, commit.rb:38-55) and Runner::StateDump (rev-parse --abbrev-ref HEAD, state_dump.rb:59). ADR-0169 moved git work out of BriefFacts to the nearest owner in Runner; it did not choose Runner on purpose. Decision (user, 2026-09-11): one boundary. Git knows files and revisions; the project knows layout. One class per file.

Design

  • OsSdlc::Git becomes a module (Zeitwerk needs this to nest). Git::Repo absorbs today's adapter (run/read/succeeds?/capture) and owns repo queries: repo?, tracked?(path), changed_paths(glob:) (diff --name-only + ls-files --others), staged_paths, current_branch, stage(paths), commit(message, paths), diff(paths, base: "HEAD").
  • Git::Diff (repo, paths, base:) → unified diff; tracked paths vs base, untracked vs /dev/null. base: is the hook for #556.
  • Git::Worktree and Git::Branch: existing OsSdlc::Worktree and OsSdlc::Branch move under the namespace, logic unchanged, constructed with a Git::Repo.
  • Project::Changes (project, repo): code_paths, test_paths (changed test files + tests mapped from changed code files), code_diff, test_diff. CandidateTestPaths becomes Project#tests_for(code_file) or a Project collaborator. Git::Diff never learns code_path or test_path.
  • Callers updated: BriefFacts (code_changes/test_changes via Project::Changes), GateCommands (3 sites), Implementation::Commit (uses Repo#changed_paths/staged_paths/stage/commit), StateDump (Repo#current_branch), Project.git_repo? (Repo#repo?).
  • Deleted: Runner::PathDiff, CodeDiff, TestDiff, DiffedRubyFiles, DiffedTestPaths; class OsSdlc::Git.
  • Left alone with reason: hooks/lint_changed.rb (standalone hook, must not load lib), Project#boundary? (filesystem heuristic), plugins/os worktree CLI (other plugin, ADR-0157).

Tasks

  • ADR amending 0162, 0169, 0173: Git namespace, Project::Changes, class→module rename.
  • Git::Repo + tests (absorb git_test.rb).
  • Git::Diff + tests.
  • Git::Worktree, Git::Branch moves + test updates (worktree_test, branch_test, two cops tests).
  • Project::Changes + Project#tests_for + tests (replace diffed_test_paths_test, test_diff_test, code_diff_test).
  • Rewire BriefFacts, GateCommands, Implementation::Commit, StateDump, Project.git_repo?.
  • Delete the five Runner classes and old git.rb; suite green; rubocop clean; refresh-plugins.
  • Post-implementation sweep: grep for any remaining "git" shell-out outside Git::Repo and tests/support; report.
  • History row in docs/implementation-status/os-sdlc.md.

#555 (introduced PathDiff/CodeDiff), #556 (start commit → Git::Diff base:), ADR-0157, ADR-0162, ADR-0169, ADR-0173.

Origin

  • Trigger: user-named and user-approved design decision, 2026-09-11.
  • Improvised this session: none.
  • Chain: five overlapping Runner diff classes and scattered git shell-outs ← ADR-0169 chose Runner as owner without a deliberate boundary decision ← DESIGN (ADR-0169).
  • Root candidate: this ticket.
  • Where: lib/os_sdlc/git.rb, lib/os_sdlc/runner/path_diff.rb, lib/os_sdlc/runner/code_diff.rb, lib/os_sdlc/runner/test_diff.rb, lib/os_sdlc/runner/diffed_ruby_files.rb, lib/os_sdlc/runner/diffed_test_paths.rb, lib/os_sdlc/project.rb, lib/os_sdlc/implementation/commit.rb, lib/os_sdlc/runner/state_dump.rb
  • Session: 6d4567e1-5bdc-481a-9221-cfd012b7cc39
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/6d4567e1-5bdc-481a-9221-cfd012b7cc39.jsonl
## Context Four production classes run the git binary through their own Open3 calls instead of the existing adapter `OsSdlc::Git` (lib/os_sdlc/git.rb): `Runner::PathDiff`, `Runner::DiffedRubyFiles`, `Project.git_repo?` (project.rb:186), and test-support helpers. Five Runner classes answer diff questions with overlapping code: PathDiff, CodeDiff, TestDiff, DiffedRubyFiles, DiffedTestPaths. Git-shaped knowledge also hides in `Implementation::Commit` (changed/staged path math, commit.rb:38-55) and `Runner::StateDump` (`rev-parse --abbrev-ref HEAD`, state_dump.rb:59). ADR-0169 moved git work out of BriefFacts to the nearest owner in Runner; it did not choose Runner on purpose. Decision (user, 2026-09-11): one boundary. Git knows files and revisions; the project knows layout. One class per file. ## Design - `OsSdlc::Git` becomes a module (Zeitwerk needs this to nest). `Git::Repo` absorbs today's adapter (run/read/succeeds?/capture) and owns repo queries: `repo?`, `tracked?(path)`, `changed_paths(glob:)` (diff --name-only + ls-files --others), `staged_paths`, `current_branch`, `stage(paths)`, `commit(message, paths)`, `diff(paths, base: "HEAD")`. - `Git::Diff` (repo, paths, base:) → unified diff; tracked paths vs base, untracked vs /dev/null. `base:` is the hook for #556. - `Git::Worktree` and `Git::Branch`: existing `OsSdlc::Worktree` and `OsSdlc::Branch` move under the namespace, logic unchanged, constructed with a `Git::Repo`. - `Project::Changes` (project, repo): `code_paths`, `test_paths` (changed test files + tests mapped from changed code files), `code_diff`, `test_diff`. `CandidateTestPaths` becomes `Project#tests_for(code_file)` or a Project collaborator. Git::Diff never learns code_path or test_path. - Callers updated: `BriefFacts` (code_changes/test_changes via Project::Changes), `GateCommands` (3 sites), `Implementation::Commit` (uses Repo#changed_paths/staged_paths/stage/commit), `StateDump` (Repo#current_branch), `Project.git_repo?` (Repo#repo?). - Deleted: Runner::PathDiff, CodeDiff, TestDiff, DiffedRubyFiles, DiffedTestPaths; class `OsSdlc::Git`. - Left alone with reason: `hooks/lint_changed.rb` (standalone hook, must not load lib), `Project#boundary?` (filesystem heuristic), plugins/os worktree CLI (other plugin, ADR-0157). ## Tasks - [ ] ADR amending 0162, 0169, 0173: Git namespace, Project::Changes, class→module rename. - [ ] Git::Repo + tests (absorb git_test.rb). - [ ] Git::Diff + tests. - [ ] Git::Worktree, Git::Branch moves + test updates (worktree_test, branch_test, two cops tests). - [ ] Project::Changes + Project#tests_for + tests (replace diffed_test_paths_test, test_diff_test, code_diff_test). - [ ] Rewire BriefFacts, GateCommands, Implementation::Commit, StateDump, Project.git_repo?. - [ ] Delete the five Runner classes and old git.rb; suite green; rubocop clean; refresh-plugins. - [ ] Post-implementation sweep: grep for any remaining `"git"` shell-out outside Git::Repo and tests/support; report. - [ ] History row in docs/implementation-status/os-sdlc.md. ## Related #555 (introduced PathDiff/CodeDiff), #556 (start commit → Git::Diff base:), ADR-0157, ADR-0162, ADR-0169, ADR-0173. ## Origin - Trigger: user-named and user-approved design decision, 2026-09-11. - Improvised this session: none. - Chain: five overlapping Runner diff classes and scattered git shell-outs ← ADR-0169 chose Runner as owner without a deliberate boundary decision ← DESIGN (ADR-0169). - Root candidate: this ticket. - Where: lib/os_sdlc/git.rb, lib/os_sdlc/runner/path_diff.rb, lib/os_sdlc/runner/code_diff.rb, lib/os_sdlc/runner/test_diff.rb, lib/os_sdlc/runner/diffed_ruby_files.rb, lib/os_sdlc/runner/diffed_test_paths.rb, lib/os_sdlc/project.rb, lib/os_sdlc/implementation/commit.rb, lib/os_sdlc/runner/state_dump.rb - Session: 6d4567e1-5bdc-481a-9221-cfd012b7cc39 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/6d4567e1-5bdc-481a-9221-cfd012b7cc39.jsonl
Author
Owner

Resolution

Done: Git::Repo is the only class in lib/ that runs git (adapter verbs plus repo?, tracked?, changed_paths, staged_paths, current_branch, stage, commit, remote_url, diff); Git::Diff renders a path set against a base revision; Git::Worktree and Git::Branch moved under the namespace unchanged; Project::Changes owns code_paths/test_paths/code_diff/test_diff and Project#tests_for wraps CandidateTestPaths; five Runner diff classes and the old Git class deleted; BriefFacts, GateCommands, Implementation::Commit, StateDump, Project.git_repo?, IssueSource rewired; ADR-0174 amends 0162/0169/0173

Evidence: main 7fbc15f on 2026-09-11; suite 1192 runs 0 failures; rubocop clean on touched files; post-implementation sweep grep -rn '"git"' plugins/os-sdlc/lib shows only lib/os_sdlc/git/repo.rb; History row in docs/implementation-status/os-sdlc.md; bin/refresh-plugins run

Follow-ups: #556 start commit now plugs into Git::Diff base: and Repo#changed_paths(base:); left alone by decision: hooks/lint_changed.rb (standalone hook), Project#boundary? (filesystem heuristic), plugins/os worktree CLI (ADR-0157 boundary); pre-existing FeatureEnvy offense on StateDump#green_entry untouched, no ticket

## Resolution **Done:** Git::Repo is the only class in lib/ that runs git (adapter verbs plus repo?, tracked?, changed_paths, staged_paths, current_branch, stage, commit, remote_url, diff); Git::Diff renders a path set against a base revision; Git::Worktree and Git::Branch moved under the namespace unchanged; Project::Changes owns code_paths/test_paths/code_diff/test_diff and Project#tests_for wraps CandidateTestPaths; five Runner diff classes and the old Git class deleted; BriefFacts, GateCommands, Implementation::Commit, StateDump, Project.git_repo?, IssueSource rewired; ADR-0174 amends 0162/0169/0173 **Evidence:** main 7fbc15f on 2026-09-11; suite 1192 runs 0 failures; rubocop clean on touched files; post-implementation sweep grep -rn '"git"' plugins/os-sdlc/lib shows only lib/os_sdlc/git/repo.rb; History row in docs/implementation-status/os-sdlc.md; bin/refresh-plugins run **Follow-ups:** #556 start commit now plugs into Git::Diff base: and Repo#changed_paths(base:); left alone by decision: hooks/lint_changed.rb (standalone hook), Project#boundary? (filesystem heuristic), plugins/os worktree CLI (ADR-0157 boundary); pre-existing FeatureEnvy offense on StateDump#green_entry untouched, no ticket
jared closed this issue 2026-09-11 16:17:37 +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#558
No description provided.