feat: US-001 - Install @xenova/transformers and add generate-embeddings script skeleton
This commit is contained in:
+17
-194
@@ -1,202 +1,25 @@
|
||||
# Progress Log — Login Logo & Blur Refinements
|
||||
# Branch: ralph/login-logo-refinements
|
||||
# Progress Log — Semantic Search & AI Chat
|
||||
# Branch: ralph/semantic-search
|
||||
# Started: 2026-02-15
|
||||
|
||||
## Codebase Patterns
|
||||
|
||||
### Project Structure
|
||||
- Components in `src/components/`, tiles in `src/components/tiles/`
|
||||
- Data files in `src/data/`
|
||||
- Types in `src/types/pmr.ts` and `src/types/index.ts`
|
||||
- Hooks in `src/hooks/`, Contexts in `src/contexts/`, Lib in `src/lib/`
|
||||
- Path alias: `@/` maps to `./src/`
|
||||
|
||||
### Phase Management
|
||||
- App.tsx controls phase: 'boot' -> 'ecg' -> 'login' -> 'pmr'
|
||||
- BootSequence.tsx, ECGAnimation.tsx — LOCKED, do not modify
|
||||
- LoginScreen.tsx bridges to dashboard
|
||||
|
||||
### Typography
|
||||
- Elvaro Grotesque (`font-ui`, `var(--font-ui)`) — primary UI font
|
||||
- Blumir (`font-ui-alt`) — alternative variable font
|
||||
- Geist Mono (`font-geist`, `var(--font-geist-mono)`) — timestamps, data values
|
||||
- Fira Code (`font-mono`) — boot/ECG terminal only
|
||||
- Do NOT use Inter, Roboto, DM Sans, or system defaults
|
||||
|
||||
### Design Tokens (index.css CSS variables)
|
||||
- --surface: #FFFFFF (card/topbar background)
|
||||
- --bg-dashboard: #F0F5F4 (warm sage content background)
|
||||
- --accent: #0D6E6E (teal primary)
|
||||
- --accent-hover: #0A8080
|
||||
- --accent-pressed: #085858
|
||||
- --accent-light: rgba(10,128,128,0.08)
|
||||
- --border: #D4E0DE (structural borders)
|
||||
- --border-card: #E4EDEB (card/inner borders)
|
||||
- --text-primary: #1A2B2A
|
||||
- --text-secondary: #5B7A78
|
||||
- --text-tertiary: #8DA8A5
|
||||
- --sidebar-width: 304px
|
||||
- --topbar-height: 56px
|
||||
|
||||
### Known Dependencies
|
||||
- React 18.3.1, TypeScript, Vite, Tailwind CSS
|
||||
- Framer Motion 11.15.0, Lucide React 0.468.0, fuse.js 7.0.0
|
||||
|
||||
### Key Files for This Feature
|
||||
- src/components/CvmisLogo.tsx — logo component with animation (timing constants to extract)
|
||||
- src/components/LoginScreen.tsx — main login screen (overlay, blur, card styling)
|
||||
- src/App.tsx — phase management (skip/restore boot sequence)
|
||||
- src/index.css — CSS custom properties, design tokens
|
||||
|
||||
### CvmisLogo Component (from previous run)
|
||||
- `size` prop: numeric, sets SVG height attribute directly
|
||||
- `cssHeight` prop: string, sets height via CSS style (use for clamp/responsive values)
|
||||
- `animated` prop: boolean, enables framer-motion reveal animation (1000ms total)
|
||||
- Logo animation: 500ms rise (green capsule) + 500ms fan-out (all three) = 1000ms total
|
||||
- All timing values are named constants at top of file — tune there, not inline
|
||||
- Blend constants (OVERLAY_BLEND_*) are exported for use by other components (US-005)
|
||||
|
||||
### LoginScreen.tsx State (from previous run)
|
||||
- Overlay: fixed inset-0 zIndex: 110, rgba(240, 245, 244, 0.7) + backdrop-filter: blur(20px)
|
||||
- TopBar is zIndex: 100 — overlay now correctly covers it (fixed in US-006)
|
||||
- Card borderRadius: 12px, inputs/button borderRadius: 4px
|
||||
- Some colors already tokenized (--surface, --accent, --bg-dashboard) from previous run
|
||||
- Some colors still hardcoded (#111827 input text, button bg states, caret color)
|
||||
- `@xenova/transformers` pipeline with `pooling: 'mean'` and `normalize: true` returns a Tensor; use `Array.from(output.data as Float32Array)` to extract the 384-d vector
|
||||
- Scripts live in `scripts/` and run via `npx tsx` (tsx is not a project dep, npx fetches it)
|
||||
- tsconfig `include` only covers `src/` — scripts are type-checked by tsx at runtime, not by `tsc --noEmit`
|
||||
- Project uses `"type": "module"` in package.json
|
||||
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-001: Skip to login phase for dev iteration
|
||||
- Changed initial Phase state from `'boot'` to `'login'` in `src/App.tsx` line 47
|
||||
- Files changed: `src/App.tsx`
|
||||
## 2026-02-15 - US-001
|
||||
- Installed `@xenova/transformers` (^2.17.2)
|
||||
- Created `scripts/generate-embeddings.ts` with main() that loads `Xenova/all-MiniLM-L6-v2` and embeds a test string
|
||||
- Added `"generate-embeddings"` npm script
|
||||
- Verified: outputs vector length 384 and exits cleanly
|
||||
- Typecheck passes
|
||||
- Files changed: `package.json`, `package-lock.json`, `scripts/generate-embeddings.ts`
|
||||
- **Learnings for future iterations:**
|
||||
- Phase state is a simple `useState<Phase>` on line 47 of App.tsx
|
||||
- All phase rendering logic (`boot`, `ecg`, `login`, `pmr`) remains intact — only initial value changes
|
||||
- US-011 will revert this exact change back to `'boot'`
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-002: Extract animation timing into named constants
|
||||
- Extracted all inline timing values in CvmisLogo.tsx to named constants at top of file
|
||||
- Constants added: RISE_DURATION_MS, RISE_DURATION_S, RISE_OPACITY_DURATION_S, RISE_EASING, RISE_START_Y, FAN_DELAY_AFTER_RISE_MS, FAN_DURATION_S, FAN_ROTATION_DEG, FAN_HORIZONTAL_PX, FAN_RIGHT_STAGGER_S, TOTAL_ANIMATION_MS
|
||||
- Added overlap blend constants for US-005: OVERLAY_BLEND_START_PROGRESS, OVERLAP_BLEND_MAX_OPACITY, OVERLAP_BLEND_TRANSITION_DURATION_S (exported)
|
||||
- Files changed: `src/components/CvmisLogo.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- Blend constants are `export`ed because TypeScript strict mode flags unused `const` declarations — exporting avoids the TS6133 error while making them available for US-005
|
||||
- TOTAL_ANIMATION_MS is computed from FAN_DELAY_AFTER_RISE_MS + FAN_DURATION_S * 1000, so changing rise or fan timing automatically updates the done-timer
|
||||
- FAN_EASING was already a named constant before this story; it was left in place and grouped with the new fan constants
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-003: Scale logo and branding block to ~50% of login card height
|
||||
- Scaled CvmisLogo `cssHeight` prop from `clamp(80px, 8vw, 120px)` to `clamp(160px, 18vw, 280px)`
|
||||
- Adjusted logo wrapper marginBottom from 10px to 12px for spacing balance
|
||||
- Browser-verified: desktop ratio 51.3% (target 50% ±10%), mobile (375px) ratio 41.1% — both within tolerance
|
||||
- No overflow or clipping on mobile viewport
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- The CvmisLogo `cssHeight` prop maps directly to a CSS `height` style on the SVG — `clamp()` values work well for responsive scaling
|
||||
- At 375px viewport, `18vw = 67.5px` which triggers the clamp minimum of 160px — the logo remains a comfortable size on small screens
|
||||
- The branding block ratio can be measured by comparing `brandingBlock.getBoundingClientRect().height + marginBottom` against `card.innerHeight - padding`
|
||||
- The branding block container has class `flex flex-col items-center` — use this selector for programmatic measurement
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-004: Increase branding text to match dashboard typography scale
|
||||
- Increased CVMIS title fontSize from `13px` to `clamp(16px, 1.4vw, 20px)` — renders 20px on desktop
|
||||
- Increased subtitle fontSize from `11px` to `clamp(12px, 1vw, 14px)` — renders 14px on desktop
|
||||
- Increased subtitle marginTop from `2px` to `3px` for better spacing with larger text
|
||||
- Both remain in font-ui (Elvaro Grotesque) with weight 600 (title) and 400 (subtitle)
|
||||
- Browser-verified: text is visually balanced with the larger logo and login form
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- The branding text clamp values use the same responsive pattern as the logo `cssHeight` — mid-values around 1-1.5vw work well for text
|
||||
- Title and subtitle are `<span>` elements inside the `.flex.flex-col.items-center` branding container
|
||||
- Weight hierarchy (600 title, 400 subtitle) provides sufficient visual differentiation without needing size contrast as large
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-005: Add overlap blend effect on fanning capsules
|
||||
- Added `blendActive` state to CvmisLogo, triggered by timer at `blendStartMs` (50% through fan animation)
|
||||
- Added two blend overlay `<g>` elements after the main pills: copies of left/right pill shapes with `mixBlendMode: 'multiply'` and opacity transitioning from 0 to 0.2
|
||||
- Blend overlays share the same `transform` and `transition` as their corresponding original pills, plus an opacity transition using `OVERLAP_BLEND_TRANSITION_DURATION_S`
|
||||
- Reduced motion: `blendActive` starts `true`, `transition: 'none'` — final blend state shown immediately
|
||||
- Browser-verified: blend darkening visible at pill overlap areas, opacity confirmed at 0.2
|
||||
- Files changed: `src/components/CvmisLogo.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- `mix-blend-mode` is not CSS-animatable — use overlay elements with animated opacity instead of trying to transition the blend mode
|
||||
- Blend overlay approach: duplicate the pill shapes (rect only, no icons) as separate `<g>` elements with `mixBlendMode: 'multiply'` and low opacity
|
||||
- The `useMemo` for `blendStartMs` avoids recalculation — all timing constants are module-level so this is stable
|
||||
- Combined CSS transition strings work in SVG `<g>` style: `transform 0.6s cubic-bezier(...), opacity 0.3s ease-out`
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-006: Extend backdrop blur to cover full dashboard including TopBar
|
||||
- Changed overlay from Tailwind `z-50` class to inline `zIndex: 110` to sit above TopBar (`zIndex: 100`)
|
||||
- Browser-verified: TopBar, sidebar, and all content uniformly blurred; login card remains crisp
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- TopBar uses inline `zIndex: 100` (not a Tailwind class), so overlay needs inline zIndex > 100
|
||||
- Tailwind's `z-50` = z-index 50, which was below the TopBar — switched to inline style for precise control
|
||||
- The login card doesn't need its own z-index since it's a child of the overlay and inherits stacking context
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-007: Reduce backdrop blur intensity by ~50%
|
||||
- Added `BACKDROP_BLUR_PX = 10` constant at top of LoginScreen.tsx
|
||||
- Replaced hardcoded `blur(20px)` in initial style with template literal using constant
|
||||
- Exit animation still targets `blur(0px)` — Framer Motion interpolates from current 10px to 0px
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- The `BACKDROP_BLUR_PX` constant is in the "Login screen timing & visual constants" block at top of LoginScreen.tsx
|
||||
- Framer Motion's `animate` prop interpolates from the element's current computed style, so the exit blur animation doesn't need the starting value explicitly
|
||||
- Only the initial style needs the constant; the exit target (`blur(0px)`) is always 0
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-008: Align login card border radius and shadow with dashboard design system
|
||||
- Changed card borderRadius from `12px` to `var(--radius-card, 8px)`
|
||||
- Changed card boxShadow from `shadow-sm` (`0 1px 2px rgba(26,43,42,0.05)`) to `var(--shadow-lg, 0 8px 32px rgba(26,43,42,0.12))`
|
||||
- Changed username input, password input, and button borderRadius from `4px` to `var(--radius-sm, 6px)`
|
||||
- All values use CSS custom property references with fallbacks
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- CSS tokens `--radius-card`, `--radius-sm`, `--shadow-sm`, `--shadow-md`, `--shadow-lg` are all defined in `index.css` `:root` — use `var()` references with fallback values
|
||||
- The button has 18-space indentation vs 20-space for inputs — `replace_all` may not catch all instances if matching on indentation
|
||||
- The spinner (`borderRadius: '50%'`) and status indicator dot should NOT be changed — they're circles, not card elements
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-009: Replace hardcoded colors with design tokens
|
||||
- Replaced all hardcoded hex colors in LoginScreen.tsx with CSS custom property references (`var()` with fallbacks)
|
||||
- Input text color: `#111827` → `var(--text-primary, #1A2B2A)`
|
||||
- Cursor/caret color: `#0D6E6E` → `var(--accent, #0D6E6E)` (2 instances)
|
||||
- Button backgrounds: `#0D6E6E` → `var(--accent)`, `#0A8080` → `var(--accent-hover)`, `#085858` → `var(--accent-pressed)`
|
||||
- Spinner border/top: `#E4EDEB` → `var(--border-light)`, `#0D6E6E` → `var(--accent)`
|
||||
- Input inactive borders: `#E4EDEB` → `var(--border-light)` (username + password fields)
|
||||
- Card border: `#E4EDEB` → `var(--border-light)`
|
||||
- Footer border: `#E4EDEB` → `var(--border-light)`
|
||||
- Connection status colors: `#059669` → `var(--success)`, `#DC2626` → `var(--alert)` (dot bg + text)
|
||||
- Focus ring: `ring-[#0D6E6E]/40` → `ring-accent/40` (Tailwind token)
|
||||
- Added `--accent-pressed: #085858` token to `index.css` `:root` (completes the accent state trio)
|
||||
- Files changed: `src/components/LoginScreen.tsx`, `src/index.css`
|
||||
- **Learnings for future iterations:**
|
||||
- `#FFFFFF` on button text is intentional for contrast — no `--text-on-accent` token exists; leave as hardcoded white
|
||||
- `rgba(240, 245, 244, 0.7)` overlay bg is `--bg-dashboard` at 70% opacity — no token for this; leave as rgba
|
||||
- Status dot glow `boxShadow` uses rgba variants of success/alert colors at 40% opacity — no token for these glow effects
|
||||
- Tailwind config has `accent` and `accent-hover` color tokens, so `ring-accent/40` works in class names
|
||||
- Always add fallback values in `var()` references (e.g., `var(--accent, #0D6E6E)`) for resilience
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-010: Fix minor typography inconsistencies
|
||||
- Changed form label fontWeight from 500 to 600 (both Username and Password labels) to match dashboard card header weight convention
|
||||
- Adjusted input text fontSize mid-value from `clamp(13px, 1.1vw, 15px)` to `clamp(13px, 1.2vw, 15px)` — renders ~14-15px on standard viewports
|
||||
- Adjusted button text fontSize mid-value from `clamp(14px, 1.1vw, 16px)` to `clamp(14px, 1.2vw, 16px)` — renders ~15px on standard viewports
|
||||
- Changed connection status indicator gap from 6px to 8px (matching dashboard CardHeader gap)
|
||||
- Files changed: `src/components/LoginScreen.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- These are all subtle alignment tweaks — the clamp mid-value change from 1.1vw to 1.2vw shifts rendering by ~1px on 1280px viewports
|
||||
- The label fontWeight 600 matches the dashboard's `CardHeader` convention (seen in `Card.tsx`)
|
||||
- The connection indicator gap of 8px matches the standard icon-text gap used in dashboard card headers
|
||||
---
|
||||
|
||||
## 2026-02-15 - US-011: Re-enable boot sequence
|
||||
- Changed initial Phase state from `'login'` back to `'boot'` in `src/App.tsx` line 47
|
||||
- Reverts the dev shortcut from US-001, restoring the full boot → ECG → login → dashboard flow
|
||||
- Typecheck and lint pass cleanly
|
||||
- Files changed: `src/App.tsx`
|
||||
- **Learnings for future iterations:**
|
||||
- This is a simple one-line revert — the phase state controls the entire UI flow
|
||||
- All 11 stories in this PRD are now complete
|
||||
- `pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2')` auto-downloads and caches the ONNX model (~23MB)
|
||||
- First run takes a few seconds for model download; subsequent runs are near-instant from cache
|
||||
- The pipeline's `pooling: 'mean'` and `normalize: true` options handle mean-pooling and L2 normalization in one step — no manual tensor manipulation needed
|
||||
- `output.data` is a `Float32Array`; wrap in `Array.from()` for a plain number array
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user