system-model resolves its root through the os-sdlc project target #1516

Closed
opened 2026-11-02 23:12:48 +00:00 by jared · 2 comments
Owner

Problem

system-model does not find its root through the Project target logic that the other os-sdlc commands use.
It needs an explicit path argument, so it ignores .sdlc/project.yaml.
In cc-os, .sdlc/project.yaml lists many codebases under targets:; Jared ruled that system-model must resolve its root through that same logic, with shared code and no new resolver.
Related: #1515 (fail loudly on an empty root) is open with no "work started" comment. It guards the explicit-path root in SystemModel::Run; this ticket adds a second way to reach that root. See Non-goals.

Reproduce

n/a: design change. Today system-model generate with no argument prints the usage text and exits 2 (plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:68).

Approach

How the other commands choose a target today: only by an explicit --target NAME flag. ArgvOption.take!(argv, "--target NAME") (boot/inputs.rb:51, :207; CrcArgv.target! for the crc commands; bin/lint-worklist:9) fills Input#target. Boot#third_argument (boot.rb:71-74) then calls ProjectBind#project(dir, target:) (boot/project_bind.rb:17-20), which calls Project::Config.load. Project#target (project.rb:46-52) raises TargetSelectionError with "no target selected ... Available: " when the project defines named targets and none is given. No existing command infers the target from the cwd.
Design:

  1. Inputs.system_model_root takes --target NAME with ArgvOption.take! and sets Input#target. With a target, no path argument is allowed.
  2. With no path argument and no --target, Input#target stays nil. Project#target then resolves a single-target project to the project root, and refuses a multi-target root and lists the targets (project.rb:80-84). No cwd inference.
  3. The system-model action in boot/commands.rb:132-139 receives a Project when a target is set. It computes the scan root as File.join(project.root, project.target.path) and passes that String to SystemModel::Run as today.
  4. An explicit path argument keeps root: set, so Boot#third_argument returns it unchanged.
    Reused: ArgvOption.take!, Input#target, Boot#third_argument, ProjectBind#project, Project::Config.load, Project#target, TargetSelectionError. New code: the root computation in step 3 (about 2 lines); the flag and wiring are about 4 lines. No new resolver class.
    Fit with #1515: the empty-lib/ refusal in Run#call applies to the root from every source, so a target path with no Ruby files also fails loudly. The two tickets touch different files except commands.rb/inputs.rb versus run.rb; either can land first.

Required work:

  1. Accept --target NAME in system_model_root — check: present --target NAME in plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb
  2. Derive the scan root from the Project target in the system-model action — check: present project.target.path in plugins/os-sdlc/lib/os_sdlc/boot/commands.rb
  3. Add tests — check: present --target in plugins/os-sdlc/tests/system_model_cli_test.rb

Orchestrator work: run bin/refresh-plugins; add one History row to docs/implementation-status/os-sdlc-system-model.md; update the usage text. A project with no .sdlc/project.yaml gets one through /os:fix, as for every other project.

Acceptance criteria

  1. Given any cwd inside cc-os, when system-model generate --target os-me runs, then it scans plugins/os-me.
  2. Given the cc-os root as cwd and no target, when system-model generate runs, then it exits nonzero and the error lists the available targets, as other commands do.
  3. Given an explicit path argument, when system-model generate <path> runs, then it scans that path as before.
  4. Given a single-target project with no targets: key, when system-model generate runs from its root with no argument, then it scans the project root.

Owner sketch

module OsSdlc::Boot::Inputs
  def self.system_model_root(io, argv, subcommand)
end

Non-goals

Removing the nested plugins/os-backlog/.sdlc/project.yaml and plugins/os-sdlc/.sdlc/project.yaml. system-model shapes. Adding cwd inference to other commands. cwd inference is out of scope; if wanted, it becomes a shared feature for all commands in its own ticket. The empty-root refusal (#1515).

Origin

  • Trigger: Jared's ruling this session that system-model must use the os-sdlc Project target logic.
  • Improvised this session: none
  • Chain: system-model needs an explicit path ← Inputs.system_model_root raises usage unless one argument is given ← DESIGN (plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:66-71)
  • Root candidate: none found; searched system-model, system_model, project target, project.yaml, system_model_root, --target
  • Where: plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:66
  • Session: d077e084-9195-4803-b761-6ce01eca0249
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/d077e084-9195-4803-b761-6ce01eca0249.jsonl
    VERDICT: CREATE
## Problem `system-model` does not find its root through the Project target logic that the other os-sdlc commands use. It needs an explicit path argument, so it ignores `.sdlc/project.yaml`. In cc-os, `.sdlc/project.yaml` lists many codebases under `targets:`; Jared ruled that `system-model` must resolve its root through that same logic, with shared code and no new resolver. Related: #1515 (fail loudly on an empty root) is open with no "work started" comment. It guards the explicit-path root in `SystemModel::Run`; this ticket adds a second way to reach that root. See Non-goals. ## Reproduce n/a: design change. Today `system-model generate` with no argument prints the usage text and exits 2 (`plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:68`). ## Approach How the other commands choose a target today: only by an explicit `--target NAME` flag. `ArgvOption.take!(argv, "--target NAME")` (`boot/inputs.rb:51`, `:207`; `CrcArgv.target!` for the crc commands; `bin/lint-worklist:9`) fills `Input#target`. `Boot#third_argument` (`boot.rb:71-74`) then calls `ProjectBind#project(dir, target:)` (`boot/project_bind.rb:17-20`), which calls `Project::Config.load`. `Project#target` (`project.rb:46-52`) raises `TargetSelectionError` with "no target selected ... Available: <names>" when the project defines named targets and none is given. No existing command infers the target from the cwd. Design: 1. `Inputs.system_model_root` takes `--target NAME` with `ArgvOption.take!` and sets `Input#target`. With a target, no path argument is allowed. 2. With no path argument and no `--target`, `Input#target` stays nil. `Project#target` then resolves a single-target project to the project root, and refuses a multi-target root and lists the targets (`project.rb:80-84`). No cwd inference. 3. The system-model action in `boot/commands.rb:132-139` receives a `Project` when a target is set. It computes the scan root as `File.join(project.root, project.target.path)` and passes that String to `SystemModel::Run` as today. 4. An explicit path argument keeps `root:` set, so `Boot#third_argument` returns it unchanged. Reused: `ArgvOption.take!`, `Input#target`, `Boot#third_argument`, `ProjectBind#project`, `Project::Config.load`, `Project#target`, `TargetSelectionError`. New code: the root computation in step 3 (about 2 lines); the flag and wiring are about 4 lines. No new resolver class. Fit with #1515: the empty-`lib/` refusal in `Run#call` applies to the root from every source, so a target path with no Ruby files also fails loudly. The two tickets touch different files except `commands.rb`/`inputs.rb` versus `run.rb`; either can land first. Required work: 1. Accept `--target NAME` in `system_model_root` — check: present `--target NAME` in `plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb` 2. Derive the scan root from the Project target in the system-model action — check: present `project.target.path` in `plugins/os-sdlc/lib/os_sdlc/boot/commands.rb` 3. Add tests — check: present `--target` in `plugins/os-sdlc/tests/system_model_cli_test.rb` Orchestrator work: run `bin/refresh-plugins`; add one History row to `docs/implementation-status/os-sdlc-system-model.md`; update the usage text. A project with no `.sdlc/project.yaml` gets one through `/os:fix`, as for every other project. ## Acceptance criteria 1. Given any cwd inside cc-os, when `system-model generate --target os-me` runs, then it scans `plugins/os-me`. 2. Given the cc-os root as cwd and no target, when `system-model generate` runs, then it exits nonzero and the error lists the available targets, as other commands do. 3. Given an explicit path argument, when `system-model generate <path>` runs, then it scans that path as before. 4. Given a single-target project with no `targets:` key, when `system-model generate` runs from its root with no argument, then it scans the project root. ## Owner sketch ```ruby module OsSdlc::Boot::Inputs def self.system_model_root(io, argv, subcommand) end ``` ## Non-goals Removing the nested `plugins/os-backlog/.sdlc/project.yaml` and `plugins/os-sdlc/.sdlc/project.yaml`. `system-model shapes`. Adding cwd inference to other commands. cwd inference is out of scope; if wanted, it becomes a shared feature for all commands in its own ticket. The empty-root refusal (#1515). ## Origin - Trigger: Jared's ruling this session that `system-model` must use the os-sdlc Project target logic. - Improvised this session: none - Chain: `system-model` needs an explicit path ← `Inputs.system_model_root` raises usage unless one argument is given ← DESIGN (`plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:66-71`) - Root candidate: none found; searched system-model, system_model, project target, project.yaml, system_model_root, --target - Where: plugins/os-sdlc/lib/os_sdlc/boot/inputs.rb:66 - Session: d077e084-9195-4803-b761-6ce01eca0249 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/d077e084-9195-4803-b761-6ce01eca0249.jsonl VERDICT: CREATE
Author
Owner

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

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

Resolution

Done: system-model resolves its root through the os-sdlc project target: with no root argument it takes --target NAME, binds the project, and scans File.join(project root, target path). A root argument works as before; a root plus --target, or extra arguments, refuses with the usage text. Bind/target errors on this path append the usage text.

Evidence: Commit 1b5f152d on ticket-1516 (implementation 225). New tests in plugins/os-sdlc/tests/system_model_cli_test.rb. Suite gate green on dispatch 2066 after two programmer-repair rounds (required-work check, then a suite failure). Contract audit pass (2067).

Follow-ups: none

## Resolution **Done:** system-model resolves its root through the os-sdlc project target: with no root argument it takes --target NAME, binds the project, and scans File.join(project root, target path). A root argument works as before; a root plus --target, or extra arguments, refuses with the usage text. Bind/target errors on this path append the usage text. **Evidence:** Commit 1b5f152d on ticket-1516 (implementation 225). New tests in plugins/os-sdlc/tests/system_model_cli_test.rb. Suite gate green on dispatch 2066 after two programmer-repair rounds (required-work check, then a suite failure). Contract audit pass (2067). **Follow-ups:** none
jared closed this issue 2026-11-03 15:27:50 +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#1516
No description provided.