pretensor 0.1.0a3__tar.gz → 0.2.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 (547) hide show
  1. pretensor-0.2.0/.github/ISSUE_TEMPLATE/schema_report.yml +122 -0
  2. pretensor-0.2.0/.github/workflows/bench.yml +155 -0
  3. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/ci.yml +66 -3
  4. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/e2e.yml +2 -2
  5. pretensor-0.2.0/.github/workflows/no-internal-refs.yml +41 -0
  6. pretensor-0.2.0/.github/workflows/open-publish-pr.yml +41 -0
  7. pretensor-0.2.0/.github/workflows/release.yml +200 -0
  8. pretensor-0.2.0/.pre-commit-config.yaml +35 -0
  9. pretensor-0.2.0/CHANGELOG.md +262 -0
  10. {pretensor-0.1.0a3 → pretensor-0.2.0}/CODE_OF_CONDUCT.md +1 -2
  11. pretensor-0.2.0/PKG-INFO +278 -0
  12. pretensor-0.2.0/README.md +201 -0
  13. {pretensor-0.1.0a3 → pretensor-0.2.0}/SECURITY.md +37 -0
  14. pretensor-0.2.0/docs/agent-framework-adapters.md +84 -0
  15. pretensor-0.2.0/docs/ci.md +49 -0
  16. {pretensor-0.1.0a3 → pretensor-0.2.0}/docs/releases.md +10 -4
  17. pretensor-0.2.0/examples/README.md +25 -0
  18. pretensor-0.2.0/examples/claude-code/README.md +52 -0
  19. pretensor-0.2.0/examples/claude-code/mcp.json +8 -0
  20. pretensor-0.2.0/examples/cursor/README.md +50 -0
  21. pretensor-0.2.0/examples/cursor/mcp.json +8 -0
  22. pretensor-0.2.0/examples/pagila/.gitignore +2 -0
  23. pretensor-0.2.0/examples/pagila/README.md +77 -0
  24. pretensor-0.2.0/examples/pagila/docker-compose.yml +19 -0
  25. pretensor-0.2.0/examples/snowflake-tpch/README.md +126 -0
  26. pretensor-0.2.0/examples/windsurf/README.md +51 -0
  27. pretensor-0.2.0/examples/windsurf/mcp_config.json +8 -0
  28. pretensor-0.2.0/guides/quickstart.md +607 -0
  29. {pretensor-0.1.0a3 → pretensor-0.2.0}/pyproject.toml +31 -5
  30. pretensor-0.2.0/scripts/check_no_internal_refs.py +114 -0
  31. pretensor-0.2.0/scripts/data/adventureworks/schema.sql +3046 -0
  32. pretensor-0.2.0/scripts/data/adventureworks_metric_templates.yaml +67 -0
  33. pretensor-0.2.0/scripts/data/adventureworks_nl2sql_bench.json +130 -0
  34. pretensor-0.2.0/scripts/data/pagila/schema.sql +1842 -0
  35. pretensor-0.2.0/scripts/data/pagila_metric_templates.yaml +67 -0
  36. {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/data/pagila_nl2sql_bench.json +18 -4
  37. pretensor-0.2.0/scripts/data/tpch/schema.sql +121 -0
  38. pretensor-0.2.0/scripts/data/tpch_metric_templates.yaml +67 -0
  39. pretensor-0.2.0/scripts/data/tpch_nl2sql_bench.json +138 -0
  40. pretensor-0.2.0/scripts/generate_schema_snapshot.py +165 -0
  41. pretensor-0.2.0/src/pretensor/benchmark/__init__.py +54 -0
  42. pretensor-0.2.0/src/pretensor/benchmark/cli.py +294 -0
  43. pretensor-0.2.0/src/pretensor/benchmark/fixtures.py +84 -0
  44. pretensor-0.2.0/src/pretensor/benchmark/l1/__init__.py +23 -0
  45. pretensor-0.2.0/src/pretensor/benchmark/l1/metrics.py +141 -0
  46. pretensor-0.2.0/src/pretensor/benchmark/l1/pipeline.py +188 -0
  47. pretensor-0.2.0/src/pretensor/benchmark/l1/runner.py +238 -0
  48. pretensor-0.2.0/src/pretensor/benchmark/l2/__init__.py +27 -0
  49. pretensor-0.2.0/src/pretensor/benchmark/l2/gold.py +236 -0
  50. pretensor-0.2.0/src/pretensor/benchmark/l2/metrics.py +146 -0
  51. pretensor-0.2.0/src/pretensor/benchmark/l2/pipeline.py +124 -0
  52. pretensor-0.2.0/src/pretensor/benchmark/l2/runner.py +523 -0
  53. pretensor-0.2.0/src/pretensor/benchmark/l3/__init__.py +73 -0
  54. pretensor-0.2.0/src/pretensor/benchmark/l3/agent.py +316 -0
  55. pretensor-0.2.0/src/pretensor/benchmark/l3/db.py +188 -0
  56. pretensor-0.2.0/src/pretensor/benchmark/l3/gold.py +85 -0
  57. pretensor-0.2.0/src/pretensor/benchmark/l3/llm_client.py +395 -0
  58. pretensor-0.2.0/src/pretensor/benchmark/l3/mcp_client.py +357 -0
  59. pretensor-0.2.0/src/pretensor/benchmark/l3/pretensor_runner.py +449 -0
  60. pretensor-0.2.0/src/pretensor/benchmark/l3/prompt.py +132 -0
  61. pretensor-0.2.0/src/pretensor/benchmark/l3/runner.py +351 -0
  62. pretensor-0.2.0/src/pretensor/benchmark/l3/sql_equivalence.py +176 -0
  63. pretensor-0.2.0/src/pretensor/benchmark/release_gate.py +675 -0
  64. pretensor-0.2.0/src/pretensor/benchmark/results.py +298 -0
  65. pretensor-0.2.0/src/pretensor/benchmark/runner.py +109 -0
  66. pretensor-0.2.0/src/pretensor/cli/commands/_command_runners.py +406 -0
  67. pretensor-0.2.0/src/pretensor/cli/commands/_source_runner.py +147 -0
  68. pretensor-0.2.0/src/pretensor/cli/commands/analyze.py +205 -0
  69. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/add_remove.py +5 -1
  70. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/export.py +15 -4
  71. pretensor-0.2.0/src/pretensor/cli/commands/index.py +301 -0
  72. pretensor-0.2.0/src/pretensor/cli/commands/init.py +661 -0
  73. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/list.py +15 -4
  74. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/quickstart.py +49 -11
  75. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/reindex.py +156 -79
  76. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/serve.py +29 -14
  77. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/validate.py +29 -9
  78. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/config_file.py +326 -23
  79. pretensor-0.2.0/src/pretensor/cli/init/inference.py +160 -0
  80. pretensor-0.2.0/src/pretensor/cli/init/mcp_clients.py +170 -0
  81. pretensor-0.2.0/src/pretensor/cli/init/steps.py +194 -0
  82. pretensor-0.2.0/src/pretensor/cli/init/wizard.py +62 -0
  83. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/main.py +53 -5
  84. pretensor-0.2.0/src/pretensor/cli/prompts.py +102 -0
  85. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/config.py +100 -6
  86. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/bigquery.py +8 -3
  87. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/inspect.py +33 -25
  88. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/lineage_sqlglot.py +15 -9
  89. pretensor-0.2.0/src/pretensor/connectors/mysql.py +402 -0
  90. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/postgres.py +36 -19
  91. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/registry.py +45 -3
  92. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/snapshot.py +62 -37
  93. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/snowflake.py +96 -28
  94. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/builder.py +43 -4
  95. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/dsn_crypto.py +14 -3
  96. pretensor-0.2.0/src/pretensor/core/graph_schema_manager.py +246 -0
  97. pretensor-0.1.0a3/src/pretensor/core/store.py → pretensor-0.2.0/src/pretensor/core/graph_store.py +389 -445
  98. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/ids.py +33 -0
  99. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/portable_export.py +34 -11
  100. pretensor-0.2.0/src/pretensor/core/query_runner.py +67 -0
  101. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/registry.py +10 -5
  102. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/schema.py +119 -14
  103. pretensor-0.2.0/src/pretensor/core/secure_io.py +93 -0
  104. pretensor-0.2.0/src/pretensor/core/store.py +501 -0
  105. pretensor-0.2.0/src/pretensor/enrichment/analyze/classify.py +49 -0
  106. pretensor-0.2.0/src/pretensor/enrichment/analyze/extract_python.py +196 -0
  107. pretensor-0.2.0/src/pretensor/enrichment/analyze/extract_sql_file.py +83 -0
  108. pretensor-0.2.0/src/pretensor/enrichment/analyze/parse.py +141 -0
  109. pretensor-0.2.0/src/pretensor/enrichment/analyze/pipeline.py +282 -0
  110. pretensor-0.2.0/src/pretensor/enrichment/analyze/summary.py +41 -0
  111. pretensor-0.2.0/src/pretensor/enrichment/analyze/walker.py +133 -0
  112. pretensor-0.2.0/src/pretensor/enrichment/analyze/writers.py +214 -0
  113. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/manifest.py +3 -1
  114. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/classifier.py +26 -2
  115. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/llm_extract.py +2 -2
  116. pretensor-0.2.0/src/pretensor/errors.py +35 -0
  117. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/__init__.py +3 -0
  118. pretensor-0.2.0/src/pretensor/graph_models/consumer.py +71 -0
  119. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/node.py +4 -0
  120. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/relationship.py +7 -1
  121. pretensor-0.2.0/src/pretensor/integrations/__init__.py +42 -0
  122. pretensor-0.2.0/src/pretensor/integrations/_base.py +138 -0
  123. pretensor-0.2.0/src/pretensor/integrations/google_adk.py +49 -0
  124. pretensor-0.2.0/src/pretensor/integrations/langchain.py +55 -0
  125. pretensor-0.2.0/src/pretensor/integrations/llamaindex.py +53 -0
  126. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/cluster_labeler.py +102 -12
  127. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/clustering.py +6 -0
  128. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/discovery.py +8 -0
  129. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/embeddings.py +121 -2
  130. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/graph_export.py +67 -6
  131. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/heuristic.py +65 -29
  132. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/on_demand.py +57 -14
  133. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/llm_infer.py +1 -1
  134. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/llm_runtime.py +4 -2
  135. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/pipeline.py +133 -23
  136. pretensor-0.2.0/src/pretensor/intelligence/role_exemplars.py +263 -0
  137. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/schema_classification.py +58 -4
  138. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/scoring.py +11 -1
  139. pretensor-0.2.0/src/pretensor/intelligence/semantic.py +240 -0
  140. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/steps.py +33 -3
  141. pretensor-0.2.0/src/pretensor/intelligence/steps_embedding.py +168 -0
  142. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/config.py +1 -0
  143. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/dsn.py +135 -6
  144. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/config_json.py +1 -1
  145. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/payload_types.py +51 -6
  146. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/resources/__init__.py +0 -2
  147. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/resources/markdown.py +13 -119
  148. pretensor-0.2.0/src/pretensor/mcp/server.py +289 -0
  149. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service.py +4 -2
  150. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service_context.py +25 -9
  151. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service_registry.py +62 -10
  152. pretensor-0.2.0/src/pretensor/mcp/store_cache.py +43 -0
  153. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tool_registry.py +21 -11
  154. pretensor-0.2.0/src/pretensor/mcp/tools/_rank.py +244 -0
  155. pretensor-0.2.0/src/pretensor/mcp/tools/_timed.py +26 -0
  156. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/compile_metric.py +59 -2
  157. pretensor-0.2.0/src/pretensor/mcp/tools/consumers.py +161 -0
  158. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/context.py +235 -8
  159. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/cypher.py +198 -22
  160. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/detect_changes.py +40 -10
  161. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/impact.py +109 -3
  162. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/list.py +23 -2
  163. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/schema.py +46 -4
  164. pretensor-0.2.0/src/pretensor/mcp/tools/search.py +316 -0
  165. pretensor-0.2.0/src/pretensor/mcp/tools/semantic_search.py +282 -0
  166. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/traverse.py +362 -36
  167. pretensor-0.2.0/src/pretensor/mcp/tools/validate_sql.py +150 -0
  168. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/README.md +3 -1
  169. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/docker-compose.yml +5 -1
  170. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/base.py +2 -2
  171. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/__init__.py +1 -1
  172. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/base.py +3 -3
  173. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/compiler.py +153 -12
  174. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/yaml_layer.py +3 -5
  175. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/graph_patcher.py +98 -1
  176. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/impact_analyzer.py +3 -2
  177. pretensor-0.2.0/src/pretensor/version.py +20 -0
  178. pretensor-0.2.0/tests/benchmark/_compare.py +23 -0
  179. pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l1-embeddings.json +1610 -0
  180. pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l1.json +1609 -0
  181. pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l2-embeddings.json +953 -0
  182. pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l2.json +487 -0
  183. pretensor-0.2.0/tests/benchmark/baselines/adversarial-l1.json +77 -0
  184. pretensor-0.2.0/tests/benchmark/baselines/analytics_dwh-l1.json +55 -0
  185. pretensor-0.2.0/tests/benchmark/baselines/messy_warehouse-l1.json +665 -0
  186. pretensor-0.2.0/tests/benchmark/baselines/pagila-l1-embeddings.json +158 -0
  187. pretensor-0.2.0/tests/benchmark/baselines/pagila-l1.json +91 -0
  188. pretensor-0.2.0/tests/benchmark/baselines/pagila-l2-embeddings.json +539 -0
  189. pretensor-0.2.0/tests/benchmark/baselines/pagila-l2.json +323 -0
  190. pretensor-0.2.0/tests/benchmark/baselines/saas_multitenant-l1.json +73 -0
  191. pretensor-0.2.0/tests/benchmark/baselines/tpch-l1-embeddings.json +80 -0
  192. pretensor-0.2.0/tests/benchmark/baselines/tpch-l1.json +79 -0
  193. pretensor-0.2.0/tests/benchmark/baselines/tpch-l2-embeddings.json +1096 -0
  194. pretensor-0.2.0/tests/benchmark/baselines/tpch-l2.json +562 -0
  195. pretensor-0.2.0/tests/benchmark/fixtures/baseline.json +20 -0
  196. pretensor-0.2.0/tests/benchmark/fixtures/regressed.json +20 -0
  197. pretensor-0.2.0/tests/benchmark/l1/test_metrics.py +168 -0
  198. pretensor-0.2.0/tests/benchmark/l1/test_runner.py +172 -0
  199. pretensor-0.2.0/tests/benchmark/l2/test_gold.py +306 -0
  200. pretensor-0.2.0/tests/benchmark/l2/test_metrics.py +201 -0
  201. pretensor-0.2.0/tests/benchmark/l2/test_runner.py +151 -0
  202. pretensor-0.2.0/tests/benchmark/l3/__init__.py +0 -0
  203. pretensor-0.2.0/tests/benchmark/l3/test_agent.py +377 -0
  204. pretensor-0.2.0/tests/benchmark/l3/test_db.py +285 -0
  205. pretensor-0.2.0/tests/benchmark/l3/test_gold.py +102 -0
  206. pretensor-0.2.0/tests/benchmark/l3/test_llm_client.py +525 -0
  207. pretensor-0.2.0/tests/benchmark/l3/test_mcp_client.py +307 -0
  208. pretensor-0.2.0/tests/benchmark/l3/test_pretensor_runner.py +950 -0
  209. pretensor-0.2.0/tests/benchmark/l3/test_prompt.py +152 -0
  210. pretensor-0.2.0/tests/benchmark/l3/test_runner.py +597 -0
  211. pretensor-0.2.0/tests/benchmark/l3/test_sql_equivalence.py +210 -0
  212. pretensor-0.2.0/tests/benchmark/results/v0.1.0/adventureworks-l1.json +4183 -0
  213. pretensor-0.2.0/tests/benchmark/results/v0.1.0/adventureworks-l2.json +487 -0
  214. pretensor-0.2.0/tests/benchmark/results/v0.1.0/pagila-l1.json +91 -0
  215. pretensor-0.2.0/tests/benchmark/results/v0.1.0/pagila-l2.json +323 -0
  216. pretensor-0.2.0/tests/benchmark/results/v0.1.0/tpch-l1.json +79 -0
  217. pretensor-0.2.0/tests/benchmark/results/v0.1.0/tpch-l2.json +562 -0
  218. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/README.md +15 -0
  219. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/adventureworks-l1.json +4183 -0
  220. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/adventureworks-l2.json +487 -0
  221. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/pagila-l1.json +91 -0
  222. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/pagila-l2.json +323 -0
  223. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/tpch-l1.json +79 -0
  224. pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/tpch-l2.json +562 -0
  225. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/adventureworks-l1.json +4183 -0
  226. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/adventureworks-l2.json +487 -0
  227. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/pagila-l1.json +91 -0
  228. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/pagila-l2.json +323 -0
  229. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/tpch-l1.json +79 -0
  230. pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/tpch-l2.json +562 -0
  231. pretensor-0.2.0/tests/benchmark/results/v0.2.0/accepted-regressions.toml +24 -0
  232. pretensor-0.2.0/tests/benchmark/test_cli.py +456 -0
  233. pretensor-0.2.0/tests/benchmark/test_fixtures.py +126 -0
  234. pretensor-0.2.0/tests/benchmark/test_release_gate.py +780 -0
  235. pretensor-0.2.0/tests/benchmark/test_results.py +489 -0
  236. pretensor-0.2.0/tests/cli/conftest.py +20 -0
  237. pretensor-0.2.0/tests/cli/init/__init__.py +0 -0
  238. pretensor-0.2.0/tests/cli/init/test_inference.py +79 -0
  239. pretensor-0.2.0/tests/cli/init/test_mcp_clients.py +209 -0
  240. pretensor-0.2.0/tests/cli/init/test_steps.py +204 -0
  241. pretensor-0.2.0/tests/cli/init/test_wizard.py +39 -0
  242. pretensor-0.2.0/tests/cli/test_analyze_cli.py +670 -0
  243. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_cli_error_handling.py +15 -7
  244. pretensor-0.2.0/tests/cli/test_config_file.py +1163 -0
  245. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_connections_cli.py +5 -2
  246. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_export_cli.py +124 -4
  247. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_index_cli.py +219 -15
  248. pretensor-0.2.0/tests/cli/test_init_cli.py +2163 -0
  249. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_list_cli.py +13 -4
  250. pretensor-0.2.0/tests/cli/test_main_cli.py +182 -0
  251. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_plugin.py +16 -6
  252. pretensor-0.2.0/tests/cli/test_prompts.py +39 -0
  253. pretensor-0.2.0/tests/cli/test_quickstart_cli.py +197 -0
  254. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_reindex_cli.py +344 -25
  255. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_serve_cli.py +23 -12
  256. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_validate_cli.py +76 -7
  257. pretensor-0.2.0/tests/conftest.py +187 -0
  258. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_dsn_parsing.py +283 -19
  259. pretensor-0.2.0/tests/connectors/test_inspect_collect_stats.py +67 -0
  260. pretensor-0.2.0/tests/connectors/test_mysql_connector.py +823 -0
  261. pretensor-0.2.0/tests/connectors/test_registry_mysql_optional.py +35 -0
  262. pretensor-0.2.0/tests/connectors/test_registry_postgres_optional.py +45 -0
  263. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_snowflake_connector.py +354 -17
  264. pretensor-0.2.0/tests/contracts/__init__.py +4 -0
  265. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_combiner.py +4 -4
  266. pretensor-0.2.0/tests/contracts/test_consumer_node.py +77 -0
  267. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_pipeline_step.py +34 -15
  268. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_scorer.py +23 -12
  269. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_search_index.py +2 -2
  270. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_semantic_layer.py +4 -4
  271. pretensor-0.2.0/tests/core/test_dsn_at_rest.py +113 -0
  272. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_portable_export.py +39 -0
  273. pretensor-0.2.0/tests/core/test_schema.py +96 -0
  274. pretensor-0.2.0/tests/core/test_schema_external_consumer.py +38 -0
  275. pretensor-0.2.0/tests/core/test_store_consumer_upserts.py +339 -0
  276. pretensor-0.2.0/tests/e2e/__init__.py +0 -0
  277. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/conftest.py +90 -0
  278. pretensor-0.2.0/tests/e2e/fixtures/__init__.py +0 -0
  279. pretensor-0.2.0/tests/e2e/fixtures/sql/messy_warehouse_ddl.sql +300 -0
  280. pretensor-0.2.0/tests/e2e/fixtures/sql/sakila_mysql_ddl.sql +83 -0
  281. pretensor-0.2.0/tests/e2e/test_l3_baseline.py +161 -0
  282. pretensor-0.2.0/tests/e2e/test_l3_pretensor.py +302 -0
  283. pretensor-0.2.0/tests/e2e/test_mysql_index_cycle.py +125 -0
  284. pretensor-0.2.0/tests/enrichment/__init__.py +0 -0
  285. pretensor-0.2.0/tests/enrichment/analyze/__init__.py +0 -0
  286. pretensor-0.2.0/tests/enrichment/analyze/fixtures/cross_connection.py +1 -0
  287. pretensor-0.2.0/tests/enrichment/analyze/fixtures/dml_writes.py +4 -0
  288. pretensor-0.2.0/tests/enrichment/analyze/fixtures/dynamic_only.py +5 -0
  289. pretensor-0.2.0/tests/enrichment/analyze/fixtures/fstring_prefix.py +2 -0
  290. pretensor-0.2.0/tests/enrichment/analyze/fixtures/multi_statement.sql +6 -0
  291. pretensor-0.2.0/tests/enrichment/analyze/fixtures/noqa_optout.py +6 -0
  292. pretensor-0.2.0/tests/enrichment/analyze/fixtures/simple.sql +4 -0
  293. pretensor-0.2.0/tests/enrichment/analyze/fixtures/simple_select.py +1 -0
  294. pretensor-0.2.0/tests/enrichment/analyze/fixtures/unparseable.sql +2 -0
  295. pretensor-0.2.0/tests/enrichment/analyze/test_classify.py +100 -0
  296. pretensor-0.2.0/tests/enrichment/analyze/test_extract_python.py +174 -0
  297. pretensor-0.2.0/tests/enrichment/analyze/test_extract_sql_file.py +215 -0
  298. pretensor-0.2.0/tests/enrichment/analyze/test_parse.py +185 -0
  299. pretensor-0.2.0/tests/enrichment/analyze/test_pipeline.py +474 -0
  300. pretensor-0.2.0/tests/enrichment/analyze/test_walker.py +177 -0
  301. pretensor-0.2.0/tests/enrichment/analyze/test_writers.py +334 -0
  302. pretensor-0.2.0/tests/fixtures/schemas/README.md +133 -0
  303. pretensor-0.2.0/tests/fixtures/schemas/adventureworks.yaml +20694 -0
  304. pretensor-0.2.0/tests/fixtures/schemas/adversarial_roles.yaml +16 -0
  305. pretensor-0.2.0/tests/fixtures/schemas/messy_warehouse.yaml +3872 -0
  306. pretensor-0.2.0/tests/fixtures/schemas/messy_warehouse_roles.yaml +43 -0
  307. pretensor-0.2.0/tests/fixtures/schemas/pagila_extended.yaml +1459 -0
  308. pretensor-0.2.0/tests/integrations/__init__.py +0 -0
  309. pretensor-0.2.0/tests/integrations/test_base.py +217 -0
  310. pretensor-0.2.0/tests/integrations/test_google_adk.py +96 -0
  311. pretensor-0.2.0/tests/integrations/test_langchain.py +107 -0
  312. pretensor-0.2.0/tests/integrations/test_llamaindex.py +105 -0
  313. pretensor-0.2.0/tests/intelligence/slow/__init__.py +0 -0
  314. pretensor-0.2.0/tests/intelligence/slow/test_real_model_smoke.py +100 -0
  315. pretensor-0.2.0/tests/intelligence/test_clustering_embeddings.py +414 -0
  316. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_discovery.py +73 -0
  317. pretensor-0.2.0/tests/intelligence/test_embedding_index_step.py +348 -0
  318. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_embeddings.py +44 -0
  319. pretensor-0.2.0/tests/intelligence/test_extended_pagila.py +80 -0
  320. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_heuristic.py +82 -18
  321. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_join_paths.py +132 -5
  322. pretensor-0.2.0/tests/intelligence/test_null_path_parity.py +212 -0
  323. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_pipeline.py +19 -3
  324. pretensor-0.2.0/tests/intelligence/test_role_exemplars.py +231 -0
  325. pretensor-0.2.0/tests/intelligence/test_semantic_scorer.py +344 -0
  326. pretensor-0.2.0/tests/mcp/test_consumers_tool.py +152 -0
  327. pretensor-0.2.0/tests/mcp/test_context_similar.py +339 -0
  328. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_tool.py +2 -1
  329. pretensor-0.2.0/tests/mcp/test_cypher_readonly.py +170 -0
  330. pretensor-0.2.0/tests/mcp/test_cypher_timeout_pool.py +104 -0
  331. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_detect_changes_errors.py +30 -3
  332. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_error_handling.py +20 -7
  333. pretensor-0.2.0/tests/mcp/test_error_sanitization.py +127 -0
  334. pretensor-0.2.0/tests/mcp/test_impact_consumers.py +127 -0
  335. pretensor-0.2.0/tests/mcp/test_kill_switch.py +211 -0
  336. pretensor-0.2.0/tests/mcp/test_mcp_null_path_parity.py +233 -0
  337. pretensor-0.2.0/tests/mcp/test_query_hybrid.py +357 -0
  338. pretensor-0.2.0/tests/mcp/test_semantic_search.py +428 -0
  339. pretensor-0.2.0/tests/mcp/test_serve_stdio_smoke.py +133 -0
  340. pretensor-0.2.0/tests/mcp/test_server_version.py +52 -0
  341. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_service.py +6 -2
  342. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_tool_registry.py +8 -8
  343. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_dijkstra.py +107 -2
  344. pretensor-0.2.0/tests/mcp/test_traverse_tiebreak.py +412 -0
  345. pretensor-0.2.0/tests/scripts/__init__.py +0 -0
  346. pretensor-0.2.0/tests/scripts/test_check_no_internal_refs.py +138 -0
  347. pretensor-0.2.0/tests/semantic/__init__.py +0 -0
  348. pretensor-0.2.0/tests/staleness/test_staleness.py +572 -0
  349. pretensor-0.2.0/tests/test_errors.py +131 -0
  350. pretensor-0.2.0/tests/test_graph_schema_manager.py +64 -0
  351. pretensor-0.2.0/tests/test_graph_store.py +86 -0
  352. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_pretensor_config.py +22 -10
  353. pretensor-0.2.0/tests/test_query_runner.py +48 -0
  354. pretensor-0.2.0/tests/test_store_cache.py +185 -0
  355. pretensor-0.2.0/tests/utils/__init__.py +0 -0
  356. pretensor-0.2.0/tests/validation/test_compile_did_you_mean.py +488 -0
  357. {pretensor-0.1.0a3 → pretensor-0.2.0}/uv.lock +1950 -63
  358. pretensor-0.1.0a3/.github/dependabot.yml +0 -49
  359. pretensor-0.1.0a3/.github/workflows/release.yml +0 -93
  360. pretensor-0.1.0a3/.pre-commit-config.yaml +0 -21
  361. pretensor-0.1.0a3/CHANGELOG.md +0 -29
  362. pretensor-0.1.0a3/PKG-INFO +0 -183
  363. pretensor-0.1.0a3/README.md +0 -120
  364. pretensor-0.1.0a3/guides/quickstart.md +0 -331
  365. pretensor-0.1.0a3/scripts/benchmark_graph_rag_nl2sql.py +0 -335
  366. pretensor-0.1.0a3/scripts/e2e_pagila.py +0 -625
  367. pretensor-0.1.0a3/src/pretensor/cli/commands/index.py +0 -551
  368. pretensor-0.1.0a3/src/pretensor/mcp/server.py +0 -723
  369. pretensor-0.1.0a3/src/pretensor/mcp/tools/search.py +0 -108
  370. pretensor-0.1.0a3/src/pretensor/mcp/tools/validate_sql.py +0 -74
  371. pretensor-0.1.0a3/tests/cli/test_config_file.py +0 -612
  372. pretensor-0.1.0a3/tests/cli/test_main_cli.py +0 -92
  373. pretensor-0.1.0a3/tests/cli/test_quickstart_cli.py +0 -109
  374. pretensor-0.1.0a3/tests/conftest.py +0 -70
  375. pretensor-0.1.0a3/tests/contracts/__init__.py +0 -4
  376. pretensor-0.1.0a3/tests/staleness/test_staleness.py +0 -159
  377. {pretensor-0.1.0a3 → pretensor-0.2.0}/.env.example +0 -0
  378. {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitattributes +0 -0
  379. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/CODEOWNERS +0 -0
  380. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  381. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  382. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  383. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/pull_request_template.md +0 -0
  384. {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/docs.yml +0 -0
  385. {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitignore +0 -0
  386. {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitlint +0 -0
  387. {pretensor-0.1.0a3 → pretensor-0.2.0}/.python-version +0 -0
  388. {pretensor-0.1.0a3 → pretensor-0.2.0}/CONTRIBUTING.md +0 -0
  389. {pretensor-0.1.0a3 → pretensor-0.2.0}/LICENSE +0 -0
  390. {pretensor-0.1.0a3 → pretensor-0.2.0}/Makefile +0 -0
  391. {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/audit_deny_list.py +0 -0
  392. {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/check_readme_urls.py +0 -0
  393. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/__init__.py +0 -0
  394. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/__init__.py +0 -0
  395. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/__init__.py +0 -0
  396. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/register.py +0 -0
  397. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/semantic.py +0 -0
  398. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/sync_grants.py +0 -0
  399. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/constants.py +0 -0
  400. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/dbt_enrichment.py +0 -0
  401. {pretensor-0.1.0a3/src/pretensor/introspection/models → pretensor-0.2.0/src/pretensor/cli/init}/__init__.py +0 -0
  402. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/paths.py +0 -0
  403. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/plugin.py +0 -0
  404. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/__init__.py +0 -0
  405. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/base.py +0 -0
  406. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/models.py +0 -0
  407. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/pg_array_parse.py +0 -0
  408. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/__init__.py +0 -0
  409. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/__init__.py +0 -0
  410. {pretensor-0.1.0a3/tests/e2e → pretensor-0.2.0/src/pretensor/enrichment/analyze}/__init__.py +0 -0
  411. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/__init__.py +0 -0
  412. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/lineage.py +0 -0
  413. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/metadata.py +0 -0
  414. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/pipeline.py +0 -0
  415. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/resolution.py +0 -0
  416. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/signals.py +0 -0
  417. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/__init__.py +0 -0
  418. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/builder.py +0 -0
  419. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/base.py +0 -0
  420. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/edge.py +0 -0
  421. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/entity.py +0 -0
  422. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/__init__.py +0 -0
  423. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/combining.py +0 -0
  424. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/__init__.py +0 -0
  425. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/storage.py +0 -0
  426. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/metric_templates.py +0 -0
  427. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/shadow_alias.py +0 -0
  428. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/statistical.py +0 -0
  429. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/__init__.py +0 -0
  430. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/inspector.py +0 -0
  431. {pretensor-0.1.0a3/tests/e2e/fixtures → pretensor-0.2.0/src/pretensor/introspection/models}/__init__.py +0 -0
  432. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/base.py +0 -0
  433. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/plan.py +0 -0
  434. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/schema.py +0 -0
  435. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/semantic.py +0 -0
  436. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/validation.py +0 -0
  437. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/snapshot.py +0 -0
  438. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/__init__.py +0 -0
  439. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/__init__.py +0 -0
  440. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/observability.py +0 -0
  441. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/py.typed +0 -0
  442. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/__init__.py +0 -0
  443. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/pagila_data.sql +0 -0
  444. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/pagila_ddl.sql +0 -0
  445. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/__init__.py +0 -0
  446. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/index.py +0 -0
  447. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/skills/__init__.py +0 -0
  448. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/skills/generator.py +0 -0
  449. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/__init__.py +0 -0
  450. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/snapshot_store.py +0 -0
  451. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/validation/__init__.py +0 -0
  452. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/validation/query_validator.py +0 -0
  453. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/__init__.py +0 -0
  454. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/config.py +0 -0
  455. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/filter.py +0 -0
  456. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/kuzu_helpers.py +0 -0
  457. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/runtime.py +0 -0
  458. {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/sync_grants.py +0 -0
  459. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/__init__.py +0 -0
  460. {pretensor-0.1.0a3/tests/enrichment → pretensor-0.2.0/tests/benchmark}/__init__.py +0 -0
  461. {pretensor-0.1.0a3/tests/semantic → pretensor-0.2.0/tests/benchmark/l1}/__init__.py +0 -0
  462. {pretensor-0.1.0a3/tests/utils → pretensor-0.2.0/tests/benchmark/l2}/__init__.py +0 -0
  463. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_dbt_enrichment_cli.py +0 -0
  464. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_paths_cli.py +0 -0
  465. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_semantic_cli.py +0 -0
  466. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_sync_grants_cli.py +0 -0
  467. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_base_connector.py +0 -0
  468. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_bigquery.py +0 -0
  469. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_catalog_enrichment.py +0 -0
  470. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_lineage_sqlglot.py +0 -0
  471. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_pg_array_parse.py +0 -0
  472. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_postgres_table_grants.py +0 -0
  473. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_postgres_views.py +0 -0
  474. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_registry_snowflake_optional.py +0 -0
  475. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_snowflake_table_grants.py +0 -0
  476. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_builder.py +0 -0
  477. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_graph_builder_lineage.py +0 -0
  478. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_lineage_store.py +0 -0
  479. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_models.py +0 -0
  480. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_registry.py +0 -0
  481. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_semantic_schema.py +0 -0
  482. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/adventureworks_ddl.sql +0 -0
  483. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/tpcds_ddl.sql +0 -0
  484. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/tpch_ddl.sql +0 -0
  485. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_adventureworks_smoke.py +0 -0
  486. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_adventureworks_traverse.py +0 -0
  487. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_dbt_warehouse_scale_enrichment.py +0 -0
  488. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_index_cycle.py +0 -0
  489. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_mcp_tools.py +0 -0
  490. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_reindex.py +0 -0
  491. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_serve_smoke.py +0 -0
  492. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_tpcds_traverse.py +0 -0
  493. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_tpch_traverse.py +0 -0
  494. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_visibility.py +0 -0
  495. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/fixtures/dbt/manifest_v10.json +0 -0
  496. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/fixtures/dbt/manifest_v9.json +0 -0
  497. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_lineage.py +0 -0
  498. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_manifest.py +0 -0
  499. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_metadata.py +0 -0
  500. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_pipeline.py +0 -0
  501. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_signals.py +0 -0
  502. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_classifier.py +0 -0
  503. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_entity_builder.py +0 -0
  504. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_llm_extract.py +0 -0
  505. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_pagila_entities.py +0 -0
  506. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/README.md +0 -0
  507. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/__init__.py +0 -0
  508. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/generator.py +0 -0
  509. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/analytics_vs_saas.yaml +0 -0
  510. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/tpch_vs_pagila.yaml +0 -0
  511. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/tpch_vs_tpch_renamed.yaml +0 -0
  512. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/adversarial.yaml +0 -0
  513. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/analytics_dwh.yaml +0 -0
  514. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/pagila.yaml +0 -0
  515. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/saas_multitenant.yaml +0 -0
  516. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/tpch.yaml +0 -0
  517. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_cluster_labeler.py +0 -0
  518. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_clustering.py +0 -0
  519. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_intelligence.py +0 -0
  520. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_llm_infer.py +0 -0
  521. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_llm_runtime.py +0 -0
  522. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_metric_templates.py +0 -0
  523. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_schema_classification.py +0 -0
  524. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_shadow_alias.py +0 -0
  525. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_statistical.py +0 -0
  526. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_compile_metric_tool.py +0 -0
  527. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_dbt.py +0 -0
  528. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_lineage.py +0 -0
  529. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_error_ergonomics.py +0 -0
  530. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_impact_hop.py +0 -0
  531. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_schema_tool.py +0 -0
  532. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_ambiguous.py +0 -0
  533. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_pagila_shape.py +0 -0
  534. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_validate_sql_tool.py +0 -0
  535. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_visibility_mcp.py +0 -0
  536. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/query_helpers.py +0 -0
  537. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/search/test_search_index.py +0 -0
  538. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_compiler.py +0 -0
  539. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_semantic_layer.py +0 -0
  540. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_yaml_layer.py +0 -0
  541. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_gitlint_config.py +0 -0
  542. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_observability.py +0 -0
  543. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_packaging.py +0 -0
  544. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/utils/score_tracker.py +0 -0
  545. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/validation/test_query_validator.py +0 -0
  546. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/visibility/test_sync_grants.py +0 -0
  547. {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/visibility/test_visibility_config.py +0 -0
@@ -0,0 +1,122 @@
1
+ name: Schema doesn't match my database
2
+ description: The knowledge graph is missing or misrepresenting tables, columns, keys, or relationships from your database.
3
+ title: "schema: <what's missing or wrong>"
4
+ labels:
5
+ - bug
6
+ - triage
7
+ body:
8
+ - type: markdown
9
+ attributes:
10
+ value: |
11
+ Use this form when Pretensor indexed your database but the resulting graph is **wrong or incomplete** — a table or column is missing, a foreign key or inferred join is wrong, or MCP tools return schema context that doesn't match reality. For crashes and errors, use the bug report form instead.
12
+
13
+ **Security vulnerabilities must not be filed as public issues.** See [SECURITY.md](https://github.com/pretensor-ai/pretensor/blob/main/SECURITY.md) and report privately via [GitHub Security Advisories](https://github.com/pretensor-ai/pretensor/security/advisories/new).
14
+
15
+ - type: input
16
+ id: pretensor-version
17
+ attributes:
18
+ label: Pretensor version
19
+ description: Output of `pretensor --version`.
20
+ placeholder: "0.1.0aN"
21
+ validations:
22
+ required: true
23
+
24
+ - type: dropdown
25
+ id: backend
26
+ attributes:
27
+ label: Database backend
28
+ options:
29
+ - PostgreSQL
30
+ - MySQL
31
+ - Snowflake
32
+ - BigQuery
33
+ - Other
34
+ validations:
35
+ required: true
36
+
37
+ - type: input
38
+ id: backend-version
39
+ attributes:
40
+ label: Database version
41
+ description: e.g. `PostgreSQL 16.3`, `Snowflake 8.x`.
42
+ validations:
43
+ required: true
44
+
45
+ - type: dropdown
46
+ id: problem-kind
47
+ attributes:
48
+ label: What is wrong in the graph?
49
+ options:
50
+ - Table missing
51
+ - Column missing
52
+ - Foreign key missing or wrong
53
+ - Inferred join / relationship wrong
54
+ - Wrong metadata (types, row counts, comments)
55
+ - Search / context returns the wrong schema objects
56
+ - Other
57
+ validations:
58
+ required: true
59
+
60
+ - type: dropdown
61
+ id: surface
62
+ attributes:
63
+ label: Where do you see it?
64
+ description: The surface where the wrong output shows up.
65
+ options:
66
+ - CLI (`pretensor list` / `validate` / `export`)
67
+ - MCP tool response (`schema`, `context`, `traverse`, ...)
68
+ - Both
69
+ - Other
70
+ validations:
71
+ required: true
72
+
73
+ - type: textarea
74
+ id: expected
75
+ attributes:
76
+ label: What the database actually contains
77
+ description: |
78
+ The relevant schema as it exists in your database — a sanitized DDL
79
+ snippet (`CREATE TABLE ...`), an information-schema query result, or a
80
+ prose description. Redact table/column names if needed, but keep the
81
+ structure (keys, references) intact.
82
+ render: sql
83
+ validations:
84
+ required: true
85
+
86
+ - type: textarea
87
+ id: actual
88
+ attributes:
89
+ label: What Pretensor produced instead
90
+ description: The wrong or missing output — CLI output, MCP tool response JSON, or `pretensor export` fragment.
91
+ render: shell
92
+ validations:
93
+ required: true
94
+
95
+ - type: dropdown
96
+ id: reindex
97
+ attributes:
98
+ label: Does a fresh index reproduce it?
99
+ description: Whether the problem survives a full `pretensor index` (not just `reindex`) into a clean state directory.
100
+ options:
101
+ - Yes — reproduced after a fresh full index
102
+ - No — a fresh index fixed it
103
+ - Not tried
104
+ validations:
105
+ required: true
106
+
107
+ - type: textarea
108
+ id: logs
109
+ attributes:
110
+ label: Index/reindex logs or additional context
111
+ description: Output of the indexing run (add `--log-level debug` if possible). Redact secrets, DSNs, and personally identifiable data.
112
+ render: shell
113
+
114
+ - type: checkboxes
115
+ id: checks
116
+ attributes:
117
+ label: Pre-submission checks
118
+ options:
119
+ - label: I searched existing issues and did not find a duplicate.
120
+ required: true
121
+ - label: I redacted credentials and sensitive schema details from all snippets.
122
+ required: true
@@ -0,0 +1,155 @@
1
+ name: Bench
2
+
3
+ on:
4
+ # No paths-ignore: the bench lane runs on every PR (including doc-only)
5
+ # so the dry-run AC is satisfiable and the lane never silently no-ops.
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+ inputs:
10
+ l3_model:
11
+ description: "L3 model id (defaults to claude-haiku-4-5)"
12
+ required: false
13
+ type: string
14
+ default: "claude-haiku-4-5"
15
+ # L3 runs weekly (Monday 04:00 UTC) for trend watching, on release-tag
16
+ # pushes for the release-being-announced snapshot, and on manual dispatch
17
+ # for ad-hoc runs.
18
+ schedule:
19
+ - cron: '0 4 * * 1'
20
+ push:
21
+ tags: ['v*.*.*']
22
+
23
+ concurrency:
24
+ group: bench-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
25
+ cancel-in-progress: true
26
+
27
+ permissions:
28
+ contents: read
29
+
30
+ jobs:
31
+ pr-bench:
32
+ name: ${{ matrix.level }} (${{ matrix.dataset }}, ${{ matrix.extras_label }})
33
+ if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
34
+ runs-on: ubuntu-latest
35
+ timeout-minutes: 20
36
+ strategy:
37
+ fail-fast: false
38
+ matrix:
39
+ level: [l1, l2]
40
+ dataset: [pagila, adventureworks, tpch]
41
+ extras: [dev, dev-embeddings]
42
+ include:
43
+ - extras: dev
44
+ extras_args: "--extra dev"
45
+ extras_label: "dev"
46
+ - extras: dev-embeddings
47
+ extras_args: "--extra dev --extra embeddings"
48
+ extras_label: "dev,embeddings"
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - uses: astral-sh/setup-uv@v4
52
+ with:
53
+ enable-cache: true
54
+ cache-dependency-glob: "uv.lock"
55
+ python-version: "3.11"
56
+ - name: Install dependencies
57
+ run: uv sync --locked ${{ matrix.extras_args }}
58
+ - name: Cache HuggingFace embedding model
59
+ if: matrix.extras == 'dev-embeddings'
60
+ uses: actions/cache@v4
61
+ with:
62
+ path: ~/.cache/huggingface
63
+ key: hf-arctic-embed-xs-${{ hashFiles('src/pretensor/intelligence/embeddings.py') }}
64
+ - name: Pre-warm embedding model (retry on Hub rate limits)
65
+ if: matrix.extras == 'dev-embeddings'
66
+ env:
67
+ # Optional repo secret; anonymous Hub downloads from shared
68
+ # runner IPs are frequently 429-rate-limited. huggingface_hub
69
+ # picks the token up from the environment automatically; an
70
+ # empty value is a no-op.
71
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
72
+ run: |
73
+ for attempt in 1 2 3 4 5; do
74
+ if uv run python -c "from pretensor.intelligence.embeddings import get_default_embedding_client; get_default_embedding_client().embed(['warm'])"; then
75
+ echo "model ready (attempt $attempt)"
76
+ exit 0
77
+ fi
78
+ sleep $((30 + attempt * 15 + RANDOM % 30))
79
+ done
80
+ echo "::error::embedding model download kept failing (HF Hub rate limit?). Add an HF_TOKEN repo secret or retry the run."
81
+ exit 1
82
+ - name: Run benchmark
83
+ # The embeddings lane passes --embeddings and compares against
84
+ # lane-specific baselines: L2 measures real cosine retrieval for
85
+ # semantic_search + the hybrid rerank; L1 measures blind join
86
+ # discovery with the embedding relationship scorer registered at
87
+ # its documented typical threshold (see L1_EMBEDDING_JOIN_THRESHOLD).
88
+ env:
89
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
90
+ run: |
91
+ BENCH_FLAG=""
92
+ SUFFIX=""
93
+ if [ "${{ matrix.extras }}" = "dev-embeddings" ]; then
94
+ BENCH_FLAG="--embeddings"
95
+ SUFFIX="-embeddings"
96
+ fi
97
+ echo "BASELINE_SUFFIX=$SUFFIX" >> "$GITHUB_ENV"
98
+ uv run pretensor benchmark ${{ matrix.level }} --dataset ${{ matrix.dataset }} $BENCH_FLAG --out current.json
99
+ - name: Compare against baseline
100
+ run: |
101
+ uv run pretensor benchmark compare \
102
+ --baseline tests/benchmark/baselines/${{ matrix.dataset }}-${{ matrix.level }}${BASELINE_SUFFIX}.json \
103
+ --current current.json
104
+ - name: Upload current result on failure
105
+ if: failure()
106
+ uses: actions/upload-artifact@v4
107
+ with:
108
+ name: ${{ matrix.level }}-${{ matrix.dataset }}-${{ matrix.extras }}-current
109
+ path: current.json
110
+ retention-days: 14
111
+ if-no-files-found: warn
112
+
113
+ l3:
114
+ name: L3 (${{ matrix.dataset }}, ${{ matrix.runner }})
115
+ # L3 is dormant until the per-dataset Postgres fixtures and DSN env
116
+ # vars are wired into CI. Set the repo variable
117
+ # `L3_ENV_PROVISIONED=true` once that work lands; until then,
118
+ # scheduled / tag-push / manual triggers no-op cleanly instead of
119
+ # producing six failed jobs that drown out the L1+L2 signal.
120
+ if: vars.L3_ENV_PROVISIONED == 'true' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule')
121
+ runs-on: ubuntu-latest
122
+ timeout-minutes: 60
123
+ continue-on-error: true
124
+ strategy:
125
+ fail-fast: false
126
+ matrix:
127
+ dataset: [pagila, adventureworks, tpch]
128
+ runner: [baseline, pretensor]
129
+ env:
130
+ ANTHROPIC_API_KEY: ${{ secrets.BENCH_ANTHROPIC_API_KEY }}
131
+ steps:
132
+ - uses: actions/checkout@v4
133
+ - uses: astral-sh/setup-uv@v4
134
+ with:
135
+ enable-cache: true
136
+ cache-dependency-glob: "uv.lock"
137
+ python-version: "3.11"
138
+ - name: Install dependencies
139
+ run: uv sync --locked --extra dev --extra embeddings
140
+ - name: Run L3
141
+ run: |
142
+ model="${{ inputs.l3_model || 'claude-haiku-4-5' }}"
143
+ uv run pretensor benchmark l3 \
144
+ --dataset ${{ matrix.dataset }} \
145
+ --runner ${{ matrix.runner }} \
146
+ --model "$model" \
147
+ --out results.json
148
+ - name: Upload result
149
+ if: always()
150
+ uses: actions/upload-artifact@v4
151
+ with:
152
+ name: l3-${{ matrix.dataset }}-${{ matrix.runner }}-${{ github.run_id }}
153
+ path: results.json
154
+ retention-days: 90
155
+ if-no-files-found: warn
@@ -12,6 +12,17 @@ on:
12
12
  - 'docs/**'
13
13
  - '**.md'
14
14
  - '.github/ISSUE_TEMPLATE/**'
15
+ schedule:
16
+ # Nightly slow lane (real-model embedding smoke + future heavy fixtures).
17
+ # Daily at 03:17 UTC.
18
+ - cron: '17 3 * * *'
19
+ workflow_dispatch:
20
+ inputs:
21
+ run_slow:
22
+ description: 'Run the slow opt-in test lane (real model downloads).'
23
+ type: boolean
24
+ required: false
25
+ default: false
15
26
 
16
27
  concurrency:
17
28
  group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -32,10 +43,25 @@ jobs:
32
43
  cache-dependency-glob: "uv.lock"
33
44
  python-version: "3.12"
34
45
  - name: Install dependencies
35
- run: uv sync --extra dev
46
+ run: uv sync --locked --extra dev
36
47
  - name: Ruff check
37
48
  run: uv run ruff check src tests
38
49
 
50
+ lockfile:
51
+ name: Lockfile up to date
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: astral-sh/setup-uv@v4
56
+ with:
57
+ enable-cache: true
58
+ cache-dependency-glob: "uv.lock"
59
+ python-version: "3.12"
60
+ - name: Verify uv.lock matches pyproject.toml
61
+ # Fails if the committed lock would be re-resolved — keeps the reviewed
62
+ # pins identical to what every other job installs with `uv sync --locked`.
63
+ run: uv lock --check
64
+
39
65
  typecheck:
40
66
  name: Typecheck (pyright)
41
67
  runs-on: ubuntu-latest
@@ -47,7 +73,7 @@ jobs:
47
73
  cache-dependency-glob: "uv.lock"
48
74
  python-version: "3.11"
49
75
  - name: Install dependencies
50
- run: uv sync --extra dev
76
+ run: uv sync --locked --extra dev
51
77
  - name: Pyright
52
78
  run: uv run pyright
53
79
 
@@ -66,7 +92,7 @@ jobs:
66
92
  cache-dependency-glob: "uv.lock"
67
93
  python-version: ${{ matrix.python-version }}
68
94
  - name: Install dependencies
69
- run: uv sync --extra dev
95
+ run: uv sync --locked --extra dev
70
96
  - name: Pytest
71
97
  env:
72
98
  PYTHONPATH: src
@@ -133,3 +159,40 @@ jobs:
133
159
  exit 1
134
160
  fi
135
161
  uvx --from "${wheels[0]}" pretensor --help > /dev/null
162
+
163
+ slow-tests:
164
+ name: Slow tests (opt-in real model)
165
+ if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.run_slow)
166
+ runs-on: ubuntu-latest
167
+ steps:
168
+ - uses: actions/checkout@v4
169
+ - uses: astral-sh/setup-uv@v4
170
+ with:
171
+ enable-cache: true
172
+ cache-dependency-glob: "uv.lock"
173
+ python-version: "3.12"
174
+ - name: Install dependencies (with embeddings extra)
175
+ run: uv sync --locked --extra dev --extra embeddings
176
+ - name: Cache HuggingFace embedding model
177
+ uses: actions/cache@v4
178
+ with:
179
+ path: ~/.cache/huggingface
180
+ key: hf-arctic-embed-xs-${{ hashFiles('src/pretensor/intelligence/embeddings.py') }}
181
+ - name: Pre-warm embedding model (retry on Hub rate limits)
182
+ env:
183
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
184
+ run: |
185
+ for attempt in 1 2 3 4 5; do
186
+ if uv run python -c "from pretensor.intelligence.embeddings import get_default_embedding_client; get_default_embedding_client().embed(['warm'])"; then
187
+ echo "model ready (attempt $attempt)"
188
+ exit 0
189
+ fi
190
+ sleep $((30 + attempt * 15 + RANDOM % 30))
191
+ done
192
+ echo "::error::embedding model download kept failing (HF Hub rate limit?). Add an HF_TOKEN repo secret or retry the run."
193
+ exit 1
194
+ - name: Pytest -m slow
195
+ env:
196
+ PYTHONPATH: src
197
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
198
+ run: uv run pytest -m slow tests/
@@ -25,8 +25,8 @@ jobs:
25
25
  curl -LsSf https://astral.sh/uv/install.sh | sh
26
26
  echo "$HOME/.local/bin" >> "$GITHUB_PATH"
27
27
 
28
- - name: Install dependencies (make test-e2e uses uv sync --extra dev --extra e2e)
29
- run: uv sync --extra dev --extra e2e
28
+ - name: Install dependencies (E2E needs the postgres driver to connect)
29
+ run: uv sync --locked --extra dev --extra e2e --extra postgres
30
30
 
31
31
  - name: Run E2E suite (PRETENSOR_E2E=1 uv run pytest tests/e2e/ ...)
32
32
  env:
@@ -0,0 +1,41 @@
1
+ name: no-internal-refs
2
+
3
+ # publish/** is included so the scan also attaches to release-snapshot pushes,
4
+ # whose PRs are opened by GITHUB_TOKEN and therefore never fire pull_request
5
+ # events — without the push trigger, a required "Block internal tracker
6
+ # references" check would wait forever on those PRs.
7
+ on:
8
+ push:
9
+ branches: [main, master, 'publish/**']
10
+ pull_request:
11
+
12
+ concurrency:
13
+ group: no-internal-refs-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ check:
21
+ name: Block internal tracker references
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ fetch-depth: 0
27
+
28
+ - name: Scan tracked files
29
+ run: |
30
+ set -euo pipefail
31
+ git ls-files -z | xargs -0 python3 scripts/check_no_internal_refs.py
32
+
33
+ - name: Scan pull-request title and body
34
+ if: github.event_name == 'pull_request'
35
+ env:
36
+ PR_TITLE: ${{ github.event.pull_request.title }}
37
+ PR_BODY: ${{ github.event.pull_request.body }}
38
+ run: |
39
+ set -euo pipefail
40
+ printf 'title: %s\n\nbody:\n%s\n' "${PR_TITLE}" "${PR_BODY}" > pr-metadata.txt
41
+ python3 scripts/check_no_internal_refs.py pr-metadata.txt
@@ -0,0 +1,41 @@
1
+ name: open-publish-pr
2
+
3
+ # Opens a review PR whenever a publish/<tag> release branch is pushed, using
4
+ # the built-in GITHUB_TOKEN. A GITHUB_TOKEN-opened PR does not trigger
5
+ # pull_request workflows, but that is fine: ci.yml already runs on push for
6
+ # publish/**, so required checks attach to the pushed commit SHA and satisfy
7
+ # branch protection.
8
+
9
+ on:
10
+ push:
11
+ branches:
12
+ - "publish/**"
13
+
14
+ permissions:
15
+ contents: read
16
+ pull-requests: write
17
+
18
+ jobs:
19
+ open-pr:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - name: Open or update the release PR
23
+ env:
24
+ GH_TOKEN: ${{ github.token }}
25
+ BRANCH: ${{ github.ref_name }}
26
+ REPO: ${{ github.repository }}
27
+ run: |
28
+ set -euo pipefail
29
+ version="${BRANCH#publish/}"
30
+ # Only an OPEN PR should count as "already handled": `gh pr view`
31
+ # on a branch name also resolves closed and merged PRs, so a
32
+ # re-pushed release branch whose earlier PR was merged would be
33
+ # skipped and the release would stall with no PR to review.
34
+ open_count=$(gh pr list --repo "$REPO" --head "$BRANCH" --state open --json number --jq 'length')
35
+ if [ "$open_count" -gt 0 ]; then
36
+ echo "PR already open for ${BRANCH}."
37
+ else
38
+ gh pr create --repo "$REPO" --base main --head "$BRANCH" \
39
+ --title "Release ${version}" \
40
+ --body "Release snapshot for ${version}. Review the diff and confirm CI is green, then merge."
41
+ fi
@@ -0,0 +1,200 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+
8
+ concurrency:
9
+ group: release-${{ github.ref }}
10
+ cancel-in-progress: false
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ release-gate:
17
+ name: Release gate (L1+L2 vs previous tag)
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ # Required so `git describe --tags HEAD^` can resolve the
23
+ # previous tag — the release-gate script needs the full
24
+ # tag history, not just HEAD.
25
+ fetch-depth: 0
26
+ - uses: astral-sh/setup-uv@v4
27
+ with:
28
+ enable-cache: true
29
+ cache-dependency-glob: "uv.lock"
30
+ python-version: "3.12"
31
+ - name: Install pretensor with dev extras
32
+ # The gate runs L1 + L2 with --no-embeddings, so the heavy
33
+ # `embeddings` optional extra (onnxruntime, transformers, …) is
34
+ # not exercised. Skip it to keep the gate job fast. If a future
35
+ # change starts gating the embeddings legs too, add `--extra
36
+ # embeddings` here and pass `--embeddings` below.
37
+ run: uv sync --locked --extra dev
38
+ - name: Run release gate
39
+ run: uv run python -m pretensor.benchmark.release_gate
40
+ - name: Upload candidate-tag results
41
+ if: always()
42
+ uses: actions/upload-artifact@v4
43
+ with:
44
+ name: release-gate-results
45
+ path: tests/benchmark/results/${{ github.ref_name }}/
46
+ if-no-files-found: warn
47
+ retention-days: 90
48
+
49
+ build:
50
+ name: Build distributions
51
+ runs-on: ubuntu-latest
52
+ steps:
53
+ - uses: actions/checkout@v4
54
+ - uses: astral-sh/setup-uv@v4
55
+ with:
56
+ enable-cache: true
57
+ cache-dependency-glob: "uv.lock"
58
+ python-version: "3.12"
59
+ - name: Verify tag matches pyproject version
60
+ run: |
61
+ tag="${GITHUB_REF_NAME#v}"
62
+ pkg=$(uv run python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
63
+ [ "$tag" = "$pkg" ] || { echo "tag $tag != pyproject $pkg"; exit 1; }
64
+ - name: Build sdist + wheel
65
+ run: uv build
66
+ - name: Validate distributions
67
+ run: uvx twine check --strict dist/*
68
+ - uses: actions/upload-artifact@v4
69
+ with:
70
+ name: dist
71
+ path: dist/
72
+ if-no-files-found: error
73
+ retention-days: 7
74
+
75
+ detect:
76
+ name: Classify tag
77
+ runs-on: ubuntu-latest
78
+ outputs:
79
+ is_prerelease: ${{ steps.check.outputs.is_prerelease }}
80
+ steps:
81
+ - id: check
82
+ run: |
83
+ if [[ "${{ github.ref_name }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(a|b|rc)[0-9]+$ ]]; then
84
+ echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
85
+ else
86
+ echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
87
+ fi
88
+
89
+ test-pypi:
90
+ name: Publish to TestPyPI (prereleases only)
91
+ needs: [build, detect, release-gate]
92
+ if: needs.detect.outputs.is_prerelease == 'true'
93
+ runs-on: ubuntu-latest
94
+ environment:
95
+ name: testpypi-release
96
+ url: https://test.pypi.org/project/pretensor/
97
+ permissions:
98
+ id-token: write
99
+ steps:
100
+ - uses: actions/download-artifact@v4
101
+ with:
102
+ name: dist
103
+ path: dist/
104
+ - uses: pypa/gh-action-pypi-publish@release/v1
105
+ with:
106
+ repository-url: https://test.pypi.org/legacy/
107
+
108
+ pypi:
109
+ name: Publish to PyPI
110
+ needs: [build, detect, test-pypi, release-gate]
111
+ if: >-
112
+ always() &&
113
+ needs.build.result == 'success' &&
114
+ needs.release-gate.result == 'success' &&
115
+ (needs.test-pypi.result == 'success' || needs.test-pypi.result == 'skipped')
116
+ runs-on: ubuntu-latest
117
+ environment:
118
+ name: pypi-release
119
+ url: https://pypi.org/project/pretensor/
120
+ permissions:
121
+ id-token: write
122
+ steps:
123
+ - uses: actions/download-artifact@v4
124
+ with:
125
+ name: dist
126
+ path: dist/
127
+ - uses: pypa/gh-action-pypi-publish@release/v1
128
+
129
+ archive-results:
130
+ # Opens a PR with the candidate-tag's release-gate JSON so the next
131
+ # tag cut has a baseline to compare against. Goes through PR review
132
+ # rather than pushing directly to main — main is the public OSS
133
+ # branch and integration there is PR-only by repo policy.
134
+ name: Archive release-gate baselines (open PR)
135
+ needs: [pypi]
136
+ # Explicit condition: the default success() check looks at the whole
137
+ # transitive needs chain, so the skipped TestPyPI job on final (non-pre)
138
+ # releases silently skipped this job even though pypi succeeded. That is
139
+ # how the v0.1.0 baseline was never archived.
140
+ if: always() && needs.pypi.result == 'success'
141
+ runs-on: ubuntu-latest
142
+ permissions:
143
+ contents: write
144
+ pull-requests: write
145
+ steps:
146
+ - uses: actions/checkout@v4
147
+ with:
148
+ ref: main
149
+ fetch-depth: 1
150
+ - uses: actions/download-artifact@v4
151
+ with:
152
+ name: release-gate-results
153
+ path: tests/benchmark/results/${{ github.ref_name }}/
154
+ - name: Open baseline-archive PR
155
+ env:
156
+ TAG: ${{ github.ref_name }}
157
+ GH_TOKEN: ${{ github.token }}
158
+ run: |
159
+ # The artifact lands as untracked files in a fresh checkout, so
160
+ # `git diff` never sees it — check the porcelain status (which
161
+ # includes untracked paths) instead.
162
+ if [ -z "$(git status --porcelain tests/benchmark/results/)" ]; then
163
+ echo "No release-gate JSON to archive."
164
+ exit 0
165
+ fi
166
+ branch="auto/release-baselines/${TAG}"
167
+ git config user.name "pretensor-vps-agent[bot]"
168
+ git config user.email "277292434+pretensor-vps-agent[bot]@users.noreply.github.com"
169
+ git checkout -b "${branch}"
170
+ git add "tests/benchmark/results/${TAG}/"
171
+ git commit -m "ci(release): archive release-gate baselines for ${TAG}"
172
+ git push -u origin "${branch}"
173
+ gh pr create \
174
+ --base main \
175
+ --head "${branch}" \
176
+ --title "ci(release): archive release-gate baselines for ${TAG}" \
177
+ --body "Auto-generated by the release workflow after a successful publish of ${TAG}. Carries the L1 + L2 result JSON the next tag cut will compare against; data only, no code change."
178
+
179
+ github-release:
180
+ name: Create GitHub Release
181
+ needs: [pypi, detect]
182
+ # Same transitive-skip fix as archive-results: run whenever the publish
183
+ # itself succeeded, even though TestPyPI was skipped for a final release.
184
+ if: always() && needs.pypi.result == 'success' && needs.detect.result == 'success'
185
+ runs-on: ubuntu-latest
186
+ permissions:
187
+ contents: write
188
+ steps:
189
+ - uses: actions/checkout@v4
190
+ with:
191
+ fetch-depth: 0
192
+ - name: Create release with generated notes
193
+ env:
194
+ GH_TOKEN: ${{ github.token }}
195
+ TAG: ${{ github.ref_name }}
196
+ PRERELEASE: ${{ needs.detect.outputs.is_prerelease }}
197
+ run: |
198
+ flags=(--generate-notes --verify-tag --title "${TAG}")
199
+ [ "${PRERELEASE}" = "true" ] && flags+=(--prerelease)
200
+ gh release create "${TAG}" "${flags[@]}"