From 48965960d36db69f499fc38a8660543869419887 Mon Sep 17 00:00:00 2001 From: Mads Lorentzen Date: Wed, 19 Aug 2026 20:31:20 +0200 Subject: [PATCH] fix(jobbank-search)!: emit deadline as YYYY-MM-DD in search output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The feed's DD.MM.YYYY parenthetical passed through raw - documented, but contradicting the /scrape contract, every other portal, and this CLI's own detail command for the same job, and ambiguous to a date parser (01.09.2026: 1 Sep or 9 Jan). The known shape converts to ISO; løbende still maps to null; unrecognized shapes pass through for /rank's defensive handling. Breaking for anything parsing the old format - the README's own search example already showed ISO. Review finding F5 (2026-08-19), decision approved by Mads. Co-Authored-By: Claude Opus 5 (1M context) --- .agents/skills/jobbank-search/cli/README.md | 2 +- .agents/skills/jobbank-search/cli/src/helpers.ts | 6 +++++- .../skills/jobbank-search/cli/tests/rss-parsing.test.ts | 9 ++++++++- .../cli/tests/search-normalization.test.ts | 2 +- CHANGELOG.md | 9 +++++++++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.agents/skills/jobbank-search/cli/README.md b/.agents/skills/jobbank-search/cli/README.md index 337f0aa..e504758 100644 --- a/.agents/skills/jobbank-search/cli/README.md +++ b/.agents/skills/jobbank-search/cli/README.md @@ -267,7 +267,7 @@ bun run src/cli.ts search --education 24 --suitable-for 2 --since 2026-03-01 | `url` | string | Full URL to job posting | | `posted` | string | Publication date in ISO 8601 | | `date` | string \| null | Publication date as `YYYY-MM-DD` (derived from `posted`), or `null` if absent | -| `deadline` | string \| null | Application deadline as `DD.MM.YYYY` string, or `null` if "løbende" / not present | +| `deadline` | string \| null | Application deadline as `YYYY-MM-DD` (converted from the feed's `DD.MM.YYYY`), or `null` if "løbende" / not present | > `meta.total` is fetched from the HTML page `` in a secondary request (pattern: `"{N} relevante job og karriereopslag"`). If the secondary request fails, `meta.total` is `null`. diff --git a/.agents/skills/jobbank-search/cli/src/helpers.ts b/.agents/skills/jobbank-search/cli/src/helpers.ts index 5b5ba98..d2a5089 100644 --- a/.agents/skills/jobbank-search/cli/src/helpers.ts +++ b/.agents/skills/jobbank-search/cli/src/helpers.ts @@ -135,7 +135,11 @@ export function parseRssDescription(desc: string): ParsedDescription { if (deadlineStr.toLowerCase() === "løbende" || deadlineStr.toLowerCase() === "lobende") { deadline = null } else { - deadline = deadlineStr + // The feed writes DD.MM.YYYY; the /scrape contract (and this CLI's own + // detail command) use YYYY-MM-DD. Convert the known shape; anything else + // passes through so an unexpected value stays visible downstream. + const dmy = deadlineStr.match(/^(\d{2})\.(\d{2})\.(\d{4})$/) + deadline = dmy ? `${dmy[3]}-${dmy[2]}-${dmy[1]}` : deadlineStr } // Remove the deadline portion from rest rest = rest.substring(0, deadlineMatch.index).trim() diff --git a/.agents/skills/jobbank-search/cli/tests/rss-parsing.test.ts b/.agents/skills/jobbank-search/cli/tests/rss-parsing.test.ts index 672019f..dc70a8e 100644 --- a/.agents/skills/jobbank-search/cli/tests/rss-parsing.test.ts +++ b/.agents/skills/jobbank-search/cli/tests/rss-parsing.test.ts @@ -56,10 +56,17 @@ describe("parseRssDescription", () => { jobType: "Fuldtidsjob, Graduate/trainee", company: "Acme A/S", location: "København", - deadline: "31.07.2026", + deadline: "2026-07-31", }); }); + test("passes an unrecognized deadline shape through for downstream defensive parsing", () => { + const parsed = parseRssDescription( + "Fuldtidsjob hos Acme A/S, Odense (Ansøgningsfrist: snarest muligt)", + ); + expect(parsed.deadline).toBe("snarest muligt"); + }); + test("normalizes a rolling deadline to null", () => { expect( parseRssDescription("Deltidsjob hos Example ApS, Aarhus (Ansøgningsfrist: løbende)"), diff --git a/.agents/skills/jobbank-search/cli/tests/search-normalization.test.ts b/.agents/skills/jobbank-search/cli/tests/search-normalization.test.ts index 494fb82..d41f42c 100644 --- a/.agents/skills/jobbank-search/cli/tests/search-normalization.test.ts +++ b/.agents/skills/jobbank-search/cli/tests/search-normalization.test.ts @@ -33,6 +33,6 @@ describe("Jobbank search normalization", () => { expect(result.company).toBe("Acme A/S"); expect(result.location).toBe("København"); expect(result.url).toBe("https://jobbank.dk/job/12345/acme/data-scientist"); - expect(result.deadline).toBe("31.07.2026"); + expect(result.deadline).toBe("2026-07-31"); }); }); \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index ffd16c4..803f30b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,15 @@ per-file diff commands. ### Changed +- **BREAKING (jobbank forks): `jobbank-search` search output emits `deadline` as + `YYYY-MM-DD`** - the feed's `DD.MM.YYYY` parenthetical was passed through raw, + contradicting the `/scrape` contract, the other portals, and the same CLI's own + `detail` command (which already emits ISO for the same job). `01.09.2026` is also + ambiguous to a date parser (1 Sep vs 9 Jan). The known shape is now converted; + "løbende" still maps to `null`, and an unrecognized shape passes through for `/rank`'s + defensive handling. Anything parsing the old `DD.MM.YYYY` output must update - though + the README's own search example already showed the ISO form. Pinned in + `tests/rss-parsing.test.ts` and `tests/search-normalization.test.ts`. - **Job matching reframed around function, not title** (`framework_version` 1.2.2 -> 1.2.3 in `04-job-evaluation.md`) - title-lookalike matching throws away career capital that doesn't fit one job-title box (e.g. a background spanning research leadership, platform ownership,