Skip to content

Commit 56259a3

Browse files
anandgupta42claude
andcommitted
release: v0.7.3
Telemetry-driven hardening release. Five P0 fixes from the telemetry-analysis-2026-05-21 pass (#828 finops auto-pick, #831 project_scan defensive spawn, #833 build-agent name normalization, #837 tokens_input_total semantics, #839 webfetch 404 cache) plus a multi-persona pre-release review that surfaced privacy/security hardening: credential strip on git.remoteUrl, masked git stderr, agent-name input hardening (control-char strip + NFKC + length cap), auth-bearing query-param strip from the webfetch cache key, cache-hit error prefix, warehouse_filter param description disambiguation, DEFAULT_FINOPS_TYPES single source of truth, and docs alignment for the auto-pick behavior. 34 adversarial tests pin every invariant. 4 deferred items filed as #840 #841 #842 #843. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a411be2 commit 56259a3

16 files changed

Lines changed: 610 additions & 48 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ __pycache__
4444
**/.github/meta/commit.txt
4545
**/.github/meta/diff.txt
4646
**/.github/meta/pr-body-*.md
47+
*.bak

CHANGELOG.md

Lines changed: 47 additions & 0 deletions
Large diffs are not rendered by default.

docs/docs/data-engineering/tools/finops-tools.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
Cost optimization and warehouse governance. These tools help you find where money is being wasted and fix it.
44

5+
!!! note "v0.7.3+ — warehouse parameter is now optional"
6+
Every `finops_*` tool used to require an explicit `warehouse=<connection-name>` argument. As of v0.7.3, the parameter is optional — if omitted, the tool auto-picks the first configured warehouse whose driver type supports the operation. Pass `warehouse=` explicitly when you have multiple compatible connections and want a specific one. The bare form (`finops_query_history --days 7`) works.
7+
58
## finops_query_history
69

710
Fetch recent query execution history from your warehouse.
@@ -27,11 +30,11 @@ Summary:
2730
```
2831

2932
**Parameters:**
30-
- `warehouse` (required): Connection name
33+
- `warehouse` (optional, since v0.7.3): Connection name. If omitted, the first configured Snowflake / BigQuery / Databricks / PostgreSQL warehouse is auto-picked.
3134
- `days` (optional, default: 7): Lookback period
3235
- `limit` (optional, default: 100): Max queries returned
3336
- `user` (optional): Filter by username
34-
- `warehouse_filter` (optional): Filter by compute warehouse name
37+
- `warehouse_filter` (optional, Snowflake-only): Filter the result rows by the in-warehouse compute name (different from the `warehouse` connection parameter). Use `warehouse` to pick which connection to query; use `warehouse_filter` to narrow which Snowflake virtual warehouse's queries appear in the output.
3538

3639
**Data sources by warehouse:**
3740
- Snowflake: `QUERY_HISTORY` function
@@ -46,7 +49,8 @@ Summary:
4649
Break down credit consumption by warehouse, time, and user.
4750

4851
```
49-
> finops_analyze_credits prod-snowflake --days 30
52+
> finops_analyze_credits --days 30
53+
# equivalent: finops_analyze_credits prod-snowflake --days 30
5054
5155
Credit Analysis (last 30 days):
5256

packages/opencode/src/altimate/native/finops/credit-analyzer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77
import * as Registry from "../connections/registry"
88
import { bqRegionFor, interpolateBqRegion } from "./bq-utils"
9-
import { resolveFinopsWarehouse } from "./warehouse-resolver"
9+
import { resolveFinopsWarehouse, DEFAULT_FINOPS_TYPES } from "./warehouse-resolver"
1010
import type {
1111
CreditAnalysisParams,
1212
CreditAnalysisResult,
1313
ExpensiveQueriesParams,
1414
ExpensiveQueriesResult,
1515
} from "../types"
1616

17-
const CREDIT_SUPPORTED_TYPES = ["snowflake", "bigquery", "databricks"] as const
17+
const CREDIT_SUPPORTED_TYPES = DEFAULT_FINOPS_TYPES
1818

1919
// ---------------------------------------------------------------------------
2020
// Snowflake SQL templates

packages/opencode/src/altimate/native/finops/role-access.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import * as Registry from "../connections/registry"
88
import { bqRegionFor, interpolateBqRegion } from "./bq-utils"
9-
import { resolveFinopsWarehouse } from "./warehouse-resolver"
9+
import { resolveFinopsWarehouse, DEFAULT_FINOPS_TYPES } from "./warehouse-resolver"
1010
import type {
1111
RoleGrantsParams,
1212
RoleGrantsResult,
@@ -108,7 +108,7 @@ LIMIT ?
108108
// Helpers
109109
// ---------------------------------------------------------------------------
110110

111-
const GRANTS_SUPPORTED_TYPES = ["snowflake", "bigquery", "databricks"] as const
111+
const GRANTS_SUPPORTED_TYPES = DEFAULT_FINOPS_TYPES
112112
const SNOWFLAKE_ONLY_TYPES = ["snowflake"] as const
113113

114114
function rowsToRecords(result: { columns: string[]; rows: any[][] }): Record<string, unknown>[] {

packages/opencode/src/altimate/native/finops/unused-resources.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66

77
import * as Registry from "../connections/registry"
88
import { bqRegionFor, interpolateBqRegion } from "./bq-utils"
9-
import { resolveFinopsWarehouse } from "./warehouse-resolver"
9+
import { resolveFinopsWarehouse, DEFAULT_FINOPS_TYPES } from "./warehouse-resolver"
1010
import type {
1111
UnusedResourcesParams,
1212
UnusedResourcesResult,
1313
} from "../types"
1414

15-
const UNUSED_RESOURCES_SUPPORTED_TYPES = ["snowflake", "bigquery", "databricks"] as const
15+
const UNUSED_RESOURCES_SUPPORTED_TYPES = DEFAULT_FINOPS_TYPES
1616

1717
// ---------------------------------------------------------------------------
1818
// Snowflake SQL templates

packages/opencode/src/altimate/native/finops/warehouse-advisor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import * as Registry from "../connections/registry"
88
import { bqRegionFor, interpolateBqRegion } from "./bq-utils"
9-
import { resolveFinopsWarehouse } from "./warehouse-resolver"
9+
import { resolveFinopsWarehouse, DEFAULT_FINOPS_TYPES } from "./warehouse-resolver"
1010
import type {
1111
WarehouseAdvisorParams,
1212
WarehouseAdvisorResult,
@@ -123,7 +123,7 @@ const SIZE_ORDER = ["X-Small", "Small", "Medium", "Large", "X-Large", "2X-Large"
123123
// Helpers
124124
// ---------------------------------------------------------------------------
125125

126-
const ADVISOR_SUPPORTED_TYPES = ["snowflake", "bigquery", "databricks"] as const
126+
const ADVISOR_SUPPORTED_TYPES = DEFAULT_FINOPS_TYPES
127127

128128
function buildLoadSql(whType: string, days: number, bqRegion?: unknown): string | null {
129129
if (whType === "snowflake") return SNOWFLAKE_LOAD_SQL.replace("{days}", String(days))

packages/opencode/src/altimate/native/finops/warehouse-resolver.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@
1818

1919
import * as Registry from "../connections/registry"
2020

21+
/**
22+
* Default supported driver types for finops operations that work against any
23+
* cloud warehouse with usage/billing tables (credit analysis, sizing advice,
24+
* unused-resource detection, etc.). Centralized here so adding a new
25+
* warehouse driver doesn't require touching 3+ handler files.
26+
*
27+
* Operations with narrower support (e.g. Snowflake-only role hierarchy,
28+
* postgres-aware query history) declare their own const arrays.
29+
*/
30+
export const DEFAULT_FINOPS_TYPES = ["snowflake", "bigquery", "databricks"] as const
31+
2132
export type FinopsWarehouseResolution =
2233
| { kind: "ok"; warehouse: string; type: string; autoPicked: boolean }
2334
| { kind: "error"; error: string }

packages/opencode/src/altimate/tools/finops-analyze-credits.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,14 @@ export const FinopsAnalyzeCreditsTool = Tool.define("finops_analyze_credits", {
7373
),
7474
days: z.number().optional().default(30).describe("Days of history to analyze"),
7575
limit: z.number().optional().default(50).describe("Max daily records"),
76-
warehouse_filter: z.string().optional().describe("Filter to a specific Snowflake warehouse"),
76+
warehouse_filter: z
77+
.string()
78+
.optional()
79+
.describe(
80+
"Filter result rows by an in-warehouse Snowflake compute name (NOT the connection name). " +
81+
"Distinct from `warehouse`: `warehouse` picks which connection to query; `warehouse_filter` narrows " +
82+
"which Snowflake virtual warehouse's queries are returned in the result set. Snowflake only.",
83+
),
7784
}),
7885
async execute(args, ctx) {
7986
try {

packages/opencode/src/altimate/tools/finops-query-history.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,14 @@ export const FinopsQueryHistoryTool = Tool.define("finops_query_history", {
6161
days: z.number().optional().default(7).describe("How many days of history to fetch"),
6262
limit: z.number().optional().default(100).describe("Maximum number of queries to return"),
6363
user: z.string().optional().describe("Filter to a specific user (Snowflake only)"),
64-
warehouse_filter: z.string().optional().describe("Filter to a specific warehouse name (Snowflake only)"),
64+
warehouse_filter: z
65+
.string()
66+
.optional()
67+
.describe(
68+
"Filter result rows by an in-warehouse Snowflake compute name (NOT the connection name). " +
69+
"Distinct from `warehouse`: `warehouse` picks which connection to query; `warehouse_filter` narrows " +
70+
"which Snowflake virtual warehouse's queries are returned in the result set. Snowflake only.",
71+
),
6572
}),
6673
async execute(args, ctx) {
6774
try {

0 commit comments

Comments
 (0)