From 1f6cea50ed721f525c8b1928f7045324dbb90e4a Mon Sep 17 00:00:00 2001 From: Isaac Sanchez-Hawkins <266845420+isanchez404@users.noreply.github.com> Date: Tue, 12 May 2026 04:10:56 -0400 Subject: [PATCH] fix(tasks): preserve timestamps when listing (#1198) Co-authored-by: Isaac Sanchez --- .../web/server/lib/projects/project-config.js | 4 ++- .../lib/projects/project-config.test.js | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/web/server/lib/projects/project-config.js b/packages/web/server/lib/projects/project-config.js index cbc2df77..d7ee5b29 100644 --- a/packages/web/server/lib/projects/project-config.js +++ b/packages/web/server/lib/projects/project-config.js @@ -270,6 +270,7 @@ const normalizeTaskForStorage = (value, options) => { createId, existingTask, allowCreate, + refreshUpdatedAt = true, } = options; if (!value || typeof value !== 'object') { @@ -307,7 +308,7 @@ const normalizeTaskForStorage = (value, options) => { const state = { ...baseState, createdAt: existingTask?.state?.createdAt ?? baseState.createdAt ?? nowMs, - updatedAt: nowMs, + updatedAt: refreshUpdatedAt ? nowMs : baseState.updatedAt ?? nowMs, }; return { @@ -386,6 +387,7 @@ export const createProjectConfigRuntime = (deps) => { createId: taskIDFactory, existingTask: null, allowCreate: true, + refreshUpdatedAt: false, }); scheduledTasks.push(normalized); } catch { diff --git a/packages/web/server/lib/projects/project-config.test.js b/packages/web/server/lib/projects/project-config.test.js index aa0d4c4e..ef7b5eb4 100644 --- a/packages/web/server/lib/projects/project-config.test.js +++ b/packages/web/server/lib/projects/project-config.test.js @@ -114,6 +114,37 @@ describe('project-config runtime', () => { } }); + it('preserves scheduled task state timestamps when listing tasks', async () => { + const { runtime, cleanup } = await createRuntime(); + try { + const projectID = 'timestamp_preserve'; + const filePath = path.join(runtime.resolveProjectConfigPath(projectID)); + await writeFile( + filePath, + JSON.stringify({ + scheduledTasks: [{ + id: 'task-existing', + name: 'nightly', + enabled: true, + schedule: { kind: 'daily', times: ['09:00'], timezone: 'UTC' }, + execution: { prompt: 'run', providerID: 'openai', modelID: 'gpt-4.1' }, + state: { createdAt: 10, updatedAt: 20, lastStatus: 'idle' }, + }], + }, null, 2), + 'utf8', + ); + + const first = await runtime.listScheduledTasks(projectID); + const second = await runtime.listScheduledTasks(projectID); + + expect(first[0].state.createdAt).toBe(10); + expect(first[0].state.updatedAt).toBe(20); + expect(second[0].state.updatedAt).toBe(20); + } finally { + await cleanup(); + } + }); + it('accepts one-time schedule with date and time', async () => { const { runtime, cleanup } = await createRuntime(); try {