timegym 1.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.
Files changed (186) hide show
  1. timegym-1.1.0/.dockerignore +12 -0
  2. timegym-1.1.0/.github/workflows/checks.yml +171 -0
  3. timegym-1.1.0/.github/workflows/claude-code-review.yml +45 -0
  4. timegym-1.1.0/.github/workflows/claude.yml +50 -0
  5. timegym-1.1.0/.github/workflows/compatibility-release.yml +47 -0
  6. timegym-1.1.0/.github/workflows/pages.yml +37 -0
  7. timegym-1.1.0/.github/workflows/python-compatibility.yml +64 -0
  8. timegym-1.1.0/.github/workflows/release.yml +89 -0
  9. timegym-1.1.0/AGENTS.md +62 -0
  10. timegym-1.1.0/CHANGELOG.md +87 -0
  11. timegym-1.1.0/CITATION.cff +34 -0
  12. timegym-1.1.0/Dockerfile +9 -0
  13. timegym-1.1.0/LICENSE +21 -0
  14. timegym-1.1.0/PKG-INFO +262 -0
  15. timegym-1.1.0/README.md +208 -0
  16. timegym-1.1.0/docs/api/data-preparation.md +100 -0
  17. timegym-1.1.0/docs/api/diagnostics.md +223 -0
  18. timegym-1.1.0/docs/api/fault-fixtures.md +28 -0
  19. timegym-1.1.0/docs/api/market-data.md +41 -0
  20. timegym-1.1.0/docs/api/models.md +42 -0
  21. timegym-1.1.0/docs/api/pipeline.md +95 -0
  22. timegym-1.1.0/docs/api/processes.md +144 -0
  23. timegym-1.1.0/docs/api/scenarios.md +69 -0
  24. timegym-1.1.0/docs/api/tasks-and-forecasts.md +23 -0
  25. timegym-1.1.0/docs/concepts/how-timegym-decides.md +149 -0
  26. timegym-1.1.0/docs/contributing.md +101 -0
  27. timegym-1.1.0/docs/notebooks.md +106 -0
  28. timegym-1.1.0/docs/reference.md +42 -0
  29. timegym-1.1.0/docs/release.md +160 -0
  30. timegym-1.1.0/docs/stress-cases.md +126 -0
  31. timegym-1.1.0/docs/stylesheets/extra.css +15 -0
  32. timegym-1.1.0/examples/README.md +24 -0
  33. timegym-1.1.0/examples/check_notebooks.py +6 -0
  34. timegym-1.1.0/examples/quickstart.py +11 -0
  35. timegym-1.1.0/examples/reproduce_report.py +40 -0
  36. timegym-1.1.0/experiments/README.md +153 -0
  37. timegym-1.1.0/experiments/__init__.py +1 -0
  38. timegym-1.1.0/experiments/common.py +65 -0
  39. timegym-1.1.0/experiments/compare_results.py +39 -0
  40. timegym-1.1.0/experiments/data/AirPassengers.csv +145 -0
  41. timegym-1.1.0/experiments/data/README.md +19 -0
  42. timegym-1.1.0/experiments/migrate_frozen.py +151 -0
  43. timegym-1.1.0/experiments/model_faults.py +132 -0
  44. timegym-1.1.0/experiments/protocol-v2.json +276 -0
  45. timegym-1.1.0/experiments/protocol.json +110 -0
  46. timegym-1.1.0/experiments/render_results.py +375 -0
  47. timegym-1.1.0/experiments/render_supplement.py +366 -0
  48. timegym-1.1.0/experiments/reproduce_fault.py +49 -0
  49. timegym-1.1.0/experiments/results/example-dependence_shuffle.json +130 -0
  50. timegym-1.1.0/experiments/results/example-index_shift.json +61 -0
  51. timegym-1.1.0/experiments/results/manifest.json +250 -0
  52. timegym-1.1.0/experiments/results/results.json +46707 -0
  53. timegym-1.1.0/experiments/results-v2/covariance-conditions.csv +13 -0
  54. timegym-1.1.0/experiments/results-v2/manifest.json +661 -0
  55. timegym-1.1.0/experiments/results-v2/model-ablation.csv +6 -0
  56. timegym-1.1.0/experiments/results-v2/model-conditions.csv +121 -0
  57. timegym-1.1.0/experiments/results-v2/model-repair-losses.csv +25 -0
  58. timegym-1.1.0/experiments/results-v2/results.json +66635 -0
  59. timegym-1.1.0/experiments/results-v2/runtime.json +11 -0
  60. timegym-1.1.0/experiments/run_study.py +278 -0
  61. timegym-1.1.0/experiments/run_supplement.py +379 -0
  62. timegym-1.1.0/mkdocs.yml +109 -0
  63. timegym-1.1.0/notebooks/00_quick_start.ipynb +245 -0
  64. timegym-1.1.0/notebooks/01_synthetic_data.ipynb +696 -0
  65. timegym-1.1.0/notebooks/02_real_data.ipynb +324 -0
  66. timegym-1.1.0/notebooks/03_smoothing.ipynb +333 -0
  67. timegym-1.1.0/notebooks/04_feature_engineering.ipynb +599 -0
  68. timegym-1.1.0/notebooks/05_target_engineering.ipynb +1096 -0
  69. timegym-1.1.0/notebooks/06_forecasting_models.ipynb +679 -0
  70. timegym-1.1.0/notebooks/07_pipeline.ipynb +734 -0
  71. timegym-1.1.0/notebooks/08_forecast_contracts.ipynb +851 -0
  72. timegym-1.1.0/notebooks/09_scores_and_diagnostics.ipynb +1409 -0
  73. timegym-1.1.0/notebooks/10_reports_and_replay.ipynb +850 -0
  74. timegym-1.1.0/notebooks/11_plotting.ipynb +629 -0
  75. timegym-1.1.0/notebooks/12_package.ipynb +428 -0
  76. timegym-1.1.0/notebooks/14_controlled_processes.ipynb +1407 -0
  77. timegym-1.1.0/notebooks/15_joint_processes.ipynb +617 -0
  78. timegym-1.1.0/notebooks/20_univariate_uncertainty.ipynb +1264 -0
  79. timegym-1.1.0/notebooks/21_multivariate_forecasting.ipynb +772 -0
  80. timegym-1.1.0/notebooks/22_multivariate_uncertainty.ipynb +1106 -0
  81. timegym-1.1.0/notebooks/23_faults_repairs_and_replay.ipynb +1264 -0
  82. timegym-1.1.0/notebooks/24_real_data_forecasts.ipynb +1212 -0
  83. timegym-1.1.0/notebooks/25_capability_sweeps.ipynb +1333 -0
  84. timegym-1.1.0/notebooks/26_composed_and_financial_stresses.ipynb +798 -0
  85. timegym-1.1.0/notebooks/27_joint_financial_uncertainty.ipynb +746 -0
  86. timegym-1.1.0/notebooks/28_custom_model.ipynb +1050 -0
  87. timegym-1.1.0/notebooks/29_target_transforms.ipynb +646 -0
  88. timegym-1.1.0/notebooks/30_reductions.ipynb +546 -0
  89. timegym-1.1.0/notebooks/README.md +131 -0
  90. timegym-1.1.0/notebooks/assets/README.md +17 -0
  91. timegym-1.1.0/notebooks/assets/alignment-demo.png +0 -0
  92. timegym-1.1.0/notebooks/assets/custom-model-knn.png +0 -0
  93. timegym-1.1.0/notebooks/assets/quick-start-matrix.png +0 -0
  94. timegym-1.1.0/notebooks/check_notebooks.py +123 -0
  95. timegym-1.1.0/notebooks/source-map.json +99 -0
  96. timegym-1.1.0/paper/README.md +99 -0
  97. timegym-1.1.0/paper/build_standalone.py +191 -0
  98. timegym-1.1.0/paper/claims.md +157 -0
  99. timegym-1.1.0/paper/figure_common.py +59 -0
  100. timegym-1.1.0/paper/figure_dependence.py +166 -0
  101. timegym-1.1.0/paper/figure_evidence.py +124 -0
  102. timegym-1.1.0/paper/figure_joint_stresses.py +86 -0
  103. timegym-1.1.0/paper/figure_matrix.py +81 -0
  104. timegym-1.1.0/paper/figure_stresses.py +140 -0
  105. timegym-1.1.0/paper/figures/capability-summary.csv +46 -0
  106. timegym-1.1.0/paper/figures/paper-dependence.tikz +187 -0
  107. timegym-1.1.0/paper/figures/paper-diagnostic-evidence.tikz +111 -0
  108. timegym-1.1.0/paper/figures/paper-figure-provenance.json +35072 -0
  109. timegym-1.1.0/paper/figures/paper-financial-stresses.tikz +1039 -0
  110. timegym-1.1.0/paper/figures/paper-forecast-matrix.tikz +1903 -0
  111. timegym-1.1.0/paper/figures/paper-joint-stresses.tikz +560 -0
  112. timegym-1.1.0/paper/generated-macros.tex +7 -0
  113. timegym-1.1.0/paper/generated-results.tex +125 -0
  114. timegym-1.1.0/paper/generated-supplement.tex +171 -0
  115. timegym-1.1.0/paper/main.tex +1151 -0
  116. timegym-1.1.0/paper/publication-strategy.md +22 -0
  117. timegym-1.1.0/paper/references.bib +570 -0
  118. timegym-1.1.0/paper/render_figures.py +40 -0
  119. timegym-1.1.0/paper/validation.md +111 -0
  120. timegym-1.1.0/paper/vector_canvas.py +148 -0
  121. timegym-1.1.0/pyproject.toml +44 -0
  122. timegym-1.1.0/requirements-study.txt +26 -0
  123. timegym-1.1.0/tests/test_contracts.py +185 -0
  124. timegym-1.1.0/tests/test_controlled_processes.py +415 -0
  125. timegym-1.1.0/tests/test_custom_model_tutorial.py +89 -0
  126. timegym-1.1.0/tests/test_diagnostics.py +383 -0
  127. timegym-1.1.0/tests/test_docs_catalogue.py +97 -0
  128. timegym-1.1.0/tests/test_docs_hooks.py +93 -0
  129. timegym-1.1.0/tests/test_docs_navigation.py +70 -0
  130. timegym-1.1.0/tests/test_experiment_pipeline.py +226 -0
  131. timegym-1.1.0/tests/test_internal.py +56 -0
  132. timegym-1.1.0/tests/test_joint_processes.py +355 -0
  133. timegym-1.1.0/tests/test_legacy_helpers.py +157 -0
  134. timegym-1.1.0/tests/test_metrics.py +119 -0
  135. timegym-1.1.0/tests/test_mutations.py +87 -0
  136. timegym-1.1.0/tests/test_notebook_build.py +217 -0
  137. timegym-1.1.0/tests/test_paper_build.py +94 -0
  138. timegym-1.1.0/tests/test_paper_figures.py +57 -0
  139. timegym-1.1.0/tests/test_pipeline.py +289 -0
  140. timegym-1.1.0/tests/test_plotting.py +274 -0
  141. timegym-1.1.0/tests/test_preprocessing.py +225 -0
  142. timegym-1.1.0/tests/test_process_integration.py +169 -0
  143. timegym-1.1.0/tests/test_python_support.py +56 -0
  144. timegym-1.1.0/tests/test_real_data.py +170 -0
  145. timegym-1.1.0/tests/test_reductions.py +165 -0
  146. timegym-1.1.0/tests/test_references.py +184 -0
  147. timegym-1.1.0/tests/test_release_metadata.py +41 -0
  148. timegym-1.1.0/tests/test_replay.py +276 -0
  149. timegym-1.1.0/tests/test_report_loading.py +218 -0
  150. timegym-1.1.0/tests/test_research_supplement.py +170 -0
  151. timegym-1.1.0/tests/test_scenario_labels.py +76 -0
  152. timegym-1.1.0/tests/test_simulation_reference.py +150 -0
  153. timegym-1.1.0/tests/test_statistics.py +29 -0
  154. timegym-1.1.0/tests/test_target_transforms.py +409 -0
  155. timegym-1.1.0/tests/test_user_reference.py +113 -0
  156. timegym-1.1.0/tests/test_validation_boundaries.py +107 -0
  157. timegym-1.1.0/timegym/__init__.py +37 -0
  158. timegym-1.1.0/timegym/_internal.py +94 -0
  159. timegym-1.1.0/timegym/_process_common.py +655 -0
  160. timegym-1.1.0/timegym/checks.py +68 -0
  161. timegym-1.1.0/timegym/contracts.py +578 -0
  162. timegym-1.1.0/timegym/data/real.py +121 -0
  163. timegym-1.1.0/timegym/data/synthetic.py +27 -0
  164. timegym-1.1.0/timegym/diagnostics.py +457 -0
  165. timegym-1.1.0/timegym/evaluation.py +75 -0
  166. timegym-1.1.0/timegym/features.py +223 -0
  167. timegym-1.1.0/timegym/joint_processes.py +439 -0
  168. timegym-1.1.0/timegym/metrics.py +201 -0
  169. timegym-1.1.0/timegym/models.py +419 -0
  170. timegym-1.1.0/timegym/mutations.py +180 -0
  171. timegym-1.1.0/timegym/pipeline.py +428 -0
  172. timegym-1.1.0/timegym/plotting.py +434 -0
  173. timegym-1.1.0/timegym/processes.py +536 -0
  174. timegym-1.1.0/timegym/provenance.py +241 -0
  175. timegym-1.1.0/timegym/reporting.py +330 -0
  176. timegym-1.1.0/timegym/scenarios.py +304 -0
  177. timegym-1.1.0/timegym/smoothing.py +75 -0
  178. timegym-1.1.0/timegym/statistics.py +46 -0
  179. timegym-1.1.0/timegym/target.py +531 -0
  180. timegym-1.1.0/tools/README.md +153 -0
  181. timegym-1.1.0/tools/check_site_links.py +67 -0
  182. timegym-1.1.0/tools/docs_hooks.py +125 -0
  183. timegym-1.1.0/tools/export_notebooks.py +296 -0
  184. timegym-1.1.0/tools/smoke_installed.py +99 -0
  185. timegym-1.1.0/tools/sync_citation.py +109 -0
  186. timegym-1.1.0/tools/update_python_support.py +128 -0
@@ -0,0 +1,12 @@
1
+ .git
2
+ .venv
3
+ __pycache__
4
+ **/__pycache__
5
+ .pytest_cache
6
+ .ipynb_checkpoints
7
+ **/.ipynb_checkpoints
8
+ dist
9
+ build
10
+ site
11
+ paper/build
12
+ .DS_Store
@@ -0,0 +1,171 @@
1
+ name: checks
2
+ on:
3
+ push:
4
+ branches: ['**']
5
+ pull_request:
6
+ workflow_call:
7
+ inputs:
8
+ ref:
9
+ type: string
10
+ required: false
11
+ permissions:
12
+ contents: read
13
+ concurrency:
14
+ group: checks-${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+ env:
17
+ MPLBACKEND: Agg
18
+ OPENBLAS_NUM_THREADS: '1'
19
+ OMP_NUM_THREADS: '1'
20
+ jobs:
21
+ source:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ ref: ${{ inputs.ref || github.sha }}
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: '3.15' # current-python
30
+ cache: pip
31
+ cache-dependency-path: |
32
+ pyproject.toml
33
+ requirements-study.txt
34
+ - run: python -m pip install -e '.[dev]'
35
+ - run: python tools/export_notebooks.py --check
36
+ - run: python paper/build_standalone.py --check
37
+ - run: python tools/sync_citation.py --check
38
+ test:
39
+ runs-on: ubuntu-latest
40
+ strategy:
41
+ matrix:
42
+ python-version: ['3.11', '3.12', '3.13', '3.14', '3.15']
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ with:
46
+ ref: ${{ inputs.ref || github.sha }}
47
+ - uses: actions/setup-python@v5
48
+ with:
49
+ python-version: ${{ matrix.python-version }}
50
+ cache: pip
51
+ cache-dependency-path: |
52
+ pyproject.toml
53
+ requirements-study.txt
54
+ - run: python -m pip install -e '.[dev]'
55
+ - run: python -m pytest
56
+ - run: python examples/quickstart.py
57
+ compatibility:
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ with:
62
+ ref: ${{ inputs.ref || github.sha }}
63
+ - uses: actions/setup-python@v5
64
+ with:
65
+ python-version: '3.12'
66
+ cache: pip
67
+ cache-dependency-path: |
68
+ pyproject.toml
69
+ requirements-study.txt
70
+ - run: python -m pip install -e '.[dev]' 'numpy==1.26.4' 'pandas==2.2.3' 'scipy==1.11.4' 'scikit-learn==1.4.2' 'matplotlib==3.8.4'
71
+ - run: python -m pytest
72
+ installed-wheel:
73
+ runs-on: ${{ matrix.os }}
74
+ strategy:
75
+ matrix:
76
+ os: [ubuntu-latest, macos-latest, windows-latest]
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+ with:
80
+ ref: ${{ inputs.ref || github.sha }}
81
+ - uses: actions/setup-python@v5
82
+ with:
83
+ python-version: '3.12'
84
+ cache: pip
85
+ cache-dependency-path: |
86
+ pyproject.toml
87
+ requirements-study.txt
88
+ - run: python -m pip install build 'twine>=6,<7'
89
+ - run: python -m build
90
+ - run: python -m twine check dist/*
91
+ - run: python -c "import glob, subprocess, sys; subprocess.check_call([sys.executable, '-m', 'pip', 'install', glob.glob('dist/*.whl')[0]])"
92
+ - run: python -I tools/smoke_installed.py --report wheel-report.json
93
+ - run: python -I examples/reproduce_report.py wheel-report.json --require-same-environment
94
+ - uses: actions/upload-artifact@v4
95
+ with:
96
+ name: distribution-${{ matrix.os }}
97
+ path: dist/*
98
+ documentation:
99
+ runs-on: ubuntu-latest
100
+ steps:
101
+ - uses: actions/checkout@v4
102
+ with:
103
+ ref: ${{ inputs.ref || github.sha }}
104
+ - uses: actions/setup-python@v5
105
+ with:
106
+ python-version: '3.15' # current-python
107
+ cache: pip
108
+ cache-dependency-path: |
109
+ pyproject.toml
110
+ requirements-study.txt
111
+ - run: python -m pip install -e '.[docs]' pytest
112
+ - run: python -m pytest -q tests/test_docs_hooks.py tests/test_docs_navigation.py
113
+ - run: python -m mkdocs build --strict
114
+ - run: python tools/check_site_links.py site
115
+ research-smoke:
116
+ runs-on: ubuntu-latest
117
+ steps:
118
+ - uses: actions/checkout@v4
119
+ with:
120
+ ref: ${{ inputs.ref || github.sha }}
121
+ - uses: actions/setup-python@v5
122
+ with:
123
+ python-version: '3.13'
124
+ cache: pip
125
+ cache-dependency-path: |
126
+ pyproject.toml
127
+ requirements-study.txt
128
+ - run: python -m pip install -r requirements-study.txt
129
+ - run: python -m pip install --no-build-isolation --no-deps -e .
130
+ - run: python -m experiments.run_study --output /tmp/timegym-study
131
+ - run: python -m experiments.run_supplement --output /tmp/timegym-supplement
132
+ - name: Compare numerical records with frozen hashes
133
+ run: |
134
+ python -m experiments.compare_results --results /tmp/timegym-study/results.json --manifest experiments/results/manifest.json --report /tmp/timegym-pilot-hash.json --warn
135
+ python -m experiments.compare_results --results /tmp/timegym-supplement/results.json --manifest experiments/results-v2/manifest.json --report /tmp/timegym-supplement-hash.json --warn
136
+ - uses: actions/upload-artifact@v4
137
+ with:
138
+ name: research-linux-hashes
139
+ path: /tmp/timegym-*-hash.json
140
+
141
+ notebooks:
142
+ runs-on: ubuntu-latest
143
+ steps:
144
+ - uses: actions/checkout@v4
145
+ with:
146
+ ref: ${{ inputs.ref || github.sha }}
147
+ - uses: actions/setup-python@v5
148
+ with:
149
+ python-version: '3.15' # current-python
150
+ cache: pip
151
+ cache-dependency-path: |
152
+ pyproject.toml
153
+ requirements-study.txt
154
+ - run: python -m pip install -e '.[notebooks]'
155
+ - run: python notebooks/check_notebooks.py
156
+ paper:
157
+ runs-on: ubuntu-latest
158
+ steps:
159
+ - uses: actions/checkout@v4
160
+ with:
161
+ ref: ${{ inputs.ref || github.sha }}
162
+ - name: Install LaTeX
163
+ # cm-super supplies Type 1 T1 fonts; without it Metafont bitmap fonts fail to build.
164
+ run: sudo apt-get update && sudo apt-get install -y --no-install-recommends latexmk texlive-latex-recommended texlive-pictures texlive-fonts-recommended cm-super
165
+ - name: Compile standalone manuscript
166
+ working-directory: paper
167
+ run: latexmk -pdf -interaction=nonstopmode -halt-on-error -outdir=build timegym.tex
168
+ - uses: actions/upload-artifact@v4
169
+ with:
170
+ name: paper-pdf
171
+ path: paper/build/timegym.pdf
@@ -0,0 +1,45 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, ready_for_review, reopened]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@v1
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
40
+ plugins: 'code-review@claude-code-plugins'
41
+ prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
42
+ claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment"'
43
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
44
+ # or https://code.claude.com/docs/en/cli-reference for available options
45
+
@@ -0,0 +1,50 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
49
+ # claude_args: '--allowed-tools Bash(gh pr *)'
50
+
@@ -0,0 +1,47 @@
1
+ name: Release merged Python compatibility update
2
+ on:
3
+ pull_request:
4
+ types: [closed]
5
+ permissions:
6
+ contents: read
7
+ jobs:
8
+ checks:
9
+ if: >-
10
+ github.event.pull_request.merged == true &&
11
+ github.event.pull_request.head.repo.full_name == github.repository &&
12
+ github.event.pull_request.base.ref == github.event.repository.default_branch &&
13
+ github.event.pull_request.head.ref == 'automation/python-compatibility' &&
14
+ contains(github.event.pull_request.labels.*.name, 'python-compatibility')
15
+ uses: ./.github/workflows/checks.yml
16
+ with:
17
+ ref: ${{ github.event.pull_request.merge_commit_sha }}
18
+ tag:
19
+ needs: checks
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: write
23
+ actions: write
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ with:
27
+ ref: ${{ github.event.pull_request.merge_commit_sha }}
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.15' # current-python
31
+ cache: pip
32
+ cache-dependency-path: pyproject.toml
33
+ - run: python -m pip install -e '.[release]'
34
+ - name: Validate and tag the new package version
35
+ env:
36
+ GH_TOKEN: ${{ github.token }}
37
+ RELEASE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
38
+ run: |
39
+ version=$(python -c 'from timegym import __version__; print(__version__)')
40
+ tag="v$version"
41
+ python tools/sync_citation.py --check --tag "$tag"
42
+ if gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$tag" >/dev/null 2>&1; then
43
+ echo "Tag $tag already exists; no publication requested."
44
+ exit 0
45
+ fi
46
+ gh api "repos/$GITHUB_REPOSITORY/git/refs" -f "ref=refs/tags/$tag" -f "sha=$RELEASE_SHA"
47
+ gh workflow run release.yml --ref "$tag"
@@ -0,0 +1,37 @@
1
+ name: docs site
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ pages: write
9
+ id-token: write
10
+ concurrency:
11
+ group: pages
12
+ cancel-in-progress: false
13
+ jobs:
14
+ build:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: '3.12'
21
+ cache: pip
22
+ cache-dependency-path: pyproject.toml
23
+ - run: python -m pip install -e '.[docs]'
24
+ - run: python -m mkdocs build --strict
25
+ - run: python tools/check_site_links.py site
26
+ - uses: actions/upload-pages-artifact@v3
27
+ with:
28
+ path: site
29
+ deploy:
30
+ needs: build
31
+ runs-on: ubuntu-latest
32
+ environment:
33
+ name: github-pages
34
+ url: ${{ steps.deployment.outputs.page_url }}
35
+ steps:
36
+ - id: deployment
37
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,64 @@
1
+ name: Python compatibility proposal
2
+ on:
3
+ schedule:
4
+ - cron: '23 7 * * 1'
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: write
8
+ pull-requests: write
9
+ concurrency:
10
+ group: python-compatibility-proposal
11
+ cancel-in-progress: false
12
+ jobs:
13
+ propose:
14
+ runs-on: ubuntu-latest
15
+ env:
16
+ MPLBACKEND: Agg
17
+ OPENBLAS_NUM_THREADS: '1'
18
+ OMP_NUM_THREADS: '1'
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.15' # current-python
24
+ cache: pip
25
+ cache-dependency-path: pyproject.toml
26
+ - run: python -m pip install packaging
27
+ - id: support
28
+ run: python tools/update_python_support.py --apply --github-output "$GITHUB_OUTPUT"
29
+ - uses: actions/setup-python@v5
30
+ if: steps.support.outputs.changed == 'true'
31
+ with:
32
+ python-version: ${{ steps.support.outputs.latest }}
33
+ cache: pip
34
+ cache-dependency-path: pyproject.toml
35
+ - if: steps.support.outputs.changed == 'true'
36
+ run: |
37
+ python -m pip install -e '.[dev,docs,release,notebooks]'
38
+ python tools/export_notebooks.py
39
+ python -m pip install --no-deps -e .
40
+ python tools/sync_citation.py
41
+ python paper/build_standalone.py
42
+ python tools/export_notebooks.py --check
43
+ python tools/sync_citation.py --check
44
+ python paper/build_standalone.py --check
45
+ python -m pytest -q
46
+ python notebooks/check_notebooks.py
47
+ python examples/quickstart.py
48
+ python -m mkdocs build --strict
49
+ python -m build
50
+ python -m twine check dist/*
51
+ docker build -t timegym-compatibility .
52
+ docker run --rm timegym-compatibility
53
+ - uses: peter-evans/create-pull-request@v7
54
+ if: steps.support.outputs.changed == 'true'
55
+ with:
56
+ branch: automation/python-compatibility
57
+ title: Update Python support following pandas
58
+ commit-message: Update Python support following pandas
59
+ labels: python-compatibility
60
+ body: |
61
+ Update the supported CPython range after a stable Python release and pandas wheel support.
62
+ Synchronizes classifiers, requires-python, CI, Docker and documentation; increments the fix counter.
63
+ The proposal passed tests, notebooks, export/citation checks, strict docs, distributions and the development image on the newest Python.
64
+ Merging runs the complete check matrix, then tags and dispatches the release when this version is unpublished.
@@ -0,0 +1,89 @@
1
+ name: release
2
+ on:
3
+ push:
4
+ tags: ['v*']
5
+ workflow_dispatch:
6
+ permissions:
7
+ contents: read
8
+ concurrency:
9
+ group: release-${{ github.ref }}
10
+ cancel-in-progress: false
11
+ jobs:
12
+ checks:
13
+ if: startsWith(github.ref, 'refs/tags/v')
14
+ uses: ./.github/workflows/checks.yml
15
+ build:
16
+ needs: checks
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: '3.15' # current-python
23
+ cache: pip
24
+ cache-dependency-path: pyproject.toml
25
+ - run: python -m pip install -e '.[release]'
26
+ - run: python tools/sync_citation.py --check --tag "$RELEASE_TAG"
27
+ env:
28
+ RELEASE_TAG: ${{ github.ref_name }}
29
+ - run: python -m build
30
+ - run: python -m twine check dist/*
31
+ - run: python paper/build_standalone.py
32
+ - name: Install LaTeX
33
+ # cm-super supplies Type 1 T1 fonts; without it Metafont bitmap fonts fail to build.
34
+ run: sudo apt-get update && sudo apt-get install -y --no-install-recommends latexmk texlive-latex-recommended texlive-pictures texlive-fonts-recommended cm-super
35
+ - name: Compile standalone manuscript
36
+ working-directory: paper
37
+ run: latexmk -pdf -interaction=nonstopmode -halt-on-error -outdir=build timegym.tex
38
+ - uses: actions/upload-artifact@v4
39
+ with:
40
+ name: release-distributions
41
+ path: dist/*
42
+ - uses: actions/upload-artifact@v4
43
+ with:
44
+ name: release-paper
45
+ path: |
46
+ paper/build/timegym.pdf
47
+ paper/timegym.tex
48
+ pypi:
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+ environment:
52
+ name: pypi
53
+ url: https://pypi.org/p/timegym
54
+ permissions:
55
+ id-token: write
56
+ steps:
57
+ - uses: actions/download-artifact@v4
58
+ with:
59
+ name: release-distributions
60
+ path: dist
61
+ - uses: pypa/gh-action-pypi-publish@release/v1
62
+ with:
63
+ skip-existing: true
64
+ github-release:
65
+ needs: [build, pypi]
66
+ runs-on: ubuntu-latest
67
+ permissions:
68
+ contents: write
69
+ steps:
70
+ - uses: actions/checkout@v4
71
+ - uses: actions/download-artifact@v4
72
+ with:
73
+ name: release-distributions
74
+ path: dist
75
+ - uses: actions/download-artifact@v4
76
+ with:
77
+ name: release-paper
78
+ path: paper-artifacts
79
+ - name: Publish versioned code and manuscript
80
+ env:
81
+ GH_TOKEN: ${{ github.token }}
82
+ RELEASE_TAG: ${{ github.ref_name }}
83
+ run: |
84
+ if ! gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
85
+ gh release create "$RELEASE_TAG" --verify-tag --draft --title "TimeGym $RELEASE_TAG" --generate-notes
86
+ fi
87
+ find paper-artifacts -type f -exec gh release upload "$RELEASE_TAG" --clobber {} +
88
+ gh release upload "$RELEASE_TAG" --clobber dist/*
89
+ gh release edit "$RELEASE_TAG" --draft=false
@@ -0,0 +1,62 @@
1
+ # Repository guidance
2
+
3
+ TimeGym is notebook-first. Every Python file under `timegym/` is generated from
4
+ marked implementation cells owned by `notebooks/source-map.json`. Edit the
5
+ owning notebook, preserve cell IDs and `metadata.timegym.role`, save it, then
6
+ run `.venv/bin/python tools/export_notebooks.py` and its `--check` mode. Never
7
+ edit generated modules by hand. Read `tools/README.md` and `notebooks/README.md`
8
+ before changing library code. Paper result fragments and `paper/timegym.tex`
9
+ are generated too; edit their inputs and run their builders.
10
+
11
+ Create the environment with `python3 -m venv .venv` and
12
+ `.venv/bin/pip install -e '.[dev]'`; use `.venv/bin/python` thereafter. Add
13
+ `.[notebooks]` to execute notebooks, `.[docs]` for documentation, and `.[release]`
14
+ for distribution checks. Before handoff run the exporter check, `python -m
15
+ pytest -q`, and `python -m mkdocs build --strict` when documentation changes.
16
+ Use the venv interpreter for each command.
17
+
18
+ ## Version policy
19
+
20
+ The three integers in `M.X.Y` are independent counters, not a decimal number.
21
+ The leading zero in the former `0.X.Y` was the major version; this round starts
22
+ `1.0.0`. An implemented feature increments X; a fix increments Y. Increasing X
23
+ must not reset Y: for example, a feature after `1.2.7` becomes `1.3.7`, and a fix
24
+ then becomes `1.3.8`. Only Diogo Seca decides when to change the major version.
25
+ Do not infer a major bump from another project's versioning convention.
26
+
27
+ The authoritative version string is `__version__` in notebook 12's package cell,
28
+ exported to `timegym/__init__.py`; flit reads it dynamically. Update the matching
29
+ CITATION.cff version/date and the leading CHANGELOG heading, run
30
+ `tools/sync_citation.py`, then regenerate the standalone manuscript. Never
31
+ invent a DOI. Follow `docs/release.md` for DOI registration and publication.
32
+
33
+ ## Compatibility policy
34
+
35
+ Follow pandas when choosing current Python and scientific dependency support.
36
+ Prefer the latest stable Python and dependency releases supported by pandas;
37
+ when uncertain, use pandas' support policy and release timing. Keep explicit
38
+ NumPy, pandas and SciPy major-version ceilings until compatibility is reviewed.
39
+ The scheduled compatibility workflow proposes coordinated metadata, CI, Docker
40
+ and documentation updates and tests them before opening a pull request. Keep
41
+ the historical study lock and its Python version separate from current support.
42
+ A successful local check is not evidence that another OS or Python version passed.
43
+
44
+ Publication is tag-driven after owner review. Do not publish, push tags, or
45
+ change external PyPI/Zenodo settings as part of ordinary implementation work.
46
+
47
+ ## Working agreements
48
+
49
+ Work on a branch and hand over a pull request; never push to `main`, never
50
+ push tags, never force-push. Before handoff run, with the venv interpreter,
51
+ `tools/export_notebooks.py --check`, `python -m pytest -q`,
52
+ `python -m mkdocs build --strict` followed by `tools/check_site_links.py site`,
53
+ `paper/build_standalone.py --check`,
54
+ `tools/sync_citation.py --check`, and `notebooks/check_notebooks.py` on every
55
+ notebook you touched, with `--write` when outputs change, because the docs
56
+ site renders saved outputs. When the manuscript changes, also compile
57
+ `paper/timegym.tex` with latexmk as `paper/README.md` describes. Recount
58
+ every stated count (source notebooks, generated modules, active notebooks,
59
+ tests) when it changes. Commit messages
60
+ have an imperative subject and no trailers: no `Co-Authored-By`, no session
61
+ links, no tool attribution of any kind. Delegate to subagents on Opus; the
62
+ session's own model is for orchestration and review.
@@ -0,0 +1,87 @@
1
+ # Changelog
2
+
3
+ ## 1.1.0 — 2026-11-05
4
+
5
+ - Added reversible target transforms to `timegym.target`: `LogTransform`,
6
+ `BoxCoxTransform`, `DifferenceTransform` and `ComposedTransform`, with
7
+ `transform_config` and `transform_from_config` for configuration and replay.
8
+ - `Pipeline(..., target_transform=None)` fits a fresh copy of the transform on each
9
+ context and inverts the model's forecast before evaluation.
10
+ - `SklearnForecaster` adds the `direct` and `multioutput` reductions beside
11
+ `recursive`; `timegym.models.REDUCTIONS` lists them and `Pipeline(reduction=...)`
12
+ selects one.
13
+ - Pipeline configuration schema 3 records `target_transform`; schema 2
14
+ configurations remain readable.
15
+ - Added tutorials 29 (target transforms) and 30 (reductions).
16
+ - Removed the command-line interface: the `timegym` console script,
17
+ `python -m timegym`, the `timegym.cli` module and source notebook 13.
18
+ TimeGym is used as a Python package.
19
+ - `examples/reproduce_report.py` is a standalone script: it replays one case with
20
+ `TestReport.read(...).replay_case(...)`, prints the comparison and exits 1 when
21
+ the case is not reproduced. The installed-wheel CI job replays the report saved
22
+ by `tools/smoke_installed.py --report`.
23
+ - Removed `Pipeline.plot_error()`, the 1.0 alias of `Pipeline.plot_errors()`.
24
+ - Pipeline configuration schema 1 (`strategy` instead of `reduction`) is no longer
25
+ read; `pipeline_from_config` accepts schemas 2 and 3.
26
+ - Removed `timegym.joint_processes.resolve_joint_process()`; call
27
+ `timegym.processes.resolve_process()` with the same arguments.
28
+ - Renamed the supplement's paired loss fields `repair_minus_faulty_mse` and
29
+ `repair_minus_faulty_reference_mse` to `clean_minus_faulty_mse` and
30
+ `clean_minus_faulty_reference_mse` in `experiments/results-v2`, as a recorded
31
+ offline migration; no value changed.
32
+
33
+ ## 1.0.0 — 2026-10-30
34
+
35
+ Prepared release; publication is performed only by the version-tag workflow.
36
+
37
+ - Unified package, citation and manuscript version metadata; added checked
38
+ citation rendering and a tag-driven PyPI/GitHub release workflow.
39
+ - Added scheduled Python compatibility updates following pandas support,
40
+ bounded runtime dependencies, and a pinned development Docker image.
41
+ - Documented module imports, built-in models, fault fixtures, and release setup.
42
+ - Excluded historical notebooks from the source archive and consolidated CI checks.
43
+ - `get_stock` now defaults to `auto_adjust=True` (adjusted OHLC); pass `False` for the
44
+ provider's unadjusted fields.
45
+
46
+ - Renamed Pipeline’s `strategy` parameter and attribute to `reduction`. Pipeline
47
+ configuration schema 2 uses `reduction`; saved schema-1 configurations remain
48
+ replayable. `NaiveForecaster(strategy=...)` continues to select its baseline.
49
+
50
+ - Renamed `Pipeline.plot_error()` to `Pipeline.plot_errors()` for consistency with
51
+ retained runs. The singular spelling remains a forwarding alias for the 1.0
52
+ release; migrate callers before the next release.
53
+
54
+ ### Joint controlled processes
55
+
56
+ - Extended composed, Merton, GARCH and Markov scenarios to multiple dependent targets.
57
+ - Added correlated shocks, shared jump events, shared hidden regimes, and state-specific correlation matrices.
58
+ - Added CCC-GARCH with exact joint simulation and explicitly labelled numerical cross-covariance.
59
+ - Added source notebook 15 and application notebook 27, including dependence-fault and repair examples.
60
+ - Preserved scalar-case outputs, seed behaviour, and replay records.
61
+
62
+
63
+ TimeGym now provides a reproducible verification and diagnosis workflow for
64
+ forecasting pipelines, with a new manuscript and bounded controlled studies.
65
+
66
+ - Explicit contracts for point means, marginal quantiles, and joint samples.
67
+ - Controlled scalar and joint compositions and parameter changes, Merton jump diffusion,
68
+ GARCH volatility, and hidden Markov regimes with optional jumps.
69
+ - Non-Gaussian conditional simulation references with explicit quantile and
70
+ filtering approximation metadata.
71
+ - Conditional Gaussian references and reproducible multivariate scenarios.
72
+ - Parameter-aware plot labels distinguish fixed-mean white noise, linear trend
73
+ plus noise, and random walks with or without drift, including mixed-target drift.
74
+ - Fresh-fitting pipeline adapters and training-only recursive sklearn forecasts.
75
+ - Structured diagnostics, validated report loading, and allowlisted model replay.
76
+ - A command-line alignment-fault demo, report inspection, and replay.
77
+ - Retained forecast matrices with observation dots and unconnected forecast
78
+ crosses; plots reuse fitted results.
79
+ - Notebook-first source with deterministic nbdev export and drift checks.
80
+ - Univariate and multivariate uncertainty demos, fault/repair examples, and local
81
+ real-data applications. The 11 original notebooks remain archived unchanged.
82
+ - Strict documentation and distribution checks, citation metadata, and CI jobs
83
+ that exercise an installed wheel outside the checkout.
84
+
85
+ The 2021 API and dependency assumptions changed substantially. Follow the
86
+ migration guide. Direct/multioutput forecasting strategies,
87
+ automatic repair discovery, and universal fault detection are not claimed.