@rotorsoft/act 1.32.14 → 1.32.15

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.
Files changed (72) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +98 -152
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/adapters/in-memory-store.d.ts +3 -3
  5. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  6. package/dist/@types/builders/act-builder.d.ts +3 -3
  7. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  8. package/dist/@types/builders/build-classify.d.ts +1 -1
  9. package/dist/@types/builders/builder-base.d.ts +3 -3
  10. package/dist/@types/builders/builder-utils.d.ts +1 -1
  11. package/dist/@types/builders/event-builder.d.ts +1 -1
  12. package/dist/@types/builders/merge.d.ts +1 -1
  13. package/dist/@types/builders/reaction-builder.d.ts +1 -1
  14. package/dist/@types/builders/slice-builder.d.ts +2 -2
  15. package/dist/@types/builders/state-builder.d.ts +3 -4
  16. package/dist/@types/builders/state-builder.d.ts.map +1 -1
  17. package/dist/@types/csv.d.ts +1 -1
  18. package/dist/@types/disposers.d.ts.map +1 -1
  19. package/dist/@types/internal/audit.d.ts +12 -42
  20. package/dist/@types/internal/audit.d.ts.map +1 -1
  21. package/dist/@types/internal/autoclose-policy.d.ts +3 -3
  22. package/dist/@types/internal/autoclose-reaction.d.ts +2 -2
  23. package/dist/@types/internal/autoclose-window.d.ts +1 -1
  24. package/dist/@types/internal/close-cycle.d.ts +10 -31
  25. package/dist/@types/internal/close-cycle.d.ts.map +1 -1
  26. package/dist/@types/internal/close-signal.d.ts +3 -3
  27. package/dist/@types/internal/config.d.ts +3 -3
  28. package/dist/@types/internal/config.d.ts.map +1 -1
  29. package/dist/@types/internal/correlate-cycle.d.ts +39 -86
  30. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
  31. package/dist/@types/internal/correlator.d.ts +1 -1
  32. package/dist/@types/internal/date-reviver.d.ts +1 -1
  33. package/dist/@types/internal/defer-config.d.ts +2 -2
  34. package/dist/@types/internal/defer-signal.d.ts +2 -2
  35. package/dist/@types/internal/defer-timer.d.ts +3 -3
  36. package/dist/@types/internal/drain-cycle.d.ts +35 -82
  37. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  38. package/dist/@types/internal/event-sourcing.d.ts +8 -19
  39. package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
  40. package/dist/@types/internal/event-versions.d.ts +1 -1
  41. package/dist/@types/internal/projection-fold.d.ts +2 -2
  42. package/dist/@types/internal/report-once.d.ts +3 -3
  43. package/dist/@types/internal/sensitive.d.ts +2 -2
  44. package/dist/@types/internal/settle.d.ts +6 -19
  45. package/dist/@types/internal/settle.d.ts.map +1 -1
  46. package/dist/@types/ports.d.ts +3 -3
  47. package/dist/@types/scoped.d.ts +6 -6
  48. package/dist/@types/scoped.d.ts.map +1 -1
  49. package/dist/@types/types/action.d.ts +19 -19
  50. package/dist/@types/types/audit.d.ts +1 -1
  51. package/dist/@types/types/ports.d.ts +22 -26
  52. package/dist/@types/types/ports.d.ts.map +1 -1
  53. package/dist/@types/types/reaction.d.ts +8 -8
  54. package/dist/@types/types/registry.d.ts +1 -1
  55. package/dist/@types/types/schemas.d.ts +2 -2
  56. package/dist/@types/utils.d.ts +1 -1
  57. package/dist/{chunk-FVJFR7GH.js → chunk-JRTZGWVS.js} +1 -1
  58. package/dist/chunk-JRTZGWVS.js.map +1 -0
  59. package/dist/{chunk-JPPO3LZ3.js → chunk-PZP5ZEZ4.js} +9 -9
  60. package/dist/chunk-PZP5ZEZ4.js.map +1 -0
  61. package/dist/index.cjs +136 -358
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.js +131 -353
  64. package/dist/index.js.map +1 -1
  65. package/dist/test/index.cjs +7 -7
  66. package/dist/test/index.cjs.map +1 -1
  67. package/dist/test/index.js +2 -2
  68. package/dist/types/index.cjs.map +1 -1
  69. package/dist/types/index.js +1 -1
  70. package/package.json +1 -1
  71. package/dist/chunk-FVJFR7GH.js.map +0 -1
  72. package/dist/chunk-JPPO3LZ3.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -635,12 +635,12 @@ var InMemoryStream = class {
635
635
  _leased_until = void 0;
636
636
  _priority = 0;
637
637
  _lane = DEFAULT_LANE;
638
- // Persisted next-visit time (#1090). When set and still in the future, the
638
+ // Persisted next-visit time. When set and still in the future, the
639
639
  // stream is held out of `claim` entirely — so a deferred reaction is not
640
640
  // re-claimed (and `retry` is never bumped) until its due-time passes. Unlike
641
641
  // in-process backoff, this is durable store state shared across workers.
642
642
  _deferred_at = void 0;
643
- // Work mark (#1485): highest event id observed to resolve to this target.
643
+ // Work mark: highest event id observed to resolve to this target.
644
644
  // `undefined` means UNKNOWN — the row predates the mark, so `claim` falls
645
645
  // back to the legacy has-work probe rather than treating it as "no work".
646
646
  _correlated_at = void 0;
@@ -686,7 +686,7 @@ var InMemoryStream = class {
686
686
  this._priority = priority;
687
687
  }
688
688
  get is_available() {
689
- return !this._blocked && (!this._leased_until || this._leased_until <= /* @__PURE__ */ new Date()) && // A stream deferred to a future time is not claimable until due (#1090).
689
+ return !this._blocked && (!this._leased_until || this._leased_until <= /* @__PURE__ */ new Date()) && // A stream deferred to a future time is not claimable until due.
690
690
  (!this._deferred_at || this._deferred_at <= Date.now());
691
691
  }
692
692
  /**
@@ -716,7 +716,7 @@ var InMemoryStream = class {
716
716
  get leased_until() {
717
717
  return this._leased_until;
718
718
  }
719
- /** Persisted next-visit time (#1090/#1221), or undefined when no active defer. */
719
+ /** Persisted next-visit time, or undefined when no active defer. */
720
720
  get deferred_at() {
721
721
  return this._deferred_at;
722
722
  }
@@ -831,16 +831,16 @@ var InMemoryStore = class {
831
831
  _next_id = 0;
832
832
  // stored stream positions and other metadata
833
833
  _streams = /* @__PURE__ */ new Map();
834
- /** Correlate checkpoint (#1484): how far the log has been READ. */
834
+ /** Correlate checkpoint: how far the log has been READ. */
835
835
  _correlated_at = -1;
836
836
  /**
837
- * Per-correlator checkpoint and lease (#1532), keyed by correlator.
837
+ * Per-correlator checkpoint and lease, keyed by correlator.
838
838
  *
839
839
  * Keyed rather than singular because correlators that look for different
840
840
  * things read the log for different reasons: sharing one position lets a
841
841
  * partial-behaviour worker inherit another's, and sharing one lease lets
842
842
  * one starve the other. Callers that supply no correlator use
843
- * `_correlated_at` instead, which is the pre-#1532 behaviour.
843
+ * `_correlated_at` instead, the shared checkpoint.
844
844
  */
845
845
  _correlators = /* @__PURE__ */ new Map();
846
846
  // last committed version per stream — O(1) replacement for filter-on-commit
@@ -2470,7 +2470,7 @@ var CloseSignal = class extends Error {
2470
2470
  */
2471
2471
  at;
2472
2472
  /**
2473
- * Windowed close (#1011): prune events older than this cutoff behind
2473
+ * Windowed close: prune events older than this cutoff behind
2474
2474
  * the closest safe snapshot instead of retiring the stream. Thrown by
2475
2475
  * the autoclose reaction of a `.autocloses({ keep })` state; flows
2476
2476
  * into {@link CloseTarget.before}. Omitted → a full close.
@@ -2548,7 +2548,7 @@ var SettleOptionsSchema = DrainOptionsSchema.extend({
2548
2548
  // rejects `±Infinity`, and an integer check cannot pass it either. Wrapper
2549
2549
  // code normalizing an optional cap (`maxPasses: opts.maxPasses ?? Infinity`)
2550
2550
  // is the natural way to hit it. Accepting it also honors this module's own
2551
- // rule that a value which works today is never newly rejected (#1711).
2551
+ // rule that a value which works today is never newly rejected.
2552
2552
  maxPasses: import_zod6.z.union([import_zod6.z.number().int().min(0), import_zod6.z.literal(Number.POSITIVE_INFINITY)]).optional()
2553
2553
  }).loose();
2554
2554
  function resolveSettleConfig(options) {
@@ -3190,7 +3190,7 @@ var CorrelateCycle = class {
3190
3190
  _checkpoint = -1;
3191
3191
  _initialized = false;
3192
3192
  /**
3193
- * This worker's identity for the correlation lease (#1532). A per-instance
3193
+ * This worker's identity for the correlation lease. A per-instance
3194
3194
  * UUID, matching the drain's convention, so a renewal is recognised as the
3195
3195
  * same holder and a restarted process never inherits a stale claim.
3196
3196
  */
@@ -3206,24 +3206,15 @@ var CorrelateCycle = class {
3206
3206
  * When this worker's correlation lease runs out, as a local clock reading,
3207
3207
  * or 0 when it holds none.
3208
3208
  *
3209
- * Asking the store on every pass costs a round trip that the holder — which
3210
- * is the *only* worker in a single-node deployment, and the steady-state
3211
- * one everywhere else — gains nothing from: it already knows the answer.
3212
- * The act-sqlite perf gate caught that as a 1.5x regression on
3213
- * correlate+drain, which is the shape an embedded app runs constantly.
3214
- *
3215
- * Believing this while the store disagrees is safe in the one direction it
3216
- * can fail. A worker that scans without really holding the lease produces
3217
- * the duplicate scan that existed before the lease, and the marks are
3218
- * idempotent — so a stale belief costs work, never correctness.
3209
+ * Cached so the holder doesn't ask the store on every pass. A stale belief
3210
+ * can only cause a duplicate scan, and marks are idempotent, so it costs
3211
+ * work, never correctness.
3219
3212
  */
3220
3213
  _lease_until = 0;
3221
3214
  /**
3222
- * Whether a scan might find anything. The drain has carried the same flag
3223
- * since it was written — a commit raises it, an empty claim lowers it, and
3224
- * a disarmed drain returns without touching the store. Correlate had no
3225
- * equivalent, so a settle pass always scanned, including the final pass
3226
- * whose only job is to confirm nothing changed (#1510).
3215
+ * Whether a scan might find anything, like the drain's flag: a commit or
3216
+ * notification raises it, a short page lowers it, and a disarmed scan
3217
+ * returns without touching the store.
3227
3218
  *
3228
3219
  * Starts armed: the log may already hold events this process has never
3229
3220
  * correlated, and only a scan can find out.
@@ -3232,15 +3223,9 @@ var CorrelateCycle = class {
3232
3223
  /** In-flight init, memoized for single-flight and cleared on failure. */
3233
3224
  _init_promise;
3234
3225
  // Dynamically discovered targets → what each was last subscribed at,
3235
- // bounded by `maxSubscribedStreams`. The static half lives in
3236
- // `_static_subscriptions` below, which is deliberately not evictable.
3237
- //
3238
- // Every scan re-subscribes the
3239
- // targets it resolved (that is how the work mark lands), so this no longer
3240
- // decides *whether* a target is sent — it decides *what* is sent with it:
3241
- // a resolution raises priority/lane only when it beats the recorded floor,
3242
- // and otherwise re-sends the row's own values so the mark changes nothing
3243
- // else. See {@link Subscription}.
3226
+ // bounded by `maxSubscribedStreams`. It decides *what* a scan sends with a
3227
+ // target: priority/lane only when the resolution beats the recorded floor,
3228
+ // otherwise the row's own values. See {@link Subscription}.
3244
3229
  _dynamic_subscriptions;
3245
3230
  /**
3246
3231
  * What each static target was subscribed at by `init`. A plain map, never
@@ -3248,14 +3233,8 @@ var CorrelateCycle = class {
3248
3233
  * is already bounded by the registry and costs nothing the registry does
3249
3234
  * not already hold.
3250
3235
  *
3251
- * Keeping these out of the LRU is what makes the `+Infinity` floor an
3252
- * invariant rather than a race (#1582). Sharing the bounded map meant a
3253
- * churn of dynamic targets could evict a static record, and the next
3254
- * dynamic resolution to that target found no record, took the
3255
- * first-discovery branch, and re-subscribed the target with its own
3256
- * priority and lane — silently re-laning a stream whose lane the
3257
- * build-time subscribe owns, and starving it wherever `onlyLanes` had
3258
- * provisioned a worker for the declared lane.
3236
+ * Kept out of the LRU so eviction can never drop a static target's
3237
+ * `+Infinity` floor and let a dynamic resolution re-lane it.
3259
3238
  */
3260
3239
  _static_subscriptions = /* @__PURE__ */ new Map();
3261
3240
  /** Compiled pattern sources, bounded by {@link PATTERN_CACHE_SIZE}. */
@@ -3265,17 +3244,13 @@ var CorrelateCycle = class {
3265
3244
  _cd;
3266
3245
  _on_init;
3267
3246
  /**
3268
- * Async cold-start hook (#1221). Runs once, after the sync `on_init`,
3269
- * inside the same `init()` await. The orchestrator uses it to re-seed the
3270
- * process-local defer timers from the store's persisted `deferred_at` so
3271
- * an idle deferred stream re-arms its drain across a restart. Kept
3272
- * separate from `on_init` because seeding is an async store read; `init`
3273
- * already awaits, so folding it in here preserves the "runs exactly once"
3274
- * guarantee without a second gate on the Act side.
3247
+ * Async cold-start hook, run once after `on_init` inside `init()`. The
3248
+ * orchestrator re-seeds its defer timers from the persisted `deferred_at`
3249
+ * here, so an idle deferred stream re-arms across a restart.
3275
3250
  */
3276
3251
  _on_init_async;
3277
3252
  /**
3278
- * Tail re-scan window applied to the cold-start checkpoint (ACT-1207).
3253
+ * Tail re-scan window applied to the cold-start checkpoint.
3279
3254
  * See {@link DEFAULT_COLD_START_BACK_SCAN}. Constructor arg (not a
3280
3255
  * public option) so tests can shrink it; defaults otherwise.
3281
3256
  */
@@ -3327,7 +3302,7 @@ var CorrelateCycle = class {
3327
3302
  * - Reads the durable correlate checkpoint (and max(at)) from the store,
3328
3303
  * flooring a first boot at `watermark - back_scan` so an event
3329
3304
  * committed-but-not-correlated before a crash is re-scanned on
3330
- * restart instead of skipped (ACT-1207)
3305
+ * restart instead of skipped
3331
3306
  * - Subscribes static resolver targets (idempotent upsert)
3332
3307
  * - Populates the subscribed-streams LRU
3333
3308
  * - Fires `on_init` once (Act uses this to flag a cold-start drain)
@@ -3358,21 +3333,6 @@ var CorrelateCycle = class {
3358
3333
  }
3359
3334
  await this._on_init_async?.();
3360
3335
  }
3361
- /**
3362
- * Forget targets whose subscription rows no longer exist, so a later
3363
- * scan can re-subscribe them.
3364
- *
3365
- * A full close deletes the closed stream's subscription row. The
3366
- * in-process dedup would otherwise still believe the target is
3367
- * subscribed and never re-issue `subscribe()`, silently stopping
3368
- * delivery for any reaction whose target is named after the stream —
3369
- * the documented per-aggregate shape `.to(e => ({target: e.stream}))`
3370
- * makes those two namespaces collide by construction (#1398).
3371
- *
3372
- * Static targets are left alone: their record lives in
3373
- * `_static_subscriptions`, which this never touches, so they stay pinned
3374
- * at +Infinity and the dynamic path never re-opens them.
3375
- */
3376
3336
  /**
3377
3337
  * Start correlation over after the event log was replaced wholesale
3378
3338
  * (`restore`). The restored log is renumbered from the start and its
@@ -3381,7 +3341,7 @@ var CorrelateCycle = class {
3381
3341
  * and the init latch makes the next pass run cold-start again: static
3382
3342
  * targets are re-subscribed, the checkpoint is re-read from the store
3383
3343
  * (which `restore` reset), and dynamic targets are rediscovered by the
3384
- * scan (#1772).
3344
+ * scan.
3385
3345
  */
3386
3346
  restart() {
3387
3347
  this._initialized = false;
@@ -3391,6 +3351,11 @@ var CorrelateCycle = class {
3391
3351
  this._static_subscriptions.clear();
3392
3352
  this._armed = true;
3393
3353
  }
3354
+ /**
3355
+ * Forget dynamic targets whose subscription rows no longer exist (a full
3356
+ * close deletes the row), so a later scan re-subscribes them. Static
3357
+ * targets keep their records.
3358
+ */
3394
3359
  forget_subscribed(streams) {
3395
3360
  for (const stream of streams) this._dynamic_subscriptions.delete(stream);
3396
3361
  }
@@ -3415,7 +3380,7 @@ var CorrelateCycle = class {
3415
3380
  * Scan the events past the checkpoint, resolve each to its target
3416
3381
  * streams, and record what it found through `cd.subscribe` — new dynamic
3417
3382
  * targets get registered, and every target an event resolved to gets its
3418
- * **work mark** raised to that event's id (#1487).
3383
+ * **work mark** raised to that event's id.
3419
3384
  *
3420
3385
  * Both resolver kinds are walked. A static target is already subscribed
3421
3386
  * at init, but marking it is what makes it claimable without probing the
@@ -3502,18 +3467,10 @@ var CorrelateCycle = class {
3502
3467
  }
3503
3468
  }
3504
3469
  },
3505
- // Decline the sensitive payload: this scan reads `name`/`stream`/`id`
3506
- // to resolve reaction targets and throws the rest away. Asking for a
3507
- // payload it discards made one unreadable row stop EVERY stream's
3508
- // reactions — correlate is the sole producer of the work mark, so a
3509
- // decrypt failure here strands the whole app with nothing blocked and
3510
- // nothing naming the row (#1675).
3511
- //
3512
- // A dynamic `.to(event => …)` resolver therefore sees `pii: null`.
3513
- // That is deliberate and is itself a fix: correlate runs actor-less,
3514
- // so handing a resolver decrypted plaintext is un-gated disclosure —
3515
- // the defect #1673 corrected on the drain return and #1277 before it.
3516
- // `data` already carries no sensitive keys; nothing merges them here.
3470
+ // Decline the sensitive payload: the scan only needs name/stream/id,
3471
+ // and one undecryptable row would otherwise stop every stream's
3472
+ // reactions. Resolvers therefore see `pii: null`; correlate runs
3473
+ // actor-less, so plaintext here would be un-gated disclosure.
3517
3474
  { ...query, after, with_pii: false }
3518
3475
  );
3519
3476
  const streams = [];
@@ -3557,18 +3514,9 @@ var CorrelateCycle = class {
3557
3514
  /**
3558
3515
  * Hand the correlation lease back early.
3559
3516
  *
3560
- * There is no release verb on the port, deliberately — expiry is the only
3561
- * path, which keeps a crash and a clean stop on the same code path. A
3562
- * holder can still shorten its own lease, because re-acquiring as the same
3563
- * holder renews, and renewing to a millisecond is a release in all but
3564
- * name.
3565
- *
3566
- * Without this a worker that stops cleanly still blocks discovery for the
3567
- * rest of its lease — invisible in a long-lived deployment, very visible
3568
- * anywhere Acts are created and dropped inside one process.
3569
- *
3570
- * Best-effort: failing here costs the lease's remaining lifetime, which is
3571
- * what would have happened had the process died instead.
3517
+ * The port has no release verb; re-acquiring as the same holder with a
3518
+ * zero duration releases it. Best-effort: a failure costs the lease's
3519
+ * remaining lifetime, as a crash would.
3572
3520
  */
3573
3521
  async release_correlation() {
3574
3522
  try {
@@ -4054,26 +4002,11 @@ async function load(me, target, callback, patch_fn = bare_patch) {
4054
4002
  {
4055
4003
  stream,
4056
4004
  stream_exact: true,
4057
- // The snapshot resume floor is a current-state optimization: it only
4058
- // holds when the load has no window of its own. `time_travel` already
4059
- // captures that (any `asOf` bound set), so request `with_snaps` only for
4060
- // a non-time-travel cold load — a bounded load full-scans real events
4061
- // under its `asOf` filter. This is the single floor-eligibility decision
4062
- // for the whole system; the stores apply the floor whenever asked and
4063
- // never re-derive it (RFC 1274).
4064
- //
4065
- // The warm path resumes from `after`, and MUST also carry `with_snaps`
4066
- // (#1345): `after` and `with_snaps` are independent store conditions —
4067
- // `after` bounds the scan (id > cached.event_id), `with_snaps` keeps
4068
- // `__snapshot__` rows in the result. A stale (lagging/cross-process)
4069
- // cache checkpoint can sit below a newer `__snapshot__` boundary, and a
4070
- // windowed close (`app.close`/`.autocloses({keep})`) may have pruned the
4071
- // domain events between the checkpoint and that snapshot. Without
4072
- // `with_snaps` the rebaselining snapshot is filtered out and the fold
4073
- // silently applies the surviving tail on top of stale state (wrong
4074
- // count, yet `version` still reports the true head — the concurrency
4075
- // guard passes). With it, the snapshot in the after-window rebaselines
4076
- // the fold; when no snapshot falls in the window it is a no-op.
4005
+ // `with_snaps` on every non-time-travel load. Cold, it resumes from the
4006
+ // latest snapshot (this is the only place that decides it; stores just
4007
+ // apply it). Warm, it keeps a snapshot above a stale checkpoint in the
4008
+ // result, so a windowed close that pruned the events in between can't
4009
+ // make the fold apply the tail onto stale state.
4077
4010
  ...cached ? { after: cached.event_id, with_snaps: true } : { ...time_travel ? {} : { with_snaps: true }, ...asOf }
4078
4011
  }
4079
4012
  );
@@ -4100,7 +4033,7 @@ async function load(me, target, callback, patch_fn = bare_patch) {
4100
4033
  // Head event id, captured atomically with `state`: the last replayed
4101
4034
  // event's id on a cache miss, or the cached checkpoint's event_id on a
4102
4035
  // warm hit with no new events. Consumers read this instead of a
4103
- // separate cache lookup that could race a concurrent commit (ACT-1204).
4036
+ // separate cache lookup that could race a concurrent commit.
4104
4037
  id: event?.id ?? cached?.event_id ?? -1,
4105
4038
  patches,
4106
4039
  snaps,
@@ -4178,14 +4111,8 @@ async function action(me, action2, target, payload, options, patch_fn = bare_pat
4178
4111
  stream,
4179
4112
  emitted,
4180
4113
  meta,
4181
- // Reactions skip the INFERRED guard: they always append against the
4182
- // current head. Stream leasing already serializes concurrent reactions,
4183
- // and forcing version checks here would turn ordinary catch-up into
4184
- // spurious retries. An expectedVersion the caller passed explicitly is
4185
- // still honored — dropping a guard the caller asked for is silent data
4186
- // loss, and the reaction context can reach further than the handler
4187
- // (detached timers, settle cycles) where the caller never intended a
4188
- // reaction's semantics at all.
4114
+ // Reactions skip the inferred version guard (leases already
4115
+ // serialize them); an explicit expectedVersion is still honored.
4189
4116
  reactingTo ? expectedVersion : expected
4190
4117
  );
4191
4118
  } catch (error) {
@@ -4561,32 +4488,25 @@ var DrainController = class {
4561
4488
  _locked = false;
4562
4489
  _ratio = 0.5;
4563
4490
  /**
4564
- * Per-stream re-visit schedule (#1090): `stream → next visit` (ms since
4565
- * epoch). Holds both retry backoff (`HandleResult.next_attempt_at`) and the
4566
- * `defer` outcome; cleared on successful ack or terminal block. Lives in
4567
- * process memory — per-worker pacing by design (see {@link BackoffOptions}
4568
- * for the multi-worker trade-off). Its wake re-arms drain at the earliest
4569
- * pending visit.
4491
+ * Local wake for streams this worker parked (backoff or defer). The
4492
+ * schedule itself is persisted in the store; this only re-arms the drain
4493
+ * at the earliest pending visit.
4570
4494
  */
4571
4495
  _defer = new DeferTimer(() => {
4572
4496
  this._armed = true;
4573
4497
  });
4574
- /** Worker timer (ACT-1103). Set when `start()` is active, undefined otherwise. */
4498
+ /** Worker timer. Set when `start()` is active, undefined otherwise. */
4575
4499
  _worker;
4576
4500
  /**
4577
- * Misroutings this controller has reported (#1563). A resolver returning a
4501
+ * Misroutings this controller has reported. A resolver returning a
4578
4502
  * projection's target does so for every matching event; one line per event
4579
4503
  * would bury the signal it exists to raise.
4580
4504
  */
4581
4505
  _misrouted = /* @__PURE__ */ new Set();
4582
4506
  _stopped = false;
4583
4507
  /**
4584
- * Resolves when the cycle currently in flight finishes; `undefined` when
4585
- * no cycle is running (#1442). `_locked` answers "is a cycle running?" for
4586
- * the overlap guard; this answers "tell me when it is done" for a graceful
4587
- * shutdown, which needs to await the handler rather than abandon it
4588
- * mid-`await` with the stream still leased. Never rejects — `drain()`
4589
- * contains its own errors — so awaiting it is always safe.
4508
+ * Resolves when the cycle in flight finishes, so a graceful shutdown can
4509
+ * wait for it. Never rejects.
4590
4510
  */
4591
4511
  _inflight;
4592
4512
  _inflight_done;
@@ -4603,16 +4523,9 @@ var DrainController = class {
4603
4523
  this._armed = true;
4604
4524
  }
4605
4525
  /**
4606
- * Re-seed a persisted defer schedule into the process-local timer at cold
4607
- * start (#1221). The `_defer` map lives in worker memory and is empty
4608
- * after a restart; a stream deferred to a future due-time (e.g. an idle
4609
- * autoclose aggregate) is durable in the store's `deferred_at` but has
4610
- * nothing in memory to re-arm the drain at the due-time. The orchestrator
4611
- * reads the persisted `deferred_at` for this controller's lane and calls
4612
- * this to park the stream + (re)schedule the shared wake — so the drain
4613
- * re-arms at the due-time with no intervening commit. `schedule()`
4614
- * collapses many seeds into one timer, so callers may seed in a loop and
4615
- * let the earliest due-time win.
4526
+ * Re-seed a persisted `deferred_at` into the local wake at cold start, so
4527
+ * an idle deferred stream re-arms at its due-time with no new commit.
4528
+ * Seeds collapse into one timer; the earliest wins.
4616
4529
  */
4617
4530
  seed_defer(stream, at) {
4618
4531
  this._defer.set(stream, at);
@@ -4622,31 +4535,21 @@ var DrainController = class {
4622
4535
  get armed() {
4623
4536
  return this._armed;
4624
4537
  }
4625
- /**
4626
- * The cycle currently in flight, or `undefined` when idle (#1442). A
4627
- * graceful shutdown awaits this so an in-flight handler reaches its `ack`
4628
- * — which releases the stream's lease — instead of being abandoned with
4629
- * the lease held until it expires.
4630
- */
4538
+ /** The cycle in flight, or `undefined` when idle. */
4631
4539
  get inflight() {
4632
4540
  return this._inflight;
4633
4541
  }
4634
- /**
4635
- * This lane's configured lease budget, or `undefined` when the lane didn't
4636
- * pin one. It is the operator's own statement of how long a handler may
4637
- * legitimately hold a stream, which makes it the right basis for a
4638
- * shutdown grace budget (#1442).
4639
- */
4542
+ /** This lane's configured lease, or `undefined`; the shutdown grace basis. */
4640
4543
  get lease_millis() {
4641
4544
  return this._deps.defaults?.leaseMillis;
4642
4545
  }
4643
- /** Lane this controller drains (undefined = legacy single-lane span). */
4546
+ /** Lane this controller drains (undefined spans all lanes). */
4644
4547
  get lane() {
4645
4548
  return this._deps.lane;
4646
4549
  }
4647
4550
  /**
4648
4551
  * Start a per-lane worker that drains at the lane's `cycleMs`
4649
- * cadence (ACT-1103). When armed, the worker calls `drain()` on every
4552
+ * cadence. When armed, the worker calls `drain()` on every
4650
4553
  * tick and re-schedules; when not armed, it still re-schedules at
4651
4554
  * `cycleMs` so a future `arm()` is picked up on the next tick.
4652
4555
  *
@@ -4833,26 +4736,13 @@ var SettleLoop = class {
4833
4736
  _timer = void 0;
4834
4737
  _running = false;
4835
4738
  /**
4836
- * Resolves when the cycle currently in flight finishes; `undefined` when
4837
- * idle (#1468). `_running` answers "is a cycle running?" for the
4838
- * re-arm bookkeeping; this answers "tell me when it is done" for a
4839
- * graceful shutdown.
4840
- *
4841
- * `stop()` only cancels *scheduling* — a cycle already inside its
4842
- * correlate → drain loop keeps going, and because `DrainController.drain`
4843
- * does not consult `_stopped`, it can claim a stream after teardown
4844
- * returned and after the store adapter was disposed. Never rejects: the
4845
- * cycle's own `catch` contains its errors, so awaiting this is safe.
4739
+ * Resolves when the cycle in flight finishes, so shutdown can wait for
4740
+ * it (`stop()` cancels scheduling only). Never rejects.
4846
4741
  */
4847
4742
  _inflight;
4848
4743
  /**
4849
- * Set when a `schedule()` timer fires while a cycle is still running
4850
- * (ACT-1205). The in-flight cycle's `finally` re-arms one more pass so
4851
- * the wake-up isn't dropped — a commit landing during the final
4852
- * no-progress drain pass would otherwise leave armed controllers with
4853
- * nothing to re-drain on an instance with no lane `cycleMs` and no
4854
- * polling. Carries the options of the dropped call so the re-armed
4855
- * pass honors its `debounceMs`/`maxPasses`/drain overrides.
4744
+ * A wake-up that fired while a cycle was running. The running cycle's
4745
+ * `finally` schedules one more pass with these options, so it isn't lost.
4856
4746
  */
4857
4747
  _pending = void 0;
4858
4748
  _deps;
@@ -4924,7 +4814,7 @@ var SettleLoop = class {
4924
4814
  }, debounceMs);
4925
4815
  }
4926
4816
  /**
4927
- * The cycle currently in flight, or `undefined` when idle (#1468). A
4817
+ * The cycle currently in flight, or `undefined` when idle. A
4928
4818
  * graceful shutdown awaits this alongside the drain controllers so a
4929
4819
  * settle parked in `correlate` does not resume after teardown.
4930
4820
  */
@@ -5070,17 +4960,17 @@ function validate_only_lanes(options, lanes) {
5070
4960
  }
5071
4961
  var Act = class {
5072
4962
  _emitter = new import_node_events.default();
5073
- /** ACT-984: orchestrator-owned circuit breaker shared by all drain lanes. */
4963
+ /** Circuit breaker shared by all drain lanes. */
5074
4964
  _breaker;
5075
- /** #803: gate the `Store.notify` subscription side. */
4965
+ /** Whether this instance subscribes to `Store.notify`. */
5076
4966
  _listen;
5077
- /** #803: gate the local reaction pipeline (drain controllers, settle, correlate). */
4967
+ /** Whether this instance runs reactions (drain, settle, correlate). */
5078
4968
  _drain;
5079
4969
  /** Event names with at least one registered reaction (computed at build time) */
5080
4970
  _reactive_events;
5081
4971
  /** One DrainController per active lane, keyed by lane name. */
5082
4972
  _drain_controllers;
5083
- /** Correlation state machine: lazy init, dynamic-resolver scan, periodic worker. */
4973
+ /** Correlation: lazy init and the scan that marks work. */
5084
4974
  _correlate;
5085
4975
  /** Debounced correlate→drain catch-up loop. */
5086
4976
  _settle;
@@ -5110,26 +5000,10 @@ var Act = class {
5110
5000
  * Emit a lifecycle event. The payload type is inferred from the event name
5111
5001
  * via {@link ActLifecycleEvents}.
5112
5002
  *
5113
- * **Every listener is contained individually.** Lifecycle listeners are
5114
- * observers — `observability.md` promises that a throwing one is "contained,
5115
- * not fatal" — and containment belongs here rather than at each call site,
5116
- * for two reasons the previous arrangement got wrong (#1437):
5117
- *
5118
- * - Wrapping the *emit* rather than each *listener* still let the first
5119
- * thrower abort the rest: `EventEmitter.emit` stops dispatching on the
5120
- * first exception, so a second `app.on("acked", …)` never ran. The
5121
- * documented "the remaining sinks still fire" was false whenever an event
5122
- * had more than one listener. Same lesson as #1423, where guarding the
5123
- * loop instead of each callback left every later SSE subscriber unserved.
5124
- * - Only *some* call sites wrapped at all. The drain contained `acked` and
5125
- * `blocked`; `committed`, `forgotten` and `close()`'s `closed` did not, so
5126
- * a throwing listener rejected `do()`, `forget()` and `close()` **after**
5127
- * their durable work had already landed. A caller retrying a "failed"
5128
- * `do()` writes the event twice, since the framework has no dedup by
5129
- * design.
5130
- *
5131
- * Containing here makes it a property of emitting, so a new lifecycle event
5132
- * cannot reintroduce the gap by omission.
5003
+ * Each listener is contained on its own: a throwing listener is logged,
5004
+ * the remaining listeners still run, and the caller (`do()`, `forget()`,
5005
+ * `close()`, the drain) never sees the throw, since its durable work has
5006
+ * already landed.
5133
5007
  *
5134
5008
  * Uses `rawListeners` so `once` wrappers still de-register themselves, and
5135
5009
  * returns "had listeners" to preserve the `EventEmitter.emit` contract.
@@ -5190,29 +5064,23 @@ var Act = class {
5190
5064
  */
5191
5065
  _event_to_state;
5192
5066
  /**
5193
- * Event-name → lane fan-in for selective arming (ACT-1103). Built by
5067
+ * Event-name → lane fan-in for selective arming. Built by
5194
5068
  * `classify_registry` once per build. `"all"` means at least one of
5195
5069
  * the event's reactions is a dynamic resolver (lane opaque until
5196
5070
  * runtime); a `Set<string>` lists the static lanes only that event's
5197
5071
  * reactions target.
5198
5072
  */
5199
5073
  _event_to_lanes;
5200
- /**
5201
- * Audit dependency bag (#723). Built once at construction; held as
5202
- * an immutable snapshot of the registry state the audit module
5203
- * needs. Lives in `internal/audit.ts` — this orchestrator never
5204
- * carries audit logic, only the deps + a one-liner that hands them
5205
- * over.
5206
- */
5074
+ /** What `internal/audit.ts` needs, built once at construction. */
5207
5075
  _audit_deps;
5208
5076
  /** Logger resolved at construction time (after user port configuration) */
5209
5077
  _logger = log();
5210
- /** Wraps a public-method body so internal `store()`/`cache()` resolve to the
5211
- * per-Act ports (ACT-501). No-op when the Act is unscoped — so the singleton
5212
- * path keeps reading fresh `store()`/`cache()` per call, which matters for
5213
- * tests that dispose and re-seed mid-suite. */
5214
5078
  /** This Act's ports: its own bag, or the singleton adapters. */
5215
5079
  _ports;
5080
+ /**
5081
+ * Runs a body inside this Act's ports frame, so internal
5082
+ * `store()`/`cache()` calls resolve to `_ports`.
5083
+ */
5216
5084
  _scoped;
5217
5085
  /**
5218
5086
  * Correlation-id generator for originating actions. Bound at
@@ -5231,24 +5099,18 @@ var Act = class {
5231
5099
  /** Reaction dispatchers built once and handed to run_drain_cycle each cycle. */
5232
5100
  _handle;
5233
5101
  _handle_batch;
5234
- /** Declared drain lanes (ACT-1103). */
5102
+ /** Declared drain lanes. */
5235
5103
  _lanes;
5236
5104
  /**
5237
- * Per-stream close serialization tails (#1222). Chains each stream's
5238
- * windowed-close work behind the previous one so a manual
5239
- * `app.close([{stream, before}])` and an autoclose windowed close for
5240
- * the same stream never run their guard-free prune concurrently — the
5241
- * manual path bypasses the `__autoclose__:X` drain lease that would
5242
- * otherwise exclude them, so without this both closers archive the
5243
- * same prefix. Process-local: both racers run on the same Act
5244
- * instance. Entries are dropped once their tail resolves so the map
5245
- * doesn't grow with distinct stream names.
5105
+ * Per-stream close serialization tails, so a manual close and an
5106
+ * autoclose of the same stream never prune concurrently (the manual path
5107
+ * has no drain lease to exclude it). Entries are dropped once settled.
5246
5108
  */
5247
5109
  _close_locks = /* @__PURE__ */ new Map();
5248
5110
  /**
5249
- * Run `work` under the per-stream close lock (#1222). Serializes close
5250
- * critical sections for the same stream (windowed prunes, and full closes
5251
- * since #1738) while letting different streams proceed in parallel.
5111
+ * Run `work` under the per-stream close lock. Serializes close
5112
+ * critical sections for the same stream (windowed prunes and full
5113
+ * closes) while letting different streams proceed in parallel.
5252
5114
  */
5253
5115
  _with_close_lock(stream, work) {
5254
5116
  const prev = this._close_locks.get(stream) ?? Promise.resolve();
@@ -5275,11 +5137,11 @@ var Act = class {
5275
5137
  * @param states Merged map of state name → state definition
5276
5138
  * @param batch_handlers Static-target projection batch handlers (target → handler)
5277
5139
  * @param options Tuning knobs — see {@link ActOptions}
5278
- * @param lanes Declared drain lanes (ACT-1103). The builder collects
5279
- * these from `.withLane(...)` calls. Slice 1 records them on the
5280
- * instance; later slices fan out one `DrainController` per lane.
5140
+ * @param lanes Declared drain lanes. The builder collects
5141
+ * these from `.withLane(...)` calls; one `DrainController` runs
5142
+ * per lane, plus the implicit `"default"`.
5281
5143
  * @param patch_fn The per-event patch step selected once by the builder
5282
- * from `ActOptions.validateFoldedState` (ACT-1238) — `bare_patch` by
5144
+ * from `ActOptions.validateFoldedState` — `bare_patch` by
5283
5145
  * default, `validating_patch` when the flag is on. The builder uses
5284
5146
  * the same value for its projection-fold handlers, so there is a
5285
5147
  * single selection site. Defaults to `bare_patch` for direct
@@ -5294,16 +5156,15 @@ var Act = class {
5294
5156
  this._ports = options.scoped ?? default_scope();
5295
5157
  const ports = this._ports;
5296
5158
  this._scoped = make_run_scoped({
5297
- // Delegating getters, NOT a spread: `default_scope()` resolves the
5298
- // process singletons lazily, so copying its properties would freeze
5299
- // whichever adapters happened to be installed at construction and
5300
- // ignore a later `store(...)` / `cache(...)`.
5159
+ // Getters, not a spread: the singletons resolve lazily, so a later
5160
+ // `store(...)` / `cache(...)` still takes effect.
5301
5161
  get store() {
5302
5162
  return ports.store;
5303
5163
  },
5304
5164
  get cache() {
5305
5165
  return ports.cache;
5306
5166
  },
5167
+ // Parsed per build, so a bad window throws on every build.
5307
5168
  autoclose_window: resolveAutocloseConfig(options).autocloseWindow
5308
5169
  });
5309
5170
  this._correlator = options.correlator ?? default_correlator;
@@ -5311,8 +5172,6 @@ var Act = class {
5311
5172
  this._cd = build_drain(this._logger);
5312
5173
  this._handle = build_handle({
5313
5174
  logger: this._logger,
5314
- // The orchestrator owns ambient context; `build_handle` only asks for
5315
- // the triggering event to be in scope while the handler runs.
5316
5175
  reaction_scope: make_reaction_scope({
5317
5176
  do: this._bound_do,
5318
5177
  load: this._bound_load,
@@ -5347,16 +5206,8 @@ var Act = class {
5347
5206
  resolveCircuitBreakerConfig(options.circuitBreaker),
5348
5207
  {
5349
5208
  on_error: (error, circuit) => this._emit_error(error, circuit),
5350
- // Re-probe the store when the cooldown elapses, so recovery is
5351
- // automatic even on the default lane (which has no periodic poller).
5352
- // The wake fires `settle()`, which (in half-open) runs a real store
5353
- // probe: for a dynamic-resolver app the probe is settle's correlate
5354
- // (a store scan); for a static-reaction app correlate is a no-op that
5355
- // records no health, so the probe is settle's DRAIN claim — either
5356
- // way one success closes the breaker and every loop resumes, a
5357
- // failure re-opens it and reschedules the wake. Settle does NOT close
5358
- // the breaker off a no-op correlate (#1329) — only a real store op
5359
- // (correlate scan or drain claim) records `passed()`.
5209
+ // When the cooldown elapses, settle once: its scan or claim is the
5210
+ // half-open probe that closes or re-opens the breaker.
5360
5211
  on_retry: () => {
5361
5212
  this.settle({ debounceMs: 0 });
5362
5213
  }
@@ -5364,12 +5215,9 @@ var Act = class {
5364
5215
  );
5365
5216
  }
5366
5217
  /**
5367
- * One DrainController per active lane. The implicit "default" lane is
5368
- * always present unless onlyLanes excludes it. Each controller filters
5369
- * its claim() by its lane name; the legacy single-controller path is the
5370
- * no-lane-declared case with `lane: undefined` deps so claim() doesn't
5371
- * filter (preserves the single-lane SQL planner shape for apps that never
5372
- * call withLane).
5218
+ * One DrainController per active lane, plus the implicit "default" unless
5219
+ * `onlyLanes` excludes it. Apps that declare no lanes pass no lane filter
5220
+ * to `claim`.
5373
5221
  */
5374
5222
  _build_drain_controllers(options, lanes) {
5375
5223
  const all_lanes = ["default", ...lanes.map((l) => l.name)];
@@ -5388,11 +5236,7 @@ var Act = class {
5388
5236
  handle_batch: this._handle_batch,
5389
5237
  on_acked: (acked) => this.emit("acked", acked),
5390
5238
  on_blocked: (blocked) => this.emit("blocked", blocked),
5391
- // Reaction-requested close. Runs the same close machinery as
5392
- // `app.close` (tombstone guard + archive + atomic truncate) for the
5393
- // targets a handler signalled via `CloseSignal`. No `correlate()`
5394
- // here — the drain that produced these targets has already
5395
- // correlated.
5239
+ // Reaction-requested close: the same machinery as `app.close`.
5396
5240
  on_close: async (targets) => {
5397
5241
  const close_actor = { id: "$close", name: "close" };
5398
5242
  const result = await run_close_cycle(targets, {
@@ -5409,12 +5253,7 @@ var Act = class {
5409
5253
  this.emit("closed", result);
5410
5254
  },
5411
5255
  breaker: this._breaker,
5412
- // Re-scope the per-lane worker's auto-start ticks so their drain
5413
- // resolves the scoped ports, not the singleton (#1191).
5414
5256
  run_scoped: this._scoped,
5415
- // Pass lane only when a true per-lane controller is active.
5416
- // The all-lanes (single default) case keeps lane=undefined so
5417
- // adapter SQL collapses to the single-lane shape.
5418
5257
  lane: single_default_lane ? void 0 : name,
5419
5258
  defaults: cfg && {
5420
5259
  streamLimit: cfg.streamLimit,
@@ -5428,17 +5267,9 @@ var Act = class {
5428
5267
  return controllers;
5429
5268
  }
5430
5269
  /**
5431
- * Orphaned-lane startup advisory (#1220). When `onlyLanes` is set, this
5432
- * instance builds a controller only for its slice of the declared lane
5433
- * universe — every OTHER declared lane's stream is persisted (correlate
5434
- * subscribes all static targets regardless of `onlyLanes`) but never
5435
- * claimed here. If no peer worker deploys with those lanes in ITS
5436
- * `onlyLanes`, their reactions accumulate forever, silently. A single
5437
- * process can't verify the cluster invariant `∪ onlyLanes ⊇ declared
5438
- * lanes`, so we surface the per-instance signal — "these declared lanes
5439
- * have no controller here" — the same way the deprecated-event advisory
5440
- * surfaces legacy events. No advisory when `onlyLanes` is unset (every
5441
- * lane gets a controller) or covers every declared lane.
5270
+ * Startup advisory naming declared lanes that `onlyLanes` leaves without a
5271
+ * controller here. One process can't check that the cluster covers every
5272
+ * lane, so it reports its own gaps.
5442
5273
  */
5443
5274
  _advise_orphaned_lanes(options, lanes) {
5444
5275
  if (!options.onlyLanes || options.onlyLanes.length === 0) return;
@@ -5452,25 +5283,15 @@ var Act = class {
5452
5283
  `Act declared ${orphaned.length} orphaned lane(s) on this instance: ${list}. onlyLanes excludes them, so no DrainController claims their streams here \u2014 their reactions accumulate un-drained unless a peer worker deploys with these lanes in its onlyLanes. Ensure the cluster invariant holds: the union of every worker's onlyLanes must cover every declared lane. See docs/docs/guides/production-checklist.md \xA7 Sizing lanes.`
5453
5284
  );
5454
5285
  }
5455
- /**
5456
- * Audit deps bag. Snapshotted after registry classification and
5457
- * drain-controller build so the audit module sees the finalized lane
5458
- * set. Held as an immutable bag — the orchestrator never carries audit
5459
- * logic itself, only this typed contract.
5460
- */
5286
+ /** Audit deps, built after the controllers so the lane set is final. */
5461
5287
  _build_audit_deps() {
5462
5288
  return {
5463
5289
  store: store2,
5464
5290
  logger: this._logger,
5465
5291
  event_to_state: this._event_to_state,
5466
5292
  states: this._states,
5467
- // The DECLARED lane universe — the implicit "default" plus every
5468
- // `.withLane(...)` name — NOT `_drain_controllers.keys()` (#1224).
5469
- // An `onlyLanes`-filtered instance builds a controller only for its
5470
- // slice of lanes, so keying off the active controller set would flag
5471
- // a stream correctly assigned to an excluded-but-declared lane (one
5472
- // another worker drains) as `unknown-lane`. The audit reports what's
5473
- // structurally routable across the cluster, not what this process runs.
5293
+ // Declared lanes, not this process's controllers: a lane another
5294
+ // worker drains is not `unknown-lane`.
5474
5295
  declared_lanes: /* @__PURE__ */ new Set(["default", ...this._lanes.map((l) => l.name)]),
5475
5296
  routed_events: new Set(this._event_to_lanes.keys())
5476
5297
  };
@@ -5486,10 +5307,8 @@ var Act = class {
5486
5307
  static_targets: classification.static_targets,
5487
5308
  cd: this._cd,
5488
5309
  max_subscribed_streams: options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,
5489
- // Every lane a controller can exist for, so correlate can reroute a
5490
- // dynamic resolution that names one that doesn't (#1564). Declared,
5491
- // not active: `onlyLanes` shrinks this process's controllers, but a
5492
- // lane another process claims is still a valid destination.
5310
+ // Declared lanes (not active ones): a lane another process claims is
5311
+ // still a valid destination.
5493
5312
  declared_lanes: /* @__PURE__ */ new Set([
5494
5313
  "default",
5495
5314
  ...this._lanes.map((l) => l.name)
@@ -5497,26 +5316,14 @@ var Act = class {
5497
5316
  on_init: () => {
5498
5317
  if (this._drain && this._reactive_events.size > 0) this._arm_all();
5499
5318
  },
5500
- // Cold-start defer re-seed (#1221). Skipped on writer-only instances
5501
- // (`drain: false`) — they run no local controllers to re-arm.
5502
5319
  on_init_async: this._drain ? () => this._seed_persisted_defers() : void 0
5503
5320
  });
5504
5321
  }
5505
5322
  /**
5506
- * Re-seed every active lane controller's process-local defer timer from
5507
- * the store's persisted `deferred_at` (#1221). Runs once at cold start,
5508
- * inside `CorrelateCycle.init`, after static targets are subscribed.
5509
- *
5510
- * The defer timer is worker memory: empty after a restart. A stream
5511
- * deferred to a future due-time (the classic case: an idle autoclose
5512
- * aggregate that deferred its terminal close) is durable in the store but
5513
- * has nothing in memory to re-arm the drain — the controller disarms on
5514
- * the first empty claim and, since the aggregate is idle, no commit ever
5515
- * re-arms it. Reading the persisted schedule and seeding the owning lane's
5516
- * timer restores the wake, so the close fires at the due-time.
5517
- *
5518
- * Streams whose lane has no controller on this instance (excluded by
5519
- * `onlyLanes`) are skipped — a peer worker owns that lane's timer.
5323
+ * At cold start, re-seed each lane controller's local wake from the
5324
+ * persisted future `deferred_at`, so an idle deferred stream (an
5325
+ * autoclose waiting out its window) still fires on time. Streams on lanes
5326
+ * this instance doesn't run are skipped.
5520
5327
  */
5521
5328
  async _seed_persisted_defers() {
5522
5329
  const now = Date.now();
@@ -5530,10 +5337,6 @@ var Act = class {
5530
5337
  _build_settle(options) {
5531
5338
  return new SettleLoop(
5532
5339
  {
5533
- // Scope the init like every other store-touching path — a bare
5534
- // `this._correlate.init()` runs `store().subscribe(...)` against
5535
- // the singleton for a scoped Act, so static targets never land on
5536
- // the scoped store and `_initialized` then blocks a retry (#1191).
5537
5340
  init: () => this._scoped(() => this._correlate.init()),
5538
5341
  checkpoint: () => this._correlate.checkpoint,
5539
5342
  correlate: (q) => this._correlate_scanned(q, true),
@@ -5551,19 +5354,11 @@ var Act = class {
5551
5354
  * already in flight a bounded chance to finish, then remove lifecycle
5552
5355
  * listeners and tear down the cross-process notify subscription.
5553
5356
  *
5554
- * The order is deliberate (#1442). Scheduling stops first, so nothing new
5555
- * is claimed while teardown runs. Then in-flight cycles are awaited up to
5556
- * `graceMs`: a reaction handler parked on an `await` holds its stream's
5557
- * lease until it acks, so abandoning it costs the replacement worker up to
5558
- * `leaseMillis` of dead time on that stream and discards the round of work
5559
- * (which #1418 then redelivers). Listeners come off *after* that wait, not
5560
- * before, so an `acked` / `blocked` subscriber still observes the work
5561
- * that completed during the grace window.
5562
- *
5563
- * The budget is a ceiling, not a delay — teardown continues the moment the
5564
- * last in-flight cycle finishes. When it is exhausted, teardown proceeds
5565
- * anyway: one stuck handler must not hang a deploy, which is the failure
5566
- * mode an unbounded wait would trade for.
5357
+ * Scheduling stops first, then in-flight cycles get up to `graceMs` to
5358
+ * reach their `ack` (an abandoned handler holds its lease until it
5359
+ * expires). Listeners come off after the wait, so they still see work that
5360
+ * finished during it. The budget is a ceiling, not a delay; when it runs
5361
+ * out, teardown proceeds anyway.
5567
5362
  *
5568
5363
  * Idempotent — repeated calls return the same promise, and the first
5569
5364
  * call's `graceMs` is the one that applies. Registered automatically with
@@ -5596,26 +5391,10 @@ var Act = class {
5596
5391
  * whichever comes first. Cycle promises never reject (`drain()` contains
5597
5392
  * its own errors), so this never throws.
5598
5393
  *
5599
- * An omitted budget is derived from the lanes that actually have a cycle
5600
- * in flight: their `leaseMillis` is the operator's own statement of how
5601
- * long one of their handlers may hold a stream, which makes it the honest
5602
- * ceiling for how long teardown should wait for that handler. A parked
5603
- * lane that pinned no lease contributes `drain()`'s own fallback, and the
5604
- * whole thing is capped so a long-leased lane cannot hold a deploy open.
5605
- * Idle lanes do not count — nothing is running on them to wait for.
5606
- *
5607
- * An in-flight settle counts the same way, on the same fallback (#1617).
5608
- * It is waited on like any cycle, and deriving from the lanes alone gave
5609
- * it a budget of `0` whenever it was the only thing running — which
5610
- * returned before the wait it was about to be added to.
5611
- *
5612
- * A lane configured `leaseMillis: 0` takes the fallback rather than its
5613
- * own value, which is why this coalesces on falsy and not just on absent
5614
- * (#1647). A zero-length lease expires the instant it is granted, so it
5615
- * has no answer to offer for "how long may a handler hold this stream" —
5616
- * it is the pinned-no-lease case spelled with a number, and #1617 already
5617
- * settled what that case is worth. Taking it literally derived a budget
5618
- * of `0` and abandoned the very cycle this had just found running.
5394
+ * An omitted budget is the largest `leaseMillis` among lanes with a cycle
5395
+ * in flight (the drain's fallback for lanes that pinned none, or pinned
5396
+ * 0, which is the same as none), with an in-flight settle counting on the
5397
+ * fallback, capped at the maximum. Idle lanes don't count.
5619
5398
  */
5620
5399
  _derive_grace_ms(running, settling) {
5621
5400
  let max = settling ? DEFAULT_SHUTDOWN_GRACE_MS : 0;
@@ -5888,7 +5667,7 @@ var Act = class {
5888
5667
  }
5889
5668
  /**
5890
5669
  * Wipe the sensitive-data payload for every event on the stream — see
5891
- * {@link IAct.forget}. Application-level half of #566.
5670
+ * {@link IAct.forget}.
5892
5671
  *
5893
5672
  * Throws on adapters without `Store.forget_pii`, invalidates the cache
5894
5673
  * entry for the stream, emits the `forgotten` lifecycle event with the
@@ -5929,7 +5708,7 @@ var Act = class {
5929
5708
  *
5930
5709
  * Call `correlate()` before `drain()`. It is not only how dynamic targets
5931
5710
  * are discovered: a stream is claimable while `at < correlated_at`, and
5932
- * `correlate` is the only component that raises that mark (#1487), so a
5711
+ * `correlate` is the only component that raises that mark, so a
5933
5712
  * commit no correlate has seen is not drainable — including for static
5934
5713
  * targets, which were served by a probe of the event log before. For a
5935
5714
  * higher-level API that handles debouncing, correlation, and signaling
@@ -5962,14 +5741,14 @@ var Act = class {
5962
5741
  return { fetched: [], leased: [], acked: [], blocked: [] };
5963
5742
  return this._scoped(() => this._drain_all(options));
5964
5743
  }
5965
- /** Arm every active lane controller (ACT-1103). */
5744
+ /** Arm every active lane controller. */
5966
5745
  _arm_all() {
5967
5746
  this._correlate.arm();
5968
5747
  for (const c of this._drain_controllers.values()) c.arm();
5969
5748
  }
5970
5749
  /**
5971
5750
  * Arm only the lane controllers whose reactions match the supplied
5972
- * event names (ACT-1103 selective arming). Events with any dynamic
5751
+ * event names (selective arming). Events with any dynamic
5973
5752
  * resolver fall back to `_arm_all()` via the `"all"` sentinel — the
5974
5753
  * resolver's lane isn't known until correlate runs the function.
5975
5754
  * Events with no reactions are skipped; `_event_to_lanes` doesn't
@@ -6073,7 +5852,7 @@ var Act = class {
6073
5852
  return { subscribed, last_id };
6074
5853
  }
6075
5854
  /**
6076
- * `correlate` plus whether the pass actually read the store (#1510).
5855
+ * `correlate` plus whether the pass actually read the store.
6077
5856
  *
6078
5857
  * The settle loop needs that extra bit to decide whether the pass carries a
6079
5858
  * circuit-breaker health signal, and a disarmed pass carries none. It stays
@@ -6334,7 +6113,7 @@ var Act = class {
6334
6113
  });
6335
6114
  }
6336
6115
  /**
6337
- * Operator-driven store audit (#723).
6116
+ * Operator-driven store audit.
6338
6117
  *
6339
6118
  * Walks the connected store and yields per-category findings —
6340
6119
  * each tagged with the remediation it suggests. Same operator-
@@ -6386,7 +6165,7 @@ var Act = class {
6386
6165
  * Bulk-update scheduling priority for streams matching `filter`.
6387
6166
  *
6388
6167
  * Operator-grade override of the `claim()` lagging-frontier
6389
- * ordering (ACT-102). Useful when a long-running replay needs to
6168
+ * ordering. Useful when a long-running replay needs to
6390
6169
  * jump ahead of other lagging streams, or when a no-longer-urgent
6391
6170
  * job should yield slots back to the rest. Build-time priorities
6392
6171
  * (set via the resolver's `priority` field) are subject to a
@@ -6483,12 +6262,12 @@ var Act = class {
6483
6262
  */
6484
6263
  /**
6485
6264
  * After a close, forget any target whose subscription row the truncate
6486
- * removed, so a later correlate can re-subscribe it (#1398). Restart
6265
+ * removed, so a later correlate can re-subscribe it. Restart
6487
6266
  * targets keep their row, so only fully-retired streams are forgotten.
6488
6267
  */
6489
6268
  /**
6490
6269
  * Advance correlation until the read cursor reaches `until`, and report
6491
- * where it landed (#1487). Used by the close cycle's safety probe, which
6270
+ * where it landed. Used by the close cycle's safety probe, which
6492
6271
  * cannot judge a subscription's pending work over events correlate has
6493
6272
  * not resolved yet.
6494
6273
  *
@@ -6514,13 +6293,12 @@ var Act = class {
6514
6293
  * A tombstone seed means the stream was retired; a snapshot seed means it
6515
6294
  * was restarted and is still consuming.
6516
6295
  *
6517
- * `truncate` no longer removes the subscription row (#1527), so this is no
6296
+ * `truncate` no longer removes the subscription row, so this is no
6518
6297
  * longer repairing damage the close itself did. It still matters, because
6519
6298
  * the row can disappear later: reclaiming retired subscriptions is an
6520
6299
  * operator job now, and that `DELETE` can land while this process is
6521
6300
  * running. Forgetting here keeps the in-process view from outliving a row
6522
- * an operator removed, which is the same silent-no-delivery failure #1398
6523
- * described — a reaction whose target is named after the stream would never
6301
+ * an operator removed, which is a silent-no-delivery failure — a reaction whose target is named after the stream would never
6524
6302
  * be re-registered.
6525
6303
  */
6526
6304
  _forget_closed_subscriptions(result) {
@@ -6795,7 +6573,7 @@ function reaction_on(event, events, builder) {
6795
6573
  const reaction = {
6796
6574
  handler: schedule ? make_deferred(handler, schedule) : handler,
6797
6575
  resolver: _this_,
6798
- // #1269: validate the whole bag at the declaration site so a bad
6576
+ // Validate the whole bag at the declaration site so a bad
6799
6577
  // `maxRetries`/`backoff`/`blockOnError` throws ZodError at build,
6800
6578
  // not a NaN gate on the first retry.
6801
6579
  options: resolveReactionConfig({
@@ -6997,7 +6775,7 @@ function act() {
6997
6775
  spec.flush,
6998
6776
  spec.config,
6999
6777
  patch_fn,
7000
- // Head loads strip sensitive keys like the warm path (#1320).
6778
+ // Head loads strip sensitive keys like the warm path.
7001
6779
  registry.sensitive_fields
7002
6780
  )
7003
6781
  )
@@ -7503,7 +7281,7 @@ var CsvFile = class {
7503
7281
  name: fields[1],
7504
7282
  // Revive dates like every Store adapter does — a Date in an event
7505
7283
  // payload must not depend on whether it came back through a store or
7506
- // through a CSV restore (#1399). The `created` column below has
7284
+ // through a CSV restore. The `created` column below has
7507
7285
  // always been parsed explicitly; the JSON columns were missed.
7508
7286
  data: JSON.parse(fields[2]),
7509
7287
  stream: fields[3],