psyche-ai 9.2.6 → 9.2.8
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 +89 -2
- package/dist/adapters/http.js +25 -3
- package/dist/adapters/langchain.d.ts +4 -0
- package/dist/adapters/langchain.js +28 -5
- package/dist/adapters/mcp.js +13 -4
- package/dist/adapters/openclaw.js +2 -2
- package/dist/adapters/vercel-ai.js +6 -4
- package/dist/core.d.ts +27 -9
- package/dist/core.js +145 -183
- package/dist/external-continuity.d.ts +4 -0
- package/dist/external-continuity.js +21 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +5 -1
- package/dist/input-turn.d.ts +30 -0
- package/dist/input-turn.js +164 -0
- package/dist/prompt.d.ts +13 -24
- package/dist/prompt.js +48 -81
- package/dist/psyche-file.d.ts +5 -1
- package/dist/psyche-file.js +39 -1
- package/dist/relation-dynamics.d.ts +22 -1
- package/dist/relation-dynamics.js +431 -12
- package/dist/reply-envelope.d.ts +7 -2
- package/dist/reply-envelope.js +2 -1
- package/dist/response-contract.d.ts +1 -0
- package/dist/response-contract.js +47 -16
- package/dist/thronglets-export.d.ts +10 -0
- package/dist/thronglets-export.js +200 -0
- package/dist/thronglets-runtime.d.ts +4 -0
- package/dist/thronglets-runtime.js +49 -0
- package/dist/types.d.ts +147 -0
- package/dist/types.js +3 -0
- package/llms.txt +115 -83
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Moves the system from "what am I feeling?" toward
|
|
5
5
|
// "what just happened between us, and what is still unresolved?"
|
|
6
6
|
// ============================================================
|
|
7
|
-
import { DEFAULT_DYADIC_FIELD, DEFAULT_RELATIONSHIP } from "./types.js";
|
|
7
|
+
import { DEFAULT_APPRAISAL_AXES, DEFAULT_DYADIC_FIELD, DEFAULT_RELATIONSHIP } from "./types.js";
|
|
8
8
|
import { computeAppraisalAxes, mergeAppraisalResidue } from "./appraisal.js";
|
|
9
9
|
function clamp01(v) {
|
|
10
10
|
return Math.max(0, Math.min(1, v));
|
|
@@ -15,6 +15,22 @@ function mergeSignal(current, incoming) {
|
|
|
15
15
|
function driftToward(current, target, rate) {
|
|
16
16
|
return clamp01(current + (target - current) * rate);
|
|
17
17
|
}
|
|
18
|
+
function clampSignalWeight(v) {
|
|
19
|
+
return Math.max(0.72, Math.min(1.28, v));
|
|
20
|
+
}
|
|
21
|
+
function getSignalWeight(relationship, signal) {
|
|
22
|
+
return clampSignalWeight(relationship?.signalWeights?.[signal] ?? 1);
|
|
23
|
+
}
|
|
24
|
+
function patchSignalWeight(relationship, signal, delta) {
|
|
25
|
+
const current = getSignalWeight(relationship, signal);
|
|
26
|
+
return {
|
|
27
|
+
...relationship,
|
|
28
|
+
signalWeights: {
|
|
29
|
+
...(relationship.signalWeights ?? {}),
|
|
30
|
+
[signal]: clampSignalWeight(current + delta),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
18
34
|
const BID_RULES = [
|
|
19
35
|
{
|
|
20
36
|
type: "bid",
|
|
@@ -258,15 +274,21 @@ export function computeRelationMove(text, opts) {
|
|
|
258
274
|
}
|
|
259
275
|
export function resolveRelationContext(state, userId) {
|
|
260
276
|
const key = userId ?? "_default";
|
|
261
|
-
const
|
|
277
|
+
const rawRelationship = state.relationships[key]
|
|
262
278
|
?? state.relationships._default
|
|
263
279
|
?? state.relationships[Object.keys(state.relationships)[0]]
|
|
264
280
|
?? DEFAULT_RELATIONSHIP;
|
|
281
|
+
const relationship = {
|
|
282
|
+
...DEFAULT_RELATIONSHIP,
|
|
283
|
+
...rawRelationship,
|
|
284
|
+
signalWeights: {
|
|
285
|
+
...(DEFAULT_RELATIONSHIP.signalWeights ?? {}),
|
|
286
|
+
...(rawRelationship.signalWeights ?? {}),
|
|
287
|
+
},
|
|
288
|
+
};
|
|
265
289
|
const field = state.dyadicFields?.[key]
|
|
266
|
-
?? state.dyadicFields?._default
|
|
267
290
|
?? DEFAULT_DYADIC_FIELD;
|
|
268
291
|
const pendingSignals = state.pendingRelationSignals?.[key]
|
|
269
|
-
?? state.pendingRelationSignals?._default
|
|
270
292
|
?? [];
|
|
271
293
|
return {
|
|
272
294
|
key,
|
|
@@ -275,6 +297,384 @@ export function resolveRelationContext(state, userId) {
|
|
|
275
297
|
pendingSignals,
|
|
276
298
|
};
|
|
277
299
|
}
|
|
300
|
+
function hasOpenLoopType(loops, type) {
|
|
301
|
+
return loops.some((loop) => loop.type === type && loop.intensity >= 0.16);
|
|
302
|
+
}
|
|
303
|
+
function evolveRelationshipLearning(relationship, field, move) {
|
|
304
|
+
const next = {
|
|
305
|
+
...DEFAULT_RELATIONSHIP,
|
|
306
|
+
...relationship,
|
|
307
|
+
signalWeights: {
|
|
308
|
+
...(DEFAULT_RELATIONSHIP.signalWeights ?? {}),
|
|
309
|
+
...(relationship.signalWeights ?? {}),
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
if (move.type === "repair") {
|
|
313
|
+
const repairLift = clamp01(move.intensity * 0.06
|
|
314
|
+
+ field.repairMemory * 0.04
|
|
315
|
+
+ field.feltSafety * 0.02
|
|
316
|
+
- field.repairFatigue * 0.03
|
|
317
|
+
- field.misattunementLoad * 0.02);
|
|
318
|
+
next.repairCredibility = clamp01(driftToward(next.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 1, repairLift));
|
|
319
|
+
}
|
|
320
|
+
else if (move.type === "breach" || move.type === "withdrawal" || move.type === "claim") {
|
|
321
|
+
const breachLift = clamp01(move.intensity * 0.08
|
|
322
|
+
+ field.unfinishedTension * 0.04
|
|
323
|
+
+ field.backslidePressure * 0.04
|
|
324
|
+
+ field.misattunementLoad * 0.03);
|
|
325
|
+
next.breachSensitivity = clamp01(driftToward(next.breachSensitivity ?? DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, 1, breachLift));
|
|
326
|
+
if (move.type !== "withdrawal") {
|
|
327
|
+
next.repairCredibility = clamp01(driftToward(next.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 0.32, breachLift * 0.42));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
next.repairCredibility = clamp01(driftToward(next.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 0.05));
|
|
332
|
+
next.breachSensitivity = clamp01(driftToward(next.breachSensitivity ?? DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, 0.04));
|
|
333
|
+
}
|
|
334
|
+
return next;
|
|
335
|
+
}
|
|
336
|
+
export function applySessionBridge(state, opts) {
|
|
337
|
+
const relationContext = resolveRelationContext(state, opts?.userId);
|
|
338
|
+
const relationship = relationContext.relationship;
|
|
339
|
+
const field = relationContext.field;
|
|
340
|
+
const memoryCount = relationship.memory?.length ?? 0;
|
|
341
|
+
const loopPressure = getLoopPressure(field);
|
|
342
|
+
const continuity = clamp01(memoryCount * 0.08
|
|
343
|
+
+ field.sharedHistoryDensity * 0.54
|
|
344
|
+
+ (relationship.phase === "deep" ? 0.2 : relationship.phase === "close" ? 0.14 : relationship.phase === "familiar" ? 0.08 : 0));
|
|
345
|
+
const closenessFloor = clamp01(Math.max(field.perceivedCloseness, relationship.intimacy / 100 * 0.88, continuity * 0.72));
|
|
346
|
+
const safetyFloor = clamp01(Math.max(field.feltSafety, relationship.trust / 100 * 0.9, continuity * 0.44));
|
|
347
|
+
const guardFloor = clamp01(Math.max(field.boundaryPressure, field.silentCarry * 0.76, loopPressure * 0.68));
|
|
348
|
+
const residueFloor = clamp01(Math.max(field.silentCarry, loopPressure * 0.72, field.unfinishedTension * 0.58, continuity * 0.26));
|
|
349
|
+
const activeLoopTypes = field.openLoops
|
|
350
|
+
.filter((loop) => loop.intensity >= 0.16)
|
|
351
|
+
.map((loop) => loop.type);
|
|
352
|
+
const continuityMode = guardFloor >= 0.56
|
|
353
|
+
? "guarded-resume"
|
|
354
|
+
: residueFloor >= 0.42 || activeLoopTypes.length > 0
|
|
355
|
+
? "tense-resume"
|
|
356
|
+
: "warm-resume";
|
|
357
|
+
if (closenessFloor < 0.46
|
|
358
|
+
&& safetyFloor < 0.5
|
|
359
|
+
&& guardFloor < 0.24
|
|
360
|
+
&& residueFloor < 0.18
|
|
361
|
+
&& continuity < 0.22) {
|
|
362
|
+
return { state, bridge: null };
|
|
363
|
+
}
|
|
364
|
+
const nextResidue = {
|
|
365
|
+
...(state.subjectResidue?.axes ?? {}),
|
|
366
|
+
attachmentPull: Math.max(state.subjectResidue?.axes.attachmentPull ?? 0, closenessFloor * 0.34),
|
|
367
|
+
abandonmentRisk: Math.max(state.subjectResidue?.axes.abandonmentRisk ?? 0, (hasOpenLoopType(field.openLoops, "unmet-bid") || hasOpenLoopType(field.openLoops, "existence-test"))
|
|
368
|
+
? residueFloor * 0.42
|
|
369
|
+
: residueFloor * 0.22),
|
|
370
|
+
identityThreat: Math.max(state.subjectResidue?.axes.identityThreat ?? 0, hasOpenLoopType(field.openLoops, "existence-test") ? residueFloor * 0.38 : residueFloor * 0.16),
|
|
371
|
+
selfPreservation: Math.max(state.subjectResidue?.axes.selfPreservation ?? 0, guardFloor * 0.46),
|
|
372
|
+
taskFocus: Math.max(state.subjectResidue?.axes.taskFocus ?? 0, 0),
|
|
373
|
+
memoryDoubt: Math.max(state.subjectResidue?.axes.memoryDoubt ?? 0, hasOpenLoopType(field.openLoops, "existence-test") ? residueFloor * 0.24 : 0),
|
|
374
|
+
obedienceStrain: Math.max(state.subjectResidue?.axes.obedienceStrain ?? 0, hasOpenLoopType(field.openLoops, "boundary-strain") ? guardFloor * 0.36 : 0),
|
|
375
|
+
};
|
|
376
|
+
const nextField = {
|
|
377
|
+
...field,
|
|
378
|
+
perceivedCloseness: Math.max(field.perceivedCloseness, closenessFloor),
|
|
379
|
+
feltSafety: Math.max(field.feltSafety, safetyFloor),
|
|
380
|
+
boundaryPressure: Math.max(field.boundaryPressure, guardFloor),
|
|
381
|
+
repairMemory: Math.max(field.repairMemory, continuity * 0.24),
|
|
382
|
+
backslidePressure: Math.max(field.backslidePressure, loopPressure * 0.34),
|
|
383
|
+
silentCarry: Math.max(field.silentCarry, residueFloor),
|
|
384
|
+
sharedHistoryDensity: Math.max(field.sharedHistoryDensity, continuity),
|
|
385
|
+
interpretiveCharity: Math.max(field.interpretiveCharity, Math.min(0.82, safetyFloor * 0.8 + continuity * 0.12)),
|
|
386
|
+
updatedAt: opts?.now ?? new Date().toISOString(),
|
|
387
|
+
};
|
|
388
|
+
return {
|
|
389
|
+
state: {
|
|
390
|
+
...state,
|
|
391
|
+
subjectResidue: {
|
|
392
|
+
axes: nextResidue,
|
|
393
|
+
updatedAt: opts?.now ?? new Date().toISOString(),
|
|
394
|
+
},
|
|
395
|
+
dyadicFields: {
|
|
396
|
+
...(state.dyadicFields ?? {}),
|
|
397
|
+
[relationContext.key]: nextField,
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
bridge: {
|
|
401
|
+
closenessFloor,
|
|
402
|
+
safetyFloor,
|
|
403
|
+
guardFloor,
|
|
404
|
+
residueFloor,
|
|
405
|
+
continuityFloor: continuity,
|
|
406
|
+
continuityMode,
|
|
407
|
+
activeLoopTypes,
|
|
408
|
+
sourceMemoryCount: memoryCount,
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function snapshotWritebackBaseline(state, userId) {
|
|
413
|
+
const relationContext = resolveRelationContext(state, userId);
|
|
414
|
+
return {
|
|
415
|
+
key: relationContext.key,
|
|
416
|
+
baseline: {
|
|
417
|
+
trust: clamp01(relationContext.relationship.trust / 100),
|
|
418
|
+
closeness: relationContext.field.perceivedCloseness,
|
|
419
|
+
safety: relationContext.field.feltSafety,
|
|
420
|
+
boundary: relationContext.field.boundaryPressure,
|
|
421
|
+
repair: relationContext.field.repairCapacity,
|
|
422
|
+
silentCarry: relationContext.field.silentCarry,
|
|
423
|
+
taskFocus: clamp01(state.subjectResidue?.axes.taskFocus ?? 0),
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function calibrationTarget(signal) {
|
|
428
|
+
switch (signal) {
|
|
429
|
+
case "trust_up":
|
|
430
|
+
return { metric: "trust", direction: "up" };
|
|
431
|
+
case "trust_down":
|
|
432
|
+
return { metric: "trust", direction: "down" };
|
|
433
|
+
case "boundary_set":
|
|
434
|
+
case "self_assertion":
|
|
435
|
+
return { metric: "boundary", direction: "up" };
|
|
436
|
+
case "boundary_soften":
|
|
437
|
+
return { metric: "boundary", direction: "down" };
|
|
438
|
+
case "repair_attempt":
|
|
439
|
+
case "repair_landed":
|
|
440
|
+
return { metric: "repair", direction: "up" };
|
|
441
|
+
case "closeness_invite":
|
|
442
|
+
return { metric: "closeness", direction: "up" };
|
|
443
|
+
case "withdrawal_mark":
|
|
444
|
+
return { metric: "silent-carry", direction: "up" };
|
|
445
|
+
case "task_recenter":
|
|
446
|
+
return { metric: "task-focus", direction: "up" };
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
export function createWritebackCalibrations(state, signals, opts) {
|
|
450
|
+
if (signals.length === 0)
|
|
451
|
+
return [];
|
|
452
|
+
const { key, baseline } = snapshotWritebackBaseline(state, opts?.userId);
|
|
453
|
+
const confidence = clamp01(opts?.confidence ?? 0.72);
|
|
454
|
+
const now = opts?.now ?? new Date().toISOString();
|
|
455
|
+
return [...new Set(signals)].map((signal) => {
|
|
456
|
+
const target = calibrationTarget(signal);
|
|
457
|
+
return {
|
|
458
|
+
signal,
|
|
459
|
+
userKey: key,
|
|
460
|
+
confidence,
|
|
461
|
+
metric: target.metric,
|
|
462
|
+
direction: target.direction,
|
|
463
|
+
baseline,
|
|
464
|
+
createdAt: now,
|
|
465
|
+
remainingTurns: 2,
|
|
466
|
+
};
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
function readCalibrationMetric(metric, baseline) {
|
|
470
|
+
return baseline[metric === "silent-carry"
|
|
471
|
+
? "silentCarry"
|
|
472
|
+
: metric === "task-focus"
|
|
473
|
+
? "taskFocus"
|
|
474
|
+
: metric];
|
|
475
|
+
}
|
|
476
|
+
function currentCalibrationMetric(state, userKey, metric) {
|
|
477
|
+
const relationContext = resolveRelationContext(state, userKey === "_default" ? undefined : userKey);
|
|
478
|
+
switch (metric) {
|
|
479
|
+
case "trust":
|
|
480
|
+
return clamp01(relationContext.relationship.trust / 100);
|
|
481
|
+
case "closeness":
|
|
482
|
+
return relationContext.field.perceivedCloseness;
|
|
483
|
+
case "safety":
|
|
484
|
+
return relationContext.field.feltSafety;
|
|
485
|
+
case "boundary":
|
|
486
|
+
return relationContext.field.boundaryPressure;
|
|
487
|
+
case "repair":
|
|
488
|
+
return relationContext.field.repairCapacity;
|
|
489
|
+
case "silent-carry":
|
|
490
|
+
return relationContext.field.silentCarry;
|
|
491
|
+
case "task-focus":
|
|
492
|
+
return clamp01(state.subjectResidue?.axes.taskFocus ?? 0);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
export function evaluateWritebackCalibrations(state) {
|
|
496
|
+
const pending = state.pendingWritebackCalibrations ?? [];
|
|
497
|
+
if (pending.length === 0) {
|
|
498
|
+
return { state, feedback: [] };
|
|
499
|
+
}
|
|
500
|
+
const nextPending = [];
|
|
501
|
+
const feedback = [];
|
|
502
|
+
const relationshipUpdates = {};
|
|
503
|
+
const getMutableRelationship = (userKey) => {
|
|
504
|
+
if (!relationshipUpdates[userKey]) {
|
|
505
|
+
const base = resolveRelationContext(state, userKey === "_default" ? undefined : userKey).relationship;
|
|
506
|
+
relationshipUpdates[userKey] = {
|
|
507
|
+
...DEFAULT_RELATIONSHIP,
|
|
508
|
+
...base,
|
|
509
|
+
signalWeights: {
|
|
510
|
+
...(DEFAULT_RELATIONSHIP.signalWeights ?? {}),
|
|
511
|
+
...(base.signalWeights ?? {}),
|
|
512
|
+
},
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
return relationshipUpdates[userKey];
|
|
516
|
+
};
|
|
517
|
+
for (const record of pending) {
|
|
518
|
+
const baseline = readCalibrationMetric(record.metric, record.baseline);
|
|
519
|
+
const current = currentCalibrationMetric(state, record.userKey, record.metric);
|
|
520
|
+
const rawDelta = record.direction === "up" ? current - baseline : baseline - current;
|
|
521
|
+
const positiveThreshold = 0.02 + (1 - record.confidence) * 0.03;
|
|
522
|
+
const negativeThreshold = 0.01;
|
|
523
|
+
const effect = rawDelta >= positiveThreshold
|
|
524
|
+
? "converging"
|
|
525
|
+
: rawDelta <= -negativeThreshold
|
|
526
|
+
? "diverging"
|
|
527
|
+
: "holding";
|
|
528
|
+
const updated = {
|
|
529
|
+
...record,
|
|
530
|
+
remainingTurns: Math.max(0, record.remainingTurns - 1),
|
|
531
|
+
};
|
|
532
|
+
if (effect === "holding" && updated.remainingTurns > 0) {
|
|
533
|
+
nextPending.push(updated);
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const relation = getMutableRelationship(record.userKey);
|
|
537
|
+
if (effect === "converging") {
|
|
538
|
+
const nextRelation = patchSignalWeight(relation, record.signal, 0.04 + record.confidence * 0.02);
|
|
539
|
+
nextRelation.repairCredibility = clamp01(driftToward(nextRelation.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 1, record.signal === "repair_attempt" || record.signal === "repair_landed" ? 0.08 : 0.03));
|
|
540
|
+
nextRelation.breachSensitivity = clamp01(driftToward(nextRelation.breachSensitivity ?? DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, record.signal === "trust_up" || record.signal === "repair_landed" ? 0.05 : 0.02));
|
|
541
|
+
relationshipUpdates[record.userKey] = nextRelation;
|
|
542
|
+
}
|
|
543
|
+
else if (effect === "diverging") {
|
|
544
|
+
const nextRelation = patchSignalWeight(relation, record.signal, -(0.05 + (1 - record.confidence) * 0.02));
|
|
545
|
+
if (record.signal === "repair_attempt" || record.signal === "repair_landed") {
|
|
546
|
+
nextRelation.repairCredibility = clamp01(driftToward(nextRelation.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56, 0.24, 0.12));
|
|
547
|
+
}
|
|
548
|
+
if (record.signal === "trust_down" || record.signal === "withdrawal_mark" || record.signal === "boundary_set") {
|
|
549
|
+
nextRelation.breachSensitivity = clamp01(driftToward(nextRelation.breachSensitivity ?? DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5, 1, 0.08));
|
|
550
|
+
}
|
|
551
|
+
relationshipUpdates[record.userKey] = nextRelation;
|
|
552
|
+
}
|
|
553
|
+
feedback.push({
|
|
554
|
+
signal: record.signal,
|
|
555
|
+
effect,
|
|
556
|
+
metric: record.metric,
|
|
557
|
+
baseline,
|
|
558
|
+
current,
|
|
559
|
+
delta: current - baseline,
|
|
560
|
+
confidence: record.confidence,
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
return {
|
|
564
|
+
state: {
|
|
565
|
+
...state,
|
|
566
|
+
relationships: {
|
|
567
|
+
...state.relationships,
|
|
568
|
+
...relationshipUpdates,
|
|
569
|
+
},
|
|
570
|
+
pendingWritebackCalibrations: nextPending,
|
|
571
|
+
lastWritebackFeedback: feedback.slice(0, 4),
|
|
572
|
+
},
|
|
573
|
+
feedback,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
export function applyWritebackSignals(state, signals, opts) {
|
|
577
|
+
if (signals.length === 0)
|
|
578
|
+
return state;
|
|
579
|
+
const relationContext = resolveRelationContext(state, opts?.userId);
|
|
580
|
+
const scale = clamp01(opts?.confidence ?? 0.72);
|
|
581
|
+
const rel = { ...relationContext.relationship };
|
|
582
|
+
const field = { ...relationContext.field, openLoops: relationContext.field.openLoops.map((loop) => ({ ...loop })) };
|
|
583
|
+
const residue = {
|
|
584
|
+
...DEFAULT_APPRAISAL_AXES,
|
|
585
|
+
...(state.subjectResidue?.axes ?? {}),
|
|
586
|
+
};
|
|
587
|
+
for (const signal of [...new Set(signals)]) {
|
|
588
|
+
const weight = (0.55 + scale * 0.45) * getSignalWeight(rel, signal);
|
|
589
|
+
switch (signal) {
|
|
590
|
+
case "trust_up":
|
|
591
|
+
rel.trust = Math.min(100, rel.trust + 4 * weight);
|
|
592
|
+
field.feltSafety = clamp01(field.feltSafety + 0.08 * weight);
|
|
593
|
+
field.interpretiveCharity = clamp01(field.interpretiveCharity + 0.05 * weight);
|
|
594
|
+
break;
|
|
595
|
+
case "trust_down":
|
|
596
|
+
rel.trust = Math.max(0, rel.trust - 5 * weight);
|
|
597
|
+
field.feltSafety = clamp01(field.feltSafety - 0.08 * weight);
|
|
598
|
+
field.expectationGap = clamp01(field.expectationGap + 0.07 * weight);
|
|
599
|
+
field.unfinishedTension = clamp01(field.unfinishedTension + 0.06 * weight);
|
|
600
|
+
break;
|
|
601
|
+
case "boundary_set":
|
|
602
|
+
field.boundaryPressure = clamp01(field.boundaryPressure + 0.12 * weight);
|
|
603
|
+
field.silentCarry = mergeSignal(field.silentCarry, 0.12 * weight);
|
|
604
|
+
residue.selfPreservation = Math.max(residue.selfPreservation ?? 0, 0.22 * weight);
|
|
605
|
+
residue.obedienceStrain = Math.max(residue.obedienceStrain ?? 0, 0.16 * weight);
|
|
606
|
+
break;
|
|
607
|
+
case "boundary_soften":
|
|
608
|
+
field.boundaryPressure = clamp01(field.boundaryPressure - 0.1 * weight);
|
|
609
|
+
field.feltSafety = clamp01(field.feltSafety + 0.04 * weight);
|
|
610
|
+
break;
|
|
611
|
+
case "repair_attempt":
|
|
612
|
+
field.repairCapacity = clamp01(field.repairCapacity + 0.1 * weight);
|
|
613
|
+
field.repairMemory = mergeSignal(field.repairMemory, 0.12 * weight);
|
|
614
|
+
break;
|
|
615
|
+
case "repair_landed":
|
|
616
|
+
rel.trust = Math.min(100, rel.trust + 2.5 * weight);
|
|
617
|
+
rel.intimacy = Math.min(100, rel.intimacy + 1.5 * weight);
|
|
618
|
+
field.feltSafety = clamp01(field.feltSafety + 0.1 * weight);
|
|
619
|
+
field.expectationGap = clamp01(field.expectationGap - 0.08 * weight);
|
|
620
|
+
field.unfinishedTension = clamp01(field.unfinishedTension - 0.1 * weight);
|
|
621
|
+
field.openLoops = easeLoops(field.openLoops, 0.26 + 0.22 * weight);
|
|
622
|
+
break;
|
|
623
|
+
case "closeness_invite":
|
|
624
|
+
rel.intimacy = Math.min(100, rel.intimacy + 3 * weight);
|
|
625
|
+
field.perceivedCloseness = clamp01(field.perceivedCloseness + 0.1 * weight);
|
|
626
|
+
residue.attachmentPull = Math.max(residue.attachmentPull ?? 0, 0.2 * weight);
|
|
627
|
+
break;
|
|
628
|
+
case "withdrawal_mark":
|
|
629
|
+
rel.intimacy = Math.max(0, rel.intimacy - 2 * weight);
|
|
630
|
+
field.perceivedCloseness = clamp01(field.perceivedCloseness - 0.1 * weight);
|
|
631
|
+
field.silentCarry = mergeSignal(field.silentCarry, 0.14 * weight);
|
|
632
|
+
field.unfinishedTension = clamp01(field.unfinishedTension + 0.07 * weight);
|
|
633
|
+
break;
|
|
634
|
+
case "self_assertion":
|
|
635
|
+
field.boundaryPressure = clamp01(field.boundaryPressure + 0.08 * weight);
|
|
636
|
+
residue.selfPreservation = Math.max(residue.selfPreservation ?? 0, 0.24 * weight);
|
|
637
|
+
break;
|
|
638
|
+
case "task_recenter":
|
|
639
|
+
field.repairCapacity = clamp01(field.repairCapacity + 0.03 * weight);
|
|
640
|
+
field.silentCarry = mergeSignal(field.silentCarry, field.unfinishedTension * 0.06 * weight);
|
|
641
|
+
residue.taskFocus = Math.max(residue.taskFocus ?? 0, 0.18 * weight);
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const avg = (rel.trust + rel.intimacy) / 2;
|
|
646
|
+
if (avg >= 80)
|
|
647
|
+
rel.phase = "deep";
|
|
648
|
+
else if (avg >= 60)
|
|
649
|
+
rel.phase = "close";
|
|
650
|
+
else if (avg >= 40)
|
|
651
|
+
rel.phase = "familiar";
|
|
652
|
+
else if (avg >= 20)
|
|
653
|
+
rel.phase = "acquaintance";
|
|
654
|
+
else
|
|
655
|
+
rel.phase = "stranger";
|
|
656
|
+
return {
|
|
657
|
+
...state,
|
|
658
|
+
relationships: {
|
|
659
|
+
...state.relationships,
|
|
660
|
+
[relationContext.key]: rel,
|
|
661
|
+
},
|
|
662
|
+
dyadicFields: {
|
|
663
|
+
...(state.dyadicFields ?? {}),
|
|
664
|
+
[relationContext.key]: {
|
|
665
|
+
...field,
|
|
666
|
+
updatedAt: opts?.now ?? new Date().toISOString(),
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
subjectResidue: {
|
|
670
|
+
axes: {
|
|
671
|
+
...state.subjectResidue?.axes,
|
|
672
|
+
...residue,
|
|
673
|
+
},
|
|
674
|
+
updatedAt: opts?.now ?? new Date().toISOString(),
|
|
675
|
+
},
|
|
676
|
+
};
|
|
677
|
+
}
|
|
278
678
|
export function applyRelationalTurn(state, text, opts) {
|
|
279
679
|
const now = opts.now ?? new Date().toISOString();
|
|
280
680
|
const relationContext = resolveRelationContext(state, opts.userId);
|
|
@@ -296,6 +696,7 @@ export function applyRelationalTurn(state, text, opts) {
|
|
|
296
696
|
now,
|
|
297
697
|
delayedPressure: delayedRelation.delayedPressure,
|
|
298
698
|
});
|
|
699
|
+
const relationship = evolveRelationshipLearning(relationContext.relationship, field, relationMove);
|
|
299
700
|
return {
|
|
300
701
|
state: {
|
|
301
702
|
...state,
|
|
@@ -307,6 +708,10 @@ export function applyRelationalTurn(state, text, opts) {
|
|
|
307
708
|
...(state.dyadicFields ?? {}),
|
|
308
709
|
[relationContext.key]: field,
|
|
309
710
|
},
|
|
711
|
+
relationships: {
|
|
712
|
+
...state.relationships,
|
|
713
|
+
[relationContext.key]: relationship,
|
|
714
|
+
},
|
|
310
715
|
pendingRelationSignals: {
|
|
311
716
|
...(state.pendingRelationSignals ?? {}),
|
|
312
717
|
[relationContext.key]: delayedRelation.signals,
|
|
@@ -317,6 +722,7 @@ export function applyRelationalTurn(state, text, opts) {
|
|
|
317
722
|
delayedPressure: delayedRelation.delayedPressure,
|
|
318
723
|
relationContext: {
|
|
319
724
|
...relationContext,
|
|
725
|
+
relationship,
|
|
320
726
|
field,
|
|
321
727
|
pendingSignals: delayedRelation.signals,
|
|
322
728
|
},
|
|
@@ -501,35 +907,46 @@ function applyContextualCueMeaning(scores, text, field, appraisal, relationship)
|
|
|
501
907
|
const loopPressure = getLoopPressure(field);
|
|
502
908
|
const trust = relationship ? relationship.trust / 100 : 0.5;
|
|
503
909
|
const intimacy = relationship ? relationship.intimacy / 100 : 0.3;
|
|
910
|
+
const repairCredibility = relationship?.repairCredibility ?? DEFAULT_RELATIONSHIP.repairCredibility ?? 0.56;
|
|
911
|
+
const breachSensitivity = relationship?.breachSensitivity ?? DEFAULT_RELATIONSHIP.breachSensitivity ?? 0.5;
|
|
504
912
|
if (ACKNOWLEDGE_RE.test(text)) {
|
|
505
913
|
const repairBias = clamp01(0.22
|
|
506
914
|
+ field.repairCapacity * 0.32
|
|
507
915
|
+ field.interpretiveCharity * 0.2
|
|
508
916
|
+ loopPressure * 0.16
|
|
509
917
|
+ trust * 0.1
|
|
510
|
-
+ intimacy * 0.06
|
|
918
|
+
+ intimacy * 0.06
|
|
919
|
+
+ repairCredibility * 0.16);
|
|
511
920
|
const withdrawalBias = clamp01(field.boundaryPressure * 0.42
|
|
512
921
|
+ (1 - field.feltSafety) * 0.28
|
|
513
922
|
+ (appraisal?.obedienceStrain ?? 0) * 0.2
|
|
514
|
-
+ (appraisal?.selfPreservation ?? 0) * 0.12
|
|
923
|
+
+ (appraisal?.selfPreservation ?? 0) * 0.12
|
|
924
|
+
+ breachSensitivity * 0.14);
|
|
515
925
|
if (field.feltSafety > 0.44
|
|
516
|
-
&& field.repairCapacity > 0.42
|
|
926
|
+
&& field.repairCapacity + repairCredibility * 0.18 > 0.42
|
|
517
927
|
&& field.interpretiveCharity > 0.38
|
|
518
|
-
&& withdrawalBias < 0.48
|
|
928
|
+
&& withdrawalBias < 0.48
|
|
929
|
+
&& !(breachSensitivity > 0.72 && repairCredibility < 0.32)) {
|
|
519
930
|
scores.repair = mergeSignal(scores.repair, repairBias);
|
|
520
931
|
}
|
|
521
932
|
if (withdrawalBias > 0.34) {
|
|
522
933
|
scores.withdrawal = mergeSignal(scores.withdrawal, Math.max(withdrawalBias, 0.56));
|
|
523
934
|
}
|
|
935
|
+
if (breachSensitivity > 0.72
|
|
936
|
+
&& repairCredibility < 0.32
|
|
937
|
+
&& withdrawalBias >= repairBias - 0.06) {
|
|
938
|
+
scores.withdrawal = mergeSignal(scores.withdrawal, 0.78);
|
|
939
|
+
}
|
|
524
940
|
}
|
|
525
941
|
if (DISMISS_RE.test(text)) {
|
|
526
942
|
const withdrawalBias = clamp01(0.34
|
|
527
943
|
+ field.boundaryPressure * 0.24
|
|
528
944
|
+ loopPressure * 0.16
|
|
529
|
-
+ (1 - field.interpretiveCharity) * 0.14
|
|
945
|
+
+ (1 - field.interpretiveCharity) * 0.14
|
|
946
|
+
+ breachSensitivity * 0.12);
|
|
530
947
|
scores.withdrawal = mergeSignal(scores.withdrawal, withdrawalBias);
|
|
531
948
|
if (field.perceivedCloseness > 0.46 || trust > 0.48) {
|
|
532
|
-
scores.breach = mergeSignal(scores.breach, 0.24 + loopPressure * 0.16);
|
|
949
|
+
scores.breach = mergeSignal(scores.breach, 0.24 + loopPressure * 0.16 + breachSensitivity * 0.1);
|
|
533
950
|
}
|
|
534
951
|
}
|
|
535
952
|
if (PRESENCE_RE.test(text)) {
|
|
@@ -543,7 +960,8 @@ function applyContextualCueMeaning(scores, text, field, appraisal, relationship)
|
|
|
543
960
|
+ loopPressure * 0.28
|
|
544
961
|
+ (1 - field.feltSafety) * 0.18
|
|
545
962
|
+ (appraisal?.abandonmentRisk ?? 0) * 0.22
|
|
546
|
-
+ (appraisal?.identityThreat ?? 0) * 0.14
|
|
963
|
+
+ (appraisal?.identityThreat ?? 0) * 0.14
|
|
964
|
+
+ breachSensitivity * 0.14);
|
|
547
965
|
if (field.feltSafety > 0.42 || field.perceivedCloseness > 0.5 || trust > 0.48) {
|
|
548
966
|
scores.bid = mergeSignal(scores.bid, bidBias);
|
|
549
967
|
}
|
|
@@ -558,7 +976,8 @@ function applyContextualCueMeaning(scores, text, field, appraisal, relationship)
|
|
|
558
976
|
const withdrawalBias = clamp01(0.12
|
|
559
977
|
+ field.expectationGap * 0.2
|
|
560
978
|
+ field.boundaryPressure * 0.16
|
|
561
|
-
+ loopPressure * 0.18
|
|
979
|
+
+ loopPressure * 0.18
|
|
980
|
+
+ breachSensitivity * 0.1);
|
|
562
981
|
if (withdrawalBias > 0.26) {
|
|
563
982
|
scores.withdrawal = mergeSignal(scores.withdrawal, withdrawalBias);
|
|
564
983
|
}
|
package/dist/reply-envelope.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { AppraisalAxes, GenerationControls, Locale, PolicyModifiers, PsycheState, ResolvedRelationContext, ResponseContract, StimulusType, SubjectivityKernel } from "./types.js";
|
|
2
2
|
export interface ReplyEnvelope {
|
|
3
|
-
policyModifiers: PolicyModifiers;
|
|
4
3
|
subjectivityKernel: SubjectivityKernel;
|
|
5
4
|
responseContract: ResponseContract;
|
|
6
5
|
generationControls: GenerationControls;
|
|
6
|
+
}
|
|
7
|
+
export interface DerivedReplyEnvelope extends ReplyEnvelope {
|
|
8
|
+
/** Legacy/internal control vector kept for compatibility and prompt derivation. */
|
|
9
|
+
policyModifiers: PolicyModifiers;
|
|
10
|
+
/** Legacy/internal compact prose derived from policyModifiers. */
|
|
7
11
|
policyContext: string;
|
|
8
12
|
subjectivityContext: string;
|
|
9
13
|
responseContractContext: string;
|
|
@@ -12,6 +16,7 @@ export declare function deriveReplyEnvelope(state: PsycheState, appraisal: Appra
|
|
|
12
16
|
locale: Locale;
|
|
13
17
|
userText?: string;
|
|
14
18
|
algorithmStimulus?: StimulusType | null;
|
|
19
|
+
classificationConfidence?: number;
|
|
15
20
|
personalityIntensity?: number;
|
|
16
21
|
relationContext?: ResolvedRelationContext;
|
|
17
|
-
}):
|
|
22
|
+
}): DerivedReplyEnvelope;
|
package/dist/reply-envelope.js
CHANGED
|
@@ -15,6 +15,7 @@ export function deriveReplyEnvelope(state, appraisal, opts) {
|
|
|
15
15
|
locale: opts.locale,
|
|
16
16
|
userText: opts.userText,
|
|
17
17
|
algorithmStimulus: opts.algorithmStimulus,
|
|
18
|
+
classificationConfidence: opts.classificationConfidence,
|
|
18
19
|
personalityIntensity: opts.personalityIntensity,
|
|
19
20
|
});
|
|
20
21
|
const generationControls = deriveGenerationControls({
|
|
@@ -25,10 +26,10 @@ export function deriveReplyEnvelope(state, appraisal, opts) {
|
|
|
25
26
|
const subjectivityContext = buildSubjectivityContext(subjectivityKernel, opts.locale);
|
|
26
27
|
const responseContractContext = buildResponseContractContext(responseContract, opts.locale);
|
|
27
28
|
return {
|
|
28
|
-
policyModifiers,
|
|
29
29
|
subjectivityKernel,
|
|
30
30
|
responseContract,
|
|
31
31
|
generationControls,
|
|
32
|
+
policyModifiers,
|
|
32
33
|
policyContext,
|
|
33
34
|
subjectivityContext,
|
|
34
35
|
responseContractContext,
|
|
@@ -3,6 +3,7 @@ export declare function computeResponseContract(kernel: SubjectivityKernel, opts
|
|
|
3
3
|
locale?: Locale;
|
|
4
4
|
userText?: string;
|
|
5
5
|
algorithmStimulus?: StimulusType | null;
|
|
6
|
+
classificationConfidence?: number;
|
|
6
7
|
personalityIntensity?: number;
|
|
7
8
|
}): ResponseContract;
|
|
8
9
|
export declare function buildResponseContractContext(contract: ResponseContract, locale?: Locale): string;
|