@warlock.js/scheduler 5.28.0 → 5.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/scheduler` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.29.0 - 2026-10-01
8
+
9
+ ### Changed
10
+
11
+ - Lockstep release; package APIs are unchanged. Skills refer to other topics by name instead of file paths, so cross-references keep working after `agent-kit` copies them into an app.
12
+
7
13
  ## 5.28.0 - 2026-10-01
8
14
 
9
15
  ### Changed
package/llms-full.txt CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ---
10
10
  name: configure-retry-and-overlap
11
- description: 'Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — `@warlock.js/scheduler/observe-scheduler/SKILL.md`; building the schedule itself — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; competing libs `p-retry`, `async-retry`, `bullmq`.'
11
+ description: 'Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — the `observe-scheduler` topic; building the schedule itself — the `schedule-fluently` topic; competing libs `p-retry`, `async-retry`, `bullmq`.'
12
12
  ---
13
13
 
14
14
  # Retry, backoff, and overlap
@@ -141,8 +141,8 @@ If retries push the total work past the next interval, `preventOverlap()` ensure
141
141
 
142
142
  ## See also
143
143
 
144
- - [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) — full event reference, `JobResult` shape, lifecycle
145
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the scheduling methods these compose with
144
+ - The `observe-scheduler` topic — full event reference, `JobResult` shape, lifecycle
145
+ - The `schedule-fluently` topic — the scheduling methods these compose with
146
146
 
147
147
  ## Running on one server only: `onOneServer()`
148
148
 
@@ -164,7 +164,7 @@ job("sync", sync).everyMinutes(5).onOneServer({ lockTtl: "10m", key: "sync-v2" }
164
164
 
165
165
  ---
166
166
  name: observe-scheduler
167
- description: 'Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; building schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; native `EventEmitter`, `process.on`.'
167
+ description: 'Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — the `configure-retry-and-overlap` topic; building schedules — the `schedule-fluently` topic; native `EventEmitter`, `process.on`.'
168
168
  ---
169
169
 
170
170
  # Observability and lifecycle
@@ -313,8 +313,8 @@ job.cronExpression; // string | null
313
313
 
314
314
  ## See also
315
315
 
316
- - [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) — what triggers each event in detail
317
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the methods that mutate the state these getters expose
316
+ - The `configure-retry-and-overlap` topic — what triggers each event in detail
317
+ - The `schedule-fluently` topic — the methods that mutate the state these getters expose
318
318
 
319
319
 
320
320
  ## overview `@warlock.js/scheduler/overview/SKILL.md`
@@ -350,28 +350,28 @@ Six task skills cover the full surface. Most callers only need `scheduler-basics
350
350
 
351
351
  ### Foundations
352
352
 
353
- #### [`scheduler-basics`](@warlock.js/scheduler/scheduler-basics/SKILL.md)
353
+ #### `scheduler-basics`
354
354
  Start here. The `job(name, fn)` factory, the `scheduler` singleton, the 2-primitive surface, UTC default, why the API is factory-first.
355
355
 
356
356
  ### Scheduling
357
357
 
358
- #### [`schedule-fluently`](@warlock.js/scheduler/schedule-fluently/SKILL.md)
358
+ #### `schedule-fluently`
359
359
  Build schedules without writing cron: `.everyMinutes(N)`, `.daily().at("03:00")`, `.weekly().on("monday")`, `.monthly()`, `.beginOf("month")`, `.endOf("year")`, and friends. Reach for this 80% of the time.
360
360
 
361
- #### [`schedule-with-cron`](@warlock.js/scheduler/schedule-with-cron/SKILL.md)
361
+ #### `schedule-with-cron`
362
362
  Drop down to `.cron("0 9 * * 1-5")` when the fluent API can't express it (Vixie OR semantics for DOM/DOW, complex multi-value lists). Includes `parseCron()` for previewing next-run times before deploy.
363
363
 
364
364
  ### Production concerns
365
365
 
366
- #### [`configure-retry-and-overlap`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md)
366
+ #### `configure-retry-and-overlap`
367
367
  `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed or exponential backoff; `.preventOverlap()` so a slow run never collides with the next tick. Reach for both anytime a job calls external services.
368
368
 
369
- #### [`pin-schedule-timezone`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md)
369
+ #### `pin-schedule-timezone`
370
370
  `.inTimezone("America/New_York")` pins wall-clock fire times across DST and across servers. The default is UTC — if your job description includes "9 AM," you almost certainly want this skill.
371
371
 
372
372
  ### Observability + shutdown
373
373
 
374
- #### [`observe-scheduler`](@warlock.js/scheduler/observe-scheduler/SKILL.md)
374
+ #### `observe-scheduler`
375
375
  The seven typed `SchedulerEvents` (`job:start` / `complete` / `error` / `skip`, `scheduler:started` / `stopped` / `tick`), the `JobResult` payload, `start()` / `stop()` / `shutdown()`. Wire this for logging, metrics, alerting, and graceful SIGTERM handling.
376
376
 
377
377
  ## Quick taste
@@ -413,15 +413,15 @@ process.on("SIGTERM", () => scheduler.shutdown());
413
413
 
414
414
  ## See also
415
415
 
416
- - [`@warlock.js/core/overview/SKILL.md`](@warlock.js/core/overview/SKILL.md) — the parent framework that scheduled jobs typically run alongside.
417
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview/SKILL.md` becomes the front-door skill in `.claude/skills/warlock-js-scheduler-overview/`. Every cross-link above uses the `@warlock.js/scheduler/<skill>/SKILL.md` name form so it survives that flattening.
416
+ - The `overview` topic of the `warlock-js-core` skill — the parent framework that scheduled jobs typically run alongside.
417
+ - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview` topic becomes the front-door skill in `.claude/skills/warlock-js-scheduler-overview/`. Every cross-link above names the topic (and the owning skill, across packages) instead of a file path so it survives that flattening.
418
418
 
419
419
 
420
420
  ## pin-schedule-timezone `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`
421
421
 
422
422
  ---
423
423
  name: pin-schedule-timezone
424
- description: 'Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; cron syntax — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.'
424
+ description: 'Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — the `schedule-fluently` topic; cron syntax — the `schedule-with-cron` topic; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.'
425
425
  ---
426
426
 
427
427
  # Per-job timezones
@@ -530,16 +530,16 @@ Node ships full ICU on most platforms, so all IANA zones work out of the box. If
530
530
 
531
531
  ## See also
532
532
 
533
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — `at()`, `on()`, `daily()`, etc.
534
- - [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) — cron schedules are timezone-aware too
535
- - [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) — `job.nextRun.toISOString()` always renders in UTC; format with `.tz(zone)` to see local time
533
+ - The `schedule-fluently` topic — `at()`, `on()`, `daily()`, etc.
534
+ - The `schedule-with-cron` topic — cron schedules are timezone-aware too
535
+ - The `observe-scheduler` topic — `job.nextRun.toISOString()` always renders in UTC; format with `.tz(zone)` to see local time
536
536
 
537
537
 
538
538
  ## schedule-fluently `@warlock.js/scheduler/schedule-fluently/SKILL.md`
539
539
 
540
540
  ---
541
541
  name: schedule-fluently
542
- description: 'Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; retry — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.'
542
+ description: 'Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — the `schedule-with-cron` topic; timezone — the `pin-schedule-timezone` topic; retry — the `configure-retry-and-overlap` topic; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.'
543
543
  ---
544
544
 
545
545
  # Fluent scheduling API
@@ -623,7 +623,7 @@ Both accept `"day" | "month" | "year"`.
623
623
 
624
624
  ## Cron is an alternative, not an addition
625
625
 
626
- `.cron("…")` clears any prior interval/`at`/`on`/`beginOf`/`endOf` config — and vice versa. They're mutually exclusive. See [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md).
626
+ `.cron("…")` clears any prior interval/`at`/`on`/`beginOf`/`endOf` config — and vice versa. They're mutually exclusive. See the `schedule-with-cron` topic.
627
627
 
628
628
  ## Chaining order doesn't matter (for the most part)
629
629
 
@@ -675,16 +675,16 @@ j?.cronExpression; // null if using fluent API
675
675
 
676
676
  ## See also
677
677
 
678
- - [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) — when the fluent API isn't enough
679
- - [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) — `.retry()` and `.preventOverlap()` on the same job
680
- - [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) — `.inTimezone()`
678
+ - The `schedule-with-cron` topic — when the fluent API isn't enough
679
+ - The `configure-retry-and-overlap` topic — `.retry()` and `.preventOverlap()` on the same job
680
+ - The `pin-schedule-timezone` topic — `.inTimezone()`
681
681
 
682
682
 
683
683
  ## schedule-with-cron `@warlock.js/scheduler/schedule-with-cron/SKILL.md`
684
684
 
685
685
  ---
686
686
  name: schedule-with-cron
687
- description: 'Write `.cron(''…'')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.'
687
+ description: 'Write `.cron(''…'')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — the `schedule-fluently` topic; timezone — the `pin-schedule-timezone` topic; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.'
688
688
  ---
689
689
 
690
690
  # Cron expressions
@@ -799,12 +799,12 @@ Impossible expressions are rejected eagerly at construction (see Validation), so
799
799
 
800
800
  ## Timezone interaction
801
801
 
802
- If the job has `.inTimezone(tz)`, the cron parser receives a timezone-aware `dayjs` object — so `0 9 * * *` with `.inTimezone("Asia/Tokyo")` fires at 09:00 JST. See [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md).
802
+ If the job has `.inTimezone(tz)`, the cron parser receives a timezone-aware `dayjs` object — so `0 9 * * *` with `.inTimezone("Asia/Tokyo")` fires at 09:00 JST. See the `pin-schedule-timezone` topic.
803
803
 
804
804
  ## See also
805
805
 
806
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the higher-level alternative for human-readable schedules
807
- - [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) — pinning a cron schedule to a wall-clock timezone
806
+ - The `schedule-fluently` topic — the higher-level alternative for human-readable schedules
807
+ - The `pin-schedule-timezone` topic — pinning a cron schedule to a wall-clock timezone
808
808
 
809
809
 
810
810
  ## scheduler-basics `@warlock.js/scheduler/scheduler-basics/SKILL.md`
@@ -840,9 +840,9 @@ npm install @warlock.js/scheduler
840
840
  The 9 things that are true in every scheduler use:
841
841
 
842
842
  1. **Factory-first.** `import { job, scheduler } from "@warlock.js/scheduler"`. Users do not call `new Job()` directly (it works, but `job()` is the documented surface).
843
- 2. **Default timezone is UTC.** `daily().at("09:00")` fires at 09:00 UTC, regardless of the server's clock. Pin a job to wall-clock with `.inTimezone("America/New_York")`. See [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md).
844
- 3. **The scheduler awaits each tick.** Concurrent same-job runs from the scheduler's own loop are structurally impossible. `preventOverlap()` is for jobs that ALSO get invoked outside the loop. See [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md).
845
- 4. **Cron uses 5-field Vixie semantics.** When both `dayOfMonth` and `dayOfWeek` are restricted (neither is `*`), a date matches if EITHER constraint matches. Standard-cron compatible. See [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md).
843
+ 2. **Default timezone is UTC.** `daily().at("09:00")` fires at 09:00 UTC, regardless of the server's clock. Pin a job to wall-clock with `.inTimezone("America/New_York")`. See the `pin-schedule-timezone` topic.
844
+ 3. **The scheduler awaits each tick.** Concurrent same-job runs from the scheduler's own loop are structurally impossible. `preventOverlap()` is for jobs that ALSO get invoked outside the loop. See the `configure-retry-and-overlap` topic.
845
+ 4. **Cron uses 5-field Vixie semantics.** When both `dayOfMonth` and `dayOfWeek` are restricted (neither is `*`), a date matches if EITHER constraint matches. Standard-cron compatible. See the `schedule-with-cron` topic.
846
846
  5. **`nextRun` always advances after a run — success OR failure.** A permanently failing job re-fires on its next scheduled slot, not on every tick.
847
847
  6. **Validation throws at definition time.** `every(0)`, `at("24:00")`, `on(32)`, `retry(-1)`, malformed cron — all throw immediately when you wire the job, not at runtime.
848
848
  7. **`Job.run()` returns a `JobResult`, never throws.** Errors funnel into `result.error`. The scheduler emits `job:error` after all retries are exhausted.
@@ -892,11 +892,11 @@ scheduler.around((job, run) => storage.run({ job: job.name }, run));
892
892
 
893
893
  | If the task is about… | Load |
894
894
  | --- | --- |
895
- | Building schedules via `every*`/`daily`/`weekly`/`monthly`/`at`/`on`/`beginOf`/`endOf` | [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) |
896
- | Writing `.cron("…")` expressions, debugging DOM/DOW behavior, using `parseCron()` for preview | [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) |
897
- | Configuring `.retry()` / exponential backoff, `.preventOverlap()`, understanding failure rescheduling | [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) |
898
- | Subscribing to scheduler events, reading `JobResult`, lifecycle, graceful shutdown | [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) |
899
- | Per-job `.inTimezone()`, multi-region patterns, DST handling | [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) |
895
+ | Building schedules via `every*`/`daily`/`weekly`/`monthly`/`at`/`on`/`beginOf`/`endOf` | the `schedule-fluently` topic |
896
+ | Writing `.cron("…")` expressions, debugging DOM/DOW behavior, using `parseCron()` for preview | the `schedule-with-cron` topic |
897
+ | Configuring `.retry()` / exponential backoff, `.preventOverlap()`, understanding failure rescheduling | the `configure-retry-and-overlap` topic |
898
+ | Subscribing to scheduler events, reading `JobResult`, lifecycle, graceful shutdown | the `observe-scheduler` topic |
899
+ | Per-job `.inTimezone()`, multi-region patterns, DST handling | the `pin-schedule-timezone` topic |
900
900
 
901
901
  ## When NOT to use this skill
902
902
 
package/llms.txt CHANGED
@@ -6,10 +6,10 @@
6
6
 
7
7
  ## Skills
8
8
 
9
- - [configure-retry-and-overlap](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md): Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — `@warlock.js/scheduler/observe-scheduler/SKILL.md`; building the schedule itself — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; competing libs `p-retry`, `async-retry`, `bullmq`.
10
- - [observe-scheduler](@warlock.js/scheduler/observe-scheduler/SKILL.md): Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; building schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; native `EventEmitter`, `process.on`.
9
+ - [configure-retry-and-overlap](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md): Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — the `observe-scheduler` topic; building the schedule itself — the `schedule-fluently` topic; competing libs `p-retry`, `async-retry`, `bullmq`.
10
+ - [observe-scheduler](@warlock.js/scheduler/observe-scheduler/SKILL.md): Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — the `configure-retry-and-overlap` topic; building schedules — the `schedule-fluently` topic; native `EventEmitter`, `process.on`.
11
11
  - [overview](@warlock.js/scheduler/overview/SKILL.md): @warlock.js/scheduler overview for orientation and choosing the focused skill for the task.
12
- - [pin-schedule-timezone](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md): Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; cron syntax — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.
13
- - [schedule-fluently](@warlock.js/scheduler/schedule-fluently/SKILL.md): Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; retry — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.
14
- - [schedule-with-cron](@warlock.js/scheduler/schedule-with-cron/SKILL.md): Write `.cron('…')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.
12
+ - [pin-schedule-timezone](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md): Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — the `schedule-fluently` topic; cron syntax — the `schedule-with-cron` topic; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.
13
+ - [schedule-fluently](@warlock.js/scheduler/schedule-fluently/SKILL.md): Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — the `schedule-with-cron` topic; timezone — the `pin-schedule-timezone` topic; retry — the `configure-retry-and-overlap` topic; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.
14
+ - [schedule-with-cron](@warlock.js/scheduler/schedule-with-cron/SKILL.md): Write `.cron('…')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — the `schedule-fluently` topic; timezone — the `pin-schedule-timezone` topic; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.
15
15
  - [scheduler-basics](@warlock.js/scheduler/scheduler-basics/SKILL.md): Start here for @warlock.js/scheduler recurring jobs, schedules, worker configuration, and job lifecycle.
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "dayjs": "^1.11.19"
9
9
  },
10
10
  "peerDependencies": {
11
- "@warlock.js/cache": "5.28.0"
11
+ "@warlock.js/cache": "5.29.0"
12
12
  },
13
13
  "peerDependenciesMeta": {
14
14
  "@warlock.js/cache": {
@@ -33,7 +33,7 @@
33
33
  ],
34
34
  "author": "hassanzohdy",
35
35
  "license": "MIT",
36
- "version": "5.28.0",
36
+ "version": "5.29.0",
37
37
  "main": "./cjs/index.cjs",
38
38
  "module": "./esm/index.mjs",
39
39
  "types": "./esm/index.d.mts",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: configure-retry-and-overlap
3
- description: 'Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — `@warlock.js/scheduler/observe-scheduler/SKILL.md`; building the schedule itself — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; competing libs `p-retry`, `async-retry`, `bullmq`.'
3
+ description: 'Configure `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed / exponential backoff and `.preventOverlap()` for external-invocation safety. Triggers: `.retry`, `.preventOverlap`, `maxRetries`, `backoffMultiplier`, `JobResult.retries`, `job:error`, `job:skip`; "how do I retry a failed job", "exponential backoff for scheduled job", "prevent concurrent job runs", "stop firing after N consecutive failures"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: events / shutdown — the `observe-scheduler` topic; building the schedule itself — the `schedule-fluently` topic; competing libs `p-retry`, `async-retry`, `bullmq`.'
4
4
  ---
5
5
 
6
6
  # Retry, backoff, and overlap
@@ -133,8 +133,8 @@ If retries push the total work past the next interval, `preventOverlap()` ensure
133
133
 
134
134
  ## See also
135
135
 
136
- - [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) — full event reference, `JobResult` shape, lifecycle
137
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the scheduling methods these compose with
136
+ - The `observe-scheduler` topic — full event reference, `JobResult` shape, lifecycle
137
+ - The `schedule-fluently` topic — the scheduling methods these compose with
138
138
 
139
139
  ## Running on one server only: `onOneServer()`
140
140
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: observe-scheduler
3
- description: 'Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; building schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; native `EventEmitter`, `process.on`.'
3
+ description: 'Subscribe to scheduler lifecycle and job events for logging / metrics / alerting / graceful shutdown — seven typed `SchedulerEvents`, `JobResult` payload, `start()` / `stop()` / `shutdown()`. Triggers: `scheduler.on`, `scheduler.shutdown`, `JobResult`, `job:complete`, `job:error`, `scheduler:started`, `scheduler.getJob`; "graceful SIGTERM shutdown", "did this job run", "scheduler metrics and alerts", "subscribe to job events"; typical import `import { scheduler, type JobResult } from "@warlock.js/scheduler"`. Skip: retry / overlap — the `configure-retry-and-overlap` topic; building schedules — the `schedule-fluently` topic; native `EventEmitter`, `process.on`.'
4
4
  ---
5
5
 
6
6
  # Observability and lifecycle
@@ -149,5 +149,5 @@ job.cronExpression; // string | null
149
149
 
150
150
  ## See also
151
151
 
152
- - [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) — what triggers each event in detail
153
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the methods that mutate the state these getters expose
152
+ - The `configure-retry-and-overlap` topic — what triggers each event in detail
153
+ - The `schedule-fluently` topic — the methods that mutate the state these getters expose
@@ -29,28 +29,28 @@ Six task skills cover the full surface. Most callers only need `scheduler-basics
29
29
 
30
30
  ### Foundations
31
31
 
32
- #### [`scheduler-basics`](@warlock.js/scheduler/scheduler-basics/SKILL.md)
32
+ #### `scheduler-basics`
33
33
  Start here. The `job(name, fn)` factory, the `scheduler` singleton, the 2-primitive surface, UTC default, why the API is factory-first.
34
34
 
35
35
  ### Scheduling
36
36
 
37
- #### [`schedule-fluently`](@warlock.js/scheduler/schedule-fluently/SKILL.md)
37
+ #### `schedule-fluently`
38
38
  Build schedules without writing cron: `.everyMinutes(N)`, `.daily().at("03:00")`, `.weekly().on("monday")`, `.monthly()`, `.beginOf("month")`, `.endOf("year")`, and friends. Reach for this 80% of the time.
39
39
 
40
- #### [`schedule-with-cron`](@warlock.js/scheduler/schedule-with-cron/SKILL.md)
40
+ #### `schedule-with-cron`
41
41
  Drop down to `.cron("0 9 * * 1-5")` when the fluent API can't express it (Vixie OR semantics for DOM/DOW, complex multi-value lists). Includes `parseCron()` for previewing next-run times before deploy.
42
42
 
43
43
  ### Production concerns
44
44
 
45
- #### [`configure-retry-and-overlap`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md)
45
+ #### `configure-retry-and-overlap`
46
46
  `.retry(maxRetries, delay?, backoffMultiplier?)` for fixed or exponential backoff; `.preventOverlap()` so a slow run never collides with the next tick. Reach for both anytime a job calls external services.
47
47
 
48
- #### [`pin-schedule-timezone`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md)
48
+ #### `pin-schedule-timezone`
49
49
  `.inTimezone("America/New_York")` pins wall-clock fire times across DST and across servers. The default is UTC — if your job description includes "9 AM," you almost certainly want this skill.
50
50
 
51
51
  ### Observability + shutdown
52
52
 
53
- #### [`observe-scheduler`](@warlock.js/scheduler/observe-scheduler/SKILL.md)
53
+ #### `observe-scheduler`
54
54
  The seven typed `SchedulerEvents` (`job:start` / `complete` / `error` / `skip`, `scheduler:started` / `stopped` / `tick`), the `JobResult` payload, `start()` / `stop()` / `shutdown()`. Wire this for logging, metrics, alerting, and graceful SIGTERM handling.
55
55
 
56
56
  ## Quick taste
@@ -92,5 +92,5 @@ process.on("SIGTERM", () => scheduler.shutdown());
92
92
 
93
93
  ## See also
94
94
 
95
- - [`@warlock.js/core/overview/SKILL.md`](@warlock.js/core/overview/SKILL.md) — the parent framework that scheduled jobs typically run alongside.
96
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview/SKILL.md` becomes the front-door skill in `.claude/skills/warlock-js-scheduler-overview/`. Every cross-link above uses the `@warlock.js/scheduler/<skill>/SKILL.md` name form so it survives that flattening.
95
+ - The `overview` topic of the `warlock-js-core` skill — the parent framework that scheduled jobs typically run alongside.
96
+ - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview` topic becomes the front-door skill in `.claude/skills/warlock-js-scheduler-overview/`. Every cross-link above names the topic (and the owning skill, across packages) instead of a file path so it survives that flattening.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: pin-schedule-timezone
3
- description: 'Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; cron syntax — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.'
3
+ description: 'Pin a job to a specific IANA timezone via `.inTimezone(zone)` so its wall-clock fire time stays correct regardless of server location / DST. Triggers: `.inTimezone`, `America/New_York`, `Europe/Berlin`, `Asia/Tokyo`, `NODE_ICU_DATA`; "schedule job in a timezone", "DST drift on non-UTC server", "multi-region fan-out scheduling", "fire at 9am ET regardless of server"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: fluent interval methods — the `schedule-fluently` topic; cron syntax — the `schedule-with-cron` topic; competing libs `dayjs-timezone`, `luxon`, `date-fns-tz`.'
4
4
  ---
5
5
 
6
6
  # Per-job timezones
@@ -109,6 +109,6 @@ Node ships full ICU on most platforms, so all IANA zones work out of the box. If
109
109
 
110
110
  ## See also
111
111
 
112
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — `at()`, `on()`, `daily()`, etc.
113
- - [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) — cron schedules are timezone-aware too
114
- - [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) — `job.nextRun.toISOString()` always renders in UTC; format with `.tz(zone)` to see local time
112
+ - The `schedule-fluently` topic — `at()`, `on()`, `daily()`, etc.
113
+ - The `schedule-with-cron` topic — cron schedules are timezone-aware too
114
+ - The `observe-scheduler` topic — `job.nextRun.toISOString()` always renders in UTC; format with `.tz(zone)` to see local time
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: schedule-fluently
3
- description: 'Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — `@warlock.js/scheduler/schedule-with-cron/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; retry — `@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.'
3
+ description: 'Build a job schedule via `every*` / `daily` / `weekly` / `monthly` / `at` / `on` / `beginOf` / `endOf`. Triggers: `.everyMinutes`, `.daily`, `.weekly`, `.monthly`, `.at`, `.on`, `.every`, `.beginOf`, `.endOf`, `.twiceDaily`, `scheduler.newJob`; "run every 5 minutes", "daily at 3am", "monday standup", "first of every month", "last day of month"; typical import `import { job, scheduler } from "@warlock.js/scheduler"`. Skip: cron — the `schedule-with-cron` topic; timezone — the `pin-schedule-timezone` topic; retry — the `configure-retry-and-overlap` topic; competing `node-cron`, `node-schedule`, `agenda`; native `setInterval`.'
4
4
  ---
5
5
 
6
6
  # Fluent scheduling API
@@ -84,7 +84,7 @@ Both accept `"day" | "month" | "year"`.
84
84
 
85
85
  ## Cron is an alternative, not an addition
86
86
 
87
- `.cron("…")` clears any prior interval/`at`/`on`/`beginOf`/`endOf` config — and vice versa. They're mutually exclusive. See [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md).
87
+ `.cron("…")` clears any prior interval/`at`/`on`/`beginOf`/`endOf` config — and vice versa. They're mutually exclusive. See the `schedule-with-cron` topic.
88
88
 
89
89
  ## Chaining order doesn't matter (for the most part)
90
90
 
@@ -136,6 +136,6 @@ j?.cronExpression; // null if using fluent API
136
136
 
137
137
  ## See also
138
138
 
139
- - [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) — when the fluent API isn't enough
140
- - [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) — `.retry()` and `.preventOverlap()` on the same job
141
- - [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) — `.inTimezone()`
139
+ - The `schedule-with-cron` topic — when the fluent API isn't enough
140
+ - The `configure-retry-and-overlap` topic — `.retry()` and `.preventOverlap()` on the same job
141
+ - The `pin-schedule-timezone` topic — `.inTimezone()`
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: schedule-with-cron
3
- description: 'Write `.cron(''…'')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — `@warlock.js/scheduler/schedule-fluently/SKILL.md`; timezone — `@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.'
3
+ description: 'Write `.cron(''…'')` expressions — 5-field syntax, operators (`*` `,` `-` `/`), Vixie OR semantics for DOM / DOW, `parseCron()` preview utility. Triggers: `.cron`, `parseCron`, `CronParser`, `*/5 * * * *`, `0 9 * * 1-5`; "write a cron expression", "every weekday at 9am cron", "preview next cron run", "migrate crontab(5) entry"; typical import `import { parseCron } from "@warlock.js/scheduler"`. Skip: human-readable schedules — the `schedule-fluently` topic; timezone — the `pin-schedule-timezone` topic; competing libs `node-cron`, `cron`, `croner`, `cronstrue`.'
4
4
  ---
5
5
 
6
6
  # Cron expressions
@@ -115,9 +115,9 @@ Impossible expressions are rejected eagerly at construction (see Validation), so
115
115
 
116
116
  ## Timezone interaction
117
117
 
118
- If the job has `.inTimezone(tz)`, the cron parser receives a timezone-aware `dayjs` object — so `0 9 * * *` with `.inTimezone("Asia/Tokyo")` fires at 09:00 JST. See [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md).
118
+ If the job has `.inTimezone(tz)`, the cron parser receives a timezone-aware `dayjs` object — so `0 9 * * *` with `.inTimezone("Asia/Tokyo")` fires at 09:00 JST. See the `pin-schedule-timezone` topic.
119
119
 
120
120
  ## See also
121
121
 
122
- - [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) — the higher-level alternative for human-readable schedules
123
- - [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) — pinning a cron schedule to a wall-clock timezone
122
+ - The `schedule-fluently` topic — the higher-level alternative for human-readable schedules
123
+ - The `pin-schedule-timezone` topic — pinning a cron schedule to a wall-clock timezone
@@ -29,9 +29,9 @@ npm install @warlock.js/scheduler
29
29
  The 9 things that are true in every scheduler use:
30
30
 
31
31
  1. **Factory-first.** `import { job, scheduler } from "@warlock.js/scheduler"`. Users do not call `new Job()` directly (it works, but `job()` is the documented surface).
32
- 2. **Default timezone is UTC.** `daily().at("09:00")` fires at 09:00 UTC, regardless of the server's clock. Pin a job to wall-clock with `.inTimezone("America/New_York")`. See [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md).
33
- 3. **The scheduler awaits each tick.** Concurrent same-job runs from the scheduler's own loop are structurally impossible. `preventOverlap()` is for jobs that ALSO get invoked outside the loop. See [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md).
34
- 4. **Cron uses 5-field Vixie semantics.** When both `dayOfMonth` and `dayOfWeek` are restricted (neither is `*`), a date matches if EITHER constraint matches. Standard-cron compatible. See [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md).
32
+ 2. **Default timezone is UTC.** `daily().at("09:00")` fires at 09:00 UTC, regardless of the server's clock. Pin a job to wall-clock with `.inTimezone("America/New_York")`. See the `pin-schedule-timezone` topic.
33
+ 3. **The scheduler awaits each tick.** Concurrent same-job runs from the scheduler's own loop are structurally impossible. `preventOverlap()` is for jobs that ALSO get invoked outside the loop. See the `configure-retry-and-overlap` topic.
34
+ 4. **Cron uses 5-field Vixie semantics.** When both `dayOfMonth` and `dayOfWeek` are restricted (neither is `*`), a date matches if EITHER constraint matches. Standard-cron compatible. See the `schedule-with-cron` topic.
35
35
  5. **`nextRun` always advances after a run — success OR failure.** A permanently failing job re-fires on its next scheduled slot, not on every tick.
36
36
  6. **Validation throws at definition time.** `every(0)`, `at("24:00")`, `on(32)`, `retry(-1)`, malformed cron — all throw immediately when you wire the job, not at runtime.
37
37
  7. **`Job.run()` returns a `JobResult`, never throws.** Errors funnel into `result.error`. The scheduler emits `job:error` after all retries are exhausted.
@@ -81,11 +81,11 @@ scheduler.around((job, run) => storage.run({ job: job.name }, run));
81
81
 
82
82
  | If the task is about… | Load |
83
83
  | --- | --- |
84
- | Building schedules via `every*`/`daily`/`weekly`/`monthly`/`at`/`on`/`beginOf`/`endOf` | [`@warlock.js/scheduler/schedule-fluently/SKILL.md`](@warlock.js/scheduler/schedule-fluently/SKILL.md) |
85
- | Writing `.cron("…")` expressions, debugging DOM/DOW behavior, using `parseCron()` for preview | [`@warlock.js/scheduler/schedule-with-cron/SKILL.md`](@warlock.js/scheduler/schedule-with-cron/SKILL.md) |
86
- | Configuring `.retry()` / exponential backoff, `.preventOverlap()`, understanding failure rescheduling | [`@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md`](@warlock.js/scheduler/configure-retry-and-overlap/SKILL.md) |
87
- | Subscribing to scheduler events, reading `JobResult`, lifecycle, graceful shutdown | [`@warlock.js/scheduler/observe-scheduler/SKILL.md`](@warlock.js/scheduler/observe-scheduler/SKILL.md) |
88
- | Per-job `.inTimezone()`, multi-region patterns, DST handling | [`@warlock.js/scheduler/pin-schedule-timezone/SKILL.md`](@warlock.js/scheduler/pin-schedule-timezone/SKILL.md) |
84
+ | Building schedules via `every*`/`daily`/`weekly`/`monthly`/`at`/`on`/`beginOf`/`endOf` | the `schedule-fluently` topic |
85
+ | Writing `.cron("…")` expressions, debugging DOM/DOW behavior, using `parseCron()` for preview | the `schedule-with-cron` topic |
86
+ | Configuring `.retry()` / exponential backoff, `.preventOverlap()`, understanding failure rescheduling | the `configure-retry-and-overlap` topic |
87
+ | Subscribing to scheduler events, reading `JobResult`, lifecycle, graceful shutdown | the `observe-scheduler` topic |
88
+ | Per-job `.inTimezone()`, multi-region patterns, DST handling | the `pin-schedule-timezone` topic |
89
89
 
90
90
  ## When NOT to use this skill
91
91