11 KiB
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=arm64returns download_url
Version check flow:
- Bridge connects → calls GET /version?os={os}&arch={arch}
- Server returns latest_bridge_version + download_url
- Bridge compares versions (semver, not string)
- If outdated: blocks all tool calls, returns curl command with exact path
- 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/callmethod, 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:
zoomStateobject 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:
-
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)
-
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
-
Portal routing fixed
- GET /api/profiles now proxies to viewer (was POST-only for creating profiles)
- All /api/* routes properly forwarded to viewer backend
-
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
-
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:
cd /tank/inou && ./bin/convert
2025-12-18 - Verification & Image URL Enhancement
What was done:
-
Verified fresh convert worked
- 3167 slices imported successfully
- instance_number now sequential (1-25 for AX T2, etc.)
- Scout/localizer filtering working
-
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 ✓
-
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()
-
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