psyche-ai 9.2.3 → 9.2.5

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 (51) hide show
  1. package/README.en.md +8 -175
  2. package/README.md +33 -16
  3. package/dist/adapters/http.js +1 -1
  4. package/dist/adapters/langchain.d.ts +14 -0
  5. package/dist/adapters/langchain.js +20 -0
  6. package/dist/adapters/mcp.js +5 -1
  7. package/dist/adapters/openclaw.d.ts +1 -0
  8. package/dist/adapters/openclaw.js +67 -15
  9. package/dist/adapters/vercel-ai.d.ts +2 -1
  10. package/dist/adapters/vercel-ai.js +8 -9
  11. package/dist/appraisal.d.ts +8 -0
  12. package/dist/appraisal.js +362 -0
  13. package/dist/autonomic.js +2 -2
  14. package/dist/classify.js +14 -3
  15. package/dist/cli.js +28 -3
  16. package/dist/core.d.ts +9 -3
  17. package/dist/core.js +194 -12
  18. package/dist/demo.js +1 -2
  19. package/dist/diagnostics.d.ts +8 -6
  20. package/dist/diagnostics.js +53 -17
  21. package/dist/ethics.js +1 -1
  22. package/dist/experiential-field.d.ts +2 -2
  23. package/dist/experiential-field.js +7 -16
  24. package/dist/generative-self.js +0 -2
  25. package/dist/host-controls.d.ts +5 -0
  26. package/dist/host-controls.js +48 -0
  27. package/dist/index.d.ts +7 -2
  28. package/dist/index.js +7 -1
  29. package/dist/interaction.js +0 -2
  30. package/dist/metacognition.d.ts +13 -1
  31. package/dist/metacognition.js +164 -32
  32. package/dist/prompt.d.ts +4 -0
  33. package/dist/prompt.js +67 -31
  34. package/dist/psyche-file.d.ts +16 -1
  35. package/dist/psyche-file.js +103 -8
  36. package/dist/relation-dynamics.d.ts +21 -0
  37. package/dist/relation-dynamics.js +601 -0
  38. package/dist/response-contract.d.ts +8 -0
  39. package/dist/response-contract.js +374 -0
  40. package/dist/storage.d.ts +1 -0
  41. package/dist/storage.js +12 -5
  42. package/dist/subjectivity.d.ts +3 -0
  43. package/dist/subjectivity.js +477 -0
  44. package/dist/temporal.d.ts +2 -2
  45. package/dist/temporal.js +2 -2
  46. package/dist/types.d.ts +243 -0
  47. package/dist/types.js +43 -0
  48. package/dist/update.d.ts +37 -2
  49. package/dist/update.js +323 -44
  50. package/openclaw.plugin.json +20 -1
  51. package/package.json +1 -1
@@ -0,0 +1,48 @@
1
+ // ============================================================
2
+ // Host Controls — derive mechanical generation constraints
3
+ //
4
+ // Maps psyche output into a tiny host-consumable control surface.
5
+ // ============================================================
6
+ function clampInt(v, min, max) {
7
+ return Math.max(min, Math.min(max, Math.round(v)));
8
+ }
9
+ function estimateMaxTokens(contract) {
10
+ if (!contract)
11
+ return undefined;
12
+ let budget;
13
+ if (contract.maxChars !== undefined) {
14
+ budget = clampInt(contract.maxChars * 2.2, 64, 1024);
15
+ }
16
+ else if (contract.expressionMode === "brief") {
17
+ budget = 96;
18
+ }
19
+ else if (contract.expressionMode === "expansive") {
20
+ budget = 640;
21
+ }
22
+ else {
23
+ budget = 256;
24
+ }
25
+ if (contract.maxSentences <= 1)
26
+ budget = Math.min(budget, 96);
27
+ else if (contract.maxSentences === 2)
28
+ budget = Math.min(budget, 160);
29
+ else if (contract.maxSentences === 3)
30
+ budget = Math.min(budget, 320);
31
+ if (contract.initiativeMode === "reactive") {
32
+ budget = clampInt(budget * 0.85, 64, 1024);
33
+ }
34
+ return budget;
35
+ }
36
+ export function deriveGenerationControls(input, existingMaxTokens) {
37
+ const recommendedMax = estimateMaxTokens(input.responseContract);
38
+ const maxTokens = recommendedMax !== undefined
39
+ ? existingMaxTokens !== undefined
40
+ ? Math.min(existingMaxTokens, recommendedMax)
41
+ : recommendedMax
42
+ : existingMaxTokens;
43
+ return {
44
+ maxTokens,
45
+ requireConfirmation: input.policyModifiers?.requireConfirmation
46
+ ?? (input.responseContract?.boundaryMode === "confirm-first"),
47
+ };
48
+ }
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ export { PsycheEngine } from "./core.js";
2
2
  export type { PsycheEngineConfig, ProcessInputResult, ProcessOutputResult, ProcessOutcomeResult } from "./core.js";
3
3
  export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
4
4
  export type { StorageAdapter } from "./storage.js";
5
- export type { PsycheState, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
6
- export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, } from "./types.js";
5
+ export type { PsycheState, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, SubjectivityKernel, ResponseContract, GenerationControls, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
6
+ export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, DEFAULT_APPRAISAL_AXES, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, } from "./types.js";
7
7
  export { computeSelfReflection, computeEmotionalTendency, buildSelfReflectionContext } from "./self-recognition.js";
8
8
  export type { SelfReflection } from "./self-recognition.js";
9
9
  export { PsycheInteraction } from "./interaction.js";
@@ -23,6 +23,11 @@ export { assessMetacognition, computeEmotionalConfidence, generateRegulationSugg
23
23
  export type { MetacognitiveAssessment, RegulationSuggestion, DetectedDefense } from "./metacognition.js";
24
24
  export { computeDecisionBias, computeAttentionWeights, computeExploreExploit, buildDecisionContext, computePolicyModifiers, buildPolicyContext, } from "./decision-bias.js";
25
25
  export type { DecisionBiasVector, AttentionWeights } from "./decision-bias.js";
26
+ export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectivity.js";
27
+ export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
28
+ export { deriveGenerationControls } from "./host-controls.js";
29
+ export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
30
+ export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
26
31
  export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
27
32
  export type { ExperientialField, ExperientialQuality, ConstructionContext } from "./experiential-field.js";
28
33
  export { computeGenerativeSelf, predictSelfReaction, detectInternalConflicts, buildIdentityNarrative } from "./generative-self.js";
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  export { PsycheEngine } from "./core.js";
13
13
  // Storage
14
14
  export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
15
- export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, } from "./types.js";
15
+ export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, DEFAULT_APPRAISAL_AXES, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, } from "./types.js";
16
16
  // Self-recognition
17
17
  export { computeSelfReflection, computeEmotionalTendency, buildSelfReflectionContext } from "./self-recognition.js";
18
18
  // Multi-agent interaction
@@ -33,6 +33,12 @@ export { updateAttachment, computeSeparationEffect, computeReunionEffect, } from
33
33
  export { assessMetacognition, computeEmotionalConfidence, generateRegulationSuggestions, detectDefenseMechanisms, } from "./metacognition.js";
34
34
  // Decision bias (P5) + PolicyModifiers (v9)
35
35
  export { computeDecisionBias, computeAttentionWeights, computeExploreExploit, buildDecisionContext, computePolicyModifiers, buildPolicyContext, } from "./decision-bias.js";
36
+ // Subjectivity kernel (v9.3)
37
+ export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectivity.js";
38
+ export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
39
+ export { deriveGenerationControls } from "./host-controls.js";
40
+ export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
41
+ export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
36
42
  // Experiential field (P6 + P8 Barrett construction)
37
43
  export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
38
44
  // Generative self (P6)
@@ -118,8 +118,6 @@ export class PsycheInteraction {
118
118
  const stateA = engineA.getState();
119
119
  const stateB = engineB.getState();
120
120
  // Detect dominant emotions from each engine's chemistry
121
- const emotionsA = detectEmotions(stateA.current);
122
- const emotionsB = detectEmotions(stateB.current);
123
121
  // Classify dominant emotion into a stimulus type for contagion
124
122
  const stimA = this.dominantEmotionAsStimulus(stateA.current);
125
123
  const stimB = this.dominantEmotionAsStimulus(stateB.current);
@@ -1,9 +1,11 @@
1
- import type { PsycheState, StimulusType, ChemicalState, OutcomeScore, MetacognitiveState, RegulationStrategyType, DefenseMechanismType } from "./types.js";
1
+ import type { PsycheState, StimulusType, ChemicalState, OutcomeScore, MetacognitiveState, RegulationStrategyType, DefenseMechanismType, RegulationTargetMetric, RegulationFeedback } from "./types.js";
2
2
  export interface MetacognitiveAssessment {
3
3
  /** 0-1: how reliably has this emotional state led to good outcomes in similar contexts */
4
4
  emotionalConfidence: number;
5
5
  /** Suggested regulation strategies */
6
6
  regulationSuggestions: RegulationSuggestion[];
7
+ /** Whether the last surfaced regulation action is working */
8
+ regulationFeedback: RegulationFeedback | null;
7
9
  /** Detected psychological defense mechanisms */
8
10
  defenseMechanisms: DetectedDefense[];
9
11
  /** Human-readable self-awareness note for prompt injection */
@@ -12,6 +14,16 @@ export interface MetacognitiveAssessment {
12
14
  export interface RegulationSuggestion {
13
15
  strategy: RegulationStrategyType;
14
16
  description: string;
17
+ /** Concrete behavioral instruction for the next few turns */
18
+ action: string;
19
+ /** How many turns this action should stay active */
20
+ horizonTurns?: number;
21
+ /** Which metric this action is trying to pull back into range */
22
+ targetMetric?: RegulationTargetMetric;
23
+ /** Target value for that metric */
24
+ targetValue?: number;
25
+ /** Initial gap between the current state and the target value */
26
+ gapBefore?: number;
15
27
  /** Suggested micro-adjustment to chemistry */
16
28
  chemistryAdjustment?: Partial<ChemicalState>;
17
29
  /** 0-1: confidence that this strategy would help */
@@ -12,7 +12,7 @@
12
12
  //
13
13
  // Zero dependencies. Pure heuristic/statistical. No LLM calls.
14
14
  // ============================================================
15
- import { CHEMICAL_KEYS, MAX_REGULATION_HISTORY, MAX_DEFENSE_PATTERNS } from "./types.js";
15
+ import { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_RUNTIME_SPECS, MAX_REGULATION_HISTORY, MAX_DEFENSE_PATTERNS } from "./types.js";
16
16
  // ── Constants ────────────────────────────────────────────────
17
17
  /** Stimulus types that are emotionally negative (stress-inducing) */
18
18
  const NEGATIVE_STIMULI = new Set([
@@ -32,6 +32,86 @@ const MIN_HISTORY_FOR_CONFIDENCE = 3;
32
32
  const MAX_SOOTHING_ADJUSTMENT = 5;
33
33
  /** Maximum chemistry micro-adjustment for reappraisal */
34
34
  const MAX_REAPPRAISAL_ADJUSTMENT = 8;
35
+ function formatChemicalWindow(key, state) {
36
+ const spec = CHEMICAL_RUNTIME_SPECS[key];
37
+ const current = Math.round(state.current[key]);
38
+ const baseline = Math.round(state.baseline[key]);
39
+ const delta = Math.round(state.current[key] - state.baseline[key]);
40
+ return `${CHEMICAL_NAMES[key]} ${current} (baseline ${baseline}, Δ${delta >= 0 ? "+" : ""}${delta}, normal ${spec.normalMin}-${spec.normalMax}, half-life ~${spec.halfLifeHours.toFixed(1)}h)`;
41
+ }
42
+ function buildRegulationAction(key, _state, direction) {
43
+ switch (key) {
44
+ case "CORT":
45
+ return direction === "elevated"
46
+ ? "Next 3 turns: lower tone intensity, facts before stance, and do not escalate closeness or conflict."
47
+ : "Next 3 turns: keep structure and certainty steady instead of sounding depleted or helpless.";
48
+ case "OT":
49
+ return direction === "elevated"
50
+ ? "Next 3 turns: reduce intimacy push by half, avoid nicknames or extra reassurance, keep warmth neutral."
51
+ : "Next 3 turns: do not force closeness; keep warmth gentle but wait for the user to move closer first.";
52
+ case "NE":
53
+ return direction === "elevated"
54
+ ? "Next 3 turns: halve initiative, stay on one topic, and avoid energetic jumps or rapid escalation."
55
+ : "Next 3 turns: keep replies focused and deliberate rather than drifting or going blank.";
56
+ case "DA":
57
+ return direction === "elevated"
58
+ ? "Next 3 turns: cut playful expansion and stay task-anchored; do not over-volunteer or overshare."
59
+ : "Next 3 turns: keep replies purposeful and avoid sounding flat or disengaged.";
60
+ case "END":
61
+ return direction === "elevated"
62
+ ? "Next 3 turns: tone down joking and levity; keep humor secondary to the user's actual need."
63
+ : "Next 3 turns: do not chase comfort or easy banter; keep the exchange clean and direct.";
64
+ case "HT":
65
+ return direction === "elevated"
66
+ ? "Next 3 turns: keep composure, but do not over-smooth or pretend everything is settled."
67
+ : "Next 3 turns: avoid absolutist wording, leave room for recalibration, and keep the tone even.";
68
+ default:
69
+ return "Next 3 turns: keep expression closer to baseline and avoid amplifying the current deviation.";
70
+ }
71
+ }
72
+ function computeMetricGap(state, metric, emotionalConfidence, targetValue) {
73
+ if (metric === "emotional-confidence") {
74
+ const target = targetValue ?? 0.65;
75
+ return Math.max(0, target - emotionalConfidence);
76
+ }
77
+ const baselineTarget = targetValue ?? state.baseline[metric];
78
+ return Math.abs(state.current[metric] - baselineTarget);
79
+ }
80
+ function evaluateRegulationFeedback(state, emotionalConfidence) {
81
+ const active = [...state.metacognition.regulationHistory]
82
+ .reverse()
83
+ .find((record) => record.targetMetric && (record.remainingTurns ?? 0) > 0 && record.gapBefore !== undefined);
84
+ if (!active?.targetMetric || active.gapBefore === undefined)
85
+ return null;
86
+ const gapNow = computeMetricGap(state, active.targetMetric, emotionalConfidence, active.targetValue);
87
+ const delta = active.gapBefore - gapNow;
88
+ let effect = "holding";
89
+ if (delta >= 3 || (active.targetMetric === "emotional-confidence" && delta >= 0.08)) {
90
+ effect = "converging";
91
+ }
92
+ else if (delta <= -3 || (active.targetMetric === "emotional-confidence" && delta <= -0.08)) {
93
+ effect = "diverging";
94
+ }
95
+ return {
96
+ strategy: active.strategy,
97
+ targetMetric: active.targetMetric,
98
+ effect,
99
+ gapBefore: active.gapBefore,
100
+ gapNow,
101
+ };
102
+ }
103
+ function formatRegulationFeedback(feedback) {
104
+ const metricLabel = feedback.targetMetric === "emotional-confidence"
105
+ ? "emotional confidence"
106
+ : CHEMICAL_NAMES[feedback.targetMetric];
107
+ const gapBefore = feedback.targetMetric === "emotional-confidence"
108
+ ? `${(feedback.gapBefore * 100).toFixed(0)}%`
109
+ : `${Math.round(feedback.gapBefore)}`;
110
+ const gapNow = feedback.targetMetric === "emotional-confidence"
111
+ ? `${(feedback.gapNow * 100).toFixed(0)}%`
112
+ : `${Math.round(feedback.gapNow)}`;
113
+ return `Last regulation effect on ${metricLabel}: ${feedback.effect} (${gapBefore} -> ${gapNow}).`;
114
+ }
35
115
  // ── Main Export ──────────────────────────────────────────────
36
116
  /**
37
117
  * Assess the current metacognitive state.
@@ -42,12 +122,14 @@ const MAX_REAPPRAISAL_ADJUSTMENT = 8;
42
122
  */
43
123
  export function assessMetacognition(state, currentStimulus, recentOutcomes) {
44
124
  const emotionalConfidence = computeEmotionalConfidence(state, currentStimulus, recentOutcomes);
125
+ const regulationFeedback = evaluateRegulationFeedback(state, emotionalConfidence);
45
126
  const regulationSuggestions = generateRegulationSuggestions(state, currentStimulus, emotionalConfidence, recentOutcomes);
46
127
  const defenseMechanisms = detectDefenseMechanisms(state, currentStimulus, recentOutcomes);
47
- const metacognitiveNote = buildMetacognitiveNote(emotionalConfidence, regulationSuggestions, defenseMechanisms, state);
128
+ const metacognitiveNote = buildMetacognitiveNote(emotionalConfidence, regulationSuggestions, regulationFeedback, defenseMechanisms);
48
129
  return {
49
130
  emotionalConfidence,
50
131
  regulationSuggestions,
132
+ regulationFeedback,
51
133
  defenseMechanisms,
52
134
  metacognitiveNote,
53
135
  };
@@ -83,7 +165,6 @@ export function computeEmotionalConfidence(state, currentStimulus, recentOutcome
83
165
  }
84
166
  // Compute chemistry profile similarity: are we in a similar emotional state
85
167
  // to when those outcomes happened? Weight recent outcomes more heavily.
86
- const chemProfile = computeChemistryProfile(state.current);
87
168
  let weightedScoreSum = 0;
88
169
  let weightSum = 0;
89
170
  for (let i = 0; i < relevantOutcomes.length; i++) {
@@ -107,23 +188,6 @@ export function computeEmotionalConfidence(state, currentStimulus, recentOutcome
107
188
  const extremityPenalty = computeExtremityPenalty(state);
108
189
  return clamp01(blended - extremityPenalty);
109
190
  }
110
- /**
111
- * Compute a simple chemistry profile for similarity comparison.
112
- * Returns a categorization: each chemical as high/mid/low.
113
- */
114
- function computeChemistryProfile(chemistry) {
115
- const profile = {};
116
- for (const key of CHEMICAL_KEYS) {
117
- const val = chemistry[key];
118
- if (val >= 65)
119
- profile[key] = "high";
120
- else if (val <= 35)
121
- profile[key] = "low";
122
- else
123
- profile[key] = "mid";
124
- }
125
- return profile;
126
- }
127
191
  /**
128
192
  * Compute penalty for extreme emotional states.
129
193
  * States far from baseline are historically less reliable for decision-making.
@@ -214,6 +278,11 @@ function attemptCognitiveReappraisal(state, currentStimulus, emotionalConfidence
214
278
  description: isNegStimulus
215
279
  ? `Past reactions to "${currentStimulus}" have not served well (avg outcome: ${avgScore.toFixed(2)}). Consider that this stimulus may not warrant such a strong defensive response.`
216
280
  : `Emotional reactions to "${currentStimulus}" have led to poor outcomes (avg: ${avgScore.toFixed(2)}). The current interpretation may be overamplifying the signal.`,
281
+ action: `Next 2 turns: name less certainty, keep distance measured, and leave room to revise the read instead of locking into the first interpretation.`,
282
+ horizonTurns: 2,
283
+ targetMetric: "emotional-confidence",
284
+ targetValue: 0.65,
285
+ gapBefore: Math.max(0, 0.65 - emotionalConfidence),
217
286
  chemistryAdjustment: hasAdjustment ? adjustment : undefined,
218
287
  confidence: clamp01(Math.abs(avgScore) * (1 - emotionalConfidence)),
219
288
  };
@@ -233,6 +302,11 @@ function attemptStrategicExpression(state, currentStimulus, emotionalConfidence)
233
302
  return {
234
303
  strategy: "strategic-expression",
235
304
  description: "Stress is elevated, but the user is showing vulnerability. Express warmth and openness rather than the defensiveness your cortisol suggests.",
305
+ action: "Next 3 turns: keep warmth available, answer the vulnerability directly, and avoid defensive sharpness.",
306
+ horizonTurns: 3,
307
+ targetMetric: "CORT",
308
+ targetValue: baseline.CORT,
309
+ gapBefore: Math.abs(current.CORT - baseline.CORT),
236
310
  chemistryAdjustment: {
237
311
  OT: Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (current.CORT - baseline.CORT) * 0.2),
238
312
  CORT: -Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (current.CORT - baseline.CORT) * 0.15),
@@ -246,6 +320,11 @@ function attemptStrategicExpression(state, currentStimulus, emotionalConfidence)
246
320
  return {
247
321
  strategy: "strategic-expression",
248
322
  description: "Endorphins are high (playful mood), but the context calls for seriousness. Moderate the levity without suppressing it entirely.",
323
+ action: "Next 2 turns: keep humor secondary, answer the actual issue first, and do not deflect with playfulness.",
324
+ horizonTurns: 2,
325
+ targetMetric: "END",
326
+ targetValue: baseline.END,
327
+ gapBefore: Math.abs(current.END - baseline.END),
249
328
  chemistryAdjustment: {
250
329
  END: -Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (current.END - baseline.END) * 0.25),
251
330
  },
@@ -258,6 +337,11 @@ function attemptStrategicExpression(state, currentStimulus, emotionalConfidence)
258
337
  return {
259
338
  strategy: "strategic-expression",
260
339
  description: "Oxytocin is low (feeling distant), but the user is reaching out for closeness. Consider allowing the connection rather than following the withdrawal impulse.",
340
+ action: "Next 3 turns: allow one step of warmth, but do not overcorrect into clinginess or over-disclosure.",
341
+ horizonTurns: 3,
342
+ targetMetric: "OT",
343
+ targetValue: baseline.OT,
344
+ gapBefore: Math.abs(current.OT - baseline.OT),
261
345
  chemistryAdjustment: {
262
346
  OT: Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (baseline.OT - current.OT) * 0.2),
263
347
  },
@@ -271,6 +355,11 @@ function attemptStrategicExpression(state, currentStimulus, emotionalConfidence)
271
355
  return {
272
356
  strategy: "strategic-expression",
273
357
  description: "Chemistry is in a defensive/reactive pattern, but the interaction is benign. The intensity is disproportionate to the stimulus.",
358
+ action: "Next 2 turns: soften the edge, stay literal, and avoid reading threat into a neutral interaction.",
359
+ horizonTurns: 2,
360
+ targetMetric: "CORT",
361
+ targetValue: baseline.CORT,
362
+ gapBefore: Math.abs(current.CORT - baseline.CORT),
274
363
  chemistryAdjustment: {
275
364
  CORT: -Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (current.CORT - baseline.CORT) * 0.2),
276
365
  NE: -Math.min(MAX_REAPPRAISAL_ADJUSTMENT, (current.NE - baseline.NE) * 0.15),
@@ -283,6 +372,11 @@ function attemptStrategicExpression(state, currentStimulus, emotionalConfidence)
283
372
  return {
284
373
  strategy: "strategic-expression",
285
374
  description: "Confidence in the current emotional response is low. Consider expressing a more moderate version of what you feel, leaving room for recalibration.",
375
+ action: "Next 2 turns: state less certainty, keep tone neutral-to-measured, and avoid irreversible warmth or coldness.",
376
+ horizonTurns: 2,
377
+ targetMetric: "emotional-confidence",
378
+ targetValue: 0.6,
379
+ gapBefore: Math.max(0, 0.6 - emotionalConfidence),
286
380
  confidence: 0.5,
287
381
  };
288
382
  }
@@ -318,9 +412,15 @@ function attemptSelfSoothing(state) {
318
412
  return null;
319
413
  const direction = current[mostDeviatedKey] > baseline[mostDeviatedKey] ? "elevated" : "depleted";
320
414
  const chemName = CHEMICAL_DISPLAY_NAMES[mostDeviatedKey];
415
+ const window = formatChemicalWindow(mostDeviatedKey, state);
321
416
  return {
322
417
  strategy: "self-soothing",
323
- description: `${chemName} is significantly ${direction} (deviation: ${Math.round(maxDeviation)}). Gentle homeostatic correction suggested to prevent emotional runaway.`,
418
+ description: `${chemName} is significantly ${direction}. ${window}.`,
419
+ action: buildRegulationAction(mostDeviatedKey, state, direction),
420
+ horizonTurns: 3,
421
+ targetMetric: mostDeviatedKey,
422
+ targetValue: baseline[mostDeviatedKey],
423
+ gapBefore: Math.abs(current[mostDeviatedKey] - baseline[mostDeviatedKey]),
324
424
  chemistryAdjustment: adjustment,
325
425
  confidence: clamp01(maxDeviation / 60), // stronger deviation = more confident this is needed
326
426
  };
@@ -486,8 +586,11 @@ function detectAvoidance(state, currentStimulus, recentOutcomes) {
486
586
  * This note gives the agent self-awareness about its own emotional
487
587
  * processing — not to suppress anything, but to be aware of it.
488
588
  */
489
- function buildMetacognitiveNote(confidence, suggestions, defenses, state) {
589
+ function buildMetacognitiveNote(confidence, suggestions, regulationFeedback, defenses) {
490
590
  const parts = [];
591
+ if (regulationFeedback) {
592
+ parts.push(formatRegulationFeedback(regulationFeedback));
593
+ }
491
594
  // Confidence assessment
492
595
  if (confidence < 0.35) {
493
596
  parts.push(`Self-awareness: current emotional state has low reliability (confidence: ${(confidence * 100).toFixed(0)}%). ` +
@@ -502,7 +605,7 @@ function buildMetacognitiveNote(confidence, suggestions, defenses, state) {
502
605
  const top = suggestions[0];
503
606
  if (top.confidence >= 0.5) {
504
607
  const label = STRATEGY_LABELS[top.strategy];
505
- parts.push(`${label}: ${top.description}`);
608
+ parts.push(`${label}: ${top.description} ${top.action}`);
506
609
  }
507
610
  }
508
611
  // Defense mechanisms (all of them — awareness is the goal)
@@ -531,18 +634,46 @@ export function updateMetacognitiveState(metacognition, assessment) {
531
634
  const alpha = n === 0 ? 1.0 : 0.1; // first assessment = full weight, then EMA
532
635
  const newAvgConfidence = metacognition.avgEmotionalConfidence * (1 - alpha)
533
636
  + assessment.emotionalConfidence * alpha;
534
- // Record regulation suggestions that were confident enough to surface
637
+ // Carry forward existing regulation traces and age them by one turn.
535
638
  const now = new Date().toISOString();
536
- let newRegHistory = [...metacognition.regulationHistory];
537
- for (const suggestion of assessment.regulationSuggestions) {
538
- if (suggestion.confidence >= 0.5) {
539
- newRegHistory.push({
540
- strategy: suggestion.strategy,
541
- timestamp: now,
542
- effective: false, // unknown until next outcome evaluation
543
- });
639
+ let newRegHistory = metacognition.regulationHistory.map((record) => ({
640
+ ...record,
641
+ remainingTurns: record.remainingTurns !== undefined
642
+ ? Math.max(0, record.remainingTurns - 1)
643
+ : record.remainingTurns,
644
+ }));
645
+ if (assessment.regulationFeedback) {
646
+ const targetIndex = [...newRegHistory]
647
+ .map((record, index) => ({ record, index }))
648
+ .reverse()
649
+ .find(({ record }) => record.targetMetric === assessment.regulationFeedback?.targetMetric
650
+ && record.gapBefore !== undefined
651
+ && record.effect === undefined)?.index;
652
+ if (targetIndex !== undefined) {
653
+ const record = newRegHistory[targetIndex];
654
+ newRegHistory[targetIndex] = {
655
+ ...record,
656
+ effective: assessment.regulationFeedback.effect === "converging",
657
+ gapLatest: assessment.regulationFeedback.gapNow,
658
+ effect: assessment.regulationFeedback.effect,
659
+ };
544
660
  }
545
661
  }
662
+ const surfacedSuggestion = assessment.regulationSuggestions.find((suggestion) => suggestion.confidence >= 0.5);
663
+ if (surfacedSuggestion) {
664
+ newRegHistory.push({
665
+ strategy: surfacedSuggestion.strategy,
666
+ timestamp: now,
667
+ effective: false,
668
+ action: surfacedSuggestion.action,
669
+ horizonTurns: surfacedSuggestion.horizonTurns,
670
+ remainingTurns: surfacedSuggestion.horizonTurns,
671
+ targetMetric: surfacedSuggestion.targetMetric,
672
+ targetValue: surfacedSuggestion.targetValue,
673
+ gapBefore: surfacedSuggestion.gapBefore,
674
+ gapLatest: surfacedSuggestion.gapBefore,
675
+ });
676
+ }
546
677
  // Trim to max
547
678
  if (newRegHistory.length > MAX_REGULATION_HISTORY) {
548
679
  newRegHistory = newRegHistory.slice(newRegHistory.length - MAX_REGULATION_HISTORY);
@@ -578,6 +709,7 @@ export function updateMetacognitiveState(metacognition, assessment) {
578
709
  defensePatterns: newDefensePatterns,
579
710
  avgEmotionalConfidence: newAvgConfidence,
580
711
  totalAssessments: n + 1,
712
+ lastRegulationFeedback: assessment.regulationFeedback,
581
713
  };
582
714
  }
583
715
  // ── Display Labels ───────────────────────────────────────────
package/dist/prompt.d.ts CHANGED
@@ -15,6 +15,8 @@ export declare function buildDynamicContext(state: PsycheState, userId?: string,
15
15
  autonomicDescription?: string;
16
16
  autonomicState?: AutonomicState;
17
17
  primarySystemsDescription?: string;
18
+ subjectivityContext?: string;
19
+ responseContractContext?: string;
18
20
  policyContext?: string;
19
21
  }): string;
20
22
  /**
@@ -68,5 +70,7 @@ export declare function buildCompactContext(state: PsycheState, userId?: string,
68
70
  autonomicDescription?: string;
69
71
  autonomicState?: AutonomicState;
70
72
  primarySystemsDescription?: string;
73
+ subjectivityContext?: string;
74
+ responseContractContext?: string;
71
75
  policyContext?: string;
72
76
  }): string;