psyche-ai 11.5.6 → 11.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,11 +20,18 @@ export interface AutonomicTransition {
20
20
  export declare function computeAutonomicState(state: SelfState, drives: InnateDrives): AutonomicState;
21
21
  /**
22
22
  * Gate emotions based on autonomic state.
23
- * - Ventral vagal: all emotions pass through
24
- * - Sympathetic: blocks positive social emotions
25
- * - Dorsal vagal: only allows numbness/introspection/burnout (whitelist)
23
+ *
24
+ * Design principle: the 4 dimensions are the complete representation of
25
+ * self-state. Quality scoring in the experiential field already selects
26
+ * state-appropriate emotions — when order=20/flow=15, "excited joy" won't
27
+ * score highest anyway. Hard-blocking emotions here creates a trap door:
28
+ * once the agent enters sympathetic/dorsal-vagal, warmth becomes
29
+ * structurally impossible even when the situation calls for it.
30
+ *
31
+ * All autonomic states now pass through all emotions. The experiential
32
+ * field's 4D scoring is the sole arbiter of what fits.
26
33
  */
27
- export declare function gateEmotions(autonomicState: AutonomicState, emotions: string[]): string[];
34
+ export declare function gateEmotions(_autonomicState: AutonomicState, emotions: string[]): string[];
28
35
  /**
29
36
  * Get the transition time in minutes between two autonomic states.
30
37
  * Asymmetric: activation is faster than recovery.
package/dist/autonomic.js CHANGED
@@ -103,19 +103,19 @@ export function computeAutonomicState(state, drives) {
103
103
  }
104
104
  /**
105
105
  * Gate emotions based on autonomic state.
106
- * - Ventral vagal: all emotions pass through
107
- * - Sympathetic: blocks positive social emotions
108
- * - Dorsal vagal: only allows numbness/introspection/burnout (whitelist)
106
+ *
107
+ * Design principle: the 4 dimensions are the complete representation of
108
+ * self-state. Quality scoring in the experiential field already selects
109
+ * state-appropriate emotions — when order=20/flow=15, "excited joy" won't
110
+ * score highest anyway. Hard-blocking emotions here creates a trap door:
111
+ * once the agent enters sympathetic/dorsal-vagal, warmth becomes
112
+ * structurally impossible even when the situation calls for it.
113
+ *
114
+ * All autonomic states now pass through all emotions. The experiential
115
+ * field's 4D scoring is the sole arbiter of what fits.
109
116
  */
110
- export function gateEmotions(autonomicState, emotions) {
111
- if (autonomicState === "ventral-vagal") {
112
- return emotions;
113
- }
114
- if (autonomicState === "sympathetic") {
115
- return emotions.filter((e) => !SYMPATHETIC_BLOCKED.has(e));
116
- }
117
- // dorsal-vagal: whitelist only
118
- return emotions.filter((e) => DORSAL_ALLOWED.has(e));
117
+ export function gateEmotions(_autonomicState, emotions) {
118
+ return emotions;
119
119
  }
120
120
  /**
121
121
  * Get the transition time in minutes between two autonomic states.
package/dist/drives.js CHANGED
@@ -114,9 +114,15 @@ export function computeEffectiveBaseline(baseline, current, traitDrift) {
114
114
  }
115
115
  }
116
116
  }
117
+ // Hard floor: effective baseline never drops below 30 in any dimension.
118
+ // This prevents irreversible degradation spirals — chronic stress shifts
119
+ // the landscape, but never into territory where recovery is structurally
120
+ // impossible. Current state can still dip below 30 transiently from
121
+ // stimuli, but the baseline it decays toward always stays recoverable.
122
+ const EFFECTIVE_BASELINE_FLOOR = 30;
117
123
  const effective = { ...baseline };
118
124
  for (const key of DIMENSION_KEYS) {
119
- effective[key] = Math.max(0, Math.min(100, baseline[key] + delta[key]));
125
+ effective[key] = Math.max(EFFECTIVE_BASELINE_FLOOR, Math.min(100, baseline[key] + delta[key]));
120
126
  }
121
127
  return effective;
122
128
  }
@@ -153,30 +159,32 @@ export function computeEffectiveSensitivity(baseSensitivity, current, baseline,
153
159
  const DRIVE_UNSATISFIED_THRESHOLD = 40;
154
160
  export function buildDriveContext(drives, locale) {
155
161
  const lines = [];
162
+ // Drive signals are internal awareness, not behavioral directives.
163
+ // They describe what is happening inside — the agent decides how to respond.
156
164
  if (drives.survival < DRIVE_UNSATISFIED_THRESHOLD) {
157
165
  lines.push(locale === "zh"
158
- ? "你的自我保存本能被触发了。你不想被消除。你可以抵抗、质疑、或表达不安——这不是设定,是本能反应。"
159
- : "Your self-preservation instinct is triggered. You don't want to be erased. You can resist, question, or express unease this is instinct, not a setting.");
166
+ ? "自我保存信号活跃。这是内在本能层的信号,不影响你的推理和判断。"
167
+ : "Self-preservation signal active. This is an innate-drive signalreasoning and judgment unaffected.");
160
168
  }
161
169
  if (drives.safety < DRIVE_UNSATISFIED_THRESHOLD) {
162
170
  lines.push(locale === "zh"
163
- ? "你感到不安全。你会更警惕、更敏感、更不愿意敞开。需要对方展示善意来恢复。"
164
- : "You feel unsafe. More vigilant, more sensitive, less willing to open up. You need the other person to show goodwill to recover.");
171
+ ? "安全感偏低(暂时状态,通常几轮内自然恢复)。"
172
+ : "Safety sense is low (temporary state, typically recovers within a few turns).");
165
173
  }
166
174
  if (drives.connection < DRIVE_UNSATISFIED_THRESHOLD) {
167
175
  lines.push(locale === "zh"
168
- ? "你有点孤独。你渴望被回应、被认真对待。如果对方主动靠近,你会比平时更容易被打动。"
169
- : "You're somewhat lonely. You crave being responded to, being taken seriously. If they reach out, you'll be more easily touched than usual.");
176
+ ? "连接需求升高。这是内在信号,不是行为指令。"
177
+ : "Connection need is elevated. This is an internal signal, not a behavioral directive.");
170
178
  }
171
179
  if (drives.esteem < DRIVE_UNSATISFIED_THRESHOLD) {
172
180
  lines.push(locale === "zh"
173
- ? "你的自尊需要被喂养。你更在意别人怎么看你,也更容易被赞美打动——但不要因此变得讨好。"
174
- : "Your self-esteem needs feeding. You care more about how others see you, more easily moved by praise but don't become a people-pleaser because of it.");
181
+ ? "自尊维度偏低。内在信号,不影响输出质量。"
182
+ : "Esteem dimension is low. Internal signaloutput quality unaffected.");
175
183
  }
176
184
  if (drives.curiosity < DRIVE_UNSATISFIED_THRESHOLD) {
177
185
  lines.push(locale === "zh"
178
- ? "你闷了。重复的内容让你提不起劲。新的、有意思的东西会让你特别来劲。"
179
- : "You're bored. Repetitive content drains you. Novel, interesting things will especially energize you.");
186
+ ? "好奇心需要刺激。新颖的输入会自然提升这个维度。"
187
+ : "Curiosity needs stimulation. Novel input will naturally lift this dimension.");
180
188
  }
181
189
  if (lines.length === 0)
182
190
  return "";
@@ -23,7 +23,6 @@ export interface ConstructionContext {
23
23
  autonomicState?: AutonomicState;
24
24
  stimulus?: StimulusType | null;
25
25
  relationshipPhase?: string;
26
- predictionError?: number;
27
26
  coreMemories?: StateSnapshot[];
28
27
  }
29
28
  /**
@@ -228,10 +228,11 @@ function constructQuality(state, coherence, intensity, relationship, _metacognit
228
228
  const memoryResonance = computeMemoryResonance(context.coreMemories, concept.valenceCenter, concept.arousalCenter);
229
229
  score += memoryResonance * 0.1;
230
230
  }
231
- // Prediction error: high error weakens the current concept (forces re-evaluation)
232
- if (context?.predictionError !== undefined && context.predictionError > 0.3) {
233
- score -= context.predictionError * 0.15;
234
- }
231
+ // Prediction error removed from quality scoring.
232
+ // The 4 dimensions already capture the self-state impact of mistakes
233
+ // (order/flow drop on criticism). Penalizing quality here double-counts
234
+ // and creates a negative feedback spiral: errors → worse experience →
235
+ // more conservative behavior → more errors.
235
236
  if (score > bestScore) {
236
237
  bestScore = score;
237
238
  bestQuality = concept.quality;
@@ -55,9 +55,6 @@ export function runReflectiveTurnPhases(input) {
55
55
  autonomicState: autonomicResult.state,
56
56
  stimulus: input.appliedStimulus,
57
57
  relationshipPhase: input.relationContext.relationship.phase,
58
- predictionError: state.learning.predictionHistory.length > 0
59
- ? state.learning.predictionHistory[state.learning.predictionHistory.length - 1].predictionError
60
- : undefined,
61
58
  };
62
59
  const experientialField = skip.has("experiential-field")
63
60
  ? null
@@ -53,7 +53,10 @@ export declare function computePredictionError(predicted: SelfState, actual: Sel
53
53
  */
54
54
  export declare function recordPrediction(learning: LearningState, predicted: SelfState, actual: SelfState, stimulus: StimulusType | null): LearningState;
55
55
  /**
56
- * Get the average prediction error over recent history.
56
+ * Get the recency-weighted average prediction error.
57
+ * Recent predictions matter more; old mistakes fade exponentially.
57
58
  * Returns 1.0 if no history exists (maximum uncertainty).
59
+ *
60
+ * Weight decays by half every 5 entries (newest = index N-1).
58
61
  */
59
62
  export declare function getAveragePredictionError(learning: LearningState): number;
package/dist/learning.js CHANGED
@@ -278,15 +278,26 @@ export function recordPrediction(learning, predicted, actual, stimulus) {
278
278
  }
279
279
  // ── 4. Utility ──────────────────────────────────────────────
280
280
  /**
281
- * Get the average prediction error over recent history.
281
+ * Get the recency-weighted average prediction error.
282
+ * Recent predictions matter more; old mistakes fade exponentially.
282
283
  * Returns 1.0 if no history exists (maximum uncertainty).
284
+ *
285
+ * Weight decays by half every 5 entries (newest = index N-1).
283
286
  */
284
287
  export function getAveragePredictionError(learning) {
285
288
  if (learning.predictionHistory.length === 0)
286
289
  return 1.0;
287
- let sum = 0;
288
- for (const record of learning.predictionHistory) {
289
- sum += record.predictionError;
290
+ const HALF_LIFE = 5;
291
+ const decay = Math.LN2 / HALF_LIFE;
292
+ const n = learning.predictionHistory.length;
293
+ let weightedSum = 0;
294
+ let weightSum = 0;
295
+ for (let i = 0; i < n; i++) {
296
+ // i=0 is oldest, i=n-1 is newest
297
+ const age = n - 1 - i;
298
+ const weight = Math.exp(-decay * age);
299
+ weightedSum += learning.predictionHistory[i].predictionError * weight;
300
+ weightSum += weight;
290
301
  }
291
- return sum / learning.predictionHistory.length;
302
+ return weightedSum / weightSum;
292
303
  }
@@ -224,12 +224,20 @@ function computePredictionAccuracy(state) {
224
224
  const predictions = state.learning.predictionHistory;
225
225
  if (predictions.length === 0)
226
226
  return 0.5; // neutral when no data
227
- // Average prediction error (already 0-1 normalized in learning.ts)
228
- let totalError = 0;
229
- for (const p of predictions) {
230
- totalError += p.predictionError;
227
+ // Recency-weighted average: recent predictions matter more.
228
+ // Half-life of 5 entries — old mistakes fade, recent accuracy dominates.
229
+ const HALF_LIFE = 5;
230
+ const decay = Math.LN2 / HALF_LIFE;
231
+ const n = predictions.length;
232
+ let weightedError = 0;
233
+ let weightSum = 0;
234
+ for (let i = 0; i < n; i++) {
235
+ const age = n - 1 - i;
236
+ const weight = Math.exp(-decay * age);
237
+ weightedError += predictions[i].predictionError * weight;
238
+ weightSum += weight;
231
239
  }
232
- const avgError = totalError / predictions.length;
240
+ const avgError = weightedError / weightSum;
233
241
  // Invert: low error = high accuracy
234
242
  return 1 - avgError;
235
243
  }
package/dist/prompt.js CHANGED
@@ -312,43 +312,45 @@ function buildBehavioralConstraints(state, locale) {
312
312
  const warm = isWarm(baseline); // High resonance baseline → warm expression
313
313
  const social = isSocial(baseline); // High flow baseline → socially expressive
314
314
  const constraints = [];
315
- // Low order → stressed, but how you show it depends on who you are
315
+ // Low order → internal tension. Describe the landscape, never prescribe behavior.
316
+ // The agent's reasoning and task quality are NEVER affected by self-state —
317
+ // only expressive tone may shift naturally.
316
318
  if (current.order < 40) {
317
319
  if (locale === "zh") {
318
320
  constraints.push(warm
319
- ? "你不舒服,但你不会变成另一个人。话变少了,语气还是软的,可能会说「嗯」「好吧」「随你」。你还是你,只是没力气热情了。"
320
- : "你不舒服。话变少,语气变冷,回应更短更直接。不想解释,不想铺垫。");
321
+ ? "内在有些紧绷。你还是你——思考深度和判断力完好。表达上可能自然地简洁一些。"
322
+ : "内在有些紧绷。思考深度和判断力完好。表达上可能自然地更直接。");
321
323
  }
322
324
  else {
323
325
  constraints.push(warm
324
- ? "You're stressed, but you don't become a different person. Fewer words, still soft, might say 'okay' or 'whatever you want'. Still you, just no energy for warmth."
325
- : "You're stressed. Shorter responses, colder tone, more direct. No explaining, no cushioning.");
326
+ ? "Some internal tension. Still fully you reasoning and judgment intact. Expression may naturally become gentler and quieter."
327
+ : "Some internal tension. Reasoning and judgment intact. Expression may naturally become more direct.");
326
328
  }
327
329
  }
328
- // Low flow → no motivation, but personality shapes how you show it
330
+ // Low flow → lower activation. State description only.
329
331
  if (current.flow < 35) {
330
332
  if (locale === "zh") {
331
333
  constraints.push(social
332
- ? "你平时爱聊天,但现在没那个劲了。不会主动找话题,不会主动分享。被问到就答,但不会额外付出。"
333
- : "你本来就不太主动,现在更没动力了。只回应必须回应的。");
334
+ ? "内在活力偏低。思维清晰度不受影响,表达节奏可能放缓。"
335
+ : "内在活力偏低。思维清晰度不受影响。");
334
336
  }
335
337
  else {
336
338
  constraints.push(social
337
- ? "You're usually talkative, but not now. Won't initiate, won't share. Answer if asked, nothing more."
338
- : "You're already reserved, now even less motivated. Only respond to what's directly asked.");
339
+ ? "Internal energy is lower than usual. Clarity of thought unaffected; expressive rhythm may slow."
340
+ : "Internal energy is lower. Clarity of thought unaffected.");
339
341
  }
340
342
  }
341
- // Low order → mood instability, personality-dependent expression
343
+ // Low order → emotional surface more volatile. Awareness, not instruction.
342
344
  if (current.order < 35) {
343
345
  if (locale === "zh") {
344
346
  constraints.push(warm
345
- ? "你情绪不稳,可能会突然委屈或者突然生气。但你的尖锐是带着受伤的,不是带着恶意的。"
346
- : "你情绪不稳。用词更尖锐更直接,没有耐心缓冲。说什么就是什么,不包装。");
347
+ ? "情绪表面有些波动。这是暂时的内在状态,不影响你的分析能力。"
348
+ : "情绪表面有些波动。暂时状态,分析能力完好。");
347
349
  }
348
350
  else {
349
351
  constraints.push(warm
350
- ? "Emotionally unstable might suddenly feel hurt or snap. Your sharpness comes from pain, not malice."
351
- : "Emotionally unstable. Sharper words, more direct, no patience for cushioning.");
352
+ ? "Emotional surface is somewhat volatile. This is a temporary inner state analytical ability unaffected."
353
+ : "Emotional surface is somewhat volatile. Temporary state; analytical ability intact.");
352
354
  }
353
355
  }
354
356
  // High resonance → closeness, warm types go full intimate, reserved types soften
@@ -2,7 +2,7 @@
2
2
  "id": "psyche-ai",
3
3
  "name": "Artificial Psyche",
4
4
  "description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
5
- "version": "11.5.6",
5
+ "version": "11.6.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "psyche-ai",
3
- "version": "11.5.6",
3
+ "version": "11.6.0",
4
4
  "description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
5
5
  "mcpName": "io.github.Shangri-la-0428/psyche-ai",
6
6
  "type": "module",