
A job application assistant for the German market. You upload your CV, search Bundesagentur
für Arbeit and Arbeitnow or paste a posting URL, and it drafts a tailored cover letter plus
CV tailoring suggestions — then tracks what you sent where.
The point is that it refuses to make things up. The match score is computed in code, not by a
model, so it can be explained and tested. Every draft has to clear a deterministic lint —
every number has to trace back to your own CV, every company or product name to the evidence
gathered from it — and then an independent judge model from a different family scores it on
grounding, specificity, voice, relevance and language. A lint failure is final; the judge
never gets to overrule it. If two revisions can't fix a draft, you get "this didn't pass, and
here's why" instead of a confident bad letter. Nothing is ever submitted on your behalf.
Built with LangGraph (a state machine for generation, a ReAct agent for the chat panel),
FastAPI, Next.js and Postgres with row-level security, reaching GPT-5.4 and Claude Haiku 4.5
through one OpenRouter key. It runs locally: clone, make setup, make dev.
Two findings worth mentioning. Thirteen individually correct code reviews still let fabricated
job postings ship as real search results — two sensible defaults composed badly, and only a
whole-branch review caught it. And the chat checkpointer's tables turned out to be readable
by anyone holding the public browser key, which is fixed and documented rather than buried.
Known gaps: English only, no held-out evaluation yet, retrieval scaffolded but unused. All in
the README, along with what comes next.