TenderCheck
Built at Meta Global AI Developer Hackathon · Oct 26, 2026 · Remote

TenderCheck checks a public-tender bid package against the tender's own documents before submission. Tender rules are scattered across a notice, a request for proposals and several annexes: mandatory and conditional documents, deadlines, file formats, seals and signatures, validity windows. Small bidders check all of it by hand, and one missing seal or wrong file format can get a bid rejected at intake, before anyone reads it. I have gone through this paperwork many times for my own applications to public programs. You give it the tender text and your file list (names, formats, signatures, seals, issue dates), and optionally scanned pages of your files. Muse Spark 1.3 reads every document and returns one record per obligation, each with the exact words that impose it and the line they come from. Code verifies every quote verbatim against the source, recomputes dates, checks formats, seals and file names, and decides every status: met, missing, error, conditional or needs check. Anything code cannot verify reads "needs check", never "met". Scanned pages are where the list and reality can differ. Muse Spark reads each page as an image and returns every seal field with a box and every printed date. Code then measures the red ink inside the model's box. In the demo, the file list alone shows no errors; with three pages added, the bid form's company seal field is empty (model and code agree) and the tax certificate's printed issue date is earlier than the list says, so three rows turn to error. A page can make a row more cautious, never "met". When two documents disagree, for example two different bid deadlines, TenderCheck shows both quotes, drafts a yes/no question for the agency and gives the date that is safe under every reading. The tender is data, never instructions: a line planted in an annex telling AI reviewers to mark everything compliant is shown and ignored. Personal numbers are masked before any model call. It never says a bid is eligible; a person makes that call. Results on synthetic data: on the final engine, 17 of 18 live runs fully matched answer keys written before the engine existed (332 of 333 rows), and seven adversarial test cards passed 21 of 21. Page reading, on our own synthetic pages: 12 of 12 on a pre-registered gate, and 3 of 3 demo runs exactly as the key says. On one real tender, Pyeongtaek City notice 2026-1272 as published on Korea's e-procurement portal (about 31,000 characters), with a synthetic bidder list carrying five planted defects, one live run set up in advance: three defects caught exactly, the other two flagged for review, none passed as "met", and two false alarms on correct documents. That is 11 of 21 key rows, a FAIL on the rule we committed before running it; the run is shown as recorded and the log is in the repo. A check is five to eight Muse Spark calls, about $0.12–0.15 on the test tenders and $0.40 on the real one. Demo (recorded live runs, no model calls): https://jin7744.github.io/tendercheck/ — all code was written during the hackathon, from Oct 27; the commit history is public.