master
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2e9d3706ec |
astrodemo: zmiana nazwy, rebase na mastera i domknięcie wycieków
Testy / Testy warstwy logicznej (silnik) (push) Failing after 4m50s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m25s
Testy / Testy astrodemo (push) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 8s
Testy / Kontrola składni wszystkich warstw (push) Successful in 5s
Testy / Testy warstwy logicznej (silnik) (pull_request) Failing after 4m43s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m25s
Testy / Testy astrodemo (pull_request) Successful in 9m25s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 6s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 4s
Pierwszy z pięciu kroków budowy trzech produktów: astrodemo (dwie funkcje) → astroklient (pełne astro bez AI) → astrololo (wszystko). Nazwa „astroklient" zostaje zwolniona dla warstwy pośredniej, więc dotychczasowe astroklient-demo nazywa się teraz astrodemo. REBASE. Cztery commity demo przeniesione na aktualnego mastera. Konflikt był jeden — rejestr wymagań (xlsx, binarny, git go nie scali). Master dodał LOG-34, gałąź demo PRE-28 i PRE-29; żaden wspólny wiersz się nie różnił, więc scalone ręcznie: 148 pozycji, wszystkie trzy obecne. ZMIANA NAZWY. Katalog, ciasteczko sesji (astrodemo_sesja), zmienne ASTRODEMO_USERS/USER/PASSWORD, CI, README, docstringi. Ponieważ PR z demo nigdy nie został zmergowany, usługa nie jest nigdzie wdrożona — zmiana nazw niczego nie migruje i nikogo nie wylogowuje. WYCIEKI. astrodemo powstało przed audytem z PRE-27, więc miało komplet tych samych dziur: - /static omijało bramkę (PUBLIC_PREFIXES), a pierwszy komentarz w styles.css brzmiał „Nie kopiujemy stylów pełnej aplikacji" — czyli anonimowy curl dowiadywał się, że istnieje pełna aplikacja. Zasoby idą teraz trasą z jawną listą, komentarze są zdejmowane przy serwowaniu. - Komunikat awarii wypisywał na ekran treść wyjątku httpx, z nazwą usługi i portem. Teraz jedno neutralne zdanie, szczegóły do dziennika. - /health oddawał nazwę warstwy. Teraz samo „ok". - Dziesięć komentarzy i docstringów tłumaczyło decyzje przez porównanie z „pełną aplikacją". Obraz tej usługi się KOMUŚ ODDAJE, więc kto go dostanie, przeczyta też komentarze. Przepisane tak, żeby opisywały tę usługę samą w sobie. - Nagłówek main.py twierdził, że demo dzieli pulę plików z produkcją. To nieprawda od PRE-29 (pule per konto) — opis poprawiony. ZAPORA SŁOWNIKOWA, dwupoziomowa. Poziom „wszędzie" (także w kodzie serwera, bo obraz się oddaje) obejmuje wzmianki o większym rodzeństwie, o modelu językowym i o funkcjach, których tu nie ma. Poziom „do przeglądarki" dokłada słownictwo mechanizmów. Test sprawdza odpowiedzi ORAZ drzewo plików. Jeden wyjątek jest jawny i opisany: stałe protokołu łącza (X-Astrololo-Token, X-Astrololo-Enc, typ treści, etykieta HKDF) niosą nazwę rodziny produktów. Są wspólne z warstwą logiczną, więc zmiana wymaga jednoczesnej podmiany we wszystkich usługach i rotacji — osobna decyzja. Osobny test pilnuje warunku, pod jakim to zostaje: że nie docierają do przeglądarki. Wcześniej przechodziły tylko dlatego, że regex nie dopasowywał po myślniku — przypadek, nie decyzja. Przy okazji: komunikat „ramka bez znacznika astrololo" zmieniony na neutralny we WSZYSTKICH PIĘCIU kopiach link_crypto.py (presentation, astrodemo, logic, data, render), żeby nie rozjechały się przed scaleniem w rdzeń. Te kopie to 2625 linii tego samego kodu. Testy: astrodemo 27, presentation 358, logic 342, data 42, render 41. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
320a0ab24e |
PRE-27: pełne ukrycie niedostępnych funkcji (paranoja)
build-render / build (push) Failing after 8s
build-swisseph / build (push) Successful in 9s
build / build (push) Successful in 8s
Testy / Testy warstwy logicznej (silnik) (push) Failing after 5s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 4s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Failing after 4s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 6s
Testy / Kontrola składni wszystkich warstw (push) Failing after 4s
Ukrywanie jest teraz nadrzędne wobec wygody i czytelności komunikatów. Persona: konto z uprawnieniami files + files_input, zatrudnione wyłącznie do wgrywania plików. Nie ma się dowiedzieć, po co je wgrywa ani co program będzie robił — bo to rozgada. Audyt sześciu kanałów wycieku (statyki, HTML, sondowanie HTTP, ekran plików, odpowiedzi JSON i błędy, pozostałe warstwy) potwierdził 26 wycieków, każdy odtworzony uruchomionym kodem i zweryfikowany adwersarialnie. Ani jeden nie był przyciskiem. ZASÓB JEST CZĘŚCIĄ FUNKCJI /static/ omijało CAŁĄ bramkę (PUBLIC_PREFIXES), więc każdy skrypt i arkusz pobierał ktokolwiek, także niezalogowany, pod zgadywalnym adresem — a ich treść wymienia ekrany, dostawców modeli i przeznaczenie plików. Ruch ten nie trafiał przy tym ani do dziennika, ani pod limit żądań, więc wyciek był niewidoczny. Zasoby idą teraz trasą z bramką; każdy ma w features.STATIC uprawnienie swojego ekranu. Publiczny został jeden base.css, bo potrzebuje go ekran logowania. KOMENTARZ NIE JEDZIE NA DRUT Komentarze w CSS/JS opisywały funkcje pełnymi zdaniami po polsku — łącznie z „Wstrzymane widzi tylko administrator", czyli i mechanizmem kwarantanny, i istnieniem konta o wyższych uprawnieniach. _asset_body() usuwa je przy serwowaniu; w repozytorium zostają. styles.css rozbity na base.css + arkusz na ekran + x-ai.css. Jeden plik z wszystkimi selektorami był spisem treści programu. Podział zrobiony mechanicznie, z osobnym sprawdzeniem, że żaden ekran nie stracił reguły. base.html ładował skrypty kosmogramu na KAŻDEJ stronie — konto mające wyłącznie Pliki pobierało je przy wejściu na swój jedyny ekran, razem ze wzmianką o „przyszłej zakładce". Teraz dokłada je ekran, który ich używa. RÓŻNICA JEST INFORMACJĄ Komunikat po wgraniu pliku różnił się zależnie od wyniku walidacji — czyli był wyrocznią do odgadywania reguł, które ma znać tylko administrator — i mówił wprost, że plik „musi zatwierdzić administrator". Teraz jest jeden, ten sam. _logic_error wypisywał na ekran nazwę trasy, nazwę podsystemu, nazwę gałęzi rozwojowej i wewnętrzny host:port. Jedno zdanie dla wszystkich awarii, szczegóły do dziennika. Odsiew w jednym punkcie, nie w siedemnastu wywołaniach. Ponadto: stopka nie ogłasza architektury, /health nie nazywa warstwy, konto bez ekranów dostaje 404 zamiast tłumaczenia, ekran plików mówi o plikach zamiast o „bazach interpretacyjnych", klasy .house-warning i .account-card przemianowane na neutralne, a logic/data/render/engine-swisseph nie wystawiają już /docs ani /openapi.json i nie publikują portów na hoście. ZAPORA SŁOWNIKOWA test_slownik_zakazany.py nie sprawdza miejsc, tylko przechodzi wszystko, co dane konto może pobrać, i szuka słów, które nie mają prawa paść (87 pozycji dla tej persony). Nazwy funkcji, adresy ekranów i nazwy zasobów biorą się wprost z katalogu, więc nowa funkcja obejmuje się sama. Kontrola pozytywna pilnuje, żeby test nie przechodził dlatego, że program jest pusty. Sprawdzone: zapora puszczona na treść sprzed poprawek daje 16 trafień na samym styles.css i łapie każdy ze zneutralizowanych komunikatów. 358 testów zielonych, ekrany obejrzane w przeglądarce. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7266f671a4 |
feat(domy): Placidus i Koch + jawny fallback poza kołem podbiegunowym
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 17s
Testy / Kontrola składni wszystkich warstw (push) Successful in 8s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m28s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 18s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
Etap 2: dwa systemy łuku dobowego — jedyne, które mają miejsca, gdzie po prostu NIE ISTNIEJĄ. Koch zgadza się z wyrocznią co do zera; Placidus do 1,7e-6°, przy czym to próg zbieżności WYROCZNI, nie nasz: nasze cuspy spełniają definicję Placidusa z dokładnością 1e-12° (osobny test, działa bez swissepha). Placidus jako jedyny nie ma wzoru zamkniętego — cusp jest zdefiniowany warunkiem na samego siebie („punkt, który przebył 1/3 swojego półłuku"), więc iterujemy po punkcie stałym do 1e-11°. Brak zbieżności traktujemy jako wyjście poza dziedzinę, nie jako wynik. Koch okazał się natomiast ZAMKNIĘTY: jego kryterium to czas od wschodu stopnia stojącego na MC, a półłuk tego stopnia znamy wprost z jego deklinacji. Definicja za Astrodienst (astro.com/astrowiki/en/Koch_House_System) — nie zgadywana. Powyżej koła podbiegunowego oba odmawiają liczenia i wyrocznia odmawia dokładnie tych samych przypadków (5245/20 000 losowych, zero rozjazdów dziedziny). Odmowa jest wyjątkiem, nie liczbą: cicha podmiana systemu jest niewykrywalna z wykresu. Ustępstwo wobec rzeczywistości siedzi osobno, w cusps_detailed(): podstawia Porphyry'ego i ZAWSZE zostawia ślad. Ten ślad idzie wszystkimi trzema wyjściami — na ekran (ramka, nie „muted"), w prompt do modelu (inaczej napisze „Twój Placidus" o Porphyrym) i do PDF-a, w ramce PRZED rysunkami. Astrolog z Tromsø dostaje wynik i wie, że go dostał inaczej. Przy okazji: nazwy systemów były zaszyte w czterech szablonach naraz. Przy trzech systemach uchodziło to na sucho, przy dziesięciu nie — jest katalog w jednym miejscu, a testy szablonów RENDERUJĄ je zamiast szukać tekstu w źródle, więc łapią też literówki w Jinja. Większe jądro efemeryd (de441): świadomie zdegradowane do „nice to have" — rozszerza wyłącznie zakres dat, nie poprawia niczego w obecnym. Odnotowane w domain.py przy JD_MIN/JD_MAX, żeby nie wróciło po cichu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f5dec15e4d |
feat: aspektarian, deklinacja i antyscja trafiają do raportu i PDF-a
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m13s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m49s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 29s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 20s
build-render / build (push) Successful in 44s
build / build (push) Successful in 54s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m19s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m59s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 34s
Testy / Kontrola składni wszystkich warstw (push) Successful in 25s
Zasada: co składamy, dodajemy i wyświetlamy, MA trafiać do finalnego raportu
(«Skompiluj») i do PDF-a — nie tylko na stronę /chart. Do tej pory do raportu i
druku szło samo koło; aspektarian (etap 5) i deklinacja/antyscja (etap 6) były
tylko w podglądzie horoskopu.
RAPORT «Skompiluj» (podgląd): handler /compile liczy teraz wszystkie cztery
rysunki, a szablon je pokazuje (koło, aspektarian, deklinacja, antyscja).
PDF (usługa render) — uogólnienie z jednego rysunku na LISTĘ:
- Kontrakt raportu: `figures = [{svg, caption}]` (uporządkowana). `wheel_svg`
zostaje dla zgodności wstecznej jako pojedynczy rysunek.
- `compile.py`: każdy SVG osobno przez rsvg-convert → PDF (fig0…figN); braki/
błędy pomijane (rysunek nie może wywalić raportu, tekst ważniejszy).
- `latex.py build()`: rysunki w sekcji 3 (po danych, przed natalną) w PODANEJ
kolejności, każdy z podpisem. Jedna reguła składania: keepaspectratio z limitem
szerokości i wysokości — kwadratowe (koło, aspektarian) ogranicza wysokość,
szerokie (deklinacja, antyscja) szerokość, bez zniekształceń.
- `compile_pdf` (prezentacja): renderuje komplet w motywie DRUKU i wysyła jako
`figures`.
Testy: render +5 (kolejność, podpisy, zgodność wsteczna, pomijanie pustych),
prezentacja +3 (raport pokazuje komplet, PDF składa komplet). Render 32,
prezentacja 173.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
998c83b26e |
fix(render): potrójne gwiazdki i kratki bez spacji nie wyciekają do PDF
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m9s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m59s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 39s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 18s
build-render / build (push) Successful in 8m52s
build / build (push) Successful in 7m9s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 13m40s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 10m3s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 36s
Testy / Kontrola składni wszystkich warstw (push) Successful in 28s
Dwie realne dziury w markdown→LaTeX, obie WIDOCZNE w gotowym PDF:
1. `***mocne***` (pogrubienie+kursywa) łapało się jako `**` + zgubiona gwiazdka →
`\textbf{*mocne}*`, czyli w druku zostawał wisior `*`. Dokładam alternatywę
`\*\*\*…\*\*\*` PRZED `**` i `*` (kolejność od najdłuższego znacznika) →
`\textbf{\textit{…}}`.
2. Nagłówek bez spacji po kratkach (`##Tytuł`), zamknięty ATX (`## Tytuł ##`)
i 7+ kratek trafiały do akapitu i były eskejpowane jako `\#\#…`. Pułapka: w
LaTeXu `\#` renderuje się jako `#`, więc w PDF WIDAĆ było `##`, choć w źródle
`.tex` jest `\#\#`. Dlatego stary test (`"##" not in out`) tego nie łapał —
podłańcuch `##` nie występuje w `\#\#`. Nagłówki traktujemy teraz pobłażliwie:
dowolna liczba kratek na starcie, spacja nieobowiązkowa, końcowe kratki
ucinane, gołe kratki bez treści pomijane. Żaden znacznik nagłówka nie ostaje.
Nowa asercja w testach patrzy pod kątem RENDERU: brak `\#` i brak wiszącej
gwiazdki (poza gwiazdką poleceń `\section*` itd.). +7 testów regresji, render 34.
UWAGA DEPLOY: obraz render w rejestrze to wciąż
|
||
|
|
623603b157 |
feat: Markdown→LaTeX w PDF + dopracowanie kosmogramu (PRE-24, PRE-12 etap 4)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m34s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m35s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 35s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 19s
build-render / build (push) Successful in 45s
build / build (push) Successful in 50s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m46s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m33s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 28s
Testy / Kontrola składni wszystkich warstw (push) Successful in 21s
Dwie rzeczy w jednym PR (na prośbę).
1) MARKDOWN → LATEX w raporcie PDF (usługa render). Tekst od AI to markdown —
świetny w przeglądarce, ale w PDF `**gwiazdki**` i `## kratki` to dosłowny szum.
Nowy markdown_to_latex zamienia je na PRAWDZIWE formatowanie: nagłówki (degradowane
o poziom, żeby wpadły pod nasz \section „Interpretacja natalna", nie obok),
pogrubienia, kursywy, kod, listy punktowe i numerowane, linki (zostaje sam tekst,
URL bezużyteczny w druku).
Skaner liniowy, nie regex na całości — listy i akapity są wielolinijkowe.
Ucieczka znaków LaTeXa działa TAKŻE wewnątrz formatowania: `**wzrost 50%**` daje
`\textbf{wzrost 50\%}`, a nie zakomentowaną resztę linii. Sprawdzone na wrogim
tekście — `\end{document}` i `\input{}` w treści nie wyrywają się z dokumentu
nawet zawinięte w pogrubienie.
2) KOSMOGRAM — etap 4 (dopracowanie):
- Lots na kole: Fortuna ⊗ (jedyny Lot ze standardowym glifem) na promieniu POD
pierścieniem planet i w akcencie — od razu widać, że to punkt wyliczony, nie
ciało. Loty bez glifu (Spirit, Eros…) pomijamy, żeby nie zaśmiecać.
- Tooltipy: natywny <title> w SVG (bez JS-a). Obiekt → nazwa, pozycja, dom,
retrogradacja. Linia aspektu → „Słońce trygon Mars · orb 0.20°" (polskie nazwy
tylko do dymka; obliczenia trzymają angielskie). Fortuna → nazwa i pozycja.
- Stopnie cuspów przy szprychach. W whole sign cuspy są na 0° znaku — wtedy
pomijamy dwanaście zbędnych zer; w systemach kwadratowych (porphyry) stopień
realnie coś mówi, więc go pokazujemy.
Wszystko działa też w motywie druku (PDF): sprawdzone, że mimo Lotów, dymków
i cuspów SVG nadal nie ma zmiennych CSS.
Weryfikacja wizualna (porphyry): Fortuna przy AC, 12 stopni cuspów, 38 dymków
(24 aspekty + 13 obiektów + Fortuna). Testy: +12 markdown (render), +7 etap 4
(prezentacja). Całość: prezentacja 145, render 27.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
f24616d342 |
feat(render): raport PDF przez LaTeX jako osobna usluga (PRE-24)
build / build (push) Successful in 1m27s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m25s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 10m1s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 33s
Testy / Kontrola składni wszystkich warstw (push) Successful in 27s
Ostatnia z osmiu wskazowek partnerow. Nowa usluga services/render sklada raport:
generuje plik posredni .tex i kompiluje go XeLaTeX-em do PDF.
OSOBNY komponent, nie czesc prezentacji — ta sama zasada co przy izolacji
swissepha (LOG-27). TeX Live wazy setki megabajtow; w obrazie produktu
spowalnialby kazdy build, a tak aktualizuje sie niezaleznie i jego awaria nie
kladzie aplikacji, tylko przycisk „Pobierz PDF".
SZYFROWANIE, o ktore prosiles: lacze prezentacja↔render idzie tak samo jak
pozostale, ale z WLASNYM, TRZECIM kluczem (LINK_KEY_PRESENTATION_RENDER). Osobny,
bo tym laczem plynie CALY raport — dane urodzeniowe i opisy z baz — wiec przejecie
go nie moze otwierac lacza do logiki ani do danych. Fail-closed: bez klucza pod
nie wstaje. Test kopii link_crypto obejmuje teraz cztery uslugi.
Uklad PDF wg prosby: imie i nazwisko -> wprowadzone dane -> RYSUNEK kosmogramu
-> interpretacja natalna -> predykcje okresowe. Test pilnuje kolejnosci.
Dwie rzeczy, ktore wyszly dopiero przy skladaniu tego kawalka:
1. KOSMOGRAM NIE NADAWAL SIE DO PDF. Uzywa zmiennych CSS (var(--line)) i klasy
.glyph, ktorej font podaje styles.css — a samodzielny konwerter SVG→PDF nie zna
naszego arkusza. Wyszlyby czarne kreski BEZ SYMBOLI. Stad wariant „print":
konkretne kolory na bialym tle i font glifow wpisany wprost w rysunek. Przy
okazji zalatwia to etap 4 planu kola (wariant do druku).
2. UCIECZKA ZNAKOW LATEXA byla zepsuta — i zlapal to moj wlasny test. Zamiana
„\” na \textbackslash{} szla w tej samej petli co nawiasy, wiec kolejne
podmiany ucieklyby nawiasy dopiero co wstawione: wychodzilo
\textbackslash\{\}. Poprawka: ukosnik chowany pod znacznik zastepczy i
rozwijany na koncu. To nie kosmetyka — niezauwazony „%” komentuje RESZTE LINII,
wiec zdanie od modelu urywaloby sie w polowie, a PDF powstawalby normalnie,
tylko krotszy. Test na wrogim tekscie sprawdza tez, ze \end{document} ani
\input{} nie wyrwa sie z dokumentu.
Usluga nie zapisuje nic poza katalogiem tymczasowym, ktory sprzata po sobie;
w manifescie readOnlyRootFilesystem + emptyDir na /tmp. /health raportuje
obecnosc xelatex i rsvg-convert, zeby zepsuty obraz bylo widac od razu.
Zweryfikowane na zywo (TestClient uslugi render): zadanie bez szyfrowania
z POPRAWNYM tokenem -> 400; obcy klucz -> 400 i tajny opis nie wraca; wlasciwy
klucz -> zadanie dochodzi do aplikacji, tresci baz NIE MA na kablu, odpowiedz
zaszyfrowana. Manifesty przechodza kubectl apply --dry-run=server na zywym
klastrze.
CZEGO NIE SPRAWDZILEM: samej kompilacji PDF. W tym srodowisku nie ma ani TeX
Live, ani dzialajacego runtime'u kontenerow (docker CLI jest, daemon nie) —
probowalem zbudowac obraz i sie nie dalo. Sprawdzone jest wszystko dookola:
generowanie .tex, ucieczka znakow, szyfrowanie, kontrakt API, samowystarczalnosc
SVG. Pierwsze uruchomienie na klastrze trzeba obejrzec — dlatego PRE-24 zostaje
jako „W trakcie", nie „Zrobione".
Instrukcja wdrozenia: docs/wdrozenie-render-pdf.md (klucz, obraz, merge,
weryfikacja, znane ograniczenia).
Testy: 15 nowych (render) + 14 (lacze i wariant druku w prezentacji).
Calosc: prezentacja 131, logika 265/1 skip, render 15.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|