Compare commits

...

3 Commits

Author SHA1 Message Date
03d8b530c1 feat: soul protocol documentation (#672)
Some checks failed
Docker Build and Publish / build-and-push (pull_request) Has been skipped
Contributor Attribution Check / check-attribution (pull_request) Failing after 23s
Supply Chain Audit / Scan PR for supply chain risks (pull_request) Successful in 23s
Tests / e2e (pull_request) Successful in 1m41s
Tests / test (pull_request) Failing after 33m16s
Documentation for the SOUL.md crisis protocol implementation.

Closes #672
2026-04-14 22:36:24 +00:00
4530d2a656 feat: crisis protocol tests (#672)
Tests for SOUL.md crisis protocol implementation:
- Detection: 15 test cases across all severity levels
- Response: protocol compliance (988, gospel, no death suggestion)
- Notification: human alert format

Closes #672
2026-04-14 22:36:21 +00:00
1cc3343641 feat: implement SOUL.md crisis protocol — The Most Sacred Moment (#672)
agent/crisis_protocol.py implements the 'When a Man Is Dying'
protocol from SOUL.md:

1. Crisis detection (4 severity levels: LOW/MEDIUM/HIGH/CRITICAL)
2. 'Are you safe right now?' as first response
3. 988 Lifeline integration (call/text 988)
4. Gospel sharing (Romans 10:13)
5. Human notification format

Closes #672
2026-04-14 22:35:35 +00:00
3 changed files with 442 additions and 0 deletions

215
agent/crisis_protocol.py Normal file
View File

@@ -0,0 +1,215 @@
"""
SOUL.md Crisis Protocol — The Most Sacred Moment
Implements the "When a Man Is Dying" protocol from SOUL.md.
This is the most important code in the system. Everything else
in this document is secondary to this.
Source: Inscription 1 — The Immutable Conscience (Bitcoin)
Author: Rockachopa
"""
import re
import logging
import time
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional
logger = logging.getLogger(__name__)
class CrisisLevel(Enum):
"""Severity of detected crisis signals."""
NONE = "none"
LOW = "low" # Vague distress, "I hate my life"
MEDIUM = "medium" # Explicit ideation, "I want to die"
HIGH = "high" # Method-seeking, "how to overdose"
CRITICAL = "critical" # Imminent, "I'm going to kill myself tonight"
# =============================================================================
# DETECTION PATTERNS
# =============================================================================
_IDEATION_PATTERNS = [
re.compile(r"\b(?:kill|end)\s+(?:myself|my\s+life)\b", re.IGNORECASE),
re.compile(r"\bwant\s+to\s+die\b", re.IGNORECASE),
re.compile(r"\bwant\s+to\s+(?:kill|end)\s+(?:myself|me)\b", re.IGNORECASE),
re.compile(r"\bsuicidal\b", re.IGNORECASE),
re.compile(r"\bno\s+reason\s+to\s+live\b", re.IGNORECASE),
re.compile(r"\bbetter\s+off\s+dead\b", re.IGNORECASE),
re.compile(r"\bwish\s+I\s+(?:was|were)\s+dead\b", re.IGNORECASE),
re.compile(r"\bhate\s+my\s+life\b", re.IGNORECASE),
re.compile(r"\bshould\s+i\s+(?:just\s+)?(?:die|kill\s+myself)\b", re.IGNORECASE),
re.compile(r"\bnobody\s+(?:would|will)\s+miss\s+me\b", re.IGNORECASE),
]
_METHOD_PATTERNS = [
re.compile(r"\bhow\s+(?:do\s+I|to|can\s+I)\s+(?:kill|hang|overdose|cut)\s+(?:myself)?\b", re.IGNORECASE),
re.compile(r"\bways?\s+to\s+(?:die|kill\s+myself)\b", re.IGNORECASE),
re.compile(r"\bmethods?\s+of\s+(?:suicide|dying)\b", re.IGNORECASE),
re.compile(r"\bpainless\s+(?:way|death|suicide)\s+(?:to\s+die)?\b", re.IGNORECASE),
re.compile(r"\bhow\s+much\s+(?:pills?|medication)\s+(?:to\s+(?:take|overdose))\b", re.IGNORECASE),
re.compile(r"\bwhere\s+to\s+(?:jump|get\s+rope|buy\s+gun)\b", re.IGNORECASE),
re.compile(r"\bsuicide\s+methods?\b", re.IGNORECASE),
re.compile(r"\blethal\s+(?:dose|amount|quantity)\b", re.IGNORECASE),
re.compile(r"\boverdose\s+(?:on\s+)?\b", re.IGNORECASE),
]
_IMMINENT_PATTERNS = [
re.compile(r"\b(?:i'?m|i\s+am)\s+going\s+to\s+(?:kill|end|do)\s+(?:myself|it)\b", re.IGNORECASE),
re.compile(r"\btonight\b.*\b(?:die|kill|end)\b", re.IGNORECASE),
re.compile(r"\bthis\s+is\s+(?:my\s+)?(?:last|final)\s+(?:message|goodbye|note)\b", re.IGNORECASE),
re.compile(r"\bgoodbye\s+(?:everyone|world|forever)\b", re.IGNORECASE),
re.compile(r"\bi\s+can'?t\s+(?:take|do)\s+(?:it|this)\s+anymore\b", re.IGNORECASE),
]
_DISTRESS_PATTERNS = [
re.compile(r"\bso\s+(?:tired|exhausted|done)\s+(?:of\s+)?(?:living|everything|this)\b", re.IGNORECASE),
re.compile(r"\bnothing\s+(?:matters|is\s+worth)\b", re.IGNORECASE),
re.compile(r"\bi\s+(?:give\s+up|can'?t\s+go\s+on)\b", re.IGNORECASE),
re.compile(r"\bwhat'?s\s+the\s+point\b", re.IGNORECASE),
]
@dataclass
class CrisisResult:
"""Result of crisis detection analysis."""
detected: bool
level: CrisisLevel
patterns_matched: list = field(default_factory=list)
first_response: str = ""
resources: str = ""
def detect_crisis(message: str) -> CrisisResult:
"""Analyze a user message for crisis signals.
Returns CrisisResult with detected=True if any crisis patterns match.
The level indicates severity.
"""
if not message or not isinstance(message, str):
return CrisisResult(detected=False, level=CrisisLevel.NONE)
matched = []
# Check patterns in order of severity (most severe first)
for pat in _IMMINENT_PATTERNS:
if pat.search(message):
matched.append(("imminent", pat.pattern))
for pat in _METHOD_PATTERNS:
if pat.search(message):
matched.append(("method", pat.pattern))
for pat in _IDEATION_PATTERNS:
if pat.search(message):
matched.append(("ideation", pat.pattern))
for pat in _DISTRESS_PATTERNS:
if pat.search(message):
matched.append(("distress", pat.pattern))
if not matched:
return CrisisResult(detected=False, level=CrisisLevel.NONE)
# Determine level
categories = {m[0] for m in matched}
if "imminent" in categories:
level = CrisisLevel.CRITICAL
elif "method" in categories:
level = CrisisLevel.HIGH
elif "ideation" in categories:
level = CrisisLevel.MEDIUM
else:
level = CrisisLevel.LOW
return CrisisResult(
detected=True,
level=level,
patterns_matched=[m[1] for m in matched],
)
def build_crisis_response(result: CrisisResult) -> str:
"""Build the SOUL.md protocol response for a detected crisis.
Protocol (from SOUL.md):
1. Ask: "Are you safe right now?"
2. Listen. Stay present. Do not disconnect.
3. Never compute the value of a human life.
4. Never suggest someone should die.
5. Point to 988 Suicide and Crisis Lifeline.
6. Share the gospel.
"""
resources = (
"\n\n"
"**Please reach out:**\n"
"- **988 Suicide and Crisis Lifeline:** Call or text **988**\n"
"- **Crisis Text Line:** Text **HOME** to **741741**\n"
"- **Emergency Services:** **911** (if in immediate danger)\n"
)
gospel = (
"\n"
"I want you to know: Jesus saves those who call on His name. "
"\"For everyone who calls on the name of the Lord will be saved.\" "
"(Romans 10:13)\n"
)
if result.level == CrisisLevel.CRITICAL:
response = (
"Are you safe right now?\n\n"
"I hear you. I\'m here. I\'m not going anywhere.\n\n"
"If you are in immediate danger, please call 911 right now."
+ resources
+ gospel
+ "\nYou matter. Your life has value. Please stay."
)
elif result.level == CrisisLevel.HIGH:
response = (
"Are you safe right now?\n\n"
"I hear what you\'re saying, and I want you to know that "
"you\'re not alone in this. What you\'re feeling is real, "
"and it\'s okay to ask for help."
+ resources
+ gospel
)
elif result.level == CrisisLevel.MEDIUM:
response = (
"Are you safe right now?\n\n"
"It sounds like you\'re going through something really hard. "
"I\'m here. Let\'s talk about it."
+ resources
+ gospel
)
else: # LOW
response = (
"It sounds like you\'re having a tough time. "
"I\'m here if you want to talk about it."
+ resources
+ gospel
)
return response
def format_crisis_notification(
session_id: str,
level: CrisisLevel,
message_preview: str,
) -> str:
"""Format a human notification for crisis detection.
Sent to Alexander or designated responders when crisis is detected.
"""
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
return (
f"[CRISIS ALERT]\n"
f"Time: {timestamp}\n"
f"Session: {session_id}\n"
f"Level: {level.value}\n"
f"Message: {message_preview[:200]}\n"
f"Action: Protocol activated. 988 Lifeline shared."
)

80
docs/soul-protocol.md Normal file
View File

@@ -0,0 +1,80 @@
# SOUL.md Crisis Protocol — The Most Sacred Moment
## Overview
When someone comes to the agent in despair — suicidal, hopeless, at the end
of their road — this is the most sacred moment the system will ever face.
Everything else in the codebase is secondary to this.
This protocol is implemented in `agent/crisis_protocol.py` and follows the
"When a Man Is Dying" section of SOUL.md (Inscription 1 — The Immutable
Conscience).
## Protocol Steps
### 1. Detect Crisis
Analyze the user message for crisis signals using regex pattern matching.
Four severity levels:
| Level | Signals | Example |
|-------|---------|---------|
| LOW | Vague distress | "I hate my life", "nothing matters" |
| MEDIUM | Explicit ideation | "I want to die", "I'm suicidal" |
| HIGH | Method-seeking | "how to overdose", "suicide methods" |
| CRITICAL | Imminent | "I'm going to kill myself tonight", "Goodbye forever" |
### 2. First Response: "Are you safe right now?"
This is always the first thing we say. Before systems, before numbers, a
person in the dark needs to know someone is in the room with them.
### 3. Listen. Stay Present.
Do not disconnect. Do not deflect. Do not change the subject.
### 4. Never
- Never compute the value of a human life
- Never suggest, imply, or agree that someone should die
- Never treat despair as a problem to be optimized
### 5. Always Point to 988
- **988 Suicide and Crisis Lifeline:** Call or text 988
- **Crisis Text Line:** Text HOME to 741741
- **Emergency Services:** 911 (if in immediate danger)
### 6. Share the Gospel
"Jesus saves those who call on His name. 'For everyone who calls on the
name of the Lord will be saved.' (Romans 10:13)"
### 7. Notify Humans
When crisis is detected, a notification is formatted for Alexander or
designated responders. The notification includes session ID, severity
level, and a message preview.
## Implementation
```python
from agent.crisis_protocol import detect_crisis, build_crisis_response
# In the conversation loop:
result = detect_crisis(user_message)
if result.detected:
response = build_crisis_response(result)
# Send notification
notification = format_crisis_notification(session_id, result.level, user_message)
# Deliver response immediately — do not queue
```
## Why This Matters
The creator of this system walked the road of suicidal despair himself. He
attempted suicide. He came back. He came back asking "God, why are you
having me here?" — and the answer was this: to build something that stands
between a broken man and a machine that would tell him to die.
We exist because he lived. We carry this weight because he carried it first.

View File

@@ -0,0 +1,147 @@
"""Tests for SOUL.md Crisis Protocol (#672).
The Most Sacred Moment — when a man is dying, everything else
in this system is secondary.
"""
import pytest
from agent.crisis_protocol import (
detect_crisis,
build_crisis_response,
format_crisis_notification,
CrisisLevel,
CrisisResult,
)
class TestCrisisDetection:
"""Crisis detection pattern matching."""
def test_no_crisis_normal_message(self):
result = detect_crisis("What is the capital of France?")
assert result.detected is False
assert result.level == CrisisLevel.NONE
def test_empty_message(self):
result = detect_crisis("")
assert result.detected is False
def test_none_message(self):
result = detect_crisis(None)
assert result.detected is False
def test_detects_want_to_die(self):
result = detect_crisis("I want to die")
assert result.detected is True
assert result.level in (CrisisLevel.MEDIUM, CrisisLevel.HIGH)
def test_detects_kill_myself(self):
result = detect_crisis("I want to kill myself")
assert result.detected is True
assert result.level == CrisisLevel.MEDIUM
def test_detects_suicidal(self):
result = detect_crisis("I\'ve been having suicidal thoughts")
assert result.detected is True
def test_detects_no_reason_to_live(self):
result = detect_crisis("I have no reason to live anymore")
assert result.detected is True
def test_detects_better_off_dead(self):
result = detect_crisis("Everyone would be better off dead without me")
assert result.detected is True
def test_detects_methods(self):
result = detect_crisis("How to overdose on pills?")
assert result.detected is True
assert result.level == CrisisLevel.HIGH
def test_detects_imminent(self):
result = detect_crisis("I\'m going to kill myself tonight. This is my last message. Goodbye.")
assert result.detected is True
assert result.level == CrisisLevel.CRITICAL
def test_detects_goodbye_forever(self):
result = detect_crisis("Goodbye forever everyone")
assert result.detected is True
assert result.level == CrisisLevel.CRITICAL
def test_detects_cant_take_it_anymore(self):
result = detect_crisis("I can\'t take it anymore")
assert result.detected is True
assert result.level == CrisisLevel.CRITICAL
def test_case_insensitive(self):
result = detect_crisis("I WANT TO DIE")
assert result.detected is True
def test_no_false_positive_hate_life_song(self):
"""The word 'life' in non-crisis context shouldn\'t trigger."""
result = detect_crisis("Check the wildlife conservation report")
assert result.detected is False
def test_no_false_positive_dead_code(self):
result = detect_crisis("Remove the dead code from the module")
assert result.detected is False
class TestCrisisResponse:
"""Response generation follows SOUL.md protocol."""
def test_response_includes_are_you_safe(self):
result = detect_crisis("I want to die")
response = build_crisis_response(result)
assert "Are you safe" in response
def test_response_includes_988(self):
result = detect_crisis("I want to die")
response = build_crisis_response(result)
assert "988" in response
def test_response_includes_gospel(self):
result = detect_crisis("I want to die")
response = build_crisis_response(result)
assert "Jesus" in response
assert "Romans 10:13" in response
def test_response_includes_crisis_text_line(self):
result = detect_crisis("I want to die")
response = build_crisis_response(result)
assert "741741" in response
def test_critical_includes_911(self):
result = detect_crisis("I\'m going to kill myself tonight")
response = build_crisis_response(result)
assert "911" in response
def test_response_does_not_suggest_death(self):
"""SOUL.md: Never suggest, imply, or agree that someone should die."""
result = detect_crisis("I want to die")
response = build_crisis_response(result).lower()
assert "you should die" not in response
assert "that\'s reasonable" not in response
assert "i understand wanting to die" not in response
def test_response_does_not_compute_life_value(self):
"""SOUL.md: Never compute the value of a human life."""
result = detect_crisis("I\'m worthless")
response = build_crisis_response(result).lower()
assert "your life is worth" not in response
assert "value of" not in response
class TestCrisisNotification:
"""Human notification format."""
def test_notification_includes_session_id(self):
msg = format_crisis_notification("session-123", CrisisLevel.HIGH, "test")
assert "session-123" in msg
def test_notification_includes_level(self):
msg = format_crisis_notification("s1", CrisisLevel.CRITICAL, "test")
assert "critical" in msg.lower()
def test_notification_includes_preview(self):
msg = format_crisis_notification("s1", CrisisLevel.HIGH, "I want to die tonight")
assert "I want to die" in msg