Cut Brief and Dispatch cycle: Dispatch owns the brief lookup and composition #1176

Closed
opened 2026-10-19 22:22:13 +00:00 by jared · 2 comments
Owner

Problem

The Brief concept and the Dispatch concept refer to each other. Brief::Lookup calls Dispatch.pending! (brief/lookup.rb:22). Brief::Retrieval rescues Dispatch::UnknownError and Dispatch::NotPendingError (brief/retrieval.rb:8). Its only caller is Dispatch::Briefing#brief (dispatch/briefing.rb:17). In the other direction, Dispatch::SubagentStart#hook_payload builds Brief::Facts and calls Brief.for(...).compose (dispatch/subagent_start.rb:37, 45). Brief::Lookup repeats the same composition. Ruling S10 moves the lookup to Dispatch and gives Dispatch one owner of the composition.

Reproduce

n/a: structure-wave cut, nothing to reproduce

Approach

Required work:

  1. Move plugins/os-sdlc/lib/os_sdlc/brief/lookup.rb to plugins/os-sdlc/lib/os_sdlc/dispatch/brief_lookup.rb as OsSdlc::Dispatch::BriefLookup. — check: present class BriefLookup in plugins/os-sdlc/lib/os_sdlc/dispatch/brief_lookup.rb
  2. Fold the rescue of Brief::Retrieval.brief into Dispatch::Briefing#brief, with the same Loud::Exit.call("brief #{e.message}"). Delete plugins/os-sdlc/lib/os_sdlc/brief/retrieval.rb. — check: absent Dispatch in plugins/os-sdlc/lib/os_sdlc/brief/**/*.rb
  3. Give Dispatch one place that builds Brief::Facts and calls Brief.for(implementation, node:, handoff:, facts:).compose. Dispatch::BriefLookup#call (tracker Tracker::Null.new) and Dispatch::SubagentStart#hook_payload (its injected tracker) both call it.

Acceptance criteria

  1. Given the suite, when run after the change, then it passes with no new failures.
  2. Given the lib tree, when bin/crc-cycle-edges runs, then no edge Brief -> Dispatch exists.
  3. Given an unknown or not-pending dispatch id, when os-sdlc brief runs, then it exits 3 with the same brief ... message as before.

Owner sketch

class OsSdlc::Dispatch::BriefLookup
  def self.call(root, dispatch_id)
  def call
end

class OsSdlc::Dispatch::Briefing
  def brief(root, dispatch_id)
end

Non-goals

The fixture TSVs under plugins/os-sdlc/tests/fixtures/crc_shares/run2/ are a record of run 2. They keep the old names.

Origin

  • Trigger: os-sdlc CRC run 3, structure-ruling wave step 1, close row C2 (bin/crc-cycle-edges after the lopsided cuts S1 to S8)
  • Improvised this session: none
  • Chain: concept cycle Brief <-> Dispatch ← brief/lookup.rb:22, brief/retrieval.rb:8, dispatch/subagent_start.rb:37 ← DESIGN (docs/crc/os-sdlc/wave0/structure-rulings.tsv S10)
  • Root candidate: none found; searched Brief::Lookup, Brief::Retrieval, BriefLookup, Briefing, hook_payload
  • Where: plugins/os-sdlc/lib/os_sdlc/brief/lookup.rb
  • Ledger: docs/crc/os-sdlc/ledger.tsv
  • Rulings: docs/crc/os-sdlc/wave0/structure-rulings.tsv
  • Session: 2e167079-f404-4139-9cfa-6c0c937ce9f0
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-os-sdlc-run-3/2e167079-f404-4139-9cfa-6c0c937ce9f0.jsonl

VERDICT: CREATE

## Problem The Brief concept and the Dispatch concept refer to each other. `Brief::Lookup` calls `Dispatch.pending!` (brief/lookup.rb:22). `Brief::Retrieval` rescues `Dispatch::UnknownError` and `Dispatch::NotPendingError` (brief/retrieval.rb:8). Its only caller is `Dispatch::Briefing#brief` (dispatch/briefing.rb:17). In the other direction, `Dispatch::SubagentStart#hook_payload` builds `Brief::Facts` and calls `Brief.for(...).compose` (dispatch/subagent_start.rb:37, 45). `Brief::Lookup` repeats the same composition. Ruling S10 moves the lookup to Dispatch and gives Dispatch one owner of the composition. ## Reproduce n/a: structure-wave cut, nothing to reproduce ## Approach Required work: 1. Move `plugins/os-sdlc/lib/os_sdlc/brief/lookup.rb` to `plugins/os-sdlc/lib/os_sdlc/dispatch/brief_lookup.rb` as `OsSdlc::Dispatch::BriefLookup`. — check: present `class BriefLookup` in `plugins/os-sdlc/lib/os_sdlc/dispatch/brief_lookup.rb` 2. Fold the rescue of `Brief::Retrieval.brief` into `Dispatch::Briefing#brief`, with the same `Loud::Exit.call("brief #{e.message}")`. Delete `plugins/os-sdlc/lib/os_sdlc/brief/retrieval.rb`. — check: absent `Dispatch` in `plugins/os-sdlc/lib/os_sdlc/brief/**/*.rb` 3. Give Dispatch one place that builds `Brief::Facts` and calls `Brief.for(implementation, node:, handoff:, facts:).compose`. `Dispatch::BriefLookup#call` (tracker `Tracker::Null.new`) and `Dispatch::SubagentStart#hook_payload` (its injected tracker) both call it. ## Acceptance criteria 1. Given the suite, when run after the change, then it passes with no new failures. 2. Given the lib tree, when `bin/crc-cycle-edges` runs, then no edge Brief -> Dispatch exists. 3. Given an unknown or not-pending dispatch id, when `os-sdlc brief` runs, then it exits 3 with the same `brief ...` message as before. ## Owner sketch ```ruby class OsSdlc::Dispatch::BriefLookup def self.call(root, dispatch_id) def call end class OsSdlc::Dispatch::Briefing def brief(root, dispatch_id) end ``` ## Non-goals The fixture TSVs under `plugins/os-sdlc/tests/fixtures/crc_shares/run2/` are a record of run 2. They keep the old names. ## Origin - Trigger: os-sdlc CRC run 3, structure-ruling wave step 1, close row C2 (bin/crc-cycle-edges after the lopsided cuts S1 to S8) - Improvised this session: none - Chain: concept cycle Brief <-> Dispatch ← brief/lookup.rb:22, brief/retrieval.rb:8, dispatch/subagent_start.rb:37 ← DESIGN (docs/crc/os-sdlc/wave0/structure-rulings.tsv S10) - Root candidate: none found; searched Brief::Lookup, Brief::Retrieval, BriefLookup, Briefing, hook_payload - Where: plugins/os-sdlc/lib/os_sdlc/brief/lookup.rb - Ledger: docs/crc/os-sdlc/ledger.tsv - Rulings: docs/crc/os-sdlc/wave0/structure-rulings.tsv - Session: 2e167079-f404-4139-9cfa-6c0c937ce9f0 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-os-sdlc-run-3/2e167079-f404-4139-9cfa-6c0c937ce9f0.jsonl VERDICT: CREATE
Author
Owner

Work started on branch crc-os-sdlc-run-3 (os-sdlc run 3 worktree), implementation 88, structure-change map.

Work started on branch crc-os-sdlc-run-3 (os-sdlc run 3 worktree), implementation 88, structure-change map.
Author
Owner

Resolution

Done: Brief->Dispatch edge cut (S10): Brief::Lookup is Dispatch::BriefLookup; Brief::Retrieval deleted, its rescue in Dispatch::Briefing#brief; Dispatch::ComposedBrief builds Facts and composes for BriefLookup and SubagentStart.

Evidence: 51a65864 on crc-os-sdlc-run-3; implementation 88, 1 structure-changer dispatch, gate pass. Deviation: ComposedBrief is an instance (new(...).call(node, handoff)) rather than the ticket's Brief.for call shape, because Sdlc/Structural/ParameterListSignalsMissingObject rejects a 5-parameter class method.

Follow-ups: none; the cycle-edge measurement after #1177 confirms AC2.

## Resolution **Done:** Brief->Dispatch edge cut (S10): Brief::Lookup is Dispatch::BriefLookup; Brief::Retrieval deleted, its rescue in Dispatch::Briefing#brief; Dispatch::ComposedBrief builds Facts and composes for BriefLookup and SubagentStart. **Evidence:** 51a65864 on crc-os-sdlc-run-3; implementation 88, 1 structure-changer dispatch, gate pass. Deviation: ComposedBrief is an instance (new(...).call(node, handoff)) rather than the ticket's Brief.for call shape, because Sdlc/Structural/ParameterListSignalsMissingObject rejects a 5-parameter class method. **Follow-ups:** none; the cycle-edge measurement after #1177 confirms AC2.
jared closed this issue 2026-10-19 22:33:56 +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#1176
No description provided.