Delete the duplicate nested project.yaml files #1519

Open
opened 2026-11-02 23:48:26 +00:00 by jared · 3 comments
Owner

Problem

Two nested .sdlc/project.yaml files duplicate the root file.
plugins/os-backlog/.sdlc/project.yaml and plugins/os-sdlc/.sdlc/project.yaml describe targets that /home/jared/dev/cc-os/.sdlc/project.yaml already lists under targets: with the same paths and test commands.
Project::RootSearch.outermost picks the cc-os root, so neither nested file is read from inside cc-os.
A dead second copy of a config can drift and mislead.

Observed

Key comparison (nested vs root target of the same name):

key os-backlog nested root target os-backlog os-sdlc nested root target os-sdlc
path lib plugins/os-backlog absent plugins/os-sdlc
test_path tests plugins/os-backlog/tests tests plugins/os-sdlc/tests
test_command ruby tests/all.rb ruby plugins/os-backlog/tests/all.rb ruby tests/all.rb ruby plugins/os-sdlc/tests/all.rb
lint_config absent plugins/os-backlog/.rubocop.yml absent plugins/os-sdlc/.rubocop.yml
tracker forgejo:jared/cc-os root forgejo:jared/cc-os same same

The nested paths are plugin-relative; the root paths are repo-relative.
The nested os-backlog path: lib differs from the root path: plugins/os-backlog.
Last change to both files: b875b231 (#832).

Risk check (done before filing):

  • Callers of RootSearch in plugins/os-sdlc/lib (boot.rb:57, boot/project_bind.rb, project/config.rb, daemon/navigation.rb, lint/sweeping.rb) all take a cwd from Dir.pwd or a hook event cwd.
  • Dir.pwd is the real path, even when the shell entered through the symlink ~/.claude/plugins/os-sdlc. A check from that symlink gives /home/jared/dev/cc-os/plugins/os-sdlc, inside the cc-os tree, so outermost finds the cc-os root.
  • No hook in os-sdlc/hooks/hooks.json or os-backlog/hooks/hooks.json passes CLAUDE_PLUGIN_ROOT as a project dir.
  • One path does find a nested file: calling RootSearch.outermost("~/.claude/plugins/os-sdlc") with the symlink path string returns /home/jared/.claude/plugins/os-sdlc. No caller passes that string. After the deletion, that call returns nil and the caller refuses loudly, which is correct.
  • The plugin cache holds real-directory copies of both files (~/.claude/plugins/cache/local-plugins/os-sdlc/0.1.0/.sdlc/project.yaml and .../os-backlog/0.3.0/.sdlc/project.yaml), outside the cc-os git tree. outermost would find them from a cwd inside the cache. No hook, skill or bin script sets its cwd to the plugin root or the cache (grep of plugins/*/hooks, skills, bin found none), so only a manual cd reaches them. bin/refresh-plugins removes them from the cache after the deletion.
  • Risk is not real; the ticket is a plain deletion.
  • Local note: plugins/os-sdlc/.sdlc/ also holds untracked pipeline.db, pipeline.db.stale, tickets, tmp. This ticket does not touch them.

Reproduce

n/a: cleanup of duplicate config, no failing behavior.

Approach

Delete both nested files.

Required work:

  1. Delete the os-sdlc nested file
  2. Delete the os-backlog nested file

Acceptance criteria

  1. Given both files are deleted, when the os-sdlc suite and the os-backlog suite run, then both are green.
  2. Given a shell at the cc-os root, when an os-sdlc command binds a project, then it binds the root .sdlc/project.yaml as before.
  3. Given the repo, when searched for plugins/os-sdlc/.sdlc/project.yaml and plugins/os-backlog/.sdlc/project.yaml, then no code reads those paths. Doc and ledger-fixture mentions (docs/os-sdlc-rebuild/interface-sketches.md:2176, plugins/os-sdlc/tests/fixtures/crc/os-sdlc-ledger-88a6bd35.tsv, plugins/os-sdlc/tests/fixtures/crc_shares/run2/ledger-pre-wave2.tsv) are historical text, not reads.

Orchestrator work: run bin/refresh-plugins after the deletion.

Owner sketch

No new objects. Two files are deleted.

Non-goals

The untracked pipeline.db files under plugins/os-sdlc/.sdlc/.

Origin

  • Trigger: review of Project::RootSearch.outermost while checking which project.yaml binds.
  • Improvised this session: none
  • Chain: duplicate config ← plugins were once project roots ← DESIGN (b875b231, #832)
  • Root candidate: none found; searched project.yaml, nested, .sdlc, RootSearch, duplicate config
    VERDICT: CREATE
  • Where: plugins/os-sdlc/.sdlc/project.yaml, plugins/os-backlog/.sdlc/project.yaml
  • Session: d077e084-9195-4803-b761-6ce01eca0249
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/d077e084-9195-4803-b761-6ce01eca0249.jsonl
## Problem Two nested `.sdlc/project.yaml` files duplicate the root file. `plugins/os-backlog/.sdlc/project.yaml` and `plugins/os-sdlc/.sdlc/project.yaml` describe targets that `/home/jared/dev/cc-os/.sdlc/project.yaml` already lists under `targets:` with the same paths and test commands. `Project::RootSearch.outermost` picks the cc-os root, so neither nested file is read from inside cc-os. A dead second copy of a config can drift and mislead. ## Observed Key comparison (nested vs root target of the same name): | key | os-backlog nested | root target os-backlog | os-sdlc nested | root target os-sdlc | |---|---|---|---|---| | path | `lib` | `plugins/os-backlog` | absent | `plugins/os-sdlc` | | test_path | `tests` | `plugins/os-backlog/tests` | `tests` | `plugins/os-sdlc/tests` | | test_command | `ruby tests/all.rb` | `ruby plugins/os-backlog/tests/all.rb` | `ruby tests/all.rb` | `ruby plugins/os-sdlc/tests/all.rb` | | lint_config | absent | `plugins/os-backlog/.rubocop.yml` | absent | `plugins/os-sdlc/.rubocop.yml` | | tracker | `forgejo:jared/cc-os` | root `forgejo:jared/cc-os` | same | same | The nested paths are plugin-relative; the root paths are repo-relative. The nested os-backlog `path: lib` differs from the root `path: plugins/os-backlog`. Last change to both files: `b875b231` (#832). Risk check (done before filing): - Callers of `RootSearch` in `plugins/os-sdlc/lib` (`boot.rb:57`, `boot/project_bind.rb`, `project/config.rb`, `daemon/navigation.rb`, `lint/sweeping.rb`) all take a cwd from `Dir.pwd` or a hook event cwd. - `Dir.pwd` is the real path, even when the shell entered through the symlink `~/.claude/plugins/os-sdlc`. A check from that symlink gives `/home/jared/dev/cc-os/plugins/os-sdlc`, inside the cc-os tree, so `outermost` finds the cc-os root. - No hook in `os-sdlc/hooks/hooks.json` or `os-backlog/hooks/hooks.json` passes `CLAUDE_PLUGIN_ROOT` as a project dir. - One path does find a nested file: calling `RootSearch.outermost("~/.claude/plugins/os-sdlc")` with the symlink path string returns `/home/jared/.claude/plugins/os-sdlc`. No caller passes that string. After the deletion, that call returns nil and the caller refuses loudly, which is correct. - The plugin cache holds real-directory copies of both files (`~/.claude/plugins/cache/local-plugins/os-sdlc/0.1.0/.sdlc/project.yaml` and `.../os-backlog/0.3.0/.sdlc/project.yaml`), outside the cc-os git tree. `outermost` would find them from a cwd inside the cache. No hook, skill or bin script sets its cwd to the plugin root or the cache (grep of `plugins/*/hooks`, `skills`, `bin` found none), so only a manual `cd` reaches them. `bin/refresh-plugins` removes them from the cache after the deletion. - Risk is not real; the ticket is a plain deletion. - Local note: `plugins/os-sdlc/.sdlc/` also holds untracked `pipeline.db`, `pipeline.db.stale`, `tickets`, `tmp`. This ticket does not touch them. ## Reproduce n/a: cleanup of duplicate config, no failing behavior. ## Approach Delete both nested files. Required work: 1. Delete the os-sdlc nested file 2. Delete the os-backlog nested file ## Acceptance criteria 1. Given both files are deleted, when the os-sdlc suite and the os-backlog suite run, then both are green. 2. Given a shell at the cc-os root, when an `os-sdlc` command binds a project, then it binds the root `.sdlc/project.yaml` as before. 3. Given the repo, when searched for `plugins/os-sdlc/.sdlc/project.yaml` and `plugins/os-backlog/.sdlc/project.yaml`, then no code reads those paths. Doc and ledger-fixture mentions (`docs/os-sdlc-rebuild/interface-sketches.md:2176`, `plugins/os-sdlc/tests/fixtures/crc/os-sdlc-ledger-88a6bd35.tsv`, `plugins/os-sdlc/tests/fixtures/crc_shares/run2/ledger-pre-wave2.tsv`) are historical text, not reads. Orchestrator work: run `bin/refresh-plugins` after the deletion. ## Owner sketch No new objects. Two files are deleted. ## Non-goals The untracked `pipeline.db` files under `plugins/os-sdlc/.sdlc/`. ## Origin - Trigger: review of `Project::RootSearch.outermost` while checking which project.yaml binds. - Improvised this session: none - Chain: duplicate config ← plugins were once project roots ← DESIGN (`b875b231`, #832) - Root candidate: none found; searched project.yaml, nested, .sdlc, RootSearch, duplicate config VERDICT: CREATE - Where: plugins/os-sdlc/.sdlc/project.yaml, plugins/os-backlog/.sdlc/project.yaml - Session: d077e084-9195-4803-b761-6ce01eca0249 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/d077e084-9195-4803-b761-6ce01eca0249.jsonl
Author
Owner

Work started on branch ticket-1519 through /os-sdlc:implement.

Work started on branch `ticket-1519` through /os-sdlc:implement.
Author
Owner

Ticket defect corrected: the two required-work checks were absent ... in <deleted file>. After the deletion the glob matches no file, so they could never pass (implementation 227, structure-changer dispatch 2078 escalated). Checks removed; the acceptance criteria (suites green, root project binds, no code reads the paths) prove the work.

Ticket defect corrected: the two required-work checks were `absent ... in <deleted file>`. After the deletion the glob matches no file, so they could never pass (implementation 227, structure-changer dispatch 2078 escalated). Checks removed; the acceptance criteria (suites green, root project binds, no code reads the paths) prove the work.
Author
Owner

Blocked: deleting the nested files breaks behavior. Project::RootSearch (project/root_search.rb:15) returns the nearest .sdlc/project.yaml, so from plugins/os-sdlc the lint sweep (lint/sweeping.rb:40) reports plugin-relative paths and uses the plugin config; LintSweepTest#test_sweep_reports_the_same_inward_dependency_offenses_from_the_repo_root_and_the_plugin_directory fails after deletion. Target-less Config.load from a plugin dir would raise TargetSelectionError against the targets-shaped root file. Recommendation: keep the files and close this ticket. Implementation 227 abandoned; awaiting Jared's ruling.

Blocked: deleting the nested files breaks behavior. Project::RootSearch (project/root_search.rb:15) returns the nearest .sdlc/project.yaml, so from plugins/os-sdlc the lint sweep (lint/sweeping.rb:40) reports plugin-relative paths and uses the plugin config; LintSweepTest#test_sweep_reports_the_same_inward_dependency_offenses_from_the_repo_root_and_the_plugin_directory fails after deletion. Target-less Config.load from a plugin dir would raise TargetSelectionError against the targets-shaped root file. Recommendation: keep the files and close this ticket. Implementation 227 abandoned; awaiting Jared's ruling.
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#1519
No description provided.