Give the .sdlc artifact directory one owner: Project::ArtifactDir [capture] #572

Closed
opened 2026-09-14 13:45:05 +00:00 by jared · 2 comments
Owner

Context

The responsibility audit found that Project.sdlc_dir is the stated owner of
the .sdlc directory name, but eight sites build the path from the literal.
The .sdlc/tmp subdirectory has no owner at all. The repository cop at
lib/os_sdlc/cops/repeated_literal_argument.rb:81 already prescribes a
sdlc_dir(root) method for ".sdlc". Callers that would delegate:
Project.sdlc_dir, Project::Yaml#path, Runner::Db, hooks/post_tool_use.rb,
Timing, Lint, AutocorrectPrepass, LintWorklistTarget, RubocopReportFetcher,
Runner::GateHandoff.

Observed

List these sites verbatim:

lib/os_sdlc/project.rb:152 File.join(dir, ".sdlc")
lib/os_sdlc/project/yaml.rb:31 File.join(Project.sdlc_dir(root),
"project.yaml")
lib/os_sdlc/runner/db.rb:12 File.join(root, ".sdlc",
"pipeline.db")
hooks/post_tool_use.rb:42 File.join(root, ".sdlc",
"pipeline.db")
lib/os_sdlc/timing.rb:53 log_path = File.join(root, ".sdlc",
"tmp", "timing.jsonl")
lib/os_sdlc/lint.rb:65 File.join(@root ||
Array(@project_dir).first, ".sdlc", "tmp")
lib/os_sdlc/autocorrect_prepass.rb:101 File.join(@root || @project_dir,
".sdlc", "tmp")
lib/os_sdlc/lint_worklist_target.rb:99 File.join(root, ".sdlc", "tmp")
lib/os_sdlc/rubocop_report_fetcher.rb:12 LintWorklistRubocopConfig.
new(project_root).write(File.join(project_root, ".sdlc", "tmp"))
lib/os_sdlc/runner/gate_handoff.rb:121 LessonLibrary.new(dir: File.
join(project_root, ".sdlc", "lint-lessons"))

Reproduce

n/a: design ticket, no failing behavior

Expected

Prose: every .sdlc child path is produced by one object, and rg '".sdlc"'
lib hooks returns one definition site.

Illustration

illustration, not spec

class Project::ArtifactDir #
lib/os_sdlc/project/artifact_dir.rb
DIRNAME = ".sdlc"
def initialize(root) = @root = root

def path        = File.join(@root, DIRNAME)                             
def tmp         = File.join(path, "tmp")                                
def pipeline_db = File.join(path, "pipeline.db")                        

end

Origin

• Trigger: /os-sdlc:responsibility-audit run 13 on plugins/os-
sdlc/lib/os_sdlc/project.rb, 2026-09-14
• Improvised this session: none
• Chain: eight literal sites ← no owner for child paths ← Project.sdlc_dir
added without a migration of existing callers (DESIGN, lib/os_sdlc/project.
rb:152)
• Root candidate: this ticket
• Where: lib/os_sdlc/project.rb
• Session: 23a382aa-f78e-495f-9cbd-0934e163b37d
• Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/23a382aa-
f78e-495f-9cbd-0934e163b37d.jsonl

Tasks

  • Add Project::ArtifactDir at lib/os_sdlc/project/artifact_dir.rb with path, tmp, pipeline_db, lint_lessons.
  • Project.sdlc_dir(dir) returns Project::ArtifactDir.new(dir).path.

Acceptance criteria

  • Project::ArtifactDir.new("/r").path is /r/.sdlc.
  • Project::ArtifactDir.new("/r").tmp is /r/.sdlc/tmp.
  • Project::ArtifactDir.new("/r").pipeline_db is /r/.sdlc/pipeline.db.
  • Project.sdlc_dir("/r") still returns /r/.sdlc.

Structural follow-through

  • The ten sites in Observed delegate to Project::ArtifactDir: Project::Yaml#path, Runner::Db, hooks/post_tool_use.rb, Timing, Lint, AutocorrectPrepass, LintWorklistTarget, RubocopReportFetcher, Runner::GateHandoff.
  • Check: rg -n '"\.sdlc"' plugins/os-sdlc/lib plugins/os-sdlc/hooks returns only project/artifact_dir.rb.
  • Do not bump SCHEMA_VERSION in Runner::Db.

ADR case

Amends ADR-0177 (the .sdlc name moves from Project to the nested Project::ArtifactDir; still under Project). Create the amending ADR when this ticket lands. ADR-0128 (thin hooks) unchanged.

Batch

Map: #570. Position 4 of 4. Follows #574. Last in batch. Map: maps/poodr-ticket-implementation.yaml.

## Context The responsibility audit found that Project.sdlc_dir is the stated owner of the .sdlc directory name, but eight sites build the path from the literal. The .sdlc/tmp subdirectory has no owner at all. The repository cop at lib/os_sdlc/cops/repeated_literal_argument.rb:81 already prescribes a sdlc_dir(root) method for ".sdlc". Callers that would delegate: Project.sdlc_dir, Project::Yaml#path, Runner::Db, hooks/post_tool_use.rb, Timing, Lint, AutocorrectPrepass, LintWorklistTarget, RubocopReportFetcher, Runner::GateHandoff. ## Observed List these sites verbatim: lib/os_sdlc/project.rb:152 File.join(dir, ".sdlc") lib/os_sdlc/project/yaml.rb:31 File.join(Project.sdlc_dir(root), "project.yaml") lib/os_sdlc/runner/db.rb:12 File.join(root, ".sdlc", "pipeline.db") hooks/post_tool_use.rb:42 File.join(root, ".sdlc", "pipeline.db") lib/os_sdlc/timing.rb:53 log_path = File.join(root, ".sdlc", "tmp", "timing.jsonl") lib/os_sdlc/lint.rb:65 File.join(@root || Array(@project_dir).first, ".sdlc", "tmp") lib/os_sdlc/autocorrect_prepass.rb:101 File.join(@root || @project_dir, ".sdlc", "tmp") lib/os_sdlc/lint_worklist_target.rb:99 File.join(root, ".sdlc", "tmp") lib/os_sdlc/rubocop_report_fetcher.rb:12 LintWorklistRubocopConfig. new(project_root).write(File.join(project_root, ".sdlc", "tmp")) lib/os_sdlc/runner/gate_handoff.rb:121 LessonLibrary.new(dir: File. join(project_root, ".sdlc", "lint-lessons")) ## Reproduce n/a: design ticket, no failing behavior ## Expected Prose: every .sdlc child path is produced by one object, and rg '"\.sdlc"' lib hooks returns one definition site. ## Illustration # illustration, not spec class Project::ArtifactDir # lib/os_sdlc/project/artifact_dir.rb DIRNAME = ".sdlc" def initialize(root) = @root = root def path = File.join(@root, DIRNAME) def tmp = File.join(path, "tmp") def pipeline_db = File.join(path, "pipeline.db") end ## Origin • Trigger: /os-sdlc:responsibility-audit run 13 on plugins/os- sdlc/lib/os_sdlc/project.rb, 2026-09-14 • Improvised this session: none • Chain: eight literal sites ← no owner for child paths ← Project.sdlc_dir added without a migration of existing callers (DESIGN, lib/os_sdlc/project. rb:152) • Root candidate: this ticket • Where: lib/os_sdlc/project.rb • Session: 23a382aa-f78e-495f-9cbd-0934e163b37d • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/23a382aa- f78e-495f-9cbd-0934e163b37d.jsonl ## Tasks - [ ] Add `Project::ArtifactDir` at lib/os_sdlc/project/artifact_dir.rb with `path`, `tmp`, `pipeline_db`, `lint_lessons`. - [ ] `Project.sdlc_dir(dir)` returns `Project::ArtifactDir.new(dir).path`. ## Acceptance criteria - `Project::ArtifactDir.new("/r").path` is `/r/.sdlc`. - `Project::ArtifactDir.new("/r").tmp` is `/r/.sdlc/tmp`. - `Project::ArtifactDir.new("/r").pipeline_db` is `/r/.sdlc/pipeline.db`. - `Project.sdlc_dir("/r")` still returns `/r/.sdlc`. ## Structural follow-through - The ten sites in Observed delegate to `Project::ArtifactDir`: `Project::Yaml#path`, `Runner::Db`, `hooks/post_tool_use.rb`, `Timing`, `Lint`, `AutocorrectPrepass`, `LintWorklistTarget`, `RubocopReportFetcher`, `Runner::GateHandoff`. - Check: `rg -n '"\.sdlc"' plugins/os-sdlc/lib plugins/os-sdlc/hooks` returns only project/artifact_dir.rb. - Do not bump `SCHEMA_VERSION` in `Runner::Db`. ## ADR case Amends ADR-0177 (the `.sdlc` name moves from `Project` to the nested `Project::ArtifactDir`; still under `Project`). Create the amending ADR when this ticket lands. ADR-0128 (thin hooks) unchanged. ## Batch Map: #570. Position 4 of 4. Follows #574. Last in batch. Map: maps/poodr-ticket-implementation.yaml.
Author
Owner

Work started via /os-sdlc:responsibility-refactor batch 2 (map #570). Branch: ticket-572, worktree .claude/worktrees/ticket-572, map poodr-ticket-implementation.yaml.

Work started via /os-sdlc:responsibility-refactor batch 2 (map #570). Branch: ticket-572, worktree .claude/worktrees/ticket-572, map poodr-ticket-implementation.yaml.
Author
Owner

Resolution

Done: Project::ArtifactDir (project/artifact_dir.rb) owns .sdlc and its child paths: path, tmp, pipeline_db, lint_lessons. Project.sdlc_dir and nine sites delegate (Yaml via sdlc_dir, Runner::Db, post_tool_use hook, Timing, Lint, AutocorrectPrepass, LintWorklistTarget, RubocopReportFetcher, GateHandoff). ADR-0181 amends ADR-0177.

Evidence: Merged to main ca5e3d9 (code 7734902). Suite 1233 runs, 0 failures; rubocop clean on 11 touched files; pre- and post-tool-use hooks smoke-tested; rg for the .sdlc literal under lib/hooks/bin returns only artifact_dir.rb and the cop catalog entry. Pipeline: 10 dispatches, 632 s, implementation_complete, one test-reviewer rejection; two await_completion stalls hand-settled by gating and subagent-stop. Deviation: structural follow-through applied by hand; first attempt broke both hooks at boot (project.rb required json pre-boot), caught by TimingBootSafetyTest; fixed by moving the json require into Project::Config. SCHEMA_VERSION untouched. Position 4 of 4 on map #570.

Follow-ups: none. Re-audit of the batch runs next per map #570.

## Resolution **Done:** Project::ArtifactDir (project/artifact_dir.rb) owns .sdlc and its child paths: path, tmp, pipeline_db, lint_lessons. Project.sdlc_dir and nine sites delegate (Yaml via sdlc_dir, Runner::Db, post_tool_use hook, Timing, Lint, AutocorrectPrepass, LintWorklistTarget, RubocopReportFetcher, GateHandoff). ADR-0181 amends ADR-0177. **Evidence:** Merged to main ca5e3d9 (code 7734902). Suite 1233 runs, 0 failures; rubocop clean on 11 touched files; pre- and post-tool-use hooks smoke-tested; rg for the .sdlc literal under lib/hooks/bin returns only artifact_dir.rb and the cop catalog entry. Pipeline: 10 dispatches, 632 s, implementation_complete, one test-reviewer rejection; two await_completion stalls hand-settled by gating and subagent-stop. Deviation: structural follow-through applied by hand; first attempt broke both hooks at boot (project.rb required json pre-boot), caught by TimingBootSafetyTest; fixed by moving the json require into Project::Config. SCHEMA_VERSION untouched. Position 4 of 4 on map #570. **Follow-ups:** none. Re-audit of the batch runs next per map #570.
jared closed this issue 2026-09-14 15:23:17 +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#572
No description provided.