RFP Evaluation Checklist

Turn any public-sector RFP into a checklist of how you'll be scored and what gets you thrown out, with every line linked to its source.

Open source, MIT license. Tested on RFPs from multiple cities across the U.S.

The checklist built from City of Tucker RFP 2026-008: issuer, project, RFP number and due date, each with an orange page-and-line chip; the stated total of 100 points matched against the items' sum; and 12 rules that can throw a proposal out.

The afternoon an RFP drops

Someone on the proposal team opens a long PDF and starts a spreadsheet by hand: every item the agency will score, its points, what it asks for, what the scorer will look for.

Then they hunt through the fine print for the rules that throw a proposal out before anyone scores it. Turned in late. A required form missing. One page over the limit.

Two small slips cost the most. A criterion paraphrased in the spreadsheet stops matching the words the scorer is holding. A disqualifier nobody copied over sinks the bid, no matter how good the rest of it is.

What you get back

One page per RFP, in the RFP's own words. The headings and labels are ours; every quote is theirs.

How you'll be scored

Every item the RFP scores, its points, what it asks you to provide, and what the scorer looks for, grouped under the RFP's own headings. The points are added up and checked against the total the RFP states.

What gets you thrown out

Every sentence that rejects or disqualifies a proposal, sorted by kind: late, missing something required, broke a page limit. This is the part that fails silently when it's built by hand, because nobody notices a line that isn't there.

Every line links to its source

Click a chip like Page 14, line 15 to open that RFP page with the words highlighted. Where the RFP says nothing, the cell reads not in source instead of a guess.

The What gets you thrown out tab, with Turned in late expanded. Clicking the chip Page 3, lines 23–24 has opened the RFP's page 3 in a sidebar, with those two lines highlighted in yellow.
Clicking Page 3, lines 23–24 opens page 3 of the RFP with those lines highlighted.

How it's kept honest

A checker re-reads every quote against the RFP and refuses the output if one word isn't at its citation, or if any scoring or disqualifying line was left out. The page is only built from a checklist the checker passed.

The RFP, page 3, as the checker reads it
Checklist line: Late bids will not be considered. Page 3, lines 23–24

The shipped checklist passes:

$ python3 tools/check_matrix.py outputs/tucker-ga-rfp-2026-008-row-maintenance.matrix.json
PASS 3 rows, every cited claim found in the source; points 100 vs stated 100 (reconciles); coverage 30 trigger line(s) accounted for

Change one word, considered to reviewed, and it refuses:

FAIL 1 problem(s)
  - disqualifiers 1: text is not verbatim (whole words) at p3:23-p3:24: 'Late bids will not be reviewed.'

Real output from the repo's checker, trimmed to fit. The tests prove it also refuses a respelled word, a figure borrowed from the next line, a wrong page, and a disqualifier nobody accounted for.

How to use it

In Claude Code

Open the folder, put the RFP PDF in it, and say:

Translate rfp.pdf.

Claude extracts the text, writes the checklist, runs the checker, and renders it. The rules it follows are in identity.md and rules.md.

From the command line

Python 3.9+ and poppler for PDFs. Full steps are in the README.

  1. Turn the PDF into numbered source text.

    python3 tools/extract.py fixtures/your-rfp.pdf
  2. Ask Claude to translate the source text into a checklist.

  3. Check it against the RFP.

    python3 tools/check_matrix.py outputs/your-rfp.matrix.json
  4. Render it as Markdown, CSV, Excel and HTML.

    python3 tools/write_matrix.py outputs/your-rfp.matrix.json