> ## 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.

# Changelog

> Living changelog tracking all architectural changes to Hitler

# Changelog

## \[1.3.0] — 2026-03-24

### Added

* **Weekend configuration** — dashboard settings page with 7 toggle buttons (Mon–Sun) to configure working days. `isWorkingDay()` accepts custom `weekendDays[]` (default Sat/Sun). Crons skip configured weekend days.
* **LLM nudge messages** — deadline nudge DMs use Claude Haiku for natural, personal tone. Falls back to static blocks if no API key.
* **Notification cooldown (2h)** — after any notification DM, suppress non-urgent nudges for 2 hours. Prevents scanner from spamming users who already got a morning summary.
* **Urgent bypass** — P1/P2 tasks or tasks due within 2 hours bypass the cooldown and fire immediately.

### Changed

* **Progress channel** — removed daily task list posting entirely. Submission deadline now replies as a thread reply to the morning thread, tagging only missing users. No more individual DMs for deadline.
* **Scanner batching** — 15-min proactive scanner groups tasks per-user and queues ONE batch nudge per user instead of N individual jobs.
* **Batch handler** — now also picks up stale tasks (in\_progress 2+ days) alongside deadline tasks.

### Fixed

* **Notification spam** — users were receiving 3-4 separate DMs from the scanner (one per task). Now receive one consolidated LLM-generated message.

***

## \[1.2.0] — 2026-03-23

### 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`
* **Assistant streaming responses** — AI App split-pane shows responses progressively (sentence-by-sentence) using `chat.update`, instead of waiting for the full reply
* **Context-aware assistant prompts** — `threadContextChanged` detects client channels via `slackChannelId` lookup and shows client-specific suggested prompts (e.g. "Show \[Client] Tasks")

### 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

***

## \[Unreleased]

### V2 Pivot: Remaining Gaps — Intervention, Same-as-Yesterday, Designer Handoffs, Reassignment, Weekend Exclusion

#### Added

* **Intervention bot command** — `log_intervention` LLM tool lets users say "I picked up X's newsletter" and the bot resolves the attributed user by name, logs the intervention via InterventionsService, and posts to progress channel
* **Task reassignment** — `reassign_task` LLM tool; finds task by title search and user by name, calls `TasksService.reassignTask()` which updates assignment, logs "reassigned" action, and DMs both old and new owners via Slack
* **"Same as yesterday" detection** — Jaccard similarity check on morning thread submissions; >85% similarity to yesterday's flags to ops channel with percentage. `calculateSimilarity()` utility with 7 unit tests (`tests/unit/same-as-yesterday.test.ts`)
* **Designer dependency tracking** — on content task completion (keywords: draft, content, writing, copy, blog, newsletter, article), looks up client's `assignedDesigners` and DMs each designer that design work can begin
* **Public holiday configuration** — `isWorkingDay(date, preferences)` utility at `apps/api/src/common/utils/working-day.ts` checks weekends + org `holidays` preference array (`[{date: "YYYY-MM-DD", name: "..."}]`). `holidays` field added to `OrgPreferences` interface
* **Weekend/holiday exclusion** — 10 cron handlers wrapped with `isWorkingDay()`: daily-checkin, personal-summary, morning-thread, submission-deadline, eod-nudge, eod-collection, blocker-escalation, classification-digest, thursday-checkin, daily-report. Always-run crons (aggregation, OOO, weekly/monthly reports, SOP jobs) unchanged
* `ReportsModule` imported into `ChatModule` (provides `InterventionsService`)
* `SlackModule` imported into `TasksModule` (provides `SlackWebApiService` for designer DMs and reassignment notifications)

### V2 Pivot: Phase 5B — SOP Tracking System

#### Added

* New `sops` API module with service, controller, and REST endpoints for managing recurring Standard Operating Procedures
* **DB schema** — `sops` and `sop_records` tables with frequency (daily/weekly/monthly/one\_time), role/user/client assignment, category grouping, and full audit trail
* **Period generation** — automatic record creation per frequency cycle (daily at 00:10) with duplicate prevention
* **Overdue detection** — daily check at 10:00 marks pending records past their period end as overdue, DMs users via Slack, escalates 2+ day overdue to admins
* **Missed marking** — 2-day grace period before overdue records become missed (daily at 00:15)
* **Compliance calculation** — per-SOP, per-user, and per-category compliance rates (completed / non-pending \* 100)
* **Slack bot integration** — `show_sop_status` and `complete_sop` LLM tools for natural language SOP interaction
* **Admin UI** — SOP management page at `/dashboard/sops` with SOPs tab (grouped by category, create/edit modal) and Compliance tab (overview stats, per-SOP table with compliance bars, per-user rates, per-category grid)
* **Report integration** — weekly private reports include SOP compliance summary with overdue/missed counts; monthly reports include per-category compliance and best/worst performers
* **Default SOP seeding** — `POST /api/sops/seed-defaults` creates client SOPs per active client + internal ops + analytics SOPs
* SDK methods: `getSOPs()`, `getSOP()`, `createSOP()`, `updateSOP()`, `deleteSOP()`, `getSOPRecords()`, `getSOPCompliance()`, `getMySOPStatus()`, `completeSOPRecord()`, `seedDefaultSOPs()`
* SDK types: `SOP`, `SOPRecord`, `UserSOPStatus`, `SOPComplianceReport`
* Zod schemas: `createSOPSchema`, `updateSOPSchema`, `completeSOPRecordSchema`
* API endpoints: `GET /api/sops`, `GET /api/sops/:id`, `POST /api/sops`, `PATCH /api/sops/:id`, `DELETE /api/sops/:id`, `GET /api/sops/records`, `GET /api/sops/compliance`, `GET /api/sops/my-status`, `POST /api/sops/records/:id/complete`, `POST /api/sops/seed-defaults`, `POST /api/sops/generate-periods`
* 3 new dynamic cron jobs: `sop-period-generation` (00:10), `sop-overdue-check` (10:00), `sop-missed-check` (00:15)
* Sidebar nav link: "SOPs" with `FileCheck` icon (manager+ role)
* Unit tests: `tests/unit/sop-tracking.test.ts` (22 tests — period generation, due descriptions, overdue/missed detection, compliance calculation, user applicability)

### V2 Pivot: Phase 5A — Checklist System

#### Added

* New `checklists` API module with service, controller, and REST endpoints
* **Pre-defined checklists per role** (writer, designer, ops) with configurable items
* **Completion tracking** — start completion, toggle items, auto-detect full completion
* **Slack bot integration** — `show_checklist`, `complete_checklist_item`, `complete_all_checklist` LLM tools for natural language checklist interaction
* **Admin UI** — checklist management page at `/dashboard/checklists` with create/edit modal, drag-to-reorder items, completion log, stats overview
* **Default checklist templates** — Content Writing, Content QC, Design QC, Client QC, Designer checklists seeded via `POST /api/checklists/seed-defaults`
* **Report integration** — daily private reports include checklist completion summary; weekly private reports include per-checklist completion rates and users who never completed
* New DB tables: `checklists`, `checklist_completions` with appropriate indexes
* SDK methods: `getChecklists()`, `createChecklist()`, `updateChecklist()`, `deleteChecklist()`, `getCompletions()`, `getCompletionStats()`, `getPendingChecklists()`, `startCompletion()`, `toggleChecklistItem()`, `seedDefaultChecklists()`
* SDK types: `Checklist`, `ChecklistCompletion`, `PendingChecklist`, `ChecklistStats`
* Zod schemas: `createChecklistSchema`, `updateChecklistSchema`, `startCompletionSchema`, `toggleItemSchema`
* API endpoints: `GET /api/checklists`, `POST /api/checklists`, `PATCH /api/checklists/:id`, `DELETE /api/checklists/:id`, `POST /api/checklists/seed-defaults`, `GET /api/checklists/completions`, `GET /api/checklists/completions/stats`, `GET /api/checklists/completions/pending`, `POST /api/checklists/completions`, `PATCH /api/checklists/completions/:id/toggle`
* Sidebar nav link: "Checklists" with `ClipboardList` icon (manager+ role)
* Unit tests: `tests/unit/checklists.test.ts` (toggle logic, completion stats, item matching, pending checklists)

### V2 Pivot: Phase 4C — Action Item Tracking

#### Added

* Action Items admin dashboard page (`/dashboard/action-items`) with ops-brain dark theme
* Filter by status (all/open/closed/cancelled), priority (all/high/mid/low), and assignee
* Inline status updates (mark done, cancel) with optimistic UI
* Create new action items manually with assignee and priority selection
* Auto-creation of action items from weekly report recommendations (with duplicate detection)
* Carry-forward badge display (`CF: N`) for items carried across reports
* "From report" source indicator for auto-generated items
* "View all →" link on Reports page navigating to Action Items
* `GET /api/action-items/count` endpoint for nav badge
* `getActionItemCount()` SDK method
* `createActionItem()` web API client method
* Sidebar nav link with `ListChecks` icon between Reports and Cards
* Left join on users table for `assignedToName` in action items listing

### V2 Pivot: Phase 4B — Positive Reinforcement System

#### Added

* New `ReinforcementService` (`apps/api/src/modules/reinforcement/`) with automatic recognition for high performers
* **Daily shoutouts** — users with 100% weighted task completion get recognized in #wins channel (or progress channel fallback)
* **Performer of the Week** — highest weighted completion user recognized after weekly report generation
* **Employee of the Month** — highest average completion user recognized after monthly report generation
* DM notifications to recognized users alongside public channel posts
* New `reinforcements` DB table for tracking recognition history
* REST endpoints: `GET /api/reinforcement/history`, `POST /api/reinforcement/trigger/daily`, `POST /api/reinforcement/trigger/weekly`
* Org preferences: `reinforcementEnabled` (default: true), `winsChannelId` (nullable, falls back to progress channel)
* Admin settings UI section for reinforcement toggle and wins channel picker
* SDK methods: `getReinforcementHistory()`, `triggerDailyShoutout()`, `triggerWeeklyPerformer()`
* Hooks into existing daily/weekly/monthly report crons — no new cron jobs created
* Unit tests: `tests/unit/reinforcement.test.ts` (selection logic, tiebreaking, edge cases)

### V2 Pivot: Phase 3D — Client Health Tracking

#### Added

* New `ClientHealthService` (`apps/api/src/modules/clients/client-health.service.ts`) computing per-client health metrics
* **Health score** (0-100) composite: 50% task completion rate, 30% deploy day compliance, 20% carry-forward ratio
* **Health levels**: `healthy` (≥75), `at_risk` (≥50), `critical` (\<50)
* **Deploy compliance tracking** — checks for completed deploy/send/newsletter/publish tasks before the configured deploy day
* **Deploy streak** — consecutive weeks with on-time deploys (up to 12 weeks lookback)
* **Week-over-week change** — completion rate delta vs previous week
* **Per-member breakdown** — per-writer/designer task completion for a client
* **4-week trend** — weekly completion rate and deploy compliance history
* **Active blocker count** per client from linked tasks
* API endpoints: `GET /api/clients/health` (all clients), `GET /api/clients/:id/health` (single client detail)
* SDK methods: `getClientHealth()`, `getClientHealthDetail(clientId)`
* Web API client methods: `getClientHealth()`, `getClientHealthDetail(clientId)`
* **Dashboard rewrite** — clients page now shows real health scores, completion rates, deploy streaks, week-over-week trends, and expandable detail with member breakdown and 4-week trend
* **Report integration** — weekly private and monthly reports now include client health summaries; critical clients generate recommended actions
* SDK types: `ClientHealthSummary`, `ClientHealthDetail`
* Unit tests: `tests/unit/client-health.test.ts` (25+ tests for health score, thresholds, carry-forward scoring, deploy streaks, member aggregation)

### V2 Pivot: Phase 3B — Report Generation System

#### Added

* New `reports` API module with service, controller, and REST endpoints
* **Daily public/private reports** posted at 9 PM — per-person task list, completion % (weighted), team total; private adds cards, stale tasks, OOO context, intervention logs, client summary
* **Weekly public/private reports** posted Friday at 6 PM — team stats, target day compliance, performer of week; private adds KPI comparison, card tally, carry-forward patterns, workload distribution, recommended actions
* **Monthly reports** generated on last working day at 6 PM — trend lines, card history, recurring blockers, scalability assessment, employee of month, recommended 1:1s, action items
* **Intervention logging system** — `/log-intervention` Slack command for managers to record 1:1s, coaching, and corrective actions attributed to team members
* **Action items with carry-forward tracking** — open action items automatically carry forward into the next report period
* **Auto-generated recommended actions** based on team data (cards, blockers, carry-forward patterns)
* New DB tables: `reports`, `interventions`, `action_items`
* New dynamic crons: `{orgId}:daily-report` (9 PM), `{orgId}:weekly-report` (Friday 6 PM), `{orgId}:monthly-report` (last working day 6 PM)
* SDK methods: `getReports()`, `logIntervention()`, `getActionItems()`, `getInterventions()`, `updateActionItem()`
* Zod schemas: `logInterventionSchema`, `updateActionItemSchema`

### Dashboard Overhaul: Ops-Brain Command Center

#### Added

* **Ops-brain dashboard** for managers/admins — dark theme, IBM Plex Mono + Instrument Serif fonts
* **5 purpose-built views**: Today (live task feed), Clients (health dashboard), Team (per-person KPI), Reports (daily/weekly/monthly), Cards (card management)
* **Today view**: task feed grouped by person, completion percentages, card pills, OOO badges, cron status panel, active alerts
* **Clients view**: health cards with open rate/CTR metrics, deploy streaks, sparkline charts, team avatars
* **Team view**: two-column layout with person list and detail panel, KPI bars, task list, card history with advisory notes
* **Reports view**: three tabs (Weekly Private, Weekly Public, Daily Digest) with KPI comparison, sends tracking, invisible labor log, action items
* **Cards view**: card log with dismiss functionality, weekly summary, manual red card issuance, rules reference
* **Shared ops components**: StatusDot, Tag, SizeTag, CardPill, OpsAvatar, KpiBar, MiniSparkBar
* **Employee role** retains simplified dashboard with task stats and recent tasks
* **API client methods**: cards, blockers, OOO, reports, KPI, interventions (graceful fallback for unbuilt endpoints)
* **Unit tests**: 43 tests for ops utility functions (status colors, completion calculation, card pill formatting, health determination, size tags)
* **CSS**: ops-brain keyframes (blink, glow, in), custom properties, font imports

### V2 Pivot: Phase 2A — Card System (Yellow/Red Cards)

#### Added

* New `cards` API module with service, controller, and REST endpoints
* **Yellow card triggers**: missing submission (11 AM deadline), task overdue 2+ days, no EOD update
* **Red card**: 3 yellows/week auto-converts to red, manual `/red-card @user reason` Slack command
* **Exemptions**: OOO users fully exempt; ramp-up period first 2 weeks exempt, weeks 3+ noted
* **Card dismissal** by Admin/Manager with reason and DM notification
* **DM notifications** on card issuance (yellow and red) via Slack
* **Weekly card summary** endpoint with per-user breakdown
* **Duplicate prevention**: same trigger+task combo won't issue twice in the same week
* Card evaluation rules as pure functions in `packages/rules/src/cards.ts`
* New static cron: daily at noon scans overdue tasks (2+ days) for yellow cards
* Integration: submission deadline (11 AM) issues MISSING\_SUBMISSION cards
* Integration: EOD collection (7 PM) issues NO\_EOD\_UPDATE cards for users without replies
* SDK methods: `getCards()`, `getCardsByUser()`, `getCardSummary()`, `issueCard()`, `issueRedCard()`, `dismissCard()`
* Zod schemas: `issueCardSchema`, `dismissCardSchema`
* API endpoints: `GET /api/cards`, `GET /api/cards/user/:userId`, `GET /api/cards/summary`, `POST /api/cards`, `POST /api/cards/:id/dismiss`
* Unit tests: `tests/unit/card-rules.test.ts` (23 tests)

### V2 Pivot: Phase 2C — Blocker System

#### Added

* New `blockers` API module with service, controller, and REST endpoints
* **`/blocked [reason]`** command — reports a blocker on user's active task, notifies ops via progress channel
* **`/unblocked [note]`** command — resolves active blocker with optional resolution note, posts resolution time
* **Auto-detection from carry-forward reasons** — EOD collection scans carry-forward text for blocker keywords (`blocked`, `waiting on`, `depends on`, `stuck`, `can't proceed`, `need approval`, `pending review`, `waiting for`)
* **Escalation ladder**:
  * 0h: Ops notified via progress channel on report
  * 8h: Admin/founder DM escalation
  * 24h: Critical alert in progress channel
* **Resolution time tracking** — calculates hours blocked, posts to progress channel on resolution
* New DB table: `blockers` (id, taskId, userId, organizationId, reason, escalationLevel, source, resolved, resolvedAt, resolutionNote)
* New task fields: `blocked` (boolean), `blockedAt` (timestamp)
* New dynamic cron: `{orgId}:blocker-escalation` (every hour)
* SDK methods: `reportBlocker()`, `resolveBlocker()`, `getActiveBlockers()`, `getBlockerStats()`, `getBlockersByUser()`, `detectBlockerFromCarryForward()`
* Zod schemas: `reportBlockerSchema`, `resolveBlockerSchema`, `detectBlockerSchema`
* API endpoints: `GET /api/blockers`, `GET /api/blockers/stats`, `GET /api/blockers/user/:userId`, `POST /api/blockers`, `POST /api/blockers/:id/resolve`, `POST /api/blockers/detect`
* Blocker detection unit tests: `tests/unit/blocker-detection.test.ts` (16 tests)

### V2 Pivot: Phase 2D — OOO (Out-of-Office) System

#### Added

* New `ooo` API module with service, controller, and REST endpoints
* LLM-based parsing of OOO messages from Slack channel (`#out-of-office`)
* Channel monitoring: bot detects messages in the configured OOO channel, parses with LLM, stores in `ooo_records`, reacts with ✅
* `/ooo` slash command fallback for structured input
* Daily OOO status transition cron: `{orgId}:ooo-status-update` (upcoming → active → completed)
* New org preference: `oooChannelId` for configuring the OOO Slack channel
* SDK methods: `listOOORecords()`, `getActiveOOO()`, `checkUserOOO()`, `createOOO()`, `parseOOOMessage()`, `cancelOOO()`
* API endpoints: `GET /api/ooo`, `GET /api/ooo/active`, `GET /api/ooo/check/:userId`, `POST /api/ooo`, `POST /api/ooo/parse`, `DELETE /api/ooo/:id`
* Unit tests: `tests/unit/ooo-parser.test.ts`

### V2 Pivot: Phase 2B — Auto-Classification Engine

#### Added

* New `classification` API module with service, controller, and REST endpoints
* **Keyword-based task classification** — auto-assigns type, size, weight, and client to tasks based on org-configurable keyword mappings
* **Auto-classification on task creation** — every confirmed task draft is immediately classified
* **Morning thread submission classification** — submissions are parsed and classified on recording
* **11:30 AM classification digest** — daily summary posted to progress channel grouping tasks by confidence level
* **Admin UI** — task type map management page at `/dashboard/settings/task-types` with CRUD, seed defaults, and bulk classify actions
* **Task type map CRUD** — create, update, delete keyword-to-type mappings per org; seed default mappings for new orgs
* SDK methods: `classifyTask()`, `classifyAndUpdateTask()`, `bulkClassify()`, `getTaskTypeMap()`, `createTaskTypeMapEntry()`, `updateTaskTypeMapEntry()`, `deleteTaskTypeMapEntry()`, `seedTaskTypeMap()`
* New dynamic cron: `{orgId}:classification-digest` at 11:30 AM
* Shared Zod schemas: `classifyTaskSchema`, `createTaskTypeMapSchema`, `updateTaskTypeMapSchema`
* Unit tests: `tests/unit/classification.test.ts`

### V2 Pivot: Phase 1E — Schedule Settings UI

#### Added

* Admin dashboard: Added "Daily Task Loop" settings section in Channels & Deadlines tab
* Configurable morning thread time, submission deadline, EOD nudge time, and EOD collection time
* Toggle to enable/disable morning threads with progress channel validation
* Sequential time validation (morning → deadline → nudge → collection)

### V2 Pivot: Phase 1D — EOD Collection System

#### Added

* New `eod` API module with service, controller, and REST endpoints
* **5 PM EOD nudge** — bot posts a reminder as a reply to the morning thread prompting users to update task statuses with emoji reactions
* **7 PM EOD collection scan** — bot scans morning thread replies and parses emoji statuses into `task_statuses` records:
  * Done, carry forward, dropped, no update
* **Carry-forward counter** — `carryForwardCount` on tasks is incremented each time a task is marked as carry forward
* **No-update detection** — users who did not reply to the morning thread by 7 PM are flagged with `no_update` status entries
* **Daily summary** — aggregated EOD summary posted to the progress channel after collection
* New org preferences: `eodNudgeTime` (default `17:00`), `eodCollectionTime` (default `19:00`)
* New dynamic crons: `{orgId}:eod-nudge`, `{orgId}:eod-collection`
* SDK methods: `getEodSummary()`, `getEodStatuses()`, `triggerEodCollection()`
* EOD parser unit tests: `tests/unit/eod-parser.test.ts`
* API endpoints: `GET /api/eod/summary/:date?`, `GET /api/eod/statuses/:date?`, `POST /api/eod/collect`

### V2 Pivot: Phase 1A — Database Schema (Foundation)

#### New Tables

* **`clients`** — Client entities with deploy schedules, content cadence, assigned writers/designers
* **`cards`** — Yellow/red accountability cards with trigger tracking, weekly reset, dismissal
* **`morning_threads`** — Daily morning thread records (channel, thread TS, deadline/EOD flags)
* **`thread_submissions`** — User replies to morning threads (raw text, parsed status)
* **`task_statuses`** — Daily per-task status snapshots (done, carry\_forward, dropped, no\_update)
* **`ooo_records`** — Out-of-office records (manual or parsed from Slack, date range, status)
* **`task_type_map`** — Org-configurable keyword → task type/size/weight mapping

#### Modified Tables

* **`tasks`** — Added: `taskType`, `size` (S/M/L), `weight`, `clientId` (FK → clients), `carryForwardCount`
* **`task_drafts`** — Added: `taskType`, `size`, `weight`, `clientId` (mirrors tasks for draft → task conversion)
* **`users`** — Added: `rampUpStartDate`, `rampUpDurationWeeks` (for onboarding ramp-up periods)

#### New Enums (`@hitler/shared`)

* `TaskSize` (small/medium/large), `TaskType` (newsletter\_draft, social\_post, design\_task, etc.)
* `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)
* `TASK_SIZE_WEIGHTS` constant mapping sizes to numeric weights

### V2 Pivot: Phase 1B — Client Management Module

#### Added

* New `clients` API module with full CRUD (create, list, get, update, soft delete)
* Member assignment endpoint (`PUT /api/clients/:id/members`) for assigning writers and designers
* Deploy schedule endpoint (`GET /api/clients/schedule`) for weekly content planning
* Zod validation schemas: `createClientSchema`, `updateClientSchema`, `assignMembersSchema`
* `ClientStatus` enum (`active`, `paused`, `offboarded`) in shared package
* SDK methods: `createClient`, `listClients`, `getClient`, `updateClient`, `deleteClient`, `assignClientMembers`, `getDeploySchedule`
* Admin dashboard page at `/dashboard/clients` with table view, status filter, create/edit forms, and member assignment dialog
* "Clients" entry in sidebar navigation (manager+ role)
* API reference documentation for all 7 client endpoints

### V2 Pivot: Phase 1C — Morning Thread System

#### Added

* New `morning-threads` API module with service, controller, and REST endpoints
* 9 AM cron posts daily thread to `#today-in-progress` channel
* Thread reply tracking: Slack bot detects replies and stores as `thread_submissions`
* 11 AM deadline scan DMs users who haven't submitted to the morning thread
* New org preferences: `enableMorningThread`, `morningThreadTime`, `submissionDeadlineTime`, `progressChannelId`
* SDK methods: `getTodayMorningThread()`, `recordThreadSubmission()`, `findMorningThreadByTs()`
* API endpoints: `GET /api/morning-threads/today`, `GET /api/morning-threads/by-date/:date`, `GET /api/morning-threads/:id/submissions`, `GET /api/morning-threads/:id/missing`

***

## \[1.4.0] - Task Table UX, Deadline Nudges, Progress Channel & Bug Fixes

### Summary

Dashboard task tables now show project names, inline status actions, and overdue highlighting. Short-deadline tasks get immediate DM nudges. Progress channel uses status-based indicators. Multiple bug fixes for flags, scheduler date serialization, and Slack status validation.

### Added

#### Inline Task Actions (Dashboard + Project Tables)

* Dropdown menu on each task row: **Start**, **Complete**, **Cancel**, **View Details**
* Project task table also has **Remove from Project** action
* Client-side pagination (10 per page) on project task table

#### Overdue Highlighting

* Task due dates in red with "OVERDUE" badge when past due and not completed/cancelled

#### Deadline Nudges for Short Deadlines

* `queueDeadlineNudge()` in `jobs.service.ts` supports BullMQ `delay` parameter
* When a task with a due date \< 24h is confirmed, three nudges are scheduled:
  * **Gentle** — immediately
  * **Reminder** — at 50% of remaining time
  * **Urgent** — at 85% of remaining time (min 5 min before due)
* Previously, only the 15-minute cron caught these — a 10-minute deadline would be missed entirely

#### Status-Based Progress Channel Indicators

* `⬜` Pending, `🔵` In-progress, `✅` Completed (strikethrough), `🔴` Overdue, `⚫` Cancelled (strikethrough)
* Priority shown as suffix only for P1/P2: `(P1)`, `(P2)`
* Replaces old priority-based colored circles which made it hard to distinguish status

### Fixed

#### Project Name in Task Table (Backend Bug)

* `findByUserPaginated()` in `tasks.service.ts` now does a `leftJoin` with `projects` table
* Previously returned `projectName: null` for all tasks because the JOIN was missing

#### Flags Endpoint Validation Error

* Frontend was sending `status=active` but Zod schema only accepts `open`, `suggested_resolved`, `resolved`
* Fixed `api.ts` client and `team/page.tsx` to use `open` instead of `active`
* Fixed Swagger annotations in `flags.controller.ts`

#### Scheduler Date Serialization

* Proactive nudge scanner was crashing every 15 minutes: `TypeError: "string" argument must be string, got Date`
* All `Date` objects in `sql` template literals now use `.toISOString()` (5 occurrences in `scheduler.service.ts`)

#### Nullable projectId in Task Updates

* `updateTaskSchema` now accepts `projectId: null` for removing a task from a project

### Files Changed

| File                                                           | Changes                                              |
| -------------------------------------------------------------- | ---------------------------------------------------- |
| `apps/api/src/modules/tasks/tasks.service.ts`                  | leftJoin for project name; deadline nudge scheduling |
| `apps/api/src/modules/tasks/tasks.controller.ts`               | Nullable projectId in update schema                  |
| `apps/api/src/modules/jobs/jobs.service.ts`                    | `queueDeadlineNudge()` with delay support            |
| `apps/api/src/modules/jobs/scheduler.service.ts`               | Date `.toISOString()` fixes (5 occurrences)          |
| `apps/api/src/modules/slack/slack-blocks.ts`                   | Status-based indicators + dueDate in interface       |
| `apps/api/src/modules/jobs/workers/progress-channel.worker.ts` | Pass dueDate in task data                            |
| `apps/api/src/modules/flags/flags.controller.ts`               | Fix Swagger enum for flag status                     |
| `apps/web/src/app/dashboard/tasks/page.tsx`                    | Inline status dropdown + overdue highlighting        |
| `apps/web/src/app/dashboard/projects/page.tsx`                 | Action buttons + pagination                          |
| `apps/web/src/app/dashboard/team/page.tsx`                     | Fix flag status from "active" to "open"              |
| `apps/web/src/lib/api.ts`                                      | Nullable projectId; fix flag status type             |
| `tests/unit/progress-channel.test.ts`                          | Updated for status-based emojis                      |

***

## \[1.3.0] - Slack Onboarding, Bot Fixes & API Client Hardening

### Summary

Welcome DM after Slack bot install, test connection button on onboarding, redirect fixes, auto-detected timezone, loading states, and multiple bug fixes across the SDK, adapters, and progress channel worker.

### Added

#### Welcome DM After Slack Install

* Bot sends a welcome DM to the installing user immediately after the OAuth flow completes
* `SlackModule` imported into `AuthModule` so `SlackAuthController` can inject `SlackWebApiService`
* Welcome message: "Hey! Hitler is now connected to your workspace. You can start chatting with me right here..."
* Wrapped in try/catch so a failed DM never breaks the install flow

#### Test Connection Button (Onboarding)

* New `POST /api/organizations/:id/test-slack` endpoint — sends a test DM to verify the bot works
* Onboarding step 2 now shows a "Connected" state with:
  * Green checkmark + "Slack Connected!" confirmation
  * "We sent you a welcome message in Slack — check your DMs!"
  * "Send Test Message" button to verify bot connection before proceeding
  * "Continue" button to advance to step 3
* `testSlackConnection()` method added to web API client

#### Auto-Detected Timezone

* Onboarding timezone selector now auto-detects the user's timezone via `Intl.DateTimeFormat().resolvedOptions().timeZone`
* If the detected timezone is not in the common list, it's dynamically added with "(detected)" label
* Hint text shows the detected timezone to the user

#### Loading States on Onboarding

* All onboarding buttons now show loading spinners and are disabled during async operations
* Prevents double-clicks and provides feedback during network requests

### Fixed

#### Slack OAuth Redirect (302)

* `handleInstallCallback()` in `slack-auth.controller.ts` now uses explicit `reply.status(302).redirect()` for all redirect paths
* Added logging before each redirect for debugging

#### API Client Content-Type Header

* `apps/web/src/lib/api.ts` — `fetch()` helper now only sets `Content-Type: application/json` when a body is present
* Previously, bodyless POST/PATCH/DELETE requests sent the header, causing Fastify to reject with "Body cannot be empty when content-type is set to 'application/json'"
* Also added `body: JSON.stringify({})` to `confirmTaskDraft()` and `rejectTaskDraft()` as belt-and-suspenders

#### SDK Paginated Response Handling

* `packages/sdk/src/client.ts` — `getTasks()` now unwraps paginated `{items, total}` responses from the API
* Previously returned the raw object, causing `tasks.slice is not a function` crashes in the Slack bot's Home tab "My Tasks" button

#### Status Button Validation Error

* `packages/adapters/src/conversation.ts` — `handleStatus()` was passing `status: "open"` to the API, which only accepts `"pending"`, `"in_progress"`, `"completed"`, `"cancelled"`
* Now fetches `"pending"` and `"in_progress"` separately and sums the counts

#### Progress Channel Duplicate Messages

* Added unique `jobId` (`progress-${eventType}-${taskId}`) to BullMQ progress channel jobs to prevent duplicate processing
* Wrapped project channel post in try/catch so a failure there doesn't cause a job retry that re-posts to the progress channel

### Files Changed

| File                                                             | Action                                          |
| ---------------------------------------------------------------- | ----------------------------------------------- |
| `apps/api/src/modules/auth/auth.module.ts`                       | Import SlackModule                              |
| `apps/api/src/modules/auth/slack-auth.controller.ts`             | Welcome DM + 302 redirect fix                   |
| `apps/api/src/modules/organizations/organizations.controller.ts` | Add test-slack endpoint                         |
| `apps/api/src/modules/jobs/jobs.service.ts`                      | Add jobId to progress channel jobs              |
| `apps/api/src/modules/jobs/workers/progress-channel.worker.ts`   | Try/catch on project channel post               |
| `apps/web/src/lib/api.ts`                                        | Content-Type fix + testSlackConnection method   |
| `apps/web/src/app/onboarding/page.tsx`                           | Connected state, test button, timezone, loading |
| `packages/sdk/src/client.ts`                                     | Unwrap paginated getTasks response              |
| `packages/adapters/src/conversation.ts`                          | Fix status "open" → "pending" + "in\_progress"  |

***

## \[1.2.0] - Dark Mode Support

### Summary

Added full dark mode support across the entire admin dashboard. Light/Dark/System toggle with consistent theming using CSS custom properties and semantic design tokens. All \~275 hardcoded gray Tailwind classes replaced with theme-aware tokens.

### Added

* **`next-themes`** — theme provider with `class` strategy, system preference detection, and persistent storage
* **`.dark` CSS variables** in `globals.css` — full dark palette for background, foreground, card, popover, primary, secondary, muted, accent, destructive, border, input, ring
* **`ThemeToggle` component** — Sun/Moon dropdown with Light/Dark/System options using `useTheme()` from next-themes
* **`suppressHydrationWarning`** on `<html>` tag to prevent flash of unstyled content

### Changed

* **`providers.tsx`** — wrapped app with `<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>`
* **`dashboard-layout.tsx`** — theme toggle added to header, all gray classes converted to semantic tokens
* **\~275 hardcoded gray classes** replaced across 25+ files:
  * `text-gray-900/700` → `text-foreground`
  * `text-gray-600/500/400` → `text-muted-foreground`
  * `bg-white` → `bg-background` or `bg-card`
  * `bg-gray-50/100` → `bg-muted`
  * `border-gray-200/300` → `border-border`
  * `divide-gray-*` → `divide-border`
  * `hover:bg-gray-50` → `hover:bg-muted`
  * `hover:bg-gray-100` → `hover:bg-accent`
* **Dark mode variants** added for colored elements (status badges, alerts, flags):
  * Green: `dark:bg-green-900/30 dark:text-green-400`
  * Red: `dark:bg-red-900/30 dark:text-red-400`
  * Yellow: `dark:bg-yellow-900/30 dark:text-yellow-400`
  * Blue: `dark:bg-blue-900/30 dark:text-blue-400`
  * Purple/Indigo/Orange: same pattern
* **`badge.tsx`** — success/warning/info variants now include dark mode colors
* **Auth pages** — error/success banners have `dark:` variants for red/green backgrounds
* **Integration pages** — converted to semantic tokens with dark mode alert variants

### Technical Notes

* Sidebar stays dark in both modes (intentional — already uses hitler-dark background)
* Landing page (`/`) intentionally unchanged — already dark-themed in both modes
* Chart components use hardcoded hex colors for Recharts compatibility (not CSS variables)
* `ring-8 ring-white` in activity-feed timeline may need `ring-background` adjustment if visual issues arise
* Zero gray Tailwind classes remain in `apps/web/src/**/*.tsx`

### Files Changed

* **1 new file**: `theme-toggle.tsx`
* **25+ modified files**: all dashboard pages, auth pages, integration pages, shared components, UI primitives

***

## \[1.1.0] - Admin Dashboard: shadcn/ui Migration

### Summary

Migrated the entire admin dashboard from hand-written Tailwind CSS classes to shadcn/ui component library with lucide-react icons. Added testing infrastructure with Vitest + React Testing Library. All 16 pages migrated with zero business logic changes.

### Added

* **shadcn/ui component library** — 21 components: Button, Card, Badge, Input, Textarea, Select, Checkbox, Switch, Label, Tabs, Dialog, DropdownMenu, Table, Separator, Skeleton, Avatar, Tooltip, ScrollArea, Sheet, Slider, Sonner
* **lucide-react icons** — replaced \~80 inline SVG icon function components across all pages
* **CSS variable theming** — `:root` variables for primary, secondary, sidebar, muted, accent, destructive, border, ring
* **Testing infrastructure** — Vitest + jsdom + React Testing Library + custom render with AuthProvider mock
* **15 component tests** — Button (8 tests) and Badge (7 tests)
* `apps/web/src/lib/utils.ts` — `cn()` utility (clsx + tailwind-merge)
* `apps/web/components.json` — shadcn/ui configuration
* `apps/web/vitest.config.mts` — web-specific test configuration

### Changed

* **All 16 pages** migrated to shadcn/ui components:
  * 9 dashboard pages (main, tasks, projects, team, chat, analytics, settings, notifications, profile)
  * 3 auth pages (login, signup, complete-signup)
  * 3 integration pages (integrations, slack, slack/callback)
  * 1 landing page
* **dashboard-layout.tsx** — Sheet for mobile sidebar, DropdownMenu for profile, Avatar, lucide-react icons
* **notifications-dropdown.tsx** — DropdownMenu with Bell trigger
* **empty-state.tsx** — Button component replacing CSS class buttons
* **settings page** — Tabs replaces manual tab state, Switch replaces checkboxes, Dialog replaces confirm(), Sonner toast replaces inline save messages
* **tailwind.config.js** — added tailwindcss-animate plugin, CSS variable color mappings, shadcn conventions

### Removed

* **40+ custom CSS classes** from `globals.css` `@layer components` block (btn-*, card-*, badge-*, table-*, modal-*, avatar-*, etc.)
* **\~80 inline SVG icon function components** replaced by lucide-react imports

### Technical Notes

* Radix Select uses `__none__` sentinel for empty values (projects page channel selector)
* Landing page FeatureCard kept custom glass-morphism styling (Card's white bg would break dark theme)
* Brand icons (Teams, WhatsApp) kept as custom SVGs — no lucide-react equivalents
* Root vitest config excludes `apps/web/**` — web tests run via `pnpm --filter @hitler/web test`

***

## \[Unreleased] - Team Visibility, Projects & Proactive Nudges

### Added

#### Phase 0: Slack Web API Service

* `SlackWebApiService` — wraps `@slack/web-api` with per-org bot token retrieval from Cloudflare KV
* `SlackModule` — NestJS module exporting the service
* `slack-blocks.ts` — reusable Slack block builders for channel posts (daily task post, deadline tag, EOD summary, nudge DM, overdue escalation)

#### Phase 1: Database Schema — Projects + Task Duration

* `projects` table with Slack channel linking and escalation configuration
* `projectId` and `estimatedDurationMinutes` columns added to `tasks` and `taskDrafts`
* `OverdueEscalationMode` enum and `projectSchema` Zod validation

#### Phase 2: Projects API Module

* Full CRUD for projects (create, list, get, update, archive)
* Task service extended with project-aware queries (`findByProject`, `findTodaysTasks`, `findUsersWithoutTasksToday`)
* Organization endpoint for listing Slack channels (admin dropdown)

#### Phase 3: Job System — Workers

* `PROGRESS_CHANNEL_UPDATE` — live task create/complete updates in progress channel
* `PROGRESS_CHANNEL_DEADLINE` — deadline enforcement with public tagging
* `PROGRESS_CHANNEL_EOD_SUMMARY` — end-of-day summary compilation
* `PROACTIVE_NUDGE` — DM nudges about approaching deadlines
* `OVERDUE_ESCALATION` — configurable escalation flow (DM → channel → admin)

#### Phase 4: Scheduler — New Cron Jobs

* Daily task deadline check (every 5 minutes, timezone-aware)
* End-of-day summary (every 5 minutes, timezone-aware)
* Proactive nudge scanner (every 15 minutes)
* Enhanced overdue scanner with project escalation support

#### Phase 5: LLM Tool Integration

* `create_task_draft` tool extended with `project_name` and `estimated_duration_minutes`
* New `get_projects` tool for listing org projects
* Duration inference in system prompt (quick call=15min, meeting=60min, etc.)

#### Phase 6: Admin Dashboard

* "Channels & Deadlines" settings tab (progress channel, deadline, EOD summary, nudges)
* Projects management page (CRUD, escalation config, task listing)
* Task table updated with project and duration columns

#### Phase 7: SDK + Adapter Updates

* `Project` interface and project methods in SDK client
* `Task` and `TaskDraft` types extended with `projectId` and `estimatedDurationMinutes`
* Block builders updated to show project and duration information

### New Organization Preferences

* `dailyTaskDeadlineEnabled`, `dailyTaskDeadline`
* `progressChannelId`, `progressChannelName`, `enableProgressChannel`
* `eodSummaryTime`
* `enableProactiveNudges`, `nudgeIntensity`

### Files Changed

* **15 new files** across API modules, DB schema, web app, and tests
* **20 modified files** spanning all layers of the stack

***

## \[1.0.0] - Admin Dashboard Baseline

### Summary

Initial release of the Hitler admin dashboard. Hand-written Tailwind CSS with 40+ custom component classes, inline SVG icons, manual dropdowns/modals, no component library, and zero frontend tests.

### Current State

* **16 pages**: 9 dashboard routes, 3 auth routes, 3 integration routes, 1 landing page
* **9 component files**: dashboard-layout, notifications-dropdown, error-boundary, protected-route, add-to-slack-button, animations, empty-state, activity-feed, charts
* **40+ custom CSS classes** in globals.css (`@layer components`)
* **0 frontend tests**
* **Stack**: Next.js 15, React 19, Tailwind CSS 3, Framer Motion, Recharts
