A job-search tool built for one person's search. Seven boards feed one local database; deterministic rules hide what could never be taken and say which rule did it; the model scores what survives on two axes and re-reads the top slice; a fixed bar makes the shortlist. Then the line that does not move: the tool never applies. It saves, dismisses, reorders a résumé from one source of truth, and records what was sent. These four diagrams trace where each of those lines falls.
The pipeline, top to bottom, with the live counts setting the width of each band — so the figure is the data, not a picture of it. Code takes 35,422 to 8,689 for free, and every posting it hides records which rule hid it. The model takes 8,689 to 115, in two reads. Then the only band that is filled solid: you, one posting at a time.
Widths are indicative, not to scale — 115 of 35,422 would be a hairline. The point of the shape is the three different kinds of narrowing: the top one is refusal (a rule, free, reversible without a rescore), the middle is judgement (two axes, re-read at the top, a fixed bar), and the bottom is a person. The counts come straight out of the database on the date above.
The model reads each surviving posting once and returns two numbers with a one-line reason and a one-line doubt. Code does the rest: the mean is the number the list is sorted by, the shortlist is everything at or above 0.70, and the top slice by fit is sent back for two more reads with the median kept. The calibration was itself checked on a sample that could disagree.
Sorting by fit alone ranks by how closely the résumé matches the posting's requirements — and therefore buries the jobs the candidate would be best at. Sorting by the mean of fit and thrive surfaces them, and showing the two numbers apart keeps the gap visible: when thrive is far above fit, the résumé is the only thing in the way. That gap is signal. It is never actioned with a cover letter.
Model calls cost quota, so the obvious economy is a cheap Python pre-ranker — score by title match, keywords, size, employment type — and only send the top slice to the model. It was built, then measured against 8,353 postings the model had already read. The measurement decided.
The refit is the instructive part: fitting the weights to the measured lift made recall worse at small cutoffs than the hand-picked ones, which means the hand-picked weights had been accidentally compensating for something the fitted ones did not. The conclusion is that scoring cannot be cheaply pre-filtered without silently losing the best jobs — so the cost is paid, and managed instead: paced chunks, a gap between them, and a stop when a chunk mostly fails.
A rule that lives only in a prompt is a request. These three live in code and tests: there is no route that submits an application, only one that opens the posting; the cover-letter path was removed and a test reads the source to keep it gone; and the résumé generator is fenced to one profile file it may reorder but never extend. What comes out the far end is a record the state accepts as a work-search log.
Every test here was mutation-verified: revert the fix, watch the test go red, put the fix back. A test that passes when you revert the fix protects nothing. The cover-letter rule leaked four times before it was tested this way — in the apply script, the scoring prompt, the endpoint default, and the export — which is why it is now enforced by reading the source rather than by remembering.