@cnstra/types 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  type TCNSAfferentPath = {
2
+ readonly index: number;
2
3
  parentAfferentPath?: TCNSAfferentPath;
3
4
  };
4
5
 
@@ -8,6 +9,7 @@ type TCNSSignal<TCollateral extends ICNSCollateral<unknown>> = {
8
9
  };
9
10
 
10
11
  interface ICNSCollateral<TPayload> {
12
+ readonly index: number;
11
13
  createSignal(): TCNSSignal<ICNSCollateral<TPayload>>;
12
14
  createSignal(payload: TPayload): TCNSSignal<ICNSCollateral<TPayload>>;
13
15
  }
@@ -37,48 +39,53 @@ type TCNSAxon<TCollaterals extends Record<string, ICNSCollateral<unknown>> = Rec
37
39
  [K in keyof TCollaterals]: TCollaterals[K];
38
40
  };
39
41
 
42
+ /**
43
+ * A context store: data attached to something the engine is running, in
44
+ * compartments.
45
+ *
46
+ * There are two of them, same shape, different life — the run's
47
+ * (`stimulationContext`, one per stimulation) and the activation's
48
+ * (`activationContext`, one per neuron activation). Same shape on purpose: they
49
+ * are used the same way, serialized the same way, and read the same way.
50
+ *
51
+ * A key is a namespace its writer owns, by convention the package name
52
+ * (`'@cnstra/persist-otel'`), so an integration and your own code cannot
53
+ * overwrite each other. A caller who owns their whole run does not need a prefix.
54
+ *
55
+ * Plain object with string keys rather than a `Map` because this crosses a
56
+ * process boundary: `JSON.stringify` turns a `Map` into `{}` and drops symbol
57
+ * keys entirely, so neither could carry anything. What is portable travels with
58
+ * the serialized frontier; a live handle stays where it was made.
59
+ */
60
+ type TCNSContextStore = Record<string, unknown>;
61
+
40
62
  /**
41
63
  * Allowed return types from a neuron dendrite `response` function.
42
64
  *
43
65
  * Signals route by collateral object identity (not by name).
44
66
  */
45
- type TNCNeuronResponseReturn<TAxon extends TCNSAxon> = Promise<TCNSSignal<TAxon[keyof TAxon]>> | TCNSSignal<TAxon[keyof TAxon]> | Promise<TCNSSignal<TAxon[keyof TAxon]>[]> | TCNSSignal<TAxon[keyof TAxon]>[] | Promise<void> | void;
46
-
47
- type TCNSLocalContextValueStore<TContextValue> = {
48
- get: () => TContextValue | undefined;
49
- set: (value: TContextValue) => void;
50
- delete: () => void;
51
- };
67
+ type TCNSNeuronResponseReturn<TAxon extends TCNSAxon> = TCNSSignal<TAxon[keyof TAxon]> | TCNSSignal<TAxon[keyof TAxon]>[] | void | Promise<TCNSSignal<TAxon[keyof TAxon]> | TCNSSignal<TAxon[keyof TAxon]>[] | void>;
52
68
 
53
- type TCNSNeuron<TContextValue, TAxonType extends TCNSAxon = TCNSAxon> = {
69
+ type TCNSNeuron<TAxonType extends TCNSAxon = TCNSAxon> = {
70
+ readonly index: number;
54
71
  axon: TAxonType;
55
72
  /** Optional per-neuron concurrency limit. If undefined or <= 0, no limit is applied. */
56
73
  concurrency?: number;
57
74
  /** Optional per-neuron max processing duration in milliseconds. */
58
75
  maxDuration?: number;
59
- dendrites: TCNSDendrite<TContextValue, ICNSCollateral<unknown>, TAxonType, any>[];
76
+ dendrites: TCNSDendrite<ICNSCollateral<unknown>, TAxonType, any>[];
60
77
  };
61
78
 
62
- type TCNSOptions = {
63
- /**
64
- * Automatically cleanup context stores when the stimulation is finished.
65
- * Default is false.
66
- *
67
- * CAN AFFECT PERFORMANCE!
68
- * Better to use only to solve problems with memory quickly.
69
- */
70
- autoCleanupContexts?: boolean;
71
- };
72
-
73
- interface ICNSStimulationContextStore {
74
- get: (key: object) => unknown;
75
- set: (key: object, value: unknown) => void;
76
- getAll: () => Map<object, unknown>;
77
- setAll: (values: Map<object, unknown>) => void;
78
- delete: (key: object) => void;
79
- }
79
+ /**
80
+ * Options bag for `new CNS(...)`. Currently empty — the former
81
+ * `autoCleanupContexts` flag was removed together with the per-neuron mutable
82
+ * context store. Kept as a named type so the constructor signature and future
83
+ * engine-level options have a stable home.
84
+ */
85
+ type TCNSOptions = Record<never, never>;
80
86
 
81
87
  type TCNSModality = {
88
+ readonly index: number;
82
89
  afferentPaths: Record<string | number, TCNSAfferentPath>;
83
90
  };
84
91
 
@@ -86,6 +93,20 @@ type TCNSNeuronActivationTask<TNeuron extends object = object, TCollateral exten
86
93
  neuron: TNeuron;
87
94
  dendriteCollateral: TCollateral;
88
95
  input?: TCNSSignal<TCollateral>;
96
+ /**
97
+ * Data attached to THIS activation, in namespaced compartments — the
98
+ * per-activation sibling of `stimulationContext`.
99
+ *
100
+ * A response listener can write here before the activation runs (the engine
101
+ * builds these tasks first and hands them to the listener on the response),
102
+ * and the dendrite reads them back as `ctx.activationContext`.
103
+ *
104
+ * Compartment keys are strings, by convention the writer's package name, so
105
+ * an integration and your own code cannot overwrite each other. What is
106
+ * portable travels with the serialized frontier; a live handle does not —
107
+ * see `portable()` in `@cnstra/persist`.
108
+ */
109
+ activationContext?: TCNSContextStore;
89
110
  };
90
111
 
91
112
  type TCNSNeuronActivationTaskFailure<TNeuron extends object = object> = {
@@ -100,7 +121,7 @@ type TCNSNeuronActivationTaskFailure<TNeuron extends object = object> = {
100
121
  * `CNSStimulation` class in `@cnstra/core` implements it; internal enqueue/dispatch
101
122
  * methods are intentionally not part of the public interface.
102
123
  */
103
- interface ICNSStimulation<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
124
+ interface ICNSStimulation<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
104
125
  /** Resolves when the run completes; rejects on failed tasks / abort. */
105
126
  waitUntilComplete(): Promise<void>;
106
127
  /** All activation tasks seen this run. */
@@ -112,47 +133,32 @@ interface ICNSStimulation<TNeuron extends TCNSNeuron<any, any>, TDendrite extend
112
133
  * pending) plus failed/aborted ones. The set to persist for resume.
113
134
  */
114
135
  getOutstandingTasks(): TCNSNeuronActivationTask<TNeuron>[];
115
- /** The per-neuron context store for this run. */
116
- getContext(): ICNSStimulationContextStore;
117
136
  }
118
137
 
119
138
  /**
120
- * Announced when a stimulation's synchronous turn ends: everything reachable
121
- * without yielding to the event loop has run, and what remains (if anything) is
122
- * waiting on a promise or blocked by a concurrency limit.
123
- *
124
- * This is the batch boundary. It is a property of the scheduler loop exhausting,
125
- * not of any individual activation starting or finishing - which is why it cannot
126
- * be derived from `onResponse`. A turn ends in six ways, and a response is only
127
- * emitted in the first:
139
+ * Announced when a stimulation's synchronous turn ends — the batch boundary — or, for a turn inside `cns.batch`, when that batch ends.
128
140
  *
129
- * 1. an activation finished and left the queue empty
130
- * 2. the last activation *started* and returned a promise
131
- * 3. the stimulation-level `concurrency` limit was reached
132
- * 4. the stimulation was aborted
133
- * 5. subscribers are parked behind an async `onResponse` listener
134
- * 6. a per-neuron `setConcurrency` gate forced an activation onto a promise
141
+ * It is a property of the scheduler loop exhausting, not of an activation
142
+ * finishing, so it cannot be derived from `onResponse`: a turn also ends when the
143
+ * last activation returned a promise, when a concurrency limit is reached, on
144
+ * abort, and behind an async listener. Fires once per turn, the final one
145
+ * included.
135
146
  *
136
- * Fires exactly once per turn, including the final one - so a listener that
137
- * flushes on every drain needs no separate completion handling.
138
- *
139
- * The counters carry the same meaning as on `TCNSStimulationResponse`, but they
140
- * are measured *after* the loop exhausted rather than before the work runs. On a
141
- * response `pendingActivations` is a forecast; here it is a fact, and a non-zero
142
- * value can only mean blocked - by a concurrency limit or by an abort - never
143
- * "about to run".
147
+ * The counters mean what they do on `TCNSStimulationResponse`, but measured after
148
+ * the loop exhausted — so a non-zero `pendingActivations` here is blocked, not
149
+ * about to run.
144
150
  */
145
151
  type TCNSStimulationDrain = {
146
152
  stimulation: ICNSStimulation<any, any>;
147
153
  /** `pendingActivations + activeActivations`. Zero means the stimulation is finished. */
148
154
  queueLength: number;
149
- /** Activations whose dendrite body has not been invoked. Non-zero here means blocked. */
155
+ /** Activations whose dendrite response has not been invoked. Non-zero here means blocked. */
150
156
  pendingActivations: number;
151
157
  /** Activations awaiting an unsettled promise. Non-zero means another drain is coming. */
152
158
  activeActivations: number;
153
159
  };
154
160
 
155
- type TCNSStimulationOptions<TResponse, TStimulationContext extends Object = {}> = {
161
+ type TCNSStimulationOptions<TResponse> = {
156
162
  maxNeuronHops?: number;
157
163
  onResponse?: (response: TResponse) => void | Promise<void>;
158
164
  /**
@@ -173,11 +179,17 @@ type TCNSStimulationOptions<TResponse, TStimulationContext extends Object = {}>
173
179
  */
174
180
  onDrain?: (drain: TCNSStimulationDrain) => void;
175
181
  abortSignal?: AbortSignal;
176
- ctx?: ICNSStimulationContextStore;
177
182
  concurrency?: number;
178
183
  modality?: TCNSModality;
179
184
  afferentPath?: TCNSAfferentPath;
180
- stimulationContext?: TStimulationContext;
185
+ /**
186
+ * Data attached to the whole run, in namespaced compartments — the same
187
+ * object on every hop. Its per-activation sibling is `activationContext`.
188
+ *
189
+ * What is portable travels with the serialized frontier, so a run resumed in
190
+ * another process reads back what the previous attempt left here.
191
+ */
192
+ stimulationContext?: TCNSContextStore;
181
193
  };
182
194
 
183
195
  type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>, TOutputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>> = {
@@ -185,7 +197,6 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
185
197
  outputSignal?: TCNSSignal<TOutputCollateral>;
186
198
  modality?: TCNSModality;
187
199
  afferentPath?: TCNSAfferentPath;
188
- contextValue: Map<object, unknown>;
189
200
  /**
190
201
  * Every activation this stimulation still owns, in any state:
191
202
  * `pendingActivations + activeActivations`.
@@ -209,17 +220,17 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
209
220
  */
210
221
  queueLength: number;
211
222
  /**
212
- * Activations that exist (or are reserved) but whose dendrite body has not
213
- * been invoked yet: waiting in the ring buffer, created and held before being
223
+ * Activations that exist (or are reserved) but whose dendrite response has
224
+ * not been invoked yet: waiting in the ring buffer, created and held before being
214
225
  * enqueued, or reserved by an array fan-out that is still mid-dispatch.
215
226
  *
216
227
  * Subscribers parked behind an async `onResponse` listener are counted here,
217
228
  * not in {@link activeActivations}: the split is by lifecycle stage - whether
218
- * the body has started - not by whether something is being awaited.
229
+ * the response has started - not by whether something is being awaited.
219
230
  */
220
231
  pendingActivations: number;
221
232
  /**
222
- * Activations whose dendrite body has been invoked and returned a promise
233
+ * Activations whose dendrite response has been invoked and returned a promise
223
234
  * that has not settled.
224
235
  *
225
236
  * A synchronous body passes through this state within a single pump
@@ -234,12 +245,52 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
234
245
  * task's neuron reliably — including for sink/failed tasks that have no output
235
246
  * collateral to trace an owner from.
236
247
  */
237
- neuron?: TCNSNeuron<any, any>;
248
+ neuron?: TCNSNeuron<any>;
238
249
  error?: Error;
239
250
  hops?: number;
251
+ /**
252
+ * When the activation's dendrite response was invoked, in epoch milliseconds.
253
+ *
254
+ * Present for real neuron activations on every path — success, sync throw and
255
+ * async rejection alike. Absent on responses that are not an activation (the
256
+ * entry-signal injection, and the terminal signal emitted on abort).
257
+ */
258
+ startedAt?: number;
259
+ /**
260
+ * How long the dendrite response took, in milliseconds: the span from
261
+ * {@link startedAt} to the moment the activation settled.
262
+ *
263
+ * This is the only place per-hop latency exists — it is what a trace needs to
264
+ * draw a waterfall and what a metrics layer needs for a latency histogram.
265
+ * Present exactly when {@link startedAt} is.
266
+ */
267
+ duration?: number;
268
+ /**
269
+ * The activations this response is about to create — built, but not yet run.
270
+ *
271
+ * The engine resolves the subscribers of the output collateral and builds
272
+ * their tasks BEFORE handing the response to a listener, then enqueues those
273
+ * very objects afterwards — on the synchronous path, after an async listener
274
+ * settles, and even after a listener throws. So a listener can write into
275
+ * `task.activationContext` here and the dendrite will read it back as
276
+ * `ctx.activationContext`.
277
+ *
278
+ * Empty on a response that starts nothing: a sink neuron, a failure, the
279
+ * entry injection with no subscribers, the terminal abort signal.
280
+ */
281
+ scheduledActivationTasks?: readonly TCNSNeuronActivationTask<any>[];
282
+ /**
283
+ * The context store of the activation that produced this response — the same
284
+ * object its own handler reads as `ctx.activationContext`.
285
+ *
286
+ * Here so a recorder can put it in the task's history row without holding the
287
+ * task itself. Undefined when nothing was attached, and on responses that are
288
+ * not an activation.
289
+ */
290
+ activationContext?: TCNSContextStore;
240
291
  };
241
292
 
242
- type TCNSSubscriber<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any>> = {
293
+ type TCNSSubscriber<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any>> = {
243
294
  neuron: TNeuron;
244
295
  dendrite: TDendrite;
245
296
  };
@@ -248,7 +299,7 @@ type TCNSSubscriber<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNS
248
299
  * The public contract of the compiled neuron network, exposed on `ICNS.network`.
249
300
  * The concrete `CNSNetwork` class in `@cnstra/core` implements it.
250
301
  */
251
- interface ICNSNetwork<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
302
+ interface ICNSNetwork<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
252
303
  readonly stronglyConnectedComponents: Set<TNeuron>[];
253
304
  getSCCSetByNeuron(neuron: TNeuron): Set<TNeuron> | undefined;
254
305
  getSccIndexByNeuron(neuron: TNeuron): number | undefined;
@@ -259,7 +310,7 @@ interface ICNSNetwork<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TC
259
310
  getSubscribers(collateral: ICNSCollateral<unknown>): TCNSSubscriber<TNeuron, TDendrite>[];
260
311
  }
261
312
 
262
- interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
313
+ interface ICNS<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
263
314
  options?: TCNSOptions;
264
315
  network: ICNSNetwork<TNeuron, TDendrite>;
265
316
  /**
@@ -269,16 +320,18 @@ interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendr
269
320
  addResponseListener(listener: (response: TCNSStimulationResponse) => void): () => void;
270
321
  /**
271
322
  * Add a global batch-boundary listener applied to all stimulations, called
272
- * once at the end of every synchronous turn.
323
+ * once at the end of every synchronous turn (inside `batch`, when the batch ends).
273
324
  * Returns an unsubscribe function.
274
325
  */
275
326
  addDrainListener(listener: (drain: TCNSStimulationDrain) => void): () => void;
327
+ batch<TResult>(run: () => TResult): TResult;
276
328
  stimulate(signalOrSignals: TCNSSignal<ICNSCollateral<unknown>> | TCNSSignal<ICNSCollateral<unknown>>[], options?: TCNSStimulationOptions<TCNSStimulationResponse>): ICNSStimulation<TNeuron, TDendrite>;
277
329
  /**
278
330
  * Resume a run from a set of activation tasks (e.g. an outstanding frontier
279
331
  * hydrated from persisted progress, or `getFailedTasks()` for a partial
280
332
  * retry). Unlike {@link stimulate}, no entry signal is derived — the given
281
- * tasks are enqueued directly. Pass `options.ctx` to restore neuron context.
333
+ * tasks are enqueued directly. Each task carries its own input signal (with
334
+ * payload), so re-driving the frontier needs no extra state.
282
335
  */
283
336
  activate(tasks: TCNSNeuronActivationTask<TNeuron>[], options?: TCNSStimulationOptions<TCNSStimulationResponse>): ICNSStimulation<TNeuron, TDendrite>;
284
337
  }
@@ -288,20 +341,30 @@ interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendr
288
341
  * lives here. Factory layers add their own fields via the `TExt` extension
289
342
  * (see {@link TCNSHandlerContext}), so the base stays clean for neurons that
290
343
  * don't opt into anything.
344
+ *
345
+ * Internal building block for {@link TCNSHandlerContext} — not part of the public API.
291
346
  */
292
- type TCNSHandlerContextBase<TContextValue> = TCNSLocalContextValueStore<TContextValue> & {
347
+ type TCNSHandlerContextBase = {
293
348
  abortSignal?: AbortSignal;
294
349
  cns?: ICNS<any, any>;
295
350
  stimulation?: any;
296
351
  /**
297
- * The caller-supplied value passed as `stimulate(sig, { stimulationContext })`
298
- * (or `activate(...)`) — the same object on every hop of this stimulation, in
299
- * any environment (sync or async, node or browser). Use it to correlate logs
300
- * to a run: pass `{ stimulationId, attemptNumber }` and read it here. Typed
301
- * `unknown` because the neuron doesn't own the shape — the caller does; cast at
302
- * the read site.
352
+ * The context store of the whole run — what the caller passed as
353
+ * `stimulate(sig, { stimulationContext })` plus whatever the run has written
354
+ * into it since, the same object on every hop in any environment (sync or
355
+ * async, node or browser). Keyed by namespace; the values inside are
356
+ * `unknown`, so cast at the read site.
303
357
  */
304
- stimulationContext?: unknown;
358
+ stimulationContext?: TCNSContextStore;
359
+ /**
360
+ * The context store of the activation currently running — data a response
361
+ * listener attached to THIS activation before it started. Unset when nobody
362
+ * wrote anything.
363
+ *
364
+ * Same shape as {@link stimulationContext}, shorter life: this one is gone
365
+ * when the activation returns.
366
+ */
367
+ activationContext?: TCNSContextStore;
305
368
  };
306
369
  /**
307
370
  * The `ctx` a dendrite handler receives. `TExt` is whatever the factory layers
@@ -312,34 +375,11 @@ type TCNSHandlerContextBase<TContextValue> = TCNSLocalContextValueStore<TContext
312
375
  * The handler signature stays `(payload, axon, ctx)` no matter how many layers
313
376
  * you stack; each layer widens the type of `ctx`, never the argument list.
314
377
  */
315
- type TCNSHandlerContext<TContextValue, TExt = unknown> = TCNSHandlerContextBase<TContextValue> & TExt;
378
+ type TCNSHandlerContext<TExt = unknown> = TCNSHandlerContextBase & TExt;
316
379
 
317
- type TCNSDendrite<TContextValue, TSenderCollateral extends ICNSCollateral<unknown>, TAxonType extends TCNSAxon, TExt = unknown> = {
380
+ type TCNSDendrite<TSenderCollateral extends ICNSCollateral<unknown>, TAxonType extends TCNSAxon, TExt = unknown> = {
318
381
  collateral: TSenderCollateral;
319
- response: (payload: TSenderCollateral extends ICNSCollateral<infer P> ? P : never, axon: TAxonType, ctx: TCNSHandlerContext<TContextValue, TExt>) => TNCNeuronResponseReturn<TAxonType>;
320
- };
321
-
322
- type CNSCollateralLike = ICNSCollateral<unknown>;
323
- type TCNSNeuronPersistOptions<TNeuron extends TCNSNeuron<unknown, any> = TCNSNeuron<unknown, any>> = {
324
- name: string;
325
- neuron: TNeuron;
326
- };
327
- type TCNSCollateralPersistOptions<TCollateral extends CNSCollateralLike = CNSCollateralLike> = {
328
- name: string;
329
- collateral: TCollateral;
330
- };
331
- type TCNSStimulationPersistOptions = {
332
- stimulationId: string;
333
- };
334
-
335
- type TCNSStimulationQueueItem<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any>, TInputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>> = {
336
- neuron: TNeuron;
337
- subscriber: TCNSSubscriber<TNeuron, TDendrite>;
338
- inputSignal?: TCNSSignal<TInputCollateral>;
339
- };
340
-
341
- type TCNSStimulationSerializedContextValue = {
342
- [key: string]: unknown;
382
+ response: (payload: TSenderCollateral extends ICNSCollateral<infer P> ? P : never, axon: TAxonType, ctx: TCNSHandlerContext<TExt>) => TCNSNeuronResponseReturn<TAxonType>;
343
383
  };
344
384
 
345
- export type { ICNS, ICNSCollateral, ICNSNetwork, ICNSStimulation, ICNSStimulationContextStore, TCNSAfferentPath, TCNSAxon, TCNSCollateralPersistOptions, TCNSDendrite, TCNSHandlerContext, TCNSHandlerContextBase, TCNSLocalContextValueStore, TCNSModality, TCNSNeuron, TCNSNeuronActivationTask, TCNSNeuronActivationTaskFailure, TCNSNeuronPersistOptions, TCNSOptions, TCNSSignal, TCNSStimulationDrain, TCNSStimulationOptions, TCNSStimulationPersistOptions, TCNSStimulationQueueItem, TCNSStimulationResponse, TCNSStimulationSerializedContextValue, TCNSSubscriber, TNCNeuronResponseReturn };
385
+ export type { ICNS, ICNSCollateral, ICNSNetwork, ICNSStimulation, TCNSAfferentPath, TCNSAxon, TCNSContextStore, TCNSDendrite, TCNSHandlerContext, TCNSModality, TCNSNeuron, TCNSNeuronActivationTask, TCNSNeuronActivationTaskFailure, TCNSNeuronResponseReturn, TCNSOptions, TCNSSignal, TCNSStimulationDrain, TCNSStimulationOptions, TCNSStimulationResponse, TCNSSubscriber };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  type TCNSAfferentPath = {
2
+ readonly index: number;
2
3
  parentAfferentPath?: TCNSAfferentPath;
3
4
  };
4
5
 
@@ -8,6 +9,7 @@ type TCNSSignal<TCollateral extends ICNSCollateral<unknown>> = {
8
9
  };
9
10
 
10
11
  interface ICNSCollateral<TPayload> {
12
+ readonly index: number;
11
13
  createSignal(): TCNSSignal<ICNSCollateral<TPayload>>;
12
14
  createSignal(payload: TPayload): TCNSSignal<ICNSCollateral<TPayload>>;
13
15
  }
@@ -37,48 +39,53 @@ type TCNSAxon<TCollaterals extends Record<string, ICNSCollateral<unknown>> = Rec
37
39
  [K in keyof TCollaterals]: TCollaterals[K];
38
40
  };
39
41
 
42
+ /**
43
+ * A context store: data attached to something the engine is running, in
44
+ * compartments.
45
+ *
46
+ * There are two of them, same shape, different life — the run's
47
+ * (`stimulationContext`, one per stimulation) and the activation's
48
+ * (`activationContext`, one per neuron activation). Same shape on purpose: they
49
+ * are used the same way, serialized the same way, and read the same way.
50
+ *
51
+ * A key is a namespace its writer owns, by convention the package name
52
+ * (`'@cnstra/persist-otel'`), so an integration and your own code cannot
53
+ * overwrite each other. A caller who owns their whole run does not need a prefix.
54
+ *
55
+ * Plain object with string keys rather than a `Map` because this crosses a
56
+ * process boundary: `JSON.stringify` turns a `Map` into `{}` and drops symbol
57
+ * keys entirely, so neither could carry anything. What is portable travels with
58
+ * the serialized frontier; a live handle stays where it was made.
59
+ */
60
+ type TCNSContextStore = Record<string, unknown>;
61
+
40
62
  /**
41
63
  * Allowed return types from a neuron dendrite `response` function.
42
64
  *
43
65
  * Signals route by collateral object identity (not by name).
44
66
  */
45
- type TNCNeuronResponseReturn<TAxon extends TCNSAxon> = Promise<TCNSSignal<TAxon[keyof TAxon]>> | TCNSSignal<TAxon[keyof TAxon]> | Promise<TCNSSignal<TAxon[keyof TAxon]>[]> | TCNSSignal<TAxon[keyof TAxon]>[] | Promise<void> | void;
46
-
47
- type TCNSLocalContextValueStore<TContextValue> = {
48
- get: () => TContextValue | undefined;
49
- set: (value: TContextValue) => void;
50
- delete: () => void;
51
- };
67
+ type TCNSNeuronResponseReturn<TAxon extends TCNSAxon> = TCNSSignal<TAxon[keyof TAxon]> | TCNSSignal<TAxon[keyof TAxon]>[] | void | Promise<TCNSSignal<TAxon[keyof TAxon]> | TCNSSignal<TAxon[keyof TAxon]>[] | void>;
52
68
 
53
- type TCNSNeuron<TContextValue, TAxonType extends TCNSAxon = TCNSAxon> = {
69
+ type TCNSNeuron<TAxonType extends TCNSAxon = TCNSAxon> = {
70
+ readonly index: number;
54
71
  axon: TAxonType;
55
72
  /** Optional per-neuron concurrency limit. If undefined or <= 0, no limit is applied. */
56
73
  concurrency?: number;
57
74
  /** Optional per-neuron max processing duration in milliseconds. */
58
75
  maxDuration?: number;
59
- dendrites: TCNSDendrite<TContextValue, ICNSCollateral<unknown>, TAxonType, any>[];
76
+ dendrites: TCNSDendrite<ICNSCollateral<unknown>, TAxonType, any>[];
60
77
  };
61
78
 
62
- type TCNSOptions = {
63
- /**
64
- * Automatically cleanup context stores when the stimulation is finished.
65
- * Default is false.
66
- *
67
- * CAN AFFECT PERFORMANCE!
68
- * Better to use only to solve problems with memory quickly.
69
- */
70
- autoCleanupContexts?: boolean;
71
- };
72
-
73
- interface ICNSStimulationContextStore {
74
- get: (key: object) => unknown;
75
- set: (key: object, value: unknown) => void;
76
- getAll: () => Map<object, unknown>;
77
- setAll: (values: Map<object, unknown>) => void;
78
- delete: (key: object) => void;
79
- }
79
+ /**
80
+ * Options bag for `new CNS(...)`. Currently empty — the former
81
+ * `autoCleanupContexts` flag was removed together with the per-neuron mutable
82
+ * context store. Kept as a named type so the constructor signature and future
83
+ * engine-level options have a stable home.
84
+ */
85
+ type TCNSOptions = Record<never, never>;
80
86
 
81
87
  type TCNSModality = {
88
+ readonly index: number;
82
89
  afferentPaths: Record<string | number, TCNSAfferentPath>;
83
90
  };
84
91
 
@@ -86,6 +93,20 @@ type TCNSNeuronActivationTask<TNeuron extends object = object, TCollateral exten
86
93
  neuron: TNeuron;
87
94
  dendriteCollateral: TCollateral;
88
95
  input?: TCNSSignal<TCollateral>;
96
+ /**
97
+ * Data attached to THIS activation, in namespaced compartments — the
98
+ * per-activation sibling of `stimulationContext`.
99
+ *
100
+ * A response listener can write here before the activation runs (the engine
101
+ * builds these tasks first and hands them to the listener on the response),
102
+ * and the dendrite reads them back as `ctx.activationContext`.
103
+ *
104
+ * Compartment keys are strings, by convention the writer's package name, so
105
+ * an integration and your own code cannot overwrite each other. What is
106
+ * portable travels with the serialized frontier; a live handle does not —
107
+ * see `portable()` in `@cnstra/persist`.
108
+ */
109
+ activationContext?: TCNSContextStore;
89
110
  };
90
111
 
91
112
  type TCNSNeuronActivationTaskFailure<TNeuron extends object = object> = {
@@ -100,7 +121,7 @@ type TCNSNeuronActivationTaskFailure<TNeuron extends object = object> = {
100
121
  * `CNSStimulation` class in `@cnstra/core` implements it; internal enqueue/dispatch
101
122
  * methods are intentionally not part of the public interface.
102
123
  */
103
- interface ICNSStimulation<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
124
+ interface ICNSStimulation<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
104
125
  /** Resolves when the run completes; rejects on failed tasks / abort. */
105
126
  waitUntilComplete(): Promise<void>;
106
127
  /** All activation tasks seen this run. */
@@ -112,47 +133,32 @@ interface ICNSStimulation<TNeuron extends TCNSNeuron<any, any>, TDendrite extend
112
133
  * pending) plus failed/aborted ones. The set to persist for resume.
113
134
  */
114
135
  getOutstandingTasks(): TCNSNeuronActivationTask<TNeuron>[];
115
- /** The per-neuron context store for this run. */
116
- getContext(): ICNSStimulationContextStore;
117
136
  }
118
137
 
119
138
  /**
120
- * Announced when a stimulation's synchronous turn ends: everything reachable
121
- * without yielding to the event loop has run, and what remains (if anything) is
122
- * waiting on a promise or blocked by a concurrency limit.
123
- *
124
- * This is the batch boundary. It is a property of the scheduler loop exhausting,
125
- * not of any individual activation starting or finishing - which is why it cannot
126
- * be derived from `onResponse`. A turn ends in six ways, and a response is only
127
- * emitted in the first:
139
+ * Announced when a stimulation's synchronous turn ends — the batch boundary — or, for a turn inside `cns.batch`, when that batch ends.
128
140
  *
129
- * 1. an activation finished and left the queue empty
130
- * 2. the last activation *started* and returned a promise
131
- * 3. the stimulation-level `concurrency` limit was reached
132
- * 4. the stimulation was aborted
133
- * 5. subscribers are parked behind an async `onResponse` listener
134
- * 6. a per-neuron `setConcurrency` gate forced an activation onto a promise
141
+ * It is a property of the scheduler loop exhausting, not of an activation
142
+ * finishing, so it cannot be derived from `onResponse`: a turn also ends when the
143
+ * last activation returned a promise, when a concurrency limit is reached, on
144
+ * abort, and behind an async listener. Fires once per turn, the final one
145
+ * included.
135
146
  *
136
- * Fires exactly once per turn, including the final one - so a listener that
137
- * flushes on every drain needs no separate completion handling.
138
- *
139
- * The counters carry the same meaning as on `TCNSStimulationResponse`, but they
140
- * are measured *after* the loop exhausted rather than before the work runs. On a
141
- * response `pendingActivations` is a forecast; here it is a fact, and a non-zero
142
- * value can only mean blocked - by a concurrency limit or by an abort - never
143
- * "about to run".
147
+ * The counters mean what they do on `TCNSStimulationResponse`, but measured after
148
+ * the loop exhausted — so a non-zero `pendingActivations` here is blocked, not
149
+ * about to run.
144
150
  */
145
151
  type TCNSStimulationDrain = {
146
152
  stimulation: ICNSStimulation<any, any>;
147
153
  /** `pendingActivations + activeActivations`. Zero means the stimulation is finished. */
148
154
  queueLength: number;
149
- /** Activations whose dendrite body has not been invoked. Non-zero here means blocked. */
155
+ /** Activations whose dendrite response has not been invoked. Non-zero here means blocked. */
150
156
  pendingActivations: number;
151
157
  /** Activations awaiting an unsettled promise. Non-zero means another drain is coming. */
152
158
  activeActivations: number;
153
159
  };
154
160
 
155
- type TCNSStimulationOptions<TResponse, TStimulationContext extends Object = {}> = {
161
+ type TCNSStimulationOptions<TResponse> = {
156
162
  maxNeuronHops?: number;
157
163
  onResponse?: (response: TResponse) => void | Promise<void>;
158
164
  /**
@@ -173,11 +179,17 @@ type TCNSStimulationOptions<TResponse, TStimulationContext extends Object = {}>
173
179
  */
174
180
  onDrain?: (drain: TCNSStimulationDrain) => void;
175
181
  abortSignal?: AbortSignal;
176
- ctx?: ICNSStimulationContextStore;
177
182
  concurrency?: number;
178
183
  modality?: TCNSModality;
179
184
  afferentPath?: TCNSAfferentPath;
180
- stimulationContext?: TStimulationContext;
185
+ /**
186
+ * Data attached to the whole run, in namespaced compartments — the same
187
+ * object on every hop. Its per-activation sibling is `activationContext`.
188
+ *
189
+ * What is portable travels with the serialized frontier, so a run resumed in
190
+ * another process reads back what the previous attempt left here.
191
+ */
192
+ stimulationContext?: TCNSContextStore;
181
193
  };
182
194
 
183
195
  type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>, TOutputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>> = {
@@ -185,7 +197,6 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
185
197
  outputSignal?: TCNSSignal<TOutputCollateral>;
186
198
  modality?: TCNSModality;
187
199
  afferentPath?: TCNSAfferentPath;
188
- contextValue: Map<object, unknown>;
189
200
  /**
190
201
  * Every activation this stimulation still owns, in any state:
191
202
  * `pendingActivations + activeActivations`.
@@ -209,17 +220,17 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
209
220
  */
210
221
  queueLength: number;
211
222
  /**
212
- * Activations that exist (or are reserved) but whose dendrite body has not
213
- * been invoked yet: waiting in the ring buffer, created and held before being
223
+ * Activations that exist (or are reserved) but whose dendrite response has
224
+ * not been invoked yet: waiting in the ring buffer, created and held before being
214
225
  * enqueued, or reserved by an array fan-out that is still mid-dispatch.
215
226
  *
216
227
  * Subscribers parked behind an async `onResponse` listener are counted here,
217
228
  * not in {@link activeActivations}: the split is by lifecycle stage - whether
218
- * the body has started - not by whether something is being awaited.
229
+ * the response has started - not by whether something is being awaited.
219
230
  */
220
231
  pendingActivations: number;
221
232
  /**
222
- * Activations whose dendrite body has been invoked and returned a promise
233
+ * Activations whose dendrite response has been invoked and returned a promise
223
234
  * that has not settled.
224
235
  *
225
236
  * A synchronous body passes through this state within a single pump
@@ -234,12 +245,52 @@ type TCNSStimulationResponse<TInputCollateral extends ICNSCollateral<unknown> =
234
245
  * task's neuron reliably — including for sink/failed tasks that have no output
235
246
  * collateral to trace an owner from.
236
247
  */
237
- neuron?: TCNSNeuron<any, any>;
248
+ neuron?: TCNSNeuron<any>;
238
249
  error?: Error;
239
250
  hops?: number;
251
+ /**
252
+ * When the activation's dendrite response was invoked, in epoch milliseconds.
253
+ *
254
+ * Present for real neuron activations on every path — success, sync throw and
255
+ * async rejection alike. Absent on responses that are not an activation (the
256
+ * entry-signal injection, and the terminal signal emitted on abort).
257
+ */
258
+ startedAt?: number;
259
+ /**
260
+ * How long the dendrite response took, in milliseconds: the span from
261
+ * {@link startedAt} to the moment the activation settled.
262
+ *
263
+ * This is the only place per-hop latency exists — it is what a trace needs to
264
+ * draw a waterfall and what a metrics layer needs for a latency histogram.
265
+ * Present exactly when {@link startedAt} is.
266
+ */
267
+ duration?: number;
268
+ /**
269
+ * The activations this response is about to create — built, but not yet run.
270
+ *
271
+ * The engine resolves the subscribers of the output collateral and builds
272
+ * their tasks BEFORE handing the response to a listener, then enqueues those
273
+ * very objects afterwards — on the synchronous path, after an async listener
274
+ * settles, and even after a listener throws. So a listener can write into
275
+ * `task.activationContext` here and the dendrite will read it back as
276
+ * `ctx.activationContext`.
277
+ *
278
+ * Empty on a response that starts nothing: a sink neuron, a failure, the
279
+ * entry injection with no subscribers, the terminal abort signal.
280
+ */
281
+ scheduledActivationTasks?: readonly TCNSNeuronActivationTask<any>[];
282
+ /**
283
+ * The context store of the activation that produced this response — the same
284
+ * object its own handler reads as `ctx.activationContext`.
285
+ *
286
+ * Here so a recorder can put it in the task's history row without holding the
287
+ * task itself. Undefined when nothing was attached, and on responses that are
288
+ * not an activation.
289
+ */
290
+ activationContext?: TCNSContextStore;
240
291
  };
241
292
 
242
- type TCNSSubscriber<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any>> = {
293
+ type TCNSSubscriber<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any>> = {
243
294
  neuron: TNeuron;
244
295
  dendrite: TDendrite;
245
296
  };
@@ -248,7 +299,7 @@ type TCNSSubscriber<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNS
248
299
  * The public contract of the compiled neuron network, exposed on `ICNS.network`.
249
300
  * The concrete `CNSNetwork` class in `@cnstra/core` implements it.
250
301
  */
251
- interface ICNSNetwork<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
302
+ interface ICNSNetwork<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
252
303
  readonly stronglyConnectedComponents: Set<TNeuron>[];
253
304
  getSCCSetByNeuron(neuron: TNeuron): Set<TNeuron> | undefined;
254
305
  getSccIndexByNeuron(neuron: TNeuron): number | undefined;
@@ -259,7 +310,7 @@ interface ICNSNetwork<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TC
259
310
  getSubscribers(collateral: ICNSCollateral<unknown>): TCNSSubscriber<TNeuron, TDendrite>[];
260
311
  }
261
312
 
262
- interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any> = TCNSDendrite<any, any, any>> {
313
+ interface ICNS<TNeuron extends TCNSNeuron<any>, TDendrite extends TCNSDendrite<any, any> = TCNSDendrite<any, any>> {
263
314
  options?: TCNSOptions;
264
315
  network: ICNSNetwork<TNeuron, TDendrite>;
265
316
  /**
@@ -269,16 +320,18 @@ interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendr
269
320
  addResponseListener(listener: (response: TCNSStimulationResponse) => void): () => void;
270
321
  /**
271
322
  * Add a global batch-boundary listener applied to all stimulations, called
272
- * once at the end of every synchronous turn.
323
+ * once at the end of every synchronous turn (inside `batch`, when the batch ends).
273
324
  * Returns an unsubscribe function.
274
325
  */
275
326
  addDrainListener(listener: (drain: TCNSStimulationDrain) => void): () => void;
327
+ batch<TResult>(run: () => TResult): TResult;
276
328
  stimulate(signalOrSignals: TCNSSignal<ICNSCollateral<unknown>> | TCNSSignal<ICNSCollateral<unknown>>[], options?: TCNSStimulationOptions<TCNSStimulationResponse>): ICNSStimulation<TNeuron, TDendrite>;
277
329
  /**
278
330
  * Resume a run from a set of activation tasks (e.g. an outstanding frontier
279
331
  * hydrated from persisted progress, or `getFailedTasks()` for a partial
280
332
  * retry). Unlike {@link stimulate}, no entry signal is derived — the given
281
- * tasks are enqueued directly. Pass `options.ctx` to restore neuron context.
333
+ * tasks are enqueued directly. Each task carries its own input signal (with
334
+ * payload), so re-driving the frontier needs no extra state.
282
335
  */
283
336
  activate(tasks: TCNSNeuronActivationTask<TNeuron>[], options?: TCNSStimulationOptions<TCNSStimulationResponse>): ICNSStimulation<TNeuron, TDendrite>;
284
337
  }
@@ -288,20 +341,30 @@ interface ICNS<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendr
288
341
  * lives here. Factory layers add their own fields via the `TExt` extension
289
342
  * (see {@link TCNSHandlerContext}), so the base stays clean for neurons that
290
343
  * don't opt into anything.
344
+ *
345
+ * Internal building block for {@link TCNSHandlerContext} — not part of the public API.
291
346
  */
292
- type TCNSHandlerContextBase<TContextValue> = TCNSLocalContextValueStore<TContextValue> & {
347
+ type TCNSHandlerContextBase = {
293
348
  abortSignal?: AbortSignal;
294
349
  cns?: ICNS<any, any>;
295
350
  stimulation?: any;
296
351
  /**
297
- * The caller-supplied value passed as `stimulate(sig, { stimulationContext })`
298
- * (or `activate(...)`) — the same object on every hop of this stimulation, in
299
- * any environment (sync or async, node or browser). Use it to correlate logs
300
- * to a run: pass `{ stimulationId, attemptNumber }` and read it here. Typed
301
- * `unknown` because the neuron doesn't own the shape — the caller does; cast at
302
- * the read site.
352
+ * The context store of the whole run — what the caller passed as
353
+ * `stimulate(sig, { stimulationContext })` plus whatever the run has written
354
+ * into it since, the same object on every hop in any environment (sync or
355
+ * async, node or browser). Keyed by namespace; the values inside are
356
+ * `unknown`, so cast at the read site.
303
357
  */
304
- stimulationContext?: unknown;
358
+ stimulationContext?: TCNSContextStore;
359
+ /**
360
+ * The context store of the activation currently running — data a response
361
+ * listener attached to THIS activation before it started. Unset when nobody
362
+ * wrote anything.
363
+ *
364
+ * Same shape as {@link stimulationContext}, shorter life: this one is gone
365
+ * when the activation returns.
366
+ */
367
+ activationContext?: TCNSContextStore;
305
368
  };
306
369
  /**
307
370
  * The `ctx` a dendrite handler receives. `TExt` is whatever the factory layers
@@ -312,34 +375,11 @@ type TCNSHandlerContextBase<TContextValue> = TCNSLocalContextValueStore<TContext
312
375
  * The handler signature stays `(payload, axon, ctx)` no matter how many layers
313
376
  * you stack; each layer widens the type of `ctx`, never the argument list.
314
377
  */
315
- type TCNSHandlerContext<TContextValue, TExt = unknown> = TCNSHandlerContextBase<TContextValue> & TExt;
378
+ type TCNSHandlerContext<TExt = unknown> = TCNSHandlerContextBase & TExt;
316
379
 
317
- type TCNSDendrite<TContextValue, TSenderCollateral extends ICNSCollateral<unknown>, TAxonType extends TCNSAxon, TExt = unknown> = {
380
+ type TCNSDendrite<TSenderCollateral extends ICNSCollateral<unknown>, TAxonType extends TCNSAxon, TExt = unknown> = {
318
381
  collateral: TSenderCollateral;
319
- response: (payload: TSenderCollateral extends ICNSCollateral<infer P> ? P : never, axon: TAxonType, ctx: TCNSHandlerContext<TContextValue, TExt>) => TNCNeuronResponseReturn<TAxonType>;
320
- };
321
-
322
- type CNSCollateralLike = ICNSCollateral<unknown>;
323
- type TCNSNeuronPersistOptions<TNeuron extends TCNSNeuron<unknown, any> = TCNSNeuron<unknown, any>> = {
324
- name: string;
325
- neuron: TNeuron;
326
- };
327
- type TCNSCollateralPersistOptions<TCollateral extends CNSCollateralLike = CNSCollateralLike> = {
328
- name: string;
329
- collateral: TCollateral;
330
- };
331
- type TCNSStimulationPersistOptions = {
332
- stimulationId: string;
333
- };
334
-
335
- type TCNSStimulationQueueItem<TNeuron extends TCNSNeuron<any, any>, TDendrite extends TCNSDendrite<any, any, any>, TInputCollateral extends ICNSCollateral<unknown> = ICNSCollateral<unknown>> = {
336
- neuron: TNeuron;
337
- subscriber: TCNSSubscriber<TNeuron, TDendrite>;
338
- inputSignal?: TCNSSignal<TInputCollateral>;
339
- };
340
-
341
- type TCNSStimulationSerializedContextValue = {
342
- [key: string]: unknown;
382
+ response: (payload: TSenderCollateral extends ICNSCollateral<infer P> ? P : never, axon: TAxonType, ctx: TCNSHandlerContext<TExt>) => TCNSNeuronResponseReturn<TAxonType>;
343
383
  };
344
384
 
345
- export type { ICNS, ICNSCollateral, ICNSNetwork, ICNSStimulation, ICNSStimulationContextStore, TCNSAfferentPath, TCNSAxon, TCNSCollateralPersistOptions, TCNSDendrite, TCNSHandlerContext, TCNSHandlerContextBase, TCNSLocalContextValueStore, TCNSModality, TCNSNeuron, TCNSNeuronActivationTask, TCNSNeuronActivationTaskFailure, TCNSNeuronPersistOptions, TCNSOptions, TCNSSignal, TCNSStimulationDrain, TCNSStimulationOptions, TCNSStimulationPersistOptions, TCNSStimulationQueueItem, TCNSStimulationResponse, TCNSStimulationSerializedContextValue, TCNSSubscriber, TNCNeuronResponseReturn };
385
+ export type { ICNS, ICNSCollateral, ICNSNetwork, ICNSStimulation, TCNSAfferentPath, TCNSAxon, TCNSContextStore, TCNSDendrite, TCNSHandlerContext, TCNSModality, TCNSNeuron, TCNSNeuronActivationTask, TCNSNeuronActivationTaskFailure, TCNSNeuronResponseReturn, TCNSOptions, TCNSSignal, TCNSStimulationDrain, TCNSStimulationOptions, TCNSStimulationResponse, TCNSSubscriber };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./types/TCNSAfferentPath\";\nexport * from \"./types/TCNSAxon\";\nexport * from \"./types/TCNSDendrite\";\nexport * from \"./types/TCNSHandlerContext\";\nexport * from \"./types/TCNSLocalContextValueStore\";\nexport * from \"./types/TCNSModality\";\nexport * from \"./types/TCNSNeuron\";\nexport * from \"./types/TCNSNeuronActivationTask\";\nexport * from \"./types/TCNSNeuronActivationTaskFailure\";\nexport * from \"./types/TCNSNeuronResponseReturn\";\nexport * from \"./types/TCNSOptions\";\nexport * from \"./types/TCNSPersist\";\nexport * from \"./types/TCNSSignal\";\nexport * from \"./types/TCNSStimulationDrain\";\nexport * from \"./types/TCNSStimulationOptions\";\nexport * from \"./types/TCNSStimulationQueueItem\";\nexport * from \"./types/TCNSStimulationResponse\";\nexport * from \"./types/TCNSStimulationSerializedContextValue\";\nexport * from \"./types/TCNSSubscriber\";\nexport * from \"./interfaces/ICNS\";\nexport * from \"./interfaces/ICNSCollateral\";\nexport * from \"./interfaces/ICNSNetwork\";\nexport * from \"./interfaces/ICNSStimulation\";\nexport * from \"./interfaces/ICNSStimulationContextStore\";\n"],"mappings":";;;;;;;;;;;;;;;AAAA;;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./types/TCNSAfferentPath\";\nexport * from \"./types/TCNSAxon\";\nexport * from \"./types/TCNSContextStore\";\nexport * from \"./types/TCNSDendrite\";\nexport * from \"./types/TCNSHandlerContext\";\nexport * from \"./types/TCNSModality\";\nexport * from \"./types/TCNSNeuron\";\nexport * from \"./types/TCNSNeuronActivationTask\";\nexport * from \"./types/TCNSNeuronActivationTaskFailure\";\nexport * from \"./types/TCNSNeuronResponseReturn\";\nexport * from \"./types/TCNSOptions\";\nexport * from \"./types/TCNSSignal\";\nexport * from \"./types/TCNSStimulationDrain\";\nexport * from \"./types/TCNSStimulationOptions\";\nexport * from \"./types/TCNSStimulationResponse\";\nexport * from \"./types/TCNSSubscriber\";\nexport * from \"./interfaces/ICNS\";\nexport * from \"./interfaces/ICNSCollateral\";\nexport * from \"./interfaces/ICNSNetwork\";\nexport * from \"./interfaces/ICNSStimulation\";\n"],"mappings":";;;;;;;;;;;;;;;AAAA;;","names":[]}
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@cnstra/types",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Shared TypeScript contract for CNStra: signals, tasks, axons, neuron/collateral/stimulation/network interfaces. Zero runtime — the base package core and integrations build on.",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/abaikov/cnstra.git",
8
+ "directory": "packages/types"
9
+ },
5
10
  "keywords": ["cnstra", "types", "contract", "interfaces"],
6
11
  "main": "dist/index.js",
7
12
  "module": "dist/index.mjs",
@@ -16,6 +21,7 @@
16
21
  "sideEffects": false,
17
22
  "files": ["dist"],
18
23
  "scripts": {
24
+ "prepublishOnly": "node ../../scripts/check-drift.mjs --gate",
19
25
  "build": "tsup",
20
26
  "test:types": "tsc --noEmit",
21
27
  "clean": "rm -rf dist"