Skip to content

Commit f7fdcc8

Browse files
authored
Merge branch 'main' into fix/678-tool-definition-mismatch
2 parents 60dcad3 + 3bdaefa commit f7fdcc8

4 files changed

Lines changed: 390 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,22 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.5.21] - 2026-04-13
99

1010
### Added
1111

12-
- **Automated dbt unit test generation**new `dbt_unit_test_gen` tool and `/dbt-unit-tests` skill for generating dbt unit tests (v1.8+) from a compiled manifest. Parses `manifest.json` via the shared `parseManifest()` helper, uses `dbtLineage()` for column lineage, detects testable SQL constructs (CASE/WHEN, JOINs, NULLs, window functions, division, incremental), and assembles complete YAML via the `yaml` library. Includes `input: this` mock for incremental models, `format: sql` fallback for ephemeral deps (even with no known columns), cross-database support via `database` param in `schema.inspect`, deterministic test names (no `Date.now()`), and rich `UnitTestContext` (descriptions, lineage, compiled SQL) for LLM-driven test value refinement. Handles seeds and snapshots as first-class ref() deps. Warns when upstream deps cannot be resolved. (#673)
13-
- **Manifest parse cache**`loadRawManifest()` helper caches by path+mtime; `parseManifest()` and `dbtLineage()` both go through it, so a 128MB manifest is read and parsed once per request instead of once per call. Benefits any tool that makes multiple manifest-backed calls in sequence.
14-
- **`description` on `DbtModelInfo`/`DbtSourceInfo`**surfaces model and source descriptions from schema.yml in the parsed manifest result, enabling downstream tools to provide richer semantic context to the LLM.
12+
- **Automated dbt unit test generation**generate dbt unit tests (v1.8+) from your terminal with `/dbt-unit-tests` or the `dbt_unit_test_gen` tool. Detects testable SQL constructs (CASE/WHEN, JOINs, NULLs, window functions, division, incremental models) and assembles complete YAML with type-correct mock data across 7 dialects. Includes `input: this` mocks for incremental models, `format: sql` for ephemeral deps, and handles seeds/snapshots as first-class `ref()` deps. Five-phase skill workflow: Analyze → Generate → Refine → Validate → Write. Requires dbt-core 1.8+. (#673)
13+
- **Manifest parse cache**`loadRawManifest()` caches by path+mtime so large manifests (100MB+) are parsed once per session, not once per tool call.
14+
- **Model/source descriptions in manifest**`DbtModelInfo` and `DbtSourceInfo` now surface descriptions from `schema.yml`, giving downstream tools richer semantic context.
1515
- **`adapter_type` on `DbtManifestResult`** — exposes the dbt adapter type (snowflake, bigquery, etc.) from manifest metadata for dialect auto-detection.
1616

17+
### Fixed
18+
19+
- **MCP env-var `$${VAR}` escape and chain-injection vulnerability** — the two-layer env-var resolution design allowed `$${VAR}` escapes to be re-resolved (breaking literal `${VAR}` passthrough) and enabled variable-chain injection where `EVIL_VAR="${SECRET}"` could exfiltrate secrets the config never referenced. Collapsed to a single resolution pass scoped to `env` and `headers` fields only. (#697, relates to #656)
20+
- **MCP server environment variables passed as literals**`${VAR}`, `${VAR:-default}`, and `{env:VAR}` patterns in MCP server `env` blocks were passed as literal strings to child processes, causing auth failures for tools like `gitlab-mcp-server`. (#666, closes #656)
21+
- **`sql_explain` and `altimate_core_validate` input hardening** — reject empty/placeholder SQL and warehouse names before hitting the warehouse. `sql_explain` now generates dialect-aware EXPLAIN statements for 12+ warehouse types. Driver errors are translated into actionable guidance (e.g., "No warehouses configured — run `warehouse_add`"). `altimate_core_validate` now runs even without a schema (previously hard-failed), with a `(no schema)` indicator and clear instructions for providing schema context. (#693, closes #691)
22+
- **`sql_explain` alternatives for unsupported warehouses** — BigQuery, Oracle, and SQL Server now return specific guidance (dry-run API, `DBMS_XPLAN`, `SET SHOWPLAN_TEXT ON`) instead of a generic "not supported" message.
23+
1724
## [0.5.20] - 2026-04-09
1825

1926
### Added

packages/opencode/src/altimate/native/connections/register.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import { Telemetry } from "../../../telemetry"
3939

4040
/** Cached dbt adapter (lazily created on first use). */
4141
let dbtAdapter: any | null | undefined = undefined
42-
let dbtConfigChecked = false
4342

4443
/**
4544
* Try to execute SQL via dbt's adapter (which uses profiles.yml for connection).
@@ -64,7 +63,6 @@ async function tryExecuteViaDbt(
6463
)
6564
const dbtConfig = await readDbtConfig()
6665
if (!dbtConfig) {
67-
dbtConfigChecked = true
6866
dbtAdapter = null
6967
return null
7068
}
@@ -145,7 +143,6 @@ async function tryExecuteViaDbt(
145143
/** Reset dbt adapter (for testing). */
146144
export function resetDbtAdapter(): void {
147145
dbtAdapter = undefined
148-
dbtConfigChecked = false
149146
}
150147

151148
// ---------------------------------------------------------------------------
@@ -277,6 +274,22 @@ export function buildExplainPrefix(warehouseType: string | undefined, analyze: b
277274
return buildExplainPlan(warehouseType, analyze).prefix
278275
}
279276

277+
// altimate_change start — actionable alternatives for unsupported EXPLAIN
278+
function explainAlternative(warehouseType: string | undefined): string {
279+
switch ((warehouseType ?? "").toLowerCase()) {
280+
case "bigquery":
281+
return "Use the BigQuery Console's Query Explanation tab, or run a dry-run query via `bq query --dry_run`."
282+
case "oracle":
283+
return "Use `EXPLAIN PLAN FOR <sql>` followed by `SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)` in your SQL client."
284+
case "mssql":
285+
case "sqlserver":
286+
return "Use `SET SHOWPLAN_TEXT ON` in SSMS or Azure Data Studio before running the query."
287+
default:
288+
return "This warehouse requires a different plan mechanism that sql_explain cannot issue directly."
289+
}
290+
}
291+
// altimate_change end
292+
280293
/**
281294
* Translate a raw warehouse/Registry error into an actionable message.
282295
*
@@ -447,7 +460,7 @@ register("sql.explain", async (params: SqlExplainParams): Promise<SqlExplainResu
447460
return {
448461
success: false,
449462
plan_rows: [],
450-
error: `sql_explain is not supported for warehouse type ${JSON.stringify(warehouseType)}. This warehouse requires a different plan mechanism (e.g. dry-run API, SET SHOWPLAN_TEXT ON, or DBMS_XPLAN) that sql_explain cannot issue directly.`,
463+
error: `sql_explain is not supported for warehouse type ${JSON.stringify(warehouseType)}. ${explainAlternative(warehouseType)}`,
451464
warehouse_type: warehouseType,
452465
analyzed: false,
453466
}

packages/opencode/src/config/paths.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export namespace ConfigPaths {
9393
// Exported so other modules (e.g. mcp/discover) can reuse the exact same grammar
9494
// without forking the regex. See issue #635, #656.
9595
export const ENV_VAR_PATTERN =
96-
/\$\$(\{[A-Za-z_][A-Za-z0-9_]*(?::-[^}]*)?\})|(?<!\$)\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}|\{env:([^}]+)\}/g
96+
/\$\$(\{[A-Za-z_][A-Za-z0-9_]*(?::-[^}]*)?\})|(?<!\$)\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}|\{env:([A-Za-z_][A-Za-z0-9_]*)\}/g
9797

9898
export interface EnvSubstitutionStats {
9999
dollarRefs: number

0 commit comments

Comments
 (0)