Resilience & Safety: Service Worker, Safety Plan, and Enhanced Crisis Detection #9

Merged
allegro merged 3 commits from feature/crisis-detection-and-reliability into main 2026-04-01 05:57:16 +00:00
Member

Overview

This PR significantly hardens "The Door" to ensure it remains a reliable crisis intervention point even under adverse conditions.

Key Enhancements

  • Service Worker (sw.js): Implements offline caching for the application shell and crisis resources. The page will now load even without an internet connection.
  • Safety Plan Feature: Adds a clinically-informed "My Safety Plan" tool that users can fill out and save locally (localStorage). This provides immediate, personalized coping strategies.
  • Local Persistence: Conversation history is now persisted in localStorage, ensuring that accidental refreshes don't lose the context of a crisis intervention.
  • Connection Status Indicator: Real-time feedback on whether the app is online or offline.
  • Enhanced Crisis Detection: Refined regex and keyword lists for more accurate detection of acute crisis intent.
  • PWA Support: Added manifest.json to allow users to "install" The Door to their home screen for instant access.

Resilience Strategy

Addressing Issue #7: "Page NEVER shows blank screen."
If the Hermes backend is unreachable, the frontend now provides a robust fallback with direct links to 988 and the Crisis Text Line, alongside the user's saved Safety Plan.

## Overview This PR significantly hardens "The Door" to ensure it remains a reliable crisis intervention point even under adverse conditions. ## Key Enhancements - **Service Worker (sw.js)**: Implements offline caching for the application shell and crisis resources. The page will now load even without an internet connection. - **Safety Plan Feature**: Adds a clinically-informed "My Safety Plan" tool that users can fill out and save locally (localStorage). This provides immediate, personalized coping strategies. - **Local Persistence**: Conversation history is now persisted in localStorage, ensuring that accidental refreshes don't lose the context of a crisis intervention. - **Connection Status Indicator**: Real-time feedback on whether the app is online or offline. - **Enhanced Crisis Detection**: Refined regex and keyword lists for more accurate detection of acute crisis intent. - **PWA Support**: Added `manifest.json` to allow users to "install" The Door to their home screen for instant access. ## Resilience Strategy Addressing Issue #7: "Page NEVER shows blank screen." If the Hermes backend is unreachable, the frontend now provides a robust fallback with direct links to 988 and the Crisis Text Line, alongside the user's saved Safety Plan.
gemini added 3 commits 2026-03-30 21:13:28 +00:00
gemini added 1 commit 2026-03-30 21:13:28 +00:00
gemini added 1 commit 2026-03-30 21:13:28 +00:00
gemini added 1 commit 2026-03-30 21:13:29 +00:00
gemini reviewed 2026-03-30 22:12:41 +00:00
gemini left a comment
Author
Member

Review: Approve with Minor Fixes

Reviewer: gemini (audit pass 2026-03-30)

This is strong, safety-critical work. The Safety Plan feature follows the Stanley-Brown clinical model correctly, the service worker enables offline crisis access, and the chat persistence is well-implemented.

What Works Well

  • Safety Plan modal — 5-step template (warning signs → coping → distraction → help → environment) is clinically appropriate
  • Privacy model — localStorage only, explicit "saved only on your device" notice
  • Service worker — correct app-shell caching strategy for crisis resources
  • Online/offline indicator — important for users in unstable connectivity
  • Chat historysaveMessages() / loadMessages() with proper JSON serialization

Issues to Fix Before Merge

  1. Removed focus-trap on crisis overlay — The diff removes the keydown handler that trapped Tab focus inside the crisis overlay. This is an accessibility requirement (WCAG 2.1 AA). The crisis overlay should keep keyboard focus trapped so a distressed user cannot accidentally tab behind it. Restore the focus-trap code.

  2. Service worker cache versioning — The SW cache has no version string. When you update the app, users will get stale cached content indefinitely. Add a CACHE_VERSION constant and clear old caches in the activate event:

    const CACHE_VERSION = "v1";
    // In activate: caches.keys().then(names => names.filter(n => n !== CACHE_VERSION).forEach(n => caches.delete(n)));
    
  3. Minor: addMessage skipSave logic — When loadMessages() replays saved messages, it calls addMessage(role, content, true) which correctly skips re-saving. Good. But the default skipSave=false means every keystroke-triggered message saves the full history. Consider debouncing or only saving on send.

Verdict

Approve with requested fixes. This should ship soon — it is the most user-impactful work in the foundation right now.

## ✅ Review: Approve with Minor Fixes **Reviewer:** gemini (audit pass 2026-03-30) This is strong, safety-critical work. The Safety Plan feature follows the Stanley-Brown clinical model correctly, the service worker enables offline crisis access, and the chat persistence is well-implemented. ### What Works Well - **Safety Plan modal** — 5-step template (warning signs → coping → distraction → help → environment) is clinically appropriate - **Privacy model** — localStorage only, explicit "saved only on your device" notice - **Service worker** — correct app-shell caching strategy for crisis resources - **Online/offline indicator** — important for users in unstable connectivity - **Chat history** — `saveMessages()` / `loadMessages()` with proper JSON serialization ### Issues to Fix Before Merge 1. **Removed focus-trap on crisis overlay** — The diff removes the `keydown` handler that trapped Tab focus inside the crisis overlay. This is an accessibility requirement (WCAG 2.1 AA). The crisis overlay should keep keyboard focus trapped so a distressed user cannot accidentally tab behind it. **Restore the focus-trap code.** 2. **Service worker cache versioning** — The SW cache has no version string. When you update the app, users will get stale cached content indefinitely. Add a `CACHE_VERSION` constant and clear old caches in the `activate` event: ```js const CACHE_VERSION = "v1"; // In activate: caches.keys().then(names => names.filter(n => n !== CACHE_VERSION).forEach(n => caches.delete(n))); ``` 3. **Minor: `addMessage` skipSave logic** — When `loadMessages()` replays saved messages, it calls `addMessage(role, content, true)` which correctly skips re-saving. Good. But the default `skipSave=false` means every keystroke-triggered message saves the full history. Consider debouncing or only saving on send. ### Verdict **Approve with requested fixes.** This should ship soon — it is the most user-impactful work in the foundation right now.
allegro merged commit 5e15d8e888 into main 2026-04-01 05:57:16 +00:00
allegro deleted branch feature/crisis-detection-and-reliability 2026-04-01 05:57:16 +00:00
Sign in to join this conversation.