os-sdlc hooks create a new pipeline database in a subagent's cwd instead of finding the project root #822

Closed
opened 2026-09-28 22:29:49 +00:00 by jared · 1 comment
Owner

Problem

The os-sdlc hooks bind the pipeline database from the event's working directory. They do not search for the project root:

# controller/arrival_hook.rb, completion_hook.rb, async_launch_hook.rb
@bind.call(event.cwd)   # bind = Db.method(:connect_project!)

Db.connect_project!(root) resolves root/.sdlc/pipeline.db (adapter/db.rb:53, model/project/artifact_dir.rb:19). Db.open runs FileUtils.mkdir_p on that folder. A new empty file has user_version 0, so Db.open treats it as stale, moves it to pipeline.db.stale, and creates a fresh schema (db.rb:65, :106). So when a subagent's working directory is a source subfolder, its SubagentStart, SubagentStop or PostToolUse:Agent event binds a new empty database there, not the run's database. RootSearch (adapter/project/root_search.rb) exists, but no hook uses it.

Observed

On 2026-09-28 two runs left the exact Db.open signature, a 57344-byte pipeline.db and a 0-byte pipeline.db.stale:

implementation 72: plugins/os-backlog/lib/backlog/.sdlc/pipeline.db                  18:12:01
implementation 73: plugins/os-sdlc/lib/os_sdlc/parser/ticket_shape/.sdlc/pipeline.db  18:24:31

The second folder is the one the programmer edited. Both were removed by hand before commit. git add -A would have committed them. No one has yet driven a hook call to reproduce it. The working directory that the harness puts in the event is inferred from the code.

Reproduce

Not yet reproduced by a driven hook call. Candidate: send a SubagentStop event whose cwd is plugins/os-sdlc/lib to plugins/os-sdlc/hooks/<completion hook script> and check for plugins/os-sdlc/lib/.sdlc/pipeline.db.

Origin

  • Trigger: git status after implementations 72 and 73
  • Improvised this session: removed the files by hand; later agent prompts said "do not cd"
  • Chain: stray database in the source tree <- hook binds Db.connect_project!(event.cwd) with no root search, and Db.open creates a database on open <- DESIGN (controller hooks, adapter/db.rb)
  • Root candidate: this ticket
  • Where: plugins/os-sdlc/lib/os_sdlc/controller/arrival_hook.rb, completion_hook.rb, async_launch_hook.rb; plugins/os-sdlc/lib/os_sdlc/adapter/db.rb
  • Session: 47a537c2-08a1-4d3c-9688-75df56dfdd3d
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-808/47a537c2-08a1-4d3c-9688-75df56dfdd3d.jsonl
  • Related: #817, #820

VERDICT: CREATE
REASON: The chain ends in DESIGN, not IMPROVISATION. The hooks bind Db.connect_project!(event.cwd) with no root search, and Db.open creates a database on open. Two runs on 2026-09-28 left stray databases with the exact Db.open signature. Fixing the hooks to use RootSearch, or making them stop creating a database on open, removes the problem. Removing the files by hand only hid it.

## Problem The os-sdlc hooks bind the pipeline database from the event's working directory. They do not search for the project root: ```ruby # controller/arrival_hook.rb, completion_hook.rb, async_launch_hook.rb @bind.call(event.cwd) # bind = Db.method(:connect_project!) ``` `Db.connect_project!(root)` resolves `root/.sdlc/pipeline.db` (`adapter/db.rb:53`, `model/project/artifact_dir.rb:19`). `Db.open` runs `FileUtils.mkdir_p` on that folder. A new empty file has `user_version` 0, so `Db.open` treats it as stale, moves it to `pipeline.db.stale`, and creates a fresh schema (`db.rb:65`, `:106`). So when a subagent's working directory is a source subfolder, its SubagentStart, SubagentStop or PostToolUse:Agent event binds a new empty database there, not the run's database. `RootSearch` (`adapter/project/root_search.rb`) exists, but no hook uses it. ## Observed On 2026-09-28 two runs left the exact `Db.open` signature, a 57344-byte `pipeline.db` and a 0-byte `pipeline.db.stale`: ``` implementation 72: plugins/os-backlog/lib/backlog/.sdlc/pipeline.db 18:12:01 implementation 73: plugins/os-sdlc/lib/os_sdlc/parser/ticket_shape/.sdlc/pipeline.db 18:24:31 ``` The second folder is the one the programmer edited. Both were removed by hand before commit. `git add -A` would have committed them. No one has yet driven a hook call to reproduce it. The working directory that the harness puts in the event is inferred from the code. ## Reproduce Not yet reproduced by a driven hook call. Candidate: send a SubagentStop event whose `cwd` is `plugins/os-sdlc/lib` to `plugins/os-sdlc/hooks/<completion hook script>` and check for `plugins/os-sdlc/lib/.sdlc/pipeline.db`. ## Origin - Trigger: git status after implementations 72 and 73 - Improvised this session: removed the files by hand; later agent prompts said "do not cd" - Chain: stray database in the source tree <- hook binds `Db.connect_project!(event.cwd)` with no root search, and `Db.open` creates a database on open <- DESIGN (controller hooks, `adapter/db.rb`) - Root candidate: this ticket - Where: plugins/os-sdlc/lib/os_sdlc/controller/arrival_hook.rb, completion_hook.rb, async_launch_hook.rb; plugins/os-sdlc/lib/os_sdlc/adapter/db.rb - Session: 47a537c2-08a1-4d3c-9688-75df56dfdd3d - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-ticket-808/47a537c2-08a1-4d3c-9688-75df56dfdd3d.jsonl - Related: #817, #820 VERDICT: CREATE REASON: The chain ends in DESIGN, not IMPROVISATION. The hooks bind `Db.connect_project!(event.cwd)` with no root search, and `Db.open` creates a database on open. Two runs on 2026-09-28 left stray databases with the exact `Db.open` signature. Fixing the hooks to use `RootSearch`, or making them stop creating a database on open, removes the problem. Removing the files by hand only hid it.
Author
Owner

Resolution

Done: Hooks and the dispatch/implementation scripts bind through ProjectBind -> RootSearch.outermost: the outermost .sdlc/project.yaml inside the git or home boundary. Nested target configs (plugins/*/.sdlc) no longer capture the bind. With no project root, hooks skip (exit 0) and scripts fail loudly; neither creates a database.

Evidence: main 675f99f8 + 9076f428 (merged ed3b8295). New hook_project_root_test and script_project_root_test, incl. a nested-project case, red then green. Driven SubagentStop event with cwd plugins/os-sdlc/lib created no pipeline.db in plugins/os-sdlc/.sdlc or lib (ls verified). Suite 1328 runs, 0 failures.

Follow-ups: none

## Resolution **Done:** Hooks and the dispatch/implementation scripts bind through ProjectBind -> RootSearch.outermost: the outermost .sdlc/project.yaml inside the git or home boundary. Nested target configs (plugins/*/.sdlc) no longer capture the bind. With no project root, hooks skip (exit 0) and scripts fail loudly; neither creates a database. **Evidence:** main 675f99f8 + 9076f428 (merged ed3b8295). New hook_project_root_test and script_project_root_test, incl. a nested-project case, red then green. Driven SubagentStop event with cwd plugins/os-sdlc/lib created no pipeline.db in plugins/os-sdlc/.sdlc or lib (ls verified). Suite 1328 runs, 0 failures. **Follow-ups:** none
jared closed this issue 2026-09-29 15:55:18 +00:00
jared referenced this issue from a commit 2026-09-29 16:46:31 +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#822
No description provided.