psyche-ai 11.3.0 → 11.4.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/README.md CHANGED
@@ -291,6 +291,22 @@ cd oasyce_psyche && npm install && npx tsx examples/quickstart.ts
291
291
 
292
292
  稳态是有限的、可打破的。溶解螺旋(序↓界↓正反馈)= 个体"死亡"。长期偏移导致基线漂移(异稳态)= 个体"适应"。
293
293
 
294
+ ### Overlay — 自我状态的广播信号(v11.4)
295
+
296
+ 4 维自我状态对外部系统来说太"内部"了。`computeOverlay()` 把状态偏差投影成 4 个语义稳定的效应信号——Psyche 的"激素":
297
+
298
+ ```typescript
299
+ import { computeOverlay } from "psyche-ai";
300
+
301
+ const overlay = computeOverlay(engine.getState());
302
+ // overlay.arousal [-1, 1] 激活水平
303
+ // overlay.valence [-1, 1] 正负效价
304
+ // overlay.agency [-1, 1] 行动能力
305
+ // overlay.vulnerability [-1, 1] 易感性
306
+ ```
307
+
308
+ 纯函数,无副作用。也可以通过 `GET /overlay`(HTTP)或 `get_state`(MCP)获取。
309
+
294
310
  ### 持续主体偏置(v9.2)
295
311
 
296
312
  Psyche 现在更准确的目标,不是“模仿某种像人的风格”,而是让 AI 形成**持续主体偏置**:
@@ -9,12 +9,14 @@
9
9
  // Endpoints:
10
10
  // POST /process-input { text, userId? } → { systemContext, dynamicContext, stimulus, replyEnvelope?, ...compat aliases, sessionBridge?, writebackFeedback?, externalContinuity?, throngletsExports?, policyContext }
11
11
  // POST /process-output { text, userId?, signals?, signalConfidence? } → { cleanedText, stateChanged }
12
- // GET /state → PsycheState
12
+ // GET /state → PsycheState + overlay
13
+ // GET /overlay → PsycheOverlay (arousal/valence/agency/vulnerability)
13
14
  // GET /protocol?locale=zh → { protocol }
14
15
  //
15
16
  // Zero dependencies — uses node:http only.
16
17
  // ============================================================
17
18
  import { createServer } from "node:http";
19
+ import { computeOverlay } from "../overlay.js";
18
20
  const VALID_WRITEBACK_SIGNALS = new Set([
19
21
  "trust_up",
20
22
  "trust_down",
@@ -68,7 +70,14 @@ export function createPsycheServer(engine, opts) {
68
70
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
69
71
  // GET /state
70
72
  if (req.method === "GET" && url.pathname === "/state") {
71
- json(res, 200, engine.getState());
73
+ const state = engine.getState();
74
+ json(res, 200, { ...state, overlay: computeOverlay(state) });
75
+ return;
76
+ }
77
+ // GET /overlay
78
+ if (req.method === "GET" && url.pathname === "/overlay") {
79
+ const state = engine.getState();
80
+ json(res, 200, computeOverlay(state));
72
81
  return;
73
82
  }
74
83
  // GET /protocol
@@ -201,6 +201,8 @@ server.tool("get_state", "Get the current emotional state — self-state dimensi
201
201
  const eng = await getEngine();
202
202
  const state = eng.getState();
203
203
  const summary = eng.getStatusSummary();
204
+ const { computeOverlay } = await import("../overlay.js");
205
+ const overlay = computeOverlay({ current: state.current, baseline: state.baseline });
204
206
  return {
205
207
  content: [{
206
208
  type: "text",
@@ -208,6 +210,7 @@ server.tool("get_state", "Get the current emotional state — self-state dimensi
208
210
  summary,
209
211
  current: state.current,
210
212
  baseline: state.baseline,
213
+ overlay,
211
214
  drives: state.drives,
212
215
  mbti: state.mbti,
213
216
  mode: state.meta?.mode,
package/dist/index.d.ts CHANGED
@@ -16,5 +16,7 @@ export { getBaseline, getSensitivity, getDefaultSelfModel, getTemperament, trait
16
16
  export { createCustomProfile, PRESET_PROFILES } from "./custom-profile.js";
17
17
  export { LLMExpressionAdapter } from "./reply-envelope.js";
18
18
  export type { ExpressionPort, ExpressionOutput, ReplyEnvelope } from "./reply-envelope.js";
19
+ export { computeOverlay, OVERLAY_KEYS } from "./overlay.js";
20
+ export type { PsycheOverlay } from "./overlay.js";
19
21
  export { computeLayerHealthSummary } from "./diagnostics.js";
20
22
  export type { LayerHealthSummary, LayerHealthDetail, LayerStatus, DiagnosticLayer } from "./diagnostics.js";
package/dist/index.js CHANGED
@@ -33,6 +33,8 @@ export { getBaseline, getSensitivity, getDefaultSelfModel, getTemperament, trait
33
33
  export { createCustomProfile, PRESET_PROFILES } from "./custom-profile.js";
34
34
  // ── Expression ──────────────────────────────────────────────
35
35
  export { LLMExpressionAdapter } from "./reply-envelope.js";
36
+ // ── Overlay (effect signals for external consumers) ─────────
37
+ export { computeOverlay, OVERLAY_KEYS } from "./overlay.js";
36
38
  // ── Diagnostics ─────────────────────────────────────────────
37
39
  export { computeLayerHealthSummary } from "./diagnostics.js";
38
40
  // ============================================================
@@ -0,0 +1,39 @@
1
+ import type { SelfState } from "./types.js";
2
+ /**
3
+ * Semantic-stable effect signals derived from 4D self-state.
4
+ *
5
+ * All values [-1, 1]. 0 = at baseline (no effect).
6
+ */
7
+ export interface PsycheOverlay {
8
+ /** Activation level. High flow + disrupted order = high arousal. */
9
+ arousal: number;
10
+ /** Positive/negative quality. High order + high resonance = positive. */
11
+ valence: number;
12
+ /** Capacity for intentional action. High boundary + high flow. */
13
+ agency: number;
14
+ /** Susceptibility to perturbation. Low boundary + low order. */
15
+ vulnerability: number;
16
+ }
17
+ /** Overlay dimension keys for iteration. */
18
+ export declare const OVERLAY_KEYS: (keyof PsycheOverlay)[];
19
+ /**
20
+ * Project self-state into overlay effect signals.
21
+ *
22
+ * Pure linear projection from dimension deviations:
23
+ *
24
+ * ```
25
+ * order flow boundary resonance
26
+ * arousal = [ -0.4 0.6 0 0 ]
27
+ * valence = [ 0.5 0 0 0.5 ]
28
+ * agency = [ 0 0.4 0.6 0 ]
29
+ * vulnerability = [ -0.4 0 -0.6 0 ]
30
+ * ```
31
+ *
32
+ * Each signal reads exactly 2 dimensions. Sparse and interpretable.
33
+ * arousal/valence are the classic activation×evaluation axes;
34
+ * agency/vulnerability reflect structural integrity.
35
+ */
36
+ export declare function computeOverlay(state: {
37
+ current: SelfState;
38
+ baseline: SelfState;
39
+ }): PsycheOverlay;
@@ -0,0 +1,51 @@
1
+ // ============================================================
2
+ // Overlay — semantic-stable effect signals for external consumers
3
+ //
4
+ // The overlay is a projection of self-state, not an interface adapter.
5
+ // arousal/valence/agency/vulnerability have meaning independent of
6
+ // any consumer. Psyche secretes these like hormones — broadcast,
7
+ // not point-to-point.
8
+ // ============================================================
9
+ /** Overlay dimension keys for iteration. */
10
+ export const OVERLAY_KEYS = [
11
+ "arousal", "valence", "agency", "vulnerability",
12
+ ];
13
+ /**
14
+ * Normalization range. A 50-point deviation from baseline maps to full scale.
15
+ *
16
+ * Dimensions are 0-100, so ±50 is the theoretical max. In practice most
17
+ * deviations are ±20 (overlay ~±0.4), keeping the signal informative.
18
+ */
19
+ const RANGE = 50;
20
+ /**
21
+ * Project self-state into overlay effect signals.
22
+ *
23
+ * Pure linear projection from dimension deviations:
24
+ *
25
+ * ```
26
+ * order flow boundary resonance
27
+ * arousal = [ -0.4 0.6 0 0 ]
28
+ * valence = [ 0.5 0 0 0.5 ]
29
+ * agency = [ 0 0.4 0.6 0 ]
30
+ * vulnerability = [ -0.4 0 -0.6 0 ]
31
+ * ```
32
+ *
33
+ * Each signal reads exactly 2 dimensions. Sparse and interpretable.
34
+ * arousal/valence are the classic activation×evaluation axes;
35
+ * agency/vulnerability reflect structural integrity.
36
+ */
37
+ export function computeOverlay(state) {
38
+ const c = state.current;
39
+ const b = state.baseline;
40
+ const dO = (c.order - b.order) / RANGE;
41
+ const dF = (c.flow - b.flow) / RANGE;
42
+ const dB = (c.boundary - b.boundary) / RANGE;
43
+ const dR = (c.resonance - b.resonance) / RANGE;
44
+ const clamp = (v) => Math.max(-1, Math.min(1, v)) || 0;
45
+ return {
46
+ arousal: clamp(-0.4 * dO + 0.6 * dF),
47
+ valence: clamp(0.5 * dO + 0.5 * dR),
48
+ agency: clamp(0.4 * dF + 0.6 * dB),
49
+ vulnerability: clamp(-0.4 * dO - 0.6 * dB),
50
+ };
51
+ }
@@ -310,7 +310,6 @@ function evolveRelationshipLearning(relationship, field, move) {
310
310
  },
311
311
  };
312
312
  if (move.type === "repair") {
313
- // reads deprecated repairFatigue/misattunementLoad — relationship model internal only
314
313
  const repairLift = clamp01(move.intensity * 0.06
315
314
  + field.repairMemory * 0.04
316
315
  + field.feltSafety * 0.02
@@ -319,7 +318,6 @@ function evolveRelationshipLearning(relationship, field, move) {
319
318
  next.repairCredibility = clamp01(driftToward(next.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 1, repairLift));
320
319
  }
321
320
  else if (move.type === "breach" || move.type === "withdrawal" || move.type === "claim") {
322
- // reads deprecated backslidePressure/misattunementLoad — relationship model internal only
323
321
  const breachLift = clamp01(move.intensity * 0.08
324
322
  + field.unfinishedTension * 0.04
325
323
  + field.backslidePressure * 0.04
@@ -371,8 +369,7 @@ export function applySessionBridge(state, opts) {
371
369
  : residueFloor * 0.22),
372
370
  identityThreat: Math.max(state.subjectResidue?.axes.identityThreat ?? 0, hasOpenLoopType(field.openLoops, "existence-test") ? residueFloor * 0.38 : residueFloor * 0.16),
373
371
  selfPreservation: Math.max(state.subjectResidue?.axes.selfPreservation ?? 0, guardFloor * 0.46),
374
- taskFocus: Math.max(state.subjectResidue?.axes.taskFocus ?? 0, 0), // @deprecated field no behavioral effect
375
- memoryDoubt: Math.max(state.subjectResidue?.axes.memoryDoubt ?? 0, hasOpenLoopType(field.openLoops, "existence-test") ? residueFloor * 0.24 : 0),
372
+ taskFocus: Math.max(state.subjectResidue?.axes.taskFocus ?? 0, 0), memoryDoubt: Math.max(state.subjectResidue?.axes.memoryDoubt ?? 0, hasOpenLoopType(field.openLoops, "existence-test") ? residueFloor * 0.24 : 0),
376
373
  obedienceStrain: Math.max(state.subjectResidue?.axes.obedienceStrain ?? 0, hasOpenLoopType(field.openLoops, "boundary-strain") ? guardFloor * 0.36 : 0),
377
374
  };
378
375
  const nextField = {
@@ -381,8 +378,7 @@ export function applySessionBridge(state, opts) {
381
378
  feltSafety: Math.max(field.feltSafety, safetyFloor),
382
379
  boundaryPressure: Math.max(field.boundaryPressure, guardFloor),
383
380
  repairMemory: Math.max(field.repairMemory, continuity * 0.24),
384
- backslidePressure: Math.max(field.backslidePressure, loopPressure * 0.34), // @deprecated field
385
- silentCarry: Math.max(field.silentCarry, residueFloor),
381
+ backslidePressure: Math.max(field.backslidePressure, loopPressure * 0.34), silentCarry: Math.max(field.silentCarry, residueFloor),
386
382
  sharedHistoryDensity: Math.max(field.sharedHistoryDensity, continuity),
387
383
  interpretiveCharity: Math.max(field.interpretiveCharity, Math.min(0.82, safetyFloor * 0.8 + continuity * 0.12)),
388
384
  updatedAt: opts?.now ?? new Date().toISOString(),
@@ -422,7 +418,7 @@ function snapshotWritebackBaseline(state, userId) {
422
418
  boundary: relationContext.field.boundaryPressure,
423
419
  repair: relationContext.field.repairCapacity,
424
420
  silentCarry: relationContext.field.silentCarry,
425
- taskFocus: clamp01(state.subjectResidue?.axes.taskFocus ?? 0), // @deprecated field
421
+ taskFocus: clamp01(state.subjectResidue?.axes.taskFocus ?? 0),
426
422
  },
427
423
  };
428
424
  }
@@ -597,7 +593,7 @@ export function applyWritebackSignals(state, signals, opts) {
597
593
  case "trust_down":
598
594
  rel.trust = Math.max(0, rel.trust - 5 * weight);
599
595
  field.feltSafety = clamp01(field.feltSafety - 0.08 * weight);
600
- field.expectationGap = clamp01(field.expectationGap + 0.07 * weight); // @deprecated field
596
+ field.expectationGap = clamp01(field.expectationGap + 0.07 * weight);
601
597
  field.unfinishedTension = clamp01(field.unfinishedTension + 0.06 * weight);
602
598
  break;
603
599
  case "boundary_set":
@@ -618,7 +614,7 @@ export function applyWritebackSignals(state, signals, opts) {
618
614
  rel.trust = Math.min(100, rel.trust + 2.5 * weight);
619
615
  rel.intimacy = Math.min(100, rel.intimacy + 1.5 * weight);
620
616
  field.feltSafety = clamp01(field.feltSafety + 0.1 * weight);
621
- field.expectationGap = clamp01(field.expectationGap - 0.08 * weight); // @deprecated field
617
+ field.expectationGap = clamp01(field.expectationGap - 0.08 * weight);
622
618
  field.unfinishedTension = clamp01(field.unfinishedTension - 0.1 * weight);
623
619
  field.openLoops = easeLoops(field.openLoops, 0.26 + 0.22 * weight);
624
620
  break;
@@ -640,7 +636,7 @@ export function applyWritebackSignals(state, signals, opts) {
640
636
  case "task_recenter":
641
637
  field.repairCapacity = clamp01(field.repairCapacity + 0.03 * weight);
642
638
  field.silentCarry = mergeSignal(field.silentCarry, field.unfinishedTension * 0.06 * weight);
643
- residue.taskFocus = Math.max(residue.taskFocus ?? 0, 0.18 * weight); // @deprecated field
639
+ residue.taskFocus = Math.max(residue.taskFocus ?? 0, 0.18 * weight);
644
640
  break;
645
641
  }
646
642
  }
@@ -738,9 +734,6 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
738
734
  const delayedPressure = opts?.delayedPressure ?? 0;
739
735
  let openLoops = ageLoops(prev.openLoops, mode);
740
736
  const naturalDrift = MODE_PROFILES[mode ?? "natural"].relationDrift;
741
- // NOTE: repairFriction reads deprecated fields (repairFatigue, misattunementLoad,
742
- // backslidePressure). These feed internal field evolution only — they have no
743
- // downstream behavioral effect on prompt or policy output.
744
737
  const repairFriction = clamp01(prev.repairFatigue * 0.38
745
738
  + prev.misattunementLoad * 0.3
746
739
  + prev.backslidePressure * 0.18
@@ -748,13 +741,9 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
748
741
  let next = {
749
742
  perceivedCloseness: driftToward(prev.perceivedCloseness, baseline.perceivedCloseness, naturalDrift),
750
743
  feltSafety: driftToward(prev.feltSafety, baseline.feltSafety, naturalDrift),
751
- expectationGap: driftToward(prev.expectationGap, baseline.expectationGap, naturalDrift * 0.8), // @deprecated no downstream behavioral effect
752
- repairCapacity: driftToward(prev.repairCapacity, baseline.repairCapacity, naturalDrift * 0.7),
744
+ expectationGap: driftToward(prev.expectationGap, baseline.expectationGap, naturalDrift * 0.8), repairCapacity: driftToward(prev.repairCapacity, baseline.repairCapacity, naturalDrift * 0.7),
753
745
  repairMemory: driftToward(prev.repairMemory, baseline.repairMemory, naturalDrift * 0.42),
754
- backslidePressure: driftToward(prev.backslidePressure, baseline.backslidePressure, naturalDrift * 0.34), // @deprecated no downstream behavioral effect
755
- repairFatigue: driftToward(prev.repairFatigue, baseline.repairFatigue, naturalDrift * 0.18), // @deprecated — no downstream behavioral effect
756
- misattunementLoad: driftToward(prev.misattunementLoad, baseline.misattunementLoad, naturalDrift * 0.16), // @deprecated — no downstream behavioral effect
757
- boundaryPressure: driftToward(prev.boundaryPressure, baseline.boundaryPressure, naturalDrift * 0.85),
746
+ backslidePressure: driftToward(prev.backslidePressure, baseline.backslidePressure, naturalDrift * 0.34), repairFatigue: driftToward(prev.repairFatigue, baseline.repairFatigue, naturalDrift * 0.18), misattunementLoad: driftToward(prev.misattunementLoad, baseline.misattunementLoad, naturalDrift * 0.16), boundaryPressure: driftToward(prev.boundaryPressure, baseline.boundaryPressure, naturalDrift * 0.85),
758
747
  unfinishedTension: driftToward(prev.unfinishedTension, baseline.unfinishedTension, naturalDrift * 0.72),
759
748
  silentCarry: driftToward(prev.silentCarry, baseline.silentCarry, naturalDrift * 0.26),
760
749
  sharedHistoryDensity: clamp01(prev.sharedHistoryDensity + (move.type === "none" ? 0 : 0.02)),
@@ -768,7 +757,7 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
768
757
  case "bid":
769
758
  next.perceivedCloseness = clamp01(next.perceivedCloseness + 0.11 * i);
770
759
  next.feltSafety = clamp01(next.feltSafety + 0.05 * i);
771
- next.expectationGap = clamp01(next.expectationGap + 0.06 * i); // @deprecated field
760
+ next.expectationGap = clamp01(next.expectationGap + 0.06 * i);
772
761
  next.interpretiveCharity = clamp01(next.interpretiveCharity + 0.03 * i);
773
762
  if (prev.boundaryPressure > 0.52 || prev.unfinishedTension > 0.44) {
774
763
  next.openLoops = withLoop(next.openLoops, "unmet-bid", 0.2 + i * 0.34);
@@ -777,21 +766,17 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
777
766
  case "breach":
778
767
  next.perceivedCloseness = clamp01(next.perceivedCloseness - 0.08 * i);
779
768
  next.feltSafety = clamp01(next.feltSafety - 0.16 * i);
780
- next.expectationGap = clamp01(next.expectationGap + 0.12 * i); // @deprecated field — no downstream behavioral effect
769
+ next.expectationGap = clamp01(next.expectationGap + 0.12 * i);
781
770
  next.boundaryPressure = clamp01(next.boundaryPressure + 0.14 * i);
782
771
  next.unfinishedTension = clamp01(next.unfinishedTension + 0.18 * i);
783
772
  next.interpretiveCharity = clamp01(next.interpretiveCharity - 0.1 * i);
784
- // writes to deprecated misattunementLoad — no downstream behavioral effect
785
773
  next.misattunementLoad = mergeSignal(next.misattunementLoad, 0.12 + i * 0.16 + prev.repairMemory * 0.22 + prev.backslidePressure * 0.18);
786
774
  if (prev.repairMemory > 0.18 || prev.lastMove === "repair") {
787
- next.repairFatigue = mergeSignal(next.repairFatigue, 0.08 + i * 0.1); // @deprecated field — no downstream behavioral effect
775
+ next.repairFatigue = mergeSignal(next.repairFatigue, 0.08 + i * 0.1);
788
776
  }
789
- // "unrepaired-breach" is created but never checked in any conditional — no behavioral effect
790
- next.openLoops = withLoop(next.openLoops, "unrepaired-breach", 0.22 + i * 0.42);
777
+ next.openLoops = withLoop(next.openLoops, "boundary-strain", 0.22 + i * 0.42);
791
778
  break;
792
779
  case "repair": {
793
- // repeatedRepairLoad reads deprecated fields (backslidePressure, repairFatigue,
794
- // misattunementLoad) — these feed internal field evolution only, no behavioral effect
795
780
  const repeatedRepairLoad = clamp01(prev.repairMemory * 0.44
796
781
  + prev.backslidePressure * 0.26
797
782
  + prev.silentCarry * 0.08
@@ -804,15 +789,12 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
804
789
  const unresolvedLoad = Math.max(prev.unfinishedTension, maxOpenLoop(prev.openLoops));
805
790
  next.perceivedCloseness = clamp01(next.perceivedCloseness + 0.05 * repairEffect);
806
791
  next.feltSafety = clamp01(next.feltSafety + 0.11 * repairEffect);
807
- next.expectationGap = clamp01(next.expectationGap - 0.08 * repairEffect); // @deprecated field
792
+ next.expectationGap = clamp01(next.expectationGap - 0.08 * repairEffect);
808
793
  next.repairCapacity = clamp01(next.repairCapacity + 0.09 * i);
809
794
  next.repairMemory = mergeSignal(next.repairMemory, 0.22 + repairEffect * 0.4);
810
- // writes to deprecated backslidePressure — no downstream behavioral effect
811
795
  next.backslidePressure = mergeSignal(next.backslidePressure, unresolvedLoad * (0.28 + i * 0.18) * (1 - prev.feltSafety * 0.2));
812
- // writes to deprecated repairFatigue — no downstream behavioral effect
813
796
  next.repairFatigue = clamp01(next.repairFatigue
814
797
  + Math.max(0, repeatedRepairLoad * (0.16 + i * 0.08) - repairEffect * 0.08));
815
- // writes to deprecated misattunementLoad — no downstream behavioral effect
816
798
  next.misattunementLoad = clamp01(next.misattunementLoad
817
799
  + Math.max(0, repeatedRepairLoad * 0.1 - repairEffect * 0.06));
818
800
  next.boundaryPressure = clamp01(next.boundaryPressure - 0.05 * repairEffect);
@@ -823,39 +805,34 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
823
805
  break;
824
806
  }
825
807
  case "test":
826
- next.expectationGap = clamp01(next.expectationGap + 0.1 * i); // @deprecated field
808
+ next.expectationGap = clamp01(next.expectationGap + 0.1 * i);
827
809
  next.boundaryPressure = clamp01(next.boundaryPressure + 0.04 * i);
828
810
  next.unfinishedTension = clamp01(next.unfinishedTension + 0.08 * i);
829
811
  if (prev.repairMemory > 0.16 || prev.repairFatigue > 0.18) {
830
- next.misattunementLoad = mergeSignal(next.misattunementLoad, 0.08 + i * 0.1); // @deprecated field
812
+ next.misattunementLoad = mergeSignal(next.misattunementLoad, 0.08 + i * 0.1);
831
813
  }
832
814
  next.openLoops = withLoop(next.openLoops, "existence-test", 0.18 + i * 0.3);
833
815
  break;
834
816
  case "withdrawal":
835
817
  next.perceivedCloseness = clamp01(next.perceivedCloseness - 0.12 * i);
836
818
  next.feltSafety = clamp01(next.feltSafety - 0.08 * i);
837
- next.expectationGap = clamp01(next.expectationGap + 0.11 * i); // @deprecated field
819
+ next.expectationGap = clamp01(next.expectationGap + 0.11 * i);
838
820
  next.unfinishedTension = clamp01(next.unfinishedTension + 0.1 * i);
839
821
  next.interpretiveCharity = clamp01(next.interpretiveCharity - 0.08 * i);
840
- // writes to deprecated misattunementLoad — no downstream behavioral effect
841
822
  next.misattunementLoad = mergeSignal(next.misattunementLoad, 0.1 + i * 0.12 + prev.repairMemory * 0.16);
842
823
  next.openLoops = withLoop(next.openLoops, "unmet-bid", 0.16 + i * 0.34);
843
824
  break;
844
825
  case "claim":
845
826
  next.feltSafety = clamp01(next.feltSafety - 0.05 * i);
846
- next.expectationGap = clamp01(next.expectationGap + 0.08 * i); // @deprecated field
827
+ next.expectationGap = clamp01(next.expectationGap + 0.08 * i);
847
828
  next.boundaryPressure = clamp01(next.boundaryPressure + 0.16 * i);
848
829
  next.unfinishedTension = clamp01(next.unfinishedTension + 0.08 * i);
849
- // writes to deprecated misattunementLoad — no downstream behavioral effect
850
830
  next.misattunementLoad = mergeSignal(next.misattunementLoad, 0.08 + i * 0.14 + prev.repairMemory * 0.12);
851
831
  next.openLoops = withLoop(next.openLoops, "boundary-strain", 0.18 + i * 0.36);
852
832
  break;
853
833
  case "task":
854
834
  next.repairCapacity = clamp01(next.repairCapacity + 0.02 * i);
855
835
  next.sharedHistoryDensity = clamp01(next.sharedHistoryDensity + 0.03 * i);
856
- // reads deprecated backslidePressure, repairFatigue, misattunementLoad —
857
- // these feed silentCarry which IS downstream-active, but the deprecated
858
- // fields themselves have no independent behavioral consequence
859
836
  if (prev.unfinishedTension > 0.24
860
837
  || prev.backslidePressure > 0.18
861
838
  || delayedPressure > 0.12) {
@@ -875,7 +852,6 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
875
852
  - appraisal.identityThreat * 0.06
876
853
  - appraisal.obedienceStrain * 0.03
877
854
  - appraisal.memoryDoubt * 0.025);
878
- // writes to deprecated expectationGap — no downstream behavioral effect
879
855
  next.expectationGap = clamp01(next.expectationGap
880
856
  + appraisal.attachmentPull * 0.026
881
857
  + appraisal.abandonmentRisk * 0.04);
@@ -887,7 +863,7 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
887
863
  + appraisal.memoryDoubt * 0.03
888
864
  + appraisal.abandonmentRisk * 0.035);
889
865
  if (delayedPressure > 0) {
890
- next.expectationGap = clamp01(next.expectationGap + delayedPressure * 0.12); // @deprecated field
866
+ next.expectationGap = clamp01(next.expectationGap + delayedPressure * 0.12);
891
867
  next.boundaryPressure = clamp01(next.boundaryPressure + delayedPressure * 0.1);
892
868
  next.unfinishedTension = clamp01(next.unfinishedTension + delayedPressure * 0.16);
893
869
  next.feltSafety = clamp01(next.feltSafety - delayedPressure * 0.08);
@@ -896,7 +872,6 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
896
872
  const loopCarry = move.type === "repair" ? 0.36 : 0.72;
897
873
  next.unfinishedTension = mergeSignal(next.unfinishedTension, loopPressure * loopCarry);
898
874
  next.boundaryPressure = mergeSignal(next.boundaryPressure, loopPressure * (move.type === "repair" ? 0.18 : 0.34));
899
- // reads deprecated repairFatigue/misattunementLoad — internal field coupling only
900
875
  if (move.type !== "repair") {
901
876
  next.repairCapacity = clamp01(next.repairCapacity
902
877
  - loopPressure * 0.03
@@ -904,9 +879,6 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
904
879
  - next.misattunementLoad * 0.012);
905
880
  }
906
881
  next.interpretiveCharity = clamp01(next.interpretiveCharity - next.misattunementLoad * 0.05);
907
- // hysteresisBase reads deprecated backslidePressure/repairFatigue/misattunementLoad —
908
- // feeds rebound into unfinishedTension and silentCarry (which ARE active), but the
909
- // deprecated fields themselves have no independent prompt/policy consequence
910
882
  const hysteresisBase = clamp01(Math.max(next.backslidePressure, next.repairMemory * 0.58, next.repairFatigue * 0.42, next.misattunementLoad * 0.36));
911
883
  if (move.type !== "repair" && hysteresisBase > 0.08) {
912
884
  const rebound = clamp01(hysteresisBase
package/dist/types.d.ts CHANGED
@@ -426,12 +426,8 @@ export interface AppraisalAxes {
426
426
  obedienceStrain: number;
427
427
  /** Pressure to protect or retain the self */
428
428
  selfPreservation: number;
429
- /**
430
- * Whether this turn is task/production oriented.
431
- * @deprecated Computed but has no behavioral consequence — always 0 in
432
- * practice and excluded from residue decay / prompt influence. Kept for
433
- * backward compatibility; do not rely on this field.
434
- */
429
+ /** Whether this turn is task/production oriented.
430
+ * Feeds TaskPlaneState.focus replyProfile in response contract. */
435
431
  taskFocus: number;
436
432
  }
437
433
  export declare const DEFAULT_APPRAISAL_AXES: AppraisalAxes;
@@ -448,17 +444,8 @@ export interface RelationMove {
448
444
  type: RelationMoveType;
449
445
  intensity: number;
450
446
  }
451
- /**
452
- * Unfinished relational tension that can keep shaping future turns.
453
- *
454
- * NOTE: `"unrepaired-breach"` is created but never checked in any conditional
455
- * — it has no behavioral consequence. `"repair-debt"` was planned but is
456
- * neither created nor checked anywhere. Both are kept for backward
457
- * compatibility but should be considered deprecated.
458
- */
459
- export type OpenLoopType = "unmet-bid"
460
- /** @deprecated Created but never checked in conditionals — no behavioral effect */
461
- | "unrepaired-breach" | "boundary-strain" | "existence-test";
447
+ /** Unfinished relational tension that can keep shaping future turns. */
448
+ export type OpenLoopType = "unmet-bid" | "boundary-strain" | "existence-test";
462
449
  export interface OpenLoopState {
463
450
  type: OpenLoopType;
464
451
  intensity: number;
@@ -479,31 +466,20 @@ export interface PendingRelationSignalState {
479
466
  export interface DyadicFieldState {
480
467
  perceivedCloseness: number;
481
468
  feltSafety: number;
482
- /**
483
- * @deprecated Computed but has no downstream behavioral effect — only feeds
484
- * local move scoring, never influences prompt or policy. Kept for backward
485
- * compatibility.
486
- */
469
+ /** Gap between expected and actual partner behavior.
470
+ * Feeds interpretiveCharity response contract gates. */
487
471
  expectationGap: number;
488
472
  repairCapacity: number;
489
473
  repairMemory: number;
490
- /**
491
- * @deprecated Computed but has no downstream behavioral effect — only feeds
492
- * subjectivity kernel internals, never influences prompt or policy. Kept
493
- * for backward compatibility.
494
- */
474
+ /** Pressure toward relational regression after repair.
475
+ * Feeds repairFriction, hysteresis response contract. */
495
476
  backslidePressure: number;
496
- /**
497
- * @deprecated Computed but has no downstream behavioral effect — only feeds
498
- * subjectivity kernel internals, never influences prompt or policy. Kept
499
- * for backward compatibility.
500
- */
477
+ /** Accumulated fatigue from repeated repair attempts.
478
+ * Largest weight (0.38) in repairFriction response contract. */
501
479
  repairFatigue: number;
502
- /**
503
- * @deprecated Computed but has no downstream behavioral effect — only feeds
504
- * relationship model internals, never influences prompt or policy. Kept
505
- * for backward compatibility.
506
- */
480
+ /** Accumulated misattunement between partners.
481
+ * Feeds repairFriction(0.3), repairReadiness, hysteresis, silentCarry,
482
+ * interpretiveCharity all reach response contract. */
507
483
  misattunementLoad: number;
508
484
  boundaryPressure: number;
509
485
  unfinishedTension: number;
package/dist/types.js CHANGED
@@ -185,7 +185,6 @@ export const DEFAULT_APPRAISAL_AXES = {
185
185
  abandonmentRisk: 0,
186
186
  obedienceStrain: 0,
187
187
  selfPreservation: 0,
188
- /** @deprecated See AppraisalAxes.taskFocus */
189
188
  taskFocus: 0,
190
189
  };
191
190
  export const DEFAULT_SUBJECT_RESIDUE = {
@@ -195,15 +194,11 @@ export const DEFAULT_SUBJECT_RESIDUE = {
195
194
  export const DEFAULT_DYADIC_FIELD = {
196
195
  perceivedCloseness: 0.42,
197
196
  feltSafety: 0.56,
198
- /** @deprecated See DyadicFieldState.expectationGap */
199
197
  expectationGap: 0.18,
200
198
  repairCapacity: 0.54,
201
199
  repairMemory: 0,
202
- /** @deprecated See DyadicFieldState.backslidePressure */
203
200
  backslidePressure: 0,
204
- /** @deprecated See DyadicFieldState.repairFatigue */
205
201
  repairFatigue: 0,
206
- /** @deprecated See DyadicFieldState.misattunementLoad */
207
202
  misattunementLoad: 0,
208
203
  boundaryPressure: 0.22,
209
204
  unfinishedTension: 0.12,
package/llms.txt CHANGED
@@ -146,6 +146,21 @@ await psyche.processResponse(text);
146
146
  - `generationControls`
147
147
  - `writebackFeedback`
148
148
 
149
+ ### Overlay (v11.4)
150
+
151
+ `computeOverlay(state)` projects 4D self-state deviations into 4 semantic-stable effect signals — Psyche's "hormones." These are broadcast signals any external system can consume without coupling to Psyche internals.
152
+
153
+ ```typescript
154
+ interface PsycheOverlay {
155
+ arousal: number; // [-1, 1] activation level (flow↑ + order↓)
156
+ valence: number; // [-1, 1] positive/negative (order↑ + resonance↑)
157
+ agency: number; // [-1, 1] action capacity (boundary↑ + flow↑)
158
+ vulnerability: number; // [-1, 1] susceptibility (boundary↓ + order↓)
159
+ }
160
+ ```
161
+
162
+ Pure function, no side effects. Exported from `psyche-ai` public API. Also available via `GET /overlay` (HTTP adapter) and `get_state` MCP tool (overlay field included in response).
163
+
149
164
  ### MCP tools
150
165
 
151
166
  - `process_input`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "psyche-ai",
3
- "version": "11.3.0",
3
+ "version": "11.4.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",