feat(goals): first-class goals with per-cycle point targets (add-goals OpenSpec change) #36
No reviewers
Labels
No labels
area/auth
area/backend
area/ci
area/deploy
area/e2e
area/frontend
area/shared
blocked
good-first-issue
needs-info
priority/high
priority/low
priority/medium
type/bug
type/chore
type/docs
type/feature
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
celilo/lunacycle!36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "add-goals"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the
add-goalsOpenSpec change end to end: first-class goals with per-cycle point targets, standing tasks and one-off/idea items rolling up into goal progress. All 23 tasks inopenspec/changes/add-goals/tasks.mdare checked off; the design contract indesigns/goal-rollup/README.mdis implemented without deviations.What shipped
Schema (additive):
goal,goal_user,goal_monthtables; nullablegoalIdontemplateTask(standing task) andtask(one-off/idea). Migration0012_add-goalsis purely additive.Server:
goal-rollup.ts), shared bygetGoalsandgetVelocityByMonth— no denormalized counter, no direct ticks on goals.rollover.ts): template instances stay as history; engaged-but-uncompleted goal one-offs silently return to idea (monthId cleared, pending schedules dropped); goal-less tasks keep today's backlog sweep byte-for-byte.goal_monthrows are written only by the commit flow (startCyclenow carries per-goal point targets), never by rollover. Velocity sources goal commitments fromgoal_month; goal-linked rows are excluded from targetCount-based committed sums.monthId. Goal-linked tasks have no completion ceiling (targetCountignored wheregoalIdis set).taskCompletion.scheduleId's FK tolerates schedule deletion (bun:sqlite never enablesPRAGMA foreign_keys; verified empirically, andreconcileSchedulesalready relies on it). Rollover still deletes onlystatus='scheduled'rows — recorded as a comment inrollover.ts.Web:
GoalBarinCategorySection(fuel gauge with scheduled segment and displayed overshoot, expandable THIS CYCLE / IDEAS rows, inline slim add-item form per design D8);DatePickerday cap lifted for goal-linked items only; Template page goal authoring (EditGoalDialog+ standing-task management); Goals page points-based commit withsuggestGoalTargetPoints(avg of last 3 committed cycles' completed points); 🎯 calendar labels for goal items.Seed:
defaultScenarionow includes the garden example — goal at 10 pts committed, two standing tasks (3 completions on "Garden session"), a done 5-pt one-off, a scheduled 5-pt one-off, and two ideas.Two things reviewers should look at
user.groups, task FKs) and anydrizzle-kit generateproduced a broken diff (it even re-emittedALTER TABLE user ADD groups, which fails).0011_resync-after-handwritten-migrationsis a deliberate no-op migration whose drizzle-generated snapshot resyncs the chain;drizzle.config.tsis added (there was none —db:generatecould not run at all).bun run db:recreateruns the full chain cleanly.determineSuggestedTarget. Task 3.4 says "replace", but deleting the count heuristic would change the goal-less recurring commit flow, which design decision 9 declares untouched. Resolution: the new points-basedsuggestGoalTargetPointsdrives goal commits; the count heuristic stays for goal-less recurring cards only.Verification
bun run test:unit: 73 passed (new: rollup mixed-completion spec scenario, all three rollover lanes, suggestion heuristic)bun run test:playwright: 32 passed, 0 failed (new goals.spec: bar render/expand, standing completion ticks progress, idea schedule pull-in, idea done logs points, idea delete — with DB assertions via /api/test-query)bun run test:seed: green; lint: 0 errors; server typecheck (tsc -p apps/lunacycle-server/tsconfig.json --noEmit --allowImportingTsExtensions): clean (root typecheck checks zero files)🤖 Generated with Claude Code
- GoalBar: full-width collapsed bar per goal inside its category section (name, fuel gauge with scheduled segment and displayed — not clamped — overshoot, item/idea counts), expanding to THIS CYCLE and IDEAS rows with inline complete / schedule / delete-idea actions and a slim add-item form (standing vs one-off, title, points, assignees — design D8 resolved toward the slim form: without targetCount, focus and backlog, almost none of EditTaskDialog survives). - Goal items render only in their bar; the goal-less card grid is untouched alongside. - DatePicker: targetCount becomes nullable — null means no day cap, passed only for goal-linked items. - Template page: goal authoring per category (EditGoalDialog for name/description/default target/users, standing-task management). - Goals page: per-goal point target commit with a points-based suggestion (suggestGoalTargetPoints from goal_month + completion history; the count-based determineSuggestedTarget stays for the goal-less recurring flow, which keeps today's behavior per design decision 9). startCycle now carries the goal commitments. - Calendar entries for goal items get a 🎯 prefix (implementer's choice). - CacheArg becomes Partial — a clear always targeted a subset of caches; requiring every key forced an `as` cast server-side and made every client clearCache call a type error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>