Skip to content

Commit 0cc4856

Browse files
LEANDERANTONYclaude
andcommitted
docs: refresh README + architecture + ADR index for Tier 1/2 + themes
Sync the doc surface to the last several days of commits: - root README: 12 résumé themes (was "two"), hybrid Tier 1/2 job search, 31 ADRs (was 27), 74 test files (was 61), corrected active board counts - architecture.md: 12-theme ThemeSpec registry, cached_jobs embedding column + the hybrid search RPC - adr/README.md: index ADR-032, refresh the current-state note - deployment.md: embed-on-write spends a little on embeddings (the flat "$0" claim was stale); new operational-gotcha entry for the embed-on-write HNSW churn incident - docs/README.md: catalog the two Tier 2 SQL migration files Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 46cf92b commit 0cc4856

5 files changed

Lines changed: 33 additions & 16 deletions

File tree

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030

3131
| System | What it does |
3232
|--------|--------------|
33-
| **Live job search** | Cached index of ~12,000 open roles from Greenhouse, Lever, Ashby, and Workday — refreshed every 4 hours. Filter by company, work mode, role type, posted-within. Sort by relevance, recency, or alphabetical. |
33+
| **Live job search** | Cached index of ~14,000 open roles from Greenhouse, Lever, Ashby, and Workday — refreshed every 4 hours. Hybrid relevance ranking fuses Postgres full-text search (with deterministic synonym / abbreviation expansion) and pgvector semantic similarity. Filter by company, work mode, role type, posted-within. Sort by relevance, recency, or alphabetical. |
3434
| **Resume intake** | Upload PDF / DOCX / TXT, or chat one into existence with the conversational builder. Parsed into a normalized profile with skills, experience timeline, projects, publications, and certifications. |
3535
| **JD review** | LLM-first JD parser with regex fallback. Surfaces hard skills, soft skills, and must-haves; shows match score against the loaded resume. |
3636
| **Supervised pipeline** | Matchmaker → Forge (tailoring) → Gatekeeper (review) → Resume Generation → Cover Letter. Three-layer LLM retry stack with per-agent fallback isolation, deterministic floor on every stage. |
37-
| **Artifact export** | Two themes (`classic_ats` for ATS parsers, `professional_neutral` for human readers) in DOCX or PDF. The same source data feeds either pathway. |
37+
| **Artifact export** | 12 résumé themes — 6 single-column (ATS-safe) + 6 bespoke two-column layouts, all from one typed `ThemeSpec` registry — in DOCX or PDF, with a matching cover letter. The same source data feeds either pathway. |
3838
| **Grounded assistant** | Floating workspace chat with full context of the loaded resume, JD, analysis state, and saved jobs. Streams answers as they generate. |
3939
| **Command palette** | `⌘K` / `Ctrl+K` from anywhere — jump between steps, load a saved job, re-ask a recent assistant question, or run the analysis. |
4040
| **Tier enforcement** | Per-(user, period, counter) atomic quota gates on every gated action (tailored applications, premium applications, assistant turns, resume parses, resume-builder sessions, job searches, saved jobs, saved workspaces). Free / Pro / Business cap matrix. Premium opt-in routes review + resume-gen + cover-letter to `gpt-5.5` while keeping tailoring on mini for COGS reasons. Refund-on-failure so a transient workflow error doesn't burn a credit. |
@@ -45,9 +45,9 @@
4545

4646
The cached jobs layer lives in Postgres (`cached_jobs` table) and is refreshed by a scheduled worker that fans out across all four sources. Highlights:
4747

48-
- **~117 Greenhouse boards** + **30 Lever sites** + **36 Ashby boards** + **11 Workday Fortune-500 tenants** in the active source pool.
48+
- **79 Greenhouse boards** + **6 Lever sites** + **36 Ashby boards** + **11 Workday Fortune-500 tenants** in the active source pool.
4949
- **4-hour refresh cadence** via `pg_net` cron triggering the `/admin/refresh-cache` endpoint (6 refreshes per day at 00:00 / 04:00 / 08:00 / 12:00 / 16:00 / 20:00 UTC).
50-
- **Relevance-ranked search** through a Postgres RPC that combines query token coverage with recency.
50+
- **Hybrid relevance ranking** a Postgres RPC fuses lexical full-text search (with deterministic synonym / abbreviation query expansion) and pgvector semantic similarity via Reciprocal Rank Fusion, so a role surfaces whether it matches on keywords or on meaning. Gracefully degrades to pure lexical if the semantic side is unavailable.
5151
- **Saved-jobs drawer** with a 24-hour TTL — bookmarks survive page reloads but expire if you don't act on them, with an `EXPIRED` badge so nothing silently disappears.
5252

5353
See [ADR-013](docs/adr/ADR-013-cached-jobs-cache-layer-with-scheduled-refresh.md) and [ADR-014](docs/adr/ADR-014-postgres-rpc-for-ranked-search.md) for the load-bearing decisions.
@@ -74,10 +74,10 @@ Each agent follows the same operating shape: deterministic baseline first, LLM-a
7474

7575
## Engineering notes
7676

77-
- **61 Python test files** cover parsing, normalization, fitting, tailoring, orchestration, builders, exports, auth, quotas, persistence, the Lemon Squeezy webhook, voice transcription, artifact feedback, prompt-registry byte-identity, error handling, and the four ATS adapters.
77+
- **74 Python test files** cover parsing, normalization, fitting, tailoring, orchestration, builders, exports, auth, quotas, persistence, the Lemon Squeezy webhook, voice transcription, artifact feedback, prompt-registry byte-identity, error handling, hybrid job search, and the four ATS adapters.
7878
- **Quality runners** in `tests/quality/` produce evidence for each LLM-driven stage (parser, tailoring, review, resume gen, cover letter, assistant, JD parser, latency baseline). `backend/nightly_eval.py` wraps them into a single regression-checked batch — manual-only at pre-revenue stage by design, see [ADR-026](docs/adr/ADR-026-manual-only-nightly-eval-at-pre-revenue-stage.md).
7979
- **Every LLM prompt loads from a versioned JSON registry** (`prompts/<name>/v1.json`) — all 11 builders migrated off Python f-string concats, each guarded by a byte-identity test so a template can't silently drift from its original.
80-
- **27 ADRs** in `docs/adr/` record the architectural decisions, including the Streamlit-first → Next.js + FastAPI transition (ADR-012), DOCX-first export (ADR-015), conversational builder (ADR-016), state-aware assistant (ADR-017), three-layer retry stack (ADR-018), independent step navigation (ADR-019), tier resolution shim (ADR-020), atomic quota with refund (ADR-021), tier-aware model selection (ADR-022), Lemon Squeezy as Merchant of Record for v1 (ADR-023), the observability stack (ADR-024), the EU cookie consent banner (ADR-025), manual-only nightly eval (ADR-026), and the tier-gated export entitlement (ADR-027).
80+
- **31 ADRs** in `docs/adr/` record the architectural decisions, including the Streamlit-first → Next.js + FastAPI transition (ADR-012), DOCX-first export (ADR-015), conversational builder (ADR-016), state-aware assistant (ADR-017), three-layer retry stack (ADR-018), independent step navigation (ADR-019), tier resolution shim (ADR-020), atomic quota with refund (ADR-021), tier-aware model selection (ADR-022), Lemon Squeezy as Merchant of Record for v1 (ADR-023), the observability stack (ADR-024), the EU cookie consent banner (ADR-025), manual-only nightly eval (ADR-026), the tier-gated export entitlement (ADR-027), LLM provider failover + premium reasoning tier (ADR-028), the single-source `ThemeSpec` registry (ADR-029), the résumé-builder agentic architecture (ADR-031), and the six bespoke two-column résumé themes (ADR-032).
8181
- **Architecture details** live in [docs/architecture.md](docs/architecture.md); the day-2 operational runbook in [docs/deployment.md](docs/deployment.md).
8282

8383
## Deployment

docs/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ The `docs/sql/*.sql` files are reference copies of the Supabase migrations appli
4949
| `docs/sql/supabase-subscriptions.sql` | `aijobagent_subscriptions` table for the Lemon Squeezy integration |
5050
| `docs/sql/supabase-run-traces.sql` | `aijobagent_run_traces` cost-attribution table (prompt/completion tokens + USD cost) |
5151
| `docs/sql/supabase-feedback.sql` | `aijobagent_feedback` artifact thumbs-up/down table + RLS |
52-
| `docs/sql/supabase-cached-jobs-search.sql` | `search_cached_jobs_ranked` RPC: text-search + filters + sort + `LIMIT`/`OFFSET` pagination over `cached_jobs`. Was untracked (DB-only); now the source of truth. **service_role-only** EXECUTE — the REVOKEs are part of the canonical definition |
52+
| `docs/sql/supabase-cached-jobs-search.sql` | `search_cached_jobs_ranked` RPC: text-search + filters + sort + `LIMIT`/`OFFSET` pagination over `cached_jobs` (Tier 1 lexical search). **service_role-only** EXECUTE — the REVOKEs are part of the canonical definition |
53+
| `docs/sql/supabase-cached-jobs-pgvector.sql` | Tier 2 semantic-search schema: the `vector` extension, the `cached_jobs.embedding vector(1536)` column, and the HNSW cosine index |
54+
| `docs/sql/supabase-cached-jobs-hybrid.sql` | `search_cached_jobs_hybrid` RPC: Reciprocal Rank Fusion of the Tier 1 lexical ranking and a pgvector semantic ranking (HNSW candidate pools). **service_role-only** EXECUTE |
5355
| `docs/sql/job_cache_cron_setup.sql` | **Template, not source of truth.** The `cached_jobs` refresh pg_cron schedule. Defaults to `*/30`; production runs `0 */4`. `SELECT jobname, schedule FROM cron.job;` is authoritative |
5456

5557
Update trigger: only when a new migration lands. Old `.sql` files are append-only.

docs/adr/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ The accepted set is grouped into four thematic clusters to make the current prod
2020
- [ADR-013: Cached jobs cache layer with scheduled refresh](ADR-013-cached-jobs-cache-layer-with-scheduled-refresh.md)
2121
- [ADR-014: Postgres RPC for ranked job search](ADR-014-postgres-rpc-for-ranked-search.md)
2222
- [ADR-015: DOCX-first artifact export with theme palette](ADR-015-docx-first-artifact-export-with-theme-palette.md)
23-
- [ADR-029: ThemeSpec single-source + color-theme expansion](ADR-029-themespec-single-source-and-color-theme-expansion.md) — realises ADR-015's typed-`ThemeSpec` follow-up; one registry derives résumé + cover-letter + DOCX palettes + the backend gate set; first new theme `modern_blue` (single-column, ATS-safe). Two-column "presentation" layout reserved for a later gated phase
23+
- [ADR-029: ThemeSpec single-source + color-theme expansion](ADR-029-themespec-single-source-and-color-theme-expansion.md) — realises ADR-015's typed-`ThemeSpec` follow-up; one registry derives résumé + cover-letter + DOCX palettes + the backend gate set; first new theme `modern_blue` (single-column, ATS-safe). Two-column "presentation" layout reserved for a later gated phase — since realised by ADR-032
24+
- [ADR-032: Six bespoke two-column résumé themes](ADR-032-two-column-resume-themes.md) — extends ADR-029's `ThemeSpec` registry with six distinct two-column résumé layouts via a `twocol_layout` discriminator, retiring the single placeholder `presentation_twocol` slot; the registry now ships 12 themes (6 single-column ATS-safe + 6 two-column)
2425
- [ADR-016: Conversational LLM resume builder](ADR-016-conversational-llm-resume-builder.md)
2526
- [ADR-031: Résumé-builder agentic architecture (tool-calling loop, promise tracking, silent-fallback discipline)](ADR-031-resume-builder-agentic-architecture.md) — extends ADR-016 from form-filler to tool-using agent: `fetch_github_readme` + `web_search` (function-wrapped to sidestep OpenAI's JSON-mode incompatibility), full conversation history with char-budget guard, `proactive_offer` channel, `pending_followups[]` promise tracking, schema-strictness + registry pact-tests against the silent-fallback antipattern that surfaced twice this slice
2627
- [ADR-017: Workspace assistant — ungated and state-aware context](ADR-017-workspace-assistant-state-aware-context.md)
@@ -56,7 +57,7 @@ The accepted set is grouped into four thematic clusters to make the current prod
5657

5758
## Current state note
5859

59-
As of 2026-05-17, the shipped product is a Next.js workspace deployed on Vercel backed by a FastAPI container on a Frankfurt VPS, with a Supabase EU project for Auth + persistence + the cached-jobs index. The agentic workflow runs Tailoring → Review → ResumeGen → CoverLetter on every analysis, with per-agent retry + fallback isolation. Tier enforcement is live across eight counters (Free / Pro / Business) with the Lemon Squeezy payment scaffold env-gated behind a "Coming soon" frontend fallback until the dashboard's final variant IDs land; export format/theme is additionally an entitlement gate (Free = PDF + `professional_neutral`, which is also the product-wide default theme; Pro/Business unlock DOCX + every non-default theme by exclusion — `classic_ats`, `modern_blue`, `creative_warm`, `architect_mono` (all single-column, ATS-safe) + the gated non-ATS two-column `presentation_twocol`) enforced server-side via the same 429 upgrade path (ADR-027). Theming is one typed `ThemeSpec` registry (ADR-029) deriving the résumé, cover-letter, and DOCX palettes plus the backend supported-theme set; its `layout` discriminator drives the single- vs two-column résumé renderer, so adding a theme is one registry entry. The observability stack (Sentry `jobagent-backend` + `jobagent-frontend` + a shared PostHog free-tier project tagged with `product: "jobagent"`) is wired with a custom EU cookie consent banner gating PostHog + Sentry Session Replay behind explicit user opt-in; consent persists in a parent-domain cookie so it is honoured across the marketing apex and the `app.` subdomain. `backend/nightly_eval.py` exists and is tested but is **not** on the production cron at pre-revenue stage — re-enabling is a single crontab edit when revenue justifies the recurring LLM spend.
60+
As of 2026-05-22, the shipped product is a Next.js workspace deployed on Vercel backed by a FastAPI container on a Frankfurt VPS, with a Supabase EU project for Auth + persistence + the cached-jobs index. The agentic workflow runs Tailoring → Review → ResumeGen → CoverLetter on every analysis, with per-agent retry + fallback isolation. Tier enforcement is live across eight counters (Free / Pro / Business) with the Lemon Squeezy payment scaffold env-gated behind a "Coming soon" frontend fallback until the dashboard's final variant IDs land; export format/theme is additionally an entitlement gate (Free = PDF + `professional_neutral`, which is also the product-wide default theme; Pro/Business unlock DOCX + every non-default theme) enforced server-side via the same 429 upgrade path (ADR-027). Theming is one typed `ThemeSpec` registry (ADR-029, ADR-032) deriving the résumé, cover-letter, and DOCX palettes plus the backend supported-theme set; it ships 12 themes — 6 single-column (ATS-safe) and 6 two-column — and its `layout` / `twocol_layout` discriminators drive the renderer, so adding a theme is one registry entry. The observability stack (Sentry `jobagent-backend` + `jobagent-frontend` + a shared PostHog free-tier project tagged with `product: "jobagent"`) is wired with a custom EU cookie consent banner gating PostHog + Sentry Session Replay behind explicit user opt-in; consent persists in a parent-domain cookie so it is honoured across the marketing apex and the `app.` subdomain. `backend/nightly_eval.py` exists and is tested but is **not** on the production cron at pre-revenue stage — re-enabling is a single crontab edit when revenue justifies the recurring LLM spend.
6061

6162
## Adding a new ADR
6263

0 commit comments

Comments
 (0)