Summary
normalize_job_query() replaces the entire search query with a single token whenever the query contains a role word. A stack-specific query cannot reach the platform adapters.
Current behavior
src/careerkit/jobs/application/title_filter.py:45-56:
def normalize_job_query(query: str) -> str:
normalized = query.strip()
query_lower = normalized.lower()
if "백엔드" in normalized:
return "백엔드"
if re.search(r"\bback(?:-|\s)?end\b", query_lower):
return "Backend"
if "서버" in normalized:
return "서버"
if re.search(r"\bserver\b", query_lower):
return "Server"
return normalized
The match is a containment test and the return discards the rest of the string:
| Input |
Sent to adapter |
PHP Laravel 백엔드 |
백엔드 |
Go 서버 개발자 |
서버 |
Kotlin Backend Engineer |
Backend |
PHP Laravel |
PHP Laravel |
Reproduce:
from careerkit.jobs.application.title_filter import normalize_job_query
normalize_job_query("PHP Laravel 백엔드") # '백엔드'
Observed in a career-jobs search run -q "PHP Laravel 백엔드" run: the adapter logged query='백엔드' and walked 39 pages of generic backend postings. None of the 12 returned postings mentioned the requested stack.
Why this matters
The widen-then-filter design is reasonable for recall, but it makes one class of search impossible rather than merely broad. A user narrowing by stack has no way to express it if the query also names the role, and nothing reports that the narrowing was dropped. The run looks successful: status: ok, a populated postings list, no diagnostic.
--query accepts a free string, so the CLI surface implies the query is used.
Suggested direction
Not prescribing an implementation, but the options seem to be:
- Keep the widening but preserve the discarded terms for the post-fetch quick filter, so a stack term still narrows results.
- Normalize only when the query is exactly a role word, leaving multi-term queries intact.
- Keep current behavior and emit a diagnostic naming the substitution, so
search run --json reports that the query was rewritten.
Option 3 alone would have saved the investigation even if the behavior stays.
Notes
normalize_job_query has no direct test coverage (tests/jobs/application/test_title_filter.py does not reference it), so any change here needs tests added first.
- Callers:
src/careerkit/jobs/application/config.py:231 (config defaults), src/careerkit/jobs/application/search.py:200 (run path).
Summary
normalize_job_query()replaces the entire search query with a single token whenever the query contains a role word. A stack-specific query cannot reach the platform adapters.Current behavior
src/careerkit/jobs/application/title_filter.py:45-56:The match is a containment test and the return discards the rest of the string:
PHP Laravel 백엔드백엔드Go 서버 개발자서버Kotlin Backend EngineerBackendPHP LaravelPHP LaravelReproduce:
Observed in a
career-jobs search run -q "PHP Laravel 백엔드"run: the adapter loggedquery='백엔드'and walked 39 pages of generic backend postings. None of the 12 returned postings mentioned the requested stack.Why this matters
The widen-then-filter design is reasonable for recall, but it makes one class of search impossible rather than merely broad. A user narrowing by stack has no way to express it if the query also names the role, and nothing reports that the narrowing was dropped. The run looks successful:
status: ok, a populatedpostingslist, no diagnostic.--queryaccepts a free string, so the CLI surface implies the query is used.Suggested direction
Not prescribing an implementation, but the options seem to be:
search run --jsonreports that the query was rewritten.Option 3 alone would have saved the investigation even if the behavior stays.
Notes
normalize_job_queryhas no direct test coverage (tests/jobs/application/test_title_filter.pydoes not reference it), so any change here needs tests added first.src/careerkit/jobs/application/config.py:231(config defaults),src/careerkit/jobs/application/search.py:200(run path).