fix: move sync max_concurrency validation to _from_func
The validation was in __post_init__ which is shared by both @daft.func and
@daft.cls paths. Sync @daft.cls methods legitimately use max_concurrency
for actor pool sizing, so the check belongs only in _from_func.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix(dashboard): update wall-clock duration once per second
Use a 1-second interval timer for live wall-clock updates instead of
updating on every stats event. The final duration still shows
immediately when end_sec arrives.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
refactor(dashboard): extract shared tree layout and colors
Extract duplicated tree connector logic from physical-plan-tree.tsx and
plan-visualizer.tsx into a generic TreeLayout<T> component. Move shared
categoryColors map into tree-colors.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>