@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,274 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/agency/proactive.communication.ts
3
+ // ─────────────────────────────────────────────────────────────
4
+
5
+ /**
6
+ * ProactiveCommunicator — the agency pipeline's communicate-enaction handler.
7
+ *
8
+ * Owned privately by the MotorSchemaExecutor (its only caller): when a `communicate`
9
+ * motor schema wins the action competition, this turns the decided intent into
10
+ * delivery + memory. It validates the request, emits the memory/state side-effects
11
+ * (`conversation.sent` + the shared `conversation.exchange`), and hands the actual
12
+ * outbox row(s) to the shared OutboxWriter. It does NOT own the row shape (the
13
+ * writer does) and does NOT gate (AccessGrants does, upstream in the executor).
14
+ *
15
+ * Effectors handled: listen, talk, text, gesture, broadcast
16
+ *
17
+ * Outbound flow:
18
+ * agency MotorSchemaExecutor → ProactiveCommunicator → OutboxWriter.enqueue
19
+ * → OutboxController drains per tick → TransportController emits (or SSE)
20
+ */
21
+
22
+ import { logger } from '#core/logger'
23
+ import { wallClock } from '#core/wall.clock'
24
+ import type { ActionRequest, ActionResult } from '#types'
25
+ import type { ReadonlySimulationState, StateCommands } from '#core/types'
26
+ import type { OutboxWriter } from '#stem/tracts/outbox.writer'
27
+ import type { SessionLogger } from '#stem/tracts/session.logger'
28
+ import { buildConversationExchange } from '#cognition/conversation.memory'
29
+
30
+ export interface ProactiveCommunicatorOptions {
31
+ /** Shared outbox producer — owns the row shape; the executor delegates pushes. */
32
+ writer: OutboxWriter
33
+ willId?: string
34
+ }
35
+
36
+ export class ProactiveCommunicator {
37
+ private _writer: OutboxWriter
38
+ private _willId: string
39
+ private _sessionLogger: SessionLogger | null = null
40
+
41
+ constructor( options: ProactiveCommunicatorOptions ){
42
+ this._writer = options.writer
43
+ this._willId = options.willId ?? 'will'
44
+ }
45
+
46
+ attachSessionLogger( logger: SessionLogger | null ): void {
47
+ this._sessionLogger = logger
48
+ }
49
+
50
+ async executeAction(
51
+ request: ActionRequest,
52
+ _state: ReadonlySimulationState,
53
+ ): Promise<ActionResult> {
54
+ const commands: StateCommands = { metrics: [] }
55
+
56
+ switch( request.effector ){
57
+ case 'listen': return this._handleListen( request, commands )
58
+ case 'talk': return this._handleOutboundMessage('talk', request, commands )
59
+ case 'text': return this._handleOutboundMessage('text', request, commands )
60
+ case 'gesture': return this._handleGesture( request, commands )
61
+ case 'broadcast': return this._handleBroadcast( request, commands )
62
+ default:
63
+ return {
64
+ success: false,
65
+ description: `ProactiveCommunicator does not handle: ${request.effector}`,
66
+ commands,
67
+ feedback: { outcomeQuality: 0, surprise: 0, lessons: [] },
68
+ }
69
+ }
70
+ }
71
+
72
+ // ── Handlers ─────────────────────────────────────────────────
73
+
74
+ private async _handleListen(
75
+ _request: ActionRequest,
76
+ commands: StateCommands,
77
+ ): Promise<ActionResult> {
78
+ return {
79
+ success: true,
80
+ description: `You open yourself to incoming communication. Others may now reach you through available channels.`,
81
+ commands,
82
+ feedback: {
83
+ outcomeQuality: 1.0,
84
+ surprise: 0.05,
85
+ lessons: [ 'Being reachable allows others to connect with you.' ],
86
+ },
87
+ }
88
+ }
89
+
90
+ private async _handleGesture(
91
+ request: ActionRequest,
92
+ commands: StateCommands,
93
+ ): Promise<ActionResult> {
94
+ const targetEntityId = request.targetEntityId
95
+ ?? ( request.parameters?.targetEntityId as string )
96
+ ?? 'unknown'
97
+ const gestureType = ( request.parameters?.gestureType as string ) ?? 'gesture'
98
+
99
+ this._writer.enqueue({
100
+ targetEntityId,
101
+ content: gestureType,
102
+ effectorName: 'gesture',
103
+ gestureType,
104
+ })
105
+
106
+ return {
107
+ success: true,
108
+ description: `You ${gestureType} toward ${targetEntityId}. The gesture is directed and sincere.`,
109
+ commands,
110
+ feedback: {
111
+ outcomeQuality: 0.8,
112
+ surprise: 0.1,
113
+ lessons: [ 'Non-verbal communication carries its own weight.' ],
114
+ },
115
+ }
116
+ }
117
+
118
+ private async _handleBroadcast(
119
+ request: ActionRequest,
120
+ commands: StateCommands,
121
+ ): Promise<ActionResult> {
122
+ const rawMessages = request.parameters?.messages
123
+ const contentParam = ( request.parameters?.content as string ) ?? ''
124
+ const targetEntityIds = ( request.parameters?.targetEntityIds as string[] ) ?? []
125
+
126
+ const bubbles: string[] = Array.isArray( rawMessages )
127
+ ? ( rawMessages as string[] ).filter( Boolean )
128
+ : [ contentParam || ( request.parameters?.message as string ) || '' ].filter( Boolean )
129
+
130
+ const finalContent = bubbles.join(' ')
131
+ const target = targetEntityIds.length > 0 ? targetEntityIds.join(',') : '*'
132
+ this._writer.enqueue({
133
+ targetEntityId: target,
134
+ content: finalContent,
135
+ effectorName: 'broadcast',
136
+ })
137
+
138
+ return {
139
+ success: true,
140
+ description: `You broadcast: "${finalContent.slice( 0, 80 )}${finalContent.length > 80 ? '…' : ''}"`,
141
+ commands,
142
+ feedback: {
143
+ outcomeQuality: 0.75,
144
+ surprise: 0.2,
145
+ lessons: [ 'Broadcasts reach multiple entities simultaneously.' ],
146
+ },
147
+ }
148
+ }
149
+
150
+ private async _handleOutboundMessage(
151
+ effectorName: 'talk' | 'text',
152
+ request: ActionRequest,
153
+ commands: StateCommands,
154
+ ): Promise<ActionResult> {
155
+ const targetEntityId = request.targetEntityId
156
+ ?? ( request.parameters?.targetEntityId as string )
157
+ const targetEntityName = ( request.parameters?.targetEntityName as string ) ?? targetEntityId ?? 'them'
158
+
159
+ // The executive always writes the actual words — no composition step.
160
+ // Accept `messages` (array), or legacy `message`/`content` (single string).
161
+ const rawMessages = request.parameters?.messages
162
+ const bubbles: string[] = Array.isArray( rawMessages )
163
+ ? ( rawMessages as string[] ).filter( Boolean )
164
+ : [ ( request.parameters?.message as string )
165
+ || ( request.parameters?.content as string )
166
+ || '' ].filter( Boolean )
167
+
168
+ if( !targetEntityId ){
169
+ return {
170
+ success: false,
171
+ description: `You want to ${effectorName} but there is no one specific to reach out to.`,
172
+ commands,
173
+ feedback: {
174
+ outcomeQuality: 0,
175
+ surprise: 0.2,
176
+ lessons: [ 'Specify a targetEntityId to send a message.' ],
177
+ },
178
+ }
179
+ }
180
+
181
+ if( bubbles.length === 0 ){
182
+ return {
183
+ success: false,
184
+ description: `You wanted to ${effectorName} ${targetEntityName} but didn't write anything.`,
185
+ commands,
186
+ feedback: { outcomeQuality: 0, surprise: 0.1, lessons: [ 'Provide a messages array with the actual words.' ] },
187
+ }
188
+ }
189
+
190
+ // Generate outbox message IDs first so we can embed them in conversation.sent
191
+ // and correlate deliveries back to this intent (TODO 11.3).
192
+ const originalMessage = ( request.parameters?.originalMessage as string ) ?? ''
193
+ const deliveryTick = ( request.parameters?.tick as number ) ?? 0
194
+ const replyToMessageId = ( request.parameters?.replyToMessageId as string ) ?? undefined
195
+ const isAck = ( request.parameters?.isAck as boolean ) ?? false
196
+
197
+ const outboxMessageIds: string[] = []
198
+ bubbles.forEach( ( bubble, i ) => {
199
+ logger.info(`[communication] pushing to outbox: ${effectorName} → ${targetEntityId} "${bubble.slice( 0, 80 )}"`)
200
+ outboxMessageIds.push( this._writer.enqueue({
201
+ targetEntityId,
202
+ targetEntityName,
203
+ content: bubble,
204
+ effectorName,
205
+ replyToMessageId,
206
+ }, `-${ i }` ) )
207
+ })
208
+
209
+ // Write the intent record at push time so context-builder can see what we said.
210
+ // NOTE (11.3): this entity tracks intent, not confirmation. confirmMessageDelivery()
211
+ // will update it with delivered:true once the client ACKs.
212
+ const sentEntityId = `conv-sent-${targetEntityId}-${deliveryTick}`
213
+
214
+ commands.set ??= []
215
+ commands.set.push({
216
+ id: sentEntityId,
217
+ type: 'conversation.sent',
218
+ createdAt: wallClock(),
219
+ metadata: {
220
+ targetEntityId,
221
+ targetEntityName,
222
+ messageCount: bubbles.length,
223
+ preview: bubbles[0]?.slice( 0, 100 ) ?? '',
224
+ effectorName,
225
+ tick: deliveryTick,
226
+ delivered: false,
227
+ isAck,
228
+ outboxMessageIds, // enables confirmMessageDelivery to update this entity
229
+ },
230
+ })
231
+
232
+ // Log the outbound message for session auditing (D4)
233
+ this._sessionLogger?.write({
234
+ type: 'conversation.out',
235
+ tick: deliveryTick,
236
+ targetEntityId,
237
+ targetEntityName,
238
+ messageCount: bubbles.length,
239
+ messages: bubbles.map( b => b.slice( 0, 300 ) ),
240
+ preview: bubbles[0]?.slice( 0, 100 ) ?? '',
241
+ isAck,
242
+ })
243
+
244
+ const fullReply = bubbles.join(' ')
245
+
246
+ // Persist every outbound as a conversation.exchange WM item so it consolidates
247
+ // into episodic + vector memory — the same shape the AuditionEngine uses for
248
+ // facet replies (built by the shared buildConversationExchange). UNCONDITIONAL
249
+ // (option a): master-initiated outreach (no inbound `originalMessage`) must also
250
+ // be remembered, so a facet later spawned to continue recalls what was said.
251
+ commands.set ??= []
252
+ commands.set.push( buildConversationExchange({
253
+ entityId: targetEntityId,
254
+ entityName: targetEntityName,
255
+ userMessage: originalMessage,
256
+ willReply: fullReply,
257
+ tick: ( request.parameters?.tick as number ) ?? 0,
258
+ idSeed: wallClock(),
259
+ createdAt: wallClock(),
260
+ }) )
261
+
262
+ return {
263
+ success: true,
264
+ description: `You reach out to ${targetEntityName}: "${fullReply.slice( 0, 80 )}${fullReply.length > 80 ? '…' : ''}"`,
265
+ commands,
266
+ feedback: {
267
+ outcomeQuality: 0.85,
268
+ surprise: 0.15,
269
+ lessons: [ `Your message is queued for delivery to ${targetEntityName}.` ],
270
+ },
271
+ }
272
+ }
273
+
274
+ }
@@ -0,0 +1,82 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/agency/reconcile.learning.ts — host-ack reconciliation
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // Closes the async loop for `external` / `communicate` enactions. When the
6
+ // MotorSchemaExecutor dispatches a host-owned effector it leaves the intent
7
+ // 'awaiting' and emits `agency.invocation`. The host later executes it and calls
8
+ // back; `reconcileInvocation` turns that callback into the `agency.outcome` the
9
+ // ReafferenceEngine already consumes — which both teaches the skill the real
10
+ // result AND frees the serial Will (reafference deletes the awaiting intent via
11
+ // the outcome's `intentId`).
12
+ //
13
+ // This is the agency-native equivalent of the legacy effectorController.
14
+ // confirmExecution — same efference-copy / reafference contract, new vocabulary.
15
+ // The stem wires its host ack endpoint to call this and write the returned entity.
16
+ // ─────────────────────────────────────────────────────────────
17
+
18
+ import type { EntityInput, Tick } from '#core/types'
19
+
20
+ export interface HostAckResult {
21
+ success: boolean
22
+ /** 0..1 — how good the world's reply was. Defaults from `success` when omitted. */
23
+ outcomeQuality?: number
24
+ /** −1..1 felt valence of the outcome. */
25
+ valence?: number
26
+ description?: string
27
+ }
28
+
29
+ /**
30
+ * Build the `agency.outcome` entity that confirms an awaiting invocation. The
31
+ * caller (stem host-ack endpoint) writes it via `stateManager.setEntity`; the
32
+ * ReafferenceEngine consumes it next tick — learning from it and deleting the
33
+ * awaiting intent identified by `intentId`.
34
+ *
35
+ * `schema` is the awaiting intent's schema (the host has it from the
36
+ * `agency.invocation` payload); `predictedReward`/`predictedValence` are the
37
+ * efference copy the executor persisted on the intent, so surprise is honest.
38
+ *
39
+ * `provenance` carries the awaiting intent's plan link (planId/stepId) when it was
40
+ * committed from a plan's frontier prior. It rides on the agency.outcome so the
41
+ * ReafferenceEngine — the engine that consumes async-acked outcomes — can emit the
42
+ * `action.outcome{planId,stepId}` the PlanningEngine advances on. (The executor
43
+ * emits that itself for sync/timeout outcomes; the host-ack path has no executor in
44
+ * the loop, so reafference is the single emitter for it — see ReafferenceEngine.)
45
+ */
46
+ export function reconcileInvocation(
47
+ intentId: string,
48
+ schema: string,
49
+ result: HostAckResult,
50
+ tick: Tick,
51
+ predicted: { reward: number; valence: number } = { reward: 0.5, valence: 0 },
52
+ provenance: { planId?: string; stepId?: string } = {},
53
+ ): EntityInput {
54
+ const outcomeQuality = result.outcomeQuality ?? ( result.success ? 0.8 : 0.1 )
55
+ const valence = result.valence ?? ( result.success ? 0.2 : -0.2 )
56
+ const surprise = clamp01( Math.abs( predicted.reward - outcomeQuality ) )
57
+
58
+ return {
59
+ id: `agency-outcome-${ tick }-${ intentId }`,
60
+ type: 'agency.outcome',
61
+ metadata: {
62
+ schema,
63
+ intentId,
64
+ success: result.success,
65
+ outcomeQuality,
66
+ valence,
67
+ predictedReward: predicted.reward,
68
+ predictedValence: predicted.valence,
69
+ surprise,
70
+ description: result.description ?? ( result.success ? 'The world confirmed the action.' : 'The world rejected the action.' ),
71
+ mode: 'external',
72
+ tick,
73
+ reconciled: true,
74
+ ...( provenance.planId ? { planId: provenance.planId } : {} ),
75
+ ...( provenance.stepId ? { stepId: provenance.stepId } : {} ),
76
+ },
77
+ }
78
+ }
79
+
80
+ function clamp01( n: number ): number {
81
+ return n < 0 ? 0 : n > 1 ? 1 : n
82
+ }
@@ -0,0 +1,59 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/agency/schemas/external.ts — host-owned domain effectors
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // A host (game engine, app, robot) declares the domain effectors its world
6
+ // supports — `move`, `attack`, `trade`, `give`, `use`, … — via a profile's
7
+ // `effectors` list or the Will's `allowedGenericEffectors`. This turns those
8
+ // declarations into enactable MotorSchemas so they enter the agency loop like
9
+ // anything else: the AffordanceSynthesizer surfaces them in the field, the
10
+ // ActionSelector competes them, and the MotorSchemaExecutor routes the chosen
11
+ // one to the host via the `external` enaction mode (emitted now, acked later,
12
+ // the result returning as reafference the Will learns from).
13
+ //
14
+ // Excluded: the communication surface (listen/talk/text/gesture/broadcast),
15
+ // which is governed by AccessGrants + the ProactiveCommunicator; and any name
16
+ // that shadows an innate stance (the innate floor already provides it).
17
+ //
18
+ // Scope (Phase 1): objectless schemas — the Will chooses the act and the host
19
+ // resolves the target. Entity-bound external effectors (e.g. attack a specific
20
+ // perceived entity) are a follow-up; the synthesizer currently binds a single
21
+ // entity schema. See CUSTOM_EFFECTOR_WIRING_TODO.md.
22
+ // ─────────────────────────────────────────────────────────────
23
+
24
+ import type { MotorSchema } from '#agency/types'
25
+ import { EXPLICIT_EFFECTORS } from '#agency/access.grants'
26
+ import { INNATE_SCHEMA_BY_ID } from '#agency/schemas/innate'
27
+
28
+ /** Default effort/energy demand for a host action when none is specified. */
29
+ const DEFAULT_EXTERNAL_COST = 0.15
30
+
31
+ /**
32
+ * Build enactable MotorSchemas for a host's declared domain effectors. Comms
33
+ * names and innate-shadowing names are filtered out; the rest become objectless,
34
+ * `external`-tagged primitives that route to the host on enaction.
35
+ */
36
+ export function externalSchemas( effectors?: string[] | null ): MotorSchema[] {
37
+ const seen = new Set<string>()
38
+ const out: MotorSchema[] = []
39
+
40
+ for( const name of effectors ?? [] ){
41
+ if( typeof name !== 'string' || name.length === 0 ) continue
42
+ if( EXPLICIT_EFFECTORS.has( name ) ) continue // communication — handled by AccessGrants
43
+ if( INNATE_SCHEMA_BY_ID.has( name ) ) continue // shadows an innate stance
44
+ if( seen.has( name ) ) continue
45
+ seen.add( name )
46
+
47
+ out.push({
48
+ id: name,
49
+ kind: 'primitive',
50
+ source: 'external',
51
+ cost: DEFAULT_EXTERNAL_COST,
52
+ binds: 'none',
53
+ baseValence: 0,
54
+ tags: [ 'external', 'host' ],
55
+ })
56
+ }
57
+
58
+ return out
59
+ }
@@ -0,0 +1,111 @@
1
+ // ─────────────────────────────────────────────────────────────
2
+ // src/agency/schemas/innate.ts — the always-on floor of the field
3
+ // ─────────────────────────────────────────────────────────────
4
+ //
5
+ // Innate schemas are the reflexive floor of agency — the possibilities a mind
6
+ // always has available simply by being an embodied perceiver, before it has
7
+ // learned anything. Most need no object (orient, rest, reflect); two bind to
8
+ // what perception surfaces (`inspect` a percept, `reach-out` to a known mind).
9
+ //
10
+ // This is NOT a catalog the executive picks from. It is the seed set the
11
+ // AffordanceSynthesizer draws on so the field is never empty; learned composite
12
+ // schemas (Phase 3) are layered on top via the repertoire.
13
+ // ─────────────────────────────────────────────────────────────
14
+
15
+ import type { MotorSchema } from '#agency/types'
16
+
17
+ export const INNATE_SCHEMAS: MotorSchema[] = [
18
+ // ── objectless stances ───────────────────────────────────────
19
+ {
20
+ id: 'orient',
21
+ kind: 'primitive',
22
+ source: 'innate',
23
+ binds: 'none',
24
+ cost: 0.05,
25
+ baseValence: 0.0,
26
+ tags: [ 'perception', 'reflexive' ],
27
+ },
28
+ {
29
+ id: 'attend',
30
+ kind: 'primitive',
31
+ source: 'innate',
32
+ binds: 'none',
33
+ cost: 0.08,
34
+ preconditions: [ { metric: 'energy.level', op: 'gt', value: 10 } ],
35
+ baseValence: 0.0,
36
+ tags: [ 'attention', 'meta-cognition' ],
37
+ },
38
+ {
39
+ id: 'rest',
40
+ kind: 'primitive',
41
+ source: 'innate',
42
+ binds: 'none',
43
+ cost: 0.0,
44
+ preconditions: [ { metric: 'energy.level', op: 'lt', value: 95 } ],
45
+ baseValence: 0.15,
46
+ tags: [ 'self-care', 'regulatory' ],
47
+ },
48
+ {
49
+ id: 'withdraw',
50
+ kind: 'primitive',
51
+ source: 'innate',
52
+ binds: 'none',
53
+ cost: 0.03,
54
+ baseValence: 0.05,
55
+ tags: [ 'self-protection', 'regulatory' ],
56
+ },
57
+ {
58
+ id: 'reflect',
59
+ kind: 'primitive',
60
+ source: 'innate',
61
+ binds: 'none',
62
+ cost: 0.06,
63
+ preconditions: [ { metric: 'energy.level', op: 'gt', value: 10 } ],
64
+ baseValence: 0.05,
65
+ tags: [ 'cognitive', 'meta-cognition', 'internal' ],
66
+ },
67
+ {
68
+ id: 'wait',
69
+ kind: 'primitive',
70
+ source: 'innate',
71
+ binds: 'none',
72
+ cost: 0.01,
73
+ baseValence: 0.0,
74
+ tags: [ 'neutral' ],
75
+ },
76
+ {
77
+ id: 'express',
78
+ kind: 'primitive',
79
+ source: 'innate',
80
+ binds: 'none',
81
+ cost: 0.02,
82
+ baseValence: 0.1,
83
+ tags: [ 'affective', 'expression' ],
84
+ },
85
+
86
+ // ── perception-bound possibilities ───────────────────────────
87
+ {
88
+ id: 'inspect',
89
+ kind: 'primitive',
90
+ source: 'perceptual',
91
+ binds: 'percept',
92
+ cost: 0.06,
93
+ preconditions: [ { metric: 'energy.level', op: 'gt', value: 8 } ],
94
+ baseValence: 0.05,
95
+ tags: [ 'perception', 'information' ],
96
+ },
97
+ {
98
+ id: 'reach-out',
99
+ kind: 'primitive',
100
+ source: 'social',
101
+ binds: 'entity',
102
+ cost: 0.1,
103
+ preconditions: [ { metric: 'energy.level', op: 'gt', value: 5 } ],
104
+ baseValence: 0.2,
105
+ tags: [ 'social', 'communication' ],
106
+ },
107
+ ]
108
+
109
+ /** Fast id → schema lookup over the innate floor. */
110
+ export const INNATE_SCHEMA_BY_ID: ReadonlyMap<string, MotorSchema> =
111
+ new Map( INNATE_SCHEMAS.map( s => [ s.id, s ] ) )