← back to the ShortList brief
ShortList · System diagrams

Code removes the impossible.
The model judges. A person decides.

● PRIVATE · IN DAILY USE · COUNTS FROM THE DATABASE, 19 SEPT 2026

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.

Grey — inputs
Blue — deterministic, computed in code
Amber — the model · the judgment
Coral — removed, with the rule that did it
White — a person · the last word
01 / 04 — THE FUNNEL

Every band is as wide as the number of postings still in it.

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.

Inputs Code Model You 35,422 postings pulledGreenhouse · Ashby · Remotive · RemoteOK · Himalayas · Jobicy · Arbeitnow · pasted 8,689 survive the hard rulesfloor · remote · travel · title rules with overrides — not endorsed, only not disqualified 24,135 hidden, each by a named rule fit · thrive each of the 8,689, scored on two axes FIT — DO THE SKILLS MATCH? · THRIVE — WOULD THE WORK SUCCEED? full range on both · paced through one subscription · sonnet 400 confirmed · top 8%re-read twice, keep the median 115 THE SHORTLIST≥ 0.70 combined · fixed bar fit and thrive shown apart Ask ShortList · chatbot TALKS TO THE LLM ABOUT THIS POSTING grounded in the DB · says "don't know" APPROVE GATE — ONE AT A TIME save · dismiss · apply Résumé · re-ordered, never added toone source of truth · a fact not in it is left out Work-search recordlink · title · date · résumé sent no code path submits an application the browser opens the posting; a person sends

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.

02 / 04 — TWO AXES, ONE BAR

Fit alone buried the best jobs, and a percentile cut called 1,998 of them strong. So: two axes, and a bar that means something on its own.

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.

One read · the model Deterministic — computed in code FitDO THE SKILLS MATCH?0 – 1 · anchored at the top ThriveWOULD THE WORK SUCCEED?0 – 1 · full range Reason · doubtone line each, shown on the row Combinedmean of the two Bar · ≥ 0.70absolute, not a percentile THE SHORTLIST 115 of 8,689 scored Top 8% by fitties kept · measured 11% Two more readsKEEP THE MEDIAN Calibration · checked, not assumed The fit rubric had only subtractive clauses: nothing could score above 0.75. Fix: a top-of-scale anchor. Checked on 60 postings the model had already read. 19 of 60 went DOWN — not inflation. A percentile shortlist once returned 1,998 "strong" — the bar is absolute now. Median, not mean, on the re-reads: one wild reading should not be able to drag a good posting down, and averaging lets it.

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.

03 / 04 — A NEGATIVE RESULT, KEPT

A cheap ranker would have found four of every ten good jobs. It was measured, rejected, and kept in the repo.

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.

Recall of the 238 genuinely strong matches (fit ≥ 0.60) among 8,353 scored postings Cheap ranker · top 80010% of the corpus · title · keywords · size · type 39% Cheap ranker · top 2,000a quarter of the corpus, still four in ten missed 58% The model reads every survivorwhat ships · paced, not pre-filtered 100% Why it fails — the useful part The model is not counting keywords. It reads "Internal Applications Engineer" and knows that is where an analyst who builds would thrive. No phrase list does. The strongest cheap signal is a title the candidate has actually held — real, and nowhere near enough to filter on. Kept as prerank.py with a --measure flag; this table is its output on 20 Sept 2026. A negative result that is deleted gets rediscovered.

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.

04 / 04 — THREE RULES WITH TEETH

It never applies, it never writes a cover letter, and it never adds a fact. Each rule is enforced somewhere other than a prompt.

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.

The rule Where it is enforced Never applies save · dismiss · apply — a person clicks No submit route exists the batch drafts and stages; it does not send the browser opens the posting; a person pastes No cover letters résumé only, by rule 400 on the endpoint · AST scan omitting the kind means résumé, not the old default no kind may default to "cover" anywhere, by syntax tree Never adds a fact reorder · re-emphasise · re-word · never extend One profile file is the only source asks for what isn't there? the line is left out documents stored per posting, append-only What leaves the far end: a work-search record — link · title · date · the exact résumé sent — which is also what the state asks for. The tool ranks and drafts; the person decides and submits.

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.