harden: validate ToolUseID and SubagentID centrally in DispatchLifecycleEvent
Commit

handleLifecycleSubagentEnd builds a subagent transcript path from event.SubagentID (AgentTranscriptPath -> filepath.Join), then stats and reads it via ExtractModifiedFilesFromOffset — before the value is validated. A "../"-laden SubagentID escapes transcriptDir for a file read. The task-checkpoint write paths (CapturePreTaskState, WriteTemporaryTask) already validate ToolUseID/AgentID, but this read ran first and unguarded.
Extend the central dispatcher guard (added for SessionID) to also reject path-unsafe event.ToolUseID (ValidateToolUseID) and event.SubagentID (ValidateAgentID) before routing, so every handler that turns these hook-supplied identifiers into a path is covered at one choke point. Empty values pass through to each handler's own empty-handling.
Taint is local hook input (same-privilege) and the sink is a read, so severity is low; this closes the last identifier in the lifecycle path family.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com Entire-Checkpoint: 92ddb0963aa9