rangebar 7.1.2__tar.gz → 11.4.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 (182) hide show
  1. {rangebar-7.1.2 → rangebar-11.4.0}/.gitignore +2 -0
  2. rangebar-11.4.0/.mcp.json +18 -0
  3. {rangebar-7.1.2 → rangebar-11.4.0}/.mise.toml +142 -59
  4. rangebar-11.4.0/.pre-commit-config.yaml +33 -0
  5. rangebar-11.4.0/CHANGELOG.md +539 -0
  6. rangebar-11.4.0/CLAUDE.md +227 -0
  7. {rangebar-7.1.2 → rangebar-11.4.0}/Cargo.lock +503 -39
  8. {rangebar-7.1.2 → rangebar-11.4.0}/Cargo.toml +27 -6
  9. {rangebar-7.1.2 → rangebar-11.4.0}/PKG-INFO +49 -33
  10. {rangebar-7.1.2 → rangebar-11.4.0}/README.md +42 -28
  11. {rangebar-7.1.2 → rangebar-11.4.0}/crates/CLAUDE.md +53 -22
  12. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/Cargo.toml +6 -0
  13. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/README.md +7 -7
  14. rangebar-11.4.0/crates/rangebar-core/src/arrow_export.rs +344 -0
  15. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/checkpoint.rs +75 -3
  16. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/fixed_point.rs +3 -3
  17. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/lib.rs +11 -0
  18. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/processor.rs +317 -73
  19. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/test_utils/mod.rs +5 -5
  20. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/types.rs +26 -15
  21. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/tests/cross_boundary_validation.rs +1 -1
  22. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/tests/cross_year_boundary_test.rs +1 -1
  23. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs +1 -1
  24. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/Cargo.toml +7 -1
  25. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/README.md +1 -1
  26. rangebar-11.4.0/crates/rangebar-providers/src/binance/checksum.rs +397 -0
  27. rangebar-11.4.0/crates/rangebar-providers/src/binance/historical.rs +755 -0
  28. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/binance/mod.rs +11 -1
  29. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/exness/builder.rs +12 -9
  30. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/lib.rs +3 -2
  31. rangebar-11.4.0/crates/rangebar-streaming/CHANGELOG.md +6 -0
  32. rangebar-11.4.0/crates/rangebar-streaming/Cargo.toml +42 -0
  33. rangebar-11.4.0/crates/rangebar-streaming/README.md +132 -0
  34. rangebar-11.4.0/crates/rangebar-streaming/src/indicators.rs +364 -0
  35. rangebar-11.4.0/crates/rangebar-streaming/src/lib.rs +32 -0
  36. rangebar-11.4.0/crates/rangebar-streaming/src/processor.rs +513 -0
  37. rangebar-11.4.0/crates/rangebar-streaming/src/replay_buffer.rs +359 -0
  38. rangebar-11.4.0/crates/rangebar-streaming/src/stats.rs +565 -0
  39. rangebar-11.4.0/crates/rangebar-streaming/src/universal.rs +353 -0
  40. rangebar-11.4.0/docs/MEMORY_REMEDIATION_PLAN.md +348 -0
  41. rangebar-11.4.0/docs/adr/2026-01-31-realtime-streaming-api.md +202 -0
  42. rangebar-11.4.0/docs/analysis/2025-10-10-flash-crash.md +375 -0
  43. {rangebar-7.1.2 → rangebar-11.4.0}/docs/api.md +422 -13
  44. rangebar-11.4.0/docs/migration-v8.md +117 -0
  45. {rangebar-7.1.2 → rangebar-11.4.0}/docs/rangebar_core_api.md +8 -8
  46. rangebar-11.4.0/docs/research/labeling-for-ml.md +773 -0
  47. rangebar-11.4.0/docs/research/price-action-patterns.md +313 -0
  48. {rangebar-7.1.2 → rangebar-11.4.0}/examples/README.md +11 -12
  49. {rangebar-7.1.2 → rangebar-11.4.0}/examples/binance_csv_example.py +1 -1
  50. {rangebar-7.1.2 → rangebar-11.4.0}/examples/with_clickhouse_cache.py +1 -1
  51. {rangebar-7.1.2 → rangebar-11.4.0}/pyproject.toml +94 -9
  52. rangebar-11.4.0/python/rangebar/__init__.py +215 -0
  53. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/__init__.pyi +299 -9
  54. rangebar-11.4.0/python/rangebar/checkpoint.py +472 -0
  55. rangebar-11.4.0/python/rangebar/cli.py +298 -0
  56. rangebar-11.4.0/python/rangebar/clickhouse/CLAUDE.md +136 -0
  57. rangebar-11.4.0/python/rangebar/clickhouse/bulk_operations.py +309 -0
  58. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/cache.py +124 -427
  59. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/preflight.py +11 -5
  60. rangebar-11.4.0/python/rangebar/clickhouse/query_operations.py +345 -0
  61. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/schema.sql +44 -1
  62. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/tunnel.py +22 -7
  63. rangebar-11.4.0/python/rangebar/constants.py +255 -0
  64. rangebar-11.4.0/python/rangebar/conversion.py +177 -0
  65. rangebar-11.4.0/python/rangebar/exceptions.py +207 -0
  66. rangebar-11.4.0/python/rangebar/exness.py +364 -0
  67. rangebar-11.4.0/python/rangebar/hooks.py +311 -0
  68. rangebar-11.4.0/python/rangebar/logging.py +171 -0
  69. rangebar-11.4.0/python/rangebar/notify/__init__.py +15 -0
  70. rangebar-11.4.0/python/rangebar/notify/pushover.py +155 -0
  71. rangebar-11.4.0/python/rangebar/notify/telegram.py +271 -0
  72. rangebar-11.4.0/python/rangebar/orchestration/__init__.py +20 -0
  73. rangebar-11.4.0/python/rangebar/orchestration/count_bounded.py +797 -0
  74. rangebar-11.4.0/python/rangebar/orchestration/helpers.py +397 -0
  75. rangebar-11.4.0/python/rangebar/orchestration/models.py +76 -0
  76. rangebar-11.4.0/python/rangebar/orchestration/precompute.py +498 -0
  77. rangebar-11.4.0/python/rangebar/orchestration/range_bars.py +726 -0
  78. rangebar-11.4.0/python/rangebar/orchestration/tick_fetcher.py +226 -0
  79. rangebar-11.4.0/python/rangebar/ouroboros.py +454 -0
  80. rangebar-11.4.0/python/rangebar/processors/__init__.py +22 -0
  81. rangebar-11.4.0/python/rangebar/processors/api.py +383 -0
  82. rangebar-11.4.0/python/rangebar/processors/core.py +510 -0
  83. rangebar-11.4.0/python/rangebar/resource_guard.py +342 -0
  84. rangebar-11.4.0/python/rangebar/storage/checksum_registry.py +218 -0
  85. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/storage/parquet.py +38 -8
  86. rangebar-11.4.0/python/rangebar/streaming.py +300 -0
  87. rangebar-11.4.0/python/rangebar/validation/__init__.py +69 -0
  88. rangebar-11.4.0/python/rangebar/validation/cache_staleness.py +277 -0
  89. rangebar-11.4.0/python/rangebar/validation/continuity.py +664 -0
  90. rangebar-11.4.0/python/rangebar/validation/gap_classification.py +294 -0
  91. rangebar-11.4.0/python/rangebar/validation/post_storage.py +317 -0
  92. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/validation/tier1.py +1 -1
  93. rangebar-11.4.0/scripts/analyze_flash_crash.py +206 -0
  94. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/build-release.sh +57 -27
  95. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/cache_status.py +6 -6
  96. rangebar-11.4.0/scripts/check-release-config.sh +102 -0
  97. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/publish-to-pypi.sh +47 -15
  98. rangebar-11.4.0/scripts/regenerate_cache.py +114 -0
  99. rangebar-11.4.0/scripts/semantic-release.sh +47 -0
  100. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/validate_microstructure_features.py +2 -2
  101. rangebar-11.4.0/src/lib.rs +2291 -0
  102. rangebar-11.4.0/tests/conftest.py +50 -0
  103. rangebar-11.4.0/tests/test_cache_schema_evolution.py +409 -0
  104. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_clickhouse.py +4 -0
  105. rangebar-11.4.0/tests/test_clickhouse_integration.py +728 -0
  106. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_get_n_range_bars.py +165 -76
  107. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_get_range_bars_e2e.py +1 -1
  108. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_issue_5_reproduction.py +1 -1
  109. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_microstructure_features.py +1 -1
  110. rangebar-11.4.0/tests/test_ouroboros.py +907 -0
  111. rangebar-11.4.0/tests/test_polars_only_downstream.py +433 -0
  112. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_preflight.py +22 -14
  113. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_rust_bindings.py +111 -5
  114. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_storage.py +47 -0
  115. rangebar-11.4.0/tests/test_streaming.py +528 -0
  116. {rangebar-7.1.2 → rangebar-11.4.0}/uv.lock +134 -634
  117. rangebar-7.1.2/.link-check-results.md +0 -12
  118. rangebar-7.1.2/.pre-commit-config.yaml +0 -51
  119. rangebar-7.1.2/CHANGELOG.md +0 -371
  120. rangebar-7.1.2/CLAUDE.md +0 -174
  121. rangebar-7.1.2/crates/rangebar-providers/src/binance/historical.rs +0 -212
  122. rangebar-7.1.2/python/rangebar/__init__.py +0 -3636
  123. rangebar-7.1.2/python/rangebar/exness.py +0 -198
  124. rangebar-7.1.2/python/rangebar/validation/__init__.py +0 -16
  125. rangebar-7.1.2/src/lib.rs +0 -1163
  126. rangebar-7.1.2/tests/test_clickhouse_integration.py +0 -348
  127. {rangebar-7.1.2 → rangebar-11.4.0}/.releaserc.yml +0 -0
  128. {rangebar-7.1.2 → rangebar-11.4.0}/LICENSE +0 -0
  129. {rangebar-7.1.2 → rangebar-11.4.0}/benches/rangebar_bench.rs +0 -0
  130. {rangebar-7.1.2 → rangebar-11.4.0}/build.rs +0 -0
  131. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/CHANGELOG.md +0 -0
  132. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/test_data_loader.rs +0 -0
  133. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/test_utils/generators.rs +0 -0
  134. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/src/timestamp.rs +0 -0
  135. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-core/tests/cross_date_real_data_validation.rs +0 -0
  136. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/CHANGELOG.md +0 -0
  137. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/binance/symbols.rs +0 -0
  138. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/binance/websocket.rs +0 -0
  139. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/exness/client.rs +0 -0
  140. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/exness/conversion.rs +0 -0
  141. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/exness/mod.rs +0 -0
  142. {rangebar-7.1.2 → rangebar-11.4.0}/crates/rangebar-providers/src/exness/types.rs +0 -0
  143. {rangebar-7.1.2 → rangebar-11.4.0}/deny.toml +0 -0
  144. {rangebar-7.1.2 → rangebar-11.4.0}/docs/ARCHITECTURE.md +0 -0
  145. {rangebar-7.1.2 → rangebar-11.4.0}/docs/CONTEXT.md +0 -0
  146. {rangebar-7.1.2 → rangebar-11.4.0}/docs/development/PERFORMANCE.md +0 -0
  147. {rangebar-7.1.2 → rangebar-11.4.0}/docs/development/RELEASE.md +0 -0
  148. {rangebar-7.1.2 → rangebar-11.4.0}/examples/backtesting_integration.py +0 -0
  149. {rangebar-7.1.2 → rangebar-11.4.0}/examples/basic_usage.py +0 -0
  150. {rangebar-7.1.2 → rangebar-11.4.0}/examples/get_range_bars_example.py +0 -0
  151. {rangebar-7.1.2 → rangebar-11.4.0}/examples/validate_output.py +0 -0
  152. {rangebar-7.1.2 → rangebar-11.4.0}/package-lock.json +0 -0
  153. {rangebar-7.1.2 → rangebar-11.4.0}/package.json +0 -0
  154. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/CLAUDE.md +0 -0
  155. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/__init__.py +0 -0
  156. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/client.py +0 -0
  157. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/config.py +0 -0
  158. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/clickhouse/mixin.py +0 -0
  159. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/storage/__init__.py +0 -0
  160. {rangebar-7.1.2 → rangebar-11.4.0}/python/rangebar/validation/tier2.py +0 -0
  161. {rangebar-7.1.2 → rangebar-11.4.0}/rust-toolchain.toml +0 -0
  162. {rangebar-7.1.2 → rangebar-11.4.0}/rustfmt.toml +0 -0
  163. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/cache_clear.py +0 -0
  164. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/dependency_monitor.sh +0 -0
  165. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/profiling_tools.sh +0 -0
  166. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/publish-wheels.sh +0 -0
  167. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/run_large_scale_benchmark.sh +0 -0
  168. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/validate_clickhouse.py +0 -0
  169. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/validate_memory_efficiency.py +0 -0
  170. {rangebar-7.1.2 → rangebar-11.4.0}/scripts/validate_n_range_bars.py +0 -0
  171. {rangebar-7.1.2 → rangebar-11.4.0}/test_data/BTCUSDT/BTCUSDT_aggTrades_20250901.csv +0 -0
  172. {rangebar-7.1.2 → rangebar-11.4.0}/test_data/ETHUSDT/ETHUSDT_aggTrades_20250901.csv +0 -0
  173. {rangebar-7.1.2 → rangebar-11.4.0}/test_data/README.md +0 -0
  174. {rangebar-7.1.2 → rangebar-11.4.0}/tests/fixtures/.gitignore +0 -0
  175. {rangebar-7.1.2 → rangebar-11.4.0}/tests/fixtures/BTCUSDT-aggTrades-2024-01-01.zip +0 -0
  176. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_e2e_optimized.py +0 -0
  177. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_edge_cases.py +0 -0
  178. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_examples.py +0 -0
  179. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_issues_7_8.py +0 -0
  180. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_python_api.py +0 -0
  181. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_real_data.py +0 -0
  182. {rangebar-7.1.2 → rangebar-11.4.0}/tests/test_validation_presets.py +0 -0
@@ -98,6 +98,7 @@ tmp/
98
98
  .lycheecache
99
99
  logs/
100
100
  node_modules/
101
+ bun.lock
101
102
 
102
103
  # ClickHouse server runtime data (created when running `clickhouse server` locally)
103
104
  data/
@@ -112,3 +113,4 @@ user_defined/
112
113
  format_schemas/
113
114
  access/
114
115
  test_data/
116
+ .claude/
@@ -0,0 +1,18 @@
1
+ {
2
+ "mcpServers": {
3
+ "mise": {
4
+ "command": "mise",
5
+ "args": ["mcp"],
6
+ "env": {
7
+ "MISE_EXPERIMENTAL": "1"
8
+ }
9
+ },
10
+ "shell": {
11
+ "command": "uvx",
12
+ "args": ["mcp-shell-server"],
13
+ "env": {
14
+ "ALLOW_COMMANDS": "mise,git,jq,cargo,uv,maturin,pytest,cat,ls,grep,head,tail,fd"
15
+ }
16
+ }
17
+ }
18
+ }
@@ -1,14 +1,45 @@
1
1
  [env]
2
- # GitHub account isolation (required for git-account-validator hooks)
2
+ # =============================================================================
3
+ # GitHub Account Isolation (CRITICAL for multi-account setups)
4
+ # =============================================================================
3
5
  # See: ADR 2025-12-17-github-multi-account-authentication
6
+ #
7
+ # This ensures all gh CLI and git operations use the correct GitHub identity.
8
+ # The git remote MUST use SSH with host alias: git@github.com-terrylica:...
4
9
  GH_ACCOUNT = "terrylica"
5
10
  GH_CONFIG_DIR = "{{ env.HOME }}/.config/gh/profiles/terrylica"
6
11
 
7
- # GitHub tokens (for API operations)
12
+ # GitHub token for gh CLI operations (uses file-based loading to prevent process storms)
13
+ # ADR: 2026-01-15-mise-env-token-loading-patterns.md
14
+ # NOTE: For semantic-release, use `mise run release:version` which fetches
15
+ # the PAT from Doppler dynamically to avoid stale token issues.
8
16
  GH_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-terrylica') | trim }}"
9
17
  GITHUB_TOKEN = "{{ read_file(path=env.HOME ~ '/.claude/.secrets/gh-token-terrylica') | trim }}"
10
18
 
11
- # Benchmark configuration
19
+ # =============================================================================
20
+ # Doppler Configuration (SSoT for secrets)
21
+ # =============================================================================
22
+ # PyPI: doppler secrets get PYPI_TOKEN --project claude-config --config prd
23
+ # GitHub PAT: doppler secrets get GH_TOKEN_TERRYLICA --project main --config dev
24
+ DOPPLER_PYPI_PROJECT = "claude-config"
25
+ DOPPLER_PYPI_CONFIG = "prd"
26
+
27
+ # =============================================================================
28
+ # ClickHouse Cache Configuration (SSoT for cache hosts)
29
+ # =============================================================================
30
+ # RANGEBAR_CH_HOSTS: SSH aliases for ClickHouse hosts (comma-separated)
31
+ # RANGEBAR_CH_PRIMARY: Preferred host when multiple available
32
+ # RANGEBAR_MODE: "auto" (default), "local", or "cloud"
33
+ #
34
+ # AUTO mode: Try localhost first, then SSH tunnel to remote hosts
35
+ # LOCAL mode: Only use localhost:8123 (fails if unavailable)
36
+ # CLOUD mode: Only use CLICKHOUSE_HOST env var (for cloud deployments)
37
+ RANGEBAR_CH_HOSTS = "bigblack"
38
+ RANGEBAR_CH_PRIMARY = "bigblack"
39
+
40
+ # =============================================================================
41
+ # Build Configuration
42
+ # =============================================================================
12
43
  BENCH_DATA_DIR = "{{ env.PWD }}/bench-data"
13
44
  PROFILE_DATA_DIR = "{{ env.PWD }}/profile-data"
14
45
 
@@ -28,7 +59,7 @@ LINUX_MIN_RUST_VERSION = "1.90"
28
59
  # =============================================================================
29
60
 
30
61
  [tools]
31
- python = "3.11"
62
+ python = "3.13"
32
63
  rust = "1.90"
33
64
  node = "22" # Required for semantic-release
34
65
  uv = "latest" # Required for publish workflow
@@ -250,7 +281,7 @@ run = "./scripts/publish-wheels.sh"
250
281
 
251
282
  [tasks."release:local"]
252
283
  description = "Build local wheel only (macOS ARM64)"
253
- run = "maturin build --release --profile wheel"
284
+ run = "maturin build --profile wheel"
254
285
 
255
286
  [tasks."release:sdist"]
256
287
  description = "Build source distribution"
@@ -261,8 +292,19 @@ run = "maturin sdist"
261
292
  # =============================================================================
262
293
 
263
294
  [tasks."release:macos-arm64"]
264
- description = "Build macOS ARM64 wheel (native)"
265
- run = "maturin build --profile wheel"
295
+ description = "Build macOS ARM64 wheels for Python 3.13 (native)"
296
+ run = """
297
+ echo "=== Building macOS ARM64 wheels (Python 3.13) ==="
298
+ for pyver in python3.13; do
299
+ if command -v $pyver &> /dev/null; then
300
+ echo "Building for $pyver..."
301
+ maturin build --profile wheel -i $pyver
302
+ else
303
+ echo "WARN: $pyver not found, skipping"
304
+ fi
305
+ done
306
+ echo "OK: macOS ARM64 wheels built"
307
+ """
266
308
 
267
309
  [tasks."release:linux-preflight"]
268
310
  description = "Verify Linux build host availability"
@@ -279,10 +321,10 @@ echo "OK: Remote Rust version: $REMOTE_RUST"
279
321
  """
280
322
 
281
323
  [tasks."release:linux"]
282
- description = "Build Linux x86_64 wheel on remote host (Docker manylinux)"
324
+ description = "Build Linux x86_64 wheels for Python 3.13 on remote host (Docker manylinux)"
283
325
  depends = ["release:linux-preflight"]
284
326
  run = """
285
- echo "=== Building Linux x86_64 Wheel (Docker manylinux) ==="
327
+ echo "=== Building Linux x86_64 Wheels (Docker manylinux, Python 3.13) ==="
286
328
  PROJECT_DIR="$(pwd)"
287
329
  REMOTE_DIR="${LINUX_BUILD_DIR}-$$"
288
330
 
@@ -297,11 +339,12 @@ rsync -az --delete \
297
339
  "$PROJECT_DIR/" "$LINUX_BUILD_USER@$LINUX_BUILD_HOST:$REMOTE_DIR/"
298
340
 
299
341
  # Build using manylinux Docker container for glibc compatibility
300
- ssh "$LINUX_BUILD_USER@$LINUX_BUILD_HOST" 'cd '"$REMOTE_DIR"' && docker run --rm -v $(pwd):/io -w /io quay.io/pypa/manylinux2014_x86_64 bash -c "yum install -y openssl-devel perl-IPC-Cmd && curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source ~/.cargo/env && /opt/python/cp311-cp311/bin/pip install maturin && /opt/python/cp311-cp311/bin/maturin build --profile wheel --compatibility manylinux2014 -i /opt/python/cp311-cp311/bin/python"'
342
+ # Build for Python 3.13 only (abi3 removed, need per-version wheels)
343
+ ssh "$LINUX_BUILD_USER@$LINUX_BUILD_HOST" 'cd '"$REMOTE_DIR"' && docker run --rm -v $(pwd):/io -w /io quay.io/pypa/manylinux2014_x86_64 bash -c "yum install -y openssl-devel perl-IPC-Cmd && curl --proto =https --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && source ~/.cargo/env && /opt/python/cp313-cp313/bin/pip install maturin && /opt/python/cp313-cp313/bin/maturin build --profile wheel --compatibility manylinux2014 -i /opt/python/cp313-cp313/bin/python"'
301
344
 
302
345
  mkdir -p dist/
303
346
  scp "$LINUX_BUILD_USER@$LINUX_BUILD_HOST:$REMOTE_DIR/target/wheels/*manylinux*.whl" dist/
304
- echo "OK: Linux wheel built"
347
+ echo "OK: Linux wheels built"
305
348
  """
306
349
 
307
350
  # =============================================================================
@@ -333,25 +376,46 @@ echo "OK: Preflight passed"
333
376
  description = "Synchronize with remote (Phase 2)"
334
377
  depends = ["release:preflight"]
335
378
  run = """
379
+ #!/usr/bin/env bash
380
+ set -euo pipefail
381
+
336
382
  echo "=== SYNC ==="
383
+
384
+ # Ensure SSH remote for terrylica account
385
+ REMOTE_URL=$(git remote get-url origin)
386
+ if [[ ! "$REMOTE_URL" =~ github.com-terrylica ]]; then
387
+ echo "Fixing remote URL for terrylica identity..."
388
+ git remote set-url origin "git@github.com-terrylica:terrylica/rangebar-py.git"
389
+ fi
390
+
337
391
  git pull --rebase origin main || { echo "FAIL: Pull failed"; exit 1; }
338
392
  git push origin main || { echo "FAIL: Push failed"; exit 1; }
339
393
  echo "OK: Synced"
340
394
  """
341
395
 
396
+ [tasks."release:check-config"]
397
+ description = "Verify release configuration (GitHub, Doppler, SSH)"
398
+ run = "./scripts/check-release-config.sh"
399
+
342
400
  [tasks."release:build-all"]
343
- description = "Build all platform wheels (Phase 3)"
401
+ description = "Build all platform wheels + sdist (Phase 3 - runs AFTER version bump)"
402
+ depends = ["release:version"]
344
403
  run = """
345
404
  echo "=== BUILD ALL PLATFORMS ==="
346
405
  mise run release:macos-arm64
347
406
  mise run release:linux
348
- echo "OK: All wheels built"
349
- ls -la dist/*.whl 2>/dev/null || true
407
+ mise run release:sdist
408
+ # Copy macOS wheel and sdist to dist/ (Linux wheel already lands there via scp)
409
+ VERSION=$(grep -A5 '\\[workspace.package\\]' Cargo.toml | grep '^version' | head -1 | sed 's/.*= "\\(.*\\)"/\\1/')
410
+ cp -n target/wheels/rangebar-${VERSION}-*.whl dist/ 2>/dev/null || true
411
+ cp -n target/wheels/rangebar-${VERSION}.tar.gz dist/ 2>/dev/null || true
412
+ echo "OK: All wheels + sdist built"
413
+ ls -la dist/rangebar-${VERSION}* 2>/dev/null || true
350
414
  """
351
415
 
352
416
  [tasks."release:postflight"]
353
- description = "Verify and publish (Phase 4)"
354
- depends = ["smoke"]
417
+ description = "Verify and publish (Phase 4 - runs AFTER builds)"
418
+ depends = ["smoke", "release:build-all"]
355
419
  run = """
356
420
  echo "=== POSTFLIGHT ==="
357
421
  WHEEL_COUNT=$(find dist/ -name "*.whl" 2>/dev/null | wc -l | tr -d ' ')
@@ -362,58 +426,31 @@ echo "To publish: mise run publish"
362
426
  """
363
427
 
364
428
  [tasks."release:version"]
365
- description = "Bump version via semantic-release (requires npm install first)"
366
- run = """
367
- if [ ! -d node_modules ]; then
368
- echo "Installing npm dependencies..."
369
- npm install
370
- fi
371
- npm run release
372
- """
429
+ description = "Bump version via semantic-release with Doppler GitHub token"
430
+ depends = ["release:sync"]
431
+ run = "./scripts/semantic-release.sh"
373
432
 
374
433
  [tasks."release:dry"]
375
434
  description = "Preview what semantic-release would do (no changes)"
376
- run = """
377
- if [ ! -d node_modules ]; then
378
- echo "Installing npm dependencies..."
379
- npm install
380
- fi
381
- echo "=== DRY RUN: Previewing release ==="
382
- npx semantic-release --dry-run --no-ci
383
- """
435
+ run = "bun install --silent 2>/dev/null && GH_CONFIG_DIR=$HOME/.config/gh/profiles/terrylica GITHUB_TOKEN=$(gh auth token) bun run semantic-release --dry-run --no-ci"
384
436
 
385
437
  [tasks."release:pypi"]
386
- description = "Publish to PyPI using Doppler credentials (local-only)"
438
+ description = "Publish to PyPI using Doppler credentials (local-only, ADR-0027)"
439
+ depends = ["release:build-all"]
387
440
  run = "./scripts/publish-to-pypi.sh"
388
441
 
389
442
  [tasks."release:full"]
390
- description = "Full 4-phase release workflow"
443
+ description = "Full release workflow: version bump → build → smoke → publish to PyPI"
444
+ # Dependency chain enforced via task-level depends:
445
+ # preflight → sync → version → build-all → postflight
446
+ # ↓
447
+ # release:pypi (publish)
448
+ # mise resolves the full DAG automatically.
449
+ depends = ["release:postflight", "release:pypi"]
391
450
  run = """
392
- echo "=== FULL RELEASE WORKFLOW ==="
393
-
394
- echo ""
395
- echo "=== Phase 1: PREFLIGHT ==="
396
- mise run release:preflight
397
-
398
- echo ""
399
- echo "=== Phase 2: SYNC ==="
400
- mise run release:sync
401
-
402
- echo ""
403
- echo "=== Phase 3: VERSION (semantic-release) ==="
404
- mise run release:version
405
-
406
- echo ""
407
- echo "=== Phase 4: BUILD ==="
408
- mise run release:build-all
409
-
410
- echo ""
411
- echo "=== Phase 5: POSTFLIGHT ==="
412
- mise run release:postflight
413
-
414
- echo ""
415
- echo "=== COMPLETE ==="
416
- echo "Run 'mise run publish' to publish to PyPI"
451
+ echo '========================================='
452
+ echo ' Release complete and published to PyPI!'
453
+ echo '========================================='
417
454
  """
418
455
 
419
456
  # =============================================================================
@@ -440,3 +477,49 @@ print("OK: basic processing works")
440
477
  [tasks.smoke]
441
478
  description = "Run all smoke tests"
442
479
  depends = ["smoke:import", "smoke:process"]
480
+
481
+ # =============================================================================
482
+ # Checksum Verification Tasks (Issue #43)
483
+ # =============================================================================
484
+
485
+ [tasks."test:checksum"]
486
+ description = "Test Rust checksum verification module"
487
+ run = "cargo nextest run -p rangebar-providers checksum"
488
+
489
+ [tasks."test:checksum:integration"]
490
+ description = "Integration test with real Binance data (requires network)"
491
+ run = """
492
+ python -c '
493
+ from rangebar import get_range_bars
494
+ import logging
495
+ logging.basicConfig(level=logging.DEBUG)
496
+
497
+ # Test with checksum verification (should see checksum events in logs)
498
+ df = get_range_bars("BTCUSDT", "2024-01-01", "2024-01-01", verify_checksum=True)
499
+ print(f"Downloaded {len(df)} bars with checksum verification")
500
+ '
501
+ """
502
+
503
+ [tasks."checksum:audit"]
504
+ description = "Audit Tier 1 cache for unverified files"
505
+ run = """
506
+ python -c '
507
+ from rangebar.storage.checksum_registry import ChecksumRegistry
508
+ registry = ChecksumRegistry()
509
+ count = registry.get_verified_count("BTCUSDT")
510
+ print(f"BTCUSDT verified dates: {count}")
511
+ '
512
+ """
513
+
514
+ [tasks."checksum:pushover-test"]
515
+ description = "Send test Pushover alert to verify credentials"
516
+ run = """
517
+ python -c '
518
+ from rangebar.notify.pushover import send_critical_alert
519
+ result = send_critical_alert(
520
+ title="🧪 RB Test Alert",
521
+ message="Checksum verification test - ignore this alert.",
522
+ )
523
+ print(f"Pushover alert sent: {result}")
524
+ '
525
+ """
@@ -0,0 +1,33 @@
1
+ # Pre-commit hooks for rangebar-py
2
+ # ADR-005: Automated Release Management
3
+ #
4
+ # Philosophy: Only checks that catch BUGS, not cosmetic formatting
5
+ #
6
+ # REMOVED (cosmetic, no bug-catching value):
7
+ # - black (Python formatting)
8
+ # - fmt (Rust formatting)
9
+ # - end-of-file-fixer
10
+ # - trailing-whitespace
11
+ #
12
+ # MOVED TO PRE-PUSH (too slow for commits):
13
+ # - clippy (Rust linting) - runs on `git push` via global hook
14
+ #
15
+ # Install: pre-commit install
16
+ # Run manually: pre-commit run --all-files
17
+
18
+ repos:
19
+ # Python linting (fast, catches bugs)
20
+ - repo: https://github.com/astral-sh/ruff-pre-commit
21
+ rev: v0.8.4
22
+ hooks:
23
+ - id: ruff
24
+ args: [--fix, --exit-non-zero-on-fix]
25
+
26
+ # Config validation (prevents broken builds)
27
+ - repo: https://github.com/pre-commit/pre-commit-hooks
28
+ rev: v5.0.0
29
+ hooks:
30
+ - id: check-yaml
31
+ - id: check-toml
32
+ - id: check-added-large-files
33
+ args: [--maxkb=1024] # Prevent committing files >1MB