@mindot/will 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +777 -0
- package/dist/index.d.ts +8144 -0
- package/dist/index.js +26231 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
- package/src/cognition/agency/access.grants.ts +59 -0
- package/src/cognition/agency/competence.codec.ts +89 -0
- package/src/cognition/agency/engines/action.selector.ts +462 -0
- package/src/cognition/agency/engines/affordance.synthesizer.ts +384 -0
- package/src/cognition/agency/engines/deliberation.engine.ts +241 -0
- package/src/cognition/agency/engines/instruction.intake.ts +54 -0
- package/src/cognition/agency/engines/motor.schema.executor.ts +532 -0
- package/src/cognition/agency/engines/reafference.engine.ts +241 -0
- package/src/cognition/agency/execution.primitives.ts +118 -0
- package/src/cognition/agency/index.ts +58 -0
- package/src/cognition/agency/proactive.communicator.ts +274 -0
- package/src/cognition/agency/reconcile.learning.ts +82 -0
- package/src/cognition/agency/schemas/external.ts +59 -0
- package/src/cognition/agency/schemas/innate.ts +111 -0
- package/src/cognition/agency/schemas/repertoire.ts +246 -0
- package/src/cognition/agency/selection.scoring.ts +191 -0
- package/src/cognition/agency/types.ts +165 -0
- package/src/cognition/bus.ts +391 -0
- package/src/cognition/completion.inbox.ts +86 -0
- package/src/cognition/config.mirror.entities.ts +475 -0
- package/src/cognition/conversation.memory.ts +81 -0
- package/src/cognition/event.log.ts +116 -0
- package/src/cognition/event.schemas.ts +568 -0
- package/src/cognition/faculties/aesthetic.evaluator.ts +313 -0
- package/src/cognition/faculties/affective.blender.ts +562 -0
- package/src/cognition/faculties/attachment.evaluator.ts +432 -0
- package/src/cognition/faculties/attention.allocator.ts +422 -0
- package/src/cognition/faculties/autobiographical.narrator.ts +300 -0
- package/src/cognition/faculties/bias.detector.ts +363 -0
- package/src/cognition/faculties/circadian.oscillator.ts +294 -0
- package/src/cognition/faculties/confidence.calibrator.ts +324 -0
- package/src/cognition/faculties/dream.simulator.ts +251 -0
- package/src/cognition/faculties/empathy.simulator.ts +253 -0
- package/src/cognition/faculties/energy.regulator.ts +320 -0
- package/src/cognition/faculties/episodic.consolidator.ts +728 -0
- package/src/cognition/faculties/executive.engine/commands.ts +459 -0
- package/src/cognition/faculties/executive.engine/config.ts +46 -0
- package/src/cognition/faculties/executive.engine/context.ts +605 -0
- package/src/cognition/faculties/executive.engine/deferred.effects.ts +104 -0
- package/src/cognition/faculties/executive.engine/deliberate.reasoning.ts +60 -0
- package/src/cognition/faculties/executive.engine/effort.gate.ts +114 -0
- package/src/cognition/faculties/executive.engine/engine.ts +1028 -0
- package/src/cognition/faculties/executive.engine/escalation.buffer.ts +90 -0
- package/src/cognition/faculties/executive.engine/facet.supervisor.ts +271 -0
- package/src/cognition/faculties/executive.engine/facet.ts +628 -0
- package/src/cognition/faculties/executive.engine/gating.ts +222 -0
- package/src/cognition/faculties/executive.engine/index.ts +6 -0
- package/src/cognition/faculties/executive.engine/messages.ts +102 -0
- package/src/cognition/faculties/executive.engine/parser.ts +380 -0
- package/src/cognition/faculties/executive.engine/prompt.factory.ts +1053 -0
- package/src/cognition/faculties/executive.engine/types.ts +323 -0
- package/src/cognition/faculties/exteroception.ts +338 -0
- package/src/cognition/faculties/forgetting.curve.ts +202 -0
- package/src/cognition/faculties/frustration.evaluator.ts +280 -0
- package/src/cognition/faculties/goal.manager.ts +1008 -0
- package/src/cognition/faculties/inhibition.controller.ts +351 -0
- package/src/cognition/faculties/interoception.ts +417 -0
- package/src/cognition/faculties/introspection.engine.ts +246 -0
- package/src/cognition/faculties/known.entity.tracker.ts +439 -0
- package/src/cognition/faculties/loss.evaluator.ts +224 -0
- package/src/cognition/faculties/moral.evaluator.ts +437 -0
- package/src/cognition/faculties/novelty.detector.ts +254 -0
- package/src/cognition/faculties/persona.consolidator.ts +845 -0
- package/src/cognition/faculties/planning.engine/engine.ts +859 -0
- package/src/cognition/faculties/planning.engine/plan.frontier.ts +83 -0
- package/src/cognition/faculties/planning.engine/plan.store.ts +174 -0
- package/src/cognition/faculties/planning.engine/plan.supervision.ts +494 -0
- package/src/cognition/faculties/planning.engine/types.ts +143 -0
- package/src/cognition/faculties/reputation.tracker.ts +294 -0
- package/src/cognition/faculties/reward.evaluator.ts +304 -0
- package/src/cognition/faculties/self.model.updater.ts +677 -0
- package/src/cognition/faculties/semantic.engine/clustering.ts +673 -0
- package/src/cognition/faculties/semantic.engine/index.ts +6 -0
- package/src/cognition/faculties/semantic.engine/integrator.ts +750 -0
- package/src/cognition/faculties/semantic.engine/types.ts +53 -0
- package/src/cognition/faculties/sleep.pressure.regulator.ts +262 -0
- package/src/cognition/faculties/social.perception.ts +333 -0
- package/src/cognition/faculties/spaced.repetition.ts +605 -0
- package/src/cognition/faculties/stress.regulator.ts +375 -0
- package/src/cognition/faculties/task.switcher.ts +239 -0
- package/src/cognition/faculties/theory.of.mind.ts +333 -0
- package/src/cognition/faculties/threat.evaluator.ts +312 -0
- package/src/cognition/faculties/working.memory.ts +406 -0
- package/src/cognition/generative.model.ts +344 -0
- package/src/cognition/heartbeat.ts +70 -0
- package/src/cognition/index.ts +291 -0
- package/src/cognition/instruction.handler.ts +146 -0
- package/src/cognition/memory/index.ts +35 -0
- package/src/cognition/memory/vector.adapter.ts +316 -0
- package/src/cognition/memory/vector.content.ts +47 -0
- package/src/cognition/memory/vector.embedder.ts +212 -0
- package/src/cognition/memory/vector.index.ts +459 -0
- package/src/cognition/memory/vector.types.ts +65 -0
- package/src/cognition/orchestrator.ts +142 -0
- package/src/cognition/persona.prior.ts +265 -0
- package/src/cognition/schema.registry.ts +145 -0
- package/src/cognition/senses/audition.engine/engine.ts +976 -0
- package/src/cognition/senses/audition.engine/salience.ts +59 -0
- package/src/cognition/senses/base.sense.engine.ts +117 -0
- package/src/cognition/senses/gustation.engine.ts +24 -0
- package/src/cognition/senses/index.ts +172 -0
- package/src/cognition/senses/olfaction.engine.ts +24 -0
- package/src/cognition/senses/somatosensation.engine.ts +23 -0
- package/src/cognition/senses/vision.engine.ts +23 -0
- package/src/cognition/types.ts +63 -0
- package/src/cognition/utilities/token.tracker.ts +492 -0
- package/src/core/abstracts.ts +60 -0
- package/src/core/async.engine.ts +539 -0
- package/src/core/clock.ts +196 -0
- package/src/core/completion.recorder.ts +122 -0
- package/src/core/conflict.detector.ts +140 -0
- package/src/core/distributed.ts +626 -0
- package/src/core/event.bus.ts +292 -0
- package/src/core/inbound.recorder.ts +100 -0
- package/src/core/index.ts +167 -0
- package/src/core/logger.ts +85 -0
- package/src/core/metrics.ts +107 -0
- package/src/core/orchestrator.ts +625 -0
- package/src/core/replay.ts +589 -0
- package/src/core/scenario.ts +120 -0
- package/src/core/serialization.ts +448 -0
- package/src/core/simulation.ts +197 -0
- package/src/core/snapshot.manager.ts +293 -0
- package/src/core/state.manager.ts +283 -0
- package/src/core/types.ts +274 -0
- package/src/core/utils.ts +82 -0
- package/src/core/wall.clock.ts +23 -0
- package/src/extensions/livestream.ext.ts +570 -0
- package/src/extensions/time.ext.ts +339 -0
- package/src/index.ts +91 -0
- package/src/llm/gate.ts +140 -0
- package/src/llm/index.ts +716 -0
- package/src/llm/summarizer.ts +170 -0
- package/src/llm/wire.contracts.ts +67 -0
- package/src/pma/eval.ts +651 -0
- package/src/pma/index.ts +1082 -0
- package/src/profiles/built-in.ts +7 -0
- package/src/profiles/companion.ts +28 -0
- package/src/profiles/company-brain.ts +54 -0
- package/src/profiles/customer-service.ts +30 -0
- package/src/profiles/game-npc.ts +20 -0
- package/src/profiles/index.ts +42 -0
- package/src/profiles/smart-home.ts +34 -0
- package/src/runners/coherence.runner.ts +49 -0
- package/src/runners/outreach.runner.ts +158 -0
- package/src/runners/social.runner.ts +182 -0
- package/src/runners/thin-shim.runner.ts +195 -0
- package/src/sdk/will.ts +334 -0
- package/src/stem/assembly.audit.ts +88 -0
- package/src/stem/distribution.ts +203 -0
- package/src/stem/guards/identity.coherence.ts +152 -0
- package/src/stem/guards/identity.guard.ts +227 -0
- package/src/stem/index.ts +1145 -0
- package/src/stem/mind.ts +1090 -0
- package/src/stem/tracts/ack.reconciler.ts +55 -0
- package/src/stem/tracts/biography.writer.ts +190 -0
- package/src/stem/tracts/effector.controller.ts +143 -0
- package/src/stem/tracts/health.reporter.ts +113 -0
- package/src/stem/tracts/inbound.queue.ts +54 -0
- package/src/stem/tracts/outbox.controller.ts +167 -0
- package/src/stem/tracts/outbox.writer.ts +133 -0
- package/src/stem/tracts/pma.controller.ts +109 -0
- package/src/stem/tracts/replay.controller.ts +177 -0
- package/src/stem/tracts/sensory.controller.ts +168 -0
- package/src/stem/tracts/session.logger.ts +157 -0
- package/src/stem/tracts/transport/index.ts +38 -0
- package/src/stem/tracts/transport/loopback.transport.ts +86 -0
- package/src/stem/tracts/transport/socketio.transport.ts +200 -0
- package/src/stem/tracts/transport/stream.transport.ts +152 -0
- package/src/stem/tracts/transport/types.ts +193 -0
- package/src/stem/tracts/transport.controller.ts +380 -0
- package/src/types.ts +116 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/semantic.engine/types.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
import type { Tick } from '#core/types'
|
|
6
|
+
import type { CognitiveBus } from '#cognition/bus'
|
|
7
|
+
|
|
8
|
+
// Stop words to strip before text-similarity comparison.
|
|
9
|
+
// Keeps common filler from driving false belief merges.
|
|
10
|
+
export const _STOP_WORDS = new Set([
|
|
11
|
+
'i','my','me','we','our','you','your','it','its',
|
|
12
|
+
'the','a','an','and','or','but','in','on','at','to',
|
|
13
|
+
'for','of','with','by','from','is','are','was','were',
|
|
14
|
+
'be','been','being','have','has','had','do','does','did',
|
|
15
|
+
'will','would','could','should','may','might','can',
|
|
16
|
+
'this','that','these','those','not','no','so','as',
|
|
17
|
+
'if','then','than','very','just','more','most','also',
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
export interface SemanticIntegratorConfig {
|
|
21
|
+
minIntervalTicks?: number
|
|
22
|
+
minNewEpisodes?: number
|
|
23
|
+
maxBeliefs?: number
|
|
24
|
+
/** Ticks without reinforcement before a belief starts losing confidence */
|
|
25
|
+
beliefStalenessThreshold?: number
|
|
26
|
+
/** Confidence lost per tick once a belief goes stale */
|
|
27
|
+
beliefDecayRate?: number
|
|
28
|
+
/** Minimum similarity threshold for semantic pattern detection (0-1) */
|
|
29
|
+
semanticSimilarityThreshold?: number
|
|
30
|
+
/** Maximum episodes to query for semantic pattern detection */
|
|
31
|
+
semanticQueryLimit?: number
|
|
32
|
+
bus?: CognitiveBus
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface BeliefHistoryEntry {
|
|
36
|
+
tick: Tick
|
|
37
|
+
confidence: number // confidence value after this event
|
|
38
|
+
delta: number // change from previous (positive = gained, negative = lost)
|
|
39
|
+
cause: string // 'created' | 'reinforced' | 'decayed' | 'executive' | 'heuristic' | 'self-model' | 'semantic'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface Belief {
|
|
43
|
+
id: string
|
|
44
|
+
statement: string
|
|
45
|
+
category: 'world_fact' | 'self_belief' | 'social_belief' | 'causal_rule' | 'pattern'
|
|
46
|
+
confidence: number
|
|
47
|
+
supportingEpisodes: number
|
|
48
|
+
lastUpdatedAt: Tick
|
|
49
|
+
tags: string[]
|
|
50
|
+
/** Bounded trajectory of confidence changes. Max 20 entries; oldest dropped when full.
|
|
51
|
+
* Becomes a first-class PMM input — the causal story of how a belief formed. */
|
|
52
|
+
history?: BeliefHistoryEntry[]
|
|
53
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/sleep.pressure.regulator.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SleepPressureRegulator — accumulates sleep drive during wakefulness
|
|
7
|
+
* and dissipates it during rest/sleep states.
|
|
8
|
+
*
|
|
9
|
+
* Models the two-process sleep model:
|
|
10
|
+
* - Process S: homeostatic sleep pressure (accumulates while awake)
|
|
11
|
+
* - Process C: circadian modulation (handled by CircadianOscillator)
|
|
12
|
+
*
|
|
13
|
+
* High sleep pressure degrades attention, working memory, and
|
|
14
|
+
* decision quality via modulation signals.
|
|
15
|
+
*
|
|
16
|
+
* Part of Shard 0 (Regulatory Layer) — runs every tick, synchronous.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
Duration,
|
|
21
|
+
Tick,
|
|
22
|
+
SimulationContext,
|
|
23
|
+
ReadonlySimulationState,
|
|
24
|
+
StateCommands,
|
|
25
|
+
DriveSignal,
|
|
26
|
+
ModulationSignal,
|
|
27
|
+
SimulationEvent,
|
|
28
|
+
} from '#core/types'
|
|
29
|
+
import type { SimulationEngine, EngineResult, CognitiveEngine } from '#cognition/types'
|
|
30
|
+
import type { CognitiveEventSchema } from '#cognition/schema.registry'
|
|
31
|
+
import type { CognitiveEvent, CognitiveBus } from '#cognition/bus'
|
|
32
|
+
import { GenerativeModel } from '#cognition/generative.model'
|
|
33
|
+
|
|
34
|
+
export interface SleepPressureConfig {
|
|
35
|
+
/** Rate at which sleep pressure accumulates while awake (per second of sim time) */
|
|
36
|
+
wakeAccumulationRate?: number
|
|
37
|
+
/** Rate at which sleep pressure dissipates during rest (per second of sim time) */
|
|
38
|
+
restDissipationRate?: number
|
|
39
|
+
/** Maximum sleep pressure (saturation point) */
|
|
40
|
+
maxPressure?: number
|
|
41
|
+
/** Pressure threshold for cognitive degradation onset */
|
|
42
|
+
fatigueThreshold?: number
|
|
43
|
+
/** Pressure threshold for severe impairment */
|
|
44
|
+
exhaustionThreshold?: number
|
|
45
|
+
bus?: CognitiveBus
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class SleepPressureRegulator implements SimulationEngine, CognitiveEngine {
|
|
49
|
+
readonly name = 'sleep-pressure-regulator'
|
|
50
|
+
|
|
51
|
+
private _wakeAccumulationRate: number
|
|
52
|
+
private _restDissipationRate: number
|
|
53
|
+
private _maxPressure: number
|
|
54
|
+
private _fatigueThreshold: number
|
|
55
|
+
private _exhaustionThreshold: number
|
|
56
|
+
|
|
57
|
+
private _wasSleeping: boolean = false
|
|
58
|
+
|
|
59
|
+
private _bus: CognitiveBus | null = null
|
|
60
|
+
|
|
61
|
+
private readonly _model = new GenerativeModel()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
constructor( config: SleepPressureConfig = {} ){
|
|
65
|
+
this._bus = config.bus ?? null
|
|
66
|
+
this._wakeAccumulationRate = config.wakeAccumulationRate ?? 0.008
|
|
67
|
+
this._restDissipationRate = config.restDissipationRate ?? 0.04
|
|
68
|
+
this._maxPressure = config.maxPressure ?? 100
|
|
69
|
+
this._fatigueThreshold = config.fatigueThreshold ?? 40
|
|
70
|
+
this._exhaustionThreshold = config.exhaustionThreshold ?? 70
|
|
71
|
+
}
|
|
72
|
+
attachBus( bus: CognitiveBus ): void { this._bus = bus }
|
|
73
|
+
|
|
74
|
+
// ── Engine interface ─────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
subscribes(): string[] { return ['executive.prediction.formed'] }
|
|
78
|
+
publishes(): CognitiveEventSchema[] {
|
|
79
|
+
return [
|
|
80
|
+
{ type: 'sleep.begun', version: 1, validate: () => null },
|
|
81
|
+
{ type: 'sleep.ended', version: 1, validate: () => null },
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
|
|
86
|
+
this._model.observe( e.type, e.salience )
|
|
87
|
+
if( e.type === 'executive.prediction.formed' ){
|
|
88
|
+
const p = e.payload as { predictedDomains: string[]; confidence: number }
|
|
89
|
+
if( p.predictedDomains.includes('interoception') )
|
|
90
|
+
this._model.setPrecision( 'sleep.pressure', 1.0 + p.confidence * 0.5 )
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
snapshot(): Record<string, unknown> { return {} }
|
|
95
|
+
|
|
96
|
+
async react(
|
|
97
|
+
delta: Duration,
|
|
98
|
+
_tick: Tick,
|
|
99
|
+
state: ReadonlySimulationState,
|
|
100
|
+
context: SimulationContext
|
|
101
|
+
): Promise<EngineResult> {
|
|
102
|
+
this._readConfigFromState( state )
|
|
103
|
+
|
|
104
|
+
const
|
|
105
|
+
currentPressure = state.metrics.get('sleep.pressure') ?? 0,
|
|
106
|
+
isResting = state.metrics.get('state.resting') ?? 0,
|
|
107
|
+
isSleeping = state.metrics.get('state.sleeping') ?? 0,
|
|
108
|
+
events: Array<Omit<SimulationEvent, 'id' | 'timestamp' | 'tick'>> = [],
|
|
109
|
+
commands: StateCommands = { metrics: [] }
|
|
110
|
+
|
|
111
|
+
const deltaSeconds = delta / 1000
|
|
112
|
+
let newPressure: number
|
|
113
|
+
|
|
114
|
+
if( isSleeping > 0 ){
|
|
115
|
+
// Deep rest — rapid dissipation
|
|
116
|
+
newPressure = Math.max( 0, currentPressure - this._restDissipationRate * deltaSeconds * 2 )
|
|
117
|
+
|
|
118
|
+
// Fully rested event
|
|
119
|
+
if( currentPressure > 5 && newPressure <= 5 )
|
|
120
|
+
events.push({
|
|
121
|
+
type: 'sleep.fully_rested',
|
|
122
|
+
source: this.name,
|
|
123
|
+
payload: { pressure: newPressure },
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
else if( isResting > 0 ){
|
|
127
|
+
// Light rest — moderate dissipation
|
|
128
|
+
newPressure = Math.max( 0, currentPressure - this._restDissipationRate * deltaSeconds )
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Awake — accumulate pressure
|
|
132
|
+
// Accumulation accelerates as pressure builds (nonlinear fatigue)
|
|
133
|
+
const pressureRatio = currentPressure / this._maxPressure,
|
|
134
|
+
acceleration = 1 + pressureRatio * 1.5,
|
|
135
|
+
accumulation = this._wakeAccumulationRate * acceleration * deltaSeconds
|
|
136
|
+
|
|
137
|
+
newPressure = Math.min( this._maxPressure, currentPressure + accumulation )
|
|
138
|
+
|
|
139
|
+
// Fatigue onset event
|
|
140
|
+
if( currentPressure < this._fatigueThreshold && newPressure >= this._fatigueThreshold )
|
|
141
|
+
events.push({
|
|
142
|
+
type: 'sleep.fatigue_onset',
|
|
143
|
+
source: this.name,
|
|
144
|
+
payload: { pressure: newPressure, threshold: this._fatigueThreshold },
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
// Exhaustion event
|
|
148
|
+
if( currentPressure < this._exhaustionThreshold && newPressure >= this._exhaustionThreshold )
|
|
149
|
+
events.push({
|
|
150
|
+
type: 'sleep.exhaustion',
|
|
151
|
+
source: this.name,
|
|
152
|
+
payload: { pressure: newPressure, threshold: this._exhaustionThreshold },
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
commands.metrics!.push([ 'sleep.pressure', newPressure ])
|
|
157
|
+
|
|
158
|
+
// Drive signal
|
|
159
|
+
const
|
|
160
|
+
intensity = newPressure / this._maxPressure,
|
|
161
|
+
urgency = newPressure >= this._exhaustionThreshold
|
|
162
|
+
? 1.0
|
|
163
|
+
: newPressure >= this._fatigueThreshold
|
|
164
|
+
? ( newPressure - this._fatigueThreshold ) / ( this._exhaustionThreshold - this._fatigueThreshold )
|
|
165
|
+
: 0
|
|
166
|
+
|
|
167
|
+
// Mirror drive intensity as a metric so GoalManager._activateFromDrives() can read it
|
|
168
|
+
commands.metrics!.push([ 'drive.sleep', intensity ])
|
|
169
|
+
|
|
170
|
+
events.push({
|
|
171
|
+
type: 'drive.sleep',
|
|
172
|
+
source: this.name,
|
|
173
|
+
payload: {
|
|
174
|
+
name: 'sleep',
|
|
175
|
+
intensity,
|
|
176
|
+
urgency,
|
|
177
|
+
source: this.name,
|
|
178
|
+
} satisfies DriveSignal,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// Modulation signals — degrade cognition proportionally to fatigue
|
|
182
|
+
if( newPressure >= this._fatigueThreshold ){
|
|
183
|
+
const fatigueRatio = ( newPressure - this._fatigueThreshold )
|
|
184
|
+
/ ( this._maxPressure - this._fatigueThreshold )
|
|
185
|
+
|
|
186
|
+
// Attention degradation
|
|
187
|
+
events.push({
|
|
188
|
+
type: 'modulation.attention_degradation',
|
|
189
|
+
source: this.name,
|
|
190
|
+
payload: {
|
|
191
|
+
target: 'attention-allocator',
|
|
192
|
+
parameter: 'capacity',
|
|
193
|
+
factor: 1 - fatigueRatio * 0.5,
|
|
194
|
+
source: this.name,
|
|
195
|
+
} satisfies ModulationSignal,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
// Working memory degradation
|
|
199
|
+
events.push({
|
|
200
|
+
type: 'modulation.working_memory_degradation',
|
|
201
|
+
source: this.name,
|
|
202
|
+
payload: {
|
|
203
|
+
target: 'working-memory',
|
|
204
|
+
parameter: 'capacity',
|
|
205
|
+
factor: 1 - fatigueRatio * 0.6,
|
|
206
|
+
source: this.name,
|
|
207
|
+
} satisfies ModulationSignal,
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Decision quality degradation (affects LLM temperature or re-evaluation threshold)
|
|
211
|
+
events.push({
|
|
212
|
+
type: 'modulation.decision_quality_degradation',
|
|
213
|
+
source: this.name,
|
|
214
|
+
payload: {
|
|
215
|
+
target: 'decision-engine',
|
|
216
|
+
parameter: 'quality',
|
|
217
|
+
factor: 1 - fatigueRatio * 0.4,
|
|
218
|
+
source: this.name,
|
|
219
|
+
} satisfies ModulationSignal,
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
// Phase C: publish cognitive event
|
|
225
|
+
const _bus = this._bus
|
|
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 } })
|
|
228
|
+
// Phase D + F: rich state-change event — gated by prediction error
|
|
229
|
+
if( _bus ){
|
|
230
|
+
const predErr = this._model.observe( 'sleep.pressure', newPressure )
|
|
231
|
+
if( !predErr.gated )
|
|
232
|
+
_bus.publish({ type: 'sleep.state.changed', version: 1, sourceEngine: this.name, salience: predErr.salience, payload: { pressure: newPressure, intensity } })
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Sleep transition events — fire once on edge, not every tick
|
|
236
|
+
const nowSleeping = isSleeping > 0
|
|
237
|
+
if( _bus ){
|
|
238
|
+
if( !this._wasSleeping && nowSleeping )
|
|
239
|
+
_bus.publish({ type: 'sleep.begun', version: 1, sourceEngine: this.name, salience: 0.8, payload: { pressure: newPressure } })
|
|
240
|
+
else if( this._wasSleeping && !nowSleeping )
|
|
241
|
+
_bus.publish({ type: 'sleep.ended', version: 1, sourceEngine: this.name, salience: 0.7, payload: { tick: _tick } })
|
|
242
|
+
}
|
|
243
|
+
this._wasSleeping = nowSleeping
|
|
244
|
+
|
|
245
|
+
return { events: events.length > 0 ? events : undefined, commands }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ── Config hot-reload ────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
private _readConfigFromState( state: ReadonlySimulationState ): void {
|
|
251
|
+
const cfg = state.entities.get('engine-config-sleep')
|
|
252
|
+
if( !cfg ) return
|
|
253
|
+
|
|
254
|
+
const p = cfg.metadata?.params as Record<string, number> | undefined
|
|
255
|
+
if( !p ) return
|
|
256
|
+
|
|
257
|
+
if( p.wakeAccumulationRate != null ) this._wakeAccumulationRate = p.wakeAccumulationRate
|
|
258
|
+
if( p.restDissipationRate != null ) this._restDissipationRate = p.restDissipationRate
|
|
259
|
+
if( p.fatigueThreshold != null ) this._fatigueThreshold = p.fatigueThreshold
|
|
260
|
+
if( p.exhaustionThreshold != null ) this._exhaustionThreshold = p.exhaustionThreshold
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/social.perception.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SocialPerception — processes social signals from other agents.
|
|
7
|
+
*
|
|
8
|
+
* Detects and interprets:
|
|
9
|
+
* - Other agents' observable actions
|
|
10
|
+
* - Communication directed at this agent
|
|
11
|
+
* - Social status and relationship cues
|
|
12
|
+
* - Group dynamics and social context
|
|
13
|
+
*
|
|
14
|
+
* Produces social percepts with salience that feed into:
|
|
15
|
+
* - AttachmentEvaluator (to update relationship models)
|
|
16
|
+
* - TheoryOfMind (to update mental models of others)
|
|
17
|
+
* - ThreatEvaluator (social evaluation threat)
|
|
18
|
+
*
|
|
19
|
+
* Part of Shard 0 (Perceptual Layer) — runs every tick, synchronous.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
Duration,
|
|
24
|
+
Tick,
|
|
25
|
+
SimulationContext,
|
|
26
|
+
ReadonlySimulationState,
|
|
27
|
+
StateCommands,
|
|
28
|
+
SimulationEvent,
|
|
29
|
+
} from '#core/types'
|
|
30
|
+
import type { SimulationEngine, EngineResult, CognitiveEngine } from '#cognition/types'
|
|
31
|
+
import type { CognitiveEventSchema } from '#cognition/schema.registry'
|
|
32
|
+
import type { CognitiveEvent, CognitiveBus } from '#cognition/bus'
|
|
33
|
+
import { GenerativeModel } from '#cognition/generative.model'
|
|
34
|
+
|
|
35
|
+
export interface SocialPerceptionConfig {
|
|
36
|
+
/** Entity types that represent other agents */
|
|
37
|
+
agentTypes?: string[]
|
|
38
|
+
/** Entity types that represent social signals */
|
|
39
|
+
signalTypes?: string[]
|
|
40
|
+
/** Maximum social percepts per tick */
|
|
41
|
+
maxPerceptsPerTick?: number
|
|
42
|
+
bus?: CognitiveBus
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface SocialPercept {
|
|
46
|
+
keid: string
|
|
47
|
+
signalType: string
|
|
48
|
+
action: string
|
|
49
|
+
valence: number // -1 (hostile) to +1 (affiliative)
|
|
50
|
+
intensity: number // 0-1
|
|
51
|
+
directedAtSelf: boolean
|
|
52
|
+
salience: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class SocialPerception implements SimulationEngine, CognitiveEngine {
|
|
56
|
+
readonly name = 'social-perception'
|
|
57
|
+
|
|
58
|
+
private _agentTypes: Set<string>
|
|
59
|
+
private _signalTypes: Set<string>
|
|
60
|
+
private _maxPerceptsPerTick: number
|
|
61
|
+
|
|
62
|
+
// Track previously observed actions for change detection
|
|
63
|
+
private _previousActions = new Map<string, string>() // keid → last action
|
|
64
|
+
|
|
65
|
+
private _bus: CognitiveBus | null = null
|
|
66
|
+
|
|
67
|
+
private readonly _model = new GenerativeModel()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
constructor( config: SocialPerceptionConfig = {} ){
|
|
71
|
+
this._bus = config.bus ?? null
|
|
72
|
+
this._agentTypes = new Set( config.agentTypes ?? [
|
|
73
|
+
'agent', 'user', 'contact', 'persona',
|
|
74
|
+
])
|
|
75
|
+
this._signalTypes = new Set( config.signalTypes ?? [
|
|
76
|
+
'message', 'action', 'expression', 'social_signal', 'communication',
|
|
77
|
+
])
|
|
78
|
+
this._maxPerceptsPerTick = config.maxPerceptsPerTick ?? 20
|
|
79
|
+
}
|
|
80
|
+
attachBus( bus: CognitiveBus ): void { this._bus = bus }
|
|
81
|
+
|
|
82
|
+
// ── Engine interface ─────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
subscribes(): string[] { return ['executive.prediction.formed'] }
|
|
85
|
+
publishes(): CognitiveEventSchema[] {
|
|
86
|
+
return [{ type: 'interaction.occurred', version: 1, validate: () => null }]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
|
|
90
|
+
this._model.observe( e.type, e.salience )
|
|
91
|
+
if( e.type === 'executive.prediction.formed' ){
|
|
92
|
+
const p = e.payload as { predictedDomains: string[]; confidence: number }
|
|
93
|
+
if( p.predictedDomains.includes('social') )
|
|
94
|
+
this._model.setPrecision( 'social.agent_count', 1.0 + p.confidence * 0.5 )
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
snapshot(): Record<string, unknown> { return {} }
|
|
99
|
+
|
|
100
|
+
async react(
|
|
101
|
+
_delta: Duration,
|
|
102
|
+
tick: Tick,
|
|
103
|
+
state: ReadonlySimulationState,
|
|
104
|
+
context: SimulationContext
|
|
105
|
+
): Promise<EngineResult> {
|
|
106
|
+
const
|
|
107
|
+
events: Array<Omit<SimulationEvent, 'id' | 'timestamp' | 'tick'>> = [],
|
|
108
|
+
commands: StateCommands = { set: [], delete: [], metrics: [] }
|
|
109
|
+
|
|
110
|
+
const socialPercepts = this._scanSocialSignals( state )
|
|
111
|
+
const capped = socialPercepts.slice( 0, this._maxPerceptsPerTick )
|
|
112
|
+
|
|
113
|
+
// Convert to percept entities
|
|
114
|
+
for( let i = 0; i < capped.length; i++ ){
|
|
115
|
+
const sp = capped[i]!
|
|
116
|
+
|
|
117
|
+
commands.set!.push({
|
|
118
|
+
id: `social-percept-${tick}-${i}`,
|
|
119
|
+
type: 'percept.social',
|
|
120
|
+
metadata: {
|
|
121
|
+
tick,
|
|
122
|
+
keid: sp.keid,
|
|
123
|
+
signalType: sp.signalType,
|
|
124
|
+
action: sp.action,
|
|
125
|
+
valence: sp.valence,
|
|
126
|
+
intensity: sp.intensity,
|
|
127
|
+
directedAtSelf: sp.directedAtSelf,
|
|
128
|
+
salience: sp.salience,
|
|
129
|
+
},
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// Update relationship metrics for the perceived agent
|
|
133
|
+
this._updateRelationshipMetrics( sp, commands.metrics! )
|
|
134
|
+
|
|
135
|
+
if( sp.salience > 0.5 )
|
|
136
|
+
events.push({
|
|
137
|
+
type: `social.${sp.signalType}`,
|
|
138
|
+
source: this.name,
|
|
139
|
+
payload: sp,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Social presence metrics
|
|
144
|
+
const activeAgents = this._countActiveAgents( state )
|
|
145
|
+
commands.metrics!.push(
|
|
146
|
+
[ 'social.percepts_this_tick', capped.length ],
|
|
147
|
+
[ 'social.active_agents', activeAgents ],
|
|
148
|
+
[ 'social.directed_at_self', capped.filter( sp => sp.directedAtSelf ).length ],
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// Social evaluation threat — how much social scrutiny exists
|
|
152
|
+
const evaluationThreat = this._computeEvaluationThreat( capped )
|
|
153
|
+
commands.metrics!.push([ 'social.evaluation_threat', evaluationThreat ])
|
|
154
|
+
|
|
155
|
+
// Cleanup
|
|
156
|
+
commands.delete = this._collectStale( state, tick )
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
// Phase C + F: publish cognitive event — gated by prediction error
|
|
160
|
+
const _bus = this._bus
|
|
161
|
+
if( _bus && activeAgents > 0 ){
|
|
162
|
+
const predErr = this._model.observe( 'social.agent_count', activeAgents )
|
|
163
|
+
if( !predErr.gated )
|
|
164
|
+
_bus.publish({ type: 'social.agents.present', version: 1, sourceEngine: this.name, salience: Math.max( 0.3, predErr.salience ), payload: { activeAgents } })
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// interaction.occurred — one event per significant percept so subscribers
|
|
168
|
+
// (theory.of.mind, attachment.evaluator, etc.) get rich per-agent context
|
|
169
|
+
if( _bus ){
|
|
170
|
+
for( const sp of capped ){
|
|
171
|
+
if( !sp.directedAtSelf && Math.abs( sp.valence ) < 0.2 ) continue
|
|
172
|
+
_bus.publish({
|
|
173
|
+
type: 'interaction.occurred', version: 1, sourceEngine: this.name,
|
|
174
|
+
salience: sp.salience,
|
|
175
|
+
payload: {
|
|
176
|
+
keid: sp.keid,
|
|
177
|
+
valence: sp.valence,
|
|
178
|
+
intensity: sp.intensity,
|
|
179
|
+
directedAtSelf: sp.directedAtSelf,
|
|
180
|
+
interactionType: sp.signalType,
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return { events: events.length > 0 ? events : undefined, commands }
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ── Internal ─────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
private _scanSocialSignals( state: ReadonlySimulationState ): SocialPercept[] {
|
|
192
|
+
const percepts: SocialPercept[] = []
|
|
193
|
+
const selfId = 'agent-self'
|
|
194
|
+
|
|
195
|
+
for( const [ id, entity ] of state.entities ){
|
|
196
|
+
// Only process signal-type entities
|
|
197
|
+
if( !this._signalTypes.has( entity.type ) ) continue
|
|
198
|
+
|
|
199
|
+
const
|
|
200
|
+
sourceKeid = ( entity.metadata?.sourceKeid as string )
|
|
201
|
+
?? ( entity.metadata?.from as string )
|
|
202
|
+
?? 'unknown',
|
|
203
|
+
action = ( entity.metadata?.action as string )
|
|
204
|
+
?? ( entity.metadata?.type as string )
|
|
205
|
+
?? entity.type,
|
|
206
|
+
directedAtSelf = ( entity.metadata?.recipientId as string ) === selfId
|
|
207
|
+
|| ( entity.metadata?.to as string ) === selfId
|
|
208
|
+
|| ( entity.metadata?.targetKeid as string ) === selfId
|
|
209
|
+
|| entity.metadata?.directedAtSelf === true,
|
|
210
|
+
isNew = this._previousActions.get( sourceKeid ) !== action
|
|
211
|
+
|
|
212
|
+
// Compute valence from entity metadata or defaults
|
|
213
|
+
const valence = typeof entity.metadata?.valence === 'number'
|
|
214
|
+
? entity.metadata.valence
|
|
215
|
+
: this._defaultValence( action )
|
|
216
|
+
|
|
217
|
+
// Intensity from explicit metadata or salience
|
|
218
|
+
const intensity = typeof entity.metadata?.intensity === 'number'
|
|
219
|
+
? entity.metadata.intensity
|
|
220
|
+
: typeof entity.metadata?.salience === 'number'
|
|
221
|
+
? entity.metadata.salience
|
|
222
|
+
: 0.5
|
|
223
|
+
|
|
224
|
+
// Salience: directed at self > new action > repeated action
|
|
225
|
+
const salience = directedAtSelf ? 0.8 + intensity * 0.2
|
|
226
|
+
: isNew ? 0.4 + intensity * 0.3
|
|
227
|
+
: 0.2 + intensity * 0.2
|
|
228
|
+
|
|
229
|
+
percepts.push({
|
|
230
|
+
keid: sourceKeid,
|
|
231
|
+
signalType: entity.type,
|
|
232
|
+
action,
|
|
233
|
+
valence,
|
|
234
|
+
intensity,
|
|
235
|
+
directedAtSelf,
|
|
236
|
+
salience: Math.min( 1, salience ),
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
// Track for change detection
|
|
240
|
+
this._previousActions.set( sourceKeid, action )
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Sort by salience
|
|
244
|
+
percepts.sort( ( a, b ) => b.salience - a.salience )
|
|
245
|
+
|
|
246
|
+
return percepts
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Default valence mapping for known action types.
|
|
251
|
+
*/
|
|
252
|
+
private _defaultValence( action: string ): number {
|
|
253
|
+
const positive = [ 'praise', 'help', 'cooperate', 'greet', 'smile', 'agree', 'support', 'share' ]
|
|
254
|
+
const negative = [ 'criticize', 'threaten', 'ignore', 'insult', 'attack', 'reject', 'lie', 'betray' ]
|
|
255
|
+
|
|
256
|
+
const lower = action.toLowerCase()
|
|
257
|
+
if( positive.some( p => lower.includes( p ) ) ) return 0.6
|
|
258
|
+
if( negative.some( n => lower.includes( n ) ) ) return -0.6
|
|
259
|
+
return 0
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Update running relationship metrics for a perceived will.
|
|
264
|
+
*/
|
|
265
|
+
private _updateRelationshipMetrics(
|
|
266
|
+
percept: SocialPercept,
|
|
267
|
+
metrics: Array<[string, number]>
|
|
268
|
+
): void {
|
|
269
|
+
const prefix = `relationship.${percept.keid}`
|
|
270
|
+
|
|
271
|
+
// Exponential moving average of interaction valence
|
|
272
|
+
metrics.push([ `${prefix}.valence`, percept.valence ])
|
|
273
|
+
|
|
274
|
+
// Count interactions
|
|
275
|
+
metrics.push([ `${prefix}.interaction_count`, 1 ])
|
|
276
|
+
|
|
277
|
+
// Track directed-at-self ratio
|
|
278
|
+
if( percept.directedAtSelf )
|
|
279
|
+
metrics.push([ `${prefix}.directed_count`, 1 ])
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private _countActiveAgents( state: ReadonlySimulationState ): number {
|
|
283
|
+
let count = 0
|
|
284
|
+
for( const entity of state.entities.values() ){
|
|
285
|
+
if( this._agentTypes.has( entity.type ) )
|
|
286
|
+
count++
|
|
287
|
+
}
|
|
288
|
+
return count
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Compute social evaluation threat — how much social scrutiny is perceived.
|
|
293
|
+
*/
|
|
294
|
+
private _computeEvaluationThreat( percepts: SocialPercept[] ): number {
|
|
295
|
+
if( percepts.length === 0 ) return 0
|
|
296
|
+
|
|
297
|
+
const
|
|
298
|
+
directedPercepts = percepts.filter( p => p.directedAtSelf ),
|
|
299
|
+
negativeDirected = directedPercepts.filter( p => p.valence < 0 )
|
|
300
|
+
|
|
301
|
+
if( directedPercepts.length === 0 ) return 0.1
|
|
302
|
+
|
|
303
|
+
const
|
|
304
|
+
negativeRatio = negativeDirected.length / directedPercepts.length,
|
|
305
|
+
intensityAvg = directedPercepts.reduce( ( s, p ) => s + p.intensity, 0 ) / directedPercepts.length
|
|
306
|
+
|
|
307
|
+
return Math.min( 1, ( negativeRatio * 0.7 + intensityAvg * 0.3 ) * directedPercepts.length / 3 )
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private _collectStale( state: ReadonlySimulationState, currentTick: Tick ): string[] {
|
|
311
|
+
const stale: string[] = []
|
|
312
|
+
for( const [ id, entity ] of state.entities ){
|
|
313
|
+
// Expire processed percept.social entities after 2 ticks
|
|
314
|
+
if( entity.type === 'percept.social' && typeof entity.metadata?.tick === 'number'){
|
|
315
|
+
if( currentTick - entity.metadata.tick > 2 )
|
|
316
|
+
stale.push( id )
|
|
317
|
+
}
|
|
318
|
+
// Expire injected signal entities (communication, message, etc.) after 2 ticks,
|
|
319
|
+
// BUT only once the executive engine has processed them.
|
|
320
|
+
// communication entities must survive until the executive fires (5-tick cooldown),
|
|
321
|
+
// so we must not delete them before processedByExecutive is set — otherwise
|
|
322
|
+
// messages arriving within 2 ticks of an executive fire are silently lost.
|
|
323
|
+
if( this._signalTypes.has( entity.type ) && entity.type !== 'percept.social'){
|
|
324
|
+
if( entity.type === 'communication' && !entity.metadata?.processedByExecutive ) continue
|
|
325
|
+
const createdAtTick = entity.metadata?.tick as number | undefined
|
|
326
|
+
?? entity.metadata?.injectedAtTick as number | undefined
|
|
327
|
+
if( typeof createdAtTick === 'number' && currentTick - createdAtTick > 1 )
|
|
328
|
+
stale.push( id )
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return stale
|
|
332
|
+
}
|
|
333
|
+
}
|