Skip to content

feat(career): Sprint 1 — dual-mode sidebar and career pillar#2

Merged
adarshkumar23 merged 6 commits intomainfrom
feat/career-os-sprint-1
Apr 17, 2026
Merged

feat(career): Sprint 1 — dual-mode sidebar and career pillar#2
adarshkumar23 merged 6 commits intomainfrom
feat/career-os-sprint-1

Conversation

@adarshkumar23
Copy link
Copy Markdown
Owner

Summary

  • Dual-mode sidebar: OSModeSwitcher pill toggles between William OS and Career OS trees; remembers last route per mode via localStorage
  • Career OS backend: 6 tables in career schema (problems, projects, applications, contacts, opportunities, score_snapshots), 33 endpoints under /api/v1/career/*, score algorithm (DSA/Projects/Applications/Network/CP components totalling 100)
  • Celery beat task: compute_and_snapshot_all_users at 02:30 UTC daily (08:00 IST), idempotent upsert
  • Frontend pages: CareerDashboard (score ring, breakdown bars, pipeline preview, opportunities feed), Applications Kanban (dnd-kit drag-to-stage with optimistic update + rollback), Problems (table + streak + difficulty donut), Projects (card grid + on-resume toggle), Network CRM (contact list + follow-up queue + Gemini outreach draft), Opportunities (tabbed inbox + countdown chips + convert flow)

Test plan

  • alembic upgrade head succeeds (merges sprint10_001 + audit_m14_index_cast heads)
  • alembic downgrade -1 then upgrade head round-trips cleanly
  • \dt career.* shows 6 tables in psql
  • GET /api/v1/career/dashboard returns 200 with empty data after first user login
  • Career OS pill in sidebar navigates to /career, William OS pill returns to /dashboard
  • Create an application via POST, drag it in Kanban, refresh — stage persists in DB
  • pytest tests/career/ -v — all score algorithm tests pass
  • npm run build — zero TypeScript errors
  • Guardrails: grep -r "settings.SECRET_KEY" backend/app/modules/career/ → clean
  • Guardrails: grep -r "gemini-2.0-flash" backend/app/modules/career/ → clean
  • Guardrails: grep -rE "datetime\.now\(timezone" backend/app/modules/career/ → clean

Deviations from spec

  1. ScoreRing extraction: used existing ProgressRing component directly with color="rgb(99,102,241)" — zero additional files touched (spec said stop if 10+ files; reuse was the right call)
  2. Sidebar useEffect for route persistence: moved into OSModeSwitcher component itself (same effect, cleaner encapsulation)
  3. Draft-message body param: FastAPI body: dict = {} default used since there's no Pydantic model needed for optional {context?} — functionally identical

Sprint 2 backlog

See CAREER_OS_SPRINT_2_BACKLOG.md — LeetCode/CF/GitHub API sync, email stage-transition auto-parse, bulk CSV import.

🤖 Generated with Claude Code

adarshkumar23 and others added 6 commits April 18, 2026 01:58
- OSModeSwitcher pill component with localStorage route memory
- layout/Sidebar updated with career OS navigation tree
- CareerDashboardPage: score ring, breakdown bars, stats strip, pipeline preview, opportunities feed
- ApplicationsKanbanPage: dnd-kit drag-to-stage with optimistic update + rollback toast
- ProblemsPage: table with filters, streak ring, difficulty breakdown
- ProjectsPage: card grid, tech chips, on-resume toggle
- NetworkPage: contact list with temperature filter, follow-up queue, Gemini outreach draft modal
- OpportunitiesPage: tabbed inbox/tracking/ignored/converted, countdown chips, convert flow
- api.ts: full career API surface added
- App.tsx: all career routes wired under /career/*
…owing

mypy reported 4 errors because `ApplicationService.list` and `ContactService.list`
shadowed the builtin `list` type, making return annotations like `list[Application]`
resolve to the method instead. Renamed to `get_all`; 0 mypy errors, 19 tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- scripts/oracle-vm-setup.sh  — first-time VM bootstrap (Docker, nginx, iptables)
- scripts/deploy.sh           — build, start, migrate on the VM
- scripts/remote-deploy.sh    — one-shot from local: scp .env + pull + deploy
- scripts/setup-nginx-oracle.sh — wire nginx, optional Let's Encrypt SSL
- infra/nginx/william-os.conf — updated to proxy frontend (:3000) + API (:8000)
  with HTTP→HTTPS redirect and no-SSL :8080 fallback for IP-only access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@adarshkumar23 adarshkumar23 merged commit 4b1570d into main Apr 17, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant