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.
- pretensor-0.2.0/.github/ISSUE_TEMPLATE/schema_report.yml +122 -0
- pretensor-0.2.0/.github/workflows/bench.yml +155 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/ci.yml +66 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/e2e.yml +2 -2
- pretensor-0.2.0/.github/workflows/no-internal-refs.yml +41 -0
- pretensor-0.2.0/.github/workflows/open-publish-pr.yml +41 -0
- pretensor-0.2.0/.github/workflows/release.yml +200 -0
- pretensor-0.2.0/.pre-commit-config.yaml +35 -0
- pretensor-0.2.0/CHANGELOG.md +262 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/CODE_OF_CONDUCT.md +1 -2
- pretensor-0.2.0/PKG-INFO +278 -0
- pretensor-0.2.0/README.md +201 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/SECURITY.md +37 -0
- pretensor-0.2.0/docs/agent-framework-adapters.md +84 -0
- pretensor-0.2.0/docs/ci.md +49 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/docs/releases.md +10 -4
- pretensor-0.2.0/examples/README.md +25 -0
- pretensor-0.2.0/examples/claude-code/README.md +52 -0
- pretensor-0.2.0/examples/claude-code/mcp.json +8 -0
- pretensor-0.2.0/examples/cursor/README.md +50 -0
- pretensor-0.2.0/examples/cursor/mcp.json +8 -0
- pretensor-0.2.0/examples/pagila/.gitignore +2 -0
- pretensor-0.2.0/examples/pagila/README.md +77 -0
- pretensor-0.2.0/examples/pagila/docker-compose.yml +19 -0
- pretensor-0.2.0/examples/snowflake-tpch/README.md +126 -0
- pretensor-0.2.0/examples/windsurf/README.md +51 -0
- pretensor-0.2.0/examples/windsurf/mcp_config.json +8 -0
- pretensor-0.2.0/guides/quickstart.md +607 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/pyproject.toml +31 -5
- pretensor-0.2.0/scripts/check_no_internal_refs.py +114 -0
- pretensor-0.2.0/scripts/data/adventureworks/schema.sql +3046 -0
- pretensor-0.2.0/scripts/data/adventureworks_metric_templates.yaml +67 -0
- pretensor-0.2.0/scripts/data/adventureworks_nl2sql_bench.json +130 -0
- pretensor-0.2.0/scripts/data/pagila/schema.sql +1842 -0
- pretensor-0.2.0/scripts/data/pagila_metric_templates.yaml +67 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/data/pagila_nl2sql_bench.json +18 -4
- pretensor-0.2.0/scripts/data/tpch/schema.sql +121 -0
- pretensor-0.2.0/scripts/data/tpch_metric_templates.yaml +67 -0
- pretensor-0.2.0/scripts/data/tpch_nl2sql_bench.json +138 -0
- pretensor-0.2.0/scripts/generate_schema_snapshot.py +165 -0
- pretensor-0.2.0/src/pretensor/benchmark/__init__.py +54 -0
- pretensor-0.2.0/src/pretensor/benchmark/cli.py +294 -0
- pretensor-0.2.0/src/pretensor/benchmark/fixtures.py +84 -0
- pretensor-0.2.0/src/pretensor/benchmark/l1/__init__.py +23 -0
- pretensor-0.2.0/src/pretensor/benchmark/l1/metrics.py +141 -0
- pretensor-0.2.0/src/pretensor/benchmark/l1/pipeline.py +188 -0
- pretensor-0.2.0/src/pretensor/benchmark/l1/runner.py +238 -0
- pretensor-0.2.0/src/pretensor/benchmark/l2/__init__.py +27 -0
- pretensor-0.2.0/src/pretensor/benchmark/l2/gold.py +236 -0
- pretensor-0.2.0/src/pretensor/benchmark/l2/metrics.py +146 -0
- pretensor-0.2.0/src/pretensor/benchmark/l2/pipeline.py +124 -0
- pretensor-0.2.0/src/pretensor/benchmark/l2/runner.py +523 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/__init__.py +73 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/agent.py +316 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/db.py +188 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/gold.py +85 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/llm_client.py +395 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/mcp_client.py +357 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/pretensor_runner.py +449 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/prompt.py +132 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/runner.py +351 -0
- pretensor-0.2.0/src/pretensor/benchmark/l3/sql_equivalence.py +176 -0
- pretensor-0.2.0/src/pretensor/benchmark/release_gate.py +675 -0
- pretensor-0.2.0/src/pretensor/benchmark/results.py +298 -0
- pretensor-0.2.0/src/pretensor/benchmark/runner.py +109 -0
- pretensor-0.2.0/src/pretensor/cli/commands/_command_runners.py +406 -0
- pretensor-0.2.0/src/pretensor/cli/commands/_source_runner.py +147 -0
- pretensor-0.2.0/src/pretensor/cli/commands/analyze.py +205 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/add_remove.py +5 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/export.py +15 -4
- pretensor-0.2.0/src/pretensor/cli/commands/index.py +301 -0
- pretensor-0.2.0/src/pretensor/cli/commands/init.py +661 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/list.py +15 -4
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/quickstart.py +49 -11
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/reindex.py +156 -79
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/serve.py +29 -14
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/validate.py +29 -9
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/config_file.py +326 -23
- pretensor-0.2.0/src/pretensor/cli/init/inference.py +160 -0
- pretensor-0.2.0/src/pretensor/cli/init/mcp_clients.py +170 -0
- pretensor-0.2.0/src/pretensor/cli/init/steps.py +194 -0
- pretensor-0.2.0/src/pretensor/cli/init/wizard.py +62 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/main.py +53 -5
- pretensor-0.2.0/src/pretensor/cli/prompts.py +102 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/config.py +100 -6
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/bigquery.py +8 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/inspect.py +33 -25
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/lineage_sqlglot.py +15 -9
- pretensor-0.2.0/src/pretensor/connectors/mysql.py +402 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/postgres.py +36 -19
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/registry.py +45 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/snapshot.py +62 -37
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/snowflake.py +96 -28
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/builder.py +43 -4
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/dsn_crypto.py +14 -3
- pretensor-0.2.0/src/pretensor/core/graph_schema_manager.py +246 -0
- pretensor-0.1.0a3/src/pretensor/core/store.py → pretensor-0.2.0/src/pretensor/core/graph_store.py +389 -445
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/ids.py +33 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/portable_export.py +34 -11
- pretensor-0.2.0/src/pretensor/core/query_runner.py +67 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/registry.py +10 -5
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/schema.py +119 -14
- pretensor-0.2.0/src/pretensor/core/secure_io.py +93 -0
- pretensor-0.2.0/src/pretensor/core/store.py +501 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/classify.py +49 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/extract_python.py +196 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/extract_sql_file.py +83 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/parse.py +141 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/pipeline.py +282 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/summary.py +41 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/walker.py +133 -0
- pretensor-0.2.0/src/pretensor/enrichment/analyze/writers.py +214 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/manifest.py +3 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/classifier.py +26 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/llm_extract.py +2 -2
- pretensor-0.2.0/src/pretensor/errors.py +35 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/__init__.py +3 -0
- pretensor-0.2.0/src/pretensor/graph_models/consumer.py +71 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/node.py +4 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/relationship.py +7 -1
- pretensor-0.2.0/src/pretensor/integrations/__init__.py +42 -0
- pretensor-0.2.0/src/pretensor/integrations/_base.py +138 -0
- pretensor-0.2.0/src/pretensor/integrations/google_adk.py +49 -0
- pretensor-0.2.0/src/pretensor/integrations/langchain.py +55 -0
- pretensor-0.2.0/src/pretensor/integrations/llamaindex.py +53 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/cluster_labeler.py +102 -12
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/clustering.py +6 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/discovery.py +8 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/embeddings.py +121 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/graph_export.py +67 -6
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/heuristic.py +65 -29
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/on_demand.py +57 -14
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/llm_infer.py +1 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/llm_runtime.py +4 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/pipeline.py +133 -23
- pretensor-0.2.0/src/pretensor/intelligence/role_exemplars.py +263 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/schema_classification.py +58 -4
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/scoring.py +11 -1
- pretensor-0.2.0/src/pretensor/intelligence/semantic.py +240 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/steps.py +33 -3
- pretensor-0.2.0/src/pretensor/intelligence/steps_embedding.py +168 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/config.py +1 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/dsn.py +135 -6
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/config_json.py +1 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/payload_types.py +51 -6
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/resources/__init__.py +0 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/resources/markdown.py +13 -119
- pretensor-0.2.0/src/pretensor/mcp/server.py +289 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service.py +4 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service_context.py +25 -9
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/service_registry.py +62 -10
- pretensor-0.2.0/src/pretensor/mcp/store_cache.py +43 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tool_registry.py +21 -11
- pretensor-0.2.0/src/pretensor/mcp/tools/_rank.py +244 -0
- pretensor-0.2.0/src/pretensor/mcp/tools/_timed.py +26 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/compile_metric.py +59 -2
- pretensor-0.2.0/src/pretensor/mcp/tools/consumers.py +161 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/context.py +235 -8
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/cypher.py +198 -22
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/detect_changes.py +40 -10
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/impact.py +109 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/list.py +23 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/schema.py +46 -4
- pretensor-0.2.0/src/pretensor/mcp/tools/search.py +316 -0
- pretensor-0.2.0/src/pretensor/mcp/tools/semantic_search.py +282 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/traverse.py +362 -36
- pretensor-0.2.0/src/pretensor/mcp/tools/validate_sql.py +150 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/README.md +3 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/docker-compose.yml +5 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/base.py +2 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/__init__.py +1 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/base.py +3 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/compiler.py +153 -12
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/semantic/yaml_layer.py +3 -5
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/graph_patcher.py +98 -1
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/impact_analyzer.py +3 -2
- pretensor-0.2.0/src/pretensor/version.py +20 -0
- pretensor-0.2.0/tests/benchmark/_compare.py +23 -0
- pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l1-embeddings.json +1610 -0
- pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l1.json +1609 -0
- pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l2-embeddings.json +953 -0
- pretensor-0.2.0/tests/benchmark/baselines/adventureworks-l2.json +487 -0
- pretensor-0.2.0/tests/benchmark/baselines/adversarial-l1.json +77 -0
- pretensor-0.2.0/tests/benchmark/baselines/analytics_dwh-l1.json +55 -0
- pretensor-0.2.0/tests/benchmark/baselines/messy_warehouse-l1.json +665 -0
- pretensor-0.2.0/tests/benchmark/baselines/pagila-l1-embeddings.json +158 -0
- pretensor-0.2.0/tests/benchmark/baselines/pagila-l1.json +91 -0
- pretensor-0.2.0/tests/benchmark/baselines/pagila-l2-embeddings.json +539 -0
- pretensor-0.2.0/tests/benchmark/baselines/pagila-l2.json +323 -0
- pretensor-0.2.0/tests/benchmark/baselines/saas_multitenant-l1.json +73 -0
- pretensor-0.2.0/tests/benchmark/baselines/tpch-l1-embeddings.json +80 -0
- pretensor-0.2.0/tests/benchmark/baselines/tpch-l1.json +79 -0
- pretensor-0.2.0/tests/benchmark/baselines/tpch-l2-embeddings.json +1096 -0
- pretensor-0.2.0/tests/benchmark/baselines/tpch-l2.json +562 -0
- pretensor-0.2.0/tests/benchmark/fixtures/baseline.json +20 -0
- pretensor-0.2.0/tests/benchmark/fixtures/regressed.json +20 -0
- pretensor-0.2.0/tests/benchmark/l1/test_metrics.py +168 -0
- pretensor-0.2.0/tests/benchmark/l1/test_runner.py +172 -0
- pretensor-0.2.0/tests/benchmark/l2/test_gold.py +306 -0
- pretensor-0.2.0/tests/benchmark/l2/test_metrics.py +201 -0
- pretensor-0.2.0/tests/benchmark/l2/test_runner.py +151 -0
- pretensor-0.2.0/tests/benchmark/l3/__init__.py +0 -0
- pretensor-0.2.0/tests/benchmark/l3/test_agent.py +377 -0
- pretensor-0.2.0/tests/benchmark/l3/test_db.py +285 -0
- pretensor-0.2.0/tests/benchmark/l3/test_gold.py +102 -0
- pretensor-0.2.0/tests/benchmark/l3/test_llm_client.py +525 -0
- pretensor-0.2.0/tests/benchmark/l3/test_mcp_client.py +307 -0
- pretensor-0.2.0/tests/benchmark/l3/test_pretensor_runner.py +950 -0
- pretensor-0.2.0/tests/benchmark/l3/test_prompt.py +152 -0
- pretensor-0.2.0/tests/benchmark/l3/test_runner.py +597 -0
- pretensor-0.2.0/tests/benchmark/l3/test_sql_equivalence.py +210 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/adventureworks-l1.json +4183 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/adventureworks-l2.json +487 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/pagila-l1.json +91 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/pagila-l2.json +323 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/tpch-l1.json +79 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0/tpch-l2.json +562 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/README.md +15 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/adventureworks-l1.json +4183 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/adventureworks-l2.json +487 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/pagila-l1.json +91 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/pagila-l2.json +323 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/tpch-l1.json +79 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a3/tpch-l2.json +562 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/adventureworks-l1.json +4183 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/adventureworks-l2.json +487 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/pagila-l1.json +91 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/pagila-l2.json +323 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/tpch-l1.json +79 -0
- pretensor-0.2.0/tests/benchmark/results/v0.1.0a4/tpch-l2.json +562 -0
- pretensor-0.2.0/tests/benchmark/results/v0.2.0/accepted-regressions.toml +24 -0
- pretensor-0.2.0/tests/benchmark/test_cli.py +456 -0
- pretensor-0.2.0/tests/benchmark/test_fixtures.py +126 -0
- pretensor-0.2.0/tests/benchmark/test_release_gate.py +780 -0
- pretensor-0.2.0/tests/benchmark/test_results.py +489 -0
- pretensor-0.2.0/tests/cli/conftest.py +20 -0
- pretensor-0.2.0/tests/cli/init/__init__.py +0 -0
- pretensor-0.2.0/tests/cli/init/test_inference.py +79 -0
- pretensor-0.2.0/tests/cli/init/test_mcp_clients.py +209 -0
- pretensor-0.2.0/tests/cli/init/test_steps.py +204 -0
- pretensor-0.2.0/tests/cli/init/test_wizard.py +39 -0
- pretensor-0.2.0/tests/cli/test_analyze_cli.py +670 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_cli_error_handling.py +15 -7
- pretensor-0.2.0/tests/cli/test_config_file.py +1163 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_connections_cli.py +5 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_export_cli.py +124 -4
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_index_cli.py +219 -15
- pretensor-0.2.0/tests/cli/test_init_cli.py +2163 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_list_cli.py +13 -4
- pretensor-0.2.0/tests/cli/test_main_cli.py +182 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_plugin.py +16 -6
- pretensor-0.2.0/tests/cli/test_prompts.py +39 -0
- pretensor-0.2.0/tests/cli/test_quickstart_cli.py +197 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_reindex_cli.py +344 -25
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_serve_cli.py +23 -12
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_validate_cli.py +76 -7
- pretensor-0.2.0/tests/conftest.py +187 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_dsn_parsing.py +283 -19
- pretensor-0.2.0/tests/connectors/test_inspect_collect_stats.py +67 -0
- pretensor-0.2.0/tests/connectors/test_mysql_connector.py +823 -0
- pretensor-0.2.0/tests/connectors/test_registry_mysql_optional.py +35 -0
- pretensor-0.2.0/tests/connectors/test_registry_postgres_optional.py +45 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_snowflake_connector.py +354 -17
- pretensor-0.2.0/tests/contracts/__init__.py +4 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_combiner.py +4 -4
- pretensor-0.2.0/tests/contracts/test_consumer_node.py +77 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_pipeline_step.py +34 -15
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_scorer.py +23 -12
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_search_index.py +2 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/contracts/test_semantic_layer.py +4 -4
- pretensor-0.2.0/tests/core/test_dsn_at_rest.py +113 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_portable_export.py +39 -0
- pretensor-0.2.0/tests/core/test_schema.py +96 -0
- pretensor-0.2.0/tests/core/test_schema_external_consumer.py +38 -0
- pretensor-0.2.0/tests/core/test_store_consumer_upserts.py +339 -0
- pretensor-0.2.0/tests/e2e/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/conftest.py +90 -0
- pretensor-0.2.0/tests/e2e/fixtures/__init__.py +0 -0
- pretensor-0.2.0/tests/e2e/fixtures/sql/messy_warehouse_ddl.sql +300 -0
- pretensor-0.2.0/tests/e2e/fixtures/sql/sakila_mysql_ddl.sql +83 -0
- pretensor-0.2.0/tests/e2e/test_l3_baseline.py +161 -0
- pretensor-0.2.0/tests/e2e/test_l3_pretensor.py +302 -0
- pretensor-0.2.0/tests/e2e/test_mysql_index_cycle.py +125 -0
- pretensor-0.2.0/tests/enrichment/__init__.py +0 -0
- pretensor-0.2.0/tests/enrichment/analyze/__init__.py +0 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/cross_connection.py +1 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/dml_writes.py +4 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/dynamic_only.py +5 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/fstring_prefix.py +2 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/multi_statement.sql +6 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/noqa_optout.py +6 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/simple.sql +4 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/simple_select.py +1 -0
- pretensor-0.2.0/tests/enrichment/analyze/fixtures/unparseable.sql +2 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_classify.py +100 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_extract_python.py +174 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_extract_sql_file.py +215 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_parse.py +185 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_pipeline.py +474 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_walker.py +177 -0
- pretensor-0.2.0/tests/enrichment/analyze/test_writers.py +334 -0
- pretensor-0.2.0/tests/fixtures/schemas/README.md +133 -0
- pretensor-0.2.0/tests/fixtures/schemas/adventureworks.yaml +20694 -0
- pretensor-0.2.0/tests/fixtures/schemas/adversarial_roles.yaml +16 -0
- pretensor-0.2.0/tests/fixtures/schemas/messy_warehouse.yaml +3872 -0
- pretensor-0.2.0/tests/fixtures/schemas/messy_warehouse_roles.yaml +43 -0
- pretensor-0.2.0/tests/fixtures/schemas/pagila_extended.yaml +1459 -0
- pretensor-0.2.0/tests/integrations/__init__.py +0 -0
- pretensor-0.2.0/tests/integrations/test_base.py +217 -0
- pretensor-0.2.0/tests/integrations/test_google_adk.py +96 -0
- pretensor-0.2.0/tests/integrations/test_langchain.py +107 -0
- pretensor-0.2.0/tests/integrations/test_llamaindex.py +105 -0
- pretensor-0.2.0/tests/intelligence/slow/__init__.py +0 -0
- pretensor-0.2.0/tests/intelligence/slow/test_real_model_smoke.py +100 -0
- pretensor-0.2.0/tests/intelligence/test_clustering_embeddings.py +414 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_discovery.py +73 -0
- pretensor-0.2.0/tests/intelligence/test_embedding_index_step.py +348 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_embeddings.py +44 -0
- pretensor-0.2.0/tests/intelligence/test_extended_pagila.py +80 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_heuristic.py +82 -18
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_join_paths.py +132 -5
- pretensor-0.2.0/tests/intelligence/test_null_path_parity.py +212 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_pipeline.py +19 -3
- pretensor-0.2.0/tests/intelligence/test_role_exemplars.py +231 -0
- pretensor-0.2.0/tests/intelligence/test_semantic_scorer.py +344 -0
- pretensor-0.2.0/tests/mcp/test_consumers_tool.py +152 -0
- pretensor-0.2.0/tests/mcp/test_context_similar.py +339 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_tool.py +2 -1
- pretensor-0.2.0/tests/mcp/test_cypher_readonly.py +170 -0
- pretensor-0.2.0/tests/mcp/test_cypher_timeout_pool.py +104 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_detect_changes_errors.py +30 -3
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_error_handling.py +20 -7
- pretensor-0.2.0/tests/mcp/test_error_sanitization.py +127 -0
- pretensor-0.2.0/tests/mcp/test_impact_consumers.py +127 -0
- pretensor-0.2.0/tests/mcp/test_kill_switch.py +211 -0
- pretensor-0.2.0/tests/mcp/test_mcp_null_path_parity.py +233 -0
- pretensor-0.2.0/tests/mcp/test_query_hybrid.py +357 -0
- pretensor-0.2.0/tests/mcp/test_semantic_search.py +428 -0
- pretensor-0.2.0/tests/mcp/test_serve_stdio_smoke.py +133 -0
- pretensor-0.2.0/tests/mcp/test_server_version.py +52 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_service.py +6 -2
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_tool_registry.py +8 -8
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_dijkstra.py +107 -2
- pretensor-0.2.0/tests/mcp/test_traverse_tiebreak.py +412 -0
- pretensor-0.2.0/tests/scripts/__init__.py +0 -0
- pretensor-0.2.0/tests/scripts/test_check_no_internal_refs.py +138 -0
- pretensor-0.2.0/tests/semantic/__init__.py +0 -0
- pretensor-0.2.0/tests/staleness/test_staleness.py +572 -0
- pretensor-0.2.0/tests/test_errors.py +131 -0
- pretensor-0.2.0/tests/test_graph_schema_manager.py +64 -0
- pretensor-0.2.0/tests/test_graph_store.py +86 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_pretensor_config.py +22 -10
- pretensor-0.2.0/tests/test_query_runner.py +48 -0
- pretensor-0.2.0/tests/test_store_cache.py +185 -0
- pretensor-0.2.0/tests/utils/__init__.py +0 -0
- pretensor-0.2.0/tests/validation/test_compile_did_you_mean.py +488 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/uv.lock +1950 -63
- pretensor-0.1.0a3/.github/dependabot.yml +0 -49
- pretensor-0.1.0a3/.github/workflows/release.yml +0 -93
- pretensor-0.1.0a3/.pre-commit-config.yaml +0 -21
- pretensor-0.1.0a3/CHANGELOG.md +0 -29
- pretensor-0.1.0a3/PKG-INFO +0 -183
- pretensor-0.1.0a3/README.md +0 -120
- pretensor-0.1.0a3/guides/quickstart.md +0 -331
- pretensor-0.1.0a3/scripts/benchmark_graph_rag_nl2sql.py +0 -335
- pretensor-0.1.0a3/scripts/e2e_pagila.py +0 -625
- pretensor-0.1.0a3/src/pretensor/cli/commands/index.py +0 -551
- pretensor-0.1.0a3/src/pretensor/mcp/server.py +0 -723
- pretensor-0.1.0a3/src/pretensor/mcp/tools/search.py +0 -108
- pretensor-0.1.0a3/src/pretensor/mcp/tools/validate_sql.py +0 -74
- pretensor-0.1.0a3/tests/cli/test_config_file.py +0 -612
- pretensor-0.1.0a3/tests/cli/test_main_cli.py +0 -92
- pretensor-0.1.0a3/tests/cli/test_quickstart_cli.py +0 -109
- pretensor-0.1.0a3/tests/conftest.py +0 -70
- pretensor-0.1.0a3/tests/contracts/__init__.py +0 -4
- pretensor-0.1.0a3/tests/staleness/test_staleness.py +0 -159
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.env.example +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitattributes +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/CODEOWNERS +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/pull_request_template.md +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.github/workflows/docs.yml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitignore +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.gitlint +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/.python-version +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/CONTRIBUTING.md +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/LICENSE +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/Makefile +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/audit_deny_list.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/scripts/check_readme_urls.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/connections/register.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/semantic.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/commands/sync_grants.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/constants.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/dbt_enrichment.py +0 -0
- {pretensor-0.1.0a3/src/pretensor/introspection/models → pretensor-0.2.0/src/pretensor/cli/init}/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/paths.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/cli/plugin.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/base.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/models.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/connectors/pg_array_parse.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/core/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/__init__.py +0 -0
- {pretensor-0.1.0a3/tests/e2e → pretensor-0.2.0/src/pretensor/enrichment/analyze}/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/lineage.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/metadata.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/pipeline.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/resolution.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/enrichment/dbt/signals.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/entities/builder.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/base.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/edge.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/graph_models/entity.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/combining.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/join_paths/storage.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/metric_templates.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/shadow_alias.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/intelligence/statistical.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/inspector.py +0 -0
- {pretensor-0.1.0a3/tests/e2e/fixtures → pretensor-0.2.0/src/pretensor/introspection/models}/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/base.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/plan.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/schema.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/semantic.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/models/validation.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/introspection/snapshot.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/mcp/tools/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/observability.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/py.typed +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/pagila_data.sql +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/quickstart/pagila_ddl.sql +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/search/index.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/skills/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/skills/generator.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/staleness/snapshot_store.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/validation/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/validation/query_validator.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/config.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/filter.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/kuzu_helpers.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/runtime.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/src/pretensor/visibility/sync_grants.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/__init__.py +0 -0
- {pretensor-0.1.0a3/tests/enrichment → pretensor-0.2.0/tests/benchmark}/__init__.py +0 -0
- {pretensor-0.1.0a3/tests/semantic → pretensor-0.2.0/tests/benchmark/l1}/__init__.py +0 -0
- {pretensor-0.1.0a3/tests/utils → pretensor-0.2.0/tests/benchmark/l2}/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_dbt_enrichment_cli.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_paths_cli.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_semantic_cli.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/cli/test_sync_grants_cli.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_base_connector.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_bigquery.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_catalog_enrichment.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_lineage_sqlglot.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_pg_array_parse.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_postgres_table_grants.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_postgres_views.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_registry_snowflake_optional.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/connectors/test_snowflake_table_grants.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_builder.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_graph_builder_lineage.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_lineage_store.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_models.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_registry.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/core/test_semantic_schema.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/adventureworks_ddl.sql +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/tpcds_ddl.sql +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/fixtures/sql/tpch_ddl.sql +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_adventureworks_smoke.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_adventureworks_traverse.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_dbt_warehouse_scale_enrichment.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_index_cycle.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_mcp_tools.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_reindex.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_serve_smoke.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_tpcds_traverse.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_tpch_traverse.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/e2e/test_visibility.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/fixtures/dbt/manifest_v10.json +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/fixtures/dbt/manifest_v9.json +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_lineage.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_manifest.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_metadata.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_pipeline.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/enrichment/test_dbt_signals.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_classifier.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_entity_builder.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_llm_extract.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/entities/test_pagila_entities.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/README.md +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/__init__.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/dbt/synthetic_warehouse/generator.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/analytics_vs_saas.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/tpch_vs_pagila.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/pairs/tpch_vs_tpch_renamed.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/adversarial.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/analytics_dwh.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/pagila.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/saas_multitenant.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/fixtures/schemas/tpch.yaml +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_cluster_labeler.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_clustering.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_intelligence.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_llm_infer.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_llm_runtime.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_metric_templates.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_schema_classification.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_shadow_alias.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/intelligence/test_statistical.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_compile_metric_tool.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_dbt.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_context_lineage.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_error_ergonomics.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_impact_hop.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_schema_tool.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_ambiguous.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_traverse_pagila_shape.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_validate_sql_tool.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/mcp/test_visibility_mcp.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/query_helpers.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/search/test_search_index.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_compiler.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_semantic_layer.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/semantic/test_yaml_layer.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_gitlint_config.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_observability.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/test_packaging.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/utils/score_tracker.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/validation/test_query_validator.py +0 -0
- {pretensor-0.1.0a3 → pretensor-0.2.0}/tests/visibility/test_sync_grants.py +0 -0
- {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 (
|
|
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[@]}"
|