@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.
- package/LICENSE +202 -0
- package/README.md +777 -0
- package/dist/index.d.ts +8144 -0
- package/dist/index.js +26231 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
- package/src/cognition/agency/access.grants.ts +59 -0
- package/src/cognition/agency/competence.codec.ts +89 -0
- package/src/cognition/agency/engines/action.selector.ts +462 -0
- package/src/cognition/agency/engines/affordance.synthesizer.ts +384 -0
- package/src/cognition/agency/engines/deliberation.engine.ts +241 -0
- package/src/cognition/agency/engines/instruction.intake.ts +54 -0
- package/src/cognition/agency/engines/motor.schema.executor.ts +532 -0
- package/src/cognition/agency/engines/reafference.engine.ts +241 -0
- package/src/cognition/agency/execution.primitives.ts +118 -0
- package/src/cognition/agency/index.ts +58 -0
- package/src/cognition/agency/proactive.communicator.ts +274 -0
- package/src/cognition/agency/reconcile.learning.ts +82 -0
- package/src/cognition/agency/schemas/external.ts +59 -0
- package/src/cognition/agency/schemas/innate.ts +111 -0
- package/src/cognition/agency/schemas/repertoire.ts +246 -0
- package/src/cognition/agency/selection.scoring.ts +191 -0
- package/src/cognition/agency/types.ts +165 -0
- package/src/cognition/bus.ts +391 -0
- package/src/cognition/completion.inbox.ts +86 -0
- package/src/cognition/config.mirror.entities.ts +475 -0
- package/src/cognition/conversation.memory.ts +81 -0
- package/src/cognition/event.log.ts +116 -0
- package/src/cognition/event.schemas.ts +568 -0
- package/src/cognition/faculties/aesthetic.evaluator.ts +313 -0
- package/src/cognition/faculties/affective.blender.ts +562 -0
- package/src/cognition/faculties/attachment.evaluator.ts +432 -0
- package/src/cognition/faculties/attention.allocator.ts +422 -0
- package/src/cognition/faculties/autobiographical.narrator.ts +300 -0
- package/src/cognition/faculties/bias.detector.ts +363 -0
- package/src/cognition/faculties/circadian.oscillator.ts +294 -0
- package/src/cognition/faculties/confidence.calibrator.ts +324 -0
- package/src/cognition/faculties/dream.simulator.ts +251 -0
- package/src/cognition/faculties/empathy.simulator.ts +253 -0
- package/src/cognition/faculties/energy.regulator.ts +320 -0
- package/src/cognition/faculties/episodic.consolidator.ts +728 -0
- package/src/cognition/faculties/executive.engine/commands.ts +459 -0
- package/src/cognition/faculties/executive.engine/config.ts +46 -0
- package/src/cognition/faculties/executive.engine/context.ts +605 -0
- package/src/cognition/faculties/executive.engine/deferred.effects.ts +104 -0
- package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +60 -0
- package/src/cognition/faculties/executive.engine/effort.gate.ts +114 -0
- package/src/cognition/faculties/executive.engine/engine.ts +1028 -0
- package/src/cognition/faculties/executive.engine/escalation.buffer.ts +90 -0
- package/src/cognition/faculties/executive.engine/facet.supervisor.ts +271 -0
- package/src/cognition/faculties/executive.engine/facet.ts +628 -0
- package/src/cognition/faculties/executive.engine/gating.ts +222 -0
- package/src/cognition/faculties/executive.engine/index.ts +6 -0
- package/src/cognition/faculties/executive.engine/messages.ts +102 -0
- package/src/cognition/faculties/executive.engine/parser.ts +380 -0
- package/src/cognition/faculties/executive.engine/prompt.factory.ts +1053 -0
- package/src/cognition/faculties/executive.engine/types.ts +323 -0
- package/src/cognition/faculties/exteroception.ts +338 -0
- package/src/cognition/faculties/forgetting.curve.ts +202 -0
- package/src/cognition/faculties/frustration.evaluator.ts +280 -0
- package/src/cognition/faculties/goal.manager.ts +1008 -0
- package/src/cognition/faculties/inhibition.controller.ts +351 -0
- package/src/cognition/faculties/interoception.ts +417 -0
- package/src/cognition/faculties/introspection.engine.ts +246 -0
- package/src/cognition/faculties/known.entity.tracker.ts +439 -0
- package/src/cognition/faculties/loss.evaluator.ts +224 -0
- package/src/cognition/faculties/moral.evaluator.ts +437 -0
- package/src/cognition/faculties/novelty.detector.ts +254 -0
- package/src/cognition/faculties/persona.consolidator.ts +845 -0
- package/src/cognition/faculties/planning.engine/engine.ts +859 -0
- package/src/cognition/faculties/planning.engine/plan.frontier.ts +83 -0
- package/src/cognition/faculties/planning.engine/plan.store.ts +174 -0
- package/src/cognition/faculties/planning.engine/plan.supervision.ts +494 -0
- package/src/cognition/faculties/planning.engine/types.ts +143 -0
- package/src/cognition/faculties/reputation.tracker.ts +294 -0
- package/src/cognition/faculties/reward.evaluator.ts +304 -0
- package/src/cognition/faculties/self.model.updater.ts +677 -0
- package/src/cognition/faculties/semantic.engine/clustering.ts +673 -0
- package/src/cognition/faculties/semantic.engine/index.ts +6 -0
- package/src/cognition/faculties/semantic.engine/integrator.ts +750 -0
- package/src/cognition/faculties/semantic.engine/types.ts +53 -0
- package/src/cognition/faculties/sleep.pressure.regulator.ts +262 -0
- package/src/cognition/faculties/social.perception.ts +333 -0
- package/src/cognition/faculties/spaced.repetition.ts +605 -0
- package/src/cognition/faculties/stress.regulator.ts +375 -0
- package/src/cognition/faculties/task.switcher.ts +239 -0
- package/src/cognition/faculties/theory.of.mind.ts +333 -0
- package/src/cognition/faculties/threat.evaluator.ts +312 -0
- package/src/cognition/faculties/working.memory.ts +406 -0
- package/src/cognition/generative.model.ts +344 -0
- package/src/cognition/heartbeat.ts +70 -0
- package/src/cognition/index.ts +291 -0
- package/src/cognition/instruction.handler.ts +146 -0
- package/src/cognition/memory/index.ts +35 -0
- package/src/cognition/memory/vector.adapter.ts +316 -0
- package/src/cognition/memory/vector.content.ts +47 -0
- package/src/cognition/memory/vector.embedder.ts +212 -0
- package/src/cognition/memory/vector.index.ts +459 -0
- package/src/cognition/memory/vector.types.ts +65 -0
- package/src/cognition/orchestrator.ts +142 -0
- package/src/cognition/persona.prior.ts +265 -0
- package/src/cognition/schema.registry.ts +145 -0
- package/src/cognition/senses/audition.engine/engine.ts +976 -0
- package/src/cognition/senses/audition.engine/salience.ts +59 -0
- package/src/cognition/senses/base.sense.engine.ts +117 -0
- package/src/cognition/senses/gustation.engine.ts +24 -0
- package/src/cognition/senses/index.ts +172 -0
- package/src/cognition/senses/olfaction.engine.ts +24 -0
- package/src/cognition/senses/somatosensation.engine.ts +23 -0
- package/src/cognition/senses/vision.engine.ts +23 -0
- package/src/cognition/types.ts +63 -0
- package/src/cognition/utilities/token.tracker.ts +492 -0
- package/src/core/abstracts.ts +60 -0
- package/src/core/async.engine.ts +539 -0
- package/src/core/clock.ts +196 -0
- package/src/core/completion.recorder.ts +122 -0
- package/src/core/conflict.detector.ts +140 -0
- package/src/core/distributed.ts +626 -0
- package/src/core/event.bus.ts +292 -0
- package/src/core/inbound.recorder.ts +100 -0
- package/src/core/index.ts +167 -0
- package/src/core/logger.ts +85 -0
- package/src/core/metrics.ts +107 -0
- package/src/core/orchestrator.ts +625 -0
- package/src/core/replay.ts +589 -0
- package/src/core/scenario.ts +120 -0
- package/src/core/serialization.ts +448 -0
- package/src/core/simulation.ts +197 -0
- package/src/core/snapshot.manager.ts +293 -0
- package/src/core/state.manager.ts +283 -0
- package/src/core/types.ts +274 -0
- package/src/core/utils.ts +82 -0
- package/src/core/wall.clock.ts +23 -0
- package/src/extensions/livestream.ext.ts +570 -0
- package/src/extensions/time.ext.ts +339 -0
- package/src/index.ts +91 -0
- package/src/llm/gate.ts +140 -0
- package/src/llm/index.ts +716 -0
- package/src/llm/summarizer.ts +170 -0
- package/src/llm/wire.contracts.ts +67 -0
- package/src/pma/eval.ts +651 -0
- package/src/pma/index.ts +1082 -0
- package/src/profiles/built-in.ts +7 -0
- package/src/profiles/companion.ts +28 -0
- package/src/profiles/company-brain.ts +54 -0
- package/src/profiles/customer-service.ts +30 -0
- package/src/profiles/game-npc.ts +20 -0
- package/src/profiles/index.ts +42 -0
- package/src/profiles/smart-home.ts +34 -0
- package/src/runners/coherence.runner.ts +49 -0
- package/src/runners/outreach.runner.ts +158 -0
- package/src/runners/social.runner.ts +182 -0
- package/src/runners/thin-shim.runner.ts +195 -0
- package/src/sdk/will.ts +334 -0
- package/src/stem/assembly.audit.ts +88 -0
- package/src/stem/distribution.ts +203 -0
- package/src/stem/guards/identity.coherence.ts +152 -0
- package/src/stem/guards/identity.guard.ts +227 -0
- package/src/stem/index.ts +1145 -0
- package/src/stem/mind.ts +1090 -0
- package/src/stem/tracts/ack.reconciler.ts +55 -0
- package/src/stem/tracts/biography.writer.ts +190 -0
- package/src/stem/tracts/effector.controller.ts +143 -0
- package/src/stem/tracts/health.reporter.ts +113 -0
- package/src/stem/tracts/inbound.queue.ts +54 -0
- package/src/stem/tracts/outbox.controller.ts +167 -0
- package/src/stem/tracts/outbox.writer.ts +133 -0
- package/src/stem/tracts/pma.controller.ts +109 -0
- package/src/stem/tracts/replay.controller.ts +177 -0
- package/src/stem/tracts/sensory.controller.ts +168 -0
- package/src/stem/tracts/session.logger.ts +157 -0
- package/src/stem/tracts/transport/index.ts +38 -0
- package/src/stem/tracts/transport/loopback.transport.ts +86 -0
- package/src/stem/tracts/transport/socketio.transport.ts +200 -0
- package/src/stem/tracts/transport/stream.transport.ts +152 -0
- package/src/stem/tracts/transport/types.ts +193 -0
- package/src/stem/tracts/transport.controller.ts +380 -0
- package/src/types.ts +116 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/core/types.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core simulation framework types — completely generic.
|
|
7
|
+
* No logistics, mobility, or domain concepts here.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type Timestamp = number // milliseconds since epoch
|
|
11
|
+
export type Duration = number // milliseconds
|
|
12
|
+
export type Tick = number // discrete simulation step
|
|
13
|
+
|
|
14
|
+
export interface Coordinates {
|
|
15
|
+
x: number
|
|
16
|
+
y: number
|
|
17
|
+
z?: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ── PRNG ─────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Seeded pseudo-random number generator (Mulberry32).
|
|
24
|
+
* Provides deterministic randomness for simulation replay.
|
|
25
|
+
* All engines should draw from SimulationContext.prng rather
|
|
26
|
+
* than Math.random() to guarantee replay fidelity.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export interface SeededPRNG {
|
|
30
|
+
/** Returns a float in [0, 1) */
|
|
31
|
+
next(): number
|
|
32
|
+
/** Returns an integer in [min, max) */
|
|
33
|
+
nextInt( min: number, max: number ): number
|
|
34
|
+
/** Returns true with the given probability (default 0.5) */
|
|
35
|
+
nextBool( probability?: number ): boolean
|
|
36
|
+
/** Current internal seed state — useful for snapshotting */
|
|
37
|
+
readonly state: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── Deep readonly utility ────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Recursively marks every property, Map, Set, and Array as readonly.
|
|
44
|
+
* Used to enforce the double-buffer contract: engines receive a frozen
|
|
45
|
+
* snapshot and may only produce changes via StateCommands.
|
|
46
|
+
*/
|
|
47
|
+
export type ReadonlyDeep<T> =
|
|
48
|
+
T extends ( infer U )[]
|
|
49
|
+
? ReadonlyArray<ReadonlyDeep<U>>
|
|
50
|
+
: T extends Map<infer K, infer V>
|
|
51
|
+
? ReadonlyMap<K, ReadonlyDeep<V>>
|
|
52
|
+
: T extends Set<infer U>
|
|
53
|
+
? ReadonlySet<ReadonlyDeep<U>>
|
|
54
|
+
: T extends object
|
|
55
|
+
? { readonly [K in keyof T]: ReadonlyDeep<T[K]> }
|
|
56
|
+
: T
|
|
57
|
+
|
|
58
|
+
// ── Event type system (discriminated union) ──────────────────
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Base interface that all simulation events extend.
|
|
62
|
+
* The 'type' field acts as a discriminated union key.
|
|
63
|
+
*/
|
|
64
|
+
export interface SimulationEventBase {
|
|
65
|
+
id: string
|
|
66
|
+
type: string
|
|
67
|
+
timestamp: Timestamp
|
|
68
|
+
tick: Tick
|
|
69
|
+
source: string
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Typed simulation event with payload and metadata.
|
|
74
|
+
* T = payload type, M = metadata type.
|
|
75
|
+
*/
|
|
76
|
+
export interface SimulationEvent<T = unknown, M = Record<string, unknown>> extends SimulationEventBase {
|
|
77
|
+
payload: T
|
|
78
|
+
metadata?: M
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Helper to extract payload type from a specific event type string.
|
|
83
|
+
* Usage: type MyPayload = EventPayload<'entity.created'>
|
|
84
|
+
*/
|
|
85
|
+
export type EventPayload<
|
|
86
|
+
T extends string,
|
|
87
|
+
E extends SimulationEvent = SimulationEvent
|
|
88
|
+
> = E extends { type: T; payload: infer P } ? P : never
|
|
89
|
+
|
|
90
|
+
// ── Core domain types ────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
export interface SimulationContext {
|
|
93
|
+
simulationId: string
|
|
94
|
+
runId: string
|
|
95
|
+
tags: Record<string, string>
|
|
96
|
+
/**
|
|
97
|
+
* Seeded PRNG for deterministic randomness.
|
|
98
|
+
* Engines must use this instead of Math.random() to guarantee
|
|
99
|
+
* that a run is fully reproducible from the same seed.
|
|
100
|
+
*/
|
|
101
|
+
prng: SeededPRNG
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface SimulationEntity {
|
|
105
|
+
id: string
|
|
106
|
+
type: string
|
|
107
|
+
createdAt: Timestamp
|
|
108
|
+
updatedAt: Timestamp
|
|
109
|
+
/**
|
|
110
|
+
* Sim tick of the last write (stamped by StateManager.setEntity).
|
|
111
|
+
* Distinct from `updatedAt` (wall-clock epoch ms). ConflictDetector compares
|
|
112
|
+
* this tick-vs-tick against a footprint's `tickObserved`; comparing `updatedAt`
|
|
113
|
+
* (ms) to a tick would always register a conflict.
|
|
114
|
+
*/
|
|
115
|
+
updatedAtTick?: Tick
|
|
116
|
+
metadata?: Record<string, unknown>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The write-side shape engines produce for an entity (via StateCommands.set or
|
|
121
|
+
* a direct setEntity call). `createdAt`/`updatedAt`/`updatedAtTick` are optional
|
|
122
|
+
* because StateManager.setEntity is the single authority that stamps them from
|
|
123
|
+
* the sim clock — engines must not supply wall-clock timestamps, which would
|
|
124
|
+
* break replay (R2). A full SimulationEntity is assignable to EntityInput, so
|
|
125
|
+
* existing callers that pass complete entities keep working.
|
|
126
|
+
*/
|
|
127
|
+
export type EntityInput =
|
|
128
|
+
Omit<SimulationEntity, 'createdAt' | 'updatedAt' | 'updatedAtTick'>
|
|
129
|
+
& Partial<Pick<SimulationEntity, 'createdAt' | 'updatedAt' | 'updatedAtTick'>>
|
|
130
|
+
|
|
131
|
+
export interface SimulationState {
|
|
132
|
+
tick: Tick
|
|
133
|
+
time: Timestamp
|
|
134
|
+
entities: Map<string, SimulationEntity>
|
|
135
|
+
metrics: Map<string, number>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Configuration for partial state restore operations.
|
|
140
|
+
* Support selective rollback — entities only,
|
|
141
|
+
* metrics only, or clock state independently.
|
|
142
|
+
*/
|
|
143
|
+
export interface RestoreOptions {
|
|
144
|
+
/** Restore entity state (default: true) */
|
|
145
|
+
entities?: boolean
|
|
146
|
+
/** Restore metric values (default: true) */
|
|
147
|
+
metrics?: boolean
|
|
148
|
+
/** Restore clock tick and time (default: true) */
|
|
149
|
+
clock?: boolean
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The frozen view of SimulationState passed to engines each tick.
|
|
154
|
+
* Engines read from this; writes go through StateCommands only.
|
|
155
|
+
*/
|
|
156
|
+
export type ReadonlySimulationState = ReadonlyDeep<SimulationState>
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The write side of the double-buffer contract.
|
|
160
|
+
* Engines return this from react() instead of mutating state directly.
|
|
161
|
+
* All commands from all engines are applied atomically after every engine
|
|
162
|
+
* has finished reading the frozen snapshot.
|
|
163
|
+
*
|
|
164
|
+
* metrics entries are either:
|
|
165
|
+
* [key, number] — set the metric to an absolute value
|
|
166
|
+
* [key, { delta: number }] — increment by delta (positive or negative)
|
|
167
|
+
*/
|
|
168
|
+
export interface StateCommands {
|
|
169
|
+
set?: EntityInput[]
|
|
170
|
+
delete?: string[]
|
|
171
|
+
metrics?: Array<[ string, number]>
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Used by orchestrator for step/run methods
|
|
175
|
+
export interface MinimalContext {
|
|
176
|
+
simulationId: string
|
|
177
|
+
runId: string
|
|
178
|
+
seed?: number
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Async Reasoning Types ─────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Captures what an async engine observed when it began reasoning.
|
|
185
|
+
* Used by ConflictDetector to validate that the world hasn't changed
|
|
186
|
+
* in ways that invalidate the engine's intended commands.
|
|
187
|
+
*/
|
|
188
|
+
export interface ReasoningFootprint {
|
|
189
|
+
/** The tick when the engine read its snapshot */
|
|
190
|
+
readonly tickObserved: Tick
|
|
191
|
+
/** Entity IDs the engine read during reasoning */
|
|
192
|
+
readonly entitiesRead: ReadonlySet<string>
|
|
193
|
+
/** Metric keys the engine read during reasoning */
|
|
194
|
+
readonly metricsRead: ReadonlySet<string>
|
|
195
|
+
/** Entity IDs the engine intends to modify */
|
|
196
|
+
readonly entitiesModified: ReadonlySet<string>
|
|
197
|
+
/** The commands the engine wants to apply */
|
|
198
|
+
readonly intendedCommands: StateCommands
|
|
199
|
+
/** Optional: engine that produced this footprint (for debugging) */
|
|
200
|
+
readonly source?: string
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface ConflictReport {
|
|
204
|
+
/** Whether any conflicts were detected */
|
|
205
|
+
readonly hasConflicts: boolean
|
|
206
|
+
/** Read conflicts: entities/metrics observed that have since changed */
|
|
207
|
+
readonly readConflicts: string[]
|
|
208
|
+
/** Write conflicts: entities the engine wants to modify that others modified */
|
|
209
|
+
readonly writeConflicts: string[]
|
|
210
|
+
/** The tick when conflict detection ran */
|
|
211
|
+
readonly detectedAtTick: Tick
|
|
212
|
+
/** The footprint that was checked */
|
|
213
|
+
readonly footprint: ReasoningFootprint
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export type ConflictStrategy = 'REJECT' | 'MERGE' | 'FORCE'
|
|
217
|
+
|
|
218
|
+
export interface ConflictResolution {
|
|
219
|
+
/** The strategy used to resolve conflicts */
|
|
220
|
+
readonly strategy: ConflictStrategy
|
|
221
|
+
/** If MERGE, the subset of commands that passed validation */
|
|
222
|
+
readonly resolvedCommands: StateCommands | null
|
|
223
|
+
/** If REJECT, whether to re-run the engine with current state */
|
|
224
|
+
readonly shouldRerun: boolean
|
|
225
|
+
/** Human-readable explanation of what happened */
|
|
226
|
+
readonly reason: string
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Configuration for async engine behavior within the orchestrator.
|
|
231
|
+
*/
|
|
232
|
+
export interface AsyncEngineConfig {
|
|
233
|
+
/** Default conflict strategy for this engine */
|
|
234
|
+
readonly defaultStrategy?: ConflictStrategy
|
|
235
|
+
/** Maximum ticks a reasoning can be pending before being auto-rejected */
|
|
236
|
+
readonly maxPendingTicks?: number
|
|
237
|
+
/** Whether to log conflict details for debugging */
|
|
238
|
+
readonly logConflicts?: boolean
|
|
239
|
+
/** Re-run on rejection (if false, commands are silently dropped) */
|
|
240
|
+
readonly rerunOnRejection?: boolean
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ── Homeostatic Types ──────────────────────────────────────────
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* A homeostatic drive signal emitted by regulatory engines.
|
|
247
|
+
* Drives represent survival-relevant needs that demand attention.
|
|
248
|
+
*/
|
|
249
|
+
export interface DriveSignal {
|
|
250
|
+
/** Drive name (e.g., 'energy', 'sleep', 'safety') */
|
|
251
|
+
readonly name: string
|
|
252
|
+
/** Current intensity 0-1 (0 = satisfied, 1 = critically deprived) */
|
|
253
|
+
readonly intensity: number
|
|
254
|
+
/** How quickly this is escalating 0-1 (0 = stable, 1 = rapidly worsening) */
|
|
255
|
+
readonly urgency: number
|
|
256
|
+
/** The engine that produced this signal */
|
|
257
|
+
readonly source: string
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* A modulation signal that adjusts parameters in other engines.
|
|
262
|
+
* Regulatory engines emit these to tune cognitive function based
|
|
263
|
+
* on homeostatic state (e.g., high sleep pressure degrades attention).
|
|
264
|
+
*/
|
|
265
|
+
export interface ModulationSignal {
|
|
266
|
+
/** Target engine name (or '*' for all engines) */
|
|
267
|
+
readonly target: string
|
|
268
|
+
/** Parameter to modulate */
|
|
269
|
+
readonly parameter: string
|
|
270
|
+
/** Multiplier to apply (1.0 = no change, 0.5 = halved, 2.0 = doubled) */
|
|
271
|
+
readonly factor: number
|
|
272
|
+
/** The engine that produced this signal */
|
|
273
|
+
readonly source: string
|
|
274
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/core/utils.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
import type { SeededPRNG, SimulationContext } from '#core/types'
|
|
6
|
+
import { wallClock } from '#core/wall.clock'
|
|
7
|
+
|
|
8
|
+
// ── PRNG ─────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a Mulberry32 PRNG from the given seed.
|
|
12
|
+
* Mulberry32 is a fast, high-quality 32-bit generator
|
|
13
|
+
* with a full 2^32 period.
|
|
14
|
+
*/
|
|
15
|
+
export function createPRNG( seed: number ): SeededPRNG {
|
|
16
|
+
// Ensure unsigned 32-bit start state
|
|
17
|
+
let s = seed >>> 0
|
|
18
|
+
|
|
19
|
+
function next(): number {
|
|
20
|
+
s += 0x6D2B79F5
|
|
21
|
+
let t = Math.imul( s ^ ( s >>> 15 ), 1 | s )
|
|
22
|
+
t = ( t + Math.imul( t ^ ( t >>> 7 ), 61 | t ) ) ^ t
|
|
23
|
+
return ( ( t ^ ( t >>> 14 ) ) >>> 0 ) / 4294967296
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
get state(){ return s },
|
|
28
|
+
next,
|
|
29
|
+
nextInt: ( min, max ) => Math.floor( next() * ( max - min ) ) + min,
|
|
30
|
+
nextBool: ( probability = 0.5 ) => next() < probability,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ── Immutability ─────────────────────────────────────────────
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Recursively `Object.freeze` a value and everything reachable from it, then
|
|
38
|
+
* return the same reference. Primitives (and `null`) pass through untouched.
|
|
39
|
+
*
|
|
40
|
+
* This is the runtime half of the double-buffer contract (R3): the type system
|
|
41
|
+
* marks the per-tick state snapshot `ReadonlyDeep`, but that is erased at
|
|
42
|
+
* runtime — a careless `entity.foo = x` on a value an engine *read* would
|
|
43
|
+
* silently corrupt the shared state and break determinism invisibly. Freezing
|
|
44
|
+
* the value turns that mutation into a loud `TypeError` (all ESM is strict
|
|
45
|
+
* mode) the instant it happens, so the "read-only snapshot" guarantee is
|
|
46
|
+
* enforced, not merely conventional.
|
|
47
|
+
*
|
|
48
|
+
* Cycle-safe: the container is frozen *before* its children are visited, so a
|
|
49
|
+
* reference that points back into an already-frozen object short-circuits on
|
|
50
|
+
* the `isFrozen` guard rather than recursing forever. Idempotent — re-freezing
|
|
51
|
+
* an already-frozen graph is a cheap no-op.
|
|
52
|
+
*/
|
|
53
|
+
export function deepFreeze<T>( value: T ): T {
|
|
54
|
+
// Only objects/arrays/functions are freezable; primitives are immutable already.
|
|
55
|
+
if( value === null || typeof value !== 'object' ) return value
|
|
56
|
+
if( Object.isFrozen( value ) ) return value
|
|
57
|
+
|
|
58
|
+
// Freeze the container first so a cyclic reference back to it hits the
|
|
59
|
+
// isFrozen guard above on re-entry (prevents infinite recursion).
|
|
60
|
+
Object.freeze( value )
|
|
61
|
+
|
|
62
|
+
for( const key of Object.keys( value as Record<string, unknown> ) )
|
|
63
|
+
deepFreeze( ( value as Record<string, unknown> )[ key ] )
|
|
64
|
+
|
|
65
|
+
return value
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ── Context helpers ──────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a minimal SimulationContext with required prng.
|
|
72
|
+
* Use for standalone operations (tests, step calls) where a full
|
|
73
|
+
* simulation is not running.
|
|
74
|
+
*/
|
|
75
|
+
export function createContext( simulationId: string, runId: string, seed?: number ): SimulationContext {
|
|
76
|
+
return {
|
|
77
|
+
simulationId,
|
|
78
|
+
runId,
|
|
79
|
+
tags: {},
|
|
80
|
+
prng: createPRNG( seed ?? wallClock() )
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/core/wall.clock.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The single sanctioned wall-clock boundary (R2).
|
|
7
|
+
*
|
|
8
|
+
* The determinism guard (tests/unit/determinism.guard.test.ts) bans bare
|
|
9
|
+
* `Date.now()` / `new Date` in `src/core` and `src/cognition`, because anything
|
|
10
|
+
* that feeds replayable state must read the *sim* clock (`SimulationState.time`
|
|
11
|
+
* or the tick) so a run reproduces byte-for-byte from the same seed.
|
|
12
|
+
*
|
|
13
|
+
* Some reads, though, are intentionally NON-replay-affecting — perf timing,
|
|
14
|
+
* idle detection, network/RPC metadata, snapshot ids, seed defaults. Those go
|
|
15
|
+
* through `wallClock()` so the intent is explicit and greppable, and so the one
|
|
16
|
+
* real `Date.now()` call lives in exactly one auditable place.
|
|
17
|
+
*
|
|
18
|
+
* Rule of thumb: if the value can ever land in the event log, a snapshot, or an
|
|
19
|
+
* entity field, it must NOT come from here — use the sim clock instead.
|
|
20
|
+
*/
|
|
21
|
+
export function wallClock(): number {
|
|
22
|
+
return Date.now() // determinism-ok: this function is the wall-clock boundary
|
|
23
|
+
}
|