quantum-forge 2.7.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.
@@ -7,20 +7,20 @@ interface InitializeOptions {
7
7
  /** Override Emscripten's default stdout handler (console.log). */
8
8
  print?: (text: string) => void;
9
9
  }
10
- declare class Predicate {
10
+ declare class Predicate$1 {
11
11
  private cppInstance;
12
12
  constructor(cppInstance: any);
13
13
  value(): number;
14
14
  is_equal(): boolean;
15
15
  getCppInstance(): any;
16
16
  }
17
- declare class QuantumProperty {
17
+ declare class QuantumProperty$1 {
18
18
  private cppInstance;
19
19
  constructor(dimension: number);
20
20
  index(): number;
21
21
  dimension(): number;
22
- is(value: number): Predicate;
23
- is_not(value: number): Predicate;
22
+ is(value: number): Predicate$1;
23
+ is_not(value: number): Predicate$1;
24
24
  /** Number of qudits in this property's shared quantum state. */
25
25
  num_active_qudits(): number;
26
26
  /** Current number of basis amplitudes in the state vector (sparse size). */
@@ -31,16 +31,16 @@ declare class QuantumProperty {
31
31
  is_valid(): boolean;
32
32
  getCppInstance(): any;
33
33
  /** @internal Create a QuantumProperty from an existing C++ instance. */
34
- static _fromCpp(cppInstance: any): QuantumProperty;
34
+ static _fromCpp(cppInstance: any): QuantumProperty$1;
35
35
  }
36
36
  declare class QuantumSimulation {
37
37
  private cppInstance;
38
38
  constructor();
39
- createProperty(dimension: number): QuantumProperty;
39
+ createProperty(dimension: number): QuantumProperty$1;
40
40
  /** Factorize a property out of this simulation's shared state and destroy it.
41
41
  * Automatically factors out any remaining qudits that became separable.
42
42
  * Frees memory incrementally — critical for search algorithms with many ancillas. */
43
- destroyProperty(prop: QuantumProperty): void;
43
+ destroyProperty(prop: QuantumProperty$1): void;
44
44
  /** Factor out any separable qudits across all shared states in this simulation.
45
45
  * Call after undo operations (e.g. i_swap reversal) that may have restored separability.
46
46
  * Separable qudits are split into independent states, reducing entanglement overhead. */
@@ -48,40 +48,40 @@ declare class QuantumSimulation {
48
48
  destroy(): void;
49
49
  isDestroyed(): boolean;
50
50
  }
51
- declare function cycle(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
52
- declare function shift(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
53
- declare function clock(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
54
- declare function hadamard(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
55
- declare function inverse_hadamard(prop: QuantumProperty, predicates?: Predicate[]): void;
56
- declare function swap(prop1: QuantumProperty, prop2: QuantumProperty, predicates?: Predicate[]): void;
57
- declare function i_swap(prop1: QuantumProperty, prop2: QuantumProperty, fraction: number, predicates?: Predicate[]): void;
51
+ declare function cycle(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
52
+ declare function shift(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
53
+ declare function clock(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
54
+ declare function hadamard(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
55
+ declare function inverse_hadamard(prop: QuantumProperty$1, predicates?: Predicate$1[]): void;
56
+ declare function swap(prop1: QuantumProperty$1, prop2: QuantumProperty$1, predicates?: Predicate$1[]): void;
57
+ declare function i_swap(prop1: QuantumProperty$1, prop2: QuantumProperty$1, fraction: number, predicates?: Predicate$1[]): void;
58
58
  /** Pauli X gate — alias for `shift` (C++ `qforge::x`, QuantumProperty.h).
59
59
  * NOTE: X is `shift` (decrement mod d), NOT `cycle` (increment mod d). The two
60
60
  * coincide only at dimension 2; for d > 2 they are inverses of each other. */
61
- declare function x(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
61
+ declare function x(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
62
62
  /** Pauli Z gate — alias for `clock` (C++ `qforge::z`, QuantumProperty.h). */
63
- declare function z(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
63
+ declare function z(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
64
64
  /** Pauli Y gate — qubit only. Composed as S · X · S† i.e.
65
65
  * `clock(-0.5); shift(fraction?); clock(0.5)` (C++ `qforge::y`, QuantumProperty.h).
66
66
  * @throws Error if the property dimension is not 2, mirroring the C++ guard. */
67
- declare function y(prop: QuantumProperty, fraction?: number, predicates?: Predicate[]): void;
68
- declare function reset(prop: QuantumProperty, currentValue: number): void;
69
- declare function phase_rotate(predicates: Predicate[], angle: number): void;
70
- declare function measure_properties(props: QuantumProperty[]): number[];
71
- declare function forced_measure_properties(props: QuantumProperty[], forcedValues: number[]): number[];
72
- declare function measure_predicate(predicates: Predicate[]): number;
67
+ declare function y(prop: QuantumProperty$1, fraction?: number, predicates?: Predicate$1[]): void;
68
+ declare function reset(prop: QuantumProperty$1, currentValue: number): void;
69
+ declare function phase_rotate(predicates: Predicate$1[], angle: number): void;
70
+ declare function measure_properties(props: QuantumProperty$1[]): number[];
71
+ declare function forced_measure_properties(props: QuantumProperty$1[], forcedValues: number[]): number[];
72
+ declare function measure_predicate(predicates: Predicate$1[]): number;
73
73
  /** Force a predicate measurement to a specific outcome.
74
74
  * If the forced value is impossible (zero probability), falls back to
75
75
  * stochastic measurement and returns the actual outcome instead of throwing. */
76
- declare function forced_measure_predicate(predicates: Predicate[], forcedValue: number): number;
76
+ declare function forced_measure_predicate(predicates: Predicate$1[], forcedValue: number): number;
77
77
  /** Get the probability that all predicates are simultaneously satisfied.
78
78
  * Read-only — does not collapse or modify quantum state. */
79
- declare function predicate_probability(predicates: Predicate[]): number;
80
- declare function probabilities(props: QuantumProperty[]): Array<{
79
+ declare function predicate_probability(predicates: Predicate$1[]): number;
80
+ declare function probabilities$1(props: QuantumProperty$1[]): Array<{
81
81
  probability: number;
82
82
  qudit_values: number[];
83
83
  }>;
84
- declare function reduced_density_matrix(props: QuantumProperty[]): Array<{
84
+ declare function reduced_density_matrix(props: QuantumProperty$1[]): Array<{
85
85
  row_values: number[];
86
86
  col_values: number[];
87
87
  value: {
@@ -94,13 +94,13 @@ type OpCode = 'cycle' | 'shift' | 'clock' | 'x' | 'z' | 'y' | 'hadamard' | 'inve
94
94
  /** A single gate operation descriptor for batch execution. */
95
95
  interface BatchOp {
96
96
  op: OpCode;
97
- target?: QuantumProperty;
98
- target2?: QuantumProperty;
97
+ target?: QuantumProperty$1;
98
+ target2?: QuantumProperty$1;
99
99
  /** Gate fraction. Omit for non-fractional (discrete permutation) variant. */
100
100
  fraction?: number;
101
101
  /** Rotation angle (phase_rotate only). */
102
102
  angle?: number;
103
- predicates?: Predicate[];
103
+ predicates?: Predicate$1[];
104
104
  }
105
105
  /** Result of a batch execution. */
106
106
  interface BatchResult {
@@ -175,7 +175,7 @@ type OpNum = typeof OP$1[keyof typeof OP$1];
175
175
  * @param tape Pre-encoded Float64Array of operations
176
176
  * @returns BatchResult
177
177
  */
178
- declare function executeBatchTape(properties: QuantumProperty[], tape: Float64Array): BatchResult;
178
+ declare function executeBatchTape(properties: QuantumProperty$1[], tape: Float64Array): BatchResult;
179
179
  declare class QuantumForge {
180
180
  /**
181
181
  * Initialize QuantumForge
@@ -188,7 +188,7 @@ declare class QuantumForge {
188
188
  * Check if QuantumForge is initialized
189
189
  */
190
190
  static isInitialized(): boolean;
191
- static createQuantumProperty(dimension: number): QuantumProperty;
191
+ static createQuantumProperty(dimension: number): QuantumProperty$1;
192
192
  static createSimulation(): QuantumSimulation;
193
193
  static getVersion(): string;
194
194
  static getMaxDimension(): number;
@@ -203,12 +203,8 @@ type __quantum_forge_api_mjs_BatchResult = BatchResult;
203
203
  type __quantum_forge_api_mjs_InitializeOptions = InitializeOptions;
204
204
  type __quantum_forge_api_mjs_OpCode = OpCode;
205
205
  type __quantum_forge_api_mjs_OpNum = OpNum;
206
- type __quantum_forge_api_mjs_Predicate = Predicate;
207
- declare const __quantum_forge_api_mjs_Predicate: typeof Predicate;
208
206
  type __quantum_forge_api_mjs_QuantumForge = QuantumForge;
209
207
  declare const __quantum_forge_api_mjs_QuantumForge: typeof QuantumForge;
210
- type __quantum_forge_api_mjs_QuantumProperty = QuantumProperty;
211
- declare const __quantum_forge_api_mjs_QuantumProperty: typeof QuantumProperty;
212
208
  type __quantum_forge_api_mjs_QuantumSimulation = QuantumSimulation;
213
209
  declare const __quantum_forge_api_mjs_QuantumSimulation: typeof QuantumSimulation;
214
210
  declare const __quantum_forge_api_mjs_clock: typeof clock;
@@ -224,7 +220,6 @@ declare const __quantum_forge_api_mjs_measure_predicate: typeof measure_predicat
224
220
  declare const __quantum_forge_api_mjs_measure_properties: typeof measure_properties;
225
221
  declare const __quantum_forge_api_mjs_phase_rotate: typeof phase_rotate;
226
222
  declare const __quantum_forge_api_mjs_predicate_probability: typeof predicate_probability;
227
- declare const __quantum_forge_api_mjs_probabilities: typeof probabilities;
228
223
  declare const __quantum_forge_api_mjs_reduced_density_matrix: typeof reduced_density_matrix;
229
224
  declare const __quantum_forge_api_mjs_reset: typeof reset;
230
225
  declare const __quantum_forge_api_mjs_shift: typeof shift;
@@ -233,23 +228,29 @@ declare const __quantum_forge_api_mjs_x: typeof x;
233
228
  declare const __quantum_forge_api_mjs_y: typeof y;
234
229
  declare const __quantum_forge_api_mjs_z: typeof z;
235
230
  declare namespace __quantum_forge_api_mjs {
236
- export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult, type __quantum_forge_api_mjs_InitializeOptions as InitializeOptions, OP$1 as OP, type __quantum_forge_api_mjs_OpCode as OpCode, type __quantum_forge_api_mjs_OpNum as OpNum, __quantum_forge_api_mjs_Predicate as Predicate, __quantum_forge_api_mjs_QuantumForge as QuantumForge, __quantum_forge_api_mjs_QuantumProperty as QuantumProperty, __quantum_forge_api_mjs_QuantumSimulation as QuantumSimulation, __quantum_forge_api_mjs_clock as clock, __quantum_forge_api_mjs_cycle as cycle, __quantum_forge_api_mjs_executeBatch as executeBatch, __quantum_forge_api_mjs_executeBatchTape as executeBatchTape, __quantum_forge_api_mjs_forced_measure_predicate as forced_measure_predicate, __quantum_forge_api_mjs_forced_measure_properties as forced_measure_properties, __quantum_forge_api_mjs_hadamard as hadamard, __quantum_forge_api_mjs_i_swap as i_swap, __quantum_forge_api_mjs_inverse_hadamard as inverse_hadamard, __quantum_forge_api_mjs_measure_predicate as measure_predicate, __quantum_forge_api_mjs_measure_properties as measure_properties, __quantum_forge_api_mjs_phase_rotate as phase_rotate, __quantum_forge_api_mjs_predicate_probability as predicate_probability, __quantum_forge_api_mjs_probabilities as probabilities, __quantum_forge_api_mjs_reduced_density_matrix as reduced_density_matrix, __quantum_forge_api_mjs_reset as reset, __quantum_forge_api_mjs_shift as shift, __quantum_forge_api_mjs_swap as swap, __quantum_forge_api_mjs_x as x, __quantum_forge_api_mjs_y as y, __quantum_forge_api_mjs_z as z };
231
+ export { type __quantum_forge_api_mjs_BatchOp as BatchOp, type __quantum_forge_api_mjs_BatchResult as BatchResult, type __quantum_forge_api_mjs_InitializeOptions as InitializeOptions, OP$1 as OP, type __quantum_forge_api_mjs_OpCode as OpCode, type __quantum_forge_api_mjs_OpNum as OpNum, Predicate$1 as Predicate, __quantum_forge_api_mjs_QuantumForge as QuantumForge, QuantumProperty$1 as QuantumProperty, __quantum_forge_api_mjs_QuantumSimulation as QuantumSimulation, __quantum_forge_api_mjs_clock as clock, __quantum_forge_api_mjs_cycle as cycle, __quantum_forge_api_mjs_executeBatch as executeBatch, __quantum_forge_api_mjs_executeBatchTape as executeBatchTape, __quantum_forge_api_mjs_forced_measure_predicate as forced_measure_predicate, __quantum_forge_api_mjs_forced_measure_properties as forced_measure_properties, __quantum_forge_api_mjs_hadamard as hadamard, __quantum_forge_api_mjs_i_swap as i_swap, __quantum_forge_api_mjs_inverse_hadamard as inverse_hadamard, __quantum_forge_api_mjs_measure_predicate as measure_predicate, __quantum_forge_api_mjs_measure_properties as measure_properties, __quantum_forge_api_mjs_phase_rotate as phase_rotate, __quantum_forge_api_mjs_predicate_probability as predicate_probability, probabilities$1 as probabilities, __quantum_forge_api_mjs_reduced_density_matrix as reduced_density_matrix, __quantum_forge_api_mjs_reset as reset, __quantum_forge_api_mjs_shift as shift, __quantum_forge_api_mjs_swap as swap, __quantum_forge_api_mjs_x as x, __quantum_forge_api_mjs_y as y, __quantum_forge_api_mjs_z as z };
237
232
  }
238
233
 
239
234
  /**
240
235
  * Set the base URL path where Quantum Forge WASM files are served.
241
236
  * Default is "/quantum-forge" which matches the Vite plugin's serve path.
242
- * Consumers using the Vite plugin don't need to call this.
237
+ * Consumers using the Vite plugin don't need to call this. In Node the default
238
+ * is this package's own dist/ directory, so a file URL is only needed when the
239
+ * WASM lives somewhere else.
243
240
  */
244
241
  declare function setWasmBasePath(path: string): void;
245
242
  /**
246
- * Select a named WASM build variant (e.g. "d7n10").
247
- * Sugar for `setWasmBasePath("/quantum-forge-{name}")`.
243
+ * Select a named WASM build variant (e.g. "qubit").
244
+ * In a page this loads from "/quantum-forge-{name}"; in Node it loads from
245
+ * this package's dist/quantum-forge-{name}/. Replaces any earlier
246
+ * setWasmBasePath() call.
248
247
  *
249
248
  * Must be called before `ensureLoaded()`. If the module is already loaded,
250
249
  * a warning is logged and the call is ignored.
251
250
  */
252
251
  declare function useQuantumForgeBuild(name: string): void;
252
+ /** The base path ensureLoaded() imports from, resolved at load time. */
253
+ declare function getWasmBasePath(): string;
253
254
  /**
254
255
  * Start loading the WASM module in the background.
255
256
  * Call this after the page has rendered (e.g., after DOMContentLoaded or initial paint).
@@ -300,6 +301,444 @@ declare function getAttribution(): string;
300
301
  */
301
302
  declare function registerServiceWorker(swPath?: string): Promise<ServiceWorkerRegistration | null>;
302
303
 
304
+ /**
305
+ * Quantum — one handle per quantum property.
306
+ *
307
+ * Declare a property by the values it can take, call gates on it as methods,
308
+ * and end its life with `dispose()` (or a `using` declaration). There is no
309
+ * manager and no `getModule()` in game code.
310
+ *
311
+ * ```typescript
312
+ * import { quantum, measure, ensureLoaded } from "quantum-forge/quantum";
313
+ *
314
+ * await ensureLoaded();
315
+ * const color = quantum(["red", "green", "blue"]); // a qutrit, starts "red"
316
+ * color.superpose(); // alias for hadamard()
317
+ * color.probability("green"); // 1/3, no collapse
318
+ * const c = color.measure(); // "red" | "green" | "blue"
319
+ *
320
+ * const alive = quantum([false, true]);
321
+ * const twin = quantum([false, true]);
322
+ * alive.superpose();
323
+ * twin.flip({ when: [alive.is(true)] }); // CNOT: the pair is now entangled
324
+ * measure(alive, twin); // [false, false] or [true, true]
325
+ * ```
326
+ *
327
+ * `dispose()` always measures the property first. What happens to the WASM
328
+ * property next depends on whether it still shares a state with others:
329
+ *
330
+ * - Alone in its state: it is reset to |0⟩ and kept in a private
331
+ * per-dimension cache, and the next `quantum()` at that dimension reuses it.
332
+ * - Still in a shared state with other qudits: it is destroyed, which factors
333
+ * it out of that state, and it is not cached. Reusing it would hand the next
334
+ * `quantum()` a qudit that still counts against the old state's size.
335
+ *
336
+ * Either way a disposed handle never grows anyone's tensor product.
337
+ */
338
+
339
+ declare global {
340
+ interface SymbolConstructor {
341
+ readonly dispose: unique symbol;
342
+ }
343
+ }
344
+ /** A value a quantum property can be declared with: a game word, a number or a boolean. */
345
+ type QuantumValue = string | number | boolean;
346
+ /** Options accepted by every gate method. */
347
+ interface GateOptions {
348
+ /**
349
+ * Predicates that condition the gate. The gate acts only on the part of the
350
+ * state where every predicate holds. A predicate on another property makes
351
+ * the gate an interaction, which entangles the two.
352
+ */
353
+ when?: QuantumPredicate[];
354
+ }
355
+ /**
356
+ * A condition on one property's value, built by `is()` or `isNot()`.
357
+ * Used in `{ when: [...] }` on gates and by the `*When` free functions.
358
+ */
359
+ interface QuantumPredicate<V extends QuantumValue = QuantumValue> {
360
+ /** The property this predicate tests. */
361
+ readonly property: Quantum<V>;
362
+ /** The declared value being tested. */
363
+ readonly value: V;
364
+ /** The basis index of `value`. */
365
+ readonly index: number;
366
+ /** True for `is()`, false for `isNot()`. */
367
+ readonly isEqual: boolean;
368
+ /** @internal The WASM predicate. */
369
+ readonly raw: Predicate$1;
370
+ }
371
+ /** A predicate as it appears in observer events: handle id, basis index, polarity. */
372
+ interface SerializedQuantumPredicate {
373
+ id: number;
374
+ index: number;
375
+ isEqual: boolean;
376
+ }
377
+ /**
378
+ * A gate that ran, as reported to observers.
379
+ *
380
+ * `op` is always the physics operation in the WASM `OpCode` spelling
381
+ * (`"hadamard"`, `"inverse_hadamard"`, `"i_swap"`, ...). Aliases report as the
382
+ * operation they alias: `superpose()` reports `"hadamard"`, `flip()` and
383
+ * `next()` report `"cycle"`, and so on. `fraction` is the value sent to WASM,
384
+ * and is `undefined` when the discrete gate ran.
385
+ */
386
+ type QuantumGateEvent = {
387
+ op: "hadamard" | "cycle" | "shift" | "clock" | "x" | "y" | "z";
388
+ target: number;
389
+ fraction: number | undefined;
390
+ predicates: SerializedQuantumPredicate[];
391
+ } | {
392
+ op: "inverse_hadamard";
393
+ target: number;
394
+ predicates: SerializedQuantumPredicate[];
395
+ } | {
396
+ op: "swap";
397
+ targets: [number, number];
398
+ predicates: SerializedQuantumPredicate[];
399
+ } | {
400
+ op: "i_swap";
401
+ targets: [number, number];
402
+ fraction: number;
403
+ predicates: SerializedQuantumPredicate[];
404
+ } | {
405
+ op: "phase_rotate";
406
+ angle: number;
407
+ predicates: SerializedQuantumPredicate[];
408
+ };
409
+ /**
410
+ * A measurement that ran, as reported to observers. Outcomes are basis
411
+ * indices; predicate outcomes are 1 (all predicates held) or 0.
412
+ *
413
+ * - `"measure"`: `Quantum.measure()` and the free `measure()`.
414
+ * - `"forced_measure"`: `Quantum.forcedMeasure()` and the free `forcedMeasure()`.
415
+ * - `"measure_predicate"`: `measureWhen()`.
416
+ * - `"forced_measure_predicate"`: `forcedMeasureWhen()`.
417
+ *
418
+ * In both forced events the outcome always equals `forced`: forcing an
419
+ * outcome with zero probability throws and reports no event.
420
+ */
421
+ type QuantumMeasureEvent = {
422
+ op: "measure";
423
+ targets: number[];
424
+ outcomes: number[];
425
+ } | {
426
+ op: "forced_measure";
427
+ targets: number[];
428
+ forced: number[];
429
+ outcomes: number[];
430
+ } | {
431
+ op: "measure_predicate";
432
+ predicates: SerializedQuantumPredicate[];
433
+ outcome: number;
434
+ } | {
435
+ op: "forced_measure_predicate";
436
+ predicates: SerializedQuantumPredicate[];
437
+ forced: number;
438
+ outcome: number;
439
+ };
440
+ /**
441
+ * Receives every quantum operation after it succeeds in WASM. Attach with
442
+ * `observeQuantum()`. The measurement `dispose()` makes internally is not
443
+ * reported through `onMeasure`; `onDispose` carries its outcome instead.
444
+ *
445
+ * Delivery rules:
446
+ * - An observer that throws does not stop the others from seeing the event,
447
+ * and the error never reaches the code that ran the operation. It is
448
+ * reported with `reportError()` where the runtime has it, else `console.error`.
449
+ * - Events arrive in execution order. An operation run from inside an
450
+ * observer callback is queued, and its event is delivered once the current
451
+ * event has reached every observer.
452
+ * - Each event goes to the observers attached when the operation ran. An
453
+ * observer attached or detached from inside a callback changes who sees
454
+ * later operations, not operations already queued.
455
+ * - Gate and measurement events are deeply frozen, and every observer gets
456
+ * the same object. Copy before changing one. `onCreate` and `onDispose`
457
+ * receive the live handle, which is not frozen.
458
+ */
459
+ interface QuantumObserver {
460
+ /** A handle was created by `quantum()`. */
461
+ onCreate?(prop: Quantum<any>): void;
462
+ /** A gate ran. */
463
+ onGate?(event: QuantumGateEvent): void;
464
+ /** A measurement ran. */
465
+ onMeasure?(event: QuantumMeasureEvent): void;
466
+ /** A handle was disposed; `value` is the declared value it measured to. */
467
+ onDispose?(prop: Quantum<any>, value: QuantumValue): void;
468
+ }
469
+ /**
470
+ * Marker present on every `Quantum` instance as an own, non-enumerable,
471
+ * read-only data property with value `true`. The engine uses it to find
472
+ * handles on an entity without walking objects it does not understand. It is
473
+ * a registry symbol so two copies of core still recognize each other's
474
+ * handles, and non-enumerable so a spread copy `{ ...handle }` is not a handle.
475
+ */
476
+ declare const QUANTUM_HANDLE: unique symbol;
477
+ /**
478
+ * One quantum property, declared by its values. Create with `quantum()`; the
479
+ * constructor is private and throws a TypeError when called directly.
480
+ *
481
+ * Every gate returns `this` so calls chain. A gate on one property is
482
+ * evolution; a gate that takes a second property, or whose `when` predicate
483
+ * reads another property, is an interaction and leaves the two entangled.
484
+ *
485
+ * Gates that take a fraction take it as an optional leading number: omit it,
486
+ * or pass exactly 1, for the discrete gate. Options may follow the fraction or
487
+ * stand in its place: `b.flip({ when: [a.is(true)] })` and
488
+ * `b.flip(0.5, { when: [a.is(true)] })` both work.
489
+ *
490
+ * Wherever a value is accepted, pass either a declared value or its basis
491
+ * index. A declared value wins when a number could be both.
492
+ *
493
+ * A bare `Quantum` means `Quantum<QuantumValue>`, so a field typed `Quantum`
494
+ * holds any handle, named or numeric.
495
+ */
496
+ declare class Quantum<V extends QuantumValue = QuantumValue> {
497
+ #private;
498
+ /**
499
+ * Marker for `isQuantum()`. Always `true`. Defined in the constructor as a
500
+ * non-enumerable data property, so it survives neither a spread nor
501
+ * `Object.assign({}, handle)`.
502
+ */
503
+ readonly [QUANTUM_HANDLE]: true;
504
+ /** Unique per `quantum()` call, increasing, never reused. */
505
+ readonly id: number;
506
+ /** Declared values in basis order. Index 0 is the starting value. */
507
+ readonly values: readonly V[];
508
+ /** Number of declared values. */
509
+ readonly dimension: number;
510
+ private readonly _raw;
511
+ /**
512
+ * The WASM property behind this handle, for the batch API (`executeBatch`,
513
+ * `executeBatchTape`), which has no handle-level form yet.
514
+ *
515
+ * Caveats:
516
+ * - Operations run through `.raw` are invisible to observers, so a
517
+ * `QuantumRecorder` log will not contain them and a replay will diverge.
518
+ * - Never call `destroy()` on it. The handle still owns it, and its
519
+ * `dispose()` would then fail.
520
+ * - It is valid only while the handle is live. After `dispose()` it may back
521
+ * a different handle, so this getter throws.
522
+ * @throws Error once the handle is disposed.
523
+ */
524
+ get raw(): QuantumProperty$1;
525
+ private constructor();
526
+ /** True once `dispose()` has run. Every other call then throws. */
527
+ get disposed(): boolean;
528
+ /**
529
+ * Hadamard gate: spread the property evenly across every value.
530
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
531
+ */
532
+ hadamard(fraction?: number | GateOptions, opts?: GateOptions): this;
533
+ /** Inverse Hadamard gate. Undoes `hadamard()`. */
534
+ inverseHadamard(opts?: GateOptions): this;
535
+ /**
536
+ * Cycle gate: move to the next value, wrapping (index + 1 mod dimension).
537
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
538
+ */
539
+ cycle(fraction?: number | GateOptions, opts?: GateOptions): this;
540
+ /**
541
+ * Shift gate: move to the previous value, wrapping (index - 1 mod dimension).
542
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
543
+ */
544
+ shift(fraction?: number | GateOptions, opts?: GateOptions): this;
545
+ /**
546
+ * Clock gate: rotate the phase of each value by its index.
547
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
548
+ */
549
+ clock(fraction?: number | GateOptions, opts?: GateOptions): this;
550
+ /**
551
+ * Pauli X gate. Same as `shift()`; at dimension 2 also the same as `cycle()`.
552
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
553
+ */
554
+ x(fraction?: number | GateOptions, opts?: GateOptions): this;
555
+ /**
556
+ * Pauli Y gate. Dimension 2 only; throws on any other dimension.
557
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
558
+ */
559
+ y(fraction?: number | GateOptions, opts?: GateOptions): this;
560
+ /**
561
+ * Pauli Z gate. Same as `clock()`.
562
+ * @param fraction Omit (or pass exactly 1) for the discrete gate; any other number runs the fractional gate.
563
+ */
564
+ z(fraction?: number | GateOptions, opts?: GateOptions): this;
565
+ /**
566
+ * Alias for `hadamard()`.
567
+ * Spread the property evenly across every value.
568
+ */
569
+ superpose(fraction?: number | GateOptions, opts?: GateOptions): this;
570
+ /**
571
+ * Alias for `cycle()`.
572
+ * Move to the next value, wrapping. `next(0.5)` is half a step.
573
+ */
574
+ next(fraction?: number | GateOptions, opts?: GateOptions): this;
575
+ /**
576
+ * Alias for `shift()`.
577
+ * Move to the previous value, wrapping.
578
+ */
579
+ previous(fraction?: number | GateOptions, opts?: GateOptions): this;
580
+ /**
581
+ * Alias for `clock()`.
582
+ * Turn the phase dial.
583
+ */
584
+ phase(fraction?: number | GateOptions, opts?: GateOptions): this;
585
+ /**
586
+ * Alias for `cycle()`, restricted to dimension 2.
587
+ * Swap the two values. `flip(0.5)` is the square root of NOT. Throws on any
588
+ * other dimension.
589
+ */
590
+ flip(fraction?: number | GateOptions, opts?: GateOptions): this;
591
+ /**
592
+ * Swap the states of this property and `other`.
593
+ * @throws Error when `other` is this property, or has a different number of values.
594
+ */
595
+ swap(other: Quantum<any>, opts?: GateOptions): this;
596
+ /**
597
+ * iSwap gate between this property and `other`. `iSwap(other, 0.5)` on
598
+ * a pair where one is set leaves them entangled.
599
+ * @param fraction Required; 1 is a full iSwap.
600
+ * @throws Error when `other` is this property, or has a different number of values.
601
+ */
602
+ iSwap(other: Quantum<any>, fraction: number, opts?: GateOptions): this;
603
+ /**
604
+ * A predicate that holds when this property equals `value`.
605
+ * @param value A declared value or its basis index.
606
+ * @throws RangeError when `value` is neither.
607
+ */
608
+ is(value: V | number): QuantumPredicate<V>;
609
+ /**
610
+ * A predicate that holds when this property does not equal `value`.
611
+ * @param value A declared value or its basis index.
612
+ * @throws RangeError when `value` is neither.
613
+ */
614
+ isNot(value: V | number): QuantumPredicate<V>;
615
+ /** Measure this property, collapsing it and every entangled partner. Returns the declared value. */
616
+ measure(): V;
617
+ /**
618
+ * Measure this property with the outcome forced to `value`. For replays and tests.
619
+ * @param value A declared value or its basis index.
620
+ * @throws Error when `value` has zero probability in the current state. The
621
+ * state is left unchanged.
622
+ */
623
+ forcedMeasure(value: V | number): V;
624
+ /**
625
+ * Probability that a measurement would give `value`. Does not collapse the state.
626
+ * @param value A declared value or its basis index.
627
+ */
628
+ probability(value: V | number): number;
629
+ /** Probability of every declared value, in basis order. Does not collapse the state. */
630
+ probabilities(): Array<{
631
+ value: V;
632
+ probability: number;
633
+ }>;
634
+ /**
635
+ * End this property's life. Measures it first, which collapses any
636
+ * entangled partners. Then:
637
+ *
638
+ * - If it is alone in its state, it is reset to its first value and its
639
+ * WASM property goes to a private cache for the next `quantum()` at this
640
+ * dimension.
641
+ * - If it still shares a state with other qudits, its WASM property is
642
+ * destroyed, which factors it out of that state, and it is not cached.
643
+ * A partner left on its own shrinks back to one qudit.
644
+ *
645
+ * Calling it again does nothing. Works on a frozen handle.
646
+ */
647
+ dispose(): void;
648
+ /** Same as `dispose()`, so a `using` declaration disposes the handle at scope exit. */
649
+ [Symbol.dispose](): void;
650
+ /** Number of qudits in the shared state this property belongs to. */
651
+ numActiveQudits(): number;
652
+ /** Number of basis amplitudes in the shared state vector. */
653
+ stateVectorSize(): number;
654
+ private _predicate;
655
+ /** Checks shared by swap() and iSwap(). Returns the WASM predicates. */
656
+ private _pair;
657
+ private _gate;
658
+ }
659
+ /**
660
+ * Create a quantum property declared by its values. The dimension is the
661
+ * number of values, and the property starts at the first one.
662
+ *
663
+ * @example
664
+ * const color = quantum(["red", "green", "blue"]);
665
+ * const alive = quantum([false, true]);
666
+ * @throws RangeError when `values` has fewer than 2 entries or a non-finite number.
667
+ * @throws Error when `values` has duplicates, or more entries than the loaded build's maximum dimension.
668
+ */
669
+ declare function quantum<V extends QuantumValue>(values: readonly V[]): Quantum<V>;
670
+ /**
671
+ * Create a quantum property with `dimension` values `0..dimension-1`, starting at 0.
672
+ * @throws RangeError when `dimension` is not an integer, or is less than 2.
673
+ * @throws Error when `dimension` exceeds the loaded build's maximum dimension.
674
+ */
675
+ declare function quantum(dimension: number): Quantum<number>;
676
+ /**
677
+ * True when `x` is a `Quantum` handle: it has an own `QUANTUM_HANDLE` data
678
+ * property whose value is `true`. The marker is read through its descriptor,
679
+ * so a getter under that key is never invoked, and a spread copy of a handle
680
+ * (which drops the non-enumerable marker) is not a handle.
681
+ */
682
+ declare function isQuantum(x: unknown): x is Quantum<any>;
683
+ /**
684
+ * Destroy every cached WASM property and empty the cache. Live handles are not
685
+ * affected. Meant for tests and for freeing memory between scenes.
686
+ */
687
+ declare function clearQuantumCache(): void;
688
+ /**
689
+ * Attach an observer that sees every quantum operation after it succeeds.
690
+ * @returns A function that detaches the observer.
691
+ */
692
+ declare function observeQuantum(observer: QuantumObserver): () => void;
693
+ /**
694
+ * Measure several properties together. Returns each one's declared value, in argument order.
695
+ * @example const [a, b] = measure(alive, twin);
696
+ */
697
+ declare function measure(...props: Quantum<any>[]): QuantumValue[];
698
+ /**
699
+ * Measure several properties together with each outcome forced. For replays and tests.
700
+ * @param values One declared value or basis index per property.
701
+ * @throws Error when the combination of values has zero probability in the
702
+ * current state. The state is left unchanged.
703
+ */
704
+ declare function forcedMeasure(props: Quantum<any>[], values: QuantumValue[]): QuantumValue[];
705
+ /**
706
+ * Joint probabilities over several properties. Each entry lists one declared
707
+ * value per property, in argument order. Does not collapse the state.
708
+ */
709
+ declare function probabilities(...props: Quantum<any>[]): Array<{
710
+ values: QuantumValue[];
711
+ probability: number;
712
+ }>;
713
+ /**
714
+ * Reduced density matrix over several properties. Rows and columns are
715
+ * labelled with one declared value per property. Does not collapse the state.
716
+ */
717
+ declare function densityMatrix(...props: Quantum<any>[]): Array<{
718
+ row: QuantumValue[];
719
+ col: QuantumValue[];
720
+ real: number;
721
+ imag: number;
722
+ }>;
723
+ /** Measure whether every predicate holds, collapsing the state to agree. */
724
+ declare function measureWhen(preds: QuantumPredicate[]): boolean;
725
+ /**
726
+ * Measure whether every predicate holds, with the outcome forced. For replays
727
+ * and tests. Returns `outcome`.
728
+ * @throws Error when the forced outcome has zero probability in the current
729
+ * state. The state is left unchanged.
730
+ */
731
+ declare function forcedMeasureWhen(preds: QuantumPredicate[], outcome: boolean): boolean;
732
+ /** Probability that every predicate holds at once. Does not collapse the state. */
733
+ declare function probabilityWhen(preds: QuantumPredicate[]): number;
734
+ /**
735
+ * Rotate the phase of the part of the state where every predicate holds by `angle` radians.
736
+ * @example phaseRotate(Math.PI, { when: [a.is(1), b.is(1)] });
737
+ */
738
+ declare function phaseRotate(angle: number, opts: {
739
+ when: QuantumPredicate[];
740
+ }): void;
741
+
303
742
  /**
304
743
  * QuantumPropertyManager — manages quantum property lifecycles.
305
744
  *
@@ -310,20 +749,26 @@ declare function registerServiceWorker(swPath?: string): Promise<ServiceWorkerRe
310
749
  * Property pooling is critical: measured/removed properties are recycled
311
750
  * to avoid growing the tensor product and hitting qudit limits.
312
751
  *
313
- * For opt-in operation recording, attach a QuantumRecorder via setRecorder().
752
+ * For opt-in operation recording, attach a LegacyQuantumRecorder via setRecorder().
314
753
  */
315
754
 
316
755
  interface PredicateSpec$1 {
317
- property: QuantumProperty;
756
+ property: QuantumProperty$1;
318
757
  value: number;
319
758
  isEqual: boolean;
320
759
  }
321
760
  interface QuantumRecorderHook {
322
- onAcquire?(prop: QuantumProperty): void;
323
- onRelease?(prop: QuantumProperty, value: number): void;
324
- onSetProperty?(id: string, prop: QuantumProperty): void;
761
+ onAcquire?(prop: QuantumProperty$1): void;
762
+ onRelease?(prop: QuantumProperty$1, value: number): void;
763
+ onSetProperty?(id: string, prop: QuantumProperty$1): void;
325
764
  onDeleteProperty?(id: string): void;
326
765
  }
766
+ /**
767
+ * Pools raw WASM properties behind string ids.
768
+ *
769
+ * @deprecated Use `quantum()` handles from the same entry point; see
770
+ * docs/QUANTUM_INTEGRATION.md. Removed in 4.0.
771
+ */
327
772
  declare class QuantumPropertyManager {
328
773
  readonly dimension: number;
329
774
  private properties;
@@ -342,15 +787,15 @@ declare class QuantumPropertyManager {
342
787
  * Get a property at |0⟩ — reuses a pooled one if available,
343
788
  * otherwise creates a fresh standalone property.
344
789
  */
345
- acquireProperty(): QuantumProperty;
790
+ acquireProperty(): QuantumProperty$1;
346
791
  /**
347
792
  * Return a property to the pool after resetting it to |0⟩.
348
793
  * Uses the `reset` primitive which applies non-fractional cycles —
349
794
  * correct for all dimensions (no superposition created).
350
795
  */
351
- releaseProperty(prop: QuantumProperty, measuredValue: number): void;
352
- setProperty(id: string, prop: QuantumProperty): void;
353
- getProperty(id: string): QuantumProperty | undefined;
796
+ releaseProperty(prop: QuantumProperty$1, measuredValue: number): void;
797
+ setProperty(id: string, prop: QuantumProperty$1): void;
798
+ getProperty(id: string): QuantumProperty$1 | undefined;
354
799
  deleteProperty(id: string): void;
355
800
  hasProperty(id: string): boolean;
356
801
  /**
@@ -362,12 +807,173 @@ declare class QuantumPropertyManager {
362
807
  get size(): number;
363
808
  get poolSize(): number;
364
809
  getModule(): ReturnType<typeof getModule>;
365
- /** @internal — used by QuantumRecorder.replayLog() to restore pool state. */
366
- _setPool(pool: QuantumProperty[]): void;
367
- /** @internal — used by QuantumRecorder to enumerate live handles. */
368
- _getProperties(): Map<string, QuantumProperty>;
369
- /** @internal — used by QuantumRecorder to enumerate pool handles. */
370
- _getPool(): QuantumProperty[];
810
+ /** @internal — used by LegacyQuantumRecorder.replayLog() to restore pool state. */
811
+ _setPool(pool: QuantumProperty$1[]): void;
812
+ /** @internal — used by LegacyQuantumRecorder to enumerate live handles. */
813
+ _getProperties(): Map<string, QuantumProperty$1>;
814
+ /** @internal — used by LegacyQuantumRecorder to enumerate pool handles. */
815
+ _getPool(): QuantumProperty$1[];
816
+ }
817
+
818
+ /**
819
+ * QuantumRecorder — opt-in recording and replay of `quantum()` handles.
820
+ *
821
+ * The recorder attaches through `observeQuantum()`, so every gate, measurement,
822
+ * creation and disposal is logged without the game calling anything extra.
823
+ * Entries name handles by their `id` and values by basis index, and the log is
824
+ * plain JSON: `{ "version": 1, "entries": [...] }`.
825
+ *
826
+ * ```typescript
827
+ * const recorder = new QuantumRecorder();
828
+ * recorder.startRecording();
829
+ * const a = quantum([false, true]);
830
+ * const b = quantum([false, true]);
831
+ * a.superpose();
832
+ * b.flip({ when: [a.is(true)] });
833
+ * measure(a, b);
834
+ * const text = QuantumRecorder.serialize(recorder.stopRecording());
835
+ *
836
+ * const handles = QuantumRecorder.replay(QuantumRecorder.deserialize(text));
837
+ * handles.get(a.id); // the replayed `a`, collapsed to the recorded outcome
838
+ * ```
839
+ */
840
+
841
+ type FractionalGateOp = "hadamard" | "cycle" | "shift" | "clock" | "x" | "y" | "z";
842
+ /**
843
+ * One recorded operation. Handles are named by `id`, values by basis index.
844
+ *
845
+ * Gate and measurement entries mirror `QuantumGateEvent` and
846
+ * `QuantumMeasureEvent` one to one, with op names in the WASM spelling
847
+ * (`"hadamard"`, `"cycle"`, `"i_swap"`, ...). A gate's `fraction` is omitted
848
+ * when the discrete gate ran.
849
+ */
850
+ type QuantumLogEntry = {
851
+ op: "create";
852
+ id: number;
853
+ values: QuantumValue[];
854
+ } | {
855
+ op: "dispose";
856
+ id: number;
857
+ outcome: number;
858
+ } | {
859
+ op: FractionalGateOp;
860
+ target: number;
861
+ fraction?: number;
862
+ predicates: SerializedQuantumPredicate[];
863
+ } | {
864
+ op: "inverse_hadamard";
865
+ target: number;
866
+ predicates: SerializedQuantumPredicate[];
867
+ } | {
868
+ op: "swap";
869
+ targets: [number, number];
870
+ predicates: SerializedQuantumPredicate[];
871
+ } | {
872
+ op: "i_swap";
873
+ targets: [number, number];
874
+ fraction: number;
875
+ predicates: SerializedQuantumPredicate[];
876
+ } | {
877
+ op: "phase_rotate";
878
+ angle: number;
879
+ predicates: SerializedQuantumPredicate[];
880
+ } | {
881
+ op: "measure";
882
+ targets: number[];
883
+ outcomes: number[];
884
+ } | {
885
+ op: "forced_measure";
886
+ targets: number[];
887
+ forced: number[];
888
+ outcomes: number[];
889
+ } | {
890
+ op: "measure_predicate";
891
+ predicates: SerializedQuantumPredicate[];
892
+ outcome: number;
893
+ } | {
894
+ op: "forced_measure_predicate";
895
+ predicates: SerializedQuantumPredicate[];
896
+ forced: number;
897
+ outcome: number;
898
+ };
899
+ /** The log format version `serialize()` writes and `deserialize()` accepts. */
900
+ declare const LOG_VERSION = 1;
901
+ /**
902
+ * A recorded session: `{ version: 1, entries: [...] }`. `getLog()`,
903
+ * `stopRecording()` and `deserialize()` return this shape, and `serialize()`
904
+ * and `replay()` take it.
905
+ *
906
+ * `untrackedIds` is present only when the recording touched handles created
907
+ * before `startRecording()`. Such a log cannot be replayed: `replay()` throws.
908
+ */
909
+ interface QuantumLog {
910
+ version: typeof LOG_VERSION;
911
+ entries: QuantumLogEntry[];
912
+ /** Ids of handles the log references but never creates, in ascending order. */
913
+ untrackedIds?: number[];
914
+ }
915
+ /**
916
+ * Records every operation on `quantum()` handles into a JSON-safe log, and
917
+ * replays a log into fresh handles with the same state.
918
+ *
919
+ * Start recording before creating the handles you want replayed. When a
920
+ * recorded operation touches a handle created before `startRecording()`, the
921
+ * recorder warns once per handle through `console.warn`, keeps recording, and
922
+ * lists the handle's id in the log's `untrackedIds`. `replay()` refuses such a
923
+ * log.
924
+ *
925
+ * Replay runs every measurement as its forced variant with the recorded
926
+ * outcomes, so the replayed state matches the recorded one. A recorder that is
927
+ * running during a replay records what the replay did: the fresh handles'
928
+ * `create` entries and the forced measurements. So "load a save, keep
929
+ * recording" yields a log that replays on its own.
930
+ */
931
+ declare class QuantumRecorder {
932
+ private _entries;
933
+ private _seen;
934
+ private _untracked;
935
+ private _detach;
936
+ /**
937
+ * @throws TypeError when given any argument. The 2.x recorder took a
938
+ * `QuantumPropertyManager`; that one is now `LegacyQuantumRecorder`.
939
+ */
940
+ constructor(...args: []);
941
+ /** Begin recording. Clears the log. Calling it while recording restarts with an empty log. */
942
+ startRecording(): void;
943
+ /** Note created ids, and warn the first time an entry touches a handle this recording never saw created. */
944
+ private _track;
945
+ /**
946
+ * Stop recording and return the log, `{ version: 1, entries }`. The log
947
+ * carries `untrackedIds` when it touched handles created before recording.
948
+ */
949
+ stopRecording(): QuantumLog;
950
+ /** True between `startRecording()` and `stopRecording()`. */
951
+ isRecording(): boolean;
952
+ /** A copy of the log so far, `{ version: 1, entries }`. Works while recording. */
953
+ getLog(): QuantumLog;
954
+ /**
955
+ * Replay a log into new handles. Each `create` makes a fresh handle with a
956
+ * new id; the returned map is keyed by the id in the log. Handles the log
957
+ * disposes are removed from the map, so it holds the handles still live at
958
+ * the end of the log.
959
+ *
960
+ * The log is validated first, as `deserialize()` does. A recorder running
961
+ * during the replay records it (see the class docs); the log passed in is
962
+ * never modified.
963
+ *
964
+ * @throws Error when the log is malformed, lists `untrackedIds`, or an entry
965
+ * references an id with no earlier `create` entry. No handle survives a throw.
966
+ */
967
+ static replay(log: QuantumLog): Map<number, Quantum<any>>;
968
+ /** Serialize a log to JSON: `{ "version": 1, "entries": [...] }`. */
969
+ static serialize(log: QuantumLog): string;
970
+ /**
971
+ * Parse a log serialized by `serialize()`.
972
+ * @throws Error when the text is not JSON, the version is missing or
973
+ * unsupported, or any entry is malformed or names a basis index outside its
974
+ * handle's declared values.
975
+ */
976
+ static deserialize(text: string): QuantumLog;
371
977
  }
372
978
 
373
979
  /**
@@ -378,11 +984,13 @@ declare class QuantumPropertyManager {
378
984
  * handle values. On replay, `forced_measure_properties` reproduces the
379
985
  * exact measurement outcomes, yielding identical quantum state.
380
986
  */
987
+ /** @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0. */
381
988
  interface SerializedPredicate {
382
989
  propertyIndex: number;
383
990
  value: number;
384
991
  isEqual: boolean;
385
992
  }
993
+ /** @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0. */
386
994
  type QuantumOperation = {
387
995
  op: "acquire";
388
996
  index: number;
@@ -456,7 +1064,9 @@ type QuantumOperation = {
456
1064
  };
457
1065
 
458
1066
  /**
459
- * QuantumRecorder — opt-in recording and replay of quantum operations.
1067
+ * LegacyQuantumRecorder — opt-in recording and replay of quantum operations
1068
+ * for QuantumPropertyManager. Superseded by QuantumRecorder, which records
1069
+ * `quantum()` handles.
460
1070
  *
461
1071
  * Attach to a QuantumPropertyManager via `manager.setRecorder(recorder)`.
462
1072
  * When recording is active, lifecycle hooks log every state-mutating
@@ -468,25 +1078,30 @@ type QuantumOperation = {
468
1078
  */
469
1079
 
470
1080
  interface PredicateSpec {
471
- property: QuantumProperty;
1081
+ property: QuantumProperty$1;
472
1082
  value: number;
473
1083
  isEqual: boolean;
474
1084
  }
475
- declare class QuantumRecorder implements QuantumRecorderHook {
1085
+ /**
1086
+ * Records and replays operations on a QuantumPropertyManager's pooled properties.
1087
+ *
1088
+ * @deprecated Use QuantumRecorder with quantum() handles. Removed in 4.0.
1089
+ */
1090
+ declare class LegacyQuantumRecorder implements QuantumRecorderHook {
476
1091
  private _recording;
477
1092
  private _log;
478
1093
  private _handleToIndex;
479
1094
  private _nextIndex;
480
1095
  private readonly _manager;
481
1096
  constructor(manager: QuantumPropertyManager);
482
- onAcquire(prop: QuantumProperty): void;
483
- onRelease(prop: QuantumProperty, value: number): void;
484
- onSetProperty(id: string, prop: QuantumProperty): void;
1097
+ onAcquire(prop: QuantumProperty$1): void;
1098
+ onRelease(prop: QuantumProperty$1, value: number): void;
1099
+ onSetProperty(id: string, prop: QuantumProperty$1): void;
485
1100
  onDeleteProperty(id: string): void;
486
1101
  /**
487
1102
  * Build WASM predicate objects from PredicateSpec array.
488
1103
  */
489
- buildWasmPredicates(specs: PredicateSpec[]): Predicate[];
1104
+ buildWasmPredicates(specs: PredicateSpec[]): Predicate$1[];
490
1105
  /**
491
1106
  * Serialize predicates for the operation log.
492
1107
  */
@@ -499,7 +1114,7 @@ declare class QuantumRecorder implements QuantumRecorderHook {
499
1114
  /**
500
1115
  * Get the recorded index for a property handle.
501
1116
  */
502
- getIndex(prop: QuantumProperty): number | undefined;
1117
+ getIndex(prop: QuantumProperty$1): number | undefined;
503
1118
  /** Begin recording quantum operations. Resets any existing log. */
504
1119
  startRecording(): void;
505
1120
  /** Stop recording and return the captured log. */
@@ -517,6 +1132,10 @@ declare class QuantumRecorder implements QuantumRecorderHook {
517
1132
  private _replayPredicates;
518
1133
  }
519
1134
 
1135
+ /** The WASM property `Quantum.raw` returns, for the batch API (`executeBatch`, `executeBatchTape`). */
1136
+ type QuantumProperty = QuantumProperty$1;
1137
+ /** The WASM predicate behind `QuantumPredicate.raw`. */
1138
+ type Predicate = Predicate$1;
520
1139
  /** Numeric opcode constants for tape encoding. Matches C++ OpCode enum. */
521
1140
  declare const OP: {
522
1141
  readonly CYCLE: 0;
@@ -533,4 +1152,4 @@ declare const OP: {
533
1152
  readonly ROTATE_BASIS_PAIR: 11;
534
1153
  };
535
1154
 
536
- export { type BatchOp, type BatchResult, OP, type OpCode, type OpNum, type PredicateSpec$1 as PredicateSpec, type QuantumOperation, QuantumPropertyManager, QuantumRecorder, type QuantumRecorderHook, type SerializedPredicate, ensureLoaded, getAttribution, getMaxDimension, getMaxQudits, getMaxStateSize, getModule, getQuantumForge, getVersion, getWasmMemoryBytes, isReady, registerServiceWorker, setWasmBasePath, startBackgroundLoad, useQuantumForgeBuild };
1155
+ export { type BatchOp, type BatchResult, type GateOptions, LegacyQuantumRecorder, OP, type OpCode, type OpNum, type Predicate, type PredicateSpec$1 as PredicateSpec, QUANTUM_HANDLE, Quantum, type QuantumGateEvent, type QuantumLog, type QuantumLogEntry, type QuantumMeasureEvent, type QuantumObserver, type QuantumOperation, type QuantumPredicate, type QuantumProperty, QuantumPropertyManager, QuantumRecorder, type QuantumRecorderHook, type QuantumValue, type SerializedPredicate, type SerializedQuantumPredicate, clearQuantumCache, densityMatrix, ensureLoaded, forcedMeasure, forcedMeasureWhen, getAttribution, getMaxDimension, getMaxQudits, getMaxStateSize, getModule, getQuantumForge, getVersion, getWasmBasePath, getWasmMemoryBytes, isQuantum, isReady, measure, measureWhen, observeQuantum, phaseRotate, probabilities, probabilityWhen, quantum, registerServiceWorker, setWasmBasePath, startBackgroundLoad, useQuantumForgeBuild };