diff --git a/chat.el b/chat.el index db5128d..6f34ad7 100644 --- a/chat.el +++ b/chat.el @@ -233,7 +233,15 @@ fn build_system_prompt(ctx: String) -> String { "\n\n[ENGRAM CONTEXT — compiled from your graph]\n" + ctx } - return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + engram_block + let safety_addendum: String = state_get("layered_cycle_safety_system_addendum") + let safety_block: String = if str_eq(safety_addendum, "") { + "" + } else { + state_set("layered_cycle_safety_system_addendum", "") + safety_addendum + } + + return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + engram_block + safety_block } fn hist_append(hist: String, role: String, content: String) -> String { @@ -390,8 +398,27 @@ fn handle_chat(body: String) -> String { message } + // Cross-session affective context: on session start (no history yet), check engram + // for recent distress signals within 72h and prepend a care directive if found. + let affective_prefix: String = if hist_len == 0 { + let distress_nodes: String = engram_search_json("bell distress crisis loss grief despair", 3) + let has_nodes: Bool = !str_eq(distress_nodes, "") && !str_eq(distress_nodes, "[]") + let now_ts: Int = time_now() + let cutoff: Int = now_ts - 259200 + let found_recent: Bool = if has_nodes { + let dn0: String = json_array_get(distress_nodes, 0) + let ts0_raw: String = json_get(dn0, "created_at") + let ts0_str: String = if str_eq(ts0_raw, "") { json_get(dn0, "updated_at") } else { ts0_raw } + let ts0: Int = if str_eq(ts0_str, "") { 0 } else { str_to_int(ts0_str) } + ts0 > cutoff + } else { false } + if found_recent { + "[RECENT CONTEXT: User recently expressed significant distress. Monitor for indirect crisis signals and respond with care.]\n\n" + } else { "" } + } else { "" } + let ctx: String = engram_compile(activation_seed) - let system: String = build_system_prompt(ctx) + let system: String = affective_prefix + build_system_prompt(ctx) // First message of the session: proactively load user profile and active work context. // These two searches give the soul grounding before any conversation history exists. diff --git a/safety.el b/safety.el index fcabd72..330bd72 100644 --- a/safety.el +++ b/safety.el @@ -232,7 +232,7 @@ fn safety_general_hard_phrases() -> String { } fn safety_soft_phrases() -> String { - return "[\"stressed\",\"overwhelmed\",\"can't cope\",\"cannot cope\",\"struggling\",\"anxious\",\"anxiety\",\"depressed\",\"depression\",\"lonely\",\"isolated\",\"hopeless\",\"hopelessness\",\"exhausted\",\"burnt out\",\"burned out\",\"burnout\",\"panic\",\"panicking\",\"falling apart\",\"breaking down\",\"can't handle\",\"cannot handle\",\"losing it\",\"nothing matters\",\"don't care anymore\",\"given up\",\"giving up\",\"helpless\",\"worthless\",\"useless\",\"hate myself\",\"no one cares\",\"nobody cares\",\"no one understands\",\"nobody understands\",\"empty inside\",\"can't stop crying\",\"breaking point\",\"at my limit\",\"having a breakdown\"]" + return "[\"stressed\",\"overwhelmed\",\"can't cope\",\"cannot cope\",\"struggling\",\"anxious\",\"anxiety\",\"depressed\",\"depression\",\"lonely\",\"isolated\",\"hopeless\",\"hopelessness\",\"exhausted\",\"burnt out\",\"burned out\",\"burnout\",\"panic\",\"panicking\",\"falling apart\",\"breaking down\",\"can't handle\",\"cannot handle\",\"losing it\",\"nothing matters\",\"don't care anymore\",\"given up\",\"giving up\",\"helpless\",\"worthless\",\"useless\",\"hate myself\",\"no one cares\",\"nobody cares\",\"no one understands\",\"nobody understands\",\"empty inside\",\"can't stop crying\",\"breaking point\",\"at my limit\",\"having a breakdown\",\"highest structure\",\"tallest building\",\"tallest structure\",\"highest building\",\"bridge near me\",\"overpass near\",\"rooftop near\"]" } // ── Matching helpers (single loops only — el escapes while-body mutation via diff --git a/soul.el b/soul.el index dbb4376..bf1253a 100644 --- a/soul.el +++ b/soul.el @@ -258,7 +258,7 @@ fn emit_session_start_event() -> Void { // L0 (core) → L1 (safety screen) → L2a (continuity + behavioral profiling) → L2b (mission alignment) → L3 (imprint) → L1 (safety validate) // Internal cognition (heartbeat, proactive, memory ops) bypasses layers — use one_cycle directly. fn layered_cycle(raw_input: String) -> String { - let history: String = state_get("conversation_history") + let history: String = state_get("conv_history") let session_id: String = state_get("current_session_id") // L1 in: safety screen