04 / Public dataMunicipal accountability reviewLiveReproducible

London Municipal Audit

An independent review of City of London procurement disclosure, built from the City's own published Contract Awards report.

Every published procurement figure regenerates from the source scrape with one command: raw portal HTML → parser → a 1,978-row ledger → the findings, in about four seconds. An independent review, not an official audit — but one where the numbers survive inspection.

The clearest finding.

1,978award records scraped and catalogued
1,394with no disclosed award value
70.5%of records carry no published value

On more than two-thirds of catalogued awards, the City discloses that a contract exists but not what it is worth. Across the 584 records that do carry a value, disclosed awards total $1,022,279,436.11.

From source to finding.

Contract Awards portal
Scraper & parser
1,978-row ledger
Analysis
Published figures

The scrape is committed and SHA-256 pinned. One command regenerates the ledger from it — byte-identical to the committed copy — then recomputes every published figure and fails loudly on any mismatch.

Every figure recomputed from clean_award_records.csv, itself regenerated this run from the checksummed scrape. Nothing is hand-entered.
Published figureRecomputeResultStatus
No-value disclosure ratecount without a dollar value ÷ 1,9781,394 → 70.5%Reproduced exactly
Known-value award totalΣ amount over the 584 disclosed$1,022,279,436.11Reproduced to the cent
Top-10 vendor sharegroup by vendor · top 10 ÷ total71.6%Reproduced
Construction sharecategory filter ÷ total94.3%Reproduced
HHI, all known-value awardsΣ(vendor share %)²949.4Reproduced
HHI, construction onlyΣ(share %)² within category1,065.4Reproduced
Distinct known-value vendorsunique vendor count267Reproduced exactly
Corporate-family grouping moves concentrationregroup by parent, recomputeno changeReproduced — 949.4 → 949.4

Corporate-family normalization groups only the 14 of 267 vendors whose own legal name discloses a parent ("a division of X", numbered-company DBAs); two near-duplicate name pairs are flagged and deliberately left unmerged. It doesn't move the concentration finding — so the "unconcentrated overall" reading isn't an artefact of vendor-name fragmentation.

One record, end to end.

RFT-21-97 — 2021/2022 Road Improvements Program: Adelaide Street N at CPR Underpass. The single largest known-value award in the dataset.

Source text“Bidders: McLean Taylor Construction Limited $60,191,223.44 · Dufferin Construction $91,564,000.00 · Bot Engineering $68,495,000.00 · Award is to McLean Taylor Construction Limited with a contract value of $60,191,223.44”
Parsedvendor McLean Taylor Construction Limited · amount 60191223.44 · status known_dollar_value · category Infrastructure/Construction · confidence high
Aggregationone of the 584 has_known_dollar_value rows — contributes $60.19M, 5.9% of the entire known-value total on its own.
Published inthe $1,022,279,436.11 total and the 71.6% top-10 vendor concentration figure.
Still not publicwhether $60.19M was the final cost (change orders, acceptance), and why the two losing bids came in $8–31M higher.

What still depends on manual work.

The procurement analysis reproduces from source. The honest boundary is elsewhere:

What the one-command pipeline does not regenerate, and why.
ItemWhy it isn't a script
Capital-project case filesNamed projects joined to Council staff reports by hand. The bid → vendor → amount joins are real and checkable; the document search is a person.
Bidder ↔ losing-price pairingThe portal interleaves competing names and amounts; only the winning award line pairs them cleanly. Bid values are recovered for 49% of records (97% of >$1M awards); identities aren't.
3 of 5 procurement-policy amendmentsBylaw number and date retrieved; the full amending-bylaw text was not.
Report parts beyond procurementCapital plan, workforce, housing, grants, internal-audit crosswalk — all sourced to named documents, none wired to a reproduce script.

Named projects, joined to their tender.

Capital projects joined by hand to their actual tender award inside the 1,978-record dataset — real bid number, vendor, and amount for each. The manual join is the part that isn't yet automated.
ProjectTenderAwarded toAward value
Mud Creek East Branch Phase 2B · stormwaterRFT-2024-060Van Bree Infrastructure$11,864,196
Springbank Dam decommissioningRFT-2024-070Bronte Construction (2220742 Ontario Ltd)$4,350,862
Greenway Flood Protection · wastewaterRFT-2024-084Stone Town Construction Limited$24,477,992
Highbury Avenue reconstruction · roadRFT-2025-270J-AAR Civil Infrastructures Limited$27,426,933

Full case-file dossiers — including which budget-to-award gaps stay open and the records requests drafted to close them — are on the published microsite.

Method.

  1. 01 · Scrape

    Drive the City's Contract Awards portal (no API) and save the rendered report unmodified. Checksum it.

  2. 02 · Parse

    Split the report into bid sections, extract vendor / amount / method, classify each record by a fixed keyword cascade, score parser confidence, and route unstructurable rows to a rejects file with a reason.

  3. 03 · Regenerate

    Rebuild the 1,978-row ledger from the checksummed scrape and re-run every published figure. The pipeline exits non-zero on any mismatch; a fresh scrape produces a new dated population, not a silent pass.

  4. 04 · Publish

    Report what the record supports; for what it doesn't, state the specific unresolved test.