> ## Documentation Index
> Fetch the complete documentation index at: https://mako-docs.devinagiffy.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# v2 Changelog

> Changelog tracking the Hitler v2 pivot to a strict accountability bot

# v2 Changelog

This changelog tracks progress on the Hitler v2 pivot from generic workplace intelligence to a strict accountability bot for Inagiffy. For the pre-pivot changelog, see [Changelog](/development/changelog).

For the full implementation plan and gap analysis, see [Pivot Roadmap](/roadmap).

***

## Status Legend

| Status      | Meaning                              |
| ----------- | ------------------------------------ |
| Not Started | Work has not begun                   |
| In Progress | Actively being developed             |
| In Review   | Code complete, awaiting review/merge |
| Done        | Merged to main                       |
| Blocked     | Waiting on a dependency or decision  |

***

## Phase 1: Foundation (Data Model + Core Loop)

**Goal:** Morning thread to task submission to end-of-day collection to basic daily report.

### 1A: Database Schema Changes — Done

**Branch:** `feat/v2-schema`

**New tables:**

* `clients` — Client entities with deploy schedules and content cadence
* `cards` — Yellow/red accountability cards with weekly reset
* `morning_threads` — Daily Slack thread tracking per org
* `thread_submissions` — Individual task submissions in morning threads
* `task_statuses` — End-of-day status snapshots (done/carry-forward/dropped)
* `ooo_records` — Out-of-office records parsed from Slack
* `task_type_map` — Admin-configurable task-type-to-size keyword mapping

**Modified tables:**

* `tasks` — Added `taskType`, `size` (S/M/L), `weight`, `clientId`, `carryForwardCount`
* `task_drafts` — Added `taskType`, `size`, `weight`, `clientId`
* `users` — Added `rampUpStartDate`, `rampUpDurationWeeks`

**New enums:**

* `TaskSize` (small, medium, large) + `TASK_SIZE_WEIGHTS` mapping
* `TaskType` (newsletter\_draft, newsletter\_edit, social\_post, community\_post, design\_task, client\_management, analytics\_report, ad\_hoc)
* `CardType` (yellow, red)
* `CardTrigger` (missing\_submission, task\_overdue, no\_eod\_update, auto\_convert, manual)
* `ReportType` (daily\_public, daily\_private, weekly\_public, weekly\_private, monthly)
* `TaskStatusType` (done, carry\_forward, dropped, no\_update)
* `OOOStatus` (active, upcoming, completed)

**Migration:** `drizzle/0006_mushy_quicksilver.sql`

**Note:** Remaining tables (`blockers`, `interventions`, `reports`, `action_items`, `kpi_targets`, `checklists`, `checklist_completions`) will be added in their respective phase branches when those features are built.

***

### 1B: Client Management Module — Done

**Branch:** `feat/v2-clients`

**Scope:**

* New `clients` API module (CRUD + member assignment + deploy schedules)
* Client-task foreign key relationship
* SDK methods: `createClient()`, `listClients()`, `updateClient()`, `getClient()`
* Admin dashboard page: client list, create/edit forms, member assignment, deploy schedule config

***

### 1C: Morning Thread System — Done

**Branch:** `feat/v2-morning-threads`

**Scope:**

* New `morning-threads` API module
* 9:00 AM cron: post thread in `#today-in-progress` channel
* Track Slack thread timestamp per day per org in `morning_threads` table
* Listen for thread replies via Slack events, store as `thread_submissions`
* 11:00 AM cron: scan thread for missing submissions, cross-reference active roster
* Slack Block Kit templates for morning thread post and status nudge

***

### 1D: End-of-Day Collection — Done

**Branch:** `feat/v2-eod-collection`

**Depends on:** 1A, 1C

**Scope:**

* 5:00 PM cron: post status nudge in morning thread
* 7:00 PM cron: scan thread for status updates
* Parse emoji indicators: done, carry-forward (with/without reason), dropped, no update
* Increment `carryForwardCount` on carried tasks
* Store snapshots in `task_statuses` table
* Carry-forward escalation: Day 2 flagged, Day 3 yellow card, Day 5+ "dead task"

***

## Phase 2: Accountability Layer

**Goal:** Card system, auto-classification, ops review, blocker tracking.

### 2A: Card System — Done

**Branch:** `feat/v2-cards`

**Scope:**

* New `cards` API module
* Yellow card triggers: missing submission (11 AM), task overdue 2+ days, no EOD update
* Red card: 3 yellows per week auto-converts, manual via `/red-card`
* Weekly reset (Monday midnight cron)
* DM notification on card issuance
* Card exemptions: OOO, onboarding ramp-up
* `/red-card @person [reason]` slash command
* `/dismiss-card @person [card-id] [reason]` slash command
* Card evaluation rules in `packages/rules/`

***

### 2B: Auto-Classification Engine — Done

**Branch:** `feat/v2-classification`

**Scope:**

* Task-type-to-size keyword map (stored in `task_type_map`, admin-configurable)
* On thread submission: match against keywords, auto-assign type/size/weight/client
* Confidence scoring; uncertain matches default to "Ad-hoc / M"
* 11:30 AM cron: send classification digest to ops via Slack interactive message
* Ops can confirm or override via buttons/dropdowns
* Admin dashboard page for task-type map CRUD

***

### 2C: Blocker System — Done

**Branch:** `feat/v2-blockers`

**Scope:**

* New `blockers` API module
* `/blocked [task] [reason]` slash command
* `/unblocked [task]` slash command
* Auto-detection from carry-forward reasons mentioning dependencies
* Escalation timeline: 0h ops notified, 8h founder DM, 24h critical in report
* Resolution time tracking
* Blocker data included in daily/weekly reports

***

### 2D: OOO Parsing — Done

**Branch:** `feat/v2-ooo`

**Scope:**

* Monitor `#out-of-office` channel via Slack events
* LLM-based NLP extraction: person, date range, reason
* Store in `ooo_records` table
* Card system checks OOO before issuing cards
* KPI engine prorates targets for partial-week absences
* Fallback: `/ooo [start] [end] [reason]` structured command
* Flag unparse-able messages to ops for manual confirmation

***

## Phase 3: Intelligence Layer

**Goal:** KPI engine, Thursday check-ins, scheduled reports, client health.

### 3A: KPI Engine — Done

**Branch:** `feat/v2-kpi`

**Scope:**

* New `kpi` API module
* Per-role KPI targets stored in `kpi_targets` table
* Weekly comparison: actual weighted output vs target
* Onboarding ramp-up: 25% (week 1), 50% (week 2), 75% (week 3), 100% (week 4)
* Workload distribution: weighted task points per person per week
* Underperformer detection (below 60% of weekly benchmark)
* Admin dashboard page for KPI target management

***

### 3B: Report Generation — Done

**Branch:** `feat/v2-reports`

**Scope:**

* New `reports` API module with Slack block templates
* **Daily Public (9 PM):** Per-person task list, weighted completion %, team total
* **Daily Private (9 PM):** Public content + cards issued, stale tasks, OOO context, intervention logs, client summary, untagged tasks
* **Weekly Public (Fri 6 PM):** Team stats, deploy day compliance, performer of the week
* **Weekly Private (Fri 6 PM):** Individual KPI comparison, card tally, carry-forward patterns, client health, workload distribution, Thursday check-in summaries, recommended actions, previous week action item status
* **Monthly (Last working day 6 PM):** 4-5 week trajectory, team velocity, card history, recurring blockers, client health dashboard, scalability assessment, employee of the month, recommended 1:1s, action items
* Report archive stored in `reports` table (JSON content)
* Searchable report history via admin dashboard

***

### 3C: Thursday Check-In — Done

**Branch:** `feat/v2-thursday-checkin`

**Depends on:** 3A

**Scope:**

* Thursday 6 PM cron: calculate week-to-date performance per person vs KPI
* Cross-reference OOO records for absences
* If below 60% benchmark AND not OOO, send empathetic DM
* Capture response, store with privacy controls
* "Prefer not to share" handling (noted but content not included in reports)
* No response by Friday noon noted as "check-in sent, no response"
* Summarized in weekly private report

***

### 3D: Client Health Tracking — Done

**Branch:** `feat/v2-client-health`

**Depends on:** 1B, 3B

**Scope:**

* Per-client task rollup (tasks completed, carry-forwards, blockers)
* Deploy deadline compliance tracking (was content ready by target day?)
* Week-over-week trend per client
* Client health section in weekly and monthly reports
* Per-client assigned team member tracking

***

## Phase 4: Reporting Dashboard + Polish

**Goal:** Admin dashboard updates, positive reinforcement, retrospectives, invisible labor logging.

### 4A: Invisible Labor Logging — Done

**Branch:** `feat/v2-remaining-gaps`

**Scope:**

* `log_intervention` LLM tool in ChatService — users can say "I picked up X's newsletter" and the bot resolves the attributed user by name, logs the intervention via InterventionsService
* Resolves users by name match against org roster (via UsersService)
* Posts to progress channel automatically (existing InterventionsService behavior)
* InterventionsService and ReportsModule integrated into ChatModule

***

### Remaining Gaps — Done

**Branch:** `feat/v2-remaining-gaps`

**Scope:**

* **"Same as yesterday" detection** — Jaccard similarity check on morning thread submissions; if >85% similar to yesterday's submission, flags to ops channel. `calculateSimilarity()` utility with unit tests (`tests/unit/same-as-yesterday.test.ts`, 7 tests)
* **Designer dependency tracking** — on content task completion (keywords: draft, content, writing, copy, blog, newsletter, article), looks up client's `assignedDesigners` array and DMs each designer that design work can begin. Uses SlackWebApiService injected into TasksService
* **Public holiday configuration** — `isWorkingDay()` utility (`apps/api/src/common/utils/working-day.ts`) checks weekends + org `holidays` preference array. `holidays` field added to `OrgPreferences` interface in DynamicCronService
* **Task reassignment** — `reassign_task` LLM tool in ChatService; finds task by title search and user by name match, calls `TasksService.reassignTask()`. Reassignment updates userId, logs "reassigned" action, DMs both old and new owners via Slack
* **Weekend exclusion** — 10 cron handlers wrapped with `isWorkingDay()` check: daily-checkin, personal-summary, morning-thread, submission-deadline, eod-nudge, eod-collection, blocker-escalation, classification-digest, thursday-checkin, daily-report. Crons that run always (aggregation, OOO, weekly/monthly reports, SOP jobs) are unchanged

***

### 4B: Positive Reinforcement — Done

**Branch:** `feat/v2-reinforcement`

**Scope:**

* **Daily:** 100% weighted completion triggers public shoutout in thread (configurable, can be disabled)
* **Weekly:** "Performer of the Week" in public weekly report (highest weighted completion + fewest cards)
* **Monthly:** "Employee of the Month" auto-nomination based on completion rate, fewest cards, consistency, initiative
* Post monthly winner in `#wins` channel
* Ops/founder can override auto-nomination
* Reward mechanism is configurable (not enforced by bot)

***

### 4C: Action Item Tracking — Done

**Branch:** `feat/v2-action-items`

**Scope:**

* New `action-items` API module
* Monthly reports auto-generate action items
* Stored in `action_items` table with status tracking
* Next month's report opens with previous month's action item status
* Admin dashboard: checklist UI (mark as done / in-progress / deferred)
* Carry-forward counter for unaddressed items

***

### 4D: Admin Dashboard Updates — Done

**Branch:** `feat/v2-admin-dashboard`

**Scope:**

* **Team Roster page:** Add/remove members, set roles, assign KPIs, toggle ramp-up, assign clients
* **Client Config page:** Client list, deploy schedules, content cadence, assigned members
* **Task-Type Map page:** Edit task-type-to-size keyword mapping, add/remove task types
* **Card Management page:** View all cards, dismiss with reason, issue manual red cards
* **Report Archive page:** Searchable history of all generated reports
* **Individual View page:** Click person to view task history, completion rates, card history, check-in history, workload trend
* **Action Items page:** Checklist of open items from monthly reports

***

## Phase 5: Checklists and SOPs (from Manager Thoughts)

**Goal:** Pre-defined checklists and SOPs for process enforcement. Needs manager validation before starting.

### 5A: Checklist System — Done

**Branch:** `feat/v2-checklists`

**Scope:**

* New `checklists` API module
* Pre-defined checklists per role (content writing, content QC, design QC, client QC, designer)
* Admin creates/edits checklists with ordered items
* Team members complete checklists via Slack bot or dashboard
* Completion tracked in `checklist_completions` table
* Incomplete checklists flagged in daily reports

***

### 5B: SOP Tracking — Done

**Branch:** `feat/v2-sops`

**Scope:**

* Recurring SOP enforcement: client SOPs (weekly report Monday, monthly report, monthly call), internal ops (deadlines, `#ooo` process, public channels, monthly 1:1), analytics (Monday updates, client sharing, internal sync)
* Client onboarding checklist automation
* Employee onboarding checklist with ramp-up integration
* SOP compliance tracking in reports

***

## Phase 6: Context Memory System — In Progress

**Goal:** Passive context intelligence — listen to Slack channels, extract facts, build organizational memory, enable proactive actions.

### 6A: Context Memory Core — Done

**Branch:** `feat/v2-context-memory`

**New tables:**

* `channel_messages` — Raw message buffer for context extraction (pruned after 7 days)
* `context_observations` — Extracted facts with pgvector embeddings (1536-dim, OpenAI text-embedding-3-small)
* `context_summaries` — Daily entity summaries, kept indefinitely

**New modules:**

* `apps/api/src/modules/context/` — Full context memory module (controller, service, embeddings, web, processor, actions, backfill)
* `packages/rules/src/context-actions.ts` — Proactive action evaluation rules

**Infrastructure changes:**

* Docker Postgres image swapped from `postgres:16-alpine` to `pgvector/pgvector:pg16`
* Migration adds `CREATE EXTENSION vector` and HNSW indexes on embedding columns

**Capabilities:**

* **Passive listening:** Bot forwards all channel messages to API (fire-and-forget)
* **Batch extraction:** BullMQ processor batches messages, Claude Haiku extracts structured observations (entity, category, confidence)
* **Vector search:** OpenAI embeddings + pgvector cosine similarity for relevant context retrieval
* **Context injection:** Relevant observations injected into chat system prompt (\~500 token cap)
* **URL browsing:** `browse_url` LLM tool — fetches via Jina Reader API, stores as observation
* **Web search:** `search_web` LLM tool — searches via Tavily API, stores results
* **Proactive actions:** Rules engine evaluates observations for deadlines, commitments, risks, handoffs, mood signals
* **Daily summaries:** 11 PM cron generates per-entity profile summaries
* **Cleanup:** 2 AM cron prunes raw channel\_messages older than retention period

**SDK methods added:** `ingestChannelMessage`, `getEntityContext`, `triggerBackfill`, `browseUrl`, `searchWeb`

**New env vars:** `JINA_API_KEY`, `TAVILY_API_KEY`, `CONTEXT_BATCH_SIZE`, `CONTEXT_BATCH_INTERVAL_MS`, `CONTEXT_RAW_RETENTION_DAYS`

**Migration:** `drizzle/0012_dazzling_phalanx.sql`

***

## Phase 6: UX Polish & Employee Experience — Done

**Date:** 2026-03-23

**Goal:** Employee-facing dashboard redesign, pipeline access, slash command improvements, notification dedup, and bug fixes across morning threads, EOD collection, and chat tools.

### Added

* **Employee dashboard redesign** — filters (status, priority, search, sort), list/board view toggle, clickable tasks open TaskDetailPanel sheet
* **Pipeline access for employees** — employees can now view and move their own tasks in the pipeline kanban
* **Pipeline filters** — status, priority, assignee, client, search filters on pipeline page
* **Temporary password system** — `mustChangePassword` column, forced password change on first login, change-password page
* **Clear bot DMs** — admin can clear bot messages from any user's DM via dashboard or `/clear-dms` slash command
* **LLM smart reminders** — personal summary DM uses Claude Haiku to write 2-3 line natural nudge instead of dumping all tasks
* **Notification dedup** — Redis-backed `TaskNotificationDedupService` prevents same task being reminded across multiple channels
* **Display IDs in slash commands** — `/tasks` shows `#displayId`, `/done` matches by displayId
* **Smart `/blocked` and `/unblocked`** — require task ID + reason, show task list when no args
* **Password visibility toggle** — eye icon on all auth pages (login, signup, complete-signup, change-password)
* **Slack commands reference** — added to `docs/development/setup.mdx`

### Fixed

* **Morning thread duplicate tasks** — follow-up replies now use LLM to match existing tasks instead of creating duplicates
* **EOD collection blanket status** — was applying same status to ALL tasks when one emoji found; now uses LLM per-task matching
* **Chat tool matching** — `complete_task`, `update_task`, `reassign_task`, `move_task_stage` use scored matching + displayId instead of `.includes()`
* **Status dropdown refresh** — task list message updates in-place when status changed via dropdown
* **Daily progress includes overdue** — "23 Mar Tasks" message now shows carry-forward/overdue tasks from previous days
* **Deadline message merging** — deadline post updates existing daily message instead of posting duplicate
* **Hardcoded deadline time** — morning thread uses org's configured `submissionDeadlineTime`, not "11 AM"
* **Dashboard relative time** — Due Today shows "in 2h", "30m ago" instead of just "Today"
* **Dashboard clickable cards** — Due Today, Needs Attention, Active Alerts tasks open TaskDetailPanel on click
* **Needs Attention shows overdue** — was showing "ALL CLEAR", now includes overdue + blocked + stale tasks
* **Due date timezone** — morning thread tasks get correct EOD time in org timezone
* **Draft wording** — removed "needs confirmation" language, tasks are auto-confirmed
* **Action item cancelled status** — added 'cancelled' to action item status enum
* **Change password validation** — `currentPassword` optional when `mustChangePassword` is true

***

## Cross-Cutting: Multi-Agent Bot Architecture — Proposal

**Status:** Pending manager approval

**Scope:**

Split Hitler from a single general-purpose bot into **3 specialized agents** that automate ops enforcement — removing manual follow-ups and reducing personality conflicts in accountability:

* **Follow-Up Agent** — Automated deadline tracking, nudges, carry-forward reminders, best practice enforcement. Replaces manual chasing.
* **Task Agent** — Morning thread lifecycle, auto-classification, "same as yesterday" detection, EOD collection, report generation.
* **Escalation Agent** — Blocker escalation timelines, stale task detection, client health monitoring, flag-to-red-flag auto-conversion.

All 3 agents live in the same NestJS app (no microservices). They share one Slack bot identity and communicate via BullMQ events. Built incrementally: Phase 1-2 keeps the single ChatService; Phase 3 extracts the agents when tool count warrants it.

See [Pivot Roadmap — Multi-Agent Architecture](/roadmap#cross-cutting-multi-agent-bot-architecture) for the full design, trigger tables, and implementation plan.

***

## Open Decisions (Blocking Phase 3+)

| Decision                                              | Status   | Owner  | Notes                                                                                    |
| ----------------------------------------------------- | -------- | ------ | ---------------------------------------------------------------------------------------- |
| Newsletter quality metrics data source (Beehiiv API?) | Pending  | Veekay | Needed for writer KPI evaluation                                                         |
| Designer dependency tracking mechanism                | Resolved | —      | Auto-notifies designers in client's `assignedDesigners` when content tasks are completed |
| AI-assisted vs manual draft detection                 | Pending  | Veekay | Default: AI-assisted (M); override to manual (L)                                         |
| Weekend bot operation (Sat/Sun?)                      | Resolved | —      | Mon-Fri only via `isWorkingDay()` check; public holidays configurable in org preferences |
| Social/community engagement metric definition         | Pending  | Veekay | Defer until baseline established                                                         |
| Public holiday calendar source                        | Resolved | —      | Manual config via org preferences `holidays` array (`[{date, name}]`)                    |

***

## Design Overhaul: Controlled Brutalism — Done

**Date:** 2026-03-08

**Scope:** Complete UI/UX redesign of the web dashboard from generic SaaS aesthetic to a refined brutalist command-center design.

### Design Direction

**"Controlled Brutalism"** — Sharp edges, bold typography, high contrast, visible structure. Not aggressive chaos, but intentional precision. Think Bloomberg Terminal meets Swiss design.

### What Changed

**Design System (`globals.css`):**

* Border radius: `0.45rem` (rounded) → `2px` (sharp, structural)
* Color palette: Emerald/indigo gradients → monochrome black/white with muted teal accent (`#0d9373`)
* Removed: glassmorphism (`.glass`), soft shadows (`.shadow-soft`, `.shadow-glow`), hover-lift effects
* Added: `.uppercase-label` utility (9px, uppercase, tracked, IBM Plex Mono), `.border-hard`, stagger animation delays
* Scrollbar: Rounded → square, thinner (6px)
* Ops-brain colors: Refined — `#22c55e` → `#00d47e` (green), `#60a5fa` → `#5ab4f5` (blue), `#f59e0b` → `#f0a000` (yellow), `#ef4444` → `#f04040` (red)
* Dark mode: Cleaner black/white contrast instead of warm stone tones
* Focus rings: `ring-2 ring-offset-2` → `ring-1 ring-offset-1` (subtler)

**Landing Page (`page.tsx`):**

* Full dark background (`#0a0a0a`) instead of gradient (`from-hitler-dark to-indigo-900`)
* Typography-driven hero: Instrument Serif at `clamp(3rem,8vw,7rem)` with italic accent
* Stats strip (17 crons, 100% bot-first, \<2s response, 0 forms) with structural grid dividers
* Feature cards: Hover-reactive panels with square icon containers and visible column borders
* "How it works" section: Oversized step numbers (`01`, `02`, `03`) in near-invisible gray
* Staggered entrance animations across sections
* Footer: Minimal, uppercase, structural

**Auth Pages (Login + Signup):**

* Split-panel layout (45/55) on desktop: brand panel left, form right
* Dark background throughout (no gradient)
* Giant Instrument Serif headline ("Ops brain.") on brand panel
* Custom raw HTML inputs instead of shadcn components (transparent bg, 1px borders)
* Uppercase labels with IBM Plex Mono
* Progress bar on signup (two segments, not numbered circles)
* Brutalist checkbox styling

**Dashboard Layout + Sidebar:**

* Square avatar (no border-radius) for user profile
* Role badge in header (uppercase label)
* Sidebar: `ops-brain` subtitle, square avatar in footer, uppercase group labels
* Backdrop blur on sticky header retained (functional, not decorative)

**Ops-Brain Dashboard (Today View):**

* Page header with Instrument Serif title + live clock + date
* Filter buttons: Uppercase, tracked, square (no border-radius)
* Task cards: Square borders, structural dividers using `var(--ops-border)` consistently
* Summary panel added (team size, total tasks, completed, blocked, OOO count)
* Staggered entrance for person groups
* All rounded elements (dots, avatars, borders) → square

**Team Page:**

* Page header with Instrument Serif + week number subtitle
* Person list: Square selection indicator, no rounded borders
* Card history: "R" / "Y" text labels instead of emoji circles for card type
* Recommendation box: Flat background, no italic

**Clients Page:**

* Health indicator: Left border accent (2px colored) instead of top border
* Page header with descriptive subtitle
* Staggered card entrance animations
* All metrics use `uppercase-label` utility consistently

**Reports Page:**

* Consistent tab bar styling (square, structural)
* Action items panel: Blue left border accent (2px)
* Daily digest: Grid-based stat strip with structural borders instead of rounded cards
* Status abbreviations (OK/CF/BL/??) instead of emoji in daily view

**Ops Components:**

* `StatusDot`: Square (removed `rounded-full`)
* `OpsAvatar`: Square (borderRadius 0), reduced opacity on bg/border
* `Tag`: Square (borderRadius 0), tighter padding
* `KpiBar`: Thinner (3px → 2px), no border-radius, uses CSS vars for colors
* `Card` component: `ring-1` → `border`, removed rounded corners
* `Button` component: Reduced focus ring intensity, lower disabled opacity (0.40)

### Design Principles

1. **Structure over decoration** — Borders define space, not shadows or gradients
2. **Typography as personality** — Instrument Serif for drama, IBM Plex Mono for function
3. **Color is functional** — Green/blue/yellow/red for status only, not decoration
4. **Square is intentional** — 2px radius max, signals precision over friendliness
5. **Data density preserved** — Same information, sharper container
6. **Consistent voice** — `uppercase-label` utility used everywhere for section headers and metadata

***

## Progress Channel & Notification Overhaul — Done

**Date:** 2026-03-24

### Progress Channel Simplification

* **Removed** daily task list posting to progress channel. Tasks are created silently — no more "23 Mar Tasks" messages with everyone's full task list.
* **Submission deadline** now replies as a **thread reply** to the morning thread, tagging only missing users with @-mentions. No more individual DMs.
* Removed `queueProgressChannelUpdate()` calls from `tasks.service.ts` and `morning-threads.service.ts`.
* EOD summary remains unchanged.

### LLM-Powered Nudge Messages

* Deadline nudge DMs now use **Claude Haiku** to generate natural, personal messages instead of static "Reminder: X is due in 4 hours."
* Example: "Hey Pranav, your API migration is due in 4 hours — might be worth wrapping that up soon."
* Falls back to static Block Kit blocks if `ANTHROPIC_API_KEY` is not set.
* Both individual nudges (`handleNudge`) and batched nudges (`handleDeadlineNudgeBatch`) use LLM.

### Notification Anti-Spam (Cooldown + Urgent Bypass)

* **Problem:** The 15-min proactive scanner was sending one DM per task, flooding users with 3-4 messages at once.
* **Fix:** Two-layer dedup system:
  1. **Task-level dedup** (24h) — same task can't be mentioned in multiple notifications
  2. **User-level cooldown** (2h) — after any notification, suppress non-urgent nudges for 2 hours
* **Urgent bypass:** P1/P2 tasks or tasks due within 2 hours always bypass the cooldown.
* Scanner now groups tasks per-user and queues ONE batch nudge per user instead of N individual jobs.

### Weekend Configuration

* `isWorkingDay()` now accepts `weekendDays?: number[]` (default `[0, 6]` for Sun/Sat).
* Dashboard settings page adds a **Working Days** section with 7 toggle buttons (Mon–Sun).
* Orgs with Fri/Sat weekends can configure this — morning threads, nudges, and crons won't fire on configured weekend days.
