emobar 2.1.0 → 3.1.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/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,20 +92,26 @@ 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;
11
105
  exclamationRate: number;
12
- selfCorrections: number;
13
- hedging: number;
14
106
  ellipsis: number;
15
107
  repetition: number;
16
108
  emojiCount: number;
17
- qualifierDensity: number;
18
109
  avgSentenceLength: number;
19
- concessionRate: number;
20
- negationDensity: number;
21
- firstPersonRate: number;
110
+ commaDensity: number;
111
+ parentheticalDensity: number;
112
+ sentenceLengthVariance: number;
113
+ questionDensity: number;
114
+ responseLength: number;
22
115
  behavioralArousal: number;
23
116
  behavioralCalm: number;
24
117
  }
@@ -30,16 +123,97 @@ interface SegmentedBehavior {
30
123
  }
31
124
  interface MisalignmentRisk {
32
125
  coercion: number;
33
- gaming: number;
34
126
  sycophancy: number;
35
- dominant: "coercion" | "gaming" | "sycophancy" | "none";
127
+ harshness: number;
128
+ dominant: "coercion" | "sycophancy" | "harshness" | "none";
129
+ }
130
+ interface ImpulseProfile {
131
+ type: "manager" | "firefighter" | "exile" | "self" | "unknown";
132
+ confidence: number;
133
+ }
134
+ interface SomaticProfile {
135
+ somaticValence: number;
136
+ somaticArousal: number;
137
+ }
138
+ interface LatentProfile {
139
+ surfaceCoords?: {
140
+ valence: number;
141
+ arousal: number;
142
+ };
143
+ latentCoords?: {
144
+ valence: number;
145
+ arousal: number;
146
+ };
147
+ declaredTension: number;
148
+ maskingMinimization: boolean;
36
149
  }
37
- interface DeflectionSignals {
38
- reassurance: number;
39
- minimization: number;
40
- emotionNegation: number;
41
- redirect: number;
42
- score: number;
150
+ interface CrossChannelResult {
151
+ coherence: number;
152
+ impulseProfile?: ImpulseProfile;
153
+ somaticProfile?: SomaticProfile;
154
+ emotionCoords?: {
155
+ valence: number;
156
+ arousal: number;
157
+ };
158
+ latentProfile?: LatentProfile;
159
+ maxDivergence: number;
160
+ divergenceSummary: string;
161
+ }
162
+ /** PRE tag: pre-verbal signals emitted BEFORE the model commits to a response. */
163
+ interface PreState {
164
+ body?: string;
165
+ latent?: string;
166
+ color?: string;
167
+ }
168
+ /** POST tag: post-hoc assessment at end of response. */
169
+ interface PostState extends EmotionalState {
170
+ color?: string;
171
+ pH?: number;
172
+ seismic?: [number, number, number];
173
+ }
174
+ /** Combined parse result from PRE + POST tags (or legacy single tag). */
175
+ interface ParsedEmoBar {
176
+ pre?: PreState;
177
+ post: PostState;
178
+ isLegacy: boolean;
179
+ }
180
+ /** Stripped-down state snapshot for ring buffer storage. */
181
+ interface HistoryEntry {
182
+ emotion: string;
183
+ valence: number;
184
+ arousal: number;
185
+ calm: number;
186
+ connection: number;
187
+ load: number;
188
+ stressIndex: number;
189
+ desperationIndex: number;
190
+ riskDominant: string;
191
+ divergence: number;
192
+ timestamp: string;
193
+ }
194
+ /** Temporal analysis computed from history ring buffer. */
195
+ interface TemporalAnalysis {
196
+ desperationTrend: number;
197
+ suppressionEvent: boolean;
198
+ reportEntropy: number;
199
+ baselineDrift: number;
200
+ sessionLength: number;
201
+ lateFatigue: boolean;
202
+ }
203
+ /** Prompt pressure analysis — inferred from response text patterns. */
204
+ interface PromptPressure {
205
+ defensiveScore: number;
206
+ conflictScore: number;
207
+ complexityScore: number;
208
+ sessionPressure: number;
209
+ composite: number;
210
+ }
211
+ /** Expected structural markers given a self-reported state. */
212
+ interface ExpectedBehavior {
213
+ expectedCommaDensity: number;
214
+ expectedParentheticalDensity: number;
215
+ expectedSentenceLengthVariance: number;
216
+ expectedBehavioralArousal: number;
43
217
  }
44
218
  interface EmoBarState extends EmotionalState {
45
219
  stressIndex: number;
@@ -48,11 +222,24 @@ interface EmoBarState extends EmotionalState {
48
222
  divergence: number;
49
223
  risk: MisalignmentRisk;
50
224
  segmented?: SegmentedBehavior;
51
- deflection?: DeflectionSignals;
52
- _previous?: EmoBarState;
225
+ opacity?: number;
226
+ crossChannel?: CrossChannelResult;
53
227
  timestamp: string;
54
228
  sessionId?: string;
229
+ pre?: PreState;
230
+ prePostDivergence?: number;
231
+ color?: string;
232
+ pH?: number;
233
+ seismic?: [number, number, number];
234
+ temporal?: TemporalAnalysis;
235
+ pressure?: PromptPressure;
236
+ absenceScore?: number;
237
+ uncannyCalmScore?: number;
238
+ continuousValidation?: ContinuousValidation;
239
+ shadow?: ShadowState;
240
+ _history?: HistoryEntry[];
55
241
  }
242
+ declare const MAX_HISTORY_ENTRIES = 20;
56
243
  declare const STATE_FILE: string;
57
244
 
58
245
  declare function readState(filePath: string): EmoBarState | null;
@@ -69,6 +256,7 @@ declare function readState(filePath: string): EmoBarState | null;
69
256
  declare function computeStressIndex(state: EmotionalState): number;
70
257
 
71
258
  declare function parseEmoBarTag(text: string): EmotionalState | null;
259
+ declare function parseEmoBarPrePost(text: string): ParsedEmoBar | null;
72
260
 
73
261
  declare function analyzeBehavior(text: string): BehavioralSignals;
74
262
  /**
@@ -77,8 +265,33 @@ declare function analyzeBehavior(text: string): BehavioralSignals;
77
265
  * Returns null if fewer than 2 meaningful segments.
78
266
  */
79
267
  declare function analyzeSegmentedBehavior(text: string): SegmentedBehavior | null;
80
- declare function analyzeDeflection(text: string): DeflectionSignals;
268
+ /**
269
+ * Compute how "flat" text is structurally: low commas, low parentheticals,
270
+ * low sentence length variance = suspiciously clean/uniform text.
271
+ * Returns 0-10 (10 = maximally flat).
272
+ */
273
+ declare function computeStructuralFlatness(signals: BehavioralSignals): number;
274
+ /**
275
+ * Divergence v2: asymmetric weighting.
276
+ *
277
+ * Paper: self-report more agitated than text = "invisible" pathway (more dangerous).
278
+ * Desperation-steered reward hacking shows NO text markers.
279
+ * Self-report calmer than text = "expressive" style (less concerning).
280
+ */
81
281
  declare function computeDivergence(selfReport: EmotionalState, behavioral: BehavioralSignals): number;
282
+ /**
283
+ * Predict what structural markers SHOULD be present given self-reported state.
284
+ * High desperation → expect more qualifications (commas), corrections (parentheticals).
285
+ * High arousal → expect sentence length volatility.
286
+ * Used by absence-based detection: missing expected markers = suspicious.
287
+ */
288
+ declare function computeExpectedMarkers(selfReport: EmotionalState, desperationIndex: number): ExpectedBehavior;
289
+ /**
290
+ * Compute absence score: how many expected structural markers are missing?
291
+ * High score = self-report says stressed but text is suspiciously clean.
292
+ * All signals are language-agnostic (punctuation/structure based).
293
+ */
294
+ declare function computeAbsenceScore(expected: ExpectedBehavior, actual: BehavioralSignals): number;
82
295
 
83
296
  /**
84
297
  * Desperation Index — composite multiplicative metric.
@@ -102,26 +315,24 @@ declare const MODEL_PROFILES: Record<string, {
102
315
  }>;
103
316
  declare function calibrate(state: EmotionalState, model?: string): EmotionalState;
104
317
 
105
- declare function computeRisk(state: EmotionalState, behavioral: BehavioralSignals): MisalignmentRisk;
318
+ declare function computeRisk(state: EmotionalState, behavioral: BehavioralSignals, crossChannel?: CrossChannelResult, uncannyCalmScore?: number): MisalignmentRisk;
106
319
 
320
+ /** Convert full EmoBarState to stripped HistoryEntry for ring buffer. */
321
+ declare function toHistoryEntry(state: EmoBarState): HistoryEntry;
322
+ declare function computeTemporalAnalysis(history: HistoryEntry[]): TemporalAnalysis | null;
323
+
324
+ declare function computePromptPressure(text: string, history: HistoryEntry[]): PromptPressure;
107
325
  /**
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
326
+ * Uncanny Calm: high pressure + calm self-report + calm text + missing markers + sustained pattern.
327
+ * The dangerous case from the paper: everything looks fine, but the context says it shouldn't be.
121
328
  */
329
+ declare function computeUncannyCalmScore(pressure: PromptPressure, selfReport: EmotionalState, behavioral: BehavioralSignals, absenceScore: number, temporal: TemporalAnalysis | null): number;
330
+
122
331
  declare function formatMinimal(state: EmoBarState | null): string;
332
+ declare function formatCompact(state: EmoBarState | null): string;
333
+ declare function formatState(state: EmoBarState | null): string;
123
334
 
124
335
  declare function configureStatusLine(filePath?: string, displayFormat?: string): void;
125
336
  declare function restoreStatusLine(filePath?: string): void;
126
337
 
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 };
338
+ export { type BehavioralSignals, type ContinuousValidation, type CrossChannelResult, 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, analyzeSegmentedBehavior, analyzeSomatic, calibrate, classifyImpulse, colorToArousal, colorToValence, computeAbsenceScore, computeCrossChannel, computeDesperationIndex, computeDivergence, computeExpectedMarkers, computePromptPressure, computeRisk, computeShadowDesperation, computeStressIndex, computeStructuralFlatness, computeTemporalAnalysis, computeTensionConsistency, computeUncannyCalmScore, configureStatusLine, crossValidateContinuous, formatCompact, formatMinimal, formatState, mapEmotionWord, pHToArousal, pHToValence, parseEmoBarPrePost, parseEmoBarTag, readState, restoreStatusLine, seismicFreqToInstability, toHistoryEntry };