How to run it, and what every answer means.
Published in full. Written for the person who will use the software, not for the person who signs for it.
Version 0.2.0 · Revised 12 October 2026
01What this is
Two tools that read construction documents
The contract engine reads a subcontract you are already bound by. It compiles every clock, gate, threshold and forfeiture the contract imposes, then flags the clauses that will cost you money.
The tender intake reads a tender you have not bid yet. It pulls the dates, the requirements, the bill and the terms, and drafts a proposal with every gap marked.
Installed on your own machine, both run there entirely. Nothing is uploaded, nothing is sent anywhere, and neither tool needs a network connection once installed. The hosted console is the same software on a server in Riyadh: you sign in, the file goes to that server over an encrypted connection, and it is read there.
The engine refuses rather than guesses. When it cannot read a value, it says so and gives you the candidates. When a document is not signed, it will not give you a settled verdict. A tool that quietly picks the wrong number is worse than no tool at all.
02Installing it
Two steps, about five minutes
1. Install Node
Node version 18 or newer. Download it from nodejs.org, take the LTS option, accept every default. Check it worked by opening a terminal and typing:
node --version
Anything from v18 upward is fine.
2. Unzip the package
Put the folder wherever you keep working files. There is nothing to install and no
administrator rights are needed. The tool has no dependencies at all, so
there is no npm install step and nothing is fetched from the internet.
Optional, for PDF files
Reading PDFs needs Poppler, which provides pdftotext and
pdfinfo. Word, Excel, HTML and text files are read natively and need
nothing.
| Platform | Command |
|---|---|
| Windows | winget install oschwartz10612.Poppler |
| macOS | brew install poppler |
| Linux | sudo apt install poppler-utils |
03Starting it
Double click, and it opens
Double click Kontra+ in the folder. It checks that Node is present, finds a free port, starts the engine and opens the screen in your browser. The first time you run it, it also puts a Kontra+ shortcut on your desktop, so from then on it behaves like any other program.
Closing the black window stops it. Nothing keeps running in the background and nothing is installed.
The address bar takes a file, so a shortcut can point straight at a live job:
http://127.0.0.1:7801/contract?file=C:\path\to\contract.pdf. Repeat
&file= for the Appendix and each amendment.
Prove it works before you trust it with anything
Open a terminal in the folder and run these two commands.
npm test
npm run demo
npm test runs 527 checks: the contract engine and the tender intake against a
contract that ships with the software, the knowledge base against the clause records and the
statute library, and the register against published contracts the engine had never seen.
It should finish with all green. If it does not, stop and read
Troubleshooting rather than continuing.
npm run demo prints a full analysis of that same contract. It is a
deliberately one sided fit-out subcontract written for this purpose, with every party and
figure invented. Read the output once before you put a real contract through it, so you
know what a complete result looks like.
04Reading a contract
One command, one or more files
node src/cli.js "conditions.pdf" "appendix.docx"
The printed conditions and the Appendix are one contract, and the Appendix is where the money is. Reading only one of them produces a confident, incomplete answer, which is more dangerous than no answer. Include every amendment and every annex you were given.
To keep the result as data rather than text:
node src/cli.js "contract.pdf" --json --out profile.json
Accepted formats: .pdf, .docx, .xlsx,
.html, .txt, .eml.
05Reading the report
Six blocks, in the order they matter
Provenance
Whether this is the signed contract. NOT_EXECUTED means blanks or
signature lines remain, which is normal for a contract under review. The plan still
compiles, but no clause verdict is presented as settled.
Document type
Whether it reads as a contract at all, with a confidence percentage. Below about 50 per cent, treat everything after it as unreliable.
Commercial terms
Retention, advance, performance security, mark up, caps and periods, each with a confidence marker.
| Marker | Meaning | What to do |
|---|---|---|
HIGH | Read cleanly from the Appendix | Use it |
COLLIDED | Two figures printed on top of each other by the conversion | Both candidates are given. Confirm against the signed original |
NOT_FOUND | Not located in the documents supplied | Check you passed every part of the contract |
A revised figure rendered over the one it replaced reads as 2412 months,
which is not a real value. It is either 24 or 12, and the difference is a year of
liability. The engine will not choose for you.
Payment milestones
The schedule and whether it closes at 100 per cent. A schedule that does not sum to 100 means a stage is missing or misread.
Compliance plan
| Part | What it holds |
|---|---|
| Heartbeats | Recurring duties that must run without a gap while an event lasts |
| Triggers | Clocks that start when something happens on site |
| Anchors | One off duties dated from the award |
| Gates | What must be true before money moves |
| Forfeitures | The duties where missing the deadline destroys the entitlement |
Read the forfeiture register first. It is the short list of ways to lose a claim on the calendar rather than on the facts.
Risk register
Each finding carries the sentence quoted from the contract, what it means in money, and the amendment to ask for. The verdict is set by how many critical findings there are.
| Verdict | Trigger |
|---|---|
| DO NOT SIGN WITHOUT NEGOTIATION | Four or more critical findings |
| NEGOTIATE THE CRITICAL ITEMS FIRST | One to three critical |
| ORDINARY RISK, WORTH A READ | Findings, none critical |
| NOTHING FLAGGED, WHICH IS UNUSUAL | Nothing matched. Read it yourself |
The last one is not a pass. It usually means the document is not a construction subcontract, so the patterns do not apply.
06Tracking a live event
The part that saves the claim
A compliance plan is only worth having if something runs against it. Feed the plan an event and it returns every obligation that event opened, which are still live, which were missed, and which of the misses destroyed an entitlement.
node test/eot-scenario.js
That runs the worked example on the demo contract. It prints the same delay event twice, side by side.
| What was done | Result |
|---|---|
| Nothing served | ENTITLEMENT LOST |
| Notice served on day five, particulars kept running | SLIPPING, zero forfeited |
Same event, same contract, same facts. The difference is a notice served on time.
When an obligation has been missed, the engine returns salvage routes rather than stopping: serve it late anyway, check when the clock actually started, check whether the same failure affects the main contractor upstream, and move the value to a route that has not expired.
To run it against your own contract, pass the file:
node test/eot-scenario.js "your-contract.pdf"
07Reading a tender
Before you commit to bidding
node src/rfp/cli.js "tender files..."
Pass the whole pack together: the instructions, the scope, the bill, the draft conditions and every addendum. They are one tender. Excel bills are read natively.
You get the submission clock with everything ambiguous flagged, the requirements with the disqualifying ones separated, the bill read back, the terms that will cost you, and a drafted proposal with every gap marked rather than invented.
| Task | Command |
|---|---|
| Draft the proposal and bid file | --proposal proposal.md --bidfile bid-file.md |
| Compare two revisions for scope drift | --diff "earlier.txt" "later.txt" |
| Create your bidder profile | --init-bidder bidder.json |
The diff exists because scope grows quietly between revisions. It reports what was added, removed or reworded, so a revised enquiry does not get priced against the original reading.
08The interface
For people who do not use a terminal
Double click Kontra+, or run it from a terminal:
npm start
The console has two screens, switched from the header.
| Screen | For |
|---|---|
| Contract | A subcontract you are already bound by. Drop the files in and press Read the contract. On your own machine you can also open Browse this computer, which stays closed until you ask for it |
| Tender | A tender you have not bid yet. Same file handling, different reader |
Once a contract is read, the header carries the project name and the subcontract number, and the page opens on the project overview: the engine verdict, the traps by tier, the next notice deadline, the forfeiture clocks and the number of rules compiled. Below it sit six tabs.
| Tab | What it holds |
|---|---|
| Overview | The highest ranked traps, what was read from each file, the money terms and what to check before you rely on the reading. Read What was read first: a file that produced no text is a scan, and everything else was read from the remaining files only |
| Trap register | Every finding, worst first, with its clause and what it does to you. Open a row for the clause as written and what to ask for |
| Redlines | Each flagged clause struck through beside the position to ask for instead. Copy the asks puts the whole list on the clipboard |
| Clocks | Every notice clock, grouped by the event that starts it, forfeitures first. Enter the date the event happened and each deadline is dated with the days left |
| Terms | The commercial figures with their confidence, collisions shown with both candidates, and the payment milestones |
| Full report | The same output the command line prints. Copy report and Print sit beside the tabs |
Two things on the screen are yours, not the engine's. Type the contract value into the money terms and the console works out what retention, security and the delay damages cap come to in riyals. Enter an event date in Clocks and it dates the deadlines that event opened, in calendar days, so check the contract's own definition of a day. Both are kept in your browser only and come back when you reopen the same subcontract.
The interface listens on 127.0.0.1 only, and it reads and writes files
anywhere on the machine, which is what a tender tool has to do. Do not expose it to a
network or forward its port. It has no authentication because it is not meant to be
reachable by anyone but the person sitting at the keyboard. The hosted console puts a
sign in and a web server in front of it, and that server refuses folder browsing and
file saving outright.
09When it refuses
A refusal is a result, not a failure
| What you see | What it means | What to do |
|---|---|---|
UNREADABLE | A scan with no text layer | Run it through optical character recognition first, or get the original file |
NOT_A_CONTRACT | Reads as something else entirely | Check you passed the right document. An empty result here means the wrong file, not no obligations |
CONTRACT_OUTSIDE_SCOPE | A real contract, but not a construction subcontract or tender, such as a services agreement, or an employment contract (including a Qiwa contract), which it names as one | Nothing was reviewed and no findings is not a clean result. Have it read by someone who reviews that kind of agreement. For an employment contract the Labour pack is coming |
NOT_EXECUTED | A draft, comparison or unsigned copy | Use the plan, but get the signed original before relying on a clause verdict |
TEMPLATE | An unfilled form | The numbers have not been written yet. An empty plan is correct |
PARTIAL | Some contract signals, not enough to be sure | Read the output with care and verify anything you act on |
10What it cannot do
Stated plainly, so nothing surprises you
- Scans need the opt in reader. A scanned signed contract with no text
layer is refused. On the command line,
--ocr=localreads it on this computer with a vision model running in LM Studio, so nothing leaves the machine; it takes about a minute and a half a page.--ocrinstead sends the page images to an outside transcription service, so it is off unless you ask for it. The console uses neither. Numerals inside stamps and handwriting are the weak points of both. - Party and appendix extraction is narrow. It reads specific subcontract conventions. On documents written to other conventions those fields come back empty rather than wrong.
- It is one machine, one operator. There are no accounts, no roles and no shared history.
- It does not store anything. Output is files and terminal, or the page in your browser. There is no record of who ran what.
- It is not legal advice. It reads what the document says and tells you what it will do to you. Whether to sign is a commercial and legal decision.
The risk register and the refusal behaviour hold up on documents the engine has never seen. On an unfamiliar subcontract it found 17 findings, each quoted from the text. That is the part you can rely on from day one.
11Troubleshooting
The five things that actually go wrong
| Symptom | Cause and fix |
|---|---|
node: command not found | Node is not installed or not on your path. Reinstall from nodejs.org and open a new terminal |
Everything is empty and the verdict is UNREADABLE | A scanned PDF, or Poppler is missing. Check with pdftotext -v |
Terms are NOT_FOUND on a real contract | The Appendix was not included. Pass every part of the contract in one command |
| Milestones do not sum to 100 | A stage was missed in conversion. Check the schedule by eye against the document |
| The interface will not open | Port 7801 is in use. Run node src/rfp/server.js 7802 and use that port |
If npm test does not finish green on a clean copy, do not use the output
for anything. Report it with the failing test names.
12Command reference
Everything, on one page
| Command | What it does |
|---|---|
npm test | 527 checks. Must finish green |
npm run demo | Full report on the contract that ships with the software |
| Double click Kontra+ | Starts it and opens the screen. The normal way in |
npm start | The same thing from a terminal, on port 7801 |
node src/cli.js "files..." | Read a contract |
node src/cli.js "files..." --json --out p.json | Same, as data |
node src/rfp/cli.js "files..." | Read a tender |
node src/rfp/cli.js "files..." --proposal p.md --bidfile b.md | Draft the proposal and bid file |
node src/rfp/cli.js --diff "a.txt" "b.txt" | Scope drift between two revisions |
node src/rfp/cli.js --init-bidder bidder.json | Create a bidder profile |
node test/eot-scenario.js ["file"] | The delay scenario, end to end |
node test/hr-scenario.js | The workforce scenario, Saudi Labour Law |
Put Kontra+ on your own computers.
The NDA is signed before anything is sent. We reply the same working day.