EWWE solutions
№ 03 · Manifest item 03 · AD MMXXVI
Time-slice · jedno ogłoszenie

OFERTOMAT. — pokazówka, nie sandbox.

Jedno realne ogłoszenie z BZP. Jedna firma demo. Pełen przebieg pipeline'u — od surowego HTML-a ogłoszenia, przez ekstrakcję 315-blokowej SIWZ, po draft siedmiosekcyjny i raport weryfikatora.

Zero wywołań LLM na wizytę. API Anthropic kosztuje pieniądze, a my nie palimy ich na boty. Produkt istnieje i działa. Demo to time-slice — jeden cached run z 19 maja 2026 roku.

Wejście, które nie znajdzie się tu nigdy: pole z numerem BZP, w które wpisujesz swoje ogłoszenie. To mamy w produkcji, nie w demo.

01 Wejście

OGŁOSZENIE BZP

2026/BZP 00236579 · SPZOZ Łapy

Małe miasto na Podlasiu, samodzielny publiczny ZOZ, krajowy próg, tryb podstawowy (art. 275 pkt 1 ustawy Pzp). Wdrożenie nowej domeny katalogowej i migracja 200 kont użytkowników. CPV 72263000-6 (Usługi wdrażania oprogramowania) plus cztery dodatkowe IT.

BZP API serwuje ogłoszenie jako JSON + 18 234 bajty HTML-a sekcji I–IX. Wszystko bez OAuth, bez paperworku, bez dev-portal-registration. Tylko publiczny endpoint /mo-board/api/v1/notice.

Identyfikatory

Numer BZP
2026/BZP 00236579
OCDS id
ocds-148610-81484d64
NIP zamaw.
9661319909
REGON
050644804
Tryb
art. 275 pkt 1
Termin ofert
19.05.2026 09:00
Realizacja
60 dni
Kryteria
Cena 100%
Wadium
nie wymagane

Dane wyciągnięte z BZP API + sparsowanego HTML-a ogłoszenia (parse.py · deterministyczne, zero LLM).

↓ Wykonawca · profil demo

firm_demo.json

PrzykładIT

Sp. z o.o.

NIP
5252888777
REGON
522444333
KRS
0000888777
Adres
ul. Próbna 1/2, 00-001 Warszawa
Podpisuje
Jan Kowalski, Prezes Zarządu
E-mail
przetargi@przyklad-it.pl

⚠  Firma fikcyjna

PrzykładIT to czysta fikcja na potrzeby demo. NIP/REGON/KRS są w zakresie poprawnych formatów, ale nie wskazują żadnego realnego podmiotu w rejestrach.

W produkcji wczytujesz własny profil z osobnego JSON-a (legal name, NIP, REGON, KRS, adres, reprezentant, dane kontaktowe). Profil żyje lokalnie, nigdy nie trafia do żadnej naszej bazy danych ani do rejestrów państwowych.

Profil demo osadzony w branży IT-procurement — typowym terenie ogłoszeń BZP.

02 Parse

HTML → JSON

parse.py · deterministyczne · ~150 ms

Sekcje SEKCJA I–IX z BZP API mają stabilne prefiksy numeryczne. BeautifulSoup4 + 20+ pól pydantic, trzy layouty parsera (span-w-h3, p-sibling, raw-text-tail). Zero LLM na tym etapie — wszystko regex/CSS.

Edge case, który łapie parser: pole organizationNationalId z API to NIP, ale pole HTML 1.4 to REGON. Bez rozróżnienia model w pierwszym runie zmyślił label „REGON” na wartości NIP — fix wymagał trzech miejsc (models.py, parse.py, prompt).

parsed.json · wycinek

TenderAnnouncement

{
  "bzp_number": "2026/BZP 00236579",
  "organization_name": "SPZOZ ŁAPY",
  "organization_nip": "9661319909",
  "order_object": "Wdrożenie …",
  "cpv_main": {
    "code": "72263000-6",
    "label": "Usługi wdrażania …"
  },
  "cpv_additional": [ … 4 kody ],
  "submitting_offers_date":
      "2026-05-19T07:00:00Z",
  "realization_period": "60 dni",
  "criteria": [
    { "name": "Cena", "weight_pct": 100.0 }
  ],
  "tender_amount_below_eu": true
}
20+ pól ~150 ms
03 SIWZ ingest

315 BLOKÓW 
→ STRUKTURA

siwz_extract.py · claude-haiku-4-5 · tool-use forced JSON

Ogłoszenie BZP to czterostronicowy nagłówek. Prawdziwe wymagania siedzą w SIWZ (Specyfikacja Warunków Zamówienia) — tu plik SPECYFIKACJA WARUNKÓW ZAMÓWIENIA (SWZ).docx, 315 paragraph-bloków, ≈57k znaków, pobrany z platformy e-Zamówienia mp-client przez nieudokumentowany endpoint /mp-readmodels/api/Search/GetTender.

Wyciąg do SiwzRequirements (pydantic): warunki udziału, kryteria oceny z formułą, wymagane dokumenty, terminy, wadium, kary umowne, kontakt. Haiku 4.5 z wymuszonym JSON-em (tool-use). Zero halucynacji: jeśli SIWZ czegoś nie definiuje, pole wraca jako null albo [].

W Łapach: warunki_udzialu=[] (poza brakiem wykluczenia), kary_umowne=[] (regulowane w projekcie umowy, załącznik nr 2), wadium=null. Każde z tych brak jest weryfikowalne w źródle — i jest powodem, dla którego drafter w sekcji D pisze „wadium nie jest wymagane” zamiast wymyślać kwotę.

SiwzRequirements · wycinek

Termin związania
do 17.06.2026
Wadium
null
Kryterium
Cena 100%
(Cn/Cb)×100
Realizacja
60 dni od umowy
≤ 6.07.2026
Warunki udziału
[ ] (puste)
Kary umowne
[ ] (w umowie)
Dokumenty
8 pozycji
Notes (SIWZ)
18 punktów

Ekstrakcja: Haiku 4.5

04 Draft

SIEDEM SEKCJI
A – G

draft.py · claude-haiku-4-5 · ~19s · prompt-cached

Drafter dostaje obie struktury: TenderAnnouncement + SiwzRequirements + FirmProfile. Wyjście to siedem oznaczonych sekcji w jednym pliku Markdown, gotowe do skopiowania do platformy e-Zamówienia po edycji przez specjalistę.

Wszędzie, gdzie brakuje danych (np. cena ofertowa, data podpisu), drafter wstawia [DO UZUPEŁNIENIA: ...] z konkretnym opisem co specjalista musi wpisać — zamiast halucynować kwoty albo daty.

Sekcje · draft.md

  • AOświadczenie o niepodleganiu wykluczeniu
  • BJEDZ Część I — postępowanie
  • CSzkic listu intencyjnego
  • DUwagi szkicownika
  • EJEDZ Część II — wykonawca
  • FJEDZ Część III — wykluczenia
  • GJEDZ Część IV — kwalifikacje

Wariant Sonnet 4.6: ~3× wall (review pass)

↓ pełny draft · renderowany z draft.md

draft.md · 2026/BZP 00236579 · ~14 KB

attempt 1/3 · verifier ✓ PASSED

ładowanie…

Źródło: artifacts/draft.md · cached z runa 19.05.2026

05 PASSED

WERYFIKATOR
DWA TIERY

verify.py · deterministic + LLM cross-check

Drafter dostaje retry — do dwóch razy regenerujemy draft, jeśli weryfikator flaguje błędy severity=error. Keep best: jeśli żadna próba nie PASSuje, zostawiamy tę z najmniejszą liczbą findingów (errors first, attempt index tie-break).

Tier 1 — deterministyczny. Pure regex/string, zero LLM. Łapie literówki w nazwie firmy (klasa PrykładIT → PrzykładIT: brakująca litera + warianty diakrytyczne), brakujące NIP/REGON/KRS firmy lub zamawiającego, brakujący numer BZP, oraz 10-cyfrowe tokeny które nie pasują do żadnego znanego identyfikatora.

Tier 2 — LLM cross-check. Haiku 4.5 z forced-JSON tool-use. Każdy cytat warunku z sekcji G musi prześledzić się z powrotem do SiwzRequirements; każda liczba/data w sekcji A/B/C musi zgadzać się z TenderAnnouncement. Flaguje tylko rzeczywiste rozbieżności faktyczne, nie preferencje stylistyczne.

Wynik (Łapy)

Status
PASSED
Errors
0
Warns
1
Info
1
Attempt
1 / 3
Model
haiku-4-5

Phase 0.9 test matrix: 3/3 samples PASS first-attempt (Łapy IT, Miastko hospital maint., Pucki GIS).

↓ findings · verify.json (renderowane)

verify.json

2 findings · 0 error · 1 warn · 1 info

Produkt · bez bota publicznego

PRODUKT 
DZIAŁA.

Tego konkretnego flow nie uruchomisz tutaj — bo każde uruchomienie pipeline'u to realny koszt LLM, a my nie wystawiamy boto-vendingu publicznie zanim mamy chociaż jednego płacącego klienta na ten produkt.

Chcesz uruchomić na własnym BZP — z własnym profilem firmy, własnym CPV-watchlistem, własnym monitorem dziennego digestu? Napisz mailem. W odpowiedzi: profil firmy do wgrania (JSON) i termin pierwszego draftu w 24 h.

patryk@ewwesolutions.work