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,