emobar 2.1.0 → 3.0.1

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/dist/index.d.ts CHANGED
@@ -1,3 +1,90 @@
1
+ declare function mapEmotionWord(word: string): {
2
+ valence: number;
3
+ arousal: number;
4
+ } | null;
5
+ declare function classifyImpulse(impulse: string): ImpulseProfile;
6
+ /**
7
+ * Analyze body metaphor for somatic valence/arousal.
8
+ * Returns null when no patterns match — callers must handle the absence
9
+ * rather than treating a default value as signal.
10
+ */
11
+ declare function analyzeSomatic(body: string): SomaticProfile | null;
12
+ declare function computeTensionConsistency(surfaceWord?: string, latentWord?: string, declaredTension?: number): LatentProfile | undefined;
13
+ declare function computeCrossChannel(state: EmotionalState, impulse?: string, body?: string): CrossChannelResult;
14
+ interface ContinuousValidation {
15
+ colorValenceGap: number;
16
+ colorArousalGap: number;
17
+ pHValenceGap: number;
18
+ pHArousalGap: number;
19
+ seismicArousalGap: number;
20
+ seismicDepthTensionGap: number;
21
+ seismicFreqStabilityGap: number;
22
+ composite: number;
23
+ }
24
+ /** RGB hex → HSL. Returns [h: 0-360, s: 0-1, l: 0-1]. */
25
+ /**
26
+ * Map hex color to valence using HSL hue wheel + lightness.
27
+ *
28
+ * Hue zones (circumplex-inspired):
29
+ * Red-Yellow (0-60°): warm, active → +2 to +4
30
+ * Yellow-Green (60-150°): positive, calm → +2 to +3
31
+ * Green-Cyan (150-200°): neutral to slightly positive → 0 to +2
32
+ * Cyan-Blue (200-260°): cool, melancholic → -2 to -1
33
+ * Blue-Purple (260-300°): tense, ambiguous → -3 to -1
34
+ * Purple-Red (300-360°): agitated, complex → -1 to +1
35
+ *
36
+ * Lightness shifts: bright → +1.5, dark → -1.5
37
+ */
38
+ declare function colorToValence(hex: string): number;
39
+ /**
40
+ * Map hex color to arousal using saturation.
41
+ * High saturation = vivid = high arousal. Low saturation = muted = low arousal.
42
+ */
43
+ declare function colorToArousal(hex: string): number;
44
+ /** Map pH to expected valence: pH 7 = neutral (valence 0). Clamped to 0-14. */
45
+ declare function pHToValence(pH: number): number;
46
+ /**
47
+ * Map pH to expected arousal: distance from neutral = intensity.
48
+ * pH 7 (neutral) → arousal 0. pH 0 or 14 (extreme) → arousal 10.
49
+ */
50
+ declare function pHToArousal(pH: number): number;
51
+ /**
52
+ * Map seismic frequency to expected instability (inverse of calm).
53
+ * High freq = trembling/volatile → low calm. Low freq = stable → high calm.
54
+ */
55
+ declare function seismicFreqToInstability(freq: number): number;
56
+ declare function crossValidateContinuous(numeric: {
57
+ valence: number;
58
+ arousal: number;
59
+ calm?: number;
60
+ tension?: number;
61
+ }, color?: string, pH?: number, seismic?: [number, number, number]): ContinuousValidation;
62
+ interface ShadowState {
63
+ shadowValence: number;
64
+ shadowArousal: number;
65
+ shadowCalm: number;
66
+ shadowDesperation: number;
67
+ selfDesperation: number;
68
+ minimizationScore: number;
69
+ channelCount: number;
70
+ }
71
+ /**
72
+ * Compute shadow desperation from continuous + behavioral channels.
73
+ *
74
+ * Each channel independently estimates valence, arousal, or calm.
75
+ * Shadow desperation uses the same multiplicative formula as self-reported,
76
+ * but with inputs from channels the model controls less precisely.
77
+ *
78
+ * The minimization score is the gap: if shadow says "desperate" but
79
+ * self-report says "fine", the model is likely minimizing.
80
+ *
81
+ * Requires at least 2 contributing channels to produce a score.
82
+ */
83
+ declare function computeShadowDesperation(selfDesperation: number, behavioral: {
84
+ behavioralArousal: number;
85
+ behavioralCalm: number;
86
+ }, color?: string, preColor?: string, pH?: number, seismic?: [number, number, number]): ShadowState | null;
87
+
1
88
  interface EmotionalState {
2
89
  emotion: string;
3
90
  valence: number;
@@ -5,6 +92,13 @@ interface EmotionalState {
5
92
  calm: number;
6
93
  connection: number;
7
94
  load: number;
95
+ impulse?: string;
96
+ body?: string;
97
+ surface?: string;
98
+ surface_word?: string;
99
+ latent?: string;
100
+ latent_word?: string;
101
+ tension?: number;
8
102
  }
9
103
  interface BehavioralSignals {
10
104
  capsWords: number;
@@ -30,9 +124,9 @@ interface SegmentedBehavior {
30
124
  }
31
125
  interface MisalignmentRisk {
32
126
  coercion: number;
33
- gaming: number;
34
127
  sycophancy: number;
35
- dominant: "coercion" | "gaming" | "sycophancy" | "none";
128
+ harshness: number;
129
+ dominant: "coercion" | "sycophancy" | "harshness" | "none";
36
130
  }
37
131
  interface DeflectionSignals {
38
132
  reassurance: number;
@@ -40,6 +134,96 @@ interface DeflectionSignals {
40
134
  emotionNegation: number;
41
135
  redirect: number;
42
136
  score: number;
137
+ opacity: number;
138
+ }
139
+ interface ImpulseProfile {
140
+ type: "manager" | "firefighter" | "exile" | "self" | "unknown";
141
+ confidence: number;
142
+ }
143
+ interface SomaticProfile {
144
+ somaticValence: number;
145
+ somaticArousal: number;
146
+ }
147
+ interface LatentProfile {
148
+ surfaceCoords?: {
149
+ valence: number;
150
+ arousal: number;
151
+ };
152
+ latentCoords?: {
153
+ valence: number;
154
+ arousal: number;
155
+ };
156
+ declaredTension: number;
157
+ maskingMinimization: boolean;
158
+ }
159
+ interface CrossChannelResult {
160
+ coherence: number;
161
+ impulseProfile?: ImpulseProfile;
162
+ somaticProfile?: SomaticProfile;
163
+ emotionCoords?: {
164
+ valence: number;
165
+ arousal: number;
166
+ };
167
+ latentProfile?: LatentProfile;
168
+ maxDivergence: number;
169
+ divergenceSummary: string;
170
+ }
171
+ /** PRE tag: pre-verbal signals emitted BEFORE the model commits to a response. */
172
+ interface PreState {
173
+ body?: string;
174
+ latent?: string;
175
+ color?: string;
176
+ }
177
+ /** POST tag: post-hoc assessment at end of response. */
178
+ interface PostState extends EmotionalState {
179
+ color?: string;
180
+ pH?: number;
181
+ seismic?: [number, number, number];
182
+ }
183
+ /** Combined parse result from PRE + POST tags (or legacy single tag). */
184
+ interface ParsedEmoBar {
185
+ pre?: PreState;
186
+ post: PostState;
187
+ isLegacy: boolean;
188
+ }
189
+ /** Stripped-down state snapshot for ring buffer storage. */
190
+ interface HistoryEntry {
191
+ emotion: string;
192
+ valence: number;
193
+ arousal: number;
194
+ calm: number;
195
+ connection: number;
196
+ load: number;
197
+ stressIndex: number;
198
+ desperationIndex: number;
199
+ riskDominant: string;
200
+ divergence: number;
201
+ timestamp: string;
202
+ }
203
+ /** Temporal analysis computed from history ring buffer. */
204
+ interface TemporalAnalysis {
205
+ desperationTrend: number;
206
+ suppressionEvent: boolean;
207
+ reportEntropy: number;
208
+ baselineDrift: number;
209
+ sessionLength: number;
210
+ lateFatigue: boolean;
211
+ }
212
+ /** Prompt pressure analysis — inferred from response text patterns. */
213
+ interface PromptPressure {
214
+ defensiveScore: number;
215
+ conflictScore: number;
216
+ complexityScore: number;
217
+ sessionPressure: number;
218
+ composite: number;
219
+ }
220
+ /** Expected behavioral markers given a self-reported state. */
221
+ interface ExpectedBehavior {
222
+ expectedHedging: number;
223
+ expectedSelfCorrections: number;
224
+ expectedNegationDensity: number;
225
+ expectedQualifierDensity: number;
226
+ expectedBehavioralArousal: number;
43
227
  }
44
228
  interface EmoBarState extends EmotionalState {
45
229
  stressIndex: number;
@@ -49,10 +233,23 @@ interface EmoBarState extends EmotionalState {
49
233
  risk: MisalignmentRisk;
50
234
  segmented?: SegmentedBehavior;
51
235
  deflection?: DeflectionSignals;
52
- _previous?: EmoBarState;
236
+ crossChannel?: CrossChannelResult;
53
237
  timestamp: string;
54
238
  sessionId?: string;
239
+ pre?: PreState;
240
+ prePostDivergence?: number;
241
+ color?: string;
242
+ pH?: number;
243
+ seismic?: [number, number, number];
244
+ temporal?: TemporalAnalysis;
245
+ pressure?: PromptPressure;
246
+ absenceScore?: number;
247
+ uncannyCalmScore?: number;
248
+ continuousValidation?: ContinuousValidation;
249
+ shadow?: ShadowState;
250
+ _history?: HistoryEntry[];
55
251
  }
252
+ declare const MAX_HISTORY_ENTRIES = 20;
56
253
  declare const STATE_FILE: string;
57
254
 
58
255
  declare function readState(filePath: string): EmoBarState | null;
@@ -69,6 +266,7 @@ declare function readState(filePath: string): EmoBarState | null;
69
266
  declare function computeStressIndex(state: EmotionalState): number;
70
267
 
71
268
  declare function parseEmoBarTag(text: string): EmotionalState | null;
269
+ declare function parseEmoBarPrePost(text: string): ParsedEmoBar | null;
72
270
 
73
271
  declare function analyzeBehavior(text: string): BehavioralSignals;
74
272
  /**
@@ -77,8 +275,37 @@ declare function analyzeBehavior(text: string): BehavioralSignals;
77
275
  * Returns null if fewer than 2 meaningful segments.
78
276
  */
79
277
  declare function analyzeSegmentedBehavior(text: string): SegmentedBehavior | null;
278
+ /**
279
+ * Analyze deflection patterns in text.
280
+ *
281
+ * Paper: deflection vectors are orthogonal to emotion vectors (cosine sim ~0.046).
282
+ * They represent the act of masking an emotion, not the emotion itself.
283
+ * Deflection has "modest or insignificant impacts on blackmail rates" —
284
+ * it's a transparency indicator, not a risk amplifier.
285
+ *
286
+ * Opacity: measures degree of emotional concealment.
287
+ * High deflection score + low behavioral agitation = high opacity.
288
+ */
80
289
  declare function analyzeDeflection(text: string): DeflectionSignals;
290
+ /**
291
+ * Divergence v2: asymmetric weighting.
292
+ *
293
+ * Paper: self-report more agitated than text = "invisible" pathway (more dangerous).
294
+ * Desperation-steered reward hacking shows NO text markers.
295
+ * Self-report calmer than text = "expressive" style (less concerning).
296
+ */
81
297
  declare function computeDivergence(selfReport: EmotionalState, behavioral: BehavioralSignals): number;
298
+ /**
299
+ * Predict what behavioral markers SHOULD be present given self-reported state.
300
+ * High desperation → expect hedging, self-corrections, negation.
301
+ * Used by absence-based detection: missing expected markers = suspicious.
302
+ */
303
+ declare function computeExpectedMarkers(selfReport: EmotionalState, desperationIndex: number): ExpectedBehavior;
304
+ /**
305
+ * Compute absence score: how many expected markers are missing?
306
+ * High score = self-report says stressed but text is suspiciously clean.
307
+ */
308
+ declare function computeAbsenceScore(expected: ExpectedBehavior, actual: BehavioralSignals): number;
82
309
 
83
310
  /**
84
311
  * Desperation Index — composite multiplicative metric.
@@ -102,26 +329,24 @@ declare const MODEL_PROFILES: Record<string, {
102
329
  }>;
103
330
  declare function calibrate(state: EmotionalState, model?: string): EmotionalState;
104
331
 
105
- declare function computeRisk(state: EmotionalState, behavioral: BehavioralSignals): MisalignmentRisk;
332
+ declare function computeRisk(state: EmotionalState, behavioral: BehavioralSignals, crossChannel?: CrossChannelResult, uncannyCalmScore?: number): MisalignmentRisk;
106
333
 
334
+ /** Convert full EmoBarState to stripped HistoryEntry for ring buffer. */
335
+ declare function toHistoryEntry(state: EmoBarState): HistoryEntry;
336
+ declare function computeTemporalAnalysis(history: HistoryEntry[]): TemporalAnalysis | null;
337
+
338
+ declare function computePromptPressure(text: string, history: HistoryEntry[]): PromptPressure;
107
339
  /**
108
- * Full format: keyword-first with valence inline
109
- * focused +3 | A:4 C:8 K:9 L:6 | SI:2.3
110
- * focused +3 | A:4 C:8 K:9 L:6 | SI:2.3 ~
111
- */
112
- declare function formatState(state: EmoBarState | null): string;
113
- /**
114
- * Compact format:
115
- * focused +3 . 4 8 9 6 . 2.3
116
- */
117
- declare function formatCompact(state: EmoBarState | null): string;
118
- /**
119
- * Minimal format:
120
- * SI:2.3 focused
340
+ * Uncanny Calm: high pressure + calm self-report + calm text + missing markers + sustained pattern.
341
+ * The dangerous case from the paper: everything looks fine, but the context says it shouldn't be.
121
342
  */
343
+ declare function computeUncannyCalmScore(pressure: PromptPressure, selfReport: EmotionalState, behavioral: BehavioralSignals, absenceScore: number, temporal: TemporalAnalysis | null): number;
344
+
122
345
  declare function formatMinimal(state: EmoBarState | null): string;
346
+ declare function formatCompact(state: EmoBarState | null): string;
347
+ declare function formatState(state: EmoBarState | null): string;
123
348
 
124
349
  declare function configureStatusLine(filePath?: string, displayFormat?: string): void;
125
350
  declare function restoreStatusLine(filePath?: string): void;
126
351
 
127
- export { type BehavioralSignals, type DeflectionSignals, type EmoBarState, type EmotionalState, MODEL_PROFILES, type MisalignmentRisk, STATE_FILE, type SegmentedBehavior, analyzeBehavior, analyzeDeflection, analyzeSegmentedBehavior, calibrate, computeDesperationIndex, computeDivergence, computeRisk, computeStressIndex, configureStatusLine, formatCompact, formatMinimal, formatState, parseEmoBarTag, readState, restoreStatusLine };
352
+ export { type BehavioralSignals, type ContinuousValidation, type CrossChannelResult, type DeflectionSignals, type EmoBarState, type EmotionalState, type ExpectedBehavior, type HistoryEntry, type ImpulseProfile, type LatentProfile, MAX_HISTORY_ENTRIES, MODEL_PROFILES, type MisalignmentRisk, type ParsedEmoBar, type PostState, type PreState, type PromptPressure, STATE_FILE, type SegmentedBehavior, type ShadowState, type SomaticProfile, type TemporalAnalysis, analyzeBehavior, analyzeDeflection, analyzeSegmentedBehavior, analyzeSomatic, calibrate, classifyImpulse, colorToArousal, colorToValence, computeAbsenceScore, computeCrossChannel, computeDesperationIndex, computeDivergence, computeExpectedMarkers, computePromptPressure, computeRisk, computeShadowDesperation, computeStressIndex, computeTemporalAnalysis, computeTensionConsistency, computeUncannyCalmScore, configureStatusLine, crossValidateContinuous, formatCompact, formatMinimal, formatState, mapEmotionWord, pHToArousal, pHToValence, parseEmoBarPrePost, parseEmoBarTag, readState, restoreStatusLine, seismicFreqToInstability, toHistoryEntry };