Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/internal/deterministic-checks-engine-split.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Relevant because it sets the cost of "add something engine-side".
layer), `altimate-core-node` (napi-rs), plus `polyglot-sql` for multi-dialect parse and
transpile.
- Published as the npm package `@altimateai/altimate-core` (per-platform native addon).
altimate-code pins it exactly: `packages/opencode/package.json` → `"@altimateai/altimate-core": "0.8.0"`.
altimate-code pins it exactly: `packages/opencode/package.json` → `"@altimateai/altimate-core": "0.9.0"`.
- Consumer binding: `packages/opencode/src/altimate/native/altimate-core.ts` registers 42
`altimate_core.*` handlers on the dispatcher. Registration is lazy — the napi binary loads
on the first `Dispatcher.call()` (`packages/opencode/src/altimate/native/index.ts`), so a
Expand Down
2 changes: 1 addition & 1 deletion packages/opencode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"@ai-sdk/togetherai": "2.0.41",
"@ai-sdk/vercel": "2.0.39",
"@ai-sdk/xai": "3.0.82",
"@altimateai/altimate-core": "0.8.0",
"@altimateai/altimate-core": "0.9.0",
"@altimateai/drivers": "workspace:*",
"@aws-sdk/credential-providers": "3.1057.0",
"@clack/prompts": "1.0.0-alpha.1",
Expand Down
44 changes: 42 additions & 2 deletions packages/opencode/src/altimate/native/altimate-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ export function isExistenceError(err: unknown): boolean {
}
// altimate_change end

// altimate_change start — fail closed when the engine skips plan-based analysis
// Core 0.9.0 returns allowed:true / valid:true with no findings for statements it rewrites
// around table-valued functions (no logical plan). That is "not evaluated", not "clean":
// policy must block, and semantics must say it did not run.
const PLAN_SKIP_RULES = new Set(["plan_unavailable", "POLICY_SKIPPED"])
const PLAN_SKIP_NOTE = /plan-based analysis was skipped|logical plan unavailable/i

export const POLICY_NOT_EVALUATED_MESSAGE =
"policy could not be evaluated for this statement (table-valued function, no plan available); treated as blocked"
export const SEMANTICS_SKIPPED_MESSAGE =
"semantic analysis skipped (no plan available for this statement, e.g. table-valued function)"

/** Mark a policy result not-allowed when the engine skipped evaluation. */
export function applyPolicySkipGuard(data: Record<string, unknown>): Record<string, unknown> {
const warnings = Array.isArray(data.warnings) ? (data.warnings as Array<Record<string, unknown>>) : []
const skipped = warnings.some((w) => PLAN_SKIP_RULES.has(String(w?.rule)) || PLAN_SKIP_RULES.has(String(w?.code)))
if (!skipped) return data
const violations = Array.isArray(data.violations) ? (data.violations as unknown[]) : []
data.allowed = false
data.policy_skipped = true
data.violations = [
...violations,
{ rule: "policy_not_evaluated", severity: "error", message: POLICY_NOT_EVALUATED_MESSAGE },
]
const audit = data.audit as Record<string, unknown> | undefined
if (audit && typeof audit === "object") audit.allowed = false
return data
}

/** Flag a semantics result whose analysis did not run. */
export function applySemanticsSkipGuard(data: Record<string, unknown>): Record<string, unknown> {
const notes = Array.isArray(data.notes) ? (data.notes as unknown[]) : []
if (notes.some((n) => PLAN_SKIP_NOTE.test(String(n)))) {
data.skipped = true
data.skip_reason = SEMANTICS_SKIPPED_MESSAGE
}
return data
}
// altimate_change end

function toData(obj: unknown): Record<string, unknown> {
if (obj === null || obj === undefined) return {}
if (typeof obj !== "object") return { value: obj }
Expand Down Expand Up @@ -400,7 +440,7 @@ export function registerAll(): void {
try {
const { sql, schema } = prepareSql(params.sql, params.schema_path, params.schema_context)
const raw = await core.checkPolicy(sql, schema, params.policy_json)
const data = toData(raw)
const data = applyPolicySkipGuard(toData(raw))
return ok(true, data)
} catch (e) {
return fail(e)
Expand All @@ -412,7 +452,7 @@ export function registerAll(): void {
try {
const { sql, schema } = prepareSql(params.sql, params.schema_path, params.schema_context)
const raw = await core.checkSemantics(sql, schema)
const data = toData(raw)
const data = applySemanticsSkipGuard(toData(raw))
return ok(true, data)
} catch (e) {
return fail(e)
Expand Down
21 changes: 17 additions & 4 deletions packages/opencode/src/altimate/native/sql/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import * as core from "@altimateai/altimate-core"
import { register } from "../dispatcher"
import { prepareSql } from "../schema-resolver"
import { preprocessIff, postprocessQualify } from "../altimate-core"
import { preprocessIff, postprocessQualify, applySemanticsSkipGuard } from "../altimate-core"
import { EngineCoerce } from "../engine-coerce"
import type {
SqlAnalyzeResult,
Expand Down Expand Up @@ -37,7 +37,10 @@ export function registerAllSql(): void {
])

const lint = JSON.parse(JSON.stringify(lintRaw))
const semantics = JSON.parse(JSON.stringify(semanticsRaw))
// altimate_change start — a skipped semantic analysis (no plan) is not a clean result
const semantics = applySemanticsSkipGuard(JSON.parse(JSON.stringify(semanticsRaw))) as any
const semanticsSkipped = semantics.skipped === true
// altimate_change end
// Redact raw-input echoes (multi_statement quotes the input verbatim).
const safety = EngineCoerce.redactScan(JSON.parse(JSON.stringify(safetyRaw))) as any

Expand Down Expand Up @@ -65,6 +68,16 @@ export function registerAllSql(): void {
})
}

if (semanticsSkipped) {
issues.push({
type: "semantic",
severity: "warning",
message: String(semantics.skip_reason),
recommendation: "",
confidence: "high",
})
}

for (const t of safety.threats ?? []) {
issues.push({
type: "safety",
Expand All @@ -80,8 +93,8 @@ export function registerAllSql(): void {
success: true,
issues,
issue_count: issues.length,
confidence: "high",
confidence_factors: ["lint", "semantics", "safety"],
confidence: semanticsSkipped ? "medium" : "high",
confidence_factors: semanticsSkipped ? ["lint", "safety"] : ["lint", "semantics", "safety"],
} satisfies SqlAnalyzeResult
} catch (e) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ export const AltimateCoreSemanticsTool = Tool.define("altimate_core_semantics",
// (e.g. cartesian product). Never gate the count or title on `valid`.
const issues = (data.findings ?? data.issues ?? []) as any[]
const issueCount = issues.length
const error = result.error ?? data.error ?? extractSemanticsErrors(data)
// altimate_change start — a skipped analysis (no plan) is not a clean result
const error =
result.error ?? data.error ?? extractSemanticsErrors(data) ?? (data.skipped ? String(data.skip_reason) : undefined)
// altimate_change end
const hasError = Boolean(error)
// altimate_change start — sql quality findings for telemetry
const findings: Telemetry.Finding[] = issues.map((f: any) => ({
category: f?.rule ?? "semantic_issue",
}))
// altimate_change end
return {
title: hasError ? "Semantics: ERROR" : `Semantics: ${issueCount === 0 ? "VALID" : `${issueCount} issues`}`,
title: data.skipped ? "Semantics: SKIPPED" : hasError ? "Semantics: ERROR" : `Semantics: ${issueCount === 0 ? "VALID" : `${issueCount} issues`}`,
metadata: {
// Semantic issues are findings, not failures — but a failed engine
// call or an abstention (validation_errors) must not report success:
Expand Down
16 changes: 15 additions & 1 deletion packages/opencode/src/cli/cmd/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,20 @@ async function runSemantic(sql: string, file: string, schemaPath?: string): Prom
if (!result.success && issues.length === 0) {
return [dispatcherErrorFinding("semantic", file, result.error ?? "altimate_core.semantics failed")]
}
// altimate_change start — skipped analysis (no plan) must not read as zero findings
const skippedFinding: Finding[] = result.data.skipped
? [
{
file,
rule: "semantic",
severity: schemaPath ? ("error" as const) : ("warning" as const),
message: String(result.data.skip_reason ?? "semantic analysis skipped (no plan available)"),
},
]
: []
// altimate_change end
if (issues.length > 0) {
return issues.map((f) => ({
const issueFindings = issues.map((f) => ({
file,
line: f.line as number | undefined,
column: f.column as number | undefined,
Expand All @@ -274,7 +286,9 @@ async function runSemantic(sql: string, file: string, schemaPath?: string): Prom
message: (f.message ?? f.description ?? "") as string,
suggestion: f.suggestion as string | undefined,
}))
return [...skippedFinding, ...issueFindings]
}
if (skippedFinding.length > 0) return skippedFinding
if (result.data.valid === false) {
// SemanticResult.validation_errors carries the reason the query is
// unplannable — surface it instead of a bare generic message. With a
Expand Down
84 changes: 84 additions & 0 deletions packages/opencode/test/altimate/core-plan-skip-fail-closed.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { describe, expect, test, beforeAll, afterAll } from "bun:test"
import * as Dispatcher from "../../src/altimate/native/dispatcher"
import { registerAll } from "../../src/altimate/native/altimate-core"
import { registerAllSql } from "../../src/altimate/native/sql/register"
import { formatSemantics } from "../../src/altimate/tools/altimate-core-semantics"

// Pins altimate-core 0.9.0: statements rewritten around table-valued functions have no
// logical plan, and the engine returns allowed:true / valid:true with no findings. The
// native handlers must report that as not evaluated, never as clean.

beforeAll(() => {
process.env.ALTIMATE_TELEMETRY_DISABLED = "true"
registerAll()
registerAllSql()
})
afterAll(() => {
delete process.env.ALTIMATE_TELEMETRY_DISABLED
})

const schema_context = {
version: "1",
dialect: "generic",
database: null,
schema_name: null,
tables: { t: { columns: [{ name: "id", type: "INT" }, { name: "name", type: "VARCHAR" }] } },
}
const policy_json = JSON.stringify({ rules: [] })
const TVF_QUERIES = [
"SELECT * FROM TABLE(my_fn())",
"SELECT * FROM t, LATERAL FLATTEN(input => t.name)",
"SELECT * FROM read_csv('x')",
]

describe("altimate_core.policy fails closed when no plan is available", () => {
for (const sql of TVF_QUERIES) {
test(`not allowed: ${sql}`, async () => {
const r = await Dispatcher.call("altimate_core.policy", { sql, policy_json, schema_context })
expect(r.data.allowed).toBe(false)
expect(r.data.policy_skipped).toBe(true)
const violations = r.data.violations as Array<{ rule: string; message: string }>
expect(violations.some((v) => v.rule === "policy_not_evaluated")).toBe(true)
expect(violations.find((v) => v.rule === "policy_not_evaluated")?.message).toContain("treated as blocked")
})
}

test("a normal query is unaffected", async () => {
const r = await Dispatcher.call("altimate_core.policy", { sql: "SELECT id FROM t", policy_json, schema_context })
expect(r.data.allowed).toBe(true)
expect(r.data.policy_skipped).toBeUndefined()
expect(r.data.violations).toEqual([])
})
})

describe("altimate_core.semantics reports skipped analysis", () => {
for (const sql of TVF_QUERIES) {
test(`skipped: ${sql}`, async () => {
const r = await Dispatcher.call("altimate_core.semantics", { sql, schema_context })
expect(r.data.skipped).toBe(true)
expect(String(r.data.skip_reason)).toContain("semantic analysis skipped")
})
}

test("a normal query is unaffected", async () => {
const r = await Dispatcher.call("altimate_core.semantics", { sql: "SELECT id FROM t", schema_context })
expect(r.data.skipped).toBeUndefined()
expect(formatSemantics(r.data)).toBe("No semantic issues found.")
})
})

describe("sql.analyze does not report skipped semantics as evaluated", () => {
test("TVF query: skipped issue, semantics not credited", async () => {
const r: any = await Dispatcher.call("sql.analyze", { sql: "SELECT id FROM TABLE(my_fn()) LIMIT 10", schema_context })
expect(r.issues.some((i: any) => i.type === "semantic" && String(i.message).includes("semantic analysis skipped"))).toBe(true)
expect(r.confidence_factors).not.toContain("semantics")
expect(r.confidence).toBe("medium")
})

test("normal query is unaffected", async () => {
const r: any = await Dispatcher.call("sql.analyze", { sql: "SELECT id FROM t", schema_context })
expect(r.issues.some((i: any) => i.type === "semantic")).toBe(false)
expect(r.confidence_factors).toContain("semantics")
expect(r.confidence).toBe("high")
})
})
37 changes: 37 additions & 0 deletions packages/opencode/test/cli/check-e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,43 @@ describe("check command E2E", () => {
expect(j.summary.total_findings).toBe(0)
})

test("policy check reports a skipped evaluation as a blocking finding", async () => {
const file = await writeSql(tmpDir.dir, "m.sql", "SELECT * FROM TABLE(my_fn());")
const policyFile = path.join(tmpDir.dir, "policy.json")
await fs.writeFile(policyFile, JSON.stringify({ rules: [] }))

// Shape produced by the native handler when core returns plan_unavailable (0.9.0).
setDispatcherResponse("altimate_core.policy", () => ({
success: true,
data: {
allowed: false,
policy_skipped: true,
violations: [{ rule: "policy_not_evaluated", severity: "error", message: "policy could not be evaluated" }],
warnings: [{ rule: "plan_unavailable", message: "Policy check skipped: no plan is available." }],
},
}))
installDispatcherMocks()

const r = await runHandler(baseArgs({ files: [file], checks: "policy", policy: policyFile }))
const j = parseJson(r.stdout)
expect(j.summary.total_findings).toBe(1)
expect(j.summary.errors).toBe(1)
})

test("semantic check reports skipped analysis instead of zero findings", async () => {
const file = await writeSql(tmpDir.dir, "m.sql", "SELECT * FROM TABLE(my_fn());")
setDispatcherResponse("altimate_core.semantics", () => ({
success: true,
data: { findings: [], valid: true, skipped: true, skip_reason: "semantic analysis skipped (no plan available)" },
}))
installDispatcherMocks()

const r = await runHandler(baseArgs({ files: [file], checks: "semantic" }))
const j = parseJson(r.stdout)
expect(j.summary.total_findings).toBe(1)
expect(JSON.stringify(j)).toContain("semantic analysis skipped")
})

// --- Unknown checks ---

test("warns on unknown check names", async () => {
Expand Down
Loading