@mindot/will 0.4.0 → 0.6.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 (135) hide show
  1. package/README.md +32 -12
  2. package/dist/channels/discord.d.ts +2 -11
  3. package/dist/channels/discord.js.map +1 -1
  4. package/dist/channels/whatsapp.d.ts +72 -0
  5. package/dist/channels/whatsapp.js +252 -0
  6. package/dist/channels/whatsapp.js.map +1 -0
  7. package/dist/cli.js +837 -91
  8. package/dist/cli.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.js +620 -79
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp/effectors.d.ts +1 -1
  13. package/dist/mcp/effectors.js.map +1 -1
  14. package/dist/types-E9-HV-SW.d.ts +11 -0
  15. package/dist/{will-D-slky1N.d.ts → will-Bikuk4s2.d.ts} +56 -12
  16. package/package.json +12 -3
  17. package/src/channels/discord.ts +11 -11
  18. package/src/channels/roster.ts +1 -1
  19. package/src/channels/types.ts +1 -1
  20. package/src/channels/whatsapp.ts +318 -0
  21. package/src/cli.ts +46 -23
  22. package/src/cognition/acp.ts +28 -0
  23. package/src/cognition/agency/consequence.ts +174 -0
  24. package/src/cognition/agency/engines/action.selector.ts +301 -48
  25. package/src/cognition/agency/engines/affordance.synthesizer.ts +26 -16
  26. package/src/cognition/agency/engines/deliberation.engine.ts +28 -14
  27. package/src/cognition/agency/engines/motor.schema.executor.ts +86 -14
  28. package/src/cognition/agency/engines/reafference.engine.ts +122 -18
  29. package/src/cognition/agency/execution.primitives.ts +13 -13
  30. package/src/cognition/agency/proactive.communicator.ts +1 -1
  31. package/src/cognition/agency/reconcile.learning.ts +1 -1
  32. package/src/cognition/agency/revocation.ts +79 -0
  33. package/src/cognition/agency/schemas/repertoire.ts +2 -2
  34. package/src/cognition/agency/selection.scoring.ts +25 -9
  35. package/src/cognition/bus.ts +2 -2
  36. package/src/cognition/completion.inbox.ts +1 -1
  37. package/src/cognition/config.mirror.entities.ts +5 -5
  38. package/src/cognition/event.log.ts +2 -2
  39. package/src/cognition/event.schemas.ts +67 -67
  40. package/src/cognition/faculties/aesthetic.evaluator.ts +6 -6
  41. package/src/cognition/faculties/affective.blender.ts +36 -4
  42. package/src/cognition/faculties/attachment.evaluator.ts +6 -6
  43. package/src/cognition/faculties/attention.allocator.ts +63 -8
  44. package/src/cognition/faculties/autobiographical.narrator.ts +3 -3
  45. package/src/cognition/faculties/bias.detector.ts +7 -7
  46. package/src/cognition/faculties/circadian.oscillator.ts +3 -3
  47. package/src/cognition/faculties/confidence.calibrator.ts +7 -7
  48. package/src/cognition/faculties/dream.simulator.ts +5 -5
  49. package/src/cognition/faculties/empathy.simulator.ts +7 -7
  50. package/src/cognition/faculties/energy.regulator.ts +4 -4
  51. package/src/cognition/faculties/episodic.consolidator.ts +6 -6
  52. package/src/cognition/faculties/executive.engine/commands.ts +6 -6
  53. package/src/cognition/faculties/executive.engine/context.ts +42 -42
  54. package/src/cognition/faculties/executive.engine/deferred.effects.ts +2 -2
  55. package/src/cognition/faculties/executive.engine/engine.ts +27 -26
  56. package/src/cognition/faculties/executive.engine/facet.supervisor.ts +12 -12
  57. package/src/cognition/faculties/executive.engine/facet.ts +18 -18
  58. package/src/cognition/faculties/executive.engine/gating.ts +2 -2
  59. package/src/cognition/faculties/executive.engine/messages.ts +3 -3
  60. package/src/cognition/faculties/executive.engine/parser.ts +11 -11
  61. package/src/cognition/faculties/executive.engine/prompt.factory.ts +55 -55
  62. package/src/cognition/faculties/exteroception.ts +99 -5
  63. package/src/cognition/faculties/forgetting.curve.ts +3 -3
  64. package/src/cognition/faculties/frustration.evaluator.ts +6 -6
  65. package/src/cognition/faculties/goal.manager.ts +15 -15
  66. package/src/cognition/faculties/inhibition.controller.ts +3 -3
  67. package/src/cognition/faculties/interoception.ts +3 -3
  68. package/src/cognition/faculties/introspection.engine.ts +3 -3
  69. package/src/cognition/faculties/known.entity.tracker.ts +15 -15
  70. package/src/cognition/faculties/loss.evaluator.ts +2 -2
  71. package/src/cognition/faculties/moral.evaluator.ts +4 -4
  72. package/src/cognition/faculties/novelty.detector.ts +4 -4
  73. package/src/cognition/faculties/persona.consolidator.ts +12 -12
  74. package/src/cognition/faculties/planning.engine/engine.ts +47 -47
  75. package/src/cognition/faculties/planning.engine/plan.frontier.ts +5 -5
  76. package/src/cognition/faculties/planning.engine/plan.store.ts +1 -1
  77. package/src/cognition/faculties/planning.engine/plan.supervision.ts +20 -20
  78. package/src/cognition/faculties/reputation.tracker.ts +6 -6
  79. package/src/cognition/faculties/reward.evaluator.ts +4 -4
  80. package/src/cognition/faculties/self.model.updater.ts +8 -8
  81. package/src/cognition/faculties/semantic.engine/integrator.ts +15 -15
  82. package/src/cognition/faculties/sleep.pressure.regulator.ts +4 -4
  83. package/src/cognition/faculties/social.perception.ts +3 -3
  84. package/src/cognition/faculties/spaced.repetition.ts +2 -2
  85. package/src/cognition/faculties/stress.regulator.ts +27 -4
  86. package/src/cognition/faculties/task.switcher.ts +11 -6
  87. package/src/cognition/faculties/theory.of.mind.ts +6 -6
  88. package/src/cognition/faculties/threat.evaluator.ts +3 -3
  89. package/src/cognition/faculties/working.memory.ts +8 -8
  90. package/src/cognition/generative.model.ts +2 -2
  91. package/src/cognition/memory/vector.adapter.ts +5 -5
  92. package/src/cognition/memory/vector.content.ts +4 -4
  93. package/src/cognition/memory/vector.embedder.ts +9 -9
  94. package/src/cognition/persona.prior.ts +1 -1
  95. package/src/cognition/schema.registry.ts +2 -2
  96. package/src/cognition/senses/audition.engine/engine.ts +2 -2
  97. package/src/cognition/senses/base.sense.engine.ts +1 -1
  98. package/src/cognition/utilities/token.tracker.ts +11 -5
  99. package/src/core/abstracts.ts +1 -1
  100. package/src/core/completion.recorder.ts +2 -2
  101. package/src/core/serialization.ts +3 -3
  102. package/src/core/snapshot.manager.ts +1 -1
  103. package/src/core/state.manager.ts +1 -1
  104. package/src/core/utils.ts +1 -1
  105. package/src/host/boot.ts +59 -37
  106. package/src/host/utterances.ts +1 -1
  107. package/src/llm/index.ts +84 -34
  108. package/src/llm/summarizer.ts +4 -4
  109. package/src/llm/wire.contracts.ts +1 -1
  110. package/src/mcp/effectors.ts +10 -10
  111. package/src/mcp/server.ts +11 -11
  112. package/src/pma/eval.ts +1 -1
  113. package/src/pma/index.ts +21 -21
  114. package/src/runners/outreach.runner.ts +3 -3
  115. package/src/runners/social.runner.ts +1 -1
  116. package/src/runners/thin-shim.runner.ts +1 -1
  117. package/src/sdk/will.ts +20 -11
  118. package/src/serve/server.ts +12 -12
  119. package/src/stem/assembly.audit.ts +3 -3
  120. package/src/stem/guards/identity.coherence.ts +13 -12
  121. package/src/stem/guards/identity.guard.ts +22 -22
  122. package/src/stem/index.ts +11 -11
  123. package/src/stem/mind.ts +12 -12
  124. package/src/stem/tracts/biography.writer.ts +3 -3
  125. package/src/stem/tracts/effector.controller.ts +4 -4
  126. package/src/stem/tracts/health.reporter.ts +1 -1
  127. package/src/stem/tracts/outbox.controller.ts +4 -0
  128. package/src/stem/tracts/outbox.writer.ts +4 -4
  129. package/src/stem/tracts/pma.controller.ts +1 -1
  130. package/src/stem/tracts/replay.controller.ts +10 -10
  131. package/src/stem/tracts/sensory.controller.ts +2 -2
  132. package/src/stem/tracts/session.logger.ts +4 -4
  133. package/src/stem/tracts/transport/socketio.transport.ts +7 -7
  134. package/src/stem/tracts/transport/stream.transport.ts +2 -2
  135. package/src/stem/tracts/transport.controller.ts +15 -15
@@ -167,7 +167,7 @@ export class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
167
167
  case 'executive.prediction.formed': {
168
168
  const p = e.payload as { predictedDomains: string[]; confidence: number }
169
169
  if( p.predictedDomains.includes('metacognition') )
170
- this._model.setPrecision( 'self_model.change', 1.0 + p.confidence * 0.5 )
170
+ this._model.setPrecision('self_model.change', 1.0 + p.confidence * 0.5 )
171
171
 
172
172
  break
173
173
  }
@@ -196,13 +196,13 @@ export class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
196
196
  restore( snap: Record<string, unknown> ): void {
197
197
  if( !snap ) return
198
198
 
199
- if( typeof snap.executiveReflectionTick === 'number' )
199
+ if( typeof snap.executiveReflectionTick === 'number')
200
200
  this._executiveReflectionTick = snap.executiveReflectionTick
201
201
 
202
- if( typeof snap.lastEvaluationTick === 'number' )
202
+ if( typeof snap.lastEvaluationTick === 'number')
203
203
  this._lastEvaluationTick = snap.lastEvaluationTick
204
204
 
205
- if( typeof snap.experienceCountAtLastEval === 'number' )
205
+ if( typeof snap.experienceCountAtLastEval === 'number')
206
206
  this._experienceCountAtLastEval = snap.experienceCountAtLastEval
207
207
 
208
208
  if( Array.isArray( snap.domainPerformance ) )
@@ -231,7 +231,7 @@ export class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
231
231
  // closed edge of the metacognition cycle: a learned prior (written back by
232
232
  // the consolidator from the Will's own introspection) modulates how often
233
233
  // the self-model re-evaluates, without ever mutating the seeded base.
234
- const p = readEffectiveParams( state, 'engine-config-self-model' )
234
+ const p = readEffectiveParams( state, 'engine-config-self-model')
235
235
 
236
236
  if( p.minIntervalTicks != null ) this._minIntervalTicks = p.minIntervalTicks
237
237
  if( p.minNewExperiences != null ) this._minNewExperiences = p.minNewExperiences
@@ -483,7 +483,7 @@ export class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
483
483
  supportingEpisodes: da.sampleSize,
484
484
  lastUpdatedAt: tick,
485
485
  tags: [ da.domain, 'competence', 'self', 'positive' ]
486
- }, tick, 'self-model' )
486
+ }, tick, 'self-model')
487
487
 
488
488
  else if( da.successRate < 0.30 )
489
489
  this._semanticIntegrator.integrateExecutiveBelief({
@@ -494,14 +494,14 @@ export class SelfModelUpdater extends AsyncEngine implements CognitiveEngine {
494
494
  supportingEpisodes: da.sampleSize,
495
495
  lastUpdatedAt: tick,
496
496
  tags: [ da.domain, 'competence', 'self', 'negative' ]
497
- }, tick, 'self-model' )
497
+ }, tick, 'self-model')
498
498
  }
499
499
  }
500
500
 
501
501
  // Phase C + F: publish cognitive event — gated by prediction error
502
502
  const _bus = this._bus
503
503
  if( _bus ){
504
- const predErr = this._model.observe( 'self_model.change', changeMagnitude )
504
+ const predErr = this._model.observe('self_model.change', changeMagnitude )
505
505
  if( !predErr.gated )
506
506
  _bus.publish({
507
507
  type: 'self_model.updated',
@@ -87,7 +87,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
87
87
  * Confidence is capped by evidence count before integration — prevents the
88
88
  * executive from asserting high-certainty beliefs from thin episodic support.
89
89
  */
90
- integrateExecutiveBelief( belief: Belief, tick?: number, cause = 'executive' ): void {
90
+ integrateExecutiveBelief( belief: Belief, tick?: number, cause = 'executive'): void {
91
91
  const capped = this._capConfidenceByEvidence( belief.confidence, belief.supportingEpisodes )
92
92
  const result = this._integrateBelief({ ...belief, confidence: capped }, cause )
93
93
 
@@ -118,7 +118,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
118
118
  */
119
119
  private _restoreFromState( state: ReadonlySimulationState ): void {
120
120
  for( const entity of state.entities.values() ){
121
- if( entity.type !== 'belief' ) continue
121
+ if( entity.type !== 'belief') continue
122
122
  if( this._beliefs.some( b => b.id === entity.id ) ) continue
123
123
 
124
124
  const m = entity.metadata ?? {}
@@ -160,7 +160,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
160
160
  case 'executive.prediction.formed': {
161
161
  const p = e.payload as { predictedDomains: string[]; confidence: number }
162
162
  if( p.predictedDomains.includes('memory') )
163
- this._model.setPrecision( 'belief.count', 1.0 + p.confidence * 0.5 )
163
+ this._model.setPrecision('belief.count', 1.0 + p.confidence * 0.5 )
164
164
 
165
165
  break
166
166
  }
@@ -201,7 +201,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
201
201
  if( payload.knownEntityUpdates )
202
202
  for( const u of payload.knownEntityUpdates )
203
203
  for( const fact of u.learned ?? [] )
204
- if( fact && u.keid && u.keid !== 'agent-self' )
204
+ if( fact && u.keid && u.keid !== 'agent-self')
205
205
  this.integrateExecutiveBelief({
206
206
  id: `belief-ke-facet-${( this._idSeq++ ).toString( 36 )}`,
207
207
  statement: fact,
@@ -224,7 +224,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
224
224
  * No-op at boot: mirror params equal the constructor defaults (reconciled in #83).
225
225
  */
226
226
  private _readConfigFromState( state: ReadonlySimulationState ): void {
227
- const p = readEffectiveParams( state, 'engine-config-semantic' )
227
+ const p = readEffectiveParams( state, 'engine-config-semantic')
228
228
  if( p.minIntervalTicks != null ) this._minIntervalTicks = p.minIntervalTicks
229
229
  if( p.minNewEpisodes != null ) this._minNewEpisodes = p.minNewEpisodes
230
230
  if( p.maxBeliefs != null ) this._maxBeliefs = p.maxBeliefs
@@ -259,7 +259,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
259
259
  if( this._episodicConsolidator && this._shouldRunHeuristic( tick ) ){
260
260
  const newBeliefs = await this._heuristicPatternDetection( tick, state )
261
261
  for( const belief of newBeliefs )
262
- this._integrateBelief( belief, 'heuristic' )
262
+ this._integrateBelief( belief, 'heuristic')
263
263
 
264
264
  this._lastIntegrationTick = tick
265
265
  if( this._episodicConsolidator )
@@ -283,7 +283,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
283
283
  const prev = belief.confidence
284
284
  belief.confidence = Math.max( 0.10, belief.confidence - this._beliefDecayRate )
285
285
  if( belief.confidence !== prev )
286
- SemanticIntegrator._recordHistory( belief, tick, prev, 'decayed' )
286
+ SemanticIntegrator._recordHistory( belief, tick, prev, 'decayed')
287
287
  }
288
288
  }
289
289
 
@@ -315,7 +315,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
315
315
  // Phase C + F: publish cognitive event — gated by prediction error
316
316
  const _bus = this._bus
317
317
  if( _bus && this._beliefs.length > 0 ){
318
- const predErr = this._model.observe( 'belief.count', this._beliefs.length )
318
+ const predErr = this._model.observe('belief.count', this._beliefs.length )
319
319
  if( !predErr.gated )
320
320
  _bus.publish({
321
321
  type: 'belief.updated',
@@ -531,7 +531,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
531
531
  .sort( ( a, b ) => b[1] - a[1] )
532
532
  .find( ( [ , count ] ) => count > semanticResults.length * 0.5 )
533
533
 
534
- if( dominantSource && dominantSource[0] !== 'unknown' ){
534
+ if( dominantSource && dominantSource[0] !== 'unknown'){
535
535
  beliefs.push({
536
536
  id: `belief-semantic-source-${( this._idSeq++ ).toString( 36 )}`,
537
537
  statement: `My semantically similar experiences tend to come from: ${dominantSource[0]}`,
@@ -567,7 +567,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
567
567
  .map( ( [ tag ] ) => tag )
568
568
 
569
569
  if( topTags.length > 0 ){
570
- parts.push( `Themes: ${topTags.join( ', ' )}` )
570
+ parts.push(`Themes: ${topTags.join(', ')}`)
571
571
  }
572
572
 
573
573
  // Add a sample of recent episode content (first 3, truncated)
@@ -581,17 +581,17 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
581
581
  })
582
582
 
583
583
  if( contentSamples.length > 0 ){
584
- parts.push( `Recent experiences: ${contentSamples.join( '; ' )}` )
584
+ parts.push(`Recent experiences: ${contentSamples.join('; ')}`)
585
585
  }
586
586
 
587
587
  // Add affective context if consistent
588
588
  const valenceSum = episodes.reduce( ( s, ep ) => s + ( ep.affectiveContext?.valence ?? 0 ), 0 )
589
589
  const meanValence = valenceSum / episodes.length
590
590
  if( Math.abs( meanValence ) > 0.2 ){
591
- parts.push( `Emotional tone: ${meanValence > 0 ? 'positive' : 'negative'}` )
591
+ parts.push(`Emotional tone: ${meanValence > 0 ? 'positive' : 'negative'}`)
592
592
  }
593
593
 
594
- return parts.length > 0 ? parts.join( '. ' ) : 'What patterns emerge from my recent experiences?'
594
+ return parts.length > 0 ? parts.join('. ') : 'What patterns emerge from my recent experiences?'
595
595
  }
596
596
 
597
597
  // ── Belief management ────────────────────────────────────
@@ -620,7 +620,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
620
620
  belief.history = next
621
621
  }
622
622
 
623
- private _integrateBelief( newBelief: Belief, cause = 'created' ): Belief {
623
+ private _integrateBelief( newBelief: Belief, cause = 'created'): Belief {
624
624
  const existing = this._beliefs.find( b => this._shouldMerge( b, newBelief ) )
625
625
 
626
626
  if( existing ){
@@ -628,7 +628,7 @@ export class SemanticIntegrator implements SimulationEngine, CognitiveEngine {
628
628
  existing.confidence = ( existing.confidence + newBelief.confidence ) / 2
629
629
  existing.supportingEpisodes += newBelief.supportingEpisodes
630
630
  existing.lastUpdatedAt = newBelief.lastUpdatedAt
631
- SemanticIntegrator._recordHistory( existing, newBelief.lastUpdatedAt, prev, 'reinforced' )
631
+ SemanticIntegrator._recordHistory( existing, newBelief.lastUpdatedAt, prev, 'reinforced')
632
632
  return existing
633
633
  }
634
634
 
@@ -84,10 +84,10 @@ export class SleepPressureRegulator implements SimulationEngine, CognitiveEngine
84
84
 
85
85
  onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
86
86
  this._model.observe( e.type, e.salience )
87
- if( e.type === 'executive.prediction.formed' ){
87
+ if( e.type === 'executive.prediction.formed'){
88
88
  const p = e.payload as { predictedDomains: string[]; confidence: number }
89
89
  if( p.predictedDomains.includes('interoception') )
90
- this._model.setPrecision( 'sleep.pressure', 1.0 + p.confidence * 0.5 )
90
+ this._model.setPrecision('sleep.pressure', 1.0 + p.confidence * 0.5 )
91
91
  }
92
92
  }
93
93
 
@@ -224,10 +224,10 @@ export class SleepPressureRegulator implements SimulationEngine, CognitiveEngine
224
224
  // Phase C: publish cognitive event
225
225
  const _bus = this._bus
226
226
  if( _bus && newPressure > 70 )
227
- _bus.publish({ type: 'sleep.pressure.critical', version: 1, sourceEngine: this.name, salience: Math.max( 0.7, this._model.observe( 'sleep.critical', newPressure ).salience ), payload: { pressure: newPressure } })
227
+ _bus.publish({ type: 'sleep.pressure.critical', version: 1, sourceEngine: this.name, salience: Math.max( 0.7, this._model.observe('sleep.critical', newPressure ).salience ), payload: { pressure: newPressure } })
228
228
  // Phase D + F: rich state-change event — gated by prediction error
229
229
  if( _bus ){
230
- const predErr = this._model.observe( 'sleep.pressure', newPressure )
230
+ const predErr = this._model.observe('sleep.pressure', newPressure )
231
231
  if( !predErr.gated )
232
232
  _bus.publish({ type: 'sleep.state.changed', version: 1, sourceEngine: this.name, salience: predErr.salience, payload: { pressure: newPressure, intensity } })
233
233
  }
@@ -88,10 +88,10 @@ export class SocialPerception implements SimulationEngine, CognitiveEngine {
88
88
 
89
89
  onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
90
90
  this._model.observe( e.type, e.salience )
91
- if( e.type === 'executive.prediction.formed' ){
91
+ if( e.type === 'executive.prediction.formed'){
92
92
  const p = e.payload as { predictedDomains: string[]; confidence: number }
93
93
  if( p.predictedDomains.includes('social') )
94
- this._model.setPrecision( 'social.agent_count', 1.0 + p.confidence * 0.5 )
94
+ this._model.setPrecision('social.agent_count', 1.0 + p.confidence * 0.5 )
95
95
  }
96
96
  }
97
97
 
@@ -159,7 +159,7 @@ export class SocialPerception implements SimulationEngine, CognitiveEngine {
159
159
  // Phase C + F: publish cognitive event — gated by prediction error
160
160
  const _bus = this._bus
161
161
  if( _bus && activeAgents > 0 ){
162
- const predErr = this._model.observe( 'social.agent_count', activeAgents )
162
+ const predErr = this._model.observe('social.agent_count', activeAgents )
163
163
  if( !predErr.gated )
164
164
  _bus.publish({ type: 'social.agents.present', version: 1, sourceEngine: this.name, salience: Math.max( 0.3, predErr.salience ), payload: { activeAgents } })
165
165
  }
@@ -471,7 +471,7 @@ export class SpacedRepetition implements SimulationEngine, CognitiveEngine {
471
471
  belief.lastUpdatedAt = tick
472
472
 
473
473
  // Record history if SemanticIntegrator exposes it
474
- this._recordBeliefHistory( belief, tick, prevConfidence, 'spaced_repetition_reinforced' )
474
+ this._recordBeliefHistory( belief, tick, prevConfidence, 'spaced_repetition_reinforced')
475
475
  }
476
476
  else {
477
477
  // Failed review — reset interval and decrease confidence
@@ -483,7 +483,7 @@ export class SpacedRepetition implements SimulationEngine, CognitiveEngine {
483
483
  belief.confidence = newConfidence
484
484
  belief.lastUpdatedAt = tick
485
485
 
486
- this._recordBeliefHistory( belief, tick, prevConfidence, 'spaced_repetition_failed' )
486
+ this._recordBeliefHistory( belief, tick, prevConfidence, 'spaced_repetition_failed')
487
487
  }
488
488
 
489
489
  record.lastReviewedAt = tick
@@ -33,6 +33,7 @@ import type { SimulationEngine, EngineResult, CognitiveEngine } from '#cognition
33
33
  import type { CognitiveEventSchema } from '#cognition/schema.registry'
34
34
  import type { CognitiveEvent, CognitiveBus } from '#cognition/bus'
35
35
  import { GenerativeModel } from '#cognition/generative.model'
36
+ import { ACP_SELF_PRECISION } from '#cognition/acp'
36
37
  import { readEffectiveParams } from '#cognition/persona.prior'
37
38
 
38
39
  export interface StressRegulatorConfig {
@@ -93,7 +94,9 @@ export class StressRegulator implements SimulationEngine, CognitiveEngine {
93
94
  // ── Engine interface ─────────────────────────────────────
94
95
 
95
96
 
96
- subscribes(): string[] { return ["energy.state.changed","sleep.state.changed","novelty.state.changed","goal.state.changed","metacognition.state.changed","executive.prediction.formed"] }
97
+ subscribes(): string[] { return ["energy.state.changed","sleep.state.changed","novelty.state.changed","goal.state.changed","metacognition.state.changed","executive.prediction.formed",
98
+ // ACP-P2: our own enactions — the stress swing they cause is expected
99
+ "agency.enacted","agency.communicate","agency.invocation"] }
97
100
  publishes(): CognitiveEventSchema[] { return [] }
98
101
 
99
102
  onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
@@ -120,9 +123,24 @@ export class StressRegulator implements SimulationEngine, CognitiveEngine {
120
123
  this._model.setPrecision('stress.load', 1.0 + p.confidence * 0.5)
121
124
  break
122
125
  }
126
+ case 'agency.enacted':
127
+ case 'agency.communicate':
128
+ case 'agency.invocation': {
129
+ // ACP-P2 (final inventoried consumer): we just acted — the stress
130
+ // swing that follows is our own doing. Precision-only (no directional
131
+ // prior: acting can LOAD or RELIEVE, so we don't pretend to know the
132
+ // sign); react() restores after one observe so a genuine world
133
+ // stressor next tick lands at full weight.
134
+ this._model.setPrecision('stress.load', ACP_SELF_PRECISION )
135
+ this._acpOneShot = true
136
+ break
137
+ }
123
138
  }
124
139
  }
125
140
 
141
+ /** ACP-P2: self-caused stress attenuation armed; react() restores after one observe. */
142
+ private _acpOneShot = false
143
+
126
144
  snapshot(): Record<string, unknown> {
127
145
  return {
128
146
  energyLevel: this._energyLevel,
@@ -261,12 +279,17 @@ export class StressRegulator implements SimulationEngine, CognitiveEngine {
261
279
 
262
280
  // Phase C: publish cognitive event
263
281
  const _bus = this._bus
264
- if( _bus && ( zone === 'distress' || zone === 'overload' ) )
282
+ if( _bus && ( zone === 'distress' || zone === 'overload') )
265
283
  _bus.publish({ type: 'stress.zone.transition', version: 1, sourceEngine: this.name, salience: Math.min(1, newLoad / 100), payload: { zone, load: newLoad } })
266
284
  // Phase D + F: rich state-change event — gated by prediction error
267
285
  if( _bus ){
268
286
  const zoneCode = zone === 'low' ? 0 : zone === 'optimal' ? 1 : zone === 'distress' ? 2 : 3
269
- const predErr = this._model.observe( 'stress.load', newLoad )
287
+ const predErr = this._model.observe('stress.load', newLoad )
288
+ // ACP-P2: self-caused observe done — restore full precision immediately.
289
+ if( this._acpOneShot ){
290
+ this._model.setPrecision('stress.load', 1.0 )
291
+ this._acpOneShot = false
292
+ }
270
293
  if( !predErr.gated || zone !== previousZone ){
271
294
  _bus.publish({ type: 'stress.state.changed', version: 1, sourceEngine: this.name, salience: predErr.salience, payload: { load: newLoad, zoneCode, deadlineUrgency: state.metrics.get('deadline.urgency') ?? 0, cognitiveLoad: state.metrics.get('cognitive.load') ?? state.metrics.get('attention.usage') ?? 0 } })
272
295
  }
@@ -279,7 +302,7 @@ export class StressRegulator implements SimulationEngine, CognitiveEngine {
279
302
  private _readConfigFromState( state: ReadonlySimulationState ): void {
280
303
  // Effective config = base engine-config-stress ⊕ persona-prior. Channel A: a steadier
281
304
  // (emotionally-stable) Will develops a higher baseDecayRate and so sheds stress faster.
282
- const p = readEffectiveParams( state, 'engine-config-stress' )
305
+ const p = readEffectiveParams( state, 'engine-config-stress')
283
306
  if( p.baseDecayRate != null ) this._baseDecayRate = p.baseDecayRate
284
307
  if( p.optimalThreshold != null ) this._optimalThreshold = p.optimalThreshold
285
308
  if( p.distressThreshold != null ) this._distressThreshold = p.distressThreshold
@@ -81,7 +81,7 @@ export class TaskSwitcher implements SimulationEngine, CognitiveEngine {
81
81
  private _readConfigFromState( state: ReadonlySimulationState ): void {
82
82
  // Effective config = base engine-config-task-switcher ⊕ persona-prior. Channel A: a
83
83
  // conscientious Will develops a higher baseSwitchCost and so is less distractible.
84
- const p = readEffectiveParams( state, 'engine-config-task-switcher' )
84
+ const p = readEffectiveParams( state, 'engine-config-task-switcher')
85
85
  if( p.baseSwitchCost != null ) this._baseSwitchCost = p.baseSwitchCost
86
86
  if( p.switchThreshold != null ) this._switchThreshold = p.switchThreshold
87
87
  if( p.minFocusTicks != null ) this._minFocusTicks = p.minFocusTicks
@@ -93,10 +93,10 @@ export class TaskSwitcher implements SimulationEngine, CognitiveEngine {
93
93
 
94
94
  onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
95
95
  this._model.observe( e.type, e.salience )
96
- if( e.type === 'executive.prediction.formed' ){
96
+ if( e.type === 'executive.prediction.formed'){
97
97
  const p = e.payload as { predictedDomains: string[]; confidence: number }
98
98
  if( p.predictedDomains.includes('executive') )
99
- this._model.setPrecision( 'task.focus_ticks', 1.0 + p.confidence * 0.5 )
99
+ this._model.setPrecision('task.focus_ticks', 1.0 + p.confidence * 0.5 )
100
100
  }
101
101
  }
102
102
 
@@ -143,8 +143,13 @@ export class TaskSwitcher implements SimulationEngine, CognitiveEngine {
143
143
  const currentPriority = currentGoal?.priority ?? 0
144
144
  const switchAdvantage = topGoal.priority - currentPriority
145
145
 
146
- // Account for switching cost
147
- const switchCost = this._baseSwitchCost * ( 1 + this._currentFocus.focusTicks * 0.01 )
146
+ // Account for switching cost. EXAFFERENCE P3 follow-up: `situation.stability`
147
+ // (absent 1 unchanged) scales the focus-hardening term, so a
148
+ // destabilized world loosens focus here exactly as it does in the
149
+ // ActionSelector — the two owners of switch resistance now read the same
150
+ // stability signal at their native scales (goal-priority vs. activation).
151
+ const stability = state.metrics.get('situation.stability') ?? 1
152
+ const switchCost = this._baseSwitchCost * ( 1 + this._currentFocus.focusTicks * 0.01 * stability )
148
153
  const netBenefit = switchAdvantage - switchCost
149
154
 
150
155
  if( netBenefit > this._switchThreshold
@@ -204,7 +209,7 @@ export class TaskSwitcher implements SimulationEngine, CognitiveEngine {
204
209
  // Phase C + F: publish cognitive event — gated by prediction error
205
210
  const _bus = this._bus
206
211
  if( _bus ){
207
- const predErr = this._model.observe( 'task.focus_ticks', this._currentFocus.focusTicks )
212
+ const predErr = this._model.observe('task.focus_ticks', this._currentFocus.focusTicks )
208
213
  if( !predErr.gated )
209
214
  _bus.publish({ type: 'task.focus.changed', version: 1, sourceEngine: this.name, salience: Math.max( 0.3, predErr.salience ), payload: { focusTicks: this._currentFocus.focusTicks } })
210
215
  }
@@ -98,17 +98,17 @@ export class TheoryOfMind implements SimulationEngine, CognitiveEngine {
98
98
 
99
99
  onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
100
100
  this._model.observe( e.type, e.salience )
101
- if( e.type === 'executive.prediction.formed' ){
101
+ if( e.type === 'executive.prediction.formed'){
102
102
  const p = e.payload as { predictedDomains: string[]; confidence: number }
103
103
  if( p.predictedDomains.includes('social') )
104
- this._model.setPrecision( 'tom.models', 1.0 + p.confidence * 0.5 )
104
+ this._model.setPrecision('tom.models', 1.0 + p.confidence * 0.5 )
105
105
  }
106
- if( e.type === 'interaction.occurred' ){
106
+ if( e.type === 'interaction.occurred'){
107
107
  const p = e.payload as {
108
108
  keid: string; valence: number; intensity: number
109
109
  directedAtSelf: boolean; interactionType: string
110
110
  }
111
- if( p.keid && p.keid !== 'agent-self' )
111
+ if( p.keid && p.keid !== 'agent-self')
112
112
  this._pendingInteractions.push( p )
113
113
  }
114
114
  }
@@ -191,7 +191,7 @@ export class TheoryOfMind implements SimulationEngine, CognitiveEngine {
191
191
  // Phase C + F: publish cognitive event — gated by prediction error
192
192
  const _bus = this._bus
193
193
  if( _bus && this._models.size > 0 ){
194
- const predErr = this._model.observe( 'tom.models', this._models.size )
194
+ const predErr = this._model.observe('tom.models', this._models.size )
195
195
  if( !predErr.gated )
196
196
  _bus.publish({ type: 'theory_of_mind.model.updated', version: 1, sourceEngine: this.name, salience: Math.max( 0.2, predErr.salience ), payload: { modelsActive: this._models.size } })
197
197
  }
@@ -231,7 +231,7 @@ export class TheoryOfMind implements SimulationEngine, CognitiveEngine {
231
231
  */
232
232
  private _restoreFromState( state: ReadonlySimulationState ): void {
233
233
  for( const entity of state.entities.values() ){
234
- if( entity.type !== 'theory_of_mind' ) continue
234
+ if( entity.type !== 'theory_of_mind') continue
235
235
  const m = entity.metadata ?? {}
236
236
  const keid = m['keid'] as string | undefined
237
237
  if( !keid ) continue
@@ -180,12 +180,12 @@ export class ThreatEvaluator implements SimulationEngine, CognitiveEngine {
180
180
  // event is refreshed each tick as base ⊕ persona-prior, so a steadier Will develops a
181
181
  // HIGHER threshold and is less easily alarmed. _computeAndEmit (no `state`) reads the
182
182
  // cached field. (The seed entity existed but was ignored before.)
183
- this._fearEventThreshold = readEffectiveParams( state, 'engine-config-threat' ).fearEventThreshold ?? this._fearEventThreshold
183
+ this._fearEventThreshold = readEffectiveParams( state, 'engine-config-threat').fearEventThreshold ?? this._fearEventThreshold
184
184
 
185
185
  // Recompute hostile threat from state entities every tick
186
186
  let maxHostile = 0
187
187
  for( const entity of state.entities.values() ){
188
- if( entity.type !== 'threat' ) continue
188
+ if( entity.type !== 'threat') continue
189
189
  if( entity.metadata?.active === false ) continue
190
190
  if( !entity.metadata?.hostile ) continue
191
191
  const intensity = typeof entity.metadata?.intensity === 'number'
@@ -288,7 +288,7 @@ export class ThreatEvaluator implements SimulationEngine, CognitiveEngine {
288
288
  // worldState.threatLevel). observe() runs every tick so the baseline tracks
289
289
  // and the executive's top-down precision (set on 'threat.level') applies;
290
290
  // the one value is reused across the tiered events.
291
- const threatSalience = this._model.observe( 'threat.level', threatLevel ).salience
291
+ const threatSalience = this._model.observe('threat.level', threatLevel ).salience
292
292
 
293
293
  if( fear > 0.4 )
294
294
  _bus.publish({ type: 'emotion.fear.elevated', version: 1, sourceEngine: this.name, salience: threatSalience, payload: { fear } })
@@ -132,7 +132,7 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
132
132
  case 'executive.prediction.formed': {
133
133
  const p = e.payload as { predictedDomains: string[]; confidence: number }
134
134
  if( p.predictedDomains.includes('memory') )
135
- this._model.setPrecision( 'memory.working.load', 1.0 + p.confidence * 0.5 )
135
+ this._model.setPrecision('memory.working.load', 1.0 + p.confidence * 0.5 )
136
136
  break
137
137
  }
138
138
  }
@@ -174,7 +174,7 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
174
174
  * No-op at boot: mirror params equal the constructor defaults (reconciled in #83).
175
175
  */
176
176
  private _readConfigFromState( state: ReadonlySimulationState ): void {
177
- const p = readEffectiveParams( state, 'engine-config-working-memory' )
177
+ const p = readEffectiveParams( state, 'engine-config-working-memory')
178
178
  if( p.maxChunks != null ) this._maxChunks = p.maxChunks
179
179
  if( p.baseDecayRate != null ) this._baseDecayRate = p.baseDecayRate
180
180
  if( p.attentionProtection != null ) this._attentionProtection = p.attentionProtection
@@ -241,7 +241,7 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
241
241
  type: 'memory.working.changed',
242
242
  version: 1,
243
243
  sourceEngine: this.name,
244
- salience: this._model.observe( 'memory.working.load', load ).salience,
244
+ salience: this._model.observe('memory.working.load', load ).salience,
245
245
  payload: { items: this._items.length, capacity: this._modulatedCapacity, load },
246
246
  })
247
247
 
@@ -275,10 +275,10 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
275
275
  */
276
276
  private _ingestPercepts( state: ReadonlySimulationState, tick: Tick ): void {
277
277
  for( const entity of state.entities.values() ){
278
- if( entity.type !== 'percept' ) continue
278
+ if( entity.type !== 'percept') continue
279
279
  if( this._items.some( i => i.sourceEntityId === entity.id ) ) continue
280
280
 
281
- const summary = ( entity.metadata?.summary ?? entity.metadata?.content ?? '' ) as string
281
+ const summary = ( entity.metadata?.summary ?? entity.metadata?.content ?? '') as string
282
282
  if( !summary || summary.startsWith('New percept:') ) continue
283
283
 
284
284
  this._evictIfNeeded()
@@ -301,8 +301,8 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
301
301
  */
302
302
  private _ingestGoals( state: ReadonlySimulationState, tick: Tick ): void {
303
303
  for( const entity of state.entities.values() ){
304
- if( entity.type !== 'goal' ) continue
305
- if( entity.metadata?.status !== 'active' ) continue
304
+ if( entity.type !== 'goal') continue
305
+ if( entity.metadata?.status !== 'active') continue
306
306
  if( this._items.some( i => i.sourceEntityId === entity.id ) ) continue
307
307
 
308
308
  this._evictIfNeeded()
@@ -335,7 +335,7 @@ export class WorkingMemory implements SimulationEngine, CognitiveEngine {
335
335
 
336
336
  // State-entity fallback: attention.focus entities
337
337
  for( const entity of state.entities.values() ){
338
- if( entity.type !== 'attention.focus' ) continue
338
+ if( entity.type !== 'attention.focus') continue
339
339
  const targetId = entity.metadata?.targetEntityId as string | undefined
340
340
  if( !targetId ) continue
341
341
  const item = this._items.find( i => i.sourceEntityId === targetId )
@@ -289,8 +289,8 @@ export class GenerativeModel {
289
289
  */
290
290
  restore( snap: GenerativeModelSnapshot | undefined | null ): void {
291
291
  if( !snap ) return
292
- if( typeof snap.defaultAlpha === 'number' ) this._defaultAlpha = snap.defaultAlpha
293
- if( typeof snap.defaultRange === 'number' ) this._defaultRange = snap.defaultRange
292
+ if( typeof snap.defaultAlpha === 'number') this._defaultAlpha = snap.defaultAlpha
293
+ if( typeof snap.defaultRange === 'number') this._defaultRange = snap.defaultRange
294
294
 
295
295
  this._streams = new Map(
296
296
  ( snap.streams ?? [] ).map( ([ k, v ]) => [ k, {
@@ -104,7 +104,7 @@ export class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
104
104
  if( this._index.size >= this._maxIndexedEpisodes )
105
105
  await this._evictColdest()
106
106
 
107
- const embedding = await this._embedder.embed( episodeContentToText( content ), 'index' )
107
+ const embedding = await this._embedder.embed( episodeContentToText( content ), 'index')
108
108
 
109
109
  const record: VectorRecord = {
110
110
  id: episode.id,
@@ -138,7 +138,7 @@ export class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
138
138
  await this._evictColdest()
139
139
 
140
140
  const contents = newEpisodes.map( e => episodeContentToText( e.content ) )
141
- const embeddings = await this._embedder.embedBatch( contents, 'index' )
141
+ const embeddings = await this._embedder.embedBatch( contents, 'index')
142
142
 
143
143
  for( let i = 0; i < newEpisodes.length; i++ ){
144
144
  const { episode } = newEpisodes[i]!
@@ -167,7 +167,7 @@ export class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
167
167
  }
168
168
 
169
169
  async search( query: unknown, filter?: VectorQueryFilter ): Promise<VectorQueryResult[]> {
170
- const embedding = await this._embedder.embed( episodeContentToText( query ), 'recall' )
170
+ const embedding = await this._embedder.embed( episodeContentToText( query ), 'recall')
171
171
  return this.searchWithVector( embedding, filter )
172
172
  }
173
173
 
@@ -275,7 +275,7 @@ export class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
275
275
  }
276
276
  }
277
277
  catch( err ){
278
- logger.warn( `[VectorMemoryAdapter] Failed to load index:`, err )
278
+ logger.warn(`[VectorMemoryAdapter] Failed to load index:`, err )
279
279
  }
280
280
  }
281
281
 
@@ -308,7 +308,7 @@ export class DefaultVectorMemoryAdapter implements VectorMemoryAdapter {
308
308
 
309
309
  this._persistDebounceTimer = setTimeout( () => {
310
310
  this.persist().catch( err => {
311
- logger.error( `[VectorMemoryAdapter] Persist failed:`, err )
311
+ logger.error(`[VectorMemoryAdapter] Persist failed:`, err )
312
312
  } )
313
313
  this._persistDebounceTimer = null
314
314
  }, 5000 )
@@ -18,9 +18,9 @@
18
18
  * strings are already clean text and pass through unchanged.
19
19
  */
20
20
  export function episodeContentToText( content: unknown ): string {
21
- if( typeof content === 'string' ) return content
21
+ if( typeof content === 'string') return content
22
22
 
23
- if( content && typeof content === 'object' ){
23
+ if( content && typeof content === 'object'){
24
24
  const m = content as Record<string, unknown>
25
25
 
26
26
  // Conversation exchanges carry the actual dialogue — by far the strongest
@@ -28,7 +28,7 @@ export function episodeContentToText( content: unknown ): string {
28
28
  const user = typeof m['userMessage'] === 'string' ? m['userMessage'] as string : ''
29
29
  const reply = typeof m['willReply'] === 'string' ? m['willReply'] as string : ''
30
30
  if( user || reply )
31
- return [ user, reply ].filter( Boolean ).join( ' → ' )
31
+ return [ user, reply ].filter( Boolean ).join(' → ')
32
32
 
33
33
  // Most WM items carry a top-level human summary.
34
34
  if( typeof m['summary'] === 'string' && m['summary'] ) return m['summary'] as string
@@ -36,7 +36,7 @@ export function episodeContentToText( content: unknown ): string {
36
36
  // Descriptor items nest their payload (e.g. plan: { content: { summary } }).
37
37
  const nested = m['content']
38
38
  if( typeof nested === 'string' && nested ) return nested
39
- if( nested && typeof nested === 'object' ){
39
+ if( nested && typeof nested === 'object'){
40
40
  const nm = nested as Record<string, unknown>
41
41
  if( typeof nm['summary'] === 'string' && nm['summary'] ) return nm['summary'] as string
42
42
  }