The JSON-LD branch of detail emitted jobPosting.description verbatim, so
`detail --format plain` printed
`description: <p>Vi søger en udvikler til R&D.</p><ul><li>Python & Go</li>...`
while the rendered-HTML branch of the same command printed one clean
line per paragraph and bullet. Two description shapes from one command
depending on which page layout it hit, and the markup landed in
/scrape's stored snippet and /rank's agent context as-is. The portal
contract (/add-portal Step 4) asks for readable text: entities decoded,
tags stripped, paragraph breaks preserved.
Render the HTML through node-html-parser's structuredText - one line per
block element, entities decoded, tags gone - which is the shape the
fallback already produces. A plain-text description is unchanged, an
absent one stays "".
The JSON-LD test that pinned the raw <p>...</p> now expects the text,
plus two new cases; the HTML case fails on master.
Jobbank and Jobdanmark each had only one narrow test, leaving required-argument errors, RSS normalization, JSON-LD variants, and malformed-page handling unprotected.
Add network-free fixture and subprocess tests for repeated RSS filters, description and ID parsing, stderr JSON errors, Bunli numeric validation, JSON-LD objects and arrays, optional fields, not-found pages, and parse failures.
The suites now cover eight Jobbank cases and six Jobdanmark cases without making live portal requests.