@mindot/will 0.1.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.
Files changed (178) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +777 -0
  3. package/dist/index.d.ts +8144 -0
  4. package/dist/index.js +26231 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +73 -0
  7. package/src/cognition/agency/access.grants.ts +59 -0
  8. package/src/cognition/agency/competence.codec.ts +89 -0
  9. package/src/cognition/agency/engines/action.selector.ts +462 -0
  10. package/src/cognition/agency/engines/affordance.synthesizer.ts +384 -0
  11. package/src/cognition/agency/engines/deliberation.engine.ts +241 -0
  12. package/src/cognition/agency/engines/instruction.intake.ts +54 -0
  13. package/src/cognition/agency/engines/motor.schema.executor.ts +532 -0
  14. package/src/cognition/agency/engines/reafference.engine.ts +241 -0
  15. package/src/cognition/agency/execution.primitives.ts +118 -0
  16. package/src/cognition/agency/index.ts +58 -0
  17. package/src/cognition/agency/proactive.communicator.ts +274 -0
  18. package/src/cognition/agency/reconcile.learning.ts +82 -0
  19. package/src/cognition/agency/schemas/external.ts +59 -0
  20. package/src/cognition/agency/schemas/innate.ts +111 -0
  21. package/src/cognition/agency/schemas/repertoire.ts +246 -0
  22. package/src/cognition/agency/selection.scoring.ts +191 -0
  23. package/src/cognition/agency/types.ts +165 -0
  24. package/src/cognition/bus.ts +391 -0
  25. package/src/cognition/completion.inbox.ts +86 -0
  26. package/src/cognition/config.mirror.entities.ts +475 -0
  27. package/src/cognition/conversation.memory.ts +81 -0
  28. package/src/cognition/event.log.ts +116 -0
  29. package/src/cognition/event.schemas.ts +568 -0
  30. package/src/cognition/faculties/aesthetic.evaluator.ts +313 -0
  31. package/src/cognition/faculties/affective.blender.ts +562 -0
  32. package/src/cognition/faculties/attachment.evaluator.ts +432 -0
  33. package/src/cognition/faculties/attention.allocator.ts +422 -0
  34. package/src/cognition/faculties/autobiographical.narrator.ts +300 -0
  35. package/src/cognition/faculties/bias.detector.ts +363 -0
  36. package/src/cognition/faculties/circadian.oscillator.ts +294 -0
  37. package/src/cognition/faculties/confidence.calibrator.ts +324 -0
  38. package/src/cognition/faculties/dream.simulator.ts +251 -0
  39. package/src/cognition/faculties/empathy.simulator.ts +253 -0
  40. package/src/cognition/faculties/energy.regulator.ts +320 -0
  41. package/src/cognition/faculties/episodic.consolidator.ts +728 -0
  42. package/src/cognition/faculties/executive.engine/commands.ts +459 -0
  43. package/src/cognition/faculties/executive.engine/config.ts +46 -0
  44. package/src/cognition/faculties/executive.engine/context.ts +605 -0
  45. package/src/cognition/faculties/executive.engine/deferred.effects.ts +104 -0
  46. package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +60 -0
  47. package/src/cognition/faculties/executive.engine/effort.gate.ts +114 -0
  48. package/src/cognition/faculties/executive.engine/engine.ts +1028 -0
  49. package/src/cognition/faculties/executive.engine/escalation.buffer.ts +90 -0
  50. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +271 -0
  51. package/src/cognition/faculties/executive.engine/facet.ts +628 -0
  52. package/src/cognition/faculties/executive.engine/gating.ts +222 -0
  53. package/src/cognition/faculties/executive.engine/index.ts +6 -0
  54. package/src/cognition/faculties/executive.engine/messages.ts +102 -0
  55. package/src/cognition/faculties/executive.engine/parser.ts +380 -0
  56. package/src/cognition/faculties/executive.engine/prompt.factory.ts +1053 -0
  57. package/src/cognition/faculties/executive.engine/types.ts +323 -0
  58. package/src/cognition/faculties/exteroception.ts +338 -0
  59. package/src/cognition/faculties/forgetting.curve.ts +202 -0
  60. package/src/cognition/faculties/frustration.evaluator.ts +280 -0
  61. package/src/cognition/faculties/goal.manager.ts +1008 -0
  62. package/src/cognition/faculties/inhibition.controller.ts +351 -0
  63. package/src/cognition/faculties/interoception.ts +417 -0
  64. package/src/cognition/faculties/introspection.engine.ts +246 -0
  65. package/src/cognition/faculties/known.entity.tracker.ts +439 -0
  66. package/src/cognition/faculties/loss.evaluator.ts +224 -0
  67. package/src/cognition/faculties/moral.evaluator.ts +437 -0
  68. package/src/cognition/faculties/novelty.detector.ts +254 -0
  69. package/src/cognition/faculties/persona.consolidator.ts +845 -0
  70. package/src/cognition/faculties/planning.engine/engine.ts +859 -0
  71. package/src/cognition/faculties/planning.engine/plan.frontier.ts +83 -0
  72. package/src/cognition/faculties/planning.engine/plan.store.ts +174 -0
  73. package/src/cognition/faculties/planning.engine/plan.supervision.ts +494 -0
  74. package/src/cognition/faculties/planning.engine/types.ts +143 -0
  75. package/src/cognition/faculties/reputation.tracker.ts +294 -0
  76. package/src/cognition/faculties/reward.evaluator.ts +304 -0
  77. package/src/cognition/faculties/self.model.updater.ts +677 -0
  78. package/src/cognition/faculties/semantic.engine/clustering.ts +673 -0
  79. package/src/cognition/faculties/semantic.engine/index.ts +6 -0
  80. package/src/cognition/faculties/semantic.engine/integrator.ts +750 -0
  81. package/src/cognition/faculties/semantic.engine/types.ts +53 -0
  82. package/src/cognition/faculties/sleep.pressure.regulator.ts +262 -0
  83. package/src/cognition/faculties/social.perception.ts +333 -0
  84. package/src/cognition/faculties/spaced.repetition.ts +605 -0
  85. package/src/cognition/faculties/stress.regulator.ts +375 -0
  86. package/src/cognition/faculties/task.switcher.ts +239 -0
  87. package/src/cognition/faculties/theory.of.mind.ts +333 -0
  88. package/src/cognition/faculties/threat.evaluator.ts +312 -0
  89. package/src/cognition/faculties/working.memory.ts +406 -0
  90. package/src/cognition/generative.model.ts +344 -0
  91. package/src/cognition/heartbeat.ts +70 -0
  92. package/src/cognition/index.ts +291 -0
  93. package/src/cognition/instruction.handler.ts +146 -0
  94. package/src/cognition/memory/index.ts +35 -0
  95. package/src/cognition/memory/vector.adapter.ts +316 -0
  96. package/src/cognition/memory/vector.content.ts +47 -0
  97. package/src/cognition/memory/vector.embedder.ts +212 -0
  98. package/src/cognition/memory/vector.index.ts +459 -0
  99. package/src/cognition/memory/vector.types.ts +65 -0
  100. package/src/cognition/orchestrator.ts +142 -0
  101. package/src/cognition/persona.prior.ts +265 -0
  102. package/src/cognition/schema.registry.ts +145 -0
  103. package/src/cognition/senses/audition.engine/engine.ts +976 -0
  104. package/src/cognition/senses/audition.engine/salience.ts +59 -0
  105. package/src/cognition/senses/base.sense.engine.ts +117 -0
  106. package/src/cognition/senses/gustation.engine.ts +24 -0
  107. package/src/cognition/senses/index.ts +172 -0
  108. package/src/cognition/senses/olfaction.engine.ts +24 -0
  109. package/src/cognition/senses/somatosensation.engine.ts +23 -0
  110. package/src/cognition/senses/vision.engine.ts +23 -0
  111. package/src/cognition/types.ts +63 -0
  112. package/src/cognition/utilities/token.tracker.ts +492 -0
  113. package/src/core/abstracts.ts +60 -0
  114. package/src/core/async.engine.ts +539 -0
  115. package/src/core/clock.ts +196 -0
  116. package/src/core/completion.recorder.ts +122 -0
  117. package/src/core/conflict.detector.ts +140 -0
  118. package/src/core/distributed.ts +626 -0
  119. package/src/core/event.bus.ts +292 -0
  120. package/src/core/inbound.recorder.ts +100 -0
  121. package/src/core/index.ts +167 -0
  122. package/src/core/logger.ts +85 -0
  123. package/src/core/metrics.ts +107 -0
  124. package/src/core/orchestrator.ts +625 -0
  125. package/src/core/replay.ts +589 -0
  126. package/src/core/scenario.ts +120 -0
  127. package/src/core/serialization.ts +448 -0
  128. package/src/core/simulation.ts +197 -0
  129. package/src/core/snapshot.manager.ts +293 -0
  130. package/src/core/state.manager.ts +283 -0
  131. package/src/core/types.ts +274 -0
  132. package/src/core/utils.ts +82 -0
  133. package/src/core/wall.clock.ts +23 -0
  134. package/src/extensions/livestream.ext.ts +570 -0
  135. package/src/extensions/time.ext.ts +339 -0
  136. package/src/index.ts +91 -0
  137. package/src/llm/gate.ts +140 -0
  138. package/src/llm/index.ts +716 -0
  139. package/src/llm/summarizer.ts +170 -0
  140. package/src/llm/wire.contracts.ts +67 -0
  141. package/src/pma/eval.ts +651 -0
  142. package/src/pma/index.ts +1082 -0
  143. package/src/profiles/built-in.ts +7 -0
  144. package/src/profiles/companion.ts +28 -0
  145. package/src/profiles/company-brain.ts +54 -0
  146. package/src/profiles/customer-service.ts +30 -0
  147. package/src/profiles/game-npc.ts +20 -0
  148. package/src/profiles/index.ts +42 -0
  149. package/src/profiles/smart-home.ts +34 -0
  150. package/src/runners/coherence.runner.ts +49 -0
  151. package/src/runners/outreach.runner.ts +158 -0
  152. package/src/runners/social.runner.ts +182 -0
  153. package/src/runners/thin-shim.runner.ts +195 -0
  154. package/src/sdk/will.ts +334 -0
  155. package/src/stem/assembly.audit.ts +88 -0
  156. package/src/stem/distribution.ts +203 -0
  157. package/src/stem/guards/identity.coherence.ts +152 -0
  158. package/src/stem/guards/identity.guard.ts +227 -0
  159. package/src/stem/index.ts +1145 -0
  160. package/src/stem/mind.ts +1090 -0
  161. package/src/stem/tracts/ack.reconciler.ts +55 -0
  162. package/src/stem/tracts/biography.writer.ts +190 -0
  163. package/src/stem/tracts/effector.controller.ts +143 -0
  164. package/src/stem/tracts/health.reporter.ts +113 -0
  165. package/src/stem/tracts/inbound.queue.ts +54 -0
  166. package/src/stem/tracts/outbox.controller.ts +167 -0
  167. package/src/stem/tracts/outbox.writer.ts +133 -0
  168. package/src/stem/tracts/pma.controller.ts +109 -0
  169. package/src/stem/tracts/replay.controller.ts +177 -0
  170. package/src/stem/tracts/sensory.controller.ts +168 -0
  171. package/src/stem/tracts/session.logger.ts +157 -0
  172. package/src/stem/tracts/transport/index.ts +38 -0
  173. package/src/stem/tracts/transport/loopback.transport.ts +86 -0
  174. package/src/stem/tracts/transport/socketio.transport.ts +200 -0
  175. package/src/stem/tracts/transport/stream.transport.ts +152 -0
  176. package/src/stem/tracts/transport/types.ts +193 -0
  177. package/src/stem/tracts/transport.controller.ts +380 -0
  178. package/src/types.ts +116 -0
@@ -0,0 +1,292 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/core/event.bus.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ import type { SimulationEvent, SimulationEventBase, SimulationContext, Tick, Timestamp } from '#core/types'
6
+ import { wallClock } from '#core/wall.clock'
7
+
8
+ export type EventHandler<T = unknown> = ( event: SimulationEvent<T>, context: SimulationContext ) => void | Promise<void>
9
+ export type EventFilter = ( event: SimulationEventBase ) => boolean
10
+
11
+ export interface EventBus {
12
+ /**
13
+ * Enqueue an event for dispatch at end of the current tick.
14
+ * Prevents silent corruption from events stamped with tick 0.
15
+ * Callers must explicitly pass the current tick from the orchestrator.
16
+ */
17
+ publish<T>(
18
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
19
+ context: SimulationContext,
20
+ tick: Tick
21
+ ): void
22
+
23
+ /**
24
+ * Enqueue and immediately flush if the queue is below the sync threshold.
25
+ * Useful outside of a managed tick loop.
26
+ */
27
+ publishAsync<T>(
28
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
29
+ context: SimulationContext,
30
+ tick: Tick
31
+ ): Promise<void>
32
+
33
+ /**
34
+ * Schedule an event to be injected into the pending queue at a future tick.
35
+ * The Orchestrator calls prepareTick() each tick to drain due events.
36
+ */
37
+ scheduleAt<T>(
38
+ scheduledTick: Tick,
39
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
40
+ context: SimulationContext
41
+ ): void
42
+
43
+ /**
44
+ * Move all scheduled events whose tick ≤ currentTick into the pending queue.
45
+ * Called by the Orchestrator at the start of each tick, before engines run.
46
+ */
47
+ prepareTick( currentTick: Tick ): void
48
+
49
+ /**
50
+ * Drain and dispatch all pending events synchronously (within the current
51
+ * async frame). Called by the Orchestrator at end of each tick, after all
52
+ * commands have been applied.
53
+ */
54
+ flush(): Promise<void>
55
+
56
+ subscribe<T>( eventType: string, handler: EventHandler<T> ): () => void
57
+ subscribeFiltered( filter: EventFilter, handler: EventHandler ): () => void
58
+ subscribeAll( handler: EventHandler ): () => void
59
+
60
+ clear(): void
61
+ getPendingCount(): number
62
+ }
63
+
64
+ export interface EventBusConfig {
65
+ maxQueueSize?: number
66
+ syncThreshold?: number
67
+ /**
68
+ * Sim-time source for event timestamps. Events land in the event log, so the
69
+ * timestamp must come from the sim clock (not wall time) for replay fidelity
70
+ * (R2). Defaults to `wallClock` for standalone/non-orchestrated use; the
71
+ * Simulation wires this to `clock.now`.
72
+ */
73
+ now?: () => Timestamp
74
+ }
75
+
76
+ // ── Internal types ───────────────────────────────────────────
77
+
78
+ interface PendingEntry {
79
+ event: SimulationEvent
80
+ context: SimulationContext
81
+ }
82
+
83
+ interface ScheduledEntry {
84
+ tick: Tick
85
+ event: SimulationEvent
86
+ context: SimulationContext
87
+ }
88
+
89
+ // ── Implementation ───────────────────────────────────────────
90
+
91
+ export class DefaultEventBus implements EventBus {
92
+ private _handlers = new Map<string, Set<EventHandler>>()
93
+ private _filteredHandlers = new Map<EventFilter, Set<EventHandler>>()
94
+ private _allHandlers = new Set<EventHandler>()
95
+ private _pendingEvents: PendingEntry[] = []
96
+ private _scheduledEvents: ScheduledEntry[] = [] // sorted ascending by tick
97
+ private _isProcessing = false
98
+ private _maxQueueSize: number
99
+ private _syncThreshold: number
100
+ private _now: () => Timestamp
101
+ // Monotonic event-id counter. Event ids land in the replay stream, so they
102
+ // must be deterministic across identical runs for byte-identical replay (R2);
103
+ // a per-bus counter incremented in publish/schedule order replaces randomUUID().
104
+ private _eventSeq = 0
105
+
106
+ constructor( config: EventBusConfig = {} ){
107
+ this._maxQueueSize = config.maxQueueSize ?? 10000
108
+ this._syncThreshold = config.syncThreshold ?? 100
109
+ this._now = config.now ?? wallClock
110
+ }
111
+
112
+ // ── Publish ─────────────────────────────────────────────
113
+
114
+ /**
115
+ * Events are always stamped with the caller-provided tick
116
+ * to prevent default-to-zero bugs.
117
+ */
118
+ publish<T>(
119
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
120
+ context: SimulationContext,
121
+ tick: Tick
122
+ ): void {
123
+ const fullEvent = this._stamp<T>( event, tick )
124
+ this._enqueue( fullEvent, context )
125
+ }
126
+
127
+ async publishAsync<T>(
128
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
129
+ context: SimulationContext,
130
+ tick: Tick
131
+ ): Promise<void> {
132
+ const fullEvent = this._stamp<T>( event, tick )
133
+ this._enqueue( fullEvent, context )
134
+
135
+ this._pendingEvents.length <= this._syncThreshold && await this.flush()
136
+ }
137
+
138
+ private _stamp<T>(
139
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
140
+ tick: Tick
141
+ ): SimulationEvent<T> {
142
+ return {
143
+ ...event,
144
+ id: `evt-${this._eventSeq++}`,
145
+ timestamp: this._now(),
146
+ tick,
147
+ } as SimulationEvent<T>
148
+ }
149
+
150
+ private _enqueue( event: SimulationEvent, context: SimulationContext ): void {
151
+ if( this._pendingEvents.length >= this._maxQueueSize )
152
+ throw new Error(`Event bus queue full (${this._maxQueueSize}). Dropping event: ${event.type}`)
153
+
154
+ this._pendingEvents.push({ event, context })
155
+
156
+ // Trigger async processing for standalone (non-orchestrated) use.
157
+ // When the Orchestrator is driving ticks it calls flush() explicitly;
158
+ // the setImmediate fires after that and finds an empty queue — no-op.
159
+ !this._isProcessing && setImmediate( () => { this._processBackground() } )
160
+ }
161
+
162
+ // ── Future-event priority queue ─────────────────────────
163
+
164
+ scheduleAt<T>(
165
+ scheduledTick: Tick,
166
+ event: Omit<SimulationEvent<T>, 'id' | 'timestamp' | 'tick'>,
167
+ context: SimulationContext
168
+ ): void {
169
+ const fullEvent: SimulationEvent<T> = {
170
+ ...event,
171
+ id: `evt-${this._eventSeq++}`,
172
+ timestamp: this._now(),
173
+ tick: scheduledTick,
174
+ } as SimulationEvent<T>
175
+
176
+ // Binary-search insertion to maintain ascending tick order — O(log n)
177
+ const entry: ScheduledEntry = { tick: scheduledTick, event: fullEvent, context }
178
+ let lo = 0, hi = this._scheduledEvents.length
179
+
180
+ while( lo < hi ){
181
+ const mid = ( lo + hi ) >>> 1
182
+ this._scheduledEvents[mid]!.tick <= scheduledTick ? lo = mid + 1 : hi = mid
183
+ }
184
+
185
+ this._scheduledEvents.splice( lo, 0, entry )
186
+ }
187
+
188
+ prepareTick( currentTick: Tick ): void {
189
+ // Find the first entry beyond the current tick — O(log n) scan
190
+ let i = 0
191
+ while( i < this._scheduledEvents.length && this._scheduledEvents[i]!.tick <= currentTick )
192
+ i++
193
+
194
+ if( i === 0 ) return
195
+
196
+ // Move due events into the pending queue (preserving scheduled tick)
197
+ const due = this._scheduledEvents.splice( 0, i )
198
+ for( const entry of due )
199
+ this._pendingEvents.push({ event: entry.event, context: entry.context })
200
+ }
201
+
202
+ // ── Flush ───────────────────────────────────────────────
203
+
204
+ async flush(): Promise<void> {
205
+ await this._process()
206
+ }
207
+
208
+ /**
209
+ * Background processing — triggered via setImmediate for standalone use.
210
+ * Silently swallows errors to avoid unhandled-rejection noise in that path.
211
+ */
212
+ private _processBackground(): void {
213
+ this._process().catch( () => {} )
214
+ }
215
+
216
+ private async _process(): Promise<void> {
217
+ if( this._isProcessing ) return
218
+ if( this._pendingEvents.length === 0 ) return
219
+
220
+ this._isProcessing = true
221
+
222
+ try {
223
+ // Loop so that events published by handlers in the same flush are
224
+ // dispatched before we yield back to the caller.
225
+ while( this._pendingEvents.length > 0 ){
226
+ const batch = this._pendingEvents.splice( 0 )
227
+ for( const { event, context } of batch )
228
+ await this._dispatch( event, context )
229
+ }
230
+ }
231
+ finally {
232
+ this._isProcessing = false
233
+ }
234
+ }
235
+
236
+ private async _dispatch( event: SimulationEvent, context: SimulationContext ): Promise<void> {
237
+ // Type-specific handlers
238
+ const handlers = this._handlers.get( event.type )
239
+ if( handlers )
240
+ for( const handler of handlers )
241
+ await handler( event, context )
242
+
243
+ // Filtered handlers
244
+ for( const [ filter, handlersSet ] of this._filteredHandlers )
245
+ filter( event ) && await Promise.all( [ ...handlersSet ].map( h => h( event, context ) ) )
246
+
247
+ // All-catch handlers
248
+ for( const handler of this._allHandlers )
249
+ await handler( event, context )
250
+ }
251
+
252
+ // ── Subscriptions ────────────────────────────────────────
253
+
254
+ subscribe<T>( eventType: string, handler: EventHandler<T> ): () => void {
255
+ !this._handlers.has( eventType ) && this._handlers.set( eventType, new Set() )
256
+ this._handlers.get( eventType )!.add( handler as EventHandler )
257
+
258
+ return () => {
259
+ this._handlers.get( eventType )?.delete( handler as EventHandler )
260
+ this._handlers.get( eventType )?.size === 0 && this._handlers.delete( eventType )
261
+ }
262
+ }
263
+
264
+ subscribeFiltered( filter: EventFilter, handler: EventHandler ): () => void {
265
+ !this._filteredHandlers.has( filter ) && this._filteredHandlers.set( filter, new Set() )
266
+ this._filteredHandlers.get( filter )!.add( handler )
267
+
268
+ return () => {
269
+ this._filteredHandlers.get( filter )?.delete( handler )
270
+ this._filteredHandlers.get( filter )?.size === 0 && this._filteredHandlers.delete( filter )
271
+ }
272
+ }
273
+
274
+ subscribeAll( handler: EventHandler ): () => void {
275
+ this._allHandlers.add( handler )
276
+ return () => { this._allHandlers.delete( handler ) }
277
+ }
278
+
279
+ // ── Housekeeping ─────────────────────────────────────────
280
+
281
+ clear(): void {
282
+ this._handlers.clear()
283
+ this._filteredHandlers.clear()
284
+ this._allHandlers.clear()
285
+ this._pendingEvents = []
286
+ this._scheduledEvents = []
287
+ }
288
+
289
+ getPendingCount(): number {
290
+ return this._pendingEvents.length
291
+ }
292
+ }
@@ -0,0 +1,100 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/core/inbound.recorder.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // External-inbound record/replay seam (REORIENT R2, transport edition).
6
+ //
7
+ // The ExternalTransport is a non-deterministic input, exactly like the LLM:
8
+ // to re-run a session deterministically the recorder must capture every inbound
9
+ // envelope (messages, percepts, acks) at the tick it was applied. On replay a
10
+ // *source* re-feeds those recorded envelopes instead of waiting on a live socket.
11
+ //
12
+ // This mirrors completion.recorder.ts: a capture sink (recordInbound) and a
13
+ // re-feed source, both keyed by willId. Deterministic re-execution itself is
14
+ // still deferred — this completes the capture half so it lands ready.
15
+ //
16
+ // `envelope` is `unknown` on purpose: this is `#core` and must not depend on the
17
+ // `#stem` transport types. It round-trips as JSON.
18
+ // ─────────────────────────────────────────────────────────────
19
+
20
+ import type { Tick, Timestamp } from '#core/types'
21
+
22
+ export interface InboundRecord {
23
+ tick: Tick
24
+ willId: string
25
+ /** The InboundEnvelope as applied (opaque here to avoid a #stem dependency). */
26
+ envelope: unknown
27
+ timestamp: Timestamp
28
+ }
29
+
30
+ export interface InboundSink {
31
+ recordInbound( record: InboundRecord ): void
32
+ }
33
+
34
+ // ── Capture sink ─────────────────────────────────────────────
35
+
36
+ const _sinks = new Map<string, InboundSink>()
37
+
38
+ export function setInboundRecorder( willId: string, sink: InboundSink ): void {
39
+ _sinks.set( willId, sink )
40
+ }
41
+
42
+ export function clearInboundRecorder( willId: string ): void {
43
+ _sinks.delete( willId )
44
+ }
45
+
46
+ export function getInboundRecorder( willId: string ): InboundSink | undefined {
47
+ return _sinks.get( willId )
48
+ }
49
+
50
+ // ── Replay re-feed source (deferred re-execution) ────────────
51
+
52
+ /**
53
+ * Supplies recorded inbound envelopes back during a deterministic re-execution
54
+ * replay, keyed by willId. Returns the envelopes recorded at `tick` (empty if
55
+ * none). Registered only while replaying; absent during live runs.
56
+ */
57
+ export interface InboundSource {
58
+ envelopesAt( tick: Tick ): unknown[]
59
+ }
60
+
61
+ /**
62
+ * Re-feed source backed by recorded inbound. Groups envelopes by their applied
63
+ * tick (FIFO within a tick, preserving record order) and hands them back once.
64
+ * Unlike the LLM source, a tick with no recorded inbound is normal (most ticks),
65
+ * so a miss returns `[]` rather than throwing — only an upstream LLM/clock/PRNG
66
+ * divergence (caught by their own sources) can invalidate the replay.
67
+ */
68
+ export class RecordedInboundSource implements InboundSource {
69
+ private readonly _byTick = new Map<Tick, unknown[]>()
70
+
71
+ constructor( records: readonly InboundRecord[] ){
72
+ for( const r of records ){
73
+ const queue = this._byTick.get( r.tick )
74
+ if( queue ) queue.push( r.envelope )
75
+ else this._byTick.set( r.tick, [ r.envelope ] )
76
+ }
77
+ }
78
+
79
+ envelopesAt( tick: Tick ): unknown[] {
80
+ const queue = this._byTick.get( tick )
81
+ if( !queue || queue.length === 0 ) return []
82
+ // Consume so a tick is never re-fed twice within one replay.
83
+ this._byTick.set( tick, [] )
84
+ return queue
85
+ }
86
+ }
87
+
88
+ const _sources = new Map<string, InboundSource>()
89
+
90
+ export function setInboundSource( willId: string, source: InboundSource ): void {
91
+ _sources.set( willId, source )
92
+ }
93
+
94
+ export function clearInboundSource( willId: string ): void {
95
+ _sources.delete( willId )
96
+ }
97
+
98
+ export function getInboundSource( willId: string ): InboundSource | undefined {
99
+ return _sources.get( willId )
100
+ }
@@ -0,0 +1,167 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/index.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ import { type ClockConfig, DefaultSimulationClock, type SimulationClock } from '#core/clock'
6
+ import type { Coordinates, Duration, SimulationContext, SimulationEntity, SimulationEvent, SimulationEventBase, EventPayload, SimulationState, Tick, Timestamp, MinimalContext, RestoreOptions } from '#core/types'
7
+ import { DefaultOrchestrator, type Orchestrator, type OrchestratorConfig, type SimulationEngine, type EngineResult } from '#core/orchestrator'
8
+ import { DefaultEventBus, type EventBus, type EventBusConfig, type EventFilter, type EventHandler } from '#core/event.bus'
9
+ import { DefaultScenario, type Scenario, type ScenarioConfig, type ScenarioValidationResult } from '#core/scenario'
10
+ import { DefaultMetricCollector, type MetricCollector, type MetricPoint } from '#core/metrics'
11
+ import { DefaultSimulation, type Simulation, type SimulationConfig } from '#core/simulation'
12
+ import { DefaultStateManager, type StateManager } from '#core/state.manager'
13
+ import { createContext, createPRNG } from '#core/utils'
14
+
15
+ // New exports
16
+ export {
17
+ DefaultSerializer,
18
+ DeltaEncoder,
19
+ type Serializer,
20
+ type SerializationConfig,
21
+ type SerializationFormat,
22
+ type SerializedState,
23
+ type SerializedEntity,
24
+ type DeltaSnapshot
25
+ } from '#core/serialization'
26
+
27
+ export {
28
+ DefaultPartitionRouter,
29
+ ConsistentHashRouter,
30
+ DistributedStateManager,
31
+ DistributedOrchestrator,
32
+ LocalTransport,
33
+ type DistributedNode,
34
+ type DistributedNodeConfig,
35
+ type ShardConfig,
36
+ type ShardStrategy,
37
+ type PartitionRouter,
38
+ type CrossShardTransport,
39
+ type CrossShardQuery,
40
+ type CrossShardResult,
41
+ type DistributedEvent,
42
+ type DeliveryGuarantee
43
+ } from '#core/distributed'
44
+
45
+ export {
46
+ DefaultReplayRecorder,
47
+ DefaultReplaySession,
48
+ ReplayManager,
49
+ type ReplayRecord,
50
+ type ReplayMetadata,
51
+ type ReplaySession,
52
+ type ReplayRecorder,
53
+ type ReplayConfig,
54
+ type ReplayComparison,
55
+ type ReplayDifference
56
+ } from '#core/replay'
57
+
58
+ export {
59
+ setCompletionRecorder,
60
+ clearCompletionRecorder,
61
+ getCompletionRecorder,
62
+ type LLMCompletionRecord,
63
+ type LLMCompletionSink
64
+ } from '#core/completion.recorder'
65
+
66
+ // Injectable diagnostic logger
67
+ export {
68
+ logger,
69
+ setLogger,
70
+ resetLogger,
71
+ getLogger,
72
+ ConsoleLogger,
73
+ SilentLogger,
74
+ type Logger
75
+ } from '#core/logger'
76
+
77
+ // Core exports
78
+ export {
79
+ DefaultSimulation,
80
+ type Simulation,
81
+ type SimulationConfig,
82
+ }
83
+
84
+ export {
85
+ DefaultSimulationClock,
86
+ type SimulationClock,
87
+ type ClockConfig
88
+ }
89
+
90
+ export {
91
+ DefaultEventBus,
92
+ type EventBus,
93
+ type EventBusConfig,
94
+ type EventHandler,
95
+ type EventFilter
96
+ }
97
+
98
+ export {
99
+ DefaultStateManager,
100
+ type StateManager
101
+ }
102
+
103
+ export {
104
+ DefaultOrchestrator,
105
+ type Orchestrator,
106
+ type OrchestratorConfig,
107
+ type SimulationEngine,
108
+ type EngineResult,
109
+ }
110
+
111
+ export {
112
+ DefaultScenario,
113
+ type Scenario,
114
+ type ScenarioConfig,
115
+ type ScenarioValidationResult
116
+ }
117
+
118
+ export {
119
+ DefaultMetricCollector,
120
+ type MetricCollector,
121
+ type MetricPoint
122
+ }
123
+
124
+ // Storage abstractions
125
+ export {
126
+ BunStorageAdapter,
127
+ type StorageAdapter
128
+ } from '#core/abstracts'
129
+
130
+ // Utility functions
131
+ export {
132
+ createContext,
133
+ createPRNG
134
+ }
135
+
136
+ // Types
137
+ export type {
138
+ Timestamp,
139
+ Duration,
140
+ Tick,
141
+ Coordinates,
142
+ SimulationContext,
143
+ SimulationEntity,
144
+ SimulationEvent,
145
+ SimulationEventBase,
146
+ EventPayload,
147
+ SimulationState,
148
+ MinimalContext,
149
+ RestoreOptions
150
+ }
151
+
152
+ export {
153
+ AsyncEngine,
154
+ } from '#core/async.engine'
155
+
156
+ export {
157
+ ConflictDetector,
158
+ } from '#core/conflict.detector'
159
+
160
+ // In the types section, add:
161
+ export type {
162
+ ReasoningFootprint,
163
+ ConflictReport,
164
+ ConflictResolution,
165
+ ConflictStrategy,
166
+ AsyncEngineConfig,
167
+ } from '#core/types'
@@ -0,0 +1,85 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/core/logger.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ /**
6
+ * Injectable diagnostic logger for the Will library.
7
+ *
8
+ * Will is embedded inside a host process (the API server, the dev runner,
9
+ * tests). A library has no business deciding where diagnostic output goes,
10
+ * so every internal `console.*` call routes through this seam instead. The
11
+ * host installs its own sink once at startup via `setLogger()`; everything
12
+ * downstream calls `logger.info()/warn()/error()/debug()` and never touches
13
+ * `console` directly.
14
+ *
15
+ * This is deliberately NOT the same thing as `SessionLogger` (stem/tracts),
16
+ * which writes the structured NDJSON cognitive event stream. This logger is
17
+ * for unstructured operational diagnostics — "rate limited, retrying",
18
+ * "S3 upload failed", "engine X skipped" — the lines that used to be
19
+ * `console.warn`.
20
+ *
21
+ * Default behaviour is identical to the previous direct `console.*` usage:
22
+ * `ConsoleLogger` forwards each level to the matching console method, so
23
+ * installing nothing changes nothing.
24
+ *
25
+ * Usage:
26
+ * import { logger } from '#core/logger'
27
+ * logger.warn('[LLMGate] rate limited — retrying')
28
+ *
29
+ * // host, once at startup:
30
+ * import { setLogger } from 'will'
31
+ * setLogger(myStructuredLogger)
32
+ */
33
+
34
+ export interface Logger {
35
+ debug( message?: unknown, ...args: unknown[] ): void
36
+ info ( message?: unknown, ...args: unknown[] ): void
37
+ warn ( message?: unknown, ...args: unknown[] ): void
38
+ error( message?: unknown, ...args: unknown[] ): void
39
+ }
40
+
41
+ /**
42
+ * Default sink: forwards to the global console. `debug` → console.debug,
43
+ * `info` → console.info (stdout, same channel as the old console.log calls),
44
+ * `warn`/`error` → their console equivalents (stderr). Behaviour matches the
45
+ * pre-refactor direct console usage exactly.
46
+ */
47
+ export class ConsoleLogger implements Logger {
48
+ debug( message?: unknown, ...args: unknown[] ): void { console.debug( message, ...args ) }
49
+ info ( message?: unknown, ...args: unknown[] ): void { console.info ( message, ...args ) }
50
+ warn ( message?: unknown, ...args: unknown[] ): void { console.warn ( message, ...args ) }
51
+ error( message?: unknown, ...args: unknown[] ): void { console.error( message, ...args ) }
52
+ }
53
+
54
+ /**
55
+ * No-op sink — useful for tests or hosts that want Will to stay silent.
56
+ */
57
+ export class SilentLogger implements Logger {
58
+ debug(): void {}
59
+ info (): void {}
60
+ warn (): void {}
61
+ error(): void {}
62
+ }
63
+
64
+ // Module-level current logger. Mutable so a host can swap it once at startup.
65
+ let _logger: Logger = new ConsoleLogger()
66
+
67
+ /**
68
+ * Stable indirection object. Callers import this and call `logger.info(...)`;
69
+ * `setLogger()` re-points the underlying sink without callers re-importing.
70
+ */
71
+ export const logger: Logger = {
72
+ debug: ( message?: unknown, ...args: unknown[] ) => _logger.debug( message, ...args ),
73
+ info : ( message?: unknown, ...args: unknown[] ) => _logger.info ( message, ...args ),
74
+ warn : ( message?: unknown, ...args: unknown[] ) => _logger.warn ( message, ...args ),
75
+ error: ( message?: unknown, ...args: unknown[] ) => _logger.error( message, ...args ),
76
+ }
77
+
78
+ /** Install a custom sink for all subsequent Will diagnostic logging. */
79
+ export function setLogger( next: Logger ): void { _logger = next }
80
+
81
+ /** Reset to the default console sink. Primarily for tests. */
82
+ export function resetLogger(): void { _logger = new ConsoleLogger() }
83
+
84
+ /** The currently-installed sink (the real object, not the indirection). */
85
+ export function getLogger(): Logger { return _logger }