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>
This commit is contained in:
2026-05-16 15:53:55 -04:00
co-authored by Cursor
parent f5179304c1
commit 2e44a131e1
9 changed files with 286 additions and 65 deletions
+10 -1
View File
@@ -7,6 +7,7 @@ import { getJobOwnerProfileId } from "@infra/request-context";
import { DEFAULT_JOB_OWNER_PROFILE_ID } from "@server/infra/job-owner-context";
import { buildJobContentFingerprint } from "@shared/job-fingerprint";
import { canonicalizeJobUrl } from "@shared/job-url-canonical";
import { normalizeIsRemote } from "@shared/work-arrangement";
import type {
CreateJobInput,
Job,
@@ -400,7 +401,15 @@ async function insertJob(input: CreateJobInput): Promise<Job> {
salaryMinAmount: input.salaryMinAmount ?? null,
salaryMaxAmount: input.salaryMaxAmount ?? null,
salaryCurrency: input.salaryCurrency ?? null,
isRemote: input.isRemote ?? null,
isRemote:
normalizeIsRemote({
title: input.title,
jobDescription: input.jobDescription,
location: input.location,
workFromHomeType: input.workFromHomeType,
jobType: input.jobType,
isRemote: input.isRemote,
}) ?? null,
jobLevel: input.jobLevel ?? null,
jobFunction: input.jobFunction ?? null,
listingType: input.listingType ?? null,
+2 -56
View File
@@ -4,6 +4,7 @@
import { logger } from "@infra/logger";
import type { Job, JobSearchProfile, SuitabilityAnalysis } from "@shared/types";
import { jobLikelyRequiresOfficePresence } from "@shared/work-arrangement";
import { LlmService } from "./llm/service";
import type { JsonSchemaDefinition } from "./llm/types";
import { stripMarkdownCodeFences } from "./llm/utils/json";
@@ -326,61 +327,6 @@ function candidateWantsRemoteOnly(p: JobSearchProfile): boolean {
return true;
}
/**
* Job text / metadata suggests hybrid or mandatory office presence (not remote-only).
*/
function jobSignalsHybridOrOnsite(job: Job): boolean {
const blob = [
job.title,
job.jobDescription ?? "",
job.location ?? "",
job.workFromHomeType ?? "",
job.jobType ?? "",
]
.filter(Boolean)
.join("\n")
.toLowerCase();
const strongRemoteOnly =
/\b100%\s*remote\b|\bfully\s+remote\b|\bremote[\s-]only\b|\bcompletely\s+remote\b|\bwork\s+from\s+anywhere\b|\banywhere\s+in\s+the\s+(us|usa|uk|world)\b/.test(
blob,
);
const hybridOrOffice =
/\bhybrid\b/.test(blob) ||
/\bremote[\s-]?hybrid\b/.test(blob) ||
/\bhybrid[\s-]?remote\b/.test(blob) ||
/\b\d[\d]?\s+days?\s+(a|per)\s+week\b.*\b(in[\s-]?office|on[\s-]?site|onsite|at\s+the\s+office)\b/.test(
blob,
) ||
/\b(in[\s-]?office|on[\s-]?site|onsite|at\s+the\s+office)\b.*\b\d[\d]?\s+days?\b/.test(
blob,
) ||
/\b(one|two|three|four|five|six|seven|eight|nine|ten)\s+days?\b.*\b(in[\s-]?office|on[\s-]?site|onsite)\b/.test(
blob,
) ||
/\b(in[\s-]?office|on[\s-]?site|onsite)\b.*\b(one|two|three|four|five|six|seven|eight|nine|ten)\s+days?\b/.test(
blob,
) ||
/\boffice[\s-]based\b/.test(blob) ||
/\bon[\s-]?site\s+(role|position|required|mandatory)\b/.test(blob) ||
/\b(required|must)\b.*\b(in[\s-]?office|on[\s-]?site|onsite|in[\s-]?person)\b/.test(
blob,
);
const wfh = (job.workFromHomeType ?? "").toLowerCase();
if (wfh.includes("hybrid")) return true;
if (job.isRemote === false) {
if (strongRemoteOnly && !hybridOrOffice) return false;
return true;
}
if (hybridOrOffice) return true;
return false;
}
/**
* Cap score when candidate wants remote-only but the job is hybrid / on-site, or
* when the model admits a poor work-arrangement fit but still scores high.
@@ -396,7 +342,7 @@ function applyRemoteOfficeMismatchCap(
return { score, reason };
}
const officeLikely = jobSignalsHybridOrOnsite(job);
const officeLikely = jobLikelyRequiresOfficePresence(job);
const wam =
typeof data.workArrangementMatch === "number"
? data.workArrangementMatch