@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,265 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/persona.prior.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* PersonaPrior — the accommodation layer of the metacognition cycle.
|
|
7
|
+
*
|
|
8
|
+
* The Will's engine configuration is seeded once as immutable `engine-config-*`
|
|
9
|
+
* entities (the *base*). This module adds a learned, durable *prior* layer on
|
|
10
|
+
* top, so introspection can write back into the apparatus that perceives and
|
|
11
|
+
* reasons without ever mutating the base:
|
|
12
|
+
*
|
|
13
|
+
* effective_params = base_config ⊕ persona_prior (additive deltas)
|
|
14
|
+
*
|
|
15
|
+
* Design (see METACOGNITION_CYCLE_TODO.md, Phase 2 — Option B):
|
|
16
|
+
* - The prior lives in a single `persona-prior` entity. Because entity state
|
|
17
|
+
* is the persistence path that's actually wired at boot, the prior survives
|
|
18
|
+
* restarts and replays for free — that's the whole point of choosing an
|
|
19
|
+
* entity over an engine-internal field.
|
|
20
|
+
* - The base entity is never mutated; the prior is a separate, reversible
|
|
21
|
+
* adjustment. A prior of 0 (or absent) ⇒ pure base, so the loop degrades
|
|
22
|
+
* gracefully and a persona can always decay back toward its base.
|
|
23
|
+
* - This reader is pure and deterministic (R2): same state ⇒ same effective
|
|
24
|
+
* params, no wall-clock, no RNG.
|
|
25
|
+
* - **Bounding lives in the writer, not here.** The reader applies whatever
|
|
26
|
+
* delta it finds. The Phase 3 consolidator owns the stability–plasticity
|
|
27
|
+
* policy (per-param clamp + decay) when it *produces* the deltas, because
|
|
28
|
+
* sane bounds depend on each param's scale (a 200-tick interval vs a 0.02
|
|
29
|
+
* rate).
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import type { ReadonlySimulationState } from '#core/types'
|
|
33
|
+
|
|
34
|
+
/** Entity id of the singleton persona-prior. */
|
|
35
|
+
export const PERSONA_PRIOR_ID = 'persona-prior'
|
|
36
|
+
|
|
37
|
+
/** Entity `type` discriminator for the persona-prior. */
|
|
38
|
+
export const PERSONA_PRIOR_TYPE = 'persona.prior'
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Shape of `persona-prior` entity metadata. `priors` maps an engine-config
|
|
42
|
+
* entity id to a set of additive per-parameter deltas.
|
|
43
|
+
*
|
|
44
|
+
* priors['engine-config-self-model'] = { minIntervalTicks: -40 }
|
|
45
|
+
*/
|
|
46
|
+
export interface PersonaPriorMeta {
|
|
47
|
+
priors: Record<string, Record<string, number>>
|
|
48
|
+
/** Monotonic write counter (observability / debugging). */
|
|
49
|
+
version: number
|
|
50
|
+
/** Sim tick of the last consolidation that touched the prior (R2-friendly). */
|
|
51
|
+
updatedAtTick: number
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The additive prior deltas for one engine-config id (empty if none).
|
|
56
|
+
*/
|
|
57
|
+
export function readPersonaPrior(
|
|
58
|
+
state: ReadonlySimulationState,
|
|
59
|
+
engineConfigId: string
|
|
60
|
+
): Record<string, number> {
|
|
61
|
+
const meta = state.entities.get( PERSONA_PRIOR_ID )?.metadata as PersonaPriorMeta | undefined
|
|
62
|
+
return meta?.priors?.[ engineConfigId ] ?? {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Effective engine params = base `engine-config-*` params ⊕ persona-prior.
|
|
67
|
+
*
|
|
68
|
+
* Only numeric base params are adjusted, and only by numeric deltas; anything
|
|
69
|
+
* else passes through untouched. Returns a fresh object — never mutates state.
|
|
70
|
+
*/
|
|
71
|
+
export function readEffectiveParams(
|
|
72
|
+
state: ReadonlySimulationState,
|
|
73
|
+
engineConfigId: string
|
|
74
|
+
): Record<string, number> {
|
|
75
|
+
const base = ( state.entities.get( engineConfigId )?.metadata as { params?: Record<string, number> } | undefined )?.params ?? {}
|
|
76
|
+
const prior = readPersonaPrior( state, engineConfigId )
|
|
77
|
+
|
|
78
|
+
const out: Record<string, number> = { ...base }
|
|
79
|
+
for( const [ key, delta ] of Object.entries( prior ) )
|
|
80
|
+
if( typeof out[ key ] === 'number' && typeof delta === 'number' )
|
|
81
|
+
out[ key ] = out[ key ] + delta
|
|
82
|
+
|
|
83
|
+
return out
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Base (un-modulated) params for an engine-config entity, or empty. */
|
|
87
|
+
export function readBaseParams(
|
|
88
|
+
state: ReadonlySimulationState,
|
|
89
|
+
engineConfigId: string
|
|
90
|
+
): Record<string, number> {
|
|
91
|
+
return ( state.entities.get( engineConfigId )?.metadata as { params?: Record<string, number> } | undefined )?.params ?? {}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The full persona-prior metadata, or undefined if not yet written. */
|
|
95
|
+
export function readPersonaPriorMeta( state: ReadonlySimulationState ): PersonaPriorMeta | undefined {
|
|
96
|
+
return state.entities.get( PERSONA_PRIOR_ID )?.metadata as PersonaPriorMeta | undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A human-readable description of one active persona-prior adjustment. */
|
|
100
|
+
export interface PersonaAdjustment {
|
|
101
|
+
/** `<engineConfigId>.<param>` the prior is tuning. */
|
|
102
|
+
key: string
|
|
103
|
+
/** First-person phrase for the executive's context (how the Will has adapted itself). */
|
|
104
|
+
description: string
|
|
105
|
+
/** The signed delta currently applied. */
|
|
106
|
+
delta: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// How each tunable reads as a first-person self-observation. `lower`/`raise`
|
|
110
|
+
// describe a negative/positive delta respectively (all current edges push
|
|
111
|
+
// negative — "do X more often / sooner / less tightly").
|
|
112
|
+
const PRIOR_DESCRIPTIONS: Record<string, { lower: string; raise: string }> = {
|
|
113
|
+
'engine-config-self-model.minIntervalTicks': { lower: 're-examining who I am more often', raise: 're-examining who I am less often' },
|
|
114
|
+
'engine-config-introspection.cooldownTicks': { lower: 'introspecting more often', raise: 'introspecting less often' },
|
|
115
|
+
'engine-config-narrator.minIntervalTicks': { lower: 'updating my life-story more often', raise: 'updating my life-story less often' },
|
|
116
|
+
'engine-config-semantic.beliefStalenessThreshold': { lower: 're-examining my beliefs sooner', raise: 'holding my beliefs longer before review' },
|
|
117
|
+
'engine-config-working-memory.attentionProtection': { lower: 'holding recent impressions less tightly', raise: 'holding recent impressions more firmly' },
|
|
118
|
+
'engine-config-inhibition.baseInhibitionStrength': { lower: 'acting on impulse more freely', raise: 'holding myself in check more firmly before acting' },
|
|
119
|
+
'engine-config-self-model.minNewExperiences': { lower: 're-evaluating who I am on less new experience', raise: 'requiring more new experience before re-evaluating who I am' },
|
|
120
|
+
'engine-config-attention.shiftInertia': { lower: 'shifting my attention more readily', raise: 'holding my attention more fixedly' },
|
|
121
|
+
'engine-config-goal-manager.gritPriority': { lower: 'refusing to give up on more of what matters to me', raise: 'letting go of goals more readily' },
|
|
122
|
+
'engine-config-goal-manager.gritPatienceScale': { lower: 'losing patience with stuck goals sooner', raise: 'staying the course on hard goals far longer' },
|
|
123
|
+
'engine-config-goal-manager.frustrationTolerance': { lower: 'giving up faster when frustrated', raise: 'holding steady through frustration' },
|
|
124
|
+
'engine-config-planning.maxStepRetries': { lower: 'giving up on stuck steps sooner', raise: 'following through on stuck steps more doggedly' },
|
|
125
|
+
'engine-config-planning.surpriseOutcomeQuality': { lower: 'letting lower-quality results slide', raise: 'watching my work more closely, stepping in on smaller dips' },
|
|
126
|
+
'engine-config-planning.planBiasGain': { lower: 'letting my plans be pulled off course by whatever pulls at me', raise: 'holding to my plans against distraction, pushing them through' },
|
|
127
|
+
'engine-config-executive.explorationRate': { lower: 'sticking with what I know more', raise: 'venturing into new approaches more' },
|
|
128
|
+
'engine-config-executive.impulsivity': { lower: 'pausing to think before I act more', raise: 'acting on impulse more readily' },
|
|
129
|
+
'engine-config-executive.riskTolerance': { lower: 'playing it safer', raise: 'taking bigger risks' },
|
|
130
|
+
'engine-config-frustration.irritabilityRate': { lower: 'letting frustration snowball into a bad mood more slowly', raise: 'getting wound up into a bad mood faster' },
|
|
131
|
+
'engine-config-executive.deliberateThreshold': { lower: 'stopping to think things through more readily', raise: 'going with my gut more, deliberating less' },
|
|
132
|
+
'engine-config-reward.socialWeight': { lower: 'caring less about social warmth', raise: 'finding warmth and connection more rewarding' },
|
|
133
|
+
'engine-config-frustration.angerReactivity': { lower: 'letting slights go, yielding rather than bristling', raise: 'bristling harder when I feel wronged' },
|
|
134
|
+
'engine-config-novelty.significanceThreshold': { lower: 'noticing what is new and unusual more readily', raise: 'needing more for something to strike me as new' },
|
|
135
|
+
'engine-config-aesthetic.aweThreshold': { lower: 'being moved to wonder by beauty more easily', raise: 'being harder to move to wonder' },
|
|
136
|
+
'engine-config-threat.fearEventThreshold': { lower: 'taking alarm more easily', raise: 'staying unalarmed unless a threat is real and large' },
|
|
137
|
+
'engine-config-stress.baseDecayRate': { lower: 'carrying stress for longer', raise: 'shedding stress and settling faster' },
|
|
138
|
+
'engine-config-empathy.resonanceStrength': { lower: 'feeling others’ emotions more faintly', raise: 'feeling what others feel more strongly' },
|
|
139
|
+
'engine-config-attachment.attachmentGrowthRate': { lower: 'forming bonds more slowly', raise: 'growing attached to people more readily' },
|
|
140
|
+
'engine-config-reward.goalWeight': { lower: 'caring less about finishing what I start', raise: 'finding real satisfaction in completing my goals' },
|
|
141
|
+
'engine-config-reputation.trustGrowthStep': { lower: 'being slower to trust', raise: 'extending trust and the benefit of the doubt more readily' },
|
|
142
|
+
'engine-config-task-switcher.baseSwitchCost': { lower: 'flitting between things more easily', raise: 'staying on one thing, harder to pull away' },
|
|
143
|
+
'engine-config-action-selector.switchCost': { lower: 'dropping what I am doing for a new pull more easily', raise: 'seeing an action through, harder to knock off course once underway' },
|
|
144
|
+
'engine-config-action-selector.riskWeight': { lower: 'weighing the downside of what I do less — acting bolder', raise: 'weighing what could go wrong more heavily before I act' },
|
|
145
|
+
'engine-config-action-selector.noveltyWeight': { lower: 'feeling less pull toward the untried', raise: 'drawn more strongly to do the untried and unpracticed' },
|
|
146
|
+
'engine-config-moral.eventThreshold': { lower: 'holding myself to my principles more sharply', raise: 'letting moral lapses weigh on me less' },
|
|
147
|
+
'engine-config-frustration.decayRate': { lower: 'staying frustrated for longer after a setback', raise: 'shaking off frustration and bouncing back faster' },
|
|
148
|
+
'engine-config-reward.socialWarmthBoost': { lower: 'being warmed less by a kind exchange', raise: 'being warmed more by every kind exchange' },
|
|
149
|
+
'engine-config-reward.socialDecayRate': { lower: 'holding the glow of connection longer', raise: 'letting the glow of connection fade faster' },
|
|
150
|
+
'engine-config-known-entity.familiarityGrowthRate': { lower: 'taking longer to feel I know someone', raise: 'getting a feel for someone more quickly' },
|
|
151
|
+
'engine-config-known-entity.curiosityGain': { lower: 'feeling less pull to know the half-known', raise: 'itching to get to know whoever I half-know' },
|
|
152
|
+
'engine-config-known-entity.reliabilityRate': { lower: 'being slower to revise whether I can rely on something', raise: 'quickly updating whether I can rely on something' },
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Summarise the active persona-prior as first-person self-observations — the
|
|
157
|
+
* accommodation the Will has made to itself, surfaced so its deliberate self
|
|
158
|
+
* (the executive) can see how it has been self-tuning. Empty when no prior.
|
|
159
|
+
*/
|
|
160
|
+
export function summarizePersonaPrior( state: ReadonlySimulationState ): PersonaAdjustment[] {
|
|
161
|
+
const meta = readPersonaPriorMeta( state )
|
|
162
|
+
if( !meta?.priors ) return []
|
|
163
|
+
|
|
164
|
+
const out: PersonaAdjustment[] = []
|
|
165
|
+
for( const [ engineConfigId, params ] of Object.entries( meta.priors ) )
|
|
166
|
+
for( const [ param, delta ] of Object.entries( params ) ){
|
|
167
|
+
if( !delta ) continue
|
|
168
|
+
|
|
169
|
+
const key = `${engineConfigId}.${param}`
|
|
170
|
+
const desc = PRIOR_DESCRIPTIONS[ key ]
|
|
171
|
+
const description = desc
|
|
172
|
+
? ( delta < 0 ? desc.lower : desc.raise )
|
|
173
|
+
: `${key} ${delta < 0 ? 'decreased' : 'increased'}`
|
|
174
|
+
|
|
175
|
+
out.push({ key, description, delta })
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return out
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Write side (the consolidator's bounded mutation) ──────────
|
|
182
|
+
|
|
183
|
+
/** Below this magnitude a delta is treated as 0 (returned-to-base) and dropped. */
|
|
184
|
+
const EPSILON_PRIOR = 1e-6
|
|
185
|
+
|
|
186
|
+
export interface ConsolidateOpts {
|
|
187
|
+
/** Cumulative |delta| cap, as a fraction of |base|. Default 0.5. */
|
|
188
|
+
maxRelMagnitude?: number
|
|
189
|
+
/** Per-step |delta| cap, as a fraction of |base|. Default 0.15. */
|
|
190
|
+
maxRelStep?: number
|
|
191
|
+
/** Multiplicative decay toward base applied to every delta each call. Default 0.98. */
|
|
192
|
+
decayFactor?: number
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* One requested adjustment to a single engine-config param. `base` is that
|
|
197
|
+
* param's base value, used to scale the bounds (so one policy fits a 200-tick
|
|
198
|
+
* interval and a 0.02 rate). `proposedDelta === 0` (or a 0/non-numeric base)
|
|
199
|
+
* means "no push" — the decay still applies globally.
|
|
200
|
+
*/
|
|
201
|
+
export interface PriorAdjustment {
|
|
202
|
+
engineConfigId: string
|
|
203
|
+
param: string
|
|
204
|
+
base: number
|
|
205
|
+
proposedDelta: number
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Produce the next persona-prior from a consolidation pass (the write counterpart
|
|
210
|
+
* of `readEffectiveParams`). Pure and deterministic — returns a fresh
|
|
211
|
+
* `PersonaPriorMeta` for the caller to emit as a `set` command (R2-safe).
|
|
212
|
+
*
|
|
213
|
+
* Two stability-preserving steps (the stability–plasticity dilemma):
|
|
214
|
+
* 1. **Decay** — every existing delta is multiplied toward 0 (toward base) once
|
|
215
|
+
* per pass, so a prior that stops being reinforced fades back to the seeded
|
|
216
|
+
* baseline rather than ossifying.
|
|
217
|
+
* 2. **Bounded additive steps** — each adjustment's delta is clamped per-step
|
|
218
|
+
* *and* cumulatively, both relative to that param's base magnitude. A single
|
|
219
|
+
* consolidation can never lurch the persona, and no accumulated delta can
|
|
220
|
+
* exceed `maxRelMagnitude × |base|`.
|
|
221
|
+
*
|
|
222
|
+
* Multiple adjustments are applied in a single pass (decay once, N bounded steps,
|
|
223
|
+
* one version bump) so the consolidator can close several edges per tick into one
|
|
224
|
+
* coherent persona-prior. Pass `[]` for a pure decay pass.
|
|
225
|
+
*/
|
|
226
|
+
export function consolidatePrior(
|
|
227
|
+
current: PersonaPriorMeta | undefined,
|
|
228
|
+
adjustments: PriorAdjustment[],
|
|
229
|
+
tick: number,
|
|
230
|
+
opts: ConsolidateOpts = {}
|
|
231
|
+
): PersonaPriorMeta {
|
|
232
|
+
const maxRel = opts.maxRelMagnitude ?? 0.5
|
|
233
|
+
const maxStep = opts.maxRelStep ?? 0.15
|
|
234
|
+
const decay = opts.decayFactor ?? 0.98
|
|
235
|
+
|
|
236
|
+
// 1. Decay every existing delta toward base once; drop ones that fall to ~0.
|
|
237
|
+
const priors: PersonaPriorMeta['priors'] = {}
|
|
238
|
+
for( const [ engineId, params ] of Object.entries( current?.priors ?? {} ) ){
|
|
239
|
+
const kept: Record<string, number> = {}
|
|
240
|
+
for( const [ p, v ] of Object.entries( params ) ){
|
|
241
|
+
const nv = v * decay
|
|
242
|
+
if( Math.abs( nv ) >= EPSILON_PRIOR ) kept[ p ] = nv
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if( Object.keys( kept ).length > 0 ) priors[ engineId ] = kept
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 2. Apply each bounded additive step (relative to its param's |base|).
|
|
249
|
+
for( const adj of adjustments ){
|
|
250
|
+
if( typeof adj.base !== 'number' || adj.base === 0 || adj.proposedDelta === 0 ) continue
|
|
251
|
+
const scale = Math.abs( adj.base )
|
|
252
|
+
const step = Math.max( -maxStep * scale, Math.min( maxStep * scale, adj.proposedDelta ) )
|
|
253
|
+
const existing = priors[ adj.engineConfigId ]?.[ adj.param ] ?? 0
|
|
254
|
+
const next = Math.max( -maxRel * scale, Math.min( maxRel * scale, existing + step ) )
|
|
255
|
+
|
|
256
|
+
const engineMap = priors[ adj.engineConfigId ] ?? ( priors[ adj.engineConfigId ] = {} )
|
|
257
|
+
if( Math.abs( next ) < EPSILON_PRIOR ) delete engineMap[ adj.param ]
|
|
258
|
+
else engineMap[ adj.param ] = next
|
|
259
|
+
|
|
260
|
+
if( Object.keys( engineMap ).length === 0 )
|
|
261
|
+
delete priors[ adj.engineConfigId ]
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return { priors, version: ( current?.version ?? 0 ) + 1, updatedAtTick: tick }
|
|
265
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// src/cognition/schema.registry.ts
|
|
3
|
+
// ─────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
export interface CognitiveEventSchema {
|
|
6
|
+
readonly type: string
|
|
7
|
+
readonly version: number
|
|
8
|
+
validate( payload: unknown ): string | null // null = valid, string = error message
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Migration transform: takes old payload, returns upgraded payload or error string
|
|
12
|
+
export type MigrationTransform = ( payload: unknown ) => { ok: true; payload: unknown } | { ok: false; error: string }
|
|
13
|
+
|
|
14
|
+
interface Migration {
|
|
15
|
+
fromVersion: number
|
|
16
|
+
toVersion: number
|
|
17
|
+
transform: MigrationTransform
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class SchemaRegistry {
|
|
21
|
+
private _schemas = new Map<string, Map<number, CognitiveEventSchema>>()
|
|
22
|
+
private _migrations = new Map<string, Migration[]>()
|
|
23
|
+
|
|
24
|
+
register( schema: CognitiveEventSchema ): void {
|
|
25
|
+
let versions = this._schemas.get( schema.type )
|
|
26
|
+
if( !versions ){
|
|
27
|
+
versions = new Map()
|
|
28
|
+
this._schemas.set( schema.type, versions )
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if( versions.has( schema.version ) )
|
|
32
|
+
throw new Error(`Schema already registered: ${schema.type} v${schema.version}`)
|
|
33
|
+
|
|
34
|
+
versions.set( schema.version, schema )
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Register a migration path from one schema version to the next.
|
|
39
|
+
* Migrations must be registered in ascending order and cover contiguous versions.
|
|
40
|
+
* The bus will auto-upgrade old payloads to the latest version on validate().
|
|
41
|
+
*/
|
|
42
|
+
registerMigration( type: string, fromVersion: number, toVersion: number, transform: MigrationTransform ): void {
|
|
43
|
+
if( toVersion !== fromVersion + 1 )
|
|
44
|
+
throw new Error(`Migration must be to the next consecutive version (got ${fromVersion}→${toVersion})`)
|
|
45
|
+
|
|
46
|
+
let migrations = this._migrations.get( type )
|
|
47
|
+
if( !migrations ){
|
|
48
|
+
migrations = []
|
|
49
|
+
this._migrations.set( type, migrations )
|
|
50
|
+
}
|
|
51
|
+
migrations.push({ fromVersion, toVersion, transform })
|
|
52
|
+
migrations.sort( ( a, b ) => a.fromVersion - b.fromVersion )
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validate payload at a given version. If the exact version is not registered
|
|
57
|
+
* but a migration path exists to a newer version, auto-upgrade and validate
|
|
58
|
+
* against the latest registered version.
|
|
59
|
+
*/
|
|
60
|
+
validate( type: string, version: number, payload: unknown ): string | null {
|
|
61
|
+
const versions = this._schemas.get( type )
|
|
62
|
+
if( !versions ) return `Unknown event type: ${type}`
|
|
63
|
+
|
|
64
|
+
// Exact version match — fast path
|
|
65
|
+
const exact = versions.get( version )
|
|
66
|
+
if( exact ) return exact.validate( payload )
|
|
67
|
+
|
|
68
|
+
// Try to migrate up to a known version
|
|
69
|
+
const migrated = this._migrate( type, version, payload )
|
|
70
|
+
if( !migrated.ok ) return migrated.error
|
|
71
|
+
|
|
72
|
+
const target = versions.get( migrated.targetVersion )
|
|
73
|
+
if( !target ) return `Unknown version ${version} for event type: ${type} (migration failed to find target)`
|
|
74
|
+
|
|
75
|
+
return target.validate( migrated.payload )
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Public migration API used by the bus for per-subscriber version filtering.
|
|
80
|
+
* Attempts to migrate payload from fromVersion up to a registered version.
|
|
81
|
+
*/
|
|
82
|
+
tryMigrate(
|
|
83
|
+
type: string,
|
|
84
|
+
fromVersion: number,
|
|
85
|
+
payload: unknown
|
|
86
|
+
): { ok: true; payload: unknown; targetVersion: number } | { ok: false; error: string } {
|
|
87
|
+
return this._migrate( type, fromVersion, payload )
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private _migrate(
|
|
91
|
+
type: string,
|
|
92
|
+
fromVersion: number,
|
|
93
|
+
payload: unknown
|
|
94
|
+
): { ok: true; payload: unknown; targetVersion: number } | { ok: false; error: string } {
|
|
95
|
+
const migrations = this._migrations.get( type )
|
|
96
|
+
if( !migrations || migrations.length === 0 )
|
|
97
|
+
return { ok: false, error: `Unknown version ${fromVersion} for event type: ${type}` }
|
|
98
|
+
|
|
99
|
+
let current = payload
|
|
100
|
+
let version = fromVersion
|
|
101
|
+
|
|
102
|
+
for( const migration of migrations ){
|
|
103
|
+
if( migration.fromVersion !== version ) continue
|
|
104
|
+
const result = migration.transform( current )
|
|
105
|
+
if( !result.ok ) return { ok: false, error: `Migration ${type} v${version}→v${migration.toVersion} failed: ${result.error}` }
|
|
106
|
+
current = result.payload
|
|
107
|
+
version = migration.toVersion
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { ok: true, payload: current, targetVersion: version }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
hasType( type: string ): boolean {
|
|
114
|
+
return this._schemas.has( type )
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getVersions( type: string ): number[] {
|
|
118
|
+
const versions = this._schemas.get( type )
|
|
119
|
+
return versions ? [ ...versions.keys() ] : []
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
registeredTypes(): string[] {
|
|
123
|
+
return [ ...this._schemas.keys() ]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const globalSchemaRegistry = new SchemaRegistry()
|
|
128
|
+
|
|
129
|
+
// ── Built-in schemas ─────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
function isRecord( v: unknown ): v is Record<string, unknown> {
|
|
132
|
+
return typeof v === 'object' && v !== null && !Array.isArray( v )
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
globalSchemaRegistry.register({
|
|
136
|
+
type: 'clock.tick',
|
|
137
|
+
version: 1,
|
|
138
|
+
validate( payload ){
|
|
139
|
+
if( !isRecord( payload ) ) return 'clock.tick payload must be an object'
|
|
140
|
+
if( typeof payload['tick'] !== 'number' ) return 'clock.tick requires numeric tick'
|
|
141
|
+
if( typeof payload['delta'] !== 'number' ) return 'clock.tick requires numeric delta'
|
|
142
|
+
|
|
143
|
+
return null
|
|
144
|
+
}
|
|
145
|
+
})
|