@systemfsoftware/effect-daemon-spec 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,124 @@
1
1
  # @systemfsoftware/effect-daemon-spec
2
2
 
3
+ ## 3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Published types no longer include names tagged `@internal`. If you imported one of those names from the package, switch to a public export or stop using it.
8
+
9
+ ### Minor Changes
10
+
11
+ - The loop kinds now ship their tags as values.
12
+
13
+ `PollLoopTag`, `StreamLoopTag` and `SubscriptionLoopTag` are new exports: each is a shared `{ _tag }`
14
+ value together with a type of the same name, and `PollLoop`, `StreamLoop` and
15
+ `SubscriptionLoop` inherit their discriminant from it. Members, tag strings and every existing
16
+ narrowing are unchanged, and constructing a loop can now spread the carrier instead of repeating
17
+ the literal.
18
+
19
+ ### Patch Changes
20
+
21
+ - The peer requirements for `effect` and for the Effect test-runner integration now accept any compatible `4.0.0-rc` release, instead of demanding one exact release candidate.
22
+
23
+ Installing alongside a newer release candidate no longer reports an unmet peer dependency or resolves a second copy of `effect` into the dependency tree.
24
+
25
+ - Updated dependencies:
26
+ - @systemfsoftware/effect-cell-types@4.0.0
27
+
28
+ ## 2.0.0
29
+
30
+ ### Major Changes
31
+
32
+ - Pass capabilities as arguments instead of requiring them through a projection tag, in these two packages
33
+
34
+ Wlaschin's second approach — dependency parameterization — is preferred over the
35
+ Reader, and it removes the requirement from the signature entirely rather than
36
+ relocating it. Each operation in `effect-daemon-spec` and `stryker-js-cli` that
37
+ previously reached into the context for a projection now receives what it uses,
38
+ and the composition root is the single place that acquires the port.
39
+
40
+ The remaining `*ExecutorDeps` projections live in `omp/**/src/internal/`, fenced
41
+ behind each package's own `exports` map, so they are unreachable from any consumer;
42
+ the exported-wiring gate scans `src/` outside `src/internal/`, so internal composition
43
+ stays internal and is not a migration target here.
44
+
45
+ - `effect-daemon-spec` — `withLeaderLock` takes `lock: LeaderLock['Type']`, and the
46
+ supervisor body takes `reporter: DaemonReporter['Type']`. Every `yield* LeaderLock`
47
+ and `yield* DaemonReporter` now lands in `mod.ts`; the exported `worker` and
48
+ `supervisor` shapes are unchanged, and `withLeaderLock` loses `LeaderLock` from `R`.
49
+ - `stryker-js-cli` — `StrykerCliExecutorDeps` and its service interface are gone.
50
+ `runStrykerCli` and the handler take `detectMode` and `createRunEventStream`, typed
51
+ as indexed accesses off the two port services, and both lose the requirement from
52
+ `R`. `main.ts` acquires both ports and passes the members down.
53
+
54
+ For these two packages, a caller that provided the projection layer now provides
55
+ nothing, because the operation no longer requires anything.
56
+
57
+ - Carry the lock decision as a `LockBinding` so a required lock can never silently vanish.
58
+
59
+ The three lock-taking operations — the internal `worker`, `supervisor`, and the
60
+ `withLockByMode` operation behind them — now take a single discriminated
61
+ argument, `LockBinding`, in place of a `(LockConfig, LeaderLock['Type'] | null)`
62
+ pair. `unlocked` is the one case for a body that takes no lock; `locked` carries
63
+ the keyed spec and the adapter that honours it.
64
+
65
+ A spec declaring `mode: 'required'` paired with a null or missing adapter
66
+ previously fell through to the body unwrapped — a silent downgrade from "must
67
+ hold the leader lock" to "no lock at all". That combination is no longer
68
+ representable: `unlocked` only exists for a `{ mode: 'none' }` spec, and `locked`
69
+ demands both a keyed spec (via `KeyedLockConfig`) and an adapter (via
70
+ `LeaderLock['Type']`). The composition root — `worker` and `supervisor` in
71
+ `mod.ts` — is now the one place that builds the binding, and its public shapes
72
+ are unchanged.
73
+
74
+ ### Minor Changes
75
+
76
+ - cut over to effect v4 (4.0.0-rc.108): public surface derives from effect types; peers flip effect ^3→^4
77
+
78
+ - Produce every workflow through `Workflow.make`.
79
+
80
+ `decideRestart`, `interpretHookResult`, and `admitSurvivorsRun` are now built by the constructor rather
81
+ than annotated with `Workflow<Command, Decision, Error>`. Each decision is behaviourally identical —
82
+ `make` is the identity at runtime — but the channels are now inferred from the decider instead of
83
+ asserted by hand, so a total decision resolves to `UninhabitedError` and becomes uncallable rather than
84
+ compiling as a workflow that cannot fail.
85
+
86
+ `effect-daemon-spec` takes a minor bump because the change is consumer-visible beyond its own source:
87
+ `@systemfsoftware/effect-cell-types` moves from `devDependencies` to `dependencies`, so installing this
88
+ package now installs it. That reclassification is required, not incidental — `make` is a runtime call,
89
+ and `scripts/guards/check-runtime-deps.mjs` fails a runtime import declared only as a dev dependency.
90
+ `omp-claude-compat` gains the same dependency; `stryker-js-cli` already declared it.
91
+
92
+ `RestartDecisionWorkflow` survives as a type-only export: one in-repo consumer, its own property test,
93
+ references it through `ReturnType<…>`.
94
+
95
+ ### Patch Changes
96
+
97
+ - Array types are spelled one way. `Array<T>` and `ReadonlyArray<T>` in emitted
98
+ declarations become `T[]` and `readonly T[]`, which the type checker cannot tell
99
+ apart: no exported type changes, only how it is written.
100
+
101
+ - New version is published through npm trusted publishing, so it carries a provenance attestation you can verify.
102
+
103
+ - Express each executor's sandwich as a `Cell` description.
104
+
105
+ Every call site that previously sequenced the phases by hand now builds one description and hands it to the interpreter, so the order these executors run in is carried by the phase types instead of by the order the statements happen to appear in. Behaviour is preserved and no public surface moves: the change is confined to `src/internal/*.executor.ts`, and each package's golden API report is unchanged.
106
+
107
+ One site needed a real fix rather than a translation. `supervisor-body.executor.ts` wrote before it could classify — it recorded a restart, then read the resulting rate — which is a read that depends on an earlier decision. Its read now gathers the restart record and the resulting rate as one product, which keeps that site a single layer, with the intensity tracker passed as the read's command rather than captured from the surrounding scope.
108
+
109
+ - The base mutation preset selects at the make boundary.
110
+
111
+ The preset carries both ignorers (`effect-schema-declarations`, `workflow-make-boundary`) and
112
+ `disableBail: true`, so killer recording is structural for every inheriting config. The sandwich
113
+ packages (daemon-spec, stryker-js-cli, omp-claude-compat) widen `mutate` to all non-test source
114
+ at explicit 100/100/100 thresholds — the ignorer is the selector, so membership is forced by the
115
+ brand rather than chosen by a path list. Library packages' mutate arrays are byte-identical.
116
+
117
+ - `restart-decision.workflow.ts` has its pure decision in a new internal `restart-decision.kernel.ts` with a colocated property test. Both files are internal, so the package's public surface is unchanged and the restart behaviour is identical.
118
+
119
+ - Updated dependencies:
120
+ - @systemfsoftware/effect-cell-types@3.0.0
121
+
3
122
  ## 1.0.0
4
123
 
5
124
  ### Major Changes
@@ -0,0 +1,406 @@
1
+ import { Cause } from 'effect';
2
+ import { Context } from 'effect';
3
+ import { Duration } from 'effect';
4
+ import { Effect } from 'effect';
5
+ import { Latch } from 'effect';
6
+ import { Layer } from 'effect';
7
+ import { Metric } from 'effect';
8
+ import { Option as Option_2 } from 'effect';
9
+ import { Schedule } from 'effect';
10
+ import { Schema } from 'effect';
11
+ import { Scope } from 'effect';
12
+ import { Scope as Scope_2 } from 'effect/Scope';
13
+ import { Stream } from 'effect';
14
+ import { YieldableError } from 'effect/Cause';
15
+
16
+ export declare class BoundedIntensity extends BoundedIntensity_base {
17
+ readonly [IntensityTypeId]: symbol;
18
+ }
19
+
20
+ declare const BoundedIntensity_base: Schema.Class<BoundedIntensity, Schema.TaggedStruct<"Bounded", {
21
+ readonly restarts: Schema.Int;
22
+ readonly window: Schema.Duration;
23
+ }>, {}>;
24
+
25
+ export declare const cappedBackoff: (base: Duration.Input, cap: Duration.Input) => Schedule.Schedule<Duration.Duration>;
26
+
27
+ export declare type Child<E, R> = Worker_2<E, R> | Supervisor<E, R>;
28
+
29
+ export declare class ChildPolicyConfig extends ChildPolicyConfig_base {}
30
+
31
+ declare const ChildPolicyConfig_base: Schema.Class<ChildPolicyConfig, Schema.Struct<{
32
+ readonly restart: Schema.optional<Schema.Literals<readonly ["permanent", "transient", "temporary"]>>;
33
+ readonly intensity: Schema.optional<Schema.Struct<{
34
+ readonly restarts: Schema.Int;
35
+ readonly window: Schema.Duration;
36
+ }>>;
37
+ }>, {}>;
38
+
39
+ export declare type ChildRef = {
40
+ readonly id: number;
41
+ readonly removed: Effect.Effect<void>;
42
+ };
43
+
44
+ export declare interface CommonOpts<L extends LockConfig> {
45
+ readonly name: string;
46
+ readonly child?: ChildPolicyConfig;
47
+ readonly tick: TickPolicyConfig;
48
+ readonly tickHooks?: TickPolicyHooks;
49
+ readonly lock: L;
50
+ }
51
+
52
+ declare const custom: <P>(policy: P) => Effect.Effect<P>;
53
+
54
+ export declare const Daemon: {
55
+ readonly poll: typeof poll;
56
+ readonly stream: typeof stream;
57
+ readonly subscription: typeof subscription;
58
+ };
59
+
60
+ export declare interface DaemonHealth {
61
+ readonly name: string;
62
+ readonly ready: Latch.Latch;
63
+ readonly healthy: Latch.Latch;
64
+ readonly paused: Latch.Latch;
65
+ }
66
+
67
+ export declare class DaemonReporter extends DaemonReporter_base {}
68
+
69
+ declare const DaemonReporter_base: Context.ServiceClass<DaemonReporter, "@systemfsoftware/effect-daemon-spec/DaemonReporterAdapter/DaemonReporter", DaemonReporterService>;
70
+
71
+ export declare interface DaemonReporterService {
72
+ readonly onRestart: (name: string, cause: Cause.Cause<never>) => Effect.Effect<void>;
73
+ readonly onExhausted: (name: string, cause: Cause.Cause<never>) => Effect.Effect<void>;
74
+ }
75
+
76
+ declare const dynamic$1: <E, R, Args>(spec: DynamicSpec<E, R, Args>) => Effect.Effect<DynamicHandle<Args, R | LeaderLock | DaemonReporter | Scope.Scope>, never, R | LeaderLock | DaemonReporter | Scope.Scope>;
77
+
78
+ export declare const dynamic: <E, R, Args>(opts: {
79
+ readonly name: string;
80
+ readonly child: (args: Args) => Worker_2<E, R>;
81
+ readonly maxChildren?: MaxChildren;
82
+ }) => DynamicSpec<E, R, Args>;
83
+
84
+ export declare interface DynamicHandle<Args, R = never> {
85
+ readonly health: SupervisorHealth;
86
+ readonly startChild: (args: Args) => Effect.Effect<ChildRef, DynamicLimitExceeded, R>;
87
+ readonly stopChild: (ref: Pick<ChildRef, 'id'>) => Effect.Effect<void>;
88
+ readonly count: Effect.Effect<number>;
89
+ }
90
+
91
+ export declare class DynamicLimitExceeded extends DynamicLimitExceeded_base {}
92
+
93
+ declare const DynamicLimitExceeded_base: Schema.Class<DynamicLimitExceeded, Schema.TaggedStruct<"DynamicLimitExceeded", {
94
+ readonly limit: Schema.Int;
95
+ }>, YieldableError>;
96
+
97
+ export declare interface DynamicSpec<E, R, Args> {
98
+ readonly [DynamicSpecTypeId]: DynamicSpecTypeId;
99
+ readonly name: string;
100
+ readonly child: (args: Args) => Worker_2<E, R>;
101
+ readonly maxChildren: MaxChildren;
102
+ }
103
+
104
+ export declare const DynamicSpecTypeId: unique symbol;
105
+
106
+ export declare type DynamicSpecTypeId = typeof DynamicSpecTypeId;
107
+
108
+ export declare const healthStateGauge: Metric.Gauge<number>;
109
+
110
+ export declare const Intensity: Schema.Union<readonly [typeof BoundedIntensity, typeof UnboundedIntensity]>;
111
+
112
+ export declare type Intensity = typeof Intensity.Type;
113
+
114
+ export declare const IntensityConfig: Schema.Struct<{
115
+ readonly restarts: Schema.Int;
116
+ readonly window: Schema.Duration;
117
+ }>;
118
+
119
+ export declare type IntensityConfig = typeof IntensityConfig.Type;
120
+
121
+ declare const IntensityTypeId: unique symbol;
122
+
123
+ declare type IntensityTypeId = typeof IntensityTypeId;
124
+
125
+ export declare const leader: (cap: Duration.Input) => Effect.Effect<SupervisionPolicy>;
126
+
127
+ export declare const LeaderConfig: Context.Reference<SupervisionConfig>;
128
+
129
+ export declare class LeaderLock extends LeaderLock_base {
130
+ static readonly Noop: Layer.Layer<LeaderLock>;
131
+ }
132
+
133
+ declare const LeaderLock_base: Context.ServiceClass<LeaderLock, "@systemfsoftware/effect-daemon-spec/LeaderLockAdapter/LeaderLock", LeaderLockService>;
134
+
135
+ export declare type LeaderLockAcquireError = LeaderLockNotAcquired | LeaderLockInfraError;
136
+
137
+ export declare const LeaderLockFromPrimitive: Layer.Layer<LeaderLock, never, LockPrimitive>;
138
+
139
+ export declare class LeaderLockInfraError extends LeaderLockInfraError_base {}
140
+
141
+ declare const LeaderLockInfraError_base: Schema.Class<LeaderLockInfraError, Schema.TaggedStruct<"LeaderLockInfraError", {
142
+ readonly key: Schema.String;
143
+ readonly cause: Schema.Unknown;
144
+ }>, YieldableError>;
145
+
146
+ export declare class LeaderLockNotAcquired extends LeaderLockNotAcquired_base {}
147
+
148
+ declare const LeaderLockNotAcquired_base: Schema.Class<LeaderLockNotAcquired, Schema.TaggedStruct<"LeaderLockNotAcquired", {
149
+ readonly key: Schema.String;
150
+ }>, YieldableError>;
151
+
152
+ export declare interface LeaderLockOptions {
153
+ readonly key: string;
154
+ readonly mode: 'required' | 'optional';
155
+ readonly acquireRetryBackoff?: Schedule.Schedule<Duration.Duration>;
156
+ }
157
+
158
+ export declare interface LeaderLockService {
159
+ readonly withLock: <A, E, R>(key: string, self: Effect.Effect<A, E, R>) => Effect.Effect<Option_2.Option<A>, E | LeaderLockInfraError, R>;
160
+ }
161
+
162
+ export declare type LockConfig = {
163
+ mode: 'none';
164
+ } | {
165
+ mode: 'optional';
166
+ key: string;
167
+ } | {
168
+ mode: 'required';
169
+ key: string;
170
+ acquireRetryBackoff: Schedule.Schedule<Duration.Duration>;
171
+ };
172
+
173
+ export declare class LockPolicyConfig extends LockPolicyConfig_base {}
174
+
175
+ declare const LockPolicyConfig_base: Schema.Class<LockPolicyConfig, Schema.Struct<{
176
+ readonly mode: Schema.optional<Schema.Literals<readonly ["none", "required", "optional"]>>;
177
+ readonly key: Schema.optional<Schema.String>;
178
+ }>, {}>;
179
+
180
+ export declare class LockPrimitive extends LockPrimitive_base {}
181
+
182
+ declare const LockPrimitive_base: Context.ServiceClass<LockPrimitive, "@systemfsoftware/effect-daemon-spec/LeaderLockAdapter/LockPrimitive", LockPrimitiveService>;
183
+
184
+ export declare class LockPrimitiveError extends LockPrimitiveError_base {}
185
+
186
+ declare const LockPrimitiveError_base: Schema.Class<LockPrimitiveError, Schema.TaggedStruct<"LockPrimitiveError", {
187
+ readonly key: Schema.String;
188
+ readonly cause: Schema.Unknown;
189
+ }>, YieldableError>;
190
+
191
+ export declare interface LockPrimitiveService {
192
+ readonly tryAcquire: (key: string) => Effect.Effect<boolean, LockPrimitiveError, Scope.Scope>;
193
+ }
194
+
195
+ export declare type LoopShape<E, R> = PollLoop<E, R> | StreamLoop<E, R> | SubscriptionLoop<E, R>;
196
+
197
+ export declare const MaxChildren: Schema.brand<Schema.Int, "MaxChildren">;
198
+
199
+ export declare type MaxChildren = typeof MaxChildren.Type;
200
+
201
+ export declare const Noop: Layer.Layer<DaemonReporter>;
202
+
203
+ export declare const oneForAll: <E, R, L extends LockConfig = LockConfig>(opts: SupervisorOpts<E, R, L>) => Supervisor<E, R, L>;
204
+
205
+ export declare const oneForOne: <E, R, L extends LockConfig = LockConfig>(opts: SupervisorOpts<E, R, L>) => Supervisor<E, R, L>;
206
+
207
+ export declare const poll: <A, E, R, L extends LockConfig>(opts: PollOpts<A, E, R, L>) => Worker_2<E, R, L>;
208
+
209
+ export declare interface PollLoop<E, R> extends PollLoopTag {
210
+ readonly gate: Effect.Effect<Option_2.Option<Effect.Effect<void, E, R>>, E, R>;
211
+ readonly interval: Duration.Input;
212
+ }
213
+
214
+ /**
215
+ * Discriminants on the public Worker loop variants.
216
+ *
217
+ * These tags are part of the published type identity of `poll`, `stream`,
218
+ * and `subscription`. They are not unpublished wiring.
219
+ */
220
+ export declare const PollLoopTag: {
221
+ readonly _tag: 'Poll';
222
+ };
223
+
224
+ export declare type PollLoopTag = typeof PollLoopTag;
225
+
226
+ export declare type PollOpts<A, E, R, L extends LockConfig> = CommonOpts<L> & {
227
+ readonly interval: Duration.Input;
228
+ } & ({
229
+ readonly prereq?: undefined;
230
+ readonly work: Effect.Effect<A, E, R>;
231
+ } | {
232
+ readonly prereq: Effect.Effect<Option_2.Option<A>, E, R>;
233
+ readonly work: (data: A) => Effect.Effect<void, E, R>;
234
+ });
235
+
236
+ export declare interface ReporterPolicyHooks {
237
+ readonly onRestart?: (cause: Cause.Cause<never>) => Effect.Effect<void>;
238
+ readonly onExhausted?: (cause: Cause.Cause<never>) => Effect.Effect<void>;
239
+ }
240
+
241
+ export declare const restForOne: <E, R, L extends LockConfig = LockConfig>(opts: SupervisorOpts<E, R, L>) => Supervisor<E, R, L>;
242
+
243
+ export declare const run: {
244
+ readonly worker: {
245
+ <E, R>(w: Worker_2<E, R, {
246
+ mode: 'none';
247
+ }>): Effect.Effect<DaemonHealth, never, R | Scope_2>;
248
+ <E, R>(w: Worker_2<E, R, LockConfig>): Effect.Effect<DaemonHealth, never, R | LeaderLock | Scope_2>;
249
+ };
250
+ readonly supervisor: typeof supervisor;
251
+ readonly dynamic: typeof dynamic$1;
252
+ };
253
+
254
+ export declare const stream: <A, E, R, L extends LockConfig>(opts: CommonOpts<L> & {
255
+ readonly stream: Stream.Stream<A, E, R>;
256
+ }) => Worker_2<E, R, L>;
257
+
258
+ export declare interface StreamLoop<E, R> extends StreamLoopTag {
259
+ readonly stream: Stream.Stream<unknown, E, R>;
260
+ }
261
+
262
+ export declare const StreamLoopTag: {
263
+ readonly _tag: 'Stream';
264
+ };
265
+
266
+ export declare type StreamLoopTag = typeof StreamLoopTag;
267
+
268
+ export declare const subscription: <A, E, R, L extends LockConfig>(opts: CommonOpts<L> & {
269
+ readonly acquire: Effect.Effect<A, E, R>;
270
+ }) => Worker_2<E, R, L>;
271
+
272
+ export declare interface SubscriptionLoop<E, R> extends SubscriptionLoopTag {
273
+ readonly acquire: Effect.Effect<void, E, R>;
274
+ }
275
+
276
+ export declare const SubscriptionLoopTag: {
277
+ readonly _tag: 'Subscription';
278
+ };
279
+
280
+ export declare type SubscriptionLoopTag = typeof SubscriptionLoopTag;
281
+
282
+ export declare const Supervision: {
283
+ readonly leader: typeof leader;
284
+ readonly worker: typeof supervision;
285
+ readonly task: typeof task;
286
+ readonly custom: typeof custom;
287
+ };
288
+
289
+ export declare const supervision: (cap: Duration.Input) => Effect.Effect<SupervisionPolicy>;
290
+
291
+ export declare interface SupervisionConfig {
292
+ readonly backoffBase: Duration.Input;
293
+ readonly intensity: Intensity;
294
+ readonly cooldown: Duration.Input;
295
+ }
296
+
297
+ export declare interface SupervisionPolicy {
298
+ readonly intensity: Intensity;
299
+ readonly backoff: Schedule.Schedule<Duration.Duration>;
300
+ readonly cooldown: Duration.Input;
301
+ }
302
+
303
+ export declare interface Supervisor<E, R, L extends LockConfig = LockConfig> {
304
+ readonly [SupervisorTypeId]: SupervisorTypeId;
305
+ readonly name: string;
306
+ readonly strategy: 'one_for_one' | 'one_for_all' | 'rest_for_one';
307
+ readonly children: readonly (Worker_2<E, R> | Supervisor<E, R>)[];
308
+ readonly supervision: Effect.Effect<SupervisionPolicy>;
309
+ readonly lock: L;
310
+ readonly reporter: ReporterPolicyHooks;
311
+ }
312
+
313
+ /**
314
+ * The supervisor: acquires the `DaemonReporter` and — unless the lock mode is none —
315
+ * the `LeaderLock` capabilities at the composition root, then hands them down to the
316
+ * supervisor body via the lock binding. The body itself only ever sees the service
317
+ * values.
318
+ */
319
+ export declare const supervisor: <E, R>(s: Supervisor<E, R, LockConfig>) => Effect.Effect<SupervisorHealth, never, R | DaemonReporter | LeaderLock | Scope.Scope>;
320
+
321
+ export declare const supervisorChildrenGauge: Metric.Gauge<number>;
322
+
323
+ export declare const supervisorExhaustionsCounter: Metric.Counter<number>;
324
+
325
+ export declare interface SupervisorHealth {
326
+ readonly name: string;
327
+ readonly ready: Latch.Latch;
328
+ readonly healthy: Latch.Latch;
329
+ readonly paused: Latch.Latch;
330
+ readonly children: readonly (DaemonHealth | SupervisorHealth)[];
331
+ }
332
+
333
+ export declare interface SupervisorOpts<E, R, L extends LockConfig> {
334
+ readonly name: string;
335
+ readonly children: readonly Child<E, R>[];
336
+ readonly supervision: Effect.Effect<SupervisionPolicy>;
337
+ readonly lock: L;
338
+ readonly reporter?: ReporterPolicyHooks;
339
+ }
340
+
341
+ export declare const supervisorRestartsCounter: Metric.Counter<number>;
342
+
343
+ export declare const SupervisorTypeId: unique symbol;
344
+
345
+ export declare type SupervisorTypeId = typeof SupervisorTypeId;
346
+
347
+ export declare const task: (budget: Duration.Input) => Effect.Effect<SupervisionPolicy>;
348
+
349
+ export declare const TaskConfig: Context.Reference<SupervisionConfig>;
350
+
351
+ export declare class TickPolicyConfig extends TickPolicyConfig_base {}
352
+
353
+ declare const TickPolicyConfig_base: Schema.Class<TickPolicyConfig, Schema.Struct<{
354
+ readonly spanName: Schema.optional<Schema.String>;
355
+ readonly tickTimeout: Schema.Duration;
356
+ readonly startLogLevel: Schema.optional<Schema.Literals<readonly ["debug", "info"]>>;
357
+ }>, {}>;
358
+
359
+ export declare interface TickPolicyHooks {
360
+ readonly spanAttributes?: Effect.Effect<Record<string, string | number | boolean>>;
361
+ readonly innerRetry?: Schedule.Schedule<unknown>;
362
+ readonly trackDuration?: Metric.Histogram<Duration.Duration>;
363
+ }
364
+
365
+ export declare class UnboundedIntensity extends UnboundedIntensity_base {
366
+ readonly [IntensityTypeId]: symbol;
367
+ }
368
+
369
+ declare const UnboundedIntensity_base: Schema.Class<UnboundedIntensity, Schema.TaggedStruct<"Unbounded", {}>, {}>;
370
+
371
+ /**
372
+ * Runs `self` while holding the named leader lock.
373
+ */
374
+ export declare function withLeaderLock<A, E, R>(self: Effect.Effect<A, E, R>, options: LeaderLockOptions, lock: LeaderLock['Service']): Effect.Effect<A | void, E | LeaderLockAcquireError, R>;
375
+
376
+ /**
377
+ * Boots a worker. The leader-lock capability is acquired here, at the composition
378
+ * root, and handed down as part of the lock binding: the executor behind this
379
+ * entry point never sees the tag. A worker whose lock is `{ mode: 'none' }`
380
+ * takes no lock at all.
381
+ */
382
+ export declare const worker: {
383
+ <E, R>(w: Worker_2<E, R, {
384
+ mode: 'none';
385
+ }>): Effect.Effect<DaemonHealth, never, R | Scope.Scope>;
386
+ <E, R>(w: Worker_2<E, R, LockConfig>): Effect.Effect<DaemonHealth, never, R | LeaderLock | Scope.Scope>;
387
+ };
388
+
389
+ declare interface Worker_2<E, R, L extends LockConfig = LockConfig> {
390
+ readonly [WorkerTypeId]: WorkerTypeId;
391
+ readonly name: string;
392
+ readonly loop: LoopShape<E, R>;
393
+ readonly child: ChildPolicyConfig;
394
+ readonly tick: TickPolicyConfig;
395
+ readonly tickHooks: TickPolicyHooks;
396
+ readonly lock: L;
397
+ }
398
+ export { Worker_2 as Worker }
399
+
400
+ export declare const WorkerConfig: Context.Reference<SupervisionConfig>;
401
+
402
+ export declare const WorkerTypeId: unique symbol;
403
+
404
+ export declare type WorkerTypeId = typeof WorkerTypeId;
405
+
406
+ export { }
@@ -9,6 +9,7 @@ import { Option as Option_2 } from 'effect';
9
9
  import { Schedule } from 'effect';
10
10
  import { Schema } from 'effect';
11
11
  import { Scope } from 'effect';
12
+ import { Scope as Scope_2 } from 'effect/Scope';
12
13
  import { Stream } from 'effect';
13
14
  import { YieldableError } from 'effect/Cause';
14
15
 
@@ -205,12 +206,23 @@ export declare const oneForOne: <E, R, L extends LockConfig = LockConfig>(opts:
205
206
 
206
207
  export declare const poll: <A, E, R, L extends LockConfig>(opts: PollOpts<A, E, R, L>) => Worker_2<E, R, L>;
207
208
 
208
- export declare type PollLoop<E, R> = {
209
- readonly _tag: 'Poll';
209
+ export declare interface PollLoop<E, R> extends PollLoopTag {
210
210
  readonly gate: Effect.Effect<Option_2.Option<Effect.Effect<void, E, R>>, E, R>;
211
211
  readonly interval: Duration.Input;
212
+ }
213
+
214
+ /**
215
+ * Discriminants on the public Worker loop variants.
216
+ *
217
+ * These tags are part of the published type identity of `poll`, `stream`,
218
+ * and `subscription`. They are not unpublished wiring.
219
+ */
220
+ export declare const PollLoopTag: {
221
+ readonly _tag: 'Poll';
212
222
  };
213
223
 
224
+ export declare type PollLoopTag = typeof PollLoopTag;
225
+
214
226
  export declare type PollOpts<A, E, R, L extends LockConfig> = CommonOpts<L> & {
215
227
  readonly interval: Duration.Input;
216
228
  } & ({
@@ -232,8 +244,8 @@ export declare const run: {
232
244
  readonly worker: {
233
245
  <E, R>(w: Worker_2<E, R, {
234
246
  mode: 'none';
235
- }>): Effect.Effect<DaemonHealth, never, R | Scope.Scope>;
236
- <E, R>(w: Worker_2<E, R, LockConfig>): Effect.Effect<DaemonHealth, never, R | LeaderLock | Scope.Scope>;
247
+ }>): Effect.Effect<DaemonHealth, never, R | Scope_2>;
248
+ <E, R>(w: Worker_2<E, R, LockConfig>): Effect.Effect<DaemonHealth, never, R | LeaderLock | Scope_2>;
237
249
  };
238
250
  readonly supervisor: typeof supervisor;
239
251
  readonly dynamic: typeof dynamic$1;
@@ -243,20 +255,30 @@ export declare const stream: <A, E, R, L extends LockConfig>(opts: CommonOpts<L>
243
255
  readonly stream: Stream.Stream<A, E, R>;
244
256
  }) => Worker_2<E, R, L>;
245
257
 
246
- export declare type StreamLoop<E, R> = {
247
- readonly _tag: 'Stream';
258
+ export declare interface StreamLoop<E, R> extends StreamLoopTag {
248
259
  readonly stream: Stream.Stream<unknown, E, R>;
260
+ }
261
+
262
+ export declare const StreamLoopTag: {
263
+ readonly _tag: 'Stream';
249
264
  };
250
265
 
266
+ export declare type StreamLoopTag = typeof StreamLoopTag;
267
+
251
268
  export declare const subscription: <A, E, R, L extends LockConfig>(opts: CommonOpts<L> & {
252
269
  readonly acquire: Effect.Effect<A, E, R>;
253
270
  }) => Worker_2<E, R, L>;
254
271
 
255
- export declare type SubscriptionLoop<E, R> = {
256
- readonly _tag: 'Subscription';
272
+ export declare interface SubscriptionLoop<E, R> extends SubscriptionLoopTag {
257
273
  readonly acquire: Effect.Effect<void, E, R>;
274
+ }
275
+
276
+ export declare const SubscriptionLoopTag: {
277
+ readonly _tag: 'Subscription';
258
278
  };
259
279
 
280
+ export declare type SubscriptionLoopTag = typeof SubscriptionLoopTag;
281
+
260
282
  export declare const Supervision: {
261
283
  readonly leader: typeof leader;
262
284
  readonly worker: typeof supervision;
@@ -346,6 +368,9 @@ export declare class UnboundedIntensity extends UnboundedIntensity_base {
346
368
 
347
369
  declare const UnboundedIntensity_base: Schema.Class<UnboundedIntensity, Schema.TaggedStruct<"Unbounded", {}>, {}>;
348
370
 
371
+ /**
372
+ * Runs `self` while holding the named leader lock.
373
+ */
349
374
  export declare function withLeaderLock<A, E, R>(self: Effect.Effect<A, E, R>, options: LeaderLockOptions, lock: LeaderLock['Service']): Effect.Effect<A | void, E | LeaderLockAcquireError, R>;
350
375
 
351
376
  /**