From a19d7be1c1d944c555d788086dffe2e2e316afa8 Mon Sep 17 00:00:00 2001 From: Vijay Yadav Date: Sat, 28 Mar 2026 18:27:24 -0400 Subject: [PATCH 1/4] fix: pass warehouse dialect to altimate-core tools instead of hardcoding snowflake Add optional `dialect` parameter (default: "snowflake") to all 8 altimate-core tools that were missing it: - altimate-core-validate, fix, correct, semantics, equivalence, policy, check, and impact-analysis Each tool now: 1. Accepts `dialect` via its zod parameter schema 2. Passes it through to the Dispatcher call 3. Includes it in telemetry metadata Follows the pattern established in sql-analyze.ts, sql-optimize.ts, and schema-diff.ts. Type interfaces updated in types.ts. Tests updated to pass dialect explicitly. Fixes #455 Co-Authored-By: Vijay Yadav --- .../opencode/src/altimate/native/types.ts | 7 ++++ .../src/altimate/tools/altimate-core-check.ts | 9 ++++- .../altimate/tools/altimate-core-correct.ts | 9 ++++- .../tools/altimate-core-equivalence.ts | 9 ++++- .../src/altimate/tools/altimate-core-fix.ts | 9 ++++- .../altimate/tools/altimate-core-policy.ts | 9 ++++- .../altimate/tools/altimate-core-semantics.ts | 9 ++++- .../altimate/tools/altimate-core-validate.ts | 9 ++++- .../src/altimate/tools/impact-analysis.ts | 3 +- .../opencode/test/altimate/e2e-tool-errors.ts | 36 ++++++++++--------- .../altimate/tool-error-propagation.test.ts | 18 +++++----- 11 files changed, 93 insertions(+), 34 deletions(-) diff --git a/packages/opencode/src/altimate/native/types.ts b/packages/opencode/src/altimate/native/types.ts index 16a7f4e06..7c1fedeee 100644 --- a/packages/opencode/src/altimate/native/types.ts +++ b/packages/opencode/src/altimate/native/types.ts @@ -680,6 +680,7 @@ export interface SchemaDiffResult { export interface AltimateCoreValidateParams { sql: string + dialect?: string schema_path?: string schema_context?: Record } @@ -708,6 +709,7 @@ export interface AltimateCoreExplainParams { export interface AltimateCoreCheckParams { sql: string + dialect?: string schema_path?: string schema_context?: Record } @@ -722,6 +724,7 @@ export interface AltimateCoreResult { export interface AltimateCoreFixParams { sql: string + dialect?: string schema_path?: string schema_context?: Record max_iterations?: number @@ -729,6 +732,7 @@ export interface AltimateCoreFixParams { export interface AltimateCorePolicyParams { sql: string + dialect?: string policy_json: string schema_path?: string schema_context?: Record @@ -736,6 +740,7 @@ export interface AltimateCorePolicyParams { export interface AltimateCoreSemanticsParams { sql: string + dialect?: string schema_path?: string schema_context?: Record } @@ -751,6 +756,7 @@ export interface AltimateCoreTestgenParams { export interface AltimateCoreEquivalenceParams { sql1: string sql2: string + dialect?: string schema_path?: string schema_context?: Record } @@ -776,6 +782,7 @@ export interface AltimateCoreRewriteParams { export interface AltimateCoreCorrectParams { sql: string + dialect?: string schema_path?: string schema_context?: Record } diff --git a/packages/opencode/src/altimate/tools/altimate-core-check.ts b/packages/opencode/src/altimate/tools/altimate-core-check.ts index 5d242a9dd..bf2cebb0c 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-check.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-check.ts @@ -8,6 +8,11 @@ export const AltimateCoreCheckTool = Tool.define("altimate_core_check", { "Run full analysis pipeline: validate + lint + safety scan + PII check. Single call for comprehensive SQL analysis. Provide schema_context or schema_path for accurate table/column resolution.", parameters: z.object({ sql: z.string().describe("SQL query to analyze"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), }), @@ -16,6 +21,7 @@ export const AltimateCoreCheckTool = Tool.define("altimate_core_check", { try { const result = await Dispatcher.call("altimate_core.check", { sql: args.sql, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) @@ -40,6 +46,7 @@ export const AltimateCoreCheckTool = Tool.define("altimate_core_check", { title: `Check: ${formatCheckTitle(data)}`, metadata: { success: result.success, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -50,7 +57,7 @@ export const AltimateCoreCheckTool = Tool.define("altimate_core_check", { const msg = e instanceof Error ? e.message : String(e) return { title: "Check: ERROR", - metadata: { success: false, has_schema: hasSchema, error: msg }, + metadata: { success: false, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-correct.ts b/packages/opencode/src/altimate/tools/altimate-core-correct.ts index 62ece364c..e02c416d0 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-correct.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-correct.ts @@ -8,6 +8,11 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", { "Iteratively correct SQL using a propose-verify-refine loop. More thorough than fix — applies multiple correction rounds to produce valid SQL. Provide schema_context or schema_path for accurate table/column resolution.", parameters: z.object({ sql: z.string().describe("SQL query to correct"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), }), @@ -16,6 +21,7 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", { try { const result = await Dispatcher.call("altimate_core.correct", { sql: args.sql, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) @@ -32,6 +38,7 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", { metadata: { success: result.success, iterations: data.iterations, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -42,7 +49,7 @@ export const AltimateCoreCorrectTool = Tool.define("altimate_core_correct", { const msg = e instanceof Error ? e.message : String(e) return { title: "Correct: ERROR", - metadata: { success: false, iterations: 0, has_schema: hasSchema, error: msg }, + metadata: { success: false, iterations: 0, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts b/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts index 0c2198ca6..2d26131e0 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts @@ -9,6 +9,11 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc parameters: z.object({ sql1: z.string().describe("First SQL query"), sql2: z.string().describe("Second SQL query"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), }), @@ -27,6 +32,7 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc const result = await Dispatcher.call("altimate_core.equivalence", { sql1: args.sql1, sql2: args.sql2, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) @@ -48,6 +54,7 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc metadata: { success: !isRealFailure, equivalent: data.equivalent, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -58,7 +65,7 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc const msg = e instanceof Error ? e.message : String(e) return { title: "Equivalence: ERROR", - metadata: { success: false, equivalent: false, has_schema: hasSchema, error: msg }, + metadata: { success: false, equivalent: false, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-fix.ts b/packages/opencode/src/altimate/tools/altimate-core-fix.ts index b01110f39..c8f44a977 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-fix.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-fix.ts @@ -8,6 +8,11 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", { "Auto-fix SQL errors using fuzzy matching and iterative re-validation. Corrects syntax errors, typos, and schema reference issues. IMPORTANT: Provide schema_context or schema_path — without schema, table/column references cannot be resolved or fixed.", parameters: z.object({ sql: z.string().describe("SQL query to fix"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), max_iterations: z.number().optional().describe("Maximum fix iterations (default: 5)"), @@ -17,6 +22,7 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", { try { const result = await Dispatcher.call("altimate_core.fix", { sql: args.sql, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, max_iterations: args.max_iterations ?? 5, @@ -40,6 +46,7 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", { metadata: { success, fixed: !!data.fixed_sql, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -50,7 +57,7 @@ export const AltimateCoreFixTool = Tool.define("altimate_core_fix", { const msg = e instanceof Error ? e.message : String(e) return { title: "Fix: ERROR", - metadata: { success: false, fixed: false, has_schema: hasSchema, error: msg }, + metadata: { success: false, fixed: false, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-policy.ts b/packages/opencode/src/altimate/tools/altimate-core-policy.ts index e55c02d29..06babafb3 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-policy.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-policy.ts @@ -8,6 +8,11 @@ export const AltimateCorePolicyTool = Tool.define("altimate_core_policy", { "Check SQL against YAML-based governance policy guardrails. Validates compliance with custom rules like allowed tables, forbidden operations, and data access restrictions. Provide schema_context or schema_path for accurate table/column resolution.", parameters: z.object({ sql: z.string().describe("SQL query to check against policy"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), policy_json: z.string().describe("JSON string defining the policy rules"), 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"), @@ -17,6 +22,7 @@ export const AltimateCorePolicyTool = Tool.define("altimate_core_policy", { try { const result = await Dispatcher.call("altimate_core.policy", { sql: args.sql, + dialect: args.dialect, policy_json: args.policy_json, schema_path: args.schema_path ?? "", schema_context: args.schema_context, @@ -34,6 +40,7 @@ export const AltimateCorePolicyTool = Tool.define("altimate_core_policy", { metadata: { success: true, // engine ran — violations are findings, not failures pass: data.pass, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -44,7 +51,7 @@ export const AltimateCorePolicyTool = Tool.define("altimate_core_policy", { const msg = e instanceof Error ? e.message : String(e) return { title: "Policy: ERROR", - metadata: { success: false, pass: false, has_schema: hasSchema, error: msg }, + metadata: { success: false, pass: false, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-semantics.ts b/packages/opencode/src/altimate/tools/altimate-core-semantics.ts index f644acf2f..981f50742 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-semantics.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-semantics.ts @@ -8,6 +8,11 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", "Run semantic validation rules against SQL. Detects logical issues like cartesian products, wrong JOIN conditions, NULL misuse, and type mismatches that syntax checking alone misses. Provide schema_context or schema_path for accurate table/column resolution.", parameters: z.object({ sql: z.string().describe("SQL query to validate semantically"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), }), @@ -25,6 +30,7 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", try { const result = await Dispatcher.call("altimate_core.semantics", { sql: args.sql, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) @@ -44,6 +50,7 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", success: true, // engine ran — semantic issues are findings, not failures valid: data.valid, issue_count: issueCount, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -54,7 +61,7 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", const msg = e instanceof Error ? e.message : String(e) return { title: "Semantics: ERROR", - metadata: { success: false, valid: false, issue_count: 0, has_schema: hasSchema, error: msg }, + metadata: { success: false, valid: false, issue_count: 0, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-validate.ts b/packages/opencode/src/altimate/tools/altimate-core-validate.ts index 384b5faed..a017af471 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-validate.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-validate.ts @@ -8,6 +8,11 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { "Validate SQL syntax and schema references. Checks if tables/columns exist in the schema and if SQL is valid for the target dialect. IMPORTANT: Provide schema_context or schema_path — without schema, all table/column references will report as 'not found'.", parameters: z.object({ sql: z.string().describe("SQL query to validate"), + dialect: z + .string() + .optional() + .default("snowflake") + .describe("SQL dialect (snowflake, postgres, bigquery, duckdb, etc.)"), 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"), }), @@ -26,6 +31,7 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { try { const result = await Dispatcher.call("altimate_core.validate", { sql: args.sql, + dialect: args.dialect, schema_path: args.schema_path ?? "", schema_context: args.schema_context, }) @@ -42,6 +48,7 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { metadata: { success: true, // engine ran — validation errors are findings, not failures valid: data.valid, + dialect: args.dialect, has_schema: hasSchema, ...(error && { error }), ...(findings.length > 0 && { findings }), @@ -52,7 +59,7 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { const msg = e instanceof Error ? e.message : String(e) return { title: "Validate: ERROR", - metadata: { success: false, valid: false, has_schema: hasSchema, error: msg }, + metadata: { success: false, valid: false, dialect: args.dialect, has_schema: hasSchema, error: msg }, output: `Failed: ${msg}`, } } diff --git a/packages/opencode/src/altimate/tools/impact-analysis.ts b/packages/opencode/src/altimate/tools/impact-analysis.ts index 205811f81..92c68c51d 100644 --- a/packages/opencode/src/altimate/tools/impact-analysis.ts +++ b/packages/opencode/src/altimate/tools/impact-analysis.ts @@ -139,6 +139,7 @@ export const ImpactAnalysisTool = Tool.define("impact_analysis", { transitive_count: transitive.length, test_count: affectedTestCount, column_impact: columnImpact.length, + dialect: args.dialect, has_schema: false, ...(findings.length > 0 && { findings }), }, @@ -148,7 +149,7 @@ export const ImpactAnalysisTool = Tool.define("impact_analysis", { const msg = e instanceof Error ? e.message : String(e) return { title: "Impact: ERROR", - metadata: { success: false, has_schema: false, error: msg }, + metadata: { success: false, dialect: args.dialect, has_schema: false, error: msg }, output: `Failed to analyze impact: ${msg}\n\nEnsure the dbt manifest exists (run \`dbt compile\`) and the dispatcher is running.`, } } diff --git a/packages/opencode/test/altimate/e2e-tool-errors.ts b/packages/opencode/test/altimate/e2e-tool-errors.ts index 57326af99..d8447d262 100644 --- a/packages/opencode/test/altimate/e2e-tool-errors.ts +++ b/packages/opencode/test/altimate/e2e-tool-errors.ts @@ -174,7 +174,7 @@ async function main() { await check( "validate: no schema → early return with 'No schema provided'", async () => { - return validateTool.execute({ sql: testSql }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake" }, stubCtx()) }, { metadataSuccess: false, metadataErrorContains: "No schema provided", noUnknownError: true }, ) @@ -182,7 +182,7 @@ async function main() { await check( "validate: with schema_context (flat) → success", async () => { - return validateTool.execute({ sql: testSql, schema_context: flatSchema }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_context: flatSchema }, stubCtx()) }, { metadataSuccess: true }, ) @@ -190,7 +190,7 @@ async function main() { await check( "validate: with schema_path (JSON file) → success", async () => { - return validateTool.execute({ sql: testSql, schema_path: schemaJsonPath }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_path: schemaJsonPath }, stubCtx()) }, { metadataSuccess: true }, ) @@ -198,7 +198,7 @@ async function main() { await check( "validate: with schema_path (YAML file) → success", async () => { - return validateTool.execute({ sql: testSql, schema_path: schemaYamlPath }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_path: schemaYamlPath }, stubCtx()) }, { metadataSuccess: true }, ) @@ -206,7 +206,7 @@ async function main() { await check( "validate: with schema_path (nonexistent file) → error", async () => { - return validateTool.execute({ sql: testSql, schema_path: "/tmp/nonexistent-schema-abc123.json" }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_path: "/tmp/nonexistent-schema-abc123.json" }, stubCtx()) }, { metadataSuccess: false, noUnknownError: true }, ) @@ -214,7 +214,7 @@ async function main() { await check( "validate: syntax error SQL with schema → error propagated", async () => { - return validateTool.execute({ sql: badSql, schema_context: flatSchema }, stubCtx()) + return validateTool.execute({ sql: badSql, dialect: "snowflake", schema_context: flatSchema }, stubCtx()) }, { metadataSuccess: true, metadataErrorContains: "Syntax error", noUnknownError: true }, ) @@ -230,7 +230,7 @@ async function main() { await check( "semantics: no schema → early return with 'No schema provided'", async () => { - return semanticsTool.execute({ sql: testSql }, stubCtx()) + return semanticsTool.execute({ sql: testSql, dialect: "snowflake" }, stubCtx()) }, { metadataSuccess: false, metadataErrorContains: "No schema provided", noUnknownError: true }, ) @@ -238,7 +238,7 @@ async function main() { await check( "semantics: with schema_context → runs (may find issues)", async () => { - return semanticsTool.execute({ sql: testSql, schema_context: flatSchema }, stubCtx()) + return semanticsTool.execute({ sql: testSql, dialect: "snowflake", schema_context: flatSchema }, stubCtx()) }, { noUnknownError: true }, ) @@ -246,7 +246,7 @@ async function main() { await check( "semantics: with schema_path → runs", async () => { - return semanticsTool.execute({ sql: testSql, schema_path: schemaJsonPath }, stubCtx()) + return semanticsTool.execute({ sql: testSql, dialect: "snowflake", schema_path: schemaJsonPath }, stubCtx()) }, { noUnknownError: true }, ) @@ -264,7 +264,7 @@ async function main() { await check( "equivalence: no schema → early return with 'No schema provided'", async () => { - return equivTool.execute({ sql1: testSql, sql2 }, stubCtx()) + return equivTool.execute({ sql1: testSql, sql2, dialect: "snowflake" }, stubCtx()) }, { metadataSuccess: false, metadataErrorContains: "No schema provided", noUnknownError: true }, ) @@ -272,7 +272,7 @@ async function main() { await check( "equivalence: with schema_context → runs", async () => { - return equivTool.execute({ sql1: testSql, sql2, schema_context: flatSchema }, stubCtx()) + return equivTool.execute({ sql1: testSql, sql2, dialect: "snowflake", schema_context: flatSchema }, stubCtx()) }, { noUnknownError: true }, ) @@ -280,7 +280,7 @@ async function main() { await check( "equivalence: with schema_path → runs", async () => { - return equivTool.execute({ sql1: testSql, sql2, schema_path: schemaJsonPath }, stubCtx()) + return equivTool.execute({ sql1: testSql, sql2, dialect: "snowflake", schema_path: schemaJsonPath }, stubCtx()) }, { noUnknownError: true }, ) @@ -296,7 +296,7 @@ async function main() { await check( "fix: unfixable syntax error → error propagated", async () => { - return fixTool.execute({ sql: badSql }, stubCtx()) + return fixTool.execute({ sql: badSql, dialect: "snowflake" }, stubCtx()) }, { metadataSuccess: true, noUnknownError: true }, ) @@ -304,7 +304,7 @@ async function main() { await check( "fix: valid SQL → success (already valid)", async () => { - return fixTool.execute({ sql: "SELECT 1", schema_context: flatSchema }, stubCtx()) + return fixTool.execute({ sql: "SELECT 1", dialect: "snowflake", schema_context: flatSchema }, stubCtx()) }, { metadataSuccess: true }, ) @@ -320,7 +320,7 @@ async function main() { await check( "correct: unfixable syntax error → error propagated", async () => { - return correctTool.execute({ sql: badSql }, stubCtx()) + return correctTool.execute({ sql: badSql, dialect: "snowflake" }, stubCtx()) }, { metadataSuccess: true, noUnknownError: true }, ) @@ -470,7 +470,7 @@ async function main() { await check( "schema_path: empty string → treated as no schema", async () => { - return validateTool.execute({ sql: testSql, schema_path: "" }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_path: "" }, stubCtx()) }, { metadataSuccess: false, metadataErrorContains: "No schema provided", noUnknownError: true }, ) @@ -478,7 +478,7 @@ async function main() { await check( "schema_context: empty object → treated as no schema", async () => { - return validateTool.execute({ sql: testSql, schema_context: {} }, stubCtx()) + return validateTool.execute({ sql: testSql, dialect: "snowflake", schema_context: {} }, stubCtx()) }, { metadataSuccess: false, metadataErrorContains: "No schema provided", noUnknownError: true }, ) @@ -489,6 +489,7 @@ async function main() { return validateTool.execute( { sql: "SELECT id FROM users", + dialect: "snowflake", schema_context: { users: [ { name: "id", type: "INTEGER" }, @@ -508,6 +509,7 @@ async function main() { return validateTool.execute( { sql: "SELECT id FROM users", + dialect: "snowflake", schema_context: { tables: { users: { diff --git a/packages/opencode/test/altimate/tool-error-propagation.test.ts b/packages/opencode/test/altimate/tool-error-propagation.test.ts index 9270440b6..edd7603cf 100644 --- a/packages/opencode/test/altimate/tool-error-propagation.test.ts +++ b/packages/opencode/test/altimate/tool-error-propagation.test.ts @@ -55,7 +55,7 @@ describe("altimate_core_validate error propagation", () => { test("returns early with clear error when no schema provided", async () => { const { AltimateCoreValidateTool } = await import("../../src/altimate/tools/altimate-core-validate") const tool = await AltimateCoreValidateTool.init() - const result = await tool.execute({ sql: "SELECT * FROM users" }, stubCtx()) + const result = await tool.execute({ sql: "SELECT * FROM users", dialect: "snowflake" }, stubCtx()) expect(result.metadata.success).toBe(false) expect(result.metadata.error).toContain("No schema provided") @@ -85,7 +85,7 @@ describe("altimate_core_validate error propagation", () => { const { AltimateCoreValidateTool } = await import("../../src/altimate/tools/altimate-core-validate") const tool = await AltimateCoreValidateTool.init() const result = await tool.execute( - { sql: "SELECT * FROM users", schema_context: { orders: { id: "INT" } } }, + { sql: "SELECT * FROM users", dialect: "snowflake", schema_context: { orders: { id: "INT" } } }, stubCtx(), ) @@ -107,7 +107,7 @@ describe("altimate_core_semantics error propagation", () => { test("returns early with clear error when no schema provided", async () => { const { AltimateCoreSemanticsTool } = await import("../../src/altimate/tools/altimate-core-semantics") const tool = await AltimateCoreSemanticsTool.init() - const result = await tool.execute({ sql: "SELECT * FROM users" }, stubCtx()) + const result = await tool.execute({ sql: "SELECT * FROM users", dialect: "snowflake" }, stubCtx()) expect(result.metadata.success).toBe(false) expect(result.metadata.error).toContain("No schema provided") @@ -130,7 +130,7 @@ describe("altimate_core_semantics error propagation", () => { const { AltimateCoreSemanticsTool } = await import("../../src/altimate/tools/altimate-core-semantics") const tool = await AltimateCoreSemanticsTool.init() const result = await tool.execute( - { sql: "SELECT * FROM users", schema_context: { orders: { id: "INT" } } }, + { sql: "SELECT * FROM users", dialect: "snowflake", schema_context: { orders: { id: "INT" } } }, stubCtx(), ) @@ -150,7 +150,7 @@ describe("altimate_core_equivalence error propagation", () => { test("returns early with clear error when no schema provided", async () => { const { AltimateCoreEquivalenceTool } = await import("../../src/altimate/tools/altimate-core-equivalence") const tool = await AltimateCoreEquivalenceTool.init() - const result = await tool.execute({ sql1: "SELECT * FROM users", sql2: "SELECT * FROM users" }, stubCtx()) + const result = await tool.execute({ sql1: "SELECT * FROM users", sql2: "SELECT * FROM users", dialect: "snowflake" }, stubCtx()) expect(result.metadata.success).toBe(false) expect(result.metadata.error).toContain("No schema provided") @@ -172,7 +172,7 @@ describe("altimate_core_equivalence error propagation", () => { const { AltimateCoreEquivalenceTool } = await import("../../src/altimate/tools/altimate-core-equivalence") const tool = await AltimateCoreEquivalenceTool.init() const result = await tool.execute( - { sql1: "SELECT * FROM users", sql2: "SELECT * FROM users", schema_context: { orders: { id: "INT" } } }, + { sql1: "SELECT * FROM users", sql2: "SELECT * FROM users", dialect: "snowflake", schema_context: { orders: { id: "INT" } } }, stubCtx(), ) @@ -216,7 +216,7 @@ describe("altimate_core_fix error propagation", () => { const { AltimateCoreFixTool } = await import("../../src/altimate/tools/altimate-core-fix") const tool = await AltimateCoreFixTool.init() - const result = await tool.execute({ sql: "SELCT * FORM users" }, stubCtx()) + const result = await tool.execute({ sql: "SELCT * FORM users", dialect: "snowflake" }, stubCtx()) expect(result.metadata.error).toContain("Syntax error") expect(telemetryWouldExtract(result.metadata)).not.toBe("unknown error") @@ -257,7 +257,7 @@ describe("altimate_core_correct error propagation", () => { const { AltimateCoreCorrectTool } = await import("../../src/altimate/tools/altimate-core-correct") const tool = await AltimateCoreCorrectTool.init() - const result = await tool.execute({ sql: "SELCT * FORM users" }, stubCtx()) + const result = await tool.execute({ sql: "SELCT * FORM users", dialect: "snowflake" }, stubCtx()) expect(result.metadata.error).toContain("Syntax error") expect(telemetryWouldExtract(result.metadata)).not.toBe("unknown error") @@ -476,7 +476,7 @@ describe("extractors handle empty message fields", () => { const { AltimateCoreValidateTool } = await import("../../src/altimate/tools/altimate-core-validate") const tool = await AltimateCoreValidateTool.init() const result = await tool.execute( - { sql: "SELECT * FROM nonexistent_table", schema_context: { users: { id: "INT" } } }, + { sql: "SELECT * FROM nonexistent_table", dialect: "snowflake", schema_context: { users: { id: "INT" } } }, stubCtx(), ) // The error should never be empty string — .filter(Boolean) removes it From 3ca8013b57f666bb66c391d508dcd25d1a46c750 Mon Sep 17 00:00:00 2001 From: Vijay Yadav Date: Mon, 30 Mar 2026 18:47:21 -0400 Subject: [PATCH 2/4] fix: include dialect in all early-return metadata paths Address behavioral analysis findings: the NO SCHEMA early returns in validate, semantics, and equivalence tools, plus the NO MANIFEST and MODEL NOT FOUND early returns in impact-analysis, were missing the dialect field in their metadata. All return paths now consistently include dialect for telemetry. Co-Authored-By: Vijay Yadav --- .../opencode/src/altimate/tools/altimate-core-equivalence.ts | 2 +- .../opencode/src/altimate/tools/altimate-core-semantics.ts | 2 +- .../opencode/src/altimate/tools/altimate-core-validate.ts | 2 +- packages/opencode/src/altimate/tools/impact-analysis.ts | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts b/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts index 2d26131e0..2bb3a80a9 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-equivalence.ts @@ -24,7 +24,7 @@ export const AltimateCoreEquivalenceTool = Tool.define("altimate_core_equivalenc "No schema provided. Provide schema_context or schema_path so table/column references can be resolved." return { title: "Equivalence: NO SCHEMA", - metadata: { success: false, equivalent: false, has_schema: false, error }, + metadata: { success: false, equivalent: false, dialect: args.dialect, has_schema: false, error }, output: `Error: ${error}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-semantics.ts b/packages/opencode/src/altimate/tools/altimate-core-semantics.ts index 981f50742..19e829fc0 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-semantics.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-semantics.ts @@ -23,7 +23,7 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics", "No schema provided. Provide schema_context or schema_path so table/column references can be resolved." return { title: "Semantics: NO SCHEMA", - metadata: { success: false, valid: false, issue_count: 0, has_schema: false, error }, + metadata: { success: false, valid: false, issue_count: 0, dialect: args.dialect, has_schema: false, error }, output: `Error: ${error}`, } } diff --git a/packages/opencode/src/altimate/tools/altimate-core-validate.ts b/packages/opencode/src/altimate/tools/altimate-core-validate.ts index a017af471..7bf2f2903 100644 --- a/packages/opencode/src/altimate/tools/altimate-core-validate.ts +++ b/packages/opencode/src/altimate/tools/altimate-core-validate.ts @@ -24,7 +24,7 @@ export const AltimateCoreValidateTool = Tool.define("altimate_core_validate", { "No schema provided. Provide schema_context or schema_path so table/column references can be resolved." return { title: "Validate: NO SCHEMA", - metadata: { success: false, valid: false, has_schema: false, error }, + metadata: { success: false, valid: false, dialect: args.dialect, has_schema: false, error }, output: `Error: ${error}`, } } diff --git a/packages/opencode/src/altimate/tools/impact-analysis.ts b/packages/opencode/src/altimate/tools/impact-analysis.ts index 92c68c51d..767d65e38 100644 --- a/packages/opencode/src/altimate/tools/impact-analysis.ts +++ b/packages/opencode/src/altimate/tools/impact-analysis.ts @@ -37,7 +37,7 @@ export const ImpactAnalysisTool = Tool.define("impact_analysis", { if (!manifest.models || manifest.models.length === 0) { return { title: "Impact: NO MANIFEST", - metadata: { success: false }, + metadata: { success: false, dialect: args.dialect }, output: `No models found in manifest at ${args.manifest_path}. Run \`dbt compile\` first to generate the manifest.`, } } @@ -54,7 +54,7 @@ export const ImpactAnalysisTool = Tool.define("impact_analysis", { .join(", ") return { title: "Impact: MODEL NOT FOUND", - metadata: { success: false }, + metadata: { success: false, dialect: args.dialect }, output: `Model "${args.model}" not found in manifest. Available models: ${available}${manifest.models.length > 10 ? ` (+${manifest.models.length - 10} more)` : ""}`, } } From 4ceea83ff9fdc2029b4604c6520eb0fe0d8926de Mon Sep 17 00:00:00 2001 From: Vijay Yadav Date: Sat, 4 Apr 2026 15:11:48 -0400 Subject: [PATCH 3/4] fix: thread dialect through schemaOrEmpty into all six native handlers The dialect parameter was passed through the tool layer but dropped at the schema resolution step. Six native handlers (validate, check, fix, semantics, equivalence, correct) called schemaOrEmpty() without dialect, so the fallback empty schema always used the default dialect. Fix: add optional dialect param to schemaOrEmpty() and pass it to Schema.fromDdl(). Update all six handlers to forward params.dialect. Co-Authored-By: Vijay Yadav --- .../opencode/src/altimate/native/altimate-core.ts | 12 ++++++------ .../opencode/src/altimate/native/schema-resolver.ts | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/opencode/src/altimate/native/altimate-core.ts b/packages/opencode/src/altimate/native/altimate-core.ts index 958230b26..8194ddae9 100644 --- a/packages/opencode/src/altimate/native/altimate-core.ts +++ b/packages/opencode/src/altimate/native/altimate-core.ts @@ -88,7 +88,7 @@ export function registerAll(): void { // 1. altimate_core.validate register("altimate_core.validate", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.validate(params.sql, schema) const data = toData(raw) return ok(true, data) @@ -167,7 +167,7 @@ export function registerAll(): void { // 6. altimate_core.check — composite: validate + lint + scan_sql register("altimate_core.check", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const validation = await core.validate(params.sql, schema) const lintResult = core.lint(params.sql, schema) const safety = core.scanSql(params.sql) @@ -185,7 +185,7 @@ export function registerAll(): void { // 7. altimate_core.fix register("altimate_core.fix", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.fix(params.sql, schema, params.max_iterations ?? undefined) const data = toData(raw) return ok(true, data) @@ -209,7 +209,7 @@ export function registerAll(): void { // 9. altimate_core.semantics register("altimate_core.semantics", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.checkSemantics(params.sql, schema) const data = toData(raw) return ok(true, data) @@ -232,7 +232,7 @@ export function registerAll(): void { // 11. altimate_core.equivalence register("altimate_core.equivalence", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.checkEquivalence(params.sql1, params.sql2, schema) const data = toData(raw) return ok(true, data) @@ -280,7 +280,7 @@ export function registerAll(): void { // 15. altimate_core.correct register("altimate_core.correct", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.correct(params.sql, schema) const data = toData(raw) return ok(true, data) diff --git a/packages/opencode/src/altimate/native/schema-resolver.ts b/packages/opencode/src/altimate/native/schema-resolver.ts index 9dc042e12..936041d8b 100644 --- a/packages/opencode/src/altimate/native/schema-resolver.ts +++ b/packages/opencode/src/altimate/native/schema-resolver.ts @@ -111,12 +111,15 @@ export function resolveSchema( /** * Resolve a Schema, falling back to a minimal empty schema when none is provided. * Use this for functions that require a non-null Schema argument. + * When a dialect is provided, it is passed to Schema.fromDdl() so the fallback + * empty schema uses the correct SQL dialect for validation/analysis. */ export function schemaOrEmpty( schemaPath?: string, schemaContext?: Record, + dialect?: string, ): Schema { const s = resolveSchema(schemaPath, schemaContext) if (s !== null) return s - return Schema.fromDdl("CREATE TABLE _empty_ (id INT);") + return Schema.fromDdl("CREATE TABLE _empty_ (id INT);", dialect || undefined) } From d2ad6ac846978d8c31100df3e36fcd7c428ce267 Mon Sep 17 00:00:00 2001 From: Vijay Yadav Date: Sun, 5 Apr 2026 07:09:44 -0700 Subject: [PATCH 4/4] fix: thread dialect through altimate_core.policy handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code review (Gemini 3.1 Pro) caught a missed handler in the dialect-threading migration: 'altimate_core.policy' (altimate-core.ts:200) called schemaOrEmpty() without params.dialect, while the 6 other policy- family handlers (validate, check, fix, semantics, equivalence, correct, explain) all pass it through. AltimateCorePolicyParams already declares 'dialect?: string' in types.ts and the tool definition plumbs it into Dispatcher.call(), so the param was reaching the handler but being silently discarded at the schema resolution step — meaning the fallback empty schema was always built with the default (Snowflake) dialect instead of the user-selected one, defeating the purpose of PR #550 for policy checks specifically. 1-line fix brings the policy handler into line with its 6 siblings. --- packages/opencode/src/altimate/native/altimate-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/altimate/native/altimate-core.ts b/packages/opencode/src/altimate/native/altimate-core.ts index 8194ddae9..94f43ea40 100644 --- a/packages/opencode/src/altimate/native/altimate-core.ts +++ b/packages/opencode/src/altimate/native/altimate-core.ts @@ -197,7 +197,7 @@ export function registerAll(): void { // 8. altimate_core.policy register("altimate_core.policy", async (params) => { try { - const schema = schemaOrEmpty(params.schema_path, params.schema_context) + const schema = schemaOrEmpty(params.schema_path, params.schema_context, params.dialect) const raw = await core.checkPolicy(params.sql, schema, params.policy_json) const data = toData(raw) return ok(true, data)