Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
context: .
file: ./backend/Dockerfile
push: false
tags: pagelm-backend:test
tags: pagelm-backend:test
cache-from: type=gha
cache-to: type=gha,mode=max

Expand All @@ -87,7 +87,7 @@ jobs:
context: ./frontend
file: ./frontend/Dockerfile
push: false
tags: pagelm-frontend:test
tags: pagelm-frontend:test
cache-from: type=gha
cache-to: type=gha,mode=max

Expand Down
2 changes: 1 addition & 1 deletion backend/src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cors from 'cors';
import path from 'path'
import server from '../utils/server/server'
import server from '../utils/server/server.js'
import { registerRoutes } from './router'
import { loggerMiddleware } from './middleware'

Expand Down
1 change: 1 addition & 0 deletions backend/src/core/routes/flashcards.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import crypto from 'crypto'
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description lists only planner-related files, but this PR also changes backend/src/core/routes/flashcards.ts, backend/src/core/index.ts, and .github/workflows/ci.yml. Please either update the PR description to cover these changes or split them into a separate PR to keep scope clear.

Copilot uses AI. Check for mistakes.
import db from '../../utils/database/keyv'

export function flashcardRoutes(app: any) {
Expand Down
5 changes: 4 additions & 1 deletion backend/src/core/routes/planner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,10 @@ setInterval(async () => {

if (hh === 8 && mm < 5 && lastDigest !== today) {
lastDigest = today
const tomorrow = new Date(today + "T23:59:59Z").toISOString()
const tomorrowDate = new Date(now)
tomorrowDate.setDate(tomorrowDate.getDate() + 1)
tomorrowDate.setHours(23, 59, 59, 999)
const tomorrow = tomorrowDate.toISOString()
Comment on lines +323 to +326
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The daily digest window mixes local time (getHours()/getMinutes()) with a UTC-based day key (now.toISOString().slice(0, 10)). Since the new tomorrowDate logic is based on local time, this UTC/local mismatch can cause the digest to run under the wrong today value (and misclassify dueToday) for users not in UTC. Consider deriving today from local midnight (e.g., new Date(now.getFullYear(), now.getMonth(), now.getDate())) and using that consistently for lastDigest, dueToday comparisons, and the dueBefore cutoff.

Copilot uses AI. Check for mistakes.
const tasks = await plannerService.listTasks({ dueBefore: tomorrow })
const dueToday = tasks.filter(t => new Date(t.dueAt).toDateString() === new Date(today).toDateString())
const todaySessions = await plannerService.getTodaySessions()
Expand Down
18 changes: 12 additions & 6 deletions backend/src/services/planner/ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,15 @@ function parseDateHeuristic(dateStr: string): string {
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())

if (dateStr.toLowerCase() === 'today') {
return new Date(today.getTime() + 23 * 60 * 60 * 1000).toISOString()
const todayEnd = new Date(today)
todayEnd.setHours(23, 59, 59, 999)
return todayEnd.toISOString()
}

if (dateStr.toLowerCase() === 'tomorrow') {
return new Date(today.getTime() + 47 * 60 * 60 * 1000).toISOString()
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000)
tomorrow.setHours(23, 59, 59, 999)
return tomorrow.toISOString()
Comment on lines 146 to +149
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In parseDateHeuristic, tomorrow is computed by adding 24 * 60 * 60 * 1000 milliseconds to today. This can produce wrong calendar dates around DST transitions (a β€œday” isn’t always 24h). Prefer using the Date API (setDate(getDate()+1) / setDate(getDate()+daysToAdd)) for day arithmetic; same concern applies to the other places in this function that add N * 24h in milliseconds (weekday calculation, fallback tomorrow, next/this week).

Copilot uses AI. Check for mistakes.
}

if (dateStr.toLowerCase().includes('next week')) {
Expand Down Expand Up @@ -171,10 +175,10 @@ function parseDateHeuristic(dateStr: string): string {
if (targetDay !== -1) {
const currentDay = now.getDay()
let daysToAdd = targetDay - currentDay
if (daysToAdd <= 0) daysToAdd += 7
if (daysToAdd < 0) daysToAdd += 7

const targetDate = new Date(today.getTime() + daysToAdd * 24 * 60 * 60 * 1000)
targetDate.setHours(23, 59, 0, 0)
targetDate.setHours(23, 59, 59, 999)
Comment on lines 176 to +181
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This weekday branch builds targetDate via today.getTime() + daysToAdd * 24h. That has the same DST-related calendar-day risk as the tomorrow calculation and can land on the wrong local day/hour when clocks shift. Use new Date(today) plus setDate(today.getDate() + daysToAdd) instead of millisecond arithmetic.

Copilot uses AI. Check for mistakes.
return targetDate.toISOString()
}

Expand All @@ -183,7 +187,7 @@ function parseDateHeuristic(dateStr: string): string {
const month = parseInt(dateMatch[1]) - 1
const day = parseInt(dateMatch[2])
const year = now.getFullYear()
const targetDate = new Date(year, month, day, 23, 59, 0, 0)
const targetDate = new Date(year, month, day, 23, 59, 59, 999)

if (targetDate.getTime() < now.getTime()) {
targetDate.setFullYear(year + 1)
Expand All @@ -192,7 +196,9 @@ function parseDateHeuristic(dateStr: string): string {
return targetDate.toISOString()
}

return new Date(today.getTime() + 47 * 60 * 60 * 1000).toISOString()
const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000)
tomorrow.setHours(23, 59, 59, 999)
return tomorrow.toISOString()
}

export async function generateSteps(task: Task): Promise<string[]> {
Expand Down
Loading