# Accuracy validation This is a validation layer, not a second predictive engine. It intentionally does not change the API response or the production calculation path. ## Reproduce locally From the API directory: ```bash python -m pip install -r requirements.txt python accuracy_validation.py --no-shadow ``` To install the optional shadow engines in a separate environment: ```bash python -m pip install -r requirements-accuracy.txt python accuracy_validation.py python accuracy_validation.py --strict-shadow ``` The command prints a JSON report and exits non-zero when a local golden case or the explicit late-Zi/midnight contract fails. `--strict-shadow` additionally fails when an installed shadow engine disagrees. ## What is covered - Five civil-date cases taken from the Hong Kong Observatory's Gregorian/lunar conversion table, including the 2033 leap-month boundary. - Current BaZi and Da Yun regression anchors from `lunar-python==1.4.8`. - The current product policy at 22:59, 23:00, 23:59, 00:00, and 00:59. - Optional Tyme4py comparison using `LunarSect2EightCharProvider` for the chart and `LunarSect1ChildLimitProvider` for 起运, matching the current product contract. - Optional sxtwl comparison for civil-calendar and four-pillar fields. sxtwl shares the ShouXing lineage with lunar-python, so a pass only catches port or interface drift; it is not an independent astronomical truth source. - A validation-only Da Yun rule registry records each current score signal, its implementation owner, double-count group, and evidence status. The weighted rules intentionally remain marked unvalidated until a blinded, labelled outcome dataset exists. ## Contract currently made explicit ```text chart sect: 2 (late 子时 keeps the birth day's 日柱) yun sect: 1 (3 days = 1 year; 1 day = 4 months; 1 时辰 = 10 days) ``` This distinction matters: `lunar-python` defaults the chart object to sect 2, while `getYun(..., sect=1)` is the current API's 起运 policy. A future change must update the contract and its fixtures deliberately. ## Authority and limitations - [GB/T 33661-2017](https://openstd.samr.gov.cn/bzgk/std/newGbInfo?hcno=E107EA4DE9725EDF819F33C60A44B296) is the modern Chinese-calendar policy reference. - [Hong Kong Observatory conversion tables](https://www.hko.gov.hk/en/gts/time/conversion.htm) provide reproducible 1901–2100 civil-date fixtures. - [sxtwl_cpp](https://github.com/yuangu/sxtwl_cpp) and [Tyme4py](https://github.com/6tail/tyme4py) are comparison implementations; both share the 寿星天文历 lineage with the current lunar-python path, so they detect drift but do not constitute independent proof of the fortune rules. - The fixture set does **not** prove that a 0–100 fortune score predicts life outcomes. That requires a separate blinded, labelled evaluation dataset. The same limitation applies to every weighted entry in [`rule_contract.py`](./rule_contract.py); its purpose is auditability and change detection, not endorsement of a predictive rule. For the next phase, use [`DAYUN_CALIBRATION.md`](./DAYUN_CALIBRATION.md) to collect blinded, dated outcome labels and compare the score against a constant 50 baseline. ## Rule-contract check ```bash PYTHONDONTWRITEBYTECODE=1 python -m pytest -q -p no:cacheprovider test_rule_contract.py PYTHONDONTWRITEBYTECODE=1 python rule_contract.py ```