Commit graph

34 commits

Author SHA1 Message Date
a38d9e5663 fix(settings): search prefs review fixes
- add try/except to suggest endpoint
- use immutable spread/filter in addTag, removeTag, acceptSuggestion
- add toggleBoard store action, remove direct v-model on board.enabled
2026-03-22 07:21:10 -07:00
2200d05b5c feat(settings): Search Prefs tab — store, view, API endpoints, remote preference filter 2026-03-21 03:09:51 -07:00
92bd82b4c9 fix(settings): address resume tab review issues
- add loadError ref (separated from empty-state path)
- add stable id to WorkEntry, use as v-for key
- move addExperience/removeExperience/addTag/removeTag to store actions
- strip id from save payload
- fix uploadError type handling in handleUpload
- add outer try/except to upload_resume endpoint
- gate syncFromProfile to non-loaded resume only
- add date_of_birth input to personal info section
- add loadError test
2026-03-21 03:04:29 -07:00
56857dc989 feat(settings): Resume Profile tab — store, view, API endpoints, identity sync 2026-03-21 02:57:49 -07:00
6093275549 fix(settings): final code quality fixes for My Profile tab
- add try/except to sync_identity endpoint
- strip id field from mission_preferences save body
- fix NDA v-for key to use company string (not index), add dedup guard
- move imports out of save_user_profile function body
2026-03-21 02:53:29 -07:00
3bcc08c080 fix(settings): spec compliance gaps in My Profile tab
- add POST /api/settings/resume/sync-identity endpoint (IdentitySyncPayload)
- fix loadError destructuring to use storeToRefs for reactivity
2026-03-21 02:40:17 -07:00
d3b4ed74bb fix(settings): address profile tab code quality issues
- add loadError ref to useProfileStore, rendered in MyProfileView
- replace raw fetch with useApiFetch in generateSummary/generateMissions
- remove await from sync-identity call (fire-and-forget)
- add stable id field to MissionPref, use as v-for key
- add test for load() error path
2026-03-21 02:37:53 -07:00
1ef418ba00 feat(settings): My Profile tab — store, view, API endpoints
- Add useProfileStore (settings/profile) with load/save, all profile fields,
  loading/saving/saveError state, and graceful resume sync-identity call
- Add MyProfileView.vue: Identity, Mission & Values, NDA Companies, and
  Research Brief Preferences sections; autosave on NDA add/remove and
  debounced autosave (400ms) on research checkbox changes
- Add GET/PUT /api/settings/profile endpoints to dev-api.py with YAML
  field mapping (linkedin ↔ linkedin_url, candidate_*_focus ↔ *_focus,
  mission_preferences dict ↔ list of {industry, note})
- 3 new store tests pass; full suite 26/26 green
2026-03-21 02:28:14 -07:00
32a83d6ff4 fix(settings): async guard awaits config load, reactive devTierOverride, validate APP_TIER 2026-03-21 02:23:10 -07:00
05a737572e feat(settings): foundation — appConfig store, settings shell, nested router
- Add useAppConfigStore (isCloud, isDevMode, tier, contractedClient, inferenceProfile)
- Add GET /api/config/app endpoint to dev-api.py (reads env vars)
- Replace flat /settings route with nested children (9 tabs) + redirect to my-profile
- Add global router.beforeEach guard for system/fine-tune/developer tab access control
- Add SettingsView.vue shell: desktop sidebar with group labels, mobile chip bar, RouterView
- Tab visibility driven reactively by store state (cloud mode hides system, GPU profile gates fine-tune, devMode gates developer)
- Tests: 3 store tests + 3 component tests, all passing
2026-03-21 02:19:43 -07:00
3bfce5e6ef feat(survey): show job picker when navigating to /survey with no id 2026-03-21 00:49:55 -07:00
80999b9e7b fix: SurveyView history reactivity, timer cleanup, accessibility
- Reassign expandedHistory.value to a new Set on toggle so Vue tracks
  the change and template expressions re-evaluate correctly
- Capture saveSuccess setTimeout in a module-level variable; clear it
  on unmount to prevent state mutation after component teardown
- Add role="region" + aria-label to screenshot drop zone div
- Add box-sizing: border-box to .save-input to match .survey-textarea
2026-03-21 00:31:31 -07:00
4bea0899db feat(survey): implement SurveyView with navigation wiring 2026-03-21 00:27:57 -07:00
b1a32ab207 fix: contacts fetch error degrades partially, not full panel blank
Contacts 5xx no longer early-returns from fetchFor, leaving the entire
right panel blank. A new contactsError ref surfaces the failure message
in the Email tab only; JD tab, Cover Letter tab, and match score all
render normally. Adds test asserting partial degradation behavior.
2026-03-20 19:16:03 -07:00
8479f79701 fix: aria-label binding, dead import, guardAndLoad network error handling
- Fix 1: Add missing `:` binding prefix to aria-label on score badge
  (was emitting literal backtick template string to DOM)
- Fix 2: Remove unused `watch` import from InterviewPrepView.vue
- Fix 3: guardAndLoad now checks interviewsStore.error after fetchAll;
  shows pageError banner instead of silently redirecting to /interviews
  on network failure; job is now a ref set explicitly in the guard
- Fix 4: Remove unconditional research-badge from InterviewCard.vue
  (added in this branch; card has no access to prep store so badge
  always showed regardless of whether research exists)
2026-03-20 18:57:41 -07:00
e6385b4c7e feat: implement interview prep view with two-column layout
Two-column desktop layout (40/60 split, sticky left panel):
- Left: job header with stage badge, interview countdown chip, research
  controls (generate/spinner/refresh/retry), and research sections
  (talking points, company, leadership, tech, funding, red flags, A11y)
- Right: tabbed panel (JD + match score/keyword gaps, email history,
  cover letter) plus locally-persisted call notes via @vueuse/core
- Mobile (≤1023px): single-column, left content first
- Routing guard: redirects to /interviews if no id, job not found, or
  wrong status; calls prepStore.fetchFor on mount, clear on unmount
2026-03-20 18:48:38 -07:00
5621140a72 fix: add error feedback and keyboard accessibility to DigestView 2026-03-20 10:16:24 -07:00
8302b58b20 feat: add DigestView with expand/extract/queue UI 2026-03-20 10:12:45 -07:00
154f691334 style: use void instead of .catch on fire-and-forget digest-queue call 2026-03-20 10:06:04 -07:00
4246e71061 feat: fire digest-queue add call from digest chip handler 2026-03-20 09:58:16 -07:00
c6f810fb30 feat(signals): add Unrelated and Digest reclassify chips to InterviewsView 2026-03-19 20:01:08 -07:00
909fe60908 feat(interviews): paginate applied list (10 per page) 2026-03-19 19:45:59 -07:00
e487942eeb fix(signals): add .stop modifiers and aria-labels to pre-list signal banner buttons 2026-03-19 19:35:15 -07:00
9de51d6b4a feat(signals): expandable body + reclassify chips in InterviewsView pre-list 2026-03-19 19:31:23 -07:00
e24e0b7233 feat(interviews): collapsible Applied section, email sync pill, pre-list signal banners 2026-03-19 16:38:05 -07:00
4abdf21981 fix(apply): check saveCoverLetter error; document cover-letter-generated in wrapper 2026-03-19 08:36:19 -07:00
1006e88e5b fix(apply): ensure loading resets on fetchJobs error and clear toast timer on unmount 2026-03-19 08:24:52 -07:00
b94828855b feat(apply): desktop split-pane layout with narrow list, expand animation, speed demon + marathon easter eggs 2026-03-19 08:21:08 -07:00
d8aca3ec52 feat(apply): extract ApplyWorkspace component with job-removed emit and perfect match easter egg 2026-03-19 08:14:15 -07:00
73c2557c31 feat(interviews): complete InterviewsView with kanban, keyboard nav, confetti
Replaces stub with full kanban implementation: three-column pipeline
(Phone Screen / Interviewing / Offer+Hired), pre-list for applied/survey
jobs, rejected accordion, keyboard navigation (arrow keys + vim keys),
confetti easter egg on hired move (respects prefers-reduced-motion),
and /prep/:id route added to router.
2026-03-19 00:38:11 -07:00
cce0f8195a feat(vue-spa): Apply view — job picker list + cover letter workspace
- router: add /apply/:id → ApplyWorkspaceView (lazy-loaded)
- ApplyView.vue: approved job list sorted by match score; badges for
  match %, remote, and cover-letter draft status; links to workspace
- ApplyWorkspaceView.vue: two-panel desktop layout (sticky job details
  left, editor right); cover letter state machine (none/queued/running/
  ready/failed); auto-resize textarea; word count toolbar; Save button
  with dirty tracking; Download PDF (programmatic <a> click, named file);
  Generate with AI + Retry; Mark as Applied + Reject Listing actions;
  polling loop for in-flight generation tasks; toast on action
- HomeView.vue: split combined "Archive Pending + Rejected" into three
  separate per-status archive buttons (only shown when count > 0)
- dev-api.py: add GET /api/jobs/:id, POST /api/jobs/:id/applied,
  PATCH /api/jobs/:id/cover_letter, POST .../cover_letter/generate
  (wires submit_task), GET .../cover_letter/task (poll), GET .../pdf
  (reportlab); has_cover_letter field on list + detail responses
2026-03-18 09:05:40 -07:00
75cc0760e1 feat(vue-spa): JobReviewView card stack with swipe gestures
- stores/review.ts: Pinia setup store — pending queue, undo stack,
  stoop-speed session timer (easter egg 9.2: 10 cards/60s)
- components/JobCard.vue: card content with match-score badge (colored
  pill), keyword-gap pills, expand/collapse description, footer with
  job URL + relative date; shimmer animation for ≥95% matches (ee 9.4)
- components/JobCardStack.vue: pointer-event drag with setPointerCapture,
  rolling 50ms velocity buffer for fling detection (600px/s + cos45°
  alignment), left/right color-tint overlay (red/green), spring snap-back
  on no-action, buffered exit animation before emitting approve/reject
- views/JobReviewView.vue: segmented status tabs, card stack for pending,
  list view for other statuses, action buttons, keyboard shortcuts
  (←/J reject, →/L approve, S skip, Z undo, ? help), help overlay,
  undo toast (5s), falcon stoop empty state (easter egg 9.3)
2026-03-17 22:30:33 -07:00
f3ce46e252 feat(web): implement design spec — peregrine.css, sidebar nav, HomeView
Applies the full design spec from circuitforge-plans/peregrine/2026-03-03-nuxt-design-system.md:

CSS tokens:
- Falcon Blue (#2B6CB0 / #68A8D8 dark) — was incorrectly using forest green
- Talon Orange (#E06820 / #F6872A dark) with --app-accent-text dark navy (never white)
- Full pipeline status token set (--status-pending/approve/reject/applied/synced/...)
- Match score tokens, motion tokens, type scale tokens
- Dark mode + hacker mode overrides

AppNav: sidebar layout (replaces top bar)
- Desktop ≥1024px: persistent sidebar with brand, links, hacker-exit, settings footer
- Mobile <1024px: bottom tab bar with 5 primary destinations
- Click-the-bird easter egg (9.6): 5 rapid clicks → ruffle animation
- Heroicons via @heroicons/vue/24/outline

App.vue:
- Skip-to-content link (a11y)
- Sidebar margin-left layout (desktop) / tab bar clearance (mobile)

HomeView: full dashboard implementation
- Pipeline metric cards (Pending/Approved/Applied/Synced/Rejected) with status colors
- Primary workflow buttons (Run Discovery, Sync Emails, Score Unscored) + sync banner
- Auto-enrichment status row
- Backlog management (conditionally visible)
- Add Jobs by URL / CSV upload tabs
- Advanced/danger zone in collapsible <details>
- Stoop speed toast easter egg (9.2)
- Midnight mode greeting easter egg (9.7)

WorkflowButton component with loading spinner, proper touch targets (min-height 44px)
Pinia jobs store (setup form) with counts + system status

Build: clean 2.28s, 0 errors
2026-03-17 22:00:42 -07:00
ae6021ceeb feat(web): Vue 3 SPA scaffold with avocet lessons applied
Sets up web/ Vue 3 SPA skeleton for issue #8, synthesizing all 15 gotchas
from avocet's Vue port testbed. Key fixes baked in before any component work:

- App.vue root uses .app-root class (not id="app") — gotcha #1
- overflow-x: clip on html (not hidden) — gotcha #3
- UnoCSS presetAttributify with prefixedOnly: true — gotcha #4
- peregrine.css alias map for theme variable names — gotcha #5
- useHaptics guards navigator.vibrate — gotcha #9
- Pinia setup store pattern documented — gotcha #10
- test-setup.ts stubs matchMedia, vibrate, ResizeObserver — gotcha #12
- min-height: 100dvh throughout — gotcha #13

Includes:
- All 7 Peregrine views as stubs (ready to port from Streamlit)
- AppNav with all routes
- useApi (fetch + SSE), useMotion, useHaptics, useEasterEgg composables
- Konami hacker mode easter egg + confetti + cursor trail
- docs/vue-spa-migration.md: full migration guide + implementation order
- Build verified clean (0 errors)
- .gitleaks.toml: allowlist web/package-lock.json (sha512 integrity hashes)
2026-03-17 21:24:00 -07:00