libpetri 2.7.1 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12,11 +12,17 @@ import {
12
12
  timeoutPlace,
13
13
  xor,
14
14
  xorPlaces
15
- } from "./chunk-ETNHEAS6.js";
15
+ } from "./chunk-M3KT7BFO.js";
16
16
  import {
17
17
  eventTransitionName,
18
18
  isFailureEvent
19
19
  } from "./chunk-SXK2Z45Z.js";
20
+ import {
21
+ keyForPlace,
22
+ matchCorrelates,
23
+ matchKey,
24
+ matchSpec
25
+ } from "./chunk-E3ZWB645.js";
20
26
  import {
21
27
  MAX_DURATION_MS,
22
28
  deadline,
@@ -131,6 +137,11 @@ function consumptionCount(spec, available) {
131
137
  }
132
138
  }
133
139
 
140
+ // src/core/name.ts
141
+ function nameId(value) {
142
+ return value;
143
+ }
144
+
134
145
  // src/core/transition-action.ts
135
146
  function passthrough() {
136
147
  return PASSTHROUGH;
@@ -204,6 +215,7 @@ function withTimeout(action, timeoutMs, timeoutPlace2, timeoutValue) {
204
215
 
205
216
  // src/core/transition-context.ts
206
217
  var EMPTY_ALIAS = /* @__PURE__ */ new Map();
218
+ var GLOBAL_FRESH_NAME_COUNTER = 0;
207
219
  var TransitionContext = class {
208
220
  rawInput;
209
221
  _rawOutput;
@@ -217,6 +229,7 @@ var TransitionContext = class {
217
229
  executionCtx;
218
230
  _logFn;
219
231
  placeAlias;
232
+ _freshNameSupplier;
220
233
  constructor(transitionName, rawInput, rawOutput, inputPlaces, readPlaces, outputPlaces, executionContext, logFn, placeAlias) {
221
234
  this._transitionName = transitionName;
222
235
  this.rawInput = rawInput;
@@ -358,6 +371,28 @@ var TransitionContext = class {
358
371
  );
359
372
  }
360
373
  }
374
+ // ==================== ν-name minting (NU-010) ====================
375
+ /**
376
+ * @internal Installs the ν-name minter. Wired by the executor at firing time
377
+ * so names minted by {@link freshName} are monotonic across the run and
378
+ * instance-prefixed (spec NU-010, NU-030).
379
+ */
380
+ setFreshNameSupplier(supplier) {
381
+ this._freshNameSupplier = supplier;
382
+ }
383
+ /**
384
+ * Mints a fresh ν-name (the ν-binder primitive — spec NU-010).
385
+ *
386
+ * An action calls this on the fork side to create a correlation id, then
387
+ * writes it into the sibling output payloads; a later join correlates those
388
+ * siblings via a {@link import('./match-spec.js').MatchSpec}. Uses the
389
+ * executor-installed minter when present; otherwise falls back to a
390
+ * process-global counter prefixed by the transition name.
391
+ */
392
+ freshName() {
393
+ if (this._freshNameSupplier) return this._freshNameSupplier();
394
+ return nameId(`${this._transitionName}#${GLOBAL_FRESH_NAME_COUNTER++}`);
395
+ }
361
396
  // ==================== Structure Info ====================
362
397
  /** Returns the transition name. */
363
398
  transitionName() {
@@ -472,6 +507,11 @@ var Transition = class {
472
507
  actionTimeout;
473
508
  action;
474
509
  priority;
510
+ /**
511
+ * ν-net join correlation: a subset of `inputSpecs` that must be correlated by
512
+ * name equality on firing (spec NU-020). `null` for ordinary transitions.
513
+ */
514
+ matchSpec;
475
515
  /**
476
516
  * Per-transition **declared → actual** place correspondence (per
477
517
  * **MOD-031**), keyed by the author-original declared place **name** →
@@ -488,7 +528,7 @@ var Transition = class {
488
528
  _readPlaces;
489
529
  _outputPlaces;
490
530
  /** @internal Use {@link Transition.builder} to create instances. */
491
- constructor(key, name, inputSpecs, outputSpec, inhibitors, reads, resets, timing, action, priority, placeAlias = EMPTY_PLACE_ALIAS) {
531
+ constructor(key, name, inputSpecs, outputSpec, inhibitors, reads, resets, timing, action, priority, placeAlias = EMPTY_PLACE_ALIAS, matchSpec2 = null) {
492
532
  if (key !== TRANSITION_KEY) throw new Error("Use Transition.builder() to create instances");
493
533
  this.name = name;
494
534
  this.inputSpecs = inputSpecs;
@@ -501,6 +541,7 @@ var Transition = class {
501
541
  this.action = action;
502
542
  this.priority = priority;
503
543
  this.placeAlias = placeAlias.size === 0 ? EMPTY_PLACE_ALIAS : placeAlias;
544
+ this.matchSpec = matchSpec2;
504
545
  const inputPlaces = /* @__PURE__ */ new Set();
505
546
  for (const spec of inputSpecs) {
506
547
  inputPlaces.add(spec.place);
@@ -553,6 +594,7 @@ var TransitionBuilder = class {
553
594
  _action = passthrough();
554
595
  _priority = 0;
555
596
  _placeAlias = EMPTY_PLACE_ALIAS;
597
+ _matchSpec = null;
556
598
  constructor(name) {
557
599
  this._name = name;
558
600
  }
@@ -617,6 +659,15 @@ var TransitionBuilder = class {
617
659
  this._priority = priority;
618
660
  return this;
619
661
  }
662
+ /**
663
+ * Sets the ν-net join correlation spec: the named input places must be
664
+ * correlated by name equality on firing (spec NU-020). Every place referenced
665
+ * by the spec must also be declared as an input.
666
+ */
667
+ match(spec) {
668
+ this._matchSpec = spec;
669
+ return this;
670
+ }
620
671
  /**
621
672
  * Sets the per-transition declared→actual place correspondence (per
622
673
  * **MOD-031**). Populated by the subnet rewriter during the compose-time
@@ -638,6 +689,16 @@ var TransitionBuilder = class {
638
689
  }
639
690
  }
640
691
  }
692
+ if (this._matchSpec !== null) {
693
+ const inputPlaceNames = new Set(this._inputSpecs.map((s) => s.place.name));
694
+ for (const k of this._matchSpec.keys) {
695
+ if (!inputPlaceNames.has(k.place.name)) {
696
+ throw new Error(
697
+ `Transition '${this._name}': MatchSpec correlates non-input place '${k.place.name}'`
698
+ );
699
+ }
700
+ }
701
+ }
641
702
  return new Transition(
642
703
  TRANSITION_KEY,
643
704
  this._name,
@@ -649,7 +710,8 @@ var TransitionBuilder = class {
649
710
  this._timing,
650
711
  this._action,
651
712
  this._priority,
652
- this._placeAlias
713
+ this._placeAlias,
714
+ this._matchSpec
653
715
  );
654
716
  }
655
717
  };
@@ -967,6 +1029,14 @@ function rebuildWithName(t, name, remap) {
967
1029
  for (let i = 0; i < t.resets.length; i++) {
968
1030
  builder.reset(rewriteReset(t.resets[i], remap).place);
969
1031
  }
1032
+ if (t.matchSpec !== null) {
1033
+ builder.match({
1034
+ keys: t.matchSpec.keys.map((k) => ({
1035
+ place: remap.get(k.place.name) ?? k.place,
1036
+ key: k.key
1037
+ }))
1038
+ });
1039
+ }
970
1040
  return builder.build();
971
1041
  }
972
1042
  function buildPlaceAlias(t, remap) {
@@ -2387,6 +2457,10 @@ var CompiledNet = class _CompiledNet {
2387
2457
  // Cardinality and guard flags
2388
2458
  _cardinalityChecks;
2389
2459
  _hasGuards;
2460
+ // ν-net join flag: the transition carries a MatchSpec (NU-020). Precomputed
2461
+ // so the hot enablement loop can skip the match check on non-ν transitions
2462
+ // (zero-cost gating), mirroring `_hasGuards`.
2463
+ _hasMatch;
2390
2464
  constructor(net) {
2391
2465
  this.net = net;
2392
2466
  const allPlacesSet = /* @__PURE__ */ new Map();
@@ -2418,12 +2492,14 @@ var CompiledNet = class _CompiledNet {
2418
2492
  this._consumptionPlaceIds = new Array(this.transitionCount);
2419
2493
  this._cardinalityChecks = new Array(this.transitionCount).fill(null);
2420
2494
  this._hasGuards = new Array(this.transitionCount).fill(false);
2495
+ this._hasMatch = new Array(this.transitionCount).fill(false);
2421
2496
  const placeToTransitionsList = new Array(this.placeCount);
2422
2497
  for (let i = 0; i < this.placeCount; i++) {
2423
2498
  placeToTransitionsList[i] = [];
2424
2499
  }
2425
2500
  for (let tid = 0; tid < this.transitionCount; tid++) {
2426
2501
  const t = this._transitionsById[tid];
2502
+ this._hasMatch[tid] = t.matchSpec !== null;
2427
2503
  const needs = new Uint32Array(this.wordCount);
2428
2504
  const inhibitors = new Uint32Array(this.wordCount);
2429
2505
  let needsCardinality = false;
@@ -2505,6 +2581,9 @@ var CompiledNet = class _CompiledNet {
2505
2581
  hasGuards(tid) {
2506
2582
  return this._hasGuards[tid];
2507
2583
  }
2584
+ hasMatch(tid) {
2585
+ return this._hasMatch[tid];
2586
+ }
2508
2587
  // ==================== Enablement Check ====================
2509
2588
  /**
2510
2589
  * Two-phase bitmap enablement check for a transition:
@@ -2609,6 +2688,81 @@ function inMemoryEventStore() {
2609
2688
  return new InMemoryEventStore();
2610
2689
  }
2611
2690
 
2691
+ // src/runtime/match-engine.ts
2692
+ function selectMatchName(perPlace, requireds) {
2693
+ if (perPlace.length === 0) return null;
2694
+ let seed = 0;
2695
+ for (let i = 1; i < perPlace.length; i++) {
2696
+ if (perPlace[i].size < perPlace[seed].size) seed = i;
2697
+ }
2698
+ let bestName = null;
2699
+ let bestTs = 0;
2700
+ for (const [name, stat] of perPlace[seed]) {
2701
+ if (stat.count < requireds[seed]) continue;
2702
+ let repTs = Number.MAX_SAFE_INTEGER;
2703
+ let satisfied = true;
2704
+ for (let j = 0; j < perPlace.length; j++) {
2705
+ const s = perPlace[j].get(name);
2706
+ if (s === void 0 || s.count < requireds[j]) {
2707
+ satisfied = false;
2708
+ break;
2709
+ }
2710
+ repTs = Math.min(repTs, s.minCreatedAt);
2711
+ }
2712
+ if (!satisfied) continue;
2713
+ const take = bestName === null || repTs < bestTs || repTs === bestTs && name < bestName;
2714
+ if (take) {
2715
+ bestName = name;
2716
+ bestTs = repTs;
2717
+ }
2718
+ }
2719
+ return bestName;
2720
+ }
2721
+ function buildNameIndex(tokens, key, guard) {
2722
+ const index = /* @__PURE__ */ new Map();
2723
+ for (const token of tokens) {
2724
+ if (guard && !guard(token.value)) continue;
2725
+ const name = key(token.value);
2726
+ if (name === void 0 || name === null) continue;
2727
+ const ts = token.createdAt;
2728
+ const prev = index.get(name);
2729
+ if (prev) {
2730
+ prev.count++;
2731
+ if (ts < prev.minCreatedAt) prev.minCreatedAt = ts;
2732
+ } else {
2733
+ index.set(name, { count: 1, minCreatedAt: ts });
2734
+ }
2735
+ }
2736
+ return index;
2737
+ }
2738
+ function requiredFor(t, placeName) {
2739
+ for (const inSpec of t.inputSpecs) {
2740
+ if (inSpec.place.name === placeName) {
2741
+ if (inSpec.type === "exactly") return inSpec.count;
2742
+ if (inSpec.type === "at-least") return inSpec.minimum;
2743
+ return 1;
2744
+ }
2745
+ }
2746
+ return 1;
2747
+ }
2748
+ function findBinding(t, getTokens) {
2749
+ const ms = t.matchSpec;
2750
+ if (!ms) return null;
2751
+ const perPlace = [];
2752
+ const requireds = [];
2753
+ for (const k of ms.keys) {
2754
+ perPlace.push(buildNameIndex(getTokens(k.place), k.key, guardFor(t, k.place.name)));
2755
+ requireds.push(requiredFor(t, k.place.name));
2756
+ }
2757
+ return selectMatchName(perPlace, requireds);
2758
+ }
2759
+ function guardFor(t, placeName) {
2760
+ for (const inSpec of t.inputSpecs) {
2761
+ if (inSpec.place.name === placeName) return inSpec.guard;
2762
+ }
2763
+ return void 0;
2764
+ }
2765
+
2612
2766
  // src/runtime/out-violation-error.ts
2613
2767
  var OutViolationError = class extends Error {
2614
2768
  constructor(message) {
@@ -2682,6 +2836,8 @@ function produceTimeoutOutput(context, timeoutChild) {
2682
2836
  var BitmapNetExecutor = class {
2683
2837
  compiled;
2684
2838
  marking;
2839
+ /** Monotonic source for ν-name minting (ctx.freshName(), NU-010). */
2840
+ freshNameCounter = 0;
2685
2841
  eventStore;
2686
2842
  environmentPlaces;
2687
2843
  hasEnvironmentPlaces;
@@ -2980,6 +3136,12 @@ var BitmapNetExecutor = class {
2980
3136
  if (this.marking.countMatching(spec) < requiredCount2) return false;
2981
3137
  }
2982
3138
  }
3139
+ if (this.compiled.hasMatch(tid)) {
3140
+ const tMatch = this.compiled.transition(tid);
3141
+ if (findBinding(tMatch, (p) => this.marking.peekTokens(p)) === null) {
3142
+ return false;
3143
+ }
3144
+ }
2983
3145
  return true;
2984
3146
  }
2985
3147
  hasInputFromResetPlace(t) {
@@ -3057,7 +3219,20 @@ var BitmapNetExecutor = class {
3057
3219
  const t = this.compiled.transition(tid);
3058
3220
  const inputs = new TokenInput();
3059
3221
  const consumed = [];
3222
+ const ms = t.matchSpec;
3223
+ const chosen = ms ? findBinding(t, (p) => this.marking.peekTokens(p)) : null;
3060
3224
  for (const inSpec of t.inputSpecs) {
3225
+ const keyFn = ms ? keyForPlace(ms, inSpec.place.name) : void 0;
3226
+ let spec;
3227
+ if (keyFn && chosen !== null) {
3228
+ const baseGuard = inSpec.guard;
3229
+ spec = {
3230
+ place: inSpec.place,
3231
+ guard: (v) => (baseGuard ? baseGuard(v) : true) && keyFn(v) === chosen
3232
+ };
3233
+ } else {
3234
+ spec = inSpec;
3235
+ }
3061
3236
  let toConsume;
3062
3237
  switch (inSpec.type) {
3063
3238
  case "one":
@@ -3067,14 +3242,12 @@ var BitmapNetExecutor = class {
3067
3242
  toConsume = inSpec.count;
3068
3243
  break;
3069
3244
  case "all":
3070
- toConsume = inSpec.guard ? this.marking.countMatching(inSpec) : this.marking.tokenCount(inSpec.place);
3071
- break;
3072
3245
  case "at-least":
3073
- toConsume = inSpec.guard ? this.marking.countMatching(inSpec) : this.marking.tokenCount(inSpec.place);
3246
+ toConsume = spec.guard ? this.marking.countMatching(spec) : this.marking.tokenCount(inSpec.place);
3074
3247
  break;
3075
3248
  }
3076
3249
  for (let i = 0; i < toConsume; i++) {
3077
- const token = inSpec.guard ? this.marking.removeFirstMatching(inSpec) : this.marking.removeFirst(inSpec.place);
3250
+ const token = spec.guard ? this.marking.removeFirstMatching(spec) : this.marking.removeFirst(inSpec.place);
3078
3251
  if (token === null) break;
3079
3252
  consumed.push(token);
3080
3253
  inputs.add(inSpec.place, token);
@@ -3136,6 +3309,8 @@ var BitmapNetExecutor = class {
3136
3309
  logFn,
3137
3310
  t.placeAlias
3138
3311
  );
3312
+ const freshNameBase = t.name;
3313
+ context.setFreshNameSupplier(() => nameId(`${freshNameBase}#${this.freshNameCounter++}`));
3139
3314
  let actionPromise = t.action(context);
3140
3315
  if (t.hasActionTimeout()) {
3141
3316
  const timeoutSpec = t.actionTimeout;
@@ -3488,6 +3663,9 @@ var PrecompiledNet = class _PrecompiledNet {
3488
3663
  // ==================== Cardinality & Guards ====================
3489
3664
  cardinalityChecks;
3490
3665
  hasGuards;
3666
+ // ν-net join flag (NU-020): gates the match-binding check off the hot
3667
+ // enablement path for non-ν transitions, mirroring `hasGuards`.
3668
+ hasMatch;
3491
3669
  // ==================== Global Flags ====================
3492
3670
  allImmediate;
3493
3671
  allSamePriority;
@@ -3582,12 +3760,15 @@ var PrecompiledNet = class _PrecompiledNet {
3582
3760
  this.consumptionPlaceIds = consumptionPlaceIds;
3583
3761
  const cardinalityChecks = new Array(tc);
3584
3762
  const hasGuards = new Array(tc);
3763
+ const hasMatch = new Array(tc);
3585
3764
  for (let tid = 0; tid < tc; tid++) {
3586
3765
  cardinalityChecks[tid] = compiled.cardinalityCheck(tid);
3587
3766
  hasGuards[tid] = compiled.hasGuards(tid);
3767
+ hasMatch[tid] = compiled.hasMatch(tid);
3588
3768
  }
3589
3769
  this.cardinalityChecks = cardinalityChecks;
3590
3770
  this.hasGuards = hasGuards;
3771
+ this.hasMatch = hasMatch;
3591
3772
  this.earliestMs = new Float64Array(tc);
3592
3773
  this.latestMs = new Float64Array(tc);
3593
3774
  this.hasDeadline = new Uint8Array(tc);
@@ -3783,6 +3964,17 @@ var PrecompiledNetExecutor = class {
3783
3964
  // ==================== Token Storage ====================
3784
3965
  /** Per-place token arrays, indexed by pid. */
3785
3966
  tokenQueues;
3967
+ /** Monotonic source for ν-name minting (ctx.freshName(), NU-010). */
3968
+ freshNameCounter = 0;
3969
+ /**
3970
+ * Per-transition ν-name minter cache, indexed by tid (built lazily). Each
3971
+ * supplier is created once and reused across firings, so installing it on a
3972
+ * per-fire context is a field assignment rather than a per-fire closure
3973
+ * allocation — keeping the fire path lean for non-ν transitions. Every
3974
+ * transition gets one (forks mint but carry no MatchSpec, so gating on
3975
+ * `hasMatch` would wrongly starve them).
3976
+ */
3977
+ freshNameSuppliers = [];
3786
3978
  // ==================== Marking Bitmap ====================
3787
3979
  markingBitmap;
3788
3980
  // ==================== Transition State ====================
@@ -4085,6 +4277,12 @@ var PrecompiledNetExecutor = class {
4085
4277
  if (this.countMatching(prog.compiled.placeId(spec.place), spec.guard) < required) return false;
4086
4278
  }
4087
4279
  }
4280
+ if (prog.hasMatch[tid]) {
4281
+ const tMatch = prog.compiled.transition(tid);
4282
+ if (findBinding(tMatch, (p) => this.tokenQueues[prog.compiled.placeId(p)]) === null) {
4283
+ return false;
4284
+ }
4285
+ }
4088
4286
  return true;
4089
4287
  }
4090
4288
  countMatching(pid, guard) {
@@ -4174,7 +4372,9 @@ var PrecompiledNetExecutor = class {
4174
4372
  const t = prog.compiled.transition(tid);
4175
4373
  const consumed = [];
4176
4374
  const inputs = new TokenInput();
4177
- if (prog.hasGuards[tid]) {
4375
+ if (t.matchSpec) {
4376
+ this.fireTransitionMatched(tid, t, inputs, consumed);
4377
+ } else if (prog.hasGuards[tid]) {
4178
4378
  this.fireTransitionGuarded(tid, t, inputs, consumed);
4179
4379
  } else {
4180
4380
  const ops = prog.consumeOps[tid];
@@ -4308,6 +4508,13 @@ var PrecompiledNetExecutor = class {
4308
4508
  logFn,
4309
4509
  t.placeAlias
4310
4510
  );
4511
+ let freshNameSupplier = this.freshNameSuppliers[tid];
4512
+ if (freshNameSupplier === void 0) {
4513
+ const base = t.name;
4514
+ freshNameSupplier = () => nameId(`${base}#${this.freshNameCounter++}`);
4515
+ this.freshNameSuppliers[tid] = freshNameSupplier;
4516
+ }
4517
+ context.setFreshNameSupplier(freshNameSupplier);
4311
4518
  let actionPromise = t.action(context);
4312
4519
  if (t.hasActionTimeout()) {
4313
4520
  const timeoutSpec = t.actionTimeout;
@@ -4361,6 +4568,63 @@ var PrecompiledNetExecutor = class {
4361
4568
  this.enabledTransitionCount--;
4362
4569
  this.enabledAtMs[tid] = -Infinity;
4363
4570
  }
4571
+ /**
4572
+ * Consumes the name-matched tokens for a ν-net join (NU-020): correlated
4573
+ * inputs take tokens whose projected name equals the chosen binding (guard
4574
+ * first, then name equality — NU-021); other inputs consume FIFO. Reset arcs
4575
+ * are honoured as on the opcode path. Mirrors {@link fireTransitionGuarded}.
4576
+ */
4577
+ fireTransitionMatched(_tid, t, inputs, consumed) {
4578
+ const prog = this.program;
4579
+ const ms = t.matchSpec;
4580
+ const chosen = findBinding(t, (p) => this.tokenQueues[prog.compiled.placeId(p)]);
4581
+ for (const inSpec of t.inputSpecs) {
4582
+ const pid = prog.compiled.placeId(inSpec.place);
4583
+ const keyFn = keyForPlace(ms, inSpec.place.name);
4584
+ const baseGuard = inSpec.guard;
4585
+ const pred = keyFn && chosen !== null ? (v) => (baseGuard ? baseGuard(v) : true) && keyFn(v) === chosen : baseGuard;
4586
+ let toConsume;
4587
+ switch (inSpec.type) {
4588
+ case "one":
4589
+ toConsume = 1;
4590
+ break;
4591
+ case "exactly":
4592
+ toConsume = inSpec.count;
4593
+ break;
4594
+ case "all":
4595
+ case "at-least":
4596
+ toConsume = pred ? this.countMatching(pid, pred) : this.tokenQueues[pid].length;
4597
+ break;
4598
+ }
4599
+ for (let i = 0; i < toConsume; i++) {
4600
+ const token = pred ? this.removeFirstMatching(pid, pred) : this.tokenQueues[pid].shift() ?? null;
4601
+ if (token === null) break;
4602
+ consumed.push(token);
4603
+ inputs.add(inSpec.place, token);
4604
+ this.emitEvent({
4605
+ type: "token-removed",
4606
+ timestamp: Date.now(),
4607
+ placeName: inSpec.place.name,
4608
+ token
4609
+ });
4610
+ }
4611
+ }
4612
+ for (const arc of t.resets) {
4613
+ const pid = prog.compiled.placeId(arc.place);
4614
+ const tokens = this.tokenQueues[pid].splice(0);
4615
+ this.pendingResetWords[pid >>> WORD_SHIFT] |= 1 << (pid & BIT_MASK);
4616
+ this.hasPendingResets = true;
4617
+ for (const token of tokens) {
4618
+ consumed.push(token);
4619
+ this.emitEvent({
4620
+ type: "token-removed",
4621
+ timestamp: Date.now(),
4622
+ placeName: arc.place.name,
4623
+ token
4624
+ });
4625
+ }
4626
+ }
4627
+ }
4364
4628
  fireTransitionGuarded(_tid, t, inputs, consumed) {
4365
4629
  const prog = this.program;
4366
4630
  for (const inSpec of t.inputSpecs) {
@@ -4719,8 +4983,13 @@ export {
4719
4983
  intersects,
4720
4984
  isFailureEvent,
4721
4985
  isUnit,
4986
+ keyForPlace,
4722
4987
  latest,
4988
+ matchCorrelates,
4989
+ matchKey,
4990
+ matchSpec,
4723
4991
  matchesGuard,
4992
+ nameId,
4724
4993
  noopEventStore,
4725
4994
  one,
4726
4995
  openSubnet,