CSS classes use the 'category-{slug}' prefix, so checking `country_slug not in card_classes`
never matched. Changed to `f"category-{country_slug}" not in card_classes`.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- README: add scholarshipdb.net and nature.com/careers to Credits
- README: add new scraper files to project structure tree
- docs: fix stray 'si' characters at start of index.html
- docs: update multi-source card (3 → 5 sources)
- docs: update "Search job boards" step to list all 5 sources
- docs: add scholarshipdb and nature.com/careers source cards
- docs: update architecture tree with new scraper files
- docs: update test count 125 → 156
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Location filter fixes:
- euraxess: loc_text defaulted to the searched location when the HTML
element was missing, causing all locationless jobs to pass country
filters; now defaults to "" so they are correctly excluded
- mlscientist: filter was skipped entirely for countries not in
_COUNTRY_SLUG (falsy country_slug short-circuited the condition);
added a second filter block for unmapped countries using card loc_text
- mlscientist: added ireland, austria, italy (confirmed on site);
removed canada (category does not exist on mlscientist.com)
New scrapers:
- scholarshipdb.net: worldwide aggregator with 28k+ positions; country
filtering via URL path (/scholarships-in-{Country}); Europe post-filter
via _EUROPEAN_COUNTRIES set; relative-date posted field supported
- nature.com/careers: multidisciplinary global board; keyword search via
URL; location filter client-side via ISO-3166 country codes in location
strings (e.g. "Berlin (DE)"); "New" badge mapped to posted="1 day a…
The agent worktree left a ghost submodule entry that was causing
GitHub Pages CI to fail with "No url found for submodule path".
Also strips HF frontmatter from GitHub README (push_to_hf.sh adds
it automatically when deploying to HF Space).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: add .nojekyll to disable Jekyll on GitHub Pages
- Add eligibility gate table and callout in Job Sources section
- Mention PhD cap in Overview "Score & rank" step
- Remove HF frontmatter block from GitHub README
- Remove Job sources table from README (covered in full docs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: update HTML and README for new agent/ folder structure
- Update project tree in docs/index.html (Architecture section)
- Update prompts section: prompts/ directory with per-service files
- Update "Adding a source" code snippet to use agent/search/scrapers/
- Update test count: 109 → 125
- Update README.md project structure tree to match
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refactor: reorganize agent/ into functional subfolders + split prompts
- New agent/prompts.py: all LLM prompts in one place (edit to tune behaviour)
- config.py: add default_model, scraper_delay, recent_days, deadline_warn_days,
min_score_default, max_results_per_source
- app.py: remove model dropdown — hardcoded to config.default_model
- README: strip 4x duplicate HF frontmatter, update structure/model sections
- push_to_hf.sh: guard against prepending frontmatter if already present
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: surface LLM error message instead of silently returning score=0
When _generate_groq/_generate_hf raises RuntimeError (rate limit, auth
error, etc.), the error was silently swallowed and every job got score=0
with no diagnostic info. Now the actual error message is preserved in
_generate_json and shown in the job's Concerns field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: force-push to HF Space to avoid non-fast-forward after frontmatter reset
- Filter out listings posted in previous years or with expired deadlines
- Add `freshness` field to each job: 🟢 Recent (≤30d), 🟡 Older,
🔴 Closing soon (deadline ≤14d), or "" when no date is available
- Show freshness in results table and job details panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: strip HF frontmatter from README + add push_to_hf.sh
push_to_hf.sh injects the frontmatter into a temporary commit,
pushes to HF Space, then immediately reverts — keeping GitHub clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete scrapers/web.py and remove duckduckgo-search dependency
- Add _parse_date() to BaseScraper (handles ISO, DD Month YYYY,
Month DD YYYY, DD/MM/YYYY with prefix stripping)
- Store `posted` field in Euraxess and mlscientist listings
- Sort results by (has_date, date desc, description length):
dated listings appear first, newest to oldest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: strip HF frontmatter from README for GitHub
Only llama-3.3-70b-versatile and llama-3.1-8b-instant are currently
available on Groq's free production tier. Update app.py, README, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove WebSearchScraper from active scrapers in JobSearcher._build_scrapers
- Remove 'any' from position type dropdown, default to 'phd'
- Add documentation link to README
- Update all docs pages to reflect changes (sources, web-ui, overview, api, index)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: add full MkDocs Material documentation site
- 11 pages covering installation, usage, architecture, API reference, deployment
- GitHub Actions workflow auto-deploys to gh-pages branch on push to main
- Site will be available at https://hipsterfil998.github.io/PhDScout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Groq (OpenAI-compatible) backend to LLMClient and config
- Auto-select Groq when GROQ_API_KEY secret is set, fall back to HF
- Update JobAgent to accept backend + api_key instead of HF-only token
- Raise LLMQuotaError (402) explicitly instead of silently scoring 0
- Switch model list to Groq models (llama-3.3-70b, llama-3.1-8b, gemma2, mixtral)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: restore HF frontmatter on hf branch after merge
- Instruct LLM to rely on title/institution when description is a short excerpt
- Require semantic equivalence (NLP = natural language processing, ML = machine learning)
- Treat adjacent/complementary fields as partial overlap (score >= 55)
- Highlight ALL matching areas including transferable skills and publications
- Be generous on ambiguous evidence rather than penalising missing keywords
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HF-specific frontmatter now lives only on the hf branch.
main branch README is clean for GitHub display.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs: center title, remove features table from README
Add live demo link, features table highlighting free usage,
project structure, local setup instructions, and models table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The minimum score now acts as a visual filter for the recommended table
only — all positions are available in the Review tab dropdown, sorted
by score. Users can review and approve any position regardless of score.
- job_matcher.score_all(): remove min_score filter, always return all
- pipeline.score_jobs(): drop min_score param (no longer needed)
- app.py: separate scored (all) from recommended (>= min_score);
scored_df shows recommended only, position_selector shows all
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
refactor: remove dead code, extract shared job helpers
agent/utils.py:
- Add job_institution(job) — eliminates repeated .get("institution", .get("company",...))
pattern; the "company" fallback was dead (no scraper ever sets it)
- Add job_description(job, max_chars) — eliminates repeated [:3000] truncation pattern
agent/job_searcher.py:
- Remove _TYPE_QUERY dict (defined but never referenced anywhere)
- Move _MLSCI_NON_COUNTRY from inside the loop body to module-level frozenset
- Fix module docstring (remove stale FindAPhD/jobs.ac.uk-only references)
agent/job_matcher.py, cover_letter.py, cv_tailor.py:
- Use job_institution() and job_description() from utils
app.py:
- Use job_institution() in all 7 display/logic locations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>