Skip to main content

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 systemmustChangePassword 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 promptsthreadContextChanged 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 matchingcomplete_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 validationcurrentPassword optional when mustChangePassword is true

[Unreleased]

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

Added

  • Intervention bot commandlog_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 reassignmentreassign_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 configurationisWorkingDay(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 schemasops 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 integrationshow_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 seedingPOST /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 integrationshow_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 countercarryForwardCount 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

FileChanges
apps/api/src/modules/tasks/tasks.service.tsleftJoin for project name; deadline nudge scheduling
apps/api/src/modules/tasks/tasks.controller.tsNullable projectId in update schema
apps/api/src/modules/jobs/jobs.service.tsqueueDeadlineNudge() with delay support
apps/api/src/modules/jobs/scheduler.service.tsDate .toISOString() fixes (5 occurrences)
apps/api/src/modules/slack/slack-blocks.tsStatus-based indicators + dueDate in interface
apps/api/src/modules/jobs/workers/progress-channel.worker.tsPass dueDate in task data
apps/api/src/modules/flags/flags.controller.tsFix Swagger enum for flag status
apps/web/src/app/dashboard/tasks/page.tsxInline status dropdown + overdue highlighting
apps/web/src/app/dashboard/projects/page.tsxAction buttons + pagination
apps/web/src/app/dashboard/team/page.tsxFix flag status from “active” to “open”
apps/web/src/lib/api.tsNullable projectId; fix flag status type
tests/unit/progress-channel.test.tsUpdated 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.tsfetch() 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.tsgetTasks() 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.tshandleStatus() 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

FileAction
apps/api/src/modules/auth/auth.module.tsImport SlackModule
apps/api/src/modules/auth/slack-auth.controller.tsWelcome DM + 302 redirect fix
apps/api/src/modules/organizations/organizations.controller.tsAdd test-slack endpoint
apps/api/src/modules/jobs/jobs.service.tsAdd jobId to progress channel jobs
apps/api/src/modules/jobs/workers/progress-channel.worker.tsTry/catch on project channel post
apps/web/src/lib/api.tsContent-Type fix + testSlackConnection method
apps/web/src/app/onboarding/page.tsxConnected state, test button, timezone, loading
packages/sdk/src/client.tsUnwrap paginated getTasks response
packages/adapters/src/conversation.tsFix 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/700text-foreground
    • text-gray-600/500/400text-muted-foreground
    • bg-whitebg-background or bg-card
    • bg-gray-50/100bg-muted
    • border-gray-200/300border-border
    • divide-gray-*divide-border
    • hover:bg-gray-50hover:bg-muted
    • hover:bg-gray-100hover: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.tscn() 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