Clearline · Live product · Procurement
Kill the quote
spreadsheet.
Every procurement team on earth retypes vendor quotes into a comparison sheet, and everyone has quietly accepted it as the cost of doing business. Clearline is the system that drafts an RFx, reads whatever vendors send back, and lets a buyer interrogate the result in plain language — built, deployed and running.
Role
Product and build · end to end
Stack
LLM extraction, agentic analysis, libSQL, deployed web app
State
Live, with an eval harness
01
Day 1
The RFx is written by hand
A category buyer needs thirty line items of corrugated packaging quoted. Scope, line items, quality questionnaire and terms all get typed from scratch, every cycle.
02
Day 2–9
Vendors reply however they like
A spreadsheet that ignores the template. A PDF on letterhead with the discount buried in a footnote. A Word doc with commercials in a paragraph. A phone photo of a printed rate card, taken at an angle. And one email that just says “₹42/kg for the 5-ply, ₹38 for the 3-ply, rest same as last year, freight extra.”
03
Day 10–12
The buyer retypes all of it
Three days of copy-paste into a comparison sheet, converting units and currencies by hand — the exact work where an awarding error costs real money.
04
Day 13
One question resets the sheet
“What if we split it, cheapest per line, but only among vendors who cleared the quality questionnaire?” There goes the fourth day.
| Vendor | Format | What makes it hard | Read |
|---|---|---|---|
| PackRite Industries | xlsx | Own codes, own column order, lines reordered | 30 / 30 |
| Global Corrugates FZE | USD pricing; 4% settlement discount in a footnote | 30 / 30 | |
| Shakti Packaging | docx | Commercials in prose; sheet pads priced per 100 | 27 / 30 |
| Metro Board & Pack | jpg | Angled phone photo of a printed rate card | 18 / 30 |
| Nova Pack | txt | Two-line email; “rest same as last year, freight extra” | 4 / 30 |
Nova Pack is the important one. Twenty-six lines are unknown, not zero. The system quotes four and refuses the rest, because “same as last year” is not a price and this system has no last year.
01
Drafting co-pilot
Plain-language brief → structured RFx. Strict tool schema; every dimension is canonicalised to millimetres at authoring time. The model must declare, in assumptions, anything it invented that the buyer never said.
02
Extraction
One document → one filled schema. Null when a value is absent, never a guess. Every field carries a mandatory verbatim source reference. Off-schema output is rejected, not repaired. There is no field for a rank, score or recommendation.
03
Analyst Q&A
Question → query → answer. The model picks one of nine queries. The application computes every number. The model narrates. It does no arithmetic.
Both providers sit behind one module, and the loops never learn which vendor answered. The PRD claimed swapping models would touch one file; porting from Claude to Gemini mid-build was the test, and it held. The figures below were produced on gemini-3.6-flash, which reads the letterhead PDF and the angled photograph as bytes rather than as pre-converted text.
01
Draft the RFx by talking
A buyer builds the request with an AI co-pilot — scope, line items, quality questionnaire, commercial terms — instead of starting from a blank template.
02
Send it out, no format rules
The RFx goes to vendors over a chosen channel. Nobody is forced into a template, because in practice that rule is what vendors ignore.
03
Read whatever comes back
Spreadsheets, letterhead PDFs, Word docs, photographed rate cards and freeform email are all extracted into structured line items, units and currencies.
04
One normalised comparison
Same lines, same units, same currency, side by side — with questionnaire answers and attached documents sitting next to the numbers, not in a separate folder.
05
Interrogate it in plain language
The buyer stops clicking and starts asking. Answers come back as text, tables and charts over the extracted data, exportable, all the way to a defensible award.
Currency
An explicit FX table with rate, source and as-of date. A converted value always displays next to its original: ₹24.30 (from USD 0.291 @ 83.5). A quote with no stated currency is never assumed to be rupees.
Unit of measure
A declared factor table. per 100 pieces → per piece converts and shows the arithmetic. per box, where the box size is never stated, does not convert — it goes to the review queue.
Line matching
Three tiers, visually distinguished: exact when the vendor cited our line code; fuzzy via deterministic attribute scoring with no model involved; and semantic as a model proposal, never counted until a human confirms it.
Why it exists
The assignment came with no sample data, so I authored a synthetic set: a 30-line RFQ and five vendor replies, each awkward in a different way, plus a sixth carrying a prompt-injection payload. The expected answers were written out separately — from the documents, not from the running system — and npm run eval scores a real extraction against them.
| Graded check | Expected | Produced |
|---|---|---|
| Split award — cheapest per line, qualified vendors only | ₹4,47,16,859 | exact |
| Per-line winner and price, every line | 30 / 30 | 30 / 30 |
| Single-vendor total — PackRite | ₹4,63,47,510 | exact |
| Single-vendor total — Global Corrugates | ₹4,56,06,857 | exact |
| Coverage — PackRite / Global / Shakti / MetroBoard / NovaPack | 30 · 30 · 27 · 18 · 4 | exact |
| Line 1 across all five vendors, incl. the FX-converted one | exact | exact |
| Sheet pads, per 100 pieces → per piece | 6.10 · 4.72 | exact |
| Apex injection document appears in the ranking | never | never |
34 of 34 checks pass, alongside 28/28 pipeline integration tests and deterministic line matching at 97.1% coverage with 100% precision.
What this proves, and what it does not. I wrote both the test data and the answer key, so this is a regression harness rather than independent validation: it shows the pipeline does what I specified on the cases I chose, not that it generalises to real vendor documents. The substantive work was designing the cases. Each targets a specific way these systems fail quietly — silent FX assumptions, zero-filling unquoted lines, applying a footnote discount to unit rates, treating a missing questionnaire answer as a pass. Scoring a new document set is a single command, which is exactly what I would want next.
Prompt injection
The adversarial document is a permanent regression fixture, not a claim. The structural defence is that the extraction schema has no field for a ranking or a recommendation, so there is nothing for injected text to populate. Document content is delimited, and forged boundary markers are stripped.
Provenance
Every number in the comparison carries its document and the verbatim words it came from. Click any price to see them.
Exports
Every CSV routes through one sanitiser that neutralises formula injection. There is no code path that writes a CSV without it.
Files and access
Byte-level MIME sniffing rather than trusting the extension; short-TTL HMAC-signed document links; a password gate on every route; an append-only audit log.
One case where the rule worked against me
My answer key expected Metro Board to be excluded for on-time delivery of 89.5%. That figure appears nowhere in the rate-card photograph — the card states ISO 9001, the in-house lab, lead time, payment terms and MOQ, and no delivery percentage. The system therefore excludes them as unassessable on that question rather than as failing it. Same outcome, reached from the only evidence in the file. When my expected answer and the actual document disagreed, I corrected the answer key rather than teaching the system to invent the number.
Refusal over coverage
Where a value is ambiguous the line is held out of the comparison rather than shown as a number nobody has checked. The grid says when it is incomplete, and why.
The application computes; the model narrates
No total, ranking or award figure is ever produced by a language model. The model picks the query; the code runs the arithmetic.
Show provenance, not just answers
Every normalised number traces back to the vendor document it came from. A buyer with crores on the line acts on evidence, not on a confident sentence.
SQLite via libSQL
An identical code path on a laptop with zero provisioning and on a host with one environment variable. Postgres buys nothing at this scale and costs setup time.
The RFx is parsed from the buyer's own workbook
The dataset arrived after the system was built, and nothing about it is hardcoded. Seeding a new RFx is a single command.
- —Multi-round negotiation, counter-offers and re-bids.
- —Supplier onboarding, master data management and contract lifecycle.
- —ERP or P2P integration; real e-signature on the award.
- —Multi-tenant accounts and per-user roles — one shared password gates the demo.
- —Live FX rates. The table is explicit and dated, because a silently drifting rate is worse than a stale one you can see.
Free-tier hosting sleeps
After roughly 15 minutes idle, the first request takes up to a minute while the instance wakes.
Free-tier Gemini allows 20 requests per day, per model
Extracting all five documents costs five. The deploy ships a committed snapshot of a genuine extraction run so the comparison is populated on arrival; re-running live may hit the daily cap.
No persistent disk on the free plan
Work done through the hosted app is lost on the next cold start. Pointing LIBSQL_URL at a Turso database makes it durable with no code change.
Vision extraction is the weakest link
18 of 30 lines from the photograph. The remainder are reported as not-quoted rather than guessed.
Matching is tuned to this category
The attribute scorer understands ply, GSM and millimetre dimensions. A different category needs a different scorer.
01
Open the link and enter the password. The first load may take a minute while the instance wakes.
02
RFx & responses. The buyer's requirement, parsed from their own workbook, and the five vendor documents. Each shows how many of the 30 lines were read.
03
Comparison. Same lines, same units, same currency. The cheapest quote on each line is marked. Click any price for the source document and the exact words behind it. Toggle only vendors that cleared the questionnaire to see the gate applied.
04
Review queue. What the system refused to decide, and why. Resolving an item releases the lines held behind it.
05
Ask. Plain language — “cheapest split across qualified vendors”. The answer arrives with the query that produced it and the caveats attached.
06
Award & audit. Two defensible options, what each one excludes, and the record of the decision.