fortune-telling-core 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fortune_telling_core-0.1.0/.github/workflows/cd.yml +67 -0
- fortune_telling_core-0.1.0/.github/workflows/ci.yml +49 -0
- fortune_telling_core-0.1.0/.github/workflows/docs.yml +70 -0
- fortune_telling_core-0.1.0/.gitignore +22 -0
- fortune_telling_core-0.1.0/AGENTS.md +83 -0
- fortune_telling_core-0.1.0/JOURNAL.md +1 -0
- fortune_telling_core-0.1.0/LICENSE +21 -0
- fortune_telling_core-0.1.0/PKG-INFO +171 -0
- fortune_telling_core-0.1.0/README.md +139 -0
- fortune_telling_core-0.1.0/docs/api/astronomy.md +7 -0
- fortune_telling_core-0.1.0/docs/api/core.md +6 -0
- fortune_telling_core-0.1.0/docs/api/traditions/astrology.md +29 -0
- fortune_telling_core-0.1.0/docs/api/traditions/four_pillars.md +34 -0
- fortune_telling_core-0.1.0/docs/api/traditions/nine_star_ki.md +48 -0
- fortune_telling_core-0.1.0/docs/api/traditions/tarot.md +20 -0
- fortune_telling_core-0.1.0/docs/index.md +57 -0
- fortune_telling_core-0.1.0/mkdocs.yml +60 -0
- fortune_telling_core-0.1.0/pyproject.toml +95 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/__init__.py +69 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/_null_rng.py +21 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/_parsing.py +45 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/_time.py +24 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/__init__.py +69 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/bodies.py +31 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/deltat.py +41 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/ephemeris/__init__.py +7 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/ephemeris/builtin.py +369 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/ephemeris/builtin_series.py +5879 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/ephemeris/fixed.py +65 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/ephemeris/protocol.py +40 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/errors.py +11 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/julian.py +74 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/nutation.py +59 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/position.py +58 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/solar.py +110 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/solar_terms.py +114 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/astronomy/time_model.py +55 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/cli.py +236 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/coerce.py +83 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/draw.py +146 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/engine.py +168 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/errors.py +21 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/provenance.py +92 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/reading.py +135 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/request.py +141 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/rng.py +207 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/serde.py +49 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/serde_types.py +9 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/spread.py +129 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/symbols.py +174 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/__init__.py +4 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/__init__.py +58 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/_julian.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/angles.py +55 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/aspects.py +67 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ayanamsa.py +13 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/birth.py +79 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/bodies.py +50 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/chart.py +79 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/config.py +36 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/deltat.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/engine.py +186 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ephemeris/__init__.py +7 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ephemeris/builtin.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ephemeris/builtin_series.py +29 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ephemeris/fixed.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/ephemeris/protocol.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/errors.py +15 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/houses.py +190 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/nutation.py +9 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/positions.py +83 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/sidereal.py +11 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/spreads.py +17 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/astrology/zodiac.py +41 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/__init__.py +43 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/birth.py +54 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/chart.py +82 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/config.py +37 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/deck.py +36 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/engine.py +236 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/luck.py +47 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/pillars.py +88 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/sexagenary.py +40 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/solar_terms.py +26 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/spreads.py +18 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/stems_branches.py +74 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/ten_gods.py +93 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/four_pillars/time_model.py +5 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/__init__.py +49 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/birth.py +47 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/chart.py +53 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/config.py +21 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/deck.py +24 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/engine.py +214 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/lo_shu.py +25 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/spreads.py +14 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/star_calc.py +192 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/nine_star_ki/stars.py +45 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/tarot/__init__.py +26 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/tarot/cards.py +74 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/tarot/engine.py +119 -0
- fortune_telling_core-0.1.0/src/fortune_telling_core/traditions/tarot/spreads.py +25 -0
- fortune_telling_core-0.1.0/tests/astronomy/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/astronomy/test_builtin_ephemeris_accuracy.py +70 -0
- fortune_telling_core-0.1.0/tests/astronomy/test_builtin_series_generation.py +44 -0
- fortune_telling_core-0.1.0/tests/astronomy/test_julian_solar.py +46 -0
- fortune_telling_core-0.1.0/tests/astronomy/test_solar_terms.py +49 -0
- fortune_telling_core-0.1.0/tests/astronomy/test_time_model.py +46 -0
- fortune_telling_core-0.1.0/tests/core/test_draw.py +31 -0
- fortune_telling_core-0.1.0/tests/core/test_schema_version.py +38 -0
- fortune_telling_core-0.1.0/tests/core/test_serde_roundtrip.py +60 -0
- fortune_telling_core-0.1.0/tests/core/test_symbols_spread.py +49 -0
- fortune_telling_core-0.1.0/tests/test_cli.py +45 -0
- fortune_telling_core-0.1.0/tests/test_package.py +5 -0
- fortune_telling_core-0.1.0/tests/test_rng.py +31 -0
- fortune_telling_core-0.1.0/tests/test_summary_contract.py +107 -0
- fortune_telling_core-0.1.0/tests/traditions/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/test_cast_replay.py +111 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/test_ephemeris.py +23 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/test_houses.py +143 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/test_sidereal_and_leakage.py +62 -0
- fortune_telling_core-0.1.0/tests/traditions/astrology/test_zodiac_spread.py +16 -0
- fortune_telling_core-0.1.0/tests/traditions/four_pillars/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/traditions/four_pillars/test_cast_replay.py +121 -0
- fortune_telling_core-0.1.0/tests/traditions/four_pillars/test_data.py +21 -0
- fortune_telling_core-0.1.0/tests/traditions/four_pillars/test_rules.py +32 -0
- fortune_telling_core-0.1.0/tests/traditions/nine_star_ki/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/traditions/nine_star_ki/test_data_calc.py +118 -0
- fortune_telling_core-0.1.0/tests/traditions/nine_star_ki/test_engine.py +141 -0
- fortune_telling_core-0.1.0/tests/traditions/tarot/__init__.py +1 -0
- fortune_telling_core-0.1.0/tests/traditions/tarot/test_deck.py +16 -0
- fortune_telling_core-0.1.0/tests/traditions/tarot/test_determinism.py +24 -0
- fortune_telling_core-0.1.0/tests/traditions/tarot/test_replay.py +31 -0
- fortune_telling_core-0.1.0/tests/traditions/tarot/test_reversals.py +30 -0
- fortune_telling_core-0.1.0/tools/ephemeris/download_vsop87d.py +70 -0
- fortune_telling_core-0.1.0/tools/ephemeris/generate_builtin_series.py +244 -0
- fortune_telling_core-0.1.0/tools/ephemeris/sources/MANIFEST.sha256 +15 -0
- fortune_telling_core-0.1.0/tools/ephemeris/sources/README.md +32 -0
- fortune_telling_core-0.1.0/tools/ephemeris/sources/meeus_tables.py +318 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CD
|
|
2
|
+
|
|
3
|
+
# Publish to PyPI on a published GitHub Release using PyPI Trusted Publishing
|
|
4
|
+
# (OIDC). No long-lived API token is stored: the publish job exchanges a
|
|
5
|
+
# short-lived GitHub OIDC token for a PyPI upload credential. Configure the
|
|
6
|
+
# trusted publisher once at https://pypi.org/manage/account/publishing/ with:
|
|
7
|
+
# owner: moriyoshi repository: fortune-telling-core
|
|
8
|
+
# workflow: cd.yml environment: pypi
|
|
9
|
+
on:
|
|
10
|
+
release:
|
|
11
|
+
types: [published]
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build distributions
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout
|
|
22
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
23
|
+
with:
|
|
24
|
+
# hatch-vcs derives the package version from tags, so fetch full
|
|
25
|
+
# history and tags rather than a shallow checkout.
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
|
|
28
|
+
- name: Set up Python
|
|
29
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
|
|
33
|
+
- name: Install release dependencies
|
|
34
|
+
run: python -m pip install --upgrade ".[release]"
|
|
35
|
+
|
|
36
|
+
- name: Build sdist + wheel
|
|
37
|
+
run: python -m build
|
|
38
|
+
|
|
39
|
+
- name: Check distributions
|
|
40
|
+
run: |
|
|
41
|
+
python -m twine check dist/*
|
|
42
|
+
|
|
43
|
+
- name: Upload distributions
|
|
44
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
if-no-files-found: error
|
|
49
|
+
|
|
50
|
+
publish:
|
|
51
|
+
name: Publish to PyPI
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/p/fortune-telling-core
|
|
57
|
+
permissions:
|
|
58
|
+
id-token: write # OIDC token for PyPI Trusted Publishing
|
|
59
|
+
steps:
|
|
60
|
+
- name: Download distributions
|
|
61
|
+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
62
|
+
with:
|
|
63
|
+
name: dist
|
|
64
|
+
path: dist/
|
|
65
|
+
|
|
66
|
+
- name: Publish
|
|
67
|
+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
# Cancel superseded runs on the same ref to save CI minutes.
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
check:
|
|
19
|
+
name: lint + type-check + test (py${{ matrix.python-version }})
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout
|
|
27
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
28
|
+
|
|
29
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
30
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python-version }}
|
|
33
|
+
cache: pip
|
|
34
|
+
cache-dependency-path: pyproject.toml
|
|
35
|
+
|
|
36
|
+
- name: Install
|
|
37
|
+
run: python -m pip install -e ".[dev]"
|
|
38
|
+
|
|
39
|
+
- name: Format check (ruff)
|
|
40
|
+
run: python -m ruff format --check .
|
|
41
|
+
|
|
42
|
+
- name: Lint (ruff)
|
|
43
|
+
run: python -m ruff check --output-format=github .
|
|
44
|
+
|
|
45
|
+
- name: Type-check (mypy)
|
|
46
|
+
run: python -m mypy src tests
|
|
47
|
+
|
|
48
|
+
- name: Test (pytest)
|
|
49
|
+
run: python -m pytest
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
# Build the MkDocs site and deploy to GitHub Pages. Deployment uses the GitHub
|
|
4
|
+
# Pages OIDC flow (id-token: write) rather than pushing to a gh-pages branch.
|
|
5
|
+
# Enable once under repository Settings -> Pages -> Build and deployment ->
|
|
6
|
+
# Source: GitHub Actions.
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
paths:
|
|
11
|
+
- "docs/**"
|
|
12
|
+
- "src/**"
|
|
13
|
+
- "mkdocs.yml"
|
|
14
|
+
- "pyproject.toml"
|
|
15
|
+
- ".github/workflows/docs.yml"
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
# Cancel superseded runs, but let an in-progress deployment finish.
|
|
19
|
+
concurrency:
|
|
20
|
+
group: pages
|
|
21
|
+
cancel-in-progress: false
|
|
22
|
+
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
build:
|
|
28
|
+
name: Build site
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout
|
|
32
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.12"
|
|
38
|
+
cache: pip
|
|
39
|
+
cache-dependency-path: pyproject.toml
|
|
40
|
+
|
|
41
|
+
- name: Install
|
|
42
|
+
run: python -m pip install -e ".[docs]"
|
|
43
|
+
|
|
44
|
+
- name: Build (strict)
|
|
45
|
+
run: mkdocs build --strict
|
|
46
|
+
|
|
47
|
+
- name: Configure Pages
|
|
48
|
+
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
|
49
|
+
|
|
50
|
+
- name: Upload Pages artifact
|
|
51
|
+
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
52
|
+
with:
|
|
53
|
+
path: site
|
|
54
|
+
|
|
55
|
+
deploy:
|
|
56
|
+
name: Deploy to Pages
|
|
57
|
+
needs: build
|
|
58
|
+
# Only publish from the default branch, not from manual runs on other refs.
|
|
59
|
+
if: github.ref == 'refs/heads/main'
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment:
|
|
62
|
+
name: github-pages
|
|
63
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
64
|
+
permissions:
|
|
65
|
+
pages: write # publish to GitHub Pages
|
|
66
|
+
id-token: write # OIDC verification of the deployment origin
|
|
67
|
+
steps:
|
|
68
|
+
- name: Deploy
|
|
69
|
+
id: deployment
|
|
70
|
+
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.agents-workspace/
|
|
2
|
+
.cache/
|
|
3
|
+
.venv/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.mypy_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
coverage/
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
site/
|
|
15
|
+
.env
|
|
16
|
+
.env.*
|
|
17
|
+
!.env.example
|
|
18
|
+
*.swp
|
|
19
|
+
*.swo
|
|
20
|
+
.DS_Store
|
|
21
|
+
Thumbs.db
|
|
22
|
+
__MACOSX
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Documents for both humans and coding agents
|
|
2
|
+
|
|
3
|
+
* [README.md](./README.md)
|
|
4
|
+
|
|
5
|
+
# Documents for coding agents
|
|
6
|
+
|
|
7
|
+
* [./.agents/docs/OVERVIEW.md](./.agents/docs/OVERVIEW.md) ... project overview.
|
|
8
|
+
* [./.agents/docs/ARCHITECTURE.md](./.agents/docs/ARCHITECTURE.md) ... library structure and design notes.
|
|
9
|
+
* [./.agents/docs/JOURNAL.md](./.agents/docs/JOURNAL.md) ... chronological findings, decisions, and work history.
|
|
10
|
+
* [./.agents/docs/LTM/INDEX.md](./.agents/docs/LTM/INDEX.md) ... long-term memory index for durable project knowledge under `./.agents/docs/LTM/`.
|
|
11
|
+
* [./.agents/docs/TODO.md](./.agents/docs/TODO.md) ... open to-do items, including the current implementation handoff: extract shared solar-term/time-model code into `astronomy`, then build the Nine Star Ki backend per the `JOURNAL.md` 2026-06-12 Nine Star Ki design entry.
|
|
12
|
+
* [./.agents/skills/](./.agents/skills/) ... local memory-maintenance skills for consolidating `JOURNAL.md`, LTM documents, and canonical project docs.
|
|
13
|
+
|
|
14
|
+
# Rules and protocols
|
|
15
|
+
|
|
16
|
+
## General
|
|
17
|
+
|
|
18
|
+
* This repository is the home for `fortune-telling-core`, a Python library for composable fortune-telling systems.
|
|
19
|
+
* Keep project knowledge in the agent docs as the implementation evolves.
|
|
20
|
+
* Prefer existing project patterns over introducing new frameworks or conventions.
|
|
21
|
+
* Keep the core library deterministic, typed, and testable. Randomness should be injectable so readings can be reproduced.
|
|
22
|
+
* Do not bake spiritual, cultural, or localisation assumptions into shared primitives. Model traditions and interpretation systems as explicit modules.
|
|
23
|
+
* When a design decision is genuinely ambiguous because established schools or conventions diverge (for example the Nine Star Ki day-star escapement, a house system, or a zodiac/ayanamsa choice), expose it as a configurable option (a config enum, engine argument, or request option) with a sensible documented default, rather than hardcoding one choice. Record the selected value in `Provenance.notes` so a reading stays reproducible and auditable. Use judgement: reserve options for genuine divergence, not every default, to avoid option sprawl.
|
|
24
|
+
* When a durable decision, pitfall, or investigation result matters to future work, append it to `.agents/docs/JOURNAL.md`.
|
|
25
|
+
|
|
26
|
+
## File Management
|
|
27
|
+
|
|
28
|
+
* Work summaries belong under `./.agents/docs`, not under `/tmp`.
|
|
29
|
+
* Temporary files belong under `./.agents-workspace/tmp`, not under `/tmp`.
|
|
30
|
+
* Never delete user files without permission. Only safe to delete: files you created in the current session under `./.agents-workspace/tmp/`.
|
|
31
|
+
* Keep generated scratch artefacts out of source directories unless they are part of the requested deliverable.
|
|
32
|
+
|
|
33
|
+
## Building and Testing
|
|
34
|
+
|
|
35
|
+
* The project stack is Python 3.12+ with a `src/` package layout.
|
|
36
|
+
* When fixing a bug, add a focused regression test whenever the codebase has a practical test harness.
|
|
37
|
+
* Do not report a change as complete until the relevant checks have been run, or until you explicitly state why they could not be run.
|
|
38
|
+
|
|
39
|
+
## Local Lint Gate
|
|
40
|
+
|
|
41
|
+
Before reporting a code change as done, run the project's canonical formatter, linter, type-checker, and tests once those commands exist. Record the current commands in this section when the stack is expanded.
|
|
42
|
+
|
|
43
|
+
Current stack: Python package with `pyproject.toml`, `src/fortune_telling_core`, and `tests`.
|
|
44
|
+
|
|
45
|
+
Always use the project virtualenv at `./.venv` for Python tooling. The bare `python`/`pip` on `PATH` resolves to the pyenv-global interpreter, **not** the venv, so activate the venv (`source .venv/bin/activate`) or call the venv binaries explicitly (`./.venv/bin/python`, `./.venv/bin/pip`). Never `pip install` into the global/pyenv interpreter — this includes `build`, `twine`, `mkdocs`, and the `.[dev]`/`.[docs]`/`.[release]` extras.
|
|
46
|
+
|
|
47
|
+
Canonical commands (run after `source .venv/bin/activate`, or prefix each with `./.venv/bin/`):
|
|
48
|
+
|
|
49
|
+
* Create the virtual environment: `python3 -m venv .venv`
|
|
50
|
+
* Activate it: `source .venv/bin/activate`
|
|
51
|
+
* Install for development: `python -m pip install -e ".[dev]"`
|
|
52
|
+
* Format: `python -m ruff format .`
|
|
53
|
+
* Lint: `python -m ruff check .`
|
|
54
|
+
* Type-check: `python -m mypy src tests`
|
|
55
|
+
* Test: `python -m pytest`
|
|
56
|
+
|
|
57
|
+
The library supports Python 3.12, 3.13, and 3.14. A Hatch matrix runs the suite (and full gate) against each:
|
|
58
|
+
|
|
59
|
+
* All versions, tests only: `hatch run test:run`
|
|
60
|
+
* All versions, full gate (ruff + mypy + pytest): `hatch run test:check`
|
|
61
|
+
* A single version: `hatch run +py=3.14 test:run`
|
|
62
|
+
|
|
63
|
+
Before reporting a change that could affect cross-version behaviour as done, run `hatch run test:check` so all three interpreters are exercised.
|
|
64
|
+
|
|
65
|
+
## Shell Pitfalls (prezto defaults)
|
|
66
|
+
|
|
67
|
+
The user's shell uses prezto, which sets aliases and options that can break non-interactive scripts:
|
|
68
|
+
|
|
69
|
+
* `cp src dst` may prompt interactively when `dst` exists. Prefer explicit overwrite-safe commands.
|
|
70
|
+
* `cat > file <<'EOF'` and `echo > file` can fail with `file exists` when the target exists. Use the repository editing tools rather than shell redirection for tracked files.
|
|
71
|
+
* `rm file` may prompt for confirmation. Never delete user files unless the task explicitly requires it.
|
|
72
|
+
|
|
73
|
+
## Git Workflow
|
|
74
|
+
|
|
75
|
+
* Never make discretionary commits. Commit only when the user asks.
|
|
76
|
+
* If commits are requested, sign them with `-S` unless the user gives different instructions.
|
|
77
|
+
* Preserve unrelated work in the tree. Do not revert changes you did not make.
|
|
78
|
+
|
|
79
|
+
## Documentation
|
|
80
|
+
|
|
81
|
+
* Append new findings to `JOURNAL.md`; do not edit existing entries in place except through established memory-consolidation workflows.
|
|
82
|
+
* In repo-authored documentation (`AGENTS.md`, `README.md`, `.agents/docs/**`), never use full-width parentheses. Use half-width parentheses.
|
|
83
|
+
* Same for full-width colons. Use a half-width colon followed by a space.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
- 2026-06-12: Split interpreter packaging prep: made core packages pkgutil namespaces and promoted coerce/serde_types helper modules for external namespace contributors.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 moriyoshi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fortune-telling-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Composable, reproducible primitives for fortune-telling systems.
|
|
5
|
+
Author-email: Moriyoshi Koizumi <mozo@mozo.jp>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: astrology,divination,fortune-telling,numerology,tarot
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: mypy>=2.1; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=9.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff>=0.15; extra == 'dev'
|
|
22
|
+
Requires-Dist: twine>=6.2; extra == 'dev'
|
|
23
|
+
Provides-Extra: docs
|
|
24
|
+
Requires-Dist: mkdocs-material>=9.7; extra == 'docs'
|
|
25
|
+
Requires-Dist: mkdocs>=1.6.1; extra == 'docs'
|
|
26
|
+
Requires-Dist: mkdocstrings[python]>=1.0; extra == 'docs'
|
|
27
|
+
Requires-Dist: ruff>=0.15; extra == 'docs'
|
|
28
|
+
Provides-Extra: release
|
|
29
|
+
Requires-Dist: build>=1.3; extra == 'release'
|
|
30
|
+
Requires-Dist: twine>=6.2; extra == 'release'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# fortune-telling-core
|
|
34
|
+
|
|
35
|
+
`fortune-telling-core` is a composable, reproducible Python library for building
|
|
36
|
+
fortune-telling and divination systems. It provides a small, deterministic, typed core of
|
|
37
|
+
primitives for readings, symbols, spreads, draws, structural summaries, and provenance, with
|
|
38
|
+
tradition-specific engines layered on top.
|
|
39
|
+
|
|
40
|
+
## Design Principles
|
|
41
|
+
|
|
42
|
+
- **Deterministic and reproducible.** Randomness enters through one narrow `Rng` protocol,
|
|
43
|
+
and every reading records the exact `Draw` that produced it. A recorded draw can be
|
|
44
|
+
replayed without any randomness.
|
|
45
|
+
- **Tradition-agnostic core.** The core knows only symbols, positions, selections,
|
|
46
|
+
deterministic summaries, and audit metadata. Tradition modules live behind their own
|
|
47
|
+
packages and are not re-exported from the top-level package.
|
|
48
|
+
- **Interpretation belongs to harnesses.** Discretionary meanings, localisation, and
|
|
49
|
+
presentation copy are intentionally outside the library. Consumers can map stable
|
|
50
|
+
symbol ids, position ids, modifiers, summaries, and provenance into their own
|
|
51
|
+
interpretation layer.
|
|
52
|
+
- **Configurable where schools diverge.** Where established schools or conventions
|
|
53
|
+
disagree, such as house systems, zodiac/ayanamsa, time models, or the Nine Star Ki
|
|
54
|
+
day-star escapement, the choice is a documented option recorded in reading provenance.
|
|
55
|
+
|
|
56
|
+
## Included Systems
|
|
57
|
+
|
|
58
|
+
- **Core**: Tradition-neutral value types, engine contracts, replay, serialisation, and
|
|
59
|
+
provenance.
|
|
60
|
+
- **Astronomy**: Shared, dependency-free astronomy including Julian-day helpers, solar
|
|
61
|
+
terms, time models, the `Ephemeris` protocol, and a pure-Python `BuiltinEphemeris`.
|
|
62
|
+
- **Traditions**: `tarot`, `astrology`, `four_pillars` (BaZi), and `nine_star_ki`.
|
|
63
|
+
Each tradition exposes its engine and deck/spread data from its own subpackage.
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from fortune_telling_core import RandomRng, ReadingRequest, reading_to_json
|
|
69
|
+
from fortune_telling_core.traditions.tarot import RWS_DECK, SINGLE_CARD, build_engine
|
|
70
|
+
|
|
71
|
+
engine = build_engine()
|
|
72
|
+
request = ReadingRequest(
|
|
73
|
+
deck_id=RWS_DECK.id,
|
|
74
|
+
spread_id=SINGLE_CARD.id,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
reading = engine.read(request, rng=RandomRng(seed=42))
|
|
78
|
+
payload = reading_to_json(reading)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Computed traditions use `cast()` instead of caller-provided randomness:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from fortune_telling_core import Querent, ReadingRequest
|
|
85
|
+
from fortune_telling_core.traditions.nine_star_ki import (
|
|
86
|
+
NINE_STAR_KI_DECK,
|
|
87
|
+
NINE_STAR_KI_SPREAD,
|
|
88
|
+
build_engine,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
engine = build_engine()
|
|
92
|
+
request = ReadingRequest(
|
|
93
|
+
deck_id=NINE_STAR_KI_DECK.id,
|
|
94
|
+
spread_id=NINE_STAR_KI_SPREAD.id,
|
|
95
|
+
querent=Querent(
|
|
96
|
+
id="example",
|
|
97
|
+
display_name="Example",
|
|
98
|
+
attributes={
|
|
99
|
+
"birth_datetime": "1990-05-17T09:30:00+09:00",
|
|
100
|
+
"latitude": "35.6895",
|
|
101
|
+
"longitude": "139.6917",
|
|
102
|
+
},
|
|
103
|
+
),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
reading = engine.cast(request)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Layout
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
.
|
|
113
|
+
├── AGENTS.md
|
|
114
|
+
├── README.md
|
|
115
|
+
├── pyproject.toml
|
|
116
|
+
├── src/
|
|
117
|
+
│ └── fortune_telling_core/
|
|
118
|
+
├── docs/
|
|
119
|
+
├── tests/
|
|
120
|
+
├── tools/
|
|
121
|
+
└── .agents/
|
|
122
|
+
└── docs/
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Development
|
|
126
|
+
|
|
127
|
+
This repository uses a `src/` Python package layout.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python3 -m venv .venv
|
|
131
|
+
source .venv/bin/activate
|
|
132
|
+
python -m pip install -e ".[dev]"
|
|
133
|
+
python -m pytest
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Run the deterministic demo CLI:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
fortune-telling-demo all
|
|
140
|
+
fortune-telling-demo tarot --seed 7
|
|
141
|
+
fortune-telling-demo nine-star-ki --json --target-year 2026
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
For computed demos, a `--birth-datetime` without a timezone is interpreted in
|
|
145
|
+
the terminal timezone and serialized with an offset.
|
|
146
|
+
|
|
147
|
+
Build or serve the API documentation:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
python -m pip install -e ".[docs]"
|
|
151
|
+
mkdocs serve
|
|
152
|
+
mkdocs build --strict
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Regenerate the built-in ephemeris series only when changing source tables or
|
|
156
|
+
the truncation threshold. The large public VSOP87D source files are downloaded
|
|
157
|
+
into `.cache/ephemeris/vsop87d/`, an ignored local cache outside `tools/`, and
|
|
158
|
+
verified by checksum:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
python tools/ephemeris/generate_builtin_series.py --download-missing
|
|
162
|
+
python tools/ephemeris/generate_builtin_series.py --check --download-missing
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Canonical agent-facing project notes live in `.agents/docs/`.
|
|
166
|
+
|
|
167
|
+
## Licence and Dependencies
|
|
168
|
+
|
|
169
|
+
`fortune-telling-core` is MIT licensed and is intended to remain zero-copyleft. The required runtime dependency set is empty.
|
|
170
|
+
|
|
171
|
+
Higher-precision astronomy is bring-your-own through the injectable `Ephemeris` Protocol. Consumers own the licensing review for any ephemeris backend they provide.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# fortune-telling-core
|
|
2
|
+
|
|
3
|
+
`fortune-telling-core` is a composable, reproducible Python library for building
|
|
4
|
+
fortune-telling and divination systems. It provides a small, deterministic, typed core of
|
|
5
|
+
primitives for readings, symbols, spreads, draws, structural summaries, and provenance, with
|
|
6
|
+
tradition-specific engines layered on top.
|
|
7
|
+
|
|
8
|
+
## Design Principles
|
|
9
|
+
|
|
10
|
+
- **Deterministic and reproducible.** Randomness enters through one narrow `Rng` protocol,
|
|
11
|
+
and every reading records the exact `Draw` that produced it. A recorded draw can be
|
|
12
|
+
replayed without any randomness.
|
|
13
|
+
- **Tradition-agnostic core.** The core knows only symbols, positions, selections,
|
|
14
|
+
deterministic summaries, and audit metadata. Tradition modules live behind their own
|
|
15
|
+
packages and are not re-exported from the top-level package.
|
|
16
|
+
- **Interpretation belongs to harnesses.** Discretionary meanings, localisation, and
|
|
17
|
+
presentation copy are intentionally outside the library. Consumers can map stable
|
|
18
|
+
symbol ids, position ids, modifiers, summaries, and provenance into their own
|
|
19
|
+
interpretation layer.
|
|
20
|
+
- **Configurable where schools diverge.** Where established schools or conventions
|
|
21
|
+
disagree, such as house systems, zodiac/ayanamsa, time models, or the Nine Star Ki
|
|
22
|
+
day-star escapement, the choice is a documented option recorded in reading provenance.
|
|
23
|
+
|
|
24
|
+
## Included Systems
|
|
25
|
+
|
|
26
|
+
- **Core**: Tradition-neutral value types, engine contracts, replay, serialisation, and
|
|
27
|
+
provenance.
|
|
28
|
+
- **Astronomy**: Shared, dependency-free astronomy including Julian-day helpers, solar
|
|
29
|
+
terms, time models, the `Ephemeris` protocol, and a pure-Python `BuiltinEphemeris`.
|
|
30
|
+
- **Traditions**: `tarot`, `astrology`, `four_pillars` (BaZi), and `nine_star_ki`.
|
|
31
|
+
Each tradition exposes its engine and deck/spread data from its own subpackage.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from fortune_telling_core import RandomRng, ReadingRequest, reading_to_json
|
|
37
|
+
from fortune_telling_core.traditions.tarot import RWS_DECK, SINGLE_CARD, build_engine
|
|
38
|
+
|
|
39
|
+
engine = build_engine()
|
|
40
|
+
request = ReadingRequest(
|
|
41
|
+
deck_id=RWS_DECK.id,
|
|
42
|
+
spread_id=SINGLE_CARD.id,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
reading = engine.read(request, rng=RandomRng(seed=42))
|
|
46
|
+
payload = reading_to_json(reading)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Computed traditions use `cast()` instead of caller-provided randomness:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from fortune_telling_core import Querent, ReadingRequest
|
|
53
|
+
from fortune_telling_core.traditions.nine_star_ki import (
|
|
54
|
+
NINE_STAR_KI_DECK,
|
|
55
|
+
NINE_STAR_KI_SPREAD,
|
|
56
|
+
build_engine,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
engine = build_engine()
|
|
60
|
+
request = ReadingRequest(
|
|
61
|
+
deck_id=NINE_STAR_KI_DECK.id,
|
|
62
|
+
spread_id=NINE_STAR_KI_SPREAD.id,
|
|
63
|
+
querent=Querent(
|
|
64
|
+
id="example",
|
|
65
|
+
display_name="Example",
|
|
66
|
+
attributes={
|
|
67
|
+
"birth_datetime": "1990-05-17T09:30:00+09:00",
|
|
68
|
+
"latitude": "35.6895",
|
|
69
|
+
"longitude": "139.6917",
|
|
70
|
+
},
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
reading = engine.cast(request)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Layout
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
.
|
|
81
|
+
├── AGENTS.md
|
|
82
|
+
├── README.md
|
|
83
|
+
├── pyproject.toml
|
|
84
|
+
├── src/
|
|
85
|
+
│ └── fortune_telling_core/
|
|
86
|
+
├── docs/
|
|
87
|
+
├── tests/
|
|
88
|
+
├── tools/
|
|
89
|
+
└── .agents/
|
|
90
|
+
└── docs/
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
This repository uses a `src/` Python package layout.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python3 -m venv .venv
|
|
99
|
+
source .venv/bin/activate
|
|
100
|
+
python -m pip install -e ".[dev]"
|
|
101
|
+
python -m pytest
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Run the deterministic demo CLI:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
fortune-telling-demo all
|
|
108
|
+
fortune-telling-demo tarot --seed 7
|
|
109
|
+
fortune-telling-demo nine-star-ki --json --target-year 2026
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For computed demos, a `--birth-datetime` without a timezone is interpreted in
|
|
113
|
+
the terminal timezone and serialized with an offset.
|
|
114
|
+
|
|
115
|
+
Build or serve the API documentation:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
python -m pip install -e ".[docs]"
|
|
119
|
+
mkdocs serve
|
|
120
|
+
mkdocs build --strict
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Regenerate the built-in ephemeris series only when changing source tables or
|
|
124
|
+
the truncation threshold. The large public VSOP87D source files are downloaded
|
|
125
|
+
into `.cache/ephemeris/vsop87d/`, an ignored local cache outside `tools/`, and
|
|
126
|
+
verified by checksum:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
python tools/ephemeris/generate_builtin_series.py --download-missing
|
|
130
|
+
python tools/ephemeris/generate_builtin_series.py --check --download-missing
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Canonical agent-facing project notes live in `.agents/docs/`.
|
|
134
|
+
|
|
135
|
+
## Licence and Dependencies
|
|
136
|
+
|
|
137
|
+
`fortune-telling-core` is MIT licensed and is intended to remain zero-copyleft. The required runtime dependency set is empty.
|
|
138
|
+
|
|
139
|
+
Higher-precision astronomy is bring-your-own through the injectable `Ephemeris` Protocol. Consumers own the licensing review for any ephemeris backend they provide.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Astronomy
|
|
2
|
+
|
|
3
|
+
Shared, tradition-neutral astronomy used by the computed traditions: Julian-day and delta-T
|
|
4
|
+
conversion, nutation, solar terms, the time-model helpers, and the injectable `Ephemeris` protocol
|
|
5
|
+
with its pure-Python `BuiltinEphemeris` (and `FixedEphemeris` test stub).
|
|
6
|
+
|
|
7
|
+
::: fortune_telling_core.astronomy
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Astrology
|
|
2
|
+
|
|
3
|
+
A natal-chart engine: tropical or sidereal zodiac, ten planets plus the lunar nodes and the
|
|
4
|
+
Ascendant/Midheaven, Whole Sign / Equal / Placidus houses, and aspects rendered into the summary.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from fortune_telling_core import Querent, ReadingRequest
|
|
8
|
+
from fortune_telling_core.traditions.astrology import NATAL_CHART, TROPICAL_ZODIAC, build_engine
|
|
9
|
+
|
|
10
|
+
engine = build_engine()
|
|
11
|
+
request = ReadingRequest(
|
|
12
|
+
deck_id=TROPICAL_ZODIAC.id,
|
|
13
|
+
spread_id=NATAL_CHART.id,
|
|
14
|
+
querent=Querent(
|
|
15
|
+
id="sample",
|
|
16
|
+
display_name="Sample",
|
|
17
|
+
attributes={
|
|
18
|
+
"birth_datetime": "1990-01-01T12:00:00+00:00",
|
|
19
|
+
"latitude": "51.5074",
|
|
20
|
+
"longitude": "-0.1278",
|
|
21
|
+
"house_system": "whole_sign",
|
|
22
|
+
},
|
|
23
|
+
),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
reading = engine.cast(request)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
::: fortune_telling_core.traditions.astrology
|