@walkeros/collector 4.7.0-next-1790722899482 → 4.7.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,6 +1,6 @@
1
1
  # @walkeros/collector
2
2
 
3
- ## 4.7.0-next-1790722899482
3
+ ## 4.7.0
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -9,6 +9,11 @@
9
9
  copy with a derived `event.id`. Unknown transformer ids warn and the chain
10
10
  continues, and a throwing transformer counts in `status.failed`. `walkChain`
11
11
  and `extractTransformerNextMap` are no longer exported.
12
+ - b9668bf: A destination's `on()` handler now receives the current state before
13
+ any event is sent to it, including with `require`, `walker destination` at
14
+ runtime, and state passed to `walker run`. Handlers are awaited up to
15
+ `config.timeout`; a destination whose handler does not respond receives no
16
+ events until it does. The exported `callDestinationOn` now returns a promise.
12
17
  - 74821ed: New `collector.next`: a transformer chain run once per event before
13
18
  the destinations; a `stop` there drops it for all of them. Routes in every
14
19
  chain field can drop an event with `{ stop: true }`, optionally gated by
@@ -22,15 +27,32 @@
22
27
 
23
28
  ### Patch Changes
24
29
 
30
+ - 786a860: AWS destinations now deliver in bundled flows without extra setup.
31
+ Firehose batches by default, ends records with a newline (`newline: false`
32
+ turns it off), sends mapped `data` and accepts `config.credentials`. Rejected
33
+ records now count as failed. SNS works with `topicArn` alone and no longer
34
+ creates topics at start. `walkeros setup` resolves `$secret` values; partial
35
+ batch failures log their causes.
36
+ - 7e5e3de: A destination added at runtime now keeps the defaults its code ships,
37
+ such as a default `batch`, just like a destination configured at startup.
38
+ Values you pass in the destination config still win over those defaults, and a
39
+ `require` set in the code's defaults now gates the destination as well.
25
40
  - 74821ed: Simulate records every vendor call through one recorder, `observeEnv`
26
41
  from `@walkeros/core`, and runs offline: BigQuery, Data Manager and the
27
42
  Sheets, GCS and S3 stores reach the network through `env`. Client and `Env`
28
43
  types of BigQuery, Firehose, PostHog, SQS and Pub/Sub are structural.
29
44
  `@walkeros/cli` exports `resolveExportName` and `selectDevExamples` and drops
30
45
  `findExample` and `compareOutput`.
46
+ - e860006: `state` gains `mapping` to shape what a lookup returns or a write
47
+ stores, merged into the target. An undeclared `state.store`, or a `file: true`
48
+ store, is now a validation error in `walkeros validate` and deploy preflight;
49
+ at runtime the entry logs an error or is skipped with a warning. The s3 and
50
+ gcs stores report their `file` mode.
31
51
  - Updated dependencies [74821ed]
32
52
  - Updated dependencies [06b498a]
33
53
  - Updated dependencies [74821ed]
54
+ - Updated dependencies [64b06de]
55
+ - Updated dependencies [4b4937f]
34
56
  - Updated dependencies [74821ed]
35
57
  - Updated dependencies [74821ed]
36
58
  - Updated dependencies [74821ed]
@@ -40,9 +62,11 @@
40
62
  - Updated dependencies [74821ed]
41
63
  - Updated dependencies [74821ed]
42
64
  - Updated dependencies [74821ed]
65
+ - Updated dependencies [e860006]
43
66
  - Updated dependencies [74821ed]
44
67
  - Updated dependencies [74821ed]
45
- - @walkeros/core@4.7.0-next-1790722899482
68
+ - Updated dependencies [4f89234]
69
+ - @walkeros/core@4.7.0
46
70
 
47
71
  ## 4.6.1
48
72
 
package/dist/index.d.mts CHANGED
@@ -213,6 +213,146 @@ declare function resolveBreakerConfig(breaker: Destination.Config['breaker']): B
213
213
  */
214
214
  declare function isBreakerProbePermitted(breaker: BreakerState | undefined, now: number): boolean;
215
215
 
216
+ /**
217
+ * State-delivery event types: the reactive-state commands that bump
218
+ * `collector.stateVersion` (see handle.ts). These are the only deliveries
219
+ * subject to the per-subscriber high-water-mark + `allowed` gate. Lifecycle
220
+ * types (ready/run/session) and non-reactive config keep their own gating
221
+ * (onReady/onRun check `allowed`, onSession checks `session`).
222
+ */
223
+ declare function isStateDelivery(type: On.Types): boolean;
224
+ /**
225
+ * Is a recorded state CELL present (non-empty)? The single source of truth for
226
+ * "cell X has a value", shared by `isRequireSatisfied` (require gating) and
227
+ * `redeliverStateAtRun` (run-barrier re-delivery) so the presence semantics
228
+ * never drift between the two. PRESENCE, not grant: a denied consent
229
+ * (`{marketing:false}`) counts as present. Non-cell types return `false` here;
230
+ * their satisfaction (session/run/ready/arbitrary) is handled by the callers.
231
+ *
232
+ * Note: `globals` is seeded from `config.globalsStatic` at construction, so it
233
+ * reads present whenever a static global exists, before any `command('globals')`
234
+ * fires. That is intentional and presence-based.
235
+ */
236
+ declare function isStatePresent(collector: Collector.Instance, type: On.Types): boolean;
237
+ /**
238
+ * Predicate: is a `require` entry satisfied by the collector's CURRENT recorded
239
+ * state? This is the level-not-edge core of order-independent activation: a
240
+ * step's gate is checked against the present state, not against whether the
241
+ * required type fired before or after the step registered.
242
+ *
243
+ * Cell-backed types defer to `isStatePresent` (presence, not grant — the
244
+ * destination send-gate `getGrantedConsent` remains a separate concern).
245
+ * `run`/`ready` map to `allowed`. Any other type (including `session`) is
246
+ * satisfied once it has been broadcast (recorded in `seenEvents`), which also
247
+ * recovers a broadcast that fired before the requiring step registered.
248
+ *
249
+ * `session` deliberately uses the `seenEvents` path, not a cell check:
250
+ * `collector.session` is vestigial (never written), so gating on it would park
251
+ * a `require:["session"]` step forever. The session source signals via
252
+ * `command('session', …)`, which records `session` in `seenEvents`, so this
253
+ * keeps `session` order-independent like every other type.
254
+ */
255
+ declare function isRequireSatisfied(collector: Collector.Instance, type: On.Types): boolean;
256
+ /**
257
+ * Advance a subscriber's mark for a cell to that cell's current version after
258
+ * an invocation. Only the delivered cell's mark moves; other cells stay owed.
259
+ */
260
+ declare function setMark(collector: Collector.Instance, subscriber: object, type: On.Types): void;
261
+ /**
262
+ * A subscriber is invoked for a state delivery iff that CELL has advanced past
263
+ * its per-cell mark AND the collector is allowed. While `!allowed`, deliveries
264
+ * are deferred (not fired, mark not advanced) so the subscriber stays "owed".
265
+ */
266
+ declare function shouldDeliver(collector: Collector.Instance, subscriber: object, type: On.Types): boolean;
267
+ /**
268
+ * Open the cascade-tracking structure for the OUTERMOST top-level state command
269
+ * (or an init flush) and return a teardown. Nested commands emitted by
270
+ * reacting callbacks find `collector.cascade` already set and join it, so the
271
+ * counters are scoped to the originating command; the cascade is cleared when
272
+ * its last holder leaves. Re-entrancy is detected by the presence of
273
+ * `collector.cascade`.
274
+ *
275
+ * Assumes top-level state commands run serially on a given collector;
276
+ * concurrent overlapping state commands on one shared collector are not
277
+ * supported (web is serial; the server per-request path is event push, not
278
+ * state commands).
279
+ */
280
+ declare function enterCascade(collector: Collector.Instance): () => void;
281
+ /**
282
+ * Registers a callback for a specific event type.
283
+ *
284
+ * @param collector The walkerOS collector instance.
285
+ * @param type The type of the event to listen for.
286
+ * @param option The callback function or an array of callback functions.
287
+ */
288
+ declare function on(collector: Collector.Instance, type: On.Types, option: WalkerOS.SingleOrArray<On.Subscription>): Promise<void>;
289
+ /**
290
+ * Calls a destination's on() handler with proper context and waits for it to
291
+ * settle. Used by onApply() for live deliveries and by destinationInit() for
292
+ * flushing queued deliveries; both await it, so a handler's side effect (a
293
+ * vendor consent update, an SDK opt-out) lands before the destination's next
294
+ * push. The wait is bounded by the destination's `config.timeout`, the same
295
+ * window as a push.
296
+ *
297
+ * Returns whether the handler settled. A state delivery holds the destination
298
+ * while it runs, and keeps holding it when it does not settle:
299
+ * `pushToDestinations` then keeps its events in `queuePush` rather than
300
+ * sending them to a vendor whose consent state was not set. The hold clears
301
+ * once no state delivery to the destination is in flight and every present
302
+ * state cell has reached the handler.
303
+ *
304
+ * One state handler call runs per destination at a time, so the state the
305
+ * vendor applies last is always the newest. A state delivery that arrives
306
+ * while a call runs does not call the handler: its cell stays owed, and the
307
+ * current cells are delivered right after the running call ends. A call that
308
+ * timed out stays in flight until its handler settles; its late settle marks
309
+ * nothing, and the current cells, then the held events, follow from there.
310
+ * Deferring rather than waiting keeps a handler that issues a state command
311
+ * itself from waiting on its own call.
312
+ *
313
+ * A state delivery carries the command's delta when the destination has
314
+ * received every earlier change of that cell, and the whole cell otherwise
315
+ * (after a failed delivery, or when its mark trails by more than one change),
316
+ * so a settled delivery never marks content it did not carry.
317
+ */
318
+ declare function callDestinationOn(collector: Collector.Instance, destination: Destination.Instance, destId: string, type: On.Types, data: unknown): Promise<boolean>;
319
+ /**
320
+ * Fire a set of registered `on` callbacks against current collector state.
321
+ *
322
+ * Used by both `on()` (when registering a new callback, to fire it against
323
+ * current state) and `onApply()` (when dispatching a state-change command to
324
+ * every registered callback of that type). Separating this from `onApply`
325
+ * ensures `on()` does NOT trigger `onApply`'s source/destination broadcast,
326
+ * which would cause infinite recursion if a source's `on` handler registers
327
+ * another callback of the same type.
328
+ */
329
+ declare function fireCallbacks(collector: Collector.Instance, type: On.Types, options: Array<On.Subscription>, config?: unknown): void;
330
+ /**
331
+ * Run-barrier re-delivery. Called once from `runCollector` after the collector
332
+ * becomes `allowed` and the RunState merge has bumped `stateVersion` for any
333
+ * merged cells. Re-broadcasts each non-empty recorded state cell to its OWED
334
+ * subscribers (mark < stateVersion) exactly once, so reactions deferred while
335
+ * `!allowed` now emit into the open, consent-gated pipeline.
336
+ *
337
+ * Narrow path: it fires `collector.on` rules/fns via `fireCallbacks`, the
338
+ * gated `source.on` handlers via `deliverStateToSource`, and the gated
339
+ * destination `on` handlers via `deliverStateToDestination` (queued for an
340
+ * uninitialized destination's init flush). It deliberately skips the
341
+ * `require`-decrement and `queueOn`-flush machinery in `onApply` (those are
342
+ * live-command concerns). Exactly-once is free from the `shouldDeliver` gate:
343
+ * already-delivered subscribers (mark == stateVersion) are skipped.
344
+ */
345
+ declare function redeliverStateAtRun(collector: Collector.Instance): Promise<void>;
346
+ /**
347
+ * Applies all registered callbacks for a specific event type.
348
+ *
349
+ * @param collector The walkerOS collector instance.
350
+ * @param type The type of the event to apply the callbacks for.
351
+ * @param options The options for the callbacks.
352
+ * @param config The consent configuration.
353
+ */
354
+ declare function onApply(collector: Collector.Instance, type: On.Types, options?: Array<On.Subscription>, config?: unknown): Promise<boolean>;
355
+
216
356
  /**
217
357
  * Adds a new destination to the collector.
218
358
  *
@@ -337,119 +477,6 @@ declare function enrichEvent(collector: Collector.Instance, event: WalkerOS.Deep
337
477
  */
338
478
  declare function runCollector(collector: Collector.Instance, state?: RunState): Promise<Elb.PushResult>;
339
479
 
340
- /**
341
- * State-delivery event types: the reactive-state commands that bump
342
- * `collector.stateVersion` (see handle.ts). These are the only deliveries
343
- * subject to the per-subscriber high-water-mark + `allowed` gate. Lifecycle
344
- * types (ready/run/session) and non-reactive config keep their own gating
345
- * (onReady/onRun check `allowed`, onSession checks `session`).
346
- */
347
- declare function isStateDelivery(type: On.Types): boolean;
348
- /**
349
- * Is a recorded state CELL present (non-empty)? The single source of truth for
350
- * "cell X has a value", shared by `isRequireSatisfied` (require gating) and
351
- * `redeliverStateAtRun` (run-barrier re-delivery) so the presence semantics
352
- * never drift between the two. PRESENCE, not grant: a denied consent
353
- * (`{marketing:false}`) counts as present. Non-cell types return `false` here;
354
- * their satisfaction (session/run/ready/arbitrary) is handled by the callers.
355
- *
356
- * Note: `globals` is seeded from `config.globalsStatic` at construction, so it
357
- * reads present whenever a static global exists, before any `command('globals')`
358
- * fires. That is intentional and presence-based.
359
- */
360
- declare function isStatePresent(collector: Collector.Instance, type: On.Types): boolean;
361
- /**
362
- * Predicate: is a `require` entry satisfied by the collector's CURRENT recorded
363
- * state? This is the level-not-edge core of order-independent activation: a
364
- * step's gate is checked against the present state, not against whether the
365
- * required type fired before or after the step registered.
366
- *
367
- * Cell-backed types defer to `isStatePresent` (presence, not grant — the
368
- * destination send-gate `getGrantedConsent` remains a separate concern).
369
- * `run`/`ready` map to `allowed`. Any other type (including `session`) is
370
- * satisfied once it has been broadcast (recorded in `seenEvents`), which also
371
- * recovers a broadcast that fired before the requiring step registered.
372
- *
373
- * `session` deliberately uses the `seenEvents` path, not a cell check:
374
- * `collector.session` is vestigial (never written), so gating on it would park
375
- * a `require:["session"]` step forever. The session source signals via
376
- * `command('session', …)`, which records `session` in `seenEvents`, so this
377
- * keeps `session` order-independent like every other type.
378
- */
379
- declare function isRequireSatisfied(collector: Collector.Instance, type: On.Types): boolean;
380
- /**
381
- * Advance a subscriber's mark for a cell to that cell's current version after
382
- * an invocation. Only the delivered cell's mark moves; other cells stay owed.
383
- */
384
- declare function setMark(collector: Collector.Instance, subscriber: object, type: On.Types): void;
385
- /**
386
- * A subscriber is invoked for a state delivery iff that CELL has advanced past
387
- * its per-cell mark AND the collector is allowed. While `!allowed`, deliveries
388
- * are deferred (not fired, mark not advanced) so the subscriber stays "owed".
389
- */
390
- declare function shouldDeliver(collector: Collector.Instance, subscriber: object, type: On.Types): boolean;
391
- /**
392
- * Open the cascade-tracking structure for the OUTERMOST top-level state command
393
- * and return a teardown that clears it. Nested commands emitted by reacting
394
- * callbacks find `collector.cascade` already set and reuse it (teardown is a
395
- * no-op for them), so the counters are scoped to the originating command and
396
- * reset when it returns. Re-entrancy is detected by the presence of
397
- * `collector.cascade`.
398
- *
399
- * Assumes top-level state commands run serially on a given collector;
400
- * concurrent overlapping state commands on one shared collector are not
401
- * supported (web is serial; the server per-request path is event push, not
402
- * state commands).
403
- */
404
- declare function enterCascade(collector: Collector.Instance): () => void;
405
- /**
406
- * Registers a callback for a specific event type.
407
- *
408
- * @param collector The walkerOS collector instance.
409
- * @param type The type of the event to listen for.
410
- * @param option The callback function or an array of callback functions.
411
- */
412
- declare function on(collector: Collector.Instance, type: On.Types, option: WalkerOS.SingleOrArray<On.Subscription>): Promise<void>;
413
- /**
414
- * Calls a destination's on() handler with proper context.
415
- * Used by both onApply() for immediate calls and destinationInit() for flushing queued events.
416
- */
417
- declare function callDestinationOn(collector: Collector.Instance, destination: Destination.Instance, destId: string, type: On.Types, data: unknown): void;
418
- /**
419
- * Fire a set of registered `on` callbacks against current collector state.
420
- *
421
- * Used by both `on()` (when registering a new callback, to fire it against
422
- * current state) and `onApply()` (when dispatching a state-change command to
423
- * every registered callback of that type). Separating this from `onApply`
424
- * ensures `on()` does NOT trigger `onApply`'s source/destination broadcast,
425
- * which would cause infinite recursion if a source's `on` handler registers
426
- * another callback of the same type.
427
- */
428
- declare function fireCallbacks(collector: Collector.Instance, type: On.Types, options: Array<On.Subscription>, config?: unknown): void;
429
- /**
430
- * Run-barrier re-delivery. Called once from `runCollector` after the collector
431
- * becomes `allowed` and the RunState merge has bumped `stateVersion` for any
432
- * merged cells. Re-broadcasts each non-empty recorded state cell to its OWED
433
- * subscribers (mark < stateVersion) exactly once, so reactions deferred while
434
- * `!allowed` now emit into the open, consent-gated pipeline.
435
- *
436
- * Narrow path: it fires `collector.on` rules/fns via `fireCallbacks` and the
437
- * gated `source.on` loop via `deliverStateToSource`. It deliberately skips the
438
- * `require`-decrement and `queueOn`-flush machinery in `onApply` (those are
439
- * live-command concerns). Exactly-once is free from the `shouldDeliver` gate:
440
- * already-delivered subscribers (mark == stateVersion) are skipped.
441
- */
442
- declare function redeliverStateAtRun(collector: Collector.Instance): Promise<void>;
443
- /**
444
- * Applies all registered callbacks for a specific event type.
445
- *
446
- * @param collector The walkerOS collector instance.
447
- * @param type The type of the event to apply the callbacks for.
448
- * @param options The options for the callbacks.
449
- * @param config The consent configuration.
450
- */
451
- declare function onApply(collector: Collector.Instance, type: On.Types, options?: Array<On.Subscription>, config?: unknown): Promise<boolean>;
452
-
453
480
  /**
454
481
  * Flush a source's queueOn buffer. Called when the source becomes "started"
455
482
  * (config.init === true AND config.require is empty/absent). Idempotent:
@@ -459,7 +486,9 @@ declare function onApply(collector: Collector.Instance, type: On.Types, options?
459
486
  * A throw inside `source.on` is treated as a pipeline failure: log via the
460
487
  * scoped 'source' logger and increment `status.failed`. The flush itself
461
488
  * is walkerOS-orchestrated startup; the throw represents the source's
462
- * inability to consume a buffered state-change event.
489
+ * inability to consume a buffered state-change event. A handler that does
490
+ * not settle within the default destination timeout is logged the same way
491
+ * but not counted, matching the live delivery path.
463
492
  *
464
493
  * State-delivery entries (consent/user/globals/custom) are gated through the
465
494
  * same per-source high-water mark as the direct `onApply` broadcast: while
package/dist/index.d.ts CHANGED
@@ -213,6 +213,146 @@ declare function resolveBreakerConfig(breaker: Destination.Config['breaker']): B
213
213
  */
214
214
  declare function isBreakerProbePermitted(breaker: BreakerState | undefined, now: number): boolean;
215
215
 
216
+ /**
217
+ * State-delivery event types: the reactive-state commands that bump
218
+ * `collector.stateVersion` (see handle.ts). These are the only deliveries
219
+ * subject to the per-subscriber high-water-mark + `allowed` gate. Lifecycle
220
+ * types (ready/run/session) and non-reactive config keep their own gating
221
+ * (onReady/onRun check `allowed`, onSession checks `session`).
222
+ */
223
+ declare function isStateDelivery(type: On.Types): boolean;
224
+ /**
225
+ * Is a recorded state CELL present (non-empty)? The single source of truth for
226
+ * "cell X has a value", shared by `isRequireSatisfied` (require gating) and
227
+ * `redeliverStateAtRun` (run-barrier re-delivery) so the presence semantics
228
+ * never drift between the two. PRESENCE, not grant: a denied consent
229
+ * (`{marketing:false}`) counts as present. Non-cell types return `false` here;
230
+ * their satisfaction (session/run/ready/arbitrary) is handled by the callers.
231
+ *
232
+ * Note: `globals` is seeded from `config.globalsStatic` at construction, so it
233
+ * reads present whenever a static global exists, before any `command('globals')`
234
+ * fires. That is intentional and presence-based.
235
+ */
236
+ declare function isStatePresent(collector: Collector.Instance, type: On.Types): boolean;
237
+ /**
238
+ * Predicate: is a `require` entry satisfied by the collector's CURRENT recorded
239
+ * state? This is the level-not-edge core of order-independent activation: a
240
+ * step's gate is checked against the present state, not against whether the
241
+ * required type fired before or after the step registered.
242
+ *
243
+ * Cell-backed types defer to `isStatePresent` (presence, not grant — the
244
+ * destination send-gate `getGrantedConsent` remains a separate concern).
245
+ * `run`/`ready` map to `allowed`. Any other type (including `session`) is
246
+ * satisfied once it has been broadcast (recorded in `seenEvents`), which also
247
+ * recovers a broadcast that fired before the requiring step registered.
248
+ *
249
+ * `session` deliberately uses the `seenEvents` path, not a cell check:
250
+ * `collector.session` is vestigial (never written), so gating on it would park
251
+ * a `require:["session"]` step forever. The session source signals via
252
+ * `command('session', …)`, which records `session` in `seenEvents`, so this
253
+ * keeps `session` order-independent like every other type.
254
+ */
255
+ declare function isRequireSatisfied(collector: Collector.Instance, type: On.Types): boolean;
256
+ /**
257
+ * Advance a subscriber's mark for a cell to that cell's current version after
258
+ * an invocation. Only the delivered cell's mark moves; other cells stay owed.
259
+ */
260
+ declare function setMark(collector: Collector.Instance, subscriber: object, type: On.Types): void;
261
+ /**
262
+ * A subscriber is invoked for a state delivery iff that CELL has advanced past
263
+ * its per-cell mark AND the collector is allowed. While `!allowed`, deliveries
264
+ * are deferred (not fired, mark not advanced) so the subscriber stays "owed".
265
+ */
266
+ declare function shouldDeliver(collector: Collector.Instance, subscriber: object, type: On.Types): boolean;
267
+ /**
268
+ * Open the cascade-tracking structure for the OUTERMOST top-level state command
269
+ * (or an init flush) and return a teardown. Nested commands emitted by
270
+ * reacting callbacks find `collector.cascade` already set and join it, so the
271
+ * counters are scoped to the originating command; the cascade is cleared when
272
+ * its last holder leaves. Re-entrancy is detected by the presence of
273
+ * `collector.cascade`.
274
+ *
275
+ * Assumes top-level state commands run serially on a given collector;
276
+ * concurrent overlapping state commands on one shared collector are not
277
+ * supported (web is serial; the server per-request path is event push, not
278
+ * state commands).
279
+ */
280
+ declare function enterCascade(collector: Collector.Instance): () => void;
281
+ /**
282
+ * Registers a callback for a specific event type.
283
+ *
284
+ * @param collector The walkerOS collector instance.
285
+ * @param type The type of the event to listen for.
286
+ * @param option The callback function or an array of callback functions.
287
+ */
288
+ declare function on(collector: Collector.Instance, type: On.Types, option: WalkerOS.SingleOrArray<On.Subscription>): Promise<void>;
289
+ /**
290
+ * Calls a destination's on() handler with proper context and waits for it to
291
+ * settle. Used by onApply() for live deliveries and by destinationInit() for
292
+ * flushing queued deliveries; both await it, so a handler's side effect (a
293
+ * vendor consent update, an SDK opt-out) lands before the destination's next
294
+ * push. The wait is bounded by the destination's `config.timeout`, the same
295
+ * window as a push.
296
+ *
297
+ * Returns whether the handler settled. A state delivery holds the destination
298
+ * while it runs, and keeps holding it when it does not settle:
299
+ * `pushToDestinations` then keeps its events in `queuePush` rather than
300
+ * sending them to a vendor whose consent state was not set. The hold clears
301
+ * once no state delivery to the destination is in flight and every present
302
+ * state cell has reached the handler.
303
+ *
304
+ * One state handler call runs per destination at a time, so the state the
305
+ * vendor applies last is always the newest. A state delivery that arrives
306
+ * while a call runs does not call the handler: its cell stays owed, and the
307
+ * current cells are delivered right after the running call ends. A call that
308
+ * timed out stays in flight until its handler settles; its late settle marks
309
+ * nothing, and the current cells, then the held events, follow from there.
310
+ * Deferring rather than waiting keeps a handler that issues a state command
311
+ * itself from waiting on its own call.
312
+ *
313
+ * A state delivery carries the command's delta when the destination has
314
+ * received every earlier change of that cell, and the whole cell otherwise
315
+ * (after a failed delivery, or when its mark trails by more than one change),
316
+ * so a settled delivery never marks content it did not carry.
317
+ */
318
+ declare function callDestinationOn(collector: Collector.Instance, destination: Destination.Instance, destId: string, type: On.Types, data: unknown): Promise<boolean>;
319
+ /**
320
+ * Fire a set of registered `on` callbacks against current collector state.
321
+ *
322
+ * Used by both `on()` (when registering a new callback, to fire it against
323
+ * current state) and `onApply()` (when dispatching a state-change command to
324
+ * every registered callback of that type). Separating this from `onApply`
325
+ * ensures `on()` does NOT trigger `onApply`'s source/destination broadcast,
326
+ * which would cause infinite recursion if a source's `on` handler registers
327
+ * another callback of the same type.
328
+ */
329
+ declare function fireCallbacks(collector: Collector.Instance, type: On.Types, options: Array<On.Subscription>, config?: unknown): void;
330
+ /**
331
+ * Run-barrier re-delivery. Called once from `runCollector` after the collector
332
+ * becomes `allowed` and the RunState merge has bumped `stateVersion` for any
333
+ * merged cells. Re-broadcasts each non-empty recorded state cell to its OWED
334
+ * subscribers (mark < stateVersion) exactly once, so reactions deferred while
335
+ * `!allowed` now emit into the open, consent-gated pipeline.
336
+ *
337
+ * Narrow path: it fires `collector.on` rules/fns via `fireCallbacks`, the
338
+ * gated `source.on` handlers via `deliverStateToSource`, and the gated
339
+ * destination `on` handlers via `deliverStateToDestination` (queued for an
340
+ * uninitialized destination's init flush). It deliberately skips the
341
+ * `require`-decrement and `queueOn`-flush machinery in `onApply` (those are
342
+ * live-command concerns). Exactly-once is free from the `shouldDeliver` gate:
343
+ * already-delivered subscribers (mark == stateVersion) are skipped.
344
+ */
345
+ declare function redeliverStateAtRun(collector: Collector.Instance): Promise<void>;
346
+ /**
347
+ * Applies all registered callbacks for a specific event type.
348
+ *
349
+ * @param collector The walkerOS collector instance.
350
+ * @param type The type of the event to apply the callbacks for.
351
+ * @param options The options for the callbacks.
352
+ * @param config The consent configuration.
353
+ */
354
+ declare function onApply(collector: Collector.Instance, type: On.Types, options?: Array<On.Subscription>, config?: unknown): Promise<boolean>;
355
+
216
356
  /**
217
357
  * Adds a new destination to the collector.
218
358
  *
@@ -337,119 +477,6 @@ declare function enrichEvent(collector: Collector.Instance, event: WalkerOS.Deep
337
477
  */
338
478
  declare function runCollector(collector: Collector.Instance, state?: RunState): Promise<Elb.PushResult>;
339
479
 
340
- /**
341
- * State-delivery event types: the reactive-state commands that bump
342
- * `collector.stateVersion` (see handle.ts). These are the only deliveries
343
- * subject to the per-subscriber high-water-mark + `allowed` gate. Lifecycle
344
- * types (ready/run/session) and non-reactive config keep their own gating
345
- * (onReady/onRun check `allowed`, onSession checks `session`).
346
- */
347
- declare function isStateDelivery(type: On.Types): boolean;
348
- /**
349
- * Is a recorded state CELL present (non-empty)? The single source of truth for
350
- * "cell X has a value", shared by `isRequireSatisfied` (require gating) and
351
- * `redeliverStateAtRun` (run-barrier re-delivery) so the presence semantics
352
- * never drift between the two. PRESENCE, not grant: a denied consent
353
- * (`{marketing:false}`) counts as present. Non-cell types return `false` here;
354
- * their satisfaction (session/run/ready/arbitrary) is handled by the callers.
355
- *
356
- * Note: `globals` is seeded from `config.globalsStatic` at construction, so it
357
- * reads present whenever a static global exists, before any `command('globals')`
358
- * fires. That is intentional and presence-based.
359
- */
360
- declare function isStatePresent(collector: Collector.Instance, type: On.Types): boolean;
361
- /**
362
- * Predicate: is a `require` entry satisfied by the collector's CURRENT recorded
363
- * state? This is the level-not-edge core of order-independent activation: a
364
- * step's gate is checked against the present state, not against whether the
365
- * required type fired before or after the step registered.
366
- *
367
- * Cell-backed types defer to `isStatePresent` (presence, not grant — the
368
- * destination send-gate `getGrantedConsent` remains a separate concern).
369
- * `run`/`ready` map to `allowed`. Any other type (including `session`) is
370
- * satisfied once it has been broadcast (recorded in `seenEvents`), which also
371
- * recovers a broadcast that fired before the requiring step registered.
372
- *
373
- * `session` deliberately uses the `seenEvents` path, not a cell check:
374
- * `collector.session` is vestigial (never written), so gating on it would park
375
- * a `require:["session"]` step forever. The session source signals via
376
- * `command('session', …)`, which records `session` in `seenEvents`, so this
377
- * keeps `session` order-independent like every other type.
378
- */
379
- declare function isRequireSatisfied(collector: Collector.Instance, type: On.Types): boolean;
380
- /**
381
- * Advance a subscriber's mark for a cell to that cell's current version after
382
- * an invocation. Only the delivered cell's mark moves; other cells stay owed.
383
- */
384
- declare function setMark(collector: Collector.Instance, subscriber: object, type: On.Types): void;
385
- /**
386
- * A subscriber is invoked for a state delivery iff that CELL has advanced past
387
- * its per-cell mark AND the collector is allowed. While `!allowed`, deliveries
388
- * are deferred (not fired, mark not advanced) so the subscriber stays "owed".
389
- */
390
- declare function shouldDeliver(collector: Collector.Instance, subscriber: object, type: On.Types): boolean;
391
- /**
392
- * Open the cascade-tracking structure for the OUTERMOST top-level state command
393
- * and return a teardown that clears it. Nested commands emitted by reacting
394
- * callbacks find `collector.cascade` already set and reuse it (teardown is a
395
- * no-op for them), so the counters are scoped to the originating command and
396
- * reset when it returns. Re-entrancy is detected by the presence of
397
- * `collector.cascade`.
398
- *
399
- * Assumes top-level state commands run serially on a given collector;
400
- * concurrent overlapping state commands on one shared collector are not
401
- * supported (web is serial; the server per-request path is event push, not
402
- * state commands).
403
- */
404
- declare function enterCascade(collector: Collector.Instance): () => void;
405
- /**
406
- * Registers a callback for a specific event type.
407
- *
408
- * @param collector The walkerOS collector instance.
409
- * @param type The type of the event to listen for.
410
- * @param option The callback function or an array of callback functions.
411
- */
412
- declare function on(collector: Collector.Instance, type: On.Types, option: WalkerOS.SingleOrArray<On.Subscription>): Promise<void>;
413
- /**
414
- * Calls a destination's on() handler with proper context.
415
- * Used by both onApply() for immediate calls and destinationInit() for flushing queued events.
416
- */
417
- declare function callDestinationOn(collector: Collector.Instance, destination: Destination.Instance, destId: string, type: On.Types, data: unknown): void;
418
- /**
419
- * Fire a set of registered `on` callbacks against current collector state.
420
- *
421
- * Used by both `on()` (when registering a new callback, to fire it against
422
- * current state) and `onApply()` (when dispatching a state-change command to
423
- * every registered callback of that type). Separating this from `onApply`
424
- * ensures `on()` does NOT trigger `onApply`'s source/destination broadcast,
425
- * which would cause infinite recursion if a source's `on` handler registers
426
- * another callback of the same type.
427
- */
428
- declare function fireCallbacks(collector: Collector.Instance, type: On.Types, options: Array<On.Subscription>, config?: unknown): void;
429
- /**
430
- * Run-barrier re-delivery. Called once from `runCollector` after the collector
431
- * becomes `allowed` and the RunState merge has bumped `stateVersion` for any
432
- * merged cells. Re-broadcasts each non-empty recorded state cell to its OWED
433
- * subscribers (mark < stateVersion) exactly once, so reactions deferred while
434
- * `!allowed` now emit into the open, consent-gated pipeline.
435
- *
436
- * Narrow path: it fires `collector.on` rules/fns via `fireCallbacks` and the
437
- * gated `source.on` loop via `deliverStateToSource`. It deliberately skips the
438
- * `require`-decrement and `queueOn`-flush machinery in `onApply` (those are
439
- * live-command concerns). Exactly-once is free from the `shouldDeliver` gate:
440
- * already-delivered subscribers (mark == stateVersion) are skipped.
441
- */
442
- declare function redeliverStateAtRun(collector: Collector.Instance): Promise<void>;
443
- /**
444
- * Applies all registered callbacks for a specific event type.
445
- *
446
- * @param collector The walkerOS collector instance.
447
- * @param type The type of the event to apply the callbacks for.
448
- * @param options The options for the callbacks.
449
- * @param config The consent configuration.
450
- */
451
- declare function onApply(collector: Collector.Instance, type: On.Types, options?: Array<On.Subscription>, config?: unknown): Promise<boolean>;
452
-
453
480
  /**
454
481
  * Flush a source's queueOn buffer. Called when the source becomes "started"
455
482
  * (config.init === true AND config.require is empty/absent). Idempotent:
@@ -459,7 +486,9 @@ declare function onApply(collector: Collector.Instance, type: On.Types, options?
459
486
  * A throw inside `source.on` is treated as a pipeline failure: log via the
460
487
  * scoped 'source' logger and increment `status.failed`. The flush itself
461
488
  * is walkerOS-orchestrated startup; the throw represents the source's
462
- * inability to consume a buffered state-change event.
489
+ * inability to consume a buffered state-change event. A handler that does
490
+ * not settle within the default destination timeout is logged the same way
491
+ * but not counted, matching the live delivery path.
463
492
  *
464
493
  * State-delivery entries (consent/user/globals/custom) are gated through the
465
494
  * same per-source high-water mark as the direct `onApply` broadcast: while