Launch readiness fixes: search filters + JD parser + tier quota + UI polish#6
Conversation
Three independent backend fixes the UI test surfaced, batched into one
commit because they each carry a focused regression test.
* Job search filters silently no-op'd. JobSearchService.search_cached
rebuilt normalized_query without copying work_modes /
employment_types / sort_by, then called store.search() without
those kwargs either. Result: the chip flipped in the UI and the
label flipped in the dropdown but the request never reached the
RPC with the new value (Remote filter + Newest sort, reported in
the in-extension UI test). Now threaded end-to-end through both
search_cached and the live-source fallback; new regression test
pins the contract.
* get_daily_quota_for_plan had no "business" branch. Business users
fell through to the FREE caps (12 calls / 60k tokens per day) on
the daily cost-limiter, silently throttling paying customers
mid-workflow. The monthly TIER_CAPS table grants Business generous
feature quotas, but this daily safety-net cap was undermining
them. Now bucketed with Pro on the daily limiter (the monthly
table still does the actual tier differentiation). Three new
regression tests cover business + internal + unknown-tier.
* JD parser leaked section headers and benefits into requirements
lists. The n8n "AI Product Builder" listing surfaced the literal
string "REQUIREMENTS / MUST-HAVES" as a Must-Have item, and a
"Benefits" block adjacent to "Nice to have" pulled vacation /
PTO / medical / HSA / 401(k) into nice_to_haves. Tightened the
prompt (explicit "do NOT echo headers" / "do NOT include
benefits") plus two deterministic post-scrubs:
_is_section_label_artifact drops heading strings, _looks_like_
benefit drops compensation vocab. Six new unit tests cover the
regex + the public _coerce_string_list flags.
35 backend tests pass (5 quota + 12 JD parser + 16 cached_jobs/search
+ 6 new JD LLM scrub). Ruff clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ab, match-score)
Four small UX corrections the in-extension UI test surfaced, all in
the workspace shell:
* Capitalize plan_tier in the account popover. Backend stores plan
tiers as lowercase enum-ish strings ("internal", "business",
"pro", "free", "admin"); the popover rendered them raw. Added a
formatTier() mapper so users see "Business" / "Internal" / etc.
* Relabel the "Runs left" indicator for unlimited tiers. When
max_calls is null (admin / internal) the popover used to show a
bare "Unlimited" — visually identical to a regular free-tier
"Unlimited (no quota fetched yet)" failure mode. Now appends the
tier: "Unlimited (Internal)" / "Unlimited (Admin)". Dev account
is obviously identifiable; a future "Unlimited" addon for paid
plans would land in the same shape.
* Inline CTA on the locked Analysis tab. Previously the disabled
HTML button was a silent no-op on click — the user reported "no
inline CTA". Now the chip uses aria-disabled instead of disabled,
and the click handler routes the user to the missing prereq step
(Step 01 if no resume, Step 03 if no JD) AND shows a warning
notice naming the gap. CSS updated: locked chips get cursor: help
+ a faint hover tint so the click affordance is visible.
* Match-score tile on Job Detail before analysis runs. The metric
only rendered post-analysis, so a user with a parsed JD but no
analysis run saw no fit signal at all and didn't know where to
look. Now always rendered with a "—" placeholder and a hint
("Run analysis to compute" or "Re-run analysis (inputs changed)"
when stale). New .b-jd-metric-hint + data-tone="muted" CSS keeps
the placeholder visually quieter than the real metric.
tsc + eslint clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThis PR introduces four independent feature updates: backend job-search filter preservation, enhanced JD LLM output scrubbing, business-tier quota configuration, and workspace UI improvements for locked steps and stale-metric hints. Job search now threads UI filter selections through the entire cache-backed path; JD parsing adds section-header and benefits filtering; plan tiers are configured consistently; and the workspace shell improves locked-step navigation and metric display. ChangesJob Search Filter Preservation
JD Parser Output Scrubbing
Plan Tier Quota Configuration
Workspace UI — Locked Steps and Metric Display
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f78bf3762a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| "medical, dental", "dental, vision", "health, dental", | ||
| "health coverage", "medical coverage", " hsa ", "(hsa)", | ||
| "health savings", "401(k)", "401k", " 401 k ", "retirement plan", | ||
| "stock options", "equity grant", "rsu", " esop ", |
There was a problem hiding this comment.
Use whole-word match for "rsu" benefit keyword
_looks_like_benefit uses substring checks against padded lowercase text, but the keyword list includes bare "rsu", so any requirement containing that letter sequence (for example, "Pursuing MSc..." or "persuasion skills") is incorrectly classified as a benefit and removed from must_haves/nice_to_haves when drop_benefits=True. This silently drops legitimate qualifications from parsed JD output and can degrade downstream fit matching.
Useful? React with 👍 / 👎.
The Next.js app shipped with zero automated tests; CI ran lint + build only, so every piece of client logic (the API error humanizer, auth-session helpers, the quota meter, the tier-gate UI PR #6 changed) was unverified, and the four recent launch commits had no regression net. Stood up Vitest + React Testing Library + jsdom (the one justified new dependency group for this PR) with a jsdom config (esbuild JSX, @/ alias) and a jest-dom setup whose type augmentation keeps the existing next-build type pass green over .test files. Added a 'npm test' script and a CI Test step between Lint and Build (reusing the same npm ci install). The FE-SEC-1 security headers were extracted to src/lib/securityHeaders.ts (byte-identical) so they can be asserted without loading the Sentry-wrapped next.config. 24 tests across 7 files cover the baseline plus the deferred component tests from earlier commits: humanizeApiError status/leak mapping; api request() 429 -> TierLimitExceededError + POST/credentials wiring (the CRITICAL-2 upgrade-CTA contract); auth-session redirect/cleanup helpers; the security-header set (FE-SEC-1/F4); the useAccessibleDialog Escape + focus-trap behaviour (A11Y-1/A11Y-2); TokenUsageMeter math + over-tone; and the AnalysisRunner premium tier gate (PR #6: a Free tap fires the upgrade CTA, a Pro tap flips the run mode). Fixes: TEST-1 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Eight pre-launch fixes surfaced by the in-extension UI test against the workspace. Branched off latest
mainso the diff is just these changes (no revert noise).Backend (
2d75bae)JobSearchService.search_cachedrebuiltnormalized_querywithout copyingwork_modes/employment_types/sort_by, then calledstore.search()without those kwargs either. Chip flipped in the UI and label flipped in the dropdown but the request never reached the RPC with the new value. Threaded end-to-end through bothsearch_cachedand the live-source fallback; offset pagination from main preserved alongside.get_daily_quota_for_planhad no"business"branch — paying customers got the 12 calls / 60k tokens free cap on the daily safety-net limiter. Now bucketed with Pro (monthly TIER_CAPS still does tier differentiation)."REQUIREMENTS / MUST-HAVES"as a Must-Have item, and a "Benefits" block adjacent to "Nice to have" pulled vacation / PTO / medical / HSA / 401(k) intonice_to_haves. Tightened the prompt + added two deterministic post-scrubs (_is_section_label_artifact,_looks_like_benefit) wired through_coerce_string_listflags.Frontend (
f78bf37)formatTier()helper."Unlimited (Internal)"/"Unlimited (Admin)".aria-disabledinstead ofdisabled; click routes to the missing prereq step (Step 01 if no résumé, Step 03 if no JD) and surfaces a warning notice."—"with hint"Run analysis to compute"(or"Re-run analysis (inputs changed)"when stale).Test plan
pytest tests/test_jd_llm_parser_service.py tests/test_job_search_service.py tests/test_quota_service.py tests/test_jd_parser.py tests/test_cached_jobs_store.py— 61 passedruff checkclean on touched Python filestsc --noEmitcleaneslintclean on touched frontend files"Business"(not"business")"— Run analysis to compute"Summary by CodeRabbit
New Features
Improvements