# Files changed · PR \#22230 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/22230/diffs)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

[revert: "fix\(scheduler\): label fixed-time tasks with the server timezone" \(\#18653\)](https://git.cafe/pingdotgg/t3code/pull/22230.md)

Version: 5

Head commit: 2d97501a25eb3fb60e72d3a22f789b5bc3a6de4d

Base commit: b14ae647a311b3e5be0487fe3f6bae217cd88ff5

Comparison base: b14ae647a311b3e5be0487fe3f6bae217cd88ff5

Showing up to 20 entries from this revision. If the pull request changes, reopen the first page before continuing.

## apps/server/src/scheduledTasks/ScheduledTaskService.schedule.test.ts

Status: modified; +0; −47

```diff
@@ -6,7 +6,6 @@
 import * as Effect from "effect/Effect";
 import * as Layer from "effect/Layer";
 import * as Schema from "effect/Schema";
-import * as Stream from "effect/Stream";
 import * as TestClock from "effect/testing/TestClock";
 
 import * as ThreadLaunchService from "../orchestration-v2/ThreadLaunchService.ts";
@@ -59,52 +58,6 @@
   }).pipe(Effect.provide(SqlitePersistence.layerMemory)),
 );
 
-it.effect("includes the scheduler zone in empty lists and subscription updates", () =>
-  Effect.gen(function* () {
-    const layerDependencies = Layer.mergeAll(
-      NodeCrypto.layer,
-      Scheduler.layer,
-      Layer.mock(ThreadLaunchService.ThreadLaunchService)({}),
-      Layer.mock(ManagedProjectFolders.ManagedProjectFolders)({
-        namedProjectsRoot: "/projects",
-        isScratchProject: () => Effect.succeed(false),
-      }),
-      Layer.mock(ThreadManagementService.ThreadManagementService)({}),
-      Layer.mock(SecretRequests.SecretRequests)({}),
-    );
-    yield* Effect.gen(function* () {
-      const service = yield* ScheduledTaskService.ScheduledTaskService;
-      const timeZone = DateTime.zoneToString(DateTime.zoneMakeLocal());
-      expect(yield* service.list()).toEqual({ tasks: [], timeZone });
-
-      const input = yield* decodeUpsertInput({
-        title: "Morning review",
-        prompt: "Review the open pull requests.",
-        enabled: false,
-        schedule: { type: "fixed_time", timeOfDay: "09:00" },
-        projectId: "project-schedule-zone",
-        workspaceStrategy: { type: "root" },
-        modelSelection: { instanceId: "codex", model: "gpt-5.4" },
-        runtimeMode: "full-access",
-        interactionMode: "default",
-      });
-      const snapshots = yield* service.subscribeList().pipe(
-        Stream.tap((snapshot) =>
-          snapshot.tasks.length === 0 ? service.upsert(input) : Effect.void,
-        ),
-        Stream.take(2),
-        Stream.runCollect,
-      );
-      const populated = yield* service.list();
-      expect(populated).toMatchObject({
-        timeZone,
-        tasks: [{ title: "Morning review", schedule: input.schedule }],
-      });
-      expect(snapshots).toEqual([{ tasks: [], timeZone }, populated]);
-    }).pipe(Effect.provide(ScheduledTaskService.layer.pipe(Layer.provide(layerDependencies))));
-  }).pipe(Effect.provide(SqlitePersistence.layerMemory)),
-);
-
 it.effect("preserves a due run when a save only pads the scheduled hour", () =>
   Effect.gen(function* () {
     const dueAt = DateTime.makeZonedUnsafe(
```

## apps/server/src/scheduledTasks/ScheduledTaskService.ts

Status: modified; +1; −4

```diff
@@ -936,10 +936,7 @@
 
     const list: ScheduledTaskService["Service"]["list"] = () =>
       listRows().pipe(
-        Effect.map((tasks) => ({
+        Effect.map((tasks) => ({ tasks })),
-          tasks,
-          timeZone: DateTime.zoneToString(DateTime.zoneMakeLocal()),
-        })),
         Effect.mapError((cause) => taskError("Could not list schedule tasks.", { cause })),
       );
 
```

## apps/server/src/ws.ts

Status: modified; +0; −1

```diff
@@ -1321,7 +1321,6 @@
         currentSession.scopes.includes(AuthOrchestrationOperateScope)
           ? result
           : {
-              ...result,
               tasks: result.tasks.map(({ webhook: _webhook, ...task }) => task),
             };
       const authorizeEffect = <A, E, R>(
```

## apps/web/src/components/chat/ThreadAutomationsPanel.permissions.browser.test.tsx

Status: modified; +2; −41

```diff
@@ -1,10 +1,4 @@
-import {
-  EnvironmentId,
-  ThreadId,
-  ScheduledTaskId,
+import { EnvironmentId, ThreadId, ScheduledTaskId, type ScheduledTask } from "@t3tools/contracts";
-  type ScheduledTask,
-  type ScheduledTaskListResult,
-} from "@t3tools/contracts";
 import { act } from "react";
 import { createRoot, type Root } from "react-dom/client";
 import { afterEach, beforeEach, expect, it, vi } from "vite-plus/test";
@@ -34,7 +28,7 @@
 });
 vi.mock(import("../../state/query"), async (importOriginal) => ({
   ...(await importOriginal()),
+  useEnvironmentQuery: (() => ({ data: { tasks: [task] }, error: null })) as never,
-  useEnvironmentQuery: (() => ({ data: listResult, error: null })) as never,
 }));
 
 import { ThreadAutomationsPanel } from "./ThreadAutomationsPanel";
@@ -47,15 +41,12 @@
   enabled: true,
   schedule: { type: "interval", everyMs: 60000 },
   lastRunStatus: "never",
-  nextRunAt: null,
 } as ScheduledTask;
-let listResult: ScheduledTaskListResult & { timeZone?: string };
 let root: Root;
 let container: HTMLDivElement;
 beforeEach(() => {
   vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
   state.allowed = true;
-  listResult = { tasks: [task] };
   state.toggle.mockReset().mockResolvedValue({ _tag: "Success" });
   state.run.mockReset().mockResolvedValue({ _tag: "Success" });
   container = document.createElement("div");
@@ -93,33 +84,3 @@
   await act(async () => byLabel("Pause Daily review").click());
   expect(state.toggle).toHaveBeenCalledOnce();
 });
-
-it("labels fixed times with the server zone and preserves labels from older servers", async () => {
-  const tasks: ScheduledTask[] = [
-    { ...task, schedule: { type: "fixed_time", timeOfDay: "09:00" } },
-    { ...task, id: ScheduledTaskId.make("interval"), title: "Interval review" },
-    {
-      ...task,
-      id: ScheduledTaskId.make("webhook"),
-      title: "Webhook review",
-      schedule: { type: "webhook", signature: null },
-    },
-  ];
-  const labels = () => Array.from(container.querySelectorAll("li p"), (row) => row.textContent);
-
-  listResult = { tasks, timeZone: "Asia/Kolkata" };
-  await renderPanel();
-  expect(labels()).toEqual(["Daily at 09:00 Asia/Kolkata", "Every 1 min", "On webhook"]);
-
-  listResult = { tasks, timeZone: "Etc/UTC" };
-  await renderPanel();
-  expect(labels()).toEqual(["Daily at 09:00 UTC", "Every 1 min", "On webhook"]);
-
-  listResult = { tasks, timeZone: "UTC" };
-  await renderPanel();
-  expect(labels()).toEqual(["Daily at 09:00 UTC", "Every 1 min", "On webhook"]);
-
-  listResult = { tasks };
-  await renderPanel();
-  expect(labels()).toEqual(["Daily at 09:00", "Every 1 min", "On webhook"]);
-});
```

## apps/web/src/components/chat/ThreadAutomationsPanel.tsx

Status: modified; +4; −8

```diff
@@ -37,10 +37,10 @@
   failed: "bg-destructive",
 };
 
-function taskScheduleLine(task: ScheduledTask, timeZone: string | undefined) {
+function taskScheduleLine(task: ScheduledTask) {
   return (
     <>
-      {scheduleLabel(task.schedule, timeZone)}
+      {scheduleLabel(task.schedule)}
       {task.enabled && task.nextRunAt !== null ? (
         <>
           {" · next "}
@@ -185,15 +185,11 @@
                 <span className="block truncate text-sm font-medium text-foreground/80">
                   {task.title}
                 </span>
-                <p className="truncate text-2xs text-muted-foreground">
-                  {taskScheduleLine(task, tasksQuery.data?.timeZone)}
-                </p>
+                <p className="truncate text-2xs text-muted-foreground">{taskScheduleLine(task)}</p>
               </TooltipTrigger>
               <TooltipPopup side="left">
                 <p className="font-medium">{task.title}</p>
-                <p className="text-muted-foreground">
-                  {taskScheduleLine(task, tasksQuery.data?.timeZone)}
+                <p className="text-muted-foreground">{taskScheduleLine(task)}</p>
-                </p>
               </TooltipPopup>
             </Tooltip>
             <Tooltip>
```

## apps/web/src/components/settings/ScheduledTasksSettings.tsx

Status: modified; +4; −18

```diff
@@ -179,11 +179,7 @@
   };
 }
 
-function scheduleTimeZoneLabel(timeZone: string | undefined) {
-  return timeZone === "Etc/UTC" ? "UTC" : timeZone;
-}
-
+export function scheduleLabel(schedule: ScheduledTaskSchedule): string {
-export function scheduleLabel(schedule: ScheduledTaskSchedule, timeZone?: string): string {
   if (schedule.type === "webhook") return "On webhook";
   if (schedule.type === "interval") {
     const minutes = schedule.everyMs / 60_000;
@@ -198,8 +194,7 @@
       : weekdays.length === 5 && weekdays.every((day) => day >= 1 && day <= 5)
         ? "Weekdays"
         : weekdays.map((day) => WEEKDAY_LABELS[day]).join(", ");
-  const zone = scheduleTimeZoneLabel(timeZone);
+  return `${days} at ${schedule.timeOfDay}`;
-  return `${days} at ${schedule.timeOfDay}${zone === undefined ? "" : ` ${zone}`}`;
 }
 
 /**
@@ -369,7 +364,6 @@
     return {
       environment,
       connected: index >= 0,
-      timeZone: data?.timeZone,
       tasks: data?.tasks.filter((task) =>
         matchesScheduledTaskScope(scope, environment.environmentId, task.projectId),
       ),
@@ -411,7 +405,7 @@
 
   return (
     <SettingsGroup>
-      {populated.map(({ environment, tasks, timeZone }) => {
+      {populated.map(({ environment, tasks }) => {
         const { primary, secondary } = settingsScopeEnvironmentLabels(environment, environments);
         const transport = environmentTransportLabel(environment);
         return (
@@ -441,7 +435,6 @@
                 key={task.id}
                 environmentId={environment.environmentId}
                 task={task}
-                timeZone={timeZone}
                 onEdit={() => onEdit(environment.environmentId, task)}
               />
             ))}
@@ -557,7 +550,6 @@
                 key={task.id}
                 environmentId={environment.environmentId}
                 task={task}
-                timeZone={tasksQuery.data?.timeZone}
                 onEdit={() => onEdit(environment.environmentId, task)}
               />
             ))
@@ -571,12 +563,10 @@
 function ScheduledTaskRow({
   environmentId,
   task,
-  timeZone,
   onEdit,
 }: {
   readonly environmentId: EnvironmentId;
   readonly task: ScheduledTask;
-  readonly timeZone: string | undefined;
   readonly onEdit: () => void;
 }) {
   const canOperate = useAtomValue(
@@ -621,7 +611,7 @@
       status={
         <div className="flex flex-wrap items-center gap-2">
           <span>
+            {scheduleLabel(task.schedule)} ·{" "}
-            {scheduleLabel(task.schedule, timeZone)} ·{" "}
             {!task.enabled ? (
               "Paused"
             ) : isWebhook ? (
@@ -1008,7 +998,6 @@
     draft.editingId !== null &&
     tasksQuery.data !== null &&
     !tasksQuery.data.tasks.some((entry) => entry.id === draft.editingId);
-  const runAtZone = scheduleTimeZoneLabel(tasksQuery.data?.timeZone);
   const liveTask = tasksQuery.data
     ? (tasksQuery.data.tasks.find((entry) => entry.id === draft.editingId) ?? null)
     : task;
@@ -1512,9 +1501,6 @@
                       setDraft((current) => ({ ...current, timeOfDay: event.target.value }))
                     }
                   />
-                  {runAtZone === undefined ? null : (
-                    <span className="text-xs text-muted-foreground">{runAtZone}</span>
-                  )}
                   <span className="text-xs text-muted-foreground">on</span>
                 </div>
                 <ToggleGroup
```

## packages/contracts/src/scheduledTask.ts

Status: modified; +0; −2

```diff
@@ -196,8 +196,6 @@
   // Trigger types grow over time; a client must not lose the whole list over
   // one task it cannot decode.
   tasks: ForwardCompatibleArray(ScheduledTask),
-  /** The server's IANA zone for fixed-time schedules. Absent from older servers. */
-  timeZone: Schema.optional(TrimmedNonEmptyString),
 });
 export type ScheduledTaskListResult = typeof ScheduledTaskListResult.Type;
 
```
