522 Commits

Author SHA1 Message Date
5401f384c1 fix(discovery): enforce search-country allow-list when Canada (etc.) is selected
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 5m19s
CI / Type Check (adzuna-extractor) (push) Successful in 1m10s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m13s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m10s
CI / Type Check (orchestrator) (push) Successful in 1m27s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m10s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m10s
CI / Documentation (push) Successful in 1m59s
Reject vague Remote/Worldwide and any non-selected country at ingest; hide mismatched jobs in the UI and stop bypassing country filters for remote listings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 18:34:35 -04:00
71f34853fd fix(discovery): use textMatchesKeyword for single deal-breaker tokens
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 5m23s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m14s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m11s
CI / Type Check (orchestrator) (push) Successful in 1m26s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m9s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m11s
CI / Documentation (push) Successful in 1m59s
Passing a string into textMatchesAnyKeyword caused keywords.some is not a function when search profile deal-breakers were applied after extract.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 17:57:20 -04:00
d28a6221e4 fix(qajobsboard): drop expired LinkedIn reposts and resolve hiring location
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 6m10s
CI / Type Check (adzuna-extractor) (push) Successful in 1m9s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m13s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m9s
CI / Type Check (orchestrator) (push) Failing after 1m16s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m9s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m10s
CI / Documentation (push) Successful in 1m56s
Probe application links for closed listings and feed expires_at; enrich vague Remote/Worldwide rows with real country before blocked-countries filtering.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 17:42:19 -04:00
0de7f90278 fix(filters): match co-op/intern skip tokens in titles with hyphen normalization
Some checks failed
CI / Linting (Biome) (push) Failing after 40s
CI / Tests (push) Successful in 5m12s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m13s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m9s
CI / Type Check (orchestrator) (push) Failing after 1m17s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m10s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m12s
CI / Documentation (push) Successful in 2m0s
Company skip list and profile deal-breakers now ignore hyphens when matching,
apply skip keywords to job titles as well as employers, and short-circuit
scoring when a deal-breaker hits so co-op posts cannot score 80 via the LLM.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 17:31:59 -04:00
03d293699a feat(qajobsboard): fetch job detail pages for concrete location text
Some checks failed
CI / Linting (Biome) (push) Failing after 40s
CI / Tests (push) Successful in 5m13s
CI / Type Check (adzuna-extractor) (push) Successful in 1m10s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m14s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m11s
CI / Type Check (orchestrator) (push) Successful in 1m30s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m12s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m13s
CI / Documentation (push) Successful in 1m57s
The jobs.json feed often labels roles Remote/Worldwide while the public
job page JSON-LD and description include the real city (e.g. Mumbai/Nagpur).
Enrich vague rows by reading each QAJobsBoard detail URL before import.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 17:20:53 -04:00
0a63316100 fix(discovery): block countries in vague locations via job description
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 5m22s
CI / Type Check (adzuna-extractor) (push) Successful in 1m9s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m14s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m11s
CI / Type Check (orchestrator) (push) Successful in 1m28s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m13s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m12s
CI / Documentation (push) Successful in 2m0s
QAJobsBoard and similar feeds often store Worldwide/Remote while the real
country is only in the description. Scan title and description when location
is vague, and prefer concrete locations from QAJobsBoard postings.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 17:15:18 -04:00
f0261711c6 chore(cron): expand QA automation search terms for scheduled runs
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 5m22s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m14s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m10s
CI / Type Check (orchestrator) (push) Successful in 1m26s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m10s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m11s
CI / Documentation (push) Successful in 1m59s
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 16:54:38 -04:00
2e44a131e1 fix(jobs): treat isRemote as 100% remote only; tighten cron for Canada QA
Reject hybrid or partial-office postings at ingest so the Remote badge and
filters match fully remote roles. Cron can PATCH search geography, remote-only
workplace types, and QA search terms before each scheduled pipeline run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 15:53:55 -04:00
f5179304c1 feat(discovery): blocked countries filter and smoke subprocess fixes
Some checks failed
CI / Linting (Biome) (push) Failing after 41s
CI / Tests (push) Successful in 5m27s
CI / Type Check (adzuna-extractor) (push) Successful in 1m9s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m13s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m9s
CI / Type Check (orchestrator) (push) Successful in 1m24s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m8s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m9s
CI / Documentation (push) Successful in 1m59s
Add blockedCountries in Settings so pipeline discovery drops jobs whose
location mentions listed countries (existing discovered rows are kept).
Document the feature, fix smoke tsconfig inheritance for nested extractors,
and run smoke via an absolute-tsconfig wrapper.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-16 11:41:29 -04:00
c840f289e1 feat(extractors): expand catalog, smoke coverage, and sourcing docs
Some checks failed
CI / Linting (Biome) (push) Failing after 40s
CI / Tests (push) Successful in 5m54s
CI / Type Check (adzuna-extractor) (push) Successful in 1m8s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m11s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m8s
CI / Type Check (orchestrator) (push) Successful in 1m23s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m6s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m7s
CI / Documentation (push) Successful in 1m54s
Adds Arc.dev, BC T-Net, Eluta, iCIMS tenants, QAJobsBoard, and SmartRecruiters
manifests with registry/settings/UI wiring; registers full extractor list in
smoke-extractors and documents supplementary board access paths. Aligns Careerjet
v4 with the url query parameter and fixes strict typing in QAJobsBoard.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-15 22:36:23 -04:00
67508d56ea fix(docker): copy full extractors tree into image for runtime manifests
Some checks failed
CI / Linting (Biome) (push) Failing after 35s
CI / Tests (push) Successful in 5m28s
CI / Type Check (adzuna-extractor) (push) Successful in 1m5s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m9s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m4s
CI / Type Check (orchestrator) (push) Successful in 1m21s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m4s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m5s
CI / Documentation (push) Successful in 1m55s
The Dockerfile only copied a fixed list of extractor dirs; new sources
were listed in shared but their manifest.ts files were absent from the
container, so discovery logged missingManifest in production.

Copy extractors/ once before npm install in builder and production, and
skip redundant per-extractor COPY lines. Add extractors/*/storage/ to
.dockerignore to avoid baking local cache into the build context.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 20:36:27 -04:00
7b3dfb002a feat(extractors): add 17 job source extractors and cross-source dedup
Some checks failed
CI / Linting (Biome) (push) Failing after 36s
CI / Tests (push) Successful in 5m54s
CI / Type Check (adzuna-extractor) (push) Successful in 1m6s
CI / Type Check (gradcracker-extractor) (push) Successful in 1m9s
CI / Type Check (hiringcafe-extractor) (push) Successful in 1m5s
CI / Type Check (orchestrator) (push) Successful in 1m21s
CI / Type Check (startupjobs-extractor) (push) Successful in 1m4s
CI / Type Check (ukvisajobs-extractor) (push) Successful in 1m4s
CI / Documentation (push) Successful in 1m52s
Adds extractor packages: arbeitnow, ashby, careerjet, fourdayweek,
greenhouse, himalayas, jobicy, jooble, lever, reed, remoteok, remotive,
themuse, usajobs, weworkremotely, workday — each with manifest, package
metadata and README.

Pipeline / shared:
- shared/job-fingerprint: stable hash for cross-source dedup, with tests
- discover-jobs: dedup via fingerprint and richer per-source merging
- jobs repository: fingerprint-aware upsert / lookup
- settings-registry, settings types/routes, demo-defaults: knobs for the
  new sources
- shared extractors index: register the new manifests
- location-support, profiles route: small fixes for the new sources

Tooling:
- scripts/smoke-extractors.ts to sanity-check each source locally
- scripts/jobber-cron-{cherepaha,dobkin}.env.example: per-host cron
  templates (CHANGEME placeholders only)
- .env.example: documented env vars for the new extractors
- .gitignore: ignore extractors/*/storage/ runtime caches (was ukvisajobs only)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 20:17:52 -04:00
b72612fd06 Add Basic Auth gate, job owner context, and multi-tenant job isolation.
- Server: auth routes, owner profile on requests/jobs/pipeline, migrations
- Client: BasicAuthAppGate, SSE/API session handling, profile quick switch
- Tests: tracer-links, ghostwriter request-context mock, pipeline coverage
- Env examples for cron and optional basic auth credentials

Made-with: Cursor
2026-04-20 21:34:42 -04:00
e39341258a feat(orchestrator): blocked company filters and keyword parsing
- Add shared helper to parse blocked company keywords from JSON or legacy text
- Wire discover-jobs to resolved keywords for employer blocking; extend filters UI
- Include vite/client in TS types for import.meta.env; fix JobListItem test fixture

Made-with: Cursor
2026-04-11 12:04:38 -04:00
60b61ffe03 feat: job notes, deal-breaker score cap, richer cover letters, bulk action limit bump
- Add per-listing notes (JobNotes component, notes column, auto-save)
- Enforce hard score cap (≤15) when deal-breaker hits are present;
  add clearance/citizenship deal-breaker rules to scoring prompt
- Cover letter prompt now uses full search profile (experience level,
  skills, work arrangement, location, salary, industries, deal-breakers)
  and produces longer, name-signed output
- Include candidate name + location in sanitized scorer profile
- Raise MAX_JOB_ACTION_BATCH_SIZE from 100 → 2500 (shared constant)
- Update README with new features

Made-with: Cursor
2026-04-06 15:55:26 -04:00
4d7c8ac0bc feat(orchestrator): job list filters — multi source/country, URL sync, exclude
- Parse location strings into country keys (shared search-cities helper).
- URL params: source, sourceExclude, countries, countriesExclude.
- Chip cycle: off → include → exclude (destructive); remote bypasses country rules.
- README: document filter behaviour and query keys.

Unrelated local changes (scorer, notes, schema, etc.) remain unstaged.

Made-with: Cursor
2026-04-06 15:50:47 -04:00
77179b2b94 feat(orchestrator): local JSON base resume for PDF generation
Use JOBOPS_LOCAL_RESUME_PATH or Settings local path as the tailored PDF
source when Reactive Resume template is not selected. Align GET
/api/profile/status with local resume configuration. Update route test
mocks for resolveLocalResumeFilePath.

Includes discovered-panel UI tweaks in DecideMode and DiscoveredPanel.

Made-with: Cursor
2026-04-05 23:47:25 -04:00
87dbda3df1 Fix Fit assessment header and job list toolbar spacing on reload
- Put match badges in their own flex-wrap row under the title (no run-on text)
- Toolbar: flex-wrap, min-w-0 label, shrink-0 count, middot separator on narrow layouts

Made-with: Cursor
2026-04-05 22:22:41 -04:00
6b26f70ef7 Make cover letter discoverable: Overview, Ready panel, ⋯ menu
- Always show Cover letter card with Generate when empty; Regenerate + Copy when present
- Shared useCoverLetterGeneration hook calling runJobAction(generate_cover_letter)
- Ready tab previously had no cover letter UI; add same block under Fit Assessment
- Floating bar Cover letter button tooltip points to Overview/Ready
- Job detail ⋯ menu: Generate / Regenerate cover letter

Made-with: Cursor
2026-04-05 21:53:27 -04:00
54adc66e73 Score hybrid/onsite jobs low when job search profile is remote-only
- Require workArrangementMatch in LLM schema; show badge in Fit Assessment
- Prompt: remote-only vs hybrid/N days in office is a hard cap (~35 score)
- Deterministic cap from JD keywords + isRemote/workFromHomeType when only Remote is selected
- hasNonEmptyProfile includes preferredWorkArrangement and preferredLocations so prefs reach the scorer

Made-with: Cursor
2026-04-05 21:40:35 -04:00
14a6da4bdf Improve job scoring for QA vs generic SWE roles; document Ollama on 16GB GPU
- Cap suitability score when roleTypeMatch is low and target roles are set
- Harden scoring prompt (role-type gating, examples, headline in resume payload)
- QA-oriented mock scoring when LLM is unavailable
- .env.example: optional Ollama MODEL/LLM_BASE_URL block for self-hosted LLM

Made-with: Cursor
2026-04-05 21:35:40 -04:00
1d450d7cc5 docs: SQLite deploy uses .backup and remove WAL/SHM on VM
Made-with: Cursor
2026-04-05 20:03:06 -04:00
09ab32e1e8 chore: default pipeline includes Glassdoor; document DB copy and cron sources
- Add glassdoor to DEFAULT_CONFIG so POST /api/pipeline/run with {} runs JobSpy trio.
- jobber-pipeline-telegram.sh: optional JOBBER_PIPELINE_SOURCES for explicit source list.
- Deploy doc: WAL checkpoint + rsync jobs.db to VM for profiles/settings/jobs.

Made-with: Cursor
2026-04-05 19:49:01 -04:00
fea00ae656 feat: search profiles, cover letters, discovery fixes
- Add search profiles (DB, API, settings UI) and wire into scorer/pipeline search terms.
- Add cover letter generation (service, job action, JobDetail UI).
- Align JobSpy Indeed country with country-level search geography when settings conflict; warn in logs.
- Infer country from search cities via inferCountryKeyFromSearchGeography (shared).
- Ignore extractor venv/storage and local data in Biome; ignore orchestrator/storage and JobSpy .venv in git.
- Vite: do not watch orchestrator/storage (prevents reloads during startup.jobs pipeline).
- JobSpy: document Python 3.10+ and venv setup in README/requirements.
- Onboarding and settings: local resume path handling, orchestrator .env.example for Vite.

Made-with: Cursor
2026-04-05 19:35:14 -04:00
0a7dbb4f16 fix(docker): bake VITE_SKIP_RXRESUME_ONBOARDING into client build
Production images previously omitted the flag, so the full RxResume wizard
always appeared. Default skip matches self-hosted LLM-in-.env workflows;
override via docker-compose build args if needed.

Made-with: Cursor
2026-04-05 14:44:59 -04:00
b2a2507615 fix(scripts): Telegram pipeline summary — timestamp compare, retries, diagnostics
- Normalize SQLite vs ISO discoveredAt for run-window filtering
- Retry jobs list after run; compressed JSON requests
- Cross-check GET /api/jobs/revision when list is empty
- Docs: cron at 9/13/18, pull + redeploy steps for VM

Made-with: Cursor
2026-04-04 22:03:53 -04:00
8a08d4991e fix(scripts): Telegram job list compares SQLite vs ISO discoveredAt 2026-04-04 21:43:50 -04:00
ae7e50fa91 feat(scripts): Telegram message includes employer, title, posting links
Made-with: Cursor
2026-04-04 16:42:04 -04:00
3d6dda35b0 docs: simplify README for personal fork; remove upstream FUNDING.yml
Made-with: Cursor
2026-04-04 16:12:22 -04:00
14b7bb34cf chore: gitignore cron Telegram env; ship pipeline+Telegram script and deploy steps
Made-with: Cursor
2026-04-04 16:10:27 -04:00
8d8c6f0ed0 fix(docs): company-skip-list links for Docusaurus next build 2026-04-04 15:31:40 -04:00
ilia
9576c3d7a1 feat: workplace filter, job dedup, company skip docs, deploy notes
- Add remote/orchestrator filter by workplace (remote, not remote, unknown) with URL param
- Expose isRemote on job list API; canonicalize URLs and source_job_id dedup on import
- Onboarding: optional VITE_SKIP_RXRESUME_ONBOARDING for RxResume-free onboarding
- Scoring UI + docs for company skip list; pipeline-run dedup note
- Vitest: TZ=UTC for stable time-based tests
- DEPLOY_GITEA_VM_CRON_TELEGRAM.md for VM/cron/Telegram ops

Made-with: Cursor
2026-04-04 14:44:52 -04:00
Shaheer Sarfaraz
0c31377ac6
Add Ko-fi username to FUNDING.yml 2026-03-22 17:42:34 +00:00
Ammad Ali
69a10acd4f
fix: render markdown in expanded job descriptions (#297)
* fix: render markdown in expanded job descriptions

* fix: respect markdown job description setting and harden rendering
2026-03-22 17:01:34 +00:00
Ryan Foote
0b22c08d7d
feat: add support for indicating workplaceTypes (#296) 2026-03-21 20:43:43 +00:00
Ammad Ali
8274ec4e14
Enhance model handling and settings integration for providers (#295) 2026-03-21 17:34:47 +00:00
0x1355
7f517776df
fix: auto-detect jobspy venv so contributors don't need PYTHON_PATH (#293) 2026-03-20 08:18:27 +00:00
Shaheer Sarfaraz
dc2c7ab2df
Update README with additional badges
Added badges for GitHub stars, Docker, release status, and contributors.
2026-03-19 19:46:22 +00:00
Shaheer Sarfaraz
7db7b374a8
Change banner image in README.md
Updated the banner image in the README file.
2026-03-19 12:26:48 +00:00
Ammad Ali
ac0a1281f4
Enhance RxResume validation, settings handling, and caching (#287)
* feat: enhance validation handling in ReactiveResumeConfigPanel and rxresume-config

* feat: enhance RxResume validation handling in SettingsPage and ReactiveResumeSection

* feat: enhance RxResume settings handling and cache management

* feat: add save-time validation and caching for Reactive Resume settings

* refactor: improve code formatting and readability across multiple files

* fix: improve condition check in hasOverrideKey function

* feat: enhance RxResume validation and settings handling with precheck options

* refactor: streamline RxResume client initialization and improve backup sorting logic
2026-03-19 11:38:04 +00:00
0x1355
4787f4d151
feat(ghostwriter): branching conversations with edit and per-message regenerate (#290)
Turn Ghostwriter's flat message list into a tree structure, enabling
Claude.ai/ChatGPT-style branching conversations.

**Data model**: Add `parentMessageId` and `activeChildId` to messages,
`activeRootMessageId` to threads. Migration backfills existing messages
into a linear chain and links regenerated messages as siblings.

**Backend**: Tree-walking queries (getActivePathFromRoot, getAncestorPath,
getSiblingsOf), rewritten history builder that follows the ancestor path,
new editMessage and switchBranch services, regenerate now works on any
assistant message (not just the latest).

**Frontend**: BranchNavigator component (← 2/3 → arrows), inline edit on
user messages, per-message regenerate on assistant messages, regenerate
button removed from composer (now per-message).

**Infra**: Pin Node 22 via Volta to prevent ABI mismatches with
better-sqlite3 across environments.
2026-03-19 11:25:00 +00:00
0x1355
f19471ab58
Fix stale job detail showing wrong tab actions on tab switch (#286)
When switching between job tabs (e.g. Discovered → Applied), the detail
panel would briefly show the previously selected job with the new tab's
action buttons — confusing and error-prone.

Three coordinated fixes:
- setActiveTab now checks if the selected job's status fits the target
  tab, keeping it when valid (e.g. Discovered → All Jobs) and clearing
  it otherwise.
- New visibleSelectedJob useMemo guard synchronously nulls out the
  selected job when it doesn't belong to the active tab, eliminating
  the one-frame flash caused by the data hook's useEffect lag.
- Auto-select effect now handles the case where a job passes the status
  check but gets filtered out by source/sponsor/salary filters.
2026-03-19 09:39:13 +00:00
0x1355
4894711396
feat: add Ghostwriter "Start over" reset with confirmation dialog (#289) 2026-03-19 08:44:40 +00:00
Shihab Hasan
0b55cb260a
“Search for a company” input can expand to full available width on desktop (#285) 2026-03-18 21:33:46 +00:00
Jeet Jawale
cdd23f5ecf
feat: add local search to docs site (closes #203) (#282)
* feat: add local search to docs site (closes #203)

* chore: update package-lock.json for search plugin

* fix: biome  format docusaurus config
2026-03-18 16:16:29 +00:00
github-actions[bot]
e8f53405c1 chore: release 0.2.0 2026-03-17 12:22:29 +00:00
Shaheer Sarfaraz
71e640b563
Add startup.jobs extractor support (#279)
* Add startup.jobs extractor support

* Harden startup.jobs extractor inputs

* Wire startupjobs into Docker and CI

* Tighten startupjobs review follow-ups

* fix: publish ghcr during release workflow

* feat: add startupjobs max jobs configuration and update related tests
2026-03-17 12:20:45 +00:00
Shaheer Sarfaraz
26275e4ee8
Fix ready-job selection jumping after PDF regeneration (#276)
* Preserve selected ready job during refresh

* show processsing in ready
2026-03-16 19:48:43 +00:00
Shaheer Sarfaraz
4e91a5ffcd
Update README.md 2026-03-16 17:04:56 +00:00
Shaheer Sarfaraz
ea1d445646
Update README.md 2026-03-16 17:03:24 +00:00