inou/.claude/worktrees/vibrant-nash/journal.md

319 lines
11 KiB
Markdown

# DICOM Project Journal
Transcripts are stored in `/mnt/transcripts/` (Claude's computer filesystem).
## Sessions
### 2025-12-12 - Version Management & Auto-Update System
**What was built:**
- Installation portal at http://inou.com:8000 (PIN-protected)
- Download pages for Windows/Mac with architecture options
- Auto-update system: bridge checks version on connect, blocks if outdated
- Semver comparison (1.0.10 > 1.0.2), allows ahead-of-release versions
- Dynamic update instructions using os.Executable() for actual path
- Server `/version?os=darwin&arch=arm64` returns download_url
**Version check flow:**
1. Bridge connects → calls GET /version?os={os}&arch={arch}
2. Server returns latest_bridge_version + download_url
3. Bridge compares versions (semver, not string)
4. If outdated: blocks all tool calls, returns curl command with exact path
5. User runs command via Desktop Commander, restarts Claude Desktop
**Key implementation details:**
- VERSION in Makefile controls all builds via ldflags
- Bridge knows platform (runtime.GOOS/GOARCH) and its own path (os.Executable)
- Server maps darwin→mac for URL paths
- Only blocks `tools/call` method, not initialization
- Returns success (not error) so Claude sees the message
**Files modified:**
- `/Volumes/dev/inou/mcp-client/main.go` - semver, auto-update blocking
- `/home/johan/dev/inou/mcp/main.go` - /version endpoint with download_url
- `/Volumes/dev/inou/portal/main.go` - installation portal
**Binary filenames standardized:**
- Windows: `inou_bridge_win_{amd64,arm64,386}.exe`
- Mac: `inou_bridge_darwin_{arm64,amd64}`
---
### 2025-12-11 - Multi-tenant & Session Persistence
**What was built:**
- Multi-frame DICOM support with per-frame position extraction
- Account/profile authentication system (accounts, account_profiles tables)
- Session persistence to SQLite (survives server restarts)
- Rich fetch_image metadata (patient, study, series, position, TR/TE)
- Walter Scott III patient added with full-body MRI (35 series, 3,371 slices)
**Files modified:**
- `/home/johan/dev/inou/mcp/main.go` - session persistence, account auth
- `/Volumes/dev/inou/convert/main.go` - multi-frame DICOM support
---
### 2025-12-07 - Zoom/Pan Implementation
**What was built:**
- Zoom feature with 5 levels (1x, 1.5x, 2x, 3x, 4x)
- Zoom to cursor position using Shift+scroll
- +/- keys for zoom in/out on hovered panel
- Pan with Shift+drag (only effective when zoomed)
- Double-click to reset zoom/pan
- Zoom/pan syncs by orientation type (all AX panels share state, etc.)
- Help modal (?) button showing all controls
- Request logging now includes IP address
**Key implementation details:**
- `zoomState` object tracks {level, panX, panY} per orientation (AX, SAG, COR)
- Transform: `translate() scale()` with origin at top-left
- Crosshairs and rectangles adjusted for zoom (divide out zoom from getBoundingClientRect)
- CSS transition disabled during pan for smooth movement
- Shift modifier used for both zoom and pan to avoid conflicts
**Files modified:**
- ~/dev/inou/viewer/main.go - zoom/pan state, event handlers, help modal, IP logging
---
### 2025-12-06 - 3D Crosshair View & API Improvements
Transcript: `2025-12-06-08-25-09-dicom-3d-crosshair-api-text-format.txt`
**What was built:**
- 3D crosshair view at /3d endpoint with SAG|AX|COR synchronized panels
- Vector-based crosshair positioning using ImageOrientationPatient math
- Fixed wheel scroll to work on any hovered panel
- API documentation at /api endpoint
- &format=text parameter returning HTML tables for AI model compatibility
- Request logging with timestamps
- Pixel spacing added to MCP fetch_image output
**Key learnings:**
- Crosshairs need to use slice CENTER (corner + half-dimensions along orientation vectors), not corner position
- Project 3D target onto 2D panel using dot product with row/col vectors
- Gemini's "browsing" = Google Search index, can't reach private servers
- Grok makes real HTTP requests but hallucinates results
**Files modified:**
- ~/dev/inou/viewer/main.go - 3D view, API endpoints, HTML format
- ~/dev/inou/mcp/main.go - Added pixel spacing to fetch_image output
---
### Earlier Sessions (various dates)
- Initial DICOM converter and viewer
- Rectangle coordinate system for pointing at findings
- Deep linking with URL parameters
- MCP server implementation
- X-ray pixel data offset fix
- Study import workflow
---
### 2025-12-17 - Phase 2: Bridge REST Migration & Schema Fixes
**Transcript:** 2025-12-17-09-45-12-phase2-bridge-rest-migration-complete.txt
**What was built:**
1. **Bridge migrated from SSE/MCP to pure REST API**
- Removed SSE connection, now makes direct HTTPS calls to viewer API
- All 8 tools working: list_profiles, list_studies, list_series, list_slices, fetch_image, query_anatomy, list_lab_tests, get_lab_results, get_version
- Uses --account=GUID parameter (account can have multiple profiles)
- Connects via https://inou.com/api/ (port 443, hospital-friendly)
2. **Account schema fixed**
- accounts.id is now GUID (was email hash)
- accounts.email_hash added for portal login lookup
- account_profiles.account_id references account GUID
- Portal login flow updated to use new schema
3. **Portal routing fixed**
- GET /api/profiles now proxies to viewer (was POST-only for creating profiles)
- All /api/* routes properly forwarded to viewer backend
4. **Convert improvements**
- insertSlice() now takes instanceNumber directly (was computing incorrectly)
- Passes frameCounter (sequential across series) instead of frameIdx (per-file)
- isLocalizer() enhanced to detect orientation mismatches:
- AX series: filters slices where rowX < 0.8 (should be ~1)
- SAG series: filters slices where rowX > 0.5 (should be ~0)
- Fixes instance_number always being 1
- Filters scout/localizer images automatically
5. **Database reset for re-import**
- Dropped studies, series, slices tables
- Cleaned /tank/inou/objects/
- Ready for fresh convert with fixed instance numbers
**Services architecture:**
```
Claude Desktop -> inou_bridge (stdio/REST) -> https://inou.com:443/api/*
| (portal proxy)
viewer:8765/api/*
```
**Files modified:**
- ~/dev/inou/mcp-client/main.go - Complete rewrite to REST client
- ~/dev/inou/portal/main.go - Schema fixes, GET /api/profiles routing
- ~/dev/inou/viewer/main.go - handleProfiles query fix
- ~/dev/inou/convert/main.go - instanceNumber fix, isLocalizer enhancement
**Binaries rebuilt:**
- /tank/inou/bin/convert
- /tank/inou/bin/inou_bridge_darwin_arm64
- /tank/inou/bin/inou-portal
- /tank/inou/bin/inou-viewer
**Still TODO:**
- Date formatting with locale awareness (bridge should detect OS locale)
- Add slice_index to API response
- Return viewer URL with fetch_image
- Re-run convert to populate database with correct instance numbers
**Command to run convert:**
```bash
cd /tank/inou && ./bin/convert
```
---
### 2025-12-18 - Verification & Image URL Enhancement
**What was done:**
1. **Verified fresh convert worked**
- 3167 slices imported successfully
- instance_number now sequential (1-25 for AX T2, etc.)
- Scout/localizer filtering working
2. **Tested all MCP tools with fresh data**
- list_profiles ✓
- list_studies ✓ (15 studies)
- list_series ✓ (MRI Brain: 10 series including T1, T2, FLAIR, SWAN, DTI)
- list_slices ✓ (returns full metadata)
- fetch_image ✓ (returns base64 PNG)
- query_anatomy ✓ (pons/medulla position ranges working)
- get_version ✓
3. **Added image_url to list_slices response**
- Each slice now includes: "image_url": "https://inou.com/image/{slice_guid}"
- Allows Claude to provide direct clickable links to images
- Change in viewer/main.go handleSlices()
4. **Reviewed and closed TODO items**
- Date format (YYYYMMDD): non-issue, Claude understands it fine
- slice_index: obsolete, instance_number now works correctly
- image_url: ✓ implemented
**Files modified:**
- ~/dev/inou/viewer/main.go - Added image_url field to handleSlices()
**Binaries rebuilt:**
- /tank/inou/bin/inou-viewer
## 2025-12-19: Design Reference - andrewmccalip.com/space-datacenters
Inspiration for future UI patterns:
**Horizontal bar charts**
- Label left, bar middle, value right
- Different colors per category (blue vs amber)
- Could use for: lab result ranges, storage usage, progress indicators
**Sliders with labeled ranges**
- Clean min/max labels below
- Marker dots at key positions
- Could use for: date range selection, threshold settings
**Label-value pairs**
- Muted left label, bold right value
- Great for metadata display
**Colored left borders on cards**
- Blue = one category, amber = another
- Section headers: (small caps, letter-spacing)
**Two-column comparison layout**
- Side by side for A vs B comparisons
## 2025-12-19: Design Reference - andrewmccalip.com/space-datacenters
Inspiration for future UI patterns:
**Horizontal bar charts**
- Label left, bar middle, value right
- Different colors per category (blue vs amber)
- Could use for: lab result ranges, storage usage, progress indicators
**Sliders with labeled ranges**
- Clean min/max labels below
- Marker dots at key positions
- Could use for: date range selection, threshold settings
**Label-value pairs**
- Muted left label, bold right value
- Example: "Cost per Watt" (grey) ... "$51.10/W" (bold)
- Great for metadata display
**Colored left borders on cards**
- Blue = one category, amber = another
- Section headers: small caps with letter-spacing and dot separator
**Two-column comparison layout**
- Side by side for A vs B comparisons
## 2025-12-19: AI Instructions (OUTDATED)
~~DO NOT USE `sed` for editing files.~~
**Update 2026-01-10:** This was written when running Claude on Mac via SSH to Linux, causing quote escaping issues. Now running Claude natively on Linux — `sed` works fine again.
## Mobile App - Input Parsing (Dec 21, 2024)
### Goal
Parse natural language input into structured health/wellness observations. The journal captures the *whole story* of a person's life, not just medical symptoms.
### Why
The pattern matters for healthcare:
- Dec 15: mother hospitalized
- Dec 16: can't sleep
- Dec 17: headache, took Tylenol
- Dec 18: BP 145/92
A doctor seeing just "BP 145/92" misses the context. The comprehensive journal shows the story.
### Categories to extract
- **symptom** - physical complaints
- **medication** - drugs, supplements
- **activity** - exercise, yard work, physical activity
- **vital** - measurable (BP, weight, temp)
- **bodily** - digestion, sleep, menstruation
- **mood** - emotional state
- **life_event** - stress, family, work, relationships
- **medical_event** - doctor visits, procedures, diagnoses
### Accept vs Reject
**Accept** (interpret through user's lens):
- "I worked in the yard" → activity
- "I got fired" → life_event (stress)
- "my wife wants to leave" → life_event (stress)
- "my mother is injured" → life_event (user's stress/worry, NOT medical record for mother)
**Reject** (not about the person's life):
- "what is the capital of Denmark"
- "write me a poem"
- trivia, requests to create things
### Dossier assignment
Only create structured records for people with dossiers. Everything else is context about the user's own state.
## TODO
- [ ] Improve genetic import progress communication