From eee608a2136626366a0fb01ffac5212060f47f73 Mon Sep 17 00:00:00 2001 From: Dennis Thiessen Date: Thu, 22 Oct 2026 09:42:47 +0200 Subject: [PATCH] fix(scout): English-only requirement reads ENGLISH OK; triage 2026-10-22 decisions - classify_language_requirement: an ad stating only an English requirement ("communication and presentation skills in English") with no Norwegian requirement now reads english_ok. Checked after the Norwegian patterns, so "fluent English and Norwegian" still reads norwegian_required. Nordic Semiconductor's ads read UNCLEAR in the first Norway run. - Decisions from the 2026-10-22 run: Nordic Embedded Software Test Automation Engineer `maybe` (embedded/Bluetooth experience required, coursework only - the Kongsberg gate); Nordic ATE Test Engineer `skip`; RUAG Senior DevOps Engineer C5I repost `skip` ("Swiss citizenship required"; a different role from the July shortlist, whose note is carried into the new row). Co-Authored-By: Claude Opus 5.5 --- job_scout/scout.py | 15 ++++++++++++++- job_scout/state/decisions.json | 28 +++++++++++++++++++++------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/job_scout/scout.py b/job_scout/scout.py index 970339f..5c42725 100644 --- a/job_scout/scout.py +++ b/job_scout/scout.py @@ -1985,6 +1985,15 @@ _LANG_NORWEGIAN_REQUIRED = [re.compile(p, re.I) for p in ( r"norwegian\s+(?:language\s+)?(?:is\s+)?(?:required|mandatory|a\s+requirement|essential)", r"(?:must|need\s+to|required\s+to)\s+(?:\w+\s+){0,4}(?:norwegian|scandinavian)", )] +# An ad that states only an English requirement ("communication and presentation skills in +# English", Nordic Semiconductor 2026-10-22). Checked only AFTER no Norwegian requirement was +# found, so "fluent English and Norwegian" still reads as Norwegian required. +_LANG_ENGLISH_STATED = [re.compile(p, re.I) for p in ( + r"(?:communication|presentation|written|spoken|verbal|language)\s+(?:and\s+\w+\s+)?skills?\s+in\s+english", + r"(?:fluent|fluency|proficien\w*|excellent|good|strong)\s+(?:\w+\s+){0,2}(?:in\s+)?english", + r"english\s+(?:is\s+)?(?:required|a\s+must|mandatory)", + r"(?:gode|god|flytende|svært\s+gode)\s+(?:\w+\s+){0,3}engelsk", +)] # A "Norwegian" that belongs to clearance or citizenship wording is not a language demand. _LANG_FALSE_CONTEXT = re.compile( r"clearance|klarering|statsborger|citizen|myndighet|authorit|armed\s+forces|forsvar", re.I) @@ -2025,7 +2034,11 @@ def classify_language_requirement(text, work_language_tags=None): if result["lang"] == "norwegian_required": break else: - if tags and all(t.startswith("engelsk") or t == "english" for t in tags): + stated = next((m for p in _LANG_ENGLISH_STATED if (m := p.search(text))), None) + if stated: + result.update(lang="english_ok", + evidence=_snippet(text, stated) + " (English stated, no Norwegian requirement)") + elif tags and all(t.startswith("engelsk") or t == "english" for t in tags): result.update(lang="english_ok", evidence="NAV work-language tag: English only") elif tags: result["evidence"] = f"no requirement sentence found; NAV tag: {', '.join(tags)}" diff --git a/job_scout/state/decisions.json b/job_scout/state/decisions.json index 2220345..d4f61d5 100644 --- a/job_scout/state/decisions.json +++ b/job_scout/state/decisions.json @@ -146,13 +146,6 @@ "note": "TOP CANDIDATE 2026-07-03 run. ISE = MSFT forward-deployed org (ex-CSE): co-engineering with strategic customers. IC4, published base CHF 146.2-245.9k clears bar; German explicitly beneficial; travel up to 25%; AI/LLM reqs are integration-side (RAG, prompt eng, model monitoring) not model-building. Zürich hybrid from Bern. | SENT 2026-07-03 (resume+CL finalized, 85.8/100). REJECTED 2026-08-11, no interview (~39 days after submission). Separate Microsoft req 200043897 (Principal FDE, German-speaking, Zürich) remains open and is unaffected.", "date": "2026-07-03" }, - "https://jobs.ruag.ch/offene-stellen/senior-devops-engineer-c5i/3b3093ab-badc-4e95-8166-0f6ee32c18d0": { - "company": "RUAG (Thun/Bern)", - "title": "Senior DevOps Engineer C5I", - "decision": "shortlist", - "note": "Bern-local WLB-exception tier. English-first (German a plus); Linux/Docker+K8s/Python/GitLab CI/Prometheus-Grafana-ELK = core DevOps lane; analytics-platform ops for Army Cyber Command (C5I, 260p unit, DevSecOps). No citizenship gate in JD (only criminal-record/debt excerpts) but verify clearance as German citizen. Comp likely lateral (market + 13th month) — local tier has relaxed bar. Contact: recruiting-c5i@ruag.ch.", - "date": "2026-07-03" - }, "https://job-boards.greenhouse.io/gitlab/jobs/8522408002": { "company": "GitLab", "title": "Forward Deployed Engineer - Germany (Staff)", @@ -2887,5 +2880,26 @@ "decision": "applied", "note": "USER DECISION: SUBMITTED 2026-10-21 via Google Careers, cold (no referral). Evidence Fit 70, fit class Stretch, hard gate PASS, Document Quality ~86 (post-edit estimate; critique scored 84 before the last edit). Package: output/Google_Staff_SWE_Shopping_Graph/. Registry id app-google-staff-shopping-graph-102064172115600070.", "date": "2026-10-21" + }, + "https://jobs.ruag.ch/offene-stellen/senior-devops-engineer-c5i/cd0c7781-211e-46db-bfba-3fa3c2dd50e4": { + "company": "RUAG (Thun/Bern)", + "title": "Senior DevOps Engineer C5I", + "decision": "skip", + "note": "Claude triage 2026-10-22, JD read (reports/2026-10-22-fit-sources/ruag_senior_devops_c5i.txt). DIFFERENT ROLE from the 2026-07-03 shortlisted req of the same title (3b3093ab, analytics-platform ops, since closed): this one runs self-hosted email/groupware/collaboration services on an on-prem private cloud (LDAP/OIDC, Terraform+Ansible, Kubernetes), Bern. Hard gate: 'Swiss citizenship required' - he is a German citizen. Also 'Experience with self-hosted email, groupware or collaboration platforms' is personal-only (PP-3 mail/Nextcloud server) and Terraform is forbidden. Superseded row note (July): shortlist, Bern-local WLB tier, Linux/Docker/K8s/Python/GitLab/Prometheus-Grafana-ELK DevOps lane, no citizenship gate in THAT JD.", + "date": "2026-10-22" + }, + "https://careers.nordicsemi.com/jobs/8483837-embedded-software-test-automation-engineer": { + "company": "", + "title": "", + "decision": "maybe", + "note": "TRIAGE 2026-10-22 (JD read, reports/2026-10-22-fit-sources/nordic_embedded_sw_test_automation.txt), NOT a user decision. Nordic Semiconductor, Oslo or Trondheim; English working language ('communication and presentation skills in English'); employer rated GOOD (Glassdoor 4.0/103). CI/CD for a multi-platform Bluetooth stack: Python strong - Direct; Jenkins + Docker + CI/CD pipelines - Direct (FC-1, BS-6, VZ-2, SW-3 historical); Grafana/monitoring + database - Adjacent (BS-4 PoC); Bash tooling Direct; Groovy named in duties - forbidden. HARD GATE: required 'Experience in embedded software development, especially within Bluetooth stack or other wireless protocol projects' and 'embedded development kits' - ED-1 coursework only. Same gate the user overrode for Kongsberg Seatex (2026-10-08). User's call.", + "date": "2026-10-22" + }, + "https://careers.nordicsemi.com/jobs/8411130-ate-test-engineer": { + "company": "", + "title": "", + "decision": "skip", + "note": "Claude triage 2026-10-22, JD read (reports/2026-10-22-fit-sources/nordic_ate_test_engineer.txt). Chip production test: 'Proven track record in high frequency, mixed-signal, digital and analog test development and execution' and 'Automated Test Equipment (ATE) Test Development in high volume manufacturing' - Gap. Bosch fab data analysis is adjacent domain, not ATE test development.", + "date": "2026-10-22" } } \ No newline at end of file