os-sdlc: PostToolUse fires at launch for async Agent dispatches — pipeline must dispatch synchronously or handle early events #402

Closed
opened 2026-08-15 11:20:46 +00:00 by jared · 2 comments
Owner

Context

Live capture 2026-08-15 confirmed the PostToolUse hook fires at agent LAUNCH for async Agent dispatches (tool_response.status: "async_launched", duration_ms ~3), not at completion. The Runner only sees completed work at hook time if pipeline agents are dispatched synchronously (foreground). Docs updated in docs/os-sdlc-rebuild/dispatch-hook.md (commit eacd3e5). Follow-up: decide whether pipeline agents must always be dispatched synchronously, or whether the runner needs to handle early/async events.

VERDICT: CREATE — live-verified correctness gap in the Runner's completion signal; passes all gauntlet tests.

Decision 2026-08-15 (code-probe evidence brief): enforce sync-only dispatch loudly. The hook never reads tool_response (plugins/os-sdlc/hooks/post_tool_use.rb — dispatchable_event reads only tool_name and subagent_type), so an async_launched event currently advances the pipeline as if the agent finished. Full async support (deferring to a completion event) is contingent on an unverified assumption that a completion-time PostToolUse event exists at all for async dispatches — out of scope here.

Tasks

  • Add a guard in plugins/os-sdlc/hooks/post_tool_use.rb: when event.dig("tool_response", "status") == "async_launched", do not call engine.handle_event; emit a loud additionalContext error stating pipeline agents must be dispatched synchronously (run_in_background: false). Provenance: live capture 2026-08-15 in docs/os-sdlc-rebuild/dispatch-hook.md; code-probe brief confirms no code inspects tool_response.
  • Test coverage: an async_launched event never advances the pipeline and produces the loud message; the synchronous event path is unchanged.
  • Record the sync-only dispatch constraint as an ADR (run /os-adr:find first; relates to ADR-0097 gate-logic-in-Ruby and the loud-stall philosophy in ADR-0108).
  • Rider: update the async-launch caveat section of docs/os-sdlc-rebuild/dispatch-hook.md to state the enforced behavior, and note the existing advisory line in plugins/os-sdlc/skills/implement/SKILL.md now has a Ruby-side backstop.

Acceptance criteria

  • A PostToolUse event with tool_response.status "async_launched" does not advance the pipeline and yields a loud error naming the sync-only constraint.
  • Existing synchronous dispatch behavior is unchanged; full suite green, rubocop clean.
  • The ADR exists and dispatch-hook.md names the enforcement.

Out of scope

Handling async dispatches to completion (Option A) — blocked on live-verifying whether a completion-time PostToolUse event exists for async dispatches; if wanted, that is a separate ticket.

Blocking edges

None.

## Context Live capture 2026-08-15 confirmed the PostToolUse hook fires at agent LAUNCH for async Agent dispatches (tool_response.status: "async_launched", duration_ms ~3), not at completion. The Runner only sees completed work at hook time if pipeline agents are dispatched synchronously (foreground). Docs updated in docs/os-sdlc-rebuild/dispatch-hook.md (commit eacd3e5). Follow-up: decide whether pipeline agents must always be dispatched synchronously, or whether the runner needs to handle early/async events. VERDICT: CREATE — live-verified correctness gap in the Runner's completion signal; passes all gauntlet tests. Decision 2026-08-15 (code-probe evidence brief): enforce sync-only dispatch loudly. The hook never reads tool_response (plugins/os-sdlc/hooks/post_tool_use.rb — dispatchable_event reads only tool_name and subagent_type), so an async_launched event currently advances the pipeline as if the agent finished. Full async support (deferring to a completion event) is contingent on an unverified assumption that a completion-time PostToolUse event exists at all for async dispatches — out of scope here. ## Tasks - [ ] Add a guard in plugins/os-sdlc/hooks/post_tool_use.rb: when event.dig("tool_response", "status") == "async_launched", do not call engine.handle_event; emit a loud additionalContext error stating pipeline agents must be dispatched synchronously (run_in_background: false). Provenance: live capture 2026-08-15 in docs/os-sdlc-rebuild/dispatch-hook.md; code-probe brief confirms no code inspects tool_response. - [ ] Test coverage: an async_launched event never advances the pipeline and produces the loud message; the synchronous event path is unchanged. - [ ] Record the sync-only dispatch constraint as an ADR (run /os-adr:find first; relates to ADR-0097 gate-logic-in-Ruby and the loud-stall philosophy in ADR-0108). - [ ] Rider: update the async-launch caveat section of docs/os-sdlc-rebuild/dispatch-hook.md to state the enforced behavior, and note the existing advisory line in plugins/os-sdlc/skills/implement/SKILL.md now has a Ruby-side backstop. ## Acceptance criteria - [ ] A PostToolUse event with tool_response.status "async_launched" does not advance the pipeline and yields a loud error naming the sync-only constraint. - [ ] Existing synchronous dispatch behavior is unchanged; full suite green, rubocop clean. - [ ] The ADR exists and dispatch-hook.md names the enforcement. ## Out of scope Handling async dispatches to completion (Option A) — blocked on live-verifying whether a completion-time PostToolUse event exists for async dispatches; if wanted, that is a separate ticket. ## Blocking edges None.
Author
Owner

Work starting via os-sdlc pipeline on branch worktree-issue-402

Work starting via os-sdlc pipeline on branch worktree-issue-402
Author
Owner

Resolution

Done: Hook guard implemented: PostToolUse events with tool_response.status async_launched never advance the pipeline and emit a loud additionalContext error naming the sync-only constraint (run_in_background: false). Test coverage added at the hook process boundary; sync path unchanged. ADR-0121 recorded; dispatch-hook.md and implement SKILL.md updated to name the enforcement.

Evidence: Commit 1d8a520 on branch worktree-issue-402: plugins/os-sdlc/hooks/post_tool_use.rb guard + plugins/os-sdlc/tests/runner/post_tool_use_async_dispatch_test.rb; suite green (920 runs, 0 failures); changed files rubocop-clean; reviewer verdict APPROVE (.sdlc/tickets/402/verdict.md); docs/adr/0121.

Follow-ups: none — full async support (completion-event handling) already scoped out to a separate ticket by the ticket itself

## Resolution **Done:** Hook guard implemented: PostToolUse events with tool_response.status async_launched never advance the pipeline and emit a loud additionalContext error naming the sync-only constraint (run_in_background: false). Test coverage added at the hook process boundary; sync path unchanged. ADR-0121 recorded; dispatch-hook.md and implement SKILL.md updated to name the enforcement. **Evidence:** Commit 1d8a520 on branch worktree-issue-402: plugins/os-sdlc/hooks/post_tool_use.rb guard + plugins/os-sdlc/tests/runner/post_tool_use_async_dispatch_test.rb; suite green (920 runs, 0 failures); changed files rubocop-clean; reviewer verdict APPROVE (.sdlc/tickets/402/verdict.md); docs/adr/0121. **Follow-ups:** none — full async support (completion-event handling) already scoped out to a separate ticket by the ticket itself
jared closed this issue 2026-08-15 23:30:43 +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#402
No description provided.