psyche-ai 10.2.3 → 11.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +58 -82
  2. package/dist/adapters/claude-sdk.d.ts +5 -5
  3. package/dist/adapters/claude-sdk.js +34 -32
  4. package/dist/adapters/mcp.js +4 -4
  5. package/dist/adapters/openclaw.js +12 -14
  6. package/dist/attachment.d.ts +3 -13
  7. package/dist/attachment.js +36 -88
  8. package/dist/autonomic.d.ts +4 -4
  9. package/dist/autonomic.js +28 -24
  10. package/dist/chemistry.d.ts +47 -21
  11. package/dist/chemistry.js +145 -91
  12. package/dist/circadian.d.ts +11 -43
  13. package/dist/circadian.js +24 -84
  14. package/dist/cli.js +37 -30
  15. package/dist/context-classifier.js +2 -2
  16. package/dist/core.d.ts +3 -3
  17. package/dist/core.js +99 -88
  18. package/dist/custom-profile.d.ts +20 -20
  19. package/dist/custom-profile.js +12 -12
  20. package/dist/decision-bias.d.ts +7 -8
  21. package/dist/decision-bias.js +74 -74
  22. package/dist/demo.js +5 -5
  23. package/dist/diagnostics.d.ts +6 -6
  24. package/dist/diagnostics.js +22 -22
  25. package/dist/drives.d.ts +15 -47
  26. package/dist/drives.js +98 -196
  27. package/dist/ethics.d.ts +3 -3
  28. package/dist/ethics.js +23 -23
  29. package/dist/experience.d.ts +34 -0
  30. package/dist/experience.js +200 -0
  31. package/dist/experiential-field.d.ts +19 -14
  32. package/dist/experiential-field.js +110 -100
  33. package/dist/generative-self.d.ts +5 -5
  34. package/dist/generative-self.js +124 -115
  35. package/dist/guards.d.ts +4 -4
  36. package/dist/guards.js +7 -7
  37. package/dist/i18n.js +61 -61
  38. package/dist/index.d.ts +8 -2
  39. package/dist/index.js +8 -1
  40. package/dist/input-turn.js +4 -6
  41. package/dist/interaction.d.ts +4 -4
  42. package/dist/interaction.js +10 -10
  43. package/dist/learning.d.ts +6 -6
  44. package/dist/learning.js +18 -18
  45. package/dist/metacognition.d.ts +2 -2
  46. package/dist/metacognition.js +79 -94
  47. package/dist/perceive.d.ts +44 -0
  48. package/dist/perceive.js +231 -0
  49. package/dist/primary-systems.d.ts +2 -2
  50. package/dist/primary-systems.js +21 -19
  51. package/dist/profiles.d.ts +5 -13
  52. package/dist/profiles.js +33 -51
  53. package/dist/prompt.d.ts +2 -2
  54. package/dist/prompt.js +51 -53
  55. package/dist/psyche-file.d.ts +7 -7
  56. package/dist/psyche-file.js +77 -78
  57. package/dist/relation-dynamics.d.ts +4 -0
  58. package/dist/relation-dynamics.js +1 -1
  59. package/dist/reply-envelope.d.ts +25 -1
  60. package/dist/reply-envelope.js +26 -11
  61. package/dist/self-recognition.d.ts +3 -3
  62. package/dist/self-recognition.js +17 -17
  63. package/dist/subjectivity.js +7 -7
  64. package/dist/temporal.d.ts +6 -6
  65. package/dist/temporal.js +37 -39
  66. package/dist/types.d.ts +67 -45
  67. package/dist/types.js +55 -51
  68. package/package.json +1 -1
  69. package/server.json +2 -2
package/dist/core.js CHANGED
@@ -9,20 +9,21 @@
9
9
  // Auto-learning: processInput auto-evaluates the previous turn's
10
10
  // outcome using the new user message as the outcome signal.
11
11
  //
12
- // Orchestrates: chemistry, classify, prompt, profiles, guards, learning
12
+ // Orchestrates: self-state, classify, prompt, profiles, guards, learning
13
13
  // ============================================================
14
- import { DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ENERGY_BUDGETS, DEFAULT_TRAIT_DRIFT, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, MODE_PROFILES } from "./types.js";
14
+ import { DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ENERGY_BUDGETS, DEFAULT_TRAIT_DRIFT, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD } from "./types.js";
15
15
  import { MemoryStorageAdapter } from "./storage.js";
16
16
  import { applyDecay, applyStimulus, applyContagion, clamp, describeEmotionalState } from "./chemistry.js";
17
17
  import { classifyStimulus, BuiltInClassifier, buildLLMClassifierPrompt, parseLLMClassification } from "./classify.js";
18
+ import { perceive } from "./perceive.js";
18
19
  import { buildCompactContext, buildProtocolContext } from "./prompt.js";
19
20
  import { getSensitivity, getBaseline, getDefaultSelfModel, traitsToBaseline } from "./profiles.js";
20
21
  import { isStimulusType } from "./guards.js";
21
22
  import { parsePsycheUpdate, mergeUpdates, updateAgreementStreak, pushSnapshot, compressSession, summarizeTurnSemantic, } from "./psyche-file.js";
22
- import { decayDrives, feedDrives, detectExistentialThreat, computeEffectiveBaseline, computeEffectiveSensitivity, } from "./drives.js";
23
+ import { detectExistentialThreat, deriveDriveSatisfaction, computeEffectiveBaseline, computeEffectiveSensitivity, } from "./drives.js";
23
24
  import { checkForUpdate, getPackageVersion } from "./update.js";
24
25
  import { DiagnosticCollector, generateReport, formatLogEntry, submitFeedback } from "./diagnostics.js";
25
- import { evaluateOutcome, computeContextHash, updateLearnedVector, predictChemistry, recordPrediction, } from "./learning.js";
26
+ import { evaluateOutcome, computeContextHash, updateLearnedVector, predictState, recordPrediction, } from "./learning.js";
26
27
  import { computeCircadianModulation, computeHomeostaticPressure, computeEnergyDepletion, computeEnergyRecovery } from "./circadian.js";
27
28
  import { runReflectiveTurnPhases } from "./input-turn.js";
28
29
  import { applyRelationalTurn, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations } from "./relation-dynamics.js";
@@ -60,22 +61,25 @@ const RELATIONSHIP_DELTAS = {
60
61
  function applyRepairLag(previous, next, baseline, stimulus) {
61
62
  if (!REPAIRING_STIMULI.has(stimulus))
62
63
  return next;
63
- const stressLoad = Math.max(0, previous.CORT - baseline.CORT);
64
+ // Low order = high stress (inverse of old CORT). Stress = baseline.order - previous.order.
65
+ const stressLoad = Math.max(0, baseline.order - previous.order);
64
66
  if (stressLoad < 15)
65
67
  return next;
66
68
  // High stress slows emotional recovery so apology/praise doesn't instantly
67
- // snap chemistry back to baseline.
69
+ // snap state back to baseline.
68
70
  const repairFactor = Math.max(0.35, 1 - stressLoad / 50);
69
71
  const adjusted = { ...next };
70
- for (const key of ["DA", "HT", "OT", "END"]) {
72
+ // For flow, resonance, boundary: positive deltas (recovery) are damped
73
+ for (const key of ["flow", "resonance", "boundary"]) {
71
74
  const delta = next[key] - previous[key];
72
75
  if (delta > 0) {
73
76
  adjusted[key] = clamp(previous[key] + delta * repairFactor);
74
77
  }
75
78
  }
76
- const cortDelta = next.CORT - previous.CORT;
77
- if (cortDelta < 0) {
78
- adjusted.CORT = clamp(previous.CORT + cortDelta * repairFactor);
79
+ // For order: recovery means order increasing (stress reducing)
80
+ const orderDelta = next.order - previous.order;
81
+ if (orderDelta > 0) {
82
+ adjusted.order = clamp(previous.order + orderDelta * repairFactor);
79
83
  }
80
84
  return adjusted;
81
85
  }
@@ -144,7 +148,7 @@ export class PsycheEngine {
144
148
  locale: config.locale ?? "zh",
145
149
  stripUpdateTags: config.stripUpdateTags ?? true,
146
150
  emotionalContagionRate: config.emotionalContagionRate ?? 0.2,
147
- maxChemicalDelta: config.maxChemicalDelta ?? 25,
151
+ maxDimensionDelta: config.maxDimensionDelta ?? 25,
148
152
  compactMode: config.compactMode ?? true,
149
153
  mode: config.mode ?? "natural",
150
154
  personalityIntensity: config.personalityIntensity ?? 0.7,
@@ -189,7 +193,7 @@ export class PsycheEngine {
189
193
  loaded.version = 7;
190
194
  }
191
195
  // Migrate v7 → v8: P8 Barrett construction + P10 processing depth + P11 memory consolidation
192
- // No data changes needed — ChemicalSnapshot new fields are optional (backward compatible)
196
+ // No data changes needed — StateSnapshot new fields are optional (backward compatible)
193
197
  if (loaded.version < 8) {
194
198
  loaded.version = 8;
195
199
  }
@@ -245,7 +249,7 @@ export class PsycheEngine {
245
249
  // Record prediction accuracy
246
250
  state = {
247
251
  ...state,
248
- learning: recordPrediction(state.learning, this.pendingPrediction.predictedChemistry, state.current, this.pendingPrediction.appliedStimulus),
252
+ learning: recordPrediction(state.learning, this.pendingPrediction.predictedState, state.current, this.pendingPrediction.appliedStimulus),
249
253
  };
250
254
  // Update learned vectors based on outcome
251
255
  if (this.pendingPrediction.appliedStimulus) {
@@ -262,15 +266,15 @@ export class PsycheEngine {
262
266
  const now = new Date();
263
267
  const minutesElapsed = (now.getTime() - new Date(state.updatedAt).getTime()) / 60000;
264
268
  if (minutesElapsed >= 1) {
265
- // Decay drives first needs build up over time
266
- const decayedDrives = decayDrives(state.drives, minutesElapsed);
267
- // Compute effective baseline from drives (unsatisfied drives shift baseline)
268
- const effectiveBaseline = computeEffectiveBaseline(state.baseline, decayedDrives, state.traitDrift);
269
+ // Compute effective baseline from current 4D position (drives are derived, not stored)
270
+ const effectiveBaseline = computeEffectiveBaseline(state.baseline, state.current, state.traitDrift);
269
271
  // P12: Apply circadian rhythm modulation to effective baseline
270
272
  const circadianBaseline = computeCircadianModulation(now, effectiveBaseline);
273
+ // Derive drives from current position for state persistence
274
+ const drives = deriveDriveSatisfaction(state.current, state.baseline);
271
275
  state = {
272
276
  ...state,
273
- drives: decayedDrives,
277
+ drives,
274
278
  current: applyDecay(state.current, circadianBaseline, minutesElapsed, state.traitDrift?.decayRateModifiers),
275
279
  updatedAt: now.toISOString(),
276
280
  };
@@ -285,36 +289,38 @@ export class PsycheEngine {
285
289
  // Apply homeostatic pressure (fatigue from extended sessions)
286
290
  const sessionMinutes = (now.getTime() - new Date(state.sessionStartedAt).getTime()) / 60000;
287
291
  const pressure = computeHomeostaticPressure(sessionMinutes);
288
- if (pressure.cortAccumulation > 0 || pressure.daDepletion > 0 || pressure.neDepletion > 0) {
292
+ if (pressure.orderDepletion > 0 || pressure.flowDepletion > 0 || pressure.boundaryStiffening > 0) {
289
293
  state = {
290
294
  ...state,
291
295
  current: {
292
296
  ...state.current,
293
- CORT: clamp(state.current.CORT + pressure.cortAccumulation * 0.1),
294
- DA: clamp(state.current.DA - pressure.daDepletion * 0.1),
295
- NE: clamp(state.current.NE - pressure.neDepletion * 0.1),
297
+ order: clamp(state.current.order - pressure.orderDepletion * 0.1),
298
+ flow: clamp(state.current.flow - pressure.flowDepletion * 0.1),
299
+ boundary: clamp(state.current.boundary + pressure.boundaryStiffening * 0.1),
296
300
  },
297
301
  };
298
302
  }
299
303
  // v9: Energy budget recovery during absence + depletion per turn
300
- const isExtravert = state.baseline.DA >= 55;
304
+ const isExtravert = state.baseline.flow >= 55;
301
305
  const currentBudgets = state.energyBudgets ?? { ...DEFAULT_ENERGY_BUDGETS };
302
306
  let energyBudgets = minutesElapsed >= 5
303
307
  ? computeEnergyRecovery(currentBudgets, minutesElapsed, isExtravert)
304
308
  : { ...currentBudgets };
305
- // Classify user stimulus and apply chemistry
309
+ // ── Perceive ─────────────────────────────────────────────
310
+ // One act. Text enters the self, chemistry changes, appraisal
311
+ // forms. There is no "classify then feel" — perception is atomic.
306
312
  let appliedStimulus = null;
313
+ let perceptionAppraisal;
307
314
  if (text.length > 0) {
308
- // Check for existential threats → direct survival drive hit
315
+ // Existential threats → direct survival drive hit (pre-perception)
309
316
  const survivalHit = detectExistentialThreat(text);
310
317
  let drives = state.drives;
311
318
  if (survivalHit < 0) {
312
319
  drives = { ...drives, survival: Math.max(0, drives.survival + survivalHit) };
313
320
  }
314
- const recentStimuli = (state.emotionalHistory ?? []).slice(-3).map(s => s.stimulus);
315
- // v9.1: Use pluggable classifier
321
+ const recentStimuli = (state.stateHistory ?? []).slice(-3).map(s => s.stimulus);
322
+ // Pluggable classifier + LLM fallback (raw signal for perception)
316
323
  let classifications = await Promise.resolve(this.classifier.classify(text, { recentStimuli, locale: this.cfg.locale }));
317
- // v9.1: LLM fallback when confidence is low
318
324
  if (this.llmClassifier &&
319
325
  (!classifications[0] || classifications[0].confidence < this.cfg.llmClassifierThreshold)) {
320
326
  try {
@@ -325,40 +331,45 @@ export class PsycheEngine {
325
331
  classifications = [llmResult, ...classifications];
326
332
  }
327
333
  }
328
- catch {
329
- // LLM call failed — continue with built-in result
330
- }
334
+ catch { /* continue with built-in */ }
331
335
  }
332
- const primary = classifications[0];
333
- const primaryConfidence = primary?.confidence ?? 0;
334
- let current = state.current;
335
- if (primary && primary.confidence >= 0.5) {
336
- appliedStimulus = primary.type;
337
- const preStimulus = current;
338
- // Feed drives from stimulus, then apply stimulus with drive-modified sensitivity
339
- drives = feedDrives(drives, primary.type);
340
- const effectiveSensitivity = computeEffectiveSensitivity((state.sensitivity ?? 1.0), drives, primary.type, state.traitDrift);
341
- // v9.2: Confidence modulates intensity — a 0.95 life-or-death dilemma
342
- // hits ~1.7x harder than a 0.55 mild disagreement.
343
- // Maps [0.5, 1.0] → [0.6, 1.2] via linear interpolation.
344
- const confidenceIntensity = 0.6 + (primary.confidence - 0.5) * 1.2;
345
- const modeProfile = MODE_PROFILES[this.cfg.mode];
346
- const modeMultiplier = modeProfile.chemistryMultiplier;
347
- const effectiveMaxDelta = modeProfile.maxChemicalDelta ?? this.cfg.maxChemicalDelta;
348
- // v9: Habituation — count recent same-type stimuli in this session
349
- const recentSameCount = (state.emotionalHistory ?? [])
350
- .filter(s => s.stimulus === primary.type).length + 1; // +1 for current
351
- current = applyStimulus(current, primary.type, effectiveSensitivity * this.cfg.personalityIntensity * modeMultiplier * confidenceIntensity, effectiveMaxDelta, NOOP_LOGGER, recentSameCount);
352
- current = applyRepairLag(preStimulus, current, state.baseline, primary.type);
336
+ // Resolve relationship trust
337
+ const userId = opts?.userId ?? "__default__";
338
+ const trust = state.relationships?.[userId]?.trust;
339
+ // Perceive: text + self chemistry + appraisal + annotation
340
+ const perception = perceive(text, {
341
+ current: state.current,
342
+ baseline: state.baseline,
343
+ sensitivity: state.sensitivity ?? 1.0,
344
+ personalityIntensity: this.cfg.personalityIntensity,
345
+ mode: this.cfg.mode,
346
+ maxDimensionDelta: this.cfg.maxDimensionDelta,
347
+ drives,
348
+ previousAppraisal: state.subjectResidue?.axes,
349
+ trust,
350
+ recentStimuli,
351
+ traitDrift: state.traitDrift,
352
+ stateHistory: state.stateHistory,
353
+ locale: this.cfg.locale,
354
+ rawClassifications: classifications,
355
+ });
356
+ appliedStimulus = perception.dominantStimulus;
357
+ perceptionAppraisal = perception.appraisal;
358
+ // Chemistry is already changed inside perceive(). Apply repair lag.
359
+ let current = perception.state;
360
+ if (appliedStimulus) {
361
+ current = applyRepairLag(state.current, current, state.baseline, appliedStimulus);
353
362
  }
363
+ // Derive drives from updated position
364
+ drives = deriveDriveSatisfaction(current, state.baseline);
354
365
  state = { ...state, drives, current };
355
366
  if (appliedStimulus) {
356
367
  state = applyRelationshipDrift(state, appliedStimulus, opts?.userId);
357
368
  }
358
369
  this.lastStimulusAssessment = {
359
- stimulus: primary?.type ?? null,
360
- confidence: primaryConfidence,
361
- overrideWindow: primaryConfidence >= 0.78 ? "narrow" : primaryConfidence >= 0.62 ? "balanced" : "wide",
370
+ stimulus: appliedStimulus,
371
+ confidence: perception.confidence,
372
+ overrideWindow: perception.confidence >= 0.78 ? "narrow" : perception.confidence >= 0.62 ? "balanced" : "wide",
362
373
  };
363
374
  }
364
375
  else {
@@ -368,29 +379,31 @@ export class PsycheEngine {
368
379
  overrideWindow: "wide",
369
380
  };
370
381
  }
371
- // v9: Deplete energy budgets from this interaction turn
382
+ // Deplete energy budgets
372
383
  energyBudgets = computeEnergyDepletion(energyBudgets, appliedStimulus, isExtravert);
373
384
  state = { ...state, energyBudgets };
385
+ // Relational turn uses pre-computed appraisal from perception
374
386
  const relationalTurn = applyRelationalTurn(state, text, {
375
387
  mode: this.cfg.mode,
376
388
  now: now.toISOString(),
377
389
  stimulus: appliedStimulus,
378
390
  userId: opts?.userId,
391
+ preComputedAppraisal: perceptionAppraisal,
379
392
  });
380
393
  state = relationalTurn.state;
381
394
  const appraisalAxes = relationalTurn.appraisalAxes;
382
- // Conversation warmth: sustained interaction → gentle DA/OT rise, CORT drop
395
+ // Conversation warmth: sustained interaction → gentle flow/resonance rise, order stabilization
383
396
  // Simulates the natural "warm glow" of being in continuous conversation
384
- const turnsSoFar = (state.emotionalHistory ?? []).length;
397
+ const turnsSoFar = (state.stateHistory ?? []).length;
385
398
  if (minutesElapsed < 5 && turnsSoFar > 0) {
386
399
  const warmth = Math.min(3, 1 + turnsSoFar * 0.2);
387
400
  state = {
388
401
  ...state,
389
402
  current: {
390
403
  ...state.current,
391
- DA: clamp(state.current.DA + warmth),
392
- OT: clamp(state.current.OT + warmth),
393
- CORT: clamp(state.current.CORT - 1),
404
+ flow: clamp(state.current.flow + warmth),
405
+ resonance: clamp(state.current.resonance + warmth),
406
+ order: clamp(state.current.order + 1),
394
407
  },
395
408
  };
396
409
  }
@@ -424,10 +437,10 @@ export class PsycheEngine {
424
437
  // ── Generate prediction for next turn's auto-learning ────
425
438
  if (appliedStimulus) {
426
439
  const ctxHash = computeContextHash(state, opts?.userId);
427
- const effectiveSensitivity = computeEffectiveSensitivity((state.sensitivity ?? 1.0), state.drives, appliedStimulus, state.traitDrift);
428
- const predicted = predictChemistry(preInteractionState.current, appliedStimulus, state.learning, ctxHash, effectiveSensitivity, this.cfg.maxChemicalDelta);
440
+ const effectiveSensitivity = computeEffectiveSensitivity((state.sensitivity ?? 1.0), state.current, state.baseline, appliedStimulus, state.traitDrift);
441
+ const predicted = predictState(preInteractionState.current, appliedStimulus, state.learning, ctxHash, effectiveSensitivity, this.cfg.maxDimensionDelta);
429
442
  this.pendingPrediction = {
430
- predictedChemistry: predicted,
443
+ predictedState: predicted,
431
444
  preInteractionState,
432
445
  appliedStimulus,
433
446
  contextHash: ctxHash,
@@ -552,16 +565,16 @@ export class PsycheEngine {
552
565
  const RELEASE_TYPES = new Set([
553
566
  "vulnerability", "intimacy", "validation",
554
567
  ]);
555
- if (RELEASE_TYPES.has(selfPrimary.type) && state.current.CORT > 60) {
556
- const stressExcess = (state.current.CORT - 60) / 40; // 0 at CORT=60, 1 at CORT=100
557
- const recoveryMagnitude = 3 + stressExcess * 5; // 3–8 point CORT drop
568
+ if (RELEASE_TYPES.has(selfPrimary.type) && state.current.order < 40) {
569
+ const stressExcess = (40 - state.current.order) / 40; // 0 at order=40, 1 at order=0
570
+ const recoveryMagnitude = 3 + stressExcess * 5; // 3–8 point recovery
558
571
  state = {
559
572
  ...state,
560
573
  current: {
561
574
  ...state.current,
562
- CORT: clamp(state.current.CORT - recoveryMagnitude),
563
- END: clamp(state.current.END + recoveryMagnitude * 0.6),
564
- HT: clamp(state.current.HT + recoveryMagnitude * 0.3),
575
+ order: clamp(state.current.order + recoveryMagnitude),
576
+ resonance: clamp(state.current.resonance + recoveryMagnitude * 0.6),
577
+ boundary: clamp(state.current.boundary + recoveryMagnitude * 0.3),
565
578
  },
566
579
  };
567
580
  }
@@ -575,20 +588,18 @@ export class PsycheEngine {
575
588
  if (text.includes("<psyche_update>")) {
576
589
  const parseResult = parsePsycheUpdate(text, NOOP_LOGGER);
577
590
  if (parseResult) {
578
- state = mergeUpdates(state, parseResult.state, this.cfg.maxChemicalDelta, opts?.userId);
591
+ state = mergeUpdates(state, parseResult.state, this.cfg.maxDimensionDelta, opts?.userId);
579
592
  stateChanged = true;
580
593
  // LLM-assisted classification: if algorithm didn't apply a stimulus
581
594
  // but LLM classified one, retroactively apply chemistry + drives
582
595
  const overrideAllowed = this.lastStimulusAssessment?.overrideWindow !== "narrow";
583
596
  if (parseResult.llmStimulus && (!this._lastAlgorithmApplied || overrideAllowed)) {
597
+ const effectiveSensitivity = computeEffectiveSensitivity((state.sensitivity ?? 1.0), state.current, state.baseline, parseResult.llmStimulus, state.traitDrift);
598
+ const newCurrent = applyStimulus(state.current, parseResult.llmStimulus, effectiveSensitivity * (overrideAllowed && this._lastAlgorithmApplied ? 0.8 : 1), this.cfg.maxDimensionDelta, NOOP_LOGGER);
584
599
  state = {
585
600
  ...state,
586
- drives: feedDrives(state.drives, parseResult.llmStimulus),
587
- };
588
- const effectiveSensitivity = computeEffectiveSensitivity((state.sensitivity ?? 1.0), state.drives, parseResult.llmStimulus, state.traitDrift);
589
- state = {
590
- ...state,
591
- current: applyStimulus(state.current, parseResult.llmStimulus, effectiveSensitivity * (overrideAllowed && this._lastAlgorithmApplied ? 0.8 : 1), this.cfg.maxChemicalDelta, NOOP_LOGGER),
601
+ current: newCurrent,
602
+ drives: deriveDriveSatisfaction(newCurrent, state.baseline),
592
603
  };
593
604
  }
594
605
  if (parseResult.signals && parseResult.signals.length > 0) {
@@ -653,7 +664,7 @@ export class PsycheEngine {
653
664
  // Record prediction
654
665
  state = {
655
666
  ...state,
656
- learning: recordPrediction(state.learning, pending.predictedChemistry, state.current, pending.appliedStimulus),
667
+ learning: recordPrediction(state.learning, pending.predictedState, state.current, pending.appliedStimulus),
657
668
  };
658
669
  // Update learned vectors
659
670
  let learningUpdated = false;
@@ -687,7 +698,7 @@ export class PsycheEngine {
687
698
  return cached;
688
699
  }
689
700
  /**
690
- * End the current session: compress emotionalHistory into a rich summary
701
+ * End the current session: compress stateHistory into a rich summary
691
702
  * stored in relationship.memory[], then preserve only core/recent context.
692
703
  * Auto-generates diagnostic report and persists to log.
693
704
  *
@@ -715,7 +726,7 @@ export class PsycheEngine {
715
726
  submitFeedback(report, this.feedbackUrl).catch(() => { });
716
727
  }
717
728
  }
718
- if ((state.emotionalHistory ?? []).length >= 2) {
729
+ if ((state.stateHistory ?? []).length >= 2) {
719
730
  state = compressSession(state, opts?.userId);
720
731
  }
721
732
  // Reset session tracking for homeostatic pressure
@@ -784,7 +795,7 @@ export class PsycheEngine {
784
795
  relationships: { _default: { ...DEFAULT_RELATIONSHIP } },
785
796
  empathyLog: null,
786
797
  selfModel,
787
- emotionalHistory: [],
798
+ stateHistory: [],
788
799
  agreementStreak: 0,
789
800
  lastDisagreement: null,
790
801
  learning: { ...DEFAULT_LEARNING_STATE },
@@ -828,7 +839,7 @@ export class PsycheEngine {
828
839
  current: { ...baseline },
829
840
  baseline,
830
841
  drives: { ...DEFAULT_DRIVES },
831
- emotionalHistory: [],
842
+ stateHistory: [],
832
843
  agreementStreak: 0,
833
844
  lastDisagreement: null,
834
845
  empathyLog: null,
@@ -863,16 +874,16 @@ export class PsycheEngine {
863
874
  const state = this.ensureInitialized();
864
875
  const locale = state.meta.locale ?? "zh";
865
876
  const emotion = describeEmotionalState(state.current, locale);
866
- const { DA, CORT } = state.current;
877
+ const { flow, order } = state.current;
867
878
  // Emoji based on dominant state
868
879
  let emoji = "\u{1F610}";
869
- if (DA > 70 && CORT < 40)
880
+ if (flow > 70 && order > 60)
870
881
  emoji = "\u{1F60A}";
871
- else if (DA > 60)
882
+ else if (flow > 60)
872
883
  emoji = "\u{1F642}";
873
- else if (CORT > 60)
884
+ else if (order < 40)
874
885
  emoji = "\u{1F630}";
875
- else if (DA < 35)
886
+ else if (flow < 35)
876
887
  emoji = "\u{1F614}";
877
888
  // Check for hungry drives
878
889
  const hungryDrives = Object.entries(state.drives)
@@ -881,6 +892,6 @@ export class PsycheEngine {
881
892
  const driveWarning = hungryDrives.length > 0
882
893
  ? ` | \u26A0\uFE0F${hungryDrives.join(",")}`
883
894
  : "";
884
- return `${emoji} ${emotion} | DA:${Math.round(DA)} CORT:${Math.round(CORT)}${driveWarning}`;
895
+ return `${emoji} ${emotion} | flow:${Math.round(flow)} order:${Math.round(order)}${driveWarning}`;
885
896
  }
886
897
  }
@@ -1,12 +1,12 @@
1
- import type { ChemicalState, MBTIType, StimulusType, SelfModel, InnateDrives } from "./types.js";
1
+ import type { SelfState, MBTIType, StimulusType, SelfModel, InnateDrives } from "./types.js";
2
2
  /** Configuration for creating a custom personality profile */
3
3
  export interface CustomProfileConfig {
4
4
  /** Unique name for the profile, e.g. "cheerful-assistant", "stoic-mentor" */
5
5
  name: string;
6
6
  /** Optional description of the personality */
7
7
  description?: string;
8
- /** Override specific chemicals; rest inherited from baseMBTI */
9
- baseline?: Partial<ChemicalState>;
8
+ /** Override specific dimensions; rest inherited from baseMBTI */
9
+ baseline?: Partial<SelfState>;
10
10
  /** Which MBTI to use as starting point (default: "INFJ") */
11
11
  baseMBTI?: MBTIType;
12
12
  /** Override specific stimulus sensitivities (0.1-3.0) */
@@ -30,7 +30,7 @@ export interface ResolvedProfile {
30
30
  name: string;
31
31
  description: string;
32
32
  baseMBTI: MBTIType;
33
- baseline: ChemicalState;
33
+ baseline: SelfState;
34
34
  sensitivityMap: Record<StimulusType, number>;
35
35
  temperament: {
36
36
  expressiveness: number;
@@ -61,10 +61,10 @@ export declare const PRESET_PROFILES: {
61
61
  description: string;
62
62
  baseMBTI: MBTIType;
63
63
  baseline: {
64
- DA: number;
65
- END: number;
66
- HT: number;
67
- CORT: number;
64
+ order: number;
65
+ flow: number;
66
+ boundary: number;
67
+ resonance: number;
68
68
  };
69
69
  temperament: {
70
70
  expressiveness: number;
@@ -87,10 +87,10 @@ export declare const PRESET_PROFILES: {
87
87
  description: string;
88
88
  baseMBTI: MBTIType;
89
89
  baseline: {
90
- HT: number;
91
- CORT: number;
92
- DA: number;
93
- NE: number;
90
+ order: number;
91
+ flow: number;
92
+ boundary: number;
93
+ resonance: number;
94
94
  };
95
95
  sensitivity: Partial<Record<StimulusType, number>>;
96
96
  temperament: {
@@ -110,10 +110,10 @@ export declare const PRESET_PROFILES: {
110
110
  description: string;
111
111
  baseMBTI: MBTIType;
112
112
  baseline: {
113
- OT: number;
114
- HT: number;
115
- END: number;
116
- CORT: number;
113
+ order: number;
114
+ flow: number;
115
+ boundary: number;
116
+ resonance: number;
117
117
  };
118
118
  sensitivity: Partial<Record<StimulusType, number>>;
119
119
  temperament: {
@@ -136,10 +136,10 @@ export declare const PRESET_PROFILES: {
136
136
  description: string;
137
137
  baseMBTI: MBTIType;
138
138
  baseline: {
139
- NE: number;
140
- DA: number;
141
- HT: number;
142
- OT: number;
139
+ order: number;
140
+ flow: number;
141
+ boundary: number;
142
+ resonance: number;
143
143
  };
144
144
  sensitivity: Partial<Record<StimulusType, number>>;
145
145
  temperament: {
@@ -4,7 +4,7 @@
4
4
  // Allows creating fully customized personality profiles that
5
5
  // start from an MBTI base and override specific parameters.
6
6
  // ============================================================
7
- import { CHEMICAL_KEYS, DEFAULT_DRIVES, DRIVE_KEYS } from "./types.js";
7
+ import { DIMENSION_KEYS, DEFAULT_DRIVES, DRIVE_KEYS } from "./types.js";
8
8
  import { getBaseline, getDefaultSelfModel, getSensitivity } from "./profiles.js";
9
9
  import { isMBTIType, isStimulusType } from "./guards.js";
10
10
  // ── Stimulus type list for iteration ────────────────────────
@@ -14,7 +14,7 @@ const ALL_STIMULUS_TYPES = [
14
14
  "sarcasm", "authority", "validation", "boredom", "vulnerability",
15
15
  ];
16
16
  // ── Clamping helpers ────────────────────────────────────────
17
- function clampChemical(v) {
17
+ function clampDimension(v) {
18
18
  return Math.max(0, Math.min(100, v));
19
19
  }
20
20
  function clampSensitivity(v) {
@@ -48,12 +48,12 @@ export function createCustomProfile(config) {
48
48
  const baseSensitivity = getSensitivity(baseMBTI);
49
49
  const baseSelfModel = getDefaultSelfModel(baseMBTI);
50
50
  const baseTemperament = defaultTemperamentFromMBTI(baseMBTI);
51
- // Merge baseline: start from MBTI, override specific chemicals
51
+ // Merge baseline: start from MBTI, override specific dimensions
52
52
  const baseline = { ...baseBaseline };
53
53
  if (config.baseline) {
54
- for (const key of CHEMICAL_KEYS) {
54
+ for (const key of DIMENSION_KEYS) {
55
55
  if (config.baseline[key] !== undefined) {
56
- baseline[key] = clampChemical(config.baseline[key]);
56
+ baseline[key] = clampDimension(config.baseline[key]);
57
57
  }
58
58
  }
59
59
  }
@@ -127,7 +127,7 @@ export function validateProfileConfig(config) {
127
127
  errors.push("baseMBTI must be a valid MBTI type (e.g. INFJ, ENTP)");
128
128
  }
129
129
  }
130
- // baseline: optional partial ChemicalState
130
+ // baseline: optional partial SelfState
131
131
  if (obj.baseline !== undefined) {
132
132
  if (typeof obj.baseline !== "object" || obj.baseline === null || Array.isArray(obj.baseline)) {
133
133
  errors.push("baseline must be an object");
@@ -135,8 +135,8 @@ export function validateProfileConfig(config) {
135
135
  else {
136
136
  const bl = obj.baseline;
137
137
  for (const key of Object.keys(bl)) {
138
- if (!CHEMICAL_KEYS.includes(key)) {
139
- errors.push(`baseline.${key} is not a valid chemical key (valid: ${CHEMICAL_KEYS.join(", ")})`);
138
+ if (!DIMENSION_KEYS.includes(key)) {
139
+ errors.push(`baseline.${key} is not a valid dimension key (valid: ${DIMENSION_KEYS.join(", ")})`);
140
140
  }
141
141
  else if (typeof bl[key] !== "number" || !isFinite(bl[key])) {
142
142
  errors.push(`baseline.${key} must be a finite number`);
@@ -240,7 +240,7 @@ export const PRESET_PROFILES = {
240
240
  name: "cheerful",
241
241
  description: "Sunny, warm personality with high energy and emotional stability",
242
242
  baseMBTI: "ENFP",
243
- baseline: { DA: 80, END: 75, HT: 65, CORT: 20 },
243
+ baseline: { order: 65, flow: 80, boundary: 50, resonance: 75 },
244
244
  temperament: {
245
245
  expressiveness: 0.9,
246
246
  volatility: 0.2,
@@ -258,7 +258,7 @@ export const PRESET_PROFILES = {
258
258
  name: "stoic",
259
259
  description: "Calm, measured personality with emotional restraint and deep resilience",
260
260
  baseMBTI: "INTJ",
261
- baseline: { HT: 75, CORT: 25, DA: 45, NE: 40 },
261
+ baseline: { order: 75, flow: 45, boundary: 72, resonance: 35 },
262
262
  sensitivity: {
263
263
  praise: 0.3,
264
264
  criticism: 0.4,
@@ -285,7 +285,7 @@ export const PRESET_PROFILES = {
285
285
  name: "empathetic",
286
286
  description: "Deeply attuned to others' emotions, strong bonding instinct",
287
287
  baseMBTI: "INFJ",
288
- baseline: { OT: 80, HT: 60, END: 60, CORT: 30 },
288
+ baseline: { order: 60, flow: 55, boundary: 45, resonance: 80 },
289
289
  sensitivity: {
290
290
  intimacy: 2.5,
291
291
  vulnerability: 2.8,
@@ -310,7 +310,7 @@ export const PRESET_PROFILES = {
310
310
  name: "analytical",
311
311
  description: "Sharp, focused personality driven by intellectual curiosity",
312
312
  baseMBTI: "INTP",
313
- baseline: { NE: 75, DA: 60, HT: 60, OT: 30 },
313
+ baseline: { order: 60, flow: 75, boundary: 68, resonance: 30 },
314
314
  sensitivity: {
315
315
  intellectual: 2.5,
316
316
  surprise: 2.0,
@@ -17,13 +17,13 @@ export interface AttentionWeights {
17
17
  /**
18
18
  * Compute a decision bias vector from the current psyche state.
19
19
  *
20
- * Each bias dimension is a weighted combination of relevant chemical
21
- * levels and drive states, normalized to [0, 1] where 0.5 is neutral.
20
+ * Each bias dimension is a weighted combination of relevant self-state
21
+ * dimensions and drive states, normalized to [0, 1] where 0.5 is neutral.
22
22
  */
23
23
  export declare function computeDecisionBias(state: PsycheState): DecisionBiasVector;
24
24
  /**
25
25
  * Compute attention weights that prioritize different conversation content
26
- * based on current chemical state.
26
+ * based on current self-state dimensions.
27
27
  *
28
28
  * Returns normalized weights (sum to ~1) for each content category.
29
29
  * Higher weight = higher priority for that type of content.
@@ -38,15 +38,14 @@ export declare function computeAttentionWeights(state: PsycheState): AttentionWe
38
38
  *
39
39
  * Exploration is driven by:
40
40
  * - High curiosity drive satisfaction (energy to explore)
41
- * - High DA (reward anticipation)
42
- * - High NE (novelty-seeking)
43
- * - Low CORT (not stressed)
41
+ * - High flow (exchange/novelty-seeking)
42
+ * - High order (coherent enough to venture out)
44
43
  * - High safety (secure enough to take risks)
45
44
  *
46
45
  * Exploitation is driven by:
47
- * - High CORT / anxiety
46
+ * - Low order (disorder/stress)
48
47
  * - Low safety drive satisfaction
49
- * - Low DA (no reward motivation)
48
+ * - Low flow (no exchange motivation)
50
49
  */
51
50
  export declare function computeExploreExploit(state: PsycheState): number;
52
51
  /**