@rotorsoft/act 1.9.0 → 1.10.1

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 (67) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +46 -14
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/adapters/console-logger.d.ts +2 -2
  5. package/dist/@types/adapters/console-logger.d.ts.map +1 -1
  6. package/dist/@types/adapters/in-memory-store.d.ts +6 -6
  7. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  8. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  9. package/dist/@types/builders/state-builder.d.ts +33 -3
  10. package/dist/@types/builders/state-builder.d.ts.map +1 -1
  11. package/dist/@types/internal/audit.d.ts +4 -4
  12. package/dist/@types/internal/audit.d.ts.map +1 -1
  13. package/dist/@types/internal/backoff.d.ts +1 -1
  14. package/dist/@types/internal/backoff.d.ts.map +1 -1
  15. package/dist/@types/internal/build-classify.d.ts +11 -11
  16. package/dist/@types/internal/build-classify.d.ts.map +1 -1
  17. package/dist/@types/internal/close-cycle.d.ts +3 -3
  18. package/dist/@types/internal/close-cycle.d.ts.map +1 -1
  19. package/dist/@types/internal/correlate-cycle.d.ts +4 -4
  20. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
  21. package/dist/@types/internal/correlator.d.ts +2 -2
  22. package/dist/@types/internal/correlator.d.ts.map +1 -1
  23. package/dist/@types/internal/drain-cycle.d.ts +20 -20
  24. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  25. package/dist/@types/internal/drain-ratio.d.ts +1 -1
  26. package/dist/@types/internal/drain-ratio.d.ts.map +1 -1
  27. package/dist/@types/internal/event-sourcing.d.ts +9 -4
  28. package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
  29. package/dist/@types/internal/event-versions.d.ts +2 -2
  30. package/dist/@types/internal/event-versions.d.ts.map +1 -1
  31. package/dist/@types/internal/index.d.ts +8 -7
  32. package/dist/@types/internal/index.d.ts.map +1 -1
  33. package/dist/@types/internal/merge.d.ts +3 -3
  34. package/dist/@types/internal/merge.d.ts.map +1 -1
  35. package/dist/@types/internal/reactions.d.ts +11 -10
  36. package/dist/@types/internal/reactions.d.ts.map +1 -1
  37. package/dist/@types/internal/sensitive.d.ts +147 -0
  38. package/dist/@types/internal/sensitive.d.ts.map +1 -0
  39. package/dist/@types/internal/settle.d.ts +3 -3
  40. package/dist/@types/internal/settle.d.ts.map +1 -1
  41. package/dist/@types/internal/tracing.d.ts +5 -5
  42. package/dist/@types/internal/tracing.d.ts.map +1 -1
  43. package/dist/@types/types/action.d.ts +57 -0
  44. package/dist/@types/types/action.d.ts.map +1 -1
  45. package/dist/@types/types/registry.d.ts +9 -1
  46. package/dist/@types/types/registry.d.ts.map +1 -1
  47. package/dist/@types/types/schemas.d.ts +36 -0
  48. package/dist/@types/types/schemas.d.ts.map +1 -1
  49. package/dist/{chunk-F4S2JOPN.js → chunk-3Z2HU726.js} +134 -133
  50. package/dist/chunk-3Z2HU726.js.map +1 -0
  51. package/dist/chunk-BY5JPOZR.js +267 -0
  52. package/dist/chunk-BY5JPOZR.js.map +1 -0
  53. package/dist/index.cjs +835 -616
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.js +567 -439
  56. package/dist/index.js.map +1 -1
  57. package/dist/test/index.cjs +194 -187
  58. package/dist/test/index.cjs.map +1 -1
  59. package/dist/test/index.js +11 -11
  60. package/dist/test/index.js.map +1 -1
  61. package/dist/types/index.cjs +52 -34
  62. package/dist/types/index.cjs.map +1 -1
  63. package/dist/types/index.js +9 -3
  64. package/package.json +3 -3
  65. package/dist/chunk-F4S2JOPN.js.map +0 -1
  66. package/dist/chunk-PMAZTOSO.js +0 -164
  67. package/dist/chunk-PMAZTOSO.js.map +0 -1
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  sleep,
20
20
  store,
21
21
  validate
22
- } from "./chunk-F4S2JOPN.js";
22
+ } from "./chunk-3Z2HU726.js";
23
23
  import {
24
24
  ActorSchema,
25
25
  CausationEventSchema,
@@ -32,11 +32,19 @@ import {
32
32
  LogLevels,
33
33
  NonRetryableError,
34
34
  QuerySchema,
35
+ REDACTED,
36
+ SHREDDED,
35
37
  StreamClosedError,
36
38
  TargetSchema,
37
39
  ValidationError,
38
- ZodEmpty
39
- } from "./chunk-PMAZTOSO.js";
40
+ ZodEmpty,
41
+ pii_fields,
42
+ pii_gate,
43
+ pii_merge,
44
+ pii_split,
45
+ pii_strip,
46
+ sensitive
47
+ } from "./chunk-BY5JPOZR.js";
40
48
  import "./chunk-5WRI5ZAA.js";
41
49
 
42
50
  // src/signals.ts
@@ -70,7 +78,7 @@ function parse(name) {
70
78
  }
71
79
  return { base: name, version: 1 };
72
80
  }
73
- function deprecatedEventNames(names) {
81
+ function deprecated_event_names(names) {
74
82
  const groups = /* @__PURE__ */ new Map();
75
83
  for (const name of names) {
76
84
  const { base, version } = parse(name);
@@ -86,10 +94,10 @@ function deprecatedEventNames(names) {
86
94
  }
87
95
  return deprecated;
88
96
  }
89
- function currentVersionOf(deprecatedName, allNames) {
90
- const target = parse(deprecatedName);
97
+ function current_version_of(deprecated_name, all_names) {
98
+ const target = parse(deprecated_name);
91
99
  let highest;
92
- for (const name of allNames) {
100
+ for (const name of all_names) {
93
101
  const { base, version } = parse(name);
94
102
  if (base !== target.base) continue;
95
103
  if (!highest || version > highest.version) highest = { version, name };
@@ -119,27 +127,27 @@ var ALL_CATEGORIES = [
119
127
  ];
120
128
  async function* audit(deps, categories, options = {}) {
121
129
  const requested = new Set(categories ?? [...ALL_CATEGORIES]);
122
- const orderedCategories = ALL_CATEGORIES.filter((c) => requested.has(c));
123
- const passes = orderedCategories.map(
130
+ const ordered_categories = ALL_CATEGORIES.filter((c) => requested.has(c));
131
+ const passes = ordered_categories.map(
124
132
  (c) => PASS_FACTORIES[c](deps, options)
125
133
  );
126
- const needStats = passes.some((p) => p.onStat !== void 0);
127
- const needStreams = passes.some((p) => p.onStream !== void 0);
128
- const needEvents = passes.some((p) => p.onEvent !== void 0);
129
- if (needStats) {
134
+ const need_stats = passes.some((p) => p.on_stat !== void 0);
135
+ const need_streams = passes.some((p) => p.on_stream !== void 0);
136
+ const need_events = passes.some((p) => p.on_event !== void 0);
137
+ if (need_stats) {
130
138
  const stats = await deps.store().query_stats({}, { count: true, names: true });
131
139
  for (const [stream, s] of stats) {
132
- for (const p of passes) p.onStat?.(stream, s);
140
+ for (const p of passes) p.on_stat?.(stream, s);
133
141
  }
134
142
  }
135
- if (needStreams) {
143
+ if (need_streams) {
136
144
  await deps.store().query_streams((pos) => {
137
- for (const p of passes) p.onStream?.(pos);
145
+ for (const p of passes) p.on_stream?.(pos);
138
146
  });
139
147
  }
140
- if (needEvents) {
148
+ if (need_events) {
141
149
  await deps.store().query((event) => {
142
- for (const p of passes) p.onEvent?.(event);
150
+ for (const p of passes) p.on_event?.(event);
143
151
  }, options.query);
144
152
  }
145
153
  for (const p of passes) await p.finalize?.(deps);
@@ -147,11 +155,11 @@ async function* audit(deps, categories, options = {}) {
147
155
  for (const f of p.drain()) yield f;
148
156
  }
149
157
  }
150
- var makeSchemaPass = (deps) => {
158
+ var make_schema_pass = (deps) => {
151
159
  const findings = [];
152
160
  return {
153
161
  category: "schema",
154
- onEvent(event) {
162
+ on_event(event) {
155
163
  const name = String(event.name);
156
164
  const state2 = deps.event_to_state.get(name);
157
165
  if (!state2) {
@@ -181,19 +189,19 @@ var makeSchemaPass = (deps) => {
181
189
  drain: () => findings
182
190
  };
183
191
  };
184
- var makeDeprecatedLoadPass = (deps, options) => {
192
+ var make_deprecated_load_pass = (deps, options) => {
185
193
  const share_min = options.thresholds?.deprecated_min ?? DEFAULTS.deprecated_min;
186
194
  const totals = /* @__PURE__ */ new Map();
187
- const perStream = /* @__PURE__ */ new Map();
195
+ const per_stream = /* @__PURE__ */ new Map();
188
196
  return {
189
197
  category: "deprecated-load",
190
- onStat(stream, { names }) {
198
+ on_stat(stream, { names }) {
191
199
  for (const [name, count] of Object.entries(names)) {
192
200
  totals.set(name, (totals.get(name) ?? 0) + count);
193
- let m = perStream.get(name);
201
+ let m = per_stream.get(name);
194
202
  if (!m) {
195
203
  m = /* @__PURE__ */ new Map();
196
- perStream.set(name, m);
204
+ per_stream.set(name, m);
197
205
  }
198
206
  m.set(stream, count);
199
207
  }
@@ -202,33 +210,33 @@ var makeDeprecatedLoadPass = (deps, options) => {
202
210
  const findings = [];
203
211
  const grand = [...totals.values()].reduce((s, n) => s + n, 0);
204
212
  if (grand === 0) return findings;
205
- const deprecated = deprecatedEventNames(deps.known_events);
213
+ const deprecated = deprecated_event_names(deps.known_events);
206
214
  const sorted = [...deprecated].map((name) => ({ name, count: totals.get(name) ?? 0 })).sort((a, b) => b.count - a.count);
207
215
  for (const { name, count } of sorted) {
208
216
  if (count === 0) continue;
209
217
  if (count / grand < share_min) continue;
210
- const currentVersion = currentVersionOf(name, deps.known_events);
211
- const topStreams = [...perStream.get(name).entries()].map(([stream, c]) => ({ stream, count: c })).sort((a, b) => b.count - a.count).slice(0, 10);
218
+ const current_version = current_version_of(name, deps.known_events);
219
+ const top_streams = [...per_stream.get(name).entries()].map(([stream, c]) => ({ stream, count: c })).sort((a, b) => b.count - a.count).slice(0, 10);
212
220
  findings.push({
213
221
  category: "deprecated-load",
214
222
  name,
215
- current_version: currentVersion,
223
+ current_version,
216
224
  total: count,
217
- top_streams: topStreams
225
+ top_streams
218
226
  });
219
227
  }
220
228
  return findings;
221
229
  }
222
230
  };
223
231
  };
224
- var makeCloseCandidatePass = (deps, options) => {
232
+ var make_close_candidate_pass = (deps, options) => {
225
233
  const idle_days = options.thresholds?.idle_days ?? DEFAULTS.idle_days;
226
234
  const terminal_events = new Set(options.thresholds?.terminal_events ?? []);
227
235
  const idle_cutoff = Date.now() - idle_days * 24 * 60 * 60 * 1e3;
228
236
  const findings = [];
229
237
  return {
230
238
  category: "close-candidate",
231
- onStat(stream, { head }) {
239
+ on_stat(stream, { head }) {
232
240
  const head_name = String(head.name);
233
241
  if (head_name.startsWith("__")) return;
234
242
  const head_time = head.created.getTime();
@@ -241,22 +249,22 @@ var makeCloseCandidatePass = (deps, options) => {
241
249
  last_event_at: head.created.toISOString(),
242
250
  reason: is_terminal ? "terminal" : "idle",
243
251
  idle_days: is_idle ? Math.floor((Date.now() - head_time) / (24 * 60 * 60 * 1e3)) : void 0,
244
- restart_supported: restartIsSupported(deps, head_name)
252
+ restart_supported: restart_is_supported(deps, head_name)
245
253
  });
246
254
  },
247
255
  drain: () => findings
248
256
  };
249
257
  };
250
- var makeRestartCandidatePass = (deps, options) => {
258
+ var make_restart_candidate_pass = (deps, options) => {
251
259
  const threshold = options.thresholds?.restart_min ?? DEFAULTS.restart_min;
252
260
  const findings = [];
253
261
  return {
254
262
  category: "restart-candidate",
255
- onStat(stream, { head, count, names }) {
263
+ on_stat(stream, { head, count, names }) {
256
264
  if (count < threshold) return;
257
265
  const head_name = String(head.name);
258
266
  if (head_name.startsWith("__")) return;
259
- if (!restartIsSupported(deps, head_name)) return;
267
+ if (!restart_is_supported(deps, head_name)) return;
260
268
  findings.push({
261
269
  category: "restart-candidate",
262
270
  stream,
@@ -270,14 +278,14 @@ var makeRestartCandidatePass = (deps, options) => {
270
278
  drain: () => findings
271
279
  };
272
280
  };
273
- var makeReactionHealthPass = (_deps, options) => {
281
+ var make_reaction_health_pass = (_deps, options) => {
274
282
  const near_block = options.thresholds?.near_block ?? DEFAULTS.near_block;
275
283
  const stuck_minutes = options.thresholds?.stuck_minutes ?? DEFAULTS.stuck_minutes;
276
284
  const stuck_cutoff = Date.now() - stuck_minutes * 60 * 1e3;
277
285
  const findings = [];
278
286
  return {
279
287
  category: "reaction-health",
280
- onStream(p) {
288
+ on_stream(p) {
281
289
  if (p.blocked) {
282
290
  findings.push({
283
291
  category: "reaction-health",
@@ -314,14 +322,14 @@ var makeReactionHealthPass = (_deps, options) => {
314
322
  drain: () => findings
315
323
  };
316
324
  };
317
- var makeSnapshotDriftPass = (deps, options) => {
325
+ var make_snapshot_drift_pass = (deps, options) => {
318
326
  const drift_min = options.thresholds?.drift_min ?? DEFAULTS.drift_min;
319
327
  const candidates = [];
320
328
  const findings = [];
321
329
  return {
322
330
  category: "snapshot-drift",
323
- onStat(stream, { head, count, names }) {
324
- if (!restartIsSupported(deps, String(head.name))) return;
331
+ on_stat(stream, { head, count, names }) {
332
+ if (!restart_is_supported(deps, String(head.name))) return;
325
333
  if (count < drift_min) return;
326
334
  candidates.push({
327
335
  stream,
@@ -370,12 +378,12 @@ var makeSnapshotDriftPass = (deps, options) => {
370
378
  drain: () => findings
371
379
  };
372
380
  };
373
- var makeRoutingHealthPass = (deps) => {
381
+ var make_routing_health_pass = (deps) => {
374
382
  const findings = [];
375
- const seenEventNames = /* @__PURE__ */ new Set();
383
+ const seen_event_names = /* @__PURE__ */ new Set();
376
384
  return {
377
385
  category: "routing-health",
378
- onStream(p) {
386
+ on_stream(p) {
379
387
  if (!p.lane) return;
380
388
  if (deps.declared_lanes.has(p.lane)) return;
381
389
  findings.push({
@@ -385,13 +393,13 @@ var makeRoutingHealthPass = (deps) => {
385
393
  lane: p.lane
386
394
  });
387
395
  },
388
- onStat(_stream, { names }) {
396
+ on_stat(_stream, { names }) {
389
397
  for (const name of Object.keys(names)) {
390
- seenEventNames.add(name);
398
+ seen_event_names.add(name);
391
399
  }
392
400
  },
393
401
  finalize() {
394
- for (const name of seenEventNames) {
402
+ for (const name of seen_event_names) {
395
403
  if (name.startsWith("__")) continue;
396
404
  if (deps.routed_events.has(name)) continue;
397
405
  findings.push({
@@ -405,23 +413,23 @@ var makeRoutingHealthPass = (deps) => {
405
413
  drain: () => findings
406
414
  };
407
415
  };
408
- var makeCorrelationGapsPass = () => {
409
- const seenIds = /* @__PURE__ */ new Set();
416
+ var make_correlation_gaps_pass = () => {
417
+ const seen_ids = /* @__PURE__ */ new Set();
410
418
  const checks = [];
411
419
  return {
412
420
  category: "correlation-gaps",
413
- onEvent(e) {
414
- seenIds.add(e.id);
421
+ on_event(e) {
422
+ seen_ids.add(e.id);
415
423
  const causation = e.meta?.causation;
416
- const parentId = causation?.event?.id;
417
- if (parentId !== void 0) {
418
- checks.push({ stream: e.stream, id: e.id, parentId });
424
+ const parent_id = causation?.event?.id;
425
+ if (parent_id !== void 0) {
426
+ checks.push({ stream: e.stream, id: e.id, parent_id });
419
427
  }
420
428
  },
421
429
  drain() {
422
430
  const findings = [];
423
- for (const { stream, id, parentId } of checks) {
424
- if (!seenIds.has(parentId)) {
431
+ for (const { stream, id, parent_id } of checks) {
432
+ if (!seen_ids.has(parent_id)) {
425
433
  findings.push({
426
434
  category: "correlation-gaps",
427
435
  stream,
@@ -434,12 +442,12 @@ var makeCorrelationGapsPass = () => {
434
442
  }
435
443
  };
436
444
  };
437
- var makeClockAnomaliesPass = () => {
445
+ var make_clock_anomalies_pass = () => {
438
446
  const findings = [];
439
- const lastPerStream = /* @__PURE__ */ new Map();
447
+ const last_per_stream = /* @__PURE__ */ new Map();
440
448
  return {
441
449
  category: "clock-anomalies",
442
- onEvent(e) {
450
+ on_event(e) {
443
451
  const created = e.created.getTime();
444
452
  if (created > Date.now()) {
445
453
  findings.push({
@@ -449,7 +457,7 @@ var makeClockAnomaliesPass = () => {
449
457
  reason: "future-created"
450
458
  });
451
459
  }
452
- const prev = lastPerStream.get(e.stream);
460
+ const prev = last_per_stream.get(e.stream);
453
461
  if (prev !== void 0 && created < prev) {
454
462
  findings.push({
455
463
  category: "clock-anomalies",
@@ -458,48 +466,48 @@ var makeClockAnomaliesPass = () => {
458
466
  reason: "out-of-order"
459
467
  });
460
468
  }
461
- lastPerStream.set(e.stream, created);
469
+ last_per_stream.set(e.stream, created);
462
470
  },
463
471
  drain: () => findings
464
472
  };
465
473
  };
466
- function restartIsSupported(deps, headEventName) {
467
- const state2 = deps.event_to_state.get(headEventName);
474
+ function restart_is_supported(deps, head_event_name) {
475
+ const state2 = deps.event_to_state.get(head_event_name);
468
476
  return state2?.snap !== void 0;
469
477
  }
470
478
  var PASS_FACTORIES = {
471
- schema: makeSchemaPass,
472
- "deprecated-load": makeDeprecatedLoadPass,
473
- "close-candidate": makeCloseCandidatePass,
474
- "restart-candidate": makeRestartCandidatePass,
475
- "reaction-health": makeReactionHealthPass,
476
- "snapshot-drift": makeSnapshotDriftPass,
477
- "routing-health": makeRoutingHealthPass,
478
- "correlation-gaps": makeCorrelationGapsPass,
479
- "clock-anomalies": makeClockAnomaliesPass
479
+ schema: make_schema_pass,
480
+ "deprecated-load": make_deprecated_load_pass,
481
+ "close-candidate": make_close_candidate_pass,
482
+ "restart-candidate": make_restart_candidate_pass,
483
+ "reaction-health": make_reaction_health_pass,
484
+ "snapshot-drift": make_snapshot_drift_pass,
485
+ "routing-health": make_routing_health_pass,
486
+ "correlation-gaps": make_correlation_gaps_pass,
487
+ "clock-anomalies": make_clock_anomalies_pass
480
488
  };
481
489
 
482
490
  // src/internal/build-classify.ts
483
491
  var ALL_LANES = /* @__PURE__ */ Symbol("act-1103/all-lanes");
484
- function classifyRegistry(registry, states) {
492
+ function classify_registry(registry, states) {
485
493
  const statics = /* @__PURE__ */ new Map();
486
- const reactiveEvents = /* @__PURE__ */ new Set();
487
- const eventToLanes = /* @__PURE__ */ new Map();
488
- let hasDynamicResolvers = false;
494
+ const reactive_events = /* @__PURE__ */ new Set();
495
+ const event_to_lanes = /* @__PURE__ */ new Map();
496
+ let has_dynamic_resolvers = false;
489
497
  for (const [name, register] of Object.entries(registry.events)) {
490
- if (register.reactions.size > 0) reactiveEvents.add(name);
498
+ if (register.reactions.size > 0) reactive_events.add(name);
491
499
  for (const reaction of register.reactions.values()) {
492
500
  if (typeof reaction.resolver === "function") {
493
- hasDynamicResolvers = true;
494
- eventToLanes.set(name, ALL_LANES);
501
+ has_dynamic_resolvers = true;
502
+ event_to_lanes.set(name, ALL_LANES);
495
503
  } else {
496
504
  const { target, source, priority = 0, lane } = reaction.resolver;
497
505
  const lane_name = lane ?? "default";
498
- const existing_lanes = eventToLanes.get(name);
506
+ const existing_lanes = event_to_lanes.get(name);
499
507
  if (existing_lanes !== ALL_LANES) {
500
508
  const set = existing_lanes ?? /* @__PURE__ */ new Set();
501
509
  set.add(lane_name);
502
- eventToLanes.set(name, set);
510
+ event_to_lanes.set(name, set);
503
511
  }
504
512
  const key = `${target}|${source ?? ""}`;
505
513
  const existing = statics.get(key);
@@ -517,59 +525,59 @@ function classifyRegistry(registry, states) {
517
525
  }
518
526
  }
519
527
  }
520
- const eventToState = /* @__PURE__ */ new Map();
528
+ const event_to_state = /* @__PURE__ */ new Map();
521
529
  for (const merged of states.values()) {
522
- for (const eventName of Object.keys(merged.events)) {
523
- eventToState.set(eventName, merged);
530
+ for (const event_name of Object.keys(merged.events)) {
531
+ event_to_state.set(event_name, merged);
524
532
  }
525
533
  }
526
534
  return {
527
- staticTargets: [...statics.values()],
528
- hasDynamicResolvers,
529
- reactiveEvents,
530
- eventToState,
531
- eventToLanes
535
+ static_targets: [...statics.values()],
536
+ has_dynamic_resolvers,
537
+ reactive_events,
538
+ event_to_state,
539
+ event_to_lanes
532
540
  };
533
541
  }
534
542
 
535
543
  // src/internal/close-cycle.ts
536
- async function runCloseCycle(targets, deps) {
537
- const targetMap = new Map(targets.map((t) => [t.stream, t]));
538
- const streams = [...targetMap.keys()];
544
+ async function run_close_cycle(targets, deps) {
545
+ const target_map = new Map(targets.map((t) => [t.stream, t]));
546
+ const streams = [...target_map.keys()];
539
547
  const skipped = [];
540
- const streamInfo = await scanStreamHeads(streams);
541
- const safe = await partitionBySafety(
542
- streamInfo,
543
- deps.reactiveEventsSize,
548
+ const stream_info = await scan_stream_heads(streams);
549
+ const safe = await partition_by_safety(
550
+ stream_info,
551
+ deps.reactive_events_size,
544
552
  skipped
545
553
  );
546
554
  if (!safe.length) return { truncated: /* @__PURE__ */ new Map(), skipped };
547
- const { guarded, guardEvents } = await guardWithTombstones(
555
+ const { guarded, guard_events } = await guard_with_tombstones(
548
556
  safe,
549
- streamInfo,
557
+ stream_info,
550
558
  deps.correlation,
551
559
  deps.tombstone,
552
560
  skipped
553
561
  );
554
562
  if (!guarded.length) return { truncated: /* @__PURE__ */ new Map(), skipped };
555
- const seedStates = await loadRestartSeeds(
563
+ const seed_states = await load_restart_seeds(
556
564
  guarded,
557
- targetMap,
558
- streamInfo,
559
- deps.eventToState,
565
+ target_map,
566
+ stream_info,
567
+ deps.event_to_state,
560
568
  deps.load,
561
569
  deps.logger
562
570
  );
563
- await runArchiveCallbacks(guarded, targetMap);
564
- const truncated = await truncateAndWarmCache(
571
+ await run_archive_callbacks(guarded, target_map);
572
+ const truncated = await truncate_and_warm_cache(
565
573
  guarded,
566
- seedStates,
567
- guardEvents,
574
+ seed_states,
575
+ guard_events,
568
576
  deps.correlation
569
577
  );
570
578
  return { truncated, skipped };
571
579
  }
572
- async function scanStreamHeads(streams) {
580
+ async function scan_stream_heads(streams) {
573
581
  const stats = await store().query_stats(streams, {
574
582
  exclude: [SNAP_EVENT]
575
583
  });
@@ -577,76 +585,76 @@ async function scanStreamHeads(streams) {
577
585
  for (const [stream, { head }] of stats) {
578
586
  if (head.name === TOMBSTONE_EVENT) continue;
579
587
  out.set(stream, {
580
- maxId: head.id,
588
+ max_id: head.id,
581
589
  version: head.version,
582
- lastEventName: head.name
590
+ last_event_name: head.name
583
591
  });
584
592
  }
585
593
  return out;
586
594
  }
587
- async function partitionBySafety(streamInfo, reactiveEventsSize, skipped) {
588
- if (reactiveEventsSize === 0) return [...streamInfo.keys()];
589
- const pendingSet = /* @__PURE__ */ new Set();
595
+ async function partition_by_safety(stream_info, reactive_events_size, skipped) {
596
+ if (reactive_events_size === 0) return [...stream_info.keys()];
597
+ const pending_set = /* @__PURE__ */ new Set();
590
598
  await store().query_streams((position) => {
591
- const sourceRe = position.source ? RegExp(position.source) : void 0;
592
- for (const [stream, info] of streamInfo) {
593
- if ((!sourceRe || sourceRe.test(stream)) && position.at < info.maxId) {
594
- pendingSet.add(stream);
599
+ const source_re = position.source ? RegExp(position.source) : void 0;
600
+ for (const [stream, info] of stream_info) {
601
+ if ((!source_re || source_re.test(stream)) && position.at < info.max_id) {
602
+ pending_set.add(stream);
595
603
  }
596
604
  }
597
605
  });
598
606
  const safe = [];
599
- for (const [stream] of streamInfo) {
600
- if (pendingSet.has(stream)) skipped.push(stream);
607
+ for (const [stream] of stream_info) {
608
+ if (pending_set.has(stream)) skipped.push(stream);
601
609
  else safe.push(stream);
602
610
  }
603
611
  return safe;
604
612
  }
605
- async function guardWithTombstones(safe, streamInfo, correlation, tombstone2, skipped) {
613
+ async function guard_with_tombstones(safe, stream_info, correlation, tombstone2, skipped) {
606
614
  const guarded = [];
607
- const guardEvents = /* @__PURE__ */ new Map();
615
+ const guard_events = /* @__PURE__ */ new Map();
608
616
  await Promise.all(
609
617
  safe.map(async (stream) => {
610
- const info = streamInfo.get(stream);
618
+ const info = stream_info.get(stream);
611
619
  const committed = await tombstone2(stream, info.version, correlation);
612
620
  if (committed) {
613
621
  guarded.push(stream);
614
- guardEvents.set(stream, { id: committed.id, stream });
622
+ guard_events.set(stream, { id: committed.id, stream });
615
623
  } else {
616
624
  skipped.push(stream);
617
625
  }
618
626
  })
619
627
  );
620
- return { guarded, guardEvents };
628
+ return { guarded, guard_events };
621
629
  }
622
- async function loadRestartSeeds(guarded, targetMap, streamInfo, eventToState, load2, logger) {
623
- const seedStates = /* @__PURE__ */ new Map();
630
+ async function load_restart_seeds(guarded, target_map, stream_info, event_to_state, load2, logger) {
631
+ const seed_states = /* @__PURE__ */ new Map();
624
632
  await Promise.all(
625
- guarded.filter((s) => targetMap.get(s)?.restart).map(async (stream) => {
626
- const lastEventName = streamInfo.get(stream).lastEventName;
627
- const ownerState = eventToState.get(lastEventName);
628
- if (!ownerState) {
633
+ guarded.filter((s) => target_map.get(s)?.restart).map(async (stream) => {
634
+ const last_event_name = stream_info.get(stream).last_event_name;
635
+ const owner_state = event_to_state.get(last_event_name);
636
+ if (!owner_state) {
629
637
  logger.error(
630
- `Cannot seed restart for "${stream}": no registered state owns event "${lastEventName}". Stream will be tombstoned instead.`
638
+ `Cannot seed restart for "${stream}": no registered state owns event "${last_event_name}". Stream will be tombstoned instead.`
631
639
  );
632
640
  return;
633
641
  }
634
- const snap2 = await load2(ownerState, stream);
635
- seedStates.set(stream, snap2.state);
642
+ const snap2 = await load2(owner_state, stream);
643
+ seed_states.set(stream, snap2.state);
636
644
  })
637
645
  );
638
- return seedStates;
646
+ return seed_states;
639
647
  }
640
- async function runArchiveCallbacks(guarded, targetMap) {
648
+ async function run_archive_callbacks(guarded, target_map) {
641
649
  for (const stream of guarded) {
642
- const archiveFn = targetMap.get(stream)?.archive;
643
- if (archiveFn) await archiveFn();
650
+ const archive_fn = target_map.get(stream)?.archive;
651
+ if (archive_fn) await archive_fn();
644
652
  }
645
653
  }
646
- async function truncateAndWarmCache(guarded, seedStates, guardEvents, correlation) {
647
- const truncTargets = guarded.map((stream) => {
648
- const snapshot = seedStates.get(stream);
649
- const guard = guardEvents.get(stream);
654
+ async function truncate_and_warm_cache(guarded, seed_states, guard_events, correlation) {
655
+ const trunc_targets = guarded.map((stream) => {
656
+ const snapshot = seed_states.get(stream);
657
+ const guard = guard_events.get(stream);
650
658
  return {
651
659
  stream,
652
660
  snapshot,
@@ -658,11 +666,11 @@ async function truncateAndWarmCache(guarded, seedStates, guardEvents, correlatio
658
666
  }
659
667
  };
660
668
  });
661
- const truncated = await store().truncate(truncTargets);
669
+ const truncated = await store().truncate(trunc_targets);
662
670
  await Promise.all(
663
671
  guarded.map(async (stream) => {
664
672
  const entry = truncated.get(stream);
665
- const state2 = seedStates.get(stream);
673
+ const state2 = seed_states.get(stream);
666
674
  if (state2 && entry) {
667
675
  await cache().set(stream, {
668
676
  state: state2,
@@ -690,13 +698,13 @@ var CorrelateCycle = class {
690
698
  _has_dynamic_resolvers;
691
699
  _cd;
692
700
  _on_init;
693
- constructor(registry, staticTargets, hasDynamicResolvers, cd, maxSubscribedStreams, onInit) {
701
+ constructor(registry, static_targets, has_dynamic_resolvers, cd, maxSubscribedStreams, on_init) {
694
702
  this._subscribed = new LruSet(maxSubscribedStreams);
695
703
  this._registry = registry;
696
- this._static_targets = staticTargets;
697
- this._has_dynamic_resolvers = hasDynamicResolvers;
704
+ this._static_targets = static_targets;
705
+ this._has_dynamic_resolvers = has_dynamic_resolvers;
698
706
  this._cd = cd;
699
- this._on_init = onInit;
707
+ this._on_init = on_init;
700
708
  }
701
709
  /** Last correlated event id. */
702
710
  get checkpoint() {
@@ -707,7 +715,7 @@ var CorrelateCycle = class {
707
715
  * - Reads max(at) from store as cold-start checkpoint
708
716
  * - Subscribes static resolver targets (idempotent upsert)
709
717
  * - Populates the subscribed-streams LRU
710
- * - Fires `onInit` once (Act uses this to flag a cold-start drain)
718
+ * - Fires `on_init` once (Act uses this to flag a cold-start drain)
711
719
  */
712
720
  async init() {
713
721
  if (this._initialized) return;
@@ -740,15 +748,15 @@ var CorrelateCycle = class {
740
748
  if (typeof reaction.resolver !== "function") continue;
741
749
  const resolved = reaction.resolver(event);
742
750
  if (resolved && !this._subscribed.has(resolved.target)) {
743
- const incomingPriority = resolved.priority ?? 0;
751
+ const incoming_priority = resolved.priority ?? 0;
744
752
  const entry = correlated.get(resolved.target) || {
745
753
  source: resolved.source,
746
- priority: incomingPriority,
754
+ priority: incoming_priority,
747
755
  lane: resolved.lane,
748
756
  payloads: []
749
757
  };
750
- if (incomingPriority > entry.priority)
751
- entry.priority = incomingPriority;
758
+ if (incoming_priority > entry.priority)
759
+ entry.priority = incoming_priority;
752
760
  entry.payloads.push({
753
761
  ...reaction,
754
762
  source: resolved.source,
@@ -787,7 +795,7 @@ var CorrelateCycle = class {
787
795
  * running. Errors from `correlate()` are routed through `log()` so they
788
796
  * land in the configured logger (the timer keeps running on failure).
789
797
  */
790
- startPolling(query = {}, frequency = 1e4, callback) {
798
+ start_polling(query = {}, frequency = 1e4, callback) {
791
799
  if (this._timer) return false;
792
800
  const limit = query.limit || 100;
793
801
  this._timer = setInterval(
@@ -799,7 +807,7 @@ var CorrelateCycle = class {
799
807
  return true;
800
808
  }
801
809
  /** Stop the periodic correlation worker. Idempotent. */
802
- stopPolling() {
810
+ stop_polling() {
803
811
  if (this._timer) {
804
812
  clearInterval(this._timer);
805
813
  this._timer = void 0;
@@ -815,14 +823,14 @@ var SEG_SPACE = BASE ** SEG_WIDTH;
815
823
  function seg(n) {
816
824
  return n.toString(BASE).padStart(SEG_WIDTH, "0");
817
825
  }
818
- var defaultCorrelator = ({ state: state2, action: action2 }) => {
826
+ var default_correlator = ({ state: state2, action: action2 }) => {
819
827
  const s = state2.slice(0, SEG_WIDTH).toLowerCase();
820
828
  const a = action2.slice(0, SEG_WIDTH).toLowerCase();
821
829
  const ts = seg(Date.now() % SEG_SPACE);
822
830
  const rnd = seg(randomInt(SEG_SPACE));
823
831
  return `${s}-${a}-${ts}${rnd}`;
824
832
  };
825
- function closeCorrelation(correlator, actor) {
833
+ function close_correlation(correlator, actor) {
826
834
  return correlator({
827
835
  state: "$close",
828
836
  action: "close",
@@ -838,7 +846,7 @@ import { randomUUID } from "crypto";
838
846
  var RATIO_MIN = 0.2;
839
847
  var RATIO_MAX = 0.8;
840
848
  var RATIO_DEFAULT = 0.5;
841
- function computeLagLeadRatio(handled, lagging, leading) {
849
+ function compute_lag_lead_ratio(handled, lagging, leading) {
842
850
  let lagging_handled = 0;
843
851
  let leading_handled = 0;
844
852
  for (const { lease, handled: count } of handled) {
@@ -875,7 +883,7 @@ var subscribe = (streams) => store().subscribe(streams);
875
883
  import { patch } from "@rotorsoft/act-patch";
876
884
 
877
885
  // src/internal/backoff.ts
878
- function computeBackoffDelay(retry, opts) {
886
+ function compute_backoff_delay(retry, opts) {
879
887
  if (!opts || opts.baseMs <= 0) return 0;
880
888
  const r = Math.max(0, retry);
881
889
  let delay;
@@ -1044,9 +1052,9 @@ async function scan(source, opts = {}, callback) {
1044
1052
  }
1045
1053
  };
1046
1054
  }
1047
- async function load(me, stream, callback, asOf) {
1048
- const timeTravel = !!asOf && Object.values(asOf).some((v) => v !== void 0);
1049
- const cached = timeTravel ? void 0 : await cache().get(stream);
1055
+ async function load(me, stream, callback, asOf, actor) {
1056
+ const time_travel = !!asOf && Object.values(asOf).some((v) => v !== void 0);
1057
+ const cached = time_travel ? void 0 : await cache().get(stream);
1050
1058
  const cache_hit = !!cached;
1051
1059
  let state2 = cached?.state ?? (me.init ? me.init() : {});
1052
1060
  let patches = cached?.patches ?? 0;
@@ -1056,15 +1064,16 @@ async function load(me, stream, callback, asOf) {
1056
1064
  let event;
1057
1065
  await store().query(
1058
1066
  (e) => {
1059
- event = e;
1060
1067
  version = e.version;
1068
+ const typed = e;
1069
+ event = me.view(typed, actor);
1061
1070
  if (e.name === SNAP_EVENT) {
1062
1071
  state2 = e.data;
1063
1072
  snaps++;
1064
1073
  patches = 0;
1065
1074
  replayed++;
1066
1075
  } else if (me.patch[e.name]) {
1067
- state2 = patch(state2, me.patch[e.name](event, state2));
1076
+ state2 = patch(state2, me.patch[e.name](typed, state2));
1068
1077
  patches++;
1069
1078
  replayed++;
1070
1079
  } else if (e.name !== TOMBSTONE_EVENT) {
@@ -1088,7 +1097,7 @@ async function load(me, stream, callback, asOf) {
1088
1097
  ...cached ? { after: cached.event_id } : { with_snaps: true, ...asOf }
1089
1098
  }
1090
1099
  );
1091
- if (replayed > 0 && !timeTravel && event) {
1100
+ if (replayed > 0 && !time_travel && event) {
1092
1101
  await cache().set(stream, {
1093
1102
  state: state2,
1094
1103
  version,
@@ -1099,15 +1108,21 @@ async function load(me, stream, callback, asOf) {
1099
1108
  }
1100
1109
  return { event, state: state2, version, patches, snaps, cache_hit, replayed };
1101
1110
  }
1102
- async function action(me, action2, target, payload, reactingTo, skipValidation = false, correlator = defaultCorrelator) {
1111
+ async function action(me, action2, target, payload, reactingTo, skipValidation = false, correlator = default_correlator) {
1103
1112
  const { stream, expectedVersion, actor } = target;
1104
1113
  if (!stream) throw new Error("Missing target stream");
1105
1114
  const validated = skipValidation ? payload : validate(action2, payload, me.actions[action2]);
1106
1115
  const opts = me.options?.[action2];
1107
- const maxRetries = opts?.maxRetries ?? 0;
1116
+ const max_retries = opts?.maxRetries ?? 0;
1108
1117
  for (let attempt = 0; ; attempt++) {
1109
1118
  try {
1110
- const snapshot = await load(me, stream);
1119
+ const snapshot = await load(
1120
+ me,
1121
+ stream,
1122
+ void 0,
1123
+ void 0,
1124
+ target.actor
1125
+ );
1111
1126
  if (snapshot.event?.name === TOMBSTONE_EVENT)
1112
1127
  throw new StreamClosedError(stream);
1113
1128
  const expected = expectedVersion ?? snapshot.event?.version;
@@ -1144,10 +1159,10 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1144
1159
  }
1145
1160
  }
1146
1161
  }
1147
- const emitted = tuples.map(([name, data]) => ({
1148
- name,
1149
- data: skipValidation ? data : validate(name, data, me.events[name])
1150
- }));
1162
+ const emitted = tuples.map(([name, data]) => {
1163
+ const validated2 = skipValidation ? data : validate(name, data, me.events[name]);
1164
+ return me.message({ name, data: validated2 });
1165
+ });
1151
1166
  const meta = {
1152
1167
  correlation: reactingTo?.meta.correlation || correlator({
1153
1168
  action: action2,
@@ -1159,8 +1174,8 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1159
1174
  action: {
1160
1175
  name: action2,
1161
1176
  ...target
1162
- // payload intentionally omitted: it can be large or contain PII,
1163
- // and callers correlate via the correlation id when they need it.
1177
+ // payload intentionally omitted from causation metadata
1178
+ // callers correlate via the correlation id when they need it.
1164
1179
  },
1165
1180
  event: reactingTo ? {
1166
1181
  id: reactingTo.id,
@@ -1193,7 +1208,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1193
1208
  state2 = patch(state2, p);
1194
1209
  patches++;
1195
1210
  return {
1196
- event,
1211
+ event: me.view(event, target.actor),
1197
1212
  state: state2,
1198
1213
  version: event.version,
1199
1214
  patches,
@@ -1216,10 +1231,10 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1216
1231
  return snapshots;
1217
1232
  } catch (error) {
1218
1233
  if (!(error instanceof ConcurrencyError)) throw error;
1219
- if (attempt >= maxRetries) throw error;
1234
+ if (attempt >= max_retries) throw error;
1220
1235
  if (opts?.backoff) {
1221
- const delayMs = computeBackoffDelay(attempt, opts.backoff);
1222
- if (delayMs > 0) await sleep(delayMs);
1236
+ const delay_ms = compute_backoff_delay(attempt, opts.backoff);
1237
+ if (delay_ms > 0) await sleep(delay_ms);
1223
1238
  }
1224
1239
  }
1225
1240
  }
@@ -1243,12 +1258,12 @@ var C_STREAM = "\x1B[38;5;226m";
1243
1258
  var dim = (text) => PRETTY ? `${C_DIM}${text}${C_RESET}` : text;
1244
1259
  var hue = (color, text) => PRETTY ? `${color}${text}${C_RESET}` : text;
1245
1260
  var drain_caption = (caption, lane) => {
1246
- const showLane = lane && lane !== "default";
1261
+ const show_lane = lane && lane !== "default";
1247
1262
  if (PRETTY) {
1248
1263
  const tag = `${C_DRAIN}>> ${caption}${C_RESET}`;
1249
- return showLane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;
1264
+ return show_lane ? `${tag} ${C_LANE}${lane}${C_RESET}` : tag;
1250
1265
  }
1251
- return showLane ? `>> ${caption} ${lane}` : `>> ${caption}`;
1266
+ return show_lane ? `>> ${caption} ${lane}` : `>> ${caption}`;
1252
1267
  };
1253
1268
  var cache_marker = (hit) => {
1254
1269
  const word = hit ? "hit" : "miss";
@@ -1277,10 +1292,10 @@ var traced = (inner, exit, entry) => (async (...args) => {
1277
1292
  exit?.(result, ...args);
1278
1293
  return result;
1279
1294
  });
1280
- function buildEs(logger, correlator = defaultCorrelator) {
1281
- const boundAction = (me, actionName, target, payload, reactingTo, skipValidation = false) => action(
1295
+ function build_es(logger, correlator = default_correlator) {
1296
+ const bound_action = (me, action_name, target, payload, reactingTo, skipValidation = false) => action(
1282
1297
  me,
1283
- actionName,
1298
+ action_name,
1284
1299
  target,
1285
1300
  payload,
1286
1301
  reactingTo,
@@ -1291,7 +1306,7 @@ function buildEs(logger, correlator = defaultCorrelator) {
1291
1306
  return {
1292
1307
  snap,
1293
1308
  load,
1294
- action: boundAction,
1309
+ action: bound_action,
1295
1310
  tombstone
1296
1311
  };
1297
1312
  }
@@ -1321,7 +1336,7 @@ function buildEs(logger, correlator = defaultCorrelator) {
1321
1336
  );
1322
1337
  }),
1323
1338
  action: traced(
1324
- boundAction,
1339
+ bound_action,
1325
1340
  (snapshots, _me, _action, target) => {
1326
1341
  const committed = snapshots.filter((s) => s.event);
1327
1342
  if (committed.length) {
@@ -1350,7 +1365,7 @@ function buildEs(logger, correlator = defaultCorrelator) {
1350
1365
  })
1351
1366
  };
1352
1367
  }
1353
- function buildDrain(logger) {
1368
+ function build_drain(logger) {
1354
1369
  return {
1355
1370
  claim,
1356
1371
  fetch,
@@ -1359,46 +1374,48 @@ function buildDrain(logger) {
1359
1374
  subscribe: logger.level !== "trace" ? subscribe : traced(subscribe, (result, streams) => {
1360
1375
  if (!result.subscribed) return;
1361
1376
  const lanes = new Set(streams.map((s) => s.lane ?? "default"));
1362
- const uniformLane = lanes.size === 1 ? streams[0]?.lane : void 0;
1377
+ const uniform_lane = lanes.size === 1 ? streams[0]?.lane : void 0;
1363
1378
  const data = streams.map(
1364
- ({ stream, lane }) => uniformLane || !lane || lane === "default" ? hue(C_STREAM, stream) : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`
1379
+ ({ stream, lane }) => uniform_lane || !lane || lane === "default" ? hue(C_STREAM, stream) : `${hue(C_STREAM, stream)}${dim(`[${lane}]`)}`
1365
1380
  ).join(" ");
1366
- logger.trace(`${drain_caption("correlated", uniformLane)} ${data}`);
1381
+ logger.trace(
1382
+ `${drain_caption("correlated", uniform_lane)} ${data}`
1383
+ );
1367
1384
  })
1368
1385
  };
1369
1386
  }
1370
- function traceCycle(logger, leased, fetched, handled, acked, blocked) {
1387
+ function trace_cycle(logger, leased, fetched, handled, acked, blocked) {
1371
1388
  if (logger.level !== "trace" || !leased.length) return;
1372
1389
  const lane = leased[0]?.lane;
1373
- const fetchByStream = new Map(fetched.map((f) => [f.stream, f]));
1374
- const ackedByStream = new Map(acked.map((a) => [a.stream, a.at]));
1375
- const blockedByStream = new Map(blocked.map((b) => [b.stream, b.error]));
1376
- const failedByStream = new Map(
1390
+ const fetch_by_stream = new Map(fetched.map((f) => [f.stream, f]));
1391
+ const acked_by_stream = new Map(acked.map((a) => [a.stream, a.at]));
1392
+ const blocked_by_stream = new Map(blocked.map((b) => [b.stream, b.error]));
1393
+ const failed_by_stream = new Map(
1377
1394
  handled.filter((h) => h.error).map((h) => [h.lease.stream, h])
1378
1395
  );
1379
1396
  const detail = leased.map(({ stream, at, retry }) => {
1380
- const f = fetchByStream.get(stream);
1397
+ const f = fetch_by_stream.get(stream);
1381
1398
  const key = f?.source ? `${hue(C_STREAM, stream)}${dim(`<-${f.source}`)}` : hue(C_STREAM, stream);
1382
1399
  const events = f && f.events.length ? ` ${dim(
1383
1400
  `[${f.events.map(({ id, name }) => `#${id} ${String(name)}`).join(", ")}]`
1384
1401
  )}` : "";
1385
- const ackedAt = ackedByStream.get(stream);
1386
- const ackPart = ackedAt !== void 0 ? hue(C_HIT, `\u2713 @${ackedAt}`) : "";
1387
- const failure = failedByStream.get(stream);
1388
- let failPart = "";
1402
+ const acked_at = acked_by_stream.get(stream);
1403
+ const ack_part = acked_at !== void 0 ? hue(C_HIT, `\u2713 @${acked_at}`) : "";
1404
+ const failure = failed_by_stream.get(stream);
1405
+ let fail_part = "";
1389
1406
  if (failure) {
1390
- const failedAt = failure.failed_at ?? at;
1391
- const blockedError = blockedByStream.get(stream);
1392
- if (blockedError !== void 0) {
1393
- failPart = `${hue(C_ERR, `\u2717 @${failedAt}/${retry}`)} ${dim(`(${blockedError})`)}`;
1407
+ const failed_at = failure.failed_at ?? at;
1408
+ const blocked_error = blocked_by_stream.get(stream);
1409
+ if (blocked_error !== void 0) {
1410
+ fail_part = `${hue(C_ERR, `\u2717 @${failed_at}/${retry}`)} ${dim(`(${blocked_error})`)}`;
1394
1411
  } else {
1395
- failPart = `${hue(C_MISS, `\u26A0 @${failedAt}/${retry}`)} ${dim(`(${failure.error})`)}`;
1412
+ fail_part = `${hue(C_MISS, `\u26A0 @${failed_at}/${retry}`)} ${dim(`(${failure.error})`)}`;
1396
1413
  }
1397
1414
  }
1398
1415
  let tail;
1399
- if (ackPart && failPart) tail = ` ${ackPart} ${failPart}`;
1400
- else if (ackPart) tail = ` ${ackPart}`;
1401
- else if (failPart) tail = ` ${failPart}`;
1416
+ if (ack_part && fail_part) tail = ` ${ack_part} ${fail_part}`;
1417
+ else if (ack_part) tail = ` ${ack_part}`;
1418
+ else if (fail_part) tail = ` ${fail_part}`;
1402
1419
  else tail = ` ${dim(`\u2298 @${at}/${retry}`)}`;
1403
1420
  return `${key}${events}${tail}`;
1404
1421
  }).join(", ");
@@ -1406,7 +1423,7 @@ function traceCycle(logger, leased, fetched, handled, acked, blocked) {
1406
1423
  }
1407
1424
 
1408
1425
  // src/internal/drain-cycle.ts
1409
- async function runDrainCycle(ops, registry, batchHandlers, handle, handleBatch, lagging, leading, eventLimit, leaseMillis, isDeferred, lane) {
1426
+ async function run_drain_cycle(ops, registry, batch_handlers, handle, handle_batch, lagging, leading, eventLimit, leaseMillis, is_deferred, lane) {
1410
1427
  const leased = await ops.claim(
1411
1428
  lagging,
1412
1429
  leading,
@@ -1415,7 +1432,7 @@ async function runDrainCycle(ops, registry, batchHandlers, handle, handleBatch,
1415
1432
  lane
1416
1433
  );
1417
1434
  if (!leased.length) return void 0;
1418
- const active = isDeferred ? leased.filter((l) => !isDeferred(l.stream)) : leased;
1435
+ const active = is_deferred ? leased.filter((l) => !is_deferred(l.stream)) : leased;
1419
1436
  if (!active.length) {
1420
1437
  return {
1421
1438
  leased,
@@ -1426,7 +1443,7 @@ async function runDrainCycle(ops, registry, batchHandlers, handle, handleBatch,
1426
1443
  };
1427
1444
  }
1428
1445
  const fetched = await ops.fetch(active, eventLimit);
1429
- const fetchMap = /* @__PURE__ */ new Map();
1446
+ const fetch_map = /* @__PURE__ */ new Map();
1430
1447
  const fetch_window_at = fetched.reduce(
1431
1448
  (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),
1432
1449
  0
@@ -1441,16 +1458,16 @@ async function runDrainCycle(ops, registry, batchHandlers, handle, handleBatch,
1441
1458
  return resolved && resolved.target === stream;
1442
1459
  }).map((reaction) => ({ ...reaction, event }));
1443
1460
  });
1444
- fetchMap.set(stream, { fetch: f, payloads });
1461
+ fetch_map.set(stream, { fetch: f, payloads });
1445
1462
  }
1446
1463
  const handled = await Promise.all(
1447
1464
  active.map((lease) => {
1448
- const entry = fetchMap.get(lease.stream);
1465
+ const entry = fetch_map.get(lease.stream);
1449
1466
  const at = entry.fetch.events.at(-1)?.id || fetch_window_at;
1450
1467
  const { payloads } = entry;
1451
- const batchHandler = batchHandlers.get(lease.stream);
1468
+ const batchHandler = batch_handlers.get(lease.stream);
1452
1469
  if (batchHandler && payloads.length > 0) {
1453
- return handleBatch({ ...lease, at }, payloads, batchHandler);
1470
+ return handle_batch({ ...lease, at }, payloads, batchHandler);
1454
1471
  }
1455
1472
  return handle({ ...lease, at }, payloads);
1456
1473
  })
@@ -1474,14 +1491,14 @@ var DrainController = class {
1474
1491
  _locked = false;
1475
1492
  _ratio = 0.5;
1476
1493
  /**
1477
- * Per-stream backoff: `stream → nextAttemptAt` (ms since epoch). Set by
1478
- * `_finalize` via `HandleResult.nextAttemptAt`; cleared on successful
1494
+ * Per-stream backoff: `stream → next_attempt_at` (ms since epoch). Set by
1495
+ * `_finalize` via `HandleResult.next_attempt_at`; cleared on successful
1479
1496
  * ack or terminal block. Lives in process memory — per-worker pacing
1480
1497
  * by design (see {@link BackoffOptions} for the multi-worker trade-off).
1481
1498
  */
1482
1499
  _backoff = /* @__PURE__ */ new Map();
1483
- /** Timer re-arming drain at the earliest pending `nextAttemptAt`. */
1484
- _backoffTimer;
1500
+ /** Timer re-arming drain at the earliest pending `next_attempt_at`. */
1501
+ _backoff_timer;
1485
1502
  /** Worker timer (ACT-1103). Set when `start()` is active, undefined otherwise. */
1486
1503
  _worker;
1487
1504
  _stopped = false;
@@ -1502,7 +1519,7 @@ var DrainController = class {
1502
1519
  return this._armed;
1503
1520
  }
1504
1521
  /** Returns true when `stream` is currently within a backoff window. */
1505
- isDeferred = (stream) => {
1522
+ is_deferred = (stream) => {
1506
1523
  const next = this._backoff.get(stream);
1507
1524
  return next !== void 0 && next > Date.now();
1508
1525
  };
@@ -1512,20 +1529,20 @@ var DrainController = class {
1512
1529
  * Idempotent — collapses many simultaneously deferred streams into a
1513
1530
  * single timer.
1514
1531
  */
1515
- scheduleBackoffWake() {
1516
- if (this._backoffTimer) clearTimeout(this._backoffTimer);
1532
+ schedule_backoff_wake() {
1533
+ if (this._backoff_timer) clearTimeout(this._backoff_timer);
1517
1534
  let earliest = Number.POSITIVE_INFINITY;
1518
1535
  for (const t of this._backoff.values()) if (t < earliest) earliest = t;
1519
1536
  const delay = Math.max(0, earliest - Date.now());
1520
- this._backoffTimer = setTimeout(() => {
1521
- this._backoffTimer = void 0;
1537
+ this._backoff_timer = setTimeout(() => {
1538
+ this._backoff_timer = void 0;
1522
1539
  const now = Date.now();
1523
1540
  for (const [stream, at] of this._backoff) {
1524
1541
  if (at <= now) this._backoff.delete(stream);
1525
1542
  }
1526
1543
  this._armed = true;
1527
1544
  }, delay);
1528
- this._backoffTimer.unref();
1545
+ this._backoff_timer.unref();
1529
1546
  }
1530
1547
  /** Lane this controller drains (undefined = legacy single-lane span). */
1531
1548
  get lane() {
@@ -1571,17 +1588,17 @@ var DrainController = class {
1571
1588
  this._locked = true;
1572
1589
  const lagging = Math.ceil(streamLimit * this._ratio);
1573
1590
  const leading = streamLimit - lagging;
1574
- const cycle = await runDrainCycle(
1591
+ const cycle = await run_drain_cycle(
1575
1592
  this._deps.ops,
1576
1593
  this._deps.registry,
1577
- this._deps.batchHandlers,
1594
+ this._deps.batch_handlers,
1578
1595
  this._deps.handle,
1579
- this._deps.handleBatch,
1596
+ this._deps.handle_batch,
1580
1597
  lagging,
1581
1598
  leading,
1582
1599
  eventLimit,
1583
1600
  leaseMillis,
1584
- this._backoff.size > 0 ? this.isDeferred : void 0,
1601
+ this._backoff.size > 0 ? this.is_deferred : void 0,
1585
1602
  this._deps.lane
1586
1603
  );
1587
1604
  if (!cycle) {
@@ -1589,20 +1606,20 @@ var DrainController = class {
1589
1606
  return EMPTY_DRAIN;
1590
1607
  }
1591
1608
  const { leased, fetched, handled, acked, blocked } = cycle;
1592
- traceCycle(this._deps.logger, leased, fetched, handled, acked, blocked);
1593
- this._ratio = computeLagLeadRatio(handled, lagging, leading);
1609
+ trace_cycle(this._deps.logger, leased, fetched, handled, acked, blocked);
1610
+ this._ratio = compute_lag_lead_ratio(handled, lagging, leading);
1594
1611
  for (const lease of acked) this._backoff.delete(lease.stream);
1595
1612
  for (const lease of blocked) this._backoff.delete(lease.stream);
1596
1613
  for (const h of handled) {
1597
- if (h.nextAttemptAt !== void 0 && !h.block) {
1598
- this._backoff.set(h.lease.stream, h.nextAttemptAt);
1614
+ if (h.next_attempt_at !== void 0 && !h.block) {
1615
+ this._backoff.set(h.lease.stream, h.next_attempt_at);
1599
1616
  }
1600
1617
  }
1601
- if (this._backoff.size > 0) this.scheduleBackoffWake();
1602
- if (acked.length) this._deps.onAcked(acked);
1603
- if (blocked.length) this._deps.onBlocked(blocked);
1604
- const hasErrors = handled.some(({ error }) => error);
1605
- if (!acked.length && !blocked.length && !hasErrors) this._armed = false;
1618
+ if (this._backoff.size > 0) this.schedule_backoff_wake();
1619
+ if (acked.length) this._deps.on_acked(acked);
1620
+ if (blocked.length) this._deps.on_blocked(blocked);
1621
+ const has_errors = handled.some(({ error }) => error);
1622
+ if (!acked.length && !blocked.length && !has_errors) this._armed = false;
1606
1623
  return { fetched, leased, acked, blocked };
1607
1624
  } catch (error) {
1608
1625
  this._deps.logger.error(error);
@@ -1615,44 +1632,44 @@ var DrainController = class {
1615
1632
 
1616
1633
  // src/internal/merge.ts
1617
1634
  import { ZodObject } from "zod";
1618
- function baseTypeName(zodType) {
1635
+ function base_type_name(zodType) {
1619
1636
  let t = zodType;
1620
1637
  while (typeof t.unwrap === "function") {
1621
1638
  t = t.unwrap();
1622
1639
  }
1623
1640
  return t.constructor.name;
1624
1641
  }
1625
- function mergeSchemas(existing, incoming, stateName) {
1642
+ function merge_schemas(existing, incoming, state_name) {
1626
1643
  if (existing instanceof ZodObject && incoming instanceof ZodObject) {
1627
- const existingShape = existing.shape;
1628
- const incomingShape = incoming.shape;
1629
- for (const key of Object.keys(incomingShape)) {
1630
- if (key in existingShape) {
1631
- const existingBase = baseTypeName(existingShape[key]);
1632
- const incomingBase = baseTypeName(incomingShape[key]);
1633
- if (existingBase !== incomingBase) {
1644
+ const existing_shape = existing.shape;
1645
+ const incoming_shape = incoming.shape;
1646
+ for (const key of Object.keys(incoming_shape)) {
1647
+ if (key in existing_shape) {
1648
+ const existing_base = base_type_name(existing_shape[key]);
1649
+ const incoming_base = base_type_name(incoming_shape[key]);
1650
+ if (existing_base !== incoming_base) {
1634
1651
  throw new Error(
1635
- `Schema conflict in "${stateName}": key "${key}" has type "${existingBase}" but incoming partial declares "${incomingBase}"`
1652
+ `Schema conflict in "${state_name}": key "${key}" has type "${existing_base}" but incoming partial declares "${incoming_base}"`
1636
1653
  );
1637
1654
  }
1638
1655
  }
1639
1656
  }
1640
- return existing.extend(incomingShape);
1657
+ return existing.extend(incoming_shape);
1641
1658
  }
1642
1659
  return existing;
1643
1660
  }
1644
- function mergeInits(existing, incoming) {
1661
+ function merge_inits(existing, incoming) {
1645
1662
  return () => ({ ...existing(), ...incoming() });
1646
1663
  }
1647
- function registerState(state2, states, actions, events) {
1664
+ function register_state(state2, states, actions, events) {
1648
1665
  const existing = states.get(state2.name);
1649
1666
  if (existing) {
1650
- mergeIntoExisting(state2, existing, states, actions, events);
1667
+ merge_into_existing(state2, existing, states, actions, events);
1651
1668
  } else {
1652
- registerNewState(state2, states, actions, events);
1669
+ register_new_state(state2, states, actions, events);
1653
1670
  }
1654
1671
  }
1655
- function registerNewState(state2, states, actions, events) {
1672
+ function register_new_state(state2, states, actions, events) {
1656
1673
  states.set(state2.name, state2);
1657
1674
  for (const name of Object.keys(state2.actions)) {
1658
1675
  if (actions[name]) throw new Error(`Duplicate action "${name}"`);
@@ -1663,7 +1680,7 @@ function registerNewState(state2, states, actions, events) {
1663
1680
  events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
1664
1681
  }
1665
1682
  }
1666
- function mergeIntoExisting(state2, existing, states, actions, events) {
1683
+ function merge_into_existing(state2, existing, states, actions, events) {
1667
1684
  for (const name of Object.keys(state2.actions)) {
1668
1685
  if (existing.actions[name] === state2.actions[name]) continue;
1669
1686
  if (actions[name]) throw new Error(`Duplicate action "${name}"`);
@@ -1677,14 +1694,14 @@ function mergeIntoExisting(state2, existing, states, actions, events) {
1677
1694
  }
1678
1695
  if (events[name]) throw new Error(`Duplicate event "${name}"`);
1679
1696
  }
1680
- const mergedPatch = mergePatches(existing.patch, state2.patch, state2.name);
1697
+ const merged_patch = merge_patches(existing.patch, state2.patch, state2.name);
1681
1698
  const merged = {
1682
1699
  ...existing,
1683
- state: mergeSchemas(existing.state, state2.state, state2.name),
1684
- init: mergeInits(existing.init, state2.init),
1700
+ state: merge_schemas(existing.state, state2.state, state2.name),
1701
+ init: merge_inits(existing.init, state2.init),
1685
1702
  events: { ...existing.events, ...state2.events },
1686
1703
  actions: { ...existing.actions, ...state2.actions },
1687
- patch: mergedPatch,
1704
+ patch: merged_patch,
1688
1705
  on: { ...existing.on, ...state2.on },
1689
1706
  given: { ...existing.given, ...state2.given },
1690
1707
  snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
@@ -1702,48 +1719,48 @@ function mergeIntoExisting(state2, existing, states, actions, events) {
1702
1719
  events[name] = { schema: state2.events[name], reactions: /* @__PURE__ */ new Map() };
1703
1720
  }
1704
1721
  }
1705
- function mergePatches(existing, incoming, stateName) {
1722
+ function merge_patches(existing, incoming, state_name) {
1706
1723
  const merged = { ...existing };
1707
1724
  for (const name of Object.keys(incoming)) {
1708
- const existingP = existing[name];
1709
- const incomingP = incoming[name];
1710
- if (!existingP) {
1711
- merged[name] = incomingP;
1725
+ const existing_p = existing[name];
1726
+ const incoming_p = incoming[name];
1727
+ if (!existing_p) {
1728
+ merged[name] = incoming_p;
1712
1729
  continue;
1713
1730
  }
1714
- const existingIsDefault = existingP._passthrough;
1715
- const incomingIsDefault = incomingP._passthrough;
1716
- if (!existingIsDefault && !incomingIsDefault && existingP !== incomingP) {
1731
+ const existing_is_default = existing_p._passthrough;
1732
+ const incoming_is_default = incoming_p._passthrough;
1733
+ if (!existing_is_default && !incoming_is_default && existing_p !== incoming_p) {
1717
1734
  throw new Error(
1718
- `Duplicate custom patch for event "${name}" in state "${stateName}"`
1735
+ `Duplicate custom patch for event "${name}" in state "${state_name}"`
1719
1736
  );
1720
1737
  }
1721
- if (existingIsDefault && !incomingIsDefault) {
1722
- merged[name] = incomingP;
1738
+ if (existing_is_default && !incoming_is_default) {
1739
+ merged[name] = incoming_p;
1723
1740
  }
1724
1741
  }
1725
1742
  return merged;
1726
1743
  }
1727
- function mergeEventRegister(target, source) {
1728
- for (const [eventName, sourceReg] of Object.entries(source)) {
1729
- const targetReg = target[eventName];
1730
- if (!targetReg) continue;
1731
- for (const [name, reaction] of sourceReg.reactions) {
1732
- targetReg.reactions.set(name, reaction);
1744
+ function merge_event_register(target, source) {
1745
+ for (const [event_name, source_reg] of Object.entries(source)) {
1746
+ const target_reg = target[event_name];
1747
+ if (!target_reg) continue;
1748
+ for (const [name, reaction] of source_reg.reactions) {
1749
+ target_reg.reactions.set(name, reaction);
1733
1750
  }
1734
1751
  }
1735
1752
  }
1736
- function mergeProjection(proj, events) {
1737
- for (const eventName of Object.keys(proj.events)) {
1738
- const projRegister = proj.events[eventName];
1739
- const existing = events[eventName];
1753
+ function merge_projection(proj, events) {
1754
+ for (const event_name of Object.keys(proj.events)) {
1755
+ const proj_register = proj.events[event_name];
1756
+ const existing = events[event_name];
1740
1757
  if (!existing) {
1741
- events[eventName] = {
1742
- schema: projRegister.schema,
1743
- reactions: new Map(projRegister.reactions)
1758
+ events[event_name] = {
1759
+ schema: proj_register.schema,
1760
+ reactions: new Map(proj_register.reactions)
1744
1761
  };
1745
1762
  } else {
1746
- for (const [name, reaction] of projRegister.reactions) {
1763
+ for (const [name, reaction] of proj_register.reactions) {
1747
1764
  let key = name;
1748
1765
  while (existing.reactions.has(key)) key = `${key}_p`;
1749
1766
  existing.reactions.set(key, reaction);
@@ -1760,25 +1777,32 @@ var _this_ = ({ stream }) => ({
1760
1777
  function finalize(lease, handled, at, error, options, logger, failed_at) {
1761
1778
  if (!error) return { lease, handled, acked_at: at };
1762
1779
  logger.error(error);
1763
- const nonRetryable = error instanceof NonRetryableError;
1764
- const block2 = options.blockOnError && (nonRetryable || lease.retry >= options.maxRetries);
1780
+ const non_retryable = error instanceof NonRetryableError;
1781
+ const block2 = options.blockOnError && (non_retryable || lease.retry >= options.maxRetries);
1765
1782
  if (block2)
1766
1783
  logger.error(
1767
- nonRetryable ? `Blocking ${lease.stream} on non-retryable error.` : `Blocking ${lease.stream} after ${lease.retry} retries.`
1784
+ non_retryable ? `Blocking ${lease.stream} on non-retryable error.` : `Blocking ${lease.stream} after ${lease.retry} retries.`
1768
1785
  );
1769
- const nextAttemptAt = !block2 && options.backoff ? Date.now() + computeBackoffDelay(lease.retry, options.backoff) : void 0;
1786
+ const next_attempt_at = !block2 && options.backoff ? Date.now() + compute_backoff_delay(lease.retry, options.backoff) : void 0;
1770
1787
  return {
1771
1788
  lease,
1772
1789
  handled,
1773
1790
  acked_at: at,
1774
1791
  error: error.message,
1775
1792
  block: block2,
1776
- nextAttemptAt,
1793
+ next_attempt_at,
1777
1794
  failed_at
1778
1795
  };
1779
1796
  }
1780
- function buildHandle(deps) {
1781
- const { logger, boundDo, boundLoad, boundQuery, boundQueryArray } = deps;
1797
+ function build_handle(deps) {
1798
+ const {
1799
+ logger,
1800
+ bound_do,
1801
+ bound_load,
1802
+ bound_query,
1803
+ bound_query_array,
1804
+ bound_forget
1805
+ } = deps;
1782
1806
  return async (lease, payloads) => {
1783
1807
  if (payloads.length === 0) return { lease, handled: 0, acked_at: lease.at };
1784
1808
  const stream = lease.stream;
@@ -1786,23 +1810,24 @@ function buildHandle(deps) {
1786
1810
  let handled = 0;
1787
1811
  if (lease.retry > 0)
1788
1812
  logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);
1789
- const scopedApp = {
1790
- do: boundDo,
1791
- load: boundLoad,
1792
- query: boundQuery,
1793
- query_array: boundQueryArray
1813
+ const scoped_app = {
1814
+ do: bound_do,
1815
+ load: bound_load,
1816
+ query: bound_query,
1817
+ query_array: bound_query_array,
1818
+ forget: bound_forget
1794
1819
  };
1795
1820
  for (const payload of payloads) {
1796
1821
  const { event, handler } = payload;
1797
- scopedApp.do = (action2, target, actionPayload, reactingTo, skipValidation) => boundDo(
1822
+ scoped_app.do = (action2, target, action_payload, reactingTo, skipValidation) => bound_do(
1798
1823
  action2,
1799
1824
  target,
1800
- actionPayload,
1825
+ action_payload,
1801
1826
  reactingTo ?? event,
1802
1827
  skipValidation
1803
1828
  );
1804
1829
  try {
1805
- await handler(event, stream, scopedApp);
1830
+ await handler(event, stream, scoped_app);
1806
1831
  at = event.id;
1807
1832
  handled++;
1808
1833
  } catch (error) {
@@ -1820,10 +1845,12 @@ function buildHandle(deps) {
1820
1845
  return finalize(lease, handled, at, void 0, payloads[0].options, logger);
1821
1846
  };
1822
1847
  }
1823
- function buildHandleBatch(logger) {
1848
+ function build_handle_batch(logger) {
1824
1849
  return async (lease, payloads, batchHandler) => {
1825
1850
  const stream = lease.stream;
1826
- const events = payloads.map((p) => p.event);
1851
+ const events = payloads.map(
1852
+ (p) => p.event
1853
+ );
1827
1854
  const options = payloads[0].options;
1828
1855
  if (lease.retry > 0)
1829
1856
  logger.warn(`Retrying batch ${stream}@${events[0].id} (${lease.retry}).`);
@@ -1850,23 +1877,23 @@ var SettleLoop = class {
1850
1877
  _deps;
1851
1878
  /** Debounce window applied when the caller doesn't override via `SettleOptions.debounceMs`. */
1852
1879
  _default_debounce_ms;
1853
- constructor(deps, defaultDebounceMs) {
1880
+ constructor(deps, default_debounce_ms) {
1854
1881
  this._deps = deps;
1855
- this._default_debounce_ms = defaultDebounceMs;
1882
+ this._default_debounce_ms = default_debounce_ms;
1856
1883
  }
1857
1884
  /**
1858
1885
  * Schedule a settle pass. Multiple calls inside the debounce window
1859
1886
  * coalesce into one cycle. The cycle runs correlate→drain in a loop
1860
1887
  * until no progress is made (no new subscriptions, no acks, no blocks)
1861
1888
  * or `maxPasses` is reached, then emits the `"settled"` lifecycle event
1862
- * via {@link SettleDeps.onSettled}.
1889
+ * via {@link SettleDeps.on_settled}.
1863
1890
  */
1864
1891
  schedule(options = {}) {
1865
1892
  const {
1866
1893
  debounceMs = this._default_debounce_ms,
1867
- correlate: correlateQuery = { after: -1, limit: 100 },
1894
+ correlate: correlate_query = { after: -1, limit: 100 },
1868
1895
  maxPasses = Infinity,
1869
- ...drainOptions
1896
+ ...drain_options
1870
1897
  } = options;
1871
1898
  if (this._timer) clearTimeout(this._timer);
1872
1899
  this._timer = setTimeout(() => {
@@ -1875,17 +1902,17 @@ var SettleLoop = class {
1875
1902
  this._running = true;
1876
1903
  (async () => {
1877
1904
  await this._deps.init();
1878
- let lastDrain;
1905
+ let last_drain;
1879
1906
  for (let i = 0; i < maxPasses; i++) {
1880
1907
  const { subscribed } = await this._deps.correlate({
1881
- ...correlateQuery,
1908
+ ...correlate_query,
1882
1909
  after: this._deps.checkpoint()
1883
1910
  });
1884
- lastDrain = await this._deps.drain(drainOptions);
1885
- const made_progress = subscribed > 0 || lastDrain.acked.length > 0 || lastDrain.blocked.length > 0;
1911
+ last_drain = await this._deps.drain(drain_options);
1912
+ const made_progress = subscribed > 0 || last_drain.acked.length > 0 || last_drain.blocked.length > 0;
1886
1913
  if (!made_progress) break;
1887
1914
  }
1888
- if (lastDrain) this._deps.onSettled(lastDrain);
1915
+ if (last_drain) this._deps.on_settled(last_drain);
1889
1916
  })().catch((err) => this._deps.logger.error(err)).finally(() => {
1890
1917
  this._running = false;
1891
1918
  });
@@ -1972,7 +1999,7 @@ var Act = class {
1972
1999
  _event_to_state;
1973
2000
  /**
1974
2001
  * Event-name → lane fan-in for selective arming (ACT-1103). Built by
1975
- * `classifyRegistry` once per build. `"all"` means at least one of
2002
+ * `classify_registry` once per build. `"all"` means at least one of
1976
2003
  * the event's reactions is a dynamic resolver (lane opaque until
1977
2004
  * runtime); a `Set<string>` lists the static lanes only that event's
1978
2005
  * reactions target.
@@ -1995,9 +2022,9 @@ var Act = class {
1995
2022
  _scoped;
1996
2023
  /**
1997
2024
  * Correlation-id generator for originating actions. Bound at
1998
- * construction from `options.correlator ?? defaultCorrelator`. The
2025
+ * construction from `options.correlator ?? default_correlator`. The
1999
2026
  * `do()` path passes this into the `_es.action` closure; close-cycle
2000
- * uses it via {@link closeCorrelation}.
2027
+ * uses it via {@link close_correlation}.
2001
2028
  */
2002
2029
  _correlator;
2003
2030
  /** Pre-bound IAct methods reused across drain cycles. Only `do` varies per
@@ -2006,7 +2033,8 @@ var Act = class {
2006
2033
  _bound_load = this.load.bind(this);
2007
2034
  _bound_query = this.query.bind(this);
2008
2035
  _bound_query_array = this.query_array.bind(this);
2009
- /** Reaction dispatchers built once and handed to runDrainCycle each cycle. */
2036
+ _bound_forget = this.forget.bind(this);
2037
+ /** Reaction dispatchers built once and handed to run_drain_cycle each cycle. */
2010
2038
  _handle;
2011
2039
  _handle_batch;
2012
2040
  /** Declared drain lanes (ACT-1103). */
@@ -2023,16 +2051,16 @@ var Act = class {
2023
2051
  *
2024
2052
  * @param registry Schemas for every event and action across registered states
2025
2053
  * @param states Merged map of state name → state definition
2026
- * @param batchHandlers Static-target projection batch handlers (target → handler)
2054
+ * @param batch_handlers Static-target projection batch handlers (target → handler)
2027
2055
  * @param options Tuning knobs — see {@link ActOptions}
2028
2056
  * @param lanes Declared drain lanes (ACT-1103). The builder collects
2029
2057
  * these from `.withLane(...)` calls. Slice 1 records them on the
2030
2058
  * instance; later slices fan out one `DrainController` per lane.
2031
2059
  */
2032
- constructor(registry, states = /* @__PURE__ */ new Map(), batchHandlers = /* @__PURE__ */ new Map(), options = {}, lanes = []) {
2060
+ constructor(registry, states = /* @__PURE__ */ new Map(), batch_handlers = /* @__PURE__ */ new Map(), options = {}, lanes = []) {
2033
2061
  this.registry = registry;
2034
2062
  this._states = states;
2035
- this._batch_handlers = batchHandlers;
2063
+ this._batch_handlers = batch_handlers;
2036
2064
  this._lanes = lanes;
2037
2065
  if (options.onlyLanes && options.onlyLanes.length > 0) {
2038
2066
  const declared = /* @__PURE__ */ new Set([
@@ -2046,49 +2074,50 @@ var Act = class {
2046
2074
  );
2047
2075
  }
2048
2076
  this._scoped = options.scoped ? (fn) => scoped.run(options.scoped, fn) : (fn) => fn();
2049
- this._correlator = options.correlator ?? defaultCorrelator;
2050
- this._es = buildEs(this._logger, this._correlator);
2051
- this._cd = buildDrain(this._logger);
2052
- this._handle = buildHandle({
2077
+ this._correlator = options.correlator ?? default_correlator;
2078
+ this._es = build_es(this._logger, this._correlator);
2079
+ this._cd = build_drain(this._logger);
2080
+ this._handle = build_handle({
2053
2081
  logger: this._logger,
2054
- boundDo: this._bound_do,
2055
- boundLoad: this._bound_load,
2056
- boundQuery: this._bound_query,
2057
- boundQueryArray: this._bound_query_array
2082
+ bound_do: this._bound_do,
2083
+ bound_load: this._bound_load,
2084
+ bound_query: this._bound_query,
2085
+ bound_query_array: this._bound_query_array,
2086
+ bound_forget: this._bound_forget
2058
2087
  });
2059
- this._handle_batch = buildHandleBatch(this._logger);
2088
+ this._handle_batch = build_handle_batch(this._logger);
2060
2089
  const {
2061
- staticTargets,
2062
- hasDynamicResolvers,
2063
- reactiveEvents,
2064
- eventToState,
2065
- eventToLanes
2066
- } = classifyRegistry(this.registry, this._states);
2067
- this._reactive_events = reactiveEvents;
2090
+ static_targets,
2091
+ has_dynamic_resolvers,
2092
+ reactive_events,
2093
+ event_to_state,
2094
+ event_to_lanes
2095
+ } = classify_registry(this.registry, this._states);
2096
+ this._reactive_events = reactive_events;
2068
2097
  this._listen = options.listen !== false;
2069
2098
  this._drain = options.drain !== false;
2070
- this._event_to_state = eventToState;
2071
- this._event_to_lanes = eventToLanes;
2072
- const allLanes = ["default", ...lanes.map((l) => l.name)];
2073
- const onlySet = options.onlyLanes && options.onlyLanes.length > 0 ? new Set(options.onlyLanes) : void 0;
2074
- const activeLanes = onlySet ? allLanes.filter((n) => onlySet.has(n)) : allLanes;
2075
- const singleDefaultLane = activeLanes.length === 1 && activeLanes[0] === "default";
2099
+ this._event_to_state = event_to_state;
2100
+ this._event_to_lanes = event_to_lanes;
2101
+ const all_lanes = ["default", ...lanes.map((l) => l.name)];
2102
+ const only_set = options.onlyLanes && options.onlyLanes.length > 0 ? new Set(options.onlyLanes) : void 0;
2103
+ const active_lanes = only_set ? all_lanes.filter((n) => only_set.has(n)) : all_lanes;
2104
+ const single_default_lane = active_lanes.length === 1 && active_lanes[0] === "default";
2076
2105
  this._drain_controllers = /* @__PURE__ */ new Map();
2077
- for (const name of activeLanes) {
2106
+ for (const name of active_lanes) {
2078
2107
  const cfg = lanes.find((l) => l.name === name);
2079
2108
  const controller = new DrainController({
2080
2109
  logger: this._logger,
2081
2110
  ops: this._cd,
2082
2111
  registry: this.registry,
2083
- batchHandlers: this._batch_handlers,
2112
+ batch_handlers: this._batch_handlers,
2084
2113
  handle: this._handle,
2085
- handleBatch: this._handle_batch,
2086
- onAcked: (acked) => this.emit("acked", acked),
2087
- onBlocked: (blocked) => this.emit("blocked", blocked),
2114
+ handle_batch: this._handle_batch,
2115
+ on_acked: (acked) => this.emit("acked", acked),
2116
+ on_blocked: (blocked) => this.emit("blocked", blocked),
2088
2117
  // Pass lane only when a true per-lane controller is active.
2089
2118
  // The all-lanes (single default) case keeps lane=undefined so
2090
2119
  // adapter SQL collapses to the pre-1103 shape.
2091
- lane: singleDefaultLane ? void 0 : name,
2120
+ lane: single_default_lane ? void 0 : name,
2092
2121
  defaults: cfg && {
2093
2122
  streamLimit: cfg.streamLimit,
2094
2123
  leaseMillis: cfg.leaseMillis
@@ -2101,22 +2130,22 @@ var Act = class {
2101
2130
  this._audit_deps = {
2102
2131
  store,
2103
2132
  logger: this._logger,
2104
- event_to_state: eventToState,
2133
+ event_to_state,
2105
2134
  states: this._states,
2106
- known_events: new Set(eventToState.keys()),
2135
+ known_events: new Set(event_to_state.keys()),
2107
2136
  declared_lanes: new Set(this._drain_controllers.keys()),
2108
- routed_events: new Set(eventToLanes.keys())
2137
+ routed_events: new Set(event_to_lanes.keys())
2109
2138
  };
2110
2139
  this._correlate = new CorrelateCycle(
2111
2140
  this.registry,
2112
- staticTargets,
2113
- hasDynamicResolvers,
2141
+ static_targets,
2142
+ has_dynamic_resolvers,
2114
2143
  this._cd,
2115
2144
  options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,
2116
2145
  // Cold start: assume drain is needed (historical events may need processing).
2117
2146
  // #803: writer-only instances skip the cold-start arm.
2118
2147
  () => {
2119
- if (this._drain && this._reactive_events.size > 0) this._armAll();
2148
+ if (this._drain && this._reactive_events.size > 0) this._arm_all();
2120
2149
  }
2121
2150
  );
2122
2151
  this._settle = new SettleLoop(
@@ -2126,11 +2155,11 @@ var Act = class {
2126
2155
  checkpoint: () => this._correlate.checkpoint,
2127
2156
  correlate: (q) => this.correlate(q),
2128
2157
  drain: (o) => this.drain(o),
2129
- onSettled: (drain) => this.emit("settled", drain)
2158
+ on_settled: (drain) => this.emit("settled", drain)
2130
2159
  },
2131
2160
  options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS
2132
2161
  );
2133
- this._notify_disposer = this._wireNotify(options.scoped?.store ?? store());
2162
+ this._notify_disposer = this._wire_notify(options.scoped?.store ?? store());
2134
2163
  dispose(() => this.shutdown());
2135
2164
  }
2136
2165
  /** True after the first `shutdown()` call. Guards idempotency. */
@@ -2164,7 +2193,7 @@ var Act = class {
2164
2193
  * subscription was made). Errors during subscription are logged but
2165
2194
  * never thrown — `notify` is a hint, not a contract.
2166
2195
  */
2167
- async _wireNotify(s) {
2196
+ async _wire_notify(s) {
2168
2197
  if (this._reactive_events.size === 0) return void 0;
2169
2198
  if (!s.notify) return void 0;
2170
2199
  if (!this._listen) return void 0;
@@ -2173,7 +2202,7 @@ var Act = class {
2173
2202
  try {
2174
2203
  this.emit("notified", notification);
2175
2204
  if (this._drain) {
2176
- const armed = this._armForEventNames(
2205
+ const armed = this._arm_for_event_names(
2177
2206
  notification.events.map((e) => e.name)
2178
2207
  );
2179
2208
  if (armed) this._settle.schedule({ debounceMs: 0 });
@@ -2279,14 +2308,14 @@ var Act = class {
2279
2308
  skipValidation
2280
2309
  );
2281
2310
  if (this._reactive_events.size > 0)
2282
- this._armForEventNames(
2311
+ this._arm_for_event_names(
2283
2312
  snapshots.map((s) => s.event.name)
2284
2313
  );
2285
2314
  this.emit("committed", snapshots);
2286
2315
  return snapshots;
2287
2316
  });
2288
2317
  }
2289
- async load(stateOrName, stream, callback, asOf) {
2318
+ async load(stateOrName, stream, callback, asOf, actor) {
2290
2319
  return this._scoped(async () => {
2291
2320
  let merged;
2292
2321
  if (typeof stateOrName === "string") {
@@ -2296,7 +2325,7 @@ var Act = class {
2296
2325
  } else {
2297
2326
  merged = this._states.get(stateOrName.name) || stateOrName;
2298
2327
  }
2299
- return await this._es.load(merged, stream, callback, asOf);
2328
+ return await this._es.load(merged, stream, callback, asOf, actor);
2300
2329
  });
2301
2330
  }
2302
2331
  /**
@@ -2390,6 +2419,34 @@ var Act = class {
2390
2419
  return events;
2391
2420
  });
2392
2421
  }
2422
+ /**
2423
+ * Wipe the sensitive-data payload for every event on the stream — see
2424
+ * {@link IAct.forget}. Application-level half of #566.
2425
+ *
2426
+ * Throws on adapters without `Store.forget_pii`, invalidates the cache
2427
+ * entry for the stream, emits the `forgotten` lifecycle event with the
2428
+ * row count. Idempotent: a second call returns `{eventCount: 0}` and
2429
+ * does NOT re-emit.
2430
+ *
2431
+ * @param stream - Target stream.
2432
+ * @returns `{eventCount}` — number of events whose PII column was wiped.
2433
+ */
2434
+ async forget(stream) {
2435
+ return this._scoped(async () => {
2436
+ const s = store();
2437
+ if (!s.forget_pii) {
2438
+ throw new Error(
2439
+ `Store does not implement forget_pii \u2014 adapter cannot comply with sensitive-data erasure. Use an adapter that declares pii_isolation: true (e.g. @rotorsoft/act on the in-memory store).`
2440
+ );
2441
+ }
2442
+ const eventCount = await s.forget_pii(stream);
2443
+ await cache().invalidate(stream);
2444
+ if (eventCount > 0) {
2445
+ this.emit("forgotten", { stream, at: /* @__PURE__ */ new Date(), eventCount });
2446
+ }
2447
+ return { eventCount };
2448
+ });
2449
+ }
2393
2450
  /**
2394
2451
  * Processes pending reactions by draining uncommitted events from the event store.
2395
2452
  *
@@ -2430,28 +2487,28 @@ var Act = class {
2430
2487
  async drain(options = {}) {
2431
2488
  if (!this._drain)
2432
2489
  return { fetched: [], leased: [], acked: [], blocked: [] };
2433
- return this._scoped(() => this._drainAll(options));
2490
+ return this._scoped(() => this._drain_all(options));
2434
2491
  }
2435
2492
  /** Arm every active lane controller (ACT-1103). */
2436
- _armAll() {
2493
+ _arm_all() {
2437
2494
  for (const c of this._drain_controllers.values()) c.arm();
2438
2495
  }
2439
2496
  /**
2440
2497
  * Arm only the lane controllers whose reactions match the supplied
2441
2498
  * event names (ACT-1103 selective arming). Events with any dynamic
2442
- * resolver fall back to `_armAll()` via the `"all"` sentinel — the
2499
+ * resolver fall back to `_arm_all()` via the `"all"` sentinel — the
2443
2500
  * resolver's lane isn't known until correlate runs the function.
2444
2501
  * Events with no reactions are skipped; `_event_to_lanes` doesn't
2445
2502
  * carry them. Returns true when any controller was armed (used by
2446
2503
  * the notify handler to decide whether to schedule a settle).
2447
2504
  */
2448
- _armForEventNames(names) {
2505
+ _arm_for_event_names(names) {
2449
2506
  const to_arm = /* @__PURE__ */ new Set();
2450
2507
  for (const name of names) {
2451
2508
  const set = this._event_to_lanes.get(name);
2452
2509
  if (set === void 0) continue;
2453
2510
  if (set === ALL_LANES) {
2454
- this._armAll();
2511
+ this._arm_all();
2455
2512
  return true;
2456
2513
  }
2457
2514
  for (const lane of set) to_arm.add(lane);
@@ -2468,7 +2525,7 @@ var Act = class {
2468
2525
  * `SKIP LOCKED` keeps cross-controller races safe. Lifecycle events
2469
2526
  * (`acked`, `blocked`) may interleave by lane — listeners filter via
2470
2527
  * `lease.lane`. */
2471
- async _drainAll(options) {
2528
+ async _drain_all(options) {
2472
2529
  const results = await Promise.all(
2473
2530
  [...this._drain_controllers.values()].map((c) => c.drain(options))
2474
2531
  );
@@ -2588,7 +2645,7 @@ var Act = class {
2588
2645
  * @see {@link stop_correlations} to stop the worker
2589
2646
  */
2590
2647
  start_correlations(query = {}, frequency = 1e4, callback) {
2591
- return this._correlate.startPolling(query, frequency, callback);
2648
+ return this._correlate.start_polling(query, frequency, callback);
2592
2649
  }
2593
2650
  /**
2594
2651
  * Stops the automatic correlation worker.
@@ -2608,7 +2665,7 @@ var Act = class {
2608
2665
  * @see {@link start_correlations}
2609
2666
  */
2610
2667
  stop_correlations() {
2611
- this._correlate.stopPolling();
2668
+ this._correlate.stop_polling();
2612
2669
  }
2613
2670
  /**
2614
2671
  * Cancels any pending or active settle cycle.
@@ -2654,7 +2711,7 @@ var Act = class {
2654
2711
  async reset(input) {
2655
2712
  return this._scoped(async () => {
2656
2713
  const count = await store().reset(input);
2657
- if (count > 0 && this._reactive_events.size > 0) this._armAll();
2714
+ if (count > 0 && this._reactive_events.size > 0) this._arm_all();
2658
2715
  return count;
2659
2716
  });
2660
2717
  }
@@ -2688,7 +2745,7 @@ var Act = class {
2688
2745
  async unblock(input) {
2689
2746
  return this._scoped(async () => {
2690
2747
  const count = await store().unblock(input);
2691
- if (count > 0 && this._reactive_events.size > 0) this._armAll();
2748
+ if (count > 0 && this._reactive_events.size > 0) this._arm_all();
2692
2749
  return count;
2693
2750
  });
2694
2751
  }
@@ -2914,14 +2971,14 @@ var Act = class {
2914
2971
  if (!targets.length) return { truncated: /* @__PURE__ */ new Map(), skipped: [] };
2915
2972
  return this._scoped(async () => {
2916
2973
  await this.correlate({ limit: 1e3 });
2917
- const closeActor = { id: "$close", name: "close" };
2918
- const result = await runCloseCycle(targets, {
2919
- reactiveEventsSize: this._reactive_events.size,
2920
- eventToState: this._event_to_state,
2974
+ const close_actor = { id: "$close", name: "close" };
2975
+ const result = await run_close_cycle(targets, {
2976
+ reactive_events_size: this._reactive_events.size,
2977
+ event_to_state: this._event_to_state,
2921
2978
  load: this._es.load,
2922
2979
  tombstone: this._es.tombstone,
2923
2980
  logger: this._logger,
2924
- correlation: closeCorrelation(this._correlator, closeActor)
2981
+ correlation: close_correlation(this._correlator, close_actor)
2925
2982
  });
2926
2983
  this.emit("closed", result);
2927
2984
  return result;
@@ -2964,17 +3021,17 @@ var Act = class {
2964
3021
  };
2965
3022
 
2966
3023
  // src/builders/act-builder.ts
2967
- function registerBatchHandler(proj, batchHandlers) {
3024
+ function register_batch_handler(proj, batch_handlers) {
2968
3025
  if (!proj.batchHandler || !proj.target) return;
2969
- const existing = batchHandlers.get(proj.target);
3026
+ const existing = batch_handlers.get(proj.target);
2970
3027
  if (existing && existing !== proj.batchHandler) {
2971
3028
  throw new Error(`Duplicate batch handler for target "${proj.target}"`);
2972
3029
  }
2973
- batchHandlers.set(proj.target, proj.batchHandler);
3030
+ batch_handlers.set(proj.target, proj.batchHandler);
2974
3031
  }
2975
- function validateLaneReferences(registry, lanes) {
3032
+ function validate_lane_references(registry, lanes) {
2976
3033
  const declared = /* @__PURE__ */ new Set([DEFAULT_LANE, ...lanes.map((l) => l.name)]);
2977
- for (const [eventName, def] of Object.entries(registry.events)) {
3034
+ for (const [event_name, def] of Object.entries(registry.events)) {
2978
3035
  const entry = def;
2979
3036
  for (const [handlerName, reaction] of entry.reactions) {
2980
3037
  const resolver = reaction.resolver;
@@ -2982,7 +3039,7 @@ function validateLaneReferences(registry, lanes) {
2982
3039
  const lane = resolver.lane;
2983
3040
  if (lane && !declared.has(lane)) {
2984
3041
  throw new Error(
2985
- `Reaction "${handlerName}" on "${eventName}" targets undeclared lane "${lane}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. Add \`.withLane({ name: "${lane}", ... })\` to act() or correct the .to() declaration.`
3042
+ `Reaction "${handlerName}" on "${event_name}" targets undeclared lane "${lane}". Declared lanes: ${[...declared].map((l) => `"${l}"`).join(", ")}. Add \`.withLane({ name: "${lane}", ... })\` to act() or correct the .to() declaration.`
2986
3043
  );
2987
3044
  }
2988
3045
  }
@@ -2990,76 +3047,80 @@ function validateLaneReferences(registry, lanes) {
2990
3047
  }
2991
3048
  function act() {
2992
3049
  const states = /* @__PURE__ */ new Map();
3050
+ const _sf = /* @__PURE__ */ new Map();
3051
+ const _dp = /* @__PURE__ */ new Map();
2993
3052
  const registry = {
2994
3053
  actions: {},
2995
- events: {}
3054
+ events: {},
3055
+ sensitive_fields: (event_name) => _sf.get(event_name) ?? [],
3056
+ disclosure_predicate: (state_name) => _dp.get(state_name) ?? null
2996
3057
  };
2997
- const pendingProjections = [];
2998
- const batchHandlers = /* @__PURE__ */ new Map();
3058
+ const pending_projections = [];
3059
+ const batch_handlers = /* @__PURE__ */ new Map();
2999
3060
  const lanes = [];
3000
3061
  let _built = false;
3001
- const finalizeDeprecations = () => {
3002
- const deprecationSummary = [];
3062
+ const finalize_deprecations = () => {
3063
+ const deprecation_summary = [];
3003
3064
  for (const state2 of states.values()) {
3004
- const eventNames = Object.keys(state2.events);
3005
- const deprecated = deprecatedEventNames(eventNames);
3065
+ const event_names = Object.keys(state2.events);
3066
+ const deprecated = deprecated_event_names(event_names);
3006
3067
  if (deprecated.size === 0) continue;
3007
3068
  state2._deprecated = deprecated;
3008
3069
  for (const name of deprecated) {
3009
- const current = currentVersionOf(name, eventNames);
3010
- deprecationSummary.push({
3011
- stateName: state2.name,
3070
+ const current = current_version_of(name, event_names);
3071
+ deprecation_summary.push({
3072
+ state_name: state2.name,
3012
3073
  deprecated: name,
3013
3074
  current
3014
3075
  });
3015
3076
  }
3016
- for (const [actionName, handler] of Object.entries(state2.on)) {
3017
- const staticTarget = handler?._staticEmit;
3018
- if (staticTarget && deprecated.has(staticTarget)) {
3019
- const current = currentVersionOf(staticTarget, eventNames);
3077
+ for (const [action_name, handler] of Object.entries(state2.on)) {
3078
+ const static_target = handler?._static_emit;
3079
+ if (static_target && deprecated.has(static_target)) {
3080
+ const current = current_version_of(static_target, event_names);
3020
3081
  throw new Error(
3021
- `Action "${actionName}" in state "${state2.name}" emits deprecated event "${staticTarget}". A newer version exists: "${current}". Update the .emit() call to target the current version. The reducer (.patch) for "${staticTarget}" stays as-is \u2014 historical events still need it.`
3082
+ `Action "${action_name}" in state "${state2.name}" emits deprecated event "${static_target}". A newer version exists: "${current}". Update the .emit() call to target the current version. The reducer (.patch) for "${static_target}" stays as-is \u2014 historical events still need it.`
3022
3083
  );
3023
3084
  }
3024
3085
  }
3025
3086
  }
3026
- if (deprecationSummary.length > 0) {
3027
- const list = deprecationSummary.map(
3028
- (d) => `"${d.deprecated}" (current: "${d.current}", state: "${d.stateName}")`
3087
+ if (deprecation_summary.length > 0) {
3088
+ const list = deprecation_summary.map(
3089
+ (d) => `"${d.deprecated}" (current: "${d.current}", state: "${d.state_name}")`
3029
3090
  ).join(", ");
3030
3091
  log().info(
3031
- `Act registered ${deprecationSummary.length} deprecated event(s): ${list}. These are legacy versions kept for the read path. Consider truncating closed streams via app.close() when feasible to reduce historical event load. See docs/docs/architecture/event-schema-evolution.md.`
3092
+ `Act registered ${deprecation_summary.length} deprecated event(s): ${list}. These are legacy versions kept for the read path. Consider truncating closed streams via app.close() when feasible to reduce historical event load. See docs/docs/architecture/event-schema-evolution.md.`
3032
3093
  );
3033
3094
  }
3034
3095
  };
3035
3096
  const builder = {
3036
3097
  withState: (state2) => {
3037
- registerState(state2, states, registry.actions, registry.events);
3098
+ register_state(state2, states, registry.actions, registry.events);
3038
3099
  return builder;
3039
3100
  },
3040
3101
  withSlice: (input) => {
3041
3102
  for (const s of input.states.values()) {
3042
- registerState(s, states, registry.actions, registry.events);
3103
+ register_state(s, states, registry.actions, registry.events);
3043
3104
  }
3044
- mergeEventRegister(registry.events, input.events);
3045
- pendingProjections.push(...input.projections);
3046
- for (const sliceLane of input.lanes) {
3047
- const existing = lanes.find((l) => l.name === sliceLane.name);
3105
+ merge_event_register(registry.events, input.events);
3106
+ pending_projections.push(...input.projections);
3107
+ for (const slice_lane of input.lanes) {
3108
+ const existing = lanes.find((l) => l.name === slice_lane.name);
3048
3109
  if (!existing) {
3049
- lanes.push(sliceLane);
3110
+ lanes.push(slice_lane);
3050
3111
  continue;
3051
3112
  }
3052
- if (existing.leaseMillis !== sliceLane.leaseMillis || existing.streamLimit !== sliceLane.streamLimit || existing.cycleMs !== sliceLane.cycleMs) {
3113
+ if (existing.leaseMillis !== slice_lane.leaseMillis || existing.streamLimit !== slice_lane.streamLimit || existing.cycleMs !== slice_lane.cycleMs) {
3053
3114
  throw new Error(
3054
- `Lane "${sliceLane.name}" was already declared with a different config`
3115
+ `Lane "${slice_lane.name}" was already declared with a different config`
3055
3116
  );
3056
3117
  }
3057
3118
  }
3058
3119
  return builder;
3059
3120
  },
3060
3121
  withProjection: (proj) => {
3061
- mergeProjection(proj, registry.events);
3062
- registerBatchHandler(proj, batchHandlers);
3122
+ merge_projection(proj, registry.events);
3123
+ register_batch_handler(proj, batch_handlers);
3063
3124
  return builder;
3064
3125
  },
3065
3126
  withActor: () => builder,
@@ -3097,18 +3158,70 @@ function act() {
3097
3158
  }),
3098
3159
  build: (options) => {
3099
3160
  if (!_built) {
3100
- for (const proj of pendingProjections) {
3101
- mergeProjection(proj, registry.events);
3102
- registerBatchHandler(proj, batchHandlers);
3161
+ for (const proj of pending_projections) {
3162
+ merge_projection(proj, registry.events);
3163
+ register_batch_handler(proj, batch_handlers);
3164
+ }
3165
+ finalize_deprecations();
3166
+ validate_lane_references(registry, lanes);
3167
+ for (const [event_name, reg] of Object.entries(
3168
+ registry.events
3169
+ )) {
3170
+ const fields = pii_fields(reg.schema);
3171
+ if (fields.length === 0) continue;
3172
+ _sf.set(event_name, fields);
3173
+ for (const [name, reaction] of reg.reactions) {
3174
+ const inner = reaction.handler;
3175
+ const wrapped = (event, stream, app) => inner(pii_strip(event, fields), stream, app);
3176
+ Object.defineProperty(wrapped, "name", { value: inner.name });
3177
+ reaction.handler = wrapped;
3178
+ reg.reactions.set(name, reaction);
3179
+ }
3180
+ }
3181
+ for (const state2 of states.values()) {
3182
+ if (state2.disclose) _dp.set(state2.name, state2.disclose);
3183
+ const fields_by_event = /* @__PURE__ */ new Map();
3184
+ for (const event_name of Object.keys(state2.events)) {
3185
+ const fields = _sf.get(event_name);
3186
+ if (fields) fields_by_event.set(event_name, fields);
3187
+ }
3188
+ if (fields_by_event.size === 0) continue;
3189
+ if (state2.snap) {
3190
+ const offending = [...fields_by_event.keys()];
3191
+ throw new Error(
3192
+ `State "${state2.name}" cannot snapshot \u2014 events {${offending.join(", ")}} carry sensitive fields. Snapshots write derived state into __snapshot__.data, which forget_pii cannot reach. Remove .snap() or remove sensitive(...) markers.`
3193
+ );
3194
+ }
3195
+ const disclose = state2.disclose ?? null;
3196
+ state2.view = (event, actor) => {
3197
+ const fields = fields_by_event.get(event.name);
3198
+ return fields ? pii_gate(event, fields, disclose, actor) : event;
3199
+ };
3200
+ state2.message = (validated) => {
3201
+ const fields = fields_by_event.get(validated.name);
3202
+ return fields ? pii_split(validated, fields) : validated;
3203
+ };
3204
+ for (const [event_name, fields] of fields_by_event) {
3205
+ const original = state2.patch[event_name];
3206
+ state2.patch[event_name] = (event, s) => original(pii_merge(event, fields), s);
3207
+ }
3208
+ }
3209
+ for (const [target, original] of batch_handlers) {
3210
+ const wrapped = async (events, stream) => {
3211
+ const stripped = events.map((e) => {
3212
+ const f = _sf.get(e.name);
3213
+ return f ? pii_strip(e, f) : e;
3214
+ });
3215
+ return original(stripped, stream);
3216
+ };
3217
+ batch_handlers.set(target, wrapped);
3103
3218
  }
3104
- finalizeDeprecations();
3105
- validateLaneReferences(registry, lanes);
3106
3219
  _built = true;
3107
3220
  }
3108
3221
  return new Act(
3109
3222
  registry,
3110
3223
  states,
3111
- batchHandlers,
3224
+ batch_handlers,
3112
3225
  options,
3113
3226
  lanes
3114
3227
  );
@@ -3121,7 +3234,7 @@ function act() {
3121
3234
  // src/builders/projection-builder.ts
3122
3235
  function _projection(target) {
3123
3236
  const events = {};
3124
- const defaultResolver = typeof target === "string" ? { target } : void 0;
3237
+ const default_resolver = typeof target === "string" ? { target } : void 0;
3125
3238
  const base = {
3126
3239
  on: (entry) => {
3127
3240
  const keys = Object.keys(entry);
@@ -3138,7 +3251,7 @@ function _projection(target) {
3138
3251
  do: (handler) => {
3139
3252
  const reaction = {
3140
3253
  handler,
3141
- resolver: defaultResolver ?? _this_,
3254
+ resolver: default_resolver ?? _this_,
3142
3255
  options: {
3143
3256
  blockOnError: true,
3144
3257
  maxRetries: 3
@@ -3194,7 +3307,7 @@ function slice() {
3194
3307
  const lanes = [];
3195
3308
  const builder = {
3196
3309
  withState: (state2) => {
3197
- registerState(state2, states, actions, events);
3310
+ register_state(state2, states, actions, events);
3198
3311
  return builder;
3199
3312
  },
3200
3313
  withProjection: (proj) => {
@@ -3250,12 +3363,12 @@ function state(entry) {
3250
3363
  const keys = Object.keys(entry);
3251
3364
  if (keys.length !== 1) throw new Error("state() requires exactly one key");
3252
3365
  const name = keys[0];
3253
- const stateSchema = entry[name];
3366
+ const state_schema = entry[name];
3254
3367
  return {
3255
3368
  init(init) {
3256
3369
  return {
3257
3370
  emits(events) {
3258
- const defaultPatch = Object.fromEntries(
3371
+ const default_patch = Object.fromEntries(
3259
3372
  Object.keys(events).map((k) => {
3260
3373
  const fn = Object.assign(({ data }) => data, {
3261
3374
  _passthrough: true
@@ -3266,11 +3379,16 @@ function state(entry) {
3266
3379
  const internal = {
3267
3380
  events,
3268
3381
  actions: {},
3269
- state: stateSchema,
3382
+ state: state_schema,
3270
3383
  name,
3271
3384
  init,
3272
- patch: defaultPatch,
3273
- on: {}
3385
+ patch: default_patch,
3386
+ on: {},
3387
+ // Step delegates initialized as identity. `act().build()`
3388
+ // overrides on states with `sensitive(...)` events to bake in
3389
+ // the gate / split.
3390
+ view: (event) => event,
3391
+ message: (validated) => validated
3274
3392
  };
3275
3393
  const builder = action_builder(internal);
3276
3394
  return Object.assign(builder, {
@@ -3306,11 +3424,14 @@ function action_builder(state2) {
3306
3424
  }
3307
3425
  function emit(handler) {
3308
3426
  if (typeof handler === "string") {
3309
- const eventName = handler;
3310
- const emitFn = Object.assign((payload) => [eventName, payload], {
3311
- _staticEmit: eventName
3312
- });
3313
- internal.on[action2] = emitFn;
3427
+ const event_name = handler;
3428
+ const emit_fn = Object.assign(
3429
+ (payload) => [event_name, payload],
3430
+ {
3431
+ _static_emit: event_name
3432
+ }
3433
+ );
3434
+ internal.on[action2] = emit_fn;
3314
3435
  } else {
3315
3436
  internal.on[action2] = handler;
3316
3437
  }
@@ -3322,6 +3443,10 @@ function action_builder(state2) {
3322
3443
  internal.snap = snap2;
3323
3444
  return builder;
3324
3445
  },
3446
+ discloses(disclose) {
3447
+ internal.disclose = disclose;
3448
+ return builder;
3449
+ },
3325
3450
  build() {
3326
3451
  return internal;
3327
3452
  }
@@ -3359,7 +3484,7 @@ var CsvFile = class {
3359
3484
  let header = null;
3360
3485
  for await (const line of lines) {
3361
3486
  if (!line.trim()) continue;
3362
- const fields = parseCsvLine(line);
3487
+ const fields = parse_csv_line(line);
3363
3488
  if (!header) {
3364
3489
  header = fields;
3365
3490
  const expected = CSV_COLUMNS.join(",");
@@ -3396,21 +3521,21 @@ var CsvFile = class {
3396
3521
  flags: "w",
3397
3522
  encoding: "utf8"
3398
3523
  });
3399
- let nextId = 1;
3524
+ let next_id = 1;
3400
3525
  try {
3401
- await writeLine(writer, CSV_COLUMNS.join(","));
3526
+ await write_line(writer, CSV_COLUMNS.join(","));
3402
3527
  await driver(async (event) => {
3403
- const id = nextId++;
3528
+ const id = next_id++;
3404
3529
  const row = [
3405
3530
  String(id),
3406
- csvEscape(event.name),
3407
- csvEscape(JSON.stringify(event.data)),
3408
- csvEscape(event.stream),
3531
+ csv_escape(event.name),
3532
+ csv_escape(JSON.stringify(event.data)),
3533
+ csv_escape(event.stream),
3409
3534
  String(event.version),
3410
3535
  event.created.toISOString(),
3411
- csvEscape(JSON.stringify(event.meta))
3536
+ csv_escape(JSON.stringify(event.meta))
3412
3537
  ].join(",");
3413
- await writeLine(writer, row);
3538
+ await write_line(writer, row);
3414
3539
  return id;
3415
3540
  });
3416
3541
  } finally {
@@ -3443,7 +3568,7 @@ async function* linesFromBlob(blob) {
3443
3568
  await Promise.resolve();
3444
3569
  }
3445
3570
  }
3446
- function parseCsvLine(line) {
3571
+ function parse_csv_line(line) {
3447
3572
  const fields = [];
3448
3573
  let i = 0;
3449
3574
  while (i < line.length) {
@@ -3476,11 +3601,11 @@ function parseCsvLine(line) {
3476
3601
  }
3477
3602
  return fields;
3478
3603
  }
3479
- function csvEscape(value) {
3604
+ function csv_escape(value) {
3480
3605
  if (/[",\n\r]/.test(value)) return `"${value.replace(/"/g, '""')}"`;
3481
3606
  return value;
3482
3607
  }
3483
- function writeLine(writer, line) {
3608
+ function write_line(writer, line) {
3484
3609
  return new Promise((resolve, reject) => {
3485
3610
  writer.write(`${line}
3486
3611
  `, (err) => {
@@ -3511,6 +3636,8 @@ export {
3511
3636
  NonRetryableError,
3512
3637
  PackageSchema,
3513
3638
  QuerySchema,
3639
+ REDACTED,
3640
+ SHREDDED,
3514
3641
  SNAP_EVENT,
3515
3642
  StreamClosedError,
3516
3643
  TOMBSTONE_EVENT,
@@ -3527,6 +3654,7 @@ export {
3527
3654
  port,
3528
3655
  projection,
3529
3656
  scoped,
3657
+ sensitive,
3530
3658
  sleep,
3531
3659
  slice,
3532
3660
  state,