# p0147d: SkillRoundHandlerBase decomposition

- [Architecture] Decomposed the 502-line `SkillRoundHandlerBase` via composition, not abstract-method extraction — modelled responsibilities as injectable services (`IPromptComposer`, `ISkillRoundDispatcher`, `ISkillResponseParser`, `ISkillRoundBufferDispatcher`, `IBlockingFollowUpDetector`) plus two round-type executors (`IDiscussionRoundExecutor`, `IStructuredRoundExecutor`). Each is mockable independently; base shrinks to a 37-line template-method router.
- [Architecture] Per-round-type prompt strategy interface (`ISkillPromptStrategy`) replaces the abstract `BuildDomainSection` / `BuildDomainSectionParts` hooks. Three implementations cover the three real round-types: `DefaultSkillPromptStrategy` (ticket-driven), `SecuritySkillPromptStrategy` (security-scan), `ApiSkillPromptStrategy` (API-security). Strategy maps 1:1 to the derived handler that used to own the domain-section logic.
- [Architecture] `ISkillRoundBufferDispatcher` replaces two static methods on the old base (`DispatchBuffer`, `ApplyBufferToContext`). `PipelineBatchRunner` now receives it via constructor injection; the tests that exercised the static signature switched to `new SkillRoundBufferDispatcher()` directly.
- [Architecture] `VerifyRoundHandler` gained `ISkillResponseParser` so its previously-duplicated `ApplyConfidenceThreshold` logic is the same instance the discussion path uses. One place to change confidence policy.
- [Architecture] Outcome→`CommandResult` translation lives in a static helper (`SkillCallOutcomeTranslator`) — pure mapping with two policies (discussion vs structured); injecting a service for two switch-cases would be ceremony.
- [Implementation] Discussion + structured round handlers split into two executor services rather than one fat executor with an `if (isStructured)`. Different inputs (discussion needs round + roles for blocking-detection; structured needs orchestration role), different outputs, different post-processing.
- [Implementation] Gate path stays inside `StructuredRoundExecutor` and delegates to `IGateRetryCoordinator` unchanged. Per p0142, gate retry semantics are observation-driven and distinct from the runtime's mechanical retry; conflating them would lose semantics.
- [TradeOff] The phase YAML's premise that Filter / Verify / Bootstrap round handlers inherited from `SkillRoundHandlerBase` was wrong on inspection — only `SkillRoundHandler`, `SecuritySkillRoundHandler`, and `ApiSkillRoundHandler` actually inherited. Migration targets adjusted to the real three; `BootstrapRoundHandler` + `FilterRoundHandler` + `VerifyRoundHandler` remain standalone (size issues there are p0147g's scope per the umbrella). Recorded so successor phases don't repeat the inspection.
- [TradeOff] Strategy implementations registered as `Transient` and consumed by name from each handler's primary constructor (not via a keyed lookup). One strategy per handler is the simpler shape — keyed DI would buy genericism the codebase doesn't need yet.
- [TradeOff] `SecuritySkillPromptStrategy` lands at 113 lines because the commodity-findings section + chain-analyst gating live there; that's within the 120-line hard limit but over the 80-line "warning" threshold. The alternative — extracting `CommodityFindingsSectionBuilder` — is shape-only and earned no real benefit; left as-is until somebody re-uses the commodity section elsewhere.
