Clusters E (plan validation, normalization, KEEP/ADD/UPDATE/REMOVE
operation-diffing - including the 145-line validateAndNormalizePlan
"god method") and F (existing block/container identity matching) from
the structural analysis. Field-free except the PLAN_SENSITIVE_ERROR_CODES
constant.
- New PlanValidationSupport holds validateAndNormalizePlan and its full
dependency tree: normalizeContainerInnerBlocks(AgainstExisting),
validateInnerBlockShapes, normalize{Inner}BlockOperation,
resolveContainerOperation, hasValidationErrorFor{Block,Container},
resolveExisting{Block,Container}(ForPlan), findExisting{Block,Container},
parsePlanOperation, isTargetedBlockRepairEligible,
buildReusedPlanForTargetedRepair, canUseMinimalDraftFallback,
hasCurrentFlow{Blocks,Containers}, isContainerBlockType, blockTypeName
- PLAN_SENSITIVE_ERROR_CODES promoted from private to package-private so
the new class can reference it without duplicating the 48-entry set
- isSharedMemoryContext made static + package-private (it already didn't
touch any instance field) so PlanValidationSupport can call it while it
stays in FlowAssistantService, next to the AssistantFlowPlan/
AssistantBlockPlan records it needs
2352 -> 1805 lines (-547, now under 1900 and past the halfway point of
the original file). 3350 -> 1805 total so far (-1545, ~46%).
Behavior-preserving: pure extraction, no logic changes.
Verified with `mvn test`: 462 tests, 0 failures, 0 errors.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>