stitchkit 0.109.1 → 0.109.3

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
@@ -15,6 +15,27 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
15
15
 
16
16
  ## [Unreleased]
17
17
 
18
+ ## [0.109.3] - 2026-10-13
19
+
20
+ ### Added
21
+
22
+ - `stitchkit/application` — `createApplicationOpenTelemetry` reports
23
+ `stitchkit.application.schedule.runs_woken` and `.wakes_coalesced` beside the existing schedule
24
+ counters, so a dashboard shows how many runs came from `wake()` and how many came from the
25
+ period.
26
+
27
+ ## [0.109.2] - 2026-10-13
28
+
29
+ ### Added
30
+
31
+ - `stitchkit/application` — `ManagedSchedule.wake()` runs the schedule now, for the owner of the
32
+ event that creates its work. The run takes the timer's path (`dependsOn`, `overlap`,
33
+ `errorPolicy`, `onError`, counters); calls in one tick or during a busy run collapse into one
34
+ following run; before activation and after stop it does nothing. The period keeps its grid, so
35
+ `everyMs: 1000` polling becomes `everyMs: 60_000` plus `wake()`. `ManagedScheduleRunContext`
36
+ gains `trigger` (`'timer' | 'wake'`) and `ManagedScheduleStatus` gains `runsWoken`,
37
+ `wakesCoalesced` and `lastTrigger`.
38
+
18
39
  ## [0.109.1] - 2026-10-11
19
40
 
20
41
  ### Fixed
@@ -1,7 +1,7 @@
1
1
  import type { Attributes, MetricOptions, ObservableGauge } from '@opentelemetry/api';
2
2
  import type { ActivityProjection } from './activity.js';
3
3
  import type { ApplicationHandle } from './kernel-contract.js';
4
- import type { ManagedSchedule } from './schedule.js';
4
+ import type { ManagedSchedule } from './schedule-contract.js';
5
5
  export interface ApplicationTelemetryMeter {
6
6
  createObservableGauge(name: string, options?: MetricOptions): ObservableGauge<Attributes>;
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../../src/application/opentelemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EAEb,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAYlD,MAAM,WAAW,yBAAyB;IACxC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;CAC3F;AAED,MAAM,WAAW,uCAAuC;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC;IAChE,iBAAiB,CAAC,CAAC,OAAO,EAAE,uCAAuC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACf;AAwOD,iFAAiF;AACjF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,+BAA+B,CAwJjC"}
1
+ {"version":3,"file":"opentelemetry.d.ts","sourceRoot":"","sources":["../../src/application/opentelemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EAEb,eAAe,EAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAY3D,MAAM,WAAW,yBAAyB;IACxC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;CAC3F;AAED,MAAM,WAAW,uCAAuC;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC;IACjF,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC;IAChE,iBAAiB,CAAC,CAAC,OAAO,EAAE,uCAAuC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;CACf;AAkPD,iFAAiF;AACjF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,8BAA8B,GACrC,+BAA+B,CAwJjC"}
@@ -0,0 +1,132 @@
1
+ import { z } from 'zod';
2
+ import type { ManagedResource } from './resource.js';
3
+ export declare const ManagedScheduleOverlapSchema: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
4
+ mode: z.ZodLiteral<"skip">;
5
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
6
+ mode: z.ZodLiteral<"queue-one">;
7
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
8
+ mode: z.ZodLiteral<"parallel">;
9
+ maxConcurrent: z.ZodNumber;
10
+ }, z.core.$strip>>], "mode">;
11
+ export type ManagedScheduleOverlap = z.infer<typeof ManagedScheduleOverlapSchema>;
12
+ export declare const ManagedScheduleErrorPolicySchema: z.ZodEnum<{
13
+ continue: "continue";
14
+ "stop-schedule": "stop-schedule";
15
+ }>;
16
+ export type ManagedScheduleErrorPolicy = z.infer<typeof ManagedScheduleErrorPolicySchema>;
17
+ declare const ManagedScheduleTriggerSchema: z.ZodEnum<{
18
+ timer: "timer";
19
+ wake: "wake";
20
+ }>;
21
+ /** What started a run: the period elapsing, or the owner's `wake()`. */
22
+ export type ManagedScheduleTrigger = z.infer<typeof ManagedScheduleTriggerSchema>;
23
+ export declare const ManagedScheduleDescriptorSchema: z.ZodReadonly<z.ZodObject<{
24
+ id: z.ZodString;
25
+ everyMs: z.ZodNumber;
26
+ startAfterMs: z.ZodNumber;
27
+ overlap: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
28
+ mode: z.ZodLiteral<"skip">;
29
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
30
+ mode: z.ZodLiteral<"queue-one">;
31
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
32
+ mode: z.ZodLiteral<"parallel">;
33
+ maxConcurrent: z.ZodNumber;
34
+ }, z.core.$strip>>], "mode">;
35
+ errorPolicy: z.ZodEnum<{
36
+ continue: "continue";
37
+ "stop-schedule": "stop-schedule";
38
+ }>;
39
+ }, z.core.$strip>>;
40
+ export type ManagedScheduleDescriptor = z.infer<typeof ManagedScheduleDescriptorSchema>;
41
+ export declare const ManagedScheduleStatusSchema: z.ZodReadonly<z.ZodObject<{
42
+ descriptor: z.ZodReadonly<z.ZodObject<{
43
+ id: z.ZodString;
44
+ everyMs: z.ZodNumber;
45
+ startAfterMs: z.ZodNumber;
46
+ overlap: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
47
+ mode: z.ZodLiteral<"skip">;
48
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
49
+ mode: z.ZodLiteral<"queue-one">;
50
+ }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
51
+ mode: z.ZodLiteral<"parallel">;
52
+ maxConcurrent: z.ZodNumber;
53
+ }, z.core.$strip>>], "mode">;
54
+ errorPolicy: z.ZodEnum<{
55
+ continue: "continue";
56
+ "stop-schedule": "stop-schedule";
57
+ }>;
58
+ }, z.core.$strip>>;
59
+ state: z.ZodEnum<{
60
+ draining: "draining";
61
+ inactive: "inactive";
62
+ running: "running";
63
+ scheduled: "scheduled";
64
+ stopped: "stopped";
65
+ }>;
66
+ revision: z.ZodNumber;
67
+ capturedAt: z.ZodString;
68
+ changedAt: z.ZodString;
69
+ accepting: z.ZodBoolean;
70
+ active: z.ZodNumber;
71
+ queued: z.ZodBoolean;
72
+ runsStarted: z.ZodNumber;
73
+ runsCompleted: z.ZodNumber;
74
+ runsFailed: z.ZodNumber;
75
+ runsWoken: z.ZodNumber;
76
+ ticksSkipped: z.ZodNumber;
77
+ wakesCoalesced: z.ZodNumber;
78
+ lastTrigger: z.ZodNullable<z.ZodEnum<{
79
+ timer: "timer";
80
+ wake: "wake";
81
+ }>>;
82
+ nextRunAt: z.ZodNullable<z.ZodString>;
83
+ lastScheduledAt: z.ZodNullable<z.ZodString>;
84
+ lastStartedAt: z.ZodNullable<z.ZodString>;
85
+ lastFinishedAt: z.ZodNullable<z.ZodString>;
86
+ }, z.core.$strip>>;
87
+ export type ManagedScheduleStatus = z.infer<typeof ManagedScheduleStatusSchema>;
88
+ export interface ManagedScheduleTimer {
89
+ cancel(): void;
90
+ }
91
+ /** Monotonic timer boundary. Tests can replace it without changing schedule semantics. */
92
+ export interface ManagedScheduleClock {
93
+ /** Monotonic clock used for cadence and deadline arithmetic. */
94
+ now(): number;
95
+ /** Wall clock used only to project portable status timestamps. */
96
+ wallNow(): Date;
97
+ schedule(callback: () => void, delayMs: number): ManagedScheduleTimer;
98
+ }
99
+ export interface ManagedScheduleRunContext {
100
+ readonly applicationId: string;
101
+ readonly signal: AbortSignal;
102
+ readonly scheduledAt: number;
103
+ readonly startedAt: number;
104
+ readonly trigger: ManagedScheduleTrigger;
105
+ now(): number;
106
+ }
107
+ export interface ManagedScheduleConfig {
108
+ readonly id: string;
109
+ readonly dependsOn?: readonly string[];
110
+ readonly required?: boolean;
111
+ readonly everyMs: number;
112
+ /** Defaults to one interval. A zero value schedules the first run after activation. */
113
+ readonly startAfterMs?: number;
114
+ readonly overlap?: ManagedScheduleOverlap;
115
+ readonly errorPolicy?: ManagedScheduleErrorPolicy;
116
+ readonly run: (context: ManagedScheduleRunContext) => void | Promise<void>;
117
+ readonly onError?: (error: unknown, context: ManagedScheduleRunContext) => void | Promise<void>;
118
+ readonly clock?: ManagedScheduleClock;
119
+ }
120
+ export interface ManagedSchedule extends ManagedResource {
121
+ readonly status: ManagedScheduleStatus;
122
+ /**
123
+ * Ask for one run now, because the owner knows work has appeared. The run takes the same path
124
+ * as a timer run: `overlap`, `onError`, `errorPolicy` and the counters apply, and the period
125
+ * keeps its own cadence as the check for an event that was lost. Calls made in one tick, or
126
+ * while a run holds every slot, collapse into one following run. Before the schedule is
127
+ * activated and after it stops accepting, the call does nothing and is not remembered.
128
+ */
129
+ wake(): void;
130
+ }
131
+ export {};
132
+ //# sourceMappingURL=schedule-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-contract.d.ts","sourceRoot":"","sources":["../../src/application/schedule-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAalD,eAAO,MAAM,4BAA4B;;;;;;;4BASvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,gCAAgC;;;EAAwC,CAAC;AACtF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,QAAA,MAAM,4BAA4B;;;EAA4B,CAAC;AAC/D,wEAAwE;AACxE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;kBAQ/B,CAAC;AACd,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsB3B,CAAC;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,MAAM,WAAW,oBAAoB;IACnC,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,0FAA0F;AAC1F,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,GAAG,IAAI,MAAM,CAAC;IACd,kEAAkE;IAClE,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACvE;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,0BAA0B,CAAC;IAClD,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,yBAAyB,KAC/B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC;;;;;;OAMG;IACH,IAAI,IAAI,IAAI,CAAC;CACd"}
@@ -0,0 +1,47 @@
1
+ import type { ManagedResourceContext } from './resource.js';
2
+ import { type ManagedScheduleClock, type ManagedScheduleConfig, type ManagedScheduleDescriptor, type ManagedScheduleOverlap, type ManagedScheduleRunContext, type ManagedScheduleStatus, type ManagedScheduleTrigger } from './schedule-contract.js';
3
+ export interface ScheduleCounts {
4
+ runsStarted: number;
5
+ runsCompleted: number;
6
+ runsFailed: number;
7
+ runsWoken: number;
8
+ ticksSkipped: number;
9
+ wakesCoalesced: number;
10
+ lastTrigger: ManagedScheduleTrigger | null;
11
+ lastScheduledAt: string | null;
12
+ lastStartedAt: string | null;
13
+ lastFinishedAt: string | null;
14
+ }
15
+ export declare function emptyCounts(): ScheduleCounts;
16
+ /** The validated public descriptor of a schedule configuration, with defaults applied. */
17
+ export declare function describeSchedule(config: ManagedScheduleConfig): ManagedScheduleDescriptor;
18
+ export declare function scheduleState(activated: boolean, stopped: boolean, accepting: boolean, active: number): ManagedScheduleStatus['state'];
19
+ /** A monotonic instant on the wall clock, through one captured anchor. */
20
+ export declare function wallAt(monotonicAt: number | null, anchor: {
21
+ readonly monotonicNow: number;
22
+ readonly wallNow: number;
23
+ }): string | null;
24
+ /** What a due tick does under the overlap policy, given how many runs are active. A wake that
25
+ * is not `start` waits for a free slot under every policy: it is an event, not a missed tick. */
26
+ export declare function overlapDecision(overlap: ManagedScheduleOverlap, active: number): 'start' | 'queue' | 'skip';
27
+ export declare function reportScheduleError(config: ManagedScheduleConfig, error: unknown, context: ManagedScheduleRunContext): void;
28
+ /** Wait for the active runs to settle, or for the signal or the deadline first. */
29
+ export declare function waitForSettled(active: ReadonlySet<Promise<void>>, clock: ManagedScheduleClock, context: ManagedResourceContext, deadlineAt: number | undefined): Promise<void>;
30
+ export interface RunDeps {
31
+ readonly config: ManagedScheduleConfig;
32
+ readonly descriptor: ManagedScheduleDescriptor;
33
+ readonly clock: ManagedScheduleClock;
34
+ readonly counts: ScheduleCounts;
35
+ readonly resourceContext: ManagedResourceContext;
36
+ changed(): void;
37
+ stopAdmission(): void;
38
+ isAccepting(): boolean;
39
+ }
40
+ /**
41
+ * One execution of the schedule's `run`, counted and timestamped, with its
42
+ * outcome turned into health under the error policy. Never rejects.
43
+ */
44
+ export declare function executeRun(deps: RunDeps, scheduledAt: number, trigger: ManagedScheduleTrigger): Promise<void>;
45
+ /** How many whole intervals a late timer spans: at least one, the tick it fired for. */
46
+ export declare function elapsedIntervals(scheduledAt: number, observedAt: number, everyMs: number): number;
47
+ //# sourceMappingURL=schedule-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-run.d.ts","sourceRoot":"","sources":["../../src/application/schedule-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAE9B,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAE1B,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAI7B,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC3C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAgB,WAAW,IAAI,cAAc,CAa5C;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,qBAAqB,GAAG,yBAAyB,CAQzF;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,MAAM,GACb,qBAAqB,CAAC,OAAO,CAAC,CAIhC;AAED,0EAA0E;AAC1E,wBAAgB,MAAM,CACpB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,MAAM,EAAE;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAClE,MAAM,GAAG,IAAI,CAGf;AAED;kGACkG;AAClG,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,MAAM,GACb,OAAO,GAAG,OAAO,GAAG,MAAM,CAI5B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,yBAAyB,GACjC,IAAI,CAON;AAED,mFAAmF;AACnF,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAClC,KAAK,EAAE,oBAAoB,EAC3B,OAAO,EAAE,sBAAsB,EAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,sBAAsB,CAAC;IACjD,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,IAAI,IAAI,CAAC;IACtB,WAAW,IAAI,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,MAAM,CAER"}
@@ -1,111 +1,4 @@
1
- import { z } from 'zod';
2
- import type { ManagedResource } from './resource.js';
3
- export declare const ManagedScheduleOverlapSchema: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
4
- mode: z.ZodLiteral<"skip">;
5
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
6
- mode: z.ZodLiteral<"queue-one">;
7
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
8
- mode: z.ZodLiteral<"parallel">;
9
- maxConcurrent: z.ZodNumber;
10
- }, z.core.$strip>>], "mode">;
11
- export type ManagedScheduleOverlap = z.infer<typeof ManagedScheduleOverlapSchema>;
12
- export declare const ManagedScheduleErrorPolicySchema: z.ZodEnum<{
13
- continue: "continue";
14
- "stop-schedule": "stop-schedule";
15
- }>;
16
- export type ManagedScheduleErrorPolicy = z.infer<typeof ManagedScheduleErrorPolicySchema>;
17
- export declare const ManagedScheduleDescriptorSchema: z.ZodReadonly<z.ZodObject<{
18
- id: z.ZodString;
19
- everyMs: z.ZodNumber;
20
- startAfterMs: z.ZodNumber;
21
- overlap: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
22
- mode: z.ZodLiteral<"skip">;
23
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
24
- mode: z.ZodLiteral<"queue-one">;
25
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
26
- mode: z.ZodLiteral<"parallel">;
27
- maxConcurrent: z.ZodNumber;
28
- }, z.core.$strip>>], "mode">;
29
- errorPolicy: z.ZodEnum<{
30
- continue: "continue";
31
- "stop-schedule": "stop-schedule";
32
- }>;
33
- }, z.core.$strip>>;
34
- export type ManagedScheduleDescriptor = z.infer<typeof ManagedScheduleDescriptorSchema>;
35
- export declare const ManagedScheduleStatusSchema: z.ZodReadonly<z.ZodObject<{
36
- descriptor: z.ZodReadonly<z.ZodObject<{
37
- id: z.ZodString;
38
- everyMs: z.ZodNumber;
39
- startAfterMs: z.ZodNumber;
40
- overlap: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
41
- mode: z.ZodLiteral<"skip">;
42
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
43
- mode: z.ZodLiteral<"queue-one">;
44
- }, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
45
- mode: z.ZodLiteral<"parallel">;
46
- maxConcurrent: z.ZodNumber;
47
- }, z.core.$strip>>], "mode">;
48
- errorPolicy: z.ZodEnum<{
49
- continue: "continue";
50
- "stop-schedule": "stop-schedule";
51
- }>;
52
- }, z.core.$strip>>;
53
- state: z.ZodEnum<{
54
- draining: "draining";
55
- inactive: "inactive";
56
- running: "running";
57
- scheduled: "scheduled";
58
- stopped: "stopped";
59
- }>;
60
- revision: z.ZodNumber;
61
- capturedAt: z.ZodString;
62
- changedAt: z.ZodString;
63
- accepting: z.ZodBoolean;
64
- active: z.ZodNumber;
65
- queued: z.ZodBoolean;
66
- runsStarted: z.ZodNumber;
67
- runsCompleted: z.ZodNumber;
68
- runsFailed: z.ZodNumber;
69
- ticksSkipped: z.ZodNumber;
70
- nextRunAt: z.ZodNullable<z.ZodString>;
71
- lastScheduledAt: z.ZodNullable<z.ZodString>;
72
- lastStartedAt: z.ZodNullable<z.ZodString>;
73
- lastFinishedAt: z.ZodNullable<z.ZodString>;
74
- }, z.core.$strip>>;
75
- export type ManagedScheduleStatus = z.infer<typeof ManagedScheduleStatusSchema>;
76
- export interface ManagedScheduleTimer {
77
- cancel(): void;
78
- }
79
- /** Monotonic timer boundary. Tests can replace it without changing schedule semantics. */
80
- export interface ManagedScheduleClock {
81
- /** Monotonic clock used for cadence and deadline arithmetic. */
82
- now(): number;
83
- /** Wall clock used only to project portable status timestamps. */
84
- wallNow(): Date;
85
- schedule(callback: () => void, delayMs: number): ManagedScheduleTimer;
86
- }
87
- export interface ManagedScheduleRunContext {
88
- readonly applicationId: string;
89
- readonly signal: AbortSignal;
90
- readonly scheduledAt: number;
91
- readonly startedAt: number;
92
- now(): number;
93
- }
94
- export interface ManagedScheduleConfig {
95
- readonly id: string;
96
- readonly dependsOn?: readonly string[];
97
- readonly required?: boolean;
98
- readonly everyMs: number;
99
- /** Defaults to one interval. A zero value schedules the first run after activation. */
100
- readonly startAfterMs?: number;
101
- readonly overlap?: ManagedScheduleOverlap;
102
- readonly errorPolicy?: ManagedScheduleErrorPolicy;
103
- readonly run: (context: ManagedScheduleRunContext) => void | Promise<void>;
104
- readonly onError?: (error: unknown, context: ManagedScheduleRunContext) => void | Promise<void>;
105
- readonly clock?: ManagedScheduleClock;
106
- }
107
- export interface ManagedSchedule extends ManagedResource {
108
- readonly status: ManagedScheduleStatus;
109
- }
1
+ import { type ManagedSchedule, type ManagedScheduleConfig } from './schedule-contract.js';
2
+ /** Create one fixed-rate, process-local periodic application resource. */
110
3
  export declare function createManagedSchedule(config: ManagedScheduleConfig): ManagedSchedule;
111
4
  //# sourceMappingURL=schedule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/application/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AAa1E,eAAO,MAAM,4BAA4B;;;;;;;4BASvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,gCAAgC;;;EAAwC,CAAC;AACtF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;kBAQ/B,CAAC;AACd,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAmB3B,CAAC;AACd,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,MAAM,WAAW,oBAAoB;IACnC,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,0FAA0F;AAC1F,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,GAAG,IAAI,MAAM,CAAC;IACd,kEAAkE;IAClE,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAAC;CACvE;AAWD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,0BAA0B,CAAC;IAClD,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,yBAAyB,KAC/B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;CACxC;AA8ID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAuMpF"}
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../src/application/schedule.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,qBAAqB,EAK3B,MAAM,qBAAqB,CAAC;AAsB7B,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAoMpF"}
@@ -3,7 +3,7 @@ import"../../index-qaet40b2.js";
3
3
  import {
4
4
  ActivitySnapshotSchema2,
5
5
  ManagedScheduleStatusSchema2
6
- } from "../../index-n4689krb.js";
6
+ } from "../../index-f24bdt13.js";
7
7
  import {
8
8
  ApplicationSnapshotSchema2
9
9
  } from "../../index-w5s3xftz.js";
@@ -103,6 +103,8 @@ var scheduleMetrics = [
103
103
  scheduleMetric("stitchkit.application.schedule.runs_started", "Absolute schedule runs started.", (value) => value.runsStarted),
104
104
  scheduleMetric("stitchkit.application.schedule.runs_completed", "Absolute schedule runs completed.", (value) => value.runsCompleted),
105
105
  scheduleMetric("stitchkit.application.schedule.runs_failed", "Absolute schedule runs failed.", (value) => value.runsFailed),
106
+ scheduleMetric("stitchkit.application.schedule.runs_woken", "Absolute schedule runs started by a wake request.", (value) => value.runsWoken),
107
+ scheduleMetric("stitchkit.application.schedule.wakes_coalesced", "Absolute wake requests folded into a run that was already pending.", (value) => value.wakesCoalesced),
106
108
  scheduleMetric("stitchkit.application.schedule.ticks_skipped", "Absolute schedule ticks skipped.", (value) => value.ticksSkipped)
107
109
  ];
108
110
  var activityMetric = (name, description, value) => ({
@@ -18,7 +18,8 @@ export { createProcessLifecycleLedger, type LifecycleLedgerResource, type Lifecy
18
18
  export { type DrainingFact, type LifecycleRun, LifecycleRunSchema, type LifecycleState, LifecycleStateSchema, type LifecycleTermination, LifecycleTerminationSchema, type LifecycleTransition, type PreviousExit, PreviousExitSchema, type ProcessLifecycleFact, type ReadyFact, type SameVersionOverlap, type ShutdownFact, type StartFact, type TransitionRunInput, type TransitionShutdownInput, type TransitionStartInput, transitionProcessDraining, transitionProcessReady, transitionProcessShutdown, transitionProcessStart, type VersionChangeOverlap, } from '../application/process-lifecycle-transitions.js';
19
19
  export { defineManagedResource, type ManagedResource, type ManagedResourceAdmission, type ManagedResourceContext, type ManagedResourceDependency, type ManagedResourcePublished, type ManagedResourcePublishesNoValue, type ManagedResourceStartResult, managedResourceDependencyId, } from '../application/resource.js';
20
20
  export { createRevisionSignal, type RevisionSignal, type RevisionSignalAdvanceResult, RevisionSignalAdvanceResultSchema, type RevisionSignalClock, type RevisionSignalConfig, type RevisionSignalSnapshot, RevisionSignalSnapshotSchema, type RevisionSignalState, RevisionSignalStateSchema, type RevisionSignalTimer, type RevisionSignalWaitOptions, type RevisionSignalWaitOutcome, RevisionSignalWaitOutcomeSchema, type RevisionSignalWaitResult, RevisionSignalWaitResultSchema, } from '../application/revision-signal.js';
21
- export { createManagedSchedule, type ManagedSchedule, type ManagedScheduleClock, type ManagedScheduleConfig, type ManagedScheduleDescriptor, ManagedScheduleDescriptorSchema, type ManagedScheduleErrorPolicy, ManagedScheduleErrorPolicySchema, type ManagedScheduleOverlap, ManagedScheduleOverlapSchema, type ManagedScheduleRunContext, type ManagedScheduleStatus, ManagedScheduleStatusSchema, type ManagedScheduleTimer, } from '../application/schedule.js';
21
+ export { createManagedSchedule } from '../application/schedule.js';
22
+ export { type ManagedSchedule, type ManagedScheduleClock, type ManagedScheduleConfig, type ManagedScheduleDescriptor, ManagedScheduleDescriptorSchema, type ManagedScheduleErrorPolicy, ManagedScheduleErrorPolicySchema, type ManagedScheduleOverlap, ManagedScheduleOverlapSchema, type ManagedScheduleRunContext, type ManagedScheduleStatus, ManagedScheduleStatusSchema, type ManagedScheduleTimer, type ManagedScheduleTrigger, } from '../application/schedule-contract.js';
22
23
  export { type ManagedServerResource, type ManagedServerResourceConfig, managedServerResource, } from '../application/server-resource.js';
23
24
  export type { StateStore, StateStoreUpdate, StateStoreUpdateContext, } from '../application/state-store.js';
24
25
  export { type AttachedWatcher, createWatchHub, type WatchAdmissionScope, type WatchHub, type WatchHubConfig, type WatchOperation, type WatchSubscriber, watchKey, } from '../application/watch-hub.js';
@@ -1 +1 @@
1
- {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/entrypoints/application.ts"],"names":[],"mappings":"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"}
@@ -23,9 +23,8 @@ import {
23
23
  ManagedScheduleOverlapSchema2,
24
24
  ManagedScheduleErrorPolicySchema2,
25
25
  ManagedScheduleDescriptorSchema2,
26
- ManagedScheduleStatusSchema2,
27
- createManagedSchedule2
28
- } from "../index-n4689krb.js";
26
+ ManagedScheduleStatusSchema2
27
+ } from "../index-f24bdt13.js";
29
28
  import {
30
29
  backoffDelay,
31
30
  createBackoff2
@@ -2094,6 +2093,310 @@ function createRevisionSignal(config) {
2094
2093
  getSnapshot: snapshot
2095
2094
  };
2096
2095
  }
2096
+ // src/application/schedule-run.ts
2097
+ var DEFAULT_OVERLAP = { mode: "skip" };
2098
+ function emptyCounts() {
2099
+ return {
2100
+ runsStarted: 0,
2101
+ runsCompleted: 0,
2102
+ runsFailed: 0,
2103
+ runsWoken: 0,
2104
+ ticksSkipped: 0,
2105
+ wakesCoalesced: 0,
2106
+ lastTrigger: null,
2107
+ lastScheduledAt: null,
2108
+ lastStartedAt: null,
2109
+ lastFinishedAt: null
2110
+ };
2111
+ }
2112
+ function describeSchedule(config) {
2113
+ return ManagedScheduleDescriptorSchema2.parse({
2114
+ id: config.id,
2115
+ everyMs: config.everyMs,
2116
+ startAfterMs: config.startAfterMs ?? config.everyMs,
2117
+ overlap: config.overlap ?? DEFAULT_OVERLAP,
2118
+ errorPolicy: config.errorPolicy ?? "continue"
2119
+ });
2120
+ }
2121
+ function scheduleState(activated, stopped, accepting, active) {
2122
+ if (!activated)
2123
+ return stopped ? "stopped" : "inactive";
2124
+ if (!accepting)
2125
+ return active > 0 ? "draining" : "stopped";
2126
+ return active > 0 ? "running" : "scheduled";
2127
+ }
2128
+ function wallAt(monotonicAt, anchor) {
2129
+ if (monotonicAt === null)
2130
+ return null;
2131
+ return new Date(anchor.wallNow + monotonicAt - anchor.monotonicNow).toISOString();
2132
+ }
2133
+ function overlapDecision(overlap, active) {
2134
+ if (overlap.mode === "skip")
2135
+ return active > 0 ? "skip" : "start";
2136
+ if (overlap.mode === "queue-one")
2137
+ return active > 0 ? "queue" : "start";
2138
+ return active >= overlap.maxConcurrent ? "skip" : "start";
2139
+ }
2140
+ function reportScheduleError(config, error, context) {
2141
+ if (!config.onError)
2142
+ return;
2143
+ Promise.resolve().then(() => config.onError?.(error, context)).catch(() => {});
2144
+ }
2145
+ async function waitForSettled(active, clock, context, deadlineAt) {
2146
+ if (active.size === 0 || context.signal.aborted)
2147
+ return;
2148
+ await new Promise((resolve) => {
2149
+ let settled = false;
2150
+ let deadlineTimer = null;
2151
+ const finish = () => {
2152
+ if (settled)
2153
+ return;
2154
+ settled = true;
2155
+ deadlineTimer?.cancel();
2156
+ context.signal.removeEventListener("abort", finish);
2157
+ resolve();
2158
+ };
2159
+ context.signal.addEventListener("abort", finish, { once: true });
2160
+ if (deadlineAt !== undefined) {
2161
+ deadlineTimer = clock.schedule(finish, Math.max(0, deadlineAt - context.now()));
2162
+ }
2163
+ Promise.allSettled([...active]).then(finish);
2164
+ });
2165
+ }
2166
+ async function executeRun(deps, scheduledAt, trigger) {
2167
+ const { config, descriptor, clock, counts, resourceContext } = deps;
2168
+ const startedAt = clock.now();
2169
+ const wallStartedAt = clock.wallNow().getTime();
2170
+ const runContext = {
2171
+ applicationId: resourceContext.applicationId,
2172
+ signal: resourceContext.signal,
2173
+ scheduledAt,
2174
+ startedAt,
2175
+ trigger,
2176
+ now: () => clock.now()
2177
+ };
2178
+ counts.runsStarted += 1;
2179
+ if (trigger === "wake")
2180
+ counts.runsWoken += 1;
2181
+ counts.lastTrigger = trigger;
2182
+ counts.lastScheduledAt = new Date(wallStartedAt + scheduledAt - startedAt).toISOString();
2183
+ counts.lastStartedAt = new Date(wallStartedAt).toISOString();
2184
+ deps.changed();
2185
+ try {
2186
+ await Promise.resolve();
2187
+ await config.run(runContext);
2188
+ } catch (error) {
2189
+ counts.runsFailed += 1;
2190
+ counts.lastFinishedAt = clock.wallNow().toISOString();
2191
+ reportScheduleError(config, error, runContext);
2192
+ if (descriptor.errorPolicy === "stop-schedule") {
2193
+ resourceContext.reportHealth("unhealthy");
2194
+ deps.stopAdmission();
2195
+ } else {
2196
+ resourceContext.reportHealth("degraded");
2197
+ }
2198
+ return;
2199
+ }
2200
+ counts.runsCompleted += 1;
2201
+ counts.lastFinishedAt = clock.wallNow().toISOString();
2202
+ if (descriptor.errorPolicy === "continue" && deps.isAccepting()) {
2203
+ resourceContext.reportHealth("healthy");
2204
+ }
2205
+ }
2206
+ function elapsedIntervals(scheduledAt, observedAt, everyMs) {
2207
+ return Math.max(1, Math.floor((observedAt - scheduledAt) / everyMs) + 1);
2208
+ }
2209
+
2210
+ // src/application/schedule.ts
2211
+ var systemClock2 = {
2212
+ now: () => performance.now(),
2213
+ wallNow: () => new Date,
2214
+ schedule(callback, delayMs) {
2215
+ const timer = setTimeout(callback, delayMs);
2216
+ return { cancel: () => clearTimeout(timer) };
2217
+ }
2218
+ };
2219
+ function createManagedSchedule(config) {
2220
+ const descriptor = describeSchedule(config);
2221
+ const dependsOn = config.dependsOn?.map((id) => ApplicationIdSchema2.parse(id));
2222
+ const clock = config.clock ?? systemClock2;
2223
+ let revision = 0;
2224
+ let accepting = false;
2225
+ let activated = false;
2226
+ let stopped = false;
2227
+ let timer = null;
2228
+ let activationContext = null;
2229
+ let nextRunAt = null;
2230
+ let queued = null;
2231
+ const counts = emptyCounts();
2232
+ let changedAt = clock.wallNow().toISOString();
2233
+ const active = new Set;
2234
+ const changed = () => {
2235
+ revision += 1;
2236
+ changedAt = clock.wallNow().toISOString();
2237
+ };
2238
+ const cancelFuture = () => {
2239
+ timer?.cancel();
2240
+ timer = null;
2241
+ nextRunAt = null;
2242
+ queued = null;
2243
+ };
2244
+ const stopAdmission = () => {
2245
+ if (!accepting && stopped)
2246
+ return;
2247
+ accepting = false;
2248
+ stopped = true;
2249
+ cancelFuture();
2250
+ changed();
2251
+ };
2252
+ const status = () => {
2253
+ const captured = clock.wallNow();
2254
+ const anchor = { monotonicNow: clock.now(), wallNow: captured.getTime() };
2255
+ return ManagedScheduleStatusSchema2.parse({
2256
+ descriptor,
2257
+ state: scheduleState(activated, stopped, accepting, active.size),
2258
+ revision,
2259
+ capturedAt: captured.toISOString(),
2260
+ changedAt,
2261
+ accepting,
2262
+ active: active.size,
2263
+ queued: queued !== null,
2264
+ ...counts,
2265
+ nextRunAt: wallAt(nextRunAt, anchor)
2266
+ });
2267
+ };
2268
+ let startExecution = () => {
2269
+ return;
2270
+ };
2271
+ const settleExecution = () => {
2272
+ if (!accepting || queued === null)
2273
+ return;
2274
+ if (overlapDecision(descriptor.overlap, active.size) !== "start")
2275
+ return;
2276
+ const successor = queued;
2277
+ queued = null;
2278
+ changed();
2279
+ startExecution(successor.at, successor.trigger);
2280
+ };
2281
+ startExecution = (scheduledAt, trigger) => {
2282
+ const resourceContext = activationContext;
2283
+ if (!accepting || !resourceContext)
2284
+ return;
2285
+ queued = null;
2286
+ const tracked = executeRun({
2287
+ config,
2288
+ descriptor,
2289
+ clock,
2290
+ counts,
2291
+ resourceContext,
2292
+ changed,
2293
+ stopAdmission,
2294
+ isAccepting: () => accepting
2295
+ }, scheduledAt, trigger).finally(() => {
2296
+ active.delete(tracked);
2297
+ changed();
2298
+ settleExecution();
2299
+ });
2300
+ active.add(tracked);
2301
+ };
2302
+ const dispatchTick = (scheduledAt) => {
2303
+ if (!accepting)
2304
+ return;
2305
+ const decision = overlapDecision(descriptor.overlap, active.size);
2306
+ if (decision === "start") {
2307
+ startExecution(scheduledAt, "timer");
2308
+ return;
2309
+ }
2310
+ if (decision === "queue")
2311
+ queued = { at: scheduledAt, trigger: queued?.trigger ?? "timer" };
2312
+ else
2313
+ counts.ticksSkipped += 1;
2314
+ changed();
2315
+ };
2316
+ const wake = () => {
2317
+ if (!accepting)
2318
+ return;
2319
+ if (queued) {
2320
+ counts.wakesCoalesced += 1;
2321
+ queued = { at: queued.at, trigger: "wake" };
2322
+ changed();
2323
+ return;
2324
+ }
2325
+ queued = { at: clock.now(), trigger: "wake" };
2326
+ changed();
2327
+ queueMicrotask(settleExecution);
2328
+ };
2329
+ const arm = () => {
2330
+ if (!accepting || nextRunAt === null)
2331
+ return;
2332
+ const delayMs = Math.max(0, nextRunAt - clock.now());
2333
+ timer = clock.schedule(() => {
2334
+ timer = null;
2335
+ if (!accepting || nextRunAt === null)
2336
+ return;
2337
+ const scheduledAt = nextRunAt;
2338
+ const elapsed = elapsedIntervals(scheduledAt, clock.now(), descriptor.everyMs);
2339
+ if (elapsed > 1) {
2340
+ counts.ticksSkipped += elapsed - 1;
2341
+ changed();
2342
+ }
2343
+ nextRunAt = scheduledAt + elapsed * descriptor.everyMs;
2344
+ arm();
2345
+ dispatchTick(scheduledAt);
2346
+ }, delayMs);
2347
+ };
2348
+ const waitForActive = (context, deadlineAt) => waitForSettled(active, clock, context, deadlineAt);
2349
+ const drain = async (context) => {
2350
+ stopAdmission();
2351
+ await waitForActive(context, context.deadlineAt);
2352
+ };
2353
+ return {
2354
+ id: descriptor.id,
2355
+ ...dependsOn && { dependsOn },
2356
+ ...config.required !== undefined && { required: config.required },
2357
+ get status() {
2358
+ return status();
2359
+ },
2360
+ wake,
2361
+ start() {
2362
+ if (active.size > 0) {
2363
+ throw new Error(`[stitchkit] schedule "${descriptor.id}" still has executions from its previous generation`);
2364
+ }
2365
+ cancelFuture();
2366
+ stopped = false;
2367
+ accepting = false;
2368
+ activated = false;
2369
+ activationContext = null;
2370
+ queued = null;
2371
+ changed();
2372
+ },
2373
+ activate(context) {
2374
+ if (activated || stopped)
2375
+ return;
2376
+ activated = true;
2377
+ accepting = true;
2378
+ activationContext = context;
2379
+ nextRunAt = clock.now() + descriptor.startAfterMs;
2380
+ context.reportHealth("healthy");
2381
+ changed();
2382
+ arm();
2383
+ },
2384
+ stopAdmission() {
2385
+ stopAdmission();
2386
+ },
2387
+ drain,
2388
+ close() {
2389
+ stopAdmission();
2390
+ },
2391
+ async force(context) {
2392
+ stopAdmission();
2393
+ await waitForActive(context, context.forceDeadlineAt);
2394
+ if (active.size > 0) {
2395
+ throw new Error(`[stitchkit] schedule "${descriptor.id}" still has active executions`);
2396
+ }
2397
+ }
2398
+ };
2399
+ }
2097
2400
  // src/application/server-resource.ts
2098
2401
  function managedServerResource(config) {
2099
2402
  let shutdownPromise;
@@ -2636,7 +2939,7 @@ export {
2636
2939
  createCreditWindow2 as createCreditWindow,
2637
2940
  createDecisionPipeline,
2638
2941
  createDiagnosticJournalReadResultSchema2 as createDiagnosticJournalReadResultSchema,
2639
- createManagedSchedule2 as createManagedSchedule,
2942
+ createManagedSchedule,
2640
2943
  createNotificationOutbox,
2641
2944
  createProcessLifecycleLedger,
2642
2945
  createRevisionSignal,
@@ -282,7 +282,7 @@ function createActivityProjection2(config) {
282
282
  };
283
283
  }
284
284
 
285
- // src/application/schedule.ts
285
+ // src/application/schedule-contract.ts
286
286
  import { z as z3 } from "zod";
287
287
  var NonNegativeSafeIntegerSchema = z3.number().int().nonnegative().refine(Number.isSafeInteger, "Expected a safe integer");
288
288
  var PositiveSafeIntegerSchema = NonNegativeSafeIntegerSchema.refine((value) => value > 0, "Expected a positive integer");
@@ -295,6 +295,7 @@ var ManagedScheduleOverlapSchema2 = z3.discriminatedUnion("mode", [
295
295
  }).readonly()
296
296
  ]);
297
297
  var ManagedScheduleErrorPolicySchema2 = z3.enum(["continue", "stop-schedule"]);
298
+ var ManagedScheduleTriggerSchema = z3.enum(["timer", "wake"]);
298
299
  var ManagedScheduleDescriptorSchema2 = z3.object({
299
300
  id: ApplicationIdSchema2,
300
301
  everyMs: PositiveSafeIntegerSchema,
@@ -314,282 +315,14 @@ var ManagedScheduleStatusSchema2 = z3.object({
314
315
  runsStarted: NonNegativeSafeIntegerSchema,
315
316
  runsCompleted: NonNegativeSafeIntegerSchema,
316
317
  runsFailed: NonNegativeSafeIntegerSchema,
318
+ runsWoken: NonNegativeSafeIntegerSchema,
317
319
  ticksSkipped: NonNegativeSafeIntegerSchema,
320
+ wakesCoalesced: NonNegativeSafeIntegerSchema,
321
+ lastTrigger: ManagedScheduleTriggerSchema.nullable(),
318
322
  nextRunAt: z3.string().datetime({ offset: true }).nullable(),
319
323
  lastScheduledAt: z3.string().datetime({ offset: true }).nullable(),
320
324
  lastStartedAt: z3.string().datetime({ offset: true }).nullable(),
321
325
  lastFinishedAt: z3.string().datetime({ offset: true }).nullable()
322
326
  }).readonly();
323
- var systemClock = {
324
- now: () => performance.now(),
325
- wallNow: () => new Date,
326
- schedule(callback, delayMs) {
327
- const timer = setTimeout(callback, delayMs);
328
- return { cancel: () => clearTimeout(timer) };
329
- }
330
- };
331
- var DEFAULT_OVERLAP = { mode: "skip" };
332
- function scheduleState(activated, stopped, accepting, active) {
333
- if (!activated)
334
- return stopped ? "stopped" : "inactive";
335
- if (!accepting)
336
- return active > 0 ? "draining" : "stopped";
337
- return active > 0 ? "running" : "scheduled";
338
- }
339
- function wallAt(monotonicAt, anchor) {
340
- if (monotonicAt === null)
341
- return null;
342
- return new Date(anchor.wallNow + monotonicAt - anchor.monotonicNow).toISOString();
343
- }
344
- function overlapDecision(overlap, active) {
345
- if (overlap.mode === "skip")
346
- return active > 0 ? "skip" : "start";
347
- if (overlap.mode === "queue-one")
348
- return active > 0 ? "queue" : "start";
349
- return active >= overlap.maxConcurrent ? "skip" : "start";
350
- }
351
- function reportScheduleError(config, error, context) {
352
- if (!config.onError)
353
- return;
354
- Promise.resolve().then(() => config.onError?.(error, context)).catch(() => {});
355
- }
356
- async function waitForSettled(active, clock, context, deadlineAt) {
357
- if (active.size === 0 || context.signal.aborted)
358
- return;
359
- await new Promise((resolve) => {
360
- let settled = false;
361
- let deadlineTimer = null;
362
- const finish = () => {
363
- if (settled)
364
- return;
365
- settled = true;
366
- deadlineTimer?.cancel();
367
- context.signal.removeEventListener("abort", finish);
368
- resolve();
369
- };
370
- context.signal.addEventListener("abort", finish, { once: true });
371
- if (deadlineAt !== undefined) {
372
- deadlineTimer = clock.schedule(finish, Math.max(0, deadlineAt - context.now()));
373
- }
374
- Promise.allSettled([...active]).then(finish);
375
- });
376
- }
377
- async function executeRun(deps, scheduledAt) {
378
- const { config, descriptor, clock, counts, resourceContext } = deps;
379
- const startedAt = clock.now();
380
- const wallStartedAt = clock.wallNow().getTime();
381
- const runContext = {
382
- applicationId: resourceContext.applicationId,
383
- signal: resourceContext.signal,
384
- scheduledAt,
385
- startedAt,
386
- now: () => clock.now()
387
- };
388
- counts.runsStarted += 1;
389
- counts.lastScheduledAt = new Date(wallStartedAt + scheduledAt - startedAt).toISOString();
390
- counts.lastStartedAt = new Date(wallStartedAt).toISOString();
391
- deps.changed();
392
- try {
393
- await Promise.resolve();
394
- await config.run(runContext);
395
- } catch (error) {
396
- counts.runsFailed += 1;
397
- counts.lastFinishedAt = clock.wallNow().toISOString();
398
- reportScheduleError(config, error, runContext);
399
- if (descriptor.errorPolicy === "stop-schedule") {
400
- resourceContext.reportHealth("unhealthy");
401
- deps.stopAdmission();
402
- } else {
403
- resourceContext.reportHealth("degraded");
404
- }
405
- return;
406
- }
407
- counts.runsCompleted += 1;
408
- counts.lastFinishedAt = clock.wallNow().toISOString();
409
- if (descriptor.errorPolicy === "continue" && deps.isAccepting()) {
410
- resourceContext.reportHealth("healthy");
411
- }
412
- }
413
- function elapsedIntervals(scheduledAt, observedAt, everyMs) {
414
- return Math.max(1, Math.floor((observedAt - scheduledAt) / everyMs) + 1);
415
- }
416
- function createManagedSchedule2(config) {
417
- const descriptor = ManagedScheduleDescriptorSchema2.parse({
418
- id: config.id,
419
- everyMs: config.everyMs,
420
- startAfterMs: config.startAfterMs ?? config.everyMs,
421
- overlap: config.overlap ?? DEFAULT_OVERLAP,
422
- errorPolicy: config.errorPolicy ?? "continue"
423
- });
424
- const dependsOn = config.dependsOn?.map((id) => ApplicationIdSchema2.parse(id));
425
- const clock = config.clock ?? systemClock;
426
- let revision = 0;
427
- let accepting = false;
428
- let activated = false;
429
- let stopped = false;
430
- let timer = null;
431
- let activationContext = null;
432
- let nextRunAt = null;
433
- let queuedAt = null;
434
- const counts = {
435
- runsStarted: 0,
436
- runsCompleted: 0,
437
- runsFailed: 0,
438
- ticksSkipped: 0,
439
- lastScheduledAt: null,
440
- lastStartedAt: null,
441
- lastFinishedAt: null
442
- };
443
- let changedAt = clock.wallNow().toISOString();
444
- const active = new Set;
445
- const changed = () => {
446
- revision += 1;
447
- changedAt = clock.wallNow().toISOString();
448
- };
449
- const cancelFuture = () => {
450
- timer?.cancel();
451
- timer = null;
452
- nextRunAt = null;
453
- queuedAt = null;
454
- };
455
- const stopAdmission = () => {
456
- if (!accepting && stopped)
457
- return;
458
- accepting = false;
459
- stopped = true;
460
- cancelFuture();
461
- changed();
462
- };
463
- const status = () => {
464
- const captured = clock.wallNow();
465
- const anchor = { monotonicNow: clock.now(), wallNow: captured.getTime() };
466
- return ManagedScheduleStatusSchema2.parse({
467
- descriptor,
468
- state: scheduleState(activated, stopped, accepting, active.size),
469
- revision,
470
- capturedAt: captured.toISOString(),
471
- changedAt,
472
- accepting,
473
- active: active.size,
474
- queued: queuedAt !== null,
475
- ...counts,
476
- nextRunAt: wallAt(nextRunAt, anchor)
477
- });
478
- };
479
- let startExecution = () => {
480
- return;
481
- };
482
- const settleExecution = () => {
483
- if (!accepting || queuedAt === null || active.size !== 0)
484
- return;
485
- const successorAt = queuedAt;
486
- queuedAt = null;
487
- changed();
488
- startExecution(successorAt);
489
- };
490
- startExecution = (scheduledAt) => {
491
- const resourceContext = activationContext;
492
- if (!accepting || !resourceContext)
493
- return;
494
- const tracked = executeRun({
495
- config,
496
- descriptor,
497
- clock,
498
- counts,
499
- resourceContext,
500
- changed,
501
- stopAdmission,
502
- isAccepting: () => accepting
503
- }, scheduledAt).finally(() => {
504
- active.delete(tracked);
505
- changed();
506
- settleExecution();
507
- });
508
- active.add(tracked);
509
- };
510
- const dispatchTick = (scheduledAt) => {
511
- if (!accepting)
512
- return;
513
- const decision = overlapDecision(descriptor.overlap, active.size);
514
- if (decision === "start") {
515
- startExecution(scheduledAt);
516
- return;
517
- }
518
- if (decision === "queue")
519
- queuedAt = scheduledAt;
520
- else
521
- counts.ticksSkipped += 1;
522
- changed();
523
- };
524
- const arm = () => {
525
- if (!accepting || nextRunAt === null)
526
- return;
527
- const delayMs = Math.max(0, nextRunAt - clock.now());
528
- timer = clock.schedule(() => {
529
- timer = null;
530
- if (!accepting || nextRunAt === null)
531
- return;
532
- const scheduledAt = nextRunAt;
533
- const elapsed = elapsedIntervals(scheduledAt, clock.now(), descriptor.everyMs);
534
- if (elapsed > 1) {
535
- counts.ticksSkipped += elapsed - 1;
536
- changed();
537
- }
538
- nextRunAt = scheduledAt + elapsed * descriptor.everyMs;
539
- arm();
540
- dispatchTick(scheduledAt);
541
- }, delayMs);
542
- };
543
- const waitForActive = (context, deadlineAt) => waitForSettled(active, clock, context, deadlineAt);
544
- const drain = async (context) => {
545
- stopAdmission();
546
- await waitForActive(context, context.deadlineAt);
547
- };
548
- return {
549
- id: descriptor.id,
550
- ...dependsOn && { dependsOn },
551
- ...config.required !== undefined && { required: config.required },
552
- get status() {
553
- return status();
554
- },
555
- start() {
556
- if (active.size > 0) {
557
- throw new Error(`[stitchkit] schedule "${descriptor.id}" still has executions from its previous generation`);
558
- }
559
- cancelFuture();
560
- stopped = false;
561
- accepting = false;
562
- activated = false;
563
- activationContext = null;
564
- queuedAt = null;
565
- changed();
566
- },
567
- activate(context) {
568
- if (activated || stopped)
569
- return;
570
- activated = true;
571
- accepting = true;
572
- activationContext = context;
573
- nextRunAt = clock.now() + descriptor.startAfterMs;
574
- context.reportHealth("healthy");
575
- changed();
576
- arm();
577
- },
578
- stopAdmission() {
579
- stopAdmission();
580
- },
581
- drain,
582
- close() {
583
- stopAdmission();
584
- },
585
- async force(context) {
586
- stopAdmission();
587
- await waitForActive(context, context.forceDeadlineAt);
588
- if (active.size > 0) {
589
- throw new Error(`[stitchkit] schedule "${descriptor.id}" still has active executions`);
590
- }
591
- }
592
- };
593
- }
594
327
 
595
- export { ApplicationSnapshotSinkStatusSchema2, createApplicationSnapshotSink2, ActivityIdSchema2, ActivityStageIdSchema2, ActivityStageSnapshotSchema2, ActivitySnapshotSchema2, ActivityLiveStateSchema2, ActivityTokenBrand2, createActivityProjection2, ManagedScheduleOverlapSchema2, ManagedScheduleErrorPolicySchema2, ManagedScheduleDescriptorSchema2, ManagedScheduleStatusSchema2, createManagedSchedule2 };
328
+ export { ApplicationSnapshotSinkStatusSchema2, createApplicationSnapshotSink2, ActivityIdSchema2, ActivityStageIdSchema2, ActivityStageSnapshotSchema2, ActivitySnapshotSchema2, ActivityLiveStateSchema2, ActivityTokenBrand2, createActivityProjection2, ManagedScheduleOverlapSchema2, ManagedScheduleErrorPolicySchema2, ManagedScheduleDescriptorSchema2, ManagedScheduleStatusSchema2 };
@@ -160,9 +160,12 @@ delivery. Its filesystem reader is in the diagnostic-journal leaf; there is no m
160
160
  | `ManagedScheduleStatusSchema` / `ManagedScheduleStatus` | schema / _type_ | absolute schedule state, revision, counters and timestamps |
161
161
 
162
162
  Schedule authoring additionally exports `ManagedSchedule`, `ManagedScheduleConfig`,
163
- `ManagedScheduleRunContext`, `ManagedScheduleClock` and `ManagedScheduleTimer`.
163
+ `ManagedScheduleRunContext`, `ManagedScheduleClock`, `ManagedScheduleTimer` and `ManagedScheduleTrigger`.
164
164
  The clock exposes monotonic cadence/deadline arithmetic and a wall-clock projection for portable
165
165
  status timestamps; it is a deterministic test boundary, not a durable scheduler.
166
+ A `ManagedSchedule` also has `wake()`: the owner of the event that creates work asks for one run now,
167
+ and the run follows the timer path (`overlap`, `errorPolicy`, `onError`, counters). Run context
168
+ carries `trigger` (`'timer'` or `'wake'`); status adds `runsWoken`, `wakesCoalesced` and `lastTrigger`.
166
169
 
167
170
  ### Application and activity projection
168
171
 
@@ -349,7 +349,7 @@ Every instrument uses unit `1` and reports an absolute current/lifetime value:
349
349
  | `stitchkit.application.lifecycle`, `.ready` | current lifecycle/health fact and readiness |
350
350
  | `stitchkit.application.admission.accepting`, `.accepted`, `.completed`, `.pending` | current gate and absolute lifetime admission counts |
351
351
  | `stitchkit.application.resource.ready` | readiness for each declared resource with required/state/health attributes |
352
- | `stitchkit.application.schedule.accepting`, `.active`, `.queued`, `.runs_started`, `.runs_completed`, `.runs_failed`, `.ticks_skipped` | current schedule state and absolute run/tick counts |
352
+ | `stitchkit.application.schedule.accepting`, `.active`, `.queued`, `.runs_started`, `.runs_completed`, `.runs_failed`, `.runs_woken`, `.wakes_coalesced`, `.ticks_skipped` | current schedule state and absolute run, wake and tick counts |
353
353
  | `stitchkit.application.activity.active`, `.queued`, `.completed`, `.failed` | absolute stage projections for declared activity sources |
354
354
 
355
355
  ## Replacing part of the graph without stopping the process
@@ -783,6 +783,35 @@ those semantics in a durable application scheduler when they are required.
783
783
  Schedule cadence stays monotonic, while status snapshots expose ISO wall-clock
784
784
  `capturedAt`, `changedAt` and next/last-run timestamps for portable observation.
785
785
 
786
+ ### Wake a schedule when work appears
787
+
788
+ An owner that knows the moment work arrives keeps a long period as the check for a lost event and
789
+ calls `wake()` from the place that enqueues:
790
+
791
+ ```ts
792
+ const drain = createManagedSchedule({
793
+ id: 'drain-queue',
794
+ everyMs: 60_000,
795
+ run: ({ trigger, signal }) => drainQueue(signal, trigger),
796
+ })
797
+
798
+ function enqueue(job: Job) {
799
+ queue.push(job)
800
+ drain.wake()
801
+ }
802
+ ```
803
+
804
+ - `wake()` asks for one run now and takes the timer's path: `dependsOn`, `overlap`, `errorPolicy`,
805
+ `onError`, the shutdown signal and the counters all apply.
806
+ - Calls made in one tick, or while a run holds every slot, collapse into one following run, under
807
+ every overlap policy (a wake is an event, so `skip` defers it instead of dropping it).
808
+ - Before the schedule is activated (its dependencies are not ready) and after it stops accepting
809
+ (shutdown, `stop-schedule`), `wake()` does nothing and is not remembered.
810
+ - The period keeps its own fixed-rate grid and is not moved by a wake, so it stays a single timer
811
+ chain and never becomes a second queue.
812
+ - `run` receives `trigger` (`'timer'` or `'wake'`); status reports `runsWoken`, `wakesCoalesced` and
813
+ `lastTrigger`.
814
+
786
815
  ## Operational projection
787
816
 
788
817
  Declare aggregate activity stages, then update them with anonymous handles:
package/llms-full.txt CHANGED
@@ -7228,7 +7228,7 @@ Every instrument uses unit `1` and reports an absolute current/lifetime value:
7228
7228
  | `stitchkit.application.lifecycle`, `.ready` | current lifecycle/health fact and readiness |
7229
7229
  | `stitchkit.application.admission.accepting`, `.accepted`, `.completed`, `.pending` | current gate and absolute lifetime admission counts |
7230
7230
  | `stitchkit.application.resource.ready` | readiness for each declared resource with required/state/health attributes |
7231
- | `stitchkit.application.schedule.accepting`, `.active`, `.queued`, `.runs_started`, `.runs_completed`, `.runs_failed`, `.ticks_skipped` | current schedule state and absolute run/tick counts |
7231
+ | `stitchkit.application.schedule.accepting`, `.active`, `.queued`, `.runs_started`, `.runs_completed`, `.runs_failed`, `.runs_woken`, `.wakes_coalesced`, `.ticks_skipped` | current schedule state and absolute run, wake and tick counts |
7232
7232
  | `stitchkit.application.activity.active`, `.queued`, `.completed`, `.failed` | absolute stage projections for declared activity sources |
7233
7233
 
7234
7234
  ## Replacing part of the graph without stopping the process
@@ -7662,6 +7662,35 @@ those semantics in a durable application scheduler when they are required.
7662
7662
  Schedule cadence stays monotonic, while status snapshots expose ISO wall-clock
7663
7663
  `capturedAt`, `changedAt` and next/last-run timestamps for portable observation.
7664
7664
 
7665
+ ### Wake a schedule when work appears
7666
+
7667
+ An owner that knows the moment work arrives keeps a long period as the check for a lost event and
7668
+ calls `wake()` from the place that enqueues:
7669
+
7670
+ ```ts
7671
+ const drain = createManagedSchedule({
7672
+ id: 'drain-queue',
7673
+ everyMs: 60_000,
7674
+ run: ({ trigger, signal }) => drainQueue(signal, trigger),
7675
+ })
7676
+
7677
+ function enqueue(job: Job) {
7678
+ queue.push(job)
7679
+ drain.wake()
7680
+ }
7681
+ ```
7682
+
7683
+ - `wake()` asks for one run now and takes the timer's path: `dependsOn`, `overlap`, `errorPolicy`,
7684
+ `onError`, the shutdown signal and the counters all apply.
7685
+ - Calls made in one tick, or while a run holds every slot, collapse into one following run, under
7686
+ every overlap policy (a wake is an event, so `skip` defers it instead of dropping it).
7687
+ - Before the schedule is activated (its dependencies are not ready) and after it stops accepting
7688
+ (shutdown, `stop-schedule`), `wake()` does nothing and is not remembered.
7689
+ - The period keeps its own fixed-rate grid and is not moved by a wake, so it stays a single timer
7690
+ chain and never becomes a second queue.
7691
+ - `run` receives `trigger` (`'timer'` or `'wake'`); status reports `runsWoken`, `wakesCoalesced` and
7692
+ `lastTrigger`.
7693
+
7665
7694
  ## Operational projection
7666
7695
 
7667
7696
  Declare aggregate activity stages, then update them with anonymous handles:
@@ -21430,9 +21459,12 @@ delivery. Its filesystem reader is in the diagnostic-journal leaf; there is no m
21430
21459
  | `ManagedScheduleStatusSchema` / `ManagedScheduleStatus` | schema / _type_ | absolute schedule state, revision, counters and timestamps |
21431
21460
 
21432
21461
  Schedule authoring additionally exports `ManagedSchedule`, `ManagedScheduleConfig`,
21433
- `ManagedScheduleRunContext`, `ManagedScheduleClock` and `ManagedScheduleTimer`.
21462
+ `ManagedScheduleRunContext`, `ManagedScheduleClock`, `ManagedScheduleTimer` and `ManagedScheduleTrigger`.
21434
21463
  The clock exposes monotonic cadence/deadline arithmetic and a wall-clock projection for portable
21435
21464
  status timestamps; it is a deterministic test boundary, not a durable scheduler.
21465
+ A `ManagedSchedule` also has `wake()`: the owner of the event that creates work asks for one run now,
21466
+ and the run follows the timer path (`overlap`, `errorPolicy`, `onError`, counters). Run context
21467
+ carries `trigger` (`'timer'` or `'wake'`); status adds `runsWoken`, `wakesCoalesced` and `lastTrigger`.
21436
21468
 
21437
21469
  ### Application and activity projection
21438
21470
 
package/llms.txt CHANGED
@@ -33,7 +33,7 @@ Load the slice for each entrypoint your code imports — `import … from 'stitc
33
33
  - **stitchkit/agent-runtime/openrouter**: [llms/agent-runtime-openrouter.txt](llms/agent-runtime-openrouter.txt) 1.1 KB
34
34
  - **stitchkit/agent-runtime/sqlite/bun**: [llms/agent-runtime-sqlite-bun.txt](llms/agent-runtime-sqlite-bun.txt) 1.8 KB
35
35
  - **stitchkit/agent-runtime/sqlite/node**: [llms/agent-runtime-sqlite-node.txt](llms/agent-runtime-sqlite-node.txt) 1.7 KB
36
- - **stitchkit/application**: [llms/application.txt](llms/application.txt) 39.6 KB → [llms/application.2.txt](llms/application.2.txt) 30.7 KB → [llms/application.3.txt](llms/application.3.txt) 29.0 KB
36
+ - **stitchkit/application**: [llms/application.txt](llms/application.txt) 40.8 KB → [llms/application.2.txt](llms/application.2.txt) 30.7 KB → [llms/application.3.txt](llms/application.3.txt) 29.4 KB
37
37
  - **stitchkit/application/grammy**: [llms/application-grammy.txt](llms/application-grammy.txt) 2.3 KB
38
38
  - **stitchkit/application/opentelemetry**: [llms/application-opentelemetry.txt](llms/application-opentelemetry.txt) 1.6 KB
39
39
  - **stitchkit/application/directory-inbox**: [llms/application-directory-inbox.txt](llms/application-directory-inbox.txt) 0.3 KB
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.109.1",
3
+ "version": "0.109.3",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",