rangebar 7.1.2__tar.gz → 11.3.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 (165) hide show
  1. {rangebar-7.1.2 → rangebar-11.3.0}/.gitignore +1 -0
  2. rangebar-11.3.0/.mcp.json +18 -0
  3. {rangebar-7.1.2 → rangebar-11.3.0}/.mise.toml +130 -59
  4. rangebar-11.3.0/.pre-commit-config.yaml +33 -0
  5. rangebar-11.3.0/CHANGELOG.md +525 -0
  6. rangebar-11.3.0/CLAUDE.md +227 -0
  7. {rangebar-7.1.2 → rangebar-11.3.0}/Cargo.lock +502 -39
  8. {rangebar-7.1.2 → rangebar-11.3.0}/Cargo.toml +23 -5
  9. {rangebar-7.1.2 → rangebar-11.3.0}/PKG-INFO +49 -33
  10. {rangebar-7.1.2 → rangebar-11.3.0}/README.md +42 -28
  11. {rangebar-7.1.2 → rangebar-11.3.0}/crates/CLAUDE.md +53 -22
  12. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/Cargo.toml +6 -0
  13. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/README.md +7 -7
  14. rangebar-11.3.0/crates/rangebar-core/src/arrow_export.rs +344 -0
  15. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/checkpoint.rs +75 -3
  16. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/fixed_point.rs +3 -3
  17. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/lib.rs +11 -0
  18. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/processor.rs +317 -73
  19. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/test_utils/mod.rs +5 -5
  20. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/types.rs +26 -15
  21. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/tests/cross_boundary_validation.rs +1 -1
  22. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/tests/cross_year_boundary_test.rs +1 -1
  23. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/tests/incomplete_bar_continuation_proof.rs +1 -1
  24. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/Cargo.toml +7 -1
  25. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/README.md +1 -1
  26. rangebar-11.3.0/crates/rangebar-providers/src/binance/checksum.rs +397 -0
  27. rangebar-11.3.0/crates/rangebar-providers/src/binance/historical.rs +755 -0
  28. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/binance/mod.rs +11 -1
  29. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/exness/builder.rs +12 -9
  30. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/lib.rs +3 -2
  31. rangebar-11.3.0/docs/MEMORY_REMEDIATION_PLAN.md +348 -0
  32. rangebar-11.3.0/docs/analysis/2025-10-10-flash-crash.md +375 -0
  33. {rangebar-7.1.2 → rangebar-11.3.0}/docs/api.md +422 -13
  34. rangebar-11.3.0/docs/migration-v8.md +117 -0
  35. {rangebar-7.1.2 → rangebar-11.3.0}/docs/rangebar_core_api.md +8 -8
  36. {rangebar-7.1.2 → rangebar-11.3.0}/examples/README.md +11 -12
  37. {rangebar-7.1.2 → rangebar-11.3.0}/examples/binance_csv_example.py +1 -1
  38. {rangebar-7.1.2 → rangebar-11.3.0}/examples/with_clickhouse_cache.py +1 -1
  39. {rangebar-7.1.2 → rangebar-11.3.0}/pyproject.toml +92 -9
  40. rangebar-11.3.0/python/rangebar/__init__.py +198 -0
  41. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/__init__.pyi +299 -9
  42. rangebar-11.3.0/python/rangebar/checkpoint.py +472 -0
  43. rangebar-11.3.0/python/rangebar/cli.py +298 -0
  44. rangebar-11.3.0/python/rangebar/clickhouse/CLAUDE.md +136 -0
  45. rangebar-11.3.0/python/rangebar/clickhouse/bulk_operations.py +309 -0
  46. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/cache.py +124 -427
  47. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/preflight.py +11 -5
  48. rangebar-11.3.0/python/rangebar/clickhouse/query_operations.py +345 -0
  49. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/schema.sql +44 -1
  50. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/tunnel.py +22 -7
  51. rangebar-11.3.0/python/rangebar/constants.py +255 -0
  52. rangebar-11.3.0/python/rangebar/conversion.py +177 -0
  53. rangebar-11.3.0/python/rangebar/exceptions.py +207 -0
  54. rangebar-11.3.0/python/rangebar/exness.py +364 -0
  55. rangebar-11.3.0/python/rangebar/hooks.py +311 -0
  56. rangebar-11.3.0/python/rangebar/logging.py +171 -0
  57. rangebar-11.3.0/python/rangebar/notify/__init__.py +15 -0
  58. rangebar-11.3.0/python/rangebar/notify/pushover.py +155 -0
  59. rangebar-11.3.0/python/rangebar/notify/telegram.py +271 -0
  60. rangebar-11.3.0/python/rangebar/orchestration/__init__.py +20 -0
  61. rangebar-11.3.0/python/rangebar/orchestration/count_bounded.py +856 -0
  62. rangebar-11.3.0/python/rangebar/orchestration/helpers.py +397 -0
  63. rangebar-11.3.0/python/rangebar/orchestration/models.py +76 -0
  64. rangebar-11.3.0/python/rangebar/orchestration/precompute.py +498 -0
  65. rangebar-11.3.0/python/rangebar/orchestration/range_bars.py +726 -0
  66. rangebar-11.3.0/python/rangebar/ouroboros.py +454 -0
  67. rangebar-11.3.0/python/rangebar/processors/__init__.py +22 -0
  68. rangebar-11.3.0/python/rangebar/processors/api.py +383 -0
  69. rangebar-11.3.0/python/rangebar/processors/core.py +510 -0
  70. rangebar-11.3.0/python/rangebar/resource_guard.py +342 -0
  71. rangebar-11.3.0/python/rangebar/storage/checksum_registry.py +218 -0
  72. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/storage/parquet.py +38 -8
  73. rangebar-11.3.0/python/rangebar/validation/__init__.py +69 -0
  74. rangebar-11.3.0/python/rangebar/validation/cache_staleness.py +277 -0
  75. rangebar-11.3.0/python/rangebar/validation/continuity.py +914 -0
  76. rangebar-11.3.0/python/rangebar/validation/post_storage.py +317 -0
  77. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/validation/tier1.py +1 -1
  78. rangebar-11.3.0/scripts/analyze_flash_crash.py +206 -0
  79. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/build-release.sh +57 -27
  80. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/cache_status.py +6 -6
  81. rangebar-11.3.0/scripts/check-release-config.sh +102 -0
  82. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/publish-to-pypi.sh +47 -15
  83. rangebar-11.3.0/scripts/regenerate_cache.py +114 -0
  84. rangebar-11.3.0/scripts/semantic-release.sh +47 -0
  85. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/validate_microstructure_features.py +2 -2
  86. {rangebar-7.1.2 → rangebar-11.3.0}/src/lib.rs +572 -10
  87. rangebar-11.3.0/tests/conftest.py +50 -0
  88. rangebar-11.3.0/tests/test_cache_schema_evolution.py +409 -0
  89. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_clickhouse.py +4 -0
  90. rangebar-11.3.0/tests/test_clickhouse_integration.py +728 -0
  91. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_get_n_range_bars.py +143 -74
  92. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_get_range_bars_e2e.py +1 -1
  93. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_issue_5_reproduction.py +1 -1
  94. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_microstructure_features.py +1 -1
  95. rangebar-11.3.0/tests/test_ouroboros.py +907 -0
  96. rangebar-11.3.0/tests/test_polars_only_downstream.py +433 -0
  97. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_preflight.py +22 -14
  98. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_rust_bindings.py +111 -5
  99. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_storage.py +47 -0
  100. {rangebar-7.1.2 → rangebar-11.3.0}/uv.lock +134 -634
  101. rangebar-7.1.2/.link-check-results.md +0 -12
  102. rangebar-7.1.2/.pre-commit-config.yaml +0 -51
  103. rangebar-7.1.2/CHANGELOG.md +0 -371
  104. rangebar-7.1.2/CLAUDE.md +0 -174
  105. rangebar-7.1.2/crates/rangebar-providers/src/binance/historical.rs +0 -212
  106. rangebar-7.1.2/python/rangebar/__init__.py +0 -3636
  107. rangebar-7.1.2/python/rangebar/exness.py +0 -198
  108. rangebar-7.1.2/python/rangebar/validation/__init__.py +0 -16
  109. rangebar-7.1.2/tests/test_clickhouse_integration.py +0 -348
  110. {rangebar-7.1.2 → rangebar-11.3.0}/.releaserc.yml +0 -0
  111. {rangebar-7.1.2 → rangebar-11.3.0}/LICENSE +0 -0
  112. {rangebar-7.1.2 → rangebar-11.3.0}/benches/rangebar_bench.rs +0 -0
  113. {rangebar-7.1.2 → rangebar-11.3.0}/build.rs +0 -0
  114. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/CHANGELOG.md +0 -0
  115. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/test_data_loader.rs +0 -0
  116. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/test_utils/generators.rs +0 -0
  117. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/src/timestamp.rs +0 -0
  118. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-core/tests/cross_date_real_data_validation.rs +0 -0
  119. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/CHANGELOG.md +0 -0
  120. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/binance/symbols.rs +0 -0
  121. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/binance/websocket.rs +0 -0
  122. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/exness/client.rs +0 -0
  123. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/exness/conversion.rs +0 -0
  124. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/exness/mod.rs +0 -0
  125. {rangebar-7.1.2 → rangebar-11.3.0}/crates/rangebar-providers/src/exness/types.rs +0 -0
  126. {rangebar-7.1.2 → rangebar-11.3.0}/deny.toml +0 -0
  127. {rangebar-7.1.2 → rangebar-11.3.0}/docs/ARCHITECTURE.md +0 -0
  128. {rangebar-7.1.2 → rangebar-11.3.0}/docs/CONTEXT.md +0 -0
  129. {rangebar-7.1.2 → rangebar-11.3.0}/docs/development/PERFORMANCE.md +0 -0
  130. {rangebar-7.1.2 → rangebar-11.3.0}/docs/development/RELEASE.md +0 -0
  131. {rangebar-7.1.2 → rangebar-11.3.0}/examples/backtesting_integration.py +0 -0
  132. {rangebar-7.1.2 → rangebar-11.3.0}/examples/basic_usage.py +0 -0
  133. {rangebar-7.1.2 → rangebar-11.3.0}/examples/get_range_bars_example.py +0 -0
  134. {rangebar-7.1.2 → rangebar-11.3.0}/examples/validate_output.py +0 -0
  135. {rangebar-7.1.2 → rangebar-11.3.0}/package-lock.json +0 -0
  136. {rangebar-7.1.2 → rangebar-11.3.0}/package.json +0 -0
  137. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/CLAUDE.md +0 -0
  138. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/__init__.py +0 -0
  139. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/client.py +0 -0
  140. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/config.py +0 -0
  141. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/clickhouse/mixin.py +0 -0
  142. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/storage/__init__.py +0 -0
  143. {rangebar-7.1.2 → rangebar-11.3.0}/python/rangebar/validation/tier2.py +0 -0
  144. {rangebar-7.1.2 → rangebar-11.3.0}/rust-toolchain.toml +0 -0
  145. {rangebar-7.1.2 → rangebar-11.3.0}/rustfmt.toml +0 -0
  146. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/cache_clear.py +0 -0
  147. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/dependency_monitor.sh +0 -0
  148. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/profiling_tools.sh +0 -0
  149. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/publish-wheels.sh +0 -0
  150. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/run_large_scale_benchmark.sh +0 -0
  151. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/validate_clickhouse.py +0 -0
  152. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/validate_memory_efficiency.py +0 -0
  153. {rangebar-7.1.2 → rangebar-11.3.0}/scripts/validate_n_range_bars.py +0 -0
  154. {rangebar-7.1.2 → rangebar-11.3.0}/test_data/BTCUSDT/BTCUSDT_aggTrades_20250901.csv +0 -0
  155. {rangebar-7.1.2 → rangebar-11.3.0}/test_data/ETHUSDT/ETHUSDT_aggTrades_20250901.csv +0 -0
  156. {rangebar-7.1.2 → rangebar-11.3.0}/test_data/README.md +0 -0
  157. {rangebar-7.1.2 → rangebar-11.3.0}/tests/fixtures/.gitignore +0 -0
  158. {rangebar-7.1.2 → rangebar-11.3.0}/tests/fixtures/BTCUSDT-aggTrades-2024-01-01.zip +0 -0
  159. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_e2e_optimized.py +0 -0
  160. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_edge_cases.py +0 -0
  161. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_examples.py +0 -0
  162. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_issues_7_8.py +0 -0
  163. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_python_api.py +0 -0
  164. {rangebar-7.1.2 → rangebar-11.3.0}/tests/test_real_data.py +0 -0
  165. {rangebar-7.1.2 → rangebar-11.3.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/
@@ -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,14 +376,30 @@ 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 (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
@@ -350,8 +409,8 @@ ls -la dist/*.whl 2>/dev/null || true
350
409
  """
351
410
 
352
411
  [tasks."release:postflight"]
353
- description = "Verify and publish (Phase 4)"
354
- depends = ["smoke"]
412
+ description = "Verify and publish (Phase 4 - runs AFTER builds)"
413
+ depends = ["smoke", "release:build-all"]
355
414
  run = """
356
415
  echo "=== POSTFLIGHT ==="
357
416
  WHEEL_COUNT=$(find dist/ -name "*.whl" 2>/dev/null | wc -l | tr -d ' ')
@@ -362,59 +421,25 @@ echo "To publish: mise run publish"
362
421
  """
363
422
 
364
423
  [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
- """
424
+ description = "Bump version via semantic-release with Doppler GitHub token"
425
+ depends = ["release:sync"]
426
+ run = "./scripts/semantic-release.sh"
373
427
 
374
428
  [tasks."release:dry"]
375
429
  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
- """
430
+ 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
431
 
385
432
  [tasks."release:pypi"]
386
- description = "Publish to PyPI using Doppler credentials (local-only)"
433
+ description = "Publish to PyPI using Doppler credentials (local-only, ADR-0027)"
387
434
  run = "./scripts/publish-to-pypi.sh"
388
435
 
389
436
  [tasks."release:full"]
390
- description = "Full 4-phase release workflow"
391
- 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"
417
- """
437
+ description = "Full 4-phase release workflow (versioning only - PyPI separate)"
438
+ # Dependency chain enforced via task-level depends:
439
+ # preflight sync version → build-all → postflight
440
+ # Only need to list the leaf task; mise resolves the full chain.
441
+ depends = ["release:postflight"]
442
+ run = "echo 'Release complete! Next: mise run release:pypi'"
418
443
 
419
444
  # =============================================================================
420
445
  # Smoke Test Tasks
@@ -440,3 +465,49 @@ print("OK: basic processing works")
440
465
  [tasks.smoke]
441
466
  description = "Run all smoke tests"
442
467
  depends = ["smoke:import", "smoke:process"]
468
+
469
+ # =============================================================================
470
+ # Checksum Verification Tasks (Issue #43)
471
+ # =============================================================================
472
+
473
+ [tasks."test:checksum"]
474
+ description = "Test Rust checksum verification module"
475
+ run = "cargo nextest run -p rangebar-providers checksum"
476
+
477
+ [tasks."test:checksum:integration"]
478
+ description = "Integration test with real Binance data (requires network)"
479
+ run = """
480
+ python -c '
481
+ from rangebar import get_range_bars
482
+ import logging
483
+ logging.basicConfig(level=logging.DEBUG)
484
+
485
+ # Test with checksum verification (should see checksum events in logs)
486
+ df = get_range_bars("BTCUSDT", "2024-01-01", "2024-01-01", verify_checksum=True)
487
+ print(f"Downloaded {len(df)} bars with checksum verification")
488
+ '
489
+ """
490
+
491
+ [tasks."checksum:audit"]
492
+ description = "Audit Tier 1 cache for unverified files"
493
+ run = """
494
+ python -c '
495
+ from rangebar.storage.checksum_registry import ChecksumRegistry
496
+ registry = ChecksumRegistry()
497
+ count = registry.get_verified_count("BTCUSDT")
498
+ print(f"BTCUSDT verified dates: {count}")
499
+ '
500
+ """
501
+
502
+ [tasks."checksum:pushover-test"]
503
+ description = "Send test Pushover alert to verify credentials"
504
+ run = """
505
+ python -c '
506
+ from rangebar.notify.pushover import send_critical_alert
507
+ result = send_critical_alert(
508
+ title="🧪 RB Test Alert",
509
+ message="Checksum verification test - ignore this alert.",
510
+ )
511
+ print(f"Pushover alert sent: {result}")
512
+ '
513
+ """
@@ -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