# Plan: Display Complete Observation Data in Viewer UI ## Current State Analysis ### What's Currently Shown (5 fields) - ✅ **type** - Displayed as chip/badge (e.g., "discovery", "bugfix") - ✅ **project** - Shown in card header - ✅ **title** - Main card title (shows "Untitled" if null) - ✅ **subtitle** - Optional subheading - ✅ **id + created_at** - Metadata line (e.g., "#1 • 2 hours ago") ### What's Hidden (10+ fields) - ❌ **narrative** - Detailed explanation text (MOST IMPORTANT) - ❌ **facts** - JSON array of key facts (structured bullet points) - ❌ **concepts** - JSON array of concept tags (e.g., "problem-solution", "gotcha") - ❌ **files_read** - JSON array of file paths that were read - ❌ **files_modified** - JSON array of file paths that were modified - ❌ **text** - Legacy unstructured text field (deprecated but still populated) - ❌ **prompt_number** - Which user prompt triggered this observation - ❌ **sdk_session_id** - Session identifier ### Database Schema (Actual Structure) ```sql observations table: - id (INTEGER PRIMARY KEY) - sdk_session_id (TEXT) - project (TEXT) - type (TEXT: decision, bugfix, feature, refactor, discovery, change) - created_at (TEXT ISO timestamp) - created_at_epoch (INTEGER milliseconds) - prompt_number (INTEGER nullable) - title (TEXT nullable) - subtitle (TEXT nullable) - narrative (TEXT nullable) -- Rich detailed explanation - text (TEXT nullable) -- Legacy field - facts (TEXT nullable) -- JSON array of key facts - concepts (TEXT nullable) -- JSON array of concept tags - files_read (TEXT nullable) -- JSON array of file paths - files_modified (TEXT nullable) -- JSON array of file paths ``` ### Issues Found 1. **Type Definition Mismatch**: Three different type definitions exist: - Actual database schema (most complete) - `worker-types.ts` Observation interface (flattened, has wrong field names) - `viewer/types.ts` Observation interface (minimal subset) 2. **Data Loss**: Rich fields are stored in DB but not transmitted to UI: - narrative, facts, files_read, files_modified all missing from API 3. **PaginationHelper Query Bug**: Selects non-existent fields: - `session_db_id` (should be `sdk_session_id`) - `claude_session_id` (doesn't exist in observations table) - `files` (should be `files_read` + `files_modified`) ## Proposed Implementation Plan ### Phase 1: Fix Data Layer #### 1.1 Update Viewer Type Definitions **File**: `src/ui/viewer/types.ts` ```typescript export interface Observation { id: number; sdk_session_id: string; project: string; type: string; title: string | null; subtitle: string | null; narrative: string | null; // NEW - detailed explanation text: string | null; // Legacy field facts: string | null; // NEW - JSON array of key facts concepts: string | null; // NEW - JSON array of concept tags files_read: string | null; // NEW - JSON array of file paths files_modified: string | null; // NEW - JSON array of file paths prompt_number: number | null; // NEW - which prompt triggered this created_at: string; created_at_epoch: number; } ``` #### 1.2 Fix PaginationHelper SQL Query **File**: `src/services/worker/PaginationHelper.ts` (around line 26) **Current (BROKEN)**: ```typescript const fields = 'id, session_db_id, claude_session_id, project, type, title, subtitle, text, concepts, files, prompt_number, created_at, created_at_epoch'; ``` **Fixed**: ```typescript const fields = 'id, sdk_session_id, project, type, title, subtitle, narrative, text, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch'; ``` #### 1.3 Update Worker Service v2 Response Mapping **File**: `src/services/worker-service-v2.ts` Ensure the `/api/observations` endpoint properly maps all fields from database to response. May need to parse JSON fields (facts, concepts, files_read, files_modified) if they're stored as JSON strings. ### Phase 2: Redesign UI Component #### 2.1 Update ObservationCard Component **File**: `src/ui/viewer/components/ObservationCard.tsx` **New Structure**: ``` ┌─────────────────────────────────────────┐ │ [type badge] [project] │ ← Header (always visible) ├─────────────────────────────────────────┤ │ Title │ ← Always visible │ Subtitle (if present) │ ← Always visible │ #123 • 2 hours ago [▼ More]│ ← Metadata + Expand button ├─────────────────────────────────────────┤ │ │ │ ┌─ EXPANDED CONTENT (when opened) ───┐ │ │ │ │ │ │ │ 📝 Narrative │ │ │ │ ─────────────────────────────────── │ │ │ │ Detailed explanation text... │ │ │ │ │ │ │ │ 📌 Key Facts │ │ │ │ ─────────────────────────────────── │ │ │ │ • Fact 1 │ │ │ │ • Fact 2 │ │ │ │ • Fact 3 │ │ │ │ │ │ │ │ 🏷️ Concepts │ │ │ │ ─────────────────────────────────── │ │ │ │ [problem-solution] [discovery] │ │ │ │ │ │ │ │ 📁 Files │ │ │ │ ─────────────────────────────────── │ │ │ │ 📖 Read: │ │ │ │ src/hooks/save-hook.ts │ │ │ │ src/services/worker.ts │ │ │ │ ✏️ Modified: │ │ │ │ src/hooks/save-hook.ts │ │ │ │ │ │ │ │ 🔗 Session Info │ │ │ │ ─────────────────────────────────── │ │ │ │ Prompt #5 • Session: abc123... │ │ │ │ │ │ │ └─────────────────────────────────────┘ │ └─────────────────────────────────────────┘ ``` **Component Logic**: ```typescript const ObservationCard = ({ observation }) => { const [isExpanded, setIsExpanded] = useState(false); // Parse JSON fields const facts = observation.facts ? JSON.parse(observation.facts) : []; const concepts = observation.concepts ? JSON.parse(observation.concepts) : []; const filesRead = observation.files_read ? JSON.parse(observation.files_read) : []; const filesModified = observation.files_modified ? JSON.parse(observation.files_modified) : []; return (