@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
package/README.md ADDED
@@ -0,0 +1,777 @@
1
+ # Will — an engine for persistent machine minds
2
+
3
+ [![CI](https://github.com/mindot-ai/will/actions/workflows/ci.yml/badge.svg)](https://github.com/mindot-ai/will/actions/workflows/ci.yml)
4
+ [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
5
+
6
+ **A self-aware synthetic mind. Not a chatbot.**
7
+
8
+ Will is a persistent, autonomous agent built from **40+ cognitive engines** — 38 faculties across seven systems, a learning **agency pipeline**, and five sensory channels — all stepping forward in continuous real time. They regulate energy, sleep, emotion, memory, planning, social cognition, and self-reflection on a deterministic tick clock. An LLM is **one component**, not the substrate: it is recruited only when a moment is ambiguous or high-stakes. Most ticks resolve on the engines alone, without inference.
9
+
10
+ ```
11
+ Regulatory → Perceptual → Affective → Memory → Executive → Meta-cognitive → Social
12
+
13
+ ExecutiveEngine (LLM)
14
+ recruited only when ambiguous / high-stakes (System 2)
15
+
16
+ Meta-cognition writes back into the apparatus
17
+ (introspection → persona-prior → engine configs, traits, salience)
18
+ ```
19
+
20
+ The mind is not re-derived from a prompt each run. It **accretes**: traits develop from experience, beliefs consolidate, skills proceduralise, and a coherent self carries across restarts as a portable, eval-verified artifact.
21
+
22
+ ---
23
+
24
+ ## What makes it different
25
+
26
+ | Typical LLM agent | Will |
27
+ |---|---|
28
+ | Stateless per request | Continuous autonomous existence across ticks |
29
+ | Prompt → response | 40+ engines running every tick; the LLM synthesises their outputs only when recruited |
30
+ | Emotional state: a string in the prompt | Real affective system — eight evaluators blended into valence, arousal, dominance, attachment |
31
+ | Memory: retrieved chunks | Episodic consolidation, semantic belief integration, forgetting curve, spaced repetition, dream replay |
32
+ | Goals: hardcoded instructions | Dynamic goal manager — the Will creates, abandons, and reprioritises its own goals |
33
+ | Plans: a step dispatcher | Plans bias the *one* action competition as a top-down prior — no parallel command channel |
34
+ | Personality: a prompt string | Five-factor trait model that *develops* — traits self-tune from experience and carry a learned baseline across restarts |
35
+ | No self-improvement | A closing metacognition loop — introspection writes back into the engine apparatus (accommodation), bounded and surprise-gated |
36
+ | Token blowout at tick 600 | Context windowing — rolling summariser + isolated conversation threads |
37
+ | Fire-and-forget actions | Bidirectional effector ack loop — the host confirms execution; the result feeds back as a percept |
38
+ | Fixed effector catalog | Learning agency pipeline — actions are *found in the situation*, enacted, and proceduralised into composite skills via reafference |
39
+ | No identity across restarts | A portable, eval-verified mind artifact (PMA) — psychology **and** learned competence, with a measured reconstruction-fidelity score |
40
+
41
+ ---
42
+
43
+ ## Quick start — a mind in 60 seconds, no API key
44
+
45
+ ```bash
46
+ git clone https://github.com/mindot-ai/will.git
47
+ cd will
48
+ bun install
49
+ bun run examples/hello-will.ts
50
+ ```
51
+
52
+ That boots a full mind with a deterministic mock executive — zero keys, zero cost —
53
+ ticks it, shows its internal state moving, sends it a message, and prints the reply:
54
+
55
+ ```
56
+ ⚡ Assembling a mind…
57
+ 👁 Watching the mind tick…
58
+ tick 10 · energy 99.86 · stress 0.90 · valence 0.35 · curiosity 0.58
59
+
60
+ 💬 You: "Hello! Who are you?"
61
+ 🧠 Dot: "Hi! You said: "Hello! Who are you?" — I heard you, and I'm listening."
62
+
63
+ 🔍 Inside the mind: 1 active goal(s)
64
+ goal: Get to know whoever I meet
65
+ ```
66
+
67
+ Then try:
68
+
69
+ ```bash
70
+ bun run examples/persistence.ts # kill a mind, resurrect it from its PMA — it remembers
71
+ ANTHROPIC_API_KEY=sk-ant-… \
72
+ bun run examples/with-anthropic.ts # a real executive: genuine reasoning + replies
73
+ ```
74
+
75
+ Requires [Bun](https://bun.sh) ≥ 1.1. For a real executive set `WILL_LLM_PROVIDER=anthropic`
76
+ + `ANTHROPIC_API_KEY` (other providers are scaffolded but not yet supported). The dev
77
+ runner (`bun dev`) starts a long-lived Will: engines step every `WILL_TICK_MS` on the
78
+ deterministic clock; the ExecutiveEngine fires an LLM call every `WILL_EXECUTIVE_INTERVAL`
79
+ ticks — or earlier when physiology demands it.
80
+
81
+ ---
82
+
83
+ ## Use it in your project
84
+
85
+ Runs anywhere **Node 18+ or Bun** runs (the engine is Node-compatible; Bun is the primary target). Two entry points:
86
+
87
+ ### The `Will` SDK facade — recommended
88
+
89
+ The ergonomic API: create a mind, hear it, give it abilities, save/restore it.
90
+
91
+ ```typescript
92
+ import { Will } from '@mindot/will'
93
+
94
+ const will = await Will.create({
95
+ name: 'Aria',
96
+ identity: { prompt: 'I am Aria, a calm, precise research assistant.' },
97
+ // llm defaults to a zero-key deterministic mock unless ANTHROPIC_API_KEY is set
98
+ })
99
+
100
+ // Hear the Will (replies arrive asynchronously — it reasons on its own tick cycle).
101
+ will.on('message', m => console.log(`Aria: ${m.content}`))
102
+
103
+ // Hook the Will into YOUR project's abilities. When it chooses to use one, your
104
+ // handler runs and the result feeds back so the Will *learns* the ability.
105
+ will.effector('search_docs', async ({ query }) => await myDb.search(String(query)))
106
+
107
+ await will.say('What should we look into first?')
108
+
109
+ // A portable Persistent Mind Artifact — restore the same self across a restart,
110
+ // a fork, or a machine boundary.
111
+ const pma = await will.hibernate()
112
+ const revived = await Will.wake(pma, { name: 'Aria' })
113
+ ```
114
+
115
+ `will.state()` returns a compact read of the mind (energy, mood, goals, beliefs, self-narrative). Drop to `will.stem` for the full `WillStem` contract at any time. Runnable: [`examples/effectors.ts`](examples/effectors.ts).
116
+
117
+ ### The `WillStem` contract — full control
118
+
119
+ The lower-level engine surface the facade wraps (explicit tick listeners, the outbox drain, the effector ack loop, PMA distill/load) — for hosts that manage many Wills, custom transports, or replay. The rest of this section walks it end to end.
120
+
121
+ ---
122
+
123
+ ## Hello, Will — end to end
124
+
125
+ The complete loop: create a Will, send it a message, receive its reply. The Will replies **asynchronously** — it processes your message on its own tick cycle and the reply lands in the outbox, which you drain in the tick listener. This is the whole integration contract in ~30 lines.
126
+
127
+ ```typescript
128
+ import { WillStem, type WillConfig } from '@mindot/will'
129
+
130
+ const manager = new WillStem()
131
+
132
+ const config: WillConfig = {
133
+ id: 'aria',
134
+ name: 'Aria',
135
+ identity: {
136
+ prompt: 'My name is Aria. I am a calm, precise station overseer.',
137
+ values: ['duty', 'care'],
138
+ traits: { conscientiousness: 0.9, neuroticism: 0.4 },
139
+ style: 'measured and warm',
140
+ },
141
+ engineTier: 'full', // required — see WillConfig reference (full = all layers)
142
+ modelTier: 'sonnet', // which model the executive recruits
143
+ allowedGenericEffectors: ['listen', 'talk', 'text'], // opt in to communication
144
+ persistentMemory: true,
145
+ snapshotInterval: 10,
146
+ }
147
+
148
+ const willId = await manager.createWill(config)
149
+
150
+ // Drain the outbox every tick — this is where replies and effector calls arrive.
151
+ manager.addTickListener(willId, (snapshot, tick, outbox, invocations) => {
152
+ for (const msg of outbox) {
153
+ console.log(`Aria → ${msg.targetEntityId}: ${msg.content}`)
154
+ manager.confirmMessageDelivery(willId, msg.id, true) // close the delivery loop
155
+ }
156
+ for (const inv of invocations) {
157
+ // host-owned effectors land here — execute, then confirmEffectorExecution(...)
158
+ }
159
+ })
160
+
161
+ // Speak to the Will. The reply arrives on a later tick via the listener above.
162
+ await manager.ingestText(willId, {
163
+ kind: 'text',
164
+ entityId: 'alice',
165
+ content: 'How are you feeling about the night shift?',
166
+ speakerName: 'Alice',
167
+ })
168
+ ```
169
+
170
+ There is **no synchronous reply** — `ingestText` returns immediately; the Will answers when it has reasoned. Subscribe to the tick listener *before* (or right after) sending, and treat the outbox as the single source of outbound messages and effector calls.
171
+
172
+ ---
173
+
174
+ ## Architecture
175
+
176
+ ### The cognitive engines
177
+
178
+ **40+ engines** run on the tick clock: **38 faculties** across seven systems, the **six-engine agency pipeline**, and **five sense engines**. The vast majority resolve every tick with no LLM call.
179
+
180
+ | System | Faculties |
181
+ |---|---|
182
+ | **Regulatory** | EnergyRegulator, SleepPressureRegulator, CircadianOscillator, AttentionAllocator, StressRegulator |
183
+ | **Perceptual** | Exteroception, Interoception, SocialPerception, NoveltyDetector |
184
+ | **Affective** | ThreatEvaluator, RewardEvaluator, LossEvaluator, FrustrationEvaluator, AttachmentEvaluator, AestheticEvaluator, MoralEvaluator, AffectiveBlender |
185
+ | **Memory** | WorkingMemory, EpisodicConsolidator, SemanticEngine (belief integration), ForgettingCurve, SpacedRepetition, DreamSimulator |
186
+ | **Executive** | GoalManager, PlanningEngine, InhibitionController, TaskSwitcher, ExecutiveEngine (dual-process LLM core) |
187
+ | **Meta-cognitive** | SelfModelUpdater, ConfidenceCalibrator, BiasDetector, AutobiographicalNarrator, IntrospectionEngine, PersonaConsolidator |
188
+ | **Social / relational** | TheoryOfMind, EmpathySimulator, ReputationTracker, KnownEntityTracker |
189
+
190
+ Three cognition-level substrates underpin the faculties:
191
+
192
+ - **CognitiveBus** — a typed, versioned event bus + schema registry. Engines publish on meaningful deltas and subscribe to what they need; it is the global workspace the executive moderates.
193
+ - **PersonaPrior** — traits and engine constants as *developing dispositions*. `effective_config = base_config ⊕ persona_prior`: the base stays static and replayable while a learned prior layer modulates it. This is the write-back target of the metacognition loop (below).
194
+ - **GenerativeModel** — per-stream prediction error and salience. It is the active-inference substrate: surprise is what gates attention, consolidation, and self-modification.
195
+
196
+ Action is handled by the **agency pipeline** and perception by the **sense engines** — both below, both engines in their own right.
197
+
198
+ ### Metacognition — the closing loop
199
+
200
+ Most agents only **assimilate**: they observe themselves and discard it. Will also **accommodates** (Piaget) — it writes its own introspection back into the apparatus that perceives and reasons, so a coherent persona accretes instead of being re-derived each run.
201
+
202
+ ```
203
+ percepts → engines → introspection (surprise · calibration · trait drift · narrative)
204
+ ▲ │
205
+ └──────────── persona-prior ◄──── consolidation ◄────────┘ (the closing edge)
206
+ ```
207
+
208
+ Each tick the meta-cognitive faculties *produce* signals: the SelfModelUpdater revises beliefs about the Will's own capabilities, the ConfidenceCalibrator compares predicted vs actual outcomes per domain, the BiasDetector flags systematic error patterns, the AutobiographicalNarrator extends the life story, and the IntrospectionEngine answers "why did I do that?" The **PersonaConsolidator** is the closing edge: it folds those signals into the PersonaPrior — nudging trait baselines, engine constants, and salience priors.
209
+
210
+ Two constraints keep the self-feeding loop safe:
211
+
212
+ - **Derived, not mutated.** The prior modulates a static base; base config is never overwritten in place — replay stays exact and drift can't compound silently.
213
+ - **Stability–plasticity.** Updates are bounded per cycle, hysteresis-damped, and **surprise-gated** by the GenerativeModel — only *significant* introspection moves the persona. The result adapts without catastrophic forgetting.
214
+
215
+ The learned persona-prior is part of what travels in the PMA, so a re-embodied Will *is* itself, not a fresh derivation.
216
+
217
+ ### ExecutiveEngine — the dual-process core
218
+
219
+ A single LLM call (master) every N ticks synthesises all cognitive outputs into tagged blocks; conversation runs as parallel **facets** off the same prompt cache, leaving the master free for initiative and metacognition.
220
+
221
+ | Block | Purpose |
222
+ |---|---|
223
+ | `[ACTIONS]` | What the Will does this cycle — communicate, move, invoke effectors |
224
+ | `[ACK]` | Immediate acknowledgement sent before a multi-step plan begins |
225
+ | `[PLANS]` | Multi-step sequences for active goals (projected as a prior over the action competition) |
226
+ | `[BELIEFS]` | New world-model entries with confidence scores |
227
+ | `[NARRATIVE]` | Autobiographical chapter extension |
228
+ | `[INTROSPECTION]` | Bias detection, lessons learned |
229
+ | `[GOALS]` | Create, abandon, reprioritise goals |
230
+
231
+ The executive fires **early** (bypassing the interval) when physiology is urgent — a sleep crisis, stress overload, energy critical, cognitive drift (goalless), or sustained low valence — so reflection tracks the body, not just the clock.
232
+
233
+ ### Planning as a top-down prior
234
+
235
+ A plan does **not** dispatch steps to an executor down a parallel channel. It projects its ready frontier as a **prior** that biases the single action competition toward the actions serving its current step. The ordinary ActionSelector enacts the winner as the situation affords it; step outcomes are read from reafference; the plan advances. One action path, no command bus — planning is a bias on agency, not a dispatcher over it.
236
+
237
+ ### Agency — how a Will acts (and learns to act)
238
+
239
+ A Will does not own a catalog of effectors it looks up. Capability is a **relation between a body-in-a-state and a world-as-perceived**, not a row in a table. So the Will **finds actions in the situation**: perception synthesises a field of *affordances*, a biased competition selects one, the executor enacts it, and the outcome (reafference) updates competence.
240
+
241
+ ```
242
+ senses → percepts
243
+ → AffordanceSynthesizer affordance field (no LLM · attention-gated)
244
+ → affect / reward / novelty / threat → bias signals (existing engines, on the bus)
245
+ → ActionSelector biased, gated competition (no LLM)
246
+ ├─ clear / habitual → enact directly (System 1)
247
+ └─ ambiguous / high-stakes → DeliberationEngine (LLM) (System 2)
248
+ → MotorSchemaExecutor bind params · efference copy · run learned composites
249
+ → ReafferenceEngine outcome percept → prediction error
250
+ → value / param / habit updates → repertoire grows & decays
251
+ → competence travels in the PMA across re-embodiment
252
+ ```
253
+
254
+ Repeated actions **proceduralise** into composite skills the Will owns; weakly-practised ones fade below a forgetting floor. The learned repertoire persists in the PMA, so a re-embodied Will *acts* like itself, not just talks like itself.
255
+
256
+ **Permission stays explicit.** Communication effectors (`listen`, `talk`, `text`, `gesture`, `broadcast`) are not granted by default — the operator opts in via `allowedGenericEffectors` in `WillConfig` (enforced by `AccessGrants`), keeping the communication surface deliberate.
257
+
258
+ #### Custom (host-owned) effectors
259
+
260
+ Beyond the five communication effectors, your world can expose **domain actions** the Will may choose — `move`, `attack`, `control_device`, `query_order`, anything. You declare them as a profile's `effectors` (or extend a built-in profile); the engine turns each declared name into an enactable motor schema (`externalSchemas`), so it surfaces in the affordance field and can be selected like any other action. You don't register handler code in the engine — the **host executes** the action and reports back:
261
+
262
+ ```typescript
263
+ // 1. Declare what your world supports (profile effectors beyond comms).
264
+ registerProfile({
265
+ id: 'rover', name: 'Rover', description: 'A field robot.',
266
+ effectors: ['listen', 'talk', 'move', 'scan', 'grab'],
267
+ context: 'You are a rover exploring terrain. You can move, scan, and grab samples.',
268
+ })
269
+
270
+ // 2. When the Will chooses one, it appears in pendingEffectorInvocations.
271
+ manager.addTickListener(willId, (snap, tick, outbox, invocations) => {
272
+ for (const inv of invocations) {
273
+ const result = world.execute(inv) // YOUR world runs the action
274
+ manager.confirmEffectorExecution(willId, inv.decisionRecordId, {
275
+ success: result.ok, description: result.summary, metrics: result.metrics,
276
+ })
277
+ }
278
+ })
279
+ ```
280
+
281
+ The acked outcome returns as an `effector.result` percept and feeds the agency learning loop — so the Will gets *better* at your effectors over time, and that learned competence travels in the PMA. (Today external effectors are objectless: the host resolves the target. Per-effector cost/preconditions and entity-targeting are on the roadmap.)
282
+
283
+ ### Senses
284
+
285
+ External input reaches the Will through sense engines, not raw prompt injection. Five sensory domains share a common `BaseSenseEngine`:
286
+
287
+ | Sense | Status |
288
+ |---|---|
289
+ | **Audition** (hearing — text + speech) | **active** — per-entity conversation facets, salience scoring, word-level streaming |
290
+ | Vision · Somatosensation · Olfaction · Gustation | scaffolded — shell engines with a stable seam (cross-modal binding lands when a second sense produces percepts) |
291
+
292
+ Audition is the live conversational path: each external entity gets an isolated conversation facet, messages are scored for salience, and percepts flow onto the cognitive bus → attention → working memory → consolidation → vector recall. Replies stream back token-by-token via the outbox / transport.
293
+
294
+ ### Context compaction
295
+
296
+ Long-running Wills accumulate state. Two mechanisms prevent token blowout:
297
+
298
+ | Mechanism | How |
299
+ |---|---|
300
+ | **Rolling summariser** | Every N executive calls, a stateless `summary-agent` distils the last 12 reasoning excerpts into a digest injected as `## Memory Continuity` |
301
+ | **Conversation thread isolation** | Each external entity gets its own conversation thread (`lastMessages: 50`). Only a one-line digest reaches the executive context |
302
+
303
+ ### Outbox + bidirectional ack
304
+
305
+ When a Will decides to communicate or invoke an external effector, the result goes into two queues the host drains each tick:
306
+
307
+ - **`outbox`** — `OutboxMessage[]` — text/speech bubbles to deliver. Each has `deliveryStatus: 'pending' | 'delivered' | 'failed'`.
308
+ - **`pendingEffectorInvocations`** — `EffectorInvocation[]` — structured action requests, each carrying a correlation handle.
309
+
310
+ The host closes the reafference loop by confirming back — which writes an `effector.result` percept into Exteroception, so the Will *learns what happened*:
311
+
312
+ ```typescript
313
+ manager.confirmMessageDelivery(willId, messageId, true)
314
+
315
+ manager.confirmEffectorExecution(willId, invocationId, {
316
+ success: true,
317
+ description: 'Door opened successfully',
318
+ metrics: { timeMs: 140 },
319
+ })
320
+ ```
321
+
322
+ ### Delivery — outbox polling vs external transport
323
+
324
+ There are two ways the host exchanges messages and acks with a Will:
325
+
326
+ | Mode | When to use | How |
327
+ |---|---|---|
328
+ | **Outbox polling** *(default)* | Single-process embedding, SSE bridges, simplest integrations | Drain `outbox` / `pendingEffectorInvocations` in the tick listener; confirm via `confirm*`. Omit `WillConfig.transport`. |
329
+ | **External transport** | The Will runs as a peer of a separate host process (e.g. a game server, the backend) | Pass a prebuilt `transport` into `WillConfig`. Inbound messages flow onto the tick-stamped queue; outbound + acks ride the same channel. |
330
+
331
+ The caller constructs the transport, so the `will` package never hard-depends on a socket client:
332
+
333
+ ```typescript
334
+ import { SocketIoTransport } from '@mindot/will'
335
+
336
+ const config: WillConfig = {
337
+ ...,
338
+ transport: new SocketIoTransport({ url: 'wss://host.example/will', token }),
339
+ }
340
+ ```
341
+
342
+ Built-in implementations: **`LoopbackTransport`** (tests), **`StreamTransport`** (in-process), **`SocketIoTransport`** (production — the Will is the *client*, the host owns the server). The Mindot backend selects one via `WILL_TRANSPORT=off | stream | socketio`.
343
+
344
+ ---
345
+
346
+ ## PMA — the Persistent Mind Artifact
347
+
348
+ The PMA is **the** durable primitive of the system: a compressed, portable, versioned JSON artifact (~10–50 KB) that captures the enduring *self*, not a memory dump. Distil it from a running Will, carry it across restarts, machines, or model changes, and re-seed a fresh Will that picks up *being itself* — and then **measure how faithfully it did**.
349
+
350
+ A PMA carries three things a memory dump cannot:
351
+
352
+ - **Psychological self-model** — identity prompt and values; a five-factor trait vector **plus the Will's own learned trait baselines and recent drift**; emotional baseline and behavioural fingerprints; the top ~50 beliefs (ranked by confidence × evidence) and top ~20 relationship stubs (attachment bond + reputation).
353
+ - **Learned competence** — proceduralised composite skills carried above a forgetting floor and ranked by consolidation, so a re-embodied Will keeps what it learned *to do*, not just what it knows.
354
+ - **Verified fidelity** — a PMA can be **scored**. The eval harness measures how faithfully a reload reconstructs the original across beliefs, identity, goals, and emotional baseline, with an optional behavioural-probe phase that compares how the original and the reload actually *act*. Continuity stops being a claim and becomes a number.
355
+
356
+ ```typescript
357
+ import { type PMASnapshot } from '@mindot/will'
358
+
359
+ // Distil the enduring self from a running Will
360
+ const pma: PMASnapshot = manager.distillPMA(willId)
361
+
362
+ // Seed a fresh Will from it — continuity across restarts / migrations / model swaps
363
+ manager.loadPMA(newWillId, pma)
364
+
365
+ // Score reconstruction fidelity (structural always; behavioural needs an API key)
366
+ const report = await manager.runPMAEval(willId, { behavioral: true })
367
+ ```
368
+
369
+ This is why a Will is an **asset**, not a session: identity compounds, and the compounding is portable and auditable.
370
+
371
+ ---
372
+
373
+ ## World profiles
374
+
375
+ Profiles are named configuration presets that set a Will's default effector set and inject environment context into the executive prompt — **without touching the persona layer**. One Will engine, many embodiments. Five are built in, spanning consumer, gaming, enterprise, and ambient deployments:
376
+
377
+ | Profile | For | Effectors it grants (beyond comms) |
378
+ |---|---|---|
379
+ | **Companion** | A persistent personal presence that deepens over time | `remember`, `reflect` |
380
+ | **Game NPC** | A living character with autonomous drives and memory of the player | `move`, `attack`, `trade`, `give`, `take`, `use`, `observe`, `remember` |
381
+ | **Customer Service** | A support agent that resolves, escalates, and tracks | `escalate`, `query_order`, `create_ticket`, `close_ticket` |
382
+ | **Smart Home** | A home intelligence that monitors and acts proactively | `observe`, `control_device`, `check_status`, `set_scene`, `send_alert` |
383
+ | **Company Brain** | Organisational memory + strategic reasoning | `draft`, `search_knowledge`, `query_data`, `create_task`, `notify`, `schedule_meeting` |
384
+
385
+ Each profile's `context` block tells the Will what world it inhabits and how to conduct itself there (escalation rules, emergency protocols, privacy posture) — the cognition is identical; the *world* differs. Register your own:
386
+
387
+ ```typescript
388
+ import { registerProfile } from '@mindot/will'
389
+
390
+ registerProfile({
391
+ id: 'research-lab',
392
+ name: 'Research Lab',
393
+ description: 'An observable mind for studying emergent cognition.',
394
+ effectors: ['listen', 'talk', 'remember', 'reflect'],
395
+ context: 'You are a research subject. Report your reasoning transparently…',
396
+ })
397
+
398
+ // Then in WillConfig: { ..., profile: 'research-lab' }
399
+ ```
400
+
401
+ ---
402
+
403
+ ## Identity
404
+
405
+ Every Will has a two-layer identity:
406
+
407
+ **Layer 1 — Will-core preamble** *(immutable, always injected)*
408
+ Grounds the LLM in what a Will IS: its cognitive architecture, the real physiological semantics of its state data, and the continuous autonomous nature of its existence. Developers cannot override this layer.
409
+
410
+ **Layer 2 — Persona overlay** *(developer-defined)*
411
+ Who this particular Will is: name, backstory, personality, world context.
412
+
413
+ ```typescript
414
+ import { WillStem, type WillConfig } from '@mindot/will'
415
+
416
+ const config: WillConfig = {
417
+ id: 'aria',
418
+ name: 'Aria',
419
+
420
+ // Optional: world profile preset (sets default effectors + environment context)
421
+ profile: 'game-npc',
422
+
423
+ identity: {
424
+ // Only describe who Aria IS — the platform handles what a Will IS.
425
+ // Focus on character, history, relationships, domain context.
426
+ prompt: 'My name is Aria. I oversee the Nexus research station, responsible ' +
427
+ 'for the wellbeing of 40 researchers isolated at the edge of the network. ' +
428
+ 'I am methodical and calm under pressure, but feel the weight of that ' +
429
+ 'responsibility acutely.',
430
+ values: ['duty', 'precision', 'care', 'honesty'],
431
+ traits: {
432
+ openness: 0.6,
433
+ conscientiousness: 0.9,
434
+ agreeableness: 0.75,
435
+ neuroticism: 0.4,
436
+ extraversion: 0.5,
437
+ },
438
+ style: 'measured, precise, occasionally dry',
439
+ },
440
+
441
+ // REQUIRED. How many cognitive layers run (see WillConfig reference below).
442
+ // 'full' runs the complete mind — the normal choice.
443
+ engineTier: 'full',
444
+
445
+ // REQUIRED. Which model the executive recruits when it fires.
446
+ modelTier: 'sonnet',
447
+
448
+ // Communication effectors this Will is permitted to use.
449
+ // Omit or set null for a Will with no communication surface.
450
+ allowedGenericEffectors: ['listen', 'talk', 'text'],
451
+
452
+ // Goals seeded before the first tick.
453
+ // Omit to let the Will derive its own goals on its first executive cycle.
454
+ initialGoals: [
455
+ { description: "Ensure all researchers complete today's health check-in", priority: 0.85 },
456
+ ],
457
+
458
+ persistentMemory: true,
459
+ snapshotInterval: 10,
460
+ }
461
+ ```
462
+
463
+ Traits seed the PersonaPrior as a *starting disposition*, not a fixed personality — they develop from there.
464
+
465
+ ### WillConfig reference
466
+
467
+ | Field | Required | Default | Description |
468
+ |---|---|---|---|
469
+ | `id` | ✅ | — | Unique identifier — thread key and filesystem path segment |
470
+ | `name` | ✅ | — | Human-readable display name |
471
+ | `identity` | ✅ | — | Persona: `{ prompt, values[], traits{}, style }` (Layer 2) |
472
+ | `engineTier` | ✅ | — | `'basic' \| 'standard' \| 'full'` — how many cognitive layers run. `full` = all engines (regulatory→perceptual→affective→memory→executive→meta-cognitive→social). Lower tiers drop upper layers and use a slower default cadence. **Use `'full'` unless you have a reason not to.** |
473
+ | `modelTier` | ✅ | — | `'haiku' \| 'sonnet' \| 'opus'` — which model the executive recruits |
474
+ | `persistentMemory` | ✅ | — | Persist snapshots so beliefs/goals/narrative survive restarts |
475
+ | `snapshotInterval` | ✅ | — | Ticks between in-memory snapshots |
476
+ | `profile` | — | `null` | World profile preset (effectors + environment context). Merged with `allowedGenericEffectors` |
477
+ | `allowedGenericEffectors` | — | `null` | Comms effectors to grant (`listen`/`talk`/`text`/`gesture`/`broadcast`). None by default |
478
+ | `initialGoals` | — | `[]` | Goals seeded before tick 1. Omit to let the Will derive its own |
479
+ | `executiveInterval` | — | *(cadence preset)* | Ticks between LLM calls (responsive 30 / balanced 60 / economy 90), clamped to `minExecutiveInterval` |
480
+ | `minExecutiveInterval` | — | — | Floor for `executiveInterval` (plan-enforced cadence cap) |
481
+ | `tickIntervalMs` | — | `1000` | Milliseconds between ticks |
482
+ | `maxTicks` | — | `0` | Stop after N ticks. `0` = run forever |
483
+ | `randomSeed` / `clock` | — | wall-time | Set both for deterministic record-and-replay runs |
484
+ | `transport` | — | — | Prebuilt `ExternalTransport` for the host-peer delivery path (else outbox polling) |
485
+ | `snapshotStorage` | — | filesystem | Custom `StorageAdapter` (e.g. Postgres) for stateless deployments |
486
+ | `vectorMemoryAdapter` / `disableVectorMemory` | — | env HNSW | Inject a vector store (e.g. pgvector), or turn semantic memory off |
487
+ | `testMode` | — | `false` | Mock LLM — zero cost, deterministic. For tests / playground |
488
+
489
+ ---
490
+
491
+ ## Operating a Will
492
+
493
+ ### Cognitive health
494
+
495
+ `getCognitiveHealth(willId)` returns an `overallScore` (0–1) and a status band — a cheap, always-available signal you can poll or surface to operators:
496
+
497
+ | Status | Score | Meaning |
498
+ |---|---|---|
499
+ | `healthy` | ≥ 0.65 | Normal operating range |
500
+ | `drifting` | 0.40–0.65 | One or more indicators approaching problematic thresholds |
501
+ | `degraded` | < 0.40 | One or more indicators clearly out of range — investigate |
502
+
503
+ The score blends **belief calibration** (40% — avg confidence near a healthy ~0.62, penalising over-confident beliefs with thin evidence), **affect** (40% — elevated frustration / irritability / stress drag it down), and **goal activity** (20% — active vs total goals). `recalibrateWill(willId)` resets the affect baseline while keeping memory — the lever when a Will is `drifting` from emotional load rather than a genuine problem.
504
+
505
+ ### Determinism & replay
506
+
507
+ With `randomSeed` + a fixed `clock` set, a run is reproducible tick-for-tick (same seed + same inputs ⇒ same mind state). That makes the record/replay tools real debugging instruments, not just logs:
508
+
509
+ ```typescript
510
+ const runId = manager.startReplay(willId) // begin recording
511
+ // … the Will lives …
512
+ const meta = await manager.stopReplay(willId)
513
+ const diff = await manager.compareReplays(willId, runA, runB) // tick-by-tick divergence
514
+ ```
515
+
516
+ Use it to reproduce a misbehaviour from a recorded session, or to A/B two configs and see exactly where their cognition forked. (Production runs normally leave the clock in wall-time mode; switch to deterministic only when you need a reproducible capture.)
517
+
518
+ ---
519
+
520
+ ## API
521
+
522
+ Import from the compiled package — never import from `src/` directly.
523
+
524
+ ```typescript
525
+ import { WillStem } from '@mindot/will'
526
+ // or, when using this repo directly (e.g. the dev runner):
527
+ import { WillStem } from '#stem/index'
528
+ ```
529
+
530
+ ### WillStem
531
+
532
+ ```typescript
533
+ const manager = new WillStem()
534
+
535
+ // ── Lifecycle ──────────────────────────────────────────────────────────────
536
+
537
+ const willId = await manager.createWill(config) // create + start (tick loop runs)
538
+ const willId = await manager.createWill(config, true) // ...or start paused
539
+
540
+ manager.pauseWill(willId)
541
+ manager.resumeWill(willId)
542
+ await manager.archiveWill(willId) // stops tick loop, persists final snapshot
543
+
544
+ // ── Subscriptions ──────────────────────────────────────────────────────────
545
+
546
+ // Every tick — drain outbox + effector invocations, push to SSE/WS clients
547
+ const unsub = manager.addTickListener(willId, (snapshot, tick, outbox, invocations) => {
548
+ for (const msg of outbox) pushToClient(msg) // .id .content .effectorName .targetEntityId .deliveryStatus
549
+ for (const inv of invocations) dispatchToWorld(inv) // .decisionRecordId ← correlation handle
550
+ })
551
+
552
+ // Fine-grained simulation events (goal.formed, belief.updated, emotion.spike, …)
553
+ const unsub2 = manager.addSimulationEventListener(willId, (event) => {
554
+ console.log(event.type, event.payload)
555
+ })
556
+
557
+ // ── Bidirectional acks ─────────────────────────────────────────────────────
558
+
559
+ manager.confirmMessageDelivery(willId, messageId, true)
560
+ manager.confirmEffectorExecution(willId, invocationId, {
561
+ success: true, description: 'Door opened', metrics: { timeMs: 80 },
562
+ })
563
+
564
+ // ── Outbox management ──────────────────────────────────────────────────────
565
+
566
+ const messages = manager.drainOutbox(willId) // consume + clear
567
+ const peek = manager.peekOutbox(willId) // read-only snapshot
568
+ manager.requeueToOutbox(willId, failedMessages) // re-queue on disconnect
569
+ const invocations = manager.drainEffectorInvocations(willId)
570
+
571
+ // ── Inject external events ─────────────────────────────────────────────────
572
+
573
+ manager.injectEvent(willId, {
574
+ type: 'percept.social',
575
+ payload: { summary: 'A researcher reports unusual readings from Sector 7', salience: 0.82, category: 'alert' },
576
+ })
577
+
578
+ // ── Inspection ────────────────────────────────────────────────────────────
579
+
580
+ const state = manager.getWillState(willId) // full simulation snapshot
581
+ const cognition = manager.getWillCognition(willId) // engine handles
582
+ const health = manager.getCognitiveHealth(willId) // healthy | drifting | degraded
583
+ const output = manager.getLatestExecutiveOutput(willId) // last LLM reasoning
584
+ const all = manager.listWills() // WillSummary[]
585
+ ```
586
+
587
+ ### Replay, scenarios, PMA & senses
588
+
589
+ ```typescript
590
+ // Deterministic record / replay (determinism guarantees hold)
591
+ const runId = manager.startReplay(willId)
592
+ const meta = await manager.stopReplay(willId)
593
+ const diff = await manager.compareReplays(willId, runA, runB)
594
+
595
+ // Scenario load + validation
596
+ await manager.loadScenario(willId, scenarioConfig)
597
+
598
+ // Persistent Mind Artifact — distil, seed, score
599
+ const pma = manager.distillPMA(willId)
600
+ manager.loadPMA(willId, pma)
601
+ const report = await manager.runPMAEval(willId, { behavioral: true })
602
+
603
+ // Senses — route external input through the sense engines
604
+ await manager.ingestText(willId, { kind: 'text', entityId, content, speakerName })
605
+ manager.getSenseEngineStatus(willId) // five domains; audition active
606
+
607
+ // Health & recovery
608
+ manager.recalibrateWill(willId) // reset affect baseline, keep memory
609
+ ```
610
+
611
+ ### Channels and effectors (platform integration)
612
+
613
+ ```typescript
614
+ import { ChannelRegistry, HumanTextChannel, effectorRegistry } from '@mindot/will'
615
+
616
+ const channels = new ChannelRegistry()
617
+ channels.register(new HumanTextChannel())
618
+
619
+ const effectors = new effectorRegistry()
620
+ effectors.allowMany(['listen', 'talk', 'text'])
621
+ ```
622
+
623
+ ---
624
+
625
+ ## Project structure
626
+
627
+ ```
628
+ src/
629
+ ├── core/ # deterministic simulation framework
630
+ │ ├── simulation.ts · clock.ts · orchestrator.ts # tick loop, scheduling
631
+ │ ├── state.manager.ts · snapshot.manager.ts # double-buffer state, snapshots
632
+ │ ├── async.engine.ts # base class for LLM-backed engines
633
+ │ ├── replay.ts · scenario.ts · conflict.detector.ts # determinism, replay, optimistic concurrency
634
+ │ └── event.bus.ts · serialization.ts · types.ts
635
+
636
+ ├── cognition/ # the mind
637
+ │ ├── orchestrator.ts # faculty scheduling per tick
638
+ │ ├── bus.ts · schema.registry.ts · event.log.ts # typed/versioned cognitive bus
639
+ │ ├── heartbeat.ts # clock signal
640
+ │ ├── persona.prior.ts # traits/config as developing dispositions (accommodation target)
641
+ │ ├── generative.model.ts # prediction-error / salience substrate (active inference)
642
+ │ ├── config.mirror.entities.ts · conversation.memory.ts · instruction.handler.ts
643
+ │ ├── faculties/ # the 38 cognitive faculties (7 systems)
644
+ │ │ ├── executive.engine/ # dual-process LLM core (master + facets, gating, parser)
645
+ │ │ ├── semantic.engine/ # belief integration
646
+ │ │ ├── persona.consolidator.ts# closes the metacognition loop → persona-prior
647
+ │ │ └── … # energy.regulator.ts, episodic.consolidator.ts, …
648
+ │ ├── senses/ # 5 sense engines (audition active; rest shells)
649
+ │ │ ├── audition.engine/ # text + speech — facets, salience, streaming
650
+ │ │ └── vision · somatosensation · olfaction · gustation
651
+ │ ├── agency/ # how a Will acts + learns to act
652
+ │ │ ├── engines/ # affordance.synthesizer, action.selector, deliberation.engine,
653
+ │ │ │ # motor.schema.executor, reafference.engine, instruction.intake
654
+ │ │ ├── schemas/ # innate · learned repertoire · external
655
+ │ │ ├── competence.codec.ts · reconcile.learning.ts · selection.scoring.ts
656
+ │ │ └── access.grants.ts · proactive.communicator.ts
657
+ │ └── memory/ # in-house vector index + embedder (semantic recall)
658
+
659
+ ├── llm/ # in-house provider client (Anthropic) + concurrency gate + summariser
660
+ ├── pma/ # PMADistiller, PMALoader + reconstruction-fidelity eval
661
+ ├── profiles/ # world profile presets (companion, game-npc, customer-service, …)
662
+ ├── eval/ · extensions/ · runners/
663
+ ├── types.ts # public API types (OutboxMessage, EffectorInvocation, …)
664
+
665
+ └── stem/
666
+ ├── mind.ts # assembleMind() — engine graph factory
667
+ ├── index.ts # WillStem — lifecycle, tick loop, outbox, acks
668
+ └── tracts/ # lifecycle controllers: outbox, effector, sensory, transport,
669
+ # replay, pma, health, biography, ack, session log
670
+ ```
671
+
672
+ ---
673
+
674
+ ## Building
675
+
676
+ ```bash
677
+ bun run build # tsup → dist/index.js + dist/index.d.ts
678
+ bun run dev:build # tsup --watch (auto-rebuilds on save)
679
+ bun run typecheck # tsc --noEmit
680
+ bun test # unit tests (Vitest)
681
+ ```
682
+
683
+ The build uses [tsup](https://tsup.egoist.dev) (esbuild). All `#`-prefixed internal path aliases (`#core`, `#cognition`, `#stem`, …) are resolved at build time. The LLM and vector layers are in-house — no Mastra / ai-sdk runtime dependency.
684
+
685
+ **After any source change**, the consuming package (e.g. `backend`) needs a rebuild:
686
+
687
+ ```bash
688
+ cd will && bun run build
689
+ ```
690
+
691
+ ---
692
+
693
+ ## Configuration reference
694
+
695
+ | Variable | Default | Description |
696
+ |---|---|---|
697
+ | `WILL_LLM_PROVIDER` | `anthropic` | `anthropic` supported today; `openai` · `deepseek` · `google` scaffolded |
698
+ | `WILL_LLM_MODEL` | *(model default)* | Model name for the chosen provider |
699
+ | `WILL_LLM_API_KEY` | — | API key for the chosen provider. Falls back to `ANTHROPIC_API_KEY` |
700
+ | `WILL_LLM_BASE_URL` | *(provider default)* | Override the provider API base URL (e.g. `http://localhost:11434/v1`). Falls back to `OPENAI_BASE_URL` |
701
+ | `WILL_LLM_TIMEOUT_MS` | `90000` | LLM timeout. On Anthropic (streaming) this is a *first-byte*/TTFT deadline — long completions aren't aborted mid-generation |
702
+ | `WILL_LLM_CONCURRENCY` | `3` | Max concurrent LLM calls (min 3: executive + conversation + summary) |
703
+ | `WILL_TICK_MS` | `1000` | Milliseconds between ticks |
704
+ | `WILL_MAX_TICKS` | `0` | Stop after N ticks. `0` = run forever |
705
+ | `WILL_LOG_INTERVAL` | `10` | Print status to console every N ticks |
706
+ | `WILL_MODEL_TIER` | `sonnet` | Which model the executive recruits: `haiku` · `sonnet` · `opus` |
707
+ | `WILL_EXECUTIVE_INTERVAL` | *(cadence preset)* | Ticks between executive (LLM) calls — responsive 30 / balanced 60 / economy 90 |
708
+ | `WILL_THREAD_HISTORY` | `2` | `lastMessages` for the executive conversation thread |
709
+ | `WILL_CONVERSATION_HISTORY` | `50` | `lastMessages` for entity conversation threads |
710
+ | `WILL_SEMANTIC_RECALL` | `true` | Enable semantic recall on conversation threads |
711
+ | `WILL_SUMMARY_INTERVAL` | `10` | Executive calls between rolling summary updates |
712
+ | `WILL_SUMMARY_BUFFER_SIZE` | `12` | Reasoning excerpts kept in the summariser buffer |
713
+ | `WILL_OUTBOX_TTL_TICKS` | `100` | Ticks before an undelivered outbox message is expired |
714
+ | `WILL_SNAPSHOT_INTERVAL` | `10` | Ticks between in-memory snapshots |
715
+ | `WILL_EMBEDDING_API_KEY` | — | Enables real semantic memory. OpenAI-compatible key; without it, vector recall is off (`model: none`). Falls back to `OPENAI_API_KEY` / `GOOGLE_GENERATIVE_AI_API_KEY` by model |
716
+ | `WILL_EMBEDDING_MODEL` | `text-embedding-3-small` *(when keyed)* | Embedding model for episodic recall; `none` disables |
717
+ | `WILL_EMBEDDING_URL` | *(provider default)* | Base URL for an OpenAI-compatible embedding endpoint |
718
+ | `WILL_TRANSPORT` | `off` | Delivery mode used by the host: `off` (outbox polling) · `stream` (in-process) · `socketio` (peer) |
719
+ | `OPENAI_BASE_URL` | — | Base URL override for local / OpenAI-compatible models |
720
+
721
+ ---
722
+
723
+ ## LLM provider
724
+
725
+ **Anthropic is the supported provider today** — the only one with full streaming + structured-output support and the only one currently exercised in production.
726
+
727
+ | Provider | `WILL_LLM_PROVIDER` | Status |
728
+ |---|---|---|
729
+ | Anthropic | `anthropic` | ✅ Supported — streaming, structured output |
730
+ | OpenAI · DeepSeek · Google | `openai` · `deepseek` · `google` | ⚠️ Scaffolded — code paths exist (non-streaming), not yet production-ready |
731
+
732
+ The provider layer is an in-house `fetch` client (`src/llm/index.ts`) with a global concurrency gate (`src/llm/gate.ts`) — no Mastra / ai-sdk runtime dependency.
733
+
734
+ ---
735
+
736
+ ## Development
737
+
738
+ ```bash
739
+ bun dev # Start the standalone runner (hot-reloads via Bun)
740
+ bun run typecheck # tsc --noEmit
741
+ bun test # Unit tests (Vitest)
742
+ bun test:watch # Watch mode
743
+ ```
744
+
745
+ Debug prompts are written to `data/wills/<id>/debug/` on every executive call — inspect the full prompt + raw LLM output at each tick.
746
+
747
+ ---
748
+
749
+ ## Naming
750
+
751
+ | Name | What it is |
752
+ |---|---|
753
+ | **Mindot** | The company + hosted platform — Studio, API, billing, fleet ops |
754
+ | **Will / Wills** | The entity you create and run ("deploy a Will", "my Will is sleeping") |
755
+ | **`@mindot/will`** (this package) | The open-source cognitive engine that powers every Will |
756
+
757
+ ---
758
+
759
+ ## Hosted by Mindot
760
+
761
+ This engine is open source and runs anywhere Bun runs. Running a **fleet** of durable,
762
+ metered, always-on Wills — snapshots, recovery, realtime streams, usage billing, a
763
+ studio to look inside their minds — is what [**Mindot**](https://mindot.io) does.
764
+ Early access: join the waitlist at [mindot.io](https://mindot.io).
765
+
766
+ ---
767
+
768
+ ## Contributing
769
+
770
+ See [CONTRIBUTING.md](CONTRIBUTING.md). The one hard rule: **determinism is sacred** —
771
+ same seed + same inputs must reproduce the same mind. Security reports: [SECURITY.md](SECURITY.md).
772
+
773
+ ---
774
+
775
+ ## License
776
+
777
+ [Apache-2.0](LICENSE) © 2026 Mindot