feat(task): GORM model + repository + ProcessTaskEvent engine
Phase B (model + repository):
- TaskDefinition: +TriggerEvent string, +TargetCount int
- UserDailyTaskProgress: +Progress int
- DailyTaskRepository: ListActiveDailyTaskDefinitions signature -> (starID, eventType string)
- IncrementProgress: atomic UPDATE progress=progress+1 WHERE status='pending'
(returns rows-affected 0 + re-read on race; caller decides completion transition)
- ResetAllDailyTasks: +progress: 0 in Updates map
- InitDailyTasksForUser: pass eventType='' (backward-compat)
Phase D (engine + ReportEvent delegation, spec §4.3):
- TaskEventResult struct (CompletedTaskKeys []string)
- DailyTaskService.ProcessTaskEvent: 5-step engine
1. ListActiveDailyTaskDefinitions(starID, eventType) - filter by trigger_event
2. GetOrCreateDailyProgress; skip if completed/claimed (day idempotency)
3. IncrementProgress (atomic +1)
4. if progress >= target_count -> status='completed'
5. UpdateDailyProgress + accumulate CompletedTaskKeys
- ReportEvent rewired: delegates to ProcessTaskEvent, maps TaskEventResult
to ReportEventResponse (F1: single isolation unit; MQ consumer + RPC both use engine)
- 3 callers (GetDailyTasks / ClaimDailyTask / ClaimAllDailyTasks) pass eventType=''
for backward-compat (preserves daily_login / daily_browse_asset before Phase F)
Note: Phase B and D are bundled because the signature change in B is what enables
D's engine to filter by trigger_event. Splitting would leave the codebase
uncompilable in the interim.
spec: docs/superpowers/specs/2026-07-21-daily-task-config-driven-design.md §4
plan: docs/superpowers/plans/2026-07-21-daily-task-config-driven-impl.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>