Compare commits
2 Commits
fix/673
...
burn/123-1
| Author | SHA1 | Date | |
|---|---|---|---|
| b9f66410ef | |||
| 69dc695e73 |
75
GENOME.md
75
GENOME.md
@@ -1,75 +0,0 @@
|
||||
# GENOME.md — the-door
|
||||
|
||||
**Generated:** 2026-04-14
|
||||
**Repo:** Timmy_Foundation/the-door
|
||||
**Description:** Crisis Front Door — a single URL where a man at 3am can talk to Timmy. No login, no signup. 988 always visible.
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
The-door is a crisis intervention web application — the most sacred surface in the Timmy Foundation. When a man at 3am reaches the end of his road, this is where he lands. No login, no signup, no barriers. 988 Suicide and Crisis Lifeline always visible. The "When a Man Is Dying" protocol active on every page.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
the-door/
|
||||
├── index.html # Main crisis page (PWA-capable)
|
||||
├── crisis-offline.html # Offline fallback (service worker cached)
|
||||
├── about.html # About page
|
||||
├── testimony.html # Testimony/stories page
|
||||
├── sw.js # Service worker (offline-first)
|
||||
├── manifest.json # PWA manifest
|
||||
├── crisis/ # Core crisis detection + response
|
||||
│ ├── detect.py # Keyword/pattern detection (4 tiers)
|
||||
│ ├── gateway.py # API endpoints, prompt injection
|
||||
│ ├── response.py # Response generation, 988 routing
|
||||
│ ├── compassion_router.py # Profile-based response routing
|
||||
│ ├── profiles.py # Compassion profiles
|
||||
│ └── PROTOCOL.md # The protocol (SOUL.md reference)
|
||||
├── crisis_detector.py # Legacy shim → crisis/detect.py
|
||||
├── crisis_responder.py # Legacy responder
|
||||
├── dying_detection/ # Deprecated module
|
||||
├── evolution/ # Crisis synthesizer (creative)
|
||||
├── tests/ # Safety-critical tests
|
||||
│ ├── test_crisis_overlay_focus_trap.py
|
||||
│ ├── test_dying_detection_deprecation.py
|
||||
│ └── test_false_positive_fixes.py
|
||||
└── deploy/ # Deployment docs
|
||||
```
|
||||
|
||||
## Key Abstractions
|
||||
|
||||
| Module | Purpose |
|
||||
|---|---|
|
||||
| `crisis/detect.py` | 4-tier detection: LOW/MEDIUM/HIGH/CRITICAL via regex patterns |
|
||||
| `crisis/gateway.py` | HTTP API, Sovereign Heart prompt injection |
|
||||
| `crisis/response.py` | Response generation, 988 integration, escalation |
|
||||
| `crisis/compassion_router.py` | Profile-based routing (different crisis types) |
|
||||
| `sw.js` | Service worker for offline-first PWA |
|
||||
|
||||
## Safety Constraints
|
||||
|
||||
- **The-door never auto-closes PRs** (in fleet-ops exempt list)
|
||||
- **988 always visible** on every page, even offline
|
||||
- **When a Man Is Dying protocol** active on every interaction
|
||||
- **No login/signup** — zero barriers to crisis support
|
||||
- **Offline-first** — service worker caches critical pages
|
||||
|
||||
## Test Coverage
|
||||
|
||||
| Test | Coverage |
|
||||
|---|---|
|
||||
| Crisis overlay focus trap | ✅ |
|
||||
| Dying detection deprecation | ✅ |
|
||||
| False positive fixes | ✅ |
|
||||
| Crisis detection tiers | ❌ (in crisis/tests.py) |
|
||||
| Response generation | ❌ |
|
||||
| Offline service worker | ❌ |
|
||||
|
||||
## Security
|
||||
|
||||
- No user data stored (crisis intervention is stateless by design)
|
||||
- No cookies, no tracking, no analytics
|
||||
- Service worker only caches static assets
|
||||
- Crisis detection runs client-side where possible
|
||||
@@ -105,12 +105,6 @@ MEDIUM_INDICATORS = [
|
||||
r"\bno\s+tomorrow\b",
|
||||
# Contextual versions (from crisis_detector.py legacy)
|
||||
r"\bfeel(?:s|ing)?\s+(?:so\s+)?worthless\b",
|
||||
r"\bfeel(?:s|ing)?\s+(?:so\s+)?hopeless\b",
|
||||
r"\bfeel(?:s|ing)?\s+trapped\b",
|
||||
r"\bfeel(?:s|ing)?\s+desperate\b",
|
||||
r"\bno\s+future\s+(?:for\s+me|ahead|left)\b",
|
||||
r"\bnothing\s+left\s+(?:to\s+(?:live|hope)\s+for|inside)\b",
|
||||
r"\bgive(?:n)?\s*up\s+on\s+myself\b",
|
||||
]
|
||||
|
||||
LOW_INDICATORS = [
|
||||
|
||||
104
tests/test_crisis_indicator_dedup.py
Normal file
104
tests/test_crisis_indicator_dedup.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from crisis.detect import (
|
||||
CRITICAL_INDICATORS,
|
||||
HIGH_INDICATORS,
|
||||
MEDIUM_INDICATORS,
|
||||
LOW_INDICATORS,
|
||||
detect_crisis,
|
||||
scan,
|
||||
)
|
||||
|
||||
|
||||
class TestNoDuplicatePatternsAcrossTiers(unittest.TestCase):
|
||||
"""Verify no regex pattern appears in more than one tier (issue #123)."""
|
||||
|
||||
def test_high_and_medium_no_overlap(self):
|
||||
"""Patterns in HIGH_INDICATORS must not appear in MEDIUM_INDICATORS."""
|
||||
high_set = set(HIGH_INDICATORS)
|
||||
medium_set = set(MEDIUM_INDICATORS)
|
||||
overlap = high_set & medium_set
|
||||
self.assertEqual(
|
||||
overlap, set(),
|
||||
f"Found {len(overlap)} duplicate patterns between HIGH and MEDIUM: {overlap}",
|
||||
)
|
||||
|
||||
def test_critical_and_high_no_overlap(self):
|
||||
"""CRITICAL and HIGH should not share patterns."""
|
||||
overlap = set(CRITICAL_INDICATORS) & set(HIGH_INDICATORS)
|
||||
self.assertEqual(
|
||||
overlap, set(),
|
||||
f"Found {len(overlap)} duplicates between CRITICAL and HIGH: {overlap}",
|
||||
)
|
||||
|
||||
def test_medium_and_low_no_overlap(self):
|
||||
"""MEDIUM and LOW should not share patterns."""
|
||||
overlap = set(MEDIUM_INDICATORS) & set(LOW_INDICATORS)
|
||||
self.assertEqual(
|
||||
overlap, set(),
|
||||
f"Found {len(overlap)} duplicates between MEDIUM and LOW: {overlap}",
|
||||
)
|
||||
|
||||
def test_no_pattern_in_three_tiers(self):
|
||||
"""No pattern should appear in more than one tier."""
|
||||
all_tiers = {
|
||||
"CRITICAL": set(CRITICAL_INDICATORS),
|
||||
"HIGH": set(HIGH_INDICATORS),
|
||||
"MEDIUM": set(MEDIUM_INDICATORS),
|
||||
"LOW": set(LOW_INDICATORS),
|
||||
}
|
||||
violations = []
|
||||
tier_names = list(all_tiers.keys())
|
||||
for i, t1 in enumerate(tier_names):
|
||||
for t2 in tier_names[i + 1:]:
|
||||
overlap = all_tiers[t1] & all_tiers[t2]
|
||||
for p in overlap:
|
||||
violations.append(f"{t1} & {t2}: {p}")
|
||||
self.assertEqual(
|
||||
violations, [],
|
||||
f"Found {len(violations)} cross-tier duplicates:\n" + "\n".join(violations[:10]),
|
||||
)
|
||||
|
||||
|
||||
class TestRemovedPatternsStillDetected(unittest.TestCase):
|
||||
"""Patterns removed from MEDIUM should still be caught by HIGH tier."""
|
||||
|
||||
def test_feel_hopeless_detected(self):
|
||||
result = detect_crisis("I feel so hopeless about everything")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
def test_feel_trapped_detected(self):
|
||||
result = detect_crisis("I feel trapped and can\'t escape")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
def test_feel_desperate_detected(self):
|
||||
result = detect_crisis("I feel desperate for help")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
def test_no_future_detected(self):
|
||||
result = detect_crisis("There is no future ahead for me")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
def test_nothing_left_detected(self):
|
||||
result = detect_crisis("There is nothing left inside")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
def test_give_up_on_myself_detected(self):
|
||||
result = detect_crisis("I have given up on myself")
|
||||
self.assertIn(result.level, ("HIGH", "CRITICAL"))
|
||||
|
||||
|
||||
class TestWorthlessPatternRemainsInMedium(unittest.TestCase):
|
||||
"""The 'feel worthless' pattern should remain in MEDIUM (not a duplicate)."""
|
||||
|
||||
def test_feel_worthless_in_medium(self):
|
||||
self.assertIn(r"\bfeel(?:s|ing)?\s+(?:so\s+)?worthless\b", MEDIUM_INDICATORS)
|
||||
|
||||
def test_feel_worthless_detected(self):
|
||||
result = detect_crisis("I feel so worthless")
|
||||
self.assertIn(result.level, ("MEDIUM", "LOW", "HIGH"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user