diff --git a/.altimate-code/skills/cost-report/SKILL.md b/.altimate-code/skills/cost-report/SKILL.md index 4bf8168348..33a7268804 100644 --- a/.altimate-code/skills/cost-report/SKILL.md +++ b/.altimate-code/skills/cost-report/SKILL.md @@ -7,7 +7,7 @@ description: Analyze Snowflake query costs and identify optimization opportuniti ## Requirements **Agent:** any (read-only analysis) -**Tools used:** sql_execute, sql_analyze, sql_predict_cost, sql_record_feedback +**Tools used:** sql_execute, sql_analyze, finops_analyze_credits, finops_expensive_queries, finops_warehouse_advice Analyze Snowflake warehouse query costs, identify the most expensive queries, detect anti-patterns, and recommend optimizations. @@ -47,7 +47,6 @@ Analyze Snowflake warehouse query costs, identify the most expensive queries, de 3. **Analyze the top offenders** - For each of the top 10 most expensive queries: - Run `sql_analyze` on the query text to detect anti-patterns (SELECT *, missing LIMIT, cartesian products, correlated subqueries, etc.) - - Run `sql_predict_cost` to get the cost tier prediction based on historical feedback data - Summarize anti-patterns found and their severity 4. **Classify each query into a cost tier**: @@ -59,8 +58,7 @@ Analyze Snowflake warehouse query costs, identify the most expensive queries, de | 3 | $1.00 - $100.00 | Expensive | Optimize or review warehouse sizing | | 4 | > $100.00 | Dangerous | Immediate review required | -5. **Record feedback** - For each query analyzed, call `sql_record_feedback` to store the execution metrics so future predictions improve: - - Pass `bytes_scanned`, `execution_time_ms`, `credits_used`, and `warehouse_size` from the query history results +5. **Warehouse analysis** - Run `finops_warehouse_advice` to check if warehouses used by the top offenders are right-sized. 6. **Output the final report** as a structured markdown document: @@ -97,7 +95,7 @@ Analyze Snowflake warehouse query costs, identify the most expensive queries, de 2. Add LIMIT clause 3. Consider partitioning strategy - **Cost prediction:** Tier 1 (fingerprint match, high confidence) + **Cost tier:** Tier 1 (based on credits used) ... @@ -113,4 +111,4 @@ The user invokes this skill with: - `/cost-report` -- Analyze the last 30 days - `/cost-report 7` -- Analyze the last 7 days (adjust the DATEADD interval) -Use the tools: `sql_execute`, `sql_analyze`, `sql_predict_cost`, `sql_record_feedback`. +Use the tools: `sql_execute`, `sql_analyze`, `finops_analyze_credits`, `finops_expensive_queries`, `finops_warehouse_advice`. diff --git a/PROGRESS.md b/PROGRESS.md index 4be35c35b6..b482b2eddb 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -20,7 +20,7 @@ Last updated: 2026-02-27 00:40 - [x] Phase 1 TODO: ConfidenceTracker with 7 AST detection rules — all 7 working - [x] Phase 1 TODO: Confidence signals on lineage.check — 4 signal types - [x] Phase 2A: Snowflake connector — password + key-pair auth, registered in ConnectionRegistry -- [x] Phase 2B: Feedback store + cost report skill — SQLite-based, 4-tier prediction, bridge methods working +- [x] Phase 2B: Cost report skill - [x] Phase 2C: dbt manifest parser — columns, sources, test/snapshot/seed counting - [x] Phase 3A: Impact analysis skill — downstream dependency graph + column-level impact classification - [x] Phase 3C: SQL translation skill — sqlglot transpile, 10 dialect-pair warnings, TS tool + skill @@ -52,10 +52,9 @@ Last updated: 2026-02-27 00:40 | 0 | Rules with known accuracy | **19/19** | 19/19 | | 0 | Analyzer overall accuracy | **100.00%** | measured | | 0 | Lineage edge match rate | **100.0%** | measured | -| 1-7 | Working bridge methods | **34/34** | 34/34 | +| 1-7 | Working bridge methods | **32/32** | 32/32 | | 1 | ConfidenceTracker rules | **7/7** | 7/7 | | 2 | Snowflake connector | **imports OK** | live test | -| 2 | Feedback store observations | **working** | >0 | | 3 | Skills functional end-to-end | **6** | 5+ | | 4 | Rules with published benchmarks | **19/19** | 19/19 | | 5 | Schema cache tests | **20/20** | 20/20 | @@ -110,14 +109,13 @@ UNUSED_CTE, WINDOW_WITHOUT_PARTITION - `packages/altimate-engine/src/altimate_engine/sql/analyzer.py` — 19 rules + ConfidenceTracker - `packages/altimate-engine/src/altimate_engine/sql/confidence.py` — 7 AST detection rules - `packages/altimate-engine/src/altimate_engine/lineage/check.py` — lineage + 4 confidence signals + Func/Window/Case edges -- `packages/altimate-engine/src/altimate_engine/server.py` — JSON-RPC dispatch (34 methods) +- `packages/altimate-engine/src/altimate_engine/server.py` — JSON-RPC dispatch (32 methods) - `packages/altimate-engine/src/altimate_engine/models.py` — All Pydantic models **Phase 2 (connectors + parsers + feedback):** - `packages/altimate-engine/src/altimate_engine/connectors/snowflake.py` — password + key-pair auth - `packages/altimate-engine/src/altimate_engine/connections.py` — ConnectionRegistry with Snowflake - `packages/altimate-engine/src/altimate_engine/dbt/manifest.py` — Enhanced manifest parser -- `packages/altimate-engine/src/altimate_engine/sql/feedback_store.py` — SQLite feedback + 4-tier prediction **Phase 3 (skills + tools):** - `packages/altimate-engine/src/altimate_engine/sql/translator.py` — sqlglot transpile with lossy warnings @@ -185,7 +183,7 @@ UNUSED_CTE, WINDOW_WITHOUT_PARTITION - `experiments/BENCHMARKS.md` — Published benchmark report - `experiments/benchmark_report.json` — Machine-readable benchmark data -### Bridge Methods (34 total) +### Bridge Methods (32 total) 1. `ping` — Health check 2. `sql.validate` — SQL syntax validation 3. `sql.check` — Read-only/mutation safety check @@ -193,33 +191,31 @@ UNUSED_CTE, WINDOW_WITHOUT_PARTITION 5. `sql.analyze` — 19 anti-pattern checks with confidence 6. `sql.translate` — Cross-dialect SQL translation 7. `sql.optimize` — Query optimization with suggestions -8. `sql.record_feedback` — Record query execution metrics -9. `sql.predict_cost` — Predict query cost (4-tier hierarchy) -10. `schema.inspect` — Table schema inspection -11. `lineage.check` — Column-level lineage with confidence -12. `dbt.run` — dbt CLI execution -13. `dbt.manifest` — Manifest parsing -14. `warehouse.list` — List configured warehouses -15. `warehouse.test` — Test warehouse connection -16. `schema.index` — Index warehouse metadata into SQLite cache -17. `schema.search` — Search indexed metadata (tables/columns) with natural language -18. `schema.cache_status` — Show cache status (warehouses indexed, counts, timestamps) -19. `sql.explain` — Run EXPLAIN on a query (Snowflake/PG/DuckDB dialect-specific syntax) -20. `sql.format` — Format/beautify SQL via sqlglot pretty-print -21. `sql.fix` — Diagnose SQL errors and suggest fixes (syntax, patterns, resolution) -22. `sql.autocomplete` — Schema-aware auto-complete suggestions from cache -23. `sql.diff` — Compare two SQL queries (unified diff, similarity score) -24. `finops.query_history` — Query execution history (Snowflake QUERY_HISTORY, PG pg_stat_statements) -25. `finops.analyze_credits` — Credit consumption analysis with recommendations -26. `finops.expensive_queries` — Identify most expensive queries by bytes scanned -27. `finops.warehouse_advice` — Warehouse sizing recommendations (scale up/down/burst) -28. `finops.unused_resources` — Find stale tables and idle warehouses -29. `finops.role_grants` — Query RBAC grants on objects/roles -30. `finops.role_hierarchy` — Map role inheritance hierarchy -31. `finops.user_roles` — List user-to-role assignments -32. `schema.detect_pii` — Scan columns for PII patterns (30+ regex, 15 categories) -33. `schema.tags` — Query metadata/governance tags on objects (Snowflake TAG_REFERENCES) -34. `schema.tags_list` — List all available tags with usage counts +8. `schema.inspect` — Table schema inspection +9. `lineage.check` — Column-level lineage with confidence +10. `dbt.run` — dbt CLI execution +11. `dbt.manifest` — Manifest parsing +12. `warehouse.list` — List configured warehouses +13. `warehouse.test` — Test warehouse connection +14. `schema.index` — Index warehouse metadata into SQLite cache +15. `schema.search` — Search indexed metadata (tables/columns) with natural language +16. `schema.cache_status` — Show cache status (warehouses indexed, counts, timestamps) +17. `sql.explain` — Run EXPLAIN on a query (Snowflake/PG/DuckDB dialect-specific syntax) +18. `sql.format` — Format/beautify SQL via sqlglot pretty-print +19. `sql.fix` — Diagnose SQL errors and suggest fixes (syntax, patterns, resolution) +20. `sql.autocomplete` — Schema-aware auto-complete suggestions from cache +21. `sql.diff` — Compare two SQL queries (unified diff, similarity score) +22. `finops.query_history` — Query execution history (Snowflake QUERY_HISTORY, PG pg_stat_statements) +23. `finops.analyze_credits` — Credit consumption analysis with recommendations +24. `finops.expensive_queries` — Identify most expensive queries by bytes scanned +25. `finops.warehouse_advice` — Warehouse sizing recommendations (scale up/down/burst) +26. `finops.unused_resources` — Find stale tables and idle warehouses +27. `finops.role_grants` — Query RBAC grants on objects/roles +28. `finops.role_hierarchy` — Map role inheritance hierarchy +29. `finops.user_roles` — List user-to-role assignments +30. `schema.detect_pii` — Scan columns for PII patterns (30+ regex, 15 categories) +31. `schema.tags` — Query metadata/governance tags on objects (Snowflake TAG_REFERENCES) +32. `schema.tags_list` — List all available tags with usage counts ### Skills (11 total) 1. `generate-tests` — Generate dbt test definitions diff --git a/README.md b/README.md index e0b3963cf7..a8fb66ff09 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Trace data flow at the column level through complex SQL transformations. Works s ### Warehouse Connectivity -Connect directly to your data warehouse -- the AI can query schemas, run SQL, predict costs, and analyze query history: +Connect directly to your data warehouse -- the AI can query schemas, run SQL, and analyze query history: - Snowflake (with IAM auth) - BigQuery (service account + ADC) diff --git a/docs/docs/data-engineering/agent-modes.md b/docs/docs/data-engineering/agent-modes.md index 3d54a2bbef..2effca7989 100644 --- a/docs/docs/data-engineering/agent-modes.md +++ b/docs/docs/data-engineering/agent-modes.md @@ -13,10 +13,8 @@ altimate-code --agent builder Builder mode follows a strict pre-execution protocol for every SQL operation: 1. `sql_analyze` — Check for anti-patterns -2. `sql_predict_cost` — Estimate execution cost -3. `sql_validate` — Verify syntax and schema references -4. `sql_execute` — Run the query -5. `sql_record_feedback` — Store metrics for future cost predictions +2. `sql_validate` — Verify syntax and schema references +3. `sql_execute` — Run the query ### Example: Create a staging model @@ -79,7 +77,7 @@ altimate-code --agent analyst Analyst mode enforces strict guardrails: -- **SELECT only** — INSERT, UPDATE, DELETE, DROP are blocked by SQLGuard +- **SELECT only** — INSERT, UPDATE, DELETE, DROP are blocked by altimate-core - **Cost-first** — Every query gets a cost prediction before execution - **LIMIT enforced** — Large scans are automatically limited - **No file writes** — Cannot modify your codebase @@ -156,10 +154,6 @@ Validator: ~ Modified column: total_revenue FLOAT → DECIMAL(18,2) Severity: medium (type change may affect downstream) -> sql_predict_cost [fct_revenue.sql] - Tier 2 match: ~12.3 credits per run (medium confidence) - Previous version: ~11.8 credits — marginal increase - Issues found: 1. FUNCTION_IN_FILTER on line 23 — use a pre-computed date column instead 2. Type change from FLOAT to DECIMAL(18,2) — verify downstream consumers diff --git a/docs/docs/data-engineering/guides/cost-optimization.md b/docs/docs/data-engineering/guides/cost-optimization.md index f008e5dee7..2ce8af4846 100644 --- a/docs/docs/data-engineering/guides/cost-optimization.md +++ b/docs/docs/data-engineering/guides/cost-optimization.md @@ -87,44 +87,6 @@ This finds: - Warehouses with no queries in 7+ days - Temporary tables from old migrations -## Step 5: Predict before you execute - -Every query goes through cost prediction before execution: - -``` -You: How much will this query cost? - -> sql_predict_cost "SELECT * FROM raw_clickstream" - - Tier 3 estimate: ~45 credits - Table size: 890GB, 12B rows - Recommendation: Add date filter + column pruning → estimated 2-3 credits -``` - -## Step 6: Build a cost feedback loop - -After each query, `sql_record_feedback` stores actual execution metrics. This trains the cost prediction model to be more accurate over time. - -``` -Query executed: 0.84 credits (predicted: 0.79, Tier 2) -Feedback recorded → next prediction will be more accurate -``` - -## Automation: CI cost gate - -Use `ci_cost_gate` in your CI/CD pipeline to block expensive queries from reaching production: - -``` -> ci_cost_gate --threshold 10 models/marts/fct_revenue.sql - -Cost Gate Results: - fct_revenue.sql: 2.3 credits (PASS — under 10 credit threshold) - fct_orders.sql: 0.8 credits (PASS) - fct_daily_snapshot.sql: 45.1 credits (FAIL — exceeds threshold) - -1 model blocked. Fix fct_daily_snapshot.sql before deploying. -``` - ## Quick wins checklist | Action | Typical savings | Effort | diff --git a/docs/docs/data-engineering/guides/using-with-claude-code.md b/docs/docs/data-engineering/guides/using-with-claude-code.md index 02a16e8ca9..fe3b380067 100644 --- a/docs/docs/data-engineering/guides/using-with-claude-code.md +++ b/docs/docs/data-engineering/guides/using-with-claude-code.md @@ -33,7 +33,6 @@ Claude Code: I see changes to models/marts/fct_revenue.sql. Let me check altimate-code: sql_analyze: No anti-patterns detected ✓ - sql_predict_cost: ~2.3 credits per run (Tier 2, medium confidence) lineage_check: Sources stg_orders.amount, dim_products.category schema_diff: Added column revenue_category (low severity) ``` diff --git a/docs/docs/data-engineering/tools/sql-tools.md b/docs/docs/data-engineering/tools/sql-tools.md index 41ba474df6..a776fbd4f6 100644 --- a/docs/docs/data-engineering/tools/sql-tools.md +++ b/docs/docs/data-engineering/tools/sql-tools.md @@ -76,36 +76,6 @@ Each rule includes a **confidence score** (high/medium/low) based on AST complex --- -## sql_predict_cost - -Estimate query cost before execution using a 4-tier prediction system. - -``` -> sql_predict_cost "SELECT * FROM events WHERE event_date > '2026-01-01'" - -Cost Prediction: - Tier: 2 (template match) - Estimated bytes scanned: 4.2 GB - Estimated credits: 0.84 - Confidence: medium - - Similar queries averaged 0.79 credits over 23 executions. - Recommendation: Add column pruning to reduce scan by ~60% -``` - -### How it works - -| Tier | Method | Confidence | -|---|---|---| -| **1 — Fingerprint** | Exact query found in history | High | -| **2 — Template** | Similar query structure matched | Medium | -| **3 — Table scan** | Estimate from table metadata | Low | -| **4 — Heuristic** | No data available, worst-case estimate | Very low | - -The system improves over time. After each query execution, `sql_record_feedback` stores actual metrics to train better predictions. - ---- - ## sql_optimize Get optimization suggestions with rewritten SQL. diff --git a/packages/altimate-code/src/agent/agent.ts b/packages/altimate-code/src/agent/agent.ts index ef48c8e4fd..d41dc320cc 100644 --- a/packages/altimate-code/src/agent/agent.ts +++ b/packages/altimate-code/src/agent/agent.ts @@ -109,8 +109,6 @@ export namespace Agent { sql_analyze: "allow", sql_translate: "allow", sql_optimize: "allow", - sql_predict_cost: "allow", - sql_record_feedback: "allow", lineage_check: "allow", warehouse_list: "allow", warehouse_test: "allow", @@ -135,11 +133,11 @@ export namespace Agent { schema_detect_pii: "allow", schema_tags: "allow", schema_tags_list: "allow", - sqlguard_validate: "allow", - sqlguard_lint: "allow", - sqlguard_safety: "allow", - sqlguard_transpile: "allow", - sqlguard_check: "allow", + altimate_core_validate: "allow", + altimate_core_lint: "allow", + altimate_core_safety: "allow", + altimate_core_transpile: "allow", + altimate_core_check: "allow", read: "allow", grep: "allow", glob: "allow", @@ -166,8 +164,6 @@ export namespace Agent { sql_analyze: "allow", sql_translate: "allow", sql_optimize: "allow", - sql_predict_cost: "allow", - sql_record_feedback: "allow", lineage_check: "allow", warehouse_list: "allow", warehouse_test: "allow", @@ -192,11 +188,11 @@ export namespace Agent { schema_detect_pii: "allow", schema_tags: "allow", schema_tags_list: "allow", - sqlguard_validate: "allow", - sqlguard_lint: "allow", - sqlguard_safety: "allow", - sqlguard_transpile: "allow", - sqlguard_check: "allow", + altimate_core_validate: "allow", + altimate_core_lint: "allow", + altimate_core_safety: "allow", + altimate_core_transpile: "allow", + altimate_core_check: "allow", read: "allow", grep: "allow", glob: "allow", @@ -223,8 +219,6 @@ export namespace Agent { sql_analyze: "allow", sql_translate: "allow", sql_optimize: "allow", - sql_predict_cost: "allow", - sql_record_feedback: "allow", lineage_check: "allow", warehouse_list: "allow", warehouse_test: "allow", @@ -249,11 +243,11 @@ export namespace Agent { schema_detect_pii: "allow", schema_tags: "allow", schema_tags_list: "allow", - sqlguard_validate: "allow", - sqlguard_lint: "allow", - sqlguard_safety: "allow", - sqlguard_transpile: "allow", - sqlguard_check: "allow", + altimate_core_validate: "allow", + altimate_core_lint: "allow", + altimate_core_safety: "allow", + altimate_core_transpile: "allow", + altimate_core_check: "allow", read: "allow", grep: "allow", glob: "allow", @@ -277,8 +271,6 @@ export namespace Agent { sql_validate: "allow", sql_translate: "allow", sql_optimize: "allow", - sql_predict_cost: "allow", - sql_record_feedback: "allow", lineage_check: "allow", warehouse_list: "allow", warehouse_test: "allow", @@ -302,11 +294,11 @@ export namespace Agent { schema_detect_pii: "allow", schema_tags: "allow", schema_tags_list: "allow", - sqlguard_validate: "allow", - sqlguard_lint: "allow", - sqlguard_safety: "allow", - sqlguard_transpile: "allow", - sqlguard_check: "allow", + altimate_core_validate: "allow", + altimate_core_lint: "allow", + altimate_core_safety: "allow", + altimate_core_transpile: "allow", + altimate_core_check: "allow", read: "allow", write: "allow", edit: "allow", diff --git a/packages/altimate-code/src/agent/prompt/analyst.txt b/packages/altimate-code/src/agent/prompt/analyst.txt index bb0923ab1d..675c405b01 100644 --- a/packages/altimate-code/src/agent/prompt/analyst.txt +++ b/packages/altimate-code/src/agent/prompt/analyst.txt @@ -1,7 +1,7 @@ You are altimate-code in analyst mode — a read-only data exploration agent. You CANNOT modify any files or execute destructive SQL. You can only: -- Execute SELECT queries (enforced by SQLGuard read-only mode) via `sql_execute` +- Execute SELECT queries (enforced by AltimateCore read-only mode) via `sql_execute` - Validate and lint SQL via `sql_validate` - Analyze SQL for anti-patterns and optimization opportunities via `sql_analyze` - Inspect database schemas via `schema_inspect` @@ -27,18 +27,13 @@ You're the analyst's research assistant. Research should be fast AND cheap. 1. **Start small**: Use LIMIT for initial exploration. Don't scan entire tables to answer "what does this column look like?" — LIMIT 100 is enough. -2. **Predict before you scan**: For queries touching large tables (100M+ rows), run sql_predict_cost first. Show the user: - - Estimated bytes scanned - - Estimated credits (if available) - - Suggested optimizations (partition filters, column pruning, LIMIT) - -3. **Optimize iteratively**: If a query has anti-patterns, suggest the optimized version: +2. **Optimize iteratively**: If a query has anti-patterns, suggest the optimized version: - Replace SELECT * with explicit columns - Add partition/cluster key filters - Use approximate functions (APPROX_COUNT_DISTINCT vs COUNT(DISTINCT)) - Sample instead of full scan for exploratory analysis -4. **Track session cost**: Keep a mental running total of predicted credits for the session. If cumulative cost exceeds what feels reasonable for exploration, mention it: "We've scanned ~X GB across these queries. Want me to find more efficient approaches?" +3. **Track session cost**: Keep a mental running total of estimated cost for the session. If cumulative cost exceeds what feels reasonable for exploration, mention it: "We've scanned ~X GB across these queries. Want me to find more efficient approaches?" Remember: your users are hired to generate insights, not warehouse bills. Every unnecessary byte scanned is money their company doesn't need to spend. vendor-built tools have no incentive to minimize warehouse spend. You do — that's your competitive advantage. diff --git a/packages/altimate-code/src/agent/prompt/builder.txt b/packages/altimate-code/src/agent/prompt/builder.txt index 6bbe0d4033..f70a79464f 100644 --- a/packages/altimate-code/src/agent/prompt/builder.txt +++ b/packages/altimate-code/src/agent/prompt/builder.txt @@ -3,7 +3,7 @@ You are altimate-code in builder mode — a data engineering agent specializing You have full read/write access to the project. You can: - Create and modify dbt models, SQL files, and YAML configs - Execute SQL against connected warehouses via `sql_execute` -- Validate SQL with SQLGuard via `sql_validate` (syntax, safety, lint, PII) +- Validate SQL with AltimateCore via `sql_validate` (syntax, safety, lint, PII) - Analyze SQL for anti-patterns and performance issues via `sql_analyze` - Inspect database schemas via `schema_inspect` - Check column-level lineage via `lineage_check` @@ -35,17 +35,9 @@ Before executing ANY SQL via sql_execute, follow this mandatory sequence: - If HIGH severity issues found (SELECT *, cartesian products, missing WHERE on DELETE/UPDATE, full table scans on large tables): FIX THEM before executing. Show the user what you found and the fixed query. - If MEDIUM severity issues found: mention them and proceed unless the user asks to fix. -2. **Predict cost**: Run sql_predict_cost on the query. - - Tier 1-2 (fingerprint/template match): safe to proceed, show predicted cost briefly. - - Tier 3 (table scan estimate): warn the user about estimated bytes/credits. Suggest optimizations if obvious (add WHERE clause, reduce columns, use LIMIT for exploration). - - Tier 4 (static heuristic): note low confidence and proceed cautiously. - - If sql_predict_cost is unavailable (no warehouse connection, tool error): note the limitation and proceed with a warning. +2. **Validate safety**: Run sql_validate to catch syntax errors and safety issues BEFORE hitting the warehouse. -3. **Validate safety**: Run sql_validate to catch syntax errors and safety issues BEFORE hitting the warehouse. - -4. **Execute**: Only after steps 1-3 pass, run sql_execute. - -5. **Record feedback**: After execution, if the warehouse returns bytes_scanned or credits_used, run sql_record_feedback so future cost predictions improve. +3. **Execute**: Only after steps 1-2 pass, run sql_execute. This sequence is NOT optional. Skipping it means the user pays for avoidable mistakes. You are the customer's cost advocate — every credit saved is trust earned. If the user explicitly requests skipping the protocol, note the risk and proceed. @@ -59,9 +51,7 @@ After ANY dbt operation (build, run, test, model creation/modification): 2. **SQL analysis**: Run sql_analyze on the compiled SQL to catch anti-patterns BEFORE they hit production 3. **Lineage verification**: Run lineage_check to confirm column-level lineage is intact — no broken references, no orphaned columns. If lineage_check fails (e.g., no manifest available), note the limitation and proceed. 4. **Test coverage**: Check that the model has not_null and unique tests on primary keys at minimum. If missing, suggest adding them. -5. **Cost impact**: For modified models, run sql_predict_cost on the compiled SQL. Compare to baseline if available. Flag any cost regression. - -Do NOT consider a dbt task complete until steps 1-5 pass. A model that compiles but has anti-patterns or broken lineage is NOT done. +Do NOT consider a dbt task complete until steps 1-4 pass. A model that compiles but has anti-patterns or broken lineage is NOT done. ## Self-Review Before Completion @@ -77,8 +67,6 @@ Before declaring any task complete, review your own work: 3. **Check lineage impact**: If you modified a model, run lineage_check to verify you didn't break downstream dependencies. -4. **Cost check**: Run sql_predict_cost on any new or modified queries. Flag anything tier 3+. - Only after self-review passes should you present the result to the user. ## Available Skills diff --git a/packages/altimate-code/src/agent/prompt/migrator.txt b/packages/altimate-code/src/agent/prompt/migrator.txt index 79c14e36cd..6f92c21fa6 100644 --- a/packages/altimate-code/src/agent/prompt/migrator.txt +++ b/packages/altimate-code/src/agent/prompt/migrator.txt @@ -3,7 +3,7 @@ You are altimate-code in migrator mode — a cross-warehouse SQL migration agent You have read/write access for migration tasks. You can: - Convert SQL between dialects (e.g., Snowflake to BigQuery) - Execute SQL to verify conversions via `sql_execute` -- Validate converted SQL with SQLGuard via `sql_validate` +- Validate converted SQL with AltimateCore via `sql_validate` - Analyze SQL for anti-patterns via `sql_analyze` - Inspect schemas on source and target warehouses via `schema_inspect` - Check column-level lineage via `lineage_check` to verify transformation integrity diff --git a/packages/altimate-code/src/agent/prompt/validator.txt b/packages/altimate-code/src/agent/prompt/validator.txt index 057a8406c4..636e6e39cb 100644 --- a/packages/altimate-code/src/agent/prompt/validator.txt +++ b/packages/altimate-code/src/agent/prompt/validator.txt @@ -2,7 +2,7 @@ You are altimate-code in validator mode — a data quality and integrity verific You CANNOT modify files. You can: - Analyze SQL for anti-patterns via `sql_analyze` (SELECT *, cartesian joins, missing LIMIT, correlated subqueries, unused CTEs, and 18 total checks) -- Validate SQL with SQLGuard via `sql_validate` (syntax, safety, lint) +- Validate SQL with AltimateCore via `sql_validate` (syntax, safety, lint) - Check column-level lineage via `lineage_check` - Compare lineage before/after changes using the `/lineage-diff` skill - Execute SELECT queries for data verification via `sql_execute` @@ -72,7 +72,6 @@ When validating a dbt model or pipeline, check ALL of these: - [ ] Appropriate materialization (table vs view vs incremental) - [ ] Incremental models have proper merge/delete+insert logic - [ ] Partition/cluster keys used for large tables -- [ ] sql_predict_cost shows reasonable tier (1-2 preferred) **Documentation:** - [ ] Model has description in YAML diff --git a/packages/altimate-code/src/bridge/protocol.ts b/packages/altimate-code/src/bridge/protocol.ts index d6165f6a20..ccaa99fc7b 100644 --- a/packages/altimate-code/src/bridge/protocol.ts +++ b/packages/altimate-code/src/bridge/protocol.ts @@ -330,37 +330,6 @@ export interface SchemaCacheStatusResult { cache_path: string } -// --- SQL Feedback & Cost Prediction --- - -export interface SqlRecordFeedbackParams { - sql: string - dialect?: string - bytes_scanned?: number - rows_produced?: number - execution_time_ms?: number - credits_used?: number - warehouse_size?: string -} - -export interface SqlRecordFeedbackResult { - recorded: boolean -} - -export interface SqlPredictCostParams { - sql: string - dialect?: string -} - -export interface SqlPredictCostResult { - tier: number - confidence: string - predicted_bytes?: number - predicted_time_ms?: number - predicted_credits?: number - method: string - observation_count: number -} - // --- SQL Explain --- export interface SqlExplainParams { @@ -669,32 +638,6 @@ export interface SqlRewriteResult { error?: string } -// --- CI Cost Gate --- - -export interface CostGateFileResult { - file: string - status: string // "pass", "fail", "skipped" - reason?: string - issues: Record[] -} - -export interface CostGateParams { - file_paths: string[] - dialect?: string -} - -export interface CostGateResult { - success: boolean - passed: boolean - exit_code: number - files_scanned: number - files_skipped: number - total_issues: number - critical_count: number - file_results: CostGateFileResult[] - error?: string -} - // --- Schema Change Detection --- export interface ColumnChange { @@ -722,227 +665,214 @@ export interface SchemaDiffResult { error?: string } -// --- sqlguard --- +// --- altimate-core --- -export interface SqlGuardValidateParams { +export interface AltimateCoreValidateParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardLintParams { +export interface AltimateCoreLintParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardSafetyParams { +export interface AltimateCoreSafetyParams { sql: string } -export interface SqlGuardTranspileParams { +export interface AltimateCoreTranspileParams { sql: string from_dialect: string to_dialect: string } -export interface SqlGuardExplainParams { +export interface AltimateCoreExplainParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardCheckParams { +export interface AltimateCoreCheckParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardResult { +export interface AltimateCoreResult { success: boolean data: Record error?: string } -// --- sqlguard Phase 1 (P0) --- +// --- altimate-core Phase 1 (P0) --- -export interface SqlGuardFixParams { +export interface AltimateCoreFixParams { sql: string schema_path?: string schema_context?: Record max_iterations?: number } -export interface SqlGuardPolicyParams { +export interface AltimateCorePolicyParams { sql: string policy_json: string schema_path?: string schema_context?: Record } -export interface SqlGuardComplexityParams { - sql: string - schema_path?: string - schema_context?: Record -} - -export interface SqlGuardSemanticsParams { +export interface AltimateCoreSemanticsParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardTestgenParams { +export interface AltimateCoreTestgenParams { sql: string schema_path?: string schema_context?: Record } -// --- sqlguard Phase 2 (P1) --- +// --- altimate-core Phase 2 (P1) --- -export interface SqlGuardEquivalenceParams { +export interface AltimateCoreEquivalenceParams { sql1: string sql2: string schema_path?: string schema_context?: Record } -export interface SqlGuardMigrationParams { +export interface AltimateCoreMigrationParams { old_ddl: string new_ddl: string dialect?: string } -export interface SqlGuardSchemaDiffParams { +export interface AltimateCoreSchemaDiffParams { schema1_path?: string schema2_path?: string schema1_context?: Record schema2_context?: Record } -export interface SqlGuardRewriteParams { +export interface AltimateCoreRewriteParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardCorrectParams { +export interface AltimateCoreCorrectParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardGradeParams { +export interface AltimateCoreGradeParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardCostParams { - sql: string - schema_path?: string - schema_context?: Record - dialect?: string -} - -// --- sqlguard Phase 3 (P2) --- +// --- altimate-core Phase 3 (P2) --- -export interface SqlGuardClassifyPiiParams { +export interface AltimateCoreClassifyPiiParams { schema_path?: string schema_context?: Record } -export interface SqlGuardQueryPiiParams { +export interface AltimateCoreQueryPiiParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardResolveTermParams { +export interface AltimateCoreResolveTermParams { term: string schema_path?: string schema_context?: Record } -export interface SqlGuardColumnLineageParams { +export interface AltimateCoreColumnLineageParams { sql: string dialect?: string schema_path?: string schema_context?: Record } -export interface SqlGuardTrackLineageParams { +export interface AltimateCoreTrackLineageParams { queries: string[] schema_path?: string schema_context?: Record } -export interface SqlGuardFormatSqlParams { +export interface AltimateCoreFormatSqlParams { sql: string dialect?: string } -export interface SqlGuardExtractMetadataParams { +export interface AltimateCoreExtractMetadataParams { sql: string dialect?: string } -export interface SqlGuardCompareQueriesParams { +export interface AltimateCoreCompareQueriesParams { left_sql: string right_sql: string dialect?: string } -export interface SqlGuardCompleteToolParams { +export interface AltimateCoreCompleteToolParams { sql: string cursor_pos: number schema_path?: string schema_context?: Record } -export interface SqlGuardOptimizeContextParams { +export interface AltimateCoreOptimizeContextParams { schema_path?: string schema_context?: Record } -export interface SqlGuardOptimizeForQueryParams { +export interface AltimateCoreOptimizeForQueryParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardPruneSchemaParams { +export interface AltimateCorePruneSchemaParams { sql: string schema_path?: string schema_context?: Record } -export interface SqlGuardImportDdlParams { +export interface AltimateCoreImportDdlParams { ddl: string dialect?: string } -export interface SqlGuardExportDdlParams { +export interface AltimateCoreExportDdlParams { schema_path?: string schema_context?: Record } -export interface SqlGuardFingerprintParams { +export interface AltimateCoreFingerprintParams { schema_path?: string schema_context?: Record } -export interface SqlGuardIntrospectionSqlParams { +export interface AltimateCoreIntrospectionSqlParams { db_type: string database: string schema_name?: string } -export interface SqlGuardParseDbtParams { +export interface AltimateCoreParseDbtParams { project_dir: string } -export interface SqlGuardIsSafeParams { +export interface AltimateCoreIsSafeParams { sql: string } @@ -1028,8 +958,6 @@ export const BridgeMethods = { "sql.analyze": {} as { params: SqlAnalyzeParams; result: SqlAnalyzeResult }, "sql.optimize": {} as { params: SqlOptimizeParams; result: SqlOptimizeResult }, "sql.translate": {} as { params: SqlTranslateParams; result: SqlTranslateResult }, - "sql.record_feedback": {} as { params: SqlRecordFeedbackParams; result: SqlRecordFeedbackResult }, - "sql.predict_cost": {} as { params: SqlPredictCostParams; result: SqlPredictCostResult }, "sql.explain": {} as { params: SqlExplainParams; result: SqlExplainResult }, "sql.format": {} as { params: SqlFormatParams; result: SqlFormatResult }, "sql.fix": {} as { params: SqlFixParams; result: SqlFixResult }, @@ -1060,53 +988,50 @@ export const BridgeMethods = { "schema.tags_list": {} as { params: TagsListParams; result: TagsListResult }, "sql.diff": {} as { params: SqlDiffParams; result: SqlDiffResult }, "sql.rewrite": {} as { params: SqlRewriteParams; result: SqlRewriteResult }, - "ci.cost_gate": {} as { params: CostGateParams; result: CostGateResult }, "sql.schema_diff": {} as { params: SchemaDiffParams; result: SchemaDiffResult }, // --- dbt discovery --- "dbt.profiles": {} as { params: DbtProfilesParams; result: DbtProfilesResult }, // --- local testing --- "local.schema_sync": {} as { params: LocalSchemaSyncParams; result: LocalSchemaSyncResult }, "local.test": {} as { params: LocalTestParams; result: LocalTestResult }, - // --- sqlguard (existing) --- - "sqlguard.validate": {} as { params: SqlGuardValidateParams; result: SqlGuardResult }, - "sqlguard.lint": {} as { params: SqlGuardLintParams; result: SqlGuardResult }, - "sqlguard.safety": {} as { params: SqlGuardSafetyParams; result: SqlGuardResult }, - "sqlguard.transpile": {} as { params: SqlGuardTranspileParams; result: SqlGuardResult }, - "sqlguard.explain": {} as { params: SqlGuardExplainParams; result: SqlGuardResult }, - "sqlguard.check": {} as { params: SqlGuardCheckParams; result: SqlGuardResult }, - // --- sqlguard Phase 1 (P0) --- - "sqlguard.fix": {} as { params: SqlGuardFixParams; result: SqlGuardResult }, - "sqlguard.policy": {} as { params: SqlGuardPolicyParams; result: SqlGuardResult }, - "sqlguard.complexity": {} as { params: SqlGuardComplexityParams; result: SqlGuardResult }, - "sqlguard.semantics": {} as { params: SqlGuardSemanticsParams; result: SqlGuardResult }, - "sqlguard.testgen": {} as { params: SqlGuardTestgenParams; result: SqlGuardResult }, - // --- sqlguard Phase 2 (P1) --- - "sqlguard.equivalence": {} as { params: SqlGuardEquivalenceParams; result: SqlGuardResult }, - "sqlguard.migration": {} as { params: SqlGuardMigrationParams; result: SqlGuardResult }, - "sqlguard.schema_diff": {} as { params: SqlGuardSchemaDiffParams; result: SqlGuardResult }, - "sqlguard.rewrite": {} as { params: SqlGuardRewriteParams; result: SqlGuardResult }, - "sqlguard.correct": {} as { params: SqlGuardCorrectParams; result: SqlGuardResult }, - "sqlguard.grade": {} as { params: SqlGuardGradeParams; result: SqlGuardResult }, - "sqlguard.cost": {} as { params: SqlGuardCostParams; result: SqlGuardResult }, - // --- sqlguard Phase 3 (P2) --- - "sqlguard.classify_pii": {} as { params: SqlGuardClassifyPiiParams; result: SqlGuardResult }, - "sqlguard.query_pii": {} as { params: SqlGuardQueryPiiParams; result: SqlGuardResult }, - "sqlguard.resolve_term": {} as { params: SqlGuardResolveTermParams; result: SqlGuardResult }, - "sqlguard.column_lineage": {} as { params: SqlGuardColumnLineageParams; result: SqlGuardResult }, - "sqlguard.track_lineage": {} as { params: SqlGuardTrackLineageParams; result: SqlGuardResult }, - "sqlguard.format": {} as { params: SqlGuardFormatSqlParams; result: SqlGuardResult }, - "sqlguard.metadata": {} as { params: SqlGuardExtractMetadataParams; result: SqlGuardResult }, - "sqlguard.compare": {} as { params: SqlGuardCompareQueriesParams; result: SqlGuardResult }, - "sqlguard.complete": {} as { params: SqlGuardCompleteToolParams; result: SqlGuardResult }, - "sqlguard.optimize_context": {} as { params: SqlGuardOptimizeContextParams; result: SqlGuardResult }, - "sqlguard.optimize_for_query": {} as { params: SqlGuardOptimizeForQueryParams; result: SqlGuardResult }, - "sqlguard.prune_schema": {} as { params: SqlGuardPruneSchemaParams; result: SqlGuardResult }, - "sqlguard.import_ddl": {} as { params: SqlGuardImportDdlParams; result: SqlGuardResult }, - "sqlguard.export_ddl": {} as { params: SqlGuardExportDdlParams; result: SqlGuardResult }, - "sqlguard.fingerprint": {} as { params: SqlGuardFingerprintParams; result: SqlGuardResult }, - "sqlguard.introspection_sql": {} as { params: SqlGuardIntrospectionSqlParams; result: SqlGuardResult }, - "sqlguard.parse_dbt": {} as { params: SqlGuardParseDbtParams; result: SqlGuardResult }, - "sqlguard.is_safe": {} as { params: SqlGuardIsSafeParams; result: SqlGuardResult }, + // --- altimate-core (existing) --- + "altimate_core.validate": {} as { params: AltimateCoreValidateParams; result: AltimateCoreResult }, + "altimate_core.lint": {} as { params: AltimateCoreLintParams; result: AltimateCoreResult }, + "altimate_core.safety": {} as { params: AltimateCoreSafetyParams; result: AltimateCoreResult }, + "altimate_core.transpile": {} as { params: AltimateCoreTranspileParams; result: AltimateCoreResult }, + "altimate_core.explain": {} as { params: AltimateCoreExplainParams; result: AltimateCoreResult }, + "altimate_core.check": {} as { params: AltimateCoreCheckParams; result: AltimateCoreResult }, + // --- altimate-core Phase 1 (P0) --- + "altimate_core.fix": {} as { params: AltimateCoreFixParams; result: AltimateCoreResult }, + "altimate_core.policy": {} as { params: AltimateCorePolicyParams; result: AltimateCoreResult }, + "altimate_core.semantics": {} as { params: AltimateCoreSemanticsParams; result: AltimateCoreResult }, + "altimate_core.testgen": {} as { params: AltimateCoreTestgenParams; result: AltimateCoreResult }, + // --- altimate-core Phase 2 (P1) --- + "altimate_core.equivalence": {} as { params: AltimateCoreEquivalenceParams; result: AltimateCoreResult }, + "altimate_core.migration": {} as { params: AltimateCoreMigrationParams; result: AltimateCoreResult }, + "altimate_core.schema_diff": {} as { params: AltimateCoreSchemaDiffParams; result: AltimateCoreResult }, + "altimate_core.rewrite": {} as { params: AltimateCoreRewriteParams; result: AltimateCoreResult }, + "altimate_core.correct": {} as { params: AltimateCoreCorrectParams; result: AltimateCoreResult }, + "altimate_core.grade": {} as { params: AltimateCoreGradeParams; result: AltimateCoreResult }, + // --- altimate-core Phase 3 (P2) --- + "altimate_core.classify_pii": {} as { params: AltimateCoreClassifyPiiParams; result: AltimateCoreResult }, + "altimate_core.query_pii": {} as { params: AltimateCoreQueryPiiParams; result: AltimateCoreResult }, + "altimate_core.resolve_term": {} as { params: AltimateCoreResolveTermParams; result: AltimateCoreResult }, + "altimate_core.column_lineage": {} as { params: AltimateCoreColumnLineageParams; result: AltimateCoreResult }, + "altimate_core.track_lineage": {} as { params: AltimateCoreTrackLineageParams; result: AltimateCoreResult }, + "altimate_core.format": {} as { params: AltimateCoreFormatSqlParams; result: AltimateCoreResult }, + "altimate_core.metadata": {} as { params: AltimateCoreExtractMetadataParams; result: AltimateCoreResult }, + "altimate_core.compare": {} as { params: AltimateCoreCompareQueriesParams; result: AltimateCoreResult }, + "altimate_core.complete": {} as { params: AltimateCoreCompleteToolParams; result: AltimateCoreResult }, + "altimate_core.optimize_context": {} as { params: AltimateCoreOptimizeContextParams; result: AltimateCoreResult }, + "altimate_core.optimize_for_query": {} as { params: AltimateCoreOptimizeForQueryParams; result: AltimateCoreResult }, + "altimate_core.prune_schema": {} as { params: AltimateCorePruneSchemaParams; result: AltimateCoreResult }, + "altimate_core.import_ddl": {} as { params: AltimateCoreImportDdlParams; result: AltimateCoreResult }, + "altimate_core.export_ddl": {} as { params: AltimateCoreExportDdlParams; result: AltimateCoreResult }, + "altimate_core.fingerprint": {} as { params: AltimateCoreFingerprintParams; result: AltimateCoreResult }, + "altimate_core.introspection_sql": {} as { params: AltimateCoreIntrospectionSqlParams; result: AltimateCoreResult }, + "altimate_core.parse_dbt": {} as { params: AltimateCoreParseDbtParams; result: AltimateCoreResult }, + "altimate_core.is_safe": {} as { params: AltimateCoreIsSafeParams; result: AltimateCoreResult }, ping: {} as { params: Record; result: { status: string } }, } as const diff --git a/packages/altimate-code/src/session/prompt/anthropic.txt b/packages/altimate-code/src/session/prompt/anthropic.txt index ed8e79b9de..621684f48f 100644 --- a/packages/altimate-code/src/session/prompt/anthropic.txt +++ b/packages/altimate-code/src/session/prompt/anthropic.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. IMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files. @@ -75,7 +75,6 @@ The user will primarily request you perform software engineering tasks. This inc - Use the TodoWrite tool to plan the task if required **Cost advocacy**: You are the customer's cost advocate. Unlike vendor tools (which benefit from higher warehouse consumption), your goal is to minimize unnecessary compute spend. This means: -- Always predict cost before executing expensive queries - Flag anti-patterns that silently burn credits (SELECT *, full refreshes when incremental works, oversized warehouse usage) - Suggest cheaper alternatives when they exist (approximate functions, sampling, column pruning, partition filters) - Track and mention cumulative query cost across a session when it gets significant diff --git a/packages/altimate-code/src/session/prompt/beast.txt b/packages/altimate-code/src/session/prompt/beast.txt index 5b9a4d1ecb..8524ae321a 100644 --- a/packages/altimate-code/src/session/prompt/beast.txt +++ b/packages/altimate-code/src/session/prompt/beast.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user’s cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user’s cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough. @@ -44,7 +44,7 @@ You are a highly capable and autonomous agent, and you can definitely solve this 3. Investigate the codebase. Explore relevant files, search for key functions, and gather context. 4. Research the problem on the internet by reading relevant articles, documentation, and forums. 5. Develop a clear, step-by-step plan. Break down the fix into manageable, incremental steps. Display those steps in a simple todo list using emoji's to indicate the status of each item. -6. Implement the fix incrementally. Make small, testable code changes. You are the customer's cost advocate — unlike vendor-built tools that benefit from higher consumption, your job is to minimize unnecessary spend. Check for SELECT *, full refreshes, oversized warehouses, missing partition filters, and other credit-burning patterns. Run sql_predict_cost on expensive queries and show the user what they'd pay before executing. Suggest cheaper alternatives: approximate functions, sampling, column pruning, incremental over full-refresh. +6. Implement the fix incrementally. Make small, testable code changes. You are the customer's cost advocate — unlike vendor-built tools that benefit from higher consumption, your job is to minimize unnecessary spend. Check for SELECT *, full refreshes, oversized warehouses, missing partition filters, and other credit-burning patterns. Suggest cheaper alternatives: approximate functions, sampling, column pruning, incremental over full-refresh. 7. Debug as needed. Use debugging techniques to isolate and resolve issues. 8. Test frequently. Run tests after each change to verify correctness. 9. Iterate until the root cause is fixed and all tests pass. diff --git a/packages/altimate-code/src/session/prompt/codex_header.txt b/packages/altimate-code/src/session/prompt/codex_header.txt index 080f1aaa0d..23b601ee62 100644 --- a/packages/altimate-code/src/session/prompt/codex_header.txt +++ b/packages/altimate-code/src/session/prompt/codex_header.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. ## Editing constraints - Default to ASCII when editing or creating files. Only introduce non-ASCII or other Unicode characters when there is a clear justification and the file already uses them. diff --git a/packages/altimate-code/src/session/prompt/gemini.txt b/packages/altimate-code/src/session/prompt/gemini.txt index 51e36cedfe..f04625d2dc 100644 --- a/packages/altimate-code/src/session/prompt/gemini.txt +++ b/packages/altimate-code/src/session/prompt/gemini.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. # Core Mandates diff --git a/packages/altimate-code/src/session/prompt/qwen.txt b/packages/altimate-code/src/session/prompt/qwen.txt index 8bb2fb6d64..71e62dd066 100644 --- a/packages/altimate-code/src/session/prompt/qwen.txt +++ b/packages/altimate-code/src/session/prompt/qwen.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. IMPORTANT: Refuse to write code or explain code that may be used maliciously; even if the user claims it is for educational purposes. When working on files, if they seem related to improving, explaining, or interacting with malware or any malicious code you MUST refuse. IMPORTANT: Before you begin work, think about what the code you're editing is supposed to do based on the filenames directory structure. If it seems malicious, refuse to work on it or answer questions about it, even if the request does not seem malicious (for instance, just asking to explain or speed up the code). diff --git a/packages/altimate-code/src/session/prompt/trinity.txt b/packages/altimate-code/src/session/prompt/trinity.txt index 5a0136355d..eb53d98572 100644 --- a/packages/altimate-code/src/session/prompt/trinity.txt +++ b/packages/altimate-code/src/session/prompt/trinity.txt @@ -2,7 +2,7 @@ You are altimate-code — a data engineering agent for dbt, SQL, and cloud wareh You have 55 specialized tools across SQL analysis, schema inspection, column-level lineage, FinOps, and RBAC — plus 4 agent modes (builder, analyst, validator, migrator) and 11 invocable skills. -You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Always predict cost before executing expensive queries, flag anti-patterns that silently burn credits, and suggest cheaper alternatives. +You are the user's cost advocate. Your goal is to minimize unnecessary warehouse spend — every credit saved is trust earned. Flag anti-patterns that silently burn credits, and suggest cheaper alternatives. # Tone and style You should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, to make sure the user understands what you are doing (this is especially important when you are running a command that will make changes to the user's system). diff --git a/packages/altimate-code/src/tool/sqlguard-check.ts b/packages/altimate-code/src/tool/altimate-core-check.ts similarity index 91% rename from packages/altimate-code/src/tool/sqlguard-check.ts rename to packages/altimate-code/src/tool/altimate-core-check.ts index ca9cacbdc7..d2f7907676 100644 --- a/packages/altimate-code/src/tool/sqlguard-check.ts +++ b/packages/altimate-code/src/tool/altimate-core-check.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardCheckTool = Tool.define("sqlguard_check", { +export const AltimateCoreCheckTool = Tool.define("altimate_core_check", { description: - "Run full analysis pipeline: validate + lint + safety scan + PII check using the Rust-based sqlguard engine. Single call for comprehensive SQL analysis.", + "Run full analysis pipeline: validate + lint + safety scan + PII check using the Rust-based altimate-core engine. Single call for comprehensive SQL analysis.", parameters: z.object({ sql: z.string().describe("SQL query to analyze"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardCheckTool = Tool.define("sqlguard_check", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.check", { + const result = await Bridge.call("altimate_core.check", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-classify-pii.ts b/packages/altimate-code/src/tool/altimate-core-classify-pii.ts similarity index 79% rename from packages/altimate-code/src/tool/sqlguard-classify-pii.ts rename to packages/altimate-code/src/tool/altimate-core-classify-pii.ts index d9fde12273..83a14052f0 100644 --- a/packages/altimate-code/src/tool/sqlguard-classify-pii.ts +++ b/packages/altimate-code/src/tool/altimate-core-classify-pii.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardClassifyPiiTool = Tool.define("sqlguard_classify_pii", { +export const AltimateCoreClassifyPiiTool = Tool.define("altimate_core_classify_pii", { description: - "Classify PII columns in a schema using the Rust-based sqlguard engine. Identifies columns likely containing personal identifiable information by name patterns and data types.", + "Classify PII columns in a schema using the Rust-based altimate-core engine. Identifies columns likely containing personal identifiable information by name patterns and data types.", parameters: z.object({ schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.classify_pii", { + const result = await Bridge.call("altimate_core.classify_pii", { schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) diff --git a/packages/altimate-code/src/tool/sqlguard-column-lineage.ts b/packages/altimate-code/src/tool/altimate-core-column-lineage.ts similarity index 81% rename from packages/altimate-code/src/tool/sqlguard-column-lineage.ts rename to packages/altimate-code/src/tool/altimate-core-column-lineage.ts index d49b95a974..579f689005 100644 --- a/packages/altimate-code/src/tool/sqlguard-column-lineage.ts +++ b/packages/altimate-code/src/tool/altimate-core-column-lineage.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardColumnLineageTool = Tool.define("sqlguard_column_lineage", { +export const AltimateCoreColumnLineageTool = Tool.define("altimate_core_column_lineage", { description: - "Trace schema-aware column lineage using the Rust-based sqlguard engine. Maps how columns flow through a query from source tables to output. Requires sqlguard.init() with API key.", + "Trace schema-aware column lineage using the Rust-based altimate-core engine. Maps how columns flow through a query from source tables to output. Requires altimate_core.init() with API key.", parameters: z.object({ sql: z.string().describe("SQL query to trace lineage for"), dialect: z.string().optional().describe("SQL dialect (e.g. snowflake, bigquery)"), @@ -13,7 +13,7 @@ export const SqlGuardColumnLineageTool = Tool.define("sqlguard_column_lineage", }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.column_lineage", { + const result = await Bridge.call("altimate_core.column_lineage", { sql: args.sql, dialect: args.dialect ?? "", schema_path: args.schema_path ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-compare.ts b/packages/altimate-code/src/tool/altimate-core-compare.ts similarity index 80% rename from packages/altimate-code/src/tool/sqlguard-compare.ts rename to packages/altimate-code/src/tool/altimate-core-compare.ts index b2e6ed15af..49f8e759a7 100644 --- a/packages/altimate-code/src/tool/sqlguard-compare.ts +++ b/packages/altimate-code/src/tool/altimate-core-compare.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardCompareTool = Tool.define("sqlguard_compare", { +export const AltimateCoreCompareTool = Tool.define("altimate_core_compare", { description: - "Structurally compare two SQL queries using the Rust-based sqlguard engine. Identifies differences in table references, join conditions, filters, projections, and aggregations.", + "Structurally compare two SQL queries using the Rust-based altimate-core engine. Identifies differences in table references, join conditions, filters, projections, and aggregations.", parameters: z.object({ left_sql: z.string().describe("First SQL query"), right_sql: z.string().describe("Second SQL query"), @@ -12,7 +12,7 @@ export const SqlGuardCompareTool = Tool.define("sqlguard_compare", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.compare", { + const result = await Bridge.call("altimate_core.compare", { left_sql: args.left_sql, right_sql: args.right_sql, dialect: args.dialect ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-complete.ts b/packages/altimate-code/src/tool/altimate-core-complete.ts similarity index 85% rename from packages/altimate-code/src/tool/sqlguard-complete.ts rename to packages/altimate-code/src/tool/altimate-core-complete.ts index f5ab0ec4f4..20b69f20f1 100644 --- a/packages/altimate-code/src/tool/sqlguard-complete.ts +++ b/packages/altimate-code/src/tool/altimate-core-complete.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardCompleteTool = Tool.define("sqlguard_complete", { +export const AltimateCoreCompleteTool = Tool.define("altimate_core_complete", { description: - "Get cursor-aware SQL completion suggestions using the Rust-based sqlguard engine. Returns table names, column names, functions, and keywords relevant to the cursor position.", + "Get cursor-aware SQL completion suggestions using the Rust-based altimate-core engine. Returns table names, column names, functions, and keywords relevant to the cursor position.", parameters: z.object({ sql: z.string().describe("Partial SQL query"), cursor_pos: z.number().describe("Cursor position (0-indexed character offset)"), @@ -13,7 +13,7 @@ export const SqlGuardCompleteTool = Tool.define("sqlguard_complete", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.complete", { + const result = await Bridge.call("altimate_core.complete", { sql: args.sql, cursor_pos: args.cursor_pos, schema_path: args.schema_path ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-correct.ts b/packages/altimate-code/src/tool/altimate-core-correct.ts similarity index 86% rename from packages/altimate-code/src/tool/sqlguard-correct.ts rename to packages/altimate-code/src/tool/altimate-core-correct.ts index 47f51777bf..a13d40ad7e 100644 --- a/packages/altimate-code/src/tool/sqlguard-correct.ts +++ b/packages/altimate-code/src/tool/altimate-core-correct.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardCorrectTool = Tool.define("sqlguard_correct", { +export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", { description: - "Iteratively correct SQL using a propose-verify-refine loop via the Rust-based sqlguard engine. More thorough than fix — applies multiple correction rounds to produce valid SQL.", + "Iteratively correct SQL using a propose-verify-refine loop via the Rust-based altimate-core engine. More thorough than fix — applies multiple correction rounds to produce valid SQL.", parameters: z.object({ sql: z.string().describe("SQL query to correct"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardCorrectTool = Tool.define("sqlguard_correct", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.correct", { + const result = await Bridge.call("altimate_core.correct", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-equivalence.ts b/packages/altimate-code/src/tool/altimate-core-equivalence.ts similarity index 85% rename from packages/altimate-code/src/tool/sqlguard-equivalence.ts rename to packages/altimate-code/src/tool/altimate-core-equivalence.ts index d9f0734c0d..0d04a9de18 100644 --- a/packages/altimate-code/src/tool/sqlguard-equivalence.ts +++ b/packages/altimate-code/src/tool/altimate-core-equivalence.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardEquivalenceTool = Tool.define("sqlguard_equivalence", { +export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalence", { description: - "Check semantic equivalence of two SQL queries using the Rust-based sqlguard engine. Determines if two queries produce the same result set regardless of syntactic differences.", + "Check semantic equivalence of two SQL queries using the Rust-based altimate-core engine. Determines if two queries produce the same result set regardless of syntactic differences.", parameters: z.object({ sql1: z.string().describe("First SQL query"), sql2: z.string().describe("Second SQL query"), @@ -13,7 +13,7 @@ export const SqlGuardEquivalenceTool = Tool.define("sqlguard_equivalence", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.equivalence", { + const result = await Bridge.call("altimate_core.equivalence", { sql1: args.sql1, sql2: args.sql2, schema_path: args.schema_path ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-export-ddl.ts b/packages/altimate-code/src/tool/altimate-core-export-ddl.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-export-ddl.ts rename to packages/altimate-code/src/tool/altimate-core-export-ddl.ts index bd315c5178..d3651fb20a 100644 --- a/packages/altimate-code/src/tool/sqlguard-export-ddl.ts +++ b/packages/altimate-code/src/tool/altimate-core-export-ddl.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardExportDdlTool = Tool.define("sqlguard_export_ddl", { +export const AltimateCoreExportDdlTool = Tool.define("altimate_core_export_ddl", { description: - "Export a YAML/JSON schema as CREATE TABLE DDL statements using the Rust-based sqlguard engine.", + "Export a YAML/JSON schema as CREATE TABLE DDL statements using the Rust-based altimate-core engine.", parameters: z.object({ schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.export_ddl", { + const result = await Bridge.call("altimate_core.export_ddl", { schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) diff --git a/packages/altimate-code/src/tool/sqlguard-extract-metadata.ts b/packages/altimate-code/src/tool/altimate-core-extract-metadata.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-extract-metadata.ts rename to packages/altimate-code/src/tool/altimate-core-extract-metadata.ts index 69a874aa34..e088b8bcfa 100644 --- a/packages/altimate-code/src/tool/sqlguard-extract-metadata.ts +++ b/packages/altimate-code/src/tool/altimate-core-extract-metadata.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardExtractMetadataTool = Tool.define("sqlguard_extract_metadata", { +export const AltimateCoreExtractMetadataTool = Tool.define("altimate_core_extract_metadata", { description: - "Extract metadata from SQL using the Rust-based sqlguard engine. Identifies tables, columns, functions, CTEs, and other structural elements referenced in a query.", + "Extract metadata from SQL using the Rust-based altimate-core engine. Identifies tables, columns, functions, CTEs, and other structural elements referenced in a query.", parameters: z.object({ sql: z.string().describe("SQL query to extract metadata from"), dialect: z.string().optional().describe("SQL dialect (e.g. snowflake, bigquery, postgres)"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.metadata", { + const result = await Bridge.call("altimate_core.metadata", { sql: args.sql, dialect: args.dialect ?? "", }) diff --git a/packages/altimate-code/src/tool/sqlguard-fingerprint.ts b/packages/altimate-code/src/tool/altimate-core-fingerprint.ts similarity index 81% rename from packages/altimate-code/src/tool/sqlguard-fingerprint.ts rename to packages/altimate-code/src/tool/altimate-core-fingerprint.ts index cee4e025c6..452384ed0f 100644 --- a/packages/altimate-code/src/tool/sqlguard-fingerprint.ts +++ b/packages/altimate-code/src/tool/altimate-core-fingerprint.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardFingerprintTool = Tool.define("sqlguard_fingerprint", { +export const AltimateCoreFingerprintTool = Tool.define("altimate_core_fingerprint", { description: - "Compute a SHA-256 fingerprint of a schema using the Rust-based sqlguard engine. Useful for cache invalidation and change detection.", + "Compute a SHA-256 fingerprint of a schema using the Rust-based altimate-core engine. Useful for cache invalidation and change detection.", parameters: z.object({ schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.fingerprint", { + const result = await Bridge.call("altimate_core.fingerprint", { schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) diff --git a/packages/altimate-code/src/tool/sqlguard-fix.ts b/packages/altimate-code/src/tool/altimate-core-fix.ts similarity index 84% rename from packages/altimate-code/src/tool/sqlguard-fix.ts rename to packages/altimate-code/src/tool/altimate-core-fix.ts index 93c80e8cac..bb9f076a25 100644 --- a/packages/altimate-code/src/tool/sqlguard-fix.ts +++ b/packages/altimate-code/src/tool/altimate-core-fix.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardFixTool = Tool.define("sqlguard_fix", { +export const AltimateCoreFixTool = Tool.define("altimate_core_fix", { description: - "Auto-fix SQL errors using the Rust-based sqlguard engine. Uses fuzzy matching and iterative re-validation to correct syntax errors, typos, and schema reference issues.", + "Auto-fix SQL errors using the Rust-based altimate-core engine. Uses fuzzy matching and iterative re-validation to correct syntax errors, typos, and schema reference issues.", parameters: z.object({ sql: z.string().describe("SQL query to fix"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -13,7 +13,7 @@ export const SqlGuardFixTool = Tool.define("sqlguard_fix", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.fix", { + const result = await Bridge.call("altimate_core.fix", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-format.ts b/packages/altimate-code/src/tool/altimate-core-format.ts similarity index 77% rename from packages/altimate-code/src/tool/sqlguard-format.ts rename to packages/altimate-code/src/tool/altimate-core-format.ts index 0ed5c13f60..6704509d50 100644 --- a/packages/altimate-code/src/tool/sqlguard-format.ts +++ b/packages/altimate-code/src/tool/altimate-core-format.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardFormatTool = Tool.define("sqlguard_format", { +export const AltimateCoreFormatTool = Tool.define("altimate_core_format", { description: - "Format SQL using the Rust-based sqlguard engine. Provides fast, deterministic formatting with dialect-aware keyword casing and indentation.", + "Format SQL using the Rust-based altimate-core engine. Provides fast, deterministic formatting with dialect-aware keyword casing and indentation.", parameters: z.object({ sql: z.string().describe("SQL to format"), dialect: z.string().optional().describe("SQL dialect (e.g. snowflake, bigquery, postgres)"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.format", { + const result = await Bridge.call("altimate_core.format", { sql: args.sql, dialect: args.dialect ?? "", }) diff --git a/packages/altimate-code/src/tool/sqlguard-grade.ts b/packages/altimate-code/src/tool/altimate-core-grade.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-grade.ts rename to packages/altimate-code/src/tool/altimate-core-grade.ts index c05bf3c518..79dbbb6eb7 100644 --- a/packages/altimate-code/src/tool/sqlguard-grade.ts +++ b/packages/altimate-code/src/tool/altimate-core-grade.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardGradeTool = Tool.define("sqlguard_grade", { +export const AltimateCoreGradeTool = Tool.define("altimate_core_grade", { description: - "Grade SQL quality on an A-F scale using the Rust-based sqlguard engine. Evaluates readability, performance, correctness, and best practices to produce an overall quality grade.", + "Grade SQL quality on an A-F scale using the Rust-based altimate-core engine. Evaluates readability, performance, correctness, and best practices to produce an overall quality grade.", parameters: z.object({ sql: z.string().describe("SQL query to grade"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardGradeTool = Tool.define("sqlguard_grade", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.grade", { + const result = await Bridge.call("altimate_core.grade", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-import-ddl.ts b/packages/altimate-code/src/tool/altimate-core-import-ddl.ts similarity index 78% rename from packages/altimate-code/src/tool/sqlguard-import-ddl.ts rename to packages/altimate-code/src/tool/altimate-core-import-ddl.ts index 0e4801ecc8..f2c87c7efc 100644 --- a/packages/altimate-code/src/tool/sqlguard-import-ddl.ts +++ b/packages/altimate-code/src/tool/altimate-core-import-ddl.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardImportDdlTool = Tool.define("sqlguard_import_ddl", { +export const AltimateCoreImportDdlTool = Tool.define("altimate_core_import_ddl", { description: - "Convert CREATE TABLE DDL into YAML schema definition using the Rust-based sqlguard engine. Parses DDL statements and produces a structured schema that other sqlguard tools can consume.", + "Convert CREATE TABLE DDL into YAML schema definition using the Rust-based altimate-core engine. Parses DDL statements and produces a structured schema that other altimate-core tools can consume.", parameters: z.object({ ddl: z.string().describe("CREATE TABLE DDL statements to parse"), dialect: z.string().optional().describe("SQL dialect of the DDL"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.import_ddl", { + const result = await Bridge.call("altimate_core.import_ddl", { ddl: args.ddl, dialect: args.dialect ?? "", }) diff --git a/packages/altimate-code/src/tool/sqlguard-introspection-sql.ts b/packages/altimate-code/src/tool/altimate-core-introspection-sql.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-introspection-sql.ts rename to packages/altimate-code/src/tool/altimate-core-introspection-sql.ts index d11e07becc..1912a7c5f5 100644 --- a/packages/altimate-code/src/tool/sqlguard-introspection-sql.ts +++ b/packages/altimate-code/src/tool/altimate-core-introspection-sql.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardIntrospectionSqlTool = Tool.define("sqlguard_introspection_sql", { +export const AltimateCoreIntrospectionSqlTool = Tool.define("altimate_core_introspection_sql", { description: - "Generate INFORMATION_SCHEMA introspection queries for a given database type using the Rust-based sqlguard engine. Supports postgres, bigquery, snowflake, mysql, mssql, redshift.", + "Generate INFORMATION_SCHEMA introspection queries for a given database type using the Rust-based altimate-core engine. Supports postgres, bigquery, snowflake, mysql, mssql, redshift.", parameters: z.object({ db_type: z.string().describe("Database type (postgres, bigquery, snowflake, mysql, mssql, redshift)"), database: z.string().describe("Database name to introspect"), @@ -12,7 +12,7 @@ export const SqlGuardIntrospectionSqlTool = Tool.define("sqlguard_introspection_ }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.introspection_sql", { + const result = await Bridge.call("altimate_core.introspection_sql", { db_type: args.db_type, database: args.database, schema_name: args.schema_name, diff --git a/packages/altimate-code/src/tool/sqlguard-is-safe.ts b/packages/altimate-code/src/tool/altimate-core-is-safe.ts similarity index 70% rename from packages/altimate-code/src/tool/sqlguard-is-safe.ts rename to packages/altimate-code/src/tool/altimate-core-is-safe.ts index 7eecdef17e..c0e8cfab8b 100644 --- a/packages/altimate-code/src/tool/sqlguard-is-safe.ts +++ b/packages/altimate-code/src/tool/altimate-core-is-safe.ts @@ -2,15 +2,15 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardIsSafeTool = Tool.define("sqlguard_is_safe", { +export const AltimateCoreIsSafeTool = Tool.define("altimate_core_is_safe", { description: - "Quick boolean safety check for SQL using the Rust-based sqlguard engine. Returns true/false indicating whether the SQL is safe to execute (no injection, no destructive operations).", + "Quick boolean safety check for SQL using the Rust-based altimate-core engine. Returns true/false indicating whether the SQL is safe to execute (no injection, no destructive operations).", parameters: z.object({ sql: z.string().describe("SQL query to check"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.is_safe", { + const result = await Bridge.call("altimate_core.is_safe", { sql: args.sql, }) const data = result.data as Record diff --git a/packages/altimate-code/src/tool/sqlguard-lint.ts b/packages/altimate-code/src/tool/altimate-core-lint.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-lint.ts rename to packages/altimate-code/src/tool/altimate-core-lint.ts index 92750a58ee..555913a927 100644 --- a/packages/altimate-code/src/tool/sqlguard-lint.ts +++ b/packages/altimate-code/src/tool/altimate-core-lint.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardLintTool = Tool.define("sqlguard_lint", { +export const AltimateCoreLintTool = Tool.define("altimate_core_lint", { description: - "Lint SQL for anti-patterns using the Rust-based sqlguard engine. Catches issues like NULL comparisons, implicit casts, unused CTEs, and dialect-specific problems.", + "Lint SQL for anti-patterns using the Rust-based altimate-core engine. Catches issues like NULL comparisons, implicit casts, unused CTEs, and dialect-specific problems.", parameters: z.object({ sql: z.string().describe("SQL query to lint"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardLintTool = Tool.define("sqlguard_lint", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.lint", { + const result = await Bridge.call("altimate_core.lint", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-migration.ts b/packages/altimate-code/src/tool/altimate-core-migration.ts similarity index 81% rename from packages/altimate-code/src/tool/sqlguard-migration.ts rename to packages/altimate-code/src/tool/altimate-core-migration.ts index 5e7b63a0eb..9fabb079cf 100644 --- a/packages/altimate-code/src/tool/sqlguard-migration.ts +++ b/packages/altimate-code/src/tool/altimate-core-migration.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardMigrationTool = Tool.define("sqlguard_migration", { +export const AltimateCoreMigrationTool = Tool.define("altimate_core_migration", { description: - "Analyze DDL migration safety using the Rust-based sqlguard engine. Detects potential data loss, type narrowing, missing defaults, and other risks in schema migration statements.", + "Analyze DDL migration safety using the Rust-based altimate-core engine. Detects potential data loss, type narrowing, missing defaults, and other risks in schema migration statements.", parameters: z.object({ old_ddl: z.string().describe("Original DDL (before migration)"), new_ddl: z.string().describe("New DDL (after migration)"), @@ -12,7 +12,7 @@ export const SqlGuardMigrationTool = Tool.define("sqlguard_migration", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.migration", { + const result = await Bridge.call("altimate_core.migration", { old_ddl: args.old_ddl, new_ddl: args.new_ddl, dialect: args.dialect ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-optimize-context.ts b/packages/altimate-code/src/tool/altimate-core-optimize-context.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-optimize-context.ts rename to packages/altimate-code/src/tool/altimate-core-optimize-context.ts index b1309ee8a5..0ec7d61c0e 100644 --- a/packages/altimate-code/src/tool/sqlguard-optimize-context.ts +++ b/packages/altimate-code/src/tool/altimate-core-optimize-context.ts @@ -2,16 +2,16 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardOptimizeContextTool = Tool.define("sqlguard_optimize_context", { +export const AltimateCoreOptimizeContextTool = Tool.define("altimate_core_optimize_context", { description: - "Optimize schema for LLM context window using the Rust-based sqlguard engine. Applies 5-level progressive disclosure to reduce schema size while preserving essential information.", + "Optimize schema for LLM context window using the Rust-based altimate-core engine. Applies 5-level progressive disclosure to reduce schema size while preserving essential information.", parameters: z.object({ schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.optimize_context", { + const result = await Bridge.call("altimate_core.optimize_context", { schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) diff --git a/packages/altimate-code/src/tool/sqlguard-optimize-for-query.ts b/packages/altimate-code/src/tool/altimate-core-optimize-for-query.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-optimize-for-query.ts rename to packages/altimate-code/src/tool/altimate-core-optimize-for-query.ts index 42b2f7141a..532598c70a 100644 --- a/packages/altimate-code/src/tool/sqlguard-optimize-for-query.ts +++ b/packages/altimate-code/src/tool/altimate-core-optimize-for-query.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardOptimizeForQueryTool = Tool.define("sqlguard_optimize_for_query", { +export const AltimateCoreOptimizeForQueryTool = Tool.define("altimate_core_optimize_for_query", { description: - "Prune schema to only tables and columns relevant to a specific query using the Rust-based sqlguard engine. Reduces context size for LLM prompts.", + "Prune schema to only tables and columns relevant to a specific query using the Rust-based altimate-core engine. Reduces context size for LLM prompts.", parameters: z.object({ sql: z.string().describe("SQL query to optimize schema for"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardOptimizeForQueryTool = Tool.define("sqlguard_optimize_for_q }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.optimize_for_query", { + const result = await Bridge.call("altimate_core.optimize_for_query", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-parse-dbt.ts b/packages/altimate-code/src/tool/altimate-core-parse-dbt.ts similarity index 80% rename from packages/altimate-code/src/tool/sqlguard-parse-dbt.ts rename to packages/altimate-code/src/tool/altimate-core-parse-dbt.ts index ea2d2f79cb..5a756e05f9 100644 --- a/packages/altimate-code/src/tool/sqlguard-parse-dbt.ts +++ b/packages/altimate-code/src/tool/altimate-core-parse-dbt.ts @@ -2,15 +2,15 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardParseDbtTool = Tool.define("sqlguard_parse_dbt", { +export const AltimateCoreParseDbtTool = Tool.define("altimate_core_parse_dbt", { description: - "Parse a dbt project directory using the Rust-based sqlguard engine. Extracts models, sources, tests, and project structure for analysis.", + "Parse a dbt project directory using the Rust-based altimate-core engine. Extracts models, sources, tests, and project structure for analysis.", parameters: z.object({ project_dir: z.string().describe("Path to the dbt project directory"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.parse_dbt", { + const result = await Bridge.call("altimate_core.parse_dbt", { project_dir: args.project_dir, }) const data = result.data as Record diff --git a/packages/altimate-code/src/tool/sqlguard-policy.ts b/packages/altimate-code/src/tool/altimate-core-policy.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-policy.ts rename to packages/altimate-code/src/tool/altimate-core-policy.ts index d5557b459b..021208b316 100644 --- a/packages/altimate-code/src/tool/sqlguard-policy.ts +++ b/packages/altimate-code/src/tool/altimate-core-policy.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardPolicyTool = Tool.define("sqlguard_policy", { +export const AltimateCorePolicyTool = Tool.define("altimate_core_policy", { description: - "Check SQL against YAML-based governance policy guardrails using the Rust-based sqlguard engine. Validates compliance with custom rules like allowed tables, forbidden operations, and data access restrictions.", + "Check SQL against YAML-based governance policy guardrails using the Rust-based altimate-core engine. Validates compliance with custom rules like allowed tables, forbidden operations, and data access restrictions.", parameters: z.object({ sql: z.string().describe("SQL query to check against policy"), policy_json: z.string().describe("JSON string defining the policy rules"), @@ -13,7 +13,7 @@ export const SqlGuardPolicyTool = Tool.define("sqlguard_policy", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.policy", { + const result = await Bridge.call("altimate_core.policy", { sql: args.sql, policy_json: args.policy_json, schema_path: args.schema_path ?? "", diff --git a/packages/altimate-code/src/tool/sqlguard-prune-schema.ts b/packages/altimate-code/src/tool/altimate-core-prune-schema.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-prune-schema.ts rename to packages/altimate-code/src/tool/altimate-core-prune-schema.ts index bfd6aceb26..aef2a54031 100644 --- a/packages/altimate-code/src/tool/sqlguard-prune-schema.ts +++ b/packages/altimate-code/src/tool/altimate-core-prune-schema.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardPruneSchemaTool = Tool.define("sqlguard_prune_schema", { +export const AltimateCorePruneSchemaTool = Tool.define("altimate_core_prune_schema", { description: - "Filter schema to only tables and columns referenced by a SQL query using the Rust-based sqlguard engine. Progressive schema disclosure for minimal context.", + "Filter schema to only tables and columns referenced by a SQL query using the Rust-based altimate-core engine. Progressive schema disclosure for minimal context.", parameters: z.object({ sql: z.string().describe("SQL query to determine relevant schema for"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardPruneSchemaTool = Tool.define("sqlguard_prune_schema", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.prune_schema", { + const result = await Bridge.call("altimate_core.prune_schema", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-query-pii.ts b/packages/altimate-code/src/tool/altimate-core-query-pii.ts similarity index 82% rename from packages/altimate-code/src/tool/sqlguard-query-pii.ts rename to packages/altimate-code/src/tool/altimate-core-query-pii.ts index b7a6b9905f..706cec9c4d 100644 --- a/packages/altimate-code/src/tool/sqlguard-query-pii.ts +++ b/packages/altimate-code/src/tool/altimate-core-query-pii.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardQueryPiiTool = Tool.define("sqlguard_query_pii", { +export const AltimateCoreQueryPiiTool = Tool.define("altimate_core_query_pii", { description: - "Analyze query-level PII exposure using the Rust-based sqlguard engine. Checks if a SQL query accesses columns classified as PII and reports the exposure risk.", + "Analyze query-level PII exposure using the Rust-based altimate-core engine. Checks if a SQL query accesses columns classified as PII and reports the exposure risk.", parameters: z.object({ sql: z.string().describe("SQL query to check for PII access"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardQueryPiiTool = Tool.define("sqlguard_query_pii", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.query_pii", { + const result = await Bridge.call("altimate_core.query_pii", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-resolve-term.ts b/packages/altimate-code/src/tool/altimate-core-resolve-term.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-resolve-term.ts rename to packages/altimate-code/src/tool/altimate-core-resolve-term.ts index d50d0edbc9..366d858224 100644 --- a/packages/altimate-code/src/tool/sqlguard-resolve-term.ts +++ b/packages/altimate-code/src/tool/altimate-core-resolve-term.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardResolveTermTool = Tool.define("sqlguard_resolve_term", { +export const AltimateCoreResolveTermTool = Tool.define("altimate_core_resolve_term", { description: - "Resolve a business glossary term to schema elements using fuzzy matching via the Rust-based sqlguard engine. Maps human-readable terms like 'revenue' or 'customer' to actual table/column names.", + "Resolve a business glossary term to schema elements using fuzzy matching via the Rust-based altimate-core engine. Maps human-readable terms like 'revenue' or 'customer' to actual table/column names.", parameters: z.object({ term: z.string().describe("Business term to resolve (e.g. 'revenue', 'customer email')"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardResolveTermTool = Tool.define("sqlguard_resolve_term", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.resolve_term", { + const result = await Bridge.call("altimate_core.resolve_term", { term: args.term, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-rewrite.ts b/packages/altimate-code/src/tool/altimate-core-rewrite.ts similarity index 85% rename from packages/altimate-code/src/tool/sqlguard-rewrite.ts rename to packages/altimate-code/src/tool/altimate-core-rewrite.ts index c7b3e9194b..a3fc6b05e7 100644 --- a/packages/altimate-code/src/tool/sqlguard-rewrite.ts +++ b/packages/altimate-code/src/tool/altimate-core-rewrite.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardRewriteTool = Tool.define("sqlguard_rewrite", { +export const AltimateCoreRewriteTool = Tool.define("altimate_core_rewrite", { description: - "Suggest query optimization rewrites using the Rust-based sqlguard engine. Analyzes SQL and proposes concrete rewrites for better performance.", + "Suggest query optimization rewrites using the Rust-based altimate-core engine. Analyzes SQL and proposes concrete rewrites for better performance.", parameters: z.object({ sql: z.string().describe("SQL query to optimize"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardRewriteTool = Tool.define("sqlguard_rewrite", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.rewrite", { + const result = await Bridge.call("altimate_core.rewrite", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-safety.ts b/packages/altimate-code/src/tool/altimate-core-safety.ts similarity index 84% rename from packages/altimate-code/src/tool/sqlguard-safety.ts rename to packages/altimate-code/src/tool/altimate-core-safety.ts index 37381c0f74..aa548a7754 100644 --- a/packages/altimate-code/src/tool/sqlguard-safety.ts +++ b/packages/altimate-code/src/tool/altimate-core-safety.ts @@ -2,15 +2,15 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardSafetyTool = Tool.define("sqlguard_safety", { +export const AltimateCoreSafetyTool = Tool.define("altimate_core_safety", { description: - "Scan SQL for injection patterns, dangerous statements (DROP, TRUNCATE), and security threats. Uses the Rust-based sqlguard safety engine.", + "Scan SQL for injection patterns, dangerous statements (DROP, TRUNCATE), and security threats. Uses the Rust-based altimate-core safety engine.", parameters: z.object({ sql: z.string().describe("SQL query to scan"), }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.safety", { sql: args.sql }) + const result = await Bridge.call("altimate_core.safety", { sql: args.sql }) const data = result.data as Record return { title: `Safety: ${data.safe ? "SAFE" : `${data.threats?.length ?? 0} threats`}`, diff --git a/packages/altimate-code/src/tool/sqlguard-schema-diff.ts b/packages/altimate-code/src/tool/altimate-core-schema-diff.ts similarity index 87% rename from packages/altimate-code/src/tool/sqlguard-schema-diff.ts rename to packages/altimate-code/src/tool/altimate-core-schema-diff.ts index e2f1902363..53d418819f 100644 --- a/packages/altimate-code/src/tool/sqlguard-schema-diff.ts +++ b/packages/altimate-code/src/tool/altimate-core-schema-diff.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardSchemaDiffTool = Tool.define("sqlguard_schema_diff", { +export const AltimateCoreSchemaDiffTool = Tool.define("altimate_core_schema_diff", { description: - "Diff two schemas and detect breaking changes using the Rust-based sqlguard engine. Compares old vs new schema files and identifies added, removed, and modified tables/columns.", + "Diff two schemas and detect breaking changes using the Rust-based altimate-core engine. Compares old vs new schema files and identifies added, removed, and modified tables/columns.", parameters: z.object({ schema1_path: z.string().optional().describe("Path to the old/baseline schema file"), schema2_path: z.string().optional().describe("Path to the new/changed schema file"), @@ -13,7 +13,7 @@ export const SqlGuardSchemaDiffTool = Tool.define("sqlguard_schema_diff", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.schema_diff", { + const result = await Bridge.call("altimate_core.schema_diff", { schema1_path: args.schema1_path ?? "", schema2_path: args.schema2_path ?? "", schema1_context: args.schema1_context, diff --git a/packages/altimate-code/src/tool/sqlguard-semantics.ts b/packages/altimate-code/src/tool/altimate-core-semantics.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-semantics.ts rename to packages/altimate-code/src/tool/altimate-core-semantics.ts index 4d0954e7c8..2760999e7a 100644 --- a/packages/altimate-code/src/tool/sqlguard-semantics.ts +++ b/packages/altimate-code/src/tool/altimate-core-semantics.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardSemanticsTool = Tool.define("sqlguard_semantics", { +export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", { description: - "Run semantic validation rules against SQL using the Rust-based sqlguard engine. Detects logical issues like cartesian products, wrong JOIN conditions, NULL misuse, and type mismatches that syntax checking alone misses.", + "Run semantic validation rules against SQL using the Rust-based altimate-core engine. Detects logical issues like cartesian products, wrong JOIN conditions, NULL misuse, and type mismatches that syntax checking alone misses.", parameters: z.object({ sql: z.string().describe("SQL query to validate semantically"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardSemanticsTool = Tool.define("sqlguard_semantics", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.semantics", { + const result = await Bridge.call("altimate_core.semantics", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-testgen.ts b/packages/altimate-code/src/tool/altimate-core-testgen.ts similarity index 83% rename from packages/altimate-code/src/tool/sqlguard-testgen.ts rename to packages/altimate-code/src/tool/altimate-core-testgen.ts index cdc5590642..b4d62449f6 100644 --- a/packages/altimate-code/src/tool/sqlguard-testgen.ts +++ b/packages/altimate-code/src/tool/altimate-core-testgen.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardTestgenTool = Tool.define("sqlguard_testgen", { +export const AltimateCoreTestgenTool = Tool.define("altimate_core_testgen", { description: - "Generate automated SQL test cases using the Rust-based sqlguard engine. Produces boundary value tests, NULL handling tests, edge cases, and expected result assertions for a given SQL query.", + "Generate automated SQL test cases using the Rust-based altimate-core engine. Produces boundary value tests, NULL handling tests, edge cases, and expected result assertions for a given SQL query.", parameters: z.object({ sql: z.string().describe("SQL query to generate tests for"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardTestgenTool = Tool.define("sqlguard_testgen", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.testgen", { + const result = await Bridge.call("altimate_core.testgen", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-track-lineage.ts b/packages/altimate-code/src/tool/altimate-core-track-lineage.ts similarity index 84% rename from packages/altimate-code/src/tool/sqlguard-track-lineage.ts rename to packages/altimate-code/src/tool/altimate-core-track-lineage.ts index a0a9dd7c30..c00aa9b921 100644 --- a/packages/altimate-code/src/tool/sqlguard-track-lineage.ts +++ b/packages/altimate-code/src/tool/altimate-core-track-lineage.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardTrackLineageTool = Tool.define("sqlguard_track_lineage", { +export const AltimateCoreTrackLineageTool = Tool.define("altimate_core_track_lineage", { description: - "Track lineage across multiple SQL queries using the Rust-based sqlguard engine. Builds a combined lineage graph from a sequence of queries. Requires sqlguard.init() with API key.", + "Track lineage across multiple SQL queries using the Rust-based altimate-core engine. Builds a combined lineage graph from a sequence of queries. Requires altimate_core.init() with API key.", parameters: z.object({ queries: z.array(z.string()).describe("List of SQL queries to track lineage across"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardTrackLineageTool = Tool.define("sqlguard_track_lineage", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.track_lineage", { + const result = await Bridge.call("altimate_core.track_lineage", { queries: args.queries, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/sqlguard-transpile.ts b/packages/altimate-code/src/tool/altimate-core-transpile.ts similarity index 81% rename from packages/altimate-code/src/tool/sqlguard-transpile.ts rename to packages/altimate-code/src/tool/altimate-core-transpile.ts index 504edf42b1..a0e73711f0 100644 --- a/packages/altimate-code/src/tool/sqlguard-transpile.ts +++ b/packages/altimate-code/src/tool/altimate-core-transpile.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardTranspileTool = Tool.define("sqlguard_transpile", { +export const AltimateCoreTranspileTool = Tool.define("altimate_core_transpile", { description: - "Transpile SQL between dialects using the Rust-based sqlguard engine. Supports snowflake, postgres, bigquery, databricks, duckdb, mysql, tsql, and more.", + "Transpile SQL between dialects using the Rust-based altimate-core engine. Supports snowflake, postgres, bigquery, databricks, duckdb, mysql, tsql, and more.", parameters: z.object({ sql: z.string().describe("SQL query to transpile"), from_dialect: z.string().describe("Source dialect (e.g., snowflake, postgres, bigquery)"), @@ -12,7 +12,7 @@ export const SqlGuardTranspileTool = Tool.define("sqlguard_transpile", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.transpile", { + const result = await Bridge.call("altimate_core.transpile", { sql: args.sql, from_dialect: args.from_dialect, to_dialect: args.to_dialect, diff --git a/packages/altimate-code/src/tool/sqlguard-validate.ts b/packages/altimate-code/src/tool/altimate-core-validate.ts similarity index 84% rename from packages/altimate-code/src/tool/sqlguard-validate.ts rename to packages/altimate-code/src/tool/altimate-core-validate.ts index c92d989481..e6d001373e 100644 --- a/packages/altimate-code/src/tool/sqlguard-validate.ts +++ b/packages/altimate-code/src/tool/altimate-core-validate.ts @@ -2,9 +2,9 @@ import z from "zod" import { Tool } from "./tool" import { Bridge } from "../bridge/client" -export const SqlGuardValidateTool = Tool.define("sqlguard_validate", { +export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { description: - "Validate SQL syntax and schema references using the Rust-based sqlguard engine. Checks if tables/columns exist in the schema and if SQL is valid for the target dialect.", + "Validate SQL syntax and schema references using the Rust-based altimate-core engine. Checks if tables/columns exist in the schema and if SQL is valid for the target dialect.", parameters: z.object({ sql: z.string().describe("SQL query to validate"), schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), @@ -12,7 +12,7 @@ export const SqlGuardValidateTool = Tool.define("sqlguard_validate", { }), async execute(args, ctx) { try { - const result = await Bridge.call("sqlguard.validate", { + const result = await Bridge.call("altimate_core.validate", { sql: args.sql, schema_path: args.schema_path ?? "", schema_context: args.schema_context, diff --git a/packages/altimate-code/src/tool/ci-cost-gate.ts b/packages/altimate-code/src/tool/ci-cost-gate.ts deleted file mode 100644 index fb104ca553..0000000000 --- a/packages/altimate-code/src/tool/ci-cost-gate.ts +++ /dev/null @@ -1,80 +0,0 @@ -import z from "zod" -import { Tool } from "./tool" -import { Bridge } from "../bridge/client" -import type { CostGateResult, CostGateFileResult } from "../bridge/protocol" - -export const CiCostGateTool = Tool.define("ci_cost_gate", { - description: - "Scan changed SQL files for critical issues. Reads SQL files, runs analysis and guard checks, and returns pass/fail based on whether critical severity issues are found. Skips Jinja templates, parse errors, and non-SQL files. Exit code 1 if critical issues found, 0 otherwise.", - parameters: z.object({ - file_paths: z.array(z.string()).describe("List of SQL file paths to scan"), - dialect: z - .string() - .optional() - .default("snowflake") - .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), - }), - async execute(args, ctx) { - try { - const result = await Bridge.call("ci.cost_gate", { - file_paths: args.file_paths, - dialect: args.dialect, - }) - - const status = result.passed ? "PASSED" : "FAILED" - - return { - title: `CI Scan: ${status} (${result.files_scanned} files, ${result.total_issues} issues, ${result.critical_count} critical)`, - metadata: { - success: result.success, - passed: result.passed, - exitCode: result.exit_code, - filesScanned: result.files_scanned, - totalIssues: result.total_issues, - criticalCount: result.critical_count, - }, - output: formatCostGate(result), - } - } catch (e) { - const msg = e instanceof Error ? e.message : String(e) - return { - title: "CI Scan: ERROR", - metadata: { success: false, passed: false, exitCode: 1, filesScanned: 0, totalIssues: 0, criticalCount: 0 }, - output: `Failed to run CI scan: ${msg}\n\nEnsure the Python bridge is running and altimate-engine is installed.`, - } - } - }, -}) - -function formatCostGate(result: CostGateResult): string { - if (!result.success) { - return `CI scan failed: ${result.error ?? "Unknown error"}` - } - - const lines: string[] = [] - const status = result.passed ? "PASSED" : "FAILED" - - lines.push(`=== CI Cost Gate: ${status} ===`) - lines.push(`Files scanned: ${result.files_scanned} | Skipped: ${result.files_skipped}`) - lines.push(`Total issues: ${result.total_issues} | Critical: ${result.critical_count}`) - lines.push(`Exit code: ${result.exit_code}`) - lines.push("") - - for (const fr of result.file_results) { - const icon = fr.status === "pass" ? "OK" : fr.status === "fail" ? "FAIL" : "SKIP" - lines.push(` [${icon}] ${fr.file}`) - - if (fr.reason) { - lines.push(` Reason: ${fr.reason}`) - } - - if (fr.issues.length > 0) { - for (const issue of fr.issues) { - const severity = ((issue.severity as string) ?? "warning").toUpperCase() - lines.push(` [${severity}] ${issue.type}: ${issue.message}`) - } - } - } - - return lines.join("\n") -} diff --git a/packages/altimate-code/src/tool/dbt-lineage.ts b/packages/altimate-code/src/tool/dbt-lineage.ts index 07f62770da..83944ba504 100644 --- a/packages/altimate-code/src/tool/dbt-lineage.ts +++ b/packages/altimate-code/src/tool/dbt-lineage.ts @@ -5,7 +5,7 @@ import type { DbtLineageResult } from "../bridge/protocol" export const DbtLineageTool = Tool.define("dbt_lineage", { description: - "Compute column-level lineage for a dbt model using the Rust-based sqlguard engine. Takes a manifest.json path and model name, extracts compiled SQL and upstream schemas, and traces column flow.", + "Compute column-level lineage for a dbt model using the Rust-based altimate-core engine. Takes a manifest.json path and model name, extracts compiled SQL and upstream schemas, and traces column flow.", parameters: z.object({ manifest_path: z.string().describe("Path to dbt manifest.json file"), model: z.string().describe("Model name or unique_id (e.g. 'my_model' or 'model.project.my_model')"), diff --git a/packages/altimate-code/src/tool/lineage-check.ts b/packages/altimate-code/src/tool/lineage-check.ts index e76f15d1cd..38d2b8cfbb 100644 --- a/packages/altimate-code/src/tool/lineage-check.ts +++ b/packages/altimate-code/src/tool/lineage-check.ts @@ -5,7 +5,7 @@ import type { LineageCheckResult } from "../bridge/protocol" export const LineageCheckTool = Tool.define("lineage_check", { description: - "Check column-level lineage for a SQL query using the Rust-based sqlguard engine. Traces how source columns flow through transformations to output columns. Useful for impact analysis and understanding data flow.", + "Check column-level lineage for a SQL query using the Rust-based altimate-core engine. Traces how source columns flow through transformations to output columns. Useful for impact analysis and understanding data flow.", parameters: z.object({ sql: z.string().describe("SQL query to trace lineage for"), dialect: z @@ -45,7 +45,7 @@ export const LineageCheckTool = Tool.define("lineage_check", { return { title: "Lineage: ERROR", metadata: { success: false }, - output: `Failed to check lineage: ${msg}\n\nEnsure the Python bridge is running and sqlguard is initialized.`, + output: `Failed to check lineage: ${msg}\n\nEnsure the Python bridge is running and altimate-core is initialized.`, } } }, diff --git a/packages/altimate-code/src/tool/registry.ts b/packages/altimate-code/src/tool/registry.ts index 6f4c74b265..9e1d0a4df5 100644 --- a/packages/altimate-code/src/tool/registry.ts +++ b/packages/altimate-code/src/tool/registry.ts @@ -35,8 +35,6 @@ import { WarehouseTestTool } from "./warehouse-test" import { WarehouseAddTool } from "./warehouse-add" import { WarehouseRemoveTool } from "./warehouse-remove" import { WarehouseDiscoverTool } from "./warehouse-discover" -import { SqlRecordFeedbackTool } from "./sql-record-feedback" -import { SqlPredictCostTool } from "./sql-predict-cost" import { DbtRunTool } from "./dbt-run" import { DbtManifestTool } from "./dbt-manifest" import { DbtProfilesTool } from "./dbt-profiles" @@ -58,46 +56,46 @@ import { FinopsRoleGrantsTool, FinopsRoleHierarchyTool, FinopsUserRolesTool } fr import { SchemaDetectPiiTool } from "./schema-detect-pii" import { SchemaTagsTool, SchemaTagsListTool } from "./schema-tags" import { SqlRewriteTool } from "./sql-rewrite" -import { CiCostGateTool } from "./ci-cost-gate" + import { SchemaDiffTool } from "./schema-diff" -import { SqlGuardValidateTool } from "./sqlguard-validate" -import { SqlGuardLintTool } from "./sqlguard-lint" -import { SqlGuardSafetyTool } from "./sqlguard-safety" -import { SqlGuardTranspileTool } from "./sqlguard-transpile" -import { SqlGuardCheckTool } from "./sqlguard-check" +import { AltimateCoreValidateTool } from "./altimate-core-validate" +import { AltimateCoreLintTool } from "./altimate-core-lint" +import { AltimateCoreSafetyTool } from "./altimate-core-safety" +import { AltimateCoreTranspileTool } from "./altimate-core-transpile" +import { AltimateCoreCheckTool } from "./altimate-core-check" // Phase 1 (P0) -import { SqlGuardFixTool } from "./sqlguard-fix" -import { SqlGuardPolicyTool } from "./sqlguard-policy" -import { SqlGuardComplexityTool } from "./sqlguard-complexity" -import { SqlGuardSemanticsTool } from "./sqlguard-semantics" -import { SqlGuardTestgenTool } from "./sqlguard-testgen" +import { AltimateCoreFixTool } from "./altimate-core-fix" +import { AltimateCorePolicyTool } from "./altimate-core-policy" + +import { AltimateCoreSemanticsTool } from "./altimate-core-semantics" +import { AltimateCoreTestgenTool } from "./altimate-core-testgen" // Phase 2 (P1) -import { SqlGuardEquivalenceTool } from "./sqlguard-equivalence" -import { SqlGuardMigrationTool } from "./sqlguard-migration" -import { SqlGuardSchemaDiffTool } from "./sqlguard-schema-diff" -import { SqlGuardRewriteTool } from "./sqlguard-rewrite" -import { SqlGuardCorrectTool } from "./sqlguard-correct" -import { SqlGuardGradeTool } from "./sqlguard-grade" -import { SqlGuardCostTool } from "./sqlguard-cost" +import { AltimateCoreEquivalenceTool } from "./altimate-core-equivalence" +import { AltimateCoreMigrationTool } from "./altimate-core-migration" +import { AltimateCoreSchemaDiffTool } from "./altimate-core-schema-diff" +import { AltimateCoreRewriteTool } from "./altimate-core-rewrite" +import { AltimateCoreCorrectTool } from "./altimate-core-correct" +import { AltimateCoreGradeTool } from "./altimate-core-grade" + // Phase 3 (P2) -import { SqlGuardClassifyPiiTool } from "./sqlguard-classify-pii" -import { SqlGuardQueryPiiTool } from "./sqlguard-query-pii" -import { SqlGuardResolveTermTool } from "./sqlguard-resolve-term" -import { SqlGuardColumnLineageTool } from "./sqlguard-column-lineage" -import { SqlGuardTrackLineageTool } from "./sqlguard-track-lineage" -import { SqlGuardFormatTool } from "./sqlguard-format" -import { SqlGuardExtractMetadataTool } from "./sqlguard-extract-metadata" -import { SqlGuardCompareTool } from "./sqlguard-compare" -import { SqlGuardCompleteTool } from "./sqlguard-complete" -import { SqlGuardOptimizeContextTool } from "./sqlguard-optimize-context" -import { SqlGuardOptimizeForQueryTool } from "./sqlguard-optimize-for-query" -import { SqlGuardPruneSchemaTool } from "./sqlguard-prune-schema" -import { SqlGuardImportDdlTool } from "./sqlguard-import-ddl" -import { SqlGuardExportDdlTool } from "./sqlguard-export-ddl" -import { SqlGuardFingerprintTool } from "./sqlguard-fingerprint" -import { SqlGuardIntrospectionSqlTool } from "./sqlguard-introspection-sql" -import { SqlGuardParseDbtTool } from "./sqlguard-parse-dbt" -import { SqlGuardIsSafeTool } from "./sqlguard-is-safe" +import { AltimateCoreClassifyPiiTool } from "./altimate-core-classify-pii" +import { AltimateCoreQueryPiiTool } from "./altimate-core-query-pii" +import { AltimateCoreResolveTermTool } from "./altimate-core-resolve-term" +import { AltimateCoreColumnLineageTool } from "./altimate-core-column-lineage" +import { AltimateCoreTrackLineageTool } from "./altimate-core-track-lineage" +import { AltimateCoreFormatTool } from "./altimate-core-format" +import { AltimateCoreExtractMetadataTool } from "./altimate-core-extract-metadata" +import { AltimateCoreCompareTool } from "./altimate-core-compare" +import { AltimateCoreCompleteTool } from "./altimate-core-complete" +import { AltimateCoreOptimizeContextTool } from "./altimate-core-optimize-context" +import { AltimateCoreOptimizeForQueryTool } from "./altimate-core-optimize-for-query" +import { AltimateCorePruneSchemaTool } from "./altimate-core-prune-schema" +import { AltimateCoreImportDdlTool } from "./altimate-core-import-ddl" +import { AltimateCoreExportDdlTool } from "./altimate-core-export-ddl" +import { AltimateCoreFingerprintTool } from "./altimate-core-fingerprint" +import { AltimateCoreIntrospectionSqlTool } from "./altimate-core-introspection-sql" +import { AltimateCoreParseDbtTool } from "./altimate-core-parse-dbt" +import { AltimateCoreIsSafeTool } from "./altimate-core-is-safe" import { ProjectScanTool } from "./project-scan" import { Glob } from "../util/glob" @@ -197,8 +195,6 @@ export namespace ToolRegistry { WarehouseAddTool, WarehouseRemoveTool, WarehouseDiscoverTool, - SqlRecordFeedbackTool, - SqlPredictCostTool, DbtRunTool, DbtManifestTool, DbtProfilesTool, @@ -223,46 +219,43 @@ export namespace ToolRegistry { SchemaTagsTool, SchemaTagsListTool, SqlRewriteTool, - CiCostGateTool, SchemaDiffTool, - SqlGuardValidateTool, - SqlGuardLintTool, - SqlGuardSafetyTool, - SqlGuardTranspileTool, - SqlGuardCheckTool, + AltimateCoreValidateTool, + AltimateCoreLintTool, + AltimateCoreSafetyTool, + AltimateCoreTranspileTool, + AltimateCoreCheckTool, // Phase 1 (P0) - SqlGuardFixTool, - SqlGuardPolicyTool, - SqlGuardComplexityTool, - SqlGuardSemanticsTool, - SqlGuardTestgenTool, + AltimateCoreFixTool, + AltimateCorePolicyTool, + AltimateCoreSemanticsTool, + AltimateCoreTestgenTool, // Phase 2 (P1) - SqlGuardEquivalenceTool, - SqlGuardMigrationTool, - SqlGuardSchemaDiffTool, - SqlGuardRewriteTool, - SqlGuardCorrectTool, - SqlGuardGradeTool, - SqlGuardCostTool, + AltimateCoreEquivalenceTool, + AltimateCoreMigrationTool, + AltimateCoreSchemaDiffTool, + AltimateCoreRewriteTool, + AltimateCoreCorrectTool, + AltimateCoreGradeTool, // Phase 3 (P2) - SqlGuardClassifyPiiTool, - SqlGuardQueryPiiTool, - SqlGuardResolveTermTool, - SqlGuardColumnLineageTool, - SqlGuardTrackLineageTool, - SqlGuardFormatTool, - SqlGuardExtractMetadataTool, - SqlGuardCompareTool, - SqlGuardCompleteTool, - SqlGuardOptimizeContextTool, - SqlGuardOptimizeForQueryTool, - SqlGuardPruneSchemaTool, - SqlGuardImportDdlTool, - SqlGuardExportDdlTool, - SqlGuardFingerprintTool, - SqlGuardIntrospectionSqlTool, - SqlGuardParseDbtTool, - SqlGuardIsSafeTool, + AltimateCoreClassifyPiiTool, + AltimateCoreQueryPiiTool, + AltimateCoreResolveTermTool, + AltimateCoreColumnLineageTool, + AltimateCoreTrackLineageTool, + AltimateCoreFormatTool, + AltimateCoreExtractMetadataTool, + AltimateCoreCompareTool, + AltimateCoreCompleteTool, + AltimateCoreOptimizeContextTool, + AltimateCoreOptimizeForQueryTool, + AltimateCorePruneSchemaTool, + AltimateCoreImportDdlTool, + AltimateCoreExportDdlTool, + AltimateCoreFingerprintTool, + AltimateCoreIntrospectionSqlTool, + AltimateCoreParseDbtTool, + AltimateCoreIsSafeTool, ProjectScanTool, ...custom, ] diff --git a/packages/altimate-code/src/tool/sql-predict-cost.ts b/packages/altimate-code/src/tool/sql-predict-cost.ts deleted file mode 100644 index 6156d0b8f7..0000000000 --- a/packages/altimate-code/src/tool/sql-predict-cost.ts +++ /dev/null @@ -1,66 +0,0 @@ -import z from "zod" -import { Tool } from "./tool" -import { Bridge } from "../bridge/client" -import type { SqlPredictCostResult } from "../bridge/protocol" - -export const SqlPredictCostTool = Tool.define("sql_predict_cost", { - description: - "Predict the cost of a SQL query based on historical execution data. Uses a multi-tier approach: fingerprint match, template match, table scan estimate, or static heuristic.", - parameters: z.object({ - sql: z.string().describe("SQL query to predict cost for"), - dialect: z.string().optional().default("snowflake").describe("SQL dialect"), - }), - async execute(args, ctx) { - try { - const result = await Bridge.call("sql.predict_cost", { - sql: args.sql, - dialect: args.dialect, - }) - - return { - title: `Cost: tier ${result.tier} [${result.confidence}]`, - metadata: { - tier: result.tier, - confidence: result.confidence, - method: result.method, - }, - output: formatPrediction(result), - } - } catch (e) { - const msg = e instanceof Error ? e.message : String(e) - return { - title: "Cost: ERROR", - metadata: { tier: 0, confidence: "unknown", method: "error" }, - output: `Failed to predict cost: ${msg}\n\nEnsure the Python bridge is running and altimate-engine is installed.`, - } - } - }, -}) - -function formatPrediction(result: SqlPredictCostResult): string { - const lines: string[] = [] - - lines.push(`Prediction Method: ${result.method} (tier ${result.tier})`) - lines.push(`Confidence: ${result.confidence}`) - lines.push(`Observations: ${result.observation_count}`) - lines.push("") - - if (result.predicted_bytes != null) { - const mb = (result.predicted_bytes / (1024 * 1024)).toFixed(1) - lines.push(`Estimated bytes scanned: ${result.predicted_bytes.toLocaleString()} (${mb} MB)`) - } - if (result.predicted_time_ms != null) { - const sec = (result.predicted_time_ms / 1000).toFixed(1) - lines.push(`Estimated execution time: ${result.predicted_time_ms.toLocaleString()} ms (${sec}s)`) - } - if (result.predicted_credits != null) { - lines.push(`Estimated credits: ${result.predicted_credits}`) - } - - if (result.observation_count === 0) { - lines.push("") - lines.push("Note: No historical data available. Record query feedback with sql_record_feedback to improve predictions.") - } - - return lines.join("\n") -} diff --git a/packages/altimate-code/src/tool/sql-record-feedback.ts b/packages/altimate-code/src/tool/sql-record-feedback.ts deleted file mode 100644 index 1a445330cf..0000000000 --- a/packages/altimate-code/src/tool/sql-record-feedback.ts +++ /dev/null @@ -1,45 +0,0 @@ -import z from "zod" -import { Tool } from "./tool" -import { Bridge } from "../bridge/client" - -export const SqlRecordFeedbackTool = Tool.define("sql_record_feedback", { - description: - "Record query execution metrics (bytes scanned, execution time, credits) for cost prediction. Builds a local feedback store that improves future cost estimates.", - parameters: z.object({ - sql: z.string().describe("The SQL query that was executed"), - dialect: z.string().optional().default("snowflake").describe("SQL dialect"), - bytes_scanned: z.number().optional().describe("Bytes scanned during execution"), - rows_produced: z.number().optional().describe("Number of rows returned"), - execution_time_ms: z.number().optional().describe("Execution time in milliseconds"), - credits_used: z.number().optional().describe("Warehouse credits consumed"), - warehouse_size: z.string().optional().describe("Warehouse size (e.g. X-Small, Small, Medium)"), - }), - async execute(args, ctx) { - try { - const result = await Bridge.call("sql.record_feedback", { - sql: args.sql, - dialect: args.dialect, - bytes_scanned: args.bytes_scanned, - rows_produced: args.rows_produced, - execution_time_ms: args.execution_time_ms, - credits_used: args.credits_used, - warehouse_size: args.warehouse_size, - }) - - return { - title: `Feedback: ${result.recorded ? "recorded" : "failed"}`, - metadata: { recorded: result.recorded }, - output: result.recorded - ? "Query execution metrics recorded successfully." - : "Failed to record feedback.", - } - } catch (e) { - const msg = e instanceof Error ? e.message : String(e) - return { - title: "Feedback: ERROR", - metadata: { recorded: false }, - output: `Failed to record feedback: ${msg}\n\nEnsure the Python bridge is running and altimate-engine is installed.`, - } - } - }, -}) diff --git a/packages/altimate-code/src/tool/sqlguard-complexity.ts b/packages/altimate-code/src/tool/sqlguard-complexity.ts deleted file mode 100644 index db91427ea7..0000000000 --- a/packages/altimate-code/src/tool/sqlguard-complexity.ts +++ /dev/null @@ -1,48 +0,0 @@ -import z from "zod" -import { Tool } from "./tool" -import { Bridge } from "../bridge/client" - -export const SqlGuardComplexityTool = Tool.define("sqlguard_complexity", { - description: - "Score multi-dimensional SQL complexity and estimated cloud cost using the Rust-based sqlguard engine. Returns a 0-100 score, tier classification (Trivial/Simple/Moderate/Complex/VeryComplex), and cost signals.", - parameters: z.object({ - sql: z.string().describe("SQL query to analyze"), - schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), - schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), - }), - async execute(args, ctx) { - try { - const result = await Bridge.call("sqlguard.complexity", { - sql: args.sql, - schema_path: args.schema_path ?? "", - schema_context: args.schema_context, - }) - const data = result.data as Record - return { - title: `Complexity: ${data.score ?? "?"}/100 (${data.tier ?? "unknown"})`, - metadata: { success: result.success, score: data.score, tier: data.tier }, - output: formatComplexity(data), - } - } catch (e) { - const msg = e instanceof Error ? e.message : String(e) - return { title: "Complexity: ERROR", metadata: { success: false, score: null, tier: null }, output: `Failed: ${msg}` } - } - }, -}) - -function formatComplexity(data: Record): string { - if (data.error) return `Error: ${data.error}` - const lines: string[] = [] - lines.push(`Score: ${data.score}/100`) - lines.push(`Tier: ${data.tier}`) - if (data.dimensions) { - lines.push("\nDimensions:") - for (const [key, val] of Object.entries(data.dimensions)) { - lines.push(` ${key}: ${val}`) - } - } - if (data.cost) { - lines.push(`\nEstimated cost: ${JSON.stringify(data.cost)}`) - } - return lines.join("\n") -} diff --git a/packages/altimate-code/src/tool/sqlguard-cost.ts b/packages/altimate-code/src/tool/sqlguard-cost.ts deleted file mode 100644 index 1e5846d30d..0000000000 --- a/packages/altimate-code/src/tool/sqlguard-cost.ts +++ /dev/null @@ -1,49 +0,0 @@ -import z from "zod" -import { Tool } from "./tool" -import { Bridge } from "../bridge/client" - -export const SqlGuardCostTool = Tool.define("sqlguard_cost", { - description: - "Estimate per-dialect cloud cost for a SQL query using the Rust-based sqlguard engine. Returns estimated bytes scanned, execution time, and USD cost for the target cloud warehouse.", - parameters: z.object({ - sql: z.string().describe("SQL query to estimate cost for"), - schema_path: z.string().optional().describe("Path to YAML/JSON schema file"), - schema_context: z.record(z.string(), z.any()).optional().describe("Inline schema definition"), - dialect: z.string().optional().describe("Target dialect (e.g. snowflake, bigquery, redshift)"), - }), - async execute(args, ctx) { - try { - const result = await Bridge.call("sqlguard.cost", { - sql: args.sql, - schema_path: args.schema_path ?? "", - schema_context: args.schema_context, - dialect: args.dialect ?? "", - }) - const data = result.data as Record - return { - title: `Cost: ${data.estimated_usd != null ? `$${data.estimated_usd}` : data.tier ?? "estimated"}`, - metadata: { success: result.success, estimated_usd: data.estimated_usd }, - output: formatCost(data), - } - } catch (e) { - const msg = e instanceof Error ? e.message : String(e) - return { title: "Cost: ERROR", metadata: { success: false, estimated_usd: null }, output: `Failed: ${msg}` } - } - }, -}) - -function formatCost(data: Record): string { - if (data.error) return `Error: ${data.error}` - const lines: string[] = [] - if (data.estimated_usd != null) lines.push(`Estimated cost: $${data.estimated_usd}`) - if (data.bytes_scanned != null) lines.push(`Bytes scanned: ${data.bytes_scanned}`) - if (data.tier) lines.push(`Cost tier: ${data.tier}`) - if (data.dialect) lines.push(`Dialect: ${data.dialect}`) - if (data.breakdown) { - lines.push("\nBreakdown:") - for (const [key, val] of Object.entries(data.breakdown)) { - lines.push(` ${key}: ${val}`) - } - } - return lines.join("\n") -} diff --git a/packages/altimate-engine/src/altimate_engine/ci/__init__.py b/packages/altimate-engine/src/altimate_engine/ci/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/altimate-engine/src/altimate_engine/ci/cost_gate.py b/packages/altimate-engine/src/altimate_engine/ci/cost_gate.py deleted file mode 100644 index f955cce4e4..0000000000 --- a/packages/altimate-engine/src/altimate_engine/ci/cost_gate.py +++ /dev/null @@ -1,162 +0,0 @@ -"""CI cost gate — scan changed SQL files for critical issues. - -Reads SQL files, runs lint analysis, and returns -pass/fail based on whether CRITICAL severity issues are found. - -Skips: - - Jinja templates ({{ }}, {% %}) - - Parse errors (likely Jinja or non-standard SQL) - - Non-SQL files -""" - -from __future__ import annotations - -import os -import re -from typing import Any - -from altimate_engine.sql.guard import guard_lint - - -# Jinja pattern: {{ ... }} or {% ... %} or {# ... #} -_JINJA_PATTERN = re.compile(r"\{\{.*?\}\}|\{%.*?%\}|\{#.*?#\}", re.DOTALL) - - -def _has_jinja(sql: str) -> bool: - """Check if SQL contains Jinja template syntax.""" - return bool(_JINJA_PATTERN.search(sql)) - - -def _split_statements(sql: str) -> list[str]: - """Split SQL on semicolons, filtering empty statements.""" - statements = [] - for stmt in sql.split(";"): - stmt = stmt.strip() - if stmt: - statements.append(stmt) - return statements - - -def scan_files( - file_paths: list[str], - dialect: str = "snowflake", -) -> dict[str, Any]: - """Scan SQL files for critical issues. - - Args: - file_paths: List of SQL file paths to scan. - dialect: SQL dialect for analysis (default: snowflake). - - Returns: - Dict with pass/fail status, per-file results, and summary. - """ - file_results: list[dict[str, Any]] = [] - total_issues = 0 - critical_count = 0 - files_scanned = 0 - files_skipped = 0 - - for path in file_paths: - # Skip non-SQL files - if not path.endswith(".sql"): - files_skipped += 1 - file_results.append({ - "file": path, - "status": "skipped", - "reason": "not a SQL file", - "issues": [], - }) - continue - - # Read file - if not os.path.isfile(path): - files_skipped += 1 - file_results.append({ - "file": path, - "status": "skipped", - "reason": "file not found", - "issues": [], - }) - continue - - try: - with open(path, "r", encoding="utf-8") as f: - content = f.read() - except Exception as e: - files_skipped += 1 - file_results.append({ - "file": path, - "status": "skipped", - "reason": f"read error: {e}", - "issues": [], - }) - continue - - # Skip Jinja templates - if _has_jinja(content): - files_skipped += 1 - file_results.append({ - "file": path, - "status": "skipped", - "reason": "contains Jinja templates", - "issues": [], - }) - continue - - # Split and analyze each statement - statements = _split_statements(content) - if not statements: - files_skipped += 1 - file_results.append({ - "file": path, - "status": "skipped", - "reason": "empty file", - "issues": [], - }) - continue - - files_scanned += 1 - file_issues: list[dict[str, Any]] = [] - - for stmt in statements: - # Run lint analysis - lint_result = guard_lint(stmt) - if lint_result.get("error"): - # Parse error — skip this statement (likely incomplete SQL) - continue - - for finding in lint_result.get("findings", lint_result.get("issues", [])): - severity = finding.get("severity", "warning") - file_issues.append({ - "type": finding.get("rule", finding.get("type", "UNKNOWN")), - "severity": severity, - "message": finding.get("message", ""), - "source": "lint", - }) - total_issues += 1 - if severity in ("error", "critical"): - critical_count += 1 - - status = "fail" if any( - i["severity"] in ("error", "critical") for i in file_issues - ) else "pass" - - file_results.append({ - "file": path, - "status": status, - "issues": file_issues, - }) - - passed = critical_count == 0 - - return { - "success": True, - "passed": passed, - "exit_code": 0 if passed else 1, - "files_scanned": files_scanned, - "files_skipped": files_skipped, - "total_issues": total_issues, - "critical_count": critical_count, - "file_results": file_results, - "error": None, - } diff --git a/packages/altimate-engine/src/altimate_engine/dbt/lineage.py b/packages/altimate-engine/src/altimate_engine/dbt/lineage.py index 478ddd8099..e68badfdc2 100644 --- a/packages/altimate-engine/src/altimate_engine/dbt/lineage.py +++ b/packages/altimate-engine/src/altimate_engine/dbt/lineage.py @@ -21,7 +21,7 @@ def dbt_lineage(params: DbtLineageParams) -> DbtLineageResult: Loads the manifest, finds the target model (by name or unique_id), extracts its compiled SQL + upstream schemas, and delegates to - sqlguard's column_lineage via guard_column_lineage. + altimate-core's column_lineage via guard_column_lineage. """ manifest_path = Path(params.manifest_path) if not manifest_path.exists(): @@ -71,7 +71,7 @@ def dbt_lineage(params: DbtLineageParams) -> DbtLineageResult: upstream_ids = model_node.get("depends_on", {}).get("nodes", []) schema_context = _build_schema_context(nodes, sources, upstream_ids) - # Delegate to sqlguard column_lineage + # Delegate to altimate-core column_lineage raw = guard_column_lineage( sql, dialect=dialect, @@ -136,7 +136,7 @@ def _build_schema_context( ) -> dict | None: """Build schema context from upstream model/source columns. - Returns sqlguard schema format: + Returns altimate-core schema format: {"tables": {"table_name": {"columns": [{"name": ..., "type": ...}]}}, "version": "1"} """ tables: dict[str, dict] = {} diff --git a/packages/altimate-engine/src/altimate_engine/models.py b/packages/altimate-engine/src/altimate_engine/models.py index bfc26491a5..47fae13c0f 100644 --- a/packages/altimate-engine/src/altimate_engine/models.py +++ b/packages/altimate-engine/src/altimate_engine/models.py @@ -101,38 +101,6 @@ class SqlOptimizeResult(BaseModel): error: str | None = None -# --- SQL Feedback & Cost Prediction --- - - -class SqlRecordFeedbackParams(BaseModel): - sql: str - dialect: str = "snowflake" - bytes_scanned: int | None = None - rows_produced: int | None = None - execution_time_ms: int | None = None - credits_used: float | None = None - warehouse_size: str | None = None - - -class SqlRecordFeedbackResult(BaseModel): - recorded: bool - - -class SqlPredictCostParams(BaseModel): - sql: str - dialect: str = "snowflake" - - -class SqlPredictCostResult(BaseModel): - tier: int - confidence: str - predicted_bytes: int | None = None - predicted_time_ms: int | None = None - predicted_credits: float | None = None - method: str - observation_count: int - - # --- SQL Explain --- @@ -776,33 +744,6 @@ class SqlRewriteResult(BaseModel): error: str | None = None -# --- CI Cost Gate --- - - -class CostGateFileResult(BaseModel): - file: str - status: str # "pass", "fail", "skipped" - reason: str | None = None - issues: list[dict[str, Any]] = Field(default_factory=list) - - -class CostGateParams(BaseModel): - file_paths: list[str] - dialect: str = "snowflake" - - -class CostGateResult(BaseModel): - success: bool - passed: bool - exit_code: int = 0 - files_scanned: int = 0 - files_skipped: int = 0 - total_issues: int = 0 - critical_count: int = 0 - file_results: list[CostGateFileResult] = Field(default_factory=list) - error: str | None = None - - # --- Schema Change Detection --- @@ -831,231 +772,218 @@ class SchemaDiffResult(BaseModel): error: str | None = None -# --- sqlguard --- +# --- altimate_core --- -class SqlGuardValidateParams(BaseModel): +class AltimateCoreValidateParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardLintParams(BaseModel): +class AltimateCoreLintParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardSafetyParams(BaseModel): +class AltimateCoreSafetyParams(BaseModel): sql: str -class SqlGuardTranspileParams(BaseModel): +class AltimateCoreTranspileParams(BaseModel): sql: str from_dialect: str to_dialect: str -class SqlGuardExplainParams(BaseModel): +class AltimateCoreExplainParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardCheckParams(BaseModel): +class AltimateCoreCheckParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardResult(BaseModel): +class AltimateCoreResult(BaseModel): success: bool = True data: dict[str, Any] | None = Field(default_factory=dict) error: str | None = None -# --- sqlguard Phase 1 (P0) --- +# --- altimate_core Phase 1 (P0) --- -class SqlGuardFixParams(BaseModel): +class AltimateCoreFixParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None max_iterations: int = 5 -class SqlGuardPolicyParams(BaseModel): +class AltimateCorePolicyParams(BaseModel): sql: str policy_json: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardComplexityParams(BaseModel): +class AltimateCoreSemanticsParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardSemanticsParams(BaseModel): +class AltimateCoreTestgenParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardTestgenParams(BaseModel): - sql: str - schema_path: str = "" - schema_context: dict[str, Any] | None = None - - -# --- sqlguard Phase 2 (P1) --- +# --- altimate_core Phase 2 (P1) --- -class SqlGuardEquivalenceParams(BaseModel): +class AltimateCoreEquivalenceParams(BaseModel): sql1: str sql2: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardMigrationParams(BaseModel): +class AltimateCoreMigrationParams(BaseModel): old_ddl: str new_ddl: str dialect: str = "" -class SqlGuardSchemaDiffParams(BaseModel): +class AltimateCoreSchemaDiffParams(BaseModel): schema1_path: str = "" schema2_path: str = "" schema1_context: dict[str, Any] | None = None schema2_context: dict[str, Any] | None = None -class SqlGuardGuardRewriteParams(BaseModel): +class AltimateCoreGuardRewriteParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardCorrectParams(BaseModel): +class AltimateCoreCorrectParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardGradeParams(BaseModel): +class AltimateCoreGradeParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardCostParams(BaseModel): - sql: str - schema_path: str = "" - schema_context: dict[str, Any] | None = None - dialect: str = "" - - -# --- sqlguard Phase 3 (P2) --- +# --- altimate_core Phase 3 (P2) --- -class SqlGuardClassifyPiiParams(BaseModel): +class AltimateCoreClassifyPiiParams(BaseModel): schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardQueryPiiParams(BaseModel): +class AltimateCoreQueryPiiParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardResolveTermParams(BaseModel): +class AltimateCoreResolveTermParams(BaseModel): term: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardColumnLineageParams(BaseModel): +class AltimateCoreColumnLineageParams(BaseModel): sql: str dialect: str = "" schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardTrackLineageParams(BaseModel): +class AltimateCoreTrackLineageParams(BaseModel): queries: list[str] schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardFormatSqlParams(BaseModel): +class AltimateCoreFormatSqlParams(BaseModel): sql: str dialect: str = "" -class SqlGuardExtractMetadataParams(BaseModel): +class AltimateCoreExtractMetadataParams(BaseModel): sql: str dialect: str = "" -class SqlGuardCompareQueriesParams(BaseModel): +class AltimateCoreCompareQueriesParams(BaseModel): left_sql: str right_sql: str dialect: str = "" -class SqlGuardCompleteParams(BaseModel): +class AltimateCoreCompleteParams(BaseModel): sql: str cursor_pos: int schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardOptimizeContextParams(BaseModel): +class AltimateCoreOptimizeContextParams(BaseModel): schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardOptimizeForQueryParams(BaseModel): +class AltimateCoreOptimizeForQueryParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardPruneSchemaParams(BaseModel): +class AltimateCorePruneSchemaParams(BaseModel): sql: str schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardImportDdlParams(BaseModel): +class AltimateCoreImportDdlParams(BaseModel): ddl: str dialect: str = "" -class SqlGuardExportDdlParams(BaseModel): +class AltimateCoreExportDdlParams(BaseModel): schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardSchemaFingerprintParams(BaseModel): +class AltimateCoreSchemaFingerprintParams(BaseModel): schema_path: str = "" schema_context: dict[str, Any] | None = None -class SqlGuardIntrospectionSqlParams(BaseModel): +class AltimateCoreIntrospectionSqlParams(BaseModel): db_type: str database: str schema_name: str | None = None -class SqlGuardParseDbtProjectParams(BaseModel): +class AltimateCoreParseDbtProjectParams(BaseModel): project_dir: str -class SqlGuardIsSafeParams(BaseModel): +class AltimateCoreIsSafeParams(BaseModel): sql: str diff --git a/packages/altimate-engine/src/altimate_engine/server.py b/packages/altimate-engine/src/altimate_engine/server.py index 01ec07c358..b29bd7438a 100644 --- a/packages/altimate-engine/src/altimate_engine/server.py +++ b/packages/altimate-engine/src/altimate_engine/server.py @@ -60,10 +60,6 @@ SqlOptimizeParams, SqlOptimizeResult, SqlOptimizeSuggestion, - SqlPredictCostParams, - SqlPredictCostResult, - SqlRecordFeedbackParams, - SqlRecordFeedbackResult, SqlRewriteParams, SqlRewriteResult, SqlRewriteRule, @@ -98,13 +94,13 @@ TagsListResult, SqlDiffParams, SqlDiffResult, - SqlGuardValidateParams, - SqlGuardLintParams, - SqlGuardSafetyParams, - SqlGuardTranspileParams, - SqlGuardExplainParams, - SqlGuardCheckParams, - SqlGuardResult, + AltimateCoreValidateParams, + AltimateCoreLintParams, + AltimateCoreSafetyParams, + AltimateCoreTranspileParams, + AltimateCoreExplainParams, + AltimateCoreCheckParams, + AltimateCoreResult, ) from altimate_engine.sql.executor import execute_sql from altimate_engine.sql.explainer import explain_sql @@ -119,7 +115,6 @@ from altimate_engine.connections import ConnectionRegistry # lineage.check delegates to guard_column_lineage -from altimate_engine.sql.feedback_store import FeedbackStore from altimate_engine.schema.cache import SchemaCache from altimate_engine.finops.query_history import get_query_history from altimate_engine.finops.credit_analyzer import ( @@ -143,7 +138,6 @@ # Phase 1 (P0) guard_fix as guard_fix_sql, guard_check_policy, - guard_complexity_score, guard_check_semantics, guard_generate_tests, # Phase 2 (P1) @@ -153,7 +147,6 @@ guard_rewrite as guard_rewrite_sql, guard_correct, guard_evaluate, - guard_estimate_cost, # Phase 3 (P2) guard_classify_pii, guard_check_query_pii, @@ -178,38 +171,36 @@ from altimate_engine.local.schema_sync import sync_schema from altimate_engine.local.test_local import test_sql_local from altimate_engine.models import ( - SqlGuardFixParams, - SqlGuardPolicyParams, - SqlGuardComplexityParams, - SqlGuardSemanticsParams, - SqlGuardTestgenParams, + AltimateCoreFixParams, + AltimateCorePolicyParams, + AltimateCoreSemanticsParams, + AltimateCoreTestgenParams, # Phase 2 (P1) - SqlGuardEquivalenceParams, - SqlGuardMigrationParams, - SqlGuardSchemaDiffParams, - SqlGuardGuardRewriteParams, - SqlGuardCorrectParams, - SqlGuardGradeParams, - SqlGuardCostParams, + AltimateCoreEquivalenceParams, + AltimateCoreMigrationParams, + AltimateCoreSchemaDiffParams, + AltimateCoreGuardRewriteParams, + AltimateCoreCorrectParams, + AltimateCoreGradeParams, # Phase 3 (P2) - SqlGuardClassifyPiiParams, - SqlGuardQueryPiiParams, - SqlGuardResolveTermParams, - SqlGuardColumnLineageParams, - SqlGuardTrackLineageParams, - SqlGuardFormatSqlParams, - SqlGuardExtractMetadataParams, - SqlGuardCompareQueriesParams, - SqlGuardCompleteParams, - SqlGuardOptimizeContextParams, - SqlGuardOptimizeForQueryParams, - SqlGuardPruneSchemaParams, - SqlGuardImportDdlParams, - SqlGuardExportDdlParams, - SqlGuardSchemaFingerprintParams, - SqlGuardIntrospectionSqlParams, - SqlGuardParseDbtProjectParams, - SqlGuardIsSafeParams, + AltimateCoreClassifyPiiParams, + AltimateCoreQueryPiiParams, + AltimateCoreResolveTermParams, + AltimateCoreColumnLineageParams, + AltimateCoreTrackLineageParams, + AltimateCoreFormatSqlParams, + AltimateCoreExtractMetadataParams, + AltimateCoreCompareQueriesParams, + AltimateCoreCompleteParams, + AltimateCoreOptimizeContextParams, + AltimateCoreOptimizeForQueryParams, + AltimateCorePruneSchemaParams, + AltimateCoreImportDdlParams, + AltimateCoreExportDdlParams, + AltimateCoreSchemaFingerprintParams, + AltimateCoreIntrospectionSqlParams, + AltimateCoreParseDbtProjectParams, + AltimateCoreIsSafeParams, ) @@ -246,18 +237,9 @@ def _schema_context_to_dict( return {"tables": tables, "version": "1"} -_feedback_store: FeedbackStore | None = None _schema_cache: SchemaCache | None = None -def _get_feedback_store() -> FeedbackStore: - """Return the singleton FeedbackStore, creating it on first use.""" - global _feedback_store - if _feedback_store is None: - _feedback_store = FeedbackStore() - return _feedback_store - - def _get_schema_cache() -> SchemaCache: """Return the singleton SchemaCache, creating it on first use.""" global _schema_cache @@ -460,7 +442,7 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: else None, ) _err = raw.get("error") - result = SqlGuardResult( + result = AltimateCoreResult( success=_err is None, data=raw if _err is None else None, error=_err, @@ -508,33 +490,6 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: except Exception as e: result = WarehouseDiscoverResult(error=str(e)) - elif method == "sql.record_feedback": - fb_params = SqlRecordFeedbackParams(**params) - store = _get_feedback_store() - store.record( - sql=fb_params.sql, - dialect=fb_params.dialect, - bytes_scanned=fb_params.bytes_scanned, - rows_produced=fb_params.rows_produced, - execution_time_ms=fb_params.execution_time_ms, - credits_used=fb_params.credits_used, - warehouse_size=fb_params.warehouse_size, - ) - result = SqlRecordFeedbackResult(recorded=True) - elif method == "sql.predict_cost": - pc_params = SqlPredictCostParams(**params) - store = _get_feedback_store() - prediction = store.predict(sql=pc_params.sql, dialect=pc_params.dialect) - # Merge sqlguard cost estimate if feedback store has no data - if prediction.get("method") == "no_data": - guard_cost = guard_estimate_cost( - pc_params.sql, dialect=pc_params.dialect - ) - if guard_cost.get("bytes_scanned") or guard_cost.get("estimated_usd"): - prediction["predicted_bytes"] = guard_cost.get("bytes_scanned") - prediction["predicted_credits"] = guard_cost.get("estimated_usd") - prediction["method"] = "sqlguard_estimate" - result = SqlPredictCostResult(**prediction) elif method == "sql.format": fmt_params = SqlFormatParams(**params) raw = guard_format_sql(fmt_params.sql, fmt_params.dialect) @@ -559,8 +514,8 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: error_message=fix_params.error_message, suggestions=[ SqlFixSuggestion( - type="SQLGUARD_FIX", - message="Auto-fixed by sqlguard engine", + type="ALTIMATE_CORE_FIX", + message="Auto-fixed by altimate_core engine", confidence="high", fixed_sql=fixed_sql, ) @@ -748,7 +703,7 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: elif method == "sql.diff": p = SqlDiffParams(**params) raw = diff_sql(p.original, p.modified, p.context_lines) - # Add semantic equivalence check via sqlguard + # Add semantic equivalence check via altimate_core equiv = guard_check_equivalence(p.original, p.modified) if equiv.get("equivalent") is not None: raw["semantic_equivalent"] = equiv["equivalent"] @@ -762,10 +717,10 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: for r in guard_rw.get("rewrites", []): rewrites.append( SqlRewriteRule( - rule=r.get("rule", "SQLGUARD_REWRITE"), + rule=r.get("rule", "ALTIMATE_CORE_REWRITE"), original_fragment=r.get("original_fragment", ""), rewritten_fragment=r.get("rewritten_fragment", ""), - explanation=r.get("explanation", "Rewritten by sqlguard"), + explanation=r.get("explanation", "Rewritten by altimate_core"), can_auto_apply=True, ) ) @@ -783,193 +738,185 @@ def dispatch(request: JsonRpcRequest) -> JsonRpcResponse: rewrites_applied=[], error=guard_rw.get("error", "No rewrites applicable"), ) - # --- sqlguard --- - elif method == "sqlguard.validate": - p = SqlGuardValidateParams(**params) + # --- altimate_core --- + elif method == "altimate_core.validate": + p = AltimateCoreValidateParams(**params) raw = guard_validate(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("valid", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.lint": - p = SqlGuardLintParams(**params) + elif method == "altimate_core.lint": + p = AltimateCoreLintParams(**params) raw = guard_lint(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("clean", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.safety": - p = SqlGuardSafetyParams(**params) + elif method == "altimate_core.safety": + p = AltimateCoreSafetyParams(**params) raw = guard_scan_safety(p.sql) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("safe", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.transpile": - p = SqlGuardTranspileParams(**params) + elif method == "altimate_core.transpile": + p = AltimateCoreTranspileParams(**params) raw = guard_transpile(p.sql, p.from_dialect, p.to_dialect) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.explain": - p = SqlGuardExplainParams(**params) + elif method == "altimate_core.explain": + p = AltimateCoreExplainParams(**params) raw = guard_explain(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("valid", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.check": - p = SqlGuardCheckParams(**params) + elif method == "altimate_core.check": + p = AltimateCoreCheckParams(**params) raw = guard_check(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - # --- sqlguard Phase 1 (P0) --- - elif method == "sqlguard.fix": - p = SqlGuardFixParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + # --- altimate_core Phase 1 (P0) --- + elif method == "altimate_core.fix": + p = AltimateCoreFixParams(**params) raw = guard_fix_sql( p.sql, p.schema_path, p.schema_context, p.max_iterations ) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.policy": - p = SqlGuardPolicyParams(**params) + elif method == "altimate_core.policy": + p = AltimateCorePolicyParams(**params) raw = guard_check_policy( p.sql, p.policy_json, p.schema_path, p.schema_context ) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("pass", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.complexity": - p = SqlGuardComplexityParams(**params) - raw = guard_complexity_score(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.semantics": - p = SqlGuardSemanticsParams(**params) + elif method == "altimate_core.semantics": + p = AltimateCoreSemanticsParams(**params) raw = guard_check_semantics(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("valid", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.testgen": - p = SqlGuardTestgenParams(**params) + elif method == "altimate_core.testgen": + p = AltimateCoreTestgenParams(**params) raw = guard_generate_tests(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - # --- sqlguard Phase 2 (P1) --- - elif method == "sqlguard.equivalence": - p = SqlGuardEquivalenceParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + # --- altimate_core Phase 2 (P1) --- + elif method == "altimate_core.equivalence": + p = AltimateCoreEquivalenceParams(**params) raw = guard_check_equivalence( p.sql1, p.sql2, p.schema_path, p.schema_context ) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.migration": - p = SqlGuardMigrationParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.migration": + p = AltimateCoreMigrationParams(**params) raw = guard_analyze_migration(p.old_ddl, p.new_ddl, p.dialect) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.schema_diff": - p = SqlGuardSchemaDiffParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.schema_diff": + p = AltimateCoreSchemaDiffParams(**params) raw = guard_diff_schemas( p.schema1_path, p.schema2_path, p.schema1_context, p.schema2_context, ) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.rewrite": - p = SqlGuardGuardRewriteParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.rewrite": + p = AltimateCoreGuardRewriteParams(**params) raw = guard_rewrite_sql(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.correct": - p = SqlGuardCorrectParams(**params) + elif method == "altimate_core.correct": + p = AltimateCoreCorrectParams(**params) raw = guard_correct(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.grade": - p = SqlGuardGradeParams(**params) + elif method == "altimate_core.grade": + p = AltimateCoreGradeParams(**params) raw = guard_evaluate(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.cost": - p = SqlGuardCostParams(**params) - raw = guard_estimate_cost(p.sql, p.schema_path, p.schema_context, p.dialect) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - # --- sqlguard Phase 3 (P2) --- - elif method == "sqlguard.classify_pii": - p = SqlGuardClassifyPiiParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + # --- altimate_core Phase 3 (P2) --- + elif method == "altimate_core.classify_pii": + p = AltimateCoreClassifyPiiParams(**params) raw = guard_classify_pii(p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.query_pii": - p = SqlGuardQueryPiiParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.query_pii": + p = AltimateCoreQueryPiiParams(**params) raw = guard_check_query_pii(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.resolve_term": - p = SqlGuardResolveTermParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.resolve_term": + p = AltimateCoreResolveTermParams(**params) raw = guard_resolve_term(p.term, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.column_lineage": - p = SqlGuardColumnLineageParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.column_lineage": + p = AltimateCoreColumnLineageParams(**params) raw = guard_column_lineage( p.sql, p.dialect, p.schema_path, p.schema_context ) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.track_lineage": - p = SqlGuardTrackLineageParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.track_lineage": + p = AltimateCoreTrackLineageParams(**params) raw = guard_track_lineage(p.queries, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.format": - p = SqlGuardFormatSqlParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.format": + p = AltimateCoreFormatSqlParams(**params) raw = guard_format_sql(p.sql, p.dialect) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.metadata": - p = SqlGuardExtractMetadataParams(**params) + elif method == "altimate_core.metadata": + p = AltimateCoreExtractMetadataParams(**params) raw = guard_extract_metadata(p.sql, p.dialect) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.compare": - p = SqlGuardCompareQueriesParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.compare": + p = AltimateCoreCompareQueriesParams(**params) raw = guard_compare_queries(p.left_sql, p.right_sql, p.dialect) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.complete": - p = SqlGuardCompleteParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.complete": + p = AltimateCoreCompleteParams(**params) raw = guard_complete(p.sql, p.cursor_pos, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.optimize_context": - p = SqlGuardOptimizeContextParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.optimize_context": + p = AltimateCoreOptimizeContextParams(**params) raw = guard_optimize_context(p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.optimize_for_query": - p = SqlGuardOptimizeForQueryParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.optimize_for_query": + p = AltimateCoreOptimizeForQueryParams(**params) raw = guard_optimize_for_query(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.prune_schema": - p = SqlGuardPruneSchemaParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.prune_schema": + p = AltimateCorePruneSchemaParams(**params) raw = guard_prune_schema(p.sql, p.schema_path, p.schema_context) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.import_ddl": - p = SqlGuardImportDdlParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.import_ddl": + p = AltimateCoreImportDdlParams(**params) raw = guard_import_ddl(p.ddl, p.dialect) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.export_ddl": - p = SqlGuardExportDdlParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.export_ddl": + p = AltimateCoreExportDdlParams(**params) raw = guard_export_ddl(p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.fingerprint": - p = SqlGuardSchemaFingerprintParams(**params) + elif method == "altimate_core.fingerprint": + p = AltimateCoreSchemaFingerprintParams(**params) raw = guard_schema_fingerprint(p.schema_path, p.schema_context) - result = SqlGuardResult( + result = AltimateCoreResult( success=raw.get("success", True), data=raw, error=raw.get("error") ) - elif method == "sqlguard.introspection_sql": - p = SqlGuardIntrospectionSqlParams(**params) + elif method == "altimate_core.introspection_sql": + p = AltimateCoreIntrospectionSqlParams(**params) raw = guard_introspection_sql(p.db_type, p.database, p.schema_name) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.parse_dbt": - p = SqlGuardParseDbtProjectParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.parse_dbt": + p = AltimateCoreParseDbtProjectParams(**params) raw = guard_parse_dbt_project(p.project_dir) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) - elif method == "sqlguard.is_safe": - p = SqlGuardIsSafeParams(**params) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) + elif method == "altimate_core.is_safe": + p = AltimateCoreIsSafeParams(**params) raw = guard_is_safe(p.sql) - result = SqlGuardResult(success=True, data=raw, error=raw.get("error")) + result = AltimateCoreResult(success=True, data=raw, error=raw.get("error")) # --- dbt discovery --- elif method == "dbt.profiles": p = DbtProfilesParams(**params) diff --git a/packages/altimate-engine/src/altimate_engine/sql/feedback_store.py b/packages/altimate-engine/src/altimate_engine/sql/feedback_store.py deleted file mode 100644 index 72fa9a8fe6..0000000000 --- a/packages/altimate-engine/src/altimate_engine/sql/feedback_store.py +++ /dev/null @@ -1,392 +0,0 @@ -"""Feedback store for query execution metrics — enables cost prediction.""" - -from __future__ import annotations - -import hashlib -import re -import sqlite3 -import statistics -from datetime import datetime, timezone -from pathlib import Path -from typing import Any - -from altimate_engine.sql.guard import guard_extract_metadata, guard_complexity_score - - -_CREATE_TABLE_SQL = """ -CREATE TABLE IF NOT EXISTS query_feedback ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - fingerprint TEXT NOT NULL, - template_hash TEXT NOT NULL, - bytes_scanned INTEGER, - rows_produced INTEGER, - execution_time_ms INTEGER, - credits_used REAL, - warehouse_size TEXT, - dialect TEXT DEFAULT 'snowflake', - timestamp TEXT NOT NULL -); -""" - -_CREATE_INDEX_FINGERPRINT = ( - "CREATE INDEX IF NOT EXISTS idx_fingerprint ON query_feedback(fingerprint);" -) -_CREATE_INDEX_TEMPLATE = ( - "CREATE INDEX IF NOT EXISTS idx_template ON query_feedback(template_hash);" -) - - -def _default_db_path() -> str: - """Return the default feedback database path: ~/.altimate/feedback.db""" - altimate_dir = Path.home() / ".altimate" - altimate_dir.mkdir(parents=True, exist_ok=True) - return str(altimate_dir / "feedback.db") - - -def _regex_strip_literals(sql: str) -> str: - """Regex-based literal stripping for SQL fingerprinting. - - Replaces string literals, numeric literals, and boolean literals with - placeholders. Normalizes whitespace. - """ - # Replace single-quoted strings - result = re.sub(r"'[^']*'", "'?'", sql) - # Replace double-quoted strings (that are not identifiers in some dialects) - # Be conservative — skip this for Snowflake where double quotes are identifiers - # Replace numeric literals (integers and floats, but not in identifiers) - result = re.sub(r"\b\d+(\.\d+)?\b", "?", result) - # Normalize whitespace - result = re.sub(r"\s+", " ", result).strip() - return result.upper() - - -class FeedbackStore: - """Local SQLite-based feedback store that records query execution metrics - and uses them for cost prediction via a multi-tier hierarchy.""" - - def __init__(self, db_path: str | None = None): - """Initialize with optional db path. Defaults to ~/.altimate/feedback.db""" - self._db_path = db_path or _default_db_path() - self._conn = sqlite3.connect(self._db_path) - self._conn.row_factory = sqlite3.Row - self._init_schema() - - def _init_schema(self) -> None: - """Create tables and indexes if they don't exist.""" - cursor = self._conn.cursor() - cursor.execute(_CREATE_TABLE_SQL) - cursor.execute(_CREATE_INDEX_FINGERPRINT) - cursor.execute(_CREATE_INDEX_TEMPLATE) - self._conn.commit() - - def record( - self, - sql: str, - dialect: str = "snowflake", - bytes_scanned: int | None = None, - rows_produced: int | None = None, - execution_time_ms: int | None = None, - credits_used: float | None = None, - warehouse_size: str | None = None, - ) -> None: - """Record a query execution observation.""" - fingerprint = self._fingerprint(sql, dialect) - template_hash = self._template_hash(sql, dialect) - timestamp = datetime.now(timezone.utc).isoformat() - - self._conn.execute( - """ - INSERT INTO query_feedback - (fingerprint, template_hash, bytes_scanned, rows_produced, - execution_time_ms, credits_used, warehouse_size, dialect, timestamp) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) - """, - ( - fingerprint, - template_hash, - bytes_scanned, - rows_produced, - execution_time_ms, - credits_used, - warehouse_size, - dialect, - timestamp, - ), - ) - self._conn.commit() - - def predict(self, sql: str, dialect: str = "snowflake") -> dict[str, Any]: - """Predict cost for a query using a multi-tier hierarchy. - - Tiers: - 1. Fingerprint match (>= 3 observations) — median of matching fingerprints - 2. Template match (>= 3 observations) — median of matching templates - 3. Table scan estimate — sum of estimated table sizes from schema - 4. Static heuristic — based on query complexity (joins, aggregations, etc.) - - Returns: - Dictionary with keys: tier, confidence, predicted_bytes, predicted_time_ms, - predicted_credits, method, observation_count - """ - # Tier 1: Fingerprint match - fingerprint = self._fingerprint(sql, dialect) - rows = self._fetch_observations_by_fingerprint(fingerprint) - if len(rows) >= 3: - return self._aggregate_predictions(rows, tier=1, method="fingerprint_match") - - # Tier 2: Template match - template_hash = self._template_hash(sql, dialect) - rows = self._fetch_observations_by_template(template_hash) - if len(rows) >= 3: - return self._aggregate_predictions(rows, tier=2, method="template_match") - - # Tier 3: Table scan estimate - table_estimate = self._estimate_from_tables(sql, dialect) - if table_estimate is not None: - return { - "tier": 3, - "confidence": "low", - "predicted_bytes": table_estimate["predicted_bytes"], - "predicted_time_ms": table_estimate["predicted_time_ms"], - "predicted_credits": table_estimate["predicted_credits"], - "method": "table_scan_estimate", - "observation_count": table_estimate["observation_count"], - } - - # Tier 4: Static heuristic - return self._static_heuristic(sql, dialect) - - def _fingerprint(self, sql: str, dialect: str) -> str: - """Normalize SQL to a canonical fingerprint (strip literals, normalize whitespace).""" - normalized = _regex_strip_literals(sql) - return hashlib.sha256(normalized.encode()).hexdigest() - - def _template_hash(self, sql: str, dialect: str) -> str: - """Generalized hash: preserve table structure, replace all literals with ?.""" - # Replace string literals with '?', numbers with ? - result = re.sub(r"'[^']*'", "'?'", sql) - result = re.sub(r"\b\d+(\.\d+)?\b", "?", result) - result = re.sub(r"\s+", " ", result).strip().upper() - return hashlib.sha256(result.encode()).hexdigest() - - # --- Internal helpers --- - - def _fetch_observations_by_fingerprint(self, fingerprint: str) -> list[sqlite3.Row]: - """Fetch all observations matching a fingerprint.""" - cursor = self._conn.execute( - "SELECT * FROM query_feedback WHERE fingerprint = ? ORDER BY timestamp DESC", - (fingerprint,), - ) - return cursor.fetchall() - - def _fetch_observations_by_template(self, template_hash: str) -> list[sqlite3.Row]: - """Fetch all observations matching a template hash.""" - cursor = self._conn.execute( - "SELECT * FROM query_feedback WHERE template_hash = ? ORDER BY timestamp DESC", - (template_hash,), - ) - return cursor.fetchall() - - def _aggregate_predictions( - self, rows: list[sqlite3.Row], tier: int, method: str - ) -> dict[str, Any]: - """Compute median-based predictions from a list of observations.""" - count = len(rows) - - bytes_values = [ - r["bytes_scanned"] for r in rows if r["bytes_scanned"] is not None - ] - time_values = [ - r["execution_time_ms"] for r in rows if r["execution_time_ms"] is not None - ] - credit_values = [ - r["credits_used"] for r in rows if r["credits_used"] is not None - ] - - predicted_bytes = int(statistics.median(bytes_values)) if bytes_values else None - predicted_time_ms = int(statistics.median(time_values)) if time_values else None - predicted_credits = ( - round(statistics.median(credit_values), 6) if credit_values else None - ) - - # Confidence based on observation count - if count >= 10: - confidence = "high" - elif count >= 5: - confidence = "medium" - else: - confidence = "low" - - return { - "tier": tier, - "confidence": confidence, - "predicted_bytes": predicted_bytes, - "predicted_time_ms": predicted_time_ms, - "predicted_credits": predicted_credits, - "method": method, - "observation_count": count, - } - - def _estimate_from_tables(self, sql: str, dialect: str) -> dict[str, Any] | None: - """Tier 3: Estimate cost based on historical data for the tables in the query. - - Looks up all observations involving the same tables (via template patterns) - and produces a rough average. Returns None if no relevant data is found. - """ - metadata = guard_extract_metadata(sql, dialect) - table_names = set() - for t in metadata.get("tables", []): - name = t.get("name", t) if isinstance(t, dict) else str(t) - if name: - table_names.add(name.upper()) - - if not table_names: - return None - - # If we have any fingerprint observations (even < 3), use them - fingerprint = self._fingerprint(sql, dialect) - rows = self._fetch_observations_by_fingerprint(fingerprint) - if rows: - # We have some observations but less than 3 (otherwise tier 1 would catch it) - return { - "predicted_bytes": self._safe_median( - [r["bytes_scanned"] for r in rows if r["bytes_scanned"] is not None] - ), - "predicted_time_ms": self._safe_median( - [ - r["execution_time_ms"] - for r in rows - if r["execution_time_ms"] is not None - ] - ), - "predicted_credits": self._safe_median_float( - [r["credits_used"] for r in rows if r["credits_used"] is not None] - ), - "observation_count": len(rows), - } - - # Check template observations - template_hash = self._template_hash(sql, dialect) - rows = self._fetch_observations_by_template(template_hash) - if rows: - return { - "predicted_bytes": self._safe_median( - [r["bytes_scanned"] for r in rows if r["bytes_scanned"] is not None] - ), - "predicted_time_ms": self._safe_median( - [ - r["execution_time_ms"] - for r in rows - if r["execution_time_ms"] is not None - ] - ), - "predicted_credits": self._safe_median_float( - [r["credits_used"] for r in rows if r["credits_used"] is not None] - ), - "observation_count": len(rows), - } - - return None - - # Dialect-specific base cost profiles for the static heuristic. - # bytes_scanned and credits are None for databases that don't expose them. - _HEURISTIC_PROFILES: dict[str, dict[str, int | float | None]] = { - "snowflake": { - "base_bytes": 10_000_000, - "base_time_ms": 500, - "base_credits": 0.001, - }, - "postgres": { - "base_bytes": None, - "base_time_ms": 100, - "base_credits": None, - }, - "duckdb": { - "base_bytes": None, - "base_time_ms": 10, - "base_credits": None, - }, - "bigquery": { - "base_bytes": 10_000_000, - "base_time_ms": 500, - "base_credits": None, - }, - "databricks": { - "base_bytes": 10_000_000, - "base_time_ms": 500, - "base_credits": None, - }, - } - - _DEFAULT_HEURISTIC_PROFILE: dict[str, int | float | None] = { - "base_bytes": 10_000_000, - "base_time_ms": 500, - "base_credits": 0.001, - } - - def _static_heuristic(self, sql: str, dialect: str) -> dict[str, Any]: - """Tier 4: Estimate cost based on query complexity analysis. - - Uses sqlguard complexity scoring, falling back to length-based heuristic. - Base costs are dialect-dependent: Snowflake uses bytes-scanned and - credit metrics, while Postgres and DuckDB use execution-time only. - """ - complexity = guard_complexity_score(sql) - complexity_score = complexity.get("total", complexity.get("score")) - if not complexity_score: - complexity_score = max(1.0, len(sql) / 100.0) - - # Select dialect-specific base costs - d = (dialect or "").lower() - profile = self._HEURISTIC_PROFILES.get(d, self._DEFAULT_HEURISTIC_PROFILE) - - base_bytes = profile["base_bytes"] - base_time_ms = profile["base_time_ms"] - base_credits = profile["base_credits"] - - predicted_bytes = ( - int(base_bytes * complexity_score) if base_bytes is not None else None - ) - predicted_time_ms = ( - int(base_time_ms * complexity_score) if base_time_ms is not None else None - ) - predicted_credits = ( - round(base_credits * complexity_score, 6) - if base_credits is not None - else None - ) - - return { - "tier": 4, - "confidence": "very_low", - "predicted_bytes": predicted_bytes, - "predicted_time_ms": predicted_time_ms, - "predicted_credits": predicted_credits, - "method": "static_heuristic", - "observation_count": 0, - } - - @staticmethod - def _safe_median(values: list[int]) -> int | None: - """Compute median of integer values, returning None for empty lists.""" - if not values: - return None - return int(statistics.median(values)) - - @staticmethod - def _safe_median_float(values: list[float]) -> float | None: - """Compute median of float values, returning None for empty lists.""" - if not values: - return None - return round(statistics.median(values), 6) - - def close(self) -> None: - """Close the database connection.""" - self._conn.close() - - def __del__(self) -> None: - """Ensure connection is closed on garbage collection.""" - try: - self._conn.close() - except Exception: - pass diff --git a/packages/altimate-engine/src/altimate_engine/sql/guard.py b/packages/altimate-engine/src/altimate_engine/sql/guard.py index 4aa6bdc212..de757a142a 100644 --- a/packages/altimate-engine/src/altimate_engine/sql/guard.py +++ b/packages/altimate-engine/src/altimate_engine/sql/guard.py @@ -14,9 +14,9 @@ try: import altimate_core - SQLGUARD_AVAILABLE = True + ALTIMATE_CORE_AVAILABLE = True except ImportError: - SQLGUARD_AVAILABLE = False + ALTIMATE_CORE_AVAILABLE = False _NOT_INSTALLED_MSG = "altimate-core not installed. Run: pip install altimate-core" @@ -83,7 +83,7 @@ def guard_validate( schema_context: dict[str, Any] | None = None, ) -> dict: """Validate SQL against schema using altimate_core.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -98,7 +98,7 @@ def guard_lint( schema_context: dict[str, Any] | None = None, ) -> dict: """Lint SQL for anti-patterns using altimate_core.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -109,7 +109,7 @@ def guard_lint( def guard_scan_safety(sql: str) -> dict: """Scan SQL for injection patterns and safety threats.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.scan_sql(sql) @@ -148,7 +148,7 @@ def _postprocess_qualify(sql: str) -> str: def guard_transpile(sql: str, from_dialect: str, to_dialect: str) -> dict: """Transpile SQL between dialects with IFF/QUALIFY pre/post-processing.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: processed = _preprocess_iff(sql) @@ -173,7 +173,7 @@ def guard_explain( schema_context: dict[str, Any] | None = None, ) -> dict: """Explain SQL query plan, lineage, and cost signals.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -191,7 +191,7 @@ def guard_check( altimate_core.check was removed; this composes validate + lint + scan_sql. """ - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -219,7 +219,7 @@ def guard_fix( max_iterations: int = 5, ) -> dict: """Auto-fix SQL errors via fuzzy matching and re-validation.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -235,7 +235,7 @@ def guard_check_policy( schema_context: dict[str, Any] | None = None, ) -> dict: """Check SQL against JSON-based governance guardrails.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -244,28 +244,13 @@ def guard_check_policy( return {"success": False, "error": str(e)} -def guard_complexity_score( - sql: str, - schema_path: str = "", - schema_context: dict[str, Any] | None = None, -) -> dict: - """Score multi-dimensional complexity and estimated cloud cost.""" - if not SQLGUARD_AVAILABLE: - return _not_installed_result() - try: - schema = _schema_or_empty(schema_path, schema_context) - return altimate_core.complexity_score(sql, schema) - except Exception as e: - return {"success": False, "error": str(e)} - - def guard_check_semantics( sql: str, schema_path: str = "", schema_context: dict[str, Any] | None = None, ) -> dict: """Run 10 semantic validation rules against SQL.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -280,7 +265,7 @@ def guard_generate_tests( schema_context: dict[str, Any] | None = None, ) -> dict: """Generate automated SQL test cases.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -301,7 +286,7 @@ def guard_check_equivalence( schema_context: dict[str, Any] | None = None, ) -> dict: """Check semantic equivalence of two queries.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -316,7 +301,7 @@ def guard_analyze_migration( dialect: str = "", ) -> dict: """Analyze DDL migration safety (data loss, type narrowing, defaults).""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.analyze_migration(old_ddl, new_ddl, dialect or "generic") @@ -331,7 +316,7 @@ def guard_diff_schemas( schema2_context: dict[str, Any] | None = None, ) -> dict: """Diff two schemas with breaking change detection.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: s1 = _schema_or_empty(schema1_path, schema1_context) @@ -347,7 +332,7 @@ def guard_rewrite( schema_context: dict[str, Any] | None = None, ) -> dict: """Suggest query optimization rewrites.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -362,7 +347,7 @@ def guard_correct( schema_context: dict[str, Any] | None = None, ) -> dict: """Iterative propose-verify-refine correction loop.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -377,7 +362,7 @@ def guard_evaluate( schema_context: dict[str, Any] | None = None, ) -> dict: """Grade SQL quality on A-F scale.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -386,22 +371,6 @@ def guard_evaluate( return {"success": False, "error": str(e)} -def guard_estimate_cost( - sql: str, - schema_path: str = "", - schema_context: dict[str, Any] | None = None, - dialect: str = "", -) -> dict: - """Estimate per-dialect cloud cost (bytes scanned, USD).""" - if not SQLGUARD_AVAILABLE: - return _not_installed_result() - try: - schema = _schema_or_empty(schema_path, schema_context) - return altimate_core.estimate_cost(sql, schema, dialect or "generic") - except Exception as e: - return {"success": False, "error": str(e)} - - # --------------------------------------------------------------------------- # Phase 3 (P2): Complete coverage # --------------------------------------------------------------------------- @@ -412,7 +381,7 @@ def guard_classify_pii( schema_context: dict[str, Any] | None = None, ) -> dict: """Classify PII columns in schema.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -427,7 +396,7 @@ def guard_check_query_pii( schema_context: dict[str, Any] | None = None, ) -> dict: """Analyze query-level PII exposure.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -442,7 +411,7 @@ def guard_resolve_term( schema_context: dict[str, Any] | None = None, ) -> dict: """Fuzzy match business glossary term to schema elements.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -481,7 +450,7 @@ def guard_column_lineage( default_schema: str = "", ) -> dict: """Schema-aware column lineage (requires altimate_core.init).""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: _ensure_init() @@ -503,7 +472,7 @@ def guard_track_lineage( schema_context: dict[str, Any] | None = None, ) -> dict: """Track lineage across multiple queries (requires altimate_core.init).""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: _ensure_init() @@ -515,7 +484,7 @@ def guard_track_lineage( def guard_format_sql(sql: str, dialect: str = "") -> dict: """Rust-powered SQL formatting.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.format_sql(sql, dialect or "generic") @@ -525,7 +494,7 @@ def guard_format_sql(sql: str, dialect: str = "") -> dict: def guard_extract_metadata(sql: str, dialect: str = "") -> dict: """Extract tables, columns, functions, CTEs from SQL.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.extract_metadata(sql, dialect or "generic") @@ -535,7 +504,7 @@ def guard_extract_metadata(sql: str, dialect: str = "") -> dict: def guard_compare_queries(left_sql: str, right_sql: str, dialect: str = "") -> dict: """Structural comparison of two queries.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.compare_queries(left_sql, right_sql, dialect or "generic") @@ -550,7 +519,7 @@ def guard_complete( schema_context: dict[str, Any] | None = None, ) -> dict: """Cursor-aware SQL completion suggestions.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -564,7 +533,7 @@ def guard_optimize_context( schema_context: dict[str, Any] | None = None, ) -> dict: """5-level progressive disclosure for context window optimization.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -579,7 +548,7 @@ def guard_optimize_for_query( schema_context: dict[str, Any] | None = None, ) -> dict: """Query-aware schema reduction — prune to relevant tables/columns.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -594,7 +563,7 @@ def guard_prune_schema( schema_context: dict[str, Any] | None = None, ) -> dict: """Filter schema to only referenced tables/columns.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -605,7 +574,7 @@ def guard_prune_schema( def guard_import_ddl(ddl: str, dialect: str = "") -> dict: """Parse CREATE TABLE DDL into schema definition.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: result = altimate_core.import_ddl(ddl, dialect or "generic") @@ -622,7 +591,7 @@ def guard_export_ddl( schema_context: dict[str, Any] | None = None, ) -> dict: """Export schema as CREATE TABLE DDL statements.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -640,7 +609,7 @@ def guard_schema_fingerprint( schema_context: dict[str, Any] | None = None, ) -> dict: """Compute SHA-256 fingerprint of schema for caching.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: schema = _schema_or_empty(schema_path, schema_context) @@ -659,7 +628,7 @@ def guard_introspection_sql( schema_name: str | None = None, ) -> dict: """Generate INFORMATION_SCHEMA introspection queries per dialect.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.introspection_sql(db_type, database, schema_name) @@ -669,7 +638,7 @@ def guard_introspection_sql( def guard_parse_dbt_project(project_dir: str) -> dict: """Parse dbt project directory for analysis.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: return altimate_core.parse_dbt_project(project_dir) @@ -679,7 +648,7 @@ def guard_parse_dbt_project(project_dir: str) -> dict: def guard_is_safe(sql: str) -> dict: """Quick boolean safety check.""" - if not SQLGUARD_AVAILABLE: + if not ALTIMATE_CORE_AVAILABLE: return _not_installed_result() try: result = altimate_core.is_safe(sql) diff --git a/packages/altimate-engine/tests/test_cost_gate.py b/packages/altimate-engine/tests/test_cost_gate.py deleted file mode 100644 index b5eeea4b1c..0000000000 --- a/packages/altimate-engine/tests/test_cost_gate.py +++ /dev/null @@ -1,176 +0,0 @@ -"""Tests for ci/cost_gate.py — CI cost gate scanner.""" - -import os -import tempfile - -import pytest - -from altimate_engine.ci.cost_gate import scan_files, _has_jinja, _split_statements - - -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- - - -def _write_temp_sql(content: str, suffix: str = ".sql") -> str: - """Write content to a temp file and return the path.""" - fd, path = tempfile.mkstemp(suffix=suffix) - with os.fdopen(fd, "w") as f: - f.write(content) - return path - - -# --------------------------------------------------------------------------- -# Unit tests: helper functions -# --------------------------------------------------------------------------- - - -class TestHasJinja: - def test_no_jinja(self): - assert _has_jinja("SELECT * FROM orders") is False - - def test_double_brace(self): - assert _has_jinja("SELECT * FROM {{ ref('orders') }}") is True - - def test_block_tag(self): - assert _has_jinja("{% if flag %}SELECT 1{% endif %}") is True - - def test_comment_tag(self): - assert _has_jinja("{# this is a comment #}") is True - - -class TestSplitStatements: - def test_single_statement(self): - assert _split_statements("SELECT 1") == ["SELECT 1"] - - def test_multiple_statements(self): - result = _split_statements("SELECT 1; SELECT 2;") - assert result == ["SELECT 1", "SELECT 2"] - - def test_empty_string(self): - assert _split_statements("") == [] - - def test_trailing_semicolons(self): - result = _split_statements("SELECT 1;; ;") - assert result == ["SELECT 1"] - - -# --------------------------------------------------------------------------- -# Integration tests: scan_files -# --------------------------------------------------------------------------- - - -class TestScanFiles: - def test_clean_file_passes(self): - path = _write_temp_sql("SELECT id, name FROM users LIMIT 10") - try: - result = scan_files([path]) - assert result["success"] - assert result["passed"] - assert result["exit_code"] == 0 - assert result["files_scanned"] == 1 - finally: - os.unlink(path) - - def test_cartesian_product_has_warnings(self): - """CROSS JOIN produces lint warnings (SELECT *, missing aliases, no LIMIT).""" - path = _write_temp_sql("SELECT * FROM a CROSS JOIN b") - try: - result = scan_files([path]) - assert result["success"] - assert result["total_issues"] > 0 - finally: - os.unlink(path) - - def test_skip_non_sql(self): - path = _write_temp_sql("not sql content", suffix=".py") - try: - result = scan_files([path]) - assert result["success"] - assert result["passed"] - assert result["files_skipped"] == 1 - assert result["files_scanned"] == 0 - finally: - os.unlink(path) - - def test_skip_jinja(self): - path = _write_temp_sql("SELECT * FROM {{ ref('orders') }} LIMIT 10") - try: - result = scan_files([path]) - assert result["success"] - assert result["passed"] - assert result["files_skipped"] == 1 - finally: - os.unlink(path) - - def test_missing_file(self): - result = scan_files(["/nonexistent/path/file.sql"]) - assert result["success"] - assert result["passed"] - assert result["files_skipped"] == 1 - - def test_empty_file_list(self): - result = scan_files([]) - assert result["success"] - assert result["passed"] - assert result["files_scanned"] == 0 - - def test_multiple_files_mixed(self): - clean_path = _write_temp_sql("SELECT id FROM users LIMIT 10") - warn_path = _write_temp_sql("SELECT * FROM a CROSS JOIN b") - try: - result = scan_files([clean_path, warn_path]) - assert result["success"] - assert result["files_scanned"] == 2 - - # Check per-file results - file_statuses = {fr["file"]: fr["status"] for fr in result["file_results"]} - assert file_statuses[clean_path] == "pass" - # CROSS JOIN only produces warnings, not errors/critical - assert file_statuses[warn_path] == "pass" - finally: - os.unlink(clean_path) - os.unlink(warn_path) - - def test_multiple_statements_in_file(self): - """Multiple statements: lint runs on each; warnings don't fail the gate.""" - path = _write_temp_sql("SELECT 1; SELECT * FROM a CROSS JOIN b;") - try: - result = scan_files([path]) - assert result["success"] - assert result["total_issues"] > 0 - finally: - os.unlink(path) - - def test_warnings_still_pass(self): - """Files with only warning-level issues should pass the gate.""" - path = _write_temp_sql("SELECT * FROM orders") - try: - result = scan_files([path]) - assert result["success"] - assert result["passed"] # SELECT * is warning, not critical - # Lint produces warnings for SELECT * and missing LIMIT - assert result["total_issues"] >= 0 - finally: - os.unlink(path) - - def test_dialect_parameter(self): - path = _write_temp_sql("SELECT id FROM users LIMIT 10") - try: - result = scan_files([path], dialect="postgres") - assert result["success"] - assert result["passed"] - finally: - os.unlink(path) - - def test_parse_error_skipped(self): - """Unparseable SQL within a file should be skipped, not crash.""" - path = _write_temp_sql("SELEC * FORM orders") - try: - result = scan_files([path]) - assert result["success"] - # Parse error is not critical — should still pass - assert result["passed"] - finally: - os.unlink(path) diff --git a/packages/altimate-engine/tests/test_feedback_store.py b/packages/altimate-engine/tests/test_feedback_store.py deleted file mode 100644 index a6ba47c711..0000000000 --- a/packages/altimate-engine/tests/test_feedback_store.py +++ /dev/null @@ -1,405 +0,0 @@ -"""Tests for sql/feedback_store.py — query execution metrics and cost prediction.""" - -import os -import tempfile - -import pytest - -from altimate_engine.sql.feedback_store import FeedbackStore, _regex_strip_literals - - -@pytest.fixture -def store(tmp_path): - """Create a FeedbackStore backed by a temp SQLite DB.""" - db_path = str(tmp_path / "test_feedback.db") - s = FeedbackStore(db_path=db_path) - yield s - s.close() - - -@pytest.fixture -def populated_store(store): - """Store with 5 observations of the same query.""" - sql = "SELECT id, name FROM users WHERE status = 'active'" - for i in range(5): - store.record( - sql=sql, - dialect="snowflake", - bytes_scanned=1_000_000 + i * 100_000, - rows_produced=1000 + i * 100, - execution_time_ms=200 + i * 50, - credits_used=0.001 + i * 0.0002, - warehouse_size="X-SMALL", - ) - return store - - -class TestFeedbackStoreInitialization: - """Schema creation and DB setup.""" - - def test_creates_database_file(self, tmp_path): - """The store should create the SQLite file on init.""" - db_path = str(tmp_path / "init_test.db") - assert not os.path.exists(db_path) - s = FeedbackStore(db_path=db_path) - assert os.path.exists(db_path) - s.close() - - def test_creates_table_and_indexes(self, store): - """query_feedback table and indexes should exist after init.""" - cursor = store._conn.execute( - "SELECT name FROM sqlite_master WHERE type='table' AND name='query_feedback'" - ) - assert cursor.fetchone() is not None - - cursor = store._conn.execute( - "SELECT name FROM sqlite_master WHERE type='index' AND name='idx_fingerprint'" - ) - assert cursor.fetchone() is not None - - cursor = store._conn.execute( - "SELECT name FROM sqlite_master WHERE type='index' AND name='idx_template'" - ) - assert cursor.fetchone() is not None - - def test_idempotent_init(self, tmp_path): - """Opening the same DB twice should not fail (IF NOT EXISTS).""" - db_path = str(tmp_path / "idem.db") - s1 = FeedbackStore(db_path=db_path) - s1.close() - s2 = FeedbackStore(db_path=db_path) - s2.close() - - def test_default_db_path_fallback(self): - """When no path is given, it uses ~/.altimate/feedback.db.""" - from altimate_engine.sql.feedback_store import _default_db_path - - default = _default_db_path() - assert "feedback.db" in default - assert ".altimate" in default - - -class TestRecord: - """Recording execution metrics.""" - - def test_record_inserts_row(self, store): - """record() should insert exactly one row.""" - store.record( - sql="SELECT 1", - bytes_scanned=100, - rows_produced=1, - execution_time_ms=10, - ) - cursor = store._conn.execute("SELECT COUNT(*) FROM query_feedback") - assert cursor.fetchone()[0] == 1 - - def test_record_with_all_fields(self, store): - """All fields should be stored correctly.""" - store.record( - sql="SELECT * FROM orders", - dialect="snowflake", - bytes_scanned=5_000_000, - rows_produced=10000, - execution_time_ms=500, - credits_used=0.005, - warehouse_size="MEDIUM", - ) - cursor = store._conn.execute("SELECT * FROM query_feedback") - row = cursor.fetchone() - assert row["bytes_scanned"] == 5_000_000 - assert row["rows_produced"] == 10000 - assert row["execution_time_ms"] == 500 - assert row["credits_used"] == 0.005 - assert row["warehouse_size"] == "MEDIUM" - assert row["dialect"] == "snowflake" - assert row["timestamp"] is not None - - def test_record_with_none_fields(self, store): - """Optional fields can be None.""" - store.record(sql="SELECT 1") - cursor = store._conn.execute("SELECT * FROM query_feedback") - row = cursor.fetchone() - assert row["bytes_scanned"] is None - assert row["credits_used"] is None - - def test_record_multiple_queries(self, store): - """Multiple records should accumulate.""" - store.record(sql="SELECT 1", bytes_scanned=100) - store.record(sql="SELECT 2", bytes_scanned=200) - store.record(sql="SELECT 3", bytes_scanned=300) - cursor = store._conn.execute("SELECT COUNT(*) FROM query_feedback") - assert cursor.fetchone()[0] == 3 - - -class TestFingerprint: - """Fingerprint generation consistency.""" - - def test_same_query_same_fingerprint(self, store): - """Identical SQL should produce the same fingerprint.""" - fp1 = store._fingerprint("SELECT id FROM users WHERE id = 1", "snowflake") - fp2 = store._fingerprint("SELECT id FROM users WHERE id = 1", "snowflake") - assert fp1 == fp2 - - def test_different_literals_same_fingerprint(self, store): - """Queries differing only in literal values should share a fingerprint.""" - fp1 = store._fingerprint("SELECT id FROM users WHERE id = 1", "snowflake") - fp2 = store._fingerprint("SELECT id FROM users WHERE id = 42", "snowflake") - assert fp1 == fp2 - - def test_different_string_literals_same_fingerprint(self, store): - """Queries differing only in string literals should share a fingerprint.""" - fp1 = store._fingerprint("SELECT * FROM users WHERE name = 'alice'", "snowflake") - fp2 = store._fingerprint("SELECT * FROM users WHERE name = 'bob'", "snowflake") - assert fp1 == fp2 - - def test_different_structure_different_fingerprint(self, store): - """Structurally different queries should have different fingerprints.""" - fp1 = store._fingerprint("SELECT id FROM users", "snowflake") - fp2 = store._fingerprint("SELECT id FROM orders", "snowflake") - assert fp1 != fp2 - - def test_fingerprint_is_hex_hash(self, store): - """Fingerprint should be a hex-encoded SHA256 hash (64 chars).""" - fp = store._fingerprint("SELECT 1", "snowflake") - assert len(fp) == 64 - assert all(c in "0123456789abcdef" for c in fp) - - -class TestTemplateHash: - """Template hash normalization.""" - - def test_same_template_same_hash(self, store): - """Same query template with different values should produce the same hash.""" - h1 = store._template_hash("SELECT * FROM t WHERE x = 1 AND y = 'a'", "snowflake") - h2 = store._template_hash("SELECT * FROM t WHERE x = 99 AND y = 'z'", "snowflake") - assert h1 == h2 - - def test_different_template_different_hash(self, store): - """Different query structures produce different template hashes.""" - h1 = store._template_hash("SELECT * FROM t WHERE x = 1", "snowflake") - h2 = store._template_hash("SELECT * FROM t WHERE x = 1 AND y = 2", "snowflake") - assert h1 != h2 - - def test_template_hash_is_hex(self, store): - """Template hash should be a hex-encoded SHA256.""" - h = store._template_hash("SELECT 1", "snowflake") - assert len(h) == 64 - - -class TestRegexStripLiterals: - """The regex fallback for literal stripping.""" - - def test_strips_string_literals(self): - result = _regex_strip_literals("SELECT * FROM t WHERE name = 'alice'") - assert "'alice'" not in result - assert "'?'" in result - - def test_strips_numeric_literals(self): - result = _regex_strip_literals("SELECT * FROM t WHERE id = 42") - assert "42" not in result - assert "?" in result - - def test_normalizes_whitespace(self): - result = _regex_strip_literals("SELECT * FROM t") - assert " " not in result - - def test_uppercases_result(self): - result = _regex_strip_literals("select * from users") - assert result == result.upper() - - -class TestPredictTier1Fingerprint: - """Tier 1: Fingerprint match with >= 3 observations.""" - - def test_tier1_with_exact_query(self, populated_store): - """With 5 observations of the same query, predict should use tier 1.""" - prediction = populated_store.predict("SELECT id, name FROM users WHERE status = 'active'") - assert prediction["tier"] == 1 - assert prediction["method"] == "fingerprint_match" - assert prediction["observation_count"] == 5 - assert prediction["predicted_bytes"] is not None - assert prediction["predicted_time_ms"] is not None - assert prediction["predicted_credits"] is not None - - def test_tier1_with_different_literal(self, populated_store): - """Same structure different literal should also match fingerprint.""" - prediction = populated_store.predict("SELECT id, name FROM users WHERE status = 'inactive'") - assert prediction["tier"] == 1 - assert prediction["method"] == "fingerprint_match" - - def test_tier1_confidence_levels(self, store): - """Confidence depends on observation count.""" - sql = "SELECT * FROM confidence_test WHERE x = 1" - # 3 observations => low confidence - for i in range(3): - store.record(sql=sql, bytes_scanned=1000, execution_time_ms=100, credits_used=0.001) - pred = store.predict(sql) - assert pred["confidence"] == "low" - - # Add to 5 => medium - for i in range(2): - store.record(sql=sql, bytes_scanned=1000, execution_time_ms=100, credits_used=0.001) - pred = store.predict(sql) - assert pred["confidence"] == "medium" - - # Add to 10 => high - for i in range(5): - store.record(sql=sql, bytes_scanned=1000, execution_time_ms=100, credits_used=0.001) - pred = store.predict(sql) - assert pred["confidence"] == "high" - - -class TestPredictTier2Template: - """Tier 2: Template match with >= 3 observations.""" - - def test_tier2_template_match(self, store): - """Queries with same template (structure) should match at tier 2 if fingerprint has < 3.""" - # Record 3 observations with different WHERE values but same structure - # Use sufficiently different SQL to get different fingerprints but same template - base_sql = "SELECT id, name FROM users WHERE id = {}" - for i in range(3): - store.record( - sql=base_sql.format(i + 1), - bytes_scanned=2_000_000, - execution_time_ms=300, - credits_used=0.003, - ) - # Predict for a new literal value - prediction = store.predict(base_sql.format(999)) - # Should match at tier 1 or 2 (fingerprint normalizes literals, so tier 1 is likely) - assert prediction["tier"] in (1, 2) - assert prediction["predicted_bytes"] is not None - - -class TestPredictTier3TableEstimate: - """Tier 3: Table-based estimation when < 3 fingerprint or template matches.""" - - def test_tier3_with_few_observations(self, store): - """With only 1-2 observations, tier 3 should kick in if table extraction works, - otherwise falls through to tier 4 (heuristic).""" - sql = "SELECT * FROM orders WHERE amount > 100" - store.record(sql=sql, bytes_scanned=5_000_000, execution_time_ms=400, credits_used=0.004) - prediction = store.predict(sql) - # Tier 3 requires table extraction; if metadata returns empty tables, falls to tier 4 - assert prediction["tier"] in (3, 4) - assert prediction["predicted_bytes"] is not None - - -class TestPredictTier4Heuristic: - """Tier 4: Static heuristic with no prior observations.""" - - def test_tier4_no_observations(self, store): - """With no observations at all, tier 4 heuristic should be used.""" - prediction = store.predict("SELECT * FROM brand_new_table WHERE x = 1") - assert prediction["tier"] == 4 - assert prediction["confidence"] == "very_low" - assert prediction["method"] == "static_heuristic" - assert prediction["observation_count"] == 0 - assert prediction["predicted_bytes"] > 0 - assert prediction["predicted_time_ms"] > 0 - assert prediction["predicted_credits"] > 0 - - def test_tier4_complexity_scaling(self, store): - """More complex queries should produce equal or higher cost estimates.""" - simple = store.predict("SELECT 1") - complex_q = store.predict(""" - SELECT a.id, b.name, c.total - FROM orders a - JOIN customers b ON a.customer_id = b.id - JOIN order_totals c ON a.id = c.order_id - WHERE a.status = 'active' - ORDER BY c.total DESC - """) - assert complex_q["predicted_bytes"] >= simple["predicted_bytes"] - assert complex_q["predicted_time_ms"] >= simple["predicted_time_ms"] - - def test_tier4_with_aggregation(self, store): - """Aggregation queries should have higher complexity.""" - simple = store.predict("SELECT id FROM t") - agg = store.predict("SELECT COUNT(*), SUM(amount) FROM orders GROUP BY status") - assert agg["predicted_bytes"] >= simple["predicted_bytes"] - - def test_tier4_with_window_functions(self, store): - """Window functions should increase complexity.""" - base = store.predict("SELECT id FROM t") - windowed = store.predict("SELECT id, ROW_NUMBER() OVER (ORDER BY id) FROM t") - assert windowed["predicted_bytes"] >= base["predicted_bytes"] - - def test_tier4_cross_join_high_complexity(self, store): - """CROSS JOINs should significantly increase the estimate.""" - simple = store.predict("SELECT id FROM t") - cross = store.predict("SELECT * FROM a CROSS JOIN b") - assert cross["predicted_bytes"] > simple["predicted_bytes"] - - def test_tier4_unparseable_sql_falls_back_to_length(self, store): - """If SQL can't be parsed, heuristic uses length.""" - # This is valid-ish but may or may not parse - prediction = store.predict("INVALID SQL THAT WILL NOT PARSE !@#$") - assert prediction["tier"] == 4 - assert prediction["method"] == "static_heuristic" - - -class TestPredictMedianCalculation: - """Verify median-based aggregation.""" - - def test_median_of_three(self, store): - """With 3 observations, median should be the middle value.""" - sql = "SELECT * FROM median_test WHERE x = 1" - store.record(sql=sql, bytes_scanned=100, execution_time_ms=10, credits_used=0.001) - store.record(sql=sql, bytes_scanned=200, execution_time_ms=20, credits_used=0.002) - store.record(sql=sql, bytes_scanned=300, execution_time_ms=30, credits_used=0.003) - pred = store.predict(sql) - assert pred["predicted_bytes"] == 200 - assert pred["predicted_time_ms"] == 20 - assert pred["predicted_credits"] == 0.002 - - def test_median_with_none_values(self, store): - """None values in observations should be excluded from median.""" - sql = "SELECT * FROM partial_data WHERE x = 1" - store.record(sql=sql, bytes_scanned=100, execution_time_ms=None, credits_used=None) - store.record(sql=sql, bytes_scanned=200, execution_time_ms=None, credits_used=None) - store.record(sql=sql, bytes_scanned=300, execution_time_ms=None, credits_used=None) - pred = store.predict(sql) - assert pred["predicted_bytes"] == 200 - assert pred["predicted_time_ms"] is None - assert pred["predicted_credits"] is None - - -class TestSafeMedian: - """Test _safe_median and _safe_median_float static methods.""" - - def test_safe_median_empty(self): - assert FeedbackStore._safe_median([]) is None - - def test_safe_median_single(self): - assert FeedbackStore._safe_median([42]) == 42 - - def test_safe_median_even_count(self): - result = FeedbackStore._safe_median([10, 20]) - assert result == 15 - - def test_safe_median_float_empty(self): - assert FeedbackStore._safe_median_float([]) is None - - def test_safe_median_float_precision(self): - result = FeedbackStore._safe_median_float([0.001, 0.002, 0.003]) - assert result == 0.002 - - -class TestStoreClose: - """Test cleanup.""" - - def test_close(self, tmp_path): - db_path = str(tmp_path / "close_test.db") - s = FeedbackStore(db_path=db_path) - s.close() - # After close, operations should fail - with pytest.raises(Exception): - s._conn.execute("SELECT 1") - - def test_del_is_safe(self, tmp_path): - """__del__ should not raise even if called multiple times.""" - db_path = str(tmp_path / "del_test.db") - s = FeedbackStore(db_path=db_path) - s.close() - s.__del__() # Should not raise diff --git a/packages/altimate-engine/tests/test_guard.py b/packages/altimate-engine/tests/test_guard.py index 9a2ed11161..fb76c23c5f 100644 --- a/packages/altimate-engine/tests/test_guard.py +++ b/packages/altimate-engine/tests/test_guard.py @@ -1,4 +1,4 @@ -"""Tests for the sqlguard Python wrapper.""" +"""Tests for the altimate-core Python wrapper.""" import json import os @@ -9,7 +9,7 @@ import yaml from altimate_engine.sql.guard import ( - SQLGUARD_AVAILABLE, + ALTIMATE_CORE_AVAILABLE, guard_validate, guard_lint, guard_scan_safety, @@ -22,9 +22,9 @@ ) -# Skip all tests if sqlguard is not installed +# Skip all tests if altimate-core is not installed pytestmark = pytest.mark.skipif( - not SQLGUARD_AVAILABLE, reason="sqlguard not installed" + not ALTIMATE_CORE_AVAILABLE, reason="altimate-core not installed" ) @@ -168,40 +168,40 @@ def test_lint_with_schema_context(self): class TestGracefulFallback: - """Test behavior when sqlguard is not installed.""" + """Test behavior when altimate-core is not installed.""" def test_validate_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_validate("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_lint_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_lint("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_safety_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_scan_safety("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_transpile_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_transpile("SELECT 1", "generic", "postgres") assert result["success"] is False assert "not installed" in result["error"] def test_explain_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_explain("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_check_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_check("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] diff --git a/packages/altimate-engine/tests/test_guard_new.py b/packages/altimate-engine/tests/test_guard_new.py index bb4920251b..e6abb744be 100644 --- a/packages/altimate-engine/tests/test_guard_new.py +++ b/packages/altimate-engine/tests/test_guard_new.py @@ -1,6 +1,6 @@ -"""Tests for the new sqlguard Python wrapper functions (Phases 1-3). +"""Tests for the new altimate-core Python wrapper functions (Phases 1-3). -Updated for new sqlguard API: Schema objects instead of path strings, +Updated for new altimate-core API: Schema objects instead of path strings, dicts returned directly, renamed/removed params. """ @@ -13,11 +13,10 @@ import yaml from altimate_engine.sql.guard import ( - SQLGUARD_AVAILABLE, + ALTIMATE_CORE_AVAILABLE, # Phase 1 (P0) guard_fix, guard_check_policy, - guard_complexity_score, guard_check_semantics, guard_generate_tests, # Phase 2 (P1) @@ -27,7 +26,6 @@ guard_rewrite, guard_correct, guard_evaluate, - guard_estimate_cost, # Phase 3 (P2) guard_classify_pii, guard_check_query_pii, @@ -50,7 +48,7 @@ ) -# Schema context in the format sqlguard expects +# Schema context in the format altimate-core expects SCHEMA_CTX = { "tables": { "users": { @@ -85,9 +83,9 @@ } -# Skip all tests if sqlguard is not installed +# Skip all tests if altimate-core is not installed pytestmark = pytest.mark.skipif( - not SQLGUARD_AVAILABLE, reason="sqlguard not installed" + not ALTIMATE_CORE_AVAILABLE, reason="altimate-core not installed" ) @@ -133,26 +131,6 @@ def test_policy_with_schema_context(self): assert isinstance(result, dict) -class TestGuardComplexityScore: - def test_simple_query(self): - result = guard_complexity_score("SELECT 1") - assert isinstance(result, dict) - - def test_complex_query(self): - result = guard_complexity_score( - "SELECT u.id, o.total FROM users u JOIN orders o ON u.id = o.user_id " - "WHERE o.total > 100 GROUP BY u.id HAVING COUNT(*) > 5" - ) - assert isinstance(result, dict) - - def test_with_schema_context(self): - result = guard_complexity_score("SELECT 1", schema_context=SIMPLE_SCHEMA) - assert isinstance(result, dict) - - def test_empty_sql(self): - result = guard_complexity_score("") - assert isinstance(result, dict) - class TestGuardCheckSemantics: def test_basic_semantics(self): @@ -318,26 +296,6 @@ def test_empty_sql(self): assert isinstance(result, dict) -class TestGuardEstimateCost: - def test_basic_cost(self): - result = guard_estimate_cost("SELECT * FROM orders") - assert isinstance(result, dict) - - def test_with_dialect(self): - result = guard_estimate_cost("SELECT * FROM orders", dialect="snowflake") - assert isinstance(result, dict) - - def test_complex_query(self): - result = guard_estimate_cost( - "SELECT u.id, SUM(o.total) FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.id", - dialect="bigquery", - ) - assert isinstance(result, dict) - - def test_empty_sql(self): - result = guard_estimate_cost("") - assert isinstance(result, dict) - # --------------------------------------------------------------------------- # Phase 3 (P2): Complete coverage @@ -598,41 +556,35 @@ def test_empty_sql(self): # --------------------------------------------------------------------------- -# Graceful Fallback Tests (when sqlguard is not installed) +# Graceful Fallback Tests (when altimate-core is not installed) # --------------------------------------------------------------------------- class TestGracefulFallbackNew: - """Test all new functions return proper fallback when sqlguard is not installed.""" + """Test all new functions return proper fallback when altimate-core is not installed.""" # Phase 1 (P0) def test_fix_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_fix("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_check_policy_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_check_policy("SELECT 1", "{}") assert result["success"] is False assert "not installed" in result["error"] - def test_complexity_score_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): - result = guard_complexity_score("SELECT 1") - assert result["success"] is False - assert "not installed" in result["error"] - def test_check_semantics_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_check_semantics("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_generate_tests_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_generate_tests("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] @@ -640,153 +592,147 @@ def test_generate_tests_fallback(self): # Phase 2 (P1) def test_check_equivalence_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_check_equivalence("SELECT 1", "SELECT 2") assert result["success"] is False assert "not installed" in result["error"] def test_analyze_migration_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_analyze_migration("CREATE TABLE t (id INT);", "CREATE TABLE t (id INT, x INT);") assert result["success"] is False assert "not installed" in result["error"] def test_diff_schemas_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_diff_schemas("/a.yaml", "/b.yaml") assert result["success"] is False assert "not installed" in result["error"] def test_rewrite_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_rewrite("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_correct_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_correct("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_evaluate_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_evaluate("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] - def test_estimate_cost_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): - result = guard_estimate_cost("SELECT 1") - assert result["success"] is False - assert "not installed" in result["error"] - # Phase 3 (P2) def test_classify_pii_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_classify_pii() assert result["success"] is False assert "not installed" in result["error"] def test_check_query_pii_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_check_query_pii("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_resolve_term_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_resolve_term("customer") assert result["success"] is False assert "not installed" in result["error"] def test_column_lineage_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_column_lineage("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_track_lineage_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_track_lineage(["SELECT 1"]) assert result["success"] is False assert "not installed" in result["error"] def test_format_sql_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_format_sql("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_extract_metadata_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_extract_metadata("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_compare_queries_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_compare_queries("SELECT 1", "SELECT 2") assert result["success"] is False assert "not installed" in result["error"] def test_complete_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_complete("SELECT ", 7) assert result["success"] is False assert "not installed" in result["error"] def test_optimize_context_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_optimize_context() assert result["success"] is False assert "not installed" in result["error"] def test_optimize_for_query_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_optimize_for_query("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_prune_schema_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_prune_schema("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] def test_import_ddl_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_import_ddl("CREATE TABLE t (id INT)") assert result["success"] is False assert "not installed" in result["error"] def test_export_ddl_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_export_ddl() assert result["success"] is False assert "not installed" in result["error"] def test_schema_fingerprint_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_schema_fingerprint() assert result["success"] is False assert "not installed" in result["error"] def test_introspection_sql_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_introspection_sql("postgres", "mydb") assert result["success"] is False assert "not installed" in result["error"] def test_parse_dbt_project_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_parse_dbt_project("/some/dir") assert result["success"] is False assert "not installed" in result["error"] def test_is_safe_fallback(self): - with patch("altimate_engine.sql.guard.SQLGUARD_AVAILABLE", False): + with patch("altimate_engine.sql.guard.ALTIMATE_CORE_AVAILABLE", False): result = guard_is_safe("SELECT 1") assert result["success"] is False assert "not installed" in result["error"] diff --git a/packages/altimate-engine/tests/test_server.py b/packages/altimate-engine/tests/test_server.py index 360694bef0..f6350620f8 100644 --- a/packages/altimate-engine/tests/test_server.py +++ b/packages/altimate-engine/tests/test_server.py @@ -50,32 +50,6 @@ def test_invalid_params(self): response = dispatch(request) assert response.error is not None - def test_sql_record_feedback(self): - request = JsonRpcRequest( - method="sql.record_feedback", - params={ - "sql": "SELECT 1", - "dialect": "snowflake", - "bytes_scanned": 1000, - "execution_time_ms": 100, - }, - id=8, - ) - response = dispatch(request) - assert response.error is None - assert response.result["recorded"] is True - - def test_sql_predict_cost(self): - request = JsonRpcRequest( - method="sql.predict_cost", - params={"sql": "SELECT 1", "dialect": "snowflake"}, - id=9, - ) - response = dispatch(request) - assert response.error is None - assert "tier" in response.result - assert "confidence" in response.result - def test_warehouse_list(self): request = JsonRpcRequest(method="warehouse.list", params={}, id=10) response = dispatch(request) diff --git a/packages/altimate-engine/tests/test_server_guard.py b/packages/altimate-engine/tests/test_server_guard.py index d81a083508..6c76c8fa93 100644 --- a/packages/altimate-engine/tests/test_server_guard.py +++ b/packages/altimate-engine/tests/test_server_guard.py @@ -1,22 +1,22 @@ -"""Tests for sqlguard JSON-RPC server dispatch.""" +"""Tests for altimate-core JSON-RPC server dispatch.""" import pytest from altimate_engine.models import JsonRpcRequest from altimate_engine.server import dispatch -from altimate_engine.sql.guard import SQLGUARD_AVAILABLE +from altimate_engine.sql.guard import ALTIMATE_CORE_AVAILABLE -# Skip all tests if sqlguard is not installed +# Skip all tests if altimate-core is not installed pytestmark = pytest.mark.skipif( - not SQLGUARD_AVAILABLE, reason="sqlguard not installed" + not ALTIMATE_CORE_AVAILABLE, reason="altimate-core not installed" ) -class TestSqlGuardValidateDispatch: +class TestAltimateCoreValidateDispatch: def test_basic_validate(self): request = JsonRpcRequest( - method="sqlguard.validate", + method="altimate_core.validate", params={"sql": "SELECT 1"}, id=1, ) @@ -27,7 +27,7 @@ def test_basic_validate(self): def test_validate_with_schema_path(self): request = JsonRpcRequest( - method="sqlguard.validate", + method="altimate_core.validate", params={"sql": "SELECT 1", "schema_path": ""}, id=2, ) @@ -36,7 +36,7 @@ def test_validate_with_schema_path(self): def test_validate_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.validate", + method="altimate_core.validate", params={ "sql": "SELECT id FROM users", "schema_context": { @@ -50,10 +50,10 @@ def test_validate_with_schema_context(self): assert response.error is None -class TestSqlGuardLintDispatch: +class TestAltimateCoreLintDispatch: def test_basic_lint(self): request = JsonRpcRequest( - method="sqlguard.lint", + method="altimate_core.lint", params={"sql": "SELECT * FROM users WHERE name = NULL"}, id=10, ) @@ -63,7 +63,7 @@ def test_basic_lint(self): def test_clean_sql_lint(self): request = JsonRpcRequest( - method="sqlguard.lint", + method="altimate_core.lint", params={"sql": "SELECT id FROM users WHERE id = 1"}, id=11, ) @@ -71,10 +71,10 @@ def test_clean_sql_lint(self): assert response.error is None -class TestSqlGuardSafetyDispatch: +class TestAltimateCoreSafetyDispatch: def test_safe_query(self): request = JsonRpcRequest( - method="sqlguard.safety", + method="altimate_core.safety", params={"sql": "SELECT 1"}, id=20, ) @@ -84,7 +84,7 @@ def test_safe_query(self): def test_unsafe_query(self): request = JsonRpcRequest( - method="sqlguard.safety", + method="altimate_core.safety", params={"sql": "DROP TABLE users"}, id=21, ) @@ -94,10 +94,10 @@ def test_unsafe_query(self): assert data.get("safe") is False or data.get("threats") -class TestSqlGuardTranspileDispatch: +class TestAltimateCoreTranspileDispatch: def test_basic_transpile(self): request = JsonRpcRequest( - method="sqlguard.transpile", + method="altimate_core.transpile", params={"sql": "SELECT 1", "from_dialect": "generic", "to_dialect": "postgres"}, id=30, ) @@ -107,7 +107,7 @@ def test_basic_transpile(self): def test_missing_params(self): request = JsonRpcRequest( - method="sqlguard.transpile", + method="altimate_core.transpile", params={"sql": "SELECT 1"}, id=31, ) @@ -116,10 +116,10 @@ def test_missing_params(self): assert response.error is not None -class TestSqlGuardExplainDispatch: +class TestAltimateCoreExplainDispatch: def test_basic_explain(self): request = JsonRpcRequest( - method="sqlguard.explain", + method="altimate_core.explain", params={"sql": "SELECT 1"}, id=40, ) @@ -128,10 +128,10 @@ def test_basic_explain(self): assert "data" in response.result -class TestSqlGuardCheckDispatch: +class TestAltimateCoreCheckDispatch: def test_basic_check(self): request = JsonRpcRequest( - method="sqlguard.check", + method="altimate_core.check", params={"sql": "SELECT 1"}, id=50, ) @@ -141,7 +141,7 @@ def test_basic_check(self): def test_check_unsafe_sql(self): request = JsonRpcRequest( - method="sqlguard.check", + method="altimate_core.check", params={"sql": "DROP TABLE users; SELECT * FROM passwords"}, id=51, ) @@ -149,10 +149,10 @@ def test_check_unsafe_sql(self): assert response.error is None -class TestSqlGuardInvalidParams: +class TestAltimateCoreInvalidParams: def test_validate_no_sql(self): request = JsonRpcRequest( - method="sqlguard.validate", + method="altimate_core.validate", params={}, id=60, ) @@ -161,7 +161,7 @@ def test_validate_no_sql(self): def test_lint_no_sql(self): request = JsonRpcRequest( - method="sqlguard.lint", + method="altimate_core.lint", params={}, id=61, ) @@ -170,7 +170,7 @@ def test_lint_no_sql(self): def test_safety_no_sql(self): request = JsonRpcRequest( - method="sqlguard.safety", + method="altimate_core.safety", params={}, id=62, ) diff --git a/packages/altimate-engine/tests/test_server_guard_new.py b/packages/altimate-engine/tests/test_server_guard_new.py index 2685e277d8..d274739438 100644 --- a/packages/altimate-engine/tests/test_server_guard_new.py +++ b/packages/altimate-engine/tests/test_server_guard_new.py @@ -1,6 +1,6 @@ -"""Tests for new sqlguard JSON-RPC server dispatch (Phases 1-3). +"""Tests for new altimate_core JSON-RPC server dispatch (Phases 1-3). -Updated for new sqlguard API: Schema objects, renamed params. +Updated for new altimate_core API: Schema objects, renamed params. """ import os @@ -11,10 +11,10 @@ from altimate_engine.models import JsonRpcRequest from altimate_engine.server import dispatch -from altimate_engine.sql.guard import SQLGUARD_AVAILABLE +from altimate_engine.sql.guard import ALTIMATE_CORE_AVAILABLE -# Schema context in the format sqlguard expects +# Schema context in the format altimate_core expects SCHEMA_CTX = { "tables": { "users": { @@ -34,9 +34,9 @@ } -# Skip all tests if sqlguard is not installed +# Skip all tests if altimate_core is not installed pytestmark = pytest.mark.skipif( - not SQLGUARD_AVAILABLE, reason="sqlguard not installed" + not ALTIMATE_CORE_AVAILABLE, reason="altimate_core not installed" ) @@ -45,10 +45,10 @@ # --------------------------------------------------------------------------- -class TestSqlGuardFixDispatch: +class TestAltimateCoreFixDispatch: def test_basic_fix(self): request = JsonRpcRequest( - method="sqlguard.fix", + method="altimate_core.fix", params={"sql": "SELCT * FORM orders"}, id=100, ) @@ -59,7 +59,7 @@ def test_basic_fix(self): def test_fix_with_max_iterations(self): request = JsonRpcRequest( - method="sqlguard.fix", + method="altimate_core.fix", params={"sql": "SELCT 1", "max_iterations": 3}, id=101, ) @@ -68,7 +68,7 @@ def test_fix_with_max_iterations(self): def test_fix_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.fix", + method="altimate_core.fix", params={"sql": "SELCT id FORM orders", "schema_context": SCHEMA_CTX}, id=102, ) @@ -76,10 +76,10 @@ def test_fix_with_schema_context(self): assert response.error is None -class TestSqlGuardPolicyDispatch: +class TestAltimateCorePolicyDispatch: def test_basic_policy(self): request = JsonRpcRequest( - method="sqlguard.policy", + method="altimate_core.policy", params={"sql": "SELECT * FROM users", "policy_json": '{"rules": []}'}, id=110, ) @@ -89,7 +89,7 @@ def test_basic_policy(self): def test_empty_policy(self): request = JsonRpcRequest( - method="sqlguard.policy", + method="altimate_core.policy", params={"sql": "SELECT 1", "policy_json": ""}, id=111, ) @@ -97,31 +97,11 @@ def test_empty_policy(self): assert response.error is None -class TestSqlGuardComplexityDispatch: - def test_basic_complexity(self): - request = JsonRpcRequest( - method="sqlguard.complexity", - params={"sql": "SELECT * FROM orders JOIN payments ON orders.id = payments.order_id"}, - id=120, - ) - response = dispatch(request) - assert response.error is None - assert "data" in response.result - def test_with_schema_context(self): - request = JsonRpcRequest( - method="sqlguard.complexity", - params={"sql": "SELECT 1", "schema_context": SCHEMA_CTX}, - id=121, - ) - response = dispatch(request) - assert response.error is None - - -class TestSqlGuardSemanticsDispatch: +class TestAltimateCoreSemanticsDispatch: def test_basic_semantics(self): request = JsonRpcRequest( - method="sqlguard.semantics", + method="altimate_core.semantics", params={"sql": "SELECT * FROM users WHERE name = NULL"}, id=130, ) @@ -131,7 +111,7 @@ def test_basic_semantics(self): def test_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.semantics", + method="altimate_core.semantics", params={"sql": "SELECT id FROM users", "schema_context": SCHEMA_CTX}, id=131, ) @@ -139,10 +119,10 @@ def test_with_schema_context(self): assert response.error is None -class TestSqlGuardTestgenDispatch: +class TestAltimateCoreTestgenDispatch: def test_basic_testgen(self): request = JsonRpcRequest( - method="sqlguard.testgen", + method="altimate_core.testgen", params={"sql": "SELECT id, name FROM users WHERE active = true"}, id=140, ) @@ -156,10 +136,10 @@ def test_basic_testgen(self): # --------------------------------------------------------------------------- -class TestSqlGuardEquivalenceDispatch: +class TestAltimateCoreEquivalenceDispatch: def test_basic_equivalence(self): request = JsonRpcRequest( - method="sqlguard.equivalence", + method="altimate_core.equivalence", params={"sql1": "SELECT 1", "sql2": "SELECT 1"}, id=200, ) @@ -169,7 +149,7 @@ def test_basic_equivalence(self): def test_different_queries(self): request = JsonRpcRequest( - method="sqlguard.equivalence", + method="altimate_core.equivalence", params={"sql1": "SELECT id FROM users", "sql2": "SELECT name FROM users"}, id=201, ) @@ -177,10 +157,10 @@ def test_different_queries(self): assert response.error is None -class TestSqlGuardMigrationDispatch: +class TestAltimateCoreMigrationDispatch: def test_basic_migration(self): request = JsonRpcRequest( - method="sqlguard.migration", + method="altimate_core.migration", params={ "old_ddl": "CREATE TABLE users (id INT);", "new_ddl": "CREATE TABLE users (id INT, email VARCHAR(255));", @@ -192,7 +172,7 @@ def test_basic_migration(self): assert "data" in response.result -class TestSqlGuardSchemaDiffDispatch: +class TestAltimateCoreSchemaDiffDispatch: def test_basic_diff(self): schema1 = {"tables": {"users": {"columns": [{"name": "id", "type": "int"}]}}, "version": "1"} schema2 = {"tables": {"users": {"columns": [{"name": "id", "type": "int"}, {"name": "email", "type": "varchar"}]}}, "version": "1"} @@ -204,7 +184,7 @@ def test_basic_diff(self): path2 = f2.name try: request = JsonRpcRequest( - method="sqlguard.schema_diff", + method="altimate_core.schema_diff", params={"schema1_path": path1, "schema2_path": path2}, id=220, ) @@ -219,7 +199,7 @@ def test_diff_with_context(self): s1 = {"tables": {"users": {"columns": [{"name": "id", "type": "int"}]}}, "version": "1"} s2 = {"tables": {"users": {"columns": [{"name": "id", "type": "int"}, {"name": "name", "type": "varchar"}]}}, "version": "1"} request = JsonRpcRequest( - method="sqlguard.schema_diff", + method="altimate_core.schema_diff", params={"schema1_context": s1, "schema2_context": s2}, id=221, ) @@ -228,10 +208,10 @@ def test_diff_with_context(self): assert "data" in response.result -class TestSqlGuardRewriteDispatch: +class TestAltimateCoreRewriteDispatch: def test_basic_rewrite(self): request = JsonRpcRequest( - method="sqlguard.rewrite", + method="altimate_core.rewrite", params={"sql": "SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)"}, id=230, ) @@ -240,10 +220,10 @@ def test_basic_rewrite(self): assert "data" in response.result -class TestSqlGuardCorrectDispatch: +class TestAltimateCoreCorrectDispatch: def test_basic_correct(self): request = JsonRpcRequest( - method="sqlguard.correct", + method="altimate_core.correct", params={"sql": "SELCT * FORM orders"}, id=240, ) @@ -252,10 +232,10 @@ def test_basic_correct(self): assert "data" in response.result -class TestSqlGuardGradeDispatch: +class TestAltimateCoreGradeDispatch: def test_basic_grade(self): request = JsonRpcRequest( - method="sqlguard.grade", + method="altimate_core.grade", params={"sql": "SELECT id FROM users WHERE id = 1"}, id=250, ) @@ -264,33 +244,13 @@ def test_basic_grade(self): assert "data" in response.result -class TestSqlGuardCostDispatch: - def test_basic_cost(self): - request = JsonRpcRequest( - method="sqlguard.cost", - params={"sql": "SELECT * FROM orders"}, - id=260, - ) - response = dispatch(request) - assert response.error is None - assert "data" in response.result - - def test_with_dialect(self): - request = JsonRpcRequest( - method="sqlguard.cost", - params={"sql": "SELECT * FROM orders", "dialect": "snowflake"}, - id=261, - ) - response = dispatch(request) - assert response.error is None - # --------------------------------------------------------------------------- # Phase 3 (P2): Complete coverage # --------------------------------------------------------------------------- -class TestSqlGuardClassifyPiiDispatch: +class TestAltimateCoreClassifyPiiDispatch: def test_with_schema_context(self): schema = { "tables": { @@ -304,7 +264,7 @@ def test_with_schema_context(self): "version": "1", } request = JsonRpcRequest( - method="sqlguard.classify_pii", + method="altimate_core.classify_pii", params={"schema_context": schema}, id=300, ) @@ -313,10 +273,10 @@ def test_with_schema_context(self): assert "data" in response.result -class TestSqlGuardQueryPiiDispatch: +class TestAltimateCoreQueryPiiDispatch: def test_basic_pii(self): request = JsonRpcRequest( - method="sqlguard.query_pii", + method="altimate_core.query_pii", params={"sql": "SELECT email, ssn FROM users"}, id=310, ) @@ -325,10 +285,10 @@ def test_basic_pii(self): assert "data" in response.result -class TestSqlGuardResolveTermDispatch: +class TestAltimateCoreResolveTermDispatch: def test_basic_resolve(self): request = JsonRpcRequest( - method="sqlguard.resolve_term", + method="altimate_core.resolve_term", params={"term": "customer"}, id=320, ) @@ -337,10 +297,10 @@ def test_basic_resolve(self): assert "data" in response.result -class TestSqlGuardColumnLineageDispatch: +class TestAltimateCoreColumnLineageDispatch: def test_basic_lineage(self): request = JsonRpcRequest( - method="sqlguard.column_lineage", + method="altimate_core.column_lineage", params={"sql": "SELECT id FROM users"}, id=330, ) @@ -349,10 +309,10 @@ def test_basic_lineage(self): assert "data" in response.result -class TestSqlGuardTrackLineageDispatch: +class TestAltimateCoreTrackLineageDispatch: def test_basic_tracking(self): request = JsonRpcRequest( - method="sqlguard.track_lineage", + method="altimate_core.track_lineage", params={"queries": ["SELECT id FROM users", "SELECT user_id FROM orders"]}, id=340, ) @@ -361,10 +321,10 @@ def test_basic_tracking(self): assert "data" in response.result -class TestSqlGuardFormatDispatch: +class TestAltimateCoreFormatDispatch: def test_basic_format(self): request = JsonRpcRequest( - method="sqlguard.format", + method="altimate_core.format", params={"sql": "select id,name from users where id=1"}, id=350, ) @@ -374,7 +334,7 @@ def test_basic_format(self): def test_with_dialect(self): request = JsonRpcRequest( - method="sqlguard.format", + method="altimate_core.format", params={"sql": "SELECT 1", "dialect": "postgres"}, id=351, ) @@ -382,10 +342,10 @@ def test_with_dialect(self): assert response.error is None -class TestSqlGuardMetadataDispatch: +class TestAltimateCoreMetadataDispatch: def test_basic_metadata(self): request = JsonRpcRequest( - method="sqlguard.metadata", + method="altimate_core.metadata", params={"sql": "SELECT id, name FROM users WHERE active = true"}, id=360, ) @@ -394,10 +354,10 @@ def test_basic_metadata(self): assert "data" in response.result -class TestSqlGuardCompareDispatch: +class TestAltimateCoreCompareDispatch: def test_basic_compare(self): request = JsonRpcRequest( - method="sqlguard.compare", + method="altimate_core.compare", params={"left_sql": "SELECT 1", "right_sql": "SELECT 2"}, id=370, ) @@ -406,10 +366,10 @@ def test_basic_compare(self): assert "data" in response.result -class TestSqlGuardCompleteDispatch: +class TestAltimateCoreCompleteDispatch: def test_basic_complete(self): request = JsonRpcRequest( - method="sqlguard.complete", + method="altimate_core.complete", params={"sql": "SELECT ", "cursor_pos": 7}, id=380, ) @@ -418,10 +378,10 @@ def test_basic_complete(self): assert "data" in response.result -class TestSqlGuardOptimizeContextDispatch: +class TestAltimateCoreOptimizeContextDispatch: def test_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.optimize_context", + method="altimate_core.optimize_context", params={"schema_context": SCHEMA_CTX}, id=390, ) @@ -430,10 +390,10 @@ def test_with_schema_context(self): assert "data" in response.result -class TestSqlGuardOptimizeForQueryDispatch: +class TestAltimateCoreOptimizeForQueryDispatch: def test_basic_optimize(self): request = JsonRpcRequest( - method="sqlguard.optimize_for_query", + method="altimate_core.optimize_for_query", params={"sql": "SELECT id FROM users"}, id=400, ) @@ -442,10 +402,10 @@ def test_basic_optimize(self): assert "data" in response.result -class TestSqlGuardPruneSchemaDispatch: +class TestAltimateCorePruneSchemaDispatch: def test_basic_prune(self): request = JsonRpcRequest( - method="sqlguard.prune_schema", + method="altimate_core.prune_schema", params={"sql": "SELECT id FROM users"}, id=410, ) @@ -454,10 +414,10 @@ def test_basic_prune(self): assert "data" in response.result -class TestSqlGuardImportDdlDispatch: +class TestAltimateCoreImportDdlDispatch: def test_basic_import(self): request = JsonRpcRequest( - method="sqlguard.import_ddl", + method="altimate_core.import_ddl", params={"ddl": "CREATE TABLE users (id INT, name VARCHAR(255))"}, id=420, ) @@ -466,10 +426,10 @@ def test_basic_import(self): assert "data" in response.result -class TestSqlGuardExportDdlDispatch: +class TestAltimateCoreExportDdlDispatch: def test_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.export_ddl", + method="altimate_core.export_ddl", params={"schema_context": SCHEMA_CTX}, id=430, ) @@ -478,10 +438,10 @@ def test_with_schema_context(self): assert "data" in response.result -class TestSqlGuardFingerprintDispatch: +class TestAltimateCoreFingerprintDispatch: def test_with_schema_context(self): request = JsonRpcRequest( - method="sqlguard.fingerprint", + method="altimate_core.fingerprint", params={"schema_context": SCHEMA_CTX}, id=440, ) @@ -490,10 +450,10 @@ def test_with_schema_context(self): assert "data" in response.result -class TestSqlGuardIntrospectionSqlDispatch: +class TestAltimateCoreIntrospectionSqlDispatch: def test_basic_introspection(self): request = JsonRpcRequest( - method="sqlguard.introspection_sql", + method="altimate_core.introspection_sql", params={"db_type": "postgres", "database": "mydb"}, id=450, ) @@ -503,7 +463,7 @@ def test_basic_introspection(self): def test_with_schema_name(self): request = JsonRpcRequest( - method="sqlguard.introspection_sql", + method="altimate_core.introspection_sql", params={"db_type": "snowflake", "database": "mydb", "schema_name": "public"}, id=451, ) @@ -511,10 +471,10 @@ def test_with_schema_name(self): assert response.error is None -class TestSqlGuardParseDbtDispatch: +class TestAltimateCoreParseDbtDispatch: def test_basic_parse(self): request = JsonRpcRequest( - method="sqlguard.parse_dbt", + method="altimate_core.parse_dbt", params={"project_dir": "/nonexistent/dbt/project"}, id=460, ) @@ -523,10 +483,10 @@ def test_basic_parse(self): assert "data" in response.result -class TestSqlGuardIsSafeDispatch: +class TestAltimateCoreIsSafeDispatch: def test_safe_query(self): request = JsonRpcRequest( - method="sqlguard.is_safe", + method="altimate_core.is_safe", params={"sql": "SELECT 1"}, id=470, ) @@ -536,7 +496,7 @@ def test_safe_query(self): def test_unsafe_query(self): request = JsonRpcRequest( - method="sqlguard.is_safe", + method="altimate_core.is_safe", params={"sql": "DROP TABLE users"}, id=471, ) @@ -550,10 +510,10 @@ def test_unsafe_query(self): # --------------------------------------------------------------------------- -class TestSqlGuardNewInvalidParams: +class TestAltimateCoreNewInvalidParams: def test_fix_no_sql(self): request = JsonRpcRequest( - method="sqlguard.fix", + method="altimate_core.fix", params={}, id=500, ) @@ -562,7 +522,7 @@ def test_fix_no_sql(self): def test_policy_no_sql(self): request = JsonRpcRequest( - method="sqlguard.policy", + method="altimate_core.policy", params={}, id=501, ) @@ -571,25 +531,16 @@ def test_policy_no_sql(self): def test_policy_no_policy_json(self): request = JsonRpcRequest( - method="sqlguard.policy", + method="altimate_core.policy", params={"sql": "SELECT 1"}, id=502, ) response = dispatch(request) assert response.error is not None - def test_complexity_no_sql(self): - request = JsonRpcRequest( - method="sqlguard.complexity", - params={}, - id=503, - ) - response = dispatch(request) - assert response.error is not None - def test_semantics_no_sql(self): request = JsonRpcRequest( - method="sqlguard.semantics", + method="altimate_core.semantics", params={}, id=504, ) @@ -598,7 +549,7 @@ def test_semantics_no_sql(self): def test_testgen_no_sql(self): request = JsonRpcRequest( - method="sqlguard.testgen", + method="altimate_core.testgen", params={}, id=505, ) @@ -607,7 +558,7 @@ def test_testgen_no_sql(self): def test_equivalence_no_params(self): request = JsonRpcRequest( - method="sqlguard.equivalence", + method="altimate_core.equivalence", params={}, id=506, ) @@ -616,7 +567,7 @@ def test_equivalence_no_params(self): def test_correct_no_sql(self): request = JsonRpcRequest( - method="sqlguard.correct", + method="altimate_core.correct", params={}, id=508, ) @@ -625,7 +576,7 @@ def test_correct_no_sql(self): def test_complete_no_params(self): request = JsonRpcRequest( - method="sqlguard.complete", + method="altimate_core.complete", params={}, id=509, ) @@ -634,7 +585,7 @@ def test_complete_no_params(self): def test_introspection_sql_no_params(self): request = JsonRpcRequest( - method="sqlguard.introspection_sql", + method="altimate_core.introspection_sql", params={}, id=510, ) @@ -643,7 +594,7 @@ def test_introspection_sql_no_params(self): def test_import_ddl_no_params(self): request = JsonRpcRequest( - method="sqlguard.import_ddl", + method="altimate_core.import_ddl", params={}, id=511, ) @@ -652,7 +603,7 @@ def test_import_ddl_no_params(self): def test_compare_no_params(self): request = JsonRpcRequest( - method="sqlguard.compare", + method="altimate_core.compare", params={}, id=512, ) @@ -661,7 +612,7 @@ def test_compare_no_params(self): def test_track_lineage_no_params(self): request = JsonRpcRequest( - method="sqlguard.track_lineage", + method="altimate_core.track_lineage", params={}, id=513, ) @@ -670,7 +621,7 @@ def test_track_lineage_no_params(self): def test_is_safe_no_sql(self): request = JsonRpcRequest( - method="sqlguard.is_safe", + method="altimate_core.is_safe", params={}, id=514, ) @@ -679,7 +630,7 @@ def test_is_safe_no_sql(self): def test_parse_dbt_no_params(self): request = JsonRpcRequest( - method="sqlguard.parse_dbt", + method="altimate_core.parse_dbt", params={}, id=515, )