@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,375 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/stress.regulator.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* StressRegulator — tracks cumulative allostatic load.
|
|
7
|
+
*
|
|
8
|
+
* Stress accumulates from:
|
|
9
|
+
* - Unresolved demands (pending goals, unread messages)
|
|
10
|
+
* - Time pressure (deadlines approaching)
|
|
11
|
+
* - Resource scarcity (low energy, high sleep pressure)
|
|
12
|
+
* - Social evaluation (perceived judgment, conflict)
|
|
13
|
+
* - Novelty/uncertainty (unfamiliar situations)
|
|
14
|
+
*
|
|
15
|
+
* Chronic stress degrades cognitive function and biases toward
|
|
16
|
+
* habitual/defensive responses. Acute stress can enhance performance
|
|
17
|
+
* (Yerkes-Dodson curve) up to an optimal point.
|
|
18
|
+
*
|
|
19
|
+
* Part of Shard 0 (Regulatory Layer) — runs every tick, synchronous.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
Duration,
|
|
24
|
+
Tick,
|
|
25
|
+
SimulationContext,
|
|
26
|
+
ReadonlySimulationState,
|
|
27
|
+
StateCommands,
|
|
28
|
+
SimulationEvent,
|
|
29
|
+
DriveSignal,
|
|
30
|
+
ModulationSignal,
|
|
31
|
+
} from '#core/types'
|
|
32
|
+
import type { SimulationEngine, EngineResult, CognitiveEngine } from '#cognition/types'
|
|
33
|
+
import type { CognitiveEventSchema } from '#cognition/schema.registry'
|
|
34
|
+
import type { CognitiveEvent, CognitiveBus } from '#cognition/bus'
|
|
35
|
+
import { GenerativeModel } from '#cognition/generative.model'
|
|
36
|
+
import { readEffectiveParams } from '#cognition/persona.prior'
|
|
37
|
+
|
|
38
|
+
export interface StressRegulatorConfig {
|
|
39
|
+
/** Maximum allostatic load */
|
|
40
|
+
maxLoad?: number
|
|
41
|
+
/**
|
|
42
|
+
* Fractional clearance rate (per second): the proportion of the *current*
|
|
43
|
+
* load shed each second. Recovery is first-order (exponential), so this also
|
|
44
|
+
* sets the recovery time-constant τ ≈ 1 / rate. Emotional-stability persona
|
|
45
|
+
* development raises it (sheds stress faster); see persona.consolidator #23.
|
|
46
|
+
*/
|
|
47
|
+
baseDecayRate?: number
|
|
48
|
+
/** Threshold for optimal stress (peak performance) */
|
|
49
|
+
optimalThreshold?: number
|
|
50
|
+
/** Threshold for distress (cognitive degradation begins) */
|
|
51
|
+
distressThreshold?: number
|
|
52
|
+
/** Threshold for overload (significant impairment) */
|
|
53
|
+
overloadThreshold?: number
|
|
54
|
+
bus?: CognitiveBus
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface Stressor {
|
|
58
|
+
type: string
|
|
59
|
+
intensity: number
|
|
60
|
+
source: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class StressRegulator implements SimulationEngine, CognitiveEngine {
|
|
64
|
+
readonly name = 'stress-regulator'
|
|
65
|
+
|
|
66
|
+
private _maxLoad: number
|
|
67
|
+
private _baseDecayRate: number
|
|
68
|
+
private _optimalThreshold: number
|
|
69
|
+
private _distressThreshold: number
|
|
70
|
+
private _overloadThreshold: number
|
|
71
|
+
|
|
72
|
+
private _energyLevel: number = 100
|
|
73
|
+
private _sleepPressure: number = 0
|
|
74
|
+
private _noveltyScore: number = 0
|
|
75
|
+
private _activeGoalCount: number = 0
|
|
76
|
+
private _metacogConfidence: number = 0.7
|
|
77
|
+
|
|
78
|
+
private _bus: CognitiveBus | null = null
|
|
79
|
+
|
|
80
|
+
private readonly _model = new GenerativeModel( 0.15, 100 )
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
constructor( config: StressRegulatorConfig = {} ){
|
|
84
|
+
this._bus = config.bus ?? null
|
|
85
|
+
this._maxLoad = config.maxLoad ?? 100
|
|
86
|
+
this._baseDecayRate = config.baseDecayRate ?? 0.05
|
|
87
|
+
this._optimalThreshold = config.optimalThreshold ?? 30
|
|
88
|
+
this._distressThreshold = config.distressThreshold ?? 50
|
|
89
|
+
this._overloadThreshold = config.overloadThreshold ?? 75
|
|
90
|
+
}
|
|
91
|
+
attachBus( bus: CognitiveBus ): void { this._bus = bus }
|
|
92
|
+
|
|
93
|
+
// ── Engine interface ─────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
subscribes(): string[] { return ["energy.state.changed","sleep.state.changed","novelty.state.changed","goal.state.changed","metacognition.state.changed","executive.prediction.formed"] }
|
|
97
|
+
publishes(): CognitiveEventSchema[] { return [] }
|
|
98
|
+
|
|
99
|
+
onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
|
|
100
|
+
this._model.observe( e.type, e.salience )
|
|
101
|
+
switch( e.type ){
|
|
102
|
+
case 'energy.state.changed':
|
|
103
|
+
this._energyLevel = (e.payload as Record<string,number>)['level'] ?? this._energyLevel
|
|
104
|
+
break
|
|
105
|
+
case 'sleep.state.changed':
|
|
106
|
+
this._sleepPressure = (e.payload as Record<string,number>)['pressure'] ?? this._sleepPressure
|
|
107
|
+
break
|
|
108
|
+
case 'novelty.state.changed':
|
|
109
|
+
this._noveltyScore = (e.payload as Record<string,number>)['novelty'] ?? this._noveltyScore
|
|
110
|
+
break
|
|
111
|
+
case 'goal.state.changed':
|
|
112
|
+
this._activeGoalCount = (e.payload as Record<string,number>)['activeCount'] ?? this._activeGoalCount
|
|
113
|
+
break
|
|
114
|
+
case 'metacognition.state.changed':
|
|
115
|
+
this._metacogConfidence = (e.payload as Record<string,number>)['confidence'] ?? this._metacogConfidence
|
|
116
|
+
break
|
|
117
|
+
case 'executive.prediction.formed': {
|
|
118
|
+
const p = e.payload as { predictedDomains: string[]; confidence: number }
|
|
119
|
+
if (p.predictedDomains.includes('stress'))
|
|
120
|
+
this._model.setPrecision('stress.load', 1.0 + p.confidence * 0.5)
|
|
121
|
+
break
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
snapshot(): Record<string, unknown> {
|
|
127
|
+
return {
|
|
128
|
+
energyLevel: this._energyLevel,
|
|
129
|
+
sleepPressure: this._sleepPressure,
|
|
130
|
+
noveltyScore: this._noveltyScore,
|
|
131
|
+
activeGoalCount: this._activeGoalCount,
|
|
132
|
+
metacogConfidence: this._metacogConfidence,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async react(
|
|
137
|
+
delta: Duration,
|
|
138
|
+
_tick: Tick,
|
|
139
|
+
state: ReadonlySimulationState,
|
|
140
|
+
context: SimulationContext
|
|
141
|
+
): Promise<EngineResult> {
|
|
142
|
+
this._readConfigFromState( state )
|
|
143
|
+
|
|
144
|
+
const
|
|
145
|
+
currentLoad = state.metrics.get('stress.load') ?? 0,
|
|
146
|
+
events: Array<Omit<SimulationEvent, 'id' | 'timestamp' | 'tick'>> = [],
|
|
147
|
+
commands: StateCommands = { metrics: [] }
|
|
148
|
+
|
|
149
|
+
// Compute stressor contributions
|
|
150
|
+
const stressors = this._assessStressors( state, delta )
|
|
151
|
+
const totalStressorIntensity = stressors.reduce( ( s, st ) => s + st.intensity, 0 )
|
|
152
|
+
|
|
153
|
+
// Allostatic load as a leaky integrator with *first-order* (proportional)
|
|
154
|
+
// clearance: dL/dt = Σstressor − k·L. Clearance scales with current load,
|
|
155
|
+
// exactly like physiological recovery — acute spikes shed fast, residual
|
|
156
|
+
// load lingers. This yields a stable, graded equilibrium L* = Σstressor / k
|
|
157
|
+
// for any sustained stressor, so light load settles at a low but non-zero
|
|
158
|
+
// baseline rather than collapsing to 0. A constant absolute leak (the prior
|
|
159
|
+
// model) had no graded equilibrium: it pinned to 0 whenever stressors fell
|
|
160
|
+
// below the leak and ran away to max otherwise.
|
|
161
|
+
//
|
|
162
|
+
// Example: 3 active goals (0.5 each = 1.5/s) at the base k=0.05 settle at
|
|
163
|
+
// L* = 30 — the optimal/eustress band. A steadier Will (higher k, via the
|
|
164
|
+
// emotional-stability prior) settles lower; a less stable one carries more.
|
|
165
|
+
const deltaSeconds = delta / 1000
|
|
166
|
+
const accumulation = totalStressorIntensity * deltaSeconds
|
|
167
|
+
const decay = this._baseDecayRate * currentLoad * deltaSeconds
|
|
168
|
+
const newLoad = Math.max( 0, Math.min( this._maxLoad, currentLoad + accumulation - decay ) )
|
|
169
|
+
|
|
170
|
+
// Recovery event
|
|
171
|
+
if( currentLoad > this._distressThreshold && newLoad <= this._optimalThreshold )
|
|
172
|
+
events.push({
|
|
173
|
+
type: 'stress.recovery',
|
|
174
|
+
source: this.name,
|
|
175
|
+
payload: { previous: currentLoad, current: newLoad },
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
commands.metrics!.push([ 'stress.load', newLoad ])
|
|
179
|
+
|
|
180
|
+
// Identify active stressors for metrics
|
|
181
|
+
for( const stressor of stressors )
|
|
182
|
+
commands.metrics!.push([ `stress.${stressor.type}`, stressor.intensity ])
|
|
183
|
+
|
|
184
|
+
// Determine stress zone
|
|
185
|
+
const zone = newLoad >= this._overloadThreshold ? 'overload'
|
|
186
|
+
: newLoad >= this._distressThreshold ? 'distress'
|
|
187
|
+
: newLoad >= this._optimalThreshold ? 'optimal'
|
|
188
|
+
: 'low'
|
|
189
|
+
|
|
190
|
+
commands.metrics!.push([ 'stress.zone', zone === 'low' ? 0 : zone === 'optimal' ? 1 : zone === 'distress' ? 2 : 3 ])
|
|
191
|
+
|
|
192
|
+
// Zone transition events
|
|
193
|
+
const previousZone = this._getZone( currentLoad )
|
|
194
|
+
if( zone !== previousZone )
|
|
195
|
+
events.push({
|
|
196
|
+
type: `stress.zone_${zone}`,
|
|
197
|
+
source: this.name,
|
|
198
|
+
payload: { load: newLoad, zone, previousZone },
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Drive signal — stress itself is a meta-drive (motivates resolution)
|
|
202
|
+
const driveIntensity = newLoad / this._maxLoad
|
|
203
|
+
|
|
204
|
+
// Mirror drive intensity as a metric so GoalManager._activateFromDrives() can read it
|
|
205
|
+
commands.metrics!.push([ 'drive.stress_reduction', newLoad >= this._distressThreshold ? driveIntensity : 0 ])
|
|
206
|
+
|
|
207
|
+
if( newLoad >= this._distressThreshold ){
|
|
208
|
+
events.push({
|
|
209
|
+
type: 'drive.stress_reduction',
|
|
210
|
+
source: this.name,
|
|
211
|
+
payload: {
|
|
212
|
+
name: 'stress_reduction',
|
|
213
|
+
intensity: driveIntensity,
|
|
214
|
+
urgency: newLoad >= this._overloadThreshold ? 1.0 : 0.5,
|
|
215
|
+
source: this.name,
|
|
216
|
+
} satisfies DriveSignal,
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Modulation signals — stress affects decision-making
|
|
221
|
+
if( zone === 'overload'){
|
|
222
|
+
// Overload: significant cognitive narrowing
|
|
223
|
+
events.push({
|
|
224
|
+
type: 'modulation.stress_overload',
|
|
225
|
+
source: this.name,
|
|
226
|
+
payload: {
|
|
227
|
+
target: 'decision-engine',
|
|
228
|
+
parameter: 'exploration',
|
|
229
|
+
factor: 0.2, // Strong bias toward habitual/defensive
|
|
230
|
+
source: this.name,
|
|
231
|
+
} satisfies ModulationSignal,
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
else if( zone === 'distress'){
|
|
235
|
+
// Distress: moderate impairment, reduced creativity
|
|
236
|
+
events.push({
|
|
237
|
+
type: 'modulation.stress_distress',
|
|
238
|
+
source: this.name,
|
|
239
|
+
payload: {
|
|
240
|
+
target: 'decision-engine',
|
|
241
|
+
parameter: 'creativity',
|
|
242
|
+
factor: 0.6,
|
|
243
|
+
source: this.name,
|
|
244
|
+
} satisfies ModulationSignal,
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
else if( zone === 'optimal'){
|
|
248
|
+
// Optimal: enhanced focus, motivation
|
|
249
|
+
events.push({
|
|
250
|
+
type: 'modulation.stress_optimal',
|
|
251
|
+
source: this.name,
|
|
252
|
+
payload: {
|
|
253
|
+
target: 'attention-allocator',
|
|
254
|
+
parameter: 'capacity',
|
|
255
|
+
factor: 1.1, // Slight boost
|
|
256
|
+
source: this.name,
|
|
257
|
+
} satisfies ModulationSignal,
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
// Phase C: publish cognitive event
|
|
263
|
+
const _bus = this._bus
|
|
264
|
+
if( _bus && ( zone === 'distress' || zone === 'overload' ) )
|
|
265
|
+
_bus.publish({ type: 'stress.zone.transition', version: 1, sourceEngine: this.name, salience: Math.min(1, newLoad / 100), payload: { zone, load: newLoad } })
|
|
266
|
+
// Phase D + F: rich state-change event — gated by prediction error
|
|
267
|
+
if( _bus ){
|
|
268
|
+
const zoneCode = zone === 'low' ? 0 : zone === 'optimal' ? 1 : zone === 'distress' ? 2 : 3
|
|
269
|
+
const predErr = this._model.observe( 'stress.load', newLoad )
|
|
270
|
+
if( !predErr.gated || zone !== previousZone ){
|
|
271
|
+
_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
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return { events: events.length > 0 ? events : undefined, commands }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ── Config hot-reload ────────────────────────────────────
|
|
278
|
+
|
|
279
|
+
private _readConfigFromState( state: ReadonlySimulationState ): void {
|
|
280
|
+
// Effective config = base engine-config-stress ⊕ persona-prior. Channel A: a steadier
|
|
281
|
+
// (emotionally-stable) Will develops a higher baseDecayRate and so sheds stress faster.
|
|
282
|
+
const p = readEffectiveParams( state, 'engine-config-stress' )
|
|
283
|
+
if( p.baseDecayRate != null ) this._baseDecayRate = p.baseDecayRate
|
|
284
|
+
if( p.optimalThreshold != null ) this._optimalThreshold = p.optimalThreshold
|
|
285
|
+
if( p.distressThreshold != null ) this._distressThreshold = p.distressThreshold
|
|
286
|
+
if( p.overloadThreshold != null ) this._overloadThreshold = p.overloadThreshold
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ── Internal ─────────────────────────────────────────────
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Assess active stressors from the current state.
|
|
293
|
+
*/
|
|
294
|
+
private _assessStressors( state: ReadonlySimulationState, delta: Duration ): Stressor[] {
|
|
295
|
+
const stressors: Stressor[] = []
|
|
296
|
+
|
|
297
|
+
// Demand pressure: active goals requiring action. ~0.5/goal so a handful of
|
|
298
|
+
// concurrent goals lands in the eustress band (3 goals ⇒ ≈optimal at base
|
|
299
|
+
// k); capped at 2 so goals alone plateau around distress and it takes
|
|
300
|
+
// compounding stressors (fatigue, low energy, deadlines) to reach overload.
|
|
301
|
+
const activeGoals = this._activeGoalCount
|
|
302
|
+
if( activeGoals > 0 )
|
|
303
|
+
stressors.push({
|
|
304
|
+
type: 'demand',
|
|
305
|
+
intensity: Math.min( activeGoals * 0.5, 2 ),
|
|
306
|
+
source: 'goals',
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
// Time pressure: deadlines approaching
|
|
310
|
+
const
|
|
311
|
+
nearestDeadline = state.metrics.get('deadline.nearest'),
|
|
312
|
+
deadlinePressure = nearestDeadline !== undefined && nearestDeadline > 0
|
|
313
|
+
? Math.min( 30, 300 / Math.max( nearestDeadline, 1 ) )
|
|
314
|
+
: 0
|
|
315
|
+
|
|
316
|
+
if( deadlinePressure > 0 )
|
|
317
|
+
stressors.push({
|
|
318
|
+
type: 'time_pressure',
|
|
319
|
+
intensity: deadlinePressure,
|
|
320
|
+
source: 'deadlines',
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// Resource scarcity: low energy
|
|
324
|
+
const energyLevel = this._energyLevel,
|
|
325
|
+
energyMax = 100,
|
|
326
|
+
energyRatio = energyLevel / energyMax
|
|
327
|
+
|
|
328
|
+
if( energyRatio < 0.3 )
|
|
329
|
+
stressors.push({
|
|
330
|
+
type: 'resource_scarcity',
|
|
331
|
+
intensity: Math.min( 3, ( 0.3 - energyRatio ) * 15 ),
|
|
332
|
+
source: 'energy',
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
// Sleep pressure as stressor
|
|
336
|
+
const sleepPressure = this._sleepPressure
|
|
337
|
+
if( sleepPressure > 40 )
|
|
338
|
+
stressors.push({
|
|
339
|
+
type: 'fatigue',
|
|
340
|
+
intensity: Math.min( 3, ( sleepPressure / 100 ) * 5 ),
|
|
341
|
+
source: 'sleep',
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
// Social evaluation: perceived judgment
|
|
345
|
+
const socialThreat = state.metrics.get('social.evaluation_threat') ?? 0
|
|
346
|
+
if( socialThreat > 0 )
|
|
347
|
+
stressors.push({
|
|
348
|
+
type: 'social_evaluation',
|
|
349
|
+
intensity: Math.min( 2, socialThreat * 5 ),
|
|
350
|
+
source: 'social',
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
// Uncertainty: novelty + low predictability
|
|
354
|
+
const
|
|
355
|
+
novelty = this._noveltyScore,
|
|
356
|
+
confidence = this._metacogConfidence,
|
|
357
|
+
uncertainty = Math.min( 2, novelty * ( 1 - confidence ) * 5 )
|
|
358
|
+
|
|
359
|
+
if( uncertainty > 0 )
|
|
360
|
+
stressors.push({
|
|
361
|
+
type: 'uncertainty',
|
|
362
|
+
intensity: uncertainty,
|
|
363
|
+
source: 'perception',
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
return stressors
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private _getZone( load: number ): string {
|
|
370
|
+
return load >= this._overloadThreshold ? 'overload'
|
|
371
|
+
: load >= this._distressThreshold ? 'distress'
|
|
372
|
+
: load >= this._optimalThreshold ? 'optimal'
|
|
373
|
+
: 'low'
|
|
374
|
+
}
|
|
375
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/faculties/task.switcher.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TaskSwitcher — manages attention shifts between competing goals.
|
|
7
|
+
*
|
|
8
|
+
* When multiple goals compete for attention, the TaskSwitcher:
|
|
9
|
+
* 1. Compares active goal priorities
|
|
10
|
+
* 2. Applies switching costs (attention residue from previous focus)
|
|
11
|
+
* 3. Decides whether to maintain current focus or switch
|
|
12
|
+
* 4. Signals the AttentionAllocator to reallocate
|
|
13
|
+
*
|
|
14
|
+
* Switching is costly — frequent switching degrades performance.
|
|
15
|
+
* The TaskSwitcher balances exploitation (stay on current goal) vs.
|
|
16
|
+
* exploration (switch to potentially higher-value goal).
|
|
17
|
+
*
|
|
18
|
+
* Part of Shard 3 (Executive Layer) — runs every tick, synchronous.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type {
|
|
22
|
+
Duration,
|
|
23
|
+
Tick,
|
|
24
|
+
SimulationContext,
|
|
25
|
+
ReadonlySimulationState,
|
|
26
|
+
StateCommands,
|
|
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
|
+
import { readEffectiveParams } from '#cognition/persona.prior'
|
|
34
|
+
|
|
35
|
+
export interface TaskSwitcherConfig {
|
|
36
|
+
/** Base switching cost (0-1, fraction of attention lost on switch) */
|
|
37
|
+
baseSwitchCost?: number
|
|
38
|
+
/** How much priority advantage a new goal needs to justify switching */
|
|
39
|
+
switchThreshold?: number
|
|
40
|
+
/** Minimum ticks on a goal before switching is considered */
|
|
41
|
+
minFocusTicks?: number
|
|
42
|
+
bus?: CognitiveBus
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface CurrentFocus {
|
|
46
|
+
goalId: string | null
|
|
47
|
+
focusTicks: number
|
|
48
|
+
startedAt: Tick
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class TaskSwitcher implements SimulationEngine, CognitiveEngine {
|
|
52
|
+
readonly name = 'task-switcher'
|
|
53
|
+
|
|
54
|
+
private _baseSwitchCost: number
|
|
55
|
+
private _switchThreshold: number
|
|
56
|
+
private _minFocusTicks: number
|
|
57
|
+
|
|
58
|
+
private _currentFocus: CurrentFocus = {
|
|
59
|
+
goalId: null,
|
|
60
|
+
focusTicks: 0,
|
|
61
|
+
startedAt: 0,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private _totalSwitches = 0
|
|
65
|
+
|
|
66
|
+
private _bus: CognitiveBus | null = null
|
|
67
|
+
|
|
68
|
+
private readonly _model = new GenerativeModel()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
constructor( config: TaskSwitcherConfig = {} ){
|
|
72
|
+
this._bus = config.bus ?? null
|
|
73
|
+
this._baseSwitchCost = config.baseSwitchCost ?? 0.3
|
|
74
|
+
this._switchThreshold = config.switchThreshold ?? 0.2
|
|
75
|
+
this._minFocusTicks = config.minFocusTicks ?? 3
|
|
76
|
+
}
|
|
77
|
+
attachBus( bus: CognitiveBus ): void { this._bus = bus }
|
|
78
|
+
|
|
79
|
+
// ── Engine interface ─────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
private _readConfigFromState( state: ReadonlySimulationState ): void {
|
|
82
|
+
// Effective config = base engine-config-task-switcher ⊕ persona-prior. Channel A: a
|
|
83
|
+
// conscientious Will develops a higher baseSwitchCost and so is less distractible.
|
|
84
|
+
const p = readEffectiveParams( state, 'engine-config-task-switcher' )
|
|
85
|
+
if( p.baseSwitchCost != null ) this._baseSwitchCost = p.baseSwitchCost
|
|
86
|
+
if( p.switchThreshold != null ) this._switchThreshold = p.switchThreshold
|
|
87
|
+
if( p.minFocusTicks != null ) this._minFocusTicks = p.minFocusTicks
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
subscribes(): string[] { return ['executive.prediction.formed'] }
|
|
92
|
+
publishes(): CognitiveEventSchema[] { return [] }
|
|
93
|
+
|
|
94
|
+
onCognitiveEvent( e: CognitiveEvent ): StateCommands | void {
|
|
95
|
+
this._model.observe( e.type, e.salience )
|
|
96
|
+
if( e.type === 'executive.prediction.formed' ){
|
|
97
|
+
const p = e.payload as { predictedDomains: string[]; confidence: number }
|
|
98
|
+
if( p.predictedDomains.includes('executive') )
|
|
99
|
+
this._model.setPrecision( 'task.focus_ticks', 1.0 + p.confidence * 0.5 )
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
snapshot(): Record<string, unknown> { return {} }
|
|
104
|
+
|
|
105
|
+
async react(
|
|
106
|
+
_delta: Duration,
|
|
107
|
+
tick: Tick,
|
|
108
|
+
state: ReadonlySimulationState,
|
|
109
|
+
context: SimulationContext
|
|
110
|
+
): Promise<EngineResult> {
|
|
111
|
+
this._readConfigFromState( state )
|
|
112
|
+
|
|
113
|
+
const
|
|
114
|
+
events: Array<Omit<SimulationEvent, 'id' | 'timestamp' | 'tick'>> = [],
|
|
115
|
+
commands: StateCommands = { metrics: [] }
|
|
116
|
+
|
|
117
|
+
// 1. Get active goals sorted by priority
|
|
118
|
+
const activeGoals = this._getActiveGoals( state )
|
|
119
|
+
|
|
120
|
+
// 2. Increment focus counter
|
|
121
|
+
this._currentFocus.focusTicks++
|
|
122
|
+
|
|
123
|
+
// 3. Evaluate whether to switch
|
|
124
|
+
let switched = false
|
|
125
|
+
let switchReason = ''
|
|
126
|
+
|
|
127
|
+
if( activeGoals.length > 0 ){
|
|
128
|
+
const topGoal = activeGoals[0]!
|
|
129
|
+
|
|
130
|
+
if( this._currentFocus.goalId === null ){
|
|
131
|
+
// First focus — adopt the top goal
|
|
132
|
+
this._currentFocus = {
|
|
133
|
+
goalId: topGoal.id,
|
|
134
|
+
focusTicks: 0,
|
|
135
|
+
startedAt: tick,
|
|
136
|
+
}
|
|
137
|
+
switched = true
|
|
138
|
+
switchReason = 'initial_focus'
|
|
139
|
+
}
|
|
140
|
+
else if( topGoal.id !== this._currentFocus.goalId ){
|
|
141
|
+
// Potential switch — evaluate
|
|
142
|
+
const currentGoal = activeGoals.find( g => g.id === this._currentFocus.goalId )
|
|
143
|
+
const currentPriority = currentGoal?.priority ?? 0
|
|
144
|
+
const switchAdvantage = topGoal.priority - currentPriority
|
|
145
|
+
|
|
146
|
+
// Account for switching cost
|
|
147
|
+
const switchCost = this._baseSwitchCost * ( 1 + this._currentFocus.focusTicks * 0.01 )
|
|
148
|
+
const netBenefit = switchAdvantage - switchCost
|
|
149
|
+
|
|
150
|
+
if( netBenefit > this._switchThreshold
|
|
151
|
+
&& this._currentFocus.focusTicks >= this._minFocusTicks ){
|
|
152
|
+
// Switch
|
|
153
|
+
this._currentFocus = {
|
|
154
|
+
goalId: topGoal.id,
|
|
155
|
+
focusTicks: 0,
|
|
156
|
+
startedAt: tick,
|
|
157
|
+
}
|
|
158
|
+
this._totalSwitches++
|
|
159
|
+
switched = true
|
|
160
|
+
switchReason = `switched_from_${currentGoal?.description ?? 'unknown'}_to_${topGoal.description}`
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if( this._currentFocus.goalId !== null ){
|
|
165
|
+
// No active goals — release focus
|
|
166
|
+
this._currentFocus = { goalId: null, focusTicks: 0, startedAt: 0 }
|
|
167
|
+
switched = true
|
|
168
|
+
switchReason = 'no_active_goals'
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 4. Update metrics
|
|
172
|
+
commands.metrics!.push(
|
|
173
|
+
[ 'task_switch.current_focus_ticks', this._currentFocus.focusTicks ],
|
|
174
|
+
[ 'task_switch.total_switches', this._totalSwitches ],
|
|
175
|
+
[ 'task_switch.switch_cost', this._baseSwitchCost ],
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
// 5. Persist current focus
|
|
179
|
+
if( this._currentFocus.goalId ){
|
|
180
|
+
commands.set = [{
|
|
181
|
+
id: 'task-switch-focus',
|
|
182
|
+
type: 'task.focus',
|
|
183
|
+
createdAt: this._currentFocus.startedAt,
|
|
184
|
+
metadata: {
|
|
185
|
+
goalId: this._currentFocus.goalId,
|
|
186
|
+
focusTicks: this._currentFocus.focusTicks,
|
|
187
|
+
startedAt: this._currentFocus.startedAt,
|
|
188
|
+
},
|
|
189
|
+
}]
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if( switched )
|
|
193
|
+
events.push({
|
|
194
|
+
type: 'task_switch.executed',
|
|
195
|
+
source: this.name,
|
|
196
|
+
payload: {
|
|
197
|
+
newGoalId: this._currentFocus.goalId,
|
|
198
|
+
reason: switchReason,
|
|
199
|
+
totalSwitches: this._totalSwitches,
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
// Phase C + F: publish cognitive event — gated by prediction error
|
|
205
|
+
const _bus = this._bus
|
|
206
|
+
if( _bus ){
|
|
207
|
+
const predErr = this._model.observe( 'task.focus_ticks', this._currentFocus.focusTicks )
|
|
208
|
+
if( !predErr.gated )
|
|
209
|
+
_bus.publish({ type: 'task.focus.changed', version: 1, sourceEngine: this.name, salience: Math.max( 0.3, predErr.salience ), payload: { focusTicks: this._currentFocus.focusTicks } })
|
|
210
|
+
}
|
|
211
|
+
return { events: events.length > 0 ? events : undefined, commands }
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ── Internal ─────────────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
private _getActiveGoals( state: ReadonlySimulationState ): Array<{ id: string; priority: number; description: string }> {
|
|
217
|
+
const goals: Array<{ id: string; priority: number; description: string }> = []
|
|
218
|
+
|
|
219
|
+
for( const entity of state.entities.values() ){
|
|
220
|
+
if( entity.type === 'goal' && entity.metadata?.status === 'active'){
|
|
221
|
+
goals.push({
|
|
222
|
+
id: entity.id,
|
|
223
|
+
priority: ( entity.metadata.priority as number ) ?? 0,
|
|
224
|
+
description: ( entity.metadata.description as string ) ?? entity.id,
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
goals.sort( ( a, b ) => b.priority - a.priority )
|
|
230
|
+
return goals
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get the current focus goal ID.
|
|
235
|
+
*/
|
|
236
|
+
getCurrentFocus(): string | null {
|
|
237
|
+
return this._currentFocus.goalId
|
|
238
|
+
}
|
|
239
|
+
}
|