terrine 0.1.0.dev0__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 (492) hide show
  1. terrine-0.1.0.dev0/.github/CLA.md +154 -0
  2. terrine-0.1.0.dev0/.github/workflows/ci.yml +188 -0
  3. terrine-0.1.0.dev0/.github/workflows/cla.yml +61 -0
  4. terrine-0.1.0.dev0/.github/workflows/release.yml +173 -0
  5. terrine-0.1.0.dev0/.github/workflows/scale.yml +32 -0
  6. terrine-0.1.0.dev0/.github/workflows/warehouse-backends.yml +127 -0
  7. terrine-0.1.0.dev0/.gitignore +20 -0
  8. terrine-0.1.0.dev0/.kata.toml +4 -0
  9. terrine-0.1.0.dev0/.pre-commit-config.yaml +14 -0
  10. terrine-0.1.0.dev0/.python-version +1 -0
  11. terrine-0.1.0.dev0/.roborev.toml +11 -0
  12. terrine-0.1.0.dev0/AGENTS.md +271 -0
  13. terrine-0.1.0.dev0/CHANGELOG.md +300 -0
  14. terrine-0.1.0.dev0/CLAUDE.md +1 -0
  15. terrine-0.1.0.dev0/CONTRIBUTING.md +70 -0
  16. terrine-0.1.0.dev0/LICENSE +202 -0
  17. terrine-0.1.0.dev0/Makefile +66 -0
  18. terrine-0.1.0.dev0/NOTICE +4 -0
  19. terrine-0.1.0.dev0/PKG-INFO +164 -0
  20. terrine-0.1.0.dev0/README.md +107 -0
  21. terrine-0.1.0.dev0/THIRD_PARTY_NOTICES.txt +219 -0
  22. terrine-0.1.0.dev0/benchmarks/README.md +238 -0
  23. terrine-0.1.0.dev0/benchmarks/report.py +51 -0
  24. terrine-0.1.0.dev0/benchmarks/results/duckdb-scale-v2-small.json +1 -0
  25. terrine-0.1.0.dev0/benchmarks/run_duckdb.py +288 -0
  26. terrine-0.1.0.dev0/benchmarks/run_live.py +361 -0
  27. terrine-0.1.0.dev0/benchmarks/run_overhead.py +494 -0
  28. terrine-0.1.0.dev0/benchmarks/workloads/small.json +10 -0
  29. terrine-0.1.0.dev0/benchmarks/workloads.py +338 -0
  30. terrine-0.1.0.dev0/docs/guides/backend-compatibility.md +407 -0
  31. terrine-0.1.0.dev0/docs/guides/candidate-anchors.md +26 -0
  32. terrine-0.1.0.dev0/docs/guides/capabilities.md +51 -0
  33. terrine-0.1.0.dev0/docs/guides/common-feature-patterns.md +174 -0
  34. terrine-0.1.0.dev0/docs/guides/common-stack-interop.md +143 -0
  35. terrine-0.1.0.dev0/docs/guides/cost-and-residency.md +68 -0
  36. terrine-0.1.0.dev0/docs/guides/dataset-agent-tools.md +187 -0
  37. terrine-0.1.0.dev0/docs/guides/design-specs.md +95 -0
  38. terrine-0.1.0.dev0/docs/guides/design-validation.md +35 -0
  39. terrine-0.1.0.dev0/docs/guides/first-dataset.md +123 -0
  40. terrine-0.1.0.dev0/docs/guides/increment-compatibility.md +41 -0
  41. terrine-0.1.0.dev0/docs/guides/index.md +50 -0
  42. terrine-0.1.0.dev0/docs/guides/library-handoffs.md +247 -0
  43. terrine-0.1.0.dev0/docs/guides/limitations.md +65 -0
  44. terrine-0.1.0.dev0/docs/guides/materialization-runtime.md +295 -0
  45. terrine-0.1.0.dev0/docs/guides/ml-staging.md +206 -0
  46. terrine-0.1.0.dev0/docs/guides/orchestrators.md +161 -0
  47. terrine-0.1.0.dev0/docs/guides/public-api.md +120 -0
  48. terrine-0.1.0.dev0/docs/guides/semantic-layer-interop.md +30 -0
  49. terrine-0.1.0.dev0/docs/guides/sequential-panels.md +127 -0
  50. terrine-0.1.0.dev0/docs/guides/shared-dataset-contract.md +108 -0
  51. terrine-0.1.0.dev0/docs/guides/state-panels.md +100 -0
  52. terrine-0.1.0.dev0/docs/guides/synthetic-worlds.md +70 -0
  53. terrine-0.1.0.dev0/docs/guides/temporal-attributes.md +63 -0
  54. terrine-0.1.0.dev0/docs/guides/temporal-engine.md +708 -0
  55. terrine-0.1.0.dev0/docs/guides/trajectories-survival.md +185 -0
  56. terrine-0.1.0.dev0/docs/index.md +30 -0
  57. terrine-0.1.0.dev0/docs/reference/refusals.md +498 -0
  58. terrine-0.1.0.dev0/docs/research/edge-case-designs.md +60 -0
  59. terrine-0.1.0.dev0/docs/research/landscape.md +133 -0
  60. terrine-0.1.0.dev0/docs/research/ohdsi-study-design.md +109 -0
  61. terrine-0.1.0.dev0/docs/research/point-in-time-feature-apis.md +80 -0
  62. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-16-terrine-build.md +416 -0
  63. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-16-terrine-dataset-workflows.md +164 -0
  64. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-16-terrine-study-api.md +312 -0
  65. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-16-terrine-temporal.md +345 -0
  66. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-17-terrine-frame.md +182 -0
  67. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-event-sequences.md +200 -0
  68. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-materialization-runtime.md +267 -0
  69. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-ml-staging.md +201 -0
  70. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-orchestrators.md +131 -0
  71. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-sequential-panels.md +183 -0
  72. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-trajectories-survival.md +269 -0
  73. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-18-terrine-warehouse-scale.md +163 -0
  74. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-agent-tools.md +181 -0
  75. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-fast-tests-inventory.md +478 -0
  76. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-fast-tests-ledger.md +561 -0
  77. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-fast-tests.md +145 -0
  78. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-interop.md +202 -0
  79. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-library-handoffs.md +81 -0
  80. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-19-terrine-release-readiness.md +100 -0
  81. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-20-terrine-test-tiers.md +113 -0
  82. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-21-terrine-postgres-execution.md +170 -0
  83. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-22-bigquery-execution.md +66 -0
  84. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-22-ibis-study-queries.md +73 -0
  85. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-22-postgres-float-windows.md +56 -0
  86. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-23-exact-float-windows.md +88 -0
  87. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-23-snowflake-execution.md +323 -0
  88. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-24-mutation-audit.md +80 -0
  89. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-24-test-suite-speed.md +68 -0
  90. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-26-public-readiness.md +255 -0
  91. terrine-0.1.0.dev0/docs/superpowers/plans/2026-10-26-table-first-binding-and-recipes.md +184 -0
  92. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-compile.md +345 -0
  93. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-dataset.md +136 -0
  94. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-runtime.md +180 -0
  95. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-test-tiers-misc.md +14 -0
  96. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-test-tiers-state-panels.md +37 -0
  97. terrine-0.1.0.dev0/docs/superpowers/plans/ledger-test-tiers-temporal.md +29 -0
  98. terrine-0.1.0.dev0/docs/superpowers/specs/2026-10-16-terrine-handoff.md +635 -0
  99. terrine-0.1.0.dev0/docs/superpowers/specs/2026-10-17-terrine-frame-design.md +135 -0
  100. terrine-0.1.0.dev0/docs/superpowers/specs/2026-10-18-terrine-scope-datasets-only.md +76 -0
  101. terrine-0.1.0.dev0/docs/superpowers/specs/2026-10-26-table-first-binding-and-recipes-design.md +146 -0
  102. terrine-0.1.0.dev0/evals/agent_dataset_tools.yaml +84 -0
  103. terrine-0.1.0.dev0/examples/batch_scoring.py +68 -0
  104. terrine-0.1.0.dev0/examples/bigquery/dataset.py +106 -0
  105. terrine-0.1.0.dev0/examples/common_stack_interop.py +115 -0
  106. terrine-0.1.0.dev0/examples/dataset_agent_tools.py +130 -0
  107. terrine-0.1.0.dev0/examples/event_sequences.py +190 -0
  108. terrine-0.1.0.dev0/examples/first_dataset.py +14 -0
  109. terrine-0.1.0.dev0/examples/increment_parity.py +237 -0
  110. terrine-0.1.0.dev0/examples/materialization_runtime.py +256 -0
  111. terrine-0.1.0.dev0/examples/ml_staging.py +174 -0
  112. terrine-0.1.0.dev0/examples/nonadditive_metrics.py +87 -0
  113. terrine-0.1.0.dev0/examples/orchestrators/airflow_materialization.py +43 -0
  114. terrine-0.1.0.dev0/examples/orchestrators/dagster_materialization.py +34 -0
  115. terrine-0.1.0.dev0/examples/orchestrators/dbt_core_after_build.py +85 -0
  116. terrine-0.1.0.dev0/examples/postgres/dataset.py +105 -0
  117. terrine-0.1.0.dev0/examples/retention_and_winsorization.py +82 -0
  118. terrine-0.1.0.dev0/examples/retention_metrics.py +100 -0
  119. terrine-0.1.0.dev0/examples/sequential_trials.py +133 -0
  120. terrine-0.1.0.dev0/examples/snowflake/dataset.py +149 -0
  121. terrine-0.1.0.dev0/examples/state_panel.py +190 -0
  122. terrine-0.1.0.dev0/examples/table_first_dataset.py +126 -0
  123. terrine-0.1.0.dev0/examples/trajectories_survival.py +180 -0
  124. terrine-0.1.0.dev0/integration/.test_durations +259 -0
  125. terrine-0.1.0.dev0/integration/agent/test_dataset_tool_example.py +27 -0
  126. terrine-0.1.0.dev0/integration/agent/test_dataset_tool_flow.py +80 -0
  127. terrine-0.1.0.dev0/integration/agent/test_dataset_tool_runtime.py +822 -0
  128. terrine-0.1.0.dev0/integration/backends/test_numeric.py +62 -0
  129. terrine-0.1.0.dev0/integration/compat/test_native_catalog.py +110 -0
  130. terrine-0.1.0.dev0/integration/compile/test_boolean_outputs.py +275 -0
  131. terrine-0.1.0.dev0/integration/compile/test_column_runtime_contracts.py +256 -0
  132. terrine-0.1.0.dev0/integration/compile/test_frame_runtime_window_export.py +34 -0
  133. terrine-0.1.0.dev0/integration/compile/test_ltv.py +148 -0
  134. terrine-0.1.0.dev0/integration/compile/test_retention.py +34 -0
  135. terrine-0.1.0.dev0/integration/compile/test_time_to_event.py +504 -0
  136. terrine-0.1.0.dev0/integration/conftest.py +1 -0
  137. terrine-0.1.0.dev0/integration/handoffs/__init__.py +0 -0
  138. terrine-0.1.0.dev0/integration/handoffs/conftest.py +53 -0
  139. terrine-0.1.0.dev0/integration/handoffs/test_diff_diff.py +53 -0
  140. terrine-0.1.0.dev0/integration/handoffs/test_library_handoffs.py +85 -0
  141. terrine-0.1.0.dev0/integration/handoffs/test_lifelines.py +88 -0
  142. terrine-0.1.0.dev0/integration/parity/test_increment_panel_parity.py +56 -0
  143. terrine-0.1.0.dev0/integration/state_panels/test_state_panel_workflows.py +398 -0
  144. terrine-0.1.0.dev0/integration/temporal/test_retention_bands.py +158 -0
  145. terrine-0.1.0.dev0/integration/temporal/test_window_quotient_composition.py +293 -0
  146. terrine-0.1.0.dev0/integration/test_independence.py +32 -0
  147. terrine-0.1.0.dev0/integration/test_model_from_tables.py +177 -0
  148. terrine-0.1.0.dev0/integration/warehouse_execution/bigquery_fixtures.py +80 -0
  149. terrine-0.1.0.dev0/integration/warehouse_execution/postgres_fixtures.py +68 -0
  150. terrine-0.1.0.dev0/integration/warehouse_execution/snowflake_fixtures.py +121 -0
  151. terrine-0.1.0.dev0/integration/warehouse_execution/test_backend_capabilities.py +536 -0
  152. terrine-0.1.0.dev0/integration/warehouse_execution/test_bigquery_admission.py +141 -0
  153. terrine-0.1.0.dev0/integration/warehouse_execution/test_bigquery_execution.py +28 -0
  154. terrine-0.1.0.dev0/integration/warehouse_execution/test_bigquery_parity.py +277 -0
  155. terrine-0.1.0.dev0/integration/warehouse_execution/test_duckdb_compiler_scale.py +67 -0
  156. terrine-0.1.0.dev0/integration/warehouse_execution/test_duckdb_runtime_recovery.py +83 -0
  157. terrine-0.1.0.dev0/integration/warehouse_execution/test_duckdb_scale.py +34 -0
  158. terrine-0.1.0.dev0/integration/warehouse_execution/test_incremental_equivalence.py +955 -0
  159. terrine-0.1.0.dev0/integration/warehouse_execution/test_live_warehouse_scale.py +34 -0
  160. terrine-0.1.0.dev0/integration/warehouse_execution/test_materialization_example.py +32 -0
  161. terrine-0.1.0.dev0/integration/warehouse_execution/test_ml_staging_duckdb.py +1897 -0
  162. terrine-0.1.0.dev0/integration/warehouse_execution/test_ml_staging_examples.py +62 -0
  163. terrine-0.1.0.dev0/integration/warehouse_execution/test_orchestrator_adapters.py +883 -0
  164. terrine-0.1.0.dev0/integration/warehouse_execution/test_planning.py +131 -0
  165. terrine-0.1.0.dev0/integration/warehouse_execution/test_postgres_admission.py +252 -0
  166. terrine-0.1.0.dev0/integration/warehouse_execution/test_postgres_execution.py +86 -0
  167. terrine-0.1.0.dev0/integration/warehouse_execution/test_postgres_shapes.py +249 -0
  168. terrine-0.1.0.dev0/integration/warehouse_execution/test_postgres_timestamps.py +108 -0
  169. terrine-0.1.0.dev0/integration/warehouse_execution/test_postgres_windows.py +336 -0
  170. terrine-0.1.0.dev0/integration/warehouse_execution/test_request_replay_process.py +151 -0
  171. terrine-0.1.0.dev0/integration/warehouse_execution/test_runtime_api.py +571 -0
  172. terrine-0.1.0.dev0/integration/warehouse_execution/test_runtime_cli.py +70 -0
  173. terrine-0.1.0.dev0/integration/warehouse_execution/test_runtime_control.py +63 -0
  174. terrine-0.1.0.dev0/integration/warehouse_execution/test_runtime_cost_budget.py +83 -0
  175. terrine-0.1.0.dev0/integration/warehouse_execution/test_saved_plan_restart.py +664 -0
  176. terrine-0.1.0.dev0/integration/warehouse_execution/test_snapshot_capture_bounds.py +102 -0
  177. terrine-0.1.0.dev0/integration/warehouse_execution/test_snapshot_partition_consistency.py +235 -0
  178. terrine-0.1.0.dev0/integration/warehouse_execution/test_snowflake_admission.py +342 -0
  179. terrine-0.1.0.dev0/integration/warehouse_execution/test_snowflake_execution.py +34 -0
  180. terrine-0.1.0.dev0/integration/warehouse_execution/test_snowflake_parity.py +672 -0
  181. terrine-0.1.0.dev0/integration/warehouse_execution/test_winsorization_definition.py +120 -0
  182. terrine-0.1.0.dev0/mkdocs.yml +32 -0
  183. terrine-0.1.0.dev0/pyproject.toml +126 -0
  184. terrine-0.1.0.dev0/scripts/mutate.py +218 -0
  185. terrine-0.1.0.dev0/tach.toml +109 -0
  186. terrine-0.1.0.dev0/terrine/__init__.py +120 -0
  187. terrine-0.1.0.dev0/terrine/_time.py +21 -0
  188. terrine-0.1.0.dev0/terrine/adapters/__init__.py +3 -0
  189. terrine-0.1.0.dev0/terrine/adapters/increment.py +365 -0
  190. terrine-0.1.0.dev0/terrine/adapters/opentelemetry.py +63 -0
  191. terrine-0.1.0.dev0/terrine/agent/__init__.py +6 -0
  192. terrine-0.1.0.dev0/terrine/agent/definitions.py +143 -0
  193. terrine-0.1.0.dev0/terrine/agent/design_schema.py +220 -0
  194. terrine-0.1.0.dev0/terrine/agent/policy.py +144 -0
  195. terrine-0.1.0.dev0/terrine/agent/schemas.py +285 -0
  196. terrine-0.1.0.dev0/terrine/agent/tools.py +956 -0
  197. terrine-0.1.0.dev0/terrine/backends/__init__.py +3 -0
  198. terrine-0.1.0.dev0/terrine/backends/capabilities.py +117 -0
  199. terrine-0.1.0.dev0/terrine/backends/dialect.py +55 -0
  200. terrine-0.1.0.dev0/terrine/backends/extrema.py +40 -0
  201. terrine-0.1.0.dev0/terrine/backends/joins.py +75 -0
  202. terrine-0.1.0.dev0/terrine/backends/numeric.py +657 -0
  203. terrine-0.1.0.dev0/terrine/backends/sequences.py +40 -0
  204. terrine-0.1.0.dev0/terrine/backends/timestamps.py +421 -0
  205. terrine-0.1.0.dev0/terrine/compile/__init__.py +3 -0
  206. terrine-0.1.0.dev0/terrine/compile/_asof.py +165 -0
  207. terrine-0.1.0.dev0/terrine/compile/_predicates.py +110 -0
  208. terrine-0.1.0.dev0/terrine/compile/anchors.py +492 -0
  209. terrine-0.1.0.dev0/terrine/compile/columns.py +1353 -0
  210. terrine-0.1.0.dev0/terrine/compile/cost.py +110 -0
  211. terrine-0.1.0.dev0/terrine/compile/dispatch.py +148 -0
  212. terrine-0.1.0.dev0/terrine/compile/layers.py +242 -0
  213. terrine-0.1.0.dev0/terrine/compile/materialize.py +91 -0
  214. terrine-0.1.0.dev0/terrine/compile/provenance.py +120 -0
  215. terrine-0.1.0.dev0/terrine/compile/ranges.py +91 -0
  216. terrine-0.1.0.dev0/terrine/compile/retention.py +127 -0
  217. terrine-0.1.0.dev0/terrine/compile/shapes/__init__.py +3 -0
  218. terrine-0.1.0.dev0/terrine/compile/shapes/_observations.py +502 -0
  219. terrine-0.1.0.dev0/terrine/compile/shapes/calendar_comparison.py +370 -0
  220. terrine-0.1.0.dev0/terrine/compile/shapes/cohorts.py +285 -0
  221. terrine-0.1.0.dev0/terrine/compile/shapes/event_panel.py +46 -0
  222. terrine-0.1.0.dev0/terrine/compile/shapes/event_sequence.py +498 -0
  223. terrine-0.1.0.dev0/terrine/compile/shapes/life_table.py +244 -0
  224. terrine-0.1.0.dev0/terrine/compile/shapes/ltv.py +287 -0
  225. terrine-0.1.0.dev0/terrine/compile/shapes/matched_t0.py +75 -0
  226. terrine-0.1.0.dev0/terrine/compile/shapes/sequential.py +320 -0
  227. terrine-0.1.0.dev0/terrine/compile/shapes/state_panel.py +460 -0
  228. terrine-0.1.0.dev0/terrine/compile/shapes/time_to_event.py +521 -0
  229. terrine-0.1.0.dev0/terrine/data.py +1311 -0
  230. terrine-0.1.0.dev0/terrine/dataset/__init__.py +5 -0
  231. terrine-0.1.0.dev0/terrine/dataset/export.py +463 -0
  232. terrine-0.1.0.dev0/terrine/dataset/manifest.py +254 -0
  233. terrine-0.1.0.dev0/terrine/dataset/reference.py +582 -0
  234. terrine-0.1.0.dev0/terrine/dataset/splits.py +373 -0
  235. terrine-0.1.0.dev0/terrine/dataset/training.py +114 -0
  236. terrine-0.1.0.dev0/terrine/dataset/transforms.py +182 -0
  237. terrine-0.1.0.dev0/terrine/errors.py +98 -0
  238. terrine-0.1.0.dev0/terrine/execution/__init__.py +5 -0
  239. terrine-0.1.0.dev0/terrine/execution/_bigquery.py +318 -0
  240. terrine-0.1.0.dev0/terrine/execution/_metadata.py +47 -0
  241. terrine-0.1.0.dev0/terrine/execution/_native.py +574 -0
  242. terrine-0.1.0.dev0/terrine/execution/_postgres.py +468 -0
  243. terrine-0.1.0.dev0/terrine/execution/_publish.py +299 -0
  244. terrine-0.1.0.dev0/terrine/execution/_snowflake.py +684 -0
  245. terrine-0.1.0.dev0/terrine/execution/backend.py +349 -0
  246. terrine-0.1.0.dev0/terrine/execution/gates.py +90 -0
  247. terrine-0.1.0.dev0/terrine/execution/inputs.py +923 -0
  248. terrine-0.1.0.dev0/terrine/export/__init__.py +31 -0
  249. terrine-0.1.0.dev0/terrine/export/diff_diff.py +177 -0
  250. terrine-0.1.0.dev0/terrine/export/lifelines.py +219 -0
  251. terrine-0.1.0.dev0/terrine/export/preflight.py +243 -0
  252. terrine-0.1.0.dev0/terrine/export/surrogate.py +168 -0
  253. terrine-0.1.0.dev0/terrine/frame.py +1042 -0
  254. terrine-0.1.0.dev0/terrine/model.py +397 -0
  255. terrine-0.1.0.dev0/terrine/orchestration/__init__.py +3 -0
  256. terrine-0.1.0.dev0/terrine/orchestration/airflow.py +115 -0
  257. terrine-0.1.0.dev0/terrine/orchestration/dagster.py +103 -0
  258. terrine-0.1.0.dev0/terrine/py.typed +0 -0
  259. terrine-0.1.0.dev0/terrine/recipes.py +295 -0
  260. terrine-0.1.0.dev0/terrine/runtime/__init__.py +70 -0
  261. terrine-0.1.0.dev0/terrine/runtime/api.py +803 -0
  262. terrine-0.1.0.dev0/terrine/runtime/arrow.py +98 -0
  263. terrine-0.1.0.dev0/terrine/runtime/backends/base.py +70 -0
  264. terrine-0.1.0.dev0/terrine/runtime/backends/duckdb.py +645 -0
  265. terrine-0.1.0.dev0/terrine/runtime/changes.py +71 -0
  266. terrine-0.1.0.dev0/terrine/runtime/cli.py +108 -0
  267. terrine-0.1.0.dev0/terrine/runtime/control.py +355 -0
  268. terrine-0.1.0.dev0/terrine/runtime/cost.py +211 -0
  269. terrine-0.1.0.dev0/terrine/runtime/events.py +194 -0
  270. terrine-0.1.0.dev0/terrine/runtime/execute.py +932 -0
  271. terrine-0.1.0.dev0/terrine/runtime/gc.py +43 -0
  272. terrine-0.1.0.dev0/terrine/runtime/graph.py +200 -0
  273. terrine-0.1.0.dev0/terrine/runtime/layers.py +61 -0
  274. terrine-0.1.0.dev0/terrine/runtime/leases.py +165 -0
  275. terrine-0.1.0.dev0/terrine/runtime/materialize.py +53 -0
  276. terrine-0.1.0.dev0/terrine/runtime/owner.py +57 -0
  277. terrine-0.1.0.dev0/terrine/runtime/planner.py +441 -0
  278. terrine-0.1.0.dev0/terrine/runtime/planning.py +394 -0
  279. terrine-0.1.0.dev0/terrine/runtime/saved_plan.py +337 -0
  280. terrine-0.1.0.dev0/terrine/runtime/snapshot.py +541 -0
  281. terrine-0.1.0.dev0/terrine/runtime/state.py +585 -0
  282. terrine-0.1.0.dev0/terrine/runtime/status.py +360 -0
  283. terrine-0.1.0.dev0/terrine/runtime/synchronization.py +15 -0
  284. terrine-0.1.0.dev0/terrine/semantic/__init__.py +3 -0
  285. terrine-0.1.0.dev0/terrine/semantic/bind.py +309 -0
  286. terrine-0.1.0.dev0/terrine/semantic/io.py +116 -0
  287. terrine-0.1.0.dev0/terrine/semantic/models.py +342 -0
  288. terrine-0.1.0.dev0/terrine/semantic/rules.py +113 -0
  289. terrine-0.1.0.dev0/terrine/semantic/sql.py +185 -0
  290. terrine-0.1.0.dev0/terrine/semantic/time.py +42 -0
  291. terrine-0.1.0.dev0/terrine/simulate/__init__.py +24 -0
  292. terrine-0.1.0.dev0/terrine/simulate/baseline.yaml +57 -0
  293. terrine-0.1.0.dev0/terrine/simulate/generate.py +182 -0
  294. terrine-0.1.0.dev0/terrine/simulate/scale.py +234 -0
  295. terrine-0.1.0.dev0/terrine/simulate/world.py +75 -0
  296. terrine-0.1.0.dev0/terrine/spec/__init__.py +96 -0
  297. terrine-0.1.0.dev0/terrine/spec/anchors.py +107 -0
  298. terrine-0.1.0.dev0/terrine/spec/dataset.py +260 -0
  299. terrine-0.1.0.dev0/terrine/spec/design.py +361 -0
  300. terrine-0.1.0.dev0/terrine/spec/expressions.py +440 -0
  301. terrine-0.1.0.dev0/terrine/spec/io.py +829 -0
  302. terrine-0.1.0.dev0/terrine/spec/panels.py +359 -0
  303. terrine-0.1.0.dev0/terrine/spec/sequence.py +165 -0
  304. terrine-0.1.0.dev0/terrine/spec/state_panel.py +246 -0
  305. terrine-0.1.0.dev0/terrine/spec/trajectory.py +144 -0
  306. terrine-0.1.0.dev0/terrine/spec/transforms.py +260 -0
  307. terrine-0.1.0.dev0/terrine/spec/validate.py +758 -0
  308. terrine-0.1.0.dev0/terrine/temporal/__init__.py +3 -0
  309. terrine-0.1.0.dev0/terrine/temporal/aggregate.py +688 -0
  310. terrine-0.1.0.dev0/terrine/temporal/attributes.py +389 -0
  311. terrine-0.1.0.dev0/terrine/temporal/daily.py +481 -0
  312. terrine-0.1.0.dev0/terrine/temporal/first.py +239 -0
  313. terrine-0.1.0.dev0/terrine/temporal/lookup.py +194 -0
  314. terrine-0.1.0.dev0/terrine/temporal/nonadditive.py +466 -0
  315. terrine-0.1.0.dev0/terrine/temporal/prefix.py +104 -0
  316. terrine-0.1.0.dev0/terrine/temporal/ranges.py +122 -0
  317. terrine-0.1.0.dev0/terrine/temporal/readiness.py +41 -0
  318. terrine-0.1.0.dev0/terrine/temporal/retention.py +225 -0
  319. terrine-0.1.0.dev0/terrine/temporal/sequence.py +900 -0
  320. terrine-0.1.0.dev0/terrine/temporal/sessionize.py +135 -0
  321. terrine-0.1.0.dev0/terrine/temporal/sketches.py +329 -0
  322. terrine-0.1.0.dev0/terrine/windows.py +54 -0
  323. terrine-0.1.0.dev0/tests/.test_durations +1229 -0
  324. terrine-0.1.0.dev0/tests/__init__.py +0 -0
  325. terrine-0.1.0.dev0/tests/_timing.py +3 -0
  326. terrine-0.1.0.dev0/tests/_worlds.py +126 -0
  327. terrine-0.1.0.dev0/tests/adapters/test_airflow.py +238 -0
  328. terrine-0.1.0.dev0/tests/adapters/test_dagster.py +199 -0
  329. terrine-0.1.0.dev0/tests/adapters/test_dbt_core_after_build.py +240 -0
  330. terrine-0.1.0.dev0/tests/agent/conftest.py +76 -0
  331. terrine-0.1.0.dev0/tests/agent/fixtures/catalog.yaml +19 -0
  332. terrine-0.1.0.dev0/tests/agent/test_inspect_design.py +271 -0
  333. terrine-0.1.0.dev0/tests/agent/test_materialize.py +135 -0
  334. terrine-0.1.0.dev0/tests/agent/test_plan_authorization.py +191 -0
  335. terrine-0.1.0.dev0/tests/agent/test_policy.py +71 -0
  336. terrine-0.1.0.dev0/tests/agent/test_requests.py +61 -0
  337. terrine-0.1.0.dev0/tests/agent/test_schemas.py +159 -0
  338. terrine-0.1.0.dev0/tests/backends/__init__.py +0 -0
  339. terrine-0.1.0.dev0/tests/backends/test_numeric.py +318 -0
  340. terrine-0.1.0.dev0/tests/backends/test_sequences.py +14 -0
  341. terrine-0.1.0.dev0/tests/backends/test_timestamps.py +62 -0
  342. terrine-0.1.0.dev0/tests/compat/__init__.py +0 -0
  343. terrine-0.1.0.dev0/tests/compat/fixtures/catalog.yaml +103 -0
  344. terrine-0.1.0.dev0/tests/compat/fixtures/increment.yaml +109 -0
  345. terrine-0.1.0.dev0/tests/compat/fixtures/same-name-collision.yaml +19 -0
  346. terrine-0.1.0.dev0/tests/compat/fixtures/unsupported-metric.yaml +13 -0
  347. terrine-0.1.0.dev0/tests/compat/test_increment_semantics.py +148 -0
  348. terrine-0.1.0.dev0/tests/compat/test_semantic_interop.py +28 -0
  349. terrine-0.1.0.dev0/tests/compile/__init__.py +0 -0
  350. terrine-0.1.0.dev0/tests/compile/test_anchors.py +494 -0
  351. terrine-0.1.0.dev0/tests/compile/test_cohorts.py +210 -0
  352. terrine-0.1.0.dev0/tests/compile/test_columns.py +753 -0
  353. terrine-0.1.0.dev0/tests/compile/test_completeness_columns.py +228 -0
  354. terrine-0.1.0.dev0/tests/compile/test_cost_estimates.py +29 -0
  355. terrine-0.1.0.dev0/tests/compile/test_event_sequence.py +1124 -0
  356. terrine-0.1.0.dev0/tests/compile/test_ltv.py +301 -0
  357. terrine-0.1.0.dev0/tests/compile/test_matched_t0.py +150 -0
  358. terrine-0.1.0.dev0/tests/compile/test_nonadditive.py +398 -0
  359. terrine-0.1.0.dev0/tests/compile/test_panels.py +551 -0
  360. terrine-0.1.0.dev0/tests/compile/test_persisted_layers.py +429 -0
  361. terrine-0.1.0.dev0/tests/compile/test_range_scaling.py +224 -0
  362. terrine-0.1.0.dev0/tests/compile/test_retention.py +278 -0
  363. terrine-0.1.0.dev0/tests/compile/test_state_panel.py +851 -0
  364. terrine-0.1.0.dev0/tests/compile/test_survival_bounds.py +39 -0
  365. terrine-0.1.0.dev0/tests/compile/test_time_to_event.py +461 -0
  366. terrine-0.1.0.dev0/tests/compile/test_winsorization.py +98 -0
  367. terrine-0.1.0.dev0/tests/conftest.py +60 -0
  368. terrine-0.1.0.dev0/tests/dataset/__init__.py +0 -0
  369. terrine-0.1.0.dev0/tests/dataset/test_definition.py +171 -0
  370. terrine-0.1.0.dev0/tests/dataset/test_label_support.py +97 -0
  371. terrine-0.1.0.dev0/tests/dataset/test_manifest.py +127 -0
  372. terrine-0.1.0.dev0/tests/dataset/test_runtime_staging.py +64 -0
  373. terrine-0.1.0.dev0/tests/dataset/test_splits.py +173 -0
  374. terrine-0.1.0.dev0/tests/dataset/test_staging.py +28 -0
  375. terrine-0.1.0.dev0/tests/dataset/test_training_view.py +298 -0
  376. terrine-0.1.0.dev0/tests/dataset/test_winsorization_definition.py +69 -0
  377. terrine-0.1.0.dev0/tests/documentation.py +236 -0
  378. terrine-0.1.0.dev0/tests/execution/__init__.py +0 -0
  379. terrine-0.1.0.dev0/tests/execution/test_backend_provider.py +272 -0
  380. terrine-0.1.0.dev0/tests/execution/test_inputs.py +631 -0
  381. terrine-0.1.0.dev0/tests/execution/test_snowflake_session.py +204 -0
  382. terrine-0.1.0.dev0/tests/export/conftest.py +60 -0
  383. terrine-0.1.0.dev0/tests/export/test_diff_diff.py +136 -0
  384. terrine-0.1.0.dev0/tests/export/test_lifelines.py +228 -0
  385. terrine-0.1.0.dev0/tests/export/test_preflight.py +115 -0
  386. terrine-0.1.0.dev0/tests/export/test_surrogate.py +103 -0
  387. terrine-0.1.0.dev0/tests/export/test_warehouse_preflight.py +105 -0
  388. terrine-0.1.0.dev0/tests/fixtures/__init__.py +0 -0
  389. terrine-0.1.0.dev0/tests/fixtures/baseline.py +260 -0
  390. terrine-0.1.0.dev0/tests/fixtures/interop.py +117 -0
  391. terrine-0.1.0.dev0/tests/fixtures/materialized_frame_v1.json +1 -0
  392. terrine-0.1.0.dev0/tests/fixtures/pre_rename_definition.json +1 -0
  393. terrine-0.1.0.dev0/tests/fixtures/pre_rename_fitted_definition.json +1 -0
  394. terrine-0.1.0.dev0/tests/fixtures/pre_rename_fitted_transform.json +1 -0
  395. terrine-0.1.0.dev0/tests/fixtures/pre_rename_invocation.json +1 -0
  396. terrine-0.1.0.dev0/tests/fixtures/pre_rename_manifest.json +1 -0
  397. terrine-0.1.0.dev0/tests/fixtures/pre_rename_plan_request.json +1 -0
  398. terrine-0.1.0.dev0/tests/fixtures/pre_rename_saved_plan.json +1 -0
  399. terrine-0.1.0.dev0/tests/fixtures/test_baseline.py +68 -0
  400. terrine-0.1.0.dev0/tests/fixtures/winsorization.py +98 -0
  401. terrine-0.1.0.dev0/tests/integration/__init__.py +0 -0
  402. terrine-0.1.0.dev0/tests/integration/distribution_smoke.py +253 -0
  403. terrine-0.1.0.dev0/tests/integration/postgres_scratch.py +122 -0
  404. terrine-0.1.0.dev0/tests/integration/study_api_smoke.py +232 -0
  405. terrine-0.1.0.dev0/tests/integration/test_benchmark_failure_reporting.py +167 -0
  406. terrine-0.1.0.dev0/tests/integration/test_live_scale_gate.py +169 -0
  407. terrine-0.1.0.dev0/tests/parity/__init__.py +0 -0
  408. terrine-0.1.0.dev0/tests/parity/test_increment_frames.py +225 -0
  409. terrine-0.1.0.dev0/tests/reference/__init__.py +0 -0
  410. terrine-0.1.0.dev0/tests/reference/baseline.py +135 -0
  411. terrine-0.1.0.dev0/tests/reference/nonadditive.py +13 -0
  412. terrine-0.1.0.dev0/tests/reference/panels.py +133 -0
  413. terrine-0.1.0.dev0/tests/reference/ranges.py +42 -0
  414. terrine-0.1.0.dev0/tests/reference/retention.py +69 -0
  415. terrine-0.1.0.dev0/tests/reference/scale_metrics.py +94 -0
  416. terrine-0.1.0.dev0/tests/reference/test_baseline.py +120 -0
  417. terrine-0.1.0.dev0/tests/reference/test_event_sequences.py +153 -0
  418. terrine-0.1.0.dev0/tests/reference/test_panels.py +80 -0
  419. terrine-0.1.0.dev0/tests/runtime/__init__.py +0 -0
  420. terrine-0.1.0.dev0/tests/runtime/test_api.py +598 -0
  421. terrine-0.1.0.dev0/tests/runtime/test_arrow_output.py +40 -0
  422. terrine-0.1.0.dev0/tests/runtime/test_backend_capabilities.py +237 -0
  423. terrine-0.1.0.dev0/tests/runtime/test_batch_cleanup.py +51 -0
  424. terrine-0.1.0.dev0/tests/runtime/test_cancel_publication.py +166 -0
  425. terrine-0.1.0.dev0/tests/runtime/test_cli.py +256 -0
  426. terrine-0.1.0.dev0/tests/runtime/test_control_ipc.py +123 -0
  427. terrine-0.1.0.dev0/tests/runtime/test_control_recovery.py +188 -0
  428. terrine-0.1.0.dev0/tests/runtime/test_cost_estimates.py +372 -0
  429. terrine-0.1.0.dev0/tests/runtime/test_duckdb_publication.py +399 -0
  430. terrine-0.1.0.dev0/tests/runtime/test_execute.py +1247 -0
  431. terrine-0.1.0.dev0/tests/runtime/test_gc.py +133 -0
  432. terrine-0.1.0.dev0/tests/runtime/test_graph.py +117 -0
  433. terrine-0.1.0.dev0/tests/runtime/test_imports.py +22 -0
  434. terrine-0.1.0.dev0/tests/runtime/test_invalidation.py +118 -0
  435. terrine-0.1.0.dev0/tests/runtime/test_layers.py +325 -0
  436. terrine-0.1.0.dev0/tests/runtime/test_leases.py +115 -0
  437. terrine-0.1.0.dev0/tests/runtime/test_opentelemetry.py +86 -0
  438. terrine-0.1.0.dev0/tests/runtime/test_planner.py +437 -0
  439. terrine-0.1.0.dev0/tests/runtime/test_planning.py +284 -0
  440. terrine-0.1.0.dev0/tests/runtime/test_recovery_lease.py +41 -0
  441. terrine-0.1.0.dev0/tests/runtime/test_request_replay.py +195 -0
  442. terrine-0.1.0.dev0/tests/runtime/test_run_events.py +213 -0
  443. terrine-0.1.0.dev0/tests/runtime/test_run_status.py +173 -0
  444. terrine-0.1.0.dev0/tests/runtime/test_saved_plan.py +445 -0
  445. terrine-0.1.0.dev0/tests/runtime/test_snapshot.py +329 -0
  446. terrine-0.1.0.dev0/tests/runtime/test_snapshot_lifecycle.py +297 -0
  447. terrine-0.1.0.dev0/tests/runtime/test_state.py +184 -0
  448. terrine-0.1.0.dev0/tests/semantic/__init__.py +0 -0
  449. terrine-0.1.0.dev0/tests/semantic/test_catalog.py +458 -0
  450. terrine-0.1.0.dev0/tests/semantic/test_metric_rules.py +41 -0
  451. terrine-0.1.0.dev0/tests/semantic/test_rules_import.py +29 -0
  452. terrine-0.1.0.dev0/tests/semantic/test_sql.py +32 -0
  453. terrine-0.1.0.dev0/tests/simulate/__init__.py +0 -0
  454. terrine-0.1.0.dev0/tests/simulate/test_scale_generator.py +177 -0
  455. terrine-0.1.0.dev0/tests/simulate/test_world.py +98 -0
  456. terrine-0.1.0.dev0/tests/spec/__init__.py +0 -0
  457. terrine-0.1.0.dev0/tests/spec/test_calendar_comparison.py +88 -0
  458. terrine-0.1.0.dev0/tests/spec/test_design_io.py +279 -0
  459. terrine-0.1.0.dev0/tests/spec/test_expressions.py +54 -0
  460. terrine-0.1.0.dev0/tests/spec/test_nonadditive_spec.py +94 -0
  461. terrine-0.1.0.dev0/tests/spec/test_panels.py +172 -0
  462. terrine-0.1.0.dev0/tests/spec/test_recipes.py +360 -0
  463. terrine-0.1.0.dev0/tests/spec/test_retention.py +27 -0
  464. terrine-0.1.0.dev0/tests/spec/test_sequence.py +113 -0
  465. terrine-0.1.0.dev0/tests/spec/test_sketch_refusal.py +94 -0
  466. terrine-0.1.0.dev0/tests/spec/test_state_panel.py +103 -0
  467. terrine-0.1.0.dev0/tests/spec/test_validate.py +982 -0
  468. terrine-0.1.0.dev0/tests/temporal/__init__.py +0 -0
  469. terrine-0.1.0.dev0/tests/temporal/test_first_occurrence.py +230 -0
  470. terrine-0.1.0.dev0/tests/temporal/test_nonadditive.py +66 -0
  471. terrine-0.1.0.dev0/tests/temporal/test_prefix_lookup.py +249 -0
  472. terrine-0.1.0.dev0/tests/temporal/test_range_scaling.py +243 -0
  473. terrine-0.1.0.dev0/tests/temporal/test_readiness.py +16 -0
  474. terrine-0.1.0.dev0/tests/temporal/test_retention.py +386 -0
  475. terrine-0.1.0.dev0/tests/temporal/test_scd2_attributes.py +363 -0
  476. terrine-0.1.0.dev0/tests/temporal/test_semantic_binding.py +451 -0
  477. terrine-0.1.0.dev0/tests/temporal/test_sequence.py +293 -0
  478. terrine-0.1.0.dev0/tests/temporal/test_sessionize.py +206 -0
  479. terrine-0.1.0.dev0/tests/temporal/test_sketches.py +86 -0
  480. terrine-0.1.0.dev0/tests/temporal/test_sparse_state.py +543 -0
  481. terrine-0.1.0.dev0/tests/temporal/test_window_aggregates.py +391 -0
  482. terrine-0.1.0.dev0/tests/test_common_stack_interop.py +32 -0
  483. terrine-0.1.0.dev0/tests/test_distribution.py +21 -0
  484. terrine-0.1.0.dev0/tests/test_documentation.py +65 -0
  485. terrine-0.1.0.dev0/tests/test_errors.py +45 -0
  486. terrine-0.1.0.dev0/tests/test_frame.py +74 -0
  487. terrine-0.1.0.dev0/tests/test_frame_runtime.py +297 -0
  488. terrine-0.1.0.dev0/tests/test_metadata.py +453 -0
  489. terrine-0.1.0.dev0/tests/test_mutation_runner.py +33 -0
  490. terrine-0.1.0.dev0/tests/test_optional_dependencies.py +48 -0
  491. terrine-0.1.0.dev0/tests/test_windows.py +28 -0
  492. terrine-0.1.0.dev0/uv.lock +5333 -0
@@ -0,0 +1,154 @@
1
+ # terrine Individual Contributor License Agreement
2
+
3
+ Version 1.0 · effective 2026-10-20
4
+
5
+ The signature record stores the commit at which you signed, so the exact text
6
+ you agreed to is always recoverable from this file's git history. If this
7
+ Agreement is revised, the version above changes and existing signatures remain
8
+ bound to the version in force when they were made.
9
+
10
+ Thank you for your interest in contributing to terrine (the "Project"),
11
+ owned by Kyle Caron ("Owner", "we", "us").
12
+
13
+ This agreement clarifies the intellectual property license granted with
14
+ Contributions from any person or entity. It protects both you and the Owner;
15
+ it does **not** change your rights to use your own Contributions for any other
16
+ purpose.
17
+
18
+ **You keep the copyright in everything you contribute.** This is a license, not
19
+ an assignment. You are free to use, sell, relicense, and redistribute your own
20
+ Contributions however you wish, with no obligation to us.
21
+
22
+ You accept and agree to the following terms for your present and future
23
+ Contributions to the Project.
24
+
25
+ ## 1. Definitions
26
+
27
+ "You" (or "Your") means the copyright owner, or the legal entity authorized by
28
+ the copyright owner, entering into this Agreement.
29
+
30
+ "Contribution" means any original work of authorship, including any
31
+ modifications to or additions to an existing work, that is or previously has
32
+ been intentionally submitted by You to the Owner for inclusion in, or
33
+ documentation of, the Project. "Submitted" means any form of electronic,
34
+ verbal, or written communication sent to the Owner or its representatives,
35
+ including but not limited to communication on electronic mailing lists, source
36
+ code control systems, and issue tracking systems that are managed by, or on
37
+ behalf of, the Owner for the purpose of discussing and improving the Project,
38
+ but excluding communication that is conspicuously marked or otherwise
39
+ designated in writing by You as "Not a Contribution."
40
+
41
+ ## 2. Grant of Copyright License
42
+
43
+ Subject to the terms and conditions of this Agreement, You hereby grant to the
44
+ Owner and to recipients of software distributed by the Owner a perpetual,
45
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable, **transferable
46
+ and assignable** copyright license to reproduce, prepare derivative works of,
47
+ publicly display, publicly perform, **sublicense**, and distribute Your
48
+ Contributions and such derivative works.
49
+
50
+ The Owner may assign this Agreement, and the licenses granted under it, to a
51
+ successor in interest to the Project, including by merger, reorganization, or
52
+ sale of the assets to which the Project relates. This Agreement binds and
53
+ benefits the Owner's successors and assigns.
54
+
55
+ ## 3. Right to License Under Any Terms
56
+
57
+ You acknowledge and agree that the Owner may license, sublicense, and
58
+ distribute Your Contributions — alone or as part of the Project — **under any
59
+ license terms the Owner chooses**, including open source licenses, source
60
+ available licenses, and proprietary or commercial licenses, and that the Owner
61
+ may offer the Project under multiple licenses simultaneously (dual licensing).
62
+
63
+ The Owner is under no obligation to distribute Your Contributions under the
64
+ license currently applied to the Project.
65
+
66
+ This clause exists so that the Owner can sustain the Project commercially. It
67
+ does not restrict You: the rights You grant here are non-exclusive, and Your
68
+ own rights in Your Contributions are unaffected.
69
+
70
+ ## 4. Grant of Patent License
71
+
72
+ Subject to the terms and conditions of this Agreement, You hereby grant to the
73
+ Owner and to recipients of software distributed by the Owner a perpetual,
74
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as
75
+ stated in this section) patent license to make, have made, use, offer to sell,
76
+ sell, import, and otherwise transfer the Project, where such license applies
77
+ only to those patent claims licensable by You that are necessarily infringed by
78
+ Your Contribution(s) alone or by combination of Your Contribution(s) with the
79
+ Project to which such Contribution(s) was submitted.
80
+
81
+ If any entity institutes patent litigation against You or any other entity
82
+ (including a cross-claim or counterclaim in a lawsuit) alleging that Your
83
+ Contribution, or the Project to which You have contributed, constitutes direct
84
+ or contributory patent infringement, then any patent licenses granted to that
85
+ entity under this Agreement for that Contribution or Project shall terminate as
86
+ of the date such litigation is filed.
87
+
88
+ ## 5. You Represent That You Are Entitled To Grant This License
89
+
90
+ You represent that You are legally entitled to grant the above license. If Your
91
+ employer(s) has rights to intellectual property that You create that includes
92
+ Your Contributions, You represent that You have received permission to make
93
+ Contributions on behalf of that employer, that You will have received
94
+ permission from Your current and future employers for all future
95
+ Contributions, that Your employer has waived such rights for all of Your
96
+ current and future Contributions to the Owner, or that Your employer has
97
+ executed a Corporate Contributor License Agreement with the Owner.
98
+
99
+ ## 6. You Represent That Each Contribution Is Your Original Creation
100
+
101
+ You represent that each of Your Contributions is Your original creation. You
102
+ represent that Your Contribution submissions include complete details of any
103
+ third-party license or other restriction (including, but not limited to,
104
+ related patents and trademarks) of which You are personally aware and which are
105
+ associated with any part of Your Contributions.
106
+
107
+ ## 7. Third-Party Work
108
+
109
+ Should You wish to submit work that is not Your original creation, You may
110
+ submit it to the Owner separately from any Contribution, identifying the
111
+ complete details of its source and of any license or other restriction
112
+ (including, but not limited to, related patents, trademarks, and license
113
+ agreements) of which You are personally aware, and conspicuously marking the
114
+ work as "Submitted on behalf of a third-party: [named here]".
115
+
116
+ ## 8. No Obligation of Support or Warranty
117
+
118
+ You are not expected to provide support for Your Contributions, except to the
119
+ extent You desire to provide support. You may provide support for free, for a
120
+ fee, or not at all. Unless required by applicable law or agreed to in writing,
121
+ You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR
122
+ CONDITIONS OF ANY KIND, either express or implied, including, without
123
+ limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
124
+ MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
125
+
126
+ ## 9. Notification of Changed Circumstances
127
+
128
+ You agree to notify the Owner of any facts or circumstances of which You become
129
+ aware that would make these representations inaccurate in any respect.
130
+
131
+ ## Signing
132
+
133
+ Contributions are accepted only from signers of this Agreement, except for
134
+ automated accounts and coding agents named in the workflow allowlist, which
135
+ cannot themselves sign; the human opening the pull request remains responsible
136
+ for the representations above.
137
+
138
+ Sign electronically by commenting the following on your pull request, exactly:
139
+
140
+ ```
141
+ I have read the CLA Document and I hereby sign the CLA
142
+ ```
143
+
144
+ You sign once; the signature covers all of Your Contributions to the Project,
145
+ past and future.
146
+
147
+ **Record kept.** Signing stores your GitHub username, the text of your comment,
148
+ and a timestamp in the `cla-signatures` branch of this repository. That record
149
+ is retained for as long as the Project exists, because it is the evidence of
150
+ the licenses granted above. It is public if this repository is public.
151
+
152
+ If you are contributing on behalf of a company and your employer requires its
153
+ own agreement rather than the representations in section 5, contact
154
+ kyle.j.caron@gmail.com before opening a pull request.
@@ -0,0 +1,188 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ workflow_dispatch:
7
+
8
+ # A newer push supersedes an in-flight run of the same ref.
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+
14
+ jobs:
15
+ checks:
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 30
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ - uses: astral-sh/setup-uv@v5
21
+ with:
22
+ enable-cache: true
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.13"
26
+ - run: uv sync --locked --group dev --group docs --all-extras
27
+ - run: make lint
28
+ - run: make typecheck
29
+ unit:
30
+ runs-on: ubuntu-latest
31
+ timeout-minutes: 30
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ group: [1, 2, 3, 4]
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+ - uses: astral-sh/setup-uv@v5
39
+ with:
40
+ enable-cache: true
41
+ - uses: actions/setup-python@v5
42
+ with:
43
+ python-version: "3.13"
44
+ - run: uv sync --locked --group dev --all-extras
45
+ - run: >-
46
+ uv run pytest -q tests
47
+ --splits 4 --group ${{ matrix.group }}
48
+ --splitting-algorithm least_duration
49
+ --durations-path tests/.test_durations
50
+ integration:
51
+ runs-on: ubuntu-latest
52
+ timeout-minutes: 30
53
+ strategy:
54
+ fail-fast: false
55
+ matrix:
56
+ # Groups are balanced from integration/.test_durations; tests without a
57
+ # stored duration get the average and are still assigned to a group.
58
+ group: [1, 2, 3, 4, 5, 6]
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ - uses: astral-sh/setup-uv@v5
62
+ with:
63
+ enable-cache: true
64
+ - uses: actions/setup-python@v5
65
+ with:
66
+ python-version: "3.13"
67
+ - run: uv sync --locked --group dev --all-extras
68
+ - if: matrix.group == 1
69
+ run: uv run python -m tests.integration.study_api_smoke
70
+ - run: >-
71
+ uv run pytest -q integration
72
+ --splits 6 --group ${{ matrix.group }}
73
+ --splitting-algorithm least_duration
74
+ --durations-path integration/.test_durations
75
+ docs-and-examples:
76
+ runs-on: ubuntu-latest
77
+ timeout-minutes: 30
78
+ steps:
79
+ - uses: actions/checkout@v4
80
+ - uses: astral-sh/setup-uv@v5
81
+ with:
82
+ enable-cache: true
83
+ - uses: actions/setup-python@v5
84
+ with:
85
+ python-version: "3.13"
86
+ - run: uv sync --locked --group dev --group docs --all-extras
87
+ - run: |
88
+ for example in examples/*.py; do
89
+ uv run python "$example"
90
+ done
91
+ - run: uv run --group docs python -m tests.documentation --build
92
+ - run: uv build
93
+ distributions:
94
+ runs-on: ubuntu-latest
95
+ strategy:
96
+ fail-fast: false
97
+ matrix:
98
+ python: ["3.13", "3.14"]
99
+ resolution: [highest, lowest-direct]
100
+ steps:
101
+ - uses: actions/checkout@v4
102
+ - uses: astral-sh/setup-uv@v5
103
+ with:
104
+ enable-cache: true
105
+ - uses: actions/setup-python@v5
106
+ with:
107
+ python-version: ${{ matrix.python }}
108
+ - run: uv build
109
+ - run: >-
110
+ uv run --no-project --python "${{ matrix.python }}" python
111
+ -m tests.integration.distribution_smoke
112
+ --wheel dist/*.whl --sdist dist/*.tar.gz
113
+ --python "${{ matrix.python }}" --resolution "${{ matrix.resolution }}"
114
+ sketches:
115
+ runs-on: ubuntu-latest
116
+ steps:
117
+ - uses: actions/checkout@v4
118
+ - uses: astral-sh/setup-uv@v5
119
+ with:
120
+ enable-cache: true
121
+ - uses: actions/setup-python@v5
122
+ with:
123
+ python-version: "3.13"
124
+ - run: uv sync --group dev --extra duckdb --extra pandas --extra sketches
125
+ - run: uv run pytest tests/temporal/test_sketches.py tests/spec/test_sketch_refusal.py tests/compile/test_nonadditive.py -q
126
+
127
+ postgres:
128
+ uses: ./.github/workflows/warehouse-backends.yml
129
+ with:
130
+ backend_mode: postgres
131
+
132
+ increment-compatibility:
133
+ runs-on: ubuntu-latest
134
+ steps:
135
+ - uses: actions/checkout@v4
136
+ - uses: astral-sh/setup-uv@v5
137
+ with:
138
+ enable-cache: true
139
+ - uses: actions/setup-python@v5
140
+ with:
141
+ python-version: "3.13"
142
+ - run: uv sync --locked --group dev --extra duckdb --extra increment
143
+ - run: uv run pytest tests/compat tests/parity
144
+ - run: uv run pytest integration/parity
145
+
146
+ library-handoffs:
147
+ runs-on: ubuntu-latest
148
+ steps:
149
+ - uses: actions/checkout@v4
150
+ - uses: astral-sh/setup-uv@v5
151
+ with:
152
+ enable-cache: true
153
+ - uses: actions/setup-python@v5
154
+ with:
155
+ python-version: "3.13"
156
+ - run: uv sync --locked --group dev --extra duckdb --extra doubleml --extra dowhy --extra duckreg --extra lifelines --extra diff-diff
157
+ - run: uv run pytest -q integration/handoffs
158
+
159
+ # Single check to require in branch protection. Matrix jobs report one check
160
+ # per entry, so requiring them individually means editing the ruleset every
161
+ # time a matrix changes.
162
+ ci-ok:
163
+ runs-on: ubuntu-latest
164
+ timeout-minutes: 5
165
+ needs:
166
+ - checks
167
+ - unit
168
+ - integration
169
+ - docs-and-examples
170
+ - distributions
171
+ - sketches
172
+ - postgres
173
+ - increment-compatibility
174
+ - library-handoffs
175
+ if: always()
176
+ permissions: {}
177
+ steps:
178
+ - name: Require every job to succeed
179
+ env:
180
+ NEEDS: ${{ toJSON(needs) }}
181
+ run: |
182
+ set -euo pipefail
183
+ echo "$NEEDS" | jq -r 'to_entries[] | "\(.key): \(.value.result)"'
184
+ failed=$(echo "$NEEDS" | jq -r '[to_entries[] | select(.value.result != "success") | .key] | join(", ")')
185
+ if [ -n "$failed" ]; then
186
+ echo "::error::jobs did not succeed: $failed"
187
+ exit 1
188
+ fi
@@ -0,0 +1,61 @@
1
+ name: cla
2
+
3
+ # Signatures are committed to the `cla-signatures` branch of this repo using
4
+ # the job's GITHUB_TOKEN, which is why `contents: write` below is required.
5
+
6
+ on:
7
+ issue_comment: {types: [created]}
8
+ pull_request_target: {types: [opened, closed, reopened, synchronize]}
9
+
10
+ concurrency:
11
+ # Recording a signature is a read-modify-write on one JSON file guarded by a
12
+ # SHA precondition; concurrent signings would race and one would 409.
13
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.issue.number }}
14
+ cancel-in-progress: false
15
+
16
+ permissions: {}
17
+
18
+ jobs:
19
+ cla:
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 10
22
+ permissions:
23
+ actions: write
24
+ contents: write
25
+ pull-requests: write
26
+ statuses: write
27
+ # Write scopes on a pull_request_target job are safe only while nothing
28
+ # here checks out or executes PR-controlled content. Don't add a checkout
29
+ # or build step.
30
+ steps:
31
+ # Maintained fork of the archived contributor-assistant/github-action,
32
+ # pinned by SHA because this job holds write scopes under
33
+ # pull_request_target.
34
+ - uses: iainmcgin/cla-github-action@0d27e5a16278d4adb6b0c4b92f08ad27b0a21dc8 # v3.2.0
35
+ # Without this guard the action runs on every comment on every plain
36
+ # issue, where there is no pull request to resolve, and fails the check.
37
+ if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
38
+ env:
39
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40
+ with:
41
+ path-to-document: ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.event.repository.default_branch }}/.github/CLA.md
42
+ path-to-signatures: signatures/v1/cla.json
43
+ branch: cla-signatures
44
+ # AI coding agents add Co-authored-by trailers; they are counted as
45
+ # committers but cannot comment to sign, so they must be allowlisted
46
+ # or every agent-assisted PR blocks permanently.
47
+ # Name automated accounts explicitly; a wildcard such as bot* would also
48
+ # exempt human accounts whose names start with "bot".
49
+ allowlist: kylejcaron,dependabot[bot],renovate[bot],github-actions[bot],copilot,Copilot,Codex,Cursor,noreply@anthropic.com,cursoragent@cursor.com,codex@openai.com
50
+ # Fail the check when the PR opener authored none of the commits.
51
+ require-opener-as-author: true
52
+ lock-pullrequest-aftermerge: false
53
+ custom-pr-sign-comment: I have read the CLA Document and I hereby sign the CLA
54
+ custom-notsigned-prcomment: >
55
+ Thanks for the pull request. Before it can be merged, please read
56
+ the [Contributor License Agreement](${{ github.server_url }}/${{ github.repository }}/blob/${{ github.event.repository.default_branch }}/.github/CLA.md)
57
+ and sign it by posting the comment below. You keep the copyright in
58
+ your work; the CLA grants terrine's owner the right to license it,
59
+ including commercially. You sign once and it covers all your future
60
+ contributions.
61
+ custom-allsigned-prcomment: CLA signed by all contributors. Thank you.
@@ -0,0 +1,173 @@
1
+ name: release
2
+
3
+ # Tag-driven release: pushing a vX.Y.Z tag whose version equals
4
+ # `project.version` in pyproject.toml builds, verifies and publishes to PyPI,
5
+ # then creates a GitHub Release.
6
+ #
7
+ # Publishing uses PyPI Trusted Publishing (OIDC). No API token is stored.
8
+ # PyPI publisher settings:
9
+ # owner: kylejcaron repository: terrine
10
+ # workflow: release.yml environment: pypi
11
+ # Configure required reviewers on the `pypi` environment so a pushed tag alone
12
+ # cannot publish.
13
+
14
+ on:
15
+ push:
16
+ tags: ["v*"]
17
+ workflow_dispatch:
18
+
19
+ concurrency:
20
+ group: release-${{ github.ref }}
21
+ cancel-in-progress: false
22
+
23
+ permissions: {}
24
+
25
+ jobs:
26
+ build:
27
+ runs-on: ubuntu-latest
28
+ timeout-minutes: 15
29
+ permissions:
30
+ contents: read
31
+ outputs:
32
+ version: ${{ steps.check.outputs.version }}
33
+ prerelease: ${{ steps.check.outputs.prerelease }}
34
+ steps:
35
+ - name: Require a version tag
36
+ env:
37
+ REF: ${{ github.ref }}
38
+ run: |
39
+ set -euo pipefail
40
+ case "$REF" in
41
+ refs/tags/v*) ;;
42
+ *) echo "::error::release requires a v* tag ref, not a branch"; exit 1 ;;
43
+ esac
44
+
45
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46
+ with:
47
+ persist-credentials: false
48
+
49
+ - uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
50
+ with:
51
+ enable-cache: true
52
+
53
+ - run: uv build --sdist --wheel --out-dir dist
54
+
55
+ - name: Verify built version matches the tag
56
+ id: check
57
+ shell: bash
58
+ run: |
59
+ set -euo pipefail
60
+ tag="${GITHUB_REF_NAME#v}"
61
+ # Wheel filename is {name}-{version}-{python}-{abi}-{platform}.whl
62
+ whl=$(ls dist/*.whl)
63
+ built=$(basename "$whl" | cut -d- -f2)
64
+ echo "tag=$tag built=$built"
65
+
66
+ if [ "$tag" != "$built" ]; then
67
+ echo "::error::tag v$tag does not match built version $built (pyproject.toml project.version)."
68
+ exit 1
69
+ fi
70
+
71
+ # PyPI rejects PEP 440 local versions; fail before publishing.
72
+ case "$built" in
73
+ *+*) echo "::error::version $built has a local segment; PyPI will reject it"; exit 1 ;;
74
+ esac
75
+
76
+ # a/b/rc/dev -> mark the GitHub Release as a prerelease
77
+ if printf '%s' "$built" | grep -Eq '(a|b|rc|\.dev)[0-9]+'; then
78
+ echo "prerelease=true" >> "$GITHUB_OUTPUT"
79
+ else
80
+ echo "prerelease=false" >> "$GITHUB_OUTPUT"
81
+ fi
82
+ echo "version=$built" >> "$GITHUB_OUTPUT"
83
+
84
+ - name: Check metadata renders on PyPI
85
+ run: uvx twine check --strict dist/*
86
+
87
+ - name: Verify artifacts actually contain the package
88
+ shell: bash
89
+ run: |
90
+ set -euo pipefail
91
+ # hatchling builds a metadata-only wheel when the package directory is
92
+ # missing; refuse to publish an empty package, since PyPI versions can
93
+ # never be reused.
94
+ python3 - <<'PY'
95
+ import glob, sys, tarfile, zipfile
96
+
97
+ def one(pattern):
98
+ hits = glob.glob(pattern)
99
+ if not hits:
100
+ sys.exit(f"::error::no artifact matching {pattern} -- the build produced nothing")
101
+ if len(hits) > 1:
102
+ sys.exit(f"::error::expected exactly one {pattern}, found {len(hits)}: {hits}")
103
+ return hits[0]
104
+
105
+ whl = one("dist/*.whl")
106
+ mods = [n for n in zipfile.ZipFile(whl).namelist()
107
+ if n.startswith("terrine/") and n.endswith(".py")]
108
+ if not mods:
109
+ sys.exit(f"::error::{whl} contains no terrine/*.py modules")
110
+ print(f"wheel: {len(mods)} module(s)")
111
+
112
+ sdist = one("dist/*.tar.gz")
113
+ with tarfile.open(sdist) as tf:
114
+ src = [n for n in tf.getnames()
115
+ if "/terrine/" in n and n.endswith(".py")]
116
+ if not src:
117
+ sys.exit(f"::error::{sdist} contains no terrine/ sources")
118
+ print(f"sdist: {len(src)} module(s)")
119
+ PY
120
+
121
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
122
+ with:
123
+ name: dist
124
+ path: dist/
125
+ if-no-files-found: error
126
+
127
+ publish:
128
+ needs: build
129
+ runs-on: ubuntu-latest
130
+ timeout-minutes: 15
131
+ environment:
132
+ name: pypi
133
+ url: https://pypi.org/project/terrine/${{ needs.build.outputs.version }}
134
+ permissions:
135
+ # OIDC token for Trusted Publishing. This is the only credential used.
136
+ id-token: write
137
+ steps:
138
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
139
+ with:
140
+ name: dist
141
+ path: dist/
142
+
143
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
144
+ with:
145
+ attestations: true
146
+ print-hash: true
147
+
148
+ github-release:
149
+ needs: [build, publish]
150
+ runs-on: ubuntu-latest
151
+ timeout-minutes: 10
152
+ permissions:
153
+ contents: write
154
+ steps:
155
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
156
+ with:
157
+ persist-credentials: false
158
+
159
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
160
+ with:
161
+ name: dist
162
+ path: dist/
163
+
164
+ - name: Create GitHub Release
165
+ env:
166
+ GH_TOKEN: ${{ github.token }}
167
+ TAG: ${{ github.ref_name }}
168
+ PRERELEASE: ${{ needs.build.outputs.prerelease }}
169
+ run: |
170
+ set -euo pipefail
171
+ args=(--verify-tag --generate-notes --title "$TAG")
172
+ [ "$PRERELEASE" = "true" ] && args+=(--prerelease)
173
+ gh release create "$TAG" "${args[@]}" dist/*
@@ -0,0 +1,32 @@
1
+ name: scale
2
+
3
+ # Resource-bound scale, oracle and live-warehouse checks. Too slow for every
4
+ # push; run weekly and on demand.
5
+ on:
6
+ schedule:
7
+ - cron: "0 7 * * 1"
8
+ workflow_dispatch:
9
+
10
+ concurrency:
11
+ group: scale
12
+ cancel-in-progress: false
13
+
14
+ env:
15
+ # One test at a time: each scale test saturates the 2-CPU runner (DuckDB uses
16
+ # every core), so parallel workers only contend and trip the hang guards.
17
+ PYTEST_ADDOPTS: -n 0
18
+
19
+ jobs:
20
+ scale:
21
+ runs-on: ubuntu-latest
22
+ timeout-minutes: 60
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: astral-sh/setup-uv@v5
26
+ with:
27
+ enable-cache: true
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.13"
31
+ - run: uv sync --locked --group dev --all-extras
32
+ - run: make test-scale