Add a notification preferences panel to the user profile page, allowing users to toggle individual email notification categories on/off. Preferences are stored as JSONB in the users table and checked at notification dispatch time.
flows-writer (Phase 1a, single-shot) — no dependencies
test-writer (Phase 1b, single-shot) — depends on: flows-writer
schema-updater (Phase 2, ralph) — no dependencies
exit_condition: "npm run build passes AND migration applies cleanly"
max_iterations: 10
preferences-ui (Phase 3, single-shot) — depends on: schema-updater
dispatch-logic (Phase 3, ralph) — depends on: schema-updater
exit_condition: "npm run build passes AND npm test passes AND shouldNotify returns correct values for all preference combinations"
max_iterations: 15
You are updating the user settings documentation with new notification preference scenarios.
## Your Task
Add 3 new user flow scenarios to docs/settings/user-flows.md:
1. User toggles off weekly digest emails
2. User enables mention notifications (previously disabled)
3. New user sees default notification preferences on first visit
## Files You Own
MODIFY: docs/settings/user-flows.md
## Files You Must NOT Touch
- Any file outside docs/settings/
## Acceptance Criteria
- 3 new scenarios following the existing format in user-flows.md
- Each scenario has Context, Flow steps, and "What user accomplished" sections
You are writing E2E tests for the notification preferences feature.
## Your Task
Write Playwright E2E tests covering ALL of these scenarios:
1. Toggle each preference on/off (weekly digest, mentions, assignments, completions)
2. Preferences persist across page reloads
3. Default state for new users (all enabled)
## Shared Contracts — Use These Exact Test IDs
| Element | Test ID |
|---------|---------|
| Preferences container | `notification-preferences` |
| Weekly digest toggle | `pref-toggle-email-weekly` |
| Mentions toggle | `pref-toggle-email-mentions` |
| Assignments toggle | `pref-toggle-email-assignments` |
| Completions toggle | `pref-toggle-email-completions` |
## Files You Own
CREATE: tests/e2e/settings/notification-preferences.spec.ts
MODIFY: tests/fixtures/test-ids.ts (add the test ID constants above)
## Files You Must NOT Touch
- src/ (any source files)
- docs/ (any documentation)
## Acceptance Criteria
- Tests cover ALL 3 scenarios listed above
- All test IDs reference constants from test-ids.ts (no hardcoded strings)
- Tests must NOT use test.skip() — if an element isn't found, the test should fail
You are adding the notification_preferences column to the users table.
## Your Task
Create a database migration that adds a JSONB column to the users table with these default preferences:
{
"email_weekly": true,
"email_mentions": true,
"email_assignments": true,
"email_completions": true
}
## Files You Own
CREATE: supabase/migrations/YYYYMMDD_add_notification_preferences.sql
## Files You Must NOT Touch
- src/ (any source files)
- tests/ (any test files)
## Scope Guard
IN SCOPE: The migration file only
OUT OF SCOPE: Modifying existing tables, adding RLS policies (those come later)
## Acceptance Criteria
- Migration adds notification_preferences JSONB column with NOT NULL constraint
- Default value matches the JSON structure above
- Migration is idempotent (uses IF NOT EXISTS or equivalent)
You are building the NotificationPreferences component and integrating it into the profile page.
## Your Task
1. Create a NotificationPreferences component with toggle switches for each notification category
2. Wire it into the profile page below the existing profile form
3. Read/write preferences via Supabase query
## Shared Contracts — Use These Exact Test IDs
| Element | Test ID |
|---------|---------|
| Preferences container | `notification-preferences` |
| Weekly digest toggle | `pref-toggle-email-weekly` |
| Mentions toggle | `pref-toggle-email-mentions` |
| Assignments toggle | `pref-toggle-email-assignments` |
| Completions toggle | `pref-toggle-email-completions` |
## Files You Own
CREATE: src/components/notification-preferences.tsx
MODIFY: src/app/profile/page.tsx
## Files You Must NOT Touch
- supabase/migrations/ (schema-updater owns this)
- src/lib/notifications.ts (dispatch-logic owns this)
- tests/ (test-writer owns this)
## Patterns to Follow
- Look at existing toggle components in the codebase for styling patterns
- Use Supabase client from src/lib/supabase/client.ts
## Acceptance Criteria
- Component renders 4 toggle switches with correct labels
- Each toggle reads current state from the database on mount
- Toggling updates the JSONB column immediately
- Loading and error states handled
- All data-testid attributes match the shared contracts above
You are adding preference-checking to the notification dispatch path.
## Your Task
1. Create a shouldNotify(userId, category) utility function
2. It reads the user's notification_preferences JSONB and returns boolean
3. Integrate into the existing notification dispatch path
## Files You Own
CREATE: src/lib/notifications.ts
CREATE: tests/unit/notifications.test.ts
## Files You Must NOT Touch
- src/components/ (preferences-ui owns the component)
- src/app/profile/ (preferences-ui owns the page)
- tests/e2e/ (test-writer owns E2E tests)
## Acceptance Criteria
- shouldNotify returns true when preference is enabled, false when disabled
- shouldNotify returns true (default) when user has no preferences set
- Unit tests cover all preference combinations
- npm run build and npm test both pass
These exact test ID values must be used by both preferences-ui (component) and test-writer (E2E tests).
| Element | Test ID | Used by |
|---|---|---|
| Preferences container | notification-preferences |
preferences-ui, test-writer |
| Weekly digest toggle | pref-toggle-email-weekly |
preferences-ui, test-writer |
| Mentions toggle | pref-toggle-email-mentions |
preferences-ui, test-writer |
| Assignments toggle | pref-toggle-email-assignments |
preferences-ui, test-writer |
| Completions toggle | pref-toggle-email-completions |
preferences-ui, test-writer |
Include in spawn prompts for: preferences-ui, test-writer
# Plan: Add notification_preferences column
## Validation
Run after every task. All must pass before marking [x].
- `npm run build`
- `npm test`
## Tasks
- [ ] Create migration file — `supabase/migrations/` — Add JSONB column with defaults {"email_weekly": true, "email_mentions": true, "email_assignments": true, "email_completions": true}
- [ ] Verify migration syntax — run build to confirm no TypeScript errors from generated types
## Completed
(agent moves checked items here)
# Plan: Notification preference checking
## Validation
Run after every task. All must pass before marking [x].
- `npm run build`
- `npm test`
## Tasks
- [ ] Create shouldNotify utility — `src/lib/notifications.ts` — Function takes userId + category, queries user's notification_preferences JSONB, returns boolean
- [ ] Handle missing preferences — `src/lib/notifications.ts` — Return true (send notification) when user has no preferences row or null JSONB
- [ ] Add unit tests — `tests/unit/notifications.test.ts` — Test all 4 categories enabled/disabled, test null/missing preferences defaults to true
- [ ] **HARD STOP** — Wire into dispatch path — Find existing notification send logic and add shouldNotify check before sending. Review integration point before continuing
## Completed
(agent moves checked items here)
flows-writer:
MODIFY: docs/settings/user-flows.md
test-writer:
CREATE: tests/e2e/settings/notification-preferences.spec.ts
MODIFY: tests/fixtures/test-ids.ts
schema-updater:
CREATE: supabase/migrations/YYYYMMDD_add_notification_preferences.sql
preferences-ui:
CREATE: src/components/notification-preferences.tsx
MODIFY: src/app/profile/page.tsx
dispatch-logic:
CREATE: src/lib/notifications.ts
CREATE: tests/unit/notifications.test.ts
No file appears under more than one teammate.
- [ ] Update user-flows docs with notification preference scenarios (flows-writer)
- [ ] Write E2E tests for notification preferences (test-writer) [depends: flows-writer]
- [ ] Add notification_preferences JSONB column migration (schema-updater)
- [ ] Build NotificationPreferences component and profile integration (preferences-ui) [depends: schema-updater]
- [ ] Create shouldNotify utility and wire into dispatch (dispatch-logic) [depends: schema-updater]
- flows-writer: 3 new scenarios added, follow existing format
- test-writer: Tests cover all 3 scenarios, no test.skip(), all test IDs from shared contracts
- schema-updater: Migration applies without error, JSONB defaults match contract
- preferences-ui: 4 toggles render with correct test IDs, read/write works
- dispatch-logic: Unit tests pass for all preference combinations
-
npm run buildpasses -
npm testpasses (unit tests) -
npm run test:e2epasses (E2E tests execute, 0 skipped) - Shared contract verification: all 5 test IDs consistent across component, test-ids.ts, and E2E spec
- No files modified outside ownership map