Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
node_modules/
dist/
.env.local
__pycache__/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep local Vite env files ignored

Removing .env.local from the ignore list makes developer-local frontend overrides trackable again; Vite projects commonly use .env.local for machine-specific URLs or secrets, and this repo’s frontend setup already relies on env files for WebSocket configuration. If a teammate recreates or runs the frontend with local overrides, those values can now be accidentally committed, so this ignore entry should stay even if the tracked frontend .env is removed.

Useful? React with 👍 / 👎.

*.pyc
Comment on lines 1 to 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep npm outputs out of git

The setup docs still instruct teammates to run npm install and npm run dev from signal/frontend; after deleting the node_modules/ and dist/ ignore rules, the next local install or Vite build can be swept into git add . as thousands of dependency or generated files. Keep these ignore patterns unless the repo is intentionally abandoning the frontend workflow everywhere.

Useful? React with 👍 / 👎.

*.pyo

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep local Vite env files ignored

Removing .env.local from the ignore list makes developer-local frontend overrides trackable again; Vite projects commonly use .env.local for machine-specific URLs or secrets, and this repo’s frontend setup already relies on env files for WebSocket configuration. If a teammate recreates or runs the frontend with local overrides, those values can now be accidentally committed, so this ignore entry should stay even if the tracked frontend .env is removed.

Useful? React with 👍 / 👎.

Expand Down
99 changes: 0 additions & 99 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,104 +1,5 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project: SIGNAL

Human-in-the-loop emergency dispatch support system for wildfire surge events. Four AI agents (MONITOR, TRIAGE, RESOURCE, RELAY) assist a 911 dispatcher — never callers. This is a HackDavis 2026 project.

**This session is Person 2 — frontend owner.** Responsible for all GitHub issues labeled `[Frontend]` (issues #9–15 in `aadityad12/HackDavis26`).

## Commands

```bash
# Frontend (Person 2's domain)
cd signal/frontend && npm install
npm run dev # http://localhost:5173
npm run build # tsc -b && vite build

# Backend (Person 1's domain — must be running for WS/API)
cd signal/backend && uv sync
uvicorn main:app --reload --port 8000
```

## Shared Contract — Do Not Deviate

| Concern | Value |
|---|---|
| Backend port | `8000` |
| Frontend port | `5173` |
| WebSocket path | `/ws` |
| API proxy | Vite proxies `/api/*` → `http://localhost:8000` (strips `/api` prefix) |
| WS env var | `VITE_WS_URL=ws://localhost:8000/ws` in `signal/frontend/.env` |

**Enum values** (exact strings — backend and frontend must match):
- Mode: `ASSISTED` | `SURGE`
- Severity: `CRITICAL` | `URGENT` | `STANDARD` | `PENDING`
- Agent names: `MONITOR` | `TRIAGE` | `RESOURCE` | `RELAY`
- Agent status: `IDLE` | `RUNNING` | `COMPLETE` | `ERROR`
- Heavy asset types: `air_tanker` | `heavy_rescue` | `hazmat`

**WebSocket messages** (backend → frontend):
```
MODE_CHANGE { mode, timestamp }
CALL_ADDED { id, severity, zone, vulnerable, incident_type }
AGENT_STATUS { agent, status, last_action }
UNIT_DISPATCHED { call_id, unit_id, eta_minutes }
HOLD_REQUIRED { call_id, unit_id, asset_type, hold_id }
HOLD_RESOLVED { hold_id, action: "CONFIRMED"|"CANCELLED" }
BRIEFING_READY { call_id, text, audio_url }
INCIDENT_REPORT { call_id, report }
```

**REST endpoints** (frontend calls via `/api` proxy):
```
POST /api/override
POST /api/confirm-hold body: { hold_id }
POST /api/cancel-hold body: { hold_id }
POST /api/demo/start
POST /api/demo/trigger-surge
POST /api/demo/reset
```

## Frontend Architecture

**Stack**: React 18 + Vite 6 + TypeScript 5 + Tailwind 3 + Leaflet 1.9 (vanilla, not react-leaflet)

**State flow**: `useWebSocket` hook → dispatches `Action` → `useReducer(reducer, initialState)` in `App.tsx` → props to components. The reducer (`src/store/reducer.ts`) is pure — no side effects. All WS message handling lives there.

**Layout**: Full-viewport flex column — `ModeIndicator` (fixed top banner) → 3-column grid (CallQueue | MapView | AgentCards+BriefingPanel) → `AuditTrail` (collapsible bottom) → `DemoControls` (fixed bottom bar). `HoldModal` is a `z-50` fullscreen overlay when `activeHold !== null`. `OverrideButton` is fixed-position, only visible in SURGE mode.

**Visual design**: No dark mode, no gradients, no heavy shadows. Background `#F8FAFC`, panels white with `border border-slate-200`. Primary blue `#1D4ED8`, SURGE red `#DC2626`. Font: Inter. Monospace only for IDs and timestamps.

## Implementation Gotchas

- **Leaflet CSS**: import `leaflet/dist/leaflet.css` in `src/index.css`, not in the component — marker icons break otherwise.
- **Leaflet map height**: container div must have `style={{ height: '400px' }}` or the map won't render.
- **Leaflet double-init**: clean up the map instance on unmount in the `useEffect` return.
- **Audio autoplay**: browsers block `audio.play()` without prior user interaction — wrap in `try/catch` and show a "Click to play briefing" fallback button.
- **`CALL_ADDED` deduplication**: this message fires twice per call (once as `PENDING`, once with real severity). The reducer deduplicates by `id` — components just render `state.calls`.
- **HoldModal**: no close-on-backdrop-click — dispatcher must explicitly confirm or cancel.
- **WS reconnect**: `useWebSocket` retries every 3s automatically. `ModeIndicator` shows connection status.

## Demo Flow (for judges)

Reset → Start Demo (2 normal calls) → Trigger Surge (SURGE banner + 4 auto-triaged calls) → ElevenLabs voice briefing (or text fallback) → HOLD modal on heavy asset → Override → show Audit Trail.

## GitHub Issues Ownership

All `[Frontend]` issues (#9–15) in `aadityad12/HackDavis26`:
- #9 Project scaffold (Vite + React + Tailwind + types + reducer)
- #10 WebSocket hook with auto-reconnect
- #11 ModeIndicator and AgentCards
- #12 CallQueue
- #13 MapView (Leaflet + Park Fire perimeter)
- #14 OverrideButton and HoldModal
- #15 BriefingPanel, AuditTrail, DemoControls

## Agents & Skills Available

- `Ubiquitous` agent: run whenever new technology or domain terms are introduced — extracts DDD-style glossary to `UBIQUITOUS_LANGUAGE.md`
- `grill-me` skill (`/grill-me`): stress-test a plan or design before implementing
This file provides guidance to Claude Code (claude.ai/code) when working in this repository.

## Project: SIGNAL
Expand Down
157 changes: 0 additions & 157 deletions UBIQUITOUS_LANGUAGE.md
Original file line number Diff line number Diff line change
@@ -1,162 +1,5 @@
# Ubiquitous Language — SIGNAL

A human-in-the-loop emergency dispatch support system for wildfire surge events. The AI never speaks to callers — only to the dispatcher. This glossary formalizes domain terminology used across backend, frontend, and integration layers.

---

## System Modes

| Term | Definition | Aliases to avoid |
| ----------- | --------------------------------------------------------------------------------------------- | ------------------------ |
| **ASSISTED** | Normal operating mode in which the dispatcher is in full control and AI agents support | Manual, normal, default |
| **SURGE** | High-volume crisis mode activated when incoming call rate exceeds the SURGE_THRESHOLD | Overload, emergency mode |

---

## Actors

| Term | Definition | Aliases to avoid |
| --------------- | --------------------------------------------------------------------------- | ------------------- |
| **Dispatcher** | The human 911 operator; sole decision-maker; never bypassed by the AI | User, operator |
| **Caller** | A person in crisis placing a 911 call; AI never communicates with them | Requester, victim |
| **AI Agent** | One of four named intelligent systems assisting the dispatcher | Agent module, bot |

---

## AI Agents

Each agent performs a distinct role in the dispatch workflow.

| Term | Definition | Aliases to avoid |
| ------------- | ---------------------------------------------------------------- | ------------------- |
| **MONITOR** | Watches incoming call volume; triggers SURGE mode when threshold | Call tracker |
| **TRIAGE** | Classifies incident severity (CRITICAL, URGENT, STANDARD) | Classifier |
| **RESOURCE** | Allocates and dispatches response units; enforces HOLD protocol | Dispatcher agent |
| **RELAY** | Generates dispatcher briefings via TTS or text; summarizes calls | Briefing generator |

---

## Call & Incident

| Term | Definition | Aliases to avoid |
| ----------------- | ------------------------------------------------------------------------------------------------- | ---------------------- |
| **Call** | An incoming 911 request from a caller; immutable identifier for the entire incident lifecycle | Request, ticket |
| **Incident** | The emergency situation described by a call (e.g., wildfire, structure fire) | Event, emergency |
| **Severity** | The classified priority level of a call; one of CRITICAL, URGENT, STANDARD, or transient PENDING | Priority, classification |
| **CRITICAL** | Most urgent severity; immediate life-safety threat | High, red |
| **URGENT** | Severe but not immediate life-safety threat | Medium, orange |
| **STANDARD** | Lower urgency or routine incident | Low, green |
| **PENDING** | Transient severity state assigned immediately upon call intake; replaced by TRIAGE classification | Unclassified, unknown |
| **Incident Type** | The category of emergency (e.g., structure fire, vegetation fire, medical, hazmat) | Event type, category |
| **Zone** | Geographic area or district where the incident is located | Region, area, sector |
| **Vulnerable** | Boolean flag indicating the caller is a vulnerable individual (elderly, disabled, etc.) | Special needs, at-risk |

---

## Response Units & Dispatch

| Term | Definition | Aliases to avoid |
| ----------- | ---------------------------------------------------------------------------------- | --------------------- |
| **Unit** | A dispatched response resource (fire truck, tanker, rescue team, etc.) | Vehicle, resource |
| **Unit ID** | Unique identifier for a response unit | Vehicle ID, truck ID |
| **ETA** | Estimated time of arrival in minutes for a dispatched unit to reach the incident | Arrival time, time to scene |
| **Dispatch** | The act of assigning and sending a unit to a call | Send, assign |

---

## Protocol HOLD

The HOLD protocol prevents dangerous deployments without explicit human approval.

| Term | Definition | Aliases to avoid |
| ---------------- | ----------------------------------------------------------------------------- | ---------------------- |
| **HOLD** | A blocking state requiring dispatcher confirmation before deploying a heavy asset | Block, gate |
| **Hold Event** | A HOLD_REQUIRED message requesting dispatcher decision on a deployment | Hold request |
| **Heavy Asset** | Specialized or high-risk response unit (air_tanker, heavy_rescue, hazmat) | Restricted unit |
| **Confirm** | Dispatcher action approving a HOLD; permits unit dispatch | Approve |
| **Cancel** | Dispatcher action rejecting a HOLD; prevents unit dispatch | Reject, deny |

---

## Briefing

| Term | Definition | Aliases to avoid |
| ----------------- | --------------------------------------------------------------------------- | ---------------------- |
| **Briefing** | A summary of a call generated by RELAY agent for the dispatcher | Summary, overview |
| **Briefing Text** | Human-readable text form of a briefing | Text summary |
| **Audio Briefing** | Briefing rendered as spoken audio via ElevenLabs TTS; optional, text fallback | Voice briefing, TTS |

---

## Audit & Observability

| Term | Definition | Aliases to avoid |
| ----------------- | --------------------------------------------------------------------------------------- | ---------------------- |
| **Audit Entry** | A timestamped record of a system event (mode change, call added, agent status, hold, etc.) | Log entry, event log |
| **Audit Log** | Chronologically ordered list of all audit entries; immutable append-only log | System log |
| **Override** | Dispatcher action to forcibly return from SURGE to ASSISTED mode | Cancel surge, reset |

---

## Technical Terms with Domain Meaning

| Term | Definition | Aliases to avoid |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| **Agent Status** | Current state of an AI agent: IDLE (ready), RUNNING (active), COMPLETE (finished), or ERROR (failed) | State, condition |
| **WebSocket Message** | Real-time event pushed from backend to frontend via `/ws` connection; carries call, agent, hold, mode, or briefing data | Event, frame |
| **Mode Change** | A WebSocket event indicating transition between ASSISTED and SURGE modes | Mode switch |
| **SURGE_THRESHOLD** | Environment variable controlling call rate (calls/min) at which SURGE mode activates; default 10 | Threshold value |

---

## Relationships

- A **Call** is placed by a **Caller** and received by a **Dispatcher**.
- A **Call** has exactly one **Severity** (CRITICAL, URGENT, STANDARD, or PENDING).
- **TRIAGE** replaces PENDING severity with a final classification (CRITICAL, URGENT, or STANDARD).
- **RESOURCE** may dispatch a **Unit** to a **Call**, generating an ETA.
- A **Unit** deployment may trigger a **HOLD** if it is a **Heavy Asset**.
- A **Dispatcher** must **Confirm** or **Cancel** a **HOLD** before the **Unit** can be dispatched.
- **RELAY** generates a **Briefing** (text or audio) for each **Call**, viewed by the **Dispatcher**.
- **MONITOR** triggers transition from **ASSISTED** to **SURGE** when call volume exceeds **SURGE_THRESHOLD**.
- **Dispatcher** can issue an **Override** to return from **SURGE** to **ASSISTED**.
- Every action is recorded as an **Audit Entry** in the immutable **Audit Log**.

---

## Example Dialogue

> **Frontend Dev:** "When a caller places a call, what severity do we show them?"
>
> **Domain Expert:** "We show nothing to the caller. The dispatcher receives the **Call** immediately with severity PENDING. TRIAGE classifies it within seconds to CRITICAL, URGENT, or STANDARD."
>
> **Frontend Dev:** "So if a **Call** comes in during **SURGE** mode with a **Heavy Asset** request, what happens?"
>
> **Domain Expert:** "RESOURCE detects the **Heavy Asset** type and emits a **HOLD_REQUIRED** message. The dispatcher sees the **Hold** modal with the **Call** details and must explicitly **Confirm** or **Cancel** before dispatch. If they **Confirm**, the **Unit** is dispatched with an ETA. If they **Cancel**, the **Unit** never moves."
>
> **Frontend Dev:** "And if the dispatcher wants to exit **SURGE** mode while there are active **Holds**?"
>
> **Domain Expert:** "They issue an **Override**. The system returns to **ASSISTED** mode immediately. Any pending **Holds** remain until the dispatcher resolves them — the mode change doesn't auto-cancel deployments. Every action, including the **Override**, is logged as an **Audit Entry** with a timestamp."
>
> **Frontend Dev:** "Got it. So the **Dispatcher** is always the bottleneck for critical decisions, and the **Audit Log** records every turn."
>
> **Domain Expert:** "Exactly. The **AI Agents** advise, but the **Dispatcher** decides. That's the core safety constraint: the AI never speaks to the **Caller**, only to the **Dispatcher**."

---

## Flagged Ambiguities

**None identified.** The terminology is internally consistent across codebase, PRD, and team specification. All synonyms (e.g., "caller" vs. "requester") have been consolidated into canonical terms. The PENDING severity state is correctly recognized as transient, not a final classification.

---

## Notes for Implementation

- **Enums** (Mode, Severity, AgentName, AgentStatus) are shared contracts across backend, frontend, and integration layers. Changes require all three to align.
- **WebSocket messages** are the source-of-truth for inter-service communication; never deviate from the canonical schema.
- **Heavy asset types** (air_tanker, heavy_rescue, hazmat) trigger HOLD protocol; new types must be added to the enum and the HOLD logic.
- **Dispatcher** is never bypassed by AI. Every HOLD, override, or critical decision requires human confirmation.
- **Audit Log** is append-only and immutable; timestamps use ISO8601 format.
## Operating Modes

| Term | Definition | Aliases to avoid |
Expand Down
1 change: 0 additions & 1 deletion signal/frontend/.env

This file was deleted.

14 changes: 0 additions & 14 deletions signal/frontend/index.html

This file was deleted.

Loading
Loading