Files
astrololo/tests/oracle/run.py
T
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

79 lines
3.3 KiB
Python

"""Uruchomienie porównania z wyrocznią. Punkt wejścia dla CI i dla Joba w klastrze.
Dwa tryby:
--mode build (domyślny) zestaw BRZEGOWY + tyle samo przypadków z wnętrza.
Szybki, deterministyczny, BLOKUJE build przy błędzie.
--mode sweep wielki losowy przemiał, o rząd wielkości większy.
Do Joba w klastrze; ziarno raportowane, więc każdy
błąd da się odtworzyć komendą z raportu.
Kod wyjścia: 0 = zgodność w granicach tolerancji, 1 = przekroczenia albo
niezgodność dziedziny. Dzięki temu CI może na tym polegać bez parsowania tekstu.
"""
from __future__ import annotations
import argparse
import os
import sys
# Ścieżka do warstwy logicznej: w CI montujemy ją do kontenera swissepha.
sys.path.insert(0, os.environ.get("LOGIC_PATH", "/logic"))
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from domain import boundary_cases, interior_cases, random_cases # noqa: E402
from harness import ( # noqa: E402
SWE_CODE, compare_asc_mc, compare_house_assignment, compare_system,
format_report,
)
# Systemy do sprawdzenia. Rośnie wraz z implementacją kolejnych (Etap 1 i 2) —
# dopisanie nazwy tutaj wystarcza, żeby weszła do każdego builda.
SYSTEMS = ["whole_sign", "whole_sign_aries", "equal", "equal_mc", "porphyry", "vehlow", "morinus",
"regiomontanus", "campanus", "alcabitus", "topocentric", "placidus", "koch"]
def main() -> int:
p = argparse.ArgumentParser(description="Zgodność domów z wyrocznią (Swiss Ephemeris)")
p.add_argument("--mode", choices=("build", "sweep"), default="build")
p.add_argument("--seed", type=int, default=0, help="ziarno losowania (do odtworzenia błędu)")
p.add_argument("--count", type=int, default=20000, help="liczba przypadków w trybie sweep")
p.add_argument("--systems", default=",".join(SYSTEMS))
args = p.parse_args()
systems = [s.strip() for s in args.systems.split(",") if s.strip()]
unknown = [s for s in systems if s not in SWE_CODE]
if unknown:
print(f"Nieznane systemy: {unknown}", file=sys.stderr)
return 2
if args.mode == "build":
boundary = boundary_cases()
# Tyle samo z wnętrza, ile brzegowych — brzegi łapią osobliwości,
# wnętrze pilnuje, że nie zepsuliśmy zwykłych przypadków.
cases = boundary + interior_cases(len(boundary), seed=args.seed)
seed_note = args.seed
else:
cases = random_cases(args.count, seed=args.seed)
seed_note = args.seed
results = [compare_asc_mc(cases)]
results += [compare_system(s, cases) for s in systems]
# Przypisanie obiektu do domu — osobny rodzaj błędu niż same cuspy.
results += [compare_house_assignment(s, cases) for s in systems]
print(f"\nprzypadków wejściowych: {len(cases)} (tryb: {args.mode})")
print(format_report(results, seed=seed_note))
failed = [r for r in results if not r.passed]
if failed:
print("\nBŁĄD: " + ", ".join(r.system for r in failed))
print(f"Odtworzenie: python run.py --mode {args.mode} --seed {args.seed}"
+ (f" --count {args.count}" if args.mode == "sweep" else ""))
return 1
print("\nWszystkie systemy zgodne z wyrocznią w granicach tolerancji.")
return 0
if __name__ == "__main__":
raise SystemExit(main())