Four hundred requirements. Two weeks.

Every one of them is the same question — have we built this before? — and the answer is spread across four systems and six colleagues' memories. The industry allows up to 180 hours for the reply; that is their figure, not ours.

Assess a requirement

24 of 24 assessed · ~55 s each · 23 of them refused a price

Every answer is assembled out of rows we made.

Nothing here holds the answer on its own. A requirement reaches a loop, the loop reaches two tools, and the tools reach five tables in one database — ours, filled by reading the customer's own files. The only thing it opens of Vantis's own is the requirement it was asked about. How those tables were filled is the rest of this page.

The questionA loop decidesA tool fetchesRows we made answer
  1. The question

    • A requirement

      one line of a spec

      Its text is the only thing about your bid that leaves this page.

    • vst_alm

      one read, for the question

      The one system of record a request opens, and never for any part of the answer.

  2. A loop decides

    • the loop

      gpt-5-mini · 12 turns at most

      Searches, prices, writes the dossier — then finds every quote in the file so the line numbers are real.

    • the work list

      24 requirements, in turn

      A whole bid, one requirement at a time and never in parallel. The list is recomputed from what is already filed.

    • the summariser

      no tools, one call

      A second and much smaller agent. It reads only the assessments already filed, and counts before it asks.

  3. A tool fetches

    • search_documents

      6 passages, no cutoff

      Hybrid search over the customer's own prose and code. It hands back the best passages even when they are poor.

    • find_comparable_work

      the median of past jobs

      Median rather than mean, and it refuses below three past jobs. On the K2 bid it refused 23 times out of 24.

  4. Rows we made answer

    • document_chunks

      2,827 passages

      The prose and the code, cut at their own seams and stored so they can be found by meaning.

    • extracted_facts

      1,318 facts

      Facts that were wearing a sentence. Each carries the sentence it was read from.

    • derived_effort

      220 past jobs

      One row per closure report, and the table a price is actually queried from.

    • effort_split_lines

      695 lines

      Hours by discipline. A price is a mix, and the mix is what a rate card is applied to.

    • rate_card_lines

      168 rates

      Approved rates by year and region. Hours become euros through these and nothing else.

    • the answer key

      vst_crm · vst_plm · vst_pmo

      What our reading is marked against. One command opens them, and it is the one that grades us.

  5. Every fact in an answer comes out of one database of ours, built by reading the customer's files. Of Vantis's own four systems a request opens exactly one, exactly once, for the text of the requirement — and never for any part of the answer.

Four answers, two weeks, one bid.

The commercial team needs the same four things every time. Each one is a reachability question over a graph nobody can see all of.

  1. 1

    Which of this do we already ship?

    Reuse. Cheap, fast, and the answer somebody will argue with.

  2. 2

    Which do we ship after a change?

    A delta — and how big, in engineering hours.

  3. 3

    Which does not exist yet?

    New development, and the risk that comes with it.

  4. 4

    What does all of that cost?

    A range, from what changes like it actually took.

What they gave us, and what we made of it.

A customer hands over a directory, not a schema. Open anything on the top row to read the actual files; open anything on the bottom row to see the table they became and a real value in every column.

before

Eight kinds of file

1,069 files · 1,943 KB

counted by pnpm steering:corpus-web

Everything Vantis handed over, sorted by what kind of thing it is. Four of the eight have been read so far; the other four are the next two stages of the work.

after

Six tables in vst_derived

19,141 rows

counted by pnpm steering:estate

vst is the prefix on every Vantis database — vst_crm, vst_plm, vst_alm and vst_pmo are theirs. kb is short for knowledge base. So this is the Vantis knowledge base: the one database in the estate that was written rather than handed over, and the only one the product is allowed to read.

738 of the 1,069 files — the requirements, the source repositories, the releases and the ticket export — have produced no rows at all. Those are the four dashed tiles above, and they are the next two stages of the work rather than an omission.

From 1,069 files to rows we can stand behind.

The documents are what the customer has. Rows are what a question can be answered from. Everything between the two is this, and it is deliberately three separate jobs, in an order that lets each one check the next.

counted by pnpm steering:derived-reconcile · pnpm steering:corpus-check

What the files do to make that hard.

All of it is planted, and all of it is the kind of thing a real export does. A parser that tidied any of it away would report a cleaner run and a worse answer.

  • Three quarters were never exported

    2020-Q4, 2021-Q2 and 2026-Q1. Work happened; no file was ever produced.

    Asserted as gaps, not filled in. A parser that assumed continuous coverage would undercount and report a clean run.

  • Twelve people are spelled two ways

    P. Strand in one export, Strand, Petra in the next.

    Both spellings survive the parse. Deciding they are one person is a judgement somebody should be able to see and disagree with.

  • A rate card does not say which year it is for

    Seven rows of discipline and rate. The year and the region are in a # comment above the header, and in the filename.

    Both sources are read and required to agree. Reading only the CSV body gives 168 numbers that cannot be told apart, and prices eight years of work off one card.

  • 742 lines were never signed off

    An empty approval column, which means nobody signed — not that somebody refused.

    Stored as unknown. 0 are stored as rejected, because 0 were rejected.

  • Thirty lines sit on closed charge codes

    253.7 hours, journalled late, flagged the way finance flags them — in a comment.

    Kept, flagged and set aside. Dropping them loses real hours; counting them silently double-books.

  • The safety level is stated in three places that disagree

    The safety assessment says ASIL B in prose, damping.h says B in a comment, and cfg/build.json compiles at D.

    Not yet read — this one is prose, so it belongs to the stage that is not built. MISRA deviation D-07 is the only place in 1,069 files that explains why.

And what no amount of reading will produce.

These are findings, not delays. Each one is the kind of thing a customer would otherwise discover in front of their own management, and naming it in week one is most of what this part of the work is for.

293,019 h

of 461,722 booked

belong to work no document names. 220 of 640 efforts have a closure report, so two thirds of the cost history cannot be classified from the files alone. This is the customer’s actual position, not a parser limitation.

0 of 293

quoted lines

can be traced to the requirement they priced — not in the documents and not in the databases. “What did we last charge for a requirement like this one?” has no answer in this estate. It is missing, not lost in extraction.

1 of 1,069

files

names a part number. The hardware estate is simply not in the documents we were given, so no amount of parsing produces it. That needs a part-master export, not a better pipeline.

And the answer key we mark ourselves against.

This is not what the product reads. These four are what a bid answer eventually has to arrive in — requirements in one tool, hardware in another, customers in a third, and what past changes cost in a fourth, with nothing joining them — filled in by hand from the same documents. Holding the right answer is what lets us score our own reading instead of admiring it. Open one to see the shape the reading is aiming at.

4databases37tables13,712rows

counted 2026-09-13 by pnpm steering:estate

They stand for the customer's systems of record — read, never written, and no query joins one to the next. They were generated alongside the documents rather than derived from them, which is why they cannot also be the product's source: one command, derived:grade, opens them and nothing else does. No real customer has this, so any check that needs it is a check that cannot ship — which is why the four that come first are the ones needing no answer key at all.

It answers one question now.

This engagement is six days old. What exists is 1,069 of the customer's documents and four databases holding the answer somebody read out of them — thirty years of programmes, requirements, architecture and what past changes actually cost.

Those four were generated alongside the files, from the same constants, in the same run — so they are a key to mark against, not an output. Until this week nothing had ever read one of those documents and written a row.

Now the reading is done and the first answer stands on it. vst_derived holds 19,141 rows — parsed out of the spreadsheets, cut out of the prose, and read out of the closure reports by a model that had to quote the sentence it read each fact from. Every row carries its file and its line.

On top of that there is a desk that assesses one customer requirement — what we already have, what has to change, what does not exist, and what past jobs of the same kind cost. It is allowed to refuse, and below three comparable jobs it does.

What is still missing: it assesses one requirement at a time and a bid is twenty-four, the search does not yet confine itself to the programme being asked about, and the eval suite has cases but no baseline on disk. Saying all of this here is cheaper than being caught.

What is built
  • Four databases, seeded and checked — the answer key
  • 1,069 documents, with their contradictions planted on purpose
  • The trace graph — requirement to element to part
  • vst_derived — ours, 12,978 rows parsed out of the files
  • A parser that reads a document and writes a row
  • Reconciliation against the answer key, to the expected delta
  • Chunking and embedding the prose and the code
  • Facts extracted from sentences, each quoting its own evidence
  • Two tools the model can call
  • An answer contract, and the rules that keep it
  • A desk that assesses a requirement and shows its working
  • Eval cases, anchored to the planted traps
  • A baseline on disk to compare a change against
  • The search confined to the programme being asked about
  • All twenty-four requirements of a bid, not one