libpetri 2.13.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  matchCorrelates
3
- } from "./chunk-E3ZWB645.js";
3
+ } from "./chunk-YVIPJ6KM.js";
4
4
  import {
5
5
  earliest,
6
6
  hasDeadline,
@@ -714,4 +714,4 @@ export {
714
714
  renderDot,
715
715
  dotExport
716
716
  };
717
- //# sourceMappingURL=chunk-JVI5HFRX.js.map
717
+ //# sourceMappingURL=chunk-VCDOKWVU.js.map
@@ -24,4 +24,4 @@ export {
24
24
  keyForPlace,
25
25
  matchCorrelates
26
26
  };
27
- //# sourceMappingURL=chunk-E3ZWB645.js.map
27
+ //# sourceMappingURL=chunk-YVIPJ6KM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/match-spec.ts"],"sourcesContent":["/**\n * ν-net join correlation ([[MatchSpec]]).\n *\n * A {@link MatchSpec} declares that a subset of a transition's **input** places\n * must be correlated by **name equality**: the transition is enabled only when\n * there exists a single {@link NameId} `n` such that every correlated input\n * supplies (at least) its required token count whose projected name equals `n`.\n * On firing, exactly those name-matched tokens are consumed (spec NU-020).\n *\n * This is the single *decidable* predicate — equality of opaque names — and is\n * deliberately NOT a general input predicate: it correlates the name dimension\n * *across* places (composition-structural, like cardinality) rather than\n * evaluating an arbitrary boolean per token. Input specifications themselves\n * remain purely structural (IO-006); name correlation is the only per-token\n * filter the enablement check ever applies (NU-021).\n */\nimport type { Place } from './place.js';\nimport type { NameId } from './name.js';\n\n/**\n * A name projection: maps a token's value to its {@link NameId}. A projection\n * that yields no name (returns `null`/`undefined` at runtime) is treated as\n * \"no name\" — that token never correlates — mirroring the Java/Rust `KeyFn`\n * contract; the binding selector handles a nullish result defensively.\n */\nexport type KeyFn<T = any> = (value: T) => NameId;\n\n/** One correlated input: the place plus its name projection. */\nexport interface MatchKey<T = any> {\n readonly place: Place<T>;\n readonly key: KeyFn<T>;\n}\n\n/** Correlated fork/join match specification (ν-net join side). */\nexport interface MatchSpec {\n readonly keys: readonly MatchKey[];\n}\n\n/** Builds one correlated input for a {@link MatchSpec}. */\nexport function matchKey<T>(place: Place<T>, key: KeyFn<T>): MatchKey<T> {\n return { place, key };\n}\n\n/**\n * Builds a {@link MatchSpec} from two or more correlated inputs.\n *\n * @example\n * Transition.builder('join')\n * .inputs(one(branchA), one(branchB))\n * .match(matchSpec(\n * matchKey(branchA, (m: Msg) => nameId(m.correlationId)),\n * matchKey(branchB, (m: Msg) => nameId(m.correlationId)),\n * ))\n *\n * @throws if fewer than two inputs are correlated (a match over a single place\n * correlates nothing).\n */\nexport function matchSpec(...keys: MatchKey[]): MatchSpec {\n if (keys.length < 2) {\n throw new Error(`MatchSpec must correlate at least 2 input places, got ${keys.length}`);\n }\n return { keys };\n}\n\n/** Returns the name projection for `placeName`, or `undefined` if not correlated. */\nexport function keyForPlace(spec: MatchSpec, placeName: string): KeyFn | undefined {\n for (const k of spec.keys) {\n if (k.place.name === placeName) return k.key;\n }\n return undefined;\n}\n\n/** True when `placeName` is one of the correlated inputs. */\nexport function matchCorrelates(spec: MatchSpec, placeName: string): boolean {\n return spec.keys.some(k => k.place.name === placeName);\n}\n"],"mappings":";AAuCO,SAAS,SAAY,OAAiB,KAA4B;AACvE,SAAO,EAAE,OAAO,IAAI;AACtB;AAgBO,SAAS,aAAa,MAA6B;AACxD,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,IAAI,MAAM,yDAAyD,KAAK,MAAM,EAAE;AAAA,EACxF;AACA,SAAO,EAAE,KAAK;AAChB;AAGO,SAAS,YAAY,MAAiB,WAAsC;AACjF,aAAW,KAAK,KAAK,MAAM;AACzB,QAAI,EAAE,MAAM,SAAS,UAAW,QAAO,EAAE;AAAA,EAC3C;AACA,SAAO;AACT;AAGO,SAAS,gBAAgB,MAAiB,WAA4B;AAC3E,SAAO,KAAK,KAAK,KAAK,OAAK,EAAE,MAAM,SAAS,SAAS;AACvD;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import { Writable } from 'node:stream';
2
- import { P as PetriNet, b as Transition, T as Token } from '../petri-net-C3LSY-vm.js';
3
- import { E as EventStore, N as NetEvent } from '../event-store-DKTenPbC.js';
2
+ import { P as PetriNet, b as Transition, T as Token } from '../petri-net-UQBBkvLl.js';
3
+ import { E as EventStore, N as NetEvent } from '../event-store-Df_sAVQ_.js';
4
4
 
5
5
  /**
6
6
  * Commands sent from debug UI client to server via WebSocket.
@@ -6,8 +6,8 @@ import {
6
6
  instancePrefixOf,
7
7
  parentOf,
8
8
  sanitize
9
- } from "../chunk-JVI5HFRX.js";
10
- import "../chunk-E3ZWB645.js";
9
+ } from "../chunk-VCDOKWVU.js";
10
+ import "../chunk-YVIPJ6KM.js";
11
11
  import "../chunk-ATT7U5H5.js";
12
12
 
13
13
  // src/debug/debug-command.ts
@@ -1,5 +1,5 @@
1
1
  import { Application } from 'typedoc';
2
- import { P as PetriNet, S as SubnetDef, o as Instance } from '../petri-net-C3LSY-vm.js';
2
+ import { P as PetriNet, S as SubnetDef, o as Instance } from '../petri-net-UQBBkvLl.js';
3
3
 
4
4
  /**
5
5
  * TypeDoc plugin for `@petrinet` and `@subnet` tags — auto-generates
@@ -3,8 +3,8 @@ import {
3
3
  dotExport,
4
4
  nodeStyle,
5
5
  sanitize
6
- } from "../chunk-JVI5HFRX.js";
7
- import "../chunk-E3ZWB645.js";
6
+ } from "../chunk-VCDOKWVU.js";
7
+ import "../chunk-YVIPJ6KM.js";
8
8
  import "../chunk-ATT7U5H5.js";
9
9
 
10
10
  // src/doclet/petri-net-plugin.ts
@@ -447,7 +447,7 @@ function escapeLabel(s) {
447
447
 
448
448
  // src/doclet/petri-net-plugin.ts
449
449
  async function getDotExport() {
450
- const mod = await import("../dot-exporter-SHBYMMJ3.js");
450
+ const mod = await import("../dot-exporter-3STXYK74.js");
451
451
  return mod.dotExport;
452
452
  }
453
453
  var TAG_PETRINET = "@petrinet";
@@ -0,0 +1,9 @@
1
+ import {
2
+ dotExport
3
+ } from "./chunk-VCDOKWVU.js";
4
+ import "./chunk-YVIPJ6KM.js";
5
+ import "./chunk-ATT7U5H5.js";
6
+ export {
7
+ dotExport
8
+ };
9
+ //# sourceMappingURL=dot-exporter-3STXYK74.js.map
@@ -1,4 +1,4 @@
1
- import { T as Token } from './petri-net-C3LSY-vm.js';
1
+ import { T as Token } from './petri-net-UQBBkvLl.js';
2
2
 
3
3
  /**
4
4
  * Events emitted during Petri Net execution.
@@ -1,4 +1,4 @@
1
- import { P as PetriNet } from '../petri-net-C3LSY-vm.js';
1
+ import { P as PetriNet } from '../petri-net-UQBBkvLl.js';
2
2
 
3
3
  /**
4
4
  * Format-agnostic typed graph model.
@@ -8,8 +8,8 @@ import {
8
8
  nodeStyle,
9
9
  renderDot,
10
10
  sanitize
11
- } from "../chunk-JVI5HFRX.js";
12
- import "../chunk-E3ZWB645.js";
11
+ } from "../chunk-VCDOKWVU.js";
12
+ import "../chunk-YVIPJ6KM.js";
13
13
  import "../chunk-ATT7U5H5.js";
14
14
  export {
15
15
  DEFAULT_DOT_CONFIG,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-C3LSY-vm.js';
2
- export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, K as KeyFn, L as LogFn, M as MAX_DURATION_MS, r as MatchKey, s as MatchSpec, N as NameId, t as OutAnd, u as OutForwardInput, v as OutPlace, w as OutTimeout, x as OutXor, y as OutputEntry, z as PetriNetBuilder, B as Port, D as PortDirection, G as SubnetDefBuilder, H as SubnetInstance, J as Timing, Q as TimingDeadline, R as TimingDelayed, U as TimingExact, V as TimingImmediate, W as TimingWindow, X as TokenInput, Y as TokenOutput, Z as TransitionAction, _ as TransitionBuilder, $ as VerificationHarness, a0 as VerificationResult, a1 as all, a2 as allPlaces, a3 as and, a4 as andPlaces, a5 as arcPlace, a6 as atLeast, a7 as consumptionCount, a8 as deadline, a9 as delayed, aa as earliest, ab as enumerateBranches, ac as environmentPlace, ad as exact, ae as exactly, af as fork, ag as forwardInput, ah as hasDeadline, ai as hasGuard, aj as immediate, ak as inhibitorArc, al as inputArc, am as isPassthrough, an as isUnit, ao as keyForPlace, ap as latest, aq as matchCorrelates, ar as matchKey, as as matchSpec, at as matchesGuard, au as nameId, av as one, aw as outPlace, ax as outputArc, ay as passthrough, az as place, aA as produce, aB as readArc, aC as requiredCount, aD as resetArc, aE as timeout, aF as timeoutPlace, aG as tokenAt, aH as tokenOf, aI as transform, aJ as transformAsync, aK as transformFrom, aL as unitToken, aM as window, aN as withTimeout, aO as xor, aP as xorPlaces } from './petri-net-C3LSY-vm.js';
3
- import { E as EventStore } from './event-store-DKTenPbC.js';
4
- export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-DKTenPbC.js';
1
+ import { P as PetriNet, S as SubnetDef, a as Place, T as Token, b as Transition, E as EnvironmentPlace, c as TransitionContext, O as Out } from './petri-net-UQBBkvLl.js';
2
+ export { A as Arc, d as ArcInhibitor, e as ArcInput, f as ArcOutput, g as ArcRead, h as ArcReset, C as Channel, i as ComposeBindings, F as FusionSet, j as FusionSetBuilder, I as In, k as InAll, l as InAtLeast, m as InExactly, n as InOne, o as Instance, p as Interface, q as InterfaceBuilder, K as KeyFn, L as LogFn, M as MAX_DURATION_MS, r as MatchKey, s as MatchSpec, N as NameId, t as OutAnd, u as OutForwardInput, v as OutPlace, w as OutTimeout, x as OutXor, y as OutputEntry, z as PetriNetBuilder, B as Port, D as PortDirection, G as SubnetDefBuilder, H as SubnetInstance, J as Timing, Q as TimingDeadline, R as TimingDelayed, U as TimingExact, V as TimingImmediate, W as TimingWindow, X as TokenInput, Y as TokenOutput, Z as TransitionAction, _ as TransitionBuilder, $ as VerificationHarness, a0 as VerificationResult, a1 as all, a2 as allPlaces, a3 as and, a4 as andPlaces, a5 as arcPlace, a6 as atLeast, a7 as consumptionCount, a8 as deadline, a9 as delayed, aa as earliest, ab as enumerateBranches, ac as environmentPlace, ad as exact, ae as exactly, af as fork, ag as forwardInput, ah as hasDeadline, ai as immediate, aj as inhibitorArc, ak as inputArc, al as isPassthrough, am as isUnit, an as keyForPlace, ao as latest, ap as matchCorrelates, aq as matchKey, ar as matchSpec, as as nameId, at as one, au as outPlace, av as outputArc, aw as passthrough, ax as place, ay as produce, az as readArc, aA as requiredCount, aB as resetArc, aC as timeout, aD as timeoutPlace, aE as tokenAt, aF as tokenOf, aG as transform, aH as transformAsync, aI as transformFrom, aJ as unitToken, aK as window, aL as withTimeout, aM as xor, aN as xorPlaces } from './petri-net-UQBBkvLl.js';
3
+ import { E as EventStore } from './event-store-Df_sAVQ_.js';
4
+ export { A as ActionTimedOut, a as ExecutionCompleted, b as ExecutionStarted, I as InMemoryEventStore, L as LogMessage, M as MarkingSnapshot, N as NetEvent, T as TokenAdded, c as TokenRemoved, d as TransitionClockRestarted, e as TransitionCompleted, f as TransitionEnabled, g as TransitionFailed, h as TransitionStarted, i as TransitionTimedOut, j as eventTransitionName, k as eventsOfType, l as failures, m as filterEvents, n as inMemoryEventStore, o as isFailureEvent, p as noopEventStore, t as transitionEvents } from './event-store-Df_sAVQ_.js';
5
5
 
6
6
  /**
7
7
  * Discriminated sum-type abstraction over Petri nets, distinguishing **closed**
@@ -51,10 +51,17 @@ declare function openSubnet(def: SubnetDef<unknown>): Subnet;
51
51
  * due to cache locality. Only optimize if profiling shows a bottleneck.
52
52
  */
53
53
 
54
- /** Anything that carries a place reference and an optional guard predicate. */
55
- interface GuardSpec<T = any> {
54
+ /**
55
+ * A place reference plus an optional per-token predicate.
56
+ *
57
+ * Used by the ν-net join path (NU-020/NU-021) to select the tokens whose
58
+ * projected correlation name equals the chosen binding. This is *not* an input
59
+ * guard (IO-006, removed) — input specifications are purely structural; the
60
+ * predicate here is always derived from name correlation.
61
+ */
62
+ interface PredicateSpec<T = any> {
56
63
  readonly place: Place<T>;
57
- readonly guard?: (value: T) => boolean;
64
+ readonly predicate?: (value: T) => boolean;
58
65
  }
59
66
  /**
60
67
  * Mutable marking (token state) of a Petri Net during execution.
@@ -75,23 +82,23 @@ declare class Marking {
75
82
  /** Removes and returns all tokens from a place. */
76
83
  removeAll<T>(place: Place<T>): Token<T>[];
77
84
  /**
78
- * Removes and returns the first token whose value satisfies the guard predicate.
85
+ * Removes and returns the first token whose value satisfies the predicate.
79
86
  *
80
- * Performs a linear scan of the place's FIFO queue. If no guard is provided,
81
- * behaves like `removeFirst()`. If a guard is provided, skips non-matching
87
+ * Performs a linear scan of the place's FIFO queue. If no predicate is
88
+ * provided, behaves like `removeFirst()`. Otherwise skips non-matching
82
89
  * tokens and splices the first match out of the queue (O(n) worst case).
83
90
  */
84
- removeFirstMatching(spec: GuardSpec): Token<any> | null;
85
- /** Check if any token matches a guard predicate. */
86
- hasMatchingToken(spec: GuardSpec): boolean;
91
+ removeFirstMatching(spec: PredicateSpec): Token<any> | null;
92
+ /** Check if any token satisfies the predicate. */
93
+ hasMatchingToken(spec: PredicateSpec): boolean;
87
94
  /**
88
- * Counts tokens in a place whose values satisfy the guard predicate.
95
+ * Counts tokens in a place whose values satisfy the predicate.
89
96
  *
90
- * If no guard is provided, returns the total token count (O(1)).
91
- * With a guard, performs a linear scan over all tokens (O(n)).
92
- * Used by the executor for enablement checks on guarded `all`/`at-least` inputs.
97
+ * If no predicate is provided, returns the total token count (O(1)).
98
+ * With a predicate, performs a linear scan over all tokens (O(n)).
99
+ * Used by the executor to size a ν-net correlated `all`/`at-least` consume.
93
100
  */
94
- countMatching(spec: GuardSpec): number;
101
+ countMatching(spec: PredicateSpec): number;
95
102
  /**
96
103
  * Returns tokens in a place. **Returns a live reference** to the internal
97
104
  * array — callers must not mutate it. Copy with `[...peekTokens(p)]` if
@@ -147,18 +154,22 @@ declare class CompiledNet {
147
154
  private readonly _placeToTransitions;
148
155
  private readonly _consumptionPlaceIds;
149
156
  private readonly _cardinalityChecks;
150
- private readonly _hasGuards;
151
157
  private readonly _hasMatch;
152
158
  private constructor();
153
159
  static compile(net: PetriNet): CompiledNet;
154
160
  place(pid: number): Place<any>;
155
161
  transition(tid: number): Transition;
156
162
  placeId(place: Place<any>): number;
163
+ /**
164
+ * Non-throwing variant of {@link placeId}: `undefined` when the compiled net
165
+ * does not know the place. Lets callers retain tokens on undeclared places
166
+ * (CORE-072) instead of rejecting or dropping them.
167
+ */
168
+ tryPlaceId(place: Place<any>): number | undefined;
157
169
  transitionId(t: Transition): number;
158
170
  affectedTransitions(pid: number): readonly number[];
159
171
  consumptionPlaceIds(tid: number): readonly number[];
160
172
  cardinalityCheck(tid: number): CardinalityCheck | null;
161
- hasGuards(tid: number): boolean;
162
173
  hasMatch(tid: number): boolean;
163
174
  /**
164
175
  * Two-phase bitmap enablement check for a transition:
@@ -167,8 +178,9 @@ declare class CompiledNet {
167
178
  * 2. **Inhibitor check**: verifies no inhibitor places have tokens
168
179
  * via `!intersects(snapshot, inhibitorMask)`.
169
180
  *
170
- * This is a necessary but not sufficient condition — cardinality and guard checks
171
- * are performed separately by the executor for transitions that pass this fast path.
181
+ * This is a necessary but not sufficient condition — cardinality and ν-net match
182
+ * checks are performed separately by the executor for transitions that pass this
183
+ * fast path.
172
184
  */
173
185
  canEnableBitmap(tid: number, markingSnapshot: Uint32Array): boolean;
174
186
  }
@@ -273,7 +285,7 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
273
285
  private readonly allImmediate;
274
286
  private readonly allSamePriority;
275
287
  private readonly eventStoreEnabled;
276
- private readonly markedPlaces;
288
+ private readonly markingBitmap;
277
289
  private readonly dirtySet;
278
290
  private readonly markingSnapBuffer;
279
291
  private readonly dirtySnapBuffer;
@@ -296,6 +308,11 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
296
308
  private wakeUpResolve;
297
309
  private readonly readyBuffer;
298
310
  private readonly pendingResetPlaces;
311
+ /**
312
+ * Undeclared place names already reported (CORE-072 AC4). Keyed by name — TS
313
+ * Place identity is name-based — so a hot loop warns once, not per token.
314
+ */
315
+ private readonly warnedUnknownPlaces;
299
316
  private readonly transitionInputPlaceNames;
300
317
  private running;
301
318
  private draining;
@@ -315,7 +332,7 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
315
332
  inject<T>(envPlace: EnvironmentPlace<T>, token: Token<T>): Promise<boolean>;
316
333
  /** Convenience: inject a raw value (creates token with current timestamp). */
317
334
  injectValue<T>(envPlace: EnvironmentPlace<T>, value: T): Promise<boolean>;
318
- private initializeMarkedBitmap;
335
+ private initializeMarkingBitmap;
319
336
  private markAllDirty;
320
337
  private shouldTerminate;
321
338
  private updateDirtyTransitions;
@@ -337,7 +354,7 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
337
354
  * Fast path for nets where all transitions are immediate and same priority.
338
355
  * Skips timing checks, sorting, and snapshot buffer — just scan and fire.
339
356
  *
340
- * Uses live `markedPlaces` instead of a snapshot. Safe because
357
+ * Uses live `markingBitmap` instead of a snapshot. Safe because
341
358
  * `updateBitmapAfterConsumption()` synchronously updates the bitmap before the next
342
359
  * iteration. For equal-priority immediate transitions, tid scan order satisfies
343
360
  * FIFO-by-enablement-time (all enabled in the same cycle).
@@ -352,7 +369,7 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
352
369
  * EventStore.append on a token-removed or transition-started emit, or an error thrown while
353
370
  * consuming the matched tokens — unwinds out of the orchestrator loop and kills the executor.
354
371
  * The transition is instead failed and marked dirty for re-evaluation, the same treatment an
355
- * asynchronously-reported failure gets. Enablement-phase throws (a guard or key function that
372
+ * asynchronously-reported failure gets. Enablement-phase throws (a key function that
356
373
  * throws inside canEnable, before the firing) run outside this boundary and are not contained
357
374
  * here.
358
375
  *
@@ -395,6 +412,12 @@ declare class BitmapNetExecutor implements PetriNetExecutor {
395
412
  executionId(): string;
396
413
  drain(): void;
397
414
  close(): void;
415
+ /**
416
+ * Reports an undeclared place once (CORE-072 AC4, emitted as the EVT-013
417
+ * log-message event). `transitionName` is the producer, empty at the
418
+ * initial-marking and injection seams. Retention never depends on this.
419
+ */
420
+ private warnUnknownPlace;
398
421
  private emitEvent;
399
422
  }
400
423
 
@@ -434,6 +457,12 @@ declare class PrecompiledNet {
434
457
  readonly places: readonly Place<any>[];
435
458
  /** Per-transition consume opcode sequences. */
436
459
  readonly consumeOps: readonly (readonly number[])[];
460
+ /**
461
+ * Per-transition index into {@link consumeOps} where the RESET tail begins; the
462
+ * executor peeks read arcs at this boundary so reads observe the post-input,
463
+ * pre-reset marking (EXEC-013 AC4).
464
+ */
465
+ readonly resetOpsStart: Uint32Array;
437
466
  /** Per-transition read-arc place IDs. */
438
467
  readonly readOps: readonly (readonly number[])[];
439
468
  readonly needsMask: readonly Uint32Array[];
@@ -466,7 +495,6 @@ declare class PrecompiledNet {
466
495
  readonly placeToTransitions: readonly (readonly number[])[];
467
496
  readonly consumptionPlaceIds: readonly (readonly number[])[];
468
497
  readonly cardinalityChecks: readonly (CardinalityCheck | null)[];
469
- readonly hasGuards: readonly boolean[];
470
498
  readonly hasMatch: readonly boolean[];
471
499
  readonly allImmediate: boolean;
472
500
  readonly allSamePriority: boolean;
@@ -544,6 +572,14 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
544
572
  private readonly eventStoreEnabled;
545
573
  /** Per-place token arrays, indexed by pid. */
546
574
  private readonly tokenQueues;
575
+ /**
576
+ * Tokens on places the compiled net does not know (CORE-072 AC3). Retained —
577
+ * never dropped — and merged into the materialized marking, matching the
578
+ * BitmapNetExecutor reference, whose Marking keeps them naturally. Keyed by
579
+ * place NAME (TS Place identity is name-based), carrying the Place so
580
+ * materializing a Marking has one to hand.
581
+ */
582
+ private readonly unknownPlaceTokens;
547
583
  /** Monotonic source for ν-name minting (ctx.freshName(), NU-010). */
548
584
  private freshNameCounter;
549
585
  /**
@@ -638,7 +674,7 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
638
674
  * EventStore.append on a token-removed or transition-started emit, or an error thrown while
639
675
  * consuming the matched tokens — unwinds out of the orchestrator loop and kills the executor.
640
676
  * The transition is instead failed and marked dirty for re-evaluation, the same treatment an
641
- * asynchronously-reported failure gets. Enablement-phase throws (a guard or key function that
677
+ * asynchronously-reported failure gets. Enablement-phase throws (a key function that
642
678
  * throws inside canEnable, before the firing) run outside this boundary and are not contained
643
679
  * here.
644
680
  *
@@ -646,24 +682,39 @@ declare class PrecompiledNetExecutor implements PetriNetExecutor {
646
682
  * so a throw inside that window would leave bits asserting tokens that are gone; the
647
683
  * recovery re-runs updateBitmapAfterConsumption against the true queue lengths.
648
684
  *
649
- * Named to avoid colliding with the pre-existing {@link fireTransitionGuarded}
650
- * guard-consume helper. Unlike the Java runtime there is no VirtualMachineError/
651
- * LinkageError analogue on the JS side, so every throw is contained here — there is
652
- * deliberately no fatal-rethrow escape hatch.
685
+ * Unlike the Java runtime there is no VirtualMachineError/LinkageError analogue on
686
+ * the JS side, so every throw is contained here — there is deliberately no
687
+ * fatal-rethrow escape hatch.
653
688
  */
654
689
  private fireTransitionContained;
655
690
  private fireTransition;
656
691
  /**
657
692
  * Consumes the name-matched tokens for a ν-net join (NU-020): correlated
658
- * inputs take tokens whose projected name equals the chosen binding (guard
659
- * first, then name equality — NU-021); other inputs consume FIFO. Reset arcs
660
- * are honoured as on the opcode path. Mirrors {@link fireTransitionGuarded}.
693
+ * inputs take tokens whose projected name equals the chosen binding (NU-021);
694
+ * other inputs consume FIFO. Reset arcs are honoured as on the opcode path.
661
695
  */
662
696
  private fireTransitionMatched;
663
- private fireTransitionGuarded;
697
+ /**
698
+ * Peeks each read-arc place's front token into the context inputs. Called at
699
+ * the input/reset boundary of a firing (EXEC-013): after input consumption,
700
+ * before reset draining — so read(p)+reset(p) observes the pre-reset token.
701
+ */
702
+ private peekReadArcs;
664
703
  private updateBitmapAfterConsumption;
665
704
  private processCompletedTransitions;
666
705
  private processExternalEvents;
706
+ /**
707
+ * Adds a produced or injected token: queue/bitmap/dirty for compiled places,
708
+ * or the retention side map when the program does not know it (CORE-072 AC3).
709
+ * `transitionName` is the producer, empty at the injection seam.
710
+ */
711
+ private produceToken;
712
+ /**
713
+ * Retains a token on an undeclared place (CORE-072 AC3) and reports the place
714
+ * once — the first insert is the only one that creates a map entry, so a hot
715
+ * loop cannot flood (AC4, emitted as the EVT-013 log-message event).
716
+ */
717
+ private retainUnknownToken;
667
718
  private drainPendingExternalEvents;
668
719
  private awaitWork;
669
720
  private millisUntilNextTimedTransition;
@@ -716,7 +767,9 @@ declare function validateOutSpec(tName: string, spec: Out, producedPlaceNames: S
716
767
  * exceeds its timeout. Walks the Out spec tree recursively:
717
768
  *
718
769
  * - **Place**: produces `null` (the timeout sentinel value).
719
- * - **ForwardInput**: forwards the consumed input token to the output place.
770
+ * - **ForwardInput**: forwards *all* tokens consumed from the `from` place to the
771
+ * output place, in consumption order — one output token per consumed token, so a
772
+ * batched input spec (`all()` / `exactly(n)`) conserves its tokens on timeout.
720
773
  * - **AND**: recurses into all children (all branches get tokens).
721
774
  * - **XOR**: disallowed — timeout cannot choose a branch non-deterministically.
722
775
  * - **Timeout**: disallowed — nested timeouts would create ambiguous recovery paths.
@@ -727,4 +780,4 @@ declare function validateOutSpec(tName: string, spec: Out, producedPlaceNames: S
727
780
  */
728
781
  declare function produceTimeoutOutput(context: TransitionContext, timeoutChild: Out): void;
729
782
 
730
- export { BitmapNetExecutor, type BitmapNetExecutorOptions, type CardinalityCheck, CompiledNet, EnvironmentPlace, EventStore, type GuardSpec, Marking, Out, OutViolationError, PetriNet, type PetriNetExecutor, Place, PrecompiledNet, PrecompiledNetExecutor, type PrecompiledNetExecutorOptions, type Subnet, SubnetDef, Token, Transition, TransitionContext, clearBit, closedSubnet, containsAll, intersects, openSubnet, produceTimeoutOutput, setBit, testBit, validateOutSpec };
783
+ export { BitmapNetExecutor, type BitmapNetExecutorOptions, type CardinalityCheck, CompiledNet, EnvironmentPlace, EventStore, Marking, Out, OutViolationError, PetriNet, type PetriNetExecutor, Place, PrecompiledNet, PrecompiledNetExecutor, type PrecompiledNetExecutorOptions, type PredicateSpec, type Subnet, SubnetDef, Token, Transition, TransitionContext, clearBit, closedSubnet, containsAll, intersects, openSubnet, produceTimeoutOutput, setBit, testBit, validateOutSpec };