Files
gitea 8b6ecc727d
Testy / Testy warstwy logicznej (silnik) (pull_request) Successful in 10m44s
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 20s
Testy / Kontrola składni wszystkich warstw (pull_request) Successful in 8s
build / build (push) Successful in 23s
Testy / Testy warstwy logicznej (silnik) (push) Successful in 10m38s
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 9s
feat(domy): przypisanie do domu przez wyrocznię + poprawki układu strony
ETAP 5, część pierwsza: assign_house pod wyrocznią (swe_house_pos).
Osobny rodzaj błędu niż same cuspy — i od razu jeden znalazł.

BŁĄD: assign_house szło ZAWSZE do przodu. Przy dużych szerokościach systemy
dzielące koła wielkie mają kolejność domów ODWRÓCONĄ (przy φ=−84,3° cusp domu I
wypada na 174,2°, a domu II na 165,3°) — co nie jest usterką, bo wyrocznia zwraca
dokładnie te same wartości. Suma przeskoków „do przodu" wychodziła 3960° zamiast
360°, czyli każdy krok obchodził koło dookoła. Planety lądowały w złych domach
dla regiomontanusa, campanusa i topocentrica: 9,7-12,5% przypadków. Błąd cichy —
wykres wyglądał bez zarzutu. Kierunek bierzemy teraz z samych cuspów.

TOPOCENTRIC MA JEDNAK GRANICĘ DZIEDZINY — korekta tego, co pisałem wcześniej.
Cuspy są poprawne wszędzie (zgodne z wyrocznią co do zera), ale powyżej koła
podbiegunowego przestają DZIELIĆ OKRĄG: cusp VII (= I + 180°) wypada przed
cuspem VI i domy nachodzą na siebie. Przypisanie planety traci wtedy sens —
co potwierdza sama wyrocznia, której swe_house_pos przeczy tam własnym cuspom
(100% zgodności do 62°, 83,9% przy 66°, ok. 50% przy 72°; regiomontanus 100%
w tych samych punktach). Odmawiamy, z jawnym fallbackiem jak Placidus i Koch.

Próg jest WYPROWADZONY z warunku „dwanaście cuspów sumuje się do 360°", nie
dobrany pod wynik testu — i wypada na kole podbiegunowym (zmierzone: 100%
podziałów do 65°, 78% w pasie 66-67°). To inny rodzaj granicy niż u Placidusa
i Kocha: tam nie istnieją same cuspy, tu istnieją, tylko nie tworzą podziału.

Framework dostał pojęcie dziedziny WĘŻSZEJ niż wyroczni (NARROWER_THAN_ORACLE),
zamiast wyjątku „bo topocentric": skoro wyrocznia przeczy sama sobie, nie może
rozstrzygać, więc tam nie porównujemy — a nasze przypisanie jest w tym obszarze
sprawdzane testem samospójności z cuspami, bez swissepha.

UKŁAD STRONY — zmierzony na żywej stronie, nie na oko:
- tabela porównania przy 13 systemach miała 14 kolumn i 1863 px, a stała
  w rodzicu bez overflow-x, więc ROZPYCHAŁA CAŁY DOKUMENT: 1713 px przy oknie
  1280 px, poziomy pasek na body. Teraz ma własny kontener przewijany
  (dokument 1265 px, nie przewija się), a numer domu jest przyklejony do lewej,
  bo inaczej po przewinięciu nie wiadomo, który to wiersz.
- przypis „* nie działa za kołem podbiegunowym" siedział WEWNĄTRZ <label>
  selektora, łamał się na dwie linie i rozciągał wiersz siatki ze 66 do 108 px,
  rozjeżdżając go z sąsiednim polem. Wyjaśnienie stoi teraz raz, przy
  checkboxach z gwiazdkami; wiersz wrócił do 66 px.
- 13 checkboxów na flexie zawijało się w poszarpane wiersze — jest siatka
  o stałej szerokości kolumny (auto-fill, więc na wąskim ekranie kolumn mniej).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:55:13 +02:00
..

Warstwa logiczna (logic)

Niezależna usługa pośrednicząca. W górę udostępnia API dla prezentacji, w dół woła warstwę bazodanową. Tu żyją reguły biznesowe — nie w prezentacji i nie w bazie.

API

  • POST /api/queryQueryRequestQueryResponse
  • POST /chart/positions{when_utc, lat, lon, house_system?} → pełny horoskop: pozycje (LOG-01) + osie i domy (LOG-05) + aspekty główne z applying/separating (LOG-06) + opcjonalnie stacje planet (stations:true, LOG-03). Zwraca też sektę i 7 Lots hermetycznych z domami (LOG-08). Obiekty: 10 planet + mean NN/SN/Lilith (LOG-02). house_system: whole_sign (dom.) / equal / porphyry.
  • POST /chart/report{when_utc, lat, lon, limit?} → wynik obliczeń wyszukany w bazie: fasety sygnifikatorów w znaku / w domu / w aspekcie, z rozwinięciem skrótów, odsiewaniem duplikatów (ten sam sygnifikator i opis), rankingiem siły (LOG-21) oraz opcją group (grupowanie identycznych opisów)
  • POST /chart/profections{when_utc, lat, lon, start_age?, count?} → profekcje roczne: wiek, profektowany Asc, Władca Roku (+MC/Su/Mo) (LOG-10)
  • POST /chart/return{when_utc, lat, lon, kind, around?} → Solar/Lunar Return: moment powrotu + pełny horoskop na ten moment (LOG-12)
  • POST /chart/firdaria{when_utc, lat, lon} → Firdaria: sekta (dzień/noc), okresy główne i podokresy time-lordów (LOG-11)
  • POST /chart/timeline{when_utc, lat, lon, from_date, to_date, techniques?} → zbiorcza oś czasu: profekcje + Solar Return + dyrekcje solar-arc + Firdaria, posortowane (technique | significator | start | exact | end); z interpret=true dopina interpretacje z bazy do dat (LOG-14, 1B->2B)
  • POST /chart/compare → jak wyżej → raport różnic dwóch silników (LOG-26; wymaga silnika B)
  • GET /health (sprawdza też warstwę bazodanową)

Silnik efemeryd (LOG-24, „wymienny silnik liczący")

W app/engine/ żyje pluggable silnik za interfejsem EphemerisEngine:

  • SkyfieldEngine — własny, permisywny (Skyfield MIT + dane JPL public domain). Domyślny.
  • RemoteEngine — klient OSOBNEJ, izolowanej usługi engine-swisseph (AGPL), używany tylko w trybie porównawczym.

Wybór: EPHEMERIS_ENGINE=own|swisseph. Silnik B włącza się przez ENGINE_SWISSEPH_URL.

Walidacja (LOG-25/28): app/engine/compare.py zestawia oba silniki z progiem tolerancji; ten sam kontrakt parzystości obowiązuje każdy silnik. Nasz SkyfieldEngine zgadza się ze Swiss Ephemeris co do ~1″ na horoskopie referencyjnym (patrz tests/).

pip install -r requirements-dev.txt
PYTHONPATH=. pytest tests -q            # silnik B pomijany, jeśli ENGINE_SWISSEPH_URL nieustawiony

Zależności w dół

Zna wyłącznie DATA_URL (adres warstwy bazodanowej) i jej kontrakt /search. Nie wie, czy pod spodem jest Excel czy SQL.

Uruchomienie

pip install -r requirements.txt
export DATA_URL=http://localhost:8002
uvicorn app.main:app --port 8001

Gdzie rozbudowywać domenę

service.pyQueryService.handle(): walidacja wejścia, tłumaczenie zapytania, obliczenia i wzbogacanie wyników.