@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,459 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/cognition/faculties/executive.engine/commands.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ import type { ReadonlySimulationState, StateCommands, ReasoningFootprint, EntityInput } from '#core/types'
6
+ import type { ExecutiveOutputFull } from '#faculties/executive.engine/types'
7
+ import type { CognitiveBus } from '#cognition/bus'
8
+ import type { ExecutiveSummarizer } from '#llm/summarizer'
9
+ import type { GoalManager } from '#faculties/goal.manager'
10
+ import type { GenerativeModel } from '#cognition/generative.model'
11
+ import type { SemanticIntegrator } from '#faculties/semantic.engine/integrator'
12
+
13
+ /** Maps the LLM's evidence enum to a numeric supportingEpisodes value for the belief store. */
14
+ export const EVIDENCE_TO_COUNT: Record<string, number> = {
15
+ single_observation: 1,
16
+ recurring_pattern: 3,
17
+ strong_pattern: 8,
18
+ }
19
+
20
+ /** A manager-side mutation deferred until the tick is confirmed to commit (FN11). */
21
+ export type DeferredEffect = () => void
22
+
23
+ export interface BuiltCommands {
24
+ /** Entity/metric mutations the orchestrator applies at commit. */
25
+ commands: StateCommands
26
+ /**
27
+ * Manager-side writes (summarizer / goal / belief / effector registry + the
28
+ * action-diversity ring buffer) that mirror `commands`. `buildStateCommands`
29
+ * no longer runs these inline — the caller MUST invoke them only after the
30
+ * tick has committed. A pre-commit validator can abort the tick
31
+ * (orchestrator.ts:469-484), discarding `commands`; if the manager writes had
32
+ * already landed during react(), state and managers would drift with no
33
+ * compensation. Deferring keeps the dual-write atomic.
34
+ */
35
+ effects: DeferredEffect[]
36
+ }
37
+
38
+ export interface CommandDependencies {
39
+ goalManager: GoalManager | null
40
+ semanticIntegrator: SemanticIntegrator | null
41
+ summarizer: ExecutiveSummarizer | null
42
+ bus: CognitiveBus | null
43
+ salience: GenerativeModel
44
+ /**
45
+ * Entity ID of the conversation participant whose message triggered the
46
+ * current executive cycle (escalation context). Passed into addGoal() so
47
+ * new goals carry a causal link back to their requester.
48
+ */
49
+ requestingEntityId?: string
50
+ requestingThreadId?: string
51
+ }
52
+
53
+ /**
54
+ * Convert an ExecutiveOutputFull into StateCommands plus a set of deferred
55
+ * manager-side mutations (FN11).
56
+ *
57
+ * This function is now PURE: it performs no manager writes. It returns the
58
+ * entity/metric `commands` AND an `effects` list mirroring them. The caller runs
59
+ * `effects` only after the tick is confirmed to commit, so a pre-commit abort
60
+ * can never leave the summarizer / goal manager / belief store / effector
61
+ * registry ahead of discarded entity commands.
62
+ */
63
+ export function buildStateCommands(
64
+ output: ExecutiveOutputFull,
65
+ footprint: ReasoningFootprint,
66
+ state: ReadonlySimulationState,
67
+ deps: CommandDependencies,
68
+ recentActionTypes: string[]
69
+ ): BuiltCommands {
70
+ const commands: StateCommands = { set: [], delete: [], metrics: [] }
71
+ const effects: DeferredEffect[] = []
72
+
73
+ // ── Persist rolling summary ───────────────────────────────
74
+ if( deps.summarizer ){
75
+ const summarizer = deps.summarizer
76
+ // Persist the *projected* post-record snapshot so the entity matches the
77
+ // summarizer state the deferred record() produces on commit.
78
+ commands.set!.push({
79
+ id: 'executive-rolling-summary',
80
+ type: 'executive.summary',
81
+ metadata: summarizer.projectedSnapshot( output.reasoning )
82
+ })
83
+
84
+ effects.push( () => summarizer.record( output.reasoning ) )
85
+ }
86
+
87
+ // ── Decisions ──────────────────────────────────────────────
88
+ // The agency pipeline is the sole action system: the executive deliberates (via
89
+ // a facet) and biases the competition, but no longer emits parameterless
90
+ // `actions[]` as decision.records. It still forms goals / beliefs / narrative.
91
+ //
92
+ // Ideomotor leg (AffordanceSource.ideomotor): the executive's imagined communicate
93
+ // actions become `ideomotor.intent` entities the AffordanceSynthesizer surfaces as
94
+ // competing reach-out affordances next tick — executive intention ENTERS the
95
+ // competition, it does not bypass it. Refreshed each cycle.
96
+ const ideo = buildIdeomotorIntents( output, state, footprint )
97
+ commands.set!.push( ...ideo.set )
98
+ commands.delete!.push( ...ideo.delete )
99
+
100
+ // ── Apply Plans ────────────────────────────────────────────
101
+ if( output.plans )
102
+ for( const plan of output.plans )
103
+ commands.set!.push({
104
+ id: `plan-executive-${plan.goalId}-${footprint.tickObserved}`,
105
+ type: 'plan',
106
+ metadata: {
107
+ goalId: plan.goalId,
108
+ steps: plan.steps.map( ( s, i ) => ({ ...s, order: i }) ),
109
+ estimatedCost: plan.estimatedCost,
110
+ confidence: plan.feasibility,
111
+ status: 'ready',
112
+ source: 'executive'
113
+ }
114
+ })
115
+
116
+ // ── Apply New Beliefs ──────────────────────────────────────
117
+ if( output.newBeliefs && deps.semanticIntegrator ){
118
+ const integrator = deps.semanticIntegrator
119
+ for( let idx = 0; idx < output.newBeliefs.length; idx++ ){
120
+ const nb = output.newBeliefs[ idx ]!
121
+ const belief = {
122
+ // FN12: deterministic id from the sim clock (tickObserved) + batch index,
123
+ // not Date.now()+Math.random() — so the same seed+inputs reproduce the
124
+ // same entity graph on replay.
125
+ id: `belief-executive-${footprint.tickObserved}-${idx}`,
126
+ statement: nb.statement,
127
+ category: nb.category as any, // Belief['category'] — 'world_fact' | 'self_belief' | 'social_belief' | 'causal_rule' | 'pattern'
128
+ confidence: nb.confidence,
129
+ supportingEpisodes: EVIDENCE_TO_COUNT[ nb.evidence ] ?? 1,
130
+ lastUpdatedAt: footprint.tickObserved,
131
+ tags: nb.tags ?? []
132
+ }
133
+
134
+ effects.push( () => integrator.integrateExecutiveBelief( belief, footprint.tickObserved ) )
135
+
136
+ commands.set!.push({
137
+ id: belief.id,
138
+ type: 'belief',
139
+ metadata: {
140
+ statement: belief.statement,
141
+ category: belief.category,
142
+ confidence: belief.confidence,
143
+ supportingEpisodes: belief.supportingEpisodes,
144
+ tags: belief.tags
145
+ }
146
+ })
147
+ }
148
+ }
149
+
150
+ // ── Apply Known-Entity Updates (Phase 2.2 — conscious learning about others) ──
151
+ // Learned facts become keid-tagged social beliefs (so they ride the episodic
152
+ // consolidator + vector memory and surface in working memory — like any belief). The
153
+ // identity/affective bits (name, felt valence) go to known.entity.tracker via an event,
154
+ // keeping it the single writer of the ke-<keid> dossier.
155
+ if( output.knownEntityUpdates && output.knownEntityUpdates.length > 0 ){
156
+ const integrator = deps.semanticIntegrator
157
+ const bus = deps.bus
158
+ output.knownEntityUpdates.forEach( ( u, ui ) => {
159
+ if( !u.keid || u.keid === 'agent-self' ) return
160
+
161
+ const facts = u.learned ?? []
162
+ facts.forEach( ( fact, fi ) => {
163
+ if( !fact || !integrator ) return
164
+ const belief = {
165
+ id: `belief-ke-${footprint.tickObserved}-${ui}-${fi}`,
166
+ statement: fact,
167
+ category: 'social_belief' as const,
168
+ confidence: 0.7,
169
+ supportingEpisodes: 1,
170
+ lastUpdatedAt: footprint.tickObserved,
171
+ tags: [ 'social', 'known-entity', `keid:${u.keid}` ],
172
+ }
173
+ effects.push( () => integrator.integrateExecutiveBelief( belief, footprint.tickObserved ) )
174
+ commands.set!.push({ id: belief.id, type: 'belief', metadata: {
175
+ statement: belief.statement, category: belief.category, confidence: belief.confidence,
176
+ supportingEpisodes: belief.supportingEpisodes, tags: belief.tags } })
177
+ })
178
+
179
+ if( bus && ( u.name || u.feeling != null ) )
180
+ effects.push( () => bus.publish({
181
+ type: 'known.entity.learned', version: 1, sourceEngine: 'executive',
182
+ salience: 0.5, payload: { keid: u.keid, name: u.name, feeling: u.feeling },
183
+ }) )
184
+ })
185
+ }
186
+
187
+ // ── Apply Introspection ────────────────────────────────────
188
+ if( output.introspection )
189
+ commands.set!.push({
190
+ id: `introspection-executive-${footprint.tickObserved}`,
191
+ type: 'introspection',
192
+ metadata: output.introspection
193
+ })
194
+
195
+ // ── Apply Narrative ────────────────────────────────────────
196
+ if( output.narrative )
197
+ commands.set!.push({
198
+ id: `narrative-executive-${footprint.tickObserved}`,
199
+ type: 'narrative_chapter',
200
+ metadata: {
201
+ narrative: output.narrative,
202
+ themes: output.narrativeThemes ?? [],
203
+ currentSelfView: output.currentSelfView ?? ''
204
+ }
205
+ })
206
+
207
+ // ── Apply Goal Changes ─────────────────────────────────────
208
+ if( output.newGoals && deps.goalManager ){
209
+ const goalManager = deps.goalManager
210
+ const requestingEntityId = deps.requestingEntityId
211
+ const requestingThreadId = deps.requestingThreadId
212
+
213
+ // If this output also contains conversation replies, auto-tag any new goals
214
+ // with communication metadata so _nudgeActionGoals can match them.
215
+ for( const goal of output.newGoals.slice( 0, 2 ) )
216
+ effects.push( () => goalManager.addGoal(
217
+ goal.description,
218
+ goal.priority,
219
+ goal.tags,
220
+ undefined,
221
+ undefined,
222
+ goal.completionType as any,
223
+ goal.completionCondition,
224
+ undefined, // id — auto-generated
225
+ requestingEntityId,
226
+ requestingThreadId
227
+ ))
228
+ }
229
+
230
+ if( output.goalsToAbandon && deps.goalManager ){
231
+ const goalManager = deps.goalManager
232
+ for( const ga of output.goalsToAbandon )
233
+ effects.push( () => goalManager.abandonGoal( ga.goalId, ga.reason ) )
234
+ }
235
+
236
+ if( output.goalsToReprioritize && deps.goalManager ){
237
+ const goalManager = deps.goalManager
238
+ for( const gr of output.goalsToReprioritize )
239
+ effects.push( () => goalManager.updateGoalPriority( gr.goalId, gr.newPriority ) )
240
+ }
241
+
242
+ // Created effectors are owned by the agency repertoire now (skills proceduralize
243
+ // from enaction); the executive no longer composes effectors in its output.
244
+
245
+ // ── Apply Self-Observations ────────────────────────────────
246
+ if( output.selfObservations )
247
+ output.selfObservations.slice( 0, 5 ).forEach( ( obs, idx ) => {
248
+ commands.set!.push({
249
+ id: `self-obs-slot-${(footprint.tickObserved + idx) % 20}`,
250
+ type: 'self_observation',
251
+ metadata: { observation: obs, tick: footprint.tickObserved }
252
+ })
253
+ })
254
+
255
+ // ── Metrics ────────────────────────────────────────────────
256
+ commands.metrics!.push(
257
+ ['executive.last_tick', footprint.tickObserved ],
258
+ ['executive.action_count', output.actions.length ],
259
+ ['executive.plan_count', output.plans?.length ?? 0 ],
260
+ ['executive.belief_count', output.newBeliefs?.length ?? 0 ],
261
+ ['cognitive.load', Math.min(1, output.actions.length / 5) ],
262
+ ['executive.confidence', output.confidence ]
263
+ )
264
+
265
+ // Action diversity metric
266
+ if( recentActionTypes.length > 0 ){
267
+ const uniqueTypes = new Set( recentActionTypes ).size
268
+
269
+ commands.metrics!.push([
270
+ 'executive.action_diversity',
271
+ uniqueTypes / recentActionTypes.length
272
+ ])
273
+ }
274
+
275
+ // ── Update action diversity ring buffer (deferred mutation) ─
276
+ // The diversity metric above reads the pre-update buffer (unchanged
277
+ // behaviour); the in-place mutation is deferred so an aborted tick's actions
278
+ // don't pollute the next cycle's diversity calculation.
279
+ effects.push( () => {
280
+ for( const action of output.actions )
281
+ recentActionTypes.push( action.type )
282
+
283
+ if( recentActionTypes.length > 5 )
284
+ recentActionTypes.splice( 0, recentActionTypes.length - 5 )
285
+ })
286
+
287
+ return { commands, effects }
288
+ }
289
+
290
+ /**
291
+ * Publish cognitive events to the bus after reasoning completes.
292
+ */
293
+ export function publishCognitiveEvents(
294
+ output: ExecutiveOutputFull,
295
+ footprint: ReasoningFootprint,
296
+ bus: CognitiveBus | null,
297
+ coherenceVersion: number,
298
+ salience: GenerativeModel
299
+ ): void {
300
+ if( !bus ) return
301
+
302
+ // interpretation.formed — always broadcast after each executive cycle
303
+ bus.publish({
304
+ type: 'executive.interpretation.formed',
305
+ version: 1,
306
+ sourceEngine: 'executive-engine',
307
+ salience: 0.8,
308
+ payload: {
309
+ confidence: output.confidence,
310
+ reasoning: output.reasoning.slice( 0, 400 ),
311
+ actionTypes: output.actions.map( a => a.type ),
312
+ tick: footprint.tickObserved,
313
+ coherenceVersion
314
+ }
315
+ })
316
+
317
+ // decision.rationale — for each action decided
318
+ for( const action of output.actions )
319
+ bus.publish({
320
+ type: 'executive.decision.rationale',
321
+ version: 1,
322
+ sourceEngine: 'executive-engine',
323
+ salience: 0.6,
324
+ payload: {
325
+ actionType: action.type,
326
+ confidence: output.confidence,
327
+ reasoning: action.reasoning.slice( 0, 200 ),
328
+ tick: footprint.tickObserved
329
+ }
330
+ })
331
+
332
+ // goal.proposed — when executive proposes new goals
333
+ if( output.newGoals?.length )
334
+ bus.publish({
335
+ type: 'executive.goal.proposed',
336
+ version: 1,
337
+ sourceEngine: 'executive-engine',
338
+ salience: 0.7,
339
+ payload: {
340
+ count: output.newGoals.length,
341
+ goals: output.newGoals.map( g => ({
342
+ description: g.description,
343
+ priority: g.priority,
344
+ })),
345
+ confidence: output.confidence,
346
+ tick: footprint.tickObserved
347
+ }
348
+ })
349
+
350
+ // self.reflection — when executive includes introspection
351
+ if( output.introspection )
352
+ bus.publish({
353
+ type: 'executive.self.reflection',
354
+ version: 1,
355
+ sourceEngine: 'executive-engine',
356
+ salience: 0.7,
357
+ payload: {
358
+ confidence: output.confidence,
359
+ identifiedBiases: output.introspection.identifiedBiases ?? [],
360
+ lessonsLearned: output.introspection.lessonsLearned ?? [],
361
+ recommendations: output.introspection.recommendations ?? [],
362
+ tick: footprint.tickObserved
363
+ }
364
+ })
365
+
366
+ // prediction.formed — top-down signal for satellite engines
367
+ const predictedDomains = inferPredictedDomains( output )
368
+
369
+ bus.publish({
370
+ type: 'executive.prediction.formed',
371
+ version: 1,
372
+ sourceEngine: 'executive-engine',
373
+ salience: Math.max( 0.5, salience.observe('executive.prediction', output.confidence ).salience ),
374
+ payload: {
375
+ confidence: output.confidence,
376
+ predictedDomains,
377
+ predictedActions: output.actions.map( a => a.type ),
378
+ tick: footprint.tickObserved
379
+ }
380
+ })
381
+ }
382
+
383
+ const COMMUNICATE_ACTION_TYPES = new Set([
384
+ 'communicate', 'speak', 'initiate_conversation', 'reach-out', 'reach_out', 'talk', 'text', 'message',
385
+ ])
386
+
387
+ /** Resolve an executive action target (a display name OR a keid) to a known-entity keid. */
388
+ function resolveKnownEntity( target: string, state: ReadonlySimulationState ): string | undefined {
389
+ const t = target.trim().toLowerCase()
390
+ for( const e of state.entities.values() ){
391
+ if( e.type !== 'known-entity' ) continue
392
+ const m = e.metadata as Record<string, unknown> | undefined
393
+ const keid = typeof m?.['keid'] === 'string' ? m['keid'] as string : undefined
394
+ const name = typeof m?.['name'] === 'string' ? m['name'] as string : undefined
395
+ if( keid && keid.toLowerCase() === t ) return keid
396
+ if( name && name.toLowerCase() === t ) return keid
397
+ }
398
+ return undefined
399
+ }
400
+
401
+ /**
402
+ * Turn the executive's imagined communicate actions into `ideomotor.intent` entities
403
+ * (the ideomotor leg). The AffordanceSynthesizer surfaces them as competing reach-out
404
+ * affordances next tick. Refreshed each executive cycle — stale intents the executive
405
+ * no longer imagines are deleted, so a momentary "I'd like to reach out" doesn't linger.
406
+ */
407
+ function buildIdeomotorIntents(
408
+ output: ExecutiveOutputFull,
409
+ state: ReadonlySimulationState,
410
+ footprint: ReasoningFootprint,
411
+ ): { set: EntityInput[]; delete: string[] } {
412
+ const set: EntityInput[] = []
413
+ const seen = new Set<string>()
414
+ const priority = clamp01( output.confidence ?? 0.8 )
415
+
416
+ for( const action of output.actions ){
417
+ if( !COMMUNICATE_ACTION_TYPES.has( action.type.toLowerCase() ) ) continue
418
+ if( !action.target ) continue
419
+ const keid = resolveKnownEntity( action.target, state )
420
+ if( !keid || seen.has( keid ) ) continue
421
+ seen.add( keid )
422
+ set.push({
423
+ id: `ideomotor-reach-out-${ keid }`,
424
+ type: 'ideomotor.intent',
425
+ metadata: { schema: 'reach-out', targetEntityId: keid, priority, origin: 'executive', tick: footprint.tickObserved },
426
+ })
427
+ }
428
+
429
+ // Clear stale executive-sourced intents the executive no longer imagines this cycle.
430
+ const currentIds = new Set( set.map( s => s.id ) )
431
+ const del: string[] = []
432
+ for( const [ id, e ] of state.entities )
433
+ if( e.type === 'ideomotor.intent'
434
+ && ( e.metadata as Record<string, unknown> | undefined )?.['origin'] === 'executive'
435
+ && !currentIds.has( id ) )
436
+ del.push( id )
437
+
438
+ return { set, delete: del }
439
+ }
440
+
441
+ function clamp01( n: number ): number { return n < 0 ? 0 : n > 1 ? 1 : n }
442
+
443
+ function inferPredictedDomains( output: ExecutiveOutputFull ): string[] {
444
+ const domains = new Set<string>()
445
+ for( const action of output.actions ){
446
+ const t = action.type.toLowerCase()
447
+
448
+ if( t.includes('rest') || t.includes('sleep') || t.includes('energy') ) domains.add('energy')
449
+ if( t.includes('social') || t.includes('talk') || t.includes('text') ) domains.add('social')
450
+ if( t.includes('learn') || t.includes('reflect') || t.includes('memorize') ) domains.add('memory')
451
+ if( t.includes('plan') || t.includes('goal') ) domains.add('executive')
452
+ if( t.includes('meditat') || t.includes('calm') ) domains.add('stress')
453
+ }
454
+
455
+ if( output.introspection ) domains.add('metacognition')
456
+ if( output.newGoals && output.newGoals.length > 0 ) domains.add('executive')
457
+
458
+ return [ ...domains ]
459
+ }
@@ -0,0 +1,46 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/cognition/faculties/executive.engine/config.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ import type { ReadonlySimulationState } from '#core/types'
6
+ import type { ExecutiveEngineConfig } from '#faculties/executive.engine/types'
7
+
8
+ // ── Constants ────────────────────────────────────────────────
9
+
10
+ export const WORKSPACE_THRESHOLD = 0.4
11
+ export const BUFFER_SALIENCE_TRIGGER = 2.5
12
+ export const BUFFER_MAX_AGE_TICKS = 30
13
+
14
+ export const DEFAULT_EXECUTIVE_INTERVAL = 15
15
+ export const DEFAULT_COOLDOWN_TICKS = 5
16
+
17
+ // ── Runtime config reader ────────────────────────────────────
18
+
19
+ export interface ExecutiveRuntimeConfig {
20
+ executiveInterval: number
21
+ cooldownTicks: number
22
+ }
23
+
24
+ export function readRuntimeConfig(
25
+ state: ReadonlySimulationState,
26
+ base: ExecutiveEngineConfig
27
+ ): ExecutiveRuntimeConfig {
28
+ const cfg = state.entities.get('engine-config-executive')
29
+ if( !cfg )
30
+ return {
31
+ executiveInterval: base.executiveInterval ?? DEFAULT_EXECUTIVE_INTERVAL,
32
+ cooldownTicks: base.cooldownTicks ?? DEFAULT_COOLDOWN_TICKS
33
+ }
34
+
35
+ const p = cfg.metadata?.params as Record<string, number> | undefined
36
+ if( !p )
37
+ return {
38
+ executiveInterval: base.executiveInterval ?? DEFAULT_EXECUTIVE_INTERVAL,
39
+ cooldownTicks: base.cooldownTicks ?? DEFAULT_COOLDOWN_TICKS
40
+ }
41
+
42
+ return {
43
+ executiveInterval: p.executiveInterval ?? base.executiveInterval ?? DEFAULT_EXECUTIVE_INTERVAL,
44
+ cooldownTicks: p.cooldownTicks ?? base.cooldownTicks ?? DEFAULT_COOLDOWN_TICKS
45
+ }
46
+ }