21a00b0000eeb83d43a518a422540f21158aa4fb
44 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
21a00b0000 |
feat(silnik B): endpoint /houses + nocny przemiał; ε PRAWDZIWE zamiast średniego
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m36s
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 24s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 10s
build-swisseph / build (push) Successful in 18s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m37s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 16s
Testy / Kontrola składni wszystkich warstw (push) Successful in 9s
Etap 4, z jedną istotną zmianą planu i jednym znalezionym błędem. /houses W SILNIKU B Domyka kontrakt parzystości (LOG-28) po stronie domów — dotąd obejmował tylko pozycje obiektów, więc błąd w podziale na domy przechodził przez porównanie silników niezauważony. Nazwy systemów są NASZE (te same, co houses.SYSTEMS), więc wołający nie musi znać liter swissepha; rozjazd tych dwóch list oznaczałby, że parzystość przestała obejmować część systemów. Poza dziedziną (Placidus/Koch za kołem podbiegunowym) zwracamy 422 z powodem, a NIE podstawiamy po cichu innego systemu — cicha podmiana jest po stronie wołającego niewykrywalna, a to on ma zdecydować, co z tym zrobić. PRZEMIAŁ: NOCNE CI ZAMIAST CRONJOBA W KLASTRZE Plan zakładał Job w k3s, bo „duży przemiał jest kosztowny". Pomiar tego nie potwierdził: 500 000 przypadków × 13 systemów = 70 mln porównań w 64 sekundy, skalowanie liniowe (20k→2,8 s, 100k→12,3 s, 500k→64 s). Osobny obraz w rejestrze, manifest, CronJob i kopia harnessu poza repo byłyby infrastrukturą do problemu, którego nie ma — a kopia harnessu poza repo to ryzyko cichego rozjazdu z kodem, który ma testować. Workflow z harmonogramem daje to samo: co noc inne ziarno, więc dziedzina przeczesuje się z czasem gęściej niż pojedynczym przebiegiem. ε PRAWDZIWE — BŁĄD ZNALEZIONY PRZY OKAZJI Silnik liczył RAMC z GAST (czas gwiazdowy POZORNY, mierzony od równonocy PRAWDZIWEJ), ale parował go z ε ŚREDNIM, czyli bez nutacji. To nie wybór konwencji, tylko pomieszanie dwóch układów odniesienia. Skutek: do 3,2″ na cuspach domów oraz niespójne ε dla deklinacji i antyscji, liczonych z pozycji POZORNYCH. Teraz ε pochodzi z serii IAU 2000A — z tego samego źródła, którego Skyfield używa do GAST, więc oba są spójne z definicji. Framework wyroczni tego NIE MÓGŁ wykryć: z założenia podaje to samo ε obu stronom, żeby izolować samą funkcję domów. Błąd siedział w danych WEJŚCIOWYCH, nie w testowanej funkcji — i cały czas świecił na zielono. Wejście ma więc teraz własny sprawdzian, ze Skyfieldem jako niezależnym autorytetem (bez swissepha, więc działa w każdym środowisku). Luka opisana wprost w tests/oracle/README.md, bo poprzedni tekst twierdził, że ε jest testowane — nie było. Reszta ~3″ przy porównaniu „cały horoskop nasz vs swissepha" to UT1 kontra UTC: Skyfield konwertuje z tablic IERS, swisseph przyjmuje podany JD jako UT1 (dla 1984-04-30 różnica 0,181 s = 2,7″ RAMC — zgadza się co do trzeciego miejsca). Podanie swissephowi JD w UT1 kasuje ją do 0,00065″. Nasza strona jest dokładniejsza; niczego tu nie zmieniam. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4d1daab35a |
feat(domy): warianty od Barana i od MC + obrót kosmogramu — LOG-05 zamknięte
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m34s
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 10s
build / build (push) Successful in 26s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m37s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m33s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m27s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 17s
Testy / Kontrola składni wszystkich warstw (push) Successful in 10s
Ostatnie trzy pozycje z treści LOG-05, których wcześniej nie było: - whole_sign_aries — znaki jako domy, ale dom I ZAWSZE na 0° Barana, niezależnie od Ascendentu (tradycja indyjska i część szkół hellenistycznych), - equal_mc — równe domy zakotwiczone na MC: dom X zaczyna się dokładnie na południku, a nie ma go gdzieś w środku, - obrót kosmogramu: Ascendent albo 0° Barana po lewej stronie koła. Zmienia WYŁĄCZNIE rysunek, żadna liczba nie jest przeliczana. Wariant „od Barana" unieruchamia koło względem zodiaku, więc dwa horoskopy da się porównać na oko. Oba nowe systemy zgodne z wyrocznią co do zera od pierwszego uruchomienia. Razem 13 systemów: 2 833 424 porównania w przemiale, zero przekroczeń. PRZY OKAZJI — DWA BŁĘDY, KTÓRE SAM WPROWADZIŁEM I KTÓRYCH TESTY NIE WIDZIAŁY: - linia zbierająca ostrzeżenia o fallbacku trafiła do handlera strony głównej zamiast do compile_pdf: odwoływała się do nieistniejącej zmiennej, czyli 500 na stronie głównej, a do PDF-a ostrzeżenia nie docierały wcale, - compile_build używał parametru formularza, którego nie miał w sygnaturze. Oba przeszły przez komplet zielonych testów, bo żaden nie wywoływał POST-a — testy prezentacji sprawdzały teksty w szablonach i w main.py. Doszły więc testy uderzające w prawdziwe trasy (POST / i POST /compile ze stubowaną logiką), które łapią tę klasę błędu. Z tego samego powodu przepisane dwa testy PDF-a: greppowały z main.py dokładny kształt wywołania render(chart, theme="print") i pękały przy dopisaniu argumentu, mimo poprawnego zachowania. Teraz wołają trasę i sprawdzają, że KAŻDY z czterech rysunków dostaje motyw druku. LOG-05 i PRE-05 → Zrobione w docs/astrololo_wymagania.xlsx. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
aec3f84331 |
feat(domy): topocentric zgodny co do zera — wybór gałęzi liczony, nie zgadywany
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m29s
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 9s
build-render / build (push) Successful in 5m34s
build / build (push) Successful in 39s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m46s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m31s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m27s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 19s
Testy / Kontrola składni wszystkich warstw (push) Successful in 11s
Topocentric był wycofany z powodu rozjazdu przy |φ| ≈ 89,9°. Ta diagnoza była BŁĘDNA: opierała się wyłącznie na zestawie brzegowym, który próbkuje tylko wybrane szerokości. Przemiał losowy pokazał prawdziwą skalę — błędy od ~70° w górę, do 50% przypadków blisko biegunów, 6,5% całości. Nie dwa przypadki brzegowe. Przyczyną nie była jednak konstrukcja, tylko wybór gałęzi: dwa koła wielkie przecinają się w dwóch punktach antypodycznych. Kolejno zawiodły reguły „po której stronie MC", „w łuku kwadrantu", „wschodnia połowa horyzontu" i śledzenie ciągłości krokami (to ostatnie maskuje własną patologię — po korekcie do bliższej gałęzi zmierzony skok ZAWSZE wychodzi ≤ 90°, więc detektor nigdy się nie zapala). Wszystkie te reguły rozstrzygają lokalnie, a przy dużych szerokościach kolejność domów potrafi się odwrócić: przy φ = −79,55° MC wypada na 306,8°, a dom 11 na 291,4°. To jest poprawne — wyrocznia zwraca to samo. Rozwiązanie: nie wybierać w ogóle. Iloczyn wektorowy zenitu z biegunem ekliptyki jest ciągłą funkcją parametru rodziny i sam niesie właściwy zwrot; dwuznaczność wprowadza dopiero atan2. Zostajemy w wektorach, znak ustalamy raz — kotwicząc rodzinę na MC górującym. Wynik: 0,000000000° na 240 000 porównań, cała dziedzina, bez iteracji i bez zawężania szerokości. Żadna granica dziedziny nie jest tu potrzebna, więc żadnej nie udajemy — test pilnuje, że topocentric liczy się wszędzie i nie fallbackuje. Morał do frameworka: zestaw brzegowy mówi, CZY system się psuje; dopiero przemiał losowy mówi JAK BARDZO. Wniosek o skali wyciągnięty z samych brzegów był tu zaniżony o trzy rzędy wielkości. Odnotowane w tests/oracle/README.md. 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> |
||
|
|
548d9301f3 |
fix(domy): przepnij build_chart na cusps_for — inaczej nowe systemy dają 500
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 20s
Testy / Kontrola składni wszystkich warstw (push) Successful in 9s
Rozszerzenie houses.SYSTEMS do ośmiu pozycji odblokowało w chart.py filtr `house_system in H.SYSTEMS`, ale liczenie zostało na H.cusps(), które zna wyłącznie trzy systemy dzielące ekliptykę i dla pozostałych rzuca ValueError. Wybranie campanusa przechodziło więc walidację i dopiero potem wywalało 500. Test parametryzowany po H.SYSTEMS zamyka tę klasę błędu na przyszłość: każdy system ogłoszony na liście musi przejść przez build_chart, więc dopisanie nazwy bez przepięcia liczenia od razu zapali się na czerwono. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
1be57a47d8 |
feat(domy): osiem systemów potwierdzonych co do zera wobec wyroczni
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m31s
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 17s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 20s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m3s
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 18s
Testy / Kontrola składni wszystkich warstw (push) Successful in 9s
Etap 1: systemy o zamkniętym wzorze. Dochodzą vehlow, morinus, regiomontanus, campanus i alcabitus — każdy zgodny ze Swiss Ephemeris z maksymalnym odchyleniem 0,000000000° na 240 000 porównań (zestaw brzegowy + przemiał 20 000 losowych). Cuspy pośrednie liczone wektorowo: koło domu to przecięcie płaszczyzny (wyznaczonej iloczynem wektorowym normalnych) z ekliptyką. Dwa punkty przecięcia wymagają wyboru gałęzi — rozstrzygany stroną względem MC, przy czym cztery osie bierzemy z dokładnych wzorów, bo przy przesunięciu równym 0° albo 180° test strony jest numerycznie niestabilny. Dwie rzeczy, które wyszły dopiero z porównania z wyrocznią: - swisseph zamienia MC z IC dla systemów opartych na horyzoncie, gdy punkt kulminujący jest pod horyzontem (za kołem podbiegunowym) — stąd _culminating_mc, - morinus wymaga bezpośredniej zamiany współrzędnych, nie rzutu po kole godzinnym. Topocentric (Polich–Page) zaimplementowany, ale świadomie POZA houses.SYSTEMS: rozjeżdża się z wyrocznią przy |φ| ≈ 89,9° i RAMC 90°/270°, gdzie kolejność domów się odwraca. Powód jest rzeczywisty, nie numeryczny — jego „biegun" atan(tan(89,9°)/3) to już 89,7°. Zawężenie dziedziny tylko po to, żeby test przeszedł, byłoby dopasowaniem kryterium do wyniku. Testy regresji w suicie logiki działają bez swissepha: antypodyczność domów przeciwległych, zakotwiczenie kwadrantowych na Ascendencie, niezależność morinusa od szerokości, odrzucanie nieznanej nazwy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
86a0f16f9e |
test: framework porównania domów z wyrocznią + DWA błędy, które od razu wykrył
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m29s
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) Failing after 14s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 19s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m29s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 13s
Testy / Kontrola składni wszystkich warstw (push) Successful in 8s
Etap 0 planu egzotycznych systemów domów: zanim zaczniemy implementować Placidusa i spółkę, potrzebujemy narzędzia, które powie, czy wynik jest poprawny. Błąd w domach jest CICHY — wykres wygląda dobrze, tylko planety siedzą w złych domach. FRAMEWORK (tests/oracle): liczenie cuspów jako funkcja (RAMC, ε, φ), Swiss Ephemeris jako wyrocznia. Trzy decyzje projektowe, które okazały się kluczowe: - IZOLACJA: obu implementacjom podajemy TE SAME wejścia przez swe_houses_armc. Porównywanie „naszego horoskopu" z „horoskopem swissepha" mieszałoby różnice czasu gwiazdowego i ε z błędami domów — utonęlibyśmy w fałszywych alarmach. Czas gwiazdowy i ε mają własny test. - KRYTERIUM to liczba przypadków powyżej tolerancji (1″), max odchylenie I MIEJSCE, a nie procent zgodności. Procent ukrywa kształt błędu: „97%" nie odróżnia szumu zmiennoprzecinkowego od rogu dziedziny, w którym mylimy się o 30°. - GRANICE PER DATA: koło podbiegunowe nie jest stałą 66,56° — zależy od ε, które zmienia się z datą (23,75° w 370 p.n.e.), więc przesuwa się o ~0,3°. Uruchomiony na kodzie uchodzącym za poprawny, w PIERWSZYM przebiegu znalazł dwa realne błędy: 1. ASCENDENT O 180° ZA KOŁEM PODBIEGUNOWYM. `atan2` wybierał niewłaściwy punkt przecięcia ekliptyki z horyzontem — zwracaliśmy Descendent. Planety lądowały w PRZECIWNYCH domach dla całej północnej Skandynawii (Tromsø, Rovaniemi, Murmańsk), na ~11% przypadków przy tych szerokościach. Rozstrzyga położenie względem MC: punkt wschodzący leży w półkolu (0°,180°) na wschód od MC. 2. NIEDETERMINIZM WHOLE SIGN NA GRANICY ZNAKU. Ascendent o włos od granicy (359,999999999976 vs 1e-10 — ta sama wartość, różne strony) przerzucał dom I o 30°. Ten sam horoskop na innej maszynie dawał inny wynik. Przyciąganie do granicy przy 1e-9° (3,6 mikrosekundy łuku — poniżej realnej dokładności danych). Oba mają testy regresji w zwykłej suicie, więc są łapane też bez swissepha. Po poprawkach: build 0 przekroczeń, sweep 20 000 przypadków = 760 000 porównań, max odchylenie 0.000000000°. Istniejące suity bez regresji (logika 277+3, prez. 249). CI: krok BLOKUJĄCY w jobie swisseph-image, odpalany wewnątrz obrazu silnika B z zamontowaną warstwą logiczną. pyswisseph zostaje wyłącznie wyrocznią testową — nie wchodzi do zależności produktu, izolacja z LOG-27 nienaruszona. Dodane `cusps_for(ramc, eps, lat, system)` — kanoniczne wejście, w które Etap 1 będzie tylko dopisywał kolejne systemy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
4c1e7f8808 |
feat: przegląd baz na udziale + globalne włączanie/wyłączanie (DAN-15/PRE-09)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m29s
Testy / Testy warstwy bazodanowej (ochrona baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 12s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 40s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m3s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m35s
Testy / Testy warstwy bazodanowej (ochrona baz) (push) Successful in 9m29s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 14s
Testy / Kontrola składni wszystkich warstw (push) Successful in 10s
Wymaganie przedefiniowane pod model serwerowy (#47): nie wybiera się folderu — pliki leżą na stałym NFS. Potrzeba za to WIDZIEĆ, jakie bazy są dostępne i móc zdecydować, które biorą udział w interpretacji. Warstwa danych: `bases.py` (lista plików + metaopis: nazwa, ścieżka, rozmiar, data, stan) i endpoint `/bases`. Wyłączone bazy są ODSIEWANE z kandydatów przy wyszukiwaniu, więc naprawdę nie biorą udziału w interpretacji — nie tylko znikają z listy. Lista wyłączonych wchodzi do klucza cache zapytań: bez tego zmiana ustawień oddawałaby wynik sprzed zmiany, czyli treść bazy uznanej za wyłączoną. `list_bases()` doszło do interfejsu dostawcy jako OPCJONALNE (SQL nie operuje na plikach → pusto, zamiast wywrotki). Przelot logika → prezentacja i ekran „Ustawienia" z tabelą baz. Przez łącze idą SAME METADANE — podgląd listy nie jest kolejną drogą do wyniesienia treści. Stan przełączników jest DEKLARATYWNY (`DISABLED_BASES`), nie klikalny — i to jest świadome: udział z bazami montujemy read-only, a katalog cache to `emptyDir`, więc zapisany przełącznik ginąłby przy restarcie poda i po cichu włączał z powrotem wyłączoną bazę. Ekran mówi wprost, jak wyłączyć bazę i dlaczego nie klikaniem. Tryb klikalny wymagałby dołożenia trwałego wolumenu. Weryfikacja na żywym łańcuchu: `/bases` przechodzi przez SZYFROWANE łącze (logic→data), pokazuje 3 bazy z metaopisem i stanem; wyszukiwanie daje 3 → 2 → 0 wierszy w miarę wyłączania baz. Testy: dane +6, prezentacja +6. Dane 13, logika 277, prezentacja 249. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
7b435d4263 |
feat: synastria — aspekty między dwoma horoskopami (PRE-04)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m32s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 11s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 9s
build / build (push) Successful in 25s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m18s
Testy / Kontrola składni wszystkich warstw (push) Successful in 31s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 13m6s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Failing after 13m25s
Pierwsza technika relacyjna z pełnym UI (Returns były już w kalendarzu od LOG-12). Dwie osoby → aspekty MIĘDZY ich horoskopami (planeta osoby A do planety osoby B). Silnik: `find_cross_aspects(a, b, orb, luminary_bonus, minor)` — każdy obiekt A × każdy obiekt B. `obj1` = osoba A, `obj2` = osoba B. Statyczne (dwa natale, brak wspólnego czasu) → bez applying/separating. Par sztywnych (NN/SN) NIE wycinamy — między dwiema osobami to realny aspekt, nie artefakt definicji. Wspólny matcher `_first_aspect` (z find_aspects), więc orb/bonus/aspekty poboczne działają tak samo. Endpoint `POST /chart/synastry` (dwie osoby + zodiak + ustawienia aspektów) → pozycje obu + siatka aspektów z glifami. Prezentacja: zakładka „Synastria", formularz dwóch osób (pętla po a_/b_), tabela aspektów A · aspekt · B · orb. Weryfikacja na żywym API: 13+13 obiektów, 63 aspekty synastryczne z poprawnymi glifami i bonusem świateł (A.Sun ☌ B.Venus przy orbie 8.67 = 8+2). Testy: logika +4 (cross-aspekty, kolejność A/B, brak filtra par sztywnych, brak applying), prezentacja +7 (trasa, formularz dwóch osób, klient, tabela). Logika 277, prezentacja 228. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b36b3bee19 |
feat: konfigurowalne aspekty i orby (PRE-06)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m47s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m27s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 12s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 9s
build / build (push) Successful in 26s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m30s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m28s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 12s
Testy / Kontrola składni wszystkich warstw (push) Successful in 8s
Dotąd orb (8°) i aspekty były zaszyte w silniku. Astrolodzy pracują na różnych orbach i lubią dokładać aspekty poboczne — teraz da się to ustawić w UI. Silnik (aspects.py): `find_aspects` przyjmuje orb, luminary_bonus i `minor`. Aspekty poboczne = tylko trzy (półsekstyl 30° / półkwadratura 45° / kwinkunks 150°) — bo mają już glify i barwy w prezentacji i w engine/glyphs.py, więc dokładają się bez ruszania czegokolwiek poza silnikiem. Bazy zwykle ich nie opisują (brak tokenu), więc trafiają na kosmogram i do tabeli, ale NIE tworzą faset — most sygnifikatorów po cichu je pomija (skip przy braku tokenu). Plumbing przez wszystkie warstwy: request logiki, build_chart, klient prezentacji, oba handlery (/, /compile) ORAZ PDF (/compile/pdf). Ustawienia wędrują między zakładkami (formsync) i lecą do PDF-a (compile.js) — żeby podsumowanie liczyło aspekty tym samym orbem co horoskop (ta sama zasada co fix podsumowania #46). UI: orb, bonus dla świateł, checkbox „aspekty poboczne" na obu formularzach. Weryfikacja na żywym /chart/positions: domyślnie 24 aspekty (główne); minor → 52 (dochodzą quincunx/semisextile/semisquare); orb 3 → 13, orb 12 → 32. Testy: logika +3 (minor/orb/bonus), prezentacja +6 (obecność pól, przekazanie przez warstwy, sync, PDF). Logika 273, prezentacja 220. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9b1e4dbb20 |
feat: wiele systemów domów naraz — porównanie obok siebie (PRE-05/LOG-05, A2a)
build / build (push) Successful in 1m3s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m7s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m55s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 36s
Testy / Kontrola składni wszystkich warstw (push) Successful in 25s
Astrolodzy spierają się o systemy domów; teraz można policzyć kilka na raz i zobaczyć, jak różny podział przesuwa planety między domami. Domy to geometria z Asc/MC — osie są WSPÓLNE, różni się tylko podział. Prymarny system zostaje w `cusps`/`house_system`/`positions[].house` (pod kosmogram i wstecznie — nic się nie zmienia dla dotychczasowych ścieżek). Nowość: - logika: `build_chart(..., house_systems=[...])` → `result["house_systems"]` = pełen zestaw (prymarny pierwszy, bez duplikatów), a `positions[].houses[system]` mówi, w którym domu obiekt siedzi wg każdego systemu. Doklejane tylko gdy > 1. Nieznany system (np. placidus — dojdzie przez swisseph osobno, A2b) pomijany, nie wywala horoskopu. - endpoint `/chart/positions`: pole `house_systems`; klient prezentacji przekazuje. - UI: checkboxy „Porównaj systemy domów" (whole sign / equal / porphyry) + tabela kusp obok siebie (12 domów × systemy), stan zaznaczeń przeżywa submit. Na razie 3 systemy z czystej matmy (`houses.py`) — zero zależności, zero walidacji krzyżowej. Egzotyczne (Placidus/Koch/Regiomontanus/Campanus) dojdą przez endpoint `/houses` w silniku B (swisseph) jako A2b — maszyneria „naraz" jest już gotowa, egzotyczne tylko dopiszą kolejne wpisy. Weryfikacja: żywy /chart/positions — prymarny whole_sign, house_systems [whole_sign, equal, porphyry], 12 kusp/system, dom per system per obiekt. Testy: logika +5, prezentacja +6. Logika 270, prezentacja 179. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
15964dd0df |
chore: wymuszenie nowego obrazu data/logic/presentation po incydencie z :latest
build / build (push) Successful in 1m16s
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m11s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m40s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 30s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 20s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m38s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m38s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 26s
Testy / Kontrola składni wszystkich warstw (push) Successful in 21s
Komentarz-marker w main.py każdej z trzech usług — zmienia zawartość obrazu, więc build.yaml wyprodukuje NOWE SHA-tagi z nowszym `created`. To odblokowuje image-updatera (strategia newest-build), który utknął: wszystkie trzy usługi mają w deployu tag `:latest`, którego build.yaml nigdy nie pcha (tylko SHA), więc nowe pody wpadły w ImagePullBackOff. Nowy build z realnym SHA da updaterowi co promować i przykryje `:latest` w kustomization — bez ręcznej zmiany w repo deploy. UWAGA: samo to NIE wystarczy. W namespace astrololo zniknął pull-secret `gitea-registry`, więc nawet z poprawnym tagiem nowe pody nie pobiorą obrazu. Trzeba go odtworzyć (kopia działającego `gitea-registry-creds` z ns argocd) — osobna, ręczna operacja, poza tym commitem. 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>
|
||
|
|
1d7f3e2136 |
feat(prezentacja): szkielet kosmogramu — koło horoskopowe SVG (PRE-12)
build / build (push) Successful in 1m26s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m10s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m55s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 38s
Testy / Kontrola składni wszystkich warstw (push) Successful in 25s
Pierwszy krok rysowania wykresu (PRE-12): SZKIELET koła — pierścień znaków, podział na domy i osie. Planety i linie aspektów w kolejnych iteracjach. Rysowane po stronie serwera jako czysty string SVG (bez zależności zewnętrznych — spójne z CSP). Ciemny motyw, spójny z paletą aplikacji (kolory z --line, --accent, --muted; glify znaków barwione wg żywiołu w stonowanych kolorach czytelnych na ciemnym tle). Geometria wg konwencji astrologicznej: Ascendent po LEWEJ, długość ekliptyczna rośnie przeciwnie do ruchu wskazówek zegara. Punkt λ → kąt φ = 180° − (λ − Asc); w SVG y rośnie w dół, co formuła uwzględnia. Zakotwiczenie sprawdzone testami liczbowo: Asc po lewej, Dsc po prawej, oś pozioma; Asc+90° (II dom) na dole. Elementy: dwa okręgi + piasta, podziałki co 5°/10°, granice znaków co 30° z glifem w środku sektora, szprychy domów od pasa do piasty, numery domów w środku każdego domu, osie Asc–Dsc i MC–IC wyróżnione akcentem z etykietami AC/DC/MC/IC. Dane bierzemy WYŁĄCZNIE z wyniku /chart/positions — prezentacja nic nie liczy: - `sign_glyphs` (pierścień 12 znaków) i glify — z LOG-22, - `angles` z długością `decimal` — już były, - `cusps` z `decimal` — DOŁOŻONE w tym PR (jedna linia w build_chart). Bez tego domy dało się narysować tylko dla whole sign; z długością cuspu działa dla KAŻDEGO systemu. Zweryfikowane na porphyry: cuspy poza wielokrotnościami 30°, szprychy odchodzą od granic znaków. Degradacja: silnik bez osi/domów albo starszy wynik bez `decimal` w cuspach → brak koła (pusty string), nie wyjątek. Testy: 8 (poprawność XML, 12 glifów, 4 osie, numery domów, Asc po lewej liczbowo, CCW, degradacja). Całość: prezentacja 33 passed, logika 265 / 1 skipped. Render potwierdzony wizualnie na horoskopie referencyjnym (AC=Leo po lewej, MC=Aries u góry, domy CCW). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
ace76183e5 |
feat(logic): glify astrologiczne — konwersja tekst↔symbol (LOG-22)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m55s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m43s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 37s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 21s
build / build (push) Successful in 1m22s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m12s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m39s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 33s
Testy / Kontrola składni wszystkich warstw (push) Successful in 24s
Warunek wstępny pod kosmogram (PRE-12): planety i znaki na kole rysujemy symbolami. Nowy moduł engine/glyphs.py: - forward: nazwa → glif (planety, punkty, Loty, znaki, aspekty, retro ℞), - reverse: glif → nazwa (znosi obecność/brak selektora wariantu), - glyphify(): tokeny [XX z bazy → glify; przyklad z wymagan „[Sa [Pis 26°08' [conj [PF" → „♄ ♓ 26°08' ☌ ⊗" (stopnie nietkniete). DAN-18 „tylko tekst, nigdy emoji" potraktowane serio, TRZEMA warstwami — bo sam selektor NIE wystarcza (potwierdzone wizualnie w przegladarce): 1. w danych: selektor wariantu tekstowego U+FE0E na znakach zodiaku oraz ♀/♂ (maja wariant emoji); ☉ i reszta go nie dostaja (zbedny), 2. CSS font-variant-emoji:text, 3. CSS font-family celujacy w MONOCHROMATYCZNE fonty symboli PRZED emoji. Bez pkt. 3 macOS/Chromium i tak renderowal znaki ♈–♓ jako kolorowe kafelki Apple Color Emoji mimo VS15 — planety wychodzily tekstem, znaki nie. Stack „Apple Symbols / Segoe UI Symbol / Noto Sans Symbols2" naprawia render. NIGDZIE nie emitujemy U+FE0F (emoji) — pilnuje tego test. Wpiete w build_chart: kazda pozycja dostaje glyph (planeta) + sign_glyph (znak, zalezny od zodiaku, wiec po przesunieciu), osie i Loty tak samo (Fortuna ⊗, reszta Lotow bez standardowego symbolu → None), aspekty dostaja glif, result[„sign_glyphs"] to pierscien 12 znakow pod kolo. UI: kolumna „Sym." w tabeli pozycji (planeta + znak) i symbol przy aspekcie. Testy: 14 (kompletnosc — kazdy obiekt/znak/aspekt ma glif; dwukierunkowosc; DAN-18 brak FE0F, znaki maja VS15, ☉ nie; przyklad glyphify z wymagan). Calosc: logika 265 passed / 1 skipped, prezentacja 25. Render znakow potwierdzony wizualnie (czarno-biale symbole, nie emoji). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f1956a08ff |
feat(logic): aspekty pozazodiakalne — antyscja i paralele deklinacji (LOG-07)
build / build (push) Successful in 1m1s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m57s
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 24s
Aspekty głowne (LOG-06) mierzą kąt wzdłuż ekliptyki. LOG-07 dokłada dwa rodzaje powiązań, które klasyczna astrologia liczy naprawdę, nie na oko: - PARALELA/KONTRPARALELA DEKLINACJI — dwa ciała na tej samej („parallel") lub przeciwnej („contraparallel") deklinacji działają jak koniunkcja/opozycja, mimo że wzdłuż ekliptyki mogą stać gdziekolwiek. Deklinacja liczona PEŁNYM wzorem (z szerokością ekliptyczną — istotne dla Księżyca i planet schodzących z ekliptyki), przez to_equatorial z LOG-04. Orb konfigurowalny (domyślnie 1°, ciasno — to kontakty punktowe). - ANTYSCJA/KONTRANTYSCJA — odbicie długości względem osi przesileń (0° Raka – 0° Koziorożca) albo równonocy (0° Barana – 0° Wagi). Liczone na współrzędnych TROPIKALNYCH of-date, bo deklinacja jest fizyczna (równikowa, niezależna od zodiaku), a antyscja z definicji tropikalna — jej oś to kardynalne punkty zodiaku tropikalnego. Dlatego PRZED przesunięciem na zodiak syderyczny/draconiczny. Dodatkowo: flaga „out of bounds" (|deklinacja| > nachylenie ekliptyki — ciało poza zakresem Słońca) i kolumna deklinacji przy każdej pozycji. Integracja z bazą: baza interpretacyjna ZNA paralele pod frazą „P. Dec.", więc generujemy fasetkę paraleli (trafia też do promptu LLM). PUŁAPKA: samo „Dec." w bazie to często DEKANAT („3rd Dec. of [Gem"), więc szukamy dokładnie „P. Dec." — inaczej sypnęłoby fałszywymi trafieniami. Kontrparaleli i antyscji baza nie opisuje osobnym znacznikiem, więc zostają obliczeniem display-only. Pary z RIGID_PAIRS (węzły) odsiane: SN = NN+180° na ekliptyce → deklinacja ZAWSZE przeciwna, czyli definicyjna kontrparalela bez informacji. Walidacja wobec faktów NIEZALEŻNYCH od kodu: - deklinacja Słońca 30.04.1984 = +14.88° wobec ~+14.9° z almanachu, - antyscja to arytmetyka odbicia: inwolucja i pary znaków (Rak↔Bliźnięta, Baran↔Panna) sprawdzone na piechotę, - węzły faktycznie mają przeciwną deklinację i są odsiane, - deklinacja niezależna od zodiaku (tropikalny == syderyczny co do 1e-6°), - realna baza: mechanizm paraleli znajduje wpisy „P. Dec." i odsiewa dekanaty (z 33 wpisów „P. Dec." 5 ma niepusty efekt — głównie „[conj or P. Dec."). UI: kolumna deklinacji (+znacznik OOB), tabela paraleli/kontrparaleli i tabela antyscji na ekranie Horoskop. Testy: 15 nowych (out_of_zodiac) + 2 (fasetka paraleli vs pułapka dekanatu). Całość: logika 251 passed / 1 skipped, prezentacja 25 passed. Render szablonu sprawdzony osobno (bez błędu Jinja, wszystkie sekcje obecne). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
56fdf01d7d |
feat(bezpieczenstwo): szyfrowanie lacz miedzy warstwami AES-256-GCM (PRE-16)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m45s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m31s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 31s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 15s
build / build (push) Successful in 4m15s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m41s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m36s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 33s
Testy / Kontrola składni wszystkich warstw (push) Successful in 15s
Warstwy rozmawialy ze soba jawnym tekstem wewnatrz klastra. Token miedzywarstwowy (LOG-32) mowil KTO pyta, ale nie ukrywal CZEGO dotyczy odpowiedz — a plyna nia surowe wiersze oryginalnych baz interpretacyjnych, czyli rdzen produktu. Kto podsluchal ruch wewnatrz sieci (drugi pod, mirror portu na switchu, zrzut z wezla), mial je w calosci. Nowy modul link_crypto (kopia w kazdej z trzech uslug — nie maja wspolnej biblioteki; test pilnuje, ze kopie sa identyczne): - AES-256-GCM na ciele kazdego zadania i odpowiedzi. GCM daje poufnosc I uwierzytelnienie naraz, wiec nie ma wariantu „zaszyfrowane, ale podatne na modyfikacje". - DWA niezalezne klucze, po jednym na pare rozmowcow (prezentacja-logika, logika-dane). Przejecie klucza prezentacji nie otwiera warstwy danych, gdzie leza cale bazy. Z kazdego klucza lacza HKDF wyprowadza osobne podklucze na kierunek, wiec zadanie i odpowiedz nigdy nie szyfruja sie tym samym kluczem. - Do materialu uwierzytelnianego (AAD) wchodza kierunek, sciezka, znacznik czasu i numer ramki — wiec ramki nie da sie przekleic na inny endpoint, odtworzyc po czasie (okno MAX_SKEW) ani przestawic w strumieniu. - Strona serwerowa to czyste ASGI: podmienia cialo zanim zobaczy je FastAPI i przepuszcza odpowiedz strumieniowa kawalek po kawalku (okno postepu dziala dalej). Fail-closed: przy ustawionym kluczu jawne zadanie dostaje odmowe. Strumien postepu (okno pisania horoskopu) tez idzie przez szyfrowane lacze: link_crypto.stream_lines() pieczetuje zadanie i odszyfrowuje odpowiedz ramka po ramce (granice ramek != granice linii NDJSON), zachowujac dostarczanie na zywo. Bez tego przy wlaczonym LINK_ENCRYPTION_REQUIRED serwer odrzucalby strumien (400) i okno postepu przestaloby dzialac. Fail-closed obejmuje takze strumien: klient bez klucza nie wysyla nic, zamiast puscic dane urodzenia jawnym tekstem, zanim serwer zdazy odmowic. Najgrozniejszy blad wyszedl z PODSLUCHU prawdziwego gniazda, nie z testow: klient bez klucza wysylal pytanie jawnym tekstem, ZANIM serwer zdazyl odmowic. Stad LINK_ENCRYPTION_REQUIRED: klient nie wysyla niczego, a usluga nie wstaje, jesli klucza brak. Ta sama zasada co przy sekrecie logowania. Klient prezentacji przepuszczony przez jeden punkt _post()/stream_lines: dopoki kazda metoda skladala zadanie sama, dolozenie nowej znaczylo, ze latwo zapomniec o tokenie albo kluczu (401 wyszedl juz raz dopiero na produkcji). Test strukturalny: kazde wyjscie w dol musi miec i token, i klucz lacza (takze strumien), a surowe httpx wolno tylko na sciezkach wyjetych spod szyfrowania. Weryfikacja: - testy link_crypto (round-trip, brak tresci baz w bajtach na sieci, odrzucenie obcego klucza / przestawionego bitu / przekleconej sciezki / przestawionej ramki / przeterminowanej koperty / urwanego strumienia; round-trip strumienia i fail-closed klienta i serwera dla strumienia), - e2e na prawdziwym uvicornie z proxy zrzucajacym gniazdo: tresci baz brak na kablu w obie strony (grep=0), takze dla strumienia horoskopu; klucz jednej pary nie otwiera drugiej, - calosc: logika 234 passed / 1 skipped, prezentacja 25 passed. docs/wdrozenie-pre16.md: instrukcja krok po kroku z uzasadnieniem kolejnosci. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
473d059a6a |
feat(logic): tabele pomocnicze horoskopu (LOG-23)
build / build (push) Successful in 1m8s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m2s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m43s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 34s
Testy / Kontrola składni wszystkich warstw (push) Successful in 22s
Komplet wyliczen, ktore astrolog czyta „obok" pozycji: - bilans zywiolow i jakosci w czterech wariantach (7 klasycznych / 10 z nowozytnymi, z Ascendentem i bez) + wykrywanie BRAKUJACYCH zywiolow — klasyczne „no air", podstawa pod scoring sily (LOG-21), - faza Ksiezyca: elongacja, nazwa fazy, procent oswietlenia, przybywa/ubywa, - stopnie krytyczne wg jakosci znaku (kardynalne 0/13/26, stale 8/21, zmienne 4/17) + 29 stopien anaretyczny i 0 stopni wejscia w znak, - dzien i godziny planetarne w porzadku chaldejskim, - syzygia prenatalna (ostatni now albo pelnia przed urodzeniem), - podzialy: dwunastniki (D12) i nawamsa (D9). Dwie rzeczy wymagaly prawdziwego liczenia, nie tabelki: * godziny planetarne sa NIEROWNE — dzien od wschodu do zachodu dzieli sie na 12, noc osobno. Bez faktycznego wschodu/zachodu wynik bylby zmyslony, wiec szukamy ich numerycznie (przejscie wysokosci Slonca przez -0°50', bisekcja jak przy stacjach z LOG-03). Doba planetarna startuje o WSCHODZIE, nie o polnocy. * syzygia prenatalna — szukanie wstecz przejscia elongacji przez 0/180 stopni. Walidacja wobec faktow NIEZALEZNYCH od naszego kodu: - 30.04.1984 to poniedzialek -> wladca dnia Ksiezyc; 5. godzina poniedzialku w porzadku chaldejskim to Slonce (Mo, Sa, Ju, Ma, Su) — zgadza sie, - wschod/zachod dla Krakowa: 03:18 / 17:57 UTC = 5:18 / 19:57 lokalnie — zgodne z rzeczywistoscia dla konca kwietnia, - syzygia: pelnia 15.04.1984 19:10:45 UTC; rzeczywista byla 19:11 — roznica ponizej minuty, - bilans przeliczony recznie: Ogien 4, Ziemia 4, Woda 3, Powietrze 0. UI: checkbox „tabele dodatkowe" na ekranie Horoskop (opt-in, bo szuka numerycznie) i sekcja wynikow. Endpoint: /chart/positions?tables=true. Testy: 28 nowych (w tym noc polarna -> brak godzin planetarnych, oraz sprawdzenie, ze w znalezionej syzygii elongacja FAKTYCZNIE wynosi 0/180). Calosc: 202 passed / 1 skipped + 17 (prezentacja). Zweryfikowane e2e w UI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
114b7eebdf |
feat(ui): okno postepu z logiem podczas pisania horoskopu
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m21s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m50s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 34s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 21s
build / build (push) Successful in 1m49s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m20s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 10m0s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 37s
Testy / Kontrola składni wszystkich warstw (push) Successful in 25s
Generowanie trwa minutami, a zwykly POST nie dawal zadnego sygnalu — aplikacja wygladala na zawieszona. Teraz w trakcie pracy pojawia sie okno z logiem, zegarem i spinnerem. Log pokazuje RZECZYWISTE zdarzenia z serwera, nie udawany pasek postepu: - app/progress.py — strumien NDJSON; praca leci w watku roboczym, generator odpompowuje kolejke, wiec zdarzenia docz w TRAKCIE pracy, nie na koncu; heartbeat co 10s, zeby proxy nie uznalo polaczenia za martwe, - providers.generate(..., on_event) — raportuje kazda ture (start, czas trwania, liczba znakow, czy urwana), bo to tura trwa, - POST /chart/horoscope/stream w logice + proxy /horoscope/stream w prezentacji. Wynik: ostatnie zdarzenie niesie GOTOWY HTML wyrenderowany z tego samego szablonu, ktory renderuje przeladowanie strony (_prompt_result.html wydzielony z _prompt_block.html). Jedno zrodlo prawdy dla wygladu wyniku — okno wstawia go bez przeladowania. Degradacja: bez strumieniowania w przegladarce formularz idzie klasycznie i wszystko dziala jak wczesniej, tylko bez okna. Blad polaczenia konczy sie komunikatem w logu, nie cisza. BLAD ZNALEZIONY PRZY TESCIE NA ZYWO: petla kontynuacji odejmowala od budzetu ZAMOWIONY limit tury zamiast tokenow faktycznie wyprodukowanych — pierwsza tura zjadala caly budzet, wiec urwana odpowiedz nigdy nie doczekala sie dokonczenia i wracala do uzytkownika jako calosc. Naprawione i pokryte testem regresyjnym. Testy: 176 passed / 1 skipped (logika) + 17 (prezentacja). Zweryfikowane na zywo z wolna atrapa modelu: zdarzenia z poprawnymi czasami, okno z 11 liniami logu, wynik wstawiony bez przeladowania strony. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
163ace4283 |
feat(ui): interaktywny wybor modelu u dostawcy
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 11m14s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 10m19s
Testy / Build obrazu silnika B (swisseph) (pull_request) Successful in 46s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 27s
build / build (push) Successful in 1m18s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m45s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 10m2s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 36s
Testy / Kontrola składni wszystkich warstw (push) Successful in 23s
Uzytkownik wybiera nie tylko dostawce, ale konkretny model — Fable czy Opus u Anthropica, gpt-4o-mini czy gpt-5 u OpenAI, cokolwiek ma pobrane lokalnie. - app/llm/catalog.py: podpowiedzi modeli per dostawca wraz z oknem kontekstu, nadpisywalne przez <DOSTAWCA>_MODELS; GET /llm/models wystawia je dla UI. - Pole modelu w UI jest TEKSTOWE z datalista, nie zamknietym <select> — konto moze miec dostep do modeli, o ktorych kod nie wie, a nowe wychodza szybciej, niz aktualizuje sie katalog. Puste pole = model domyslny dostawcy. - static/models.js: zmiana dostawcy przelacza podpowiedzi, podmienia placeholder na model domyslny i pokazuje okno kontekstu wybranego modelu. - build_provider(name, model) — model z zadania wygrywa nad konfiguracja. WAZNE (znalezione przy tescie e2e): liczenie budzetu „maksymalny kontekst modelu" szlo przez build_provider(), ktory WYMAGA klucza API — bez klucza budzet cicho spadal do wartosci zapasowej i byl identyczny dla wszystkich modeli Anthropic. Budzet zalezy wylacznie od okna kontekstu, wiec doszlo resolve_model(), ktore rozwiazuje nazwe modelu bez budowania dostawcy. Teraz budzet realnie sie rozni: Opus/Fable 3,48 mln znakow, Haiku 536 tys., gpt-4o-mini 438 tys., llama3.1 8 tys. Pewnosc danych w katalogu: modele Anthropic pochodza z oficjalnej dokumentacji API (okna i limity zgodne z limits.py); modele OpenAI to podpowiedzi, ktorych nie weryfikowalem; lokalne zaleza od tego, co masz pobrane. Testy: 174 passed / 1 skipped (logika) + 17 (prezentacja). Nowy test strukturalny pilnuje, ze KAZDE wywolanie w dol niesie wybrany model i dostawce — dokladnie ta klasa bledu zlapala brakujacy parametr przy horoskopie okresowym. Zweryfikowane w przegladarce: przelaczanie dostawcy podmienia liste modeli. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f33cdc88f4 |
feat(llm): horoskop powstaje zawsze — kontynuacja, okna kontekstu, budzet max
PRZYCZYNA PUSTYCH ODPOWIEDZI NA ANTHROPICU (potwierdzona w dokumentacji API): domyslnym modelem byl `claude-sonnet-5`, ktory przy POMINIETYM parametrze `thinking` wlacza myslenie adaptacyjne, a `thinking.display` domyslnie jest "omitted". Tokeny myslenia licza sie do max_tokens, wiec przy LLM_MAX_TOKENS=2000 cala tura wychodzila jako bloki `thinking` z pustym tekstem — parser filtrowal type=="text" i zwracal pusty string. Opus 4.8 bez `thinking` nie mysli, wiec tam objaw by nie wystapil. Gwarancja niepustej odpowiedzi (wszyscy trzej dostawcy): - generate() to teraz PETLA, nie pojedynczy strzal: tura -> jesli urwana na limicie, dopisz ture „kontynuuj" w tej samej rozmowie i sklej tekst, - tura zlozona z samego myslenia traktowana jak urwana (nie jak pustka), - pusta i NIE urwana -> jedna proba z podpowiedzia, dopiero potem blad, - kontynuacja konczy sie tura UZYTKOWNIKA — Claude odrzuca prefill asystenta (400), - `thinking` konfigurowany JAWNIE (adaptive + effort=high; ANTHROPIC_THINKING=off). Okna kontekstu i rezerwa na odpowiedz (app/llm/limits.py): - tabela okien/limitow wyjscia per model + nadpisanie z ENV, - plan() liczy okno odpowiedzi jako okno - prompt - margines i NIGDY nie oddaje calego kontekstu promptowi, - Anthropic liczy tokeny DOKLADNIE (/v1/messages/count_tokens), reszta szacuje, - >90 tys. tokenow promptu -> ostrzezenie, ale wyslanie NADAL mozliwe i z pelnym oknem odpowiedzi. UI: suwak budzetu rozszerzony o „bardzo obszerny" i „maksymalny kontekst modelu" (liczony z okna wybranego modelu po odjeciu rezerwy); przy wyniku widac plan tokenow, liczbe tur i ostrzezenia. Domyslny model Anthropic: claude-opus-4-8. Testy: 170 passed / 1 skipped (logika) + 15 (prezentacja). Nowe testy pokrywaja sklejanie kontynuacji, brak prefillu asystenta, ture z samego myslenia, rezerwe na odpowiedz i prog ostrzezenia. Zweryfikowane e2e na atrapie Anthropica odtwarzajacej zgloszony objaw: 3 tury, obie czesci tekstu obecne. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
877ec91ff0 |
fix(llm): pusta odpowiedz modelu to blad, nie pusta strona
build / build (push) Successful in 57s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 13m7s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m57s
Testy / Build obrazu silnika B (swisseph) (push) Successful in 40s
Testy / Kontrola składni wszystkich warstw (push) Successful in 25s
Objaw zgloszony przez uzytkownika: w Kalendarzu horoskop wyswietla sie
poprawnie, w Interpretacjach zapytanie wychodzi, wraca — i NIC sie nie
pokazuje. Bez zadnego komunikatu.
Przyczyna: model potrafi oddac pusta tresc (finish_reason=length,
completion_tokens=0), a generate() zwracalo wtedy pusty tekst BEZ bledu.
Widok sprawdza {% if prompt_result.horoscope %} -> falsz -> nie renderuje nic,
a llm_error nie jest ustawiony -> zero wyjasnienia. Cicha awaria.
Asymetria miedzy ekranami wynika z rozmiaru promptu: natalny (13 obiektow x
fasety x opisy z bazy) wypelnia okno kontekstu modelu lokalnego i na odpowiedz
nie zostaje miejsca; okresowy jest mniejszy i sie miesci.
- wspolny straznik _require_text() dla obu dostawcow: pusta lub bialoznakowa
odpowiedz podnosi LLMError,
- komunikat PROWADZI DO PRZYCZYNY: podaje finish_reason i zuzycie tokenow oraz
radzi zmniejszyc budzet promptu / zwiekszyc num_ctx / LLM_MAX_TOKENS,
- Anthropic sprowadzony do wspolnego ksztaltu diagnostyki (input/output_tokens).
Dzieki temu uzytkownik widzi powod ORAZ gotowy prompt do recznego uzycia.
Zweryfikowane na zywym stosie z atrapa modelu oddajaca pusta tresc: zamiast
pustej strony pojawia sie pelny komunikat z diagnostyka. Testy: 148 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
5203ba9e76 |
fix(llm): konfiguracja per dostawca — przelacznik w UI byl iluzja
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m49s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m55s
Testy / Build obrazu silnika B (swisseph) (pull_request) Failing after 28s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 23s
build / build (push) Successful in 1m14s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m0s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 10m0s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 50s
Testy / Kontrola składni wszystkich warstw (push) Successful in 22s
UI pozwala wybrac dostawce przy KAZDYM zadaniu, ale factory czytalo jedna wspolna trojke LLM_MODEL / LLM_BASE_URL / LLM_API_KEY dla wszystkich. Na klastrze LLM_BASE_URL trzeba ustawic na lokalny model (localhost:11434 w podzie nie istnieje) — i wtedy: - wybor „OpenAI" wysylal zadanie do Ollamy, - LLM_MODEL=llama3.1:8b kazal Anthropic uzyc modelu llama, - jeden LLM_API_KEY nie moze byc kluczem OpenAI i Anthropic naraz. Czyli nie bylo miejsca, w ktore dalo sie sensownie wpisac klucze do chmury. - konfiguracja per dostawca: <DOSTAWCA>_MODEL / _BASE_URL / _API_KEY (LOCAL_*, OPENAI_*, ANTHROPIC_*), - zgodnosc wstecz: wspolne LLM_* dziala nadal, ale stosuje sie WYLACZNIE do dostawcy domyslnego (LLM_PROVIDER) — instalacja jednodostawcowa bez zmian, - Anthropic dostal brakujaca walidacje klucza (mial ja tylko OpenAI), - komunikat bledu wskazuje konkretna zmienna do ustawienia. Testy regresyjne pilnuja, ze ustawienia jednego dostawcy NIE przeciekaja na pozostalych. Calosc: 143 passed / 1 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
4ef90b30bc |
feat(logic): dostawcy LLM i pisanie horoskopu (LOG-31)
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m38s
Testy / Testy warstwy prezentacji (dostęp do baz) (pull_request) Successful in 9m43s
Testy / Build obrazu silnika B (swisseph) (pull_request) Failing after 24s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 24s
build / build (push) Successful in 59s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m47s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m53s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 29s
Testy / Kontrola składni wszystkich warstw (push) Successful in 18s
Domyslnie model LOKALNY — prompt niesie oryginalne opisy z baz, wiec domyslnie NIC nie opuszcza sieci. Chmura wlaczana swiadomie (LOG-32). - app/llm/: LLMProvider (jak EphemerisEngine z LOG-24) + dwie implementacje. Lokalny serwer modelu (Ollama/vLLM/llama.cpp) i OpenAI mowia TYM SAMYM protokolem /chat/completions, wiec obsluguje je jedna klasa; Anthropic ma wlasny /v1/messages. Napisane na samym httpx — bez SDK openai/anthropic: mniej zaleznosci i pelna kontrola nad tym, co wychodzi z sieci. - Kazdy dostawca deklaruje `leaves_lan` — interfejs MUSI jawnie mowic, czy tresc baz opuszcza siec; UI na tej podstawie ostrzega. - Ponawianie z backoffem (429/5xx), timeouty, czytelne bledy zamiast stacktrace. - Klucz wylacznie z LLM_API_KEY (sekret), nigdy w repo ani w UI. - POST /chart/horoscope + GET /llm/health. WAZNE: prompt jest zwracany ZAWSZE — takze gdy model padnie lub brakuje klucza. Dzieki temu awaria dostawcy nie blokuje pracy: prompt mozna skopiowac i uzyc recznie. Prezentacja: wybor modelu (lokalny/Anthropic/OpenAI), przycisk „Napisz horoskop (AI)", wynik z informacja kto go napisal, czy dane opuscily siec, ile wskazan weszlo, oraz zastrzezenie ze to nie porada medyczna (PRE-15). Testy: 13 nowych (transport podstawiony — zaden prawdziwy model nie wolany), calosc 131 passed / 1 skipped. Zweryfikowane e2e na atrapie serwera modelu: horoskop napisany, leaves_lan=false, tokeny zliczone; a przy padnietym modelu / braku klucza / zlym dostawcy — czytelny blad i zachowany prompt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
73fd41b9d3 |
fix(logic): pomijaj trywialne aspekty par sztywnych (NN/SN)
build / build (push) Successful in 53s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m44s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m55s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 26s
Testy / Kontrola składni wszystkich warstw (push) Successful in 23s
Węzły księżycowe są z definicji w dokładnej opozycji (SN = NN + 180°), więc wpis "North Node opposition South Node orb 0.00°" nie niósł żadnej informacji astrologicznej — zaśmiecał /chart/positions i UI horoskopu, a w generatorze promptów LLM zjadał budżet znaków i mógł zostać wzięty przez model za realne świadectwo. - aspects.py: RIGID_PAIRS + pomijanie takich par w find_aspects; struktura zbioru pozwala dopisać kolejne pary definicyjne, - aspekty węzłów do pozostałych obiektów bez zmian, - testy: jawne sprawdzenie braku pary NN/SN (jednostkowo i na horoskopie referencyjnym). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
752f477a27 |
feat(security): zamkniecie dostepu do baz interpretacyjnych (LOG-32)
build / build (push) Successful in 1m16s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 11m9s
Testy / Testy warstwy prezentacji (dostęp do baz) (push) Successful in 9m51s
Testy / Build obrazu silnika B (swisseph) (push) Failing after 26s
Testy / Kontrola składni wszystkich warstw (push) Successful in 22s
Bazy sa rdzeniem produktu i wlasnie zostaly kupione — a aplikacja nie miala ZADNEGO uwierzytelniania. Prezentacja to NodePort, wiec kazdy w LAN wchodzil bez logowania, a `/search` oddawal surowe wiersze do 50 000 na zapytanie. Bazy mogly wyjsc przez sama aplikacje, bez udzialu jakiegokolwiek LLM. - prezentacja: HTTP Basic (APP_USER/APP_PASSWORD) + limit zadan na IP (RATE_LIMIT_PER_MIN, domyslnie 120/min). Limit dziala TAKZE przed uwierzytelnieniem, zeby zgadywanie hasla i sondowanie API nie bylo darmowe. - logika i dane: token miedzywarstwowy X-Astrololo-Token (INTERNAL_TOKEN) — bez niego dalo sie ominac logowanie, uderzajac wprost w warstwe nizej. Warstwa danych oddaje surowe wiersze, wiec to najwrazliwszy punkt. - /search: gorny limit 50 000 -> 5000 (tyle realnie uzywa build_report). Publiczne /api/query zostaje na 200. - /health celowo publiczny (sondy k8s go nie uwierzytelnia). - swiadomie nie logujemy tresci zadan ani promptow — logi to kolejny nosnik. Fail-open przy braku konfiguracji (zgodnosc wstecz i dev), ale z GLOSNYM ostrzezeniem przy starcie, zeby nikt nie wdrozyl tego w przekonaniu, ze jest chroniony. Wlaczenie w produkcji wymaga ustawienia sekretow w repo deploy. Testy: 12 (prezentacja, nowy katalog + job w CI) i 5 (logika). Zweryfikowane na zywym stosie: bez hasla 401, z haslem 200, logika wprost bez tokenu 401, z tokenem 200, /health 200, limit 50000 odrzucony (422), a prezentacja nadal liczy horoskop przez logike. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
04b26afa6d |
feat(logic): generator promptow do LLM + budzetowanie (LOG-29, LOG-30)
Pierwszy krok ustalonej kolejnosci: prompt z podgladem, uzyteczny od razu BEZ integracji API (ta przyjdzie w LOG-31). LOG-29 — app/prompt.py: - profil natal (ekran Interpretacje) i period (ekran Kalendarz), - prompt po polsku: zadanie -> dane horoskopu (pozycje, osie, Lots, aspekty, sekta, zodiak) -> wskazania z baz wg wagi -> instrukcje -> zastrzezenie, - twarde reguly: kazda teza musi cytowac konkretny sygnifikator, zakaz wychodzenia poza dostarczone dane, jawne wskazanie sprzecznosci, - deterministyczny: ten sam horoskop + budzet = ten sam prompt. LOG-30 — redukcja do budzetu (concise/medium/extensive): dedup -> grupowanie z licznikiem -> sortowanie wg punktacji sily (LOG-21) -> obciecie ogona (jednostka = CALE wskazanie) -> skracanie dlugich opisow. Statystyki zwracaja ile weszlo/pominieto i jaki byl prog — takze w tresci promptu, zeby model wiedzial, ze widzi wybor. POST /chart/prompt — zwraca sam prompt + statystyki, bez wolania modelu. Prezentacja: przycisk „Generuj prompt (AI)" na obu ekranach, wybor budzetu, pole z promptem + kopiowanie (z fallbackiem dla http bez secure context). WAZNE (znalezione przy tescie e2e): padnieta warstwa danych zabiera tylko wskazania — horoskop i OS CZASU zostaja, bo sa czysto obliczeniowe. Wczesniej blad bazy gubil cala osie czasu, czyniac prognoze okresowa bezuzyteczna. Zabezpieczone testem. Testy: 19 nowych, calosc 118 passed / 1 skipped. Zweryfikowane e2e w przegladarce: profil natal (3340 znakow) i period (15 zdarzen, 4728 znakow). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6f87b2b323 |
feat(logic): systemy zodiaku — syderyczny, draconic (LOG-04)
Jedyne wymaganie Must bez implementacji. Nowy zodiac.py + wpiecie w horoskop: - zodiac.py: ayanamsy (Lahiri, Fagan-Bradley, Krishnamurti) modelem ayan(jd)=ayan0+B*x+C*x^2 (wspolna precesja, rozna stala) — skalibrowanym do Swiss Ephemeris jako WYROCZNI: zgodnosc do ~0,02" w latach 1900-2100. Draconic = wzgledem wzla wznoszacego (wzel = 0 Barana). RA: konwersja ekliptyka->rownik (to_equatorial) na przyszly widok rownikowy. - chart.py: build_chart(..., zodiac): offset jednolicie przesuwa etykiety znakow/dlugosci obiektow, osi, cusps i Lots; DOMY licza sie po dlugosci tropikalnej (geometria niezmiennicza wzgledem obrotu -> numery domow bez zmian). Domyslnie tropical -> sciezka i wyniki bez zmian. - main.py: /chart/positions przyjmuje `zodiac`; bledny -> 422. - prezentacja: dropdown „Zodiak" + pokazanie ayanamshy w wynikach. Testy (14): ayanamsy vs wyrocznia swisseph (<0.1"), julian_day, draconic (wzel=0 Barana), niezmienniczosc domow, RA w punktach charakterystycznych, odrzucenie bledow. Cala logika: 99 passed, 1 skipped. Zweryfikowane e2e w przegladarce (horoskop syderyczny Lahiri: Slonce Aries 16°34', ayan 23.6382). RA jako osobny widok zodiaku (per-obiekt, z szerokoscia) — do osobnego PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
79bce8ae90 |
Lots / punkty arabskie — 7 Lots hermetycznych (LOG-08)
- engine/lots.py: formuła Lot = C + A − B z odwracaniem w horoskopach nocnych (zamiana A<->B); 7 Lots hermetycznych (Fortuna, Duch, Eros, Konieczność, Odwaga, Zwycięstwo, Nemezis) — Fortuna i Duch liczone pierwsze, bo pozostałe się do nich odwołują. Dwa warianty: degree (domyślny) i sign (całe znaki). - build_chart: liczy sektę (reużyta is_day_birth z Firdarii) i zwraca lots ze znakiem, pozycją i domem; parametr lots_method. - wyszukiwarka: token [PF (tak Fortuna występuje w realnej bazie) + rozwinięcie skrótu do "Part of Fortune". - widok Horoskop: tabela Lots z formułami i sektą. Walidacja (dwie niezależne wyrocznie z notes3): - Fortuna = Can 12°35'27" vs astro-seek Can 12°35'24" (3 sekundy różnicy), dom 1; - Duch potwierdzony przez swoją antyscję (Taurus 28°14' z tabeli antyscji); - odwracanie nocne: Fortuna nocna == Duch dzienny i odwrotnie; - Lots pochodne faktycznie używają Fortuny/Ducha; wariant sign trafia w 0° znaku. 85 testów przechodzi (nowy test_lots). Odblokowuje Zodiacal Releasing (LOG-11), które startuje z Fortuny/Ducha. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9d5b65ddbd |
Firdaria (LOG-11) — perska technika time-lord
- engine/firdaria.py: sekta (dzień = Słońce nad horyzontem, ta sama półkula osi Asc-Dsc co MC); kolejność diurnalna/nokturnalna; klasyczne długości okresów (Su10 Ve8 Me13 Mo9 Sa11 Ju12 Ma7 + NN3 + SN2 = 75 lat); okresy główne planet dzielone na 7 podokresów (sub-lord od władcy okresu), węzły bez sub. - endpoint /chart/firdaria. - oś czasu: firdaria_events — starty (pod)okresów w oknie; wpięte w build_timeline (domyślnie) + tokeny [major][sub] do dopięcia interpretacji (1B->2B). Walidacja: - sekta = day dla horoskopu referencyjnego (zgodnie z notes3 "Day birth"); night gdy Słońce po stronie IC; sumy i przyleganie okresów; podokresy 7x sumujące się do okresu; wiek 42 w okresie Saturna. - E2E: okresy Sun 1984-1994 ... Saturn 2024-2035; w osi czasu "Firdaria: Saturn / Mars" 2027 -> 223 interpretacje ([Sa+[Ma -> "injury"). - 78 testów przechodzi (nowy test_firdaria). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
c4a181b810 |
Spięcie osi czasu z bazą interpretacji i widokiem (LOG-14, 1B->2B)
Realizuje przepływ 1B->2B z notes2: predykcyjne sygnifikatory (z datami)
dopasowane do interpretacji z bazy.
Logika:
- timeline.py: zdarzenia niosą strukturę (directed/aspect/target dla dyrekcji,
lord/sign dla profekcji) do budowy tokenów.
- significators.interpret_events + _event_tokens: z każdego zdarzenia buduje
tokeny bazy (dyrekcja: [planeta][aspekt][cel]; profekcja: [władca][znak]) i
dopina interpretacje reużywając _facet_samples (AND tokenów, dedup, rozwinięcie).
- /chart/timeline: flaga interpret=true.
Prezentacja:
- nowa strona /timeline "Kalendarz": formularz (urodzenie + zakres dat) -> oś
czasu z technikami, datami i interpretacjami; nawigacja + wspólne now.js.
Walidacja E2E na realnym main_base.xlsx (2025-2026):
- dyr. Saturn kwadratura MC -> 50 interpret. ("...5th house" -> "abortion/miscarriage")
- Władca Roku Saturn (wiek 42) -> 63; strona renderuje badge dat/technik.
71 testów przechodzi (nowy test_timeline_interpret).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
2dbd3410e9 |
Zbiorcza tabela dat z technik (LOG-14)
engine/timeline.py: scala w jedną posortowaną oś czasu (technique | significator | start | exact | end): - profekcje roczne (LOG-10) — Władca Roku per rok życia, - Solar Return (LOG-12) — moment powrotu Słońca, - dyrekcje solar-arc — daty dokładnych aspektów kierowanych planet do punktów natalnych (klucz Naiboda 0°59'08"/rok, konfigurowalny; okno orbowe ±1 rok). Endpoint /chart/timeline (zakres from_date..to_date, wybór technik). Walidacja: - profekcje spójne z tabelą notes3; dyrekcja Sun koniunkcja MC (łuk 312°) słusznie poza życiem; oś posortowana po dacie dokładnej; wiek = łuk/klucz spójny z datą. - E2E: dla 2025-2026 zwraca 19 zdarzeń (m.in. Władca Roku 42 Saturn 30.04.2026, Solar Return, dyr. Venus koniunkcja North Node 27.05.2025). 66 testów przechodzi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b013831492 |
Profekcje roczne (LOG-10) i Solar/Lunar Return (LOG-12)
Pierwsze techniki predykcyjne. Profekcje (LOG-10): - engine/profections.py: Whole Sign, wiek mod 12; profektowany Asc + Władca Roku (władca domicylowy) + profekcje MC/Su/Mo. Obsługa 29 lutego. - endpoint /chart/profections (zakres lat: start_age, count). Returns (LOG-12): - engine/returns.py: moment powrotu Słońca/Księżyca do długości natalnej; skan dobowy + bisekcja do ~sekundy, z pominięciem artefaktu zawinięcia 0/360. - endpoint /chart/return (kind solar|lunar, around) — zwraca pełny horoskop na znaleziony moment (oba warianty użycia po stronie technik wyżej). Walidacja: - profekcje zgodne co do joty z tabelą astro-seek z notes3 (wiek 0..42: Asc + Władca Roku + MC/Su/Mo). - Solar Return 2026: Słońce wraca do Tau 10°08'22" = natalny stopień; Lunar Return trafia natalny Księżyc <2'; samospójność potwierdzona. - 62 testy przechodzą (nowe: test_profections, test_returns). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a8c3072e62 |
Węzły księżycowe, mean Lilith i wykrywanie stacji (LOG-02/03)
Punkty wirtualne (LOG-02): - engine/points.py: mean Node (Ω) i mean Lilith (apogeum) wzorami Meeusa; prędkości numerycznie. SN = NN + 180° (ta sama prędkość), zawsze Rx. - DEFAULT_OBJECTS + North Node / South Node / Lilith — automatycznie dostają domy, aspekty i A/S. Parzystość silnika B: swe.MEAN_NODE / swe.MEAN_APOG (uwaga: stała pyswisseph to MEAN_APOG, nie MEAN_APOGEE). - significators: tokeny [NN / [SN / [Lilith (zgodne z SIGNIFICATORS KEY). Stacje (LOG-03): - engine/stations.py: skan prędkości (krok 4 dni, okno ±800 dni — pokrywa najdłuższe przerwy Marsa/Wenus) + bisekcja; klasyfikacja SD/SR; poprzednia/ następna stacja (dni, data, stopień w znaku) + flaga station_soon (<7 dni). - /chart/positions: opt-in stations:true; UI: checkbox + tabela stacji. Walidacja: - mean NN vs astro-seek (Gem 8°09'24"): Δ=0,3'; vs swisseph: Δ=17"; mean Lilith vs swisseph: Δ=1,5'. NN dom 12 / SN dom 6 zgodnie z astro-seek. - Stacje Marsa 1984 trafiają w historię: SR 5.04.1984, SD 19.06.1984; samospójność |speed|<0,01°/d w znalezionych momentach; flaga "blisko" działa (Merkury +5,3d, Jowisz -0,6d). - E2E na realnej bazie: [SN 134 rekordy, trafienie w 6. domu. 54 testy przechodzą. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
8d579de34a |
Aspekty: applying/separating (A/S) + bonus siły dla aplikujących (LOG-06)
- aspects.py: _is_applying — odchyłka od dokładnego kąta teraz vs po małym
kroku czasu (prędkość·dt, dt=0,01 doby by szybki Księżyc nie przeskoczył
dokładności); aspekt niesie applying (bool) i "as": A/S. Bez prędkości —
brak flagi (None).
- scoring: aspekt aplikacyjny silniejszy (APPLYING_BONUS 1.15) — zgodnie z
notatkami projektu ("impact considered more powerful").
- significators: faseta aspektu niesie applying, etykieta z sufiksem (A)/(S).
- widok Horoskop: kolumna A/S w tabeli aspektów (tooltip z objaśnieniem).
Walidacja: flagi A/S wszystkich 16 aspektów horoskopu referencyjnego
(30.04.1984, Warszawa) zgodne z tabelą astro-seek z notes3 (test regresyjny
REFERENCE_AS). 45 testów przechodzi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
f6323cac10 |
Ranking siły (LOG-21) + grupowanie identycznych opisów + geolokalizacja
Punktacja siły (LOG-21): - scoring.py: siła fasety z sygnałów obliczalnych (typ fasety, rodzaj aspektu, ciasnota orbu). Konfigurowalne wagi. Hook na przyszłość: kolumny countas*/level* z SIGNIFICATORS KEY (obecnie puste). - aspekty niosą orb+allowed; fasety dostają "score"; ranking faset malejąco. Grupowanie: - opcja group: zwija próbki po opisie (ten sam efekt = jedna grupa z listą sygnifikatorów i licznikiem). Checkbox "grupuj identyczne opisy" w /interpret. Geolokalizacja (bajer): - "Tu i teraz" (widok Horoskop i Interpretacje) uzupełnia lat/lon z przeglądarki (navigator.geolocation; wymaga zgody, https/localhost). Zweryfikowano na realnym main_base.xlsx: ranking sensowny (ciasna opozycja z Saturn 9.59 > szeroka koniunkcja z Moon 6.25 > znak/dom 5.0); grupowanie zwija powtórzone opisy. 41 testów przechodzi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
166b438f83 |
Aspekty (LOG-06) + faseta aspektu, dedup i dopieszczenie wyników
Aspekty: - engine/aspects.py: aspekty główne (conj/sex/sq/tri/opp) z orbami (bonus dla luminarzy), separacja z obsługą zawinięcia. Applying/sep na później. - build_chart zwraca listę aspektów; /chart/positions je udostępnia; widok Horoskop pokazuje tabelę aspektów. Bogatsze sygnifikatory: - trzecia faseta "w aspekcie": dla każdego aspektu głównego obiektu filtruje rekordy po tokenie aspektu + drugiej planety ([conj + [Mo). Cookbook komplet: znak + dom + aspekt. Dopieszczenie wyników: - ODSIEWANIE DUPLIKATÓW: duplikat = ten sam sygnifikator ORAZ ten sam opis (po normalizacji). Dedup wewnątrz fasety, działa też na wynikach z wielu baz. - _facet_samples przyjmuje wiele tokenów (AND); dedup + istniejące odsiewanie szumu. Zweryfikowano na realnym main_base.xlsx (30.04.1984): 16 aspektów zgodnych z astro.com (Sun conj Moon 9.59°, Sun opp Saturn 3.17°); faseta aspektu daje bogate trafienia (Sun koniunkcja z Moon 84, opozycja z Saturn 43); dedup obniżył duplikaty (Sun w znaku 46->44). 36 testów przechodzi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
82809665ff |
Odsiewanie szumu + rozwijanie skrótów sygnifikatorów
- abbreviations.py: słownik skrót -> pełna nazwa (z SIGNIFICATORS KEY, built-in) + expand(): [Su in [Tau -> "Sun in Taurus", [Sa in 6th H. -> "...6th house", affl. -> afflicted itd. - significators: każda próbka ma pole "expanded" (postać czytelna); hartowanie filtra szumu (efekty zastępcze x/?/-, wiersze *MARKER, legendy/nagłówki). - prezentacja /interpret: pokazuje rozwiniętą postać, surowy skrót w tooltipie. Zweryfikowano na realnym main_base.xlsx: "[Sa or [Ma in the 5th H." -> "Saturn or Mars in the 5th house". 9 testów przechodzi (w tym test_abbreviations). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0e74566a78 |
Bogatsze sygnifikatory: faseta "w domu" obok "w znaku" (LOG-15/16)
Most horoskop -> sygnifikatory generuje teraz dla każdego obiektu dwie fasety:
- "w znaku": planeta + token znaku ([Su + [Tau)
- "w domu": planeta + token domu ([Su + 11th H.) — używa domów z LOG-05
- significators.build_report: przyjmuje pozycje z build_chart (z numerami domów),
generuje fasety znak/dom, filtruje szum. Ordinal helper (1st..12th).
- /chart/report: używa build_chart (pozycje z domami).
- Prezentacja /interpret: render faset (znak/dom) per obiekt.
Aspekty ([conj/[sq/[opp) na później — wymagają policzenia aspektów (LOG-06).
Zweryfikowano na realnym main_base.xlsx (53969 wierszy), 30.04.1984:
Mars w 5. domu 10 dopasowań ("[Sa or [Ma in the 5th H." -> "abortion/miscarriage"),
Neptune w 7. domu 6, Uranus w 6. domu 4. 7 testów przechodzi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
dabbaef9dd | Merge branch 'master' into feat/search-integration | ||
|
|
eef67d37b5 |
Wyszukiwarka: wynik obliczeń szukany w bazie interpretacji
Pierwsza wersja mostu horoskop -> sygnifikatory -> baza (zalążek LOG-16/18/19).
- logic/significators.py: z pozycji generuje tokeny w składni bazy (planeta
[Su, znak [Tau...), pyta warstwę danych o rekordy z tokenem planety i zawęża
do tych, które wspominają też jej znak ("planeta w swoim znaku"); odsiewa szum.
- logic /chart/report: nowy endpoint (pozycje -> raport dopasowań z interpretacjami).
- logic DataClient.search: parametr fields (lżejszy payload).
- data: naprawa str.contains regex=True -> regex=False (sygnifikatory zawierają
[ + itd., metaznaki regex); podniesiony górny limit zapytania (le=50000).
- prezentacja: strona /interpret (formularz -> wyszukane interpretacje per obiekt)
+ nawigacja.
Zweryfikowano end-to-end na realnym pliku (Encyclopaedia of Medical Astrology,
53969 wierszy): dla horoskopu 30.04.1984 znaleziono m.in. Sun w Taurus 46,
Mars w Scorpio 57, Saturn w Scorpio 61 dopasowań; przykłady: "[Su in [Tau" ->
"the bump of amativeness prominent". 15 testów przechodzi.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
94c3023d3a |
Silnik: osie (Asc/MC) i systemy domów (LOG-05)
Kontynuacja silnika efemeryd o osie i domy. - engine/houses.py: czysta matematyka sferyczna — Asc, MC (z RAMC + ε + φ), cusps dla Whole Sign / Equal / Porphyry, przypisanie obiektu do domu. - SkyfieldEngine.sidereal(): RAMC (lokalny apparent ST) + średnie nachylenie ekliptyki ze Skyfielda. - engine/chart.py: build_chart() składa pełny horoskop (pozycje + osie + domy). - Endpoint /chart/positions rozszerzony o house_system i zwraca angles + cusps + numer domu per obiekt. - Prezentacja: lokalizacja i wybór systemu domów w formularzu, tabela osi, kolumna Dom, rozwijane cusps. Walidacja względem astro.com (30.04.1984, Warszawa): Asc Can 22°10'43", MC Pis 22°35'29" (~1' od referencji); wszystkie przypisania domów Whole Sign zgodne (Sun 11, Mercury 10, Mars 5, ...). 20 testów przechodzi. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e69c0714b9 |
Silnik efemeryd: EngineProvider + SkyfieldEngine + harness porównawczy
Pierwszy increment implementacji warstwy logicznej (ścieżka A). LOG-24: interfejs EphemerisEngine z dwoma backendami — SkyfieldEngine (własny, permisywny: Skyfield MIT + dane JPL public domain) oraz RemoteEngine (klient izolowanej usługi swisseph). Fabryka + leniwa inicjalizacja; endpointy /chart/positions i /chart/compare. LOG-01: pozycje obiektów (długość/szerokość ekliptyczna, prędkość, kierunek, formaty: w znaku / absolutny / dziesiętny). LOG-25/28: harness porównawczy (compare.py) z progami tolerancji oraz wspólny kontrakt parzystości; pełen zestaw testów. LOG-27: services/engine-swisseph — osobna, opcjonalna usługa AGPL (pyswisseph, tryb Moshiera), licencjonowana osobno, w compose pod profilem "comparison"; nie wchodzi do zamkniętego produktu. Walidacja: SkyfieldEngine zgadza się ze Swiss Ephemeris co do ~1" dla wszystkich 10 obiektów na horoskopie referencyjnym (30.04.1984, Warszawa); 12 testów przechodzi (silnik B pomijany gdy nieskonfigurowany). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
16d35c16dc |
Szkielet aplikacji trójwarstwowej (prezentacja / logika / dane)
Trzy niezależne usługi FastAPI komunikujące się przez HTTP/JSON, każda zna tylko adres warstwy bezpośrednio pod nią: - presentation (:8000) — strona WWW + formularz - logic (:8001) — reguły biznesowe, pośrednik - data (:8002) — wyszukiwanie danych za interfejsem DataProvider Warstwa danych: czytanie setek plików .xlsx z wykrywaniem nagłówka i mapowaniem układu kolumn na schemat kanoniczny, z 4-poziomowym cache (schemat L1, Parquet L2, wyniki zapytań L3, odwrócony indeks L4) i unieważnianiem po odcisku pliku. Gotowa ścieżka migracji do SQL (ingest/to_sql.py + SqlDataProvider, przełączane przez DATA_PROVIDER). Zawiera docker-compose, Makefile, generator danych przykładowych. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |