Skip to content

Implementation Roadmap

Status (2026-06-02): Phases 1–5 and the Settings slice have shipped. On top of the job-search vertical (Adzuna primary + Seek + LinkedIn adapters, the FastAPI server at /api/v1/, the CLI), the LLM layer is live — kairos.llm covers the LiteLLM client, JD analyzer + match scoring, skill extractor, resume tailor, and WebSocket streaming, with pandoc-based resume rendering in kairos.render and a keyring-backed secret store in kairos.secrets. The React frontend ships the JobSearch, ResumeForm, and Settings views (Sidebar/Topbar nav, LLM key + settings UI). Remaining work, in flight on feat/audit-followups: the Phase 6 apply/track backend and the matching Job Detail / JD-analysis / Applications frontend views (Phase 8c–e), plus a CI test gate. Phase 6 Indeed stays deferred (Cloudflare ban risk — Adzuna API covers the same listings); Phase 7 polish is ongoing.

Phase Overview

gantt
    title Kairos Implementation Phases
    dateFormat YYYY-MM-DD
    axisFormat %b %d

    section Phase 1 Skeleton + API
    Project setup + Docker Compose       :done, p1a, 2026-04-01, 2d
    Domain entities + interfaces (core)  :done, p1b, after p1a, 2d
    PostgreSQL models + migrations       :done, p1c, after p1b, 1d
    FastAPI server + core routes         :done, p1d, after p1b, 2d
    kairos.client library                :done, p1e, after p1d, 1d

    section Phase 2 Seek Search
    SeekClient + parser                  :done, p2a, after p1e, 3d
    PostgreSQL job repository            :done, p2b, after p1c, 1d
    Job search + list API endpoints      :done, p2c, after p2a, 1d

    section Phase 3 LLM Analysis
    LiteLLM client setup                 :done, p3a, after p2c, 2d
    JD analysis + match scoring          :done, p3b, after p3a, 2d
    Analysis API endpoints               :done, p3c, after p3b, 1d

    section Phase 4 Resume Tailoring
    Resume parser + import               :done, p4a, after p3c, 2d
    Tailoring prompts + validation       :done, p4b, after p4a, 3d
    Resume API endpoints + WebSocket     :done, p4c, after p4b, 1d

    section Phase 5 CLI
    Typer commands + kairos.client       :done, p5a, after p1e, 3d
    Rich output formatting               :done, p5b, after p5a, 1d

    section Settings + Secrets
    Keyring secret store                 :done, psa, after p4c, 1d
    LLM key + settings API               :done, psb, after psa, 1d
    Settings + Resume form UI            :done, psc, after psb, 2d

    section Phase 6 Apply + Track
    Apply workflow + browser open        :active, p6a, after psc, 1d
    Application tracking                 :active, p6b, after p6a, 2d
    Indeed adapter (deferred)            :p6c, after p6a, 3d

    section Phase 7 Polish
    Error handling + edge cases          :p7a, after p6c, 2d
    CLI UX polish                        :p7b, after p7a, 2d

    section Phase 8 Web Frontend
    React project setup                  :done, p8a, after p1e, 2d
    Core views (search + resume + settings) :done, p8b, after p8a, 5d
    Job detail + JD analysis + tracker UI :active, p8c, after p8b, 3d

Phase Details

Phase 1: Skeleton + API ✅ Shipped

Goal: Working project with a running FastAPI server, PostgreSQL, and shared client library.

  • Init Python project with uv init, configure pyproject.toml
  • Docker Compose: PostgreSQL 18 + FastAPI (hot reload)
  • Define all entities in kairos.core (Pydantic models)
  • Define all interfaces (ABCs for Repository + Service)
  • Define exception hierarchy per module
  • Config loading via pydantic-settings (TOML + env vars)
  • PostgreSQL setup + Alembic migrations (001 initial, 002 cursor index, 003 owner_id)
  • FastAPI server with health check, RFC 9457 problem+json errors (no envelope), middleware stack
  • kairos.client library with typed async methods

Verify: docker compose up -d succeeds. curl localhost:8880/api/v1/health/ returns 200.

Phase 2: Job Search ✅ Shipped

Goal: Search jobs across multiple platforms via API.

  • AdzunaSearchService (HTTP API, primary source — free, structured JSON, no scraping)
  • SeekClient + LinkedInClient with httpx + beautifulsoup4 (fallback)
  • Rate limiter with randomized delays for scrapers
  • PostgreSQL job repository (SQLAlchemy, owner-scoped)
  • API endpoints: POST /api/v1/jobs/search, GET /api/v1/jobs (cursor-paginated), GET /api/v1/jobs/{id}, POST /api/v1/jobs/{id}/fetch-details, DELETE /api/v1/jobs/{id}
  • Backend pytest suite locks the contract (270 cases overall, +12 DB-gated)

Verify: curl -X POST localhost:8880/api/v1/jobs/search -d '{"keywords":"rust","country":"AU","location":"Perth"}' returns results.

Phase 3: LLM Analysis ✅ Shipped

Goal: Analyze JDs with an LLM via API.

  • LiteLLM async client (LiteLlmClient, multi-provider) with mapped error hierarchy
  • JD analysis + skill-extraction prompt templates
  • Analyzer + SkillExtractor with Pydantic structured output and match scoring
  • API endpoints: POST /api/v1/jobs/{id}/analyze, GET /api/v1/jobs/{id}/analysis, plus the /api/v1/skills Skill Profile CRUD
  • JdAnalysis persisted (migration 006)

Verify: POST /api/v1/jobs/{id}/analyze returns analysis with match score.

Phase 4: Resume Tailoring ✅ Shipped

Goal: Import resume, tailor per JD via API, with WebSocket streaming.

  • Resume section parser + import flow, PostgreSQL resume repository (migration 004)
  • Tailor with anti-hallucination prompts + a validation pass (validation.py)
  • API endpoints: resume CRUD under /api/v1/resumes (incl. set-base and per-section patch), POST /api/v1/jobs/{id}/tailor, GET /api/v1/jobs/{id}/tailored-resume, POST /api/v1/tailored-resumes/{id}/approve, POST /api/v1/tailored-resumes/{id}/export
  • WebSocket streaming of TailorEvents at WS /api/v1/jobs/{id}/tailor/stream (kairos.llm.streaming + kairos.api.ws.tailor)
  • Pandoc-based rendering in kairos.render (migration 007 stores tailored resumes)

Verify: Full resume flow works via API: import → tailor → approve → export.

Phase 5: CLI ✅ Shipped

Goal: Lightweight command-line client for scripting and daily use.

  • Typer-based command structure, talks to the API over HTTP
  • Commands: jobs search/list/view, resumes import/list/delete/tailor/export, skills extract/list, plus config and init
  • Rich output formatting (tables)
  • applications commands deferred to Phase 6

Verify: kairos jobs search "rust" --location perth returns results.

Settings + Secrets ✅ Shipped

Goal: Manage LLM provider keys and settings safely, from the API and the web UI.

  • Keyring-backed secret store (kairos.secrets.secret_store) + env injection on startup
  • LLM key + settings API: GET/PATCH /api/v1/config/llm, GET /api/v1/config/llm/models, POST /api/v1/config/llm/key, DELETE /api/v1/config/llm/key/{env_var}
  • Frontend Settings view (LLM key + model UI) and ResumeForm view, wired via the useSettings / useResumeForm hooks, with Sidebar/Topbar nav

Verify: Set an LLM key in the Settings view → POST /api/v1/jobs/{id}/analyze succeeds.

Phase 6: Apply + Track ◐ In flight (feat/audit-followups)

Goal: Complete semi-automatic workflow.

  • Apply action (open browser with application URL)
  • Application tracking API endpoints (this branch adds the backend slice)
  • ~~Indeed adapter (playwright)~~ — deferred, Cloudflare ban risk
  • ~~LinkedIn adapter~~ ✅ shipped in Phase 2 (public guest API, httpx + bs4)

Verify: Full flow: search → analyze → tailor → apply → track.

Phase 7: Polish

Goal: Production-quality UX.

  • Graceful error handling across API and CLI
  • CLI: colorized output, progress spinners, help text
  • Resume export (PDF/LaTeX)
  • API rate limits, retries, and edge case handling

Phase 8: Web Frontend (React) ◐ Search + resume + settings shipped

Goal: Browser-based access to all Kairos features.

  • ✅ React 19 + Vite+ + TypeScript scaffold with token-based design system (Phase 8a)
  • ✅ Core search view: filter panel matching all CLI flags, cursor pagination, per-platform error surfacing (Phase 8b)
  • ResumeForm and Settings views (resume import/edit + LLM key/model), Sidebar/Topbar nav
  • Job detail view + JD analysis surface (in flight on feat/audit-followups, Phase 8c)
  • Resume tailor diff viewer (planned, Phase 8d)
  • LLM streaming consumed via the existing WS /api/v1/jobs/{id}/tailor/stream endpoint (frontend wiring planned)
  • Application tracker board (in flight on feat/audit-followups, Phase 8e)
  • Responsive design polish for mobile access (planned)

Verify: Open browser → search → analyze → tailor → track — full workflow.

Definition of Done

  • All tests pass with pytest
  • ruff check and ruff format pass with no issues
  • Core workflow works end-to-end (search → analyze → tailor → apply → track)
  • At least Seek adapter is fully functional
  • Resume tailoring produces valid LaTeX output
  • API server handles all core operations via REST + WebSocket
  • CLI can perform the full workflow via API
  • All frontends produce consistent behavior through the unified API
  • API keys and JWT secrets handled securely (env var or config, never logged)
  • docker compose up -d brings up the full stack