os-sdlc: rename and split the five transport-named controllers by job (ADR-0247) #834

Closed
opened 2026-09-29 16:52:26 +00:00 by jared · 2 comments
Owner

Problem

Five top-level controllers in plugins/os-sdlc/lib/os_sdlc/controller/ are named after transport, not job: ArrivalHook, CompletionHook, AsyncLaunchHook, DispatchScripts, ImplementationScripts.
Each hook does the same job as a script and differs only in transport.
ADR-0247 rules that a class is named after its job.
The user accepted the new names on 2026-09-29.

Reproduce

n/a: naming and ownership refactor, nothing to reproduce.

Approach

Each hook merges into its job's controller as a .hook(io) entry point beside the script method.
The Scripts classes split by job.
Dispatch and Implementation are Sequel::Model classes. Nesting a controller under a model has precedent (Project::Onboarding).
Avoid shadowing: Brief, Gate, Arrival, Implementation::Open are taken.

Target map:

  • Dispatch::Briefing (controller/dispatch/briefing.rb) = ArrivalHook + DispatchScripts#subagent_start + #brief. Callers: hooks/subagent_start.rb, bin/os-sdlc-subagent-start, bin/os-sdlc-brief.
  • Dispatch::Completion (dispatch/completion.rb) = CompletionHook + DispatchScripts#subagent_stop. Callers: hooks/subagent_stop.rb, bin/os-sdlc-subagent-stop.
  • Dispatch::Gating (dispatch/gating.rb) = DispatchScripts#gate. Caller: bin/os-sdlc-gate.
  • Implementation::Guidance (implementation/guidance.rb) = AsyncLaunchHook + ImplementationScripts#next. Callers: hooks/post_tool_use.rb, bin/os-sdlc-next.
  • Implementation::Opening (implementation/opening.rb) = #implementation_open. Caller: bin/os-sdlc-implementation-open.
  • Implementation::Accounting (implementation/accounting.rb) = #implementation_report (+ --sweep-only). Caller: bin/os-sdlc-implementation-report.
  • Implementation::Acceptance (implementation/acceptance.rb) = #retired_tests_check + #required_work_check. Callers: bin/os-sdlc-retired-tests-check, bin/os-sdlc-required-work-check.

Duplicated hook helpers (no_project message, cwd/bound/bound_event) move to ProjectBind or one small mixin.
Tests are renamed: tests/controller/{arrival_hook,completion_hook,dispatch_scripts_bind,implementation_scripts_bind}_test.rb, hook_*_test.rb, script_project_root_test.rb, async_launch_hook_bare_dir_test.rb, tests/support/in_process_dispatch_script.rb, post_tool_use_hook_test_case.rb.

Required work:

  1. Record hook envelope, script stdout/stderr and exit-code fixtures before the change (as in #767/#768).
  2. Create the seven controllers and delete the five old classes.
  3. Rename the tests and support files listed above.
  4. Update CLAUDE.md and docs/architecture/os-sdlc-profile.md.
  5. Amend ADR-0247.
  6. Restart open Claude sessions after merge.

Acceptance criteria

  1. Given the fixtures recorded before the change, when each hook and script runs after the change, then every hook envelope, stdout, stderr and exit code is byte-identical.
  2. Given the refactor, when the suite runs, then it is green.
  3. Given plugins/os-sdlc/lib/os_sdlc/controller/, when listed, then no class is named *Hook or *Scripts.

Owner sketch

class Dispatch::Briefing
  def self.hook(io); end
  def subagent_start; end
  def brief; end
end

Origin

  • Trigger: user ruling 2026-09-29 accepting the ADR-0247 names as an improvement.
  • Improvised this session: none
  • Chain: transport-named controllers ← #833 named controllers by transport ← DESIGN (ADR-0247)
  • Root candidate: none
  • Where: plugins/os-sdlc/lib/os_sdlc/controller/
  • Session: 61834fd0-8fa2-40d2-8215-fb2f0622220d
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-pass-os-sdlc/61834fd0-8fa2-40d2-8215-fb2f0622220d.jsonl
## Problem Five top-level controllers in `plugins/os-sdlc/lib/os_sdlc/controller/` are named after transport, not job: `ArrivalHook`, `CompletionHook`, `AsyncLaunchHook`, `DispatchScripts`, `ImplementationScripts`. Each hook does the same job as a script and differs only in transport. ADR-0247 rules that a class is named after its job. The user accepted the new names on 2026-09-29. ## Reproduce n/a: naming and ownership refactor, nothing to reproduce. ## Approach Each hook merges into its job's controller as a `.hook(io)` entry point beside the script method. The Scripts classes split by job. Dispatch and Implementation are Sequel::Model classes. Nesting a controller under a model has precedent (`Project::Onboarding`). Avoid shadowing: `Brief`, `Gate`, `Arrival`, `Implementation::Open` are taken. Target map: - `Dispatch::Briefing` (`controller/dispatch/briefing.rb`) = ArrivalHook + DispatchScripts#subagent_start + #brief. Callers: `hooks/subagent_start.rb`, `bin/os-sdlc-subagent-start`, `bin/os-sdlc-brief`. - `Dispatch::Completion` (`dispatch/completion.rb`) = CompletionHook + DispatchScripts#subagent_stop. Callers: `hooks/subagent_stop.rb`, `bin/os-sdlc-subagent-stop`. - `Dispatch::Gating` (`dispatch/gating.rb`) = DispatchScripts#gate. Caller: `bin/os-sdlc-gate`. - `Implementation::Guidance` (`implementation/guidance.rb`) = AsyncLaunchHook + ImplementationScripts#next. Callers: `hooks/post_tool_use.rb`, `bin/os-sdlc-next`. - `Implementation::Opening` (`implementation/opening.rb`) = #implementation_open. Caller: `bin/os-sdlc-implementation-open`. - `Implementation::Accounting` (`implementation/accounting.rb`) = #implementation_report (+ --sweep-only). Caller: `bin/os-sdlc-implementation-report`. - `Implementation::Acceptance` (`implementation/acceptance.rb`) = #retired_tests_check + #required_work_check. Callers: `bin/os-sdlc-retired-tests-check`, `bin/os-sdlc-required-work-check`. Duplicated hook helpers (no_project message, cwd/bound/bound_event) move to `ProjectBind` or one small mixin. Tests are renamed: `tests/controller/{arrival_hook,completion_hook,dispatch_scripts_bind,implementation_scripts_bind}_test.rb`, `hook_*_test.rb`, `script_project_root_test.rb`, `async_launch_hook_bare_dir_test.rb`, `tests/support/in_process_dispatch_script.rb`, `post_tool_use_hook_test_case.rb`. Required work: 1. Record hook envelope, script stdout/stderr and exit-code fixtures before the change (as in #767/#768). 2. Create the seven controllers and delete the five old classes. 3. Rename the tests and support files listed above. 4. Update `CLAUDE.md` and `docs/architecture/os-sdlc-profile.md`. 5. Amend ADR-0247. 6. Restart open Claude sessions after merge. ## Acceptance criteria 1. Given the fixtures recorded before the change, when each hook and script runs after the change, then every hook envelope, stdout, stderr and exit code is byte-identical. 2. Given the refactor, when the suite runs, then it is green. 3. Given `plugins/os-sdlc/lib/os_sdlc/controller/`, when listed, then no class is named `*Hook` or `*Scripts`. ## Owner sketch ```ruby class Dispatch::Briefing def self.hook(io); end def subagent_start; end def brief; end end ``` ## Origin - Trigger: user ruling 2026-09-29 accepting the ADR-0247 names as an improvement. - Improvised this session: none - Chain: transport-named controllers ← #833 named controllers by transport ← DESIGN (ADR-0247) - Root candidate: none - Where: plugins/os-sdlc/lib/os_sdlc/controller/ - Session: 61834fd0-8fa2-40d2-8215-fb2f0622220d - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-pass-os-sdlc/61834fd0-8fa2-40d2-8215-fb2f0622220d.jsonl
Author
Owner

Work started on branch crc-pass-os-sdlc (worktree crc-pass-os-sdlc), direct agents as in #833.

Work started on branch crc-pass-os-sdlc (worktree crc-pass-os-sdlc), direct agents as in #833.
Author
Owner

Resolution

Done: Five transport-named controllers replaced by Dispatch::{Briefing,Completion,Gating} and Implementation::{Guidance,Opening,Accounting,Acceptance}, nested under their Sequel models. OsSdlc::Boot is the one entry point: it validates input, binds the project, then runs the controller from one command table shared by bin/, hooks/ and tests. ADR-0250 (amends ADR-0236, ADR-0247). Docs and tests renamed.

Evidence: Commit 72fc9ff8, merged to main at 4bc3ed59. Suite 1331 runs, 0 failures. RuboCop clean. Inward-dependency edges 57 (unchanged). HEAD-baseline harness 111 scenarios: 99 byte-identical; 12 accepted differences: 3 bare-dir crashes with a new Sequel message, 2 bare-dir no-arg crashes now print usage errors, 7 uncaught hook JSON crashes show one more stack frame. AC1 holds for every in-project case and every hook envelope.

Follow-ups: #838 script outside a project points the agent at /os-sdlc:setup-project (user-approved). #839 required-work-check usage names the wrong command (user-approved). Restart open Claude sessions: user action.

## Resolution **Done:** Five transport-named controllers replaced by Dispatch::{Briefing,Completion,Gating} and Implementation::{Guidance,Opening,Accounting,Acceptance}, nested under their Sequel models. OsSdlc::Boot is the one entry point: it validates input, binds the project, then runs the controller from one command table shared by bin/, hooks/ and tests. ADR-0250 (amends ADR-0236, ADR-0247). Docs and tests renamed. **Evidence:** Commit 72fc9ff8, merged to main at 4bc3ed59. Suite 1331 runs, 0 failures. RuboCop clean. Inward-dependency edges 57 (unchanged). HEAD-baseline harness 111 scenarios: 99 byte-identical; 12 accepted differences: 3 bare-dir crashes with a new Sequel message, 2 bare-dir no-arg crashes now print usage errors, 7 uncaught hook JSON crashes show one more stack frame. AC1 holds for every in-project case and every hook envelope. **Follow-ups:** #838 script outside a project points the agent at /os-sdlc:setup-project (user-approved). #839 required-work-check usage names the wrong command (user-approved). Restart open Claude sessions: user action.
jared closed this issue 2026-09-29 21:11:09 +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#834
No description provided.