F15 - dates and metadata kept their meaning
- The Taleo parser stored an application DEADLINE in `posted`, so a role closing
on 30 September looked as though it had been published then - backwards for a
freshness signal. It now populates `deadline`, and `posted` stays empty
because that board genuinely publishes none.
- The Prospective adapter read unit, Lohnklasse and a named contact, folded them
into `description` for scoring, and `_process_company` then discarded
`description` - losing exactly the fields that decide level, pay and whether a
cold submit is necessary. They are now carried as fields through to the report
and the JSON dump, alongside `date_provenance`.
- Named contacts now appear in report rows. Channel is the rationed variable
since 2026-09-05, so a published, reachable name is the difference between a
cold submit being a choice and being the only option.
F16 - writes stopped destroying delivered work
- Every run of a day wrote `<date>.md`/`.json`, so a restricted run replaced the
full daily report. This is not hypothetical: it happened twice in this session
and both times the 37-company run had to be repeated by hand. Restricted runs
now write `<date>.only-kdocy.md` and say so.
- `save_seen()` ran in a `finally:` BEFORE the report was written. A failed
report write therefore left roles marked seen, so a `--new-only` retry would
hide precisely the hits that were never delivered. Seen-state is now committed
only after report and dump are on disk - and never by a restricted run, which
did not look at the whole board.
- Atomic writes used a fixed `.tmp` name; two writers could share it and
os.replace the wrong content into place. Unique temp names now.
34/34 tests pass; validated on a live 37-company run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qej5SBvhcbGXHwLqNWiskM