psyche-ai 9.2.9 → 9.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -326,6 +326,14 @@ Psyche 现在更准确的目标,不是“模仿某种像人的风格”,而
326
326
 
327
327
  当前主线里,`processInput()` 会直接返回 `replyEnvelope` 作为规范主接口;原有平级字段继续保留为兼容别名,避免打断现有宿主。`policyModifiers` 不再属于规范主接口,只保留为 legacy raw vector。
328
328
 
329
+ 在这个规范主接口之外,`processInput()` 现在还会可选返回一个很薄的 `observability` side-channel。它不是新的控制面,也不会反向改写 `replyEnvelope`;它只回答三件事:
330
+
331
+ - 这轮当前由哪一个控制平面主导
332
+ - 当前 turn / writeback / session bridge / persisted relationship 四层是怎么对账的
333
+ - 这次 `work/private` 选择为什么会落在这个 profile 上
334
+
335
+ 这样别的 agent 或宿主不用再自己猜“现在到底是谁在主导”和“为什么这次选了这个策略”,但主链路仍然只有 `replyEnvelope` 一个真相源。
336
+
329
337
  ### 内在世界
330
338
 
331
339
  Psyche 给 AI 一个始终运转的内在自我——不是条件触发,而是每时每刻都在:
package/dist/core.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls, SessionBridgeState, ThrongletsExport, WritebackCalibrationFeedback, WritebackSignalType, ExternalContinuityEnvelope } from "./types.js";
1
+ import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls, SessionBridgeState, ThrongletsExport, TurnObservability, WritebackCalibrationFeedback, WritebackSignalType, ExternalContinuityEnvelope } from "./types.js";
2
2
  import type { StorageAdapter } from "./storage.js";
3
3
  import type { DiagnosticReport, SessionMetrics } from "./diagnostics.js";
4
4
  import type { ReplyEnvelope } from "./reply-envelope.js";
@@ -57,6 +57,8 @@ export interface ProcessInputResult {
57
57
  externalContinuity?: ExternalContinuityEnvelope<ThrongletsExport>;
58
58
  /** v9.2.8: sparse low-frequency export surface suitable for Thronglets */
59
59
  throngletsExports?: ThrongletsExport[];
60
+ /** v9.2.10: low-cost side channel for control boundary, state layers, and output attribution */
61
+ observability?: TurnObservability;
60
62
  /**
61
63
  * Legacy compatibility alias: ready-to-use prompt fragment summarizing raw policy modifiers.
62
64
  *
package/dist/core.js CHANGED
@@ -28,6 +28,7 @@ import { runReflectiveTurnPhases } from "./input-turn.js";
28
28
  import { applyRelationalTurn, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations } from "./relation-dynamics.js";
29
29
  import { buildExternalContinuityEnvelope } from "./external-continuity.js";
30
30
  import { deriveThrongletsExports } from "./thronglets-export.js";
31
+ import { buildTurnObservability } from "./observability.js";
31
32
  function formatWritebackFeedbackNote(feedback, locale) {
32
33
  const top = feedback?.[0];
33
34
  if (!top)
@@ -480,6 +481,17 @@ export class PsycheEngine {
480
481
  responseContractContext: derivedReplyEnvelope.responseContractContext,
481
482
  policyContext: derivedReplyEnvelope.policyContext || undefined,
482
483
  };
484
+ const observability = buildTurnObservability(state, {
485
+ replyEnvelope,
486
+ promptRenderInputs,
487
+ compactMode: this.cfg.compactMode,
488
+ stimulus: appliedStimulus,
489
+ userText: text || undefined,
490
+ sessionBridge,
491
+ writebackFeedback,
492
+ relationContext: relationalTurn.relationContext,
493
+ externalContinuityExports: throngletsExports.length,
494
+ });
483
495
  if (this.cfg.compactMode) {
484
496
  const externalContinuity = buildExternalContinuityEnvelope(throngletsExports);
485
497
  return {
@@ -496,6 +508,7 @@ export class PsycheEngine {
496
508
  writebackFeedback,
497
509
  externalContinuity,
498
510
  throngletsExports,
511
+ observability,
499
512
  policyContext: derivedReplyEnvelope.policyContext,
500
513
  };
501
514
  }
@@ -514,6 +527,7 @@ export class PsycheEngine {
514
527
  writebackFeedback,
515
528
  externalContinuity,
516
529
  throngletsExports,
530
+ observability,
517
531
  policyContext: derivedReplyEnvelope.policyContext,
518
532
  };
519
533
  }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ 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, SubjectivityKernel, ResponseContract, GenerationControls, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, SessionBridgeState, ThrongletsExportSubject, ThrongletsExportPrimitive, ThrongletsExportBase, RelationMilestoneExport, OpenLoopAnchorExport, WritebackCalibrationExport, ContinuityAnchorExport, ThrongletsExport, ThrongletsExportState, ExternalContinuityEvent, ExternalContinuityEnvelope, ThrongletsTraceTaxonomy, ThrongletsExternalContinuityRecord, ThrongletsTracePayload, ThrongletsTraceSerializationOptions, WritebackSignalType, WritebackSignalWeightMap, PendingWritebackCalibration, WritebackCalibrationFeedback, WritebackCalibrationMetric, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } 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, TurnControlPlane, TurnControlDriver, ControlBoundaryObservation, StateLayerKind, StateLayerObservation, PromptRenderInputName, RuntimeHookName, OutputAttributionObservation, StateReconciliationObservation, DecisionCandidateName, DecisionCandidateObservation, DecisionRationaleObservation, TurnObservability, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, SessionBridgeState, ThrongletsExportSubject, ThrongletsExportPrimitive, ThrongletsExportBase, RelationMilestoneExport, OpenLoopAnchorExport, WritebackCalibrationExport, ContinuityAnchorExport, ThrongletsExport, ThrongletsExportState, ExternalContinuityEvent, ExternalContinuityEnvelope, ThrongletsTraceTaxonomy, ThrongletsExternalContinuityRecord, ThrongletsTracePayload, ThrongletsTraceSerializationOptions, WritebackSignalType, WritebackSignalWeightMap, PendingWritebackCalibration, WritebackCalibrationFeedback, WritebackCalibrationMetric, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
6
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";
@@ -28,6 +28,7 @@ export { computeResponseContract, buildResponseContractContext } from "./respons
28
28
  export { deriveGenerationControls } from "./host-controls.js";
29
29
  export { deriveReplyEnvelope } from "./reply-envelope.js";
30
30
  export type { ReplyEnvelope } from "./reply-envelope.js";
31
+ export { buildTurnObservability } from "./observability.js";
31
32
  export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
32
33
  export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations, } from "./relation-dynamics.js";
33
34
  export { EXTERNAL_CONTINUITY_SIGNAL_KINDS, EXTERNAL_CONTINUITY_TRACE_KINDS, buildExternalContinuityEnvelope, } from "./external-continuity.js";
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectiv
38
38
  export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
39
39
  export { deriveGenerationControls } from "./host-controls.js";
40
40
  export { deriveReplyEnvelope } from "./reply-envelope.js";
41
+ export { buildTurnObservability } from "./observability.js";
41
42
  export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
42
43
  export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations, } from "./relation-dynamics.js";
43
44
  export { EXTERNAL_CONTINUITY_SIGNAL_KINDS, EXTERNAL_CONTINUITY_TRACE_KINDS, buildExternalContinuityEnvelope, } from "./external-continuity.js";
@@ -0,0 +1,14 @@
1
+ import type { PsycheState, ResolvedRelationContext, SessionBridgeState, StimulusType, TurnObservability, WritebackCalibrationFeedback } from "./types.js";
2
+ import type { PromptRenderInputs } from "./prompt.js";
3
+ import type { ReplyEnvelope } from "./reply-envelope.js";
4
+ export declare function buildTurnObservability(state: PsycheState, opts: {
5
+ replyEnvelope: ReplyEnvelope;
6
+ promptRenderInputs: PromptRenderInputs;
7
+ compactMode: boolean;
8
+ stimulus: StimulusType | null;
9
+ userText?: string;
10
+ sessionBridge: SessionBridgeState | null;
11
+ writebackFeedback: WritebackCalibrationFeedback[];
12
+ relationContext?: ResolvedRelationContext;
13
+ externalContinuityExports: number;
14
+ }): TurnObservability;
@@ -0,0 +1,274 @@
1
+ function clamp01(v) {
2
+ return Math.max(0, Math.min(1, v));
3
+ }
4
+ function pickDominantPlane(replyEnvelope) {
5
+ const { subjectivityKernel, responseContract } = replyEnvelope;
6
+ const taskCandidates = [
7
+ ["task-focus", subjectivityKernel.taskPlane.focus],
8
+ ["discipline", subjectivityKernel.taskPlane.discipline],
9
+ ];
10
+ const subjectCandidates = [
11
+ ["attachment", subjectivityKernel.subjectPlane.attachment],
12
+ ["guardedness", subjectivityKernel.subjectPlane.guardedness],
13
+ ["identity-strain", subjectivityKernel.subjectPlane.identityStrain],
14
+ ["residue", subjectivityKernel.subjectPlane.residue],
15
+ ];
16
+ const relationCandidates = [
17
+ ["closeness", subjectivityKernel.relationPlane.closeness],
18
+ ["loop-pressure", subjectivityKernel.relationPlane.loopPressure],
19
+ ["repair-readiness", subjectivityKernel.relationPlane.repairReadiness],
20
+ ["repair-friction", subjectivityKernel.relationPlane.repairFriction],
21
+ ["hysteresis", subjectivityKernel.relationPlane.hysteresis],
22
+ ["silent-carry", subjectivityKernel.relationPlane.silentCarry],
23
+ ];
24
+ const ambiguityCandidates = [
25
+ ["conflict-load", subjectivityKernel.ambiguityPlane.conflictLoad],
26
+ ["expression-inhibition", subjectivityKernel.ambiguityPlane.expressionInhibition],
27
+ ["naming-uncertainty", 1 - subjectivityKernel.ambiguityPlane.namingConfidence],
28
+ ];
29
+ const planeSummaries = [
30
+ ["task", ...taskCandidates.sort((a, b) => b[1] - a[1])[0]],
31
+ ["subject", ...subjectCandidates.sort((a, b) => b[1] - a[1])[0]],
32
+ ["relation", ...relationCandidates.sort((a, b) => b[1] - a[1])[0]],
33
+ ["ambiguity", ...ambiguityCandidates.sort((a, b) => b[1] - a[1])[0]],
34
+ ];
35
+ planeSummaries.sort((a, b) => {
36
+ if (b[2] !== a[2])
37
+ return b[2] - a[2];
38
+ if (responseContract.replyProfile === "work") {
39
+ if (a[0] === "task")
40
+ return -1;
41
+ if (b[0] === "task")
42
+ return 1;
43
+ }
44
+ return 0;
45
+ });
46
+ const [dominantPlane, dominantDriver, strength] = planeSummaries[0];
47
+ return {
48
+ dominantPlane,
49
+ dominantDriver,
50
+ strength: clamp01(strength),
51
+ replyProfile: responseContract.replyProfile,
52
+ replyProfileBasis: responseContract.replyProfileBasis,
53
+ overrideWindow: responseContract.overrideWindow,
54
+ };
55
+ }
56
+ function summarizeCurrentTurn(stimulus, userText) {
57
+ if (stimulus)
58
+ return `stimulus:${stimulus}`;
59
+ if (userText && userText.trim().length > 0)
60
+ return "stimulus:none";
61
+ return "no-user-input";
62
+ }
63
+ function summarizeWriteback(feedback) {
64
+ if (feedback.length === 0)
65
+ return "none";
66
+ const top = feedback[0];
67
+ return `${top.signal}:${top.effect}`;
68
+ }
69
+ function summarizeSessionBridge(bridge) {
70
+ if (!bridge)
71
+ return "none";
72
+ const loops = bridge.activeLoopTypes.length > 0 ? bridge.activeLoopTypes.join("+") : "no-open-loops";
73
+ return `${bridge.continuityMode}/${loops}`;
74
+ }
75
+ function summarizeRelationship(state, relationContext) {
76
+ const relationship = relationContext?.relationship
77
+ ?? state.relationships._default
78
+ ?? state.relationships[Object.keys(state.relationships)[0]];
79
+ if (!relationship)
80
+ return "none";
81
+ return `${relationship.phase}/trust:${Math.round(relationship.trust)}/intimacy:${Math.round(relationship.intimacy)}`;
82
+ }
83
+ function buildStateLayers(state, opts) {
84
+ return [
85
+ {
86
+ layer: "current-turn",
87
+ precedence: 1,
88
+ scope: "turn",
89
+ active: Boolean(opts.stimulus) || Boolean(opts.userText?.trim()),
90
+ summary: summarizeCurrentTurn(opts.stimulus, opts.userText),
91
+ },
92
+ {
93
+ layer: "writeback-feedback",
94
+ precedence: 2,
95
+ scope: "session",
96
+ active: opts.writebackFeedback.length > 0,
97
+ summary: summarizeWriteback(opts.writebackFeedback),
98
+ },
99
+ {
100
+ layer: "session-bridge",
101
+ precedence: 3,
102
+ scope: "session",
103
+ active: Boolean(opts.sessionBridge),
104
+ summary: summarizeSessionBridge(opts.sessionBridge),
105
+ },
106
+ {
107
+ layer: "persisted-relationship",
108
+ precedence: 4,
109
+ scope: "persistent",
110
+ active: true,
111
+ summary: summarizeRelationship(state, opts.relationContext),
112
+ },
113
+ ];
114
+ }
115
+ function buildStateReconciliation(stateLayers) {
116
+ const activeObservations = stateLayers
117
+ .filter((layer) => layer.active)
118
+ .sort((a, b) => a.precedence - b.precedence);
119
+ const activeLayers = activeObservations.map((layer) => layer.layer);
120
+ const carryLayers = activeLayers.filter((layer) => layer !== "current-turn");
121
+ const governingLayer = activeObservations[0]?.layer ?? "persisted-relationship";
122
+ let resolution = "persistent-baseline";
123
+ if (activeLayers.includes("writeback-feedback")) {
124
+ resolution = "writeback-adjusted";
125
+ }
126
+ else if (activeLayers.includes("session-bridge") && activeLayers.includes("current-turn")) {
127
+ resolution = "session-bridge-biased";
128
+ }
129
+ else if (activeLayers.includes("current-turn")) {
130
+ resolution = "current-turn-dominant";
131
+ }
132
+ const notes = stateLayers
133
+ .filter((layer) => layer.active && layer.layer !== "persisted-relationship")
134
+ .map((layer) => `${layer.layer}:${layer.summary}`);
135
+ return {
136
+ governingLayer,
137
+ activeLayers,
138
+ carryLayers,
139
+ resolution,
140
+ notes,
141
+ };
142
+ }
143
+ function pushReason(reasons, condition, label) {
144
+ if (condition)
145
+ reasons.push(label);
146
+ }
147
+ function buildDecisionRationale(replyEnvelope) {
148
+ const { subjectivityKernel, responseContract } = replyEnvelope;
149
+ const taskFocus = subjectivityKernel.taskPlane.focus;
150
+ const discipline = subjectivityKernel.taskPlane.discipline;
151
+ const attachment = subjectivityKernel.subjectPlane.attachment;
152
+ const residue = subjectivityKernel.subjectPlane.residue;
153
+ const guardedness = subjectivityKernel.subjectPlane.guardedness;
154
+ const closeness = subjectivityKernel.relationPlane.closeness;
155
+ const loopPressure = subjectivityKernel.relationPlane.loopPressure;
156
+ const repairFriction = subjectivityKernel.relationPlane.repairFriction;
157
+ const expressionInhibition = subjectivityKernel.ambiguityPlane.expressionInhibition;
158
+ const namingConfidence = subjectivityKernel.ambiguityPlane.namingConfidence;
159
+ const taskFocused = taskFocus >= 0.62;
160
+ const disciplined = discipline >= 0.72;
161
+ const taskFocusRatio = clamp01(taskFocus / 0.62);
162
+ const disciplineRatio = clamp01(discipline / 0.72);
163
+ const triggerConditions = [];
164
+ pushReason(triggerConditions, taskFocused, "task-focus>=0.62");
165
+ pushReason(triggerConditions, disciplined, "discipline>=0.72");
166
+ pushReason(triggerConditions, expressionInhibition > 0.64, "expression-inhibition>0.64");
167
+ pushReason(triggerConditions, loopPressure > 0.68, "loop-pressure>0.68");
168
+ pushReason(triggerConditions, repairFriction > 0.6, "repair-friction>0.60");
169
+ pushReason(triggerConditions, namingConfidence < 0.36, "naming-confidence<0.36");
170
+ if (triggerConditions.length === 0) {
171
+ triggerConditions.push("default-private-fallback");
172
+ }
173
+ const workReasons = [];
174
+ pushReason(workReasons, taskFocused, "task focus crossed work threshold");
175
+ pushReason(workReasons, disciplined, "discipline crossed work threshold");
176
+ pushReason(workReasons, taskFocus > 0.78 && discipline > 0.68, "high task-focus and discipline reinforce work mode");
177
+ const workScore = taskFocused && disciplined
178
+ ? 1
179
+ : taskFocused || disciplined
180
+ ? 0.82
181
+ : clamp01(Math.max(taskFocusRatio, disciplineRatio) * 0.35);
182
+ const privateReasons = [];
183
+ pushReason(privateReasons, !taskFocused && !disciplined, "no work threshold active");
184
+ pushReason(privateReasons, attachment > 0.58, "attachment keeps private surface viable");
185
+ pushReason(privateReasons, closeness > 0.58, "relational closeness favors private surface");
186
+ pushReason(privateReasons, guardedness > 0.62 || loopPressure > 0.58, "guarded relation state prefers private handling");
187
+ pushReason(privateReasons, repairFriction > 0.48 || residue > 0.45, "carry or friction remains active");
188
+ const privateScore = !taskFocused && !disciplined
189
+ ? clamp01(0.78 + (((1 - taskFocusRatio) + (1 - disciplineRatio)) / 2) * 0.22)
190
+ : clamp01((1 - Math.max(taskFocusRatio, disciplineRatio)) * 0.3);
191
+ const selected = responseContract.replyProfile === "work"
192
+ ? "work-profile"
193
+ : "private-profile";
194
+ return {
195
+ selected,
196
+ triggerConditions,
197
+ candidates: [
198
+ {
199
+ candidate: "work-profile",
200
+ score: workScore,
201
+ accepted: selected === "work-profile",
202
+ reasons: workReasons,
203
+ },
204
+ {
205
+ candidate: "private-profile",
206
+ score: privateScore,
207
+ accepted: selected === "private-profile",
208
+ reasons: privateReasons,
209
+ },
210
+ ],
211
+ };
212
+ }
213
+ function listRenderInputs(inputs) {
214
+ const names = [];
215
+ if (inputs.userText)
216
+ names.push("sensing");
217
+ if (inputs.subjectivityContext)
218
+ names.push("subjectivity");
219
+ if (inputs.responseContractContext)
220
+ names.push("response-contract");
221
+ if (inputs.metacognitiveNote)
222
+ names.push("metacognition");
223
+ if (inputs.decisionContext)
224
+ names.push("decision");
225
+ if (inputs.ethicsContext)
226
+ names.push("ethics");
227
+ if (inputs.sharedIntentionalityContext)
228
+ names.push("shared-intentionality");
229
+ if (inputs.experientialNarrative)
230
+ names.push("experiential");
231
+ if (inputs.autonomicDescription)
232
+ names.push("autonomic");
233
+ if (inputs.primarySystemsDescription)
234
+ names.push("primary-systems");
235
+ if (inputs.policyContext)
236
+ names.push("policy");
237
+ return names;
238
+ }
239
+ function listRuntimeHooks(externalContinuityExports, writebackFeedbackCount) {
240
+ const hooks = [
241
+ "appraisal",
242
+ "relation-dynamics",
243
+ "reply-envelope",
244
+ "prompt-renderer",
245
+ ];
246
+ if (writebackFeedbackCount > 0)
247
+ hooks.push("writeback-evaluation");
248
+ if (externalContinuityExports > 0)
249
+ hooks.push("external-continuity");
250
+ return hooks;
251
+ }
252
+ export function buildTurnObservability(state, opts) {
253
+ const stateLayers = buildStateLayers(state, {
254
+ stimulus: opts.stimulus,
255
+ userText: opts.userText,
256
+ sessionBridge: opts.sessionBridge,
257
+ writebackFeedback: opts.writebackFeedback,
258
+ relationContext: opts.relationContext,
259
+ });
260
+ return {
261
+ controlBoundary: pickDominantPlane(opts.replyEnvelope),
262
+ stateLayers,
263
+ stateReconciliation: buildStateReconciliation(stateLayers),
264
+ decisionRationale: buildDecisionRationale(opts.replyEnvelope),
265
+ outputAttribution: {
266
+ canonicalSurface: "reply-envelope",
267
+ promptRenderer: opts.compactMode ? "compact" : "dynamic",
268
+ renderInputs: listRenderInputs(opts.promptRenderInputs),
269
+ runtimeHooks: listRuntimeHooks(opts.externalContinuityExports, opts.writebackFeedback.length),
270
+ externalContinuityExports: opts.externalContinuityExports,
271
+ writebackFeedbackCount: opts.writebackFeedback.length,
272
+ },
273
+ };
274
+ }
package/dist/types.d.ts CHANGED
@@ -638,6 +638,60 @@ export interface ResponseContract {
638
638
  /** Which internal report, if any, should be requested in <psyche_update> */
639
639
  updateMode: "none" | "stimulus" | "empathy" | "stimulus+empathy";
640
640
  }
641
+ export type TurnControlPlane = "task" | "subject" | "relation" | "ambiguity";
642
+ export type TurnControlDriver = "task-focus" | "discipline" | "attachment" | "guardedness" | "identity-strain" | "residue" | "closeness" | "loop-pressure" | "repair-readiness" | "repair-friction" | "hysteresis" | "silent-carry" | "conflict-load" | "expression-inhibition" | "naming-uncertainty";
643
+ export interface ControlBoundaryObservation {
644
+ dominantPlane: TurnControlPlane;
645
+ dominantDriver: TurnControlDriver;
646
+ strength: number;
647
+ replyProfile: ResponseContract["replyProfile"];
648
+ replyProfileBasis: ResponseContract["replyProfileBasis"];
649
+ overrideWindow: ResponseContract["overrideWindow"];
650
+ }
651
+ export type StateLayerKind = "current-turn" | "writeback-feedback" | "session-bridge" | "persisted-relationship";
652
+ export interface StateLayerObservation {
653
+ layer: StateLayerKind;
654
+ precedence: number;
655
+ scope: "turn" | "session" | "persistent";
656
+ active: boolean;
657
+ summary: string;
658
+ }
659
+ export type PromptRenderInputName = "sensing" | "subjectivity" | "response-contract" | "metacognition" | "decision" | "ethics" | "shared-intentionality" | "experiential" | "autonomic" | "primary-systems" | "policy";
660
+ export type RuntimeHookName = "appraisal" | "relation-dynamics" | "writeback-evaluation" | "reply-envelope" | "prompt-renderer" | "external-continuity";
661
+ export interface OutputAttributionObservation {
662
+ canonicalSurface: "reply-envelope";
663
+ promptRenderer: "compact" | "dynamic";
664
+ renderInputs: PromptRenderInputName[];
665
+ runtimeHooks: RuntimeHookName[];
666
+ externalContinuityExports: number;
667
+ writebackFeedbackCount: number;
668
+ }
669
+ export interface StateReconciliationObservation {
670
+ governingLayer: StateLayerKind;
671
+ activeLayers: StateLayerKind[];
672
+ carryLayers: StateLayerKind[];
673
+ resolution: "current-turn-dominant" | "writeback-adjusted" | "session-bridge-biased" | "persistent-baseline";
674
+ notes: string[];
675
+ }
676
+ export type DecisionCandidateName = "work-profile" | "private-profile";
677
+ export interface DecisionCandidateObservation {
678
+ candidate: DecisionCandidateName;
679
+ score: number;
680
+ accepted: boolean;
681
+ reasons: string[];
682
+ }
683
+ export interface DecisionRationaleObservation {
684
+ selected: DecisionCandidateName;
685
+ triggerConditions: string[];
686
+ candidates: DecisionCandidateObservation[];
687
+ }
688
+ export interface TurnObservability {
689
+ controlBoundary: ControlBoundaryObservation;
690
+ stateLayers: StateLayerObservation[];
691
+ stateReconciliation: StateReconciliationObservation;
692
+ decisionRationale: DecisionRationaleObservation;
693
+ outputAttribution: OutputAttributionObservation;
694
+ }
641
695
  /** Sparse agent-authored writeback signals. */
642
696
  export type WritebackSignalType = "trust_up" | "trust_down" | "boundary_set" | "boundary_soften" | "repair_attempt" | "repair_landed" | "closeness_invite" | "withdrawal_mark" | "self_assertion" | "task_recenter";
643
697
  export type WritebackCalibrationMetric = "trust" | "closeness" | "safety" | "boundary" | "repair" | "silent-carry" | "task-focus";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "psyche-ai",
3
- "version": "9.2.9",
3
+ "version": "9.2.10",
4
4
  "description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
5
5
  "mcpName": "io.github.Shangri-la-0428/psyche-ai",
6
6
  "type": "module",