@orkestrel/workflow 0.0.16 → 0.0.18

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/README.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # @orkestrel/workflow
2
2
 
3
- A typed, host-independent workflow engine for the `@orkestrel` line. It keeps
4
- work as a serializable `Workflow Phase Task` tree and executes task behavior
5
- through a caller-supplied function registry on a cooperative scheduler.
3
+ > Orchestration as data: a JSON-serializable `Workflow Phase Task` tree that a UI or an
4
+ > LLM authors, a store persists, and a thin engine drives by composing the shipped execution
5
+ > substrate.
6
+
7
+ Author the definition as plain JSON, register the functions its tasks name, and
8
+ hand both to the runner: it builds the live tree, runs each phase in turn with
9
+ that phase's tasks concurrent, and resolves the settled result. Host-independent,
10
+ with browser-native and Node-native scheduler backends beside the default. Part
11
+ of the `@orkestrel` line.
6
12
 
7
13
  ## Install
8
14
 
@@ -33,13 +39,13 @@ attempt. Runtime pause gates are intentionally not persisted.
33
39
 
34
40
  Provider sessions, external processes, MCP projection, journals, leases, and
35
41
  distributed fencing remain integration concerns rather than core workflow
36
- behavior. See [guides/src/workflow.md](./guides/src/workflow.md) for the complete
37
- shipped contract. The proposed integration architecture now lives with the
42
+ behavior. See [guides/workflow.md](./guides/workflow.md) for the complete
43
+ shipped contract. The proposed integration architecture lives with the
38
44
  package that implements it, as `plan/PROPOSAL.md` in `@orkestrel/supervisor`.
39
45
 
40
46
  ## Package
41
47
 
42
- Published as three environment-scoped entry points: `.` provides the shared
48
+ Published as environment-scoped entry points: `.` provides the shared
43
49
  environment-agnostic core and default scheduler, `./browser` adds browser-native
44
50
  schedulers, and `./server` adds the Node-native scheduler. Core ships dual
45
51
  ESM+CJS builds; `./browser` is ESM-only.
@@ -1,11 +1,12 @@
1
- import { SchedulerInterface } from '@orkestrel/workflow';
2
- import { SchedulerOptions } from '@orkestrel/workflow';
3
- import { SchedulerPriority } from '@orkestrel/workflow';
1
+ import type { SchedulerInterface } from '@orkestrel/workflow';
2
+ import type { SchedulerOptions } from '@orkestrel/workflow';
3
+ import type { SchedulerPriority } from '@orkestrel/workflow';
4
4
 
5
5
  /**
6
- * The browser {@link SchedulerInterface} — the browser-native cooperative-yield backend
7
- * built on the Prioritized Task Scheduling API (`scheduler.postTask`), falling back to a
8
- * zero-delay macrotask where it is absent.
6
+ * Implements the browser {@link SchedulerInterface} — the browser-native cooperative-yield backend
7
+ * built on the Prioritized Task Scheduling API (`scheduler.postTask`) at the mapped priority,
8
+ * falling back to a zero-delay macrotask where it is absent, and rejecting an aborted wait
9
+ * with the caller's own reason.
9
10
  *
10
11
  * @remarks
11
12
  * - **`yield` prefers `scheduler.postTask`, honouring priority.** When `globalThis`
@@ -13,12 +14,12 @@ import { SchedulerPriority } from '@orkestrel/workflow';
13
14
  * priority (`user` → `'user-blocking'`, `normal` → `'user-visible'`, `background` →
14
15
  * `'background'`), so the host genuinely regains control and the urgency hint is
15
16
  * honoured. The capability is feature-detected through guards (`isRecord` / `isFunction`),
16
- * never an `as` (AGENTS §14). Where the API is absent (Firefox today, older engines),
17
- * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, just
18
- * without priority. `delay(ms)` is always a real `setTimeout`.
17
+ * never an `as`. Where the API is absent (Firefox today, older engines),
18
+ * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, without
19
+ * priority. `delay(ms)` is always a real `setTimeout`.
19
20
  * - **Abort fidelity is verbatim.** The shared `scheduleHost` lifecycle links an owned
20
21
  * settlement composite before scheduling, preserving the exact caller reason without
21
- * invoking caller-owned signal methods. The caller signal is NOT handed to `postTask`;
22
+ * invoking caller-owned signal methods. The caller signal is not handed to `postTask`;
22
23
  * an internal controller cancels that native task. An unexpected native promise rejection
23
24
  * is routed back as the exact host failure instead of being discarded.
24
25
  * - **Event-free.** A pure functional primitive — no Emitter, no events.
@@ -39,26 +40,25 @@ import { SchedulerPriority } from '@orkestrel/workflow';
39
40
  export declare class BrowserScheduler implements SchedulerInterface {
40
41
  #private;
41
42
  /**
42
- * Yield control to the host via `scheduler.postTask` at the given priority (or a
43
- * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with
43
+ * Yields control to the host through `scheduler.postTask` at the given priority (or a
44
+ * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with
44
45
  * `signal.reason`.
45
46
  */
46
47
  yield(options?: SchedulerOptions): Promise<void>;
47
48
  /**
48
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
49
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
49
50
  * `signal.reason`.
50
51
  *
51
52
  * @remarks
52
- * `ms` should be a non-negative finite number. The primitive does no validation: it
53
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
54
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
55
- * throwing.
53
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
54
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
55
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
56
56
  */
57
57
  delay(ms: number, options?: SchedulerOptions): Promise<void>;
58
58
  }
59
59
 
60
60
  /**
61
- * Create the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses
61
+ * Creates the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses
62
62
  * the Prioritized Task Scheduling API (`scheduler.postTask`) at the requested priority
63
63
  * when present, falling back to a `setTimeout(0)` macrotask; `delay(ms)` is a real
64
64
  * `setTimeout`.
@@ -85,13 +85,13 @@ export declare class BrowserScheduler implements SchedulerInterface {
85
85
  export declare function createBrowserScheduler(): SchedulerInterface;
86
86
 
87
87
  /**
88
- * Create the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes
89
- * just before the next paint via `requestAnimationFrame`; `delay(ms)` is a real
88
+ * Creates the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes
89
+ * before the next paint through `requestAnimationFrame`; `delay(ms)` is a real
90
90
  * `setTimeout`.
91
91
  *
92
92
  * @remarks
93
- * Use it for work that should batch per render frame (animation, incremental DOM updates)
94
- * and naturally pause while the tab is hidden. `yield` is abort-aware: pass `options.signal`
93
+ * Use it for work that batches per render frame (animation, incremental DOM updates) and
94
+ * naturally pauses while the tab is hidden. `yield` is abort-aware: pass `options.signal`
95
95
  * and a pending yield rejects with the signal's `reason` verbatim, cancelling the pending
96
96
  * frame request. `options.priority` is accepted but a no-op — a frame callback has no
97
97
  * priority dimension.
@@ -109,8 +109,8 @@ export declare function createBrowserScheduler(): SchedulerInterface;
109
109
  export declare function createFrameScheduler(): SchedulerInterface;
110
110
 
111
111
  /**
112
- * Create the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when
113
- * the host is idle via `requestIdleCallback` when present, falling back to a `setTimeout(0)`
112
+ * Creates the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when
113
+ * the host is idle through `requestIdleCallback` when present, falling back to a `setTimeout(0)`
114
114
  * macrotask; `delay(ms)` is a real `setTimeout`.
115
115
  *
116
116
  * @remarks
@@ -133,14 +133,15 @@ export declare function createFrameScheduler(): SchedulerInterface;
133
133
  export declare function createIdleScheduler(): SchedulerInterface;
134
134
 
135
135
  /**
136
- * The frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend
137
- * whose `yield` resumes just before the next paint via `requestAnimationFrame`.
136
+ * Implements the frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend
137
+ * whose `yield` resumes before the next paint through `requestAnimationFrame`, rejecting an
138
+ * aborted wait with the caller's own reason. A `priority` hint is accepted and does nothing.
138
139
  *
139
140
  * @remarks
140
141
  * - **`yield` resumes before the next paint.** `yield()` waits on `requestAnimationFrame`,
141
142
  * so the resumption is aligned to the browser's render loop — ideal for work that
142
- * should batch per frame (animation, incremental DOM updates) and pause while the tab
143
- * is hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to
143
+ * batches per frame (animation, incremental DOM updates) and pauses while the tab is
144
+ * hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to
144
145
  * frames. `options.priority` is accepted for contract compliance but a no-op — a frame
145
146
  * callback has no priority dimension.
146
147
  * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links
@@ -164,50 +165,50 @@ export declare function createIdleScheduler(): SchedulerInterface;
164
165
  export declare class FrameScheduler implements SchedulerInterface {
165
166
  #private;
166
167
  /**
167
- * Yield control to the host until just before the next paint via
168
- * `requestAnimationFrame`, then resume; abort rejects with `signal.reason`.
168
+ * Yields control to the host until the moment before the next paint through
169
+ * `requestAnimationFrame`, then resumes; abort rejects with `signal.reason`.
169
170
  */
170
171
  yield(options?: SchedulerOptions): Promise<void>;
171
172
  /**
172
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
173
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
173
174
  * `signal.reason`.
174
175
  *
175
176
  * @remarks
176
- * `ms` should be a non-negative finite number. The primitive does no validation: it
177
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
178
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
179
- * throwing.
177
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
178
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
179
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
180
180
  */
181
181
  delay(ms: number, options?: SchedulerOptions): Promise<void>;
182
182
  }
183
183
 
184
184
  /**
185
- * The narrowed `requestIdleCallback` / `cancelIdleCallback` pair feature-detected off
185
+ * Declares the narrowed `requestIdleCallback` / `cancelIdleCallback` pair feature-detected off
186
186
  * `globalThis`.
187
187
  *
188
188
  * @remarks
189
189
  * A `request` taking a callback and returning a numeric handle, and a `cancel` taking that
190
190
  * handle. {@link IdleScheduler} feature-detects the pair through a guard (`isFunction`,
191
- * never an `as` — AGENTS §14) and resolves to `undefined` when the API is absent (Safari
191
+ * never an `as`) and resolves to `undefined` when the API is absent (Safari
192
192
  * today), so `yield` falls back to a macrotask.
193
193
  */
194
- export declare interface IdleAPI {
194
+ export declare interface IdleInterface {
195
195
  readonly request: (callback: () => void) => number;
196
196
  readonly cancel: (handle: number) => void;
197
197
  }
198
198
 
199
199
  /**
200
- * The idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose
201
- * `yield` resumes when the host is idle via `requestIdleCallback`, falling back to a
202
- * zero-delay macrotask where it is absent.
200
+ * Implements the idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose
201
+ * `yield` resumes when the host is idle through `requestIdleCallback`, falling back to a
202
+ * zero-delay macrotask where it is absent, and rejecting an aborted wait with the caller's own
203
+ * reason. A `priority` hint is accepted and does nothing.
203
204
  *
204
205
  * @remarks
205
206
  * - **`yield` resumes during idle time.** When `globalThis` exposes `requestIdleCallback`,
206
207
  * `yield()` waits on it, so the resumption happens when the browser has spare time after
207
208
  * rendering and input — ideal for low-priority background work that must not contend with
208
209
  * the user. The capability is feature-detected through a guard (`isFunction`), never an
209
- * `as` (AGENTS §14). Where the API is absent (Safari today), it **falls back** to a
210
- * `setTimeout(0)` macrotask — still a real host-turn, just not idle-gated. `delay(ms)` is
210
+ * `as`. Where the API is absent (Safari today), it **falls back** to a
211
+ * `setTimeout(0)` macrotask — still a real host-turn, not idle-gated. `delay(ms)` is
211
212
  * always a real `setTimeout`. `options.priority` is accepted for contract compliance but a
212
213
  * no-op — idle scheduling has no priority dimension.
213
214
  * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links
@@ -231,27 +232,27 @@ export declare interface IdleAPI {
231
232
  export declare class IdleScheduler implements SchedulerInterface {
232
233
  #private;
233
234
  /**
234
- * Yield control to the host until it is idle via `requestIdleCallback` (or a
235
- * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with
235
+ * Yields control to the host until it is idle through `requestIdleCallback` (or a
236
+ * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with
236
237
  * `signal.reason`.
237
238
  */
238
239
  yield(options?: SchedulerOptions): Promise<void>;
239
240
  /**
240
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
241
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
241
242
  * `signal.reason`.
242
243
  *
243
244
  * @remarks
244
- * `ms` should be a non-negative finite number. The primitive does no validation: it
245
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
246
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
247
- * throwing.
245
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
246
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
247
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
248
248
  */
249
249
  delay(ms: number, options?: SchedulerOptions): Promise<void>;
250
250
  }
251
251
 
252
252
  /**
253
- * The browser-native `postTask` priority for each portable {@link SchedulerPriority} the
254
- * Prioritized Task Scheduling API's three levels.
253
+ * Maps each portable {@link SchedulerPriority} to the browser-native `postTask` priority —
254
+ * `user` to `'user-blocking'`, `normal` to `'user-visible'`, and `background` to
255
+ * `'background'`.
255
256
  *
256
257
  * @remarks
257
258
  * A `user` hint maps to the most urgent `'user-blocking'`, `normal` to the default
@@ -1,9 +1,10 @@
1
- import { scheduleHost } from "../core/index.js";
1
+ import { delayHost, scheduleHost } from "../core/index.js";
2
2
  import { isFunction, isPromise, isRecord } from "@orkestrel/contract";
3
3
  //#region src/browser/constants.ts
4
4
  /**
5
- * The browser-native `postTask` priority for each portable {@link SchedulerPriority} the
6
- * Prioritized Task Scheduling API's three levels.
5
+ * Maps each portable {@link SchedulerPriority} to the browser-native `postTask` priority —
6
+ * `user` to `'user-blocking'`, `normal` to `'user-visible'`, and `background` to
7
+ * `'background'`.
7
8
  *
8
9
  * @remarks
9
10
  * A `user` hint maps to the most urgent `'user-blocking'`, `normal` to the default
@@ -19,9 +20,10 @@ var POST_TASK_PRIORITY = Object.freeze({
19
20
  //#endregion
20
21
  //#region src/browser/BrowserScheduler.ts
21
22
  /**
22
- * The browser {@link SchedulerInterface} — the browser-native cooperative-yield backend
23
- * built on the Prioritized Task Scheduling API (`scheduler.postTask`), falling back to a
24
- * zero-delay macrotask where it is absent.
23
+ * Implements the browser {@link SchedulerInterface} — the browser-native cooperative-yield backend
24
+ * built on the Prioritized Task Scheduling API (`scheduler.postTask`) at the mapped priority,
25
+ * falling back to a zero-delay macrotask where it is absent, and rejecting an aborted wait
26
+ * with the caller's own reason.
25
27
  *
26
28
  * @remarks
27
29
  * - **`yield` prefers `scheduler.postTask`, honouring priority.** When `globalThis`
@@ -29,12 +31,12 @@ var POST_TASK_PRIORITY = Object.freeze({
29
31
  * priority (`user` → `'user-blocking'`, `normal` → `'user-visible'`, `background` →
30
32
  * `'background'`), so the host genuinely regains control and the urgency hint is
31
33
  * honoured. The capability is feature-detected through guards (`isRecord` / `isFunction`),
32
- * never an `as` (AGENTS §14). Where the API is absent (Firefox today, older engines),
33
- * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, just
34
- * without priority. `delay(ms)` is always a real `setTimeout`.
34
+ * never an `as`. Where the API is absent (Firefox today, older engines),
35
+ * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, without
36
+ * priority. `delay(ms)` is always a real `setTimeout`.
35
37
  * - **Abort fidelity is verbatim.** The shared `scheduleHost` lifecycle links an owned
36
38
  * settlement composite before scheduling, preserving the exact caller reason without
37
- * invoking caller-owned signal methods. The caller signal is NOT handed to `postTask`;
39
+ * invoking caller-owned signal methods. The caller signal is not handed to `postTask`;
38
40
  * an internal controller cancels that native task. An unexpected native promise rejection
39
41
  * is routed back as the exact host failure instead of being discarded.
40
42
  * - **Event-free.** A pure functional primitive — no Emitter, no events.
@@ -54,27 +56,26 @@ var POST_TASK_PRIORITY = Object.freeze({
54
56
  */
55
57
  var BrowserScheduler = class {
56
58
  /**
57
- * Yield control to the host via `scheduler.postTask` at the given priority (or a
58
- * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with
59
+ * Yields control to the host through `scheduler.postTask` at the given priority (or a
60
+ * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with
59
61
  * `signal.reason`.
60
62
  */
61
63
  yield(options) {
62
64
  const post = this.#postTask();
63
- if (post === void 0) return this.#timer(0, options?.signal);
65
+ if (post === void 0) return delayHost(0, options?.signal);
64
66
  return this.#yieldVia(post, options?.priority ?? "normal", options?.signal);
65
67
  }
66
68
  /**
67
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
69
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
68
70
  * `signal.reason`.
69
71
  *
70
72
  * @remarks
71
- * `ms` should be a non-negative finite number. The primitive does no validation: it
72
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
73
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
74
- * throwing.
73
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
74
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
75
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
75
76
  */
76
77
  delay(ms, options) {
77
- return this.#timer(ms, options?.signal);
78
+ return delayHost(ms, options?.signal);
78
79
  }
79
80
  #postTask() {
80
81
  const candidate = Reflect.get(globalThis, "scheduler");
@@ -94,24 +95,19 @@ var BrowserScheduler = class {
94
95
  return () => internal.abort();
95
96
  }, signal);
96
97
  }
97
- #timer(ms, signal) {
98
- return scheduleHost((complete) => {
99
- const handle = setTimeout(complete, ms);
100
- return () => clearTimeout(handle);
101
- }, signal);
102
- }
103
98
  };
104
99
  //#endregion
105
100
  //#region src/browser/FrameScheduler.ts
106
101
  /**
107
- * The frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend
108
- * whose `yield` resumes just before the next paint via `requestAnimationFrame`.
102
+ * Implements the frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend
103
+ * whose `yield` resumes before the next paint through `requestAnimationFrame`, rejecting an
104
+ * aborted wait with the caller's own reason. A `priority` hint is accepted and does nothing.
109
105
  *
110
106
  * @remarks
111
107
  * - **`yield` resumes before the next paint.** `yield()` waits on `requestAnimationFrame`,
112
108
  * so the resumption is aligned to the browser's render loop — ideal for work that
113
- * should batch per frame (animation, incremental DOM updates) and pause while the tab
114
- * is hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to
109
+ * batches per frame (animation, incremental DOM updates) and pauses while the tab is
110
+ * hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to
115
111
  * frames. `options.priority` is accepted for contract compliance but a no-op — a frame
116
112
  * callback has no priority dimension.
117
113
  * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links
@@ -134,24 +130,23 @@ var BrowserScheduler = class {
134
130
  */
135
131
  var FrameScheduler = class {
136
132
  /**
137
- * Yield control to the host until just before the next paint via
138
- * `requestAnimationFrame`, then resume; abort rejects with `signal.reason`.
133
+ * Yields control to the host until the moment before the next paint through
134
+ * `requestAnimationFrame`, then resumes; abort rejects with `signal.reason`.
139
135
  */
140
136
  yield(options) {
141
137
  return this.#frame(options?.signal);
142
138
  }
143
139
  /**
144
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
140
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
145
141
  * `signal.reason`.
146
142
  *
147
143
  * @remarks
148
- * `ms` should be a non-negative finite number. The primitive does no validation: it
149
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
150
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
151
- * throwing.
144
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
145
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
146
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
152
147
  */
153
148
  delay(ms, options) {
154
- return this.#sleep(ms, options?.signal);
149
+ return delayHost(ms, options?.signal);
155
150
  }
156
151
  #frame(signal) {
157
152
  return scheduleHost((complete) => {
@@ -159,27 +154,22 @@ var FrameScheduler = class {
159
154
  return () => cancelAnimationFrame(handle);
160
155
  }, signal);
161
156
  }
162
- #sleep(ms, signal) {
163
- return scheduleHost((complete) => {
164
- const handle = setTimeout(complete, ms);
165
- return () => clearTimeout(handle);
166
- }, signal);
167
- }
168
157
  };
169
158
  //#endregion
170
159
  //#region src/browser/IdleScheduler.ts
171
160
  /**
172
- * The idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose
173
- * `yield` resumes when the host is idle via `requestIdleCallback`, falling back to a
174
- * zero-delay macrotask where it is absent.
161
+ * Implements the idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose
162
+ * `yield` resumes when the host is idle through `requestIdleCallback`, falling back to a
163
+ * zero-delay macrotask where it is absent, and rejecting an aborted wait with the caller's own
164
+ * reason. A `priority` hint is accepted and does nothing.
175
165
  *
176
166
  * @remarks
177
167
  * - **`yield` resumes during idle time.** When `globalThis` exposes `requestIdleCallback`,
178
168
  * `yield()` waits on it, so the resumption happens when the browser has spare time after
179
169
  * rendering and input — ideal for low-priority background work that must not contend with
180
170
  * the user. The capability is feature-detected through a guard (`isFunction`), never an
181
- * `as` (AGENTS §14). Where the API is absent (Safari today), it **falls back** to a
182
- * `setTimeout(0)` macrotask — still a real host-turn, just not idle-gated. `delay(ms)` is
171
+ * `as`. Where the API is absent (Safari today), it **falls back** to a
172
+ * `setTimeout(0)` macrotask — still a real host-turn, not idle-gated. `delay(ms)` is
183
173
  * always a real `setTimeout`. `options.priority` is accepted for contract compliance but a
184
174
  * no-op — idle scheduling has no priority dimension.
185
175
  * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links
@@ -202,29 +192,28 @@ var FrameScheduler = class {
202
192
  */
203
193
  var IdleScheduler = class {
204
194
  /**
205
- * Yield control to the host until it is idle via `requestIdleCallback` (or a
206
- * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with
195
+ * Yields control to the host until it is idle through `requestIdleCallback` (or a
196
+ * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with
207
197
  * `signal.reason`.
208
198
  */
209
199
  yield(options) {
210
- const idle = this.#idleAPI();
211
- if (idle === void 0) return this.#sleep(0, options?.signal);
200
+ const idle = this.#idleCallback();
201
+ if (idle === void 0) return delayHost(0, options?.signal);
212
202
  return this.#idle(idle, options?.signal);
213
203
  }
214
204
  /**
215
- * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with
205
+ * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with
216
206
  * `signal.reason`.
217
207
  *
218
208
  * @remarks
219
- * `ms` should be a non-negative finite number. The primitive does no validation: it
220
- * passes `ms` straight to the host `setTimeout`, which clamps a negative value or
221
- * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than
222
- * throwing.
209
+ * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`
210
+ * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an
211
+ * out-of-domain `ms` resolves on the next host turn rather than throwing.
223
212
  */
224
213
  delay(ms, options) {
225
- return this.#sleep(ms, options?.signal);
214
+ return delayHost(ms, options?.signal);
226
215
  }
227
- #idleAPI() {
216
+ #idleCallback() {
228
217
  const request = Reflect.get(globalThis, "requestIdleCallback");
229
218
  const cancel = Reflect.get(globalThis, "cancelIdleCallback");
230
219
  if (!isFunction(request) || !isFunction(cancel)) return void 0;
@@ -239,12 +228,6 @@ var IdleScheduler = class {
239
228
  return () => idle.cancel(handle);
240
229
  }, signal);
241
230
  }
242
- #sleep(ms, signal) {
243
- return scheduleHost((complete) => {
244
- const handle = setTimeout(complete, ms);
245
- return () => clearTimeout(handle);
246
- }, signal);
247
- }
248
231
  #request(request, callback) {
249
232
  return Number(Reflect.apply(request, globalThis, [callback]));
250
233
  }
@@ -255,7 +238,7 @@ var IdleScheduler = class {
255
238
  //#endregion
256
239
  //#region src/browser/factories.ts
257
240
  /**
258
- * Create the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses
241
+ * Creates the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses
259
242
  * the Prioritized Task Scheduling API (`scheduler.postTask`) at the requested priority
260
243
  * when present, falling back to a `setTimeout(0)` macrotask; `delay(ms)` is a real
261
244
  * `setTimeout`.
@@ -283,13 +266,13 @@ function createBrowserScheduler() {
283
266
  return new BrowserScheduler();
284
267
  }
285
268
  /**
286
- * Create the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes
287
- * just before the next paint via `requestAnimationFrame`; `delay(ms)` is a real
269
+ * Creates the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes
270
+ * before the next paint through `requestAnimationFrame`; `delay(ms)` is a real
288
271
  * `setTimeout`.
289
272
  *
290
273
  * @remarks
291
- * Use it for work that should batch per render frame (animation, incremental DOM updates)
292
- * and naturally pause while the tab is hidden. `yield` is abort-aware: pass `options.signal`
274
+ * Use it for work that batches per render frame (animation, incremental DOM updates) and
275
+ * naturally pauses while the tab is hidden. `yield` is abort-aware: pass `options.signal`
293
276
  * and a pending yield rejects with the signal's `reason` verbatim, cancelling the pending
294
277
  * frame request. `options.priority` is accepted but a no-op — a frame callback has no
295
278
  * priority dimension.
@@ -308,8 +291,8 @@ function createFrameScheduler() {
308
291
  return new FrameScheduler();
309
292
  }
310
293
  /**
311
- * Create the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when
312
- * the host is idle via `requestIdleCallback` when present, falling back to a `setTimeout(0)`
294
+ * Creates the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when
295
+ * the host is idle through `requestIdleCallback` when present, falling back to a `setTimeout(0)`
313
296
  * macrotask; `delay(ms)` is a real `setTimeout`.
314
297
  *
315
298
  * @remarks
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/browser/constants.ts","../../../src/browser/BrowserScheduler.ts","../../../src/browser/FrameScheduler.ts","../../../src/browser/IdleScheduler.ts","../../../src/browser/factories.ts"],"sourcesContent":["import type { SchedulerPriority } from '@src/core'\n\n/**\n * The browser-native `postTask` priority for each portable {@link SchedulerPriority} — the\n * Prioritized Task Scheduling API's three levels.\n *\n * @remarks\n * A `user` hint maps to the most urgent `'user-blocking'`, `normal` to the default\n * `'user-visible'`, and `background` to `'background'`. {@link BrowserScheduler} reads this\n * map to translate the caller's portable priority into the value passed to\n * `scheduler.postTask`, so the urgency hint is honoured by the host.\n */\nexport const POST_TASK_PRIORITY: Readonly<Record<SchedulerPriority, string>> = Object.freeze({\n\tuser: 'user-blocking',\n\tnormal: 'user-visible',\n\tbackground: 'background',\n})\n","import type { SchedulerInterface, SchedulerOptions, SchedulerPriority } from '@src/core'\nimport { scheduleHost } from '@src/core'\nimport { isFunction, isPromise, isRecord } from '@orkestrel/contract'\nimport { POST_TASK_PRIORITY } from './constants.js'\n\n/**\n * The browser {@link SchedulerInterface} — the browser-native cooperative-yield backend\n * built on the Prioritized Task Scheduling API (`scheduler.postTask`), falling back to a\n * zero-delay macrotask where it is absent.\n *\n * @remarks\n * - **`yield` prefers `scheduler.postTask`, honouring priority.** When `globalThis`\n * exposes a `scheduler` with a `postTask` method, `yield()` posts a task at the mapped\n * priority (`user` → `'user-blocking'`, `normal` → `'user-visible'`, `background` →\n * `'background'`), so the host genuinely regains control and the urgency hint is\n * honoured. The capability is feature-detected through guards (`isRecord` / `isFunction`),\n * never an `as` (AGENTS §14). Where the API is absent (Firefox today, older engines),\n * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, just\n * without priority. `delay(ms)` is always a real `setTimeout`.\n * - **Abort fidelity is verbatim.** The shared `scheduleHost` lifecycle links an owned\n * settlement composite before scheduling, preserving the exact caller reason without\n * invoking caller-owned signal methods. The caller signal is NOT handed to `postTask`;\n * an internal controller cancels that native task. An unexpected native promise rejection\n * is routed back as the exact host failure instead of being discarded.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { BrowserScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new BrowserScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ priority: 'background', signal: abort.signal })\n * }\n * ```\n */\nexport class BrowserScheduler implements SchedulerInterface {\n\t/**\n\t * Yield control to the host via `scheduler.postTask` at the given priority (or a\n\t * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with\n\t * `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\tconst post = this.#postTask()\n\t\tif (post === undefined) return this.#timer(0, options?.signal)\n\t\treturn this.#yieldVia(post, options?.priority ?? 'normal', options?.signal)\n\t}\n\n\t/**\n\t * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * `ms` should be a non-negative finite number. The primitive does no validation: it\n\t * passes `ms` straight to the host `setTimeout`, which clamps a negative value or\n\t * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than\n\t * throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#timer(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// Feature-detect the Prioritized Task Scheduling API through guards (no `as`): the\n\t// global `scheduler` must be a record carrying a callable `postTask`. Returns the\n\t// narrowed `postTask` function, or `undefined` when the API is absent (the fallback).\n\t#postTask(): ((callback: () => void, options: Record<string, unknown>) => unknown) | undefined {\n\t\tconst candidate: unknown = Reflect.get(globalThis, 'scheduler')\n\t\tif (!isRecord(candidate)) return undefined\n\t\tconst post = candidate.postTask\n\t\tif (!isFunction(post)) return undefined\n\t\treturn (callback, options) => Reflect.apply(post, candidate, [callback, options])\n\t}\n\n\t// A `scheduler.postTask` boundary with an internal cancellation controller; `scheduleHost`\n\t// owns caller linking and first-settlement arbitration, including native promise failure.\n\t#yieldVia(\n\t\tpost: (callback: () => void, options: Record<string, unknown>) => unknown,\n\t\tpriority: SchedulerPriority,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\treturn scheduleHost((complete, failure) => {\n\t\t\tconst internal = new AbortController()\n\t\t\tconst task = post(complete, {\n\t\t\t\tpriority: POST_TASK_PRIORITY[priority],\n\t\t\t\tsignal: internal.signal,\n\t\t\t})\n\t\t\tif (isPromise(task)) void task.catch(failure)\n\t\t\treturn () => internal.abort()\n\t\t}, signal)\n\t}\n\n\t// The browser timer boundary shared by `delay` and fallback `yield`.\n\t#timer(ms: number, signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setTimeout(complete, ms)\n\t\t\treturn () => clearTimeout(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { scheduleHost } from '@src/core'\n\n/**\n * The frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend\n * whose `yield` resumes just before the next paint via `requestAnimationFrame`.\n *\n * @remarks\n * - **`yield` resumes before the next paint.** `yield()` waits on `requestAnimationFrame`,\n * so the resumption is aligned to the browser's render loop — ideal for work that\n * should batch per frame (animation, incremental DOM updates) and pause while the tab\n * is hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to\n * frames. `options.priority` is accepted for contract compliance but a no-op — a frame\n * callback has no priority dimension.\n * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links\n * an owned settlement composite before requesting a frame, never invokes caller-owned\n * signal methods, and cancels the native handle when abort wins.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { FrameScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new FrameScheduler()\n * while (!abort.signal.aborted) {\n * \trenderOneFrameOfWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // resume before the next paint\n * }\n * ```\n */\nexport class FrameScheduler implements SchedulerInterface {\n\t/**\n\t * Yield control to the host until just before the next paint via\n\t * `requestAnimationFrame`, then resume; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#frame(options?.signal)\n\t}\n\n\t/**\n\t * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * `ms` should be a non-negative finite number. The primitive does no validation: it\n\t * passes `ms` straight to the host `setTimeout`, which clamps a negative value or\n\t * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than\n\t * throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#sleep(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The frame request boundary; `scheduleHost` owns cancellation lifecycle.\n\t#frame(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = requestAnimationFrame(complete)\n\t\t\treturn () => cancelAnimationFrame(handle)\n\t\t}, signal)\n\t}\n\n\t// The browser timer boundary; `scheduleHost` owns cancellation lifecycle.\n\t#sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setTimeout(complete, ms)\n\t\t\treturn () => clearTimeout(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { scheduleHost } from '@src/core'\nimport type { AnyFunction } from '@orkestrel/contract'\nimport type { IdleAPI } from './types.js'\nimport { isFunction } from '@orkestrel/contract'\n\n/**\n * The idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose\n * `yield` resumes when the host is idle via `requestIdleCallback`, falling back to a\n * zero-delay macrotask where it is absent.\n *\n * @remarks\n * - **`yield` resumes during idle time.** When `globalThis` exposes `requestIdleCallback`,\n * `yield()` waits on it, so the resumption happens when the browser has spare time after\n * rendering and input — ideal for low-priority background work that must not contend with\n * the user. The capability is feature-detected through a guard (`isFunction`), never an\n * `as` (AGENTS §14). Where the API is absent (Safari today), it **falls back** to a\n * `setTimeout(0)` macrotask — still a real host-turn, just not idle-gated. `delay(ms)` is\n * always a real `setTimeout`. `options.priority` is accepted for contract compliance but a\n * no-op — idle scheduling has no priority dimension.\n * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links\n * an owned settlement composite before scheduling, never invokes caller-owned signal\n * methods, and cancels the idle callback or fallback timer when abort wins.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { IdleScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new IdleScheduler()\n * while (!abort.signal.aborted) {\n * \tdoLowPriorityWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // resume when the host is idle\n * }\n * ```\n */\nexport class IdleScheduler implements SchedulerInterface {\n\t/**\n\t * Yield control to the host until it is idle via `requestIdleCallback` (or a\n\t * `setTimeout(0)` macrotask where the API is absent), then resume; abort rejects with\n\t * `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\tconst idle = this.#idleAPI()\n\t\tif (idle === undefined) return this.#sleep(0, options?.signal)\n\t\treturn this.#idle(idle, options?.signal)\n\t}\n\n\t/**\n\t * Resume after at least `ms` milliseconds via `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * `ms` should be a non-negative finite number. The primitive does no validation: it\n\t * passes `ms` straight to the host `setTimeout`, which clamps a negative value or\n\t * `NaN` to ~0 — so an out-of-domain `ms` resolves on the next host turn rather than\n\t * throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#sleep(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// Feature-detect `requestIdleCallback` / `cancelIdleCallback` off `globalThis` through\n\t// guards (no `as`): both must be callable. Returns the narrowed pair, or `undefined`\n\t// when the API is absent (the macrotask fallback).\n\t#idleAPI(): IdleAPI | undefined {\n\t\tconst request: unknown = Reflect.get(globalThis, 'requestIdleCallback')\n\t\tconst cancel: unknown = Reflect.get(globalThis, 'cancelIdleCallback')\n\t\tif (!isFunction(request) || !isFunction(cancel)) return undefined\n\t\treturn {\n\t\t\trequest: this.#request.bind(this, request),\n\t\t\tcancel: this.#cancel.bind(this, cancel),\n\t\t}\n\t}\n\n\t// The idle callback boundary; `scheduleHost` owns cancellation lifecycle.\n\t#idle(idle: IdleAPI, signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = idle.request(complete)\n\t\t\treturn () => idle.cancel(handle)\n\t\t}, signal)\n\t}\n\n\t// The browser timer boundary shared by `delay` and fallback `yield`.\n\t#sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = setTimeout(complete, ms)\n\t\t\treturn () => clearTimeout(handle)\n\t\t}, signal)\n\t}\n\n\t#request(request: AnyFunction, callback: () => void): number {\n\t\treturn Number(Reflect.apply(request, globalThis, [callback]))\n\t}\n\n\t#cancel(cancel: AnyFunction, handle: number): void {\n\t\tReflect.apply(cancel, globalThis, [handle])\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { BrowserScheduler } from './BrowserScheduler.js'\nimport { FrameScheduler } from './FrameScheduler.js'\nimport { IdleScheduler } from './IdleScheduler.js'\n\n/**\n * Create the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses\n * the Prioritized Task Scheduling API (`scheduler.postTask`) at the requested priority\n * when present, falling back to a `setTimeout(0)` macrotask; `delay(ms)` is a real\n * `setTimeout`.\n *\n * @remarks\n * The default browser scheduler: it honours `options.priority` (`user` /\n * `normal` / `background`) when `scheduler.postTask` is available and degrades to a plain\n * macrotask elsewhere. Both methods are abort-aware: pass `options.signal` and a pending\n * yield/delay rejects with the signal's exact `reason`; the shared owned-signal lifecycle\n * cancels the native handle without invoking caller listener methods. Prefer\n * {@link createFrameScheduler} for paint-aligned work or\n * {@link createIdleScheduler} for idle-time background work.\n *\n * @returns A {@link SchedulerInterface} backed by `scheduler.postTask` (or a macrotask)\n *\n * @example\n * ```ts\n * import { createBrowserScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createBrowserScheduler()\n * await scheduler.yield({ priority: 'background' })\n * ```\n */\nexport function createBrowserScheduler(): SchedulerInterface {\n\treturn new BrowserScheduler()\n}\n\n/**\n * Create the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes\n * just before the next paint via `requestAnimationFrame`; `delay(ms)` is a real\n * `setTimeout`.\n *\n * @remarks\n * Use it for work that should batch per render frame (animation, incremental DOM updates)\n * and naturally pause while the tab is hidden. `yield` is abort-aware: pass `options.signal`\n * and a pending yield rejects with the signal's `reason` verbatim, cancelling the pending\n * frame request. `options.priority` is accepted but a no-op — a frame callback has no\n * priority dimension.\n *\n * @returns A {@link SchedulerInterface} backed by `requestAnimationFrame`\n *\n * @example\n * ```ts\n * import { createFrameScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createFrameScheduler()\n * await scheduler.yield() // resumes before the next paint\n * ```\n */\nexport function createFrameScheduler(): SchedulerInterface {\n\treturn new FrameScheduler()\n}\n\n/**\n * Create the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when\n * the host is idle via `requestIdleCallback` when present, falling back to a `setTimeout(0)`\n * macrotask; `delay(ms)` is a real `setTimeout`.\n *\n * @remarks\n * Use it for low-priority background work that must not contend with rendering or input.\n * Where `requestIdleCallback` is absent (Safari today) it degrades to a plain macrotask.\n * `yield` is abort-aware: pass `options.signal` and a pending yield rejects with the\n * signal's `reason` verbatim, cancelling the pending idle callback. `options.priority` is\n * accepted but a no-op — idle scheduling has no priority dimension.\n *\n * @returns A {@link SchedulerInterface} backed by `requestIdleCallback` (or a macrotask)\n *\n * @example\n * ```ts\n * import { createIdleScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createIdleScheduler()\n * await scheduler.yield() // resumes when the host is idle\n * ```\n */\nexport function createIdleScheduler(): SchedulerInterface {\n\treturn new IdleScheduler()\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/browser/constants.ts","../../../src/browser/BrowserScheduler.ts","../../../src/browser/FrameScheduler.ts","../../../src/browser/IdleScheduler.ts","../../../src/browser/factories.ts"],"sourcesContent":["import type { SchedulerPriority } from '@src/core'\n\n/**\n * Maps each portable {@link SchedulerPriority} to the browser-native `postTask` priority —\n * `user` to `'user-blocking'`, `normal` to `'user-visible'`, and `background` to\n * `'background'`.\n *\n * @remarks\n * A `user` hint maps to the most urgent `'user-blocking'`, `normal` to the default\n * `'user-visible'`, and `background` to `'background'`. {@link BrowserScheduler} reads this\n * map to translate the caller's portable priority into the value passed to\n * `scheduler.postTask`, so the urgency hint is honoured by the host.\n */\nexport const POST_TASK_PRIORITY: Readonly<Record<SchedulerPriority, string>> = Object.freeze({\n\tuser: 'user-blocking',\n\tnormal: 'user-visible',\n\tbackground: 'background',\n})\n","import type { SchedulerInterface, SchedulerOptions, SchedulerPriority } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\nimport { isFunction, isPromise, isRecord } from '@orkestrel/contract'\nimport { POST_TASK_PRIORITY } from './constants.js'\n\n/**\n * Implements the browser {@link SchedulerInterface} — the browser-native cooperative-yield backend\n * built on the Prioritized Task Scheduling API (`scheduler.postTask`) at the mapped priority,\n * falling back to a zero-delay macrotask where it is absent, and rejecting an aborted wait\n * with the caller's own reason.\n *\n * @remarks\n * - **`yield` prefers `scheduler.postTask`, honouring priority.** When `globalThis`\n * exposes a `scheduler` with a `postTask` method, `yield()` posts a task at the mapped\n * priority (`user` → `'user-blocking'`, `normal` → `'user-visible'`, `background` →\n * `'background'`), so the host genuinely regains control and the urgency hint is\n * honoured. The capability is feature-detected through guards (`isRecord` / `isFunction`),\n * never an `as`. Where the API is absent (Firefox today, older engines),\n * it **falls back** to a `setTimeout(0)` macrotask — still a real host-turn, without\n * priority. `delay(ms)` is always a real `setTimeout`.\n * - **Abort fidelity is verbatim.** The shared `scheduleHost` lifecycle links an owned\n * settlement composite before scheduling, preserving the exact caller reason without\n * invoking caller-owned signal methods. The caller signal is not handed to `postTask`;\n * an internal controller cancels that native task. An unexpected native promise rejection\n * is routed back as the exact host failure instead of being discarded.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { BrowserScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new BrowserScheduler()\n * while (!abort.signal.aborted) {\n * \tdoSomeWork()\n * \tawait scheduler.yield({ priority: 'background', signal: abort.signal })\n * }\n * ```\n */\nexport class BrowserScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control to the host through `scheduler.postTask` at the given priority (or a\n\t * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with\n\t * `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\tconst post = this.#postTask()\n\t\tif (post === undefined) return delayHost(0, options?.signal)\n\t\treturn this.#yieldVia(post, options?.priority ?? 'normal', options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// Feature-detect the Prioritized Task Scheduling API through guards (no `as`): the\n\t// global `scheduler` must be a record carrying a callable `postTask`. Returns the\n\t// narrowed `postTask` function, or `undefined` when the API is absent (the fallback).\n\t#postTask(): ((callback: () => void, options: Record<string, unknown>) => unknown) | undefined {\n\t\tconst candidate: unknown = Reflect.get(globalThis, 'scheduler')\n\t\tif (!isRecord(candidate)) return undefined\n\t\tconst post = candidate.postTask\n\t\tif (!isFunction(post)) return undefined\n\t\treturn (callback, options) => Reflect.apply(post, candidate, [callback, options])\n\t}\n\n\t// A `scheduler.postTask` boundary with an internal cancellation controller; `scheduleHost`\n\t// owns caller linking and first-settlement arbitration, including native promise failure.\n\t#yieldVia(\n\t\tpost: (callback: () => void, options: Record<string, unknown>) => unknown,\n\t\tpriority: SchedulerPriority,\n\t\tsignal?: AbortSignal,\n\t): Promise<void> {\n\t\treturn scheduleHost((complete, failure) => {\n\t\t\tconst internal = new AbortController()\n\t\t\tconst task = post(complete, {\n\t\t\t\tpriority: POST_TASK_PRIORITY[priority],\n\t\t\t\tsignal: internal.signal,\n\t\t\t})\n\t\t\tif (isPromise(task)) void task.catch(failure)\n\t\t\treturn () => internal.abort()\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport { delayHost, scheduleHost } from '@src/core'\n\n/**\n * Implements the frame-aligned {@link SchedulerInterface} — a browser cooperative-yield backend\n * whose `yield` resumes before the next paint through `requestAnimationFrame`, rejecting an\n * aborted wait with the caller's own reason. A `priority` hint is accepted and does nothing.\n *\n * @remarks\n * - **`yield` resumes before the next paint.** `yield()` waits on `requestAnimationFrame`,\n * so the resumption is aligned to the browser's render loop — ideal for work that\n * batches per frame (animation, incremental DOM updates) and pauses while the tab is\n * hidden (the host throttles rAF). `delay(ms)` is a real `setTimeout`, unaligned to\n * frames. `options.priority` is accepted for contract compliance but a no-op — a frame\n * callback has no priority dimension.\n * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links\n * an owned settlement composite before requesting a frame, never invokes caller-owned\n * signal methods, and cancels the native handle when abort wins.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { FrameScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new FrameScheduler()\n * while (!abort.signal.aborted) {\n * \trenderOneFrameOfWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // resume before the next paint\n * }\n * ```\n */\nexport class FrameScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control to the host until the moment before the next paint through\n\t * `requestAnimationFrame`, then resumes; abort rejects with `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\treturn this.#frame(options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// The frame request boundary; `scheduleHost` owns cancellation lifecycle.\n\t#frame(signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = requestAnimationFrame(complete)\n\t\t\treturn () => cancelAnimationFrame(handle)\n\t\t}, signal)\n\t}\n}\n","import type { SchedulerInterface, SchedulerOptions } from '@src/core'\nimport type { AnyFunction } from '@orkestrel/contract'\nimport type { IdleInterface } from './types.js'\nimport { delayHost, scheduleHost } from '@src/core'\nimport { isFunction } from '@orkestrel/contract'\n\n/**\n * Implements the idle-time {@link SchedulerInterface} — a browser cooperative-yield backend whose\n * `yield` resumes when the host is idle through `requestIdleCallback`, falling back to a\n * zero-delay macrotask where it is absent, and rejecting an aborted wait with the caller's own\n * reason. A `priority` hint is accepted and does nothing.\n *\n * @remarks\n * - **`yield` resumes during idle time.** When `globalThis` exposes `requestIdleCallback`,\n * `yield()` waits on it, so the resumption happens when the browser has spare time after\n * rendering and input — ideal for low-priority background work that must not contend with\n * the user. The capability is feature-detected through a guard (`isFunction`), never an\n * `as`. Where the API is absent (Safari today), it **falls back** to a\n * `setTimeout(0)` macrotask — still a real host-turn, not idle-gated. `delay(ms)` is\n * always a real `setTimeout`. `options.priority` is accepted for contract compliance but a\n * no-op — idle scheduling has no priority dimension.\n * - **Abort fidelity is verbatim, with cleanup.** The shared `scheduleHost` lifecycle links\n * an owned settlement composite before scheduling, never invokes caller-owned signal\n * methods, and cancels the idle callback or fallback timer when abort wins.\n * - **Event-free.** A pure functional primitive — no Emitter, no events.\n *\n * @example\n * ```ts\n * import { createAbort } from '@orkestrel/abort'\n * import { IdleScheduler } from '@orkestrel/workflow/browser'\n *\n * const abort = createAbort()\n * const scheduler = new IdleScheduler()\n * while (!abort.signal.aborted) {\n * \tdoLowPriorityWork()\n * \tawait scheduler.yield({ signal: abort.signal }) // resume when the host is idle\n * }\n * ```\n */\nexport class IdleScheduler implements SchedulerInterface {\n\t/**\n\t * Yields control to the host until it is idle through `requestIdleCallback` (or a\n\t * `setTimeout(0)` macrotask where the API is absent), then resumes; abort rejects with\n\t * `signal.reason`.\n\t */\n\tyield(options?: SchedulerOptions): Promise<void> {\n\t\tconst idle = this.#idleCallback()\n\t\tif (idle === undefined) return delayHost(0, options?.signal)\n\t\treturn this.#idle(idle, options?.signal)\n\t}\n\n\t/**\n\t * Resumes after at least `ms` milliseconds through `setTimeout`; abort rejects with\n\t * `signal.reason`.\n\t *\n\t * @remarks\n\t * Pass a non-negative finite `ms`. The primitive does no validation: it passes `ms`\n\t * straight to the host `setTimeout`, which clamps a negative value or `NaN` to ~0 — so an\n\t * out-of-domain `ms` resolves on the next host turn rather than throwing.\n\t */\n\tdelay(ms: number, options?: SchedulerOptions): Promise<void> {\n\t\treturn delayHost(ms, options?.signal)\n\t}\n\n\t// === Private\n\n\t// Feature-detect `requestIdleCallback` / `cancelIdleCallback` off `globalThis` through\n\t// guards (no `as`): both must be callable. Returns the narrowed pair, or `undefined`\n\t// when the API is absent (the macrotask fallback).\n\t#idleCallback(): IdleInterface | undefined {\n\t\tconst request: unknown = Reflect.get(globalThis, 'requestIdleCallback')\n\t\tconst cancel: unknown = Reflect.get(globalThis, 'cancelIdleCallback')\n\t\tif (!isFunction(request) || !isFunction(cancel)) return undefined\n\t\treturn {\n\t\t\trequest: this.#request.bind(this, request),\n\t\t\tcancel: this.#cancel.bind(this, cancel),\n\t\t}\n\t}\n\n\t// The idle yield boundary; `scheduleHost` owns cancellation lifecycle.\n\t#idle(idle: IdleInterface, signal?: AbortSignal): Promise<void> {\n\t\treturn scheduleHost((complete) => {\n\t\t\tconst handle = idle.request(complete)\n\t\t\treturn () => idle.cancel(handle)\n\t\t}, signal)\n\t}\n\n\t#request(request: AnyFunction, callback: () => void): number {\n\t\treturn Number(Reflect.apply(request, globalThis, [callback]))\n\t}\n\n\t#cancel(cancel: AnyFunction, handle: number): void {\n\t\tReflect.apply(cancel, globalThis, [handle])\n\t}\n}\n","import type { SchedulerInterface } from '@src/core'\nimport { BrowserScheduler } from './BrowserScheduler.js'\nimport { FrameScheduler } from './FrameScheduler.js'\nimport { IdleScheduler } from './IdleScheduler.js'\n\n/**\n * Creates the browser-native cooperative-yield {@link SchedulerInterface} — `yield()` uses\n * the Prioritized Task Scheduling API (`scheduler.postTask`) at the requested priority\n * when present, falling back to a `setTimeout(0)` macrotask; `delay(ms)` is a real\n * `setTimeout`.\n *\n * @remarks\n * The default browser scheduler: it honours `options.priority` (`user` /\n * `normal` / `background`) when `scheduler.postTask` is available and degrades to a plain\n * macrotask elsewhere. Both methods are abort-aware: pass `options.signal` and a pending\n * yield/delay rejects with the signal's exact `reason`; the shared owned-signal lifecycle\n * cancels the native handle without invoking caller listener methods. Prefer\n * {@link createFrameScheduler} for paint-aligned work or\n * {@link createIdleScheduler} for idle-time background work.\n *\n * @returns A {@link SchedulerInterface} backed by `scheduler.postTask` (or a macrotask)\n *\n * @example\n * ```ts\n * import { createBrowserScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createBrowserScheduler()\n * await scheduler.yield({ priority: 'background' })\n * ```\n */\nexport function createBrowserScheduler(): SchedulerInterface {\n\treturn new BrowserScheduler()\n}\n\n/**\n * Creates the frame-aligned cooperative-yield {@link SchedulerInterface} — `yield()` resumes\n * before the next paint through `requestAnimationFrame`; `delay(ms)` is a real\n * `setTimeout`.\n *\n * @remarks\n * Use it for work that batches per render frame (animation, incremental DOM updates) and\n * naturally pauses while the tab is hidden. `yield` is abort-aware: pass `options.signal`\n * and a pending yield rejects with the signal's `reason` verbatim, cancelling the pending\n * frame request. `options.priority` is accepted but a no-op — a frame callback has no\n * priority dimension.\n *\n * @returns A {@link SchedulerInterface} backed by `requestAnimationFrame`\n *\n * @example\n * ```ts\n * import { createFrameScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createFrameScheduler()\n * await scheduler.yield() // resumes before the next paint\n * ```\n */\nexport function createFrameScheduler(): SchedulerInterface {\n\treturn new FrameScheduler()\n}\n\n/**\n * Creates the idle-time cooperative-yield {@link SchedulerInterface} — `yield()` resumes when\n * the host is idle through `requestIdleCallback` when present, falling back to a `setTimeout(0)`\n * macrotask; `delay(ms)` is a real `setTimeout`.\n *\n * @remarks\n * Use it for low-priority background work that must not contend with rendering or input.\n * Where `requestIdleCallback` is absent (Safari today) it degrades to a plain macrotask.\n * `yield` is abort-aware: pass `options.signal` and a pending yield rejects with the\n * signal's `reason` verbatim, cancelling the pending idle callback. `options.priority` is\n * accepted but a no-op — idle scheduling has no priority dimension.\n *\n * @returns A {@link SchedulerInterface} backed by `requestIdleCallback` (or a macrotask)\n *\n * @example\n * ```ts\n * import { createIdleScheduler } from '@orkestrel/workflow/browser'\n *\n * const scheduler = createIdleScheduler()\n * await scheduler.yield() // resumes when the host is idle\n * ```\n */\nexport function createIdleScheduler(): SchedulerInterface {\n\treturn new IdleScheduler()\n}\n"],"mappings":"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"}