Explainable procurement metadata triage, run locally.
· v0.2.0-alpha.1
· Python 3.11+
· Apache-2.0
Quick start · Desktop preview · Example output · Verdicts · Roadmap · Limitations · Contributing
TenderVerdict is experimental open-source software for supplier-side pre-qualification of public-procurement notice metadata. The published developer alpha contains a CLI, Python library, and an unsigned local desktop preview. You supply a company profile and structured notices; TenderVerdict applies narrow, deterministic rules and produces a review queue with reasons, unresolved fields, and a human next step.
It does not read full procurement documents or decide whether you should bid.
| Property | What it means |
|---|---|
| Local-first | demo and qualify read local files and make no network requests. |
| Deterministic | The same inputs and explicit --as-of review point produce the same verdicts. |
| Traceable | Reports preserve reasons, unknowns, source metadata, generator version, and input SHA-256 digests. |
| Fail closed | Invalid input or a failed fetch returns an error without publishing partial output. |
| Small footprint | The installed package has no runtime dependencies. |
Important
v0.2.0-alpha.1 is an unsigned developer alpha, not a consumer installer. Interfaces and rules
may change. Start with the bundled synthetic example, avoid confidential inputs, and do not
disable operating-system security controls to run an archive.
| Surface | Current state | Installation path |
|---|---|---|
| CLI and library | Published as v0.2.0-alpha.1 |
Versioned source tag below |
| Desktop UI | Published developer alpha | Source with Tk or unsigned native archive |
| macOS archives | CI-tested; arm64 flow completed hands-on | Opt-in evaluation only |
| Windows x64 archive | Native CI and frozen smoke test passed; no hands-on run yet | Experimental opt-in evaluation |
There is no trusted one-click installer, hosted service, account system, telemetry, or automatic
update channel. See ROADMAP.md for the evidence gates and evaluation thresholds.
Requires Python 3.11 or newer. The commands below install the immutable developer alpha in an isolated virtual environment.
git clone --branch v0.2.0-alpha.1 --depth 1 \
https://github.com/demidgost-sys/tenderverdict.git
cd tenderverdict
python3 -m venv .venv
.venv/bin/python -m pip install .
.venv/bin/tenderverdict demogit clone --branch v0.2.0-alpha.1 --depth 1 `
https://github.com/demidgost-sys/tenderverdict.git
cd tenderverdict
py -m venv .venv
.venv\Scripts\python -m pip install .
.venv\Scripts\tenderverdict demoOnce installed, the demo is fully offline and returns exactly one example of each verdict. Installing from source may download the pinned build tool if it is not already cached.
The desktop preview removes the need to edit the supplier profile by hand. It provides labelled fields for the supplier criteria, immediate validation for normalized CSV or JSON notice data, an editable CSV example, an explicit review point, verdict filters, sortable results, plain-text copy, and atomic HTML, Markdown, or JSON export.
It uses the same deterministic workflow as the CLI. It does not upload data, fetch TED metadata, open source URLs automatically, or make a participation decision.
Run it from source:
git clone https://github.com/demidgost-sys/tenderverdict.git
cd tenderverdict
python3 -m venv .venv
.venv/bin/python -m pip install .
.venv/bin/tenderverdict desktopOr download the archive and matching .sha256 file for macos-arm64, macos-x64, or
windows-x64 from the
v0.2.0-alpha.1 prerelease.
Read START_HERE.txt and verify the checksum before extracting. These archives are unsigned:
macOS lacks Developer ID signing and notarization, and Windows lacks Authenticode signing. If the
operating system does not accept an archive normally, use the source workflow or stop the test;
do not weaken Gatekeeper, SmartScreen, antivirus, or another security control. See
DESKTOP.md for the complete trust, privacy, build, and accessibility boundaries.
Completed an independent packaged run? Share the target, commit, completed steps, and first blocker in the opt-in desktop feedback issue. Use only synthetic, public, or fully de-identified material.
| Verdict | Why it appears | Human next step |
|---|---|---|
open_documents |
Exact CPV and geography match, sufficient lead time, competition notice, valid HTTPS source URL | Open and review the official documents. |
watch |
Important metadata is missing or only a broader CPV-family match is available | Resolve the flagged uncertainty first. |
reject |
A configured hard stop applies, such as a near deadline or explicit mismatch | Stop unless the metadata is corrected. |
View the complete synthetic HTML report
The report is generated from fictional data committed to this repository. Reproduce it with:
tenderverdict demo --format html --output demo/index.htmltenderverdict qualify \
--profile examples/synthetic/profile.json \
--notices examples/synthetic/notices.csv \
--as-of 2026-08-02 \
--format markdown \
--output report.mdUse --format json for machine-readable output. Notice data can be normalized .csv or .json.
Validation errors return a non-zero exit code and do not replace an existing output file.
Minimal company profile:
{
"schema_version": 1,
"name": "Example Software GmbH",
"cpv_codes": ["72260000"],
"countries": ["AUT", "DEU"],
"minimum_days_to_deadline": 14
}The complete CSV header is:
publication_number,lot_id,notice_type,title,buyer,cpv_codes,countries,deadline,deadline_at,publication_date,source_url
publication_number is required. A notice-level row must be unique case-insensitively; distinct
lot-level rows may share it when each has a unique official lot_id. lot_id, deadline_at, and
publication_date are optional, so the shorter v0.1 header remains accepted. Do not mix a
notice-level row and lot-level rows for the same publication.
Use deadline for a YYYY-MM-DD calendar date, or leave it empty and use deadline_at for an
RFC 3339 timestamp with an explicit UTC offset. Supplying both is an error. --as-of accepts the
same date-or-timestamp distinction. A date-only review point becomes watch when an exact
timestamp falls on a boundary that cannot be resolved without a review instant.
Use | inside cpv_codes or countries when a row has multiple values, for example
72260000|72261000 or AUT|DEU. Comma-, semicolon-, and tab-separated files are accepted; the
bundled example uses commas. CSV is treated as data, never as executable spreadsheet content.
A notices file may contain at most 1,000 records and 10 MiB. Text fields and value lists also have
explicit bounds. A valid header-only CSV and an empty JSON array both produce a zero-notice report;
validation or network failure remains an error and never means "zero matches". JSON, Markdown, and
HTML reports include provenance; the JSON report format in 0.2.0a1 is schema version 3.
Eight-digit CPV values and three-letter country values are checked offline against the bundled,
source-traceable EU vocabulary snapshots described in DATA_SOURCES.md.
See examples/synthetic for matching CSV and JSON fixtures and a
reproducible report.
The qualification rules are deliberately narrow:
reject— a closed or near deadline, explicit CPV/country mismatch, or non-competition notice;watch— missing important metadata, an invalid source URL, or only a CPV-family match;open_documents— exact CPV and geography match, sufficient lead time, competition notice, and a syntactically valid absolute HTTPS source URL.
open_documents means only that the configured metadata checks passed. TenderVerdict does not
provide legal advice, determine eligibility, compare bidders, predict outcomes, recommend bidding,
or take an autonomous procurement action. Read LIMITATIONS.md before applying
the output to real work.
Calendar-date deadlines retain the v0.1 rule: a deadline equal to a date-only --as-of is treated
as closed. Exact deadline_at timestamps are compared in UTC when --as-of is also an RFC 3339
instant; unresolved date-only boundary cases become watch instead of being guessed.
fetch-ted is an explicit, read-only network operation. The demo, local qualification, tests, and
CI do not use it.
tenderverdict fetch-ted \
--query "classification-cpv = 72260000 SORT BY publication-date DESC" \
--max-notices 10 \
--output notices.jsonThe adapter uses the fixed HTTPS TED Search API endpoint, bounded pagination and response limits,
and atomic output replacement after a complete successful fetch. Its JSON snapshot records the
query, UTC retrieval time, endpoint, and lot policy, and can be passed directly to qualify.
TED Search API rows are notice-level. For a multi-lot result, TenderVerdict retrieves that notice's
bounded official eForms XML from a fixed TED HTTPS URL and emits one normalized row per verified
lot. Search and XML lot identifiers must agree exactly or the whole fetch fails without replacing
output. A zero-lot result still withholds scope-ambiguous evidence and becomes a human-review case.
The number of XML documents and expanded rows is bounded. Review
DATA_SOURCES.md and the current source terms before relying on fetched metadata.
PYTHONPATH=src python3 -m unittest discover -s tests -v
python3 tools/check_public_tree.py
python3 tools/security_scan.py
ruff check .
ruff format --check .
mypyThe functional test suite is offline; TED behaviour is tested with mocked HTTP responses.
Reproducible bug reports and research feedback are welcome through
GitHub Issues. There is no guaranteed
support or response time during the alpha period.
Read ROADMAP.md, CONTRIBUTING.md,
SECURITY.md, and CODE_OF_CONDUCT.md before contributing.
TenderVerdict ist ein experimentelles, quelloffenes und lokal ausgeführtes CLI zur
Vorqualifizierung von Metadaten öffentlicher Ausschreibungen aus Sicht von Anbietern. Ein lokales
Unternehmensprofil und strukturierte Notice-Daten aus CSV oder JSON werden nachvollziehbar als
open_documents, watch oder reject eingeordnet. Das Werkzeug bietet keine Rechtsberatung,
trifft keine Vergabe- oder Teilnahmeentscheidung und ersetzt nicht die Prüfung der
Ausschreibungsunterlagen. Die veröffentlichte Alpha-Version ist ein CLI; main enthält zusätzlich
eine noch unveröffentlichte Desktop-Vorschau ohne unterstützten Ein-Klick-Installer.
The code is licensed under the Apache License 2.0. Procurement records, TED names,
logos, interfaces, and source data are not relicensed by this repository. See NOTICE
and DATA_SOURCES.md.
Maintained by Demid Valiullin in Graz, Austria.
