Spaces:
Running
Running
Commit History
16 days ago
-
docs/env: 24h ceiling, Firecrawl-first, Fantastic Jobs budget; pin selftest clock
Claude +1: Claude Sonnet 5.5Unverified signatureCo-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01St57jDbnhsxp47mMrr4yigc656aba -
Fantastic Jobs call overhaul, 24h recency, Firecrawl-first page fetch
ClaudeUnverified signatureRecency - Product window is 24h only. 48h/week/month clamp to 24h. - Removed the 24h->48h "widen" outcome-policy nudge and digest broaden. Fantastic Jobs - time_frame=24h on both endpoints (never the 7d feed). - Freshness keys on date_created (documented index time); date_posted only guards re-indexed backfills (48h floor, also sent as date_posted_gte, which is a shared parameter). - title_advanced OR-of-variants (Fullstack/Full Stack, engineer/developer, senior/sr) with sanitised terms; falls back to plain title on 400/422. - organization_agency=exclude by default (FANTASTIC_JOBS_INCLUDE_AGENCIES). - Per-job budget bucket (fantastic_job): reserve per page, refund unused, shrink the page to remaining headroom, retry lost concurrent races. - Use ai_remote_location_derived / location_requirements as the real remote geography, map ai_work_arrangement to hybrid/onsite, append provider enrichment (salary, experience, employment type) to the description. - verify:fantastic scrip…654190a
18 days ago
-
feat(ui): small teal + gold details and a brand guide
Claude +1: Claude Sonnet 5.5Unverified signature- Add --brand-teal / --brand-gold aliases (no value changes) and docs/BRAND.md describing when to use each colour. - Links: gold underline on hover. - Inputs: gold caret; checkboxes, radios and sliders follow teal. - Gold buttons get a dark spinner so loading stays visible. - Dashboard: saved roles get a gold edge (and a gold saved flash); the Strong tab gets a gold dot. - Agent report emails: teal-to-gold line at the top. Logo, brand assets and both brand hex values are unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q54vp7U5MJ3JrbTQk45zmt4701b58
19 days ago
-
Show a top-up prompt after a zero-credit search
Claude +1: Claude Sonnet 5.5Unverified signatureWhen a search runs in zero-cost mode, the chat now says so under the result and offers the existing credit top-up action. The "found nothing" help text is suppressed for zero-cost runs, since an empty zero-cost result reflects limited sources rather than a quiet market. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EF53r6Eqc4Kx6ohxjQjXQq3e836a0 -
Add zero-credit discovery fallback with central spend policy
Claude +1: Claude Sonnet 5.5Unverified signatureRunning out of credits now stops new paid spending instead of the product. - discover-spend-gate: one atomic authorization per run, reusing tryDeductCredits and the credit-guard marker. Out of credits or unreadable ledger => zero_cost (fail closed). Retries never double charge or refund. - spend-policy / provider: zero_cost runs only reach free sources (atsdirect by default, optional webindex); enforced in settleProviders plus a per-provider guard. - discover tool: zero_cost skips LLM scoring, embeddings, inner planner, Firecrawl page fetch and crawl; results carry a structured `spend` summary and an honest note. - SearchRun stores spendMode; background chunks and resume never upgrade it and no longer dead-end at zero balance. - Separate bounded daily budget for zero-cost searches. - /api/score/subscriber returns a labelled heuristic score instead of 429. - Provider errors are not treated as the user's balance (isJobScorerCreditDenial). Co-Authored-By: Claude Sonnet 5.5 <no…db1d726
20 days ago
-
Chat model outage: always fall back to a profile search; clearer failure copy
Claude +1: Claude Sonnet 5.5Unverified signatureThe chat model failing only triggered the profile-based discover_jobs fallback for capacity / retired-model errors. A 5xx, timeout, network failure or unknown error on a search turn ended the run with an error even though the search does not need the chat model. - shouldUseDeterministicDiscoverFallback now accepts any failure on a search turn, except auth/key/config errors (401/403, invalid or missing API key), which still fail loudly, and a turn the user stopped (new `aborted` option, passed from both call sites). - Progress text when falling back says the assistant is limited and that the search runs from the saved profile. - Failure messages now say the assistant is temporarily unavailable and that saved matches are still on the dashboard, instead of implying a user error. Tests: eligibility (outage kinds, auth/config rejected, abort, non-search intent) and message copy; both fail on the previous code. tsc clean; all selftests pass. Co-Authored-By: Claude Sonnet 5.5 <no…9393656 -
Treat a scoring-model outage as infra, not as weak search results
Claude +1: Claude Sonnet 5.5Unverified signatureWhen the scoring model is down, rows fall back to heuristic scores. Those low scores were diagnosed as low_role_fit / low_remote_score, so the inner loop pivoted ("broader titles", geo, skill-adjacency) and recorded the angle as a failed search, all because of an outage. buildAngleReflection now treats it as provider_unavailable (infraFailure) when at least 2 rows and at least half the scored pool hit a scoring failure. The loop stops without a strategy pivot, memory does not mark the approach exhausted, and the user is told the scoring model was unavailable rather than "search sources". Pool-exhausted and pre-gate geo diagnoses are unaffected (they do not depend on scores). Tests: unit (control, below-threshold, outage, gated-out) and inner-loop (an outage runs one angle, not two); both fail on the previous code. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DiGbNfvkFBXtwjrEu6qup461c4673 -
Durable search runs: execution lease and stale-write guards
Claude +1: Claude Sonnet 5.5Unverified signatureQStash delivers at least once and Resume can race a queued chunk, so two workers could run the same SearchRun concurrently, and late writers could overwrite newer state. - Execution lease (cas.ts): one chunk worker per run via a Redis NX lease (TTL 420s: above maxDuration 300s, below the 8-min "worker died" stale threshold). Duplicate deliveries return ok/skipped with no retry. The run is re-read after the lease is taken. Fails open without Redis. - queueNextChunk now pauses, releases the lease, then schedules. Before, it scheduled first, so the next worker could mark the run running before the pause landed (stuck "paused"); the lease must also be free by then. - Final states stay final: cancelled/completed runs can no longer be flipped by markSearchRunRunning / pauseSearchRun / completeSearchRun / failSearchRun / cancelSearchRun from a stale writer. "failed" remains resumable (Resume route relies on it). - Checkpoints merge instead of replace: discovered/hits/closeMat…e7ef20a -
Outer proposer: only pivot to a visa/relocation search when the user opted in
Claude +1: Claude Sonnet 5.5Unverified signatureThe visa/relocation avenue was an unconditional fallback candidate, so a remote-employed profile with nothing else to try was sent to a visa search. The default opportunity modes include visa_relocation, so gating on the default would not help; require an explicit opt-in in accessibilityPreferences.opportunityModes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DiGbNfvkFBXtwjrEu6qup4ff29034 -
Show the inner-loop agent what was filtered before scoring (Fix 3)
Claude +1: Claude Sonnet 5.5Unverified signaturebuildAngleReflection diagnosed an angle only from the surviving (gated) pool. Rows dropped as already-seen or geo-filtered never reached it and only appeared in dropCounts, so an exhausted or geo-failed search could read as "weak titles" and trigger a title-broadening pivot. - Add a pool_exhausted failure reason, used when more than half of the discovered pool was already seen. It pivots to semantic_broadening (new vocabulary), never broaden_role, and classifies as a strategy signal rather than search quality. - Add a pre-gate geo override: when most of the unseen pool was dropped on geography (>= 3 rows), diagnose low_remote_score regardless of how the survivors look. - Put a funnel on AngleObservation (discovered, alreadySeen, geoDropped, scored, survived) and expose it to the planner and outer LLM. - Tell the planner prompt what pool_exhausted means. - Record preFilteredRemote and alreadySeen on the all-dropped early return, the case the geo override most needs to see…98d038b
21 days ago
-
Agent loop: search every revealed role family; don't repeat inner angles
Claude +1: Claude Sonnet 5.5Unverified signatureTwo reliability fixes found while reviewing the discovery loops. 1. Outer switch repeated inner angles. proposeNextAvenueFromEvidence only treated the avenue's starting approach as exhausted, so it could "pivot" to a query the inner loop had already run (e.g. a market title like "Design Systems Engineer remote"). Inner strategyTrace intents now count as exhausted. 2. Role discovery stopped after one revealed role family. The market_vocabulary transform was once-only, so when results revealed several role families the agent searched the first and then stopped ("Bounded transform set exhausted"). It is now repeatable: one hop per family, capped at 3 (MAX_MARKET_VOCABULARY_HOPS), choosing from the latest observation plus families remembered from earlier angles, and never repeating an intent already searched this run. Memory no longer marks market_vocabulary as spent after its first use, and the "diminishing" stop no longer fires while revealed familie…a39dc9d
24 days ago
-
fix(discovery): deeper, safer provider calls and result handling
Claude +1: Claude Sonnet 5.5Unverified signature- Fantastic Jobs: paginate with offset after full pages (page size up to 1000, FANTASTIC_JOBS_MAX_PAGES), stop when offset is ignored, merge cap spans pages/endpoints, expose truncated - Treat 200 error bodies as outages (Firecrawl success:false, Fantastic/TheirStack bad shape, SearXNG all engines unresponsive) - Fresh timeout per retry attempt plus total fan-out cap; per-provider deadline; ATS direct query timeout - Interleave web query lanes before the cap; release budget and issued keys for failed requests - Add provider-recall selftests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKbC9wYNpJZycBKTEZA3pq39920b8 -
fix(discovery): send searchable queries to every provider
Claude +1: Claude Sonnet 5.5Unverified signatureReview of the discovery planners found that the digest and agent-chat intents reached providers as non-titles, so most queries matched nothing: - Digest intent is a composite ("A / B · skills · fully remote") and LLM intents are sentences. Fantastic Jobs `title` is an AND-search and the web plan quoted the whole string as an exact phrase (cut mid-word). - Visa lane was remote-only on every provider although visa roles are relocation/onsite by design. - Fantastic Jobs sent an undocumented `location_type`, a case-sensitive exact `organization`, and pulled a 7d feed for a 48h window. - Angles re-sent identical FJ / Firecrawl / SearXNG requests, burning the per-user Firecrawl budget. Changes: - Add lib/discovery/search-titles.ts: one normalizer used by discoveryInputFromProfile and TheirStack; word-boundary truncation. - Add DiscoveryQueryInput.lane=visa_relocation: FJ ai_visa_sponsorship=only, TheirStack hybrid/on_site + description keywords, web queries without "remote"…71cb485
25 days ago
-
Judge the visa-sponsored lane on role fit and sponsorship, not global remote
Claude +1: Claude Sonnet 5.5Unverified signatureThe worldwide gate and the keyword fallback turned a low global_remote score into a hard Skip for relocation roles, so visa-lane listings (for example confirmed sponsorship with US presence required) never surfaced. Reconcile a Skip in the visa lane the way restricted remote is reconciled, and drop the global_remote requirement from the lane's pass gate. Only a Skip is lifted. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011C97diC1dDVdD78DoL3g5Dc36aeb0
27 days ago
-
Show searches left from the credit balance.
Co-authored-by: Cursor <cursoragent@cursor.com>866a4fc -
Use credit wording in the quota email subject and privacy policy.
The quota subject still described a monthly subscription limit, and the privacy payments line still described a subscription. Co-authored-by: Cursor <cursoragent@cursor.com>5e67c1e -
Merge pull request #37 from zimejin07/cursor/pricing-credits-hunt-pass-cc41
Unverified signatureReplace subscription with credits + Hunt Pass pricing919a135 -
Rank atsdirect rows against the profile before the 200 cap.
The query keeps a wider recent pool and only includes the visa lane when the search asked for it. Co-authored-by: Cursor <cursoragent@cursor.com>ce8d322 -
Rewrite marketing, FAQ, and Terms for credits and Hunt Pass.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureReplace subscription pricing UI and user-facing Subscribe/monthly copy with Start free, credit packs, and Hunt Pass; Terms note legal review. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>ec7ce69 -
Update agent gate and top-up UI for credits and Hunt Pass.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureStart free claims welcome credits; out-of-credits surfaces packs and the pass; banners and shortlist drop subscription/monthly reset wording. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>5774303 -
Grant pack/pass credits in Stripe webhook with stacked passUntil.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureIdempotent payment handling sets hasAccess for packs, grants Hunt Pass credits and extends passUntil, and stops wiping balances on invoice.paid. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>f8e09af -
Add welcome-credits claim route and shared Clerk metadata helper.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signaturePOST /api/billing/claim-welcome grants WELCOME_CREDITS once per verified user/email (Redis NX), sets hasAccess, and moves mergePublicMetadata into lib/clerk-metadata for reuse by Stripe webhooks. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>5fc2566 -
Gate access on hasAccess or Hunt Pass, not only subscription.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureExtend canUseSubscriberInference for hasAccess and passUntil, add isPassActive, and limit daily digest to pass holders or legacy active subscribers (hasAccess alone is not enough for the emailed report). Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>0cfdde4 -
Add credits packs, welcome grant, and Hunt Pass constants.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureReplace subscription-era pack amounts with Starter/Standard/Pro pricing, export WELCOME_CREDITS and HUNT_PASS, and add deepSearchesFor / dailyReportsFor / nextPassUntil helpers for UI and webhook use. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>bae12e7 -
Merge branch 'cursor/discover-bg-continue-f456' (PR #36)
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureMake discover background continue reliable without requiring Resume. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>7b73b75 -
Remove unused continuationAfterSchedule import from run-chunk.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureCo-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>ff39706 -
Make discover background continue reliable without requiring Resume.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureCheckpoint discovered listings as soon as providers return them, retry QStash scheduling with backoff, and fall back to an inline/after() chunk worker so timeout mid-score keeps scoring without a manual Resume click. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>8daf7b1 -
Fix discover timeout UX: keep source counts and stop false empty results.
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureMid-angle timeouts were zeroing provider attribution (backend: none / atsdirect:0) and grounding that let the model claim no roles were found after 50 listings had already been discovered for resume/background scoring. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>2f55582 -
Read job-radar listings from Supabase and fix sponsorship negation.
Add the atsdirect discovery provider for the shared discovered_jobs table, and stop treating negated visa phrases or 'work from anywhere in the world' as the wrong eligibility signal. Co-authored-by: Cursor <cursoragent@cursor.com>f38b5c1
-
Add stronger homepage motion and restore marketing CSS.
Staggered hero reveals, floating signal orbs, scroll-driven section animations, and a richer CTA/product glow. Also unblocks the production build by typing seniorityLevels in the score-pipeline selftest. Co-authored-by: Cursor <cursoragent@cursor.com>34e9573
-
Show country-matched restricted remote as Possible when the worldwide score stays low.
A saved US or EU country can keep roles that name that place without changing Strong Match or the worldwide score. Co-authored-by: Cursor <cursoragent@cursor.com>c756d19
-
Merge pull request #32 into main.
Keep the review shelf and the score-read label on stored findings. Co-authored-by: Cursor <cursoragent@cursor.com>a076356 -
Merge pull request #31 from zimejin07/cursor/full-provider-inventory-8595
Unverified signatureUse the full Fantastic inventory on each search179cfd7 -
Merge pull request #30 from zimejin07/cursor/search-continues-on-disconnect-8595
Unverified signatureKeep the search running after the page closese2236c9 -
feat(search): score every kept listing and show which read it was
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureThe model still reads the top shortlist. Listings past that are checked against the profile in the same pass instead of being dropped, and the card says Full score or Quick check. A search now costs 300 credits. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>635aaf9 -
fix(discovery): use Fantastic's full page without narrowing the inventory
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA configured Fantastic key was trimmed to the open-web cap, and a source hint could turn into a company or ATS filter that dropped the rest of that provider. TheirStack still bills per job, so its page stays inside the daily credit cap and spends a leftover balance instead of skipping. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>f7228e1 -
fix(search): retry a failed background chunk and show Resume when it stops
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA worker failure used to answer success, so the queue never retried, and a missed continuation stayed on "still searching" with no Resume. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>9e94fef -
fix(search): keep searching after the page closes
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureClosing the page aborted the chat and left the current pass running in that request, then marked the search stopped. Leave the request immediately and continue the same run in the background. Stop still cancels the search. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>2bc82be -
feat(dashboard): keep low scores on a review shelf for 7 days
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureScored listings that miss the match bar are saved for a human look when they still fit the user's hard preferences. Unsaved review rows are deleted after 7 days. Saved and applied rows stay. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>f46c04f -
fix(chat): one clear line when a search keeps scoring
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA timed-out search was telling the user to resume while the same run was still scoring. Say once that scoring continues, and show Resume only when the background worker was not scheduled. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>6d69f02 -
fix(search): finish scoring with the heuristic when the clock is short
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA model batch needs about a minute. Starting one that the session timeout will abandon spends the search and returns no scores. Score the rest of the pass locally instead. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>657da55 -
fix(chat): explain background search and where matches land
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureThe time-limit reply, the status line, and Resume talked past each other. Say that the same search continues on its own, matches appear in this chat and on the dashboard, and Resume only continues a stalled run. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>88b3a57 -
fix(search): score listings saved when a search times out
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA timed-out angle kept the URLs it had found only in memory, and the background continuation started a new search without scoring them. Save those listings on the run without marking them seen, then score that backlog before searching again. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>9ea225b
-
Merge pull request #27 from zimejin07/cursor/digest-dashboard-without-email-8595
Unverified signatureSkip the daily digest when email cannot be sentf9666f2 -
fix(discovery): release a user credit hold when the global cap rejects it
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureThe per-user counter is taken first. If the shared daily cap then refuses the same hold, that user reservation is returned instead of sticking until midnight. A TheirStack body is marked sent only after the hold succeeds. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>4770b83 -
fix(discovery): send TheirStack short titles and release unused credits
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA full search sentence is one job_title_or pattern, and TheirStack combines every word in that pattern, so the avenue intent matched nothing. Use short title patterns instead. Reserve the request limit up front, then give back credits for jobs that were not returned, and do not send the same body twice in one run. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>2942399 -
fix(digest): skip the run when the sending domain is unverified
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA configured but unverified Resend domain cannot deliver the digest. Check it before search and stop so discovery credits are not spent. A domains API error still lets the run continue. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>f1efdc1 -
fix(digest): skip the run when email cannot be sent
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureSearch and scoring are the credit cost. A missing sending address, Resend key, or recipient stops the daily run before discovery. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>d2e4d54 -
fix(digest): save qualified roles when email is not configured
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureA missing sending domain or Resend key no longer stops the daily fan-out before search. Qualified matches still land on the dashboard; the email is skipped. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>506c714 -
fix(discovery): keep TheirStack office cities off the remote lock
Cursor Agent +1: Zimuzo EjinkeonyeUnverified signatureLive Jobs Search rows are remote with a listed city and often no final_url. Do not treat that city as a work-country lock, and size the credit budget for several angles. Co-authored-by: Zimuzo Ejinkeonye <zimejin07@users.noreply.github.com>1b4315d